am 46f2b208: am c8eebea2: am 860440a4: test if libFLAC is patched against CVE-2014-9028

* commit '46f2b208bf1645bea1f3d39abde27ecb3fb13bfc':
  test if libFLAC is patched against CVE-2014-9028
diff --git a/.gitignore b/.gitignore
index b8a343c..07a80d6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,6 @@
 .project
 .cproject
 .classpath
+/bin
+.idea/*
+.idea/
diff --git a/CtsBuild.mk b/CtsBuild.mk
index 6e57086..dbe93c7 100644
--- a/CtsBuild.mk
+++ b/CtsBuild.mk
@@ -30,6 +30,12 @@
 # File indicating which tests should be blacklisted due to problems.
 CTS_EXPECTATIONS := cts/tests/expectations/knownfailures.txt
 
+# File indicating which tests should be blacklisted due to unsupported abi.
+CTS_UNSUPPORTED_ABIS := cts/tests/expectations/unsupportedabis.txt
+
+# Holds the target architecture to build for.
+CTS_TARGET_ARCH := $(TARGET_ARCH)
+
 # Functions to get the paths of the build outputs.
 
 define cts-get-lib-paths
@@ -41,7 +47,7 @@
 endef
 
 define cts-get-native-paths
-	$(foreach exe,$(1),$(call intermediates-dir-for,EXECUTABLES,$(exe))/$(exe))
+	$(foreach exe,$(1),$(call intermediates-dir-for,EXECUTABLES,$(exe),,,$(3))/$(exe)$(2))
 endef
 
 define cts-get-package-paths
@@ -51,3 +57,11 @@
 define cts-get-test-xmls
 	$(foreach name,$(1),$(CTS_TESTCASES_OUT)/$(name).xml)
 endef
+
+define cts-get-executable-paths
+	$(foreach executable,$(1),$(CTS_TESTCASES_OUT)/$(executable))
+endef
+
+define cts-get-deqp-test-xmls
+	$(foreach api,$(1),$(CTS_TESTCASES_OUT)/com.drawelements.deqp.$(api).xml)
+endef
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index bc240c2..b3b826d 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -13,50 +13,83 @@
 # limitations under the License.
 
 cts_security_apps_list := \
-	CtsAppAccessData \
-	CtsAppWithData \
-	CtsExternalStorageApp \
-	CtsInstrumentationAppDiffCert \
-	CtsPermissionDeclareApp \
-	CtsPermissionDeclareAppCompat \
-	CtsReadExternalStorageApp \
-	CtsSharedUidInstall \
-	CtsSharedUidInstallDiffCert \
-	CtsSimpleAppInstall \
-	CtsSimpleAppInstallDiffCert \
-	CtsTargetInstrumentationApp \
-	CtsUsePermissionDiffCert \
-	CtsWriteExternalStorageApp \
-	CtsMultiUserStorageApp
+    CtsAppAccessData \
+    CtsAppWithData \
+    CtsDocumentProvider \
+    CtsDocumentClient \
+    CtsExternalStorageApp \
+    CtsInstrumentationAppDiffCert \
+    CtsPermissionDeclareApp \
+    CtsPermissionDeclareAppCompat \
+    CtsReadExternalStorageApp \
+    CtsSharedUidInstall \
+    CtsSharedUidInstallDiffCert \
+    CtsSimpleAppInstall \
+    CtsSimpleAppInstallDiffCert \
+    CtsSplitApp \
+    CtsSplitApp_x86 \
+    CtsSplitApp_x86_64 \
+    CtsSplitApp_armeabi-v7a \
+    CtsSplitApp_armeabi \
+    CtsSplitApp_arm64-v8a \
+    CtsSplitApp_mips64 \
+    CtsSplitApp_mips \
+    CtsSplitAppDiffVersion \
+    CtsSplitAppDiffCert \
+    CtsSplitAppFeature \
+    CtsTargetInstrumentationApp \
+    CtsUsePermissionDiffCert \
+    CtsWriteExternalStorageApp \
+    CtsMultiUserStorageApp
+
+cts_security_keysets_list := \
+    CtsKeySetTestApp \
+    CtsKeySetPermDefSigningA \
+    CtsKeySetPermDefSigningB\
+    CtsKeySetPermUseSigningA \
+    CtsKeySetPermUseSigningB \
+    CtsKeySetSigningAUpgradeA \
+    CtsKeySetSigningBUpgradeA \
+    CtsKeySetSigningAUpgradeAAndB \
+    CtsKeySetSigningAUpgradeAOrB \
+    CtsKeySetSigningAUpgradeB \
+    CtsKeySetSigningBUpgradeB \
+    CtsKeySetSigningAAndBUpgradeA \
+    CtsKeySetSigningAAndCUpgradeB \
+    CtsKeySetSigningAUpgradeNone
 
 cts_support_packages := \
     CtsAccelerationTestStubs \
+    CtsAppTestStubs \
     CtsDeviceAdmin \
     CtsDeviceOpenGl \
+    CtsDeviceOwnerApp \
     CtsDeviceTaskswitchingAppA \
     CtsDeviceTaskswitchingAppB \
     CtsDeviceTaskswitchingControl \
     CtsDeviceUi \
+    CtsIntentReceiverApp \
+    CtsIntentSenderApp \
+    CtsManagedProfileApp \
     CtsMonkeyApp \
     CtsMonkeyApp2 \
-    CtsSampleDeviceApp \
     CtsSomeAccessibilityServices \
-    CtsTestStubs \
     CtsThemeDeviceApp \
-    SignatureTest \
     TestDeviceSetup \
     CtsUiAutomatorApp \
     CtsUsbSerialTestApp \
-    $(cts_security_apps_list)
+    $(cts_security_apps_list) \
+    $(cts_security_keysets_list)
 
 cts_external_packages := \
-	com.replica.replicaisland
+    com.replica.replicaisland \
+    com.drawelements.deqp
 
 # Any APKs that need to be copied to the CTS distribution's testcases
 # directory but do not require an associated test package XML.
 CTS_TEST_CASE_LIST := \
-	$(cts_support_packages) \
-	$(cts_external_packages)
+    $(cts_support_packages) \
+    $(cts_external_packages)
 
 # Test packages that require an associated test package XML.
 cts_test_packages := \
@@ -88,9 +121,11 @@
     CtsGraphicsTestCases \
     CtsGraphics2TestCases \
     CtsHardwareTestCases \
+    CtsJobSchedulerDeviceTestCases \
     CtsJniTestCases \
     CtsKeystoreTestCases \
     CtsLocationTestCases \
+    CtsLocation2TestCases \
     CtsMediaStressTestCases \
     CtsMediaTestCases \
     CtsNativeOpenGLTestCases \
@@ -103,68 +138,105 @@
     CtsPermission2TestCases \
     CtsPreferenceTestCases \
     CtsPreference2TestCases \
+    CtsPrintTestCases \
     CtsProviderTestCases \
     CtsRenderscriptTestCases \
-    CtsRenderscriptGraphicsTestCases \
+    CtsRenderscriptLegacyTestCases \
     CtsRsCppTestCases \
-    CtsSampleDeviceTestCases \
     CtsSaxTestCases \
     CtsSecurityTestCases \
+    CtsSignatureTestCases \
     CtsSpeechTestCases \
     CtsTelephonyTestCases \
     CtsTextTestCases \
     CtsTextureViewTestCases \
     CtsThemeTestCases \
+    CtsTvTestCases \
+    CtsUiAutomationTestCases \
+    CtsUiRenderingTestCases \
+    CtsUsageStatsTestCases \
     CtsUtilTestCases \
     CtsViewTestCases \
     CtsWebkitTestCases \
+    CtsWebGLTestCases \
     CtsWidgetTestCases
 
 # All APKs that need to be scanned by the coverage utilities.
 CTS_COVERAGE_TEST_CASE_LIST := \
-	$(cts_support_packages) \
-	$(cts_test_packages)
+    $(cts_support_packages) \
+    $(cts_test_packages)
 
 # Host side only tests
 cts_host_libraries := \
     CtsAdbTests \
     CtsAppSecurityTests \
+    CtsDevicePolicyManagerTestCases \
     CtsHostJank \
     CtsHostUi \
     CtsJdwpSecurityHostTestCases \
     CtsMonkeyTestCases \
-    CtsSampleHostTestCases \
     CtsThemeHostTestCases \
+    CtsSecurityHostTestCases \
     CtsUsbTests
 
-# Native test executables that need to have associated test XMLs.
-cts_native_exes := \
-	NativeMediaTest_SL \
-	NativeMediaTest_XA \
-	bionic-unit-tests-cts \
+# List of native tests. For 32 bit targets, assumes that there will be
+# one test executable, and it will end in 32. For 64 bit targets, assumes
+# that there will be two executables, one that ends in 32 for the 32
+# bit executable and one that ends in 64 for the 64 bit executable.
+cts_native_tests := \
+    NativeMediaTest_SL \
+    NativeMediaTest_XA \
+
+ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x86_64))
+cts_native_tests += bionic-unit-tests-cts
+endif
 
 cts_ui_tests := \
     CtsUiAutomatorTests
 
 cts_device_jars := \
     CtsDeviceJank \
-    CtsJdwpApp
+    CtsJdwpApp \
+    CtsPrintInstrument
+
+cts_device_executables := \
+    print-instrument
+
+cts_target_junit_tests := \
+    CtsJdwp
+
+cts_deqp_test_apis := \
+    gles3 \
+    gles31
 
 # All the files that will end up under the repository/testcases
 # directory of the final CTS distribution.
 CTS_TEST_CASES := $(call cts-get-lib-paths,$(cts_host_libraries)) \
     $(call cts-get-package-paths,$(cts_test_packages)) \
-    $(call cts-get-native-paths,$(cts_native_exes)) \
     $(call cts-get-ui-lib-paths,$(cts_ui_tests)) \
-    $(call cts-get-ui-lib-paths,$(cts_device_jars))
+    $(call cts-get-ui-lib-paths,$(cts_device_jars)) \
+    $(call cts-get-ui-lib-paths,$(cts_target_junit_tests)) \
+    $(call cts-get-executable-paths,$(cts_device_executables))
+
+# NOTE: If compiling on a 64 bit target, TARGET_2ND_ARCH will be non-empty
+# and will cause the function to expand to the secondary arch object
+# directory. If compiling on a 32 bit target, TARGET_2ND_ARCH will be
+# empty and will cause the function to expand to the primary arch object
+# directory.
+CTS_TEST_CASES += $(call cts-get-native-paths,$(cts_native_tests),32,$(TARGET_2ND_ARCH))
+
+ifeq ($(TARGET_IS_64_BIT),true)
+CTS_TEST_CASES += $(call cts-get-native-paths,$(cts_native_tests),64)
+endif
 
 # All the XMLs that will end up under the repository/testcases
 # and that need to be created before making the final CTS distribution.
 CTS_TEST_XMLS := $(call cts-get-test-xmls,$(cts_host_libraries)) \
     $(call cts-get-test-xmls,$(cts_test_packages)) \
-    $(call cts-get-test-xmls,$(cts_native_exes)) \
-    $(call cts-get-test-xmls,$(cts_ui_tests))
-
+    $(call cts-get-test-xmls,$(cts_native_tests)) \
+    $(call cts-get-test-xmls,$(cts_target_junit_tests)) \
+    $(call cts-get-test-xmls,$(cts_ui_tests)) \
+    $(call cts-get-deqp-test-xmls,$(cts_deqp_test_apis))
 
 # The following files will be placed in the tools directory of the CTS distribution
 CTS_TOOLS_LIST :=
diff --git a/apps/CtsVerifier/Android.mk b/apps/CtsVerifier/Android.mk
index 397b39a..460b88a 100644
--- a/apps/CtsVerifier/Android.mk
+++ b/apps/CtsVerifier/Android.mk
@@ -21,9 +21,11 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_MULTILIB := both
 
-LOCAL_STATIC_JAVA_LIBRARIES := cts-sensors-tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-Iaidl-files-under, src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := cts-sensors-tests ctstestrunner
 
 LOCAL_PACKAGE_NAME := CtsVerifier
 
@@ -41,7 +43,7 @@
 # Builds and launches CTS Verifier on a device.
 .PHONY: cts-verifier
 cts-verifier: CtsVerifier adb
-	adb install -r $(PRODUCT_OUT)/data/app/CtsVerifier.apk \
+	adb install -r $(PRODUCT_OUT)/data/app/CtsVerifier/CtsVerifier.apk \
 		&& adb shell "am start -n com.android.cts.verifier/.CtsVerifierActivity"
 
 #
@@ -59,6 +61,19 @@
 verifier-zip-name := $(verifier-dir-name).zip
 verifier-zip := $(cts-dir)/$(verifier-zip-name)
 
+# turned off sensor power tests in initial L release
+#$(PRODUCT_OUT)/data/app/CtsVerifier.apk $(verifier-zip): $(verifier-dir)/power/execute_power_tests.py
+#$(PRODUCT_OUT)/data/app/CtsVerifier.apk $(verifier-zip): $(verifier-dir)/power/power_monitors/monsoon.py
+
+# Copy the necessary host-side scripts to include in the zip file:
+#$(verifier-dir)/power/power_monitors/monsoon.py: cts/apps/CtsVerifier/assets/scripts/power_monitors/monsoon.py | $(ACP)
+#	$(hide) mkdir -p $(verifier-dir)/power/power_monitors
+#	$(hide) $(ACP) -fp cts/apps/CtsVerifier/assets/scripts/power_monitors/*.py $(verifier-dir)/power/power_monitors/.
+#
+#$(verifier-dir)/power/execute_power_tests.py: cts/apps/CtsVerifier/assets/scripts/execute_power_tests.py | $(ACP)
+#	$(hide) mkdir -p $(verifier-dir)/power
+#	$(hide) $(ACP) -fp cts/apps/CtsVerifier/assets/scripts/execute_power_tests.py $@
+
 cts : $(verifier-zip)
 ifeq ($(HOST_OS),linux)
 $(verifier-zip) : $(HOST_OUT)/bin/cts-usb-accessory
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 418742c..12ed5e5 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -17,11 +17,10 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="com.android.cts.verifier"
-      android:versionCode="1"
-      android:versionName="4.4W_r4">
+      android:versionCode="4"
+      android:versionName="5.0_r2">
 
-    <!-- Using 10+ for more complete NFC support... -->
-    <uses-sdk android:minSdkVersion="12"></uses-sdk>
+    <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="21"/>
 
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
@@ -34,6 +33,7 @@
     <uses-permission android:name="android.permission.FULLSCREEN" />
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.NFC" />
+    <uses-permission android:name="android.permission.VIBRATE" />
     <uses-feature android:name="android.hardware.camera.front"
                   android:required="false" />
     <uses-feature android:name="android.hardware.camera.autofocus"
@@ -43,8 +43,12 @@
     <uses-permission android:name="android.permission.WAKE_LOCK" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
-
     <uses-feature android:name="android.hardware.usb.accessory" />
+    <uses-permission android:name="android.permission.CALL_PHONE" />
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+    <uses-permission android:name="android.permission.READ_CONTACTS"/>
+    <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
 
     <!-- Needed by the Audio Quality Verifier to store the sound samples that will be mailed. -->
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
@@ -58,6 +62,8 @@
         <meta-data android:name="com.google.android.backup.api_key"
                 android:value="AEdPqrEAAAAIbK6ldcOzoeRtQ1u1dFVJ1A7KetRhit-a1Xa82Q" />
 
+        <uses-library android:name="android.test.runner"/>
+
         <activity android:name=".TestListActivity" android:label="@string/app_name">
             <!--
                 TestListActivity will have the USB accessory Test in its test list, but it
@@ -88,6 +94,8 @@
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_device_admin" />
+            <meta-data android:name="test_required_features"
+                    android:value="android.software.device_admin" />
         </activity>
 
         <!-- A generic activity for intent based tests -->
@@ -101,6 +109,8 @@
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_device_admin" />
+            <meta-data android:name="test_excluded_features"
+                       android:value="android.hardware.type.television:android.software.leanback:android.hardware.type.watch" />
         </activity>
 
         <receiver android:name=".admin.TestDeviceAdminReceiver"
@@ -117,6 +127,8 @@
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
+            <meta-data android:name="test_required_features"
+                    android:value="android.software.backup" />
         </activity>
 
         <activity android:name=".bluetooth.BluetoothTestActivity"
@@ -139,6 +151,7 @@
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/bt_control" />
             <meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BluetoothTestActivity" />
+            <meta-data android:name="test_excluded_features" android:value="android.software.leanback" />
         </activity>
 
         <activity android:name=".bluetooth.SecureServerActivity"
@@ -215,7 +228,14 @@
         <service android:name=".bluetooth.BleServerService"
                 android:label="ble_server_service_name" />
 
-        <activity android:name=".bluetooth.BleClientTestActivity"
+        <service android:name=".bluetooth.BleAdvertiserService"
+                android:label="@string/ble_advertiser_service_name" />
+
+        <service android:name=".bluetooth.BleScannerService"
+                android:label="@string/ble_scanner_service_name" />
+
+        <!-- TODO: Enable when test quality issues listed in b/18283088 is resolved -->
+        <!-- activity android:name=".bluetooth.BleClientTestActivity"
                 android:label="@string/ble_client_test_name"
                 android:configChanges="keyboardHidden|orientation|screenSize">
             <intent-filter>
@@ -224,7 +244,9 @@
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/bt_le" />
             <meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BluetoothTestActivity" />
-        </activity>
+            <meta-data android:name="test_required_features"
+                       android:value="android.hardware.bluetooth_le"/>
+        </activity -->
 
         <activity android:name=".bluetooth.BleClientConnectActivity"
                 android:label="@string/ble_client_connect_name"
@@ -314,7 +336,8 @@
             <meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BleClientTestActivity" />
         </activity>
 
-        <activity android:name=".bluetooth.BleServerStartActivity"
+        <!-- TODO: Enable when test quality issues listed in b/18283088 is resolved -->
+        <!-- activity android:name=".bluetooth.BleServerStartActivity"
                 android:label="@string/ble_server_start_name"
                 android:configChanges="keyboardHidden|orientation|screenSize">
             <intent-filter>
@@ -323,6 +346,80 @@
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/bt_le" />
             <meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BluetoothTestActivity" />
+            <meta-data android:name="test_required_features"
+                       android:value="android.hardware.bluetooth_le"/>
+        </activity -->
+
+        <!-- TODO: Enable when test quality issues listed in b/18282549 is resolved -->
+        <!-- activity android:name=".bluetooth.BleScannerTestActivity"
+                android:label="@string/ble_scanner_test_name"
+                android:configChanges="keyboardHidden|orientation|screenSize">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/bt_le" />
+            <meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BluetoothTestActivity" />
+            <meta-data android:name="test_required_features"
+                       android:value="android.hardware.bluetooth_le"/>
+        </activity -->
+
+        <activity android:name=".bluetooth.BleScannerPowerLevelActivity"
+                android:label="@string/ble_power_level_name"
+                android:configChanges="keyboardHidden|orientation|screenSize">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/bt_le" />
+            <meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BleScannerTestActivity" />
+        </activity>
+
+        <activity android:name=".bluetooth.BleScannerHardwareScanFilterActivity"
+                android:label="@string/ble_scanner_scan_filter_name"
+                android:configChanges="keyboardHidden|orientation|screenSize">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/bt_le" />
+            <meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BleScannerTestActivity" />
+        </activity>
+
+        <!-- TODO: Enable when test quality issues listed in b/18282549 is resolved -->
+        <!-- activity android:name=".bluetooth.BleAdvertiserTestActivity"
+                android:label="@string/ble_advertiser_test_name"
+                android:configChanges="keyboardHidden|orientation|screenSize">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/bt_le" />
+            <meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BluetoothTestActivity" />
+            <meta-data android:name="test_required_features"
+                       android:value="android.hardware.bluetooth_le"/>
+         </activity -->
+
+        <activity android:name=".bluetooth.BleAdvertiserPowerLevelActivity"
+                android:label="@string/ble_power_level_name"
+                android:configChanges="keyboardHidden|orientation|screenSize">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/bt_le" />
+            <meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BleAdvertiserTestActivity" />
+        </activity>
+
+        <activity android:name=".bluetooth.BleAdvertiserHardwareScanFilterActivity"
+                android:label="@string/ble_advertiser_scan_filter_name"
+                android:configChanges="keyboardHidden|orientation|screenSize">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/bt_le" />
+            <meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BleAdvertiserTestActivity" />
         </activity>
 
         <activity android:name=".suid.SuidFilesActivity"
@@ -343,6 +440,8 @@
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_security" />
+            <meta-data android:name="test_excluded_features"
+                       android:value="android.hardware.type.television:android.software.leanback:android.hardware.type.watch" />
         </activity>
 
         <activity android:name=".streamquality.StreamingVideoActivity"
@@ -353,6 +452,8 @@
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_streaming" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.hardware.type.watch" />
         </activity>
 
         <activity android:name=".streamquality.PlayVideoActivity"
@@ -452,6 +553,14 @@
                 android:label="@string/nfc_hce_conflicting_non_payment_emulator"
                 android:configChanges="keyboardHidden|orientation|screenSize" />
 
+        <activity android:name=".nfc.hce.ForegroundNonPaymentEmulatorActivity"
+                android:label="@string/nfc_hce_foreground_non_payment_emulator"
+                android:configChanges="keyboardHidden|orientation|screenSize" />
+
+        <activity android:name=".nfc.hce.ForegroundPaymentEmulatorActivity"
+                android:label="@string/nfc_hce_foreground_payment_emulator"
+                android:configChanges="keyboardHidden|orientation|screenSize" />
+
         <activity android:name=".nfc.hce.OffHostEmulatorActivity"
                 android:label="@string/nfc_hce_offhost_service_emulator"
                 android:configChanges="keyboardHidden|orientation|screenSize" />
@@ -468,6 +577,26 @@
                 android:label="@string/nfc_hce_tap_test_emulator"
                 android:configChanges="keyboardHidden|orientation|screenSize" />
 
+        <activity android:name=".nfc.hce.DynamicAidEmulatorActivity"
+                android:label="@string/nfc_hce_payment_dynamic_aids_emulator"
+                android:configChanges="keyboardHidden|orientation|screenSize" />
+
+        <activity android:name=".nfc.hce.PrefixPaymentEmulatorActivity"
+                android:label="@string/nfc_hce_payment_prefix_aids_emulator"
+                android:configChanges="keyboardHidden|orientation|screenSize" />
+
+        <activity android:name=".nfc.hce.PrefixPaymentEmulator2Activity"
+                android:label="@string/nfc_hce_payment_prefix_aids_emulator_2"
+                android:configChanges="keyboardHidden|orientation|screenSize" />
+
+        <activity android:name=".nfc.hce.DualNonPaymentPrefixEmulatorActivity"
+                android:label="@string/nfc_hce_other_prefix_aids_emulator"
+                android:configChanges="keyboardHidden|orientation|screenSize" />
+
+        <activity android:name=".nfc.hce.ConflictingNonPaymentPrefixEmulatorActivity"
+                android:label="@string/nfc_hce_other_conflicting_prefix_aids_emulator"
+                android:configChanges="keyboardHidden|orientation|screenSize" />
+
         <!-- services used for testing NFC host-based card emulation -->
         <service android:name=".nfc.hce.PaymentService1" android:exported="true"
                  android:permission="android.permission.BIND_NFC_SERVICE"
@@ -533,20 +662,76 @@
             </intent-filter>
             <meta-data android:name="android.nfc.cardemulation.off_host_apdu_service" android:resource="@xml/offhost_aid_list"/>
         </service>
-
-        <activity android:name=".sensors.AccelerometerTestActivity" android:label="@string/snsr_accel_test"
-                android:screenOrientation="nosensor">
+        <service android:name=".nfc.hce.PaymentServiceDynamicAids" android:exported="true"
+                 android:permission="android.permission.BIND_NFC_SERVICE"
+                 android:enabled="false">
             <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+                <action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/>
+                <category android:name="android.intent.category.DEFAULT"/>
             </intent-filter>
-            <meta-data android:name="test_category" android:value="@string/test_category_sensors" />
-            <meta-data android:name="test_required_features" android:value="android.hardware.sensor.accelerometer" />
-        </activity>
+            <meta-data android:name="android.nfc.cardemulation.host_apdu_service" android:resource="@xml/payment_aid_list_1"/>
+        </service>
+        <service android:name=".nfc.hce.PrefixPaymentService1" android:exported="true"
+                 android:permission="android.permission.BIND_NFC_SERVICE"
+                 android:enabled="false">
+            <intent-filter>
+                <action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+            <meta-data android:name="android.nfc.cardemulation.host_apdu_service" android:resource="@xml/payment_prefix_aid_list"/>
+        </service>
+        <service android:name=".nfc.hce.PrefixPaymentService2" android:exported="true"
+                 android:permission="android.permission.BIND_NFC_SERVICE"
+                 android:enabled="false">
+            <intent-filter>
+                <action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+            <meta-data android:name="android.nfc.cardemulation.host_apdu_service" android:resource="@xml/payment_prefix_aid_list_2"/>
+        </service>
+        <service android:name=".nfc.hce.PrefixTransportService1" android:exported="true"
+                 android:permission="android.permission.BIND_NFC_SERVICE"
+                 android:enabled="false">
+            <intent-filter>
+                <action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+            <meta-data android:name="android.nfc.cardemulation.host_apdu_service" android:resource="@xml/transport_prefix_aid_list_1"/>
+        </service>
+        <service android:name=".nfc.hce.PrefixTransportService2" android:exported="true"
+                 android:permission="android.permission.BIND_NFC_SERVICE"
+                 android:enabled="false">
+            <intent-filter>
+                <action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+            <meta-data android:name="android.nfc.cardemulation.host_apdu_service" android:resource="@xml/transport_prefix_aid_list_2"/>
+        </service>
+        <service android:name=".nfc.hce.PrefixAccessService" android:exported="true"
+                 android:permission="android.permission.BIND_NFC_SERVICE"
+                 android:enabled="false">
+            <intent-filter>
+                <action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+            <meta-data android:name="android.nfc.cardemulation.host_apdu_service" android:resource="@xml/access_prefix_aid_list"/>
+        </service>
+
+        <!--
+            A DeviceAdmin receiver for sensor tests, it allows sensor tests to turn off the screen.
+        -->
+        <receiver android:name=".sensors.helpers.SensorDeviceAdminReceiver"
+                android:label="@string/snsr_device_admin_receiver">
+            <meta-data android:name="android.app.device_admin"
+                       android:resource="@xml/sensor_device_admin" />
+            <intent-filter>
+                <action android:name="android.app.action.DEVICE_ADMIN_ENABLED"/>
+            </intent-filter>
+        </receiver>
 
         <activity android:name=".sensors.AccelerometerMeasurementTestActivity"
                   android:label="@string/snsr_accel_m_test"
-                  android:screenOrientation="nosensor">
+                  android:screenOrientation="locked">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
                 <category android:name="android.cts.intent.category.MANUAL_TEST"/>
@@ -556,19 +741,9 @@
                        android:value="android.hardware.sensor.accelerometer"/>
         </activity>
 
-        <activity android:name=".sensors.GyroscopeTestActivity" android:label="@string/snsr_gyro_test"
-                android:screenOrientation="nosensor">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.cts.intent.category.MANUAL_TEST" />
-            </intent-filter>
-            <meta-data android:name="test_category" android:value="@string/test_category_sensors" />
-            <meta-data android:name="test_required_features" android:value="android.hardware.sensor.gyroscope" />
-        </activity>
-
         <activity android:name=".sensors.GyroscopeMeasurementTestActivity"
                   android:label="@string/snsr_gyro_m_test"
-                  android:screenOrientation="nosensor">
+                  android:screenOrientation="locked">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
                 <category android:name="android.cts.intent.category.MANUAL_TEST"/>
@@ -590,10 +765,9 @@
                        android:value="android.hardware.sensor.heartrate" />
         </activity>
 
-        <!-- Disable the test until calibration routine is verified -->
-        <!--activity android:name=".sensors.MagneticFieldMeasurementTestActivity"
+        <activity android:name=".sensors.MagneticFieldMeasurementTestActivity"
                   android:label="@string/snsr_mag_m_test"
-                  android:screenOrientation="nosensor">
+                  android:screenOrientation="locked">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
@@ -601,8 +775,96 @@
             <meta-data android:name="test_category" android:value="@string/test_category_sensors" />
             <meta-data android:name="test_required_features"
                        android:value="android.hardware.sensor.compass" />
+        </activity>
+
+        <!-- TODO: enable when a full set of verifications can be implemented -->
+        <!--activity android:name=".sensors.RotationVectorTestActivity"
+                  android:label="@string/snsr_rot_vec_test"
+                  android:screenOrientation="locked">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_sensors" />
+            <meta-data android:name="test_required_features"
+                       android:value="android.hardware.sensor.gyroscope" />
         </activity-->
 
+        <activity android:name=".sensors.BatchingTestActivity"
+                  android:label="@string/snsr_batch_test"
+                  android:screenOrientation="locked">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_sensors" />
+            <meta-data android:name="test_applicable_features"
+                       android:value="android.hardware.sensor.stepcounter:android.hardware.sensor.stepdetector:android.hardware.sensor.proximity:android.hardware.sensor.light" />
+        </activity>
+
+        <!-- TODO: enable when a more reliable way to identify time synchronization is available -->
+        <!--activity android:name=".sensors.SensorSynchronizationTestActivity"
+                  android:label="@string/snsr_synch_test"
+                  android:screenOrientation="locked">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_sensors" />
+            <meta-data android:name="test_required_features"
+                       android:value="android.hardware.sensor.gyroscope" />
+        </activity-->
+
+        <activity android:name=".sensors.SingleSensorTestsActivity"
+                  android:label="@string/snsr_single_sensor_tests"
+                  android:screenOrientation="locked">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.cts.intent.category.MANUAL_TEST"/>
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_sensors"/>
+            <meta-data android:name="test_applicable_features"
+                       android:value="android.hardware.sensor.accelerometer:android.hardware.sensor.compass:android.hardware.sensor.gyroscope:android.hardware.sensor.barometer" />
+        </activity>
+
+        <activity android:name=".sensors.SensorBatchingTestsActivity"
+                  android:label="@string/snsr_sensor_batching_tests"
+                  android:screenOrientation="locked">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.cts.intent.category.MANUAL_TEST"/>
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_sensors"/>
+            <meta-data android:name="test_applicable_features"
+                       android:value="android.hardware.sensor.accelerometer:android.hardware.sensor.compass:android.hardware.sensor.gyroscope:android.hardware.sensor.barometer" />
+        </activity>
+
+        <activity android:name=".sensors.SensorIntegrationTestsActivity"
+                  android:label="@string/snsr_sensor_integration_tests"
+                  android:screenOrientation="locked">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.cts.intent.category.MANUAL_TEST"/>
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_sensors"/>
+            <meta-data android:name="test_applicable_features"
+                       android:value="android.hardware.sensor.accelerometer:android.hardware.sensor.compass:android.hardware.sensor.gyroscope" />
+        </activity>
+
+        <activity android:name=".sensors.SensorTestActivity"
+                  android:label="@string/snsr_sensor_test"
+                  android:screenOrientation="locked">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.cts.intent.category.MANUAL_TEST"/>
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_sensors"/>
+            <meta-data android:name="test_applicable_features"
+                       android:value="android.hardware.sensor.accelerometer:android.hardware.sensor.stepcounter:android.hardware.sensor.stepdetector:android.hardware.sensor.heartrate:android.hardware.sensor.compass:android.hardware.sensor.ambient_temperature" />
+        </activity>
+
+        <!-- End sensor tests definitions -->
+
         <activity android:name=".location.LocationModeOffTestActivity"
                 android:label="@string/location_mode_off_test">
             <intent-filter>
@@ -610,6 +872,10 @@
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_location" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.hardware.type.television" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.software.leanback" />
         </activity>
         <activity android:name=".location.LocationModeHighAccuracyTestActivity"
                 android:label="@string/location_mode_high_accuracy_test">
@@ -618,6 +884,12 @@
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_location" />
+            <meta-data android:name="test_required_features"
+                    android:value="android.hardware.location.network:android.hardware.location.gps" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.hardware.type.television" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.software.leanback" />
         </activity>
         <activity android:name=".location.LocationModeBatterySavingTestActivity"
                 android:label="@string/location_mode_battery_saving_test">
@@ -626,6 +898,11 @@
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_location" />
+            <meta-data android:name="test_required_features" android:value="android.hardware.location.network" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.hardware.type.television" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.software.leanback" />
         </activity>
         <activity android:name=".location.LocationModeDeviceOnlyTestActivity"
                 android:label="@string/location_mode_device_only_test">
@@ -634,6 +911,11 @@
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_location" />
+            <meta-data android:name="test_required_features" android:value="android.hardware.location.gps" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.hardware.type.television" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.software.leanback" />
         </activity>
 
         <activity android:name=".camera.formats.CameraFormatsActivity"
@@ -735,8 +1017,22 @@
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_hardware" />
             <meta-data android:name="test_required_features" android:value="android.hardware.usb.accessory" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.hardware.type.watch" />
         </activity>
-
+<!-- Turned off Sensor Power Test in initial L release
+        <activity android:name=".sensors.SensorPowerTestActivity"
+                android:label="@string/sensor_power_test"
+                android:configChanges="keyboardHidden|orientation|screenSize">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_sensors" />
+            <meta-data android:name="test_excluded_features"
+                       android:value="android.hardware.type.television:android.software.leanback" />
+        </activity>
+-->
         <activity android:name=".p2p.P2pTestListActivity"
                 android:label="@string/p2p_test"
                 android:configChanges="keyboardHidden|orientation|screenSize">
@@ -748,7 +1044,7 @@
             <meta-data android:name="test_required_features" android:value="android.hardware.wifi.direct" />
         </activity>
 
-        <activity android:name=".nls.NotificationListenerVerifierActivity"
+        <activity android:name=".notifications.NotificationListenerVerifierActivity"
                 android:label="@string/nls_test">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -757,7 +1053,16 @@
             <meta-data android:name="test_category" android:value="@string/test_category_notifications" />
         </activity>
 
-        <service android:name=".nls.MockListener"
+        <activity android:name=".notifications.NotificationAttentionManagementVerifierActivity"
+                android:label="@string/attention_test">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_notifications" />
+        </activity>
+
+        <service android:name=".notifications.MockListener"
                  android:exported="true"
                  android:label="@string/nls_service_name"
                  android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
@@ -766,7 +1071,7 @@
             </intent-filter>
         </service>
 
-        <service  android:name=".nls.NotificationListenerVerifierActivity$DismissService"/>
+        <service  android:name=".notifications.NotificationListenerVerifierActivity$DismissService"/>
         <activity android:name=".security.CAInstallNotificationVerifierActivity"
                 android:label="@string/cacert_test">
             <intent-filter>
@@ -774,6 +1079,12 @@
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_notifications" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.hardware.type.watch" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.hardware.type.television" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.software.leanback" />
         </activity>
         <activity android:name=".security.CANotifyOnBootActivity"
                 android:label="@string/caboot_test">
@@ -782,6 +1093,12 @@
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_notifications" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.hardware.type.watch" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.hardware.type.television" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.software.leanback" />
         </activity>
 
         <activity android:name=".p2p.GoNegRequesterTestListActivity"
@@ -825,17 +1142,19 @@
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
+                <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
             </intent-filter>
         </activity-alias>
 
-        <activity android:name=".sample.SampleTestActivity"
+        <!-- remove comment from the next activity to see the sample test surfacing in the app -->
+        <!-- activity android:name=".sample.SampleTestActivity"
                   android:label="@string/sample_framework_test">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_other" />
-        </activity>
+        </activity -->
 
         <activity android:name=".widget.WidgetTestActivity"
                 android:label="@string/widget_framework_test">
@@ -844,6 +1163,10 @@
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_other" />
+            <meta-data android:name="test_required_features"
+                    android:value="android.software.app_widgets" />
+            <meta-data android:name="test_excluded_features"
+                       android:value="android.software.leanback" />
         </activity>
 
         <activity android:name=".deskclock.DeskClockTestsActivity"
@@ -853,6 +1176,43 @@
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_deskclock" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.hardware.type.television" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.software.leanback" />
+        </activity>
+
+<!-- TODO: enable when not requiring to tap the screen and timeouts are tuned -->
+<!-- Removed from initial L release
+
+        <activity
+                android:name="com.android.cts.verifier.sensors.StepCounterTestActivity"
+                android:label="@string/snsr_step_counter_test"
+                android:screenOrientation="nosensor" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_sensors" />
+            <meta-data android:name="test_excluded_features"
+                       android:value="android.hardware.type.television:android.software.leanback" />
+        </activity>
+-->
+        <activity
+            android:name="com.android.cts.verifier.sensors.SignificantMotionTestActivity"
+            android:label="@string/snsr_significant_motion_test"
+            android:screenOrientation="nosensor" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+
+            <meta-data
+                android:name="test_category"
+                android:value="@string/test_category_sensors" />
+            <meta-data android:name="test_required_features"
+                       android:value="android.hardware.sensor.accelerometer" />
         </activity>
 
         <receiver android:name=".widget.WidgetCtsProvider">
@@ -869,6 +1229,166 @@
             android:permission="android.permission.BIND_REMOTEVIEWS"
             android:exported="false" />
 
-   </application>
+        <activity android:name=".projection.cube.ProjectionCubeActivity"
+                  android:label="@string/pca_test">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_projection" />
+            <meta-data android:name="test_required_features" android:value="android.hardware.faketouch" />
+        </activity>
+
+        <activity android:name=".projection.widgets.ProjectionWidgetActivity"
+                  android:label="@string/pwa_test">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_projection" />
+            <meta-data android:name="test_required_features" android:value="android.hardware.faketouch" />
+        </activity>
+
+        <activity android:name=".projection.list.ProjectionListActivity"
+                  android:label="@string/pla_test">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_projection" />
+            <meta-data android:name="test_excluded_features"
+                       android:value="android.hardware.type.television:android.software.leanback" />
+        </activity>
+
+        <activity android:name=".projection.video.ProjectionVideoActivity"
+                  android:label="@string/pva_test">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_projection" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.hardware.type.watch" />
+        </activity>
+
+        <activity android:name=".projection.touch.ProjectionTouchActivity"
+                  android:label="@string/pta_test">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_projection" />
+            <meta-data android:name="test_required_features" android:value="android.hardware.faketouch" />
+        </activity>
+
+
+        <activity android:name=".projection.offscreen.ProjectionOffscreenActivity"
+                  android:label="@string/poa_test">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_projection" />
+            <meta-data android:name="test_excluded_features"
+                       android:value="android.hardware.type.television:android.software.leanback" />
+        </activity>
+
+        <service android:name=".projection.ProjectionService"
+                 android:label="@string/projection_service_name"
+                 android:process=":projectionservice" />
+
+        <activity android:name=".managedprovisioning.DeviceOwnerTestActivity"
+                android:label="@string/provisioning_device_owner">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_managed_provisioning" />
+            <meta-data android:name="test_required_features" android:value="android.software.managed_users:android.software.device_admin" />
+        </activity>
+
+
+        <!-- TODO: enable when the test can be executed without leaving marks -->
+        <!-- activity android:name=".managedprovisioning.ByodFlowTestActivity"
+                android:launchMode="singleTask"
+                android:label="@string/provisioning_byod">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="com.android.cts.verifier.managedprovisioning.BYOD_STATUS" />
+                <category android:name="android.intent.category.DEFAULT"></category>
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_managed_provisioning" />
+            <meta-data android:name="test_required_features" android:value="android.software.managed_users:android.software.device_admin" />
+        </activity-->
+
+        <activity android:name=".managedprovisioning.ByodHelperActivity">
+            <intent-filter>
+                <action android:name="com.android.cts.verifier.managedprovisioning.BYOD_QUERY" />
+                <action android:name="com.android.cts.verifier.managedprovisioning.BYOD_REMOVE" />
+                <category android:name="android.intent.category.DEFAULT"></category>
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".managedprovisioning.CrossProfileTestActivity">
+            <intent-filter>
+                <action android:name="com.android.cts.verifier.managedprovisioning.CROSS_PROFILE" />
+                <category android:name="android.intent.category.DEFAULT"></category>
+            </intent-filter>
+        </activity>
+
+        <receiver android:name=".managedprovisioning.DeviceAdminTestReceiver"
+                android:label="@string/provisioning_byod_device_admin"
+                android:permission="android.permission.BIND_DEVICE_ADMIN">
+            <meta-data android:name="android.app.device_admin"
+                       android:resource="@xml/device_admin_byod" />
+            <intent-filter>
+                <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+                <action android:name="android.app.action.PROFILE_PROVISIONING_COMPLETE"/>
+            </intent-filter>
+        </receiver>
+
+        <activity android:name=".jobscheduler.IdleConstraintTestActivity" android:label="@string/js_idle_test">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_jobscheduler" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.hardware.type.television" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.software.leanback" />
+        </activity>
+
+        <activity android:name=".jobscheduler.ChargingConstraintTestActivity" android:label="@string/js_charging_test">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_jobscheduler" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.hardware.type.television" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.software.leanback" />
+        </activity>
+
+        <activity android:name=".jobscheduler.ConnectivityConstraintTestActivity" android:label="@string/js_connectivity_test">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
+            </intent-filter>
+            <meta-data android:name="test_category" android:value="@string/test_category_jobscheduler" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.hardware.type.television" />
+            <meta-data android:name="test_excluded_features"
+                    android:value="android.software.leanback" />
+        </activity>
+
+        <service android:name=".jobscheduler.MockJobService"
+            android:permission="android.permission.BIND_JOB_SERVICE"/>
+
+    </application>
 
 </manifest>
diff --git a/apps/CtsVerifier/assets/scripts/execute_power_tests.py b/apps/CtsVerifier/assets/scripts/execute_power_tests.py
new file mode 100755
index 0000000..d1c2dac
--- /dev/null
+++ b/apps/CtsVerifier/assets/scripts/execute_power_tests.py
@@ -0,0 +1,585 @@
+#!/usr/bin/python
+
+# 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.
+
+import logging
+import os.path
+import select
+import sys
+import time
+import collections
+import socket
+import gflags as flags  # http://code.google.com/p/python-gflags/
+import pkgutil
+import threading
+import Queue
+
+# queue to signal thread to exit
+signal_exit_q = Queue.Queue()
+signal_abort = Queue.Queue()
+
+# let this script know about the power monitor implementations
+sys.path = [os.path.basename(__file__)] + sys.path
+available_monitors = [name for _, name, _ in pkgutil.iter_modules(
+    [os.path.join(os.path.dirname(__file__),'power_monitors')]) if not name.startswith('_')]
+
+APK = os.path.join( os.path.dirname(__file__), '..', "CtsVerifier.apk")
+
+FLAGS = flags.FLAGS
+
+# whether to use a strict delay to ensure screen is off, or attempt to use power measurements
+USE_STRICT_DELAY = False
+if USE_STRICT_DELAY:
+    DELAY_SCREEN_OFF = 30.0
+else:
+    DELAY_SCREEN_OFF = 2.0
+
+# whether to log data collected to a file for each sensor run:
+LOG_DATA_TO_FILE = True
+
+logging.getLogger().setLevel(logging.ERROR)
+
+def do_import(name):
+    """import a module by name dynamically"""
+    mod = __import__(name)
+    components = name.split('.')
+    for comp in components[1:]:
+        mod = getattr(mod, comp)
+    return mod
+
+
+class PowerTest:
+    """Class to run a suite of power tests"""
+
+    # Thresholds for max allowed power usage per sensor tested
+    MAX_ACCEL_POWER = 0.08  # Amps
+    MAX_MAG_POWER = 0.08  # Amps
+    MAX_GYRO_POWER = 0.08  # Amps
+    MAX_SIGMO_POWER = 0.08 # Amps
+    MAX_STEP_COUNTER_POWER = 0.08 # Amps
+    MAX_STEP_DETECTOR_POWER = 0.08 # Amps
+
+
+    PORT = 0  # any available port
+    DOMAIN_NAME = "/android/cts/powertest"
+    SAMPLE_COUNT_NOMINAL = 1000
+    RATE_NOMINAL = 100
+
+    REQUEST_EXTERNAL_STORAGE = "EXTERNAL STORAGE?"
+    REQUEST_EXIT = "EXIT"
+    REQUEST_RAISE = "RAISE %s %s"
+    REQUEST_USER_RESPONSE = "USER RESPONSE %s"
+    REQUEST_SET_TEST_RESULT = "SET TEST RESULT %s %s %s"
+    REQUEST_SENSOR_SWITCH = "SENSOR %s %s"
+    REQUEST_SENSOR_AVAILABILITY = "SENSOR? %s"
+    REQUEST_SCREEN_OFF = "SCREEN OFF"
+    REQUEST_SHOW_MESSAGE = "MESSAGE %s"
+
+
+    def __init__(self):
+        power_monitors = do_import("power_monitors.%s" % FLAGS.power_monitor)
+        testid = time.strftime("%d_%m_%Y__%H__%M_%S")
+        self._power_monitor = power_monitors.Power_Monitor(log_file_id = testid)
+        print ("Establishing connection to device...")
+        self.setUsbEnabled(True)
+        status = self._power_monitor.GetStatus()
+        self._native_hz = status["sampleRate"] * 1000
+        self._current_test = "None"
+        self._external_storage = self.executeOnDevice(PowerTest.REQUEST_EXTERNAL_STORAGE,
+                                                      reportErrors=True)
+
+    def __del__(self):
+        self.finalize()
+
+    def finalize(self):
+        """To be called upon termination of host connection to device"""
+        if PowerTest.PORT > 0:
+            # tell device side to exit connection loop, and remove the forwarding connection
+            self.executeOnDevice(PowerTest.REQUEST_EXIT, reportErrors=False)
+            self.executeLocal("adb forward --remove tcp:%d" % PowerTest.PORT)
+        PowerTest.PORT = 0
+        if self._power_monitor:
+            self._power_monitor.Close()
+            self._power_monitor = None
+
+    def _send(self, msg, report_errors=True):
+        """Connect to the device, send the given command, and then disconnect"""
+        if PowerTest.PORT == 0:
+            # on first attempt to send a command, connect to device via any open port number,
+            # forwarding that port to a local socket on the device via adb
+            logging.debug("Seeking port for communication...")
+            # discover an open port
+            dummysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+            dummysocket.bind(("localhost", 0))
+            (_, PowerTest.PORT) = dummysocket.getsockname()
+            dummysocket.close()
+            assert(PowerTest.PORT > 0)
+            status = self.executeLocal("adb forward tcp:%d localabstract:%s" %
+                    (PowerTest.PORT, PowerTest.DOMAIN_NAME))
+            if report_errors:
+                self.reportErrorIf(status != 0, msg="Unable to forward requests to client over adb")
+            logging.info("Forwarding requests over local port %d" % PowerTest.PORT)
+
+        link = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+
+        try:
+            logging.debug("Connecting to device...")
+            link.connect (("localhost", PowerTest.PORT))
+            logging.debug("Connected.")
+        except:
+            if report_errors:
+                self.reportErrorIf(True, msg="Unable to communicate with device: connection refused")
+        logging.debug("Sending '%s'" % msg)
+        link.sendall(msg)
+        logging.debug("Getting response...")
+        response = link.recv(4096)
+        logging.debug("Got response '%s'" % response)
+        link.close()
+        return response
+
+    def queryDevice(self, query):
+        """Post a yes/no query to the device, return True upon successful query, False otherwise"""
+        logging.info("Querying device with '%s'" % query)
+        return self._send(query) == "OK"
+
+    # TODO: abstract device communication (and string commands) into its own class
+    def executeOnDevice(self, cmd , reportErrors=True):
+        """Execute a (string) command on the remote device"""
+        return self._send(cmd , reportErrors)
+
+    def executeLocal(self, cmd, check_status=True):
+        """execute a shell command locally (on the host)"""
+        from subprocess import call
+        status = call(cmd.split(' '))
+        if status != 0 and check_status:
+            logging.error("Failed to execute \"%s\"" % cmd)
+        else:
+            logging.debug("Executed \"%s\"" % cmd)
+        return status
+
+    def reportErrorIf(self, condition, msg):
+        """Report an error condition to the device if condition is True.
+        Will raise an exception on the device if condition is True"""
+        if condition:
+            try:
+                logging.error("Exiting on error: %s" % msg)
+                self.executeOnDevice(PowerTest.REQUEST_RAISE % (self._current_test, msg), False)
+            except:
+
+                logging.error("Unable to communicate with device to report error: %s" % msg)
+                self.finalize()
+                sys.exit(msg)
+            raise Exception(msg)
+
+    def setUsbEnabled(self, enabled, verbose=True):
+        if enabled:
+            val = 1
+        else:
+            val = 0
+        self._power_monitor.SetUsbPassthrough(val)
+        tries = 0
+
+        # Sometimes command won't go through first time, particularly if immediately after a data
+        # collection, so allow for retries
+        status = self._power_monitor.GetStatus()
+        while status is None and tries < 5:
+            tries += 1
+            time.sleep(2.0)
+            logging.error("Retrying get status call...")
+            self._power_monitor.StopDataCollection()
+            self._power_monitor.SetUsbPassthrough(val)
+            status = self._power_monitor.GetStatus()
+
+        if enabled:
+            if verbose: print("...USB enabled, waiting for device")
+            self.executeLocal ("adb wait-for-device")
+            if verbose: print("...device online")
+        else:
+            if verbose: logging.info("...USB disabled")
+        # re-establish port forwarding
+        if enabled and PowerTest.PORT > 0:
+            status = self.executeLocal("adb forward tcp:%d localabstract:%s" %
+                                       (PowerTest.PORT, PowerTest.DOMAIN_NAME))
+            self.reportErrorIf(status != 0, msg="Unable to forward requests to client over adb")
+
+    def waitForScreenOff(self):
+        # disconnect of USB will cause screen to go on, so must wait (1 second more than screen off
+        # timeout)
+        if USE_STRICT_DELAY:
+            time.sleep(DELAY_SCREEN_OFF)
+            return
+
+        # need at least 100 sequential clean low-power measurements to know screen is off
+        THRESHOLD_COUNT_LOW_POWER = 100
+        CURRENT_LOW_POWER_THRESHOLD = 0.060  # Amps
+        TIMEOUT_SCREEN_OFF = 30 # this many tries at most
+        count_good = 0
+        tries = 0
+        print("Waiting for screen off and application processor in suspend mode...")
+        while count_good < THRESHOLD_COUNT_LOW_POWER:
+            measurements = self.collectMeasurements(THRESHOLD_COUNT_LOW_POWER,
+                                                      PowerTest.RATE_NOMINAL,
+                                                      ensure_screen_off=False,
+                                                      verbose=False)
+            count_good = len([m for m in measurements
+                               if m < CURRENT_LOW_POWER_THRESHOLD])
+            tries += 1
+            if count_good < THRESHOLD_COUNT_LOW_POWER and measurements:
+                print("Current usage: %.2f mAmps. Device is probably not in suspend mode.   Waiting..." %
+                      (1000.0*(sum(measurements)/len(measurements))))
+            if tries >= TIMEOUT_SCREEN_OFF:
+                # TODO: dump the state of sensor service to identify if there are features using sensors
+                self.reportErrorIf(tries>=TIMEOUT_SCREEN_OFF,
+                    msg="Unable to determine application processor suspend mode status.")
+                break
+        if DELAY_SCREEN_OFF:
+            # add additional delay time if necessary
+            time.sleep(DELAY_SCREEN_OFF)
+        print("...Screen off and device in suspend mode.")
+
+    def collectMeasurements(self, measurementCount, rate , ensure_screen_off=True, verbose=True,
+                             plot_data = False):
+        assert(measurementCount > 0)
+        decimate_by = self._native_hz / rate  or 1
+        if ensure_screen_off:
+            self.waitForScreenOff()
+            print ("Taking measurements...")
+        self._power_monitor.StartDataCollection()
+        sub_measurements = []
+        measurements = []
+        tries = 0
+        if verbose: print("")
+        try:
+            while len(measurements) < measurementCount and tries < 5:
+                if tries:
+                    self._power_monitor.StopDataCollection()
+                    self._power_monitor.StartDataCollection()
+                    time.sleep(1.0)
+                tries += 1
+                additional = self._power_monitor.CollectData()
+                if additional is not None:
+                    tries = 0
+                    sub_measurements.extend(additional)
+                    while len(sub_measurements) >= decimate_by:
+                        sub_avg = sum(sub_measurements) / len(sub_measurements)
+                        measurements.append(sub_avg)
+                        sub_measurements = sub_measurements[decimate_by:]
+                        if verbose:
+                            sys.stdout.write("\33[1A\33[2K")
+                            print ("MEASURED[%d]: %f" % (len(measurements),measurements[-1]))
+        finally:
+            self._power_monitor.StopDataCollection()
+
+        self.reportErrorIf(measurementCount > len(measurements),
+                            "Unable to collect all requested measurements")
+        return measurements
+
+    def request_user_acknowledgment(self, msg):
+        """Post message to user on screen and wait for acknowledgment"""
+        response = self.executeOnDevice(PowerTest.REQUEST_USER_RESPONSE % msg)
+        self.reportErrorIf(response != "OK", "Unable to request user acknowledgment")
+
+    def setTestResult (self, testname, condition, msg):
+        if condition is False:
+            val = "FAIL"
+        elif condition is True:
+            val = "PASS"
+        else:
+            val = condition
+        print ("Test %s : %s" % (testname, val))
+        response = self.executeOnDevice(PowerTest.REQUEST_SET_TEST_RESULT % (testname, val, msg))
+        self.reportErrorIf(response != "OK", "Unable to send test status to Verifier")
+
+    def setPowerOn(self, sensor, powered_on):
+        response = self.executeOnDevice(PowerTest.REQUEST_SENSOR_SWITCH %
+                                        ({True:"ON", False:"OFF"}[powered_on], sensor))
+        self.reportErrorIf(response == "ERR", "Unable to set sensor %s state" % sensor)
+        logging.info("Set %s %s" % (sensor, {True:"ON", False:"OFF"}[powered_on]))
+        return response
+
+    def runPowerTest(self, sensor, max_power_allowed, user_request = None):
+        if not signal_abort.empty():
+            sys.exit( signal_abort.get() )
+        self._current_test = "%s_Power_Test_While_%s" % (sensor,
+                                    {True:"Under_Motion", False:"Still"}[user_request is not None])
+        try:
+            print ("\n\n---------------------------------")
+            if user_request is not None:
+                print ("Running power test on %s under motion." % sensor)
+            else:
+                print ("Running power test on %s while device is still." % sensor)
+            print ("---------------------------------")
+            response = self.executeOnDevice(PowerTest.REQUEST_SENSOR_AVAILABILITY % sensor)
+            if response == "UNAVAILABLE":
+                self.setTestResult(self._current_test, condition="SKIPPED",
+                    msg="Sensor %s not available on this platform"%sensor)
+            self.setPowerOn("ALL", False)
+            if response == "UNAVAILABLE":
+                self.setTestResult(self._current_test, condition="SKIPPED",
+                                   msg="Sensor %s not available on this device"%sensor)
+                return
+
+            self.reportErrorIf(response != "OK", "Unable to set all sensor off")
+            if not signal_abort.empty():
+                sys.exit( signal_abort.get() )
+            self.executeOnDevice(PowerTest.REQUEST_SCREEN_OFF)
+            self.setUsbEnabled(False)
+            print("Collecting background measurements...")
+            measurements = self.collectMeasurements( PowerTest.SAMPLE_COUNT_NOMINAL,
+                                                     PowerTest.RATE_NOMINAL,
+                                                     plot_data = True)
+            if measurements and LOG_DATA_TO_FILE:
+                with open( "/tmp/cts-power-tests-%s-%s-background-data.log"%(sensor,
+                   {True:"Under_Motion", False:"Still"}[user_request is not None] ),'w') as f:
+                    for m in measurements:
+                        f.write( "%.4f\n"%m)
+            self.reportErrorIf(not measurements, "No background measurements could be taken")
+            backgnd = sum(measurements) / len(measurements)
+            self.setUsbEnabled(True)
+            self.setPowerOn(sensor, True)
+            if user_request is not None:
+                print("===========================================\n" +
+                      "==> Please follow the instructions presented on the device\n" +
+                      "==========================================="
+                     )
+                self.request_user_acknowledgment(user_request)
+            self.executeOnDevice(PowerTest.REQUEST_SCREEN_OFF)
+            self.setUsbEnabled(False)
+            self.reportErrorIf(response != "OK", "Unable to set sensor %s ON" % sensor)
+            print ("Collecting sensor %s measurements" % sensor)
+            measurements = self.collectMeasurements(PowerTest.SAMPLE_COUNT_NOMINAL,
+                                                    PowerTest.RATE_NOMINAL)
+
+            if measurements and LOG_DATA_TO_FILE:
+                with open( "/tmp/cts-power-tests-%s-%s-sensor-data.log"%(sensor,
+                   {True:"Under_Motion", False:"Still"}[user_request is not None] ),'w') as f:
+                    for m in measurements:
+                        f.write( "%.4f\n"%m)
+                    self.setUsbEnabled(True, verbose = False)
+                    print("Saving raw data files to device...")
+                    self.executeLocal("adb shell mkdir -p %s" % self._external_storage, False)
+                    self.executeLocal("adb push %s %s/." % (f.name, self._external_storage))
+                    self.setUsbEnabled(False, verbose = False)
+            self.reportErrorIf(not measurements, "No measurements could be taken for %s" % sensor)
+            avg = sum(measurements) / len(measurements)
+            squared = [(m-avg)*(m-avg) for m in measurements]
+
+            import math
+            stddev = math.sqrt(sum(squared)/len(squared))
+            current_diff = avg - backgnd
+            self.setUsbEnabled(True)
+            max_power = max(measurements) - avg
+            if current_diff <= max_power_allowed:
+                # TODO: fail the test of background > current
+                message = ("Draw is within limits. Current:%f Background:%f   Measured: %f Stddev: %f  Peak: %f")%\
+                             ( current_diff*1000.0, backgnd*1000.0, avg*1000.0, stddev*1000.0, max_power*1000.0)
+            else:
+                message = ("Draw is too high. Current:%f Background:%f   Measured: %f Stddev: %f  Peak: %f")%\
+                             ( current_diff*1000.0, backgnd*1000.0, avg*1000.0, stddev*1000.0, max_power*1000.0)
+            self.setTestResult( testname = self._current_test,
+                                condition = current_diff <= max_power_allowed,
+                                msg = message)
+            print("Result: "+message)
+        except:
+            import traceback
+            traceback.print_exc()
+            self.setTestResult(self._current_test, condition="FAIL",
+                               msg="Exception occurred during run of test.")
+
+
+    @staticmethod
+    def run_tests():
+        testrunner = None
+        try:
+            GENERIC_MOTION_REQUEST = "\n===> Please press Next and when the screen is off, keep " + \
+                "the device under motion with only tiny, slow movements until the screen turns " + \
+                "on again.\nPlease refrain from interacting with the screen or pressing any side " + \
+                "buttons while measurements are taken."
+            USER_STEPS_REQUEST = "\n===> Please press Next and when the screen is off, then move " + \
+                "the device to simulate step motion until the screen turns on again.\nPlease " + \
+                "refrain from interacting with the screen or pressing any side buttons while " + \
+                "measurements are taken."
+            testrunner = PowerTest()
+            testrunner.executeOnDevice(PowerTest.REQUEST_SHOW_MESSAGE % "Connected.  Running tests...")
+            testrunner.runPowerTest("SIGNIFICANT_MOTION", PowerTest.MAX_SIGMO_POWER, user_request = GENERIC_MOTION_REQUEST)
+            testrunner.runPowerTest("STEP_DETECTOR", PowerTest.MAX_STEP_DETECTOR_POWER, user_request = USER_STEPS_REQUEST)
+            testrunner.runPowerTest("STEP_COUNTER", PowerTest.MAX_STEP_COUNTER_POWER, user_request = USER_STEPS_REQUEST)
+            testrunner.runPowerTest("ACCELEROMETER", PowerTest.MAX_ACCEL_POWER, user_request = GENERIC_MOTION_REQUEST)
+            testrunner.runPowerTest("MAGNETIC_FIELD", PowerTest.MAX_MAG_POWER, user_request = GENERIC_MOTION_REQUEST)
+            testrunner.runPowerTest("GYROSCOPE", PowerTest.MAX_GYRO_POWER, user_request = GENERIC_MOTION_REQUEST)
+            testrunner.runPowerTest("ACCELEROMETER", PowerTest.MAX_ACCEL_POWER, user_request = None)
+            testrunner.runPowerTest("MAGNETIC_FIELD", PowerTest.MAX_MAG_POWER, user_request = None)
+            testrunner.runPowerTest("GYROSCOPE", PowerTest.MAX_GYRO_POWER, user_request = None)
+            testrunner.runPowerTest("SIGNIFICANT_MOTION", PowerTest.MAX_SIGMO_POWER, user_request = None)
+            testrunner.runPowerTest("STEP_DETECTOR", PowerTest.MAX_STEP_DETECTOR_POWER, user_request = None)
+            testrunner.runPowerTest("STEP_COUNTER", PowerTest.MAX_STEP_COUNTER_POWER, user_request = None)
+        except:
+            import traceback
+            traceback.print_exc()
+        finally:
+            signal_exit_q.put(0) # anything will signal thread to terminate
+            logging.info("TESTS COMPLETE")
+            if testrunner:
+                try:
+                    testrunner.finalize()
+                except socket.error:
+                    sys.exit("============================\nUnable to connect to device under " + \
+                             "test. Make sure the device is connected via the usb pass-through, " + \
+                             "the CtsVerifier app is running the SensorPowerTest on the device, " + \
+                             "and USB pass-through is enabled.\n===========================")
+
+
+def main(argv):
+  """ Simple command-line interface for a power test application."""
+  useful_flags = ["voltage", "status", "usbpassthrough",
+                  "samples", "current", "log", "power_monitor"]
+  if not [f for f in useful_flags if FLAGS.get(f, None) is not None]:
+    print __doc__.strip()
+    print FLAGS.MainModuleHelp()
+    return
+
+  if FLAGS.avg and FLAGS.avg < 0:
+    loggign.error("--avg must be greater than 0")
+    return
+
+  if FLAGS.voltage is not None:
+    if FLAGS.voltage > 5.5:
+        print("!!WARNING: Voltage higher than typical values!!!")
+    try:
+        response = raw_input("Voltage of %.3f requested.  Confirm this is correct (Y/N)"%FLAGS.voltage)
+        if response.upper() != "Y":
+            sys.exit("Aborting")
+    except:
+        sys.exit("Aborting.")
+
+  if not FLAGS.power_monitor:
+      sys.exit("You must specify a '--power_monitor' option to specify which power monitor type " + \
+               "you are using.\nOne of:\n  \n  ".join(available_monitors))
+  power_monitors = do_import('power_monitors.%s' % FLAGS.power_monitor)
+  try:
+      mon = power_monitors.Power_Monitor(device=FLAGS.device)
+  except:
+      import traceback
+      traceback.print_exc()
+      sys.exit("No power monitors found")
+
+  if FLAGS.voltage is not None:
+
+    if FLAGS.ramp is not None:
+      mon.RampVoltage(mon.start_voltage, FLAGS.voltage)
+    else:
+      mon.SetVoltage(FLAGS.voltage)
+
+  if FLAGS.current is not None:
+    mon.SetMaxCurrent(FLAGS.current)
+
+  if FLAGS.status:
+    items = sorted(mon.GetStatus().items())
+    print "\n".join(["%s: %s" % item for item in items])
+
+  if FLAGS.usbpassthrough:
+    if FLAGS.usbpassthrough == 'off':
+      mon.SetUsbPassthrough(0)
+    elif FLAGS.usbpassthrough == 'on':
+      mon.SetUsbPassthrough(1)
+    elif FLAGS.usbpassthrough == 'auto':
+      mon.SetUsbPassthrough(2)
+    else:
+      mon.Close()
+      sys.exit('bad pass-through flag: %s' % FLAGS.usbpassthrough)
+
+  if FLAGS.samples:
+    # Make sure state is normal
+    mon.StopDataCollection()
+    status = mon.GetStatus()
+    native_hz = status["sampleRate"] * 1000
+
+    # Collect and average samples as specified
+    mon.StartDataCollection()
+
+    # In case FLAGS.hz doesn't divide native_hz exactly, use this invariant:
+    # 'offset' = (consumed samples) * FLAGS.hz - (emitted samples) * native_hz
+    # This is the error accumulator in a variation of Bresenham's algorithm.
+    emitted = offset = 0
+    collected = []
+    history_deque = collections.deque()  # past n samples for rolling average
+
+    try:
+      last_flush = time.time()
+      while emitted < FLAGS.samples or FLAGS.samples == -1:
+        # The number of raw samples to consume before emitting the next output
+        need = (native_hz - offset + FLAGS.hz - 1) / FLAGS.hz
+        if need > len(collected):  # still need more input samples
+          samples = mon.CollectData()
+          if not samples: break
+          collected.extend(samples)
+        else:
+          # Have enough data, generate output samples.
+          # Adjust for consuming 'need' input samples.
+          offset += need * FLAGS.hz
+          while offset >= native_hz:  # maybe multiple, if FLAGS.hz > native_hz
+            this_sample = sum(collected[:need]) / need
+
+            if FLAGS.timestamp: print int(time.time()),
+
+            if FLAGS.avg:
+              history_deque.appendleft(this_sample)
+              if len(history_deque) > FLAGS.avg: history_deque.pop()
+              print "%f %f" % (this_sample,
+                               sum(history_deque) / len(history_deque))
+            else:
+              print "%f" % this_sample
+            sys.stdout.flush()
+
+            offset -= native_hz
+            emitted += 1  # adjust for emitting 1 output sample
+          collected = collected[need:]
+          now = time.time()
+          if now - last_flush >= 0.99:  # flush every second
+            sys.stdout.flush()
+            last_flush = now
+    except KeyboardInterrupt:
+      print("interrupted")
+      return 1
+    finally:
+      mon.Close()
+    return 0
+
+  if FLAGS.run:
+    if not FLAGS.power_monitor:
+        sys.exit("When running power tests, you must specify which type of power monitor to use" +
+                 " with '--power_monitor <type of power monitor>'")
+    PowerTest.run_tests()
+
+
+if __name__ == "__main__":
+    flags.DEFINE_boolean("status", None, "Print power meter status")
+    flags.DEFINE_integer("avg", None,
+                         "Also report average over last n data points")
+    flags.DEFINE_float("voltage", None, "Set output voltage (0 for off)")
+    flags.DEFINE_float("current", None, "Set max output current")
+    flags.DEFINE_string("usbpassthrough", None, "USB control (on, off, auto)")
+    flags.DEFINE_integer("samples", None, "Collect and print this many samples")
+    flags.DEFINE_integer("hz", 5000, "Print this many samples/sec")
+    flags.DEFINE_string("device", None,
+                        "Path to the device in /dev/... (ex:/dev/ttyACM1)")
+    flags.DEFINE_boolean("timestamp", None,
+                         "Also print integer (seconds) timestamp on each line")
+    flags.DEFINE_boolean("ramp", True, "Gradually increase voltage")
+    flags.DEFINE_boolean("log", False, "Log progress to a file or not")
+    flags.DEFINE_boolean("run", False, "Run the test suite for power")
+    flags.DEFINE_string("power_monitor", None, "Type of power monitor to use")
+    sys.exit(main(FLAGS(sys.argv)))
+
diff --git a/apps/CtsVerifier/assets/scripts/power_monitors/__init__.py b/apps/CtsVerifier/assets/scripts/power_monitors/__init__.py
new file mode 100644
index 0000000..cec4545
--- /dev/null
+++ b/apps/CtsVerifier/assets/scripts/power_monitors/__init__.py
@@ -0,0 +1,96 @@
+#!/usr/bin/python
+
+# 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.
+#
+
+from abc import abstractmethod
+
+class Abstract_Power_Monitor(object):
+  """
+  Provides a simple interface to use the power meter.
+  The implementer should establish communications with the power monitor
+  on __init__:
+
+  monitor = <<Implementing Class>>(...)
+
+  Afterward, data can be collected multiple times via the
+  series of calls, for example:
+
+      montior.StartDataCollection()
+      data = True
+      while data is not None:
+          data = monitor.CollectData()
+          <<do-something-with-data>>
+      monitor.StopDataCollection()
+
+  On exit, Close should be called:
+
+      monitor.Close()
+
+  The method GetStatus() can be used to check voltage setting as well as
+  ensure status of the USB passthrough connection.
+  """
+
+  
+  
+  def __init__(self ):
+      pass  
+
+  @abstractmethod
+  def Close(self):
+      """Close the connection to the device, preventing
+      further interactions.  This should be called only
+      when the power monitor is no longer needed
+      (e.g. on exit)
+      """
+      pass
+
+  @abstractmethod
+  def GetStatus(self):
+    """ Requests and waits for status.  Returns status dictionary.
+    This should at a minimum contain entries for "usbPassthroughMode"
+    and "outputVoltageSetting" """
+    pass
+
+  @abstractmethod
+  def SetVoltage(self, v):
+    """ Set the output voltage, 0 to disable. """
+    pass
+
+  @abstractmethod
+  def SetMaxCurrent(self, i):
+    """Set the max output current."""
+    pass
+    
+  @abstractmethod
+  def SetUsbPassthrough(self, val):
+    """ Set the USB passthrough mode: 0 = off, 1 = on,  2 = auto. """
+    pass
+
+  @abstractmethod
+  def StartDataCollection(self):    
+    """ Tell the device to start collecting and sending measurement data. """
+    pass
+    
+  @abstractmethod
+  def StopDataCollection(self):
+    """ Tell the device to stop collecting measurement data. """
+    pass
+    
+  @abstractmethod
+  def CollectData(self, verbose = True):
+    """ Return some current samples.  Call StartDataCollection() first.
+    Returns None if no data available"""
+    pass
diff --git a/apps/CtsVerifier/assets/scripts/power_monitors/_dummy.py b/apps/CtsVerifier/assets/scripts/power_monitors/_dummy.py
new file mode 100644
index 0000000..16c2f3c
--- /dev/null
+++ b/apps/CtsVerifier/assets/scripts/power_monitors/_dummy.py
@@ -0,0 +1,84 @@
+#!/usr/bin/python
+
+# 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.
+
+from . import Abstract_Power_Monitor
+
+class Power_Monitor(Abstract_Power_Monitor):
+  """
+  Dummy implementation for internal use only to test host-to-device
+  interactions without need for a real power monitor.  This is not
+  to be used in any way as part of CtsVerifier or CTS verification
+  activities in general.
+  """
+
+  
+  def __init__(self, device = None, wait = False, log_file_id = None ):
+      self._device = device
+      self._usbpassthroughmode = 1
+      self._voltage = 0.0
+      self._data_active = False
+      self._sequence = 0
+      
+  def __del__(self):
+      self.Close()
+
+  def Close(self):
+      pass
+    
+  @staticmethod
+  def Discover():
+      return ["dummy_monitor"]
+
+  def GetStatus(self):
+    """ Requests and waits for status.  Returns status dictionary. """
+    return {"usbPassthroughMode": self._usbpassthroughmode,
+            "sampleRate":1}
+
+
+  def RampVoltage(self, start, end):
+      self._voltage = end   
+
+  def SetVoltage(self, v):
+    """ Set the output voltage, 0 to disable. """
+    self._voltage = v
+
+  def SetMaxCurrent(self, i):
+    """Set the max output current."""
+    self._max_current = i
+    
+  def SetUsbPassthrough(self, val):
+    """ Set the USB passthrough mode: 0 = off, 1 = on,  2 = auto. """
+    self._usbpassthroughmode = val
+
+  def StartDataCollection(self):    
+    """ Tell the device to start collecting and sending measurement data. """
+    self._data_active = True
+    
+  def StopDataCollection(self):
+    """ Tell the device to stop collecting measurement data. """
+    self._data_active = False
+    
+  def CollectData(self, verbose = True):
+    """ Return some current samples.  Call StartDataCollection() first. """
+    #self.log("Collecting data ...", debug = True)
+    import random
+    if self._data_active:
+        base = [0.003, 0.003, 0.003, (self._sequence%4)*0.0005]
+        self._sequence += 1
+        values = [ random.gauss(base[(self._sequence-1)%4], 0.0005) for _ in range(100)]
+    else:
+        values = None
+    return values
diff --git a/apps/CtsVerifier/assets/scripts/power_monitors/monsoon.py b/apps/CtsVerifier/assets/scripts/power_monitors/monsoon.py
new file mode 100644
index 0000000..c02f113
--- /dev/null
+++ b/apps/CtsVerifier/assets/scripts/power_monitors/monsoon.py
@@ -0,0 +1,433 @@
+#!/usr/bin/python
+
+# 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.
+
+
+import fcntl
+import logging
+logging.getLogger().setLevel(logging.ERROR)
+
+import os.path
+import select
+import stat
+import struct
+import sys
+import time
+import collections
+import socket
+import glob
+import signal
+import serial           # http://pyserial.sourceforge.net/
+
+#Set to True if you want log output to go to screen:
+LOG_TO_SCREEN = False
+
+TIMEOUT_SERIAL = 1 #seconds
+
+#ignore SIG CONTINUE signals
+for signum in [signal.SIGCONT]:              
+  signal.signal(signum, signal.SIG_IGN)
+
+try:
+  from . import Abstract_Power_Monitor
+except:
+  sys.exit("You cannot run 'monsoon.py' directly.  Run 'execut_power_tests.py' instead.")
+  
+class Power_Monitor(Abstract_Power_Monitor):
+  """
+  Provides a simple class to use the power meter, e.g.
+  mon = monsoon.Power_Monitor()
+  mon.SetVoltage(3.7)
+  mon.StartDataCollection()
+  mydata = []
+  while len(mydata) < 1000:
+    mydata.extend(mon.CollectData())
+  mon.StopDataCollection()
+  """
+  _do_log = False
+
+  @staticmethod
+  def lock( device ):
+      tmpname = "/tmp/monsoon.%s.%s" % ( os.uname()[0],
+                                         os.path.basename(device))
+      lockfile = open(tmpname, "w")
+      try:  # use a lockfile to ensure exclusive access
+          fcntl.lockf(lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
+          logging.debug("Locked device %s"%device)
+      except IOError as e:
+          self.log("device %s is in use" % dev)
+          sys.exit('device in use')
+      return lockfile
+  
+  def to_string(self):
+      return self._devicename
+  
+  def __init__(self, device = None, wait = False, log_file_id= None ):
+    """
+    Establish a connection to a Power_Monitor.
+    By default, opens the first available port, waiting if none are ready.
+    A particular port can be specified with "device".
+    With wait=0, IOError is thrown if a device is not immediately available.
+    """
+    self._lockfile = None
+    self._logfile = None
+    self.ser = None
+    for signum in [signal.SIGALRM, signal.SIGHUP, signal.SIGINT,
+                   signal.SIGILL, signal.SIGQUIT,
+                   signal.SIGTRAP,signal.SIGABRT, signal.SIGIOT, signal.SIGBUS,
+                   signal.SIGFPE, signal.SIGSEGV, signal.SIGUSR2, signal.SIGPIPE,
+                   signal.SIGTERM]:
+      signal.signal(signum, self.handle_signal)
+
+    self._coarse_ref = self._fine_ref = self._coarse_zero = self._fine_zero = 0
+    self._coarse_scale = self._fine_scale = 0
+    self._last_seq = 0
+    self.start_voltage = 0
+        
+    if device:
+      if isinstance( device, serial.Serial ):
+        self.ser = device
+        
+    else:
+        device_list = None
+        while not device_list:
+            device_list = Power_Monitor.Discover()
+            if not device_list and wait:
+                time.sleep(1.0)
+                logging.info("No power monitor serial devices found.  Retrying...")
+            elif not device_list and not wait:
+                logging.error("No power monitor serial devices found.  Exiting")
+                self.Close()
+                sys.exit("No power monitor serial devices found")
+                
+        if device_list:
+            if len(device_list) > 1:
+                logging.error("=======================================")
+                logging.error("More than one power monitor discovered!")
+                logging.error("Test may not execute properly.Aborting test.")
+                logging.error("=======================================")
+                sys.exit("More than one power monitor connected.")
+            device = device_list[0].to_string() # choose the first one
+            if len(device_list) > 1:
+                logging.info("More than one device found.  Using %s"%device)
+            else:
+                logging.info("Power monitor @ %s"%device)
+        else: raise IOError("No device found")
+          
+    self._lockfile = Power_Monitor.lock( device )
+    if log_file_id is not None:
+        self._logfilename = "/tmp/monsoon_%s_%s.%s.log" % (os.uname()[0], os.path.basename(device),
+                                                            log_file_id)
+        self._logfile = open(self._logfilename,'a')
+    else:
+        self._logfile = None
+    try:
+        self.ser = serial.Serial(device, timeout= TIMEOUT_SERIAL)
+    except Exception as e:
+      self.log( "error opening device %s: %s" % (dev, e))
+      self._lockfile.close()
+      raise
+    logging.debug("Setting up power monitor...")
+    self._devicename = device
+    #just in case, stop any active data collection on monsoon
+    self._dataCollectionActive = True
+    self.StopDataCollection()
+    logging.debug("Flushing input...")
+    self._FlushInput()  # discard stale input
+    logging.debug("Getting status....")
+    status = self.GetStatus()
+    
+    if not status:
+      self.log( "no response from device %s" % device)
+      self._lockfile.close()
+      raise IOError("Failed to get status from device")
+    self.start_voltage = status["voltage1"]
+    
+  def __del__(self):
+    self.Close()
+
+  def Close(self):
+    if self._logfile:
+      print("=============\n"+\
+            "Power Monitor log file can be found at '%s'"%self._logfilename +
+            "=============\n")
+      self._logfile.close()
+      self._logfile = None
+    if (self.ser):
+      #self.StopDataCollection()
+      self.ser.flush()
+      self.ser.close()
+      self.ser = None
+    if self._lockfile:
+      self._lockfile.close()
+
+  def log(self, msg , debug = False):
+    if self._logfile: self._logfile.write( msg + "\n")
+    if not debug and LOG_TO_SCREEN:
+      logging.error( msg )
+    else:
+      logging.debug(msg)
+
+  def handle_signal( self, signum, frame):
+    if self.ser:
+      self.ser.flush()
+      self.ser.close()
+      self.ser = None
+    self.log("Got signal %d"%signum)
+    sys.exit("\nGot signal %d\n"%signum)
+    
+  @staticmethod
+  def Discover():
+    monsoon_list = []
+    elapsed = 0
+    logging.info("Discovering power monitor(s)...")
+    ser_device_list = glob.glob("/dev/ttyACM*")
+    logging.info("Seeking devices %s"%ser_device_list)
+    for dev in ser_device_list:
+        try:
+            lockfile = Power_Monitor.lock( dev )
+        except:
+            logging.info( "... device %s in use, skipping"%dev)
+            continue
+        tries = 0
+        ser = None
+        while ser is None and tries < 100:
+             try:  # try to open the device
+                ser = serial.Serial( dev, timeout=TIMEOUT_SERIAL)
+             except Exception as e:
+                logging.error(  "error opening device %s: %s" % (dev, e) )
+                tries += 1
+                time.sleep(2);
+                ser = None
+        logging.info("... found device %s"%dev)
+        lockfile.close()#will be re-locked once monsoon instance created
+        logging.debug("unlocked")
+        if not ser:
+            continue
+        if ser is not None:
+            try:
+                monsoon = Power_Monitor(device = dev)
+                status = monsoon.GetStatus()
+                
+                if not status:
+                    monsoon.log("... no response from device %s, skipping")
+                    continue
+                else:
+                    logging.info("... found power monitor @ %s"%dev)
+                    monsoon_list.append( monsoon )
+            except:
+                import traceback
+                traceback.print_exc()
+                logging.error("... %s appears to not be a monsoon device"%dev)
+    logging.debug("Returning list of %s"%monsoon_list)
+    return monsoon_list
+
+  def GetStatus(self):
+    """ Requests and waits for status.  Returns status dictionary. """
+
+    # status packet format
+    self.log("Getting status...", debug = True)
+    STATUS_FORMAT = ">BBBhhhHhhhHBBBxBbHBHHHHBbbHHBBBbbbbbbbbbBH"
+    STATUS_FIELDS = [
+        "packetType", "firmwareVersion", "protocolVersion",
+        "mainFineCurrent", "usbFineCurrent", "auxFineCurrent", "voltage1",
+        "mainCoarseCurrent", "usbCoarseCurrent", "auxCoarseCurrent", "voltage2",
+        "outputVoltageSetting", "temperature", "status", "leds",
+        "mainFineResistor", "serialNumber", "sampleRate",
+        "dacCalLow", "dacCalHigh",
+        "powerUpCurrentLimit", "runTimeCurrentLimit", "powerUpTime",
+        "usbFineResistor", "auxFineResistor",
+        "initialUsbVoltage", "initialAuxVoltage",
+        "hardwareRevision", "temperatureLimit", "usbPassthroughMode",
+        "mainCoarseResistor", "usbCoarseResistor", "auxCoarseResistor",
+        "defMainFineResistor", "defUsbFineResistor", "defAuxFineResistor",
+        "defMainCoarseResistor", "defUsbCoarseResistor", "defAuxCoarseResistor",
+        "eventCode", "eventData", ]
+
+    self._SendStruct("BBB", 0x01, 0x00, 0x00)
+    while True:  # Keep reading, discarding non-status packets
+      bytes = self._ReadPacket()
+      if not bytes: return None
+      if len(bytes) != struct.calcsize(STATUS_FORMAT) or bytes[0] != "\x10":
+        self.log("wanted status, dropped type=0x%02x, len=%d" % (
+                ord(bytes[0]), len(bytes)))
+        continue
+
+      status = dict(zip(STATUS_FIELDS, struct.unpack(STATUS_FORMAT, bytes)))
+      assert status["packetType"] == 0x10
+      for k in status.keys():
+        if k.endswith("VoltageSetting"):
+          status[k] = 2.0 + status[k] * 0.01
+        elif k.endswith("FineCurrent"):
+          pass # needs calibration data
+        elif k.endswith("CoarseCurrent"):
+          pass # needs calibration data
+        elif k.startswith("voltage") or k.endswith("Voltage"):
+          status[k] = status[k] * 0.000125
+        elif k.endswith("Resistor"):
+          status[k] = 0.05 + status[k] * 0.0001
+          if k.startswith("aux") or k.startswith("defAux"): status[k] += 0.05
+        elif k.endswith("CurrentLimit"):
+          status[k] = 8 * (1023 - status[k]) / 1023.0
+      #self.log( "Returning requested status: \n %s"%(status), debug = True)
+      return status
+
+  def RampVoltage(self, start, end):
+    v = start
+    if v < 3.0: v = 3.0       # protocol doesn't support lower than this
+    while (v < end):
+      self.SetVoltage(v)
+      v += .1
+      time.sleep(.1)
+    self.SetVoltage(end)
+
+  def SetVoltage(self, v):
+    """ Set the output voltage, 0 to disable. """
+    self.log("Setting voltage to %s..."%v, debug = True)
+    if v == 0:
+      self._SendStruct("BBB", 0x01, 0x01, 0x00)
+    else:
+      self._SendStruct("BBB", 0x01, 0x01, int((v - 2.0) * 100))
+    self.log("...Set voltage", debug = True)
+
+  def SetMaxCurrent(self, i):
+    """Set the max output current."""
+    assert i >= 0 and i <= 8
+    self.log("Setting max current to %s..."%i, debug = True)
+    val = 1023 - int((i/8)*1023)
+    self._SendStruct("BBB", 0x01, 0x0a, val & 0xff)
+    self._SendStruct("BBB", 0x01, 0x0b, val >> 8)
+    self.log("...Set max current.", debug = True)
+    
+  def SetUsbPassthrough(self, val):
+    """ Set the USB passthrough mode: 0 = off, 1 = on,  2 = auto. """
+    self._SendStruct("BBB", 0x01, 0x10, val)
+
+  def StartDataCollection(self):    
+    """ Tell the device to start collecting and sending measurement data. """
+    self.log("Starting data collection...", debug = True)
+    self._SendStruct("BBB", 0x01, 0x1b, 0x01) # Mystery command
+    self._SendStruct("BBBBBBB", 0x02, 0xff, 0xff, 0xff, 0xff, 0x03, 0xe8)
+    self.log("...started", debug = True)
+    self._dataCollectionActive = True
+    
+  def StopDataCollection(self):
+    """ Tell the device to stop collecting measurement data. """
+    self._SendStruct("BB", 0x03, 0x00) # stop
+    if self._dataCollectionActive:
+      while self.CollectData(False) is not None:
+        pass
+    self._dataCollectionActive = False
+    
+  def CollectData(self, verbose = True):
+    """ Return some current samples.  Call StartDataCollection() first. """
+    #self.log("Collecting data ...", debug = True)
+    while True:  # loop until we get data or a timeout
+      bytes = self._ReadPacket(verbose)
+      
+      if not bytes: return None
+      if len(bytes) < 4 + 8 + 1 or bytes[0] < "\x20" or bytes[0] > "\x2F":
+        if verbose: self.log( "wanted data, dropped type=0x%02x, len=%d" % (
+          ord(bytes[0]), len(bytes)), debug=verbose)
+        continue
+
+      seq, type, x, y = struct.unpack("BBBB", bytes[:4])
+      data = [struct.unpack(">hhhh", bytes[x:x+8])
+              for x in range(4, len(bytes) - 8, 8)]
+
+      if self._last_seq and seq & 0xF != (self._last_seq + 1) & 0xF:
+        self.log( "data sequence skipped, lost packet?" )
+      self._last_seq = seq
+
+      if type == 0:
+        if not self._coarse_scale or not self._fine_scale:
+          self.log("waiting for calibration, dropped data packet")
+          continue
+
+        out = []
+        for main, usb, aux, voltage in data:
+          if main & 1:
+            out.append(((main & ~1) - self._coarse_zero) * self._coarse_scale)
+          else:
+            out.append((main - self._fine_zero) * self._fine_scale)
+        #self.log("...Collected %d samples"%(len(out)), debug = True)
+        return out
+
+      elif type == 1:
+        self._fine_zero = data[0][0]
+        self._coarse_zero = data[1][0]
+
+      elif type == 2:
+        self._fine_ref = data[0][0]
+        self._coarse_ref = data[1][0]
+
+      else:
+        self.log( "discarding data packet type=0x%02x" % type)
+        continue
+
+      if self._coarse_ref != self._coarse_zero:
+        self._coarse_scale = 2.88 / (self._coarse_ref - self._coarse_zero)
+      if self._fine_ref != self._fine_zero:
+        self._fine_scale = 0.0332 / (self._fine_ref - self._fine_zero)
+
+
+  def _SendStruct(self, fmt, *args):
+    """ Pack a struct (without length or checksum) and send it. """
+    data = struct.pack(fmt, *args)
+    data_len = len(data) + 1
+    checksum = (data_len + sum(struct.unpack("B" * len(data), data))) % 256
+    out = struct.pack("B", data_len) + data + struct.pack("B", checksum)
+    self.ser.write(out)
+    self.ser.flush()
+
+  def _ReadPacket(self, verbose = True):
+    """ Read a single data record as a string (without length or checksum). """
+    len_char = self.ser.read(1)
+    if not len_char:
+      if verbose: self.log( "timeout reading from serial port" )
+      return None
+
+    data_len = struct.unpack("B", len_char)
+    data_len = ord(len_char)
+    if not data_len: return ""
+
+    result = self.ser.read(data_len)
+    if len(result) != data_len: return None
+    body = result[:-1]
+    checksum = (data_len + sum(struct.unpack("B" * len(body), body))) % 256
+    if result[-1] != struct.pack("B", checksum):
+      self.log( "Invalid checksum from serial port" )
+      return None
+    return result[:-1]
+
+  def _FlushInput(self):
+    """ Flush all read data until no more available. """
+    self.ser.flushInput()
+    flushed = 0
+    self.log("Flushing input...", debug = True)
+    while True:
+      ready_r, ready_w, ready_x = select.select([self.ser], [], [self.ser], 0)
+      if len(ready_x) > 0:
+        self.log( "exception from serial port" )
+        return None
+      elif len(ready_r) > 0:
+        flushed += 1
+        self.ser.read(1)  # This may cause underlying buffering.
+        self.ser.flush()  # Flush the underlying buffer too.
+      else:
+        break
+    if flushed > 0:
+      self.log( "flushed >%d bytes" % flushed, debug = True )
+
diff --git a/apps/CtsVerifier/proguard.flags b/apps/CtsVerifier/proguard.flags
index 7e6587a..ca4680f 100644
--- a/apps/CtsVerifier/proguard.flags
+++ b/apps/CtsVerifier/proguard.flags
@@ -6,7 +6,16 @@
     private <fields>;
 }
 
+# ensure we keep public sensor test methods, these are needed at runtime
+-keepclassmembers class * extends com.android.cts.verifier.sensors.base.BaseSensorTestActivity {
+    public <methods>;
+}
+-keepclassmembers class * extends android.hardware.cts.SensorTestCase {
+    public <methods>;
+}
+
 -keepclasseswithmembers class * extends com.android.cts.verifier.location.LocationModeTestActivity
 
 -dontwarn android.hardware.Sensor
+-dontwarn android.test.AndroidTestRunner
 -dontwarn java.util.concurrent.ConcurrentLinkedDeque
diff --git a/apps/CtsVerifier/res/drawable-hdpi/nfc_hce_banner.png b/apps/CtsVerifier/res/drawable-hdpi/nfc_hce_banner.png
new file mode 100644
index 0000000..333b797
--- /dev/null
+++ b/apps/CtsVerifier/res/drawable-hdpi/nfc_hce_banner.png
Binary files differ
diff --git a/apps/CtsVerifier/res/layout-land/sensor_test.xml b/apps/CtsVerifier/res/layout-land/sensor_test.xml
new file mode 100644
index 0000000..293b4b0
--- /dev/null
+++ b/apps/CtsVerifier/res/layout-land/sensor_test.xml
@@ -0,0 +1,53 @@
+<?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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        >
+
+    <LinearLayout
+            android:orientation="horizontal"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="1">
+
+        <ScrollView
+                android:id="@+id/log_scroll_view"
+                android:fillViewport="true"
+                android:layout_height="match_parent"
+                android:layout_width="0dp"
+                android:layout_weight="1">
+
+            <LinearLayout
+                    android:id="@+id/log_layout"
+                    android:orientation="vertical"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"/>
+
+        </ScrollView>
+
+        <android.opengl.GLSurfaceView android:id="@+id/gl_surface_view"
+                android:visibility="gone"
+                android:layout_width="0dp"
+                android:layout_height="match_parent"
+                android:layout_weight="1"/>
+
+    </LinearLayout>
+
+    <include layout="@layout/snsr_next_button" />
+
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout-port/sensor_test.xml b/apps/CtsVerifier/res/layout-port/sensor_test.xml
new file mode 100644
index 0000000..eac5357
--- /dev/null
+++ b/apps/CtsVerifier/res/layout-port/sensor_test.xml
@@ -0,0 +1,42 @@
+<?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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+    <ScrollView android:id="@+id/log_scroll_view"
+            android:fillViewport="true"
+            android:layout_height="0dp"
+            android:layout_weight="1"
+            android:layout_width="match_parent">
+
+        <LinearLayout android:id="@+id/log_layout"
+                android:orientation="vertical"
+                android:layout_height="match_parent"
+                android:layout_width="match_parent"/>
+
+    </ScrollView>
+
+    <android.opengl.GLSurfaceView android:id="@+id/gl_surface_view"
+            android:visibility="gone"
+            android:layout_height="0dp"
+            android:layout_weight="1"
+            android:layout_width="match_parent"/>
+
+    <include layout="@layout/snsr_next_button"/>
+
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/ble_advertiser_hardware_scan_filter.xml b/apps/CtsVerifier/res/layout/ble_advertiser_hardware_scan_filter.xml
new file mode 100644
index 0000000..ce3e1e1
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/ble_advertiser_hardware_scan_filter.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        android:padding="10dip"
+        >
+
+    <LinearLayout android:orientation="vertical"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_centerInParent="true"
+            >
+        <TextView android:text="@string/ble_advertiser_scannable"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+        />
+        <TextView android:text="@string/ble_advertiser_scannable_instruction"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+        />
+        <LinearLayout android:orientation="horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                >
+            <Button android:id="@+id/ble_advertiser_scannable_start"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/ble_advertiser_start"
+                    />
+            <Button android:id="@+id/ble_advertiser_scannable_stop"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/ble_advertiser_stop"
+                    />
+        </LinearLayout>
+        <TextView android:text="@string/ble_advertiser_unscannable"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+        />
+        <TextView android:text="@string/ble_advertiser_unscannable_instruction"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+        />
+        <LinearLayout android:orientation="horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                >
+            <Button android:id="@+id/ble_advertiser_unscannable_start"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/ble_advertiser_start"
+                    />
+            <Button android:id="@+id/ble_advertiser_unscannable_stop"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/ble_advertiser_stop"
+                    />
+        </LinearLayout>
+    </LinearLayout>
+
+    <include android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_alignParentBottom="true"
+            layout="@layout/pass_fail_buttons"
+            />
+</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/ble_advertiser_power_level.xml b/apps/CtsVerifier/res/layout/ble_advertiser_power_level.xml
new file mode 100644
index 0000000..ec3284d
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/ble_advertiser_power_level.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        android:padding="10dip"
+        >
+
+    <TextView android:text="@string/ble_advertiser_power_level_instruction"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+    />
+    <LinearLayout android:orientation="horizontal"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_centerInParent="true"
+            >
+        <Button android:id="@+id/ble_power_level_start"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/ble_advertiser_start"
+                />
+        <Button android:id="@+id/ble_power_level_stop"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/ble_advertiser_stop"
+                />
+    </LinearLayout>
+
+    <include android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_alignParentBottom="true"
+            layout="@layout/pass_fail_buttons"
+            />
+</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/ble_advertiser_test.xml b/apps/CtsVerifier/res/layout/ble_advertiser_test.xml
new file mode 100644
index 0000000..7db2b4e
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/ble_advertiser_test.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        android:padding="10dip"
+        >
+    <ListView android:id="@+id/ble_advertiser_tests"
+            android:layout_height="fill_parent"
+            android:layout_width="match_parent"
+            android:padding="10dip"
+            />
+
+    <include android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_alignParentBottom="true"
+            layout="@layout/pass_fail_buttons"
+            />
+</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/ble_scanner_hardware_scan_filter.xml b/apps/CtsVerifier/res/layout/ble_scanner_hardware_scan_filter.xml
new file mode 100644
index 0000000..f356ded
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/ble_scanner_hardware_scan_filter.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        android:padding="10dip"
+        >
+    <TextView android:text="@string/ble_scanner_scan_filter_instruction"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+    />
+    <LinearLayout android:orientation="vertical"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_centerInParent="true"
+            >
+        <LinearLayout android:orientation="horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                >
+            <Button android:id="@+id/ble_scan_with_filter"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/ble_scan_with_filter"
+                    />
+            <Button android:id="@+id/ble_scan_without_filter"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/ble_scan_without_filter"
+                    />
+        </LinearLayout>
+        <ListView android:id="@+id/ble_scan_result_list"
+                android:layout_height="wrap_content"
+                android:layout_width="match_parent">
+        </ListView>
+    </LinearLayout>
+    <include android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_alignParentBottom="true"
+            layout="@layout/pass_fail_buttons"
+    />
+</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/ble_scanner_power_level.xml b/apps/CtsVerifier/res/layout/ble_scanner_power_level.xml
new file mode 100644
index 0000000..b240db6
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/ble_scanner_power_level.xml
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        android:padding="10dip"
+        >
+    <TextView android:text="@string/ble_scanner_power_level_instruction"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/ble_scanner_power_level_instruction"
+    />
+    <LinearLayout android:orientation="vertical"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_below="@+id/ble_scanner_power_level_instruction"
+            android:layout_centerInParent="true"
+            android:padding="10dp"
+            >
+        <LinearLayout android:orientation="horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_centerInParent="true"
+                >
+            <TextView android:text="@string/ble_ultra_low"
+                  android:layout_width="100dp"
+                  android:layout_height="wrap_content"
+            />
+            <TextView android:id="@+id/ble_ultra_low_mac"
+                  android:layout_width="200dp"
+                  android:layout_height="wrap_content"
+            />
+            <TextView android:id="@+id/ble_ultra_low_rssi"
+                  android:layout_width="100dp"
+                  android:layout_height="wrap_content"
+            />
+        </LinearLayout>
+        <LinearLayout android:orientation="horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+            <TextView android:layout_width="100dp"
+                  android:layout_height="wrap_content"/>
+            <TextView android:id="@+id/ble_ultra_low_count"
+                    android:layout_width="100dp"
+                    android:layout_height="wrap_content"
+            />
+            <TextView android:id="@+id/ble_ultra_low_set_power"
+                    android:layout_width="100dp"
+                    android:layout_height="wrap_content"
+            />
+        </LinearLayout>
+        <LinearLayout android:orientation="horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_centerInParent="true"
+                >
+            <TextView android:text="@string/ble_low"
+                  android:layout_width="100dp"
+                  android:layout_height="wrap_content"
+            />
+            <TextView android:id="@+id/ble_low_mac"
+                  android:layout_width="200dp"
+                  android:layout_height="wrap_content"
+            />
+            <TextView android:id="@+id/ble_low_rssi"
+                  android:layout_width="100dp"
+                  android:layout_height="wrap_content"
+            />
+        </LinearLayout>
+        <LinearLayout android:orientation="horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+            <TextView android:layout_width="100dp"
+                  android:layout_height="wrap_content"/>
+            <TextView android:id="@+id/ble_low_count"
+                    android:layout_width="100dp"
+                    android:layout_height="wrap_content"
+            />
+            <TextView android:id="@+id/ble_low_set_power"
+                    android:layout_width="100dp"
+                    android:layout_height="wrap_content"
+            />
+        </LinearLayout>
+        <LinearLayout android:orientation="horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_centerInParent="true"
+                >
+            <TextView android:text="@string/ble_medium"
+                  android:layout_width="100dp"
+                  android:layout_height="wrap_content"
+            />
+            <TextView android:id="@+id/ble_medium_mac"
+                  android:layout_width="200dp"
+                  android:layout_height="wrap_content"
+            />
+            <TextView android:id="@+id/ble_medium_rssi"
+                  android:layout_width="100dp"
+                  android:layout_height="wrap_content"
+            />
+        </LinearLayout>
+        <LinearLayout android:orientation="horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+            <TextView android:layout_width="100dp"
+                  android:layout_height="wrap_content"/>
+            <TextView android:id="@+id/ble_medium_count"
+                    android:layout_width="100dp"
+                    android:layout_height="wrap_content"
+            />
+            <TextView android:id="@+id/ble_medium_set_power"
+                    android:layout_width="100dp"
+                    android:layout_height="wrap_content"
+            />
+        </LinearLayout>
+        <LinearLayout android:orientation="horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_centerInParent="true"
+                >
+            <TextView android:text="@string/ble_high"
+                  android:layout_width="100dp"
+                  android:layout_height="wrap_content"
+            />
+            <TextView android:id="@+id/ble_high_mac"
+                  android:layout_width="200dp"
+                  android:layout_height="wrap_content"
+            />
+            <TextView android:id="@+id/ble_high_rssi"
+                  android:layout_width="100dp"
+                  android:layout_height="wrap_content"
+            />
+        </LinearLayout>
+        <LinearLayout android:orientation="horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+            <TextView android:layout_width="100dp"
+                  android:layout_height="wrap_content"/>
+            <TextView android:id="@+id/ble_high_count"
+                    android:layout_width="100dp"
+                    android:layout_height="wrap_content"
+            />
+            <TextView android:id="@+id/ble_high_set_power"
+                    android:layout_width="100dp"
+                    android:layout_height="wrap_content"
+            />
+        </LinearLayout>
+        <TextView android:id="@+id/ble_timer"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content" />
+    </LinearLayout>
+
+    <include android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_alignParentBottom="true"
+            layout="@layout/pass_fail_buttons"
+            />
+</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/ble_scanner_test.xml b/apps/CtsVerifier/res/layout/ble_scanner_test.xml
new file mode 100644
index 0000000..c685d57
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/ble_scanner_test.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        android:padding="10dip"
+        >
+    <include android:id="@+id/pass_fail_buttons"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_alignParentBottom="true"
+            layout="@layout/pass_fail_buttons"
+            />
+    <ListView android:id="@+id/ble_scanner_tests"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:layout_above="@id/pass_fail_buttons"
+            android:layout_alignParentTop="true"
+            android:padding="10dip"
+            />
+</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/intent_driven_test.xml b/apps/CtsVerifier/res/layout/intent_driven_test.xml
index e23f4410e..00c1cf6 100644
--- a/apps/CtsVerifier/res/layout/intent_driven_test.xml
+++ b/apps/CtsVerifier/res/layout/intent_driven_test.xml
@@ -1,32 +1,30 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:orientation="vertical"
-    >
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
 
   <ScrollView
       android:layout_width="match_parent"
       android:layout_height="0dp"
       android:layout_weight="1">
     <TextView android:id="@+id/info"
-              android:layout_width="match_parent"
-              android:layout_height="wrap_content"
-              android:textSize="18sp"
-              android:padding="5dp"
-              android:text="@string/dc_start_alarm_test_info"
-        />
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textSize="18sp"
+        android:padding="5dp"
+        android:text="@string/dc_start_alarm_test_info"/>
   </ScrollView>
 
   <LinearLayout android:id="@+id/buttons"
-                android:orientation="horizontal"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"/>
+      android:orientation="horizontal"
+      android:layout_width="wrap_content"
+      android:layout_height="wrap_content"/>
 
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content">
-        <include layout="@layout/pass_fail_buttons"/>
-    </LinearLayout>
+      <include layout="@layout/pass_fail_buttons"/>
+  </LinearLayout>
 </LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/js_charging.xml b/apps/CtsVerifier/res/layout/js_charging.xml
new file mode 100644
index 0000000..4c0e552
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/js_charging.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical" android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/js_test_description"
+        android:layout_margin="@dimen/js_padding"/>
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_margin="@dimen/js_padding"
+        android:text="@string/js_charging_description_1"
+        android:textStyle="bold"/>
+    <Button
+        android:id="@+id/js_charging_start_test_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:text="@string/js_start_test_text"
+        android:onClick="startTest"
+        android:enabled="false"/>
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="@dimen/js_padding"
+        android:layout_marginBottom="@dimen/js_padding">
+        <ImageView
+            android:id="@+id/charging_off_test_image"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@drawable/fs_indeterminate"
+            android:layout_marginRight="@dimen/js_padding"/>
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/js_charging_off_test"
+            android:textSize="16dp"/>
+    </LinearLayout>
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_margin="@dimen/js_padding"
+        android:text="@string/js_charging_description_2"
+        android:textStyle="bold"/>
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="@dimen/js_padding"
+        android:layout_marginBottom="@dimen/js_padding">
+        <ImageView
+            android:id="@+id/charging_on_test_image"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@drawable/fs_indeterminate"
+            android:layout_marginRight="@dimen/js_padding"/>
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/js_charging_on_test"
+            android:textSize="16dp"/>
+    </LinearLayout>
+    <include layout="@layout/pass_fail_buttons" />
+</LinearLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/layout/js_connectivity.xml b/apps/CtsVerifier/res/layout/js_connectivity.xml
new file mode 100644
index 0000000..5208c18
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/js_connectivity.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical" android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/js_test_description"
+        android:layout_margin="@dimen/js_padding"/>
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/js_connectivity_description_1"
+        android:layout_margin="@dimen/js_padding"
+        android:textStyle="bold"/>
+
+    <Button
+        android:id="@+id/js_connectivity_start_test_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:text="@string/js_start_test_text"
+        android:onClick="startTest"
+        android:enabled="false"/>
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="@dimen/js_padding"
+        android:layout_marginBottom="@dimen/js_padding">
+        <ImageView
+            android:id="@+id/connectivity_off_test_unmetered_image"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@drawable/fs_indeterminate"
+            android:layout_marginRight="@dimen/js_padding"/>
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/js_unmetered_connectivity_test"
+            android:textSize="16dp"/>
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="@dimen/js_padding"
+        android:layout_marginBottom="@dimen/js_padding">
+        <ImageView
+            android:id="@+id/connectivity_off_test_any_connectivity_image"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@drawable/fs_indeterminate"
+            android:layout_marginRight="@dimen/js_padding"/>
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/js_any_connectivity_test"
+            android:textSize="16dp"/>
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="@dimen/js_padding"
+        android:layout_marginBottom="@dimen/js_padding">
+        <ImageView
+            android:id="@+id/connectivity_off_test_no_connectivity_image"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@drawable/fs_indeterminate"
+            android:layout_marginRight="@dimen/js_padding"/>
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/js_no_connectivity_test"
+            android:textSize="16dp"/>
+    </LinearLayout>
+
+    <include layout="@layout/pass_fail_buttons" />
+</LinearLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/layout/js_idle.xml b/apps/CtsVerifier/res/layout/js_idle.xml
new file mode 100644
index 0000000..90e55ec
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/js_idle.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical" android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/js_test_description"
+        android:layout_margin="@dimen/js_padding"/>
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/js_idle_description_1"
+        android:layout_margin="@dimen/js_padding"
+        android:textStyle="bold"/>
+
+    <Button
+        android:id="@+id/js_idle_start_test_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:text="@string/js_start_test_text"
+        android:onClick="startTest"
+        android:enabled="false"/>
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="@dimen/js_padding"
+        android:layout_marginBottom="@dimen/js_padding">
+        <ImageView
+            android:id="@+id/idle_off_test_image"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@drawable/fs_indeterminate"
+            android:layout_marginRight="@dimen/js_padding"/>
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/js_idle_item_idle_off"
+            android:textSize="16dp"/>
+    </LinearLayout>
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="@dimen/js_padding"
+        android:layout_marginBottom="@dimen/js_padding">
+        <ImageView
+            android:id="@+id/idle_on_test_image"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@drawable/fs_indeterminate"
+            android:layout_marginRight="@dimen/js_padding"/>
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/js_idle_item_idle_on"
+            android:textSize="16dp"/>
+    </LinearLayout>
+    <include layout="@layout/pass_fail_buttons" />
+</LinearLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/layout/list_content.xml b/apps/CtsVerifier/res/layout/list_content.xml
new file mode 100644
index 0000000..8670283
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/list_content.xml
@@ -0,0 +1,28 @@
+<?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
+  -->
+<android.support.wearable.view.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <ListView
+        android:id="@android:id/list"
+        app:layout_box="all"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+</android.support.wearable.view.BoxInsetLayout>
diff --git a/apps/CtsVerifier/res/layout/nls_item.xml b/apps/CtsVerifier/res/layout/nls_item.xml
index 3ced3cc..f1a10bf 100644
--- a/apps/CtsVerifier/res/layout/nls_item.xml
+++ b/apps/CtsVerifier/res/layout/nls_item.xml
@@ -40,7 +40,7 @@
         android:text="@string/nls_enable_service" />
 
     <Button
-        android:id="@+id/nls_launch_settings"
+        android:id="@+id/nls_action_button"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_alignParentRight="true"
@@ -48,7 +48,7 @@
         android:layout_marginLeft="20dip"
         android:layout_marginRight="20dip"
         android:layout_toRightOf="@id/nls_status"
-        android:onClick="launchSettings"
+        android:onClick="actionPressed"
         android:text="@string/nls_start_settings" />
 
 </RelativeLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/layout/pa_main.xml b/apps/CtsVerifier/res/layout/pa_main.xml
new file mode 100644
index 0000000..76cb7d4
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/pa_main.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" >
+
+    <include
+        android:id="@+id/pass_fail_buttons"
+        android:layout_gravity="top"
+        layout="@layout/pass_fail_buttons" />
+
+    <TextureView
+        android:id="@+id/texture_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_below="@id/pass_fail_buttons" />
+
+</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/pass_fail_buttons.xml b/apps/CtsVerifier/res/layout/pass_fail_buttons.xml
index d70e839..5eec539 100644
--- a/apps/CtsVerifier/res/layout/pass_fail_buttons.xml
+++ b/apps/CtsVerifier/res/layout/pass_fail_buttons.xml
@@ -18,26 +18,23 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content">
 
-    <Button android:id="@+id/pass_button"
+    <ImageButton android:id="@+id/pass_button"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_weight="1"            
-            android:drawableTop="@drawable/fs_good"
-            android:text="@string/pass_button_text"/>
+            android:src="@drawable/fs_good"/>
             
-    <Button android:id="@+id/info_button"
+    <ImageButton android:id="@+id/info_button"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_weight="1"
-            android:drawableTop="@drawable/fs_indeterminate"
-            android:visibility="gone"
-            android:text="@string/info_button_text"/>
+            android:src="@drawable/fs_indeterminate"
+            android:visibility="gone"/>
 
-    <Button android:id="@+id/fail_button"
+    <ImageButton android:id="@+id/fail_button"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_weight="1"            
-            android:drawableTop="@drawable/fs_error"
-            android:text="@string/fail_button_text"/>
+            android:src="@drawable/fs_error"/>
             
 </LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/pca_cubes.xml b/apps/CtsVerifier/res/layout/pca_cubes.xml
new file mode 100644
index 0000000..25869b9
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/pca_cubes.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:fitsSystemWindows="true" >
+
+    <android.opengl.GLSurfaceView
+        android:id="@+id/cube_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/pla_list.xml b/apps/CtsVerifier/res/layout/pla_list.xml
new file mode 100644
index 0000000..0973136
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/pla_list.xml
@@ -0,0 +1,27 @@
+<?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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical" >
+
+    <ListView
+        android:id="@+id/pla_list"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" >
+    </ListView>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/layout/poa_main.xml b/apps/CtsVerifier/res/layout/poa_main.xml
new file mode 100644
index 0000000..578a6a6
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/poa_main.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical" >
+
+    <include layout="@layout/pass_fail_buttons" />
+
+    <TextView
+        android:id="@+id/poa_status_text"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:textAppearance="@style/InstructionsFont" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/layout/poa_touch.xml b/apps/CtsVerifier/res/layout/poa_touch.xml
new file mode 100644
index 0000000..0085227
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/poa_touch.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" >
+    <com.android.cts.verifier.projection.offscreen.ColorChangeOnKeyView
+        android:id="@+id/multi_touch_view"
+        android:focusable="true"
+        android:focusableInTouchMode="true"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/provisioning_byod.xml b/apps/CtsVerifier/res/layout/provisioning_byod.xml
new file mode 100644
index 0000000..989266f
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/provisioning_byod.xml
@@ -0,0 +1,48 @@
+<?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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        >
+
+    <ScrollView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_weight="1">
+        <TextView
+                android:id="@+id/byod_instructions"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:padding="10dip"
+                android:text="@string/provisioning_byod_instructions"
+                android:textSize="18dip" />
+    </ScrollView>
+
+    <Button
+        android:id="@+id/byod_start"
+        android:layout_width="204dp"
+        android:layout_height="wrap_content"
+        android:text="@string/provisioning_byod_start" />
+
+    <ListView
+        android:id="@id/android:list"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+
+    <include layout="@layout/pass_fail_buttons" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/layout/provisioning_cross_profile.xml b/apps/CtsVerifier/res/layout/provisioning_cross_profile.xml
new file mode 100644
index 0000000..345e99d
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/provisioning_cross_profile.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:orientation="vertical" >
+    <TextView android:id="@+id/text"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              android:textAppearance="?android:attr/textAppearanceLarge" />
+
+    <Button
+        android:id="@+id/button_finish"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/provisioning_button_finish" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/layout/pta_touch.xml b/apps/CtsVerifier/res/layout/pta_touch.xml
new file mode 100644
index 0000000..8cf6e89
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/pta_touch.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" >
+    <com.android.cts.verifier.projection.touch.TouchPointView
+        android:id="@+id/multi_touch_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/pva_video.xml b/apps/CtsVerifier/res/layout/pva_video.xml
new file mode 100644
index 0000000..a62c833
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/pva_video.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" >
+
+    <VideoView
+        android:id="@+id/video_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/layout/pwa_buttons.xml b/apps/CtsVerifier/res/layout/pwa_buttons.xml
new file mode 100644
index 0000000..fc2d10f
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/pwa_buttons.xml
@@ -0,0 +1,42 @@
+<?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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:gravity="bottom"
+    android:orientation="vertical" >
+
+    <Button
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/pwa_button" />
+
+    <Button
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/pwa_button" />
+
+    <Button
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/pwa_button" />
+
+    <Button
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/pwa_button" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/layout/pwa_widgets.xml b/apps/CtsVerifier/res/layout/pwa_widgets.xml
new file mode 100644
index 0000000..4bfcec6
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/pwa_widgets.xml
@@ -0,0 +1,73 @@
+<?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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" >
+
+     <TextureView
+         android:id="@+id/texture_view"
+         android:layout_width="match_parent"
+         android:layout_height="match_parent" />
+
+     <LinearLayout
+         android:layout_width="fill_parent"
+         android:layout_height="wrap_content"
+         android:orientation="vertical" >
+
+         <LinearLayout
+             android:layout_width="match_parent"
+             android:layout_height="match_parent" >
+
+             <include layout="@layout/pass_fail_buttons" />
+         </LinearLayout>
+
+         <LinearLayout
+             android:layout_width="match_parent"
+             android:layout_height="wrap_content"
+             android:orientation="horizontal" >
+
+             <Button
+                 android:id="@+id/up_button"
+                 android:layout_width="match_parent"
+                 android:layout_height="wrap_content"
+                 android:layout_weight="1"
+                 android:text="@string/pwa_button_up" />
+
+             <Button
+                 android:id="@+id/down_button"
+                 android:layout_width="match_parent"
+                 android:layout_height="wrap_content"
+                 android:layout_weight="1"
+                 android:text="@string/pwa_button_down" />
+
+             <Button
+                 android:id="@+id/left_button"
+                 android:layout_width="match_parent"
+                 android:layout_height="match_parent"
+                 android:layout_weight="1"
+                 android:text="@string/pwa_button_left" />
+
+             <Button
+                 android:id="@+id/right_button"
+                 android:layout_width="match_parent"
+                 android:layout_height="wrap_content"
+                 android:layout_weight="1"
+                 android:text="@string/pwa_button_right" />
+
+         </LinearLayout>
+     </LinearLayout>
+
+</FrameLayout>
diff --git a/apps/CtsVerifier/res/layout/snsr_error.xml b/apps/CtsVerifier/res/layout/snsr_error.xml
new file mode 100644
index 0000000..d78a8fb
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/snsr_error.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingBottom="@dimen/snsr_boxed_padding_bottom"
+        android:paddingTop="@dimen/snsr_boxed_padding_top"
+        android:paddingLeft="@dimen/snsr_boxed_padding_left"
+        android:paddingRight="@dimen/snsr_boxed_padding_right"
+        android:background="@color/snsr_error_background"
+        android:textColor="@color/snsr_error" />
diff --git a/apps/CtsVerifier/res/layout/snsr_information.xml b/apps/CtsVerifier/res/layout/snsr_information.xml
new file mode 100644
index 0000000..e3d9542
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/snsr_information.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingBottom="@dimen/snsr_boxed_padding_bottom"
+        android:paddingTop="@dimen/snsr_boxed_padding_top"
+        android:paddingLeft="@dimen/snsr_boxed_padding_left"
+        android:paddingRight="@dimen/snsr_boxed_padding_right"
+        android:background="@color/snsr_information_background"
+        android:textColor="@color/snsr_information" />
diff --git a/apps/CtsVerifier/res/layout/snsr_instruction.xml b/apps/CtsVerifier/res/layout/snsr_instruction.xml
new file mode 100644
index 0000000..e7369c7
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/snsr_instruction.xml
@@ -0,0 +1,23 @@
+<?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.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:textColor="?android:attr/textColorSecondary"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingBottom="@dimen/snsr_log_padding_bottom"
+        android:paddingTop="@dimen/snsr_log_padding_top"
+        android:paddingLeft="@dimen/snsr_log_padding_left"
+        android:paddingRight="@dimen/snsr_log_padding_right" />
diff --git a/apps/CtsVerifier/res/layout/snsr_message.xml b/apps/CtsVerifier/res/layout/snsr_message.xml
new file mode 100644
index 0000000..cef35ca
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/snsr_message.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:textStyle="italic"
+        android:textColor="?android:attr/textColorTertiary"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingTop="@dimen/snsr_log_padding_top"
+        android:paddingLeft="@dimen/snsr_boxed_padding_left"
+        android:paddingRight="@dimen/snsr_boxed_padding_right"
+        android:paddingBottom="@dimen/snsr_log_padding_bottom" />
diff --git a/apps/CtsVerifier/res/layout/snsr_next_button.xml b/apps/CtsVerifier/res/layout/snsr_next_button.xml
new file mode 100644
index 0000000..e7a6d72
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/snsr_next_button.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:orientation="horizontal"
+        android:gravity="center"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingBottom="@dimen/snsr_view_padding_bottom"
+        android:paddingTop="@dimen/snsr_view_padding_top"
+        >
+
+    <Button android:id="@+id/next_button"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:text="@string/next_button_text"
+            />
+
+    <Button android:id="@+id/pass_button"
+            android:visibility="gone"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:drawableTop="@drawable/fs_good"
+            />
+
+    <Button android:id="@+id/fail_button"
+            android:visibility="gone"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:drawableTop="@drawable/fs_error"
+            />
+
+</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/snsr_semi_auto_test.xml b/apps/CtsVerifier/res/layout/snsr_semi_auto_test.xml
deleted file mode 100644
index 92039f0..0000000
--- a/apps/CtsVerifier/res/layout/snsr_semi_auto_test.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-
-    <TextView android:id="@+id/log_text"
-              android:gravity="bottom"
-              android:layout_height="wrap_content"
-              android:layout_width="wrap_content"
-              android:maxLines="27"
-              android:paddingBottom="5dip"
-              android:paddingLeft="10dip"
-              android:paddingRight="10dip"
-              android:paddingTop="5dip"
-              android:scrollbars="vertical"
-            />
-
-    <Button android:id="@+id/next_button"
-            android:layout_alignParentBottom="true"
-            android:layout_centerInParent="true"
-            android:layout_height="wrap_content"
-            android:layout_marginBottom="20dip"
-            android:layout_width="120dip"
-            android:text="@string/next_button_text"
-            android:textSize="24dip"
-            />
-
-</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/snsr_success.xml b/apps/CtsVerifier/res/layout/snsr_success.xml
new file mode 100644
index 0000000..9d600dc
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/snsr_success.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingBottom="@dimen/snsr_boxed_padding_bottom"
+        android:paddingTop="@dimen/snsr_boxed_padding_top"
+        android:paddingLeft="@dimen/snsr_boxed_padding_left"
+        android:paddingRight="@dimen/snsr_boxed_padding_right"
+        android:background="@color/snsr_success_background"
+        android:textColor="@color/snsr_success" />
diff --git a/apps/CtsVerifier/res/layout/snsr_test_title.xml b/apps/CtsVerifier/res/layout/snsr_test_title.xml
new file mode 100644
index 0000000..374fb54
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/snsr_test_title.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:textStyle="bold"
+        android:textColor="?android:attr/textColorPrimary"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingBottom="@dimen/snsr_boxed_padding_bottom"
+        android:paddingTop="@dimen/snsr_boxed_padding_top"
+        android:paddingLeft="@dimen/snsr_boxed_padding_left"
+        android:paddingRight="@dimen/snsr_boxed_padding_right" />
diff --git a/apps/CtsVerifier/res/layout/snsr_warning.xml b/apps/CtsVerifier/res/layout/snsr_warning.xml
new file mode 100644
index 0000000..5d63fc1
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/snsr_warning.xml
@@ -0,0 +1,24 @@
+<?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.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingBottom="@dimen/snsr_boxed_padding_bottom"
+        android:paddingTop="@dimen/snsr_boxed_padding_top"
+        android:paddingLeft="@dimen/snsr_boxed_padding_left"
+        android:paddingRight="@dimen/snsr_boxed_padding_right"
+        android:background="@color/snsr_warning_background"
+        android:textColor="@color/snsr_warning" />
diff --git a/apps/CtsVerifier/res/raw/test_video.mp4 b/apps/CtsVerifier/res/raw/test_video.mp4
new file mode 100644
index 0000000..ab95ac0
--- /dev/null
+++ b/apps/CtsVerifier/res/raw/test_video.mp4
Binary files differ
diff --git a/apps/CtsVerifier/res/values-television/strings.xml b/apps/CtsVerifier/res/values-television/strings.xml
new file mode 100644
index 0000000..1042fa8
--- /dev/null
+++ b/apps/CtsVerifier/res/values-television/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+<resources>
+    <!-- Don't test these features on televisions. -->
+    <string-array name="disabled_tests">
+        <item>com.android.cts.verifier.notifications.NotificationAttentionManagementVerifierActivity</item>
+        <item>com.android.cts.verifier.notifications.NotificationListenerVerifierActivity</item>
+    </string-array>
+</resources>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/values-watch/strings.xml b/apps/CtsVerifier/res/values-watch/strings.xml
new file mode 100644
index 0000000..1f25b04
--- /dev/null
+++ b/apps/CtsVerifier/res/values-watch/strings.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+<resources>
+    <!-- Don't test these features on watches. -->
+    <string-array name="disabled_tests">
+        <item>com.android.cts.verifier.notifications.NotificationAttentionManagementVerifierActivity</item>
+        <item>com.android.cts.verifier.notifications.NotificationListenerVerifierActivity</item>
+    </string-array>
+</resources>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/values/attrs.xml b/apps/CtsVerifier/res/values/attrs.xml
new file mode 100644
index 0000000..71a1ba6
--- /dev/null
+++ b/apps/CtsVerifier/res/values/attrs.xml
@@ -0,0 +1,26 @@
+<?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
+  -->
+<resources>
+    <declare-styleable name="BoxInsetLayout_Layout">
+        <attr name="layout_box">
+            <flag name="left" value="0x01" />
+            <flag name="top" value="0x02" />
+            <flag name="right" value="0x04" />
+            <flag name="bottom" value="0x08" />
+            <flag name="all" value="0x0F" />
+        </attr>
+    </declare-styleable>
+</resources>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/values/colors.xml b/apps/CtsVerifier/res/values/colors.xml
new file mode 100644
index 0000000..c855d5f
--- /dev/null
+++ b/apps/CtsVerifier/res/values/colors.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="red">#F00</color>
+    <color name="green">#0F0</color>
+
+    <!-- Sensor tests log colors -->
+    <color name="snsr_error_background">#F5D1D1</color>
+    <color name="snsr_error">#AA0404</color>
+    <color name="snsr_success_background">#DDF6D2</color>
+    <color name="snsr_success">#467701</color>
+    <color name="snsr_warning_background">#F0E4B6</color>
+    <color name="snsr_warning">#75540C</color>
+    <color name="snsr_information_background">#D0D2F6</color>
+    <color name="snsr_information">#41576B</color>
+</resources>
diff --git a/apps/CtsVerifier/res/values/dimens.xml b/apps/CtsVerifier/res/values/dimens.xml
index 00257a9..8df5b35 100644
--- a/apps/CtsVerifier/res/values/dimens.xml
+++ b/apps/CtsVerifier/res/values/dimens.xml
@@ -18,4 +18,24 @@
     <dimen name="widget_margin_bottom">8dp</dimen>
     <dimen name="widget_margin_left">8dp</dimen>
     <dimen name="widget_margin_right">8dp</dimen>
+
+    <!-- Sensor logging values -->
+
+    <dimen name="snsr_boxed_padding_top">15dp</dimen>
+    <dimen name="snsr_boxed_padding_bottom">15dp</dimen>
+    <dimen name="snsr_boxed_padding_left">15dp</dimen>
+    <dimen name="snsr_boxed_padding_right">15dp</dimen>
+
+    <dimen name="snsr_log_padding_top">1dp</dimen>
+    <dimen name="snsr_log_padding_bottom">1dp</dimen>
+    <dimen name="snsr_log_padding_left">8dp</dimen>
+    <dimen name="snsr_log_padding_right">8dp</dimen>
+
+    <dimen name="snsr_view_padding_top">8dp</dimen>
+    <dimen name="snsr_view_padding_bottom">8dp</dimen>
+    <dimen name="snsr_view_padding_left">8dp</dimen>
+    <dimen name="snsr_view_padding_right">8dp</dimen>
+
+    <dimen name="js_padding">10dp</dimen>
+
 </resources>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index d93649e..3225bcf 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -35,6 +35,7 @@
     <string name="test_category_streaming">Streaming</string>
     <string name="test_category_features">Features</string>
     <string name="test_category_deskclock">Clock</string>
+    <string name="test_category_jobscheduler">Job Scheduler</string>
     <string name="test_category_other">Other</string>
     <string name="clear">Clear</string>
     <string name="test_results_cleared">Test results cleared.</string>
@@ -66,7 +67,10 @@
         \n\nFollow the instructions below to check that the data backup and restore works:
         \n\n1. Make sure backup and automatic restore are enabled in settings. Depending on the
         backup transport supported by the device you may need to do additional steps. For instance
-        you may need to set a Google account as the backup account for the device.
+        you may need to set a Google account as the backup account for the device. If you cannot
+        find the corresponding setting options on your device, run \"adb shell bmgr enable true\"
+        to enable the backup manager. You can check its status by executing \"adb shell bmgr
+        enabled\".
         \n\n2. Run the backup manager: adb shell bmgr run
         \n\n3. Uninstall the program: adb uninstall com.android.cts.verifier
         \n\n4. Reinstall the CTS Verifier and verify that the values are still the same.
@@ -227,6 +231,42 @@
     <string name="ble_server_reliable_write">Waiting on reliable write from client</string>
     <string name="ble_server_receiving_disconnect">Waiting on disconnection from BLE client</string>
 
+    <!-- BLE advertiser side strings -->
+    <string name="ble_advertiser_test_name">BLE Advertiser Test</string>
+    <string name="ble_advertiser_test_info">The BLE test must be done simultaneously on two devices, an advertiser and a scanner. This device is the advertiser.</string>
+    <string name="ble_advertiser_service_name">Bluetooth LE Advertiser Handler Service</string>
+    <string name="ble_privacy_mac_name">BLE Privacy Mac</string>
+    <string name="ble_privacy_mac_info">BLE Advertiser should advertise in non-repeating MAC address.</string>
+    <string name="ble_advertiser_privacy_mac_instruction">Click start to start advertising, you can disconnect USB and lock the screen of advertiser. Counts and mac address will show on scanner. You may receive message that this device does not support BLE advertising.</string>
+    <string name="ble_power_level_name">BLE Tx Power Level</string>
+    <string name="ble_power_level_info">BLE Advertiser advertises in 4 different power levels. Scanner should receive them in different strength of Rssi, cannot receive weak signals beyond several feet.</string>
+    <string name="ble_advertiser_power_level_instruction">Click start to start multi-advertising. Data packets are advertised in 4 different power levels. You may receive message that this device does not support multi advertising. If advertiser does not advertise in 4 power levels, neither you receive the error message, you may not stop the advertising in previous test, or this device does not support 4 advertisers at the same time. Try rebooting the device and run the test to free those advertisers in use.</string>
+    <string name="ble_advertiser_scan_filter_name">BLE Hardware Scan Filter</string>
+    <string name="ble_advertiser_scan_filter_info">BLE Advertiser advertises with 2 different data separately. One can wake up the scanner, the other cannot. This test cares about behavior on scanner only.</string>
+    <string name="ble_advertiser_scannable">Scannable advertising</string>
+    <string name="ble_advertiser_scannable_instruction">Start scannable advertising, expect scanner consume more power on Monsoon monitor, or see log of GattService from scanner logcat.</string>
+    <string name="ble_advertiser_unscannable">Unscannble advertising</string>
+    <string name="ble_advertiser_unscannable_instruction">Start unscannable advertising, expect scanner stay calm on Monsoon monitor, no log of GattService from scanner logcat.</string>
+    <string name="ble_advertiser_start">Start</string>
+    <string name="ble_advertiser_stop">Stop</string>
+
+    <!-- BLE scanner side strings -->
+    <string name="ble_scanner_test_name">BLE Scanner Test</string>
+    <string name="ble_scanner_service_name">Bluetooth LE Scanner Handler Service</string>
+    <string name="ble_scanner_test_info">The BLE test must be done simultaneously on two devices, an advertiser and a scanner. This device is the scanner.</string>
+    <string name="ble_scanner_privacy_mac">Hold for 15 min to see if receive a different MAC address from advertiser.</string>
+    <string name="ble_scanner_privacy_mac_instruction">Mac address, counts are shown on screen. It should continuously receive data packet from advertiser. Every 15 min, a new mac address should show up, which prevents mac address disclosure.</string>
+    <string name="ble_ultra_low">Ultra low</string>
+    <string name="ble_low">Low</string>
+    <string name="ble_medium">Medium</string>
+    <string name="ble_high">High</string>
+    <string name="ble_scanner_power_level_instruction">Count: Ultra low &lt; low &lt; medium &lt; high\nRssi: Ultra low &lt; low &lt; medium &lt; high\nDistance to see count freezing: Ultra low &lt; low &lt; medium &lt; high\nA common error is ultra low, low and medium behave similarly, with similar rssi, freeze at similar distance.\n\n All power level receive a different mac address. After 15 mins, a green text "Get a new Mac address" will show up.</string>
+    <string name="ble_scanner_scan_filter_name">BLE Hardware Scan Filter</string>
+    <string name="ble_scanner_scan_filter_info">Lock the screen of scanner, and connect to monsoon. It will not wake up when advertiser is advertising unscannable, and scanner is scanning with filter.</string>
+    <string name="ble_scanner_scan_filter_instruction">Scan filter is to scan data with service UUID = 0x6666 only. If you scan without scan filter, data with service UUID = 0x5555 and 0x6666 will show up on screen.\nFor monsoon test:\n\tClick scan with filter, lock the screen, connect to monsoon. It will not wake up when advertiser is advertising unscannable data packets, but will show a peak in power usage when advertiser is advertising scannable data.\nFor logcat test:\n\tClick scan with filter, logcat the scanner. No data will be received by GattService when advertiser is advertising unscannable data.</string>
+    <string name="ble_scan_with_filter">Scan with filter</string>
+    <string name="ble_scan_without_filter">Scan without filter</string>
+
     <!-- Strings for FeatureSummaryActivity -->
     <string name="feature_summary">Hardware/Software Feature Summary</string>
     <string name="feature_summary_info">This is a test for...</string>
@@ -367,6 +407,14 @@
     <string name="nfc_hce_conflicting_non_payment_emulator">Two conflicting non-payment services (Emulator)</string>
     <string name="nfc_hce_conflicting_non_payment_reader">Two conflicting non-payment services (Reader)</string>
 
+    <string name="nfc_hce_foreground_non_payment_emulator">Foreground override non-payment services (Emulator)</string>
+    <string name="nfc_hce_foreground_non_payment_reader">Foreground override non-payment services (Reader)</string>
+    <string name="nfc_hce_foreground_non_payment_help">This test enables two non-payment services with conflicting AIDs. It then uses Androids API to allow the foreground app to set a preference for a specific service. This should prevent a popup dialog from showing. If you see a popup dialog during this asking you to select an app, this test has failed.</string>
+
+    <string name="nfc_hce_foreground_payment_emulator">Foreground override payment services (Emulator)</string>
+    <string name="nfc_hce_foreground_payment_reader">Foreground override payment services (Reader)</string>
+    <string name="nfc_hce_foreground_payment_help">This test enables two payment services, and asks you to set one as the default service. It then uses Androids API to allow the foreground app to set a preference for the non-default service. This will cause the non-default payment service to be invoked.</string>
+    <string name="nfc_hce_change_favor_foreground">This test requires the "Favor foreground app" setting to be enabled. Tap OK to go to Tap and Pay settings and check the Favor foreground app option</string>
     <string name="nfc_hce_offhost_service_emulator">Off-host service (Emulator)</string>
     <string name="nfc_hce_offhost_service_reader">Off-host service (Reader)</string>
     <string name="nfc_hce_offhost_emulator_help">This tests enables a service that declares some AIDs to reside off-host. This test only needs to be passed if your device has a secure element (either embedded or UICC.). The responses from the secure element are not verified by the test - it is up to the tester to verify the responses are as expected.</string>
@@ -381,12 +429,33 @@
     <string name="nfc_hce_throughput_emulator">HCE throughput test (Emulator)</string>
     <string name="nfc_hce_throughput_reader">HCE throughput test (Reader)</string>
     <string name="nfc_hce_throughput_emulator_help">This tests verifies that your HCE implementation can reach a decent throughput. While Android does not have any requirements on HCE performance, many HCE applications such as transport and payment apps do. If the average APDU roundtrip time is more than 50ms, please take a look at your implementation to see where the delay is coming from.</string>
-    <string name="nfc_hce_change_preinstalled_wallet">The device has an installed payment application that is currently set as default. To complete the test, you will be asked whether you want to make Payment Service #1 or #2 the default app. Select yes.</string>
+    <string name="nfc_hce_change_preinstalled_wallet">The device has an installed payment application that is currently set as default. To complete the test, you will be asked whether you want to make another app the default app. Select yes.</string>
     <string name="nfc_hce_change_default_help">You will now be asked whether you want to make Payment Service #1 the default app. Select yes.</string>
     <string name="nfc_hce_conflicting_non_payment_help">When tapping the first time, you will be shown a dialog that asks you to choose between TransportService #1 and TransportService #2. Select TransportService #2. Verify a dialog is shown that asks you to tap again to complete. Now tap again, and if communication with TransportService #2 is successfull the pass button will be enabled."</string>
+
+    <string name="nfc_hce_payment_dynamic_aids_emulator">Dynamic payment AIDs (Emulator)</string>
+    <string name="nfc_hce_payment_dynamic_aids_reader">Dynamic payment AIDs (Reader)</string>
+    <string name="nfc_hce_payment_dynamic_aids_help">This test tries to register dynamic AIDs for a payment service.</string>
+
+    <string name="nfc_hce_payment_prefix_aids_emulator">Payment prefix AIDs (Emulator)</string>
+    <string name="nfc_hce_payment_prefix_aids_reader">Payment prefix AIDs (Reader)</string>
+    <string name="nfc_hce_payment_prefix_aids_help">This test statically registers prefix AIDs for a payment service.</string>
+
+    <string name="nfc_hce_payment_prefix_aids_emulator_2">Payment prefix AIDs 2 (Emulator)</string>
+    <string name="nfc_hce_payment_prefix_aids_reader_2">Payment prefix AIDs 2 (Reader)</string>
+
+    <string name="nfc_hce_other_prefix_aids_emulator">Other prefix AIDs (Emulator)</string>
+    <string name="nfc_hce_other_prefix_aids_reader">Other prefix AIDs (Reader)</string>
+    <string name="nfc_hce_other_prefix_aids_help">This test dynamically registers prefix AIDs for a non-payment service.</string>
+
+    <string name="nfc_hce_other_conflicting_prefix_aids_emulator">Conflicting non-payment prefix AIDs (Emulator)</string>
+    <string name="nfc_hce_other_conflicting_prefix_aids_reader">Conflicting non-payment prefix AIDs (Reader)</string>
+    <string name="nfc_hce_other_conflicting_prefix_aids_help">This test registers conflicting prefix AIDs and makes sure AID conflict detection with prefix AIDs works properly. When tapping the first time, you will be shown a dialog that asks you to choose between TransportService #1 and TransportService #2. Select TransportService #2. Verify a dialog is shown that asks you to tap again to complete. Now tap again, and if communication with TransportService #2 is successfull the pass button will be enabled."</string>
+
     <string name="nfc_payment_service_desc">NFC Payment service</string>
     <string name="ppse">PPSE</string>
     <string name="mastercard">MasterCard</string>
+    <string name="visa">Visa</string>
     <string name="paymentService1">Payment Service #1</string>
     <string name="paymentService2">Payment Service #2</string>
     <string name="transportService1">TransportService #1</string>
@@ -395,10 +464,58 @@
     <string name="offhostService">OffhostService</string>
 
     <!-- Strings for Sensor Test Activities -->
+    <string name="snsr_device_admin_receiver">Sensor Tests Device Admin Receiver</string>
+    <string name="snsr_test_summary">Tests passed: %1$d, Tests skipped: %2$d, Tests failed: %3$d</string>
+    <string name="snsr_test_complete">Test completed without errors.</string>
+    <string name="snsr_test_complete_with_errors">Test completed with errors: those errors
+        might degrade the user experience and might cause some applications to misbehave. They are
+        not required for Android Compatibility at this time, but will in a future release.</string>
+    <string name="snsr_test_pass">PASS</string>
+    <string name="snsr_test_skipped">SKIPPED</string>
+    <string name="snsr_test_fail">FAIL</string>
+    <string name="snsr_execution_time">Test execution time %1$s sec</string>
+
+    <!-- Strings to interact with users in Sensor Tests -->
+    <string name="snsr_test_play_sound">A sound will be played once the verification is complete...</string>
+    <string name="snsr_no_interaction">Leave the device on top of a flat surface.</string>
+    <string name="snsr_interaction_needed">Once the test begins, you will have to wave your hand over the front of the device.</string>
+    <string name="snsr_device_steady">Keep the device steady.</string>
+    <string name="snsr_keep_device_rotating_clockwise">Once the test begins, you will have to keep rotating the device clockwise.</string>
+    <string name="snsr_wait_for_user">Press \'Next\' to continue.</string>
+    <string name="snsr_wait_to_begin">Press \'Next\' to begin.</string>
+    <string name="snsr_on_complete_return">After completing the task, go back to this test.</string>
+    <string name="snsr_movement_expected">Movement was expected during the test. Found=%1$b.</string>
+    <string name="snsr_sensor_feature_deactivation">Turn off any special features installed in the
+        device that register for sensors. Once you are done, you can begin the test.</string>
+    <string name="snsr_setting_mode_request">You will be redirected to set \'%1$s\' to: %2$s.</string>
+    <string name="snsr_setting_mode_set">\'%1$s\' set to: %2$s.</string>
+    <string name="snsr_setting_mode_not_set">\'%1$s\' not set to: %2$s.</string>
+    <string name="snsr_setting_airplane_mode">Airplane mode</string>
+    <string name="snsr_setting_screen_brightness_mode">Adaptive Brightness</string>
+    <string name="snsr_setting_auto_rotate_screen_mode">Auto-rotate screen</string>
+    <string name="snsr_setting_keep_screen_on">Stay awake</string>
+    <string name="snsr_setting_location_mode">Location</string>
+    <string name="snsr_setting_ambient_display">Ambient Display</string>
+    <string name="snsr_pass_on_error">Pass Anyway</string>
+    <string name="snsr_run_automated_tests">The screen will be turned off to execute the tests,
+        when tests complete, the device will vibrate and the screen will be turned back on.</string>
+
     <!-- Accelerometer -->
     <string name="snsr_accel_test">Accelerometer Test</string>
     <string name="snsr_accel_test_info">This test verifies that the accelerometer is working properly. As you move the device around through space, the triangle should always point down (i.e. in the direction of gravity.) If it does not, the accelerometer is improperly configured.</string>
     <string name="snsr_accel_m_test">Accelerometer Measurement Tests</string>
+    <string name="snsr_accel_test_face_up">Place the device on a flat surface with the screen
+        facing the ceiling.</string>
+    <string name="snsr_accel_test_face_down">Place the device on a flat surface with the screen
+        facing it.</string>
+    <string name="snsr_accel_test_right_side">Place the device in a flat surface resting vertically
+        on its right side.</string>
+    <string name="snsr_accel_test_left_side">Place the device in a flat surface resting vertically
+        on its left side.</string>
+    <string name="snsr_accel_test_top_side">Place the device in a flat surface resting vertically
+        on its top side.</string>
+    <string name="snsr_accel_test_bottom_side">Place the device in a flat surface resting vertically
+        on its bottom side.</string>
 
     <!-- Gyroscope -->
     <string name="snsr_gyro_test">Gyroscope Test</string>
@@ -409,6 +526,13 @@
     <string name="snsr_gyro_test_degrees_title">Wrong units?</string>
     <string name="snsr_gyro_test_degrees_message">These values looks like degrees per second. These should be radians per second!</string>
     <string name="snsr_gyro_m_test">Gyroscope Measurement Test</string>
+    <string name="snsr_gyro_device_placement">Place the device in a flat surface with the screen
+        facing the ceiling. Read the instructions for each scenario, before you perform the
+        test.</string>
+    <string name="snsr_gyro_device_static">Leave the device static.</string>
+    <string name="snsr_gyro_rotate_device">Once you begin the test, you will need to rotate the
+        device 360deg (one time) in the direction show by the animation, then place it back on the
+        flat surface.</string>
 
     <!-- Heart Rate -->
     <string name="snsr_heartrate_test">Heart Rate Test</string>
@@ -418,6 +542,62 @@
 
     <!-- Magnetic Field -->
     <string name="snsr_mag_m_test">Magnetic Field Measurement Tests</string>
+    <string name="snsr_mag_verify_norm">Verifying the Norm...</string>
+    <string name="snsr_mag_verify_std_dev">Verifying the Standard Deviation...</string>
+    <string name="snsr_mag_verify_calibrated_uncalibrated">Verifying the relationship between
+        calibrated and uncalibrated measurements...</string>
+    <string name="snsr_mag_calibration_description">Please calibrate the Magnetometer by moving
+        it in 8 shapes in different orientations.</string>
+    <string name="snsr_mag_calibration_complete">When done, leave the device in a flat surface, far
+        from all metallic objects (if the test does not pass, try re-running it outdoors).</string>
+    <string name="snsr_mag_measurement">-&gt; (%1$.2f, %2$.2f, %3$.2f) : %4$.2f uT</string>
+
+    <!-- Sensor Value Accuracy -->
+    <string name="snsr_rot_vec_test">Rotation Vector Accuracy Test</string>
+    <string name="snsr_event_length">Sensor(%3$s). Event values expected to have size=%1$d. Found=%2$d.</string>
+    <string name="snsr_event_value">Sensor(%3$s). Event value[0] expected to be of value=%1$f. Found=%2$f.</string>
+    <string name="snsr_event_time">Sensor(%5$s). Event timestamp expected to be synchronized with SystemClock.elapsedRealtimeNanos(). Event received at=%1$d. Event timestamp=%2$d. Delta=%3$d. Threshold=%4$d.</string>
+
+    <!-- Sensor Batching -->
+    <string name="snsr_batch_test">Sensor Batching Tests</string>
+    <string name="snsr_batching_walking_needed">Once the test begins, you will have to take the
+        device in your hand and walk.</string>
+
+    <!-- Sensor Synchronization -->
+    <string name="snsr_synch_test">Sensor Synchronization Test</string>
+
+    <!-- Step Counter and Detector -->
+    <string name="snsr_step_counter_test">Step Counter and Detector Tests</string>
+    <string name="snsr_step_counter_test_walking">Once the test begins, you will need to walk, and tap on the screen with each step you take.</string>
+    <string name="snsr_step_counter_test_still">Once the test begins, you will need to remain still and hold the device still in your hand.</string>
+    <string name="snsr_step_counter_expected_steps">At least %1$d steps are expected to be reported. Reported=%2$d.</string>
+    <string name="snsr_step_counter_detected_reported">Steps reported by user=%1$d. Steps counted=%2$d. Delta=%3$d. Tolerance=%4$d.</string>
+    <string name="snsr_step_detector_detected_reported">Steps reported by user=%1$d. Steps detected=%2$d. Delta=%3$d. Tolerance=%4$d.</string>
+    <string name="snsr_step_counter_event_changed">Step counter expected to increase monotonically, with a delta > 0. Found=%1$d. Timestamp=%2$d.</string>
+    <string name="snsr_step_reported">%1$d | User reported step.</string>
+    <string name="snsr_step_counter_event">%1$d | Step Counter event. count=%2$d.</string>
+    <string name="snsr_step_detector_event">%1$d | Step Detector event.</string>
+
+    <!-- Significant Motion -->
+    <string name="snsr_significant_motion_test">Significant Motion Tests</string>
+    <string name="snsr_significant_motion_event_arrival">Event expected to trigger. Triggered=%1$s.</string>
+    <string name="snsr_significant_motion_event_type">Event expected to be of type=%1$d. Found=%2$d.</string>
+    <string name="snsr_significant_motion_event_unexpected">Event not expected to trigger. Triggered=%1$s.</string>
+    <string name="snsr_significant_motion_disable_info">Significant Motion is expected to disable itself after it triggers once.</string>
+    <string name="snsr_significant_motion_test_trigger">Once you begin the test, you will need to walk for Significant Motion to be detected.</string>
+    <string name="snsr_significant_motion_test_cancel">Once you begin the test, you will need to walk to ensure Significant Motion is not reported after trigger canceled.</string>
+    <string name="snsr_significant_motion_test_vibration">Leave the device in a level surface. Once you begin the test, the device will vibrate to ensure that Significant Motion is not triggered.</string>
+    <string name="snsr_significant_motion_test_in_hand">Once you begin the test, hold the device in your hand while you perform natural hand movements.</string>
+    <string name="snsr_significant_motion_test_sitting">Once you begin the test, keep the device in your pocket and move naturally while sitting in a chair.</string>
+    <string name="snsr_significant_motion_test_deactivation">Once you begin the test, you will need to walk to ensure Significant Motion triggers only once.</string>
+    <string name="snsr_significant_motion_registration">Expected to be able to register for TriggerSensor. Found=%1$b.</string>
+    <string name="snsr_significant_motion_cancelation">Expected to be able to cancel TriggerSensor. Found=%b.</string>
+
+    <!-- Strings for Sensor CTS tests inside CtsVerifier -->
+    <string name="snsr_single_sensor_tests">CTS Single Sensor Tests</string>
+    <string name="snsr_sensor_integration_tests">CTS Sensor Integration Tests</string>
+    <string name="snsr_sensor_test">CTS Sensor Test</string>
+    <string name="snsr_sensor_batching_tests">CTS Sensor Batching Tests</string>
 
     <!-- Strings for Sample Test Activities -->
     <string name="share_button_text">Share</string>
@@ -567,6 +747,7 @@
 
     <!-- Strings for USB accessory test activity -->
     <string name="usb_accessory_test">USB Accessory Test</string>
+    <string name="sensor_power_test">Sensor Power Test</string>
     <string name="usb_accessory_test_info">
         1. Connect your Android device to a computer and run the \'cts-usb-accessory\' program
         included with the CTS Verifier bundle.
@@ -760,10 +941,35 @@
         itself according to the current rotation of the device.</string>
 
     <string name="test_category_notifications">Notifications</string>
+    <string name="attention_test">Notification Attention Management Test</string>
+    <string name="attention_info">This test checks that the NotificationManagerService is
+        respecting user preferences about notification ranking and filtering.
+    </string>
+    <string name="attention_ready">I\'m done</string>
+    <string name="attention_filter_all">Please set the notification filter to \"All\" in the dialog
+        that appears when you change the device\'s volume.</string>
+    <string name="attention_filter_priority">Please set the notification filter to \"Priority\" in
+        the dialog that appears when you change the device\'s volume, and allow messages from
+        starred contacts.</string>
+    <string name="attention_filter_none">Please set the notification filter to \"None\" in the dialog
+        that appears when you change the device\'s volume.</string>
+    <string name="attention_create_contacts">Create contacts for notification annotations.</string>
+    <string name="attention_delete_contacts">Delete test contacts.</string>
+    <string name="attention_default_order">Check that ranker defaults to time order.</string>
+    <string name="attention_priority_order">Check that ranker respects developers priorities.</string>
+    <string name="attention_ambient_bit">Check that the ambient bit is set appropriately.</string>
+    <string name="attention_lookup_order">Check that ranker respects Lookup URIs for contacts.</string>
+    <string name="attention_email_order">Check that ranker respects mailto URIs for contacts.</string>
+    <string name="attention_phone_order">Check that ranker respects telephone URIs for contacts.</string>
+    <string name="attention_interruption_order">Check that ranker temporarily boosts interruptions.
+    This test takes 15 seconds to complete.</string>
+    <string name="attention_none_are_filtered">Check that \"All\" mode doesn\'t filter any notifications.</string>
+    <string name="attention_some_are_filtered">Check that \"Priority\" mode doesn\'t filter priority notifications.</string>
+    <string name="attention_all_are_filtered">Check that \"None\" mode filters all notifications.</string>
     <string name="nls_test">Notification Listener Test</string>
     <string name="nls_service_name">Notification Listener for CTS Verifier</string>
     <string name="nls_info">This test checks that a NotificationListenerService can be enabled
-        and disabled, and that once enabled the service is able to receive notificaitons and
+        and disabled, and that once enabled the service is able to receive notifications and
         dismiss them.
     </string>
     <string name="nls_enable_service">Please enable \"Notification Listener for CTS Verifier\"
@@ -932,7 +1138,6 @@
         2. Verify that a timer is started  and the timers UI is shown with a timer named "Start Timer Test".\n
         3. Verify that the timer rings after 30 seconds.\n
     </string>
-    
     <!-- Strings for LockConfirmBypassTest -->
     <string name="lock_confirm_test_title">Keyguard Password Verification</string>
     <string name="lock_set_button_text">Set password</string>
@@ -943,4 +1148,153 @@
         \nThen click the \"Change password\" button to change it. You should be prompted for the current password first. If you are not, then mark the test as failed.
     </string>
 
+    <!-- String for Projection Tests -->
+    <string name="test_category_projection">Projection Tests</string>
+    <string name="projection_service_name">Projection Service</string>
+    <string name="pca_info">This tests whether or not OpenGL projection works.\n
+        You should see two "tumbling cubes." Tapping the screen should case the cubes to explode.</string>
+    <string name="pca_test">Projection Cube Test</string>
+    <string name="pwa_info">This tests whether or displaying widets and keyfocus navigation works.\n
+        You should see four buttons on the bottom of the screen.\n
+        Pressing the "up" and "down" buttons should highlight different buttons.\n
+        Further, you should also be able to touch them and they should highlight as usual.</string>
+    <string name="pwa_test">Projection Widget Test</string>
+    <string name="pwa_button_up">Up</string>
+    <string name="pwa_button_down">Down</string>
+    <string name="pwa_button_left">Left</string>
+    <string name="pwa_button_right">Right</string>
+    <string name="pwa_button">Button</string>
+    <string name="pla_test">Projection Scrolling List Test</string>
+    <string name="pla_info">This tests whether a projected list view will scroll properly\n
+        You should see 50 list items and be able to scroll up and down the list</string>
+    <string name="pva_test">Projection Video Playback Test</string>
+    <string name="pva_info">This tests whether video playback works when projected.\n
+        You should see a blinking white box and here a beep that is synchronized with each blink</string>
+    <string name="pta_test">Projection Multitouch Test</string>
+    <string name="pta_info">This tests whether multitouch works.\n
+        Touching the screen should render a dot at the location you touched.\n
+        Touching with additional fingers will render additoinal dots and you should be able to drag them around.</string>
+    <string name="poa_test">Projection Offscreen Activity</string>
+    <string name="poa_info">This tests whether a virtual display will continue to respond to and render even when the screen is off.\n
+        Simply follow the instructions and the test will detect the pass conditions.\n
+        Note that turning on the screen too early will result in a failure.</string>
+
+    <!-- Strings for RotationVectorTest and GameRotationVectorTest -->
+    <string name="rotation_vector_test">Rotation Vector Accuracy Test</string>
+    <string name="snsr_rotation_vector_set_reference">
+        Place the mobile device in a reference position. Note: to provide an accurate reference,
+        align the device along one edge of a notebook laying on a table.</string>
+    <string name="snsr_rotation_vector_reference_set">Reference position set.</string>
+    <string name="snsr_rotation_vector_move_info">Move, shake, and rotate the device.</string>
+    <string name="snsr_rotation_vector_set_final">Place the device back to the reference position.</string>
+    <string name="snsr_rotation_vector_verification">Angular deviation [%1$4.1f %2$4.1f %3$4.1f]. Current: %4$f deg. Max tolerated: %5$f.</string>
+
+    <!-- Strings for BYOD managed provisioning tests (ByodFlowTestActivity) -->
+    <string name="test_category_managed_provisioning">Managed Provisioning</string>
+    <string name="provisioning_byod_device_admin">CTS Verifier - BYOD Admin</string>
+    <string name="provisioning_byod">BYOD Managed Provisioning</string>
+    <string name="provisioning_byod_info">
+        This test exercises the BYOD managed provisioning flow.
+        Start by pressing the button on screen and follow instructions to finish the managed provisioning process.
+        If your device has not been encrypted before, it will be encrypted and rebooted.
+        After the provisioning process completes, return to this page and carry out further verifications.
+    </string>
+    <string name="provisioning_byod_start">Start BYOD provisioning flow</string>
+    <string name="provisioning_byod_instructions">
+        1. Press the button below to start the managed provisioning flow.
+        If your device has not been encrypted before, it will reboot to apply encryption.
+        After reboot follow instructions in the notification area to complete the provisioning.\n
+        2. After successful provisioning, you should be automatically redirected back to this page.
+        Please press through the following verification steps.
+        Allow a few seconds after returning from provisioning, as the profile owner test should automatically pass.
+    </string>
+    <string name="provisioning_byod_profileowner">Profile owner installed</string>
+    <string name="provisioning_byod_diskencryption">Full disk encryption enabled</string>
+    <string name="provisioning_byod_profile_visible">Work profile visible in Settings</string>
+    <string name="provisioning_byod_admin_visible">Device administrator visible in Settings</string>
+    <string name="provisioning_byod_workapps_visible">Badged work apps visible in Launcher</string>
+    <string name="provisioning_byod_cross_profile">Open app cross profiles</string>
+    <string name="provisioning_byod_cross_profile_app_personal">
+        You selected the CTS Verifier option.
+    </string>
+    <string name="provisioning_byod_cross_profile_app_work">You selected the Work option.</string>
+    <string name="provisioning_byod_cross_profile_instruction">
+        Please press the Go button to start an action.\n
+        \n
+        You should be asked to choose either \"CTS Verifier\" or \"Work\" to complete the action.
+        Pressing either should bring up a page stating your choice.\n
+        \n
+        Verify that you are prompted with the above choices and both options work as intended. Then mark this test accordingly.
+    </string>
+    <string name="provisioning_byod_profile_visible_instruction">
+        Please press the Go button to open the Settings page.
+        Navigate to Accounts and confirm that:\n
+        \n
+        - Both Personal and Work categories exist.\n
+        - \"Remove work profile\" exists under the Work category.\n
+        \n
+        Use the Back button to return to this page.
+    </string>
+    <string name="provisioning_byod_admin_visible_instruction">
+        Please press the Go button to open the Security page in Settings.
+        Navigate to Device administrators and confirm that:\n
+        \n
+        - Both Personal and Work categories exist.\n
+        - \"CTS Verifier - BYOD Admin\" exists under the Work category, and is activated.\n
+        \n
+        Use the Back button to return to this page.
+    </string>
+    <string name="provisioning_byod_workapps_visible_instruction">
+        Please press the Go button to start the launcher.
+        Go to All Apps screen and scroll through it to confirm that:\n
+        \n
+        - A new set of work apps including CTS Verifier appear in the list.\n
+        - Work badge overlay appears on work app\'s icon.\n
+        \n
+        Then navigate back to this screen using Recents button.
+    </string>
+    <string name="provisioning_byod_no_activity">Cannot communicate with activity in the work profile.</string>
+    <string name="provisioning_byod_delete_profile">Initiate deletion of work profile.</string>
+    <string name="provisioning_byod_profile_deleted">Work profile deleted.</string>
+    <string name="provisioning_byod_disabled">Device provisioning is not enabled.</string>
+    <string name="provisioning_byod_go">Go</string>
+    <string name="provisioning_button_finish">Finish</string>
+    <string name="provisioning_cross_profile_chooser">Choose an app to complete action</string>
+
+    <!-- Strings for DeviceOwnerProvisioningTest -->
+    <string name="provisioning_device_owner">Device Owner Provisioning</string>
+    <string name="device_owner_provisioning_tests">Device Owner provisioning tests</string>
+    <string name="device_owner_provisioning_tests_info">The device owner provisioning tests verify that setting up a corporate owned device can only be done on a factory reset device.</string>
+    <string name="device_owner_provisioning_category">Device Owner Provisioning</string>
+    <string name="device_owner_negative_test">Device owner negative test</string>
+    <string name="device_owner_negative_test_info">Please click the "Start provisioning" button, and when you see a warning dialog telling the device is already set up, select "pass". Otherwise, select "fail".</string>
+    <string name="start_device_owner_provisioning_button">Start provisioning</string>
+
+    <!-- Strings for JobScheduler Tests -->
+    <string name="js_test_description">This test is mostly automated, but requires some user interaction. You can pass this test once the list items below are checked.</string>
+
+    <string name="js_idle_test">Idle Mode Constraints</string>
+    <string name="js_start_test_text">Start test</string>
+    <string name="js_idle_instructions">Verify the behaviour of the JobScheduler API for when the device is in idle mode. Simply follow the on-screen instructions.</string>
+    <string name="js_idle_description_1">Turn the screen off and then back on in order to begin.</string>
+    <string name="js_idle_item_idle_off">Idle job does not execute when device is not idle.</string>
+    <string name="js_idle_item_idle_on">Idle job does execute when device is forced into idle.</string>
+
+    <string name="js_charging_test">Charging Constraints</string>
+    <string name="js_charging_instructions">Verify the behaviour of the JobScheduler API for when the device is on power and unplugged from power. Simply follow the on-screen instructions.</string>
+    <string name="js_charging_description_1">Unplug the phone in order to begin.</string>
+    <string name="js_charging_off_test">Device not charging will not execute a job with a charging constraint.</string>
+    <string name="js_charging_on_test">Device when charging will execute a job with a charging constraint.</string>
+    <string name="js_charging_description_2">After the above test has passed, plug the device back in to continue. If the above failed, you can simply fail this test.</string>
+
+    <string name="js_connectivity_test">Connectivity Constraints</string>
+    <string name="js_connectivity_instructions">Verify the behaviour of the JobScheduler API for when the device has no access to data connectivity. Simply follow the on-screen instructions.</string>
+    <string name="js_connectivity_description_1">Disable WiFi and Cellular data to begin.</string>
+    <string name="js_unmetered_connectivity_test">Device with no connectivity will not execute a job with an unmetered connectivity constraint.</string>
+    <string name="js_any_connectivity_test">Device with no connectivity will not execute a job with an unmetered connectivity constraint.</string>
+    <string name="js_no_connectivity_test">Device with no connectivity will still execute a job with no connectivity constraints.</string>
+
+    <!-- A list of fully-qualified test classes that should not be run. -->
+    <string-array name="disabled_tests" />
+
 </resources>
diff --git a/apps/CtsVerifier/res/xml/access_prefix_aid_list.xml b/apps/CtsVerifier/res/xml/access_prefix_aid_list.xml
new file mode 100644
index 0000000..915c041
--- /dev/null
+++ b/apps/CtsVerifier/res/xml/access_prefix_aid_list.xml
@@ -0,0 +1,3 @@
+<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
+    android:description="@string/accessService">
+</host-apdu-service>
diff --git a/apps/CtsVerifier/res/xml/device_admin_byod.xml b/apps/CtsVerifier/res/xml/device_admin_byod.xml
new file mode 100644
index 0000000..0408ce2
--- /dev/null
+++ b/apps/CtsVerifier/res/xml/device_admin_byod.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<!-- BEGIN_INCLUDE(meta_data) -->
+<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
+    <uses-policies>
+        <encrypted-storage />
+        <wipe-data />
+    </uses-policies>
+</device-admin>
+<!-- END_INCLUDE(meta_data) -->
diff --git a/apps/CtsVerifier/res/xml/empty_aid_list.xml b/apps/CtsVerifier/res/xml/empty_aid_list.xml
new file mode 100644
index 0000000..0646fd9
--- /dev/null
+++ b/apps/CtsVerifier/res/xml/empty_aid_list.xml
@@ -0,0 +1,3 @@
+<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
+    android:description="@string/transportService1">
+</host-apdu-service>
diff --git a/apps/CtsVerifier/res/xml/payment_aid_list_1.xml b/apps/CtsVerifier/res/xml/payment_aid_list_1.xml
index 2036402..37344ff 100644
--- a/apps/CtsVerifier/res/xml/payment_aid_list_1.xml
+++ b/apps/CtsVerifier/res/xml/payment_aid_list_1.xml
@@ -1,5 +1,6 @@
 <host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
-    android:description="@string/paymentService1">
+    android:description="@string/paymentService1"
+    android:apduServiceBanner="@drawable/nfc_hce_banner">
         <aid-group android:description="@string/paymentService1" android:category="payment">
             <aid-filter android:name="325041592E5359532E4444463031"
                         android:description="@string/ppse"/>
diff --git a/apps/CtsVerifier/res/xml/payment_aid_list_2.xml b/apps/CtsVerifier/res/xml/payment_aid_list_2.xml
index 36a5af0..fbf9ce5 100644
--- a/apps/CtsVerifier/res/xml/payment_aid_list_2.xml
+++ b/apps/CtsVerifier/res/xml/payment_aid_list_2.xml
@@ -1,5 +1,5 @@
 <host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
-    android:description="@string/paymentService2">
+    android:description="@string/paymentService2" android:apduServiceBanner="@drawable/nfc_hce_banner">
         <aid-group android:description="@string/paymentService2" android:category="payment">
             <aid-filter android:name="325041592E5359532E4444463031"
                         android:description="@string/ppse"/>
diff --git a/apps/CtsVerifier/res/xml/payment_empty_aid_list.xml b/apps/CtsVerifier/res/xml/payment_empty_aid_list.xml
new file mode 100644
index 0000000..6daf5ea
--- /dev/null
+++ b/apps/CtsVerifier/res/xml/payment_empty_aid_list.xml
@@ -0,0 +1,9 @@
+<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
+    android:description="@string/paymentService1" android:apduServiceBanner="@drawable/nfc_hce_banner">
+        <aid-group android:description="@string/paymentService1" android:category="payment">
+            <aid-filter android:name="325041592E5359532E4444463031"
+                        android:description="@string/ppse"/>
+            <aid-filter android:name="A0000000041010"
+                        android:description="@string/mastercard"/>
+        </aid-group>
+</host-apdu-service>
diff --git a/apps/CtsVerifier/res/xml/payment_prefix_aid_list.xml b/apps/CtsVerifier/res/xml/payment_prefix_aid_list.xml
new file mode 100644
index 0000000..cea5600
--- /dev/null
+++ b/apps/CtsVerifier/res/xml/payment_prefix_aid_list.xml
@@ -0,0 +1,11 @@
+<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
+    android:description="@string/paymentService1" android:apduServiceBanner="@drawable/nfc_hce_banner">
+        <aid-group android:description="@string/paymentService1" android:category="payment">
+            <aid-filter android:name="325041592E5359532E4444463031"
+                        android:description="@string/ppse"/>
+            <aid-prefix-filter android:name="A000000004"
+                        android:description="@string/mastercard"/>
+            <aid-prefix-filter android:name="A000000003"
+                        android:description="@string/visa"/>
+        </aid-group>
+</host-apdu-service>
diff --git a/apps/CtsVerifier/res/xml/payment_prefix_aid_list_2.xml b/apps/CtsVerifier/res/xml/payment_prefix_aid_list_2.xml
new file mode 100644
index 0000000..67b4d90
--- /dev/null
+++ b/apps/CtsVerifier/res/xml/payment_prefix_aid_list_2.xml
@@ -0,0 +1,19 @@
+<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
+    android:description="@string/paymentService1" android:apduServiceBanner="@drawable/nfc_hce_banner">
+        <aid-group android:description="@string/paymentService1" android:category="payment">
+            <aid-filter android:name="325041592E5359532E4444463031"
+                        android:description="@string/ppse"/>
+            <aid-prefix-filter android:name="A00000000410"
+                        android:description="@string/mastercard"/>
+            <aid-prefix-filter android:name="A0000000041010"
+                        android:description="@string/mastercard"/>
+            <aid-prefix-filter android:name="A00000000310"
+                        android:description="@string/visa"/>
+        </aid-group>
+        <aid-group android:description="@string/transportService1" android:category="other">
+            <aid-prefix-filter android:name="F0000000FF"
+                        android:description="@string/transportService1"/>
+            <aid-prefix-filter android:name="F000000000"
+                        android:description="@string/transportService1"/>
+        </aid-group>
+</host-apdu-service>
diff --git a/apps/CtsVerifier/res/xml/sensor_device_admin.xml b/apps/CtsVerifier/res/xml/sensor_device_admin.xml
new file mode 100644
index 0000000..2a3437d
--- /dev/null
+++ b/apps/CtsVerifier/res/xml/sensor_device_admin.xml
@@ -0,0 +1,20 @@
+<!-- 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.
+-->
+
+<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
+    <uses-policies>
+        <force-lock />
+    </uses-policies>
+</device-admin>
diff --git a/apps/CtsVerifier/res/xml/transport_prefix_aid_list_1.xml b/apps/CtsVerifier/res/xml/transport_prefix_aid_list_1.xml
new file mode 100644
index 0000000..0646fd9
--- /dev/null
+++ b/apps/CtsVerifier/res/xml/transport_prefix_aid_list_1.xml
@@ -0,0 +1,3 @@
+<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
+    android:description="@string/transportService1">
+</host-apdu-service>
diff --git a/apps/CtsVerifier/res/xml/transport_prefix_aid_list_2.xml b/apps/CtsVerifier/res/xml/transport_prefix_aid_list_2.xml
new file mode 100644
index 0000000..44b1772
--- /dev/null
+++ b/apps/CtsVerifier/res/xml/transport_prefix_aid_list_2.xml
@@ -0,0 +1,3 @@
+<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
+    android:description="@string/transportService2">
+</host-apdu-service>
diff --git a/apps/CtsVerifier/src/android/support/wearable/view/BoxInsetLayout.java b/apps/CtsVerifier/src/android/support/wearable/view/BoxInsetLayout.java
new file mode 100644
index 0000000..95bac11
--- /dev/null
+++ b/apps/CtsVerifier/src/android/support/wearable/view/BoxInsetLayout.java
@@ -0,0 +1,408 @@
+/*
+ * 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.support.wearable.view;
+
+import com.android.cts.verifier.R;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowInsets;
+import android.widget.FrameLayout;
+
+/**
+ * BoxInsetLayout is a screen shape-aware FrameLayout that can box its children
+ * in the center square of a round screen by using the
+ * {@code layout_box} attribute. The values for this attribute specify the
+ * child's edges to be boxed in:
+ * {@code left|top|right|bottom} or {@code all}.
+ * The {@code layout_box} attribute is ignored on a device with a rectangular
+ * screen.
+ */
+public class BoxInsetLayout extends FrameLayout {
+
+    private static float FACTOR = 0.146467f; //(1 - sqrt(2)/2)/2
+    private static final int DEFAULT_CHILD_GRAVITY = Gravity.TOP | Gravity.START;
+
+    private Rect mForegroundPadding;
+    private boolean mLastKnownRound;
+    private Rect mInsets;
+
+    public BoxInsetLayout(Context context) {
+        this(context, null);
+    }
+
+    public BoxInsetLayout(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public BoxInsetLayout(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        // make sure we have foreground padding object
+        if (mForegroundPadding == null) {
+            mForegroundPadding = new Rect();
+        }
+        if (mInsets == null) {
+            mInsets = new Rect();
+        }
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        requestApplyInsets();
+    }
+
+    @Override
+    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+        insets = super.onApplyWindowInsets(insets);
+        final boolean round = insets.isRound();
+        if (round != mLastKnownRound) {
+            mLastKnownRound = round;
+            requestLayout();
+        }
+        mInsets.set(
+                insets.getSystemWindowInsetLeft(),
+                insets.getSystemWindowInsetTop(),
+                insets.getSystemWindowInsetRight(),
+                insets.getSystemWindowInsetBottom());
+        return insets;
+    }
+
+    /**
+     * determine screen shape
+     * @return true if on a round screen
+     */
+    public boolean isRound() {
+        return mLastKnownRound;
+    }
+
+    /**
+     * @return the system window insets Rect
+     */
+    public Rect getInsets() {
+        return mInsets;
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        int count = getChildCount();
+        // find max size
+        int maxWidth = 0;
+        int maxHeight = 0;
+        int childState = 0;
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            if (child.getVisibility() != GONE) {
+                LayoutParams lp = (BoxInsetLayout.LayoutParams) child.getLayoutParams();
+                int marginLeft = 0;
+                int marginRight = 0;
+                int marginTop = 0;
+                int marginBottom = 0;
+                if (mLastKnownRound) {
+                    // round screen, check boxed, don't use margins on boxed
+                    if ((lp.boxedEdges & LayoutParams.BOX_LEFT) == 0) {
+                        marginLeft = lp.leftMargin;
+                    }
+                    if ((lp.boxedEdges & LayoutParams.BOX_RIGHT) == 0) {
+                        marginRight = lp.rightMargin;
+                    }
+                    if ((lp.boxedEdges & LayoutParams.BOX_TOP) == 0) {
+                        marginTop = lp.topMargin;
+                    }
+                    if ((lp.boxedEdges & LayoutParams.BOX_BOTTOM) == 0) {
+                        marginBottom = lp.bottomMargin;
+                    }
+                } else {
+                    // rectangular, ignore boxed, use margins
+                    marginLeft = lp.leftMargin;
+                    marginTop = lp.topMargin;
+                    marginRight = lp.rightMargin;
+                    marginBottom = lp.bottomMargin;
+                }
+                measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
+                maxWidth = Math.max(maxWidth,
+                        child.getMeasuredWidth() + marginLeft + marginRight);
+                maxHeight = Math.max(maxHeight,
+                        child.getMeasuredHeight() + marginTop + marginBottom);
+                childState = combineMeasuredStates(childState, child.getMeasuredState());
+            }
+        }
+        // Account for padding too
+        maxWidth += getPaddingLeft() + mForegroundPadding.left
+                + getPaddingRight() + mForegroundPadding.right;
+        maxHeight += getPaddingTop() + mForegroundPadding.top
+                + getPaddingBottom() + mForegroundPadding.bottom;
+
+        // Check against our minimum height and width
+        maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
+        maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
+
+        // Check against our foreground's minimum height and width
+        final Drawable drawable = getForeground();
+        if (drawable != null) {
+            maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
+            maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
+        }
+
+        setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
+                resolveSizeAndState(maxHeight, heightMeasureSpec,
+                        childState << MEASURED_HEIGHT_STATE_SHIFT));
+
+        // determine boxed inset
+        int boxInset = (int) (FACTOR * Math.max(getMeasuredWidth(), getMeasuredHeight()));
+        // adjust the match parent children
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+
+            final LayoutParams lp = (BoxInsetLayout.LayoutParams) child.getLayoutParams();
+            int childWidthMeasureSpec;
+            int childHeightMeasureSpec;
+            int plwf = getPaddingLeft() + mForegroundPadding.left;
+            int prwf = getPaddingRight() + mForegroundPadding.right;
+            int ptwf = getPaddingTop() + mForegroundPadding.top;
+            int pbwf = getPaddingBottom() + mForegroundPadding.bottom;
+
+            // adjust width
+            int totalPadding = 0;
+            int totalMargin = 0;
+            // BoxInset is a padding. Ignore margin when we want to do BoxInset.
+            if (mLastKnownRound && ((lp.boxedEdges & LayoutParams.BOX_LEFT) != 0)) {
+                totalPadding = boxInset;
+            } else {
+                totalMargin = plwf + lp.leftMargin;
+            }
+            if (mLastKnownRound && ((lp.boxedEdges & LayoutParams.BOX_RIGHT) != 0)) {
+                totalPadding += boxInset;
+            } else {
+                totalMargin += prwf + lp.rightMargin;
+            }
+            if (lp.width == LayoutParams.MATCH_PARENT) {
+                //  Only subtract margin from the actual width, leave the padding in.
+                childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
+                        getMeasuredWidth() - totalMargin, MeasureSpec.EXACTLY);
+            } else {
+                childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
+                        totalPadding + totalMargin, lp.width);
+            }
+
+            // adjust height
+            if (mLastKnownRound && ((lp.boxedEdges & LayoutParams.BOX_TOP) != 0)) {
+                totalPadding = boxInset;
+            } else {
+                totalMargin = ptwf + lp.topMargin;
+            }
+            if (mLastKnownRound && ((lp.boxedEdges & LayoutParams.BOX_BOTTOM) != 0)) {
+                totalPadding += boxInset;
+            } else {
+                totalMargin += pbwf + lp.bottomMargin;
+            }
+
+            if (lp.height == LayoutParams.MATCH_PARENT) {
+                childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
+                        getMeasuredHeight() - totalMargin, MeasureSpec.EXACTLY);
+            } else {
+                childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
+                        totalPadding + totalMargin, lp.height);
+            }
+
+            child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+        }
+    }
+
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        layoutBoxChildren(left, top, right, bottom, false /* no force left gravity */);
+    }
+
+    private void layoutBoxChildren(int left, int top, int right, int bottom,
+            boolean forceLeftGravity) {
+        final int count = getChildCount();
+        int boxInset = (int)(FACTOR * Math.max(right - left, bottom - top));
+
+        final int parentLeft = getPaddingLeft() + mForegroundPadding.left;
+        final int parentRight = right - left - getPaddingRight() - mForegroundPadding.right;
+
+        final int parentTop = getPaddingTop() + mForegroundPadding.top;
+        final int parentBottom = bottom - top - getPaddingBottom() - mForegroundPadding.bottom;
+
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            if (child.getVisibility() != GONE) {
+                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+
+                final int width = child.getMeasuredWidth();
+                final int height = child.getMeasuredHeight();
+
+                int childLeft;
+                int childTop;
+
+                int gravity = lp.gravity;
+                if (gravity == -1) {
+                    gravity = DEFAULT_CHILD_GRAVITY;
+                }
+
+                final int layoutDirection = getLayoutDirection();
+                final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);
+                final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
+
+                // These values are replaced with boxInset below as necessary.
+                int paddingLeft = child.getPaddingLeft();
+                int paddingRight = child.getPaddingRight();
+                int paddingTop = child.getPaddingTop();
+                int paddingBottom = child.getPaddingBottom();
+
+                switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
+                    case Gravity.CENTER_HORIZONTAL:
+                        childLeft = parentLeft + (parentRight - parentLeft - width) / 2 +
+                                lp.leftMargin - lp.rightMargin;
+                        break;
+                    case Gravity.RIGHT:
+                        if (!forceLeftGravity) {
+                            if (mLastKnownRound
+                                    && ((lp.boxedEdges & LayoutParams.BOX_RIGHT) != 0)) {
+                                paddingRight = boxInset;
+                                childLeft = right - left - width;
+                            } else {
+                                childLeft = parentRight - width - lp.rightMargin;
+                            }
+                            break;
+                        }
+                    case Gravity.LEFT:
+                    default:
+                        if (mLastKnownRound && ((lp.boxedEdges & LayoutParams.BOX_LEFT) != 0)) {
+                            paddingLeft = boxInset;
+                            childLeft = 0;
+                        } else {
+                            childLeft = parentLeft + lp.leftMargin;
+                        }
+                }
+
+                switch (verticalGravity) {
+                    case Gravity.TOP:
+                        if (mLastKnownRound && ((lp.boxedEdges & LayoutParams.BOX_TOP) != 0)) {
+                            paddingTop = boxInset;
+                            childTop = 0;
+                        } else {
+                            childTop = parentTop + lp.topMargin;
+                        }
+                        break;
+                    case Gravity.CENTER_VERTICAL:
+                        childTop = parentTop + (parentBottom - parentTop - height) / 2 +
+                                lp.topMargin - lp.bottomMargin;
+                        break;
+                    case Gravity.BOTTOM:
+                        if (mLastKnownRound && ((lp.boxedEdges & LayoutParams.BOX_BOTTOM) != 0)) {
+                            paddingBottom = boxInset;
+                            childTop = bottom - top - height;
+                        } else {
+                            childTop = parentBottom - height - lp.bottomMargin;
+                        }
+                        break;
+                    default:
+                        childTop = parentTop + lp.topMargin;
+                }
+
+                child.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
+                child.layout(childLeft, childTop, childLeft + width, childTop + height);
+            }
+        }
+    }
+
+    public void setForeground(Drawable drawable) {
+        super.setForeground(drawable);
+        if (mForegroundPadding == null) {
+            mForegroundPadding = new Rect();
+        }
+        drawable.getPadding(mForegroundPadding);
+    }
+
+    @Override
+    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
+        return p instanceof LayoutParams;
+    }
+
+    @Override
+    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
+        return new LayoutParams(p);
+    }
+
+    @Override
+    public LayoutParams generateLayoutParams(AttributeSet attrs) {
+        return new BoxInsetLayout.LayoutParams(getContext(), attrs);
+    }
+
+    /**
+     * adds {@code layout_box} attribute to layout parameters
+     */
+    public static class LayoutParams extends FrameLayout.LayoutParams {
+
+        public static final int BOX_NONE = 0x0;
+        public static final int BOX_LEFT = 0x01;
+        public static final int BOX_TOP = 0x02;
+        public static final int BOX_RIGHT = 0x04;
+        public static final int BOX_BOTTOM = 0x08;
+        public static final int BOX_ALL = 0x0F;
+
+        public int boxedEdges = BOX_NONE;
+
+        public LayoutParams(Context context, AttributeSet attrs) {
+            super(context, attrs);
+            TypedArray a = context.obtainStyledAttributes(attrs,  R.styleable.BoxInsetLayout_Layout, 0, 0);
+            boxedEdges = a.getInt(R.styleable.BoxInsetLayout_Layout_layout_box, BOX_NONE);
+            a.recycle();
+        }
+
+        public LayoutParams(int width, int height) {
+            super(width, height);
+        }
+
+        public LayoutParams(int width, int height, int gravity) {
+            super(width, height, gravity);
+        }
+
+        public LayoutParams(int width, int height, int gravity, int boxed) {
+            super(width, height, gravity);
+            boxedEdges = boxed;
+        }
+
+        public LayoutParams(ViewGroup.LayoutParams source) {
+            super(source);
+        }
+
+        public LayoutParams(ViewGroup.MarginLayoutParams source) {
+            super(source);
+        }
+
+        public LayoutParams(FrameLayout.LayoutParams source) {
+            super(source);
+        }
+
+        public LayoutParams(LayoutParams source) {
+            super(source);
+            this.boxedEdges = source.boxedEdges;
+            this.gravity = source.gravity;
+        }
+
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/AbstractTestListActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/AbstractTestListActivity.java
index 9b53bfd..6495a05 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/AbstractTestListActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/AbstractTestListActivity.java
@@ -20,6 +20,7 @@
 
 import android.app.ListActivity;
 import android.content.Intent;
+import android.os.Bundle;
 import android.view.View;
 import android.widget.ListView;
 
@@ -53,6 +54,12 @@
         }
     }
 
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.list_content);
+    }
+
     private void handleLaunchTestResult(int resultCode, Intent data) {
         if (resultCode == RESULT_OK) {
             TestResult testResult = TestResult.fromActivityResult(resultCode, data);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/ManifestTestListAdapter.java b/apps/CtsVerifier/src/com/android/cts/verifier/ManifestTestListAdapter.java
index 1f19cbe..ebddf4f 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/ManifestTestListAdapter.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/ManifestTestListAdapter.java
@@ -22,12 +22,14 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.os.Bundle;
+import android.util.Log;
 import android.widget.ListView;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -67,6 +69,21 @@
  *             <meta-data android:name="test_required_features" android:value="android.hardware.sensor.accelerometer" />
  *         </pre>
  *     </li>
+ *     <li>OPTIONAL: Add a meta data attribute to indicate features such that, if any present, the
+ *         test gets excluded from being shown. If the device has any of the excluded features then
+ *         the test will not appear in the test list. Use a colon (:) to specify multiple features
+ *         to exclude for the test. Note that the colon means "or" in this case.
+ *         <pre>
+ *             <meta-data android:name="test_excluded_features" android:value="android.hardware.type.television" />
+ *         </pre>
+ *     </li>
+ *     <li>OPTIONAL: Add a meta data attribute to indicate features such that, if any present,
+ *         the test is applicable to run. If the device has any of the applicable features then
+ *         the test will appear in the test list. Use a colon (:) to specify multiple features
+ *         <pre>
+ *             <meta-data android:name="test_applicable_features" android:value="android.hardware.sensor.compass" />
+ *         </pre>
+ *     </li>
  *
  * </ol>
  */
@@ -78,6 +95,12 @@
 
     private static final String TEST_REQUIRED_FEATURES_META_DATA = "test_required_features";
 
+    private static final String TEST_EXCLUDED_FEATURES_META_DATA = "test_excluded_features";
+
+    private static final String TEST_APPLICABLE_FEATURES_META_DATA = "test_applicable_features";
+
+    private final HashSet<String> mDisabledTests;
+
     private Context mContext;
 
     private String mTestParent;
@@ -86,6 +109,12 @@
         super(context);
         mContext = context;
         mTestParent = testParent;
+
+        String[] disabledTestArray = context.getResources().getStringArray(R.array.disabled_tests);
+        mDisabledTests = new HashSet<>(disabledTestArray.length);
+        for (int i = 0; i < disabledTestArray.length; i++) {
+            mDisabledTests.add(disabledTestArray[i]);
+        }
     }
 
     @Override
@@ -148,11 +177,18 @@
         int size = list.size();
         for (int i = 0; i < size; i++) {
             ResolveInfo info = list.get(i);
+            if (info.activityInfo == null || mDisabledTests.contains(info.activityInfo.name)) {
+                Log.w("CtsVerifier", "ignoring disabled test: " + info.activityInfo.name);
+                continue;
+            }
             String title = getTitle(mContext, info.activityInfo);
             String testName = info.activityInfo.name;
             Intent intent = getActivityIntent(info.activityInfo);
             String[] requiredFeatures = getRequiredFeatures(info.activityInfo.metaData);
-            TestListItem item = TestListItem.newTest(title, testName, intent, requiredFeatures);
+            String[] excludedFeatures = getExcludedFeatures(info.activityInfo.metaData);
+            String[] applicableFeatures = getApplicableFeatures(info.activityInfo.metaData);
+            TestListItem item = TestListItem.newTest(title, testName, intent, requiredFeatures,
+                    excludedFeatures, applicableFeatures);
 
             String testCategory = getTestCategory(mContext, info.activityInfo.metaData);
             addTestToCategory(testsByCategory, testCategory, item);
@@ -190,6 +226,32 @@
         }
     }
 
+    static String[] getExcludedFeatures(Bundle metaData) {
+        if (metaData == null) {
+            return null;
+        } else {
+            String value = metaData.getString(TEST_EXCLUDED_FEATURES_META_DATA);
+            if (value == null) {
+                return null;
+            } else {
+                return value.split(":");
+            }
+        }
+    }
+
+    static String[] getApplicableFeatures(Bundle metaData) {
+        if (metaData == null) {
+            return null;
+        } else {
+            String value = metaData.getString(TEST_APPLICABLE_FEATURES_META_DATA);
+            if (value == null) {
+                return null;
+            } else {
+                return value.split(":");
+            }
+        }
+    }
+
     static String getTitle(Context context, ActivityInfo activityInfo) {
         if (activityInfo.labelRes != 0) {
             return context.getString(activityInfo.labelRes);
@@ -216,19 +278,36 @@
         tests.add(item);
     }
 
+    private boolean hasAnyFeature(String[] features) {
+        if (features != null) {
+            PackageManager packageManager = mContext.getPackageManager();
+            for (String feature : features) {
+                if (packageManager.hasSystemFeature(feature)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private boolean hasAllFeatures(String[] features) {
+        if (features != null) {
+            PackageManager packageManager = mContext.getPackageManager();
+            for (String feature : features) {
+                if (!packageManager.hasSystemFeature(feature)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
     List<TestListItem> filterTests(List<TestListItem> tests) {
-        List<TestListItem> filteredTests = new ArrayList<TestListItem>(tests);
-        PackageManager packageManager = mContext.getPackageManager();
-        Iterator<TestListItem> iterator = filteredTests.iterator();
-        while (iterator.hasNext()) {
-            TestListItem item = iterator.next();
-            String[] requiredFeatures = item.requiredFeatures;
-            if (requiredFeatures != null) {
-                for (int i = 0; i < requiredFeatures.length; i++) {
-                    if (!packageManager.hasSystemFeature(requiredFeatures[i])) {
-                        iterator.remove();
-                        break;
-                    }
+        List<TestListItem> filteredTests = new ArrayList<TestListItem>();
+        for (TestListItem test : tests) {
+            if (!hasAnyFeature(test.excludedFeatures) && hasAllFeatures(test.requiredFeatures)) {
+                if (test.applicableFeatures == null || hasAnyFeature(test.applicableFeatures)) {
+                    filteredTests.add(test);
                 }
             }
         }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java b/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java
index ef80b5d..444a250 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java
@@ -31,7 +31,7 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;
-import android.widget.Button;
+import android.widget.ImageButton;
 
 /**
  * {@link Activity}s to handle clicks to the pass and fail buttons of the pass fail buttons layout.
@@ -77,7 +77,7 @@
          */
         void setInfoResources(int titleId, int messageId, int viewId);
 
-        Button getPassButton();
+        View getPassButton();
 
         /**
          * Returns a unique identifier for the test.  Usually, this is just the class name.
@@ -86,6 +86,13 @@
 
         /** @return null or details about the test run. */
         String getTestDetails();
+
+        /**
+         * Set the result of the test and finish the activity.
+         *
+         * @param passed Whether or not the test passed.
+         */
+        void setTestResultAndFinish(boolean passed);
     }
 
     public static class Activity extends android.app.Activity implements PassFailActivity {
@@ -120,7 +127,7 @@
         }
 
         @Override
-        public Button getPassButton() {
+        public View getPassButton() {
             return getPassButtonView(this);
         }
 
@@ -138,6 +145,12 @@
         public String getTestDetails() {
             return null;
         }
+
+        @Override
+        public void setTestResultAndFinish(boolean passed) {
+            PassFailButtons.setTestResultAndFinishHelper(this, getTestId(), getTestDetails(),
+                    passed);
+        }
     }
 
     public static class ListActivity extends android.app.ListActivity implements PassFailActivity {
@@ -153,7 +166,7 @@
         }
 
         @Override
-        public Button getPassButton() {
+        public View getPassButton() {
             return getPassButtonView(this);
         }
 
@@ -171,6 +184,12 @@
         public String getTestDetails() {
             return null;
         }
+
+        @Override
+        public void setTestResultAndFinish(boolean passed) {
+            PassFailButtons.setTestResultAndFinishHelper(this, getTestId(), getTestDetails(),
+                    passed);
+        }
     }
 
     public static class TestListActivity extends AbstractTestListActivity
@@ -187,7 +206,7 @@
         }
 
         @Override
-        public Button getPassButton() {
+        public View getPassButton() {
             return getPassButtonView(this);
         }
 
@@ -205,6 +224,12 @@
         public String getTestDetails() {
             return null;
         }
+
+        @Override
+        public void setTestResultAndFinish(boolean passed) {
+            PassFailButtons.setTestResultAndFinishHelper(this, getTestId(), getTestDetails(),
+                    passed);
+        }
     }
 
     private static <T extends android.app.Activity & PassFailActivity>
@@ -328,11 +353,11 @@
             default:
                 throw new IllegalArgumentException("Unknown id: " + target.getId());
         }
-        setTestResultAndFinish(activity, testId, testDetails, passed);
+        setTestResultAndFinishHelper(activity, testId, testDetails, passed);
     }
 
     /** Set the test result and finish the activity. */
-    public static void setTestResultAndFinish(android.app.Activity activity, String testId,
+    private static void setTestResultAndFinishHelper(android.app.Activity activity, String testId,
             String testDetails, boolean passed) {
         if (passed) {
             TestResult.setPassedResult(activity, testId, testDetails);
@@ -343,7 +368,7 @@
         activity.finish();
     }
 
-    private static Button getPassButtonView(android.app.Activity activity) {
-        return (Button) activity.findViewById(R.id.pass_button);
+    private static ImageButton getPassButtonView(android.app.Activity activity) {
+        return (ImageButton) activity.findViewById(R.id.pass_button);
     }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java
index 2cc79fb..afe3a73 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/TestListAdapter.java
@@ -83,14 +83,46 @@
         /** Features necessary to run this test. */
         final String[] requiredFeatures;
 
+        /** Features such that, if any present, the test gets excluded from being shown. */
+        final String[] excludedFeatures;
+
+        /** If any of of the features are present the test is meaningful to run. */
+        final String[] applicableFeatures;
+
+        public static TestListItem newTest(Context context, int titleResId, String testName,
+                Intent intent, String[] requiredFeatures, String[] excludedFeatures,
+                String[] applicableFeatures) {
+            return newTest(context.getString(titleResId), testName, intent, requiredFeatures,
+                    excludedFeatures, applicableFeatures);
+        }
+
+        public static TestListItem newTest(Context context, int titleResId, String testName,
+                Intent intent, String[] requiredFeatures, String[] excludedFeatures) {
+            return newTest(context.getString(titleResId), testName, intent, requiredFeatures,
+                    excludedFeatures, null);
+        }
+
         public static TestListItem newTest(Context context, int titleResId, String testName,
                 Intent intent, String[] requiredFeatures) {
-            return newTest(context.getString(titleResId), testName, intent, requiredFeatures);
+            return newTest(context.getString(titleResId), testName, intent, requiredFeatures, null,
+                    null);
+        }
+
+        public static TestListItem newTest(String title, String testName, Intent intent,
+                String[] requiredFeatures, String[] excludedFeatures, String[] applicableFeatures) {
+            return new TestListItem(title, testName, intent, requiredFeatures, excludedFeatures,
+                    applicableFeatures);
+        }
+
+        public static TestListItem newTest(String title, String testName, Intent intent,
+                String[] requiredFeatures, String[] excludedFeatures) {
+            return new TestListItem(title, testName, intent, requiredFeatures, excludedFeatures,
+                    null);
         }
 
         public static TestListItem newTest(String title, String testName, Intent intent,
                 String[] requiredFeatures) {
-            return new TestListItem(title, testName, intent, requiredFeatures);
+            return new TestListItem(title, testName, intent, requiredFeatures, null, null);
         }
 
         public static TestListItem newCategory(Context context, int titleResId) {
@@ -98,15 +130,17 @@
         }
 
         public static TestListItem newCategory(String title) {
-            return new TestListItem(title, null, null, null);
+            return new TestListItem(title, null, null, null, null, null);
         }
 
         private TestListItem(String title, String testName, Intent intent,
-                String[] requiredFeatures) {
+                String[] requiredFeatures, String[] excludedFeatures, String[] applicableFeatures) {
             this.title = title;
             this.testName = testName;
             this.intent = intent;
             this.requiredFeatures = requiredFeatures;
+            this.excludedFeatures = excludedFeatures;
+            this.applicableFeatures = applicableFeatures;
         }
 
         boolean isTest() {
@@ -366,4 +400,4 @@
 
         }
     }
-}
\ No newline at end of file
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertiserHardwareScanFilterActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertiserHardwareScanFilterActivity.java
new file mode 100644
index 0000000..be2fef9
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertiserHardwareScanFilterActivity.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.bluetooth;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.Toast;
+
+public class BleAdvertiserHardwareScanFilterActivity extends PassFailButtons.Activity {
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.ble_advertiser_hardware_scan_filter);
+        setPassFailButtonClickListeners();
+        setInfoResources(R.string.ble_advertiser_scan_filter_name,
+                         R.string.ble_advertiser_scan_filter_info, -1);
+
+        ((Button) findViewById(R.id.ble_advertiser_scannable_start))
+            .setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    Intent intent = new Intent(BleAdvertiserHardwareScanFilterActivity.this,
+                                               BleAdvertiserService.class);
+                    intent.putExtra(BleAdvertiserService.EXTRA_COMMAND,
+                                    BleAdvertiserService.COMMAND_START_SCANNABLE);
+                    startService(intent);
+                }
+            });
+        ((Button)findViewById(R.id.ble_advertiser_scannable_stop))
+            .setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    stopAdvertising();
+                }
+            });
+        ((Button)findViewById(R.id.ble_advertiser_unscannable_start))
+            .setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    Intent intent = new Intent(BleAdvertiserHardwareScanFilterActivity.this,
+                                               BleAdvertiserService.class);
+                    intent.putExtra(BleAdvertiserService.EXTRA_COMMAND,
+                                    BleAdvertiserService.COMMAND_START_UNSCANNABLE);
+                    startService(intent);
+                }
+        });
+        ((Button)findViewById(R.id.ble_advertiser_unscannable_stop))
+            .setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    stopAdvertising();
+                }
+        });
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(BleAdvertiserService.BLE_ADV_NOT_SUPPORT);
+        filter.addAction(BleAdvertiserService.BLE_START_SCANNABLE);
+        filter.addAction(BleAdvertiserService.BLE_START_UNSCANNABLE);
+        filter.addAction(BleAdvertiserService.BLE_STOP_SCANNABLE);
+        filter.addAction(BleAdvertiserService.BLE_STOP_UNSCANNABLE);
+        registerReceiver(onBroadcast, filter);
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        unregisterReceiver(onBroadcast);
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        stopAdvertising();
+    }
+
+    private void showMessage(String msg) {
+        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
+    }
+
+    private void pass() {
+        this.setTestResultAndFinish(true);
+    }
+
+    private void stopAdvertising() {
+        Intent intent = new Intent(BleAdvertiserHardwareScanFilterActivity.this,
+                                   BleAdvertiserService.class);
+        intent.putExtra(BleAdvertiserService.EXTRA_COMMAND,
+                        BleAdvertiserService.COMMAND_STOP_SCANNABLE);
+        intent.putExtra(BleAdvertiserService.EXTRA_COMMAND,
+                        BleAdvertiserService.COMMAND_STOP_UNSCANNABLE);
+        startService(intent);
+    }
+
+    private BroadcastReceiver onBroadcast = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            switch (intent.getAction()) {
+                case BleAdvertiserService.BLE_START_SCANNABLE:
+                    showMessage("Start advertising, this should be scanned");
+                    break;
+                case BleAdvertiserService.BLE_START_UNSCANNABLE:
+                    showMessage("Start advertising, this should not be scanned");
+                    break;
+                case BleAdvertiserService.BLE_STOP_SCANNABLE:
+                case BleAdvertiserService.BLE_STOP_UNSCANNABLE:
+                    showMessage("Stop advertising");
+                    break;
+                case BleAdvertiserService.BLE_ADV_NOT_SUPPORT:
+                    pass();
+                    break;
+            }
+        }
+    };
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertiserPowerLevelActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertiserPowerLevelActivity.java
new file mode 100644
index 0000000..1cc9206
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertiserPowerLevelActivity.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.bluetooth;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.Toast;
+
+public class BleAdvertiserPowerLevelActivity extends PassFailButtons.Activity {
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.ble_advertiser_power_level);
+        setPassFailButtonClickListeners();
+        setInfoResources(R.string.ble_power_level_name,
+                         R.string.ble_power_level_info, -1);
+
+        ((Button) findViewById(R.id.ble_power_level_start))
+            .setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    Intent intent = new Intent(BleAdvertiserPowerLevelActivity.this,
+                                               BleAdvertiserService.class);
+                    intent.putExtra(BleAdvertiserService.EXTRA_COMMAND,
+                                    BleAdvertiserService.COMMAND_START_POWER_LEVEL);
+                    startService(intent);
+                }
+            });
+        ((Button) findViewById(R.id.ble_power_level_stop))
+            .setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    stopAdvertising();
+                }
+            });
+
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(BleAdvertiserService.BLE_START_POWER_LEVEL);
+        filter.addAction(BleAdvertiserService.BLE_STOP_POWER_LEVEL);
+        filter.addAction(BleAdvertiserService.BLE_ADV_NOT_SUPPORT);
+        registerReceiver(onBroadcast, filter);
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        unregisterReceiver(onBroadcast);
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        stopAdvertising();
+    }
+
+    private void stopAdvertising() {
+        Intent intent = new Intent(BleAdvertiserPowerLevelActivity.this,
+                                   BleAdvertiserService.class);
+        intent.putExtra(BleAdvertiserService.EXTRA_COMMAND,
+                        BleAdvertiserService.COMMAND_STOP_POWER_LEVEL);
+        startService(intent);
+    }
+
+    private void showMessage(String msg) {
+        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
+    }
+
+    private void pass() {
+        this.setTestResultAndFinish(true);
+    }
+
+    private BroadcastReceiver onBroadcast = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            switch (intent.getAction()) {
+                case BleAdvertiserService.BLE_START_POWER_LEVEL:
+                    showMessage("Start advertising, please hold for a while.");
+                    break;
+                case BleAdvertiserService.BLE_STOP_POWER_LEVEL:
+                    showMessage("Stop advertising");
+                    break;
+                case BleAdvertiserService.BLE_ADV_NOT_SUPPORT:
+                    pass();
+                    break;
+            }
+        }
+    };
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertiserService.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertiserService.java
new file mode 100644
index 0000000..281b2e8
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertiserService.java
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.bluetooth;
+
+import java.util.UUID;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import android.app.Service;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothGattServer;
+import android.bluetooth.BluetoothGattServerCallback;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.le.BluetoothLeAdvertiser;
+import android.bluetooth.le.AdvertiseCallback;
+import android.bluetooth.le.AdvertiseData;
+import android.bluetooth.le.AdvertiseSettings;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.ParcelUuid;
+import android.util.Log;
+import android.widget.Toast;
+
+public class BleAdvertiserService extends Service {
+
+    public static final boolean DEBUG = true;
+    public static final String TAG = "BleAdvertiseService";
+
+    public static final int COMMAND_START_ADVERTISE = 0;
+    public static final int COMMAND_STOP_ADVERTISE = 1;
+    public static final int COMMAND_START_POWER_LEVEL = 2;
+    public static final int COMMAND_STOP_POWER_LEVEL = 3;
+    public static final int COMMAND_START_SCANNABLE = 4;
+    public static final int COMMAND_STOP_SCANNABLE = 5;
+    public static final int COMMAND_START_UNSCANNABLE = 6;
+    public static final int COMMAND_STOP_UNSCANNABLE = 7;
+
+    public static final String BLE_ADV_NOT_SUPPORT =
+            "com.android.cts.verifier.bluetooth.BLE_ADV_NOT_SUPPORT";
+    public static final String BLE_START_ADVERTISE =
+            "com.android.cts.verifier.bluetooth.BLE_START_ADVERTISE";
+    public static final String BLE_STOP_ADVERTISE =
+            "com.android.cts.verifier.bluetooth.BLE_STOP_ADVERTISE";
+    public static final String BLE_START_POWER_LEVEL =
+            "com.android.cts.verifier.bluetooth.BLE_START_POWER_LEVEL";
+    public static final String BLE_STOP_POWER_LEVEL =
+            "com.android.cts.verifier.bluetooth.BLE_STOP_POWER_LEVEL";
+    public static final String BLE_START_SCANNABLE =
+            "com.android.cts.verifier.bluetooth.BLE_START_SCANNABLE";
+    public static final String BLE_START_UNSCANNABLE =
+            "com.android.cts.verifier.bluetooth.BLE_START_UNSCANNABLE";
+    public static final String BLE_STOP_SCANNABLE =
+            "com.android.cts.verifier.bluetooth.BLE_STOP_SCANNABLE";
+    public static final String BLE_STOP_UNSCANNABLE =
+            "com.android.cts.verifier.bluetooth.BLE_STOP_UNSCANNABLE";
+
+    public static final String EXTRA_COMMAND =
+            "com.android.cts.verifier.bluetooth.EXTRA_COMMAND";
+
+    protected static final UUID PRIVACY_MAC_UUID =
+            UUID.fromString("00009999-0000-1000-8000-00805f9b34fb");
+    protected static final UUID POWER_LEVEL_UUID =
+            UUID.fromString("00008888-0000-1000-8000-00805f9b34fb");
+    protected static final UUID SCAN_RESP_UUID =
+            UUID.fromString("00007777-0000-1000-8000-00805f9b34fb");
+    protected static final UUID SCANNABLE_UUID =
+            UUID.fromString("00006666-0000-1000-8000-00805f9b34fb");
+    protected static final UUID UNSCANNABLE_UUID =
+            UUID.fromString("00005555-0000-1000-8000-00805f9b34fb");
+
+    public static final byte MANUFACTURER_TEST_ID = (byte)0x07;
+    public static final byte[] PRIVACY_MAC_DATA = new byte[]{3, 1, 4};
+    public static final byte[] PRIVACY_RESPONSE = new byte[]{9, 2, 6};
+    public static final byte[] POWER_LEVEL_DATA = new byte[]{1, 5, 0};
+    public static final byte[] POWER_LEVEL_MASK = new byte[]{1, 1, 0};
+    public static final byte[] SCANNABLE_DATA = new byte[]{5, 3, 5};
+    public static final byte[] UNSCANNABLE_DATA = new byte[]{8, 9, 7};
+
+    private BluetoothManager mBluetoothManager;
+    private BluetoothAdapter mBluetoothAdapter;
+    private BluetoothLeAdvertiser mAdvertiser;
+    private BluetoothGattServer mGattServer;
+    private AdvertiseCallback mCallback;
+    private Handler mHandler;
+
+    private int[] mPowerLevel;
+    private Map<Integer, AdvertiseCallback> mPowerCallback;
+    private int mAdvertiserStatus;
+
+    private AdvertiseCallback mScannableCallback;
+    private AdvertiseCallback mUnscannableCallback;
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+
+        mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
+        mBluetoothAdapter = mBluetoothManager.getAdapter();
+        mAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();
+        mGattServer = mBluetoothManager.openGattServer(getApplicationContext(),
+            new BluetoothGattServerCallback() {});
+        mHandler = new Handler();
+        mAdvertiserStatus = 0;
+
+        mCallback = new BLEAdvertiseCallback();
+        mScannableCallback = new BLEAdvertiseCallback();
+        mUnscannableCallback = new BLEAdvertiseCallback();
+        mPowerLevel = new int[]{
+            AdvertiseSettings.ADVERTISE_TX_POWER_ULTRA_LOW,
+            AdvertiseSettings.ADVERTISE_TX_POWER_LOW,
+            AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM,
+            AdvertiseSettings.ADVERTISE_TX_POWER_HIGH};
+        mPowerCallback = new HashMap<Integer, AdvertiseCallback>();
+        for (int x : mPowerLevel) {
+            mPowerCallback.put(x, new BLEAdvertiseCallback());
+        }
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        if (intent != null) handleIntent(intent);
+        return START_NOT_STICKY;
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        if (mAdvertiser != null) {
+            stopAdvertiser();
+        }
+    }
+
+    private void stopAdvertiser() {
+        if (mAdvertiser == null) {
+            mAdvertiserStatus = 0;
+            return;
+        }
+        if ((mAdvertiserStatus & (1 << COMMAND_START_ADVERTISE)) > 0) {
+            mAdvertiser.stopAdvertising(mCallback);
+        }
+        if ((mAdvertiserStatus & (1 << COMMAND_START_POWER_LEVEL)) > 0) {
+            for (int t : mPowerLevel) {
+                mAdvertiser.stopAdvertising(mPowerCallback.get(t));
+            }
+        }
+        if ((mAdvertiserStatus & (1 << COMMAND_START_SCANNABLE)) > 0) {
+            mAdvertiser.stopAdvertising(mScannableCallback);
+        }
+        if ((mAdvertiserStatus & (1 << COMMAND_START_UNSCANNABLE)) > 0) {
+            mAdvertiser.stopAdvertising(mUnscannableCallback);
+        }
+        mAdvertiserStatus = 0;
+    }
+
+    private AdvertiseData generateAdvertiseData(UUID uuid, byte[] data) {
+        return new AdvertiseData.Builder()
+            .addManufacturerData(MANUFACTURER_TEST_ID, new byte[]{MANUFACTURER_TEST_ID, 0})
+            .addServiceData(new ParcelUuid(uuid), data)
+            .setIncludeTxPowerLevel(true)
+            .build();
+    }
+
+    private AdvertiseSettings generateSetting(int power) {
+        return new AdvertiseSettings.Builder()
+            .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
+            .setTxPowerLevel(power)
+            .setConnectable(false)
+            .build();
+    }
+
+    private void handleIntent(Intent intent) {
+        if (mBluetoothAdapter != null && !mBluetoothAdapter.isMultipleAdvertisementSupported()) {
+            showMessage("Multiple advertisement is not supported.");
+            sendBroadcast(new Intent(BLE_ADV_NOT_SUPPORT));
+            return;
+        } else if (mAdvertiser == null) {
+            showMessage("Cannot start advertising on this device.");
+            return;
+        }
+        int command = intent.getIntExtra(EXTRA_COMMAND, -1);
+        if (command >= 0) {
+            stopAdvertiser();
+            mAdvertiserStatus |= (1 << command);
+        }
+
+        switch (command) {
+            case COMMAND_START_ADVERTISE:
+                AdvertiseData data = generateAdvertiseData(PRIVACY_MAC_UUID, PRIVACY_MAC_DATA);
+                AdvertiseData response = generateAdvertiseData(SCAN_RESP_UUID, PRIVACY_RESPONSE);
+                AdvertiseSettings setting =
+                        generateSetting(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM);
+
+                mAdvertiser.startAdvertising(setting, data, response, mCallback);
+                sendBroadcast(new Intent(BLE_START_ADVERTISE));
+                break;
+            case COMMAND_STOP_ADVERTISE:
+                sendBroadcast(new Intent(BLE_STOP_ADVERTISE));
+                break;
+            case COMMAND_START_POWER_LEVEL:
+                for (int t : mPowerLevel) {
+                    AdvertiseData d =
+                            generateAdvertiseData(POWER_LEVEL_UUID, new byte[]{1, 5, (byte)t});
+                    AdvertiseSettings settings = generateSetting(t);
+                    mAdvertiser.startAdvertising(settings, d, mPowerCallback.get(t));
+                }
+                sendBroadcast(new Intent(BLE_START_POWER_LEVEL));
+                break;
+            case COMMAND_STOP_POWER_LEVEL:
+                sendBroadcast(new Intent(BLE_STOP_POWER_LEVEL));
+                break;
+            case COMMAND_START_SCANNABLE:
+                data = generateAdvertiseData(SCANNABLE_UUID, SCANNABLE_DATA);
+                setting = generateSetting(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM);
+
+                mAdvertiser.startAdvertising(setting, data, mScannableCallback);
+                sendBroadcast(new Intent(BLE_START_SCANNABLE));
+                break;
+            case COMMAND_START_UNSCANNABLE:
+                data = generateAdvertiseData(UNSCANNABLE_UUID, UNSCANNABLE_DATA);
+                setting = generateSetting(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM);
+
+                mAdvertiser.startAdvertising(setting, data, mUnscannableCallback);
+                sendBroadcast(new Intent(BLE_START_UNSCANNABLE));
+                break;
+            case COMMAND_STOP_SCANNABLE:
+                sendBroadcast(new Intent(BLE_STOP_SCANNABLE));
+                break;
+            case COMMAND_STOP_UNSCANNABLE:
+                sendBroadcast(new Intent(BLE_STOP_UNSCANNABLE));
+                break;
+            default:
+                showMessage("Unrecognized command: " + command);
+                break;
+        }
+    }
+
+    private void showMessage(final String msg) {
+        mHandler.post(new Runnable() {
+            public void run() {
+                Toast.makeText(BleAdvertiserService.this, msg, Toast.LENGTH_SHORT).show();
+            }
+        });
+    }
+
+    private class BLEAdvertiseCallback extends AdvertiseCallback {
+        @Override
+        public void onStartFailure(int errorCode) {
+            Log.e(TAG, "fail. Error code: " + errorCode);
+        }
+
+        @Override
+        public void onStartSuccess(AdvertiseSettings setting) {
+            if (DEBUG) Log.d(TAG, "success.");
+        }
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertiserTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertiserTestActivity.java
new file mode 100644
index 0000000..637ef71
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertiserTestActivity.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+package com.android.cts.verifier.bluetooth;
+
+import com.android.cts.verifier.ManifestTestListAdapter;
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+import android.os.Bundle;
+
+public class BleAdvertiserTestActivity extends PassFailButtons.TestListActivity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.pass_fail_list);
+        setPassFailButtonClickListeners();
+        setInfoResources(R.string.ble_advertiser_test_name, R.string.ble_advertiser_test_info, -1);
+
+        setTestListAdapter(new ManifestTestListAdapter(this, getClass().getName()));
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerHardwareScanFilterActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerHardwareScanFilterActivity.java
new file mode 100644
index 0000000..dd7e66c
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerHardwareScanFilterActivity.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.bluetooth;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.Button;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+
+public class BleScannerHardwareScanFilterActivity extends PassFailButtons.Activity {
+
+    private static final String TAG = "BleScannerHardwareScanFilter";
+
+    private ListView mScanResultListView;
+    private MapAdapter mAdapter;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.ble_scanner_hardware_scan_filter);
+        setPassFailButtonClickListeners();
+        setInfoResources(R.string.ble_scanner_scan_filter_name,
+                         R.string.ble_scanner_scan_filter_info, -1);
+
+        mScanResultListView = (ListView)findViewById(R.id.ble_scan_result_list);
+        mAdapter = new MapAdapter();
+        mScanResultListView.setAdapter(mAdapter);
+
+        ((Button) findViewById(R.id.ble_scan_with_filter))
+                .setOnClickListener(new OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        Intent intent = new Intent(BleScannerHardwareScanFilterActivity.this,
+                                BleScannerService.class);
+                        intent.putExtra(BleScannerService.EXTRA_COMMAND,
+                                BleScannerService.COMMAND_SCAN_WITH_FILTER);
+                        startService(intent);
+                    }
+                });
+
+        ((Button) findViewById(R.id.ble_scan_without_filter))
+                .setOnClickListener(new OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        Intent intent = new Intent(BleScannerHardwareScanFilterActivity.this,
+                                BleScannerService.class);
+                        intent.putExtra(BleScannerService.EXTRA_COMMAND,
+                                BleScannerService.COMMAND_SCAN_WITHOUT_FILTER);
+                        startService(intent);
+                    }
+                });
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(BleScannerService.BLE_SCAN_RESULT);
+        registerReceiver(onBroadcast, filter);
+    }
+
+
+    private BroadcastReceiver onBroadcast = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            switch (intent.getAction()) {
+                case BleScannerService.BLE_SCAN_RESULT:
+                    String uuid = intent.getStringExtra(BleScannerService.EXTRA_UUID);
+                    String data = intent.getStringExtra(BleScannerService.EXTRA_DATA);
+                    if (data != null) {
+                        mAdapter.addItem(uuid + " : " + data);
+                    }
+                    break;
+            }
+        }
+    };
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        unregisterReceiver(onBroadcast);
+    }
+
+    private void stop() {
+        stopService(new Intent(this, BleScannerService.class));
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        stop();
+    }
+
+    public class MapAdapter extends BaseAdapter {
+        private Map<String, Integer> mData;
+        private ArrayList<String> mKeys;
+        public MapAdapter() {
+            mData = new HashMap<>();
+            mKeys = new ArrayList<>();
+        }
+
+        @Override
+        public int getCount() {
+            return mData.size();
+        }
+
+        @Override
+        public Object getItem(int position) {
+            return mData.get(mKeys.get(position));
+        }
+
+        @Override
+        public long getItemId(int arg0) {
+            return arg0;
+        }
+
+        public void addItem(String key) {
+            if (!mData.containsKey(key)) {
+                mKeys.add(key);
+                mData.put(key, new Integer(1));
+            } else {
+                mData.put(key, mData.get(key) + 1);
+            }
+            this.notifyDataSetChanged();
+        }
+
+        @Override
+        public View getView(int pos, View view, ViewGroup parent) {
+            if (view == null) {
+                view = LayoutInflater.from(parent.getContext())
+                    .inflate(android.R.layout.simple_list_item_2, parent, false);
+            }
+            String key = mKeys.get(pos);
+            String value = getItem(pos).toString();
+            TextView text1 = (TextView) view.findViewById(android.R.id.text1);
+            TextView text2 = (TextView) view.findViewById(android.R.id.text2);
+            text1.setText(key);
+            text2.setText(value);
+            return view;
+        }
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerPowerLevelActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerPowerLevelActivity.java
new file mode 100644
index 0000000..a6489c1
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerPowerLevelActivity.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.bluetooth;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+import java.lang.Math;
+import java.util.Set;
+import java.util.Map;
+import java.util.HashMap;
+
+import android.bluetooth.le.AdvertiseSettings;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.os.CountDownTimer;
+import android.util.Log;
+import android.widget.TextView;
+import android.widget.Toast;
+
+public class BleScannerPowerLevelActivity extends PassFailButtons.Activity {
+
+    private static final String TAG = "BleScannerPowerLevel";
+
+    private Map<Integer, TextView> mMacText;
+    private Map<Integer, TextView> mCountText;
+    private Map<Integer, TextView> mRssiText;
+    private Map<Integer, TextView> mSetPowerText;
+    private Map<Integer, Integer> mCount;
+    private int[] mPowerLevel;
+
+    private TextView mTimerText;
+    private CountDownTimer mTimer;
+    private static final long REFRESH_MAC_TIME = 930000; // 15.5 min
+
+    private static final int[] POWER_DBM = {-21, -15, -7, 1, 9};
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.ble_scanner_power_level);
+        setPassFailButtonClickListeners();
+        setInfoResources(R.string.ble_power_level_name,
+                         R.string.ble_power_level_info, -1);
+
+        mTimerText = (TextView)findViewById(R.id.ble_timer);
+        mTimer = new CountDownTimer(REFRESH_MAC_TIME, 1000) {
+            @Override
+            public void onTick(long millis) {
+                int min = (int)millis / 60000;
+                int sec = ((int)millis / 1000) % 60;
+                mTimerText.setText(min + ":" + sec);
+            }
+
+            @Override
+            public void onFinish() {
+                mTimerText.setTextColor(getResources().getColor(R.color.red));
+                mTimerText.setText("Time is up!");
+            }
+        };
+
+        mRssiText = new HashMap<Integer, TextView>();
+        mCountText = new HashMap<Integer, TextView>();
+        mCount = null;
+        mMacText = new HashMap<Integer, TextView>();
+        mSetPowerText = new HashMap<Integer, TextView>();
+        mPowerLevel = new int[]{AdvertiseSettings.ADVERTISE_TX_POWER_ULTRA_LOW,
+            AdvertiseSettings.ADVERTISE_TX_POWER_LOW,
+            AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM,
+            AdvertiseSettings.ADVERTISE_TX_POWER_HIGH};
+
+        mMacText.put(AdvertiseSettings.ADVERTISE_TX_POWER_ULTRA_LOW,
+            (TextView)findViewById(R.id.ble_ultra_low_mac));
+        mMacText.put(AdvertiseSettings.ADVERTISE_TX_POWER_LOW,
+            (TextView)findViewById(R.id.ble_low_mac));
+        mMacText.put(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM,
+            (TextView)findViewById(R.id.ble_medium_mac));
+        mMacText.put(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH,
+            (TextView)findViewById(R.id.ble_high_mac));
+
+        mCountText.put(AdvertiseSettings.ADVERTISE_TX_POWER_ULTRA_LOW,
+            (TextView)findViewById(R.id.ble_ultra_low_count));
+        mCountText.put(AdvertiseSettings.ADVERTISE_TX_POWER_LOW,
+            (TextView)findViewById(R.id.ble_low_count));
+        mCountText.put(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM,
+            (TextView)findViewById(R.id.ble_medium_count));
+        mCountText.put(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH,
+            (TextView)findViewById(R.id.ble_high_count));
+
+        mRssiText.put(AdvertiseSettings.ADVERTISE_TX_POWER_ULTRA_LOW,
+            (TextView)findViewById(R.id.ble_ultra_low_rssi));
+        mRssiText.put(AdvertiseSettings.ADVERTISE_TX_POWER_LOW,
+            (TextView)findViewById(R.id.ble_low_rssi));
+        mRssiText.put(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM,
+            (TextView)findViewById(R.id.ble_medium_rssi));
+        mRssiText.put(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH,
+            (TextView)findViewById(R.id.ble_high_rssi));
+
+        mSetPowerText.put(AdvertiseSettings.ADVERTISE_TX_POWER_ULTRA_LOW,
+            (TextView)findViewById(R.id.ble_ultra_low_set_power));
+        mSetPowerText.put(AdvertiseSettings.ADVERTISE_TX_POWER_LOW,
+            (TextView)findViewById(R.id.ble_low_set_power));
+        mSetPowerText.put(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM,
+            (TextView)findViewById(R.id.ble_medium_set_power));
+        mSetPowerText.put(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH,
+            (TextView)findViewById(R.id.ble_high_set_power));
+
+        Intent intent = new Intent(this, BleScannerService.class);
+        intent.putExtra(BleScannerService.EXTRA_COMMAND, BleScannerService.COMMAND_POWER_LEVEL);
+        startService(intent);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(BleScannerService.BLE_POWER_LEVEL);
+        filter.addAction(BleScannerService.BLE_PRIVACY_NEW_MAC_RECEIVE);
+        registerReceiver(onBroadcast, filter);
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        unregisterReceiver(onBroadcast);
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        stopService(new Intent(this, BleScannerService.class));
+    }
+
+    private BroadcastReceiver onBroadcast = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            switch (intent.getAction()) {
+                case BleScannerService.BLE_POWER_LEVEL:
+                    int powerLevelBit = intent.getIntExtra(
+                            BleScannerService.EXTRA_POWER_LEVEL_BIT, -1);
+                    int powerLevel = intent.getIntExtra(BleScannerService.EXTRA_POWER_LEVEL, -2);
+                    if (powerLevelBit < 0 || powerLevelBit > 3) {
+                        Toast.makeText(context, "Invalid power level", Toast.LENGTH_SHORT).show();
+                        break;
+                    }
+
+                    if (mCount == null) {
+                        mCount = new HashMap<Integer, Integer>();
+                        for (int i : mPowerLevel) {
+                            mCount.put(i, 0);
+                        }
+                        mTimer.start();
+                    }
+                    Integer t = mCount.get(powerLevelBit) + 1;
+                    mCount.put(powerLevelBit, t);
+                    mCountText.get(powerLevelBit).setText(t.toString());
+
+                    mMacText.get(powerLevelBit)
+                        .setText(intent.getStringExtra(BleScannerService.EXTRA_MAC_ADDRESS));
+                    mRssiText.get(powerLevelBit)
+                        .setText(intent.getStringExtra(BleScannerService.EXTRA_RSSI));
+                    if (Math.abs(POWER_DBM[powerLevelBit] - powerLevel) < 2) {
+                        mSetPowerText.get(powerLevelBit).setText("Valid power level");
+                    } else {
+                        mSetPowerText.get(powerLevelBit)
+                            .setText("Unknown BLe advertise tx power: " + powerLevel);
+                    }
+                    break;
+                case BleScannerService.BLE_PRIVACY_NEW_MAC_RECEIVE:
+                     Toast.makeText(context, "New MAC address detected", Toast.LENGTH_SHORT)
+                            .show();
+                     mTimerText.setTextColor(getResources().getColor(R.color.green));
+                     mTimerText.append("   Get new MAC address.");
+                     mTimer.cancel();
+                     getPassButton().setEnabled(true);
+                     break;
+            }
+        }
+    };
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerService.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerService.java
new file mode 100644
index 0000000..d3d96ac
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerService.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.bluetooth;
+
+import android.app.Service;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.le.AdvertiseSettings;
+import android.bluetooth.le.BluetoothLeScanner;
+import android.bluetooth.le.ScanCallback;
+import android.bluetooth.le.ScanFilter;
+import android.bluetooth.le.ScanSettings;
+import android.bluetooth.le.ScanRecord;
+import android.bluetooth.le.ScanResult;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.ParcelUuid;
+import android.util.Log;
+import android.widget.Toast;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+public class BleScannerService extends Service {
+
+    public static final boolean DEBUG = true;
+    public static final String TAG = "BleScannerService";
+
+    public static final int COMMAND_POWER_LEVEL = 1;
+    public static final int COMMAND_SCAN_WITH_FILTER = 2;
+    public static final int COMMAND_SCAN_WITHOUT_FILTER = 3;
+
+    public static final String BLE_PRIVACY_NEW_MAC_RECEIVE =
+            "com.android.cts.verifier.bluetooth.BLE_PRIVACY_NEW_MAC_RECEIVE";
+    public static final String BLE_MAC_ADDRESS =
+            "com.android.cts.verifier.bluetooth.BLE_MAC_ADDRESS";
+    public static final String BLE_POWER_LEVEL =
+            "com.android.cts.verifier.bluetooth.BLE_POWER_LEVEL";
+    public static final String BLE_SCAN_RESP =
+            "com.android.cts.verifier.bluetooth.BLE_SCAN_RESP";
+    public static final String BLE_SCAN_RESULT =
+            "com.android.cts.verifier.bluetooth.BLE_SCAN_RESULT";
+
+    public static final String EXTRA_COMMAND =
+            "com.google.cts.verifier.bluetooth.EXTRA_COMMAND";
+    public static final String EXTRA_MAC_ADDRESS =
+            "com.google.cts.verifier.bluetooth.EXTRA_MAC_ADDRESS";
+    public static final String EXTRA_RSSI =
+            "com.google.cts.verifier.bluetooth.EXTRA_RSSI";
+    public static final String EXTRA_POWER_LEVEL =
+            "com.google.cts.verifier.bluetooth.EXTRA_POWER_LEVEL";
+    public static final String EXTRA_POWER_LEVEL_BIT =
+            "com.google.cts.verifier.bluetooth.EXTRA_POWER_LEVEL_BIT";
+    public static final String EXTRA_UUID =
+            "com.google.cts.verifier.bluetooth.EXTRA_UUID";
+    public static final String EXTRA_DATA =
+            "com.google.cts.verifier.bluetooth.EXTRA_DATA";
+
+    private static final byte MANUFACTURER_TEST_ID = (byte)0x07;
+
+    private BluetoothManager mBluetoothManager;
+    private BluetoothAdapter mAdapter;
+    private BluetoothLeScanner mScanner;
+    private ScanCallback mCallback;
+    private Handler mHandler;
+    private String mOldMac;
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+
+        mCallback = new BLEScanCallback();
+        mHandler = new Handler();
+        mOldMac = null;
+
+        mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
+        mAdapter = mBluetoothManager.getAdapter();
+        mScanner = mAdapter.getBluetoothLeScanner();
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        if (mScanner != null) {
+            List<ScanFilter> filters = new ArrayList<ScanFilter>();
+            ScanSettings.Builder settingBuilder = new ScanSettings.Builder();
+
+            int command = intent.getIntExtra(EXTRA_COMMAND, -1);
+            switch (command) {
+                case COMMAND_POWER_LEVEL:
+                    filters.add(new ScanFilter.Builder()
+                        .setManufacturerData(MANUFACTURER_TEST_ID,
+                            new byte[]{MANUFACTURER_TEST_ID, 0})
+                        .setServiceData(new ParcelUuid(BleAdvertiserService.POWER_LEVEL_UUID),
+                            BleAdvertiserService.POWER_LEVEL_DATA,
+                            BleAdvertiserService.POWER_LEVEL_MASK)
+                        .build());
+                    settingBuilder.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY);
+                    break;
+                case COMMAND_SCAN_WITH_FILTER:
+                    mScanner.stopScan(mCallback);
+                    filters.add(new ScanFilter.Builder()
+                        .setManufacturerData(MANUFACTURER_TEST_ID,
+                            new byte[]{MANUFACTURER_TEST_ID, 0})
+                        .setServiceData(new ParcelUuid(BleAdvertiserService.SCANNABLE_UUID),
+                            BleAdvertiserService.SCANNABLE_DATA)
+                        .build());
+                    settingBuilder.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY);
+                    break;
+                case COMMAND_SCAN_WITHOUT_FILTER:
+                    mScanner.stopScan(mCallback);
+                    settingBuilder.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY);
+                    break;
+            }
+            mOldMac = null;
+            mScanner.startScan(filters, settingBuilder.build(), mCallback);
+        }
+        return START_NOT_STICKY;
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        mScanner.stopScan(mCallback);
+    }
+
+    private void showMessage(final String msg) {
+        mHandler.post(new Runnable() {
+            public void run() {
+                Toast.makeText(BleScannerService.this, msg, Toast.LENGTH_SHORT).show();
+            }
+        });
+    }
+
+    private class BLEScanCallback extends ScanCallback {
+        @Override
+        public void onScanResult(int callBackType, ScanResult result) {
+            if (callBackType != ScanSettings.CALLBACK_TYPE_ALL_MATCHES) {
+                Log.e(TAG, "onScanResult fail. callBackType is not CALLBACK_TYPE_ALL_MATCHES");
+                return;
+            }
+
+            ScanRecord record = result.getScanRecord();
+            String mac = result.getDevice().getAddress();
+            Map<ParcelUuid, byte[]> serviceData = record.getServiceData();
+
+            if (serviceData.get(new ParcelUuid(BleAdvertiserService.POWER_LEVEL_UUID)) != null) {
+                byte[] data =
+                        serviceData.get(new ParcelUuid(BleAdvertiserService.POWER_LEVEL_UUID));
+                if (data.length == 3) {
+                    Intent powerIntent = new Intent(BLE_POWER_LEVEL);
+                    powerIntent.putExtra(EXTRA_MAC_ADDRESS, result.getDevice().getAddress());
+                    powerIntent.putExtra(EXTRA_POWER_LEVEL, record.getTxPowerLevel());
+                    powerIntent.putExtra(EXTRA_RSSI, new Integer(result.getRssi()).toString());
+                    powerIntent.putExtra(EXTRA_POWER_LEVEL_BIT, (int)data[2]);
+                    sendBroadcast(powerIntent);
+
+                    // Check privacy mac.
+                    if (data[2] == AdvertiseSettings.ADVERTISE_TX_POWER_HIGH) {
+                        String newMac = result.getDevice().getAddress();
+                        if (mOldMac == null) {
+                            mOldMac = newMac;
+                        } else if (!mOldMac.equals(mac)) {
+                            mOldMac = newMac;
+                            Intent newIntent = new Intent(BLE_PRIVACY_NEW_MAC_RECEIVE);
+                            sendBroadcast(newIntent);
+                        }
+                    }
+                }
+            }
+
+            if (serviceData.get(new ParcelUuid(BleAdvertiserService.SCAN_RESP_UUID)) != null) {
+                Intent responseIntent = new Intent(BLE_SCAN_RESP);
+                sendBroadcast(responseIntent);
+            }
+
+            byte[] data = null;
+            String uuid = "";
+            if (serviceData.containsKey(new ParcelUuid(BleAdvertiserService.SCANNABLE_UUID))) {
+                uuid = BleAdvertiserService.SCANNABLE_UUID.toString();
+                data = serviceData.get(new ParcelUuid(BleAdvertiserService.SCANNABLE_UUID));
+            }
+            if (serviceData.containsKey(new ParcelUuid(BleAdvertiserService.UNSCANNABLE_UUID))) {
+                uuid = BleAdvertiserService.UNSCANNABLE_UUID.toString();
+                data = serviceData.get(new ParcelUuid(BleAdvertiserService.UNSCANNABLE_UUID));
+            }
+            if (uuid.length() > 0) {
+                Intent scanIntent = new Intent(BLE_SCAN_RESULT);
+                scanIntent.putExtra(EXTRA_UUID, uuid);
+                String dataStr = "{";
+                for (byte x : data) {
+                    dataStr = dataStr + " " + x;
+                }
+                dataStr = dataStr + "}";
+                scanIntent.putExtra(EXTRA_DATA, dataStr);
+                sendBroadcast(scanIntent);
+            }
+        }
+
+        public void onScanFailed(int errorCode) {
+            Log.e(TAG, "Scan fail. Error code: " + new Integer(errorCode).toString());
+        }
+
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerTestActivity.java
new file mode 100644
index 0000000..1f54917
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerTestActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.bluetooth;
+
+import com.android.cts.verifier.ManifestTestListAdapter;
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+import android.os.Bundle;
+
+public class BleScannerTestActivity extends PassFailButtons.TestListActivity {
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.pass_fail_list);
+        setPassFailButtonClickListeners();
+        setInfoResources(R.string.ble_scanner_test_name,
+                         R.string.ble_scanner_test_info, -1);
+        setTestListAdapter(new ManifestTestListAdapter(this, getClass().getName()));
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleServerService.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleServerService.java
index 5606041..91b3a6c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleServerService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleServerService.java
@@ -65,6 +65,8 @@
             "com.android.cts.verifier.bluetooth.BLE_DESCRIPTOR_WRITE_REQUEST";
     public static final String BLE_EXECUTE_WRITE =
             "com.android.cts.verifier.bluetooth.BLE_EXECUTE_WRITE";
+    public static final String BLE_OPEN_FAIL =
+            "com.android.cts.verifier.bluetooth.BLE_OPEN_FAIL";
 
     private static final UUID SERVICE_UUID =
             UUID.fromString("00009999-0000-1000-8000-00805f9b34fb");
@@ -90,11 +92,16 @@
         mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
         mGattServer = mBluetoothManager.openGattServer(this, mCallbacks);
         mService = createService();
-        mGattServer.addService(mService);
+        if (mGattServer != null) {
+            mGattServer.addService(mService);
+        }
         mDevice = null;
         mReliableWriteValue = null;
 
         mHandler = new Handler();
+        if (mGattServer == null) {
+            notifyOpenFail();
+        }
     }
 
     @Override
@@ -110,6 +117,9 @@
     @Override
     public void onDestroy() {
         super.onDestroy();
+        if (mGattServer == null) {
+           return;
+        }
         if (mDevice != null) mGattServer.cancelConnection(mDevice);
         mGattServer.close();
     }
@@ -126,6 +136,12 @@
         descriptor.setValue(writeValue.getBytes());
     }
 
+    private void notifyOpenFail() {
+        if (DEBUG) Log.d(TAG, "notifyOpenFail");
+        Intent intent = new Intent(BLE_OPEN_FAIL);
+        sendBroadcast(intent);
+    }
+
     private void notifyConnected() {
         if (DEBUG) Log.d(TAG, "notifyConnected");
         Intent intent = new Intent(BLE_SERVER_CONNECTED);
@@ -216,6 +232,10 @@
         TimerTask task = new TimerTask() {
             @Override
             public void run() {
+                if (mGattServer == null) {
+                    if (DEBUG) Log.d(TAG, "GattServer is null, return");
+                    return;
+                }
                 BluetoothGattCharacteristic characteristic =
                         mService.getCharacteristic(UPDATE_CHARACTERISTIC_UUID);
                 if (characteristic == null) return;
@@ -268,7 +288,11 @@
 
         @Override
         public void onCharacteristicReadRequest(BluetoothDevice device, int requestId,
-                            int offset, BluetoothGattCharacteristic characteristic) {
+                int offset, BluetoothGattCharacteristic characteristic) {
+            if (mGattServer == null) {
+                if (DEBUG) Log.d(TAG, "GattServer is null, return");
+                return;
+            }
             if (DEBUG) Log.d(TAG, "onCharacteristicReadRequest()");
 
             notifyCharacteristicReadRequest();
@@ -278,9 +302,13 @@
 
         @Override
         public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId,
-                                                 BluetoothGattCharacteristic characteristic,
-                                                 boolean preparedWrite, boolean responseNeeded,
-                                                 int offset, byte[] value) {
+                BluetoothGattCharacteristic characteristic,
+                boolean preparedWrite, boolean responseNeeded,
+                int offset, byte[] value) {
+            if (mGattServer == null) {
+                if (DEBUG) Log.d(TAG, "GattServer is null, return");
+                return;
+            }
             if (DEBUG) Log.d(TAG, "onCharacteristicWriteRequest: preparedWrite=" + preparedWrite);
 
             notifyCharacteristicWriteRequest();
@@ -293,7 +321,11 @@
 
         @Override
         public void onDescriptorReadRequest(BluetoothDevice device, int requestId,
-                                            int offset, BluetoothGattDescriptor descriptor) {
+                int offset, BluetoothGattDescriptor descriptor) {
+            if (mGattServer == null) {
+                if (DEBUG) Log.d(TAG, "GattServer is null, return");
+                return;
+            }
             if (DEBUG) Log.d(TAG, "onDescriptorReadRequest(): (descriptor == getDescriptor())="
                                   + (descriptor == getDescriptor()));
 
@@ -304,9 +336,13 @@
 
         @Override
         public void onDescriptorWriteRequest(BluetoothDevice device, int requestId,
-                                             BluetoothGattDescriptor descriptor,
-                                             boolean preparedWrite, boolean responseNeeded,
-                                             int offset,  byte[] value) {
+                BluetoothGattDescriptor descriptor,
+                boolean preparedWrite, boolean responseNeeded,
+                int offset,  byte[] value) {
+            if (mGattServer == null) {
+                if (DEBUG) Log.d(TAG, "GattServer is null, return");
+                return;
+            }
             if (DEBUG) Log.d(TAG, "onDescriptorWriteRequest(): (descriptor == getDescriptor())="
                                   + (descriptor == getDescriptor()));
 
@@ -318,6 +354,10 @@
 
         @Override
         public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {
+            if (mGattServer == null) {
+                if (DEBUG) Log.d(TAG, "GattServer is null, return");
+                return;
+            }
             if (DEBUG) Log.d(TAG, "onExecuteWrite");
             if (execute) {
                 notifyExecuteWrite();
@@ -326,4 +366,5 @@
             }
         }
     };
-}
\ No newline at end of file
+}
+
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleServerStartActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleServerStartActivity.java
index ec31fde..e8e35d5 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleServerStartActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleServerStartActivity.java
@@ -34,10 +34,10 @@
 import android.widget.ImageView;
 import android.widget.ListView;
 import android.widget.TextView;
+import android.widget.Toast;
 
 public class BleServerStartActivity extends PassFailButtons.Activity {
 
-    private List<Test> mTestList;
     private TestAdapter mTestAdapter;
     private int mAllPassed;
 
@@ -50,9 +50,7 @@
                          R.string.ble_server_start_info, -1);
         getPassButton().setEnabled(false);
 
-        mTestList = setupTestList();
-        mTestAdapter = new TestAdapter(this, mTestList);
-
+        mTestAdapter = new TestAdapter(this, setupTestList());
         ListView listView = (ListView) findViewById(R.id.ble_server_tests);
         listView.setAdapter(mTestAdapter);
 
@@ -73,6 +71,7 @@
         filter.addAction(BleServerService.BLE_DESCRIPTOR_WRITE_REQUEST);
         filter.addAction(BleServerService.BLE_EXECUTE_WRITE);
         filter.addAction(BleServerService.BLE_SERVER_DISCONNECTED);
+        filter.addAction(BleServerService.BLE_OPEN_FAIL);
         registerReceiver(onBroadcast, filter);
     }
 
@@ -88,109 +87,59 @@
         stopService(new Intent(this, BleServerService.class));
     }
 
-    private List<Test> setupTestList() {
-        ArrayList<Test> testList = new ArrayList<Test>();
-        testList.add(new Test(R.string.ble_server_add_service));
-        testList.add(new Test(R.string.ble_server_receiving_connect));
-        testList.add(new Test(R.string.ble_server_read_characteristic));
-        testList.add(new Test(R.string.ble_server_write_characteristic));
-        testList.add(new Test(R.string.ble_server_read_descriptor));
-        testList.add(new Test(R.string.ble_server_write_descriptor));
-        testList.add(new Test(R.string.ble_server_reliable_write));
-        testList.add(new Test(R.string.ble_server_receiving_disconnect));
+    private List<Integer> setupTestList() {
+        ArrayList<Integer> testList = new ArrayList<Integer>();
+        testList.add(R.string.ble_server_add_service);
+        testList.add(R.string.ble_server_receiving_connect);
+        testList.add(R.string.ble_server_read_characteristic);
+        testList.add(R.string.ble_server_write_characteristic);
+        testList.add(R.string.ble_server_read_descriptor);
+        testList.add(R.string.ble_server_write_descriptor);
+        testList.add(R.string.ble_server_reliable_write);
+        testList.add(R.string.ble_server_receiving_disconnect);
         return testList;
     }
 
-    class Test {
-        private boolean passed;
-        private int instructions;
-
-        private Test(int instructions) {
-            passed = false;
-            this.instructions = instructions;
-        }
-    }
-
     private BroadcastReceiver onBroadcast = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
             if (action == BleServerService.BLE_SERVICE_ADDED) {
-                mTestList.get(0).passed = true;
+                mTestAdapter.setTestPass(0);
                 mAllPassed |= 0x01;
             } else if (action == BleServerService.BLE_SERVER_CONNECTED) {
-                mTestList.get(1).passed = true;
+                mTestAdapter.setTestPass(1);
                 mAllPassed |= 0x02;
             } else if (action == BleServerService.BLE_CHARACTERISTIC_READ_REQUEST) {
-                mTestList.get(2).passed = true;
+                mTestAdapter.setTestPass(2);
                 mAllPassed |= 0x04;
             } else if (action == BleServerService.BLE_CHARACTERISTIC_WRITE_REQUEST) {
-                mTestList.get(3).passed = true;
+                mTestAdapter.setTestPass(3);
                 mAllPassed |= 0x08;
             } else if (action == BleServerService.BLE_DESCRIPTOR_READ_REQUEST) {
-                mTestList.get(4).passed = true;
+                mTestAdapter.setTestPass(4);
                 mAllPassed |= 0x10;
             } else if (action == BleServerService.BLE_DESCRIPTOR_WRITE_REQUEST) {
-                mTestList.get(5).passed = true;
+                mTestAdapter.setTestPass(5);
                 mAllPassed |= 0x20;
             } else if (action == BleServerService.BLE_EXECUTE_WRITE) {
-                mTestList.get(6).passed = true;
+                mTestAdapter.setTestPass(6);
                 mAllPassed |= 0x40;
             } else if (action == BleServerService.BLE_SERVER_DISCONNECTED) {
-                mTestList.get(7).passed = true;
+                mTestAdapter.setTestPass(7);
                 mAllPassed |= 0x80;
+            } else if (action == BleServerService.BLE_OPEN_FAIL) {
+                setTestResultAndFinish(false);
+                runOnUiThread(new Runnable() {
+                    @Override
+                    public void run() {
+                        Toast.makeText(BleServerStartActivity.this, "Cannot open GattService",
+                                Toast.LENGTH_SHORT).show();
+                    }
+                });
             }
             mTestAdapter.notifyDataSetChanged();
             if (mAllPassed == 0xFF) getPassButton().setEnabled(true);
         }
     };
-
-    class TestAdapter extends BaseAdapter {
-        Context context;
-        List<Test> tests;
-        LayoutInflater inflater;
-
-        public TestAdapter(Context context, List<Test> tests) {
-            this.context = context;
-            inflater = LayoutInflater.from(context);
-            this.tests = tests;
-        }
-
-        @Override
-        public int getCount() {
-            return tests.size();
-        }
-
-        @Override
-        public Object getItem(int position) {
-            return tests.get(position);
-        }
-
-        @Override
-        public long getItemId(int position) {
-            return position;
-        }
-
-        @Override
-        public View getView(int position, View convertView, ViewGroup parent) {
-            ViewGroup vg;
-
-            if (convertView != null) {
-                vg = (ViewGroup) convertView;
-            } else {
-                vg = (ViewGroup) inflater.inflate(R.layout.ble_server_start_item, null);
-            }
-
-            Test test = tests.get(position);
-            if (test.passed) {
-                ((ImageView) vg.findViewById(R.id.status)).setImageResource(R.drawable.fs_good);
-            } else {
-                ((ImageView) vg.findViewById(R.id.status)).
-                                setImageResource(R.drawable.fs_indeterminate);
-            }
-            ((TextView) vg.findViewById(R.id.instructions)).setText(test.instructions);
-
-            return vg;
-        }
-    }
-}
\ No newline at end of file
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/TestAdapter.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/TestAdapter.java
new file mode 100644
index 0000000..631fe36
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/TestAdapter.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.bluetooth;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+class TestAdapter extends BaseAdapter {
+    Context context;
+    List<Test> tests;
+    LayoutInflater inflater;
+
+    private class Test {
+        private boolean mPassed;
+        private final int mInstructions;
+
+        protected Test(int instructions) {
+            this.mPassed = false;
+            this.mInstructions = instructions;
+        }
+    }
+
+    public TestAdapter(Context context, List<Integer> testInstructions) {
+        this.context = context;
+        inflater = LayoutInflater.from(context);
+        this.tests = new ArrayList<Test>();
+        for (int t : testInstructions) {
+            this.tests.add(new Test(t));
+        }
+    }
+
+    @Override
+    public int getCount() {
+        return tests.size();
+    }
+
+    @Override
+    public Object getItem(int position) {
+        return tests.get(position);
+    }
+
+    public void setTestPass(int position) {
+        tests.get(position).mPassed = true;
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return position;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        ViewGroup vg;
+
+        if (convertView != null) {
+            vg = (ViewGroup) convertView;
+        } else {
+            vg = (ViewGroup) inflater.inflate(R.layout.ble_server_start_item, null);
+        }
+
+        Test test = tests.get(position);
+        if (test.mPassed) {
+            ((ImageView) vg.findViewById(R.id.status)).setImageResource(R.drawable.fs_good);
+        } else {
+            ((ImageView) vg.findViewById(R.id.status)).
+                            setImageResource(R.drawable.fs_indeterminate);
+        }
+        ((TextView) vg.findViewById(R.id.instructions)).setText(test.mInstructions);
+
+        return vg;
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
old mode 100644
new mode 100755
index d68d1da..d325b65
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
@@ -18,7 +18,6 @@
 import com.android.cts.verifier.PassFailButtons;
 import com.android.cts.verifier.R;
 
-import android.app.Activity;
 import android.app.AlertDialog;
 import android.graphics.Bitmap;
 import android.graphics.Color;
@@ -34,19 +33,22 @@
 import android.os.Handler;
 import android.util.Log;
 import android.util.SparseArray;
+import android.view.Menu;
+import android.view.MenuItem;
 import android.view.View;
 import android.view.Surface;
 import android.view.TextureView;
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
+import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.Spinner;
+import android.widget.Toast;
 
 import java.io.IOException;
-import java.lang.InterruptedException;
 import java.lang.Math;
-import java.lang.Thread;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.Comparator;
 import java.util.List;
 import java.util.TreeSet;
@@ -100,11 +102,22 @@
     private TreeSet<String> mTestedCombinations = new TreeSet<String>();
     private TreeSet<String> mUntestedCombinations = new TreeSet<String>();
 
+    private int mAllCombinationsSize = 0;
+
+    // Menu to show the test progress
+    private static final int MENU_ID_PROGRESS = Menu.FIRST + 1;
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
         setContentView(R.layout.cf_main);
+
+        mAllCombinationsSize = calcAllCombinationsSize();
+
+        // disable "Pass" button until all combinations are tested
+        setPassButtonEnabled(false);
+
         setPassFailButtonClickListeners();
         setInfoResources(R.string.camera_format, R.string.cf_info, -1);
 
@@ -161,6 +174,36 @@
     }
 
     @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        menu.add(Menu.NONE, MENU_ID_PROGRESS, Menu.NONE, "Current Progress");
+        return super.onCreateOptionsMenu(menu);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        boolean ret = true;
+        switch (item.getItemId()) {
+        case MENU_ID_PROGRESS:
+            showCombinationsDialog();
+            ret = true;
+            break;
+        default:
+            ret = super.onOptionsItemSelected(item);
+            break;
+        }
+        return ret;
+    }
+
+    private void showCombinationsDialog() {
+        AlertDialog.Builder builder =
+                new AlertDialog.Builder(CameraFormatsActivity.this);
+        builder.setMessage(getTestDetails())
+                .setTitle("Current Progress")
+                .setPositiveButton("OK", null);
+        builder.show();
+    }
+
+    @Override
     public void onResume() {
         super.onResume();
 
@@ -299,9 +342,10 @@
             new ArrayAdapter<String>(
                 this, R.layout.cf_format_list_item, availableSizeNames));
 
-        // Get preview formats
+        // Get preview formats, removing duplicates
 
-        mPreviewFormats =  p.getSupportedPreviewFormats();
+        HashSet<Integer> formatSet = new HashSet<>(p.getSupportedPreviewFormats());
+        mPreviewFormats = new ArrayList<Integer>(formatSet);
 
         String[] availableFormatNames = new String[mPreviewFormats.size()];
         for (int i = 0; i < mPreviewFormats.size(); i++) {
@@ -526,6 +570,12 @@
                             + "\n";
                     mUntestedCombinations.remove(combination);
                     mTestedCombinations.add(combination);
+
+                    displayToast(combination.replace("\n", ""));
+
+                    if (mTestedCombinations.size() == mAllCombinationsSize) {
+                        setPassButtonEnabled(true);
+                    }
                 }
             }
             mProcessInProgress = false;
@@ -533,6 +583,36 @@
 
     }
 
+    private void setPassButtonEnabled(boolean enabled) {
+        ImageButton pass_button = (ImageButton) findViewById(R.id.pass_button);
+        pass_button.setEnabled(enabled);
+    }
+
+    private int calcAllCombinationsSize() {
+        int allCombinationsSize = 0;
+        int numCameras = Camera.getNumberOfCameras();
+
+        for (int i = 0; i<numCameras; i++) {
+            // must release a Camera object before a new Camera object is created
+            shutdownCamera();
+
+            mCamera = Camera.open(i);
+            Camera.Parameters p = mCamera.getParameters();
+
+            HashSet<Integer> formatSet = new HashSet<>(p.getSupportedPreviewFormats());
+
+            allCombinationsSize +=
+                    p.getSupportedPreviewSizes().size() *   // resolutions
+                    formatSet.size();  // unique formats
+        }
+
+        return allCombinationsSize;
+    }
+
+    private void displayToast(String combination) {
+        Toast.makeText(this, "\"" + combination + "\"\n" + " has been tested.", Toast.LENGTH_LONG).show();
+    }
+
     public void onPreviewFrame(byte[] data, Camera camera) {
         if (mProcessInProgress || mState != STATE_PREVIEW) return;
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java
index 05013ed..e5af6ba 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java
@@ -30,6 +30,7 @@
 import android.os.PowerManager;
 import android.os.PowerManager.WakeLock;
 import android.util.Log;
+import android.view.Surface;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
 import android.view.View;
@@ -68,7 +69,7 @@
     private List<SelectableResolution> mSupportedResolutions;
     private ArrayAdapter<SelectableResolution> mAdapter;
 
-    private int mCameraId;
+    private SelectableResolution mSelectedResolution;
     private Camera mCamera;
     private Size mSurfaceSize;
     private boolean mCameraInitialized = false;
@@ -76,6 +77,8 @@
     private int mResolutionSpinnerIndex = -1;
     private WakeLock mWakeLock;
     private long shutterStartTime;
+    private int mPreviewOrientation;
+    private int mJpegOrientation;
 
     private ArrayList<Integer> mPreviewSizeCamerasToProcess = new ArrayList<Integer>();
 
@@ -164,18 +167,13 @@
                     AdapterView<?> parent, View view, int position, long id) {
                 if (mSupportedResolutions != null) {
                     SelectableResolution resolution = mSupportedResolutions.get(position);
-
-                    switchToCamera(resolution.cameraId, false);
-
-                    Camera.Parameters params = mCamera.getParameters();
-                    params.setPictureSize(resolution.width, resolution.height);
-                    mCamera.setParameters(params);
+                    switchToCamera(resolution, false);
 
                     // It should be guaranteed that the FOV is correctly updated after setParameters().
                     mReportedFovPrePictureTaken = mCamera.getParameters().getHorizontalViewAngle();
 
                     mResolutionSpinnerIndex = position;
-                    initializeCamera();
+                    startPreview();
                 }
             }
 
@@ -375,7 +373,7 @@
                     public void onCancel(DialogInterface arg0) {
                         // User cancelled preview size selection.
                         mPreviewSizes = null;
-                        switchToCamera(mCameraId, true);
+                        switchToCamera(mSelectedResolution, true);
                     }
                 }).
                 setSingleChoiceItems(choices, 0, new DialogInterface.OnClickListener() {
@@ -388,7 +386,7 @@
 
                         if (mPreviewSizeCamerasToProcess.isEmpty()) {
                             // We're done, re-initialize camera.
-                            switchToCamera(mCameraId, true);
+                            switchToCamera(mSelectedResolution, true);
                         } else {
                             // Process other cameras.
                             showNextDialogToChoosePreviewSize();
@@ -399,6 +397,10 @@
     }
 
     private void initializeCamera() {
+        initializeCamera(true);
+    }
+
+    private void initializeCamera(boolean startPreviewAfterInit) {
         if (mCamera == null || mSurfaceHolder.getSurface() == null) {
             return;
         }
@@ -410,38 +412,43 @@
             Toast.makeText(this, t.getMessage(), Toast.LENGTH_LONG).show();
             return;
         }
+
+        calculateOrientations(this, mSelectedResolution.cameraId, mCamera);
         Camera.Parameters params = setCameraParams(mCamera);
 
         // Either use chosen preview size for current camera or automatically
         // choose preview size based on view dimensions.
-        Size selectedPreviewSize = (mPreviewSizes != null) ? mPreviewSizes[mCameraId] :
+        Size selectedPreviewSize = (mPreviewSizes != null) ? mPreviewSizes[mSelectedResolution.cameraId] :
             getBestPreviewSize(mSurfaceSize.width, mSurfaceSize.height, params);
         if (selectedPreviewSize != null) {
             params.setPreviewSize(selectedPreviewSize.width, selectedPreviewSize.height);
             mCamera.setParameters(params);
             mCameraInitialized = true;
         }
-        startPreview();
+
+        if (startPreviewAfterInit) {
+          startPreview();
+        }
     }
 
     private void startPreview() {
         if (mCameraInitialized && mCamera != null) {
+            mCamera.setDisplayOrientation(mPreviewOrientation);
             mCamera.startPreview();
             mPreviewActive = true;
         }
     }
 
-    private void switchToCamera(int cameraId, boolean initializeCamera) {
+    private void switchToCamera(SelectableResolution resolution, boolean startPreview) {
         if (mCamera != null) {
             mCamera.stopPreview();
             mCamera.release();
         }
-        mCameraId = cameraId;
-        mCamera = Camera.open(cameraId);
 
-        if (initializeCamera){
-          initializeCamera();
-        }
+        mSelectedResolution = resolution;
+        mCamera = Camera.open(mSelectedResolution.cameraId);
+
+        initializeCamera(startPreview);
     }
 
     /**
@@ -470,14 +477,16 @@
      * Set the common camera parameters on the given camera and returns the
      * parameter object for further modification, if needed.
      */
-    private static Camera.Parameters setCameraParams(Camera camera) {
+    private Camera.Parameters setCameraParams(Camera camera) {
         // The picture size is taken and set from the spinner selection
         // callback.
         Camera.Parameters params = camera.getParameters();
         params.setJpegThumbnailSize(0, 0);
         params.setJpegQuality(100);
+        params.setRotation(mJpegOrientation);
         params.setFocusMode(getFocusMode(camera));
         params.setZoom(0);
+        params.setPictureSize(mSelectedResolution.width, mSelectedResolution.height);
         return params;
     }
 
@@ -501,4 +510,28 @@
         }
         return result;
     }
+
+    private void calculateOrientations(Activity activity,
+            int cameraId, android.hardware.Camera camera) {
+        android.hardware.Camera.CameraInfo info =
+                new android.hardware.Camera.CameraInfo();
+        android.hardware.Camera.getCameraInfo(cameraId, info);
+        int rotation = activity.getWindowManager().getDefaultDisplay()
+                .getRotation();
+        int degrees = 0;
+        switch (rotation) {
+            case Surface.ROTATION_0: degrees = 0; break;
+            case Surface.ROTATION_90: degrees = 90; break;
+            case Surface.ROTATION_180: degrees = 180; break;
+            case Surface.ROTATION_270: degrees = 270; break;
+        }
+
+        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
+            mJpegOrientation = (info.orientation + degrees) % 360;
+            mPreviewOrientation = (360 - mJpegOrientation) % 360;  // compensate the mirror
+        } else {  // back-facing
+            mJpegOrientation = (info.orientation - degrees + 360) % 360;
+            mPreviewOrientation = mJpegOrientation;
+        }
+    }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/intents/CameraIntentsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/intents/CameraIntentsActivity.java
index e48ce93..9204de3 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/intents/CameraIntentsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/intents/CameraIntentsActivity.java
@@ -19,31 +19,20 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.ImageFormat;
-import android.graphics.Matrix;
 import android.hardware.Camera;
 import android.os.Bundle;
-import android.os.Handler;
 import android.util.Log;
 import android.view.SurfaceHolder;
-import android.view.SurfaceView;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.LinearLayout.LayoutParams;
+import android.widget.ImageButton;
 import android.widget.TextView;
 
 import com.android.cts.verifier.PassFailButtons;
 import com.android.cts.verifier.R;
 import com.android.cts.verifier.TestResult;
 
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.List;
 import java.util.TreeSet;
 
 /**
@@ -88,8 +77,8 @@
         Camera.ACTION_NEW_VIDEO
     };
 
-    private Button mPassButton;
-    private Button mFailButton;
+    private ImageButton mPassButton;
+    private ImageButton mFailButton;
     private Button mStartTestButton;
 
     private int mState = STATE_OFF;
@@ -212,8 +201,8 @@
         setPassFailButtonClickListeners();
         setInfoResources(R.string.camera_intents, R.string.ci_info, -1);
 
-        mPassButton         = (Button) findViewById(R.id.pass_button);
-        mFailButton         = (Button) findViewById(R.id.fail_button);
+        mPassButton         = (ImageButton) findViewById(R.id.pass_button);
+        mFailButton         = (ImageButton) findViewById(R.id.fail_button);
         mStartTestButton  = (Button) findViewById(R.id.start_test_button);
         mStartTestButton.setOnClickListener(this);
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/orientation/CameraOrientationActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/orientation/CameraOrientationActivity.java
index b970e40..273d78a 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/orientation/CameraOrientationActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/orientation/CameraOrientationActivity.java
@@ -27,6 +27,7 @@
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.Button;
+import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.LinearLayout.LayoutParams;
 import android.widget.TextView;
@@ -55,8 +56,8 @@
     private static final int NUM_ORIENTATIONS = 4;
     private static final String STAGE_INDEX_EXTRA = "stageIndex";
 
-    private Button mPassButton;
-    private Button mFailButton;
+    private ImageButton mPassButton;
+    private ImageButton mFailButton;
     private Button mTakePictureButton;
 
     private SurfaceView mCameraView;
@@ -85,8 +86,8 @@
         setInfoResources(R.string.camera_orientation, R.string.co_info, -1);
         mNumCameras = Camera.getNumberOfCameras();
 
-        mPassButton         = (Button) findViewById(R.id.pass_button);
-        mFailButton         = (Button) findViewById(R.id.fail_button);
+        mPassButton         = (ImageButton) findViewById(R.id.pass_button);
+        mFailButton         = (ImageButton) findViewById(R.id.fail_button);
         mTakePictureButton  = (Button) findViewById(R.id.take_picture_button);
         mFormatView         = (ImageView) findViewById(R.id.format_view);
         mCameraView         = (SurfaceView) findViewById(R.id.camera_view);
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..0a0e830 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
@@ -35,6 +35,7 @@
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
 import android.widget.Button;
+import android.widget.ImageButton;
 import android.widget.Spinner;
 import android.widget.TextView;
 import android.widget.VideoView;
@@ -69,6 +70,7 @@
     private int mPreviewTexWidth;
     private int mPreviewTexHeight;
     private int mPreviewRotation;
+    private int mVideoRotation;
 
     private VideoView mPlaybackView;
 
@@ -89,8 +91,8 @@
     private boolean isRecording = false;
     private boolean isPlayingBack = false;
     private Button captureButton;
-    private Button mPassButton;
-    private Button mFailButton;
+    private ImageButton mPassButton;
+    private ImageButton mFailButton;
 
     private TextView mStatusLabel;
 
@@ -161,7 +163,10 @@
         // Step 5: set preview output
         // This is not necessary since preview has been taken care of
 
-        // Step 6: prepare configured MediaRecorder
+        // Step 6: set orientation hint
+        mMediaRecorder.setOrientationHint(mVideoRotation);
+
+        // Step 7: prepare configured MediaRecorder
         try {
             mMediaRecorder.prepare();
         } catch (IOException e) {
@@ -204,8 +209,8 @@
         mPlaybackView.setOnCompletionListener(mPlaybackViewListener);
 
         captureButton = (Button) findViewById(R.id.record_button);
-        mPassButton = (Button) findViewById(R.id.pass_button);
-        mFailButton = (Button) findViewById(R.id.fail_button);
+        mPassButton = (ImageButton) findViewById(R.id.pass_button);
+        mFailButton = (ImageButton) findViewById(R.id.fail_button);
         mPassButton.setEnabled(false);
         mFailButton.setEnabled(true);
 
@@ -449,7 +454,8 @@
                 CamcorderProfile.QUALITY_CIF,
                 CamcorderProfile.QUALITY_480P,
                 CamcorderProfile.QUALITY_720P,
-                CamcorderProfile.QUALITY_1080P
+                CamcorderProfile.QUALITY_1080P,
+                CamcorderProfile.QUALITY_2160P
         };
 
         String[] nameArray = {
@@ -460,7 +466,8 @@
                 "CIF",
                 "480P",
                 "720P",
-                "1080P"
+                "1080P",
+                "2160P"
         };
 
         ArrayList<VideoSizeNamePair> availableSizes =
@@ -499,7 +506,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>();
@@ -640,10 +648,11 @@
         }
 
         if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
-            mPreviewRotation = (info.orientation + degrees) % 360;
-            mPreviewRotation = (360 - mPreviewRotation) % 360;  // compensate the mirror
+            mVideoRotation = (info.orientation + degrees) % 360;
+            mPreviewRotation = (360 - mVideoRotation) % 360;  // compensate the mirror
         } else {  // back-facing
-            mPreviewRotation = (info.orientation - degrees + 360) % 360;
+            mVideoRotation = (info.orientation - degrees + 360) % 360;
+            mPreviewRotation = mVideoRotation;
         }
         if (mPreviewRotation != 0 && mPreviewRotation != 180) {
             Log.w(TAG,
@@ -731,10 +740,7 @@
                     public void onClick(DialogInterface dialog, int which) {
                         switch (which) {
                             case DialogInterface.BUTTON_POSITIVE:
-                                PassFailButtons.setTestResultAndFinish(CameraVideoActivity.this,
-                                        CameraVideoActivity.this.getTestId(),
-                                        CameraVideoActivity.this.getTestDetails(),
-                                        /* passed */false);
+                                setTestResultAndFinish(/* passed */false);
                                 break;
                             case DialogInterface.BUTTON_NEGATIVE:
                                 break;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureSummaryActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureSummaryActivity.java
index 581121e..74a5317 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureSummaryActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureSummaryActivity.java
@@ -169,6 +169,10 @@
     };
 
     public static final Feature[] ALL_JELLY_BEAN_FEATURES = {
+            // Required features in prior releases that became optional
+            new Feature(PackageManager.FEATURE_FAKETOUCH, false),
+
+            //new feature in JB
             new Feature(PackageManager.FEATURE_TELEVISION, false),
     };
 
@@ -190,6 +194,37 @@
 
     public static final Feature[] ALL_KITKAT_WATCH_FEATURES = {
             new Feature(PackageManager.FEATURE_SENSOR_HEART_RATE, false),
+            new Feature(PackageManager.FEATURE_BACKUP, false),
+            new Feature(PackageManager.FEATURE_PRINTING, false),
+            new Feature(PackageManager.FEATURE_WATCH, false),
+            new Feature(PackageManager.FEATURE_WEBVIEW, false),
+            new Feature(PackageManager.FEATURE_CAMERA_EXTERNAL, false),
+    };
+
+    public static final Feature[] ALL_LOLLIPOP_FEATURES = {
+            // New features in L
+            new Feature(PackageManager.FEATURE_AUDIO_OUTPUT, false),
+            new Feature(PackageManager.FEATURE_CAMERA_CAPABILITY_MANUAL_POST_PROCESSING, false),
+            new Feature(PackageManager.FEATURE_CAMERA_CAPABILITY_MANUAL_SENSOR, false),
+            new Feature(PackageManager.FEATURE_CAMERA_CAPABILITY_RAW, false),
+            new Feature(PackageManager.FEATURE_CAMERA_LEVEL_FULL, false),
+            new Feature(PackageManager.FEATURE_CONNECTION_SERVICE, false),
+            new Feature(PackageManager.FEATURE_GAMEPAD, false),
+            new Feature(PackageManager.FEATURE_LEANBACK, false),
+            new Feature(PackageManager.FEATURE_LIVE_TV, false),
+            new Feature(PackageManager.FEATURE_MANAGED_USERS, false),
+            new Feature(PackageManager.FEATURE_OPENGLES_EXTENSION_PACK, false),
+            new Feature(PackageManager.FEATURE_SECURELY_REMOVES_USERS, false),
+            new Feature(PackageManager.FEATURE_SENSOR_AMBIENT_TEMPERATURE, false),
+            new Feature(PackageManager.FEATURE_SENSOR_HEART_RATE_ECG, false),
+            new Feature(PackageManager.FEATURE_SENSOR_RELATIVE_HUMIDITY, false),
+            new Feature(PackageManager.FEATURE_VERIFIED_BOOT, false),
+
+            // New hidden features in L
+            new Feature("android.hardware.ethernet", false),
+            new Feature("android.hardware.hdmi.cec", false),
+            new Feature("android.software.leanback_only", false),
+            new Feature("android.software.voice_recognizers", false),
     };
 
     @Override
@@ -222,6 +257,9 @@
 
         // add features from latest to last so that the latest requirements are put in the set first
         int apiVersion = Build.VERSION.SDK_INT;
+        if (apiVersion >= Build.VERSION_CODES.LOLLIPOP) {
+            Collections.addAll(features, ALL_LOLLIPOP_FEATURES);
+        }
         if (apiVersion >= Build.VERSION_CODES.KITKAT_WATCH) {
             Collections.addAll(features, ALL_KITKAT_WATCH_FEATURES);
         }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/jobscheduler/ChargingConstraintTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/jobscheduler/ChargingConstraintTestActivity.java
new file mode 100644
index 0000000..2a94ace
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/jobscheduler/ChargingConstraintTestActivity.java
@@ -0,0 +1,184 @@
+package com.android.cts.verifier.jobscheduler;
+
+import android.annotation.TargetApi;
+import android.app.job.JobInfo;
+import android.app.job.JobScheduler;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.widget.Button;
+import android.widget.ImageView;
+
+import com.android.cts.verifier.R;
+
+/**
+ *  This activity runs the following tests:
+ *     - Ask the tester to unplug the phone, and verify that jobs with charging constraints will
+ *      not run.
+ *     - Ask the tester to ensure the phone is plugged in, and verify that jobs with charging
+ *      constraints are run.
+ */
+@TargetApi(21)
+public class ChargingConstraintTestActivity extends ConstraintTestActivity {
+
+    private static final int ON_CHARGING_JOB_ID =
+            ChargingConstraintTestActivity.class.hashCode() + 0;
+    private static final int OFF_CHARGING_JOB_ID =
+            ChargingConstraintTestActivity.class.hashCode() + 1;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // Set up the UI.
+        setContentView(R.layout.js_charging);
+        setPassFailButtonClickListeners();
+        setInfoResources(R.string.js_charging_test, R.string.js_charging_instructions, -1);
+        mStartButton = (Button) findViewById(R.id.js_charging_start_test_button);
+
+        mJobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
+
+        // Register receiver for connected/disconnected power events.
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(Intent.ACTION_POWER_CONNECTED);
+        intentFilter.addAction(Intent.ACTION_POWER_DISCONNECTED);
+
+        registerReceiver(mChargingChangedReceiver, intentFilter);
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        unregisterReceiver(mChargingChangedReceiver);
+    }
+
+    @Override
+    public void startTestImpl() {
+        new TestDeviceUnpluggedConstraint().execute();
+    }
+
+    private BroadcastReceiver mChargingChangedReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (Intent.ACTION_POWER_DISCONNECTED.equals(intent.getAction())) {
+                mDeviceUnpluggedTestPassed = false;
+                mStartButton.setEnabled(true);
+            } else if (Intent.ACTION_POWER_CONNECTED.equals(intent.getAction())) {
+                mStartButton.setEnabled(false);
+                if (mDeviceUnpluggedTestPassed) {
+                    continueTest();
+                }
+            }
+        }
+    };
+
+    /** Simple state boolean we use to determine whether to continue with the second test. */
+    private boolean mDeviceUnpluggedTestPassed = false;
+
+    /**
+     * After the first test has passed, and preconditions are met, this will kick off the second
+     * test.
+     * See {@link #startTest(android.view.View)}.
+     */
+    private void continueTest() {
+        new TestDevicePluggedInConstraint().execute();
+    }
+
+    /**
+     * Test blocks and can't be run on the main thread.
+     */
+    private void testChargingConstraintFails_notCharging() {
+        mTestEnvironment.setUp();
+
+        mTestEnvironment.setExpectedExecutions(0);
+        JobInfo runOnCharge = new JobInfo.Builder(OFF_CHARGING_JOB_ID, mMockComponent)
+                .setRequiresCharging(true)
+                .build();
+        mJobScheduler.schedule(runOnCharge);
+
+        // Send intent to kick off any jobs. This will be a no-op as the device is not plugged in;
+        // the JobScheduler tracks charging state independently.
+        sendBroadcastAndBlockForResult(EXPEDITE_STABLE_CHARGING);
+
+        boolean testPassed;
+        try {
+            testPassed = mTestEnvironment.awaitTimeout();
+        } catch (InterruptedException e) {
+            testPassed = false;
+        }
+        mDeviceUnpluggedTestPassed = testPassed;
+        runOnUiThread(new ChargingConstraintTestResultRunner(OFF_CHARGING_JOB_ID, testPassed));
+    }
+
+    /**
+     * Test blocks and can't be run on the main thread.
+     */
+    private void testChargingConstraintExecutes_onCharging() {
+        mTestEnvironment.setUp();
+
+        JobInfo delayConstraintAndUnexpiredDeadline =
+                new JobInfo.Builder(ON_CHARGING_JOB_ID, mMockComponent)
+                        .setRequiresCharging(true)
+                        .build();
+
+        mTestEnvironment.setExpectedExecutions(1);
+        mJobScheduler.schedule(delayConstraintAndUnexpiredDeadline);
+
+        // Force the JobScheduler to consider any jobs that have charging constraints.
+        sendBroadcast(EXPEDITE_STABLE_CHARGING);
+
+        boolean testPassed;
+        try {
+            testPassed = mTestEnvironment.awaitExecution();
+        } catch (InterruptedException e) {
+            testPassed = false;
+        }
+        runOnUiThread(new ChargingConstraintTestResultRunner(ON_CHARGING_JOB_ID, testPassed));
+    }
+
+    /** Run test for when the <bold>device is not connected to power.</bold>. */
+    private class TestDeviceUnpluggedConstraint extends AsyncTask<Void, Void, Void> {
+        @Override
+        protected Void doInBackground(Void... voids) {
+            testChargingConstraintFails_notCharging();
+
+            // Do not call notifyTestCompleted here, as we're still waiting for the user to put
+            // the device back on charge to continue with TestDevicePluggedInConstraint.
+            return null;
+        }
+    }
+
+    /** Run test for when the <bold>device is connected to power.</bold> */
+    private class TestDevicePluggedInConstraint extends AsyncTask<Void, Void, Void> {
+        @Override
+        protected Void doInBackground(Void... voids) {
+            testChargingConstraintExecutes_onCharging();
+
+            notifyTestCompleted();
+            return null;
+        }
+    }
+
+    private class ChargingConstraintTestResultRunner extends TestResultRunner {
+        ChargingConstraintTestResultRunner(int jobId, boolean testPassed) {
+            super(jobId, testPassed);
+        }
+
+        @Override
+        public void run() {
+            ImageView view;
+            if (mJobId == OFF_CHARGING_JOB_ID) {
+                view = (ImageView) findViewById(R.id.charging_off_test_image);
+            } else if (mJobId == ON_CHARGING_JOB_ID) {
+                view = (ImageView) findViewById(R.id.charging_on_test_image);
+            } else {
+                noteInvalidTest();
+                return;
+            }
+            view.setImageResource(mTestPassed ? R.drawable.fs_good : R.drawable.fs_error);
+        }
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/jobscheduler/ConnectivityConstraintTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/jobscheduler/ConnectivityConstraintTestActivity.java
new file mode 100644
index 0000000..e97539d
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/jobscheduler/ConnectivityConstraintTestActivity.java
@@ -0,0 +1,184 @@
+package com.android.cts.verifier.jobscheduler;
+
+import android.annotation.TargetApi;
+import android.app.job.JobInfo;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.util.Log;
+import android.widget.Button;
+import android.widget.ImageView;
+
+import com.android.cts.verifier.R;
+
+/**
+ * The majority of the connectivity constraints are done in the device-side test app
+ * android.jobscheduler.cts.deviceside. However a manual tester is required to completely turn off
+ * connectivity on the device in order to verify that jobs with connectivity constraints will not
+ * run in the absence of an internet connection.
+ */
+@TargetApi(21)
+public class ConnectivityConstraintTestActivity extends ConstraintTestActivity {
+    private static final String TAG = "ConnectivityConstraintTestActivity";
+    private static final int ANY_CONNECTIVITY_JOB_ID =
+            ConnectivityConstraintTestActivity.class.hashCode() + 0;
+    private static final int UNMETERED_CONNECTIVITY_JOB_ID =
+            ConnectivityConstraintTestActivity.class.hashCode() + 1;
+    private static final int NO_CONNECTIVITY_JOB_ID =
+            ConnectivityConstraintTestActivity.class.hashCode() + 2;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // Set up the UI.
+        setContentView(R.layout.js_connectivity);
+        setPassFailButtonClickListeners();
+        setInfoResources(R.string.js_connectivity_test, R.string.js_connectivity_instructions, -1);
+        mStartButton = (Button) findViewById(R.id.js_connectivity_start_test_button);
+
+        // Disable test start if there is data connectivity.
+        mStartButton.setEnabled(isDataUnavailable());
+        // Register receiver to listen for connectivity changes.
+        IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
+        registerReceiver(mConnectivityChangedReceiver, intentFilter);
+
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        unregisterReceiver(mConnectivityChangedReceiver);
+    }
+
+    @Override
+    protected void startTestImpl() {
+        new TestConnectivityConstraint().execute();
+    }
+
+    /** Ensure that there's no connectivity before we allow the test to start. */
+    BroadcastReceiver mConnectivityChangedReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            Log.d(TAG, "received: " + intent);
+            String extras = "";
+            for (String name : intent.getExtras().keySet()) {
+                extras += " |" + name + " " + intent.getExtras().get(name) + "|";
+
+            }
+            Log.d(TAG, "extras: " + extras);
+            if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
+                // Only enable the test when we know there is no connectivity.
+                mStartButton.setEnabled(isDataUnavailable());
+            }
+        }
+    };
+
+    private void testUnmeteredConstraintFails_noConnectivity() {
+        testConnectivityConstraintFailsImpl(
+                JobInfo.NETWORK_TYPE_UNMETERED, UNMETERED_CONNECTIVITY_JOB_ID);
+    }
+
+    private void testAnyConnectivityConstraintFails_noConnectivity() {
+        testConnectivityConstraintFailsImpl(JobInfo.NETWORK_TYPE_ANY, ANY_CONNECTIVITY_JOB_ID);
+    }
+
+    private void testNoConnectivityConstraintExecutes_noConnectivity() {
+        JobInfo testJob = new JobInfo.Builder(NO_CONNECTIVITY_JOB_ID, mMockComponent)
+                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_NONE)
+                .setOverrideDeadline(100000L)  // Will not expire.
+                .build();
+
+        mTestEnvironment.setUp();
+        mTestEnvironment.setExpectedExecutions(1);
+
+        mJobScheduler.schedule(testJob);
+
+        // Send intent to kick off ready jobs that the JobScheduler might be lazily holding on to.
+        sendBroadcastAndBlockForResult(EXPEDITE_STABLE_CHARGING);
+
+        boolean testPassed;
+        try {
+            testPassed = mTestEnvironment.awaitExecution();
+        } catch (InterruptedException e) {
+            testPassed = false;
+        }
+        runOnUiThread(
+                new ConnectivityConstraintTestResultRunner(NO_CONNECTIVITY_JOB_ID, testPassed));
+    }
+
+    private void testConnectivityConstraintFailsImpl(int requiredNetworkType, int jobId) {
+        // Use arguments provided to construct job with required connectivity constraint.
+        JobInfo testJob = new JobInfo.Builder(jobId, mMockComponent)
+                .setRequiredNetworkType(requiredNetworkType)
+                .build();
+
+        mTestEnvironment.setUp();
+        mTestEnvironment.setExpectedExecutions(0);
+
+        mJobScheduler.schedule(testJob);
+
+        // Send intent to kick off ready jobs that the JobScheduler might be lazily holding on to.
+        sendBroadcastAndBlockForResult(EXPEDITE_STABLE_CHARGING);
+
+        boolean testPassed;
+        try {
+            testPassed = mTestEnvironment.awaitTimeout();
+        } catch (InterruptedException e) {
+            testPassed = false;
+        }
+        runOnUiThread(
+                new ConnectivityConstraintTestResultRunner(jobId, testPassed));
+    }
+
+    /** Query the active network connection and return if there is no data connection. */
+    private boolean isDataUnavailable() {
+        final ConnectivityManager cm =
+                (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+        final NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
+
+        return (activeNetwork == null) ||
+                !activeNetwork.isConnectedOrConnecting();
+    }
+
+    private class TestConnectivityConstraint extends AsyncTask<Void, Void, Void> {
+
+        @Override
+        protected Void doInBackground(Void... voids) {
+            testUnmeteredConstraintFails_noConnectivity();
+            testAnyConnectivityConstraintFails_noConnectivity();
+            testNoConnectivityConstraintExecutes_noConnectivity();
+
+            notifyTestCompleted();
+            return null;
+        }
+    }
+
+    private class ConnectivityConstraintTestResultRunner extends TestResultRunner {
+        ConnectivityConstraintTestResultRunner(int jobId, boolean testPassed) {
+            super(jobId, testPassed);
+        }
+
+        @Override
+        public void run() {
+            ImageView view;
+            if (mJobId == ANY_CONNECTIVITY_JOB_ID) {
+                view = (ImageView) findViewById(R.id.connectivity_off_test_any_connectivity_image);
+            } else if (mJobId == UNMETERED_CONNECTIVITY_JOB_ID) {
+                view = (ImageView) findViewById(R.id.connectivity_off_test_unmetered_image);
+            } else if (mJobId == NO_CONNECTIVITY_JOB_ID) {
+                view = (ImageView) findViewById(R.id.connectivity_off_test_no_connectivity_image);
+            } else {
+                noteInvalidTest();
+                return;
+            }
+            view.setImageResource(mTestPassed ? R.drawable.fs_good : R.drawable.fs_error);
+        }
+    }
+
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/jobscheduler/ConstraintTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/jobscheduler/ConstraintTestActivity.java
new file mode 100644
index 0000000..da0862a
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/jobscheduler/ConstraintTestActivity.java
@@ -0,0 +1,115 @@
+package com.android.cts.verifier.jobscheduler;
+
+import android.annotation.TargetApi;
+import android.app.job.JobScheduler;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import android.widget.Toast;
+
+import com.android.cts.verifier.PassFailButtons;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@TargetApi(21)
+public abstract class ConstraintTestActivity extends PassFailButtons.Activity {
+    /**
+     * Intent we use to force the job scheduler to consider any ready jobs that otherwise it may
+     * have decided to be lazy about.
+     */
+    protected static final Intent EXPEDITE_STABLE_CHARGING =
+            new Intent("com.android.server.task.controllers.BatteryController.ACTION_CHARGING_STABLE");
+
+    protected ComponentName mMockComponent;
+
+    protected MockJobService.TestEnvironment mTestEnvironment;
+    protected JobScheduler mJobScheduler;
+
+    /** Avoid cases where user might press "start test" more than once. */
+    private boolean mTestInProgress;
+    /**
+     * Starts the test - set up by subclass, which also controls the logic for how/when the test
+     * can be started.
+     */
+    protected Button mStartButton;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        mJobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
+        mMockComponent = new ComponentName(this, MockJobService.class);
+        mTestEnvironment = MockJobService.TestEnvironment.getTestEnvironment();
+    }
+
+    /** OnClickListener for the "Start Test" ({@link #mStartButton}) button */
+    public final void startTest(View v) {
+        if (mTestInProgress) {
+            Toast toast =
+                    Toast.makeText(
+                            ConstraintTestActivity.this,
+                            "Test already in progress",
+                            Toast.LENGTH_SHORT);
+            toast.show();
+            return;
+        } else {
+            mTestInProgress = true;
+            startTestImpl();
+        }
+    }
+
+    /** Called by subclasses to allow the user to rerun the test if necessary. */
+    protected final void notifyTestCompleted() {
+        mTestInProgress = false;
+    }
+
+    /** Implemented by subclasses to determine logic for running the test. */
+    protected abstract void startTestImpl();
+
+    /**
+     * Broadcast the provided intent, and register a receiver to notify us after the broadcast has
+     * been processed.
+     * This function will block until the broadcast comes back, and <bold>cannot</bold> be called
+     * on the main thread.
+     * @return True if we received the callback, false if not.
+     */
+    protected boolean sendBroadcastAndBlockForResult(Intent intent) {
+        final CountDownLatch latch = new CountDownLatch(1);
+        sendOrderedBroadcast(intent, null, new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                latch.countDown();
+            }
+        }, null, -1, null, null);
+        try {
+            return latch.await(5, TimeUnit.SECONDS);
+        } catch (InterruptedException e) {
+            return false;
+        }
+    }
+
+    /** Extended by test activities to report results of a test. */
+    protected abstract class TestResultRunner implements Runnable {
+        final int mJobId;
+        final boolean mTestPassed;
+
+        TestResultRunner(int jobId, boolean testPassed) {
+            mJobId = jobId;
+            mTestPassed = testPassed;
+        }
+        protected void noteInvalidTest() {
+            final Toast toast =
+                    Toast.makeText(
+                            ConstraintTestActivity.this,
+                            "Invalid result returned from test thread: job=" + mJobId + ", res="
+                                    + mTestPassed,
+                            Toast.LENGTH_SHORT);
+            toast.show();
+        }
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/jobscheduler/IdleConstraintTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/jobscheduler/IdleConstraintTestActivity.java
new file mode 100644
index 0000000..a8bd993
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/jobscheduler/IdleConstraintTestActivity.java
@@ -0,0 +1,203 @@
+/*
+ * 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 com.android.cts.verifier.jobscheduler;
+
+import com.android.cts.verifier.R;
+
+import android.annotation.TargetApi;
+import android.app.job.JobInfo;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.util.Log;
+import android.widget.Button;
+import android.widget.ImageView;
+
+/**
+ *  Idle constraints:
+ *      The framework doesn't support turning idle mode off. Use the manual tester to ensure that
+ *      the device is not in idle mode (by turning the screen off and then back on) before running
+ *      the tests.
+ */
+@TargetApi(21)
+public class IdleConstraintTestActivity extends ConstraintTestActivity {
+    private static final String TAG = "IdleModeTestActivity";
+    /**
+     * It takes >1hr for idle mode to be triggered. We'll use this secret broadcast to force the
+     * scheduler into idle. It's not a protected broadcast so that's alright.
+     */
+    private static final String ACTION_EXPEDITE_IDLE_MODE =
+            "com.android.server.task.controllers.IdleController.ACTION_TRIGGER_IDLE";
+
+    /**
+     * Id for the job that we schedule when the device is not in idle mode. This job is expected
+     * to not execute. Executing means that the verifier test should fail.
+     */
+    private static final int IDLE_OFF_JOB_ID = IdleConstraintTestActivity.class.hashCode() + 0;
+    /**
+     * Id for the job that we schedule when the device *is* in idle mode. This job is expected to
+     * execute. Not executing means that the verifier test should fail.
+     */
+    private static final int IDLE_ON_JOB_ID = IdleConstraintTestActivity.class.hashCode() + 1;
+
+    /**
+     * Listens for idle mode off/on events, namely {@link #ACTION_EXPEDITE_IDLE_MODE} and
+     * {@link Intent#ACTION_SCREEN_ON}.
+     * On ACTION_EXPEDITE_IDLE_MODE, we will disable the {@link #mStartButton}, and on
+     * ACTION_SCREEN_ON we enable it. This is to avoid the start button being clicked when the
+     * device is in idle mode.
+     */
+    private BroadcastReceiver mIdleChangedReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) {
+                mStartButton.setEnabled(true);
+            } else if (ACTION_EXPEDITE_IDLE_MODE.equals(intent.getAction())) {
+                mStartButton.setEnabled(false);
+            } else {
+                Log.e(TAG, "Invalid broadcast received, was expecting SCREEN_ON");
+            }
+        }
+    };
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // Set up the UI.
+        setContentView(R.layout.js_idle);
+        setPassFailButtonClickListeners();
+        setInfoResources(R.string.js_idle_test, R.string.js_idle_instructions, -1);
+        mStartButton = (Button) findViewById(R.id.js_idle_start_test_button);
+
+        // Register receiver for idle off/on events.
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(Intent.ACTION_SCREEN_ON);
+        intentFilter.addAction(ACTION_EXPEDITE_IDLE_MODE);
+
+        registerReceiver(mIdleChangedReceiver, intentFilter);
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        unregisterReceiver(mIdleChangedReceiver);
+    }
+
+    @Override
+    protected void startTestImpl() {
+        new TestIdleModeTask().execute();
+    }
+
+    /** Background task that will run the actual test. */
+    private class TestIdleModeTask extends AsyncTask<Void, Void, Void> {
+
+        @Override
+        protected Void doInBackground(Void... voids) {
+            testIdleConstraintFails_notIdle();
+
+
+            // Send the {@link #ACTION_EXPEDITE_IDLE_MODE} broadcast as an ordered broadcast, this
+            // function will block until all receivers have processed the broadcast.
+            if (!sendBroadcastAndBlockForResult(new Intent(ACTION_EXPEDITE_IDLE_MODE))) {
+                // Fail the test if the broadcast wasn't processed.
+                runOnUiThread(new IdleTestResultRunner(IDLE_ON_JOB_ID, false));
+            }
+
+            testIdleConstraintExecutes_onIdle();
+
+            notifyTestCompleted();
+            return null;
+        }
+
+    }
+
+    /**
+     * The user has just pressed the "Start Test" button, so we know that the device can't be idle.
+     * Schedule a job with an idle constraint and verify that it doesn't execute.
+     */
+    private void testIdleConstraintFails_notIdle() {
+        mTestEnvironment.setUp();
+        mJobScheduler.cancelAll();
+
+        mTestEnvironment.setExpectedExecutions(0);
+
+        mJobScheduler.schedule(
+                new JobInfo.Builder(IDLE_OFF_JOB_ID, mMockComponent)
+                        .setRequiresDeviceIdle(true)
+                        .build());
+
+        boolean testPassed;
+        try {
+            testPassed = mTestEnvironment.awaitTimeout();
+        } catch (InterruptedException e) {
+            // We'll just indicate that it failed, not why.
+            testPassed = false;
+        }
+        runOnUiThread(new IdleTestResultRunner(IDLE_OFF_JOB_ID, testPassed));
+    }
+
+    private void testIdleConstraintExecutes_onIdle() {
+        mTestEnvironment.setUp();
+        mJobScheduler.cancelAll();
+
+        mTestEnvironment.setExpectedExecutions(1);
+
+        mJobScheduler.schedule(
+                new JobInfo.Builder(IDLE_ON_JOB_ID, mMockComponent)
+                .setRequiresDeviceIdle(true)
+                .build());
+
+        boolean testPassed;
+        try {
+            testPassed = mTestEnvironment.awaitExecution();
+        } catch (InterruptedException e) {
+            // We'll just indicate that it failed, not why.
+            testPassed = false;
+        }
+        runOnUiThread(new IdleTestResultRunner(IDLE_ON_JOB_ID, testPassed));
+    }
+
+    /**
+     * Runnable to update the UI with the outcome of the test. This class only runs two tests, so
+     * the argument passed into the constructor will indicate which of the tests we are reporting
+     * for.
+     */
+    protected class IdleTestResultRunner extends TestResultRunner {
+
+        IdleTestResultRunner(int jobId, boolean testPassed) {
+            super(jobId, testPassed);
+        }
+
+        @Override
+        public void run() {
+            ImageView view;
+            if (mJobId == IDLE_OFF_JOB_ID) {
+                view = (ImageView) findViewById(R.id.idle_off_test_image);
+            } else if (mJobId == IDLE_ON_JOB_ID) {
+                view = (ImageView) findViewById(R.id.idle_on_test_image);
+            } else {
+                noteInvalidTest();
+                return;
+            }
+            view.setImageResource(mTestPassed ? R.drawable.fs_good : R.drawable.fs_error);
+        }
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/jobscheduler/MockJobService.java b/apps/CtsVerifier/src/com/android/cts/verifier/jobscheduler/MockJobService.java
new file mode 100644
index 0000000..9595a6a
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/jobscheduler/MockJobService.java
@@ -0,0 +1,118 @@
+/*
+ * 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 com.android.cts.verifier.jobscheduler;
+
+import android.annotation.TargetApi;
+import android.app.job.JobParameters;
+import android.app.job.JobService;
+import android.util.Log;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Handles callback from the framework {@link android.app.job.JobScheduler}. The behaviour of this
+ * class is configured through the static
+ * {@link TestEnvironment}.
+ */
+@TargetApi(21)
+public class MockJobService extends JobService {
+    private static final String TAG = "MockJobService";
+
+    /** Wait this long before timing out the test. */
+    private static final long DEFAULT_TIMEOUT_MILLIS = 5000L; // 5 seconds.
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        Log.e(TAG, "Created test service.");
+    }
+
+    @Override
+    public boolean onStartJob(JobParameters params) {
+        Log.i(TAG, "Test job executing: " + params.getJobId());
+
+        TestEnvironment.getTestEnvironment().notifyExecution(params.getJobId());
+        return false;  // No work to do.
+    }
+
+    @Override
+    public boolean onStopJob(JobParameters params) {
+        return false;
+    }
+
+    /**
+     * Configures the expected behaviour for each test. This object is shared across consecutive
+     * tests, so to clear state each test is responsible for calling
+     * {@link TestEnvironment#setUp()}.
+     */
+    public static final class TestEnvironment {
+
+        private static TestEnvironment kTestEnvironment;
+        public static final int INVALID_JOB_ID = -1;
+
+        private CountDownLatch mLatch;
+        private int mExecutedJobId;
+
+        public static TestEnvironment getTestEnvironment() {
+            if (kTestEnvironment == null) {
+                kTestEnvironment = new TestEnvironment();
+            }
+            return kTestEnvironment;
+        }
+
+        /**
+         * Block the test thread, waiting on the JobScheduler to execute some previously scheduled
+         * job on this service.
+         */
+        public boolean awaitExecution() throws InterruptedException {
+            final boolean executed = mLatch.await(DEFAULT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+            return executed;
+        }
+
+        /**
+         * Block the test thread, expecting to timeout but still listening to ensure that no jobs
+         * land in the interim.
+         * @return True if the latch timed out waiting on an execution.
+         */
+        public boolean awaitTimeout() throws InterruptedException {
+            return !mLatch.await(DEFAULT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+        }
+
+        private void notifyExecution(int jobId) {
+            Log.d(TAG, "Job executed:" + jobId);
+            mExecutedJobId = jobId;
+            mLatch.countDown();
+        }
+
+        public void setExpectedExecutions(int numExecutions) {
+            // For no executions expected, set count to 1 so we can still block for the timeout.
+            if (numExecutions == 0) {
+                mLatch = new CountDownLatch(1);
+            } else {
+                mLatch = new CountDownLatch(numExecutions);
+            }
+        }
+
+        /** Called in each testCase#setup */
+        public void setUp() {
+            mLatch = null;
+            mExecutedJobId = INVALID_JOB_ID;
+        }
+
+    }
+}
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
new file mode 100644
index 0000000..da823e8
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
@@ -0,0 +1,384 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.managedprovisioning;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.admin.DevicePolicyManager;
+import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.View.OnClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.TestListActivity;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * CTS verifier test for BYOD managed provisioning flow.
+ * This activity is responsible for starting the managed provisioning flow and verify the outcome of provisioning.
+ * It performs the following verifications:
+ *   Full disk encryption is enabled.
+ *   Profile owner is correctly installed.
+ *   Profile owner shows up in the Settings app.
+ *   Badged work apps show up in launcher.
+ * The first two verifications are performed automatically, by interacting with profile owner using
+ * cross-profile intents, while the last two are carried out manually by the user.
+ */
+public class ByodFlowTestActivity extends PassFailButtons.ListActivity {
+
+    private final String TAG = "ByodFlowTestActivity";
+    private static final int REQUEST_STATUS = 1;
+
+    private ComponentName mAdminReceiverComponent;
+
+    private TestAdapter mAdapter;
+    private View mStartProvisioningButton;
+    private List<TestItem> mTests = new ArrayList<TestItem>();
+
+    protected DevicePolicyManager mDevicePolicyManager;
+
+    private TestItem mProfileOwnerInstalled;
+    private TestItem mDiskEncryptionTest;
+    private TestItem mProfileVisibleTest;
+    private TestItem mDeviceAdminVisibleTest;
+    private TestItem mWorkAppVisibleTest;
+    private TestItem mCrossProfileIntentFiltersTest;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mAdminReceiverComponent = new ComponentName(this, DeviceAdminTestReceiver.class.getName());
+        mDevicePolicyManager = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
+        disableComponent();
+
+        setContentView(R.layout.provisioning_byod);
+        setInfoResources(R.string.provisioning_byod, R.string.provisioning_byod_info, -1);
+        setPassFailButtonClickListeners();
+        getPassButton().setEnabled(false);
+        setResult(RESULT_CANCELED);
+
+        setupTests();
+
+        mAdapter = new TestAdapter(this);
+        setListAdapter(mAdapter);
+        mAdapter.addAll(mTests);
+
+        mStartProvisioningButton = findViewById(R.id.byod_start);
+        mStartProvisioningButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                startByodProvisioning();
+            }
+        });
+
+        // If we are started by managed provisioning (fresh managed provisioning after encryption
+        // reboot), redirect the user back to the main test list. This is because the test result
+        // is only saved by the parent TestListActivity, and if we did allow the user to proceed
+        // here, the test result would be lost when this activity finishes.
+        if (ByodHelperActivity.ACTION_PROFILE_OWNER_STATUS.equals(getIntent().getAction())) {
+            startActivity(new Intent(this, TestListActivity.class));
+            // Calling super.finish() because we delete managed profile in our overridden of finish(),
+            // which is not what we want to do here.
+            super.finish();
+        } else {
+            queryProfileOwner(false);
+        }
+    }
+
+    @Override
+    protected void onNewIntent(Intent intent) {
+        // This is called when managed provisioning completes successfully without reboot.
+        super.onNewIntent(intent);
+        if (ByodHelperActivity.ACTION_PROFILE_OWNER_STATUS.equals(intent.getAction())) {
+            handleStatusUpdate(intent);
+        }
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        // Called after queryProfileOwner()
+        super.onActivityResult(requestCode, resultCode, data);
+        if (requestCode == REQUEST_STATUS && resultCode == RESULT_OK) {
+            handleStatusUpdate(data);
+        }
+    }
+
+    private void handleStatusUpdate(Intent data) {
+        boolean provisioned = data.getBooleanExtra(ByodHelperActivity.EXTRA_PROVISIONED, false);
+        setTestResult(mProfileOwnerInstalled, provisioned ? TestResult.Passed : TestResult.Failed);
+    }
+
+    @Override
+    public void finish() {
+        // Pass and fail buttons are known to call finish() when clicked, and this is when we want to
+        // clean up the provisioned profile.
+        requestDeleteProfileOwner();
+        super.finish();
+    }
+
+    private void setupTests() {
+        mProfileOwnerInstalled = new TestItem(this, R.string.provisioning_byod_profileowner) {
+            @Override
+            public void performTest(ByodFlowTestActivity activity) {
+                queryProfileOwner(true);
+            }
+        };
+
+        mDiskEncryptionTest = new TestItem(this, R.string.provisioning_byod_diskencryption) {
+            @Override
+            public TestResult getPassFailState() {
+                return isDeviceEncrypted() ? TestResult.Passed : TestResult.Failed;
+            }
+        };
+
+        mProfileVisibleTest = new TestItem(this, R.string.provisioning_byod_profile_visible,
+                R.string.provisioning_byod_profile_visible_instruction,
+                new Intent(Settings.ACTION_SETTINGS));
+
+        mDeviceAdminVisibleTest = new TestItem(this, R.string.provisioning_byod_admin_visible,
+                R.string.provisioning_byod_admin_visible_instruction,
+                new Intent(Settings.ACTION_SECURITY_SETTINGS));
+
+        mWorkAppVisibleTest = new TestItem(this, R.string.provisioning_byod_workapps_visible,
+                R.string.provisioning_byod_workapps_visible_instruction,
+                new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME));
+
+        Intent intent = new Intent(CrossProfileTestActivity.ACTION_CROSS_PROFILE);
+        Intent chooser = Intent.createChooser(intent, getResources().getString(R.string.provisioning_cross_profile_chooser));
+        mCrossProfileIntentFiltersTest = new TestItem(this,
+                R.string.provisioning_byod_cross_profile,
+                R.string.provisioning_byod_cross_profile_instruction,
+                chooser);
+
+        mTests.add(mDiskEncryptionTest);
+        mTests.add(mProfileOwnerInstalled);
+        mTests.add(mProfileVisibleTest);
+        mTests.add(mDeviceAdminVisibleTest);
+        mTests.add(mWorkAppVisibleTest);
+        mTests.add(mCrossProfileIntentFiltersTest);
+    }
+
+    @Override
+    protected void onListItemClick(ListView l, View v, int position, long id) {
+        super.onListItemClick(l, v, position, id);
+        TestItem test = (TestItem) getListAdapter().getItem(position);
+        test.performTest(this);
+    }
+
+    private void showManualTestDialog(final TestItem test) {
+        AlertDialog dialog = new AlertDialog.Builder(this)
+                .setIcon(android.R.drawable.ic_dialog_info)
+                .setMessage(test.getManualTestInstruction())
+                .setNeutralButton(R.string.provisioning_byod_go, null)
+                .setPositiveButton(R.string.pass_button_text, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        setTestResult(test, TestResult.Passed);
+                    }
+                })
+                .setNegativeButton(R.string.fail_button_text, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        setTestResult(test, TestResult.Failed);
+                    }
+                })
+                .create();
+        dialog.show();
+
+        dialog.getButton(AlertDialog.BUTTON_NEUTRAL).setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                ByodFlowTestActivity.this.startActivity(test.getManualTestIntent());
+            }
+        });
+    }
+
+    private void setTestResult(TestItem test, TestResult result) {
+        test.setPassFailState(result);
+
+        boolean testSucceeds = true;
+        for(TestItem aTest : mTests) {
+            testSucceeds &= (aTest.getPassFailState() == TestResult.Passed);
+        }
+        getPassButton().setEnabled(testSucceeds);
+        mAdapter.notifyDataSetChanged();
+    }
+
+    private void startByodProvisioning() {
+        Intent sending = new Intent(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE);
+        sending.putExtra(DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME,
+                mAdminReceiverComponent.getPackageName());
+        sending.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mAdminReceiverComponent);
+
+        if (sending.resolveActivity(getPackageManager()) != null) {
+            // ManagedProvisioning must be started with startActivityForResult, but we don't
+            // care about the result, so passing 0 as a requestCode
+            startActivityForResult(sending, 0);
+        } else {
+            showToast(R.string.provisioning_byod_disabled);
+        }
+    }
+
+    private void queryProfileOwner(boolean showToast) {
+        try {
+            Intent intent = new Intent(ByodHelperActivity.ACTION_QUERY_PROFILE_OWNER);
+            startActivityForResult(intent, REQUEST_STATUS);
+        }
+        catch (ActivityNotFoundException e) {
+            Log.d(TAG, "queryProfileOwner: ActivityNotFoundException", e);
+            setTestResult(mProfileOwnerInstalled, TestResult.Failed);
+            if (showToast) {
+                showToast(R.string.provisioning_byod_no_activity);
+            }
+        }
+    }
+
+    private void requestDeleteProfileOwner() {
+        try {
+            Intent intent = new Intent(ByodHelperActivity.ACTION_REMOVE_PROFILE_OWNER);
+            startActivity(intent);
+            showToast(R.string.provisioning_byod_delete_profile);
+        }
+        catch (ActivityNotFoundException e) {
+            Log.d(TAG, "requestDeleteProfileOwner: ActivityNotFoundException", e);
+        }
+    }
+
+    private void disableComponent() {
+        // Disable app components in the current profile, so only the counterpart in the other profile
+        // can respond (via cross-profile intent filter)
+        getPackageManager().setComponentEnabledSetting(new ComponentName(
+                this, ByodHelperActivity.class),
+                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+                PackageManager.DONT_KILL_APP);
+    }
+
+    private boolean isDeviceEncrypted() {
+        return mDevicePolicyManager.getStorageEncryptionStatus()
+                == DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE;
+    }
+
+    private void showToast(int messageId) {
+        String message = getString(messageId);
+        Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
+    }
+
+    enum TestResult {
+        Unknown, Failed, Passed
+    }
+
+    static class TestItem {
+
+        private String mDisplayName;
+        private TestResult mPassed;
+        private boolean mManualTest;
+        private String mManualInstruction;
+        private Intent mManualIntent;
+
+        public TestItem(Context context, int nameResId) {
+            mDisplayName = context.getString(nameResId);
+            mPassed = TestResult.Unknown;
+            mManualTest = false;
+        }
+
+        public void performTest(ByodFlowTestActivity activity) {
+            if (isManualTest()) {
+                activity.showManualTestDialog(this);
+            }
+        }
+
+        public TestItem(Context context, int nameResId, int testInstructionResId, Intent testIntent) {
+            mDisplayName = context.getString(nameResId);
+            mPassed = TestResult.Unknown;
+            mManualTest = true;
+            mManualInstruction = context.getString(testInstructionResId);
+            mManualIntent = testIntent;
+        }
+
+        @Override
+        public String toString() {
+            return mDisplayName;
+        }
+
+        TestResult getPassFailState() {
+            return mPassed;
+        }
+
+        void setPassFailState(TestResult state) {
+            mPassed = state;
+        }
+
+        public boolean isManualTest() {
+            return mManualTest;
+        }
+
+        public String getManualTestInstruction() {
+            return mManualInstruction;
+        }
+
+        public Intent getManualTestIntent() {
+            return mManualIntent;
+        }
+    }
+
+    static class TestAdapter extends ArrayAdapter<TestItem> {
+
+        public TestAdapter(Context context) {
+            super(context, android.R.layout.simple_list_item_1);
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            TextView view = (TextView) super.getView(position, convertView, parent);
+
+            TestItem item = getItem(position);
+            int backgroundResource = 0;
+            int iconResource = 0;
+            if (item.getPassFailState() == TestResult.Passed) {
+                backgroundResource = R.drawable.test_pass_gradient;
+                iconResource = R.drawable.fs_good;
+            } else if (item.getPassFailState() == TestResult.Failed){
+                backgroundResource = R.drawable.test_fail_gradient;
+                iconResource = R.drawable.fs_error;
+            }
+            view.setBackgroundResource(backgroundResource);
+            view.setPadding(10, 0, 10, 0);
+            view.setCompoundDrawablePadding(10);
+            view.setCompoundDrawablesWithIntrinsicBounds(0, 0, iconResource, 0);
+
+            return view;
+        }
+    }
+
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
new file mode 100644
index 0000000..5dac4bd
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodHelperActivity.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.managedprovisioning;
+
+import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.managedprovisioning.ByodFlowTestActivity.TestResult;
+
+/**
+ * A helper activity from the managed profile side that responds to requests from CTS verifier in
+ * primary user. Profile owner APIs are accessible inside this activity (given this activity is
+ * started within the work profile). Its current functionalities include making sure the profile
+ * owner is setup correctly, and removing the work profile upon request.
+ *
+ * Note: We have to use a dummy activity because cross-profile intents only work for activities.
+ */
+public class ByodHelperActivity extends Activity {
+    static final String TAG = "ByodHelperActivity";
+
+    // Primary -> managed intent: query if the profile owner has been set up.
+    public static final String ACTION_QUERY_PROFILE_OWNER = "com.android.cts.verifier.managedprovisioning.BYOD_QUERY";
+    // Managed -> primary intent: update profile owner test status in primary's CtsVerifer
+    public static final String ACTION_PROFILE_OWNER_STATUS = "com.android.cts.verifier.managedprovisioning.BYOD_STATUS";
+    // Primary -> managed intent: request to delete the current profile
+    public static final String ACTION_REMOVE_PROFILE_OWNER = "com.android.cts.verifier.managedprovisioning.BYOD_REMOVE";
+    // Managed -> managed intent: provisioning completed successfully
+    public static final String ACTION_PROFILE_PROVISIONED = "com.android.cts.verifier.managedprovisioning.BYOD_PROVISIONED";
+
+    public static final String EXTRA_PROVISIONED = "extra_provisioned";
+
+    private ComponentName mAdminReceiverComponent;
+
+    private DevicePolicyManager mDevicePolicyManager;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mAdminReceiverComponent = new ComponentName(this, DeviceAdminTestReceiver.class.getName());
+        mDevicePolicyManager = (DevicePolicyManager) getSystemService(
+                Context.DEVICE_POLICY_SERVICE);
+        String action = getIntent().getAction();
+        Log.d(TAG, "ByodHelperActivity.onCreate: " + action);
+
+        // we are explicitly started by {@link DeviceAdminTestReceiver} after a successful provisioning.
+        if (action.equals(ACTION_PROFILE_PROVISIONED)) {
+            // Jump back to CTS verifier with result.
+            Intent response = new Intent(ACTION_PROFILE_OWNER_STATUS);
+            response.putExtra(EXTRA_PROVISIONED, isProfileOwner());
+            startActivityInPrimary(response);
+            // Queried by CtsVerifier in the primary side using startActivityForResult.
+        } else if (action.equals(ACTION_QUERY_PROFILE_OWNER)) {
+            Intent response = new Intent();
+            response.putExtra(EXTRA_PROVISIONED, isProfileOwner());
+            setResult(RESULT_OK, response);
+            // Request to delete work profile.
+        } else if (action.equals(ACTION_REMOVE_PROFILE_OWNER)) {
+            if (isProfileOwner()) {
+                mDevicePolicyManager.wipeData(0);
+                showToast(R.string.provisioning_byod_profile_deleted);
+            }
+        }
+        // This activity has no UI and is only used to respond to CtsVerifier in the primary side.
+        finish();
+    }
+
+    private boolean isProfileOwner() {
+        return mDevicePolicyManager.isAdminActive(mAdminReceiverComponent) &&
+                mDevicePolicyManager.isProfileOwnerApp(mAdminReceiverComponent.getPackageName());
+    }
+
+    private void startActivityInPrimary(Intent intent) {
+        // Disable app components in the current profile, so only the counterpart in the other
+        // profile can respond (via cross-profile intent filter)
+        getPackageManager().setComponentEnabledSetting(new ComponentName(
+                this, ByodFlowTestActivity.class),
+                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+                PackageManager.DONT_KILL_APP);
+        startActivity(intent);
+    }
+
+    private void showToast(int messageId) {
+        String message = getString(messageId);
+        Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CrossProfileTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CrossProfileTestActivity.java
new file mode 100644
index 0000000..6c38e12
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CrossProfileTestActivity.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.managedprovisioning;
+//package com.android.cts.verifier.managedprovisioning;
+
+import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Process;
+import android.os.UserManager;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.TextView;
+
+import com.android.cts.verifier.R;
+
+/**
+ * Test activity for cross profile intents.
+ */
+public class CrossProfileTestActivity extends Activity {
+    // Intent for app in both profiles
+    public static final String ACTION_CROSS_PROFILE = "com.android.cts.verifier.managedprovisioning.CROSS_PROFILE";
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.provisioning_cross_profile);
+        TextView textView = (TextView) findViewById(R.id.text);
+
+        // Check if we are running in the work or personal side, by testing if currently we are the
+        // profile owner or not.
+        textView.setText(isProfileOwner() ? R.string.provisioning_byod_cross_profile_app_work
+                : R.string.provisioning_byod_cross_profile_app_personal);
+
+        findViewById(R.id.button_finish).setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                CrossProfileTestActivity.this.finish();
+            }
+        });
+    }
+
+    private boolean isProfileOwner() {
+        ComponentName adminReceiver = new ComponentName(this, DeviceAdminTestReceiver.class.getName());
+        DevicePolicyManager dpm = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
+        return dpm.isAdminActive(adminReceiver) && dpm.isProfileOwnerApp(adminReceiver.getPackageName());
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
new file mode 100644
index 0000000..8dccac3
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceAdminTestReceiver.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.managedprovisioning;
+
+import android.app.admin.DeviceAdminReceiver;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.android.cts.verifier.managedprovisioning.ByodHelperActivity;
+
+/**
+ * Profile owner receiver for BYOD flow test.
+ * Setup cross-profile intent filter after successful provisioning.
+ */
+public class DeviceAdminTestReceiver extends DeviceAdminReceiver {
+        private static final String TAG = "DeviceAdminTestReceiver";
+
+        @Override
+        public void onProfileProvisioningComplete(Context context, Intent intent) {
+            Log.d(TAG, "Provisioning complete intent received");
+            setupProfile(context);
+        }
+
+        private void setupProfile(Context context) {
+            DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
+            dpm.setProfileEnabled(new ComponentName(context.getApplicationContext(), getClass()));
+
+            // Setup cross-profile intent filter to allow communications between the two versions of CtsVerifier
+            // Primary -> work direction
+            IntentFilter filter = new IntentFilter();
+            filter.addAction(ByodHelperActivity.ACTION_QUERY_PROFILE_OWNER);
+            filter.addAction(ByodHelperActivity.ACTION_REMOVE_PROFILE_OWNER);
+            filter.addAction(CrossProfileTestActivity.ACTION_CROSS_PROFILE);
+            dpm.addCrossProfileIntentFilter(getWho(context), filter,
+                    DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT);
+
+            // Work -> primary direction
+            filter = new IntentFilter();
+            filter.addAction(ByodHelperActivity.ACTION_PROFILE_OWNER_STATUS);
+            dpm.addCrossProfileIntentFilter(getWho(context), filter,
+                    DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED);
+
+            Intent intent = new Intent(context, ByodHelperActivity.class);
+            intent.setAction(ByodHelperActivity.ACTION_PROFILE_PROVISIONED);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            context.startActivity(intent);
+        }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerTestActivity.java
new file mode 100644
index 0000000..7cb3825
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerTestActivity.java
@@ -0,0 +1,93 @@
+package com.android.cts.verifier.managedprovisioning;
+
+import android.app.AlertDialog;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.database.DataSetObserver;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.View.OnClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.android.cts.verifier.ArrayTestListAdapter;
+import com.android.cts.verifier.IntentDrivenTestActivity;
+import com.android.cts.verifier.IntentDrivenTestActivity.ButtonInfo;
+import com.android.cts.verifier.IntentDrivenTestActivity.TestInfo;
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.TestListAdapter.TestListItem;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Activity that lists all device owner provisioning tests.
+ */
+public class DeviceOwnerTestActivity extends PassFailButtons.TestListActivity {
+
+    private static final String ACTION_PROVISION_MANAGED_DEVICE
+        = "com.android.managedprovisioning.ACTION_PROVISION_MANAGED_DEVICE";
+    private static final Intent PROVISION_DEVICE_INTENT =
+            new Intent(ACTION_PROVISION_MANAGED_DEVICE);
+
+    private static final String DEVICE_OWNER_NEGATIVE_TEST = "DEVICE_OWNER_PROVISIONING_NEGATIVE";
+    private static final TestInfo DEVICE_OWNER_NEGATIVE_TEST_INFO = new TestInfo(
+                    DEVICE_OWNER_NEGATIVE_TEST,
+                    R.string.device_owner_negative_test,
+                    R.string.device_owner_negative_test_info,
+                    new ButtonInfo(
+                            R.string.start_device_owner_provisioning_button,
+                            PROVISION_DEVICE_INTENT));
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.pass_fail_list);
+        setInfoResources(R.string.device_owner_provisioning_tests,
+                R.string.device_owner_provisioning_tests_info, 0);
+        setPassFailButtonClickListeners();
+
+        final ArrayTestListAdapter adapter = new ArrayTestListAdapter(this);
+        adapter.add(TestListItem.newCategory(this, R.string.device_owner_provisioning_category));
+
+        Intent startTestIntent = new Intent(this, IntentDrivenTestActivity.class)
+                    .putExtra(IntentDrivenTestActivity.EXTRA_ID,
+                            DEVICE_OWNER_NEGATIVE_TEST_INFO.getTestId())
+                    .putExtra(IntentDrivenTestActivity.EXTRA_TITLE,
+                            DEVICE_OWNER_NEGATIVE_TEST_INFO.getTitle())
+                    .putExtra(IntentDrivenTestActivity.EXTRA_INFO,
+                            DEVICE_OWNER_NEGATIVE_TEST_INFO.getInfoText())
+                    .putExtra(IntentDrivenTestActivity.EXTRA_BUTTONS,
+                            DEVICE_OWNER_NEGATIVE_TEST_INFO.getButtons());
+
+
+        adapter.add(TestListItem.newTest(this, DEVICE_OWNER_NEGATIVE_TEST_INFO.getTitle(),
+                DEVICE_OWNER_NEGATIVE_TEST_INFO.getTestId(), startTestIntent, null));
+
+        adapter.registerDataSetObserver(new DataSetObserver() {
+            @Override
+            public void onChanged() {
+                updatePassButton();
+            }
+        });
+
+        setTestListAdapter(adapter);
+    }
+
+    /**
+     * Enable Pass Button when the all tests passed.
+     */
+    private void updatePassButton() {
+        getPassButton().setEnabled(mAdapter.allTestsPassed());
+    }
+}
+
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/NfcDialogs.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/NfcDialogs.java
index 40a12ae..644e637 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/NfcDialogs.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/NfcDialogs.java
@@ -66,6 +66,22 @@
                 .setPositiveButton("OK", null)
                 .create();
     }
+
+    public static AlertDialog createChangeForegroundDialog(final Context context) {
+        return new AlertDialog.Builder(context)
+                .setIcon(android.R.drawable.ic_dialog_alert)
+                .setTitle(R.string.nfc_hce_tap_reader_title)
+                .setMessage(context.getString(R.string.nfc_hce_change_favor_foreground))
+                .setPositiveButton("OK", new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        Intent intent = new Intent(Settings.ACTION_NFC_PAYMENT_SETTINGS);
+                        context.startActivity(intent);
+                    }
+                })
+                .create();
+    }
+
     private NfcDialogs() {
     }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/AccessService.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/AccessService.java
index 969f621..51eb7ec 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/AccessService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/AccessService.java
@@ -7,9 +7,9 @@
             new ComponentName("com.android.cts.verifier",
             AccessService.class.getName());
 
-    public static final String[] APDU_COMMAND_SEQUENCE = {
-        HceUtils.buildSelectApdu(HceUtils.ACCESS_AID),
-        "80CA01F000"
+    public static final CommandApdu[] APDU_COMMAND_SEQUENCE = {
+        HceUtils.buildSelectApdu(HceUtils.ACCESS_AID, true),
+        HceUtils.buildCommandApdu("80CA01F000", true)
     };
 
     public static final String[] APDU_RESPOND_SEQUENCE = {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/BaseEmulatorActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/BaseEmulatorActivity.java
index bcd2b8d..8aa82b5 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/BaseEmulatorActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/BaseEmulatorActivity.java
@@ -1,10 +1,13 @@
 package com.android.cts.verifier.nfc.hce;
 
 import android.annotation.TargetApi;
+import android.app.Activity;
+import android.app.AlertDialog;
 import android.app.ProgressDialog;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.nfc.NfcAdapter;
@@ -19,7 +22,6 @@
 
 import com.android.cts.verifier.PassFailButtons;
 import com.android.cts.verifier.R;
-import com.android.cts.verifier.nfc.hce.PaymentService1;
 
 @TargetApi(19)
 public abstract class BaseEmulatorActivity extends PassFailButtons.Activity {
@@ -27,6 +29,7 @@
     NfcAdapter mAdapter;
     CardEmulation mCardEmulation;
     ProgressDialog mSetupDialog;
+    ComponentName mMakingDefault;
 
     final ArrayList<ComponentName> SERVICES = new ArrayList<ComponentName>(
             Arrays.asList(
@@ -36,7 +39,13 @@
             TransportService2.COMPONENT,
             AccessService.COMPONENT,
             ThroughputService.COMPONENT,
-            OffHostService.COMPONENT)
+            OffHostService.COMPONENT,
+            PaymentServiceDynamicAids.COMPONENT,
+            PrefixPaymentService1.COMPONENT,
+            PrefixPaymentService2.COMPONENT,
+            PrefixTransportService1.COMPONENT,
+            PrefixTransportService2.COMPONENT,
+            PrefixAccessService.COMPONENT)
     );
 
     @Override
@@ -73,6 +82,29 @@
         new SetupServicesTask().execute(components);
     }
 
+    final boolean makePaymentDefault(final ComponentName defaultComponent, int stringId) {
+        if (!mCardEmulation.isDefaultServiceForCategory(defaultComponent,
+                CardEmulation.CATEGORY_PAYMENT)) {
+            AlertDialog.Builder builder = new AlertDialog.Builder(this);
+            builder.setTitle("Note");
+            builder.setMessage(stringId);
+            mMakingDefault = defaultComponent;
+            builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
+                @Override
+                public void onClick(DialogInterface dialog, int which) {
+                Intent changeDefault = new Intent(CardEmulation.ACTION_CHANGE_DEFAULT);
+                changeDefault.putExtra(CardEmulation.EXTRA_CATEGORY, CardEmulation.CATEGORY_PAYMENT);
+                changeDefault.putExtra(CardEmulation.EXTRA_SERVICE_COMPONENT, defaultComponent);
+                startActivityForResult(changeDefault, 0);
+                }
+            });
+            builder.show();
+            return true;
+        } else {
+            return false;
+        }
+    }
+
     final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -127,5 +159,38 @@
                     CardEmulation.CATEGORY_PAYMENT);
             return true;
         }
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+        if (resultCode == Activity.RESULT_OK) {
+            // Verify it's default
+            if (!mCardEmulation.isDefaultServiceForCategory(mMakingDefault,
+                    CardEmulation.CATEGORY_PAYMENT)) {
+                // Popup dialog-box
+                AlertDialog.Builder builder = new AlertDialog.Builder(this);
+                builder.setTitle("Test failed.");
+                builder.setMessage("The service was not made the default service according " +
+                        "to CardEmulation.getDefaultServiceForCategory(), verify the make " +
+                        "default implementation is correct.");
+                builder.setPositiveButton("OK", null);
+                builder.show();
+                onPaymentDefaultResult(mMakingDefault, false);
+            } else {
+                onPaymentDefaultResult(mMakingDefault, true);
+            }
+        } else {
+            AlertDialog.Builder builder = new AlertDialog.Builder(this);
+            builder.setTitle("Test failed.");
+            builder.setMessage("You clicked no.");
+            builder.setPositiveButton("OK", null);
+            builder.show();
+            onPaymentDefaultResult(mMakingDefault, false);
+        }
+    }
+
+    void onPaymentDefaultResult(ComponentName component, boolean success) {
+
     };
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/ChangeDefaultEmulatorActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/ChangeDefaultEmulatorActivity.java
index 0681f49..633a152 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/ChangeDefaultEmulatorActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/ChangeDefaultEmulatorActivity.java
@@ -1,20 +1,16 @@
 package com.android.cts.verifier.nfc.hce;
 
 import android.annotation.TargetApi;
-import android.app.AlertDialog;
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
 import android.content.Intent;
-import android.nfc.cardemulation.CardEmulation;
 import android.os.Bundle;
 
 import com.android.cts.verifier.R;
 import com.android.cts.verifier.nfc.NfcDialogs;
 
 @TargetApi(19)
-public class ChangeDefaultEmulatorActivity extends BaseEmulatorActivity implements OnClickListener {
+public class ChangeDefaultEmulatorActivity extends BaseEmulatorActivity {
     final static int STATE_IDLE = 0;
     final static int STATE_SERVICE1_SETTING_UP = 1;
     final static int STATE_SERVICE2_SETTING_UP = 2;
@@ -48,22 +44,14 @@
             setupServices(this, PaymentService1.COMPONENT, PaymentService2.COMPONENT);
             return;
         }
-        // Verify HCE service 2 is the default
-        if (!mCardEmulation.isDefaultServiceForCategory(
-                PaymentService2.COMPONENT, CardEmulation.CATEGORY_PAYMENT)) {
-            mState = STATE_MAKING_SERVICE2_DEFAULT;
-            AlertDialog.Builder builder = new AlertDialog.Builder(this);
-            builder.setTitle("Note");
-            builder.setMessage(R.string.nfc_hce_change_preinstalled_wallet);
-            builder.setPositiveButton("OK", this);
-            builder.show();
-        } else {
+        if (!makePaymentDefault(PaymentService2.COMPONENT,
+                R.string.nfc_hce_change_preinstalled_wallet)) {
+            // Service 2 is already default, make one default now
             mState = STATE_MAKING_SERVICE1_DEFAULT;
-            AlertDialog.Builder builder = new AlertDialog.Builder(this);
-            builder.setTitle("Note");
-            builder.setMessage(R.string.nfc_hce_change_default_help);
-            builder.setPositiveButton("OK", this);
-            builder.show();
+            makePaymentDefault(PaymentService1.COMPONENT, R.string.nfc_hce_change_default_help);
+        } else {
+            mState = STATE_MAKING_SERVICE2_DEFAULT;
+            // will get callback when 2 is made default
         }
     }
 
@@ -94,57 +82,17 @@
     }
 
     @Override
-    public void onClick(DialogInterface dialog, int which) {
-        if (mState == STATE_MAKING_SERVICE1_DEFAULT) {
-            Intent changeDefault = new Intent(CardEmulation.ACTION_CHANGE_DEFAULT);
-            changeDefault.putExtra(CardEmulation.EXTRA_CATEGORY, CardEmulation.CATEGORY_PAYMENT);
-            changeDefault.putExtra(CardEmulation.EXTRA_SERVICE_COMPONENT, PaymentService1.COMPONENT);
-            startActivityForResult(changeDefault, 0);
-        } else if (mState == STATE_MAKING_SERVICE2_DEFAULT) {
-            Intent changeDefault = new Intent(CardEmulation.ACTION_CHANGE_DEFAULT);
-            changeDefault.putExtra(CardEmulation.EXTRA_CATEGORY, CardEmulation.CATEGORY_PAYMENT);
-            changeDefault.putExtra(CardEmulation.EXTRA_SERVICE_COMPONENT, PaymentService2.COMPONENT);
-            startActivityForResult(changeDefault, 0);
-        }
-    }
-
-    @Override
-    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-        super.onActivityResult(requestCode, resultCode, data);
-        if (mState == STATE_MAKING_SERVICE1_DEFAULT) {
-            if (!mCardEmulation.isDefaultServiceForCategory(
-                    PaymentService1.COMPONENT, CardEmulation.CATEGORY_PAYMENT)) {
-                // Popup dialog-box, fail test
-                AlertDialog.Builder builder = new AlertDialog.Builder(this);
-                builder.setTitle("Test failed.");
-                builder.setMessage("PaymentService1 is not the default service according " +
-                        "to CardEmulation.getDefaultServiceForCategory(), verify the make " +
-                        "default implementation is correct.");
-                builder.setPositiveButton("OK", null);
-                builder.show();
-            } else {
+    void onPaymentDefaultResult(ComponentName component, boolean success) {
+        if (mState == STATE_MAKING_SERVICE2_DEFAULT) {
+            if (success) {
+                mState = STATE_MAKING_SERVICE1_DEFAULT;
+	            makePaymentDefault(PaymentService1.COMPONENT, R.string.nfc_hce_change_default_help);
+            }
+        } else if (mState == STATE_MAKING_SERVICE1_DEFAULT) {
+            if (success) {
                 mState = STATE_DEFAULT_CHANGED;
                 NfcDialogs.createHceTapReaderDialog(this, null).show();
             }
-        } else if (mState == STATE_MAKING_SERVICE2_DEFAULT) {
-            if (!mCardEmulation.isDefaultServiceForCategory(
-                    PaymentService2.COMPONENT, CardEmulation.CATEGORY_PAYMENT)) {
-                // Popup dialog-box, fail test
-                AlertDialog.Builder builder = new AlertDialog.Builder(this);
-                builder.setTitle("Test failed.");
-                builder.setMessage("PaymentService2 is not the default service according " +
-                        "to CardEmulation.getDefaultServiceForCategory(), verify the make " +
-                        "default implementation is correct.");
-                builder.setPositiveButton("OK", null);
-                builder.show();
-            } else {
-                mState = STATE_MAKING_SERVICE1_DEFAULT;
-                AlertDialog.Builder builder = new AlertDialog.Builder(this);
-                builder.setTitle("Note");
-                builder.setMessage(R.string.nfc_hce_change_default_help);
-                builder.setPositiveButton("OK", this);
-                builder.show();
-            }
         }
     }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/CommandApdu.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/CommandApdu.java
new file mode 100644
index 0000000..3039efd
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/CommandApdu.java
@@ -0,0 +1,49 @@
+package com.android.cts.verifier.nfc.hce;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class CommandApdu implements Parcelable {
+    private String mApdu;
+    private boolean mReachable;
+
+    public CommandApdu(String apdu, boolean reachable) {
+        mApdu = apdu;
+        mReachable = reachable;
+    }
+
+    public boolean isReachable() {
+        return mReachable;
+    }
+
+    public String getApdu() {
+        return mApdu;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public static final Parcelable.Creator<CommandApdu> CREATOR =
+            new Parcelable.Creator<CommandApdu>() {
+        @Override
+        public CommandApdu createFromParcel(Parcel source) {
+            String apdu = source.readString();
+            boolean reachable = source.readInt() != 0 ? true : false;
+            return new CommandApdu(apdu, reachable);
+        }
+
+        @Override
+        public CommandApdu[] newArray(int size) {
+            return new CommandApdu[size];
+        }
+    };
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mApdu);
+        dest.writeInt(mReachable ? 1 : 0);
+    }
+
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/ConflictingNonPaymentPrefixEmulatorActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/ConflictingNonPaymentPrefixEmulatorActivity.java
new file mode 100644
index 0000000..3b0313a
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/ConflictingNonPaymentPrefixEmulatorActivity.java
@@ -0,0 +1,54 @@
+package com.android.cts.verifier.nfc.hce;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.nfc.cardemulation.CardEmulation;
+import android.os.Bundle;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.nfc.NfcDialogs;
+
+import java.util.ArrayList;
+
+public class ConflictingNonPaymentPrefixEmulatorActivity extends BaseEmulatorActivity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.pass_fail_text);
+        setPassFailButtonClickListeners();
+        getPassButton().setEnabled(false);
+        setupServices(this, PrefixTransportService1.COMPONENT, PrefixTransportService2.COMPONENT);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+    }
+
+    @Override
+    void onServicesSetup(boolean result) {
+        // Do dynamic AID registration
+        ArrayList<String> service_aids = new ArrayList<String>();
+        service_aids.add(HceUtils.TRANSPORT_PREFIX_AID + "*");
+        mCardEmulation.registerAidsForService(PrefixTransportService1.COMPONENT, CardEmulation.CATEGORY_OTHER, service_aids);
+        mCardEmulation.registerAidsForService(PrefixTransportService2.COMPONENT, CardEmulation.CATEGORY_OTHER, service_aids);
+        NfcDialogs.createHceTapReaderDialog(this, getString(R.string.nfc_hce_other_conflicting_prefix_aids_help)).show();
+    }
+
+    public static Intent buildReaderIntent(Context context) {
+        Intent readerIntent = new Intent(context, SimpleReaderActivity.class);
+        readerIntent.putExtra(SimpleReaderActivity.EXTRA_APDUS, PrefixTransportService2.APDU_COMMAND_SEQUENCE);
+        readerIntent.putExtra(SimpleReaderActivity.EXTRA_RESPONSES, PrefixTransportService2.APDU_RESPOND_SEQUENCE);
+        readerIntent.putExtra(SimpleReaderActivity.EXTRA_LABEL,
+                context.getString(R.string.nfc_hce_other_conflicting_prefix_aids_reader));
+        return readerIntent;
+    }
+
+    @Override
+    void onApduSequenceComplete(ComponentName component, long duration) {
+        if (component.equals(PrefixTransportService2.COMPONENT)) {
+            getPassButton().setEnabled(true);
+        }
+    }
+}
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/DefaultRouteEmulatorActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/DefaultRouteEmulatorActivity.java
index 2de99e7..fbf07e7 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/DefaultRouteEmulatorActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/DefaultRouteEmulatorActivity.java
@@ -9,8 +9,8 @@
 import com.android.cts.verifier.nfc.NfcDialogs;
 
 public class DefaultRouteEmulatorActivity extends BaseEmulatorActivity {
-    public static final String[] APDU_COMMAND_SEQUENCE = {
-        HceUtils.buildSelectApdu("A000000476416E64726F6964484345"),
+    public static final CommandApdu[] APDU_COMMAND_SEQUENCE = {
+        HceUtils.buildSelectApdu("A000000476416E64726F6964484345", true),
     };
     public static final String[] APDU_RESPONSE_SEQUENCE = {
         "148100009000"
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/DualNonPaymentEmulatorActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/DualNonPaymentEmulatorActivity.java
index 27b063c..0a9362a 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/DualNonPaymentEmulatorActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/DualNonPaymentEmulatorActivity.java
@@ -31,7 +31,7 @@
     public static Intent buildReaderIntent(Context context) {
         Intent readerIntent = new Intent(context, SimpleReaderActivity.class);
         // Combine command/response APDU arrays
-        String[] commandSequences = new String[TransportService2.APDU_COMMAND_SEQUENCE.length +
+        CommandApdu[] commandSequences = new CommandApdu[TransportService2.APDU_COMMAND_SEQUENCE.length +
                                                AccessService.APDU_COMMAND_SEQUENCE.length];
         System.arraycopy(TransportService2.APDU_COMMAND_SEQUENCE, 0, commandSequences, 0,
                 TransportService2.APDU_COMMAND_SEQUENCE.length);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/DualNonPaymentPrefixEmulatorActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/DualNonPaymentPrefixEmulatorActivity.java
new file mode 100644
index 0000000..c02faca
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/DualNonPaymentPrefixEmulatorActivity.java
@@ -0,0 +1,73 @@
+package com.android.cts.verifier.nfc.hce;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.nfc.cardemulation.CardEmulation;
+import android.os.Bundle;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.nfc.NfcDialogs;
+
+import java.util.ArrayList;
+
+public class DualNonPaymentPrefixEmulatorActivity extends BaseEmulatorActivity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.pass_fail_text);
+        setPassFailButtonClickListeners();
+        getPassButton().setEnabled(false);
+        setupServices(this, PrefixTransportService1.COMPONENT, PrefixAccessService.COMPONENT);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+    }
+
+    @Override
+    void onServicesSetup(boolean result) {
+        // Do dynamic AID registration
+        ArrayList<String> service1_aids = new ArrayList<String>();
+        service1_aids.add(HceUtils.TRANSPORT_PREFIX_AID + "*");
+        ArrayList<String> service2_aids = new ArrayList<String>();
+        service2_aids.add(HceUtils.ACCESS_PREFIX_AID + "*");
+        mCardEmulation.registerAidsForService(PrefixTransportService1.COMPONENT, CardEmulation.CATEGORY_OTHER, service1_aids);
+        mCardEmulation.registerAidsForService(PrefixAccessService.COMPONENT, CardEmulation.CATEGORY_OTHER, service2_aids);
+        NfcDialogs.createHceTapReaderDialog(this, getString(R.string.nfc_hce_other_prefix_aids_help)).show();
+    }
+
+    public static Intent buildReaderIntent(Context context) {
+        Intent readerIntent = new Intent(context, SimpleReaderActivity.class);
+        // Combine command/response APDU arrays
+        CommandApdu[] commandSequences = new CommandApdu[PrefixTransportService1.APDU_COMMAND_SEQUENCE.length +
+                PrefixAccessService.APDU_COMMAND_SEQUENCE.length];
+        System.arraycopy(PrefixTransportService1.APDU_COMMAND_SEQUENCE, 0, commandSequences, 0,
+                PrefixTransportService1.APDU_COMMAND_SEQUENCE.length);
+        System.arraycopy(PrefixAccessService.APDU_COMMAND_SEQUENCE, 0, commandSequences,
+                PrefixTransportService1.APDU_COMMAND_SEQUENCE.length,
+                PrefixAccessService.APDU_COMMAND_SEQUENCE.length);
+
+        String[] responseSequences = new String[PrefixTransportService1.APDU_RESPOND_SEQUENCE.length +
+                PrefixAccessService.APDU_RESPOND_SEQUENCE.length];
+        System.arraycopy(PrefixTransportService1.APDU_RESPOND_SEQUENCE, 0, responseSequences, 0,
+                PrefixTransportService1.APDU_RESPOND_SEQUENCE.length);
+        System.arraycopy(PrefixAccessService.APDU_RESPOND_SEQUENCE, 0, responseSequences,
+                PrefixTransportService1.APDU_RESPOND_SEQUENCE.length,
+                PrefixAccessService.APDU_RESPOND_SEQUENCE.length);
+
+        readerIntent.putExtra(SimpleReaderActivity.EXTRA_APDUS, commandSequences);
+        readerIntent.putExtra(SimpleReaderActivity.EXTRA_RESPONSES, responseSequences);
+        readerIntent.putExtra(SimpleReaderActivity.EXTRA_LABEL,
+                context.getString(R.string.nfc_hce_other_prefix_aids_reader));
+        return readerIntent;
+    }
+
+    @Override
+    void onApduSequenceComplete(ComponentName component, long duration) {
+        if (component.equals(PrefixAccessService.COMPONENT)) {
+            getPassButton().setEnabled(true);
+        }
+    }
+}
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/DualPaymentEmulatorActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/DualPaymentEmulatorActivity.java
index 125045f..2e72e09 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/DualPaymentEmulatorActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/DualPaymentEmulatorActivity.java
@@ -1,11 +1,8 @@
 package com.android.cts.verifier.nfc.hce;
 
 import android.annotation.TargetApi;
-import android.app.AlertDialog;
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
 import android.content.Intent;
 import android.nfc.cardemulation.CardEmulation;
 import android.os.Bundle;
@@ -14,7 +11,7 @@
 import com.android.cts.verifier.nfc.NfcDialogs;
 
 @TargetApi(19)
-public class DualPaymentEmulatorActivity extends BaseEmulatorActivity implements OnClickListener {
+public class DualPaymentEmulatorActivity extends BaseEmulatorActivity {
     final static int STATE_IDLE = 0;
     final static int STATE_SERVICE1_SETTING_UP = 1;
     final static int STATE_SERVICE2_SETTING_UP = 2;
@@ -46,43 +43,28 @@
             return;
         }
         // Verify HCE service 2 is the default
-        if (!mCardEmulation.isDefaultServiceForCategory(
-                PaymentService2.COMPONENT, CardEmulation.CATEGORY_PAYMENT)) {
+        if (makePaymentDefault(PaymentService2.COMPONENT, R.string.nfc_hce_change_preinstalled_wallet)) {
             mState = STATE_MAKING_SERVICE2_DEFAULT;
-            AlertDialog.Builder builder = new AlertDialog.Builder(this);
-            builder.setTitle("Note");
-            builder.setMessage(R.string.nfc_hce_change_preinstalled_wallet);
-            builder.setPositiveButton("OK", this);
-            builder.show();
         } else {
+            // Already default
             NfcDialogs.createHceTapReaderDialog(this,null).show();
         }
     }
 
     @Override
+    void onPaymentDefaultResult(ComponentName component, boolean success) {
+        if (success) {
+            NfcDialogs.createHceTapReaderDialog(this, null).show();
+        }
+    }
+
+    @Override
     protected void onPause() {
         super.onPause();
         if (mReceiverRegistered) {
             unregisterReceiver(mReceiver);
         }
     }
-    @Override
-    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-        super.onActivityResult(requestCode, resultCode, data);
-        if (!mCardEmulation.isDefaultServiceForCategory(
-                PaymentService2.COMPONENT, CardEmulation.CATEGORY_PAYMENT)) {
-            // Popup dialog-box, fail test
-            AlertDialog.Builder builder = new AlertDialog.Builder(this);
-            builder.setTitle("Test failed.");
-            builder.setMessage("PaymentService2 is not the default service according " +
-                    "to CardEmulation.getDefaultServiceForCategory(), verify the make " +
-                    "default implementation is correct.");
-            builder.setPositiveButton("OK", null);
-            builder.show();
-        } else {
-            NfcDialogs.createHceTapReaderDialog(this, null).show();
-        }
-    }
     public static Intent buildReaderIntent(Context context) {
         Intent readerIntent = new Intent(context, SimpleReaderActivity.class);
         readerIntent.putExtra(SimpleReaderActivity.EXTRA_APDUS,
@@ -100,12 +82,4 @@
             getPassButton().setEnabled(true);
         }
     }
-
-    @Override
-    public void onClick(DialogInterface dialog, int which) {
-        Intent changeDefault = new Intent(CardEmulation.ACTION_CHANGE_DEFAULT);
-        changeDefault.putExtra(CardEmulation.EXTRA_CATEGORY, CardEmulation.CATEGORY_PAYMENT);
-        changeDefault.putExtra(CardEmulation.EXTRA_SERVICE_COMPONENT, PaymentService2.COMPONENT);
-        startActivityForResult(changeDefault, 0);
-    }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/DynamicAidEmulatorActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/DynamicAidEmulatorActivity.java
new file mode 100644
index 0000000..ae8d50c
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/DynamicAidEmulatorActivity.java
@@ -0,0 +1,73 @@
+package com.android.cts.verifier.nfc.hce;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.nfc.cardemulation.CardEmulation;
+import android.os.Bundle;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.nfc.NfcDialogs;
+
+import java.util.ArrayList;
+
+public class DynamicAidEmulatorActivity extends BaseEmulatorActivity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+       super.onCreate(savedInstanceState);
+       setContentView(R.layout.pass_fail_text);
+       setPassFailButtonClickListeners();
+       getPassButton().setEnabled(false);
+       setupServices(this, PaymentServiceDynamicAids.COMPONENT);
+    }
+
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+    }
+
+
+    @Override
+    void onServicesSetup(boolean result) {
+        ArrayList<String> paymentAids = new ArrayList<String>();
+        paymentAids.add(HceUtils.PPSE_AID);
+        paymentAids.add(HceUtils.VISA_AID);
+        // Register a different set of AIDs for the foreground
+        mCardEmulation.registerAidsForService(PaymentServiceDynamicAids.COMPONENT,
+                CardEmulation.CATEGORY_PAYMENT, paymentAids);
+        // Now make sure it's default
+        if (makePaymentDefault(PaymentServiceDynamicAids.COMPONENT,
+                R.string.nfc_hce_change_preinstalled_wallet)) {
+            // Wait for callback
+        } else {
+	        NfcDialogs.createHceTapReaderDialog(this, getString(R.string.nfc_hce_payment_dynamic_aids_help)).show();
+        }
+    }
+
+    @Override
+    void onPaymentDefaultResult(ComponentName component, boolean success) {
+        if (success) {
+	        NfcDialogs.createHceTapReaderDialog(this, getString(R.string.nfc_hce_payment_dynamic_aids_help)).show();
+        }
+    }
+
+    @Override
+    void onApduSequenceComplete(ComponentName component, long duration) {
+        if (component.equals(PaymentServiceDynamicAids.COMPONENT)) {
+            getPassButton().setEnabled(true);
+        }
+    }
+
+    public static Intent buildReaderIntent(Context context) {
+        Intent readerIntent = new Intent(context, SimpleReaderActivity.class);
+        readerIntent.putExtra(SimpleReaderActivity.EXTRA_APDUS,
+                PaymentServiceDynamicAids.APDU_COMMAND_SEQUENCE);
+        readerIntent.putExtra(SimpleReaderActivity.EXTRA_RESPONSES,
+                PaymentServiceDynamicAids.APDU_RESPOND_SEQUENCE);
+        readerIntent.putExtra(SimpleReaderActivity.EXTRA_LABEL,
+                context.getString(R.string.nfc_hce_payment_dynamic_aids_reader));
+        return readerIntent;
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/ForegroundNonPaymentEmulatorActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/ForegroundNonPaymentEmulatorActivity.java
new file mode 100644
index 0000000..e8bf5f1
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/ForegroundNonPaymentEmulatorActivity.java
@@ -0,0 +1,58 @@
+package com.android.cts.verifier.nfc.hce;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.nfc.NfcDialogs;
+
+public class ForegroundNonPaymentEmulatorActivity extends BaseEmulatorActivity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.pass_fail_text);
+        setPassFailButtonClickListeners();
+        getPassButton().setEnabled(false);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        setupServices(this, TransportService1.COMPONENT, TransportService2.COMPONENT);
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        mCardEmulation.unsetPreferredService(this);
+    }
+
+    @Override
+    void onServicesSetup(boolean result) {
+        // Tell NFC service we prefer TransportService2
+        mCardEmulation.setPreferredService(this, TransportService2.COMPONENT);
+        NfcDialogs.createHceTapReaderDialog(this,
+                getString(R.string.nfc_hce_foreground_non_payment_help)).show();
+    }
+
+    public static Intent buildReaderIntent(Context context) {
+        Intent readerIntent = new Intent(context, SimpleReaderActivity.class);
+        readerIntent.putExtra(SimpleReaderActivity.EXTRA_APDUS,
+                TransportService2.APDU_COMMAND_SEQUENCE);
+        readerIntent.putExtra(SimpleReaderActivity.EXTRA_RESPONSES,
+                TransportService2.APDU_RESPOND_SEQUENCE);
+        readerIntent.putExtra(SimpleReaderActivity.EXTRA_LABEL,
+                context.getString(R.string.nfc_hce_foreground_non_payment_reader));
+        return readerIntent;
+    }
+
+    @Override
+    void onApduSequenceComplete(ComponentName component, long duration) {
+        if (component.equals(TransportService2.COMPONENT)) {
+            getPassButton().setEnabled(true);
+        }
+    }
+
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/ForegroundPaymentEmulatorActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/ForegroundPaymentEmulatorActivity.java
new file mode 100644
index 0000000..27cb061
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/ForegroundPaymentEmulatorActivity.java
@@ -0,0 +1,75 @@
+package com.android.cts.verifier.nfc.hce;
+
+import android.annotation.TargetApi;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.nfc.cardemulation.CardEmulation;
+import android.os.Bundle;
+import android.util.Log;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.nfc.NfcDialogs;
+
+@TargetApi(19)
+public class ForegroundPaymentEmulatorActivity extends BaseEmulatorActivity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.pass_fail_text);
+        setPassFailButtonClickListeners();
+        getPassButton().setEnabled(false);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        if (!mCardEmulation.categoryAllowsForegroundPreference(CardEmulation.CATEGORY_PAYMENT)) {
+            // Launch tap&pay settings
+            NfcDialogs.createChangeForegroundDialog(this).show();
+        } else {
+            setupServices(this, PaymentService2.COMPONENT, PaymentService1.COMPONENT);
+        }
+    }
+
+    @Override
+    void onServicesSetup(boolean result) {
+        if (!makePaymentDefault(PaymentService1.COMPONENT,
+                R.string.nfc_hce_change_preinstalled_wallet)) {
+            mCardEmulation.setPreferredService(this, PaymentService2.COMPONENT);
+            NfcDialogs.createHceTapReaderDialog(this, getString(R.string.nfc_hce_foreground_payment_help)).show();
+        } // else, wait for callback
+    }
+
+    @Override
+    void onPaymentDefaultResult(ComponentName component, boolean success) {
+        if (success) {
+            NfcDialogs.createHceTapReaderDialog(this, null).show();
+        }
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        mCardEmulation.unsetPreferredService(this);
+    }
+
+    public static Intent buildReaderIntent(Context context) {
+        Intent readerIntent = new Intent(context, SimpleReaderActivity.class);
+        readerIntent.putExtra(SimpleReaderActivity.EXTRA_APDUS,
+                PaymentService2.APDU_COMMAND_SEQUENCE);
+        readerIntent.putExtra(SimpleReaderActivity.EXTRA_RESPONSES,
+                PaymentService2.APDU_RESPOND_SEQUENCE);
+        readerIntent.putExtra(SimpleReaderActivity.EXTRA_LABEL,
+                context.getString(R.string.nfc_hce_foreground_payment_reader));
+        return readerIntent;
+    }
+
+    @Override
+    void onApduSequenceComplete(ComponentName component, long duration) {
+        if (component.equals(PaymentService2.COMPONENT)) {
+            getPassButton().setEnabled(true);
+        }
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceEmulatorTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceEmulatorTestActivity.java
index e85d387..87fa3d1 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceEmulatorTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceEmulatorTestActivity.java
@@ -23,6 +23,9 @@
 
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.nfc.NfcAdapter;
+import android.nfc.cardemulation.CardEmulation;
+import android.os.Build;
 import android.os.Bundle;
 
 /** Activity that lists all the NFC HCE emulator tests. */
@@ -37,6 +40,8 @@
 
         ArrayTestListAdapter adapter = new ArrayTestListAdapter(this);
 
+        NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
+        CardEmulation cardEmulation = CardEmulation.getInstance(nfcAdapter);
         if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)) {
             adapter.add(TestListItem.newCategory(this, R.string.nfc_hce_emulator_tests));
 
@@ -62,6 +67,9 @@
                     ChangeDefaultEmulatorActivity.class.getName(),
                     new Intent(this, ChangeDefaultEmulatorActivity.class), null));
 
+            adapter.add(TestListItem.newTest(this, R.string.nfc_hce_foreground_payment_emulator,
+                    ForegroundPaymentEmulatorActivity.class.getName(),
+                    new Intent(this, ForegroundPaymentEmulatorActivity.class), null));
 
             adapter.add(TestListItem.newTest(this, R.string.nfc_hce_single_non_payment_emulator,
                     SingleNonPaymentEmulatorActivity.class.getName(),
@@ -75,6 +83,10 @@
                     ConflictingNonPaymentEmulatorActivity.class.getName(),
                     new Intent(this, ConflictingNonPaymentEmulatorActivity.class), null));
 
+            adapter.add(TestListItem.newTest(this, R.string.nfc_hce_foreground_non_payment_emulator,
+                    ForegroundNonPaymentEmulatorActivity.class.getName(),
+                    new Intent(this, ForegroundNonPaymentEmulatorActivity.class), null));
+
             adapter.add(TestListItem.newTest(this, R.string.nfc_hce_throughput_emulator,
                     ThroughputEmulatorActivity.class.getName(),
                     new Intent(this, ThroughputEmulatorActivity.class), null));
@@ -91,6 +103,29 @@
                     OnAndOffHostEmulatorActivity.class.getName(),
                     new Intent(this, OnAndOffHostEmulatorActivity.class), null));
 
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+                adapter.add(TestListItem.newTest(this, R.string.nfc_hce_payment_dynamic_aids_emulator,
+                        DynamicAidEmulatorActivity.class.getName(),
+                        new Intent(this, DynamicAidEmulatorActivity.class), null));
+
+                if (cardEmulation.supportsAidPrefixRegistration()) {
+                    adapter.add(TestListItem.newTest(this, R.string.nfc_hce_payment_prefix_aids_emulator,
+                            PrefixPaymentEmulatorActivity.class.getName(),
+                            new Intent(this, PrefixPaymentEmulatorActivity.class), null));
+
+                    adapter.add(TestListItem.newTest(this, R.string.nfc_hce_payment_prefix_aids_emulator_2,
+                            PrefixPaymentEmulator2Activity.class.getName(),
+                            new Intent(this, PrefixPaymentEmulator2Activity.class), null));
+
+                    adapter.add(TestListItem.newTest(this, R.string.nfc_hce_other_prefix_aids_emulator,
+                            DualNonPaymentPrefixEmulatorActivity.class.getName(),
+                            new Intent(this, DualNonPaymentPrefixEmulatorActivity.class), null));
+
+                    adapter.add(TestListItem.newTest(this, R.string.nfc_hce_other_conflicting_prefix_aids_emulator,
+                            ConflictingNonPaymentPrefixEmulatorActivity.class.getName(),
+                            new Intent(this, ConflictingNonPaymentPrefixEmulatorActivity.class), null));
+                }
+            }
         }
 
         setTestListAdapter(adapter);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceReaderTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceReaderTestActivity.java
index 704cc89..f628fb7 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceReaderTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceReaderTestActivity.java
@@ -61,6 +61,10 @@
                     SimpleReaderActivity.class.getName(),
                     ChangeDefaultEmulatorActivity.buildReaderIntent(this), null));
 
+            adapter.add(TestListItem.newTest(this, R.string.nfc_hce_foreground_payment_reader,
+                    SimpleReaderActivity.class.getName(),
+                    ForegroundPaymentEmulatorActivity.buildReaderIntent(this), null));
+
             adapter.add(TestListItem.newTest(this, R.string.nfc_hce_single_non_payment_reader,
                     SimpleReaderActivity.class.getName(),
                     SingleNonPaymentEmulatorActivity.buildReaderIntent(this), null));
@@ -73,6 +77,10 @@
                     SimpleReaderActivity.class.getName(),
                     ConflictingNonPaymentEmulatorActivity.buildReaderIntent(this), null));
 
+            adapter.add(TestListItem.newTest(this, R.string.nfc_hce_foreground_non_payment_reader,
+                    SimpleReaderActivity.class.getName(),
+                    ForegroundNonPaymentEmulatorActivity.buildReaderIntent(this), null));
+
             adapter.add(TestListItem.newTest(this, R.string.nfc_hce_throughput_reader,
                     SimpleReaderActivity.class.getName(),
                     ThroughputEmulatorActivity.buildReaderIntent(this), null));
@@ -88,6 +96,26 @@
             adapter.add(TestListItem.newTest(this, R.string.nfc_hce_on_and_offhost_service_reader,
                     SimpleReaderActivity.class.getName(),
                     OnAndOffHostEmulatorActivity.buildReaderIntent(this), null));
+
+            adapter.add(TestListItem.newTest(this, R.string.nfc_hce_payment_dynamic_aids_reader,
+                    SimpleReaderActivity.class.getName(),
+                    DynamicAidEmulatorActivity.buildReaderIntent(this), null));
+
+            adapter.add(TestListItem.newTest(this, R.string.nfc_hce_payment_prefix_aids_reader,
+                    SimpleReaderActivity.class.getName(),
+                    PrefixPaymentEmulatorActivity.buildReaderIntent(this), null));
+
+            adapter.add(TestListItem.newTest(this, R.string.nfc_hce_payment_prefix_aids_reader_2,
+                    SimpleReaderActivity.class.getName(),
+                    PrefixPaymentEmulator2Activity.buildReaderIntent(this), null));
+
+            adapter.add(TestListItem.newTest(this, R.string.nfc_hce_other_prefix_aids_reader,
+                    SimpleReaderActivity.class.getName(),
+                    DualNonPaymentPrefixEmulatorActivity.buildReaderIntent(this), null));
+
+            adapter.add(TestListItem.newTest(this, R.string.nfc_hce_other_conflicting_prefix_aids_reader,
+                    SimpleReaderActivity.class.getName(),
+                    ConflictingNonPaymentPrefixEmulatorActivity.buildReaderIntent(this), null));
         }
 
         setTestListAdapter(adapter);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceService.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceService.java
index 20b34df..e9cd121 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceService.java
@@ -18,13 +18,13 @@
     final static int STATE_FAILED = 2;
 
     // Variables below only used on main thread
-    String[] mCommandApdus = null;
+    CommandApdu[] mCommandApdus = null;
     String[] mResponseApdus = null;
     int mApduIndex = 0;
     int mState = STATE_IDLE;
     long mStartTime;
 
-    public void initialize(String[] commandApdus, String[] responseApdus) {
+    public void initialize(CommandApdu[] commandApdus, String[] responseApdus) {
        mCommandApdus = commandApdus;
        mResponseApdus = responseApdus;
     }
@@ -62,12 +62,27 @@
             mStartTime = System.currentTimeMillis();
         }
 
+
+        if (mApduIndex >= mCommandApdus.length) {
+	        // Skip all APDUs which aren't supposed to reach us
+            return null;
+        }
+
+        do {
+            if (!mCommandApdus[mApduIndex].isReachable()) {
+                mApduIndex++;
+            } else {
+                break;
+            }
+        } while (mApduIndex < mCommandApdus.length);
+
         if (mApduIndex >= mCommandApdus.length) {
             Log.d(TAG, "Ignoring command APDU; protocol complete.");
             // Ignore new APDUs after completion
             return null;
         } else {
-            if (!Arrays.equals(HceUtils.hexStringToBytes(mCommandApdus[mApduIndex]), arg0)) {
+
+            if (!Arrays.equals(HceUtils.hexStringToBytes(mCommandApdus[mApduIndex].getApdu()), arg0)) {
                 Log.d(TAG, "Unexpected command APDU: " + HceUtils.getHexBytes("", arg0));
                 onApduSequenceError();
                 return null;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceUtils.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceUtils.java
index 3bab53b..c67169a 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceUtils.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceUtils.java
@@ -14,10 +14,14 @@
 
     public static final String PPSE_AID = "325041592E5359532E4444463031";
     public static final String MC_AID = "A0000000041010";
+    public static final String VISA_AID = "A0000000030000";
 
     public static final String TRANSPORT_AID = "F001020304";
     public static final String ACCESS_AID = "F005060708";
 
+    public static final String TRANSPORT_PREFIX_AID = "F001020304";
+    public static final String ACCESS_PREFIX_AID = "F005060708";
+
     public static void enableComponent(PackageManager pm, ComponentName component) {
         pm.setComponentEnabledSetting(
                 component,
@@ -58,11 +62,15 @@
         return data;
     }
 
-    public static final String buildSelectApdu(String aid) {
+    public static final CommandApdu buildCommandApdu(String apdu, boolean reachable) {
+        return new CommandApdu(apdu, reachable);
+    }
+
+    public static final CommandApdu buildSelectApdu(String aid, boolean reachable) {
         StringBuilder sb = new StringBuilder();
         sb.append("00A40400");
         sb.append(String.format("%02X", aid.length() / 2));
         sb.append(aid);
-        return sb.toString();
+        return new CommandApdu(sb.toString(), reachable);
     }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/OffHostService.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/OffHostService.java
index c087c99..d8cdf19 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/OffHostService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/OffHostService.java
@@ -7,11 +7,11 @@
             new ComponentName("com.android.cts.verifier",
                     OffHostService.class.getName());
 
-    public static final String[] APDU_COMMAND_SEQUENCE = {
-        HceUtils.buildSelectApdu("A000000151000000"),
-        "80CA9F7F00",
-        HceUtils.buildSelectApdu("A000000003000000"),
-        "80CA9F7F00"
+    public static final CommandApdu[] APDU_COMMAND_SEQUENCE = {
+        HceUtils.buildSelectApdu("A000000151000000", true),
+        HceUtils.buildCommandApdu("80CA9F7F00", true),
+        HceUtils.buildSelectApdu("A000000003000000", true),
+        HceUtils.buildCommandApdu("80CA9F7F00", true)
     };
 
     public static final String[] APDU_RESPOND_SEQUENCE = {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/OnAndOffHostEmulatorActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/OnAndOffHostEmulatorActivity.java
index 3d5190f..d599959 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/OnAndOffHostEmulatorActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/OnAndOffHostEmulatorActivity.java
@@ -6,8 +6,8 @@
 import android.content.Intent;
 import android.os.Bundle;
 
-import com.android.cts.verifier.R;
 import com.android.cts.verifier.nfc.NfcDialogs;
+import com.android.cts.verifier.R;
 
 @TargetApi(19)
 public class OnAndOffHostEmulatorActivity extends BaseEmulatorActivity {
@@ -32,7 +32,7 @@
 
     public static Intent buildReaderIntent(Context context) {
         // Combine command/response APDU arrays
-        String[] commandSequences = new String[OffHostService.APDU_COMMAND_SEQUENCE.length +
+        CommandApdu[] commandSequences = new CommandApdu[OffHostService.APDU_COMMAND_SEQUENCE.length +
                                                AccessService.APDU_COMMAND_SEQUENCE.length];
         System.arraycopy(OffHostService.APDU_COMMAND_SEQUENCE, 0, commandSequences, 0,
                 OffHostService.APDU_COMMAND_SEQUENCE.length);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PaymentService1.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PaymentService1.java
index f6119eb..80df0cb 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PaymentService1.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PaymentService1.java
@@ -9,10 +9,10 @@
             new ComponentName("com.android.cts.verifier",
             PaymentService1.class.getName());
 
-    public static final String[] APDU_COMMAND_SEQUENCE = {
-        HceUtils.buildSelectApdu(HceUtils.PPSE_AID),
-        HceUtils.buildSelectApdu(HceUtils.MC_AID),
-        "80CA01F000"
+    public static final CommandApdu[] APDU_COMMAND_SEQUENCE = {
+        HceUtils.buildSelectApdu(HceUtils.PPSE_AID, true),
+        HceUtils.buildSelectApdu(HceUtils.MC_AID, true),
+        HceUtils.buildCommandApdu("80CA01F000", true)
     };
 
     public static final String[] APDU_RESPOND_SEQUENCE = {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PaymentService2.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PaymentService2.java
index 23664b9..f2c4835 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PaymentService2.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PaymentService2.java
@@ -7,9 +7,9 @@
             new ComponentName("com.android.cts.verifier",
             PaymentService2.class.getName());
 
-    public static final String[] APDU_COMMAND_SEQUENCE = {
-        HceUtils.buildSelectApdu(HceUtils.PPSE_AID),
-        HceUtils.buildSelectApdu(HceUtils.MC_AID)
+    public static final CommandApdu[] APDU_COMMAND_SEQUENCE = {
+        HceUtils.buildSelectApdu(HceUtils.PPSE_AID, true),
+        HceUtils.buildSelectApdu(HceUtils.MC_AID, true)
     };
 
     public static final String[] APDU_RESPOND_SEQUENCE = {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PaymentServiceDynamicAids.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PaymentServiceDynamicAids.java
new file mode 100644
index 0000000..047a667
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PaymentServiceDynamicAids.java
@@ -0,0 +1,32 @@
+package com.android.cts.verifier.nfc.hce;
+
+import android.content.ComponentName;
+
+public class PaymentServiceDynamicAids extends HceService {
+    static final String TAG = "PaymentService1";
+
+    static final ComponentName COMPONENT =
+            new ComponentName("com.android.cts.verifier",
+            PaymentServiceDynamicAids.class.getName());
+
+    public static final CommandApdu[] APDU_COMMAND_SEQUENCE = {
+        HceUtils.buildSelectApdu(HceUtils.PPSE_AID, true),
+        HceUtils.buildSelectApdu(HceUtils.VISA_AID, true),
+        HceUtils.buildCommandApdu("80CA01F000", true)
+    };
+
+    public static final String[] APDU_RESPOND_SEQUENCE = {
+        "FFFF9000",
+        "FF0F9000",
+        "FFDFFFAACB9000"
+    };
+
+    public PaymentServiceDynamicAids() {
+        initialize(APDU_COMMAND_SEQUENCE, APDU_RESPOND_SEQUENCE);
+    }
+
+    @Override
+    public ComponentName getComponent() {
+        return COMPONENT;
+    }
+}
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PrefixAccessService.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PrefixAccessService.java
new file mode 100644
index 0000000..8cecb56
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PrefixAccessService.java
@@ -0,0 +1,34 @@
+package com.android.cts.verifier.nfc.hce;
+
+import android.content.ComponentName;
+
+public class PrefixAccessService extends HceService {
+    static final String TAG = "PrefixAccessService";
+
+    static final ComponentName COMPONENT =
+            new ComponentName("com.android.cts.verifier",
+            PrefixAccessService.class.getName());
+
+    public static final CommandApdu[] APDU_COMMAND_SEQUENCE = {
+        HceUtils.buildSelectApdu(HceUtils.ACCESS_PREFIX_AID + "FFFF", true),
+        HceUtils.buildSelectApdu(HceUtils.ACCESS_PREFIX_AID + "FFAA", true),
+        HceUtils.buildSelectApdu(HceUtils.ACCESS_PREFIX_AID + "FFAABBCCDDEEFF", true),
+        HceUtils.buildCommandApdu("80CA010000010203", true)
+    };
+
+    public static final String[] APDU_RESPOND_SEQUENCE = {
+        "FAFE9000",
+        "FAFE25929000",
+        "FAFEAABB25929000",
+        "FAFEFFAACC25929000"
+    };
+
+    public PrefixAccessService() {
+        initialize(APDU_COMMAND_SEQUENCE, APDU_RESPOND_SEQUENCE);
+    }
+
+    @Override
+    public ComponentName getComponent() {
+        return COMPONENT;
+    }
+}
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PrefixPaymentEmulator2Activity.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PrefixPaymentEmulator2Activity.java
new file mode 100644
index 0000000..5ed6fe9
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PrefixPaymentEmulator2Activity.java
@@ -0,0 +1,84 @@
+package com.android.cts.verifier.nfc.hce;
+
+import android.annotation.TargetApi;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.nfc.NfcDialogs;
+
+@TargetApi(19)
+public class PrefixPaymentEmulator2Activity extends BaseEmulatorActivity {
+    final static int STATE_IDLE = 0;
+    final static int STATE_SERVICE1_SETTING_UP = 1;
+    final static int STATE_SERVICE2_SETTING_UP = 2;
+    final static int STATE_MAKING_SERVICE2_DEFAULT = 3;
+
+    boolean mReceiverRegistered = false;
+    int mState = STATE_IDLE;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.pass_fail_text);
+        setPassFailButtonClickListeners();
+        getPassButton().setEnabled(false);
+        mState = STATE_SERVICE2_SETTING_UP;
+        setupServices(this, PrefixPaymentService2.COMPONENT);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+    }
+
+    @Override
+    void onServicesSetup(boolean result) {
+        if (mState == STATE_SERVICE2_SETTING_UP) {
+            mState = STATE_SERVICE1_SETTING_UP;
+            setupServices(this, PrefixPaymentService1.COMPONENT, PrefixPaymentService2.COMPONENT);
+            return;
+        }
+        // Verify HCE service 2 is the default
+        if (makePaymentDefault(PrefixPaymentService2.COMPONENT, R.string.nfc_hce_change_preinstalled_wallet)) {
+            mState = STATE_MAKING_SERVICE2_DEFAULT;
+        } else {
+            // Already default
+            NfcDialogs.createHceTapReaderDialog(this,getString(R.string.nfc_hce_payment_prefix_aids_help)).show();
+        }
+    }
+
+    @Override
+    void onPaymentDefaultResult(ComponentName component, boolean success) {
+        if (success) {
+            NfcDialogs.createHceTapReaderDialog(this, getString(R.string.nfc_hce_payment_prefix_aids_help)).show();
+        }
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        if (mReceiverRegistered) {
+            unregisterReceiver(mReceiver);
+        }
+    }
+    public static Intent buildReaderIntent(Context context) {
+        Intent readerIntent = new Intent(context, SimpleReaderActivity.class);
+        readerIntent.putExtra(SimpleReaderActivity.EXTRA_APDUS,
+                PrefixPaymentService2.APDU_COMMAND_SEQUENCE);
+        readerIntent.putExtra(SimpleReaderActivity.EXTRA_RESPONSES,
+                PrefixPaymentService2.APDU_RESPOND_SEQUENCE);
+        readerIntent.putExtra(SimpleReaderActivity.EXTRA_LABEL,
+                context.getString(R.string.nfc_hce_payment_prefix_aids_reader_2));
+        return readerIntent;
+    }
+
+    @Override
+    void onApduSequenceComplete(ComponentName component, long duration) {
+        if (component.equals(PrefixPaymentService2.COMPONENT)) {
+            getPassButton().setEnabled(true);
+        }
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PrefixPaymentEmulatorActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PrefixPaymentEmulatorActivity.java
new file mode 100644
index 0000000..d3a4189
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PrefixPaymentEmulatorActivity.java
@@ -0,0 +1,84 @@
+package com.android.cts.verifier.nfc.hce;
+
+import android.annotation.TargetApi;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.nfc.NfcDialogs;
+
+@TargetApi(19)
+public class PrefixPaymentEmulatorActivity extends BaseEmulatorActivity {
+    final static int STATE_IDLE = 0;
+    final static int STATE_SERVICE1_SETTING_UP = 1;
+    final static int STATE_SERVICE2_SETTING_UP = 2;
+    final static int STATE_MAKING_SERVICE1_DEFAULT = 3;
+
+    boolean mReceiverRegistered = false;
+    int mState = STATE_IDLE;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.pass_fail_text);
+        setPassFailButtonClickListeners();
+        getPassButton().setEnabled(false);
+        mState = STATE_SERVICE1_SETTING_UP;
+        setupServices(this, PrefixPaymentService1.COMPONENT);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+    }
+
+    @Override
+    void onServicesSetup(boolean result) {
+        if (mState == STATE_SERVICE1_SETTING_UP) {
+            mState = STATE_SERVICE2_SETTING_UP;
+            setupServices(this, PrefixPaymentService1.COMPONENT, PrefixPaymentService2.COMPONENT);
+            return;
+        }
+        // Verify HCE service 1 is the default
+        if (makePaymentDefault(PrefixPaymentService1.COMPONENT, R.string.nfc_hce_change_preinstalled_wallet)) {
+            mState = STATE_MAKING_SERVICE1_DEFAULT;
+        } else {
+            // Already default
+            NfcDialogs.createHceTapReaderDialog(this, getString(R.string.nfc_hce_payment_prefix_aids_help)).show();
+        }
+    }
+
+    @Override
+    void onPaymentDefaultResult(ComponentName component, boolean success) {
+        if (success) {
+            NfcDialogs.createHceTapReaderDialog(this, getString(R.string.nfc_hce_payment_prefix_aids_help)).show();
+        }
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        if (mReceiverRegistered) {
+            unregisterReceiver(mReceiver);
+        }
+    }
+    public static Intent buildReaderIntent(Context context) {
+        Intent readerIntent = new Intent(context, SimpleReaderActivity.class);
+        readerIntent.putExtra(SimpleReaderActivity.EXTRA_APDUS,
+                PrefixPaymentService1.APDU_COMMAND_SEQUENCE);
+        readerIntent.putExtra(SimpleReaderActivity.EXTRA_RESPONSES,
+                PrefixPaymentService1.APDU_RESPOND_SEQUENCE);
+        readerIntent.putExtra(SimpleReaderActivity.EXTRA_LABEL,
+                context.getString(R.string.nfc_hce_payment_prefix_aids_reader));
+        return readerIntent;
+    }
+
+    @Override
+    void onApduSequenceComplete(ComponentName component, long duration) {
+        if (component.equals(PrefixPaymentService1.COMPONENT)) {
+            getPassButton().setEnabled(true);
+        }
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PrefixPaymentService1.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PrefixPaymentService1.java
new file mode 100644
index 0000000..be6acc2
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PrefixPaymentService1.java
@@ -0,0 +1,32 @@
+package com.android.cts.verifier.nfc.hce;
+
+import android.content.ComponentName;
+
+public class PrefixPaymentService1 extends HceService {
+    static final String TAG = "PrefixPaymentService1";
+
+    static final ComponentName COMPONENT =
+            new ComponentName("com.android.cts.verifier",
+            PrefixPaymentService1.class.getName());
+
+    public static final CommandApdu[] APDU_COMMAND_SEQUENCE = {
+        HceUtils.buildSelectApdu(HceUtils.PPSE_AID, true),
+        HceUtils.buildSelectApdu(HceUtils.MC_AID, true),
+        HceUtils.buildCommandApdu("80CA01F000", true)
+    };
+
+    public static final String[] APDU_RESPOND_SEQUENCE = {
+        "F1239000",
+        "F4569000",
+        "F789FFAABB9000"
+    };
+
+    public PrefixPaymentService1() {
+        initialize(APDU_COMMAND_SEQUENCE, APDU_RESPOND_SEQUENCE);
+    }
+
+    @Override
+    public ComponentName getComponent() {
+        return COMPONENT;
+    }
+}
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PrefixPaymentService2.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PrefixPaymentService2.java
new file mode 100644
index 0000000..9642025
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PrefixPaymentService2.java
@@ -0,0 +1,36 @@
+package com.android.cts.verifier.nfc.hce;
+
+import android.content.ComponentName;
+
+public class PrefixPaymentService2 extends HceService {
+    static final String TAG = "PrefixPaymentService2";
+
+    static final ComponentName COMPONENT =
+            new ComponentName("com.android.cts.verifier",
+            PrefixPaymentService2.class.getName());
+
+    public static final CommandApdu[] APDU_COMMAND_SEQUENCE = {
+        HceUtils.buildSelectApdu(HceUtils.PPSE_AID, true),
+        HceUtils.buildSelectApdu(HceUtils.MC_AID, true),
+        HceUtils.buildCommandApdu("80CA02F000", true),
+        HceUtils.buildSelectApdu("F0000000FFFFFFFFFFFFFFFFFFFFFFFF", true),
+        HceUtils.buildSelectApdu("F000000000", true)
+    };
+
+    public static final String[] APDU_RESPOND_SEQUENCE = {
+        "FAAA9000",
+        "FBBB9000",
+        "F789FFCCDD9000",
+        "FFBAFEBECA",
+        "F0BABEFECA"
+    };
+
+    public PrefixPaymentService2() {
+        initialize(APDU_COMMAND_SEQUENCE, APDU_RESPOND_SEQUENCE);
+    }
+
+    @Override
+    public ComponentName getComponent() {
+        return COMPONENT;
+    }
+}
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PrefixTransportService1.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PrefixTransportService1.java
new file mode 100644
index 0000000..5521440
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PrefixTransportService1.java
@@ -0,0 +1,34 @@
+package com.android.cts.verifier.nfc.hce;
+
+import android.content.ComponentName;
+
+public class PrefixTransportService1 extends HceService {
+    static final String TAG = "PrefixTransportService1";
+
+    static final ComponentName COMPONENT =
+            new ComponentName("com.android.cts.verifier",
+            PrefixTransportService1.class.getName());
+
+    public static final CommandApdu[] APDU_COMMAND_SEQUENCE = {
+        HceUtils.buildSelectApdu(HceUtils.TRANSPORT_PREFIX_AID + "FFFF", true),
+        HceUtils.buildSelectApdu(HceUtils.TRANSPORT_PREFIX_AID + "FFAA", true),
+        HceUtils.buildSelectApdu(HceUtils.TRANSPORT_PREFIX_AID + "FFAABBCCDDEEFF", true),
+        HceUtils.buildCommandApdu("80CA01FFAA", true)
+    };
+
+    public static final String[] APDU_RESPOND_SEQUENCE = {
+        "25929000",
+        "FFEF25929000",
+        "FFDFFFAABB25929000",
+        "FFDFFFAACC25929000"
+    };
+
+    public PrefixTransportService1() {
+        initialize(APDU_COMMAND_SEQUENCE, APDU_RESPOND_SEQUENCE);
+    }
+
+    @Override
+    public ComponentName getComponent() {
+        return COMPONENT;
+    }
+}
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PrefixTransportService2.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PrefixTransportService2.java
new file mode 100644
index 0000000..2235446
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/PrefixTransportService2.java
@@ -0,0 +1,34 @@
+package com.android.cts.verifier.nfc.hce;
+
+import android.content.ComponentName;
+
+public class PrefixTransportService2 extends HceService {
+    static final String TAG = "PrefixTransportService2";
+
+    static final ComponentName COMPONENT =
+            new ComponentName("com.android.cts.verifier",
+            PrefixTransportService2.class.getName());
+
+    public static final CommandApdu[] APDU_COMMAND_SEQUENCE = {
+        HceUtils.buildSelectApdu(HceUtils.TRANSPORT_PREFIX_AID + "FFFF", true),
+        HceUtils.buildSelectApdu(HceUtils.TRANSPORT_PREFIX_AID + "FFAA", true),
+        HceUtils.buildSelectApdu(HceUtils.TRANSPORT_PREFIX_AID + "FFAABBCCDDEEFF", true),
+        HceUtils.buildCommandApdu("80CA01FFBB", true)
+    };
+
+    public static final String[] APDU_RESPOND_SEQUENCE = {
+        "36039000",
+        "FFBB25929000",
+        "FFDFFFBBBB25929000",
+        "FFDFFFBBCC25929000"
+    };
+
+    public PrefixTransportService2() {
+        initialize(APDU_COMMAND_SEQUENCE, APDU_RESPOND_SEQUENCE);
+    }
+
+    @Override
+    public ComponentName getComponent() {
+        return COMPONENT;
+    }
+}
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/SimpleReaderActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/SimpleReaderActivity.java
index 6c15811..638bc6f 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/SimpleReaderActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/SimpleReaderActivity.java
@@ -9,6 +9,7 @@
 import android.nfc.tech.IsoDep;
 import android.nfc.Tag;
 import android.os.Bundle;
+import android.os.Parcelable;
 import android.util.Log;
 import android.view.View;
 import android.widget.AdapterView;
@@ -34,7 +35,7 @@
     public static final String EXTRA_LABEL = "label";
 
     NfcAdapter mAdapter;
-    String[] mApdus;
+    CommandApdu[] mApdus;
     String[] mResponses;
 
     TextView mTextView;
@@ -76,7 +77,15 @@
         mAdapter.enableReaderMode(this, this, NfcAdapter.FLAG_READER_NFC_A |
                 NfcAdapter.FLAG_READER_NFC_BARCODE | NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK, null);
         Intent intent = getIntent();
-        mApdus = intent.getStringArrayExtra(EXTRA_APDUS);
+        Parcelable[] apdus = intent.getParcelableArrayExtra(EXTRA_APDUS);
+        if (apdus != null) {
+	        mApdus = new CommandApdu[apdus.length];
+	        for (int i = 0; i < apdus.length; i++) {
+	            mApdus[i] = (CommandApdu) apdus[i];
+	        }
+        } else {
+            mApdus = null;
+        }
         mResponses = intent.getStringArrayExtra(EXTRA_RESPONSES);
     }
 
@@ -95,11 +104,11 @@
             int count = 0;
             boolean success = true;
             long startTime = System.currentTimeMillis();
-            for (String apdu: mApdus) {
+            for (CommandApdu apdu: mApdus) {
                 sb.append("Request APDU:\n");
-                sb.append(apdu + "\n\n");
+                sb.append(apdu.getApdu() + "\n\n");
                 long apduStartTime = System.currentTimeMillis();
-                byte[] response = isoDep.transceive(HceUtils.hexStringToBytes(apdu));
+                byte[] response = isoDep.transceive(HceUtils.hexStringToBytes(apdu.getApdu()));
                 long apduEndTime = System.currentTimeMillis();
                 sb.append("Response APDU (in " + Long.toString(apduEndTime - apduStartTime) +
                         " ms):\n");
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/SinglePaymentEmulatorActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/SinglePaymentEmulatorActivity.java
index 13b2fe8..0f1fba0 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/SinglePaymentEmulatorActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/SinglePaymentEmulatorActivity.java
@@ -1,19 +1,15 @@
 package com.android.cts.verifier.nfc.hce;
 
 import android.annotation.TargetApi;
-import android.app.AlertDialog;
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
 import android.content.Intent;
-import android.nfc.cardemulation.CardEmulation;
 import android.os.Bundle;
 import com.android.cts.verifier.R;
 import com.android.cts.verifier.nfc.NfcDialogs;
 
 @TargetApi(19)
-public class SinglePaymentEmulatorActivity extends BaseEmulatorActivity implements OnClickListener {
+public class SinglePaymentEmulatorActivity extends BaseEmulatorActivity {
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -31,18 +27,21 @@
     @Override
     void onServicesSetup(boolean result) {
         // Verify HCE service 1 is the default
-        if (!mCardEmulation.isDefaultServiceForCategory(
-                PaymentService1.COMPONENT, CardEmulation.CATEGORY_PAYMENT)) {
-            AlertDialog.Builder builder = new AlertDialog.Builder(this);
-            builder.setTitle("Note");
-            builder.setMessage(R.string.nfc_hce_change_preinstalled_wallet);
-            builder.setPositiveButton("OK", this);
-            builder.show();
+        if (makePaymentDefault(PaymentService1.COMPONENT,
+                R.string.nfc_hce_change_preinstalled_wallet)) {
+            // Wait for callback
         } else {
 	        NfcDialogs.createHceTapReaderDialog(this, null).show();
         }
     }
 
+    @Override
+    void onPaymentDefaultResult(ComponentName component, boolean success) {
+        if (success) {
+	        NfcDialogs.createHceTapReaderDialog(this, null).show();
+        }
+    }
+
     public static Intent buildReaderIntent(Context context) {
         Intent readerIntent = new Intent(context, SimpleReaderActivity.class);
         readerIntent.putExtra(SimpleReaderActivity.EXTRA_APDUS,
@@ -60,30 +59,4 @@
             getPassButton().setEnabled(true);
         }
     }
-
-    @Override
-    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-        super.onActivityResult(requestCode, resultCode, data);
-        if (!mCardEmulation.isDefaultServiceForCategory(
-                PaymentService1.COMPONENT, CardEmulation.CATEGORY_PAYMENT)) {
-            // Popup dialog-box, fail test
-            AlertDialog.Builder builder = new AlertDialog.Builder(this);
-            builder.setTitle("Test failed.");
-            builder.setMessage("PaymentService1 is not the default service according " +
-                    "to CardEmulation.getDefaultServiceForCategory(), verify the make " +
-                    "default implementation is correct.");
-            builder.setPositiveButton("OK", null);
-            builder.show();
-        } else {
-            NfcDialogs.createHceTapReaderDialog(this, null).show();
-        }
-    }
-
-    @Override
-    public void onClick(DialogInterface dialog, int which) {
-        Intent changeDefault = new Intent(CardEmulation.ACTION_CHANGE_DEFAULT);
-        changeDefault.putExtra(CardEmulation.EXTRA_CATEGORY, CardEmulation.CATEGORY_PAYMENT);
-        changeDefault.putExtra(CardEmulation.EXTRA_SERVICE_COMPONENT, PaymentService1.COMPONENT);
-        startActivityForResult(changeDefault, 0);
-    }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/ThroughputService.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/ThroughputService.java
index 8f826ff..b74f0b7 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/ThroughputService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/ThroughputService.java
@@ -9,23 +9,23 @@
             new ComponentName("com.android.cts.verifier",
             ThroughputService.class.getName());
 
-    public static final String[] APDU_COMMAND_SEQUENCE = {
-        HceUtils.buildSelectApdu("F0010203040607FF"),
-        "80CA010000",
-        "80CA010100",
-        "80CA010200",
-        "80CA010300",
-        "80CA010400",
-        "80CA010500",
-        "80CA010600",
-        "80CA010700",
-        "80CA010800",
-        "80CA010900",
-        "80CA010A00",
-        "80CA010B00",
-        "80CA010C00",
-        "80CA010D00",
-        "80CA010E00",
+    public static final CommandApdu[] APDU_COMMAND_SEQUENCE = {
+        HceUtils.buildSelectApdu("F0010203040607FF", true),
+        HceUtils.buildCommandApdu("80CA010100", true),
+        HceUtils.buildCommandApdu("80CA010200", true),
+        HceUtils.buildCommandApdu("80CA010300", true),
+        HceUtils.buildCommandApdu("80CA010400", true),
+        HceUtils.buildCommandApdu("80CA010500", true),
+        HceUtils.buildCommandApdu("80CA010600", true),
+        HceUtils.buildCommandApdu("80CA010700", true),
+        HceUtils.buildCommandApdu("80CA010800", true),
+        HceUtils.buildCommandApdu("80CA010900", true),
+        HceUtils.buildCommandApdu("80CA010A00", true),
+        HceUtils.buildCommandApdu("80CA010B00", true),
+        HceUtils.buildCommandApdu("80CA010C00", true),
+        HceUtils.buildCommandApdu("80CA010D00", true),
+        HceUtils.buildCommandApdu("80CA010E00", true),
+        HceUtils.buildCommandApdu("80CA010F00", true),
     };
 
     public static final String[] APDU_RESPOND_SEQUENCE = {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/TransportService1.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/TransportService1.java
index c751e76..c8d8460 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/TransportService1.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/TransportService1.java
@@ -7,9 +7,9 @@
             new ComponentName("com.android.cts.verifier",
             TransportService1.class.getName());
 
-    public static final String[] APDU_COMMAND_SEQUENCE = {
-        HceUtils.buildSelectApdu(HceUtils.TRANSPORT_AID),
-        "80CA01E000"
+    public static final CommandApdu[] APDU_COMMAND_SEQUENCE = {
+        HceUtils.buildSelectApdu(HceUtils.TRANSPORT_AID, true),
+        HceUtils.buildCommandApdu("80CA01E000", true)
     };
 
     public static final String[] APDU_RESPOND_SEQUENCE = {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/TransportService2.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/TransportService2.java
index 0815b9c..322a076 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/TransportService2.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/TransportService2.java
@@ -7,9 +7,9 @@
             new ComponentName("com.android.cts.verifier",
             TransportService2.class.getName());
 
-    public static final String[] APDU_COMMAND_SEQUENCE = {
-        HceUtils.buildSelectApdu(HceUtils.TRANSPORT_AID),
-        "80CA01E100"
+    public static final CommandApdu[] APDU_COMMAND_SEQUENCE = {
+        HceUtils.buildSelectApdu(HceUtils.TRANSPORT_AID, true),
+        HceUtils.buildCommandApdu("80CA01E100", true)
     };
 
     public static final String[] APDU_RESPOND_SEQUENCE = {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nls/MockListener.java b/apps/CtsVerifier/src/com/android/cts/verifier/nls/MockListener.java
deleted file mode 100644
index 0b74fa3..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nls/MockListener.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.cts.verifier.nls;
-
-import android.app.Activity;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.service.notification.NotificationListenerService;
-import android.service.notification.StatusBarNotification;
-import android.util.Log;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class MockListener extends NotificationListenerService {
-    static final String TAG = "MockListener";
-
-    static final String SERVICE_CHECK = "android.service.notification.cts.SERVICE_CHECK";
-    static final String SERVICE_POSTED = "android.service.notification.cts.SERVICE_POSTED";
-    static final String SERVICE_PAYLOADS = "android.service.notification.cts.SERVICE_PAYLOADS";
-    static final String SERVICE_REMOVED = "android.service.notification.cts.SERVICE_REMOVED";
-    static final String SERVICE_RESET = "android.service.notification.cts.SERVICE_RESET";
-    static final String SERVICE_CLEAR_ONE = "android.service.notification.cts.SERVICE_CLEAR_ONE";
-    static final String SERVICE_CLEAR_ALL = "android.service.notification.cts.SERVICE_CLEAR_ALL";
-
-    static final String EXTRA_PAYLOAD = "TAGS";
-    static final String EXTRA_TAG = "TAG";
-    static final String EXTRA_CODE = "CODE";
-
-    static final int RESULT_TIMEOUT = Activity.RESULT_FIRST_USER;
-    static final int RESULT_NO_SERVER = Activity.RESULT_FIRST_USER + 1;
-
-    public static final String JSON_FLAGS = "flag";
-    public static final String JSON_ICON = "icon";
-    public static final String JSON_ID = "id";
-    public static final String JSON_PACKAGE = "pkg";
-    public static final String JSON_WHEN = "when";
-    public static final String JSON_TAG = "tag";
-
-    private ArrayList<String> mPosted = new ArrayList<String>();
-    private ArrayList<String> mPayloads = new ArrayList<String>();
-    private ArrayList<String> mRemoved = new ArrayList<String>();
-    private BroadcastReceiver mReceiver;
-
-    @Override
-    public void onCreate() {
-        super.onCreate();
-        Log.d(TAG, "created");
-
-        mPosted = new ArrayList<String>();
-        mRemoved = new ArrayList<String>();
-
-        mReceiver = new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                String action = intent.getAction();
-                if (SERVICE_CHECK.equals(action)) {
-                    Log.d(TAG, "SERVICE_CHECK");
-                    setResultCode(Activity.RESULT_OK);
-                } else if (SERVICE_POSTED.equals(action)) {
-                    Log.d(TAG, "SERVICE_POSTED");
-                    Bundle bundle = new Bundle();
-                    bundle.putStringArrayList(EXTRA_PAYLOAD, mPosted);
-                    setResultExtras(bundle);
-                    setResultCode(Activity.RESULT_OK);
-                } else if (SERVICE_PAYLOADS.equals(action)) {
-                    Log.d(TAG, "SERVICE_PAYLOADS");
-                    Bundle bundle = new Bundle();
-                    bundle.putStringArrayList(EXTRA_PAYLOAD, mPayloads);
-                    setResultExtras(bundle);
-                    setResultCode(Activity.RESULT_OK);
-                } else if (SERVICE_REMOVED.equals(action)) {
-                    Log.d(TAG, "SERVICE_REMOVED");
-                    Bundle bundle = new Bundle();
-                    bundle.putStringArrayList(EXTRA_PAYLOAD, mRemoved);
-                    setResultExtras(bundle);
-                    setResultCode(Activity.RESULT_OK);
-                } else if (SERVICE_CLEAR_ONE.equals(action)) {
-                    Log.d(TAG, "SERVICE_CLEAR_ONE");
-                    MockListener.this.cancelNotification(
-                            context.getApplicationInfo().packageName,
-                            intent.getStringExtra(EXTRA_TAG),
-                            intent.getIntExtra(EXTRA_CODE, 0));
-                } else if (SERVICE_CLEAR_ALL.equals(action)) {
-                    Log.d(TAG, "SERVICE_CLEAR_ALL");
-                    MockListener.this.cancelAllNotifications();
-                } else if (SERVICE_RESET.equals(action)) {
-                    Log.d(TAG, "SERVICE_RESET");
-                    resetData();
-                } else {
-                    Log.w(TAG, "unknown action");
-                    setResultCode(Activity.RESULT_CANCELED);
-                }
-            }
-        };
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(SERVICE_CHECK);
-        filter.addAction(SERVICE_POSTED);
-        filter.addAction(SERVICE_PAYLOADS);
-        filter.addAction(SERVICE_REMOVED);
-        filter.addAction(SERVICE_CLEAR_ONE);
-        filter.addAction(SERVICE_CLEAR_ALL);
-        filter.addAction(SERVICE_RESET);
-        registerReceiver(mReceiver, filter);
-    }
-
-    @Override
-    public void onDestroy() {
-        super.onDestroy();
-        unregisterReceiver(mReceiver);
-        mReceiver = null;
-        Log.d(TAG, "destroyed");
-    }
-
-    public void resetData() {
-        mPosted.clear();
-        mPayloads.clear();
-        mRemoved.clear();
-    }
-
-    @Override
-    public void onNotificationPosted(StatusBarNotification sbn) {
-        Log.d(TAG, "posted: " + sbn.getTag());
-        mPosted.add(sbn.getTag());
-        JSONObject payload = new JSONObject();
-        try {
-            payload.put(JSON_TAG, sbn.getTag());
-            payload.put(JSON_ID, sbn.getId());
-            payload.put(JSON_PACKAGE, sbn.getPackageName());
-            payload.put(JSON_WHEN, sbn.getNotification().when);
-            payload.put(JSON_ICON, sbn.getNotification().icon);
-            payload.put(JSON_FLAGS, sbn.getNotification().flags);
-            mPayloads.add(payload.toString());
-        } catch (JSONException e) {
-            Log.e(TAG, "failed to pack up notification payload", e);
-        }
-    }
-
-    @Override
-    public void onNotificationRemoved(StatusBarNotification sbn) {
-        Log.d(TAG, "removed: " + sbn.getTag());
-        mRemoved.add(sbn.getTag());
-    }
-
-    public static void resetListenerData(Context context) {
-        sendCommand(context, SERVICE_RESET, null, 0);
-    }
-
-    public static void probeListenerStatus(Context context, IntegerResultCatcher catcher) {
-        requestIntegerResult(context, SERVICE_CHECK, catcher);
-    }
-
-    public static void probeListenerPosted(Context context, StringListResultCatcher catcher) {
-        requestStringListResult(context, SERVICE_POSTED, catcher);
-    }
-
-    public static void probeListenerPayloads(Context context, StringListResultCatcher catcher) {
-        requestStringListResult(context, SERVICE_PAYLOADS, catcher);
-    }
-
-    public static void probeListenerRemoved(Context context, StringListResultCatcher catcher) {
-        requestStringListResult(context, SERVICE_REMOVED, catcher);
-    }
-
-    public static void clearOne(Context context, String tag, int code) {
-        sendCommand(context, SERVICE_CLEAR_ONE, tag, code);
-    }
-
-    public static void clearAll(Context context) {
-        sendCommand(context, SERVICE_CLEAR_ALL, null, 0);
-    }
-
-    private static void sendCommand(Context context, String action, String tag, int code) {
-        Intent broadcast = new Intent(action);
-        if (tag != null) {
-            broadcast.putExtra(EXTRA_TAG, tag);
-            broadcast.putExtra(EXTRA_CODE, code);
-        }
-        context.sendBroadcast(broadcast);
-    }
-
-    public abstract static class IntegerResultCatcher extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            accept(Integer.valueOf(getResultCode()));
-        }
-
-        abstract public void accept(int result);
-    }
-
-    private static void requestIntegerResult(Context context, String action,
-            IntegerResultCatcher catcher) {
-        Intent broadcast = new Intent(action);
-        context.sendOrderedBroadcast(broadcast, null, catcher, null, RESULT_NO_SERVER, null, null);
-    }
-
-    public abstract static class StringListResultCatcher extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            accept(getResultExtras(true).getStringArrayList(EXTRA_PAYLOAD));
-        }
-
-        abstract public void accept(List<String> result);
-    }
-
-    private static void requestStringListResult(Context context, String action,
-            StringListResultCatcher catcher) {
-        Intent broadcast = new Intent(action);
-        context.sendOrderedBroadcast(broadcast, null, catcher, null, RESULT_NO_SERVER, null, null);
-    }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nls/NotificationListenerVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/nls/NotificationListenerVerifierActivity.java
deleted file mode 100644
index 842c024..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nls/NotificationListenerVerifierActivity.java
+++ /dev/null
@@ -1,630 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.verifier.nls;
-
-import static com.android.cts.verifier.nls.MockListener.JSON_FLAGS;
-import static com.android.cts.verifier.nls.MockListener.JSON_ICON;
-import static com.android.cts.verifier.nls.MockListener.JSON_ID;
-import static com.android.cts.verifier.nls.MockListener.JSON_PACKAGE;
-import static com.android.cts.verifier.nls.MockListener.JSON_TAG;
-import static com.android.cts.verifier.nls.MockListener.JSON_WHEN;
-
-import android.annotation.SuppressLint;
-import android.app.Activity;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.app.Service;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.provider.Settings.Secure;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-import com.android.cts.verifier.nfc.TagVerifierActivity;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.LinkedBlockingQueue;
-
-public class NotificationListenerVerifierActivity extends PassFailButtons.Activity
-implements Runnable {
-    static final String TAG = TagVerifierActivity.class.getSimpleName();
-    private static final String STATE = "state";
-    private static final String LISTENER_PATH = "com.android.cts.verifier/" + 
-            "com.android.cts.verifier.nls.MockListener";
-    private static final int SETUP = 0;
-    private static final int PASS = 1;
-    private static final int FAIL = 2;
-    private static final int WAIT_FOR_USER = 3;
-    private static final int CLEARED = 4;
-    private static final int READY = 5;
-    private static final int RETRY = 6;
-    private static final int NOTIFICATION_ID = 1001;
-    private static LinkedBlockingQueue<String> sDeletedQueue = new LinkedBlockingQueue<String>();
-
-    private int mState;
-    private int[] mStatus;
-    private LayoutInflater mInflater;
-    private ViewGroup mItemList;
-    private PackageManager mPackageManager;
-    private String mTag1;
-    private String mTag2;
-    private String mTag3;
-    private NotificationManager mNm;
-    private Context mContext;
-    private Runnable mRunner;
-    private View mHandler;
-    private String mPackageString;
-    private int mIcon1;
-    private int mIcon2;
-    private int mIcon3;
-    private int mId1;
-    private int mId2;
-    private int mId3;
-    private long mWhen1;
-    private long mWhen2;
-    private long mWhen3;
-    private int mFlag1;
-    private int mFlag2;
-    private int mFlag3;
-
-    public static class DismissService extends Service {
-        @Override
-        public IBinder onBind(Intent intent) {
-            return null;
-        }
-
-        @Override
-        public void onStart(Intent intent, int startId) {
-            sDeletedQueue.offer(intent.getAction());
-        }
-    }
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        if (savedInstanceState != null) {
-            mState = savedInstanceState.getInt(STATE, 0);
-        }
-        mContext = this;
-        mRunner = this;
-        mNm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
-        mPackageManager = getPackageManager();
-        mInflater = getLayoutInflater();
-        View view = mInflater.inflate(R.layout.nls_main, null);
-        mItemList = (ViewGroup) view.findViewById(R.id.nls_test_items);
-        mHandler = mItemList;
-        createTestItems();
-        mStatus = new int[mItemList.getChildCount()];
-        setContentView(view);
-
-        setPassFailButtonClickListeners();
-        setInfoResources(R.string.nls_test, R.string.nls_info, -1);
-
-        getPassButton().setEnabled(false);
-    }
-
-    @Override
-    protected void onSaveInstanceState (Bundle outState) {
-        outState.putInt(STATE, mState);
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        next();
-    }
-
-    // Interface Utilities
-
-    private void createTestItems() {
-        createUserItem(R.string.nls_enable_service);
-        createAutoItem(R.string.nls_service_started);
-        createAutoItem(R.string.nls_note_received);
-        createAutoItem(R.string.nls_payload_intact);
-        createAutoItem(R.string.nls_clear_one);
-        createAutoItem(R.string.nls_clear_all);
-        createUserItem(R.string.nls_disable_service);
-        createAutoItem(R.string.nls_service_stopped);
-        createAutoItem(R.string.nls_note_missed);
-    }
-
-    private void setItemState(int index, boolean passed) {
-        ViewGroup item = (ViewGroup) mItemList.getChildAt(index);
-        ImageView status = (ImageView) item.findViewById(R.id.nls_status);
-        status.setImageResource(passed ? R.drawable.fs_good : R.drawable.fs_error);
-        View button = item.findViewById(R.id.nls_launch_settings);
-        button.setClickable(false);
-        button.setEnabled(false);
-        status.invalidate();
-    }
-
-    private void markItemWaiting(int index) {
-        ViewGroup item = (ViewGroup) mItemList.getChildAt(index);
-        ImageView status = (ImageView) item.findViewById(R.id.nls_status);
-        status.setImageResource(R.drawable.fs_warning);
-        status.invalidate();
-    }
-
-    private View createUserItem(int stringId) {
-        View item = mInflater.inflate(R.layout.nls_item, mItemList, false);
-        TextView instructions = (TextView) item.findViewById(R.id.nls_instructions);
-        instructions.setText(stringId);
-        mItemList.addView(item);
-        return item;
-    }
-
-    private View createAutoItem(int stringId) {
-        View item = mInflater.inflate(R.layout.nls_item, mItemList, false);
-        TextView instructions = (TextView) item.findViewById(R.id.nls_instructions);
-        instructions.setText(stringId);
-        View button = item.findViewById(R.id.nls_launch_settings);
-        button.setVisibility(View.GONE);
-        mItemList.addView(item);
-        return item;
-    }
-
-    // Test management
-
-    public void run() {
-        while (mState < mStatus.length && mStatus[mState] != WAIT_FOR_USER) {
-            if (mStatus[mState] == PASS) {
-                setItemState(mState, true);
-                mState++;
-            } else if (mStatus[mState] == FAIL) {
-                setItemState(mState, false);
-                return;
-            } else {
-                break;
-            }
-        }
-
-        if (mState < mStatus.length && mStatus[mState] == WAIT_FOR_USER) {
-            markItemWaiting(mState);
-        }
-
-        switch (mState) {
-            case 0:
-                testIsEnabled(0);
-                break;
-            case 1:
-                testIsStarted(1);
-                break;
-            case 2:
-                testNotificationRecieved(2);
-                break;
-            case 3:
-                testDataIntact(3);
-                break;
-            case 4:
-                testDismissOne(4);
-                break;
-            case 5:
-                testDismissAll(5);
-                break;
-            case 6:
-                testIsDisabled(6);
-                break;
-            case 7:
-                testIsStopped(7);
-                break;
-            case 8:
-                testNotificationNotRecieved(8);
-                break;
-            case 9:
-                getPassButton().setEnabled(true);
-                mNm.cancelAll();
-                break;
-        }
-    }
-
-    public void launchSettings(View button) {
-        startActivity(
-                new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"));
-    }
-
-    private PendingIntent makeIntent(int code, String tag) {
-        Intent intent = new Intent(tag);
-        intent.setComponent(new ComponentName(mContext, DismissService.class));
-        PendingIntent pi = PendingIntent.getService(mContext, code, intent,
-                PendingIntent.FLAG_UPDATE_CURRENT);
-        return pi;
-    }
-
-    @SuppressLint("NewApi")
-    private void sendNotificaitons() {
-        mTag1 = UUID.randomUUID().toString();
-        mTag2 = UUID.randomUUID().toString();
-        mTag3 = UUID.randomUUID().toString();
-
-        mNm.cancelAll();
-
-        mWhen1 = System.currentTimeMillis() + 1;
-        mWhen2 = System.currentTimeMillis() + 2;
-        mWhen3 = System.currentTimeMillis() + 3;
-
-        mIcon1 = R.drawable.fs_good;
-        mIcon2 = R.drawable.fs_error;
-        mIcon3 = R.drawable.fs_warning;
-
-        mId1 = NOTIFICATION_ID + 1;
-        mId2 = NOTIFICATION_ID + 2;
-        mId3 = NOTIFICATION_ID + 3;
-
-        mPackageString = "com.android.cts.verifier";
-
-        Notification n1 = new Notification.Builder(mContext)
-        .setContentTitle("ClearTest 1")
-        .setContentText(mTag1.toString())
-        .setPriority(Notification.PRIORITY_LOW)
-        .setSmallIcon(mIcon1)
-        .setWhen(mWhen1)
-        .setDeleteIntent(makeIntent(1, mTag1))
-        .setOnlyAlertOnce(true)
-        .build();
-        mNm.notify(mTag1, mId1, n1);
-        mFlag1 = Notification.FLAG_ONLY_ALERT_ONCE;
-
-        Notification n2 = new Notification.Builder(mContext)
-        .setContentTitle("ClearTest 2")
-        .setContentText(mTag2.toString())
-        .setPriority(Notification.PRIORITY_HIGH)
-        .setSmallIcon(mIcon2)
-        .setWhen(mWhen2)
-        .setDeleteIntent(makeIntent(2, mTag2))
-        .setAutoCancel(true)
-        .build();
-        mNm.notify(mTag2, mId2, n2);
-        mFlag2 = Notification.FLAG_AUTO_CANCEL;
-
-        Notification n3 = new Notification.Builder(mContext)
-        .setContentTitle("ClearTest 3")
-        .setContentText(mTag3.toString())
-        .setPriority(Notification.PRIORITY_LOW)
-        .setSmallIcon(mIcon3)
-        .setWhen(mWhen3)
-        .setDeleteIntent(makeIntent(3, mTag3))
-        .setAutoCancel(true)
-        .setOnlyAlertOnce(true)
-        .build();
-        mNm.notify(mTag3, mId3, n3);
-        mFlag3 = Notification.FLAG_ONLY_ALERT_ONCE | Notification.FLAG_AUTO_CANCEL;
-    }
-
-    /**
-     * Return to the state machine to progress through the tests.
-     */
-    private void next() {
-        mHandler.post(mRunner);
-    }
-
-    /**
-     * Wait for things to settle before returning to the state machine.
-     */
-    private void delay() {
-        mHandler.postDelayed(mRunner, 2000);
-    }
-
-    boolean checkEquals(long expected, long actual, String message) {
-        if (expected == actual) {
-            return true;
-        }
-        logWithStack(String.format(message, expected, actual));
-        return false;
-    }
-
-    boolean checkEquals(String expected, String actual, String message) {
-        if (expected.equals(actual)) {
-            return true;
-        }
-        logWithStack(String.format(message, expected, actual));
-        return false;
-    }
-
-    boolean checkFlagSet(int expected, int actual, String message) {
-        if ((expected & actual) != 0) {
-            return true;
-        }
-        logWithStack(String.format(message, expected, actual));
-        return false;
-    };
-
-    private void logWithStack(String message) {
-        Throwable stackTrace = new Throwable();
-        stackTrace.fillInStackTrace();
-        Log.e(TAG, message, stackTrace);
-    }
-
-    // Tests
-
-    private void testIsEnabled(int i) {
-        // no setup required
-        Intent settings = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
-        if (settings.resolveActivity(mPackageManager) == null) {
-            logWithStack("failed testIsEnabled: no settings activity");
-            mStatus[i] = FAIL;
-        } else {
-            // TODO: find out why Secure.ENABLED_NOTIFICATION_LISTENERS is hidden
-            String listeners = Secure.getString(getContentResolver(),
-                    "enabled_notification_listeners");
-            if (listeners != null && listeners.contains(LISTENER_PATH)) {
-                mStatus[i] = PASS;
-            } else {
-                mStatus[i] = WAIT_FOR_USER;
-            }
-        }
-        next();
-    }
-
-    private void testIsStarted(final int i) {
-        if (mStatus[i] == SETUP) {
-            mStatus[i] = READY;
-            // wait for the service to start
-            delay();
-        } else {
-            MockListener.probeListenerStatus(mContext,
-                    new MockListener.IntegerResultCatcher() {
-                @Override
-                public void accept(int result) {
-                    if (result == Activity.RESULT_OK) {
-                        mStatus[i] = PASS;
-                    } else {
-                        logWithStack("failed testIsStarted: " + result);
-                        mStatus[i] = FAIL;
-                    }
-                    next();
-                }
-            });
-        }
-    }
-
-    private void testNotificationRecieved(final int i) {
-        if (mStatus[i] == SETUP) {
-            MockListener.resetListenerData(this);
-            mStatus[i] = CLEARED;
-            // wait for intent to move through the system
-            delay();
-        } else if (mStatus[i] == CLEARED) {
-            sendNotificaitons();
-            mStatus[i] = READY;
-            // wait for notifications to move through the system
-            delay();
-        } else {
-            MockListener.probeListenerPosted(mContext,
-                    new MockListener.StringListResultCatcher() {
-                @Override
-                public void accept(List<String> result) {
-                    if (result.size() > 0 && result.contains(mTag1)) {
-                        mStatus[i] = PASS;
-                    } else {
-                        logWithStack("failed testNotificationRecieved");
-                        mStatus[i] = FAIL;
-                    }
-                    next();
-                }});
-        }
-    }
-
-    private void testDataIntact(final int i) {
-        // no setup required
-        MockListener.probeListenerPayloads(mContext,
-                new MockListener.StringListResultCatcher() {
-            @Override
-            public void accept(List<String> result) {
-                boolean pass = false;
-                Set<String> found = new HashSet<String>();
-                if (result.size() > 0) {
-                    pass = true;
-                    for(String payloadData : result) {
-                        try {
-                            JSONObject payload = new JSONObject(payloadData);
-                            pass &= checkEquals(mPackageString, payload.getString(JSON_PACKAGE),
-                                    "data integrity test fail: notificaiton package (%s, %s)");
-                            String tag = payload.getString(JSON_TAG);
-                            if (mTag1.equals(tag)) {
-                                found.add(mTag1);
-                                pass &= checkEquals(mIcon1, payload.getInt(JSON_ICON),
-                                        "data integrity test fail: notificaiton icon (%d, %d)");
-                                pass &= checkFlagSet(mFlag1, payload.getInt(JSON_FLAGS),
-                                        "data integrity test fail: notificaiton flags (%d, %d)");
-                                pass &= checkEquals(mId1, payload.getInt(JSON_ID),
-                                        "data integrity test fail: notificaiton ID (%d, %d)");
-                                pass &= checkEquals(mWhen1, payload.getLong(JSON_WHEN),
-                                        "data integrity test fail: notificaiton when (%d, %d)");
-                            } else if (mTag2.equals(tag)) {
-                                found.add(mTag2);
-                                pass &= checkEquals(mIcon2, payload.getInt(JSON_ICON),
-                                        "data integrity test fail: notificaiton icon (%d, %d)");
-                                pass &= checkFlagSet(mFlag2, payload.getInt(JSON_FLAGS),
-                                        "data integrity test fail: notificaiton flags (%d, %d)");
-                                pass &= checkEquals(mId2, payload.getInt(JSON_ID),
-                                        "data integrity test fail: notificaiton ID (%d, %d)");
-                                pass &= checkEquals(mWhen2, payload.getLong(JSON_WHEN),
-                                        "data integrity test fail: notificaiton when (%d, %d)");
-                            } else if (mTag3.equals(tag)) {
-                                found.add(mTag3);
-                                pass &= checkEquals(mIcon3, payload.getInt(JSON_ICON),
-                                        "data integrity test fail: notificaiton icon (%d, %d)");
-                                pass &= checkFlagSet(mFlag3, payload.getInt(JSON_FLAGS),
-                                        "data integrity test fail: notificaiton flags (%d, %d)");
-                                pass &= checkEquals(mId3, payload.getInt(JSON_ID),
-                                        "data integrity test fail: notificaiton ID (%d, %d)");
-                                pass &= checkEquals(mWhen3, payload.getLong(JSON_WHEN),
-                                        "data integrity test fail: notificaiton when (%d, %d)");
-                            } else {
-                                pass = false;
-                                logWithStack("failed on unexpected notification tag: " + tag);
-                            }
-                        } catch (JSONException e) {
-                            pass = false;
-                            Log.e(TAG, "failed to unpack data from mocklistener", e);
-                        }
-                    }
-                }
-                pass &= found.size() == 3;
-                mStatus[i] = pass ? PASS : FAIL;
-                next();
-            }});
-    }
-
-    private void testDismissOne(final int i) {
-        if (mStatus[i] == SETUP) {
-            MockListener.resetListenerData(this);
-            mStatus[i] = CLEARED;
-            // wait for intent to move through the system
-            delay();
-        } else if (mStatus[i] == CLEARED) {
-            MockListener.clearOne(mContext, mTag1, NOTIFICATION_ID + 1);
-            mStatus[i] = READY;
-            delay();
-        } else {
-            MockListener.probeListenerRemoved(mContext,
-                    new MockListener.StringListResultCatcher() {
-                @Override
-                public void accept(List<String> result) {
-                    if (result.size() > 0 && result.contains(mTag1)) {
-                        mStatus[i] = PASS;
-                        next();
-                    } else {
-                        if (mStatus[i] == RETRY) {
-                            logWithStack("failed testDismissOne");
-                            mStatus[i] = FAIL;
-                            next();
-                        } else {
-                            logWithStack("failed testDismissOne, once: retrying");
-                            mStatus[i] = RETRY;
-                            delay();
-                        }
-                    }
-                }});
-        }
-    }
-
-    private void testDismissAll(final int i) {
-        if (mStatus[i] == SETUP) {
-            MockListener.resetListenerData(this);
-            mStatus[i] = CLEARED;
-            // wait for intent to move through the system
-            delay();
-        } else if (mStatus[i] == CLEARED) {
-            MockListener.clearAll(mContext);
-            mStatus[i] = READY;
-            delay();
-        } else {
-            MockListener.probeListenerRemoved(mContext,
-                    new MockListener.StringListResultCatcher() {
-                @Override
-                public void accept(List<String> result) {
-                    if (result.size() == 2 && result.contains(mTag2) && result.contains(mTag3)) {
-                        mStatus[i] = PASS;
-                        next();
-                    } else {
-                        if (mStatus[i] == RETRY) {
-                            logWithStack("failed testDismissAll");
-                            mStatus[i] = FAIL;
-                            next();
-                        } else {
-                            logWithStack("failed testDismissAll, once: retrying");
-                            mStatus[i] = RETRY;
-                            delay();
-                        }
-                    }
-                }
-            });
-        }
-    }
-
-    private void testIsDisabled(int i) {
-        // no setup required
-        // TODO: find out why Secure.ENABLED_NOTIFICATION_LISTENERS is hidden
-        String listeners = Secure.getString(getContentResolver(),
-                "enabled_notification_listeners");
-        if (listeners == null || !listeners.contains(LISTENER_PATH)) {
-            mStatus[i] = PASS;
-            next();
-        } else {
-            mStatus[i] = WAIT_FOR_USER;
-            delay();
-        }
-    }
-
-    private void testIsStopped(final int i) {
-        if (mStatus[i] == SETUP) {
-            mStatus[i] = READY;
-            // wait for the service to start
-            delay();
-        } else {
-            MockListener.probeListenerStatus(mContext,
-                    new MockListener.IntegerResultCatcher() {
-                @Override
-                public void accept(int result) {
-                    if (result == Activity.RESULT_OK) {
-                        logWithStack("failed testIsStopped");
-                        mStatus[i] = FAIL;
-                    } else {
-                        mStatus[i] = PASS;
-                    }
-                    next();
-                }
-            });
-        }
-    }
-
-    private void testNotificationNotRecieved(final int i) {
-        if (mStatus[i] == SETUP) {
-            MockListener.resetListenerData(this);
-            mStatus[i] = CLEARED;
-            // wait for intent to move through the system
-            delay();
-        } else if (mStatus[i] == CLEARED) {
-            // setup for testNotificationRecieved
-            sendNotificaitons();
-            mStatus[i] = READY;
-            delay();
-        } else {
-            MockListener.probeListenerPosted(mContext,
-                    new MockListener.StringListResultCatcher() {
-                @Override
-                public void accept(List<String> result) {
-                    if (result == null || result.size() == 0) {
-                        mStatus[i] = PASS;
-                    } else {
-                        logWithStack("failed testNotificationNotRecieved");
-                        mStatus[i] = FAIL;
-                    }
-                    next();
-                }});
-        }
-    }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/MockListener.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/MockListener.java
new file mode 100644
index 0000000..b4863fa
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/MockListener.java
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.verifier.notifications;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.StatusBarNotification;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class MockListener extends NotificationListenerService {
+    static final String TAG = "MockListener";
+
+    static final String SERVICE_BASE = "android.service.notification.cts.";
+    static final String SERVICE_CHECK = SERVICE_BASE + "SERVICE_CHECK";
+    static final String SERVICE_POSTED = SERVICE_BASE + "SERVICE_POSTED";
+    static final String SERVICE_PAYLOADS = SERVICE_BASE + "SERVICE_PAYLOADS";
+    static final String SERVICE_REMOVED = SERVICE_BASE + "SERVICE_REMOVED";
+    static final String SERVICE_RESET = SERVICE_BASE + "SERVICE_RESET";
+    static final String SERVICE_CLEAR_ONE = SERVICE_BASE + "SERVICE_CLEAR_ONE";
+    static final String SERVICE_CLEAR_ALL = SERVICE_BASE + "SERVICE_CLEAR_ALL";
+    public static final String SERVICE_ORDER = SERVICE_BASE + "SERVICE_ORDER";
+    public static final String SERVICE_DND = SERVICE_BASE + "SERVICE_DND";
+
+    static final String EXTRA_PAYLOAD = "PAYLOAD";
+    static final String EXTRA_INT = "INT";
+    static final String EXTRA_TAG = "TAG";
+    static final String EXTRA_CODE = "CODE";
+
+    static final int RESULT_TIMEOUT = Activity.RESULT_FIRST_USER;
+    static final int RESULT_NO_SERVER = Activity.RESULT_FIRST_USER + 1;
+
+    public static final String JSON_FLAGS = "flag";
+    public static final String JSON_ICON = "icon";
+    public static final String JSON_ID = "id";
+    public static final String JSON_PACKAGE = "pkg";
+    public static final String JSON_WHEN = "when";
+    public static final String JSON_TAG = "tag";
+    public static final String JSON_RANK = "rank";
+    public static final String JSON_AMBIENT = "ambient";
+    public static final String JSON_MATCHES_ZEN_FILTER = "matches_zen_filter";
+
+    private ArrayList<String> mPosted = new ArrayList<String>();
+    private ArrayMap<String, JSONObject> mNotifications = new ArrayMap<>();
+    private ArrayMap<String, String> mNotificationKeys = new ArrayMap<>();
+    private ArrayList<String> mRemoved = new ArrayList<String>();
+    private ArrayList<String> mOrder = new ArrayList<>();
+    private Set<String> mTestPackages = new HashSet<>();
+    private BroadcastReceiver mReceiver;
+    private int mDND = -1;
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        Log.d(TAG, "created");
+
+        mTestPackages.add("com.android.cts.verifier");
+
+        mPosted = new ArrayList<String>();
+        mRemoved = new ArrayList<String>();
+
+        mReceiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                String action = intent.getAction();
+                if (SERVICE_CHECK.equals(action)) {
+                    Log.d(TAG, "SERVICE_CHECK");
+                    setResultCode(Activity.RESULT_OK);
+                } else if (SERVICE_POSTED.equals(action)) {
+                    Log.d(TAG, "SERVICE_POSTED");
+                    Bundle bundle = new Bundle();
+                    bundle.putStringArrayList(EXTRA_PAYLOAD, mPosted);
+                    setResultExtras(bundle);
+                    setResultCode(Activity.RESULT_OK);
+                } else if (SERVICE_DND.equals(action)) {
+                    Log.d(TAG, "SERVICE_DND");
+                    Bundle bundle = new Bundle();
+                    bundle.putInt(EXTRA_INT, mDND);
+                    setResultExtras(bundle);
+                    setResultCode(Activity.RESULT_OK);
+                } else if (SERVICE_ORDER.equals(action)) {
+                    Log.d(TAG, "SERVICE_ORDER");
+                    Bundle bundle = new Bundle();
+                    bundle.putStringArrayList(EXTRA_PAYLOAD, mOrder);
+                    setResultExtras(bundle);
+                    setResultCode(Activity.RESULT_OK);
+                } else if (SERVICE_PAYLOADS.equals(action)) {
+                    Log.d(TAG, "SERVICE_PAYLOADS");
+                    Bundle bundle = new Bundle();
+                    ArrayList<String> payloadData = new ArrayList<>(mNotifications.size());
+                    for (JSONObject payload: mNotifications.values()) {
+                        payloadData.add(payload.toString());
+                    }
+                    bundle.putStringArrayList(EXTRA_PAYLOAD, payloadData);
+                    setResultExtras(bundle);
+                    setResultCode(Activity.RESULT_OK);
+                } else if (SERVICE_REMOVED.equals(action)) {
+                    Log.d(TAG, "SERVICE_REMOVED");
+                    Bundle bundle = new Bundle();
+                    bundle.putStringArrayList(EXTRA_PAYLOAD, mRemoved);
+                    setResultExtras(bundle);
+                    setResultCode(Activity.RESULT_OK);
+                } else if (SERVICE_CLEAR_ONE.equals(action)) {
+                    Log.d(TAG, "SERVICE_CLEAR_ONE");
+                    String tag = intent.getStringExtra(EXTRA_TAG);
+                    String key = mNotificationKeys.get(tag);
+                    if (key != null) {
+                        MockListener.this.cancelNotification(key);
+                    } else {
+                        Log.w(TAG, "Notification does not exist: " + tag);
+                    }
+                } else if (SERVICE_CLEAR_ALL.equals(action)) {
+                    Log.d(TAG, "SERVICE_CLEAR_ALL");
+                    MockListener.this.cancelAllNotifications();
+                } else if (SERVICE_RESET.equals(action)) {
+                    Log.d(TAG, "SERVICE_RESET");
+                    resetData();
+                } else {
+                    Log.w(TAG, "unknown action");
+                    setResultCode(Activity.RESULT_CANCELED);
+                }
+            }
+        };
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(SERVICE_CHECK);
+        filter.addAction(SERVICE_DND);
+        filter.addAction(SERVICE_POSTED);
+        filter.addAction(SERVICE_ORDER);
+        filter.addAction(SERVICE_PAYLOADS);
+        filter.addAction(SERVICE_REMOVED);
+        filter.addAction(SERVICE_CLEAR_ONE);
+        filter.addAction(SERVICE_CLEAR_ALL);
+        filter.addAction(SERVICE_RESET);
+        registerReceiver(mReceiver, filter);
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        unregisterReceiver(mReceiver);
+        mReceiver = null;
+        Log.d(TAG, "destroyed");
+    }
+
+    @Override
+    public void onListenerConnected() {
+        super.onListenerConnected();
+        mDND = getCurrentInterruptionFilter();
+        Log.d(TAG, "initial value of CurrentInterruptionFilter is " + mDND);
+    }
+
+    @Override
+    public void onInterruptionFilterChanged(int interruptionFilter) {
+        super.onInterruptionFilterChanged(interruptionFilter);
+        mDND = interruptionFilter;
+        Log.d(TAG, "value of CurrentInterruptionFilter changed to " + mDND);
+    }
+
+    public void resetData() {
+        mPosted.clear();
+        mNotifications.clear();
+        mRemoved.clear();
+        mOrder.clear();
+    }
+
+    @Override
+    public void onNotificationRankingUpdate(RankingMap rankingMap) {
+        String[] orderedKeys = rankingMap.getOrderedKeys();
+        mOrder.clear();
+        Ranking rank = new Ranking();
+        for( int i = 0; i < orderedKeys.length; i++) {
+            String key = orderedKeys[i];
+            mOrder.add(key);
+            rankingMap.getRanking(key, rank);
+            JSONObject note = mNotifications.get(key);
+            if (note != null) {
+                try {
+                    note.put(JSON_RANK, rank.getRank());
+                    note.put(JSON_AMBIENT, rank.isAmbient());
+                    note.put(JSON_MATCHES_ZEN_FILTER, rank.matchesInterruptionFilter());
+                } catch (JSONException e) {
+                    Log.e(TAG, "failed to pack up notification payload", e);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
+        if (!mTestPackages.contains(sbn.getPackageName())) { return; }
+        Log.d(TAG, "posted: " + sbn.getTag());
+        mPosted.add(sbn.getTag());
+        JSONObject notification = new JSONObject();
+        try {
+            notification.put(JSON_TAG, sbn.getTag());
+            notification.put(JSON_ID, sbn.getId());
+            notification.put(JSON_PACKAGE, sbn.getPackageName());
+            notification.put(JSON_WHEN, sbn.getNotification().when);
+            notification.put(JSON_ICON, sbn.getNotification().icon);
+            notification.put(JSON_FLAGS, sbn.getNotification().flags);
+            mNotifications.put(sbn.getKey(), notification);
+            mNotificationKeys.put(sbn.getTag(), sbn.getKey());
+        } catch (JSONException e) {
+            Log.e(TAG, "failed to pack up notification payload", e);
+        }
+        onNotificationRankingUpdate(rankingMap);
+    }
+
+    @Override
+    public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap) {
+        Log.d(TAG, "removed: " + sbn.getTag());
+        mRemoved.add(sbn.getTag());
+        mNotifications.remove(sbn.getKey());
+        onNotificationRankingUpdate(rankingMap);
+        mNotificationKeys.remove(sbn.getTag());
+    }
+
+    public static void resetListenerData(Context context) {
+        sendCommand(context, SERVICE_RESET, null, 0);
+    }
+
+    public static void probeListenerStatus(Context context, StatusCatcher catcher) {
+        requestStatus(context, SERVICE_CHECK, catcher);
+    }
+
+    public static void probeFilter(Context context, IntegerResultCatcher catcher) {
+        requestIntegerResult(context, SERVICE_DND, catcher);
+    }
+
+    public static void probeListenerPosted(Context context, StringListResultCatcher catcher) {
+        requestStringListResult(context, SERVICE_POSTED, catcher);
+    }
+
+    public static void probeListenerOrder(Context context, StringListResultCatcher catcher) {
+        requestStringListResult(context, SERVICE_ORDER, catcher);
+    }
+
+    public static void probeListenerPayloads(Context context, StringListResultCatcher catcher) {
+        requestStringListResult(context, SERVICE_PAYLOADS, catcher);
+    }
+
+    public static void probeListenerRemoved(Context context, StringListResultCatcher catcher) {
+        requestStringListResult(context, SERVICE_REMOVED, catcher);
+    }
+
+    public static void clearOne(Context context, String tag, int code) {
+        sendCommand(context, SERVICE_CLEAR_ONE, tag, code);
+    }
+
+    public static void clearAll(Context context) {
+        sendCommand(context, SERVICE_CLEAR_ALL, null, 0);
+    }
+
+    private static void sendCommand(Context context, String action, String tag, int code) {
+        Intent broadcast = new Intent(action);
+        if (tag != null) {
+            broadcast.putExtra(EXTRA_TAG, tag);
+            broadcast.putExtra(EXTRA_CODE, code);
+        }
+        context.sendBroadcast(broadcast);
+    }
+
+    public abstract static class StatusCatcher extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            accept(Integer.valueOf(getResultCode()));
+        }
+
+        abstract public void accept(int result);
+    }
+
+    private static void requestStatus(Context context, String action,
+            StatusCatcher catcher) {
+        Intent broadcast = new Intent(action);
+        context.sendOrderedBroadcast(broadcast, null, catcher, null, RESULT_NO_SERVER, null, null);
+    }
+
+    public abstract static class IntegerResultCatcher extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            accept(getResultExtras(true).getInt(EXTRA_INT, -1));
+        }
+
+        abstract public void accept(int result);
+    }
+
+    private static void requestIntegerResult(Context context, String action,
+            IntegerResultCatcher catcher) {
+        Intent broadcast = new Intent(action);
+        context.sendOrderedBroadcast(broadcast, null, catcher, null, RESULT_NO_SERVER, null, null);
+    }
+
+    public abstract static class StringListResultCatcher extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            accept(getResultExtras(true).getStringArrayList(EXTRA_PAYLOAD));
+        }
+
+        abstract public void accept(List<String> result);
+    }
+
+    private static void requestStringListResult(Context context, String action,
+            StringListResultCatcher catcher) {
+        Intent broadcast = new Intent(action);
+        context.sendOrderedBroadcast(broadcast, null, catcher, null, RESULT_NO_SERVER, null, null);
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationAttentionManagementVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationAttentionManagementVerifierActivity.java
new file mode 100644
index 0000000..b4e348f
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationAttentionManagementVerifierActivity.java
@@ -0,0 +1,883 @@
+/*
+ * 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 com.android.cts.verifier.notifications;
+
+import static com.android.cts.verifier.notifications.MockListener.JSON_AMBIENT;
+import static com.android.cts.verifier.notifications.MockListener.JSON_MATCHES_ZEN_FILTER;
+import static com.android.cts.verifier.notifications.MockListener.JSON_TAG;
+
+import android.app.Activity;
+import android.app.Notification;
+import android.content.ContentProviderOperation;
+import android.content.Intent;
+import android.content.OperationApplicationException;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
+import android.provider.Settings.Secure;
+import android.service.notification.NotificationListenerService;
+import android.util.Log;
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.nfc.TagVerifierActivity;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class NotificationAttentionManagementVerifierActivity
+        extends NotificationListenerVerifierActivity {
+    private static final String TAG = TagVerifierActivity.class.getSimpleName();
+    private static final String ALICE = "Alice";
+    private static final String ALICE_PHONE = "+16175551212";
+    private static final String ALICE_EMAIL = "alice@_foo._bar";
+    private static final String BOB = "Bob";
+    private static final String BOB_PHONE = "+16505551212";;
+    private static final String BOB_EMAIL = "bob@_foo._bar";
+    private static final String CHARLIE = "Charlie";
+    private static final String CHARLIE_PHONE = "+13305551212";
+    private static final String CHARLIE_EMAIL = "charlie@_foo._bar";
+    private static final int MODE_NONE = 0;
+    private static final int MODE_URI = 1;
+    private static final int MODE_PHONE = 2;
+    private static final int MODE_EMAIL = 3;
+    private static final int DELAYED_SETUP = CLEARED;
+
+    private Uri mAliceUri;
+    private Uri mBobUri;
+    private Uri mCharlieUri;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState, R.layout.nls_main);
+        setInfoResources(R.string.attention_test, R.string.attention_info, -1);
+    }
+
+    // Test Setup
+
+    @Override
+    protected void createTestItems() {
+        createNlsSettingsItem(R.string.nls_enable_service);
+        createAutoItem(R.string.nls_service_started);
+        createAutoItem(R.string.attention_create_contacts);
+        createRetryItem(R.string.attention_filter_none);
+        createAutoItem(R.string.attention_all_are_filtered);
+        createRetryItem(R.string.attention_filter_all);
+        createAutoItem(R.string.attention_none_are_filtered);
+        createAutoItem(R.string.attention_default_order);
+        createAutoItem(R.string.attention_interruption_order);
+        createAutoItem(R.string.attention_priority_order);
+        createAutoItem(R.string.attention_ambient_bit);
+        createAutoItem(R.string.attention_lookup_order);
+        createAutoItem(R.string.attention_email_order);
+        createAutoItem(R.string.attention_phone_order);
+        createRetryItem(R.string.attention_filter_priority);
+        createAutoItem(R.string.attention_some_are_filtered);
+        createAutoItem(R.string.attention_delete_contacts);
+    }
+
+    // Test management
+
+    @Override
+    protected void updateStateMachine() {
+        switch (mState) {
+            case 0:
+                testIsEnabled(mState);
+                break;
+            case 1:
+                testIsStarted(mState);
+                break;
+            case 2:
+                testInsertContacts(mState);
+                break;
+            case 3:
+                testModeNone(mState);
+                break;
+            case 4:
+                testNoneInterceptsAll(mState);
+                break;
+            case 5:
+                testModeAll(mState);
+                break;
+            case 6:
+                testAllInterceptsNothing(mState);
+                break;
+            case 7:
+                testDefaultOrder(mState);
+                break;
+            case 8:
+                testInterruptionOrder(mState);
+                break;
+            case 9:
+                testPrioritytOrder(mState);
+                break;
+            case 10:
+                testAmbientBits(mState);
+                break;
+            case 11:
+                testLookupUriOrder(mState);
+                break;
+            case 12:
+                testEmailOrder(mState);
+                break;
+            case 13:
+                testPhoneOrder(mState);
+                break;
+            case 14:
+                testModePriority(mState);
+                break;
+            case 15:
+                testPriorityInterceptsSome(mState);
+                break;
+            case 16:
+                testDeleteContacts(mState);
+                break;
+            case 17:
+                getPassButton().setEnabled(true);
+                mNm.cancelAll();
+                break;
+        }
+    }
+
+    // usePriorities true: B, C, A
+    // usePriorities false:
+    //   MODE_NONE: C, B, A
+    //   otherwise: A, B ,C
+    private void sendNotifications(int annotationMode, boolean usePriorities, boolean noisy) {
+        // TODO(cwren) Fixes flakey tests due to bug 17644321. Remove this line when it is fixed.
+        int baseId = NOTIFICATION_ID + (noisy ? 3 : 0);
+
+        // C, B, A when sorted by time.  Times must be in the past.
+        long whenA = System.currentTimeMillis() - 4000000L;
+        long whenB = System.currentTimeMillis() - 2000000L;
+        long whenC = System.currentTimeMillis() - 1000000L;
+
+        // B, C, A when sorted by priorities
+        int priorityA = usePriorities ? Notification.PRIORITY_MIN : Notification.PRIORITY_DEFAULT;
+        int priorityB = usePriorities ? Notification.PRIORITY_MAX : Notification.PRIORITY_DEFAULT;
+        int priorityC = usePriorities ? Notification.PRIORITY_LOW : Notification.PRIORITY_DEFAULT;
+
+        Notification.Builder alice = new Notification.Builder(mContext)
+                .setContentTitle(ALICE)
+                .setContentText(ALICE)
+                .setSmallIcon(R.drawable.fs_good)
+                .setPriority(priorityA)
+                .setCategory(Notification.CATEGORY_MESSAGE)
+                .setWhen(whenA);
+        alice.setDefaults(noisy ? Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE : 0);
+        addPerson(annotationMode, alice, mAliceUri, ALICE_PHONE, ALICE_EMAIL);
+        mNm.notify(ALICE, baseId + 1, alice.build());
+
+        Notification.Builder bob = new Notification.Builder(mContext)
+                .setContentTitle(BOB)
+                .setContentText(BOB)
+                .setSmallIcon(R.drawable.fs_warning)
+                .setPriority(priorityB)
+                .setCategory(Notification.CATEGORY_MESSAGE)
+                .setWhen(whenB);
+        addPerson(annotationMode, bob, mBobUri, BOB_PHONE, BOB_EMAIL);
+        mNm.notify(BOB, baseId + 2, bob.build());
+
+        Notification.Builder charlie = new Notification.Builder(mContext)
+                .setContentTitle(CHARLIE)
+                .setContentText(CHARLIE)
+                .setSmallIcon(R.drawable.fs_error)
+                .setPriority(priorityC)
+                .setCategory(Notification.CATEGORY_MESSAGE)
+                .setWhen(whenC);
+        addPerson(annotationMode, charlie, mCharlieUri, CHARLIE_PHONE, CHARLIE_EMAIL);
+        mNm.notify(CHARLIE, baseId + 3, charlie.build());
+    }
+
+    private void addPerson(int mode, Notification.Builder note,
+            Uri uri, String phone, String email) {
+        if (mode == MODE_URI && uri != null) {
+            note.addPerson(uri.toString());
+        } else if (mode == MODE_PHONE) {
+            note.addPerson(Uri.fromParts("tel", phone, null).toString());
+        } else if (mode == MODE_EMAIL) {
+            note.addPerson(Uri.fromParts("mailto", email, null).toString());
+        }
+    }
+
+    // Tests
+
+    private void testIsEnabled(int i) {
+        // no setup required
+        Intent settings = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
+        if (settings.resolveActivity(mPackageManager) == null) {
+            logWithStack("failed testIsEnabled: no settings activity");
+            mStatus[i] = FAIL;
+        } else {
+            // TODO: find out why Secure.ENABLED_NOTIFICATION_LISTENERS is hidden
+            String listeners = Secure.getString(getContentResolver(),
+                    "enabled_notification_listeners");
+            if (listeners != null && listeners.contains(LISTENER_PATH)) {
+                mStatus[i] = PASS;
+            } else {
+                mStatus[i] = WAIT_FOR_USER;
+            }
+        }
+        next();
+    }
+
+    private void testIsStarted(final int i) {
+        if (mStatus[i] == SETUP) {
+            mStatus[i] = READY;
+            // wait for the service to start
+            delay();
+        } else {
+            MockListener.probeListenerStatus(mContext,
+                    new MockListener.StatusCatcher() {
+                        @Override
+                        public void accept(int result) {
+                            if (result == Activity.RESULT_OK) {
+                                mStatus[i] = PASS;
+                            } else {
+                                logWithStack("failed testIsStarted: " + result);
+                                mStatus[i] = FAIL;
+                            }
+                            next();
+                        }
+                    });
+        }
+    }
+
+    private void testModeAll(final int i) {
+        if (mStatus[i] == READY || mStatus[i] == SETUP) {
+            MockListener.probeFilter(mContext,
+                    new MockListener.IntegerResultCatcher() {
+                        @Override
+                        public void accept(int mode) {
+                            if (mode == NotificationListenerService.INTERRUPTION_FILTER_ALL) {
+                                mStatus[i] = PASS;
+                            } else {
+                                logWithStack("waiting testModeAll: " + mode);
+                                mStatus[i] = WAIT_FOR_USER;
+                            }
+                            next();
+                        }
+                    });
+        }
+    }
+
+    private void testModePriority(final int i) {
+        if (mStatus[i] == READY || mStatus[i] == SETUP) {
+            MockListener.probeFilter(mContext,
+                    new MockListener.IntegerResultCatcher() {
+                        @Override
+                        public void accept(int mode) {
+                            if (mode == NotificationListenerService.INTERRUPTION_FILTER_PRIORITY) {
+                                mStatus[i] = PASS;
+                            } else {
+                                logWithStack("waiting testModePriority: " + mode);
+                                mStatus[i] = WAIT_FOR_USER;
+                            }
+                            next();
+                        }
+                    });
+        }
+    }
+
+    private void testModeNone(final int i) {
+        if (mStatus[i] == READY || mStatus[i] == SETUP) {
+            MockListener.probeFilter(mContext,
+                    new MockListener.IntegerResultCatcher() {
+                        @Override
+                        public void accept(int mode) {
+                            if (mode == NotificationListenerService.INTERRUPTION_FILTER_NONE) {
+                                mStatus[i] = PASS;
+                            } else {
+                                logWithStack("waiting testModeNone: " + mode);
+                                mStatus[i] = WAIT_FOR_USER;
+                            }
+                            next();
+                        }
+                    });
+        }
+    }
+
+
+    private void insertSingleContact(String name, String phone, String email, boolean starred) {
+        final ArrayList<ContentProviderOperation> operationList =
+                new ArrayList<ContentProviderOperation>();
+        ContentProviderOperation.Builder builder =
+                ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI);
+        builder.withValue(ContactsContract.RawContacts.STARRED, starred ? 1 : 0);
+        operationList.add(builder.build());
+
+        builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
+        builder.withValueBackReference(StructuredName.RAW_CONTACT_ID, 0);
+        builder.withValue(ContactsContract.Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
+        builder.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name);
+        operationList.add(builder.build());
+
+        if (phone != null) {
+            builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
+            builder.withValueBackReference(Phone.RAW_CONTACT_ID, 0);
+            builder.withValue(ContactsContract.Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
+            builder.withValue(Phone.TYPE, Phone.TYPE_MOBILE);
+            builder.withValue(Phone.NUMBER, phone);
+            builder.withValue(ContactsContract.Data.IS_PRIMARY, 1);
+            operationList.add(builder.build());
+        }
+        if (email != null) {
+            builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
+            builder.withValueBackReference(Email.RAW_CONTACT_ID, 0);
+            builder.withValue(ContactsContract.Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
+            builder.withValue(Email.TYPE, Email.TYPE_HOME);
+            builder.withValue(Email.DATA, email);
+            operationList.add(builder.build());
+        }
+
+        try {
+            mContext.getContentResolver().applyBatch(ContactsContract.AUTHORITY, operationList);
+        } catch (RemoteException e) {
+            Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
+        } catch (OperationApplicationException e) {
+            Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
+        }
+    }
+
+    private Uri lookupContact(String phone) {
+        Cursor c = null;
+        try {
+            Uri phoneUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
+                    Uri.encode(phone));
+            String[] projection = new String[] { ContactsContract.Contacts._ID,
+                    ContactsContract.Contacts.LOOKUP_KEY };
+            c = mContext.getContentResolver().query(phoneUri, projection, null, null, null);
+            if (c != null && c.getCount() > 0) {
+                c.moveToFirst();
+                int lookupIdx = c.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY);
+                int idIdx = c.getColumnIndex(ContactsContract.Contacts._ID);
+                String lookupKey = c.getString(lookupIdx);
+                long contactId = c.getLong(idIdx);
+                return ContactsContract.Contacts.getLookupUri(contactId, lookupKey);
+            }
+        } catch (Throwable t) {
+            Log.w(TAG, "Problem getting content resolver or performing contacts query.", t);
+        } finally {
+            if (c != null) {
+                c.close();
+            }
+        }
+        return null;
+    }
+
+    private void testInsertContacts(final int i) {
+        if (mStatus[i] == SETUP) {
+            insertSingleContact(ALICE, ALICE_PHONE, ALICE_EMAIL, true);
+            insertSingleContact(BOB, BOB_PHONE, BOB_EMAIL, false);
+            // charlie is not in contacts
+            mStatus[i] = READY;
+            // wait for insertions to move through the system
+            delay();
+        } else {
+            mAliceUri = lookupContact(ALICE_PHONE);
+            mBobUri = lookupContact(BOB_PHONE);
+            mCharlieUri = lookupContact(CHARLIE_PHONE);
+
+            mStatus[i] = PASS;
+            if (mAliceUri == null) { mStatus[i] = FAIL; }
+            if (mBobUri == null) { mStatus[i] = FAIL; }
+            if (mCharlieUri != null) { mStatus[i] = FAIL; }
+            next();
+        }
+    }
+
+    // ordered by time: C, B, A
+    private void testDefaultOrder(final int i) {
+        if (mStatus[i] == SETUP) {
+            mNm.cancelAll();
+            MockListener.resetListenerData(this);
+            mStatus[i] = CLEARED;
+            // wait for intent to move through the system
+            delay();
+        } else if (mStatus[i] == CLEARED) {
+            sendNotifications(MODE_NONE, false, false);
+            mStatus[i] = READY;
+            // wait for notifications to move through the system
+            delay();
+        } else {
+            MockListener.probeListenerOrder(mContext,
+                    new MockListener.StringListResultCatcher() {
+                        @Override
+                        public void accept(List<String> orderedKeys) {
+                            int rankA = findTagInKeys(ALICE, orderedKeys);
+                            int rankB = findTagInKeys(BOB, orderedKeys);
+                            int rankC = findTagInKeys(CHARLIE, orderedKeys);
+                            if (rankC < rankB && rankB < rankA) {
+                                mStatus[i] = PASS;
+                            } else {
+                                logWithStack("failed testDefaultOrder : "
+                                        + rankA + ", " + rankB + ", " + rankC);
+                                mStatus[i] = FAIL;
+                            }
+                            next();
+                        }
+                    });
+        }
+    }
+
+    // ordered by priority: B, C, A
+    private void testPrioritytOrder(final int i) {
+        if (mStatus[i] == SETUP) {
+            mNm.cancelAll();
+            MockListener.resetListenerData(this);
+            mStatus[i] = CLEARED;
+            // wait for intent to move through the system
+            delay();
+        } else if (mStatus[i] == CLEARED) {
+            sendNotifications(MODE_PHONE, true, false);
+            mStatus[i] = READY;
+            // wait for notifications to move through the system
+            delay();
+        } else {
+            MockListener.probeListenerOrder(mContext,
+                    new MockListener.StringListResultCatcher() {
+                        @Override
+                        public void accept(List<String> orderedKeys) {
+                            int rankA = findTagInKeys(ALICE, orderedKeys);
+                            int rankB = findTagInKeys(BOB, orderedKeys);
+                            int rankC = findTagInKeys(CHARLIE, orderedKeys);
+                            if (rankB < rankC && rankC < rankA) {
+                                mStatus[i] = PASS;
+                            } else {
+                                logWithStack("failed testPrioritytOrder : "
+                                        + rankA + ", " + rankB + ", " + rankC);
+                                mStatus[i] = FAIL;
+                            }
+                            next();
+                        }
+                    });
+        }
+    }
+
+    // B & C above the fold, A below
+    private void testAmbientBits(final int i) {
+        if (mStatus[i] == SETUP) {
+            mNm.cancelAll();
+            MockListener.resetListenerData(this);
+            mStatus[i] = CLEARED;
+            // wait for intent to move through the system
+            delay();
+        } else if (mStatus[i] == CLEARED) {
+            sendNotifications(MODE_PHONE, true, false);
+            mStatus[i] = READY;
+            // wait for notifications to move through the system
+            delay();
+        } else {
+            MockListener.probeListenerPayloads(mContext,
+                    new MockListener.StringListResultCatcher() {
+                        @Override
+                        public void accept(List<String> result) {
+                            boolean pass = false;
+                            Set<String> found = new HashSet<String>();
+                            if (result != null && result.size() > 0) {
+                                pass = true;
+                                for (String payloadData : result) {
+                                    try {
+                                        JSONObject payload = new JSONObject(payloadData);
+                                        String tag = payload.getString(JSON_TAG);
+                                        if (found.contains(tag)) {
+                                            // multiple entries for same notification!
+                                            pass = false;
+                                        } else if (ALICE.equals(tag)) {
+                                            found.add(ALICE);
+                                            pass &= payload.getBoolean(JSON_AMBIENT);
+                                        } else if (BOB.equals(tag)) {
+                                            found.add(BOB);
+                                            pass &= !payload.getBoolean(JSON_AMBIENT);
+                                        } else if (CHARLIE.equals(tag)) {
+                                            found.add(CHARLIE);
+                                            pass &= !payload.getBoolean(JSON_AMBIENT);
+                                        }
+                                    } catch (JSONException e) {
+                                        pass = false;
+                                        Log.e(TAG, "failed to unpack data from mocklistener", e);
+                                    }
+                                }
+                            }
+                            pass &= found.size() == 3;
+                            mStatus[i] = pass ? PASS : FAIL;
+                            next();
+                        }
+                    });
+        }
+    }
+
+    // ordered by contact affinity: A, B, C
+    private void testLookupUriOrder(final int i) {
+        if (mStatus[i] == SETUP) {
+            mNm.cancelAll();
+            MockListener.resetListenerData(this);
+            mStatus[i] = CLEARED;
+            // wait for intent to move through the system
+            delay();
+        } else if (mStatus[i] == CLEARED) {
+            sendNotifications(MODE_URI, false, false);
+            mStatus[i] = READY;
+            // wait for notifications to move through the system
+            delay();
+        } else {
+            MockListener.probeListenerOrder(mContext,
+                    new MockListener.StringListResultCatcher() {
+                        @Override
+                        public void accept(List<String> orderedKeys) {
+                            int rankA = findTagInKeys(ALICE, orderedKeys);
+                            int rankB = findTagInKeys(BOB, orderedKeys);
+                            int rankC = findTagInKeys(CHARLIE, orderedKeys);
+                            if (rankA < rankB && rankB < rankC) {
+                                mStatus[i] = PASS;
+                            } else {
+                                logWithStack("failed testLookupUriOrder : "
+                                        + rankA + ", " + rankB + ", " + rankC);
+                                mStatus[i] = FAIL;
+                            }
+                            next();
+                        }
+                    });
+        }
+    }
+
+    // ordered by contact affinity: A, B, C
+    private void testEmailOrder(final int i) {
+        if (mStatus[i] == SETUP) {
+            mNm.cancelAll();
+            MockListener.resetListenerData(this);
+            mStatus[i] = DELAYED_SETUP;
+            // wait for intent to move through the system
+            delay();
+        } else if (mStatus[i] == DELAYED_SETUP) {
+            sendNotifications(MODE_EMAIL, false, false);
+            mStatus[i] = READY;
+            // wait for notifications to move through the system
+            delay();
+        } else {
+            MockListener.probeListenerOrder(mContext,
+                    new MockListener.StringListResultCatcher() {
+                        @Override
+                        public void accept(List<String> orderedKeys) {
+                            int rankA = findTagInKeys(ALICE, orderedKeys);
+                            int rankB = findTagInKeys(BOB, orderedKeys);
+                            int rankC = findTagInKeys(CHARLIE, orderedKeys);
+                            if (rankA < rankB && rankB < rankC) {
+                                mStatus[i] = PASS;
+                            } else {
+                                logWithStack("failed testEmailOrder : "
+                                        + rankA + ", " + rankB + ", " + rankC);
+                                mStatus[i] = FAIL;
+                            }
+                            next();
+                        }
+                    });
+        }
+    }
+
+    // ordered by contact affinity: A, B, C
+    private void testPhoneOrder(final int i) {
+        if (mStatus[i] == SETUP) {
+            mNm.cancelAll();
+            MockListener.resetListenerData(this);
+            mStatus[i] = CLEARED;
+            // wait for intent to move through the system
+            delay();
+        } else if (mStatus[i] == CLEARED) {
+            sendNotifications(MODE_PHONE, false, false);
+            mStatus[i] = READY;
+            // wait for notifications to move through the system
+            delay();
+        } else {
+            MockListener.probeListenerOrder(mContext,
+                    new MockListener.StringListResultCatcher() {
+                        @Override
+                        public void accept(List<String> orderedKeys) {
+                            int rankA = findTagInKeys(ALICE, orderedKeys);
+                            int rankB = findTagInKeys(BOB, orderedKeys);
+                            int rankC = findTagInKeys(CHARLIE, orderedKeys);
+                            if (rankA < rankB && rankB < rankC) {
+                                mStatus[i] = PASS;
+                            } else {
+                                logWithStack("failed testPhoneOrder : "
+                                        + rankA + ", " + rankB + ", " + rankC);
+                                mStatus[i] = FAIL;
+                            }
+                            next();
+                        }
+                    });
+        }
+    }
+
+    // A starts at the top then falls to the bottom
+    private void testInterruptionOrder(final int i) {
+        if (mStatus[i] == SETUP) {
+            mNm.cancelAll();
+            MockListener.resetListenerData(this);
+            mStatus[i] = CLEARED;
+            // wait for intent to move through the system
+            delay();
+        } else if (mStatus[i] == CLEARED) {
+            sendNotifications(MODE_NONE, false, true);
+            mStatus[i] = READY;
+            // wait for notifications to move through the system
+            delay();
+        } else if (mStatus[i] == READY) {
+            MockListener.probeListenerOrder(mContext,
+                    new MockListener.StringListResultCatcher() {
+                        @Override
+                        public void accept(List<String> orderedKeys) {
+                            int rankA = findTagInKeys(ALICE, orderedKeys);
+                            int rankB = findTagInKeys(BOB, orderedKeys);
+                            int rankC = findTagInKeys(CHARLIE, orderedKeys);
+                            if (rankA < rankB && rankA < rankC) {
+                                mStatus[i] = RETRY;
+                                delay(12000);
+                            } else {
+                                logWithStack("noisy notification did not sort to top.");
+                                mStatus[i] = FAIL;
+                                next();
+                            }
+                        }
+                    });
+        } else if (mStatus[i] == RETRY) {
+            MockListener.probeListenerOrder(mContext,
+                    new MockListener.StringListResultCatcher() {
+                        @Override
+                        public void accept(List<String> orderedKeys) {
+                            int rankA = findTagInKeys(ALICE, orderedKeys);
+                            int rankB = findTagInKeys(BOB, orderedKeys);
+                            int rankC = findTagInKeys(CHARLIE, orderedKeys);
+                            if (rankA > rankB && rankA > rankC) {
+                                mStatus[i] = PASS;
+                            } else {
+                                logWithStack("noisy notification did not fade back into the list.");
+                                mStatus[i] = FAIL;
+                            }
+                            next();
+                        }
+                    });
+        }
+    }
+
+    // Nothing should be filtered when mode is ALL
+    private void testAllInterceptsNothing(final int i) {
+        if (mStatus[i] == SETUP) {
+            mNm.cancelAll();
+            MockListener.resetListenerData(this);
+            mStatus[i] = CLEARED;
+            // wait for intent to move through the system
+            delay();
+        } else if (mStatus[i] == CLEARED) {
+            sendNotifications(MODE_URI, false, false);
+            mStatus[i] = READY;
+            // wait for notifications to move through the system
+            delay();
+        } else {
+            MockListener.probeListenerPayloads(mContext,
+                    new MockListener.StringListResultCatcher() {
+                        @Override
+                        public void accept(List<String> result) {
+                            boolean pass = false;
+                            Set<String> found = new HashSet<String>();
+                            if (result != null && result.size() > 0) {
+                                pass = true;
+                                for (String payloadData : result) {
+                                    try {
+                                        JSONObject payload = new JSONObject(payloadData);
+                                        String tag = payload.getString(JSON_TAG);
+                                        if (found.contains(tag)) {
+                                            // multiple entries for same notification!
+                                            pass = false;
+                                        } else if (ALICE.equals(tag)) {
+                                            found.add(ALICE);
+                                            pass &= payload.getBoolean(JSON_MATCHES_ZEN_FILTER);
+                                        } else if (BOB.equals(tag)) {
+                                            found.add(BOB);
+                                            pass &= payload.getBoolean(JSON_MATCHES_ZEN_FILTER);
+                                        } else if (CHARLIE.equals(tag)) {
+                                            found.add(CHARLIE);
+                                            pass &= payload.getBoolean(JSON_MATCHES_ZEN_FILTER);
+                                        }
+                                    } catch (JSONException e) {
+                                        pass = false;
+                                        Log.e(TAG, "failed to unpack data from mocklistener", e);
+                                    }
+                                }
+                            }
+                            pass &= found.size() == 3;
+                            mStatus[i] = pass ? PASS : FAIL;
+                            next();
+                        }
+                    });
+        }
+    }
+
+    // A should be filtered when mode is Priority/Starred.
+    private void testPriorityInterceptsSome(final int i) {
+        if (mStatus[i] == SETUP) {
+            mNm.cancelAll();
+            MockListener.resetListenerData(this);
+            mStatus[i] = CLEARED;
+            // wait for intent to move through the system
+            delay();
+        } else if (mStatus[i] == CLEARED) {
+            sendNotifications(MODE_URI, false, false);
+            mStatus[i] = READY;
+            // wait for notifications to move through the system
+            delay();
+        } else {
+            MockListener.probeListenerPayloads(mContext,
+                    new MockListener.StringListResultCatcher() {
+                        @Override
+                        public void accept(List<String> result) {
+                            boolean pass = false;
+                            Set<String> found = new HashSet<String>();
+                            if (result != null && result.size() > 0) {
+                                pass = true;
+                                for (String payloadData : result) {
+                                    try {
+                                        JSONObject payload = new JSONObject(payloadData);
+                                        String tag = payload.getString(JSON_TAG);
+                                        if (found.contains(tag)) {
+                                            // multiple entries for same notification!
+                                            pass = false;
+                                        } else if (ALICE.equals(tag)) {
+                                            found.add(ALICE);
+                                            pass &= payload.getBoolean(JSON_MATCHES_ZEN_FILTER);
+                                        } else if (BOB.equals(tag)) {
+                                            found.add(BOB);
+                                            pass &= !payload.getBoolean(JSON_MATCHES_ZEN_FILTER);
+                                        } else if (CHARLIE.equals(tag)) {
+                                            found.add(CHARLIE);
+                                            pass &= !payload.getBoolean(JSON_MATCHES_ZEN_FILTER);
+                                        }
+                                    } catch (JSONException e) {
+                                        pass = false;
+                                        Log.e(TAG, "failed to unpack data from mocklistener", e);
+                                    }
+                                }
+                            }
+                            pass &= found.size() == 3;
+                            mStatus[i] = pass ? PASS : FAIL;
+                            next();
+                        }
+                    });
+        }
+    }
+
+    // Nothing should get through when mode is None.
+    private void testNoneInterceptsAll(final int i) {
+        if (mStatus[i] == SETUP) {
+            mNm.cancelAll();
+            MockListener.resetListenerData(this);
+            mStatus[i] = CLEARED;
+            // wait for intent to move through the system
+            delay();
+        } else if (mStatus[i] == CLEARED) {
+            sendNotifications(MODE_URI, false, false);
+            mStatus[i] = READY;
+            // wait for notifications to move through the system
+            delay();
+        } else {
+            MockListener.probeListenerPayloads(mContext,
+                    new MockListener.StringListResultCatcher() {
+                        @Override
+                        public void accept(List<String> result) {
+                            boolean pass = false;
+                            Set<String> found = new HashSet<String>();
+                            if (result != null && result.size() > 0) {
+                                pass = true;
+                                for (String payloadData : result) {
+                                    try {
+                                        JSONObject payload = new JSONObject(payloadData);
+                                        String tag = payload.getString(JSON_TAG);
+                                        if (found.contains(tag)) {
+                                            // multiple entries for same notification!
+                                            pass = false;
+                                        } else if (ALICE.equals(tag)) {
+                                            found.add(ALICE);
+                                            pass &= !payload.getBoolean(JSON_MATCHES_ZEN_FILTER);
+                                        } else if (BOB.equals(tag)) {
+                                            found.add(BOB);
+                                            pass &= !payload.getBoolean(JSON_MATCHES_ZEN_FILTER);
+                                        } else if (CHARLIE.equals(tag)) {
+                                            found.add(CHARLIE);
+                                            pass &= !payload.getBoolean(JSON_MATCHES_ZEN_FILTER);
+                                        }
+                                    } catch (JSONException e) {
+                                        pass = false;
+                                        Log.e(TAG, "failed to unpack data from mocklistener", e);
+                                    }
+                                }
+                            }
+                            pass &= found.size() == 3;
+                            mStatus[i] = pass ? PASS : FAIL;
+                            next();
+                        }
+                    });
+        }
+    }
+
+    /** Search a list of notification keys for a givcen tag. */
+    private int findTagInKeys(String tag, List<String> orderedKeys) {
+        for (int i = 0; i < orderedKeys.size(); i++) {
+            if (orderedKeys.get(i).contains(tag)) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    private void testDeleteContacts(final int i) {
+        if (mStatus[i] == SETUP) {
+            final ArrayList<ContentProviderOperation> operationList =
+                    new ArrayList<ContentProviderOperation>();
+            operationList.add(ContentProviderOperation.newDelete(mAliceUri).build());
+            operationList.add(ContentProviderOperation.newDelete(mBobUri).build());
+            try {
+                mContext.getContentResolver().applyBatch(ContactsContract.AUTHORITY, operationList);
+                mStatus[i] = READY;
+            } catch (RemoteException e) {
+                Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
+                mStatus[i] = FAIL;
+            } catch (OperationApplicationException e) {
+                Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
+                mStatus[i] = FAIL;
+            }
+            // wait for deletions to move through the system
+            delay(3000);
+        } else if (mStatus[i] == READY) {
+            mAliceUri = lookupContact(ALICE_PHONE);
+            mBobUri = lookupContact(BOB_PHONE);
+            mCharlieUri = lookupContact(CHARLIE_PHONE);
+
+            mStatus[i] = PASS;
+            if (mAliceUri != null) { mStatus[i] = FAIL; }
+            if (mBobUri != null) { mStatus[i] = FAIL; }
+            if (mCharlieUri != null) { mStatus[i] = FAIL; }
+            next();
+        }
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java
new file mode 100644
index 0000000..0ef595b
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationListenerVerifierActivity.java
@@ -0,0 +1,676 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.notifications;
+
+import static com.android.cts.verifier.notifications.MockListener.JSON_FLAGS;
+import static com.android.cts.verifier.notifications.MockListener.JSON_ICON;
+import static com.android.cts.verifier.notifications.MockListener.JSON_ID;
+import static com.android.cts.verifier.notifications.MockListener.JSON_PACKAGE;
+import static com.android.cts.verifier.notifications.MockListener.JSON_TAG;
+import static com.android.cts.verifier.notifications.MockListener.JSON_WHEN;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.provider.Settings.Secure;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.nfc.TagVerifierActivity;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.LinkedBlockingQueue;
+
+public class NotificationListenerVerifierActivity extends PassFailButtons.Activity
+implements Runnable {
+    private static final String TAG = TagVerifierActivity.class.getSimpleName();
+    private static final String STATE = "state";
+    private static LinkedBlockingQueue<String> sDeletedQueue = new LinkedBlockingQueue<String>();
+
+    protected static final String LISTENER_PATH = "com.android.cts.verifier/" +
+            "com.android.cts.verifier.notifications.MockListener";
+    protected static final int SETUP = 0;
+    protected static final int PASS = 1;
+    protected static final int FAIL = 2;
+    protected static final int WAIT_FOR_USER = 3;
+    protected static final int CLEARED = 4;
+    protected static final int READY = 5;
+    protected static final int RETRY = 6;
+
+    protected static final int NOTIFICATION_ID = 1001;
+
+    protected int mState;
+    protected int[] mStatus;
+    protected PackageManager mPackageManager;
+    protected NotificationManager mNm;
+    protected Context mContext;
+    protected Runnable mRunner;
+    protected View mHandler;
+    protected String mPackageString;
+
+    private LayoutInflater mInflater;
+    private ViewGroup mItemList;
+
+    private String mTag1;
+    private String mTag2;
+    private String mTag3;
+    private int mIcon1;
+    private int mIcon2;
+    private int mIcon3;
+    private int mId1;
+    private int mId2;
+    private int mId3;
+    private long mWhen1;
+    private long mWhen2;
+    private long mWhen3;
+    private int mFlag1;
+    private int mFlag2;
+    private int mFlag3;
+
+    public static class DismissService extends Service {
+        @Override
+        public IBinder onBind(Intent intent) {
+            return null;
+        }
+
+        @Override
+        public void onStart(Intent intent, int startId) {
+            sDeletedQueue.offer(intent.getAction());
+        }
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        onCreate(savedInstanceState, R.layout.nls_main);
+        setInfoResources(R.string.nls_test, R.string.nls_info, -1);
+    }
+
+    protected void onCreate(Bundle savedInstanceState, int layoutId) {
+        super.onCreate(savedInstanceState);
+
+        if (savedInstanceState != null) {
+            mState = savedInstanceState.getInt(STATE, 0);
+        }
+        mContext = this;
+        mRunner = this;
+        mNm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
+        mPackageManager = getPackageManager();
+        mInflater = getLayoutInflater();
+        View view = mInflater.inflate(layoutId, null);
+        mItemList = (ViewGroup) view.findViewById(R.id.nls_test_items);
+        mHandler = mItemList;
+        createTestItems();
+        mStatus = new int[mItemList.getChildCount()];
+        setContentView(view);
+
+        setPassFailButtonClickListeners();
+        getPassButton().setEnabled(false);
+    }
+
+    @Override
+    protected void onSaveInstanceState (Bundle outState) {
+        outState.putInt(STATE, mState);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        next();
+    }
+
+    // Interface Utilities
+
+    protected void createTestItems() {
+        createNlsSettingsItem(R.string.nls_enable_service);
+        createAutoItem(R.string.nls_service_started);
+        createAutoItem(R.string.nls_note_received);
+        createAutoItem(R.string.nls_payload_intact);
+        createAutoItem(R.string.nls_clear_one);
+        createAutoItem(R.string.nls_clear_all);
+        createNlsSettingsItem(R.string.nls_disable_service);
+        createAutoItem(R.string.nls_service_stopped);
+        createAutoItem(R.string.nls_note_missed);
+    }
+
+    protected void setItemState(int index, boolean passed) {
+        ViewGroup item = (ViewGroup) mItemList.getChildAt(index);
+        ImageView status = (ImageView) item.findViewById(R.id.nls_status);
+        status.setImageResource(passed ? R.drawable.fs_good : R.drawable.fs_error);
+        View button = item.findViewById(R.id.nls_action_button);
+        button.setClickable(false);
+        button.setEnabled(false);
+        status.invalidate();
+    }
+
+    protected void markItemWaiting(int index) {
+        ViewGroup item = (ViewGroup) mItemList.getChildAt(index);
+        ImageView status = (ImageView) item.findViewById(R.id.nls_status);
+        status.setImageResource(R.drawable.fs_warning);
+        status.invalidate();
+    }
+
+    protected View createNlsSettingsItem(int messageId) {
+        return createUserItem(messageId, R.string.nls_start_settings);
+    }
+
+    protected View createRetryItem(int messageId) {
+        return createUserItem(messageId, R.string.attention_ready);
+    }
+
+    protected View createUserItem(int messageId, int actionId) {
+        View item = mInflater.inflate(R.layout.nls_item, mItemList, false);
+        TextView instructions = (TextView) item.findViewById(R.id.nls_instructions);
+        instructions.setText(messageId);
+        Button button = (Button) item.findViewById(R.id.nls_action_button);
+        button.setText(actionId);
+        mItemList.addView(item);
+        button.setTag(actionId);
+        return item;
+    }
+
+    protected View createAutoItem(int stringId) {
+        View item = mInflater.inflate(R.layout.nls_item, mItemList, false);
+        TextView instructions = (TextView) item.findViewById(R.id.nls_instructions);
+        instructions.setText(stringId);
+        View button = item.findViewById(R.id.nls_action_button);
+        button.setVisibility(View.GONE);
+        mItemList.addView(item);
+        return item;
+    }
+
+    // Test management
+
+    public void run() {
+        while (mState < mStatus.length && mStatus[mState] != WAIT_FOR_USER) {
+            if (mStatus[mState] == PASS) {
+                setItemState(mState, true);
+                mState++;
+            } else if (mStatus[mState] == FAIL) {
+                setItemState(mState, false);
+                return;
+            } else {
+                break;
+            }
+        }
+
+        if (mState < mStatus.length && mStatus[mState] == WAIT_FOR_USER) {
+            markItemWaiting(mState);
+        }
+
+        updateStateMachine();
+    }
+
+    protected void updateStateMachine() {
+        switch (mState) {
+            case 0:
+                testIsEnabled(mState);
+                break;
+            case 1:
+                testIsStarted(mState);
+                break;
+            case 2:
+                testNotificationRecieved(mState);
+                break;
+            case 3:
+                testDataIntact(mState);
+                break;
+            case 4:
+                testDismissOne(mState);
+                break;
+            case 5:
+                testDismissAll(mState);
+                break;
+            case 6:
+                testIsDisabled(mState);
+                break;
+            case 7:
+                testIsStopped(mState);
+                break;
+            case 8:
+                testNotificationNotRecieved(mState);
+                break;
+            case 9:
+                getPassButton().setEnabled(true);
+                mNm.cancelAll();
+                break;
+        }
+    }
+
+    public void launchSettings() {
+        startActivity(
+                new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"));
+    }
+
+    public void actionPressed(View v) {
+        Object tag = v.getTag();
+        if (tag instanceof Integer) {
+            int id = ((Integer) tag).intValue();
+            if (id == R.string.nls_start_settings) {
+                launchSettings();
+            } else if (id == R.string.attention_ready) {
+                mStatus[mState] = READY;
+                next();
+            }
+        }
+    }
+
+    protected PendingIntent makeIntent(int code, String tag) {
+        Intent intent = new Intent(tag);
+        intent.setComponent(new ComponentName(mContext, DismissService.class));
+        PendingIntent pi = PendingIntent.getService(mContext, code, intent,
+                PendingIntent.FLAG_UPDATE_CURRENT);
+        return pi;
+    }
+
+    @SuppressLint("NewApi")
+    private void sendNotifications() {
+        mTag1 = UUID.randomUUID().toString();
+        mTag2 = UUID.randomUUID().toString();
+        mTag3 = UUID.randomUUID().toString();
+
+        mNm.cancelAll();
+
+        mWhen1 = System.currentTimeMillis() + 1;
+        mWhen2 = System.currentTimeMillis() + 2;
+        mWhen3 = System.currentTimeMillis() + 3;
+
+        mIcon1 = R.drawable.fs_good;
+        mIcon2 = R.drawable.fs_error;
+        mIcon3 = R.drawable.fs_warning;
+
+        mId1 = NOTIFICATION_ID + 1;
+        mId2 = NOTIFICATION_ID + 2;
+        mId3 = NOTIFICATION_ID + 3;
+
+        mPackageString = "com.android.cts.verifier";
+
+        Notification n1 = new Notification.Builder(mContext)
+        .setContentTitle("ClearTest 1")
+        .setContentText(mTag1.toString())
+        .setPriority(Notification.PRIORITY_LOW)
+        .setSmallIcon(mIcon1)
+        .setWhen(mWhen1)
+        .setDeleteIntent(makeIntent(1, mTag1))
+        .setOnlyAlertOnce(true)
+        .build();
+        mNm.notify(mTag1, mId1, n1);
+        mFlag1 = Notification.FLAG_ONLY_ALERT_ONCE;
+
+        Notification n2 = new Notification.Builder(mContext)
+        .setContentTitle("ClearTest 2")
+        .setContentText(mTag2.toString())
+        .setPriority(Notification.PRIORITY_HIGH)
+        .setSmallIcon(mIcon2)
+        .setWhen(mWhen2)
+        .setDeleteIntent(makeIntent(2, mTag2))
+        .setAutoCancel(true)
+        .build();
+        mNm.notify(mTag2, mId2, n2);
+        mFlag2 = Notification.FLAG_AUTO_CANCEL;
+
+        Notification n3 = new Notification.Builder(mContext)
+        .setContentTitle("ClearTest 3")
+        .setContentText(mTag3.toString())
+        .setPriority(Notification.PRIORITY_LOW)
+        .setSmallIcon(mIcon3)
+        .setWhen(mWhen3)
+        .setDeleteIntent(makeIntent(3, mTag3))
+        .setAutoCancel(true)
+        .setOnlyAlertOnce(true)
+        .build();
+        mNm.notify(mTag3, mId3, n3);
+        mFlag3 = Notification.FLAG_ONLY_ALERT_ONCE | Notification.FLAG_AUTO_CANCEL;
+    }
+
+    /**
+     * Return to the state machine to progress through the tests.
+     */
+    protected void next() {
+        mHandler.removeCallbacks(mRunner);
+        mHandler.post(mRunner);
+    }
+
+    /**
+     * Wait for things to settle before returning to the state machine.
+     */
+    protected void delay() {
+        delay(2000);
+    }
+
+    /**
+     * Wait for some time.
+     */
+    protected void delay(long waitTime) {
+        mHandler.removeCallbacks(mRunner);
+        mHandler.postDelayed(mRunner, waitTime);
+    }
+
+    protected boolean checkEquals(long expected, long actual, String message) {
+        if (expected == actual) {
+            return true;
+        }
+        logWithStack(String.format(message, expected, actual));
+        return false;
+    }
+
+    protected boolean checkEquals(String expected, String actual, String message) {
+        if (expected.equals(actual)) {
+            return true;
+        }
+        logWithStack(String.format(message, expected, actual));
+        return false;
+    }
+
+    protected boolean checkFlagSet(int expected, int actual, String message) {
+        if ((expected & actual) != 0) {
+            return true;
+        }
+        logWithStack(String.format(message, expected, actual));
+        return false;
+    };
+
+    protected void logWithStack(String message) {
+        Throwable stackTrace = new Throwable();
+        stackTrace.fillInStackTrace();
+        Log.e(TAG, message, stackTrace);
+    }
+
+    // Tests
+
+    private void testIsEnabled(int i) {
+        // no setup required
+        Intent settings = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
+        if (settings.resolveActivity(mPackageManager) == null) {
+            logWithStack("failed testIsEnabled: no settings activity");
+            mStatus[i] = FAIL;
+        } else {
+            // TODO: find out why Secure.ENABLED_NOTIFICATION_LISTENERS is hidden
+            String listeners = Secure.getString(getContentResolver(),
+                    "enabled_notification_listeners");
+            if (listeners != null && listeners.contains(LISTENER_PATH)) {
+                mStatus[i] = PASS;
+            } else {
+                mStatus[i] = WAIT_FOR_USER;
+            }
+        }
+        next();
+    }
+
+    private void testIsStarted(final int i) {
+        if (mStatus[i] == SETUP) {
+            mStatus[i] = READY;
+            // wait for the service to start
+            delay();
+        } else {
+            MockListener.probeListenerStatus(mContext,
+                    new MockListener.StatusCatcher() {
+                @Override
+                public void accept(int result) {
+                    if (result == Activity.RESULT_OK) {
+                        mStatus[i] = PASS;
+                    } else {
+                        logWithStack("failed testIsStarted: " + result);
+                        mStatus[i] = FAIL;
+                    }
+                    next();
+                }
+            });
+        }
+    }
+
+    private void testNotificationRecieved(final int i) {
+        if (mStatus[i] == SETUP) {
+            MockListener.resetListenerData(this);
+            mStatus[i] = CLEARED;
+            // wait for intent to move through the system
+            delay();
+        } else if (mStatus[i] == CLEARED) {
+            sendNotifications();
+            mStatus[i] = READY;
+            // wait for notifications to move through the system
+            delay();
+        } else {
+            MockListener.probeListenerPosted(mContext,
+                    new MockListener.StringListResultCatcher() {
+                @Override
+                public void accept(List<String> result) {
+                    if (result != null && result.size() > 0 && result.contains(mTag1)) {
+                        mStatus[i] = PASS;
+                    } else {
+                        logWithStack("failed testNotificationRecieved");
+                        mStatus[i] = FAIL;
+                    }
+                    next();
+                }});
+        }
+    }
+
+    private void testDataIntact(final int i) {
+        // no setup required
+        MockListener.probeListenerPayloads(mContext,
+                new MockListener.StringListResultCatcher() {
+            @Override
+            public void accept(List<String> result) {
+                boolean pass = false;
+                Set<String> found = new HashSet<String>();
+                if (result != null && result.size() > 0) {
+                    pass = true;
+                    for(String payloadData : result) {
+                        try {
+                            JSONObject payload = new JSONObject(payloadData);
+                            pass &= checkEquals(mPackageString, payload.getString(JSON_PACKAGE),
+                                    "data integrity test fail: notification package (%s, %s)");
+                            String tag = payload.getString(JSON_TAG);
+                            if (mTag1.equals(tag)) {
+                                found.add(mTag1);
+                                pass &= checkEquals(mIcon1, payload.getInt(JSON_ICON),
+                                        "data integrity test fail: notification icon (%d, %d)");
+                                pass &= checkFlagSet(mFlag1, payload.getInt(JSON_FLAGS),
+                                        "data integrity test fail: notification flags (%d, %d)");
+                                pass &= checkEquals(mId1, payload.getInt(JSON_ID),
+                                        "data integrity test fail: notification ID (%d, %d)");
+                                pass &= checkEquals(mWhen1, payload.getLong(JSON_WHEN),
+                                        "data integrity test fail: notification when (%d, %d)");
+                            } else if (mTag2.equals(tag)) {
+                                found.add(mTag2);
+                                pass &= checkEquals(mIcon2, payload.getInt(JSON_ICON),
+                                        "data integrity test fail: notification icon (%d, %d)");
+                                pass &= checkFlagSet(mFlag2, payload.getInt(JSON_FLAGS),
+                                        "data integrity test fail: notification flags (%d, %d)");
+                                pass &= checkEquals(mId2, payload.getInt(JSON_ID),
+                                        "data integrity test fail: notification ID (%d, %d)");
+                                pass &= checkEquals(mWhen2, payload.getLong(JSON_WHEN),
+                                        "data integrity test fail: notification when (%d, %d)");
+                            } else if (mTag3.equals(tag)) {
+                                found.add(mTag3);
+                                pass &= checkEquals(mIcon3, payload.getInt(JSON_ICON),
+                                        "data integrity test fail: notification icon (%d, %d)");
+                                pass &= checkFlagSet(mFlag3, payload.getInt(JSON_FLAGS),
+                                        "data integrity test fail: notification flags (%d, %d)");
+                                pass &= checkEquals(mId3, payload.getInt(JSON_ID),
+                                        "data integrity test fail: notification ID (%d, %d)");
+                                pass &= checkEquals(mWhen3, payload.getLong(JSON_WHEN),
+                                        "data integrity test fail: notification when (%d, %d)");
+                            } else {
+                                pass = false;
+                                logWithStack("failed on unexpected notification tag: " + tag);
+                            }
+                        } catch (JSONException e) {
+                            pass = false;
+                            Log.e(TAG, "failed to unpack data from mocklistener", e);
+                        }
+                    }
+                }
+                pass &= found.size() == 3;
+                mStatus[i] = pass ? PASS : FAIL;
+                next();
+            }});
+    }
+
+    private void testDismissOne(final int i) {
+        if (mStatus[i] == SETUP) {
+            MockListener.resetListenerData(this);
+            mStatus[i] = CLEARED;
+            // wait for intent to move through the system
+            delay();
+        } else if (mStatus[i] == CLEARED) {
+            MockListener.clearOne(mContext, mTag1, NOTIFICATION_ID + 1);
+            mStatus[i] = READY;
+            delay();
+        } else {
+            MockListener.probeListenerRemoved(mContext,
+                    new MockListener.StringListResultCatcher() {
+                @Override
+                public void accept(List<String> result) {
+                    if (result != null && result.size() > 0 && result.contains(mTag1)) {
+                        mStatus[i] = PASS;
+                        next();
+                    } else {
+                        if (mStatus[i] == RETRY) {
+                            logWithStack("failed testDismissOne");
+                            mStatus[i] = FAIL;
+                            next();
+                        } else {
+                            logWithStack("failed testDismissOne, once: retrying");
+                            mStatus[i] = RETRY;
+                            delay();
+                        }
+                    }
+                }});
+        }
+    }
+
+    private void testDismissAll(final int i) {
+        if (mStatus[i] == SETUP) {
+            MockListener.resetListenerData(this);
+            mStatus[i] = CLEARED;
+            // wait for intent to move through the system
+            delay();
+        } else if (mStatus[i] == CLEARED) {
+            MockListener.clearAll(mContext);
+            mStatus[i] = READY;
+            delay();
+        } else {
+            MockListener.probeListenerRemoved(mContext,
+                    new MockListener.StringListResultCatcher() {
+                @Override
+                public void accept(List<String> result) {
+                    if (result != null && result.size() == 2
+                            && result.contains(mTag2) && result.contains(mTag3)) {
+                        mStatus[i] = PASS;
+                        next();
+                    } else {
+                        if (mStatus[i] == RETRY) {
+                            logWithStack("failed testDismissAll");
+                            mStatus[i] = FAIL;
+                            next();
+                        } else {
+                            logWithStack("failed testDismissAll, once: retrying");
+                            mStatus[i] = RETRY;
+                            delay();
+                        }
+                    }
+                }
+            });
+        }
+    }
+
+    private void testIsDisabled(int i) {
+        // no setup required
+        // TODO: find out why Secure.ENABLED_NOTIFICATION_LISTENERS is hidden
+        String listeners = Secure.getString(getContentResolver(),
+                "enabled_notification_listeners");
+        if (listeners == null || !listeners.contains(LISTENER_PATH)) {
+            mStatus[i] = PASS;
+            next();
+        } else {
+            mStatus[i] = WAIT_FOR_USER;
+            delay();
+        }
+    }
+
+    private void testIsStopped(final int i) {
+        if (mStatus[i] == SETUP) {
+            mStatus[i] = READY;
+            // wait for the service to start
+            delay();
+        } else {
+            MockListener.probeListenerStatus(mContext,
+                    new MockListener.StatusCatcher() {
+                @Override
+                public void accept(int result) {
+                    if (result == Activity.RESULT_OK) {
+                        logWithStack("failed testIsStopped");
+                        mStatus[i] = FAIL;
+                    } else {
+                        mStatus[i] = PASS;
+                    }
+                    next();
+                }
+            });
+        }
+    }
+
+    private void testNotificationNotRecieved(final int i) {
+        if (mStatus[i] == SETUP) {
+            MockListener.resetListenerData(this);
+            mStatus[i] = CLEARED;
+            // wait for intent to move through the system
+            delay();
+        } else if (mStatus[i] == CLEARED) {
+            // setup for testNotificationRecieved
+            sendNotifications();
+            mStatus[i] = READY;
+            delay();
+        } else {
+            MockListener.probeListenerPosted(mContext,
+                    new MockListener.StringListResultCatcher() {
+                @Override
+                public void accept(List<String> result) {
+                    if (result == null || result.size() == 0) {
+                        mStatus[i] = PASS;
+                    } else {
+                        logWithStack("failed testNotificationNotRecieved");
+                        mStatus[i] = FAIL;
+                    }
+                    next();
+                }});
+        }
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/IProjectionService.aidl b/apps/CtsVerifier/src/com/android/cts/verifier/projection/IProjectionService.aidl
new file mode 100644
index 0000000..0bc1b20
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/IProjectionService.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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 com.android.cts.verifier.projection;
+
+import android.view.Surface;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+interface IProjectionService {
+    void startRendering(in Surface surface, int width, int height, int density, int viewType);
+    void stopRendering();
+    void onTouchEvent(in MotionEvent event);
+    void onKeyEvent(in KeyEvent event);
+}
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/ProjectedPresentation.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/ProjectedPresentation.java
new file mode 100644
index 0000000..53d715a
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/ProjectedPresentation.java
@@ -0,0 +1,50 @@
+/*
+ * 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 com.android.cts.verifier.projection;
+
+import android.app.Presentation;
+import android.content.Context;
+import android.view.Display;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.WindowManager;
+
+/**
+ * Base class for Presentations which are to be projected onto a VirtualDisplay
+ */
+public abstract class ProjectedPresentation extends Presentation {
+    public ProjectedPresentation(Context outerContext, Display display) {
+        // This theme is required to prevent an extra view from obscuring the presentation
+        super(outerContext, display, android.R.style.Theme_Holo_Light_NoActionBar_TranslucentDecor);
+
+        getWindow().setType(WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION);
+
+        // So we can control the input
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE);
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
+    }
+
+    public void injectTouchEvent(MotionEvent event) {
+        getWindow().setLocalFocus(true, true);
+        getWindow().injectInputEvent(event);
+    }
+
+    public void injectKeyEvent(KeyEvent event) {
+        getWindow().setLocalFocus(true, false);
+        getWindow().injectInputEvent(event);
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/ProjectionActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/ProjectionActivity.java
new file mode 100644
index 0000000..18d9d43
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/ProjectionActivity.java
@@ -0,0 +1,160 @@
+/*
+ * 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 com.android.cts.verifier.projection;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.graphics.SurfaceTexture;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.Surface;
+import android.view.TextureView;
+import android.view.View;
+import android.view.View.OnTouchListener;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+/**
+ * Base activity for each projection test case. Handles the service connection and TextureView
+ * listeners
+ */
+public abstract class ProjectionActivity extends PassFailButtons.Activity
+        implements TextureView.SurfaceTextureListener {
+    private static final String TAG = ProjectionActivity.class.getSimpleName();
+    protected Intent mStartIntent;
+    protected TextureView mTextureView;
+    protected volatile Surface mSurface;
+    protected int mWidth;
+    protected int mHeight;
+    protected ProjectionPresentationType mType;
+
+    protected IProjectionService mService;
+    protected final ServiceConnection mConnection = new ServiceConnection() {
+
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder binder) {
+            mService = IProjectionService.Stub.asInterface(binder);
+            new Handler().post(new Runnable() {
+
+                @Override
+                public void run() {
+                    Log.i(TAG, "onServiceConnected thread " + Thread.currentThread());
+                    DisplayMetrics metrics = ProjectionActivity.this.getResources().getDisplayMetrics();
+                    try {
+                        mService.startRendering(mSurface, mWidth, mHeight, metrics.densityDpi, mType.ordinal());
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Failed to execute startRendering", e);
+                    }
+                }
+
+            });
+
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            mService = null;
+        }
+
+    };
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Log.i(TAG, "onCreate");
+        mStartIntent = new Intent(this, ProjectionService.class);
+
+    }
+
+    protected View setContentViewAndInfoResources(int layoutId, int titleId, int infoId) {
+        View view = getLayoutInflater().inflate(layoutId, null);
+        setContentView(view);
+
+        mTextureView = (TextureView) view.findViewById(R.id.texture_view);
+        mTextureView.setSurfaceTextureListener(this);
+        mTextureView.setOnTouchListener(new OnTouchListener() {
+
+            @Override
+            public boolean onTouch(View view, MotionEvent event) {
+                if (mService != null) {
+                    try {
+                        mService.onTouchEvent(event);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Failed to execute onTouchEvent", e);
+                    }
+                }
+                return true;
+            }
+
+        });
+
+        setInfoResources(titleId, infoId, -1);
+        setPassFailButtonClickListeners();
+        return view;
+    }
+
+    @Override
+    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
+        Log.i(TAG, "onSurfaceTextureAvailable " + "w: " + width + " h: " + height);
+        mSurface = new Surface(surface);
+        mWidth = width;
+        mHeight = height;
+        if (mService == null) {
+            bindService(mStartIntent, mConnection,
+                    Context.BIND_AUTO_CREATE);
+        }
+
+    }
+
+    @Override
+    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
+        Log.i(TAG, "onSurfaceTextureDestroyed");
+        if (mService != null) {
+            try {
+                mService.stopRendering();
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to execute stopRendering", e);
+            }
+        }
+        mSurface.release();
+        mSurface = null;
+
+        unbindService(mConnection);
+        return true;
+    }
+
+    @Override
+    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+        Log.i(TAG, "onSurfaceTextureSizeChanged " + surface.toString() + "w: " + width + " h: "
+                + height);
+    }
+
+    @Override
+    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+        Log.i(TAG, "onSurfaceTextureUpdated " + surface.toString());
+    }
+
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/ProjectionPresentationType.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/ProjectionPresentationType.java
new file mode 100644
index 0000000..fbcd1a3
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/ProjectionPresentationType.java
@@ -0,0 +1,26 @@
+/*
+ * 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 com.android.cts.verifier.projection;
+
+public enum ProjectionPresentationType {
+    TUMBLING_CUBES,
+    BASIC_WIDGETS,
+    MULTI_TOUCH,
+    SCROLLING_LIST,
+    VIDEO_PLAYBACK,
+    OFFSCREEN
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/ProjectionService.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/ProjectionService.java
new file mode 100644
index 0000000..11f8e0c
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/ProjectionService.java
@@ -0,0 +1,151 @@
+/*
+ * 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 com.android.cts.verifier.projection;
+
+import android.app.Service;
+import android.content.Intent;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.VirtualDisplay;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.Surface;
+
+import com.android.cts.verifier.projection.cube.CubePresentation;
+import com.android.cts.verifier.projection.list.ListPresentation;
+import com.android.cts.verifier.projection.offscreen.OffscreenPresentation;
+import com.android.cts.verifier.projection.touch.TouchPresentation;
+import com.android.cts.verifier.projection.video.VideoPresentation;
+import com.android.cts.verifier.projection.widgets.WidgetPresentation;
+
+/**
+ * Service to handle rendering of views on a virtual display and to forward input events to the
+ * display
+ */
+public class ProjectionService extends Service {
+    private final String TAG = ProjectionService.class.getSimpleName();
+    private final String DISPLAY_NAME = "CtsVerifier Virtual Display";
+
+    private Handler mUIHandler;
+
+    private ProjectedPresentation createPresentation(int typeOrdinal) {
+        ProjectionPresentationType type = ProjectionPresentationType.values()[typeOrdinal];
+        switch (type) {
+            case TUMBLING_CUBES:
+                return new CubePresentation(ProjectionService.this, mDisplay.getDisplay());
+
+            case BASIC_WIDGETS:
+                return new WidgetPresentation(ProjectionService.this, mDisplay.getDisplay());
+
+            case SCROLLING_LIST:
+                return new ListPresentation(ProjectionService.this, mDisplay.getDisplay());
+
+            case VIDEO_PLAYBACK:
+                return new VideoPresentation(ProjectionService.this, mDisplay.getDisplay());
+
+            case MULTI_TOUCH:
+                return new TouchPresentation(ProjectionService.this, mDisplay.getDisplay());
+
+            case OFFSCREEN:
+                return new OffscreenPresentation(ProjectionService.this, mDisplay.getDisplay());
+        }
+
+        return null;
+    }
+
+    private class ProjectionServiceBinder extends IProjectionService.Stub {
+        @Override
+        public void startRendering(final Surface surface, final int width, final int height,
+                final int density,
+                final int viewType) throws RemoteException {
+            mUIHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    DisplayManager manager = (DisplayManager) getSystemService(DISPLAY_SERVICE);
+                    Log.i(TAG, "Surface " + surface.toString() + ": "
+                            + Boolean.toString(surface.isValid()));
+                    mDisplay = manager.createVirtualDisplay(DISPLAY_NAME, width, height, density,
+                            surface, 0);
+                    mPresentation = createPresentation(viewType);
+                    if (mPresentation == null) {
+                        return;
+                    }
+
+                    mPresentation.show();
+                }
+            });
+        }
+
+        @Override
+        public void stopRendering() throws RemoteException {
+            mUIHandler.post(new Runnable() {
+
+                @Override
+                public void run() {
+                    if (mPresentation != null) {
+                        mPresentation.dismiss();
+                        mPresentation = null;
+                    }
+                }
+
+            });
+        }
+
+        @Override
+        public void onTouchEvent(final MotionEvent event) throws RemoteException {
+            mUIHandler.post(new Runnable() {
+
+                @Override
+                public void run() {
+                    if (mPresentation != null) {
+                        mPresentation.injectTouchEvent(event);
+                    }
+                }
+
+            });
+        }
+
+        @Override
+        public void onKeyEvent(final KeyEvent event) throws RemoteException {
+            mUIHandler.post(new Runnable() {
+
+                @Override
+                public void run() {
+                    if (mPresentation != null) {
+                        mPresentation.injectKeyEvent(event);
+                    }
+                }
+
+            });
+        }
+    }
+
+    private final IBinder mBinder = new ProjectionServiceBinder();
+    private VirtualDisplay mDisplay;
+    private ProjectedPresentation mPresentation;
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        Log.i(TAG, "onBind");
+        mUIHandler = new Handler(Looper.getMainLooper());
+        return mBinder;
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/cube/Cube.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/cube/Cube.java
new file mode 100644
index 0000000..0b521fb
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/cube/Cube.java
@@ -0,0 +1,100 @@
+/*
+ * 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 com.android.cts.verifier.projection.cube;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.IntBuffer;
+
+import javax.microedition.khronos.opengles.GL10;
+
+/**
+ * A vertex shaded cube.
+ */
+class Cube
+{
+    public Cube()
+    {
+        int one = 0x10000;
+        int vertices[] = {
+                -one, -one, -one,
+                one, -one, -one,
+                one,  one, -one,
+                -one,  one, -one,
+                -one, -one,  one,
+                one, -one,  one,
+                one,  one,  one,
+                -one,  one,  one,
+        };
+
+        int colors[] = {
+                0,    0,    0,  one,
+                one,    0,    0,  one,
+                one,  one,    0,  one,
+                0,  one,    0,  one,
+                0,    0,  one,  one,
+                one,    0,  one,  one,
+                one,  one,  one,  one,
+                0,  one,  one,  one,
+        };
+
+        byte indices[] = {
+                0, 4, 5,    0, 5, 1,
+                1, 5, 6,    1, 6, 2,
+                2, 6, 7,    2, 7, 3,
+                3, 7, 4,    3, 4, 0,
+                4, 7, 6,    4, 6, 5,
+                3, 0, 1,    3, 1, 2
+        };
+
+        // Buffers to be passed to gl*Pointer() functions
+        // must be direct, i.e., they must be placed on the
+        // native heap where the garbage collector cannot
+        // move them.
+        //
+        // Buffers with multi-byte datatypes (e.g., short, int, float)
+        // must have their byte order set to native order
+
+        ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
+        vbb.order(ByteOrder.nativeOrder());
+        mVertexBuffer = vbb.asIntBuffer();
+        mVertexBuffer.put(vertices);
+        mVertexBuffer.position(0);
+
+        ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length*4);
+        cbb.order(ByteOrder.nativeOrder());
+        mColorBuffer = cbb.asIntBuffer();
+        mColorBuffer.put(colors);
+        mColorBuffer.position(0);
+
+        mIndexBuffer = ByteBuffer.allocateDirect(indices.length);
+        mIndexBuffer.put(indices);
+        mIndexBuffer.position(0);
+    }
+
+    public void draw(GL10 gl)
+    {
+        gl.glFrontFace(GL10.GL_CW);
+        gl.glVertexPointer(3, GL10.GL_FIXED, 0, mVertexBuffer);
+        gl.glColorPointer(4, GL10.GL_FIXED, 0, mColorBuffer);
+        gl.glDrawElements(GL10.GL_TRIANGLES, 36, GL10.GL_UNSIGNED_BYTE, mIndexBuffer);
+    }
+
+    private IntBuffer   mVertexBuffer;
+    private IntBuffer   mColorBuffer;
+    private ByteBuffer  mIndexBuffer;
+}
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/cube/CubePresentation.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/cube/CubePresentation.java
new file mode 100644
index 0000000..bf7825b
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/cube/CubePresentation.java
@@ -0,0 +1,60 @@
+/*
+ * 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 com.android.cts.verifier.projection.cube;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.view.Display;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnTouchListener;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.projection.ProjectedPresentation;
+
+
+
+/**
+ * Render tumbling cubes
+ *
+ */
+public class CubePresentation extends ProjectedPresentation {
+    public CubePresentation(Context context, Display display) {
+        super(context, display);
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        View view = getLayoutInflater().inflate(R.layout.pca_cubes, null);
+        setContentView(view);
+
+        GLSurfaceView cubeView = (GLSurfaceView) view.findViewById(R.id.cube_view);
+        final CubeRenderer renderer = new CubeRenderer(true);
+        cubeView.setRenderer(renderer);
+
+        cubeView.setOnTouchListener(new OnTouchListener() {
+
+            @Override
+            public boolean onTouch(View view, MotionEvent event) {
+                renderer.explode();
+                return true;
+            }
+        });
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/cube/CubeRenderer.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/cube/CubeRenderer.java
new file mode 100644
index 0000000..9205fec
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/cube/CubeRenderer.java
@@ -0,0 +1,128 @@
+/*
+ * 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 com.android.cts.verifier.projection.cube;
+
+import android.opengl.GLSurfaceView;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+/**
+ * Render a pair of tumbling cubes.
+ */
+public class CubeRenderer implements GLSurfaceView.Renderer {
+
+    private final boolean mTranslucentBackground;
+
+    private final Cube mCube;
+    private float mAngle;
+    private float mScale = 1.0f;
+    private boolean mExploding;
+
+    public CubeRenderer(boolean useTranslucentBackground) {
+        mTranslucentBackground = useTranslucentBackground;
+        mCube = new Cube();
+    }
+
+    public void explode() {
+        mExploding = true;
+    }
+
+    @Override
+    public void onDrawFrame(GL10 gl) {
+        /*
+         * Usually, the first thing one might want to do is to clear
+         * the screen. The most efficient way of doing this is to use
+         * glClear().
+         */
+
+        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+
+        /*
+         * Now we're ready to draw some 3D objects
+         */
+
+        gl.glMatrixMode(GL10.GL_MODELVIEW);
+        gl.glLoadIdentity();
+        gl.glTranslatef(0, 0, -3.0f);
+        gl.glRotatef(mAngle,        0, 1, 0);
+        gl.glRotatef(mAngle*0.25f,  1, 0, 0);
+
+        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
+        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
+
+        gl.glScalef(mScale, mScale, mScale);
+        mCube.draw(gl);
+
+        gl.glRotatef(mAngle*2.0f, 0, 1, 1);
+        gl.glTranslatef(0.5f, 0.5f, 0.5f);
+
+        mCube.draw(gl);
+
+        mAngle += 1.2f;
+
+        if (mExploding) {
+            mScale *= 1.02f;
+            if (mScale > 4.0f) {
+                mScale = 1.0f;
+                mExploding = false;
+            }
+        }
+    }
+
+    @Override
+    public void onSurfaceChanged(GL10 gl, int width, int height) {
+        gl.glViewport(0, 0, width, height);
+
+        /*
+         * Set our projection matrix. This doesn't have to be done
+         * each time we draw, but usually a new projection needs to
+         * be set when the viewport is resized.
+         */
+
+        float ratio = (float) width / height;
+        gl.glMatrixMode(GL10.GL_PROJECTION);
+        gl.glLoadIdentity();
+        gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
+    }
+
+    @Override
+    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+        /*
+         * By default, OpenGL enables features that improve quality
+         * but reduce performance. One might want to tweak that
+         * especially on software renderer.
+         */
+        gl.glDisable(GL10.GL_DITHER);
+
+        /*
+         * Some one-time OpenGL initialization can be made here
+         * probably based on features of this particular context
+         */
+        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,
+                GL10.GL_FASTEST);
+
+        if (mTranslucentBackground) {
+            gl.glClearColor(0,0,0,0);
+        } else {
+            gl.glClearColor(1,1,1,1);
+        }
+        gl.glEnable(GL10.GL_CULL_FACE);
+        gl.glShadeModel(GL10.GL_SMOOTH);
+        gl.glEnable(GL10.GL_DEPTH_TEST);
+    }
+}
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/cube/ProjectionCubeActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/cube/ProjectionCubeActivity.java
new file mode 100644
index 0000000..0ef9a30
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/cube/ProjectionCubeActivity.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 com.android.cts.verifier.projection.cube;
+
+import com.android.cts.verifier.R;
+
+import android.os.Bundle;
+import android.util.Log;
+
+import com.android.cts.verifier.projection.ProjectionActivity;
+import com.android.cts.verifier.projection.ProjectionPresentationType;
+
+public class ProjectionCubeActivity extends ProjectionActivity {
+    private static final String TAG = ProjectionCubeActivity.class.getSimpleName();
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Log.i(TAG, "onCreate");
+        setContentViewAndInfoResources(R.layout.pa_main, R.string.pca_test, R.string.pca_info);
+        mType = ProjectionPresentationType.TUMBLING_CUBES;
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/list/ListPresentation.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/list/ListPresentation.java
new file mode 100644
index 0000000..5dddf5c
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/list/ListPresentation.java
@@ -0,0 +1,62 @@
+/*
+ * 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 com.android.cts.verifier.projection.list;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.view.Display;
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.projection.ProjectedPresentation;
+
+import java.util.ArrayList;
+
+/**
+ * Render a list view that scrolls
+ */
+public class ListPresentation extends ProjectedPresentation {
+    private ArrayList<String> mItemList = new ArrayList<String>();
+    private static final int NUM_ITEMS = 50; // Enough to make the list scroll
+
+    /**
+     * @param outerContext
+     * @param display
+     */
+    public ListPresentation(Context outerContext, Display display) {
+        super(outerContext, display);
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        View view = getLayoutInflater().inflate(R.layout.pla_list, null);
+        setContentView(view);
+
+        for (int i = 0; i < NUM_ITEMS; ++i) {
+            mItemList.add("Item #" + 1 + i);
+        }
+
+        ListView listView = (ListView) view.findViewById(R.id.pla_list);
+
+        listView.setAdapter(new ArrayAdapter<String>(getContext(),
+                android.R.layout.simple_list_item_1, mItemList));
+    }
+
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/list/ProjectionListActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/list/ProjectionListActivity.java
new file mode 100644
index 0000000..c166320
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/list/ProjectionListActivity.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 com.android.cts.verifier.projection.list;
+
+import android.os.Bundle;
+import android.util.Log;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.projection.ProjectionActivity;
+import com.android.cts.verifier.projection.ProjectionPresentationType;
+import com.android.cts.verifier.projection.cube.ProjectionCubeActivity;
+
+public class ProjectionListActivity extends ProjectionActivity {
+    private static final String TAG = ProjectionCubeActivity.class.getSimpleName();
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Log.i(TAG, "onCreate");
+        setContentViewAndInfoResources(R.layout.pa_main, R.string.pla_test, R.string.pla_info);
+        mType = ProjectionPresentationType.SCROLLING_LIST;
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/offscreen/ColorChangeOnKeyView.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/offscreen/ColorChangeOnKeyView.java
new file mode 100644
index 0000000..297009a
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/offscreen/ColorChangeOnKeyView.java
@@ -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.
+ */
+
+package com.android.cts.verifier.projection.offscreen;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.View;
+
+/**
+ * Changes color from black to blue on keyevent
+ */
+public class ColorChangeOnKeyView extends View {
+    private int mColor = Color.BLACK;
+
+    public ColorChangeOnKeyView(Context context) {
+        super(context);
+    }
+
+    public ColorChangeOnKeyView(Context context, AttributeSet attrs) {
+        super(context, attrs, 0);
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+            mColor = Color.BLUE;
+            invalidate();
+            return true;
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        canvas.drawColor(mColor);
+    }
+
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/offscreen/OffscreenPresentation.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/offscreen/OffscreenPresentation.java
new file mode 100644
index 0000000..18ba20d
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/offscreen/OffscreenPresentation.java
@@ -0,0 +1,41 @@
+/*
+ * 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 com.android.cts.verifier.projection.offscreen;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.view.Display;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.projection.ProjectedPresentation;
+
+/**
+ * Draws a presentation that will be interacted with fake events while the screen is off
+ */
+public class OffscreenPresentation extends ProjectedPresentation {
+
+    public OffscreenPresentation(Context outerContext, Display display) {
+        super(outerContext, display);
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.poa_touch);
+    }
+
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/offscreen/ProjectionOffscreenActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/offscreen/ProjectionOffscreenActivity.java
new file mode 100644
index 0000000..510a03b
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/offscreen/ProjectionOffscreenActivity.java
@@ -0,0 +1,283 @@
+/*
+ * 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 com.android.cts.verifier.projection.offscreen;
+
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.ServiceConnection;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.media.Image;
+import android.media.ImageReader;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.View;
+import android.widget.TextView;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.projection.IProjectionService;
+import com.android.cts.verifier.projection.ProjectionPresentationType;
+import com.android.cts.verifier.projection.ProjectionService;
+
+import java.nio.ByteBuffer;
+
+public class ProjectionOffscreenActivity extends PassFailButtons.Activity
+        implements ImageReader.OnImageAvailableListener {
+    private static String TAG = ProjectionOffscreenActivity.class.getSimpleName();
+    private static final int WIDTH = 800;
+    private static final int HEIGHT = 480;
+    private static final int DENSITY = DisplayMetrics.DENSITY_MEDIUM;
+    private static final int TIME_SCREEN_OFF = 5000; // Time screen must remain off for test to run
+    private static final int DELAYED_RUNNABLE_TIME = 1000; // Time after screen turned off
+                                                           // keyevent is sent
+    private static final int RENDERER_DELAY_THRESHOLD = 2000; // Time after keyevent sent that
+                                                              // rendering must happen by
+
+    protected ImageReader mReader;
+    protected IProjectionService mService;
+    protected TextView mStatusView;
+    protected int mPreviousColor = Color.BLACK;
+    private long mTimeScreenTurnedOff = 0;
+    private long mTimeKeyEventSent = 0;
+    private enum TestStatus { PASSED, FAILED, RUNNING };
+    protected TestStatus mTestStatus = TestStatus.RUNNING;
+
+    private final Runnable sendKeyEventRunnable = new Runnable() {
+        @Override
+        public void run() {
+            try {
+                mService.onKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN));
+                mTimeKeyEventSent = SystemClock.uptimeMillis();
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error running onKeyEvent", e);
+            }
+        }
+    };
+
+    private final Runnable playNotificationRunnable = new Runnable() {
+
+        @Override
+        public void run() {
+            Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
+            Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
+            r.play();
+        }
+    };
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
+            Handler handler = new Handler(Looper.getMainLooper());
+            handler.postDelayed(
+                    sendKeyEventRunnable, DELAYED_RUNNABLE_TIME);
+            mStatusView.setText("Running test...");
+            mTimeScreenTurnedOff = SystemClock.uptimeMillis();
+            // Notify user its safe to turn screen back on after 5s + fudge factor
+            handler.postDelayed(playNotificationRunnable, TIME_SCREEN_OFF + 500);
+        } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
+            if (SystemClock.uptimeMillis() - mTimeScreenTurnedOff < TIME_SCREEN_OFF) {
+                mStatusView.setText("ERROR: Turned on screen too early");
+                getPassButton().setEnabled(false);
+                mTestStatus = TestStatus.FAILED;
+            }
+        }
+    }
+
+};
+
+    protected final ServiceConnection mConnection = new ServiceConnection() {
+
+            @Override
+        public void onServiceConnected(ComponentName name, IBinder binder) {
+            mService = IProjectionService.Stub.asInterface(binder);
+            new Handler().post(new Runnable() {
+
+                    @Override
+                public void run() {
+                    Log.i(TAG, "onServiceConnected thread " + Thread.currentThread());
+                    try {
+                        mService.startRendering(mReader.getSurface(), WIDTH, HEIGHT, DENSITY,
+                                ProjectionPresentationType.OFFSCREEN.ordinal());
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Failed to execute startRendering", e);
+                    }
+
+                    IntentFilter filter = new IntentFilter();
+                    filter.addAction(Intent.ACTION_SCREEN_OFF);
+                    filter.addAction(Intent.ACTION_SCREEN_ON);
+
+                    registerReceiver(mReceiver, filter);
+                    mStatusView.setText("Please turn off your screen and turn it back on after " +
+                            "5 seconds. A sound will be played when it is safe to turn the " +
+                            "screen back on");
+                }
+
+            });
+
+        }
+
+            @Override
+        public void onServiceDisconnected(ComponentName name) {
+            mService = null;
+        }
+
+    };
+
+
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        View view = getLayoutInflater().inflate(R.layout.poa_main, null);
+        mStatusView = (TextView) view.findViewById(R.id.poa_status_text);
+        mStatusView.setText("Waiting for service to bind...");
+
+        setContentView(view);
+
+        setInfoResources(R.string.poa_test, R.string.poa_info, -1);
+        setPassFailButtonClickListeners();
+        mReader = ImageReader.newInstance(WIDTH, HEIGHT, PixelFormat.RGBA_8888, 2);
+        mReader.setOnImageAvailableListener(this, null);
+        bindService(new Intent(this, ProjectionService.class), mConnection,
+                Context.BIND_AUTO_CREATE);
+
+        getPassButton().setEnabled(false);
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        unregisterReceiver(mReceiver);
+        mReader.close();
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        if (mTestStatus == TestStatus.FAILED) {
+            setTestResultAndFinish(false);
+        }
+    }
+
+    @Override
+    public void onImageAvailable(ImageReader reader) {
+        Log.i(TAG, "onImageAvailable: " + reader);
+
+        if (mTimeKeyEventSent != 0
+                && mTestStatus == TestStatus.RUNNING
+                && mTimeKeyEventSent + RENDERER_DELAY_THRESHOLD < SystemClock.uptimeMillis()) {
+            mTestStatus = TestStatus.FAILED;
+            mStatusView.setText("Failed: took too long to render");
+        }
+
+        Image image = reader.acquireLatestImage();
+
+        // No new images available
+        if (image == null) {
+            Log.w(TAG, "onImageAvailable called but no image!");
+            return;
+        }
+
+        if (mTestStatus == TestStatus.RUNNING) {
+            int ret = scanImage(image);
+            if (ret == -1) {
+                mStatusView.setText("Failed: saw unexpected color");
+                getPassButton().setEnabled(false);
+                mTestStatus = TestStatus.FAILED;
+            } else if (ret != mPreviousColor && ret == Color.BLUE) {
+                mStatusView.setText("Success: virtual display rendered expected color");
+                getPassButton().setEnabled(true);
+                mTestStatus = TestStatus.PASSED;
+            }
+        }
+        image.close();
+    }
+
+    // modified from the VirtualDisplay Cts test
+    /**
+     * Gets the color of the image and ensures all the pixels are the same color
+     * @param image input image
+     * @return The color of the image, or -1 for failure
+     */
+    private int scanImage(Image image) {
+        final Image.Plane plane = image.getPlanes()[0];
+        final ByteBuffer buffer = plane.getBuffer();
+        final int width = image.getWidth();
+        final int height = image.getHeight();
+        final int pixelStride = plane.getPixelStride();
+        final int rowStride = plane.getRowStride();
+        final int rowPadding = rowStride - pixelStride * width;
+
+        Log.d(TAG, "- Scanning image: width=" + width + ", height=" + height
+                + ", pixelStride=" + pixelStride + ", rowStride=" + rowStride);
+
+        int offset = 0;
+        int blackPixels = 0;
+        int bluePixels = 0;
+        int otherPixels = 0;
+        for (int y = 0; y < height; y++) {
+            for (int x = 0; x < width; x++) {
+                int pixel = 0;
+                pixel |= (buffer.get(offset) & 0xff) << 16;     // R
+                pixel |= (buffer.get(offset + 1) & 0xff) << 8;  // G
+                pixel |= (buffer.get(offset + 2) & 0xff);       // B
+                pixel |= (buffer.get(offset + 3) & 0xff) << 24; // A
+                if (pixel == Color.BLACK || pixel == 0) {
+                    blackPixels += 1;
+                } else if (pixel == Color.BLUE) {
+                    bluePixels += 1;
+                } else {
+                    otherPixels += 1;
+                    if (otherPixels < 10) {
+                        Log.d(TAG, "- Found unexpected color: " + Integer.toHexString(pixel));
+                    }
+                }
+                offset += pixelStride;
+            }
+            offset += rowPadding;
+        }
+
+        // Return a color if it represents all of the pixels.
+        Log.d(TAG, "- Pixels: " + blackPixels + " black, "
+                + bluePixels + " blue, "
+                + otherPixels + " other");
+        if (blackPixels == width * height) {
+            return Color.BLACK;
+        } else if (bluePixels == width * height) {
+            return Color.BLUE;
+        } else {
+            return -1;
+        }
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/touch/ProjectionTouchActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/touch/ProjectionTouchActivity.java
new file mode 100644
index 0000000..ed1d881
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/touch/ProjectionTouchActivity.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 com.android.cts.verifier.projection.touch;
+
+import android.os.Bundle;
+import android.util.Log;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.projection.ProjectionActivity;
+import com.android.cts.verifier.projection.ProjectionPresentationType;
+import com.android.cts.verifier.projection.cube.ProjectionCubeActivity;
+
+public class ProjectionTouchActivity extends ProjectionActivity {
+    private static final String TAG = ProjectionCubeActivity.class.getSimpleName();
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Log.i(TAG, "onCreate");
+        setContentViewAndInfoResources(R.layout.pa_main, R.string.pta_test, R.string.pta_info);
+        mType = ProjectionPresentationType.MULTI_TOUCH;
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/touch/TouchPointView.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/touch/TouchPointView.java
new file mode 100644
index 0000000..c88fd79
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/touch/TouchPointView.java
@@ -0,0 +1,98 @@
+/*
+ * 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 com.android.cts.verifier.projection.touch;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+
+import java.util.ArrayList;
+import java.util.List;
+/*
+ * Simple view that draws a circle where a touch is registered
+ */
+public class TouchPointView extends View {
+    @SuppressWarnings("unused")
+    private static final String TAG = TouchPointView.class.getSimpleName();
+
+    private final int[] mColors = {
+            Color.RED,
+            Color.GREEN,
+            Color.BLUE,
+            Color.YELLOW,
+            Color.MAGENTA,
+            Color.BLACK,
+            Color.DKGRAY
+    };
+    List<Finger> mFingers;
+    Paint mPaint;
+
+    public TouchPointView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public TouchPointView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        mFingers = new ArrayList<Finger>();
+
+        mPaint = new Paint();
+        mPaint.setStyle(Paint.Style.FILL);
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        mFingers.clear();
+        if (event.getActionMasked() == MotionEvent.ACTION_UP) {
+            invalidate();
+            return true;
+        }
+        for (int i = 0; i < event.getPointerCount(); i++) {
+            int pointerId = event.getPointerId(i);
+            int pointerIndex = event.findPointerIndex(pointerId);
+            Finger finger = new Finger();
+            finger.point =  new Point((int)event.getX(pointerIndex), (int)event.getY(pointerIndex));
+            finger.pointerId = pointerId;
+
+            mFingers.add(finger);
+        }
+        invalidate();
+        return true;
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        int radius = canvas.getWidth() / 20;
+        for (int i = 0; i < mFingers.size(); i++) {
+            Finger finger = mFingers.get(i);
+            Point point = finger.point;
+            int color = mColors[finger.pointerId % mColors.length];
+            mPaint.setColor(color);
+            canvas.drawCircle(point.x, point.y, radius, mPaint);
+        }
+    }
+
+    private class Finger {
+        public Point point;
+        public int pointerId;
+    }
+}
+
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/touch/TouchPresentation.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/touch/TouchPresentation.java
new file mode 100644
index 0000000..84834b5
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/touch/TouchPresentation.java
@@ -0,0 +1,45 @@
+/*
+ * 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 com.android.cts.verifier.projection.touch;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.view.Display;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.projection.ProjectedPresentation;
+
+/**
+ * Draw the TouchPointview to see if multitouch works in projected presentations
+ */
+public class TouchPresentation extends ProjectedPresentation {
+
+    /**
+     * @param outerContext
+     * @param display
+     */
+    public TouchPresentation(Context outerContext, Display display) {
+        super(outerContext, display);
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.pta_touch);
+    }
+
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/video/ProjectionVideoActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/video/ProjectionVideoActivity.java
new file mode 100644
index 0000000..7a32b27
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/video/ProjectionVideoActivity.java
@@ -0,0 +1,36 @@
+/*
+ * 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 com.android.cts.verifier.projection.video;
+
+import android.os.Bundle;
+import android.util.Log;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.projection.ProjectionActivity;
+import com.android.cts.verifier.projection.ProjectionPresentationType;
+
+public class ProjectionVideoActivity extends ProjectionActivity {
+    private static final String TAG = ProjectionVideoActivity.class.getSimpleName();
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Log.i(TAG, "onCreate");
+        setContentViewAndInfoResources(R.layout.pa_main, R.string.pva_test, R.string.pva_info);
+        mType = ProjectionPresentationType.VIDEO_PLAYBACK;
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/video/VideoPresentation.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/video/VideoPresentation.java
new file mode 100644
index 0000000..4275cb8
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/video/VideoPresentation.java
@@ -0,0 +1,60 @@
+/*
+ * 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 com.android.cts.verifier.projection.video;
+
+import android.content.Context;
+import android.media.MediaPlayer;
+import android.media.MediaPlayer.OnPreparedListener;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.Display;
+import android.view.View;
+import android.widget.VideoView;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.projection.ProjectedPresentation;
+
+/**
+ * Play a test video that determines if the video and audio are in sync in projected presentations
+ */
+public class VideoPresentation extends ProjectedPresentation {
+
+    /**
+     * @param outerContext
+     * @param display
+     */
+    public VideoPresentation(Context outerContext, Display display) {
+        super(outerContext, display);
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        View view = getLayoutInflater().inflate(R.layout.pva_video, null);
+        setContentView(view);
+        VideoView videoView = (VideoView) view.findViewById(R.id.video_view);
+        videoView.setOnPreparedListener(new OnPreparedListener() {
+            @Override
+            public void onPrepared(MediaPlayer mp) {
+                mp.setLooping(true);
+            }
+        });
+        String packageName = getContext().getPackageName();
+        Uri uri = Uri.parse("android.resource://" + packageName + "/" + R.raw.test_video);
+        videoView.setVideoURI(uri);
+        videoView.start();
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/widgets/ProjectionWidgetActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/widgets/ProjectionWidgetActivity.java
new file mode 100644
index 0000000..9b862de
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/widgets/ProjectionWidgetActivity.java
@@ -0,0 +1,79 @@
+/*
+ * 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 com.android.cts.verifier.projection.widgets;
+
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.projection.ProjectionActivity;
+import com.android.cts.verifier.projection.ProjectionPresentationType;
+
+public class ProjectionWidgetActivity extends ProjectionActivity {
+    private static final String TAG = ProjectionWidgetActivity.class.getSimpleName();
+
+    private class InjectDPadClickListener implements OnClickListener {
+        private int mKeyCode;
+
+        InjectDPadClickListener(int keyCode) {
+            mKeyCode = keyCode;
+        }
+
+        @Override
+        public void onClick(View view) {
+            if (mService != null) {
+                try {
+                    mService.onKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, mKeyCode));
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Error executing onKeyEvent", e);
+                }
+            }
+        }
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        View view = setContentViewAndInfoResources(R.layout.pwa_widgets, R.string.pwa_test,
+                R.string.pwa_info);
+
+        mType = ProjectionPresentationType.BASIC_WIDGETS;
+
+        Button button;
+        {
+            button = (Button) view.findViewById(R.id.up_button);
+            button.setOnClickListener(new InjectDPadClickListener(KeyEvent.KEYCODE_DPAD_UP));
+        }
+        {
+            button = (Button) view.findViewById(R.id.down_button);
+            button.setOnClickListener(new InjectDPadClickListener(KeyEvent.KEYCODE_DPAD_DOWN));
+        }
+        {
+            button = (Button) view.findViewById(R.id.right_button);
+            button.setOnClickListener(new InjectDPadClickListener(KeyEvent.KEYCODE_DPAD_RIGHT));
+        }
+        {
+            button = (Button) view.findViewById(R.id.left_button);
+            button.setOnClickListener(new InjectDPadClickListener(KeyEvent.KEYCODE_DPAD_LEFT));
+        }
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/widgets/WidgetPresentation.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/widgets/WidgetPresentation.java
new file mode 100644
index 0000000..8af2757
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/widgets/WidgetPresentation.java
@@ -0,0 +1,46 @@
+/*
+ * 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 com.android.cts.verifier.projection.widgets;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.view.Display;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.projection.ProjectedPresentation;
+import com.android.cts.verifier.projection.ProjectionPresentationType;
+
+/**
+ * Check if widgets display and that key focus works in projected mode
+ */
+public class WidgetPresentation extends ProjectedPresentation {
+
+    /**
+     * @param outerContext
+     * @param display
+     */
+    public WidgetPresentation(Context outerContext, Display display) {
+        super(outerContext, display);
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.pwa_buttons);
+    }
+
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/AccelerometerMeasurementTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/AccelerometerMeasurementTestActivity.java
index bcd00ed..dfcf120 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/AccelerometerMeasurementTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/AccelerometerMeasurementTestActivity.java
@@ -16,40 +16,58 @@
 
 package com.android.cts.verifier.sensors;
 
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.sensors.base.SensorCtsVerifierTestActivity;
+
 import android.hardware.Sensor;
 import android.hardware.SensorManager;
-import android.hardware.cts.helpers.sensorTestOperations.VerifyMeasurementsOperation;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.sensoroperations.TestSensorOperation;
+import android.hardware.cts.helpers.sensorverification.MeanVerification;
 
 import java.util.concurrent.TimeUnit;
 
 /**
  * Semi-automated test that focuses on characteristics associated with Accelerometer measurements.
  */
-public class AccelerometerMeasurementTestActivity extends BaseSensorSemiAutomatedTestActivity {
-    @Override
-    protected void onRun() throws Throwable {
-        verifyMeasurements(
-                "Place the device in a flat surface with the screen facing the ceiling",
+public class AccelerometerMeasurementTestActivity extends SensorCtsVerifierTestActivity {
+    public AccelerometerMeasurementTestActivity() {
+        super(AccelerometerMeasurementTestActivity.class);
+    }
+
+    public String testFaceUp() throws Throwable {
+        return verifyMeasurements(
+                R.string.snsr_accel_test_face_up,
                 0, 0, SensorManager.STANDARD_GRAVITY);
+    }
 
-        delayedVerifyMeasurements(
-                "Press 'Next' and place the device in a flat surface with the screen facing it",
+    public String testFaceDown() throws Throwable {
+        return delayedVerifyMeasurements(
+                R.string.snsr_accel_test_face_down,
                 0, 0, -SensorManager.STANDARD_GRAVITY);
+    }
 
-        verifyMeasurements(
-                "Place the device in a flat surface resting vertically on its right side",
+    public String testRightSide() throws Throwable {
+        return verifyMeasurements(
+                R.string.snsr_accel_test_right_side,
                 -SensorManager.STANDARD_GRAVITY, 0, 0);
+    }
 
-        verifyMeasurements(
-                "Place the device in a flat surface resting vertically on its left side",
+    public String testLeftSide() throws Throwable {
+        return verifyMeasurements(
+                R.string.snsr_accel_test_left_side,
                 SensorManager.STANDARD_GRAVITY, 0, 0);
+    }
 
-        verifyMeasurements(
-                "Place the device in a flat surface resting vertically on its top side",
+    public String testTopSide() throws Throwable {
+        return verifyMeasurements(
+                R.string.snsr_accel_test_top_side,
                 0, -SensorManager.STANDARD_GRAVITY, 0);
+    }
 
-        verifyMeasurements(
-                "Place the device in a flat surface resting vertically on its bottom side",
+    public String testBottomSide() throws Throwable {
+        return verifyMeasurements(
+                R.string.snsr_accel_test_bottom_side,
                 0, SensorManager.STANDARD_GRAVITY, 0);
     }
 
@@ -72,39 +90,43 @@
      * - the values representing the expectation of the test
      * - the mean of values sampled from the sensor
      */
-    private void verifyMeasurements(double ... expectations) throws Throwable {
+    private String verifyMeasurements(float ... expectations) throws Throwable {
         Thread.sleep(500 /*ms*/);
-        VerifyMeasurementsOperation verifyMeasurements = new VerifyMeasurementsOperation(
+        TestSensorEnvironment environment = new TestSensorEnvironment(
                 getApplicationContext(),
                 Sensor.TYPE_ACCELEROMETER,
-                SensorManager.SENSOR_DELAY_FASTEST,
-                0 /*reportLatencyInUs*/,
+                SensorManager.SENSOR_DELAY_FASTEST);
+        TestSensorOperation verifyMeasurements =
+                new TestSensorOperation(environment, 100 /* event count */);
+        verifyMeasurements.addVerification(new MeanVerification(
                 expectations,
-                1.95f /* m / s^2 */);
+                new float[]{1.95f, 1.95f, 1.95f} /* m / s^2 */));
         verifyMeasurements.execute();
-        logSuccess();
+        return null;
     }
 
-    private void delayedVerifyMeasurements(
-            String message,
-            double ... expectations) throws Throwable {
-        appendText(String.format("\n%s.", message));
-        appendText("A sound will be played once the verification is complete...");
-        waitForUser();
-        Thread.sleep(TimeUnit.MILLISECONDS.convert(10, TimeUnit.SECONDS));
+    private String delayedVerifyMeasurements(int descriptionResId, float ... expectations)
+            throws Throwable {
+        SensorTestLogger logger = getTestLogger();
+        logger.logInstructions(descriptionResId);
+        logger.logWaitForSound();
+        waitForUserToBegin();
+        Thread.sleep(TimeUnit.MILLISECONDS.convert(7, TimeUnit.SECONDS));
 
         try {
-            verifyMeasurements(expectations);
+            return verifyMeasurements(expectations);
         } finally {
             playSound();
         }
     }
 
-    private void verifyMeasurements(String message, double ... expectations) throws Throwable {
-        appendText(String.format("\n%s.", message));
-        appendText("Press 'Next' when ready and keep the device steady.");
-        waitForUser();
+    private String verifyMeasurements(int descriptionResId, float ... expectations)
+            throws Throwable {
+        SensorTestLogger logger = getTestLogger();
+        logger.logInstructions(descriptionResId);
+        logger.logInstructions(R.string.snsr_device_steady);
+        waitForUserToBegin();
 
-        verifyMeasurements(expectations);
+        return verifyMeasurements(expectations);
     }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/AccelerometerTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/AccelerometerTestActivity.java
index 193f37e..0d4f755e 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/AccelerometerTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/AccelerometerTestActivity.java
@@ -18,6 +18,7 @@
 
 import com.android.cts.verifier.PassFailButtons;
 import com.android.cts.verifier.R;
+import com.android.cts.verifier.sensors.renderers.GLArrowSensorTestRenderer;
 
 import android.content.Context;
 import android.hardware.Sensor;
@@ -30,7 +31,10 @@
  * CTS Verifier case for verifying correct integration of accelerometer.
  * Displays a wedge using OpenGL that, on a correctly-integrated device, always
  * points down.
+ *
+ * @deprecated It has been replaced by {@link AccelerometerMeasurementTestActivity}
  */
+@Deprecated
 public class AccelerometerTestActivity extends PassFailButtons.Activity {
     private GLSurfaceView mGLSurfaceView;
 
@@ -44,7 +48,8 @@
 
         mSensorManager = (SensorManager) getApplicationContext().getSystemService(
                 Context.SENSOR_SERVICE);
-        AccelerometerTestRenderer renderer = new AccelerometerTestRenderer(this);
+        GLArrowSensorTestRenderer renderer =
+                new GLArrowSensorTestRenderer(this, Sensor.TYPE_ACCELEROMETER);
         mListener = renderer;
 
         setContentView(R.layout.pass_fail_gl);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/AccelerometerTestRenderer.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/AccelerometerTestRenderer.java
deleted file mode 100644
index b6c3a6e..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/AccelerometerTestRenderer.java
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.verifier.sensors;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.FloatBuffer;
-import java.nio.ShortBuffer;
-
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.opengles.GL10;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-import android.opengl.GLSurfaceView;
-import android.opengl.GLU;
-import android.opengl.GLUtils;
-
-import com.android.cts.verifier.R;
-
-public class AccelerometerTestRenderer implements GLSurfaceView.Renderer, SensorEventListener {
-
-    /**
-     * A representation of a 3D triangular wedge or arrowhead shape, suitable
-     * for pointing a direction.
-     */
-    private static class Wedge {
-        private final static int VERTS = 6;
-
-        /**
-         * Storage for the vertices.
-         */
-        private FloatBuffer mFVertexBuffer;
-
-        /**
-         * Storage for the drawing sequence of the vertices. This contains
-         * integer indices into the mFVertextBuffer structure.
-         */
-        private ShortBuffer mIndexBuffer;
-
-        /**
-         * Storage for the texture used on the surface of the wedge.
-         */
-        private FloatBuffer mTexBuffer;
-
-        public Wedge() {
-            // Buffers to be passed to gl*Pointer() functions
-            // must be direct & use native ordering
-
-            ByteBuffer vbb = ByteBuffer.allocateDirect(VERTS * 6 * 4);
-            vbb.order(ByteOrder.nativeOrder());
-            mFVertexBuffer = vbb.asFloatBuffer();
-
-            ByteBuffer tbb = ByteBuffer.allocateDirect(VERTS * 2 * 4);
-            tbb.order(ByteOrder.nativeOrder());
-            mTexBuffer = tbb.asFloatBuffer();
-
-            ByteBuffer ibb = ByteBuffer.allocateDirect(VERTS * 8 * 2);
-            ibb.order(ByteOrder.nativeOrder());
-            mIndexBuffer = ibb.asShortBuffer();
-
-            /**
-             * Coordinates of the vertices making up a simple wedge. Six total
-             * vertices, representing two isosceles triangles, side by side,
-             * centered on the origin separated by 0.25 units, with elongated
-             * ends pointing down the negative Z axis.
-             */
-            float[] coords = {
-                    // X, Y, Z
-                    -0.125f, -0.25f, -0.25f,
-                    -0.125f,  0.25f, -0.25f,
-                    -0.125f,  0.0f,   0.559016994f,
-                     0.125f, -0.25f, -0.25f,
-                     0.125f,  0.25f, -0.25f,
-                     0.125f,  0.0f,   0.559016994f,
-            };
-
-            for (int i = 0; i < VERTS; i++) {
-                for (int j = 0; j < 3; j++) {
-                    mFVertexBuffer.put(coords[i * 3 + j] * 2.0f);
-                }
-            }
-
-            for (int i = 0; i < VERTS; i++) {
-                for (int j = 0; j < 2; j++) {
-                    mTexBuffer.put(coords[i * 3 + j] * 2.0f + 0.5f);
-                }
-            }
-
-            // left face
-            mIndexBuffer.put((short) 0);
-            mIndexBuffer.put((short) 1);
-            mIndexBuffer.put((short) 2);
-
-            // right face
-            mIndexBuffer.put((short) 5);
-            mIndexBuffer.put((short) 4);
-            mIndexBuffer.put((short) 3);
-
-            // top side, 2 triangles to make rect
-            mIndexBuffer.put((short) 2);
-            mIndexBuffer.put((short) 5);
-            mIndexBuffer.put((short) 3);
-            mIndexBuffer.put((short) 3);
-            mIndexBuffer.put((short) 0);
-            mIndexBuffer.put((short) 2);
-
-            // bottom side, 2 triangles to make rect
-            mIndexBuffer.put((short) 5);
-            mIndexBuffer.put((short) 2);
-            mIndexBuffer.put((short) 1);
-            mIndexBuffer.put((short) 1);
-            mIndexBuffer.put((short) 4);
-            mIndexBuffer.put((short) 5);
-
-            // base, 2 triangles to make rect
-            mIndexBuffer.put((short) 0);
-            mIndexBuffer.put((short) 3);
-            mIndexBuffer.put((short) 4);
-            mIndexBuffer.put((short) 4);
-            mIndexBuffer.put((short) 1);
-            mIndexBuffer.put((short) 0);
-
-            mFVertexBuffer.position(0);
-            mTexBuffer.position(0);
-            mIndexBuffer.position(0);
-        }
-
-        public void draw(GL10 gl) {
-            gl.glFrontFace(GL10.GL_CCW);
-            gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mFVertexBuffer);
-            gl.glEnable(GL10.GL_TEXTURE_2D);
-            gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTexBuffer);
-            gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 24, GL10.GL_UNSIGNED_SHORT, mIndexBuffer);
-        }
-    }
-
-    /**
-     * A representation of the Z-axis in vector form.
-     */
-    protected static final float[] Z_AXIS = new float[] {
-            0, 0, 1
-    };
-
-    /**
-     * Computes the cross product of two vectors, storing the resulting
-     * pseudovector in out. All arrays must be length 3 or more, and out is
-     * overwritten.
-     * 
-     * @param left the left operand of the cross product
-     * @param right the right operand of the cross product
-     * @param out the array into which to store the cross-product pseudovector's
-     *            data
-     */
-    public static void crossProduct(float[] left, float[] right, float[] out) {
-        out[0] = left[1] * right[2] - left[2] * right[1];
-        out[1] = left[2] * right[0] - left[0] * right[2];
-        out[2] = left[0] * right[1] - left[1] * right[0];
-    }
-
-    /**
-     * Computes the dot product of two vectors.
-     * 
-     * @param left the first dot product operand
-     * @param right the second dot product operand
-     * @return the dot product of left and right
-     */
-    public static float dotProduct(float[] left, float[] right) {
-        return left[0] * right[0] + left[1] * right[1] + left[2] * right[2];
-    }
-
-    /**
-     * Normalizes the input vector into a unit vector.
-     * 
-     * @param vector the vector to normalize. Contents are overwritten.
-     */
-    public static void normalize(float[] vector) {
-        double mag = Math.sqrt(vector[0] * vector[0] + vector[1] * vector[1] + vector[2]
-                * vector[2]);
-        vector[0] /= mag;
-        vector[1] /= mag;
-        vector[2] /= mag;
-    }
-
-    /**
-     * The angle around mCrossProd to rotate to align Z-axis with gravity.
-     */
-    protected float mAngle;
-
-    private Context mContext;
-
-    /**
-     * The (pseudo)vector around which to rotate to align Z-axis with gravity.
-     */
-    protected float[] mCrossProd = new float[3];
-
-    private int mTextureID;
-
-    private Wedge mWedge;
-
-    /**
-     * It's a constructor. Can you dig it?
-     * 
-     * @param context the Android Context that owns this renderer
-     */
-    public AccelerometerTestRenderer(Context context) {
-        mContext = context;
-        mWedge = new Wedge();
-    }
-
-    public void onAccuracyChanged(Sensor arg0, int arg1) {
-        // no-op
-    }
-
-    /**
-     * Actually draws the wedge.
-     */
-    public void onDrawFrame(GL10 gl) {
-        // set up the texture for drawing
-        gl.glTexEnvx(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_MODULATE);
-        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
-        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
-        gl.glActiveTexture(GL10.GL_TEXTURE0);
-        gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
-        gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
-        gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
-
-        // clear the screen and draw
-        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
-        gl.glMatrixMode(GL10.GL_MODELVIEW);
-        gl.glLoadIdentity();
-        gl.glRotatef(-mAngle * 180 / (float) Math.PI, mCrossProd[0], mCrossProd[1], mCrossProd[2]);
-        mWedge.draw(gl);
-    }
-
-    public void onSensorChanged(SensorEvent event) {
-        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
-            /*
-             * For this test we want *only* accelerometer data, so we can't use
-             * the convenience methods on SensorManager; so compute manually.
-             */
-            normalize(event.values);
-
-            /*
-             * Because we need to invert gravity (because the accelerometer vector
-             * actually points up), that constitutes a 180-degree rotation around X,
-             * which means we need to invert Y.
-             */
-            event.values[1] *= -1;
-
-            crossProduct(event.values, Z_AXIS, mCrossProd);
-            mAngle = (float) Math.acos(dotProduct(event.values, Z_AXIS));
-        }
-    }
-
-    public void onSurfaceChanged(GL10 gl, int w, int h) {
-        gl.glViewport(0, 0, w, h);
-        float ratio = (float) w / h;
-        gl.glMatrixMode(GL10.GL_PROJECTION);
-        gl.glLoadIdentity();
-        gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7);
-        GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
-    }
-
-    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
-        // set up general OpenGL config
-        gl.glClearColor(0.6f, 0f, 0.4f, 1); // a nice purpley magenta
-        gl.glShadeModel(GL10.GL_SMOOTH);
-        gl.glEnable(GL10.GL_DEPTH_TEST);
-        gl.glEnable(GL10.GL_TEXTURE_2D);
-
-        // create the texture we use on the wedge
-        int[] textures = new int[1];
-        gl.glGenTextures(1, textures, 0);
-        mTextureID = textures[0];
-        
-        gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
-        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
-        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
-        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
-        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
-        gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_REPLACE);
-
-        InputStream is = mContext.getResources().openRawResource(R.raw.sns_texture);
-        Bitmap bitmap;
-        try {
-            bitmap = BitmapFactory.decodeStream(is);
-        } finally {
-            try {
-                is.close();
-            } catch (IOException e) {
-                // Ignore.
-            }
-        }
-
-        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
-        bitmap.recycle();
-    }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/BaseSensorSemiAutomatedTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/BaseSensorSemiAutomatedTestActivity.java
deleted file mode 100644
index c634e16..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/BaseSensorSemiAutomatedTestActivity.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.verifier.sensors;
-
-import android.app.Activity;
-import android.graphics.Color;
-import android.hardware.cts.helpers.SensorNotSupportedException;
-import android.media.MediaPlayer;
-import android.os.Bundle;
-import android.provider.Settings;
-import android.text.Spannable;
-import android.text.SpannableStringBuilder;
-import android.text.method.ScrollingMovementMethod;
-import android.text.style.ForegroundColorSpan;
-import android.view.View;
-import android.widget.TextView;
-
-import com.android.cts.verifier.R;
-import com.android.cts.verifier.TestResult;
-
-import java.security.InvalidParameterException;
-import java.util.concurrent.Semaphore;
-
-/**
- * Base class to author Sensor semi-automated test cases.
- * These tests can only wait for operators to notify at some intervals, but the test needs to be
- * autonomous to verify the data collected.
- */
-public abstract class BaseSensorSemiAutomatedTestActivity
-        extends Activity
-        implements View.OnClickListener, Runnable {
-    protected final String LOG_TAG = "TestRunner";
-
-    private final Semaphore mSemaphore = new Semaphore(0);
-
-    private TextView mLogView;
-    private View mNextView;
-    private Thread mWorkerThread;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.snsr_semi_auto_test);
-    }
-
-    @Override
-    public void onStart() {
-        super.onStart();
-
-        mLogView = (TextView) this.findViewById(R.id.log_text);
-        mNextView = this.findViewById(R.id.next_button);
-        mNextView.setOnClickListener(this);
-        mLogView.setMovementMethod(new ScrollingMovementMethod());
-
-        updateButton(false /*enabled*/);
-        mWorkerThread = new Thread(this);
-        mWorkerThread.start();
-    }
-
-    @Override
-    public void onClick(View target) {
-        mSemaphore.release();
-    }
-
-    @Override
-    public void run() {
-        String message = "";
-        SensorTestResult testResult = SensorTestResult.PASS;
-        try {
-            onRun();
-        } catch(SensorNotSupportedException e) {
-            // the sensor is not supported/available in the device, log a warning and skip the test
-            testResult = SensorTestResult.SKIPPED;
-            message = e.getMessage();
-        } catch(Throwable e) {
-            testResult = SensorTestResult.FAIL;
-            message = e.getMessage();
-        }
-        setTestResult(testResult, message);
-        appendText("\nTest completed. Press 'Next' to finish.\n");
-        waitForUser();
-        finish();
-    }
-
-    /**
-     * This is the method that subclasses will implement to define the operations that need to be
-     * verified.
-     * Any exception thrown will cause the test to fail, additionally mAssert can be used to verify
-     * the tests state.
-     *
-     * throws Throwable
-     */
-    protected abstract void onRun() throws Throwable;
-
-    /**
-     * Helper methods for subclasses to interact with the UI and the operator.
-     */
-    protected void appendText(String text, int textColor) {
-        this.runOnUiThread(new TextAppender(mLogView, text, textColor));
-    }
-
-    protected void appendText(String text) {
-        this.runOnUiThread(new TextAppender(mLogView, text));
-    }
-
-    protected void clearText() {
-        this.runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mLogView.setText("");
-            }
-        });
-    }
-
-    protected void updateButton(boolean enabled) {
-        this.runOnUiThread(new ButtonEnabler(this.mNextView, enabled));
-    }
-
-    protected void waitForUser() {
-        updateButton(true);
-        try {
-            mSemaphore.acquire();
-        } catch(InterruptedException e) {}
-        updateButton(false);
-    }
-
-    protected void logSuccess() {
-        appendText("PASS", Color.GREEN);
-    }
-
-    protected void playSound() {
-        MediaPlayer player = MediaPlayer.create(this, Settings.System.DEFAULT_NOTIFICATION_URI);
-        player.start();
-        try {
-            Thread.sleep(500);
-        } catch(InterruptedException e) {
-        } finally {
-            player.stop();
-        }
-    }
-
-    /**
-     * Private methods.
-     */
-    private String getTestId() {
-        return this.getClass().getName();
-    }
-
-    private void setTestResult(SensorTestResult testResult, String message) {
-        int textColor;
-        switch(testResult) {
-            case SKIPPED:
-                textColor = Color.YELLOW;
-                TestResult.setPassedResult(this, this.getTestId(), message);
-                break;
-            case PASS:
-                textColor = Color.GREEN;
-                TestResult.setPassedResult(this, this.getTestId(), message);
-                break;
-            case FAIL:
-                textColor = Color.RED;
-                TestResult.setFailedResult(this, this.getTestId(), message);
-                break;
-            default:
-                throw new InvalidParameterException("Unrecognized testResult.");
-        }
-        appendText(message, textColor);
-    }
-
-    private enum SensorTestResult {
-        SKIPPED,
-        PASS,
-        FAIL
-    }
-
-    private class TextAppender implements Runnable {
-        private final TextView mTextView;
-        private final SpannableStringBuilder mMessageBuilder;
-
-        public TextAppender(TextView textView, String message, int textColor) {
-            mTextView = textView;
-            mMessageBuilder = new SpannableStringBuilder(message + "\n");
-
-            ForegroundColorSpan colorSpan = new ForegroundColorSpan(textColor);
-            mMessageBuilder.setSpan(
-                    colorSpan,
-                    0 /*start*/,
-                    message.length(),
-                    Spannable.SPAN_INCLUSIVE_INCLUSIVE);
-        }
-
-        public TextAppender(TextView textView, String message) {
-            this(textView, message, textView.getCurrentTextColor());
-        }
-
-        @Override
-        public void run() {
-            mTextView.append(mMessageBuilder);
-        }
-    }
-
-    private class ButtonEnabler implements Runnable {
-        private final View mButtonView;
-        private final boolean mButtonEnabled;
-
-        public ButtonEnabler(View buttonView, boolean buttonEnabled) {
-            mButtonView = buttonView;
-            mButtonEnabled = buttonEnabled;
-        }
-
-        @Override
-        public void run() {
-            mButtonView.setEnabled(mButtonEnabled);
-        }
-    }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/BatchingTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/BatchingTestActivity.java
new file mode 100644
index 0000000..6f0a7aa
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/BatchingTestActivity.java
@@ -0,0 +1,159 @@
+/*
+ * 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 com.android.cts.verifier.sensors;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.sensors.base.SensorCtsVerifierTestActivity;
+
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.sensoroperations.TestSensorFlushOperation;
+import android.hardware.cts.helpers.sensoroperations.TestSensorOperation;
+import android.hardware.cts.helpers.sensoroperations.VerifiableSensorOperation;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Activity that verifies batching capabilities for sensors
+ * (https://source.android.com/devices/sensors/batching.html).
+ *
+ * If a sensor supports the batching mode, FifoReservedEventCount for that sensor should be greater
+ * than one.
+ */
+public class BatchingTestActivity extends SensorCtsVerifierTestActivity {
+    public BatchingTestActivity() {
+        super(BatchingTestActivity.class);
+    }
+
+    private static final int SENSOR_BATCHING_RATE_US = SensorManager.SENSOR_DELAY_FASTEST;
+    private static final int REPORT_LATENCY_10_SEC = 10;
+    private static final int BATCHING_PADDING_TIME_S = 2;
+
+    // we are testing sensors that only trigger based on external events, so leave enough time for
+    // such events to generate
+    private static final int REPORT_LATENCY_25_SEC = 25;
+
+    // TODO: refactor to discover all available sensors of each type and dynamically generate test
+    // cases for all of them
+    @SuppressWarnings("unused")
+    public String testStepCounter_batching() throws Throwable {
+        return runBatchTest(
+                Sensor.TYPE_STEP_COUNTER,
+                REPORT_LATENCY_25_SEC,
+                R.string.snsr_batching_walking_needed);
+    }
+
+    @SuppressWarnings("unused")
+    public String testStepCounter_flush() throws Throwable {
+        return runFlushTest(
+                Sensor.TYPE_STEP_COUNTER,
+                REPORT_LATENCY_25_SEC,
+                R.string.snsr_batching_walking_needed);
+    }
+
+    @SuppressWarnings("unused")
+    public String testStepDetector_batching() throws Throwable {
+        return  runBatchTest(
+                Sensor.TYPE_STEP_DETECTOR,
+                REPORT_LATENCY_25_SEC,
+                R.string.snsr_batching_walking_needed);
+    }
+
+    @SuppressWarnings("unused")
+    public String testStepDetector_flush() throws Throwable {
+        return  runFlushTest(
+                Sensor.TYPE_STEP_DETECTOR,
+                REPORT_LATENCY_25_SEC,
+                R.string.snsr_batching_walking_needed);
+    }
+
+    @SuppressWarnings("unused")
+    public String testProximity_batching() throws Throwable {
+        return runBatchTest(
+                Sensor.TYPE_PROXIMITY,
+                REPORT_LATENCY_10_SEC,
+                R.string.snsr_interaction_needed);
+    }
+
+    @SuppressWarnings("unused")
+    public String testProximity_flush() throws Throwable {
+        return runFlushTest(
+                Sensor.TYPE_PROXIMITY,
+                REPORT_LATENCY_10_SEC,
+                R.string.snsr_interaction_needed);
+    }
+
+    @SuppressWarnings("unused")
+    public String testLight_batching() throws Throwable {
+        return runBatchTest(
+                Sensor.TYPE_LIGHT,
+                REPORT_LATENCY_10_SEC,
+                R.string.snsr_interaction_needed);
+    }
+
+    @SuppressWarnings("unused")
+    public String testLight_flush() throws Throwable {
+        return runFlushTest(
+                Sensor.TYPE_LIGHT,
+                REPORT_LATENCY_10_SEC,
+                R.string.snsr_interaction_needed);
+    }
+
+    private String runBatchTest(int sensorType, int maxBatchReportLatencySec, int instructionsResId)
+            throws Throwable {
+        getTestLogger().logInstructions(instructionsResId);
+        waitForUserToBegin();
+
+        int maxBatchReportLatencyUs = (int) TimeUnit.SECONDS.toMicros(maxBatchReportLatencySec);
+        TestSensorEnvironment environment = new TestSensorEnvironment(
+                getApplicationContext(),
+                sensorType,
+                SENSOR_BATCHING_RATE_US,
+                maxBatchReportLatencyUs);
+
+        int testDurationSec = maxBatchReportLatencySec + BATCHING_PADDING_TIME_S;
+        TestSensorOperation operation =
+                new TestSensorOperation(environment, testDurationSec,TimeUnit.SECONDS);
+        return executeTest(operation);
+    }
+
+    private String runFlushTest(int sensorType, int maxBatchReportLatencySec, int instructionsResId)
+            throws Throwable {
+        getTestLogger().logInstructions(instructionsResId);
+        waitForUserToBegin();
+
+        int maxBatchReportLatencyUs = (int) TimeUnit.SECONDS.toMicros(maxBatchReportLatencySec);
+        TestSensorEnvironment environment = new TestSensorEnvironment(
+                getApplicationContext(),
+                sensorType,
+                SENSOR_BATCHING_RATE_US,
+                maxBatchReportLatencyUs);
+
+        int flushDurationSec = maxBatchReportLatencySec / 2;
+        TestSensorFlushOperation operation =
+                new TestSensorFlushOperation(environment, flushDurationSec, TimeUnit.SECONDS);
+        return executeTest(operation);
+    }
+
+    private String executeTest(VerifiableSensorOperation operation) throws InterruptedException {
+        operation.addDefaultVerifications();
+        operation.setLogEvents(true);
+        operation.execute();
+        return null;
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/GyroscopeMeasurementTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/GyroscopeMeasurementTestActivity.java
index 4bcdd56..4b2a7f4 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/GyroscopeMeasurementTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/GyroscopeMeasurementTestActivity.java
@@ -16,93 +16,201 @@
 
 package com.android.cts.verifier.sensors;
 
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.sensors.base.SensorCtsVerifierTestActivity;
+import com.android.cts.verifier.sensors.renderers.GLRotationGuideRenderer;
+
 import android.hardware.Sensor;
 import android.hardware.SensorManager;
-import android.hardware.cts.helpers.sensorTestOperations.VerifySignumOperation;
+import android.hardware.cts.helpers.SensorCalibratedUncalibratedVerifier;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.sensoroperations.TestSensorOperation;
+import android.hardware.cts.helpers.sensorverification.GyroscopeIntegrationVerification;
+
+import java.util.concurrent.TimeUnit;
 
 /**
- * Semi-automated test that focuses on characteristics associated with Accelerometer measurements.
+ * Semi-automated test that focuses on characteristics associated with Gyroscope measurements.
  */
-public class GyroscopeMeasurementTestActivity extends BaseSensorSemiAutomatedTestActivity {
+public class GyroscopeMeasurementTestActivity extends SensorCtsVerifierTestActivity {
+    private static final float THRESHOLD_CALIBRATED_UNCALIBRATED_RAD_SEC = 0.01f;
+    private static final float THRESHOLD_AXIS_UNDER_ROTATION_DEG = 10.0f;
+    private static final float THRESHOLD_AXIS_UNDER_NO_ROTATION_DEG = 50.0f;
+
+    private static final int ROTATE_360_DEG = 360;
+    private static final int ROTATION_COLLECTION_SEC = 10;
+
+    private static final int X_AXIS = 0;
+    private static final int Y_AXIS = 1;
+    private static final int Z_AXIS = 2;
+
+    private final GLRotationGuideRenderer mRenderer = new GLRotationGuideRenderer();
+
+    public GyroscopeMeasurementTestActivity() {
+        super(GyroscopeMeasurementTestActivity.class);
+    }
+
     @Override
-    protected void onRun() throws Throwable {
-        appendText("Place the device in a flat surface with the screen facing the ceiling, make "
-                + "sure the device aligns with the orientation specified for each scenario. Then "
-                + "follow the instructions for each scenario:");
+    protected void activitySetUp() throws InterruptedException {
+        getTestLogger().logInstructions(R.string.snsr_gyro_device_placement);
+        waitForUserToContinue();
+        initializeGlSurfaceView(mRenderer);
+    }
 
-        verifyMeasurements(
-                "leave the device static",
-                true /*portrait*/,
-                0, 0, 0);
+    @Override
+    protected void activityCleanUp() {
+        closeGlSurfaceView();
+    }
 
-        verifyMeasurements(
-                "rotate the device clockwise",
-                true /*portrait*/,
-                0, 0, -1);
+    @SuppressWarnings("unused")
+    public String testDeviceStatic() throws Throwable {
+        return verifyMeasurements(
+                R.string.snsr_gyro_device_static,
+                -1 /* rotationAxis */,
+                0 /* expectationDeg */);
+    }
 
-        verifyMeasurements(
-                "rotate the device counter-clockwise",
-                true /*portrait*/,
-                0, 0, +1);
+    @SuppressWarnings("unused")
+    public String testRotateClockwise() throws Throwable {
+        return verifyMeasurements(R.string.snsr_gyro_rotate_device, Z_AXIS, -ROTATE_360_DEG);
+    }
 
-        verifyMeasurements(
-                "rotate the device on its right until it stands on its side",
-                true /*portrait*/,
-                0, +1, 0);
+    @SuppressWarnings("unused")
+    public String testRotateCounterClockwise() throws Throwable {
+        return verifyMeasurements(R.string.snsr_gyro_rotate_device, Z_AXIS, ROTATE_360_DEG);
+    }
 
-        verifyMeasurements(
-                "rotate the device on its left until it stands on its side",
-                true /*portrait*/,
-                0, -1, 0);
+    @SuppressWarnings("unused")
+    public String testRotateRightSide() throws Throwable {
+        return verifyMeasurements(R.string.snsr_gyro_rotate_device, Y_AXIS, ROTATE_360_DEG);
+    }
 
-        verifyMeasurements(
-                "rotate the device on its top until it stands perpendicular",
-                false /*portrait*/,
-                -1, 0, 0);
+    @SuppressWarnings("unused")
+    public String testRotateLeftSide() throws Throwable {
+        return verifyMeasurements(R.string.snsr_gyro_rotate_device, Y_AXIS, -ROTATE_360_DEG);
+    }
 
-        verifyMeasurements(
-                "rotate the device on its bottom until it stands perpendicular",
-                false /*portrait*/,
-                +1, 0, 0);
+    @SuppressWarnings("unused")
+    public String testRotateTopSide() throws Throwable {
+        return verifyMeasurements(R.string.snsr_gyro_rotate_device, X_AXIS, -ROTATE_360_DEG);
+    }
+
+    @SuppressWarnings("unused")
+    public String testRotateBottomSide() throws Throwable {
+        return verifyMeasurements(R.string.snsr_gyro_rotate_device, X_AXIS, ROTATE_360_DEG);
     }
 
     /**
-     * This test verifies that the Gyroscope measures angular speeds with the right direction.
-     * The test does not measure the range or scale, apart from filtering small readings that
-     * deviate from zero.
-     *
-     * The test takes a set of samples from the sensor under test and calculates the mean of each
-     * axis that the sensor data collects. It then compares it against the test expectations that
-     * are represented by signed values. It verifies that the readings have the right direction.
-
-     * The reference values are coupled to the orientation of the device. The test is susceptible to
-     * errors when the device is not oriented properly, the device has moved to slowly, or it has
-     * moved in more than the direction conducted.
-     *
-     * The error message associated with the test provides the required data needed to identify any
-     * possible issue. It provides:
-     * - the thread id on which the failure occurred
-     * - the sensor type and sensor handle that caused the failure
-     * - the values representing the expectation of the test
-     * - the mean of values sampled from the sensor
+     * Verifies that the relationship between readings from calibrated and their corresponding
+     * uncalibrated sensors comply to the following equation:
+     *      calibrated = uncalibrated - bias
      */
-    private void verifyMeasurements(
-            String scenarioInstructions,
-            boolean usePortraitOrientation,
-            int ... expectations) throws Throwable {
-        final String orientation = usePortraitOrientation ? "Portrait": "Landscape";
-        appendText(String.format("\n[Device orientation]: %s", orientation));
-        appendText(String.format("Press 'Next' and %s.", scenarioInstructions));
-        waitForUser();
+    @SuppressWarnings("unused")
+    public String testCalibratedAndUncalibrated() throws Throwable {
+        setRendererRotation(Z_AXIS, false);
 
-        Thread.sleep(500 /*ms*/);
-        VerifySignumOperation verifySignum = new VerifySignumOperation(
+        SensorTestLogger logger = getTestLogger();
+        logger.logInstructions(R.string.snsr_keep_device_rotating_clockwise);
+        waitForUserToBegin();
+        logger.logWaitForSound();
+
+        TestSensorEnvironment calibratedEnvironment = new TestSensorEnvironment(
                 getApplicationContext(),
                 Sensor.TYPE_GYROSCOPE,
-                SensorManager.SENSOR_DELAY_FASTEST,
-                expectations,
-                0.2 /*noiseThreshold*/);
-        verifySignum.execute();
-        logSuccess();
+                SensorManager.SENSOR_DELAY_FASTEST);
+        TestSensorEnvironment uncalibratedEnvironment = new TestSensorEnvironment(
+                getApplicationContext(),
+                Sensor.TYPE_GYROSCOPE_UNCALIBRATED,
+                SensorManager.SENSOR_DELAY_FASTEST);
+        SensorCalibratedUncalibratedVerifier verifier = new SensorCalibratedUncalibratedVerifier(
+                calibratedEnvironment,
+                uncalibratedEnvironment,
+                THRESHOLD_CALIBRATED_UNCALIBRATED_RAD_SEC);
+
+        try {
+            verifier.execute();
+        } finally {
+            playSound();
+        }
+        return null;
+    }
+
+    /**
+     * This test verifies that the Gyroscope measures the appropriate angular position.
+     *
+     * The test takes a set of samples from the sensor under test and calculates the angular
+     * position for each axis that the sensor data collects. It then compares it against the test
+     * expectations that are represented by signed values. It verifies that the readings have the
+     * right magnitude.
+     */
+    private String verifyMeasurements(int instructionsResId, int rotationAxis, int expectationDeg)
+            throws Throwable {
+        setRendererRotation(rotationAxis, expectationDeg >= 0);
+
+        SensorTestLogger logger = getTestLogger();
+        logger.logInstructions(instructionsResId);
+        waitForUserToBegin();
+        logger.logWaitForSound();
+
+        TestSensorEnvironment environment = new TestSensorEnvironment(
+                getApplicationContext(),
+                Sensor.TYPE_GYROSCOPE,
+                SensorManager.SENSOR_DELAY_FASTEST);
+        TestSensorOperation sensorOperation =
+                new TestSensorOperation(environment, ROTATION_COLLECTION_SEC, TimeUnit.SECONDS);
+
+        int gyroscopeAxes = environment.getSensorAxesCount();
+        int[] expectationsDeg = getExpectationsDeg(gyroscopeAxes, rotationAxis, expectationDeg);
+        float[] thresholdsDeg = getThresholdsDeg(gyroscopeAxes, rotationAxis);
+        GyroscopeIntegrationVerification integrationVerification =
+                new GyroscopeIntegrationVerification(expectationsDeg, thresholdsDeg);
+        sensorOperation.addVerification(integrationVerification);
+
+        try {
+            sensorOperation.execute();
+        } finally {
+            playSound();
+        }
+        return null;
+    }
+
+    private int[] getExpectationsDeg(int axes, int rotationAxis, int expectationDeg) {
+        int[] expectationsDeg = new int[axes];
+        for (int i = 0; i < axes; ++i) {
+            // tests assume that rotation is expected on one axis at a time
+            expectationsDeg[i] = (i == rotationAxis) ? expectationDeg : 0;
+        }
+        return expectationsDeg;
+    }
+
+    private float[] getThresholdsDeg(int axes, int rotationAxis) {
+        float[] thresholdsDeg = new float[axes];
+        for (int i = 0; i < axes; ++i) {
+            // tests set a high threshold on the axes where rotation is not expected, to account
+            // for movement from the operator
+            // the rotation axis has a lower threshold to ensure the gyroscope's accuracy
+            thresholdsDeg[i] = (i == rotationAxis)
+                    ? THRESHOLD_AXIS_UNDER_ROTATION_DEG
+                    : THRESHOLD_AXIS_UNDER_NO_ROTATION_DEG;
+        }
+        return thresholdsDeg;
+    }
+
+    private void setRendererRotation(int rotationAxis, boolean positiveRotation) {
+        int axis1 = 0;
+        int axis2 = 0;
+        int axis3 = 0;
+        switch (rotationAxis) {
+            case X_AXIS:
+                axis1 = positiveRotation ? 1 : -1;
+                break;
+            case Y_AXIS:
+                axis2 = positiveRotation ? 1 : -1;
+                break;
+            case Z_AXIS:
+                axis3 = positiveRotation ? 1 : -1;
+                break;
+        }
+        mRenderer.setRotation(axis1, axis2, axis3);
     }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/GyroscopeTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/GyroscopeTestActivity.java
index ea6ca4c..f886e75 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/GyroscopeTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/GyroscopeTestActivity.java
@@ -18,6 +18,7 @@
 
 import com.android.cts.verifier.PassFailButtons;
 import com.android.cts.verifier.R;
+import com.android.cts.verifier.sensors.renderers.GLRotationGuideRenderer;
 
 import android.app.AlertDialog;
 import android.content.Intent;
@@ -26,41 +27,29 @@
 import android.hardware.SensorEventListener;
 import android.hardware.SensorManager;
 import android.opengl.GLSurfaceView;
-import android.opengl.GLU;
 import android.os.Bundle;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.TextView;
 
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.FloatBuffer;
-import java.nio.ShortBuffer;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.opengles.GL10;
-
 /**
  * Manual test for testing the gyroscope sensor. This test consists of 6 steps for all the
  * different ways to rotate the device along the x, y, and z axis. It also raises a warning
  * if the values seem to high and may be degrees.
+ *
+ * @deprecated It has been replaced by {@link GyroscopeMeasurementTestActivity}
  */
+@Deprecated
 public class GyroscopeTestActivity extends PassFailButtons.Activity {
 
     private static final int NUM_STAGES = 6;
     private static final String STAGE_INDEX_EXTRA = "stageIndex";
 
-    private static final int BACKGROUND_BLACK = 0;
-    private static final int BACKGROUND_RED = 1;
-    private static final int BACKGROUND_GREEN = 2;
-
-    private AtomicInteger mBackgroundColor = new AtomicInteger(BACKGROUND_BLACK);
-
     private SensorManager mSensorManager;
     private Sensor mSensor;
     private SensorListener mSensorListener;
     private GLSurfaceView mGLSurfaceView;
+    private GLRotationGuideRenderer mRenderer;
     private TextView mProgressText;
     private TextView mSensorText;
 
@@ -89,8 +78,9 @@
                 settings.mExpectPositiveValue);
 
         mGLSurfaceView = (GLSurfaceView) findViewById(R.id.gl_surface_view);
-        mGLSurfaceView.setRenderer(new RotationGuideRenderer(settings.mRotateX, settings.mRotateY,
-                settings.mRotateZ));
+        mRenderer = new GLRotationGuideRenderer();
+        mRenderer.setRotation(settings.mRotateX, settings.mRotateY, settings.mRotateZ);
+        mGLSurfaceView.setRenderer(mRenderer);
 
         mProgressText = (TextView) findViewById(R.id.progress);
         mProgressText.setText(String.format(getString(R.string.snsr_gyro_test_progress),
@@ -169,168 +159,6 @@
         mSensorManager.unregisterListener(mSensorListener, mSensor);
     }
 
-    /** Renders a spinning block to indicate how the device should be rotated in the test. */
-    class RotationGuideRenderer implements GLSurfaceView.Renderer {
-
-        private static final double ANGLE_INCREMENT = 1.0;
-
-        private final Monolith mMonolith = new Monolith();
-
-        private float mAngle = 0.0f;
-
-        private float mRotateX;
-
-        private float mRotateY;
-
-        private float mRotateZ;
-
-        public RotationGuideRenderer(float rotateX, float rotateY, float rotateZ) {
-            mRotateX = rotateX;
-            mRotateY = rotateY;
-            mRotateZ = rotateZ;
-        }
-
-        @Override
-        public void onDrawFrame(GL10 gl) {
-            clearBackground(gl);
-            gl.glMatrixMode(GL10.GL_MODELVIEW);
-            gl.glLoadIdentity();
-            gl.glRotatef(mAngle, mRotateX, mRotateY, mRotateZ);
-            mMonolith.draw(gl);
-            mAngle += ANGLE_INCREMENT;
-        }
-
-        private void clearBackground(GL10 gl) {
-            switch (mBackgroundColor.get()) {
-                case BACKGROUND_GREEN:
-                    gl.glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
-                    break;
-
-                case BACKGROUND_RED:
-                    gl.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
-                    break;
-
-                default:
-                    gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
-                    break;
-            }
-            gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
-        }
-
-        @Override
-        public void onSurfaceChanged(GL10 gl, int width, int height) {
-            gl.glViewport(0, 0, width, height);
-            gl.glMatrixMode(GL10.GL_PROJECTION);
-            gl.glLoadIdentity();
-            float ratio = (float) width / height;
-            gl.glFrustumf(-ratio, ratio, -1, 1, 3, 15);
-            GLU.gluLookAt(gl, 0, 0, 10, 0, 0, 0, 0, 1, 0);
-        }
-
-        @Override
-        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
-            gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
-            gl.glEnable(GL10.GL_LIGHTING);
-            gl.glEnable(GL10.GL_LIGHT0);
-            gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, new float[] {0.75f, 0.75f, 0.75f, 1f}, 0);
-        }
-    }
-
-    /** Rectangular block that is rotated by {@link RotationGuideRenderer}. */
-    class Monolith {
-
-        private static final int NUM_VERTICES = 8;
-
-        private static final int NUM_INDICES = 36;
-
-        private FloatBuffer mVertexBuffer;
-
-        private ShortBuffer mIndexBuffer;
-
-        public Monolith() {
-            mVertexBuffer = ByteBuffer.allocateDirect(NUM_VERTICES * 3 * 4)
-                    .order(ByteOrder.nativeOrder())
-                    .asFloatBuffer();
-
-            float[] coordinates = {
-                    -0.65f, -1, 0.2f,
-                    -0.65f, 1, 0.2f,
-                    0.65f, 1, 0.2f,
-                    0.65f, -1, 0.2f,
-
-                    -0.65f, -1, -0.2f,
-                    -0.65f, 1, -0.2f,
-                    0.65f, 1, -0.2f,
-                    0.65f, -1, -0.2f,
-            };
-
-            for (int i = 0; i < coordinates.length; i++) {
-                mVertexBuffer.put(coordinates[i]);
-            }
-
-            mIndexBuffer = ByteBuffer.allocateDirect(NUM_INDICES * 2)
-                    .order(ByteOrder.nativeOrder())
-                    .asShortBuffer();
-
-            // Front
-            mIndexBuffer.put((short) 0);
-            mIndexBuffer.put((short) 1);
-            mIndexBuffer.put((short) 2);
-            mIndexBuffer.put((short) 0);
-            mIndexBuffer.put((short) 2);
-            mIndexBuffer.put((short) 3);
-
-            // Back
-            mIndexBuffer.put((short) 7);
-            mIndexBuffer.put((short) 6);
-            mIndexBuffer.put((short) 5);
-            mIndexBuffer.put((short) 7);
-            mIndexBuffer.put((short) 5);
-            mIndexBuffer.put((short) 4);
-
-            // Right
-            mIndexBuffer.put((short) 3);
-            mIndexBuffer.put((short) 2);
-            mIndexBuffer.put((short) 6);
-            mIndexBuffer.put((short) 3);
-            mIndexBuffer.put((short) 6);
-            mIndexBuffer.put((short) 7);
-
-            // Left
-            mIndexBuffer.put((short) 4);
-            mIndexBuffer.put((short) 5);
-            mIndexBuffer.put((short) 1);
-            mIndexBuffer.put((short) 4);
-            mIndexBuffer.put((short) 1);
-            mIndexBuffer.put((short) 0);
-
-            // Top
-            mIndexBuffer.put((short) 1);
-            mIndexBuffer.put((short) 5);
-            mIndexBuffer.put((short) 6);
-            mIndexBuffer.put((short) 1);
-            mIndexBuffer.put((short) 6);
-            mIndexBuffer.put((short) 2);
-
-            // Bottom
-            mIndexBuffer.put((short) 3);
-            mIndexBuffer.put((short) 7);
-            mIndexBuffer.put((short) 4);
-            mIndexBuffer.put((short) 3);
-            mIndexBuffer.put((short) 4);
-            mIndexBuffer.put((short) 0);
-
-            mVertexBuffer.position(0);
-            mIndexBuffer.position(0);
-        }
-
-        public void draw(GL10 gl) {
-            gl.glColor4f(0.5f, 0.5f, 0.5f, 1f);
-            gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);
-            gl.glDrawElements(GL10.GL_TRIANGLES, NUM_INDICES, GL10.GL_UNSIGNED_SHORT, mIndexBuffer);
-        }
-    }
-
     class SensorListener implements SensorEventListener {
 
         /** Throw away other events that are smaller than this. */
@@ -350,18 +178,33 @@
             float value = event.values[mEventIndex];
             if (value > MOVING_AMOUNT) {
                 if (mExpectPositive) {
-                    updateWidgets(value, BACKGROUND_GREEN, R.drawable.fs_good);
+                    updateWidgets(
+                            value,
+                            GLRotationGuideRenderer.BACKGROUND_GREEN,
+                            R.drawable.fs_good);
                 } else {
-                    updateWidgets(value, BACKGROUND_RED, R.drawable.fs_error);
+                    updateWidgets(
+                            value,
+                            GLRotationGuideRenderer.BACKGROUND_RED,
+                            R.drawable.fs_error);
                 }
             } else if (value < -MOVING_AMOUNT) {
                 if (mExpectPositive) {
-                    updateWidgets(value, BACKGROUND_RED, R.drawable.fs_error);
+                    updateWidgets(
+                            value,
+                            GLRotationGuideRenderer.BACKGROUND_RED,
+                            R.drawable.fs_error);
                 } else {
-                    updateWidgets(value, BACKGROUND_GREEN, R.drawable.fs_good);
+                    updateWidgets(
+                            value,
+                            GLRotationGuideRenderer.BACKGROUND_GREEN,
+                            R.drawable.fs_good);
                 }
             } else {
-                updateWidgets(value, BACKGROUND_BLACK, R.drawable.fs_indeterminate);
+                updateWidgets(
+                        value,
+                        GLRotationGuideRenderer.BACKGROUND_BLACK,
+                        R.drawable.fs_indeterminate);
             }
 
             if (value > 10) {
@@ -371,7 +214,7 @@
 
         void updateWidgets(float sensorValue, int backgroundColor, int icon) {
             synchronized (GyroscopeTestActivity.this) {
-                mBackgroundColor.set(backgroundColor);
+                mRenderer.setBackgroundColor(backgroundColor);
             }
             mSensorText.setText(String.format("%+.2f", sensorValue));
             mSensorText.setCompoundDrawablesWithIntrinsicBounds(0, 0, icon, 0);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/HeartRateMonitorTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/HeartRateMonitorTestActivity.java
index 3a48e3c..b6a1c47 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/HeartRateMonitorTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/HeartRateMonitorTestActivity.java
@@ -61,7 +61,7 @@
         if (!mSensorManager.registerListener(mSensorListener, mSensor,
                 SensorManager.SENSOR_DELAY_UI)) {
             showNoHeartRateWarningDialog();
-            PassFailButtons.setTestResultAndFinish(this, getTestId(), getTestDetails(), true);
+            setTestResultAndFinish(true);
         }
     }
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/MagneticFieldMeasurementTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/MagneticFieldMeasurementTestActivity.java
index ffed1ab..553147b 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/MagneticFieldMeasurementTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/MagneticFieldMeasurementTestActivity.java
@@ -16,13 +16,21 @@
 
 package com.android.cts.verifier.sensors;
 
-import android.graphics.Color;
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.sensors.base.SensorCtsVerifierTestActivity;
+
 import android.hardware.Sensor;
 import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener2;
 import android.hardware.SensorManager;
-import android.hardware.cts.helpers.SensorManagerTestVerifier;
-import android.hardware.cts.helpers.sensorTestOperations.VerifyMagnitudeOperation;
-import android.hardware.cts.helpers.sensorTestOperations.VerifyStandardDeviationOperation;
+import android.hardware.cts.helpers.SensorCalibratedUncalibratedVerifier;
+import android.hardware.cts.helpers.SensorCtsHelper;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.TestSensorEventListener;
+import android.hardware.cts.helpers.TestSensorManager;
+import android.hardware.cts.helpers.sensoroperations.TestSensorOperation;
+import android.hardware.cts.helpers.sensorverification.MagnitudeVerification;
+import android.hardware.cts.helpers.sensorverification.StandardDeviationVerification;
 
 /**
  * Semi-automated test that focuses characteristics associated with Accelerometer measurements.
@@ -30,40 +38,16 @@
  * Also, it is recommended to execute these tests outdoors, or at least far from magnetic
  * disturbances.
  */
-public class MagneticFieldMeasurementTestActivity extends BaseSensorSemiAutomatedTestActivity {
-    @Override
-    protected void onRun() throws Throwable {
-        calibrateMagnetometer();
+public class MagneticFieldMeasurementTestActivity extends SensorCtsVerifierTestActivity {
+    private static final float THRESHOLD_CALIBRATED_UNCALIBRATED_UT = 3f;
 
-        appendText("Verifying the Norm...");
-        verifyNorm();
-
-        appendText("\nVerifying the Standard Deviation...");
-        verifyStandardDeviation();
+    public MagneticFieldMeasurementTestActivity() {
+        super(MagneticFieldMeasurementTestActivity.class);
     }
 
-    private void calibrateMagnetometer() {
-        SensorManagerTestVerifier magnetometer = new SensorManagerTestVerifier(
-                this.getApplicationContext(),
-                Sensor.TYPE_MAGNETIC_FIELD,
-                SensorManager.SENSOR_DELAY_NORMAL,
-                0 /*reportLatencyInUs*/) {
-            @Override
-            public void onSensorChanged(SensorEvent event) {
-                float values[] = event.values;
-                clearText();
-                appendText(
-                        "Please calibrate the Magnetometer by moving it in 8 shapes in different " +
-                                "orientations.");
-                appendText(
-                        String.format("->  (%.2f, %.2f, %.2f) uT", values[0], values[1], values[2]),
-                        Color.GRAY);
-                appendText("Then leave the device in a flat surface and press Next...\n");
-            }
-        };
-        magnetometer.registerListener();
-        waitForUser();
-        magnetometer.unregisterListener();
+    @Override
+    public void activitySetUp() throws InterruptedException {
+        calibrateMagnetometer();
     }
 
     /**
@@ -86,19 +70,26 @@
      * - the values representing the expectation of the test
      * - the values sampled from the sensor
      */
-    private void verifyNorm() throws Throwable {
+    @SuppressWarnings("unused")
+    public String testNorm() throws Throwable {
+        getTestLogger().logMessage(R.string.snsr_mag_verify_norm);
+
+        TestSensorEnvironment environment = new TestSensorEnvironment(
+                getApplicationContext(),
+                Sensor.TYPE_MAGNETIC_FIELD,
+                SensorManager.SENSOR_DELAY_FASTEST);
+        TestSensorOperation verifyNorm =
+                new TestSensorOperation(environment, 100 /* event count */);
+
         float expectedMagneticFieldEarth =
                 (SensorManager.MAGNETIC_FIELD_EARTH_MAX + SensorManager.MAGNETIC_FIELD_EARTH_MIN) / 2;
         float magneticFieldEarthThreshold =
                 expectedMagneticFieldEarth - SensorManager.MAGNETIC_FIELD_EARTH_MIN;
-        VerifyMagnitudeOperation verifyNorm = new VerifyMagnitudeOperation(
-                this.getApplicationContext(),
-                Sensor.TYPE_MAGNETIC_FIELD,
-                SensorManager.SENSOR_DELAY_FASTEST,
+        verifyNorm.addVerification(new MagnitudeVerification(
                 expectedMagneticFieldEarth,
-                magneticFieldEarthThreshold);
+                magneticFieldEarthThreshold));
         verifyNorm.execute();
-        logSuccess();
+        return null;
     }
 
     /**
@@ -124,14 +115,93 @@
      * Additionally, the device's debug output (adb logcat) dumps the set of values associated with
      * the failure to help track down the issue.
      */
-    private void verifyStandardDeviation() throws Throwable {
-        VerifyStandardDeviationOperation verifyStdDev = new VerifyStandardDeviationOperation(
-                this.getApplicationContext(),
+    @SuppressWarnings("unused")
+    public String testStandardDeviation() throws Throwable {
+        getTestLogger().logMessage(R.string.snsr_mag_verify_std_dev);
+
+        TestSensorEnvironment environment = new TestSensorEnvironment(
+                getApplicationContext(),
                 Sensor.TYPE_MAGNETIC_FIELD,
-                SensorManager.SENSOR_DELAY_FASTEST,
-                0 /*reportLatencyInUs*/,
-                2f /* uT */);
+                SensorManager.SENSOR_DELAY_FASTEST);
+        TestSensorOperation verifyStdDev =
+                new TestSensorOperation(environment, 100 /* event count */);
+
+        verifyStdDev.addVerification(new StandardDeviationVerification(
+                new float[]{2f, 2f, 2f} /* uT */));
         verifyStdDev.execute();
-        logSuccess();
+        return null;
+    }
+
+    /**
+     * Verifies that the relationship between readings from calibrated and their corresponding
+     * uncalibrated sensors comply to the following equation:
+     *      calibrated = uncalibrated - bias
+     */
+    @SuppressWarnings("unused")
+    public String testCalibratedAndUncalibrated() throws Throwable {
+        getTestLogger().logMessage(R.string.snsr_mag_verify_calibrated_uncalibrated);
+
+        TestSensorEnvironment calibratedEnvironment = new TestSensorEnvironment(
+                getApplicationContext(),
+                Sensor.TYPE_MAGNETIC_FIELD,
+                SensorManager.SENSOR_DELAY_FASTEST);
+        TestSensorEnvironment uncalibratedEnvironment = new TestSensorEnvironment(
+                getApplicationContext(),
+                Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED,
+                SensorManager.SENSOR_DELAY_FASTEST);
+        SensorCalibratedUncalibratedVerifier verifier = new SensorCalibratedUncalibratedVerifier(
+                calibratedEnvironment,
+                uncalibratedEnvironment,
+                THRESHOLD_CALIBRATED_UNCALIBRATED_UT);
+
+        try {
+            verifier.execute();
+        } finally {
+            playSound();
+        }
+        return null;
+    }
+
+    /**
+     * A routine to help operators calibrate the magnetometer.
+     */
+    private void calibrateMagnetometer() throws InterruptedException {
+        SensorEventListener2 listener = new SensorEventListener2() {
+            @Override
+            public void onSensorChanged(SensorEvent event) {
+                clearText();
+
+                float values[] = event.values;
+                SensorTestLogger logger = getTestLogger();
+                logger.logInstructions(R.string.snsr_mag_calibration_description);
+                logger.logMessage(
+                        R.string.snsr_mag_measurement,
+                        values[0],
+                        values[1],
+                        values[2],
+                        SensorCtsHelper.getMagnitude(values));
+
+                // TODO: automate finding out when the magnetometer is calibrated
+                logger.logInstructions(R.string.snsr_mag_calibration_complete);
+            }
+
+            @Override
+            public void onAccuracyChanged(Sensor sensor, int accuracy) {}
+
+            @Override
+            public void onFlushCompleted(Sensor sensor) {}
+        };
+
+        TestSensorEnvironment environment = new TestSensorEnvironment(
+                getApplicationContext(),
+                Sensor.TYPE_MAGNETIC_FIELD,
+                SensorManager.SENSOR_DELAY_NORMAL);
+        TestSensorManager magnetometer = new TestSensorManager(environment);
+        try {
+            magnetometer.registerListener(new TestSensorEventListener(listener));
+            waitForUserToContinue();
+        } finally {
+            magnetometer.unregisterListener();
+        }
     }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RotationVectorTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RotationVectorTestActivity.java
new file mode 100644
index 0000000..6b804dd
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RotationVectorTestActivity.java
@@ -0,0 +1,239 @@
+/*
+ * 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 com.android.cts.verifier.sensors;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.sensors.base.SensorCtsVerifierTestActivity;
+import com.android.cts.verifier.sensors.renderers.GLArrowSensorTestRenderer;
+
+import junit.framework.Assert;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.hardware.cts.helpers.SensorNotSupportedException;
+import android.hardware.cts.helpers.SensorTestStateNotSupportedException;
+import android.os.Bundle;
+import android.util.Log;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * This test verifies that mobile device can detect it's orientation in space and after device
+ * movement in space it correctly detects original (reference) position.
+ * All three rotation vectors are tested:
+ * - ROTATION_VECTOR,
+ * - GEOMAGNETIC_ROTATION_VECTOR,
+ * - GAME_ROTATION_VECTOR.
+ */
+public class RotationVectorTestActivity
+        extends SensorCtsVerifierTestActivity
+        implements SensorEventListener {
+    public RotationVectorTestActivity() {
+        super(RotationVectorTestActivity.class);
+    }
+
+    private SensorManager mSensorManager;
+    private SensorEventListener mListener;
+
+    /**
+     * Defines the thresholds for each rotation vector in degrees.
+     */
+    private static final double[] MAX_DEVIATION_DEGREES = {
+        10.0, // ROTATION_VECTOR
+        10.0, // GEOMAGNETIC ROTATION_VECTOR
+        40.0, // GAME_ROTATION_VECTOR
+    };
+
+    private static final int MAX_SENSORS_AVAILABLE = 3;
+    private static final int ROTATION_VECTOR_INDEX = 0;
+    private static final int GEOMAGNETIC_ROTATION_VECTOR_INDEX = 1;
+    private static final int GAME_ROTATION_VECTOR_INDEX = 2;
+
+    private float[][] mLastEvent = new float[3][5];
+    private final float[][] mReference = new float[3][16];
+    private final float[][] mAngularChange = new float[3][3];
+    private final Sensor[] mSensor = new Sensor[3];
+
+    /**
+     * The activity setup collects all the required data for test cases.
+     * This approach allows to test all sensors at once.
+     */
+    @Override
+    protected void activitySetUp() throws InterruptedException {
+        if (mSensor[ROTATION_VECTOR_INDEX] == null
+                && mSensor[GEOMAGNETIC_ROTATION_VECTOR_INDEX] == null
+                && mSensor[GAME_ROTATION_VECTOR_INDEX] == null) {
+            // if none of the sensors is supported, skip the test by throwing an exception
+            throw new SensorTestStateNotSupportedException("Rotation vectors are not supported.");
+        }
+
+        // TODO: take reference value automatically when device is 'still'
+        clearText();
+        appendText(R.string.snsr_rotation_vector_set_reference);
+        waitForUserToContinue();
+
+        clearText();
+        for (int i = 0; i < MAX_SENSORS_AVAILABLE; ++i) {
+            SensorManager.getRotationMatrixFromVector(mReference[i], mLastEvent[i].clone());
+        }
+
+        // TODO: check the user actually moved the device during the test
+        appendText(R.string.snsr_rotation_vector_reference_set);
+        appendText(R.string.snsr_rotation_vector_move_info);
+        appendText(R.string.snsr_test_play_sound);
+        Thread.sleep(TimeUnit.SECONDS.toMillis(30));
+        playSound();
+
+        // TODO: take final value automatically when device becomes 'still' at the end
+        clearText();
+        appendText(R.string.snsr_rotation_vector_set_final);
+        waitForUserToContinue();
+
+        clearText();
+        closeGlSurfaceView();
+
+        float[] finalVector = new float[16];
+        for (int i = 0; i < MAX_SENSORS_AVAILABLE; ++i) {
+            SensorManager.getRotationMatrixFromVector(finalVector, mLastEvent[i].clone());
+            SensorManager.getAngleChange(mAngularChange[i], mReference[i], finalVector);
+        }
+    }
+
+    /**
+     * Verifies that a given 'Rotation Vector' sensor does not drift over time.
+     * The test takes in consideration a reference measurement, and a final measurement. It then
+     * calculates its angular change.
+     */
+    private String verifyVector(int sensorIndex, int sensorType)
+            throws Throwable {
+        Sensor sensor = mSensor[sensorIndex];
+        if (sensor == null) {
+            throw new SensorNotSupportedException(sensorType);
+        }
+
+        float[] angularChange = mAngularChange[sensorIndex];
+        double maxDeviationDegrees = MAX_DEVIATION_DEGREES[sensorIndex];
+        double maxComponentDegrees = findMaxComponentDegrees(angularChange);
+        String message = getString(
+                R.string.snsr_rotation_vector_verification,
+                Math.toDegrees(angularChange[0]),
+                Math.toDegrees(angularChange[1]),
+                Math.toDegrees(angularChange[2]),
+                maxComponentDegrees,
+                maxDeviationDegrees);
+
+        Assert.assertEquals(message, 0, maxComponentDegrees, maxDeviationDegrees);
+        return message;
+    }
+
+    /**
+     * Test cases.
+     */
+    public String testRotationVector() throws Throwable {
+        return verifyVector(ROTATION_VECTOR_INDEX, Sensor.TYPE_ROTATION_VECTOR);
+    }
+
+    public String testGeomagneticRotationVector() throws Throwable {
+        return verifyVector(
+                GEOMAGNETIC_ROTATION_VECTOR_INDEX,
+                Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR);
+    }
+
+    public String testGameRotationVector() throws Throwable {
+        return verifyVector(GAME_ROTATION_VECTOR_INDEX, Sensor.TYPE_GAME_ROTATION_VECTOR);
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        // set up sensors first, so activitySetUp has the state in place
+        mSensorManager = (SensorManager) getApplicationContext().getSystemService(
+                Context.SENSOR_SERVICE);
+        mSensor[ROTATION_VECTOR_INDEX] =
+                mSensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
+        mSensor[GEOMAGNETIC_ROTATION_VECTOR_INDEX] =
+                mSensorManager.getDefaultSensor(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR);
+        mSensor[GAME_ROTATION_VECTOR_INDEX] =
+                mSensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR);
+
+        super.onCreate(savedInstanceState);
+
+        GLArrowSensorTestRenderer renderer =
+                new GLArrowSensorTestRenderer(this, Sensor.TYPE_ROTATION_VECTOR);
+        mListener = renderer;
+
+        initializeGlSurfaceView(renderer);
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        mSensorManager.unregisterListener(mListener);
+        mSensorManager.unregisterListener(this);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+
+        // listener for rendering
+        boolean renderListenerRegistered = false;
+        for (int i = 0; (!renderListenerRegistered && i < MAX_SENSORS_AVAILABLE); ++i) {
+            Sensor sensor = mSensor[i];
+            if (sensor != null) {
+                renderListenerRegistered = mSensorManager
+                        .registerListener(mListener, sensor, SensorManager.SENSOR_DELAY_GAME);
+                Log.v(LOG_TAG, "Renderer using sensor: " + sensor.getName());
+            }
+        }
+
+        // listeners for testing
+        for (int i = 0; i < MAX_SENSORS_AVAILABLE; ++i) {
+            mSensorManager.registerListener(this, mSensor[i], SensorManager.SENSOR_DELAY_GAME);
+        }
+    }
+
+    @Override
+    public void onSensorChanged(SensorEvent event) {
+        if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) {
+            mLastEvent[ROTATION_VECTOR_INDEX] = event.values.clone();
+        }
+        if (event.sensor.getType() == Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR) {
+            mLastEvent[GEOMAGNETIC_ROTATION_VECTOR_INDEX] = event.values.clone();
+        }
+        if (event.sensor.getType() == Sensor.TYPE_GAME_ROTATION_VECTOR) {
+            mLastEvent[GAME_ROTATION_VECTOR_INDEX] = event.values.clone();
+        }
+    }
+
+    @Override
+    public void onAccuracyChanged(Sensor sensor, int accuracy) {
+    }
+
+    private static double findMaxComponentDegrees(float[] vec) {
+        float maxComponent = 0;
+        for (int i = 0; i < vec.length; i++) {
+            float absComp = Math.abs(vec[i]);
+            if (maxComponent < absComp) {
+                maxComponent = absComp;
+            }
+        }
+        return Math.toDegrees(maxComponent);
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorBatchingTestsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorBatchingTestsActivity.java
new file mode 100644
index 0000000..d1923cc
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorBatchingTestsActivity.java
@@ -0,0 +1,31 @@
+/*
+ * 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 com.android.cts.verifier.sensors;
+
+import com.android.cts.verifier.sensors.base.SensorCtsTestActivity;
+
+import android.hardware.cts.SensorBatchingTests;
+
+/**
+ * Activity to execute CTS sensor batching tests.
+ * It is a wrapper for {@link SensorBatchingTests} running with AndroidJUnitRunner.
+ */
+public class SensorBatchingTestsActivity extends SensorCtsTestActivity {
+    public SensorBatchingTestsActivity() {
+        super(SensorBatchingTests.class);
+    }
+}
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorIntegrationTestsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorIntegrationTestsActivity.java
new file mode 100644
index 0000000..bda7f2b
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorIntegrationTestsActivity.java
@@ -0,0 +1,31 @@
+/*
+ * 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 com.android.cts.verifier.sensors;
+
+import com.android.cts.verifier.sensors.base.SensorCtsTestActivity;
+
+import android.hardware.cts.SensorIntegrationTests;
+
+/**
+ * Activity to execute CTS sensor integration tests.
+ * It is a wrapper for {@link SensorIntegrationTests} running with AndroidJUnitRunner.
+ */
+public class SensorIntegrationTestsActivity extends SensorCtsTestActivity {
+    public SensorIntegrationTestsActivity() {
+        super(SensorIntegrationTests.class);
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorPowerTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorPowerTestActivity.java
new file mode 100644
index 0000000..8370d3e
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorPowerTestActivity.java
@@ -0,0 +1,116 @@
+/*
+ * 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 com.android.cts.verifier.sensors;
+
+import com.android.cts.verifier.sensors.base.SensorCtsVerifierTestActivity;
+import com.android.cts.verifier.sensors.helpers.PowerTestHostLink;
+import com.android.cts.verifier.sensors.helpers.SensorTestScreenManipulator;
+import com.android.cts.verifier.sensors.reporting.SensorTestDetails;
+
+import junit.framework.Assert;
+
+public class SensorPowerTestActivity
+        extends SensorCtsVerifierTestActivity
+        implements PowerTestHostLink.HostToDeviceInterface {
+
+    private PowerTestHostLink mHostLink;
+    private SensorTestScreenManipulator mScreenManipulator;
+
+    public SensorPowerTestActivity() {
+        super(SensorPowerTestActivity.class);
+    }
+
+    @Override
+    public void waitForUserAcknowledgement(final String message) throws InterruptedException {
+        appendText(message);
+        waitForUserToContinue();
+    }
+
+    @Override
+    public void raiseError(String testName, String message) throws Exception {
+        getTestLogger().logTestFail(testName, message);
+        throw new RuntimeException(message);
+    }
+
+    @Override
+    public void logText(String text) {
+        appendText(text);
+    }
+
+    @Override
+    public void logTestResult(SensorTestDetails testDetails) {
+        getTestLogger().logTestDetails(testDetails);
+    }
+
+    @Override
+    public void turnScreenOff() {
+        mScreenManipulator.turnScreenOffOnNextPowerDisconnect();
+    }
+
+    @Override
+    protected void activitySetUp() throws InterruptedException {
+        mScreenManipulator = new SensorTestScreenManipulator(getApplicationContext());
+        mScreenManipulator.initialize(this);
+    }
+
+    @Override
+    protected void activityCleanUp() throws InterruptedException {
+        if (mHostLink != null) {
+            mHostLink.close();
+        }
+        mScreenManipulator.close();
+    }
+
+    public String testSensorsPower() throws Throwable {
+        if (mHostLink == null) {
+            // prepare Activity screen to show instructions to the operator
+            clearText();
+
+            // ask the operator to set up the host
+            appendText("Connect the device to the host machine via the USB passthrough.");
+            appendText("Execute the following script (the command is available in CtsVerifier.zip):");
+            appendText("    # python power/execute_power_tests.py --power_monitor <implementation> --run");
+            appendText("where \"<implementation>\" is the power monitor implementation being used, for example \"monsoon\"");
+            try {
+                mHostLink = new PowerTestHostLink(this, this);
+
+                appendText("Waiting for connection from Host...");
+
+                // this will block until first connection from host,
+                // and then allow the host to execute tests one by on
+                // until it issues an "EXIT" command to break out
+                // of the run loop. The host will run all associated tests
+                // sequentially here:
+                PowerTestHostLink.PowerTestResult testResult = mHostLink.run();
+
+                SensorTestDetails testDetails = new SensorTestDetails(
+                        getApplicationContext(),
+                        "SensorPowerTest",
+                        testResult.passedCount,
+                        testResult.skippedCount,
+                        testResult.failedCount);
+                Assert.assertEquals(testDetails.getSummary(), 0, testResult.failedCount);
+                return testDetails.getSummary();
+            } finally {
+                mHostLink.close();
+                mHostLink = null;
+            }
+        } else {
+            throw new IllegalStateException("Attempt to run test twice");
+        }
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorSynchronizationTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorSynchronizationTestActivity.java
new file mode 100644
index 0000000..683430c
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorSynchronizationTestActivity.java
@@ -0,0 +1,168 @@
+
+package com.android.cts.verifier.sensors;
+
+import com.android.cts.verifier.sensors.base.SensorCtsVerifierTestActivity;
+
+import junit.framework.Assert;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.hardware.cts.helpers.TestSensorEvent;
+import android.os.Build;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Test cross-sensor timestamp alignment by detecting major change in each
+ * sensor and comparing timestamps of that change.
+ */
+@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
+public class SensorSynchronizationTestActivity
+        extends SensorCtsVerifierTestActivity
+        implements SensorEventListener {
+    public SensorSynchronizationTestActivity() {
+        super(SensorSynchronizationTestActivity.class);
+    }
+
+    private final double NANOS_PER_MILLI = 1e6;
+    private final int DATA_COLLECTION_TIME_IN_MS = 5000;
+    private final int RATE_100HZ_IN_US = 10000;
+    private final int MAX_CROSS_SENSOR_DELAY_MILLIS = 125;
+    private final double THRESH_DEGREES = 10.0;
+    private final double THRESH_RPS = 1.0;
+
+    private SensorManager mSensorManager = null;
+    private List<TestSensorEvent> mSensorEvents = new ArrayList<TestSensorEvent>();
+
+    private void startDataCollection() {
+        mSensorEvents.clear();
+
+        mSensorManager = (SensorManager) getApplicationContext()
+                .getSystemService(Context.SENSOR_SERVICE);
+        mSensorManager.registerListener(this,
+                mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
+                RATE_100HZ_IN_US);
+        mSensorManager.registerListener(this,
+                mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
+                RATE_100HZ_IN_US);
+        mSensorManager.registerListener(this,
+                mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE),
+                RATE_100HZ_IN_US);
+    }
+
+    private void stopDataCollection() {
+        mSensorManager.unregisterListener(this);
+    }
+
+    private void analyzeData() {
+        int numberOfCollectedEvents = mSensorEvents.size();
+        Assert.assertTrue("No sensor events collected", numberOfCollectedEvents > 2);
+
+        boolean accMovementDetected = false;
+        boolean magMovementDetected = false;
+        boolean gyrMovementDetected = false;
+        long accMovementTimestamp = 0, magMovementTimestamp = 0, gyrMovementTimestamp = 0;
+        float[] accInitValues = null, magInitValues = null, gyrInitValues = null;
+
+        for (int i = 0; i < numberOfCollectedEvents; i++) {
+            TestSensorEvent event = mSensorEvents.get(i);
+
+            if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
+                if (accInitValues == null) {
+                    accInitValues = event.values.clone();
+                } else if (angleBetweenVecsDegrees(accInitValues, event.values) > THRESH_DEGREES
+                        && !accMovementDetected) {
+                    accMovementDetected = true;
+                    accMovementTimestamp = event.timestamp;
+                }
+            } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
+                if (magInitValues == null) {
+                    magInitValues = event.values.clone();
+                } else if (angleBetweenVecsDegrees(magInitValues, event.values) > THRESH_DEGREES
+                        && !magMovementDetected) {
+                    magMovementDetected = true;
+                    magMovementTimestamp = event.timestamp;
+                }
+            }
+            if (event.sensor.getType() == Sensor.TYPE_GYROSCOPE) {
+                if (gyrInitValues == null) {
+                    gyrInitValues = event.values.clone();
+                } else if (normVec(event.values) > THRESH_RPS && !gyrMovementDetected) {
+                    gyrMovementDetected = true;
+                    gyrMovementTimestamp = event.timestamp;
+                }
+            }
+
+            if (accMovementDetected && magMovementDetected && gyrMovementDetected) {
+                double maxTimestamp = Math.max(accMovementTimestamp,
+                        magMovementTimestamp);
+                maxTimestamp = Math.max(gyrMovementTimestamp, maxTimestamp);
+
+                double minTimestamp = Math.min(accMovementTimestamp,
+                        magMovementTimestamp);
+                minTimestamp = Math.min(gyrMovementTimestamp, minTimestamp);
+
+                double timeDifferenceBetweenMovementMillis =
+                        (maxTimestamp - minTimestamp) / NANOS_PER_MILLI;
+
+                appendText(String.format("\nSensor  |  Relative Timestamp (msec)\n"
+                        + "Accelerometer | %4.1f\nMagnetometer | %4.1f\nGyroscope | %4.1f\n",
+                        (accMovementTimestamp - minTimestamp) / NANOS_PER_MILLI,
+                        (magMovementTimestamp - minTimestamp) / NANOS_PER_MILLI,
+                        (gyrMovementTimestamp - minTimestamp) / NANOS_PER_MILLI));
+                Assert.assertEquals(String.format(
+                        "Cross sensor timestamp alignment off by more than %d msec.",
+                        MAX_CROSS_SENSOR_DELAY_MILLIS),
+                        0, timeDifferenceBetweenMovementMillis, MAX_CROSS_SENSOR_DELAY_MILLIS);
+                appendText(String.format(
+                        "Maximum cross sensor time between movement: %4.1f msec is within "
+                                + "required tolerance of %4.1f msec",
+                        timeDifferenceBetweenMovementMillis,
+                        (float) MAX_CROSS_SENSOR_DELAY_MILLIS));
+                break;
+            }
+        }
+
+        Assert.assertTrue("Accelerometer did not detect any movement", accMovementDetected);
+        Assert.assertTrue("Magnetometer did not detect any movement", magMovementDetected);
+        Assert.assertTrue("Gyroscope did not detect any movement", gyrMovementDetected);
+    }
+
+    public String testCrossSensorSynchronization() throws Throwable {
+        appendText("This test provides a rough indication of cross-sensor timestamp synchronization.");
+        appendText("Hold device still in hand and click 'Next'");
+        waitForUserToBegin();
+        clearText();
+        appendText("Quickly twist device upside-down and back");
+
+        startDataCollection();
+        Thread.sleep(DATA_COLLECTION_TIME_IN_MS);
+
+        stopDataCollection();
+        analyzeData();
+        return null;
+    }
+
+    protected double angleBetweenVecsDegrees(float[] vec1, float[] vec2) {
+        return Math.toDegrees(Math.acos((vec1[0] * vec2[0] + vec1[1] * vec2[1] + vec1[2] * vec2[2])
+                / normVec(vec1) / normVec(vec2)));
+    }
+
+    protected double normVec(float[] vec1) {
+        return Math.sqrt(vec1[0] * vec1[0] + vec1[1] * vec1[1] + vec1[2] * vec1[2]);
+    }
+
+    @Override
+    public void onSensorChanged(SensorEvent sensorEvent) {
+        mSensorEvents.add(new TestSensorEvent(sensorEvent));
+    }
+
+    @Override
+    public void onAccuracyChanged(Sensor sensor, int accuracy) {
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorTestActivity.java
new file mode 100644
index 0000000..fd3d380
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorTestActivity.java
@@ -0,0 +1,31 @@
+/*
+ * 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 com.android.cts.verifier.sensors;
+
+import com.android.cts.verifier.sensors.base.SensorCtsTestActivity;
+
+import android.hardware.cts.SensorTest;
+
+/**
+ * Activity to execute CTS sensor tests.
+ * It is a wrapper for {@link SensorTest} running with AndroidJUnitRunner.
+ */
+public class SensorTestActivity extends SensorCtsTestActivity {
+    public SensorTestActivity() {
+        super(SensorTest.class);
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SignificantMotionTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SignificantMotionTestActivity.java
new file mode 100644
index 0000000..faba445
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SignificantMotionTestActivity.java
@@ -0,0 +1,280 @@
+/*
+ * 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 com.android.cts.verifier.sensors;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.sensors.base.SensorCtsVerifierTestActivity;
+
+import junit.framework.Assert;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.hardware.TriggerEvent;
+import android.hardware.TriggerEventListener;
+import android.hardware.cts.helpers.SensorNotSupportedException;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.os.SystemClock;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Test cases for Significant Motion sensor.
+ * They use walking motion to change the location and trigger Significant Motion.
+ */
+public class SignificantMotionTestActivity extends SensorCtsVerifierTestActivity {
+    public SignificantMotionTestActivity() {
+        super(SignificantMotionTestActivity.class);
+    }
+
+    // acceptable time difference between event time and system time
+    private static final long MAX_ACCEPTABLE_EVENT_TIME_DELAY_NANOS =
+            TimeUnit.MILLISECONDS.toNanos(500);
+
+    // time for the test to wait for a trigger
+    private static final int TRIGGER_MAX_DELAY_SECONDS = 30;
+    private static final int VIBRATE_DURATION_MILLIS = 10000;
+
+    private static final int EVENT_VALUES_LENGTH = 1;
+    private static final float EXPECTED_EVENT_VALUE = 1.0f;
+
+    private SensorManager mSensorManager;
+    private Sensor mSensorSignificantMotion;
+
+    /**
+     * Test cases.
+     */
+
+    @SuppressWarnings("unused")
+    public String testTrigger() throws Throwable {
+        return runTest(
+                R.string.snsr_significant_motion_test_trigger,
+                true /* isMotionExpected */,
+                false /* cancelEventNotification */,
+                false /* vibrate */);
+    }
+
+    @SuppressWarnings("unused")
+    public String testNotTriggerAfterCancel() throws Throwable {
+        return runTest(
+                R.string.snsr_significant_motion_test_cancel,
+                false /* isMotionExpected */,
+                true /* cancelEventNotification */,
+                false /* vibrate */);
+    }
+
+    /**
+     * Verifies that Significant Motion is not trigger by the vibrator motion.
+     */
+    @SuppressWarnings("unused")
+    public String testVibratorDoesNotTrigger() throws Throwable {
+     return runTest(
+             R.string.snsr_significant_motion_test_vibration,
+             false /* isMotionExpected */,
+             false /* cancelEventNotification */,
+             true /* vibrate */);
+    }
+
+    /**
+     * Verifies that the natural motion of keeping the device in hand does not change the location.
+     * It ensures that Significant Motion will not trigger in that scenario.
+     */
+    @SuppressWarnings("unused")
+    public String testInHandDoesNotTrigger() throws Throwable {
+        return runTest(
+                R.string.snsr_significant_motion_test_in_hand,
+                false /* isMotionExpected */,
+                false /* cancelEventNotification */,
+                false /* vibrate */);
+    }
+
+    @SuppressWarnings("unused")
+    public String testSittingDoesNotTrigger() throws Throwable {
+        return runTest(
+                R.string.snsr_significant_motion_test_sitting,
+                false /* isMotionExpected */,
+                false /* cancelEventNotification */,
+                false /* vibrate */);
+    }
+
+    @SuppressWarnings("unused")
+    public String testTriggerDeactivation() throws Throwable {
+        SensorTestLogger logger = getTestLogger();
+        logger.logInstructions(R.string.snsr_significant_motion_test_deactivation);
+        waitForUserToBegin();
+
+        TriggerVerifier verifier = new TriggerVerifier();
+        mSensorManager.requestTriggerSensor(verifier, mSensorSignificantMotion);
+        logger.logWaitForSound();
+
+        // wait for the first event to trigger
+        verifier.verifyEventTriggered();
+
+        // wait for a second event not to trigger
+        String result = verifier.verifyEventNotTriggered();
+        playSound();
+        return result;
+    }
+
+    /**
+     * @param instructionsResId Instruction to be shown to testers
+     * @param isMotionExpected Should the device detect significant motion event
+     *            for this test?
+     * @param cancelEventNotification If TRUE, motion notifications will be
+     *            requested first and request will be cancelled
+     * @param vibrate If TRUE, vibration will be concurrent with the test
+     * @throws Throwable
+     */
+    private String runTest(
+            int instructionsResId,
+            boolean isMotionExpected,
+            boolean cancelEventNotification,
+            boolean vibrate) throws Throwable {
+        SensorTestLogger logger = getTestLogger();
+        logger.logInstructions(instructionsResId);
+        waitForUserToBegin();
+
+        if (vibrate) {
+            vibrate(VIBRATE_DURATION_MILLIS);
+        }
+
+        TriggerVerifier verifier = new TriggerVerifier();
+        boolean success = mSensorManager.requestTriggerSensor(verifier, mSensorSignificantMotion);
+        Assert.assertTrue(
+                getString(R.string.snsr_significant_motion_registration, success),
+                success);
+        if (cancelEventNotification) {
+            Assert.assertTrue(
+                    getString(R.string.snsr_significant_motion_cancelation),
+                    mSensorManager.cancelTriggerSensor(verifier, mSensorSignificantMotion));
+        }
+        logger.logWaitForSound();
+
+        String result;
+        try {
+            if (isMotionExpected) {
+                result = verifier.verifyEventTriggered();
+            } else {
+                result = verifier.verifyEventNotTriggered();
+            }
+        } finally {
+            mSensorManager.cancelTriggerSensor(verifier, mSensorSignificantMotion);
+            playSound();
+        }
+        return result;
+    }
+
+    @Override
+    protected void activitySetUp() {
+        mSensorManager = (SensorManager) getApplicationContext()
+                .getSystemService(Context.SENSOR_SERVICE);
+        mSensorSignificantMotion = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);
+        if (mSensorSignificantMotion == null) {
+            throw new SensorNotSupportedException(Sensor.TYPE_SIGNIFICANT_MOTION);
+        }
+    }
+
+    /**
+     * Helper Trigger listener for testing.
+     * It cannot be reused.
+     */
+    private class TriggerVerifier extends TriggerEventListener {
+        private volatile CountDownLatch mCountDownLatch;
+        private volatile TriggerEventRegistry mEventRegistry;
+
+        // TODO: refactor out if needed
+        private class TriggerEventRegistry {
+            public final TriggerEvent triggerEvent;
+            public final long realtimeTimestampNanos;
+
+            public TriggerEventRegistry(TriggerEvent event, long realtimeTimestampNanos) {
+                this.triggerEvent = event;
+                this.realtimeTimestampNanos = realtimeTimestampNanos;
+            }
+        }
+
+        public void onTrigger(TriggerEvent event) {
+            long elapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos();
+            mEventRegistry = new TriggerEventRegistry(event, elapsedRealtimeNanos);
+            mCountDownLatch.countDown();
+        }
+
+        public String verifyEventTriggered() throws Throwable {
+            TriggerEventRegistry registry = awaitForEvent();
+
+            // verify an event arrived, and it is indeed a Significant Motion event
+            TriggerEvent event = registry.triggerEvent;
+            String eventArrivalMessage =
+                    getString(R.string.snsr_significant_motion_event_arrival, event != null);
+            Assert.assertNotNull(eventArrivalMessage, event);
+
+            int eventType = event.sensor.getType();
+            String eventTypeMessage = getString(
+                    R.string.snsr_significant_motion_event_type,
+                    Sensor.TYPE_SIGNIFICANT_MOTION,
+                    eventType);
+            Assert.assertEquals(eventTypeMessage, Sensor.TYPE_SIGNIFICANT_MOTION, eventType);
+
+            String sensorName = event.sensor.getName();
+            int valuesLength = event.values.length;
+            String valuesLengthMessage = getString(
+                    R.string.snsr_event_length,
+                    EVENT_VALUES_LENGTH,
+                    valuesLength,
+                    sensorName);
+            Assert.assertEquals(valuesLengthMessage, EVENT_VALUES_LENGTH, valuesLength);
+
+            float value = event.values[0];
+            String valuesMessage = getString(
+                    R.string.snsr_event_value,
+                    EXPECTED_EVENT_VALUE,
+                    value,
+                    sensorName);
+            Assert.assertEquals(valuesMessage, EXPECTED_EVENT_VALUE, value);
+
+            long deltaThreshold = MAX_ACCEPTABLE_EVENT_TIME_DELAY_NANOS
+                    + TestSensorEnvironment.getSensorMaxDetectionLatencyNs(event.sensor);
+            return assertTimestampSynchronization(
+                    event.timestamp,
+                    registry.realtimeTimestampNanos,
+                    deltaThreshold,
+                    sensorName);
+        }
+
+        public String verifyEventNotTriggered() throws Throwable {
+            TriggerEventRegistry registry = awaitForEvent();
+
+            TriggerEvent event = registry.triggerEvent;
+            String eventMessage =
+                    getString(R.string.snsr_significant_motion_event_unexpected, event != null);
+            Assert.assertNull(eventMessage, event);
+            return eventMessage;
+        }
+
+        private TriggerEventRegistry awaitForEvent() throws InterruptedException {
+            mCountDownLatch = new CountDownLatch(1);
+            mCountDownLatch.await(TRIGGER_MAX_DELAY_SECONDS, TimeUnit.SECONDS);
+
+            TriggerEventRegistry registry = mEventRegistry;
+            mEventRegistry = null;
+
+            playSound();
+            return registry != null ? registry : new TriggerEventRegistry(null, 0);
+        }
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SingleSensorTestsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SingleSensorTestsActivity.java
new file mode 100644
index 0000000..23b5707
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SingleSensorTestsActivity.java
@@ -0,0 +1,31 @@
+/*
+ * 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 com.android.cts.verifier.sensors;
+
+import com.android.cts.verifier.sensors.base.SensorCtsTestActivity;
+
+import android.hardware.cts.SingleSensorTests;
+
+/**
+ * Activity to execute CTS single sensor tests.
+ * It is a wrapper for {@link SingleSensorTests} running with AndroidJUnitRunner.
+ */
+public class SingleSensorTestsActivity extends SensorCtsTestActivity {
+    public SingleSensorTestsActivity() {
+        super(SingleSensorTests.class);
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/StepCounterTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/StepCounterTestActivity.java
new file mode 100644
index 0000000..98368c6
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/StepCounterTestActivity.java
@@ -0,0 +1,345 @@
+/*
+ * 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 com.android.cts.verifier.sensors;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.sensors.base.SensorCtsVerifierTestActivity;
+
+import junit.framework.Assert;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.hardware.cts.helpers.MovementDetectorHelper;
+import android.hardware.cts.helpers.SensorTestStateNotSupportedException;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.TestSensorEvent;
+import android.os.SystemClock;
+import android.view.MotionEvent;
+import android.view.View;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+public class StepCounterTestActivity
+        extends SensorCtsVerifierTestActivity
+        implements SensorEventListener {
+    public StepCounterTestActivity() {
+        super(StepCounterTestActivity.class);
+    }
+
+    private static final int TEST_DURATION_SECONDS = 20;
+    private static final long TIMESTAMP_SYNCHRONIZATION_THRESHOLD_NANOS =
+            TimeUnit.MILLISECONDS.toNanos(500);
+
+    private static final int MIN_NUM_STEPS_PER_TEST = 10;
+    private static final int MAX_STEP_DISCREPANCY = 5;
+    private static final long MAX_TOLERANCE_STEP_TIME_NANOS = TimeUnit.SECONDS.toNanos(10);
+
+    private static final long[] VIBRATE_PATTERN = {
+            1000L, 500L, 1000L, 750L, 1000L, 500L, 1000L, 750L, 1000L, 1000L, 500L, 1000L,
+            750L, 1000L, 500L, 1000L };
+
+    private SensorManager mSensorManager;
+    private Sensor mSensorStepCounter;
+    private Sensor mSensorStepDetector;
+    private MovementDetectorHelper mMovementDetectorHelper;
+
+    private volatile boolean mMoveDetected;
+
+    private final List<Long> mTimestampsUserReported = new ArrayList<Long>();
+    private final List<TestSensorEvent> mStepCounterEvents = new ArrayList<TestSensorEvent>();
+    private final List<TestSensorEvent> mStepDetectorEvents = new ArrayList<TestSensorEvent>();
+
+    /**
+     * A flag that indicates if the test is interested in registering steps reported by the
+     * operator. The registration of events happens by tapping the screen throughout the test.
+     */
+    private volatile boolean mCheckForMotion;
+
+    @Override
+    protected void activitySetUp() {
+        mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
+        mSensorStepCounter = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
+        mSensorStepDetector = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
+
+        if (mSensorStepCounter == null && mSensorStepDetector == null) {
+            throw new SensorTestStateNotSupportedException(
+                    "Sensors Step Counter/Detector are not supported.");
+        }
+
+        setLogScrollViewListener(new View.OnTouchListener() {
+            @Override
+            public boolean onTouch(View v, MotionEvent event) {
+                // during movement of the device, the ScrollView will detect user taps as attempts
+                // to scroll, when in reality they are taps in the layout
+                // to overcome the fact that a ScrollView cannot be disabled from scrolling, we
+                // listen for ACTION_UP events instead of click events in the child layout
+                long elapsedTime = SystemClock.elapsedRealtimeNanos();
+                if (event.getAction() != MotionEvent.ACTION_UP) {
+                    return false;
+                }
+
+                try {
+                    logUserReportedStep(elapsedTime);
+                } catch (InterruptedException e) {
+                    // we cannot propagate the exception in the main thread, so we just catch and
+                    // restore the status, we don't need to log as we are terminating anyways
+                    Thread.currentThread().interrupt();
+                }
+                return false;
+            }
+        });
+    }
+
+    @Override
+    protected void activityCleanUp() {
+        setLogScrollViewListener(null /* listener */);
+    }
+
+    public String testWalking() throws Throwable {
+        return runTest(
+                R.string.snsr_step_counter_test_walking,
+                MIN_NUM_STEPS_PER_TEST,
+                false /* vibrate */);
+    }
+
+    public String testStill() throws Throwable {
+        return runTest(
+                R.string.snsr_step_counter_test_still,
+                0 /* expectedSteps */,
+                true /* vibrate */);
+    }
+
+    /**
+     * @param instructionsResId Resource ID containing instruction to be shown to testers
+     * @param expectedSteps Number of steps expected in this test
+     * @param vibrate If TRUE, vibration will be concurrent with the test
+     */
+    private String runTest(int instructionsResId, int expectedSteps, boolean vibrate)
+            throws Throwable {
+        mTimestampsUserReported.clear();
+        mStepCounterEvents.clear();
+        mStepDetectorEvents.clear();
+
+        mMoveDetected = false;
+        mCheckForMotion = false;
+
+        getTestLogger().logInstructions(instructionsResId);
+        waitForUserToBegin();
+
+        mCheckForMotion = (expectedSteps > 0);
+        if (vibrate) {
+            vibrate(VIBRATE_PATTERN);
+        }
+        startMeasurements();
+        getTestLogger().logWaitForSound();
+
+        Thread.sleep(TimeUnit.SECONDS.toMillis(TEST_DURATION_SECONDS));
+        mCheckForMotion = false;
+        playSound();
+
+        return verifyMeasurements(expectedSteps);
+    }
+
+    private void startMeasurements() {
+        if (mSensorStepCounter != null) {
+            mSensorManager.registerListener(this, mSensorStepCounter,
+                    SensorManager.SENSOR_DELAY_NORMAL);
+        }
+
+        if (mSensorStepDetector != null) {
+            mSensorManager.registerListener(this, mSensorStepDetector,
+                    SensorManager.SENSOR_DELAY_NORMAL);
+        }
+
+        mMovementDetectorHelper = new MovementDetectorHelper(getApplicationContext()) {
+            @Override
+            protected void onMovementDetected() {
+                mMoveDetected = true;
+            }
+        };
+        mMovementDetectorHelper.start();
+    }
+
+    private String verifyMeasurements(int stepsExpected) {
+        mSensorManager.unregisterListener(this);
+        mMovementDetectorHelper.stop();
+
+        if (mCheckForMotion) {
+            Assert.assertTrue(
+                    getString(R.string.snsr_movement_expected, mMoveDetected),
+                    mMoveDetected);
+        }
+
+        final int userReportedSteps = mTimestampsUserReported.size();
+        String stepsReportedMessage = getString(
+                R.string.snsr_step_counter_expected_steps,
+                stepsExpected,
+                userReportedSteps);
+        Assert.assertFalse(stepsReportedMessage, userReportedSteps < stepsExpected);
+
+        // TODO: split test cases for step detector and counter
+        verifyStepDetectorMeasurements();
+        verifyStepCounterMeasurements();
+        return null;
+    }
+
+    private void verifyStepCounterMeasurements() {
+        if (mSensorStepCounter == null) {
+            // sensor not supported, so no-op
+            return;
+        }
+
+        final int userReportedSteps = mTimestampsUserReported.size();
+        int totalStepsCounted = 0;
+        int initialStepCount = -1;
+        for (TestSensorEvent counterEvent : mStepCounterEvents) {
+            String sensorName = counterEvent.sensor.getName();
+            float[] values = counterEvent.values;
+
+            final int expectedLength = 1;
+            int valuesLength = values.length;
+            String eventLengthMessage = getString(
+                    R.string.snsr_event_length,
+                    expectedLength,
+                    valuesLength,
+                    sensorName);
+            Assert.assertEquals(eventLengthMessage, expectedLength, valuesLength);
+
+            int stepValue = (int) values[0];
+            if (initialStepCount == -1) {
+                initialStepCount = stepValue;
+            } else {
+                int stepsCounted = stepValue - initialStepCount;
+                int countDelta = stepsCounted - totalStepsCounted;
+
+                String eventTriggered = getString(
+                        R.string.snsr_step_counter_event_changed,
+                        countDelta,
+                        counterEvent.timestamp);
+                Assert.assertTrue(eventTriggered, countDelta > 0);
+
+                // TODO: abstract this into an ISensorVerification
+
+                long deltaThreshold = TIMESTAMP_SYNCHRONIZATION_THRESHOLD_NANOS
+                        + TestSensorEnvironment.getSensorMaxDetectionLatencyNs(counterEvent.sensor);
+                assertTimestampSynchronization(
+                        counterEvent.timestamp,
+                        counterEvent.receivedTimestamp,
+                        deltaThreshold,
+                        counterEvent.sensor.getName());
+
+                totalStepsCounted = stepsCounted;
+            }
+        }
+
+        int stepsCountedDelta = Math.abs(totalStepsCounted - userReportedSteps);
+        String stepsDeltaMessage = getString(
+                R.string.snsr_step_counter_detected_reported,
+                userReportedSteps,
+                totalStepsCounted,
+                stepsCountedDelta,
+                MAX_STEP_DISCREPANCY);
+        Assert.assertFalse(stepsDeltaMessage, stepsCountedDelta > MAX_STEP_DISCREPANCY);
+
+        int stepCounterLength = mStepCounterEvents.size();
+        for (int i = 0; i < userReportedSteps && i < stepCounterLength; ++i) {
+            long userReportedTimestamp = mTimestampsUserReported.get(i);
+            TestSensorEvent counterEvent = mStepCounterEvents.get(i);
+
+            assertTimestampSynchronization(
+                    counterEvent.timestamp,
+                    userReportedTimestamp,
+                    MAX_TOLERANCE_STEP_TIME_NANOS,
+                    counterEvent.sensor.getName());
+        }
+    }
+
+    private void verifyStepDetectorMeasurements() {
+        if (mSensorStepDetector == null) {
+            // sensor not supported, so no-op
+            return;
+        }
+
+        final int userReportedSteps = mTimestampsUserReported.size();
+        int stepsDetected = mStepDetectorEvents.size();
+        int stepsDetectedDelta = Math.abs(stepsDetected - userReportedSteps);
+        String stepsDetectedMessage = getString(
+                R.string.snsr_step_detector_detected_reported,
+                userReportedSteps,
+                stepsDetected,
+                stepsDetectedDelta,
+                MAX_STEP_DISCREPANCY);
+        Assert.assertFalse(stepsDetectedMessage, stepsDetectedDelta > MAX_STEP_DISCREPANCY);
+
+        for (TestSensorEvent detectorEvent : mStepDetectorEvents) {
+            String sensorName = detectorEvent.sensor.getName();
+            float[] values = detectorEvent.values;
+
+            final int expectedLength = 1;
+            int valuesLength = values.length;
+            String eventLengthMessage = getString(
+                    R.string.snsr_event_length,
+                    expectedLength,
+                    valuesLength,
+                    sensorName);
+            Assert.assertEquals(eventLengthMessage, expectedLength, valuesLength);
+
+            final float expectedValue = 1.0f;
+            float value0 = values[0];
+            String eventValueMessage =
+                    getString(R.string.snsr_event_value, expectedValue, value0, sensorName);
+            Assert.assertEquals(eventValueMessage, expectedValue, value0);
+        }
+
+        // TODO: verify correlation of events with steps from user
+    }
+
+    @Override
+    public final void onAccuracyChanged(Sensor sensor, int accuracy) {
+    }
+
+    public final void onSensorChanged(SensorEvent event) {
+        long elapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos();
+        int type = event.sensor.getType();
+        if (type == Sensor.TYPE_STEP_COUNTER) {
+            mStepCounterEvents.add(new TestSensorEvent(event, elapsedRealtimeNanos));
+            getTestLogger().logMessage(
+                    R.string.snsr_step_counter_event,
+                    elapsedRealtimeNanos,
+                    (int) event.values[0]);
+        } else if (type == Sensor.TYPE_STEP_DETECTOR) {
+            mStepDetectorEvents.add(new TestSensorEvent(event, elapsedRealtimeNanos));
+            getTestLogger().logMessage(R.string.snsr_step_detector_event, elapsedRealtimeNanos);
+
+        }
+        // TODO: with delayed assertions check events of other types are tracked
+    }
+
+    private void logUserReportedStep(long timestamp) throws InterruptedException {
+        if (!mCheckForMotion) {
+            return;
+        }
+        playSound();
+        mTimestampsUserReported.add(timestamp);
+        getTestLogger().logMessage(R.string.snsr_step_reported, timestamp);
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/BaseSensorTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/BaseSensorTestActivity.java
new file mode 100644
index 0000000..0bf9636
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/BaseSensorTestActivity.java
@@ -0,0 +1,678 @@
+/*
+
+ * 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 com.android.cts.verifier.sensors.base;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.TestResult;
+import com.android.cts.verifier.sensors.helpers.SensorFeaturesDeactivator;
+import com.android.cts.verifier.sensors.reporting.SensorTestDetails;
+
+import junit.framework.Assert;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.hardware.cts.helpers.ActivityResultMultiplexedLatch;
+import android.media.MediaPlayer;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.os.SystemClock;
+import android.os.Vibrator;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.text.format.DateUtils;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A base Activity that is used to build different methods to execute tests inside CtsVerifier.
+ * i.e. CTS tests, and semi-automated CtsVerifier tests.
+ *
+ * This class provides access to the following flow:
+ *      Activity set up
+ *          Execute tests (implemented by sub-classes)
+ *      Activity clean up
+ *
+ * Currently the following class structure is available:
+ * - BaseSensorTestActivity                 : provides the platform to execute Sensor tests inside
+ *      |                                     CtsVerifier, and logging support
+ *      |
+ *      -- SensorCtsTestActivity            : an activity that can be inherited from to wrap a CTS
+ *      |                                     sensor test, and execute it inside CtsVerifier
+ *      |                                     these tests do not require any operator interaction
+ *      |
+ *      -- SensorCtsVerifierTestActivity    : an activity that can be inherited to write sensor
+ *                                            tests that require operator interaction
+ */
+public abstract class BaseSensorTestActivity
+        extends Activity
+        implements View.OnClickListener, Runnable, ISensorTestStateContainer {
+    @Deprecated
+    protected static final String LOG_TAG = "SensorTest";
+
+    protected final Class mTestClass;
+
+    private final int mLayoutId;
+    private final SensorFeaturesDeactivator mSensorFeaturesDeactivator;
+
+    private final ExecutorService mExecutorService = Executors.newSingleThreadExecutor();
+    private final SensorTestLogger mTestLogger = new SensorTestLogger();
+    private final ActivityResultMultiplexedLatch mActivityResultMultiplexedLatch =
+            new ActivityResultMultiplexedLatch();
+    private final ArrayList<CountDownLatch> mWaitForUserLatches = new ArrayList<CountDownLatch>();
+
+    private ScrollView mLogScrollView;
+    private LinearLayout mLogLayout;
+    private Button mNextButton;
+    private Button mPassButton;
+    private Button mFailButton;
+
+    private GLSurfaceView mGLSurfaceView;
+    private boolean mUsingGlSurfaceView;
+
+    /**
+     * Constructor to be used by subclasses.
+     *
+     * @param testClass The class that contains the tests. It is dependant on test executor
+     *                  implemented by subclasses.
+     */
+    protected BaseSensorTestActivity(Class testClass) {
+        this(testClass, R.layout.sensor_test);
+    }
+
+    /**
+     * Constructor to be used by subclasses. It allows to provide a custom layout for the test UI.
+     *
+     * @param testClass The class that contains the tests. It is dependant on test executor
+     *                  implemented by subclasses.
+     * @param layoutId The Id of the layout to use for the test UI. The layout must contain all the
+     *                 elements in the base layout {@code R.layout.sensor_test}.
+     */
+    protected BaseSensorTestActivity(Class testClass, int layoutId) {
+        mTestClass = testClass;
+        mLayoutId = layoutId;
+        mSensorFeaturesDeactivator = new SensorFeaturesDeactivator(this);
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(mLayoutId);
+
+        mLogScrollView = (ScrollView) findViewById(R.id.log_scroll_view);
+        mLogLayout = (LinearLayout) findViewById(R.id.log_layout);
+        mNextButton = (Button) findViewById(R.id.next_button);
+        mNextButton.setOnClickListener(this);
+        mPassButton = (Button) findViewById(R.id.pass_button);
+        mFailButton = (Button) findViewById(R.id.fail_button);
+        mGLSurfaceView = (GLSurfaceView) findViewById(R.id.gl_surface_view);
+
+        updateNextButton(false /*enabled*/);
+        mExecutorService.execute(this);
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        mExecutorService.shutdownNow();
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        if (mUsingGlSurfaceView) {
+            mGLSurfaceView.onPause();
+        }
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        if (mUsingGlSurfaceView) {
+            mGLSurfaceView.onResume();
+        }
+    }
+
+    @Override
+    public void onClick(View target) {
+        synchronized (mWaitForUserLatches) {
+            for (CountDownLatch latch : mWaitForUserLatches) {
+                latch.countDown();
+            }
+            mWaitForUserLatches.clear();
+        }
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        mActivityResultMultiplexedLatch.onActivityResult(requestCode, resultCode);
+    }
+
+    /**
+     * The main execution {@link Thread}.
+     *
+     * This function executes in a background thread, allowing the test run freely behind the
+     * scenes. It provides the following execution hooks:
+     *  - Activity SetUp/CleanUp (not available in JUnit)
+     *  - executeTests: to implement several execution engines
+     */
+    @Override
+    public void run() {
+        long startTimeNs = SystemClock.elapsedRealtimeNanos();
+        String testName = getTestClassName();
+
+        SensorTestDetails testDetails;
+        try {
+            mSensorFeaturesDeactivator.requestDeactivationOfFeatures();
+            testDetails = new SensorTestDetails(testName, SensorTestDetails.ResultCode.PASS);
+        } catch (Throwable e) {
+            testDetails = new SensorTestDetails(testName, "DeactivateSensorFeatures", e);
+        }
+
+        SensorTestDetails.ResultCode resultCode = testDetails.getResultCode();
+        if (resultCode == SensorTestDetails.ResultCode.SKIPPED) {
+            // this is an invalid state at this point of the test setup
+            throw new IllegalStateException("Deactivation of features cannot skip the test.");
+        }
+        if (resultCode == SensorTestDetails.ResultCode.PASS) {
+            testDetails = executeActivityTests(testName);
+        }
+
+        // we consider all remaining states at this point, because we could have been half way
+        // deactivating features
+        try {
+            mSensorFeaturesDeactivator.requestToRestoreFeatures();
+        } catch (Throwable e) {
+            testDetails = new SensorTestDetails(testName, "RestoreSensorFeatures", e);
+        }
+
+        mTestLogger.logTestDetails(testDetails);
+        mTestLogger.logExecutionTime(startTimeNs);
+
+        // because we cannot enforce test failures in several devices, set the test UI so the
+        // operator can report the result of the test
+        promptUserToSetResult(testDetails);
+    }
+
+    /**
+     * A general set up routine. It executes only once before the first test case.
+     *
+     * NOTE: implementers must be aware of the interrupted status of the worker thread, and let
+     * {@link InterruptedException} propagate.
+     *
+     * @throws Throwable An exception that denotes the failure of set up. No tests will be executed.
+     */
+    protected void activitySetUp() throws Throwable {}
+
+    /**
+     * A general clean up routine. It executes upon successful execution of {@link #activitySetUp()}
+     * and after all the test cases.
+     *
+     * NOTE: implementers must be aware of the interrupted status of the worker thread, and handle
+     * it in two cases:
+     * - let {@link InterruptedException} propagate
+     * - if it is invoked with the interrupted status, prevent from showing any UI
+
+     * @throws Throwable An exception that will be logged and ignored, for ease of implementation
+     *                   by subclasses.
+     */
+    protected void activityCleanUp() throws Throwable {}
+
+    /**
+     * Performs the work of executing the tests.
+     * Sub-classes implementing different execution methods implement this method.
+     *
+     * @return A {@link SensorTestDetails} object containing information about the executed tests.
+     */
+    protected abstract SensorTestDetails executeTests() throws InterruptedException;
+
+    @Override
+    public SensorTestLogger getTestLogger() {
+        return mTestLogger;
+    }
+
+    @Deprecated
+    protected void appendText(int resId) {
+        mTestLogger.logInstructions(resId);
+    }
+
+    @Deprecated
+    protected void appendText(String text) {
+        TextAppender textAppender = new TextAppender(R.layout.snsr_instruction);
+        textAppender.setText(text);
+        textAppender.append();
+    }
+
+    @Deprecated
+    protected void clearText() {
+        this.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mLogLayout.removeAllViews();
+            }
+        });
+    }
+
+    /**
+     * Waits for the operator to acknowledge a requested action.
+     *
+     * @param waitMessageResId The action requested to the operator.
+     */
+    protected void waitForUser(int waitMessageResId) throws InterruptedException {
+        CountDownLatch latch = new CountDownLatch(1);
+        synchronized (mWaitForUserLatches) {
+            mWaitForUserLatches.add(latch);
+        }
+
+        mTestLogger.logInstructions(waitMessageResId);
+        updateNextButton(true);
+        latch.await();
+        updateNextButton(false);
+    }
+
+    /**
+     * Waits for the operator to acknowledge to begin execution.
+     */
+    protected void waitForUserToBegin() throws InterruptedException {
+        waitForUser(R.string.snsr_wait_to_begin);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void waitForUserToContinue() throws InterruptedException {
+        waitForUser(R.string.snsr_wait_for_user);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int executeActivity(String action) throws InterruptedException {
+        return executeActivity(new Intent(action));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int executeActivity(Intent intent) throws InterruptedException {
+        ActivityResultMultiplexedLatch.Latch latch = mActivityResultMultiplexedLatch.bindThread();
+        startActivityForResult(intent, latch.getRequestCode());
+        return latch.await();
+    }
+
+    /**
+     * Initializes and shows the {@link GLSurfaceView} available to tests.
+     * NOTE: initialization can be performed only once, usually inside {@link #activitySetUp()}.
+     */
+    protected void initializeGlSurfaceView(final GLSurfaceView.Renderer renderer) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mGLSurfaceView.setVisibility(View.VISIBLE);
+                mGLSurfaceView.setRenderer(renderer);
+                mUsingGlSurfaceView = true;
+            }
+        });
+    }
+
+    /**
+     * Closes and hides the {@link GLSurfaceView}.
+     */
+    protected void closeGlSurfaceView() {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                if (!mUsingGlSurfaceView) {
+                    return;
+                }
+                mGLSurfaceView.setVisibility(View.GONE);
+                mGLSurfaceView.onPause();
+                mUsingGlSurfaceView = false;
+            }
+        });
+    }
+
+    /**
+     * Plays a (default) sound as a notification for the operator.
+     */
+    protected void playSound() throws InterruptedException {
+        MediaPlayer player = MediaPlayer.create(this, Settings.System.DEFAULT_NOTIFICATION_URI);
+        if (player == null) {
+            Log.e(LOG_TAG, "MediaPlayer unavailable.");
+            return;
+        }
+        player.start();
+        try {
+            Thread.sleep(500);
+        } finally {
+            player.stop();
+        }
+    }
+
+    /**
+     * Makes the device vibrate for the given amount of time.
+     */
+    protected void vibrate(int timeInMs) {
+        Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
+        vibrator.vibrate(timeInMs);
+    }
+
+    /**
+     * Makes the device vibrate following the given pattern.
+     * See {@link Vibrator#vibrate(long[], int)} for more information.
+     */
+    protected void vibrate(long[] pattern) {
+        Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
+        vibrator.vibrate(pattern, -1);
+    }
+
+    // TODO: move to sensor assertions
+    protected String assertTimestampSynchronization(
+            long eventTimestamp,
+            long receivedTimestamp,
+            long deltaThreshold,
+            String sensorName) {
+        long timestampDelta = Math.abs(eventTimestamp - receivedTimestamp);
+        String timestampMessage = getString(
+                R.string.snsr_event_time,
+                receivedTimestamp,
+                eventTimestamp,
+                timestampDelta,
+                deltaThreshold,
+                sensorName);
+        Assert.assertTrue(timestampMessage, timestampDelta < deltaThreshold);
+        return timestampMessage;
+    }
+
+    protected String getTestClassName() {
+        if (mTestClass == null) {
+            return "<unknown>";
+        }
+        return mTestClass.getName();
+    }
+
+    protected void setLogScrollViewListener(View.OnTouchListener listener) {
+        mLogScrollView.setOnTouchListener(listener);
+    }
+
+    private void setTestResult(SensorTestDetails testDetails) {
+        // the name here, must be the Activity's name because it is what CtsVerifier expects
+        String name = super.getClass().getName();
+        String summary = mTestLogger.getOverallSummary();
+        SensorTestDetails.ResultCode resultCode = testDetails.getResultCode();
+        switch(resultCode) {
+            case SKIPPED:
+                TestResult.setPassedResult(this, name, summary);
+                break;
+            case PASS:
+                TestResult.setPassedResult(this, name, summary);
+                break;
+            case FAIL:
+                TestResult.setFailedResult(this, name, summary);
+                break;
+            case INTERRUPTED:
+                // do not set a result, just return so the test can complete
+                break;
+            default:
+                throw new IllegalStateException("Unknown ResultCode: " + resultCode);
+        }
+    }
+
+    private SensorTestDetails executeActivityTests(String testName) {
+        SensorTestDetails testDetails;
+        try {
+            activitySetUp();
+            testDetails = new SensorTestDetails(testName, SensorTestDetails.ResultCode.PASS);
+        } catch (Throwable e) {
+            testDetails = new SensorTestDetails(testName, "ActivitySetUp", e);
+        }
+
+        SensorTestDetails.ResultCode resultCode = testDetails.getResultCode();
+        if (resultCode == SensorTestDetails.ResultCode.PASS) {
+            // TODO: implement execution filters:
+            //      - execute all tests and report results officially
+            //      - execute single test or failed tests only
+            try {
+                testDetails = executeTests();
+            } catch (Throwable e) {
+                // we catch and continue because we have to guarantee a proper clean-up sequence
+                testDetails = new SensorTestDetails(testName, "TestExecution", e);
+            }
+        }
+
+        // clean-up executes for all states, even on SKIPPED and INTERRUPTED there might be some
+        // intermediate state that needs to be taken care of
+        try {
+            activityCleanUp();
+        } catch (Throwable e) {
+            testDetails = new SensorTestDetails(testName, "ActivityCleanUp", e);
+        }
+
+        return testDetails;
+    }
+
+    private void promptUserToSetResult(SensorTestDetails testDetails) {
+        SensorTestDetails.ResultCode resultCode = testDetails.getResultCode();
+        if (resultCode == SensorTestDetails.ResultCode.FAIL) {
+            mTestLogger.logInstructions(R.string.snsr_test_complete_with_errors);
+            enableTestResultButton(
+                    mPassButton,
+                    R.string.snsr_pass_on_error,
+                    testDetails.cloneAndChangeResultCode(SensorTestDetails.ResultCode.PASS));
+            enableTestResultButton(
+                    mFailButton,
+                    R.string.fail_button_text,
+                    testDetails.cloneAndChangeResultCode(SensorTestDetails.ResultCode.FAIL));
+        } else if (resultCode != SensorTestDetails.ResultCode.INTERRUPTED) {
+            mTestLogger.logInstructions(R.string.snsr_test_complete);
+            enableTestResultButton(
+                    mPassButton,
+                    R.string.pass_button_text,
+                    testDetails.cloneAndChangeResultCode(SensorTestDetails.ResultCode.PASS));
+        }
+    }
+
+    private void updateNextButton(final boolean enabled) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mNextButton.setEnabled(enabled);
+            }
+        });
+    }
+
+    private void enableTestResultButton(
+            final Button button,
+            final int textResId,
+            final SensorTestDetails testDetails) {
+        final View.OnClickListener listener = new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                setTestResult(testDetails);
+                finish();
+            }
+        };
+
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mNextButton.setVisibility(View.GONE);
+                button.setText(textResId);
+                button.setOnClickListener(listener);
+                button.setVisibility(View.VISIBLE);
+            }
+        });
+    }
+
+    // a logger available until sensor reporting is in place
+    public class SensorTestLogger {
+        private static final String SUMMARY_SEPARATOR = " | ";
+
+        private final StringBuilder mOverallSummaryBuilder = new StringBuilder("\n");
+
+        void logTestStart(String testName) {
+            // TODO: log the sensor information and expected execution time of each test
+            TextAppender textAppender = new TextAppender(R.layout.snsr_test_title);
+            textAppender.setText(testName);
+            textAppender.append();
+        }
+
+        public void logInstructions(int instructionsResId, Object ... params) {
+            TextAppender textAppender = new TextAppender(R.layout.snsr_instruction);
+            textAppender.setText(getString(instructionsResId, params));
+            textAppender.append();
+        }
+
+        public void logMessage(int messageResId, Object ... params) {
+            TextAppender textAppender = new TextAppender(R.layout.snsr_message);
+            textAppender.setText(getString(messageResId, params));
+            textAppender.append();
+        }
+
+        public void logWaitForSound() {
+            logInstructions(R.string.snsr_test_play_sound);
+        }
+
+        public void logTestDetails(SensorTestDetails testDetails) {
+            String name = testDetails.getName();
+            String summary = testDetails.getSummary();
+            SensorTestDetails.ResultCode resultCode = testDetails.getResultCode();
+            switch (resultCode) {
+                case SKIPPED:
+                    logTestSkip(name, summary);
+                    break;
+                case PASS:
+                    logTestPass(name, summary);
+                    break;
+                case FAIL:
+                    logTestFail(name, summary);
+                    break;
+                case INTERRUPTED:
+                    // do nothing, the test was interrupted so do we
+                    break;
+                default:
+                    throw new IllegalStateException("Unknown ResultCode: " + resultCode);
+            }
+        }
+
+        void logTestPass(String testName, String testSummary) {
+            testSummary = getValidTestSummary(testSummary, R.string.snsr_test_pass);
+            logTestEnd(R.layout.snsr_success, testSummary);
+            Log.d(LOG_TAG, testSummary);
+            saveResult(testName, SensorTestDetails.ResultCode.PASS, testSummary);
+        }
+
+        public void logTestFail(String testName, String testSummary) {
+            testSummary = getValidTestSummary(testSummary, R.string.snsr_test_fail);
+            logTestEnd(R.layout.snsr_error, testSummary);
+            Log.e(LOG_TAG, testSummary);
+            saveResult(testName, SensorTestDetails.ResultCode.FAIL, testSummary);
+        }
+
+        void logTestSkip(String testName, String testSummary) {
+            testSummary = getValidTestSummary(testSummary, R.string.snsr_test_skipped);
+            logTestEnd(R.layout.snsr_warning, testSummary);
+            Log.i(LOG_TAG, testSummary);
+            saveResult(testName, SensorTestDetails.ResultCode.SKIPPED, testSummary);
+        }
+
+        String getOverallSummary() {
+            return mOverallSummaryBuilder.toString();
+        }
+
+        void logExecutionTime(long startTimeNs) {
+            if (Thread.currentThread().isInterrupted()) {
+                return;
+            }
+            long executionTimeNs = SystemClock.elapsedRealtimeNanos() - startTimeNs;
+            long executionTimeSec = TimeUnit.NANOSECONDS.toSeconds(executionTimeNs);
+            // TODO: find a way to format times with nanosecond accuracy and longer than 24hrs
+            String formattedElapsedTime = DateUtils.formatElapsedTime(executionTimeSec);
+            logMessage(R.string.snsr_execution_time, formattedElapsedTime);
+        }
+
+        private void logTestEnd(int textViewResId, String testSummary) {
+            TextAppender textAppender = new TextAppender(textViewResId);
+            textAppender.setText(testSummary);
+            textAppender.append();
+        }
+
+        private String getValidTestSummary(String testSummary, int defaultSummaryResId) {
+            if (TextUtils.isEmpty(testSummary)) {
+                return getString(defaultSummaryResId);
+            }
+            return testSummary;
+        }
+
+        private void saveResult(
+                String testName,
+                SensorTestDetails.ResultCode resultCode,
+                String summary) {
+            mOverallSummaryBuilder.append(testName);
+            mOverallSummaryBuilder.append(SUMMARY_SEPARATOR);
+            mOverallSummaryBuilder.append(resultCode.name());
+            mOverallSummaryBuilder.append(SUMMARY_SEPARATOR);
+            mOverallSummaryBuilder.append(summary);
+            mOverallSummaryBuilder.append("\n");
+        }
+    }
+
+    private class TextAppender {
+        private final TextView mTextView;
+
+        public TextAppender(int textViewResId) {
+            mTextView = (TextView) getLayoutInflater().inflate(textViewResId, null /* viewGroup */);
+        }
+
+        public void setText(String text) {
+            mTextView.setText(text);
+        }
+
+        public void setText(int textResId) {
+            mTextView.setText(textResId);
+        }
+
+        public void append() {
+            runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    mLogLayout.addView(mTextView);
+                    mLogScrollView.post(new Runnable() {
+                        @Override
+                        public void run() {
+                            mLogScrollView.fullScroll(View.FOCUS_DOWN);
+                        }
+                    });
+                }
+            });
+        }
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/ISensorTestStateContainer.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/ISensorTestStateContainer.java
new file mode 100644
index 0000000..2ba74e3
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/ISensorTestStateContainer.java
@@ -0,0 +1,73 @@
+/*
+ * 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 com.android.cts.verifier.sensors.base;
+
+import android.content.ContentResolver;
+import android.content.Intent;
+
+/**
+ * An interface that defines a facade for {@link BaseSensorTestActivity}, so it can be consumed by
+ * other CtsVerifier Sensor Test Framework helper components.
+ */
+public interface ISensorTestStateContainer {
+
+    /**
+     * @return The current logger.
+     */
+    BaseSensorTestActivity.SensorTestLogger getTestLogger();
+
+    /**
+     * Waits for the operator to acknowledge to continue execution.
+     */
+    void waitForUserToContinue() throws InterruptedException;
+
+    /**
+     * @param resId The resource Id to extract.
+     * @return The extracted string.
+     */
+    String getString(int resId);
+
+    /**
+     * @param resId The resource Id to extract.
+     * @param params The parameters to format the string represented by the resource contents.
+     * @return The formatted extracted string.
+     */
+    String getString(int resId, Object ... params);
+
+    /**
+     * Starts an Activity and blocks until it completes, then it returns its result back to the
+     * client.
+     *
+     * @param action The action to start the Activity.
+     * @return The Activity's result code.
+     */
+    int executeActivity(String action) throws InterruptedException;
+
+    /**
+     * Starts an Activity and blocks until it completes, then it returns its result back to the
+     * client.
+     *
+     * @param intent The intent to start the Activity.
+     * @return The Activity's result code.
+     */
+    int executeActivity(Intent intent) throws InterruptedException;
+
+    /**
+     * @return The {@link ContentResolver} associated with the test.
+     */
+    ContentResolver getContentResolver();
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsTestActivity.java
new file mode 100644
index 0000000..16c5fcd
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsTestActivity.java
@@ -0,0 +1,214 @@
+/*
+
+ * 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 com.android.cts.verifier.sensors.base;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.sensors.helpers.SensorTestScreenManipulator;
+import com.android.cts.verifier.sensors.reporting.SensorTestDetails;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.junit.internal.runners.JUnit38ClassRunner;
+import org.junit.internal.runners.SuiteMethod;
+import org.junit.runner.Computer;
+import org.junit.runner.Description;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Request;
+import org.junit.runner.Result;
+import org.junit.runner.Runner;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+import org.junit.runners.model.InitializationError;
+import org.junit.runners.model.RunnerBuilder;
+
+import android.content.Context;
+import android.hardware.cts.SensorTestCase;
+import android.os.PowerManager;
+import android.view.WindowManager;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An Activity that allows Sensor CTS tests to be executed inside CtsVerifier.
+ *
+ * Sub-classes pass the test class as part of construction.
+ * One JUnit test class is executed per Activity, the test class can still be executed outside
+ * CtsVerifier.
+ */
+public abstract class SensorCtsTestActivity extends BaseSensorTestActivity {
+
+    private SensorTestScreenManipulator mScreenManipulator;
+    private PowerManager.WakeLock mWakeLock;
+
+    /**
+     * Constructor for a CTS test executor. It will execute a standalone CTS test class.
+     *
+     * @param testClass The test class to execute, it must be a subclass of {@link SensorTestCase}.
+     */
+    protected SensorCtsTestActivity(Class<? extends SensorTestCase> testClass) {
+        super(testClass);
+    }
+
+    @Override
+    protected void activitySetUp() throws InterruptedException {
+        PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
+        mWakeLock =  powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SensorCtsTests");
+        mScreenManipulator = new SensorTestScreenManipulator(getApplicationContext());
+        mScreenManipulator.initialize(this);
+
+        SensorTestLogger logger = getTestLogger();
+        logger.logInstructions(R.string.snsr_no_interaction);
+        logger.logInstructions(R.string.snsr_run_automated_tests);
+        waitForUserToBegin();
+
+        // automated CTS tests run with the USB connected, so the AP doesn't go to sleep
+        // here we are not connected to USB, so we need to hold a wake-lock to avoid going to sleep
+        mWakeLock.acquire();
+        mScreenManipulator.turnScreenOff();
+    }
+
+    @Override
+    protected void activityCleanUp() {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
+            }
+        });
+        mScreenManipulator.turnScreenOn();
+        if (mWakeLock.isHeld()) {
+            mWakeLock.release();
+        }
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        if (mScreenManipulator != null) {
+            mScreenManipulator.releaseScreenOn();
+            mScreenManipulator.close();
+        }
+    }
+
+    /**
+     * For reference on the implementation of this test executor see:
+     *      android.support.test.runner.AndroidJUnitRunner
+     */
+    @Override
+    protected SensorTestDetails executeTests() {
+        JUnitCore testRunner = new JUnitCore();
+        testRunner.addListener(new SensorRunListener());
+
+        Computer computer = new Computer();
+        RunnerBuilder runnerBuilder = new SensorRunnerBuilder();
+
+        Runner runner;
+        try {
+            runner = computer.getSuite(runnerBuilder, new Class[]{ mTestClass });
+        } catch (InitializationError e) {
+            return new SensorTestDetails(
+                    getTestClassName(),
+                    SensorTestDetails.ResultCode.FAIL,
+                    "[JUnit Initialization]" + e.getMessage());
+        }
+
+        Request request = Request.runner(runner);
+        Result result = testRunner.run(request);
+        return new SensorTestDetails(getApplicationContext(), getClass().getName(), result);
+    }
+
+    /**
+     * A {@link RunnerBuilder} that is used to inject during execution a {@link SensorCtsTestSuite}.
+     */
+    private class SensorRunnerBuilder extends RunnerBuilder {
+        @Override
+        public Runner runnerForClass(Class<?> testClass) throws Throwable {
+            TestSuite testSuite;
+            if (hasSuiteMethod(testClass)) {
+                Test test = SuiteMethod.testFromSuiteMethod(testClass);
+                if (test instanceof TestSuite) {
+                    testSuite = (TestSuite) test;
+                } else {
+                    throw new IllegalArgumentException(
+                            testClass.getName() + "#suite() did not return a TestSuite.");
+                }
+            } else {
+                testSuite = new TestSuite(testClass);
+            }
+            SensorCtsTestSuite sensorTestSuite =
+                    new SensorCtsTestSuite(getApplicationContext(), testSuite);
+            return new JUnit38ClassRunner(sensorTestSuite);
+        }
+
+        private boolean hasSuiteMethod(Class<?> testClass) {
+            try {
+                testClass.getMethod("suite");
+                return true;
+            } catch (NoSuchMethodException e) {
+                return false;
+            }
+        }
+    }
+
+    /**
+     * Dummy {@link RunListener}.
+     * It is only used to handle logging into the UI.
+     */
+    private class SensorRunListener extends RunListener {
+        private volatile boolean mCurrentTestReported;
+
+        public void testRunStarted(Description description) throws Exception {
+            // nothing to log
+        }
+
+        public void testRunFinished(Result result) throws Exception {
+            // nothing to log
+            vibrate((int)TimeUnit.SECONDS.toMillis(2));
+            playSound();
+        }
+
+        public void testStarted(Description description) throws Exception {
+            mCurrentTestReported = false;
+            getTestLogger().logTestStart(description.getMethodName());
+        }
+
+        public void testFinished(Description description) throws Exception {
+            if (!mCurrentTestReported) {
+                getTestLogger().logTestPass(description.getMethodName(), null /* testSummary */);
+            }
+        }
+
+        public void testFailure(Failure failure) throws Exception {
+            mCurrentTestReported = true;
+            getTestLogger()
+                    .logTestFail(failure.getDescription().getMethodName(), failure.toString());
+        }
+
+        public void testAssumptionFailure(Failure failure) {
+            mCurrentTestReported = true;
+            getTestLogger()
+                    .logTestFail(failure.getDescription().getMethodName(), failure.toString());
+        }
+
+        public void testIgnored(Description description) throws Exception {
+            mCurrentTestReported = true;
+            getTestLogger().logTestSkip(description.getMethodName(), description.toString());
+        }
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsTestResult.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsTestResult.java
new file mode 100644
index 0000000..5bbaaf7
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsTestResult.java
@@ -0,0 +1,147 @@
+/*
+ * 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 com.android.cts.verifier.sensors.base;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.Protectable;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestFailure;
+import junit.framework.TestListener;
+import junit.framework.TestResult;
+
+import android.content.Context;
+import android.hardware.cts.SensorTestCase;
+
+import java.util.Enumeration;
+
+/**
+ * A wrapper class for a {@link TestResult}.
+ *
+ * It provides a way to inject augmented data and helper objects during the execution of tests.
+ * i.e. inject a Context object for use by tests.
+ */
+class SensorCtsTestResult extends TestResult {
+    private final Context mContext;
+    private final TestResult mWrappedTestResult;
+
+    private volatile boolean mInterrupted;
+
+    public SensorCtsTestResult(Context context, TestResult testResult) {
+        mContext = context;
+        mWrappedTestResult = testResult;
+    }
+
+    @Override
+    public void addError(Test test, Throwable throwable) {
+        mWrappedTestResult.addError(test, throwable);
+    }
+
+    @Override
+    public void addFailure(Test test, AssertionFailedError assertionFailedError) {
+        mWrappedTestResult.addFailure(test, assertionFailedError);
+    }
+
+    @Override
+    public void addListener(TestListener testListener) {
+        mWrappedTestResult.addListener(testListener);
+    }
+
+    @Override
+    public void removeListener(TestListener testListener) {
+        mWrappedTestResult.removeListener(testListener);
+    }
+
+    @Override
+    public void endTest(Test test) {
+        mWrappedTestResult.endTest(test);
+    }
+
+    @Override
+    public int errorCount() {
+        return mWrappedTestResult.errorCount();
+    }
+
+    @Override
+    public Enumeration<TestFailure> errors() {
+        return mWrappedTestResult.errors();
+    }
+
+    @Override
+    public int failureCount() {
+        return mWrappedTestResult.failureCount();
+    }
+
+    @Override
+    public Enumeration<TestFailure> failures() {
+        return mWrappedTestResult.failures();
+    }
+
+    @Override
+    public int runCount() {
+        return mWrappedTestResult.runCount();
+    }
+
+    @Override
+    public void runProtected(Test test, Protectable protectable) {
+        try {
+            protectable.protect();
+        } catch (AssertionFailedError e) {
+            addFailure(test, e);
+        } catch (ThreadDeath e) {
+            throw e;
+        } catch (InterruptedException e) {
+            mInterrupted = true;
+            addError(test, e);
+        } catch (Throwable e) {
+            addError(test, e);
+        }
+    }
+
+    @Override
+    public boolean shouldStop() {
+        return mInterrupted || mWrappedTestResult.shouldStop();
+    }
+
+    @Override
+    public void startTest(Test test) {
+        mWrappedTestResult.startTest(test);
+    }
+
+    @Override
+    public void stop() {
+        mWrappedTestResult.stop();
+    }
+
+    @Override
+    public boolean wasSuccessful() {
+        return mWrappedTestResult.wasSuccessful();
+    }
+
+    @Override
+    protected void run(TestCase testCase) {
+        if (testCase instanceof SensorTestCase) {
+            SensorTestCase sensorTestCase = (SensorTestCase) testCase;
+            sensorTestCase.setContext(mContext);
+            sensorTestCase.setEmulateSensorUnderLoad(false);
+            // TODO: set delayed assertion provider
+        } else {
+            throw new IllegalStateException("TestCase must be an instance of SensorTestCase.");
+        }
+        super.run(testCase);
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsTestSuite.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsTestSuite.java
new file mode 100644
index 0000000..bbf76a7
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsTestSuite.java
@@ -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
+ */
+
+package com.android.cts.verifier.sensors.base;
+
+import junit.framework.Test;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+
+import android.content.Context;
+
+import java.util.Enumeration;
+
+/**
+ * A wrapper class for a {@link TestSuite}.
+ *
+ * It provides a way to inject a {@link SensorCtsTestResult} during execution.
+ */
+class SensorCtsTestSuite extends TestSuite {
+    private final Context mContext;
+    private final TestSuite mWrappedTestSuite;
+
+    public SensorCtsTestSuite(Context context, TestSuite testSuite) {
+        mContext = context;
+        mWrappedTestSuite = testSuite;
+    }
+
+    @Override
+    public void run(TestResult testResult) {
+        mWrappedTestSuite.run(new SensorCtsTestResult(mContext, testResult));
+    }
+
+    @Override
+    public void addTest(Test test) {
+        mWrappedTestSuite.addTest(test);
+    }
+
+    @Override
+    public int countTestCases() {
+        return mWrappedTestSuite.countTestCases();
+    }
+
+    @Override
+    public String getName() {
+        return mWrappedTestSuite.getName();
+    }
+
+    @Override
+    public void runTest(Test test, TestResult testResult) {
+        mWrappedTestSuite.runTest(test, testResult);
+    }
+
+    @Override
+    public void setName(String name) {
+        mWrappedTestSuite.setName(name);
+    }
+
+    @Override
+    public Test testAt(int index) {
+        return mWrappedTestSuite.testAt(index);
+    }
+
+    @Override
+    public int testCount() {
+        return mWrappedTestSuite.testCount();
+    }
+
+    @Override
+    public Enumeration<Test> tests() {
+        return mWrappedTestSuite.tests();
+    }
+
+    @Override
+    public String toString() {
+        return mWrappedTestSuite.toString();
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsVerifierTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsVerifierTestActivity.java
new file mode 100644
index 0000000..a88abd0
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsVerifierTestActivity.java
@@ -0,0 +1,115 @@
+/*
+
+ * 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 com.android.cts.verifier.sensors.base;
+
+import com.android.cts.verifier.sensors.reporting.SensorTestDetails;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An Activity that provides a test execution engine for Sensor CtsVerifier tests. The tests are
+ * able to interact with an operator.
+ *
+ * Sub-classes reuse its own class definition to 'load' tests at runtime through reflection.
+ */
+public abstract class SensorCtsVerifierTestActivity extends BaseSensorTestActivity {
+    private volatile int mTestPassedCounter;
+    private volatile int mTestSkippedCounter;
+    private volatile int mTestFailedCounter;
+
+    /**
+     * {@inheritDoc}
+     */
+    protected SensorCtsVerifierTestActivity(
+            Class<? extends SensorCtsVerifierTestActivity> testClass) {
+        super(testClass);
+    }
+
+    /**
+     * Executes Semi-automated Sensor tests.
+     * Execution is driven by this class, and allows discovery of tests using reflection.
+     */
+    @Override
+    protected SensorTestDetails executeTests() throws InterruptedException {
+        // TODO: use reporting to log individual test results
+        for (Method testMethod : findTestMethods()) {
+            SensorTestDetails testDetails = executeTest(testMethod);
+            getTestLogger().logTestDetails(testDetails);
+        }
+        return new SensorTestDetails(
+                getApplicationContext(),
+                getTestClassName(),
+                mTestPassedCounter,
+                mTestSkippedCounter,
+                mTestFailedCounter);
+    }
+
+    private List<Method> findTestMethods() {
+        ArrayList<Method> testMethods = new ArrayList<Method>();
+        for (Method method : mTestClass.getDeclaredMethods()) {
+            if (Modifier.isPublic(method.getModifiers())
+                    && method.getParameterTypes().length == 0
+                    && method.getName().startsWith("test")
+                    && method.getReturnType().equals(String.class)) {
+                testMethods.add(method);
+            }
+        }
+        return testMethods;
+    }
+
+    private SensorTestDetails executeTest(Method testMethod) throws InterruptedException {
+        String testMethodName = testMethod.getName();
+        String testName = String.format("%s#%s", getTestClassName(), testMethodName);
+
+        SensorTestDetails testDetails;
+        try {
+            getTestLogger().logTestStart(testMethodName);
+            String testSummary = (String) testMethod.invoke(this);
+            testDetails =
+                    new SensorTestDetails(testName, SensorTestDetails.ResultCode.PASS, testSummary);
+        } catch (InvocationTargetException e) {
+            // get the inner exception, because we use reflection APIs to execute the test
+            testDetails = new SensorTestDetails(testName, "TestExecution", e.getCause());
+        } catch (Throwable e) {
+            testDetails = new SensorTestDetails(testName, "TestInfrastructure", e);
+        }
+
+        SensorTestDetails.ResultCode resultCode = testDetails.getResultCode();
+        switch(resultCode) {
+            case PASS:
+                ++mTestPassedCounter;
+                break;
+            case SKIPPED:
+                ++mTestSkippedCounter;
+                break;
+            case INTERRUPTED:
+                throw new InterruptedException();
+            case FAIL:
+                ++mTestFailedCounter;
+                break;
+            default:
+                throw new IllegalStateException("Unknown ResultCode: " + resultCode);
+        }
+
+        return testDetails;
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/PowerTestHostLink.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/PowerTestHostLink.java
new file mode 100644
index 0000000..ed2fea3
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/PowerTestHostLink.java
@@ -0,0 +1,440 @@
+/*
+ * 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 com.android.cts.verifier.sensors.helpers;
+
+import com.android.cts.verifier.sensors.reporting.SensorTestDetails;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.hardware.cts.helpers.SensorCtsHelper;
+import android.net.LocalServerSocket;
+import android.net.LocalSocket;
+import android.util.Log;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+import java.util.StringTokenizer;
+
+/**
+ * This class handles communication with the host to respond to commands.
+ * The command/response link is through a TCP socket on the host side, forwarded via adb to a local
+ * socket on the device. The system uses a standard "accept-read_command-send_response-close" to
+ * execute commands sent from the host.
+ *
+ * CAUTION: The local socket name (SOCKET_NAME below) must match that used by the host to set up
+ * the adb-forwarding.
+ */
+public class PowerTestHostLink {
+    private static final String TAG = "PowerTestHostLink";
+
+    /**
+     * Host-to-device bridge will use a Listener instance to drive the test via the CtsVerifier
+     * running on the device.
+     */
+    public interface HostToDeviceInterface {
+        void logTestResult(SensorTestDetails testDetails);
+        void raiseError(String testName, String message) throws Exception;
+        void waitForUserAcknowledgement(String message) throws InterruptedException;
+        void logText(String text);
+        void turnScreenOff();
+    }
+
+    /** This is a data-only message to communicate result of a power test */
+    public class PowerTestResult{
+        public int passedCount = 0;
+        public int skippedCount = 0;
+        public int failedCount = 0;
+    }
+
+    /**
+     * Standard response types back to host. Host-side code must match these definitions.
+     */
+    private final static String RESPONSE_OK = "OK";
+    private final static String RESPONSE_ERR = "ERR";
+    private final static String RESPONSE_UNAVAILABLE = "UNAVAILABLE";
+
+    /**
+     * Socket name for host adb forwarded communications. Must match naem in host-side code.
+     */
+    public final static String SOCKET_NAME = "/android/cts/powertest";
+
+    private volatile boolean mStopThread;
+    private final SensorManager mSensorManager;
+    private final HostToDeviceInterface mHostToDeviceExecutor;
+    private final PowerTestResult mTestResult = new PowerTestResult();
+
+    public PowerTestHostLink(Context context, HostToDeviceInterface listener) {
+        Log.d(TAG, " +++ Begin of localSocketServer() +++ ");
+        mHostToDeviceExecutor = listener;
+        mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
+    }
+
+    /**
+     * Ensure connection to host is closed; stop accepting requests.
+     **/
+    public void close() {
+        mStopThread = true;
+    }
+
+    /**
+     * Run the suite of tests via the host, responding to host requests.
+     *
+     * @return number of failed test cases
+     * @throws Exception
+     */
+    public PowerTestResult run() throws Exception {
+        // define buffer to receive data from host
+        final int BUFFER_SIZE = 4096;
+        byte[] buffer = new byte[BUFFER_SIZE];
+
+        LocalServerSocket serverSocket = createSocket();
+        if (null == serverSocket) {
+            mStopThread = true;
+        }
+
+        InputStream streamIn;
+        OutputStream streamOut;
+        LocalSocket receiverSocket;
+        while (!mStopThread) {
+
+            try {
+                Log.d(TAG, "localSocketServer accept...");
+                receiverSocket = serverSocket.accept();
+                Log.d(TAG, "Got new connection");
+            } catch (IOException e) {
+                Log.d(TAG, "localSocketServer accept() failed !!!", e);
+                continue;
+            }
+
+            try {
+                streamIn = receiverSocket.getInputStream();
+            } catch (IOException e) {
+                Log.d(TAG, "getInputStream() failed !!!", e);
+                continue;
+            }
+
+            try {
+                streamOut = receiverSocket.getOutputStream();
+            } catch (IOException e) {
+                Log.e(TAG, "getOutputStream() failed", e);
+                continue;
+            }
+
+            Log.d(TAG, "The client connected to LocalServerSocket");
+
+            try {
+                int total = 0;
+                // command and response handshake, so read all data
+                while (streamIn.available() > 0 || total == 0) {
+                    if (total < BUFFER_SIZE) {
+                        int bytesRead = streamIn.read(buffer, total,
+                                (BUFFER_SIZE - total));
+                        if (bytesRead > 0) {
+                            total += bytesRead;
+                        }
+                    } else {
+                        Log.e(TAG, "Message too long: truncating");
+                    }
+                }
+                String clientRequest = new String(buffer);
+                clientRequest = clientRequest.substring(0, total);
+                if (clientRequest.length() > 0) {
+
+                    Log.d(TAG, "Client requested: " + clientRequest);
+                    try {
+                        String response = processClientRequest(clientRequest);
+                        if (response != null) {
+                            Log.d(TAG, "Sending response " + response);
+                            streamOut.write(response.getBytes(), 0, response.length());
+                        }
+                        // null response means response is deferred awaiting user response
+                    } catch (Exception e) {
+                        Log.e(TAG, "Error executing " + clientRequest, e);
+                        streamOut.write(RESPONSE_ERR.getBytes(), 0, RESPONSE_ERR.length());
+                    }
+                }
+                receiverSocket.close();
+            } catch (IOException e) {
+                Log.e(TAG, "There is an exception when reading from or writing to socket", e);
+                break;
+            }
+        }
+        Log.d(TAG, "The LocalSocketServer thread is going to stop !!!");
+
+        if (serverSocket != null) {
+            try {
+                serverSocket.close();
+            } catch (IOException e) {
+                Log.d(TAG, "Exception on close of server socket", e);
+            }
+        }
+        mHostToDeviceExecutor.logText("Device disconnected.");
+        Log.d(TAG, "Returning " + mTestResult.passedCount + "passed " + mTestResult.skippedCount +
+                "skipped " + mTestResult.failedCount + "failed.");
+        return mTestResult;
+    }
+
+    private  String processClientRequest(String request) throws Exception {
+        // the following constants need to match the definitions in execute_power_tests.py
+        final String REQUEST_EXTERNAL_STORAGE = "EXTERNAL STORAGE?";
+        final String REQUEST_EXIT = "EXIT";
+        final String REQUEST_RAISE = "RAISE ";
+        final String REQUEST_USER_RESPONSE = "USER RESPONSE ";
+        final String REQUEST_SET_TEST_RESULT = "SET TEST RESULT ";
+        final String REQUEST_SENSOR_ON = "SENSOR ON ";
+        final String REQUEST_SENSOR_OFF = "SENSOR OFF";
+        final String REQUEST_SENSOR_AVAILABILITY = "SENSOR? ";
+        final String REQUEST_SCREEN_OFF = "SCREEN OFF";
+        final String REQUEST_SHOW_MESSAGE = "MESSAGE ";
+
+        String response = RESPONSE_ERR;
+        // Queries must appear first and then commands to direct actions after in these statements
+        if (request.startsWith(REQUEST_SENSOR_AVAILABILITY)) {
+            final String sensor = request.substring(REQUEST_SENSOR_AVAILABILITY.length());
+            final int sensorId = getSensorId(sensor);
+            if (mSensorManager.getDefaultSensor(sensorId) == null) {
+                response = RESPONSE_UNAVAILABLE;
+            } else {
+                response = RESPONSE_OK;
+            }
+        } else if (request.startsWith(REQUEST_EXTERNAL_STORAGE)){
+            response = SensorCtsHelper.getSensorTestDataDirectory("power/").getAbsolutePath();
+            Log.d(TAG,"External storage is " + response);
+        } else if (request.startsWith(REQUEST_SCREEN_OFF)) {
+            try {
+                mHostToDeviceExecutor.turnScreenOff();
+                response = RESPONSE_OK;
+            } catch (SecurityException e) {
+                Log.e(TAG, "Error Turning screen off", e);
+                response = RESPONSE_ERR;
+            }
+        } else if (request.startsWith(REQUEST_SENSOR_ON)) {
+            String sensorList = request.substring(REQUEST_SENSOR_ON.length()).trim();
+            response = handleSensorSwitchCommand(sensorList, true);
+        } else if (request.startsWith(REQUEST_SENSOR_OFF)) {
+            String sensorList = request.substring(REQUEST_SENSOR_ON.length()).trim();
+            response = handleSensorSwitchCommand(sensorList, false);
+        } else if (request.startsWith(REQUEST_SHOW_MESSAGE)) {
+            final String message = request.substring(REQUEST_SHOW_MESSAGE.length());
+            mHostToDeviceExecutor.logText(message);
+            response = RESPONSE_OK;
+        } else if (request.startsWith(REQUEST_USER_RESPONSE)) {
+            String message = request.substring(REQUEST_USER_RESPONSE.length());
+            mHostToDeviceExecutor.waitForUserAcknowledgement(message);
+            response = RESPONSE_OK;
+        } else if (request.startsWith(REQUEST_SET_TEST_RESULT)) {
+            String testResult = request.substring(REQUEST_SET_TEST_RESULT.length());
+            response = handleSetTestResultCmd(testResult);
+        } else if (request.startsWith(REQUEST_RAISE)) {
+            String command = request.substring(REQUEST_RAISE.length());
+            StringTokenizer tokenizer = new StringTokenizer(command);
+            try {
+                final String testName = tokenizer.nextToken();
+                final String message = request.substring(7 + testName.length());
+                mHostToDeviceExecutor.raiseError(testName, message);
+                response = RESPONSE_OK;
+            } catch (Exception e) {
+                Log.e(TAG, "Invalid RAISE command received (bad arguments): " + request);
+                response = RESPONSE_ERR;
+            }
+        } else if (request.startsWith(REQUEST_EXIT)) {
+            mStopThread = true;
+            response = RESPONSE_OK;
+        } else {
+            Log.e(TAG, "Unknown request: " + request);
+        }
+        return response;
+    }
+
+    private String handleSetTestResultCmd(final String request) {
+        String response;
+        StringTokenizer tokenizer = new StringTokenizer(request, " ");
+        String testName = "";
+        SensorTestDetails.ResultCode resultCode = SensorTestDetails.ResultCode.FAIL;
+        String message = "";
+
+        try {
+            testName = tokenizer.nextToken();
+            final String resultToken = tokenizer.nextToken();
+
+            if (resultToken.equals("PASS")) {
+                resultCode = SensorTestDetails.ResultCode.PASS;
+                ++mTestResult.passedCount;
+                message = "PASSED: ";
+                response = RESPONSE_OK;
+            } else if (resultToken.equals("FAIL")) {
+                resultCode = SensorTestDetails.ResultCode.FAIL;
+                ++mTestResult.failedCount;
+                message = "FAILED: ";
+                response = RESPONSE_OK;
+            } else if (resultToken.equals("SKIPPED")) {
+                resultCode = SensorTestDetails.ResultCode.SKIPPED;
+                ++mTestResult.skippedCount;
+                message = "SKIPPED: ";
+                response = RESPONSE_OK;
+            } else {
+                response = RESPONSE_ERR;
+            }
+            while (tokenizer.hasMoreTokens()) {
+                message += tokenizer.nextToken() + " ";
+            }
+            Log.i(TAG, message);
+        } catch (Exception e) {
+            Log.e(TAG, "Improperly formatted command received: " + request, e);
+            response = RESPONSE_ERR;
+        }
+        String fullMessage = testName + " " + message;
+        mHostToDeviceExecutor.logTestResult(
+                new SensorTestDetails(testName, resultCode, fullMessage));
+        return response;
+    }
+
+    private String handleSensorSwitchCommand(String sensorList, boolean switchOn) {
+        String response;
+        try {
+            StringTokenizer tokenizer = new StringTokenizer(sensorList, " ");
+            int n = tokenizer.countTokens();
+            if (n == 0) {
+                response = switchAllSensors(switchOn);
+            } else {
+                String sensorName = tokenizer.nextToken();
+                String requestRate = "";
+                if (n > 1) {
+                    requestRate = tokenizer.nextToken();
+                }
+                if (sensorName.equals("ALL")) {
+                    response = switchAllSensors(switchOn);
+                } else {
+                    int sensorId = getSensorId(sensorName);
+                    if (sensorId >= 0) {
+                        response = switchSensor(sensorId, switchOn, requestRate);
+                    } else {
+                        Log.e(TAG, "Unknown sensor in request: " + sensorName);
+                        response = RESPONSE_UNAVAILABLE;
+                    }
+                }
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Improperly formatted command received on setting sensor state");
+            response = RESPONSE_ERR;
+        }
+        return response;
+    }
+
+    private static int getSensorId(String sensorName) {
+        int sensorId = -1;
+
+        if (sensorName.compareToIgnoreCase("ACCELEROMETER") == 0) {
+            sensorId = Sensor.TYPE_ACCELEROMETER;
+        } else if (sensorName.compareToIgnoreCase("AMBIENT_TEMPERATURE") == 0) {
+            sensorId = Sensor.TYPE_AMBIENT_TEMPERATURE;
+        } else if (sensorName.compareToIgnoreCase("GAME_ROTATION_VECTOR") == 0) {
+            sensorId = Sensor.TYPE_GAME_ROTATION_VECTOR;
+        } else if (sensorName.compareToIgnoreCase("GEOMAGNETIC_ROTATION_VECTOR") == 0) {
+            sensorId = Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR;
+        } else if (sensorName.compareToIgnoreCase("GRAVITY") == 0) {
+            sensorId = Sensor.TYPE_GRAVITY;
+        } else if (sensorName.compareToIgnoreCase("GYROSCOPE") == 0) {
+            sensorId = Sensor.TYPE_GYROSCOPE;
+        } else if (sensorName.compareToIgnoreCase("LIGHT") == 0) {
+            sensorId = Sensor.TYPE_LIGHT;
+        } else if (sensorName.compareToIgnoreCase("MAGNETIC_FIELD") == 0) {
+            sensorId = Sensor.TYPE_MAGNETIC_FIELD;
+        } else if (sensorName.compareToIgnoreCase("PRESSURE") == 0) {
+            sensorId = Sensor.TYPE_PRESSURE;
+        } else if (sensorName.compareToIgnoreCase("PROXIMITY") == 0) {
+            sensorId = Sensor.TYPE_PROXIMITY;
+        } else if (sensorName.compareToIgnoreCase("RELATIVE_HUMIDITY") == 0) {
+            sensorId = Sensor.TYPE_RELATIVE_HUMIDITY;
+        } else if (sensorName.compareToIgnoreCase("ROTATION_VECTOR") == 0) {
+            sensorId = Sensor.TYPE_ROTATION_VECTOR;
+        } else if (sensorName.compareToIgnoreCase("SIGNIFICANT_MOTION") == 0) {
+            sensorId = Sensor.TYPE_SIGNIFICANT_MOTION;
+        } else if (sensorName.compareToIgnoreCase("STEP_COUNTER") == 0) {
+            sensorId = Sensor.TYPE_STEP_COUNTER;
+        } else if (sensorName.compareToIgnoreCase("STEP_DETECTOR") == 0) {
+            sensorId = Sensor.TYPE_STEP_DETECTOR;
+        }
+
+        return sensorId;
+    }
+
+    private String switchSensor(int sensorId, boolean switchOn) {
+        return switchSensor(sensorId, switchOn, "SENSOR_DELAY_NORMAL");
+    }
+
+    private String switchSensor(int sensorId, boolean switchOn, String requestFrequency) {
+        String response;
+        int rateUs = SensorManager.SENSOR_DELAY_NORMAL;
+
+        if (requestFrequency.compareToIgnoreCase("SENSOR_DELAY_FASTEST") == 0) {
+            rateUs = SensorManager.SENSOR_DELAY_FASTEST;
+        } else if (requestFrequency.compareToIgnoreCase("SENSOR_DELAY_GAME") == 0) {
+            rateUs = SensorManager.SENSOR_DELAY_GAME;
+        } else if (requestFrequency.compareToIgnoreCase("SENSOR_DELAY_UI") == 0) {
+            rateUs = SensorManager.SENSOR_DELAY_UI;
+        }
+
+        if (switchOn) {
+            mSensorManager.registerListener(mSensorEventListener,
+                    mSensorManager.getDefaultSensor(sensorId), rateUs);
+            response = RESPONSE_OK;
+            Log.v(TAG, "Switching ON " + String.valueOf(sensorId) + " | " + String.valueOf(rateUs));
+        } else {
+            mSensorManager.unregisterListener(mSensorEventListener,
+                    mSensorManager.getDefaultSensor(sensorId));
+            response = RESPONSE_OK;
+            Log.v(TAG, "Switching  OFF " + String.valueOf(sensorId));
+        }
+
+        return response;
+    }
+
+    private String switchAllSensors(boolean on) {
+        List<Sensor> allSensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);
+        String response = RESPONSE_OK;
+        for (Sensor sensor : allSensors) {
+            response = switchSensor(sensor.getType(), on);
+            if (response == null) {
+                response = RESPONSE_ERR;
+            }
+        }
+        return response;
+    }
+
+    private LocalServerSocket createSocket() {
+        try {
+            return new LocalServerSocket(SOCKET_NAME);
+        } catch (IOException e) {
+            Log.e(TAG, "LocalSocketServer creation failure.", e);
+            return null;
+        }
+    }
+
+    private SensorEventListener mSensorEventListener = new SensorEventListener() {
+        @Override
+        public void onAccuracyChanged(Sensor sensor, int accuracy) {}
+
+        @Override
+        public void onSensorChanged(SensorEvent event) {}
+    };
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorDeviceAdminReceiver.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorDeviceAdminReceiver.java
new file mode 100644
index 0000000..9d75a98
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorDeviceAdminReceiver.java
@@ -0,0 +1,34 @@
+/*
+ * 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 com.android.cts.verifier.sensors.helpers;
+
+import android.app.admin.DeviceAdminReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+
+/**
+ * Receiver to be used with {@link SensorTestScreenManipulator}.
+ */
+public class SensorDeviceAdminReceiver extends DeviceAdminReceiver {
+
+    /**
+     * Gets the associated {@link ComponentName} of the current receiver.
+     */
+    public static ComponentName getComponentName(Context context) {
+        return new ComponentName(context, SensorDeviceAdminReceiver.class);
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorFeaturesDeactivator.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorFeaturesDeactivator.java
new file mode 100644
index 0000000..36559bd
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorFeaturesDeactivator.java
@@ -0,0 +1,199 @@
+/*
+ * 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 com.android.cts.verifier.sensors.helpers;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.sensors.base.ISensorTestStateContainer;
+
+import android.content.ContentResolver;
+import android.os.Build;
+import android.provider.Settings;
+
+import java.lang.reflect.Field;
+
+/**
+ * A helper class that provides a mechanism to:
+ * - prompt users to activate/deactivate features that are known to register for sensor data.
+ * - turn on/off certain components of the device on behalf of the test (described as 'runtime
+ *   features')
+ * - keep track of the initial state for each sensor feature, so it can be restored at will
+ */
+public class SensorFeaturesDeactivator {
+
+    private final ISensorTestStateContainer mStateContainer;
+
+    private final SensorSettingContainer mAirplaneMode = new AirplaneModeSettingContainer();
+    private final SensorSettingContainer mScreenBrightnessMode =
+            new ScreenBrightnessModeSettingContainer();
+    private final SensorSettingContainer mAmbientDisplayMode = new AmbientDisplaySettingContainer();
+    private final SensorSettingContainer mAutoRotateScreenMode =
+            new AutoRotateScreenModeSettingContainer();
+    private final SensorSettingContainer mKeepScreenOnMode = new KeepScreenOnModeSettingContainer();
+    private final SensorSettingContainer mLocationMode = new LocationModeSettingContainer();
+
+    public SensorFeaturesDeactivator(ISensorTestStateContainer stateContainer) {
+        mStateContainer = stateContainer;
+    }
+
+    public synchronized void requestDeactivationOfFeatures() throws InterruptedException {
+        captureInitialState();
+
+        mAirplaneMode.requestToSetMode(mStateContainer, true);
+        mScreenBrightnessMode.requestToSetMode(mStateContainer, false);
+        mAmbientDisplayMode.requestToSetMode(mStateContainer, false);
+        mAutoRotateScreenMode.requestToSetMode(mStateContainer, false);
+        mKeepScreenOnMode.requestToSetMode(mStateContainer, false);
+        mLocationMode.requestToSetMode(mStateContainer, false);
+
+        // TODO: find a way to find out if there are clients still registered at this time
+        mStateContainer.getTestLogger()
+                .logInstructions(R.string.snsr_sensor_feature_deactivation);
+        mStateContainer.waitForUserToContinue();
+    }
+
+    public synchronized void requestToRestoreFeatures() throws InterruptedException {
+        if (Thread.currentThread().isInterrupted()) {
+            // TODO: in the future, if the thread is interrupted, we might need to serialize the
+            //       intermediate state we acquired so we can restore when we have a chance
+            return;
+        }
+
+        mAirplaneMode.requestToResetMode(mStateContainer);
+        mScreenBrightnessMode.requestToResetMode(mStateContainer);
+        mAmbientDisplayMode.requestToResetMode(mStateContainer);
+        mAutoRotateScreenMode.requestToResetMode(mStateContainer);
+        mKeepScreenOnMode.requestToResetMode(mStateContainer);
+        mLocationMode.requestToResetMode(mStateContainer);
+    }
+
+    private void captureInitialState() {
+        mAirplaneMode.captureInitialState();
+        mScreenBrightnessMode.captureInitialState();
+        mAmbientDisplayMode.captureInitialState();
+        mAutoRotateScreenMode.captureInitialState();
+        mLocationMode.captureInitialState();
+        mKeepScreenOnMode.captureInitialState();
+    }
+
+    private class AirplaneModeSettingContainer extends SensorSettingContainer {
+        public AirplaneModeSettingContainer() {
+            super(Settings.ACTION_WIRELESS_SETTINGS, R.string.snsr_setting_airplane_mode);
+        }
+
+        @Override
+        protected int getSettingMode(int defaultValue) {
+            ContentResolver contentResolver = mStateContainer.getContentResolver();
+            // Settings.System.AIRPLANE_MODE_ON is deprecated in API 17
+            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
+                return Settings.System
+                        .getInt(contentResolver, Settings.System.AIRPLANE_MODE_ON, defaultValue);
+            } else {
+                return Settings.Global
+                        .getInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, defaultValue);
+            }
+        }
+    }
+
+    private class ScreenBrightnessModeSettingContainer extends SensorSettingContainer {
+        public ScreenBrightnessModeSettingContainer() {
+            super(Settings.ACTION_DISPLAY_SETTINGS, R.string.snsr_setting_screen_brightness_mode);
+        }
+
+        @Override
+        public int getSettingMode(int defaultValue) {
+            return Settings.System.getInt(
+                    mStateContainer.getContentResolver(),
+                    Settings.System.SCREEN_BRIGHTNESS_MODE,
+                    defaultValue);
+        }
+    }
+
+    private class AmbientDisplaySettingContainer extends SensorSettingContainer {
+        public AmbientDisplaySettingContainer() {
+            super(Settings.ACTION_DISPLAY_SETTINGS, R.string.snsr_setting_ambient_display);
+        }
+
+        @Override
+        protected int getSettingMode(int defaultValue) {
+            // TODO: replace the use of reflection with Settings.Secure.DOZE_ENABLED when the
+            //       static field is not hidden anymore
+            Class<?> secureSettingsClass = Settings.Secure.class;
+            Field dozeEnabledField;
+            try {
+                dozeEnabledField = secureSettingsClass.getField("DOZE_ENABLED");
+            } catch (NoSuchFieldException e) {
+                return defaultValue;
+            }
+
+            String settingName;
+            try {
+                settingName = (String) dozeEnabledField.get(null /* obj */);
+            } catch (IllegalAccessException e) {
+                return defaultValue;
+            }
+
+            return Settings.Secure.getInt(
+                    mStateContainer.getContentResolver(),
+                    settingName,
+                    defaultValue);
+        }
+    }
+
+    private class AutoRotateScreenModeSettingContainer extends SensorSettingContainer {
+        public AutoRotateScreenModeSettingContainer() {
+            super(Settings.ACTION_ACCESSIBILITY_SETTINGS,
+                    R.string.snsr_setting_auto_rotate_screen_mode);
+        }
+
+        @Override
+        protected int getSettingMode(int defaultValue) {
+            return Settings.System.getInt(
+                    mStateContainer.getContentResolver(),
+                    Settings.System.ACCELEROMETER_ROTATION,
+                    defaultValue);
+        }
+    }
+
+    private class KeepScreenOnModeSettingContainer extends SensorSettingContainer {
+        public KeepScreenOnModeSettingContainer() {
+            super(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS,
+                    R.string.snsr_setting_keep_screen_on);
+        }
+
+        @Override
+        protected int getSettingMode(int defaultValue) {
+            return Settings.Global.getInt(
+                    mStateContainer.getContentResolver(),
+                    Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
+                    defaultValue);
+        }
+    }
+
+    private class LocationModeSettingContainer extends SensorSettingContainer {
+        public LocationModeSettingContainer() {
+            super(Settings.ACTION_LOCATION_SOURCE_SETTINGS, R.string.snsr_setting_location_mode);
+        }
+
+        @Override
+        protected int getSettingMode(int defaultValue) {
+            return Settings.Secure.getInt(
+                    mStateContainer.getContentResolver(),
+                    Settings.Secure.LOCATION_MODE,
+                    defaultValue);
+        }
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorSettingContainer.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorSettingContainer.java
new file mode 100644
index 0000000..2d44d8d
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorSettingContainer.java
@@ -0,0 +1,111 @@
+/*
+ * 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 com.android.cts.verifier.sensors.helpers;
+
+import com.android.cts.verifier.R;
+import com.android.cts.verifier.sensors.base.BaseSensorTestActivity;
+import com.android.cts.verifier.sensors.base.ISensorTestStateContainer;
+
+/**
+ * A helper class for {@link SensorFeaturesDeactivator}. It abstracts the responsibility of handling
+ * device settings that affect sensors.
+ *
+ * This class is meant to be used only by {@link SensorFeaturesDeactivator}.
+ * To keep things simple, this class synchronizes access to its internal state on public methods.
+ * This approach is fine, because there is no need for concurrent access.
+ */
+abstract class SensorSettingContainer {
+    private static final int DEFAULT_SETTING_VALUE = -1;
+
+    private final String mAction;
+    private final int mSettingNameResId;
+
+    private boolean mInitialized;
+    private boolean mSettingAvailable;
+    private boolean mCapturedModeOn;
+
+    public SensorSettingContainer(String action, int settingNameResId) {
+        mAction = action;
+        mSettingNameResId = settingNameResId;
+    }
+
+    public synchronized void captureInitialState() {
+        if (mInitialized) {
+            return;
+        }
+        mSettingAvailable = getSettingMode(DEFAULT_SETTING_VALUE) != DEFAULT_SETTING_VALUE;
+        mCapturedModeOn = getCurrentSettingMode();
+        mInitialized = true;
+    }
+
+    public synchronized void requestToSetMode(
+            ISensorTestStateContainer stateContainer,
+            boolean modeOn) throws InterruptedException {
+        if (!isSettingAvailable()) {
+            return;
+        }
+        trySetMode(stateContainer, modeOn);
+        if (getCurrentSettingMode() != modeOn) {
+            String message = stateContainer.getString(
+                    R.string.snsr_setting_mode_not_set,
+                    getSettingName(stateContainer),
+                    modeOn);
+            throw new IllegalStateException(message);
+        }
+    }
+
+    public synchronized void requestToResetMode(ISensorTestStateContainer stateContainer)
+            throws InterruptedException {
+        if (!isSettingAvailable()) {
+            return;
+        }
+        trySetMode(stateContainer, mCapturedModeOn);
+    }
+
+    private void trySetMode(ISensorTestStateContainer stateContainer, boolean modeOn)
+            throws InterruptedException {
+        BaseSensorTestActivity.SensorTestLogger logger = stateContainer.getTestLogger();
+        String settingName = getSettingName(stateContainer);
+        if (getCurrentSettingMode() == modeOn) {
+            logger.logMessage(R.string.snsr_setting_mode_set, settingName, modeOn);
+            return;
+        }
+
+        logger.logInstructions(R.string.snsr_setting_mode_request, settingName, modeOn);
+        logger.logInstructions(R.string.snsr_on_complete_return);
+        stateContainer.waitForUserToContinue();
+        stateContainer.executeActivity(mAction);
+    }
+
+    private boolean getCurrentSettingMode() {
+        return getSettingMode(DEFAULT_SETTING_VALUE) != 0;
+    }
+
+    private String getSettingName(ISensorTestStateContainer stateContainer) {
+        return stateContainer.getString(mSettingNameResId);
+    }
+
+    private boolean isSettingAvailable() {
+        if (!mInitialized) {
+            throw new IllegalStateException(
+                    "Object must be initialized first by invoking #captureInitialState.");
+        }
+        return mSettingAvailable;
+    }
+
+    protected abstract int getSettingMode(int defaultValue);
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorTestScreenManipulator.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorTestScreenManipulator.java
new file mode 100644
index 0000000..835ff56
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorTestScreenManipulator.java
@@ -0,0 +1,207 @@
+/*
+ * 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 com.android.cts.verifier.sensors.helpers;
+
+import com.android.cts.verifier.sensors.base.BaseSensorTestActivity;
+import com.android.cts.verifier.sensors.base.ISensorTestStateContainer;
+
+import android.app.Activity;
+import android.app.admin.DeviceAdminInfo;
+import android.app.admin.DevicePolicyManager;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.PowerManager;
+import android.text.TextUtils;
+
+/**
+ * A class that provides functionality to manipulate the state of the device's screen.
+ *
+ * The implementation uses a simple state machine with 3 states: keep-screen-off, keep-screen-on,
+ * and a free-state where the class does not affect the system's state.
+ *
+ * The list of transitions and their handlers are:
+ *      keep-screen-on --(turnScreenOff)--> keep-screen-off
+ *      keep-screen-on --(releaseScreenOn)--> free-state
+ *
+ *      keep-screen-off --(turnScreenOn)--> keep-screen-on
+ *      keep-screen-off --(wakeUpScreen)--> free-state
+ *
+ *      free-state --(turnScreenOff)--> keep-screen-off
+ *      free-state --(turnScreenOn)--> keep-screen-on
+ *
+ * NOTES:
+ * - the operator still can turn on/off the screen by pressing the power button
+ * - this class must be used by a single client, that can manage the state of the instance, likely
+ * - in a single-threaded environment
+ */
+public class SensorTestScreenManipulator {
+
+    private final Context mContext;
+    private final DevicePolicyManager mDevicePolicyManager;
+    private final ComponentName mComponentName;
+    private final PowerManager.WakeLock mWakeUpScreenWakeLock;
+    private final PowerManager.WakeLock mKeepScreenOnWakeLock;
+
+    private InternalBroadcastReceiver mBroadcastReceiver;
+    private boolean mTurnOffScreenOnPowerDisconnected;
+
+    public SensorTestScreenManipulator(Context context) {
+        mContext = context;
+        mComponentName = SensorDeviceAdminReceiver.getComponentName(context);
+        mDevicePolicyManager =
+                (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
+
+        int levelAndFlags = PowerManager.FULL_WAKE_LOCK
+                | PowerManager.ON_AFTER_RELEASE
+                | PowerManager.ACQUIRE_CAUSES_WAKEUP;
+        PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+        mWakeUpScreenWakeLock = powerManager.newWakeLock(levelAndFlags, "SensorTestWakeUpScreen");
+        mWakeUpScreenWakeLock.setReferenceCounted(false);
+        mKeepScreenOnWakeLock = powerManager.newWakeLock(levelAndFlags, "SensorTestKeepScreenOn");
+        mWakeUpScreenWakeLock.setReferenceCounted(false);
+    }
+
+    /**
+     * Initializes the current instance.
+     * Initialization should usually happen inside {@link BaseSensorTestActivity#activitySetUp}.
+     *
+     * NOTE: Initialization will bring up an Activity to let the user activate the Device Admin,
+     * this method will block until the user completes the operation.
+     */
+    public synchronized void initialize(ISensorTestStateContainer stateContainer)
+            throws InterruptedException {
+        if (!isDeviceAdminInitialized()) {
+            Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
+            intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mComponentName);
+            int resultCode = stateContainer.executeActivity(intent);
+            if (resultCode != Activity.RESULT_OK) {
+                throw new IllegalStateException(
+                        "Test cannot execute without Activating the Device Administrator.");
+            }
+        }
+
+        if (mBroadcastReceiver == null) {
+            mBroadcastReceiver = new InternalBroadcastReceiver();
+            IntentFilter intentFilter = new IntentFilter();
+            intentFilter.addAction(Intent.ACTION_POWER_DISCONNECTED);
+            mContext.registerReceiver(mBroadcastReceiver, intentFilter);
+        }
+    }
+
+    /**
+     * Closes the current instance.
+     * This operation should usually happen inside {@link BaseSensorTestActivity#activityCleanUp}.
+     */
+    public synchronized  void close() {
+        if (mBroadcastReceiver != null) {
+            mContext.unregisterReceiver(mBroadcastReceiver);
+            mBroadcastReceiver = null;
+        }
+    }
+
+    /**
+     * Instruct the device to turn off the screen immediately.
+     */
+    public synchronized void turnScreenOff() {
+        ensureDeviceAdminInitialized();
+        releaseScreenOn();
+        mDevicePolicyManager.lockNow();
+    }
+
+    /**
+     * Instruct the device to wake up the screen immediately, the screen will remain on for a bit,
+     * but the system might turn the screen off in the near future.
+     */
+    public synchronized void wakeUpScreen() {
+        mWakeUpScreenWakeLock.acquire();
+        // release right away, the screen still remains on for a bit, but not indefinitely
+        mWakeUpScreenWakeLock.release();
+    }
+
+    /**
+     * Instructs the device to turn on the screen immediately.
+     *
+     * The screen will remain on until the client invokes {@link #releaseScreenOn()}, or the user
+     * presses the device's power button.
+     */
+    public synchronized void turnScreenOn() {
+        if (mKeepScreenOnWakeLock.isHeld()) {
+            // recover from cases when we could get out of sync, this can happen because the user
+            // can press the power button, and other wake-locks can prevent intents to be received
+            mKeepScreenOnWakeLock.release();
+        }
+        mKeepScreenOnWakeLock.acquire();
+    }
+
+    /**
+     * Indicates that the client does not require the screen to remain on anymore.
+     *
+     * See {@link #turnScreenOn()} for more information.
+     */
+    public synchronized void releaseScreenOn() {
+        if (!mKeepScreenOnWakeLock.isHeld()) {
+            return;
+        }
+        mKeepScreenOnWakeLock.release();
+    }
+
+    /**
+     * Queues a request to turn off the screen off when the device has been disconnected from a
+     * power source (usually upon USB disconnected).
+     *
+     * (It is useful for Sensor Power Tests, as the Power Monitor usually detaches itself from the
+     * device before beginning to sample data).
+     */
+    public synchronized void turnScreenOffOnNextPowerDisconnect() {
+        ensureDeviceAdminInitialized();
+        mTurnOffScreenOnPowerDisconnected = true;
+    }
+
+    private void ensureDeviceAdminInitialized() throws IllegalStateException {
+        if (!isDeviceAdminInitialized()) {
+            throw new IllegalStateException("Component must be initialized before it can be used.");
+        }
+    }
+
+    private boolean isDeviceAdminInitialized() {
+        if (!mDevicePolicyManager.isAdminActive(mComponentName)) {
+            return false;
+        }
+        return mDevicePolicyManager
+                .hasGrantedPolicy(mComponentName, DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
+    }
+
+    private class InternalBroadcastReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+
+            if (TextUtils.equals(action, Intent.ACTION_POWER_DISCONNECTED)) {
+                if (mTurnOffScreenOnPowerDisconnected) {
+                    turnScreenOff();
+                    // reset the flag after it has triggered once, we try to avoid cases when the test
+                    // might leave the receiver enabled after itself,
+                    // this approach still provides a way to multiplex one time requests
+                    mTurnOffScreenOnPowerDisconnected = false;
+                }
+            }
+        }
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/renderers/GLArrowSensorTestRenderer.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/renderers/GLArrowSensorTestRenderer.java
new file mode 100644
index 0000000..f2f33c1
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/renderers/GLArrowSensorTestRenderer.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.sensors.renderers;
+
+import com.android.cts.verifier.R;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.opengl.GLSurfaceView;
+import android.opengl.GLU;
+import android.opengl.GLUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+/**
+ * Renders a wedge to indicate the direction of sensor data.
+ */
+public class GLArrowSensorTestRenderer implements GLSurfaceView.Renderer, SensorEventListener {
+    // A representation of the Z-axis in vector form.
+    private static final float[] Z_AXIS = new float[] {0, 0, 1};
+
+    // The (pseudo)vector around which to rotate to align Z-axis with gravity.
+    private final float[] mCrossProd = new float[3];
+    private final float[] mRotationMatrix = new float[16];
+
+    private final int mSensorType;
+    private final Context mContext;
+    private final Wedge mWedge;
+
+    // The angle around mCrossProd to rotate to align Z-axis with gravity.
+    private float mAngle;
+    private int mTextureID;
+
+    /**
+     * It's a constructor. Can you dig it?
+     *
+     * @param context the Android Context that owns this renderer
+     * @param type of arrow. Possible values: 0 = points towards gravity. 1 =
+     *            points towards reference North
+     */
+    public GLArrowSensorTestRenderer(Context context, int type) {
+        mContext = context;
+        mSensorType = type;
+        mWedge = new Wedge(mSensorType);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onDrawFrame(GL10 gl) {
+        // set up the texture for drawing
+        gl.glTexEnvx(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_MODULATE);
+        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
+        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
+        gl.glActiveTexture(GL10.GL_TEXTURE0);
+        gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
+        gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
+        gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
+
+        // clear the screen and draw
+        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+        gl.glMatrixMode(GL10.GL_MODELVIEW);
+        gl.glLoadIdentity();
+
+        if (mSensorType == Sensor.TYPE_ACCELEROMETER) {
+            gl.glRotatef(
+                    -mAngle * 180 / (float) Math.PI,
+                    mCrossProd[0],
+                    mCrossProd[1],
+                    mCrossProd[2]);
+        } else {
+            gl.glMultMatrixf(mRotationMatrix, 0);
+        }
+        mWedge.draw(gl);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onSurfaceChanged(GL10 gl, int w, int h) {
+        gl.glViewport(0, 0, w, h);
+        float ratio = (float) w / h;
+        gl.glMatrixMode(GL10.GL_PROJECTION);
+        gl.glLoadIdentity();
+        gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7);
+        GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+        // set up general OpenGL config
+        gl.glClearColor(0.6f, 0f, 0.4f, 1); // a nice purpley magenta
+        gl.glShadeModel(GL10.GL_SMOOTH);
+        gl.glEnable(GL10.GL_DEPTH_TEST);
+        gl.glEnable(GL10.GL_TEXTURE_2D);
+
+        // create the texture we use on the wedge
+        int[] textures = new int[1];
+        gl.glGenTextures(1, textures, 0);
+        mTextureID = textures[0];
+
+        gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
+        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
+        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
+        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
+        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
+        gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_REPLACE);
+
+        InputStream is = mContext.getResources().openRawResource(R.raw.sns_texture);
+        Bitmap bitmap;
+        try {
+            bitmap = BitmapFactory.decodeStream(is);
+        } finally {
+            try {
+                is.close();
+            } catch (IOException e) {
+                // Ignore.
+            }
+        }
+
+        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
+        bitmap.recycle();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onAccuracyChanged(Sensor arg0, int arg1) {
+        // no-op
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onSensorChanged(SensorEvent event) {
+        int type = event.sensor.getType();
+        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
+            /*
+             * For this test we want *only* accelerometer data, so we can't use
+             * the convenience methods on SensorManager; so compute manually.
+             */
+            normalize(event.values);
+
+            /*
+             * Because we need to invert gravity (because the accelerometer
+             * vector actually points up), that constitutes a 180-degree
+             * rotation around X, which means we need to invert Y.
+             */
+            event.values[1] *= -1;
+
+            crossProduct(event.values, Z_AXIS, mCrossProd);
+            mAngle = (float) Math.acos(dotProduct(event.values, Z_AXIS));
+        } else if (type == Sensor.TYPE_ROTATION_VECTOR
+                || type == Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR
+                || type == Sensor.TYPE_GAME_ROTATION_VECTOR) {
+            float[] rotationMatrixTmp = new float[16];
+
+            SensorManager.getRotationMatrixFromVector(rotationMatrixTmp, event.values);
+            SensorManager.remapCoordinateSystem(rotationMatrixTmp,
+                    SensorManager.AXIS_MINUS_X, SensorManager.AXIS_Y, mRotationMatrix);
+        }
+
+    }
+
+    /**
+     * Computes the cross product of two vectors, storing the resulting pseudo-vector in out. All
+     * arrays must be length 3 or more, and out is overwritten.
+     *
+     * @param left the left operand of the cross product
+     * @param right the right operand of the cross product
+     * @param out the array into which to store the cross-product pseudo-vector's data
+     */
+    public static void crossProduct(float[] left, float[] right, float[] out) {
+        out[0] = left[1] * right[2] - left[2] * right[1];
+        out[1] = left[2] * right[0] - left[0] * right[2];
+        out[2] = left[0] * right[1] - left[1] * right[0];
+    }
+
+    /**
+     * Computes the dot product of two vectors.
+     *
+     * @param left the first dot product operand
+     * @param right the second dot product operand
+     * @return the dot product of left and right
+     */
+    public static float dotProduct(float[] left, float[] right) {
+        return left[0] * right[0] + left[1] * right[1] + left[2] * right[2];
+    }
+
+    /**
+     * Normalizes the input vector into a unit vector.
+     *
+     * @param vector the vector to normalize. Contents are overwritten.
+     */
+    public static void normalize(float[] vector) {
+        double mag = Math.sqrt(vector[0] * vector[0] + vector[1] * vector[1] + vector[2]
+                * vector[2]);
+        vector[0] /= mag;
+        vector[1] /= mag;
+        vector[2] /= mag;
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/renderers/GLRotationGuideRenderer.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/renderers/GLRotationGuideRenderer.java
new file mode 100644
index 0000000..6f2109f
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/renderers/GLRotationGuideRenderer.java
@@ -0,0 +1,113 @@
+/*
+ * 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 com.android.cts.verifier.sensors.renderers;
+
+import android.opengl.GLSurfaceView;
+import android.opengl.GLU;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+/**
+ * Renders a spinning block to indicate how the device should be rotated in the test.
+ */
+public class GLRotationGuideRenderer implements GLSurfaceView.Renderer {
+    public static final int BACKGROUND_BLACK = 0;
+    public static final int BACKGROUND_RED = 1;
+    public static final int BACKGROUND_GREEN = 2;
+    private static final double ANGLE_INCREMENT = 1.0;
+
+    private final Monolith mMonolith = new Monolith();
+    private final AtomicInteger mBackgroundColor = new AtomicInteger(BACKGROUND_BLACK);
+
+    private float mAngle;
+    private float mRotateX;
+    private float mRotateY;
+    private float mRotateZ;
+
+    /**
+     * Sets the rotation of the monolith.
+     */
+    public void setRotation(float rotateX, float rotateY, float rotateZ) {
+        mRotateX = rotateX;
+        mRotateY = rotateY;
+        mRotateZ = rotateZ;
+    }
+
+    /**
+     * Sets the background color.
+     */
+    public void setBackgroundColor(int value) {
+        mBackgroundColor.set(value);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onDrawFrame(GL10 gl) {
+        clearBackground(gl);
+        gl.glMatrixMode(GL10.GL_MODELVIEW);
+        gl.glLoadIdentity();
+        gl.glRotatef(mAngle, mRotateX, mRotateY, mRotateZ);
+        mMonolith.draw(gl);
+        mAngle += ANGLE_INCREMENT;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onSurfaceChanged(GL10 gl, int width, int height) {
+        gl.glViewport(0, 0, width, height);
+        gl.glMatrixMode(GL10.GL_PROJECTION);
+        gl.glLoadIdentity();
+        float ratio = (float) width / height;
+        gl.glFrustumf(-ratio, ratio, -1, 1, 3, 15);
+        GLU.gluLookAt(gl, 0, 0, 10, 0, 0, 0, 0, 1, 0);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
+        gl.glEnable(GL10.GL_LIGHTING);
+        gl.glEnable(GL10.GL_LIGHT0);
+        gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, new float[] {0.75f, 0.75f, 0.75f, 1f}, 0);
+    }
+
+    private void clearBackground(GL10 gl) {
+        switch (mBackgroundColor.get()) {
+            case BACKGROUND_GREEN:
+                gl.glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+                break;
+
+            case BACKGROUND_RED:
+                gl.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+                break;
+
+            default:
+                gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+                break;
+        }
+        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/renderers/Monolith.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/renderers/Monolith.java
new file mode 100644
index 0000000..56e230d
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/renderers/Monolith.java
@@ -0,0 +1,118 @@
+/*
+ * 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 com.android.cts.verifier.sensors.renderers;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
+
+import javax.microedition.khronos.opengles.GL10;
+
+/**
+ * Rectangular block that is rotated by {@link GLRotationGuideRenderer}.
+ */
+class Monolith {
+    private static final int NUM_VERTICES = 8;
+    private static final int NUM_INDICES = 36;
+
+    private final FloatBuffer mVertexBuffer;
+    private final ShortBuffer mIndexBuffer;
+
+    public Monolith() {
+        mVertexBuffer = ByteBuffer.allocateDirect(NUM_VERTICES * 3 * 4)
+                .order(ByteOrder.nativeOrder())
+                .asFloatBuffer();
+
+        float[] coordinates = {
+                -0.65f, -1, 0.2f,
+                -0.65f, 1, 0.2f,
+                0.65f, 1, 0.2f,
+                0.65f, -1, 0.2f,
+
+                -0.65f, -1, -0.2f,
+                -0.65f, 1, -0.2f,
+                0.65f, 1, -0.2f,
+                0.65f, -1, -0.2f,
+        };
+
+        for (int i = 0; i < coordinates.length; i++) {
+            mVertexBuffer.put(coordinates[i]);
+        }
+
+        mIndexBuffer = ByteBuffer.allocateDirect(NUM_INDICES * 2)
+                .order(ByteOrder.nativeOrder())
+                .asShortBuffer();
+
+        // Front
+        mIndexBuffer.put((short) 0);
+        mIndexBuffer.put((short) 1);
+        mIndexBuffer.put((short) 2);
+        mIndexBuffer.put((short) 0);
+        mIndexBuffer.put((short) 2);
+        mIndexBuffer.put((short) 3);
+
+        // Back
+        mIndexBuffer.put((short) 7);
+        mIndexBuffer.put((short) 6);
+        mIndexBuffer.put((short) 5);
+        mIndexBuffer.put((short) 7);
+        mIndexBuffer.put((short) 5);
+        mIndexBuffer.put((short) 4);
+
+        // Right
+        mIndexBuffer.put((short) 3);
+        mIndexBuffer.put((short) 2);
+        mIndexBuffer.put((short) 6);
+        mIndexBuffer.put((short) 3);
+        mIndexBuffer.put((short) 6);
+        mIndexBuffer.put((short) 7);
+
+        // Left
+        mIndexBuffer.put((short) 4);
+        mIndexBuffer.put((short) 5);
+        mIndexBuffer.put((short) 1);
+        mIndexBuffer.put((short) 4);
+        mIndexBuffer.put((short) 1);
+        mIndexBuffer.put((short) 0);
+
+        // Top
+        mIndexBuffer.put((short) 1);
+        mIndexBuffer.put((short) 5);
+        mIndexBuffer.put((short) 6);
+        mIndexBuffer.put((short) 1);
+        mIndexBuffer.put((short) 6);
+        mIndexBuffer.put((short) 2);
+
+        // Bottom
+        mIndexBuffer.put((short) 3);
+        mIndexBuffer.put((short) 7);
+        mIndexBuffer.put((short) 4);
+        mIndexBuffer.put((short) 3);
+        mIndexBuffer.put((short) 4);
+        mIndexBuffer.put((short) 0);
+
+        mVertexBuffer.position(0);
+        mIndexBuffer.position(0);
+    }
+
+    public void draw(GL10 gl) {
+        gl.glColor4f(0.5f, 0.5f, 0.5f, 1f);
+        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);
+        gl.glDrawElements(GL10.GL_TRIANGLES, NUM_INDICES, GL10.GL_UNSIGNED_SHORT, mIndexBuffer);
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/renderers/Wedge.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/renderers/Wedge.java
new file mode 100644
index 0000000..bee75d6
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/renderers/Wedge.java
@@ -0,0 +1,146 @@
+/*
+ * 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 com.android.cts.verifier.sensors.renderers;
+
+import android.hardware.Sensor;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.ShortBuffer;
+
+import javax.microedition.khronos.opengles.GL10;
+
+/**
+ * A representation of a 3D triangular wedge or arrowhead shape, suitable for pointing a direction.
+ */
+class Wedge {
+    private final static int VERTS = 6;
+
+    // Storage for the vertices.
+    private final FloatBuffer mFVertexBuffer;
+
+    // Storage for the drawing sequence of the vertices. This contains integer indices into the
+    // mFVertextBuffer structure.
+    private final ShortBuffer mIndexBuffer;
+
+    // Storage for the texture used on the surface of the wedge.
+    private final FloatBuffer mTexBuffer;
+
+    public Wedge(int sensorType) {
+        // Buffers to be passed to gl*Pointer() functions
+        // must be direct & use native ordering
+
+        ByteBuffer vbb = ByteBuffer.allocateDirect(VERTS * 6 * 4);
+        vbb.order(ByteOrder.nativeOrder());
+        mFVertexBuffer = vbb.asFloatBuffer();
+
+        ByteBuffer tbb = ByteBuffer.allocateDirect(VERTS * 2 * 4);
+        tbb.order(ByteOrder.nativeOrder());
+        mTexBuffer = tbb.asFloatBuffer();
+
+        ByteBuffer ibb = ByteBuffer.allocateDirect(VERTS * 8 * 2);
+        ibb.order(ByteOrder.nativeOrder());
+        mIndexBuffer = ibb.asShortBuffer();
+
+        // Coordinates of the vertices making up a simple wedge. Six total vertices, representing
+        // two isosceles triangles, side by side, centered on the origin separated by 0.25 units,
+        // with elongated ends pointing down the negative Z axis.
+        float[] coords;
+        if (sensorType == Sensor.TYPE_ACCELEROMETER) {
+            float[] verts = {
+                    // X, Y, Z
+                    -0.125f, -0.25f, -0.25f,
+                    -0.125f, 0.25f, -0.25f,
+                    -0.125f, 0.0f, 0.559016994f,
+                    0.125f, -0.25f, -0.25f,
+                    0.125f, 0.25f, -0.25f,
+                    0.125f, 0.0f, 0.559016994f,
+            };
+            coords = verts.clone();
+        } else {
+            float[] verts = {
+                    // X, Y, Z
+                    -0.25f, -0.25f, -0.125f,
+                    -0.25f, 0.25f, -0.125f,
+                    0.559016994f, 0.0f, -0.125f,
+                    -0.25f, -0.25f, 0.125f,
+                    -0.25f, 0.25f, 0.125f,
+                    0.559016994f, 0.0f, 0.125f,
+            };
+            coords = verts.clone();
+        }
+
+        for (int i = 0; i < VERTS; i++) {
+            for (int j = 0; j < 3; j++) {
+                mFVertexBuffer.put(coords[i * 3 + j] * 2.0f);
+            }
+        }
+
+        for (int i = 0; i < VERTS; i++) {
+            for (int j = 0; j < 2; j++) {
+                mTexBuffer.put(coords[i * 3 + j] * 2.0f + 0.5f);
+            }
+        }
+
+        // left face
+        mIndexBuffer.put((short) 0);
+        mIndexBuffer.put((short) 1);
+        mIndexBuffer.put((short) 2);
+
+        // right face
+        mIndexBuffer.put((short) 5);
+        mIndexBuffer.put((short) 4);
+        mIndexBuffer.put((short) 3);
+
+        // top side, 2 triangles to make rect
+        mIndexBuffer.put((short) 2);
+        mIndexBuffer.put((short) 5);
+        mIndexBuffer.put((short) 3);
+        mIndexBuffer.put((short) 3);
+        mIndexBuffer.put((short) 0);
+        mIndexBuffer.put((short) 2);
+
+        // bottom side, 2 triangles to make rect
+        mIndexBuffer.put((short) 5);
+        mIndexBuffer.put((short) 2);
+        mIndexBuffer.put((short) 1);
+        mIndexBuffer.put((short) 1);
+        mIndexBuffer.put((short) 4);
+        mIndexBuffer.put((short) 5);
+
+        // base, 2 triangles to make rect
+        mIndexBuffer.put((short) 0);
+        mIndexBuffer.put((short) 3);
+        mIndexBuffer.put((short) 4);
+        mIndexBuffer.put((short) 4);
+        mIndexBuffer.put((short) 1);
+        mIndexBuffer.put((short) 0);
+
+        mFVertexBuffer.position(0);
+        mTexBuffer.position(0);
+        mIndexBuffer.position(0);
+    }
+
+    public void draw(GL10 gl) {
+        gl.glFrontFace(GL10.GL_CCW);
+        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mFVertexBuffer);
+        gl.glEnable(GL10.GL_TEXTURE_2D);
+        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTexBuffer);
+        gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 24, GL10.GL_UNSIGNED_SHORT, mIndexBuffer);
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/reporting/SensorTestDetails.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/reporting/SensorTestDetails.java
new file mode 100644
index 0000000..c88187c
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/reporting/SensorTestDetails.java
@@ -0,0 +1,113 @@
+/*
+
+ * 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 com.android.cts.verifier.sensors.reporting;
+
+import com.android.cts.verifier.R;
+
+import org.junit.runner.Result;
+
+import android.content.Context;
+import android.hardware.cts.helpers.SensorTestStateNotSupportedException;
+
+/**
+ * A class that holds the result of a Sensor test execution.
+ */
+public class SensorTestDetails {
+    private final String mName;
+    private final ResultCode mResultCode;
+    private final String mSummary;
+
+    public enum ResultCode {
+        SKIPPED,
+        PASS,
+        FAIL,
+        INTERRUPTED
+    }
+
+    public SensorTestDetails(String name, ResultCode resultCode) {
+        this(name, resultCode, null /* summary */);
+    }
+
+    public SensorTestDetails(String name, ResultCode resultCode, String summary) {
+        mName = name;
+        mResultCode = resultCode;
+        mSummary = summary;
+    }
+
+    public SensorTestDetails(
+            Context context,
+            String name,
+            int passCount,
+            int skipCount,
+            int failCount) {
+        ResultCode resultCode = ResultCode.PASS;
+        if (failCount > 0) {
+            resultCode = ResultCode.FAIL;
+        } else if (skipCount > 0) {
+            resultCode = ResultCode.SKIPPED;
+        }
+
+        mName = name;
+        mResultCode = resultCode;
+        mSummary = context.getString(R.string.snsr_test_summary, passCount, skipCount, failCount);
+    }
+
+    public SensorTestDetails(Context context, String name, Result result) {
+        this(context,
+                name,
+                result.getRunCount() - result.getFailureCount() - result.getIgnoreCount(),
+                result.getIgnoreCount(),
+                result.getFailureCount());
+    }
+
+    public SensorTestDetails(String name, String tag, Throwable cause) {
+        ResultCode resultCode = ResultCode.FAIL;
+        if (cause instanceof InterruptedException) {
+            resultCode = ResultCode.INTERRUPTED;
+            // the interrupted status must be restored, so other routines can consume it
+            Thread.currentThread().interrupt();
+        } else if (cause instanceof SensorTestStateNotSupportedException) {
+            resultCode = ResultCode.SKIPPED;
+        }
+
+        mName = name;
+        mResultCode = resultCode;
+        mSummary = String.format("[%s] %s", tag, cause.getMessage());
+    }
+
+    public String getName() {
+        return mName;
+    }
+
+    public ResultCode getResultCode() {
+        return mResultCode;
+    }
+
+    public String getSummary() {
+        return mSummary;
+    }
+
+    public SensorTestDetails cloneAndChangeResultCode(ResultCode resultCode) {
+        return new SensorTestDetails(mName, resultCode, mSummary);
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s|%s|%s", mName, mResultCode.name(), mSummary);
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/streamquality/PlayVideoActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/streamquality/PlayVideoActivity.java
index 369d32c..b8d8c30 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/streamquality/PlayVideoActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/streamquality/PlayVideoActivity.java
@@ -118,8 +118,7 @@
                         .setNegativeButton("Close", new OnClickListener() {
                             @Override
                             public void onClick(DialogInterface dialog, int which) {
-                                PassFailButtons.setTestResultAndFinish(PlayVideoActivity.this,
-                                        getTestId(), null, false);
+                                setTestResultAndFinish(false);
                             }
                         })
                         .show();
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 acf1018..9684d97 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/streamquality/StreamingVideoActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/streamquality/StreamingVideoActivity.java
@@ -169,8 +169,7 @@
                         .setNegativeButton("Close", new OnClickListener() {
                             @Override
                             public void onClick(DialogInterface dialog, int which) {
-                                PassFailButtons.setTestResultAndFinish(StreamingVideoActivity.this,
-                                        getTestId(), null, false);
+                                setTestResultAndFinish(false);
                             }
                         }).show();
             default:
diff --git a/apps/cts-usb-accessory/Android.mk b/apps/cts-usb-accessory/Android.mk
index 76022a1..8d18da3 100644
--- a/apps/cts-usb-accessory/Android.mk
+++ b/apps/cts-usb-accessory/Android.mk
@@ -28,7 +28,7 @@
 
 LOCAL_C_INCLUDES += \
 	bionic/libc/kernel/uapi \
-	bionic/libc/kernel/uapi/asm-$(HOST_ARCH) \
+	bionic/libc/kernel/uapi/asm-x86 \
 
 LOCAL_STATIC_LIBRARIES := libusbhost libcutils
 LOCAL_LDLIBS += -lpthread
diff --git a/build/config.mk b/build/config.mk
index b737ef7..931220b 100644
--- a/build/config.mk
+++ b/build/config.mk
@@ -16,4 +16,6 @@
 BUILD_CTS_PACKAGE := cts/build/test_package.mk
 BUILD_CTS_GTEST_PACKAGE := cts/build/test_gtest_package.mk
 BUILD_CTS_HOST_JAVA_LIBRARY := cts/build/test_host_java_library.mk
+BUILD_CTS_TARGET_JAVA_LIBRARY := cts/build/test_target_java_library.mk
 BUILD_CTS_UI_JAVA_LIBRARY := cts/build/test_uiautomator.mk
+BUILD_CTS_DEQP_PACKAGE := cts/build/test_deqp_package.mk
diff --git a/build/deqp_dummy_test_list b/build/deqp_dummy_test_list
new file mode 100644
index 0000000..6bf22aa
--- /dev/null
+++ b/build/deqp_dummy_test_list
@@ -0,0 +1,3 @@
+suite:TestSuite
+case:TEST_CASE_NAME
+test:TEST_NAME
diff --git a/build/test_deqp_package.mk b/build/test_deqp_package.mk
new file mode 100644
index 0000000..b07876d
--- /dev/null
+++ b/build/test_deqp_package.mk
@@ -0,0 +1,44 @@
+# Copyright (C) 2012 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.
+
+#
+# Builds dEQP test description XMLs needed by CTS.
+#
+
+CTS_DEQP_CONFIG_PATH := $(call my-dir)
+
+cts_library_xml := $(CTS_TESTCASES_OUT)/com.drawelements.deqp.$(DEQP_API).xml
+
+$(cts_library_xml): MUSTPASS_XML_FILE := external/deqp/android/cts/com.drawelements.deqp.$(DEQP_API).xml
+$(cts_library_xml): PRIVATE_TEST_NAME := $(DEQP_TEST_NAME)
+$(cts_library_xml): PRIVATE_TEST_PACKAGE := com.drawelements.deqp.$(DEQP_API)
+$(cts_library_xml): PRIVATE_DUMMY_CASELIST := $(CTS_DEQP_CONFIG_PATH)/deqp_dummy_test_list
+$(cts_library_xml): $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME))/package.apk external/deqp/android/cts/com.drawelements.deqp.$(DEQP_API).xml $(CTS_EXPECTATIONS) $(CTS_UNSUPPORTED_ABIS) $(CTS_XML_GENERATOR)
+	$(hide) echo Generating test description for $(PRIVATE_TEST_NAME)
+	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
+	
+# Query build ABIs by routing a dummy test list through xml generator and parse result
+	$(hide) $(eval supported_abi_attr := $(shell $(CTS_XML_GENERATOR) -t dummyTest \
+										-n dummyName \
+										-p invalid.dummy \
+										-e $(CTS_EXPECTATIONS) \
+										-b $(CTS_UNSUPPORTED_ABIS) \
+										-a $(CTS_TARGET_ARCH) \
+										< $(PRIVATE_DUMMY_CASELIST) \
+										| grep --only-matching -e " abis=\"[^\"]*\""))
+	
+# Patch xml caselist with supported abi
+	$(hide) $(SED_EXTENDED) -e 's:^<Test (.*)/>$$:<Test \1 $(supported_abi_attr) />:' \
+				< $(MUSTPASS_XML_FILE) \
+				> $@
diff --git a/build/test_executable.mk b/build/test_executable.mk
index 0d42d02..e0352ba 100644
--- a/build/test_executable.mk
+++ b/build/test_executable.mk
@@ -29,14 +29,17 @@
 
 $(cts_executable_xml): PRIVATE_TEST_PACKAGE := $(LOCAL_CTS_TEST_PACKAGE)
 $(cts_executable_xml): PRIVATE_EXECUTABLE := $(LOCAL_MODULE)
-$(cts_executable_xml): PRIVATE_TEST_LIST := $(LOCAL_PATH)/$(LOCAL_MODULE)_list.txt
-$(cts_executable_xml): $(addprefix $(LOCAL_PATH)/,$(LOCAL_SRC_FILES)) $(CTS_EXPECTATIONS) $(CTS_NATIVE_TEST_SCANNER) $(CTS_XML_GENERATOR)
+$(cts_executable_xml): PRIVATE_LIST_EXECUTABLE := $(HOST_OUT_EXECUTABLES)/$(LOCAL_MODULE)_list
+$(cts_executable_xml): $(HOST_OUT_EXECUTABLES)/$(LOCAL_MODULE)_list
+$(cts_executable_xml): $(addprefix $(LOCAL_PATH)/,$(LOCAL_SRC_FILES)) $(CTS_EXPECTATIONS) $(CTS_UNSUPPORTED_ABIS) $(CTS_NATIVE_TEST_SCANNER) $(CTS_XML_GENERATOR) $(cts_list_executable)
 	$(hide) echo Generating test description for native package $(PRIVATE_TEST_PACKAGE)
 	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
-	$(hide) cat $(PRIVATE_TEST_LIST) | \
+	$(hide) $(PRIVATE_LIST_EXECUTABLE) --gtest_list_tests | \
 			$(CTS_NATIVE_TEST_SCANNER) -t $(PRIVATE_TEST_PACKAGE) | \
 			$(CTS_XML_GENERATOR) -t native \
 						-n $(PRIVATE_EXECUTABLE) \
 						-p $(PRIVATE_TEST_PACKAGE) \
 						-e $(CTS_EXPECTATIONS) \
+						-b $(CTS_UNSUPPORTED_ABIS) \
+						-a $(CTS_TARGET_ARCH) \
 						-o $@
diff --git a/build/test_gtest_package.mk b/build/test_gtest_package.mk
index cbd9414..6868081 100644
--- a/build/test_gtest_package.mk
+++ b/build/test_gtest_package.mk
@@ -49,4 +49,6 @@
 						-n $(PRIVATE_EXECUTABLE) \
 						-p $(PRIVATE_TEST_PACKAGE) \
 						-e $(CTS_EXPECTATIONS) \
+						-b $(CTS_UNSUPPORTED_ABIS) \
+						-a $(CTS_TARGET_ARCH) \
 						-o $@
diff --git a/build/test_host_java_library.mk b/build/test_host_java_library.mk
index 9512bfa..baf9e75 100644
--- a/build/test_host_java_library.mk
+++ b/build/test_host_java_library.mk
@@ -25,7 +25,7 @@
 $(cts_library_xml): PRIVATE_TEST_PACKAGE := $(LOCAL_CTS_TEST_PACKAGE)
 $(cts_library_xml): PRIVATE_LIBRARY := $(LOCAL_MODULE)
 $(cts_library_xml): PRIVATE_JAR_PATH := $(LOCAL_MODULE).jar
-$(cts_library_xml): $(HOST_OUT_JAVA_LIBRARIES)/$(LOCAL_MODULE).jar $(CTS_EXPECTATIONS) $(CTS_JAVA_TEST_SCANNER_DOCLET) $(CTS_JAVA_TEST_SCANNER) $(CTS_XML_GENERATOR)
+$(cts_library_xml): $(HOST_OUT_JAVA_LIBRARIES)/$(LOCAL_MODULE).jar $(CTS_EXPECTATIONS) $(CTS_UNSUPPORTED_ABIS) $(CTS_JAVA_TEST_SCANNER_DOCLET) $(CTS_JAVA_TEST_SCANNER) $(CTS_XML_GENERATOR)
 	$(hide) echo Generating test description for host library $(PRIVATE_LIBRARY)
 	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
 	$(hide) $(CTS_JAVA_TEST_SCANNER) -s $(PRIVATE_PATH) \
@@ -35,4 +35,6 @@
 						-n $(PRIVATE_LIBRARY) \
 						-p $(PRIVATE_TEST_PACKAGE) \
 						-e $(CTS_EXPECTATIONS) \
+						-b $(CTS_UNSUPPORTED_ABIS) \
+						-a $(CTS_TARGET_ARCH) \
 						-o $@
diff --git a/build/test_package.mk b/build/test_package.mk
index a0adb5f..353ae07 100644
--- a/build/test_package.mk
+++ b/build/test_package.mk
@@ -44,7 +44,7 @@
 $(cts_package_xml): PRIVATE_TEST_PACKAGE := $(PRIVATE_CTS_TEST_PACKAGE_NAME_)
 $(cts_package_xml): PRIVATE_MANIFEST := $(LOCAL_PATH)/AndroidManifest.xml
 $(cts_package_xml): PRIVATE_TEST_TYPE := $(if $(LOCAL_CTS_TEST_RUNNER),$(LOCAL_CTS_TEST_RUNNER),'')
-$(cts_package_xml): $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME))/package.apk $(CTS_EXPECTATIONS) $(CTS_JAVA_TEST_SCANNER_DOCLET) $(CTS_JAVA_TEST_SCANNER) $(CTS_XML_GENERATOR)
+$(cts_package_xml): $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME))/package.apk $(CTS_EXPECTATIONS) $(CTS_UNSUPPORTED_ABIS) $(CTS_JAVA_TEST_SCANNER_DOCLET) $(CTS_JAVA_TEST_SCANNER) $(CTS_XML_GENERATOR)
 	$(hide) echo Generating test description for java package $(PRIVATE_PACKAGE)
 	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
 	$(hide) $(CTS_JAVA_TEST_SCANNER) \
@@ -57,4 +57,6 @@
 						-n $(PRIVATE_PACKAGE) \
 						-p $(PRIVATE_TEST_PACKAGE) \
 						-e $(CTS_EXPECTATIONS) \
+						-b $(CTS_UNSUPPORTED_ABIS) \
+						-a $(CTS_TARGET_ARCH) \
 						-o $@
diff --git a/build/test_target_java_library.mk b/build/test_target_java_library.mk
new file mode 100644
index 0000000..c0d7a2a
--- /dev/null
+++ b/build/test_target_java_library.mk
@@ -0,0 +1,46 @@
+# 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.
+
+#
+# Builds a host library and defines a rule to generate the associated test
+# package XML needed by CTS.
+#
+# Disable by default so "m cts" will work in emulator builds
+LOCAL_DEX_PREOPT := false
+include $(BUILD_JAVA_LIBRARY)
+cts_library_jar := $(CTS_TESTCASES_OUT)/$(LOCAL_MODULE).jar
+$(cts_library_jar): $(LOCAL_BUILT_MODULE) | $(ACP)
+	$(copy-file-to-target)
+
+cts_library_xml := $(CTS_TESTCASES_OUT)/$(LOCAL_MODULE).xml
+$(cts_library_xml): $(cts_library_jar)
+$(cts_library_xml): PRIVATE_PATH := $(LOCAL_PATH)/src
+$(cts_library_xml): PRIVATE_TEST_PACKAGE := $(LOCAL_CTS_TEST_PACKAGE)
+$(cts_library_xml): PRIVATE_LIBRARY := $(LOCAL_MODULE)
+$(cts_library_xml): PRIVATE_JAR_PATH := $(LOCAL_MODULE).jar
+$(cts_library_xml): PRIVATE_RUNTIME_ARGS := $(LOCAL_CTS_TARGET_RUNTIME_ARGS)
+$(cts_library_xml): $(TARGET_OUT_JAVA_LIBRARIES)/$(LOCAL_MODULE).jar $(CTS_EXPECTATIONS) $(CTS_UNSUPPORTED_ABIS) $(CTS_JAVA_TEST_SCANNER_DOCLET) $(CTS_JAVA_TEST_SCANNER) $(CTS_XML_GENERATOR)
+	$(hide) echo Generating test description for target library $(PRIVATE_LIBRARY)
+	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
+	$(hide) $(CTS_JAVA_TEST_SCANNER) -s $(PRIVATE_PATH) \
+						-d $(CTS_JAVA_TEST_SCANNER_DOCLET) | \
+			$(CTS_XML_GENERATOR) -t jUnitDeviceTest \
+						-j $(PRIVATE_JAR_PATH) \
+						-n $(PRIVATE_LIBRARY) \
+						-p $(PRIVATE_TEST_PACKAGE) \
+						-e $(CTS_EXPECTATIONS) \
+						-b $(CTS_UNSUPPORTED_ABIS) \
+						-a $(CTS_TARGET_ARCH) \
+						-x "runtimeArgs->$(PRIVATE_RUNTIME_ARGS)" \
+						-o $@
diff --git a/build/test_uiautomator.mk b/build/test_uiautomator.mk
index c17f12b..5e2f07a 100644
--- a/build/test_uiautomator.mk
+++ b/build/test_uiautomator.mk
@@ -35,7 +35,7 @@
 $(cts_library_xml): PRIVATE_TEST_APK := $(LOCAL_CTS_TEST_APK)
 $(cts_library_xml): PRIVATE_LIBRARY := $(LOCAL_MODULE)
 $(cts_library_xml): PRIVATE_JAR_PATH := $(LOCAL_MODULE).jar
-$(cts_library_xml): $(call intermediates-dir-for,JAVA_LIBRARIES,$(LOCAL_MODULE))/javalib.jar $(CTS_EXPECTATIONS) $(CTS_JAVA_TEST_SCANNER_DOCLET) $(CTS_JAVA_TEST_SCANNER) $(CTS_XML_GENERATOR)
+$(cts_library_xml): $(call intermediates-dir-for,JAVA_LIBRARIES,$(LOCAL_MODULE))/javalib.jar $(CTS_EXPECTATIONS) $(CTS_UNSUPPORTED_ABIS) $(CTS_JAVA_TEST_SCANNER_DOCLET) $(CTS_JAVA_TEST_SCANNER) $(CTS_XML_GENERATOR)
 	$(hide) echo Generating test description for uiautomator library $(PRIVATE_LIBRARY)
 	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
 	$(hide) $(CTS_JAVA_TEST_SCANNER) -s $(PRIVATE_PATH) \
@@ -43,9 +43,11 @@
 			$(CTS_XML_GENERATOR) -t uiAutomator \
 						-i $(PRIVATE_TEST_APK) \
 						-j $(PRIVATE_JAR_PATH) \
-						-a $(PRIVATE_TEST_PACKAGE) \
+						-s $(PRIVATE_TEST_PACKAGE) \
 						-n $(PRIVATE_LIBRARY) \
 						-p $(PRIVATE_TEST_PACKAGE) \
 						-r $(PRIVATE_TEST_APP_PACKAGE) \
 						-e $(CTS_EXPECTATIONS) \
+						-b $(CTS_UNSUPPORTED_ABIS) \
+						-a $(CTS_TARGET_ARCH) \
 						-o $@
diff --git a/common/host-side/tradefed/Android.mk b/common/host-side/tradefed/Android.mk
index 2cb559a..8ff7c8c 100644
--- a/common/host-side/tradefed/Android.mk
+++ b/common/host-side/tradefed/Android.mk
@@ -28,7 +28,7 @@
 
 LOCAL_MODULE_TAGS := optional
 
-LOCAL_JAVA_LIBRARIES := ddmlib-prebuilt tradefed-prebuilt hosttestlib compatibility-common-util-hostsidelib_v2
+LOCAL_JAVA_LIBRARIES := tradefed-prebuilt hosttestlib compatibility-common-util-hostsidelib_v2
 
 include $(BUILD_HOST_JAVA_LIBRARY)
 
@@ -44,7 +44,7 @@
 
 LOCAL_MODULE_TAGS := optional
 
-LOCAL_JAVA_LIBRARIES := ddmlib-prebuilt tradefed-prebuilt compatibility-tradefed_v2 junit
+LOCAL_JAVA_LIBRARIES := tradefed-prebuilt compatibility-tradefed_v2 junit
 
 LOCAL_STATIC_JAVA_LIBRARIES := easymock
 
diff --git a/development/ide/eclipse/.classpath b/development/ide/eclipse/.classpath
index 2ddb4d8..98939ba 100644
--- a/development/ide/eclipse/.classpath
+++ b/development/ide/eclipse/.classpath
@@ -1,95 +1,101 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-    <classpathentry kind="lib" path="prebuilt/common/ddmlib/ddmlib-prebuilt.jar"/>
-    <classpathentry kind="lib" path="prebuilt/common/tradefed/tradefed-prebuilt.jar"/>
-    <classpathentry kind="src" path="cts/apps/CtsVerifier/src"/>
-    <classpathentry kind="src" path="cts/apps/CtsVerifier/tests/src"/>
-    <classpathentry kind="src" path="cts/hostsidetests/appsecurity/src"/>
-    <classpathentry kind="src" path="cts/hostsidetests/appsecurity/test-apps/AppWithData/src"/>
-    <classpathentry kind="src" path="cts/hostsidetests/monkey/src"/>
-    <classpathentry kind="src" path="cts/hostsidetests/monkey/test-apps/CtsMonkeyApp/src"/>
-    <classpathentry kind="src" path="cts/hostsidetests/monkey/test-apps/CtsMonkeyApp2/src"/>
-    <classpathentry kind="src" path="cts/libs/vogar-expect/src"/>
-    <classpathentry kind="src" path="cts/tests/ApiDemosReferenceTest/src"/>
-    <classpathentry kind="src" path="cts/tests/ProcessTest/src"/>
-    <classpathentry kind="src" path="cts/tests/ProcessTest/NoShareUidApp/src"/>
-    <classpathentry kind="src" path="cts/tests/ProcessTest/ShareUidApp/src"/>
-    <classpathentry kind="src" path="cts/tests/SignatureTest/src"/>
-    <classpathentry kind="src" path="cts/tests/SignatureTest/tests/src"/>
-    <classpathentry kind="src" path="cts/tests/acceleration/src"/>
-    <classpathentry kind="src" path="cts/tests/accessibilityservice/src"/>
-    <classpathentry kind="src" path="cts/tests/core/runner/src"/>
-    <classpathentry kind="src" path="cts/tests/deviceadmin/src"/>
-    <classpathentry kind="src" path="cts/tests/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/acceleration/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/accessibility/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/accessibilityservice/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/accounts/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/admin/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/animation/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/app/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/bluetooth/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/content/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/database/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/dpi/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/dpi2/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/drm/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/example/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/gesture/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/graphics/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/graphics2/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/hardware/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/holo/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/jni/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/location/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/media/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/mediastress/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/net/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/opengl/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/openglperf/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/os/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/performance/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/performance2/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/performance3/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/performance4/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/performance5/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/permission/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/permission2/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/preference/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/preference2/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/provider/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/renderscript/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/security/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/speech/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/telephony/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/text/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/textureview/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/theme/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/util/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/view/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/webkit/src"/>
-    <classpathentry kind="src" path="cts/tests/tests/widget/src"/>
-    <classpathentry kind="src" path="cts/tools/cts-api-coverage/src"/>
-    <classpathentry kind="src" path="cts/tools/cts-java-scanner/src"/>
-    <classpathentry kind="src" path="cts/tools/cts-java-scanner-doclet/src"/>
-    <classpathentry kind="src" path="cts/tools/cts-native-scanner/src"/>
-    <classpathentry kind="src" path="cts/tools/cts-reference-app-lib/src"/>
-    <classpathentry kind="src" path="cts/tools/cts-xml-generator/src"/>
-    <classpathentry kind="src" path="cts/tools/dasm/src"/>
-    <classpathentry kind="src" path="cts/tools/device-setup/TestDeviceSetup/src"/>
-    <classpathentry kind="src" path="cts/tools/dex-tools/src"/>
-    <classpathentry kind="src" path="cts/tools/dx-tests/src"/>
-    <classpathentry kind="src" path="cts/tools/host/src"/>
-    <classpathentry kind="src" path="cts/tools/host/test"/>
-    <classpathentry kind="src" path="cts/tools/signature-tools/src"/>
-    <classpathentry kind="src" path="cts/tools/signature-tools/test"/>
-    <classpathentry kind="src" path="cts/tools/tradefed-host/src"/>
-    <classpathentry kind="src" path="cts/tools/tradefed-host/tests/src"/>
-    <classpathentry kind="src" path="cts/tools/utils"/>
-    <classpathentry kind="src" path="cts/tools/vm-tests/src"/>
-    <classpathentry kind="src" path="external/easymock/src"/>
-    <classpathentry kind="src" path="out/target/common/obj/APPS/CtsAccessibilityServiceTestCases_intermediates/src/src"/>
-    <classpathentry kind="src" path="out/target/common/obj/APPS/CtsTestStubs_intermediates/src/src"/>
-    <classpathentry kind="src" path="out/target/common/obj/APPS/CtsVerifier_intermediates/src"/>
-    <classpathentry kind="src" path="out/target/common/obj/APPS/CtsVerifierTests_intermediates/src"/>
+        <classpathentry kind="lib" path="prebuilts/misc/common/ddmlib/ddmlib-prebuilt.jar"/>
+        <classpathentry kind="lib" path="prebuilts/misc/common/tradefed/tradefed-prebuilt.jar"/>
+        <classpathentry kind="src" path="cts/apps/CtsVerifier/src"/>
+        <classpathentry kind="src" path="cts/hostsidetests/appsecurity/src"/>
+        <classpathentry kind="src" path="cts/hostsidetests/appsecurity/test-apps/AppWithData/src"/>
+        <classpathentry kind="src" path="cts/hostsidetests/monkey/src"/>
+        <classpathentry kind="src" path="cts/hostsidetests/monkey/test-apps/CtsMonkeyApp/src"/>
+        <classpathentry kind="src" path="cts/hostsidetests/monkey/test-apps/CtsMonkeyApp2/src"/>
+        <classpathentry kind="src" path="cts/hostsidetests/sample/src"/>
+        <classpathentry kind="src" path="cts/hostsidetests/sample/app/src"/>
+        <classpathentry kind="src" path="cts/hostsidetests/theme/src"/>
+        <classpathentry kind="src" path="cts/hostsidetests/theme/app/src"/>
+        <classpathentry kind="src" path="cts/hostsidetests/usb/src"/>
+        <classpathentry kind="src" path="cts/libs/vogar-expect/src"/>
+        <classpathentry kind="src" path="cts/libs/commonutil/src"/>
+        <classpathentry kind="src" path="cts/libs/deviceutil/src"/>
+        <classpathentry kind="src" path="cts/libs/json/src"/>
+        <classpathentry kind="src" path="cts/libs/testserver/src"/>
+        <classpathentry kind="src" path="cts/libs/wrappedgtest/src"/>
+        <classpathentry kind="src" path="cts/suite/cts/deviceTests/browserbench/src"/>
+        <classpathentry kind="src" path="cts/suite/cts/deviceTests/dram/src"/>
+        <classpathentry kind="src" path="cts/suite/cts/deviceTests/filesystemperf/src"/>
+        <classpathentry kind="src" path="cts/suite/cts/deviceTests/opengl/src"/>
+        <classpathentry kind="src" path="cts/suite/cts/deviceTests/simplecpu/src"/>
+        <classpathentry kind="src" path="cts/suite/cts/deviceTests/ui/src"/>
+        <classpathentry kind="src" path="cts/suite/cts/deviceTests/videoperf/src"/>
+        <classpathentry kind="src" path="cts/suite/cts/hostTests/jank/app/src"/>
+        <classpathentry kind="src" path="cts/suite/cts/hostTests/jank/src"/>
+        <classpathentry kind="src" path="cts/suite/cts/hostTests/uihost/appA/src"/>
+        <classpathentry kind="src" path="cts/suite/cts/hostTests/uihost/appB/src"/>
+        <classpathentry kind="src" path="cts/suite/cts/hostTests/uihost/control/src"/>
+        <classpathentry kind="src" path="cts/suite/cts/hostTests/uihost/src"/>
+        <classpathentry kind="src" path="cts/tests/ProcessTest/src"/>
+        <classpathentry kind="src" path="cts/tests/ProcessTest/NoShareUidApp/src"/>
+        <classpathentry kind="src" path="cts/tests/ProcessTest/ShareUidApp/src"/>
+        <classpathentry kind="src" path="cts/tests/signature/src"/>
+        <classpathentry kind="src" path="cts/tests/signature-tests/src"/>
+        <classpathentry kind="src" path="cts/tests/acceleration/src"/>
+        <classpathentry kind="src" path="cts/tests/core/runner/src"/>
+        <classpathentry kind="src" path="cts/tests/deviceadmin/src"/>
+        <classpathentry kind="src" path="cts/tests/sample/src"/>
+        <classpathentry kind="src" path="cts/tests/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/acceleration/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/accessibility/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/accessibilityservice/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/accounts/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/admin/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/animation/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/app/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/bluetooth/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/content/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/database/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/dpi/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/dpi2/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/drm/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/gesture/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/graphics/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/graphics2/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/hardware/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/jni/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/location/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/media/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/mediastress/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/net/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/opengl/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/openglperf/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/os/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/permission/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/permission2/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/preference/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/preference2/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/provider/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/renderscript/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/security/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/speech/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/telephony/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/text/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/textureview/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/util/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/view/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/webkit/src"/>
+        <classpathentry kind="src" path="cts/tests/tests/widget/src"/>
+        <classpathentry kind="src" path="cts/tools/cts-api-coverage/src"/>
+        <classpathentry kind="src" path="cts/tools/cts-java-scanner/src"/>
+        <classpathentry kind="src" path="cts/tools/cts-java-scanner-doclet/src"/>
+        <classpathentry kind="src" path="cts/tools/cts-native-scanner/src"/>
+        <classpathentry kind="src" path="cts/tools/cts-reference-app-lib/src"/>
+        <classpathentry kind="src" path="cts/tools/cts-xml-generator/src"/>
+        <classpathentry kind="src" path="cts/tools/dasm/src"/>
+        <classpathentry kind="src" path="cts/tools/device-setup/TestDeviceSetup/src"/>
+        <classpathentry kind="src" path="cts/tools/dex-tools/src"/>
+        <classpathentry kind="src" path="cts/tools/signature-tools/src"/>
+        <classpathentry kind="src" path="cts/tools/signature-tools/test"/>
+        <classpathentry kind="src" path="cts/tools/tradefed-host/src"/>
+        <classpathentry kind="src" path="cts/tools/tradefed-host/tests/src"/>
+        <classpathentry kind="src" path="cts/tools/utils"/>
+        <classpathentry kind="src" path="cts/tools/vm-tests-tf/src"/>
+        <classpathentry kind="src" path="external/easymock/src"/>
 </classpath>
diff --git a/development/ide/eclipse/genclasspath.sh b/development/ide/eclipse/genclasspath.sh
index 00ee9b3..9b90d82 100755
--- a/development/ide/eclipse/genclasspath.sh
+++ b/development/ide/eclipse/genclasspath.sh
@@ -13,6 +13,5 @@
 
 echo '<?xml version="1.0" encoding="UTF-8"?>'
 echo '<classpath>'
-cat $ANDROID_BUILD_TOP/cts/development/ide/eclipse/.classpath | grep classpathentry
-cat $ANDROID_BUILD_TOP/development/ide/eclipse/.classpath | grep classpathentry
+cat $ANDROID_BUILD_TOP/cts/development/ide/eclipse/.classpath $ANDROID_BUILD_TOP/development/ide/eclipse/.classpath | grep classpathentry | sort
 echo '</classpath>'
diff --git a/hostsidetests/aadb/Android.mk b/hostsidetests/aadb/Android.mk
index 2f2113c..b9551d1 100644
--- a/hostsidetests/aadb/Android.mk
+++ b/hostsidetests/aadb/Android.mk
@@ -21,7 +21,7 @@
 
 LOCAL_MODULE := CtsAdbTests
 
-LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt ddmlib-prebuilt junit
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
 
 LOCAL_CTS_TEST_PACKAGE := android.aadb
 
diff --git a/hostsidetests/appsecurity/.gitignore b/hostsidetests/appsecurity/.gitignore
new file mode 100644
index 0000000..5e56e04
--- /dev/null
+++ b/hostsidetests/appsecurity/.gitignore
@@ -0,0 +1 @@
+/bin
diff --git a/hostsidetests/appsecurity/Android.mk b/hostsidetests/appsecurity/Android.mk
index 4dd8d5c..61f9a4d 100644
--- a/hostsidetests/appsecurity/Android.mk
+++ b/hostsidetests/appsecurity/Android.mk
@@ -21,7 +21,7 @@
 
 LOCAL_MODULE := CtsAppSecurityTests
 
-LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt ddmlib-prebuilt junit
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
 
 LOCAL_CTS_TEST_PACKAGE := android.tests.appsecurity
 
diff --git a/hostsidetests/appsecurity/certs/keysets/README b/hostsidetests/appsecurity/certs/keysets/README
new file mode 100644
index 0000000..251dab1
--- /dev/null
+++ b/hostsidetests/appsecurity/certs/keysets/README
@@ -0,0 +1,9 @@
+# Generated with:
+development/tools/make_key cts-keyset-test-a         '/CN=unit_test_a'
+development/tools/make_key cts-keyset-test-b         '/CN=unit_test_b'
+development/tools/make_key cts-keyset-test-c         '/CN=unit_test_c'
+
+# Display public key (for use in Manifest) with:
+openssl x509 -in cts-keyset-test-a.x509.pem -inform PEM -pubkey
+openssl x509 -in cts-keyset-test-b.x509.pem -inform PEM -pubkey
+openssl x509 -in cts-keyset-test-c.x509.pem -inform PEM -pubkey
\ No newline at end of file
diff --git a/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a.pk8 b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a.pk8
new file mode 100644
index 0000000..b0dd6a3
--- /dev/null
+++ b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a.pk8
Binary files differ
diff --git a/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a.x509.pem b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a.x509.pem
new file mode 100644
index 0000000..cee8227
--- /dev/null
+++ b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a.x509.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDCzCCAfOgAwIBAgIJAJ126KYAFwgTMA0GCSqGSIb3DQEBBQUAMBwxGjAYBgNV
+BAMMEWN0cy1rZXlzZXQtdGVzdC1hMB4XDTE0MDkxMTAwNDQ0OFoXDTQyMDEyNzAw
+NDQ0OFowHDEaMBgGA1UEAwwRY3RzLWtleXNldC10ZXN0LWEwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDB/nMluW9hIHtibuiv/saCAAC7uantGvKQ8mxe
+Gh3x2gWFVPmzt4XcDgwITnm+8A0/se/AzDZv5PqrHs+rRUm1ttIO2UEcG0hzjs+O
+rQKwODn3QFRyAqns90n0npRWC3MOdXpwYSleZJqDexj6WqJbTjK0+EJXDNhNYZ1h
+735MiXjtwGu95F8s6Uaty4VB77MJOYMWrMEoJEcr1vuXk8Na9dfKDrlS78wFQD9N
+lY7R8So6XFkb+efoNQpAuE92YlFdYndaow0yEkYP6cq2SZ1fvTfFGqaDiH7qDRLs
+z1jchDY1QbLDTkBjMKC4cH8y/q5UiJbrn3ClvJvjlOAobdSFAgMBAAGjUDBOMB0G
+A1UdDgQWBBTev2AuCLdXO85IFqwy6rIV+wUokjAfBgNVHSMEGDAWgBTev2AuCLdX
+O85IFqwy6rIV+wUokjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQCS
+8bjQglLYCNMFHc6AeAvSfu/j9rbZNTmK+0SCCUYbb4s1LoMNQ1hmHhs+nrmrOTe9
+3VgaKPUz2h6+toOM5KhMpkxDUHxe+VKJF4V+TRxMWZbPaz0wgj21FKcV7u5wnWnj
+i08O9dzksIzkD9UrOaxlExG20YFJE9kizoR0i2mZJWhR+1g6SeNc7PeaUnEI344G
+LfSDGt27EqZhmZ1BhJ4lRRUMq3TJFEfdFeVc3z+AgtyrZnxc7jNQ0PFdOXDtzz6B
+iC6AmFsMC/mRettVxjTeOpLo+12UE7FwO+wRa57pNGtljzlKz+DGBAZxi+gLcRDf
+i0TJhPAB4dFqrDgxr+4Y
+-----END CERTIFICATE-----
diff --git a/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b.pk8 b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b.pk8
new file mode 100644
index 0000000..bf6dee1
--- /dev/null
+++ b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b.pk8
Binary files differ
diff --git a/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b.x509.pem b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b.x509.pem
new file mode 100644
index 0000000..912861f
--- /dev/null
+++ b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b.x509.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDCzCCAfOgAwIBAgIJAOZwpbLsHooSMA0GCSqGSIb3DQEBBQUAMBwxGjAYBgNV
+BAMMEWN0cy1rZXlzZXQtdGVzdC1iMB4XDTE0MDkxMTAwNDQ0MVoXDTQyMDEyNzAw
+NDQ0MVowHDEaMBgGA1UEAwwRY3RzLWtleXNldC10ZXN0LWIwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQCh4VmoypNtmKjMVNcyRe1IolHOfao4NmC9VcAD
+ApOLnTFhxs9wdN8rG2J/z6rs4Kn/nQlgMffZuDrCRS6efn50RoeTFljx3u7Djq1C
+2Xl00aL7pxzgx7NUsJLqeSo0O6wCB2+AtToWXpIaLTYpOnW+S3oLAs73vtgk/uS3
+2i4NFMbsBImKrc7JFGg6pgeEP2CmxtSrjD7VtcZ+65m6MDV1fKi9e2+sdQY50UgQ
+Fg5VgZ8JzCHeVc+aM0kyUe0pCS6urz8sftrUHmhyhcIazJHxgd2VZ+upEB/OA4HU
+oKc02ZaqyRT0s5yLe5Cf0gN4wQWYB3wWoXxLBX7gu52T/FYZAgMBAAGjUDBOMB0G
+A1UdDgQWBBTM1NnUfcwYiJ3Loy3jfmVwyI+BCTAfBgNVHSMEGDAWgBTM1NnUfcwY
+iJ3Loy3jfmVwyI+BCTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQBh
+lRz5yaYpswtWDVPWKnJ5btyXsLIQtWeFkxGxRXSrsFLvCMq7CxjO9VF1l+q+6UmK
+B6BEcrjm7uhmjAXS/ygUGjY1FZNVHwydJ/60Nn/Q0jx242A1+dBtLSS0FnEg+r3P
+3fvocr0SemAt6FY61gJ+4Zr8IQZc8C1qr5e/eDiMPBKectGzH1cniWqq1/5nc/vC
+hTTokZSnXh7PZLzF+iKOceO+nvx4yzm7q/YOM0tAP8PknrWcNAeIPRDvsERwp9fR
+IRTnyd3Ds4H/xD6OioMO+lk45H7vDU3TmoAYbDtCNvgS9Sd1lB/h3XPVH29QqwkW
+4xScMf6rzziGC+RdETpU
+-----END CERTIFICATE-----
diff --git a/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-c.pk8 b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-c.pk8
new file mode 100644
index 0000000..303f1ad
--- /dev/null
+++ b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-c.pk8
Binary files differ
diff --git a/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-c.x509.pem b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-c.x509.pem
new file mode 100644
index 0000000..324f218
--- /dev/null
+++ b/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-c.x509.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDCzCCAfOgAwIBAgIJAI8ugk5OF4ENMA0GCSqGSIb3DQEBBQUAMBwxGjAYBgNV
+BAMMEWN0cy1rZXlzZXQtdGVzdC1jMB4XDTE0MDkxMTAwNDQyMloXDTQyMDEyNzAw
+NDQyMlowHDEaMBgGA1UEAwwRY3RzLWtleXNldC10ZXN0LWMwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQCvAgn+n3NnqkZ7uHWUElQsTmVthsLeaHkbjc6w
+n4HQJ5s3grMQrJWD7CaS4ZK8bbFdSnUGVuKlKOdMnltS3aIG7AHzUu+6aD0Y58Kl
+MEa18ThriKC1+jt7ZTwhtHMRhuFpmUESYLUENS91MV0xEZk+6FRwyTCK3hGkeQvq
+u22459p6gnCyASNsQvLOByb7Vnj0N6f8maZc0YzDX9AyJsEUa8aSG7aseD9JiIqm
+6lyVTgUh4Atw5Kc+Sutjou5IBMcOdi+68rdWG7QQEogP6sC/mPoE2+e7blIB/caB
+Ls8u7JWWGITmneFN69efmD/u2MmVdrQWxsyWcV/ndbI/2lFbAgMBAAGjUDBOMB0G
+A1UdDgQWBBQbgTfHOXShdjNob5N5in97g4W97TAfBgNVHSMEGDAWgBQbgTfHOXSh
+djNob5N5in97g4W97TAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAn
+bOLKe3ixKqLkMsgocHWvkeUqFahYbiPN11JKTFrgQVYwfpUnXN/YQfLSjAWDyzZ3
+niXYSai2COtIqEpQICp4JceEfoZUCbHdATA7Wxvfr+yrv+HG7F8wzhyxa5Pbcu9y
+b3ekjKT1rF4SxK0Ixt9vv34VSO98qAzx2Yq7VQwOKLJG6MDxqXX/tiTxpK7sEfAb
+pgJjHVZkX1rgQtv2e0RLFgcRyiYpxFbFzBLi/1b6EzK2kkg9FNLm+44CYkYFj7WC
+bjlY7o94DQ/CuEDVHCu/DSTp4QjvHC2ewTeXu05XkzSWKKLdsqecnZxXNueuqT5F
+Uhj9Fi4KQqT7tKqd+CuK
+-----END CERTIFICATE-----
diff --git a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/AppSecurityTests.java b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/AppSecurityTests.java
index 88b05fb..9dc51c9 100644
--- a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/AppSecurityTests.java
+++ b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/AppSecurityTests.java
@@ -17,18 +17,21 @@
 package com.android.cts.appsecurity;
 
 import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.cts.util.AbiUtils;
 import com.android.ddmlib.Log;
 import com.android.ddmlib.testrunner.InstrumentationResultParser;
 import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
 import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.ddmlib.testrunner.TestResult;
+import com.android.ddmlib.testrunner.TestResult.TestStatus;
+import com.android.ddmlib.testrunner.TestRunResult;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.result.CollectingTestListener;
-import com.android.tradefed.result.TestResult;
-import com.android.tradefed.result.TestResult.TestStatus;
-import com.android.tradefed.result.TestRunResult;
 import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
 import com.android.tradefed.testtype.IBuildReceiver;
 
 import java.io.File;
@@ -38,7 +41,9 @@
 /**
  * Set of tests that verify various security checks involving multiple apps are properly enforced.
  */
-public class AppSecurityTests extends DeviceTestCase implements IBuildReceiver {
+public class AppSecurityTests extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
+
+    private static final String RUNNER = "android.support.test.runner.AndroidJUnitRunner";
 
     // testSharedUidDifferentCerts constants
     private static final String SHARED_UI_APK = "CtsSharedUidInstall.apk";
@@ -102,8 +107,14 @@
 
     private static final String LOG_TAG = "AppSecurityTests";
 
+    private IAbi mAbi;
     private CtsBuildHelper mCtsBuild;
 
+    @Override
+    public void setAbi(IAbi abi) {
+        mAbi = abi;
+    }
+
     /**
      * {@inheritDoc}
      */
@@ -134,12 +145,13 @@
             getDevice().uninstallPackage(SHARED_UI_PKG);
             getDevice().uninstallPackage(SHARED_UI_DIFF_CERT_PKG);
 
+            String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
             String installResult = getDevice().installPackage(getTestAppFile(SHARED_UI_APK),
-                    false);
+                    false, options);
             assertNull(String.format("failed to install shared uid app, Reason: %s", installResult),
                     installResult);
             installResult = getDevice().installPackage(getTestAppFile(SHARED_UI_DIFF_CERT_APK),
-                    false);
+                    false, options);
             assertNotNull("shared uid app with different cert than existing app installed " +
                     "successfully", installResult);
             assertEquals("INSTALL_FAILED_SHARED_USER_INCOMPATIBLE", installResult);
@@ -160,12 +172,13 @@
             // cleanup test app that might be installed from previous partial test run
             getDevice().uninstallPackage(SIMPLE_APP_PKG);
 
+            String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
             String installResult = getDevice().installPackage(getTestAppFile(SIMPLE_APP_APK),
-                    false);
+                    false, options);
             assertNull(String.format("failed to install simple app. Reason: %s", installResult),
                     installResult);
             installResult = getDevice().installPackage(getTestAppFile(SIMPLE_APP_DIFF_CERT_APK),
-                    true /* reinstall */);
+                    true /* reinstall */, options);
             assertNotNull("app upgrade with different cert than existing app installed " +
                     "successfully", installResult);
             assertEquals("INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES", installResult);
@@ -185,8 +198,9 @@
             getDevice().uninstallPackage(APP_WITH_DATA_PKG);
             getDevice().uninstallPackage(APP_ACCESS_DATA_PKG);
 
+            String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
             String installResult = getDevice().installPackage(getTestAppFile(APP_WITH_DATA_APK),
-                    false);
+                    false, options);
             assertNull(String.format("failed to install app with data. Reason: %s", installResult),
                     installResult);
             // run appwithdata's tests to create private data
@@ -194,7 +208,7 @@
                     APP_WITH_DATA_CLASS, APP_WITH_DATA_CREATE_METHOD));
 
             installResult = getDevice().installPackage(getTestAppFile(APP_ACCESS_DATA_APK),
-                    false);
+                    false, options);
             assertNull(String.format("failed to install app access data. Reason: %s",
                     installResult), installResult);
             // run appaccessdata's tests which attempt to access appwithdata's private data
@@ -214,8 +228,9 @@
             wipePrimaryExternalStorage(getDevice());
 
             getDevice().uninstallPackage(EXTERNAL_STORAGE_APP_PKG);
+            String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
             assertNull(getDevice()
-                    .installPackage(getTestAppFile(EXTERNAL_STORAGE_APP_APK), false));
+                    .installPackage(getTestAppFile(EXTERNAL_STORAGE_APP_APK), false, options));
             assertTrue("Failed external storage with no permissions",
                     runDeviceTests(EXTERNAL_STORAGE_APP_PKG));
         } finally {
@@ -233,8 +248,9 @@
             wipePrimaryExternalStorage(getDevice());
 
             getDevice().uninstallPackage(READ_EXTERNAL_STORAGE_APP_PKG);
+            String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
             assertNull(getDevice()
-                    .installPackage(getTestAppFile(READ_EXTERNAL_STORAGE_APP_APK), false));
+                    .installPackage(getTestAppFile(READ_EXTERNAL_STORAGE_APP_APK), false, options));
             assertTrue("Failed external storage with read permissions",
                     runDeviceTests(READ_EXTERNAL_STORAGE_APP_PKG));
         } finally {
@@ -252,8 +268,9 @@
             wipePrimaryExternalStorage(getDevice());
 
             getDevice().uninstallPackage(WRITE_EXTERNAL_STORAGE_APP_PKG);
+            String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
             assertNull(getDevice()
-                    .installPackage(getTestAppFile(WRITE_EXTERNAL_STORAGE_APP_APK), false));
+                    .installPackage(getTestAppFile(WRITE_EXTERNAL_STORAGE_APP_APK), false, options));
             assertTrue("Failed external storage with write permissions",
                     runDeviceTests(WRITE_EXTERNAL_STORAGE_APP_PKG));
         } finally {
@@ -272,12 +289,13 @@
             getDevice().uninstallPackage(EXTERNAL_STORAGE_APP_PKG);
             getDevice().uninstallPackage(READ_EXTERNAL_STORAGE_APP_PKG);
             getDevice().uninstallPackage(WRITE_EXTERNAL_STORAGE_APP_PKG);
+            String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
             assertNull(getDevice()
-                    .installPackage(getTestAppFile(EXTERNAL_STORAGE_APP_APK), false));
+                    .installPackage(getTestAppFile(EXTERNAL_STORAGE_APP_APK), false, options));
             assertNull(getDevice()
-                    .installPackage(getTestAppFile(READ_EXTERNAL_STORAGE_APP_APK), false));
+                    .installPackage(getTestAppFile(READ_EXTERNAL_STORAGE_APP_APK), false, options));
             assertNull(getDevice()
-                    .installPackage(getTestAppFile(WRITE_EXTERNAL_STORAGE_APP_APK), false));
+                    .installPackage(getTestAppFile(WRITE_EXTERNAL_STORAGE_APP_APK), false, options));
 
             assertTrue("Failed to write gifts", runDeviceTests(WRITE_EXTERNAL_STORAGE_APP_PKG,
                     WRITE_EXTERNAL_STORAGE_APP_CLASS, "doWriteGifts"));
@@ -303,8 +321,9 @@
             // cleanup test app that might be installed from previous partial test run
             getDevice().uninstallPackage(APP_WITH_DATA_PKG);
 
+            String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
             String installResult = getDevice().installPackage(getTestAppFile(APP_WITH_DATA_APK),
-                    false);
+                    false, options);
             assertNull(String.format("failed to install app with data. Reason: %s", installResult),
                     installResult);
             // run appwithdata's tests to create private data
@@ -314,7 +333,7 @@
             getDevice().uninstallPackage(APP_WITH_DATA_PKG);
 
             installResult = getDevice().installPackage(getTestAppFile(APP_WITH_DATA_APK),
-                    false);
+                    false, options);
             assertNull(String.format("failed to install app with data second time. Reason: %s",
                     installResult), installResult);
             // run appwithdata's 'check if file exists' test
@@ -337,14 +356,15 @@
             getDevice().uninstallPackage(TARGET_INSTRUMENT_PKG);
             getDevice().uninstallPackage(INSTRUMENT_DIFF_CERT_PKG);
 
+            String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
             String installResult = getDevice().installPackage(
-                    getTestAppFile(TARGET_INSTRUMENT_APK), false);
+                    getTestAppFile(TARGET_INSTRUMENT_APK), false, options);
             assertNull(String.format("failed to install target instrumentation app. Reason: %s",
                     installResult), installResult);
 
             // the app will install, but will get error at runtime when starting instrumentation
             installResult = getDevice().installPackage(getTestAppFile(INSTRUMENT_DIFF_CERT_APK),
-                    false);
+                    false, options);
             assertNull(String.format(
                     "failed to install instrumentation app with diff cert. Reason: %s",
                     installResult), installResult);
@@ -372,19 +392,20 @@
             getDevice().uninstallPackage(DECLARE_PERMISSION_COMPAT_PKG);
             getDevice().uninstallPackage(PERMISSION_DIFF_CERT_PKG);
 
+            String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
             String installResult = getDevice().installPackage(
-                    getTestAppFile(DECLARE_PERMISSION_APK), false);
+                    getTestAppFile(DECLARE_PERMISSION_APK), false, options);
             assertNull(String.format("failed to install declare permission app. Reason: %s",
                     installResult), installResult);
 
             installResult = getDevice().installPackage(
-                    getTestAppFile(DECLARE_PERMISSION_COMPAT_APK), false);
+                    getTestAppFile(DECLARE_PERMISSION_COMPAT_APK), false, options);
             assertNull(String.format("failed to install declare permission compat app. Reason: %s",
                     installResult), installResult);
 
             // the app will install, but will get error at runtime
             installResult = getDevice().installPackage(getTestAppFile(PERMISSION_DIFF_CERT_APK),
-                    false);
+                    false, options);
             assertNull(String.format("failed to install permission app with diff cert. Reason: %s",
                     installResult), installResult);
             // run PERMISSION_DIFF_CERT_PKG tests which try to access the permission
@@ -419,8 +440,9 @@
 
             // Install our test app
             getDevice().uninstallPackage(MULTIUSER_STORAGE_PKG);
+            String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
             final String installResult = getDevice()
-                    .installPackage(getTestAppFile(MULTIUSER_STORAGE_APK), false);
+                    .installPackage(getTestAppFile(MULTIUSER_STORAGE_APK), false, options);
             assertNull("Failed to install: " + installResult, installResult);
 
             // Clear data from previous tests
@@ -509,7 +531,7 @@
             String testMethodName) throws DeviceNotAvailableException {
 
         RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(pkgName,
-                getDevice().getIDevice());
+                RUNNER, getDevice().getIDevice());
         if (testClassName != null && testMethodName != null) {
             testRunner.setMethodName(testClassName, testMethodName);
         }
@@ -560,7 +582,7 @@
             throws DeviceNotAvailableException {
         // TODO: move this to RemoteAndroidTestRunner once it supports users
         final String cmd = "am instrument --user " + userId + " -w -r -e class " + testClassName
-                + "#" + testMethodName + " " + pkgName + "/android.test.InstrumentationTestRunner";
+                + "#" + testMethodName + " " + pkgName + "/" + RUNNER;
         Log.i(LOG_TAG, "Running " + cmd + " on " + getDevice().getSerialNumber());
 
         CollectingTestListener listener = new CollectingTestListener();
diff --git a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/DocumentsTest.java b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/DocumentsTest.java
new file mode 100644
index 0000000..fbde558
--- /dev/null
+++ b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/DocumentsTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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 com.android.cts.appsecurity;
+
+import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+public class DocumentsTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
+    private static final String PROVIDER_PKG = "com.android.cts.documentprovider";
+    private static final String PROVIDER_APK = "CtsDocumentProvider.apk";
+
+    private static final String CLIENT_PKG = "com.android.cts.documentclient";
+    private static final String CLIENT_APK = "CtsDocumentClient.apk";
+
+    private IAbi mAbi;
+    private CtsBuildHelper mCtsBuild;
+
+    @Override
+    public void setAbi(IAbi abi) {
+        mAbi = abi;
+    }
+
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        assertNotNull(mAbi);
+        assertNotNull(mCtsBuild);
+
+        getDevice().uninstallPackage(PROVIDER_PKG);
+        getDevice().uninstallPackage(CLIENT_PKG);
+
+        assertNull(getDevice().installPackage(mCtsBuild.getTestApp(PROVIDER_APK), false));
+        assertNull(getDevice().installPackage(mCtsBuild.getTestApp(CLIENT_APK), false));
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+
+        getDevice().uninstallPackage(PROVIDER_PKG);
+        getDevice().uninstallPackage(CLIENT_PKG);
+    }
+
+    public void testOpenSimple() throws Exception {
+        runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testOpenSimple");
+    }
+
+    public void testCreateNew() throws Exception {
+        runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testCreateNew");
+    }
+
+    public void testCreateExisting() throws Exception {
+        runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testCreateExisting");
+    }
+
+    public void testTree() throws Exception {
+        runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testTree");
+    }
+
+    public void testGetContent() throws Exception {
+        runDeviceTests(CLIENT_PKG, ".DocumentsClientTest", "testGetContent");
+    }
+
+    public void runDeviceTests(String packageName, String testClassName, String testMethodName)
+            throws DeviceNotAvailableException {
+        Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
+    }
+}
diff --git a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/KeySetHostTest.java b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/KeySetHostTest.java
new file mode 100644
index 0000000..dae5ee7
--- /dev/null
+++ b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/KeySetHostTest.java
@@ -0,0 +1,435 @@
+/*
+ * 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.cts.appsecurity;
+
+import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.ddmlib.Log;
+import com.android.ddmlib.Log.LogLevel;
+import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.ddmlib.testrunner.TestResult;
+import com.android.ddmlib.testrunner.TestResult.TestStatus;
+import com.android.ddmlib.testrunner.TestRunResult;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.Map;
+
+/**
+ * Tests for Keyset based features.
+ */
+public class KeySetHostTest extends DeviceTestCase implements IBuildReceiver {
+
+    private static final String RUNNER = "android.support.test.runner.AndroidJUnitRunner";
+
+    /* package with device-side tests */
+    private static final String KEYSET_TEST_PKG = "com.android.cts.keysets.testapp";
+    private static final String KEYSET_TEST_APP_APK = "CtsKeySetTestApp.apk";
+
+    /* plain test apks with different signing and upgrade keysets */
+    private static final String KEYSET_PKG = "com.android.cts.keysets";
+    private static final String A_SIGNED_NO_UPGRADE =
+            "CtsKeySetSigningAUpgradeNone.apk";
+    private static final String A_SIGNED_A_UPGRADE =
+            "CtsKeySetSigningAUpgradeA.apk";
+    private static final String A_SIGNED_B_UPGRADE =
+            "CtsKeySetSigningAUpgradeB.apk";
+    private static final String A_SIGNED_A_OR_B_UPGRADE =
+            "CtsKeySetSigningAUpgradeAOrB.apk";
+    private static final String B_SIGNED_A_UPGRADE =
+            "CtsKeySetSigningBUpgradeA.apk";
+    private static final String B_SIGNED_B_UPGRADE =
+            "CtsKeySetSigningBUpgradeB.apk";
+    private static final String A_AND_B_SIGNED_A_UPGRADE =
+            "CtsKeySetSigningAAndBUpgradeA.apk";
+    private static final String A_AND_B_SIGNED_B_UPGRADE =
+            "CtsKeySetSigningAAndBUpgradeB.apk";
+    private static final String A_AND_C_SIGNED_B_UPGRADE =
+            "CtsKeySetSigningAAndCUpgradeB.apk";
+
+    /* package which defines the KEYSET_PERM_NAME signature permission */
+    private static final String KEYSET_PERM_DEF_PKG =
+            "com.android.cts.keysets_permdef";
+
+    /* The apks defining and using the permission have both A and B as upgrade keys */
+    private static final String PERM_DEF_A_SIGNED =
+            "CtsKeySetPermDefSigningA.apk";
+    private static final String PERM_DEF_B_SIGNED =
+            "CtsKeySetPermDefSigningB.apk";
+    private static final String PERM_USE_A_SIGNED =
+            "CtsKeySetPermUseSigningA.apk";
+    private static final String PERM_USE_B_SIGNED =
+            "CtsKeySetPermUseSigningB.apk";
+
+    private static final String PERM_TEST_CLASS =
+        "com.android.cts.keysets.KeySetPermissionsTest";
+
+    private static final String LOG_TAG = "AppsecurityHostTests";
+
+    private File getTestAppFile(String fileName) throws FileNotFoundException {
+        return mCtsBuild.getTestApp(fileName);
+    }
+
+    /**
+     * Helper method that checks that all tests in given result passed, and attempts to generate
+     * a meaningful error message if they failed.
+     *
+     * @param result
+     */
+    private void assertDeviceTestsPass(TestRunResult result) {
+        assertFalse(String.format("Failed to successfully run device tests for %s. Reason: %s",
+                result.getName(), result.getRunFailureMessage()), result.isRunFailure());
+
+        if (result.hasFailedTests()) {
+
+            /* build a meaningful error message */
+            StringBuilder errorBuilder = new StringBuilder("on-device tests failed:\n");
+            for (Map.Entry<TestIdentifier, TestResult> resultEntry :
+                result.getTestResults().entrySet()) {
+                if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
+                    errorBuilder.append(resultEntry.getKey().toString());
+                    errorBuilder.append(":\n");
+                    errorBuilder.append(resultEntry.getValue().getStackTrace());
+                }
+            }
+            fail(errorBuilder.toString());
+        }
+    }
+
+    /**
+     * Helper method that checks that all tests in given result passed, and attempts to generate
+     * a meaningful error message if they failed.
+     *
+     * @param result
+     */
+    private void assertDeviceTestsFail(String msg, TestRunResult result) {
+        assertFalse(String.format("Failed to successfully run device tests for %s. Reason: %s",
+                result.getName(), result.getRunFailureMessage()), result.isRunFailure());
+
+        if (!result.hasFailedTests()) {
+            fail(msg);
+        }
+    }
+
+    /**
+     * Helper method that will run the specified packages tests on device.
+     *
+     * @param pkgName Android application package for tests
+     * @return <code>true</code> if all tests passed.
+     * @throws DeviceNotAvailableException if connection to device was lost.
+     */
+    private boolean runDeviceTests(String pkgName) throws DeviceNotAvailableException {
+        return runDeviceTests(pkgName, null, null);
+    }
+
+    /**
+     * Helper method that will run the specified packages tests on device.
+     *
+     * @param pkgName Android application package for tests
+     * @return <code>true</code> if all tests passed.
+     * @throws DeviceNotAvailableException if connection to device was lost.
+     */
+    private boolean runDeviceTests(String pkgName, String testClassName, String testMethodName)
+            throws DeviceNotAvailableException {
+        TestRunResult runResult = doRunTests(pkgName, testClassName, testMethodName);
+        return !runResult.hasFailedTests();
+    }
+
+    /**
+     * Helper method to run tests and return the listener that collected the results.
+     *
+     * @param pkgName Android application package for tests
+     * @return the {@link TestRunResult}
+     * @throws DeviceNotAvailableException if connection to device was lost.
+     */
+    private TestRunResult doRunTests(String pkgName, String testClassName,
+            String testMethodName) throws DeviceNotAvailableException {
+
+        RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(pkgName,
+                RUNNER, getDevice().getIDevice());
+        if (testClassName != null && testMethodName != null) {
+            testRunner.setMethodName(testClassName, testMethodName);
+        }
+        CollectingTestListener listener = new CollectingTestListener();
+        getDevice().runInstrumentationTests(testRunner, listener);
+        return listener.getCurrentRunResults();
+    }
+
+    /**
+     * Helper method which installs a package and an upgrade to it.
+     *
+     * @param pkgName - package name of apk.
+     * @param firstApk - first apk to install
+     * @param secondApk - apk to which we attempt to upgrade
+     * @param expectedResult - null if successful, otherwise expected error.
+     */
+    private String testPackageUpgrade(String pkgName, String firstApk,
+             String secondApk) throws Exception {
+        String installResult;
+        try {
+
+            /* cleanup test apps that might be installed from previous partial test run */
+            mDevice.uninstallPackage(pkgName);
+
+            installResult = mDevice.installPackage(getTestAppFile(firstApk),
+                    false);
+            /* we should always succeed on first-install */
+            assertNull(String.format("failed to install %s, Reason: %s", pkgName,
+                       installResult), installResult);
+
+            /* attempt to install upgrade */
+            installResult = mDevice.installPackage(getTestAppFile(secondApk),
+                    true);
+        } finally {
+            mDevice.uninstallPackage(pkgName);
+        }
+        return installResult;
+    }
+    /**
+     * A reference to the device under test.
+     */
+    private ITestDevice mDevice;
+
+    private CtsBuildHelper mCtsBuild;
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+    }
+
+    @Override
+        protected void setUp() throws Exception {
+        super.setUp();
+        mDevice = getDevice();
+        assertNotNull(mCtsBuild);
+    }
+
+    /**
+     * Tests for KeySet based key rotation
+     */
+
+    /*
+     * Check if an apk which does not specify an upgrade-key-set may be upgraded
+     * to an apk which does.
+     */
+    public void testNoKSToUpgradeKS() throws Exception {
+        String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_NO_UPGRADE, A_SIGNED_A_UPGRADE);
+        assertNull(String.format("failed to upgrade keyset app from no specified upgrade-key-set"
+                + "to version with specified upgrade-key-set, Reason: %s", installResult),
+                installResult);
+    }
+
+    /*
+     * Check if an apk which does specify an upgrade-key-set may be upgraded
+     * to an apk which does not.
+     */
+    public void testUpgradeKSToNoKS() throws Exception {
+        String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_UPGRADE, A_SIGNED_NO_UPGRADE);
+        assertNull(String.format("failed to upgrade keyset app from specified upgrade-key-set"
+                + "to version without specified upgrade-key-set, Reason: %s", installResult),
+                installResult);
+    }
+
+    /*
+     * Check if an apk signed by a key other than the upgrade keyset can update
+     * an app
+     */
+    public void testUpgradeKSWithWrongKey() throws Exception {
+        String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_UPGRADE, B_SIGNED_A_UPGRADE);
+        assertNotNull("upgrade to improperly signed app succeeded!", installResult);
+    }
+
+    /*
+     * Check if an apk signed by its signing key, which is not an upgrade key,
+     * can upgrade an app.
+     */
+    public void testUpgradeKSWithWrongSigningKey() throws Exception {
+        String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_B_UPGRADE, A_SIGNED_B_UPGRADE);
+         assertNotNull("upgrade to improperly signed app succeeded!",
+                 installResult);
+    }
+
+    /*
+     * Check if an apk signed by its upgrade key, which is not its signing key,
+     * can upgrade an app.
+     */
+    public void testUpgradeKSWithUpgradeKey() throws Exception {
+        String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_B_UPGRADE, B_SIGNED_B_UPGRADE);
+        assertNull(String.format("failed to upgrade keyset app from one signed by key-a"
+                 + "to version signed by upgrade-key-set key-b, Reason: %s", installResult),
+                 installResult);
+    }
+
+    /*
+     * Check if an apk signed by its upgrade key, which is its signing key, can
+     * upgrade an app.
+     */
+    public void testUpgradeKSWithSigningUpgradeKey() throws Exception {
+        String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_UPGRADE, A_SIGNED_A_UPGRADE);
+        assertNull(String.format("failed to upgrade keyset app from one signed by key-a"
+                    + "to version signed by upgrade-key-set key-b, Reason: %s", installResult),
+                    installResult);
+    }
+
+    /*
+     * Check if an apk signed by multiple keys, one of which is its upgrade key,
+     * can upgrade an app.
+     */
+    public void testMultipleUpgradeKSWithUpgradeKey() throws Exception {
+        String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_UPGRADE,
+                A_AND_B_SIGNED_A_UPGRADE);
+        assertNull(String.format("failed to upgrade keyset app from one signed by key-a"
+                + "to version signed by upgrade-key-set key-b, Reason: %s", installResult),
+                installResult);
+    }
+
+    /*
+     * Check if an apk signed by multiple keys, its signing keys,
+     * but none of which is an upgrade key, can upgrade an app.
+     */
+    public void testMultipleUpgradeKSWithSigningKey() throws Exception {
+        String installResult = testPackageUpgrade(KEYSET_PKG, A_AND_C_SIGNED_B_UPGRADE,
+                A_AND_C_SIGNED_B_UPGRADE);
+        assertNotNull("upgrade to improperly signed app succeeded!", installResult);
+    }
+
+    /*
+     * Check if an apk which defines multiple (two) upgrade keysets is
+     * upgrade-able by either.
+     */
+    public void testUpgradeKSWithMultipleUpgradeKeySetsFirstKey() throws Exception {
+        String installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_OR_B_UPGRADE,
+                A_SIGNED_A_UPGRADE);
+        assertNull(String.format("failed to upgrade keyset app from one signed by key-a"
+                + "to one signed by first upgrade keyset key-a, Reason: %s", installResult),
+                installResult);
+        installResult = testPackageUpgrade(KEYSET_PKG, A_SIGNED_A_OR_B_UPGRADE,
+                B_SIGNED_B_UPGRADE);
+        assertNull(String.format("failed to upgrade keyset app from one signed by key-a"
+                + "to one signed by second upgrade keyset key-b, Reason: %s", installResult),
+                installResult);
+    }
+
+    /**
+     * Helper method which installs a package defining a permission and a package
+     * using the permission, and then rotates the signing keys for one of them.
+     * A device-side test is then used to ascertain whether or not the permission
+     * was appropriately gained or lost.
+     *
+     * @param permDefApk - apk to install which defines the sig-permissoin
+     * @param permUseApk - apk to install which declares it uses the permission
+     * @param upgradeApk - apk to install which upgrades one of the first two
+     * @param hasPermBeforeUpgrade - whether we expect the consuming app to have
+     *        the permission before the upgrade takes place.
+     * @param hasPermAfterUpgrade - whether we expect the consuming app to have
+     *        the permission after the upgrade takes place.
+     */
+    private void testKeyRotationPerm(String permDefApk, String permUseApk,
+            String upgradeApk, boolean hasPermBeforeUpgrade,
+            boolean hasPermAfterUpgrade) throws Exception {
+        try {
+
+            /* cleanup test apps that might be installed from previous partial test run */
+            mDevice.uninstallPackage(KEYSET_PKG);
+            mDevice.uninstallPackage(KEYSET_PERM_DEF_PKG);
+            mDevice.uninstallPackage(KEYSET_TEST_PKG);
+
+            /* install PERM_DEF, KEYSET_APP and KEYSET_TEST_APP */
+            String installResult = mDevice.installPackage(
+                    getTestAppFile(permDefApk), false);
+            assertNull(String.format("failed to install keyset perm-def app, Reason: %s",
+                       installResult), installResult);
+            installResult = getDevice().installPackage(
+                    getTestAppFile(permUseApk), false);
+            assertNull(String.format("failed to install keyset test app. Reason: %s",
+                    installResult), installResult);
+            installResult = getDevice().installPackage(
+                    getTestAppFile(KEYSET_TEST_APP_APK), false);
+            assertNull(String.format("failed to install keyset test app. Reason: %s",
+                    installResult), installResult);
+
+            /* verify package does have perm */
+            TestRunResult result = doRunTests(KEYSET_TEST_PKG, PERM_TEST_CLASS,
+                    "testHasPerm");
+            if (hasPermBeforeUpgrade) {
+                assertDeviceTestsPass(result);
+            } else {
+                assertDeviceTestsFail(" has permission permission it should not have.", result);
+            }
+
+            /* rotate keys */
+            installResult = mDevice.installPackage(getTestAppFile(upgradeApk),
+                    true);
+            result = doRunTests(KEYSET_TEST_PKG, PERM_TEST_CLASS,
+                    "testHasPerm");
+            if (hasPermAfterUpgrade) {
+                assertDeviceTestsPass(result);
+            } else {
+                assertDeviceTestsFail(KEYSET_PKG + " has permission it should not have.", result);
+            }
+        } finally {
+            mDevice.uninstallPackage(KEYSET_PKG);
+            mDevice.uninstallPackage(KEYSET_PERM_DEF_PKG);
+            mDevice.uninstallPackage(KEYSET_TEST_PKG);
+        }
+    }
+
+    /*
+     * Check if an apk gains signature-level permission after changing to a new
+     * signature, for which a permission should be granted.
+     */
+    public void testUpgradeSigPermGained() throws Exception {
+        testKeyRotationPerm(PERM_DEF_A_SIGNED, PERM_USE_B_SIGNED, PERM_USE_A_SIGNED,
+                false, true);
+    }
+
+    /*
+     * Check if an apk loses signature-level permission after changing to a new
+     * signature, from one for which a permission was previously granted.
+     */
+    public void testUpgradeSigPermLost() throws Exception {
+        testKeyRotationPerm(PERM_DEF_A_SIGNED, PERM_USE_A_SIGNED, PERM_USE_B_SIGNED,
+                true, false);
+    }
+
+    /*
+     * Check if an apk gains signature-level permission after the app defining
+     * it rotates to the same signature.
+     */
+    public void testUpgradeDefinerSigPermGained() throws Exception {
+        testKeyRotationPerm(PERM_DEF_A_SIGNED, PERM_USE_B_SIGNED, PERM_DEF_B_SIGNED,
+                false, true);
+    }
+
+    /*
+     * Check if an apk loses signature-level permission after the app defining
+     * it rotates to a different signature.
+     */
+    public void testUpgradeDefinerSigPermLost() throws Exception {
+        testKeyRotationPerm(PERM_DEF_A_SIGNED, PERM_USE_A_SIGNED, PERM_DEF_B_SIGNED,
+                true, false);
+    }
+}
\ No newline at end of file
diff --git a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/SplitTests.java b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/SplitTests.java
new file mode 100644
index 0000000..264c0b1
--- /dev/null
+++ b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/SplitTests.java
@@ -0,0 +1,355 @@
+/*
+ * 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 com.android.cts.appsecurity;
+
+import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.cts.util.AbiUtils;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Tests that verify installing of various split APKs from host side.
+ */
+public class SplitTests extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
+    private static final String PKG = "com.android.cts.splitapp";
+
+    private static final String APK = "CtsSplitApp.apk";
+
+    private static final String APK_mdpi = "CtsSplitApp_mdpi-v4.apk";
+    private static final String APK_hdpi = "CtsSplitApp_hdpi-v4.apk";
+    private static final String APK_xhdpi = "CtsSplitApp_xhdpi-v4.apk";
+    private static final String APK_xxhdpi = "CtsSplitApp_xxhdpi-v4.apk";
+
+    private static final String APK_v7 = "CtsSplitApp_v7.apk";
+    private static final String APK_fr = "CtsSplitApp_fr.apk";
+    private static final String APK_de = "CtsSplitApp_de.apk";
+
+    private static final String APK_x86 = "CtsSplitApp_x86.apk";
+    private static final String APK_x86_64 = "CtsSplitApp_x86_64.apk";
+    private static final String APK_armeabi_v7a = "CtsSplitApp_armeabi-v7a.apk";
+    private static final String APK_armeabi = "CtsSplitApp_armeabi.apk";
+    private static final String APK_arm64_v8a = "CtsSplitApp_arm64-v8a.apk";
+    private static final String APK_mips64 = "CtsSplitApp_mips64.apk";
+    private static final String APK_mips = "CtsSplitApp_mips.apk";
+
+    private static final String APK_DIFF_VERSION_v7 = "CtsSplitAppDiffVersion_v7.apk";
+    private static final String APK_DIFF_CERT_v7 = "CtsSplitAppDiffCert_v7.apk";
+
+    private static final String APK_FEATURE = "CtsSplitAppFeature.apk";
+    private static final String APK_FEATURE_v7 = "CtsSplitAppFeature_v7.apk";
+
+    private static final HashMap<String, String> ABI_TO_APK = new HashMap<>();
+
+    static {
+        ABI_TO_APK.put("x86", APK_x86);
+        ABI_TO_APK.put("x86_64", APK_x86_64);
+        ABI_TO_APK.put("armeabi-v7a", APK_armeabi_v7a);
+        ABI_TO_APK.put("armeabi", APK_armeabi);
+        ABI_TO_APK.put("arm64-v8a", APK_arm64_v8a);
+        ABI_TO_APK.put("mips64", APK_mips64);
+        ABI_TO_APK.put("mips", APK_mips);
+    }
+
+    private IAbi mAbi;
+    private CtsBuildHelper mCtsBuild;
+
+    @Override
+    public void setAbi(IAbi abi) {
+        mAbi = abi;
+    }
+
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        assertNotNull(mAbi);
+        assertNotNull(mCtsBuild);
+
+        getDevice().uninstallPackage(PKG);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+
+        getDevice().uninstallPackage(PKG);
+    }
+
+    public void testSingleBase() throws Exception {
+        new InstallMultiple().addApk(APK).run();
+        runDeviceTests(PKG, ".SplitAppTest", "testSingleBase");
+    }
+
+    public void testDensitySingle() throws Exception {
+        new InstallMultiple().addApk(APK).addApk(APK_mdpi).run();
+        runDeviceTests(PKG, ".SplitAppTest", "testDensitySingle");
+    }
+
+    public void testDensityAll() throws Exception {
+        new InstallMultiple().addApk(APK).addApk(APK_mdpi).addApk(APK_hdpi).addApk(APK_xhdpi)
+                .addApk(APK_xxhdpi).run();
+        runDeviceTests(PKG, ".SplitAppTest", "testDensityAll");
+    }
+
+    /**
+     * Install first with low-resolution resources, then add a split that offers
+     * higher-resolution resources.
+     */
+    public void testDensityBest() throws Exception {
+        new InstallMultiple().addApk(APK).addApk(APK_mdpi).run();
+        runDeviceTests(PKG, ".SplitAppTest", "testDensityBest1");
+
+        // Now splice in an additional split which offers better resources
+        new InstallMultiple().inheritFrom(PKG).addApk(APK_xxhdpi).run();
+        runDeviceTests(PKG, ".SplitAppTest", "testDensityBest2");
+    }
+
+    /**
+     * Verify that an API-based split can change enabled/disabled state of
+     * manifest elements.
+     */
+    public void testApi() throws Exception {
+        new InstallMultiple().addApk(APK).addApk(APK_v7).run();
+        runDeviceTests(PKG, ".SplitAppTest", "testApi");
+    }
+
+    public void testLocale() throws Exception {
+        new InstallMultiple().addApk(APK).addApk(APK_de).addApk(APK_fr).run();
+        runDeviceTests(PKG, ".SplitAppTest", "testLocale");
+    }
+
+    /**
+     * Install test app with <em>single</em> split that exactly matches the
+     * currently active ABI. This also explicitly forces ABI when installing.
+     */
+    public void testNativeSingle() throws Exception {
+        final String abi = mAbi.getName();
+        final String apk = ABI_TO_APK.get(abi);
+        assertNotNull("Failed to find APK for ABI " + abi, apk);
+
+        new InstallMultiple().addApk(APK).addApk(apk).run();
+        runDeviceTests(PKG, ".SplitAppTest", "testNative");
+    }
+
+    /**
+     * Install test app with <em>single</em> split that exactly matches the
+     * currently active ABI. This variant <em>does not</em> force the ABI when
+     * installing, instead exercising the system's ability to choose the ABI
+     * through inspection of the installed app.
+     */
+    public void testNativeSingleNatural() throws Exception {
+        final String abi = mAbi.getName();
+        final String apk = ABI_TO_APK.get(abi);
+        assertNotNull("Failed to find APK for ABI " + abi, apk);
+
+        new InstallMultiple().useNaturalAbi().addApk(APK).addApk(apk).run();
+        runDeviceTests(PKG, ".SplitAppTest", "testNative");
+    }
+
+    /**
+     * Install test app with <em>all</em> possible ABI splits. This also
+     * explicitly forces ABI when installing.
+     */
+    public void testNativeAll() throws Exception {
+        final InstallMultiple inst = new InstallMultiple().addApk(APK);
+        for (String apk : ABI_TO_APK.values()) {
+            inst.addApk(apk);
+        }
+        inst.run();
+        runDeviceTests(PKG, ".SplitAppTest", "testNative");
+    }
+
+    /**
+     * Install test app with <em>all</em> possible ABI splits. This variant
+     * <em>does not</em> force the ABI when installing, instead exercising the
+     * system's ability to choose the ABI through inspection of the installed
+     * app.
+     */
+    public void testNativeAllNatural() throws Exception {
+        final InstallMultiple inst = new InstallMultiple().useNaturalAbi().addApk(APK);
+        for (String apk : ABI_TO_APK.values()) {
+            inst.addApk(apk);
+        }
+        inst.run();
+        runDeviceTests(PKG, ".SplitAppTest", "testNative");
+    }
+
+    public void testDuplicateBase() throws Exception {
+        new InstallMultiple().addApk(APK).addApk(APK).runExpectingFailure();
+    }
+
+    public void testDuplicateSplit() throws Exception {
+        new InstallMultiple().addApk(APK).addApk(APK_v7).addApk(APK_v7).runExpectingFailure();
+    }
+
+    public void testDiffCert() throws Exception {
+        new InstallMultiple().addApk(APK).addApk(APK_DIFF_CERT_v7).runExpectingFailure();
+    }
+
+    public void testDiffCertInherit() throws Exception {
+        new InstallMultiple().addApk(APK).run();
+        // TODO: remove this once we fix 17900178
+        runDeviceTests(PKG, ".SplitAppTest", "testSingleBase");
+        new InstallMultiple().inheritFrom(PKG).addApk(APK_DIFF_CERT_v7).runExpectingFailure();
+    }
+
+    public void testDiffVersion() throws Exception {
+        new InstallMultiple().addApk(APK).addApk(APK_DIFF_VERSION_v7).runExpectingFailure();
+    }
+
+    public void testDiffVersionInherit() throws Exception {
+        new InstallMultiple().addApk(APK).run();
+        // TODO: remove this once we fix 17900178
+        runDeviceTests(PKG, ".SplitAppTest", "testSingleBase");
+        new InstallMultiple().inheritFrom(PKG).addApk(APK_DIFF_VERSION_v7).runExpectingFailure();
+    }
+
+    public void testFeatureBase() throws Exception {
+        new InstallMultiple().addApk(APK).addApk(APK_FEATURE).run();
+        runDeviceTests(PKG, ".SplitAppTest", "testFeatureBase");
+    }
+
+    public void testFeatureApi() throws Exception {
+        new InstallMultiple().addApk(APK).addApk(APK_FEATURE).addApk(APK_FEATURE_v7).run();
+        runDeviceTests(PKG, ".SplitAppTest", "testFeatureApi");
+    }
+
+    public void testInheritUpdatedBase() throws Exception {
+        // TODO: flesh out this test
+    }
+
+    public void testInheritUpdatedSplit() throws Exception {
+        // TODO: flesh out this test
+    }
+
+    class InstallMultiple {
+        private List<String> mArgs = new ArrayList<>();
+        private List<File> mApks = new ArrayList<>();
+        private boolean mUseNaturalAbi;
+
+        InstallMultiple addArg(String arg) {
+            mArgs.add(arg);
+            return this;
+        }
+
+        InstallMultiple addApk(String apk) throws FileNotFoundException {
+            mApks.add(mCtsBuild.getTestApp(apk));
+            return this;
+        }
+
+        InstallMultiple inheritFrom(String packageName) {
+            addArg("-r");
+            addArg("-p " + packageName);
+            return this;
+        }
+
+        InstallMultiple useNaturalAbi() {
+            mUseNaturalAbi = true;
+            return this;
+        }
+
+        void run() throws DeviceNotAvailableException {
+            run(true);
+        }
+
+        void runExpectingFailure() throws DeviceNotAvailableException {
+            run(false);
+        }
+
+        private void run(boolean expectingSuccess) throws DeviceNotAvailableException {
+            final ITestDevice device = getDevice();
+
+            // Create an install session
+            final StringBuilder cmd = new StringBuilder();
+            cmd.append("pm install-create");
+            for (String arg : mArgs) {
+                cmd.append(' ').append(arg);
+            }
+            if (!mUseNaturalAbi) {
+                cmd.append(' ').append(AbiUtils.createAbiFlag(mAbi.getName()));
+            }
+
+            String result = device.executeShellCommand(cmd.toString());
+            assertTrue(result, result.startsWith("Success"));
+
+            final int start = result.lastIndexOf("[");
+            final int end = result.lastIndexOf("]");
+            int sessionId = -1;
+            try {
+                if (start != -1 && end != -1 && start < end) {
+                    sessionId = Integer.parseInt(result.substring(start + 1, end));
+                }
+            } catch (NumberFormatException e) {
+            }
+            if (sessionId == -1) {
+                throw new IllegalStateException("Failed to create install session: " + result);
+            }
+
+            // Push our files into session. Ideally we'd use stdin streaming,
+            // but ddmlib doesn't support it yet.
+            for (int i = 0; i < mApks.size(); i++) {
+                final File apk = mApks.get(i);
+                final String remotePath = "/data/local/tmp/" + i + "_" + apk.getName();
+                if (!device.pushFile(apk, remotePath)) {
+                    throw new IllegalStateException("Failed to push " + apk);
+                }
+
+                cmd.setLength(0);
+                cmd.append("pm install-write");
+                cmd.append(' ').append(sessionId);
+                cmd.append(' ').append(i + "_" + apk.getName());
+                cmd.append(' ').append(remotePath);
+
+                result = device.executeShellCommand(cmd.toString());
+                assertTrue(result, result.startsWith("Success"));
+            }
+
+            // Everything staged; let's pull trigger
+            cmd.setLength(0);
+            cmd.append("pm install-commit");
+            cmd.append(' ').append(sessionId);
+
+            result = device.executeShellCommand(cmd.toString());
+            if (expectingSuccess) {
+                assertTrue(result, result.startsWith("Success"));
+            } else {
+                assertFalse(result, result.startsWith("Success"));
+            }
+        }
+    }
+
+    public void runDeviceTests(String packageName, String testClassName, String testMethodName)
+            throws DeviceNotAvailableException {
+        Utils.runDeviceTests(getDevice(), packageName, testClassName, testMethodName);
+    }
+}
diff --git a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/Utils.java b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/Utils.java
new file mode 100644
index 0000000..c58d6bf
--- /dev/null
+++ b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/Utils.java
@@ -0,0 +1,71 @@
+/*
+ * 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 com.android.cts.appsecurity;
+
+import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.ddmlib.testrunner.TestResult;
+import com.android.ddmlib.testrunner.TestResult.TestStatus;
+import com.android.ddmlib.testrunner.TestRunResult;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.result.CollectingTestListener;
+
+import java.util.Map;
+
+public class Utils {
+    public static void runDeviceTests(ITestDevice device, String packageName)
+            throws DeviceNotAvailableException {
+        runDeviceTests(device, packageName, null, null);
+    }
+
+    public static void runDeviceTests(ITestDevice device, String packageName, String testClassName,
+            String testMethodName) throws DeviceNotAvailableException {
+        if (testClassName != null && testClassName.startsWith(".")) {
+            testClassName = packageName + testClassName;
+        }
+
+        RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(packageName,
+                "android.support.test.runner.AndroidJUnitRunner", device.getIDevice());
+        if (testClassName != null && testMethodName != null) {
+            testRunner.setMethodName(testClassName, testMethodName);
+        }
+
+        final CollectingTestListener listener = new CollectingTestListener();
+        device.runInstrumentationTests(testRunner, listener);
+
+        final TestRunResult result = listener.getCurrentRunResults();
+        if (result.isRunFailure()) {
+            throw new AssertionError("Failed to successfully run device tests for "
+                    + result.getName() + ": " + result.getRunFailureMessage());
+        }
+
+        if (result.hasFailedTests()) {
+            // build a meaningful error message
+            StringBuilder errorBuilder = new StringBuilder("on-device tests failed:\n");
+            for (Map.Entry<TestIdentifier, TestResult> resultEntry :
+                result.getTestResults().entrySet()) {
+                if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
+                    errorBuilder.append(resultEntry.getKey().toString());
+                    errorBuilder.append(":\n");
+                    errorBuilder.append(resultEntry.getValue().getStackTrace());
+                }
+            }
+            throw new AssertionError(errorBuilder.toString());
+        }
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/AppAccessData/Android.mk b/hostsidetests/appsecurity/test-apps/AppAccessData/Android.mk
index 308992e..2c9c624 100644
--- a/hostsidetests/appsecurity/test-apps/AppAccessData/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/AppAccessData/Android.mk
@@ -21,6 +21,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
 
 LOCAL_PACKAGE_NAME := CtsAppAccessData
 
diff --git a/hostsidetests/appsecurity/test-apps/AppAccessData/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/AppAccessData/AndroidManifest.xml
index 3824ef3..ffc104e 100644
--- a/hostsidetests/appsecurity/test-apps/AppAccessData/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/AppAccessData/AndroidManifest.xml
@@ -26,7 +26,7 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.cts.appaccessdata"
                      android:label="Test to create app data."/>
 </manifest>
diff --git a/hostsidetests/appsecurity/test-apps/AppWithData/Android.mk b/hostsidetests/appsecurity/test-apps/AppWithData/Android.mk
index 8bcb045..098ce9c 100644
--- a/hostsidetests/appsecurity/test-apps/AppWithData/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/AppWithData/Android.mk
@@ -21,6 +21,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
 
 LOCAL_PACKAGE_NAME := CtsAppWithData
 
diff --git a/hostsidetests/appsecurity/test-apps/AppWithData/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/AppWithData/AndroidManifest.xml
index 9decbcd..598ebe77 100644
--- a/hostsidetests/appsecurity/test-apps/AppWithData/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/AppWithData/AndroidManifest.xml
@@ -27,7 +27,7 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.cts.appwithdata"
                      android:label="Test to create app data."/>
 </manifest>
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/Android.mk b/hostsidetests/appsecurity/test-apps/DocumentClient/Android.mk
new file mode 100644
index 0000000..910e3cd
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/DocumentClient/Android.mk
@@ -0,0 +1,34 @@
+#
+# 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test ctsdeviceutil ctstestrunner ub-uiautomator
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsDocumentClient
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey2
+
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/DocumentClient/AndroidManifest.xml
new file mode 100644
index 0000000..0064e15
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/DocumentClient/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?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="com.android.cts.documentclient">
+    <application>
+        <uses-library android:name="android.test.runner" />
+        <activity android:name=".MyActivity" />
+    </application>
+    <instrumentation
+        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.cts.documentclient" />
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java
new file mode 100644
index 0000000..fe8f9ee
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java
@@ -0,0 +1,303 @@
+/*
+ * 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 com.android.cts.documentclient;
+
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.SystemClock;
+import android.provider.DocumentsContract;
+import android.provider.DocumentsContract.Document;
+import android.provider.DocumentsProvider;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiSelector;
+import android.test.InstrumentationTestCase;
+import android.test.MoreAsserts;
+import android.text.format.DateUtils;
+
+import com.android.cts.documentclient.MyActivity.Result;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Tests for {@link DocumentsProvider} and interaction with platform intents
+ * like {@link Intent#ACTION_OPEN_DOCUMENT}.
+ */
+public class DocumentsClientTest extends InstrumentationTestCase {
+    private UiDevice mDevice;
+    private MyActivity mActivity;
+
+    private static final long TIMEOUT = 10 * DateUtils.SECOND_IN_MILLIS;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        mDevice = UiDevice.getInstance(getInstrumentation());
+        mActivity = launchActivity(getInstrumentation().getTargetContext().getPackageName(),
+                MyActivity.class, null);
+        mDevice.waitForIdle();
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        super.tearDown();
+        mActivity.finish();
+    }
+
+    public void testOpenSimple() throws Exception {
+        if (!supportedHardware()) return;
+
+        try {
+            // Opening without permission should fail
+            readFully(Uri.parse("content://com.android.cts.documentprovider/document/doc:file1"));
+            fail("Able to read data before opened!");
+        } catch (SecurityException expected) {
+        }
+
+        final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+        intent.addCategory(Intent.CATEGORY_OPENABLE);
+        intent.setType("*/*");
+        mActivity.startActivityForResult(intent, 42);
+
+        // Ensure that we see both of our roots
+        mDevice.waitForIdle();
+        assertTrue("CtsLocal root", new UiObject(new UiSelector().text("CtsLocal")).waitForExists(TIMEOUT));
+        assertTrue("CtsCreate root", new UiObject(new UiSelector().text("CtsCreate")).exists());
+        assertFalse("CtsGetContent", new UiObject(new UiSelector().text("CtsGetContent")).exists());
+
+        // Pick a specific file from our test provider
+        mDevice.waitForIdle();
+        new UiObject(new UiSelector().text("CtsLocal")).click();
+
+        mDevice.waitForIdle();
+        new UiObject(new UiSelector().text("FILE1")).click();
+
+        final Result result = mActivity.getResult();
+        final Uri uri = result.data.getData();
+
+        // We should now have permission to read/write
+        MoreAsserts.assertEquals("fileone".getBytes(), readFully(uri));
+
+        writeFully(uri, "replaced!".getBytes());
+        SystemClock.sleep(500);
+        MoreAsserts.assertEquals("replaced!".getBytes(), readFully(uri));
+    }
+
+    public void testCreateNew() throws Exception {
+        if (!supportedHardware()) return;
+
+        final String DISPLAY_NAME = "My New Awesome Document Title";
+        final String MIME_TYPE = "image/png";
+
+        final Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
+        intent.addCategory(Intent.CATEGORY_OPENABLE);
+        intent.putExtra(Intent.EXTRA_TITLE, DISPLAY_NAME);
+        intent.setType(MIME_TYPE);
+        mActivity.startActivityForResult(intent, 42);
+
+        mDevice.waitForIdle();
+        new UiObject(new UiSelector().text("CtsCreate")).click();
+        mDevice.waitForIdle();
+        new UiObject(new UiSelector().resourceId("com.android.documentsui:id/container_save")
+                .childSelector(new UiSelector().resourceId("android:id/button1"))).click();
+
+        final Result result = mActivity.getResult();
+        final Uri uri = result.data.getData();
+
+        writeFully(uri, "meow!".getBytes());
+
+        assertEquals(DISPLAY_NAME, getColumn(uri, Document.COLUMN_DISPLAY_NAME));
+        assertEquals(MIME_TYPE, getColumn(uri, Document.COLUMN_MIME_TYPE));
+    }
+
+    public void testCreateExisting() throws Exception {
+        if (!supportedHardware()) return;
+
+        final Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
+        intent.addCategory(Intent.CATEGORY_OPENABLE);
+        intent.putExtra(Intent.EXTRA_TITLE, "NEVERUSED");
+        intent.setType("mime2/file2");
+        mActivity.startActivityForResult(intent, 42);
+
+        mDevice.waitForIdle();
+        new UiObject(new UiSelector().text("CtsCreate")).click();
+
+        // Pick file2, which should be selected since MIME matches, then try
+        // picking a non-matching MIME, which should leave file2 selected.
+        mDevice.waitForIdle();
+        new UiObject(new UiSelector().text("FILE2")).click();
+        mDevice.waitForIdle();
+        new UiObject(new UiSelector().text("FILE1")).click();
+
+        mDevice.waitForIdle();
+        new UiObject(new UiSelector().resourceId("com.android.documentsui:id/container_save")
+                .childSelector(new UiSelector().resourceId("android:id/button1"))).click();
+
+        final Result result = mActivity.getResult();
+        final Uri uri = result.data.getData();
+
+        MoreAsserts.assertEquals("filetwo".getBytes(), readFully(uri));
+    }
+
+    public void testTree() throws Exception {
+        if (!supportedHardware()) return;
+
+        final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
+        mActivity.startActivityForResult(intent, 42);
+
+        mDevice.waitForIdle();
+        new UiObject(new UiSelector().text("CtsCreate")).click();
+        mDevice.waitForIdle();
+        new UiObject(new UiSelector().text("DIR2")).click();
+        mDevice.waitForIdle();
+        new UiObject(new UiSelector().resourceId("com.android.documentsui:id/container_save")
+                .childSelector(new UiSelector().resourceId("android:id/button1"))).click();
+
+        final Result result = mActivity.getResult();
+        final Uri uri = result.data.getData();
+
+        // We should have selected DIR2
+        Uri doc = DocumentsContract.buildDocumentUriUsingTree(uri,
+                DocumentsContract.getTreeDocumentId(uri));
+        Uri children = DocumentsContract.buildChildDocumentsUriUsingTree(uri,
+                DocumentsContract.getTreeDocumentId(uri));
+
+        assertEquals("DIR2", getColumn(doc, Document.COLUMN_DISPLAY_NAME));
+
+        // Look around and make sure we can see children
+        final ContentResolver resolver = getInstrumentation().getContext().getContentResolver();
+        Cursor cursor = resolver.query(children, new String[] {
+                Document.COLUMN_DISPLAY_NAME }, null, null, null);
+        try {
+            assertEquals(1, cursor.getCount());
+            assertTrue(cursor.moveToFirst());
+            assertEquals("FILE4", cursor.getString(0));
+        } finally {
+            cursor.close();
+        }
+
+        // Create some documents
+        Uri pic = DocumentsContract.createDocument(resolver, doc, "image/png", "pic.png");
+        Uri dir = DocumentsContract.createDocument(resolver, doc, Document.MIME_TYPE_DIR, "my dir");
+        Uri dirPic = DocumentsContract.createDocument(resolver, dir, "image/png", "pic2.png");
+
+        writeFully(pic, "pic".getBytes());
+        writeFully(dirPic, "dirPic".getBytes());
+
+        // Read then delete existing doc
+        final Uri file4 = DocumentsContract.buildDocumentUriUsingTree(uri, "doc:file4");
+        MoreAsserts.assertEquals("filefour".getBytes(), readFully(file4));
+        assertTrue("delete", DocumentsContract.deleteDocument(resolver, file4));
+        try {
+            MoreAsserts.assertEquals("filefour".getBytes(), readFully(file4));
+            fail("Expected file to be gone");
+        } catch (FileNotFoundException expected) {
+        }
+
+        // And rename something
+        dirPic = DocumentsContract.renameDocument(resolver, dirPic, "wow");
+        assertNotNull("rename", dirPic);
+
+        // We should only see single child
+        assertEquals("wow", getColumn(dirPic, Document.COLUMN_DISPLAY_NAME));
+        MoreAsserts.assertEquals("dirPic".getBytes(), readFully(dirPic));
+
+        try {
+            // Make sure we can't see files outside selected dir
+            getColumn(DocumentsContract.buildDocumentUriUsingTree(uri, "doc:file1"),
+                    Document.COLUMN_DISPLAY_NAME);
+            fail("Somehow read document outside tree!");
+        } catch (SecurityException expected) {
+        }
+    }
+
+    public void testGetContent() throws Exception {
+        if (!supportedHardware()) return;
+
+        final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+        intent.addCategory(Intent.CATEGORY_OPENABLE);
+        intent.setType("*/*");
+        mActivity.startActivityForResult(intent, 42);
+
+        // Look around, we should be able to see both DocumentsProviders and
+        // other GET_CONTENT sources.
+        mDevice.waitForIdle();
+        assertTrue("CtsLocal root", new UiObject(new UiSelector().text("CtsLocal")).waitForExists(TIMEOUT));
+        assertTrue("CtsCreate root", new UiObject(new UiSelector().text("CtsCreate")).exists());
+        assertTrue("CtsGetContent", new UiObject(new UiSelector().text("CtsGetContent")).exists());
+
+        mDevice.waitForIdle();
+        new UiObject(new UiSelector().text("CtsGetContent")).click();
+
+        final Result result = mActivity.getResult();
+        assertEquals("ReSuLt", result.data.getAction());
+    }
+
+    private String getColumn(Uri uri, String column) {
+        final ContentResolver resolver = getInstrumentation().getContext().getContentResolver();
+        final Cursor cursor = resolver.query(uri, new String[] { column }, null, null, null);
+        try {
+            assertTrue(cursor.moveToFirst());
+            return cursor.getString(0);
+        } finally {
+            cursor.close();
+        }
+    }
+
+    private byte[] readFully(Uri uri) throws IOException {
+        InputStream in = getInstrumentation().getContext().getContentResolver()
+                .openInputStream(uri);
+        try {
+            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+            byte[] buffer = new byte[1024];
+            int count;
+            while ((count = in.read(buffer)) != -1) {
+                bytes.write(buffer, 0, count);
+            }
+            return bytes.toByteArray();
+        } finally {
+            in.close();
+        }
+    }
+
+    private void writeFully(Uri uri, byte[] data) throws IOException {
+        OutputStream out = getInstrumentation().getContext().getContentResolver()
+                .openOutputStream(uri);
+        try {
+            out.write(data);
+        } finally {
+            out.close();
+        }
+    }
+
+    private boolean supportedHardware() {
+        final PackageManager pm = getInstrumentation().getContext().getPackageManager();
+        if (pm.hasSystemFeature("android.hardware.type.television")
+                || pm.hasSystemFeature("android.hardware.type.watch")) {
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/MyActivity.java b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/MyActivity.java
new file mode 100644
index 0000000..a6cb28d
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/MyActivity.java
@@ -0,0 +1,65 @@
+/*
+ * 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 com.android.cts.documentclient;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.WindowManager;
+
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.TimeUnit;
+
+public class MyActivity extends Activity {
+    private final SynchronousQueue<Result> mResult = new SynchronousQueue<>();
+
+    public static class Result {
+        public final int resultCode;
+        public final Intent data;
+
+        public Result(int resultCode, Intent data) {
+            this.resultCode = resultCode;
+            this.data = data;
+        }
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
+                | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
+                | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        try {
+            mResult.offer(new Result(resultCode, data), 5, TimeUnit.SECONDS);
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public Result getResult() {
+        try {
+            return mResult.take();
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/DocumentProvider/Android.mk b/hostsidetests/appsecurity/test-apps/DocumentProvider/Android.mk
new file mode 100644
index 0000000..a886fb2
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/DocumentProvider/Android.mk
@@ -0,0 +1,34 @@
+#
+# 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test ctsdeviceutil ctstestrunner ub-uiautomator
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsDocumentProvider
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/DocumentProvider/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/DocumentProvider/AndroidManifest.xml
new file mode 100644
index 0000000..c0fc6cc
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/DocumentProvider/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?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="com.android.cts.documentprovider">
+    <application>
+        <provider android:name=".MyDocumentsProvider"
+                android:authorities="com.android.cts.documentprovider"
+                android:exported="true"
+                android:grantUriPermissions="true"
+                android:permission="android.permission.MANAGE_DOCUMENTS">
+            <intent-filter>
+                <action android:name="android.content.action.DOCUMENTS_PROVIDER" />
+            </intent-filter>
+        </provider>
+
+        <activity android:name=".GetContentActivity"
+                android:label="CtsGetContent">
+            <intent-filter>
+                <action android:name="android.intent.action.GET_CONTENT" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.OPENABLE" />
+                <data android:mimeType="image/*" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/DocumentProvider/src/com/android/cts/documentprovider/GetContentActivity.java b/hostsidetests/appsecurity/test-apps/DocumentProvider/src/com/android/cts/documentprovider/GetContentActivity.java
new file mode 100644
index 0000000..1aba526
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/DocumentProvider/src/com/android/cts/documentprovider/GetContentActivity.java
@@ -0,0 +1,31 @@
+/*
+ * 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 com.android.cts.documentprovider;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+public class GetContentActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setResult(Activity.RESULT_OK, new Intent("ReSuLt"));
+        finish();
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/DocumentProvider/src/com/android/cts/documentprovider/MyDocumentsProvider.java b/hostsidetests/appsecurity/test-apps/DocumentProvider/src/com/android/cts/documentprovider/MyDocumentsProvider.java
new file mode 100644
index 0000000..fb8993c
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/DocumentProvider/src/com/android/cts/documentprovider/MyDocumentsProvider.java
@@ -0,0 +1,282 @@
+/*
+ * 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 com.android.cts.documentprovider;
+
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.database.MatrixCursor.RowBuilder;
+import android.os.AsyncTask;
+import android.os.CancellationSignal;
+import android.os.ParcelFileDescriptor;
+import android.provider.DocumentsContract.Document;
+import android.provider.DocumentsContract.Root;
+import android.provider.DocumentsProvider;
+import android.util.Log;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class MyDocumentsProvider extends DocumentsProvider {
+    private static final String TAG = "TestDocumentsProvider";
+
+    private static final String[] DEFAULT_ROOT_PROJECTION = new String[] {
+            Root.COLUMN_ROOT_ID, Root.COLUMN_FLAGS, Root.COLUMN_ICON, Root.COLUMN_TITLE,
+            Root.COLUMN_DOCUMENT_ID, Root.COLUMN_AVAILABLE_BYTES,
+    };
+
+    private static final String[] DEFAULT_DOCUMENT_PROJECTION = new String[] {
+            Document.COLUMN_DOCUMENT_ID, Document.COLUMN_MIME_TYPE, Document.COLUMN_DISPLAY_NAME,
+            Document.COLUMN_LAST_MODIFIED, Document.COLUMN_FLAGS, Document.COLUMN_SIZE,
+    };
+
+    private static String[] resolveRootProjection(String[] projection) {
+        return projection != null ? projection : DEFAULT_ROOT_PROJECTION;
+    }
+
+    private static String[] resolveDocumentProjection(String[] projection) {
+        return projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION;
+    }
+
+    @Override
+    public boolean onCreate() {
+        resetRoots();
+        return true;
+    }
+
+    @Override
+    public Cursor queryRoots(String[] projection) throws FileNotFoundException {
+        final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
+
+        RowBuilder row = result.newRow();
+        row.add(Root.COLUMN_ROOT_ID, "local");
+        row.add(Root.COLUMN_FLAGS, Root.FLAG_LOCAL_ONLY);
+        row.add(Root.COLUMN_TITLE, "CtsLocal");
+        row.add(Root.COLUMN_SUMMARY, "CtsLocalSummary");
+        row.add(Root.COLUMN_DOCUMENT_ID, "doc:local");
+
+        row = result.newRow();
+        row.add(Root.COLUMN_ROOT_ID, "create");
+        row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_CREATE | Root.FLAG_SUPPORTS_IS_CHILD);
+        row.add(Root.COLUMN_TITLE, "CtsCreate");
+        row.add(Root.COLUMN_DOCUMENT_ID, "doc:create");
+
+        return result;
+    }
+
+    private Map<String, Doc> mDocs = new HashMap<>();
+
+    private Doc mLocalRoot;
+    private Doc mCreateRoot;
+
+    private Doc buildDoc(String docId, String displayName, String mimeType) {
+        final Doc doc = new Doc();
+        doc.docId = docId;
+        doc.displayName = displayName;
+        doc.mimeType = mimeType;
+        mDocs.put(doc.docId, doc);
+        return doc;
+    }
+
+    public void resetRoots() {
+        Log.d(TAG, "resetRoots()");
+
+        mDocs.clear();
+
+        mLocalRoot = buildDoc("doc:local", null, Document.MIME_TYPE_DIR);
+
+        mCreateRoot = buildDoc("doc:create", null, Document.MIME_TYPE_DIR);
+        mCreateRoot.flags = Document.FLAG_DIR_SUPPORTS_CREATE;
+
+        {
+            Doc file1 = buildDoc("doc:file1", "FILE1", "mime1/file1");
+            file1.contents = "fileone".getBytes();
+            file1.flags = Document.FLAG_SUPPORTS_WRITE;
+            mLocalRoot.children.add(file1);
+            mCreateRoot.children.add(file1);
+        }
+
+        {
+            Doc file2 = buildDoc("doc:file2", "FILE2", "mime2/file2");
+            file2.contents = "filetwo".getBytes();
+            file2.flags = Document.FLAG_SUPPORTS_WRITE;
+            mLocalRoot.children.add(file2);
+            mCreateRoot.children.add(file2);
+        }
+
+        Doc dir1 = buildDoc("doc:dir1", "DIR1", Document.MIME_TYPE_DIR);
+        mLocalRoot.children.add(dir1);
+
+        {
+            Doc file3 = buildDoc("doc:file3", "FILE3", "mime3/file3");
+            file3.contents = "filethree".getBytes();
+            file3.flags = Document.FLAG_SUPPORTS_WRITE;
+            dir1.children.add(file3);
+        }
+
+        Doc dir2 = buildDoc("doc:dir2", "DIR2", Document.MIME_TYPE_DIR);
+        mCreateRoot.children.add(dir2);
+
+        {
+            Doc file4 = buildDoc("doc:file4", "FILE4", "mime4/file4");
+            file4.contents = "filefour".getBytes();
+            file4.flags = Document.FLAG_SUPPORTS_WRITE;
+            dir2.children.add(file4);
+        }
+    }
+
+    private static class Doc {
+        public String docId;
+        public int flags;
+        public String displayName;
+        public long size;
+        public String mimeType;
+        public long lastModified;
+        public byte[] contents;
+        public List<Doc> children = new ArrayList<>();
+
+        public void include(MatrixCursor result) {
+            final RowBuilder row = result.newRow();
+            row.add(Document.COLUMN_DOCUMENT_ID, docId);
+            row.add(Document.COLUMN_DISPLAY_NAME, displayName);
+            row.add(Document.COLUMN_SIZE, size);
+            row.add(Document.COLUMN_MIME_TYPE, mimeType);
+            row.add(Document.COLUMN_FLAGS, flags);
+            row.add(Document.COLUMN_LAST_MODIFIED, lastModified);
+        }
+    }
+
+    @Override
+    public boolean isChildDocument(String parentDocumentId, String documentId) {
+        for (Doc doc : mDocs.get(parentDocumentId).children) {
+            if (doc.docId.equals(documentId)) {
+                return true;
+            }
+            if (Document.MIME_TYPE_DIR.equals(doc.mimeType)) {
+                return isChildDocument(doc.docId, documentId);
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String createDocument(String parentDocumentId, String mimeType, String displayName)
+            throws FileNotFoundException {
+        final String docId = "doc:" + System.currentTimeMillis();
+        final Doc doc = buildDoc(docId, displayName, mimeType);
+        doc.flags = Document.FLAG_SUPPORTS_WRITE | Document.FLAG_SUPPORTS_RENAME;
+        mDocs.get(parentDocumentId).children.add(doc);
+        return docId;
+    }
+
+    @Override
+    public String renameDocument(String documentId, String displayName)
+            throws FileNotFoundException {
+        mDocs.get(documentId).displayName = displayName;
+        return null;
+    }
+
+    @Override
+    public void deleteDocument(String documentId) throws FileNotFoundException {
+        mDocs.remove(documentId);
+        for (Doc doc : mDocs.values()) {
+            doc.children.remove(documentId);
+        }
+    }
+
+    @Override
+    public Cursor queryDocument(String documentId, String[] projection)
+            throws FileNotFoundException {
+        final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
+        mDocs.get(documentId).include(result);
+        return result;
+    }
+
+    @Override
+    public Cursor queryChildDocuments(String parentDocumentId, String[] projection,
+            String sortOrder) throws FileNotFoundException {
+        final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
+        for (Doc doc : mDocs.get(parentDocumentId).children) {
+            doc.include(result);
+        }
+        return result;
+    }
+
+    @Override
+    public ParcelFileDescriptor openDocument(String documentId, String mode,
+            CancellationSignal signal) throws FileNotFoundException {
+        final Doc doc = mDocs.get(documentId);
+        if (doc == null) {
+            throw new FileNotFoundException();
+        }
+        final ParcelFileDescriptor[] pipe;
+        try {
+            pipe = ParcelFileDescriptor.createPipe();
+        } catch (IOException e) {
+            throw new IllegalStateException(e);
+        }
+        if (mode.contains("w")) {
+            new AsyncTask<Void, Void, Void>() {
+                @Override
+                protected Void doInBackground(Void... params) {
+                    try {
+                        final InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(
+                                pipe[0]);
+                        doc.contents = readFullyNoClose(is);
+                        is.close();
+                    } catch (IOException e) {
+                        Log.w(TAG, "Failed to stream", e);
+                    }
+                    return null;
+                }
+            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+            return pipe[1];
+        } else {
+            new AsyncTask<Void, Void, Void>() {
+                @Override
+                protected Void doInBackground(Void... params) {
+                    try {
+                        final OutputStream os = new ParcelFileDescriptor.AutoCloseOutputStream(
+                                pipe[1]);
+                        os.write(doc.contents);
+                        os.close();
+                    } catch (IOException e) {
+                        Log.w(TAG, "Failed to stream", e);
+                    }
+                    return null;
+                }
+            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+            return pipe[0];
+        }
+    }
+
+    private static byte[] readFullyNoClose(InputStream in) throws IOException {
+        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+        byte[] buffer = new byte[1024];
+        int count;
+        while ((count = in.read(buffer)) != -1) {
+            bytes.write(buffer, 0, count);
+        }
+        return bytes.toByteArray();
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/Android.mk b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/Android.mk
index bc99560..afc8764 100644
--- a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/Android.mk
@@ -18,6 +18,7 @@
 
 LOCAL_MODULE_TAGS := tests
 LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_PACKAGE_NAME := CtsExternalStorageApp
diff --git a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/AndroidManifest.xml
index 0ba6684..9d8f615 100644
--- a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/AndroidManifest.xml
@@ -20,7 +20,7 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
         android:targetPackage="com.android.cts.externalstorageapp" />
 
 </manifest>
diff --git a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java
index f38236b..5b4d9f7 100644
--- a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java
+++ b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java
@@ -274,8 +274,38 @@
         }
     }
 
+    private static boolean isWhiteList(File file) {
+        final String[] whiteLists = {
+                "autorun.inf", ".android_secure", "android_secure"
+        };
+        if (file.getParentFile().getAbsolutePath().equals(
+                Environment.getExternalStorageDirectory().getAbsolutePath())) {
+            for (String whiteList : whiteLists) {
+                if (file.getName().equalsIgnoreCase(whiteList)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private static File[] removeWhiteList(File[] files) {
+        List<File> fileList = new ArrayList<File>();
+        if (files == null) {
+            return null;
+        }
+
+        for (File file : files) {
+            if (!isWhiteList(file)) {
+                fileList.add(file);
+            }
+        }
+        return fileList.toArray(new File[fileList.size()]);
+    }
+
     public static void deleteContents(File dir) throws IOException {
         File[] files = dir.listFiles();
+        files = removeWhiteList(files);
         if (files != null) {
             for (File file : files) {
                 if (file.isDirectory()) {
@@ -283,7 +313,9 @@
                 }
                 assertTrue(file.delete());
             }
-            assertEquals(0, dir.listFiles().length);
+
+            File[] dirs = removeWhiteList(dir.listFiles());
+            assertEquals(0, dirs.length);
         }
     }
 
diff --git a/hostsidetests/appsecurity/test-apps/InstrumentationAppDiffCert/Android.mk b/hostsidetests/appsecurity/test-apps/InstrumentationAppDiffCert/Android.mk
index 268ac73..e8ce3b8 100644
--- a/hostsidetests/appsecurity/test-apps/InstrumentationAppDiffCert/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/InstrumentationAppDiffCert/Android.mk
@@ -21,6 +21,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
 
 LOCAL_PACKAGE_NAME := CtsInstrumentationAppDiffCert
 
diff --git a/hostsidetests/appsecurity/test-apps/InstrumentationAppDiffCert/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/InstrumentationAppDiffCert/AndroidManifest.xml
index 8102656..a958c4c 100644
--- a/hostsidetests/appsecurity/test-apps/InstrumentationAppDiffCert/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/InstrumentationAppDiffCert/AndroidManifest.xml
@@ -34,7 +34,7 @@
     A self-instrumenting test runner, that will try to start the above instrumentation and
     verify it fails.
      -->
-    <instrumentation android:name="android.test.InstrumentationTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.cts.instrumentationdiffcertapp"
                      android:label="Test for instrumentation with different cert" />
 </manifest>
diff --git a/hostsidetests/appsecurity/test-apps/MultiUserStorageApp/Android.mk b/hostsidetests/appsecurity/test-apps/MultiUserStorageApp/Android.mk
index 48f88b8..1dd109a 100644
--- a/hostsidetests/appsecurity/test-apps/MultiUserStorageApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/MultiUserStorageApp/Android.mk
@@ -18,6 +18,7 @@
 
 LOCAL_MODULE_TAGS := tests
 LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) \
     ../ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java
diff --git a/hostsidetests/appsecurity/test-apps/MultiUserStorageApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/MultiUserStorageApp/AndroidManifest.xml
index 6ace31b..8b599f2 100644
--- a/hostsidetests/appsecurity/test-apps/MultiUserStorageApp/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/MultiUserStorageApp/AndroidManifest.xml
@@ -20,7 +20,7 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
         android:targetPackage="com.android.cts.multiuserstorageapp" />
 
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/Android.mk b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/Android.mk
index 938b325..60d6fad 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/Android.mk
@@ -21,6 +21,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
 
 LOCAL_PACKAGE_NAME := CtsPermissionDeclareApp
 
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/Android.mk b/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/Android.mk
index acdc20f..ba7285c 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/Android.mk
@@ -21,6 +21,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_SDK_VERSION := 16
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
 
 LOCAL_PACKAGE_NAME := CtsPermissionDeclareAppCompat
 
diff --git a/hostsidetests/appsecurity/test-apps/ReadExternalStorageApp/Android.mk b/hostsidetests/appsecurity/test-apps/ReadExternalStorageApp/Android.mk
index 44e4bef..3e392e3 100644
--- a/hostsidetests/appsecurity/test-apps/ReadExternalStorageApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/ReadExternalStorageApp/Android.mk
@@ -18,6 +18,7 @@
 
 LOCAL_MODULE_TAGS := tests
 LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) \
     ../ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java
diff --git a/hostsidetests/appsecurity/test-apps/ReadExternalStorageApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/ReadExternalStorageApp/AndroidManifest.xml
index f6582b9..03884c9 100644
--- a/hostsidetests/appsecurity/test-apps/ReadExternalStorageApp/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/ReadExternalStorageApp/AndroidManifest.xml
@@ -20,7 +20,7 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
         android:targetPackage="com.android.cts.readexternalstorageapp" />
 
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
diff --git a/hostsidetests/appsecurity/test-apps/SharedUidInstall/Android.mk b/hostsidetests/appsecurity/test-apps/SharedUidInstall/Android.mk
index 25ba1fe..76187ab 100644
--- a/hostsidetests/appsecurity/test-apps/SharedUidInstall/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SharedUidInstall/Android.mk
@@ -21,6 +21,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
 
 LOCAL_PACKAGE_NAME := CtsSharedUidInstall
 
diff --git a/hostsidetests/appsecurity/test-apps/SharedUidInstallDiffCert/Android.mk b/hostsidetests/appsecurity/test-apps/SharedUidInstallDiffCert/Android.mk
index a00b009..c1422ec 100644
--- a/hostsidetests/appsecurity/test-apps/SharedUidInstallDiffCert/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SharedUidInstallDiffCert/Android.mk
@@ -21,6 +21,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
 
 LOCAL_PACKAGE_NAME := CtsSharedUidInstallDiffCert
 
diff --git a/hostsidetests/appsecurity/test-apps/SimpleAppInstall/Android.mk b/hostsidetests/appsecurity/test-apps/SimpleAppInstall/Android.mk
index 3cd78cf..fb925cd 100644
--- a/hostsidetests/appsecurity/test-apps/SimpleAppInstall/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SimpleAppInstall/Android.mk
@@ -21,6 +21,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
 
 LOCAL_PACKAGE_NAME := CtsSimpleAppInstall
 
diff --git a/hostsidetests/appsecurity/test-apps/SimpleAppInstallDiffCert/Android.mk b/hostsidetests/appsecurity/test-apps/SimpleAppInstallDiffCert/Android.mk
index 5fbc910..2224d72 100644
--- a/hostsidetests/appsecurity/test-apps/SimpleAppInstallDiffCert/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SimpleAppInstallDiffCert/Android.mk
@@ -21,6 +21,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
 
 LOCAL_PACKAGE_NAME := CtsSimpleAppInstallDiffCert
 
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/Android.mk
new file mode 100644
index 0000000..8b25f4b
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/Android.mk
@@ -0,0 +1,89 @@
+#
+# 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsSplitApp
+LOCAL_PACKAGE_SPLITS := mdpi-v4 hdpi-v4 xhdpi-v4 xxhdpi-v4 v7 fr de
+
+LOCAL_ASSET_DIR := $(LOCAL_PATH)/assets
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+LOCAL_AAPT_FLAGS := --version-code 100 --version-name OneHundred --replace-version -c mdpi -c hdpi -c xhdpi -c xxhdpi
+
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+
+################################################
+# Define a variant with a different version code
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsSplitAppDiffVersion
+LOCAL_PACKAGE_SPLITS := v7
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+LOCAL_AAPT_FLAGS := --version-code 101 --version-name OneHundredOne --replace-version -c mdpi -c hdpi -c xhdpi -c xxhdpi
+
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+
+################################################
+# Define a variant with a different signature
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsSplitAppDiffCert
+LOCAL_PACKAGE_SPLITS := v7
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey2
+LOCAL_AAPT_FLAGS := --version-code 100 --version-name OneHundred --replace-version -c mdpi -c hdpi -c xhdpi -c xxhdpi
+
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+
+ifeq (,$(ONE_SHOT_MAKEFILE))
+include $(LOCAL_PATH)/libs/Android.mk $(LOCAL_PATH)/feature/Android.mk
+endif
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml
new file mode 100644
index 0000000..dba384c
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml
@@ -0,0 +1,43 @@
+<?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="com.android.cts.splitapp">
+
+    <uses-permission android:name="android.permission.CAMERA" />
+
+    <application android:label="SplitApp">
+        <activity android:name=".MyActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+            <meta-data android:name="android.service.wallpaper" android:resource="@xml/my_activity_meta" />
+        </activity>
+        <receiver android:name=".MyReceiver"
+                android:enabled="@bool/my_receiver_enabled">
+            <intent-filter>
+                <action android:name="android.intent.action.DATE_CHANGED" />
+            </intent-filter>
+        </receiver>
+
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.cts.splitapp" />
+
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/NativeTemplate.mk b/hostsidetests/appsecurity/test-apps/SplitApp/NativeTemplate.mk
new file mode 100644
index 0000000..b61c5d6
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/NativeTemplate.mk
@@ -0,0 +1,28 @@
+#
+# 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsSplitApp_ARCHARCH
+
+LOCAL_JAVA_RESOURCE_DIRS := raw
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/README b/hostsidetests/appsecurity/test-apps/SplitApp/README
new file mode 100644
index 0000000..480289e
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/README
@@ -0,0 +1,7 @@
+
+The entire libs/ directory is built and constructed automatically with
+the build_libs.sh script.  Don't attempt to modify manually.  To rebuild
+the native code, make the following change to the NDK to pass through
+the target architecture, and then run build_libs.sh:
+
+build/core/build-binary.mk:LOCAL_CFLAGS := -DANDROID -D__ANDROID_ARCH__=\"$(TARGET_ARCH_ABI)\" $(LOCAL_CFLAGS)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/assets/dir/dirfile1.txt b/hostsidetests/appsecurity/test-apps/SplitApp/assets/dir/dirfile1.txt
new file mode 100644
index 0000000..8fba750
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/assets/dir/dirfile1.txt
@@ -0,0 +1 @@
+DIRFILE1
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/assets/file1.txt b/hostsidetests/appsecurity/test-apps/SplitApp/assets/file1.txt
new file mode 100644
index 0000000..cb4ee5e
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/assets/file1.txt
@@ -0,0 +1 @@
+FILE1
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/build_libs.sh b/hostsidetests/appsecurity/test-apps/SplitApp/build_libs.sh
new file mode 100755
index 0000000..6090374
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/build_libs.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+#
+# 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.
+#
+
+NDK_BUILD="$HOME/android-ndk-r10b/ndk-build"
+
+# Go build everything
+rm -rf libs
+cd jni/
+$NDK_BUILD clean
+$NDK_BUILD
+cd ../
+
+for arch in `ls libs/`;
+do
+    (
+    mkdir -p tmp/$arch/raw/lib/$arch/
+    mv libs/$arch/* tmp/$arch/raw/lib/$arch/
+
+    echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>
+<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"
+        package=\"com.android.cts.splitapp\"
+        split=\"lib_${arch//[^a-zA-Z0-9_]/_}\">
+    <application android:hasCode=\"false\" />
+</manifest>" > tmp/$arch/AndroidManifest.xml
+
+    cp NativeTemplate.mk tmp/$arch/Android.mk
+    sed -i -r "s/ARCHARCH/$arch/" tmp/$arch/Android.mk
+
+    )
+done
+
+echo "include \$(call all-subdir-makefiles)" > tmp/Android.mk
+
+rm -rf libs
+rm -rf obj
+
+mv tmp libs
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/feature/Android.mk
new file mode 100644
index 0000000..e93f6c3
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/Android.mk
@@ -0,0 +1,38 @@
+#
+# 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)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_PACKAGE_NAME := CtsSplitAppFeature
+LOCAL_PACKAGE_SPLITS := v7
+
+LOCAL_ASSET_DIR := $(LOCAL_PATH)/assets
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+LOCAL_AAPT_FLAGS := --version-code 100 --version-name OneHundred --replace-version -c mdpi -c hdpi -c xhdpi -c xxhdpi
+
+LOCAL_MODULE_TAGS := tests
+
+featureOf := CtsSplitApp
+featureOfApk := $(call intermediates-dir-for,APPS,$(featureOf))/package.apk
+localRStamp := $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),,COMMON)/src/R.stamp
+$(localRStamp): $(featureOfApk)
+
+LOCAL_AAPT_FLAGS += --feature-of $(featureOfApk)
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/feature/AndroidManifest.xml
new file mode 100644
index 0000000..8ba3c2f
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/AndroidManifest.xml
@@ -0,0 +1,46 @@
+<?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="com.android.cts.splitapp"
+        featureName="feature">
+
+    <!-- New permission should be ignored -->
+    <uses-permission android:name="android.permission.INTERNET" />
+
+    <!-- New application flag should be ignored -->
+    <application android:largeHeap="true">
+        <activity android:name=".FeatureActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+            <meta-data android:name="android.service.wallpaper" android:resource="@xml/my_activity_meta" />
+        </activity>
+        <receiver android:name=".FeatureReceiver"
+                android:enabled="@bool/feature_receiver_enabled">
+            <intent-filter>
+                <action android:name="android.intent.action.DATE_CHANGED" />
+            </intent-filter>
+        </receiver>
+        <service android:name=".FeatureService">
+            <intent-filter>
+                <action android:name="com.android.cts.splitapp.service" />
+            </intent-filter>
+        </service>
+        <provider android:name=".FeatureProvider" android:authorities="com.android.cts.splitapp.provider" />
+    </application>
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/assets/dir/dirfile2.txt b/hostsidetests/appsecurity/test-apps/SplitApp/feature/assets/dir/dirfile2.txt
new file mode 100644
index 0000000..c4a2fff
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/assets/dir/dirfile2.txt
@@ -0,0 +1 @@
+DIRFILE2
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/assets/file2.txt b/hostsidetests/appsecurity/test-apps/SplitApp/feature/assets/file2.txt
new file mode 100644
index 0000000..d77231c
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/assets/file2.txt
@@ -0,0 +1 @@
+FILE2
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/res/values-v7/values.xml b/hostsidetests/appsecurity/test-apps/SplitApp/feature/res/values-v7/values.xml
new file mode 100644
index 0000000..8d91234
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/res/values-v7/values.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<resources>
+    <bool name="feature_receiver_enabled">false</bool>
+    <integer name="feature_integer">321</integer>
+</resources>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/res/values/values.xml b/hostsidetests/appsecurity/test-apps/SplitApp/feature/res/values/values.xml
new file mode 100644
index 0000000..7d670cf
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/res/values/values.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+
+<resources>
+    <bool name="feature_receiver_enabled">true</bool>
+    <string name="feature_string">red</string>
+    <integer name="feature_integer">123</integer>
+</resources>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureActivity.java b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureActivity.java
new file mode 100644
index 0000000..a4df004
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureActivity.java
@@ -0,0 +1,22 @@
+/*
+ * 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 com.android.cts.splitapp;
+
+import android.app.Activity;
+
+public class FeatureActivity extends Activity {
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureLogic.java b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureLogic.java
new file mode 100644
index 0000000..0481546
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureLogic.java
@@ -0,0 +1,28 @@
+/*
+ * 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 com.android.cts.splitapp;
+
+import android.util.Log;
+
+public class FeatureLogic {
+    private static final String TAG = "FeatureLogic";
+
+    public static int mult(int a, int b) {
+        Log.d(TAG, "FeatureLogic.mult(" + a + ", " + b + ")");
+        return a * b;
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureProvider.java b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureProvider.java
new file mode 100644
index 0000000..087aeb7
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureProvider.java
@@ -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.
+ */
+
+package com.android.cts.splitapp;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.util.Log;
+
+import java.lang.reflect.Field;
+
+public class FeatureProvider extends ContentProvider {
+    private static final String TAG = "FeatureProvider";
+
+    public static boolean sCreated = false;
+
+    @Override
+    public boolean onCreate() {
+        Log.d(TAG, "FeatureProvider.onCreate()");
+
+        sCreated = true;
+
+        try {
+            // Just reach out and touch
+            final Class<?> test = Class.forName("com.android.cts.splitapp.SplitAppTest");
+            final Field touched = test.getDeclaredField("sFeatureTouched");
+            touched.set(null, true);
+
+            // Also make sure we can read a resource from the base; we just
+            // stash the value we saw over on the test for them to verify.
+            final Class<?> baseR = Class.forName("com.android.cts.splitapp.BaseR");
+            final int stringId = (int) baseR.getDeclaredField("my_string1").get(null);
+            final Field value = test.getDeclaredField("sFeatureValue");
+            value.set(null, getContext().getResources().getString(stringId));
+
+        } catch (Throwable t) {
+            // We're okay if anything above fails, since the test later verifies
+            // that we actually touched the boolean.
+            Log.e(TAG, "Failed to communicate back to base", t);
+        }
+
+        return true;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+            String sortOrder) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+        throw new UnsupportedOperationException();
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureR.java b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureR.java
new file mode 100644
index 0000000..3dbd83b
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureR.java
@@ -0,0 +1,23 @@
+/*
+ * 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 com.android.cts.splitapp;
+
+public class FeatureR {
+    public static final int feature_receiver_enabled = R.bool.feature_receiver_enabled;
+    public static final int feature_integer = R.integer.feature_integer;
+    public static final int feature_string = R.string.feature_string;
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureReceiver.java b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureReceiver.java
new file mode 100644
index 0000000..49559f3
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureReceiver.java
@@ -0,0 +1,28 @@
+/*
+ * 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 com.android.cts.splitapp;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public class FeatureReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        // Ignored
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureService.java b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureService.java
new file mode 100644
index 0000000..b07297f
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/feature/src/com/android/cts/splitapp/FeatureService.java
@@ -0,0 +1,31 @@
+/*
+ * 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 com.android.cts.splitapp;
+
+import android.app.IntentService;
+import android.content.Intent;
+
+public class FeatureService extends IntentService {
+    public FeatureService() {
+        super("Feature1Service");
+    }
+
+    @Override
+    protected void onHandleIntent(Intent intent) {
+        // Ignored
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/jni/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/jni/Android.mk
new file mode 100644
index 0000000..507b13a
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/jni/Android.mk
@@ -0,0 +1,26 @@
+#
+# Copyright (C) 2008 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libsplitappjni
+LOCAL_SRC_FILES := com_android_cts_splitapp_Native.cpp
+
+LOCAL_LDLIBS += -llog
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/jni/Application.mk b/hostsidetests/appsecurity/test-apps/SplitApp/jni/Application.mk
new file mode 100644
index 0000000..a304c8f
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/jni/Application.mk
@@ -0,0 +1,2 @@
+APP_ABI := all
+APP_PLATFORM := android-10
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/jni/com_android_cts_splitapp_Native.cpp b/hostsidetests/appsecurity/test-apps/SplitApp/jni/com_android_cts_splitapp_Native.cpp
new file mode 100644
index 0000000..01302f5
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/jni/com_android_cts_splitapp_Native.cpp
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "SplitApp"
+
+#include <android/log.h>
+#include <stdio.h>
+
+#include "jni.h"
+
+#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
+#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
+
+
+static jint add(JNIEnv *env, jobject thiz, jint a, jint b) {
+    int result = a + b;
+    LOGI("%d + %d = %d", a, b, result);
+    return result;
+}
+
+static jstring arch(JNIEnv *env, jobject thiz) {
+    return env->NewStringUTF(__ANDROID_ARCH__);
+}
+
+static const char *classPathName = "com/android/cts/splitapp/Native";
+
+static JNINativeMethod methods[] = {
+    {"add", "(II)I", (void*)add },
+    {"arch", "()Ljava/lang/String;", (void*)arch },
+};
+
+static int registerNativeMethods(JNIEnv* env, const char* className, JNINativeMethod* gMethods, int numMethods) {
+    jclass clazz;
+
+    clazz = env->FindClass(className);
+    if (clazz == NULL) {
+        LOGE("Native registration unable to find class '%s'", className);
+        return JNI_FALSE;
+    }
+    if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
+        LOGE("RegisterNatives failed for '%s'", className);
+        return JNI_FALSE;
+    }
+
+    return JNI_TRUE;
+}
+
+static int registerNatives(JNIEnv* env) {
+    if (!registerNativeMethods(env, classPathName, methods, sizeof(methods) / sizeof(methods[0]))) {
+        return JNI_FALSE;
+    }
+
+    return JNI_TRUE;
+}
+
+typedef union {
+    JNIEnv* env;
+    void* venv;
+} UnionJNIEnvToVoid;
+
+jint JNI_OnLoad(JavaVM* vm, void* reserved) {
+    UnionJNIEnvToVoid uenv;
+    uenv.venv = NULL;
+    jint result = -1;
+    JNIEnv* env = NULL;
+
+    LOGI("JNI_OnLoad");
+
+    if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) {
+        LOGE("ERROR: GetEnv failed");
+        goto bail;
+    }
+    env = uenv.env;
+
+    if (registerNatives(env) != JNI_TRUE) {
+        LOGE("ERROR: registerNatives failed");
+        goto bail;
+    }
+
+    result = JNI_VERSION_1_4;
+
+bail:
+    return result;
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/Android.mk
new file mode 100644
index 0000000..5053e7d
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/Android.mk
@@ -0,0 +1 @@
+include $(call all-subdir-makefiles)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/Android.mk
new file mode 100644
index 0000000..543e4ac
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/Android.mk
@@ -0,0 +1,28 @@
+#
+# 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsSplitApp_arm64-v8a
+
+LOCAL_JAVA_RESOURCE_DIRS := raw
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/AndroidManifest.xml
new file mode 100644
index 0000000..206e207
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.cts.splitapp"
+        split="lib_arm64_v8a">
+    <application android:hasCode="false" />
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/raw/lib/arm64-v8a/libsplitappjni.so b/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/raw/lib/arm64-v8a/libsplitappjni.so
new file mode 100755
index 0000000..bcc8f51
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/arm64-v8a/raw/lib/arm64-v8a/libsplitappjni.so
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/Android.mk
new file mode 100644
index 0000000..7cdef62
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/Android.mk
@@ -0,0 +1,28 @@
+#
+# 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsSplitApp_armeabi-v7a
+
+LOCAL_JAVA_RESOURCE_DIRS := raw
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/AndroidManifest.xml
new file mode 100644
index 0000000..1d19420
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.cts.splitapp"
+        split="lib_armeabi_v7a">
+    <application android:hasCode="false" />
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/raw/lib/armeabi-v7a/libsplitappjni.so b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/raw/lib/armeabi-v7a/libsplitappjni.so
new file mode 100755
index 0000000..010c372
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi-v7a/raw/lib/armeabi-v7a/libsplitappjni.so
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/Android.mk
new file mode 100644
index 0000000..26ec5bd
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/Android.mk
@@ -0,0 +1,28 @@
+#
+# 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsSplitApp_armeabi
+
+LOCAL_JAVA_RESOURCE_DIRS := raw
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/AndroidManifest.xml
new file mode 100644
index 0000000..95fdb23
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.cts.splitapp"
+        split="lib_armeabi">
+    <application android:hasCode="false" />
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/raw/lib/armeabi/libsplitappjni.so b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/raw/lib/armeabi/libsplitappjni.so
new file mode 100755
index 0000000..8977e70
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/armeabi/raw/lib/armeabi/libsplitappjni.so
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/Android.mk
new file mode 100644
index 0000000..fea0603
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/Android.mk
@@ -0,0 +1,28 @@
+#
+# 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsSplitApp_mips
+
+LOCAL_JAVA_RESOURCE_DIRS := raw
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/AndroidManifest.xml
new file mode 100644
index 0000000..53ea38f
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.cts.splitapp"
+        split="lib_mips">
+    <application android:hasCode="false" />
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/raw/lib/mips/libsplitappjni.so b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/raw/lib/mips/libsplitappjni.so
new file mode 100755
index 0000000..45b8382
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips/raw/lib/mips/libsplitappjni.so
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/Android.mk
new file mode 100644
index 0000000..3cc5609
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/Android.mk
@@ -0,0 +1,28 @@
+#
+# 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsSplitApp_mips64
+
+LOCAL_JAVA_RESOURCE_DIRS := raw
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/AndroidManifest.xml
new file mode 100644
index 0000000..0b75613
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.cts.splitapp"
+        split="lib_mips64">
+    <application android:hasCode="false" />
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/raw/lib/mips64/libsplitappjni.so b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/raw/lib/mips64/libsplitappjni.so
new file mode 100755
index 0000000..8c29904
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/mips64/raw/lib/mips64/libsplitappjni.so
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/Android.mk
new file mode 100644
index 0000000..d45ca8f
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/Android.mk
@@ -0,0 +1,28 @@
+#
+# 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsSplitApp_x86
+
+LOCAL_JAVA_RESOURCE_DIRS := raw
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/AndroidManifest.xml
new file mode 100644
index 0000000..4219791
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.cts.splitapp"
+        split="lib_x86">
+    <application android:hasCode="false" />
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/raw/lib/x86/libsplitappjni.so b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/raw/lib/x86/libsplitappjni.so
new file mode 100755
index 0000000..2993d92
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86/raw/lib/x86/libsplitappjni.so
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/Android.mk b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/Android.mk
new file mode 100644
index 0000000..fa0e488
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/Android.mk
@@ -0,0 +1,28 @@
+#
+# 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsSplitApp_x86_64
+
+LOCAL_JAVA_RESOURCE_DIRS := raw
+
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+LOCAL_AAPT_FLAGS := --version-code 100 --replace-version
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/AndroidManifest.xml
new file mode 100644
index 0000000..e697d5c
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.cts.splitapp"
+        split="lib_x86_64">
+    <application android:hasCode="false" />
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/raw/lib/x86_64/libsplitappjni.so b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/raw/lib/x86_64/libsplitappjni.so
new file mode 100755
index 0000000..23f4169
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/libs/x86_64/raw/lib/x86_64/libsplitappjni.so
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/res/drawable-hdpi/image.png b/hostsidetests/appsecurity/test-apps/SplitApp/res/drawable-hdpi/image.png
new file mode 100644
index 0000000..b5f1a13
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/res/drawable-hdpi/image.png
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/res/drawable-mdpi/image.png b/hostsidetests/appsecurity/test-apps/SplitApp/res/drawable-mdpi/image.png
new file mode 100644
index 0000000..2d67c8f
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/res/drawable-mdpi/image.png
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/res/drawable-xhdpi/image.png b/hostsidetests/appsecurity/test-apps/SplitApp/res/drawable-xhdpi/image.png
new file mode 100644
index 0000000..2540371
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/res/drawable-xhdpi/image.png
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/res/drawable-xxhdpi/image.png b/hostsidetests/appsecurity/test-apps/SplitApp/res/drawable-xxhdpi/image.png
new file mode 100644
index 0000000..18a3443
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/res/drawable-xxhdpi/image.png
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/res/values-de/values.xml b/hostsidetests/appsecurity/test-apps/SplitApp/res/values-de/values.xml
new file mode 100644
index 0000000..88b6f84
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/res/values-de/values.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<resources>
+    <string name="my_string1">blau</string>
+</resources>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/res/values-fr/values.xml b/hostsidetests/appsecurity/test-apps/SplitApp/res/values-fr/values.xml
new file mode 100644
index 0000000..c372f6a
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/res/values-fr/values.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<resources>
+    <string name="my_string2">pourpre</string>
+</resources>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/res/values-sw600dp/values.xml b/hostsidetests/appsecurity/test-apps/SplitApp/res/values-sw600dp/values.xml
new file mode 100644
index 0000000..edf4525
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/res/values-sw600dp/values.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<resources>
+    <dimen name="my_dimen">46dp</dimen>
+</resources>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/res/values-v7/values.xml b/hostsidetests/appsecurity/test-apps/SplitApp/res/values-v7/values.xml
new file mode 100644
index 0000000..d0a0db9
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/res/values-v7/values.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<resources>
+    <bool name="my_receiver_enabled">true</bool>
+</resources>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/res/values/values.xml b/hostsidetests/appsecurity/test-apps/SplitApp/res/values/values.xml
new file mode 100644
index 0000000..3118fde
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/res/values/values.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+
+<resources>
+    <bool name="my_receiver_enabled">false</bool>
+
+    <string name="my_string1">blue</string>
+    <string name="my_string2">purple</string>
+
+    <string-array name="my_string_array">
+        <item>@string/my_string1</item>
+        <item>@string/my_string2</item>
+    </string-array>
+
+    <color name="my_color">#00FF00</color>
+    <dimen name="my_dimen">23dp</dimen>
+    <integer name="my_integer">123</integer>
+</resources>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/res/xml-v7/my_activity_meta.xml b/hostsidetests/appsecurity/test-apps/SplitApp/res/xml-v7/my_activity_meta.xml
new file mode 100644
index 0000000..50cb6ec
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/res/xml-v7/my_activity_meta.xml
@@ -0,0 +1,17 @@
+<?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.
+-->
+
+<tag value="v7" />
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/res/xml/my_activity_meta.xml b/hostsidetests/appsecurity/test-apps/SplitApp/res/xml/my_activity_meta.xml
new file mode 100644
index 0000000..58f2a6a
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/res/xml/my_activity_meta.xml
@@ -0,0 +1,17 @@
+<?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.
+-->
+
+<tag value="base" />
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/BaseActivity.java b/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/BaseActivity.java
new file mode 100644
index 0000000..efd1843
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/BaseActivity.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.splitapp;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TextView;
+
+public class BaseActivity extends Activity {
+    /** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        TextView tv = new TextView(this);
+        int sum = Native.add(2, 3);
+        tv.setText("2 + 3 = " + Integer.toString(sum));
+        setContentView(tv);
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/BaseR.java b/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/BaseR.java
new file mode 100644
index 0000000..ecf6975
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/BaseR.java
@@ -0,0 +1,21 @@
+/*
+ * 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 com.android.cts.splitapp;
+
+public class BaseR {
+    public static final int my_string1 = R.string.my_string1;
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/Native.java b/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/Native.java
new file mode 100644
index 0000000..080053a
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/Native.java
@@ -0,0 +1,26 @@
+/*
+ * 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 com.android.cts.splitapp;
+
+public class Native {
+    static {
+        System.loadLibrary("splitappjni");
+    }
+
+    public static native int add(int a, int b);
+    public static native String arch();
+}
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/SplitAppTest.java b/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/SplitAppTest.java
new file mode 100644
index 0000000..277a1a2
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/src/com/android/cts/splitapp/SplitAppTest.java
@@ -0,0 +1,358 @@
+/*
+ * 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 com.android.cts.splitapp;
+
+import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
+import static org.xmlpull.v1.XmlPullParser.START_TAG;
+
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
+import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.test.AndroidTestCase;
+import android.util.DisplayMetrics;
+import android.util.Log;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Locale;
+
+public class SplitAppTest extends AndroidTestCase {
+    private static final String TAG = "SplitAppTest";
+    private static final String PKG = "com.android.cts.splitapp";
+
+    public static boolean sFeatureTouched = false;
+    public static String sFeatureValue = null;
+
+    public void testSingleBase() throws Exception {
+        final Resources r = getContext().getResources();
+        final PackageManager pm = getContext().getPackageManager();
+
+        // Should have untouched resources from base
+        assertEquals(false, r.getBoolean(R.bool.my_receiver_enabled));
+
+        assertEquals("blue", r.getString(R.string.my_string1));
+        assertEquals("purple", r.getString(R.string.my_string2));
+
+        assertEquals(0xff00ff00, r.getColor(R.color.my_color));
+        assertEquals(123, r.getInteger(R.integer.my_integer));
+
+        assertEquals("base", getXmlTestValue(r.getXml(R.xml.my_activity_meta)));
+
+        // We know about drawable IDs, but they're stripped from base
+        try {
+            r.getDrawable(R.drawable.image);
+            fail("Unexpected drawable in base");
+        } catch (Resources.NotFoundException expected) {
+        }
+
+        // Should have base assets
+        assertAssetContents(r, "file1.txt", "FILE1");
+        assertAssetContents(r, "dir/dirfile1.txt", "DIRFILE1");
+
+        try {
+            assertAssetContents(r, "file2.txt", null);
+            fail("Unexpected asset file2");
+        } catch (IOException expected) {
+        }
+
+        // Should only have base manifest items
+        Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.addCategory(Intent.CATEGORY_LAUNCHER);
+        intent.setPackage(PKG);
+
+        List<ResolveInfo> result = pm.queryIntentActivities(intent, 0);
+        assertEquals(1, result.size());
+        assertEquals("com.android.cts.splitapp.MyActivity", result.get(0).activityInfo.name);
+
+        // Receiver disabled by default in base
+        intent = new Intent(Intent.ACTION_DATE_CHANGED);
+        intent.setPackage(PKG);
+
+        result = pm.queryBroadcastReceivers(intent, 0);
+        assertEquals(0, result.size());
+
+        // We shouldn't have any native code in base
+        try {
+            Native.add(2, 4);
+            fail("Unexpected native code in base");
+        } catch (UnsatisfiedLinkError expected) {
+        }
+    }
+
+    public void testDensitySingle() throws Exception {
+        final Resources r = getContext().getResources();
+
+        // We should still have base resources
+        assertEquals("blue", r.getString(R.string.my_string1));
+        assertEquals("purple", r.getString(R.string.my_string2));
+
+        // Now we know about drawables, but only mdpi
+        final Drawable d = r.getDrawable(R.drawable.image);
+        assertEquals(0xff7e00ff, getDrawableColor(d));
+    }
+
+    public void testDensityAll() throws Exception {
+        final Resources r = getContext().getResources();
+
+        // We should still have base resources
+        assertEquals("blue", r.getString(R.string.my_string1));
+        assertEquals("purple", r.getString(R.string.my_string2));
+
+        // Pretend that we're at each density
+        updateDpi(r, DisplayMetrics.DENSITY_MEDIUM);
+        assertEquals(0xff7e00ff, getDrawableColor(r.getDrawable(R.drawable.image)));
+
+        updateDpi(r, DisplayMetrics.DENSITY_HIGH);
+        assertEquals(0xff00fcff, getDrawableColor(r.getDrawable(R.drawable.image)));
+
+        updateDpi(r, DisplayMetrics.DENSITY_XHIGH);
+        assertEquals(0xff80ff00, getDrawableColor(r.getDrawable(R.drawable.image)));
+
+        updateDpi(r, DisplayMetrics.DENSITY_XXHIGH);
+        assertEquals(0xffff0000, getDrawableColor(r.getDrawable(R.drawable.image)));
+    }
+
+    public void testDensityBest1() throws Exception {
+        final Resources r = getContext().getResources();
+
+        // Pretend that we're really high density, but we only have mdpi installed
+        updateDpi(r, DisplayMetrics.DENSITY_XXHIGH);
+        assertEquals(0xff7e00ff, getDrawableColor(r.getDrawable(R.drawable.image)));
+    }
+
+    public void testDensityBest2() throws Exception {
+        final Resources r = getContext().getResources();
+
+        // Pretend that we're really high density, and now we have better match
+        updateDpi(r, DisplayMetrics.DENSITY_XXHIGH);
+        assertEquals(0xffff0000, getDrawableColor(r.getDrawable(R.drawable.image)));
+    }
+
+    public void testApi() throws Exception {
+        final Resources r = getContext().getResources();
+        final PackageManager pm = getContext().getPackageManager();
+
+        // We should have updated boolean, different from base
+        assertEquals(true, r.getBoolean(R.bool.my_receiver_enabled));
+
+        // Receiver should be enabled now
+        Intent intent = new Intent(Intent.ACTION_DATE_CHANGED);
+        intent.setPackage(PKG);
+
+        List<ResolveInfo> result = pm.queryBroadcastReceivers(intent, 0);
+        assertEquals(1, result.size());
+        assertEquals("com.android.cts.splitapp.MyReceiver", result.get(0).activityInfo.name);
+    }
+
+    public void testLocale() throws Exception {
+        final Resources r = getContext().getResources();
+
+        updateLocale(r, Locale.ENGLISH);
+        assertEquals("blue", r.getString(R.string.my_string1));
+        assertEquals("purple", r.getString(R.string.my_string2));
+
+        updateLocale(r, Locale.GERMAN);
+        assertEquals("blau", r.getString(R.string.my_string1));
+        assertEquals("purple", r.getString(R.string.my_string2));
+
+        updateLocale(r, Locale.FRENCH);
+        assertEquals("blue", r.getString(R.string.my_string1));
+        assertEquals("pourpre", r.getString(R.string.my_string2));
+    }
+
+    public void testNative() throws Exception {
+        Log.d(TAG, "testNative() thinks it's using ABI " + Native.arch());
+
+        // Make sure we can do the maths
+        assertEquals(11642, Native.add(4933, 6709));
+    }
+
+    public void testFeatureBase() throws Exception {
+        final Resources r = getContext().getResources();
+        final PackageManager pm = getContext().getPackageManager();
+
+        // Should have untouched resources from base
+        assertEquals(false, r.getBoolean(R.bool.my_receiver_enabled));
+
+        assertEquals("blue", r.getString(R.string.my_string1));
+        assertEquals("purple", r.getString(R.string.my_string2));
+
+        assertEquals(0xff00ff00, r.getColor(R.color.my_color));
+        assertEquals(123, r.getInteger(R.integer.my_integer));
+
+        assertEquals("base", getXmlTestValue(r.getXml(R.xml.my_activity_meta)));
+
+        // And that we can access resources from feature
+        // TODO: enable these once 17924027 is fixed
+//        assertEquals("red", r.getString(r.getIdentifier("feature_string", "string", PKG)));
+//        assertEquals(123, r.getInteger(r.getIdentifier("feature_integer", "integer", PKG)));
+
+        final Class<?> featR = Class.forName("com.android.cts.splitapp.FeatureR");
+        final int boolId = (int) featR.getDeclaredField("feature_receiver_enabled").get(null);
+        final int intId = (int) featR.getDeclaredField("feature_integer").get(null);
+        final int stringId = (int) featR.getDeclaredField("feature_string").get(null);
+        assertEquals(true, r.getBoolean(boolId));
+        assertEquals(123, r.getInteger(intId));
+        assertEquals("red", r.getString(stringId));
+
+        // Should have both base and feature assets
+        assertAssetContents(r, "file1.txt", "FILE1");
+        assertAssetContents(r, "file2.txt", "FILE2");
+        assertAssetContents(r, "dir/dirfile1.txt", "DIRFILE1");
+        assertAssetContents(r, "dir/dirfile2.txt", "DIRFILE2");
+
+        // Should have both base and feature components
+        Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.addCategory(Intent.CATEGORY_LAUNCHER);
+        intent.setPackage(PKG);
+        List<ResolveInfo> result = pm.queryIntentActivities(intent, 0);
+        assertEquals(2, result.size());
+        assertEquals("com.android.cts.splitapp.MyActivity", result.get(0).activityInfo.name);
+        assertEquals("com.android.cts.splitapp.FeatureActivity", result.get(1).activityInfo.name);
+
+        // Receiver only enabled in feature
+        intent = new Intent(Intent.ACTION_DATE_CHANGED);
+        intent.setPackage(PKG);
+        result = pm.queryBroadcastReceivers(intent, 0);
+        assertEquals(1, result.size());
+        assertEquals("com.android.cts.splitapp.FeatureReceiver", result.get(0).activityInfo.name);
+
+        // And we should have a service
+        intent = new Intent("com.android.cts.splitapp.service");
+        intent.setPackage(PKG);
+        result = pm.queryIntentServices(intent, 0);
+        assertEquals(1, result.size());
+        assertEquals("com.android.cts.splitapp.FeatureService", result.get(0).serviceInfo.name);
+
+        // And a provider too
+        ProviderInfo info = pm.resolveContentProvider("com.android.cts.splitapp.provider", 0);
+        assertEquals("com.android.cts.splitapp.FeatureProvider", info.name);
+
+        // And assert that we spun up the provider in this process
+        final Class<?> provider = Class.forName("com.android.cts.splitapp.FeatureProvider");
+        final Field field = provider.getDeclaredField("sCreated");
+        assertTrue("Expected provider to have been created", (boolean) field.get(null));
+        assertTrue("Expected provider to have touched us", sFeatureTouched);
+        assertEquals(r.getString(R.string.my_string1), sFeatureValue);
+
+        // Finally ensure that we can execute some code from split
+        final Class<?> logic = Class.forName("com.android.cts.splitapp.FeatureLogic");
+        final Method method = logic.getDeclaredMethod("mult", new Class[] {
+                Integer.TYPE, Integer.TYPE });
+        assertEquals(72, (int) method.invoke(null, 12, 6));
+
+        // Make sure we didn't get an extra flag from feature split
+        assertTrue("Someone parsed application flag!",
+                (getContext().getApplicationInfo().flags & ApplicationInfo.FLAG_LARGE_HEAP) == 0);
+
+        // Make sure we have permission from base APK
+        getContext().enforceCallingOrSelfPermission(android.Manifest.permission.CAMERA, null);
+
+        try {
+            // But no new permissions from the feature APK
+            getContext().enforceCallingOrSelfPermission(android.Manifest.permission.INTERNET, null);
+            fail("Whaaa, we somehow gained permission from feature?");
+        } catch (SecurityException expected) {
+        }
+    }
+
+    public void testFeatureApi() throws Exception {
+        final Resources r = getContext().getResources();
+        final PackageManager pm = getContext().getPackageManager();
+
+        // Should have untouched resources from base
+        assertEquals(false, r.getBoolean(R.bool.my_receiver_enabled));
+
+        // And that we can access resources from feature
+        // TODO: enable these once 17924027 is fixed
+//        assertEquals(321, r.getInteger(r.getIdentifier("feature_integer", "integer", PKG)));
+
+        final Class<?> featR = Class.forName("com.android.cts.splitapp.FeatureR");
+        final int boolId = (int) featR.getDeclaredField("feature_receiver_enabled").get(null);
+        final int intId = (int) featR.getDeclaredField("feature_integer").get(null);
+        final int stringId = (int) featR.getDeclaredField("feature_string").get(null);
+        assertEquals(false, r.getBoolean(boolId));
+        assertEquals(321, r.getInteger(intId));
+        assertEquals("red", r.getString(stringId));
+
+        // And now both receivers should be disabled
+        Intent intent = new Intent(Intent.ACTION_DATE_CHANGED);
+        intent.setPackage(PKG);
+        List<ResolveInfo> result = pm.queryBroadcastReceivers(intent, 0);
+        assertEquals(0, result.size());
+    }
+
+    private static void updateDpi(Resources r, int densityDpi) {
+        final Configuration c = new Configuration(r.getConfiguration());
+        c.densityDpi = densityDpi;
+        r.updateConfiguration(c, r.getDisplayMetrics());
+    }
+
+    private static void updateLocale(Resources r, Locale locale) {
+        final Configuration c = new Configuration(r.getConfiguration());
+        c.locale = locale;
+        r.updateConfiguration(c, r.getDisplayMetrics());
+    }
+
+    private static int getDrawableColor(Drawable d) {
+        final Bitmap bitmap = Bitmap.createBitmap(d.getIntrinsicWidth(), d.getIntrinsicHeight(),
+                Bitmap.Config.ARGB_8888);
+        final Canvas canvas = new Canvas(bitmap);
+        d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
+        d.draw(canvas);
+        return bitmap.getPixel(0, 0);
+    }
+
+    private static String getXmlTestValue(XmlPullParser in) throws XmlPullParserException,
+            IOException {
+        int type;
+        while ((type = in.next()) != END_DOCUMENT) {
+            if (type == START_TAG) {
+                final String tag = in.getName();
+                if ("tag".equals(tag)) {
+                    return in.getAttributeValue(null, "value");
+                }
+            }
+        }
+        return null;
+    }
+
+    private static void assertAssetContents(Resources r, String path, String expected)
+            throws IOException {
+        BufferedReader in = null;
+        try {
+            in = new BufferedReader(new InputStreamReader(r.getAssets().open(path)));
+            assertEquals(expected, in.readLine());
+        } finally {
+            if (in != null) in.close();
+        }
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/TargetInstrumentationApp/Android.mk b/hostsidetests/appsecurity/test-apps/TargetInstrumentationApp/Android.mk
index cc87e29..38a0511 100644
--- a/hostsidetests/appsecurity/test-apps/TargetInstrumentationApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/TargetInstrumentationApp/Android.mk
@@ -21,6 +21,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
 
 LOCAL_PACKAGE_NAME := CtsTargetInstrumentationApp
 
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/Android.mk b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/Android.mk
index d836042..8878c47 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/Android.mk
@@ -22,6 +22,7 @@
     ../PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/GrantUriPermission.java
 
 LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
 
 LOCAL_PACKAGE_NAME := CtsUsePermissionDiffCert
 
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/AndroidManifest.xml
index b7307bb..7acf98f 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/AndroidManifest.xml
@@ -38,5 +38,5 @@
     </application>
 
     <instrumentation android:targetPackage="com.android.cts.usespermissiondiffcertapp"
-            android:name="android.test.InstrumentationTestRunner"/>
+            android:name="android.support.test.runner.AndroidJUnitRunner"/>
 </manifest>
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
index db26eec..5378266 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
@@ -591,6 +591,7 @@
         grantIntent.setClass(getContext(),
                 service ? ReceiveUriService.class : ReceiveUriActivity.class);
         Intent intent = new Intent();
+        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
         intent.setComponent(GRANT_URI_PERM_COMP);
         intent.setAction(service ? GrantUriPermission.ACTION_START_SERVICE
                 : GrantUriPermission.ACTION_START_ACTIVITY);
@@ -598,6 +599,27 @@
         getContext().sendBroadcast(intent);
     }
 
+    private void grantClipUriPermissionViaContext(Uri uri, int mode) {
+        Intent intent = new Intent();
+        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+        intent.setComponent(GRANT_URI_PERM_COMP);
+        intent.setAction(GrantUriPermission.ACTION_GRANT_URI);
+        intent.putExtra(GrantUriPermission.EXTRA_PACKAGE_NAME, getContext().getPackageName());
+        intent.putExtra(GrantUriPermission.EXTRA_URI, uri);
+        intent.putExtra(GrantUriPermission.EXTRA_MODE, mode);
+        getContext().sendBroadcast(intent);
+    }
+
+    private void revokeClipUriPermissionViaContext(Uri uri, int mode) {
+        Intent intent = new Intent();
+        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+        intent.setComponent(GRANT_URI_PERM_COMP);
+        intent.setAction(GrantUriPermission.ACTION_REVOKE_URI);
+        intent.putExtra(GrantUriPermission.EXTRA_URI, uri);
+        intent.putExtra(GrantUriPermission.EXTRA_MODE, mode);
+        getContext().sendBroadcast(intent);
+    }
+
     private void assertReadingClipAllowed(ClipData clip) {
         for (int i=0; i<clip.getItemCount(); i++) {
             ClipData.Item item = clip.getItemAt(i);
@@ -1355,4 +1377,233 @@
         getContext().sendOrderedBroadcast(intent, null, receiver, null, 0, null, null);
         receiver.assertSuccess("unexpected outgoing persisted Uri status");
     }
+
+    /**
+     * Validate behavior of prefix permission grants.
+     */
+    public void testGrantPrefixUriPermission() throws Exception {
+        final Uri target = Uri.withAppendedPath(PERM_URI_GRANTING, "foo1");
+        final Uri targetMeow = Uri.withAppendedPath(target, "meow");
+        final Uri targetMeowCat = Uri.withAppendedPath(targetMeow, "cat");
+
+        final ClipData clip = makeSingleClipData(target);
+        final ClipData clipMeow = makeSingleClipData(targetMeow);
+        final ClipData clipMeowCat = makeSingleClipData(targetMeowCat);
+
+        // Make sure we can't see the target
+        assertReadingClipNotAllowed(clip, "reading should have failed");
+        assertWritingClipNotAllowed(clip, "writing should have failed");
+
+        // Give ourselves prefix read access
+        ReceiveUriActivity.clearStarted();
+        grantClipUriPermission(clipMeow, Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false);
+        ReceiveUriActivity.waitForStart();
+
+        // Verify prefix read access
+        assertReadingClipNotAllowed(clip, "reading should have failed");
+        assertReadingClipAllowed(clipMeow);
+        assertReadingClipAllowed(clipMeowCat);
+        assertWritingClipNotAllowed(clip, "writing should have failed");
+        assertWritingClipNotAllowed(clipMeow, "writing should have failed");
+        assertWritingClipNotAllowed(clipMeowCat, "writing should have failed");
+
+        // Now give ourselves exact write access
+        ReceiveUriActivity.clearNewIntent();
+        grantClipUriPermission(clip, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, false);
+        ReceiveUriActivity.waitForNewIntent();
+
+        // Verify we have exact write access, but not prefix write
+        assertReadingClipNotAllowed(clip, "reading should have failed");
+        assertReadingClipAllowed(clipMeow);
+        assertReadingClipAllowed(clipMeowCat);
+        assertWritingClipAllowed(clip);
+        assertWritingClipNotAllowed(clipMeow, "writing should have failed");
+        assertWritingClipNotAllowed(clipMeowCat, "writing should have failed");
+
+        ReceiveUriActivity.finishCurInstanceSync();
+    }
+
+    public void testGrantPersistablePrefixUriPermission() {
+        final ContentResolver resolver = getContext().getContentResolver();
+
+        final Uri target = Uri.withAppendedPath(PERM_URI_GRANTING, "foo2");
+        final Uri targetMeow = Uri.withAppendedPath(target, "meow");
+
+        final ClipData clip = makeSingleClipData(target);
+        final ClipData clipMeow = makeSingleClipData(targetMeow);
+
+        // Make sure we can't see the target
+        assertReadingClipNotAllowed(clip, "reading should have failed");
+
+        // Give ourselves prefix read access
+        ReceiveUriActivity.clearStarted();
+        grantClipUriPermission(clip, Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+                | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false);
+        ReceiveUriActivity.waitForStart();
+
+        // Verify prefix read access
+        assertReadingClipAllowed(clip);
+        assertReadingClipAllowed(clipMeow);
+
+        // Verify we can persist direct grant
+        long before = System.currentTimeMillis();
+        resolver.takePersistableUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        long after = System.currentTimeMillis();
+        assertPersistedUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION, before, after);
+
+        // But we can't take anywhere under the prefix
+        try {
+            resolver.takePersistableUriPermission(targetMeow,
+                    Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            fail("taking under prefix should have failed");
+        } catch (SecurityException expected) {
+        }
+
+        // Should still have access regardless of taking
+        assertReadingClipAllowed(clip);
+        assertReadingClipAllowed(clipMeow);
+
+        // And clean up our grants
+        resolver.releasePersistableUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        assertNoPersistedUriPermission();
+
+        ReceiveUriActivity.finishCurInstanceSync();
+    }
+
+    /**
+     * Validate behavior of directly granting/revoking permission grants.
+     */
+    public void testDirectGrantRevokeUriPermission() throws Exception {
+        final ContentResolver resolver = getContext().getContentResolver();
+
+        final Uri target = Uri.withAppendedPath(PERM_URI_GRANTING, "foo3");
+        final Uri targetMeow = Uri.withAppendedPath(target, "meow");
+        final Uri targetMeowCat = Uri.withAppendedPath(targetMeow, "cat");
+
+        final ClipData clip = makeSingleClipData(target);
+        final ClipData clipMeow = makeSingleClipData(targetMeow);
+        final ClipData clipMeowCat = makeSingleClipData(targetMeowCat);
+
+        // Make sure we can't see the target
+        assertReadingClipNotAllowed(clipMeow, "reading should have failed");
+        assertWritingClipNotAllowed(clipMeow, "writing should have failed");
+
+        // Give ourselves some grants:
+        // /meow/cat  WRITE|PERSISTABLE
+        // /meow      READ|PREFIX
+        // /meow      WRITE
+        grantClipUriPermissionViaContext(targetMeowCat, Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+                | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
+        grantClipUriPermissionViaContext(targetMeow, Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
+        grantClipUriPermissionViaContext(targetMeow, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+        SystemClock.sleep(2000);
+
+        long before = System.currentTimeMillis();
+        resolver.takePersistableUriPermission(targetMeowCat, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+        long after = System.currentTimeMillis();
+        assertPersistedUriPermission(targetMeowCat, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, before, after);
+
+        // Verify they look good
+        assertReadingClipNotAllowed(clip, "reading should have failed");
+        assertReadingClipAllowed(clipMeow);
+        assertReadingClipAllowed(clipMeowCat);
+        assertWritingClipNotAllowed(clip, "writing should have failed");
+        assertWritingClipAllowed(clipMeow);
+        assertWritingClipAllowed(clipMeowCat);
+
+        // Revoke anyone with write under meow
+        revokeClipUriPermissionViaContext(targetMeow, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+        SystemClock.sleep(2000);
+
+        // This should have nuked persisted permission at lower level, but it
+        // shoulnd't have touched our prefix read.
+        assertReadingClipNotAllowed(clip, "reading should have failed");
+        assertReadingClipAllowed(clipMeow);
+        assertReadingClipAllowed(clipMeowCat);
+        assertWritingClipNotAllowed(clip, "writing should have failed");
+        assertWritingClipNotAllowed(clipMeow, "writing should have failed");
+        assertWritingClipNotAllowed(clipMeowCat, "writing should have failed");
+        assertNoPersistedUriPermission();
+
+        // Revoking read at top of tree should nuke everything else
+        revokeClipUriPermissionViaContext(target, Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        SystemClock.sleep(2000);
+        assertReadingClipNotAllowed(clip, "reading should have failed");
+        assertReadingClipNotAllowed(clipMeow, "reading should have failed");
+        assertReadingClipNotAllowed(clipMeowCat, "reading should have failed");
+        assertWritingClipNotAllowed(clip, "writing should have failed");
+        assertWritingClipNotAllowed(clipMeow, "writing should have failed");
+        assertWritingClipNotAllowed(clipMeowCat, "writing should have failed");
+        assertNoPersistedUriPermission();
+    }
+
+    /**
+     * Validate behavior of a direct permission grant, where the receiver of
+     * that permission revokes it.
+     */
+    public void testDirectGrantReceiverRevokeUriPermission() throws Exception {
+        final ContentResolver resolver = getContext().getContentResolver();
+
+        final Uri target = Uri.withAppendedPath(PERM_URI_GRANTING, "foo3");
+        final Uri targetMeow = Uri.withAppendedPath(target, "meow");
+        final Uri targetMeowCat = Uri.withAppendedPath(targetMeow, "cat");
+
+        final ClipData clip = makeSingleClipData(target);
+        final ClipData clipMeow = makeSingleClipData(targetMeow);
+        final ClipData clipMeowCat = makeSingleClipData(targetMeowCat);
+
+        // Make sure we can't see the target
+        assertReadingClipNotAllowed(clipMeow, "reading should have failed");
+        assertWritingClipNotAllowed(clipMeow, "writing should have failed");
+
+        // Give ourselves some grants:
+        // /meow/cat  WRITE|PERSISTABLE
+        // /meow      READ|PREFIX
+        // /meow      WRITE
+        grantClipUriPermissionViaContext(targetMeowCat, Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+                | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
+        grantClipUriPermissionViaContext(targetMeow, Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
+        grantClipUriPermissionViaContext(targetMeow, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+        SystemClock.sleep(2000);
+
+        long before = System.currentTimeMillis();
+        resolver.takePersistableUriPermission(targetMeowCat, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+        long after = System.currentTimeMillis();
+        assertPersistedUriPermission(targetMeowCat, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, before, after);
+
+        // Verify they look good
+        assertReadingClipNotAllowed(clip, "reading should have failed");
+        assertReadingClipAllowed(clipMeow);
+        assertReadingClipAllowed(clipMeowCat);
+        assertWritingClipNotAllowed(clip, "writing should have failed");
+        assertWritingClipAllowed(clipMeow);
+        assertWritingClipAllowed(clipMeowCat);
+
+        // Revoke anyone with write under meow
+        getContext().revokeUriPermission(targetMeow, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+        // This should have nuked persisted permission at lower level, but it
+        // shoulnd't have touched our prefix read.
+        assertReadingClipNotAllowed(clip, "reading should have failed");
+        assertReadingClipAllowed(clipMeow);
+        assertReadingClipAllowed(clipMeowCat);
+        assertWritingClipNotAllowed(clip, "writing should have failed");
+        assertWritingClipNotAllowed(clipMeow, "writing should have failed");
+        assertWritingClipNotAllowed(clipMeowCat, "writing should have failed");
+        assertNoPersistedUriPermission();
+
+        // Revoking read at top of tree should nuke everything else
+        getContext().revokeUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        assertReadingClipNotAllowed(clip, "reading should have failed");
+        assertReadingClipNotAllowed(clipMeow, "reading should have failed");
+        assertReadingClipNotAllowed(clipMeowCat, "reading should have failed");
+        assertWritingClipNotAllowed(clip, "writing should have failed");
+        assertWritingClipNotAllowed(clipMeow, "writing should have failed");
+        assertWritingClipNotAllowed(clipMeowCat, "writing should have failed");
+        assertNoPersistedUriPermission();
+    }
 }
diff --git a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/Android.mk b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/Android.mk
index 4352bfb..a98fcea 100644
--- a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/Android.mk
@@ -18,6 +18,7 @@
 
 LOCAL_MODULE_TAGS := tests
 LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) \
     ../ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java
diff --git a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/AndroidManifest.xml
index 82910aa..37e39e9 100644
--- a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/AndroidManifest.xml
@@ -20,7 +20,7 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
         android:targetPackage="com.android.cts.writeexternalstorageapp" />
 
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
diff --git a/hostsidetests/appsecurity/test-apps/keysets/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/Android.mk
new file mode 100644
index 0000000..935fa95
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/Android.mk
@@ -0,0 +1,21 @@
+# 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)
+
+include $(CLEAR_VARS)
+
+# Build the test APKs using their own makefiles
+include $(call all-makefiles-under,$(LOCAL_PATH))
+
diff --git a/hostsidetests/appsecurity/test-apps/keysets/permDef/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/permDef/Android.mk
new file mode 100644
index 0000000..eb71540
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/permDef/Android.mk
@@ -0,0 +1,41 @@
+# 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)
+
+#apks signed cts-keyset-test-a
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetPermDefSigningA
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+#apks signed cts-keyset-test-b
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetPermDefSigningB
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/permDef/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/keysets/permDef/AndroidManifest.xml
new file mode 100644
index 0000000..7b84f6a
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/permDef/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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="com.android.cts.keysets_permdef">
+    <application android:hasCode="false">
+    </application>
+    <permission android:description="@string/keysets_perm_desc"
+                android:label="@string/keysets_perm_label"
+                android:name="com.android.cts.keysets_permdef.keysets_perm"
+                android:protectionLevel="signature" />
+    <key-sets>
+        <key-set android:name="A" >
+          <public-key android:name="keyA"
+                      android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwf5zJblvYSB7Ym7or/7GggAAu7mp7RrykPJsXhod8doFhVT5s7eF3A4MCE55vvANP7HvwMw2b+T6qx7Pq0VJtbbSDtlBHBtIc47Pjq0CsDg590BUcgKp7PdJ9J6UVgtzDnV6cGEpXmSag3sY+lqiW04ytPhCVwzYTWGdYe9+TIl47cBrveRfLOlGrcuFQe+zCTmDFqzBKCRHK9b7l5PDWvXXyg65Uu/MBUA/TZWO0fEqOlxZG/nn6DUKQLhPdmJRXWJ3WqMNMhJGD+nKtkmdX703xRqmg4h+6g0S7M9Y3IQ2NUGyw05AYzCguHB/Mv6uVIiW659wpbyb45TgKG3UhQIDAQAB" />
+        </key-set>
+        <key-set android:name="B" >
+          <public-key android:name="keyB"
+                      android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoeFZqMqTbZiozFTXMkXtSKJRzn2qODZgvVXAAwKTi50xYcbPcHTfKxtif8+q7OCp/50JYDH32bg6wkUunn5+dEaHkxZY8d7uw46tQtl5dNGi+6cc4MezVLCS6nkqNDusAgdvgLU6Fl6SGi02KTp1vkt6CwLO977YJP7kt9ouDRTG7ASJiq3OyRRoOqYHhD9gpsbUq4w+1bXGfuuZujA1dXyovXtvrHUGOdFIEBYOVYGfCcwh3lXPmjNJMlHtKQkurq8/LH7a1B5ocoXCGsyR8YHdlWfrqRAfzgOB1KCnNNmWqskU9LOci3uQn9IDeMEFmAd8FqF8SwV+4Ludk/xWGQIDAQAB" />
+        </key-set>
+        <upgrade-key-set android:name="A"/>
+        <upgrade-key-set android:name="B"/>
+    </key-sets>
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/permDef/res/values/strings.xml b/hostsidetests/appsecurity/test-apps/keysets/permDef/res/values/strings.xml
new file mode 100644
index 0000000..4e5e870
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/permDef/res/values/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Just need this dummy file to have something to build. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string name="keysets_perm_desc">keysets_perm_description</string>
+  <string name="keysets_perm_label">keysets_perm_label</string>
+</resources>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/permUse/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/permUse/Android.mk
new file mode 100644
index 0000000..000b12a
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/permUse/Android.mk
@@ -0,0 +1,41 @@
+# 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)
+
+#apks signed cts-keyset-test-a
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetPermUseSigningA
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+#apks signed cts-keyset-test-b
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetPermUseSigningB
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/permUse/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/keysets/permUse/AndroidManifest.xml
new file mode 100644
index 0000000..40ca1cb
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/permUse/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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="com.android.cts.keysets">
+    <application android:hasCode="false">
+    </application>
+    <uses-permission android:name="com.android.cts.keysets_permdef.keysets_perm" />
+    <key-sets>
+        <key-set android:name="A">
+          <public-key android:name="keyA"
+                      android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwf5zJblvYSB7Ym7or/7GggAAu7mp7RrykPJsXhod8doFhVT5s7eF3A4MCE55vvANP7HvwMw2b+T6qx7Pq0VJtbbSDtlBHBtIc47Pjq0CsDg590BUcgKp7PdJ9J6UVgtzDnV6cGEpXmSag3sY+lqiW04ytPhCVwzYTWGdYe9+TIl47cBrveRfLOlGrcuFQe+zCTmDFqzBKCRHK9b7l5PDWvXXyg65Uu/MBUA/TZWO0fEqOlxZG/nn6DUKQLhPdmJRXWJ3WqMNMhJGD+nKtkmdX703xRqmg4h+6g0S7M9Y3IQ2NUGyw05AYzCguHB/Mv6uVIiW659wpbyb45TgKG3UhQIDAQAB" />
+        </key-set>
+        <key-set android:name="B">
+          <public-key android:name="keyB"
+                      android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoeFZqMqTbZiozFTXMkXtSKJRzn2qODZgvVXAAwKTi50xYcbPcHTfKxtif8+q7OCp/50JYDH32bg6wkUunn5+dEaHkxZY8d7uw46tQtl5dNGi+6cc4MezVLCS6nkqNDusAgdvgLU6Fl6SGi02KTp1vkt6CwLO977YJP7kt9ouDRTG7ASJiq3OyRRoOqYHhD9gpsbUq4w+1bXGfuuZujA1dXyovXtvrHUGOdFIEBYOVYGfCcwh3lXPmjNJMlHtKQkurq8/LH7a1B5ocoXCGsyR8YHdlWfrqRAfzgOB1KCnNNmWqskU9LOci3uQn9IDeMEFmAd8FqF8SwV+4Ludk/xWGQIDAQAB" />
+        </key-set>
+        <upgrade-key-set android:name="A"/>
+        <upgrade-key-set android:name="B"/>
+    </key-sets>
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/permUse/res/values/strings.xml b/hostsidetests/appsecurity/test-apps/keysets/permUse/res/values/strings.xml
new file mode 100644
index 0000000..4e5e870
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/permUse/res/values/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Just need this dummy file to have something to build. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string name="keysets_perm_desc">keysets_perm_description</string>
+  <string name="keysets_perm_label">keysets_perm_label</string>
+</resources>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/testApp/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/testApp/Android.mk
new file mode 100644
index 0000000..ed6db690
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/testApp/Android.mk
@@ -0,0 +1,26 @@
+# 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetTestApp
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/testApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/keysets/testApp/AndroidManifest.xml
new file mode 100644
index 0000000..38edf5f
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/testApp/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?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="com.android.cts.keysets.testapp">
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation
+        android:targetPackage="com.android.cts.keysets.testapp"
+        android:name="android.support.test.runner.AndroidJUnitRunner" />
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/testApp/src/com/android/cts/keysets/KeySetPermissionsTest.java b/hostsidetests/appsecurity/test-apps/keysets/testApp/src/com/android/cts/keysets/KeySetPermissionsTest.java
new file mode 100644
index 0000000..467a212
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/testApp/src/com/android/cts/keysets/KeySetPermissionsTest.java
@@ -0,0 +1,40 @@
+/*
+ * 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 com.android.cts.keysets;
+
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.util.Log;
+import android.test.AndroidTestCase;
+
+import java.lang.Override;
+
+/**
+ * KeySets device-side tests involving permissions
+ */
+public class KeySetPermissionsTest extends AndroidTestCase {
+
+    private static final String KEYSET_APP_PKG = "com.android.cts.keysets";
+    private static final String KEYSET_PERM_DEF_PKG = "com.android.cts.keysets_permdef";
+    private static final String KEYSET_PERM_NAME = "com.android.cts.keysets_permdef.keysets_perm";
+
+    public void testHasPerm() throws Exception {
+        PackageManager pm = getContext().getPackageManager();
+        assertTrue(KEYSET_PERM_NAME + " not granted to " + KEYSET_APP_PKG,
+                pm.checkPermission(KEYSET_PERM_NAME, KEYSET_APP_PKG) == PackageManager.PERMISSION_GRANTED);
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uA/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/uA/Android.mk
new file mode 100644
index 0000000..6220790
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uA/Android.mk
@@ -0,0 +1,53 @@
+# 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)
+
+#apks signed by cts-keyset-test-a
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningAUpgradeA
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+#apks signed by cts-keyset-test-b
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningBUpgradeA
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+#apks signed by cts-keyset-test-a and cts-keyset-test-b
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningAAndBUpgradeA
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_ADDITIONAL_CERTIFICATES := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b
+LOCAL_DEX_PREOPT := false
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uA/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/keysets/uA/AndroidManifest.xml
new file mode 100644
index 0000000..8813c37
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uA/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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="com.android.cts.keysets">
+    <application android:hasCode="false">
+    </application>
+    <key-sets>
+        <key-set android:name="A" >
+          <public-key android:name="keyA"
+                      android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwf5zJblvYSB7Ym7or/7GggAAu7mp7RrykPJsXhod8doFhVT5s7eF3A4MCE55vvANP7HvwMw2b+T6qx7Pq0VJtbbSDtlBHBtIc47Pjq0CsDg590BUcgKp7PdJ9J6UVgtzDnV6cGEpXmSag3sY+lqiW04ytPhCVwzYTWGdYe9+TIl47cBrveRfLOlGrcuFQe+zCTmDFqzBKCRHK9b7l5PDWvXXyg65Uu/MBUA/TZWO0fEqOlxZG/nn6DUKQLhPdmJRXWJ3WqMNMhJGD+nKtkmdX703xRqmg4h+6g0S7M9Y3IQ2NUGyw05AYzCguHB/Mv6uVIiW659wpbyb45TgKG3UhQIDAQAB" />
+        </key-set>
+        <upgrade-key-set android:name="A"/>
+    </key-sets>
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uAB/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/uAB/Android.mk
new file mode 100644
index 0000000..534dba3
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uAB/Android.mk
@@ -0,0 +1,28 @@
+# 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)
+
+#apks signed cts-keyset-test-a
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningAUpgradeAAndB
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uAB/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/keysets/uAB/AndroidManifest.xml
new file mode 100644
index 0000000..65f78e3
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uAB/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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="com.android.cts.keysets">
+    <application android:hasCode="false">
+    </application>
+    <key-sets>
+        <key-set android:name="AB" >
+          <public-key android:name="keyA"
+                      android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwf5zJblvYSB7Ym7or/7GggAAu7mp7RrykPJsXhod8doFhVT5s7eF3A4MCE55vvANP7HvwMw2b+T6qx7Pq0VJtbbSDtlBHBtIc47Pjq0CsDg590BUcgKp7PdJ9J6UVgtzDnV6cGEpXmSag3sY+lqiW04ytPhCVwzYTWGdYe9+TIl47cBrveRfLOlGrcuFQe+zCTmDFqzBKCRHK9b7l5PDWvXXyg65Uu/MBUA/TZWO0fEqOlxZG/nn6DUKQLhPdmJRXWJ3WqMNMhJGD+nKtkmdX703xRqmg4h+6g0S7M9Y3IQ2NUGyw05AYzCguHB/Mv6uVIiW659wpbyb45TgKG3UhQIDAQAB" />
+          <public-key android:name="keyB"
+                      android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoeFZqMqTbZiozFTXMkXtSKJRzn2qODZgvVXAAwKTi50xYcbPcHTfKxtif8+q7OCp/50JYDH32bg6wkUunn5+dEaHkxZY8d7uw46tQtl5dNGi+6cc4MezVLCS6nkqNDusAgdvgLU6Fl6SGi02KTp1vkt6CwLO977YJP7kt9ouDRTG7ASJiq3OyRRoOqYHhD9gpsbUq4w+1bXGfuuZujA1dXyovXtvrHUGOdFIEBYOVYGfCcwh3lXPmjNJMlHtKQkurq8/LH7a1B5ocoXCGsyR8YHdlWfrqRAfzgOB1KCnNNmWqskU9LOci3uQn9IDeMEFmAd8FqF8SwV+4Ludk/xWGQIDAQAB" />
+        </key-set>
+        <upgrade-key-set android:name="AB"/>
+    </key-sets>
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uAuB/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/uAuB/Android.mk
new file mode 100644
index 0000000..75729e0
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uAuB/Android.mk
@@ -0,0 +1,28 @@
+# 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)
+
+#apks signed cts-keyset-test-a
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningAUpgradeAOrB
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uAuB/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/keysets/uAuB/AndroidManifest.xml
new file mode 100644
index 0000000..546c5fe
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uAuB/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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="com.android.cts.keysets">
+    <application android:hasCode="false">
+    </application>
+    <key-sets>
+        <key-set android:name="A" >
+          <public-key android:name="keyA"
+                      android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwf5zJblvYSB7Ym7or/7GggAAu7mp7RrykPJsXhod8doFhVT5s7eF3A4MCE55vvANP7HvwMw2b+T6qx7Pq0VJtbbSDtlBHBtIc47Pjq0CsDg590BUcgKp7PdJ9J6UVgtzDnV6cGEpXmSag3sY+lqiW04ytPhCVwzYTWGdYe9+TIl47cBrveRfLOlGrcuFQe+zCTmDFqzBKCRHK9b7l5PDWvXXyg65Uu/MBUA/TZWO0fEqOlxZG/nn6DUKQLhPdmJRXWJ3WqMNMhJGD+nKtkmdX703xRqmg4h+6g0S7M9Y3IQ2NUGyw05AYzCguHB/Mv6uVIiW659wpbyb45TgKG3UhQIDAQAB" />
+        </key-set>
+        <key-set android:name="B" >
+          <public-key android:name="keyB"
+                      android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoeFZqMqTbZiozFTXMkXtSKJRzn2qODZgvVXAAwKTi50xYcbPcHTfKxtif8+q7OCp/50JYDH32bg6wkUunn5+dEaHkxZY8d7uw46tQtl5dNGi+6cc4MezVLCS6nkqNDusAgdvgLU6Fl6SGi02KTp1vkt6CwLO977YJP7kt9ouDRTG7ASJiq3OyRRoOqYHhD9gpsbUq4w+1bXGfuuZujA1dXyovXtvrHUGOdFIEBYOVYGfCcwh3lXPmjNJMlHtKQkurq8/LH7a1B5ocoXCGsyR8YHdlWfrqRAfzgOB1KCnNNmWqskU9LOci3uQn9IDeMEFmAd8FqF8SwV+4Ludk/xWGQIDAQAB" />
+        </key-set>
+        <upgrade-key-set android:name="A"/>
+        <upgrade-key-set android:name="B"/>
+    </key-sets>
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uB/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/uB/Android.mk
new file mode 100644
index 0000000..121c342
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uB/Android.mk
@@ -0,0 +1,55 @@
+# 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)
+
+#apks signed cts-keyset-test-a
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningAUpgradeB
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+#apks signed cts-keyset-test-b
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningBUpgradeB
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-b
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+#apks signed by cts-keyset-test-a and cts-keyset-test-c
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningAAndCUpgradeB
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_ADDITIONAL_CERTIFICATES := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-c
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uB/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/keysets/uB/AndroidManifest.xml
new file mode 100644
index 0000000..9c837bc
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uB/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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="com.android.cts.keysets">
+    <application android:hasCode="false">
+    </application>
+    <key-sets>
+        <key-set android:name="B" >
+          <public-key android:name="keyB"
+                      android:value="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoeFZqMqTbZiozFTXMkXtSKJRzn2qODZgvVXAAwKTi50xYcbPcHTfKxtif8+q7OCp/50JYDH32bg6wkUunn5+dEaHkxZY8d7uw46tQtl5dNGi+6cc4MezVLCS6nkqNDusAgdvgLU6Fl6SGi02KTp1vkt6CwLO977YJP7kt9ouDRTG7ASJiq3OyRRoOqYHhD9gpsbUq4w+1bXGfuuZujA1dXyovXtvrHUGOdFIEBYOVYGfCcwh3lXPmjNJMlHtKQkurq8/LH7a1B5ocoXCGsyR8YHdlWfrqRAfzgOB1KCnNNmWqskU9LOci3uQn9IDeMEFmAd8FqF8SwV+4Ludk/xWGQIDAQAB" />
+        </key-set>
+        <upgrade-key-set android:name="B"/>
+    </key-sets>
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uNone/Android.mk b/hostsidetests/appsecurity/test-apps/keysets/uNone/Android.mk
new file mode 100644
index 0000000..a8746ec
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uNone/Android.mk
@@ -0,0 +1,28 @@
+# 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)
+
+#apks signed cts-keyset-test-a
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_PACKAGE_NAME := CtsKeySetSigningAUpgradeNone
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/keysets/cts-keyset-test-a
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/keysets/uNone/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/keysets/uNone/AndroidManifest.xml
new file mode 100644
index 0000000..55304f4
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/keysets/uNone/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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="com.android.cts.keysets">
+    <application android:hasCode="false">
+    </application>
+</manifest>
diff --git a/hostsidetests/devicepolicy/.gitignore b/hostsidetests/devicepolicy/.gitignore
new file mode 100644
index 0000000..5e56e04
--- /dev/null
+++ b/hostsidetests/devicepolicy/.gitignore
@@ -0,0 +1 @@
+/bin
diff --git a/hostsidetests/devicepolicy/Android.mk b/hostsidetests/devicepolicy/Android.mk
new file mode 100644
index 0000000..6708c3d
--- /dev/null
+++ b/hostsidetests/devicepolicy/Android.mk
@@ -0,0 +1,32 @@
+# 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CtsDevicePolicyManagerTestCases
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := tradefed-prebuilt tools-common-prebuilt cts-tradefed
+
+LOCAL_CTS_TEST_PACKAGE := android.adminhostside
+
+include $(BUILD_CTS_HOST_JAVA_LIBRARY)
+
+# Build the test APKs using their own makefiles
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/devicepolicy/app/Android.mk b/hostsidetests/devicepolicy/app/Android.mk
new file mode 100644
index 0000000..a22ef3f
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/Android.mk
@@ -0,0 +1,20 @@
+# 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)
+
+include $(CLEAR_VARS)
+
+# Build the test APKs using their own makefiles
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk b/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk
new file mode 100644
index 0000000..e621933
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk
@@ -0,0 +1,31 @@
+# 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsDeviceOwnerApp
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner cts-junit
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml b/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml
new file mode 100644
index 0000000..7a196bf
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml
@@ -0,0 +1,59 @@
+<?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="com.android.cts.deviceowner" >
+
+    <uses-sdk android:minSdkVersion="20"/>
+
+    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
+    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+        <receiver
+            android:name="com.android.cts.deviceowner.BaseDeviceOwnerTest$BasicAdminReceiver"
+            android:permission="android.permission.BIND_DEVICE_ADMIN">
+            <meta-data android:name="android.app.device_admin"
+                       android:resource="@xml/device_admin" />
+            <intent-filter>
+                <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+            </intent-filter>
+        </receiver>
+        <activity android:name="com.android.cts.deviceowner.ExampleIntentReceivingActivity1">
+            <intent-filter>
+                <action android:name="com.android.cts.deviceowner.EXAMPLE_ACTION" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="com.android.cts.deviceowner.ExampleIntentReceivingActivity2">
+            <intent-filter>
+                <action android:name="com.android.cts.deviceowner.EXAMPLE_ACTION" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+        <activity
+            android:name="com.android.cts.deviceowner.LockTaskUtilityActivity" />
+        <activity
+            android:name="com.android.cts.deviceowner.ApplicationRestrictionActivity" />
+    </application>
+
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+                     android:targetPackage="com.android.cts.deviceowner"
+                     android:label="Device Owner CTS tests"/>
+</manifest>
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/res/xml/device_admin.xml b/hostsidetests/devicepolicy/app/DeviceOwner/res/xml/device_admin.xml
new file mode 100644
index 0000000..fe58d38
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/res/xml/device_admin.xml
@@ -0,0 +1,6 @@
+<device-admin xmlns:android="http://schemas.android.com/apk/res/android" android:visible="false">
+    <uses-policies>
+        <reset-password />
+        <limit-password />
+    </uses-policies>
+</device-admin>
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/ApplicationRestrictionActivity.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/ApplicationRestrictionActivity.java
new file mode 100644
index 0000000..4d8e4f2
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/ApplicationRestrictionActivity.java
@@ -0,0 +1,94 @@
+/*
+ * 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 com.android.cts.deviceowner;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.os.UserManager;
+
+/**
+ * Test activity for setApplicationRestrictions().
+ *
+ * The actual test will set restrictions for this package, and the purpose of this
+ * activity is to listen for the ACTION_APPLICATION_RESTRICTIONS_CHANGED broadcast
+ * and relay the retrieved restriction bundle back to the test for validation.
+ */
+public class ApplicationRestrictionActivity extends Activity {
+
+    // Incoming intent type
+    public static final String FINISH = "finishActivity";
+
+    // Outgoing broadcast
+    public static final String REGISTERED_ACTION =
+            "com.android.cts.deviceowner.APP_RESTRICTION_REGISTERED";
+    public static final String RESTRICTION_ACTION =
+            "com.android.cts.deviceowner.APP_RESTRICTION_VALUE";
+
+    private UserManager mUserManager;
+
+    private final BroadcastReceiver mAppRestrictionReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            broadcastRestriction();
+        }
+    };
+
+    private void broadcastRestriction() {
+        Bundle restrictions = mUserManager.getApplicationRestrictions(getPackageName());
+        Intent intent = new Intent(RESTRICTION_ACTION);
+        intent.putExtra("value", restrictions);
+        sendBroadcast(intent);
+    }
+
+    @Override
+    protected void onNewIntent(Intent intent) {
+        super.onNewIntent(intent);
+        handleIntent(intent);
+    }
+
+    @Override
+    protected void onCreate(android.os.Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        handleIntent(getIntent());
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
+        IntentFilter filter = new IntentFilter(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED);
+        registerReceiver(mAppRestrictionReceiver, filter);
+        sendBroadcast(new Intent(REGISTERED_ACTION));
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        unregisterReceiver(mAppRestrictionReceiver);
+    }
+
+    private void handleIntent(Intent intent) {
+        if (intent.getBooleanExtra(FINISH, false)) {
+            finish();
+        }
+    }
+
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/ApplicationRestrictionsTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/ApplicationRestrictionsTest.java
new file mode 100644
index 0000000..5e03de9
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/ApplicationRestrictionsTest.java
@@ -0,0 +1,199 @@
+/*
+ * 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 com.android.cts.deviceowner;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Functionality tests for setApplicationRestrictions and getApplicationRestrictions
+ * in DevicePolicyManager.
+ *
+ * First of all, these two APIs are executed locally to assert that what you set
+ * can later be retrieved via the getter. It also fires up an external activity
+ * (which runs in com.google.android.xts.gmscore, unlike the test code itself
+ * which runs in the test target package com.google.android.gms due to
+ * instrumentation) to observe an application's view of its restrictions.
+ * The activity listens to ACTION_APPLICATION_RESTRICTIONS_CHANGED broadcast
+ * which is fired by the system whenever its restriction is modified,
+ * and relays the value back to this test for verification.
+ */
+public class ApplicationRestrictionsTest extends BaseDeviceOwnerTest {
+
+    private static final String[] testStrings = new String[] {
+            "<bad/>",
+            ">worse!\"£$%^&*()'<",
+            "<JSON>\"{ \\\"One\\\": { \\\"OneOne\\\": \\\"11\\\", \\\""
+                    + "OneTwo\\\": \\\"12\\\" }, \\\"Two\\\": \\\"2\\\" } <JSON/>\""
+    };
+
+    private final Semaphore mOnRegisteredSemaphore = new Semaphore(0);
+    private final Semaphore mOnRestrictionSemaphore = new Semaphore(0);
+    private Bundle mReceivedRestrictions;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(ApplicationRestrictionActivity.REGISTERED_ACTION);
+        filter.addAction(ApplicationRestrictionActivity.RESTRICTION_ACTION);
+        mContext.registerReceiver(mReceiver, filter);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mContext.unregisterReceiver(mReceiver);
+        super.tearDown();
+    }
+
+    public void testSetApplicationRestrictions() {
+        final String CTS_PACKAGE = PACKAGE_NAME;
+        final String OTHER_PACKAGE = CTS_PACKAGE + "dummy";
+
+        startAndWait();
+
+        Bundle bundle0 = createBundle0();
+        Bundle bundle1 = createBundle1();
+
+        // Test setting restrictions
+        mDevicePolicyManager.setApplicationRestrictions(getWho(), CTS_PACKAGE, bundle0);
+        mDevicePolicyManager.setApplicationRestrictions(getWho(), OTHER_PACKAGE, bundle1);
+
+        // Retrieve restrictions locally and make sure they are what we put in.
+        assertBundle0(mDevicePolicyManager.getApplicationRestrictions(getWho(), CTS_PACKAGE));
+        assertBundle1(mDevicePolicyManager.getApplicationRestrictions(getWho(), OTHER_PACKAGE));
+
+        // The test activity should have received a change_restriction broadcast
+        // and relay the value back to us.
+        assertBundle0(waitForChangedRestriction());
+
+        // Test overwriting
+        mDevicePolicyManager.setApplicationRestrictions(getWho(), CTS_PACKAGE, bundle1);
+        assertBundle1(mDevicePolicyManager.getApplicationRestrictions(getWho(), CTS_PACKAGE));
+        assertBundle1(waitForChangedRestriction());
+
+        // Cleanup
+        mDevicePolicyManager.setApplicationRestrictions(getWho(), CTS_PACKAGE, new Bundle());
+        assertTrue(
+                mDevicePolicyManager.getApplicationRestrictions(getWho(), CTS_PACKAGE).isEmpty());
+        assertTrue(waitForChangedRestriction().isEmpty());
+        mDevicePolicyManager.setApplicationRestrictions(getWho(), OTHER_PACKAGE, new Bundle());
+        assertTrue(
+                mDevicePolicyManager.getApplicationRestrictions(getWho(), OTHER_PACKAGE).isEmpty());
+
+        finish();
+    }
+
+    // Should be consistent with assertBundle0
+    private Bundle createBundle0() {
+        Bundle result = new Bundle();
+        // Tests for four allowed types: Integer, Boolean, String and String[]
+        // Also test for string escaping handling
+        result.putBoolean("boolean_0", false);
+        result.putBoolean("boolean_1", true);
+        result.putInt("integer", 0x7fffffff);
+        // If a null is stored, "" will be read back
+        result.putString("empty", "");
+        result.putString("string", "text");
+        result.putStringArray("string[]", testStrings);
+        return result;
+    }
+
+    // Should be consistent with createBundle0
+    private void assertBundle0(Bundle bundle) {
+        assertEquals(6, bundle.size());
+        assertEquals(false, bundle.getBoolean("boolean_0"));
+        assertEquals(true, bundle.getBoolean("boolean_1"));
+        assertEquals(0x7fffffff, bundle.getInt("integer"));
+        assertEquals("", bundle.getString("empty"));
+        assertEquals("text", bundle.getString("string"));
+
+        String[] strings = bundle.getStringArray("string[]");
+        assertTrue(strings != null && strings.length == testStrings.length);
+        for (int i = 0; i < strings.length; i++) {
+            assertEquals(strings[i], testStrings[i]);
+        }
+    }
+
+    // Should be consistent with assertBundle1
+    private Bundle createBundle1() {
+        Bundle result = new Bundle();
+        result.putInt("dummy", 1);
+        return result;
+    }
+
+    // Should be consistent with createBundle1
+    private void assertBundle1(Bundle bundle) {
+        assertEquals(1, bundle.size());
+        assertEquals(1, bundle.getInt("dummy"));
+    }
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (ApplicationRestrictionActivity.REGISTERED_ACTION.equals(action)) {
+                mOnRegisteredSemaphore.release();
+            } else if (ApplicationRestrictionActivity.RESTRICTION_ACTION.equals(action)) {
+                mReceivedRestrictions = intent.getBundleExtra("value");
+                mOnRestrictionSemaphore.release();
+            }
+        }
+    };
+
+    private void startTestActivity(String command) {
+        Intent intent = new Intent();
+        intent.setClassName(PACKAGE_NAME, ApplicationRestrictionActivity.class.getName());
+        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
+
+        if (command != null) {
+            intent.putExtra(command, true);
+        }
+        mContext.startActivity(intent);
+    }
+
+    private void startAndWait() {
+        startTestActivity(null);
+        // Wait until the activity has registered its broadcast receiver and ready for incoming
+        // restriction changes.
+        try {
+            assertTrue(mOnRegisteredSemaphore.tryAcquire(5, TimeUnit.SECONDS));
+        } catch (InterruptedException e) {
+            fail("Start ApplicationRestrictionActivity interrupted");
+        }
+    }
+
+    private Bundle waitForChangedRestriction() {
+        try {
+            assertTrue(mOnRestrictionSemaphore.tryAcquire(5, TimeUnit.SECONDS));
+        } catch (InterruptedException e) {
+            fail("getRestrictionsAndWait() interrupted");
+        }
+
+        return mReceivedRestrictions;
+    }
+
+    private void finish() {
+        startTestActivity(ApplicationRestrictionActivity.FINISH);
+    }
+
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/BaseDeviceOwnerTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/BaseDeviceOwnerTest.java
new file mode 100644
index 0000000..e4f5134b
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/BaseDeviceOwnerTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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 com.android.cts.deviceowner;
+
+import android.app.admin.DeviceAdminReceiver;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.test.AndroidTestCase;
+
+/**
+ * Base class for device-owner based tests.
+ *
+ * This class handles making sure that the test is the device owner
+ * and that it has an active admin registered, so that all tests may
+ * assume these are done. The admin component can be accessed through
+ * {@link #getWho()}.
+ */
+public class BaseDeviceOwnerTest extends AndroidTestCase {
+
+    public static class BasicAdminReceiver extends DeviceAdminReceiver {
+    }
+
+    public static final String PACKAGE_NAME = BaseDeviceOwnerTest.class.getPackage().getName();
+
+    protected DevicePolicyManager mDevicePolicyManager;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mDevicePolicyManager = (DevicePolicyManager)
+                mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+        assertTrue(mDevicePolicyManager.isAdminActive(getWho()));
+        assertTrue(mDevicePolicyManager.isDeviceOwnerApp(PACKAGE_NAME));
+    }
+
+    public static ComponentName getWho() {
+        return new ComponentName(PACKAGE_NAME, BasicAdminReceiver.class.getName());
+    }
+}
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CaCertManagementTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CaCertManagementTest.java
new file mode 100644
index 0000000..9127dab
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CaCertManagementTest.java
@@ -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.
+ */
+package com.android.cts.deviceowner;
+
+import static com.android.cts.deviceowner.FakeKeys.FAKE_RSA_1;
+import static com.android.cts.deviceowner.FakeKeys.FAKE_DSA_1;
+
+import java.io.ByteArrayInputStream;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.Certificate;
+import java.util.List;
+
+public class CaCertManagementTest extends BaseDeviceOwnerTest {
+    public void testCanRetrieveListOfInstalledCaCerts() {
+        List<byte[]> caCerts = mDevicePolicyManager.getInstalledCaCerts(getWho());
+        assertNotNull(caCerts);
+    }
+
+    public void testCanInstallAndUninstallACaCert()
+    throws CertificateException {
+        assertFalse(hasCaCertInstalled(FAKE_RSA_1.caCertificate));
+        assertFalse(hasCaCertInstalled(FAKE_DSA_1.caCertificate));
+        assertTrue(mDevicePolicyManager.installCaCert(getWho(), FAKE_RSA_1.caCertificate));
+        assertTrue(hasCaCertInstalled(FAKE_RSA_1.caCertificate));
+        assertFalse(hasCaCertInstalled(FAKE_DSA_1.caCertificate));
+        mDevicePolicyManager.uninstallCaCert(getWho(), FAKE_RSA_1.caCertificate);
+        assertFalse(hasCaCertInstalled(FAKE_RSA_1.caCertificate));
+        assertFalse(hasCaCertInstalled(FAKE_DSA_1.caCertificate));
+    }
+
+    public void testUninstallationIsSelective() throws CertificateException {
+        assertTrue(mDevicePolicyManager.installCaCert(getWho(), FAKE_RSA_1.caCertificate));
+        assertTrue(mDevicePolicyManager.installCaCert(getWho(), FAKE_DSA_1.caCertificate));
+        mDevicePolicyManager.uninstallCaCert(getWho(), FAKE_DSA_1.caCertificate);
+        assertTrue(hasCaCertInstalled(FAKE_RSA_1.caCertificate));
+        assertFalse(hasCaCertInstalled(FAKE_DSA_1.caCertificate));
+        mDevicePolicyManager.uninstallCaCert(getWho(), FAKE_RSA_1.caCertificate);
+    }
+
+    public void testCanUninstallAllUserCaCerts() throws CertificateException {
+        assertTrue(mDevicePolicyManager.installCaCert(getWho(), FAKE_RSA_1.caCertificate));
+        assertTrue(mDevicePolicyManager.installCaCert(getWho(), FAKE_DSA_1.caCertificate));
+        mDevicePolicyManager.uninstallAllUserCaCerts(getWho());
+        assertFalse(hasCaCertInstalled(FAKE_RSA_1.caCertificate));
+        assertFalse(hasCaCertInstalled(FAKE_DSA_1.caCertificate));
+    }
+
+    private boolean hasCaCertInstalled(byte [] caCert) throws CertificateException {
+        boolean result = mDevicePolicyManager.hasCaCertInstalled(getWho(), caCert);
+        assertEquals(result, containsCertificate(
+            mDevicePolicyManager.getInstalledCaCerts(getWho()), caCert));
+        return result;
+    }
+
+    private static boolean containsCertificate(List<byte[]> certificates, byte [] toMatch)
+            throws CertificateException {
+        Certificate certificateToMatch = readCertificate(toMatch);
+        for (byte[] certBuffer : certificates) {
+            Certificate cert = readCertificate(certBuffer);
+            if (certificateToMatch.equals(cert)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static Certificate readCertificate(byte[] certBuffer) throws CertificateException {
+        final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+        return certFactory.generateCertificate(new ByteArrayInputStream(certBuffer));
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/ClearDeviceOwnerTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/ClearDeviceOwnerTest.java
new file mode 100644
index 0000000..f10124a
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/ClearDeviceOwnerTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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 com.android.cts.deviceowner;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.test.AndroidTestCase;
+
+public class ClearDeviceOwnerTest extends AndroidTestCase {
+
+    private DevicePolicyManager mDevicePolicyManager;
+
+    @Override
+    protected void tearDown() throws Exception {
+        mDevicePolicyManager = (DevicePolicyManager)
+                mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+        if (mDevicePolicyManager != null) {
+            removeActiveAdmin(BaseDeviceOwnerTest.getWho());
+            if (mDevicePolicyManager.isDeviceOwnerApp(BaseDeviceOwnerTest.PACKAGE_NAME)) {
+                mDevicePolicyManager.clearDeviceOwnerApp(BaseDeviceOwnerTest.PACKAGE_NAME);
+            }
+            assertFalse(mDevicePolicyManager.isAdminActive(BaseDeviceOwnerTest.getWho()));
+            assertFalse(mDevicePolicyManager.isDeviceOwnerApp(BaseDeviceOwnerTest.PACKAGE_NAME));
+        }
+
+        super.tearDown();
+    }
+
+    // This test clears the device owner and active admin on tearDown(). To be called from the host
+    // side test once a test case is finished.
+    public void testClearDeviceOwner() {
+    }
+
+    private void removeActiveAdmin(ComponentName cn) throws InterruptedException {
+        if (mDevicePolicyManager.isAdminActive(cn)) {
+            mDevicePolicyManager.removeActiveAdmin(cn);
+            for (int i = 0; i < 1000 && mDevicePolicyManager.isAdminActive(cn); i++) {
+                Thread.sleep(100);
+            }
+        }
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DeviceOwnerSetupTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DeviceOwnerSetupTest.java
new file mode 100644
index 0000000..e6441ef
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/DeviceOwnerSetupTest.java
@@ -0,0 +1,27 @@
+/*
+ * 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 com.android.cts.deviceowner;
+
+
+public class DeviceOwnerSetupTest extends BaseDeviceOwnerTest {
+
+    // This test verifies that the setup assertions are working to verify
+    // we are the device owner and have a valid active admin.
+    public void testEmptyTest() {
+    }
+
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/ExampleIntentReceivingActivity1.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/ExampleIntentReceivingActivity1.java
new file mode 100644
index 0000000..03ca9a4
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/ExampleIntentReceivingActivity1.java
@@ -0,0 +1,34 @@
+/*
+ * 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 com.android.cts.deviceowner;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+public class ExampleIntentReceivingActivity1 extends Activity {
+    public static final String CONFIRM_ACTION = "com.android.cts.deviceowner.CONFIRM_1";
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        if (getIntent().getAction().equals(PersistentIntentResolvingTest.EXAMPLE_ACTION)) {
+            sendBroadcast(new Intent(CONFIRM_ACTION));
+        }
+        finish();
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/ExampleIntentReceivingActivity2.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/ExampleIntentReceivingActivity2.java
new file mode 100644
index 0000000..65ccb36
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/ExampleIntentReceivingActivity2.java
@@ -0,0 +1,34 @@
+/*
+ * 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 com.android.cts.deviceowner;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+public class ExampleIntentReceivingActivity2 extends Activity {
+    public static final String CONFIRM_ACTION = "com.android.cts.deviceowner.CONFIRM_2";
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        if (getIntent().getAction().equals(PersistentIntentResolvingTest.EXAMPLE_ACTION)) {
+            sendBroadcast(new Intent(CONFIRM_ACTION));
+        }
+        finish();
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/FakeKeys.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/FakeKeys.java
new file mode 100644
index 0000000..11df8e5
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/FakeKeys.java
@@ -0,0 +1,469 @@
+/*
+ * 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 com.android.cts.deviceowner;
+
+// Copied from cts/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java
+
+public class FakeKeys {
+    /*
+     * The keys and certificates below are generated with:
+     *
+     * openssl req -new -x509 -days 3650 -extensions v3_ca -keyout cakey.pem -out cacert.pem
+     * openssl req -newkey rsa:1024 -keyout userkey.pem -nodes -days 3650 -out userkey.req
+     * mkdir -p demoCA/newcerts
+     * touch demoCA/index.txt
+     * echo "01" > demoCA/serial
+     * openssl ca -out usercert.pem -in userkey.req -cert cacert.pem -keyfile cakey.pem -days 3650
+     */
+    public static class FAKE_RSA_1 {
+        /**
+         * Generated from above and converted with:
+         *
+         * openssl pkcs8 -topk8 -outform d -in userkey.pem -nocrypt | xxd -i | sed 's/0x/(byte) 0x/g'
+         */
+        public static final byte[] privateKey = {
+            (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x78, (byte) 0x02, (byte) 0x01,
+            (byte) 0x00, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a,
+            (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01,
+            (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x82,
+            (byte) 0x02, (byte) 0x62, (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x5e,
+            (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x02, (byte) 0x81, (byte) 0x81,
+            (byte) 0x00, (byte) 0xce, (byte) 0x29, (byte) 0xeb, (byte) 0xf6, (byte) 0x5b,
+            (byte) 0x25, (byte) 0xdc, (byte) 0xa1, (byte) 0xa6, (byte) 0x2c, (byte) 0x66,
+            (byte) 0xcb, (byte) 0x20, (byte) 0x90, (byte) 0x27, (byte) 0x86, (byte) 0x8a,
+            (byte) 0x44, (byte) 0x71, (byte) 0x50, (byte) 0xda, (byte) 0xd3, (byte) 0x02,
+            (byte) 0x77, (byte) 0x55, (byte) 0xe9, (byte) 0xe8, (byte) 0x08, (byte) 0xf3,
+            (byte) 0x36, (byte) 0x9a, (byte) 0xae, (byte) 0xab, (byte) 0x04, (byte) 0x6d,
+            (byte) 0x00, (byte) 0x99, (byte) 0xbf, (byte) 0x7d, (byte) 0x0f, (byte) 0x67,
+            (byte) 0x8b, (byte) 0x1d, (byte) 0xd4, (byte) 0x2b, (byte) 0x7c, (byte) 0xcb,
+            (byte) 0xcd, (byte) 0x33, (byte) 0xc7, (byte) 0x84, (byte) 0x30, (byte) 0xe2,
+            (byte) 0x45, (byte) 0x21, (byte) 0xb3, (byte) 0x75, (byte) 0xf5, (byte) 0x79,
+            (byte) 0x02, (byte) 0xda, (byte) 0x50, (byte) 0xa3, (byte) 0x8b, (byte) 0xce,
+            (byte) 0xc3, (byte) 0x8e, (byte) 0x0f, (byte) 0x25, (byte) 0xeb, (byte) 0x08,
+            (byte) 0x2c, (byte) 0xdd, (byte) 0x1c, (byte) 0xcf, (byte) 0xff, (byte) 0x3b,
+            (byte) 0xde, (byte) 0xb6, (byte) 0xaa, (byte) 0x2a, (byte) 0xa9, (byte) 0xc4,
+            (byte) 0x8a, (byte) 0x24, (byte) 0x24, (byte) 0xe6, (byte) 0x29, (byte) 0x0d,
+            (byte) 0x98, (byte) 0x4c, (byte) 0x32, (byte) 0xa1, (byte) 0x7b, (byte) 0x23,
+            (byte) 0x2b, (byte) 0x42, (byte) 0x30, (byte) 0xee, (byte) 0x78, (byte) 0x08,
+            (byte) 0x47, (byte) 0xad, (byte) 0xf2, (byte) 0x96, (byte) 0xd5, (byte) 0xf1,
+            (byte) 0x62, (byte) 0x42, (byte) 0x2d, (byte) 0x35, (byte) 0x19, (byte) 0xb4,
+            (byte) 0x3c, (byte) 0xc9, (byte) 0xc3, (byte) 0x5f, (byte) 0x03, (byte) 0x16,
+            (byte) 0x3a, (byte) 0x23, (byte) 0xac, (byte) 0xcb, (byte) 0xce, (byte) 0x9e,
+            (byte) 0x51, (byte) 0x2e, (byte) 0x6d, (byte) 0x02, (byte) 0x03, (byte) 0x01,
+            (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x81, (byte) 0x80, (byte) 0x16,
+            (byte) 0x59, (byte) 0xc3, (byte) 0x24, (byte) 0x1d, (byte) 0x33, (byte) 0x98,
+            (byte) 0x9c, (byte) 0xc9, (byte) 0xc8, (byte) 0x2c, (byte) 0x88, (byte) 0xbf,
+            (byte) 0x0a, (byte) 0x01, (byte) 0xce, (byte) 0xfb, (byte) 0x34, (byte) 0x7a,
+            (byte) 0x58, (byte) 0x7a, (byte) 0xb0, (byte) 0xbf, (byte) 0xa6, (byte) 0xb2,
+            (byte) 0x60, (byte) 0xbe, (byte) 0x70, (byte) 0x21, (byte) 0xf5, (byte) 0xfc,
+            (byte) 0x85, (byte) 0x0d, (byte) 0x33, (byte) 0x58, (byte) 0xa1, (byte) 0xe5,
+            (byte) 0x09, (byte) 0x36, (byte) 0x84, (byte) 0xb2, (byte) 0x04, (byte) 0x0a,
+            (byte) 0x02, (byte) 0xd3, (byte) 0x88, (byte) 0x1f, (byte) 0x0c, (byte) 0x2b,
+            (byte) 0x1d, (byte) 0xe9, (byte) 0x3d, (byte) 0xe7, (byte) 0x79, (byte) 0xf9,
+            (byte) 0x32, (byte) 0x5c, (byte) 0x8a, (byte) 0x75, (byte) 0x49, (byte) 0x12,
+            (byte) 0xe4, (byte) 0x05, (byte) 0x26, (byte) 0xd4, (byte) 0x2e, (byte) 0x9e,
+            (byte) 0x1f, (byte) 0xcc, (byte) 0x54, (byte) 0xad, (byte) 0x33, (byte) 0x8d,
+            (byte) 0x99, (byte) 0x00, (byte) 0xdc, (byte) 0xf5, (byte) 0xb4, (byte) 0xa2,
+            (byte) 0x2f, (byte) 0xba, (byte) 0xe5, (byte) 0x62, (byte) 0x30, (byte) 0x6d,
+            (byte) 0xe6, (byte) 0x3d, (byte) 0xeb, (byte) 0x24, (byte) 0xc2, (byte) 0xdc,
+            (byte) 0x5f, (byte) 0xb7, (byte) 0x16, (byte) 0x35, (byte) 0xa3, (byte) 0x98,
+            (byte) 0x98, (byte) 0xa8, (byte) 0xef, (byte) 0xe8, (byte) 0xc4, (byte) 0x96,
+            (byte) 0x6d, (byte) 0x38, (byte) 0xab, (byte) 0x26, (byte) 0x6d, (byte) 0x30,
+            (byte) 0xc2, (byte) 0xa0, (byte) 0x44, (byte) 0xe4, (byte) 0xff, (byte) 0x7e,
+            (byte) 0xbe, (byte) 0x7c, (byte) 0x33, (byte) 0xa5, (byte) 0x10, (byte) 0xad,
+            (byte) 0xd7, (byte) 0x1e, (byte) 0x13, (byte) 0x20, (byte) 0xb3, (byte) 0x1f,
+            (byte) 0x41, (byte) 0x02, (byte) 0x41, (byte) 0x00, (byte) 0xf1, (byte) 0x89,
+            (byte) 0x07, (byte) 0x0f, (byte) 0xe8, (byte) 0xcf, (byte) 0xab, (byte) 0x13,
+            (byte) 0x2a, (byte) 0x8f, (byte) 0x88, (byte) 0x80, (byte) 0x11, (byte) 0x9a,
+            (byte) 0x79, (byte) 0xb6, (byte) 0x59, (byte) 0x3a, (byte) 0x50, (byte) 0x6e,
+            (byte) 0x57, (byte) 0x37, (byte) 0xab, (byte) 0x2a, (byte) 0xd2, (byte) 0xaa,
+            (byte) 0xd9, (byte) 0x72, (byte) 0x73, (byte) 0xff, (byte) 0x8b, (byte) 0x47,
+            (byte) 0x76, (byte) 0xdd, (byte) 0xdc, (byte) 0xf5, (byte) 0x97, (byte) 0x44,
+            (byte) 0x3a, (byte) 0x78, (byte) 0xbe, (byte) 0x17, (byte) 0xb4, (byte) 0x22,
+            (byte) 0x6f, (byte) 0xe5, (byte) 0x23, (byte) 0x70, (byte) 0x1d, (byte) 0x10,
+            (byte) 0x5d, (byte) 0xba, (byte) 0x16, (byte) 0x81, (byte) 0xf1, (byte) 0x45,
+            (byte) 0xce, (byte) 0x30, (byte) 0xb4, (byte) 0xab, (byte) 0x80, (byte) 0xe4,
+            (byte) 0x98, (byte) 0x31, (byte) 0x02, (byte) 0x41, (byte) 0x00, (byte) 0xda,
+            (byte) 0x82, (byte) 0x9d, (byte) 0x3f, (byte) 0xca, (byte) 0x2f, (byte) 0xe1,
+            (byte) 0xd4, (byte) 0x86, (byte) 0x77, (byte) 0x48, (byte) 0xa6, (byte) 0xab,
+            (byte) 0xab, (byte) 0x1c, (byte) 0x42, (byte) 0x5c, (byte) 0xd5, (byte) 0xc7,
+            (byte) 0x46, (byte) 0x59, (byte) 0x91, (byte) 0x3f, (byte) 0xfc, (byte) 0xcc,
+            (byte) 0xec, (byte) 0xc2, (byte) 0x40, (byte) 0x12, (byte) 0x2c, (byte) 0x8d,
+            (byte) 0x1f, (byte) 0xa2, (byte) 0x18, (byte) 0x88, (byte) 0xee, (byte) 0x82,
+            (byte) 0x4a, (byte) 0x5a, (byte) 0x5e, (byte) 0x88, (byte) 0x20, (byte) 0xe3,
+            (byte) 0x7b, (byte) 0xe0, (byte) 0xd8, (byte) 0x3a, (byte) 0x52, (byte) 0x9a,
+            (byte) 0x26, (byte) 0x6a, (byte) 0x04, (byte) 0xec, (byte) 0xe8, (byte) 0xb9,
+            (byte) 0x48, (byte) 0x40, (byte) 0xe1, (byte) 0xe1, (byte) 0x83, (byte) 0xa6,
+            (byte) 0x67, (byte) 0xa6, (byte) 0xfd, (byte) 0x02, (byte) 0x41, (byte) 0x00,
+            (byte) 0x89, (byte) 0x72, (byte) 0x3e, (byte) 0xb0, (byte) 0x90, (byte) 0xfd,
+            (byte) 0x4c, (byte) 0x0e, (byte) 0xd6, (byte) 0x13, (byte) 0x63, (byte) 0xcb,
+            (byte) 0xed, (byte) 0x38, (byte) 0x88, (byte) 0xb6, (byte) 0x79, (byte) 0xc4,
+            (byte) 0x33, (byte) 0x6c, (byte) 0xf6, (byte) 0xf8, (byte) 0xd8, (byte) 0xd0,
+            (byte) 0xbf, (byte) 0x9d, (byte) 0x35, (byte) 0xac, (byte) 0x69, (byte) 0xd2,
+            (byte) 0x2b, (byte) 0xc1, (byte) 0xf9, (byte) 0x24, (byte) 0x7b, (byte) 0xce,
+            (byte) 0xcd, (byte) 0xcb, (byte) 0xa7, (byte) 0xb2, (byte) 0x7a, (byte) 0x0a,
+            (byte) 0x27, (byte) 0x19, (byte) 0xc9, (byte) 0xaf, (byte) 0x0d, (byte) 0x21,
+            (byte) 0x89, (byte) 0x88, (byte) 0x7c, (byte) 0xad, (byte) 0x9e, (byte) 0x8d,
+            (byte) 0x47, (byte) 0x6d, (byte) 0x3f, (byte) 0xce, (byte) 0x7b, (byte) 0xa1,
+            (byte) 0x74, (byte) 0xf1, (byte) 0xa0, (byte) 0xa1, (byte) 0x02, (byte) 0x41,
+            (byte) 0x00, (byte) 0xd9, (byte) 0xa8, (byte) 0xf5, (byte) 0xfe, (byte) 0xce,
+            (byte) 0xe6, (byte) 0x77, (byte) 0x6b, (byte) 0xfe, (byte) 0x2d, (byte) 0xe0,
+            (byte) 0x1e, (byte) 0xb6, (byte) 0x2e, (byte) 0x12, (byte) 0x4e, (byte) 0x40,
+            (byte) 0xaf, (byte) 0x6a, (byte) 0x7b, (byte) 0x37, (byte) 0x49, (byte) 0x2a,
+            (byte) 0x96, (byte) 0x25, (byte) 0x83, (byte) 0x49, (byte) 0xd4, (byte) 0x0c,
+            (byte) 0xc6, (byte) 0x78, (byte) 0x25, (byte) 0x24, (byte) 0x90, (byte) 0x90,
+            (byte) 0x06, (byte) 0x15, (byte) 0x9e, (byte) 0xfe, (byte) 0xf9, (byte) 0xdf,
+            (byte) 0x5b, (byte) 0xf3, (byte) 0x7e, (byte) 0x38, (byte) 0x70, (byte) 0xeb,
+            (byte) 0x57, (byte) 0xd0, (byte) 0xd9, (byte) 0xa7, (byte) 0x0e, (byte) 0x14,
+            (byte) 0xf7, (byte) 0x95, (byte) 0x68, (byte) 0xd5, (byte) 0xc8, (byte) 0xab,
+            (byte) 0x9d, (byte) 0x3a, (byte) 0x2b, (byte) 0x51, (byte) 0xf9, (byte) 0x02,
+            (byte) 0x41, (byte) 0x00, (byte) 0x96, (byte) 0xdf, (byte) 0xe9, (byte) 0x67,
+            (byte) 0x6c, (byte) 0xdc, (byte) 0x90, (byte) 0x14, (byte) 0xb4, (byte) 0x1d,
+            (byte) 0x22, (byte) 0x33, (byte) 0x4a, (byte) 0x31, (byte) 0xc1, (byte) 0x9d,
+            (byte) 0x2e, (byte) 0xff, (byte) 0x9a, (byte) 0x2a, (byte) 0x95, (byte) 0x4b,
+            (byte) 0x27, (byte) 0x74, (byte) 0xcb, (byte) 0x21, (byte) 0xc3, (byte) 0xd2,
+            (byte) 0x0b, (byte) 0xb2, (byte) 0x46, (byte) 0x87, (byte) 0xf8, (byte) 0x28,
+            (byte) 0x01, (byte) 0x8b, (byte) 0xd8, (byte) 0xb9, (byte) 0x4b, (byte) 0xcd,
+            (byte) 0x9a, (byte) 0x96, (byte) 0x41, (byte) 0x0e, (byte) 0x36, (byte) 0x6d,
+            (byte) 0x40, (byte) 0x42, (byte) 0xbc, (byte) 0xd9, (byte) 0xd3, (byte) 0x7b,
+            (byte) 0xbc, (byte) 0xa7, (byte) 0x92, (byte) 0x90, (byte) 0xdd, (byte) 0xa1,
+            (byte) 0x9c, (byte) 0xce, (byte) 0xa1, (byte) 0x87, (byte) 0x11, (byte) 0x51
+        };
+
+        /**
+         * Generated from above and converted with:
+         *
+         * openssl x509 -outform d -in cacert.pem | xxd -i | sed 's/0x/(byte) 0x/g'
+         */
+        public static final byte[] caCertificate = {
+            (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0xce, (byte) 0x30, (byte) 0x82,
+            (byte) 0x02, (byte) 0x37, (byte) 0xa0, (byte) 0x03, (byte) 0x02, (byte) 0x01,
+            (byte) 0x02, (byte) 0x02, (byte) 0x09, (byte) 0x00, (byte) 0xe1, (byte) 0x6a,
+            (byte) 0xa2, (byte) 0xf4, (byte) 0x2e, (byte) 0x55, (byte) 0x48, (byte) 0x0a,
+            (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86,
+            (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01,
+            (byte) 0x05, (byte) 0x05, (byte) 0x00, (byte) 0x30, (byte) 0x4f, (byte) 0x31,
+            (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x04, (byte) 0x06, (byte) 0x13, (byte) 0x02, (byte) 0x55, (byte) 0x53,
+            (byte) 0x31, (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03,
+            (byte) 0x55, (byte) 0x04, (byte) 0x08, (byte) 0x13, (byte) 0x02, (byte) 0x43,
+            (byte) 0x41, (byte) 0x31, (byte) 0x16, (byte) 0x30, (byte) 0x14, (byte) 0x06,
+            (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x07, (byte) 0x13, (byte) 0x0d,
+            (byte) 0x4d, (byte) 0x6f, (byte) 0x75, (byte) 0x6e, (byte) 0x74, (byte) 0x61,
+            (byte) 0x69, (byte) 0x6e, (byte) 0x20, (byte) 0x56, (byte) 0x69, (byte) 0x65,
+            (byte) 0x77, (byte) 0x31, (byte) 0x1b, (byte) 0x30, (byte) 0x19, (byte) 0x06,
+            (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x13, (byte) 0x12,
+            (byte) 0x41, (byte) 0x6e, (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69,
+            (byte) 0x64, (byte) 0x20, (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74,
+            (byte) 0x20, (byte) 0x43, (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x73,
+            (byte) 0x30, (byte) 0x1e, (byte) 0x17, (byte) 0x0d, (byte) 0x31, (byte) 0x32,
+            (byte) 0x30, (byte) 0x38, (byte) 0x31, (byte) 0x34, (byte) 0x31, (byte) 0x36,
+            (byte) 0x35, (byte) 0x35, (byte) 0x34, (byte) 0x34, (byte) 0x5a, (byte) 0x17,
+            (byte) 0x0d, (byte) 0x32, (byte) 0x32, (byte) 0x30, (byte) 0x38, (byte) 0x31,
+            (byte) 0x32, (byte) 0x31, (byte) 0x36, (byte) 0x35, (byte) 0x35, (byte) 0x34,
+            (byte) 0x34, (byte) 0x5a, (byte) 0x30, (byte) 0x4f, (byte) 0x31, (byte) 0x0b,
+            (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+            (byte) 0x06, (byte) 0x13, (byte) 0x02, (byte) 0x55, (byte) 0x53, (byte) 0x31,
+            (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x04, (byte) 0x08, (byte) 0x13, (byte) 0x02, (byte) 0x43, (byte) 0x41,
+            (byte) 0x31, (byte) 0x16, (byte) 0x30, (byte) 0x14, (byte) 0x06, (byte) 0x03,
+            (byte) 0x55, (byte) 0x04, (byte) 0x07, (byte) 0x13, (byte) 0x0d, (byte) 0x4d,
+            (byte) 0x6f, (byte) 0x75, (byte) 0x6e, (byte) 0x74, (byte) 0x61, (byte) 0x69,
+            (byte) 0x6e, (byte) 0x20, (byte) 0x56, (byte) 0x69, (byte) 0x65, (byte) 0x77,
+            (byte) 0x31, (byte) 0x1b, (byte) 0x30, (byte) 0x19, (byte) 0x06, (byte) 0x03,
+            (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x13, (byte) 0x12, (byte) 0x41,
+            (byte) 0x6e, (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64,
+            (byte) 0x20, (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x20,
+            (byte) 0x43, (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x73, (byte) 0x30,
+            (byte) 0x81, (byte) 0x9f, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09,
+            (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d,
+            (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x03,
+            (byte) 0x81, (byte) 0x8d, (byte) 0x00, (byte) 0x30, (byte) 0x81, (byte) 0x89,
+            (byte) 0x02, (byte) 0x81, (byte) 0x81, (byte) 0x00, (byte) 0xa3, (byte) 0x72,
+            (byte) 0xab, (byte) 0xd0, (byte) 0xe4, (byte) 0xad, (byte) 0x2f, (byte) 0xe7,
+            (byte) 0xe2, (byte) 0x79, (byte) 0x07, (byte) 0x36, (byte) 0x3d, (byte) 0x0c,
+            (byte) 0x8d, (byte) 0x42, (byte) 0x9a, (byte) 0x0a, (byte) 0x33, (byte) 0x64,
+            (byte) 0xb3, (byte) 0xcd, (byte) 0xb2, (byte) 0xd7, (byte) 0x3a, (byte) 0x42,
+            (byte) 0x06, (byte) 0x77, (byte) 0x45, (byte) 0x29, (byte) 0xe9, (byte) 0xcb,
+            (byte) 0xb7, (byte) 0x4a, (byte) 0xd6, (byte) 0xee, (byte) 0xad, (byte) 0x01,
+            (byte) 0x91, (byte) 0x9b, (byte) 0x0c, (byte) 0x59, (byte) 0xa1, (byte) 0x03,
+            (byte) 0xfa, (byte) 0xf0, (byte) 0x5a, (byte) 0x7c, (byte) 0x4f, (byte) 0xf7,
+            (byte) 0x8d, (byte) 0x36, (byte) 0x0f, (byte) 0x1f, (byte) 0x45, (byte) 0x7d,
+            (byte) 0x1b, (byte) 0x31, (byte) 0xa1, (byte) 0x35, (byte) 0x0b, (byte) 0x00,
+            (byte) 0xed, (byte) 0x7a, (byte) 0xb6, (byte) 0xc8, (byte) 0x4e, (byte) 0xa9,
+            (byte) 0x86, (byte) 0x4c, (byte) 0x7b, (byte) 0x99, (byte) 0x57, (byte) 0x41,
+            (byte) 0x12, (byte) 0xef, (byte) 0x6b, (byte) 0xbc, (byte) 0x3d, (byte) 0x60,
+            (byte) 0xf2, (byte) 0x99, (byte) 0x1a, (byte) 0xcd, (byte) 0xed, (byte) 0x56,
+            (byte) 0xa4, (byte) 0xe5, (byte) 0x36, (byte) 0x9f, (byte) 0x24, (byte) 0x1f,
+            (byte) 0xdc, (byte) 0x89, (byte) 0x40, (byte) 0xc8, (byte) 0x99, (byte) 0x92,
+            (byte) 0xab, (byte) 0x4a, (byte) 0xb5, (byte) 0x61, (byte) 0x45, (byte) 0x62,
+            (byte) 0xff, (byte) 0xa3, (byte) 0x45, (byte) 0x65, (byte) 0xaf, (byte) 0xf6,
+            (byte) 0x27, (byte) 0x30, (byte) 0x51, (byte) 0x0e, (byte) 0x0e, (byte) 0xeb,
+            (byte) 0x79, (byte) 0x0c, (byte) 0xbe, (byte) 0xb3, (byte) 0x0a, (byte) 0x6f,
+            (byte) 0x29, (byte) 0x06, (byte) 0xdc, (byte) 0x2f, (byte) 0x6b, (byte) 0x51,
+            (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0xa3,
+            (byte) 0x81, (byte) 0xb1, (byte) 0x30, (byte) 0x81, (byte) 0xae, (byte) 0x30,
+            (byte) 0x1d, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x0e,
+            (byte) 0x04, (byte) 0x16, (byte) 0x04, (byte) 0x14, (byte) 0x33, (byte) 0x05,
+            (byte) 0xee, (byte) 0xfe, (byte) 0x6f, (byte) 0x60, (byte) 0xc7, (byte) 0xf9,
+            (byte) 0xa9, (byte) 0xd2, (byte) 0x73, (byte) 0x5c, (byte) 0x8f, (byte) 0x6d,
+            (byte) 0xa2, (byte) 0x2f, (byte) 0x97, (byte) 0x8e, (byte) 0x5d, (byte) 0x51,
+            (byte) 0x30, (byte) 0x7f, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d,
+            (byte) 0x23, (byte) 0x04, (byte) 0x78, (byte) 0x30, (byte) 0x76, (byte) 0x80,
+            (byte) 0x14, (byte) 0x33, (byte) 0x05, (byte) 0xee, (byte) 0xfe, (byte) 0x6f,
+            (byte) 0x60, (byte) 0xc7, (byte) 0xf9, (byte) 0xa9, (byte) 0xd2, (byte) 0x73,
+            (byte) 0x5c, (byte) 0x8f, (byte) 0x6d, (byte) 0xa2, (byte) 0x2f, (byte) 0x97,
+            (byte) 0x8e, (byte) 0x5d, (byte) 0x51, (byte) 0xa1, (byte) 0x53, (byte) 0xa4,
+            (byte) 0x51, (byte) 0x30, (byte) 0x4f, (byte) 0x31, (byte) 0x0b, (byte) 0x30,
+            (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x06,
+            (byte) 0x13, (byte) 0x02, (byte) 0x55, (byte) 0x53, (byte) 0x31, (byte) 0x0b,
+            (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+            (byte) 0x08, (byte) 0x13, (byte) 0x02, (byte) 0x43, (byte) 0x41, (byte) 0x31,
+            (byte) 0x16, (byte) 0x30, (byte) 0x14, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x04, (byte) 0x07, (byte) 0x13, (byte) 0x0d, (byte) 0x4d, (byte) 0x6f,
+            (byte) 0x75, (byte) 0x6e, (byte) 0x74, (byte) 0x61, (byte) 0x69, (byte) 0x6e,
+            (byte) 0x20, (byte) 0x56, (byte) 0x69, (byte) 0x65, (byte) 0x77, (byte) 0x31,
+            (byte) 0x1b, (byte) 0x30, (byte) 0x19, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x04, (byte) 0x0a, (byte) 0x13, (byte) 0x12, (byte) 0x41, (byte) 0x6e,
+            (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64, (byte) 0x20,
+            (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x20, (byte) 0x43,
+            (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x73, (byte) 0x82, (byte) 0x09,
+            (byte) 0x00, (byte) 0xe1, (byte) 0x6a, (byte) 0xa2, (byte) 0xf4, (byte) 0x2e,
+            (byte) 0x55, (byte) 0x48, (byte) 0x0a, (byte) 0x30, (byte) 0x0c, (byte) 0x06,
+            (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x13, (byte) 0x04, (byte) 0x05,
+            (byte) 0x30, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0xff, (byte) 0x30,
+            (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48,
+            (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01, (byte) 0x05,
+            (byte) 0x05, (byte) 0x00, (byte) 0x03, (byte) 0x81, (byte) 0x81, (byte) 0x00,
+            (byte) 0x8c, (byte) 0x30, (byte) 0x42, (byte) 0xfa, (byte) 0xeb, (byte) 0x1a,
+            (byte) 0x26, (byte) 0xeb, (byte) 0xda, (byte) 0x56, (byte) 0x32, (byte) 0xf2,
+            (byte) 0x9d, (byte) 0xa5, (byte) 0x24, (byte) 0xd8, (byte) 0x3a, (byte) 0xda,
+            (byte) 0x30, (byte) 0xa6, (byte) 0x8b, (byte) 0x46, (byte) 0xfe, (byte) 0xfe,
+            (byte) 0xdb, (byte) 0xf1, (byte) 0xe6, (byte) 0xe1, (byte) 0x7c, (byte) 0x1b,
+            (byte) 0xe7, (byte) 0x77, (byte) 0x00, (byte) 0xa1, (byte) 0x1c, (byte) 0x19,
+            (byte) 0x17, (byte) 0x73, (byte) 0xb0, (byte) 0xf0, (byte) 0x9d, (byte) 0xf3,
+            (byte) 0x4f, (byte) 0xb6, (byte) 0xbc, (byte) 0xc7, (byte) 0x47, (byte) 0x85,
+            (byte) 0x2a, (byte) 0x4a, (byte) 0xa1, (byte) 0xa5, (byte) 0x58, (byte) 0xf5,
+            (byte) 0xc5, (byte) 0x1a, (byte) 0x51, (byte) 0xb1, (byte) 0x04, (byte) 0x80,
+            (byte) 0xee, (byte) 0x3a, (byte) 0xec, (byte) 0x2f, (byte) 0xe1, (byte) 0xfd,
+            (byte) 0x58, (byte) 0xeb, (byte) 0xed, (byte) 0x82, (byte) 0x9e, (byte) 0x38,
+            (byte) 0xa3, (byte) 0x24, (byte) 0x75, (byte) 0xf7, (byte) 0x3e, (byte) 0xc2,
+            (byte) 0xc5, (byte) 0x27, (byte) 0xeb, (byte) 0x6f, (byte) 0x7b, (byte) 0x50,
+            (byte) 0xda, (byte) 0x43, (byte) 0xdc, (byte) 0x3b, (byte) 0x0b, (byte) 0x6f,
+            (byte) 0x78, (byte) 0x8f, (byte) 0xb0, (byte) 0x66, (byte) 0xe1, (byte) 0x12,
+            (byte) 0x87, (byte) 0x5f, (byte) 0x97, (byte) 0x7b, (byte) 0xca, (byte) 0x14,
+            (byte) 0x79, (byte) 0xf7, (byte) 0xe8, (byte) 0x6c, (byte) 0x72, (byte) 0xdb,
+            (byte) 0x91, (byte) 0x65, (byte) 0x17, (byte) 0x54, (byte) 0xe0, (byte) 0x74,
+            (byte) 0x1d, (byte) 0xac, (byte) 0x47, (byte) 0x04, (byte) 0x12, (byte) 0xe0,
+            (byte) 0xc3, (byte) 0x66, (byte) 0x19, (byte) 0x05, (byte) 0x2e, (byte) 0x7e,
+            (byte) 0xf1, (byte) 0x61
+        };
+    }
+
+    /*
+     * The keys and certificates below are generated with:
+     *
+     * openssl req -new -x509 -days 3650 -extensions v3_ca -keyout cakey.pem -out cacert.pem
+     * openssl dsaparam -out dsaparam.pem 1024
+     * openssl req -newkey dsa:dsaparam.pem -keyout userkey.pem -nodes -days 3650 -out userkey.req
+     * mkdir -p demoCA/newcerts
+     * touch demoCA/index.txt
+     * echo "01" > demoCA/serial
+     * openssl ca -out usercert.pem -in userkey.req -cert cacert.pem -keyfile cakey.pem -days 3650
+     */
+    public static class FAKE_DSA_1 {
+        /**
+         * Generated from above and converted with: openssl pkcs8 -topk8 -outform d
+         * -in userkey.pem -nocrypt | xxd -i | sed 's/0x/(byte) 0x/g'
+         */
+        public static final byte[] privateKey = {
+            (byte) 0x30, (byte) 0x82, (byte) 0x01, (byte) 0x4c, (byte) 0x02, (byte) 0x01,
+            (byte) 0x00, (byte) 0x30, (byte) 0x82, (byte) 0x01, (byte) 0x2c, (byte) 0x06,
+            (byte) 0x07, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0xce, (byte) 0x38,
+            (byte) 0x04, (byte) 0x01, (byte) 0x30, (byte) 0x82, (byte) 0x01, (byte) 0x1f,
+            (byte) 0x02, (byte) 0x81, (byte) 0x81, (byte) 0x00, (byte) 0xb3, (byte) 0x23,
+            (byte) 0xf7, (byte) 0x86, (byte) 0xbd, (byte) 0x3b, (byte) 0x86, (byte) 0xcc,
+            (byte) 0xc3, (byte) 0x91, (byte) 0xc0, (byte) 0x30, (byte) 0x32, (byte) 0x02,
+            (byte) 0x47, (byte) 0x35, (byte) 0x01, (byte) 0xef, (byte) 0xee, (byte) 0x98,
+            (byte) 0x13, (byte) 0x56, (byte) 0x49, (byte) 0x47, (byte) 0xb5, (byte) 0x20,
+            (byte) 0xa8, (byte) 0x60, (byte) 0xcb, (byte) 0xc0, (byte) 0xd5, (byte) 0x77,
+            (byte) 0xc1, (byte) 0x69, (byte) 0xcd, (byte) 0x18, (byte) 0x34, (byte) 0x92,
+            (byte) 0xf2, (byte) 0x6a, (byte) 0x2a, (byte) 0x10, (byte) 0x59, (byte) 0x1c,
+            (byte) 0x91, (byte) 0x20, (byte) 0x51, (byte) 0xca, (byte) 0x37, (byte) 0xb2,
+            (byte) 0x87, (byte) 0xa6, (byte) 0x8a, (byte) 0x02, (byte) 0xfd, (byte) 0x45,
+            (byte) 0x46, (byte) 0xf9, (byte) 0x76, (byte) 0xb1, (byte) 0x35, (byte) 0x38,
+            (byte) 0x8d, (byte) 0xff, (byte) 0x4c, (byte) 0x5d, (byte) 0x75, (byte) 0x8f,
+            (byte) 0x66, (byte) 0x15, (byte) 0x7d, (byte) 0x7b, (byte) 0xda, (byte) 0xdb,
+            (byte) 0x57, (byte) 0x39, (byte) 0xff, (byte) 0x91, (byte) 0x3f, (byte) 0xdd,
+            (byte) 0xe2, (byte) 0xb4, (byte) 0x22, (byte) 0x60, (byte) 0x4c, (byte) 0x32,
+            (byte) 0x3b, (byte) 0x9d, (byte) 0x34, (byte) 0x9f, (byte) 0xb9, (byte) 0x5d,
+            (byte) 0x75, (byte) 0xb9, (byte) 0xd3, (byte) 0x7f, (byte) 0x11, (byte) 0xba,
+            (byte) 0xb7, (byte) 0xc8, (byte) 0x32, (byte) 0xc6, (byte) 0xce, (byte) 0x71,
+            (byte) 0x91, (byte) 0xd3, (byte) 0x32, (byte) 0xaf, (byte) 0x4d, (byte) 0x7e,
+            (byte) 0x7c, (byte) 0x15, (byte) 0xf7, (byte) 0x71, (byte) 0x2c, (byte) 0x52,
+            (byte) 0x65, (byte) 0x4d, (byte) 0xa9, (byte) 0x81, (byte) 0x25, (byte) 0x35,
+            (byte) 0xce, (byte) 0x0b, (byte) 0x5b, (byte) 0x56, (byte) 0xfe, (byte) 0xf1,
+            (byte) 0x02, (byte) 0x15, (byte) 0x00, (byte) 0xeb, (byte) 0x4e, (byte) 0x7f,
+            (byte) 0x7a, (byte) 0x31, (byte) 0xb3, (byte) 0x7d, (byte) 0x8d, (byte) 0xb2,
+            (byte) 0xf7, (byte) 0xaf, (byte) 0xad, (byte) 0xb1, (byte) 0x42, (byte) 0x92,
+            (byte) 0xf3, (byte) 0x6c, (byte) 0xe4, (byte) 0xed, (byte) 0x8b, (byte) 0x02,
+            (byte) 0x81, (byte) 0x81, (byte) 0x00, (byte) 0x81, (byte) 0xc8, (byte) 0x36,
+            (byte) 0x48, (byte) 0xdb, (byte) 0x71, (byte) 0x2b, (byte) 0x91, (byte) 0xce,
+            (byte) 0x6d, (byte) 0xbc, (byte) 0xb8, (byte) 0xf9, (byte) 0xcb, (byte) 0x50,
+            (byte) 0x91, (byte) 0x10, (byte) 0x8a, (byte) 0xf8, (byte) 0x37, (byte) 0x50,
+            (byte) 0xda, (byte) 0x4f, (byte) 0xc8, (byte) 0x4d, (byte) 0x73, (byte) 0xcb,
+            (byte) 0x4d, (byte) 0xb0, (byte) 0x19, (byte) 0x54, (byte) 0x5a, (byte) 0xf3,
+            (byte) 0x6c, (byte) 0xc9, (byte) 0xd8, (byte) 0x96, (byte) 0xd9, (byte) 0xb0,
+            (byte) 0x54, (byte) 0x7e, (byte) 0x7d, (byte) 0xe2, (byte) 0x58, (byte) 0x0e,
+            (byte) 0x5f, (byte) 0xc0, (byte) 0xce, (byte) 0xb9, (byte) 0x5c, (byte) 0xe3,
+            (byte) 0xd3, (byte) 0xdf, (byte) 0xcf, (byte) 0x45, (byte) 0x74, (byte) 0xfb,
+            (byte) 0xe6, (byte) 0x20, (byte) 0xe7, (byte) 0xfc, (byte) 0x0f, (byte) 0xca,
+            (byte) 0xdb, (byte) 0xc0, (byte) 0x0b, (byte) 0xe1, (byte) 0x5a, (byte) 0x16,
+            (byte) 0x1d, (byte) 0xb3, (byte) 0x2e, (byte) 0xe5, (byte) 0x5f, (byte) 0x89,
+            (byte) 0x17, (byte) 0x73, (byte) 0x50, (byte) 0xd1, (byte) 0x4a, (byte) 0x60,
+            (byte) 0xb7, (byte) 0xaa, (byte) 0xf0, (byte) 0xc7, (byte) 0xc5, (byte) 0x03,
+            (byte) 0x4e, (byte) 0x36, (byte) 0x51, (byte) 0x9e, (byte) 0x2f, (byte) 0xfa,
+            (byte) 0xf3, (byte) 0xd6, (byte) 0x58, (byte) 0x14, (byte) 0x02, (byte) 0xb4,
+            (byte) 0x41, (byte) 0xd6, (byte) 0x72, (byte) 0x6f, (byte) 0x58, (byte) 0x5b,
+            (byte) 0x2d, (byte) 0x23, (byte) 0xc0, (byte) 0x75, (byte) 0x4f, (byte) 0x39,
+            (byte) 0xa8, (byte) 0x6a, (byte) 0xdf, (byte) 0x79, (byte) 0x21, (byte) 0xf2,
+            (byte) 0x77, (byte) 0x91, (byte) 0x3f, (byte) 0x1c, (byte) 0x4d, (byte) 0x48,
+            (byte) 0x78, (byte) 0xcd, (byte) 0xed, (byte) 0x79, (byte) 0x23, (byte) 0x04,
+            (byte) 0x17, (byte) 0x02, (byte) 0x15, (byte) 0x00, (byte) 0xc7, (byte) 0xe7,
+            (byte) 0xe2, (byte) 0x6b, (byte) 0x14, (byte) 0xe6, (byte) 0x31, (byte) 0x12,
+            (byte) 0xb2, (byte) 0x1e, (byte) 0xd4, (byte) 0xf2, (byte) 0x9b, (byte) 0x2c,
+            (byte) 0xf6, (byte) 0x54, (byte) 0x4c, (byte) 0x12, (byte) 0xe8, (byte) 0x22
+
+        };
+
+        /**
+         * Generated from above and converted with:
+         *
+         * openssl x509 -outform d -in cacert.pem | xxd -i | sed 's/0x/(byte) 0x/g'
+         */
+        public static final byte[] caCertificate = new byte[] {
+            (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x8a, (byte) 0x30, (byte) 0x82,
+            (byte) 0x01, (byte) 0xf3, (byte) 0xa0, (byte) 0x03, (byte) 0x02, (byte) 0x01,
+            (byte) 0x02, (byte) 0x02, (byte) 0x09, (byte) 0x00, (byte) 0x87, (byte) 0xc0,
+            (byte) 0x68, (byte) 0x7f, (byte) 0x42, (byte) 0x92, (byte) 0x0b, (byte) 0x7a,
+            (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86,
+            (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01,
+            (byte) 0x05, (byte) 0x05, (byte) 0x00, (byte) 0x30, (byte) 0x5e, (byte) 0x31,
+            (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x04, (byte) 0x06, (byte) 0x13, (byte) 0x02, (byte) 0x41, (byte) 0x55,
+            (byte) 0x31, (byte) 0x13, (byte) 0x30, (byte) 0x11, (byte) 0x06, (byte) 0x03,
+            (byte) 0x55, (byte) 0x04, (byte) 0x08, (byte) 0x0c, (byte) 0x0a, (byte) 0x53,
+            (byte) 0x6f, (byte) 0x6d, (byte) 0x65, (byte) 0x2d, (byte) 0x53, (byte) 0x74,
+            (byte) 0x61, (byte) 0x74, (byte) 0x65, (byte) 0x31, (byte) 0x21, (byte) 0x30,
+            (byte) 0x1f, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x0a,
+            (byte) 0x0c, (byte) 0x18, (byte) 0x49, (byte) 0x6e, (byte) 0x74, (byte) 0x65,
+            (byte) 0x72, (byte) 0x6e, (byte) 0x65, (byte) 0x74, (byte) 0x20, (byte) 0x57,
+            (byte) 0x69, (byte) 0x64, (byte) 0x67, (byte) 0x69, (byte) 0x74, (byte) 0x73,
+            (byte) 0x20, (byte) 0x50, (byte) 0x74, (byte) 0x79, (byte) 0x20, (byte) 0x4c,
+            (byte) 0x74, (byte) 0x64, (byte) 0x31, (byte) 0x17, (byte) 0x30, (byte) 0x15,
+            (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x03, (byte) 0x0c,
+            (byte) 0x0e, (byte) 0x63, (byte) 0x61, (byte) 0x2e, (byte) 0x65, (byte) 0x78,
+            (byte) 0x61, (byte) 0x6d, (byte) 0x70, (byte) 0x6c, (byte) 0x65, (byte) 0x2e,
+            (byte) 0x63, (byte) 0x6f, (byte) 0x6d, (byte) 0x30, (byte) 0x1e, (byte) 0x17,
+            (byte) 0x0d, (byte) 0x31, (byte) 0x33, (byte) 0x30, (byte) 0x38, (byte) 0x32,
+            (byte) 0x37, (byte) 0x32, (byte) 0x33, (byte) 0x33, (byte) 0x31, (byte) 0x32,
+            (byte) 0x39, (byte) 0x5a, (byte) 0x17, (byte) 0x0d, (byte) 0x32, (byte) 0x33,
+            (byte) 0x30, (byte) 0x38, (byte) 0x32, (byte) 0x35, (byte) 0x32, (byte) 0x33,
+            (byte) 0x33, (byte) 0x31, (byte) 0x32, (byte) 0x39, (byte) 0x5a, (byte) 0x30,
+            (byte) 0x5e, (byte) 0x31, (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06,
+            (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x06, (byte) 0x13, (byte) 0x02,
+            (byte) 0x41, (byte) 0x55, (byte) 0x31, (byte) 0x13, (byte) 0x30, (byte) 0x11,
+            (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x08, (byte) 0x0c,
+            (byte) 0x0a, (byte) 0x53, (byte) 0x6f, (byte) 0x6d, (byte) 0x65, (byte) 0x2d,
+            (byte) 0x53, (byte) 0x74, (byte) 0x61, (byte) 0x74, (byte) 0x65, (byte) 0x31,
+            (byte) 0x21, (byte) 0x30, (byte) 0x1f, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x04, (byte) 0x0a, (byte) 0x0c, (byte) 0x18, (byte) 0x49, (byte) 0x6e,
+            (byte) 0x74, (byte) 0x65, (byte) 0x72, (byte) 0x6e, (byte) 0x65, (byte) 0x74,
+            (byte) 0x20, (byte) 0x57, (byte) 0x69, (byte) 0x64, (byte) 0x67, (byte) 0x69,
+            (byte) 0x74, (byte) 0x73, (byte) 0x20, (byte) 0x50, (byte) 0x74, (byte) 0x79,
+            (byte) 0x20, (byte) 0x4c, (byte) 0x74, (byte) 0x64, (byte) 0x31, (byte) 0x17,
+            (byte) 0x30, (byte) 0x15, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+            (byte) 0x03, (byte) 0x0c, (byte) 0x0e, (byte) 0x63, (byte) 0x61, (byte) 0x2e,
+            (byte) 0x65, (byte) 0x78, (byte) 0x61, (byte) 0x6d, (byte) 0x70, (byte) 0x6c,
+            (byte) 0x65, (byte) 0x2e, (byte) 0x63, (byte) 0x6f, (byte) 0x6d, (byte) 0x30,
+            (byte) 0x81, (byte) 0x9f, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09,
+            (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d,
+            (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x03,
+            (byte) 0x81, (byte) 0x8d, (byte) 0x00, (byte) 0x30, (byte) 0x81, (byte) 0x89,
+            (byte) 0x02, (byte) 0x81, (byte) 0x81, (byte) 0x00, (byte) 0xa4, (byte) 0xc7,
+            (byte) 0x06, (byte) 0xba, (byte) 0xdf, (byte) 0x2b, (byte) 0xee, (byte) 0xd2,
+            (byte) 0xb9, (byte) 0xe4, (byte) 0x52, (byte) 0x21, (byte) 0x68, (byte) 0x2b,
+            (byte) 0x83, (byte) 0xdf, (byte) 0xe3, (byte) 0x9c, (byte) 0x08, (byte) 0x73,
+            (byte) 0xdd, (byte) 0x90, (byte) 0xea, (byte) 0x97, (byte) 0x0c, (byte) 0x96,
+            (byte) 0x20, (byte) 0xb1, (byte) 0xee, (byte) 0x11, (byte) 0xd5, (byte) 0xd4,
+            (byte) 0x7c, (byte) 0x44, (byte) 0x96, (byte) 0x2e, (byte) 0x6e, (byte) 0xa2,
+            (byte) 0xb2, (byte) 0xa3, (byte) 0x4b, (byte) 0x0f, (byte) 0x32, (byte) 0x90,
+            (byte) 0xaf, (byte) 0x5c, (byte) 0x6f, (byte) 0x00, (byte) 0x88, (byte) 0x45,
+            (byte) 0x4e, (byte) 0x9b, (byte) 0x26, (byte) 0xc1, (byte) 0x94, (byte) 0x3c,
+            (byte) 0xfe, (byte) 0x10, (byte) 0xbd, (byte) 0xda, (byte) 0xf2, (byte) 0x8d,
+            (byte) 0x03, (byte) 0x52, (byte) 0x32, (byte) 0x11, (byte) 0xff, (byte) 0xf6,
+            (byte) 0xf9, (byte) 0x6e, (byte) 0x8f, (byte) 0x0f, (byte) 0xc8, (byte) 0x0a,
+            (byte) 0x48, (byte) 0x39, (byte) 0x33, (byte) 0xb9, (byte) 0x0c, (byte) 0xb3,
+            (byte) 0x2b, (byte) 0xab, (byte) 0x7d, (byte) 0x79, (byte) 0x6f, (byte) 0x57,
+            (byte) 0x5b, (byte) 0xb8, (byte) 0x84, (byte) 0xb6, (byte) 0xcc, (byte) 0xe8,
+            (byte) 0x30, (byte) 0x78, (byte) 0xff, (byte) 0x92, (byte) 0xe5, (byte) 0x43,
+            (byte) 0x2e, (byte) 0xef, (byte) 0x66, (byte) 0x98, (byte) 0xb4, (byte) 0xfe,
+            (byte) 0xa2, (byte) 0x40, (byte) 0xf2, (byte) 0x1f, (byte) 0xd0, (byte) 0x86,
+            (byte) 0x16, (byte) 0xc8, (byte) 0x45, (byte) 0xc4, (byte) 0x52, (byte) 0xcb,
+            (byte) 0x31, (byte) 0x5c, (byte) 0x9f, (byte) 0x32, (byte) 0x3b, (byte) 0xf7,
+            (byte) 0x19, (byte) 0x08, (byte) 0xc7, (byte) 0x00, (byte) 0x21, (byte) 0x7d,
+            (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0xa3,
+            (byte) 0x50, (byte) 0x30, (byte) 0x4e, (byte) 0x30, (byte) 0x1d, (byte) 0x06,
+            (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x0e, (byte) 0x04, (byte) 0x16,
+            (byte) 0x04, (byte) 0x14, (byte) 0x47, (byte) 0x82, (byte) 0xa3, (byte) 0xf1,
+            (byte) 0xc2, (byte) 0x7e, (byte) 0x3a, (byte) 0xde, (byte) 0x4f, (byte) 0x30,
+            (byte) 0x4c, (byte) 0x7f, (byte) 0x72, (byte) 0x81, (byte) 0x15, (byte) 0x32,
+            (byte) 0xda, (byte) 0x7f, (byte) 0x58, (byte) 0x18, (byte) 0x30, (byte) 0x1f,
+            (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x23, (byte) 0x04,
+            (byte) 0x18, (byte) 0x30, (byte) 0x16, (byte) 0x80, (byte) 0x14, (byte) 0x47,
+            (byte) 0x82, (byte) 0xa3, (byte) 0xf1, (byte) 0xc2, (byte) 0x7e, (byte) 0x3a,
+            (byte) 0xde, (byte) 0x4f, (byte) 0x30, (byte) 0x4c, (byte) 0x7f, (byte) 0x72,
+            (byte) 0x81, (byte) 0x15, (byte) 0x32, (byte) 0xda, (byte) 0x7f, (byte) 0x58,
+            (byte) 0x18, (byte) 0x30, (byte) 0x0c, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x1d, (byte) 0x13, (byte) 0x04, (byte) 0x05, (byte) 0x30, (byte) 0x03,
+            (byte) 0x01, (byte) 0x01, (byte) 0xff, (byte) 0x30, (byte) 0x0d, (byte) 0x06,
+            (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7,
+            (byte) 0x0d, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x05, (byte) 0x00,
+            (byte) 0x03, (byte) 0x81, (byte) 0x81, (byte) 0x00, (byte) 0x08, (byte) 0x7f,
+            (byte) 0x6a, (byte) 0x48, (byte) 0x90, (byte) 0x7b, (byte) 0x9b, (byte) 0x72,
+            (byte) 0x13, (byte) 0xa7, (byte) 0xef, (byte) 0x6b, (byte) 0x0b, (byte) 0x59,
+            (byte) 0xe5, (byte) 0x49, (byte) 0x72, (byte) 0x3a, (byte) 0xc8, (byte) 0x84,
+            (byte) 0xcc, (byte) 0x23, (byte) 0x18, (byte) 0x4c, (byte) 0xec, (byte) 0xc7,
+            (byte) 0xef, (byte) 0xcb, (byte) 0xa7, (byte) 0xbe, (byte) 0xe4, (byte) 0xef,
+            (byte) 0x8f, (byte) 0xc6, (byte) 0x06, (byte) 0x8c, (byte) 0xc0, (byte) 0xe4,
+            (byte) 0x2f, (byte) 0x2a, (byte) 0xc0, (byte) 0x35, (byte) 0x7d, (byte) 0x5e,
+            (byte) 0x19, (byte) 0x29, (byte) 0x8c, (byte) 0xb9, (byte) 0xf1, (byte) 0x1e,
+            (byte) 0xaf, (byte) 0x82, (byte) 0xd8, (byte) 0xe3, (byte) 0x88, (byte) 0xe1,
+            (byte) 0x31, (byte) 0xc8, (byte) 0x82, (byte) 0x1f, (byte) 0x83, (byte) 0xa9,
+            (byte) 0xde, (byte) 0xfe, (byte) 0x4b, (byte) 0xe2, (byte) 0x78, (byte) 0x64,
+            (byte) 0xed, (byte) 0xa4, (byte) 0x7b, (byte) 0xee, (byte) 0x8d, (byte) 0x71,
+            (byte) 0x1b, (byte) 0x44, (byte) 0xe6, (byte) 0xb7, (byte) 0xe8, (byte) 0xc5,
+            (byte) 0x9a, (byte) 0x93, (byte) 0x92, (byte) 0x6f, (byte) 0x6f, (byte) 0xdb,
+            (byte) 0xbd, (byte) 0xd7, (byte) 0x03, (byte) 0x85, (byte) 0xa9, (byte) 0x5f,
+            (byte) 0x53, (byte) 0x5f, (byte) 0x5d, (byte) 0x30, (byte) 0xc6, (byte) 0xd9,
+            (byte) 0xce, (byte) 0x34, (byte) 0xa8, (byte) 0xbe, (byte) 0x31, (byte) 0x47,
+            (byte) 0x1c, (byte) 0xa4, (byte) 0x7f, (byte) 0xc0, (byte) 0x2c, (byte) 0xbc,
+            (byte) 0xfe, (byte) 0x1a, (byte) 0x31, (byte) 0xd8, (byte) 0x77, (byte) 0x4d,
+            (byte) 0xfc, (byte) 0x45, (byte) 0x84, (byte) 0xfc, (byte) 0x45, (byte) 0x12,
+            (byte) 0xab, (byte) 0x50, (byte) 0xe4, (byte) 0x45, (byte) 0xe5, (byte) 0x11
+        };
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/KeyManagementTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/KeyManagementTest.java
new file mode 100644
index 0000000..fe2bdda
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/KeyManagementTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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 com.android.cts.deviceowner;
+
+import static com.android.cts.deviceowner.FakeKeys.FAKE_RSA_1;
+
+import android.app.admin.DevicePolicyManager;
+
+import java.io.ByteArrayInputStream;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.Certificate;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+
+public class KeyManagementTest extends BaseDeviceOwnerTest {
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        assertTrue(mDevicePolicyManager.resetPassword("test", 0));
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mDevicePolicyManager.setPasswordQuality(getWho(),
+                DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
+        mDevicePolicyManager.setPasswordMinimumLength(getWho(), 0);
+        assertTrue(mDevicePolicyManager.resetPassword("", 0));
+        super.tearDown();
+    }
+
+    public void testCanInstallValidRsaKeypair()
+            throws CertificateException, NoSuchAlgorithmException, InvalidKeySpecException {
+        final String alias = "com.android.test.valid-rsa-key-1";
+        final PrivateKey privKey = getPrivateKey(FAKE_RSA_1.privateKey , "RSA");
+        final Certificate cert = getCertificate(FAKE_RSA_1.caCertificate);
+        assertTrue(mDevicePolicyManager.installKeyPair(getWho(), privKey, cert, alias));
+    }
+
+    public void testNullKeyParamsFailGracefully()
+            throws CertificateException, NoSuchAlgorithmException, InvalidKeySpecException {
+        final String alias = "com.android.test.null-key-1";
+        final PrivateKey privKey = getPrivateKey(FAKE_RSA_1.privateKey, "RSA");
+        final Certificate cert = getCertificate(FAKE_RSA_1.caCertificate);
+        try {
+            assertFalse(mDevicePolicyManager.installKeyPair(getWho(), null, cert, alias));
+        } catch (NullPointerException accept) {
+            // Accept either false return value or NPE
+        }
+        try {
+            assertFalse(mDevicePolicyManager.installKeyPair(getWho(), privKey, null, alias));
+        } catch (NullPointerException accept) {
+            // Accept either false return value or NPE
+        }
+    }
+
+    public void testNullAdminComponentIsDenied()
+            throws CertificateException, NoSuchAlgorithmException, InvalidKeySpecException {
+        final String alias = "com.android.test.null-admin-1";
+        final PrivateKey privKey = getPrivateKey(FAKE_RSA_1.privateKey, "RSA");
+        final Certificate cert = getCertificate(FAKE_RSA_1.caCertificate);
+        try {
+            assertFalse(mDevicePolicyManager.installKeyPair(null, privKey, cert, alias));
+            fail("Exception should have been thrown for null ComponentName");
+        } catch (SecurityException | NullPointerException expected) {
+        }
+    }
+
+    PrivateKey getPrivateKey(final byte[] key, String type)
+            throws NoSuchAlgorithmException, InvalidKeySpecException {
+        return KeyFactory.getInstance(type).generatePrivate(
+                new PKCS8EncodedKeySpec(key));
+    }
+
+    Certificate getCertificate(byte[] cert) throws CertificateException {
+        return CertificateFactory.getInstance("X.509").generateCertificate(
+                new ByteArrayInputStream(cert));
+    }
+
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/LockTaskTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/LockTaskTest.java
new file mode 100644
index 0000000..42aa847
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/LockTaskTest.java
@@ -0,0 +1,293 @@
+/*
+ * 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 com.android.cts.deviceowner;
+
+import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.provider.Settings;
+
+// This is not a standard test of an android activity (such as
+// ActivityInstrumentationTestCase2) as it is attempting to test the actual
+// life cycle and how it is affected by lock task, rather than mock intents
+// and setup.
+public class LockTaskTest extends BaseDeviceOwnerTest {
+
+    private static final String TEST_PACKAGE = "com.google.android.example.somepackage";
+
+    private static final int ACTIVITY_RESUMED_TIMEOUT_MILLIS = 60000;  // 60 seconds
+    private static final int ACTIVITY_RUNNING_TIMEOUT_MILLIS = 20000;  // 20 seconds
+
+    /**
+     * The tests below need to keep detailed track of the state of the activity
+     * that is started and stopped frequently.  To do this it sends a number of
+     * broadcasts that are caught here and translated into booleans (as well as
+     * notify some locks in case we are waiting).  There is also an action used
+     * to specify that the activity has finished handling the current command
+     * (INTENT_ACTION).
+     */
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (LockTaskUtilityActivity.CREATE_ACTION.equals(action)) {
+                synchronized (mActivityRunningLock) {
+                    mIsActivityRunning = true;
+                    mActivityRunningLock.notify();
+                }
+            } else if (LockTaskUtilityActivity.DESTROY_ACTION.equals(action)) {
+                synchronized (mActivityRunningLock) {
+                    mIsActivityRunning = false;
+                    mActivityRunningLock.notify();
+                }
+            } else if (LockTaskUtilityActivity.RESUME_ACTION.equals(action)) {
+                synchronized (mActivityResumedLock) {
+                    mIsActivityResumed = true;
+                    mActivityResumedLock.notify();
+                }
+            } else if (LockTaskUtilityActivity.PAUSE_ACTION.equals(action)) {
+                synchronized (mActivityResumedLock) {
+                    mIsActivityResumed = false;
+                    mActivityResumedLock.notify();
+                }
+            } else if (LockTaskUtilityActivity.INTENT_ACTION.equals(action)) {
+                // Notify that intent has been handled.
+                synchronized (LockTaskTest.this) {
+                    mIntentHandled = true;
+                    LockTaskTest.this.notify();
+                }
+            }
+        }
+    };
+
+    private boolean mIsActivityRunning;
+    private boolean mIsActivityResumed;
+    private final Object mActivityRunningLock = new Object();
+    private final Object mActivityResumedLock = new Object();
+    private Boolean mIntentHandled;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(LockTaskUtilityActivity.CREATE_ACTION);
+        filter.addAction(LockTaskUtilityActivity.DESTROY_ACTION);
+        filter.addAction(LockTaskUtilityActivity.INTENT_ACTION);
+        filter.addAction(LockTaskUtilityActivity.RESUME_ACTION);
+        filter.addAction(LockTaskUtilityActivity.PAUSE_ACTION);
+        mContext.registerReceiver(mReceiver, filter);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mContext.unregisterReceiver(mReceiver);
+        super.tearDown();
+    }
+
+    public void testSetLockTaskPackages() {
+        mDevicePolicyManager.setLockTaskPackages(getWho(), new String[] { TEST_PACKAGE });
+        assertTrue(mDevicePolicyManager.isLockTaskPermitted(TEST_PACKAGE));
+
+        mDevicePolicyManager.setLockTaskPackages(getWho(), new String[0]);
+        assertFalse(mDevicePolicyManager.isLockTaskPermitted(TEST_PACKAGE));
+    }
+
+    // Start lock task, verify that ActivityManager knows thats what is going on.
+    public void testStartLockTask() {
+        mDevicePolicyManager.setLockTaskPackages(getWho(), new String[] { PACKAGE_NAME });
+        startLockTask();
+        waitForResume();
+
+        // Verify that activity open and activity manager is in lock task.
+        ActivityManager activityManager = (ActivityManager)
+                mContext.getSystemService(Context.ACTIVITY_SERVICE);
+        assertTrue(activityManager.isInLockTaskMode());
+        assertTrue(mIsActivityRunning);
+        assertTrue(mIsActivityResumed);
+
+        stopAndFinish(activityManager);
+    }
+
+    // Verifies that the act of finishing is blocked by ActivityManager in lock task.
+    // This results in onDestroy not being called until stopLockTask is called before finish.
+    public void testCannotFinish() {
+        mDevicePolicyManager.setLockTaskPackages(getWho(), new String[] { PACKAGE_NAME });
+        startLockTask();
+
+        // If lock task has not exited then the activity shouldn't actually receive onDestroy.
+        finishAndWait();
+        ActivityManager activityManager = (ActivityManager)
+                mContext.getSystemService(Context.ACTIVITY_SERVICE);
+        assertTrue(activityManager.isInLockTaskMode());
+        assertTrue(mIsActivityRunning);
+
+        stopAndFinish(activityManager);
+    }
+
+    // This test has the UtilityActivity trigger starting another activity (settings)
+    // this should be permitted as a part of lock task (since it isn't a new task).
+    // As a result onPause should be called as it goes to a new activity.
+    public void testStartActivityWithinTask() {
+        mDevicePolicyManager.setLockTaskPackages(getWho(), new String[] { PACKAGE_NAME });
+        startLockTask();
+        waitForResume();
+
+        Intent launchIntent = new Intent(Settings.ACTION_SETTINGS);
+        Intent lockTaskUtility = getLockTaskUtility();
+        lockTaskUtility.putExtra(LockTaskUtilityActivity.START_ACTIVITY, launchIntent);
+        mContext.startActivity(lockTaskUtility);
+
+        synchronized (mActivityResumedLock) {
+            if (mIsActivityResumed) {
+                try {
+                    mActivityResumedLock.wait(ACTIVITY_RESUMED_TIMEOUT_MILLIS);
+                } catch (InterruptedException e) {
+                }
+                assertFalse(mIsActivityResumed);
+            }
+        }
+        stopAndFinish(null);
+    }
+
+    // This launches an activity that is not part of the current task and therefore
+    // should be blocked.  This is verified by making sure that the activity does
+    // not get a call to onPause.
+    public void testCannotStartActivityOutsideTask() {
+        mDevicePolicyManager.setLockTaskPackages(getWho(), new String[] { PACKAGE_NAME });
+        startLockTask();
+        waitForResume();
+
+        Intent launchIntent = new Intent(Settings.ACTION_SETTINGS);
+        launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mContext.startActivity(launchIntent);
+
+        synchronized (mActivityResumedLock) {
+            try {
+                mActivityResumedLock.wait(ACTIVITY_RESUMED_TIMEOUT_MILLIS);
+            } catch (InterruptedException e) {
+            }
+            assertTrue(mIsActivityResumed);
+        }
+        stopAndFinish(null);
+    }
+
+    /**
+     * Call stopLockTask and finish on the LockTaskUtilityActivity.
+     *
+     * Verify that the activity is no longer running.
+     *
+     * If activityManager is not null then verify that the ActivityManager
+     * is no longer in lock task mode.
+     */
+    private void stopAndFinish(ActivityManager activityManager) {
+        stopLockTask();
+        finishAndWait();
+        if (activityManager != null) {
+            assertFalse(activityManager.isInLockTaskMode());
+        }
+        assertFalse(mIsActivityRunning);
+    }
+
+    /**
+     * Call finish on the LockTaskUtilityActivity and wait for
+     * onDestroy to be called.
+     */
+    private void finishAndWait() {
+        synchronized (mActivityRunningLock) {
+            finish();
+            if (mIsActivityRunning) {
+                try {
+                    mActivityRunningLock.wait(ACTIVITY_RUNNING_TIMEOUT_MILLIS);
+                } catch (InterruptedException e) {
+                }
+            }
+        }
+    }
+
+    /**
+     * Wait for onPause to be called on the LockTaskUtilityActivity.
+     */
+    private void waitForResume() {
+        // It may take a moment for the resume to come in.
+        synchronized (mActivityResumedLock) {
+            if (!mIsActivityResumed) {
+                try {
+                    mActivityResumedLock.wait(ACTIVITY_RESUMED_TIMEOUT_MILLIS);
+                } catch (InterruptedException e) {
+                }
+            }
+        }
+    }
+
+    /**
+     * Calls startLockTask on the LockTaskUtilityActivity
+     */
+    private void startLockTask() {
+        Intent intent = getLockTaskUtility();
+        intent.putExtra(LockTaskUtilityActivity.START_LOCK_TASK, true);
+        startAndWait(intent);
+    }
+
+    /**
+     * Calls stopLockTask on the LockTaskUtilityActivity
+     */
+    private void stopLockTask() {
+        Intent intent = getLockTaskUtility();
+        intent.putExtra(LockTaskUtilityActivity.STOP_LOCK_TASK, true);
+        startAndWait(intent);
+    }
+
+    /**
+     * Calls finish on the LockTaskUtilityActivity
+     */
+    private void finish() {
+        Intent intent = getLockTaskUtility();
+        intent.putExtra(LockTaskUtilityActivity.FINISH, true);
+        startAndWait(intent);
+    }
+
+    /**
+     * Sends a command intent to the LockTaskUtilityActivity and waits
+     * to receive the broadcast back confirming it has finished processing
+     * the command.
+     */
+    private void startAndWait(Intent intent) {
+        mIntentHandled = false;
+        synchronized (this) {
+            mContext.startActivity(intent);
+            // Give 20 secs to finish.
+            try {
+                wait(ACTIVITY_RUNNING_TIMEOUT_MILLIS);
+            } catch (InterruptedException e) {
+            }
+            assertTrue(mIntentHandled);
+        }
+    }
+
+    /**
+     * Get basic intent that points at the LockTaskUtilityActivity.
+     *
+     * This intent includes the flags to make it act as single top.
+     */
+    private Intent getLockTaskUtility() {
+        Intent intent = new Intent();
+        intent.setClassName(PACKAGE_NAME, LockTaskUtilityActivity.class.getName());
+        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
+        return intent;
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/LockTaskUtilityActivity.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/LockTaskUtilityActivity.java
new file mode 100644
index 0000000..2901f5b
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/LockTaskUtilityActivity.java
@@ -0,0 +1,83 @@
+/*
+ * 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 com.android.cts.deviceowner;
+
+import android.app.Activity;
+import android.content.Intent;
+
+public class LockTaskUtilityActivity extends Activity {
+
+    public static final String START_LOCK_TASK = "startLockTask";
+    public static final String STOP_LOCK_TASK = "stopLockTask";
+    public static final String START_ACTIVITY = "startActivity";
+    public static final String FINISH = "finish";
+
+    public static final String CREATE_ACTION = "com.android.cts.deviceowner.LOCK_TASK_CREATE";
+    public static final String DESTROY_ACTION = "com.android.cts.deviceowner.LOCK_TASK_DESTROY";
+    public static final String PAUSE_ACTION = "com.android.cts.deviceowner.LOCK_TASK_PAUSE";
+    public static final String RESUME_ACTION = "com.android.cts.deviceowner.LOCK_TASK_RESUME";
+    public static final String INTENT_ACTION = "com.android.cts.deviceowner.LOCK_TASK_INTENT";
+
+    @Override
+    protected void onNewIntent(Intent intent) {
+        super.onNewIntent(intent);
+        handleIntent(intent);
+    }
+
+    @Override
+    protected void onCreate(android.os.Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        sendBroadcast(new Intent(CREATE_ACTION));
+        handleIntent(getIntent());
+    }
+
+    @Override
+    protected void onDestroy() {
+        sendBroadcast(new Intent(DESTROY_ACTION));
+        super.onDestroy();
+    }
+
+    @Override
+    protected void onResume() {
+        sendBroadcast(new Intent(RESUME_ACTION));
+        super.onResume();
+    }
+
+    @Override
+    protected void onPause() {
+        sendBroadcast(new Intent(PAUSE_ACTION));
+        super.onPause();
+    }
+
+    private void handleIntent(Intent intent) {
+        if (intent.getBooleanExtra(START_LOCK_TASK, false)) {
+            startLockTask();
+        }
+        if (intent.getBooleanExtra(STOP_LOCK_TASK, false)) {
+            stopLockTask();
+        }
+        if (intent.hasExtra(START_ACTIVITY)) {
+            Intent i = intent.getParcelableExtra(START_ACTIVITY);
+            startActivity(i);
+        }
+        if (intent.getBooleanExtra(FINISH, false)) {
+            finish();
+        }
+        sendBroadcast(new Intent(INTENT_ACTION));
+    }
+
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/PersistentIntentResolvingTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/PersistentIntentResolvingTest.java
new file mode 100644
index 0000000..fcef05f
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/PersistentIntentResolvingTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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 com.android.cts.deviceowner;
+
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.SystemClock;
+
+public class PersistentIntentResolvingTest extends BaseDeviceOwnerTest {
+    public static final String EXAMPLE_ACTION = "com.android.cts.deviceowner.EXAMPLE_ACTION";
+
+    private boolean mReceivedConfirmationFrom1;
+    private boolean mReceivedConfirmationFrom2;
+    private BroadcastReceiver mReceiver;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(ExampleIntentReceivingActivity1.CONFIRM_ACTION);
+        filter.addAction(ExampleIntentReceivingActivity2.CONFIRM_ACTION);
+
+        mReceiver = new ConfirmReceiver();
+        mContext.registerReceiver(mReceiver, filter);
+
+        synchronized(this) {
+            mReceivedConfirmationFrom1 = false;
+            mReceivedConfirmationFrom2 = false;
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mDevicePolicyManager.clearPackagePersistentPreferredActivities(getWho(), PACKAGE_NAME);
+        mContext.unregisterReceiver(mReceiver);
+
+        super.tearDown();
+    }
+
+    public void testNoPersistentPreferredActivityYieldsResolverActivity() {
+        sendExampleIntent();
+        SystemClock.sleep(5000);
+
+        // Default behavior: intent results in resolver activity, since there are two potential
+        // receivers. No intent is received.
+        synchronized(this) {
+            assertFalse(mReceivedConfirmationFrom1);
+            assertFalse(mReceivedConfirmationFrom2);
+        }
+    }
+
+    public void testAddPersistentPreferredActivityYieldsReceptionAtTarget() {
+        addPersistentPreferredActivity();
+        sendExampleIntent();
+        SystemClock.sleep(5000);
+
+        // Persistent preferred activity present: intent should be received by activity 2.
+        synchronized(this) {
+            assertFalse(mReceivedConfirmationFrom1);
+            assertTrue(mReceivedConfirmationFrom2);
+        }
+    }
+
+    public void testAddAndClearPersistentPreferredActivitiesYieldsResolverActivity() {
+        addPersistentPreferredActivity();
+        mDevicePolicyManager.clearPackagePersistentPreferredActivities(getWho(), PACKAGE_NAME);
+
+        sendExampleIntent();
+        SystemClock.sleep(5000);
+
+        // Default behavior: intent results in resolver activity, since there are two potential
+        // receivers. No intent is received.
+        synchronized(this) {
+            assertFalse(mReceivedConfirmationFrom1);
+            assertFalse(mReceivedConfirmationFrom2);
+        }
+    }
+
+    public class ConfirmReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent.getAction().equals(ExampleIntentReceivingActivity1.CONFIRM_ACTION)) {
+                synchronized (PersistentIntentResolvingTest.this) {
+                    mReceivedConfirmationFrom1 = true;
+                }
+            } else if (intent.getAction().equals(ExampleIntentReceivingActivity2
+                            .CONFIRM_ACTION)) {
+                synchronized (PersistentIntentResolvingTest.this) {
+                    mReceivedConfirmationFrom2 = true;
+                }
+            }
+        }
+    }
+
+    private void sendExampleIntent() {
+        Intent exampleIntent = new Intent(EXAMPLE_ACTION);
+        exampleIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mContext.startActivity(exampleIntent);
+    }
+
+    private void addPersistentPreferredActivity() {
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(EXAMPLE_ACTION);
+        filter.addCategory(Intent.CATEGORY_DEFAULT);
+        ComponentName targetComponent = new ComponentName(PACKAGE_NAME,
+                ExampleIntentReceivingActivity2.class.getName());
+        mDevicePolicyManager.addPersistentPreferredActivity(getWho(), filter, targetComponent);
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/ScreenCaptureDisabledTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/ScreenCaptureDisabledTest.java
new file mode 100644
index 0000000..59b9773
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/ScreenCaptureDisabledTest.java
@@ -0,0 +1,45 @@
+/*
+ * 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 com.android.cts.deviceowner;
+
+import android.app.admin.DevicePolicyManager;
+
+/**
+ * Tests for {@link DevicePolicyManager#setScreenCaptureDisabled} and
+ * {@link DevicePolicyManager#getScreenCaptureDisabled} APIs.
+ */
+public class ScreenCaptureDisabledTest extends BaseDeviceOwnerTest {
+
+    public void testSetScreenCaptureDisabled_false() throws Exception {
+        mDevicePolicyManager.setScreenCaptureDisabled(getWho(), false);
+        assertFalse(mDevicePolicyManager.getScreenCaptureDisabled(getWho()));
+    }
+
+    public void testSetScreenCaptureDisabled_true() throws Exception {
+        mDevicePolicyManager.setScreenCaptureDisabled(getWho(), true);
+        assertTrue(mDevicePolicyManager.getScreenCaptureDisabled(getWho()));
+    }
+
+    public void testSetScreenCaptureDisabled_anyAdminTrue() {
+        mDevicePolicyManager.setScreenCaptureDisabled(getWho(), true);
+        assertTrue(mDevicePolicyManager.getScreenCaptureDisabled(null /* any admin */));
+    }
+
+    public void testSetScreenCaptureDisabled_anyAdminFalse() {
+        mDevicePolicyManager.setScreenCaptureDisabled(getWho(), false);
+        assertFalse(mDevicePolicyManager.getScreenCaptureDisabled(null /* any admin */));
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/IntentReceiver/Android.mk b/hostsidetests/devicepolicy/app/IntentReceiver/Android.mk
new file mode 100644
index 0000000..62c7f28
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/IntentReceiver/Android.mk
@@ -0,0 +1,31 @@
+# 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsIntentReceiverApp
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/IntentReceiver/AndroidManifest.xml b/hostsidetests/devicepolicy/app/IntentReceiver/AndroidManifest.xml
new file mode 100644
index 0000000..e1f6886
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/IntentReceiver/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?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="com.android.cts.intent.receiver">
+
+    <uses-sdk android:minSdkVersion="19"/>
+
+    <uses-permission android:name="com.android.cts.managedprofile.permission.SAMPLE"/>
+
+    <application>
+        <activity android:name="com.android.cts.intent.receiver.IntentReceiverActivity">
+            <intent-filter>
+                <action android:name="com.android.cts.action.READ_FROM_URI" />
+                <action android:name="com.android.cts.action.WRITE_TO_URI" />
+                <action android:name="com.android.cts.action.TAKE_PERSISTABLE_URI_PERMISSION" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
diff --git a/hostsidetests/devicepolicy/app/IntentReceiver/src/com/android/cts/intent/receiver/IntentReceiverActivity.java b/hostsidetests/devicepolicy/app/IntentReceiver/src/com/android/cts/intent/receiver/IntentReceiverActivity.java
new file mode 100644
index 0000000..59f0752
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/IntentReceiver/src/com/android/cts/intent/receiver/IntentReceiverActivity.java
@@ -0,0 +1,104 @@
+/*
+ * 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 com.android.cts.intent.receiver;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+
+/**
+ * Class to receive intents sent across profile boundaries, and read/write to content uri specified
+ * in these intents to test cross-profile content uris.
+ */
+public class IntentReceiverActivity extends Activity {
+
+    private static final String TAG = "IntentReceiverActivity";
+
+    private static final String ACTION_READ_FROM_URI = "com.android.cts.action.READ_FROM_URI";
+
+    private static final String ACTION_WRITE_TO_URI = "com.android.cts.action.WRITE_TO_URI";
+
+    private static final String ACTION_TAKE_PERSISTABLE_URI_PERMISSION =
+            "com.android.cts.action.TAKE_PERSISTABLE_URI_PERMISSION";
+
+    private static final String EXTRA_CAUGHT_SECURITY_EXCEPTION = "extra_caught_security_exception";
+
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Intent received = getIntent();
+        String action = received.getAction();
+        Uri uri = getIntent().getClipData().getItemAt(0).getUri();
+        if (ACTION_READ_FROM_URI.equals(action)) {
+            Intent result = new Intent();
+            String message = null;
+            try {
+                message = getFirstLineFromUri(uri);
+            } catch (SecurityException e) {
+                Log.i(TAG, "Caught a SecurityException while trying to read " + uri, e);
+                result.putExtra(EXTRA_CAUGHT_SECURITY_EXCEPTION, true);
+            } catch (IOException e) {
+                Log.i(TAG, "Caught a IOException while trying to read " + uri, e);
+            }
+            Log.i(TAG, "Message received in reading test: " + message);
+            result.putExtra("extra_response", message);
+            setResult(Activity.RESULT_OK, result);
+        } else if (ACTION_WRITE_TO_URI.equals(action)) {
+            Intent result = new Intent();
+            String message = received.getStringExtra("extra_message");
+            Log.i(TAG, "Message received in writing test: " + message);
+            try {
+                writeToUri(uri, message);
+            } catch (SecurityException e) {
+                Log.i(TAG, "Caught a SecurityException while trying to write to " + uri, e);
+                result.putExtra(EXTRA_CAUGHT_SECURITY_EXCEPTION, true);
+            } catch (IOException e) {
+                Log.i(TAG, "Caught a IOException while trying to write to " + uri, e);
+            }
+            setResult(Activity.RESULT_OK, result);
+        } else if (ACTION_TAKE_PERSISTABLE_URI_PERMISSION.equals(action)) {
+            Log.i(TAG, "Taking persistable uri permission to " + uri);
+            getContentResolver().takePersistableUriPermission(uri,
+                    Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            setResult(Activity.RESULT_OK);
+        }
+        finish();
+    }
+
+    /**
+     * Returns the first line of the file associated with uri.
+     */
+    private String getFirstLineFromUri(Uri uri) throws IOException {
+        InputStream is = getContentResolver().openInputStream(uri);
+        BufferedReader r = new BufferedReader(new InputStreamReader(is));
+        return r.readLine();
+    }
+
+    private void writeToUri(Uri uri, String text) throws IOException {
+        OutputStreamWriter writer = new OutputStreamWriter(
+                getContentResolver().openOutputStream(uri));
+        writer.write(text);
+        writer.flush();
+        writer.close();
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/IntentSender/Android.mk b/hostsidetests/devicepolicy/app/IntentSender/Android.mk
new file mode 100644
index 0000000..e45ec31
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/IntentSender/Android.mk
@@ -0,0 +1,33 @@
+# 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsIntentSenderApp
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/IntentSender/AndroidManifest.xml b/hostsidetests/devicepolicy/app/IntentSender/AndroidManifest.xml
new file mode 100644
index 0000000..070ef40
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/IntentSender/AndroidManifest.xml
@@ -0,0 +1,59 @@
+<?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="com.android.cts.intent.sender">
+
+    <uses-sdk android:minSdkVersion="19" />
+
+    <permission
+        android:name="com.android.cts.intent.sender.permission.SAMPLE"
+        android:label="Sample Permission" />
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+
+        <activity android:name=".IntentSenderActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+            </intent-filter>
+        </activity>
+
+        <provider
+            android:name="android.support.v4.content.FileProvider"
+            android:authorities="com.android.cts.intent.sender.fileprovider"
+            android:grantUriPermissions="true"
+            android:exported="false">
+            <meta-data
+                android:name="android.support.FILE_PROVIDER_PATHS"
+                android:resource="@xml/filepaths" />
+        </provider>
+
+        <provider
+            android:name=".BasicContentProvider"
+            android:authorities="com.android.cts.intent.sender.provider"
+            android:grantUriPermissions="true"
+            android:exported="true"
+            android:permission="com.android.cts.intent.sender.permission.SAMPLE" />
+
+    </application>
+
+    <instrumentation
+        android:name="android.test.InstrumentationTestRunner"
+        android:targetPackage="com.android.cts.intent.sender"
+        android:label="Intent Sender CTS Tests" />
+
+</manifest>
diff --git a/hostsidetests/devicepolicy/app/IntentSender/res/xml/filepaths.xml b/hostsidetests/devicepolicy/app/IntentSender/res/xml/filepaths.xml
new file mode 100644
index 0000000..f7bf461
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/IntentSender/res/xml/filepaths.xml
@@ -0,0 +1,17 @@
+<!-- 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.
+-->
+<paths xmlns:android="http://schemas.android.com/apk/res/android">
+    <files-path path="texts/" name="texts" />
+</paths>
diff --git a/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/BasicContentProvider.java b/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/BasicContentProvider.java
new file mode 100644
index 0000000..183ab9f
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/BasicContentProvider.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.intent.sender;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+/**
+ * Empty content provider, all permissions are enforced in manifest
+ */
+public class BasicContentProvider extends ContentProvider {
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        // do nothing
+        return 0;
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        return "";
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        return null;
+    }
+
+    @Override
+    public boolean onCreate() {
+        return false;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection,
+            String[] selectionArgs, String sortOrder) {
+        return null;
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection,
+            String[] selectionArgs) {
+        return 0;
+    }
+
+    @Override
+    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+        return ParcelFileDescriptor.open(
+                new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/IntentSenderActivity.java b/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/IntentSenderActivity.java
new file mode 100644
index 0000000..00fa6b7
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/IntentSenderActivity.java
@@ -0,0 +1,55 @@
+/*
+ * 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 com.android.cts.intent.sender;
+
+import android.app.Activity;
+import android.content.Intent;
+
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.TimeUnit;
+
+public class IntentSenderActivity extends Activity {
+
+    private final SynchronousQueue<Result> mResult = new SynchronousQueue<>();
+
+    public static class Result {
+        public final int resultCode;
+        public final Intent data;
+
+        public Result(int resultCode, Intent data) {
+            this.resultCode = resultCode;
+            this.data = data;
+        }
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (resultCode == Activity.RESULT_OK) {
+            try {
+                mResult.offer(new Result(resultCode, data), 5, TimeUnit.SECONDS);
+            } catch (InterruptedException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    public Intent getResult(Intent intent) throws Exception {
+        startActivityForResult(intent, 42);
+        final Result result = mResult.poll(30, TimeUnit.SECONDS);
+        return (result != null) ? result.data : null;
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/IntentSenderTest.java b/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/IntentSenderTest.java
new file mode 100644
index 0000000..47de0da
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/IntentSenderTest.java
@@ -0,0 +1,217 @@
+/*
+ * 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 com.android.cts.intent.sender;
+
+import android.content.ClipData;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.support.v4.content.FileProvider;
+import android.test.InstrumentationTestCase;
+import android.util.Log;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class IntentSenderTest extends InstrumentationTestCase {
+
+    private static final String MESSAGE = "Sample Message";
+
+    private static final String ACTION_READ_FROM_URI = "com.android.cts.action.READ_FROM_URI";
+
+    private static final String ACTION_WRITE_TO_URI = "com.android.cts.action.WRITE_TO_URI";
+
+    private static final String ACTION_TAKE_PERSISTABLE_URI_PERMISSION =
+            "com.android.cts.action.TAKE_PERSISTABLE_URI_PERMISSION";
+
+    private static final String TAG = "CrossProfileContentTest";
+
+    private Context mContext;
+    private IntentSenderActivity mActivity;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mContext = getInstrumentation().getTargetContext();
+        mActivity = launchActivity(mContext.getPackageName(), IntentSenderActivity.class, null);
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        super.tearDown();
+        mActivity.finish();
+    }
+
+    /**
+     * This method will send an intent to a receiver in another profile.
+     * This intent will have, in the ClipData, a uri whose associated file stores a message.
+     * The receiver will read the message from the uri, and put it inside the result intent.
+     */
+    public void testReceiverCanRead() throws Exception {
+        Uri uri = getUriWithTextInFile("reading_test", MESSAGE);
+        assertTrue(uri != null);
+        Intent intent = new Intent(ACTION_READ_FROM_URI);
+        intent.setClipData(ClipData.newRawUri("", uri));
+        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+        final Intent result = mActivity.getResult(intent);
+        assertNotNull(result);
+        assertEquals(MESSAGE, result.getStringExtra("extra_response"));
+    }
+
+    /**
+     * This method will send an intent to a receiver in another profile.
+     * This intent will have a message in an extra, and a uri specified by the ClipData.
+     * The receiver will read the message from the extra, and write it to the uri in
+     * the ClipData.
+     */
+    public void testReceiverCanWrite() throws Exception {
+        // It's the receiver of the intent that should write to the uri, not us. So, for now, we
+        // write an empty string.
+        Uri uri = getUriWithTextInFile("writing_test", "");
+        assertTrue(uri != null);
+        Intent intent = new Intent(ACTION_WRITE_TO_URI);
+        intent.setClipData(ClipData.newRawUri("", uri));
+        intent.putExtra("extra_message", MESSAGE);
+        intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+                | Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+        mActivity.getResult(intent);
+        assertEquals(MESSAGE, getFirstLineFromUri(uri));
+    }
+
+    public void testPersistablePermission() throws Exception {
+        Uri uri = getUriWithTextInFile("persistable_test", MESSAGE);
+        grantPersistableReadPermission(uri);
+
+        // Now checking if the receiver can read this uri, without re-granting the read permission.
+        Intent intent = new Intent(ACTION_READ_FROM_URI);
+        intent.setClipData(ClipData.newRawUri("", uri));
+
+        final Intent result = mActivity.getResult(intent);
+        assertNotNull(result);
+        assertEquals(MESSAGE, result.getStringExtra("extra_response"));
+    }
+
+    /**
+     * The intent receiver will try to read uriNotGranted.
+     * Inside the same user, this uri can be read if the receiver has the
+     * com.android.cts.managedprofile.permission.SAMPLE permission. But since we cross
+     * user-boundaries, it should not be able to (only uri grants work accross users for apps
+     * without special permission).
+     * We also grant uriGranted to the receiver (this uri belongs to the same content provider as
+     * uriNotGranted), to enforce that even if an app has permission to one uri of a
+     * ContentProvider, it still cannot access a uri it does not have access to.
+     */
+    public void testAppPermissionsDontWorkAcrossProfiles() throws Exception {
+        // The FileProvider does not allow to use app permissions. So we need to use another
+        // ContentProvider.
+        Uri uriGranted = getBasicContentProviderUri("uri_granted");
+        Uri uriNotGranted = getBasicContentProviderUri("uri_not_granted");
+
+        // Granting uriGranted to the receiver
+        // Using a persistable permission so that it is kept even after we restart the receiver
+        // activity with another intent.
+        grantPersistableReadPermission(uriGranted);
+
+        Intent notGrant = new Intent(ACTION_READ_FROM_URI);
+        notGrant.setClipData(ClipData.newRawUri("", uriNotGranted));
+
+        final Intent result = mActivity.getResult(notGrant);
+        assertNotNull(result);
+        // The receiver did not have permission to read the uri. So it should have caught a security
+        // exception.
+        assertTrue(result.getBooleanExtra("extra_caught_security_exception", false));
+    }
+
+    /**
+     * Ensure that sender is only able to send data that it has access to.
+     */
+    public void testSecurity() throws Exception {
+        // Pick a URI that neither of us have access to; it doens't matter if
+        // its missing, since we expect a SE before a FNFE.
+        final Uri uri = Uri.parse("content://media/external/images/media/10240");
+        final Intent intent = new Intent(ACTION_READ_FROM_URI);
+        intent.setClipData(ClipData.newRawUri("", uri));
+        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+        // We're expecting to run into a security exception
+        final Intent result = mActivity.getResult(intent);
+        if (result == null) {
+            // This is fine; probably of a SecurityException when off in the
+            // system somewhere.
+        } else {
+            // But if we somehow came through, make sure they threw.
+            assertTrue(result.getBooleanExtra("extra_caught_security_exception", false));
+        }
+    }
+
+    private void grantPersistableReadPermission(Uri uri) throws Exception {
+        Intent grantPersistable = new Intent(ACTION_TAKE_PERSISTABLE_URI_PERMISSION);
+        grantPersistable.setClipData(ClipData.newRawUri("", uri));
+        grantPersistable.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
+        mActivity.getResult(grantPersistable);
+    }
+
+    private Uri getBasicContentProviderUri(String path) {
+        // The uris created here are not associated with any data. But this does not prevent us from
+        // granting these uris to other apps, or these apps from trying to access these uris.
+        return new Uri.Builder()
+                .scheme(ContentResolver.SCHEME_CONTENT)
+                .authority("com.android.cts.intent.sender.provider")
+                .path(path)
+                .build();
+    }
+
+    private Uri getUriWithTextInFile(String name, String text) {
+        String filename = mContext.getFilesDir() + File.separator + "texts" + File.separator
+                + name + ".txt";
+        Log.i(TAG, "Creating file " + filename + " with text \"" + text + "\"");
+        final File file = new File(filename);
+        file.getParentFile().mkdirs(); // If the folder doesn't exists it is created
+        try {
+            FileWriter writer = new FileWriter(file);
+            writer.write(text);
+            writer.close();
+        } catch(IOException e) {
+            Log.e(TAG, "Could not create file " + filename + " with text " + text);
+            return null;
+        }
+        return FileProvider.getUriForFile(mContext, "com.android.cts.intent.sender.fileprovider",
+                file);
+    }
+
+    /**
+     * Returns the first line of the file associated with uri.
+     */
+    private String getFirstLineFromUri(Uri uri) {
+        try {
+            InputStream is = mContext.getContentResolver().openInputStream(uri);
+            BufferedReader r = new BufferedReader(new InputStreamReader(is));
+            return r.readLine();
+        } catch (IOException e) {
+            Log.e(TAG, "could not read the uri " + uri);
+            return null;
+        }
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk b/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk
new file mode 100644
index 0000000..46e3cf7
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk
@@ -0,0 +1,33 @@
+# 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsManagedProfileApp
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner cts-junit
+
+LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
new file mode 100644
index 0000000..008ed38
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
@@ -0,0 +1,77 @@
+<?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="com.android.cts.managedprofile">
+
+    <uses-sdk android:minSdkVersion="20"/>
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+        <receiver
+            android:name="com.android.cts.managedprofile.BaseManagedProfileTest$BasicAdminReceiver"
+            android:permission="android.permission.BIND_DEVICE_ADMIN">
+            <meta-data android:name="android.app.device_admin"
+                       android:resource="@xml/device_admin" />
+            <intent-filter>
+                <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
+            </intent-filter>
+        </receiver>
+        <activity android:name=".PrimaryUserFilterSetterActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity android:name=".ComponentDisablingActivity" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity android:name=".ManagedProfileActivity">
+            <intent-filter>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <action android:name="com.android.cts.managedprofile.ACTION_TEST_MANAGED_ACTIVITY" />
+            </intent-filter>
+        </activity>
+        <activity android:name=".PrimaryUserActivity">
+            <intent-filter>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <action android:name="com.android.cts.managedprofile.ACTION_TEST_PRIMARY_ACTIVITY" />
+            </intent-filter>
+        </activity>
+        <activity android:name=".AllUsersActivity">
+            <intent-filter>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <action android:name="com.android.cts.managedprofile.ACTION_TEST_ALL_ACTIVITY" />
+            </intent-filter>
+        </activity>
+        <activity android:name=".UserRestrictionActivity" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+        </activity>
+        <activity android:name=".TestActivity" />
+    </application>
+
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+                     android:targetPackage="com.android.cts.managedprofile"
+                     android:label="Managed Profile CTS Tests"/>
+</manifest>
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/res/values/strings.xml b/hostsidetests/devicepolicy/app/ManagedProfile/res/values/strings.xml
new file mode 100644
index 0000000..640b8b5
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/res/values/strings.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Label for this package -->
+    <string name="label">Android CTS - Profile Owner</string>
+</resources>
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/res/xml/device_admin.xml b/hostsidetests/devicepolicy/app/ManagedProfile/res/xml/device_admin.xml
new file mode 100644
index 0000000..8f39ed0
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/res/xml/device_admin.xml
@@ -0,0 +1,19 @@
+<!-- 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.
+-->
+<device-admin xmlns:android="http://schemas.android.com/apk/res/android" android:visible="false">
+    <uses-policies>
+        <wipe-data />
+    </uses-policies>
+</device-admin>
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/AllUsersActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/AllUsersActivity.java
new file mode 100644
index 0000000..7260acd
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/AllUsersActivity.java
@@ -0,0 +1,36 @@
+/*
+ * 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 com.android.cts.managedprofile;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+
+/**
+ * Activity that lives in both primary user and its profile.
+ */
+public class AllUsersActivity extends Activity {
+    private static final String TAG = AllUsersActivity.class.getName();
+
+    public static final String ACTION =
+            "com.android.cts.managedprofile.ACTION_TEST_ALL_ACTIVITY";
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Log.i(TAG, "Roger that!");
+    }
+}
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/BaseManagedProfileTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/BaseManagedProfileTest.java
new file mode 100644
index 0000000..2a54d97
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/BaseManagedProfileTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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 com.android.cts.managedprofile;
+
+import android.app.admin.DeviceAdminReceiver;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.test.AndroidTestCase;
+
+/**
+ * Base class for profile-owner based tests.
+ *
+ * This class handles making sure that the test is the profile owner and that it has an active admin
+ * registered, so that all tests may assume these are done.
+ */
+public class BaseManagedProfileTest extends AndroidTestCase {
+
+    public static class BasicAdminReceiver extends DeviceAdminReceiver {
+    }
+
+    public static final ComponentName ADMIN_RECEIVER_COMPONENT = new ComponentName(
+            BasicAdminReceiver.class.getPackage().getName(), BasicAdminReceiver.class.getName());
+
+    protected DevicePolicyManager mDevicePolicyManager;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+       mDevicePolicyManager = (DevicePolicyManager)
+               mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+       assertNotNull(mDevicePolicyManager);
+
+       // TODO: Only check the below if we are running as the profile user. If running under the
+       // user owner, can we check that there is a profile and that the below holds for it? If we
+       // don't want to do these checks every time we could get rid of this class altogether and
+       // just have a single test case running under the profile user that do them.
+       assertTrue(mDevicePolicyManager.isAdminActive(ADMIN_RECEIVER_COMPONENT));
+       assertTrue(mDevicePolicyManager.isProfileOwnerApp(
+               ADMIN_RECEIVER_COMPONENT.getPackageName()));
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ComponentDisablingActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ComponentDisablingActivity.java
new file mode 100644
index 0000000..03922da
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ComponentDisablingActivity.java
@@ -0,0 +1,47 @@
+/*
+ * 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 com.android.cts.managedprofile;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.os.Process;
+import android.util.Log;
+
+/**
+ * Class that disables a given component for the user it's running in.
+ */
+public class ComponentDisablingActivity extends Activity {
+
+    private static final String TAG = ComponentDisablingActivity.class.getName();
+    public static final String EXTRA_PACKAGE = "extra-package";
+    public static final String EXTRA_CLASS_NAME = "extra-class-name";
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        String extraClassName = getIntent().getStringExtra(EXTRA_CLASS_NAME);
+        String extraPackage = getIntent().getStringExtra(EXTRA_PACKAGE);
+
+        Log.i(TAG, "Disabling: " + extraPackage + "/" + extraClassName + " for user "
+                + Process.myUserHandle());
+        PackageManager packageManager = getPackageManager();
+        packageManager.setComponentEnabledSetting(new ComponentName(extraPackage, extraClassName),
+                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+                PackageManager.DONT_KILL_APP);
+    }
+}
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileUtils.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileUtils.java
new file mode 100644
index 0000000..9615991
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileUtils.java
@@ -0,0 +1,65 @@
+/*
+ * 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 com.android.cts.managedprofile;
+
+import static com.android.cts.managedprofile.BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.IntentFilter;
+import android.test.AndroidTestCase;
+
+public class CrossProfileUtils extends AndroidTestCase {
+    private static final String ACTION_READ_FROM_URI = "com.android.cts.action.READ_FROM_URI";
+
+    private static final String ACTION_WRITE_TO_URI = "com.android.cts.action.WRITE_TO_URI";
+
+    private static final String ACTION_TAKE_PERSISTABLE_URI_PERMISSION =
+            "com.android.cts.action.TAKE_PERSISTABLE_URI_PERMISSION";
+
+    public void addParentCanAccessManagedFilters() {
+        removeAllFilters();
+
+        final DevicePolicyManager dpm = (DevicePolicyManager) getContext().getSystemService(
+                Context.DEVICE_POLICY_SERVICE);
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(ACTION_READ_FROM_URI);
+        intentFilter.addAction(ACTION_WRITE_TO_URI);
+        intentFilter.addAction(ACTION_TAKE_PERSISTABLE_URI_PERMISSION);
+        dpm.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT, intentFilter,
+                DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED);
+    }
+
+    public void addManagedCanAccessParentFilters() {
+        removeAllFilters();
+
+        final DevicePolicyManager dpm = (DevicePolicyManager) getContext().getSystemService(
+                Context.DEVICE_POLICY_SERVICE);
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(ACTION_READ_FROM_URI);
+        intentFilter.addAction(ACTION_WRITE_TO_URI);
+        intentFilter.addAction(ACTION_TAKE_PERSISTABLE_URI_PERMISSION);
+        dpm.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT, intentFilter,
+                DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT);
+    }
+
+    public void removeAllFilters() {
+        final DevicePolicyManager dpm = (DevicePolicyManager) getContext().getSystemService(
+                Context.DEVICE_POLICY_SERVICE);
+        dpm.clearCrossProfileIntentFilters(ADMIN_RECEIVER_COMPONENT);
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileActivity.java
new file mode 100644
index 0000000..a383e2c
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileActivity.java
@@ -0,0 +1,38 @@
+/*
+ * 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 com.android.cts.managedprofile;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+
+/**
+ * Activity that lives in the managed profile.
+ */
+public class ManagedProfileActivity extends Activity {
+    private static final String TAG = ManagedProfileActivity.class.getName();
+
+    public static final String ACTION =
+            "com.android.cts.managedprofile.ACTION_TEST_MANAGED_ACTIVITY";
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Log.i(TAG, "Managed profile activity started!");
+        setResult(RESULT_OK);
+        finish();
+    }
+}
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileSetupTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileSetupTest.java
new file mode 100644
index 0000000..b95194e
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileSetupTest.java
@@ -0,0 +1,27 @@
+/*
+ * 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 com.android.cts.managedprofile;
+
+
+public class ManagedProfileSetupTest extends BaseManagedProfileTest {
+
+    // This test verifies that the setUp assertions on the base class are working to verify
+    // we are the profile owner and have a valid active admin.
+    public void testManagedProfileSetup() {
+        // Empty test. We just want the assertions from super.setUp() to be executed.
+    }
+
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileTest.java
new file mode 100644
index 0000000..47ecfcb
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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 com.android.cts.managedprofile;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.test.ActivityInstrumentationTestCase2;
+
+import static com.android.cts.managedprofile.BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT;
+
+/**
+ * Test for {@link DevicePolicyManager#addCrossProfileIntentFilter} API.
+ *
+ * Note that it expects that there is an activity responding to {@code PrimaryUserActivity.ACTION}
+ * in the primary profile, one to {@code ManagedProfileActivity.ACTION} in the secondary profile,
+ * and one to {@code AllUsersActivity.ACTION} in both profiles.
+ */
+public class ManagedProfileTest extends ActivityInstrumentationTestCase2<TestActivity> {
+
+    private PackageManager mPackageManager;
+    private DevicePolicyManager mDevicePolicyManager;
+
+    public ManagedProfileTest() {
+        super(TestActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mPackageManager = getActivity().getPackageManager();
+        mDevicePolicyManager = (DevicePolicyManager)
+                getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mDevicePolicyManager.clearCrossProfileIntentFilters(ADMIN_RECEIVER_COMPONENT);
+        super.tearDown();
+    }
+
+    public void testClearCrossProfileIntentFilters() {
+        IntentFilter testIntentFilter = new IntentFilter();
+        testIntentFilter.addAction(PrimaryUserActivity.ACTION);
+        mDevicePolicyManager.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT,
+                testIntentFilter, DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED);
+        assertEquals(1, mPackageManager.queryIntentActivities(
+                new Intent(PrimaryUserActivity.ACTION), /* flags = */ 0).size());
+
+        mDevicePolicyManager.clearCrossProfileIntentFilters(ADMIN_RECEIVER_COMPONENT);
+
+        assertTrue(mPackageManager.queryIntentActivities(
+                new Intent(PrimaryUserActivity.ACTION), /* flags = */ 0).isEmpty());
+        getActivity().startActivity(ManagedProfileActivity.ACTION);
+        assertTrue(getActivity().checkActivityStarted());
+    }
+
+    public void testAddCrossProfileIntentFilter_primary() {
+        assertEquals(0, mPackageManager.queryIntentActivities(
+                new Intent(PrimaryUserActivity.ACTION), /* flags = */ 0).size());
+
+        IntentFilter testIntentFilter = new IntentFilter();
+        testIntentFilter.addAction(PrimaryUserActivity.ACTION);
+        mDevicePolicyManager.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT,
+                testIntentFilter, DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED);
+
+        assertEquals(1, mPackageManager.queryIntentActivities(
+                new Intent(PrimaryUserActivity.ACTION), /* flags = */ 0).size());
+        getActivity().startActivity(PrimaryUserActivity.ACTION);
+        assertTrue(getActivity().checkActivityStarted());
+    }
+
+    public void testAddCrossProfileIntentFilter_all() {
+        assertEquals(1, mPackageManager.queryIntentActivities(
+                new Intent(AllUsersActivity.ACTION), /* flags = */ 0).size());
+
+        IntentFilter testIntentFilter = new IntentFilter();
+        testIntentFilter.addAction(AllUsersActivity.ACTION);
+        mDevicePolicyManager.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT,
+                testIntentFilter, DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED);
+
+        assertEquals(2, mPackageManager.queryIntentActivities(
+                new Intent(AllUsersActivity.ACTION), /* flags = */ 0).size());
+        // If we used startActivity(), the user would have a disambiguation dialog presented which
+        // requires human intervention, so we won't be testing like that
+    }
+
+    public void testAddCrossProfileIntentFilter_managed() {
+        assertEquals(1, mPackageManager.queryIntentActivities(
+                new Intent(ManagedProfileActivity.ACTION), /* flags = */ 0).size());
+
+        IntentFilter testIntentFilter = new IntentFilter();
+        testIntentFilter.addAction(ManagedProfileActivity.ACTION);
+        mDevicePolicyManager.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT,
+                testIntentFilter, DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED);
+
+        // We should still be resolving in the profile
+        assertEquals(1, mPackageManager.queryIntentActivities(
+                new Intent(ManagedProfileActivity.ACTION), /* flags = */ 0).size());
+        getActivity().startActivity(ManagedProfileActivity.ACTION);
+        assertTrue(getActivity().checkActivityStarted());
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserActivity.java
new file mode 100644
index 0000000..b0e84ae
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserActivity.java
@@ -0,0 +1,39 @@
+/*
+ * 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 com.android.cts.managedprofile;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+
+/**
+ * Activity for that lives in the primary user.
+ */
+public class PrimaryUserActivity extends Activity {
+    private static final String TAG = PrimaryUserActivity.class.getName();
+
+    public static final String ACTION =
+            "com.android.cts.managedprofile.ACTION_TEST_PRIMARY_ACTIVITY";
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Log.i(TAG, "Primary user activity started!");
+        setResult(RESULT_OK);
+        finish();
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserFilterSetterActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserFilterSetterActivity.java
new file mode 100644
index 0000000..c00ced5
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserFilterSetterActivity.java
@@ -0,0 +1,43 @@
+package com.android.cts.managedprofile;
+
+import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.util.Log;
+
+import static com.android.cts.managedprofile.BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT;
+
+/**
+ * Class that sets the cross-profile intent filters required to test intent filtering from
+ * the primary profile to the managed one.
+ */
+public class PrimaryUserFilterSetterActivity extends Activity {
+
+    public static final String TAG = PrimaryUserFilterSetterActivity.class.getName();
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        PackageManager packageManager = getPackageManager();
+        DevicePolicyManager devicePolicyManager = (DevicePolicyManager)
+                getSystemService(Context.DEVICE_POLICY_SERVICE);
+        IntentFilter testIntentFilter = new IntentFilter();
+        testIntentFilter.addAction(PrimaryUserActivity.ACTION);
+        devicePolicyManager.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT,
+                testIntentFilter, DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT);
+
+        testIntentFilter = new IntentFilter();
+        testIntentFilter.addAction(ManagedProfileActivity.ACTION);
+        devicePolicyManager.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT,
+                testIntentFilter, DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT);
+
+        testIntentFilter = new IntentFilter();
+        testIntentFilter.addAction(AllUsersActivity.ACTION);
+        devicePolicyManager.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT,
+                testIntentFilter, DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT);
+        Log.i(TAG, "Roger that!");
+    }
+}
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserTest.java
new file mode 100644
index 0000000..40ff6c5
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserTest.java
@@ -0,0 +1,70 @@
+/*
+ * 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 com.android.cts.managedprofile;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.test.ActivityInstrumentationTestCase2;
+
+/**
+ * Test for {@link DevicePolicyManager#addCrossProfileIntentFilter} API, for
+ * {@code DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT}.
+ *
+ * Note that it expects that there is an activity responding to {@code PrimaryUserActivity.ACTION}
+ * in the primary profile, one to {@code ManagedProfileActivity.ACTION} in the secondary profile,
+ * and one to {@code AllUsersActivity.ACTION} in both profiles.
+ *
+ * Note that the {code DevicePolicyManager#clearCrossProfileIntentFilters} as well as more complex
+ * test scenarios can be found in {@link ManagedProfileTest}.
+ */
+public class PrimaryUserTest extends ActivityInstrumentationTestCase2<TestActivity> {
+
+    private PackageManager mPackageManager;
+
+    public PrimaryUserTest() {
+        super(TestActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mPackageManager = getActivity().getPackageManager();
+    }
+
+    public void testAddCrossProfileIntentFilter_primary() {
+        assertEquals(1, mPackageManager.queryIntentActivities(
+                new Intent(PrimaryUserActivity.ACTION), /* flags = */ 0).size());
+        getActivity().startActivity(PrimaryUserActivity.ACTION);
+        assertTrue(getActivity().checkActivityStarted());
+    }
+
+    public void testAddCrossProfileIntentFilter_all() {
+        assertEquals(2, mPackageManager.queryIntentActivities(
+                new Intent(AllUsersActivity.ACTION), /* flags = */ 0).size());
+
+        // If we used startActivity(), the user would have a disambiguation dialog presented which
+        // requires human intervention, so we won't be testing like that
+    }
+
+    public void testAddCrossProfileIntentFilter_managed() {
+        assertEquals(1, mPackageManager.queryIntentActivities(
+                new Intent(ManagedProfileActivity.ACTION), /* flags = */ 0).size());
+        getActivity().startActivity(ManagedProfileActivity.ACTION);
+        assertTrue(getActivity().checkActivityStarted());
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/TestActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/TestActivity.java
new file mode 100644
index 0000000..b0e22b6
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/TestActivity.java
@@ -0,0 +1,54 @@
+/*
+ * 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 com.android.cts.managedprofile;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.util.Log;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Dummy activity necessary for the tests.
+ */
+public class TestActivity extends Activity {
+    private static final String TAG = TestActivity.class.getName();
+
+    private final Semaphore mActivityStartedSemaphore = new Semaphore(0);
+
+    public void startActivity(String action) {
+        startActivityForResult(new Intent(action), /* requestCode= */ 0);
+    }
+
+    public boolean checkActivityStarted() {
+        Log.i(TAG, "Waiting to see if an activity was started");
+        try {
+            return mActivityStartedSemaphore.tryAcquire(5, TimeUnit.SECONDS);
+        } catch (InterruptedException e) {
+           return false;
+        }
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        Log.i(TAG, "An activity sent a result");
+        if (resultCode != RESULT_OK) {
+            Log.w(TAG, "Activity returned error code: " + resultCode);
+        }
+        mActivityStartedSemaphore.release();
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/UserRestrictionActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/UserRestrictionActivity.java
new file mode 100644
index 0000000..e8decf8
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/UserRestrictionActivity.java
@@ -0,0 +1,83 @@
+/*
+ * 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 com.android.cts.managedprofile;
+
+import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Process;
+import android.util.Log;
+
+import com.android.cts.managedprofile.BaseManagedProfileTest;
+
+/**
+ * Simple activity that adds or clears a user restriction depending on the value of the extras.
+ */
+public class UserRestrictionActivity extends Activity {
+
+    private static final String TAG = UserRestrictionActivity.class.getName();
+
+    private static final String EXTRA_RESTRICTION_KEY = "extra-restriction-key";
+    private static final String EXTRA_COMMAND = "extra-command";
+
+    private static final String ADD_COMMAND = "add-restriction";
+    private static final String CLEAR_COMMAND = "clear-restriction";
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        handleIntent(getIntent());
+    }
+
+    // Overriding this method in case another intent is sent to this activity before finish()
+    @Override
+    public void onNewIntent(Intent intent) {
+        super.onNewIntent(intent);
+        handleIntent(intent);
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        // Calling finish() here because doing it in onCreate(), onStart() or onResume() makes
+        // "adb shell am start" timeout if using the -W option.
+        finish();
+    }
+
+    private void handleIntent(Intent intent) {
+        DevicePolicyManager dpm = (DevicePolicyManager)
+                getSystemService(Context.DEVICE_POLICY_SERVICE);
+        String restrictionKey = intent.getStringExtra(EXTRA_RESTRICTION_KEY);
+        String command = intent.getStringExtra(EXTRA_COMMAND);
+        Log.i(TAG, "Command: \"" + command + "\". Restriction: \"" + restrictionKey + "\"");
+
+        if (ADD_COMMAND.equals(command)) {
+            dpm.addUserRestriction(BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT, restrictionKey);
+            Log.i(TAG, "Added user restriction " + restrictionKey
+                    + " for user " + Process.myUserHandle());
+        } else if (CLEAR_COMMAND.equals(command)) {
+            dpm.clearUserRestriction(
+                    BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT, restrictionKey);
+            Log.i(TAG, "Cleared user restriction " + restrictionKey
+                    + " for user " + Process.myUserHandle());
+        } else {
+            Log.e(TAG, "Invalid command: " + command);
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/WipeDataTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/WipeDataTest.java
new file mode 100644
index 0000000..b548c96
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/WipeDataTest.java
@@ -0,0 +1,80 @@
+/*
+ * 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 com.android.cts.managedprofile;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.Process;
+import android.os.UserHandle;
+import android.os.UserManager;
+
+import com.android.cts.managedprofile.BaseManagedProfileTest.BasicAdminReceiver;
+
+import org.junit.Ignore;
+
+/**
+ * Test wipeData() for use in managed profile. If called from a managed profile, wipeData() should
+ * remove the current managed profile. Also, no erasing of external storage should be allowed.
+ */
+public class WipeDataTest extends BaseManagedProfileTest {
+
+    private UserManager mUserManager;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        // Make sure we are running in a managed profile, otherwise risk wiping the primary user's
+        // data.
+        assertTrue(mDevicePolicyManager.isAdminActive(ADMIN_RECEIVER_COMPONENT));
+        assertTrue(mDevicePolicyManager.isProfileOwnerApp(ADMIN_RECEIVER_COMPONENT.getPackageName()));
+        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+    }
+
+    public void testWipeData() throws InterruptedException {
+        try {
+            mDevicePolicyManager.wipeData(DevicePolicyManager.WIPE_EXTERNAL_STORAGE);
+            fail("Should not be able to wipe external storage from managed profile.");
+        } catch (SecurityException expected) {
+        }
+
+        UserHandle currentUser = Process.myUserHandle();
+        assertTrue(mUserManager.getUserProfiles().contains(currentUser));
+
+        mDevicePolicyManager.wipeData(0);
+
+        // ACTION_MANAGED_PROFILE_REMOVED is only sent to parent user.
+        // As a result, we have to poll in order to know when the profile
+        // is actually removed.
+        long epoch = System.currentTimeMillis();
+        while (System.currentTimeMillis() - epoch <= 10 * 1000) {
+            if (!mUserManager.getUserProfiles().contains(currentUser)) {
+                break;
+            }
+            Thread.sleep(250);
+        }
+
+        // Verify the profile is deleted
+        assertFalse(mUserManager.getUserProfiles().contains(currentUser));
+    }
+
+    // Override this test inherited from base class, as it will trigger another round of setUp()
+    // which would fail because the managed profile has been removed by this test.
+    @Override
+    @Ignore
+    public void testAndroidTestCaseSetupProperly() {
+    }
+}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
new file mode 100644
index 0000000..544ddff
--- /dev/null
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -0,0 +1,258 @@
+/*
+ * 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 com.android.cts.devicepolicy;
+
+import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.cts.util.AbiUtils;
+import com.android.ddmlib.Log.LogLevel;
+import com.android.ddmlib.testrunner.InstrumentationResultParser;
+import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.ddmlib.testrunner.TestResult;
+import com.android.ddmlib.testrunner.TestResult.TestStatus;
+import com.android.ddmlib.testrunner.TestRunResult;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Map;
+
+import javax.annotation.Nullable;
+
+/**
+ * Base class for device policy tests. It offers utility methods to run tests, set device or profile
+ * owner, etc.
+ */
+public class BaseDevicePolicyTest extends DeviceTestCase implements IBuildReceiver {
+
+    private static final String RUNNER = "android.test.InstrumentationTestRunner";
+
+    private static final String[] REQUIRED_DEVICE_FEATURES = new String[] {
+        "android.software.managed_users",
+        "android.software.device_admin" };
+
+    private CtsBuildHelper mCtsBuild;
+
+    protected boolean mHasFeature;
+
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        assertNotNull(mCtsBuild);  // ensure build has been set before test is run.
+        mHasFeature = getDevice().getApiLevel() >= 21 /* Build.VERSION_CODES.L */
+                && hasDeviceFeatures(REQUIRED_DEVICE_FEATURES);
+    }
+
+    protected void installApp(String fileName)
+            throws FileNotFoundException, DeviceNotAvailableException {
+        String installResult = getDevice().installPackage(mCtsBuild.getTestApp(fileName), true);
+        assertNull(String.format("Failed to install %s, Reason: %s", fileName, installResult),
+                installResult);
+    }
+
+    protected void installAppAsUser(String appFileName, int userId) throws FileNotFoundException,
+            DeviceNotAvailableException {
+        final ITestDevice device = getDevice();
+
+        final File apk = mCtsBuild.getTestApp(appFileName);
+        final String remotePath = "/data/local/tmp/" + apk.getName();
+        if (!device.pushFile(apk, remotePath)) {
+            throw new IllegalStateException("Failed to push " + apk);
+        }
+
+        final String result = device.executeShellCommand(
+                "pm install --user " + userId + " " + remotePath);
+        assertTrue(result, result.contains("\nSuccess"));
+    }
+
+    /** Initializes the user with the given id. This is required so that apps can run on it. */
+    protected void startUser(int userId) throws DeviceNotAvailableException {
+        String command = "am start-user " + userId;
+        String commandOutput = getDevice().executeShellCommand(command);
+        CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": " + commandOutput);
+        assertTrue(commandOutput + " expected to start with \"Success:\"",
+                commandOutput.startsWith("Success:"));
+    }
+
+    protected int getMaxNumberOfUsersSupported() throws DeviceNotAvailableException {
+        // TODO: move this to ITestDevice once it supports users
+        String command = "pm get-max-users";
+        String commandOutput = getDevice().executeShellCommand(command);
+        CLog.i("Output for command " + command + ": " + commandOutput);
+
+        try {
+            return Integer.parseInt(commandOutput.substring(commandOutput.lastIndexOf(" ")).trim());
+        } catch (NumberFormatException e) {
+            fail("Failed to parse result: " + commandOutput);
+        }
+        return 0;
+    }
+
+    protected ArrayList<Integer> listUsers() throws DeviceNotAvailableException {
+        String command = "pm list users";
+        String commandOutput = getDevice().executeShellCommand(command);
+        CLog.i("Output for command " + command + ": " + commandOutput);
+
+        // Extract the id of all existing users.
+        String[] lines = commandOutput.split("\\r?\\n");
+        assertTrue(commandOutput + " should contain at least one line", lines.length >= 1);
+        assertEquals(commandOutput, lines[0], "Users:");
+
+        ArrayList<Integer> users = new ArrayList<Integer>();
+        for (int i = 1; i < lines.length; i++) {
+            // Individual user is printed out like this:
+            // \tUserInfo{$id$:$name$:$Integer.toHexString(flags)$} [running]
+            String[] tokens = lines[i].split("\\{|\\}|:");
+            assertTrue(lines[i] + " doesn't contain 4 or 5 tokens",
+                    tokens.length == 4 || tokens.length == 5);
+            users.add(Integer.parseInt(tokens[1]));
+        }
+        return users;
+    }
+
+    protected void removeUser(int userId) throws DeviceNotAvailableException  {
+        String removeUserCommand = "pm remove-user " + userId;
+        CLog.logAndDisplay(LogLevel.INFO, "Output for command " + removeUserCommand + ": "
+                + getDevice().executeShellCommand(removeUserCommand));
+    }
+
+    /** Returns true if the specified tests passed. Tests are run as user owner. */
+    protected boolean runDeviceTests(String pkgName, @Nullable String testClassName)
+            throws DeviceNotAvailableException {
+        return runDeviceTests(pkgName, testClassName, null /*testMethodName*/, null /*userId*/);
+    }
+
+    /** Returns true if the specified tests passed. Tests are run as given user. */
+    protected boolean runDeviceTestsAsUser(
+            String pkgName, @Nullable String testClassName, int userId)
+            throws DeviceNotAvailableException {
+        return runDeviceTestsAsUser(pkgName, testClassName, null, userId);
+    }
+
+    /** Returns true if the specified tests passed. Tests are run as given user. */
+    protected boolean runDeviceTestsAsUser(
+            String pkgName, @Nullable String testClassName, String testMethodName, int userId)
+            throws DeviceNotAvailableException {
+        if (testClassName.startsWith(".")) {
+            testClassName = pkgName + testClassName;
+        }
+        return runDeviceTests(pkgName, testClassName, testMethodName, userId);
+    }
+
+    private boolean runDeviceTests(String pkgName, @Nullable String testClassName,
+            @Nullable String testMethodName, @Nullable Integer userId)
+                    throws DeviceNotAvailableException {
+        TestRunResult runResult = (userId == null)
+                ? doRunTests(pkgName, testClassName, testMethodName)
+                : doRunTestsAsUser(pkgName, testClassName, testMethodName, userId);
+        printTestResult(runResult);
+        return !runResult.hasFailedTests() && runResult.getNumTestsInState(TestStatus.PASSED) > 0;
+    }
+
+    /** Helper method to run tests and return the listener that collected the results. */
+    private TestRunResult doRunTests(
+            String pkgName, String testClassName,
+            String testMethodName) throws DeviceNotAvailableException {
+        RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(
+                pkgName, RUNNER, getDevice().getIDevice());
+        if (testClassName != null && testMethodName != null) {
+            testRunner.setMethodName(testClassName, testMethodName);
+        } else if (testClassName != null) {
+            testRunner.setClassName(testClassName);
+        }
+
+        CollectingTestListener listener = new CollectingTestListener();
+        assertTrue(getDevice().runInstrumentationTests(testRunner, listener));
+        return listener.getCurrentRunResults();
+    }
+
+    private TestRunResult doRunTestsAsUser(String pkgName, @Nullable String testClassName,
+            @Nullable String testMethodName, int userId)
+            throws DeviceNotAvailableException {
+        // TODO: move this to RemoteAndroidTestRunner once it supports users. Should be straight
+        // forward to add a RemoteAndroidTestRunner.setUser(userId) method. Then we can merge both
+        // doRunTests* methods.
+        StringBuilder testsToRun = new StringBuilder();
+        if (testClassName != null) {
+            testsToRun.append("-e class " + testClassName);
+            if (testMethodName != null) {
+                testsToRun.append("#" + testMethodName);
+            }
+        }
+        String command = "am instrument --user " + userId + " -w -r " + testsToRun + " "
+                + pkgName + "/" + RUNNER;
+        CLog.i("Running " + command);
+
+        CollectingTestListener listener = new CollectingTestListener();
+        InstrumentationResultParser parser = new InstrumentationResultParser(pkgName, listener);
+        getDevice().executeShellCommand(command, parser);
+        return listener.getCurrentRunResults();
+    }
+
+    private void printTestResult(TestRunResult runResult) {
+        for (Map.Entry<TestIdentifier, TestResult> testEntry :
+                runResult.getTestResults().entrySet()) {
+            TestResult testResult = testEntry.getValue();
+            CLog.logAndDisplay(LogLevel.INFO,
+                    "Test " + testEntry.getKey() + ": " + testResult.getStatus());
+            if (testResult.getStatus() != TestStatus.PASSED) {
+                CLog.logAndDisplay(LogLevel.WARN, testResult.getStackTrace());
+            }
+        }
+    }
+
+    private boolean hasDeviceFeatures(String[] requiredFeatures)
+            throws DeviceNotAvailableException {
+        // TODO: Move this logic to ITestDevice.
+        String command = "pm list features";
+        String commandOutput = getDevice().executeShellCommand(command);
+        CLog.i("Output for command " + command + ": " + commandOutput);
+
+        // Extract the id of the new user.
+        HashSet<String> availableFeatures = new HashSet<String>();
+        for (String feature: commandOutput.split("\\s+")) {
+            // Each line in the output of the command has the format "feature:{FEATURE_VALUE}".
+            String[] tokens = feature.split(":");
+            assertTrue("\"" + feature + "\" expected to have format feature:{FEATURE_VALUE}",
+                    tokens.length > 1);
+            assertEquals(feature, "feature", tokens[0]);
+            availableFeatures.add(tokens[1]);
+        }
+
+        for (String requiredFeature : requiredFeatures) {
+            if(!availableFeatures.contains(requiredFeature)) {
+                CLog.logAndDisplay(LogLevel.INFO, "Device doesn't have required feature "
+                        + requiredFeature + ". Tests won't run.");
+                return false;
+            }
+        }
+        return true;
+    }
+}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
new file mode 100644
index 0000000..b84e9fe
--- /dev/null
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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 com.android.cts.devicepolicy;
+
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.log.LogUtil.CLog;
+
+/**
+ * Set of tests for Device Owner use cases.
+ */
+public class DeviceOwnerTest extends BaseDevicePolicyTest {
+
+    private static final String DEVICE_OWNER_PKG = "com.android.cts.deviceowner";
+    private static final String DEVICE_OWNER_APK = "CtsDeviceOwnerApp.apk";
+
+    private static final String ADMIN_RECEIVER_TEST_CLASS =
+            DEVICE_OWNER_PKG + ".BaseDeviceOwnerTest$BasicAdminReceiver";
+    private static final String CLEAR_DEVICE_OWNER_TEST_CLASS =
+            DEVICE_OWNER_PKG + ".ClearDeviceOwnerTest";
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        if (mHasFeature) {
+            installApp(DEVICE_OWNER_APK);
+            setDeviceOwner(DEVICE_OWNER_PKG + "/" + ADMIN_RECEIVER_TEST_CLASS);
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mHasFeature) {
+            assertTrue("Failed to remove device owner.",
+                    runDeviceTests(DEVICE_OWNER_PKG, CLEAR_DEVICE_OWNER_TEST_CLASS));
+            getDevice().uninstallPackage(DEVICE_OWNER_PKG);
+        }
+
+        super.tearDown();
+    }
+
+    public void testApplicationRestrictions() throws Exception {
+        executeDeviceOwnerTest("ApplicationRestrictionsTest");
+    }
+
+    public void testCaCertManagement() throws Exception {
+        executeDeviceOwnerTest("CaCertManagementTest");
+    }
+
+    public void testDeviceOwnerSetup() throws Exception {
+        executeDeviceOwnerTest("DeviceOwnerSetupTest");
+    }
+
+    public void testKeyManagement() throws Exception {
+        executeDeviceOwnerTest("KeyManagementTest");
+    }
+
+    public void testLockTask() throws Exception {
+        executeDeviceOwnerTest("LockTaskTest");
+    }
+
+    public void testPersistentIntentResolving() throws Exception {
+        executeDeviceOwnerTest("PersistentIntentResolvingTest");
+    }
+
+    public void testScreenCaptureDisabled() throws Exception {
+        executeDeviceOwnerTest("ScreenCaptureDisabledTest");
+    }
+
+    private void executeDeviceOwnerTest(String testClassName) throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        String testClass = DEVICE_OWNER_PKG + "." + testClassName;
+        assertTrue(testClass + " failed.", runDeviceTests(DEVICE_OWNER_PKG, testClass));
+    }
+
+    private void setDeviceOwner(String componentName) throws DeviceNotAvailableException {
+        String command = "dpm set-device-owner '" + componentName + "'";
+        String commandOutput = getDevice().executeShellCommand(command);
+        CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": " + commandOutput);
+        assertTrue(commandOutput + " expected to start with \"Success:\"",
+                commandOutput.startsWith("Success:"));
+    }
+
+}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
new file mode 100644
index 0000000..6ece85c
--- /dev/null
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
@@ -0,0 +1,215 @@
+/*
+ * 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 com.android.cts.devicepolicy;
+
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.log.LogUtil.CLog;
+
+/**
+ * Set of tests for Managed Profile use cases.
+ */
+public class ManagedProfileTest extends BaseDevicePolicyTest {
+
+    private static final String MANAGED_PROFILE_PKG = "com.android.cts.managedprofile";
+    private static final String MANAGED_PROFILE_APK = "CtsManagedProfileApp.apk";
+
+    private static final String INTENT_SENDER_PKG = "com.android.cts.intent.sender";
+    private static final String INTENT_SENDER_APK = "CtsIntentSenderApp.apk";
+
+    private static final String INTENT_RECEIVER_PKG = "com.android.cts.intent.receiver";
+    private static final String INTENT_RECEIVER_APK = "CtsIntentReceiverApp.apk";
+
+    private static final String ADMIN_RECEIVER_TEST_CLASS =
+            MANAGED_PROFILE_PKG + ".BaseManagedProfileTest$BasicAdminReceiver";
+
+    private int mUserId;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        // We need multi user to be supported in order to create a profile of the user owner.
+        mHasFeature = mHasFeature && (getMaxNumberOfUsersSupported() > 1);
+
+        if (mHasFeature) {
+            mUserId = createManagedProfile();
+            installApp(MANAGED_PROFILE_APK);
+            setProfileOwner(MANAGED_PROFILE_PKG + "/" + ADMIN_RECEIVER_TEST_CLASS, mUserId);
+            startUser(mUserId);
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mHasFeature) {
+            removeUser(mUserId);
+            getDevice().uninstallPackage(MANAGED_PROFILE_PKG);
+        }
+
+        super.tearDown();
+    }
+
+    public void testManagedProfileSetup() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        assertTrue(runDeviceTestsAsUser(
+                MANAGED_PROFILE_PKG, MANAGED_PROFILE_PKG + ".ManagedProfileSetupTest", mUserId));
+    }
+
+    /**
+     *  wipeData() test removes the managed profile, so it needs to separated from other tests.
+     */
+    public void testWipeData() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        assertTrue(listUsers().contains(mUserId));
+        assertTrue(runDeviceTestsAsUser(
+                MANAGED_PROFILE_PKG, MANAGED_PROFILE_PKG + ".WipeDataTest", mUserId));
+        // Note: the managed profile is removed by this test, which will make removeUserCommand in
+        // tearDown() to complain, but that should be OK since its result is not asserted.
+        assertFalse(listUsers().contains(mUserId));
+    }
+
+    public void testCrossProfileIntentFilters() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        // Set up activities: ManagedProfileActivity will only be enabled in the managed profile and
+        // PrimaryUserActivity only in the primary one
+        disableActivityForUser("ManagedProfileActivity", 0);
+        disableActivityForUser("PrimaryUserActivity", mUserId);
+
+        assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG,
+                MANAGED_PROFILE_PKG + ".ManagedProfileTest", mUserId));
+
+        // Set up filters from primary to managed profile
+        String command = "am start -W --user " + mUserId  + " " + MANAGED_PROFILE_PKG
+                + "/.PrimaryUserFilterSetterActivity";
+        CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": "
+              + getDevice().executeShellCommand(command));
+        assertTrue(runDeviceTests(MANAGED_PROFILE_PKG, MANAGED_PROFILE_PKG + ".PrimaryUserTest"));
+        // TODO: Test with startActivity
+        // TODO: Test with CtsVerifier for disambiguation cases
+    }
+
+    public void testCrossProfileContent() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+
+        try {
+            getDevice().uninstallPackage(INTENT_SENDER_PKG);
+            getDevice().uninstallPackage(INTENT_RECEIVER_PKG);
+            installAppAsUser(INTENT_SENDER_APK, 0);
+            installAppAsUser(INTENT_RECEIVER_APK, mUserId);
+
+            // Test from parent to managed
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CrossProfileUtils",
+                    "addManagedCanAccessParentFilters", mUserId));
+            assertTrue(runDeviceTestsAsUser(INTENT_SENDER_PKG, ".IntentSenderTest", 0));
+
+            getDevice().uninstallPackage(INTENT_SENDER_PKG);
+            getDevice().uninstallPackage(INTENT_RECEIVER_PKG);
+            installAppAsUser(INTENT_SENDER_APK, mUserId);
+            installAppAsUser(INTENT_RECEIVER_APK, 0);
+
+            // Test from managed to parent
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CrossProfileUtils",
+                    "addParentCanAccessManagedFilters", mUserId));
+            assertTrue(runDeviceTestsAsUser(INTENT_SENDER_PKG, ".IntentSenderTest", mUserId));
+
+        } finally {
+            getDevice().uninstallPackage(INTENT_SENDER_PKG);
+            getDevice().uninstallPackage(INTENT_RECEIVER_PKG);
+        }
+    }
+
+    // TODO: This test is not specific to managed profiles, but applies to multi-user in general.
+    // Move it to a MultiUserTest class when there is one. Should probably move
+    // UserRestrictionActivity to a more generic apk too as it might be useful for different kinds
+    // of tests (same applies to ComponentDisablingActivity).
+    public void testNoDebuggingFeaturesRestriction() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        String restriction = "no_debugging_features";  // UserManager.DISALLOW_DEBUGGING_FEATURES
+        String command = "add-restriction";
+
+        String addRestrictionCommandOutput =
+                changeUserRestrictionForUser(restriction, command, mUserId);
+        assertTrue("Command was expected to succeed " + addRestrictionCommandOutput,
+                addRestrictionCommandOutput.contains("Status: ok"));
+
+        // This should now fail, as the shell is not available to start activities under a different
+        // user once the restriction is in place.
+        addRestrictionCommandOutput =
+                changeUserRestrictionForUser(restriction, command, mUserId);
+        assertTrue(
+                "Expected SecurityException when starting the activity "
+                        + addRestrictionCommandOutput,
+                addRestrictionCommandOutput.contains("SecurityException"));
+    }
+
+    private void disableActivityForUser(String activityName, int userId)
+            throws DeviceNotAvailableException {
+        String command = "am start -W --user " + userId
+                + " --es extra-package " + MANAGED_PROFILE_PKG
+                + " --es extra-class-name " + MANAGED_PROFILE_PKG + "." + activityName
+                + " " + MANAGED_PROFILE_PKG + "/.ComponentDisablingActivity ";
+        CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": "
+                + getDevice().executeShellCommand(command));
+    }
+
+    private String changeUserRestrictionForUser(String key, String command, int userId)
+            throws DeviceNotAvailableException {
+        String adbCommand = "am start -W --user " + userId
+                + " -c android.intent.category.DEFAULT "
+                + " --es extra-command " + command
+                + " --es extra-restriction-key " + key
+                + " " + MANAGED_PROFILE_PKG + "/.UserRestrictionActivity";
+        String commandOutput = getDevice().executeShellCommand(adbCommand);
+        CLog.logAndDisplay(LogLevel.INFO,
+                "Output for command " + adbCommand + ": " + commandOutput);
+        return commandOutput;
+    }
+
+    private int createManagedProfile() throws DeviceNotAvailableException {
+        String command =
+                "pm create-user --profileOf 0 --managed TestProfile_" + System.currentTimeMillis();
+        String commandOutput = getDevice().executeShellCommand(command);
+        CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": " + commandOutput);
+
+        // Extract the id of the new user.
+        String[] tokens = commandOutput.split("\\s+");
+        assertTrue(commandOutput + " expected to have format \"Success: {USER_ID}\"",
+                tokens.length > 0);
+        assertEquals(commandOutput, "Success:", tokens[0]);
+        return Integer.parseInt(tokens[tokens.length-1]);
+    }
+
+    private void setProfileOwner(String componentName, int userId)
+            throws DeviceNotAvailableException {
+        String command = "dpm set-profile-owner '" + componentName + "' " + userId;
+        String commandOutput = getDevice().executeShellCommand(command);
+        CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": " + commandOutput);
+        assertTrue(commandOutput + " expected to start with \"Success:\"",
+                commandOutput.startsWith("Success:"));
+    }
+}
diff --git a/hostsidetests/monkey/Android.mk b/hostsidetests/monkey/Android.mk
index 45d2e37..c9f3bb3 100644
--- a/hostsidetests/monkey/Android.mk
+++ b/hostsidetests/monkey/Android.mk
@@ -22,7 +22,7 @@
 
 LOCAL_MODULE := CtsMonkeyTestCases
 
-LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt ddmlib-prebuilt junit
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
 
 # prefix zzz intentional to run this last
 LOCAL_CTS_TEST_PACKAGE := zzz.android.monkey
diff --git a/hostsidetests/monkey/src/com/android/cts/monkey/AbstractMonkeyTest.java b/hostsidetests/monkey/src/com/android/cts/monkey/AbstractMonkeyTest.java
index 9c27b62..9e04274 100644
--- a/hostsidetests/monkey/src/com/android/cts/monkey/AbstractMonkeyTest.java
+++ b/hostsidetests/monkey/src/com/android/cts/monkey/AbstractMonkeyTest.java
@@ -1,28 +1,37 @@
 package com.android.cts.monkey;
 
 import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.cts.util.AbiUtils;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
 import com.android.tradefed.testtype.IBuildReceiver;
 
 import java.io.File;
 
-abstract class AbstractMonkeyTest extends DeviceTestCase implements IBuildReceiver {
+abstract class AbstractMonkeyTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
 
     static final String[] PKGS = {"com.android.cts.monkey", "com.android.cts.monkey2"};
     static final String[] APKS = {"CtsMonkeyApp.apk", "CtsMonkeyApp2.apk"};
 
-    /** 
+    /**
      * Base monkey command with flags to avoid side effects like airplane mode.
      */
     static final String MONKEY_CMD = "monkey --pct-touch 0 --pct-motion 0 --pct-majornav 0 --pct-syskeys 0 --pct-anyevent 0 --pct-rotation 0";
 
+    IAbi mAbi;
     CtsBuildHelper mBuild;
     ITestDevice mDevice;
 
     @Override
+    public void setAbi(IAbi abi) {
+        mAbi = abi;
+    }
+
+    @Override
     public void setBuild(IBuildInfo buildInfo) {
         mBuild = CtsBuildHelper.createBuildHelper(buildInfo);
     }
@@ -31,10 +40,11 @@
     protected void setUp() throws Exception {
         super.setUp();
         mDevice = getDevice();
+        String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
         for (int i = 0; i < PKGS.length; i++) {
             mDevice.uninstallPackage(PKGS[i]);
             File app = mBuild.getTestApp(APKS[i]);
-            mDevice.installPackage(app, false);
+            mDevice.installPackage(app, false, options);
         }
         clearLogCat();
     }
diff --git a/hostsidetests/sample/Android.mk b/hostsidetests/sample/Android.mk
index 1d3ddc8..e8cbdda 100644
--- a/hostsidetests/sample/Android.mk
+++ b/hostsidetests/sample/Android.mk
@@ -23,7 +23,7 @@
 # Must match the package name in CtsTestCaseList.mk
 LOCAL_MODULE := CtsSampleHostTestCases
 
-LOCAL_JAVA_LIBRARIES := cts-tradefed ddmlib-prebuilt tradefed-prebuilt
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
 
 LOCAL_CTS_TEST_PACKAGE := android.host.sample
 
diff --git a/hostsidetests/sample/src/android/sample/cts/SampleHostResultTest.java b/hostsidetests/sample/src/android/sample/cts/SampleHostResultTest.java
index a3bc08f..bed4c05 100644
--- a/hostsidetests/sample/src/android/sample/cts/SampleHostResultTest.java
+++ b/hostsidetests/sample/src/android/sample/cts/SampleHostResultTest.java
@@ -24,11 +24,12 @@
 import com.android.cts.util.ResultUnit;
 import com.android.cts.util.ReportLog;
 import com.android.cts.util.Stat;
-import com.android.ddmlib.Log;
 import com.android.ddmlib.IDevice;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
 import com.android.tradefed.testtype.IBuildReceiver;
 import com.android.tradefed.util.CommandResult;
 import com.android.tradefed.util.CommandStatus;
@@ -41,7 +42,7 @@
 /**
  * Test to measure the transfer time of a file from the host to the device.
  */
-public class SampleHostResultTest extends DeviceTestCase implements IBuildReceiver {
+public class SampleHostResultTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
 
     private static final String TAG = SampleHostResultTest.class.getSimpleName();
 
@@ -67,6 +68,16 @@
      */
     private ITestDevice mDevice;
 
+    /**
+     * A reference to the ABI under test.
+     */
+    private IAbi mAbi;
+
+    @Override
+    public void setAbi(IAbi abi) {
+        mAbi = abi;
+    }
+
     @Override
     public void setBuild(IBuildInfo buildInfo) {
         // Get the build, this is used to access the APK.
@@ -122,7 +133,7 @@
         // Compute the stats.
         Stat.StatResult stat = Stat.getStat(result);
         // Get the report for this test and add the results to record.
-        HostReportLog report = new HostReportLog(mDevice.getSerialNumber(),
+        HostReportLog report = new HostReportLog(mDevice.getSerialNumber(), mAbi.getName(),
                 ReportLog.getClassMethodNames());
         report.printArray("Times", result, ResultType.LOWER_BETTER, ResultUnit.MS);
         report.printValue("Min", stat.mMin, ResultType.LOWER_BETTER, ResultUnit.MS);
diff --git a/hostsidetests/sample/src/android/sample/cts/SampleHostTest.java b/hostsidetests/sample/src/android/sample/cts/SampleHostTest.java
index 7ccde0e..3cc4aa9 100644
--- a/hostsidetests/sample/src/android/sample/cts/SampleHostTest.java
+++ b/hostsidetests/sample/src/android/sample/cts/SampleHostTest.java
@@ -17,9 +17,12 @@
 package android.sample.cts;
 
 import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.cts.util.AbiUtils;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
 import com.android.tradefed.testtype.IBuildReceiver;
 
 import java.io.File;
@@ -29,11 +32,11 @@
 /**
  * Test to check the APK logs to Logcat.
  *
- * When this test builds, it also builds {@see android.sample.app.SampleDeviceActivity} into an APK
+ * When this test builds, it also builds {@link android.sample.app.SampleDeviceActivity} into an APK
  * which it then installs at runtime and starts. The activity simply prints a message to Logcat and
  * then gets uninstalled.
  */
-public class SampleHostTest extends DeviceTestCase implements IBuildReceiver {
+public class SampleHostTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
 
     /**
      * The package name of the APK.
@@ -62,6 +65,11 @@
     private static final String TEST_STRING = "SampleTestString";
 
     /**
+     * The ABI to use.
+     */
+    private IAbi mAbi;
+
+    /**
      * A reference to the build.
      */
     private CtsBuildHelper mBuild;
@@ -72,6 +80,11 @@
     private ITestDevice mDevice;
 
     @Override
+    public void setAbi(IAbi abi) {
+        mAbi = abi;
+    }
+
+    @Override
     public void setBuild(IBuildInfo buildInfo) {
         // Get the build, this is used to access the APK.
         mBuild = CtsBuildHelper.createBuildHelper(buildInfo);
@@ -86,8 +99,10 @@
         mDevice.uninstallPackage(PACKAGE);
         // Get the APK from the build.
         File app = mBuild.getTestApp(APK);
+        // Get the ABI flag.
+        String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
         // Install the APK on the device.
-        mDevice.installPackage(app, false);
+        mDevice.installPackage(app, false, options);
     }
 
     @Override
@@ -118,6 +133,7 @@
                 testString = line.split(":")[1].trim();
             }
         }
+        in.close();
         // Assert the logged string matches the test string.
         assertEquals("Incorrect test string", TEST_STRING, testString);
     }
diff --git a/hostsidetests/security/Android.mk b/hostsidetests/security/Android.mk
new file mode 100644
index 0000000..a42ee8a
--- /dev/null
+++ b/hostsidetests/security/Android.mk
@@ -0,0 +1,34 @@
+# 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_MODULE_TAGS := optional
+
+# Must match the package name in CtsTestCaseList.mk
+LOCAL_MODULE := CtsSecurityHostTestCases
+
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
+
+LOCAL_CTS_TEST_PACKAGE := android.host.security
+
+LOCAL_JAVA_RESOURCE_FILES := $(HOST_OUT_EXECUTABLES)/sepolicy-analyze
+
+include $(BUILD_CTS_HOST_JAVA_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
new file mode 100644
index 0000000..e2c98fe
--- /dev/null
+++ b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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 com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.ddmlib.Log;
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.FileOutputStream;
+import java.lang.String;
+import java.net.URL;
+import java.util.Scanner;
+
+/**
+ * Host-side SELinux tests.
+ *
+ * These tests analyze the policy file in use on the subject device directly or
+ * run as the shell user to evaluate aspects of the state of SELinux on the test
+ * device which otherwise would not be available to a normal apk.
+ */
+public class SELinuxHostTest extends DeviceTestCase {
+
+    /**
+     * A reference to the device under test.
+     */
+    private ITestDevice mDevice;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mDevice = getDevice();
+    }
+
+    /**
+     * Tests that all domains in the running policy file are in enforcing mode
+     *
+     * @throws Exception
+     */
+    public void testAllEnforcing() throws Exception {
+
+        /* retrieve the sepolicy-analyze executable from jar */
+        InputStream is = this.getClass().getResourceAsStream("/sepolicy-analyze");
+        File execFile = File.createTempFile("sepolicy-analyze", ".tmp");
+        FileOutputStream os = new FileOutputStream(execFile);
+        int rByte = 0;
+        while ((rByte = is.read()) != -1) {
+            os.write(rByte);
+        }
+        os.flush();
+        os.close();
+        execFile.setExecutable(true);
+
+        /* obtain sepolicy file from running device */
+        File policyFile = File.createTempFile("sepolicy", ".tmp");
+        mDevice.executeAdbCommand("pull", "/sys/fs/selinux/policy", policyFile.getAbsolutePath());
+
+        /* run sepolicy-analyze permissive check on policy file */
+        ProcessBuilder pb = new ProcessBuilder(execFile.getAbsolutePath(), "-p", "-P",
+                policyFile.getAbsolutePath());
+        pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
+        pb.redirectErrorStream(true);
+        Process p = pb.start();
+        p.waitFor();
+        BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
+        String line;
+        StringBuilder errorString = new StringBuilder();
+        while ((line = result.readLine()) != null) {
+            errorString.append(line);
+            errorString.append("\n");
+        }
+
+        /* clean up and check condition */
+        execFile.delete();
+        policyFile.delete();
+        assertTrue("The following SELinux domains were found to be in permissive mode:\n"
+                   + errorString, errorString.length() == 0);
+    }
+}
diff --git a/hostsidetests/theme/Android.mk b/hostsidetests/theme/Android.mk
index 8e283a3..71027c7 100644
--- a/hostsidetests/theme/Android.mk
+++ b/hostsidetests/theme/Android.mk
@@ -25,7 +25,7 @@
 # Must match the package name in CtsTestCaseList.mk
 LOCAL_MODULE := CtsThemeHostTestCases
 
-LOCAL_JAVA_LIBRARIES := cts-tradefed ddmlib-prebuilt tradefed-prebuilt
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
 
 LOCAL_CTS_TEST_PACKAGE := android.host.theme
 
diff --git a/hostsidetests/theme/app/Android.mk b/hostsidetests/theme/app/Android.mk
index a8d331d..1be2983 100644
--- a/hostsidetests/theme/app/Android.mk
+++ b/hostsidetests/theme/app/Android.mk
@@ -26,13 +26,13 @@
 
 LOCAL_PROGUARD_ENABLED := disabled
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 #Flags to tell the Android Asset Packaging Tool not to strip for some densities
 LOCAL_AAPT_FLAGS = -c land -c xx_YY -c cs -c small -c normal -c large -c xlarge \
- -c 640dpi -c 480dpi -c 400dpi -c 320dpi -c 240dpi -c 213dpi -c 160dpi -c 120dpi
+ -c 640dpi -c 560dpi -c 480dpi -c 400dpi -c 320dpi -c 240dpi -c 213dpi -c 160dpi -c 120dpi
 
 LOCAL_PACKAGE_NAME := CtsThemeDeviceApp
 
diff --git a/hostsidetests/theme/app/AndroidManifest.xml b/hostsidetests/theme/app/AndroidManifest.xml
index 0add2da..2f8fb3b 100755
--- a/hostsidetests/theme/app/AndroidManifest.xml
+++ b/hostsidetests/theme/app/AndroidManifest.xml
@@ -41,7 +41,7 @@
     </application>
 
     <!--  self-instrumenting test package. -->
-    <instrumentation android:name="android.test.InstrumentationTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="android.theme.app"
                      android:label="Generates Theme reference images"/>
 
diff --git a/hostsidetests/theme/app/res/drawable-560dpi/display_info.png b/hostsidetests/theme/app/res/drawable-560dpi/display_info.png
new file mode 100644
index 0000000..babe0da
--- /dev/null
+++ b/hostsidetests/theme/app/res/drawable-560dpi/display_info.png
Binary files differ
diff --git a/hostsidetests/theme/app/src/android/theme/app/DisplayInfoActivity.java b/hostsidetests/theme/app/src/android/theme/app/DisplayInfoActivity.java
index 12504c1..f263eef 100644
--- a/hostsidetests/theme/app/src/android/theme/app/DisplayInfoActivity.java
+++ b/hostsidetests/theme/app/src/android/theme/app/DisplayInfoActivity.java
@@ -68,6 +68,9 @@
             case DisplayMetrics.DENSITY_XXHIGH:
                 return "xxhdpi";
 
+            case DisplayMetrics.DENSITY_560:
+                return "560dpi";
+
             case DisplayMetrics.DENSITY_XXXHIGH:
                 return "xxxhdpi";
 
diff --git a/hostsidetests/theme/app/src/android/theme/app/HoloDeviceActivity.java b/hostsidetests/theme/app/src/android/theme/app/HoloDeviceActivity.java
index ab81dbd..3939979 100644
--- a/hostsidetests/theme/app/src/android/theme/app/HoloDeviceActivity.java
+++ b/hostsidetests/theme/app/src/android/theme/app/HoloDeviceActivity.java
@@ -157,7 +157,7 @@
 
         @Override
         protected void onPostExecute(Boolean success) {
-            Log.i(TAG, success ? "OKAY" : "ERROR");
+            Log.i(TAG, (success ? "OKAY" : "ERROR") + ":" + mName);
             setResult(RESULT_OK);
             finish();
         }
diff --git a/hostsidetests/theme/assets/21/400dpi.zip b/hostsidetests/theme/assets/21/400dpi.zip
new file mode 100644
index 0000000..6d62e5b
--- /dev/null
+++ b/hostsidetests/theme/assets/21/400dpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/21/560dpi.zip b/hostsidetests/theme/assets/21/560dpi.zip
new file mode 100644
index 0000000..eff363c
--- /dev/null
+++ b/hostsidetests/theme/assets/21/560dpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/21/hdpi.zip b/hostsidetests/theme/assets/21/hdpi.zip
new file mode 100644
index 0000000..9cc179c
--- /dev/null
+++ b/hostsidetests/theme/assets/21/hdpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/21/ldpi.zip b/hostsidetests/theme/assets/21/ldpi.zip
new file mode 100644
index 0000000..059bf33
--- /dev/null
+++ b/hostsidetests/theme/assets/21/ldpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/21/mdpi.zip b/hostsidetests/theme/assets/21/mdpi.zip
new file mode 100644
index 0000000..0fb0778
--- /dev/null
+++ b/hostsidetests/theme/assets/21/mdpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/21/tvdpi.zip b/hostsidetests/theme/assets/21/tvdpi.zip
new file mode 100644
index 0000000..fbe1781
--- /dev/null
+++ b/hostsidetests/theme/assets/21/tvdpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/21/xhdpi.zip b/hostsidetests/theme/assets/21/xhdpi.zip
new file mode 100644
index 0000000..de6e2e1
--- /dev/null
+++ b/hostsidetests/theme/assets/21/xhdpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/21/xxhdpi.zip b/hostsidetests/theme/assets/21/xxhdpi.zip
new file mode 100644
index 0000000..9f0d778
--- /dev/null
+++ b/hostsidetests/theme/assets/21/xxhdpi.zip
Binary files differ
diff --git a/hostsidetests/theme/src/android/theme/cts/ComparisonTask.java b/hostsidetests/theme/src/android/theme/cts/ComparisonTask.java
index aae33e7..33e67e5 100644
--- a/hostsidetests/theme/src/android/theme/cts/ComparisonTask.java
+++ b/hostsidetests/theme/src/android/theme/cts/ComparisonTask.java
@@ -49,7 +49,6 @@
 
     private final String mStoragePath;
 
-
     public ComparisonTask(ITestDevice device, File reference, String name) {
         mDevice = device;
         mReference = reference;
@@ -68,7 +67,12 @@
         try {
             generated = File.createTempFile("gen_" + mName, ".png");
 
-            mDevice.pullFile(String.format(mStoragePath, mName), generated);
+            final String remoteGenerated = String.format(mStoragePath, mName);
+            if (!mDevice.doesFileExist(remoteGenerated)) {
+                Log.logAndDisplay(LogLevel.ERROR, TAG, "File " + remoteGenerated + " have not been saved on device");
+                return false;
+            }
+            mDevice.pullFile(remoteGenerated, generated);
 
             final BufferedImage ref = ImageIO.read(mReference);
             final BufferedImage gen = ImageIO.read(generated);
@@ -80,6 +84,7 @@
                 Log.logAndDisplay(LogLevel.INFO, TAG, "Diff created: " + diff.getPath());
             }
         } catch (Exception e) {
+            Log.logAndDisplay(LogLevel.ERROR, TAG, String.format(mStoragePath, mName));
             Log.logAndDisplay(LogLevel.ERROR, TAG, e.toString());
             e.printStackTrace();
         } finally {
diff --git a/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java b/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java
index fe24bcb..90a0c72 100644
--- a/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java
+++ b/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java
@@ -17,16 +17,18 @@
 package android.theme.cts;
 
 import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.cts.util.AbiUtils;
+import com.android.cts.util.TimeoutReq;
 import com.android.ddmlib.Log;
 import com.android.ddmlib.Log.LogLevel;
 import com.android.ddmlib.IShellOutputReceiver;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
 import com.android.tradefed.testtype.IBuildReceiver;
 
-import com.android.cts.util.TimeoutReq;
-
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.InputStream;
@@ -46,7 +48,7 @@
 /**
  * Test to check the Holo theme has not been changed.
  */
-public class ThemeHostTest extends DeviceTestCase implements IBuildReceiver {
+public class ThemeHostTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
 
     private static final String TAG = ThemeHostTest.class.getSimpleName();
 
@@ -69,6 +71,8 @@
 
     private static final String STOP_CMD = String.format("am force-stop %s", PACKAGE);
 
+    private static final String HARDWARE_TYPE_CMD = "dumpsys | grep android.hardware.type";
+
     private static final String DENSITY_PROP_DEVICE = "ro.sf.lcd_density";
 
     private static final String DENSITY_PROP_EMULATOR = "qemu.sf.lcd_density";
@@ -170,6 +174,9 @@
 
     private final HashMap<String, File> mReferences = new HashMap<String, File>();
 
+    /** The ABI to use. */
+    private IAbi mAbi;
+
     /** A reference to the build. */
     private CtsBuildHelper mBuild;
 
@@ -181,6 +188,11 @@
     private ExecutorCompletionService<Boolean> mCompletionService;
 
     @Override
+    public void setAbi(IAbi abi) {
+        mAbi = abi;
+    }
+
+    @Override
     public void setBuild(IBuildInfo buildInfo) {
         // Get the build, this is used to access the APK.
         mBuild = CtsBuildHelper.createBuildHelper(buildInfo);
@@ -195,8 +207,10 @@
         mDevice.uninstallPackage(PACKAGE);
         // Get the APK from the build.
         File app = mBuild.getTestApp(APK);
+        // Get the ABI flag.
+        String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
         // Install the APK on the device.
-        mDevice.installPackage(app, false);
+        mDevice.installPackage(app, false, options);
 
         final String densityProp;
 
@@ -252,6 +266,13 @@
 
     @TimeoutReq(minutes = 60)
     public void testHoloThemes() throws Exception {
+        if (checkHardwareTypeSkipTest(
+                mDevice.executeShellCommand(HARDWARE_TYPE_CMD).trim())) {
+            Log.logAndDisplay(LogLevel.INFO, TAG, "Skipped HoloThemes test for watch and TV");
+            return;
+        }
+
+
         if (mReferences.isEmpty()) {
             Log.logAndDisplay(LogLevel.INFO, TAG,
                     "Skipped HoloThemes test due to no reference images");
@@ -263,7 +284,7 @@
             final String themeName = THEMES[i];
             for (int j = 0; j < NUM_LAYOUTS; j++) {
                 final String name = String.format("%s_%s", themeName, LAYOUTS[j]);
-                if (runCapture(i, j)) {
+                if (runCapture(i, j, name)) {
                     final File ref = mReferences.get(name + ".png");
                     if (!ref.exists()) {
                         Log.logAndDisplay(LogLevel.INFO, TAG,
@@ -284,7 +305,7 @@
         assertTrue(failures + " failures in theme test", failures == 0);
     }
 
-    private boolean runCapture(int themeId, int layoutId) throws Exception {
+    private boolean runCapture(int themeId, int layoutId, String imageName) throws Exception {
         final StringBuilder sb = new StringBuilder(START_CMD);
         sb.append(String.format(INTENT_INTEGER_EXTRA, EXTRA_THEME, themeId));
         sb.append(String.format(INTENT_INTEGER_EXTRA, EXTRA_LAYOUT, layoutId));
@@ -307,16 +328,19 @@
             while (in.hasNextLine()) {
                 final String line = in.nextLine();
                 if (line.startsWith("I/" + CLASS)) {
-                    final String s = line.split(":")[1].trim();
-                    if (s.equals("OKAY")) {
+                    final String[] lineSplit = line.split(":");
+                    final String s = lineSplit[1].trim();
+                    final String imageNameGenerated = lineSplit[2].trim();
+                    if (s.equals("OKAY") && imageNameGenerated.equals(imageName)) {
                         success = true;
                         waiting = false;
-                    } else if (s.equals("ERROR")) {
+                    } else if (s.equals("ERROR") && imageNameGenerated.equals(imageName)) {
                         success = false;
                         waiting = false;
                     }
                 }
             }
+            in.close();
         }
 
         return success;
@@ -338,10 +362,22 @@
                 return "400dpi";
             case 480:
                 return "xxhdpi";
+            case 560:
+                return "560dpi";
             case 640:
                 return "xxxhdpi";
             default:
                 return "" + density;
         }
     }
+
+    private static boolean checkHardwareTypeSkipTest(String hardwareTypeString) {
+        if (hardwareTypeString.contains("android.hardware.type.watch")) {
+            return true;
+        }
+        if (hardwareTypeString.contains("android.hardware.type.television")) {
+            return true;
+        }
+        return false;
+    }
 }
diff --git a/hostsidetests/usb/.gitignore b/hostsidetests/usb/.gitignore
new file mode 100644
index 0000000..5e56e04
--- /dev/null
+++ b/hostsidetests/usb/.gitignore
@@ -0,0 +1 @@
+/bin
diff --git a/hostsidetests/usb/Android.mk b/hostsidetests/usb/Android.mk
index 488acbb..f93dfa4 100644
--- a/hostsidetests/usb/Android.mk
+++ b/hostsidetests/usb/Android.mk
@@ -21,7 +21,7 @@
 
 LOCAL_MODULE := CtsUsbTests
 
-LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt ddmlib-prebuilt junit
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
 
 LOCAL_CTS_TEST_PACKAGE := android.usb
 
diff --git a/hostsidetests/usb/SerialTestApp/Android.mk b/hostsidetests/usb/SerialTestApp/Android.mk
index d36b98e..a8f51ad 100644
--- a/hostsidetests/usb/SerialTestApp/Android.mk
+++ b/hostsidetests/usb/SerialTestApp/Android.mk
@@ -20,8 +20,6 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/hostsidetests/usb/SerialTestApp/AndroidManifest.xml b/hostsidetests/usb/SerialTestApp/AndroidManifest.xml
index 0667d60..a75dd75 100644
--- a/hostsidetests/usb/SerialTestApp/AndroidManifest.xml
+++ b/hostsidetests/usb/SerialTestApp/AndroidManifest.xml
@@ -22,5 +22,5 @@
     </application>
     <instrumentation
         android:targetPackage="com.android.cts.usb.serialtest"
-        android:name="android.test.InstrumentationCtsTestRunner" />
+        android:name="android.support.test.runner.AndroidJUnitRunner" />
 </manifest>
diff --git a/hostsidetests/usb/src/com/android/cts/usb/TestUsbTest.java b/hostsidetests/usb/src/com/android/cts/usb/TestUsbTest.java
index f53d210..4736e51 100644
--- a/hostsidetests/usb/src/com/android/cts/usb/TestUsbTest.java
+++ b/hostsidetests/usb/src/com/android/cts/usb/TestUsbTest.java
@@ -16,48 +16,45 @@
 package com.android.cts.usb;
 
 import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.ddmlib.IDevice;
-import com.android.ddmlib.Log;
+import com.android.cts.util.AbiUtils;
 import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.ddmlib.testrunner.TestRunResult;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.IFileEntry;
 import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.result.CollectingTestListener;
-import com.android.tradefed.result.InputStreamSource;
-import com.android.tradefed.result.TestRunResult;
 import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
 import com.android.tradefed.testtype.IBuildReceiver;
 import com.android.tradefed.util.CommandResult;
 import com.android.tradefed.util.CommandStatus;
-import com.android.tradefed.util.FileUtil;
 import com.android.tradefed.util.RunUtil;
-import com.android.tradefed.util.StreamUtil;
 
-import java.io.BufferedInputStream;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 /**
  * Functional tests for usb connection
  */
-public class TestUsbTest extends DeviceTestCase implements IBuildReceiver {
+public class TestUsbTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
 
     private static final String LOG_TAG = "TestUsbTest";
-    private static final String CTS_RUNNER = "android.test.InstrumentationCtsTestRunner";
+    private static final String CTS_RUNNER = "android.support.test.runner.AndroidJUnitRunner";
     private static final String PACKAGE_NAME = "com.android.cts.usb.serialtest";
     private static final String APK_NAME="CtsUsbSerialTestApp.apk";
     private ITestDevice mDevice;
+    private IAbi mAbi;
+    private String mAbiBitness;
     private CtsBuildHelper mBuild;
 
     @Override
+    public void setAbi(IAbi abi) {
+        mAbi = abi;
+    }
+
+    @Override
     public void setBuild(IBuildInfo buildInfo) {
         mBuild = CtsBuildHelper.createBuildHelper(buildInfo);
     }
@@ -68,7 +65,8 @@
         mDevice = getDevice();
         mDevice.uninstallPackage(PACKAGE_NAME);
         File app = mBuild.getTestApp(APK_NAME);
-        mDevice.installPackage(app, false);
+        String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+        mDevice.installPackage(app, false, options);
     }
 
     @Override
diff --git a/libs/commonutil/Android.mk b/libs/commonutil/Android.mk
new file mode 100644
index 0000000..9c131b0
--- /dev/null
+++ b/libs/commonutil/Android.mk
@@ -0,0 +1,27 @@
+#
+# 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 $(call all-subdir-makefiles)
+
+# ======================================================
+# Build a static host library for the AbiUtils
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := src/com/android/cts/util/AbiUtils.java
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE := ctsabiutilslib
+include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/libs/commonutil/src/com/android/cts/util/AbiUtils.java b/libs/commonutil/src/com/android/cts/util/AbiUtils.java
new file mode 100644
index 0000000..42336f3
--- /dev/null
+++ b/libs/commonutil/src/com/android/cts/util/AbiUtils.java
@@ -0,0 +1,200 @@
+/*
+ * 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 com.android.cts.util;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Utility class for handling device ABIs
+ */
+public class AbiUtils {
+
+    /**
+     * The set of 32Bit ABIs.
+     */
+    private static final Set<String> ABIS_32BIT = new HashSet<String>();
+
+    /**
+     * The set of 64Bit ABIs.
+     */
+    private static final Set<String> ABIS_64BIT = new HashSet<String>();
+
+    /**
+     * The set of ARM ABIs.
+     */
+    private static final Set<String> ARM_ABIS = new HashSet<String>();
+
+    /**
+     * The set of Intel ABIs.
+     */
+    private static final Set<String> INTEL_ABIS = new HashSet<String>();
+
+    /**
+     * The set of Mips ABIs.
+     */
+    private static final Set<String> MIPS_ABIS = new HashSet<String>();
+
+    /**
+     * The set of ABI names which CTS supports.
+     */
+    private static final Set<String> ABIS_SUPPORTED_BY_CTS = new HashSet<String>();
+
+    /**
+     * The map of architecture to ABI.
+     */
+    private static final Map<String, Set<String>> ARCH_TO_ABIS = new HashMap<String, Set<String>>();
+    static {
+        ABIS_32BIT.add("armeabi-v7a");
+        ABIS_32BIT.add("x86");
+        ABIS_32BIT.add("mips");
+
+        ABIS_64BIT.add("arm64-v8a");
+        ABIS_64BIT.add("x86_64");
+        ABIS_64BIT.add("mips64");
+
+        ARM_ABIS.add("armeabi-v7a");
+        ARM_ABIS.add("arm64-v8a");
+
+        INTEL_ABIS.add("x86");
+        INTEL_ABIS.add("x86_64");
+
+        MIPS_ABIS.add("mips");
+        MIPS_ABIS.add("mips64");
+
+        ARCH_TO_ABIS.put("arm", ARM_ABIS);
+        ARCH_TO_ABIS.put("arm64", ARM_ABIS);
+        ARCH_TO_ABIS.put("x86", INTEL_ABIS);
+        ARCH_TO_ABIS.put("x86_64", INTEL_ABIS);
+        ARCH_TO_ABIS.put("mips", MIPS_ABIS);
+        ARCH_TO_ABIS.put("mips64", MIPS_ABIS);
+
+        ABIS_SUPPORTED_BY_CTS.addAll(ARM_ABIS);
+        ABIS_SUPPORTED_BY_CTS.addAll(INTEL_ABIS);
+        ABIS_SUPPORTED_BY_CTS.addAll(MIPS_ABIS);
+    }
+
+    /**
+     * Private constructor to avoid instantiation.
+     */
+    private AbiUtils() {}
+
+    /**
+     * Returns the set of ABIs associated with the given architecture.
+     * @param arch The architecture to look up.
+     * @return a new Set containing the ABIs.
+     */
+    public static Set<String> getAbisForArch(String arch) {
+        if (arch == null || arch.isEmpty() || !ARCH_TO_ABIS.containsKey(arch)) {
+            return getAbisSupportedByCts();
+        }
+        return new HashSet<String>(ARCH_TO_ABIS.get(arch));
+    }
+
+    /**
+     * Returns the set of ABIs supported by CTS.
+     * @return a new Set containing the supported ABIs.
+     */
+    public static Set<String> getAbisSupportedByCts() {
+        return new HashSet<String>(ABIS_SUPPORTED_BY_CTS);
+    }
+
+    /**
+     * @param abi The ABI name to test.
+     * @return true if the given ABI is supported by CTS.
+     */
+    public static boolean isAbiSupportedByCts(String abi) {
+        return ABIS_SUPPORTED_BY_CTS.contains(abi);
+    }
+
+    /**
+     * Creates a flag for the given ABI.
+     * @param abi the ABI to create the flag for.
+     * @return a string which can be add to a command sent to ADB.
+     */
+    public static String createAbiFlag(String abi) {
+        if (abi == null || abi.isEmpty() || !isAbiSupportedByCts(abi)) {
+            return "";
+        }
+        return String.format("--abi %s ", abi);
+    }
+
+    /**
+     * Creates a unique id from the given ABI and name.
+     * @param abi The ABI to use.
+     * @param name The name to use.
+     * @return a string which uniquely identifies a run.
+     */
+    public static String createId(String abi, String name) {
+        return String.format("%s %s", abi, name);
+    }
+
+    /**
+     * Parses a unique id into the ABI and name.
+     * @param id The id to parse.
+     * @return a string array containing the ABI and name.
+     */
+    public static String[] parseId(String id) {
+        if (id == null || !id.contains(" ")) {
+            return new String[] {"", ""};
+        }
+        return id.split(" ");
+    }
+
+    /**
+     * @return the test name portion of the test id.
+     *         e.g. armeabi-v7a android.mytest = android.mytest
+     */
+    public static String parseTestName(String id) {
+        return parseId(id)[1];
+    }
+
+    /**
+     * @return the abi portion of the test id.
+     *         e.g. armeabi-v7a android.mytest = armeabi-v7a
+     */
+    public static String parseAbi(String id) {
+        return parseId(id)[0];
+    }
+
+    /**
+     * @param name The name of the ABI.
+     * @return The bitness of the ABI with the given name
+     */
+    public static String getBitness(String name) {
+        return ABIS_32BIT.contains(name) ? "32" : "64";
+    }
+
+    /**
+     * @param abilistString A comma separated string containing abis.
+     * @return A List of Strings containing valid ABIs.
+     */
+    public static Set<String> parseAbiList(String unsupportedAbiDescription) {
+        Set<String> abiSet = new HashSet<>();
+        String[] descSegments = unsupportedAbiDescription.split(":");
+        if (descSegments.length == 2) {
+            for (String abi : descSegments[1].split(",")) {
+                String trimmedAbi = abi.trim();
+                if (isAbiSupportedByCts(trimmedAbi)) {
+                    abiSet.add(trimmedAbi);
+                }
+            }
+        }
+        return abiSet;
+    }
+}
diff --git a/libs/commonutil/src/com/android/cts/util/CtsException.java b/libs/commonutil/src/com/android/cts/util/CtsException.java
deleted file mode 100644
index 7e79590..0000000
--- a/libs/commonutil/src/com/android/cts/util/CtsException.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.util;
-
-/**
- * Exception throw by CTS test to pass the result to host
- * This should not be thrown by test app unless the result is complete.
- */
-@SuppressWarnings("serial")
-public class CtsException extends Exception {
-    public CtsException(String message) {
-        super(message);
-    }
-}
diff --git a/libs/commonutil/src/com/android/cts/util/ReportLog.java b/libs/commonutil/src/com/android/cts/util/ReportLog.java
index 115cec6..56b431a 100644
--- a/libs/commonutil/src/com/android/cts/util/ReportLog.java
+++ b/libs/commonutil/src/com/android/cts/util/ReportLog.java
@@ -43,22 +43,19 @@
     /**
      * print array of values to output log
      */
-    public void printArray(String message, double[] values, ResultType type,
-            ResultUnit unit) {
+    public void printArray(String message, double[] values, ResultType type, ResultUnit unit) {
         doPrintArray(message, values, type, unit);
     }
 
     /**
      * Print a value to output log
      */
-    public void printValue(String message, double value, ResultType type,
-            ResultUnit unit) {
+    public void printValue(String message, double value, ResultType type, ResultUnit unit) {
         double[] vals = { value };
         doPrintArray(message, vals, type, unit);
     }
 
-    private void doPrintArray(String message, double[] values, ResultType type,
-    ResultUnit unit) {
+    private void doPrintArray(String message, double[] values, ResultType type, ResultUnit unit) {
         StringBuilder builder = new StringBuilder();
         // note mDepth + 1 as this function will be called by printVaue or printArray
         // and we need caller of printValue / printArray
@@ -104,17 +101,19 @@
     /**
      * For standard report summary without target value.
      * Note that this function will not fail as there is no target.
-     * @param messsage
+     * @param message
      * @param value
      * @param type type of the value
      * @param unit unit of the data
      */
-    public void printSummary(String message, double value, ResultType type,
-            ResultUnit unit) {
+    public void printSummary(String message, double value, ResultType type, ResultUnit unit) {
         mSummary = message + LOG_ELEM_SEPARATOR + " " + LOG_ELEM_SEPARATOR + type.getXmlString() +
                 LOG_ELEM_SEPARATOR + unit.getXmlString() + LOG_ELEM_SEPARATOR + value;
     }
 
+    /**
+     * @return a string representation of this report.
+     */
     protected String generateReport() {
         if ((mSummary == null) && mMessages.isEmpty()) {
             // just return empty string
diff --git a/libs/deviceutil/Android.mk b/libs/deviceutil/Android.mk
index 1b7db18..8c81ee4 100644
--- a/libs/deviceutil/Android.mk
+++ b/libs/deviceutil/Android.mk
@@ -20,12 +20,14 @@
     $(call all-java-files-under, src) \
     $(call all-java-files-under, ../commonutil/src)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 
 LOCAL_MODULE_TAGS := optional
 
 LOCAL_MODULE := ctsdeviceutil
 
+LOCAL_SDK_VERSION := current
+
 include $(BUILD_STATIC_JAVA_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libs/deviceutil/jni/Android.mk b/libs/deviceutil/jni/Android.mk
new file mode 100644
index 0000000..b801a4d
--- /dev/null
+++ b/libs/deviceutil/jni/Android.mk
@@ -0,0 +1,32 @@
+# Copyright (C) 2010 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libcts_jni
+
+# Don't include this package in any configuration by default.
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := \
+		CtsJniOnLoad.cpp \
+		android_cts_FileUtils.cpp
+
+LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
+
+LOCAL_SHARED_LIBRARIES := libnativehelper liblog libdl
+
+include $(BUILD_SHARED_LIBRARY)
\ No newline at end of file
diff --git a/libs/deviceutil/jni/CtsJniOnLoad.cpp b/libs/deviceutil/jni/CtsJniOnLoad.cpp
new file mode 100644
index 0000000..abf8e01
--- /dev/null
+++ b/libs/deviceutil/jni/CtsJniOnLoad.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2010 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 <jni.h>
+#include <stdio.h>
+
+extern int register_android_cts_FileUtils(JNIEnv*);
+
+jint JNI_OnLoad(JavaVM *vm, void *reserved) {
+    JNIEnv *env = NULL;
+
+    if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
+        return JNI_ERR;
+    }
+
+    if (register_android_cts_FileUtils(env)) {
+      return JNI_ERR;
+    }
+
+    return JNI_VERSION_1_4;
+}
diff --git a/libs/deviceutil/jni/android_cts_FileUtils.cpp b/libs/deviceutil/jni/android_cts_FileUtils.cpp
new file mode 100644
index 0000000..91b74bf
--- /dev/null
+++ b/libs/deviceutil/jni/android_cts_FileUtils.cpp
@@ -0,0 +1,145 @@
+/*
+ * 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.
+ */
+
+#include <grp.h>
+#include <jni.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <assert.h>
+
+static jclass gFileStatusClass;
+static jfieldID gFileStatusDevFieldID;
+static jfieldID gFileStatusInoFieldID;
+static jfieldID gFileStatusModeFieldID;
+static jfieldID gFileStatusNlinkFieldID;
+static jfieldID gFileStatusUidFieldID;
+static jfieldID gFileStatusGidFieldID;
+static jfieldID gFileStatusSizeFieldID;
+static jfieldID gFileStatusBlksizeFieldID;
+static jfieldID gFileStatusBlocksFieldID;
+static jfieldID gFileStatusAtimeFieldID;
+static jfieldID gFileStatusMtimeFieldID;
+static jfieldID gFileStatusCtimeFieldID;
+
+/*
+ * Native methods used by
+ * cts/libs/deviceutil/src/android/cts/util/FileUtils.java
+ *
+ * Copied from hidden API: frameworks/base/core/jni/android_FileUtils.cpp
+ */
+
+jboolean android_cts_FileUtils_getFileStatus(JNIEnv* env, jobject thiz,
+        jstring path, jobject fileStatus, jboolean statLinks)
+{
+    const char* pathStr = env->GetStringUTFChars(path, NULL);
+    jboolean ret = false;
+    struct stat s;
+
+    int res = statLinks == true ? lstat(pathStr, &s) : stat(pathStr, &s);
+
+    if (res == 0) {
+        ret = true;
+        if (fileStatus != NULL) {
+            env->SetIntField(fileStatus, gFileStatusDevFieldID, s.st_dev);
+            env->SetIntField(fileStatus, gFileStatusInoFieldID, s.st_ino);
+            env->SetIntField(fileStatus, gFileStatusModeFieldID, s.st_mode);
+            env->SetIntField(fileStatus, gFileStatusNlinkFieldID, s.st_nlink);
+            env->SetIntField(fileStatus, gFileStatusUidFieldID, s.st_uid);
+            env->SetIntField(fileStatus, gFileStatusGidFieldID, s.st_gid);
+            env->SetLongField(fileStatus, gFileStatusSizeFieldID, s.st_size);
+            env->SetIntField(fileStatus, gFileStatusBlksizeFieldID, s.st_blksize);
+            env->SetLongField(fileStatus, gFileStatusBlocksFieldID, s.st_blocks);
+            env->SetLongField(fileStatus, gFileStatusAtimeFieldID, s.st_atime);
+            env->SetLongField(fileStatus, gFileStatusMtimeFieldID, s.st_mtime);
+            env->SetLongField(fileStatus, gFileStatusCtimeFieldID, s.st_ctime);
+        }
+    }
+
+    env->ReleaseStringUTFChars(path, pathStr);
+
+    return ret;
+}
+
+jstring android_cts_FileUtils_getUserName(JNIEnv* env, jobject thiz,
+        jint uid)
+{
+    struct passwd *pwd = getpwuid(uid);
+    return env->NewStringUTF(pwd->pw_name);
+}
+
+jstring android_cts_FileUtils_getGroupName(JNIEnv* env, jobject thiz,
+        jint gid)
+{
+    struct group *grp = getgrgid(gid);
+    return env->NewStringUTF(grp->gr_name);
+}
+
+jint android_cts_FileUtils_setPermissions(JNIEnv* env, jobject clazz,
+        jstring file, jint mode)
+{
+    const char *fileStr = env->GetStringUTFChars(file, NULL);
+    if (fileStr == NULL) {
+        return -1;
+    }
+
+    if (strlen(fileStr) <= 0) {
+        env->ReleaseStringUTFChars(file, fileStr);
+        return ENOENT;
+    }
+
+    jint returnValue = chmod(fileStr, mode) == 0 ? 0 : errno;
+    env->ReleaseStringUTFChars(file, fileStr);
+    return returnValue;
+}
+
+static JNINativeMethod gMethods[] = {
+    {  "getFileStatus", "(Ljava/lang/String;Landroid/cts/util/FileUtils$FileStatus;Z)Z",
+            (void *) android_cts_FileUtils_getFileStatus  },
+    {  "getUserName", "(I)Ljava/lang/String;",
+            (void *) android_cts_FileUtils_getUserName  },
+    {  "getGroupName", "(I)Ljava/lang/String;",
+            (void *) android_cts_FileUtils_getGroupName  },
+    {  "setPermissions", "(Ljava/lang/String;I)I",
+            (void *) android_cts_FileUtils_setPermissions },
+};
+
+int register_android_cts_FileUtils(JNIEnv* env)
+{
+    jclass clazz = env->FindClass("android/cts/util/FileUtils");
+    assert(clazz != null);
+
+    gFileStatusClass = env->FindClass("android/cts/util/FileUtils$FileStatus");
+    assert(gFileStatusClass != null);
+    gFileStatusDevFieldID = env->GetFieldID(gFileStatusClass, "dev", "I");
+    gFileStatusInoFieldID = env->GetFieldID(gFileStatusClass, "ino", "I");
+    gFileStatusModeFieldID = env->GetFieldID(gFileStatusClass, "mode", "I");
+    gFileStatusNlinkFieldID = env->GetFieldID(gFileStatusClass, "nlink", "I");
+    gFileStatusUidFieldID = env->GetFieldID(gFileStatusClass, "uid", "I");
+    gFileStatusGidFieldID = env->GetFieldID(gFileStatusClass, "gid", "I");
+    gFileStatusSizeFieldID = env->GetFieldID(gFileStatusClass, "size", "J");
+    gFileStatusBlksizeFieldID = env->GetFieldID(gFileStatusClass, "blksize", "I");
+    gFileStatusBlocksFieldID = env->GetFieldID(gFileStatusClass, "blocks", "J");
+    gFileStatusAtimeFieldID = env->GetFieldID(gFileStatusClass, "atime", "J");
+    gFileStatusMtimeFieldID = env->GetFieldID(gFileStatusClass, "mtime", "J");
+    gFileStatusCtimeFieldID = env->GetFieldID(gFileStatusClass, "ctime", "J");
+
+    return env->RegisterNatives(clazz, gMethods,
+            sizeof(gMethods) / sizeof(JNINativeMethod));
+}
diff --git a/libs/deviceutil/src/android/app/cts/CTSResult.java b/libs/deviceutil/src/android/app/cts/CTSResult.java
deleted file mode 100644
index ae4dbfd..0000000
--- a/libs/deviceutil/src/android/app/cts/CTSResult.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2008 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.app.cts;
-
-public interface CTSResult {
-    public static final int RESULT_OK = 1;
-    public static final int RESULT_FAIL = 2;
-    public void setResult(int resultCode);
-}
diff --git a/libs/deviceutil/src/android/cts/util/CTSResult.java b/libs/deviceutil/src/android/cts/util/CTSResult.java
new file mode 100644
index 0000000..c780f57
--- /dev/null
+++ b/libs/deviceutil/src/android/cts/util/CTSResult.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2008 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.cts.util;
+
+public interface CTSResult {
+    public static final int RESULT_OK = 1;
+    public static final int RESULT_FAIL = 2;
+    public void setResult(int resultCode);
+}
diff --git a/libs/deviceutil/src/android/cts/util/DeviceReportLog.java b/libs/deviceutil/src/android/cts/util/DeviceReportLog.java
index b707fc8..63b07b7 100644
--- a/libs/deviceutil/src/android/cts/util/DeviceReportLog.java
+++ b/libs/deviceutil/src/android/cts/util/DeviceReportLog.java
@@ -16,19 +16,24 @@
 
 package android.cts.util;
 
-import com.android.cts.util.ReportLog;
-
 import android.app.Instrumentation;
 import android.os.Bundle;
 import android.util.Log;
 
+import com.android.cts.util.ReportLog;
+
 public class DeviceReportLog extends ReportLog {
     private static final String TAG = "DeviceCtsReport";
-    private static final String CTS_RESULT = "CTS_RESULT";
+    private static final String CTS_RESULT_KEY = "CTS_TEST_RESULT";
     private static final int INST_STATUS_IN_PROGRESS = 2;
+    private static final int BASE_DEPTH = 4;
 
-    DeviceReportLog() {
-        mDepth = 4;
+    public DeviceReportLog() {
+        this(0);
+    }
+
+    public DeviceReportLog(int depth) {
+        mDepth = BASE_DEPTH + depth;
     }
 
     @Override
@@ -41,7 +46,7 @@
         String report = generateReport();
         if (!report.equals("")) {
             Bundle output = new Bundle();
-            output.putString(CTS_RESULT, report);
+            output.putString(CTS_RESULT_KEY, report);
             instrumentation.sendStatus(INST_STATUS_IN_PROGRESS, output);
         }
     }
diff --git a/libs/deviceutil/src/android/cts/util/FileCopyHelper.java b/libs/deviceutil/src/android/cts/util/FileCopyHelper.java
new file mode 100644
index 0000000..e84e920
--- /dev/null
+++ b/libs/deviceutil/src/android/cts/util/FileCopyHelper.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2009 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.cts.util;
+
+import android.content.Context;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+
+/**
+ * The Class FileCopyHelper is used to copy files from resources to the
+ * application directory and responsible for deleting the files.
+ *
+ * @see MediaStore_VideoTest
+ * @see MediaStore_Images_MediaTest
+ * @see MediaStore_Images_ThumbnailsTest
+ */
+public class FileCopyHelper {
+    /** The context. */
+    private Context mContext;
+
+    /** The files added. */
+    private ArrayList<String> mFilesList;
+
+    /**
+     * Instantiates a new file copy helper.
+     *
+     * @param context the context
+     */
+    public FileCopyHelper(Context context) {
+        mContext = context;
+        mFilesList = new ArrayList<String>();
+    }
+
+    /**
+     * Copy the file from the resources with a filename .
+     *
+     * @param resId the res id
+     * @param fileName the file name
+     *
+     * @return the absolute path of the destination file
+     * @throws IOException
+     */
+    public String copy(int resId, String fileName) throws IOException {
+        InputStream source = mContext.getResources().openRawResource(resId);
+        OutputStream target = mContext.openFileOutput(fileName, Context.MODE_WORLD_READABLE);
+        copyFile(source, target);
+        mFilesList.add(fileName);
+        return mContext.getFileStreamPath(fileName).getAbsolutePath();
+    }
+
+    public void copyToExternalStorage(int resId, File path) throws IOException {
+        InputStream source = mContext.getResources().openRawResource(resId);
+        OutputStream target = new FileOutputStream(path);
+        copyFile(source, target);
+    }
+
+    private void copyFile(InputStream source, OutputStream target) throws IOException {
+        try {
+            byte[] buffer = new byte[1024];
+            for (int len = source.read(buffer); len > 0; len = source.read(buffer)) {
+                target.write(buffer, 0, len);
+            }
+        } finally {
+            if (source != null) {
+                source.close();
+            }
+            if (target != null) {
+                target.close();
+            }
+        }
+    }
+
+    /**
+     * Delete all the files copied by the helper.
+     */
+    public void clear(){
+        for (String path : mFilesList) {
+            mContext.deleteFile(path);
+        }
+    }
+}
diff --git a/libs/deviceutil/src/android/cts/util/FileUtils.java b/libs/deviceutil/src/android/cts/util/FileUtils.java
new file mode 100644
index 0000000..055f2d6
--- /dev/null
+++ b/libs/deviceutil/src/android/cts/util/FileUtils.java
@@ -0,0 +1,163 @@
+/*
+ * 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.
+ */
+
+package android.cts.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/** Bits and pieces copied from hidden API of android.os.FileUtils. */
+public class FileUtils {
+
+    public static final int S_IFMT  = 0170000;
+    public static final int S_IFSOCK = 0140000;
+    public static final int S_IFLNK = 0120000;
+    public static final int S_IFREG = 0100000;
+    public static final int S_IFBLK = 0060000;
+    public static final int S_IFDIR = 0040000;
+    public static final int S_IFCHR = 0020000;
+    public static final int S_IFIFO = 0010000;
+
+    public static final int S_ISUID = 0004000;
+    public static final int S_ISGID = 0002000;
+    public static final int S_ISVTX = 0001000;
+
+    public static final int S_IRWXU = 00700;
+    public static final int S_IRUSR = 00400;
+    public static final int S_IWUSR = 00200;
+    public static final int S_IXUSR = 00100;
+
+    public static final int S_IRWXG = 00070;
+    public static final int S_IRGRP = 00040;
+    public static final int S_IWGRP = 00020;
+    public static final int S_IXGRP = 00010;
+
+    public static final int S_IRWXO = 00007;
+    public static final int S_IROTH = 00004;
+    public static final int S_IWOTH = 00002;
+    public static final int S_IXOTH = 00001;
+
+    static {
+        System.loadLibrary("cts_jni");
+    }
+
+    public static class FileStatus {
+
+        public int dev;
+        public int ino;
+        public int mode;
+        public int nlink;
+        public int uid;
+        public int gid;
+        public int rdev;
+        public long size;
+        public int blksize;
+        public long blocks;
+        public long atime;
+        public long mtime;
+        public long ctime;
+
+        public boolean hasModeFlag(int flag) {
+            if (((S_IRWXU | S_IRWXG | S_IRWXO) & flag) != flag) {
+                throw new IllegalArgumentException("Inappropriate flag " + flag);
+            }
+            return (mode & flag) == flag;
+        }
+
+        public boolean isOfType(int type) {
+            if ((type & S_IFMT) != type) {
+                throw new IllegalArgumentException("Unknown type " + type);
+            }
+            return (mode & S_IFMT) == type;
+        }
+    }
+
+    /**
+     * @param path of the file to stat
+     * @param status object to set the fields on
+     * @param statLinks or don't stat links (lstat vs stat)
+     * @return whether or not we were able to stat the file
+     */
+    public native static boolean getFileStatus(String path, FileStatus status, boolean statLinks);
+
+    public native static String getUserName(int uid);
+
+    public native static String getGroupName(int gid);
+
+    public native static int setPermissions(String file, int mode);
+
+    /**
+     * Copy data from a source stream to destFile.
+     * Return true if succeed, return false if failed.
+     */
+    public static boolean copyToFile(InputStream inputStream, File destFile) {
+        try {
+            if (destFile.exists()) {
+                destFile.delete();
+            }
+            FileOutputStream out = new FileOutputStream(destFile);
+            try {
+                byte[] buffer = new byte[4096];
+                int bytesRead;
+                while ((bytesRead = inputStream.read(buffer)) >= 0) {
+                    out.write(buffer, 0, bytesRead);
+                }
+            } finally {
+                out.flush();
+                try {
+                    out.getFD().sync();
+                } catch (IOException e) {
+                }
+                out.close();
+            }
+            return true;
+        } catch (IOException e) {
+            return false;
+        }
+    }
+
+    public static void createFile(File file, int numBytes) throws IOException {
+        File parentFile = file.getParentFile();
+        if (parentFile != null) {
+            parentFile.mkdirs();
+        }
+        byte[] buffer = new byte[numBytes];
+        FileOutputStream output = new FileOutputStream(file);
+        try {
+            output.write(buffer);
+        } finally {
+            output.close();
+        }
+    }
+
+    public static byte[] readInputStreamFully(InputStream is) {
+        ByteArrayOutputStream os = new ByteArrayOutputStream();
+        byte[] buffer = new byte[32768];
+        int count;
+        try {
+            while ((count = is.read(buffer)) != -1) {
+                os.write(buffer, 0, count);
+            }
+            is.close();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        return os.toByteArray();
+    }
+}
diff --git a/libs/deviceutil/src/android/cts/util/IBinderParcelable.java b/libs/deviceutil/src/android/cts/util/IBinderParcelable.java
new file mode 100644
index 0000000..c80716e
--- /dev/null
+++ b/libs/deviceutil/src/android/cts/util/IBinderParcelable.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2009 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.cts.util;
+
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class IBinderParcelable implements Parcelable {
+    public IBinder binder;
+
+    public IBinderParcelable(IBinder source) {
+        binder = source;
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeStrongBinder(binder);
+    }
+
+    public static final Parcelable.Creator<IBinderParcelable>
+        CREATOR = new Parcelable.Creator<IBinderParcelable>() {
+
+        public IBinderParcelable createFromParcel(Parcel source) {
+            return new IBinderParcelable(source);
+        }
+
+        public IBinderParcelable[] newArray(int size) {
+            return new IBinderParcelable[size];
+        }
+    };
+
+    private IBinderParcelable(Parcel source) {
+        binder = source.readStrongBinder();
+    }
+}
diff --git a/libs/deviceutil/src/android/cts/util/NullWebViewUtils.java b/libs/deviceutil/src/android/cts/util/NullWebViewUtils.java
new file mode 100644
index 0000000..e1b23f7
--- /dev/null
+++ b/libs/deviceutil/src/android/cts/util/NullWebViewUtils.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2010 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.cts.util;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+/**
+ * Utilities to enable the android.webkit.* CTS tests (and others that rely on a functioning
+ * android.webkit.WebView implementation) to determine whether a functioning WebView is present
+ * on the device or not.
+ *
+ * Test cases that require android.webkit.* classes should wrap their first usage of WebView in a
+ * try catch block, and pass any exception that is thrown to
+ * NullWebViewUtils.determineIfWebViewAvailable. The return value of
+ * NullWebViewUtils.isWebViewAvailable will then determine if the test should expect to be able to
+ * use a WebView.
+ */
+public class NullWebViewUtils {
+
+    private static boolean sWebViewUnavailable;
+
+    /**
+     * @param context Current Activity context, used to query the PackageManager.
+     * @param t       An exception thrown by trying to invoke android.webkit.* APIs.
+     */
+    public static void determineIfWebViewAvailable(Context context, Throwable t) {
+        sWebViewUnavailable = !hasWebViewFeature(context) && checkCauseWasUnsupportedOperation(t);
+    }
+
+    /**
+     * After calling determineIfWebViewAvailable, this returns whether a WebView is available on the
+     * device and wheter the test can rely on it.
+     * @return True iff. PackageManager determined that there is no WebView on the device and the
+     *         exception thrown from android.webkit.* was UnsupportedOperationException.
+     */
+    public static boolean isWebViewAvailable() {
+        return !sWebViewUnavailable;
+    }
+
+    private static boolean hasWebViewFeature(Context context) {
+        // Query the system property that determins if there is a functional WebView on the device.
+        PackageManager pm = context.getPackageManager();
+        return pm.hasSystemFeature(PackageManager.FEATURE_WEBVIEW);
+    }
+
+    private static boolean checkCauseWasUnsupportedOperation(Throwable t) {
+        if (t == null) return false;
+        while (t.getCause() != null) {
+            t = t.getCause();
+        }
+        return t instanceof UnsupportedOperationException;
+    }
+
+    /**
+     * Some CTS tests (by design) first use android.webkit.* from a background thread. This helper
+     * allows the test to catch the UnsupportedOperationException from that background thread, and
+     * then query the result from the test main thread.
+     */
+    public static class NullWebViewFromThreadExceptionHandler
+            implements Thread.UncaughtExceptionHandler {
+        private Throwable mPendingException;
+
+        @Override
+        public void uncaughtException(Thread t, Throwable e) {
+            mPendingException = e;
+        }
+
+        public boolean isWebViewAvailable(Context context) {
+            return hasWebViewFeature(context) ||
+                    !checkCauseWasUnsupportedOperation(mPendingException);
+        }
+    }
+}
\ No newline at end of file
diff --git a/libs/deviceutil/src/android/cts/util/ReadElf.java b/libs/deviceutil/src/android/cts/util/ReadElf.java
new file mode 100644
index 0000000..559cbd0
--- /dev/null
+++ b/libs/deviceutil/src/android/cts/util/ReadElf.java
@@ -0,0 +1,494 @@
+/*
+ * 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.
+ */
+
+package android.cts.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A poor man's implementation of the readelf command. This program is designed
+ * to parse ELF (Executable and Linkable Format) files.
+ */
+public class ReadElf implements AutoCloseable {
+    /** The magic values for the ELF identification. */
+    private static final byte[] ELFMAG = {
+            (byte) 0x7F, (byte) 'E', (byte) 'L', (byte) 'F', };
+
+    private static final int EI_NIDENT = 16;
+
+    private static final int EI_CLASS = 4;
+    private static final int EI_DATA = 5;
+
+    private static final int EM_386 = 3;
+    private static final int EM_MIPS = 8;
+    private static final int EM_ARM = 40;
+    private static final int EM_X86_64 = 62;
+    // http://en.wikipedia.org/wiki/Qualcomm_Hexagon
+    private static final int EM_QDSP6 = 164;
+    private static final int EM_AARCH64 = 183;
+
+    private static final int ELFCLASS32 = 1;
+    private static final int ELFCLASS64 = 2;
+
+    private static final int ELFDATA2LSB = 1;
+    private static final int ELFDATA2MSB = 2;
+
+    private static final int EV_CURRENT = 1;
+
+    private static final long PT_LOAD = 1;
+
+    private static final int SHT_SYMTAB = 2;
+    private static final int SHT_STRTAB = 3;
+    private static final int SHT_DYNAMIC = 6;
+    private static final int SHT_DYNSYM = 11;
+
+    public static class Symbol {
+        public static final int STB_LOCAL = 0;
+        public static final int STB_GLOBAL = 1;
+        public static final int STB_WEAK = 2;
+        public static final int STB_LOPROC = 13;
+        public static final int STB_HIPROC = 15;
+
+        public static final int STT_NOTYPE = 0;
+        public static final int STT_OBJECT = 1;
+        public static final int STT_FUNC = 2;
+        public static final int STT_SECTION = 3;
+        public static final int STT_FILE = 4;
+        public static final int STT_COMMON = 5;
+        public static final int STT_TLS = 6;
+
+        public final String name;
+        public final int bind;
+        public final int type;
+
+        Symbol(String name, int st_info) {
+            this.name = name;
+            this.bind = (st_info >> 4) & 0x0F;
+            this.type = st_info & 0x0F;
+        }
+
+        @Override
+        public String toString() {
+            return "Symbol[" + name + "," + toBind() + "," + toType() + "]";
+        }
+
+        private String toBind() {
+            switch (bind) {
+                case STB_LOCAL:
+                    return "LOCAL";
+                case STB_GLOBAL:
+                    return "GLOBAL";
+                case STB_WEAK:
+                    return "WEAK";
+            }
+            return "STB_??? (" + bind + ")";
+        }
+
+        private String toType() {
+            switch (type) {
+                case STT_NOTYPE:
+                    return "NOTYPE";
+                case STT_OBJECT:
+                    return "OBJECT";
+                case STT_FUNC:
+                    return "FUNC";
+                case STT_SECTION:
+                    return "SECTION";
+                case STT_FILE:
+                    return "FILE";
+                case STT_COMMON:
+                    return "COMMON";
+                case STT_TLS:
+                    return "TLS";
+            }
+            return "STT_??? (" + type + ")";
+        }
+    }
+
+    private final String mPath;
+    private final RandomAccessFile mFile;
+    private final byte[] mBuffer = new byte[512];
+    private int mEndian;
+    private boolean mIsDynamic;
+    private boolean mIsPIE;
+    private int mType;
+    private int mAddrSize;
+
+    /** Symbol Table offset */
+    private long mSymTabOffset;
+
+    /** Symbol Table size */
+    private long mSymTabSize;
+
+    /** Dynamic Symbol Table offset */
+    private long mDynSymOffset;
+
+    /** Dynamic Symbol Table size */
+    private long mDynSymSize;
+
+    /** Section Header String Table offset */
+    private long mShStrTabOffset;
+
+    /** Section Header String Table size */
+    private long mShStrTabSize;
+
+    /** String Table offset */
+    private long mStrTabOffset;
+
+    /** String Table size */
+    private long mStrTabSize;
+
+    /** Dynamic String Table offset */
+    private long mDynStrOffset;
+
+    /** Dynamic String Table size */
+    private long mDynStrSize;
+
+    /** Symbol Table symbol names */
+    private Map<String, Symbol> mSymbols;
+
+    /** Dynamic Symbol Table symbol names */
+    private Map<String, Symbol> mDynamicSymbols;
+
+    public static ReadElf read(File file) throws IOException {
+        return new ReadElf(file);
+    }
+
+    public static void main(String[] args) throws IOException {
+        for (String arg : args) {
+            ReadElf re = new ReadElf(new File(arg));
+            re.getSymbol("x");
+            re.getDynamicSymbol("x");
+            re.close();
+        }
+    }
+
+    public boolean isDynamic() {
+        return mIsDynamic;
+    }
+
+    public int getType() {
+        return mType;
+    }
+
+    public boolean isPIE() {
+        return mIsPIE;
+    }
+
+    private ReadElf(File file) throws IOException {
+        mPath = file.getPath();
+        mFile = new RandomAccessFile(file, "r");
+
+        if (mFile.length() < EI_NIDENT) {
+            throw new IllegalArgumentException("Too small to be an ELF file: " + file);
+        }
+
+        readHeader();
+    }
+
+    @Override
+    public void close() {
+        try {
+            mFile.close();
+        } catch (IOException ignored) {
+        }
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            close();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    private void readHeader() throws IOException {
+        mFile.seek(0);
+        mFile.readFully(mBuffer, 0, EI_NIDENT);
+
+        if (mBuffer[0] != ELFMAG[0] || mBuffer[1] != ELFMAG[1] ||
+                mBuffer[2] != ELFMAG[2] || mBuffer[3] != ELFMAG[3]) {
+            throw new IllegalArgumentException("Invalid ELF file: " + mPath);
+        }
+
+        int elfClass = mBuffer[EI_CLASS];
+        if (elfClass == ELFCLASS32) {
+            mAddrSize = 4;
+        } else if (elfClass == ELFCLASS64) {
+            mAddrSize = 8;
+        } else {
+            throw new IOException("Invalid ELF EI_CLASS: " + elfClass + ": " + mPath);
+        }
+
+        mEndian = mBuffer[EI_DATA];
+        if (mEndian == ELFDATA2LSB) {
+        } else if (mEndian == ELFDATA2MSB) {
+            throw new IOException("Unsupported ELFDATA2MSB file: " + mPath);
+        } else {
+            throw new IOException("Invalid ELF EI_DATA: " + mEndian + ": " + mPath);
+        }
+
+        mType = readHalf();
+
+        int e_machine = readHalf();
+        if (e_machine != EM_386 && e_machine != EM_X86_64 &&
+                e_machine != EM_AARCH64 && e_machine != EM_ARM &&
+                e_machine != EM_MIPS &&
+                e_machine != EM_QDSP6) {
+            throw new IOException("Invalid ELF e_machine: " + e_machine + ": " + mPath);
+        }
+
+        // AbiTest relies on us rejecting any unsupported combinations.
+        if ((e_machine == EM_386 && elfClass != ELFCLASS32) ||
+                (e_machine == EM_X86_64 && elfClass != ELFCLASS64) ||
+                (e_machine == EM_AARCH64 && elfClass != ELFCLASS64) ||
+                (e_machine == EM_ARM && elfClass != ELFCLASS32) ||
+                (e_machine == EM_QDSP6 && elfClass != ELFCLASS32)) {
+            throw new IOException("Invalid e_machine/EI_CLASS ELF combination: " +
+                    e_machine + "/" + elfClass + ": " + mPath);
+        }
+
+        long e_version = readWord();
+        if (e_version != EV_CURRENT) {
+            throw new IOException("Invalid e_version: " + e_version + ": " + mPath);
+        }
+
+        long e_entry = readAddr();
+
+        long ph_off = readOff();
+        long sh_off = readOff();
+
+        long e_flags = readWord();
+        int e_ehsize = readHalf();
+        int e_phentsize = readHalf();
+        int e_phnum = readHalf();
+        int e_shentsize = readHalf();
+        int e_shnum = readHalf();
+        int e_shstrndx = readHalf();
+
+        readSectionHeaders(sh_off, e_shnum, e_shentsize, e_shstrndx);
+        readProgramHeaders(ph_off, e_phnum, e_phentsize);
+    }
+
+    private void readSectionHeaders(long sh_off, int e_shnum, int e_shentsize, int e_shstrndx)
+            throws IOException {
+        // Read the Section Header String Table offset first.
+        {
+            mFile.seek(sh_off + e_shstrndx * e_shentsize);
+
+            long sh_name = readWord();
+            long sh_type = readWord();
+            long sh_flags = readX(mAddrSize);
+            long sh_addr = readAddr();
+            long sh_offset = readOff();
+            long sh_size = readX(mAddrSize);
+            // ...
+
+            if (sh_type == SHT_STRTAB) {
+                mShStrTabOffset = sh_offset;
+                mShStrTabSize = sh_size;
+            }
+        }
+
+        for (int i = 0; i < e_shnum; ++i) {
+            // Don't bother to re-read the Section Header StrTab.
+            if (i == e_shstrndx) {
+                continue;
+            }
+
+            mFile.seek(sh_off + i * e_shentsize);
+
+            long sh_name = readWord();
+            long sh_type = readWord();
+            long sh_flags = readX(mAddrSize);
+            long sh_addr = readAddr();
+            long sh_offset = readOff();
+            long sh_size = readX(mAddrSize);
+
+            if (sh_type == SHT_SYMTAB || sh_type == SHT_DYNSYM) {
+                final String symTabName = readShStrTabEntry(sh_name);
+                if (".symtab".equals(symTabName)) {
+                    mSymTabOffset = sh_offset;
+                    mSymTabSize = sh_size;
+                } else if (".dynsym".equals(symTabName)) {
+                    mDynSymOffset = sh_offset;
+                    mDynSymSize = sh_size;
+                }
+            } else if (sh_type == SHT_STRTAB) {
+                final String strTabName = readShStrTabEntry(sh_name);
+                if (".strtab".equals(strTabName)) {
+                    mStrTabOffset = sh_offset;
+                    mStrTabSize = sh_size;
+                } else if (".dynstr".equals(strTabName)) {
+                    mDynStrOffset = sh_offset;
+                    mDynStrSize = sh_size;
+                }
+            } else if (sh_type == SHT_DYNAMIC) {
+                mIsDynamic = true;
+            }
+        }
+    }
+
+    private void readProgramHeaders(long ph_off, int e_phnum, int e_phentsize) throws IOException {
+        for (int i = 0; i < e_phnum; ++i) {
+            mFile.seek(ph_off + i * e_phentsize);
+
+            long p_type = readWord();
+            if (p_type == PT_LOAD) {
+                if (mAddrSize == 8) {
+                    // Only in Elf64_phdr; in Elf32_phdr p_flags is at the end.
+                    long p_flags = readWord();
+                }
+                long p_offset = readOff();
+                long p_vaddr = readAddr();
+                // ...
+
+                if (p_vaddr == 0) {
+                    mIsPIE = true;
+                }
+            }
+        }
+    }
+
+    private HashMap<String, Symbol> readSymbolTable(long symStrOffset, long symStrSize,
+            long tableOffset, long tableSize) throws IOException {
+        HashMap<String, Symbol> result = new HashMap<String, Symbol>();
+        mFile.seek(tableOffset);
+        while (mFile.getFilePointer() < tableOffset + tableSize) {
+            long st_name = readWord();
+            int st_info;
+            if (mAddrSize == 8) {
+                st_info = readByte();
+                int st_other = readByte();
+                int st_shndx = readHalf();
+                long st_value = readAddr();
+                long st_size = readX(mAddrSize);
+            } else {
+                long st_value = readAddr();
+                long st_size = readWord();
+                st_info = readByte();
+                int st_other = readByte();
+                int st_shndx = readHalf();
+            }
+            if (st_name == 0) {
+                continue;
+            }
+
+            final String symName = readStrTabEntry(symStrOffset, symStrSize, st_name);
+            if (symName != null) {
+                Symbol s = new Symbol(symName, st_info);
+                result.put(symName, s);
+            }
+        }
+        return result;
+    }
+
+    private String readShStrTabEntry(long strOffset) throws IOException {
+        if (mShStrTabOffset == 0 || strOffset < 0 || strOffset >= mShStrTabSize) {
+            return null;
+        }
+        return readString(mShStrTabOffset + strOffset);
+    }
+
+    private String readStrTabEntry(long tableOffset, long tableSize, long strOffset)
+            throws IOException {
+        if (tableOffset == 0 || strOffset < 0 || strOffset >= tableSize) {
+            return null;
+        }
+        return readString(tableOffset + strOffset);
+    }
+
+    private int readHalf() throws IOException {
+        return (int) readX(2);
+    }
+
+    private long readWord() throws IOException {
+        return readX(4);
+    }
+
+    private long readOff() throws IOException {
+        return readX(mAddrSize);
+    }
+
+    private long readAddr() throws IOException {
+        return readX(mAddrSize);
+    }
+
+    private long readX(int byteCount) throws IOException {
+        mFile.readFully(mBuffer, 0, byteCount);
+
+        int answer = 0;
+        if (mEndian == ELFDATA2LSB) {
+            for (int i = byteCount - 1; i >= 0; i--) {
+                answer = (answer << 8) | (mBuffer[i] & 0xff);
+            }
+        } else {
+            final int N = byteCount - 1;
+            for (int i = 0; i <= N; ++i) {
+                answer = (answer << 8) | (mBuffer[i] & 0xff);
+            }
+        }
+
+        return answer;
+    }
+
+    private String readString(long offset) throws IOException {
+        long originalOffset = mFile.getFilePointer();
+        mFile.seek(offset);
+        mFile.readFully(mBuffer, 0, (int) Math.min(mBuffer.length, mFile.length() - offset));
+        mFile.seek(originalOffset);
+
+        for (int i = 0; i < mBuffer.length; ++i) {
+            if (mBuffer[i] == 0) {
+                return new String(mBuffer, 0, i);
+            }
+        }
+
+        return null;
+    }
+
+    private int readByte() throws IOException {
+        return mFile.read() & 0xff;
+    }
+
+    public Symbol getSymbol(String name) {
+        if (mSymbols == null) {
+            try {
+                mSymbols = readSymbolTable(mStrTabOffset, mStrTabSize, mSymTabOffset, mSymTabSize);
+            } catch (IOException e) {
+                return null;
+            }
+        }
+        return mSymbols.get(name);
+    }
+
+    public Symbol getDynamicSymbol(String name) {
+        if (mDynamicSymbols == null) {
+            try {
+                mDynamicSymbols = readSymbolTable(
+                        mDynStrOffset, mDynStrSize, mDynSymOffset, mDynSymSize);
+            } catch (IOException e) {
+                return null;
+            }
+        }
+        return mDynamicSymbols.get(name);
+    }
+}
diff --git a/libs/deviceutil/src/android/cts/util/TestThread.java b/libs/deviceutil/src/android/cts/util/TestThread.java
new file mode 100644
index 0000000..14df61c
--- /dev/null
+++ b/libs/deviceutil/src/android/cts/util/TestThread.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2009 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.cts.util;
+
+/**
+ * Thread class for executing a Runnable containing assertions in a separate thread.
+ * Uncaught exceptions in the Runnable are rethrown in the context of the the thread
+ * calling the <code>runTest()</code> method.
+ */
+public final class TestThread extends Thread {
+    private Throwable mThrowable;
+    private Runnable mTarget;
+
+    public TestThread(Runnable target) {
+        mTarget = target;
+    }
+
+    @Override
+    public final void run() {
+        try {
+            mTarget.run();
+        } catch (Throwable t) {
+            mThrowable = t;
+        }
+    }
+
+    /**
+     * Run the target Runnable object and wait until the test finish or throw
+     * out Exception if test fail.
+     *
+     * @param runTime
+     * @throws Throwable
+     */
+    public void runTest(long runTime) throws Throwable {
+        start();
+        joinAndCheck(runTime);
+    }
+
+    /**
+     * Get the Throwable object which is thrown when test running
+     * @return  The Throwable object
+     */
+    public Throwable getThrowable() {
+        return mThrowable;
+    }
+
+    /**
+     * Set the Throwable object which is thrown when test running
+     * @param t The Throwable object
+     */
+    public void setThrowable(Throwable t) {
+        mThrowable = t;
+    }
+
+    /**
+     * Wait for the test thread to complete and throw the stored exception if there is one.
+     *
+     * @param runTime The time to wait for the test thread to complete.
+     * @throws Throwable
+     */
+    public void joinAndCheck(long runTime) throws Throwable {
+        this.join(runTime);
+        if (this.isAlive()) {
+            this.interrupt();
+            this.join(runTime);
+            throw new Exception("Thread did not finish within allotted time.");
+        }
+        checkException();
+    }
+
+    /**
+     * Check whether there is an exception when running Runnable object.
+     * @throws Throwable
+     */
+    public void checkException() throws Throwable {
+        if (mThrowable != null) {
+            throw mThrowable;
+        }
+    }
+}
diff --git a/libs/deviceutil/src/android/cts/util/WidgetTestUtils.java b/libs/deviceutil/src/android/cts/util/WidgetTestUtils.java
new file mode 100644
index 0000000..813672e
--- /dev/null
+++ b/libs/deviceutil/src/android/cts/util/WidgetTestUtils.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2008 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.cts.util;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+
+import java.io.IOException;
+
+import junit.framework.Assert;
+
+/**
+ * The useful methods for widget test.
+ */
+public class WidgetTestUtils {
+    /**
+     * Assert that two bitmaps are equal.
+     *
+     * @param Bitmap b1 the first bitmap which needs to compare.
+     * @param Bitmap b2 the second bitmap which needs to compare.
+     */
+    public static void assertEquals(Bitmap b1, Bitmap b2) {
+        if (b1 == b2) {
+            return;
+        }
+
+        if (b1 == null || b2 == null) {
+            Assert.fail("the bitmaps are not equal");
+        }
+
+        // b1 and b2 are all not null.
+        if (b1.getWidth() != b2.getWidth() || b1.getHeight() != b2.getHeight()
+            || b1.getConfig() != b2.getConfig()) {
+            Assert.fail("the bitmaps are not equal");
+        }
+
+        int w = b1.getWidth();
+        int h = b1.getHeight();
+        int s = w * h;
+        int[] pixels1 = new int[s];
+        int[] pixels2 = new int[s];
+
+        b1.getPixels(pixels1, 0, w, 0, 0, w, h);
+        b2.getPixels(pixels2, 0, w, 0, 0, w, h);
+
+        for (int i = 0; i < s; i++) {
+            if (pixels1[i] != pixels2[i]) {
+                Assert.fail("the bitmaps are not equal");
+            }
+        }
+    }
+
+    /**
+     * Find beginning of the special element.
+     * @param parser XmlPullParser will be parsed.
+     * @param firstElementName the target element name.
+     *
+     * @throws XmlPullParserException if XML Pull Parser related faults occur.
+     * @throws IOException if I/O-related error occur when parsing.
+     */
+    public static final void beginDocument(XmlPullParser parser, String firstElementName)
+            throws XmlPullParserException, IOException {
+        Assert.assertNotNull(parser);
+        Assert.assertNotNull(firstElementName);
+
+        int type;
+        while ((type = parser.next()) != XmlPullParser.START_TAG
+                && type != XmlPullParser.END_DOCUMENT) {
+            ;
+        }
+
+        if (!parser.getName().equals(firstElementName)) {
+            throw new XmlPullParserException("Unexpected start tag: found " + parser.getName()
+                    + ", expected " + firstElementName);
+        }
+    }
+
+    /**
+     * Compare the expected pixels with actual, scaling for the target context density
+     *
+     * @throws AssertionFailedError
+     */
+    public static void assertScaledPixels(int expected, int actual, Context context) {
+        Assert.assertEquals(expected * context.getResources().getDisplayMetrics().density,
+                actual, 3);
+    }
+
+    /** Converts dips into pixels using the {@link Context}'s density. */
+    public static int convertDipToPixels(Context context, int dip) {
+      float density = context.getResources().getDisplayMetrics().density;
+      return Math.round(density * dip);
+    }
+
+    /**
+     * Retrieve a bitmap that can be used for comparison on any density
+     * @param resources
+     * @return the {@link Bitmap} or <code>null</code>
+     */
+    public static Bitmap getUnscaledBitmap(Resources resources, int resId) {
+        BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inScaled = false;
+        return BitmapFactory.decodeResource(resources, resId, options);
+    }
+
+    /**
+     * Retrieve a dithered bitmap that can be used for comparison on any density
+     * @param resources
+     * @param config the preferred config for the returning bitmap
+     * @return the {@link Bitmap} or <code>null</code>
+     */
+    public static Bitmap getUnscaledAndDitheredBitmap(Resources resources,
+            int resId, Bitmap.Config config) {
+        BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inDither = true;
+        options.inScaled = false;
+        options.inPreferredConfig = config;
+        return BitmapFactory.decodeResource(resources, resId, options);
+    }
+}
diff --git a/libs/deviceutil/src/android/provider/cts/FileCopyHelper.java b/libs/deviceutil/src/android/provider/cts/FileCopyHelper.java
deleted file mode 100644
index 507eb06..0000000
--- a/libs/deviceutil/src/android/provider/cts/FileCopyHelper.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2009 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.provider.cts;
-
-import android.content.Context;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-
-/**
- * The Class FileCopyHelper is used to copy files from resources to the
- * application directory and responsible for deleting the files.
- *
- * @see MediaStore_VideoTest
- * @see MediaStore_Images_MediaTest
- * @see MediaStore_Images_ThumbnailsTest
- */
-public class FileCopyHelper {
-    /** The context. */
-    private Context mContext;
-
-    /** The files added. */
-    private ArrayList<String> mFilesList;
-
-    /**
-     * Instantiates a new file copy helper.
-     *
-     * @param context the context
-     */
-    public FileCopyHelper(Context context) {
-        mContext = context;
-        mFilesList = new ArrayList<String>();
-    }
-
-    /**
-     * Copy the file from the resources with a filename .
-     *
-     * @param resId the res id
-     * @param fileName the file name
-     *
-     * @return the absolute path of the destination file
-     * @throws IOException
-     */
-    public String copy(int resId, String fileName) throws IOException {
-        InputStream source = mContext.getResources().openRawResource(resId);
-        OutputStream target = mContext.openFileOutput(fileName, Context.MODE_WORLD_READABLE);
-        copyFile(source, target);
-        mFilesList.add(fileName);
-        return mContext.getFileStreamPath(fileName).getAbsolutePath();
-    }
-
-    public void copyToExternalStorage(int resId, File path) throws IOException {
-        InputStream source = mContext.getResources().openRawResource(resId);
-        OutputStream target = new FileOutputStream(path);
-        copyFile(source, target);
-    }
-
-    private void copyFile(InputStream source, OutputStream target) throws IOException {
-        try {
-            byte[] buffer = new byte[1024];
-            for (int len = source.read(buffer); len > 0; len = source.read(buffer)) {
-                target.write(buffer, 0, len);
-            }
-        } finally {
-            if (source != null) {
-                source.close();
-            }
-            if (target != null) {
-                target.close();
-            }
-        }
-    }
-
-    /**
-     * Delete all the files copied by the helper.
-     */
-    public void clear(){
-        for (String path : mFilesList) {
-            mContext.deleteFile(path);
-        }
-    }
-}
diff --git a/libs/deviceutillegacy/Android.mk b/libs/deviceutillegacy/Android.mk
new file mode 100644
index 0000000..852ce38
--- /dev/null
+++ b/libs/deviceutillegacy/Android.mk
@@ -0,0 +1,30 @@
+# 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil
+
+LOCAL_SRC_FILES := \
+    $(call all-java-files-under, src)
+
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE := ctsdeviceutillegacy
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/libs/deviceutillegacy/src/android/webkit/cts/WebViewOnUiThread.java b/libs/deviceutillegacy/src/android/webkit/cts/WebViewOnUiThread.java
new file mode 100644
index 0000000..b9d3af1
--- /dev/null
+++ b/libs/deviceutillegacy/src/android/webkit/cts/WebViewOnUiThread.java
@@ -0,0 +1,1009 @@
+/*
+ * 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.
+ */
+
+package android.webkit.cts;
+
+import android.cts.util.PollingCheck;
+import android.cts.util.TestThread;
+import android.graphics.Bitmap;
+import android.graphics.Picture;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.Looper;
+import android.os.Message;
+import android.os.SystemClock;
+import android.print.PrintDocumentAdapter;
+import android.test.InstrumentationTestCase;
+import android.util.DisplayMetrics;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.webkit.DownloadListener;
+import android.webkit.CookieManager;
+import android.webkit.ValueCallback;
+import android.webkit.WebBackForwardList;
+import android.webkit.WebChromeClient;
+import android.webkit.WebSettings;
+import android.webkit.WebView.HitTestResult;
+import android.webkit.WebView.PictureListener;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+
+import junit.framework.Assert;
+
+import java.io.File;
+import java.util.concurrent.Callable;
+import java.util.Map;
+
+/**
+ * Many tests need to run WebView code in the UI thread. This class
+ * wraps a WebView so that calls are ensured to arrive on the UI thread.
+ *
+ * All methods may be run on either the UI thread or test thread.
+ */
+public class WebViewOnUiThread {
+    /**
+     * The maximum time, in milliseconds (10 seconds) to wait for a load
+     * to be triggered.
+     */
+    private static final long LOAD_TIMEOUT = 10000;
+
+    /**
+     * Set to true after onPageFinished is called.
+     */
+    private boolean mLoaded;
+
+    /**
+     * Set to true after onNewPicture is called. Reset when onPageStarted
+     * is called.
+     */
+    private boolean mNewPicture;
+
+    /**
+     * The progress, in percentage, of the page load. Valid values are between
+     * 0 and 100.
+     */
+    private int mProgress;
+
+    /**
+     * The test that this class is being used in. Used for runTestOnUiThread.
+     */
+    private InstrumentationTestCase mTest;
+
+    /**
+     * The WebView that calls will be made on.
+     */
+    private WebView mWebView;
+
+    /**
+     * Initializes the webView with a WebViewClient, WebChromeClient,
+     * and PictureListener to prepare for loadUrlAndWaitForCompletion.
+     *
+     * A new WebViewOnUiThread should be called during setUp so as to
+     * reinitialize between calls.
+     *
+     * @param test The test in which this is being run.
+     * @param webView The webView that the methods should call.
+     * @see loadUrlAndWaitForCompletion
+     */
+    public WebViewOnUiThread(InstrumentationTestCase test, WebView webView) {
+        mTest = test;
+        mWebView = webView;
+        final WebViewClient webViewClient = new WaitForLoadedClient(this);
+        final WebChromeClient webChromeClient = new WaitForProgressClient(this);
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.setWebViewClient(webViewClient);
+                mWebView.setWebChromeClient(webChromeClient);
+                mWebView.setPictureListener(new WaitForNewPicture());
+            }
+        });
+    }
+
+    /**
+     * Called after a test is complete and the WebView should be disengaged from
+     * the tests.
+     */
+    public void cleanUp() {
+        clearHistory();
+        clearCache(true);
+        setPictureListener(null);
+        setWebChromeClient(null);
+        setWebViewClient(null);
+    }
+
+    /**
+     * Called from WaitForNewPicture, this is used to indicate that
+     * the page has been drawn.
+     */
+    synchronized public void onNewPicture() {
+        mNewPicture = true;
+        this.notifyAll();
+    }
+
+    /**
+     * Called from WaitForLoadedClient, this is used to clear the picture
+     * draw state so that draws before the URL begins loading don't count.
+     */
+    synchronized public void onPageStarted() {
+        mNewPicture = false; // Earlier paints won't count.
+    }
+
+    /**
+     * Called from WaitForLoadedClient, this is used to indicate that
+     * the page is loaded, but not drawn yet.
+     */
+    synchronized public void onPageFinished() {
+        mLoaded = true;
+        this.notifyAll();
+    }
+
+    /**
+     * Called from the WebChrome client, this sets the current progress
+     * for a page.
+     * @param progress The progress made so far between 0 and 100.
+     */
+    synchronized public void onProgressChanged(int progress) {
+        mProgress = progress;
+        this.notifyAll();
+    }
+
+    public void setWebViewClient(final WebViewClient webViewClient) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.setWebViewClient(webViewClient);
+            }
+        });
+    }
+
+    public void setWebChromeClient(final WebChromeClient webChromeClient) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.setWebChromeClient(webChromeClient);
+            }
+        });
+    }
+
+    public void setPictureListener(final PictureListener pictureListener) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.setPictureListener(pictureListener);
+            }
+        });
+    }
+
+    public void setNetworkAvailable(final boolean available) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.setNetworkAvailable(available);
+            }
+        });
+    }
+
+    public void setDownloadListener(final DownloadListener listener) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.setDownloadListener(listener);
+            }
+        });
+    }
+
+    public void setBackgroundColor(final int color) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.setBackgroundColor(color);
+            }
+        });
+    }
+
+    public void clearCache(final boolean includeDiskFiles) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.clearCache(includeDiskFiles);
+            }
+        });
+    }
+
+    public void clearHistory() {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.clearHistory();
+            }
+        });
+    }
+
+    public void requestFocus() {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.requestFocus();
+            }
+        });
+    }
+
+    public boolean canZoomIn() {
+        return getValue(new ValueGetter<Boolean>() {
+            @Override
+            public Boolean capture() {
+                return mWebView.canZoomIn();
+            }
+        });
+    }
+
+    public boolean canZoomOut() {
+        return getValue(new ValueGetter<Boolean>() {
+            @Override
+            public Boolean capture() {
+                return mWebView.canZoomOut();
+            }
+        });
+    }
+
+    public boolean zoomIn() {
+        return getValue(new ValueGetter<Boolean>() {
+            @Override
+            public Boolean capture() {
+                return mWebView.zoomIn();
+            }
+        });
+    }
+
+    public boolean zoomOut() {
+        return getValue(new ValueGetter<Boolean>() {
+            @Override
+            public Boolean capture() {
+                return mWebView.zoomOut();
+            }
+        });
+    }
+
+    public void zoomBy(final float zoomFactor) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.zoomBy(zoomFactor);
+            }
+        });
+    }
+
+    public void setFindListener(final WebView.FindListener listener) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.setFindListener(listener);
+            }
+        });
+    }
+
+    public void removeJavascriptInterface(final String interfaceName) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.removeJavascriptInterface(interfaceName);
+            }
+        });
+    }
+
+    public void addJavascriptInterface(final Object object, final String name) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.addJavascriptInterface(object, name);
+            }
+        });
+    }
+
+    public void flingScroll(final int vx, final int vy) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.flingScroll(vx, vy);
+            }
+        });
+    }
+
+    public void requestFocusNodeHref(final Message hrefMsg) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.requestFocusNodeHref(hrefMsg);
+            }
+        });
+    }
+
+    public void requestImageRef(final Message msg) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.requestImageRef(msg);
+            }
+        });
+    }
+
+    public void setInitialScale(final int scaleInPercent) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.setInitialScale(scaleInPercent);
+            }
+        });
+    }
+
+    public void clearSslPreferences() {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.clearSslPreferences();
+            }
+        });
+    }
+
+    public void clearClientCertPreferences(final Runnable onCleared) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                WebView.clearClientCertPreferences(onCleared);
+            }
+        });
+    }
+
+    public void resumeTimers() {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.resumeTimers();
+            }
+        });
+    }
+
+    public void findNext(final boolean forward) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.findNext(forward);
+            }
+        });
+    }
+
+    public void clearMatches() {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.clearMatches();
+            }
+        });
+    }
+
+    /**
+     * Calls loadUrl on the WebView and then waits onPageFinished,
+     * onNewPicture and onProgressChange to reach 100.
+     * Test fails if the load timeout elapses.
+     * @param url The URL to load.
+     */
+    public void loadUrlAndWaitForCompletion(final String url) {
+        callAndWait(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.loadUrl(url);
+            }
+        });
+    }
+
+    /**
+     * Calls loadUrl on the WebView and then waits onPageFinished,
+     * onNewPicture and onProgressChange to reach 100.
+     * Test fails if the load timeout elapses.
+     * @param url The URL to load.
+     * @param extraHeaders The additional headers to be used in the HTTP request.
+     */
+    public void loadUrlAndWaitForCompletion(final String url,
+            final Map<String, String> extraHeaders) {
+        callAndWait(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.loadUrl(url, extraHeaders);
+            }
+        });
+    }
+
+    public void loadUrl(final String url) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.loadUrl(url);
+            }
+        });
+    }
+
+    public void stopLoading() {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.stopLoading();
+            }
+        });
+    }
+
+    public void postUrlAndWaitForCompletion(final String url, final byte[] postData) {
+        callAndWait(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.postUrl(url, postData);
+            }
+        });
+    }
+
+    public void loadDataAndWaitForCompletion(final String data,
+            final String mimeType, final String encoding) {
+        callAndWait(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.loadData(data, mimeType, encoding);
+            }
+        });
+    }
+
+    public void loadDataWithBaseURLAndWaitForCompletion(final String baseUrl,
+            final String data, final String mimeType, final String encoding,
+            final String historyUrl) {
+        callAndWait(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.loadDataWithBaseURL(baseUrl, data, mimeType, encoding,
+                        historyUrl);
+            }
+        });
+    }
+
+    /**
+     * Reloads a page and waits for it to complete reloading. Use reload
+     * if it is a form resubmission and the onFormResubmission responds
+     * by telling WebView not to resubmit it.
+     */
+    public void reloadAndWaitForCompletion() {
+        callAndWait(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.reload();
+            }
+        });
+    }
+
+    /**
+     * Reload the previous URL. Use reloadAndWaitForCompletion unless
+     * it is a form resubmission and the onFormResubmission responds
+     * by telling WebView not to resubmit it.
+     */
+    public void reload() {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.reload();
+            }
+        });
+    }
+
+    /**
+     * Use this only when JavaScript causes a page load to wait for the
+     * page load to complete. Otherwise use loadUrlAndWaitForCompletion or
+     * similar functions.
+     */
+    public void waitForLoadCompletion() {
+        waitForCriteria(LOAD_TIMEOUT,
+                new Callable<Boolean>() {
+                    @Override
+                    public Boolean call() {
+                        return isLoaded();
+                    }
+                });
+        clearLoad();
+    }
+
+    private void waitForCriteria(long timeout, Callable<Boolean> doneCriteria) {
+        if (isUiThread()) {
+            waitOnUiThread(timeout, doneCriteria);
+        } else {
+            waitOnTestThread(timeout, doneCriteria);
+        }
+    }
+
+    public String getTitle() {
+        return getValue(new ValueGetter<String>() {
+            @Override
+            public String capture() {
+                return mWebView.getTitle();
+            }
+        });
+    }
+
+    public WebSettings getSettings() {
+        return getValue(new ValueGetter<WebSettings>() {
+            @Override
+            public WebSettings capture() {
+                return mWebView.getSettings();
+            }
+        });
+    }
+
+    public WebBackForwardList copyBackForwardList() {
+        return getValue(new ValueGetter<WebBackForwardList>() {
+            @Override
+            public WebBackForwardList capture() {
+                return mWebView.copyBackForwardList();
+            }
+        });
+    }
+
+    public Bitmap getFavicon() {
+        return getValue(new ValueGetter<Bitmap>() {
+            @Override
+            public Bitmap capture() {
+                return mWebView.getFavicon();
+            }
+        });
+    }
+
+    public String getUrl() {
+        return getValue(new ValueGetter<String>() {
+            @Override
+            public String capture() {
+                return mWebView.getUrl();
+            }
+        });
+    }
+
+    public int getProgress() {
+        return getValue(new ValueGetter<Integer>() {
+            @Override
+            public Integer capture() {
+                return mWebView.getProgress();
+            }
+        });
+    }
+
+    public int getHeight() {
+        return getValue(new ValueGetter<Integer>() {
+            @Override
+            public Integer capture() {
+                return mWebView.getHeight();
+            }
+        });
+    }
+
+    public int getContentHeight() {
+        return getValue(new ValueGetter<Integer>() {
+            @Override
+            public Integer capture() {
+                return mWebView.getContentHeight();
+            }
+        });
+    }
+
+    public boolean savePicture(final Bundle b, final File dest) {
+        return getValue(new ValueGetter<Boolean>() {
+            @Override
+            public Boolean capture() {
+                return mWebView.savePicture(b, dest);
+            }
+        });
+    }
+
+    public boolean pageUp(final boolean top) {
+        return getValue(new ValueGetter<Boolean>() {
+            @Override
+            public Boolean capture() {
+                return mWebView.pageUp(top);
+            }
+        });
+    }
+
+    public boolean pageDown(final boolean bottom) {
+        return getValue(new ValueGetter<Boolean>() {
+            @Override
+            public Boolean capture() {
+                return mWebView.pageDown(bottom);
+            }
+        });
+    }
+
+    public int[] getLocationOnScreen() {
+        final int[] location = new int[2];
+        return getValue(new ValueGetter<int[]>() {
+            @Override
+            public int[] capture() {
+                mWebView.getLocationOnScreen(location);
+                return location;
+            }
+        });
+    }
+
+    public float getScale() {
+        return getValue(new ValueGetter<Float>() {
+            @Override
+            public Float capture() {
+                return mWebView.getScale();
+            }
+        });
+    }
+
+    public boolean requestFocus(final int direction,
+            final Rect previouslyFocusedRect) {
+        return getValue(new ValueGetter<Boolean>() {
+            @Override
+            public Boolean capture() {
+                return mWebView.requestFocus(direction, previouslyFocusedRect);
+            }
+        });
+    }
+
+    public HitTestResult getHitTestResult() {
+        return getValue(new ValueGetter<HitTestResult>() {
+            @Override
+            public HitTestResult capture() {
+                return mWebView.getHitTestResult();
+            }
+        });
+    }
+
+    public int getScrollX() {
+        return getValue(new ValueGetter<Integer>() {
+            @Override
+            public Integer capture() {
+                return mWebView.getScrollX();
+            }
+        });
+    }
+
+    public int getScrollY() {
+        return getValue(new ValueGetter<Integer>() {
+            @Override
+            public Integer capture() {
+                return mWebView.getScrollY();
+            }
+        });
+    }
+
+    public final DisplayMetrics getDisplayMetrics() {
+        return getValue(new ValueGetter<DisplayMetrics>() {
+            @Override
+            public DisplayMetrics capture() {
+                return mWebView.getContext().getResources().getDisplayMetrics();
+            }
+        });
+    }
+
+    public boolean requestChildRectangleOnScreen(final View child,
+            final Rect rect,
+            final boolean immediate) {
+        return getValue(new ValueGetter<Boolean>() {
+            @Override
+            public Boolean capture() {
+                return mWebView.requestChildRectangleOnScreen(child, rect,
+                        immediate);
+            }
+        });
+    }
+
+    public int findAll(final String find) {
+        return getValue(new ValueGetter<Integer>() {
+            @Override
+            public Integer capture() {
+                return mWebView.findAll(find);
+            }
+        });
+    }
+
+    public Picture capturePicture() {
+        return getValue(new ValueGetter<Picture>() {
+            @Override
+            public Picture capture() {
+                return mWebView.capturePicture();
+            }
+        });
+    }
+
+    public void evaluateJavascript(final String script, final ValueCallback<String> result) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.evaluateJavascript(script, result);
+            }
+        });
+    }
+
+    public void saveWebArchive(final String basename, final boolean autoname,
+                               final ValueCallback<String> callback) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mWebView.saveWebArchive(basename, autoname, callback);
+            }
+        });
+    }
+
+    public WebView createWebView() {
+        return getValue(new ValueGetter<WebView>() {
+            @Override
+            public WebView capture() {
+                return new WebView(mWebView.getContext());
+            }
+        });
+    }
+
+    public PrintDocumentAdapter createPrintDocumentAdapter() {
+        return getValue(new ValueGetter<PrintDocumentAdapter>() {
+            @Override
+            public PrintDocumentAdapter capture() {
+                return mWebView.createPrintDocumentAdapter();
+            }
+        });
+    }
+
+    public void setLayoutHeightToMatchParent() {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                ViewParent parent = mWebView.getParent();
+                if (parent instanceof ViewGroup) {
+                    ((ViewGroup) parent).getLayoutParams().height =
+                        ViewGroup.LayoutParams.MATCH_PARENT;
+                }
+                mWebView.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
+                mWebView.requestLayout();
+            }
+        });
+    }
+
+    public void setAcceptThirdPartyCookies(final boolean accept) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                CookieManager.getInstance().setAcceptThirdPartyCookies(mWebView, accept);
+            }
+        });
+    }
+
+    public boolean acceptThirdPartyCookies() {
+        return getValue(new ValueGetter<Boolean>() {
+            @Override
+            public Boolean capture() {
+                return CookieManager.getInstance().acceptThirdPartyCookies(mWebView);
+            }
+        });
+    }
+
+    /**
+     * Helper for running code on the UI thread where an exception is
+     * a test failure. If this is already the UI thread then it runs
+     * the code immediately.
+     *
+     * @see runTestOnUiThread
+     * @param r The code to run in the UI thread
+     */
+    public void runOnUiThread(Runnable r) {
+        try {
+            if (isUiThread()) {
+                r.run();
+            } else {
+                mTest.runTestOnUiThread(r);
+            }
+        } catch (Throwable t) {
+            Assert.fail("Unexpected error while running on UI thread: "
+                    + t.getMessage());
+        }
+    }
+
+    /**
+     * Accessor for underlying WebView.
+     * @return The WebView being wrapped by this class.
+     */
+    public WebView getWebView() {
+        return mWebView;
+    }
+
+    private<T> T getValue(ValueGetter<T> getter) {
+        runOnUiThread(getter);
+        return getter.getValue();
+    }
+
+    private abstract class ValueGetter<T> implements Runnable {
+        private T mValue;
+
+        @Override
+        public void run() {
+            mValue = capture();
+        }
+
+        protected abstract T capture();
+
+        public T getValue() {
+           return mValue;
+        }
+    }
+
+    /**
+     * Returns true if the current thread is the UI thread based on the
+     * Looper.
+     */
+    private static boolean isUiThread() {
+        return (Looper.myLooper() == Looper.getMainLooper());
+    }
+
+    /**
+     * @return Whether or not the load has finished.
+     */
+    private synchronized boolean isLoaded() {
+        return mLoaded && mNewPicture && mProgress == 100;
+    }
+
+    /**
+     * Makes a WebView call, waits for completion and then resets the
+     * load state in preparation for the next load call.
+     * @param call The call to make on the UI thread prior to waiting.
+     */
+    private void callAndWait(Runnable call) {
+        Assert.assertTrue("WebViewOnUiThread.load*AndWaitForCompletion calls "
+                + "may not be mixed with load* calls directly on WebView "
+                + "without calling waitForLoadCompletion after the load",
+                !isLoaded());
+        clearLoad(); // clear any extraneous signals from a previous load.
+        runOnUiThread(call);
+        waitForLoadCompletion();
+    }
+
+    /**
+     * Called whenever a load has been completed so that a subsequent call to
+     * waitForLoadCompletion doesn't return immediately.
+     */
+    synchronized private void clearLoad() {
+        mLoaded = false;
+        mNewPicture = false;
+        mProgress = 0;
+    }
+
+    /**
+     * Uses a polling mechanism, while pumping messages to check when the
+     * criteria is met.
+     */
+    private void waitOnUiThread(long timeout, final Callable<Boolean> doneCriteria) {
+        new PollingCheck(timeout) {
+            @Override
+            protected boolean check() {
+                pumpMessages();
+                try {
+                    return doneCriteria.call();
+                } catch (Exception e) {
+                    Assert.fail("Unexpected error while checking the criteria: "
+                            + e.getMessage());
+                    return true;
+                }
+            }
+        }.run();
+    }
+
+    /**
+     * Uses a wait/notify to check when the criteria is met.
+     */
+    private synchronized void waitOnTestThread(long timeout, Callable<Boolean> doneCriteria) {
+        try {
+            long waitEnd = SystemClock.uptimeMillis() + timeout;
+            long timeRemaining = timeout;
+            while (!doneCriteria.call() && timeRemaining > 0) {
+                this.wait(timeRemaining);
+                timeRemaining = waitEnd - SystemClock.uptimeMillis();
+            }
+            Assert.assertTrue("Action failed to complete before timeout", doneCriteria.call());
+        } catch (InterruptedException e) {
+            // We'll just drop out of the loop and fail
+        } catch (Exception e) {
+            Assert.fail("Unexpected error while checking the criteria: "
+                    + e.getMessage());
+        }
+    }
+
+    /**
+     * Pumps all currently-queued messages in the UI thread and then exits.
+     * This is useful to force processing while running tests in the UI thread.
+     */
+    private void pumpMessages() {
+        class ExitLoopException extends RuntimeException {
+        }
+
+        // Force loop to exit when processing this. Loop.quit() doesn't
+        // work because this is the main Loop.
+        mWebView.getHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                throw new ExitLoopException(); // exit loop!
+            }
+        });
+        try {
+            // Pump messages until our message gets through.
+            Looper.loop();
+        } catch (ExitLoopException e) {
+        }
+    }
+
+    /**
+     * A WebChromeClient used to capture the onProgressChanged for use
+     * in waitFor functions. If a test must override the WebChromeClient,
+     * it can derive from this class or call onProgressChanged
+     * directly.
+     */
+    public static class WaitForProgressClient extends WebChromeClient {
+        private WebViewOnUiThread mOnUiThread;
+
+        public WaitForProgressClient(WebViewOnUiThread onUiThread) {
+            mOnUiThread = onUiThread;
+        }
+
+        @Override
+        public void onProgressChanged(WebView view, int newProgress) {
+            super.onProgressChanged(view, newProgress);
+            mOnUiThread.onProgressChanged(newProgress);
+        }
+    }
+
+    /**
+     * A WebViewClient that captures the onPageFinished for use in
+     * waitFor functions. Using initializeWebView sets the WaitForLoadedClient
+     * into the WebView. If a test needs to set a specific WebViewClient and
+     * needs the waitForCompletion capability then it should derive from
+     * WaitForLoadedClient or call WebViewOnUiThread.onPageFinished.
+     */
+    public static class WaitForLoadedClient extends WebViewClient {
+        private WebViewOnUiThread mOnUiThread;
+
+        public WaitForLoadedClient(WebViewOnUiThread onUiThread) {
+            mOnUiThread = onUiThread;
+        }
+
+        @Override
+        public void onPageFinished(WebView view, String url) {
+            super.onPageFinished(view, url);
+            mOnUiThread.onPageFinished();
+        }
+
+        @Override
+        public void onPageStarted(WebView view, String url, Bitmap favicon) {
+            super.onPageStarted(view, url, favicon);
+            mOnUiThread.onPageStarted();
+        }
+    }
+
+    /**
+     * A PictureListener that captures the onNewPicture for use in
+     * waitForLoadCompletion. Using initializeWebView sets the PictureListener
+     * into the WebView. If a test needs to set a specific PictureListener and
+     * needs the waitForCompletion capability then it should call
+     * WebViewOnUiThread.onNewPicture.
+     */
+    private class WaitForNewPicture implements PictureListener {
+        @Override
+        public void onNewPicture(WebView view, Picture picture) {
+            WebViewOnUiThread.this.onNewPicture();
+        }
+    }
+}
diff --git a/libs/runner/Android.mk b/libs/runner/Android.mk
index 629c1c2..9642f53 100644
--- a/libs/runner/Android.mk
+++ b/libs/runner/Android.mk
@@ -18,10 +18,12 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, ../../tests/core/runner/src)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
 
 LOCAL_MODULE_TAGS := optional
 
 LOCAL_MODULE := ctstestrunner
 
+LOCAL_SDK_VERSION := current
+
 include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/libs/testserver/src/android/webkit/cts/CtsTestServer.java b/libs/testserver/src/android/webkit/cts/CtsTestServer.java
index 928a68e..22cbb7b 100644
--- a/libs/testserver/src/android/webkit/cts/CtsTestServer.java
+++ b/libs/testserver/src/android/webkit/cts/CtsTestServer.java
@@ -85,6 +85,7 @@
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.KeyManagerFactory;
 import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLServerSocket;
 import javax.net.ssl.SSLSession;
 import javax.net.ssl.X509TrustManager;
 
@@ -101,20 +102,22 @@
     private static final String DOWNLOAD_ID_PARAMETER = "downloadId";
     private static final String NUM_BYTES_PARAMETER = "numBytes";
 
-    public static final String ASSET_PREFIX = "/assets/";
-    public static final String RAW_PREFIX = "raw/";
-    public static final String FAVICON_ASSET_PATH = ASSET_PREFIX + "webkit/favicon.png";
-    public static final String APPCACHE_PATH = "/appcache.html";
-    public static final String APPCACHE_MANIFEST_PATH = "/appcache.manifest";
-    public static final String REDIRECT_PREFIX = "/redirect";
-    public static final String QUERY_REDIRECT_PATH = "/alt_redirect";
-    public static final String DELAY_PREFIX = "/delayed";
-    public static final String BINARY_PREFIX = "/binary";
-    public static final String COOKIE_PREFIX = "/cookie";
-    public static final String AUTH_PREFIX = "/auth";
-    public static final String SHUTDOWN_PREFIX = "/shutdown";
+    private static final String ASSET_PREFIX = "/assets/";
+    private static final String RAW_PREFIX = "raw/";
+    private static final String FAVICON_ASSET_PATH = ASSET_PREFIX + "webkit/favicon.png";
+    private static final String APPCACHE_PATH = "/appcache.html";
+    private static final String APPCACHE_MANIFEST_PATH = "/appcache.manifest";
+    private static final String REDIRECT_PREFIX = "/redirect";
+    private static final String QUERY_REDIRECT_PATH = "/alt_redirect";
+    private static final String DELAY_PREFIX = "/delayed";
+    private static final String BINARY_PREFIX = "/binary";
+    private static final String SET_COOKIE_PREFIX = "/setcookie";
+    private static final String COOKIE_PREFIX = "/cookie";
+    private static final String LINKED_SCRIPT_PREFIX = "/linkedscriptprefix";
+    private static final String AUTH_PREFIX = "/auth";
+    private static final String SHUTDOWN_PREFIX = "/shutdown";
     public static final String NOLENGTH_POSTFIX = "nolength";
-    public static final int DELAY_MILLIS = 2000;
+    private static final int DELAY_MILLIS = 2000;
 
     public static final String AUTH_REALM = "Android CTS";
     public static final String AUTH_USER = "cts";
@@ -126,6 +129,13 @@
     public static final String MESSAGE_403 = "403 forbidden";
     public static final String MESSAGE_404 = "404 not found";
 
+    public enum SslMode {
+        INSECURE,
+        NO_CLIENT_AUTH,
+        WANTS_CLIENT_AUTH,
+        NEEDS_CLIENT_AUTH,
+    }
+
     private static Hashtable<Integer, String> sReasons;
 
     private ServerThread mServerThread;
@@ -133,13 +143,14 @@
     private AssetManager mAssets;
     private Context mContext;
     private Resources mResources;
-    private boolean mSsl;
+    private SslMode mSsl;
     private MimeTypeMap mMap;
     private Vector<String> mQueries;
     private ArrayList<HttpEntity> mRequestEntities;
     private final Map<String, HttpRequest> mLastRequestMap = new HashMap<String, HttpRequest>();
     private long mDocValidity;
     private long mDocAge;
+    private X509TrustManager mTrustManager;
 
     /**
      * Create and start a local HTTP server instance.
@@ -168,19 +179,43 @@
      * @throws Exception
      */
     public CtsTestServer(Context context, boolean ssl) throws Exception {
+        this(context, ssl ? SslMode.NO_CLIENT_AUTH : SslMode.INSECURE);
+    }
+
+    /**
+     * Create and start a local HTTP server instance.
+     * @param context The application context to use for fetching assets.
+     * @param sslMode Whether to use SSL, and if so, what client auth (if any) to use.
+     * @throws Exception
+     */
+    public CtsTestServer(Context context, SslMode sslMode) throws Exception {
+        this(context, sslMode, new CtsTrustManager());
+    }
+
+    /**
+     * Create and start a local HTTP server instance.
+     * @param context The application context to use for fetching assets.
+     * @param sslMode Whether to use SSL, and if so, what client auth (if any) to use.
+     * @param trustManager the trustManager
+     * @throws Exception
+     */
+    public CtsTestServer(Context context, SslMode sslMode, X509TrustManager trustManager)
+            throws Exception {
         mContext = context;
         mAssets = mContext.getAssets();
         mResources = mContext.getResources();
-        mSsl = ssl;
+        mSsl = sslMode;
         mRequestEntities = new ArrayList<HttpEntity>();
         mMap = MimeTypeMap.getSingleton();
         mQueries = new Vector<String>();
+        mTrustManager = trustManager;
         mServerThread = new ServerThread(this, mSsl);
-        if (mSsl) {
-            mServerUri = "https://localhost:" + mServerThread.mSocket.getLocalPort();
+        if (mSsl == SslMode.INSECURE) {
+            mServerUri = "http:";
         } else {
-            mServerUri = "http://localhost:" + mServerThread.mSocket.getLocalPort();
+            mServerUri = "https:";
         }
+        mServerUri += "//localhost:" + mServerThread.mSocket.getLocalPort();
         mServerThread.start();
     }
 
@@ -219,7 +254,9 @@
 
     private URLConnection openConnection(URL url)
             throws IOException, NoSuchAlgorithmException, KeyManagementException {
-        if (mSsl) {
+        if (mSsl == SslMode.INSECURE) {
+            return url.openConnection();
+        } else {
             // Install hostname verifiers and trust managers that don't do
             // anything in order to get around the client not trusting
             // the test server due to a lack of certificates.
@@ -228,13 +265,14 @@
             connection.setHostnameVerifier(new CtsHostnameVerifier());
 
             SSLContext context = SSLContext.getInstance("TLS");
-            CtsTrustManager trustManager = new CtsTrustManager();
-            context.init(null, new CtsTrustManager[] {trustManager}, null);
+            try {
+                context.init(ServerThread.getKeyManagers(), getTrustManagers(), null);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
             connection.setSSLSocketFactory(context.getSocketFactory());
 
             return connection;
-        } else {
-            return url.openConnection();
         }
     }
 
@@ -246,7 +284,7 @@
      */
     private static class CtsTrustManager implements X509TrustManager {
         public void checkClientTrusted(X509Certificate[] chain, String authType) {
-            // Trust the CtSTestServer...
+            // Trust the CtSTestServer's client...
         }
 
         public void checkServerTrusted(X509Certificate[] chain, String authType) {
@@ -259,6 +297,13 @@
     }
 
     /**
+     * @return a trust manager array of size 1.
+     */
+    private X509TrustManager[] getTrustManagers() {
+        return new X509TrustManager[] { mTrustManager };
+    }
+
+    /**
      * {@link HostnameVerifier} that verifies everybody. This permits
      * the client to trust the web server and call
      * {@link CtsTestServer#shutdown()}.
@@ -293,8 +338,20 @@
      * @param path The path of the asset. See {@link AssetManager#open(String)}
      */
     public String getDelayedAssetUrl(String path) {
+        return getDelayedAssetUrl(path, DELAY_MILLIS);
+    }
+
+    /**
+     * Return an artificially delayed absolute URL that refers to the given asset. This can be
+     * used to emulate a slow HTTP server or connection.
+     * @param path The path of the asset. See {@link AssetManager#open(String)}
+     * @param delayMs The number of milliseconds to delay the request
+     */
+    public String getDelayedAssetUrl(String path, int delayMs) {
         StringBuilder sb = new StringBuilder(getBaseUri());
         sb.append(DELAY_PREFIX);
+        sb.append("/");
+        sb.append(delayMs);
         sb.append(ASSET_PREFIX);
         sb.append(path);
         return sb.toString();
@@ -313,7 +370,6 @@
         return sb.toString();
     }
 
-
     /**
      * Return an absolute URL that indirectly refers to the given asset.
      * When a client fetches this URL, the server will respond with a temporary redirect (302)
@@ -359,6 +415,43 @@
         return sb.toString();
     }
 
+    /**
+     * getSetCookieUrl returns a URL that attempts to set the cookie
+     * "key=value" when fetched.
+     * @param path a suffix to disambiguate mulitple Cookie URLs.
+     * @param key the key of the cookie.
+     * @return the url for a page that attempts to set the cookie.
+     */
+    public String getSetCookieUrl(String path, String key, String value) {
+        StringBuilder sb = new StringBuilder(getBaseUri());
+        sb.append(SET_COOKIE_PREFIX);
+        sb.append(path);
+        sb.append("?key=");
+        sb.append(key);
+        sb.append("&value=");
+        sb.append(value);
+        return sb.toString();
+    }
+
+    /**
+     * getLinkedScriptUrl returns a URL for a page with a script tag where
+     * src equals the URL passed in.
+     * @param path a suffix to disambiguate mulitple Linked Script URLs.
+     * @param url the src of the script tag.
+     * @return the url for the page with the script link in.
+     */
+    public String getLinkedScriptUrl(String path, String url) {
+        StringBuilder sb = new StringBuilder(getBaseUri());
+        sb.append(LINKED_SCRIPT_PREFIX);
+        sb.append(path);
+        sb.append("?url=");
+        try {
+            sb.append(URLEncoder.encode(url, "UTF-8"));
+        } catch (UnsupportedEncodingException e) {
+        }
+        return sb.toString();
+    }
+
     public String getBinaryUrl(String mimeType, int contentLength) {
         StringBuilder sb = new StringBuilder(getBaseUri());
         sb.append(BINARY_PREFIX);
@@ -520,12 +613,14 @@
             path = FAVICON_ASSET_PATH;
         }
         if (path.startsWith(DELAY_PREFIX)) {
+            String delayPath = path.substring(DELAY_PREFIX.length() + 1);
+            String delay = delayPath.substring(0, delayPath.indexOf('/'));
+            path = delayPath.substring(delay.length());
             try {
-                Thread.sleep(DELAY_MILLIS);
+                Thread.sleep(Integer.valueOf(delay));
             } catch (InterruptedException ignored) {
                 // ignore
             }
-            path = path.substring(DELAY_PREFIX.length());
         }
         if (path.startsWith(AUTH_PREFIX)) {
             // authentication required
@@ -561,6 +656,8 @@
                     response = createResponse(HttpStatus.SC_OK);
                     response.setEntity(entity);
                     response.addHeader("Content-Disposition", "attachment; filename=test.bin");
+                    response.addHeader("Content-Type", mimeType);
+                    response.addHeader("Content-Length", "" + length);
                 } else {
                     // fall through, return 404 at the end
                 }
@@ -636,8 +733,20 @@
             }
 
             response.addHeader("Set-Cookie", "count=" + count + "; path=" + COOKIE_PREFIX);
-            response.setEntity(createEntity("<html><head><title>" + cookieString +
-                    "</title></head><body>" + cookieString + "</body></html>"));
+            response.setEntity(createPage(cookieString.toString(), cookieString.toString()));
+        } else if (path.startsWith(SET_COOKIE_PREFIX)) {
+            response = createResponse(HttpStatus.SC_OK);
+            Uri parsedUri = Uri.parse(uriString);
+            String key = parsedUri.getQueryParameter("key");
+            String value = parsedUri.getQueryParameter("value");
+            String cookie = key + "=" + value;
+            response.addHeader("Set-Cookie", cookie);
+            response.setEntity(createPage(cookie, cookie));
+        } else if (path.startsWith(LINKED_SCRIPT_PREFIX)) {
+            response = createResponse(HttpStatus.SC_OK);
+            String src = Uri.parse(uriString).getQueryParameter("url");
+            String scriptTag = "<script src=\"" + src + "\"></script>";
+            response.setEntity(createPage("LinkedScript", scriptTag));
         } else if (path.equals(USERAGENT_PATH)) {
             response = createResponse(HttpStatus.SC_OK);
             Header agentHeader = request.getFirstHeader("User-Agent");
@@ -645,8 +754,7 @@
             if (agentHeader != null) {
                 agent = agentHeader.getValue();
             }
-            response.setEntity(createEntity("<html><head><title>" + agent + "</title></head>" +
-                    "<body>" + agent + "</body></html>"));
+            response.setEntity(createPage(agent, agent));
         } else if (path.equals(TEST_DOWNLOAD_PATH)) {
             response = createTestDownloadResponse(Uri.parse(uriString));
         } else if (path.equals(SHUTDOWN_PREFIX)) {
@@ -727,12 +835,7 @@
         // Fill in error reason. Avoid use of the ReasonPhraseCatalog, which is Locale-dependent.
         String reason = getReasonString(status);
         if (reason != null) {
-            StringBuffer buf = new StringBuffer("<html><head><title>");
-            buf.append(reason);
-            buf.append("</title></head><body>");
-            buf.append(reason);
-            buf.append("</body></html>");
-            response.setEntity(createEntity(buf.toString()));
+            response.setEntity(createPage(reason, reason));
         }
         return response;
     }
@@ -751,6 +854,14 @@
         return null;
     }
 
+    /**
+     * Create a string entity for a bare bones html page with provided title and body.
+     */
+    private static StringEntity createPage(String title, String bodyContent) {
+        return createEntity("<html><head><title>" + title + "</title></head>" +
+                "<body>" + bodyContent + "</body></html>");
+    }
+
     private static HttpResponse createTestDownloadResponse(Uri uri) throws IOException {
         String downloadId = uri.getQueryParameter(DOWNLOAD_ID_PARAMETER);
         int numBytes = uri.getQueryParameter(NUM_BYTES_PARAMETER) != null
@@ -794,7 +905,7 @@
     private static class ServerThread extends Thread {
         private CtsTestServer mServer;
         private ServerSocket mSocket;
-        private boolean mIsSsl;
+        private SslMode mSsl;
         private boolean mIsCancelled;
         private SSLContext mSslContext;
         private ExecutorService mExecutorService = Executors.newFixedThreadPool(20);
@@ -829,13 +940,13 @@
             "1gaEjsC/0wGmmBDg1dTDH+F1p9TInzr3EFuYD0YiQ7YlAHq3cPuyGoLXJ5dXYuSBfhDXJSeddUkl" +
             "k1ufZyOOcskeInQge7jzaRfmKg3U94r+spMEvb0AzDQVOKvjjo1ivxMSgFRZaDb/4qw=";
 
-        private String PASSWORD = "android";
+        private static final String PASSWORD = "android";
 
         /**
          * Loads a keystore from a base64-encoded String. Returns the KeyManager[]
          * for the result.
          */
-        private KeyManager[] getKeyManagers() throws Exception {
+        private static KeyManager[] getKeyManagers() throws Exception {
             byte[] bytes = Base64.decode(SERVER_KEYS_BKS.getBytes());
             InputStream inputStream = new ByteArrayInputStream(bytes);
 
@@ -851,19 +962,24 @@
         }
 
 
-        public ServerThread(CtsTestServer server, boolean ssl) throws Exception {
+        public ServerThread(CtsTestServer server, SslMode sslMode) throws Exception {
             super("ServerThread");
             mServer = server;
-            mIsSsl = ssl;
+            mSsl = sslMode;
             int retry = 3;
             while (true) {
                 try {
-                    if (mIsSsl) {
-                        mSslContext = SSLContext.getInstance("TLS");
-                        mSslContext.init(getKeyManagers(), null, null);
-                        mSocket = mSslContext.getServerSocketFactory().createServerSocket(0);
-                    } else {
+                    if (mSsl == SslMode.INSECURE) {
                         mSocket = new ServerSocket(0);
+                    } else {  // Use SSL
+                        mSslContext = SSLContext.getInstance("TLS");
+                        mSslContext.init(getKeyManagers(), mServer.getTrustManagers(), null);
+                        mSocket = mSslContext.getServerSocketFactory().createServerSocket(0);
+                        if (mSsl == SslMode.WANTS_CLIENT_AUTH) {
+                            ((SSLServerSocket) mSocket).setWantClientAuth(true);
+                        } else if (mSsl == SslMode.NEEDS_CLIENT_AUTH) {
+                            ((SSLServerSocket) mSocket).setNeedClientAuth(true);
+                        }
                     }
                     return;
                 } catch (IOException e) {
diff --git a/libs/testserver/src/android/webkit/cts/TestWebServer.java b/libs/testserver/src/android/webkit/cts/TestWebServer.java
new file mode 100644
index 0000000..9f03939
--- /dev/null
+++ b/libs/testserver/src/android/webkit/cts/TestWebServer.java
@@ -0,0 +1,625 @@
+// Copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Any changes to this file should be done in upstream chromium.org:
+// net/test/android/javatests/src/org/chromium/net/test/util/TestWebServer.java
+
+package android.webkit.cts;
+
+import android.util.Base64;
+import android.util.Log;
+import android.util.Pair;
+
+import org.apache.http.HttpException;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.HttpVersion;
+import org.apache.http.RequestLine;
+import org.apache.http.StatusLine;
+import org.apache.http.entity.ByteArrayEntity;
+import org.apache.http.impl.DefaultHttpServerConnection;
+import org.apache.http.impl.cookie.DateUtils;
+import org.apache.http.message.BasicHttpResponse;
+import org.apache.http.params.BasicHttpParams;
+import org.apache.http.params.CoreProtocolPNames;
+import org.apache.http.params.HttpParams;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLConnection;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.X509TrustManager;
+
+/**
+ * Simple http test server for testing.
+ *
+ * This server runs in a thread in the current process, so it is convenient
+ * for loopback testing without the need to setup tcp forwarding to the
+ * host computer.
+ *
+ * Based heavily on the CTSWebServer in Android.
+ */
+public class TestWebServer {
+    private static final String TAG = "TestWebServer";
+
+    public static final String SHUTDOWN_PREFIX = "/shutdown";
+
+    private static TestWebServer sInstance;
+    private static TestWebServer sSecureInstance;
+    private static Hashtable<Integer, String> sReasons;
+
+    private final ServerThread mServerThread;
+    private String mServerUri;
+    private final boolean mSsl;
+
+    private static class Response {
+        final byte[] mResponseData;
+        final List<Pair<String, String>> mResponseHeaders;
+        final boolean mIsRedirect;
+        final Runnable mResponseAction;
+        final boolean mIsNotFound;
+
+        Response(byte[] responseData, List<Pair<String, String>> responseHeaders,
+                boolean isRedirect, boolean isNotFound, Runnable responseAction) {
+            mIsRedirect = isRedirect;
+            mIsNotFound = isNotFound;
+            mResponseData = responseData;
+            mResponseHeaders = responseHeaders == null ?
+                    new ArrayList<Pair<String, String>>() : responseHeaders;
+            mResponseAction = responseAction;
+        }
+    }
+
+    // The Maps below are modified on both the client thread and the internal server thread, so
+    // need to use a lock when accessing them.
+    private final Object mLock = new Object();
+    private final Map<String, Response> mResponseMap = new HashMap<String, Response>();
+    private final Map<String, Integer> mResponseCountMap = new HashMap<String, Integer>();
+    private final Map<String, HttpRequest> mLastRequestMap = new HashMap<String, HttpRequest>();
+
+    /**
+     * Create and start a local HTTP server instance.
+     * @param ssl True if the server should be using secure sockets.
+     * @throws Exception
+     */
+    public TestWebServer(boolean ssl) throws Exception {
+        mSsl = ssl;
+        if (mSsl) {
+            mServerUri = "https:";
+            if (sSecureInstance != null) {
+                sSecureInstance.shutdown();
+            }
+        } else {
+            mServerUri = "http:";
+            if (sInstance != null) {
+                sInstance.shutdown();
+            }
+        }
+
+        setInstance(this, mSsl);
+        mServerThread = new ServerThread(this, mSsl);
+        mServerThread.start();
+        mServerUri += "//localhost:" + mServerThread.mSocket.getLocalPort();
+    }
+
+    /**
+     * Terminate the http server.
+     */
+    public void shutdown() {
+        try {
+            // Avoid a deadlock between two threads where one is trying to call
+            // close() and the other one is calling accept() by sending a GET
+            // request for shutdown and having the server's one thread
+            // sequentially call accept() and close().
+            URL url = new URL(mServerUri + SHUTDOWN_PREFIX);
+            URLConnection connection = openConnection(url);
+            connection.connect();
+
+            // Read the input from the stream to send the request.
+            InputStream is = connection.getInputStream();
+            is.close();
+
+            // Block until the server thread is done shutting down.
+            mServerThread.join();
+
+        } catch (MalformedURLException e) {
+            throw new IllegalStateException(e);
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        } catch (NoSuchAlgorithmException e) {
+            throw new IllegalStateException(e);
+        } catch (KeyManagementException e) {
+            throw new IllegalStateException(e);
+        }
+
+        setInstance(null, mSsl);
+    }
+
+    private static void setInstance(TestWebServer instance, boolean isSsl) {
+        if (isSsl) {
+            sSecureInstance = instance;
+        } else {
+            sInstance = instance;
+        }
+    }
+
+    private static final int RESPONSE_STATUS_NORMAL = 0;
+    private static final int RESPONSE_STATUS_MOVED_TEMPORARILY = 1;
+    private static final int RESPONSE_STATUS_NOT_FOUND = 2;
+
+    private String setResponseInternal(
+            String requestPath, byte[] responseData,
+            List<Pair<String, String>> responseHeaders, Runnable responseAction,
+            int status) {
+        final boolean isRedirect = (status == RESPONSE_STATUS_MOVED_TEMPORARILY);
+        final boolean isNotFound = (status == RESPONSE_STATUS_NOT_FOUND);
+
+        synchronized (mLock) {
+            mResponseMap.put(requestPath, new Response(
+                    responseData, responseHeaders, isRedirect, isNotFound, responseAction));
+            mResponseCountMap.put(requestPath, Integer.valueOf(0));
+            mLastRequestMap.put(requestPath, null);
+        }
+        return getResponseUrl(requestPath);
+    }
+
+    /**
+     * Gets the URL on the server under which a particular request path will be accessible.
+     *
+     * This only gets the URL, you still need to set the response if you intend to access it.
+     *
+     * @param requestPath The path to respond to.
+     * @return The full URL including the requestPath.
+     */
+    public String getResponseUrl(String requestPath) {
+        return mServerUri + requestPath;
+    }
+
+    /**
+     * Sets a 404 (not found) response to be returned when a particular request path is passed in.
+     *
+     * @param requestPath The path to respond to.
+     * @return The full URL including the path that should be requested to get the expected
+     *         response.
+     */
+    public String setResponseWithNotFoundStatus(
+            String requestPath) {
+        return setResponseInternal(requestPath, "".getBytes(), null, null,
+                RESPONSE_STATUS_NOT_FOUND);
+    }
+
+    /**
+     * Sets a response to be returned when a particular request path is passed
+     * in (with the option to specify additional headers).
+     *
+     * @param requestPath The path to respond to.
+     * @param responseString The response body that will be returned.
+     * @param responseHeaders Any additional headers that should be returned along with the
+     *                        response (null is acceptable).
+     * @return The full URL including the path that should be requested to get the expected
+     *         response.
+     */
+    public String setResponse(
+            String requestPath, String responseString,
+            List<Pair<String, String>> responseHeaders) {
+        return setResponseInternal(requestPath, responseString.getBytes(), responseHeaders, null,
+                RESPONSE_STATUS_NORMAL);
+    }
+
+    /**
+     * Sets a response to be returned when a particular request path is passed
+     * in with the option to specify additional headers as well as an arbitrary action to be
+     * executed on each request.
+     *
+     * @param requestPath The path to respond to.
+     * @param responseString The response body that will be returned.
+     * @param responseHeaders Any additional headers that should be returned along with the
+     *                        response (null is acceptable).
+     * @param responseAction The action to be performed when fetching the response.  This action
+     *                       will be executed for each request and will be handled on a background
+     *                       thread.
+     * @return The full URL including the path that should be requested to get the expected
+     *         response.
+     */
+    public String setResponseWithRunnableAction(
+            String requestPath, String responseString, List<Pair<String, String>> responseHeaders,
+            Runnable responseAction) {
+        return setResponseInternal(
+                requestPath, responseString.getBytes(), responseHeaders, responseAction,
+                RESPONSE_STATUS_NORMAL);
+    }
+
+    /**
+     * Sets a redirect.
+     *
+     * @param requestPath The path to respond to.
+     * @param targetPath The path to redirect to.
+     * @return The full URL including the path that should be requested to get the expected
+     *         response.
+     */
+    public String setRedirect(
+            String requestPath, String targetPath) {
+        List<Pair<String, String>> responseHeaders = new ArrayList<Pair<String, String>>();
+        responseHeaders.add(Pair.create("Location", targetPath));
+
+        return setResponseInternal(requestPath, targetPath.getBytes(), responseHeaders, null,
+                RESPONSE_STATUS_MOVED_TEMPORARILY);
+    }
+
+    /**
+     * Sets a base64 encoded response to be returned when a particular request path is passed
+     * in (with the option to specify additional headers).
+     *
+     * @param requestPath The path to respond to.
+     * @param base64EncodedResponse The response body that is base64 encoded. The actual server
+     *                              response will the decoded binary form.
+     * @param responseHeaders Any additional headers that should be returned along with the
+     *                        response (null is acceptable).
+     * @return The full URL including the path that should be requested to get the expected
+     *         response.
+     */
+    public String setResponseBase64(
+            String requestPath, String base64EncodedResponse,
+            List<Pair<String, String>> responseHeaders) {
+        return setResponseInternal(
+                requestPath, Base64.decode(base64EncodedResponse, Base64.DEFAULT),
+                responseHeaders, null, RESPONSE_STATUS_NORMAL);
+    }
+
+    /**
+     * Get the number of requests was made at this path since it was last set.
+     */
+    public int getRequestCount(String requestPath) {
+        Integer count = null;
+        synchronized (mLock) {
+            count = mResponseCountMap.get(requestPath);
+        }
+        if (count == null) throw new IllegalArgumentException("Path not set: " + requestPath);
+        return count.intValue();
+    }
+
+    /**
+     * Returns the last HttpRequest at this path. Can return null if it is never requested.
+     */
+    public HttpRequest getLastRequest(String requestPath) {
+        synchronized (mLock) {
+            if (!mLastRequestMap.containsKey(requestPath))
+                throw new IllegalArgumentException("Path not set: " + requestPath);
+            return mLastRequestMap.get(requestPath);
+        }
+    }
+
+    public String getBaseUrl() {
+        return mServerUri + "/";
+    }
+
+    private URLConnection openConnection(URL url)
+            throws IOException, NoSuchAlgorithmException, KeyManagementException {
+        if (mSsl) {
+            // Install hostname verifiers and trust managers that don't do
+            // anything in order to get around the client not trusting
+            // the test server due to a lack of certificates.
+
+            HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
+            connection.setHostnameVerifier(new TestHostnameVerifier());
+
+            SSLContext context = SSLContext.getInstance("TLS");
+            TestTrustManager trustManager = new TestTrustManager();
+            context.init(null, new TestTrustManager[] {trustManager}, null);
+            connection.setSSLSocketFactory(context.getSocketFactory());
+
+            return connection;
+        } else {
+            return url.openConnection();
+        }
+    }
+
+    /**
+     * {@link X509TrustManager} that trusts everybody. This is used so that
+     * the client calling {@link TestWebServer#shutdown()} can issue a request
+     * for shutdown by blindly trusting the {@link TestWebServer}'s
+     * credentials.
+     */
+    private static class TestTrustManager implements X509TrustManager {
+        @Override
+        public void checkClientTrusted(X509Certificate[] chain, String authType) {
+            // Trust the TestWebServer...
+        }
+
+        @Override
+        public void checkServerTrusted(X509Certificate[] chain, String authType) {
+            // Trust the TestWebServer...
+        }
+
+        @Override
+        public X509Certificate[] getAcceptedIssuers() {
+            return null;
+        }
+    }
+
+    /**
+     * {@link HostnameVerifier} that verifies everybody. This permits
+     * the client to trust the web server and call
+     * {@link TestWebServer#shutdown()}.
+     */
+    private static class TestHostnameVerifier implements HostnameVerifier {
+        @Override
+        public boolean verify(String hostname, SSLSession session) {
+            return true;
+        }
+    }
+
+    private void servedResponseFor(String path, HttpRequest request) {
+        synchronized (mLock) {
+            mResponseCountMap.put(path, Integer.valueOf(
+                    mResponseCountMap.get(path).intValue() + 1));
+            mLastRequestMap.put(path, request);
+        }
+    }
+
+    /**
+     * Generate a response to the given request.
+     *
+     * <p>Always executed on the background server thread.
+     *
+     * <p>If there is an action associated with the response, it will be executed inside of
+     * this function.
+     *
+     * @throws InterruptedException
+     */
+    private HttpResponse getResponse(HttpRequest request) throws InterruptedException {
+        assert Thread.currentThread() == mServerThread
+                : "getResponse called from non-server thread";
+
+        RequestLine requestLine = request.getRequestLine();
+        HttpResponse httpResponse = null;
+        Log.i(TAG, requestLine.getMethod() + ": " + requestLine.getUri());
+        String uriString = requestLine.getUri();
+        URI uri = URI.create(uriString);
+        String path = uri.getPath();
+
+        Response response = null;
+        synchronized (mLock) {
+            response = mResponseMap.get(path);
+        }
+        if (path.equals(SHUTDOWN_PREFIX)) {
+            httpResponse = createResponse(HttpStatus.SC_OK);
+        } else if (response == null) {
+            httpResponse = createResponse(HttpStatus.SC_NOT_FOUND);
+        } else if (response.mIsNotFound) {
+            httpResponse = createResponse(HttpStatus.SC_NOT_FOUND);
+            servedResponseFor(path, request);
+        } else if (response.mIsRedirect) {
+            httpResponse = createResponse(HttpStatus.SC_MOVED_TEMPORARILY);
+            for (Pair<String, String> header : response.mResponseHeaders) {
+                httpResponse.addHeader(header.first, header.second);
+            }
+            servedResponseFor(path, request);
+        } else {
+            if (response.mResponseAction != null) response.mResponseAction.run();
+
+            httpResponse = createResponse(HttpStatus.SC_OK);
+            ByteArrayEntity entity = createEntity(response.mResponseData);
+            httpResponse.setEntity(entity);
+            httpResponse.setHeader("Content-Length", "" + entity.getContentLength());
+            for (Pair<String, String> header : response.mResponseHeaders) {
+                httpResponse.addHeader(header.first, header.second);
+            }
+            servedResponseFor(path, request);
+        }
+        StatusLine sl = httpResponse.getStatusLine();
+        Log.i(TAG, sl.getStatusCode() + "(" + sl.getReasonPhrase() + ")");
+        setDateHeaders(httpResponse);
+        return httpResponse;
+    }
+
+    private void setDateHeaders(HttpResponse response) {
+        response.addHeader("Date", DateUtils.formatDate(new Date(), DateUtils.PATTERN_RFC1123));
+    }
+
+    /**
+     * Create an empty response with the given status.
+     */
+    private HttpResponse createResponse(int status) {
+        HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_0, status, null);
+        String reason = null;
+
+        // This synchronized silences findbugs.
+        synchronized (TestWebServer.class) {
+            if (sReasons == null) {
+                sReasons = new Hashtable<Integer, String>();
+                sReasons.put(HttpStatus.SC_UNAUTHORIZED, "Unauthorized");
+                sReasons.put(HttpStatus.SC_NOT_FOUND, "Not Found");
+                sReasons.put(HttpStatus.SC_FORBIDDEN, "Forbidden");
+                sReasons.put(HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily");
+            }
+            // Fill in error reason. Avoid use of the ReasonPhraseCatalog, which is
+            // Locale-dependent.
+            reason = sReasons.get(status);
+        }
+
+        if (reason != null) {
+            StringBuffer buf = new StringBuffer("<html><head><title>");
+            buf.append(reason);
+            buf.append("</title></head><body>");
+            buf.append(reason);
+            buf.append("</body></html>");
+            ByteArrayEntity entity = createEntity(buf.toString().getBytes());
+            response.setEntity(entity);
+            response.setHeader("Content-Length", "" + entity.getContentLength());
+        }
+        return response;
+    }
+
+    /**
+     * Create a string entity for the given content.
+     */
+    private ByteArrayEntity createEntity(byte[] data) {
+        ByteArrayEntity entity = new ByteArrayEntity(data);
+        entity.setContentType("text/html");
+        return entity;
+    }
+
+    private static class ServerThread extends Thread {
+        private TestWebServer mServer;
+        private ServerSocket mSocket;
+        private boolean mIsSsl;
+        private boolean mIsCancelled;
+        private SSLContext mSslContext;
+
+        /**
+         * Defines the keystore contents for the server, BKS version. Holds just a
+         * single self-generated key. The subject name is "Test Server".
+         */
+        private static final String SERVER_KEYS_BKS =
+            "AAAAAQAAABQDkebzoP1XwqyWKRCJEpn/t8dqIQAABDkEAAVteWtleQAAARpYl20nAAAAAQAFWC41" +
+            "MDkAAAJNMIICSTCCAbKgAwIBAgIESEfU1jANBgkqhkiG9w0BAQUFADBpMQswCQYDVQQGEwJVUzET" +
+            "MBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEBxMDTVRWMQ8wDQYDVQQKEwZHb29nbGUxEDAOBgNV" +
+            "BAsTB0FuZHJvaWQxFDASBgNVBAMTC1Rlc3QgU2VydmVyMB4XDTA4MDYwNTExNTgxNFoXDTA4MDkw" +
+            "MzExNTgxNFowaTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExDDAKBgNVBAcTA01U" +
+            "VjEPMA0GA1UEChMGR29vZ2xlMRAwDgYDVQQLEwdBbmRyb2lkMRQwEgYDVQQDEwtUZXN0IFNlcnZl" +
+            "cjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0LIdKaIr9/vsTq8BZlA3R+NFWRaH4lGsTAQy" +
+            "DPMF9ZqEDOaL6DJuu0colSBBBQ85hQTPa9m9nyJoN3pEi1hgamqOvQIWcXBk+SOpUGRZZFXwniJV" +
+            "zDKU5nE9MYgn2B9AoiH3CSuMz6HRqgVaqtppIe1jhukMc/kHVJvlKRNy9XMCAwEAATANBgkqhkiG" +
+            "9w0BAQUFAAOBgQC7yBmJ9O/eWDGtSH9BH0R3dh2NdST3W9hNZ8hIa8U8klhNHbUCSSktZmZkvbPU" +
+            "hse5LI3dh6RyNDuqDrbYwcqzKbFJaq/jX9kCoeb3vgbQElMRX8D2ID1vRjxwlALFISrtaN4VpWzV" +
+            "yeoHPW4xldeZmoVtjn8zXNzQhLuBqX2MmAAAAqwAAAAUvkUScfw9yCSmALruURNmtBai7kQAAAZx" +
+            "4Jmijxs/l8EBaleaUru6EOPioWkUAEVWCxjM/TxbGHOi2VMsQWqRr/DZ3wsDmtQgw3QTrUK666sR" +
+            "MBnbqdnyCyvM1J2V1xxLXPUeRBmR2CXorYGF9Dye7NkgVdfA+9g9L/0Au6Ugn+2Cj5leoIgkgApN" +
+            "vuEcZegFlNOUPVEs3SlBgUF1BY6OBM0UBHTPwGGxFBBcetcuMRbUnu65vyDG0pslT59qpaR0TMVs" +
+            "P+tcheEzhyjbfM32/vwhnL9dBEgM8qMt0sqF6itNOQU/F4WGkK2Cm2v4CYEyKYw325fEhzTXosck" +
+            "MhbqmcyLab8EPceWF3dweoUT76+jEZx8lV2dapR+CmczQI43tV9btsd1xiBbBHAKvymm9Ep9bPzM" +
+            "J0MQi+OtURL9Lxke/70/MRueqbPeUlOaGvANTmXQD2OnW7PISwJ9lpeLfTG0LcqkoqkbtLKQLYHI" +
+            "rQfV5j0j+wmvmpMxzjN3uvNajLa4zQ8l0Eok9SFaRr2RL0gN8Q2JegfOL4pUiHPsh64WWya2NB7f" +
+            "V+1s65eA5ospXYsShRjo046QhGTmymwXXzdzuxu8IlnTEont6P4+J+GsWk6cldGbl20hctuUKzyx" +
+            "OptjEPOKejV60iDCYGmHbCWAzQ8h5MILV82IclzNViZmzAapeeCnexhpXhWTs+xDEYSKEiG/camt" +
+            "bhmZc3BcyVJrW23PktSfpBQ6D8ZxoMfF0L7V2GQMaUg+3r7ucrx82kpqotjv0xHghNIm95aBr1Qw" +
+            "1gaEjsC/0wGmmBDg1dTDH+F1p9TInzr3EFuYD0YiQ7YlAHq3cPuyGoLXJ5dXYuSBfhDXJSeddUkl" +
+            "k1ufZyOOcskeInQge7jzaRfmKg3U94r+spMEvb0AzDQVOKvjjo1ivxMSgFRZaDb/4qw=";
+
+        private static final String PASSWORD = "android";
+
+        /**
+         * Loads a keystore from a base64-encoded String. Returns the KeyManager[]
+         * for the result.
+         */
+        private KeyManager[] getKeyManagers() throws Exception {
+            byte[] bytes = Base64.decode(SERVER_KEYS_BKS, Base64.DEFAULT);
+            InputStream inputStream = new ByteArrayInputStream(bytes);
+
+            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+            keyStore.load(inputStream, PASSWORD.toCharArray());
+            inputStream.close();
+
+            String algorithm = KeyManagerFactory.getDefaultAlgorithm();
+            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(algorithm);
+            keyManagerFactory.init(keyStore, PASSWORD.toCharArray());
+
+            return keyManagerFactory.getKeyManagers();
+        }
+
+
+        public ServerThread(TestWebServer server, boolean ssl) throws Exception {
+            super("ServerThread");
+            mServer = server;
+            mIsSsl = ssl;
+            int retry = 3;
+            while (true) {
+                try {
+                    if (mIsSsl) {
+                        mSslContext = SSLContext.getInstance("TLS");
+                        mSslContext.init(getKeyManagers(), null, null);
+                        mSocket = mSslContext.getServerSocketFactory().createServerSocket(0);
+                    } else {
+                        mSocket = new ServerSocket(0);
+                    }
+                    return;
+                } catch (IOException e) {
+                    Log.w(TAG, e);
+                    if (--retry == 0) {
+                        throw e;
+                    }
+                    // sleep in case server socket is still being closed
+                    Thread.sleep(1000);
+                }
+            }
+        }
+
+        @Override
+        public void run() {
+            HttpParams params = new BasicHttpParams();
+            params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_0);
+            while (!mIsCancelled) {
+                try {
+                    Socket socket = mSocket.accept();
+                    DefaultHttpServerConnection conn = new DefaultHttpServerConnection();
+                    conn.bind(socket, params);
+
+                    // Determine whether we need to shutdown early before
+                    // parsing the response since conn.close() will crash
+                    // for SSL requests due to UnsupportedOperationException.
+                    HttpRequest request = conn.receiveRequestHeader();
+                    if (isShutdownRequest(request)) {
+                        mIsCancelled = true;
+                    }
+
+                    HttpResponse response = mServer.getResponse(request);
+                    conn.sendResponseHeader(response);
+                    conn.sendResponseEntity(response);
+                    conn.close();
+
+                } catch (IOException e) {
+                    // normal during shutdown, ignore
+                    Log.w(TAG, e);
+                } catch (HttpException e) {
+                    Log.w(TAG, e);
+                } catch (InterruptedException e) {
+                    Log.w(TAG, e);
+                } catch (UnsupportedOperationException e) {
+                    // DefaultHttpServerConnection's close() throws an
+                    // UnsupportedOperationException.
+                    Log.w(TAG, e);
+                }
+            }
+            try {
+                mSocket.close();
+            } catch (IOException ignored) {
+                // safe to ignore
+            }
+        }
+
+        private boolean isShutdownRequest(HttpRequest request) {
+            RequestLine requestLine = request.getRequestLine();
+            String uriString = requestLine.getUri();
+            URI uri = URI.create(uriString);
+            String path = uri.getPath();
+            return path.equals(SHUTDOWN_PREFIX);
+        }
+    }
+}
diff --git a/suite/audio_quality/Android.mk b/suite/audio_quality/Android.mk
index 65abd23..491596e 100644
--- a/suite/audio_quality/Android.mk
+++ b/suite/audio_quality/Android.mk
@@ -22,7 +22,7 @@
 CTS_AUDIO_INSTALL_DIR := $(HOST_OUT)/cts-audio-quality/android-cts-audio-quality
 CTS_AUDIO_QUALITY_ZIP := $(HOST_OUT)/cts-audio-quality/android-cts-audio-quality.zip
 
-cts_audio_quality_client_apk := $(TARGET_OUT_DATA_APPS)/CtsAudioClient.apk
+cts_audio_quality_client_apk := $(TARGET_OUT_DATA_APPS)/CtsAudioClient/CtsAudioClient.apk
 cts_audio_quality_host_bins := $(HOST_OUT)/bin/cts_audio_quality_test $(HOST_OUT)/bin/cts_audio_quality
 $(CTS_AUDIO_QUALITY_ZIP): PRIVATE_CLIENT_APK := $(cts_audio_quality_client_apk)
 $(CTS_AUDIO_QUALITY_ZIP): PRIVATE_HOST_BINS := $(cts_audio_quality_host_bins)
diff --git a/suite/audio_quality/executable/Android.mk b/suite/audio_quality/executable/Android.mk
index dfb67d0..a37b987 100644
--- a/suite/audio_quality/executable/Android.mk
+++ b/suite/audio_quality/executable/Android.mk
@@ -29,7 +29,7 @@
 LOCAL_STATIC_LIBRARIES += libutils liblog libcutils libtinyalsa libtinyxml
 LOCAL_WHOLE_STATIC_LIBRARIES := libcts_audio_quality
 LOCAL_CFLAGS:= -g -fno-exceptions
-LOCAL_LDFLAGS:= -g -lrt -ldl -lstdc++ -lm -fno-exceptions
+LOCAL_LDFLAGS:= -g -lrt -ldl -lstdc++ -lm -fno-exceptions -lpthread
 LOCAL_MODULE:= cts_audio_quality
 include $(BUILD_HOST_EXECUTABLE)
 
diff --git a/suite/audio_quality/lib/src/audio/AudioPlaybackLocal.cpp b/suite/audio_quality/lib/src/audio/AudioPlaybackLocal.cpp
index fe91cb3..06c92d6 100644
--- a/suite/audio_quality/lib/src/audio/AudioPlaybackLocal.cpp
+++ b/suite/audio_quality/lib/src/audio/AudioPlaybackLocal.cpp
@@ -42,12 +42,12 @@
     : mHwId(hwId),
       mPcmHandle(NULL)
 {
-    LOGV("AudioPlaybackLocal %x", (unsigned int)this);
+    LOGV("AudioPlaybackLocal %x", (unsigned long)this);
 }
 
 AudioPlaybackLocal::~AudioPlaybackLocal()
 {
-    LOGV("~AudioPlaybackLocal %x", (unsigned int)this);
+    LOGV("~AudioPlaybackLocal %x", (unsigned long)this);
     releaseHw();
 }
 
@@ -108,7 +108,7 @@
 void AudioPlaybackLocal::releaseHw()
 {
     if (mPcmHandle != NULL) {
-        LOGV("releaseHw %x", (unsigned int)this);
+        LOGV("releaseHw %x", (unsigned long)this);
         doStop();
         pcm_close(mPcmHandle);
         mPcmHandle = NULL;
diff --git a/suite/audio_quality/lib/src/audio/AudioRecordingLocal.cpp b/suite/audio_quality/lib/src/audio/AudioRecordingLocal.cpp
index 1325949..eda705d 100644
--- a/suite/audio_quality/lib/src/audio/AudioRecordingLocal.cpp
+++ b/suite/audio_quality/lib/src/audio/AudioRecordingLocal.cpp
@@ -29,12 +29,12 @@
     : mHwId(hwId),
       mPcmHandle(NULL)
 {
-    LOGV("AudioRecordingLocal %x", (unsigned int)this);
+    LOGV("AudioRecordingLocal %x", (unsigned long)this);
 }
 
 AudioRecordingLocal::~AudioRecordingLocal()
 {
-    LOGV("~AudioRecordingLocal %x", (unsigned int)this);
+    LOGV("~AudioRecordingLocal %x", (unsigned long)this);
     releaseHw();
 }
 
@@ -97,7 +97,7 @@
 void AudioRecordingLocal::releaseHw()
 {
     if (mPcmHandle != NULL) {
-        LOGV("releaseHw %x", (unsigned int)this);
+        LOGV("releaseHw %x", (unsigned long)this);
         doStop();
         pcm_close(mPcmHandle);
         mPcmHandle = NULL;
diff --git a/suite/audio_quality/lib/src/task/TaskProcess.cpp b/suite/audio_quality/lib/src/task/TaskProcess.cpp
index f1e47af..061dda5 100644
--- a/suite/audio_quality/lib/src/task/TaskProcess.cpp
+++ b/suite/audio_quality/lib/src/task/TaskProcess.cpp
@@ -271,7 +271,7 @@
             list.push_back(param);
             LOGD(" val %s", param.getParamString().string());
         } else if (isInput && (StringUtil::compare(item[0], "consti") == 0)) {
-            long long value = atoll(item[1].string());
+            int64_t value = atoll(item[1].string());
             TaskCase::Value v(value);
             Param param(v);
             list.push_back(param);
diff --git a/suite/audio_quality/test/Android.mk b/suite/audio_quality/test/Android.mk
index 9e32557..4582fe7 100644
--- a/suite/audio_quality/test/Android.mk
+++ b/suite/audio_quality/test/Android.mk
@@ -34,7 +34,7 @@
 # functions and linker error happens
 LOCAL_WHOLE_STATIC_LIBRARIES := libcts_audio_quality
 LOCAL_CFLAGS:= -g -fno-exceptions
-LOCAL_LDFLAGS:= -g -lrt -ldl -lstdc++ -lm -fno-exceptions
+LOCAL_LDFLAGS:= -g -lrt -ldl -lstdc++ -lm -fno-exceptions -lpthread
 LOCAL_MODULE:= cts_audio_quality_test
 include $(BUILD_HOST_EXECUTABLE)
 
diff --git a/suite/audio_quality/test_description/dut_playback_sample.xml b/suite/audio_quality/test_description/dut_playback_sample.xml
new file mode 100644
index 0000000..f78209e
--- /dev/null
+++ b/suite/audio_quality/test_description/dut_playback_sample.xml
@@ -0,0 +1,38 @@
+<?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.
+-->
+
+<case name="dut_playback_sample" version="1.0" description="Sample test which check frequency of DUT's playback">
+	<setup>
+		<!-- prepare sound source id: to be used in output, sine 1000Hz, 4000ms long -->
+		<sound id="sound1" type="sin:32000:1000:4000" preload="1" />
+	</setup>
+	<action>
+		<sequential repeat="1" index="i">
+			<output device="DUT" id="sound1" gain="100" sync="start" waitforcompletion="0" />
+			<sequential repeat="1" index="j">
+				<!-- dummy recording to compensate for possible playback latency -->
+				<input device="host" id="dummy" gain="100" time="1000" sync="complete" />
+				<input device="host" id="host_in_$j" gain="100" time="2000" sync="complete" />
+			</sequential>
+		</sequential>
+		<sequential repeat="1" index="k">
+			<!-- input: host record, signal frequency in Hz, threshold, output: frequency calculated -->
+			<process method="script:playback_sample" input="id:host_in_$k,consti:1000,constf:5.0" output="val:freq_device_$k" />
+		</sequential>
+	</action>
+	<save file="host_in_.*" report="freq_device_.*" />
+</case>
diff --git a/suite/audio_quality/test_description/processing/playback_sample.py b/suite/audio_quality/test_description/processing/playback_sample.py
new file mode 100644
index 0000000..79e8d53
--- /dev/null
+++ b/suite/audio_quality/test_description/processing/playback_sample.py
@@ -0,0 +1,63 @@
+#!/usr/bin/python
+
+# 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.
+
+from consts import *
+
+# Sample test for dut_playback_sample case
+# Input: host recording (mono),
+#        frequency of sine in Hz (i64)
+#        pass level threshold (double)
+# Output: device (double) frequency
+
+def playback_sample(inputData, inputTypes):
+    output = []
+    outputData = []
+    outputTypes = []
+    # basic sanity check
+    inputError = False
+    if (inputTypes[0] != TYPE_MONO):
+        inputError = True
+    if (inputTypes[1] != TYPE_I64):
+        inputError = True
+    if (inputTypes[2] != TYPE_DOUBLE):
+        inputError = True
+    if inputError:
+        output.append(RESULT_ERROR)
+        output.append(outputData)
+        output.append(outputTypes)
+        return output
+
+    hostRecording = inputData[0]
+    signalFrequency = inputData[1]
+    threshold = inputData[2]
+    samplingRate = 44100
+
+    freq = calc_freq(hostRecording, samplingRate)
+    print "Expected Freq ", signalFrequency, "Actual Freq ", freq, "Threshold % ", threshold
+    diff = abs(freq - signalFrequency)
+    if (diff < threshold):
+        output.append(RESULT_PASS)
+    else:
+        output.append(RESULT_OK)
+    outputData.append(freq)
+    outputTypes.append(TYPE_DOUBLE)
+    output.append(outputData)
+    output.append(outputTypes)
+    return output
+
+def calc_freq(recording, samplingRate):
+    #This would calculate the frequency of recording, but is skipped in this sample test for brevity
+    return 32000
\ No newline at end of file
diff --git a/suite/cts/deviceTests/browserbench/Android.mk b/suite/cts/deviceTests/browserbench/Android.mk
index 6fdb06d..3696bcd 100644
--- a/suite/cts/deviceTests/browserbench/Android.mk
+++ b/suite/cts/deviceTests/browserbench/Android.mk
@@ -18,15 +18,13 @@
 # don't include this package in any target
 LOCAL_MODULE_TAGS := optional
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner ctstestserver
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsDeviceBrowserBench
 
-LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := 16
 
 include $(BUILD_CTS_PACKAGE)
 
diff --git a/suite/cts/deviceTests/browserbench/AndroidManifest.xml b/suite/cts/deviceTests/browserbench/AndroidManifest.xml
index 16626ad..4bf5b5e 100644
--- a/suite/cts/deviceTests/browserbench/AndroidManifest.xml
+++ b/suite/cts/deviceTests/browserbench/AndroidManifest.xml
@@ -24,6 +24,6 @@
     <application>
         <uses-library android:name="android.test.runner" />
     </application>
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
             android:targetPackage="com.android.cts.browser" />
 </manifest>
diff --git a/suite/cts/deviceTests/browserbench/src/com/android/cts/browser/BrowserBenchTest.java b/suite/cts/deviceTests/browserbench/src/com/android/cts/browser/BrowserBenchTest.java
index 81e6a21..d74ddb2 100644
--- a/suite/cts/deviceTests/browserbench/src/com/android/cts/browser/BrowserBenchTest.java
+++ b/suite/cts/deviceTests/browserbench/src/com/android/cts/browser/BrowserBenchTest.java
@@ -16,7 +16,6 @@
 
 package com.android.cts.browser;
 
-import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.cts.util.WatchDog;
@@ -72,10 +71,12 @@
     private volatile int mRunIndex;
     /** stores results for each runs. last entry will be the final score. */
     private LinkedHashMap<String, double[]> mResultsMap;
+    private PackageManager mPackageManager;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+        mPackageManager = getInstrumentation().getContext().getPackageManager();
         mWebServer = new CtsTestServer(getContext()) {
             @Override
             protected HttpResponse onPost(HttpRequest request) throws Exception {
@@ -126,8 +127,8 @@
 
     @TimeoutReq(minutes = 60)
     public void testOctane() throws InterruptedException {
-        if (!hasWebViewFeature(getContext())) {
-            Log.w(TAG, "Skipping testOctane");
+        if (!isBrowserSupported()) {
+            Log.i(TAG, "Skipping test for device with no supported browser");
             return;
         }
         String url = mWebServer.getAssetUrl(OCTANE_START_FILE) + "?auto=1";
@@ -174,8 +175,12 @@
         }
     }
 
-    private static boolean hasWebViewFeature(Context context) {
-        // Query the system property that determines if there is a functional WebView on the device
-        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WEBVIEW);
+    /**
+     * @return true iff this device is has a working browser.
+     */
+    private boolean isBrowserSupported() {
+        return !(mPackageManager.hasSystemFeature("android.hardware.type.television")
+                 || mPackageManager.hasSystemFeature("android.software.leanback")
+                 || mPackageManager.hasSystemFeature("android.hardware.type.watch"));
     }
 }
diff --git a/suite/cts/deviceTests/dram/Android.mk b/suite/cts/deviceTests/dram/Android.mk
index 1935483..879d151 100644
--- a/suite/cts/deviceTests/dram/Android.mk
+++ b/suite/cts/deviceTests/dram/Android.mk
@@ -16,9 +16,10 @@
 include $(CLEAR_VARS)
 
 # don't include this package in any target
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
 
 LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
 
diff --git a/suite/cts/deviceTests/dram/AndroidManifest.xml b/suite/cts/deviceTests/dram/AndroidManifest.xml
index 70f6b11..c9aaf3d 100644
--- a/suite/cts/deviceTests/dram/AndroidManifest.xml
+++ b/suite/cts/deviceTests/dram/AndroidManifest.xml
@@ -23,7 +23,7 @@
     <application>
         <uses-library android:name="android.test.runner" />
     </application>
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
             android:targetPackage="com.android.cts.dram"
             android:label="DRAM bandwidth measurement" />
 </manifest>
diff --git a/suite/cts/deviceTests/filesystemperf/Android.mk b/suite/cts/deviceTests/filesystemperf/Android.mk
index 5f0606e..843d21a 100644
--- a/suite/cts/deviceTests/filesystemperf/Android.mk
+++ b/suite/cts/deviceTests/filesystemperf/Android.mk
@@ -18,8 +18,6 @@
 # don't include this package in any target
 LOCAL_MODULE_TAGS := optional
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/suite/cts/deviceTests/filesystemperf/AndroidManifest.xml b/suite/cts/deviceTests/filesystemperf/AndroidManifest.xml
index dc90a94..329bf19 100644
--- a/suite/cts/deviceTests/filesystemperf/AndroidManifest.xml
+++ b/suite/cts/deviceTests/filesystemperf/AndroidManifest.xml
@@ -23,7 +23,7 @@
     <application>
         <uses-library android:name="android.test.runner" />
     </application>
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
             android:targetPackage="com.android.cts.filesystemperf"
             android:label="UI Latency measurement" />
 </manifest>
diff --git a/suite/cts/deviceTests/filesystemperf/src/com/android/cts/filesystemperf/FileUtil.java b/suite/cts/deviceTests/filesystemperf/src/com/android/cts/filesystemperf/FileUtil.java
old mode 100644
new mode 100755
index b342b61..6231774
--- a/suite/cts/deviceTests/filesystemperf/src/com/android/cts/filesystemperf/FileUtil.java
+++ b/suite/cts/deviceTests/filesystemperf/src/com/android/cts/filesystemperf/FileUtil.java
@@ -244,6 +244,7 @@
         long memSize = SystemUtil.getTotalMemory(context);
         long diskSizeTarget = (2 * memSize / bufferSize) * bufferSize;
         final long minimumDiskSize = (512L * 1024L * 1024L / bufferSize) * bufferSize;
+        final long reservedDiskSize = (50L * 1024L * 1024L / bufferSize) * bufferSize;
         if ( diskSizeTarget < minimumDiskSize ) {
             diskSizeTarget = minimumDiskSize;
         }
@@ -251,6 +252,9 @@
             Log.i(TAG, "Free disk size " + freeDisk + " too small");
             return 0;
         }
+        if ((freeDisk - diskSizeTarget) < reservedDiskSize) {
+            diskSizeTarget -= reservedDiskSize;
+        }
         return diskSizeTarget;
     }
 
diff --git a/suite/cts/deviceTests/opengl/Android.mk b/suite/cts/deviceTests/opengl/Android.mk
index 1b7d42b..0708efb 100644
--- a/suite/cts/deviceTests/opengl/Android.mk
+++ b/suite/cts/deviceTests/opengl/Android.mk
@@ -16,9 +16,10 @@
 include $(CLEAR_VARS)
 
 # don't include this package in any target
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
 
 LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
 
@@ -32,4 +33,4 @@
 
 include $(BUILD_CTS_PACKAGE)
 
-include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/suite/cts/deviceTests/opengl/AndroidManifest.xml b/suite/cts/deviceTests/opengl/AndroidManifest.xml
index a0273ec..05fb5be 100644
--- a/suite/cts/deviceTests/opengl/AndroidManifest.xml
+++ b/suite/cts/deviceTests/opengl/AndroidManifest.xml
@@ -46,7 +46,7 @@
     </application>
 
     <instrumentation
-        android:name="android.test.InstrumentationCtsTestRunner"
+        android:name="android.support.test.runner.AndroidJUnitRunner"
         android:label="OpenGL ES 2.0 Benchmark"
         android:targetPackage="com.android.cts.opengl" />
 
diff --git a/suite/cts/deviceTests/opengl/jni/graphics/GLUtils.cpp b/suite/cts/deviceTests/opengl/jni/graphics/GLUtils.cpp
index 9076f39..ea166a1 100644
--- a/suite/cts/deviceTests/opengl/jni/graphics/GLUtils.cpp
+++ b/suite/cts/deviceTests/opengl/jni/graphics/GLUtils.cpp
@@ -77,7 +77,8 @@
 }
 
 static int readInt(char* b) {
-    return (((int) b[0]) << 24) | (((int) b[1]) << 16) | (((int) b[2]) << 8) | ((int) b[3]);
+    unsigned char* ub = (unsigned char*) b;
+    return (((int) ub[0]) << 24) | (((int) ub[1]) << 16) | (((int) ub[2]) << 8) | ((int) ub[3]);
 }
 
 static float readFloat(char* b) {
diff --git a/suite/cts/deviceTests/opengl/src/com/android/cts/opengl/primitive/GLPrimitiveBenchmark.java b/suite/cts/deviceTests/opengl/src/com/android/cts/opengl/primitive/GLPrimitiveBenchmark.java
index 6c2c87d..c177129 100644
--- a/suite/cts/deviceTests/opengl/src/com/android/cts/opengl/primitive/GLPrimitiveBenchmark.java
+++ b/suite/cts/deviceTests/opengl/src/com/android/cts/opengl/primitive/GLPrimitiveBenchmark.java
@@ -118,9 +118,8 @@
         intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_NUM_ITERATIONS, numIterations);
         intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_TIMEOUT, timeout);
 
-        GLPrimitiveActivity activity = null;
         setActivityIntent(intent);
-        activity = getActivity();
+        GLPrimitiveActivity activity = getActivity();
         if (activity != null) {
             activity.waitForCompletion();
             double[] fpsValues = activity.mFpsValues;
diff --git a/suite/cts/deviceTests/opengl/test/Android.mk b/suite/cts/deviceTests/opengl/test/Android.mk
index b571dbf..a4abe4f 100644
--- a/suite/cts/deviceTests/opengl/test/Android.mk
+++ b/suite/cts/deviceTests/opengl/test/Android.mk
@@ -27,7 +27,7 @@
 #$(info $(LOCAL_SRC_FILES))
 LOCAL_C_INCLUDES += external/gtest/include $(LOCAL_PATH)/../jni/graphics/
 LOCAL_STATIC_LIBRARIES := libutils libcutils libgtest_host libgtest_main_host liblog
-LOCAL_LDFLAGS:= -g -lrt -ldl -lstdc++ -lm -fno-exceptions
+LOCAL_LDFLAGS:= -g -lrt -ldl -lstdc++ -lm -fno-exceptions -lpthread
 LOCAL_MODULE:= cts_device_opengl_test
 include $(BUILD_HOST_EXECUTABLE)
 
diff --git a/suite/cts/deviceTests/simplecpu/Android.mk b/suite/cts/deviceTests/simplecpu/Android.mk
index 003b0f2..17e7506 100644
--- a/suite/cts/deviceTests/simplecpu/Android.mk
+++ b/suite/cts/deviceTests/simplecpu/Android.mk
@@ -16,9 +16,10 @@
 include $(CLEAR_VARS)
 
 # don't include this package in any target
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
 
 LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
 
diff --git a/suite/cts/deviceTests/simplecpu/AndroidManifest.xml b/suite/cts/deviceTests/simplecpu/AndroidManifest.xml
index 69e4ad2..e5c1c2b 100644
--- a/suite/cts/deviceTests/simplecpu/AndroidManifest.xml
+++ b/suite/cts/deviceTests/simplecpu/AndroidManifest.xml
@@ -23,7 +23,7 @@
     <application>
         <uses-library android:name="android.test.runner" />
     </application>
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
             android:targetPackage="com.android.cts.simplecpu"
             android:label="Very simple CPU benchmarking" />
 </manifest>
diff --git a/suite/cts/deviceTests/ui/Android.mk b/suite/cts/deviceTests/ui/Android.mk
index 17287b2..ee52172 100644
--- a/suite/cts/deviceTests/ui/Android.mk
+++ b/suite/cts/deviceTests/ui/Android.mk
@@ -20,8 +20,6 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/suite/cts/deviceTests/ui/AndroidManifest.xml b/suite/cts/deviceTests/ui/AndroidManifest.xml
index 1be3eed..b41008e7 100644
--- a/suite/cts/deviceTests/ui/AndroidManifest.xml
+++ b/suite/cts/deviceTests/ui/AndroidManifest.xml
@@ -36,8 +36,12 @@
     </application>
 
     <instrumentation
-        android:name="android.test.InstrumentationCtsTestRunner"
+        android:name="android.support.test.runner.AndroidJUnitRunner"
         android:label="UI Latency measurement"
-        android:targetPackage="com.android.cts.ui" />
+        android:targetPackage="com.android.cts.ui" >
+        <meta-data
+            android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
-</manifest>
\ No newline at end of file
+</manifest>
diff --git a/suite/cts/deviceTests/videoperf/Android.mk b/suite/cts/deviceTests/videoperf/Android.mk
index 6ace48f..cb398a9 100644
--- a/suite/cts/deviceTests/videoperf/Android.mk
+++ b/suite/cts/deviceTests/videoperf/Android.mk
@@ -18,8 +18,6 @@
 # don't include this package in any target
 LOCAL_MODULE_TAGS := optional
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/suite/cts/deviceTests/videoperf/AndroidManifest.xml b/suite/cts/deviceTests/videoperf/AndroidManifest.xml
index 631141d..ca01298b 100644
--- a/suite/cts/deviceTests/videoperf/AndroidManifest.xml
+++ b/suite/cts/deviceTests/videoperf/AndroidManifest.xml
@@ -23,7 +23,11 @@
     <application>
         <uses-library android:name="android.test.runner" />
     </application>
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
             android:targetPackage="com.android.cts.videoperf"
-            android:label="UI Latency measurement" />
+            android:label="UI Latency measurement" >
+        <meta-data
+            android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 </manifest>
diff --git a/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/VideoEncoderDecoderTest.java b/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/VideoEncoderDecoderTest.java
index fe28a96..a009ce2 100644
--- a/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/VideoEncoderDecoderTest.java
+++ b/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/VideoEncoderDecoderTest.java
@@ -387,31 +387,36 @@
             int res = codec.dequeueOutputBuffer(info, VIDEO_CODEC_WAIT_TIME_US);
             if (res >= 0) {
                 int outputBufIndex = res;
-                ByteBuffer buf = codecOutputBuffers[outputBufIndex];
-                if (VERBOSE && (outFrameCount == 0)) {
-                    printByteBuffer("Y ", buf, 0, 20);
-                    printByteBuffer("UV ", buf, mVideoWidth * mVideoHeight, 20);
-                    printByteBuffer("UV ", buf, mVideoWidth * mVideoHeight + mVideoWidth * 60, 20);
-                }
-                Point origin = getOrigin(outFrameCount);
-                for (int i = 0; i < PIXEL_CHECK_PER_FRAME; i++) {
-                    int w = mRandom.nextInt(mVideoWidth);
-                    int h = mRandom.nextInt(mVideoHeight);
-                    getPixelValuesFromYUVBuffers(origin.x, origin.y, w, h, expected);
-                    getPixelValuesFromOutputBuffer(buf, w, h, decoded);
-                    if (VERBOSE) {
-                        Log.i(TAG, outFrameCount + "-" + i + "- th round expcted " + expected.mY +
-                                "," + expected.mU + "," + expected.mV + "  decoded " + decoded.mY +
-                                "," + decoded.mU + "," + decoded.mV);
+
+                // only do YUV compare on EOS frame if the buffer size is none-zero
+                if (info.size > 0) {
+                    ByteBuffer buf = codecOutputBuffers[outputBufIndex];
+                    if (VERBOSE && (outFrameCount == 0)) {
+                        printByteBuffer("Y ", buf, 0, 20);
+                        printByteBuffer("UV ", buf, mVideoWidth * mVideoHeight, 20);
+                        printByteBuffer("UV ", buf,
+                                mVideoWidth * mVideoHeight + mVideoWidth * 60, 20);
                     }
-                    totalErrorSquared += expected.calcErrorSquared(decoded);
+                    Point origin = getOrigin(outFrameCount);
+                    for (int i = 0; i < PIXEL_CHECK_PER_FRAME; i++) {
+                        int w = mRandom.nextInt(mVideoWidth);
+                        int h = mRandom.nextInt(mVideoHeight);
+                        getPixelValuesFromYUVBuffers(origin.x, origin.y, w, h, expected);
+                        getPixelValuesFromOutputBuffer(buf, w, h, decoded);
+                        if (VERBOSE) {
+                            Log.i(TAG, outFrameCount + "-" + i + "- th round expcted " + expected.mY
+                                    + "," + expected.mU + "," + expected.mV + "  decoded "
+                                    + decoded.mY + "," + decoded.mU + "," + decoded.mV);
+                        }
+                        totalErrorSquared += expected.calcErrorSquared(decoded);
+                    }
+                    outFrameCount++;
                 }
                 codec.releaseOutputBuffer(outputBufIndex, false /* render */);
                 if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                     Log.d(TAG, "saw output EOS.");
                     sawOutputEOS = true;
                 }
-                outFrameCount++;
             } else if (res == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
                 codecOutputBuffers = codec.getOutputBuffers();
                 Log.d(TAG, "output buffers have changed.");
diff --git a/suite/cts/hostTests/jank/Android.mk b/suite/cts/hostTests/jank/Android.mk
index a7d85de..a1f4d90 100644
--- a/suite/cts/hostTests/jank/Android.mk
+++ b/suite/cts/hostTests/jank/Android.mk
@@ -22,7 +22,7 @@
 
 LOCAL_MODULE := CtsHostJank
 
-LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt ddmlib-prebuilt
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
 
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 
diff --git a/suite/cts/hostTests/jank/src/com/android/cts/jank/CtsHostJankTest.java b/suite/cts/hostTests/jank/src/com/android/cts/jank/CtsHostJankTest.java
index f8c7ec1..e196bfb 100644
--- a/suite/cts/hostTests/jank/src/com/android/cts/jank/CtsHostJankTest.java
+++ b/suite/cts/hostTests/jank/src/com/android/cts/jank/CtsHostJankTest.java
@@ -23,16 +23,19 @@
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
 import com.android.tradefed.testtype.IBuildReceiver;
 
 import java.io.File;
 import java.util.HashMap;
 import java.util.Scanner;
 
-public class CtsHostJankTest extends DeviceTestCase implements IBuildReceiver {
+public class CtsHostJankTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
 
     private static final String TAG = CtsHostJankTest.class.getSimpleName();
     private static final String DEVICE_LOCATION = "/data/local/tmp/";
+    // FIXME uiautomator is deprecated and does not support --abi flag
     private static final String RUN_UI_AUTOMATOR_CMD = "uiautomator runtest %s -c %s";
     private final String mHostTestClass;
     private final String mDeviceTestClass;
@@ -40,6 +43,7 @@
     private final String mJarPath;
     protected ITestDevice mDevice;
     protected CtsBuildHelper mBuild;
+    protected IAbi mAbi;
 
     public CtsHostJankTest(String jarName, String deviceTestClass, String hostTestClass) {
         this.mHostTestClass = hostTestClass;
@@ -49,6 +53,11 @@
     }
 
     @Override
+    public void setAbi(IAbi abi) {
+        mAbi = abi;
+    }
+
+    @Override
     public void setBuild(IBuildInfo buildInfo) {
         mBuild = CtsBuildHelper.createBuildHelper(buildInfo);
     }
@@ -80,6 +89,7 @@
                 new IShellOutputReceiver() {
                     private StringBuilder sb = new StringBuilder();
 
+                    @Override
                     public void addOutput(byte[] data, int offset, int length) {
                         byte[] raw = new byte[length];
                         for (int i = 0; i < length; i++) {
@@ -88,10 +98,12 @@
                         sb.append(new String(raw));
                     }
 
+                    @Override
                     public void flush() {
                         Log.logAndDisplay(LogLevel.INFO, TAG, sb.toString());
                     }
 
+                    @Override
                     public boolean isCancelled() {
                         return false;
                     }
@@ -109,6 +121,7 @@
                 results.put(parts[0], Double.parseDouble(parts[1]));
             }
         }
+        in.close();
         Log.logAndDisplay(LogLevel.INFO, TAG, "Results: " + results);
         assertEquals("Could not parse the results file: ", 4, results.size());
 
@@ -118,8 +131,8 @@
         double avgMaxAccFrames = results.get("average of max accumulated frames");
 
         // Create and deliver the report.
-        HostReportLog report =
-                new HostReportLog(mDevice.getSerialNumber(), mHostTestClass + "#" + testName);
+        HostReportLog report = new HostReportLog(mDevice.getSerialNumber(), mAbi.getName(),
+                mHostTestClass + "#" + testName);
         report.printValue(
                 "Average Frame Rate", avgFrameRate, ResultType.HIGHER_BETTER, ResultUnit.COUNT);
         report.printValue("Average of Maximum Accumulated Frames", avgMaxAccFrames,
diff --git a/suite/cts/hostTests/jank/src/com/android/cts/jank/opengl/CtsHostJankOpenGl.java b/suite/cts/hostTests/jank/src/com/android/cts/jank/opengl/CtsHostJankOpenGl.java
index ebd5bfa..2942ecf 100644
--- a/suite/cts/hostTests/jank/src/com/android/cts/jank/opengl/CtsHostJankOpenGl.java
+++ b/suite/cts/hostTests/jank/src/com/android/cts/jank/opengl/CtsHostJankOpenGl.java
@@ -14,7 +14,7 @@
 package com.android.cts.jank.opengl;
 
 import com.android.cts.jank.CtsHostJankTest;
-
+import com.android.cts.util.AbiUtils;
 import java.io.File;
 
 public class CtsHostJankOpenGl extends CtsHostJankTest {
@@ -36,7 +36,8 @@
         // Install the app.
         mDevice.uninstallPackage(APK_PACKAGE);
         File app = mBuild.getTestApp(APK);
-        mDevice.installPackage(app, false);
+        String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+        mDevice.installPackage(app, false, options);
     }
 
     @Override
diff --git a/suite/cts/hostTests/jank/src/com/android/cts/jank/ui/CtsHostJankUi.java b/suite/cts/hostTests/jank/src/com/android/cts/jank/ui/CtsHostJankUi.java
index 3027899..a07171e 100644
--- a/suite/cts/hostTests/jank/src/com/android/cts/jank/ui/CtsHostJankUi.java
+++ b/suite/cts/hostTests/jank/src/com/android/cts/jank/ui/CtsHostJankUi.java
@@ -14,7 +14,7 @@
 package com.android.cts.jank.ui;
 
 import com.android.cts.jank.CtsHostJankTest;
-
+import com.android.cts.util.AbiUtils;
 import java.io.File;
 
 public class CtsHostJankUi extends CtsHostJankTest {
@@ -36,7 +36,8 @@
         // Install the app.
         mDevice.uninstallPackage(APK_PACKAGE);
         File app = mBuild.getTestApp(APK);
-        mDevice.installPackage(app, false);
+        String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+        mDevice.installPackage(app, false, options);
     }
 
     @Override
diff --git a/suite/cts/hostTests/uihost/.gitignore b/suite/cts/hostTests/uihost/.gitignore
new file mode 100644
index 0000000..5e56e04
--- /dev/null
+++ b/suite/cts/hostTests/uihost/.gitignore
@@ -0,0 +1 @@
+/bin
diff --git a/suite/cts/hostTests/uihost/Android.mk b/suite/cts/hostTests/uihost/Android.mk
index dd51b6b..67ebcbb 100644
--- a/suite/cts/hostTests/uihost/Android.mk
+++ b/suite/cts/hostTests/uihost/Android.mk
@@ -22,7 +22,7 @@
 
 LOCAL_MODULE := CtsHostUi
 
-LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt ddmlib-prebuilt junit
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
 
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 
diff --git a/suite/cts/hostTests/uihost/appA/Android.mk b/suite/cts/hostTests/uihost/appA/Android.mk
index 48d9009..3e76fdb 100644
--- a/suite/cts/hostTests/uihost/appA/Android.mk
+++ b/suite/cts/hostTests/uihost/appA/Android.mk
@@ -20,8 +20,6 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/suite/cts/hostTests/uihost/appB/Android.mk b/suite/cts/hostTests/uihost/appB/Android.mk
index 812637e..13af40f 100644
--- a/suite/cts/hostTests/uihost/appB/Android.mk
+++ b/suite/cts/hostTests/uihost/appB/Android.mk
@@ -20,8 +20,6 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/suite/cts/hostTests/uihost/control/Android.mk b/suite/cts/hostTests/uihost/control/Android.mk
index 565e2c0..3770918 100644
--- a/suite/cts/hostTests/uihost/control/Android.mk
+++ b/suite/cts/hostTests/uihost/control/Android.mk
@@ -20,8 +20,6 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/suite/cts/hostTests/uihost/control/AndroidManifest.xml b/suite/cts/hostTests/uihost/control/AndroidManifest.xml
index 9901d50..e4b10f2 100644
--- a/suite/cts/hostTests/uihost/control/AndroidManifest.xml
+++ b/suite/cts/hostTests/uihost/control/AndroidManifest.xml
@@ -24,5 +24,9 @@
     </application>
     <instrumentation
         android:targetPackage="com.android.cts.taskswitching.control"
-        android:name="android.test.InstrumentationCtsTestRunner" />
+        android:name="android.support.test.runner.AndroidJUnitRunner" >
+        <meta-data
+            android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 </manifest>
diff --git a/suite/cts/hostTests/uihost/src/com/android/cts/uihost/InstallTimeTest.java b/suite/cts/hostTests/uihost/src/com/android/cts/uihost/InstallTimeTest.java
index 63c2d84..75a2e92 100644
--- a/suite/cts/hostTests/uihost/src/com/android/cts/uihost/InstallTimeTest.java
+++ b/suite/cts/hostTests/uihost/src/com/android/cts/uihost/InstallTimeTest.java
@@ -18,6 +18,7 @@
 
 import com.android.cts.tradefed.build.CtsBuildHelper;
 import com.android.cts.tradefed.util.HostReportLog;
+import com.android.cts.util.AbiUtils;
 import com.android.cts.util.MeasureRun;
 import com.android.cts.util.MeasureTime;
 import com.android.cts.util.ResultType;
@@ -28,6 +29,8 @@
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
 import com.android.tradefed.testtype.IBuildReceiver;
 
 import java.io.File;
@@ -36,9 +39,10 @@
 /**
  * Test to measure installation time of a APK.
  */
-public class InstallTimeTest extends DeviceTestCase implements IBuildReceiver {
+public class InstallTimeTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
     private CtsBuildHelper mBuild;
     private ITestDevice mDevice;
+    private IAbi mAbi;
 
     private static final String TAG = "InstallTimeTest";
     static final String PACKAGE = "com.replica.replicaisland";
@@ -46,6 +50,11 @@
     private static final double OUTLIER_THRESHOLD = 0.1;
 
     @Override
+    public void setAbi(IAbi abi) {
+        mAbi = abi;
+    }
+
+    @Override
     public void setBuild(IBuildInfo buildInfo) {
         mBuild = CtsBuildHelper.createBuildHelper(buildInfo);
     }
@@ -64,8 +73,8 @@
     }
 
     public void testInstallTime() throws Exception {
-        HostReportLog report =
-                new HostReportLog(mDevice.getSerialNumber(), ReportLog.getClassMethodNames());
+        HostReportLog report = new HostReportLog(mDevice.getSerialNumber(), mAbi.getName(),
+                ReportLog.getClassMethodNames());
         final int NUMBER_REPEAT = 10;
         final CtsBuildHelper build = mBuild;
         final ITestDevice device = mDevice;
@@ -77,7 +86,8 @@
             @Override
             public void run(int i) throws Exception {
                 File app = build.getTestApp(APK);
-                device.installPackage(app, false);
+                String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+                device.installPackage(app, false, options);
             }
         });
         report.printArray("install time", result, ResultType.LOWER_BETTER,
diff --git a/suite/cts/hostTests/uihost/src/com/android/cts/uihost/TaskSwitchingTest.java b/suite/cts/hostTests/uihost/src/com/android/cts/uihost/TaskSwitchingTest.java
index 0bfecdc..894b824 100644
--- a/suite/cts/hostTests/uihost/src/com/android/cts/uihost/TaskSwitchingTest.java
+++ b/suite/cts/hostTests/uihost/src/com/android/cts/uihost/TaskSwitchingTest.java
@@ -17,23 +17,20 @@
 package com.android.cts.uihost;
 
 import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.cts.tradefed.result.CtsReportUtil;
 import com.android.cts.tradefed.util.CtsHostStore;
 import com.android.cts.tradefed.util.HostReportLog;
+import com.android.cts.util.AbiUtils;
 import com.android.cts.util.ReportLog;
 import com.android.cts.util.TimeoutReq;
-import com.android.ddmlib.Log;
-import com.android.ddmlib.Log.LogLevel;
 import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
 import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.ddmlib.testrunner.TestRunResult;
 import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.device.TestDeviceOptions;
 import com.android.tradefed.result.CollectingTestListener;
-import com.android.tradefed.result.TestResult;
-import com.android.tradefed.result.TestRunResult;
 import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
 import com.android.tradefed.testtype.IBuildReceiver;
 
 import java.io.File;
@@ -45,12 +42,13 @@
  * Actual test is done in device, but this host side code installs all necessary APKs
  * and starts device test which is in CtsDeviceTaskswitchingControl.
  */
-public class TaskSwitchingTest extends DeviceTestCase implements IBuildReceiver {
+public class TaskSwitchingTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {
     private static final String TAG = "TaskSwitchingTest";
-    private final static String CTS_RUNNER = "android.test.InstrumentationCtsTestRunner";
+    private final static String RUNNER = "android.support.test.runner.AndroidJUnitRunner";
     private CtsBuildHelper mBuild;
     private ITestDevice mDevice;
     private String mCtsReport = null;
+    private IAbi mAbi;
 
     static final String[] PACKAGES = {
         "com.android.cts.taskswitching.control",
@@ -64,6 +62,11 @@
     };
 
     @Override
+    public void setAbi(IAbi abi) {
+        mAbi = abi;
+    }
+
+    @Override
     public void setBuild(IBuildInfo buildInfo) {
         mBuild = CtsBuildHelper.createBuildHelper(buildInfo);
     }
@@ -72,10 +75,11 @@
     protected void setUp() throws Exception {
         super.setUp();
         mDevice = getDevice();
+        String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
         for (int i = 0; i < PACKAGES.length; i++) {
             mDevice.uninstallPackage(PACKAGES[i]);
             File app = mBuild.getTestApp(APKS[i]);
-            mDevice.installPackage(app, false);
+            mDevice.installPackage(app, false, options);
         }
     }
 
@@ -90,9 +94,10 @@
 
     @TimeoutReq(minutes = 30)
     public void testTaskswitching() throws Exception {
-        HostReportLog report =
-                new HostReportLog(mDevice.getSerialNumber(), ReportLog.getClassMethodNames());
-        RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(PACKAGES[0], CTS_RUNNER,
+        // TODO is this used?
+        HostReportLog report = new HostReportLog(mDevice.getSerialNumber(), mAbi.getName(),
+                ReportLog.getClassMethodNames());
+        RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(PACKAGES[0], RUNNER,
                 mDevice.getIDevice());
         LocalListener listener = new LocalListener();
         mDevice.runInstrumentationTests(testRunner, listener);
@@ -101,7 +106,7 @@
             fail(result.getRunFailureMessage());
         }
         assertNotNull("no performance data", mCtsReport);
-        CtsHostStore.storeCtsResult(mDevice.getSerialNumber(),
+        CtsHostStore.storeCtsResult(mDevice.getSerialNumber(), mAbi.getName(),
                 ReportLog.getClassMethodNames(), mCtsReport);
 
     }
@@ -110,7 +115,7 @@
         @Override
         public void testEnded(TestIdentifier test, Map<String, String> testMetrics) {
             // necessary as testMetrics passed from CollectingTestListerner is empty
-            mCtsReport = CtsReportUtil.getCtsResultFromMetrics(testMetrics);
+            mCtsReport = testMetrics.get("CTS_TEST_RESULT");
             super.testEnded(test, testMetrics);
         }
     }
diff --git a/tests/Android.mk b/tests/Android.mk
index a4cc38f..46a8ec2 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -12,34 +12,5 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)\
-              $(call all-renderscript-files-under, src)\
-              src/android/app/cts/ISecondary.aidl\
-              src/android/os/cts/IEmptyService.aidl\
-              src/android/security/cts/activity/ISecureRandomService.aidl
-
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
-LOCAL_JNI_SHARED_LIBRARIES := libcts_jni
-
-# Resource unit tests use a private locale and some densities
-LOCAL_AAPT_FLAGS = -c xx_YY -c cs -c small -c normal -c large -c xlarge \
-        -c 320dpi -c 240dpi -c 160dpi -c 32dpi \
-        --preferred-configurations 320dpi --preferred-configurations 240dpi \
-        --preferred-configurations 160dpi --preferred-configurations 32dpi
-
-LOCAL_PACKAGE_NAME := CtsTestStubs
-
-LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestserver ctstestrunner
-
-LOCAL_DEX_PREOPT := false
-
-include $(BUILD_PACKAGE)
-
 # Build the test APK using its own makefile, and any other CTS-related packages
-include $(call all-makefiles-under,$(LOCAL_PATH))
+include $(call all-subdir-makefiles)
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
deleted file mode 100644
index 29caf33..0000000
--- a/tests/AndroidManifest.xml
+++ /dev/null
@@ -1,1034 +0,0 @@
-<!--
- * Copyright (C) 2008 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="com.android.cts.stub">
-
-    <permission android:name="android.app.cts.permission.TEST_GRANTED"
-        android:protectionLevel="normal"
-            android:label="@string/permlab_testGranted"
-            android:description="@string/permdesc_testGranted">
-        <meta-data android:name="android.app.cts.string" android:value="foo" />
-        <meta-data android:name="android.app.cts.boolean" android:value="true" />
-        <meta-data android:name="android.app.cts.integer" android:value="100" />
-        <meta-data android:name="android.app.cts.color" android:value="#ff000000" />
-        <meta-data android:name="android.app.cts.float" android:value="100.1" />
-        <meta-data android:name="android.app.cts.reference" android:resource="@xml/metadata" />
-    </permission>
-
-    <uses-permission android:name="android.permission.GET_TASKS" />
-    <uses-permission android:name="android.permission.SET_WALLPAPER" />
-    <uses-permission android:name="android.permission.SET_TIME_ZONE" />
-    <uses-permission android:name="android.permission.WRITE_CALL_LOG" />
-    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
-    <uses-permission android:name="android.permission.WRITE_SOCIAL_STREAM" />
-    <uses-permission android:name="android.permission.READ_CALL_LOG" />
-    <uses-permission android:name="android.permission.READ_CONTACTS" />
-    <uses-permission android:name="android.permission.READ_SOCIAL_STREAM" />
-    <uses-permission android:name="android.permission.WRITE_CALENDAR" />
-    <uses-permission android:name="android.permission.READ_CALENDAR" />
-    <uses-permission android:name="android.permission.DEVICE_POWER" />
-    <uses-permission android:name="android.permission.STATUS_BAR" />
-    <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
-    <uses-permission android:name="android.permission.VIBRATE" />
-    <uses-permission android:name="android.permission.PERSISTENT_ACTIVITY" />
-    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
-    <uses-permission android:name="android.permission.INSTALL_PACKAGES" />
-    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
-    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
-    <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
-    <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
-    <uses-permission android:name="android.permission.WRITE_OWNER_DATA" />
-    <uses-permission android:name="android.permission.READ_OWNER_DATA" />
-    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
-    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
-    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
-    <uses-permission android:name="android.permission.DELETE_CACHE_FILES" />
-    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
-    <uses-permission android:name="android.permission.ADD_SYSTEM_SERVICE" />
-    <uses-permission android:name="android.permission.BROADCAST_STICKY" />
-    <uses-permission android:name="android.app.cts.permission.TEST_GRANTED" />
-    <uses-permission android:name="android.permission.INJECT_EVENTS" />
-    <uses-permission android:name="android.permission.INTERNET" />
-    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
-    <uses-permission android:name="android.permission.WAKE_LOCK" />
-    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
-    <uses-permission android:name="android.permission.CALL_PHONE" />
-    <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
-    <uses-permission android:name="android.permission.RECORD_AUDIO" />
-    <uses-permission android:name="android.permission.DUMP" />
-    <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" />
-    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
-    <uses-permission android:name="android.permission.WAKE_LOCK" />
-    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
-    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
-    <uses-permission android:name="android.permission.CAMERA" />
-    <uses-permission android:name="android.permission.SET_PREFERRED_APPLICATIONS" />
-    <uses-permission android:name="android.permission.INSTALL_PACKAGES" />
-    <uses-permission android:name="android.permission.GET_PACKAGE_SIZE" />
-    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
-    <uses-permission android:name="android.permission.SEND_SMS" />
-    <uses-permission android:name="android.permission.RECEIVE_SMS" />
-    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
-    <uses-permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS" />
-    <uses-permission android:name="com.android.browser.permission.WRITE_HISTORY_BOOKMARKS" />
-    <uses-permission android:name="android.permission.WRITE_USER_DICTIONARY" />
-    <uses-permission android:name="android.permission.READ_USER_DICTIONARY" />
-
-    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-    <uses-permission android:name="android.permission.READ_LOGS" />
-
-    <!-- telephony provider tests -->
-    <uses-permission android:name="android.permission.READ_SMS"/>
-    <uses-permission android:name="android.permission.WRITE_SMS"/>
-
-    <!-- content sync tests -->
-    <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
-    <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
-    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
-    <uses-permission android:name="android.permission.USE_CREDENTIALS" />
-    <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
-    <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
-    <uses-permission android:name="android.permission.READ_SYNC_STATS" />
-
-    <!-- Used for ClonedSecureRandomTest -->
-    <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
-
-    <!-- Used for Transmit IR Test -->
-    <uses-permission android:name="android.permission.TRANSMIT_IR" />
-
-    <!-- Used for SystemFeatures Test -->
-    <uses-permission android:name="android.permission.BODY_SENSORS"/>
-
-    <!-- Used for PackageManager test, don't delete this permission-tree -->
-    <permission-tree android:name="com.android.cts.stub.permission.TEST_DYNAMIC"
-                    android:label="Test Tree"/>
-
-    <!-- Used for PackageManager test, don't delete this permission-group -->
-    <permission-group android:name="android.permission-group.COST_MONEY"/>
-    <!-- Used for PackageManager test, don't delete! -->
-    <uses-configuration/>
-
-    <application android:label="Android TestCase"
-                android:icon="@drawable/size_48x48"
-                android:name="android.app.cts.MockApplication"
-                android:supportsRtl="true">
-
-        <activity android:name="android.app.cts.ActionBarActivity" />
-        <activity android:name="android.widget.cts.TwoLineListItemStubActivity"
-            android:label="TwoLineListItemStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.view.cts.ViewStubStubActivity"
-            android:label="ViewStubStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.ViewFlipperStubActivity"
-            android:label="ViewFlipperStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.app.cts.DialogStubActivity"
-            android:label="DialogStubActivity"
-            android:configChanges="keyboardHidden|orientation|screenSize">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.HorizontalScrollViewStubActivity"
-            android:label="HorizontalScrollViewStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.SlidingDrawerStubActivity"
-            android:label="SlidingDrawerStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.view.cts.UsingViewsStubActivity"
-            android:label="Using Views Test">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-        <activity android:name="android.view.cts.FocusHandlingStubActivity"
-            android:label="Focus Handling Test">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-        <activity android:name="android.app.cts.MockActivity" android:label="MockActivity">
-            <meta-data android:name="android.app.alias"
-                android:resource="@xml/alias" />
-            <meta-data android:name="android.app.intent.filter"
-                android:resource="@xml/intentfilter" />
-            <meta-data android:name="android.widget.layout"
-                android:resource="@xml/layout" />
-            <meta-data android:name="android.view.merge"
-                android:resource="@xml/merge" />
-        </activity>
-
-        <activity android:name="android.widget.cts.DigitalClockStubActivity"
-            android:label="DigitalClockStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.ImageViewStubActivity"
-            android:label="ImageViewStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.SeekBarStubActivity"
-            android:label="SeekBarStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.ScrollViewStubActivity"
-            android:label="ScrollViewStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.FrameLayoutStubActivity"
-            android:label="FrameLayoutStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.LinearLayoutStubActivity"
-            android:label="LinearLayoutStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.GridLayoutStubActivity"
-            android:label="GridLayoutStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.LayoutDirectionStubActivity"
-            android:label="LayoutDirectionStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.ProgressBarStubActivity"
-            android:label="ProgressBarStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.ChronometerStubActivity"
-            android:label="ChronometerStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.MediaControllerStubActivity"
-            android:label="MediaControllerStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.RatingBarStubActivity"
-            android:label="RatingBarStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.RemoteViewsStubActivity"
-            android:label="RemoteViewsStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.view.cts.ViewGroupStubActivity" android:label="ViewGroupStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-        <activity android:name="android.view.cts.ViewTestStubActivity"
-            android:label="ViewTestStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-        <activity android:name="android.view.cts.ViewLayoutPositionTestStubActivity"
-            android:label="ViewTestStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.view.cts.WindowStubActivity"
-            android:theme="@android:style/Theme.Holo.NoActionBar"
-            android:label="WindowStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.ViewGroupStubActivity"
-            android:label="WidgetViewGroupStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.VideoViewStubActivity"
-            android:configChanges="keyboardHidden|orientation|screenSize">
-            android:label="VideoViewStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.AutoCompleteStubActivity"
-            android:label="AutoCompleteStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.ViewAnimatorStubActivity" android:label="ViewAnimatorStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.GridViewStubActivity"
-            android:label="GridViewStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.RelativeLayoutStubActivity"
-            android:label="RelativeLayoutStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.FrameLayoutStubActivity"
-            android:label="FrameLayoutStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <service android:name="android.content.cts.MockContextWrapperService" />
-        <activity android:name=".content.ContextWrapperStubActivity"
-            android:label="ContextWrapperStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-            </intent-filter>
-        </activity>
-
-        <receiver android:name="android.content.cts.MockReceiverFirst">
-            <intent-filter android:priority="3">
-                <action android:name="android.content.cts.BroadcastReceiverTest.BROADCAST_TESTABORT" />
-            </intent-filter>
-        </receiver>
-        <receiver android:name="android.content.cts.MockReceiverAbort">
-            <intent-filter android:priority="2">
-                <action android:name="android.content.cts.BroadcastReceiverTest.BROADCAST_TESTABORT" />
-            </intent-filter>
-        </receiver>
-        <receiver android:name="android.content.cts.MockReceiver">
-            <intent-filter android:priority="1">
-                <action android:name="android.content.cts.BroadcastReceiverTest.BROADCAST_MOCKTEST" />
-                <action android:name="android.content.cts.BroadcastReceiverTest.BROADCAST_TESTABORT" />
-                <action android:name="android.content.cts.ContextWrapperTest.BROADCAST_TESTORDER" />
-            </intent-filter>
-        </receiver>
-
-        <activity android:name="android.provider.cts.BrowserStubActivity"
-            android:label="BrowserStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.content.cts.AvailableIntentsActivity"
-            android:label="AvailableIntentsActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.text.cts.EmojiStubActivity"
-            android:label="AvailableIntentsActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.TableStubActivity"
-            android:label="TableStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.TabHostStubActivity"
-            android:label="TabHostStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.view.animation.cts.AnimationTestStubActivity"
-            android:label="AnimationTestStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.view.animation.cts.GridLayoutAnimStubActivity"
-            android:label="GridLayoutAnimStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.view.animation.cts.LayoutAnimStubActivity"
-            android:label="LayoutAnimStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.webkit.cts.CookieSyncManagerStubActivity"
-            android:label="CookieSyncManagerStubActivity"
-            android:screenOrientation="nosensor">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.ExpandableListSimple"
-            android:label="ExpandableListSimple">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.StubActivity"
-            android:label="StubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.ExpandableListWithHeaders"
-            android:label="ExpandableListWithHeaders">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.GalleryStubActivity"
-            android:label="GalleryStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.MockPopupWindowStubActivity"
-            android:label="MockPopupWindowStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.ListViewStubActivity"
-            android:label="ListViewStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.TextViewStubActivity"
-            android:label="TextViewStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.DialerFilterStubActivity"
-            android:label="DialerFilterStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-        <activity android:name="android.widget.cts.MultiAutoCompleteTextViewStubActivity"
-            android:label="MultiAutoCompleteTextView Test Activity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.AdapterViewStubActivity"
-            android:label="AdapterViewStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.CheckedTextViewStubActivity"
-            android:label="CheckedTextViewStubActivity"/>
-
-        <activity android:name="android.hardware.cts.CameraStubActivity"
-            android:label="CameraStubActivity"
-            android:screenOrientation="landscape"
-            android:configChanges="keyboardHidden|orientation|screenSize">
-        </activity>
-
-        <activity android:name="android.view.inputmethod.cts.InputMethodStubActivity"
-            android:label="InputMethodStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-        <service android:name="android.view.inputmethod.cts.InputMethodInfoStub"
-            android:label="InputMethodInfoStub">
-            <intent-filter>
-                <action android:name="android.view.InputMethod" />
-            </intent-filter>
-            <meta-data android:name="android.view.im"
-                android:resource="@xml/method" />
-        </service>
-
-        <activity android:name="android.view.cts.MenuInflaterStubActivity"
-                                        android:label="MenuInflaterStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.text.method.cts.KeyListenerStubActivity"
-            android:label="KeyListenerStubActivity"/>
-
-        <activity android:name="android.text.method.cts.StubActivity"
-            android:label="StubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.text.style.cts.URLSpanStubActivity"
-            android:label="URLSpanStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.text.style.cts.MockURLSpanTestActivity"
-            android:label="MockURLSpanTestActivity"
-            android:launchMode="singleTask"
-            android:alwaysRetainTaskState="true"
-            android:configChanges="orientation|keyboardHidden">
-            <intent-filter>
-                <action android:name="android.intent.action.VIEW" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.BROWSABLE" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-                <data android:scheme="ctstest" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.widget.cts.ZoomButtonStubActivity"
-            android:label="ZoomButtonStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.view.cts.SurfaceViewStubActivity"
-            android:label="SurfaceViewStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.app.cts.MockApplicationActivity"
-            android:label="MockApplicationActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.app.cts.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" />
-                <data android:mimeType="vnd.android.cursor.dir/person" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.app.cts.AliasActivityStub">
-            <meta-data android:name="android.app.alias"
-                android:resource="@xml/alias" />
-        </activity>
-
-        <activity android:name="android.webkit.cts.WebViewStubActivity"
-            android:label="WebViewStubActivity"
-            android:screenOrientation="nosensor">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.webkit.cts.WebViewStartupStubActivity"
-            android:label="WebViewStartupStubActivity"
-            android:screenOrientation="nosensor">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.app.cts.ChildActivity"
-                        android:label="ChildActivity" />
-
-        <receiver android:name="android.app.cts.MockReceiver">
-            <intent-filter>
-                <action android:name="android.app.cts.PendingIntentTest.TEST_RECEIVER" />
-            </intent-filter>
-        </receiver>
-
-        <service android:name="android.app.cts.MockService" />
-
-        <activity android:name="android.app.cts.SearchManagerStubActivity"
-                android:label="SearchManagerStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.SEARCH" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-            <meta-data android:name="android.app.searchable" android:resource="@xml/searchable" />
-        </activity>
-
-        <service android:name="android.app.cts.LocalService">
-            <intent-filter>
-                <action android:name="android.app.cts.activity.SERVICE_LOCAL" />
-            </intent-filter>
-            <meta-data android:name="android.app.cts.string" android:value="foo" />
-            <meta-data android:name="android.app.cts.boolean" android:value="true" />
-            <meta-data android:name="android.app.cts.integer" android:value="100" />
-            <meta-data android:name="android.app.cts.color" android:value="#ff000000" />
-            <meta-data android:name="android.app.cts.float" android:value="100.1" />
-            <meta-data android:name="android.app.cts.reference" android:resource="@xml/metadata" />
-        </service>
-
-        <service android:name="android.app.cts.LocalGrantedService"
-             android:permission="android.app.cts.permission.TEST_GRANTED">
-            <intent-filter>
-                <action android:name="android.app.cts.activity.SERVICE_LOCAL_GRANTED" />
-            </intent-filter>
-        </service>
-
-        <service android:name="android.app.cts.LocalDeniedService"
-               android:permission="android.app.cts.permission.TEST_DENIED">
-            <intent-filter>
-                <action android:name="android.app.cts.activity.SERVICE_LOCAL_DENIED" />
-            </intent-filter>
-        </service>
-
-        <activity android:name="android.app.cts.TestedScreen"
-                android:process=":remoteScreen">
-        </activity>
-        <activity android:name="android.app.cts.LocalScreen" android:multiprocess="true">
-        </activity>
-        <activity android:name="android.app.cts.ClearTop" android:multiprocess="true"
-               android:launchMode="singleTop">
-        </activity>
-        <activity android:name="android.app.cts.LocalDialog" android:multiprocess="true"
-               android:theme="@android:style/Theme.Dialog">
-        </activity>
-
-        <activity android:name="android.app.cts.PendingIntentStubActivity"
-             android:label="PendingIntentStubActivity"/>
-
-        <activity android:name="android.app.cts.LocalActivityManagerStubActivity"
-                        android:label="LocalActivityManagerStubActivity" />
-
-        <activity android:name="android.app.cts.LocalActivityManagerTestHelper"
-            android:label="LocalActivityManagerTestHelper" />
-
-        <activity android:name="android.app.cts.LaunchpadTabActivity" android:multiprocess="true">
-        </activity>
-
-        <activity android:name="android.app.cts.LocalActivity" android:multiprocess="true">
-            <meta-data android:name="android.app.cts.string" android:value="foo" />
-            <meta-data android:name="android.app.cts.boolean" android:value="true" />
-            <meta-data android:name="android.app.cts.integer" android:value="100" />
-            <meta-data android:name="android.app.cts.color" android:value="#ff000000" />
-            <meta-data android:name="android.app.cts.float" android:value="100.1" />
-            <meta-data android:name="android.app.cts.reference" android:resource="@xml/metadata" />
-        </activity>
-
-        <activity android:name="android.app.cts.TestedActivity"
-                android:process=":remoteActivity">
-        </activity>
-
-        <activity android:name="android.app.cts.ExpandableListTestActivity"
-            android:label="ExpandableListTestActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.view.cts.FocusFinderStubActivity"
-            android:label="FocusFinderStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.view.cts.GestureDetectorStubActivity"
-            android:label="GestureDetectorStubActivity"
-            android:theme="@android:style/Theme.NoTitleBar.Fullscreen" />
-
-        <!--Test for PackageManager-->
-        <activity android:name="android.content.pm.cts.TestPmActivity"
-                android:icon="@drawable/start">
-            <intent-filter>
-                <action android:name="android.intent.action.PMTEST" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-            <meta-data android:name="android.content.pm.cts.xmltest" android:resource="@xml/pm_test" />
-        </activity>
-        <activity android:name="android.content.pm.cts.TestPmCompare">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.INFO" />
-            </intent-filter>
-        </activity>
-        <!--Test for PackageManager-->
-        <service android:name="android.content.pm.cts.TestPmService">
-            <intent-filter>
-                <action android:name="android.content.pm.cts.activity.PMTEST_SERVICE" />
-            </intent-filter>
-        </service>
-        <!--Test for PackageManager-->
-        <receiver android:name="android.content.pm.cts.PmTestReceiver">
-            <intent-filter>
-                <action android:name="android.content.pm.cts.PackageManagerTest.PMTEST_RECEIVER" />
-            </intent-filter>
-        </receiver>
-
-        <!-- Used for PackageManager test, don't delete this MockContentProvider provider -->
-        <provider android:name="android.content.cts.MockContentProvider" android:authorities="ctstest"
-            android:multiprocess="false" />
-        <provider android:name="android.content.cts.DummyProvider"
-            android:authorities="android.content.cts.dummyprovider"
-            android:multiprocess="true" />
-        <provider android:name="android.content.cts.MockRemoteContentProvider"
-            android:authorities="remotectstest"
-            android:process=":remoteprovider" android:multiprocess="false" />
-
-        <activity android:name="android.app.cts.ChildTabActivity" android:label="ChildTabActivity" />
-
-        <activity android:name="android.app.cts.LauncherActivityStub"
-                  android:label="LauncherActivityStub" >
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.app.cts.MockTabActivity" android:label="MockTabActivity" />
-
-        <activity android:name="android.app.cts.AppStubActivity" android:label="AppStubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.app.cts.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" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.app.cts.ActivityManagerStubFooActivity"
-            android:label="ActivityManagerStubFooActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.app.cts.ActivityManagerRecentOneActivity"
-            android:label="ActivityManagerRecentOneActivity"
-            android:allowTaskReparenting="true"
-            android:taskAffinity="android.app.cts.recentOne">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.app.cts.ActivityManagerRecentTwoActivity"
-            android:label="ActivityManagerRecentTwoActivity"
-            android:allowTaskReparenting="true"
-            android:taskAffinity="android.app.cts.recentTwo">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.app.cts.ActivityManagerStubCrashActivity"
-            android:label="ActivityManagerStubCrashActivity"
-            android:multiprocess="true"
-            android:process=":ActivityManagerStubCrashActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.text.method.cts.StubActivity"
-            android:label="StubActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <service android:name="android.app.cts.StubRemoteService"
-            android:process=":remote">
-            <intent-filter>
-                <action
-                    android:name="android.app.cts.ISecondary" />
-                <action
-                    android:name="android.app.REMOTESERVICE" />
-            </intent-filter>
-        </service>
-
-        <activity android:name="android.app.ActivityGroup"
-            android:label="ActivityGroup" />
-
-        <activity android:name="android.app.cts.KeyguardManagerActivity"
-            android:label="KeyguardManagerActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.os.cts.CountDownTimerTestStub"
-            android:label="CountDownTimerTestStub">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <service android:name="android.os.cts.EmptyService"
-            android:process=":remote">
-            <intent-filter>
-                <action
-                    android:name="android.os.cts.IEmptyService" />
-                <action
-                    android:name="android.os.REMOTESERVICE" />
-            </intent-filter>
-        </service>
-
-        <service android:name="android.os.cts.MessengerService"
-                android:process=":messengerService">
-        </service>
-        <service android:name="android.app.cts.IntentServiceStub"/>
-
-        <activity android:name="android.app.cts.LaunchpadActivity"
-                  android:configChanges="keyboardHidden|orientation|screenSize"
-                  android:multiprocess="true">
-        </activity>
-
-        <service android:name="android.content.cts.MockSyncAdapterService" android:exported="true">
-            <intent-filter>
-                <action android:name="android.content.SyncAdapter" />
-            </intent-filter>
-
-            <meta-data android:name="android.content.SyncAdapter"
-                       android:resource="@xml/syncadapter" />
-        </service>
-
-        <service android:name="android.content.cts.MockAccountService" android:exported="true"
-                 >
-            <intent-filter>
-                <action android:name="android.accounts.AccountAuthenticator" />
-            </intent-filter>
-
-            <meta-data android:name="android.accounts.AccountAuthenticator"
-                       android:resource="@xml/authenticator" />
-        </service>
-
-        <activity android:name="android.opengl.cts.GLSurfaceViewStubActivity"
-                  android:label="GLSurfaceViewStub"/>
-
-        <activity android:name="android.opengl.cts.OpenGlEsVersionStubActivity"/>
-
-        <activity android:name="android.opengl.cts.EglConfigStubActivity"
-            android:configChanges="keyboardHidden|orientation|screenSize|uiMode" />
-
-        <activity android:name="android.opengl.cts.CompressedTextureStubActivity"
-            android:label="CompressedTextureStubActivity"
-            android:screenOrientation="nosensor">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-        </activity>
-
-        <activity android:name="android.preference.cts.PreferenceStubActivity">
-            <meta-data android:name="android.preference"
-                    android:resource="@xml/preferences_from_intent" />
-        </activity>
-
-        <activity android:name="android.content.cts.ClipboardManagerListenerActivity"/>
-
-        <activity android:name="android.app.cts.ActivityManagerMemoryClassLaunchActivity" />
-
-        <activity android:name="android.app.cts.ActivityManagerMemoryClassTestActivity"
-                android:process=":memoryclass" />
-
-        <service android:name="android.speech.tts.cts.StubTextToSpeechService">
-            <intent-filter>
-                <action android:name="android.intent.action.TTS_SERVICE" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-        </service>
-
-        <activity android:name="android.renderscriptgraphics.cts.RenderscriptGLStubActivity"
-                  android:label="RenderscriptGLStub"/>
-
-        <service android:name="android.security.cts.activity.SecureRandomService"
-                 android:process=":secureRandom"/>
-    </application>
-
-
-    <!--Test for PackageManager, please put this at the very beginning-->
-    <instrumentation android:name="android.content.pm.cts.TestPmInstrumentation"
-        android:targetPackage="android"
-        android:label="PackageManager Instrumentation Test" />
-
-</manifest>
-
diff --git a/tests/JobScheduler/Android.mk b/tests/JobScheduler/Android.mk
new file mode 100755
index 0000000..499abded
--- /dev/null
+++ b/tests/JobScheduler/Android.mk
@@ -0,0 +1,34 @@
+# 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)
+
+include $(CLEAR_VARS)
+
+# Don't include this package in any target.
+LOCAL_MODULE_TAGS := optional
+
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# Must match the package name in CtsTestCaseList.mk
+LOCAL_PACKAGE_NAME := CtsJobSchedulerDeviceTestCases
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/JobScheduler/AndroidManifest.xml b/tests/JobScheduler/AndroidManifest.xml
new file mode 100755
index 0000000..17cf399
--- /dev/null
+++ b/tests/JobScheduler/AndroidManifest.xml
@@ -0,0 +1,44 @@
+<?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.jobscheduler.cts.deviceside">
+
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+
+        <service android:name="android.jobscheduler.MockJobService"
+            android:permission="android.permission.BIND_JOB_SERVICE" />
+    </application>
+
+    <!--  self-instrumenting test package. -->
+    <instrumentation
+        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:label="JobScheduler device-side tests"
+        android:targetPackage="android.jobscheduler.cts.deviceside" >
+        <meta-data
+            android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
+</manifest>
+
diff --git a/tests/JobScheduler/src/android/jobscheduler/MockJobService.java b/tests/JobScheduler/src/android/jobscheduler/MockJobService.java
new file mode 100644
index 0000000..a0177e2
--- /dev/null
+++ b/tests/JobScheduler/src/android/jobscheduler/MockJobService.java
@@ -0,0 +1,118 @@
+/*
+ * 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.jobscheduler;
+
+import android.annotation.TargetApi;
+import android.app.job.JobParameters;
+import android.app.job.JobService;
+import android.util.Log;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Handles callback from the framework {@link android.app.job.JobScheduler}. The behaviour of this
+ * class is configured through the static
+ * {@link TestEnvironment}.
+ */
+@TargetApi(21)
+public class MockJobService extends JobService {
+    private static final String TAG = "MockJobService";
+
+    /** Wait this long before timing out the test. */
+    private static final long DEFAULT_TIMEOUT_MILLIS = 5000L; // 5 seconds.
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        Log.e(TAG, "Created test service.");
+    }
+
+    @Override
+    public boolean onStartJob(JobParameters params) {
+        Log.i(TAG, "Test job executing: " + params.getJobId());
+
+        TestEnvironment.getTestEnvironment().notifyExecution(params.getJobId());
+        return false;  // No work to do.
+    }
+
+    @Override
+    public boolean onStopJob(JobParameters params) {
+        return false;
+    }
+
+    /**
+     * Configures the expected behaviour for each test. This object is shared across consecutive
+     * tests, so to clear state each test is responsible for calling
+     * {@link TestEnvironment#setUp()}.
+     */
+    public static final class TestEnvironment {
+
+        private static TestEnvironment kTestEnvironment;
+        public static final int INVALID_JOB_ID = -1;
+
+        private CountDownLatch mLatch;
+        private int mExecutedJobId;
+
+        public static TestEnvironment getTestEnvironment() {
+            if (kTestEnvironment == null) {
+                kTestEnvironment = new TestEnvironment();
+            }
+            return kTestEnvironment;
+        }
+
+        /**
+         * Block the test thread, waiting on the JobScheduler to execute some previously scheduled
+         * job on this service.
+         */
+        public boolean awaitExecution() throws InterruptedException {
+            final boolean executed = mLatch.await(DEFAULT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+            return executed;
+        }
+
+        /**
+         * Block the test thread, expecting to timeout but still listening to ensure that no jobs
+         * land in the interim.
+         * @return True if the latch timed out waiting on an execution.
+         */
+        public boolean awaitTimeout() throws InterruptedException {
+            return !mLatch.await(DEFAULT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+        }
+
+        private void notifyExecution(int jobId) {
+            Log.d(TAG, "Job executed:" + jobId);
+            mExecutedJobId = jobId;
+            mLatch.countDown();
+        }
+
+        public void setExpectedExecutions(int numExecutions) {
+            // For no executions expected, set count to 1 so we can still block for the timeout.
+            if (numExecutions == 0) {
+                mLatch = new CountDownLatch(1);
+            } else {
+                mLatch = new CountDownLatch(numExecutions);
+            }
+        }
+
+        /** Called in each testCase#setup */
+        public void setUp() {
+            mLatch = null;
+            mExecutedJobId = INVALID_JOB_ID;
+        }
+
+    }
+}
\ No newline at end of file
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java
new file mode 100644
index 0000000..a83f7a9
--- /dev/null
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java
@@ -0,0 +1,287 @@
+/*
+ * 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.jobscheduler.cts;
+
+
+import android.annotation.TargetApi;
+import android.app.job.JobInfo;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiManager;
+import android.util.Log;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Schedules jobs with the {@link android.app.job.JobScheduler} that have network connectivity
+ * constraints.
+ * Requires manipulating the {@link android.net.wifi.WifiManager} to ensure an unmetered network.
+ * Similarly, requires that the phone be connected to a wifi hotspot, or else the test will fail.
+ */
+@TargetApi(21)
+public class ConnectivityConstraintTest extends ConstraintTest {
+    private static final String TAG = "ConnectivityConstraintTest";
+
+    /** Unique identifier for the job scheduled by this suite of tests. */
+    public static final int CONNECTIVITY_JOB_ID = ConnectivityConstraintTest.class.hashCode();
+
+    private WifiManager mWifiManager;
+    private ConnectivityManager mCm;
+
+    /** Whether the device running these tests supports WiFi. */
+    private boolean mHasWifi;
+    /** Whether the device running these tests supports telephony. */
+    private boolean mHasTelephony;
+
+    private JobInfo.Builder mBuilder;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
+        mCm =
+                (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
+
+        PackageManager packageManager = mContext.getPackageManager();
+        mHasWifi = packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI);
+        mHasTelephony = packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
+        mBuilder =
+                new JobInfo.Builder(CONNECTIVITY_JOB_ID, kJobServiceComponent);
+    }
+
+    // --------------------------------------------------------------------------------------------
+    // Positives - schedule jobs under conditions that require them to pass.
+    // --------------------------------------------------------------------------------------------
+
+    /**
+     * Schedule a job that requires a WiFi connection, and assert that it executes when the device
+     * is connected to WiFi. This will fail if a wifi connection is unavailable.
+     */
+    public void testUnmeteredConstraintExecutes_withWifi() throws Exception {
+        if (!mHasWifi) {
+            Log.d(TAG, "Skipping test that requires the device be WiFi enabled.");
+            return;
+        }
+        connectToWiFi();
+
+        kTestEnvironment.setExpectedExecutions(1);
+        mJobScheduler.schedule(
+                mBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
+                        .build());
+
+        sendExpediteStableChargingBroadcast();
+
+        assertTrue("Job with unmetered constraint did not fire on WiFi.",
+                kTestEnvironment.awaitExecution());
+    }
+
+    /**
+     * Schedule a job with a connectivity constraint, and ensure that it executes on WiFi.
+     */
+    public void testConnectivityConstraintExecutes_withWifi() throws Exception {
+        if (!mHasWifi) {
+            Log.d(TAG, "Skipping test that requires the device be WiFi enabled.");
+            return;
+        }
+        connectToWiFi();
+
+        kTestEnvironment.setExpectedExecutions(1);
+        mJobScheduler.schedule(
+                mBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
+                        .build());
+
+        sendExpediteStableChargingBroadcast();
+
+        assertTrue("Job with connectivity constraint did not fire on WiFi.",
+                kTestEnvironment.awaitExecution());
+    }
+
+    /**
+     * Schedule a job with a connectivity constraint, and ensure that it executes on on a mobile
+     * data connection.
+     */
+    public void testConnectivityConstraintExecutes_withMobile() throws Exception {
+        if (!checkDeviceSupportsMobileData()) {
+            return;
+        }
+        disconnectWifiToConnectToMobile();
+
+        kTestEnvironment.setExpectedExecutions(1);
+        mJobScheduler.schedule(
+                mBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
+                        .build());
+
+        sendExpediteStableChargingBroadcast();
+
+        assertTrue("Job with connectivity constraint did not fire on mobile.",
+                kTestEnvironment.awaitExecution());
+    }
+
+    // --------------------------------------------------------------------------------------------
+    // Negatives - schedule jobs under conditions that require that they fail.
+    // --------------------------------------------------------------------------------------------
+
+    /**
+     * Schedule a job that requires a WiFi connection, and assert that it fails when the device is
+     * connected to a cellular provider.
+     * This test assumes that if the device supports a mobile data connection, then this connection
+     * will be available.
+     */
+    public void testUnmeteredConstraintFails_withMobile() throws Exception {
+        if (!checkDeviceSupportsMobileData()) {
+            return;
+        }
+        disconnectWifiToConnectToMobile();
+
+        kTestEnvironment.setExpectedExecutions(0);
+        mJobScheduler.schedule(
+                mBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
+                        .build());
+        sendExpediteStableChargingBroadcast();
+
+        assertTrue("Job requiring unmetered connectivity still executed on mobile.",
+                kTestEnvironment.awaitTimeout());
+    }
+
+    /**
+     * Determine whether the device running these CTS tests should be subject to tests involving
+     * mobile data.
+     * @return True if this device will support a mobile data connection.
+     */
+    private boolean checkDeviceSupportsMobileData() {
+        if (!mHasTelephony) {
+            Log.d(TAG, "Skipping test that requires telephony features, not supported by this" +
+                    " device");
+            return false;
+        }
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Ensure WiFi is enabled, and block until we've verified that we are in fact connected.
+     * Taken from {@link android.net.http.cts.ApacheHttpClientTest}.
+     */
+    private void connectToWiFi() throws InterruptedException {
+        if (!mWifiManager.isWifiEnabled()) {
+            ConnectivityActionReceiver receiver =
+                    new ConnectivityActionReceiver(ConnectivityManager.TYPE_WIFI,
+                            NetworkInfo.State.CONNECTED);
+            IntentFilter filter = new IntentFilter();
+            filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+            mContext.registerReceiver(receiver, filter);
+
+            assertTrue(mWifiManager.setWifiEnabled(true));
+            assertTrue("Wifi must be configured to connect to an access point for this test.",
+                    receiver.waitForStateChange());
+
+            mContext.unregisterReceiver(receiver);
+        }
+    }
+
+    private void disconnectWifiToConnectToMobile() throws InterruptedException {
+        if (mHasWifi && mWifiManager.isWifiEnabled()) {
+            ConnectivityActionReceiver connectMobileReceiver =
+                    new ConnectivityActionReceiver(ConnectivityManager.TYPE_MOBILE,
+                            NetworkInfo.State.CONNECTED);
+            ConnectivityActionReceiver disconnectWifiReceiver =
+                    new ConnectivityActionReceiver(ConnectivityManager.TYPE_WIFI,
+                            NetworkInfo.State.DISCONNECTED);
+            IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
+            mContext.registerReceiver(connectMobileReceiver, filter);
+            mContext.registerReceiver(disconnectWifiReceiver, filter);
+
+            assertTrue(mWifiManager.setWifiEnabled(false));
+            assertTrue("Failure disconnecting from WiFi.",
+                    disconnectWifiReceiver.waitForStateChange());
+            assertTrue("Device must have access to a metered network for this test.",
+                    connectMobileReceiver.waitForStateChange());
+
+            mContext.unregisterReceiver(connectMobileReceiver);
+            mContext.unregisterReceiver(disconnectWifiReceiver);
+        }
+    }
+
+    /** Capture the last connectivity change's network type and state. */
+    private class ConnectivityActionReceiver extends BroadcastReceiver {
+
+        private final CountDownLatch mReceiveLatch = new CountDownLatch(1);
+
+        private final int mNetworkType;
+
+        private final NetworkInfo.State mExpectedState;
+
+        ConnectivityActionReceiver(int networkType, NetworkInfo.State expectedState) {
+            mNetworkType = networkType;
+            mExpectedState = expectedState;
+        }
+
+        public void onReceive(Context context, Intent intent) {
+            // Dealing with a connectivity changed event for this network type.
+            final int networkTypeChanged =
+                    intent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, -1);
+            if (networkTypeChanged == -1) {
+                Log.e(TAG, "No network type provided in intent");
+                return;
+            }
+
+            if (networkTypeChanged != mNetworkType) {
+                // Only track changes for the connectivity event that we are interested in.
+                return;
+            }
+            // Pull out the NetworkState object that we're interested in. Necessary because
+            // the ConnectivityManager will filter on uid for background connectivity.
+            NetworkInfo[] allNetworkInfo = mCm.getAllNetworkInfo();
+            NetworkInfo networkInfo = null;
+            for (int i=0; i<allNetworkInfo.length; i++) {
+                NetworkInfo ni = allNetworkInfo[i];
+                if (ni.getType() == mNetworkType) {
+                    networkInfo =  ni;
+                    break;
+                }
+            }
+            if (networkInfo == null) {
+                Log.e(TAG, "Could not find correct network type.");
+                return;
+            }
+
+            NetworkInfo.State networkState = networkInfo.getState();
+            Log.i(TAG, "Network type: " + mNetworkType + " State: " + networkState);
+            if (networkState == mExpectedState) {
+                mReceiveLatch.countDown();
+            }
+        }
+
+        public boolean waitForStateChange() throws InterruptedException {
+            return mReceiveLatch.await(30, TimeUnit.SECONDS) || hasExpectedState();
+        }
+
+        private boolean hasExpectedState() {
+            return mExpectedState == mCm.getNetworkInfo(mNetworkType).getState();
+        }
+    }
+
+}
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/ConstraintTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/ConstraintTest.java
new file mode 100644
index 0000000..b9a498f
--- /dev/null
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/ConstraintTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.jobscheduler.cts;
+
+import android.annotation.TargetApi;
+import android.app.job.JobScheduler;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.jobscheduler.MockJobService;
+import android.test.AndroidTestCase;
+
+/**
+ * Common functionality from which the other test case classes derive.
+ */
+@TargetApi(21)
+public abstract class ConstraintTest extends AndroidTestCase {
+    /** Force the scheduler to consider the device to be on stable charging. */
+    private static final Intent EXPEDITE_STABLE_CHARGING =
+            new Intent("com.android.server.task.controllers.BatteryController.ACTION_CHARGING_STABLE");
+
+    /** Environment that notifies of JobScheduler callbacks. */
+    static MockJobService.TestEnvironment kTestEnvironment =
+            MockJobService.TestEnvironment.getTestEnvironment();
+    /** Handle for the service which receives the execution callbacks from the JobScheduler. */
+    static ComponentName kJobServiceComponent;
+    JobScheduler mJobScheduler;
+
+    @Override
+    public void setUp() throws Exception {
+        kTestEnvironment.setUp();
+        kJobServiceComponent = new ComponentName(getContext(), MockJobService.class);
+        mJobScheduler = (JobScheduler) getContext().getSystemService(Context.JOB_SCHEDULER_SERVICE);
+        mJobScheduler.cancelAll();
+    }
+
+    /**
+     * The scheduler will usually only flush its queue of unexpired jobs when the device is
+     * considered to be on stable power - that is, plugged in for a period of 2 minutes.
+     * Rather than wait for this to happen, we cheat and send this broadcast instead.
+     */
+    protected void sendExpediteStableChargingBroadcast() {
+        getContext().sendBroadcast(EXPEDITE_STABLE_CHARGING);
+    }
+}
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/TimingConstraintsTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/TimingConstraintsTest.java
new file mode 100644
index 0000000..36f44ef
--- /dev/null
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/TimingConstraintsTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.jobscheduler.cts;
+
+import android.annotation.TargetApi;
+import android.app.job.JobInfo;
+
+/**
+ * Schedules jobs with various timing constraints and ensures that they are executed when
+ * appropriate.
+ */
+@TargetApi(21)
+public class TimingConstraintsTest extends ConstraintTest {
+    private static final int TIMING_JOB_ID = TimingConstraintsTest.class.hashCode() + 0;
+    private static final int CANCEL_JOB_ID = TimingConstraintsTest.class.hashCode() + 1;
+
+    public void testScheduleOnce() throws Exception {
+        JobInfo oneTimeJob = new JobInfo.Builder(TIMING_JOB_ID, kJobServiceComponent)
+                        .setOverrideDeadline(1000)  // 1 secs
+                        .build();
+
+        kTestEnvironment.setExpectedExecutions(1);
+        mJobScheduler.schedule(oneTimeJob);
+        final boolean executed = kTestEnvironment.awaitExecution();
+        assertTrue("Timed out waiting for override deadline.", executed);
+    }
+
+    public void testSchedulePeriodic() throws Exception {
+        JobInfo periodicJob =
+                new JobInfo.Builder(TIMING_JOB_ID, kJobServiceComponent)
+                        .setPeriodic(1000L)  // 1 second period.
+                        .build();
+
+        kTestEnvironment.setExpectedExecutions(3);
+        mJobScheduler.schedule(periodicJob);
+        final boolean countedDown = kTestEnvironment.awaitExecution();
+        assertTrue("Timed out waiting for periodic jobs to execute", countedDown);
+    }
+
+    public void testCancel() throws Exception {
+        JobInfo cancelJob = new JobInfo.Builder(CANCEL_JOB_ID, kJobServiceComponent)
+                .setOverrideDeadline(2000L)
+                .build();
+
+        kTestEnvironment.setExpectedExecutions(0);
+        mJobScheduler.schedule(cancelJob);
+        // Now cancel it.
+        mJobScheduler.cancel(CANCEL_JOB_ID);
+        assertTrue("Cancel failed: job executed when it shouldn't have.",
+                kTestEnvironment.awaitTimeout());
+    }
+}
\ No newline at end of file
diff --git a/tests/ProcessTest/Android.mk b/tests/ProcessTest/Android.mk
index a2958fe..5611b3b 100644
--- a/tests/ProcessTest/Android.mk
+++ b/tests/ProcessTest/Android.mk
@@ -20,8 +20,6 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_AAPT_FLAGS = -c xx_YY -c cs
 
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
@@ -31,6 +29,8 @@
 LOCAL_DEX_PREOPT := false
 LOCAL_PROGUARD_ENABLED := disabled
 
+LOCAL_SDK_VERSION := current
+
 include $(BUILD_PACKAGE)
 
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/ProcessTest/AndroidManifest.xml b/tests/ProcessTest/AndroidManifest.xml
index b860bde..c7cf635 100644
--- a/tests/ProcessTest/AndroidManifest.xml
+++ b/tests/ProcessTest/AndroidManifest.xml
@@ -18,7 +18,7 @@
        android:sharedUserId="com.android.cts.process.uidpid_test">
 
     <!-- InstrumentationTestRunner for AndroidTests -->
-    <instrumentation android:name="android.test.InstrumentationTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.cts.process"
                      android:label="Test process"/>
     <application>
diff --git a/tests/SignatureTest/Android.mk b/tests/SignatureTest/Android.mk
deleted file mode 100644
index 209e78a..0000000
--- a/tests/SignatureTest/Android.mk
+++ /dev/null
@@ -1,90 +0,0 @@
-# Copyright (C) 2008 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)
-include $(CLEAR_VARS)
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
-LOCAL_PACKAGE_NAME := SignatureTest
-
-LOCAL_SDK_VERSION := current
-
-# To be passed in on command line
-CTS_API_VERSION ?= current
-ifeq (current,$(CTS_API_VERSION))
-android_api_description := frameworks/base/api/$(CTS_API_VERSION).txt
-else
-android_api_description := $(SRC_API_DIR)/$(CTS_API_VERSION).txt
-endif
-
-# Can't call local-intermediates-dir directly here because we have to
-# include BUILD_CTS_PACKAGE first.  Can't include BUILD_CTS_PACKAGE first
-# because we have to override LOCAL_RESOURCE_DIR first.  Hence this
-# hack.
-intermediates.COMMON := $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),,COMMON)
-signature_res_dir := $(intermediates.COMMON)/genres
-LOCAL_RESOURCE_DIR := $(signature_res_dir) $(LOCAL_PATH)/res
-
-include $(BUILD_CTS_PACKAGE)
-
-$(info $(call local-intermediates-dir))
-
-generated_res_stamp := $(intermediates.COMMON)/genres.stamp
-api_ver_file := $(intermediates.COMMON)/api_ver_is_$(CTS_API_VERSION)
-
-# The api_ver_file keeps track of which api version was last built.
-# By only ever having one of these magic files in existence and making
-# sure the generated resources rule depend on it, we can ensure that
-# the proper version of the api resource gets generated.
-$(api_ver_file):
-	$(hide) rm -f $(dir $@)/api_ver_is_* \
-		&& mkdir -p $(dir $@) && touch $@
-
-android_api_xml_description := $(intermediates.COMMON)/api.xml
-$(android_api_xml_description): $(android_api_description) | $(APICHECK)
-	@ echo "Convert api file to xml: $@"
-	@ mkdir -p $(dir $@)
-	$(hide) $(APICHECK_COMMAND) -convert2xml $< $@
-
-# Split up config/api/1.xml by "package" and save the files as the
-# resource files of SignatureTest.
-$(generated_res_stamp): PRIVATE_PATH := $(LOCAL_PATH)
-$(generated_res_stamp): PRIVATE_MODULE := $(LOCAL_MODULE)
-$(generated_res_stamp): PRIVATE_RES_DIR := $(signature_res_dir)
-$(generated_res_stamp): PRIVATE_API_XML_DESC := $(android_api_xml_description)
-$(generated_res_stamp): $(api_ver_file)
-$(generated_res_stamp): $(android_api_xml_description)
-	@ echo "Copy generated resources: $(PRIVATE_MODULE)"
-	$(hide) python cts/tools/utils/android_api_description_splitter.py \
-		$(PRIVATE_API_XML_DESC) $(PRIVATE_RES_DIR) package
-	$(hide) touch $@
-
-$(R_file_stamp): $(generated_res_stamp)
-
-# clean up temp vars
-android_api_xml_description :=
-api_ver_file :=
-generated_res_stamp :=
-signature_res_dir :=
-android_api_description :=
-CTS_API_VERSION :=
-
-# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/SignatureTest/AndroidManifest.xml b/tests/SignatureTest/AndroidManifest.xml
deleted file mode 100644
index b4813e6..0000000
--- a/tests/SignatureTest/AndroidManifest.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2008 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.tests.sigtest">
-    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
-
-    <application>
-        <uses-library android:name="android.test.runner"/>
-    </application>
-
-    <instrumentation android:name="android.test.InstrumentationTestRunner"
-                     android:targetPackage="android.tests.sigtest"
-                     android:label="API Signature Test"/>
-
-</manifest>
\ No newline at end of file
diff --git a/tests/SignatureTest/src/android/tests/sigtest/JDiffClassDescription.java b/tests/SignatureTest/src/android/tests/sigtest/JDiffClassDescription.java
deleted file mode 100644
index c51c6c3..0000000
--- a/tests/SignatureTest/src/android/tests/sigtest/JDiffClassDescription.java
+++ /dev/null
@@ -1,1203 +0,0 @@
-/*
- * Copyright (C) 2008 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.tests.sigtest;
-
-import android.tests.sigtest.SignatureTest.FAILURE_TYPE;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.GenericArrayType;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.lang.reflect.TypeVariable;
-import java.lang.reflect.WildcardType;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Represents class descriptions loaded from a jdiff xml file.  Used
- * for CTS SignatureTests.
- */
-public class JDiffClassDescription {
-    /** Indicates that the class is an annotation. */
-    private static final int CLASS_MODIFIER_ANNOTATION = 0x00002000;
-    /** Indicates that the class is an enum. */
-    private static final int CLASS_MODIFIER_ENUM       = 0x00004000;
-
-    /** Indicates that the method is a bridge method. */
-    private static final int METHOD_MODIFIER_BRIDGE    = 0x00000040;
-    /** Indicates that the method is takes a variable number of arguments. */
-    private static final int METHOD_MODIFIER_VAR_ARGS  = 0x00000080;
-    /** Indicates that the method is a synthetic method. */
-    private static final int METHOD_MODIFIER_SYNTHETIC = 0x00001000;
-
-    public enum JDiffType {
-        INTERFACE, CLASS
-    }
-
-    @SuppressWarnings("unchecked")
-    private Class<?> mClass;
-
-    private String mPackageName;
-    private String mShortClassName;
-
-    /**
-     * Package name + short class name
-     */
-    private String mAbsoluteClassName;
-
-    private int mModifier;
-
-    private String mExtendedClass;
-    private List<String> implInterfaces = new ArrayList<String>();
-    private List<JDiffField> jDiffFields = new ArrayList<JDiffField>();
-    private List<JDiffMethod> jDiffMethods = new ArrayList<JDiffMethod>();
-    private List<JDiffConstructor> jDiffConstructors = new ArrayList<JDiffConstructor>();
-
-    private ResultObserver mResultObserver;
-    private JDiffType mClassType;
-
-    /**
-     * Creates a new JDiffClassDescription.
-     *
-     * @param pkg the java package this class will end up in.
-     * @param className the name of the class.
-     */
-    public JDiffClassDescription(String pkg, String className) {
-        this(pkg, className, new ResultObserver() {
-            public void notifyFailure(FAILURE_TYPE type,
-                    String name,
-                    String errorMessage) {
-                // This is a null result observer that doesn't do anything.
-            }
-        });
-    }
-
-    /**
-     * Creates a new JDiffClassDescription with the specified results
-     * observer.
-     *
-     * @param pkg the java package this class belongs in.
-     * @param className the name of the class.
-     * @param resultObserver the resultObserver to get results with.
-     */
-    public JDiffClassDescription(String pkg,
-            String className,
-            ResultObserver resultObserver) {
-        mPackageName = pkg;
-        mShortClassName = className;
-        mResultObserver = resultObserver;
-    }
-
-    /**
-     * adds implemented interface name.
-     *
-     * @param iname name of interface
-     */
-    public void addImplInterface(String iname) {
-        implInterfaces.add(iname);
-    }
-
-    /**
-     * Adds a field.
-     *
-     * @param field the field to be added.
-     */
-    public void addField(JDiffField field) {
-        jDiffFields.add(field);
-    }
-
-    /**
-     * Adds a method.
-     *
-     * @param method the method to be added.
-     */
-    public void addMethod(JDiffMethod method) {
-        jDiffMethods.add(method);
-    }
-
-    /**
-     * Adds a constructor.
-     *
-     * @param tc the constructor to be added.
-     */
-    public void addConstructor(JDiffConstructor tc) {
-        jDiffConstructors.add(tc);
-    }
-
-    static String convertModifiersToAccessLevel(int modifiers) {
-        String accessLevel = "";
-        if ((modifiers & Modifier.PUBLIC) != 0) {
-            return "public";
-        } else if ((modifiers & Modifier.PRIVATE) != 0) {
-            return "private";
-        } else if ((modifiers & Modifier.PROTECTED) != 0) {
-            return "protected";
-        } else {
-            // package protected
-            return "";
-        }
-    }
-
-    static String convertModifersToModifierString(int modifiers) {
-        StringBuffer sb = new StringBuffer();
-        boolean isFirst = true;
-
-        // order taken from Java Language Spec, sections 8.1.1, 8.3.1, and 8.4.3
-        if ((modifiers & Modifier.ABSTRACT) != 0) {
-            if (isFirst) {
-                isFirst = false;
-            } else {
-                sb.append(" ");
-            }
-            sb.append("abstract");
-        }
-        if ((modifiers & Modifier.STATIC) != 0) {
-            if (isFirst) {
-                isFirst = false;
-            } else {
-                sb.append(" ");
-            }
-            sb.append("static");
-        }
-        if ((modifiers & Modifier.FINAL) != 0) {
-            if (isFirst) {
-                isFirst = false;
-            } else {
-                sb.append(" ");
-            }
-            sb.append("final");
-        }
-        if ((modifiers & Modifier.TRANSIENT) != 0) {
-            if (isFirst) {
-                isFirst = false;
-            } else {
-                sb.append(" ");
-            }
-            sb.append("transient");
-        }
-        if ((modifiers & Modifier.VOLATILE) != 0) {
-            if (isFirst) {
-                isFirst = false;
-            } else {
-                sb.append(" ");
-            }
-            sb.append("volatile");
-        }
-        if ((modifiers & Modifier.SYNCHRONIZED) != 0) {
-            if (isFirst) {
-                isFirst = false;
-            } else {
-                sb.append(" ");
-            }
-            sb.append("synchronized");
-        }
-        if ((modifiers & Modifier.NATIVE) != 0) {
-            if (isFirst) {
-                isFirst = false;
-            } else {
-                sb.append(" ");
-            }
-            sb.append("native");
-        }
-        if ((modifiers & Modifier.STRICT) != 0) {
-            if (isFirst) {
-                isFirst = false;
-            } else {
-                sb.append(" ");
-            }
-            sb.append("strictfp");
-        }
-
-        return sb.toString();
-    }
-
-    public abstract static class JDiffElement {
-        final String mName;
-        int mModifier;
-
-        public JDiffElement(String name, int modifier) {
-            mName = name;
-            mModifier = modifier;
-        }
-    }
-
-    /**
-     * Represents a  field.
-     */
-    public static final class JDiffField extends JDiffElement {
-        private String mFieldType;
-
-        public JDiffField(String name, String fieldType, int modifier) {
-            super(name, modifier);
-
-            mFieldType = fieldType;
-        }
-
-        /**
-         * Make a readable string according to the class name specified.
-         *
-         * @param className The specified class name.
-         * @return A readable string to represent this field along with the class name.
-         */
-        public String toReadableString(String className) {
-            return className + "#" + mName + "(" + mFieldType + ")";
-        }
-
-        public String toSignatureString() {
-            StringBuffer sb = new StringBuffer();
-
-            // access level
-            String accesLevel = convertModifiersToAccessLevel(mModifier);
-            if (!"".equals(accesLevel)) {
-                sb.append(accesLevel).append(" ");
-            }
-
-            String modifierString = convertModifersToModifierString(mModifier);
-            if (!"".equals(modifierString)) {
-                sb.append(modifierString).append(" ");
-            }
-
-            sb.append(mFieldType).append(" ");
-
-            sb.append(mName);
-
-            return sb.toString();
-        }
-    }
-
-    /**
-     * Represents a method.
-     */
-    public static class JDiffMethod extends JDiffElement {
-        protected String mReturnType;
-        protected ArrayList<String> mParamList;
-        protected ArrayList<String> mExceptionList;
-
-        public JDiffMethod(String name, int modifier, String returnType) {
-            super(name, modifier);
-
-            if (returnType == null) {
-                mReturnType = "void";
-            } else {
-                mReturnType = scrubJdiffParamType(returnType);
-            }
-
-            mParamList = new ArrayList<String>();
-            mExceptionList = new ArrayList<String>();
-        }
-
-        /**
-         * Adds a parameter.
-         *
-         * @param param parameter type
-         */
-        public void addParam(String param) {
-            mParamList.add(scrubJdiffParamType(param));
-        }
-
-        /**
-         * Adds an exception.
-         *
-         * @param exceptionName name of exception
-         */
-        public void addException(String exceptionName) {
-            mExceptionList.add(exceptionName);
-        }
-
-        /**
-         * Makes a readable string according to the class name specified.
-         *
-         * @param className The specified class name.
-         * @return A readable string to represent this method along with the class name.
-         */
-        public String toReadableString(String className) {
-            return className + "#" + mName + "(" + convertParamList(mParamList) + ")";
-        }
-
-        /**
-         * Converts a parameter array to a string
-         *
-         * @param params the array to convert
-         * @return converted parameter string
-         */
-        private static String convertParamList(final ArrayList<String> params) {
-
-            StringBuffer paramList = new StringBuffer();
-
-            if (params != null) {
-                for (String str : params) {
-                    paramList.append(str + ", ");
-                }
-                if (params.size() > 0) {
-                    paramList.delete(paramList.length() - 2, paramList.length());
-                }
-            }
-
-            return paramList.toString();
-        }
-
-        public String toSignatureString() {
-            StringBuffer sb = new StringBuffer();
-
-            // access level
-            String accesLevel = convertModifiersToAccessLevel(mModifier);
-            if (!"".equals(accesLevel)) {
-                sb.append(accesLevel).append(" ");
-            }
-
-            String modifierString = convertModifersToModifierString(mModifier);
-            if (!"".equals(modifierString)) {
-                sb.append(modifierString).append(" ");
-            }
-
-            String returnType = getReturnType();
-            if (!"".equals(returnType)) {
-                sb.append(returnType).append(" ");
-            }
-
-            sb.append(mName);
-            sb.append("(");
-            for (int x = 0; x < mParamList.size(); x++) {
-                sb.append(mParamList.get(x));
-                if (x + 1 != mParamList.size()) {
-                    sb.append(", ");
-                }
-            }
-            sb.append(")");
-
-            // does it throw?
-            if (mExceptionList.size() > 0) {
-                sb.append(" throws ");
-                for (int x = 0; x < mExceptionList.size(); x++) {
-                    sb.append(mExceptionList.get(x));
-                    if (x + 1 != mExceptionList.size()) {
-                        sb.append(", ");
-                    }
-                }
-            }
-
-            return sb.toString();
-        }
-
-        /**
-         * Gets the return type.
-         *
-         * @return the return type of this method.
-         */
-        protected String getReturnType() {
-            return mReturnType;
-        }
-    }
-
-    /**
-     * Represents a constructor.
-     */
-    public static final class JDiffConstructor extends JDiffMethod {
-        public JDiffConstructor(String name, int modifier) {
-            super(name, modifier, null);
-        }
-
-        public JDiffConstructor(String name, String[] param, int modifier) {
-            super(name, modifier, null);
-
-            for (int i = 0; i < param.length; i++) {
-                addParam(param[i]);
-            }
-        }
-
-        /**
-         * Gets the return type.
-         *
-         * @return the return type of this method.
-         */
-        @Override
-        protected String getReturnType() {
-            // Constructors have no return type.
-            return "";
-        }
-    }
-
-    /**
-     * Checks test class's name, modifier, fields, constructors, and
-     * methods.
-     */
-    public void checkSignatureCompliance() {
-        checkClassCompliance();
-        if (mClass != null) {
-            checkFieldsCompliance();
-            checkConstructorCompliance();
-            checkMethodCompliance();
-        }
-    }
-
-    /**
-     * Checks to ensure that the modifiers value for two methods are
-     * compatible.
-     *
-     * Allowable differences are:
-     *   - synchronized is allowed to be removed from an apiMethod
-     *     that has it
-     *   - the native modified is ignored
-     *
-     * @param apiMethod the method read from the api file.
-     * @param reflectedMethod the method found via reflections.
-     */
-    private boolean areMethodModifiedCompatibile(JDiffMethod apiMethod ,
-            Method reflectedMethod) {
-
-        // If the apiMethod isn't synchronized
-        if (((apiMethod.mModifier & Modifier.SYNCHRONIZED) == 0) &&
-                // but the reflected method is
-                ((reflectedMethod.getModifiers() & Modifier.SYNCHRONIZED) != 0)) {
-            // that is a problem
-            return false;
-        }
-
-        // Mask off NATIVE since it is a don't care.  Also mask off
-        // SYNCHRONIZED since we've already handled that check.
-        int mod1 = reflectedMethod.getModifiers() & ~(Modifier.NATIVE | Modifier.SYNCHRONIZED);
-        int mod2 = apiMethod.mModifier & ~(Modifier.NATIVE | Modifier.SYNCHRONIZED);
-
-        // We can ignore FINAL for final classes
-        if ((mModifier & Modifier.FINAL) != 0) {
-            mod1 &= ~Modifier.FINAL;
-            mod2 &= ~Modifier.FINAL;
-        }
-
-        return mod1 == mod2;
-    }
-
-    /**
-     * Checks that the method found through reflection matches the
-     * specification from the API xml file.
-     */
-    private void checkMethodCompliance() {
-        for (JDiffMethod method : jDiffMethods) {
-            try {
-                // this is because jdiff think a method in an interface is not abstract
-                if (JDiffType.INTERFACE.equals(mClassType)) {
-                    method.mModifier |= Modifier.ABSTRACT;
-                }
-
-                Method m = findMatchingMethod(method);
-                if (m == null) {
-                    mResultObserver.notifyFailure(FAILURE_TYPE.MISSING_METHOD,
-                            method.toReadableString(mAbsoluteClassName),
-                            "No method with correct signature found:" +
-                            method.toSignatureString());
-                } else {
-                    if (m.isVarArgs()) {
-                        method.mModifier |= METHOD_MODIFIER_VAR_ARGS;
-                    }
-                    if (m.isBridge()) {
-                        method.mModifier |= METHOD_MODIFIER_BRIDGE;
-                    }
-                    if (m.isSynthetic()) {
-                        method.mModifier |= METHOD_MODIFIER_SYNTHETIC;
-                    }
-
-                    // FIXME: A workaround to fix the final mismatch on enumeration
-                    if (mClass.isEnum() && method.mName.equals("values")) {
-                        return;
-                    }
-
-                    if (!areMethodModifiedCompatibile(method, m)) {
-                        mResultObserver.notifyFailure(FAILURE_TYPE.MISMATCH_METHOD,
-                                method.toReadableString(mAbsoluteClassName),
-                                "Non-compatible method found when looking for " +
-                                method.toSignatureString());
-                    }
-                }
-            } catch (Exception e) {
-                SignatureTestLog.e("Got exception when checking method compliance", e);
-                mResultObserver.notifyFailure(FAILURE_TYPE.CAUGHT_EXCEPTION,
-                        method.toReadableString(mAbsoluteClassName),
-                "Exception!");
-            }
-        }
-    }
-
-    /**
-     * Checks if the two types of methods are the same.
-     *
-     * @param jDiffMethod the jDiffMethod to compare
-     * @param method the reflected method to compare
-     * @return true, if both methods are the same
-     */
-    private boolean matches(JDiffMethod jDiffMethod, Method method) {
-        // If the method names aren't equal, the methods can't match.
-        if (jDiffMethod.mName.equals(method.getName())) {
-            String jdiffReturnType = jDiffMethod.mReturnType;
-            String reflectionReturnType = typeToString(method.getGenericReturnType());
-            List<String> jdiffParamList = jDiffMethod.mParamList;
-
-            // Next, compare the return types of the two methods.  If
-            // they aren't equal, the methods can't match.
-            if (jdiffReturnType.equals(reflectionReturnType)) {
-                Type[] params = method.getGenericParameterTypes();
-                // Next, check the method parameters.  If they have
-                // different number of parameters, the two methods
-                // can't match.
-                if (jdiffParamList.size() == params.length) {
-                    // If any of the parameters don't match, the
-                    // methods can't match.
-                    for (int i = 0; i < jdiffParamList.size(); i++) {
-                        if (!compareParam(jdiffParamList.get(i), params[i])) {
-                            return false;
-                        }
-                    }
-                    // We've passed all the tests, the methods do
-                    // match.
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Finds the reflected method specified by the method description.
-     *
-     * @param method description of the method to find
-     * @return the reflected method, or null if not found.
-     */
-    @SuppressWarnings("unchecked")
-    private Method findMatchingMethod(JDiffMethod method) {
-        Method[] methods = mClass.getDeclaredMethods();
-        boolean found = false;
-
-        for (Method m : methods) {
-            if (matches(method, m)) {
-                return m;
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Compares the parameter from the API and the parameter from
-     * reflection.
-     *
-     * @param jdiffParam param parsed from the API xml file.
-     * @param reflectionParamType param gotten from the Java reflection.
-     * @return True if the two params match, otherwise return false.
-     */
-    private static boolean compareParam(String jdiffParam, Type reflectionParamType) {
-        if (jdiffParam == null) {
-            return false;
-        }
-
-        String reflectionParam = typeToString(reflectionParamType);
-        // Most things aren't varargs, so just do a simple compare
-        // first.
-        if (jdiffParam.equals(reflectionParam)) {
-            return true;
-        }
-
-        // Check for varargs.  jdiff reports varargs as ..., while
-        // reflection reports them as []
-        int jdiffParamEndOffset = jdiffParam.indexOf("...");
-        int reflectionParamEndOffset = reflectionParam.indexOf("[]");
-        if (jdiffParamEndOffset != -1 && reflectionParamEndOffset != -1) {
-            jdiffParam = jdiffParam.substring(0, jdiffParamEndOffset);
-            reflectionParam = reflectionParam.substring(0, reflectionParamEndOffset);
-            return jdiffParam.equals(reflectionParam);
-        }
-
-        return false;
-    }
-
-    /**
-     * Checks whether the constructor parsed from API xml file and
-     * Java reflection are compliant.
-     */
-    @SuppressWarnings("unchecked")
-    private void checkConstructorCompliance() {
-        for (JDiffConstructor con : jDiffConstructors) {
-            try {
-                Constructor<?> c = findMatchingConstructor(con);
-                if (c == null) {
-                    mResultObserver.notifyFailure(FAILURE_TYPE.MISSING_METHOD,
-                            con.toReadableString(mAbsoluteClassName),
-                            "No method with correct signature found:" +
-                            con.toSignatureString());
-                } else {
-                    if (c.isVarArgs()) {// some method's parameter are variable args
-                        con.mModifier |= METHOD_MODIFIER_VAR_ARGS;
-                    }
-                    if (c.getModifiers() != con.mModifier) {
-                        mResultObserver.notifyFailure(
-                                FAILURE_TYPE.MISMATCH_METHOD,
-                                con.toReadableString(mAbsoluteClassName),
-                                "Non-compatible method found when looking for " +
-                                con.toSignatureString());
-                    }
-                }
-            } catch (Exception e) {
-                SignatureTestLog.e("Got exception when checking constructor compliance", e);
-                mResultObserver.notifyFailure(FAILURE_TYPE.CAUGHT_EXCEPTION,
-                        con.toReadableString(mAbsoluteClassName),
-                "Exception!");
-            }
-        }
-    }
-
-    /**
-     * Searches available constructor.
-     *
-     * @param jdiffDes constructor description to find.
-     * @return reflected constructor, or null if not found.
-     */
-    @SuppressWarnings("unchecked")
-    private Constructor<?> findMatchingConstructor(JDiffConstructor jdiffDes) {
-        for (Constructor<?> c : mClass.getDeclaredConstructors()) {
-            Type[] params = c.getGenericParameterTypes();
-            boolean isStaticClass = ((mClass.getModifiers() & Modifier.STATIC) != 0);
-
-            int startParamOffset = 0;
-            int numberOfParams = params.length;
-
-            // non-static inner class -> skip implicit parent pointer
-            // as first arg
-            if (mClass.isMemberClass() && !isStaticClass && params.length >= 1) {
-                startParamOffset = 1;
-                --numberOfParams;
-            }
-
-            ArrayList<String> jdiffParamList = jdiffDes.mParamList;
-            if (jdiffParamList.size() == numberOfParams) {
-                boolean isFound = true;
-                // i counts jdiff params, j counts reflected params
-                int i = 0;
-                int j = startParamOffset;
-                while (i < jdiffParamList.size()) {
-                    if (!compareParam(jdiffParamList.get(i), params[j])) {
-                        isFound = false;
-                        break;
-                    }
-                    ++i;
-                    ++j;
-                }
-                if (isFound) {
-                    return c;
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Checks all fields in test class for compliance with the API
-     * xml.
-     */
-    @SuppressWarnings("unchecked")
-    private void checkFieldsCompliance() {
-        for (JDiffField field : jDiffFields) {
-            try {
-                Field f = findMatchingField(field);
-                if (f == null) {
-                    mResultObserver.notifyFailure(FAILURE_TYPE.MISSING_FIELD,
-                            field.toReadableString(mAbsoluteClassName),
-                            "No field with correct signature found:" +
-                            field.toSignatureString());
-                } else if (f.getModifiers() != field.mModifier) {
-                    mResultObserver.notifyFailure(FAILURE_TYPE.MISMATCH_FIELD,
-                            field.toReadableString(mAbsoluteClassName),
-                            "Non-compatible field modifiers found when looking for " +
-                            field.toSignatureString());
-                } else if (!f.getType().getCanonicalName().equals(field.mFieldType)) {
-                    // type name does not match, but this might be a generic
-                    String genericTypeName = null;
-                    Type type = f.getGenericType();
-                    if (type != null) {
-                        genericTypeName = type instanceof Class ? ((Class) type).getName() :
-                            type.toString();
-                    }
-                    if (genericTypeName == null || !genericTypeName.equals(field.mFieldType)) {
-                        mResultObserver.notifyFailure(
-                                FAILURE_TYPE.MISMATCH_FIELD,
-                                field.toReadableString(mAbsoluteClassName),
-                                "Non-compatible field type found when looking for " +
-                                field.toSignatureString());
-                    }
-                }
-
-            } catch (Exception e) {
-                SignatureTestLog.e("Got exception when checking field compliance", e);
-                mResultObserver.notifyFailure(FAILURE_TYPE.CAUGHT_EXCEPTION,
-                        field.toReadableString(mAbsoluteClassName),
-                "Exception!");
-            }
-        }
-    }
-
-    /**
-     * Finds the reflected field specified by the field description.
-     *
-     * @param field the field description to find
-     * @return the reflected field, or null if not found.
-     */
-    private Field findMatchingField(JDiffField field){
-        Field[] fields = mClass.getDeclaredFields();
-        for (Field f : fields) {
-            if (f.getName().equals(field.mName)) {
-                return f;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Checks if the class under test has compliant modifiers compared to the API.
-     *
-     * @return true if modifiers are compliant.
-     */
-    private boolean checkClassModifiersCompliance() {
-        int reflectionModifier = mClass.getModifiers();
-        int apiModifier = mModifier;
-
-        // If the api class isn't abstract
-        if (((apiModifier & Modifier.ABSTRACT) == 0) &&
-                // but the reflected class is
-                ((reflectionModifier & Modifier.ABSTRACT) != 0) &&
-                // and it isn't an enum
-                !isEnumType()) {
-            // that is a problem
-            return false;
-        }
-        // ABSTRACT check passed, so mask off ABSTRACT
-        reflectionModifier &= ~Modifier.ABSTRACT;
-        apiModifier &= ~Modifier.ABSTRACT;
-
-        if (isAnnotation()) {
-            reflectionModifier &= ~CLASS_MODIFIER_ANNOTATION;
-        }
-        if (mClass.isInterface()) {
-            reflectionModifier &= ~(Modifier.INTERFACE);
-        }
-        if (isEnumType() && mClass.isEnum()) {
-            reflectionModifier &= ~CLASS_MODIFIER_ENUM;
-        }
-
-        return ((reflectionModifier == apiModifier) &&
-                (isEnumType() == mClass.isEnum()));
-    }
-
-    /**
-     * Checks if the class under test is compliant with regards to
-     * annnotations when compared to the API.
-     *
-     * @return true if the class is compliant
-     */
-    private boolean checkClassAnnotationCompliace() {
-        if (mClass.isAnnotation()) {
-            // check annotation
-            for (String inter : implInterfaces) {
-                if ("java.lang.annotation.Annotation".equals(inter)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Checks if the class under test extends the proper classes
-     * according to the API.
-     *
-     * @return true if the class is compliant.
-     */
-    private boolean checkClassExtendsCompliance() {
-        // Nothing to check if it doesn't extend anything.
-        if (mExtendedClass != null) {
-            Class<?> superClass = mClass.getSuperclass();
-            if (superClass == null) {
-                // API indicates superclass, reflection doesn't.
-                return false;
-            }
-
-            if (superClass.getCanonicalName().equals(mExtendedClass)) {
-                return true;
-            }
-
-            if (mAbsoluteClassName.equals("android.hardware.SensorManager")) {
-                // FIXME: Please see Issue 1496822 for more information
-                return true;
-            }
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Checks if the class under test implements the proper interfaces
-     * according to the API.
-     *
-     * @return true if the class is compliant
-     */
-    private boolean checkClassImplementsCompliance() {
-        Class<?>[] interfaces = mClass.getInterfaces();
-        Set<String> interFaceSet = new HashSet<String>();
-
-        for (Class<?> c : interfaces) {
-            interFaceSet.add(c.getCanonicalName());
-        }
-
-        for (String inter : implInterfaces) {
-            if (!interFaceSet.contains(inter)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Checks that the class found through reflection matches the
-     * specification from the API xml file.
-     */
-    @SuppressWarnings("unchecked")
-    private void checkClassCompliance() {
-        try {
-            mAbsoluteClassName = mPackageName + "." + mShortClassName;
-            mClass = findMatchingClass();
-
-            if (mClass == null) {
-                // No class found, notify the observer according to the class type
-                if (JDiffType.INTERFACE.equals(mClassType)) {
-                    mResultObserver.notifyFailure(FAILURE_TYPE.MISSING_INTERFACE,
-                            mAbsoluteClassName,
-                            "Classloader is unable to find " + mAbsoluteClassName);
-                } else {
-                    mResultObserver.notifyFailure(FAILURE_TYPE.MISSING_CLASS,
-                            mAbsoluteClassName,
-                            "Classloader is unable to find " + mAbsoluteClassName);
-                }
-
-                return;
-            }
-            if (!checkClassModifiersCompliance()) {
-                logMismatchInterfaceSignature(mAbsoluteClassName,
-                        "Non-compatible class found when looking for " +
-                        toSignatureString());
-                return;
-            }
-
-            if (!checkClassAnnotationCompliace()) {
-                logMismatchInterfaceSignature(mAbsoluteClassName,
-                "Annotation mismatch");
-                return;
-            }
-
-            if (!mClass.isAnnotation()) {
-                // check father class
-                if (!checkClassExtendsCompliance()) {
-                    logMismatchInterfaceSignature(mAbsoluteClassName,
-                    "Extends mismatch");
-                    return;
-                }
-
-                // check implements interface
-                if (!checkClassImplementsCompliance()) {
-                    logMismatchInterfaceSignature(mAbsoluteClassName,
-                    "Implements mismatch");
-                    return;
-                }
-            }
-        } catch (Exception e) {
-            SignatureTestLog.e("Got exception when checking field compliance", e);
-            mResultObserver.notifyFailure(FAILURE_TYPE.CAUGHT_EXCEPTION,
-                    mAbsoluteClassName,
-            "Exception!");
-        }
-    }
-
-
-    /**
-     * Convert the class into a printable signature string.
-     *
-     * @return the signature string
-     */
-    public String toSignatureString() {
-        StringBuffer sb = new StringBuffer();
-
-        String accessLevel = convertModifiersToAccessLevel(mModifier);
-        if (!"".equals(accessLevel)) {
-            sb.append(accessLevel).append(" ");
-        }
-        if (!JDiffType.INTERFACE.equals(mClassType)) {
-            String modifierString = convertModifersToModifierString(mModifier);
-            if (!"".equals(modifierString)) {
-                sb.append(modifierString).append(" ");
-            }
-            sb.append("class ");
-        } else {
-            sb.append("interface ");
-        }
-        // class name
-        sb.append(mShortClassName);
-
-        // does it extends something?
-        if (mExtendedClass != null) {
-            sb.append(" extends ").append(mExtendedClass).append(" ");
-        }
-
-        // implements something?
-        if (implInterfaces.size() > 0) {
-            sb.append(" implements ");
-            for (int x = 0; x < implInterfaces.size(); x++) {
-                String interf = implInterfaces.get(x);
-                sb.append(interf);
-                // if not last elements
-                if (x + 1 != implInterfaces.size()) {
-                    sb.append(", ");
-                }
-            }
-        }
-        return sb.toString();
-    }
-
-    private void logMismatchInterfaceSignature(String classFullName, String errorMessage) {
-        if (JDiffType.INTERFACE.equals(mClassType)) {
-            mResultObserver.notifyFailure(FAILURE_TYPE.MISMATCH_INTERFACE,
-                    classFullName,
-                    errorMessage);
-        } else {
-            mResultObserver.notifyFailure(FAILURE_TYPE.MISMATCH_CLASS,
-                    classFullName,
-                    errorMessage);
-        }
-    }
-
-    /**
-     * Sees if the class under test is actually an enum.
-     *
-     * @return true if this class is enum
-     */
-    private boolean isEnumType() {
-        return "java.lang.Enum".equals(mExtendedClass);
-    }
-
-    /**
-     * Finds the reflected class for the class under test.
-     *
-     * @return the reflected class, or null if not found.
-     */
-    @SuppressWarnings("unchecked")
-    private Class<?> findMatchingClass() {
-        // even if there are no . in the string, split will return an
-        // array of length 1
-        String[] classNameParts = mShortClassName.split("\\.");
-        String currentName = mPackageName + "." + classNameParts[0];
-
-        try {
-            // Check to see if the class we're looking for is the top
-            // level class.
-            Class<?> clz = Class.forName(currentName,
-                    false,
-                    this.getClass().getClassLoader());
-            if (clz.getCanonicalName().equals(mAbsoluteClassName)) {
-                return clz;
-            }
-
-            // Then it must be an inner class.
-            for (int x = 1; x < classNameParts.length; x++) {
-                clz = findInnerClassByName(clz, classNameParts[x]);
-                if (clz == null) {
-                    return null;
-                }
-                if (clz.getCanonicalName().equals(mAbsoluteClassName)) {
-                    return clz;
-                }
-            }
-        } catch (ClassNotFoundException e) {
-            SignatureTestLog.e("ClassNotFoundException for " + mPackageName + "." + mShortClassName, e);
-            return null;
-        }
-        return null;
-    }
-
-    /**
-     * Searches the class for the specified inner class.
-     *
-     * @param clz the class to search in.
-     * @param simpleName the simpleName of the class to find
-     * @returns the class being searched for, or null if it can't be found.
-     */
-    private Class<?> findInnerClassByName(Class<?> clz, String simpleName) {
-        for (Class<?> c : clz.getDeclaredClasses()) {
-            if (c.getSimpleName().equals(simpleName)) {
-                return c;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Sees if the class under test is actually an annotation.
-     *
-     * @return true if this class is Annotation.
-     */
-    private boolean isAnnotation() {
-        if (implInterfaces.contains("java.lang.annotation.Annotation")) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Gets the class name for the class under test.
-     *
-     * @return the class name.
-     */
-    public String getClassName() {
-        return mShortClassName;
-    }
-
-    /**
-     * Sets the modifier for the class under test.
-     *
-     * @param modifier the modifier
-     */
-    public void setModifier(int modifier) {
-        mModifier = modifier;
-    }
-
-    /**
-     * Sets the return type for the class under test.
-     *
-     * @param type the return type
-     */
-    public void setType(JDiffType type) {
-        mClassType = type;
-    }
-
-    /**
-     * Sets the class that is beign extended for the class under test.
-     *
-     * @param extendsClass the class being extended.
-     */
-    public void setExtendsClass(String extendsClass) {
-        mExtendedClass = extendsClass;
-    }
-
-    /**
-     * Registers a ResultObserver to process the output from the
-     * compliance testing done in this class.
-     *
-     * @param resultObserver the observer to register.
-     */
-    public void registerResultObserver(ResultObserver resultObserver) {
-        mResultObserver = resultObserver;
-    }
-
-    /**
-     * Converts WildcardType array into a jdiff compatible string..
-     * This is a helper function for typeToString.
-     *
-     * @param types array of types to format.
-     * @return the jdiff formatted string.
-     */
-    private static String concatWildcardTypes(Type[] types) {
-        StringBuffer sb = new StringBuffer();
-        int elementNum = 0;
-        for (Type t : types) {
-            sb.append(typeToString(t));
-            if (++elementNum < types.length) {
-                sb.append(" & ");
-            }
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Converts a Type into a jdiff compatible String.  The returned
-     * types from this function should match the same Strings that
-     * jdiff is providing to us.
-     *
-     * @param type the type to convert.
-     * @return the jdiff formatted string.
-     */
-    private static String typeToString(Type type) {
-        if (type instanceof ParameterizedType) {
-            ParameterizedType pt = (ParameterizedType) type;
-
-            StringBuffer sb = new StringBuffer();
-            sb.append(typeToString(pt.getRawType()));
-            sb.append("<");
-
-            int elementNum = 0;
-            Type[] types = pt.getActualTypeArguments();
-            for (Type t : types) {
-                sb.append(typeToString(t));
-                if (++elementNum < types.length) {
-                    sb.append(", ");
-                }
-            }
-
-            sb.append(">");
-            return sb.toString();
-        } else if (type instanceof TypeVariable) {
-            return ((TypeVariable<?>) type).getName();
-        } else if (type instanceof Class) {
-            return ((Class<?>) type).getCanonicalName();
-        } else if (type instanceof GenericArrayType) {
-            String typeName = typeToString(((GenericArrayType) type).getGenericComponentType());
-            return typeName + "[]";
-        } else if (type instanceof WildcardType) {
-            WildcardType wt = (WildcardType) type;
-            Type[] lowerBounds = wt.getLowerBounds();
-            if (lowerBounds.length == 0) {
-                String name = "? extends " + concatWildcardTypes(wt.getUpperBounds());
-
-                // Special case for ?
-                if (name.equals("? extends java.lang.Object")) {
-                    return "?";
-                } else {
-                    return name;
-                }
-            } else {
-                String name = concatWildcardTypes(wt.getUpperBounds()) +
-                " super " +
-                concatWildcardTypes(wt.getLowerBounds());
-                // Another special case for ?
-                name = name.replace("java.lang.Object", "?");
-                return name;
-            }
-        } else {
-            throw new RuntimeException("Got an unknown java.lang.Type");
-        }
-    }
-
-    /**
-     * Cleans up jdiff parameters to canonicalize them.
-     *
-     * @param paramType the parameter from jdiff.
-     * @return the scrubbed version of the parameter.
-     */
-    private static String scrubJdiffParamType(String paramType) {
-        // <? extends java.lang.Object and <?> are the same, so
-        // canonicalize them to one form.
-        return paramType.replace("<? extends java.lang.Object>", "<?>");
-    }
-}
diff --git a/tests/SignatureTest/src/android/tests/sigtest/ResultObserver.java b/tests/SignatureTest/src/android/tests/sigtest/ResultObserver.java
deleted file mode 100644
index e9d2260..0000000
--- a/tests/SignatureTest/src/android/tests/sigtest/ResultObserver.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2008 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.tests.sigtest;
-
-import android.tests.sigtest.SignatureTest.FAILURE_TYPE;
-/**
- * Interface for saving signature test result.
- */
-public interface ResultObserver {
-    /**
-     * Notify failure.
-     * @param type Failure type.
-     * @param name Name of the failed element (interface/class/method/field)
-     * @param errorMessage a descriptive message indicating why it failed.
-     */
-    void notifyFailure(FAILURE_TYPE type,
-                       String name,
-                       String errorMessage);
-
-}
diff --git a/tests/SignatureTest/src/android/tests/sigtest/SignatureTest.java b/tests/SignatureTest/src/android/tests/sigtest/SignatureTest.java
deleted file mode 100644
index 8ae02ac3..0000000
--- a/tests/SignatureTest/src/android/tests/sigtest/SignatureTest.java
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * 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.
- */
-
-package android.tests.sigtest;
-
-import android.content.res.Resources;
-import android.test.AndroidTestCase;
-import android.tests.sigtest.JDiffClassDescription.JDiffConstructor;
-import android.tests.sigtest.JDiffClassDescription.JDiffField;
-import android.tests.sigtest.JDiffClassDescription.JDiffMethod;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-
-/**
- * Performs the signature check via a JUnit test.
- */
-public class SignatureTest extends AndroidTestCase {
-
-    private static final String TAG_ROOT = "api";
-    private static final String TAG_PACKAGE = "package";
-    private static final String TAG_CLASS = "class";
-    private static final String TAG_INTERFACE = "interface";
-    private static final String TAG_IMPLEMENTS = "implements";
-    private static final String TAG_CONSTRUCTOR = "constructor";
-    private static final String TAG_METHOD = "method";
-    private static final String TAG_PARAM = "parameter";
-    private static final String TAG_EXCEPTION = "exception";
-    private static final String TAG_FIELD = "field";
-
-    private static final String MODIFIER_ABSTRACT = "abstract";
-    private static final String MODIFIER_FINAL = "final";
-    private static final String MODIFIER_NATIVE = "native";
-    private static final String MODIFIER_PRIVATE = "private";
-    private static final String MODIFIER_PROTECTED = "protected";
-    private static final String MODIFIER_PUBLIC = "public";
-    private static final String MODIFIER_STATIC = "static";
-    private static final String MODIFIER_SYNCHRONIZED = "synchronized";
-    private static final String MODIFIER_TRANSIENT = "transient";
-    private static final String MODIFIER_VOLATILE = "volatile";
-    private static final String MODIFIER_VISIBILITY = "visibility";
-
-    private static final String ATTRIBUTE_NAME = "name";
-    private static final String ATTRIBUTE_EXTENDS = "extends";
-    private static final String ATTRIBUTE_TYPE = "type";
-    private static final String ATTRIBUTE_RETURN = "return";
-
-    private static ArrayList<String> mDebugArray = new ArrayList<String>();
-
-    private HashSet<String> mKeyTagSet;
-    private TestResultObserver mResultObserver;
-
-    /**
-     * Define the type of the signature check failures.
-     */
-    public static enum FAILURE_TYPE {
-        MISSING_CLASS,
-        MISSING_INTERFACE,
-        MISSING_METHOD,
-        MISSING_FIELD,
-        MISMATCH_CLASS,
-        MISMATCH_INTERFACE,
-        MISMATCH_METHOD,
-        MISMATCH_FIELD,
-        CAUGHT_EXCEPTION,
-    }
-
-    private class TestResultObserver implements ResultObserver {
-        boolean mDidFail = false;
-        StringBuilder mErrorString = new StringBuilder();
-
-        public void notifyFailure(FAILURE_TYPE type, String name, String errorMessage) {
-            mDidFail = true;
-            mErrorString.append("\n");
-            mErrorString.append(type.toString().toLowerCase());
-            mErrorString.append(":\t");
-            mErrorString.append(name);
-        }
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mKeyTagSet = new HashSet<String>();
-        mKeyTagSet.addAll(Arrays.asList(new String[] {
-                TAG_PACKAGE, TAG_CLASS, TAG_INTERFACE, TAG_IMPLEMENTS, TAG_CONSTRUCTOR,
-                TAG_METHOD, TAG_PARAM, TAG_EXCEPTION, TAG_FIELD }));
-        mResultObserver = new TestResultObserver();
-    }
-
-    /**
-     * Tests that the device's API matches the expected set defined in xml.
-     * <p/>
-     * Will check the entire API, and then report the complete list of failures
-     */
-    public void testSignature() {
-        Resources r = getContext().getResources();
-        Class rClass = R.xml.class;
-        Field[] fs = rClass.getFields();
-        for (Field f : fs) {
-            try {
-                start(r.getXml(f.getInt(rClass)));
-            } catch (Exception e) {
-                mResultObserver.notifyFailure(FAILURE_TYPE.CAUGHT_EXCEPTION, e.getMessage(),
-                        e.getMessage());
-            }
-        }
-        if (mResultObserver.mDidFail) {
-            fail(mResultObserver.mErrorString.toString());
-        }
-    }
-
-    private  void beginDocument(XmlPullParser parser, String firstElementName)
-            throws XmlPullParserException, IOException {
-        int type;
-        while ((type=parser.next()) != XmlPullParser.START_TAG
-                   && type != XmlPullParser.END_DOCUMENT) { }
-
-        if (type != XmlPullParser.START_TAG) {
-            throw new XmlPullParserException("No start tag found");
-        }
-
-        if (!parser.getName().equals(firstElementName)) {
-            throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() +
-                    ", expected " + firstElementName);
-        }
-    }
-
-    /**
-     * Signature test entry point.
-     */
-    private void start(XmlPullParser parser) throws XmlPullParserException, IOException {
-        JDiffClassDescription currentClass = null;
-        String currentPackage = "";
-        JDiffMethod currentMethod = null;
-
-        beginDocument(parser, TAG_ROOT);
-        int type;
-        while (true) {
-            type = XmlPullParser.START_DOCUMENT;
-            while ((type=parser.next()) != XmlPullParser.START_TAG
-                       && type != XmlPullParser.END_DOCUMENT
-                       && type != XmlPullParser.END_TAG) {
-
-            }
-
-            if (type == XmlPullParser.END_TAG) {
-                if (TAG_CLASS.equals(parser.getName())
-                        || TAG_INTERFACE.equals(parser.getName())) {
-                    currentClass.checkSignatureCompliance();
-                } else if (TAG_PACKAGE.equals(parser.getName())) {
-                    currentPackage = "";
-                }
-                continue;
-            }
-
-            if (type == XmlPullParser.END_DOCUMENT) {
-                break;
-            }
-
-            String tagname = parser.getName();
-            if (!mKeyTagSet.contains(tagname)) {
-                continue;
-            }
-
-            if (type == XmlPullParser.START_TAG && tagname.equals(TAG_PACKAGE)) {
-                currentPackage = parser.getAttributeValue(null, ATTRIBUTE_NAME);
-            } else if (tagname.equals(TAG_CLASS)) {
-                currentClass = loadClassInfo(parser, false, currentPackage);
-            } else if (tagname.equals(TAG_INTERFACE)) {
-                currentClass = loadClassInfo(parser, true, currentPackage);
-            } else if (tagname.equals(TAG_IMPLEMENTS)) {
-                currentClass.addImplInterface(parser.getAttributeValue(null, ATTRIBUTE_NAME));
-            } else if (tagname.equals(TAG_CONSTRUCTOR)) {
-                JDiffConstructor constructor = loadConstructorInfo(parser, currentClass);
-                currentClass.addConstructor(constructor);
-                currentMethod = constructor;
-            } else if (tagname.equals(TAG_METHOD)) {
-                currentMethod = loadMethodInfo(currentClass.getClassName(), parser);
-                currentClass.addMethod(currentMethod);
-            } else if (tagname.equals(TAG_PARAM)) {
-                currentMethod.addParam(parser.getAttributeValue(null, ATTRIBUTE_TYPE));
-            } else if (tagname.equals(TAG_EXCEPTION)) {
-                currentMethod.addException(parser.getAttributeValue(null, ATTRIBUTE_TYPE));
-            } else if (tagname.equals(TAG_FIELD)) {
-                JDiffField field = loadFieldInfo(currentClass.getClassName(), parser);
-                currentClass.addField(field);
-            } else {
-                throw new RuntimeException(
-                        "unknow tag exception:" + tagname);
-            }
-        }
-    }
-
-    /**
-     * Load field information from xml to memory.
-     *
-     * @param className of the class being examined which will be shown in error messages
-     * @param parser The XmlPullParser which carries the xml information.
-     * @return the new field
-     */
-    private JDiffField loadFieldInfo(String className, XmlPullParser parser) {
-        String fieldName = parser.getAttributeValue(null, ATTRIBUTE_NAME);
-        String fieldType = parser.getAttributeValue(null, ATTRIBUTE_TYPE);
-        int modifier = jdiffModifierToReflectionFormat(className, parser);
-        return new JDiffField(fieldName, fieldType, modifier);
-    }
-
-    /**
-     * Load method information from xml to memory.
-     *
-     * @param className of the class being examined which will be shown in error messages
-     * @param parser The XmlPullParser which carries the xml information.
-     * @return the newly loaded method.
-     */
-    private JDiffMethod loadMethodInfo(String className, XmlPullParser parser) {
-        String methodName = parser.getAttributeValue(null, ATTRIBUTE_NAME);
-        String returnType = parser.getAttributeValue(null, ATTRIBUTE_RETURN);
-        int modifier = jdiffModifierToReflectionFormat(className, parser);
-        return new JDiffMethod(methodName, modifier, returnType);
-    }
-
-    /**
-     * Load constructor information from xml to memory.
-     *
-     * @param parser The XmlPullParser which carries the xml information.
-     * @param currentClass the current class being loaded.
-     * @return the new constructor
-     */
-    private JDiffConstructor loadConstructorInfo(XmlPullParser parser,
-                                                 JDiffClassDescription currentClass) {
-        String name = currentClass.getClassName();
-        int modifier = jdiffModifierToReflectionFormat(name, parser);
-        return new JDiffConstructor(name, modifier);
-    }
-
-    /**
-     * Load class or interface information to memory.
-     *
-     * @param parser The XmlPullParser which carries the xml information.
-     * @param isInterface true if the current class is an interface, otherwise is false.
-     * @param pkg the name of the java package this class can be found in.
-     * @return the new class description.
-     */
-    private JDiffClassDescription loadClassInfo(XmlPullParser parser,
-                                                boolean isInterface,
-                                                String pkg) {
-        String className = parser.getAttributeValue(null, ATTRIBUTE_NAME);
-        JDiffClassDescription currentClass = new JDiffClassDescription(pkg,
-                                                                       className,
-                                                                       mResultObserver);
-        currentClass.setModifier(jdiffModifierToReflectionFormat(className, parser));
-        currentClass.setType(isInterface ? JDiffClassDescription.JDiffType.INTERFACE :
-                             JDiffClassDescription.JDiffType.CLASS);
-        currentClass.setExtendsClass(parser.getAttributeValue(null, ATTRIBUTE_EXTENDS));
-        return currentClass;
-    }
-
-    /**
-     * Convert string modifier to int modifier.
-     *
-     * @param name of the class/method/field being examined which will be shown in error messages
-     * @param key modifier name
-     * @param value modifier value
-     * @return converted modifier value
-     */
-    private static int modifierDescriptionToReflectedType(String name, String key, String value) {
-        if (key.equals(MODIFIER_ABSTRACT)) {
-            return value.equals("true") ? Modifier.ABSTRACT : 0;
-        } else if (key.equals(MODIFIER_FINAL)) {
-            return value.equals("true") ? Modifier.FINAL : 0;
-        } else if (key.equals(MODIFIER_NATIVE)) {
-            return value.equals("true") ? Modifier.NATIVE : 0;
-        } else if (key.equals(MODIFIER_STATIC)) {
-            return value.equals("true") ? Modifier.STATIC : 0;
-        } else if (key.equals(MODIFIER_SYNCHRONIZED)) {
-            return value.equals("true") ? Modifier.SYNCHRONIZED : 0;
-        } else if (key.equals(MODIFIER_TRANSIENT)) {
-            return value.equals("true") ? Modifier.TRANSIENT : 0;
-        } else if (key.equals(MODIFIER_VOLATILE)) {
-            return value.equals("true") ? Modifier.VOLATILE : 0;
-        } else if (key.equals(MODIFIER_VISIBILITY)) {
-            if (value.equals(MODIFIER_PRIVATE)) {
-                throw new RuntimeException("Private visibility found in API spec: " + name);
-            } else if (value.equals(MODIFIER_PROTECTED)) {
-                return Modifier.PROTECTED;
-            } else if (value.equals(MODIFIER_PUBLIC)) {
-                return Modifier.PUBLIC;
-            } else if ("".equals(value)) {
-                // If the visibility is "", it means it has no modifier.
-                // which is package private. We should return 0 for this modifier.
-                return 0;
-            } else {
-                throw new RuntimeException("Unknown modifier found in API spec: " + value);
-            }
-        }
-        return 0;
-    }
-
-    /**
-     * Transfer string modifier to int one.
-     *
-     * @param name of the class/method/field being examined which will be shown in error messages
-     * @param parser XML resource parser
-     * @return converted modifier
-     */
-    private static int jdiffModifierToReflectionFormat(String name, XmlPullParser parser){
-        int modifier = 0;
-        for (int i = 0;i < parser.getAttributeCount();i++) {
-            modifier |= modifierDescriptionToReflectedType(name, parser.getAttributeName(i),
-                    parser.getAttributeValue(i));
-        }
-        return modifier;
-    }
-}
diff --git a/tests/SignatureTest/src/android/tests/sigtest/SignatureTestLog.java b/tests/SignatureTest/src/android/tests/sigtest/SignatureTestLog.java
deleted file mode 100644
index 7cd9663..0000000
--- a/tests/SignatureTest/src/android/tests/sigtest/SignatureTestLog.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2008 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.tests.sigtest;
-
-import android.util.Log;
-
-public class SignatureTestLog {
-    private static final String TAG = "CTSSignatureTest";
-
-    public static void e(String msg, Exception e) {
-        Log.e(TAG, msg, e);
-    }
-
-    public static void d(String msg) {
-        Log.d(TAG, msg);
-    }
-}
diff --git a/tests/SignatureTest/tests/Android.mk b/tests/SignatureTest/tests/Android.mk
deleted file mode 100644
index bdd0a90..0000000
--- a/tests/SignatureTest/tests/Android.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-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_JAVA_LIBRARIES := android.test.runner
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := SignatureTestTests
-
-LOCAL_INSTRUMENTATION_FOR := SignatureTest
-
-LOCAL_PROGUARD_FLAGS := -ignorewarnings
-
-LOCAL_DEX_PREOPT := false
-
-include $(BUILD_PACKAGE)
diff --git a/tests/SignatureTest/tests/AndroidManifest.xml b/tests/SignatureTest/tests/AndroidManifest.xml
deleted file mode 100644
index ab8a6d6..0000000
--- a/tests/SignatureTest/tests/AndroidManifest.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 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.tests.sigtest.tests">
-
-    <application>
-        <uses-library android:name="android.test.runner"/>
-    </application>
-
-    <instrumentation android:name="android.test.InstrumentationTestRunner"
-                     android:targetPackage="android.tests.sigtest"
-                     android:label="SignatureTest Functional Testset"/>
-
-</manifest>
diff --git a/tests/SignatureTest/tests/src/android/tests/sigtest/tests/AllTests.java b/tests/SignatureTest/tests/src/android/tests/sigtest/tests/AllTests.java
deleted file mode 100644
index 096cb02..0000000
--- a/tests/SignatureTest/tests/src/android/tests/sigtest/tests/AllTests.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2008 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.tests.sigtest.tests;
-
-import android.test.TestSuiteProvider;
-import android.test.suitebuilder.TestSuiteBuilder;
-
-import junit.framework.TestSuite;
-
-/**
- * Finds all instrumentation and unit tests for this application.
- */
-public class AllTests implements TestSuiteProvider {
-    public TestSuite getTestSuite() {
-        return new TestSuiteBuilder(getClass()).includeAllPackagesUnderHere().build();
-    }
-}
diff --git a/tests/SignatureTest/tests/src/android/tests/sigtest/tests/JDiffClassDescriptionTest.java b/tests/SignatureTest/tests/src/android/tests/sigtest/tests/JDiffClassDescriptionTest.java
deleted file mode 100644
index b5bf49e..0000000
--- a/tests/SignatureTest/tests/src/android/tests/sigtest/tests/JDiffClassDescriptionTest.java
+++ /dev/null
@@ -1,394 +0,0 @@
-/*
- * Copyright (C) 2007 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.tests.sigtest.tests;
-
-import android.test.InstrumentationTestCase;
-import android.tests.sigtest.JDiffClassDescription;
-import android.tests.sigtest.ResultObserver;
-import android.tests.sigtest.SignatureTest.FAILURE_TYPE;
-
-import java.lang.reflect.Modifier;
-
-/**
- * Test class for JDiffClassDescription.
- */
-public class JDiffClassDescriptionTest extends InstrumentationTestCase {
-    private class NoFailures implements ResultObserver {
-        public void notifyFailure(FAILURE_TYPE type, String name, String errmsg) {
-            JDiffClassDescriptionTest.this.fail("Saw unexpected test failure: " + name + " failure type: " + type);
-        }
-    }
-
-    private class ExpectFailure implements ResultObserver {
-        private FAILURE_TYPE expectedType;
-        private boolean failureSeen;
-
-        public ExpectFailure(FAILURE_TYPE expectedType) {
-            this.expectedType = expectedType;
-        }
-
-        public void notifyFailure(FAILURE_TYPE type, String name, String errMsg) {
-            if (type == expectedType) {
-                if (failureSeen) {
-                    JDiffClassDescriptionTest.this.fail("Saw second test failure: " + name + " failure type: " + type);
-                } else {
-                    // We've seen the error, mark it and keep going
-                    failureSeen = true;
-                }
-            } else {
-                JDiffClassDescriptionTest.this.fail("Saw unexpected test failure: " + name + " failure type: " + type);
-            }
-        }
-        
-        public void validate() {
-            JDiffClassDescriptionTest.this.assertTrue(failureSeen);
-        }
-    }
-
-    /**
-     * Create the JDiffClassDescription for "NormalClass".
-     *
-     * @return the new JDiffClassDescription
-     */
-    private JDiffClassDescription createNormalClass() {
-        return createNormalClass(new NoFailures());
-    }
-
-    /**
-     * Create the JDiffClassDescription for "NormalClass".
-     *
-     * @return the new JDiffClassDescription
-     */
-    private JDiffClassDescription createNormalClass(ResultObserver observer) {
-        JDiffClassDescription clz = new JDiffClassDescription("android.tests.sigtest.tests.data", "NormalClass", observer);
-        clz.setType(JDiffClassDescription.JDiffType.CLASS);
-        clz.setModifier(Modifier.PUBLIC);
-        return clz;
-    }    
-
-    public void testNormalClassCompliance() {
-        JDiffClassDescription clz = createNormalClass();
-        clz.checkSignatureCompliance();
-        assertEquals(clz.toSignatureString(),
-        "public class NormalClass");
-    }
-
-    public void testMissingClass() {
-        ExpectFailure observer = new ExpectFailure(FAILURE_TYPE.MISSING_CLASS);
-        JDiffClassDescription clz = new JDiffClassDescription("android.tests.sigtest.tests.data",
-                "NoSuchClass",
-                observer);
-        clz.setType(JDiffClassDescription.JDiffType.CLASS);
-        clz.checkSignatureCompliance();
-        observer.validate();
-    }
-
-    public void testSimpleConstructor() {
-        JDiffClassDescription clz = createNormalClass();
-        JDiffClassDescription.JDiffConstructor constructor = new JDiffClassDescription.JDiffConstructor("NormalClass", Modifier.PUBLIC);
-        clz.addConstructor(constructor);
-        clz.checkSignatureCompliance();
-        assertEquals(constructor.toSignatureString(), "public NormalClass()");
-    }
-    public void testOneArgConstructor() {
-        JDiffClassDescription clz = createNormalClass();
-        JDiffClassDescription.JDiffConstructor constructor = new JDiffClassDescription.JDiffConstructor("NormalClass", Modifier.PRIVATE);
-        constructor.addParam("java.lang.String");
-        clz.addConstructor(constructor);
-        clz.checkSignatureCompliance();
-        assertEquals(constructor.toSignatureString(), "private NormalClass(java.lang.String)");
-    }
-    public void testConstructorThrowsException() {
-        JDiffClassDescription clz = createNormalClass();
-        JDiffClassDescription.JDiffConstructor constructor = new JDiffClassDescription.JDiffConstructor("NormalClass", Modifier.PROTECTED);
-        constructor.addParam("java.lang.String");
-        constructor.addParam("java.lang.String");
-        constructor.addException("android.tests.sigtest.tests.data.NormalException");
-        clz.addConstructor(constructor);
-        clz.checkSignatureCompliance();
-        assertEquals(constructor.toSignatureString(), "protected NormalClass(java.lang.String, " +
-                "java.lang.String) throws android.tests.sigtest.tests.data.NormalException");
-    }
-    public void testPackageProtectedConstructor() {
-        JDiffClassDescription clz = createNormalClass();
-        JDiffClassDescription.JDiffConstructor constructor = new JDiffClassDescription.JDiffConstructor("NormalClass", 0);
-        constructor.addParam("java.lang.String");
-        constructor.addParam("java.lang.String");
-        constructor.addParam("java.lang.String");
-        clz.addConstructor(constructor);
-        clz.checkSignatureCompliance();
-        assertEquals(constructor.toSignatureString(), "NormalClass(java.lang.String, java.lang.String, java.lang.String)");
-    }
-
-    public void testStaticMethod() {
-        JDiffClassDescription clz = createNormalClass();
-        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod("staticMethod", Modifier.STATIC | Modifier.PUBLIC, "void");
-        clz.addMethod(method);
-        clz.checkSignatureCompliance();
-        assertEquals(method.toSignatureString(), "public static void staticMethod()");
-    }
-    public void testSyncMethod() {
-        JDiffClassDescription clz = createNormalClass();
-        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod("syncMethod", Modifier.SYNCHRONIZED | Modifier.PUBLIC, "void");
-        clz.addMethod(method);
-        clz.checkSignatureCompliance();
-        assertEquals(method.toSignatureString(), "public synchronized void syncMethod()");
-    }
-    public void testPackageProtectMethod() {
-        JDiffClassDescription clz = createNormalClass();
-        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod("packageProtectedMethod", 0, "boolean");
-        clz.addMethod(method);
-        clz.checkSignatureCompliance();
-        assertEquals(method.toSignatureString(), "boolean packageProtectedMethod()");
-    }
-    public void testPrivateMethod() {
-        JDiffClassDescription clz = createNormalClass();
-        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod("privateMethod", Modifier.PRIVATE, "void");
-        clz.addMethod(method);
-        clz.checkSignatureCompliance();
-        assertEquals(method.toSignatureString(), "private void privateMethod()");
-    }
-    public void testProtectedMethod() {
-        JDiffClassDescription clz = createNormalClass();
-        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod("protectedMethod", Modifier.PROTECTED, "java.lang.String");
-        clz.addMethod(method);
-        clz.checkSignatureCompliance();
-        assertEquals(method.toSignatureString(), "protected java.lang.String protectedMethod()");
-    }
-    public void testThrowsMethod() {
-        JDiffClassDescription clz = createNormalClass();
-        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod("throwsMethod", Modifier.PUBLIC, "void");
-        method.addException("android.tests.sigtest.tests.data.NormalException");
-        clz.addMethod(method);
-        clz.checkSignatureCompliance();
-        assertEquals(method.toSignatureString(), "public void throwsMethod() throws" + 
-                " android.tests.sigtest.tests.data.NormalException");
-    }
-    public void testNativeMethod() {
-        JDiffClassDescription clz = createNormalClass();
-        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod("nativeMethod", Modifier.PUBLIC | Modifier.NATIVE, "void");
-        clz.addMethod(method);
-        clz.checkSignatureCompliance();
-        assertEquals(method.toSignatureString(), "public native void nativeMethod()");
-    }
-
-    public void testFinalField() {
-        JDiffClassDescription clz = createNormalClass();
-        JDiffClassDescription.JDiffField field = new JDiffClassDescription.JDiffField("FINAL_FIELD", "java.lang.String", Modifier.PUBLIC | Modifier.FINAL);
-        clz.addField(field);
-        clz.checkSignatureCompliance();
-        assertEquals(field.toSignatureString(), "public final java.lang.String FINAL_FIELD");
-    }
-    public void testStaticField() {
-        JDiffClassDescription clz = createNormalClass();
-        JDiffClassDescription.JDiffField field = new JDiffClassDescription.JDiffField("STATIC_FIELD", "java.lang.String", Modifier.PUBLIC | Modifier.STATIC);
-        clz.addField(field);
-        clz.checkSignatureCompliance();
-        assertEquals(field.toSignatureString(), "public static java.lang.String STATIC_FIELD");
-    }
-    public void testVolatileFiled() {
-        JDiffClassDescription clz = createNormalClass();
-        JDiffClassDescription.JDiffField field = new JDiffClassDescription.JDiffField("VOLATILE_FIELD", "java.lang.String", Modifier.PUBLIC | Modifier.VOLATILE);
-        clz.addField(field);
-        clz.checkSignatureCompliance();
-        assertEquals(field.toSignatureString(), "public volatile java.lang.String VOLATILE_FIELD");
-    }
-    public void testTransientField() {
-        JDiffClassDescription clz = createNormalClass();
-        JDiffClassDescription.JDiffField field = new JDiffClassDescription.JDiffField("TRANSIENT_FIELD", "java.lang.String", Modifier.PUBLIC | Modifier.TRANSIENT);
-        clz.addField(field);
-        clz.checkSignatureCompliance();
-        assertEquals(field.toSignatureString(), "public transient java.lang.String TRANSIENT_FIELD");
-    }
-    public void testPacakgeField() {
-        JDiffClassDescription clz = createNormalClass();
-        JDiffClassDescription.JDiffField field = new JDiffClassDescription.JDiffField("PACAKGE_FIELD", "java.lang.String", 0);
-        clz.addField(field);
-        clz.checkSignatureCompliance();
-        assertEquals(field.toSignatureString(), "java.lang.String PACAKGE_FIELD");
-    }
-    public void testPrivateField() {
-        JDiffClassDescription clz = createNormalClass();
-        JDiffClassDescription.JDiffField field = new JDiffClassDescription.JDiffField("PRIVATE_FIELD", "java.lang.String", Modifier.PRIVATE);
-        clz.addField(field);
-        clz.checkSignatureCompliance();
-        assertEquals(field.toSignatureString(), "private java.lang.String PRIVATE_FIELD");
-    }
-    public void testProtectedField() {
-        JDiffClassDescription clz = createNormalClass();
-        JDiffClassDescription.JDiffField field = new JDiffClassDescription.JDiffField("PROTECTED_FIELD", "java.lang.String", Modifier.PROTECTED);
-        clz.addField(field);
-        clz.checkSignatureCompliance();
-        assertEquals(field.toSignatureString(), "protected java.lang.String PROTECTED_FIELD");
-    }
-
-    public void testInnerClass() {
-        JDiffClassDescription clz = new JDiffClassDescription("android.tests.sigtest.tests.data", "NormalClass.InnerClass", new NoFailures());
-        clz.setType(JDiffClassDescription.JDiffType.CLASS);
-        clz.setModifier(Modifier.PUBLIC);
-        JDiffClassDescription.JDiffField field = new JDiffClassDescription.JDiffField("innerClassData", "java.lang.String", Modifier.PRIVATE);
-        clz.addField(field);
-        clz.checkSignatureCompliance();
-        assertEquals(clz.toSignatureString(), "public class NormalClass.InnerClass");
-    }
-    public void testInnerInnerClass() {
-        JDiffClassDescription clz = new JDiffClassDescription("android.tests.sigtest.tests.data", "NormalClass.InnerClass.InnerInnerClass", new NoFailures());
-        clz.setType(JDiffClassDescription.JDiffType.CLASS);
-        clz.setModifier(Modifier.PUBLIC);
-        JDiffClassDescription.JDiffField field = new JDiffClassDescription.JDiffField("innerInnerClassData", "java.lang.String", Modifier.PRIVATE);
-        clz.addField(field);
-        clz.checkSignatureCompliance();
-        assertEquals(clz.toSignatureString(), "public class NormalClass.InnerClass.InnerInnerClass");
-    }
-    public void testInnerInterface() {
-        JDiffClassDescription clz = new JDiffClassDescription("android.tests.sigtest.tests.data", "NormalClass.InnerInterface", new NoFailures());
-        clz.setType(JDiffClassDescription.JDiffType.INTERFACE);
-        clz.setModifier(Modifier.PUBLIC | Modifier.STATIC | Modifier.ABSTRACT);
-        clz.addMethod(new JDiffClassDescription.JDiffMethod("doSomething", Modifier.PUBLIC, "void"));
-        clz.checkSignatureCompliance();
-        assertEquals(clz.toSignatureString(), "public interface NormalClass.InnerInterface");
-    }
-    public void testInterface() {
-        JDiffClassDescription clz = new JDiffClassDescription("android.tests.sigtest.tests.data", "NormalInterface", new NoFailures());
-        clz.setType(JDiffClassDescription.JDiffType.INTERFACE);
-        clz.setModifier(Modifier.PUBLIC | Modifier.ABSTRACT);
-        clz.addMethod(new JDiffClassDescription.JDiffMethod("doSomething", Modifier.PUBLIC, "void"));
-        clz.checkSignatureCompliance();
-        assertEquals(clz.toSignatureString(), "public interface NormalInterface");
-    }
-    public void testFinalClass() {
-        JDiffClassDescription clz = new JDiffClassDescription("android.tests.sigtest.tests.data", "FinalClass", new NoFailures());
-        clz.setType(JDiffClassDescription.JDiffType.CLASS);
-        clz.setModifier(Modifier.PUBLIC | Modifier.FINAL);
-        clz.checkSignatureCompliance();
-        assertEquals(clz.toSignatureString(), "public final class FinalClass");
-    }
-    /** Test the case where the API declares the method not
-     *  synchronized, but it actually is. */
-    public void testAddingSync() {
-        ExpectFailure observer = new ExpectFailure(FAILURE_TYPE.MISMATCH_METHOD);
-        JDiffClassDescription clz = createNormalClass(observer);
-        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod("syncMethod", Modifier.PUBLIC, "void");
-        clz.addMethod(method);
-        clz.checkSignatureCompliance();
-        observer.validate();
-    }
-    /** Test the case where the API declares the method is
-     *  synchronized, but it actually is not. */
-    public void testRemovingSync() {
-        JDiffClassDescription clz = createNormalClass();
-        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod("notSyncMethod", Modifier.SYNCHRONIZED | Modifier.PUBLIC, "void");
-        clz.addMethod(method);
-        clz.checkSignatureCompliance();
-    }
-    /** API says method is not native, but it actually is.
-     *  http://b/1839558
-     */
-    public void testAddingNative() {
-        JDiffClassDescription clz = createNormalClass();
-        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod("nativeMethod", Modifier.PUBLIC, "void");
-        clz.addMethod(method);
-        clz.checkSignatureCompliance();
-    }
-    /** API says method is native, but actually isn't.
-     *  http://b/1839558
-     */
-    public void testRemovingNative() {
-        JDiffClassDescription clz = createNormalClass();
-        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod("notNativeMethod", Modifier.NATIVE | Modifier.PUBLIC, "void");
-        clz.addMethod(method);
-        clz.checkSignatureCompliance();
-    }
-    public void testAbstractClass() {
-        JDiffClassDescription clz = new JDiffClassDescription("android.tests.sigtest.tests.data", "AbstractClass", new NoFailures());
-        clz.setType(JDiffClassDescription.JDiffType.CLASS);
-        clz.setModifier(Modifier.PUBLIC | Modifier.ABSTRACT);
-        clz.checkSignatureCompliance();
-        assertEquals(clz.toSignatureString(), "public abstract class AbstractClass");
-    }
-    /** API lists class as abstract, reflection does not.
-     * http://b/1839622
-     */
-    public void testRemovingAbstractFromAClass() {
-        JDiffClassDescription clz = new JDiffClassDescription("android.tests.sigtest.tests.data", "NormalClass", new NoFailures());
-        clz.setType(JDiffClassDescription.JDiffType.CLASS);
-        clz.setModifier(Modifier.PUBLIC | Modifier.ABSTRACT);
-        clz.checkSignatureCompliance();
-    }
-    /** reflection lists class as abstract, api does not.
-     * http://b/1839622
-     */
-    public void testAddingAbstractToAClass() {
-        ExpectFailure observer = new ExpectFailure(FAILURE_TYPE.MISMATCH_CLASS);
-        JDiffClassDescription clz = new JDiffClassDescription("android.tests.sigtest.tests.data",
-                "AbstractClass", 
-                observer);
-        clz.setType(JDiffClassDescription.JDiffType.CLASS);
-        clz.setModifier(Modifier.PUBLIC);
-        clz.checkSignatureCompliance();
-        observer.validate();
-    }
-    public void testFinalMethod() {
-        JDiffClassDescription clz = createNormalClass();
-        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod("finalMethod", Modifier.PUBLIC | Modifier.FINAL, "void");
-        clz.addMethod(method);
-        clz.checkSignatureCompliance();
-        assertEquals(method.toSignatureString(), "public final void finalMethod()");
-    }
-    /**
-     * Final Class, API lists methods as non-final, reflection has it as final.
-     * http://b/1839589
-     */
-    public void testAddingFinalToAMethodInAFinalClass() {
-        JDiffClassDescription clz = new JDiffClassDescription("android.tests.sigtest.tests.data", "FinalClass", new NoFailures());
-        clz.setType(JDiffClassDescription.JDiffType.CLASS);
-        clz.setModifier(Modifier.PUBLIC | Modifier.FINAL);
-        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod("finalMethod", Modifier.PUBLIC, "void");
-        clz.addMethod(method);
-        clz.checkSignatureCompliance();        
-    }
-    /**
-     * Final Class, API lists methods as final, reflection has it as non-final.
-     * http://b/1839589
-     */
-    public void testRemovingFinalToAMethodInAFinalClass() {
-        JDiffClassDescription clz = new JDiffClassDescription("android.tests.sigtest.tests.data", "FinalClass", new NoFailures());
-        clz.setType(JDiffClassDescription.JDiffType.CLASS);
-        clz.setModifier(Modifier.PUBLIC | Modifier.FINAL);
-        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod("nonFinalMethod", 
-                Modifier.PUBLIC | Modifier.FINAL, 
-                "void");
-        clz.addMethod(method);
-        clz.checkSignatureCompliance();        
-    }
-    /**
-     * non-final Class, API lists methods as non-final, reflection has it as final.
-     * http://b/1839589
-     */  
-    public void testAddingFinalToAMethodInANonFinalClass() {
-        ExpectFailure observer = new ExpectFailure(FAILURE_TYPE.MISMATCH_METHOD);
-        JDiffClassDescription clz = new JDiffClassDescription("android.tests.sigtest.tests.data", 
-                "NormalClass", 
-                observer);
-        clz.setType(JDiffClassDescription.JDiffType.CLASS);
-        clz.setModifier(Modifier.PUBLIC);
-        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod("finalMethod", Modifier.PUBLIC, "void");
-        clz.addMethod(method);
-        clz.checkSignatureCompliance();  
-        observer.validate();
-    }
-}
diff --git a/tests/SignatureTest/tests/src/android/tests/sigtest/tests/data/AbstractClass.java b/tests/SignatureTest/tests/src/android/tests/sigtest/tests/data/AbstractClass.java
deleted file mode 100644
index d24d691..0000000
--- a/tests/SignatureTest/tests/src/android/tests/sigtest/tests/data/AbstractClass.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2009 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.tests.sigtest.tests.data;
-
-/**
-* This class is used as reference data for the JDiffClassDescriptionTest tests.
-*/
-public abstract class AbstractClass {
-
-}
diff --git a/tests/SignatureTest/tests/src/android/tests/sigtest/tests/data/FinalClass.java b/tests/SignatureTest/tests/src/android/tests/sigtest/tests/data/FinalClass.java
deleted file mode 100644
index 4c871f0..0000000
--- a/tests/SignatureTest/tests/src/android/tests/sigtest/tests/data/FinalClass.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2007 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.tests.sigtest.tests.data;
-
-/**
- * This class is used as reference data for the
- * JDiffClassDescriptionTest tests.  These classes will actually be
- * examined through reflection and Class.forName as part of testing
- * JDiffClassDescription.  That is why there is no implementation for
- * any of these methods.
- */
-public final class FinalClass {
-    public final void finalMethod() { }
-    public void nonFinalMethod() { }
-}
diff --git a/tests/SignatureTest/tests/src/android/tests/sigtest/tests/data/NormalClass.java b/tests/SignatureTest/tests/src/android/tests/sigtest/tests/data/NormalClass.java
deleted file mode 100644
index 9cd54ab..0000000
--- a/tests/SignatureTest/tests/src/android/tests/sigtest/tests/data/NormalClass.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2007 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.tests.sigtest.tests.data;
-
-/**
- * This class is used as reference data for the
- * JDiffClassDescriptionTest tests.  These classes will actually be
- * examined through reflection and Class.forName as part of testing
- * JDiffClassDescription.  That is why there is no implementation for
- * any of these methods.
- */
-public class NormalClass {
-    // Constructors to test.
-    public NormalClass() { }
-    private NormalClass(String arg1) { }
-    protected NormalClass(String arg1, String arg2) throws NormalException { }
-    NormalClass(String arg1, String arg2, String arg3) { }
-
-    // Methods to test.
-    public static void staticMethod() { }
-    public synchronized void syncMethod() { }
-    public void notSyncMethod() { }
-    boolean packageProtectedMethod() { return false; }
-    private void privateMethod() { }
-    protected String protectedMethod() { return null; }
-    public void throwsMethod() throws NormalException { }
-    public native void nativeMethod();
-    public void notNativeMethod() { }
-    public final void finalMethod() { }
-
-    // Fields to test.
-    public final String FINAL_FIELD = "";
-    public static String STATIC_FIELD;
-    public volatile String VOLATILE_FIELD;
-    public transient String TRANSIENT_FIELD;
-    String PACAKGE_FIELD;
-    private String PRIVATE_FIELD;
-    protected String PROTECTED_FIELD;
-
-    public class InnerClass {
-        public class InnerInnerClass {
-            private String innerInnerClassData;
-        }
-        private String innerClassData;
-    }
-
-    public interface InnerInterface {
-        void doSomething();
-    }
-}
diff --git a/tests/SignatureTest/tests/src/android/tests/sigtest/tests/data/NormalException.java b/tests/SignatureTest/tests/src/android/tests/sigtest/tests/data/NormalException.java
deleted file mode 100644
index cc3d725..0000000
--- a/tests/SignatureTest/tests/src/android/tests/sigtest/tests/data/NormalException.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2007 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.tests.sigtest.tests.data;
-
-import java.lang.Exception;
-
-/**
- * This class is used as reference data for the JDiffClassDescriptionTest tests.
- */
-public class NormalException extends Exception {
-
-}
diff --git a/tests/SignatureTest/tests/src/android/tests/sigtest/tests/data/NormalInterface.java b/tests/SignatureTest/tests/src/android/tests/sigtest/tests/data/NormalInterface.java
deleted file mode 100644
index 3200b76..0000000
--- a/tests/SignatureTest/tests/src/android/tests/sigtest/tests/data/NormalInterface.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2007 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.tests.sigtest.tests.data;
-
-/**
- * This class is used as reference data for the
- * JDiffClassDescriptionTest tests.  These classes will actually be
- * examined through reflection and Class.forName as part of testing
- * JDiffClassDescription.  That is why there is no implementation for
- * any of these methods.
- */
-public interface NormalInterface {
-    void doSomething();
-}
diff --git a/tests/acceleration/Android.mk b/tests/acceleration/Android.mk
index ef96a24..a6d6022 100644
--- a/tests/acceleration/Android.mk
+++ b/tests/acceleration/Android.mk
@@ -24,8 +24,6 @@
 
 LOCAL_PROGUARD_ENABLED := disabled
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsAccelerationTestStubs
diff --git a/tests/accessibility/AndroidManifest.xml b/tests/accessibility/AndroidManifest.xml
index 0d18cef..dde1de8 100644
--- a/tests/accessibility/AndroidManifest.xml
+++ b/tests/accessibility/AndroidManifest.xml
@@ -19,8 +19,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="android.view.accessibility.services">
 
-  <uses-permission android:name="android.permission.CAN_REQUEST_TOUCH_EXPLORATION_MODE"/>
-
   <application>
 
     <service android:name=".SpeakingAccessibilityService"
diff --git a/tests/app/Android.mk b/tests/app/Android.mk
new file mode 100644
index 0000000..69bf590
--- /dev/null
+++ b/tests/app/Android.mk
@@ -0,0 +1,35 @@
+# Copyright (C) 2008 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)
+
+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_PROGUARD_ENABLED := disabled
+
+LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common voip-common
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner ctstestserver
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+              src/android/app/cts/ISecondary.aidl
+
+LOCAL_PACKAGE_NAME := CtsAppTestStubs
+
+include $(BUILD_PACKAGE)
diff --git a/tests/app/AndroidManifest.xml b/tests/app/AndroidManifest.xml
new file mode 100644
index 0000000..b628a0c
--- /dev/null
+++ b/tests/app/AndroidManifest.xml
@@ -0,0 +1,283 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2007 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="com.android.cts.app.stub">
+
+    <permission android:name="android.app.cts.permission.TEST_GRANTED"
+        android:protectionLevel="normal"
+            android:label="@string/permlab_testGranted"
+            android:description="@string/permdesc_testGranted">
+        <meta-data android:name="android.app.cts.string" android:value="foo" />
+        <meta-data android:name="android.app.cts.boolean" android:value="true" />
+        <meta-data android:name="android.app.cts.integer" android:value="100" />
+        <meta-data android:name="android.app.cts.color" android:value="#ff000000" />
+        <meta-data android:name="android.app.cts.float" android:value="100.1" />
+        <meta-data android:name="android.app.cts.reference" android:resource="@xml/metadata" />
+    </permission>
+
+    <uses-permission android:name="android.app.cts.permission.TEST_GRANTED" />
+    <uses-permission android:name="android.permission.READ_CONTACTS" />
+    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+    <uses-permission android:name="android.permission.CAMERA" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+    <uses-permission android:name="android.permission.SET_WALLPAPER_HINTS" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+    <application android:label="Android TestCase"
+                android:icon="@drawable/size_48x48"
+                android:maxRecents="1"
+                android:multiArch="true"
+                android:name="android.app.cts.MockApplication"
+                android:supportsRtl="true">
+        <uses-library android:name="android.test.runner" />
+
+        <activity android:name="android.app.cts.ActionBarActivity" />
+
+        <activity android:name="android.app.cts.DialogStubActivity"
+            android:label="DialogStubActivity"
+            android:configChanges="keyboardHidden|orientation|screenSize">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.app.cts.MockActivity" android:label="MockActivity">
+            <meta-data android:name="android.app.alias"
+                android:resource="@xml/alias" />
+            <meta-data android:name="android.app.intent.filter"
+                android:resource="@xml/intentfilter" />
+        </activity>
+
+        <activity android:name="android.app.cts.MockApplicationActivity"
+            android:label="MockApplicationActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.app.cts.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" />
+                <data android:mimeType="vnd.android.cursor.dir/person" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.app.cts.AliasActivityStub">
+            <meta-data android:name="android.app.alias"
+                android:resource="@xml/alias" />
+        </activity>
+
+        <activity android:name="android.app.cts.ChildActivity"
+                        android:label="ChildActivity" />
+
+        <receiver android:name="android.app.cts.MockReceiver">
+            <intent-filter>
+                <action android:name="android.app.cts.PendingIntentTest.TEST_RECEIVER" />
+            </intent-filter>
+        </receiver>
+
+        <service android:name="android.app.cts.MockService" />
+
+        <activity android:name="android.app.cts.SearchManagerStubActivity"
+                android:label="SearchManagerStubActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.SEARCH" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <meta-data android:name="android.app.searchable" android:resource="@xml/searchable" />
+        </activity>
+
+        <service android:name="android.app.cts.LocalService">
+            <intent-filter>
+                <action android:name="android.app.cts.activity.SERVICE_LOCAL" />
+            </intent-filter>
+            <meta-data android:name="android.app.cts.string" android:value="foo" />
+            <meta-data android:name="android.app.cts.boolean" android:value="true" />
+            <meta-data android:name="android.app.cts.integer" android:value="100" />
+            <meta-data android:name="android.app.cts.color" android:value="#ff000000" />
+            <meta-data android:name="android.app.cts.float" android:value="100.1" />
+            <meta-data android:name="android.app.cts.reference" android:resource="@xml/metadata" />
+        </service>
+
+        <service android:name="android.app.cts.LocalGrantedService"
+             android:permission="android.app.cts.permission.TEST_GRANTED">
+            <intent-filter>
+                <action android:name="android.app.cts.activity.SERVICE_LOCAL_GRANTED" />
+            </intent-filter>
+        </service>
+
+        <service android:name="android.app.cts.LocalDeniedService"
+               android:permission="android.app.cts.permission.TEST_DENIED">
+            <intent-filter>
+                <action android:name="android.app.cts.activity.SERVICE_LOCAL_DENIED" />
+            </intent-filter>
+        </service>
+
+        <activity android:name="android.app.cts.TestedScreen"
+                android:process=":remoteScreen">
+        </activity>
+        <activity android:name="android.app.cts.LocalScreen" android:multiprocess="true">
+        </activity>
+        <activity android:name="android.app.cts.ClearTop" android:multiprocess="true"
+               android:launchMode="singleTop">
+        </activity>
+        <activity android:name="android.app.cts.LocalDialog" android:multiprocess="true"
+               android:theme="@android:style/Theme.Dialog">
+        </activity>
+
+        <activity android:name="android.app.cts.PendingIntentStubActivity"
+             android:label="PendingIntentStubActivity"/>
+
+        <activity android:name="android.app.cts.LocalActivityManagerStubActivity"
+                        android:label="LocalActivityManagerStubActivity" />
+
+        <activity android:name="android.app.cts.LocalActivityManagerTestHelper"
+            android:label="LocalActivityManagerTestHelper" />
+
+        <activity android:name="android.app.cts.LaunchpadTabActivity" android:multiprocess="true">
+        </activity>
+
+        <activity android:name="android.app.cts.LocalActivity" android:multiprocess="true">
+            <meta-data android:name="android.app.cts.string" android:value="foo" />
+            <meta-data android:name="android.app.cts.boolean" android:value="true" />
+            <meta-data android:name="android.app.cts.integer" android:value="100" />
+            <meta-data android:name="android.app.cts.color" android:value="#ff000000" />
+            <meta-data android:name="android.app.cts.float" android:value="100.1" />
+            <meta-data android:name="android.app.cts.reference" android:resource="@xml/metadata" />
+        </activity>
+
+        <activity android:name="android.app.cts.TestedActivity"
+                android:process=":remoteActivity">
+        </activity>
+
+        <activity android:name="android.app.cts.ExpandableListTestActivity"
+            android:label="ExpandableListTestActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.app.cts.ChildTabActivity" android:label="ChildTabActivity" />
+
+        <activity android:name="android.app.cts.LauncherActivityStub"
+                  android:label="LauncherActivityStub" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.app.cts.MockTabActivity" android:label="MockTabActivity" />
+
+        <activity android:name="android.app.cts.AppStubActivity" android:label="AppStubActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.app.cts.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" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.app.cts.ActivityManagerStubFooActivity"
+            android:label="ActivityManagerStubFooActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.app.cts.ActivityManagerRecentOneActivity"
+            android:label="ActivityManagerRecentOneActivity"
+            android:allowTaskReparenting="true"
+            android:taskAffinity="android.app.cts.recentOne">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.app.cts.ActivityManagerRecentTwoActivity"
+            android:label="ActivityManagerRecentTwoActivity"
+            android:allowTaskReparenting="true"
+            android:taskAffinity="android.app.cts.recentTwo">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.app.cts.ActivityManagerStubCrashActivity"
+            android:label="ActivityManagerStubCrashActivity"
+            android:multiprocess="true"
+            android:process=":ActivityManagerStubCrashActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+            </intent-filter>
+        </activity>
+
+        <service android:name="android.app.cts.StubRemoteService"
+            android:process=":remote">
+            <intent-filter>
+                <action
+                    android:name="android.app.cts.ISecondary" />
+                <action
+                    android:name="android.app.REMOTESERVICE" />
+            </intent-filter>
+        </service>
+
+        <activity android:name="android.app.ActivityGroup"
+            android:label="ActivityGroup" />
+
+        <activity android:name="android.app.cts.KeyguardManagerActivity"
+            android:label="KeyguardManagerActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <service android:name="android.app.cts.IntentServiceStub"/>
+
+        <activity android:name="android.app.cts.LaunchpadActivity"
+                  android:configChanges="keyboardHidden|orientation|screenSize"
+                  android:multiprocess="true">
+        </activity>
+
+        <activity android:name="android.app.cts.ActivityManagerMemoryClassLaunchActivity" />
+
+        <activity android:name="android.app.cts.ActivityManagerMemoryClassTestActivity"
+                android:process=":memoryclass" />
+
+    </application>
+
+</manifest>
+
diff --git a/tests/assets/noiseandchirps b/tests/app/assets/noiseandchirps
similarity index 100%
rename from tests/assets/noiseandchirps
rename to tests/app/assets/noiseandchirps
Binary files differ
diff --git a/tests/assets/noiseandchirps.mp3 b/tests/app/assets/noiseandchirps.mp3
similarity index 100%
rename from tests/assets/noiseandchirps.mp3
rename to tests/app/assets/noiseandchirps.mp3
Binary files differ
diff --git a/tests/assets/noiseandchirps.ogg b/tests/app/assets/noiseandchirps.ogg
similarity index 100%
rename from tests/assets/noiseandchirps.ogg
rename to tests/app/assets/noiseandchirps.ogg
Binary files differ
diff --git a/tests/assets/noiseandchirps.wrong b/tests/app/assets/noiseandchirps.wrong
similarity index 100%
rename from tests/assets/noiseandchirps.wrong
rename to tests/app/assets/noiseandchirps.wrong
Binary files differ
diff --git a/tests/res/drawable/icon_black.jpg b/tests/app/res/drawable/icon_black.jpg
similarity index 100%
rename from tests/res/drawable/icon_black.jpg
rename to tests/app/res/drawable/icon_black.jpg
Binary files differ
diff --git a/tests/res/drawable/icon_blue.jpg b/tests/app/res/drawable/icon_blue.jpg
similarity index 100%
rename from tests/res/drawable/icon_blue.jpg
rename to tests/app/res/drawable/icon_blue.jpg
Binary files differ
diff --git a/tests/res/drawable/icon_green.jpg b/tests/app/res/drawable/icon_green.jpg
similarity index 100%
rename from tests/res/drawable/icon_green.jpg
rename to tests/app/res/drawable/icon_green.jpg
Binary files differ
diff --git a/tests/res/drawable/icon_red.jpg b/tests/app/res/drawable/icon_red.jpg
similarity index 100%
rename from tests/res/drawable/icon_red.jpg
rename to tests/app/res/drawable/icon_red.jpg
Binary files differ
diff --git a/tests/res/drawable/icon_yellow.jpg b/tests/app/res/drawable/icon_yellow.jpg
similarity index 100%
rename from tests/res/drawable/icon_yellow.jpg
rename to tests/app/res/drawable/icon_yellow.jpg
Binary files differ
diff --git a/tests/res/drawable/ninepatch_0.9.png b/tests/app/res/drawable/ninepatch_0.9.png
similarity index 100%
rename from tests/res/drawable/ninepatch_0.9.png
rename to tests/app/res/drawable/ninepatch_0.9.png
Binary files differ
diff --git a/tests/res/drawable/ninepatch_1.9.png b/tests/app/res/drawable/ninepatch_1.9.png
similarity index 100%
rename from tests/res/drawable/ninepatch_1.9.png
rename to tests/app/res/drawable/ninepatch_1.9.png
Binary files differ
diff --git a/tests/res/drawable/pass.jpg b/tests/app/res/drawable/pass.jpg
similarity index 100%
rename from tests/res/drawable/pass.jpg
rename to tests/app/res/drawable/pass.jpg
Binary files differ
diff --git a/tests/res/drawable/robot.png b/tests/app/res/drawable/robot.png
similarity index 100%
rename from tests/res/drawable/robot.png
rename to tests/app/res/drawable/robot.png
Binary files differ
diff --git a/tests/res/drawable/size_48x48.jpg b/tests/app/res/drawable/size_48x48.jpg
similarity index 100%
rename from tests/res/drawable/size_48x48.jpg
rename to tests/app/res/drawable/size_48x48.jpg
Binary files differ
diff --git a/tests/res/layout/alert_dialog_text_entry.xml b/tests/app/res/layout/alert_dialog_text_entry.xml
similarity index 100%
rename from tests/res/layout/alert_dialog_text_entry.xml
rename to tests/app/res/layout/alert_dialog_text_entry.xml
diff --git a/tests/res/layout/alert_dialog_text_entry_2.xml b/tests/app/res/layout/alert_dialog_text_entry_2.xml
similarity index 100%
rename from tests/res/layout/alert_dialog_text_entry_2.xml
rename to tests/app/res/layout/alert_dialog_text_entry_2.xml
diff --git a/tests/res/layout/alertdialog_custom_title.xml b/tests/app/res/layout/alertdialog_custom_title.xml
similarity index 100%
rename from tests/res/layout/alertdialog_custom_title.xml
rename to tests/app/res/layout/alertdialog_custom_title.xml
diff --git a/tests/res/layout/app_activity.xml b/tests/app/res/layout/app_activity.xml
similarity index 100%
rename from tests/res/layout/app_activity.xml
rename to tests/app/res/layout/app_activity.xml
diff --git a/tests/res/layout/checkbox_layout.xml b/tests/app/res/layout/checkbox_layout.xml
similarity index 100%
rename from tests/res/layout/checkbox_layout.xml
rename to tests/app/res/layout/checkbox_layout.xml
diff --git a/tests/app/res/layout/dialog_stub_layout.xml b/tests/app/res/layout/dialog_stub_layout.xml
new file mode 100644
index 0000000..c6eb10d
--- /dev/null
+++ b/tests/app/res/layout/dialog_stub_layout.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        >
+</LinearLayout>
diff --git a/tests/res/menu/browser.xml b/tests/app/res/menu/browser.xml
similarity index 100%
rename from tests/res/menu/browser.xml
rename to tests/app/res/menu/browser.xml
diff --git a/tests/res/values/arrays.xml b/tests/app/res/values/arrays.xml
similarity index 100%
rename from tests/res/values/arrays.xml
rename to tests/app/res/values/arrays.xml
diff --git a/tests/app/res/values/attrs.xml b/tests/app/res/values/attrs.xml
new file mode 100644
index 0000000..4c3d9db
--- /dev/null
+++ b/tests/app/res/values/attrs.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2008 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>
+    <declare-styleable name="Style1">
+        <attr name="Type1" format="integer">
+            <enum name="type" value="28" />
+            <enum name="data" value="0xff00ff00" />
+            <enum name="asset_cookie" value="0" />
+            <enum name="resource_id" value="0" />
+            <enum name="changing_config" value="0" />
+        </attr>
+        <attr name="Type2" format="integer">
+            <enum name="type" value="28" />
+            <enum name="data" value="0xff0000ff" />
+            <enum name="asset_cookie" value="0" />
+            <enum name="resource_id" value="0" />
+            <enum name="changing_config" value="0" />
+        </attr>
+    </declare-styleable>
+    <attr name="type1" format="boolean"/>
+    <attr name="type2" format="boolean"/>
+    <attr name="type3" format="color"/>
+    <attr name="type4" format="reference|color"/>
+    <attr name="type5" format="dimension"/>
+    <attr name="type6" format="dimension"/>
+    <attr name="type7" format="dimension"/>
+    <attr name="type8" format="reference"/>
+    <attr name="type9" format="float"/>
+    <attr name="type10" format="fraction"/>
+    <attr name="type11" format="integer"/>
+    <attr name="type12" format="integer"/>
+    <attr name="type13" format="reference|string"/>
+    <attr name="type14" format="string"/>
+    <attr name="type15" format="reference"/>
+    <attr name="type16" format="string"/>
+    <declare-styleable name="style1">
+        <attr name="type1"/>
+        <attr name="type2"/>
+        <attr name="type3"/>
+        <attr name="type4"/>
+        <attr name="type5"/>
+        <attr name="type6"/>
+        <attr name="type7"/>
+        <attr name="type8"/>
+        <attr name="type9"/>
+        <attr name="type10"/>
+        <attr name="type11"/>
+        <attr name="type12"/>
+        <attr name="type13"/>
+        <attr name="type14"/>
+        <attr name="type15"/>
+        <attr name="type16"/>
+    </declare-styleable>
+    <attr name="testEnum">
+        <enum name="val1" value="1" />
+        <enum name="val2" value="2" />
+        <enum name="val10" value="10" />
+    </attr>
+    <attr name="testFlags">
+        <flag name="bit1" value="0x1" />
+        <flag name="bit2" value="0x2" />
+        <flag name="bit31" value="0x40000000" />
+    </attr>
+    <attr name="testString" format="string" />
+    <declare-styleable name="EnumStyle">
+        <attr name="testEnum" />
+    </declare-styleable>
+    <declare-styleable name="FlagStyle">
+        <attr name="testFlags" />
+    </declare-styleable>
+    <declare-styleable name="TestConfig">
+        <attr name="testString" />
+    </declare-styleable>
+    <!-- Size of text. Recommended dimension type for text is "sp" for scaled-pixels (example: 15sp).
+         Supported values include the following:<p/>
+    <ul>
+        <li><b>px</b> Pixels</li>
+        <li><b>sp</b> Scaled pixels (scaled to relative pixel size on screen). See {@link android.util.DisplayMetrics} for more information.</li>
+        <li><b>pt</b> Points</li>
+        <li><b>dip</b> Device independent pixels. See {@link android.util.DisplayMetrics} for more information.</li>
+    </ul>
+    -->
+    <attr name="textSize" format="dimension" />
+    <attr name="typeface">
+        <enum name="normal" value="0" />
+        <enum name="sans" value="1" />
+        <enum name="serif" value="2" />
+        <enum name="monospace" value="3" />
+    </attr>
+    <!-- Default text typeface style. -->
+    <attr name="textStyle">
+        <flag name="normal" value="0" />
+        <flag name="bold" value="1" />
+        <flag name="italic" value="2" />
+    </attr>
+    <!-- Color of text (usually same as colorForeground). -->
+    <attr name="textColor" format="reference|color" />
+    <!-- Color of highlighted text. -->
+    <attr name="textColorHighlight" format="reference|color" />
+    <!-- Color of hint text (displayed when the field is empty). -->
+    <attr name="textColorHint" format="reference|color" />
+    <!-- Color of link text (URLs). -->
+    <attr name="textColorLink" format="reference|color" />
+    <declare-styleable name="TextAppearance">
+        <attr name="textColor"/>
+        <attr name="textSize"/>
+        <attr name="textStyle"/>
+        <attr name="typeface"/>
+        <attr name="textColorHighlight"/>
+        <attr name="textColorHint"/>
+        <attr name="textColorLink"/>
+    </declare-styleable>
+    <!-- Integer used to uniquely identify theme overrides. -->
+    <attr name="themeType" format="integer"/>
+    <!-- Theme reference used to override parent theme. -->
+    <attr name="themeOverrideAttr" format="reference"/>
+
+    <!-- Drawable theming attributes -->
+    <attr name="themeBoolean" />
+    <attr name="themeColor" />
+    <attr name="themeFloat" />
+    <attr name="themeInteger" />
+    <attr name="themeDimension" />
+    <attr name="themeDrawable" />
+    <attr name="themeBitmap" />
+    <attr name="themeNinePatch" />
+    <attr name="themeGravity" />
+    <attr name="themeTileMode" />
+    <attr name="themeAngle" />
+</resources>
diff --git a/tests/res/values/colors.xml b/tests/app/res/values/colors.xml
similarity index 100%
rename from tests/res/values/colors.xml
rename to tests/app/res/values/colors.xml
diff --git a/tests/app/res/values/strings.xml b/tests/app/res/values/strings.xml
new file mode 100644
index 0000000..c167278
--- /dev/null
+++ b/tests/app/res/values/strings.xml
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="permlab_testGranted">Test Granted</string>
+    <string name="permdesc_testGranted">Used for running CTS tests, for testing operations
+        where we have the permission.</string>
+    <string name="permlab_testDynamic">Test Dynamic</string>
+    <string name="permdesc_testDynamic">Used for running CTS tests, for testing adding
+        dynamic permissions.</string>
+    <string name="permlab_testDenied">Test Denied</string>
+    <string name="permdesc_testDenied">Used for running CTS tests, for testing operations
+        where we do not have the permission.</string>
+    <string name="explain">1. click start. \n2. if above image shaked, then press pass button,
+         else press failed button.</string>
+    <string name="text_view_hello">Hello! Text view!</string>
+    <string name="text_view_hello_two_lines">Hello! \nText view!</string>
+    <string name="text_view_simple_hint">This is a hint.</string>
+    <string name="text_view_hint">This is a string for testing hint of textview.</string>
+    <string name="activity_forwarding">App/Forwarding</string>
+    <string name="forwarding">$$$</string>
+    <string name="go">Go</string>
+    <string name="back">Back</string>
+    <string name="forward_target">
+        Press back button and notice we don\'t see the previous activity.
+    </string>
+    <string name="edit_text">testing</string>
+    <string name="text">DialogTest</string>
+    <string name="text_country">Country</string>
+    <string name="text_name">Name</string>
+    <string name="hello_world">Hello, World!</string>
+    <string name="hello_android">Hello, Android!</string>
+    <string name="alert_dialog_username">Name:</string>
+    <string name="alert_dialog_password">Password:</string>
+    <string name="alert_dialog_positive">Positive</string>
+    <string name="alert_dialog_negative">Negative</string>
+    <string name="alert_dialog_neutral">Neutral</string>
+    <string name="notify">Notify </string>
+    <string name="tabs_1">testing</string>
+    <string name="table_layout_first">first</string>
+    <string name="table_layout_second">second</string>
+    <string name="table_layout_third">third</string>
+    <string name="table_layout_long">Very long to make the string out of the screen</string>
+    <string name="chronometer_text">Test Chronometer</string>
+    <string name="am">AM</string>
+    <string name="pm">PM</string>
+    <string name="viewgroup_test">ViewGroup test</string>
+    <string name="viewanimator_test">ViewAnimator test</string>
+    <string name="id_ok">OK</string>
+    <string name="id_cancel">Cancel</string>
+    <string name="context_test_string1">This is %s string.</string>
+    <string name="context_test_string2">This is test string.</string>
+    <string name="animationutils_test_instructions">Choose different animations</string>
+    <string name="animationutils_test_alpha">Alpha animation</string>
+    <string name="animationutils_test_scale">Scale animation</string>
+    <string name="animationutils_test_rotate">Rotate animation</string>
+    <string name="animationutils_test_translate">Translate animation</string>
+    <string name="animationutils_test_set">Animation set</string>
+    <string name="animationutils_test_layout">Layout animation</string>
+    <string name="animationutils_test_gridlayout">Grid layout animation</string>
+    <string name="twolinelistitem_test_text1">text1</string>
+    <string name="twolinelistitem_test_text2">text2</string>
+    <string name="metadata_text">metadata text</string>
+    <string name="horizontal_text_1">horizontal 1</string>
+    <string name="horizontal_text_2">horizontal 2</string>
+    <string name="horizontal_text_3">horizontal 3</string>
+    <string name="vertical_text_1">vertical 1</string>
+    <string name="vertical_text_2">vertical 2</string>
+    <string name="vertical_text_3">vertical 3</string>
+    <string name="reference">here</string>
+    <string name="coerceIntegerToString">100</string>
+    <string name="coerceBooleanToString">true</string>
+    <string name="coerceColorToString">#fff</string>
+    <string name="coerceFloatToString">100.0</string>
+    <string name="coerceDimensionToString">100px</string>
+    <string name="coerceFractionToString">100<xliff:g id="percent">%</xliff:g></string>
+    <string name="formattedStringNone">Format[]</string>
+    <string name="formattedStringOne">Format[<xliff:g id="format">%d</xliff:g>]</string>
+    <string name="formattedStringTwo">Format[<xliff:g id="format">%3$d,%2$s</xliff:g>]</string>
+    <string name="checkboxpref_key">checkboxpref_key</string>
+   <string name="checkboxpref_title">title of preference</string>
+   <string name="checkboxpref_summary">summary of preference</string>
+   <string name="checkboxpref_summary_on">summary on of preference</string>
+   <string name="checkboxpref_summary_off">summary off of preference</string>
+   <string name="checkboxpref_depend">checkboxpref_depend</string>
+   <string name="checkboxpref_depend_title"> depend title of preference</string>
+   <string name="checkboxpref_depend_summary"> depend summary of preference</string>
+   <string name="edittextpref_key">edittextpref_key</string>
+   <string name="edittextpref_default_value">default value of preference</string>
+   <string name="edittextpref_title">title of edit text preference</string>
+   <string name="edittextpref_summary">summary of edit text preference</string>
+   <string name="edittextpref_dialog_title">dialog title of edit text preference</string>
+   <string name="edittextpref_text">text of  edit text preference</string>
+   <string name="listpref_key">listpref_key</string>
+   <string name="listpref_title">title of list preference</string>
+   <string name="listpref_summary">summary of list preference</string>
+   <string name="listpref_dialogtitle">dialog title of list preference</string>
+   <string name="easy">Easy</string>
+   <string name="medium">Medium</string>
+   <string name="hard">Hard</string>
+   <string name="footer_view">Footer view</string>
+   <string name="header_view">Header view</string>
+   <string name="dialogpref_title">title of dialog preference </string>
+   <string name="dialogpref_dialog_title">dialog title of dialog preference </string>
+   <string name="dialogpref_key">dialogpref_key</string>
+   <string name="dialogpref_default_value">default value of dialog preference</string>
+   <string name="dialogpref_summary">summary of dialog preference</string>
+   <string name="dialogpref_message">message of dialog preference</string>
+   <string name="dialogpref_sure">Sure</string>
+   <string name="dialogpref_cancel">Cancel</string>
+   <string name="pref_key">pref_key</string>
+   <string name="pref_title">title of preference</string>
+   <string name="pref_summary">summary of preference</string>
+   <string name="pref_depend_key">pref_depend_key</string>
+   <string name="pref_depend_title"> depend title of preference</string>
+   <string name="pref_depend_summary"> depend summary of preference</string>
+   <string name="android_intent_action_preference">android.intent.action.PREFERENCE</string>
+   <string name="def_pref_key">def_pref_key</string>
+   <string name="def_pref_title">default preference</string>
+   <string name="def_pref_summary">This is default preference of cts</string>
+   <string name="relative_view1">view 1</string>
+   <string name="relative_view2">view 2</string>
+   <string name="relative_view3">view 3</string>
+   <string name="relative_view4">view 4</string>
+   <string name="relative_view5">view 5</string>
+   <string name="relative_view6">view 6</string>
+   <string name="relative_view7">view 7</string>
+   <string name="relative_view8">view 8</string>
+   <string name="relative_view9">view 9</string>
+   <string name="relative_view10">view 10</string>
+   <string name="relative_view11">view 11</string>
+   <string name="relative_view12">view 12</string>
+   <string name="relative_view13">view 13</string>
+   <string name="country">Country:</string>
+   <string name="symbol">Symbol:</string>
+   <string name="country_warning">No such country registered</string>
+   <string name="version_cur">base</string>
+   <string name="version_old">base</string>
+   <string name="version_v3">base</string>
+   <string name="authenticator_label">Android CTS</string>
+   <string name="search_label">Android CTS</string>
+   <string name="tag1">tag 1</string>
+   <string name="tag2">tag 2</string>
+
+   <string name="button">Button</string>
+   <string name="holo_test">Holo Test</string>
+   <string name="holo_generator">Holo Generator</string>
+   <string name="holo_light_test">Holo Light Test</string>
+   <string name="holo_light_generator">Holo Light Generator</string>
+   <string name="reference_image">Reference Image: </string>
+   <string name="generated_image">Generated Image: </string>
+   <string name="themes_prompt">Select a Theme:</string>
+   <string name="sample_text">Sample text goes here. I wanted something creative and whimsical
+but then I just got bored...</string>
+    <string name="long_text">This is a really long string which exceeds the width of the view.
+New devices have a much larger screen which actually enables long strings to be displayed
+with no fading. I have made this string longer to fix this case. If you are correcting this
+text, I would love to see the kind of devices you guys now use! Guys, maybe some devices need longer string!
+I think so, so how about double this string, like copy and paste!
+This is a really long string which exceeds the width of the view.
+New devices have a much larger screen which actually enables long strings to be displayed
+with no fading. I have made this string longer to fix this case. If you are correcting this
+text, I would love to see the kind of devices you guys now use! Guys, maybe some devices need longer string!
+I think so, so how about double this string, like copy and paste! </string>
+    <string name="rectangle200">"M 0,0 l 200,0 l 0, 200 l -200, 0 z"</string>
+</resources>
diff --git a/tests/app/res/values/styles.xml b/tests/app/res/values/styles.xml
new file mode 100644
index 0000000..81925cc
--- /dev/null
+++ b/tests/app/res/values/styles.xml
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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 xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <style name="Whatever">
+        <item name="type1">true</item>
+        <item name="type2">false</item>
+        <item name="type3">#ff0000ff</item>
+        <item name="type4">#ff00ff00</item>
+        <item name="type5">0.75px</item>
+        <item name="type6">10px</item>
+        <item name="type7">18px</item>
+        <item name="type8">@drawable/pass</item>
+        <item name="type9">3.14</item>
+        <item name="type10">100%</item>
+        <item name="type11">365</item>
+        <item name="type12">86400</item>
+        <item name="type13">@string/hello_android</item>
+        <item name="type14">TypedArray Test!</item>
+        <item name="type15">@array/difficultyLevel</item>
+        <item name="type16">Typed Value!</item>
+    </style>
+
+    <style name="TextViewWithoutColorAndAppearance">
+        <item name="android:textSize">18sp</item>
+    </style>
+
+    <style name="TextViewWithColorButWithOutAppearance">
+        <item name="android:textColor">#ff0000ff</item>
+    </style>
+
+    <style name="TextViewWithColorAndAppearance">
+        <item name="android:textColor">#ff0000ff</item>
+        <item name="android:textAppearance">@style/TextAppearance.WithColor</item>
+    </style>
+
+    <style name="TextViewWithoutColorButWithAppearance">
+        <item name="android:textAppearance">@style/TextAppearance.WithColor</item>
+    </style>
+
+    <style name="TextAppearance" parent="android:TextAppearance">
+    </style>
+
+    <style name="TextAppearance.WithColor">
+        <item name="android:textColor">#ffff0000</item>
+    </style>
+
+    <style name="TextAppearance.All">
+        <item name="android:textColor">@drawable/black</item>
+        <item name="android:textSize">20px</item>
+        <item name="android:textStyle">bold</item>
+        <item name="android:textColorHint">@drawable/red</item>
+        <item name="android:textColorLink">@drawable/blue</item>
+        <item name="android:textColorHighlight">@drawable/yellow</item>
+    </style>
+
+    <style name="TextAppearance.Colors">
+        <item name="android:textColor">@drawable/black</item>
+        <item name="android:textColorHint">@drawable/blue</item>
+        <item name="android:textColorLink">@drawable/yellow</item>
+        <item name="android:textColorHighlight">@drawable/red</item>
+    </style>
+
+    <style name="TextAppearance.NotColors">
+        <item name="android:textSize">17px</item>
+        <item name="android:typeface">sans</item>
+        <item name="android:textStyle">normal</item>
+    </style>
+
+    <style name="TextAppearance.Style">
+        <item name="android:textStyle">normal</item>
+    </style>
+
+    <style name="TestEnum1">
+        <item name="testEnum">val1</item>
+    </style>
+
+    <style name="TestEnum2">
+        <item name="testEnum">val2</item>
+    </style>
+
+    <style name="TestEnum10">
+        <item name="testEnum">val10</item>
+    </style>
+
+    <style name="TestFlag1">
+        <item name="testFlags">bit1</item>
+    </style>
+
+    <style name="TestFlag2">
+        <item name="testFlags">bit2</item>
+    </style>
+
+    <style name="TestFlag31">
+        <item name="testFlags">bit31</item>
+    </style>
+
+    <style name="TestFlag1And2">
+        <item name="testFlags">bit1|bit2</item>
+    </style>
+
+    <style name="TestFlag1And2And31">
+        <item name="testFlags">bit1|bit2|bit31</item>
+    </style>
+
+    <style name="TestEnum1.EmptyInherit" />
+
+    <style name="Theme_AlertDialog">
+        <item name="android:textSize">18sp</item>
+    </style>
+
+    <style name="TestProgressBar">
+        <item name="android:indeterminateOnly">false</item>
+        <item name="android:progressDrawable">?android:drawable/progress_horizontal</item>
+        <item name="android:indeterminateDrawable">?android:drawable/progress_horizontal</item>
+        <item name="android:minHeight">20dip</item>
+        <item name="android:maxHeight">20dip</item>
+        <item name="android:focusable">true</item>
+    </style>
+
+    <style name="Test_Theme">
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:panelColorForeground">#ff000000</item>
+        <item name="android:panelColorBackground">#ffffffff</item>
+    </style>
+
+    <style name="Theme_OverrideOuter">
+        <item name="themeType">1</item>
+    </style>
+
+    <style name="Theme_OverrideInner">
+        <item name="themeType">2</item>
+        <item name="themeOverrideAttr">@style/Theme_OverrideAttr</item>
+    </style>
+
+    <style name="Theme_OverrideAttr">
+        <item name="themeType">3</item>
+    </style>
+
+    <style name="Theme_ThemedDrawableTest">
+        <item name="themeBoolean">true</item>
+        <item name="themeColor">@android:color/black</item>
+        <item name="themeFloat">1.0</item>
+        <item name="themeAngle">45.0</item>
+        <item name="themeInteger">1</item>
+        <item name="themeDimension">1px</item>
+        <item name="themeDrawable">@drawable/icon_black</item>
+        <item name="themeBitmap">@drawable/icon_black</item>
+        <item name="themeNinePatch">@drawable/ninepatch_0</item>
+        <item name="themeGravity">48</item>
+        <item name="themeTileMode">2</item>
+    </style>
+
+    <style name="Theme_NoSwipeDismiss">
+        <item name="android:windowSwipeToDismiss">false</item>
+    </style>
+
+</resources>
diff --git a/tests/app/res/xml/alias.xml b/tests/app/res/xml/alias.xml
new file mode 100644
index 0000000..321e536
--- /dev/null
+++ b/tests/app/res/xml/alias.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2008 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.
+ */
+-->
+
+<alias xmlns:android="http://schemas.android.com/apk/res/android">
+    <intent android:action="android.intent.action.MAIN"
+        android:targetPackage="com.android.cts.app.stub"
+        android:targetClass="android.app.cts.ChildActivity"
+        android:data="http://www.google.com/">
+    </intent>
+</alias>
+
diff --git a/tests/res/xml/intentfilter.xml b/tests/app/res/xml/intentfilter.xml
similarity index 100%
rename from tests/res/xml/intentfilter.xml
rename to tests/app/res/xml/intentfilter.xml
diff --git a/tests/res/xml/metadata.xml b/tests/app/res/xml/metadata.xml
similarity index 100%
rename from tests/res/xml/metadata.xml
rename to tests/app/res/xml/metadata.xml
diff --git a/tests/app/res/xml/searchable.xml b/tests/app/res/xml/searchable.xml
new file mode 100644
index 0000000..f09c917
--- /dev/null
+++ b/tests/app/res/xml/searchable.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<searchable xmlns:android="http://schemas.android.com/apk/res/android"
+    android:label="@string/search_label"
+/>
diff --git a/tests/tests/app/src/android/app/cts/ActionBarActivity.java b/tests/app/src/android/app/cts/ActionBarActivity.java
similarity index 100%
rename from tests/tests/app/src/android/app/cts/ActionBarActivity.java
rename to tests/app/src/android/app/cts/ActionBarActivity.java
diff --git a/tests/src/android/app/cts/ActivityManagerMemoryClassLaunchActivity.java b/tests/app/src/android/app/cts/ActivityManagerMemoryClassLaunchActivity.java
similarity index 100%
rename from tests/src/android/app/cts/ActivityManagerMemoryClassLaunchActivity.java
rename to tests/app/src/android/app/cts/ActivityManagerMemoryClassLaunchActivity.java
diff --git a/tests/src/android/app/cts/ActivityManagerMemoryClassTestActivity.java b/tests/app/src/android/app/cts/ActivityManagerMemoryClassTestActivity.java
similarity index 100%
rename from tests/src/android/app/cts/ActivityManagerMemoryClassTestActivity.java
rename to tests/app/src/android/app/cts/ActivityManagerMemoryClassTestActivity.java
diff --git a/tests/src/android/app/cts/ActivityManagerRecentOneActivity.java b/tests/app/src/android/app/cts/ActivityManagerRecentOneActivity.java
similarity index 100%
rename from tests/src/android/app/cts/ActivityManagerRecentOneActivity.java
rename to tests/app/src/android/app/cts/ActivityManagerRecentOneActivity.java
diff --git a/tests/src/android/app/cts/ActivityManagerRecentTwoActivity.java b/tests/app/src/android/app/cts/ActivityManagerRecentTwoActivity.java
similarity index 100%
rename from tests/src/android/app/cts/ActivityManagerRecentTwoActivity.java
rename to tests/app/src/android/app/cts/ActivityManagerRecentTwoActivity.java
diff --git a/tests/src/android/app/cts/ActivityManagerStubCrashActivity.java b/tests/app/src/android/app/cts/ActivityManagerStubCrashActivity.java
similarity index 100%
rename from tests/src/android/app/cts/ActivityManagerStubCrashActivity.java
rename to tests/app/src/android/app/cts/ActivityManagerStubCrashActivity.java
diff --git a/tests/src/android/app/cts/ActivityManagerStubFooActivity.java b/tests/app/src/android/app/cts/ActivityManagerStubFooActivity.java
similarity index 100%
rename from tests/src/android/app/cts/ActivityManagerStubFooActivity.java
rename to tests/app/src/android/app/cts/ActivityManagerStubFooActivity.java
diff --git a/tests/src/android/app/cts/ActivityTestsBase.java b/tests/app/src/android/app/cts/ActivityTestsBase.java
similarity index 100%
rename from tests/src/android/app/cts/ActivityTestsBase.java
rename to tests/app/src/android/app/cts/ActivityTestsBase.java
diff --git a/tests/src/android/app/cts/AliasActivityStub.java b/tests/app/src/android/app/cts/AliasActivityStub.java
similarity index 100%
rename from tests/src/android/app/cts/AliasActivityStub.java
rename to tests/app/src/android/app/cts/AliasActivityStub.java
diff --git a/tests/app/src/android/app/cts/AppStubActivity.java b/tests/app/src/android/app/cts/AppStubActivity.java
new file mode 100644
index 0000000..da5e55a
--- /dev/null
+++ b/tests/app/src/android/app/cts/AppStubActivity.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2008 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.app.cts;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.view.ContextMenu;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ContextMenu.ContextMenuInfo;
+
+import com.android.cts.app.stub.R;
+
+/**
+ * A minimal "Hello, World!" application.
+ */
+public class AppStubActivity extends Activity {
+    private Dialog mDialog;
+    public boolean mOnPrepareDialog;
+    public boolean mOnOptionsMenuClosedCalled;
+    public boolean mOnPrepareOptionsMenuCalled;
+    public boolean mOnOptionsItemSelectedCalled;
+    public boolean mOnCreateOptionsMenu;
+    public boolean mIndterminate = false;
+    public boolean mIndterminatevisibility = false;
+    public boolean mSecPro = false;
+    public boolean mOnContextItemSelectedCalled;
+    public boolean mOnCreateContextMenu;
+    public boolean mApplyResourceCalled;
+    public boolean mCreateContextMenuCalled;
+    public boolean mRequestWinFeatureRet = false;
+
+    public AppStubActivity() {
+
+    }
+
+    public void finalize() {
+        try {
+            super.finalize();
+        } catch (Throwable exception) {
+            System.err.print("exception!");
+        }
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState){
+        super.onCreate(savedInstanceState);
+        mRequestWinFeatureRet = requestWindowFeature(1);
+        setContentView(R.layout.app_activity);
+    }
+
+    public Dialog getDialogById(int id) {
+        return mDialog;
+    }
+
+    @Override
+    public Dialog onCreateDialog(int id) {
+        super.onCreateDialog(id);
+        mDialog = new Dialog(this);
+        return mDialog;
+    }
+
+    @Override
+    protected void onPrepareDialog(int id, Dialog dialog) {
+        super.onPrepareDialog(id, dialog);
+        mOnPrepareDialog = true;
+    }
+
+    @Override
+    public void onOptionsMenuClosed(Menu menu) {
+        super.onOptionsMenuClosed(menu);
+        mOnOptionsMenuClosedCalled = true;
+    }
+
+    @Override
+    public boolean onPrepareOptionsMenu(Menu menu) {
+        mOnPrepareOptionsMenuCalled = true;
+        return super.onPrepareOptionsMenu(menu);
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        mOnCreateOptionsMenu = true;
+        if(menu != null)
+            menu.add(0, 0, 0, "Fake Item");
+        return super.onCreateOptionsMenu(menu);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        mOnOptionsItemSelectedCalled = true;
+        return super.onOptionsItemSelected(item);
+    }
+
+    public boolean setProBarIndeterminate(boolean indeterminate){
+        mIndterminate = indeterminate;
+        super.setProgressBarIndeterminate(indeterminate);
+        return mIndterminate;
+    }
+
+    public boolean setProBarIndeterminateVisibility(boolean visible){
+        mIndterminatevisibility = visible;
+        super.setProgressBarIndeterminateVisibility(visible);
+        return mIndterminatevisibility;
+    }
+
+    public boolean setSecPro(int secPro){
+        mSecPro = true;
+        super.setSecondaryProgress(secPro);
+        return mSecPro;
+    }
+
+    @Override
+    public boolean onContextItemSelected(MenuItem item){
+        mOnContextItemSelectedCalled = true;
+        return super.onContextItemSelected(item);
+    }
+
+    @Override
+    public void onApplyThemeResource( Resources.Theme theme,
+                                      int resid,
+                                      boolean first){
+        super.onApplyThemeResource(theme,resid,first);
+        mApplyResourceCalled = true;
+    }
+
+    @Override
+    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
+        super.onCreateContextMenu(menu,v,menuInfo);
+        mCreateContextMenuCalled = true;
+    }
+}
+
diff --git a/tests/app/src/android/app/cts/CTSActivityTestCaseBase.java b/tests/app/src/android/app/cts/CTSActivityTestCaseBase.java
new file mode 100644
index 0000000..efe693a
--- /dev/null
+++ b/tests/app/src/android/app/cts/CTSActivityTestCaseBase.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2008 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.app.cts;
+
+import android.cts.util.CTSResult;
+import android.test.InstrumentationTestCase;
+
+public class CTSActivityTestCaseBase extends InstrumentationTestCase implements CTSResult {
+
+    private Sync mSync;
+    static class Sync {
+        public boolean mHasNotify;
+        public int mResult;
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mSync = new Sync();
+    }
+
+    public void setResult(int resultCode) {
+        synchronized (mSync) {
+            mSync.mHasNotify = true;
+            mSync.mResult = resultCode;
+            mSync.notify();
+        }
+    }
+
+    protected void waitForResult() throws InterruptedException {
+        synchronized (mSync) {
+            while (!mSync.mHasNotify) {
+                mSync.wait();
+            }
+            assertEquals(CTSResult.RESULT_OK, mSync.mResult);
+        }
+    }
+}
diff --git a/tests/src/android/app/cts/ChildActivity.java b/tests/app/src/android/app/cts/ChildActivity.java
similarity index 100%
rename from tests/src/android/app/cts/ChildActivity.java
rename to tests/app/src/android/app/cts/ChildActivity.java
diff --git a/tests/src/android/app/cts/ChildTabActivity.java b/tests/app/src/android/app/cts/ChildTabActivity.java
similarity index 100%
rename from tests/src/android/app/cts/ChildTabActivity.java
rename to tests/app/src/android/app/cts/ChildTabActivity.java
diff --git a/tests/src/android/app/cts/ClearTop.java b/tests/app/src/android/app/cts/ClearTop.java
similarity index 100%
rename from tests/src/android/app/cts/ClearTop.java
rename to tests/app/src/android/app/cts/ClearTop.java
diff --git a/tests/app/src/android/app/cts/DialogStubActivity.java b/tests/app/src/android/app/cts/DialogStubActivity.java
new file mode 100644
index 0000000..a773ae2
--- /dev/null
+++ b/tests/app/src/android/app/cts/DialogStubActivity.java
@@ -0,0 +1,424 @@
+/*
+ * Copyright (C) 2008 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.app.cts;
+
+import com.android.cts.app.stub.R;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.DatePickerDialog;
+import android.app.Dialog;
+import android.app.TimePickerDialog;
+import android.app.DatePickerDialog.OnDateSetListener;
+import android.app.TimePickerDialog.OnTimeSetListener;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.DialogInterface.OnCancelListener;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.DatePicker;
+import android.widget.TimePicker;
+
+/*
+ * Stub class for  Dialog, AlertDialog, DatePickerDialog, TimePickerDialog etc.
+ */
+public class DialogStubActivity extends Activity {
+    public static final int TEST_DIALOG_WITHOUT_THEME = 0;
+    public static final int TEST_DIALOG_WITH_THEME = 1;
+    public static final int TEST_ALERTDIALOG = 2;
+    public static final int TEST_CUSTOM_ALERTDIALOG = 3;
+    public static final int TEST_DATEPICKERDIALOG = 4;
+    public static final int TEST_DATEPICKERDIALOG_WITH_THEME = 5;
+    public static final int TEST_TIMEPICKERDIALOG = 6;
+    public static final int TEST_TIMEPICKERDIALOG_WITH_THEME = 7;
+    public static final int TEST_ONSTART_AND_ONSTOP = 8;
+    public static final int TEST_ALERTDIALOG_DEPRECATED = 9;
+    public static final int TEST_ALERTDIALOG_CALLBACK = 10;
+    public static final int TEST_CUSTOM_ALERTDIALOG_VIEW = 11;
+    public static final int TEST_ALERTDIALOG_DEPRECATED_WITH_MESSAGE = 12;
+    public static final int TEST_ALERTDIALOG_THEME = 13;
+    public static final int TEST_ALERTDIALOG_CANCELABLE = 14;
+    public static final int TEST_ALERTDIALOG_NOT_CANCELABLE = 15;
+    public static final int TEST_PROTECTED_CANCELABLE = 16;
+    public static final int TEST_PROTECTED_NOT_CANCELABLE = 17;
+
+    public static final int SPACING_LEFT = 10;
+    public static final int SPACING_TOP = 20;
+    public static final int SPACING_RIGHT = 30;
+    public static final int SPACING_BOTTOM = 40;
+    public static int buttonIndex;
+
+    public static final String DEFAULT_ALERTDIALOG_TITLE = "AlertDialog";
+    public static final String DEFAULT_ALERTDIALOG_MESSAGE = "AlertDialog message";
+    private static final String LOG_TAG = "DialogStubActivity";
+
+    public boolean isPositiveButtonClicked = false;
+    public boolean isNegativeButtonClicked = false;
+    public boolean isNeutralButtonClicked = false;
+    public boolean isCallBackCalled;
+    public boolean onCancelCalled;
+    public boolean onKeyDownCalled;
+    public boolean onKeyUpCalled;
+    public boolean onCreateCalled;
+    public boolean onCancelListenerCalled;
+    public boolean onClickCalled;
+    public static boolean onDateChangedCalled;
+    public static boolean onRestoreInstanceStateCalled;
+    public boolean onSaveInstanceStateCalled;
+    public int updatedYear;
+    public int updatedMonth;
+    public int updatedDay;
+
+    public final int INITIAL_YEAR = 2008;
+    public final int INITIAL_MONTH = 7;
+    public final int INITIAL_DAY_OF_MONTH = 27;
+    private final int INITIAL_HOUR = 10;
+    private final int INITIAL_MINUTE = 35;
+    private Dialog mDialog;
+    private AlertDialog mAlertDialog;
+    private OnDateSetListener mOnDateSetListener = new OnDateSetListener() {
+        public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
+            updatedYear = year;
+            updatedMonth = monthOfYear;
+            updatedDay = dayOfMonth;
+        }
+    };
+
+    @SuppressWarnings("deprecation")
+    @Override
+    protected Dialog onCreateDialog(int id) {
+        switch (id) {
+            case TEST_DIALOG_WITHOUT_THEME:
+                mDialog = new Dialog(this);
+                mDialog.setTitle("Hello, Dialog");
+                break;
+
+            case TEST_DIALOG_WITH_THEME:
+                mDialog = new Dialog(this, 1);
+                break;
+
+            case TEST_ALERTDIALOG:
+                mDialog = getAlertDialogInstance(false);
+                break;
+
+            case TEST_CUSTOM_ALERTDIALOG:
+                mDialog = getCustomAlertDialogInstance(false);
+                break;
+
+            case TEST_CUSTOM_ALERTDIALOG_VIEW:
+                mDialog = getCustomAlertDialogInstance(true);
+                break;
+
+            case TEST_DATEPICKERDIALOG:
+                mDialog = new MockDatePickerDialog(this, mOnDateSetListener, INITIAL_YEAR,
+                        INITIAL_MONTH, INITIAL_DAY_OF_MONTH);
+                break;
+
+            case TEST_DATEPICKERDIALOG_WITH_THEME:
+                mDialog = new MockDatePickerDialog(this,
+                        com.android.internal.R.style.Theme_Translucent, mOnDateSetListener,
+                        INITIAL_YEAR, INITIAL_MONTH, INITIAL_DAY_OF_MONTH);
+                break;
+
+            case TEST_TIMEPICKERDIALOG:
+                mDialog = new TimePickerDialog(this, new OnTimeSetListener() {
+                    public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
+                        isCallBackCalled = true;
+                    }
+                }, INITIAL_HOUR, INITIAL_MINUTE, true);
+                break;
+
+            case TEST_TIMEPICKERDIALOG_WITH_THEME:
+                mDialog = new TimePickerDialog(this,
+                        com.android.internal.R.style.Theme_Translucent, null, INITIAL_HOUR,
+                        INITIAL_MINUTE, true);
+                break;
+
+            case TEST_ONSTART_AND_ONSTOP:
+                mDialog = new TestDialog(this);
+                Log.i(LOG_TAG, "mTestDialog:" + mDialog);
+                return mDialog;
+
+            case TEST_ALERTDIALOG_DEPRECATED:
+                mDialog = getAlertDialogInstance(true);
+                break;
+
+            case TEST_ALERTDIALOG_DEPRECATED_WITH_MESSAGE:
+                final Handler handler = new Handler() {
+                    @Override
+                    public void handleMessage(Message msg) {
+                        buttonIndex = msg.what;
+                        super.handleMessage(msg);
+                    }
+                };
+                final Message positiveMessage = Message.obtain();
+                positiveMessage.setTarget(handler);
+                positiveMessage.what = DialogInterface.BUTTON_POSITIVE;
+
+                final Message negativeMessage = Message.obtain();
+                negativeMessage.setTarget(handler);
+                negativeMessage.what = DialogInterface.BUTTON_NEGATIVE;
+
+                final Message neutralMessage = Message.obtain();
+                neutralMessage.setTarget(handler);
+                neutralMessage.what = DialogInterface.BUTTON_NEUTRAL;
+                mAlertDialog = getAlertDialogInstance(false);
+                mAlertDialog.setButton(getString(R.string.alert_dialog_positive), positiveMessage);
+                mAlertDialog.setButton2(getString(R.string.alert_dialog_negative), negativeMessage);
+                mAlertDialog.setButton3(getString(R.string.alert_dialog_neutral), neutralMessage);
+                mDialog = mAlertDialog;
+                break;
+
+            case TEST_ALERTDIALOG_CALLBACK:
+                mDialog = new MockAlertDialog(this);
+                break;
+            case TEST_ALERTDIALOG_THEME:
+                mDialog = new MockAlertDialog(this, R.style.Theme_AlertDialog);
+                break;
+            case TEST_ALERTDIALOG_CANCELABLE:
+                mDialog = getAlertDialogCancelablInstance(true);
+                break;
+            case TEST_ALERTDIALOG_NOT_CANCELABLE:
+                mDialog = getAlertDialogCancelablInstance(false);
+                break;
+            case TEST_PROTECTED_CANCELABLE:
+                mDialog = new TestDialog(this, true, new OnCancelListener() {
+                    public void onCancel(DialogInterface dialog) {
+                        onCancelListenerCalled = true;
+                    }
+                });
+                break;
+            case TEST_PROTECTED_NOT_CANCELABLE:
+                mDialog = new TestDialog(this, false, new OnCancelListener() {
+                    public void onCancel(DialogInterface dialog) {
+                        onCancelListenerCalled = true;
+                    }
+                });
+                break;
+            default:
+                break;
+        }
+
+        Log.i(LOG_TAG, "mDialog:" + mDialog);
+        return mDialog;
+    }
+
+    private AlertDialog getAlertDialogCancelablInstance(boolean cancelable) {
+        OnCancelListener cancelListener = new OnCancelListener() {
+            public void onCancel(DialogInterface dialog) {
+                onCancelCalled = true;
+            }
+        };
+        return new MockAlertDialog(this, cancelable, cancelListener);
+    }
+
+    @SuppressWarnings("deprecation")
+    private AlertDialog getAlertDialogInstance(boolean deprecated) {
+        mAlertDialog = new AlertDialog.Builder(DialogStubActivity.this).create();
+        mAlertDialog.setIcon(com.android.cts.app.stub.R.drawable.pass);
+        mAlertDialog.setTitle(DEFAULT_ALERTDIALOG_TITLE);
+        mAlertDialog.setMessage(DEFAULT_ALERTDIALOG_MESSAGE);
+        mAlertDialog.setInverseBackgroundForced(true);
+        final DialogInterface.OnClickListener positiveListener = new MockOnClickListener(
+                DialogInterface.BUTTON_POSITIVE);
+        final DialogInterface.OnClickListener netativeListener = new MockOnClickListener(
+                DialogInterface.BUTTON_NEGATIVE);
+        final DialogInterface.OnClickListener neutralListener = new MockOnClickListener(
+                DialogInterface.BUTTON_NEUTRAL);
+
+        if (deprecated) {
+            mAlertDialog.setButton(getString(R.string.alert_dialog_positive), positiveListener);
+            mAlertDialog.setButton2(getString(R.string.alert_dialog_negative), netativeListener);
+            mAlertDialog.setButton3(getString(R.string.alert_dialog_neutral), neutralListener);
+        } else {
+            mAlertDialog.setButton(DialogInterface.BUTTON_POSITIVE,
+                    getString(R.string.alert_dialog_positive), positiveListener);
+            mAlertDialog.setButton(DialogInterface.BUTTON_NEGATIVE,
+                    getString(R.string.alert_dialog_negative), netativeListener);
+            mAlertDialog.setButton(DialogInterface.BUTTON_NEUTRAL,
+                    getString(R.string.alert_dialog_neutral), neutralListener);
+        }
+        return mAlertDialog;
+
+    }
+
+    private AlertDialog getCustomAlertDialogInstance(boolean withSpacing) {
+        final LayoutInflater inflate = getLayoutInflater();
+        final View customTitleViewCustom = inflate.inflate(R.layout.alertdialog_custom_title, null);
+        final View textEntryView = inflate.inflate(R.layout.alert_dialog_text_entry_2, null);
+        mAlertDialog = new AlertDialog.Builder(DialogStubActivity.this).create();
+        mAlertDialog.setCustomTitle(customTitleViewCustom);
+        mAlertDialog.setMessage(DEFAULT_ALERTDIALOG_MESSAGE);
+        if (withSpacing) {
+            mAlertDialog.setView(textEntryView, SPACING_LEFT, SPACING_TOP, SPACING_RIGHT,
+                    SPACING_BOTTOM);
+        } else {
+            mAlertDialog.setView(textEntryView);
+        }
+
+        return mAlertDialog;
+
+    }
+
+    public Dialog getDialog() {
+        return mDialog;
+    }
+
+    public String getDialogTitle() {
+        return (String) mDialog.getWindow().getAttributes().getTitle();
+    }
+
+    private static final String TEST_DIALOG_NUMBER_EXTRA = "testDialogNumber";
+
+    public static <T extends Activity> T startDialogActivity(
+            ActivityInstrumentationTestCase2<T> testCase, int dialogNumber) {
+        Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.putExtra(TEST_DIALOG_NUMBER_EXTRA, dialogNumber);
+        testCase.setActivityIntent(intent);
+        return testCase.getActivity();
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.dialog_stub_layout);
+
+        Intent intent = getIntent();
+        int dialogNum = intent.getIntExtra(TEST_DIALOG_NUMBER_EXTRA, -1);
+        if (dialogNum != -1) {
+            showDialog(dialogNum);
+        }
+    }
+
+    public void setUpTitle(final String title) {
+        runOnUiThread(new Runnable() {
+            public void run() {
+                getDialog().setTitle(title);
+            }
+        });
+    }
+
+    public void setUpTitle(final int id) {
+        runOnUiThread(new Runnable() {
+            public void run() {
+                getDialog().setTitle(id);
+            }
+        });
+    }
+
+    class MockAlertDialog extends AlertDialog {
+        public MockAlertDialog(Context context) {
+            super(context);
+        }
+
+        public MockAlertDialog(Context context, int theme) {
+            super(context, theme);
+        }
+
+        public MockAlertDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
+            super(context, cancelable, cancelListener);
+        }
+
+        @Override
+        public boolean onKeyDown(int keyCode, KeyEvent event) {
+            onKeyDownCalled = true;
+            return super.onKeyDown(keyCode, event);
+        }
+
+        @Override
+        public boolean onKeyUp(int keyCode, KeyEvent event) {
+            onKeyUpCalled = true;
+            return super.onKeyUp(keyCode, event);
+        }
+
+        @Override
+        protected void onCreate(Bundle savedInstanceState) {
+            onCreateCalled = true;
+            super.onCreate(savedInstanceState);
+        }
+
+    }
+
+    class MockOnClickListener implements DialogInterface.OnClickListener {
+        private final int mId;
+
+        public MockOnClickListener(final int buttonId) {
+            mId = buttonId;
+        }
+
+        public void onClick(DialogInterface dialog, int which) {
+            switch (mId) {
+                case DialogInterface.BUTTON_POSITIVE:
+                    isPositiveButtonClicked = true;
+                    break;
+                case DialogInterface.BUTTON_NEGATIVE:
+                    isNegativeButtonClicked = true;
+                    break;
+                case DialogInterface.BUTTON_NEUTRAL:
+                    isNeutralButtonClicked = true;
+                    break;
+                default:
+                    break;
+            }
+        }
+    }
+
+    class MockDatePickerDialog extends DatePickerDialog {
+        public MockDatePickerDialog(Context context, OnDateSetListener callBack, int year,
+                int monthOfYear, int dayOfMonth) {
+            super(context, callBack, year, monthOfYear, dayOfMonth);
+        }
+
+        public MockDatePickerDialog(Context context, int theme, OnDateSetListener callBack,
+                int year, int monthOfYear, int dayOfMonth) {
+            super(context, theme, callBack, year, monthOfYear, dayOfMonth);
+        }
+
+        @Override
+        public void onClick(DialogInterface dialog, int which) {
+            onClickCalled = true;
+            super.onClick(dialog, which);
+        }
+
+        @Override
+        public void onDateChanged(DatePicker view, int year, int month, int day) {
+            onDateChangedCalled = true;
+            super.onDateChanged(view, year, month, day);
+        }
+
+        @Override
+        public void onRestoreInstanceState(Bundle savedInstanceState) {
+            onRestoreInstanceStateCalled = true;
+            super.onRestoreInstanceState(savedInstanceState);
+        }
+
+        @Override
+        public Bundle onSaveInstanceState() {
+            onSaveInstanceStateCalled = true;
+            return super.onSaveInstanceState();
+        }
+
+    }
+}
diff --git a/tests/src/android/app/cts/ExpandableListTestActivity.java b/tests/app/src/android/app/cts/ExpandableListTestActivity.java
similarity index 100%
rename from tests/src/android/app/cts/ExpandableListTestActivity.java
rename to tests/app/src/android/app/cts/ExpandableListTestActivity.java
diff --git a/tests/src/android/app/cts/ISecondary.aidl b/tests/app/src/android/app/cts/ISecondary.aidl
similarity index 100%
rename from tests/src/android/app/cts/ISecondary.aidl
rename to tests/app/src/android/app/cts/ISecondary.aidl
diff --git a/tests/app/src/android/app/cts/InstrumentationTestActivity.java b/tests/app/src/android/app/cts/InstrumentationTestActivity.java
new file mode 100644
index 0000000..bec721e
--- /dev/null
+++ b/tests/app/src/android/app/cts/InstrumentationTestActivity.java
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) 2009 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.app.cts;
+
+import java.util.ArrayList;
+import java.util.List;
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.TextView;
+import com.android.cts.app.stub.R;
+
+public class InstrumentationTestActivity extends Activity {
+
+    private boolean mOnCreateCalled;
+    private boolean mOnDestroyCalled ;
+    private boolean mOnNewIntentCalled;
+    private boolean mOnPauseCalled;
+    private boolean mOnPostCreate;
+    private boolean mOnRestart;
+    private boolean mOnRestoreInstanceState;
+    private boolean mOnResume;
+    private boolean mOnSaveInstanceState;
+    private boolean mOnStart;
+    private boolean mOnStop;
+    private boolean mOnMenuOpened;
+    private boolean mOnLeave;
+    private int mMenuID;
+    private boolean mOnTouchEventCalled;
+    private int mKeyDownCode;
+    private int mKeyUpCode;
+    private MotionEvent mMotionEvent;
+    private Bundle mBundle;
+    private MockTextView mTextView;
+    private List<KeyEvent> mKeyDownList = new ArrayList<KeyEvent>();
+    private List<KeyEvent> mKeyUpList = new ArrayList<KeyEvent>();
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mTextView = new MockTextView(this);
+        setContentView(mTextView);
+        mOnCreateCalled = true;
+    }
+
+    class MockTextView extends TextView {
+
+        public MockTextView(Context context) {
+            super(context);
+        }
+
+        @Override
+        public boolean onTouchEvent(MotionEvent event) {
+            return super.onTouchEvent(event);
+        }
+
+        @Override
+        public boolean onTrackballEvent(MotionEvent event) {
+            return super.onTrackballEvent(event);
+        }
+
+        @Override
+        public void getLocationOnScreen(int[] location) {
+            super.getLocationOnScreen(location);
+            location[0] = location[1] = 10;
+        }
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        mOnDestroyCalled = true;
+    }
+
+    @Override
+    protected void onNewIntent(Intent intent) {
+        super.onNewIntent(intent);
+        mOnNewIntentCalled = true;
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        mOnPauseCalled = true;
+    }
+
+    @Override
+    protected void onPostCreate(Bundle savedInstanceState) {
+        super.onPostCreate(savedInstanceState);
+        mOnPostCreate = true;
+    }
+
+    @Override
+    protected void onRestart() {
+        super.onRestart();
+        mOnRestart = true;
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Bundle savedInstanceState) {
+        super.onRestoreInstanceState(savedInstanceState);
+        mOnRestoreInstanceState = true;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        mOnTouchEventCalled = true;
+        mMotionEvent = event;
+        return super.onTouchEvent(event);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        mOnResume = true;
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        mOnSaveInstanceState = true;
+        mBundle = outState;
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+        mOnStart = true;
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+        mOnStop = true;
+    }
+
+    @Override
+    protected void onUserLeaveHint() {
+        super.onUserLeaveHint();
+        mOnLeave = true;
+    }
+
+    @Override
+    public boolean onMenuOpened(int featureId, Menu menu) {
+        mOnMenuOpened = true;
+        return super.onMenuOpened(featureId, menu);
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        super.onCreateOptionsMenu(menu);
+        MenuInflater inflater = getMenuInflater();
+        inflater.inflate(R.menu.browser, menu);
+
+        menu.add("title");
+        mOnMenuOpened = true;
+        return true;
+    }
+
+    @Override
+    public boolean onCreatePanelMenu(int featureId, Menu menu) {
+        return super.onCreatePanelMenu(featureId, menu);
+    }
+
+    @Override
+    public boolean onMenuItemSelected(int featureId, MenuItem item) {
+        mMenuID = item.getItemId();
+        return super.onMenuItemSelected(featureId, item);
+    }
+
+    @Override
+    public void openContextMenu(View view) {
+        super.openContextMenu(view);
+    }
+
+    @Override
+    public void openOptionsMenu() {
+        super.openOptionsMenu();
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        return super.onOptionsItemSelected(item);
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        mKeyDownList.add(event);
+        mKeyDownCode = keyCode;
+        return super.onKeyDown(keyCode, event);
+    }
+
+    @Override
+    public boolean onTrackballEvent(MotionEvent event) {
+        mMotionEvent = event;
+        return super.onTrackballEvent(event);
+    }
+
+    @Override
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
+        mKeyUpList.add(event);
+        mKeyUpCode = keyCode;
+        return super.onKeyUp(keyCode, event);
+    }
+
+    public boolean isOnCreateCalled() {
+        return mOnCreateCalled;
+    }
+
+    public void setOnCreateCalled(boolean onCreateCalled) {
+        mOnCreateCalled = onCreateCalled;
+    }
+
+    public boolean isOnDestroyCalled() {
+        return mOnDestroyCalled;
+    }
+
+    public void setOnDestroyCalled(boolean onDestroyCalled) {
+        mOnDestroyCalled = onDestroyCalled;
+    }
+
+    public boolean isOnNewIntentCalled() {
+        return mOnNewIntentCalled;
+    }
+
+    public void setOnNewIntentCalled(boolean onNewIntentCalled) {
+        mOnNewIntentCalled = onNewIntentCalled;
+    }
+
+    public boolean isOnPauseCalled() {
+        return mOnPauseCalled;
+    }
+
+    public void setOnPauseCalled(boolean onPauseCalled) {
+        mOnPauseCalled = onPauseCalled;
+    }
+
+    public boolean isOnPostCreate() {
+        return mOnPostCreate;
+    }
+
+    public void setOnPostCreate(boolean onPostCreate) {
+        mOnPostCreate = onPostCreate;
+    }
+
+    public boolean isOnRestart() {
+        return mOnRestart;
+    }
+
+    public void setOnRestart(boolean onRestart) {
+        mOnRestart = onRestart;
+    }
+
+    public boolean isOnRestoreInstanceState() {
+        return mOnRestoreInstanceState;
+    }
+
+    public void setOnRestoreInstanceState(boolean onRestoreInstanceState) {
+        mOnRestoreInstanceState = onRestoreInstanceState;
+    }
+
+    public boolean isOnResume() {
+        return mOnResume;
+    }
+
+    public void setOnResume(boolean onResume) {
+        mOnResume = onResume;
+    }
+
+    public boolean isOnSaveInstanceState() {
+        return mOnSaveInstanceState;
+    }
+
+    public void setOnSaveInstanceState(boolean onSaveInstanceState) {
+        mOnSaveInstanceState = onSaveInstanceState;
+    }
+
+    public boolean isOnStart() {
+        return mOnStart;
+    }
+
+    public void setOnStart(boolean onStart) {
+        mOnStart = onStart;
+    }
+
+    public boolean isOnStop() {
+        return mOnStop;
+    }
+
+    public boolean isOnLeave() {
+        return mOnLeave;
+    }
+
+    public void setOnStop(boolean onStop) {
+        mOnStop = onStop;
+    }
+
+    public boolean isMOnMenuOpened() {
+        return mOnMenuOpened;
+    }
+
+    public void setOnMenuOpened(boolean onMenuOpened) {
+        mOnMenuOpened = onMenuOpened;
+    }
+
+    public int getMenuID() {
+        return mMenuID;
+    }
+
+    public void setMenuID(int menuID) {
+        mMenuID = menuID;
+    }
+
+    public MotionEvent getMotionEvent() {
+        return mMotionEvent;
+    }
+
+    public Bundle getBundle() {
+        return mBundle;
+    }
+
+    public boolean isOnTouchEventCalled() {
+        return mOnTouchEventCalled;
+    }
+
+    public void setOnTouchEventCalled(boolean onTouchEventCalled) {
+        mOnTouchEventCalled = onTouchEventCalled;
+    }
+
+    public int getKeyUpCode() {
+        return mKeyUpCode;
+    }
+
+    public int getKeyDownCode() {
+        return mKeyDownCode;
+    }
+
+    public List<KeyEvent> getKeyUpList() {
+        return mKeyUpList;
+    }
+
+    public List<KeyEvent> getKeyDownList() {
+        return mKeyDownList;
+    }
+}
diff --git a/tests/src/android/app/cts/IntentServiceStub.java b/tests/app/src/android/app/cts/IntentServiceStub.java
similarity index 100%
rename from tests/src/android/app/cts/IntentServiceStub.java
rename to tests/app/src/android/app/cts/IntentServiceStub.java
diff --git a/tests/src/android/app/cts/KeyguardManagerActivity.java b/tests/app/src/android/app/cts/KeyguardManagerActivity.java
similarity index 100%
rename from tests/src/android/app/cts/KeyguardManagerActivity.java
rename to tests/app/src/android/app/cts/KeyguardManagerActivity.java
diff --git a/tests/src/android/app/cts/LauncherActivityStub.java b/tests/app/src/android/app/cts/LauncherActivityStub.java
similarity index 100%
rename from tests/src/android/app/cts/LauncherActivityStub.java
rename to tests/app/src/android/app/cts/LauncherActivityStub.java
diff --git a/tests/src/android/app/cts/LaunchpadActivity.java b/tests/app/src/android/app/cts/LaunchpadActivity.java
similarity index 100%
rename from tests/src/android/app/cts/LaunchpadActivity.java
rename to tests/app/src/android/app/cts/LaunchpadActivity.java
diff --git a/tests/src/android/app/cts/LaunchpadTabActivity.java b/tests/app/src/android/app/cts/LaunchpadTabActivity.java
similarity index 100%
rename from tests/src/android/app/cts/LaunchpadTabActivity.java
rename to tests/app/src/android/app/cts/LaunchpadTabActivity.java
diff --git a/tests/src/android/app/cts/LocalActivity.java b/tests/app/src/android/app/cts/LocalActivity.java
similarity index 100%
rename from tests/src/android/app/cts/LocalActivity.java
rename to tests/app/src/android/app/cts/LocalActivity.java
diff --git a/tests/src/android/app/cts/LocalActivityManagerStubActivity.java b/tests/app/src/android/app/cts/LocalActivityManagerStubActivity.java
similarity index 100%
rename from tests/src/android/app/cts/LocalActivityManagerStubActivity.java
rename to tests/app/src/android/app/cts/LocalActivityManagerStubActivity.java
diff --git a/tests/app/src/android/app/cts/LocalActivityManagerTestHelper.java b/tests/app/src/android/app/cts/LocalActivityManagerTestHelper.java
new file mode 100644
index 0000000..70764e4
--- /dev/null
+++ b/tests/app/src/android/app/cts/LocalActivityManagerTestHelper.java
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2008 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.app.cts;
+
+
+import android.app.Activity;
+import android.app.ActivityGroup;
+import android.app.LocalActivityManager;
+import android.content.Intent;
+import android.cts.util.CTSResult;
+import android.os.Bundle;
+import android.view.Window;
+
+public class LocalActivityManagerTestHelper extends ActivityGroup {
+
+    public static final String ACTION_DISPATCH_RESUME = "dispatchResume";
+    public static final String ACTION_START_ACTIVITY = "startActivity";
+    public static final String ACTION_DISPATCH_CREATE = "dispatchCreate";
+    public static final String ACTION_DISPATCH_STOP = "dispatchStop";
+    public static final String ACTION_DISPATCH_PAUSE_TRUE = "dispatchPauseTrue";
+    public static final String ACTION_DISPATCH_PAUSE_FALSE = "dispatchPauseFalse";
+    public static final String ACTION_SAVE_INSTANCE_STATE = "saveInstanceState";
+    public static final String ACTION_DISPATCH_DESTROY = "dispatchDestroy";
+    public static final String ACTION_REMOVE_ALL_ACTIVITY = "removeAllActivities";
+
+    private String mCurrentAction;
+    private LocalActivityManager mLocalActivityManager;
+
+    private static CTSResult sResult;
+
+    public static void setResult(CTSResult cr) {
+        sResult = cr;
+    }
+
+    public LocalActivityManagerTestHelper() {
+        super();
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mCurrentAction = getIntent().getAction();
+        mLocalActivityManager = getLocalActivityManager();
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+    }
+
+    protected void onResume() {
+        super.onResume();
+        if (mCurrentAction.equals(ACTION_DISPATCH_RESUME)) {
+            testDispatchResume();
+        } else if (mCurrentAction.equals(ACTION_START_ACTIVITY)) {
+            testStartActivity();
+        } else if (mCurrentAction.equals(ACTION_DISPATCH_CREATE)) {
+            testDispatchCreate();
+        } else if (mCurrentAction.equals(ACTION_DISPATCH_STOP)) {
+            testDispatchStop();
+        } else if (mCurrentAction.equals(ACTION_DISPATCH_PAUSE_TRUE)) {
+            testDispatchPauseTrue();
+        } else if (mCurrentAction.equals(ACTION_DISPATCH_PAUSE_FALSE)) {
+            testDispatchPauseFalse();
+        } else if (mCurrentAction.equals(ACTION_SAVE_INSTANCE_STATE)) {
+            testSaveInstanceState();
+        } else if (mCurrentAction.equals(ACTION_DISPATCH_DESTROY)) {
+            testDispatchDestroy();
+        } else if (mCurrentAction.equals(ACTION_REMOVE_ALL_ACTIVITY)) {
+            testRemoveAllActivity();
+        }
+    }
+
+    private void testRemoveAllActivity() {
+        final String id = "id_remove_activity";
+        final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mLocalActivityManager.startActivity(id, intent);
+
+        Activity activity = mLocalActivityManager.getActivity(id);
+        if (activity == null) {
+            fail();
+            return;
+        }
+
+        if (!activity.getClass().getName().equals("android.app.cts."
+                    + "LocalActivityManagerStubActivity")) {
+            fail();
+            return;
+        }
+
+        mLocalActivityManager.removeAllActivities();
+        activity = mLocalActivityManager.getActivity(id);
+        if (activity != null) {
+            fail();
+            return;
+        }
+        pass();
+    }
+
+    private void testDispatchDestroy() {
+        final String id1 = "id_dispatch_destroy1";
+        final String id2 = "id_dispatch_destroy2";
+        final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mLocalActivityManager.startActivity(id1, intent);
+
+        LocalActivityManagerStubActivity.sIsOnDestroyCalled = false;
+        mLocalActivityManager.dispatchDestroy(false);
+        if (mLocalActivityManager.getCurrentActivity().isFinishing()){
+            fail();
+            return;
+        }
+
+        if (!LocalActivityManagerStubActivity.sIsOnDestroyCalled) {
+            fail();
+            return;
+        }
+
+        mLocalActivityManager.startActivity(id2, intent);
+        LocalActivityManagerStubActivity.sIsOnDestroyCalled = false;
+        mLocalActivityManager.dispatchDestroy(true);
+
+        if (!LocalActivityManagerStubActivity.sIsOnDestroyCalled) {
+            fail();
+            return;
+        }
+
+        if (!mLocalActivityManager.getCurrentActivity().isFinishing()){
+            fail();
+            return;
+        }
+        pass();
+    }
+
+    private void testSaveInstanceState() {
+        final String key = "_id1";
+        mLocalActivityManager.dispatchCreate(null);
+        final Bundle bundle = mLocalActivityManager.saveInstanceState();
+        if (bundle != null) {
+            fail();
+            return;
+        }
+
+        final String id = "id_dispatch_pause";
+        final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mLocalActivityManager.startActivity(id, intent);
+
+        final Bundle savedBundle = new Bundle();
+        final Bundle bb = new Bundle();
+        savedBundle.putBundle(key, bb);
+
+        mLocalActivityManager.dispatchCreate(savedBundle);
+        final Bundle returnedBundle = mLocalActivityManager.saveInstanceState();
+        if (returnedBundle.getBundle(key) == null ) {
+            fail();
+            return;
+        }
+        pass();
+    }
+
+    private void testDispatchPauseFalse() {
+        final String id = "id_dispatch_pause";
+        final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mLocalActivityManager.startActivity(id, intent);
+        LocalActivityManagerStubActivity.sIsOnPauseCalled = false;
+        mLocalActivityManager.dispatchPause(false);
+        if (!LocalActivityManagerStubActivity.sIsOnPauseCalled) {
+            fail();
+            return;
+        }
+        pass();
+    }
+
+    private void testDispatchPauseTrue() {
+        final String id = "id_dispatch_pause";
+        final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mLocalActivityManager.startActivity(id, intent);
+        LocalActivityManagerStubActivity.sIsOnPauseCalled = false;
+        mLocalActivityManager.dispatchPause(true);
+        if (!LocalActivityManagerStubActivity.sIsOnPauseCalled) {
+            fail();
+            return;
+        }
+        pass();
+    }
+
+    private void testDispatchStop() {
+        final String id = "id_dispatch_stop";
+        final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mLocalActivityManager.startActivity(id, intent);
+        if (mLocalActivityManager.getCurrentActivity() == null) {
+            fail();
+            return;
+        }
+
+        LocalActivityManagerStubActivity.sIsOnStopCalled = false;
+        mLocalActivityManager.dispatchStop();
+
+        if (!LocalActivityManagerStubActivity.sIsOnStopCalled) {
+            fail();
+            return;
+        }
+        pass();
+    }
+
+    private void testDispatchCreate() {
+        final Bundle EXPECTED = new Bundle();
+        final String id = "id";
+
+        final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mLocalActivityManager.startActivity("_id" + System.currentTimeMillis(), intent);
+        final Bundle bundle = mLocalActivityManager.saveInstanceState();
+        if (bundle == null) {
+            fail();
+            return;
+        }
+
+        if (bundle.keySet().size() != 1) {
+            fail();
+            return;
+        }
+
+        bundle.putBundle(id, EXPECTED);
+        // test null parameter
+        mLocalActivityManager.dispatchCreate(null);
+
+        if (mLocalActivityManager.saveInstanceState().keySet().size() != 1) {
+            fail();
+            return;
+        }
+
+        mLocalActivityManager.dispatchCreate(bundle);
+
+        final Bundle b = mLocalActivityManager.saveInstanceState();
+        final Bundle bb = b.getBundle(id);
+        if (bb != EXPECTED) {
+            fail();
+            return;
+        }
+        pass();
+    }
+
+    private void testStartActivity() {
+        final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        final String id = "_id_resume_test";
+        final Window w = mLocalActivityManager.startActivity(id, intent);
+        if (w == null) {
+            fail();
+            return;
+        }
+
+        Activity activity = mLocalActivityManager.getActivity(id);
+        if (activity == null) {
+            fail();
+            return;
+        }
+
+        // testing null id
+        activity = mLocalActivityManager.getActivity("null id");
+        if (activity != null) {
+            fail();
+            return;
+        }
+
+        if (!mLocalActivityManager.getCurrentId().equals(id)) {
+            fail();
+            return;
+        }
+
+        if (mLocalActivityManager.getActivity(id) != mLocalActivityManager
+                .getCurrentActivity()) {
+            fail();
+            return;
+        }
+
+        if (mLocalActivityManager.destroyActivity(id, true) == null) {
+            fail();
+            return;
+        }
+
+        if (mLocalActivityManager.startActivity(null, intent) == null) {
+            fail();
+            return;
+        }
+
+        try {
+            // test when calling startActivity with both null parameter.
+            mLocalActivityManager.startActivity(null, null);
+            fail();
+            return;
+        } catch (NullPointerException e) {
+        }
+        pass();
+    }
+
+    private void testDispatchResume() {
+        final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mLocalActivityManager.startActivity("_id_resume_test", intent);
+        mLocalActivityManager.dispatchStop();
+        LocalActivityManagerStubActivity.sIsOnResumeCalled = false;
+        mLocalActivityManager.dispatchResume();
+        if (LocalActivityManagerStubActivity.sIsOnResumeCalled) {
+            pass();
+        } else {
+            fail();
+        }
+    }
+
+    private void fail() {
+        sResult.setResult(CTSResult.RESULT_FAIL);
+        finish();
+    }
+
+    private void pass() {
+        sResult.setResult(CTSResult.RESULT_OK);
+        finish();
+    }
+}
diff --git a/tests/src/android/app/cts/LocalDeniedService.java b/tests/app/src/android/app/cts/LocalDeniedService.java
similarity index 100%
rename from tests/src/android/app/cts/LocalDeniedService.java
rename to tests/app/src/android/app/cts/LocalDeniedService.java
diff --git a/tests/src/android/app/cts/LocalDialog.java b/tests/app/src/android/app/cts/LocalDialog.java
similarity index 100%
rename from tests/src/android/app/cts/LocalDialog.java
rename to tests/app/src/android/app/cts/LocalDialog.java
diff --git a/tests/src/android/app/cts/LocalGrantedService.java b/tests/app/src/android/app/cts/LocalGrantedService.java
similarity index 100%
rename from tests/src/android/app/cts/LocalGrantedService.java
rename to tests/app/src/android/app/cts/LocalGrantedService.java
diff --git a/tests/src/android/app/cts/LocalScreen.java b/tests/app/src/android/app/cts/LocalScreen.java
similarity index 100%
rename from tests/src/android/app/cts/LocalScreen.java
rename to tests/app/src/android/app/cts/LocalScreen.java
diff --git a/tests/app/src/android/app/cts/LocalService.java b/tests/app/src/android/app/cts/LocalService.java
new file mode 100644
index 0000000..6c4ae99
--- /dev/null
+++ b/tests/app/src/android/app/cts/LocalService.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2008 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.app.cts;
+
+import android.app.Service;
+import android.content.Intent;
+import android.cts.util.IBinderParcelable;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteException;
+
+public class LocalService extends Service {
+    public static final String SERVICE_LOCAL =
+            "android.app.cts.activity.SERVICE_LOCAL";
+    public static final String SERVICE_LOCAL_GRANTED =
+            "android.app.cts.activity.SERVICE_LOCAL_GRANTED";
+    public static final String SERVICE_LOCAL_DENIED =
+            "android.app.cts.activity.SERVICE_LOCAL_DENIED";
+
+    public static final String REPORT_OBJ_NAME = "report";
+
+    public static final int STARTED_CODE = 1;
+    public static final int DESTROYED_CODE = 2;
+    public static final int SET_REPORTER_CODE = 3;
+    public static final int UNBIND_CODE = 4;
+    public static final int REBIND_CODE = 5;
+
+    private IBinder mReportObject;
+    private int mStartCount = 1;
+
+    private final IBinder mBinder = new Binder() {
+        @Override
+        protected boolean onTransact(int code, Parcel data, Parcel reply,
+                int flags) throws RemoteException {
+            if (code == SET_REPORTER_CODE) {
+                data.enforceInterface(SERVICE_LOCAL);
+                mReportObject = data.readStrongBinder();
+                return true;
+            } else {
+                return super.onTransact(code, data, reply, flags);
+            }
+        }
+    };
+
+
+    public LocalService() {
+    }
+
+    @Override
+    public void onStart(Intent intent, int startId) {
+        if (intent.getExtras() != null) {
+            IBinderParcelable parcelable
+                    = (IBinderParcelable) intent.getExtras().getParcelable(REPORT_OBJ_NAME);
+            mReportObject = parcelable.binder;
+            if (mReportObject != null) {
+                bindAction(STARTED_CODE);
+            }
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        if (mReportObject != null) {
+            bindAction(DESTROYED_CODE);
+        }
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mBinder;
+    }
+
+    @Override
+    public boolean onUnbind(Intent intent) {
+        if (mReportObject != null) {
+            bindAction(UNBIND_CODE);
+        }
+        return true;
+    }
+
+    @Override
+    public void onRebind(Intent intent) {
+        if (mReportObject != null) {
+            bindAction(REBIND_CODE);
+        }
+    }
+
+    private void bindAction(final int bindCode) {
+        try {
+            Parcel data = Parcel.obtain();
+            data.writeInterfaceToken(SERVICE_LOCAL);
+            if (bindCode == STARTED_CODE) {
+                data.writeInt(mStartCount);
+                mStartCount++;
+            }
+            mReportObject.transact(
+                    bindCode, data, null, 0);
+            data.recycle();
+        } catch (RemoteException e) {
+            // fail
+        }
+    }
+}
diff --git a/tests/src/android/app/cts/MockActivity.java b/tests/app/src/android/app/cts/MockActivity.java
similarity index 100%
rename from tests/src/android/app/cts/MockActivity.java
rename to tests/app/src/android/app/cts/MockActivity.java
diff --git a/tests/app/src/android/app/cts/MockAlarmReceiver.java b/tests/app/src/android/app/cts/MockAlarmReceiver.java
new file mode 100644
index 0000000..8745db6
--- /dev/null
+++ b/tests/app/src/android/app/cts/MockAlarmReceiver.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2008 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.app.cts;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.SystemClock;
+
+/**
+ * this class  receive alarm from AlarmManagerTest
+ */
+public class MockAlarmReceiver extends BroadcastReceiver {
+    private final Object mSync = new Object();
+    public final String mTargetAction;
+
+    public volatile boolean alarmed = false;
+    public volatile long elapsedTime;
+    public volatile long rtcTime;
+
+    public MockAlarmReceiver(String targetAction) {
+        mTargetAction = targetAction;
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        final String action = intent.getAction();
+        if (action.equals(mTargetAction)) {
+            synchronized (mSync) {
+                alarmed = true;
+                elapsedTime = SystemClock.elapsedRealtime();
+                rtcTime = System.currentTimeMillis();
+            }
+        }
+    }
+
+    public void setAlarmedFalse() {
+        synchronized (mSync) {
+            alarmed = false;
+        }
+    }
+}
diff --git a/tests/src/android/app/cts/MockApplication.java b/tests/app/src/android/app/cts/MockApplication.java
similarity index 100%
rename from tests/src/android/app/cts/MockApplication.java
rename to tests/app/src/android/app/cts/MockApplication.java
diff --git a/tests/src/android/app/cts/MockApplicationActivity.java b/tests/app/src/android/app/cts/MockApplicationActivity.java
similarity index 100%
rename from tests/src/android/app/cts/MockApplicationActivity.java
rename to tests/app/src/android/app/cts/MockApplicationActivity.java
diff --git a/tests/src/android/app/cts/MockReceiver.java b/tests/app/src/android/app/cts/MockReceiver.java
similarity index 100%
rename from tests/src/android/app/cts/MockReceiver.java
rename to tests/app/src/android/app/cts/MockReceiver.java
diff --git a/tests/src/android/app/cts/MockService.java b/tests/app/src/android/app/cts/MockService.java
similarity index 100%
rename from tests/src/android/app/cts/MockService.java
rename to tests/app/src/android/app/cts/MockService.java
diff --git a/tests/src/android/app/cts/MockTabActivity.java b/tests/app/src/android/app/cts/MockTabActivity.java
similarity index 100%
rename from tests/src/android/app/cts/MockTabActivity.java
rename to tests/app/src/android/app/cts/MockTabActivity.java
diff --git a/tests/src/android/app/cts/OrientationTestUtils.java b/tests/app/src/android/app/cts/OrientationTestUtils.java
similarity index 100%
rename from tests/src/android/app/cts/OrientationTestUtils.java
rename to tests/app/src/android/app/cts/OrientationTestUtils.java
diff --git a/tests/src/android/app/cts/PendingIntentStubActivity.java b/tests/app/src/android/app/cts/PendingIntentStubActivity.java
similarity index 100%
rename from tests/src/android/app/cts/PendingIntentStubActivity.java
rename to tests/app/src/android/app/cts/PendingIntentStubActivity.java
diff --git a/tests/app/src/android/app/cts/SearchManagerStubActivity.java b/tests/app/src/android/app/cts/SearchManagerStubActivity.java
new file mode 100644
index 0000000..0dbd832
--- /dev/null
+++ b/tests/app/src/android/app/cts/SearchManagerStubActivity.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2008 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.app.cts;
+
+import android.app.Activity;
+import android.app.SearchManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.cts.util.CTSResult;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+public class SearchManagerStubActivity extends Activity {
+
+    private static final String TAG = "SearchManagerStubActivity";
+
+    public static final String TEST_STOP_SEARCH = "stopSearch";
+    public static final String TEST_ON_DISMISSLISTENER = "setOnDismissListener";
+    public static final String TEST_ON_CANCELLISTENER = "setOnCancelListener";
+
+    private SearchManager mSearchManager;
+    private ComponentName mComponentName;
+
+    private static CTSResult sCTSResult;
+    private boolean mDismissCalled;
+    private boolean mCancelCalled;
+
+    public static void setCTSResult(CTSResult result) {
+        sCTSResult = result;
+    }
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        mSearchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
+        mComponentName = getComponentName();
+        String action = getIntent().getAction();
+        if (action.equals(TEST_STOP_SEARCH)) {
+            testStopSearch();
+        } else if (action.equals(TEST_ON_DISMISSLISTENER)) {
+            testOnDismissListener();
+        } else if (action.equals(TEST_ON_CANCELLISTENER)) {
+            testOnCancelListener();
+        }
+    }
+
+    private void testOnCancelListener() {
+        mCancelCalled = false;
+        mSearchManager.setOnCancelListener(new SearchManager.OnCancelListener() {
+            @Override
+            public void onCancel() {
+               mCancelCalled = true;
+            }
+        });
+
+        new TestStepHandler() {
+            @Override
+            public boolean doStep(int step) throws FailException {
+                switch (step) {
+                    case 1:
+                        startSearch("test", false, mComponentName, null, false);
+                        return false;
+                    case 2:
+                        assertFalse("cancel called", mCancelCalled);
+                        stopSearch();
+                        return false;
+                    case 3:
+                        assertTrue("cancel not called", mCancelCalled);
+                        pass();
+                        return true;
+                    default:
+                        throw new IllegalArgumentException("Bad step " + step);
+                }
+            }
+        }.start();
+    }
+
+    private void testOnDismissListener() {
+        mDismissCalled = false;
+
+        mSearchManager.setOnDismissListener(new SearchManager.OnDismissListener() {
+            public void onDismiss() {
+                mDismissCalled = true;
+            }
+        });
+
+        new TestStepHandler() {
+            @Override
+            public boolean doStep(int step) throws FailException {
+                switch (step) {
+                    case 1:
+                        startSearch("test", false, mComponentName, null, false);
+                        return false;
+                    case 2:
+                        if (mDismissCalled) {
+                            throw new FailException("dismiss called");
+                        } else {
+                            stopSearch();
+                        }
+                        return false;
+                    case 3:
+                        if (mDismissCalled) {
+                            pass();
+                        } else {
+                            throw new FailException("dismiss not called");
+                        }
+                        return true;
+                    default:
+                        throw new IllegalArgumentException("Bad step " + step);
+                }
+            }
+        }.start();
+    }
+
+    private void testStopSearch() {
+        new TestStepHandler() {
+            @Override
+            public boolean doStep(int step) throws FailException {
+                switch (step) {
+                    case 1:
+                        startSearch("test", false, mComponentName, null, false);
+                        return false;
+                    case 2:
+                        assertVisible();
+                        stopSearch();
+                        return false;
+                    case 3:
+                        assertInVisible();
+                        pass();
+                        return true;
+                    default:
+                        throw new IllegalArgumentException("Bad step " + step);
+                }
+            }
+        }.start();
+    }
+
+    private void fail(Exception ex) {
+        Log.e(TAG, "test failed", ex);
+        sCTSResult.setResult(CTSResult.RESULT_FAIL);
+        finish();
+    }
+
+    private void pass() {
+        sCTSResult.setResult(CTSResult.RESULT_OK);
+        finish();
+    }
+
+    private void assertInVisible() throws FailException {
+        if (isVisible()) {
+            throw new FailException();
+        }
+    }
+
+    private void assertVisible() throws FailException {
+        if (!isVisible()) {
+            throw new FailException();
+        }
+    }
+
+    private void assertFalse(String message, boolean value) throws FailException {
+        assertTrue(message, !value);
+    }
+
+    private void assertTrue(String message, boolean value) throws FailException {
+        if (!value) {
+            throw new FailException(message);
+        }
+    }
+
+    private void startSearch(String initialQuery, boolean selectInitialQuery,
+            ComponentName launchActivity, Bundle appSearchData, boolean globalSearch) {
+        mSearchManager.startSearch(initialQuery, selectInitialQuery, launchActivity, appSearchData,
+                globalSearch);
+    }
+
+    private void stopSearch() {
+       mSearchManager.stopSearch();
+    }
+
+    private boolean isVisible() {
+        return mSearchManager.isVisible();
+    }
+
+    private abstract class TestStepHandler extends Handler {
+
+        public void start() {
+            sendEmptyMessage(1);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            try {
+                if (!doStep(msg.what)) {
+                    sendEmptyMessage(msg.what + 1);
+                }
+            } catch (FailException ex) {
+                fail(ex);
+            }
+        }
+
+        /**
+         * Performs one step of the test.
+         *
+         * @param step The 1-based number of the step to perform.
+         * @return {@code true} if this was the last step.
+         * @throws FailException If the test failed.
+         */
+        protected abstract boolean doStep(int step) throws FailException;
+    }
+
+    private static class FailException extends Exception {
+        private static final long serialVersionUID = 1L;
+
+        public FailException() {
+            super();
+        }
+
+        public FailException(String detailMessage) {
+            super(detailMessage);
+        }
+    }
+}
diff --git a/tests/src/android/app/cts/StubRemoteService.java b/tests/app/src/android/app/cts/StubRemoteService.java
similarity index 100%
rename from tests/src/android/app/cts/StubRemoteService.java
rename to tests/app/src/android/app/cts/StubRemoteService.java
diff --git a/tests/src/android/app/cts/TestDialog.java b/tests/app/src/android/app/cts/TestDialog.java
similarity index 100%
rename from tests/src/android/app/cts/TestDialog.java
rename to tests/app/src/android/app/cts/TestDialog.java
diff --git a/tests/src/android/app/cts/TestedActivity.java b/tests/app/src/android/app/cts/TestedActivity.java
similarity index 100%
rename from tests/src/android/app/cts/TestedActivity.java
rename to tests/app/src/android/app/cts/TestedActivity.java
diff --git a/tests/src/android/app/cts/TestedScreen.java b/tests/app/src/android/app/cts/TestedScreen.java
similarity index 100%
rename from tests/src/android/app/cts/TestedScreen.java
rename to tests/app/src/android/app/cts/TestedScreen.java
diff --git a/tests/assets/ringer.mp3 b/tests/assets/ringer.mp3
deleted file mode 100644
index aa052e7..0000000
--- a/tests/assets/ringer.mp3
+++ /dev/null
Binary files differ
diff --git a/tests/assets/sphere.a3d b/tests/assets/sphere.a3d
deleted file mode 100644
index 3d78b01..0000000
--- a/tests/assets/sphere.a3d
+++ /dev/null
Binary files differ
diff --git a/tests/assets/webkit/iframe_blank_tag.html b/tests/assets/webkit/iframe_blank_tag.html
deleted file mode 100644
index 55ff410d..0000000
--- a/tests/assets/webkit/iframe_blank_tag.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<!-- Copyright (C) 2013 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.
--->
-
-<!DOCTYPE html>
-<html>
-<head>
-  <script type='text/javascript'> window.open('test_hello_world.html'); </script>
-</head>
-</html>
-
diff --git a/tests/core/ctscore.mk b/tests/core/ctscore.mk
index 95f4634..fea0b07 100644
--- a/tests/core/ctscore.mk
+++ b/tests/core/ctscore.mk
@@ -25,4 +25,8 @@
 
 LOCAL_JNI_SHARED_LIBRARIES := libjavacoretests
 
+# Include both the 32 and 64 bit versions of libjavacoretests,
+# where applicable.
+LOCAL_MULTILIB := both
+
 include $(BUILD_PACKAGE)
diff --git a/tests/core/libcore/com/Android.mk b/tests/core/libcore/com/Android.mk
index 02dc3de..db08dbd 100644
--- a/tests/core/libcore/com/Android.mk
+++ b/tests/core/libcore/com/Android.mk
@@ -14,10 +14,6 @@
 
 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.com
 LOCAL_STATIC_JAVA_LIBRARIES := core-tests
diff --git a/tests/core/libcore/com/AndroidManifest.xml b/tests/core/libcore/com/AndroidManifest.xml
index 4e37ef4..8790a7e 100644
--- a/tests/core/libcore/com/AndroidManifest.xml
+++ b/tests/core/libcore/com/AndroidManifest.xml
@@ -22,8 +22,12 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="android.core.tests.runner"
-                     android:label="cts framework tests"/>
+                     android:label="cts framework tests">
+        <meta-data
+            android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
diff --git a/tests/core/libcore/conscrypt/AndroidManifest.xml b/tests/core/libcore/conscrypt/AndroidManifest.xml
index 6517a0b..b299793 100644
--- a/tests/core/libcore/conscrypt/AndroidManifest.xml
+++ b/tests/core/libcore/conscrypt/AndroidManifest.xml
@@ -22,8 +22,11 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="android.core.tests.runner"
-                     android:label="cts framework tests"/>
+                     android:label="cts framework tests">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
diff --git a/tests/core/libcore/dalvik/Android.mk b/tests/core/libcore/dalvik/Android.mk
index 7b77a75..42d14f3 100644
--- a/tests/core/libcore/dalvik/Android.mk
+++ b/tests/core/libcore/dalvik/Android.mk
@@ -14,10 +14,6 @@
 
 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.dalvik
 LOCAL_STATIC_JAVA_LIBRARIES := core-tests
diff --git a/tests/core/libcore/dalvik/AndroidManifest.xml b/tests/core/libcore/dalvik/AndroidManifest.xml
index 6def32c..ca34678 100644
--- a/tests/core/libcore/dalvik/AndroidManifest.xml
+++ b/tests/core/libcore/dalvik/AndroidManifest.xml
@@ -22,8 +22,12 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="android.core.tests.runner"
-                     android:label="cts framework tests"/>
+                     android:label="cts framework tests">
+        <meta-data
+            android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
diff --git a/tests/core/libcore/harmony_annotation/Android.mk b/tests/core/libcore/harmony_annotation/Android.mk
new file mode 100644
index 0000000..e9f716e
--- /dev/null
+++ b/tests/core/libcore/harmony_annotation/Android.mk
@@ -0,0 +1,24 @@
+# Copyright (C) 2012 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.harmony_annotation
+LOCAL_STATIC_JAVA_LIBRARIES := core-tests
+include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/libcore/harmony_annotation/AndroidManifest.xml b/tests/core/libcore/harmony_annotation/AndroidManifest.xml
new file mode 100644
index 0000000..c83ecf2
--- /dev/null
+++ b/tests/core/libcore/harmony_annotation/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2012 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.harmony_annotation">
+    <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/libcore/harmony_beans/Android.mk b/tests/core/libcore/harmony_beans/Android.mk
new file mode 100644
index 0000000..2131ae0
--- /dev/null
+++ b/tests/core/libcore/harmony_beans/Android.mk
@@ -0,0 +1,24 @@
+# Copyright (C) 2012 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.harmony_beans
+LOCAL_STATIC_JAVA_LIBRARIES := apache-harmony-tests
+include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/libcore/harmony_beans/AndroidManifest.xml b/tests/core/libcore/harmony_beans/AndroidManifest.xml
new file mode 100644
index 0000000..b9b161c
--- /dev/null
+++ b/tests/core/libcore/harmony_beans/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2012 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.harmony_beans">
+    <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/libcore/harmony_java_io/Android.mk b/tests/core/libcore/harmony_java_io/Android.mk
new file mode 100644
index 0000000..a8d4fa0
--- /dev/null
+++ b/tests/core/libcore/harmony_java_io/Android.mk
@@ -0,0 +1,24 @@
+# Copyright (C) 2012 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.harmony_java_io
+LOCAL_STATIC_JAVA_LIBRARIES := core-tests
+include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/libcore/harmony_java_io/AndroidManifest.xml b/tests/core/libcore/harmony_java_io/AndroidManifest.xml
new file mode 100644
index 0000000..e69d4b4
--- /dev/null
+++ b/tests/core/libcore/harmony_java_io/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2012 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.harmony_java_io">
+    <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/libcore/harmony_java_lang/Android.mk b/tests/core/libcore/harmony_java_lang/Android.mk
new file mode 100644
index 0000000..8b1bdff
--- /dev/null
+++ b/tests/core/libcore/harmony_java_lang/Android.mk
@@ -0,0 +1,24 @@
+# Copyright (C) 2012 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.harmony_java_lang
+LOCAL_STATIC_JAVA_LIBRARIES := core-tests
+include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/libcore/harmony_java_lang/AndroidManifest.xml b/tests/core/libcore/harmony_java_lang/AndroidManifest.xml
new file mode 100644
index 0000000..1a5a748
--- /dev/null
+++ b/tests/core/libcore/harmony_java_lang/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2012 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.harmony_java_lang">
+    <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/libcore/harmony_java_math/Android.mk b/tests/core/libcore/harmony_java_math/Android.mk
new file mode 100644
index 0000000..8310743
--- /dev/null
+++ b/tests/core/libcore/harmony_java_math/Android.mk
@@ -0,0 +1,24 @@
+# Copyright (C) 2012 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.harmony_java_math
+LOCAL_STATIC_JAVA_LIBRARIES := core-tests
+include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/libcore/harmony_java_math/AndroidManifest.xml b/tests/core/libcore/harmony_java_math/AndroidManifest.xml
new file mode 100644
index 0000000..4cdf654
--- /dev/null
+++ b/tests/core/libcore/harmony_java_math/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2012 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.harmony_java_math">
+    <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/libcore/harmony_java_net/Android.mk b/tests/core/libcore/harmony_java_net/Android.mk
new file mode 100644
index 0000000..7917bcc
--- /dev/null
+++ b/tests/core/libcore/harmony_java_net/Android.mk
@@ -0,0 +1,24 @@
+# Copyright (C) 2012 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.harmony_java_net
+LOCAL_STATIC_JAVA_LIBRARIES := core-tests
+include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/libcore/harmony_java_net/AndroidManifest.xml b/tests/core/libcore/harmony_java_net/AndroidManifest.xml
new file mode 100644
index 0000000..db14fa9
--- /dev/null
+++ b/tests/core/libcore/harmony_java_net/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2012 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.harmony_java_net">
+    <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/libcore/harmony_java_nio/Android.mk b/tests/core/libcore/harmony_java_nio/Android.mk
new file mode 100644
index 0000000..2c6f673
--- /dev/null
+++ b/tests/core/libcore/harmony_java_nio/Android.mk
@@ -0,0 +1,24 @@
+# Copyright (C) 2012 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.harmony_java_nio
+LOCAL_STATIC_JAVA_LIBRARIES := core-tests
+include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/libcore/harmony_java_nio/AndroidManifest.xml b/tests/core/libcore/harmony_java_nio/AndroidManifest.xml
new file mode 100644
index 0000000..0221ebb
--- /dev/null
+++ b/tests/core/libcore/harmony_java_nio/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2012 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.harmony_java_nio">
+    <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/libcore/harmony_java_text/Android.mk b/tests/core/libcore/harmony_java_text/Android.mk
new file mode 100644
index 0000000..ecd1574
--- /dev/null
+++ b/tests/core/libcore/harmony_java_text/Android.mk
@@ -0,0 +1,24 @@
+# Copyright (C) 2012 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.harmony_java_text
+LOCAL_STATIC_JAVA_LIBRARIES := core-tests
+include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/libcore/harmony_java_text/AndroidManifest.xml b/tests/core/libcore/harmony_java_text/AndroidManifest.xml
new file mode 100644
index 0000000..6818053
--- /dev/null
+++ b/tests/core/libcore/harmony_java_text/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2012 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.harmony_java_text">
+    <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/libcore/harmony_java_util/Android.mk b/tests/core/libcore/harmony_java_util/Android.mk
new file mode 100644
index 0000000..6d7bded
--- /dev/null
+++ b/tests/core/libcore/harmony_java_util/Android.mk
@@ -0,0 +1,24 @@
+# Copyright (C) 2012 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.harmony_java_util
+LOCAL_STATIC_JAVA_LIBRARIES := core-tests
+include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/libcore/harmony_java_util/AndroidManifest.xml b/tests/core/libcore/harmony_java_util/AndroidManifest.xml
new file mode 100644
index 0000000..e36468e
--- /dev/null
+++ b/tests/core/libcore/harmony_java_util/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2012 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.harmony_java_util">
+    <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/libcore/harmony_javax_security/Android.mk b/tests/core/libcore/harmony_javax_security/Android.mk
new file mode 100644
index 0000000..011940d
--- /dev/null
+++ b/tests/core/libcore/harmony_javax_security/Android.mk
@@ -0,0 +1,24 @@
+# Copyright (C) 2012 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.harmony_javax_security
+LOCAL_STATIC_JAVA_LIBRARIES := core-tests
+include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/libcore/harmony_javax_security/AndroidManifest.xml b/tests/core/libcore/harmony_javax_security/AndroidManifest.xml
new file mode 100644
index 0000000..c927855
--- /dev/null
+++ b/tests/core/libcore/harmony_javax_security/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2012 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.harmony_javax_security">
+    <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/libcore/harmony_logging/Android.mk b/tests/core/libcore/harmony_logging/Android.mk
new file mode 100644
index 0000000..2ec10f1
--- /dev/null
+++ b/tests/core/libcore/harmony_logging/Android.mk
@@ -0,0 +1,24 @@
+# Copyright (C) 2012 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.harmony_logging
+LOCAL_STATIC_JAVA_LIBRARIES := apache-harmony-tests
+include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/libcore/harmony_logging/AndroidManifest.xml b/tests/core/libcore/harmony_logging/AndroidManifest.xml
new file mode 100644
index 0000000..8a669e2
--- /dev/null
+++ b/tests/core/libcore/harmony_logging/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2012 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.harmony_logging">
+    <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/libcore/harmony_prefs/Android.mk b/tests/core/libcore/harmony_prefs/Android.mk
new file mode 100644
index 0000000..92b0c7d
--- /dev/null
+++ b/tests/core/libcore/harmony_prefs/Android.mk
@@ -0,0 +1,24 @@
+# Copyright (C) 2012 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.harmony_prefs
+LOCAL_STATIC_JAVA_LIBRARIES := apache-harmony-tests
+include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/libcore/harmony_prefs/AndroidManifest.xml b/tests/core/libcore/harmony_prefs/AndroidManifest.xml
new file mode 100644
index 0000000..ebcb4ef
--- /dev/null
+++ b/tests/core/libcore/harmony_prefs/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2012 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.harmony_prefs">
+    <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/libcore/harmony_sql/Android.mk b/tests/core/libcore/harmony_sql/Android.mk
new file mode 100644
index 0000000..b1df215
--- /dev/null
+++ b/tests/core/libcore/harmony_sql/Android.mk
@@ -0,0 +1,24 @@
+# Copyright (C) 2012 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.harmony_sql
+LOCAL_STATIC_JAVA_LIBRARIES := apache-harmony-tests
+include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/libcore/harmony_sql/AndroidManifest.xml b/tests/core/libcore/harmony_sql/AndroidManifest.xml
new file mode 100644
index 0000000..7cd86da
--- /dev/null
+++ b/tests/core/libcore/harmony_sql/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2012 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.harmony_sql">
+    <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/libcore/jsr166/Android.mk b/tests/core/libcore/jsr166/Android.mk
new file mode 100644
index 0000000..3f9871e
--- /dev/null
+++ b/tests/core/libcore/jsr166/Android.mk
@@ -0,0 +1,20 @@
+# Copyright (C) 2013 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)
+
+include $(CLEAR_VARS)
+LOCAL_PACKAGE_NAME := android.core.tests.libcore.package.jsr166
+LOCAL_STATIC_JAVA_LIBRARIES := jsr166-tests
+include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/libcore/jsr166/AndroidManifest.xml b/tests/core/libcore/jsr166/AndroidManifest.xml
new file mode 100644
index 0000000..fb4a648
--- /dev/null
+++ b/tests/core/libcore/jsr166/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2013 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.jsr166">
+    <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/libcore/libcore/Android.mk b/tests/core/libcore/libcore/Android.mk
index 382b386..a86d2c0 100644
--- a/tests/core/libcore/libcore/Android.mk
+++ b/tests/core/libcore/libcore/Android.mk
@@ -14,10 +14,6 @@
 
 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.libcore
 LOCAL_STATIC_JAVA_LIBRARIES := core-tests
diff --git a/tests/core/libcore/libcore/AndroidManifest.xml b/tests/core/libcore/libcore/AndroidManifest.xml
index e4a5d1e..67a3023 100644
--- a/tests/core/libcore/libcore/AndroidManifest.xml
+++ b/tests/core/libcore/libcore/AndroidManifest.xml
@@ -22,8 +22,11 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="android.core.tests.runner"
-                     android:label="cts framework tests"/>
+                     android:label="cts framework tests">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
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/libcore/org/Android.mk b/tests/core/libcore/org/Android.mk
index d7a96b3..0f3f0ca 100644
--- a/tests/core/libcore/org/Android.mk
+++ b/tests/core/libcore/org/Android.mk
@@ -14,10 +14,6 @@
 
 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.org
 LOCAL_STATIC_JAVA_LIBRARIES := core-tests
diff --git a/tests/core/libcore/org/AndroidManifest.xml b/tests/core/libcore/org/AndroidManifest.xml
index d5b77bd..d705f65 100644
--- a/tests/core/libcore/org/AndroidManifest.xml
+++ b/tests/core/libcore/org/AndroidManifest.xml
@@ -22,8 +22,11 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="android.core.tests.runner"
-                     android:label="cts framework tests"/>
+                     android:label="cts framework tests">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
diff --git a/tests/core/libcore/sun/Android.mk b/tests/core/libcore/sun/Android.mk
index 44d3d70..ed6d2c7 100644
--- a/tests/core/libcore/sun/Android.mk
+++ b/tests/core/libcore/sun/Android.mk
@@ -14,10 +14,6 @@
 
 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.sun
 LOCAL_STATIC_JAVA_LIBRARIES := core-tests
diff --git a/tests/core/libcore/sun/AndroidManifest.xml b/tests/core/libcore/sun/AndroidManifest.xml
index cc1a853..9888af3 100644
--- a/tests/core/libcore/sun/AndroidManifest.xml
+++ b/tests/core/libcore/sun/AndroidManifest.xml
@@ -22,8 +22,11 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="android.core.tests.runner"
-                     android:label="cts framework tests"/>
+                     android:label="cts framework tests">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
diff --git a/tests/core/libcore/tests/Android.mk b/tests/core/libcore/tests/Android.mk
index bfd235f..54ffd31 100644
--- a/tests/core/libcore/tests/Android.mk
+++ b/tests/core/libcore/tests/Android.mk
@@ -14,10 +14,6 @@
 
 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.tests
 LOCAL_STATIC_JAVA_LIBRARIES := core-tests
diff --git a/tests/core/libcore/tests/AndroidManifest.xml b/tests/core/libcore/tests/AndroidManifest.xml
index 02f8b4a..f7dab9c 100644
--- a/tests/core/libcore/tests/AndroidManifest.xml
+++ b/tests/core/libcore/tests/AndroidManifest.xml
@@ -22,8 +22,11 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="android.core.tests.runner"
-                     android:label="cts framework tests"/>
+                     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/Android.mk b/tests/core/runner/Android.mk
index fb548fc..649b3b4 100644
--- a/tests/core/runner/Android.mk
+++ b/tests/core/runner/Android.mk
@@ -27,6 +27,6 @@
 
 LOCAL_PACKAGE_NAME := android.core.tests.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := core-tests
+LOCAL_STATIC_JAVA_LIBRARIES := core-tests android-support-test
 
 include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/runner/AndroidManifest.xml b/tests/core/runner/AndroidManifest.xml
index e179710..05d210b 100644
--- a/tests/core/runner/AndroidManifest.xml
+++ b/tests/core/runner/AndroidManifest.xml
@@ -22,7 +22,7 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="android.core.tests.runner"
                      android:label="cts framework tests"/>
 
diff --git a/tests/core/runner/src/android/test/InstrumentationCtsTestRunner.java b/tests/core/runner/src/android/test/InstrumentationCtsTestRunner.java
deleted file mode 100644
index d992839..0000000
--- a/tests/core/runner/src/android/test/InstrumentationCtsTestRunner.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright (C) 2008 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.test;
-
-import com.android.internal.util.Predicate;
-import com.android.internal.util.Predicates;
-
-import dalvik.annotation.BrokenTest;
-import dalvik.annotation.SideEffect;
-
-import android.app.KeyguardManager;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.test.suitebuilder.TestMethod;
-import android.test.suitebuilder.annotation.HasAnnotation;
-import android.util.Log;
-
-import java.io.File;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.net.Authenticator;
-import java.net.CookieHandler;
-import java.net.ResponseCache;
-import java.util.List;
-import java.util.Locale;
-import java.util.TimeZone;
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLSocketFactory;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestListener;
-
-/**
- * This test runner extends the default InstrumentationTestRunner. It overrides
- * the {@code onCreate(Bundle)} method and sets the system properties necessary
- * for many core tests to run. This is needed because there are some core tests
- * that need writing access to the file system. We also need to set the harness
- * Thread's context ClassLoader. Otherwise some classes and resources will not
- * be found. Finally, we add a means to free memory allocated by a TestCase
- * after its execution.
- *
- * @hide
- */
-public class InstrumentationCtsTestRunner extends InstrumentationTestRunner {
-
-    private static final String TAG = "InstrumentationCtsTestRunner";
-
-    /**
-     * True if (and only if) we are running in single-test mode (as opposed to
-     * batch mode).
-     */
-    private boolean mSingleTest = false;
-
-    private TestEnvironment mEnvironment;
-
-    @Override
-    public void onCreate(Bundle arguments) {
-        // We might want to move this to /sdcard, if is is mounted/writable.
-        File cacheDir = 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());
-
-
-        mEnvironment = new TestEnvironment();
-
-        if (arguments != null) {
-            String classArg = arguments.getString(ARGUMENT_TEST_CLASS);
-            mSingleTest = classArg != null && classArg.contains("#");
-        }
-
-        // attempt to disable keyguard,  if current test has permission to do so
-        // TODO: move this to a better place, such as InstrumentationTestRunner ?
-        if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
-                == PackageManager.PERMISSION_GRANTED) {
-            Log.i(TAG, "Disabling keyguard");
-            KeyguardManager keyguardManager =
-                (KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE);
-            keyguardManager.newKeyguardLock("cts").disableKeyguard();
-        } else {
-            Log.i(TAG, "Test lacks permission to disable keyguard. " +
-                    "UI based tests may fail if keyguard is up");
-        }
-
-        super.onCreate(arguments);
-    }
-
-    @Override
-    protected AndroidTestRunner getAndroidTestRunner() {
-        AndroidTestRunner runner = super.getAndroidTestRunner();
-
-        runner.addTestListener(new TestListener() {
-            /**
-             * The last test class we executed code from.
-             */
-            private Class<?> lastClass;
-
-            @Override
-            public void startTest(Test test) {
-                if (test.getClass() != lastClass) {
-                    lastClass = test.getClass();
-                    printMemory(test.getClass());
-                }
-
-                Thread.currentThread().setContextClassLoader(
-                        test.getClass().getClassLoader());
-
-                mEnvironment.reset();
-            }
-
-            @Override
-            public void endTest(Test test) {
-                if (test instanceof TestCase) {
-                    cleanup((TestCase)test);
-                }
-            }
-
-            @Override
-            public void addError(Test test, Throwable t) {
-                // This space intentionally left blank.
-            }
-
-            @Override
-            public void addFailure(Test test, AssertionFailedError t) {
-                // This space intentionally left blank.
-            }
-
-            /**
-             * Dumps some memory info.
-             */
-            private void printMemory(Class<? extends Test> testClass) {
-                Runtime runtime = Runtime.getRuntime();
-
-                long total = runtime.totalMemory();
-                long free = runtime.freeMemory();
-                long used = total - free;
-
-                Log.d(TAG, "Total memory  : " + total);
-                Log.d(TAG, "Used memory   : " + used);
-                Log.d(TAG, "Free memory   : " + free);
-                Log.d(TAG, "Now executing : " + testClass.getName());
-            }
-
-            /**
-             * Nulls all non-static reference fields in the given test class.
-             * This method helps us with those test classes that don't have an
-             * explicit tearDown() method. Normally the garbage collector should
-             * take care of everything, but since JUnit keeps references to all
-             * test cases, a little help might be a good idea.
-             */
-            private void cleanup(TestCase test) {
-                Class<?> clazz = test.getClass();
-
-                while (clazz != TestCase.class) {
-                    Field[] fields = clazz.getDeclaredFields();
-                    for (int i = 0; i < fields.length; i++) {
-                        Field f = fields[i];
-                        if (!f.getType().isPrimitive() &&
-                                !Modifier.isStatic(f.getModifiers())) {
-                            try {
-                                f.setAccessible(true);
-                                f.set(test, null);
-                            } catch (Exception ignored) {
-                                // Nothing we can do about it.
-                            }
-                        }
-                    }
-
-                    clazz = clazz.getSuperclass();
-                }
-            }
-
-        });
-
-        return runner;
-    }
-
-    // http://code.google.com/p/vogar/source/browse/trunk/src/vogar/target/TestEnvironment.java
-    static class TestEnvironment {
-        private Locale mDefaultLocale;
-        private String mUserHome;
-        private String mJavaIoTmpDir;
-        private HostnameVerifier mHostnameVerifier;
-        private SSLSocketFactory mSslSocketFactory;
-
-        TestEnvironment() {
-            mDefaultLocale = Locale.getDefault();
-            mUserHome = System.getProperty("user.home");
-            mJavaIoTmpDir = System.getProperty("java.io.tmpdir");
-            mHostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
-            mSslSocketFactory = HttpsURLConnection.getDefaultSSLSocketFactory();
-        }
-
-        void reset() {
-            Locale.setDefault(mDefaultLocale);
-            System.setProperty("user.home", mUserHome);
-            System.setProperty("java.io.tmpdir", mJavaIoTmpDir);
-            Authenticator.setDefault(null);
-            CookieHandler.setDefault(null);
-            ResponseCache.setDefault(null);
-            HttpsURLConnection.setDefaultHostnameVerifier(mHostnameVerifier);
-            HttpsURLConnection.setDefaultSSLSocketFactory(mSslSocketFactory);
-        }
-    }
-
-    @Override
-    List<Predicate<TestMethod>> getBuilderRequirements() {
-        List<Predicate<TestMethod>> builderRequirements =
-                super.getBuilderRequirements();
-
-        Predicate<TestMethod> brokenTestPredicate =
-                Predicates.not(new HasAnnotation(BrokenTest.class));
-        builderRequirements.add(brokenTestPredicate);
-
-        if (!mSingleTest) {
-            Predicate<TestMethod> sideEffectPredicate =
-                    Predicates.not(new HasAnnotation(SideEffect.class));
-            builderRequirements.add(sideEffectPredicate);
-        }
-        return builderRequirements;
-    }
-}
diff --git a/tests/core/runner/src/com/android/cts/runner/CtsTestRunListener.java b/tests/core/runner/src/com/android/cts/runner/CtsTestRunListener.java
new file mode 100644
index 0000000..5196df1
--- /dev/null
+++ b/tests/core/runner/src/com/android/cts/runner/CtsTestRunListener.java
@@ -0,0 +1,177 @@
+/*
+ * 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 com.android.cts.runner;
+
+import android.app.Instrumentation;
+import android.app.KeyguardManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.support.test.internal.runner.listener.InstrumentationRunListener;
+import android.util.Log;
+
+import junit.framework.TestCase;
+
+import org.junit.runner.Description;
+import org.junit.runner.notification.RunListener;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.net.Authenticator;
+import java.net.CookieHandler;
+import java.net.ResponseCache;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLSocketFactory;
+
+/**
+ * A {@link RunListener} for CTS. Sets the system properties necessary for many
+ * core tests to run. This is needed because there are some core tests that need
+ * writing access to the file system.
+ * Finally, we add a means to free memory allocated by a TestCase after its
+ * execution.
+ */
+public class CtsTestRunListener extends InstrumentationRunListener {
+
+    private static final String TAG = "CtsTestRunListener";
+
+    private TestEnvironment mEnvironment;
+    private Class<?> lastClass;
+
+    @Override
+    public void testRunStarted(Description description) throws Exception {
+        mEnvironment = new TestEnvironment();
+
+        // We might want to move this to /sdcard, if is is mounted/writable.
+        File cacheDir = getInstrumentation().getTargetContext().getCacheDir();
+        System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
+
+        // attempt to disable keyguard, if current test has permission to do so
+        // TODO: move this to a better place, such as InstrumentationTestRunner
+        // ?
+        if (getInstrumentation().getContext().checkCallingOrSelfPermission(
+                android.Manifest.permission.DISABLE_KEYGUARD)
+                == PackageManager.PERMISSION_GRANTED) {
+            Log.i(TAG, "Disabling keyguard");
+            KeyguardManager keyguardManager =
+                    (KeyguardManager) getInstrumentation().getContext().getSystemService(
+                            Context.KEYGUARD_SERVICE);
+            keyguardManager.newKeyguardLock("cts").disableKeyguard();
+        } else {
+            Log.i(TAG, "Test lacks permission to disable keyguard. " +
+                    "UI based tests may fail if keyguard is up");
+        }
+    }
+
+    @Override
+    public void testStarted(Description description) throws Exception {
+        if (description.getTestClass() != lastClass) {
+            lastClass = description.getTestClass();
+            printMemory(description.getTestClass());
+        }
+
+        mEnvironment.reset();
+    }
+
+    @Override
+    public void testFinished(Description description) {
+        // no way to implement this in JUnit4...
+        // offending test cases that need this logic should probably be cleaned
+        // up individually
+        // if (test instanceof TestCase) {
+        // cleanup((TestCase) test);
+        // }
+    }
+
+    /**
+     * Dumps some memory info.
+     */
+    private void printMemory(Class<?> testClass) {
+        Runtime runtime = Runtime.getRuntime();
+
+        long total = runtime.totalMemory();
+        long free = runtime.freeMemory();
+        long used = total - free;
+
+        Log.d(TAG, "Total memory  : " + total);
+        Log.d(TAG, "Used memory   : " + used);
+        Log.d(TAG, "Free memory   : " + free);
+        Log.d(TAG, "Now executing : " + testClass.getName());
+    }
+
+    /**
+     * Nulls all non-static reference fields in the given test class. This
+     * method helps us with those test classes that don't have an explicit
+     * tearDown() method. Normally the garbage collector should take care of
+     * everything, but since JUnit keeps references to all test cases, a little
+     * help might be a good idea.
+     */
+    private void cleanup(TestCase test) {
+        Class<?> clazz = test.getClass();
+
+        while (clazz != TestCase.class) {
+            Field[] fields = clazz.getDeclaredFields();
+            for (int i = 0; i < fields.length; i++) {
+                Field f = fields[i];
+                if (!f.getType().isPrimitive() &&
+                        !Modifier.isStatic(f.getModifiers())) {
+                    try {
+                        f.setAccessible(true);
+                        f.set(test, null);
+                    } catch (Exception ignored) {
+                        // Nothing we can do about it.
+                    }
+                }
+            }
+
+            clazz = clazz.getSuperclass();
+        }
+    }
+
+    // http://code.google.com/p/vogar/source/browse/trunk/src/vogar/target/TestEnvironment.java
+    static class TestEnvironment {
+        private final Locale mDefaultLocale;
+        private final TimeZone mDefaultTimeZone;
+        private final String mJavaIoTmpDir;
+        private final HostnameVerifier mHostnameVerifier;
+        private final SSLSocketFactory mSslSocketFactory;
+
+        TestEnvironment() {
+            mDefaultLocale = Locale.getDefault();
+            mDefaultTimeZone = TimeZone.getDefault();
+            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);
+            Authenticator.setDefault(null);
+            CookieHandler.setDefault(null);
+            ResponseCache.setDefault(null);
+            HttpsURLConnection.setDefaultHostnameVerifier(mHostnameVerifier);
+            HttpsURLConnection.setDefaultSSLSocketFactory(mSslSocketFactory);
+        }
+    }
+
+}
diff --git a/tests/deviceadmin/Android.mk b/tests/deviceadmin/Android.mk
index bcc23fc..9ab9cb8 100644
--- a/tests/deviceadmin/Android.mk
+++ b/tests/deviceadmin/Android.mk
@@ -20,7 +20,7 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner guava
+LOCAL_JAVA_LIBRARIES := guava
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/deviceadmin/AndroidManifest.xml b/tests/deviceadmin/AndroidManifest.xml
index 2395d99..f70a677 100644
--- a/tests/deviceadmin/AndroidManifest.xml
+++ b/tests/deviceadmin/AndroidManifest.xml
@@ -107,7 +107,7 @@
 
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
             android:targetPackage="com.android.cts.admin"
             android:label="Tests for the device admin APIs."/>
 </manifest>
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index adefd76..dd8660f 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -1,188 +1,368 @@
 [
 {
-  name: "android.openglperf.cts.GlVboPerfTest#testVboWithVaryingIndexBufferNumbers",
-  bug: 6950385
+  description: "the UsageStats is not yet stable enough",
+  names: [
+    "android.app.usage.cts.UsageStatsTest"
+  ],
+  bug: 17536113
 },
 {
-  name: "android.holo.cts.HoloTest",
-  bug: 8148617
+  description: "the ConnectivityConstraintTest are not yet stable",
+  names: [
+    "android.jobscheduler.cts.ConnectivityConstraintTest"
+  ],
+  bug: 18117279
 },
 {
-  name: "android.holo.cts.HoloHostTest",
-  bug: 15343612
+  description: "tests a fragile by nature as they rely on hardcoded behavior",
+  names: [
+    "android.accessibilityservice.cts.AccessibilityTextTraversalTest#testActionNextAndPreviousAtGranularityPageOverText",
+    "android.accessibilityservice.cts.AccessibilityTextTraversalTest#testActionNextAndPreviousAtGranularityPageOverTextExtend"
+  ],
+  bug: 17595050
 },
 {
-  name: "android.nativeopengl.EGLCleanupTest#TestCorrect",
-  name: "android.nativeopengl.EGLCreateContextTest#BadAttributeFails",
-  bug: 11652564
+  description: "Not all jdwp features are currently supported. These tests will fail",
+  names: [
+    "org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowDebuggerLaunchTest#testDebuggerLaunch001",
+    "org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowDebuggerLaunchTest#testDebuggerLaunch002",
+    "org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowDebuggerLaunchTest#testDebuggerLaunch003",
+    "org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowDebuggerLaunchTest#testDebuggerLaunch004",
+    "org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowLaunchDebugger001#testDebugger002",
+    "org.apache.harmony.jpda.tests.jdwp.DebuggerOnDemand.OnthrowLaunchDebugger002#testDebugger",
+    "org.apache.harmony.jpda.tests.jdwp.Events.ClassUnloadTest#testClassUnloadEvent",
+    "org.apache.harmony.jpda.tests.jdwp.Events.MonitorContendedEnterTest#testMonitorContendedEnterForClassMatch",
+    "org.apache.harmony.jpda.tests.jdwp.Events.MonitorContendedEnteredTest#testMonitorContendedEnteredForClassMatch",
+    "org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitTest#testMonitorWaitForClassExclude",
+    "org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitTest#testMonitorWaitForClassMatchExact",
+    "org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitTest#testMonitorWaitForClassMatchFirst",
+    "org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitTest#testMonitorWaitForClassMatchSecond",
+    "org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitTest#testMonitorWaitForClassOnly",
+    "org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitedTest#testMonitorWaitedForClassExclude",
+    "org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitedTest#testMonitorWaitedForClassMatchExact",
+    "org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitedTest#testMonitorWaitedForClassMatchFirst",
+    "org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitedTest#testMonitorWaitedForClassMatchSecond",
+    "org.apache.harmony.jpda.tests.jdwp.Events.MonitorWaitedTest#testMonitorWaitedForClassOnly",
+    "org.apache.harmony.jpda.tests.jdwp.ReferenceType.ClassFileVersionTest#testClassFileVersion001",
+    "org.apache.harmony.jpda.tests.jdwp.ReferenceType.NestedTypesTest#testNestedTypes001",
+    "org.apache.harmony.jpda.tests.jdwp.ThreadReference.StopTest#testStop001",
+    "org.apache.harmony.jpda.tests.jdwp.VirtualMachine.HoldEventsTest#testHoldEvents001",
+    "org.apache.harmony.jpda.tests.jdwp.VirtualMachine.ReleaseEventsTest#testReleaseEvents001"
+  ],
+  bug: 16720689
 },
 {
-  name: "android.hardware.camera2.cts.ImageReaderTest",
-  name: "android.hardware.camera2.cts.CameraCharacteristicsTest",
-  name: "android.hardware.camera2.cts.CameraCaptureResultTest",
-  name: "android.hardware.camera2.cts.CameraDeviceTest",
-  name: "android.hardware.camera2.cts.CameraManagerTest",
-  bug: 11141002
+  description: "A few WebGL tests are known to fail in WebView",
+  names: [
+    "android.webgl.cts.WebGLTest#test_conformance_extensions_oes_texture_float_with_video_html",
+    "android.webgl.cts.WebGLTest#test_conformance_renderbuffers_framebuffer_object_attachment_html",
+    "android.webgl.cts.WebGLTest#test_conformance_rendering_multisample_corruption_html",
+    "android.webgl.cts.WebGLTest#test_conformance_textures_tex_image_and_sub_image_2d_with_video_html",
+    "android.webgl.cts.WebGLTest#test_conformance_textures_tex_image_and_sub_image_2d_with_video_rgb565_html",
+    "android.webgl.cts.WebGLTest#test_conformance_textures_tex_image_and_sub_image_2d_with_video_rgba4444_html",
+    "android.webgl.cts.WebGLTest#test_conformance_textures_tex_image_and_sub_image_2d_with_video_rgba5551_html",
+    "android.webgl.cts.WebGLTest#test_conformance_textures_texture_npot_html",
+    "android.webgl.cts.WebGLTest#test_conformance_textures_texture_npot_video_html",
+    "android.webgl.cts.WebGLTest#test_conformance_glsl_misc_empty_main_vert_html",
+    "android.webgl.cts.WebGLTest#test_conformance_glsl_misc_gl_position_unset_vert_html",
+    "android.webgl.cts.WebGLTest#test_conformance_misc_webgl_specific_html"
+  ],
+  bug: 17748398
 },
 {
-  name: "com.android.cts.opengl.primitive.GLPrimitiveBenchmark#testFullPipelineOffscreen",
-  name: "com.android.cts.opengl.primitive.GLPrimitiveBenchmark#testPixelOutputOffscreen",
-  bug: 11238219
+  description: "permissions for the API previously used in the test has changed, making it impossible to pass",
+  names: [
+    "android.openglperf.cts.GlAppSwitchTest#testGlActivitySwitchingFast",
+    "android.openglperf.cts.GlAppSwitchTest#testGlActivitySwitchingSlow"
+  ],
+  bug: 17394321
 },
 {
-  name: "android.hardware.cts.SensorIntegrationTests#testSensorsWithSeveralClients",
-  name: "android.hardware.cts.SensorIntegrationTests#testSensorsMovingRates",
-  bug: 11352697
+  description: "unexpected failures",
+  names: [
+    "android.openglperf.cts.GlVboPerfTest#testVboWithVaryingIndexBufferNumbers"
+  ],
+  bug: 18091590
 },
 {
-  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
+  description: "these tests require a good test scene, so they fail if run in random conditions",
+  names: [
+    "android.hardware.camera2.cts.AllocationTest#testBlackWhite",
+    "android.hardware.camera2.cts.AllocationTest#testParamSensitivity"
+  ],
+  bug: 17530117
 },
 {
-  name: "android.app.cts.DialogTest#testTouchEvent",
-  bug: 15455341
+  description: "this test removes the stay-awake option, causing the screen to turn off during the execution of subsequent tests",
+  names: [
+    "android.admin.cts.DevicePolicyManagerTest#testMaximumTimeToLock"
+  ],
+  bug: 18002490
 },
 {
-  name: "android.database.sqlite.cts.SQLiteQueryBuilderTest#testSetProjectionMap",
-  bug: 12475524
+  description: "these tests locks the screen with an emtpy password or swipe-to-unlock, blocking subsequent test to dismiss keyguard",
+  names: [
+    "android.admin.cts.DevicePolicyManagerTest#testPasswordQuality_something",
+    "android.admin.cts.DevicePolicyManagerTest#testPasswordQuality_numeric",
+    "android.admin.cts.DevicePolicyManagerTest#testPasswordQuality_alphabetic",
+    "android.admin.cts.DevicePolicyManagerTest#testPasswordQuality_alphanumeric",
+    "android.admin.cts.DevicePolicyManagerTest#testPasswordQuality_complexUpperCase",
+    "android.admin.cts.DevicePolicyManagerTest#testPasswordQuality_complexLowerCase",
+    "android.admin.cts.DevicePolicyManagerTest#testPasswordQuality_complexLetters",
+    "android.admin.cts.DevicePolicyManagerTest#testPasswordQuality_complexNumeric",
+    "android.admin.cts.DevicePolicyManagerTest#testPasswordQuality_complexSymbols",
+    "android.admin.cts.DevicePolicyManagerTest#testPasswordQuality_complexNonLetter",
+    "android.admin.cts.DevicePolicyManagerTest#testGetMaximumFailedPasswordsForWipe"
+  ],
+  bug: 17496766
 },
 {
-  name: "android.keystore.cts.KeyChainTest#testIsBoundKeyAlgorithm_RequiredAlgorithmsSupported",
-  bug: 15314696
+  description: "these tests locks the screen with an emtpy password or swipe-to-unlock, blocking subsequent test to dismiss keyguard",
+  names: [
+    "com.android.cts.devicepolicy.DeviceOwnerTest#testKeyManagement"
+  ],
+  bug: 17496766
 },
 {
-  name: "android.location.cts.LocationManagerTest",
-  name: "android.location.cts.LocationProviderTest",
-  bug: 15748237
+  description: "Current implementation of uninstallAllUserCaCerts does not throw expected security exception, wait for fix from framework",
+  names: [
+    "android.admin.cts.DevicePolicyManagerTest#testUninstallAllUserCaCerts_failIfNotProfileOwner"
+  ],
+  bug: 17508787
 },
 {
-  name: "android.media.cts.AudioEffectTest",
-  bug: 15081808
+  description: "New tests recently added for Android Enterprise. To be moved out of CTS-staging as soon as they show that they are stable",
+  names: [
+    "com.android.cts.devicepolicy.DeviceOwnerTest#testApplicationRestrictions",
+    "com.android.cts.devicepolicy.DeviceOwnerTest#testCaCertManagement",
+    "com.android.cts.devicepolicy.DeviceOwnerTest#testDeviceOwnerSetup",
+    "com.android.cts.devicepolicy.DeviceOwnerTest#testPersistentIntentResolving",
+    "com.android.cts.devicepolicy.DeviceOwnerTest#testScreenCaptureDisabled",
+    "com.android.cts.devicepolicy.ManagedProfileTest#testManagedProfileSetup",
+    "com.android.cts.devicepolicy.ManagedProfileTest#testWipeData",
+    "com.android.cts.devicepolicy.ManagedProfileTest#testCrossProfileIntentFilters",
+    "com.android.cts.devicepolicy.ManagedProfileTest#testCrossProfileContent",
+    "com.android.cts.devicepolicy.ManagedProfileTest#testNoDebuggingFeaturesRestriction"
+  ]
 },
 {
-  name: "android.media.cts.AudioManagerTest#testMusicActive",
-  name: "android.media.cts.AudioManagerTest#testVolume",
-  bug: 15319269
+  description: "Flaky test which ocassionally fails",
+  names: [
+    "com.android.cts.devicepolicy.DeviceOwnerTest#testLockTask"
+  ],
+  bug: 17890673
 },
 {
-  name: "android.media.cts.AudioTrackTest#testGetTimestamp",
-  bug: 15320704
+
+  description: "These tests fail on some devices.",
+  names: [
+    "android.uirendering.cts.testclasses.ExactCanvasTests#testBlueRect",
+    "android.uirendering.cts.testclasses.ExactCanvasTests#testBluePaddedSquare",
+    "android.uirendering.cts.testclasses.ViewClippingTests#testSimplePaddingClip",
+    "android.uirendering.cts.testclasses.ViewClippingTests#testSimpleClipBoundsClip",
+    "android.uirendering.cts.testclasses.ViewClippingTests#testSimpleOutlineClip",
+    "android.uirendering.cts.testclasses.ViewClippingTests#testSimpleBoundsClip",
+    "android.uirendering.cts.testclasses.InfrastructureTests#testViewInitializer"
+  ],
+  bug: 17511118
 },
 {
-  name: "android.media.cts.BassBoostTest",
-  name: "android.media.cts.EnvReverbTest",
-  name: "android.media.cts.EqualizerTest",
-  bug: 15163233
+  description: "This test failed on devices that use effect off loading. In addition it uses hidden apis",
+  names: [
+    "android.media.cts.AudioEffectTest#test1_1ConstructorFromUuid"
+  ],
+  bug: 17605875
 },
 {
-  name: "android.media.cts.DecoderTest",
-  bug: 15163143
+  description: "Failures on these tests are known on several devices.",
+  names: [
+    "android.hardware.cts.SensorBatchingTests#testAccelerometer_fastest_batching",
+    "android.hardware.cts.SensorBatchingTests#testAccelerometer_50hz_batching",
+    "android.hardware.cts.SensorBatchingTests#testAccelerometer_fastest_flush",
+    "android.hardware.cts.SensorBatchingTests#testAccelerometer_50hz_flush",
+    "android.hardware.cts.SensorBatchingTests#testMagneticField_fastest_batching",
+    "android.hardware.cts.SensorBatchingTests#testMagneticField_50hz_batching",
+    "android.hardware.cts.SensorBatchingTests#testMagneticField_fastest_flush",
+    "android.hardware.cts.SensorBatchingTests#testMagneticField_50hz_flush",
+    "android.hardware.cts.SensorBatchingTests#testOrientation_fastest_batching",
+    "android.hardware.cts.SensorBatchingTests#testOrientation_50hz_batching",
+    "android.hardware.cts.SensorBatchingTests#testOrientation_fastest_flush",
+    "android.hardware.cts.SensorBatchingTests#testOrientation_50hz_flush",
+    "android.hardware.cts.SensorBatchingTests#testGyroscope_fastest_batching",
+    "android.hardware.cts.SensorBatchingTests#testGyroscope_50hz_batching",
+    "android.hardware.cts.SensorBatchingTests#testGyroscope_fastest_flush",
+    "android.hardware.cts.SensorBatchingTests#testGyroscope_50hz_flush",
+    "android.hardware.cts.SensorBatchingTests#testPressure_fastest_batching",
+    "android.hardware.cts.SensorBatchingTests#testPressure_50hz_batching",
+    "android.hardware.cts.SensorBatchingTests#testPressure_fastest_flush",
+    "android.hardware.cts.SensorBatchingTests#testPressure_50hz_flush",
+    "android.hardware.cts.SensorBatchingTests#testGravity_fastest_batching",
+    "android.hardware.cts.SensorBatchingTests#testGravity_50hz_batching",
+    "android.hardware.cts.SensorBatchingTests#testGravity_fastest_flush",
+    "android.hardware.cts.SensorBatchingTests#testGravity_50hz_flush",
+    "android.hardware.cts.SensorBatchingTests#testRotationVector_fastest_batching",
+    "android.hardware.cts.SensorBatchingTests#testRotationVector_50hz_batching",
+    "android.hardware.cts.SensorBatchingTests#testRotationVector_fastest_flush",
+    "android.hardware.cts.SensorBatchingTests#testRotationVector_50hz_flush",
+    "android.hardware.cts.SensorBatchingTests#testMagneticFieldUncalibrated_fastest_batching",
+    "android.hardware.cts.SensorBatchingTests#testMagneticFieldUncalibrated_50hz_batching",
+    "android.hardware.cts.SensorBatchingTests#testMagneticFieldUncalibrated_fastest_flush",
+    "android.hardware.cts.SensorBatchingTests#testMagneticFieldUncalibrated_50hz_flush",
+    "android.hardware.cts.SensorBatchingTests#testGameRotationVector_fastest_batching",
+    "android.hardware.cts.SensorBatchingTests#testGameRotationVector_50hz_batching",
+    "android.hardware.cts.SensorBatchingTests#testGameRotationVector_fastest_flush",
+    "android.hardware.cts.SensorBatchingTests#testGameRotationVector_50hz_flush",
+    "android.hardware.cts.SensorBatchingTests#testGyroscopeUncalibrated_fastest_batching",
+    "android.hardware.cts.SensorBatchingTests#testGyroscopeUncalibrated_50hz_batching",
+    "android.hardware.cts.SensorBatchingTests#testGyroscopeUncalibrated_fastest_flush",
+    "android.hardware.cts.SensorBatchingTests#testGyroscopeUncalibrated_50hz_flush",
+    "android.hardware.cts.SensorBatchingTests#testLinearAcceleration_fastest_batching",
+    "android.hardware.cts.SensorBatchingTests#testLinearAcceleration_50hz_batching",
+    "android.hardware.cts.SensorBatchingTests#testLinearAcceleration_fastest_flush",
+    "android.hardware.cts.SensorBatchingTests#testLinearAcceleration_50hz_flush",
+    "android.hardware.cts.SensorBatchingTests#testGeomagneticRotationVector_fastest_batching",
+    "android.hardware.cts.SensorBatchingTests#testGeomagneticRotationVector_50hz_batching",
+    "android.hardware.cts.SensorBatchingTests#testGeomagneticRotationVector_fastest_flush",
+    "android.hardware.cts.SensorBatchingTests#testGeomagneticRotationVector_50hz_flush",
+    "android.hardware.cts.SensorIntegrationTests#testSensorsWithSeveralClients",
+    "android.hardware.cts.SensorIntegrationTests#testSensorsMovingRates",
+    "android.hardware.cts.SensorIntegrationTests#testAccelerometerAccelerometerStopping",
+    "android.hardware.cts.SensorIntegrationTests#testAccelerometerGyroscopeStopping",
+    "android.hardware.cts.SensorIntegrationTests#testAccelerometerMagneticFieldStopping",
+    "android.hardware.cts.SensorIntegrationTests#testGyroscopeAccelerometerStopping",
+    "android.hardware.cts.SensorIntegrationTests#testGyroscopeGyroscopeStopping",
+    "android.hardware.cts.SensorIntegrationTests#testGyroscopeMagneticFieldStopping",
+    "android.hardware.cts.SensorIntegrationTests#testMagneticFieldAccelerometerStopping",
+    "android.hardware.cts.SensorIntegrationTests#testMagneticFieldGyroscopeStopping",
+    "android.hardware.cts.SensorIntegrationTests#testMagneticFieldMagneticFieldStopping",
+    "android.hardware.cts.SingleSensorTests#testSensorProperties",
+    "android.hardware.cts.SingleSensorTests#testAccelerometer_fastest",
+    "android.hardware.cts.SingleSensorTests#testAccelerometer_100hz",
+    "android.hardware.cts.SingleSensorTests#testAccelerometer_200hz",
+    "android.hardware.cts.SingleSensorTests#testAccelerometer_50hz",
+    "android.hardware.cts.SingleSensorTests#testAccelerometer_25hz",
+    "android.hardware.cts.SingleSensorTests#testAccelerometer_15hz",
+    "android.hardware.cts.SingleSensorTests#testAccelerometer_10hz",
+    "android.hardware.cts.SingleSensorTests#testAccelerometer_5hz",
+    "android.hardware.cts.SingleSensorTests#testAccelerometer_1hz",
+    "android.hardware.cts.SingleSensorTests#testMagneticField_fastest",
+    "android.hardware.cts.SingleSensorTests#testMagneticField_200hz",
+    "android.hardware.cts.SingleSensorTests#testMagneticField_100hz",
+    "android.hardware.cts.SingleSensorTests#testMagneticField_50hz",
+    "android.hardware.cts.SingleSensorTests#testMagneticField_25hz",
+    "android.hardware.cts.SingleSensorTests#testMagneticField_15hz",
+    "android.hardware.cts.SingleSensorTests#testMagneticField_10hz",
+    "android.hardware.cts.SingleSensorTests#testMagneticField_5hz",
+    "android.hardware.cts.SingleSensorTests#testMagneticField_1hz",
+    "android.hardware.cts.SingleSensorTests#testOrientation_fastest",
+    "android.hardware.cts.SingleSensorTests#testOrientation_200hz",
+    "android.hardware.cts.SingleSensorTests#testOrientation_100hz",
+    "android.hardware.cts.SingleSensorTests#testOrientation_50hz",
+    "android.hardware.cts.SingleSensorTests#testOrientation_25hz",
+    "android.hardware.cts.SingleSensorTests#testOrientation_15hz",
+    "android.hardware.cts.SingleSensorTests#testOrientation_10hz",
+    "android.hardware.cts.SingleSensorTests#testOrientation_5hz",
+    "android.hardware.cts.SingleSensorTests#testOrientation_1hz",
+    "android.hardware.cts.SingleSensorTests#testGyroscope_fastest",
+    "android.hardware.cts.SingleSensorTests#testGyroscope_200hz",
+    "android.hardware.cts.SingleSensorTests#testGyroscope_100hz",
+    "android.hardware.cts.SingleSensorTests#testGyroscope_50hz",
+    "android.hardware.cts.SingleSensorTests#testGyroscope_25hz",
+    "android.hardware.cts.SingleSensorTests#testGyroscope_15hz",
+    "android.hardware.cts.SingleSensorTests#testGyroscope_10hz",
+    "android.hardware.cts.SingleSensorTests#testGyroscope_5hz",
+    "android.hardware.cts.SingleSensorTests#testGyroscope_1hz",
+    "android.hardware.cts.SingleSensorTests#testPressure_fastest",
+    "android.hardware.cts.SingleSensorTests#testPressure_200hz",
+    "android.hardware.cts.SingleSensorTests#testPressure_100hz",
+    "android.hardware.cts.SingleSensorTests#testPressure_50hz",
+    "android.hardware.cts.SingleSensorTests#testPressure_25hz",
+    "android.hardware.cts.SingleSensorTests#testPressure_15hz",
+    "android.hardware.cts.SingleSensorTests#testPressure_10hz",
+    "android.hardware.cts.SingleSensorTests#testPressure_5hz",
+    "android.hardware.cts.SingleSensorTests#testPressure_1hz",
+    "android.hardware.cts.SingleSensorTests#testGravity_fastest",
+    "android.hardware.cts.SingleSensorTests#testGravity_200hz",
+    "android.hardware.cts.SingleSensorTests#testGravity_100hz",
+    "android.hardware.cts.SingleSensorTests#testGravity_50hz",
+    "android.hardware.cts.SingleSensorTests#testGravity_25hz",
+    "android.hardware.cts.SingleSensorTests#testGravity_15hz",
+    "android.hardware.cts.SingleSensorTests#testGravity_10hz",
+    "android.hardware.cts.SingleSensorTests#testGravity_5hz",
+    "android.hardware.cts.SingleSensorTests#testGravity_1hz",
+    "android.hardware.cts.SingleSensorTests#testRotationVector_fastest",
+    "android.hardware.cts.SingleSensorTests#testRotationVector_200hz",
+    "android.hardware.cts.SingleSensorTests#testRotationVector_100hz",
+    "android.hardware.cts.SingleSensorTests#testRotationVector_50hz",
+    "android.hardware.cts.SingleSensorTests#testRotationVector_25hz",
+    "android.hardware.cts.SingleSensorTests#testRotationVector_15hz",
+    "android.hardware.cts.SingleSensorTests#testRotationVector_10hz",
+    "android.hardware.cts.SingleSensorTests#testRotationVector_5hz",
+    "android.hardware.cts.SingleSensorTests#testRotationVector_1hz",
+    "android.hardware.cts.SingleSensorTests#testMagneticFieldUncalibrated_fastest",
+    "android.hardware.cts.SingleSensorTests#testMagneticFieldUncalibrated_200hz",
+    "android.hardware.cts.SingleSensorTests#testMagneticFieldUncalibrated_100hz",
+    "android.hardware.cts.SingleSensorTests#testMagneticFieldUncalibrated_50hz",
+    "android.hardware.cts.SingleSensorTests#testMagneticFieldUncalibrated_25hz",
+    "android.hardware.cts.SingleSensorTests#testMagneticFieldUncalibrated_15hz",
+    "android.hardware.cts.SingleSensorTests#testMagneticFieldUncalibrated_10hz",
+    "android.hardware.cts.SingleSensorTests#testMagneticFieldUncalibrated_5hz",
+    "android.hardware.cts.SingleSensorTests#testMagneticFieldUncalibrated_1hz",
+    "android.hardware.cts.SingleSensorTests#testGameRotationVector_fastest",
+    "android.hardware.cts.SingleSensorTests#testGameRotationVector_200hz",
+    "android.hardware.cts.SingleSensorTests#testGameRotationVector_100hz",
+    "android.hardware.cts.SingleSensorTests#testGameRotationVector_50hz",
+    "android.hardware.cts.SingleSensorTests#testGameRotationVector_25hz",
+    "android.hardware.cts.SingleSensorTests#testGameRotationVector_15hz",
+    "android.hardware.cts.SingleSensorTests#testGameRotationVector_10hz",
+    "android.hardware.cts.SingleSensorTests#testGameRotationVector_5hz",
+    "android.hardware.cts.SingleSensorTests#testGameRotationVector_1hz",
+    "android.hardware.cts.SingleSensorTests#testGyroscopeUncalibrated_fastest",
+    "android.hardware.cts.SingleSensorTests#testGyroscopeUncalibrated_200hz",
+    "android.hardware.cts.SingleSensorTests#testGyroscopeUncalibrated_100hz",
+    "android.hardware.cts.SingleSensorTests#testGyroscopeUncalibrated_50hz",
+    "android.hardware.cts.SingleSensorTests#testGyroscopeUncalibrated_25hz",
+    "android.hardware.cts.SingleSensorTests#testGyroscopeUncalibrated_15hz",
+    "android.hardware.cts.SingleSensorTests#testGyroscopeUncalibrated_10hz",
+    "android.hardware.cts.SingleSensorTests#testGyroscopeUncalibrated_5hz",
+    "android.hardware.cts.SingleSensorTests#testGyroscopeUncalibrated_1hz",
+    "android.hardware.cts.SingleSensorTests#testGeomagneticRotationVector_fastest",
+    "android.hardware.cts.SingleSensorTests#testLinearAcceleration_200hz",
+    "android.hardware.cts.SingleSensorTests#testLinearAcceleration_100hz",
+    "android.hardware.cts.SingleSensorTests#testLinearAcceleration_50hz",
+    "android.hardware.cts.SingleSensorTests#testLinearAcceleration_25hz",
+    "android.hardware.cts.SingleSensorTests#testLinearAcceleration_15hz",
+    "android.hardware.cts.SingleSensorTests#testLinearAcceleration_10hz",
+    "android.hardware.cts.SingleSensorTests#testLinearAcceleration_5hz",
+    "android.hardware.cts.SingleSensorTests#testLinearAcceleration_1hz",
+    "android.hardware.cts.SensorTest#testValuesForAllSensors",
+    "android.hardware.cts.SensorTest#testSensorTimeStamps",
+    "android.hardware.cts.SensorTest#testBatchAndFlush",
+    "android.hardware.cts.SensorTest#testBatchAndFlushWithHandler"
+  ],
+  bug: 17675466
 },
 {
-  name: "android.media.cts.MediaPlayerFlakyNetworkTest",
-  bug: 15350295
+  description: "This test failed on hw decoder that doesn't output frame with the configured format.",
+  names: [
+    "android.media.cts.ImageReaderDecoderTest#testHwAVCDecode360pForFlexibleYuv"
+  ],
+  bug: 17144778
 },
 {
-  name: "android.media.cts.MediaPlayerTest",
-  bug: 15321806
+  description: "Roboto font tests are not yet known good on all devices",
+  names: [
+    "android.uirendering.cts.testclasses.FontRenderingTests"
+  ],
+  bug: 17109280
 },
 {
-  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.media.cts.AudioRecordTest#testAudioRecordOP",
-  bug: 15340791
-},
-{
-  name: "android.text.cts.BoringLayoutTest#testScale",
-  bug: 15134518
-},
-{
-  name: "android.media.cts.MediaRecorderTest#testOnErrorListener",
-  name: "android.media.cts.MediaRecorderTest#testOnInfoListener",
-  name: "android.media.cts.MediaRecorderTest#testRecorderAudio",
-  name: "android.media.cts.MediaRecorderTest#testRecordingAudioInRawFormats",
-  name: "android.media.cts.MediaRecorderTest#testSetMaxDuration",
-  bug: 15106730
-},
-{
-  name: "android.widget.cts.TextViewTest#testTextAttr",
-  bug: 15131296
-},
-{
-  name: "android.permission.cts.NoSystemFunctionPermissionTest#testSetWallpaper",
-  bug: 15383108
+  description: "android.keystore tests will replace these tests",
+  names: [
+    "com.android.org.conscrypt.MacTest#test_getInstance_OpenSSL_ENGINE",
+    "com.android.org.conscrypt.NativeCryptoTest#test_ENGINE_by_id_TestEngine",
+    "com.android.org.conscrypt.SignatureTest#test_getInstance_OpenSSL_ENGINE"
+  ],
+  bug: 18030049
 }
 ]
diff --git a/tests/expectations/unsupportedabis.txt b/tests/expectations/unsupportedabis.txt
new file mode 100644
index 0000000..7ad36825
--- /dev/null
+++ b/tests/expectations/unsupportedabis.txt
@@ -0,0 +1,15 @@
+[
+{
+  description: "Tests not supporting: arm64-v8a, x86_64, mips64",
+  names: [
+    "android.bionic.malloc#pvalloc_overflow",
+    "android.bionic.malloc#pvalloc_std",
+    "android.bionic.malloc#valloc_overflow",
+    "android.bionic.malloc#valloc_std",
+    "android.renderscriptlegacy.cts.LeakTest",
+    "android.renderscriptlegacy.cts.RSBase",
+    "android.renderscriptlegacy.cts.RSBaseCompute",
+    "android.renderscriptlegacy.cts.VersionTest"
+  ]
+}
+]
diff --git a/tests/jni/Android.mk b/tests/jni/Android.mk
deleted file mode 100644
index 0f7511e..0000000
--- a/tests/jni/Android.mk
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright (C) 2010 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)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libcts_jni
-
-# Don't include this package in any configuration by default.
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := \
-		CtsJniOnLoad.cpp \
-		android_os_cts_OSFeatures.cpp \
-		android_os_cts_FileUtils.cpp \
-		android_net_cts_NetlinkSocket.cpp
-
-LOCAL_C_INCLUDES := $(JNI_H_INCLUDE) 
-
-LOCAL_SHARED_LIBRARIES := libnativehelper liblog
-
-LOCAL_SRC_FILES += android_os_cts_CpuFeatures.cpp
-LOCAL_C_INCLUDES += ndk/sources/cpufeatures
-LOCAL_STATIC_LIBRARIES := cpufeatures
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/jni/CtsJniOnLoad.cpp b/tests/jni/CtsJniOnLoad.cpp
deleted file mode 100644
index 99ea37e..0000000
--- a/tests/jni/CtsJniOnLoad.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/* 
- * Copyright (C) 2010 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 <jni.h>
-#include <stdio.h>
-#include "android_net_cts_NetlinkSocket.h"
-
-extern int register_android_os_cts_CpuFeatures(JNIEnv*);
-
-extern int register_android_os_cts_OSFeatures(JNIEnv*);
-
-extern int register_android_os_cts_FileUtils(JNIEnv*);
-
-jint JNI_OnLoad(JavaVM *vm, void *reserved) {
-    JNIEnv *env = NULL;
-
-    if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
-        return JNI_ERR;
-    }
-
-    if (register_android_os_cts_CpuFeatures(env)) {
-        return JNI_ERR;
-    }
-
-    if (register_android_os_cts_OSFeatures(env)) {
-        return JNI_ERR;
-    }
-
-    if (register_android_os_cts_FileUtils(env)) {
-      return JNI_ERR;
-    }
-
-    if (register_android_net_cts_NetlinkSocket(env)) {
-        return JNI_ERR;
-    }
-
-    return JNI_VERSION_1_4;
-}
diff --git a/tests/jni/android_net_cts_NetlinkSocket.cpp b/tests/jni/android_net_cts_NetlinkSocket.cpp
deleted file mode 100644
index f2fc38f..0000000
--- a/tests/jni/android_net_cts_NetlinkSocket.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.
- */
-
-#include <jni.h>
-#include <stdio.h>
-#include <cutils/log.h>
-#include <asm/types.h>
-#include <sys/socket.h>
-#include <linux/netlink.h>
-#include <errno.h>
-#include <string.h>
-#include "JNIHelp.h"
-
-#include "android_net_cts_NetlinkSocket.h"
-
-static void android_net_cts_NetlinkSocket_create(JNIEnv* env, jclass,
-    jobject fileDescriptor)
-{
-    int sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
-    if (sock == -1) {
-        ALOGE("Can't create socket %s", strerror(errno));
-        jclass SocketException = env->FindClass("java/net/SocketException");
-        env->ThrowNew(SocketException, "Can't create socket");
-        return;
-    }
-    jniSetFileDescriptorOfFD(env, fileDescriptor, sock);
-}
-
-static int android_net_cts_NetlinkSocket_sendmsg(JNIEnv *e, jclass,
-    jobject fileDescriptor, jint pid, jbyteArray packet)
-{
-    void *bytes = (void *)e->GetByteArrayElements(packet, NULL);
-    uint32_t length = (uint32_t)e->GetArrayLength(packet);
-    struct sockaddr_nl snl;
-    struct iovec iov = {bytes, length};
-    struct msghdr msg = {&snl, sizeof(snl), &iov, 1, NULL, 0, 0};
-
-    memset(&snl, 0, sizeof(snl));
-    snl.nl_family = AF_NETLINK;
-    snl.nl_pid = pid;
-
-    int sock = jniGetFDFromFileDescriptor(e, fileDescriptor);
-    int retval = sendmsg(sock, &msg, 0);
-    e->ReleaseByteArrayElements(packet, (jbyte*)bytes, 0);
-    return retval;
-}
-
-
-static JNINativeMethod gMethods[] = {
-    {  "sendmsg", "(Ljava/io/FileDescriptor;I[B)I", (void *) android_net_cts_NetlinkSocket_sendmsg },
-    {  "create_native", "(Ljava/io/FileDescriptor;)V", (void *) android_net_cts_NetlinkSocket_create },
-};
-
-int register_android_net_cts_NetlinkSocket(JNIEnv* env)
-{
-    jclass clazz = env->FindClass("android/net/cts/NetlinkSocket");
-
-    return env->RegisterNatives(clazz, gMethods,
-            sizeof(gMethods) / sizeof(JNINativeMethod));
-}
diff --git a/tests/jni/android_net_cts_NetlinkSocket.h b/tests/jni/android_net_cts_NetlinkSocket.h
deleted file mode 100644
index d406892..0000000
--- a/tests/jni/android_net_cts_NetlinkSocket.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef __ANDROID_NET_CTS_H__
-#define __ANDROID_NET_CTS_H__
-
-int register_android_net_cts_NetlinkSocket(JNIEnv*);
-
-#endif /* __ANDROID_NET_CTS_H__ */
diff --git a/tests/jni/android_os_cts_CpuFeatures.cpp b/tests/jni/android_os_cts_CpuFeatures.cpp
deleted file mode 100644
index 053b44e..0000000
--- a/tests/jni/android_os_cts_CpuFeatures.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2010 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 <cpu-features.h>
-#include <jni.h>
-#include <string.h>
-
-jboolean android_os_cts_CpuFeatures_isArmCpu(JNIEnv* env, jobject thiz)
-{
-    AndroidCpuFamily cpuFamily = android_getCpuFamily();
-    return cpuFamily == ANDROID_CPU_FAMILY_ARM;
-}
-
-jboolean android_os_cts_CpuFeatures_isArm7Compatible(JNIEnv* env, jobject thiz)
-{
-    uint64_t cpuFeatures = android_getCpuFeatures();
-    return (cpuFeatures & ANDROID_CPU_ARM_FEATURE_ARMv7) == ANDROID_CPU_ARM_FEATURE_ARMv7;
-}
-
-jboolean android_os_cts_CpuFeatures_isMipsCpu(JNIEnv* env, jobject thiz)
-{
-    AndroidCpuFamily cpuFamily = android_getCpuFamily();
-    return cpuFamily == ANDROID_CPU_FAMILY_MIPS;
-}
-
-jboolean android_os_cts_CpuFeatures_isX86Cpu(JNIEnv* env, jobject thiz)
-{
-    AndroidCpuFamily cpuFamily = android_getCpuFamily();
-    return cpuFamily == ANDROID_CPU_FAMILY_X86;
-}
-
-static JNINativeMethod gMethods[] = {
-    {  "isArmCpu", "()Z",
-            (void *) android_os_cts_CpuFeatures_isArmCpu  },
-    {  "isArm7Compatible", "()Z",
-            (void *) android_os_cts_CpuFeatures_isArm7Compatible  },
-    {  "isMipsCpu", "()Z",
-            (void *) android_os_cts_CpuFeatures_isMipsCpu  },
-    {  "isX86Cpu", "()Z",
-            (void *) android_os_cts_CpuFeatures_isX86Cpu  },
-};
-
-int register_android_os_cts_CpuFeatures(JNIEnv* env)
-{
-    jclass clazz = env->FindClass("android/os/cts/CpuFeatures");
-
-    return env->RegisterNatives(clazz, gMethods,
-            sizeof(gMethods) / sizeof(JNINativeMethod));
-}
diff --git a/tests/jni/android_os_cts_FileUtils.cpp b/tests/jni/android_os_cts_FileUtils.cpp
deleted file mode 100644
index d78d26c..0000000
--- a/tests/jni/android_os_cts_FileUtils.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-/* 
- * 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.
- */
-
-#include <grp.h>
-#include <jni.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-static jclass gFileStatusClass;
-static jfieldID gFileStatusDevFieldID;
-static jfieldID gFileStatusInoFieldID;
-static jfieldID gFileStatusModeFieldID;
-static jfieldID gFileStatusNlinkFieldID;
-static jfieldID gFileStatusUidFieldID;
-static jfieldID gFileStatusGidFieldID;
-static jfieldID gFileStatusSizeFieldID;
-static jfieldID gFileStatusBlksizeFieldID;
-static jfieldID gFileStatusBlocksFieldID;
-static jfieldID gFileStatusAtimeFieldID;
-static jfieldID gFileStatusMtimeFieldID;
-static jfieldID gFileStatusCtimeFieldID;
-
-/*
- * Native methods used by
- * cts/tests/src/android/os/cts/FileUtils.java
- *
- * Copied from hidden API: frameworks/base/core/jni/android_os_FileUtils.cpp
- */
-
-jboolean android_os_cts_FileUtils_getFileStatus(JNIEnv* env, jobject thiz,
-        jstring path, jobject fileStatus, jboolean statLinks)
-{
-    const char* pathStr = env->GetStringUTFChars(path, NULL);
-    jboolean ret = false;
-    struct stat s;
-
-    int res = statLinks == true ? lstat(pathStr, &s) : stat(pathStr, &s);
-
-    if (res == 0) {
-        ret = true;
-        if (fileStatus != NULL) {
-            env->SetIntField(fileStatus, gFileStatusDevFieldID, s.st_dev);
-            env->SetIntField(fileStatus, gFileStatusInoFieldID, s.st_ino);
-            env->SetIntField(fileStatus, gFileStatusModeFieldID, s.st_mode);
-            env->SetIntField(fileStatus, gFileStatusNlinkFieldID, s.st_nlink);
-            env->SetIntField(fileStatus, gFileStatusUidFieldID, s.st_uid);
-            env->SetIntField(fileStatus, gFileStatusGidFieldID, s.st_gid);
-            env->SetLongField(fileStatus, gFileStatusSizeFieldID, s.st_size);
-            env->SetIntField(fileStatus, gFileStatusBlksizeFieldID, s.st_blksize);
-            env->SetLongField(fileStatus, gFileStatusBlocksFieldID, s.st_blocks);
-            env->SetLongField(fileStatus, gFileStatusAtimeFieldID, s.st_atime);
-            env->SetLongField(fileStatus, gFileStatusMtimeFieldID, s.st_mtime);
-            env->SetLongField(fileStatus, gFileStatusCtimeFieldID, s.st_ctime);
-        }
-    }
-
-    env->ReleaseStringUTFChars(path, pathStr);
-
-    return ret;
-}
-
-jstring android_os_cts_FileUtils_getUserName(JNIEnv* env, jobject thiz,
-        jint uid)
-{
-    struct passwd *pwd = getpwuid(uid);
-    return env->NewStringUTF(pwd->pw_name);
-}
-
-jstring android_os_cts_FileUtils_getGroupName(JNIEnv* env, jobject thiz,
-        jint gid)
-{
-    struct group *grp = getgrgid(gid);
-    return env->NewStringUTF(grp->gr_name);
-}
-
-jint android_os_cts_FileUtils_setPermissions(JNIEnv* env, jobject clazz,
-        jstring file, jint mode)
-{
-    const char *fileStr = env->GetStringUTFChars(file, NULL);
-    if (fileStr == NULL) {
-        return -1;
-    }
-
-    if (strlen(fileStr) <= 0) {
-        env->ReleaseStringUTFChars(file, fileStr);
-        return ENOENT;
-    } 
-
-    jint returnValue = chmod(fileStr, mode) == 0 ? 0 : errno;
-    env->ReleaseStringUTFChars(file, fileStr);
-    return returnValue;
-}
-
-static JNINativeMethod gMethods[] = {
-    {  "getFileStatus", "(Ljava/lang/String;Landroid/os/cts/FileUtils$FileStatus;Z)Z",
-            (void *) android_os_cts_FileUtils_getFileStatus  },
-    {  "getUserName", "(I)Ljava/lang/String;",
-            (void *) android_os_cts_FileUtils_getUserName  },
-    {  "getGroupName", "(I)Ljava/lang/String;",
-            (void *) android_os_cts_FileUtils_getGroupName  },
-    {  "setPermissions", "(Ljava/lang/String;I)I",
-            (void *) android_os_cts_FileUtils_setPermissions },
-};
-
-int register_android_os_cts_FileUtils(JNIEnv* env)
-{
-    jclass clazz = env->FindClass("android/os/cts/FileUtils");
-
-    gFileStatusClass = env->FindClass("android/os/cts/FileUtils$FileStatus");
-    gFileStatusDevFieldID = env->GetFieldID(gFileStatusClass, "dev", "I");
-    gFileStatusInoFieldID = env->GetFieldID(gFileStatusClass, "ino", "I");
-    gFileStatusModeFieldID = env->GetFieldID(gFileStatusClass, "mode", "I");
-    gFileStatusNlinkFieldID = env->GetFieldID(gFileStatusClass, "nlink", "I");
-    gFileStatusUidFieldID = env->GetFieldID(gFileStatusClass, "uid", "I");
-    gFileStatusGidFieldID = env->GetFieldID(gFileStatusClass, "gid", "I");
-    gFileStatusSizeFieldID = env->GetFieldID(gFileStatusClass, "size", "J");
-    gFileStatusBlksizeFieldID = env->GetFieldID(gFileStatusClass, "blksize", "I");
-    gFileStatusBlocksFieldID = env->GetFieldID(gFileStatusClass, "blocks", "J");
-    gFileStatusAtimeFieldID = env->GetFieldID(gFileStatusClass, "atime", "J");
-    gFileStatusMtimeFieldID = env->GetFieldID(gFileStatusClass, "mtime", "J");
-    gFileStatusCtimeFieldID = env->GetFieldID(gFileStatusClass, "ctime", "J");
-
-    return env->RegisterNatives(clazz, gMethods, 
-            sizeof(gMethods) / sizeof(JNINativeMethod)); 
-}
diff --git a/tests/jni/android_os_cts_OSFeatures.cpp b/tests/jni/android_os_cts_OSFeatures.cpp
deleted file mode 100644
index 4ee8454..0000000
--- a/tests/jni/android_os_cts_OSFeatures.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2013 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 <jni.h>
-#include <sys/prctl.h>
-
-jint android_os_cts_OSFeatures_getNoNewPrivs(JNIEnv* env, jobject thiz)
-{
-    return prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0);
-}
-
-jint android_os_cts_OSFeatures_prctlCapBsetRead(JNIEnv* env, jobject thiz, jint i)
-{
-    return prctl(PR_CAPBSET_READ, i, 0, 0, 0);
-}
-
-static JNINativeMethod gMethods[] = {
-    {  "getNoNewPrivs", "()I",
-            (void *) android_os_cts_OSFeatures_getNoNewPrivs  },
-    {  "prctlCapBsetRead", "(I)I",
-            (void *) android_os_cts_OSFeatures_prctlCapBsetRead },
-};
-
-int register_android_os_cts_OSFeatures(JNIEnv* env)
-{
-    jclass clazz = env->FindClass("android/os/cts/OSFeatures");
-
-    return env->RegisterNatives(clazz, gMethods,
-            sizeof(gMethods) / sizeof(JNINativeMethod));
-}
diff --git a/tests/print/Android.mk b/tests/print/Android.mk
new file mode 100644
index 0000000..fea7dc0
--- /dev/null
+++ b/tests/print/Android.mk
@@ -0,0 +1,36 @@
+# 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)
+
+##################################################
+# Build the print instrument library
+##################################################
+include $(CLEAR_VARS)
+LOCAL_MODULE := CtsPrintInstrument
+LOCAL_SRC_FILES := $(call all-subdir-java-files) \
+    src/android/print/cts/IPrivilegedOperations.aidl
+LOCAL_MODULE_TAGS := optional
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_JAVA_LIBRARY)
+
+# Copy the shell script to run the print instrument Jar to the CTS out folder.
+$(CTS_TESTCASES_OUT)/$(LOCAL_MODULE).jar : $(LOCAL_BUILT_MODULE) | $(ACP) 
+	$(copy-file-to-target)
+
+# Copy the built print instrument library Jar to the CTS out folder.
+$(CTS_TESTCASES_OUT)/print-instrument : $(LOCAL_PATH)/print-instrument | $(ACP)
+	$(copy-file-to-target)
+
diff --git a/tests/print/print-instrument b/tests/print/print-instrument
new file mode 100755
index 0000000..a79cb8a
--- /dev/null
+++ b/tests/print/print-instrument
@@ -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.
+
+# Script to start "print-instrument" on the device
+#
+# The script sets up an alternative dalvik cache when running as
+# non-root. Jar files needs to be dexopt'd to run in Dalvik. For
+# plain jar files, this is done at first use. shell user does not
+# have write permission to default system Dalvik cache so we
+# redirect to an alternative cache.
+
+RUN_BASE=/data/local/tmp
+
+# If not running as root, use an alternative dex cache.
+if [ ${USER_ID} -ne 0 ]; then
+  tmp_cache=${RUN_BASE}/dalvik-cache
+  if [ ! -d ${tmp_cache} ]; then
+    mkdir -p ${tmp_cache}
+  fi
+  export ANDROID_DATA=${RUN_BASE}
+fi
+
+# Run print-instrument.
+export CLASSPATH=${RUN_BASE}/CtsPrintInstrument.jar
+
+exec app_process ${RUN_BASE} android.print.cts.PrintInstrument ${@}
diff --git a/tests/print/src/android/print/cts/IPrivilegedOperations.aidl b/tests/print/src/android/print/cts/IPrivilegedOperations.aidl
new file mode 100644
index 0000000..93c8c3e
--- /dev/null
+++ b/tests/print/src/android/print/cts/IPrivilegedOperations.aidl
@@ -0,0 +1,21 @@
+/*
+ * 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.print.cts;
+
+interface IPrivilegedOperations {
+    boolean clearApplicationUserData(String packageName);
+}
diff --git a/tests/print/src/android/print/cts/PrintInstrument.java b/tests/print/src/android/print/cts/PrintInstrument.java
new file mode 100644
index 0000000..1c568a1
--- /dev/null
+++ b/tests/print/src/android/print/cts/PrintInstrument.java
@@ -0,0 +1,279 @@
+/*
+ * 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.print.cts;
+
+import android.app.ActivityManagerNative;
+import android.app.IActivityManager;
+import android.app.IInstrumentationWatcher;
+import android.app.Instrumentation;
+import android.app.UiAutomationConnection;
+import android.content.ComponentName;
+import android.content.pm.IPackageDataObserver;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.util.AndroidException;
+import android.view.IWindowManager;
+
+import com.android.internal.os.BaseCommand;
+
+import java.io.PrintStream;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public final class PrintInstrument extends BaseCommand {
+
+    private static final String ARG_PRIVILEGED_OPS = "ARG_PRIVILEGED_OPS";
+
+    private IActivityManager mAm;
+
+    public static void main(String[] args) {
+        PrintInstrument instrumenter = new PrintInstrument();
+        instrumenter.run(args);
+    }
+
+    @Override
+    public void onRun() throws Exception {
+        mAm = ActivityManagerNative.getDefault();
+        if (mAm == null) {
+            System.err.println(NO_SYSTEM_ERROR_CODE);
+            throw new AndroidException("Can't connect to activity manager;"
+                    + " is the system running?");
+        }
+
+        String op = nextArgRequired();
+
+        if (op.equals("instrument")) {
+            runInstrument();
+        } else {
+            showError("Error: unknown command '" + op + "'");
+        }
+    }
+
+    @Override
+    public void onShowUsage(PrintStream out) {
+        /* do nothing */
+    }
+
+    @SuppressWarnings("deprecation")
+    private void runInstrument() throws Exception {
+        String profileFile = null;
+        boolean wait = false;
+        boolean rawMode = false;
+        boolean no_window_animation = false;
+        int userId = UserHandle.USER_CURRENT;
+        Bundle args = new Bundle();
+        String argKey = null, argValue = null;
+        IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
+
+        String opt;
+        while ((opt=nextOption()) != null) {
+            if (opt.equals("-p")) {
+                profileFile = nextArgRequired();
+            } else if (opt.equals("-w")) {
+                wait = true;
+            } else if (opt.equals("-r")) {
+                rawMode = true;
+            } else if (opt.equals("-e")) {
+                argKey = nextArgRequired();
+                argValue = nextArgRequired();
+                args.putString(argKey, argValue);
+            } else if (opt.equals("--no_window_animation")
+                    || opt.equals("--no-window-animation")) {
+                no_window_animation = true;
+            } else if (opt.equals("--user")) {
+                userId = parseUserArg(nextArgRequired());
+            } else {
+                System.err.println("Error: Unknown option: " + opt);
+                return;
+            }
+        }
+
+        if (userId == UserHandle.USER_ALL) {
+            System.err.println("Error: Can't start instrumentation with user 'all'");
+            return;
+        }
+
+        String cnArg = nextArgRequired();
+        ComponentName cn = ComponentName.unflattenFromString(cnArg);
+        if (cn == null) throw new IllegalArgumentException("Bad component name: " + cnArg);
+
+        InstrumentationWatcher watcher = null;
+        UiAutomationConnection connection = null;
+        if (wait) {
+            watcher = new InstrumentationWatcher();
+            watcher.setRawOutput(rawMode);
+            connection = new UiAutomationConnection();
+        }
+
+        float[] oldAnims = null;
+        if (no_window_animation) {
+            oldAnims = wm.getAnimationScales();
+            wm.setAnimationScale(0, 0.0f);
+            wm.setAnimationScale(1, 0.0f);
+        }
+
+        args.putIBinder(ARG_PRIVILEGED_OPS, new PrivilegedOperations(mAm));
+
+        if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher, connection, userId, null)) {
+            throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString());
+        }
+
+        if (watcher != null) {
+            if (!watcher.waitForFinish()) {
+                System.out.println("INSTRUMENTATION_ABORTED: System has crashed.");
+            }
+        }
+
+        if (oldAnims != null) {
+            wm.setAnimationScales(oldAnims);
+        }
+    }
+
+    private int parseUserArg(String arg) {
+        int userId;
+        if ("all".equals(arg)) {
+            userId = UserHandle.USER_ALL;
+        } else if ("current".equals(arg) || "cur".equals(arg)) {
+            userId = UserHandle.USER_CURRENT;
+        } else {
+            userId = Integer.parseInt(arg);
+        }
+        return userId;
+    }
+
+    private class InstrumentationWatcher extends IInstrumentationWatcher.Stub {
+        private boolean mFinished = false;
+        private boolean mRawMode = false;
+
+        /**
+         * Set or reset "raw mode".  In "raw mode", all bundles are dumped.  In "pretty mode",
+         * if a bundle includes Instrumentation.REPORT_KEY_STREAMRESULT, just print that.
+         * @param rawMode true for raw mode, false for pretty mode.
+         */
+        public void setRawOutput(boolean rawMode) {
+            mRawMode = rawMode;
+        }
+
+        @Override
+        public void instrumentationStatus(ComponentName name, int resultCode, Bundle results) {
+            synchronized (this) {
+                // pretty printer mode?
+                String pretty = null;
+                if (!mRawMode && results != null) {
+                    pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT);
+                }
+                if (pretty != null) {
+                    System.out.print(pretty);
+                } else {
+                    if (results != null) {
+                        for (String key : results.keySet()) {
+                            System.out.println(
+                                    "INSTRUMENTATION_STATUS: " + key + "=" + results.get(key));
+                        }
+                    }
+                    System.out.println("INSTRUMENTATION_STATUS_CODE: " + resultCode);
+                }
+                notifyAll();
+            }
+        }
+
+        @Override
+        public void instrumentationFinished(ComponentName name, int resultCode,
+                Bundle results) {
+            synchronized (this) {
+                // pretty printer mode?
+                String pretty = null;
+                if (!mRawMode && results != null) {
+                    pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT);
+                }
+                if (pretty != null) {
+                    System.out.println(pretty);
+                } else {
+                    if (results != null) {
+                        for (String key : results.keySet()) {
+                            System.out.println(
+                                    "INSTRUMENTATION_RESULT: " + key + "=" + results.get(key));
+                        }
+                    }
+                    System.out.println("INSTRUMENTATION_CODE: " + resultCode);
+                }
+                mFinished = true;
+                notifyAll();
+            }
+        }
+
+        public boolean waitForFinish() {
+            synchronized (this) {
+                while (!mFinished) {
+                    try {
+                        if (!mAm.asBinder().pingBinder()) {
+                            return false;
+                        }
+                        wait(1000);
+                    } catch (InterruptedException e) {
+                        throw new IllegalStateException(e);
+                    }
+                }
+            }
+            return true;
+        }
+    }
+
+    private static final class PrivilegedOperations extends IPrivilegedOperations.Stub {
+        private final IActivityManager mAm;
+
+        public PrivilegedOperations(IActivityManager am) {
+            mAm = am;
+        }
+
+        @Override
+        public boolean clearApplicationUserData(final String clearedPackageName)
+                throws RemoteException {
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                final AtomicBoolean success = new AtomicBoolean();
+                final CountDownLatch completionLatch = new CountDownLatch(1);
+
+                mAm.clearApplicationUserData(clearedPackageName,
+                        new IPackageDataObserver.Stub() {
+                            @Override
+                            public void onRemoveCompleted(String packageName, boolean succeeded) {
+                                if (clearedPackageName.equals(packageName) && succeeded) {
+                                    success.set(true);
+                                } else {
+                                    success.set(false);
+                                }
+                                completionLatch.countDown();
+                            }
+                }, UserHandle.USER_CURRENT);
+
+                try {
+                    completionLatch.await();
+                } catch (InterruptedException ie) {
+                    /* ignore */
+                }
+
+                return success.get();
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+    }
+}
diff --git a/tests/res/anim/lineartest.xml b/tests/res/anim/lineartest.xml
deleted file mode 100644
index 7a41628..0000000
--- a/tests/res/anim/lineartest.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2008 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.
- -->
-<screenplay>
-     <paint id="paint" antiAlias="true">
-         <color id="col" color="gray"/>
-     </paint>
-     <event kind="onLoad">
-         <add id="addPaint" use="paint"/>
-         <text y="15" text="hello"/>
-     </event>
-     <event kind="keyPress" code="up">
-         <apply scope="addPaint">
-             <set target="paint" field="linearText" to="true"/>
-             <set target="col" field="color" to="black"/>
-             <animate target="paint" id="grow" field="textSize" from="12" to="15" dur=".25"/>
-         </apply>
-     </event>
-     <event kind="onEnd" target="grow">
-         <apply scope="addPaint">
-             <set target="paint" field="linearText" to="false"/>
-         </apply>
-     </event>
-     <event kind="keyPress" code="down">
-         <apply scope="addPaint">
-             <set target="col" field="color" to="gray"/>
-             <animate target="paint" id="shrink" field="textSize" from="15" to="12" dur=".25"/>
-         </apply>
-     </event>
-     <event kind="onEnd" target="shrink">
-         <apply scope="addPaint">
-             <set target="paint" field="linearText" to="false"/>
-         </apply>
-     </event>
- </screenplay>
diff --git a/tests/res/anim/move_ani.xml b/tests/res/anim/move_ani.xml
deleted file mode 100644
index b691c0d..0000000
--- a/tests/res/anim/move_ani.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<translate xmlns:android="http://schemas.android.com/apk/res/android"
-           android:fromXDelta="0"
-           android:toXDelta="4"
-           android:duration="2000"
-           android:interpolator="@anim/move_cycle" />
diff --git a/tests/res/anim/move_cycle.xml b/tests/res/anim/move_cycle.xml
deleted file mode 100644
index 2e2233a..0000000
--- a/tests/res/anim/move_cycle.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<cycleInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:cycles="20" />
diff --git a/tests/res/anim/movie_test.xml b/tests/res/anim/movie_test.xml
deleted file mode 100644
index dcebd16..0000000
--- a/tests/res/anim/movie_test.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2008 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.
- -->
-<screenplay>
-    <event kind="onLoad">
-        <movie src="lineartest.xml"/>
-    </event>
-</screenplay>
diff --git a/tests/res/drawable/statelistdrawable.xml b/tests/res/drawable/statelistdrawable.xml
deleted file mode 100644
index 9d9aa3b0..0000000
--- a/tests/res/drawable/statelistdrawable.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2009 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.
- -->
-
-<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"/>
-</selector>
-
diff --git a/tests/res/layout-land/mediaplayer.xml b/tests/res/layout-land/mediaplayer.xml
deleted file mode 100644
index 5dafdb9..0000000
--- a/tests/res/layout-land/mediaplayer.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2009 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.
- -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="horizontal"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <SurfaceView android:id="@+id/surface"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_weight="1">
-    </SurfaceView>
-
-    <SurfaceView android:id="@+id/surface2"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_weight="1">
-    </SurfaceView>
-
-    <SurfaceView android:id="@+id/surface3"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_weight="1">
-    </SurfaceView>
-
-</LinearLayout>
diff --git a/tests/res/layout/alertdialog_custom_title2.xml b/tests/res/layout/alertdialog_custom_title2.xml
deleted file mode 100644
index 51c154d..0000000
--- a/tests/res/layout/alertdialog_custom_title2.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<TextView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/alertdialog_custom_title"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:gravity="center_vertical|center_horizontal"
-    android:text="@string/hello_android"/>
diff --git a/tests/res/layout/animation_layout.xml b/tests/res/layout/animation_layout.xml
deleted file mode 100644
index 13228d1..0000000
--- a/tests/res/layout/animation_layout.xml
+++ /dev/null
@@ -1,66 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:id="@+id/layout"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content">
-
-    <ImageButton android:id="@+id/scenery"
-        android:src="@drawable/scenery"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_centerHorizontal="true"/>
-
-    <ImageButton android:id="@+id/start"
-        android:src="@drawable/start"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_centerHorizontal="true"
-        android:layout_below="@id/scenery"/>
-
-    <TextView android:id="@+id/explain"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textSize="18sp"
-        android:autoText="true"
-        android:capitalize="sentences"
-        android:text="@string/explain"
-        android:layout_centerHorizontal="true"
-        android:layout_below="@id/start"/>
-
-    <LinearLayout android:id="@+id/button_layout"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:orientation="horizontal"
-        android:layout_centerHorizontal="true"
-        android:layout_alignParentBottom="true">
-
-        <ImageButton android:id="@+id/pass"
-            android:src="@drawable/pass"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginRight="20px"/>
-
-        <ImageButton android:id="@+id/failed"
-            android:src="@drawable/failed"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginLeft="40px"/>
-
-    </LinearLayout>
-
-</RelativeLayout>
diff --git a/tests/res/layout/app_another.xml b/tests/res/layout/app_another.xml
deleted file mode 100644
index f4574a2..0000000
--- a/tests/res/layout/app_another.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2008 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.
- -->
-
-<!-- Demonstrates receiving activity results.
-     See corresponding Java code com.android.sdk.app.ReceiveResult.java. -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
-    android:gravity="center_horizontal"
-    android:layout_width="match_parent" android:layout_height="match_parent">
-
-    <TextView
-        android:layout_width="match_parent" android:layout_height="wrap_content"
-        android:layout_weight="0"
-        android:paddingBottom="4dip"
-        android:text="@string/forwarding"/>
-
-    <Button android:id="@+id/back"
-        android:layout_width="wrap_content" android:layout_height="wrap_content"
-        android:text="@string/back">
-        <requestFocus />
-    </Button>
-
-</LinearLayout>
-
diff --git a/tests/res/layout/autocompletetextview_layout.xml b/tests/res/layout/autocompletetextview_layout.xml
deleted file mode 100644
index be1d284..0000000
--- a/tests/res/layout/autocompletetextview_layout.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
-    android:orientation="vertical"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content">
-
-    <TextView android:id="@+id/autocompletetv_title"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:text="@string/notify" />
-
-    <AutoCompleteTextView android:id="@+id/autocompletetv_edit"
-        android:completionThreshold="1"
-        android:completionHint="@string/tabs_1"
-        android:layout_width="match_parent" 
-        android:layout_height="wrap_content" />
-</LinearLayout>
diff --git a/tests/res/layout/datepicker.xml b/tests/res/layout/datepicker.xml
deleted file mode 100644
index 6a7b51c..0000000
--- a/tests/res/layout/datepicker.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?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.
--->
-    <DatePicker android:id="@+id/datePicker1"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:spinnersShown="false"
-                xmlns:android="http://schemas.android.com/apk/res/android">
-    </DatePicker>
diff --git a/tests/res/layout/dialog_stub_layout.xml b/tests/res/layout/dialog_stub_layout.xml
deleted file mode 100644
index b0a8861..0000000
--- a/tests/res/layout/dialog_stub_layout.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
-        android:layout_width="match_parent" 
-        android:layout_height="match_parent"
-        >
-</LinearLayout>
diff --git a/tests/res/layout/digitalclock_layout.xml b/tests/res/layout/digitalclock_layout.xml
deleted file mode 100644
index cbdb84d..0000000
--- a/tests/res/layout/digitalclock_layout.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<com.android.cts.stub.alarmclock.DigitalClock android:id="@+id/digitalClock"
-     xmlns:android="http://schemas.android.com/apk/res/android"
-     android:layout_width="wrap_content"
-     android:layout_height="208dip"
-     android:gravity="center">
-     <!-- Includes vertical padding so animated background doesn't
-          stretch much -->
-     <TextView android:id="@+id/timeDisplay"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:textSize="64sp"
-         android:paddingRight="4dip"
-         android:paddingTop="48dip"
-         android:paddingBottom="48dip"/>
-     <LinearLayout android:id="@+id/am_pm"
-         android:layout_width="wrap_content"
-         android:layout_height="wrap_content"
-         android:orientation="vertical">
-         <TextView android:id="@+id/am"
-             android:layout_width="wrap_content"
-             android:layout_height="wrap_content"
-             android:layout_marginTop="-7dp"
-             android:text="@string/am"
-             android:textSize="28sp"/>
-         <TextView android:id="@+id/pm"
-             android:layout_width="wrap_content"
-             android:layout_height="wrap_content"
-             android:layout_marginTop="-4dp"
-             android:text="@string/pm"
-             android:textSize="28sp"/>
-     </LinearLayout>
-</com.android.cts.stub.alarmclock.DigitalClock>
diff --git a/tests/res/layout/framelayout_layout.xml b/tests/res/layout/framelayout_layout.xml
deleted file mode 100644
index c6d1a83..0000000
--- a/tests/res/layout/framelayout_layout.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2008 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.
- -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:id="@+id/framelayout_container"
-                android:background="@drawable/red"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:layout_gravity="bottom"
-                android:orientation="vertical">
-
-    <FrameLayout
-        android:layout_width="100dip"
-        android:layout_height="100dip"
-        android:background="@drawable/yellow"
-        android:id="@+id/framelayout">
-    </FrameLayout>
-
-    <FrameLayout
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:background="@drawable/yellow"
-        android:id="@+id/framelayout_measureall">
-
-        <TextView android:id="@+id/framelayout_textview"
-            android:background="@drawable/blue"
-            android:layout_width="60dip"
-            android:layout_height="30dip"
-            android:text="@string/hello_world"/>
-
-        <Button android:id="@+id/framelayout_button"
-            android:layout_width="50dip"
-            android:layout_height="15dip"
-            android:text="@string/go"/>
-
-    </FrameLayout>
-
-</LinearLayout>
diff --git a/tests/res/layout/home_activity.xml b/tests/res/layout/home_activity.xml
deleted file mode 100644
index 49174da..0000000
--- a/tests/res/layout/home_activity.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:orientation="vertical"
-              android:layout_width="match_parent"
-              android:layout_height="match_parent">
-      <Button android:text="@string/holo_test"
-              android:id="@+id/button_holo"
-              android:onClick="onHoloTestClick"
-              android:layout_width="wrap_content"
-              android:layout_height="wrap_content">
-      </Button>
-      <Button android:text="@string/holo_generator"
-              android:id="@+id/button2"
-              android:onClick="onHoloGenClick"
-              android:layout_width="wrap_content"
-              android:layout_height="wrap_content">
-      </Button>
-      <Button android:text="@string/holo_light_test"
-              android:id="@+id/button3"
-              android:onClick="onHoloLightTestClick"
-              android:layout_width="wrap_content"
-              android:layout_height="wrap_content">
-      </Button>
-      <Button android:text="@string/holo_light_generator"
-              android:id="@+id/button4"
-              android:onClick="onHoloLightGenClick"
-              android:layout_width="wrap_content"
-              android:layout_height="wrap_content">
-      </Button>
-</LinearLayout>
diff --git a/tests/res/layout/imageview_layout.xml b/tests/res/layout/imageview_layout.xml
deleted file mode 100644
index d1e17fa..0000000
--- a/tests/res/layout/imageview_layout.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * Copyright (C) 2008 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.
- */
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <ImageView
-        android:id="@+id/imageview"
-        android:layout_width="320px"
-        android:layout_height="240px"/>
-</LinearLayout>
-
diff --git a/tests/res/layout/list_activity_layout.xml b/tests/res/layout/list_activity_layout.xml
deleted file mode 100644
index 0486cf0..0000000
--- a/tests/res/layout/list_activity_layout.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2008 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.
- -->
-
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@android:id/text1"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-/>
diff --git a/tests/res/layout/popupwindow.xml b/tests/res/layout/popupwindow.xml
deleted file mode 100644
index e6b0aed..0000000
--- a/tests/res/layout/popupwindow.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:orientation="vertical">
-
-    <TextView android:id="@+id/anchor_upper"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:text="@string/text_view_hint"
-        android:layout_weight="1"/>
-
-    <LinearLayout android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_weight="1">
-
-        <TextView android:id="@+id/anchor_middle_left"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:text="@string/text_view_hint"
-            android:layout_weight="1"/>
-
-        <TextView android:id="@+id/anchor_middle_right"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:text="@string/text_view_hint"
-            android:layout_weight="1"/>
-
-    </LinearLayout>
-
-    <TextView android:id="@+id/anchor_lower"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:text="@string/text_view_hint"
-        android:layout_weight="1"/>
-
-</LinearLayout>
diff --git a/tests/res/layout/seekbar.xml b/tests/res/layout/seekbar.xml
deleted file mode 100644
index c6f5246..0000000
--- a/tests/res/layout/seekbar.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-     <SeekBar android:id="@+id/seekBar"
-         android:layout_width="match_parent"
-         android:layout_height="wrap_content"
-         android:max="100"
-         android:progress="50"
-         android:secondaryProgress="75" />
-
-</LinearLayout>
diff --git a/tests/res/layout/simple_spinner_item.xml b/tests/res/layout/simple_spinner_item.xml
deleted file mode 100644
index 247bffa..0000000
--- a/tests/res/layout/simple_spinner_item.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-<TextView xmlns:android="http://schemas.android.com/apk/res/android" 
-    android:id="@android:id/text1"
-    style="?android:attr/spinnerItemStyle"
-    android:singleLine="true"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content" />
diff --git a/tests/res/layout/surface_view.xml b/tests/res/layout/surface_view.xml
deleted file mode 100644
index f410544..0000000
--- a/tests/res/layout/surface_view.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <SurfaceView
-        android:id="@+id/surface_view"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"/>
-
-</LinearLayout>
diff --git a/tests/res/layout/textview_autotext.xml b/tests/res/layout/textview_autotext.xml
deleted file mode 100644
index 9a1e9ef..0000000
--- a/tests/res/layout/textview_autotext.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content">
-
-    <TextView android:id="@+id/autotext_default"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"/>
-
-    <TextView android:id="@+id/autotext_false"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:autoText="false"/>
-
-    <TextView android:id="@+id/autotext_true"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:autoText="true"/>
-
-</LinearLayout>
diff --git a/tests/res/layout/textview_buffertype.xml b/tests/res/layout/textview_buffertype.xml
deleted file mode 100644
index 33b0d20..0000000
--- a/tests/res/layout/textview_buffertype.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content">
-
-    <TextView android:id="@+id/buffertype_default"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"/>
-
-    <TextView android:id="@+id/buffertype_normal"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:bufferType="normal"/>
-
-    <TextView android:id="@+id/buffertype_spannable"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:bufferType="spannable"/>
-
-    <TextView android:id="@+id/buffertype_editable"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:bufferType="editable"/>
-
-</LinearLayout>
diff --git a/tests/res/layout/textview_capitalize.xml b/tests/res/layout/textview_capitalize.xml
deleted file mode 100644
index 4b80ce0..0000000
--- a/tests/res/layout/textview_capitalize.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content">
-
-    <TextView android:id="@+id/capitalize_default"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:editable="true"/>
-
-    <TextView android:id="@+id/capitalize_none"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:capitalize="none"/>
-
-    <TextView android:id="@+id/capitalize_sentences"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:capitalize="sentences"/>
-
-    <TextView android:id="@+id/capitalize_words"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:capitalize="words"/>
-
-    <TextView android:id="@+id/capitalize_characters"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:capitalize="characters"/>
-
-</LinearLayout>
diff --git a/tests/res/layout/textview_content.xml b/tests/res/layout/textview_content.xml
deleted file mode 100644
index 189f812..0000000
--- a/tests/res/layout/textview_content.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content">
-
-    <TextView android:id="@+id/text_default"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"/>
-
-    <TextView android:id="@+id/text_resid"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:text="@string/text_view_hello"/>
-
-</LinearLayout>
diff --git a/tests/res/layout/textview_digits.xml b/tests/res/layout/textview_digits.xml
deleted file mode 100644
index 2a0d470..0000000
--- a/tests/res/layout/textview_digits.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content">
-
-    <TextView android:id="@+id/digits_default"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:editable="true"/>
-
-    <TextView android:id="@+id/digits_hex"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:digits="0123456789ABCDEFabcdef.-"/>
-
-    <TextView android:id="@+id/digits_blank"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:digits=""/>
-
-</LinearLayout>
diff --git a/tests/res/layout/textview_ems.xml b/tests/res/layout/textview_ems.xml
deleted file mode 100644
index a169cb0..0000000
--- a/tests/res/layout/textview_ems.xml
+++ /dev/null
@@ -1,97 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content">
-
-    <TextView android:id="@+id/ems_default"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:scrollHorizontally="true"/>
-
-    <TextView android:id="@+id/ems_huge"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:ems="60"
-        android:text="@string/explain"
-        android:scrollHorizontally="true"/>
-
-    <TextView android:id="@+id/ems_tiny"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:ems="1"
-        android:text="@string/explain"
-        android:scrollHorizontally="true"/>
-
-    <TextView android:id="@+id/ems_zero"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:ems="0"
-        android:text="@string/explain"
-        android:scrollHorizontally="true"/>
-
-    <TextView android:id="@+id/minEms_tiny"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:minEms="1"
-        android:scrollHorizontally="true"/>
-
-    <TextView android:id="@+id/minEms_huge"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:minEms="1000"
-        android:scrollHorizontally="true"/>
-
-    <TextView android:id="@+id/minEms_zero"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:minEms="0"
-        android:scrollHorizontally="true"/>
-
-    <TextView android:id="@+id/maxEms_tiny"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:maxEms="1"
-        android:scrollHorizontally="true"/>
-
-    <TextView android:id="@+id/maxEms_huge"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:maxEms="1000"
-        android:scrollHorizontally="true"/>
-
-    <TextView android:id="@+id/maxEms_zero"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:maxEms="0"
-        android:scrollHorizontally="true"/>
-
-    <TextView android:id="@+id/minEms_maxEms_correct"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:maxEms="60"
-        android:minEms="10"
-        android:scrollHorizontally="true"/>
-
-    <TextView android:id="@+id/minEms_maxEms_wrong"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:maxEms="10"
-        android:minEms="60"
-        android:scrollHorizontally="true"/>
-
-</LinearLayout>
diff --git a/tests/res/layout/textview_inputmethod_blank.xml b/tests/res/layout/textview_inputmethod_blank.xml
deleted file mode 100644
index 4420611..0000000
--- a/tests/res/layout/textview_inputmethod_blank.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content">
-
-    <TextView android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:inputMethod=""/>
-
-</LinearLayout>
diff --git a/tests/res/layout/textview_inputmethod_builtin.xml b/tests/res/layout/textview_inputmethod_builtin.xml
deleted file mode 100644
index e09a0ea..0000000
--- a/tests/res/layout/textview_inputmethod_builtin.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content">
-
-    <TextView android:id="@+id/inputMethod_builtIn_digits"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:inputMethod="android.text.method.DigitsKeyListener"/>
-
-    <TextView android:id="@+id/inputMethod_builtIn_datetime"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:inputMethod="android.text.method.DateTimeKeyListener"/>
-
-</LinearLayout>
diff --git a/tests/res/layout/textview_inputmethod_notexist.xml b/tests/res/layout/textview_inputmethod_notexist.xml
deleted file mode 100644
index 9030b62..0000000
--- a/tests/res/layout/textview_inputmethod_notexist.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content">
-
-    <TextView android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:inputMethod="android.text.method.NotExistKeyListener"/>
-
-</LinearLayout>
diff --git a/tests/res/layout/textview_layout.xml b/tests/res/layout/textview_layout.xml
deleted file mode 100644
index 108e3f0..0000000
--- a/tests/res/layout/textview_layout.xml
+++ /dev/null
@@ -1,219 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:id="@+id/layout_textviewtest">
-
-    <ScrollView android:layout_width="match_parent"
-            android:layout_height="match_parent">
-
-        <LinearLayout android:orientation="vertical"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent">
-
-            <TextView android:id="@+id/textview_textAttr"
-                    android:text="@string/text_view_hello"
-                    android:textColor="@drawable/black"
-                    android:textColorHighlight="@drawable/yellow"
-                    android:textColorHint="@drawable/red"
-                    android:textColorLink="@drawable/blue"
-                    android:textScaleX="1.2"
-                    android:typeface="normal"
-                    android:textSize="20px"
-                    android:textStyle="normal"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"/>
-        
-            <TextView android:id="@+id/textview_password"
-                    android:password="true"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"/>
-        
-            <TextView android:id="@+id/textview_singleLine"
-                    android:singleLine="true"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"/>
-        
-            <TextView android:id="@+id/textview_text"
-                    android:text="@string/text_view_hello"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"/>
-
-            <TextView android:id="@+id/textview_text_two_lines"
-                    android:text="@string/text_view_hello_two_lines"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"/>
-
-            <android.widget.cts.MockTextView
-                    android:id="@+id/mock_textview_left"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:requiresFadingEdge="horizontal"
-                    android:singleLine="true"
-                    android:text="@string/long_text"
-                    android:gravity="left"
-                    />
-
-            <android.widget.cts.MockTextView
-                    android:id="@+id/mock_textview_right"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:requiresFadingEdge="horizontal"
-                    android:singleLine="true"
-                    android:text="@string/long_text"
-                    android:gravity="right"
-                    />
-
-            <android.widget.cts.MockTextView
-                    android:id="@+id/mock_textview_center"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:requiresFadingEdge="horizontal"
-                    android:singleLine="true"
-                    android:text="@string/long_text"
-                    android:gravity="center"
-                    />
-        </LinearLayout>
-
-    </ScrollView>
-
-    <TextView android:id="@+id/textview_ltr"
-              android:layout_height="wrap_content"
-              android:layout_width="wrap_content"/>
-
-    <TextView android:id="@+id/textview_rtl"
-              android:layout_height="wrap_content"
-              android:layout_width="wrap_content"/>
-
-    <TextView android:id="@+id/textview_drawable_1_1"
-              android:layout_height="wrap_content"
-              android:layout_width="wrap_content"
-              android:drawableLeft="@drawable/icon_blue"
-              android:drawableRight="@drawable/icon_red"
-              android:drawableTop="@drawable/icon_green"
-              android:drawableBottom="@drawable/icon_yellow"
-            />
-
-    <TextView android:id="@+id/textview_drawable_1_2"
-              android:layout_height="wrap_content"
-              android:layout_width="wrap_content"
-              android:drawableLeft="@drawable/icon_blue"
-              android:drawableRight="@drawable/icon_red"
-              android:drawableTop="@drawable/icon_green"
-              android:drawableBottom="@drawable/icon_yellow"
-              android:layoutDirection="rtl"
-            />
-
-    <TextView android:id="@+id/textview_drawable_2_1"
-              android:layout_height="wrap_content"
-              android:layout_width="wrap_content"
-              android:drawableStart="@drawable/icon_blue"
-              android:drawableEnd="@drawable/icon_red"
-              android:drawableTop="@drawable/icon_green"
-              android:drawableBottom="@drawable/icon_yellow"
-            />
-
-    <TextView android:id="@+id/textview_drawable_2_2"
-              android:layout_height="wrap_content"
-              android:layout_width="wrap_content"
-              android:drawableStart="@drawable/icon_blue"
-              android:drawableEnd="@drawable/icon_red"
-              android:drawableTop="@drawable/icon_green"
-              android:drawableBottom="@drawable/icon_yellow"
-              android:layoutDirection="rtl"
-            />
-
-    <TextView android:id="@+id/textview_drawable_3_1"
-              android:layout_height="wrap_content"
-              android:layout_width="wrap_content"
-              android:drawableLeft="@drawable/icon_black"
-              android:drawableRight="@drawable/icon_black"
-              android:drawableStart="@drawable/icon_blue"
-              android:drawableEnd="@drawable/icon_red"
-              android:drawableTop="@drawable/icon_green"
-              android:drawableBottom="@drawable/icon_yellow"
-            />
-
-    <TextView android:id="@+id/textview_drawable_3_2"
-              android:layout_height="wrap_content"
-              android:layout_width="wrap_content"
-              android:drawableLeft="@drawable/icon_black"
-              android:drawableRight="@drawable/icon_black"
-              android:drawableStart="@drawable/icon_blue"
-              android:drawableEnd="@drawable/icon_red"
-              android:drawableTop="@drawable/icon_green"
-              android:drawableBottom="@drawable/icon_yellow"
-              android:layoutDirection="rtl"
-            />
-
-
-    <LinearLayout android:orientation="vertical"
-                  android:layout_width="match_parent"
-                  android:layout_height="match_parent"
-                  android:layoutDirection="ltr">
-
-        <TextView android:id="@+id/textview_drawable_4_1"
-                  android:layout_height="wrap_content"
-                  android:layout_width="wrap_content"
-                  android:drawableStart="@drawable/icon_blue"
-                  android:drawableEnd="@drawable/icon_red"
-                  android:drawableTop="@drawable/icon_green"
-                  android:drawableBottom="@drawable/icon_yellow"
-                />
-
-        <TextView android:id="@+id/textview_drawable_5_1"
-                  android:layout_height="wrap_content"
-                  android:layout_width="wrap_content"
-                  android:drawableLeft="@drawable/icon_black"
-                  android:drawableRight="@drawable/icon_black"
-                  android:drawableStart="@drawable/icon_blue"
-                  android:drawableEnd="@drawable/icon_red"
-                  android:drawableTop="@drawable/icon_green"
-                  android:drawableBottom="@drawable/icon_yellow"
-                />
-
-    </LinearLayout>
-
-    <LinearLayout android:orientation="vertical"
-                  android:layout_width="match_parent"
-                  android:layout_height="match_parent"
-                  android:layoutDirection="rtl">
-
-        <TextView android:id="@+id/textview_drawable_4_2"
-                  android:layout_height="wrap_content"
-                  android:layout_width="wrap_content"
-                  android:drawableStart="@drawable/icon_blue"
-                  android:drawableEnd="@drawable/icon_red"
-                  android:drawableTop="@drawable/icon_green"
-                  android:drawableBottom="@drawable/icon_yellow"
-                />
-
-        <TextView android:id="@+id/textview_drawable_5_2"
-                  android:layout_height="wrap_content"
-                  android:layout_width="wrap_content"
-                  android:drawableLeft="@drawable/icon_black"
-                  android:drawableRight="@drawable/icon_black"
-                  android:drawableStart="@drawable/icon_blue"
-                  android:drawableEnd="@drawable/icon_red"
-                  android:drawableTop="@drawable/icon_green"
-                  android:drawableBottom="@drawable/icon_yellow"
-                />
-
-    </LinearLayout>
-
-</LinearLayout>
diff --git a/tests/res/layout/textview_numeric.xml b/tests/res/layout/textview_numeric.xml
deleted file mode 100644
index e60cb26..0000000
--- a/tests/res/layout/textview_numeric.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content">
-
-    <TextView android:id="@+id/numeric_default"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:editable="true"/>
-
-    <TextView android:id="@+id/numeric_integer"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:numeric="integer"/>
-
-    <TextView android:id="@+id/numeric_signed"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:numeric="signed"/>
-
-    <TextView android:id="@+id/numeric_decimal"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:numeric="decimal"/>
-
-    <TextView android:id="@+id/numeric_signed_integer"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:numeric="signed|integer"/>
-
-    <TextView android:id="@+id/numeric_integer_decimal"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:numeric="integer|decimal"/>
-
-    <TextView android:id="@+id/numeric_signed_decimal"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:numeric="signed|decimal"/>
-
-    <TextView android:id="@+id/numeric_signed_decimal_integer"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:numeric="signed|integer|decimal"/>
-
-</LinearLayout>
diff --git a/tests/res/layout/textview_phonenumber.xml b/tests/res/layout/textview_phonenumber.xml
deleted file mode 100644
index d0975c6..0000000
--- a/tests/res/layout/textview_phonenumber.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content">
-
-    <TextView android:id="@+id/phoneNumber_default"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:editable="true"/>
-
-    <TextView android:id="@+id/phoneNumber_true"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:phoneNumber="true"/>
-
-    <TextView android:id="@+id/phoneNumber_false"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:phoneNumber="false"
-        android:editable="true"/>
-
-</LinearLayout>
diff --git a/tests/res/layout/togglebutton_layout.xml b/tests/res/layout/togglebutton_layout.xml
deleted file mode 100644
index bb8a07d..0000000
--- a/tests/res/layout/togglebutton_layout.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2008 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.
- -->
-
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <LinearLayout
-        android:orientation="vertical"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content">
-
-        <ToggleButton android:id="@+id/toggle1"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content" />
-
-        <ToggleButton android:id="@+id/toggle2"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content" />
-
-    </LinearLayout>
-
-</ScrollView>
diff --git a/tests/res/layout/view_layout.xml b/tests/res/layout/view_layout.xml
deleted file mode 100644
index 40974f0..0000000
--- a/tests/res/layout/view_layout.xml
+++ /dev/null
@@ -1,96 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * Copyright (C) 2008 Esmertec AG.
- * Copyright (C) 2008 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.
- */
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/viewlayout_root"
-    android:orientation="vertical"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <android.view.cts.MockView
-        android:id="@+id/mock_view"
-        android:layout_width="100px"
-        android:layout_height="200px"/>
-
-    <android.view.cts.MockView
-        android:id="@+id/scroll_view"
-        android:layout_width="100px"
-        android:layout_height="200px"
-        android:scrollbars="horizontal|vertical"
-        android:fadingEdge="horizontal|vertical"
-        android:fadingEdgeLength="20px"/>
-
-    <android.view.cts.MockView
-        android:id="@+id/scroll_view_2"
-        android:layout_width="100px"
-        android:layout_height="200px"
-        android:scrollbars="horizontal|vertical"
-        android:requiresFadingEdge="horizontal|vertical"
-        android:fadingEdgeLength="20px"/>
-
-    <View
-        android:id="@+id/fit_windows"
-        android:fitsSystemWindows="true"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"/>
-
-    <android.view.cts.MockView
-            android:id="@+id/mock_view_padding_full"
-            android:layout_width="200px"
-            android:layout_height="200px"
-            android:padding="0px"
-            android:background="@drawable/padding_0" />
-
-    <android.view.cts.MockView
-            android:id="@+id/mock_view_padding_left"
-            android:layout_width="200px"
-            android:layout_height="200px"
-            android:paddingLeft="0px"
-            android:background="@drawable/padding_0" />
-
-    <android.view.cts.MockView
-            android:id="@+id/mock_view_padding_right"
-            android:layout_width="200px"
-            android:layout_height="200px"
-            android:paddingRight="0px"
-            android:background="@drawable/padding_0" />
-
-    <android.view.cts.MockView
-            android:id="@+id/mock_view_padding_top"
-            android:layout_width="200px"
-            android:layout_height="200px"
-            android:paddingTop="0px"
-            android:background="@drawable/padding_0" />
-
-    <android.view.cts.MockView
-            android:id="@+id/mock_view_padding_bottom"
-            android:layout_width="200px"
-            android:layout_height="200px"
-            android:paddingBottom="0dp"
-            android:background="@drawable/padding_0" />
-
-    <android.view.cts.MockView
-            android:id="@+id/mock_view_padding_runtime_updated"
-            android:layout_width="200px"
-            android:layout_height="200px"
-            android:paddingStart="8px"
-            android:paddingEnd="8px"
-            android:background="@drawable/no_padding" />
-
-</LinearLayout>
diff --git a/tests/res/raw/samplefont.ttf b/tests/res/raw/samplefont.ttf
deleted file mode 100644
index 49f1c62..0000000
--- a/tests/res/raw/samplefont.ttf
+++ /dev/null
Binary files differ
diff --git a/tests/res/raw/sphere.a3d b/tests/res/raw/sphere.a3d
deleted file mode 100644
index 3d78b01..0000000
--- a/tests/res/raw/sphere.a3d
+++ /dev/null
Binary files differ
diff --git a/tests/res/raw/test1.obb b/tests/res/raw/test1.obb
deleted file mode 100644
index a6b3e1c..0000000
--- a/tests/res/raw/test1.obb
+++ /dev/null
Binary files differ
diff --git a/tests/res/values/attrs.xml b/tests/res/values/attrs.xml
deleted file mode 100644
index 9793893..0000000
--- a/tests/res/values/attrs.xml
+++ /dev/null
@@ -1,128 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (C) 2008 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>
-    <declare-styleable name="Style1">
-        <attr name="Type1" format="integer">
-            <enum name="type" value="28" />
-            <enum name="data" value="0xff00ff00" />
-            <enum name="asset_cookie" value="0" />
-            <enum name="resource_id" value="0" />
-            <enum name="changing_config" value="0" />
-        </attr>
-        <attr name="Type2" format="integer">
-            <enum name="type" value="28" />
-            <enum name="data" value="0xff0000ff" />
-            <enum name="asset_cookie" value="0" />
-            <enum name="resource_id" value="0" />
-            <enum name="changing_config" value="0" />
-        </attr>
-    </declare-styleable>
-    <attr name="type1" format="boolean"/>
-    <attr name="type2" format="boolean"/>
-    <attr name="type3" format="color"/>
-    <attr name="type4" format="reference|color"/>
-    <attr name="type5" format="dimension"/>
-    <attr name="type6" format="dimension"/>
-    <attr name="type7" format="dimension"/>
-    <attr name="type8" format="reference"/>
-    <attr name="type9" format="float"/>
-    <attr name="type10" format="fraction"/>
-    <attr name="type11" format="integer"/>
-    <attr name="type12" format="integer"/>
-    <attr name="type13" format="reference|string"/>
-    <attr name="type14" format="string"/>
-    <attr name="type15" format="reference"/>
-    <attr name="type16" format="string"/>
-    <declare-styleable name="style1">
-        <attr name="type1"/>
-        <attr name="type2"/>
-        <attr name="type3"/>
-        <attr name="type4"/>
-        <attr name="type5"/>
-        <attr name="type6"/>
-        <attr name="type7"/>
-        <attr name="type8"/>
-        <attr name="type9"/>
-        <attr name="type10"/>
-        <attr name="type11"/>
-        <attr name="type12"/>
-        <attr name="type13"/>
-        <attr name="type14"/>
-        <attr name="type15"/>
-        <attr name="type16"/>
-    </declare-styleable>
-    <attr name="testEnum">
-        <enum name="val1" value="1" />
-        <enum name="val2" value="2" />
-        <enum name="val10" value="10" />
-    </attr>
-    <attr name="testFlags">
-        <flag name="bit1" value="0x1" />
-        <flag name="bit2" value="0x2" />
-        <flag name="bit31" value="0x40000000" />
-    </attr>
-    <attr name="testString" format="string" />
-    <declare-styleable name="EnumStyle">
-        <attr name="testEnum" />
-    </declare-styleable>
-    <declare-styleable name="FlagStyle">
-        <attr name="testFlags" />
-    </declare-styleable>
-    <declare-styleable name="TestConfig">
-        <attr name="testString" />
-    </declare-styleable>
-    <!-- Size of text. Recommended dimension type for text is "sp" for scaled-pixels (example: 15sp).
-         Supported values include the following:<p/>
-    <ul>
-        <li><b>px</b> Pixels</li>
-        <li><b>sp</b> Scaled pixels (scaled to relative pixel size on screen). See {@link android.util.DisplayMetrics} for more information.</li>
-        <li><b>pt</b> Points</li>
-        <li><b>dip</b> Device independent pixels. See {@link android.util.DisplayMetrics} for more information.</li>
-    </ul>
-    -->
-    <attr name="textSize" format="dimension" />
-    <attr name="typeface">
-        <enum name="normal" value="0" />
-        <enum name="sans" value="1" />
-        <enum name="serif" value="2" />
-        <enum name="monospace" value="3" />
-    </attr>
-    <!-- Default text typeface style. -->
-    <attr name="textStyle">
-        <flag name="normal" value="0" />
-        <flag name="bold" value="1" />
-        <flag name="italic" value="2" />
-    </attr>
-    <!-- Color of text (usually same as colorForeground). -->
-    <attr name="textColor" format="reference|color" />
-    <!-- Color of highlighted text. -->
-    <attr name="textColorHighlight" format="reference|color" />
-    <!-- Color of hint text (displayed when the field is empty). -->
-    <attr name="textColorHint" format="reference|color" />
-    <!-- Color of link text (URLs). -->
-    <attr name="textColorLink" format="reference|color" />
-    <declare-styleable name="TextAppearance">
-        <attr name="textColor"/>
-        <attr name="textSize"/>
-        <attr name="textStyle"/>
-        <attr name="typeface"/>
-        <attr name="textColorHighlight"/>
-        <attr name="textColorHint"/>
-        <attr name="textColorLink"/>
-    </declare-styleable>
-</resources>
diff --git a/tests/res/values/strings.xml b/tests/res/values/strings.xml
deleted file mode 100644
index 0ab3dd6..0000000
--- a/tests/res/values/strings.xml
+++ /dev/null
@@ -1,170 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="permlab_testGranted">Test Granted</string>
-    <string name="permdesc_testGranted">Used for running CTS tests, for testing operations
-        where we have the permission.</string>
-    <string name="permlab_testDynamic">Test Dynamic</string>
-    <string name="permdesc_testDynamic">Used for running CTS tests, for testing adding
-        dynamic permissions.</string>
-    <string name="permlab_testDenied">Test Denied</string>
-    <string name="permdesc_testDenied">Used for running CTS tests, for testing operations
-        where we do not have the permission.</string>
-    <string name="explain">1. click start. \n2. if above image shaked, then press pass button,
-         else press failed button.</string>
-    <string name="text_view_hello">Hello! Text view!</string>
-    <string name="text_view_hello_two_lines">Hello! \nText view!</string>
-    <string name="text_view_simple_hint">This is a hint.</string>
-    <string name="text_view_hint">This is a string for testing hint of textview.</string>
-    <string name="activity_forwarding">App/Forwarding</string>
-    <string name="forwarding">$$$</string>
-    <string name="go">Go</string>
-    <string name="back">Back</string>
-    <string name="forward_target">
-        Press back button and notice we don\'t see the previous activity.
-    </string>
-    <string name="edit_text">testing</string>
-    <string name="text">DialogTest</string>
-    <string name="text_country">Country</string>
-    <string name="text_name">Name</string>
-    <string name="hello_world">Hello, World!</string>
-    <string name="hello_android">Hello, Android!</string>
-    <string name="alert_dialog_username">Name:</string>
-    <string name="alert_dialog_password">Password:</string>
-    <string name="alert_dialog_positive">Positive</string>
-    <string name="alert_dialog_negative">Negative</string>
-    <string name="alert_dialog_neutral">Neutral</string>
-    <string name="notify">Notify </string>
-    <string name="tabs_1">testing</string>
-    <string name="table_layout_first">first</string>
-    <string name="table_layout_second">second</string>
-    <string name="table_layout_third">third</string>
-    <string name="table_layout_long">Very long to make the string out of the screen</string>
-    <string name="chronometer_text">Test Chronometer</string>
-    <string name="am">AM</string>
-    <string name="pm">PM</string>
-    <string name="viewgroup_test">ViewGroup test</string>
-    <string name="viewanimator_test">ViewAnimator test</string>
-    <string name="id_ok">OK</string>
-    <string name="id_cancel">Cancel</string>
-    <string name="context_test_string1">This is %s string.</string>
-    <string name="context_test_string2">This is test string.</string>
-    <string name="animationutils_test_instructions">Choose different animations</string>
-    <string name="animationutils_test_alpha">Alpha animation</string>
-    <string name="animationutils_test_scale">Scale animation</string>
-    <string name="animationutils_test_rotate">Rotate animation</string>
-    <string name="animationutils_test_translate">Translate animation</string>
-    <string name="animationutils_test_set">Animation set</string>
-    <string name="animationutils_test_layout">Layout animation</string>
-    <string name="animationutils_test_gridlayout">Grid layout animation</string>
-    <string name="twolinelistitem_test_text1">text1</string>
-    <string name="twolinelistitem_test_text2">text2</string>
-    <string name="metadata_text">metadata text</string>
-    <string name="horizontal_text_1">horizontal 1</string>
-    <string name="horizontal_text_2">horizontal 2</string>
-    <string name="horizontal_text_3">horizontal 3</string>
-    <string name="vertical_text_1">vertical 1</string>
-    <string name="vertical_text_2">vertical 2</string>
-    <string name="vertical_text_3">vertical 3</string>
-    <string name="reference">here</string>
-    <string name="coerceIntegerToString">100</string>
-    <string name="coerceBooleanToString">true</string>
-    <string name="coerceColorToString">#fff</string>
-    <string name="coerceFloatToString">100.0</string>
-    <string name="coerceDimensionToString">100px</string>
-    <string name="coerceFractionToString">100<xliff:g id="percent">%</xliff:g></string>
-    <string name="formattedStringNone">Format[]</string>
-    <string name="formattedStringOne">Format[<xliff:g id="format">%d</xliff:g>]</string>
-    <string name="formattedStringTwo">Format[<xliff:g id="format">%3$d,%2$s</xliff:g>]</string>
-    <string name="checkboxpref_key">checkboxpref_key</string>
-   <string name="checkboxpref_title">title of preference</string>
-   <string name="checkboxpref_summary">summary of preference</string>
-   <string name="checkboxpref_summary_on">summary on of preference</string>
-   <string name="checkboxpref_summary_off">summary off of preference</string>
-   <string name="checkboxpref_depend">checkboxpref_depend</string>
-   <string name="checkboxpref_depend_title"> depend title of preference</string>
-   <string name="checkboxpref_depend_summary"> depend summary of preference</string>
-   <string name="edittextpref_key">edittextpref_key</string>
-   <string name="edittextpref_default_value">default value of preference</string>
-   <string name="edittextpref_title">title of edit text preference</string>
-   <string name="edittextpref_summary">summary of edit text preference</string>
-   <string name="edittextpref_dialog_title">dialog title of edit text preference</string>
-   <string name="edittextpref_text">text of  edit text preference</string>
-   <string name="listpref_key">listpref_key</string>
-   <string name="listpref_title">title of list preference</string>
-   <string name="listpref_summary">summary of list preference</string>
-   <string name="listpref_dialogtitle">dialog title of list preference</string>
-   <string name="easy">Easy</string>
-   <string name="medium">Medium</string>
-   <string name="hard">Hard</string>
-   <string name="footer_view">Footer view</string>
-   <string name="header_view">Header view</string>
-   <string name="dialogpref_title">title of dialog preference </string>
-   <string name="dialogpref_dialog_title">dialog title of dialog preference </string>
-   <string name="dialogpref_key">dialogpref_key</string>
-   <string name="dialogpref_default_value">default value of dialog preference</string>
-   <string name="dialogpref_summary">summary of dialog preference</string>
-   <string name="dialogpref_message">message of dialog preference</string>
-   <string name="dialogpref_sure">Sure</string>
-   <string name="dialogpref_cancel">Cancel</string>
-   <string name="pref_key">pref_key</string>
-   <string name="pref_title">title of preference</string>
-   <string name="pref_summary">summary of preference</string>
-   <string name="pref_depend_key">pref_depend_key</string>
-   <string name="pref_depend_title"> depend title of preference</string>
-   <string name="pref_depend_summary"> depend summary of preference</string>
-   <string name="android_intent_action_preference">android.intent.action.PREFERENCE</string>
-   <string name="def_pref_key">def_pref_key</string>
-   <string name="def_pref_title">default preference</string>
-   <string name="def_pref_summary">This is default preference of cts</string>
-   <string name="relative_view1">view 1</string>
-   <string name="relative_view2">view 2</string>
-   <string name="relative_view3">view 3</string>
-   <string name="relative_view4">view 4</string>
-   <string name="relative_view5">view 5</string>
-   <string name="relative_view6">view 6</string>
-   <string name="relative_view7">view 7</string>
-   <string name="relative_view8">view 8</string>
-   <string name="relative_view9">view 9</string>
-   <string name="relative_view10">view 10</string>
-   <string name="relative_view11">view 11</string>
-   <string name="relative_view12">view 12</string>
-   <string name="relative_view13">view 13</string>
-   <string name="country">Country:</string>
-   <string name="symbol">Symbol:</string>
-   <string name="country_warning">No such country registered</string>
-   <string name="version_cur">base</string>
-   <string name="version_old">base</string>
-   <string name="version_v3">base</string>
-   <string name="authenticator_label">Android CTS</string>
-   <string name="search_label">Android CTS</string>
-
-   <string name="button">Button</string>
-   <string name="holo_test">Holo Test</string>
-   <string name="holo_generator">Holo Generator</string>
-   <string name="holo_light_test">Holo Light Test</string>
-   <string name="holo_light_generator">Holo Light Generator</string>
-   <string name="reference_image">Reference Image: </string>
-   <string name="generated_image">Generated Image: </string>
-   <string name="themes_prompt">Select a Theme:</string>
-   <string name="sample_text">Sample text goes here. I wanted something creative and whimsical
-but then I just got bored...</string>
-    <string name="long_text">This is a really long string which exceeds the width of the view.
-New devices have a much larger screen which actually enables long strings to be displayed
-with no fading. I have made this string longer to fix this case. If you are correcting this
-text, I would love to see the kind of devices you guys now use! Guys, maybe some devices need longer string! </string>
-</resources>
diff --git a/tests/res/values/styles.xml b/tests/res/values/styles.xml
deleted file mode 100644
index e0110cc..0000000
--- a/tests/res/values/styles.xml
+++ /dev/null
@@ -1,145 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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="Whatever">
-        <item name="type1">true</item>
-        <item name="type2">false</item>
-        <item name="type3">#ff0000ff</item>
-        <item name="type4">#ff00ff00</item>
-        <item name="type5">0.75px</item>
-        <item name="type6">10px</item>
-        <item name="type7">18px</item>
-        <item name="type8">@drawable/pass</item>
-        <item name="type9">3.14</item>
-        <item name="type10">100%</item>
-        <item name="type11">365</item>
-        <item name="type12">86400</item>
-        <item name="type13">@string/hello_android</item>
-        <item name="type14">TypedArray Test!</item>
-        <item name="type15">@array/difficultyLevel</item>
-        <item name="type16">Typed Value!</item>
-    </style>
-
-    <style name="TextViewWithoutColorAndAppearance">
-        <item name="android:textSize">18sp</item>
-    </style>
-
-    <style name="TextViewWithColorButWithOutAppearance">
-        <item name="android:textColor">#ff0000ff</item>
-    </style>
-
-    <style name="TextViewWithColorAndAppearance">
-        <item name="android:textColor">#ff0000ff</item>
-        <item name="android:textAppearance">@style/TextAppearance.WithColor</item>
-    </style>
-
-    <style name="TextViewWithoutColorButWithAppearance">
-        <item name="android:textAppearance">@style/TextAppearance.WithColor</item>
-    </style>
-
-    <style name="TextAppearance" parent="android:TextAppearance">
-    </style>
-
-    <style name="TextAppearance.WithColor">
-        <item name="android:textColor">#ffff0000</item>
-    </style>
-
-    <style name="TextAppearance.All">
-        <item name="android:textColor">@drawable/black</item>
-        <item name="android:textSize">20px</item>
-        <item name="android:textStyle">bold</item>
-        <item name="android:textColorHint">@drawable/red</item>
-        <item name="android:textColorLink">@drawable/blue</item>
-        <item name="android:textColorHighlight">@drawable/yellow</item>
-    </style>
-
-    <style name="TextAppearance.Colors">
-        <item name="android:textColor">@drawable/black</item>
-        <item name="android:textColorHint">@drawable/blue</item>
-        <item name="android:textColorLink">@drawable/yellow</item>
-        <item name="android:textColorHighlight">@drawable/red</item>
-    </style>
-
-    <style name="TextAppearance.NotColors">
-        <item name="android:textSize">17px</item>
-        <item name="android:typeface">sans</item>
-        <item name="android:textStyle">normal</item>
-    </style>
-
-    <style name="TextAppearance.Style">
-        <item name="android:textStyle">normal</item>
-    </style>
-
-    <style name="TestEnum1">
-        <item name="testEnum">val1</item>
-    </style>
-
-    <style name="TestEnum2">
-        <item name="testEnum">val2</item>
-    </style>
-
-    <style name="TestEnum10">
-        <item name="testEnum">val10</item>
-    </style>
-
-    <style name="TestFlag1">
-        <item name="testFlags">bit1</item>
-    </style>
-
-    <style name="TestFlag2">
-        <item name="testFlags">bit2</item>
-    </style>
-
-    <style name="TestFlag31">
-        <item name="testFlags">bit31</item>
-    </style>
-
-    <style name="TestFlag1And2">
-        <item name="testFlags">bit1|bit2</item>
-    </style>
-
-    <style name="TestFlag1And2And31">
-        <item name="testFlags">bit1|bit2|bit31</item>
-    </style>
-
-    <style name="TestEnum1.EmptyInherit" />
-
-    <style name="Theme_AlertDialog">
-        <item name="android:textSize">18sp</item>
-    </style>
-
-    <style name="TestProgressBar">
-        <item name="android:indeterminateOnly">false</item>
-        <item name="android:progressDrawable">?android:drawable/progress_horizontal</item>
-        <item name="android:indeterminateDrawable">?android:drawable/progress_horizontal</item>
-        <item name="android:minHeight">20dip</item>
-        <item name="android:maxHeight">20dip</item>
-        <item name="android:focusable">true</item>
-    </style>
-
-    <style name="Test_Theme">
-        <item name="android:windowNoTitle">true</item>
-        <item name="android:panelColorForeground">#ff000000</item>
-        <item name="android:panelColorBackground">#ffffffff</item>
-    </style>
-
-    <style name="Theme_NoSwipeDismiss">
-        <item name="android:windowSwipeToDismiss">false</item>
-    </style>
-
-</resources>
diff --git a/tests/res/xml/alias.xml b/tests/res/xml/alias.xml
deleted file mode 100644
index f88f3dc..0000000
--- a/tests/res/xml/alias.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * Copyright (C) 2008 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.
- */
--->
-
-<alias xmlns:android="http://schemas.android.com/apk/res/android">
-    <intent android:action="android.intent.action.MAIN"
-        android:targetPackage="com.android.cts.stub"
-        android:targetClass="android.app.cts.ChildActivity"
-        android:data="http://www.google.com/">
-    </intent>
-</alias>
-
diff --git a/tests/res/xml/layout.xml b/tests/res/xml/layout.xml
deleted file mode 100644
index 6bcb27d..0000000
--- a/tests/res/xml/layout.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<alias xmlns:android="http://schemas.android.com/apk/res/android">
-    <AbsoluteLayout    android:layout_width="20dip"
-               android:layout_height="30dip"
-               android:layout_x="10dip"
-               android:layout_y="20dip">
-
-            <TextView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_x="0dip"
-                android:layout_y="0dip"
-                android:text="@string/notify">
-                <requestFocuse/>
-            </TextView>
-
-            <TextView
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_x="0dip"
-                android:layout_y="0dip"
-                android:text="@string/notify"/>
-
-            <View
-                android:id="@+id/fit_windows"
-                android:fitsSystemWindows="true"
-                android:layout_height="wrap_content"/>
-            <include layout="@xml/merge" />
-    </AbsoluteLayout>
-
-</alias>
diff --git a/tests/res/xml/searchable.xml b/tests/res/xml/searchable.xml
deleted file mode 100644
index f526341..0000000
--- a/tests/res/xml/searchable.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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.
--->
-
-<searchable xmlns:android="http://schemas.android.com/apk/res/android"
-    android:label="@string/search_label"
-/>
diff --git a/tests/sample/Android.mk b/tests/sample/Android.mk
index e1a9408..5e8f571 100755
--- a/tests/sample/Android.mk
+++ b/tests/sample/Android.mk
@@ -22,9 +22,6 @@
 # When built, explicitly put it in the data partition.
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-# All tests should include android.test.runner.
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/sample/AndroidManifest.xml b/tests/sample/AndroidManifest.xml
index ae58f0a..f07ebbe 100755
--- a/tests/sample/AndroidManifest.xml
+++ b/tests/sample/AndroidManifest.xml
@@ -31,9 +31,12 @@
 
     <!--  self-instrumenting test package. -->
     <instrumentation
-        android:name="android.test.InstrumentationCtsTestRunner"
+        android:name="android.support.test.runner.AndroidJUnitRunner"
         android:label="CTS sample tests"
-        android:targetPackage="android.sample.cts" />
-
+        android:targetPackage="android.sample.cts" >
+        <meta-data
+            android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 </manifest>
 
diff --git a/tests/signature-tests/Android.mk b/tests/signature-tests/Android.mk
new file mode 100644
index 0000000..f17ee47
--- /dev/null
+++ b/tests/signature-tests/Android.mk
@@ -0,0 +1,26 @@
+# Copyright (C) 2010 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)
+
+include $(CLEAR_VARS)
+
+# Include all test java files.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_MODULE := signature-tests
+LOCAL_MODULE_TAGS := optional
+LOCAL_JAVA_LIBRARIES := tradefed-prebuilt cts-tradefed signature-hostside
+
+include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/tests/signature-tests/run_unit_tests.sh b/tests/signature-tests/run_unit_tests.sh
new file mode 100755
index 0000000..19ce8d2
--- /dev/null
+++ b/tests/signature-tests/run_unit_tests.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# 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.
+
+# helper script for running the signature unit tests
+
+checkFile() {
+    if [ ! -f "$1" ]; then
+        echo "Unable to locate $1"
+        exit
+    fi;
+}
+
+# check if in Android build env
+if [ ! -z ${ANDROID_BUILD_TOP} ]; then
+    HOST=`uname`
+    if [ "$HOST" == "Linux" ]; then
+        OS="linux-x86"
+    elif [ "$HOST" == "Darwin" ]; then
+        OS="darwin-x86"
+    else
+        echo "Unrecognized OS"
+        exit
+    fi;
+fi;
+
+JAR_DIR=${ANDROID_BUILD_TOP}/out/host/$OS/framework
+JARS="tradefed-prebuilt.jar hosttestlib.jar signature-hostside.jar signature-tests.jar"
+
+for JAR in $JARS; do
+    checkFile ${JAR_DIR}/${JAR}
+    JAR_PATH=${JAR_PATH}:${JAR_DIR}/${JAR}
+done
+
+java $RDBG_FLAG \
+  -cp ${JAR_PATH} com.android.tradefed.command.Console run singleCommand host -n --class android.signature.cts.tests.AllTests "$@"
+
diff --git a/tests/signature-tests/src/android/signature/cts/tests/AllTests.java b/tests/signature-tests/src/android/signature/cts/tests/AllTests.java
new file mode 100644
index 0000000..56916f4
--- /dev/null
+++ b/tests/signature-tests/src/android/signature/cts/tests/AllTests.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008 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.signature.cts.tests;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Finds all instrumentation and unit tests for this application.
+ */
+public class AllTests extends TestSuite {
+
+    public AllTests() {
+        super();
+
+        addTestSuite(JDiffClassDescriptionTest.class);
+    }
+
+    public static Test suite() {
+        return new AllTests();
+    }
+}
diff --git a/tests/signature-tests/src/android/signature/cts/tests/JDiffClassDescriptionTest.java b/tests/signature-tests/src/android/signature/cts/tests/JDiffClassDescriptionTest.java
new file mode 100644
index 0000000..ffb81ce
--- /dev/null
+++ b/tests/signature-tests/src/android/signature/cts/tests/JDiffClassDescriptionTest.java
@@ -0,0 +1,472 @@
+/*
+ * Copyright (C) 2007 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.signature.cts.tests;
+
+import android.signature.cts.FailureType;
+import android.signature.cts.JDiffClassDescription;
+import android.signature.cts.ResultObserver;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import java.lang.reflect.Modifier;
+
+/**
+ * Test class for JDiffClassDescription.
+ */
+public class JDiffClassDescriptionTest extends TestCase {
+
+    private class NoFailures implements ResultObserver {
+        @Override
+        public void notifyFailure(FailureType type, String name, String errmsg) {
+            Assert.fail("Saw unexpected test failure: " + name + " failure type: " + type);
+        }
+    }
+
+    private class ExpectFailure implements ResultObserver {
+        private FailureType expectedType;
+        private boolean failureSeen;
+
+        public ExpectFailure(FailureType expectedType) {
+            this.expectedType = expectedType;
+        }
+
+        @Override
+        public void notifyFailure(FailureType type, String name, String errMsg) {
+            if (type == expectedType) {
+                if (failureSeen) {
+                    Assert.fail("Saw second test failure: " + name + " failure type: " + type);
+                } else {
+                    // We've seen the error, mark it and keep going
+                    failureSeen = true;
+                }
+            } else {
+                Assert.fail("Saw unexpected test failure: " + name + " failure type: " + type);
+            }
+        }
+
+        public void validate() {
+            Assert.assertTrue(failureSeen);
+        }
+    }
+
+    /**
+     * Create the JDiffClassDescription for "NormalClass".
+     *
+     * @return the new JDiffClassDescription
+     */
+    private JDiffClassDescription createNormalClass() {
+        return createNormalClass(new NoFailures());
+    }
+
+    /**
+     * Create the JDiffClassDescription for "NormalClass".
+     *
+     * @return the new JDiffClassDescription
+     */
+    private JDiffClassDescription createNormalClass(ResultObserver observer) {
+        JDiffClassDescription clz = new JDiffClassDescription(
+                "android.signature.cts.tests.data", "NormalClass", observer);
+        clz.setType(JDiffClassDescription.JDiffType.CLASS);
+        clz.setModifier(Modifier.PUBLIC);
+        return clz;
+    }
+
+    public void testNormalClassCompliance() {
+        JDiffClassDescription clz = createNormalClass();
+        clz.checkSignatureCompliance();
+        assertEquals(clz.toSignatureString(), "public class NormalClass");
+    }
+
+    public void testMissingClass() {
+        ExpectFailure observer = new ExpectFailure(FailureType.MISSING_CLASS);
+        JDiffClassDescription clz = new JDiffClassDescription(
+                "android.signature.cts.tests.data", "NoSuchClass", observer);
+        clz.setType(JDiffClassDescription.JDiffType.CLASS);
+        clz.checkSignatureCompliance();
+        observer.validate();
+    }
+
+    public void testSimpleConstructor() {
+        JDiffClassDescription clz = createNormalClass();
+        JDiffClassDescription.JDiffConstructor constructor =
+                new JDiffClassDescription.JDiffConstructor("NormalClass", Modifier.PUBLIC);
+        clz.addConstructor(constructor);
+        clz.checkSignatureCompliance();
+        assertEquals(constructor.toSignatureString(), "public NormalClass()");
+    }
+
+    public void testOneArgConstructor() {
+        JDiffClassDescription clz = createNormalClass();
+        JDiffClassDescription.JDiffConstructor constructor =
+                new JDiffClassDescription.JDiffConstructor("NormalClass", Modifier.PRIVATE);
+        constructor.addParam("java.lang.String");
+        clz.addConstructor(constructor);
+        clz.checkSignatureCompliance();
+        assertEquals(constructor.toSignatureString(), "private NormalClass(java.lang.String)");
+    }
+
+    public void testConstructorThrowsException() {
+        JDiffClassDescription clz = createNormalClass();
+        JDiffClassDescription.JDiffConstructor constructor =
+                new JDiffClassDescription.JDiffConstructor("NormalClass", Modifier.PROTECTED);
+        constructor.addParam("java.lang.String");
+        constructor.addParam("java.lang.String");
+        constructor.addException("android.signature.cts.tests.data.NormalException");
+        clz.addConstructor(constructor);
+        clz.checkSignatureCompliance();
+        assertEquals(constructor.toSignatureString(),
+                "protected NormalClass(java.lang.String, java.lang.String) " +
+                "throws android.signature.cts.tests.data.NormalException");
+    }
+
+    public void testPackageProtectedConstructor() {
+        JDiffClassDescription clz = createNormalClass();
+        JDiffClassDescription.JDiffConstructor constructor =
+                new JDiffClassDescription.JDiffConstructor("NormalClass", 0);
+        constructor.addParam("java.lang.String");
+        constructor.addParam("java.lang.String");
+        constructor.addParam("java.lang.String");
+        clz.addConstructor(constructor);
+        clz.checkSignatureCompliance();
+        assertEquals(constructor.toSignatureString(),
+                "NormalClass(java.lang.String, java.lang.String, java.lang.String)");
+    }
+
+    public void testStaticMethod() {
+        JDiffClassDescription clz = createNormalClass();
+        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod(
+                "staticMethod", Modifier.STATIC | Modifier.PUBLIC, "void");
+        clz.addMethod(method);
+        clz.checkSignatureCompliance();
+        assertEquals(method.toSignatureString(), "public static void staticMethod()");
+    }
+
+    public void testSyncMethod() {
+        JDiffClassDescription clz = createNormalClass();
+        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod(
+                "syncMethod", Modifier.SYNCHRONIZED | Modifier.PUBLIC, "void");
+        clz.addMethod(method);
+        clz.checkSignatureCompliance();
+        assertEquals(method.toSignatureString(), "public synchronized void syncMethod()");
+    }
+
+    public void testPackageProtectMethod() {
+        JDiffClassDescription clz = createNormalClass();
+        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod(
+                "packageProtectedMethod", 0, "boolean");
+        clz.addMethod(method);
+        clz.checkSignatureCompliance();
+        assertEquals(method.toSignatureString(), "boolean packageProtectedMethod()");
+    }
+
+    public void testPrivateMethod() {
+        JDiffClassDescription clz = createNormalClass();
+        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod(
+                "privateMethod", Modifier.PRIVATE, "void");
+        clz.addMethod(method);
+        clz.checkSignatureCompliance();
+        assertEquals(method.toSignatureString(), "private void privateMethod()");
+    }
+
+    public void testProtectedMethod() {
+        JDiffClassDescription clz = createNormalClass();
+        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod(
+                "protectedMethod", Modifier.PROTECTED, "java.lang.String");
+        clz.addMethod(method);
+        clz.checkSignatureCompliance();
+        assertEquals(method.toSignatureString(), "protected java.lang.String protectedMethod()");
+    }
+
+    public void testThrowsMethod() {
+        JDiffClassDescription clz = createNormalClass();
+        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod(
+                "throwsMethod", Modifier.PUBLIC, "void");
+        method.addException("android.signature.cts.tests.data.NormalException");
+        clz.addMethod(method);
+        clz.checkSignatureCompliance();
+        assertEquals(method.toSignatureString(), "public void throwsMethod() " +
+                "throws android.signature.cts.tests.data.NormalException");
+    }
+
+    public void testNativeMethod() {
+        JDiffClassDescription clz = createNormalClass();
+        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod(
+                "nativeMethod", Modifier.PUBLIC | Modifier.NATIVE, "void");
+        clz.addMethod(method);
+        clz.checkSignatureCompliance();
+        assertEquals(method.toSignatureString(), "public native void nativeMethod()");
+    }
+
+    public void testFinalField() {
+        JDiffClassDescription clz = createNormalClass();
+        JDiffClassDescription.JDiffField field = new JDiffClassDescription.JDiffField(
+                "FINAL_FIELD", "java.lang.String", Modifier.PUBLIC | Modifier.FINAL);
+        clz.addField(field);
+        clz.checkSignatureCompliance();
+        assertEquals(field.toSignatureString(), "public final java.lang.String FINAL_FIELD");
+    }
+
+    public void testStaticField() {
+        JDiffClassDescription clz = createNormalClass();
+        JDiffClassDescription.JDiffField field = new JDiffClassDescription.JDiffField(
+                "STATIC_FIELD", "java.lang.String", Modifier.PUBLIC | Modifier.STATIC);
+        clz.addField(field);
+        clz.checkSignatureCompliance();
+        assertEquals(field.toSignatureString(), "public static java.lang.String STATIC_FIELD");
+    }
+
+    public void testVolatileFiled() {
+        JDiffClassDescription clz = createNormalClass();
+        JDiffClassDescription.JDiffField field = new JDiffClassDescription.JDiffField(
+                "VOLATILE_FIELD", "java.lang.String", Modifier.PUBLIC | Modifier.VOLATILE);
+        clz.addField(field);
+        clz.checkSignatureCompliance();
+        assertEquals(field.toSignatureString(), "public volatile java.lang.String VOLATILE_FIELD");
+    }
+
+    public void testTransientField() {
+        JDiffClassDescription clz = createNormalClass();
+        JDiffClassDescription.JDiffField field = new JDiffClassDescription.JDiffField(
+                "TRANSIENT_FIELD", "java.lang.String", Modifier.PUBLIC | Modifier.TRANSIENT);
+        clz.addField(field);
+        clz.checkSignatureCompliance();
+        assertEquals(field.toSignatureString(),
+                "public transient java.lang.String TRANSIENT_FIELD");
+    }
+
+    public void testPacakgeField() {
+        JDiffClassDescription clz = createNormalClass();
+        JDiffClassDescription.JDiffField field = new JDiffClassDescription.JDiffField(
+                "PACAKGE_FIELD", "java.lang.String", 0);
+        clz.addField(field);
+        clz.checkSignatureCompliance();
+        assertEquals(field.toSignatureString(), "java.lang.String PACAKGE_FIELD");
+    }
+
+    public void testPrivateField() {
+        JDiffClassDescription clz = createNormalClass();
+        JDiffClassDescription.JDiffField field = new JDiffClassDescription.JDiffField(
+                "PRIVATE_FIELD", "java.lang.String", Modifier.PRIVATE);
+        clz.addField(field);
+        clz.checkSignatureCompliance();
+        assertEquals(field.toSignatureString(), "private java.lang.String PRIVATE_FIELD");
+    }
+
+    public void testProtectedField() {
+        JDiffClassDescription clz = createNormalClass();
+        JDiffClassDescription.JDiffField field = new JDiffClassDescription.JDiffField(
+                "PROTECTED_FIELD", "java.lang.String", Modifier.PROTECTED);
+        clz.addField(field);
+        clz.checkSignatureCompliance();
+        assertEquals(field.toSignatureString(), "protected java.lang.String PROTECTED_FIELD");
+    }
+
+    public void testInnerClass() {
+        JDiffClassDescription clz = new JDiffClassDescription(
+                "android.signature.cts.tests.data", "NormalClass.InnerClass", new NoFailures());
+        clz.setType(JDiffClassDescription.JDiffType.CLASS);
+        clz.setModifier(Modifier.PUBLIC);
+        JDiffClassDescription.JDiffField field = new JDiffClassDescription.JDiffField(
+                "innerClassData", "java.lang.String", Modifier.PRIVATE);
+        clz.addField(field);
+        clz.checkSignatureCompliance();
+        assertEquals(clz.toSignatureString(), "public class NormalClass.InnerClass");
+    }
+
+    public void testInnerInnerClass() {
+        JDiffClassDescription clz = new JDiffClassDescription(
+                "android.signature.cts.tests.data", "NormalClass.InnerClass.InnerInnerClass",
+                new NoFailures());
+        clz.setType(JDiffClassDescription.JDiffType.CLASS);
+        clz.setModifier(Modifier.PUBLIC);
+        JDiffClassDescription.JDiffField field = new JDiffClassDescription.JDiffField(
+                "innerInnerClassData", "java.lang.String", Modifier.PRIVATE);
+        clz.addField(field);
+        clz.checkSignatureCompliance();
+        assertEquals(clz.toSignatureString(),
+                "public class NormalClass.InnerClass.InnerInnerClass");
+    }
+
+    public void testInnerInterface() {
+        JDiffClassDescription clz = new JDiffClassDescription(
+                "android.signature.cts.tests.data", "NormalClass.InnerInterface", new NoFailures());
+        clz.setType(JDiffClassDescription.JDiffType.INTERFACE);
+        clz.setModifier(Modifier.PUBLIC | Modifier.STATIC | Modifier.ABSTRACT);
+        clz.addMethod(
+                new JDiffClassDescription.JDiffMethod("doSomething", Modifier.PUBLIC, "void"));
+        clz.checkSignatureCompliance();
+        assertEquals(clz.toSignatureString(), "public interface NormalClass.InnerInterface");
+    }
+
+    public void testInterface() {
+        JDiffClassDescription clz = new JDiffClassDescription(
+                "android.signature.cts.tests.data", "NormalInterface", new NoFailures());
+        clz.setType(JDiffClassDescription.JDiffType.INTERFACE);
+        clz.setModifier(Modifier.PUBLIC | Modifier.ABSTRACT);
+        clz.addMethod(
+                new JDiffClassDescription.JDiffMethod("doSomething", Modifier.PUBLIC, "void"));
+        clz.checkSignatureCompliance();
+        assertEquals(clz.toSignatureString(), "public interface NormalInterface");
+    }
+
+    public void testFinalClass() {
+        JDiffClassDescription clz = new JDiffClassDescription(
+                "android.signature.cts.tests.data", "FinalClass", new NoFailures());
+        clz.setType(JDiffClassDescription.JDiffType.CLASS);
+        clz.setModifier(Modifier.PUBLIC | Modifier.FINAL);
+        clz.checkSignatureCompliance();
+        assertEquals(clz.toSignatureString(), "public final class FinalClass");
+    }
+
+    /**
+     * Test the case where the API declares the method not synchronized, but it
+     * actually is.
+     */
+    public void testAddingSync() {
+        ExpectFailure observer = new ExpectFailure(FailureType.MISMATCH_METHOD);
+        JDiffClassDescription clz = createNormalClass(observer);
+        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod(
+                "syncMethod", Modifier.PUBLIC, "void");
+        clz.addMethod(method);
+        clz.checkSignatureCompliance();
+        observer.validate();
+    }
+
+    /**
+     * Test the case where the API declares the method is synchronized, but it
+     * actually is not.
+     */
+    public void testRemovingSync() {
+        JDiffClassDescription clz = createNormalClass();
+        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod(
+                "notSyncMethod", Modifier.SYNCHRONIZED | Modifier.PUBLIC, "void");
+        clz.addMethod(method);
+        clz.checkSignatureCompliance();
+    }
+
+    /**
+     * API says method is not native, but it actually is. http://b/1839558
+     */
+    public void testAddingNative() {
+        JDiffClassDescription clz = createNormalClass();
+        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod(
+                "nativeMethod", Modifier.PUBLIC, "void");
+        clz.addMethod(method);
+        clz.checkSignatureCompliance();
+    }
+
+    /**
+     * API says method is native, but actually isn't. http://b/1839558
+     */
+    public void testRemovingNative() {
+        JDiffClassDescription clz = createNormalClass();
+        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod(
+                "notNativeMethod", Modifier.NATIVE | Modifier.PUBLIC, "void");
+        clz.addMethod(method);
+        clz.checkSignatureCompliance();
+    }
+
+    public void testAbstractClass() {
+        JDiffClassDescription clz = new JDiffClassDescription(
+                "android.signature.cts.tests.data", "AbstractClass", new NoFailures());
+        clz.setType(JDiffClassDescription.JDiffType.CLASS);
+        clz.setModifier(Modifier.PUBLIC | Modifier.ABSTRACT);
+        clz.checkSignatureCompliance();
+        assertEquals(clz.toSignatureString(), "public abstract class AbstractClass");
+    }
+
+    /**
+     * API lists class as abstract, reflection does not. http://b/1839622
+     */
+    public void testRemovingAbstractFromAClass() {
+        JDiffClassDescription clz = new JDiffClassDescription(
+                "android.signature.cts.tests.data", "NormalClass", new NoFailures());
+        clz.setType(JDiffClassDescription.JDiffType.CLASS);
+        clz.setModifier(Modifier.PUBLIC | Modifier.ABSTRACT);
+        clz.checkSignatureCompliance();
+    }
+
+    /**
+     * reflection lists class as abstract, api does not. http://b/1839622
+     */
+    public void testAddingAbstractToAClass() {
+        ExpectFailure observer = new ExpectFailure(FailureType.MISMATCH_CLASS);
+        JDiffClassDescription clz = new JDiffClassDescription(
+                "android.signature.cts.tests.data", "AbstractClass", observer);
+        clz.setType(JDiffClassDescription.JDiffType.CLASS);
+        clz.setModifier(Modifier.PUBLIC);
+        clz.checkSignatureCompliance();
+        observer.validate();
+    }
+
+    public void testFinalMethod() {
+        JDiffClassDescription clz = createNormalClass();
+        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod(
+                "finalMethod", Modifier.PUBLIC | Modifier.FINAL, "void");
+        clz.addMethod(method);
+        clz.checkSignatureCompliance();
+        assertEquals(method.toSignatureString(), "public final void finalMethod()");
+    }
+
+    /**
+     * Final Class, API lists methods as non-final, reflection has it as final.
+     * http://b/1839589
+     */
+    public void testAddingFinalToAMethodInAFinalClass() {
+        JDiffClassDescription clz = new JDiffClassDescription(
+                "android.signature.cts.tests.data", "FinalClass", new NoFailures());
+        clz.setType(JDiffClassDescription.JDiffType.CLASS);
+        clz.setModifier(Modifier.PUBLIC | Modifier.FINAL);
+        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod(
+                "finalMethod", Modifier.PUBLIC, "void");
+        clz.addMethod(method);
+        clz.checkSignatureCompliance();
+    }
+
+    /**
+     * Final Class, API lists methods as final, reflection has it as non-final.
+     * http://b/1839589
+     */
+    public void testRemovingFinalToAMethodInAFinalClass() {
+        JDiffClassDescription clz = new JDiffClassDescription(
+                "android.signature.cts.tests.data", "FinalClass", new NoFailures());
+        clz.setType(JDiffClassDescription.JDiffType.CLASS);
+        clz.setModifier(Modifier.PUBLIC | Modifier.FINAL);
+        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod(
+                "nonFinalMethod", Modifier.PUBLIC | Modifier.FINAL, "void");
+        clz.addMethod(method);
+        clz.checkSignatureCompliance();
+    }
+
+    /**
+     * non-final Class, API lists methods as non-final, reflection has it as
+     * final. http://b/1839589
+     */
+    public void testAddingFinalToAMethodInANonFinalClass() {
+        ExpectFailure observer = new ExpectFailure(FailureType.MISMATCH_METHOD);
+        JDiffClassDescription clz = new JDiffClassDescription(
+                "android.signature.cts.tests.data", "NormalClass", observer);
+        clz.setType(JDiffClassDescription.JDiffType.CLASS);
+        clz.setModifier(Modifier.PUBLIC);
+        JDiffClassDescription.JDiffMethod method = new JDiffClassDescription.JDiffMethod(
+                "finalMethod", Modifier.PUBLIC, "void");
+        clz.addMethod(method);
+        clz.checkSignatureCompliance();
+        observer.validate();
+    }
+}
diff --git a/tests/signature-tests/src/android/signature/cts/tests/data/AbstractClass.java b/tests/signature-tests/src/android/signature/cts/tests/data/AbstractClass.java
new file mode 100644
index 0000000..527e7eb
--- /dev/null
+++ b/tests/signature-tests/src/android/signature/cts/tests/data/AbstractClass.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2009 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.signature.cts.tests.data;
+
+/**
+* This class is used as reference data for the JDiffClassDescriptionTest tests.
+*/
+public abstract class AbstractClass {
+
+}
diff --git a/tests/signature-tests/src/android/signature/cts/tests/data/FinalClass.java b/tests/signature-tests/src/android/signature/cts/tests/data/FinalClass.java
new file mode 100644
index 0000000..395e166
--- /dev/null
+++ b/tests/signature-tests/src/android/signature/cts/tests/data/FinalClass.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2007 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.signature.cts.tests.data;
+
+/**
+ * This class is used as reference data for the
+ * JDiffClassDescriptionTest tests.  These classes will actually be
+ * examined through reflection and Class.forName as part of testing
+ * JDiffClassDescription.  That is why there is no implementation for
+ * any of these methods.
+ */
+public final class FinalClass {
+    public final void finalMethod() { }
+    public void nonFinalMethod() { }
+}
diff --git a/tests/signature-tests/src/android/signature/cts/tests/data/NormalClass.java b/tests/signature-tests/src/android/signature/cts/tests/data/NormalClass.java
new file mode 100644
index 0000000..5acd696
--- /dev/null
+++ b/tests/signature-tests/src/android/signature/cts/tests/data/NormalClass.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2007 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.signature.cts.tests.data;
+
+/**
+ * This class is used as reference data for the
+ * JDiffClassDescriptionTest tests.  These classes will actually be
+ * examined through reflection and Class.forName as part of testing
+ * JDiffClassDescription.  That is why there is no implementation for
+ * any of these methods.
+ */
+public class NormalClass {
+    // Constructors to test.
+    public NormalClass() { }
+    private NormalClass(String arg1) { }
+    protected NormalClass(String arg1, String arg2) throws NormalException { }
+    NormalClass(String arg1, String arg2, String arg3) { }
+
+    // Methods to test.
+    public static void staticMethod() { }
+    public synchronized void syncMethod() { }
+    public void notSyncMethod() { }
+    boolean packageProtectedMethod() { return false; }
+    private void privateMethod() { }
+    protected String protectedMethod() { return null; }
+    public void throwsMethod() throws NormalException { }
+    public native void nativeMethod();
+    public void notNativeMethod() { }
+    public final void finalMethod() { }
+
+    // Fields to test.
+    public final String FINAL_FIELD = "";
+    public static String STATIC_FIELD;
+    public volatile String VOLATILE_FIELD;
+    public transient String TRANSIENT_FIELD;
+    String PACAKGE_FIELD;
+    private String PRIVATE_FIELD;
+    protected String PROTECTED_FIELD;
+
+    public class InnerClass {
+        public class InnerInnerClass {
+            private String innerInnerClassData;
+        }
+        private String innerClassData;
+    }
+
+    public interface InnerInterface {
+        void doSomething();
+    }
+}
diff --git a/tests/signature-tests/src/android/signature/cts/tests/data/NormalException.java b/tests/signature-tests/src/android/signature/cts/tests/data/NormalException.java
new file mode 100644
index 0000000..b2dd52d
--- /dev/null
+++ b/tests/signature-tests/src/android/signature/cts/tests/data/NormalException.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2007 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.signature.cts.tests.data;
+
+import java.lang.Exception;
+
+/**
+ * This class is used as reference data for the JDiffClassDescriptionTest tests.
+ */
+public class NormalException extends Exception {
+
+}
diff --git a/tests/signature-tests/src/android/signature/cts/tests/data/NormalInterface.java b/tests/signature-tests/src/android/signature/cts/tests/data/NormalInterface.java
new file mode 100644
index 0000000..899f4cc
--- /dev/null
+++ b/tests/signature-tests/src/android/signature/cts/tests/data/NormalInterface.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2007 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.signature.cts.tests.data;
+
+/**
+ * This class is used as reference data for the
+ * JDiffClassDescriptionTest tests.  These classes will actually be
+ * examined through reflection and Class.forName as part of testing
+ * JDiffClassDescription.  That is why there is no implementation for
+ * any of these methods.
+ */
+public interface NormalInterface {
+    void doSomething();
+}
diff --git a/tests/signature/Android.mk b/tests/signature/Android.mk
new file mode 100644
index 0000000..53ba50d
--- /dev/null
+++ b/tests/signature/Android.mk
@@ -0,0 +1,101 @@
+# Copyright (C) 2008 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)
+include $(CLEAR_VARS)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsSignatureTestCases
+
+LOCAL_SDK_VERSION := current
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+
+# To be passed in on command line
+CTS_API_VERSION ?= current
+ifeq (current,$(CTS_API_VERSION))
+android_api_description := frameworks/base/api/$(CTS_API_VERSION).txt
+else
+android_api_description := $(SRC_API_DIR)/$(CTS_API_VERSION).txt
+endif
+
+# Can't call local-intermediates-dir directly here because we have to
+# include BUILD_CTS_PACKAGE first.  Can't include BUILD_CTS_PACKAGE first
+# because we have to override LOCAL_RESOURCE_DIR first.  Hence this
+# hack.
+intermediates.COMMON := $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),,COMMON)
+signature_res_dir := $(intermediates.COMMON)/genres
+LOCAL_RESOURCE_DIR := $(signature_res_dir) $(LOCAL_PATH)/res
+
+include $(BUILD_CTS_PACKAGE)
+
+generated_res_stamp := $(intermediates.COMMON)/genres.stamp
+api_ver_file := $(intermediates.COMMON)/api_ver_is_$(CTS_API_VERSION)
+
+# The api_ver_file keeps track of which api version was last built.
+# By only ever having one of these magic files in existence and making
+# sure the generated resources rule depend on it, we can ensure that
+# the proper version of the api resource gets generated.
+$(api_ver_file):
+	$(hide) rm -f $(dir $@)/api_ver_is_* \
+		&& mkdir -p $(dir $@) && touch $@
+
+android_api_xml_description := $(intermediates.COMMON)/api.xml
+$(android_api_xml_description): $(android_api_description) | $(APICHECK)
+	@ echo "Convert api file to xml: $@"
+	@ mkdir -p $(dir $@)
+	$(hide) $(APICHECK_COMMAND) -convert2xml $< $@
+
+# Split up config/api/1.xml by "package" and save the files as the
+# resource files of SignatureTest.
+$(generated_res_stamp): PRIVATE_PATH := $(LOCAL_PATH)
+$(generated_res_stamp): PRIVATE_MODULE := $(LOCAL_MODULE)
+$(generated_res_stamp): PRIVATE_RES_DIR := $(signature_res_dir)
+$(generated_res_stamp): PRIVATE_API_XML_DESC := $(android_api_xml_description)
+$(generated_res_stamp): $(api_ver_file)
+$(generated_res_stamp): $(android_api_xml_description)
+	@ echo "Copy generated resources: $(PRIVATE_MODULE)"
+	$(hide) python cts/tools/utils/android_api_description_splitter.py \
+		$(PRIVATE_API_XML_DESC) $(PRIVATE_RES_DIR) package
+	$(hide) touch $@
+
+$(R_file_stamp): $(generated_res_stamp)
+
+# clean up temp vars
+android_api_xml_description :=
+api_ver_file :=
+generated_res_stamp :=
+signature_res_dir :=
+android_api_description :=
+CTS_API_VERSION :=
+
+# signature-hostside java library (for testing)
+# ============================================================
+
+include $(CLEAR_VARS)
+
+# These files are for device-side only, so filter-out for host library
+LOCAL_DEVICE_ONLY_SOURCES := %/SignatureTest.java
+
+LOCAL_SRC_FILES := $(filter-out $(LOCAL_DEVICE_ONLY_SOURCES), $(call all-java-files-under, src))
+
+LOCAL_MODULE := signature-hostside
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_HOST_JAVA_LIBRARY)
\ No newline at end of file
diff --git a/tests/signature/AndroidManifest.xml b/tests/signature/AndroidManifest.xml
new file mode 100644
index 0000000..e42302e
--- /dev/null
+++ b/tests/signature/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2008 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.signature">
+    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
+
+    <application>
+        <uses-library android:name="android.test.runner"/>
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="android.signature"
+                     android:label="API Signature Test"/>
+
+</manifest>
\ No newline at end of file
diff --git a/tests/SignatureTest/res/raw/excludepackages.txt b/tests/signature/res/raw/excludepackages.txt
similarity index 100%
rename from tests/SignatureTest/res/raw/excludepackages.txt
rename to tests/signature/res/raw/excludepackages.txt
diff --git a/tests/signature/src/android/signature/cts/FailureType.java b/tests/signature/src/android/signature/cts/FailureType.java
new file mode 100644
index 0000000..5aaebc4
--- /dev/null
+++ b/tests/signature/src/android/signature/cts/FailureType.java
@@ -0,0 +1,16 @@
+package android.signature.cts;
+
+/**
+ * Define the type of the signature check failures.
+ */
+public enum FailureType {
+    MISSING_CLASS,
+    MISSING_INTERFACE,
+    MISSING_METHOD,
+    MISSING_FIELD,
+    MISMATCH_CLASS,
+    MISMATCH_INTERFACE,
+    MISMATCH_METHOD,
+    MISMATCH_FIELD,
+    CAUGHT_EXCEPTION,
+}
diff --git a/tests/signature/src/android/signature/cts/JDiffClassDescription.java b/tests/signature/src/android/signature/cts/JDiffClassDescription.java
new file mode 100644
index 0000000..afcaa15
--- /dev/null
+++ b/tests/signature/src/android/signature/cts/JDiffClassDescription.java
@@ -0,0 +1,1223 @@
+/*
+ * Copyright (C) 2008 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.signature.cts;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.lang.reflect.WildcardType;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Represents class descriptions loaded from a jdiff xml file.  Used
+ * for CTS SignatureTests.
+ */
+public class JDiffClassDescription {
+    /** Indicates that the class is an annotation. */
+    private static final int CLASS_MODIFIER_ANNOTATION = 0x00002000;
+    /** Indicates that the class is an enum. */
+    private static final int CLASS_MODIFIER_ENUM       = 0x00004000;
+
+    /** Indicates that the method is a bridge method. */
+    private static final int METHOD_MODIFIER_BRIDGE    = 0x00000040;
+    /** Indicates that the method is takes a variable number of arguments. */
+    private static final int METHOD_MODIFIER_VAR_ARGS  = 0x00000080;
+    /** Indicates that the method is a synthetic method. */
+    private static final int METHOD_MODIFIER_SYNTHETIC = 0x00001000;
+
+    public enum JDiffType {
+        INTERFACE, CLASS
+    }
+
+    @SuppressWarnings("unchecked")
+    private Class<?> mClass;
+    // A map of field name to field of the fields contained in {@code mClass}
+    private Map<String, Field> mClassFieldMap;
+
+    private String mPackageName;
+    private String mShortClassName;
+
+    /**
+     * Package name + short class name
+     */
+    private String mAbsoluteClassName;
+
+    private int mModifier;
+
+    private String mExtendedClass;
+    private List<String> implInterfaces = new ArrayList<String>();
+    private List<JDiffField> jDiffFields = new ArrayList<JDiffField>();
+    private List<JDiffMethod> jDiffMethods = new ArrayList<JDiffMethod>();
+    private List<JDiffConstructor> jDiffConstructors = new ArrayList<JDiffConstructor>();
+
+    private ResultObserver mResultObserver;
+    private JDiffType mClassType;
+
+    /**
+     * Creates a new JDiffClassDescription.
+     *
+     * @param pkg the java package this class will end up in.
+     * @param className the name of the class.
+     */
+    public JDiffClassDescription(String pkg, String className) {
+        this(pkg, className, new ResultObserver() {
+            @Override
+            public void notifyFailure(FailureType type, String name, String errorMessage) {
+                // This is a null result observer that doesn't do anything.
+            }
+        });
+    }
+
+    /**
+     * Creates a new JDiffClassDescription with the specified results
+     * observer.
+     *
+     * @param pkg the java package this class belongs in.
+     * @param className the name of the class.
+     * @param resultObserver the resultObserver to get results with.
+     */
+    public JDiffClassDescription(String pkg, String className, ResultObserver resultObserver) {
+        mPackageName = pkg;
+        mShortClassName = className;
+        mResultObserver = resultObserver;
+    }
+
+    /**
+     * adds implemented interface name.
+     *
+     * @param iname name of interface
+     */
+    public void addImplInterface(String iname) {
+        implInterfaces.add(iname);
+    }
+
+    /**
+     * Adds a field.
+     *
+     * @param field the field to be added.
+     */
+    public void addField(JDiffField field) {
+        jDiffFields.add(field);
+    }
+
+    /**
+     * Adds a method.
+     *
+     * @param method the method to be added.
+     */
+    public void addMethod(JDiffMethod method) {
+        jDiffMethods.add(method);
+    }
+
+    /**
+     * Adds a constructor.
+     *
+     * @param tc the constructor to be added.
+     */
+    public void addConstructor(JDiffConstructor tc) {
+        jDiffConstructors.add(tc);
+    }
+
+    static String convertModifiersToAccessLevel(int modifiers) {
+        if ((modifiers & Modifier.PUBLIC) != 0) {
+            return "public";
+        } else if ((modifiers & Modifier.PRIVATE) != 0) {
+            return "private";
+        } else if ((modifiers & Modifier.PROTECTED) != 0) {
+            return "protected";
+        } else {
+            // package protected
+            return "";
+        }
+    }
+
+    static String convertModifersToModifierString(int modifiers) {
+        StringBuffer sb = new StringBuffer();
+        boolean isFirst = true;
+
+        // order taken from Java Language Spec, sections 8.1.1, 8.3.1, and 8.4.3
+        if ((modifiers & Modifier.ABSTRACT) != 0) {
+            if (isFirst) {
+                isFirst = false;
+            } else {
+                sb.append(" ");
+            }
+            sb.append("abstract");
+        }
+        if ((modifiers & Modifier.STATIC) != 0) {
+            if (isFirst) {
+                isFirst = false;
+            } else {
+                sb.append(" ");
+            }
+            sb.append("static");
+        }
+        if ((modifiers & Modifier.FINAL) != 0) {
+            if (isFirst) {
+                isFirst = false;
+            } else {
+                sb.append(" ");
+            }
+            sb.append("final");
+        }
+        if ((modifiers & Modifier.TRANSIENT) != 0) {
+            if (isFirst) {
+                isFirst = false;
+            } else {
+                sb.append(" ");
+            }
+            sb.append("transient");
+        }
+        if ((modifiers & Modifier.VOLATILE) != 0) {
+            if (isFirst) {
+                isFirst = false;
+            } else {
+                sb.append(" ");
+            }
+            sb.append("volatile");
+        }
+        if ((modifiers & Modifier.SYNCHRONIZED) != 0) {
+            if (isFirst) {
+                isFirst = false;
+            } else {
+                sb.append(" ");
+            }
+            sb.append("synchronized");
+        }
+        if ((modifiers & Modifier.NATIVE) != 0) {
+            if (isFirst) {
+                isFirst = false;
+            } else {
+                sb.append(" ");
+            }
+            sb.append("native");
+        }
+        if ((modifiers & Modifier.STRICT) != 0) {
+            if (isFirst) {
+                isFirst = false;
+            } else {
+                sb.append(" ");
+            }
+            sb.append("strictfp");
+        }
+
+        return sb.toString();
+    }
+
+    public abstract static class JDiffElement {
+        final String mName;
+        int mModifier;
+
+        public JDiffElement(String name, int modifier) {
+            mName = name;
+            mModifier = modifier;
+        }
+    }
+
+    /**
+     * Represents a  field.
+     */
+    public static final class JDiffField extends JDiffElement {
+        private String mFieldType;
+
+        public JDiffField(String name, String fieldType, int modifier) {
+            super(name, modifier);
+
+            mFieldType = fieldType;
+        }
+
+        /**
+         * Make a readable string according to the class name specified.
+         *
+         * @param className The specified class name.
+         * @return A readable string to represent this field along with the class name.
+         */
+        public String toReadableString(String className) {
+            return className + "#" + mName + "(" + mFieldType + ")";
+        }
+
+        public String toSignatureString() {
+            StringBuffer sb = new StringBuffer();
+
+            // access level
+            String accesLevel = convertModifiersToAccessLevel(mModifier);
+            if (!"".equals(accesLevel)) {
+                sb.append(accesLevel).append(" ");
+            }
+
+            String modifierString = convertModifersToModifierString(mModifier);
+            if (!"".equals(modifierString)) {
+                sb.append(modifierString).append(" ");
+            }
+
+            sb.append(mFieldType).append(" ");
+
+            sb.append(mName);
+
+            return sb.toString();
+        }
+    }
+
+    /**
+     * Represents a method.
+     */
+    public static class JDiffMethod extends JDiffElement {
+        protected String mReturnType;
+        protected ArrayList<String> mParamList;
+        protected ArrayList<String> mExceptionList;
+
+        public JDiffMethod(String name, int modifier, String returnType) {
+            super(name, modifier);
+
+            if (returnType == null) {
+                mReturnType = "void";
+            } else {
+                mReturnType = scrubJdiffParamType(returnType);
+            }
+
+            mParamList = new ArrayList<String>();
+            mExceptionList = new ArrayList<String>();
+        }
+
+        /**
+         * Adds a parameter.
+         *
+         * @param param parameter type
+         */
+        public void addParam(String param) {
+            mParamList.add(scrubJdiffParamType(param));
+        }
+
+        /**
+         * Adds an exception.
+         *
+         * @param exceptionName name of exception
+         */
+        public void addException(String exceptionName) {
+            mExceptionList.add(exceptionName);
+        }
+
+        /**
+         * Makes a readable string according to the class name specified.
+         *
+         * @param className The specified class name.
+         * @return A readable string to represent this method along with the class name.
+         */
+        public String toReadableString(String className) {
+            return className + "#" + mName + "(" + convertParamList(mParamList) + ")";
+        }
+
+        /**
+         * Converts a parameter array to a string
+         *
+         * @param params the array to convert
+         * @return converted parameter string
+         */
+        private static String convertParamList(final ArrayList<String> params) {
+
+            StringBuffer paramList = new StringBuffer();
+
+            if (params != null) {
+                for (String str : params) {
+                    paramList.append(str + ", ");
+                }
+                if (params.size() > 0) {
+                    paramList.delete(paramList.length() - 2, paramList.length());
+                }
+            }
+
+            return paramList.toString();
+        }
+
+        public String toSignatureString() {
+            StringBuffer sb = new StringBuffer();
+
+            // access level
+            String accesLevel = convertModifiersToAccessLevel(mModifier);
+            if (!"".equals(accesLevel)) {
+                sb.append(accesLevel).append(" ");
+            }
+
+            String modifierString = convertModifersToModifierString(mModifier);
+            if (!"".equals(modifierString)) {
+                sb.append(modifierString).append(" ");
+            }
+
+            String returnType = getReturnType();
+            if (!"".equals(returnType)) {
+                sb.append(returnType).append(" ");
+            }
+
+            sb.append(mName);
+            sb.append("(");
+            for (int x = 0; x < mParamList.size(); x++) {
+                sb.append(mParamList.get(x));
+                if (x + 1 != mParamList.size()) {
+                    sb.append(", ");
+                }
+            }
+            sb.append(")");
+
+            // does it throw?
+            if (mExceptionList.size() > 0) {
+                sb.append(" throws ");
+                for (int x = 0; x < mExceptionList.size(); x++) {
+                    sb.append(mExceptionList.get(x));
+                    if (x + 1 != mExceptionList.size()) {
+                        sb.append(", ");
+                    }
+                }
+            }
+
+            return sb.toString();
+        }
+
+        /**
+         * Gets the return type.
+         *
+         * @return the return type of this method.
+         */
+        protected String getReturnType() {
+            return mReturnType;
+        }
+    }
+
+    /**
+     * Represents a constructor.
+     */
+    public static final class JDiffConstructor extends JDiffMethod {
+        public JDiffConstructor(String name, int modifier) {
+            super(name, modifier, null);
+        }
+
+        public JDiffConstructor(String name, String[] param, int modifier) {
+            super(name, modifier, null);
+
+            for (int i = 0; i < param.length; i++) {
+                addParam(param[i]);
+            }
+        }
+
+        /**
+         * Gets the return type.
+         *
+         * @return the return type of this method.
+         */
+        @Override
+        protected String getReturnType() {
+            // Constructors have no return type.
+            return "";
+        }
+    }
+
+    /**
+     * Checks test class's name, modifier, fields, constructors, and
+     * methods.
+     */
+    public void checkSignatureCompliance() {
+        checkClassCompliance();
+        if (mClass != null) {
+            mClassFieldMap = buildFieldMap(mClass);
+            checkFieldsCompliance();
+            checkConstructorCompliance();
+            checkMethodCompliance();
+        } else {
+            mClassFieldMap = null;
+        }
+    }
+
+    /**
+     * Checks to ensure that the modifiers value for two methods are
+     * compatible.
+     *
+     * Allowable differences are:
+     *   - synchronized is allowed to be removed from an apiMethod
+     *     that has it
+     *   - the native modified is ignored
+     *
+     * @param apiMethod the method read from the api file.
+     * @param reflectedMethod the method found via reflections.
+     */
+    private boolean areMethodModifiedCompatibile(JDiffMethod apiMethod ,
+            Method reflectedMethod) {
+
+        // If the apiMethod isn't synchronized
+        if (((apiMethod.mModifier & Modifier.SYNCHRONIZED) == 0) &&
+                // but the reflected method is
+                ((reflectedMethod.getModifiers() & Modifier.SYNCHRONIZED) != 0)) {
+            // that is a problem
+            return false;
+        }
+
+        // Mask off NATIVE since it is a don't care.  Also mask off
+        // SYNCHRONIZED since we've already handled that check.
+        int mod1 = reflectedMethod.getModifiers() & ~(Modifier.NATIVE | Modifier.SYNCHRONIZED);
+        int mod2 = apiMethod.mModifier & ~(Modifier.NATIVE | Modifier.SYNCHRONIZED);
+
+        // We can ignore FINAL for final classes
+        if ((mModifier & Modifier.FINAL) != 0) {
+            mod1 &= ~Modifier.FINAL;
+            mod2 &= ~Modifier.FINAL;
+        }
+
+        return mod1 == mod2;
+    }
+
+    /**
+     * Checks that the method found through reflection matches the
+     * specification from the API xml file.
+     */
+    private void checkMethodCompliance() {
+        for (JDiffMethod method : jDiffMethods) {
+            try {
+                // this is because jdiff think a method in an interface is not abstract
+                if (JDiffType.INTERFACE.equals(mClassType)) {
+                    method.mModifier |= Modifier.ABSTRACT;
+                }
+
+                Method m = findMatchingMethod(method);
+                if (m == null) {
+                    mResultObserver.notifyFailure(FailureType.MISSING_METHOD,
+                            method.toReadableString(mAbsoluteClassName),
+                            "No method with correct signature found:" +
+                            method.toSignatureString());
+                } else {
+                    if (m.isVarArgs()) {
+                        method.mModifier |= METHOD_MODIFIER_VAR_ARGS;
+                    }
+                    if (m.isBridge()) {
+                        method.mModifier |= METHOD_MODIFIER_BRIDGE;
+                    }
+                    if (m.isSynthetic()) {
+                        method.mModifier |= METHOD_MODIFIER_SYNTHETIC;
+                    }
+
+                    // FIXME: A workaround to fix the final mismatch on enumeration
+                    if (mClass.isEnum() && method.mName.equals("values")) {
+                        return;
+                    }
+
+                    if (!areMethodModifiedCompatibile(method, m)) {
+                        mResultObserver.notifyFailure(FailureType.MISMATCH_METHOD,
+                                method.toReadableString(mAbsoluteClassName),
+                                "Non-compatible method found when looking for " +
+                                method.toSignatureString());
+                    }
+                }
+            } catch (Exception e) {
+                loge("Got exception when checking method compliance", e);
+                mResultObserver.notifyFailure(FailureType.CAUGHT_EXCEPTION,
+                        method.toReadableString(mAbsoluteClassName),
+                "Exception!");
+            }
+        }
+    }
+
+    /**
+     * Checks if the two types of methods are the same.
+     *
+     * @param jDiffMethod the jDiffMethod to compare
+     * @param method the reflected method to compare
+     * @return true, if both methods are the same
+     */
+    private boolean matches(JDiffMethod jDiffMethod, Method method) {
+        // If the method names aren't equal, the methods can't match.
+        if (jDiffMethod.mName.equals(method.getName())) {
+            String jdiffReturnType = jDiffMethod.mReturnType;
+            String reflectionReturnType = typeToString(method.getGenericReturnType());
+            List<String> jdiffParamList = jDiffMethod.mParamList;
+
+            // Next, compare the return types of the two methods.  If
+            // they aren't equal, the methods can't match.
+            if (jdiffReturnType.equals(reflectionReturnType)) {
+                Type[] params = method.getGenericParameterTypes();
+                // Next, check the method parameters.  If they have
+                // different number of parameters, the two methods
+                // can't match.
+                if (jdiffParamList.size() == params.length) {
+                    // If any of the parameters don't match, the
+                    // methods can't match.
+                    for (int i = 0; i < jdiffParamList.size(); i++) {
+                        if (!compareParam(jdiffParamList.get(i), params[i])) {
+                            return false;
+                        }
+                    }
+                    // We've passed all the tests, the methods do
+                    // match.
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Finds the reflected method specified by the method description.
+     *
+     * @param method description of the method to find
+     * @return the reflected method, or null if not found.
+     */
+    @SuppressWarnings("unchecked")
+    private Method findMatchingMethod(JDiffMethod method) {
+        Method[] methods = mClass.getDeclaredMethods();
+
+        for (Method m : methods) {
+            if (matches(method, m)) {
+                return m;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Compares the parameter from the API and the parameter from
+     * reflection.
+     *
+     * @param jdiffParam param parsed from the API xml file.
+     * @param reflectionParamType param gotten from the Java reflection.
+     * @return True if the two params match, otherwise return false.
+     */
+    private static boolean compareParam(String jdiffParam, Type reflectionParamType) {
+        if (jdiffParam == null) {
+            return false;
+        }
+
+        String reflectionParam = typeToString(reflectionParamType);
+        // Most things aren't varargs, so just do a simple compare
+        // first.
+        if (jdiffParam.equals(reflectionParam)) {
+            return true;
+        }
+
+        // Check for varargs.  jdiff reports varargs as ..., while
+        // reflection reports them as []
+        int jdiffParamEndOffset = jdiffParam.indexOf("...");
+        int reflectionParamEndOffset = reflectionParam.indexOf("[]");
+        if (jdiffParamEndOffset != -1 && reflectionParamEndOffset != -1) {
+            jdiffParam = jdiffParam.substring(0, jdiffParamEndOffset);
+            reflectionParam = reflectionParam.substring(0, reflectionParamEndOffset);
+            return jdiffParam.equals(reflectionParam);
+        }
+
+        return false;
+    }
+
+    /**
+     * Checks whether the constructor parsed from API xml file and
+     * Java reflection are compliant.
+     */
+    @SuppressWarnings("unchecked")
+    private void checkConstructorCompliance() {
+        for (JDiffConstructor con : jDiffConstructors) {
+            try {
+                Constructor<?> c = findMatchingConstructor(con);
+                if (c == null) {
+                    mResultObserver.notifyFailure(FailureType.MISSING_METHOD,
+                            con.toReadableString(mAbsoluteClassName),
+                            "No method with correct signature found:" +
+                            con.toSignatureString());
+                } else {
+                    if (c.isVarArgs()) {// some method's parameter are variable args
+                        con.mModifier |= METHOD_MODIFIER_VAR_ARGS;
+                    }
+                    if (c.getModifiers() != con.mModifier) {
+                        mResultObserver.notifyFailure(
+                                FailureType.MISMATCH_METHOD,
+                                con.toReadableString(mAbsoluteClassName),
+                                "Non-compatible method found when looking for " +
+                                con.toSignatureString());
+                    }
+                }
+            } catch (Exception e) {
+                loge("Got exception when checking constructor compliance", e);
+                mResultObserver.notifyFailure(FailureType.CAUGHT_EXCEPTION,
+                        con.toReadableString(mAbsoluteClassName),
+                "Exception!");
+            }
+        }
+    }
+
+    /**
+     * Searches available constructor.
+     *
+     * @param jdiffDes constructor description to find.
+     * @return reflected constructor, or null if not found.
+     */
+    @SuppressWarnings("unchecked")
+    private Constructor<?> findMatchingConstructor(JDiffConstructor jdiffDes) {
+        for (Constructor<?> c : mClass.getDeclaredConstructors()) {
+            Type[] params = c.getGenericParameterTypes();
+            boolean isStaticClass = ((mClass.getModifiers() & Modifier.STATIC) != 0);
+
+            int startParamOffset = 0;
+            int numberOfParams = params.length;
+
+            // non-static inner class -> skip implicit parent pointer
+            // as first arg
+            if (mClass.isMemberClass() && !isStaticClass && params.length >= 1) {
+                startParamOffset = 1;
+                --numberOfParams;
+            }
+
+            ArrayList<String> jdiffParamList = jdiffDes.mParamList;
+            if (jdiffParamList.size() == numberOfParams) {
+                boolean isFound = true;
+                // i counts jdiff params, j counts reflected params
+                int i = 0;
+                int j = startParamOffset;
+                while (i < jdiffParamList.size()) {
+                    if (!compareParam(jdiffParamList.get(i), params[j])) {
+                        isFound = false;
+                        break;
+                    }
+                    ++i;
+                    ++j;
+                }
+                if (isFound) {
+                    return c;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Checks all fields in test class for compliance with the API
+     * xml.
+     */
+    @SuppressWarnings("unchecked")
+    private void checkFieldsCompliance() {
+        for (JDiffField field : jDiffFields) {
+            try {
+                Field f = findMatchingField(field);
+                if (f == null) {
+                    mResultObserver.notifyFailure(FailureType.MISSING_FIELD,
+                            field.toReadableString(mAbsoluteClassName),
+                            "No field with correct signature found:" +
+                            field.toSignatureString());
+                } else if (f.getModifiers() != field.mModifier) {
+                    mResultObserver.notifyFailure(FailureType.MISMATCH_FIELD,
+                            field.toReadableString(mAbsoluteClassName),
+                            "Non-compatible field modifiers found when looking for " +
+                            field.toSignatureString());
+                } else if (!f.getType().getCanonicalName().equals(field.mFieldType)) {
+                    // type name does not match, but this might be a generic
+                    String genericTypeName = null;
+                    Type type = f.getGenericType();
+                    if (type != null) {
+                        genericTypeName = type instanceof Class ? ((Class) type).getName() :
+                            type.toString().replace('$', '.');
+                    }
+                    if (genericTypeName == null || !genericTypeName.equals(field.mFieldType)) {
+                        mResultObserver.notifyFailure(
+                                FailureType.MISMATCH_FIELD,
+                                field.toReadableString(mAbsoluteClassName),
+                                "Non-compatible field type found when looking for " +
+                                field.toSignatureString());
+                    }
+                }
+
+            } catch (Exception e) {
+                loge("Got exception when checking field compliance", e);
+                mResultObserver.notifyFailure(
+                        FailureType.CAUGHT_EXCEPTION,
+                        field.toReadableString(mAbsoluteClassName),
+                        "Exception!");
+            }
+        }
+    }
+
+    /**
+     * Finds the reflected field specified by the field description.
+     *
+     * @param field the field description to find
+     * @return the reflected field, or null if not found.
+     */
+    private Field findMatchingField(JDiffField field) {
+        return mClassFieldMap.get(field.mName);
+    }
+
+    /**
+     * Checks if the class under test has compliant modifiers compared to the API.
+     *
+     * @return true if modifiers are compliant.
+     */
+    private boolean checkClassModifiersCompliance() {
+        int reflectionModifier = mClass.getModifiers();
+        int apiModifier = mModifier;
+
+        // If the api class isn't abstract
+        if (((apiModifier & Modifier.ABSTRACT) == 0) &&
+                // but the reflected class is
+                ((reflectionModifier & Modifier.ABSTRACT) != 0) &&
+                // and it isn't an enum
+                !isEnumType()) {
+            // that is a problem
+            return false;
+        }
+        // ABSTRACT check passed, so mask off ABSTRACT
+        reflectionModifier &= ~Modifier.ABSTRACT;
+        apiModifier &= ~Modifier.ABSTRACT;
+
+        if (isAnnotation()) {
+            reflectionModifier &= ~CLASS_MODIFIER_ANNOTATION;
+        }
+        if (mClass.isInterface()) {
+            reflectionModifier &= ~(Modifier.INTERFACE);
+        }
+        if (isEnumType() && mClass.isEnum()) {
+            reflectionModifier &= ~CLASS_MODIFIER_ENUM;
+        }
+
+        return ((reflectionModifier == apiModifier) &&
+                (isEnumType() == mClass.isEnum()));
+    }
+
+    /**
+     * Checks if the class under test is compliant with regards to
+     * annnotations when compared to the API.
+     *
+     * @return true if the class is compliant
+     */
+    private boolean checkClassAnnotationCompliace() {
+        if (mClass.isAnnotation()) {
+            // check annotation
+            for (String inter : implInterfaces) {
+                if ("java.lang.annotation.Annotation".equals(inter)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Checks if the class under test extends the proper classes
+     * according to the API.
+     *
+     * @return true if the class is compliant.
+     */
+    private boolean checkClassExtendsCompliance() {
+        // Nothing to check if it doesn't extend anything.
+        if (mExtendedClass != null) {
+            Class<?> superClass = mClass.getSuperclass();
+
+            while (superClass != null) {
+                if (superClass.getCanonicalName().equals(mExtendedClass)) {
+                    return true;
+                }
+                superClass = superClass.getSuperclass();
+            }
+            // Couldn't find a matching superclass.
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Checks if the class under test implements the proper interfaces
+     * according to the API.
+     *
+     * @return true if the class is compliant
+     */
+    private boolean checkClassImplementsCompliance() {
+        Class<?>[] interfaces = mClass.getInterfaces();
+        Set<String> interFaceSet = new HashSet<String>();
+
+        for (Class<?> c : interfaces) {
+            interFaceSet.add(c.getCanonicalName());
+        }
+
+        for (String inter : implInterfaces) {
+            if (!interFaceSet.contains(inter)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Checks that the class found through reflection matches the
+     * specification from the API xml file.
+     */
+    @SuppressWarnings("unchecked")
+    private void checkClassCompliance() {
+        try {
+            mAbsoluteClassName = mPackageName + "." + mShortClassName;
+            mClass = findMatchingClass();
+
+            if (mClass == null) {
+                // No class found, notify the observer according to the class type
+                if (JDiffType.INTERFACE.equals(mClassType)) {
+                    mResultObserver.notifyFailure(FailureType.MISSING_INTERFACE,
+                            mAbsoluteClassName,
+                            "Classloader is unable to find " + mAbsoluteClassName);
+                } else {
+                    mResultObserver.notifyFailure(FailureType.MISSING_CLASS,
+                            mAbsoluteClassName,
+                            "Classloader is unable to find " + mAbsoluteClassName);
+                }
+
+                return;
+            }
+            if (!checkClassModifiersCompliance()) {
+                logMismatchInterfaceSignature(mAbsoluteClassName,
+                        "Non-compatible class found when looking for " +
+                        toSignatureString());
+                return;
+            }
+
+            if (!checkClassAnnotationCompliace()) {
+                logMismatchInterfaceSignature(mAbsoluteClassName,
+                "Annotation mismatch");
+                return;
+            }
+
+            if (!mClass.isAnnotation()) {
+                // check father class
+                if (!checkClassExtendsCompliance()) {
+                    logMismatchInterfaceSignature(mAbsoluteClassName,
+                    "Extends mismatch");
+                    return;
+                }
+
+                // check implements interface
+                if (!checkClassImplementsCompliance()) {
+                    logMismatchInterfaceSignature(mAbsoluteClassName,
+                    "Implements mismatch");
+                    return;
+                }
+            }
+        } catch (Exception e) {
+            loge("Got exception when checking field compliance", e);
+            mResultObserver.notifyFailure(
+                    FailureType.CAUGHT_EXCEPTION,
+                    mAbsoluteClassName,
+                    "Exception!");
+        }
+    }
+
+
+    /**
+     * Convert the class into a printable signature string.
+     *
+     * @return the signature string
+     */
+    public String toSignatureString() {
+        StringBuffer sb = new StringBuffer();
+
+        String accessLevel = convertModifiersToAccessLevel(mModifier);
+        if (!"".equals(accessLevel)) {
+            sb.append(accessLevel).append(" ");
+        }
+        if (!JDiffType.INTERFACE.equals(mClassType)) {
+            String modifierString = convertModifersToModifierString(mModifier);
+            if (!"".equals(modifierString)) {
+                sb.append(modifierString).append(" ");
+            }
+            sb.append("class ");
+        } else {
+            sb.append("interface ");
+        }
+        // class name
+        sb.append(mShortClassName);
+
+        // does it extends something?
+        if (mExtendedClass != null) {
+            sb.append(" extends ").append(mExtendedClass).append(" ");
+        }
+
+        // implements something?
+        if (implInterfaces.size() > 0) {
+            sb.append(" implements ");
+            for (int x = 0; x < implInterfaces.size(); x++) {
+                String interf = implInterfaces.get(x);
+                sb.append(interf);
+                // if not last elements
+                if (x + 1 != implInterfaces.size()) {
+                    sb.append(", ");
+                }
+            }
+        }
+        return sb.toString();
+    }
+
+    private void logMismatchInterfaceSignature(String classFullName, String errorMessage) {
+        if (JDiffType.INTERFACE.equals(mClassType)) {
+            mResultObserver.notifyFailure(FailureType.MISMATCH_INTERFACE,
+                    classFullName,
+                    errorMessage);
+        } else {
+            mResultObserver.notifyFailure(FailureType.MISMATCH_CLASS,
+                    classFullName,
+                    errorMessage);
+        }
+    }
+
+    /**
+     * Sees if the class under test is actually an enum.
+     *
+     * @return true if this class is enum
+     */
+    private boolean isEnumType() {
+        return "java.lang.Enum".equals(mExtendedClass);
+    }
+
+    /**
+     * Finds the reflected class for the class under test.
+     *
+     * @return the reflected class, or null if not found.
+     */
+    @SuppressWarnings("unchecked")
+    private Class<?> findMatchingClass() {
+        // even if there are no . in the string, split will return an
+        // array of length 1
+        String[] classNameParts = mShortClassName.split("\\.");
+        String currentName = mPackageName + "." + classNameParts[0];
+
+        try {
+            // Check to see if the class we're looking for is the top
+            // level class.
+            Class<?> clz = Class.forName(currentName,
+                    false,
+                    this.getClass().getClassLoader());
+            if (clz.getCanonicalName().equals(mAbsoluteClassName)) {
+                return clz;
+            }
+
+            // Then it must be an inner class.
+            for (int x = 1; x < classNameParts.length; x++) {
+                clz = findInnerClassByName(clz, classNameParts[x]);
+                if (clz == null) {
+                    return null;
+                }
+                if (clz.getCanonicalName().equals(mAbsoluteClassName)) {
+                    return clz;
+                }
+            }
+        } catch (ClassNotFoundException e) {
+            loge("ClassNotFoundException for " + mPackageName + "." + mShortClassName, e);
+            return null;
+        }
+        return null;
+    }
+
+    /**
+     * Searches the class for the specified inner class.
+     *
+     * @param clz the class to search in.
+     * @param simpleName the simpleName of the class to find
+     * @returns the class being searched for, or null if it can't be found.
+     */
+    private Class<?> findInnerClassByName(Class<?> clz, String simpleName) {
+        for (Class<?> c : clz.getDeclaredClasses()) {
+            if (c.getSimpleName().equals(simpleName)) {
+                return c;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Sees if the class under test is actually an annotation.
+     *
+     * @return true if this class is Annotation.
+     */
+    private boolean isAnnotation() {
+        if (implInterfaces.contains("java.lang.annotation.Annotation")) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Gets the class name for the class under test.
+     *
+     * @return the class name.
+     */
+    public String getClassName() {
+        return mShortClassName;
+    }
+
+    /**
+     * Sets the modifier for the class under test.
+     *
+     * @param modifier the modifier
+     */
+    public void setModifier(int modifier) {
+        mModifier = modifier;
+    }
+
+    /**
+     * Sets the return type for the class under test.
+     *
+     * @param type the return type
+     */
+    public void setType(JDiffType type) {
+        mClassType = type;
+    }
+
+    /**
+     * Sets the class that is beign extended for the class under test.
+     *
+     * @param extendsClass the class being extended.
+     */
+    public void setExtendsClass(String extendsClass) {
+        mExtendedClass = extendsClass;
+    }
+
+    /**
+     * Registers a ResultObserver to process the output from the
+     * compliance testing done in this class.
+     *
+     * @param resultObserver the observer to register.
+     */
+    public void registerResultObserver(ResultObserver resultObserver) {
+        mResultObserver = resultObserver;
+    }
+
+    /**
+     * Converts WildcardType array into a jdiff compatible string..
+     * This is a helper function for typeToString.
+     *
+     * @param types array of types to format.
+     * @return the jdiff formatted string.
+     */
+    private static String concatWildcardTypes(Type[] types) {
+        StringBuffer sb = new StringBuffer();
+        int elementNum = 0;
+        for (Type t : types) {
+            sb.append(typeToString(t));
+            if (++elementNum < types.length) {
+                sb.append(" & ");
+            }
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Converts a Type into a jdiff compatible String.  The returned
+     * types from this function should match the same Strings that
+     * jdiff is providing to us.
+     *
+     * @param type the type to convert.
+     * @return the jdiff formatted string.
+     */
+    private static String typeToString(Type type) {
+        if (type instanceof ParameterizedType) {
+            ParameterizedType pt = (ParameterizedType) type;
+
+            StringBuffer sb = new StringBuffer();
+            sb.append(typeToString(pt.getRawType()));
+            sb.append("<");
+
+            int elementNum = 0;
+            Type[] types = pt.getActualTypeArguments();
+            for (Type t : types) {
+                sb.append(typeToString(t));
+                if (++elementNum < types.length) {
+                    sb.append(", ");
+                }
+            }
+
+            sb.append(">");
+            return sb.toString();
+        } else if (type instanceof TypeVariable) {
+            return ((TypeVariable<?>) type).getName();
+        } else if (type instanceof Class) {
+            return ((Class<?>) type).getCanonicalName();
+        } else if (type instanceof GenericArrayType) {
+            String typeName = typeToString(((GenericArrayType) type).getGenericComponentType());
+            return typeName + "[]";
+        } else if (type instanceof WildcardType) {
+            WildcardType wt = (WildcardType) type;
+            Type[] lowerBounds = wt.getLowerBounds();
+            if (lowerBounds.length == 0) {
+                String name = "? extends " + concatWildcardTypes(wt.getUpperBounds());
+
+                // Special case for ?
+                if (name.equals("? extends java.lang.Object")) {
+                    return "?";
+                } else {
+                    return name;
+                }
+            } else {
+                String name = concatWildcardTypes(wt.getUpperBounds()) +
+                " super " +
+                concatWildcardTypes(wt.getLowerBounds());
+                // Another special case for ?
+                name = name.replace("java.lang.Object", "?");
+                return name;
+            }
+        } else {
+            throw new RuntimeException("Got an unknown java.lang.Type");
+        }
+    }
+
+    /**
+     * Cleans up jdiff parameters to canonicalize them.
+     *
+     * @param paramType the parameter from jdiff.
+     * @return the scrubbed version of the parameter.
+     */
+    private static String scrubJdiffParamType(String paramType) {
+        // <? extends java.lang.Object and <?> are the same, so
+        // canonicalize them to one form.
+        return paramType.replace("<? extends java.lang.Object>", "<?>");
+    }
+
+    /**
+     * Scan a class (an its entire inheritance chain) for fields.
+     *
+     * @return a {@link Map} of fieldName to {@link Field}
+     */
+    private static Map<String, Field> buildFieldMap(Class testClass) {
+        Map<String, Field> fieldMap = new HashMap<String, Field>();
+        // Scan the superclass
+        if (testClass.getSuperclass() != null) {
+            fieldMap.putAll(buildFieldMap(testClass.getSuperclass()));
+        }
+
+        // Scan the interfaces
+        for (Class interfaceClass : testClass.getInterfaces()) {
+            fieldMap.putAll(buildFieldMap(interfaceClass));
+        }
+
+        // Check the fields in the test class
+        for (Field field : testClass.getDeclaredFields()) {
+            fieldMap.put(field.getName(), field);
+        }
+
+        return fieldMap;
+    }
+
+    private static void loge(String message, Exception exception) {
+        System.err.println(String.format("%s: %s", message, exception));
+    }
+}
diff --git a/tests/signature/src/android/signature/cts/ResultObserver.java b/tests/signature/src/android/signature/cts/ResultObserver.java
new file mode 100644
index 0000000..33234e9
--- /dev/null
+++ b/tests/signature/src/android/signature/cts/ResultObserver.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2008 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.signature.cts;
+
+/**
+ * Interface for saving signature test result.
+ */
+public interface ResultObserver {
+    /**
+     * Notify failure.
+     * @param type Failure type.
+     * @param name Name of the failed element (interface/class/method/field)
+     * @param errorMessage a descriptive message indicating why it failed.
+     */
+    void notifyFailure(FailureType type, String name, String errorMessage);
+
+}
diff --git a/tests/signature/src/android/signature/cts/SignatureTest.java b/tests/signature/src/android/signature/cts/SignatureTest.java
new file mode 100644
index 0000000..85b77f8
--- /dev/null
+++ b/tests/signature/src/android/signature/cts/SignatureTest.java
@@ -0,0 +1,350 @@
+/*
+ * 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.
+ */
+
+package android.signature.cts;
+
+import android.content.res.Resources;
+import android.signature.R;
+import android.signature.cts.JDiffClassDescription.JDiffConstructor;
+import android.signature.cts.JDiffClassDescription.JDiffField;
+import android.signature.cts.JDiffClassDescription.JDiffMethod;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+
+/**
+ * Performs the signature check via a JUnit test.
+ */
+public class SignatureTest extends AndroidTestCase {
+
+    private static final String TAG = SignatureTest.class.getSimpleName();
+
+    private static final String TAG_ROOT = "api";
+    private static final String TAG_PACKAGE = "package";
+    private static final String TAG_CLASS = "class";
+    private static final String TAG_INTERFACE = "interface";
+    private static final String TAG_IMPLEMENTS = "implements";
+    private static final String TAG_CONSTRUCTOR = "constructor";
+    private static final String TAG_METHOD = "method";
+    private static final String TAG_PARAM = "parameter";
+    private static final String TAG_EXCEPTION = "exception";
+    private static final String TAG_FIELD = "field";
+
+    private static final String MODIFIER_ABSTRACT = "abstract";
+    private static final String MODIFIER_FINAL = "final";
+    private static final String MODIFIER_NATIVE = "native";
+    private static final String MODIFIER_PRIVATE = "private";
+    private static final String MODIFIER_PROTECTED = "protected";
+    private static final String MODIFIER_PUBLIC = "public";
+    private static final String MODIFIER_STATIC = "static";
+    private static final String MODIFIER_SYNCHRONIZED = "synchronized";
+    private static final String MODIFIER_TRANSIENT = "transient";
+    private static final String MODIFIER_VOLATILE = "volatile";
+    private static final String MODIFIER_VISIBILITY = "visibility";
+
+    private static final String ATTRIBUTE_NAME = "name";
+    private static final String ATTRIBUTE_EXTENDS = "extends";
+    private static final String ATTRIBUTE_TYPE = "type";
+    private static final String ATTRIBUTE_RETURN = "return";
+
+    private HashSet<String> mKeyTagSet;
+    private TestResultObserver mResultObserver;
+
+    private class TestResultObserver implements ResultObserver {
+        boolean mDidFail = false;
+        StringBuilder mErrorString = new StringBuilder();
+
+        @Override
+        public void notifyFailure(FailureType type, String name, String errorMessage) {
+            mDidFail = true;
+            mErrorString.append("\n");
+            mErrorString.append(type.toString().toLowerCase());
+            mErrorString.append(":\t");
+            mErrorString.append(name);
+            mErrorString.append("\tError: ");
+            mErrorString.append(errorMessage);
+        }
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mKeyTagSet = new HashSet<String>();
+        mKeyTagSet.addAll(Arrays.asList(new String[] {
+                TAG_PACKAGE, TAG_CLASS, TAG_INTERFACE, TAG_IMPLEMENTS, TAG_CONSTRUCTOR,
+                TAG_METHOD, TAG_PARAM, TAG_EXCEPTION, TAG_FIELD }));
+        mResultObserver = new TestResultObserver();
+    }
+
+    /**
+     * Tests that the device's API matches the expected set defined in xml.
+     * <p/>
+     * Will check the entire API, and then report the complete list of failures
+     */
+    public void testSignature() {
+        Resources r = getContext().getResources();
+        Class rClass = R.xml.class;
+        logd(String.format("Class: %s", rClass.toString()));
+        Field[] fs = rClass.getFields();
+        for (Field f : fs) {
+            logd(String.format("Field: %s", f.toString()));
+            try {
+                start(r.getXml(f.getInt(rClass)));
+            } catch (Exception e) {
+                mResultObserver.notifyFailure(FailureType.CAUGHT_EXCEPTION, e.getMessage(),
+                        e.getMessage());
+            }
+        }
+        if (mResultObserver.mDidFail) {
+            fail(mResultObserver.mErrorString.toString());
+        }
+    }
+
+    private  void beginDocument(XmlPullParser parser, String firstElementName)
+            throws XmlPullParserException, IOException {
+        int type;
+        while ((type=parser.next()) != XmlPullParser.START_TAG
+                   && type != XmlPullParser.END_DOCUMENT) { }
+
+        if (type != XmlPullParser.START_TAG) {
+            throw new XmlPullParserException("No start tag found");
+        }
+
+        if (!parser.getName().equals(firstElementName)) {
+            throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() +
+                    ", expected " + firstElementName);
+        }
+    }
+
+    /**
+     * Signature test entry point.
+     */
+    private void start(XmlPullParser parser) throws XmlPullParserException, IOException {
+        logd(String.format("Name: %s", parser.getName()));
+        logd(String.format("Text: %s", parser.getText()));
+        logd(String.format("Namespace: %s", parser.getNamespace()));
+        logd(String.format("Line Number: %s", parser.getLineNumber()));
+        logd(String.format("Column Number: %s", parser.getColumnNumber()));
+        logd(String.format("Position Description: %s", parser.getPositionDescription()));
+        JDiffClassDescription currentClass = null;
+        String currentPackage = "";
+        JDiffMethod currentMethod = null;
+
+        beginDocument(parser, TAG_ROOT);
+        int type;
+        while (true) {
+            type = XmlPullParser.START_DOCUMENT;
+            while ((type=parser.next()) != XmlPullParser.START_TAG
+                       && type != XmlPullParser.END_DOCUMENT
+                       && type != XmlPullParser.END_TAG) {
+
+            }
+
+            if (type == XmlPullParser.END_TAG) {
+                if (TAG_CLASS.equals(parser.getName())
+                        || TAG_INTERFACE.equals(parser.getName())) {
+                    currentClass.checkSignatureCompliance();
+                } else if (TAG_PACKAGE.equals(parser.getName())) {
+                    currentPackage = "";
+                }
+                continue;
+            }
+
+            if (type == XmlPullParser.END_DOCUMENT) {
+                break;
+            }
+
+            String tagname = parser.getName();
+            if (!mKeyTagSet.contains(tagname)) {
+                continue;
+            }
+
+            if (type == XmlPullParser.START_TAG && tagname.equals(TAG_PACKAGE)) {
+                currentPackage = parser.getAttributeValue(null, ATTRIBUTE_NAME);
+            } else if (tagname.equals(TAG_CLASS)) {
+                currentClass = loadClassInfo(parser, false, currentPackage);
+            } else if (tagname.equals(TAG_INTERFACE)) {
+                currentClass = loadClassInfo(parser, true, currentPackage);
+            } else if (tagname.equals(TAG_IMPLEMENTS)) {
+                currentClass.addImplInterface(parser.getAttributeValue(null, ATTRIBUTE_NAME));
+            } else if (tagname.equals(TAG_CONSTRUCTOR)) {
+                JDiffConstructor constructor = loadConstructorInfo(parser, currentClass);
+                currentClass.addConstructor(constructor);
+                currentMethod = constructor;
+            } else if (tagname.equals(TAG_METHOD)) {
+                currentMethod = loadMethodInfo(currentClass.getClassName(), parser);
+                currentClass.addMethod(currentMethod);
+            } else if (tagname.equals(TAG_PARAM)) {
+                currentMethod.addParam(parser.getAttributeValue(null, ATTRIBUTE_TYPE));
+            } else if (tagname.equals(TAG_EXCEPTION)) {
+                currentMethod.addException(parser.getAttributeValue(null, ATTRIBUTE_TYPE));
+            } else if (tagname.equals(TAG_FIELD)) {
+                JDiffField field = loadFieldInfo(currentClass.getClassName(), parser);
+                currentClass.addField(field);
+            } else {
+                throw new RuntimeException(
+                        "unknown tag exception:" + tagname);
+            }
+            if (currentPackage != null) {
+                logd(String.format("currentPackage: %s", currentPackage));
+            }
+            if (currentClass != null) {
+                logd(String.format("currentClass: %s", currentClass.toSignatureString()));
+            }
+            if (currentMethod != null) {
+                logd(String.format("currentMethod: %s", currentMethod.toSignatureString()));
+            }
+        }
+    }
+
+    /**
+     * Load field information from xml to memory.
+     *
+     * @param className of the class being examined which will be shown in error messages
+     * @param parser The XmlPullParser which carries the xml information.
+     * @return the new field
+     */
+    private JDiffField loadFieldInfo(String className, XmlPullParser parser) {
+        String fieldName = parser.getAttributeValue(null, ATTRIBUTE_NAME);
+        String fieldType = parser.getAttributeValue(null, ATTRIBUTE_TYPE);
+        int modifier = jdiffModifierToReflectionFormat(className, parser);
+        return new JDiffField(fieldName, fieldType, modifier);
+    }
+
+    /**
+     * Load method information from xml to memory.
+     *
+     * @param className of the class being examined which will be shown in error messages
+     * @param parser The XmlPullParser which carries the xml information.
+     * @return the newly loaded method.
+     */
+    private JDiffMethod loadMethodInfo(String className, XmlPullParser parser) {
+        String methodName = parser.getAttributeValue(null, ATTRIBUTE_NAME);
+        String returnType = parser.getAttributeValue(null, ATTRIBUTE_RETURN);
+        int modifier = jdiffModifierToReflectionFormat(className, parser);
+        return new JDiffMethod(methodName, modifier, returnType);
+    }
+
+    /**
+     * Load constructor information from xml to memory.
+     *
+     * @param parser The XmlPullParser which carries the xml information.
+     * @param currentClass the current class being loaded.
+     * @return the new constructor
+     */
+    private JDiffConstructor loadConstructorInfo(XmlPullParser parser,
+                                                 JDiffClassDescription currentClass) {
+        String name = currentClass.getClassName();
+        int modifier = jdiffModifierToReflectionFormat(name, parser);
+        return new JDiffConstructor(name, modifier);
+    }
+
+    /**
+     * Load class or interface information to memory.
+     *
+     * @param parser The XmlPullParser which carries the xml information.
+     * @param isInterface true if the current class is an interface, otherwise is false.
+     * @param pkg the name of the java package this class can be found in.
+     * @return the new class description.
+     */
+    private JDiffClassDescription loadClassInfo(XmlPullParser parser,
+                                                boolean isInterface,
+                                                String pkg) {
+        String className = parser.getAttributeValue(null, ATTRIBUTE_NAME);
+        JDiffClassDescription currentClass = new JDiffClassDescription(pkg,
+                                                                       className,
+                                                                       mResultObserver);
+        currentClass.setModifier(jdiffModifierToReflectionFormat(className, parser));
+        currentClass.setType(isInterface ? JDiffClassDescription.JDiffType.INTERFACE :
+                             JDiffClassDescription.JDiffType.CLASS);
+        currentClass.setExtendsClass(parser.getAttributeValue(null, ATTRIBUTE_EXTENDS));
+        return currentClass;
+    }
+
+    /**
+     * Convert string modifier to int modifier.
+     *
+     * @param name of the class/method/field being examined which will be shown in error messages
+     * @param key modifier name
+     * @param value modifier value
+     * @return converted modifier value
+     */
+    private static int modifierDescriptionToReflectedType(String name, String key, String value) {
+        if (key.equals(MODIFIER_ABSTRACT)) {
+            return value.equals("true") ? Modifier.ABSTRACT : 0;
+        } else if (key.equals(MODIFIER_FINAL)) {
+            return value.equals("true") ? Modifier.FINAL : 0;
+        } else if (key.equals(MODIFIER_NATIVE)) {
+            return value.equals("true") ? Modifier.NATIVE : 0;
+        } else if (key.equals(MODIFIER_STATIC)) {
+            return value.equals("true") ? Modifier.STATIC : 0;
+        } else if (key.equals(MODIFIER_SYNCHRONIZED)) {
+            return value.equals("true") ? Modifier.SYNCHRONIZED : 0;
+        } else if (key.equals(MODIFIER_TRANSIENT)) {
+            return value.equals("true") ? Modifier.TRANSIENT : 0;
+        } else if (key.equals(MODIFIER_VOLATILE)) {
+            return value.equals("true") ? Modifier.VOLATILE : 0;
+        } else if (key.equals(MODIFIER_VISIBILITY)) {
+            if (value.equals(MODIFIER_PRIVATE)) {
+                throw new RuntimeException("Private visibility found in API spec: " + name);
+            } else if (value.equals(MODIFIER_PROTECTED)) {
+                return Modifier.PROTECTED;
+            } else if (value.equals(MODIFIER_PUBLIC)) {
+                return Modifier.PUBLIC;
+            } else if ("".equals(value)) {
+                // If the visibility is "", it means it has no modifier.
+                // which is package private. We should return 0 for this modifier.
+                return 0;
+            } else {
+                throw new RuntimeException("Unknown modifier found in API spec: " + value);
+            }
+        }
+        return 0;
+    }
+
+    /**
+     * Transfer string modifier to int one.
+     *
+     * @param name of the class/method/field being examined which will be shown in error messages
+     * @param parser XML resource parser
+     * @return converted modifier
+     */
+    private static int jdiffModifierToReflectionFormat(String name, XmlPullParser parser){
+        int modifier = 0;
+        for (int i = 0;i < parser.getAttributeCount();i++) {
+            modifier |= modifierDescriptionToReflectedType(name, parser.getAttributeName(i),
+                    parser.getAttributeValue(i));
+        }
+        return modifier;
+    }
+
+    public static void loge(String msg, Exception e) {
+        Log.e(TAG, msg, e);
+    }
+
+    public static void logd(String msg) {
+        Log.d(TAG, msg);
+    }
+}
diff --git a/tests/src/android/app/cts/AppStubActivity.java b/tests/src/android/app/cts/AppStubActivity.java
deleted file mode 100644
index fa786fa..0000000
--- a/tests/src/android/app/cts/AppStubActivity.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2008 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.app.cts;
-
-import android.app.Activity;
-import android.app.Dialog;
-import android.content.res.Resources;
-import android.os.Bundle;
-import android.view.ContextMenu;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ContextMenu.ContextMenuInfo;
-
-import com.android.cts.stub.R;
-
-/**
- * A minimal "Hello, World!" application.
- */
-public class AppStubActivity extends Activity {
-    private Dialog mDialog;
-    public boolean mOnPrepareDialog;
-    public boolean mOnOptionsMenuClosedCalled;
-    public boolean mOnPrepareOptionsMenuCalled;
-    public boolean mOnOptionsItemSelectedCalled;
-    public boolean mOnCreateOptionsMenu;
-    public boolean mIndterminate = false;
-    public boolean mIndterminatevisibility = false;
-    public boolean mSecPro = false;
-    public boolean mOnContextItemSelectedCalled;
-    public boolean mOnCreateContextMenu;
-    public boolean mApplyResourceCalled;
-    public boolean mCreateContextMenuCalled;
-    public boolean mRequestWinFeatureRet = false;
-
-    public AppStubActivity() {
-
-    }
-
-    public void finalize() {
-        try {
-            super.finalize();
-        } catch (Throwable exception) {
-            System.err.print("exception!");
-        }
-    }
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState){
-        super.onCreate(savedInstanceState);
-        mRequestWinFeatureRet = requestWindowFeature(1);
-        setContentView(R.layout.app_activity);
-    }
-
-    public Dialog getDialogById(int id) {
-        return mDialog;
-    }
-
-    @Override
-    public Dialog onCreateDialog(int id) {
-        super.onCreateDialog(id);
-        mDialog = new Dialog(this);
-        return mDialog;
-    }
-
-    @Override
-    protected void onPrepareDialog(int id, Dialog dialog) {
-        super.onPrepareDialog(id, dialog);
-        mOnPrepareDialog = true;
-    }
-
-    @Override
-    public void onOptionsMenuClosed(Menu menu) {
-        super.onOptionsMenuClosed(menu);
-        mOnOptionsMenuClosedCalled = true;
-    }
-
-    @Override
-    public boolean onPrepareOptionsMenu(Menu menu) {
-        mOnPrepareOptionsMenuCalled = true;
-        return super.onPrepareOptionsMenu(menu);
-    }
-
-    @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        mOnCreateOptionsMenu = true;
-        if(menu != null)
-            menu.add(0, 0, 0, "Fake Item");
-        return super.onCreateOptionsMenu(menu);
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        mOnOptionsItemSelectedCalled = true;
-        return super.onOptionsItemSelected(item);
-    }
-
-    public boolean setProBarIndeterminate(boolean indeterminate){
-        mIndterminate = indeterminate;
-        super.setProgressBarIndeterminate(indeterminate);
-        return mIndterminate;
-    }
-
-    public boolean setProBarIndeterminateVisibility(boolean visible){
-        mIndterminatevisibility = visible;
-        super.setProgressBarIndeterminateVisibility(visible);
-        return mIndterminatevisibility;
-    }
-
-    public boolean setSecPro(int secPro){
-        mSecPro = true;
-        super.setSecondaryProgress(secPro);
-        return mSecPro;
-    }
-
-    @Override
-    public boolean onContextItemSelected(MenuItem item){
-        mOnContextItemSelectedCalled = true;
-        return super.onContextItemSelected(item);
-    }
-
-    @Override
-    public void onApplyThemeResource( Resources.Theme theme,
-                                      int resid,
-                                      boolean first){
-        super.onApplyThemeResource(theme,resid,first);
-        mApplyResourceCalled = true;
-    }
-
-    @Override
-    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
-        super.onCreateContextMenu(menu,v,menuInfo);
-        mCreateContextMenuCalled = true;
-    }
-}
-
diff --git a/tests/src/android/app/cts/DialogStubActivity.java b/tests/src/android/app/cts/DialogStubActivity.java
deleted file mode 100644
index 817e716..0000000
--- a/tests/src/android/app/cts/DialogStubActivity.java
+++ /dev/null
@@ -1,424 +0,0 @@
-/*
- * Copyright (C) 2008 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.app.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.DatePickerDialog;
-import android.app.Dialog;
-import android.app.TimePickerDialog;
-import android.app.DatePickerDialog.OnDateSetListener;
-import android.app.TimePickerDialog.OnTimeSetListener;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.DialogInterface.OnCancelListener;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.test.ActivityInstrumentationTestCase2;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.DatePicker;
-import android.widget.TimePicker;
-
-/*
- * Stub class for  Dialog, AlertDialog, DatePickerDialog, TimePickerDialog etc.
- */
-public class DialogStubActivity extends Activity {
-    public static final int TEST_DIALOG_WITHOUT_THEME = 0;
-    public static final int TEST_DIALOG_WITH_THEME = 1;
-    public static final int TEST_ALERTDIALOG = 2;
-    public static final int TEST_CUSTOM_ALERTDIALOG = 3;
-    public static final int TEST_DATEPICKERDIALOG = 4;
-    public static final int TEST_DATEPICKERDIALOG_WITH_THEME = 5;
-    public static final int TEST_TIMEPICKERDIALOG = 6;
-    public static final int TEST_TIMEPICKERDIALOG_WITH_THEME = 7;
-    public static final int TEST_ONSTART_AND_ONSTOP = 8;
-    public static final int TEST_ALERTDIALOG_DEPRECATED = 9;
-    public static final int TEST_ALERTDIALOG_CALLBACK = 10;
-    public static final int TEST_CUSTOM_ALERTDIALOG_VIEW = 11;
-    public static final int TEST_ALERTDIALOG_DEPRECATED_WITH_MESSAGE = 12;
-    public static final int TEST_ALERTDIALOG_THEME = 13;
-    public static final int TEST_ALERTDIALOG_CANCELABLE = 14;
-    public static final int TEST_ALERTDIALOG_NOT_CANCELABLE = 15;
-    public static final int TEST_PROTECTED_CANCELABLE = 16;
-    public static final int TEST_PROTECTED_NOT_CANCELABLE = 17;
-
-    public static final int SPACING_LEFT = 10;
-    public static final int SPACING_TOP = 20;
-    public static final int SPACING_RIGHT = 30;
-    public static final int SPACING_BOTTOM = 40;
-    public static int buttonIndex;
-
-    public static final String DEFAULT_ALERTDIALOG_TITLE = "AlertDialog";
-    public static final String DEFAULT_ALERTDIALOG_MESSAGE = "AlertDialog message";
-    private static final String LOG_TAG = "DialogStubActivity";
-
-    public boolean isPositiveButtonClicked = false;
-    public boolean isNegativeButtonClicked = false;
-    public boolean isNeutralButtonClicked = false;
-    public boolean isCallBackCalled;
-    public boolean onCancelCalled;
-    public boolean onKeyDownCalled;
-    public boolean onKeyUpCalled;
-    public boolean onCreateCalled;
-    public boolean onCancelListenerCalled;
-    public boolean onClickCalled;
-    public static boolean onDateChangedCalled;
-    public static boolean onRestoreInstanceStateCalled;
-    public boolean onSaveInstanceStateCalled;
-    public int updatedYear;
-    public int updatedMonth;
-    public int updatedDay;
-
-    public final int INITIAL_YEAR = 2008;
-    public final int INITIAL_MONTH = 7;
-    public final int INITIAL_DAY_OF_MONTH = 27;
-    private final int INITIAL_HOUR = 10;
-    private final int INITIAL_MINUTE = 35;
-    private Dialog mDialog;
-    private AlertDialog mAlertDialog;
-    private OnDateSetListener mOnDateSetListener = new OnDateSetListener() {
-        public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
-            updatedYear = year;
-            updatedMonth = monthOfYear;
-            updatedDay = dayOfMonth;
-        }
-    };
-
-    @SuppressWarnings("deprecation")
-    @Override
-    protected Dialog onCreateDialog(int id) {
-        switch (id) {
-            case TEST_DIALOG_WITHOUT_THEME:
-                mDialog = new Dialog(this);
-                mDialog.setTitle("Hello, Dialog");
-                break;
-
-            case TEST_DIALOG_WITH_THEME:
-                mDialog = new Dialog(this, 1);
-                break;
-
-            case TEST_ALERTDIALOG:
-                mDialog = getAlertDialogInstance(false);
-                break;
-
-            case TEST_CUSTOM_ALERTDIALOG:
-                mDialog = getCustomAlertDialogInstance(false);
-                break;
-
-            case TEST_CUSTOM_ALERTDIALOG_VIEW:
-                mDialog = getCustomAlertDialogInstance(true);
-                break;
-
-            case TEST_DATEPICKERDIALOG:
-                mDialog = new MockDatePickerDialog(this, mOnDateSetListener, INITIAL_YEAR,
-                        INITIAL_MONTH, INITIAL_DAY_OF_MONTH);
-                break;
-
-            case TEST_DATEPICKERDIALOG_WITH_THEME:
-                mDialog = new MockDatePickerDialog(this,
-                        com.android.internal.R.style.Theme_Translucent, mOnDateSetListener,
-                        INITIAL_YEAR, INITIAL_MONTH, INITIAL_DAY_OF_MONTH);
-                break;
-
-            case TEST_TIMEPICKERDIALOG:
-                mDialog = new TimePickerDialog(this, new OnTimeSetListener() {
-                    public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
-                        isCallBackCalled = true;
-                    }
-                }, INITIAL_HOUR, INITIAL_MINUTE, true);
-                break;
-
-            case TEST_TIMEPICKERDIALOG_WITH_THEME:
-                mDialog = new TimePickerDialog(this,
-                        com.android.internal.R.style.Theme_Translucent, null, INITIAL_HOUR,
-                        INITIAL_MINUTE, true);
-                break;
-
-            case TEST_ONSTART_AND_ONSTOP:
-                mDialog = new TestDialog(this);
-                Log.i(LOG_TAG, "mTestDialog:" + mDialog);
-                return mDialog;
-
-            case TEST_ALERTDIALOG_DEPRECATED:
-                mDialog = getAlertDialogInstance(true);
-                break;
-
-            case TEST_ALERTDIALOG_DEPRECATED_WITH_MESSAGE:
-                final Handler handler = new Handler() {
-                    @Override
-                    public void handleMessage(Message msg) {
-                        buttonIndex = msg.what;
-                        super.handleMessage(msg);
-                    }
-                };
-                final Message positiveMessage = Message.obtain();
-                positiveMessage.setTarget(handler);
-                positiveMessage.what = DialogInterface.BUTTON_POSITIVE;
-
-                final Message negativeMessage = Message.obtain();
-                negativeMessage.setTarget(handler);
-                negativeMessage.what = DialogInterface.BUTTON_NEGATIVE;
-
-                final Message neutralMessage = Message.obtain();
-                neutralMessage.setTarget(handler);
-                neutralMessage.what = DialogInterface.BUTTON_NEUTRAL;
-                mAlertDialog = getAlertDialogInstance(false);
-                mAlertDialog.setButton(getString(R.string.alert_dialog_positive), positiveMessage);
-                mAlertDialog.setButton2(getString(R.string.alert_dialog_negative), negativeMessage);
-                mAlertDialog.setButton3(getString(R.string.alert_dialog_neutral), neutralMessage);
-                mDialog = mAlertDialog;
-                break;
-
-            case TEST_ALERTDIALOG_CALLBACK:
-                mDialog = new MockAlertDialog(this);
-                break;
-            case TEST_ALERTDIALOG_THEME:
-                mDialog = new MockAlertDialog(this, R.style.Theme_AlertDialog);
-                break;
-            case TEST_ALERTDIALOG_CANCELABLE:
-                mDialog = getAlertDialogCancelablInstance(true);
-                break;
-            case TEST_ALERTDIALOG_NOT_CANCELABLE:
-                mDialog = getAlertDialogCancelablInstance(false);
-                break;
-            case TEST_PROTECTED_CANCELABLE:
-                mDialog = new TestDialog(this, true, new OnCancelListener() {
-                    public void onCancel(DialogInterface dialog) {
-                        onCancelListenerCalled = true;
-                    }
-                });
-                break;
-            case TEST_PROTECTED_NOT_CANCELABLE:
-                mDialog = new TestDialog(this, false, new OnCancelListener() {
-                    public void onCancel(DialogInterface dialog) {
-                        onCancelListenerCalled = true;
-                    }
-                });
-                break;
-            default:
-                break;
-        }
-
-        Log.i(LOG_TAG, "mDialog:" + mDialog);
-        return mDialog;
-    }
-
-    private AlertDialog getAlertDialogCancelablInstance(boolean cancelable) {
-        OnCancelListener cancelListener = new OnCancelListener() {
-            public void onCancel(DialogInterface dialog) {
-                onCancelCalled = true;
-            }
-        };
-        return new MockAlertDialog(this, cancelable, cancelListener);
-    }
-
-    @SuppressWarnings("deprecation")
-    private AlertDialog getAlertDialogInstance(boolean deprecated) {
-        mAlertDialog = new AlertDialog.Builder(DialogStubActivity.this).create();
-        mAlertDialog.setIcon(com.android.cts.stub.R.drawable.pass);
-        mAlertDialog.setTitle(DEFAULT_ALERTDIALOG_TITLE);
-        mAlertDialog.setMessage(DEFAULT_ALERTDIALOG_MESSAGE);
-        mAlertDialog.setInverseBackgroundForced(true);
-        final DialogInterface.OnClickListener positiveListener = new MockOnClickListener(
-                DialogInterface.BUTTON_POSITIVE);
-        final DialogInterface.OnClickListener netativeListener = new MockOnClickListener(
-                DialogInterface.BUTTON_NEGATIVE);
-        final DialogInterface.OnClickListener neutralListener = new MockOnClickListener(
-                DialogInterface.BUTTON_NEUTRAL);
-
-        if (deprecated) {
-            mAlertDialog.setButton(getString(R.string.alert_dialog_positive), positiveListener);
-            mAlertDialog.setButton2(getString(R.string.alert_dialog_negative), netativeListener);
-            mAlertDialog.setButton3(getString(R.string.alert_dialog_neutral), neutralListener);
-        } else {
-            mAlertDialog.setButton(DialogInterface.BUTTON_POSITIVE,
-                    getString(R.string.alert_dialog_positive), positiveListener);
-            mAlertDialog.setButton(DialogInterface.BUTTON_NEGATIVE,
-                    getString(R.string.alert_dialog_negative), netativeListener);
-            mAlertDialog.setButton(DialogInterface.BUTTON_NEUTRAL,
-                    getString(R.string.alert_dialog_neutral), neutralListener);
-        }
-        return mAlertDialog;
-
-    }
-
-    private AlertDialog getCustomAlertDialogInstance(boolean withSpacing) {
-        final LayoutInflater inflate = getLayoutInflater();
-        final View customTitleViewCustom = inflate.inflate(R.layout.alertdialog_custom_title, null);
-        final View textEntryView = inflate.inflate(R.layout.alert_dialog_text_entry_2, null);
-        mAlertDialog = new AlertDialog.Builder(DialogStubActivity.this).create();
-        mAlertDialog.setCustomTitle(customTitleViewCustom);
-        mAlertDialog.setMessage(DEFAULT_ALERTDIALOG_MESSAGE);
-        if (withSpacing) {
-            mAlertDialog.setView(textEntryView, SPACING_LEFT, SPACING_TOP, SPACING_RIGHT,
-                    SPACING_BOTTOM);
-        } else {
-            mAlertDialog.setView(textEntryView);
-        }
-
-        return mAlertDialog;
-
-    }
-
-    public Dialog getDialog() {
-        return mDialog;
-    }
-
-    public String getDialogTitle() {
-        return (String) mDialog.getWindow().getAttributes().getTitle();
-    }
-
-    private static final String TEST_DIALOG_NUMBER_EXTRA = "testDialogNumber";
-
-    public static <T extends Activity> T startDialogActivity(
-            ActivityInstrumentationTestCase2<T> testCase, int dialogNumber) {
-        Intent intent = new Intent(Intent.ACTION_MAIN);
-        intent.putExtra(TEST_DIALOG_NUMBER_EXTRA, dialogNumber);
-        testCase.setActivityIntent(intent);
-        return testCase.getActivity();
-    }
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        setContentView(R.layout.dialog_stub_layout);
-
-        Intent intent = getIntent();
-        int dialogNum = intent.getIntExtra(TEST_DIALOG_NUMBER_EXTRA, -1);
-        if (dialogNum != -1) {
-            showDialog(dialogNum);
-        }
-    }
-
-    public void setUpTitle(final String title) {
-        runOnUiThread(new Runnable() {
-            public void run() {
-                getDialog().setTitle(title);
-            }
-        });
-    }
-
-    public void setUpTitle(final int id) {
-        runOnUiThread(new Runnable() {
-            public void run() {
-                getDialog().setTitle(id);
-            }
-        });
-    }
-
-    class MockAlertDialog extends AlertDialog {
-        public MockAlertDialog(Context context) {
-            super(context);
-        }
-
-        public MockAlertDialog(Context context, int theme) {
-            super(context, theme);
-        }
-
-        public MockAlertDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
-            super(context, cancelable, cancelListener);
-        }
-
-        @Override
-        public boolean onKeyDown(int keyCode, KeyEvent event) {
-            onKeyDownCalled = true;
-            return super.onKeyDown(keyCode, event);
-        }
-
-        @Override
-        public boolean onKeyUp(int keyCode, KeyEvent event) {
-            onKeyUpCalled = true;
-            return super.onKeyUp(keyCode, event);
-        }
-
-        @Override
-        protected void onCreate(Bundle savedInstanceState) {
-            onCreateCalled = true;
-            super.onCreate(savedInstanceState);
-        }
-
-    }
-
-    class MockOnClickListener implements DialogInterface.OnClickListener {
-        private final int mId;
-
-        public MockOnClickListener(final int buttonId) {
-            mId = buttonId;
-        }
-
-        public void onClick(DialogInterface dialog, int which) {
-            switch (mId) {
-                case DialogInterface.BUTTON_POSITIVE:
-                    isPositiveButtonClicked = true;
-                    break;
-                case DialogInterface.BUTTON_NEGATIVE:
-                    isNegativeButtonClicked = true;
-                    break;
-                case DialogInterface.BUTTON_NEUTRAL:
-                    isNeutralButtonClicked = true;
-                    break;
-                default:
-                    break;
-            }
-        }
-    }
-
-    class MockDatePickerDialog extends DatePickerDialog {
-        public MockDatePickerDialog(Context context, OnDateSetListener callBack, int year,
-                int monthOfYear, int dayOfMonth) {
-            super(context, callBack, year, monthOfYear, dayOfMonth);
-        }
-
-        public MockDatePickerDialog(Context context, int theme, OnDateSetListener callBack,
-                int year, int monthOfYear, int dayOfMonth) {
-            super(context, theme, callBack, year, monthOfYear, dayOfMonth);
-        }
-
-        @Override
-        public void onClick(DialogInterface dialog, int which) {
-            onClickCalled = true;
-            super.onClick(dialog, which);
-        }
-
-        @Override
-        public void onDateChanged(DatePicker view, int year, int month, int day) {
-            onDateChangedCalled = true;
-            super.onDateChanged(view, year, month, day);
-        }
-
-        @Override
-        public void onRestoreInstanceState(Bundle savedInstanceState) {
-            onRestoreInstanceStateCalled = true;
-            super.onRestoreInstanceState(savedInstanceState);
-        }
-
-        @Override
-        public Bundle onSaveInstanceState() {
-            onSaveInstanceStateCalled = true;
-            return super.onSaveInstanceState();
-        }
-
-    }
-}
diff --git a/tests/src/android/app/cts/IBinderParcelable.java b/tests/src/android/app/cts/IBinderParcelable.java
deleted file mode 100644
index 228097f..0000000
--- a/tests/src/android/app/cts/IBinderParcelable.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2009 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.app.cts;
-
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-public class IBinderParcelable implements Parcelable {
-    public IBinder binder;
-
-    public IBinderParcelable(IBinder source) {
-        binder = source;
-    }
-
-    public int describeContents() {
-        return 0;
-    }
-
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeStrongBinder(binder);
-    }
-
-    public static final Parcelable.Creator<IBinderParcelable>
-        CREATOR = new Parcelable.Creator<IBinderParcelable>() {
-
-        public IBinderParcelable createFromParcel(Parcel source) {
-            return new IBinderParcelable(source);
-        }
-
-        public IBinderParcelable[] newArray(int size) {
-            return new IBinderParcelable[size];
-        }
-    };
-
-    private IBinderParcelable(Parcel source) {
-        binder = source.readStrongBinder();
-    }
-}
diff --git a/tests/src/android/app/cts/InstrumentationTestActivity.java b/tests/src/android/app/cts/InstrumentationTestActivity.java
deleted file mode 100644
index 1cedd9f..0000000
--- a/tests/src/android/app/cts/InstrumentationTestActivity.java
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * Copyright (C) 2009 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.app.cts;
-
-import java.util.ArrayList;
-import java.util.List;
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.view.View;
-import android.widget.TextView;
-import com.android.cts.stub.R;
-
-public class InstrumentationTestActivity extends Activity {
-
-    private boolean mOnCreateCalled;
-    private boolean mOnDestroyCalled ;
-    private boolean mOnNewIntentCalled;
-    private boolean mOnPauseCalled;
-    private boolean mOnPostCreate;
-    private boolean mOnRestart;
-    private boolean mOnRestoreInstanceState;
-    private boolean mOnResume;
-    private boolean mOnSaveInstanceState;
-    private boolean mOnStart;
-    private boolean mOnStop;
-    private boolean mOnMenuOpened;
-    private boolean mOnLeave;
-    private int mMenuID;
-    private boolean mOnTouchEventCalled;
-    private int mKeyDownCode;
-    private int mKeyUpCode;
-    private MotionEvent mMotionEvent;
-    private Bundle mBundle;
-    private MockTextView mTextView;
-    private List<KeyEvent> mKeyDownList = new ArrayList<KeyEvent>();
-    private List<KeyEvent> mKeyUpList = new ArrayList<KeyEvent>();
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        mTextView = new MockTextView(this);
-        setContentView(mTextView);
-        mOnCreateCalled = true;
-    }
-
-    class MockTextView extends TextView {
-
-        public MockTextView(Context context) {
-            super(context);
-        }
-
-        @Override
-        public boolean onTouchEvent(MotionEvent event) {
-            return super.onTouchEvent(event);
-        }
-
-        @Override
-        public boolean onTrackballEvent(MotionEvent event) {
-            return super.onTrackballEvent(event);
-        }
-
-        @Override
-        public void getLocationOnScreen(int[] location) {
-            super.getLocationOnScreen(location);
-            location[0] = location[1] = 10;
-        }
-    }
-
-    @Override
-    protected void onDestroy() {
-        super.onDestroy();
-        mOnDestroyCalled = true;
-    }
-
-    @Override
-    protected void onNewIntent(Intent intent) {
-        super.onNewIntent(intent);
-        mOnNewIntentCalled = true;
-    }
-
-    @Override
-    protected void onPause() {
-        super.onPause();
-        mOnPauseCalled = true;
-    }
-
-    @Override
-    protected void onPostCreate(Bundle savedInstanceState) {
-        super.onPostCreate(savedInstanceState);
-        mOnPostCreate = true;
-    }
-
-    @Override
-    protected void onRestart() {
-        super.onRestart();
-        mOnRestart = true;
-    }
-
-    @Override
-    protected void onRestoreInstanceState(Bundle savedInstanceState) {
-        super.onRestoreInstanceState(savedInstanceState);
-        mOnRestoreInstanceState = true;
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        mOnTouchEventCalled = true;
-        mMotionEvent = event;
-        return super.onTouchEvent(event);
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        mOnResume = true;
-    }
-
-    @Override
-    protected void onSaveInstanceState(Bundle outState) {
-        super.onSaveInstanceState(outState);
-        mOnSaveInstanceState = true;
-        mBundle = outState;
-    }
-
-    @Override
-    protected void onStart() {
-        super.onStart();
-        mOnStart = true;
-    }
-
-    @Override
-    protected void onStop() {
-        super.onStop();
-        mOnStop = true;
-    }
-
-    @Override
-    protected void onUserLeaveHint() {
-        super.onUserLeaveHint();
-        mOnLeave = true;
-    }
-
-    @Override
-    public boolean onMenuOpened(int featureId, Menu menu) {
-        mOnMenuOpened = true;
-        return super.onMenuOpened(featureId, menu);
-    }
-
-    @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        super.onCreateOptionsMenu(menu);
-        MenuInflater inflater = getMenuInflater();
-        inflater.inflate(R.menu.browser, menu);
-
-        menu.add("title");
-        mOnMenuOpened = true;
-        return true;
-    }
-
-    @Override
-    public boolean onCreatePanelMenu(int featureId, Menu menu) {
-        return super.onCreatePanelMenu(featureId, menu);
-    }
-
-    @Override
-    public boolean onMenuItemSelected(int featureId, MenuItem item) {
-        mMenuID = item.getItemId();
-        return super.onMenuItemSelected(featureId, item);
-    }
-
-    @Override
-    public void openContextMenu(View view) {
-        super.openContextMenu(view);
-    }
-
-    @Override
-    public void openOptionsMenu() {
-        super.openOptionsMenu();
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        return super.onOptionsItemSelected(item);
-    }
-
-    @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
-        mKeyDownList.add(event);
-        mKeyDownCode = keyCode;
-        return super.onKeyDown(keyCode, event);
-    }
-
-    @Override
-    public boolean onTrackballEvent(MotionEvent event) {
-        mMotionEvent = event;
-        return super.onTrackballEvent(event);
-    }
-
-    @Override
-    public boolean onKeyUp(int keyCode, KeyEvent event) {
-        mKeyUpList.add(event);
-        mKeyUpCode = keyCode;
-        return super.onKeyUp(keyCode, event);
-    }
-
-    public boolean isOnCreateCalled() {
-        return mOnCreateCalled;
-    }
-
-    public void setOnCreateCalled(boolean onCreateCalled) {
-        mOnCreateCalled = onCreateCalled;
-    }
-
-    public boolean isOnDestroyCalled() {
-        return mOnDestroyCalled;
-    }
-
-    public void setOnDestroyCalled(boolean onDestroyCalled) {
-        mOnDestroyCalled = onDestroyCalled;
-    }
-
-    public boolean isOnNewIntentCalled() {
-        return mOnNewIntentCalled;
-    }
-
-    public void setOnNewIntentCalled(boolean onNewIntentCalled) {
-        mOnNewIntentCalled = onNewIntentCalled;
-    }
-
-    public boolean isOnPauseCalled() {
-        return mOnPauseCalled;
-    }
-
-    public void setOnPauseCalled(boolean onPauseCalled) {
-        mOnPauseCalled = onPauseCalled;
-    }
-
-    public boolean isOnPostCreate() {
-        return mOnPostCreate;
-    }
-
-    public void setOnPostCreate(boolean onPostCreate) {
-        mOnPostCreate = onPostCreate;
-    }
-
-    public boolean isOnRestart() {
-        return mOnRestart;
-    }
-
-    public void setOnRestart(boolean onRestart) {
-        mOnRestart = onRestart;
-    }
-
-    public boolean isOnRestoreInstanceState() {
-        return mOnRestoreInstanceState;
-    }
-
-    public void setOnRestoreInstanceState(boolean onRestoreInstanceState) {
-        mOnRestoreInstanceState = onRestoreInstanceState;
-    }
-
-    public boolean isOnResume() {
-        return mOnResume;
-    }
-
-    public void setOnResume(boolean onResume) {
-        mOnResume = onResume;
-    }
-
-    public boolean isOnSaveInstanceState() {
-        return mOnSaveInstanceState;
-    }
-
-    public void setOnSaveInstanceState(boolean onSaveInstanceState) {
-        mOnSaveInstanceState = onSaveInstanceState;
-    }
-
-    public boolean isOnStart() {
-        return mOnStart;
-    }
-
-    public void setOnStart(boolean onStart) {
-        mOnStart = onStart;
-    }
-
-    public boolean isOnStop() {
-        return mOnStop;
-    }
-
-    public boolean isOnLeave() {
-        return mOnLeave;
-    }
-
-    public void setOnStop(boolean onStop) {
-        mOnStop = onStop;
-    }
-
-    public boolean isMOnMenuOpened() {
-        return mOnMenuOpened;
-    }
-
-    public void setOnMenuOpened(boolean onMenuOpened) {
-        mOnMenuOpened = onMenuOpened;
-    }
-
-    public int getMenuID() {
-        return mMenuID;
-    }
-
-    public void setMenuID(int menuID) {
-        mMenuID = menuID;
-    }
-
-    public MotionEvent getMotionEvent() {
-        return mMotionEvent;
-    }
-
-    public Bundle getBundle() {
-        return mBundle;
-    }
-
-    public boolean isOnTouchEventCalled() {
-        return mOnTouchEventCalled;
-    }
-
-    public void setOnTouchEventCalled(boolean onTouchEventCalled) {
-        mOnTouchEventCalled = onTouchEventCalled;
-    }
-
-    public int getKeyUpCode() {
-        return mKeyUpCode;
-    }
-
-    public int getKeyDownCode() {
-        return mKeyDownCode;
-    }
-
-    public List<KeyEvent> getKeyUpList() {
-        return mKeyUpList;
-    }
-
-    public List<KeyEvent> getKeyDownList() {
-        return mKeyDownList;
-    }
-}
diff --git a/tests/src/android/app/cts/LocalActivityManagerTestHelper.java b/tests/src/android/app/cts/LocalActivityManagerTestHelper.java
deleted file mode 100644
index 76af648..0000000
--- a/tests/src/android/app/cts/LocalActivityManagerTestHelper.java
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * Copyright (C) 2008 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.app.cts;
-
-
-import android.app.Activity;
-import android.app.ActivityGroup;
-import android.app.LocalActivityManager;
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.Window;
-import android.app.cts.CTSResult;
-
-public class LocalActivityManagerTestHelper extends ActivityGroup {
-
-    public static final String ACTION_DISPATCH_RESUME = "dispatchResume";
-    public static final String ACTION_START_ACTIVITY = "startActivity";
-    public static final String ACTION_DISPATCH_CREATE = "dispatchCreate";
-    public static final String ACTION_DISPATCH_STOP = "dispatchStop";
-    public static final String ACTION_DISPATCH_PAUSE_TRUE = "dispatchPauseTrue";
-    public static final String ACTION_DISPATCH_PAUSE_FALSE = "dispatchPauseFalse";
-    public static final String ACTION_SAVE_INSTANCE_STATE = "saveInstanceState";
-    public static final String ACTION_DISPATCH_DESTROY = "dispatchDestroy";
-    public static final String ACTION_REMOVE_ALL_ACTIVITY = "removeAllActivities";
-
-    private String mCurrentAction;
-    private LocalActivityManager mLocalActivityManager;
-
-    private static CTSResult sResult;
-
-    public static void setResult(CTSResult cr) {
-        sResult = cr;
-    }
-
-    public LocalActivityManagerTestHelper() {
-        super();
-    }
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        mCurrentAction = getIntent().getAction();
-        mLocalActivityManager = getLocalActivityManager();
-    }
-
-    @Override
-    protected void onStart() {
-        super.onStart();
-    }
-
-    protected void onResume() {
-        super.onResume();
-        if (mCurrentAction.equals(ACTION_DISPATCH_RESUME)) {
-            testDispatchResume();
-        } else if (mCurrentAction.equals(ACTION_START_ACTIVITY)) {
-            testStartActivity();
-        } else if (mCurrentAction.equals(ACTION_DISPATCH_CREATE)) {
-            testDispatchCreate();
-        } else if (mCurrentAction.equals(ACTION_DISPATCH_STOP)) {
-            testDispatchStop();
-        } else if (mCurrentAction.equals(ACTION_DISPATCH_PAUSE_TRUE)) {
-            testDispatchPauseTrue();
-        } else if (mCurrentAction.equals(ACTION_DISPATCH_PAUSE_FALSE)) {
-            testDispatchPauseFalse();
-        } else if (mCurrentAction.equals(ACTION_SAVE_INSTANCE_STATE)) {
-            testSaveInstanceState();
-        } else if (mCurrentAction.equals(ACTION_DISPATCH_DESTROY)) {
-            testDispatchDestroy();
-        } else if (mCurrentAction.equals(ACTION_REMOVE_ALL_ACTIVITY)) {
-            testRemoveAllActivity();
-        }
-    }
-
-    private void testRemoveAllActivity() {
-        final String id = "id_remove_activity";
-        final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        mLocalActivityManager.startActivity(id, intent);
-
-        Activity activity = mLocalActivityManager.getActivity(id);
-        if (activity == null) {
-            fail();
-            return;
-        }
-
-        if (!activity.getClass().getName().equals("android.app.cts."
-                    + "LocalActivityManagerStubActivity")) {
-            fail();
-            return;
-        }
-
-        mLocalActivityManager.removeAllActivities();
-        activity = mLocalActivityManager.getActivity(id);
-        if (activity != null) {
-            fail();
-            return;
-        }
-        pass();
-    }
-
-    private void testDispatchDestroy() {
-        final String id1 = "id_dispatch_destroy1";
-        final String id2 = "id_dispatch_destroy2";
-        final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        mLocalActivityManager.startActivity(id1, intent);
-
-        LocalActivityManagerStubActivity.sIsOnDestroyCalled = false;
-        mLocalActivityManager.dispatchDestroy(false);
-        if (mLocalActivityManager.getCurrentActivity().isFinishing()){
-            fail();
-            return;
-        }
-
-        if (!LocalActivityManagerStubActivity.sIsOnDestroyCalled) {
-            fail();
-            return;
-        }
-
-        mLocalActivityManager.startActivity(id2, intent);
-        LocalActivityManagerStubActivity.sIsOnDestroyCalled = false;
-        mLocalActivityManager.dispatchDestroy(true);
-
-        if (!LocalActivityManagerStubActivity.sIsOnDestroyCalled) {
-            fail();
-            return;
-        }
-
-        if (!mLocalActivityManager.getCurrentActivity().isFinishing()){
-            fail();
-            return;
-        }
-        pass();
-    }
-
-    private void testSaveInstanceState() {
-        final String key = "_id1";
-        mLocalActivityManager.dispatchCreate(null);
-        final Bundle bundle = mLocalActivityManager.saveInstanceState();
-        if (bundle != null) {
-            fail();
-            return;
-        }
-
-        final String id = "id_dispatch_pause";
-        final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        mLocalActivityManager.startActivity(id, intent);
-
-        final Bundle savedBundle = new Bundle();
-        final Bundle bb = new Bundle();
-        savedBundle.putBundle(key, bb);
-
-        mLocalActivityManager.dispatchCreate(savedBundle);
-        final Bundle returnedBundle = mLocalActivityManager.saveInstanceState();
-        if (returnedBundle.getBundle(key) == null ) {
-            fail();
-            return;
-        }
-        pass();
-    }
-
-    private void testDispatchPauseFalse() {
-        final String id = "id_dispatch_pause";
-        final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        mLocalActivityManager.startActivity(id, intent);
-        LocalActivityManagerStubActivity.sIsOnPauseCalled = false;
-        mLocalActivityManager.dispatchPause(false);
-        if (!LocalActivityManagerStubActivity.sIsOnPauseCalled) {
-            fail();
-            return;
-        }
-        pass();
-    }
-
-    private void testDispatchPauseTrue() {
-        final String id = "id_dispatch_pause";
-        final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        mLocalActivityManager.startActivity(id, intent);
-        LocalActivityManagerStubActivity.sIsOnPauseCalled = false;
-        mLocalActivityManager.dispatchPause(true);
-        if (!LocalActivityManagerStubActivity.sIsOnPauseCalled) {
-            fail();
-            return;
-        }
-        pass();
-    }
-
-    private void testDispatchStop() {
-        final String id = "id_dispatch_stop";
-        final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        mLocalActivityManager.startActivity(id, intent);
-        if (mLocalActivityManager.getCurrentActivity() == null) {
-            fail();
-            return;
-        }
-
-        LocalActivityManagerStubActivity.sIsOnStopCalled = false;
-        mLocalActivityManager.dispatchStop();
-
-        if (!LocalActivityManagerStubActivity.sIsOnStopCalled) {
-            fail();
-            return;
-        }
-        pass();
-    }
-
-    private void testDispatchCreate() {
-        final Bundle EXPECTED = new Bundle();
-        final String id = "id";
-
-        final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        mLocalActivityManager.startActivity("_id" + System.currentTimeMillis(), intent);
-        final Bundle bundle = mLocalActivityManager.saveInstanceState();
-        if (bundle == null) {
-            fail();
-            return;
-        }
-
-        if (bundle.keySet().size() != 1) {
-            fail();
-            return;
-        }
-
-        bundle.putBundle(id, EXPECTED);
-        // test null parameter
-        mLocalActivityManager.dispatchCreate(null);
-
-        if (mLocalActivityManager.saveInstanceState().keySet().size() != 1) {
-            fail();
-            return;
-        }
-
-        mLocalActivityManager.dispatchCreate(bundle);
-
-        final Bundle b = mLocalActivityManager.saveInstanceState();
-        final Bundle bb = b.getBundle(id);
-        if (bb != EXPECTED) {
-            fail();
-            return;
-        }
-        pass();
-    }
-
-    private void testStartActivity() {
-        final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        final String id = "_id_resume_test";
-        final Window w = mLocalActivityManager.startActivity(id, intent);
-        if (w == null) {
-            fail();
-            return;
-        }
-
-        Activity activity = mLocalActivityManager.getActivity(id);
-        if (activity == null) {
-            fail();
-            return;
-        }
-
-        // testing null id
-        activity = mLocalActivityManager.getActivity("null id");
-        if (activity != null) {
-            fail();
-            return;
-        }
-
-        if (!mLocalActivityManager.getCurrentId().equals(id)) {
-            fail();
-            return;
-        }
-
-        if (mLocalActivityManager.getActivity(id) != mLocalActivityManager
-                .getCurrentActivity()) {
-            fail();
-            return;
-        }
-
-        if (mLocalActivityManager.destroyActivity(id, true) == null) {
-            fail();
-            return;
-        }
-
-        if (mLocalActivityManager.startActivity(null, intent) == null) {
-            fail();
-            return;
-        }
-
-        try {
-            // test when calling startActivity with both null parameter.
-            mLocalActivityManager.startActivity(null, null);
-            fail();
-            return;
-        } catch (NullPointerException e) {
-        }
-        pass();
-    }
-
-    private void testDispatchResume() {
-        final Intent intent = new Intent(this, LocalActivityManagerStubActivity.class);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        mLocalActivityManager.startActivity("_id_resume_test", intent);
-        mLocalActivityManager.dispatchStop();
-        LocalActivityManagerStubActivity.sIsOnResumeCalled = false;
-        mLocalActivityManager.dispatchResume();
-        if (LocalActivityManagerStubActivity.sIsOnResumeCalled) {
-            pass();
-        } else {
-            fail();
-        }
-    }
-
-    private void fail() {
-        sResult.setResult(CTSResult.RESULT_FAIL);
-        finish();
-    }
-
-    private void pass() {
-        sResult.setResult(CTSResult.RESULT_OK);
-        finish();
-    }
-}
diff --git a/tests/src/android/app/cts/LocalService.java b/tests/src/android/app/cts/LocalService.java
deleted file mode 100644
index 22273b0..0000000
--- a/tests/src/android/app/cts/LocalService.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2008 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.app.cts;
-
-import android.app.Service;
-import android.content.Intent;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.RemoteException;
-
-public class LocalService extends Service {
-    public static final String SERVICE_LOCAL =
-            "android.app.cts.activity.SERVICE_LOCAL";
-    public static final String SERVICE_LOCAL_GRANTED =
-            "android.app.cts.activity.SERVICE_LOCAL_GRANTED";
-    public static final String SERVICE_LOCAL_DENIED =
-            "android.app.cts.activity.SERVICE_LOCAL_DENIED";
-
-    public static final String REPORT_OBJ_NAME = "report";
-
-    public static final int STARTED_CODE = 1;
-    public static final int DESTROYED_CODE = 2;
-    public static final int SET_REPORTER_CODE = 3;
-    public static final int UNBIND_CODE = 4;
-    public static final int REBIND_CODE = 5;
-
-    private IBinder mReportObject;
-    private int mStartCount = 1;
-
-    private final IBinder mBinder = new Binder() {
-        @Override
-        protected boolean onTransact(int code, Parcel data, Parcel reply,
-                int flags) throws RemoteException {
-            if (code == SET_REPORTER_CODE) {
-                data.enforceInterface(SERVICE_LOCAL);
-                mReportObject = data.readStrongBinder();
-                return true;
-            } else {
-                return super.onTransact(code, data, reply, flags);
-            }
-        }
-    };
-
-
-    public LocalService() {
-    }
-
-    @Override
-    public void onStart(Intent intent, int startId) {
-        if (intent.getExtras() != null) {
-            IBinderParcelable parcelable
-                    = (IBinderParcelable) intent.getExtras().getParcelable(REPORT_OBJ_NAME);
-            mReportObject = parcelable.binder;
-            if (mReportObject != null) {
-                bindAction(STARTED_CODE);
-            }
-        }
-    }
-
-    @Override
-    public void onDestroy() {
-        if (mReportObject != null) {
-            bindAction(DESTROYED_CODE);
-        }
-    }
-
-    @Override
-    public IBinder onBind(Intent intent) {
-        return mBinder;
-    }
-
-    @Override
-    public boolean onUnbind(Intent intent) {
-        if (mReportObject != null) {
-            bindAction(UNBIND_CODE);
-        }
-        return true;
-    }
-
-    @Override
-    public void onRebind(Intent intent) {
-        if (mReportObject != null) {
-            bindAction(REBIND_CODE);
-        }
-    }
-
-    private void bindAction(final int bindCode) {
-        try {
-            Parcel data = Parcel.obtain();
-            data.writeInterfaceToken(SERVICE_LOCAL);
-            if (bindCode == STARTED_CODE) {
-                data.writeInt(mStartCount);
-                mStartCount++;
-            }
-            mReportObject.transact(
-                    bindCode, data, null, 0);
-            data.recycle();
-        } catch (RemoteException e) {
-            // fail
-        }
-    }
-}
diff --git a/tests/src/android/app/cts/MockAlarmReceiver.java b/tests/src/android/app/cts/MockAlarmReceiver.java
deleted file mode 100644
index 5060cef..0000000
--- a/tests/src/android/app/cts/MockAlarmReceiver.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2008 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.app.cts;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.os.SystemClock;
-
-/**
- * this class  receive alarm from AlarmManagerTest
- */
-public class MockAlarmReceiver extends BroadcastReceiver {
-    public boolean alarmed = false;
-    private Object mSync = new Object();
-    public static final String MOCKACTION = "android.app.AlarmManagerTest.TEST_ALARMRECEIVER";
-
-    public long elapsedTime;
-    public long rtcTime;
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        final String action = intent.getAction();
-        if (action.equals(MOCKACTION)) {
-            synchronized (mSync) {
-                alarmed = true;
-                elapsedTime = SystemClock.elapsedRealtime();
-                rtcTime = System.currentTimeMillis();
-            }
-        }
-    }
-
-    public void setAlarmedFalse() {
-        synchronized (mSync) {
-            alarmed = false;
-        }
-    }
-}
diff --git a/tests/src/android/app/cts/SearchManagerStubActivity.java b/tests/src/android/app/cts/SearchManagerStubActivity.java
deleted file mode 100644
index 6385fef..0000000
--- a/tests/src/android/app/cts/SearchManagerStubActivity.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright (C) 2008 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.app.cts;
-
-import android.app.Activity;
-import android.app.SearchManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.util.Log;
-
-public class SearchManagerStubActivity extends Activity {
-
-    private static final String TAG = "SearchManagerStubActivity";
-
-    public static final String TEST_STOP_SEARCH = "stopSearch";
-    public static final String TEST_ON_DISMISSLISTENER = "setOnDismissListener";
-    public static final String TEST_ON_CANCELLISTENER = "setOnCancelListener";
-
-    private SearchManager mSearchManager;
-    private ComponentName mComponentName;
-
-    private static CTSResult sCTSResult;
-    private boolean mDismissCalled;
-    private boolean mCancelCalled;
-
-    public static void setCTSResult(CTSResult result) {
-        sCTSResult = result;
-    }
-
-    @Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-        mSearchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
-        mComponentName = getComponentName();
-        String action = getIntent().getAction();
-        if (action.equals(TEST_STOP_SEARCH)) {
-            testStopSearch();
-        } else if (action.equals(TEST_ON_DISMISSLISTENER)) {
-            testOnDismissListener();
-        } else if (action.equals(TEST_ON_CANCELLISTENER)) {
-            testOnCancelListener();
-        }
-    }
-
-    private void testOnCancelListener() {
-        mCancelCalled = false;
-        mSearchManager.setOnCancelListener(new SearchManager.OnCancelListener() {
-            @Override
-            public void onCancel() {
-               mCancelCalled = true;
-            }
-        });
-
-        new TestStepHandler() {
-            @Override
-            public boolean doStep(int step) throws FailException {
-                switch (step) {
-                    case 1:
-                        startSearch("test", false, mComponentName, null, false);
-                        return false;
-                    case 2:
-                        assertFalse("cancel called", mCancelCalled);
-                        stopSearch();
-                        return false;
-                    case 3:
-                        assertTrue("cancel not called", mCancelCalled);
-                        pass();
-                        return true;
-                    default:
-                        throw new IllegalArgumentException("Bad step " + step);
-                }
-            }
-        }.start();
-    }
-
-    private void testOnDismissListener() {
-        mDismissCalled = false;
-
-        mSearchManager.setOnDismissListener(new SearchManager.OnDismissListener() {
-            public void onDismiss() {
-                mDismissCalled = true;
-            }
-        });
-
-        new TestStepHandler() {
-            @Override
-            public boolean doStep(int step) throws FailException {
-                switch (step) {
-                    case 1:
-                        startSearch("test", false, mComponentName, null, false);
-                        return false;
-                    case 2:
-                        if (mDismissCalled) {
-                            throw new FailException("dismiss called");
-                        } else {
-                            stopSearch();
-                        }
-                        return false;
-                    case 3:
-                        if (mDismissCalled) {
-                            pass();
-                        } else {
-                            throw new FailException("dismiss not called");
-                        }
-                        return true;
-                    default:
-                        throw new IllegalArgumentException("Bad step " + step);
-                }
-            }
-        }.start();
-    }
-
-    private void testStopSearch() {
-        new TestStepHandler() {
-            @Override
-            public boolean doStep(int step) throws FailException {
-                switch (step) {
-                    case 1:
-                        startSearch("test", false, mComponentName, null, false);
-                        return false;
-                    case 2:
-                        assertVisible();
-                        stopSearch();
-                        return false;
-                    case 3:
-                        assertInVisible();
-                        pass();
-                        return true;
-                    default:
-                        throw new IllegalArgumentException("Bad step " + step);
-                }
-            }
-        }.start();
-    }
-
-    private void fail(Exception ex) {
-        Log.e(TAG, "test failed", ex);
-        sCTSResult.setResult(CTSResult.RESULT_FAIL);
-        finish();
-    }
-
-    private void pass() {
-        sCTSResult.setResult(CTSResult.RESULT_OK);
-        finish();
-    }
-
-    private void assertInVisible() throws FailException {
-        if (isVisible()) {
-            throw new FailException();
-        }
-    }
-
-    private void assertVisible() throws FailException {
-        if (!isVisible()) {
-            throw new FailException();
-        }
-    }
-
-    private void assertFalse(String message, boolean value) throws FailException {
-        assertTrue(message, !value);
-    }
-
-    private void assertTrue(String message, boolean value) throws FailException {
-        if (!value) {
-            throw new FailException(message);
-        }
-    }
-
-    private void startSearch(String initialQuery, boolean selectInitialQuery,
-            ComponentName launchActivity, Bundle appSearchData, boolean globalSearch) {
-        mSearchManager.startSearch(initialQuery, selectInitialQuery, launchActivity, appSearchData,
-                globalSearch);
-    }
-
-    private void stopSearch() {
-       mSearchManager.stopSearch();
-    }
-
-    private boolean isVisible() {
-        return mSearchManager.isVisible();
-    }
-
-    private abstract class TestStepHandler extends Handler {
-
-        public void start() {
-            sendEmptyMessage(1);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            try {
-                if (!doStep(msg.what)) {
-                    sendEmptyMessage(msg.what + 1);
-                }
-            } catch (FailException ex) {
-                fail(ex);
-            }
-        }
-
-        /**
-         * Performs one step of the test.
-         *
-         * @param step The 1-based number of the step to perform.
-         * @return {@code true} if this was the last step.
-         * @throws FailException If the test failed.
-         */
-        protected abstract boolean doStep(int step) throws FailException;
-    }
-
-    private static class FailException extends Exception {
-        private static final long serialVersionUID = 1L;
-
-        public FailException() {
-            super();
-        }
-
-        public FailException(String detailMessage) {
-            super(detailMessage);
-        }
-    }
-}
diff --git a/tests/src/android/content/cts/AvailableIntentsActivity.java b/tests/src/android/content/cts/AvailableIntentsActivity.java
deleted file mode 100644
index ac676de..0000000
--- a/tests/src/android/content/cts/AvailableIntentsActivity.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2008 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.content.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-/**
- * This is a stub activity for test available intents. We do not care about
- * what it layouts. We only need an activity even if it's empty for this test.
- */
-public class AvailableIntentsActivity extends Activity {
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.available_intents_layout);
-    }
-}
diff --git a/tests/src/android/content/cts/ContextWrapperStubActivity.java b/tests/src/android/content/cts/ContextWrapperStubActivity.java
deleted file mode 100644
index 977cedc..0000000
--- a/tests/src/android/content/cts/ContextWrapperStubActivity.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2008 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.content.cts;
-
-// Need the following import to get access to the app resources, since this
-// class is in a sub-package.
-import android.app.Activity;
-import android.os.Bundle;
-
-import com.android.cts.stub.R;
-
-public class ContextWrapperStubActivity extends Activity {
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        setContentView(R.layout.local_sample);
-    }
-}
-
diff --git a/tests/src/android/graphics/drawable/cts/DrawableTestUtils.java b/tests/src/android/graphics/drawable/cts/DrawableTestUtils.java
deleted file mode 100644
index 73574e9..0000000
--- a/tests/src/android/graphics/drawable/cts/DrawableTestUtils.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2008 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.content.res.XmlResourceParser;
-import android.util.AttributeSet;
-import android.util.Xml;
-
-import java.io.IOException;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-/**
- * The useful methods for graphics.drawable test.
- */
-public class DrawableTestUtils {
-
-    public static void skipCurrentTag(XmlPullParser parser)
-            throws XmlPullParserException, IOException {
-        int outerDepth = parser.getDepth();
-        int type;
-        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
-               && (type != XmlPullParser.END_TAG
-                       || parser.getDepth() > outerDepth)) {
-        }
-    }
-    
-    /**
-     * Retrieve an AttributeSet from a XML.
-     *
-     * @param parser the XmlPullParser to use for the xml parsing.
-     * @param searchedNodeName the name of the target node.
-     * @return the AttributeSet retrieved from specified node.
-     * @throws IOException
-     * @throws XmlPullParserException
-     */
-    public static AttributeSet getAttributeSet(XmlResourceParser parser, String searchedNodeName)
-            throws XmlPullParserException, IOException {
-        AttributeSet attrs = null;
-        int type;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && type != XmlPullParser.START_TAG) {
-        }
-        String nodeName = parser.getName();
-        if (!"alias".equals(nodeName)) {
-            throw new RuntimeException();
-        }
-        int outerDepth = parser.getDepth();
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-            nodeName = parser.getName();
-            if (searchedNodeName.equals(nodeName)) {
-                outerDepth = parser.getDepth();
-                while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                        && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-                    if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                        continue;
-                    }
-                    nodeName = parser.getName();
-                    attrs = Xml.asAttributeSet(parser);
-                    break;
-                }
-                break;
-            } else {
-                skipCurrentTag(parser);
-            }
-        }
-        return attrs;
-    }
-}
diff --git a/tests/src/android/hardware/cts/CameraStubActivity.java b/tests/src/android/hardware/cts/CameraStubActivity.java
deleted file mode 100644
index 8ab7fbd..0000000
--- a/tests/src/android/hardware/cts/CameraStubActivity.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.cts;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.view.SurfaceHolder;
-import android.view.SurfaceView;
-import android.view.ViewGroup;
-import com.android.cts.stub.R;
-
-public class CameraStubActivity extends Activity {
-    private SurfaceView mSurfaceView;
-    private final int LAYOUT_WIDTH = 480;
-    private final int LAYOUT_HEIGHT = 320;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        setContentView(R.layout.surface_view);
-        mSurfaceView = (SurfaceView)findViewById(R.id.surface_view);
-        ViewGroup.LayoutParams lp = mSurfaceView.getLayoutParams();
-        lp.width = LAYOUT_WIDTH;
-        lp.height = LAYOUT_HEIGHT;
-        mSurfaceView.setLayoutParams(lp);
-        mSurfaceView.getHolder().setFixedSize(LAYOUT_WIDTH, LAYOUT_HEIGHT);
-        mSurfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
-    }
-
-    public SurfaceView getSurfaceView() {
-        return mSurfaceView;
-    }
-}
diff --git a/tests/src/android/net/cts/NetlinkSocket.java b/tests/src/android/net/cts/NetlinkSocket.java
deleted file mode 100644
index 1635843..0000000
--- a/tests/src/android/net/cts/NetlinkSocket.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.
- */
-
-package android.net.cts;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-
-public class NetlinkSocket {
-
-    static {
-        System.loadLibrary("cts_jni");
-    }
-
-    private static native void create_native(FileDescriptor fd);
-    private static native int sendmsg(FileDescriptor fd, int pid, byte[] bytes);
-
-    private FileDescriptor fd = new FileDescriptor();
-
-    /** no public constructors */
-    private NetlinkSocket() { }
-
-    public static NetlinkSocket create() {
-        NetlinkSocket retval = new NetlinkSocket();
-        create_native(retval.fd);
-        return retval;
-    }
-
-    public boolean valid() {
-        return fd.valid();
-    }
-
-    public int sendmsg(int pid, byte[] bytes) throws IOException {
-        int retval = sendmsg(fd, pid, bytes);
-        if (retval == -1) {
-            throw new IOException("Unable to send message to PID=" + pid);
-        }
-        return retval;
-    }
-}
diff --git a/tests/src/android/opengl/cts/CompressedTextureLoader.java b/tests/src/android/opengl/cts/CompressedTextureLoader.java
deleted file mode 100644
index 2cb6910..0000000
--- a/tests/src/android/opengl/cts/CompressedTextureLoader.java
+++ /dev/null
@@ -1,485 +0,0 @@
-/*
- * 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.
- */
-package android.opengl.cts;
-
-import java.io.InputStream;
-import java.nio.ByteBuffer;
-import java.nio.Buffer;
-import java.nio.ByteOrder;
-import java.util.HashMap;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.content.res.AssetFileDescriptor;
-import android.content.res.Resources;
-import android.os.Bundle;
-import android.util.Log;
-
-import android.opengl.ETC1;
-import android.opengl.ETC1Util;
-import android.opengl.GLES20;
-
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.BitmapFactory;
-
-public class CompressedTextureLoader {
-    private static final String TAG = "CompressedTextureLoader";
-
-    public static final String TEXTURE_UNCOMPRESSED = "UNCOMPRESSED";
-    public static final String TEXTURE_ETC1 = "ETC1";
-    public static final String TEXTURE_S3TC = "S3TC";
-    public static final String TEXTURE_ATC = "ATC";
-    public static final String TEXTURE_PVRTC = "PVRTC";
-
-    public static class Texture {
-        public Texture(int width, int height, int internalformat, ByteBuffer data,
-                       String formatName) {
-            mWidth = width;
-            mHeight = height;
-            mInternalFormat = internalformat;
-            mData = data;
-            mFormatName = formatName;
-        }
-
-        /**
-         * Get the width of the texture in pixels.
-         * @return the width of the texture in pixels.
-         */
-        public int getWidth() { return mWidth; }
-
-        /**
-         * Get the height of the texture in pixels.
-         * @return the width of the texture in pixels.
-         */
-        public int getHeight() { return mHeight; }
-
-        /**
-         * Get the compressed data of the texture.
-         * @return the texture data.
-         */
-        public ByteBuffer getData() { return mData; }
-
-        /**
-         * Get the format of the texture.
-         * @return the internal format.
-         */
-        public int getFormat() { return mInternalFormat; }
-
-        /**
-         * Get the format of the texture.
-         * @return the internal format.
-         */
-        public boolean isSupported() { return isFormatSupported(mFormatName); }
-
-        private int mWidth;
-        private int mHeight;
-        private int mInternalFormat;
-        private ByteBuffer mData;
-        private String mFormatName;
-    }
-
-    /*  .pvr header is described by the following c struct
-        typedef struct PVR_TEXTURE_HEADER_TAG{
-            unsigned int  dwHeaderSize;   // size of the structure
-            unsigned int  dwHeight;    // height of surface to be created
-            unsigned int  dwWidth;    // width of input surface
-            unsigned int  dwMipMapCount;   // number of MIP-map levels requested
-            unsigned int  dwpfFlags;   // pixel format flags
-            unsigned int  dwDataSize;   // Size of the compress data
-            unsigned int  dwBitCount;   // number of bits per pixel
-            unsigned int  dwRBitMask;   // mask for red bit
-            unsigned int  dwGBitMask;   // mask for green bits
-            unsigned int  dwBBitMask;   // mask for blue bits
-            unsigned int  dwAlphaBitMask;   // mask for alpha channel
-            unsigned int  dwPVR;    // should be 'P' 'V' 'R' '!'
-            unsigned int  dwNumSurfs;   //number of slices for volume textures or skyboxes
-        } PVR_TEXTURE_HEADER;
-    */
-    static final int PVR_HEADER_SIZE = 13 * 4;
-    static final int PVR_2BPP = 24;
-    static final int PVR_4BPP = 25;
-    static final int PVR_MAGIC_NUMBER = 559044176;
-
-    static final int GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00;
-    static final int GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG = 0x8C01;
-    static final int GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02;
-    static final int GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03;
-
-    static class PVRHeader {
-        int mHeaderSize;   // size of the structure
-        int mHeight;    // height of surface to be created
-        int mWidth;    // width of input surface
-        int mMipMapCount;   // number of MIP-map levels requested
-        int mpfFlags;   // pixel format flags
-        int mDataSize;   // Size of the compress data
-        int mBitCount;   // number of bits per pixel
-        int mRBitMask;   // mask for red bit
-        int mGBitMask;   // mask for green bits
-        int mBBitMask;   // mask for blue bits
-        int mAlphaBitMask;   // mask for alpha channel
-        int mPVR;    // should be 'P' 'V' 'R' '!'
-        int mNumSurfs;   //number of slices for volume textures or skyboxes
-    }
-
-    protected static PVRHeader readPVRHeader(InputStream is) {
-
-        byte[] headerData = new byte[PVR_HEADER_SIZE];
-        try {
-            is.read(headerData);
-        } catch (Exception e) {
-            throw new RuntimeException("Unable to read data");
-        }
-
-        ByteBuffer headerBuffer = ByteBuffer.allocateDirect(PVR_HEADER_SIZE)
-                .order(ByteOrder.nativeOrder());
-        headerBuffer.put(headerData, 0, PVR_HEADER_SIZE).position(0);
-
-        PVRHeader header = new PVRHeader();
-
-        header.mHeaderSize = headerBuffer.getInt();
-        header.mHeight = headerBuffer.getInt();
-        header.mWidth = headerBuffer.getInt();
-        header.mMipMapCount = headerBuffer.getInt();
-        header.mpfFlags = headerBuffer.getInt();
-        header.mDataSize = headerBuffer.getInt();
-        header.mBitCount = headerBuffer.getInt();
-        header.mRBitMask = headerBuffer.getInt();
-        header.mGBitMask = headerBuffer.getInt();
-        header.mBBitMask = headerBuffer.getInt();
-        header.mAlphaBitMask = headerBuffer.getInt();
-        header.mPVR = headerBuffer.getInt();
-        header.mNumSurfs = headerBuffer.getInt();
-
-        if (header.mHeaderSize != PVR_HEADER_SIZE ||
-            header.mPVR != PVR_MAGIC_NUMBER) {
-            throw new RuntimeException("Invalid header data");
-        }
-
-        return header;
-    }
-
-    public static Texture loadTextureATC(Resources res, int id) {
-        Texture tex = new Texture(0, 0, 0, null, "Stub!");
-        return tex;
-    }
-
-    private static ETC1Util.ETC1Texture compressTexture(Buffer input,
-                                                        int width, int height,
-                                                        int pixelSize, int stride){
-        int encodedImageSize = ETC1.getEncodedDataSize(width, height);
-        ByteBuffer compressedImage = ByteBuffer.allocateDirect(encodedImageSize).
-            order(ByteOrder.nativeOrder());
-        ETC1.encodeImage(input, width, height, pixelSize, stride, compressedImage);
-        return new ETC1Util.ETC1Texture(width, height, compressedImage);
-    }
-
-    public static Texture createFromUncompressedETC1(Bitmap bitmap) {
-        int dataSize = bitmap.getRowBytes() * bitmap.getHeight();
-
-        ByteBuffer dataBuffer;
-        dataBuffer = ByteBuffer.allocateDirect(dataSize).order(ByteOrder.nativeOrder());
-        bitmap.copyPixelsToBuffer(dataBuffer);
-        dataBuffer.position(0);
-
-        int bytesPerPixel = bitmap.getRowBytes() / bitmap.getWidth();
-        ETC1Util.ETC1Texture compressed = compressTexture(dataBuffer,
-                                                          bitmap.getWidth(),
-                                                          bitmap.getHeight(),
-                                                          bytesPerPixel,
-                                                          bitmap.getRowBytes());
-
-        Texture tex = new Texture(compressed.getWidth(), compressed.getHeight(),
-                                  ETC1.ETC1_RGB8_OES, compressed.getData(), TEXTURE_ETC1);
-
-        return tex;
-    }
-
-    private static ByteBuffer read(InputStream is, int dataSize) {
-        ByteBuffer dataBuffer;
-        dataBuffer = ByteBuffer.allocateDirect(dataSize).order(ByteOrder.nativeOrder());
-        byte[] ioBuffer = new byte[4096];
-        for (int i = 0; i < dataSize; ) {
-            int chunkSize = Math.min(ioBuffer.length, dataSize - i);
-            try {
-                is.read(ioBuffer, 0, chunkSize);
-            } catch (Exception e) {
-                throw new RuntimeException("Unable to read data");
-            }
-            dataBuffer.put(ioBuffer, 0, chunkSize);
-            i += chunkSize;
-        }
-        dataBuffer.position(0);
-        return dataBuffer;
-    }
-
-    public static Texture loadTexturePVRTC(Resources res, int id) {
-        InputStream is = null;
-        try {
-            is = res.openRawResource(id);
-        } catch (Exception e) {
-            throw new RuntimeException("Unable to open resource " + id);
-        }
-
-        PVRHeader header = readPVRHeader(is);
-
-        int format = header.mpfFlags & 0xFF;
-        int internalFormat = 0;
-        if (format == PVR_2BPP && header.mAlphaBitMask == 1) {
-            internalFormat = GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
-        } else if (format == PVR_2BPP && header.mAlphaBitMask == 0) {
-            internalFormat = GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
-        } else if (format == PVR_4BPP && header.mAlphaBitMask == 1) {
-            internalFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
-        } else if (format == PVR_4BPP && header.mAlphaBitMask == 0) {
-            internalFormat = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
-        }
-
-        // only load the first mip level for now
-        int dataSize = (header.mWidth * header.mHeight * header.mBitCount) >> 3;
-        ByteBuffer dataBuffer = read(is, dataSize);
-        Texture tex = new Texture(header.mWidth, header.mHeight,
-                                  internalFormat, dataBuffer,
-                                  TEXTURE_PVRTC);
-        try {
-            is.close();
-        } catch (Exception e) {
-            throw new RuntimeException("Unable to close resource stream " + id);
-        }
-        return tex;
-    }
-
-    /* DDS Header is described by the following structs
-       typedef struct {
-          DWORD           dwSize;
-          DWORD           dwFlags;
-          DWORD           dwHeight;
-          DWORD           dwWidth;
-          DWORD           dwPitchOrLinearSize;
-          DWORD           dwDepth;
-          DWORD           dwMipMapCount;
-          DWORD           dwReserved1[11];
-          DDS_PIXELFORMAT ddspf;
-          DWORD           dwCaps;
-          DWORD           dwCaps2;
-          DWORD           dwCaps3;
-          DWORD           dwCaps4;
-          DWORD           dwReserved2;
-        } DDS_HEADER;
-
-        struct DDS_PIXELFORMAT {
-          DWORD dwSize;
-          DWORD dwFlags;
-          DWORD dwFourCC;
-          DWORD dwRGBBitCount;
-          DWORD dwRBitMask;
-          DWORD dwGBitMask;
-          DWORD dwBBitMask;
-          DWORD dwABitMask;
-        };
-
-        In the file it looks like this
-        DWORD               dwMagic;
-        DDS_HEADER          header;
-        DDS_HEADER_DXT10    header10; // If the DDS_PIXELFORMAT dwFlags is set to DDPF_FOURCC
-                                      // and dwFourCC is DX10
-
-    */
-
-    static final int DDS_HEADER_STRUCT_SIZE = 124;
-    static final int DDS_PIXELFORMAT_STRUCT_SIZE = 32;
-    static final int DDS_HEADER_SIZE = 128;
-    static final int DDS_MAGIC_NUMBER = 0x20534444;
-    static final int DDS_DDPF_FOURCC = 0x4;
-    static final int DDS_DXT1 = 0x31545844;
-    static final int DDS_DXT5 = 0x35545844;
-
-    static final int COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0;
-    static final int COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1;
-    static final int COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3;
-
-    static class DDSHeader {
-        int mMagic;
-        int mSize;
-        int mFlags;
-        int mHeight;
-        int mWidth;
-        int mPitchOrLinearSize;
-        int mDepth;
-        int mMipMapCount;
-        int[] mReserved1;
-        // struct DDS_PIXELFORMAT {
-            int mPixelFormatSize;
-            int mPixelFormatFlags;
-            int mPixelFormatFourCC;
-            int mPixelFormatRGBBitCount;
-            int mPixelFormatRBitMask;
-            int mPixelFormatGBitMask;
-            int mPixelFormatBBitMask;
-            int mPixelFormatABitMask;
-        // };
-        int mCaps;
-        int mCaps2;
-        int mCaps3;
-        int mCaps4;
-        int mReserved2;
-
-        DDSHeader() {
-            mReserved1 = new int[11];
-        }
-    }
-
-    protected static DDSHeader readDDSHeader(InputStream is) {
-
-        byte[] headerData = new byte[DDS_HEADER_SIZE];
-        try {
-            is.read(headerData);
-        } catch (Exception e) {
-            throw new RuntimeException("Unable to read data");
-        }
-
-        ByteBuffer headerBuffer = ByteBuffer.allocateDirect(DDS_HEADER_SIZE)
-                .order(ByteOrder.nativeOrder());
-        headerBuffer.put(headerData, 0, DDS_HEADER_SIZE).position(0);
-
-        DDSHeader header = new DDSHeader();
-
-        header.mMagic = headerBuffer.getInt();
-        header.mSize = headerBuffer.getInt();
-        header.mFlags = headerBuffer.getInt();
-        header.mHeight = headerBuffer.getInt();
-        header.mWidth = headerBuffer.getInt();
-        header.mPitchOrLinearSize = headerBuffer.getInt();
-        header.mDepth = headerBuffer.getInt();
-        header.mMipMapCount = headerBuffer.getInt();
-        for (int i = 0; i < header.mReserved1.length; i ++) {
-            header.mReserved1[i] = headerBuffer.getInt();
-        }
-        // struct DDS_PIXELFORMAT {
-            header.mPixelFormatSize = headerBuffer.getInt();
-            header.mPixelFormatFlags = headerBuffer.getInt();
-            header.mPixelFormatFourCC = headerBuffer.getInt();
-            header.mPixelFormatRGBBitCount = headerBuffer.getInt();
-            header.mPixelFormatRBitMask = headerBuffer.getInt();
-            header.mPixelFormatGBitMask = headerBuffer.getInt();
-            header.mPixelFormatBBitMask = headerBuffer.getInt();
-            header.mPixelFormatABitMask = headerBuffer.getInt();
-        // };
-        header.mCaps = headerBuffer.getInt();
-        header.mCaps2 = headerBuffer.getInt();
-        header.mCaps3 = headerBuffer.getInt();
-        header.mCaps4 = headerBuffer.getInt();
-        header.mReserved2 = headerBuffer.getInt();
-
-        if (header.mSize != DDS_HEADER_STRUCT_SIZE ||
-            header.mPixelFormatSize != DDS_PIXELFORMAT_STRUCT_SIZE ||
-            header.mMagic != DDS_MAGIC_NUMBER) {
-            throw new RuntimeException("Invalid header data");
-        }
-
-        return header;
-    }
-
-    // Very simple loader that only reads in the header and a DXT1 mip level 0
-    public static Texture loadTextureDXT(Resources res, int id) {
-        InputStream is = null;
-        try {
-            is = res.openRawResource(id);
-        } catch (Exception e) {
-            throw new RuntimeException("Unable to open resource " + id);
-        }
-
-        DDSHeader header = readDDSHeader(is);
-
-        if (header.mPixelFormatFlags != DDS_DDPF_FOURCC) {
-            throw new RuntimeException("Unsupported DXT data");
-        }
-
-        int internalFormat = 0;
-        int bpp = 0;
-        switch (header.mPixelFormatFourCC) {
-        case DDS_DXT1:
-            internalFormat = COMPRESSED_RGB_S3TC_DXT1_EXT;
-            bpp = 4;
-            break;
-        case DDS_DXT5:
-            internalFormat = COMPRESSED_RGBA_S3TC_DXT5_EXT;
-            bpp = 8;
-            break;
-        default:
-            throw new RuntimeException("Unsupported DXT data");
-        }
-
-        // only load the first mip level for now
-        int dataSize = (header.mWidth * header.mHeight * bpp) >> 3;
-        if (dataSize != header.mPitchOrLinearSize) {
-            throw new RuntimeException("Expected data and header mismatch");
-        }
-        ByteBuffer dataBuffer = read(is, dataSize);
-
-        Texture tex = new Texture(header.mWidth, header.mHeight, internalFormat,
-                                  dataBuffer, TEXTURE_S3TC);
-        return tex;
-    }
-
-    static HashMap<String, Boolean> sExtensionMap;
-    static HashMap<String, Boolean> sFormatMap;
-
-    private static synchronized void updateSupportedFormats() {
-        if (sExtensionMap != null) {
-            return;
-        }
-
-        sExtensionMap = new HashMap<String, Boolean>();
-        sFormatMap = new HashMap<String, Boolean>();
-        String extensionList = GLES20.glGetString(GLES20.GL_EXTENSIONS);
-
-        for (String extension : extensionList.split(" ")) {
-            sExtensionMap.put(extension, true);
-        }
-
-        // Check ETC1
-        sFormatMap.put(TEXTURE_ETC1, ETC1Util.isETC1Supported());
-        // Check ATC
-        if (sExtensionMap.get("GL_AMD_compressed_ATC_texture") != null ||
-            sExtensionMap.get("GL_ATI_compressed_texture_atitc") != null ||
-            sExtensionMap.get("GL_ATI_texture_compression_atitc") != null) {
-            sFormatMap.put(TEXTURE_ATC, true);
-        }
-        // Check DXT
-        if (sExtensionMap.get("GL_EXT_texture_compression_dxt1") != null ||
-            sExtensionMap.get("GL_EXT_texture_compression_s3tc") != null ||
-            sExtensionMap.get("OES_texture_compression_S3TC") != null) {
-            sFormatMap.put(TEXTURE_S3TC, true);
-        }
-        // Check DXT
-        if (sExtensionMap.get("GL_IMG_texture_compression_pvrtc") != null) {
-            sFormatMap.put(TEXTURE_PVRTC, true);
-        }
-
-        /*Log.i(TAG, "mIsSupportedETC1 " + sFormatMap.get(TEXTURE_ETC1));
-        Log.i(TAG, "mIsSupportedATC " + sFormatMap.get(TEXTURE_ATC));
-        Log.i(TAG, "mIsSupportedDXT " + sFormatMap.get(TEXTURE_S3TC));
-        Log.i(TAG, "mIsSupportedPVRTC " + sFormatMap.get(TEXTURE_PVRTC));*/
-    }
-
-    private static boolean isFormatSupported(String format) {
-        updateSupportedFormats();
-        Boolean supported = sFormatMap.get(format);
-        return supported != null ? supported : false;
-    }
-}
diff --git a/tests/src/android/opengl/cts/CompressedTextureStubActivity.java b/tests/src/android/opengl/cts/CompressedTextureStubActivity.java
deleted file mode 100644
index cfd3129..0000000
--- a/tests/src/android/opengl/cts/CompressedTextureStubActivity.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.
- */
-package android.opengl.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.content.res.AssetFileDescriptor;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.BitmapFactory;
-import android.os.Bundle;
-import android.util.Log;
-
-public class CompressedTextureStubActivity extends Activity {
-
-    private static final String TAG = "CompressedTextureStubActivity";
-
-    protected Resources mResources;
-
-    private CompressedTextureSurfaceView mCompressedTextureView = null;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        Bundle extras = getIntent().getExtras();
-        String formatTest = extras.getString("TextureFormat", null);
-
-        Log.i(TAG, "Testing format " + formatTest);
-
-        mResources = getResources();
-
-        CompressedTextureLoader.Texture compressed = null;
-
-        BitmapFactory.Options optionsRGB = new BitmapFactory.Options();
-        optionsRGB.inPreferredConfig = Bitmap.Config.RGB_565;
-        optionsRGB.inScaled = false;
-        Bitmap bitmap = BitmapFactory.decodeResource(mResources, R.raw.basetex, optionsRGB);
-
-        if (formatTest.equals(CompressedTextureLoader.TEXTURE_ETC1)) {
-            compressed = CompressedTextureLoader.createFromUncompressedETC1(bitmap);
-        } else if (formatTest.equals(CompressedTextureLoader.TEXTURE_S3TC)) {
-            compressed = CompressedTextureLoader.loadTextureDXT(mResources, R.raw.ddstex);
-        } else if (formatTest.equals(CompressedTextureLoader.TEXTURE_ATC)) {
-            compressed = CompressedTextureLoader.loadTextureATC(mResources, 0); //stub for now
-        } else if (formatTest.equals(CompressedTextureLoader.TEXTURE_PVRTC)) {
-            compressed = CompressedTextureLoader.loadTexturePVRTC(mResources, R.raw.pvrtex);
-        }
-
-        mCompressedTextureView = new CompressedTextureSurfaceView(this, bitmap, compressed);
-        setContentView(mCompressedTextureView);
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        mCompressedTextureView.onResume();
-    }
-
-    public boolean getPassed() throws InterruptedException {
-        return mCompressedTextureView.getTestPassed();
-    }
-}
diff --git a/tests/src/android/opengl/cts/CompressedTextureSurfaceView.java b/tests/src/android/opengl/cts/CompressedTextureSurfaceView.java
deleted file mode 100644
index d0c8ed4..0000000
--- a/tests/src/android/opengl/cts/CompressedTextureSurfaceView.java
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * 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.
- */
-
-package android.opengl.cts;
-
-import java.io.IOException;
-import java.nio.Buffer;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.FloatBuffer;
-import java.util.ArrayList;
-import java.util.HashMap;
-
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.opengles.GL10;
-
-import com.android.cts.stub.R;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.BitmapFactory;
-import android.graphics.Color;
-import android.graphics.SurfaceTexture;
-import android.opengl.ETC1;
-import android.opengl.ETC1Util;
-import android.opengl.GLES20;
-import android.opengl.GLSurfaceView;
-import android.opengl.GLUtils;
-import android.opengl.Matrix;
-import android.util.Log;
-import android.view.Surface;
-
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-class CompressedTextureSurfaceView extends GLSurfaceView {
-    private static final String TAG = "CompressedTextureSurfaceView";
-    private static final int SLEEP_TIME_MS = 1000;
-
-    CompressedTextureRender mRenderer;
-
-    public CompressedTextureSurfaceView(Context context,
-                                        Bitmap base,
-                                        CompressedTextureLoader.Texture compressed) {
-        super(context);
-
-        setEGLContextClientVersion(2);
-        mRenderer = new CompressedTextureRender(context, base, compressed);
-        setRenderer(mRenderer);
-        setRenderMode(RENDERMODE_WHEN_DIRTY);
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-    }
-
-    public boolean getTestPassed() throws InterruptedException {
-        return mRenderer.getTestPassed();
-    }
-
-    private static class CompressedTextureRender implements GLSurfaceView.Renderer {
-        private static String TAG = "CompressedTextureRender";
-
-        private static final int ALLOWED_DELTA = 25;
-        private static final int FBO_PIXEL_SIZE_BYTES = 4;
-        private static final int FLOAT_SIZE_BYTES = 4;
-        private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
-        private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
-        private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
-        private final float[] mTriangleVerticesData = {
-            // X, Y, Z, U, V
-            -1.0f, -1.0f, 0, 0.f, 0.f,
-            1.0f, -1.0f, 0, 1.f, 0.f,
-            -1.0f,  1.0f, 0, 0.f, 1.f,
-            1.0f,  1.0f, 0, 1.f, 1.f,
-        };
-
-        private FloatBuffer mTriangleVertices;
-
-        private final String mVertexShader =
-                "uniform mat4 uMVPMatrix;\n" +
-                "attribute vec4 aPosition;\n" +
-                "attribute vec4 aTextureCoord;\n" +
-                "varying vec2 vTextureCoord;\n" +
-                "void main() {\n" +
-                "  gl_Position = uMVPMatrix * aPosition;\n" +
-                "  vTextureCoord = aTextureCoord.xy;\n" +
-                "}\n";
-
-        private final String mFragmentShader =
-                "precision mediump float;\n" +
-                "varying vec2 vTextureCoord;\n" +
-                "uniform sampler2D sTexture;\n" +
-                "void main() {\n" +
-                "  gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
-                "}\n";
-
-        private float[] mMVPMatrix = new float[16];
-        private float[] mSTMatrix = new float[16];
-
-        private int mProgram;
-        private int mTextureID;
-        private int muMVPMatrixHandle;
-        private int maPositionHandle;
-        private int maTextureHandle;
-        private int msTextureHandle;
-
-        private int mColorTargetID;
-        private int mFrameBufferObjectID;
-
-        private boolean updateSurface = false;
-
-        private boolean mTestPassed;
-        private CountDownLatch mDoneSignal;
-
-        Bitmap mBaseTexture;
-        CompressedTextureLoader.Texture mCompressedTexture;
-
-        int mWidth;
-        int mHeight;
-
-        ByteBuffer mReadBackBuffer;
-
-        boolean getTestPassed() throws InterruptedException {
-            if (!mDoneSignal.await(2000L, TimeUnit.MILLISECONDS)) {
-                throw new IllegalStateException("Coudn't finish drawing frames!");
-            }
-
-            return mTestPassed;
-        }
-
-        public CompressedTextureRender(Context context,
-                                       Bitmap base,
-                                       CompressedTextureLoader.Texture compressed) {
-            mBaseTexture = base;
-            mCompressedTexture = compressed;
-            mTriangleVertices = ByteBuffer.allocateDirect(
-                mTriangleVerticesData.length * FLOAT_SIZE_BYTES)
-                    .order(ByteOrder.nativeOrder()).asFloatBuffer();
-            mTriangleVertices.put(mTriangleVerticesData).position(0);
-
-            Matrix.setIdentityM(mSTMatrix, 0);
-
-            int byteBufferSize = mBaseTexture.getWidth() *
-                                 mBaseTexture.getHeight() *
-                                 FBO_PIXEL_SIZE_BYTES;
-            mReadBackBuffer = ByteBuffer.allocateDirect(byteBufferSize);
-
-            mDoneSignal = new CountDownLatch(1);
-        }
-
-        private void renderQuad(int textureID) {
-            GLES20.glUseProgram(mProgram);
-            checkGlError("glUseProgram");
-
-            GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
-            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureID);
-
-            mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
-            GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false,
-                TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
-            checkGlError("glVertexAttribPointer maPosition");
-            GLES20.glEnableVertexAttribArray(maPositionHandle);
-            checkGlError("glEnableVertexAttribArray maPositionHandle");
-
-            mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
-            GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false,
-                TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
-            checkGlError("glVertexAttribPointer maTextureHandle");
-            GLES20.glEnableVertexAttribArray(maTextureHandle);
-            checkGlError("glEnableVertexAttribArray maTextureHandle");
-
-            Matrix.setIdentityM(mMVPMatrix, 0);
-            GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
-
-            GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
-            checkGlError("glDrawArrays");
-        }
-
-        private int getUnsignedByte(byte val) {
-            return 0xFF & ((int)val);
-        }
-
-        private boolean comparePixel(int x, int y) {
-            int w = mBaseTexture.getWidth();
-            int sampleStart = (y * w + x) * FBO_PIXEL_SIZE_BYTES;
-
-            int R = getUnsignedByte(mReadBackBuffer.get(sampleStart));
-            int G = getUnsignedByte(mReadBackBuffer.get(sampleStart + 1));
-            int B = getUnsignedByte(mReadBackBuffer.get(sampleStart + 2));
-
-            int original = mBaseTexture.getPixel(x, y);
-
-            int deltaR = Math.abs(R - Color.red(original));
-            int deltaG = Math.abs(G - Color.green(original));
-            int deltaB = Math.abs(B - Color.blue(original));
-
-            if (deltaR <= ALLOWED_DELTA &&
-                deltaG <= ALLOWED_DELTA &&
-                deltaB <= ALLOWED_DELTA) {
-                return true;
-            }
-
-            Log.i("PIXEL DELTA", "R: " + deltaR + " G: " + deltaG + " B: " + deltaB);
-
-            return false;
-        }
-
-        private void comparePixels() {
-            int w = mBaseTexture.getWidth();
-            int h = mBaseTexture.getWidth();
-            int wOver4 = w / 4;
-            int hOver4 = h / 4;
-
-            // Sample 4 points in the image. Test is designed so that
-            // sample areas are low frequency and easy to compare
-            boolean sample1Matches = comparePixel(wOver4, hOver4);
-            boolean sample2Matches = comparePixel(wOver4 * 3, hOver4);
-            boolean sample3Matches = comparePixel(wOver4, hOver4 * 3);
-            boolean sample4Matches = comparePixel(wOver4 * 3, hOver4 * 3);
-
-            mTestPassed = sample1Matches && sample2Matches && sample3Matches && sample4Matches;
-            mDoneSignal.countDown();
-        }
-
-        public void onDrawFrame(GL10 glUnused) {
-            if (mProgram == 0) {
-                return;
-            }
-
-            GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBufferObjectID);
-            GLES20.glViewport(0, 0, mBaseTexture.getWidth(), mBaseTexture.getHeight());
-            GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
-            renderQuad(mTextureID);
-            GLES20.glReadPixels(0, 0, mBaseTexture.getWidth(), mBaseTexture.getHeight(),
-                                GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, mReadBackBuffer);
-            comparePixels();
-            GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
-
-            GLES20.glViewport(0, 0, mWidth, mHeight);
-            GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
-            GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-
-            renderQuad(mColorTargetID);
-
-            GLES20.glFinish();
-        }
-
-        public void onSurfaceChanged(GL10 glUnused, int width, int height) {
-            mWidth = width;
-            mHeight = height;
-        }
-
-        private void setupSamplers() {
-            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
-                    GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
-            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
-                    GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
-            GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
-                    GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
-            GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
-                    GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
-        }
-
-        private void initFBO() {
-            int[] textures = new int[1];
-            GLES20.glGenTextures(1, textures, 0);
-
-            mColorTargetID = textures[0];
-            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mColorTargetID);
-            checkGlError("glBindTexture mColorTargetID");
-            setupSamplers();
-            GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA,
-                                mBaseTexture.getWidth(), mBaseTexture.getHeight(), 0,
-                                GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
-            checkGlError("glTexImage2D mColorTargetID");
-
-            GLES20.glGenFramebuffers(1, textures, 0);
-            mFrameBufferObjectID = textures[0];
-            GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBufferObjectID);
-
-            GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
-                                          GLES20.GL_TEXTURE_2D, mColorTargetID, 0);
-
-            int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
-            if(status != GLES20.GL_FRAMEBUFFER_COMPLETE) {
-                throw new RuntimeException("Failed to initialize framebuffer object");
-            }
-
-            GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
-        }
-
-        public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
-            if (mCompressedTexture != null && !mCompressedTexture.isSupported()) {
-                mTestPassed = true;
-                mDoneSignal.countDown();
-                return;
-            }
-
-            initFBO();
-
-            mProgram = createProgram(mVertexShader, mFragmentShader);
-            if (mProgram == 0) {
-                return;
-            }
-            maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
-            checkGlError("glGetAttribLocation aPosition");
-            if (maPositionHandle == -1) {
-                throw new RuntimeException("Could not get attrib location for aPosition");
-            }
-            maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord");
-            checkGlError("glGetAttribLocation aTextureCoord");
-            if (maTextureHandle == -1) {
-                throw new RuntimeException("Could not get attrib location for aTextureCoord");
-            }
-
-            muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
-            checkGlError("glGetUniformLocation uMVPMatrix");
-            if (muMVPMatrixHandle == -1) {
-                throw new RuntimeException("Could not get attrib location for uMVPMatrix");
-            }
-
-            int[] textures = new int[1];
-            GLES20.glGenTextures(1, textures, 0);
-
-            mTextureID = textures[0];
-            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);
-            checkGlError("glBindTexture mTextureID");
-            setupSamplers();
-
-            if (mCompressedTexture == null) {
-                GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, mBaseTexture, 0);
-                checkGlError("texImage2D mBaseTexture");
-            } else {
-                GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D,
-                                              0,
-                                              mCompressedTexture.getFormat(),
-                                              mCompressedTexture.getWidth(),
-                                              mCompressedTexture.getHeight(),
-                                              0,
-                                              mCompressedTexture.getData().remaining(),
-                                              mCompressedTexture.getData());
-                checkGlError("glCompressedTexImage2D mTextureID");
-            }
-        }
-
-        synchronized public void onFrameAvailable(SurfaceTexture surface) {
-            updateSurface = true;
-        }
-
-        private int loadShader(int shaderType, String source) {
-            int shader = GLES20.glCreateShader(shaderType);
-            if (shader != 0) {
-                GLES20.glShaderSource(shader, source);
-                GLES20.glCompileShader(shader);
-                int[] compiled = new int[1];
-                GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
-                if (compiled[0] == 0) {
-                    Log.e(TAG, "Could not compile shader " + shaderType + ":");
-                    Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
-                    GLES20.glDeleteShader(shader);
-                    shader = 0;
-                }
-            }
-            return shader;
-        }
-
-        private int createProgram(String vertexSource, String fragmentSource) {
-            int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
-            if (vertexShader == 0) {
-                return 0;
-            }
-            int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
-            if (pixelShader == 0) {
-                return 0;
-            }
-
-            int program = GLES20.glCreateProgram();
-            if (program != 0) {
-                GLES20.glAttachShader(program, vertexShader);
-                checkGlError("glAttachShader");
-                GLES20.glAttachShader(program, pixelShader);
-                checkGlError("glAttachShader");
-                GLES20.glLinkProgram(program);
-                int[] linkStatus = new int[1];
-                GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
-                if (linkStatus[0] != GLES20.GL_TRUE) {
-                    Log.e(TAG, "Could not link program: ");
-                    Log.e(TAG, GLES20.glGetProgramInfoLog(program));
-                    GLES20.glDeleteProgram(program);
-                    program = 0;
-                }
-            }
-            return program;
-        }
-
-        private void checkGlError(String op) {
-            int error;
-            while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
-                Log.e(TAG, op + ": glError " + error);
-                throw new RuntimeException(op + ": glError " + error);
-            }
-        }
-
-    }  // End of class CompressedTextureRender.
-
-}  // End of class CompressedTextureSurfaceView.
diff --git a/tests/src/android/opengl/cts/EglConfigStubActivity.java b/tests/src/android/opengl/cts/EglConfigStubActivity.java
deleted file mode 100644
index 749679a..0000000
--- a/tests/src/android/opengl/cts/EglConfigStubActivity.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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.
- */
-
-package android.opengl.cts;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.opengl.GLSurfaceView;
-import android.os.Bundle;
-import android.view.WindowManager;
-
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-/**
- * {@link Activity} with a {@link GLSurfaceView} that chooses a specific configuration.
- */
-public class EglConfigStubActivity extends Activity {
-
-    public static final String CONFIG_ID_EXTRA = "eglConfigId";
-
-    public static final String CONTEXT_CLIENT_VERSION_EXTRA = "eglContextClientVersion";
-
-    private EglConfigGLSurfaceView mView;
-
-    private CountDownLatch mFinishedDrawing;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        int configId = getConfigId();
-        int contextClientVersion = getContextClientVersion();
-        setTitle("EGL Config Id: " + configId + " Client Version: " + contextClientVersion);
-
-        // Dismiss keyguard and keep screen on while this test is on.
-        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
-                WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
-                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
-
-        mFinishedDrawing = new CountDownLatch(1);
-        mView = new EglConfigGLSurfaceView(this, configId, contextClientVersion, new Runnable() {
-            @Override
-            public void run() {
-                mFinishedDrawing.countDown();
-            }
-        });
-        setContentView(mView);
-    }
-
-    private int getConfigId() {
-        Intent intent = getIntent();
-        if (intent != null) {
-            return intent.getIntExtra(CONFIG_ID_EXTRA, 0);
-        } else {
-            return 0;
-        }
-    }
-
-    private int getContextClientVersion() {
-        Intent intent = getIntent();
-        if (intent != null) {
-            return intent.getIntExtra(CONTEXT_CLIENT_VERSION_EXTRA, 0);
-        } else {
-            return 0;
-        }
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        mView.onResume();
-    }
-
-    @Override
-    protected void onPause() {
-        super.onPause();
-        mView.onPause();
-    }
-
-    public void waitToFinishDrawing() throws InterruptedException {
-        if (!mFinishedDrawing.await(3, TimeUnit.SECONDS)) {
-            throw new IllegalStateException("Coudn't finish drawing frames!");
-        }
-    }
-}
diff --git a/tests/src/android/opengl/cts/GLSurfaceViewStubActivity.java b/tests/src/android/opengl/cts/GLSurfaceViewStubActivity.java
deleted file mode 100644
index 85ad172..0000000
--- a/tests/src/android/opengl/cts/GLSurfaceViewStubActivity.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2010 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.opengl.cts;
-
-import android.app.Activity;
-import android.opengl.GLSurfaceView;
-import android.os.Bundle;
-import android.view.Window;
-
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.opengles.GL10;
-
-/**
- * A minimal activity for testing {@link android.opengl.GLSurfaceView}.
- * Also accepts non-blank renderers to allow its use for more complex tests.
- */
-public class GLSurfaceViewStubActivity extends Activity {
-
-    private static class Renderer implements GLSurfaceView.Renderer {
-
-        public void onDrawFrame(GL10 gl) {
-            // Do nothing.
-        }
-
-        public void onSurfaceChanged(GL10 gl, int width, int height) {
-            // Do nothing.
-        }
-
-        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
-            // Do nothing.
-        }
-    }
-
-    private GLSurfaceView mView;
-
-    /** To override the blank renderer, or other settings, these
-     * static set* methods must be called before onCreate() is called.
-     * If using ActivityInstrumentationTestCase2, that means the set
-     * methods need to be called before calling getActivity in the
-     * test setUp().
-     */
-    private static GLSurfaceView.Renderer mRenderer = null;
-    public static void setRenderer(GLSurfaceView.Renderer renderer) {
-        mRenderer = renderer;
-    }
-    public static void resetRenderer() {
-        mRenderer = null;
-    }
-
-    private static int mRenderMode = 0;
-    private static boolean mRenderModeSet = false;
-    public static void setRenderMode(int renderMode) {
-        mRenderModeSet = true;
-        mRenderMode = renderMode;
-    }
-    public static void resetRenderMode() {
-        mRenderModeSet = false;
-        mRenderMode = 0;
-    }
-
-    private static int mGlVersion = 0;
-    private static boolean mGlVersionSet = false;
-    public static void setGlVersion(int glVersion) {
-        mGlVersionSet = true;
-        mGlVersion = glVersion;
-    }
-    public static void resetGlVersion() {
-        mGlVersionSet = false;
-        mGlVersion = 0;
-    }
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        mView = new GLSurfaceView(this);
-        // Only set this if explicitly asked for
-        if (mGlVersionSet) {
-            mView.setEGLContextClientVersion(mGlVersion);
-        }
-        // Use no-op renderer by default
-        if (mRenderer == null) {
-            mView.setRenderer(new Renderer());
-        } else {
-            mView.setRenderer(mRenderer);
-        }
-        // Only set this if explicitly asked for
-        if (mRenderModeSet) {
-            mView.setRenderMode(mRenderMode);
-        }
-        this.requestWindowFeature(Window.FEATURE_NO_TITLE);
-        setContentView(mView);
-    }
-
-    public GLSurfaceView getView() {
-        return mView;
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        mView.onResume();
-    }
-
-    @Override
-    protected void onPause() {
-        super.onPause();
-        mView.onPause();
-    }
-}
diff --git a/tests/src/android/opengl/cts/OpenGlEsVersionStubActivity.java b/tests/src/android/opengl/cts/OpenGlEsVersionStubActivity.java
deleted file mode 100644
index 488c8bd..0000000
--- a/tests/src/android/opengl/cts/OpenGlEsVersionStubActivity.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2010 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.opengl.cts;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.opengl.GLSurfaceView;
-import android.os.Bundle;
-
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.opengles.GL10;
-
-/**
- * {@link Activity} that queries the device's display attributes to determine what version of
- * OpenGL ES is supported and returns what the GL version string reports.
- */
-public class OpenGlEsVersionStubActivity extends Activity {
-
-    private static final String EGL_CONTEXT_CLIENT_VERSION = "eglContextClientVersion";
-
-    /** Timeout to wait for the surface to be created and the version queried. */
-    private static final int TIMEOUT_SECONDS = 10;
-
-    /** Version string reported by glGetString. */
-    private String mVersionString;
-
-    /** Latch that is unlocked when the activity is done finding the version. */
-    private CountDownLatch mSurfaceCreatedLatch = new CountDownLatch(1);
-
-    public static Intent createIntent(int eglContextClientVersion) {
-        Intent intent = new Intent(Intent.ACTION_MAIN);
-        intent.putExtra(EGL_CONTEXT_CLIENT_VERSION, eglContextClientVersion);
-        return intent;
-    }
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        GLSurfaceView view = new GLSurfaceView(this);
-
-        Intent intent = getIntent();
-        int eglContextClientVersion = intent.getIntExtra(EGL_CONTEXT_CLIENT_VERSION, -1);
-        if (eglContextClientVersion > 0) {
-            view.setEGLContextClientVersion(eglContextClientVersion);
-        }
-
-        view.setRenderer(new Renderer());
-        setContentView(view);
-    }
-
-    public String getVersionString() throws InterruptedException {
-        mSurfaceCreatedLatch.await(TIMEOUT_SECONDS, TimeUnit.SECONDS);
-        synchronized (this) {
-            return mVersionString;
-        }
-    }
-
-    private class Renderer implements GLSurfaceView.Renderer {
-
-        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
-            synchronized (OpenGlEsVersionStubActivity.this) {
-                try {
-                    mVersionString = gl.glGetString(GL10.GL_VERSION);
-                } finally {
-                    mSurfaceCreatedLatch.countDown();
-                }
-            }
-        }
-
-        public void onSurfaceChanged(GL10 gl, int width, int height) {
-        }
-
-        public void onDrawFrame(GL10 gl) {
-        }
-    }
-}
diff --git a/tests/src/android/os/cts/CpuFeatures.java b/tests/src/android/os/cts/CpuFeatures.java
deleted file mode 100644
index 5009474..0000000
--- a/tests/src/android/os/cts/CpuFeatures.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2010 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.os.cts;
-
-public class CpuFeatures {
-
-    public static final String ARMEABI_V7 = "armeabi-v7a";
-
-    public static final String ARMEABI = "armeabi";
-
-    public static final String MIPSABI = "mips";
-
-    public static final  String X86ABI = "x86";
-
-    static {
-        System.loadLibrary("cts_jni");
-    }
-
-    public static native boolean isArmCpu();
-
-    public static native boolean isArm7Compatible();
-
-    public static native boolean isMipsCpu();
-
-    public static native boolean isX86Cpu();
-}
diff --git a/tests/src/android/os/cts/FileUtils.java b/tests/src/android/os/cts/FileUtils.java
deleted file mode 100644
index ea31c54..0000000
--- a/tests/src/android/os/cts/FileUtils.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * 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.
- */
-
-package android.os.cts;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/** Bits and pieces copied from hidden API of android.os.FileUtils. */
-public class FileUtils {
-
-    public static final int S_IFMT  = 0170000;
-    public static final int S_IFSOCK = 0140000;
-    public static final int S_IFLNK = 0120000;
-    public static final int S_IFREG = 0100000;
-    public static final int S_IFBLK = 0060000;
-    public static final int S_IFDIR = 0040000;
-    public static final int S_IFCHR = 0020000;
-    public static final int S_IFIFO = 0010000;
-
-    public static final int S_ISUID = 0004000;
-    public static final int S_ISGID = 0002000;
-    public static final int S_ISVTX = 0001000;
-
-    public static final int S_IRWXU = 00700;
-    public static final int S_IRUSR = 00400;
-    public static final int S_IWUSR = 00200;
-    public static final int S_IXUSR = 00100;
-
-    public static final int S_IRWXG = 00070;
-    public static final int S_IRGRP = 00040;
-    public static final int S_IWGRP = 00020;
-    public static final int S_IXGRP = 00010;
-
-    public static final int S_IRWXO = 00007;
-    public static final int S_IROTH = 00004;
-    public static final int S_IWOTH = 00002;
-    public static final int S_IXOTH = 00001;
-
-    static {
-        System.loadLibrary("cts_jni");
-    }
-
-    public static class FileStatus {
-
-        public int dev;
-        public int ino;
-        public int mode;
-        public int nlink;
-        public int uid;
-        public int gid;
-        public int rdev;
-        public long size;
-        public int blksize;
-        public long blocks;
-        public long atime;
-        public long mtime;
-        public long ctime;
-
-        public boolean hasModeFlag(int flag) {
-            if (((S_IRWXU | S_IRWXG | S_IRWXO) & flag) != flag) {
-                throw new IllegalArgumentException("Inappropriate flag " + flag);
-            }
-            return (mode & flag) == flag;
-        }
-
-        public boolean isOfType(int type) {
-            if ((type & S_IFMT) != type) {
-                throw new IllegalArgumentException("Unknown type " + type);
-            }
-            return (mode & S_IFMT) == type;
-        }
-    }
-
-    /**
-     * @param path of the file to stat
-     * @param status object to set the fields on
-     * @param statLinks or don't stat links (lstat vs stat)
-     * @return whether or not we were able to stat the file
-     */
-    public native static boolean getFileStatus(String path, FileStatus status, boolean statLinks);
-
-    public native static String getUserName(int uid);
-
-    public native static String getGroupName(int gid);
-
-    public native static int setPermissions(String file, int mode);
-
-    /**
-     * Copy data from a source stream to destFile.
-     * Return true if succeed, return false if failed.
-     */
-    public static boolean copyToFile(InputStream inputStream, File destFile) {
-        try {
-            if (destFile.exists()) {
-                destFile.delete();
-            }
-            FileOutputStream out = new FileOutputStream(destFile);
-            try {
-                byte[] buffer = new byte[4096];
-                int bytesRead;
-                while ((bytesRead = inputStream.read(buffer)) >= 0) {
-                    out.write(buffer, 0, bytesRead);
-                }
-            } finally {
-                out.flush();
-                try {
-                    out.getFD().sync();
-                } catch (IOException e) {
-                }
-                out.close();
-            }
-            return true;
-        } catch (IOException e) {
-            return false;
-        }
-    }
-
-    public static void createFile(File file, int numBytes) throws IOException {
-        File parentFile = file.getParentFile();
-        if (parentFile != null) {
-            parentFile.mkdirs();
-        }
-        byte[] buffer = new byte[numBytes];
-        FileOutputStream output = new FileOutputStream(file);
-        try {
-            output.write(buffer);
-        } finally {
-            output.close();
-        }
-    }
-
-    public static byte[] readInputStreamFully(InputStream is) {
-        ByteArrayOutputStream os = new ByteArrayOutputStream();
-        byte[] buffer = new byte[32768];
-        int count;
-        try {
-            while ((count = is.read(buffer)) != -1) {
-                os.write(buffer, 0, count);
-            }
-            is.close();
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-        return os.toByteArray();
-    }
-}
diff --git a/tests/src/android/os/cts/OSFeatures.java b/tests/src/android/os/cts/OSFeatures.java
deleted file mode 100644
index fd30f58..0000000
--- a/tests/src/android/os/cts/OSFeatures.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2013 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.os.cts;
-
-public class OSFeatures {
-    static {
-        System.loadLibrary("cts_jni");
-    }
-
-    public static native int getNoNewPrivs();
-    public static native int prctlCapBsetRead(int i);
-}
diff --git a/tests/src/android/os/cts/ReadElf.java b/tests/src/android/os/cts/ReadElf.java
deleted file mode 100644
index 89e9d48..0000000
--- a/tests/src/android/os/cts/ReadElf.java
+++ /dev/null
@@ -1,523 +0,0 @@
-/*
- * 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.
- */
-
-package android.os.cts;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * A poor man's implementation of the readelf command. This program is
- * designed to parse ELF (Executable and Linkable Format) files.
- */
-public class ReadElf implements AutoCloseable {
-    /** The magic values for the ELF identification. */
-    private static final byte[] ELF_IDENT = {
-            (byte) 0x7F, (byte) 'E', (byte) 'L', (byte) 'F',
-    };
-
-    private static final int EI_CLASS = 4;
-    private static final int EI_DATA = 5;
-
-    private static final int EM_386 = 3;
-    private static final int EM_MIPS = 8;
-    private static final int EM_ARM = 40;
-    // http://en.wikipedia.org/wiki/Qualcomm_Hexagon
-    private static final int EM_QDSP6 = 164;
-
-    /** Size of the e_ident[] structure in the ELF header. */
-    private static final int EI_NIDENT = 16;
-
-    /** Offset from end of ident structure in half-word sizes. */
-    private static final int OFFSET_TYPE = 0;
-
-    /** Machine type. */
-    private static final int OFFSET_MACHINE = 1;
-
-    /** ELF version. */
-    private static final int OFFSET_VERSION = 2;
-
-    /**
-     * The offset to which the system transfers control. e.g., the first thing
-     * executed.
-     */
-    private static final int OFFSET_ENTRY = 4;
-
-    /** Program header offset in bytes. */
-    private static final int OFFSET_PHOFF = 6;
-
-    /** Segment header offset in bytes. */
-    private static final int OFFSET_SHOFF = 8;
-
-    /** Processor-specific flags for binary. */
-    private static final int OFFSET_FLAGS = 10;
-
-    /** ELF header size in bytes. */
-    private static final int OFFSET_EHSIZE = 12;
-
-    /** All program headers entry size in bytes. */
-    private static final int OFFSET_PHENTSIZE = 13;
-
-    /** Number of program headers in ELF. */
-    private static final int OFFSET_PHNUM = 14;
-
-    /** All segment headers entry size in bytes. */
-    private static final int OFFSET_SHENTSIZE = 15;
-
-    /** Number of segment headers in ELF. */
-    private static final int OFFSET_SHNUM = 16;
-
-    /** The section header index that refers to string table. */
-    private static final int OFFSET_SHSTRNDX = 17;
-
-    /** Program header offset for type of this program header. */
-    private static final int PHOFF_TYPE = 0;
-
-    /** Program header offset for absolute offset in file. */
-    private static final int PHOFF_OFFSET = 2;
-
-    /** Program header offset for virtual address. */
-    private static final int PHOFF_VADDR = 4;
-
-    /** Program header offset for physical address. */
-    private static final int PHOFF_PADDR = 6;
-
-    /** Program header offset for file size in bytes. */
-    private static final int PHOFF_FILESZ = 8;
-
-    /** Program header offset for memory size in bytes. */
-    private static final int PHOFF_MEMSZ = 10;
-
-    /** Program header offset for flags. */
-    private static final int PHOFF_FLAGS = 12;
-
-    /**
-     * Program header offset for required alignment. 0 or 1 means no alignment
-     * necessary.
-     */
-    private static final int PHOFF_ALIGN = 14;
-
-    /** Index into string pool for segment name. */
-    private static final long SHOFF_NAME = 0;
-
-    /** Segment header offset for type (half-words) */
-    private static final long SHOFF_TYPE = 2;
-
-    /** Segment header offset for offset (meta!) (half-words) */
-    private static final long SHOFF_OFFSET = 8;
-
-    /** Segment header offset for size (half-words) */
-    private static final long SHOFF_SIZE = 10;
-
-    /** Data is presented in LSB format. */
-    private static final int ELFDATA2LSB = 1;
-
-    /** Date is presented in MSB format. */
-    private static final int ELFDATA2MSB = 2;
-
-    private static final int ELFCLASS32 = 1;
-
-    private static final int ELFCLASS64 = 2;
-
-    private static final long PT_LOAD = 1;
-
-    /** Section Type: Symbol Table */
-    private static final int SHT_SYMTAB = 2;
-
-    /** Section Type: String Table */
-    private static final int SHT_STRTAB = 3;
-
-    /** Section Type: Dynamic **/
-    private static final int SHT_DYNAMIC = 6;
-
-    /** Section Type: Dynamic Symbol Table */
-    private static final int SHT_DYNSYM = 11;
-
-    /** Symbol Table Entry: Name offset */
-    private static final int SYMTAB_NAME = 0;
-
-    /** Symbol Table Entry: SymTab Info */
-    private static final int SYMTAB_ST_INFO = 6;
-
-    /** Symbol Table Entry size (half-words) */
-    private static final int SYMTAB_ENTRY_HALFWORD_SIZE = 7;
-
-    /**
-     * Symbol Table Entry size (extra in bytes) to cover "st_info" and
-     * "st_other"
-     */
-    private static final int SYMTAB_ENTRY_BYTE_EXTRA_SIZE = 2;
-
-    public static class Symbol {
-        public static final int STB_LOCAL = 0;
-
-        public static final int STB_GLOBAL = 1;
-
-        public static final int STB_WEAK = 2;
-
-        public static final int STB_LOPROC = 13;
-
-        public static final int STB_HIPROC = 15;
-
-        public final String name;
-
-        public final int bind;
-
-        public final int type;
-
-        Symbol(String name, int st_info) {
-            this.name = name;
-            this.bind = (st_info >> 4) & 0x0F;
-            this.type = st_info & 0x0F;
-        }
-    };
-
-    private final String mPath;
-    private final RandomAccessFile mFile;
-    private final byte[] mBuffer = new byte[512];
-    private int mEndian;
-    private boolean mIsDynamic;
-    private boolean mIsPIE;
-    private int mType;
-    private int mWordSize;
-    private int mHalfWordSize;
-
-    /** Symbol Table offset */
-    private long mSymTabOffset;
-
-    /** Symbol Table size */
-    private long mSymTabSize;
-
-    /** Dynamic Symbol Table offset */
-    private long mDynSymOffset;
-
-    /** Dynamic Symbol Table size */
-    private long mDynSymSize;
-
-    /** Section Header String Table offset */
-    private long mShStrTabOffset;
-
-    /** Section Header String Table size */
-    private long mShStrTabSize;
-
-    /** String Table offset */
-    private long mStrTabOffset;
-
-    /** String Table size */
-    private long mStrTabSize;
-
-    /** Dynamic String Table offset */
-    private long mDynStrOffset;
-
-    /** Dynamic String Table size */
-    private long mDynStrSize;
-
-    /** Symbol Table symbol names */
-    private Map<String, Symbol> mSymbols;
-
-    /** Dynamic Symbol Table symbol names */
-    private Map<String, Symbol> mDynamicSymbols;
-
-    public static ReadElf read(File file) throws IOException {
-        return new ReadElf(file);
-    }
-
-    public boolean isDynamic() {
-        return mIsDynamic;
-    }
-
-    public int getType() {
-        return mType;
-    }
-
-    public boolean isPIE() {
-        return mIsPIE;
-    }
-
-    private ReadElf(File file) throws IOException {
-        mPath = file.getPath();
-        mFile = new RandomAccessFile(file, "r");
-
-        if (mFile.length() < EI_NIDENT) {
-            throw new IllegalArgumentException("Too small to be an ELF file: " + file);
-        }
-
-        readIdent();
-        readHeader();
-    }
-
-    public void close() {
-        try {
-            mFile.close();
-        } catch (IOException ignored) {
-        }
-    }
-
-    protected void finalize() throws Throwable {
-        try {
-            close();
-        } finally {
-            super.finalize();
-        }
-    }
-
-    private void readHeader() throws IOException {
-        mType = readHalf(getHeaderOffset(OFFSET_TYPE));
-        int e_machine = readHalf(getHeaderOffset(OFFSET_MACHINE));
-        if (e_machine != EM_386 && e_machine != EM_MIPS && e_machine != EM_ARM &&
-                e_machine != EM_QDSP6) {
-            throw new IOException("Invalid ELF e_machine: " + e_machine + ": " + mPath);
-        }
-
-        final long shOffset = readWord(getHeaderOffset(OFFSET_SHOFF));
-        final int shNumber = readHalf(getHeaderOffset(OFFSET_SHNUM));
-        final int shSize = readHalf(getHeaderOffset(OFFSET_SHENTSIZE));
-        final int shStrIndex = readHalf(getHeaderOffset(OFFSET_SHSTRNDX));
-
-        readSectionHeaders(shOffset, shNumber, shSize, shStrIndex);
-
-        final long phOffset = readWord(getHeaderOffset(OFFSET_PHOFF));
-        final int phNumber = readHalf(getHeaderOffset(OFFSET_PHNUM));
-        final int phSize = readHalf(getHeaderOffset(OFFSET_PHENTSIZE));
-
-        readProgramHeaders(phOffset, phNumber, phSize);
-    }
-
-    private void readSectionHeaders(long tableOffset, int shNumber, int shSize, int shStrIndex)
-            throws IOException {
-        // Read the Section Header String Table offset first.
-        {
-            final long shStrTabShOffset = tableOffset + shStrIndex * shSize;
-            final long type = readWord(shStrTabShOffset + mHalfWordSize * SHOFF_TYPE);
-
-            if (type == SHT_STRTAB) {
-                mShStrTabOffset = readWord(shStrTabShOffset + mHalfWordSize * SHOFF_OFFSET);
-                mShStrTabSize = readWord(shStrTabShOffset + mHalfWordSize * SHOFF_SIZE);
-            }
-        }
-
-        for (int i = 0; i < shNumber; i++) {
-            // Don't bother to re-read the Section Header StrTab.
-            if (i == shStrIndex) {
-                continue;
-            }
-
-            final long shOffset = tableOffset + i * shSize;
-
-            final long type = readWord(shOffset + mHalfWordSize * SHOFF_TYPE);
-            if ((type == SHT_SYMTAB) || (type == SHT_DYNSYM)) {
-                final long nameOffset = readWord(shOffset + mHalfWordSize * SHOFF_NAME);
-                final long offset = readWord(shOffset + mHalfWordSize * SHOFF_OFFSET);
-                final long size = readWord(shOffset + mHalfWordSize * SHOFF_SIZE);
-
-                final String symTabName = readShStrTabEntry(nameOffset);
-                if (".symtab".equals(symTabName)) {
-                    mSymTabOffset = offset;
-                    mSymTabSize = size;
-                } else if (".dynsym".equals(symTabName)) {
-                    mDynSymOffset = offset;
-                    mDynSymSize = size;
-                }
-            } else if (type == SHT_STRTAB) {
-                final long nameOffset = readWord(shOffset + mHalfWordSize * SHOFF_NAME);
-                final long offset = readWord(shOffset + mHalfWordSize * SHOFF_OFFSET);
-                final long size = readWord(shOffset + mHalfWordSize * SHOFF_SIZE);
-
-                final String strTabName = readShStrTabEntry(nameOffset);
-                if (".strtab".equals(strTabName)) {
-                    mStrTabOffset = offset;
-                    mStrTabSize = size;
-                } else if (".dynstr".equals(strTabName)) {
-                    mDynStrOffset = offset;
-                    mDynStrSize = size;
-                }
-            } else if (type == SHT_DYNAMIC) {
-                mIsDynamic = true;
-            }
-        }
-    }
-
-    private void readProgramHeaders(long phOffset, int phNumber, int phSize) throws IOException {
-        for (int i = 0; i < phNumber; i++) {
-            final long baseOffset = phOffset + i * phSize;
-            final long type = readWord(baseOffset);
-            if (type == PT_LOAD) {
-                final long virtAddress = readWord(baseOffset + mHalfWordSize * PHOFF_VADDR);
-                if (virtAddress == 0) {
-                    mIsPIE = true;
-                }
-            }
-        }
-    }
-
-    private void readSymbolTable(Map<String, Symbol> symbolMap, long symStrOffset, long symStrSize,
-            long symOffset, long symSize) throws IOException {
-        final long symEnd = symOffset + symSize;
-        for (long off = symOffset; off < symEnd; off += SYMTAB_ENTRY_HALFWORD_SIZE * mHalfWordSize
-                + SYMTAB_ENTRY_BYTE_EXTRA_SIZE) {
-            long strOffset = readWord(off + SYMTAB_NAME);
-            if (strOffset == 0) {
-                continue;
-            }
-
-            final String symName = readStrTabEntry(symStrOffset, symStrSize, strOffset);
-            if (symName != null) {
-                final int st_info = readByte(off + SYMTAB_ST_INFO);
-                symbolMap.put(symName, new Symbol(symName, st_info));
-            }
-        }
-    }
-
-    private String readShStrTabEntry(long strOffset) throws IOException {
-        if ((mShStrTabOffset == 0) || (strOffset < 0) || (strOffset >= mShStrTabSize)) {
-            return null;
-        }
-
-        return readString(mShStrTabOffset + strOffset);
-    }
-
-    private String readStrTabEntry(long tableOffset, long tableSize, long strOffset)
-            throws IOException {
-        if ((tableOffset == 0) || (strOffset < 0) || (strOffset >= tableSize)) {
-            return null;
-        }
-
-        return readString(tableOffset + strOffset);
-    }
-
-    private int getHeaderOffset(int halfWorldOffset) {
-        return EI_NIDENT + halfWorldOffset * mHalfWordSize;
-    }
-
-    private int readByte(long offset) throws IOException {
-        mFile.seek(offset);
-        mFile.readFully(mBuffer, 0, 1);
-
-        return mBuffer[0] & 0xff;
-    }
-
-    private int readHalf(long offset) throws IOException {
-        mFile.seek(offset);
-        mFile.readFully(mBuffer, 0, mWordSize);
-
-        final int answer;
-        if (mEndian == ELFDATA2LSB) {
-            answer = mBuffer[1] << 8 | (mBuffer[0] & 0xff);
-        } else {
-            answer = mBuffer[0] << 8 | (mBuffer[1] & 0xff);
-        }
-
-        return answer;
-    }
-
-    private long readWord(long offset) throws IOException {
-        mFile.seek(offset);
-        mFile.readFully(mBuffer, 0, mWordSize);
-
-        int answer = 0;
-        if (mEndian == ELFDATA2LSB) {
-            for (int i = mWordSize - 1; i >= 0; i--) {
-                answer = (answer << 8) | (mBuffer[i] & 0xff);
-            }
-        } else {
-            final int N = mWordSize - 1;
-            for (int i = 0; i <= N; i++) {
-                answer = (answer << 8) | (mBuffer[i] & 0xff);
-            }
-        }
-
-        return answer;
-    }
-
-    private String readString(long offset) throws IOException {
-        mFile.seek(offset);
-        mFile.readFully(mBuffer, 0, (int) Math.min(mBuffer.length, mFile.length() - offset));
-
-        for (int i = 0; i < mBuffer.length; i++) {
-            if (mBuffer[i] == 0) {
-                return new String(mBuffer, 0, i);
-            }
-        }
-
-        return null;
-    }
-
-    private void readIdent() throws IOException {
-        mFile.seek(0);
-        mFile.readFully(mBuffer, 0, EI_NIDENT);
-
-        if ((mBuffer[0] != ELF_IDENT[0]) || (mBuffer[1] != ELF_IDENT[1])
-                || (mBuffer[2] != ELF_IDENT[2]) || (mBuffer[3] != ELF_IDENT[3])) {
-            throw new IllegalArgumentException("Invalid ELF file: " + mPath);
-        }
-
-        int elfClass = mBuffer[EI_CLASS];
-        if (elfClass == ELFCLASS32) {
-            mWordSize = 4;
-            mHalfWordSize = 2;
-        } else if (elfClass == ELFCLASS64) {
-            throw new IOException("Unsupported ELFCLASS64 file: " + mPath);
-        } else {
-            throw new IOException("Invalid ELF EI_CLASS: " + elfClass + ": " + mPath);
-        }
-
-        mEndian = mBuffer[EI_DATA];
-        if (mEndian == ELFDATA2LSB) {
-        } else if (mEndian == ELFDATA2MSB) {
-            throw new IOException("Unsupported ELFDATA2MSB file: " + mPath);
-        } else {
-            throw new IOException("Invalid ELF EI_DATA: " + mEndian + ": " + mPath);
-        }
-    }
-
-    public Symbol getSymbol(String name) {
-        if ((mSymTabOffset == 0) && (mSymTabSize == 0)) {
-            return null;
-        }
-
-        if (mSymbols == null) {
-            mSymbols = new HashMap<String, Symbol>();
-            try {
-                readSymbolTable(mSymbols, mStrTabOffset, mStrTabSize, mSymTabOffset, mSymTabSize);
-            } catch (IOException e) {
-                return null;
-            }
-        }
-
-        return mSymbols.get(name);
-    }
-
-    public Symbol getDynamicSymbol(String name) {
-        if ((mDynSymOffset == 0) && (mDynSymSize == 0)) {
-            return null;
-        }
-
-        if (mDynamicSymbols == null) {
-            mDynamicSymbols = new HashMap<String, Symbol>();
-            try {
-                readSymbolTable(mDynamicSymbols, mDynStrOffset, mDynStrSize, mDynSymOffset,
-                        mDynSymSize);
-            } catch (IOException e) {
-                return null;
-            }
-        }
-
-        return mDynamicSymbols.get(name);
-    }
-}
diff --git a/tests/src/android/os/cts/TestThread.java b/tests/src/android/os/cts/TestThread.java
deleted file mode 100644
index 1a28a20..0000000
--- a/tests/src/android/os/cts/TestThread.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2009 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.os.cts;
-
-/**
- * Thread class for executing a Runnable containing assertions in a separate thread.
- * Uncaught exceptions in the Runnable are rethrown in the context of the the thread
- * calling the <code>runTest()</code> method.
- */
-public final class TestThread extends Thread {
-    private Throwable mThrowable;
-    private Runnable mTarget;
-
-    public TestThread(Runnable target) {
-        mTarget = target;
-    }
-
-    @Override
-    public final void run() {
-        try {
-            mTarget.run();
-        } catch (Throwable t) {
-            mThrowable = t;
-        }
-    }
-
-    /**
-     * Run the target Runnable object and wait until the test finish or throw
-     * out Exception if test fail.
-     *
-     * @param runTime
-     * @throws Throwable
-     */
-    public void runTest(long runTime) throws Throwable {
-        start();
-        joinAndCheck(runTime);
-    }
-
-    /**
-     * Get the Throwable object which is thrown when test running
-     * @return  The Throwable object
-     */
-    public Throwable getThrowable() {
-        return mThrowable;
-    }
-
-    /**
-     * Set the Throwable object which is thrown when test running
-     * @param t The Throwable object
-     */
-    public void setThrowable(Throwable t) {
-        mThrowable = t;
-    }
-
-    /**
-     * Wait for the test thread to complete and throw the stored exception if there is one.
-     *
-     * @param runTime The time to wait for the test thread to complete.
-     * @throws Throwable
-     */
-    public void joinAndCheck(long runTime) throws Throwable {
-        this.join(runTime);
-        if (this.isAlive()) {
-            this.interrupt();
-            this.join(runTime);
-            throw new Exception("Thread did not finish within allotted time.");
-        }
-        checkException();
-    }
-
-    /**
-     * Check whether there is an exception when running Runnable object.
-     * @throws Throwable
-     */
-    public void checkException() throws Throwable {
-        if (mThrowable != null) {
-            throw mThrowable;
-        }
-    }
-}
diff --git a/tests/src/android/preference/cts/PreferenceStubActivity.java b/tests/src/android/preference/cts/PreferenceStubActivity.java
deleted file mode 100644
index 4b6062b..0000000
--- a/tests/src/android/preference/cts/PreferenceStubActivity.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2010 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.preference.cts;
-
-import android.preference.PreferenceActivity;
-
-public class PreferenceStubActivity extends PreferenceActivity {
-}
diff --git a/tests/src/android/provider/cts/MediaStoreAudioTestHelper.java b/tests/src/android/provider/cts/MediaStoreAudioTestHelper.java
deleted file mode 100644
index a87cd3a..0000000
--- a/tests/src/android/provider/cts/MediaStoreAudioTestHelper.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright (C) 2009 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.provider.cts;
-
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.net.Uri;
-import android.os.Environment;
-import android.provider.MediaStore;
-import android.provider.MediaStore.Audio.Media;
-
-import junit.framework.Assert;
-
-/**
- * This class contains fake data and convenient methods for testing:
- * {@link MediaStore.Audio.Media}
- * {@link MediaStore.Audio.Genres}
- * {@link MediaStore.Audio.Genres.Members}
- * {@link MediaStore.Audio.Playlists}
- * {@link MediaStore.Audio.Playlists.Members}
- * {@link MediaStore.Audio.Albums}
- * {@link MediaStore.Audio.Artists}
- * {@link MediaStore.Audio.Artists.Albums}
- *
- * @see MediaStore_Audio_MediaTest
- * @see MediaStore_Audio_GenresTest
- * @see MediaStore_Audio_Genres_MembersTest
- * @see MediaStore_Audio_PlaylistsTest
- * @see MediaStore_Audio_Playlists_MembersTest
- * @see MediaStore_Audio_ArtistsTest
- * @see MediaStore_Audio_Artists_AlbumsTest
- * @see MediaStore_Audio_AlbumsTest
- */
-public class MediaStoreAudioTestHelper {
-    public static abstract class MockAudioMediaInfo {
-        public abstract ContentValues getContentValues(boolean isInternal);
-
-        public Uri insertToInternal(ContentResolver contentResolver) {
-            Uri uri = contentResolver.insert(Media.INTERNAL_CONTENT_URI, getContentValues(true));
-            Assert.assertNotNull(uri);
-            return uri;
-        }
-
-        public Uri insertToExternal(ContentResolver contentResolver) {
-            Uri uri = contentResolver.insert(Media.EXTERNAL_CONTENT_URI, getContentValues(false));
-            Assert.assertNotNull(uri);
-            return uri;
-        }
-
-        public int delete(ContentResolver contentResolver, Uri uri) {
-            return contentResolver.delete(uri, null, null);
-        }
-    }
-
-    public static class Audio1 extends MockAudioMediaInfo {
-        private Audio1() {
-        }
-
-        private static Audio1 sInstance = new Audio1();
-
-        public static Audio1 getInstance() {
-            return sInstance;
-        }
-
-        public static final int IS_RINGTONE = 0;
-
-        public static final int IS_NOTIFICATION = 0;
-
-        public static final int IS_ALARM = 0;
-
-        public static final int IS_MUSIC = 1;
-
-        public static final int IS_DRM = 0;
-
-        public static final int YEAR = 1992;
-
-        public static final int TRACK = 1;
-
-        public static final int DURATION = 340000;
-
-        public static final String COMPOSER = "Bruce Swedien";
-
-        public static final String ARTIST = "Michael Jackson";
-
-        public static final String ALBUM = "Dangerous";
-
-        public static final String TITLE = "Jam";
-
-        public static final int SIZE = 2737870;
-
-        public static final String MIME_TYPE = "audio/x-mpeg";
-
-        public static final String DISPLAY_NAME = "Jam -Michael Jackson";
-
-        public static final String INTERNAL_DATA =
-            "/data/data/com.android.cts.stub/files/Jam.mp3";
-
-        public static final String FILE_NAME = "Jam.mp3";
-
-        public static final String EXTERNAL_DATA = Environment.getExternalStorageDirectory() +
-                "/" + FILE_NAME;
-
-        public static final long DATE_MODIFIED = System.currentTimeMillis() / 1000;
-
-        public static final String GENRE = "POP";
-        @Override
-        public ContentValues getContentValues(boolean isInternal) {
-            ContentValues values = new ContentValues();
-            values.put(Media.DATA, isInternal ? INTERNAL_DATA : EXTERNAL_DATA);
-            values.put(Media.DATE_MODIFIED, DATE_MODIFIED);
-            values.put(Media.DISPLAY_NAME, DISPLAY_NAME);
-            values.put(Media.MIME_TYPE, MIME_TYPE);
-            values.put(Media.SIZE, SIZE);
-            values.put(Media.TITLE, TITLE);
-            values.put(Media.ALBUM, ALBUM);
-            values.put(Media.ARTIST, ARTIST);
-            values.put(Media.COMPOSER, COMPOSER);
-            values.put(Media.DURATION, DURATION);
-            values.put(Media.TRACK, TRACK);
-            values.put(Media.YEAR, YEAR);
-            values.put(Media.IS_MUSIC, IS_MUSIC);
-            values.put(Media.IS_ALARM, IS_ALARM);
-            values.put(Media.IS_NOTIFICATION, IS_NOTIFICATION);
-            values.put(Media.IS_RINGTONE, IS_RINGTONE);
-            values.put(Media.IS_DRM, IS_DRM);
-
-            return values;
-        }
-    }
-
-    public static class Audio2 extends MockAudioMediaInfo {
-        private Audio2() {
-        }
-
-        private static Audio2 sInstance = new Audio2();
-
-        public static Audio2 getInstance() {
-            return sInstance;
-        }
-
-        public static final int IS_RINGTONE = 1;
-
-        public static final int IS_NOTIFICATION = 0;
-
-        public static final int IS_ALARM = 0;
-
-        public static final int IS_MUSIC = 0;
-
-        public static final int IS_DRM = 0;
-
-        public static final int YEAR = 1992;
-
-        public static final int TRACK = 1001;
-
-        public static final int DURATION = 338000;
-
-        public static final String COMPOSER = "Bruce Swedien";
-
-        public static final String ARTIST =
-            "Michael Jackson - Live And Dangerous - National Stadium Bucharest";
-
-        public static final String ALBUM =
-            "Michael Jackson - Live And Dangerous - National Stadium Bucharest";
-
-        public static final String TITLE = "Jam";
-
-        public static final int SIZE = 2737321;
-
-        public static final String MIME_TYPE = "audio/x-mpeg";
-
-        public static final String DISPLAY_NAME = "Jam(Live)-Michael Jackson";
-
-        public static final String FILE_NAME = "Jam_live.mp3";
-
-        public static final String EXTERNAL_DATA =
-            Environment.getExternalStorageDirectory().getPath() + "/" + FILE_NAME;
-
-        public static final String INTERNAL_DATA =
-            "/data/data/com.android.cts.stub/files/Jam_live.mp3";
-
-
-
-        public static final long DATE_MODIFIED = System.currentTimeMillis();
-
-        @Override
-        public ContentValues getContentValues(boolean isInternal) {
-            ContentValues values = new ContentValues();
-            values.put(Media.DATA, isInternal ? INTERNAL_DATA : EXTERNAL_DATA);
-            values.put(Media.DATE_MODIFIED, DATE_MODIFIED);
-            values.put(Media.DISPLAY_NAME, DISPLAY_NAME);
-            values.put(Media.MIME_TYPE, MIME_TYPE);
-            values.put(Media.SIZE, SIZE);
-            values.put(Media.TITLE, TITLE);
-            values.put(Media.ALBUM, ALBUM);
-            values.put(Media.ARTIST, ARTIST);
-            values.put(Media.COMPOSER, COMPOSER);
-            values.put(Media.DURATION, DURATION);
-            values.put(Media.TRACK, TRACK);
-            values.put(Media.YEAR, YEAR);
-            values.put(Media.IS_MUSIC, IS_MUSIC);
-            values.put(Media.IS_ALARM, IS_ALARM);
-            values.put(Media.IS_NOTIFICATION, IS_NOTIFICATION);
-            values.put(Media.IS_RINGTONE, IS_RINGTONE);
-            values.put(Media.IS_DRM, IS_DRM);
-
-            return values;
-        }
-    }
-
-    public static class Audio3 extends Audio1 {
-        private Audio3() {
-        }
-
-        private static Audio3 sInstance = new Audio3();
-
-        public static Audio3 getInstance() {
-            return sInstance;
-        }
-
-        @Override
-        public ContentValues getContentValues(boolean isInternal) {
-            ContentValues values = super.getContentValues(isInternal);
-            values.put(Media.DATA, values.getAsString(Media.DATA) + "_3");
-            return values;
-        }
-    }
-
-    public static class Audio4 extends Audio1 {
-        private Audio4() {
-        }
-
-        private static Audio4 sInstance = new Audio4();
-
-        public static Audio4 getInstance() {
-            return sInstance;
-        }
-
-        @Override
-        public ContentValues getContentValues(boolean isInternal) {
-            ContentValues values = super.getContentValues(isInternal);
-            values.put(Media.DATA, values.getAsString(Media.DATA) + "_4");
-            return values;
-        }
-    }
-
-    public static class Audio5 extends Audio1 {
-        private Audio5() {
-        }
-
-        private static Audio5 sInstance = new Audio5();
-
-        public static Audio5 getInstance() {
-            return sInstance;
-        }
-
-        @Override
-        public ContentValues getContentValues(boolean isInternal) {
-            ContentValues values = super.getContentValues(isInternal);
-            values.put(Media.DATA, values.getAsString(Media.DATA) + "_5");
-            return values;
-        }
-    }
-
-    // These constants are not part of the public API
-    public static final String EXTERNAL_VOLUME_NAME = "external";
-    public static final String INTERNAL_VOLUME_NAME = "internal";
-}
diff --git a/tests/src/android/provider/cts/PhotoUtil.java b/tests/src/android/provider/cts/PhotoUtil.java
deleted file mode 100644
index 9c3047f..0000000
--- a/tests/src/android/provider/cts/PhotoUtil.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2012 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.provider.cts;
-
-import com.android.cts.stub.R;
-
-import android.content.Context;
-import android.os.cts.FileUtils;
-
-import java.io.InputStream;
-
-public class PhotoUtil {
-
-    public static byte[] getTestPhotoData(Context context) {
-        InputStream input = context.getResources().openRawResource(R.drawable.testimage);
-        return FileUtils.readInputStreamFully(input);
-    }
-}
diff --git a/tests/src/android/renderscript/cts/acos_f32.rs b/tests/src/android/renderscript/cts/acos_f32.rs
deleted file mode 100644
index 4bc948b..0000000
--- a/tests/src/android/renderscript/cts/acos_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void acos_f32_1 (const float* in, float* out) {
-    *out = acos(*in);
-}
-
-void acos_f32_2 (const float2* in, float2* out) {
-    *out = acos(*in);
-}
-
-void acos_f32_3 (const float3* in, float3* out) {
-    *out = acos(*in);
-}
-
-void acos_f32_4 (const float4* in , float4* out) {
-    *out = acos(*in);
-}
diff --git a/tests/src/android/renderscript/cts/acos_f32_relaxed.rs b/tests/src/android/renderscript/cts/acos_f32_relaxed.rs
deleted file mode 100644
index b553719..0000000
--- a/tests/src/android/renderscript/cts/acos_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "acos_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/acosh_f32.rs b/tests/src/android/renderscript/cts/acosh_f32.rs
deleted file mode 100644
index 8784b02..0000000
--- a/tests/src/android/renderscript/cts/acosh_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void acosh_f32_1 (const float* in, float* out) {
-    *out = acosh(*in);
-}
-
-void acosh_f32_2 (const float2* in, float2* out) {
-    *out = acosh(*in);
-}
-
-void acosh_f32_3 (const float3* in, float3* out) {
-    *out = acosh(*in);
-}
-
-void acosh_f32_4 (const float4* in , float4* out) {
-    *out = acosh(*in);
-}
diff --git a/tests/src/android/renderscript/cts/acosh_f32_relaxed.rs b/tests/src/android/renderscript/cts/acosh_f32_relaxed.rs
deleted file mode 100644
index b7995c1..0000000
--- a/tests/src/android/renderscript/cts/acosh_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "acosh_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/acospi_f32.rs b/tests/src/android/renderscript/cts/acospi_f32.rs
deleted file mode 100644
index 66d89eb..0000000
--- a/tests/src/android/renderscript/cts/acospi_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void acospi_f32_1 (const float* in, float* out) {
-    *out = acospi(*in);
-}
-
-void acospi_f32_2 (const float2* in, float2* out) {
-    *out = acospi(*in);
-}
-
-void acospi_f32_3 (const float3* in, float3* out) {
-    *out = acospi(*in);
-}
-
-void acospi_f32_4 (const float4* in, float4* out) {
-    *out = acospi(*in);
-}
diff --git a/tests/src/android/renderscript/cts/acospi_f32_relaxed.rs b/tests/src/android/renderscript/cts/acospi_f32_relaxed.rs
deleted file mode 100644
index 0d76365..0000000
--- a/tests/src/android/renderscript/cts/acospi_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "acospi_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/asin_f32.rs b/tests/src/android/renderscript/cts/asin_f32.rs
deleted file mode 100644
index 5f062f9..0000000
--- a/tests/src/android/renderscript/cts/asin_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void asin_f32_1 (const float* in, float* out) {
-    *out = asin(*in);
-}
-
-void asin_f32_2 (const float2* in, float2* out) {
-    *out = asin(*in);
-}
-
-void asin_f32_3 (const float3* in, float3* out) {
-    *out = asin(*in);
-}
-
-void asin_f32_4 (const float4* in , float4* out) {
-    *out = asin (*in) ;
-}
diff --git a/tests/src/android/renderscript/cts/asin_f32_relaxed.rs b/tests/src/android/renderscript/cts/asin_f32_relaxed.rs
deleted file mode 100644
index b5b3926..0000000
--- a/tests/src/android/renderscript/cts/asin_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "asin_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/asinh_f32.rs b/tests/src/android/renderscript/cts/asinh_f32.rs
deleted file mode 100644
index 82525074..0000000
--- a/tests/src/android/renderscript/cts/asinh_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void asinh_f32_1 (const float* in, float* out) {
-    *out = asinh(*in);
-}
-
-void asinh_f32_2 (const float2* in, float2* out) {
-    *out = asinh(*in);
-}
-
-void asinh_f32_3 (const float3* in, float3* out) {
-    *out = asinh(*in);
-}
-
-void asinh_f32_4 (const float4* in, float4* out) {
-    *out = asinh(*in);
-}
diff --git a/tests/src/android/renderscript/cts/asinh_f32_relaxed.rs b/tests/src/android/renderscript/cts/asinh_f32_relaxed.rs
deleted file mode 100644
index 02a7082..0000000
--- a/tests/src/android/renderscript/cts/asinh_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "asinh_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/asinpi_f32.rs b/tests/src/android/renderscript/cts/asinpi_f32.rs
deleted file mode 100644
index 66bf1d7..0000000
--- a/tests/src/android/renderscript/cts/asinpi_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void asinpi_f32_1 (const float* in, float* out) {
-    *out = asinpi(*in);
-}
-
-void asinpi_f32_2 (const float2* in, float2* out) {
-    *out = asinpi(*in);
-}
-
-void asinpi_f32_3 (const float3* in, float3* out) {
-    *out = asinpi(*in);
-}
-
-void asinpi_f32_4 (const float4* in, float4* out) {
-    *out = asinpi(*in);
-}
diff --git a/tests/src/android/renderscript/cts/asinpi_f32_relaxed.rs b/tests/src/android/renderscript/cts/asinpi_f32_relaxed.rs
deleted file mode 100644
index 924a5346..0000000
--- a/tests/src/android/renderscript/cts/asinpi_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "asinpi_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/atan2_f32.rs b/tests/src/android/renderscript/cts/atan2_f32.rs
deleted file mode 100644
index e1bab48..0000000
--- a/tests/src/android/renderscript/cts/atan2_f32.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-typedef struct atan2_f32_in {
-    float first;
-    float second;
-} input;
-
-void atan2_f32_1(const input* in, float* out){
-    *out = atan2(in->first, in->second);
-}
-
-typedef struct atan2_f32_2_in {
-    float2 first;
-    float2 second;
-} input2;
-
-void atan2_f32_2(const input2* in, float2* out){
-    *out = atan2(in->first, in->second);
-}
-
-typedef struct atan2_f32_3_in {
-    float3 first;
-    float3 second;
-} input3;
-
-void atan2_f32_3(const input3* in, float3* out){
-    *out = atan2(in->first, in->second);
-}
-
-typedef struct atan2_f32_4_in {
-    float4 first;
-    float4 second;
-} input4;
-
-void atan2_f32_4(const input4* in, float4* out){
-    *out = atan2(in->first, in->second);
-}
diff --git a/tests/src/android/renderscript/cts/atan2_f32_relaxed.rs b/tests/src/android/renderscript/cts/atan2_f32_relaxed.rs
deleted file mode 100644
index dd749fa..0000000
--- a/tests/src/android/renderscript/cts/atan2_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "atan2_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/atan2pi_f32.rs b/tests/src/android/renderscript/cts/atan2pi_f32.rs
deleted file mode 100644
index 2fe52d8..0000000
--- a/tests/src/android/renderscript/cts/atan2pi_f32.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-struct atan2pi_float_input {
-    float x;
-    float y;
-};
-
-void atan2pi_f32_1 (const struct atan2pi_float_input* in, float* out) {
-    *out = atan2pi(in->x, in->y);
-}
-
-struct atan2pi_float2_input {
-    float2 x;
-    float2 y;
-};
-
-void atan2pi_f32_2 (const struct atan2pi_float2_input* in, float2* out) {
-    *out = atan2pi(in->x, in->y);
-}
-
-struct atan2pi_float3_input {
-    float3 x;
-    float3 y;
-};
-
-void atan2pi_f32_3 (const struct atan2pi_float3_input* in, float3* out) {
-    *out = atan2pi(in->x, in->y);
-}
-
-struct atan2pi_float4_input {
-    float4 x;
-    float4 y;
-};
-
-void atan2pi_f32_4 (const struct atan2pi_float4_input* in, float4* out) {
-    *out = atan2pi(in->x, in->y);
-}
diff --git a/tests/src/android/renderscript/cts/atan2pi_f32_relaxed.rs b/tests/src/android/renderscript/cts/atan2pi_f32_relaxed.rs
deleted file mode 100644
index 0d4e8fb..0000000
--- a/tests/src/android/renderscript/cts/atan2pi_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "atan2pi_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/atan_f32.rs b/tests/src/android/renderscript/cts/atan_f32.rs
deleted file mode 100644
index 65a5ab5..0000000
--- a/tests/src/android/renderscript/cts/atan_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void atan_f32_1 (const float* in, float* out) {
-    *out = atan(*in);
-}
-
-void atan_f32_2 (const float2* in, float2* out) {
-    *out = atan(*in);
-}
-
-void atan_f32_3 (const float3* in, float3* out) {
-    *out = atan(*in);
-}
-
-void atan_f32_4 (const float4* in, float4* out) {
-    *out =atan(*in);
-}
diff --git a/tests/src/android/renderscript/cts/atan_f32_relaxed.rs b/tests/src/android/renderscript/cts/atan_f32_relaxed.rs
deleted file mode 100644
index e015aa8..0000000
--- a/tests/src/android/renderscript/cts/atan_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "atan_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/atanh_f32.rs b/tests/src/android/renderscript/cts/atanh_f32.rs
deleted file mode 100644
index 1f61e5e..0000000
--- a/tests/src/android/renderscript/cts/atanh_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void atanh_f32_1 (const float* in, float* out) {
-    *out = atanh(*in);
-}
-
-void atanh_f32_2 (const float2* in, float2* out) {
-    *out = atanh(*in);
-}
-
-void atanh_f32_3 (const float3* in, float3* out) {
-    *out = atanh(*in);
-}
-
-void atanh_f32_4 (const float4* in, float4* out) {
-    *out = atanh(*in);
-}
diff --git a/tests/src/android/renderscript/cts/atanh_f32_relaxed.rs b/tests/src/android/renderscript/cts/atanh_f32_relaxed.rs
deleted file mode 100644
index 2083e4d..0000000
--- a/tests/src/android/renderscript/cts/atanh_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "atanh_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/atanpi_f32.rs b/tests/src/android/renderscript/cts/atanpi_f32.rs
deleted file mode 100644
index 182a43c..0000000
--- a/tests/src/android/renderscript/cts/atanpi_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void atanpi_f32_1 (const float* in, float* out) {
-    *out = atanpi(*in);
-}
-
-void atanpi_f32_2 (const float2* in, float2* out) {
-    *out = atanpi(*in);
-}
-
-void atanpi_f32_3 (const float3* in, float3* out) {
-    *out = atanpi(*in);
-}
-
-void atanpi_f32_4 (const float4* in, float4* out) {
-    *out = atanpi(*in);
-}
diff --git a/tests/src/android/renderscript/cts/atanpi_f32_relaxed.rs b/tests/src/android/renderscript/cts/atanpi_f32_relaxed.rs
deleted file mode 100644
index fefe784..0000000
--- a/tests/src/android/renderscript/cts/atanpi_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "atanpi_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/cbrt_f32.rs b/tests/src/android/renderscript/cts/cbrt_f32.rs
deleted file mode 100644
index 273e8a4..0000000
--- a/tests/src/android/renderscript/cts/cbrt_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void cbrt_f32_1(const float *in, float *out) {
-    *out = cbrt(*in);
-}
-
-void cbrt_f32_2(const float2 *in, float2 *out) {
-    *out = cbrt(*in);
-}
-
-void cbrt_f32_3(const float3 *in, float3 *out) {
-    *out = cbrt(*in);
-}
-
-void cbrt_f32_4(const float4 *in, float4 *out) {
-    *out = cbrt(*in);
-}
diff --git a/tests/src/android/renderscript/cts/cbrt_f32_relaxed.rs b/tests/src/android/renderscript/cts/cbrt_f32_relaxed.rs
deleted file mode 100644
index 9b9e5a5..0000000
--- a/tests/src/android/renderscript/cts/cbrt_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "cbrt_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/ceil_f32.rs b/tests/src/android/renderscript/cts/ceil_f32.rs
deleted file mode 100644
index c0817e2..0000000
--- a/tests/src/android/renderscript/cts/ceil_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void ceil_f32_1(const float *in, float *out) {
-    *out = ceil(*in);
-}
-
-void ceil_f32_2(const float2 *in, float2 *out) {
-    *out = ceil(*in);
-}
-
-void ceil_f32_3(const float3 *in, float3 *out) {
-    *out = ceil(*in);
-}
-
-void ceil_f32_4(const float4 *in, float4 *out) {
-    *out = ceil(*in);
-}
diff --git a/tests/src/android/renderscript/cts/ceil_f32_relaxed.rs b/tests/src/android/renderscript/cts/ceil_f32_relaxed.rs
deleted file mode 100644
index 332ca6c..0000000
--- a/tests/src/android/renderscript/cts/ceil_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "ceil_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/clamp.rs b/tests/src/android/renderscript/cts/clamp.rs
deleted file mode 100644
index 28b00bd..0000000
--- a/tests/src/android/renderscript/cts/clamp.rs
+++ /dev/null
@@ -1,56 +0,0 @@
-#include "shared.rsh"
-
-static bool test_clamp_vector() {
-    bool failed = false;
-
-    float2 src2 = { 2.0f, 2.0f};
-    float2 min2 = { 0.5f, -3.0f};
-    float2 max2 = { 1.0f, 9.0f};
-
-    float2 res2 = clamp(src2, min2, max2);
-    _RS_ASSERT(res2.x == 1.0f);
-    _RS_ASSERT(res2.y == 2.0f);
-
-
-    float3 src3 = { 2.0f, 2.0f, 1.0f};
-    float3 min3 = { 0.5f, -3.0f, 3.0f};
-    float3 max3 = { 1.0f, 9.0f, 4.0f};
-
-    float3 res3 = clamp(src3, min3, max3);
-    _RS_ASSERT(res3.x == 1.0f);
-    _RS_ASSERT(res3.y == 2.0f);
-    _RS_ASSERT(res3.z == 3.0f);
-
-
-    float4 src4 = { 2.0f, 2.0f, 1.0f, 4.0f };
-    float4 min4 = { 0.5f, -3.0f, 3.0f, 4.0f };
-    float4 max4 = { 1.0f, 9.0f, 4.0f, 4.0f };
-
-    float4 res4 = clamp(src4, min4, max4);
-    _RS_ASSERT(res4.x == 1.0f);
-    _RS_ASSERT(res4.y == 2.0f);
-    _RS_ASSERT(res4.z == 3.0f);
-    _RS_ASSERT(res4.w == 4.0f);
-
-    if (failed) {
-        rsDebug("test_clamp_vector FAILED", 0);
-    }
-    else {
-        rsDebug("test_clamp_vector PASSED", 0);
-    }
-
-    return failed;
-}
-
-void clamp_test() {
-    bool failed = false;
-    failed |= test_clamp_vector();
-
-    if (failed) {
-        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
-    }
-    else {
-        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
-    }
-}
-
diff --git a/tests/src/android/renderscript/cts/clamp_relaxed.rs b/tests/src/android/renderscript/cts/clamp_relaxed.rs
deleted file mode 100644
index 71c65ae..0000000
--- a/tests/src/android/renderscript/cts/clamp_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "clamp.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/copysign_f32.rs b/tests/src/android/renderscript/cts/copysign_f32.rs
deleted file mode 100644
index b0b300d..0000000
--- a/tests/src/android/renderscript/cts/copysign_f32.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-struct copysign_f32_input {
-    float x;
-    float y;
-};
-
-void copysign_f32_1(const struct copysign_f32_input *in, float *out) {
-    *out = copysign(in->x, in->y);
-}
-
-struct copysign_f32_2_input {
-    float2 x;
-    float2 y;
-};
-
-void copysign_f32_2(const struct copysign_f32_2_input *in, float2 *out) {
-    *out = copysign(in->x, in->y);
-}
-
-struct copysign_f32_3_input {
-    float3 x;
-    float3 y;
-};
-
-void copysign_f32_3(const struct copysign_f32_3_input *in, float3 *out) {
-    *out = copysign(in->x, in->y);
-}
-
-struct copysign_f32_4_input {
-    float4 x;
-    float4 y;
-};
-
-void copysign_f32_4(const struct copysign_f32_4_input *in, float4 *out) {
-    *out = copysign(in->x, in->y);
-}
diff --git a/tests/src/android/renderscript/cts/copysign_f32_relaxed.rs b/tests/src/android/renderscript/cts/copysign_f32_relaxed.rs
deleted file mode 100644
index e7fe701..0000000
--- a/tests/src/android/renderscript/cts/copysign_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "copysign_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/cos_f32.rs b/tests/src/android/renderscript/cts/cos_f32.rs
deleted file mode 100644
index fd061dc..0000000
--- a/tests/src/android/renderscript/cts/cos_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void cos_f32_1(const float *in, float *out) {
-    *out = cos(*in);
-}
-
-void cos_f32_2(const float2 *in, float2 *out) {
-    *out = cos(*in);
-}
-
-void cos_f32_3(const float3 *in, float3 *out) {
-    *out = cos(*in);
-}
-
-void cos_f32_4(const float4 *in, float4 *out) {
-    *out = cos(*in);
-}
diff --git a/tests/src/android/renderscript/cts/cos_f32_relaxed.rs b/tests/src/android/renderscript/cts/cos_f32_relaxed.rs
deleted file mode 100644
index ceb51d2..0000000
--- a/tests/src/android/renderscript/cts/cos_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "cos_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/cosh_f32.rs b/tests/src/android/renderscript/cts/cosh_f32.rs
deleted file mode 100644
index 0f2ab0f..0000000
--- a/tests/src/android/renderscript/cts/cosh_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void cosh_f32_1(const float *in, float *out) {
-    *out = cosh(*in);
-}
-
-void cosh_f32_2(const float2 *in, float2 *out) {
-    *out = cosh(*in);
-}
-
-void cosh_f32_3(const float3 *in, float3 *out) {
-    *out = cosh(*in);
-}
-
-void cosh_f32_4(const float4 *in, float4 *out) {
-    *out = cosh(*in);
-}
diff --git a/tests/src/android/renderscript/cts/cosh_f32_relaxed.rs b/tests/src/android/renderscript/cts/cosh_f32_relaxed.rs
deleted file mode 100644
index 7f6a79b..0000000
--- a/tests/src/android/renderscript/cts/cosh_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "cosh_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/cross_f32.rs b/tests/src/android/renderscript/cts/cross_f32.rs
deleted file mode 100644
index e996e5f..0000000
--- a/tests/src/android/renderscript/cts/cross_f32.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-typedef struct _cross_f32_3_struct {
-    float3 low;
-    float3 high;
-} cross_f32_3_struct;
-
-void cross_f32_3(const cross_f32_3_struct *in, float3 *out) {
-    *out = cross(in->low, in->high);
-}
-
-typedef struct _cross_f32_4_struct {
-    float4 low;
-    float4 high;
-} cross_f32_4_struct;
-
-void cross_f32_4(const cross_f32_4_struct *in, float4 *out) {
-    *out = cross(in->low, in->high);
-}
diff --git a/tests/src/android/renderscript/cts/cross_f32_relaxed.rs b/tests/src/android/renderscript/cts/cross_f32_relaxed.rs
deleted file mode 100644
index d9fbfed..0000000
--- a/tests/src/android/renderscript/cts/cross_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "cross_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/degrees_f32.rs b/tests/src/android/renderscript/cts/degrees_f32.rs
deleted file mode 100644
index e571246..0000000
--- a/tests/src/android/renderscript/cts/degrees_f32.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void degrees_f32_1(const float* in, float* out) {
-    *out = degrees(*in);
-}
-
-void degrees_f32_2(const float2* in, float2* out) {
-    *out = degrees (*in);
-
-}
-
-void degrees_f32_3(const float3* in, float3* out) {
-    *out = degrees(*in);
-
-}
-
-void degrees_f32_4(const float4* in, float4* out) {
-    *out = degrees(*in);
-
-}
diff --git a/tests/src/android/renderscript/cts/degrees_f32_relaxed.rs b/tests/src/android/renderscript/cts/degrees_f32_relaxed.rs
deleted file mode 100644
index bc603a5..0000000
--- a/tests/src/android/renderscript/cts/degrees_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "degrees_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/exp10_f32.rs b/tests/src/android/renderscript/cts/exp10_f32.rs
deleted file mode 100644
index 67f5c26..0000000
--- a/tests/src/android/renderscript/cts/exp10_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void exp10_f32_1(const float *in, float *out) {
-    *out = exp10(*in);
-}
-
-void exp10_f32_2(const float2 *in, float2 *out) {
-    *out = exp10(*in);
-}
-
-void exp10_f32_3(const float3 *in, float3 *out) {
-    *out = exp10(*in);
-}
-
-void exp10_f32_4(const float4 *in, float4 *out) {
-    *out = exp10(*in);
-}
diff --git a/tests/src/android/renderscript/cts/exp10_f32_relaxed.rs b/tests/src/android/renderscript/cts/exp10_f32_relaxed.rs
deleted file mode 100644
index 6e4e007..0000000
--- a/tests/src/android/renderscript/cts/exp10_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "exp10_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/exp2_f32.rs b/tests/src/android/renderscript/cts/exp2_f32.rs
deleted file mode 100644
index 9095bf3..0000000
--- a/tests/src/android/renderscript/cts/exp2_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void exp2_f32_1(const float *in, float *out) {
-    *out = exp2(*in);
-}
-
-void exp2_f32_2(const float2 *in, float2 *out) {
-    *out = exp2(*in);
-}
-
-void exp2_f32_3(const float3 *in, float3 *out) {
-    *out = exp2(*in);
-}
-
-void exp2_f32_4(const float4 *in, float4 *out) {
-    *out = exp2(*in);
-}
diff --git a/tests/src/android/renderscript/cts/exp2_f32_relaxed.rs b/tests/src/android/renderscript/cts/exp2_f32_relaxed.rs
deleted file mode 100644
index 676b30a..0000000
--- a/tests/src/android/renderscript/cts/exp2_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "exp2_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/exp_f32.rs b/tests/src/android/renderscript/cts/exp_f32.rs
deleted file mode 100644
index 036c490..0000000
--- a/tests/src/android/renderscript/cts/exp_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void exp_f32_1(const float *in, float *out) {
-    *out = exp(*in);
-}
-
-void exp_f32_2(const float2 *in, float2 *out) {
-    *out = exp(*in);
-}
-
-void exp_f32_3(const float3 *in, float3 *out) {
-    *out = exp(*in);
-}
-
-void exp_f32_4(const float4 *in, float4 *out) {
-    *out = exp(*in);
-}
diff --git a/tests/src/android/renderscript/cts/exp_f32_relaxed.rs b/tests/src/android/renderscript/cts/exp_f32_relaxed.rs
deleted file mode 100644
index dc4b3d0..0000000
--- a/tests/src/android/renderscript/cts/exp_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "exp_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/expm1_f32.rs b/tests/src/android/renderscript/cts/expm1_f32.rs
deleted file mode 100644
index 1950131..0000000
--- a/tests/src/android/renderscript/cts/expm1_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void expm1_f32_1(const float *in, float *out) {
-    *out = expm1(*in);
-}
-
-void expm1_f32_2(const float2 *in, float2 *out) {
-    *out = expm1(*in);
-}
-
-void expm1_f32_3(const float3 *in, float3 *out) {
-    *out = expm1(*in);
-}
-
-void expm1_f32_4(const float4 *in, float4 *out) {
-    *out = expm1(*in);
-}
diff --git a/tests/src/android/renderscript/cts/expm1_f32_relaxed.rs b/tests/src/android/renderscript/cts/expm1_f32_relaxed.rs
deleted file mode 100644
index 5a3c40e..0000000
--- a/tests/src/android/renderscript/cts/expm1_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "expm1_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/fabs_f32.rs b/tests/src/android/renderscript/cts/fabs_f32.rs
deleted file mode 100644
index 1567e4d..0000000
--- a/tests/src/android/renderscript/cts/fabs_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void fabs_f32_1(const float *in, float *out) {
-    *out = fabs(*in);
-}
-
-void fabs_f32_2(const float2 *in, float2 *out) {
-    *out = fabs(*in);
-}
-
-void fabs_f32_3(const float3 *in, float3 *out) {
-    *out = fabs(*in);
-}
-
-void fabs_f32_4(const float4 *in, float4 *out) {
-    *out = fabs(*in);
-}
diff --git a/tests/src/android/renderscript/cts/fabs_f32_relaxed.rs b/tests/src/android/renderscript/cts/fabs_f32_relaxed.rs
deleted file mode 100644
index e0add35..0000000
--- a/tests/src/android/renderscript/cts/fabs_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "fabs_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/fdim_f32.rs b/tests/src/android/renderscript/cts/fdim_f32.rs
deleted file mode 100644
index e2c5fb1..0000000
--- a/tests/src/android/renderscript/cts/fdim_f32.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-struct fdim_f32_input {
-    float x;
-    float y;
-};
-
-void fdim_f32_1(const struct fdim_f32_input *in, float *out) {
-    *out = fdim(in->x, in->y);
-}
-
-struct fdim_f32_2_input {
-    float2 x;
-    float2 y;
-};
-
-void fdim_f32_2(const struct fdim_f32_2_input *in, float2 *out) {
-    *out = fdim(in->x, in->y);
-}
-
-struct fdim_f32_3_input {
-    float3 x;
-    float3 y;
-};
-
-void fdim_f32_3(const struct fdim_f32_3_input *in, float3 *out) {
-    *out = fdim(in->x, in->y);
-}
-
-struct fdim_f32_4_input {
-    float4 x;
-    float4 y;
-};
-
-void fdim_f32_4(const struct fdim_f32_4_input *in, float4 *out) {
-    *out = fdim(in->x, in->y);
-}
diff --git a/tests/src/android/renderscript/cts/fdim_f32_relaxed.rs b/tests/src/android/renderscript/cts/fdim_f32_relaxed.rs
deleted file mode 100644
index 18c8cf0..0000000
--- a/tests/src/android/renderscript/cts/fdim_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "fdim_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/floor_f32.rs b/tests/src/android/renderscript/cts/floor_f32.rs
deleted file mode 100644
index 2300dab..0000000
--- a/tests/src/android/renderscript/cts/floor_f32.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-void floor_f32_1(const float *in, float *out) {
-    *out = floor(*in);
-}
-
-void floor_f32_2(const float2 *in, float2 *out) {
-    *out = floor(*in);
-}
-
-void floor_f32_3(const float3 *in, float3 *out) {
-    *out = floor(*in);
-}
-
-void floor_f32_4(const float4 *in, float4 *out) {
-    *out = floor(*in);
-}
diff --git a/tests/src/android/renderscript/cts/floor_f32_relaxed.rs b/tests/src/android/renderscript/cts/floor_f32_relaxed.rs
deleted file mode 100644
index d6bef83..0000000
--- a/tests/src/android/renderscript/cts/floor_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "floor_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/fma_f32.rs b/tests/src/android/renderscript/cts/fma_f32.rs
deleted file mode 100644
index 36257a5..0000000
--- a/tests/src/android/renderscript/cts/fma_f32.rs
+++ /dev/null
@@ -1,42 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-typedef struct Floats {
-    float fa;
-    float fb;
-    float fc;
-} Floats;
-
-void fma_f32_1(const Floats *in, float *out) {
-    *out = fma(in->fa, in->fb, in->fc);
-}
-
-typedef struct Floats2 {
-    float2 fa;
-    float2 fb;
-    float2 fc;
-} Floats2;
-
-void fma_f32_2(const Floats2 *in, float2 *out) {
-    *out = fma(in->fa, in->fb, in->fc);
-}
-
-typedef struct Floats3 {
-    float3 fa;
-    float3 fb;
-    float3 fc;
-} Floats3;
-
-void fma_f32_3(const Floats3 *in, float3 *out) {
-    *out = fma(in->fa, in->fb, in->fc);
-}
-
-typedef struct Floats4 {
-    float4 fa;
-    float4 fb;
-    float4 fc;
-} Floats4;
-
-void fma_f32_4(const Floats4 *in, float4 *out) {
-    *out = fma(in->fa, in->fb, in->fc);
-}
diff --git a/tests/src/android/renderscript/cts/fma_f32_relaxed.rs b/tests/src/android/renderscript/cts/fma_f32_relaxed.rs
deleted file mode 100644
index 77f92df..0000000
--- a/tests/src/android/renderscript/cts/fma_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "fma_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/fmax_f32.rs b/tests/src/android/renderscript/cts/fmax_f32.rs
deleted file mode 100644
index e03f258..0000000
--- a/tests/src/android/renderscript/cts/fmax_f32.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-typedef struct fmax_f32_in {
-    float first;
-    float second;
-} input1;
-
-void fmax_f32_1(const input1* in, float* out){
-    *out = fmax(in->first, in->second);
-}
-
-typedef struct fmax_f32_2_in {
-    float2 first;
-    float2 second;
-} input2;
-
-void fmax_f32_2(const input2* in, float2* out){
-    *out = fmax(in->first, in->second);
-}
-
-typedef struct fmax_f32_3_in {
-    float3 first;
-    float3 second;
-} input3;
-
-void fmax_f32_3(const input3* in, float3* out){
-    *out = fmax(in->first, in->second);
-}
-
-typedef struct fmax_f32_4_in {
-    float4 first;
-    float4 second;
-} input4;
-
-void fmax_f32_4(const input4* in, float4* out){
-    *out = fmax(in->first, in->second);
-}
diff --git a/tests/src/android/renderscript/cts/fmax_f32_relaxed.rs b/tests/src/android/renderscript/cts/fmax_f32_relaxed.rs
deleted file mode 100644
index 23beccf..0000000
--- a/tests/src/android/renderscript/cts/fmax_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "fmax_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/fmin_f32.rs b/tests/src/android/renderscript/cts/fmin_f32.rs
deleted file mode 100644
index 49033f0..0000000
--- a/tests/src/android/renderscript/cts/fmin_f32.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-typedef struct fmin_f32_in {
-    float first;
-    float second;
-} input1;
-
-void fmin_f32_1(const input1* in, float* out){
-    *out = fmin(in->first, in->second);
-}
-
-typedef struct fmin_f32_2_in {
-    float2 first;
-    float2 second;
-} input2;
-
-void fmin_f32_2(const input2* in, float2* out){
-    *out = fmin(in->first, in->second);
-}
-
-typedef struct fmin_f32_3_in {
-    float3 first;
-    float3 second;
-} input3;
-
-void fmin_f32_3(const input3* in, float3* out){
-    *out = fmin(in->first, in->second);
-}
-
-typedef struct fmin_f32_4_in {
-    float4 first;
-    float4 second;
-} input4;
-
-void fmin_f32_4(const input4* in, float4* out){
-    *out = fmin(in->first, in->second);
-}
diff --git a/tests/src/android/renderscript/cts/fmin_f32_relaxed.rs b/tests/src/android/renderscript/cts/fmin_f32_relaxed.rs
deleted file mode 100644
index 8be4f13..0000000
--- a/tests/src/android/renderscript/cts/fmin_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "fmin_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/fmod_f32.rs b/tests/src/android/renderscript/cts/fmod_f32.rs
deleted file mode 100644
index ca8b282..0000000
--- a/tests/src/android/renderscript/cts/fmod_f32.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-struct fmod_input_f32 {
-    float param1;
-    float param2;
-};
-
-void fmod_f32_1(const struct fmod_input_f32 *in, float *out) {
-    *out = fmod(in->param1, in->param2);
-}
-
-struct fmod_input_f32_2 {
-    float2 param1;
-    float2 param2;
-};
-
-void fmod_f32_2(const struct fmod_input_f32_2 *in, float2 *out) {
-    *out = fmod(in->param1, in->param2);
-}
-
-struct fmod_input_f32_3 {
-    float3 param1;
-    float3 param2;
-};
-
-void fmod_f32_3(const struct fmod_input_f32_3 *in, float3 *out) {
-    *out = fmod(in->param1, in->param2);
-}
-
-struct fmod_input_f32_4 {
-    float4 param1;
-    float4 param2;
-};
-
-void fmod_f32_4(const struct fmod_input_f32_4 *in, float4 *out) {
-    *out = fmod(in->param1, in->param2);
-}
diff --git a/tests/src/android/renderscript/cts/fmod_f32_relaxed.rs b/tests/src/android/renderscript/cts/fmod_f32_relaxed.rs
deleted file mode 100644
index 7a02136..0000000
--- a/tests/src/android/renderscript/cts/fmod_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "fmod_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/foreach.rs b/tests/src/android/renderscript/cts/foreach.rs
deleted file mode 100644
index 8747961..0000000
--- a/tests/src/android/renderscript/cts/foreach.rs
+++ /dev/null
@@ -1,77 +0,0 @@
-#include "shared.rsh"
-
-int *a;
-rs_allocation aRaw;
-int dimX;
-int dimY;
-static bool failed = false;
-
-void root(int *out, uint32_t x, uint32_t y) {
-    *out = x + y * dimX;
-}
-
-void foo(const int *in, int *out, uint32_t x, uint32_t y) {
-    _RS_ASSERT(*in == (x + y * dimX));
-    *out = 99 + x + y * dimX;
-    _RS_ASSERT(*out == (99 + x + y * dimX));
-}
-
-static bool test_root_output() {
-    bool failed = false;
-    int i, j;
-
-    for (j = 0; j < dimY; j++) {
-        for (i = 0; i < dimX; i++) {
-            int v = rsGetElementAt_int(aRaw, i, j);
-            _RS_ASSERT(v == (i + j * dimX));
-        }
-    }
-
-    if (failed) {
-        rsDebug("test_root_output FAILED", 0);
-    }
-    else {
-        rsDebug("test_root_output PASSED", 0);
-    }
-
-    return failed;
-}
-
-static bool test_foo_output() {
-    bool failed = false;
-    int i, j;
-
-    for (j = 0; j < dimY; j++) {
-        for (i = 0; i < dimX; i++) {
-            int v = rsGetElementAt_int(aRaw, i, j);
-            _RS_ASSERT(v == (99 + i + j * dimX));
-        }
-    }
-
-    if (failed) {
-        rsDebug("test_foo_output FAILED", 0);
-    }
-    else {
-        rsDebug("test_foo_output PASSED", 0);
-    }
-
-    return failed;
-}
-
-void verify_root() {
-    failed |= test_root_output();
-}
-
-void verify_foo() {
-    failed |= test_foo_output();
-}
-
-void foreach_test() {
-    if (failed) {
-        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
-    }
-    else {
-        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
-    }
-}
-
diff --git a/tests/src/android/renderscript/cts/hypot_f32.rs b/tests/src/android/renderscript/cts/hypot_f32.rs
deleted file mode 100644
index 4f9159c..0000000
--- a/tests/src/android/renderscript/cts/hypot_f32.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-typedef struct hypot_f32_in {
-    float x;
-    float y;
-} hypot_input_f32;
-
-void hypot_f32_1(const hypot_input_f32 *in, float *out) {
-    *out = hypot(in->x, in->y);
-}
-
-typedef struct hypot_f32_2_in {
-    float2 x;
-    float2 y;
-} hypot_input_f32_2;
-
-void hypot_f32_2(const hypot_input_f32_2 *in, float2 *out) {
-    *out = hypot(in->x, in->y);
-}
-
-typedef struct hypot_f32_3_in {
-    float3 x;
-    float3 y;
-} hypot_input_f32_3;
-
-void hypot_f32_3(const hypot_input_f32_3 *in, float3 *out) {
-    *out = hypot(in->x, in->y);
-}
-
-typedef struct hypot_f32_4_in {
-    float4 x;
-    float4 y;
-} hypot_input_f32_4;
-
-void hypot_f32_4(const hypot_input_f32_4 *in, float4 *out) {
-    *out = hypot(in->x, in->y);
-}
diff --git a/tests/src/android/renderscript/cts/hypot_f32_relaxed.rs b/tests/src/android/renderscript/cts/hypot_f32_relaxed.rs
deleted file mode 100644
index 7414788..0000000
--- a/tests/src/android/renderscript/cts/hypot_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "hypot_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/intrinsic_colormatrix.rs b/tests/src/android/renderscript/cts/intrinsic_colormatrix.rs
deleted file mode 100644
index 30b40c4..0000000
--- a/tests/src/android/renderscript/cts/intrinsic_colormatrix.rs
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2013 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"
-
-
-void reference(rs_matrix4x4 m, float4 add, rs_allocation in, rs_allocation out) {
-    uint32_t w = rsAllocationGetDimX(in);
-    uint32_t h = rsAllocationGetDimY(in);
-
-    rs_element ein = rsAllocationGetElement(in);
-    rs_element eout = rsAllocationGetElement(out);
-    rs_data_type dtin = rsElementGetDataType(ein);
-    rs_data_type dtout = rsElementGetDataType(eout);
-    uint32_t vsin = rsElementGetVectorSize(ein);
-    uint32_t vsout = rsElementGetVectorSize(eout);
-
-    for (uint32_t y = 0; y < h; y++) {
-        for (uint32_t x = 0; x < w; x++) {
-            float4 pin = 0.f;
-
-            if (dtin == RS_TYPE_FLOAT_32) {
-                switch(vsin) {
-                case 4:
-                    pin.xyzw = rsGetElementAt_float4(in, x, y);
-                    break;
-                case 3:
-                    pin.xyz = rsGetElementAt_float3(in, x, y);
-                    break;
-                case 2:
-                    pin.xy = rsGetElementAt_float2(in, x, y);
-                    break;
-                case 1:
-                    pin.x = rsGetElementAt_float(in, x, y);
-                    break;
-                }
-            }
-
-            if (dtin == RS_TYPE_UNSIGNED_8) {
-                uchar4 u = 0;
-                switch(vsin) {
-                case 4:
-                    u.xyzw = rsGetElementAt_uchar4(in, x, y);
-                    break;
-                case 3:
-                    u.xyz = rsGetElementAt_uchar3(in, x, y);
-                    break;
-                case 2:
-                    u.xy = rsGetElementAt_uchar2(in, x, y);
-                    break;
-                case 1:
-                    u.x = rsGetElementAt_uchar(in, x, y);
-                    break;
-                }
-                pin = rsUnpackColor8888(u);
-            }
-
-            pin = rsMatrixMultiply(&m, pin);
-            pin += add;
-
-            if (dtout == RS_TYPE_FLOAT_32) {
-                switch(vsout) {
-                case 4:
-                    rsSetElementAt_float4(out, pin, x, y);
-                    break;
-                case 3:
-                    rsSetElementAt_float3(out, pin.xyz, x, y);
-                    break;
-                case 2:
-                    rsSetElementAt_float2(out, pin.xy, x, y);
-                    break;
-                case 1:
-                    rsSetElementAt_float(out, pin.x, x, y);
-                    break;
-                }
-            }
-
-            if (dtout == RS_TYPE_UNSIGNED_8) {
-                uchar4 u = rsPackColorTo8888(pin);
-                switch(vsout) {
-                case 4:
-                    rsSetElementAt_uchar4(out, u, x, y);
-                    break;
-                case 3:
-                    rsSetElementAt_uchar3(out, u.xyz, x, y);
-                    break;
-                case 2:
-                    rsSetElementAt_uchar2(out, u.xy, x, y);
-                    break;
-                case 1:
-                    rsSetElementAt_uchar(out, u.x, x, y);
-                    break;
-                }
-            }
-
-        }
-    }
-}
-
-
diff --git a/tests/src/android/renderscript/cts/log10_f32.rs b/tests/src/android/renderscript/cts/log10_f32.rs
deleted file mode 100644
index dbb5150..0000000
--- a/tests/src/android/renderscript/cts/log10_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void log10_f32_1 (const float* in, float* out) {
-    *out = log10(*in);
-}
-
-void log10_f32_2 (const float2* in, float2* out) {
-    *out = log10(*in);
-}
-
-void log10_f32_3 (const float3* in, float3* out) {
-    *out = log10(*in);
-}
-
-void log10_f32_4 (const float4* in, float4* out) {
-    *out = log10(*in);
-}
diff --git a/tests/src/android/renderscript/cts/log10_f32_relaxed.rs b/tests/src/android/renderscript/cts/log10_f32_relaxed.rs
deleted file mode 100644
index bedfa6d..0000000
--- a/tests/src/android/renderscript/cts/log10_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "log10_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/log1p_f32.rs b/tests/src/android/renderscript/cts/log1p_f32.rs
deleted file mode 100644
index 3c725fe..0000000
--- a/tests/src/android/renderscript/cts/log1p_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void log1p_f32_1 (const float* in, float* out) {
-    *out = log1p(*in);
-}
-
-void log1p_f32_2 (const float2* in, float2* out) {
-    *out = log1p(*in);
-}
-
-void log1p_f32_3 (const float3* in, float3* out) {
-    *out = log1p(*in);
-}
-
-void log1p_f32_4 (const float4* in, float4* out) {
-    *out = log1p(*in);
-}
diff --git a/tests/src/android/renderscript/cts/log1p_f32_relaxed.rs b/tests/src/android/renderscript/cts/log1p_f32_relaxed.rs
deleted file mode 100644
index c3aed11..0000000
--- a/tests/src/android/renderscript/cts/log1p_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "log1p_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/log2_f32.rs b/tests/src/android/renderscript/cts/log2_f32.rs
deleted file mode 100644
index 2ed2b98..0000000
--- a/tests/src/android/renderscript/cts/log2_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void log2_f32_1 (const float* in, float* out) {
-    *out = log2(*in);
-}
-
-void log2_f32_2 (const float2* in, float2* out) {
-    *out = log2(*in);
-}
-
-void log2_f32_3 (const float3* in, float3* out) {
-    *out = log2(*in);
-}
-
-void log2_f32_4 (const float4* in, float4* out) {
-    *out = log2(*in);
-}
diff --git a/tests/src/android/renderscript/cts/log2_f32_relaxed.rs b/tests/src/android/renderscript/cts/log2_f32_relaxed.rs
deleted file mode 100644
index 7e0883a..0000000
--- a/tests/src/android/renderscript/cts/log2_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "log2_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/log_f32.rs b/tests/src/android/renderscript/cts/log_f32.rs
deleted file mode 100644
index 14052a2..0000000
--- a/tests/src/android/renderscript/cts/log_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void log_f32_1 (const float* in, float* out) {
-    *out = log(*in);
-}
-
-void log_f32_2 (const float2* in, float2* out) {
-    *out = log(*in);
-}
-
-void log_f32_3 (const float3* in, float3* out) {
-    *out = log(*in);
-}
-
-void log_f32_4 (const float4* in, float4* out) {
-    *out = log(*in);
-}
diff --git a/tests/src/android/renderscript/cts/log_f32_relaxed.rs b/tests/src/android/renderscript/cts/log_f32_relaxed.rs
deleted file mode 100644
index d66d3c9..0000000
--- a/tests/src/android/renderscript/cts/log_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "log_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/logb_f32.rs b/tests/src/android/renderscript/cts/logb_f32.rs
deleted file mode 100644
index 1b3acfa..0000000
--- a/tests/src/android/renderscript/cts/logb_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void logb_f32_1 (const float* in, float* out) {
-    *out = logb(*in);
-}
-
-void logb_f32_2 (const float2* in, float2* out) {
-    *out = logb(*in);
-}
-
-void logb_f32_3 (const float3* in, float3* out) {
-    *out = logb(*in);
-}
-
-void logb_f32_4 (const float4* in, float4* out) {
-    *out = logb(*in);
-}
diff --git a/tests/src/android/renderscript/cts/logb_f32_relaxed.rs b/tests/src/android/renderscript/cts/logb_f32_relaxed.rs
deleted file mode 100644
index 9b906dc..0000000
--- a/tests/src/android/renderscript/cts/logb_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "logb_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/mad_f32.rs b/tests/src/android/renderscript/cts/mad_f32.rs
deleted file mode 100644
index fc5081b..0000000
--- a/tests/src/android/renderscript/cts/mad_f32.rs
+++ /dev/null
@@ -1,42 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-struct mad_input_f32 {
-    float x;
-    float y;
-    float z;
-};
-
-void mad_f32_1(const struct mad_input_f32 *param, float *out) {
-    *out = mad(param->x, param->y, param->z);
-}
-
-struct mad_input_f32_2 {
-    float2 x;
-    float2 y;
-    float2 z;
-};
-
-void mad_f32_2(const struct mad_input_f32_2 *param, float2 *out) {
-    *out = mad(param->x, param->y, param->z);
-}
-
-struct mad_input_f32_3 {
-    float3 x;
-    float3 y;
-    float3 z;
-};
-
-void mad_f32_3(const struct mad_input_f32_3 *param, float3 *out) {
-    *out = mad(param->x, param->y, param->z);
-}
-
-struct mad_input_f32_4 {
-    float4 x;
-    float4 y;
-    float4 z;
-};
-
-void mad_f32_4(const struct mad_input_f32_4 *param, float4 *out) {
-    *out = mad(param->x, param->y, param->z);
-}
diff --git a/tests/src/android/renderscript/cts/mad_f32_relaxed.rs b/tests/src/android/renderscript/cts/mad_f32_relaxed.rs
deleted file mode 100644
index 36d8306..0000000
--- a/tests/src/android/renderscript/cts/mad_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "mad_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/nextafter_f32.rs b/tests/src/android/renderscript/cts/nextafter_f32.rs
deleted file mode 100644
index 04ce73a4..0000000
--- a/tests/src/android/renderscript/cts/nextafter_f32.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-typedef struct InputData {
-    float a;
-    float b;
-} InputData;
-
-void nextafter_f32_1(const InputData *in, float *out) {
-    *out = nextafter (in->a, in->b);
-}
-
-typedef struct InputData_2 {
-    float2 a;
-    float2 b;
-} InputData_2;
-
-void nextafter_f32_2(const InputData_2 *in, float2 *out) {
-    *out = nextafter (in->a, in->b);
-}
-
-typedef struct InputData_3 {
-    float3 a;
-    float3 b;
-} InputData_3;
-
-void nextafter_f32_3(const InputData_3 *in, float3 *out) {
-    *out = nextafter (in->a, in->b);
-}
-
-typedef struct InputData_4 {
-    float4 a;
-    float4 b;
-} InputData_4;
-
-void nextafter_f32_4(const InputData_4 *in, float4 *out) {
-    *out = nextafter (in->a, in->b);
-}
diff --git a/tests/src/android/renderscript/cts/nextafter_f32_relaxed.rs b/tests/src/android/renderscript/cts/nextafter_f32_relaxed.rs
deleted file mode 100644
index 5c6edd5..0000000
--- a/tests/src/android/renderscript/cts/nextafter_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "nextafter_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/pow_f32.rs b/tests/src/android/renderscript/cts/pow_f32.rs
deleted file mode 100644
index 426d4b1..0000000
--- a/tests/src/android/renderscript/cts/pow_f32.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-typedef struct PowInputData {
-    float base;
-    float expo;
-} PowInputData;
-
-void pow_f32_1(const PowInputData *in, float *out) {
-    *out = pow(in->base, in->expo);
-}
-
-typedef struct PowInputData_2 {
-    float2 base;
-    float2 expo;
-} PowInputData_2;
-
-void pow_f32_2(const PowInputData_2 *in, float2 *out) {
-    *out = pow(in->base, in->expo);
-}
-
-typedef struct PowInputData_3 {
-    float3 base;
-    float3 expo;
-} PowInputData_3;
-
-void pow_f32_3(const PowInputData_3 *in, float3 *out) {
-    *out = pow(in->base, in->expo);
-}
-
-typedef struct PowInputData_4 {
-    float4 base;
-    float4 expo;
-} PowInputData_4;
-
-void pow_f32_4(const PowInputData_4 *in, float4 *out) {
-    *out = pow(in->base, in->expo);
-}
diff --git a/tests/src/android/renderscript/cts/pow_f32_relaxed.rs b/tests/src/android/renderscript/cts/pow_f32_relaxed.rs
deleted file mode 100644
index 5da7048..0000000
--- a/tests/src/android/renderscript/cts/pow_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "pow_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/pown_f32.rs b/tests/src/android/renderscript/cts/pown_f32.rs
deleted file mode 100644
index fa066d0..0000000
--- a/tests/src/android/renderscript/cts/pown_f32.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-rs_allocation n1;
-
-void pown_f32_1(const float *in, float *out, uint32_t x) {
-    *out = pown(*in, *(int *)rsGetElementAt(n1,x));
-}
-
-rs_allocation n2;
-
-void pown_f32_2(const float2 *in, float2 *out, uint32_t x) {
-    *out = pown(*in, *(int2 *)rsGetElementAt(n2,x));
-}
-
-rs_allocation n3;
-
-void pown_f32_3(const float3 *in, float3 *out, uint32_t x) {
-    *out = pown(*in, *(int3 *)rsGetElementAt(n3,x));
-}
-
-rs_allocation n4;
-
-void pown_f32_4(const float4 *in, float4 *out, uint32_t x) {
-    *out = pown(*in, *(int4 *)rsGetElementAt(n4,x));
-}
diff --git a/tests/src/android/renderscript/cts/pown_f32_relaxed.rs b/tests/src/android/renderscript/cts/pown_f32_relaxed.rs
deleted file mode 100644
index bdc4b47..0000000
--- a/tests/src/android/renderscript/cts/pown_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "pown_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/powr_f32.rs b/tests/src/android/renderscript/cts/powr_f32.rs
deleted file mode 100644
index 6eb36b0..0000000
--- a/tests/src/android/renderscript/cts/powr_f32.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-typedef struct PowInputData {
-    float base;
-    float expo;
-} PowInputData;
-
-void powr_f32_1(const PowInputData *in, float *out) {
-    *out = powr(in->base, in->expo);
-}
-
-typedef struct PowInputData_2 {
-    float2 base;
-    float2 expo;
-} PowInputData_2;
-
-void powr_f32_2(const PowInputData_2 *in, float2 *out) {
-    *out = powr(in->base, in->expo);
-}
-
-typedef struct PowInputData_3 {
-    float3 base;
-    float3 expo;
-} PowInputData_3;
-
-void powr_f32_3(const PowInputData_3 *in, float3 *out) {
-    *out = powr(in->base, in->expo);
-}
-
-typedef struct PowInputData_4 {
-    float4 base;
-    float4 expo;
-} PowInputData_4;
-
-void powr_f32_4(const PowInputData_4 *in, float4 *out) {
-    *out = powr(in->base, in->expo);
-}
diff --git a/tests/src/android/renderscript/cts/powr_f32_relaxed.rs b/tests/src/android/renderscript/cts/powr_f32_relaxed.rs
deleted file mode 100644
index b8690af..0000000
--- a/tests/src/android/renderscript/cts/powr_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "powr_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/radians_f32.rs b/tests/src/android/renderscript/cts/radians_f32.rs
deleted file mode 100644
index 1aa743e..0000000
--- a/tests/src/android/renderscript/cts/radians_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void radians_f32_1(const float* in, float* out) {
-    *out = radians (*in);
-}
-
-void radians_f32_2(const float2* in, float2* out) {
-    *out = radians(*in);
-}
-
-void radians_f32_3(const float3* in, float3* out) {
-    *out = radians(*in);
-}
-
-void radians_f32_4(const float4* in, float4* out) {
-    *out = radians(*in);
-}
diff --git a/tests/src/android/renderscript/cts/radians_f32_relaxed.rs b/tests/src/android/renderscript/cts/radians_f32_relaxed.rs
deleted file mode 100644
index 4ab3070..0000000
--- a/tests/src/android/renderscript/cts/radians_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "radians_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/remainder_f32.rs b/tests/src/android/renderscript/cts/remainder_f32.rs
deleted file mode 100644
index d08a034..0000000
--- a/tests/src/android/renderscript/cts/remainder_f32.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-struct remainder_f32 {
-    float num;
-    float den;
-};
-
-void remainder_f32_1 (const struct remainder_f32* in, float* out) {
-    *out = remainder(in->num, in->den);
-}
-
-struct remainder_f32_2 {
-    float2 num;
-    float2 den;
-};
-
-void remainder_f32_2 (const struct remainder_f32_2* in, float2* out) {
-    *out = remainder(in->num, in->den);
-}
-
-struct remainder_f32_3 {
-    float3 num;
-    float3 den;
-};
-
-void remainder_f32_3 (const struct remainder_f32_3* in, float3* out) {
-    *out = remainder(in->num, in->den);
-}
-
-struct remainder_f32_4 {
-    float4 num;
-    float4 den;
-};
-
-void remainder_f32_4 (const struct remainder_f32_4* in, float4* out) {
-    *out = remainder(in->num, in->den);
-}
diff --git a/tests/src/android/renderscript/cts/remainder_f32_relaxed.rs b/tests/src/android/renderscript/cts/remainder_f32_relaxed.rs
deleted file mode 100644
index d546e50..0000000
--- a/tests/src/android/renderscript/cts/remainder_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "remainder_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/rint_f32.rs b/tests/src/android/renderscript/cts/rint_f32.rs
deleted file mode 100644
index 46ef8b1..0000000
--- a/tests/src/android/renderscript/cts/rint_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void rint_f32_1 (const float* in, float* out) {
-    *out = rint(*in);
-}
-
-void rint_f32_2 (const float2* in, float2* out) {
-    *out = rint(*in);
-}
-
-void rint_f32_3 (const float3* in, float3* out) {
-    *out = rint(*in);
-}
-
-void rint_f32_4 (const float4* in, float4* out) {
-    *out = rint(*in);
-}
diff --git a/tests/src/android/renderscript/cts/rint_f32_relaxed.rs b/tests/src/android/renderscript/cts/rint_f32_relaxed.rs
deleted file mode 100644
index e9b4950..0000000
--- a/tests/src/android/renderscript/cts/rint_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "rint_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/rootn_f32.rs b/tests/src/android/renderscript/cts/rootn_f32.rs
deleted file mode 100644
index 1c60ea9..0000000
--- a/tests/src/android/renderscript/cts/rootn_f32.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-rs_allocation n1;
-
-void rootn_f32_1(const float *in, float *out, uint32_t x) {
-    *out = rootn(*in, *(int *)rsGetElementAt(n1,x));
-}
-
-rs_allocation n2;
-
-void rootn_f32_2(const float2 *in, float2 *out, uint32_t x) {
-    *out = rootn(*in, *(int2 *)rsGetElementAt(n2,x));
-}
-
-rs_allocation n3;
-
-void rootn_f32_3(const float3 *in, float3 *out, uint32_t x) {
-    *out = rootn(*in, *(int3 *)rsGetElementAt(n3,x));
-}
-
-rs_allocation n4;
-
-void rootn_f32_4(const float4 *in, float4 *out, uint32_t x) {
-    *out = rootn(*in, *(int4 *)rsGetElementAt(n4,x));
-}
diff --git a/tests/src/android/renderscript/cts/rootn_f32_relaxed.rs b/tests/src/android/renderscript/cts/rootn_f32_relaxed.rs
deleted file mode 100644
index f6509ae..0000000
--- a/tests/src/android/renderscript/cts/rootn_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "rootn_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/round_f32.rs b/tests/src/android/renderscript/cts/round_f32.rs
deleted file mode 100644
index 60b5e8d..0000000
--- a/tests/src/android/renderscript/cts/round_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void round_f32_1 (const float* in, float* out) {
-    *out = round(*in);
-}
-
-void round_f32_2 (const float2* in , float2* out) {
-    *out = round(*in);
-}
-
-void round_f32_3 (const float3* in, float3* out) {
-    *out = round(*in);
-}
-
-void round_f32_4 (const float4* in , float4* out) {
-    *out = round(*in);
-}
diff --git a/tests/src/android/renderscript/cts/round_f32_relaxed.rs b/tests/src/android/renderscript/cts/round_f32_relaxed.rs
deleted file mode 100644
index 026515e..0000000
--- a/tests/src/android/renderscript/cts/round_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "round_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/rsqrt_f32.rs b/tests/src/android/renderscript/cts/rsqrt_f32.rs
deleted file mode 100644
index 1e8f5a2..0000000
--- a/tests/src/android/renderscript/cts/rsqrt_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void Rsqrt_f32_1 (const float* in, float* out) {
-    *out = rsqrt(*in);
-}
-
-void Rsqrt_f32_2 (const float2* in, float2* out) {
-    *out = rsqrt(*in);
-}
-
-void Rsqrt_f32_3 (const float3* in, float3* out) {
-    *out = rsqrt(*in);
-}
-
-void Rsqrt_f32_4 (const float4* in, float4* out) {
-    *out = rsqrt(*in);
-}
diff --git a/tests/src/android/renderscript/cts/rsqrt_f32_relaxed.rs b/tests/src/android/renderscript/cts/rsqrt_f32_relaxed.rs
deleted file mode 100644
index 1d7c08b..0000000
--- a/tests/src/android/renderscript/cts/rsqrt_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "rsqrt_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/sample.rs b/tests/src/android/renderscript/cts/sample.rs
deleted file mode 100644
index 7a8d5bb..0000000
--- a/tests/src/android/renderscript/cts/sample.rs
+++ /dev/null
@@ -1,205 +0,0 @@
-#include "shared.rsh"
-
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-rs_sampler gNearest;
-rs_sampler gLinear;
-rs_sampler gMipNearest;
-rs_sampler gMipLinear;
-
-uint8_t *gAllocPtr;
-
-static uchar4 lod0Color = {255, 255, 0, 0};
-static uchar4 lod1Color = {255, 0, 255, 0};
-static uchar4 lod2Color = {0, 255, 255, 0};
-static uchar4 lod3Color = {255, 255, 255, 0};
-
-// Allocation has been bound to gAllocPtr
-void init_RGBA(rs_allocation a) {
-    // Fill base level with one color, mips with something else
-    uchar4 *allocPtr = (uchar4*)gAllocPtr;
-    uint32_t dimX = rsAllocationGetDimX(a);
-    uint32_t dimY = rsAllocationGetDimY(a);
-    uint32_t minSize = 1;
-    dimX = max(dimX, minSize);
-    dimY = max(dimY, minSize);
-
-    uint32_t numPixels = dimX * dimY;
-    for (uint32_t i = 0; i < numPixels; i ++) {
-        (*allocPtr++) = lod0Color;
-    }
-    dimX = max(dimX >> 1, minSize);
-    dimY = max(dimY >> 1, minSize);
-    numPixels = dimX * dimY;
-    for (uint32_t i = 0; i < numPixels; i ++) {
-        (*allocPtr++) = lod1Color;
-    }
-    dimX = max(dimX >> 1, minSize);
-    dimY = max(dimY >> 1, minSize);
-    numPixels = dimX * dimY;
-    for (uint32_t i = 0; i < numPixels; i ++) {
-        (*allocPtr++) = lod2Color;
-    }
-    dimX = max(dimX >> 1, minSize);
-    dimY = max(dimY >> 1, minSize);
-    numPixels = dimX * dimY;
-    for (uint32_t i = 0; i < numPixels; i ++) {
-        (*allocPtr++) = lod3Color;
-    }
-}
-
-static bool compare(float4 expected, float4 value) {
-    float allowedDelta = 10.0f;
-    float4 diff = fabs(expected - value);
-    if (diff.x > allowedDelta || diff.y > allowedDelta ||
-        diff.z > allowedDelta || diff.w > allowedDelta) {
-        return false;
-    }
-    return true;
-}
-
-static bool sub_test_RGBA_1D(rs_allocation alloc1D, float location, float lod,
-                          float4 expected0, float4 expected1, float4 expected2, float4 expected3) {
-    bool failed = false;
-    float4 result = rsSample(alloc1D, gNearest, location, lod);
-    _RS_ASSERT(compare(expected0, result));
-
-    result = rsSample(alloc1D, gLinear, location, lod);
-    _RS_ASSERT(compare(expected1, result));
-
-    result = rsSample(alloc1D, gMipNearest, location, lod);
-    _RS_ASSERT(compare(expected2, result));
-
-    result = rsSample(alloc1D, gMipLinear, location, lod);
-    _RS_ASSERT(compare(expected3, result));
-    return !failed;
-}
-
-static bool sub_test_RGBA_2D(rs_allocation alloc2D, float2 location, float lod,
-                          float4 expected0, float4 expected1, float4 expected2, float4 expected3) {
-    bool failed = false;
-    float4 result = rsSample(alloc2D, gNearest, location, lod);
-    _RS_ASSERT(compare(expected0, result));
-
-    result = rsSample(alloc2D, gLinear, location, lod);
-    _RS_ASSERT(compare(expected1, result));
-
-    result = rsSample(alloc2D, gMipNearest, location, lod);
-    _RS_ASSERT(compare(expected2, result));
-
-    result = rsSample(alloc2D, gMipLinear, location, lod);
-    _RS_ASSERT(compare(expected3, result));
-    return !failed;
-}
-
-void test_RGBA(rs_allocation alloc1D, rs_allocation alloc2D) {
-    bool failed = false;
-    float4 result;
-
-    float4 fLOD0 = rsUnpackColor8888(lod0Color);
-    float4 fLOD1 = rsUnpackColor8888(lod1Color);
-    float4 fLOD2 = rsUnpackColor8888(lod2Color);
-    float4 fLOD3 = rsUnpackColor8888(lod3Color);
-
-    float4 fLOD04 = fLOD0*0.6f + fLOD1*0.4f;
-    float4 fLOD06 = fLOD0*0.4f + fLOD1*0.6f;
-
-    // Test for proper LOD sampling behaviour
-    uint32_t numSamples = 5;
-    for (uint32_t i = 0; i < numSamples; i ++) {
-        float location = (float)i/(float)(numSamples - 1);
-
-        // No lod specified, should be lod 0
-        result = rsSample(alloc1D, gNearest, location);
-        _RS_ASSERT(compare(fLOD0, result));
-
-        result = rsSample(alloc1D, gLinear, location);
-        _RS_ASSERT(compare(fLOD0, result));
-
-        result = rsSample(alloc1D, gMipNearest, location);
-        _RS_ASSERT(compare(fLOD0, result));
-
-        result = rsSample(alloc1D, gMipLinear, location);
-        _RS_ASSERT(compare(fLOD0, result));
-
-        // Mid lod test
-        float lod = 0.4f;
-        _RS_ASSERT(sub_test_RGBA_1D(alloc1D, location, lod, fLOD0, fLOD0, fLOD0, fLOD04));
-
-        lod = 0.6f;
-        _RS_ASSERT(sub_test_RGBA_1D(alloc1D, location, lod, fLOD0, fLOD0, fLOD1, fLOD06));
-
-        // Base lod sample
-        lod = 0.0f;
-        _RS_ASSERT(sub_test_RGBA_1D(alloc1D, location, lod, fLOD0, fLOD0, fLOD0, fLOD0));
-
-        // lod 1 test
-        lod = 1.0f;
-        _RS_ASSERT(sub_test_RGBA_1D(alloc1D, location, lod, fLOD0, fLOD0, fLOD1, fLOD1));
-
-        // lod 2 test
-        lod = 2.0f;
-        _RS_ASSERT(sub_test_RGBA_1D(alloc1D, location, lod, fLOD0, fLOD0, fLOD2, fLOD2));
-
-        // lod 3 test
-        lod = 3.0f;
-        _RS_ASSERT(sub_test_RGBA_1D(alloc1D, location, lod, fLOD0, fLOD0, fLOD3, fLOD3));
-
-        // lod 4 test, but only have 3 lods
-        lod = 4.0f;
-        _RS_ASSERT(sub_test_RGBA_1D(alloc1D, location, lod, fLOD0, fLOD0, fLOD3, fLOD3));
-
-        // 2D case
-        float2 f2Location;
-        f2Location.x = location;
-        f2Location.y = location;
-        // No lod specified, should be lod 0
-        result = rsSample(alloc2D, gNearest, f2Location);
-        _RS_ASSERT(compare(fLOD0, result));
-
-        result = rsSample(alloc2D, gLinear, f2Location);
-        _RS_ASSERT(compare(fLOD0, result));
-
-        result = rsSample(alloc2D, gMipNearest, f2Location);
-        _RS_ASSERT(compare(fLOD0, result));
-
-        result = rsSample(alloc2D, gMipLinear, f2Location);
-        _RS_ASSERT(compare(fLOD0, result));
-
-        // Mid lod test
-        lod = 0.4f;
-        _RS_ASSERT(sub_test_RGBA_2D(alloc2D, f2Location, lod, fLOD0, fLOD0, fLOD0, fLOD04));
-
-        lod = 0.6f;
-        _RS_ASSERT(sub_test_RGBA_2D(alloc2D, f2Location, lod, fLOD0, fLOD0, fLOD1, fLOD06));
-
-        // Base lod sample
-        lod = 0.0f;
-        _RS_ASSERT(sub_test_RGBA_2D(alloc2D, f2Location, lod, fLOD0, fLOD0, fLOD0, fLOD0));
-
-        // lod 1 test
-        lod = 1.0f;
-        _RS_ASSERT(sub_test_RGBA_2D(alloc2D, f2Location, lod, fLOD0, fLOD0, fLOD1, fLOD1));
-
-        // lod 2 test
-        lod = 2.0f;
-        _RS_ASSERT(sub_test_RGBA_2D(alloc2D, f2Location, lod, fLOD0, fLOD0, fLOD2, fLOD2));
-
-        // lod 2 test
-        lod = 3.0f;
-        _RS_ASSERT(sub_test_RGBA_2D(alloc2D, f2Location, lod, fLOD0, fLOD0, fLOD3, fLOD3));
-
-        // lod 4 test, but only have 3 lods
-        lod = 4.0f;
-        _RS_ASSERT(sub_test_RGBA_2D(alloc2D, f2Location, lod, fLOD0, fLOD0, fLOD3, fLOD3));
-    }
-
-    if (failed) {
-        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
-    }
-    else {
-        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
-    }
-}
-
diff --git a/tests/src/android/renderscript/cts/sign_f32.rs b/tests/src/android/renderscript/cts/sign_f32.rs
deleted file mode 100644
index f9edb908..0000000
--- a/tests/src/android/renderscript/cts/sign_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void sign_f32_1(const float *in, float *out) {
-    *out = sign (*in);
-}
-
-void sign_f32_2(const float2 *in, float2 *out) {
-    *out = sign (*in);
-}
-
-void sign_f32_3(const float3 *in, float3 *out) {
-    *out = sign (*in);
-}
-
-void sign_f32_4(const float4 *in, float4 *out) {
-    *out = sign (*in);
-}
diff --git a/tests/src/android/renderscript/cts/sign_f32_relaxed.rs b/tests/src/android/renderscript/cts/sign_f32_relaxed.rs
deleted file mode 100644
index 2ea41e2..0000000
--- a/tests/src/android/renderscript/cts/sign_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "sign_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/sin_f32.rs b/tests/src/android/renderscript/cts/sin_f32.rs
deleted file mode 100644
index 91652bb..0000000
--- a/tests/src/android/renderscript/cts/sin_f32.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-void sin_f32_1(const float *in, float *out) {
-    *out = sin(*in);
-}
-
-void sin_f32_2(const float2 *in, float2 *out) {
-    *out = sin(*in);
-}
-
-void sin_f32_3(const float3 *in, float3 *out) {
-    *out = sin(*in);
-}
-
-void sin_f32_4(const float4 *in, float4 *out) {
-    *out = sin(*in);
-}
diff --git a/tests/src/android/renderscript/cts/sin_f32_relaxed.rs b/tests/src/android/renderscript/cts/sin_f32_relaxed.rs
deleted file mode 100644
index 1ebf69e..0000000
--- a/tests/src/android/renderscript/cts/sin_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "sin_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/sinh_f32.rs b/tests/src/android/renderscript/cts/sinh_f32.rs
deleted file mode 100644
index b785399..0000000
--- a/tests/src/android/renderscript/cts/sinh_f32.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-void sinh_f32_1(const float *in, float *out) {
-    *out = sinh(*in);
-}
-
-void sinh_f32_2(const float2 *in, float2 *out) {
-    *out = sinh(*in);
-}
-
-void sinh_f32_3(const float3 *in, float3 *out) {
-    *out = sinh(*in);
-}
-
-void sinh_f32_4(const float4 *in, float4 *out) {
-    *out = sinh(*in);
-}
diff --git a/tests/src/android/renderscript/cts/sinh_f32_relaxed.rs b/tests/src/android/renderscript/cts/sinh_f32_relaxed.rs
deleted file mode 100644
index ba1d5c7..0000000
--- a/tests/src/android/renderscript/cts/sinh_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "sinh_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/sqrt_f32.rs b/tests/src/android/renderscript/cts/sqrt_f32.rs
deleted file mode 100644
index 253f1c0..0000000
--- a/tests/src/android/renderscript/cts/sqrt_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void sqrt_f32_1 (const float* in, float* out) {
-    *out = sqrt(*in);
-}
-
-void sqrt_f32_2 (const float2* in, float2* out) {
-    *out = sqrt(*in);
-}
-
-void sqrt_f32_3 (const float3* in, float3* out) {
-    *out = sqrt(*in);
-}
-
-void sqrt_f32_4 (const float4* in, float4* out) {
-    *out = sqrt(*in);
-}
diff --git a/tests/src/android/renderscript/cts/sqrt_f32_relaxed.rs b/tests/src/android/renderscript/cts/sqrt_f32_relaxed.rs
deleted file mode 100644
index 460ea63..0000000
--- a/tests/src/android/renderscript/cts/sqrt_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "sqrt_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/step_f32.rs b/tests/src/android/renderscript/cts/step_f32.rs
deleted file mode 100644
index d2261b3..0000000
--- a/tests/src/android/renderscript/cts/step_f32.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-struct step_input {
-    float x;
-    float y;
-};
-
-void step_f32_1(const struct step_input *in, float *out) {
-    *out = step(in->x, in->y);
-}
-
-struct step_2_input {
-    float2 x;
-    float2 y;
-};
-
-void step_f32_2(const struct step_2_input *in, float2 *out) {
-    *out = step(in->x, in->y);
-}
-
-struct step_3_input {
-    float3 x;
-    float3 y;
-};
-
-void step_f32_3(const struct step_3_input *in, float3 *out) {
-    *out = step(in->x, in->y);
-}
-
-struct step_4_input {
-    float4 x;
-    float4 y;
-};
-
-void step_f32_4(const struct step_4_input *in, float4 *out) {
-    *out = step(in->x, in->y);
-}
diff --git a/tests/src/android/renderscript/cts/step_f32_relaxed.rs b/tests/src/android/renderscript/cts/step_f32_relaxed.rs
deleted file mode 100644
index c59b548..0000000
--- a/tests/src/android/renderscript/cts/step_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "step_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/tan_f32.rs b/tests/src/android/renderscript/cts/tan_f32.rs
deleted file mode 100644
index 35ee971..0000000
--- a/tests/src/android/renderscript/cts/tan_f32.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-void tan_f32_1(const float *in, float *out) {
-    *out = tan(*in);
-}
-
-void tan_f32_2(const float2 *in, float2 *out) {
-    *out = tan(*in);
-}
-
-void tan_f32_3(const float3 *in, float3 *out) {
-    *out = tan(*in);
-}
-
-void tan_f32_4(const float4 *in, float4 *out) {
-    *out = tan(*in);
-}
diff --git a/tests/src/android/renderscript/cts/tan_f32_relaxed.rs b/tests/src/android/renderscript/cts/tan_f32_relaxed.rs
deleted file mode 100644
index adf98f0..0000000
--- a/tests/src/android/renderscript/cts/tan_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "tan_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/tanh_f32.rs b/tests/src/android/renderscript/cts/tanh_f32.rs
deleted file mode 100644
index 2b0782e..0000000
--- a/tests/src/android/renderscript/cts/tanh_f32.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-void tanh_f32_1(const float *in, float *out) {
-    *out = tanh(*in);
-}
-
-void tanh_f32_2(const float2 *in, float2 *out) {
-    *out = tanh(*in);
-}
-
-void tanh_f32_3(const float3 *in, float3 *out) {
-    *out = tanh(*in);
-}
-
-void tanh_f32_4(const float4 *in, float4 *out) {
-    *out = tanh(*in);
-}
diff --git a/tests/src/android/renderscript/cts/tanh_f32_relaxed.rs b/tests/src/android/renderscript/cts/tanh_f32_relaxed.rs
deleted file mode 100644
index 2d7463b..0000000
--- a/tests/src/android/renderscript/cts/tanh_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "tanh_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/renderscript/cts/trunc_f32.rs b/tests/src/android/renderscript/cts/trunc_f32.rs
deleted file mode 100644
index a464086..0000000
--- a/tests/src/android/renderscript/cts/trunc_f32.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-void trunc_f32_1 (const float* in, float* out) {
-    *out = trunc(*in);
-}
-
-void trunc_f32_2 (const float2* in, float2* out) {
-    *out = trunc(*in);
-}
-
-void trunc_f32_3 (const float3* in, float3* out) {
-    *out = trunc(*in);
-}
-
-void trunc_f32_4 (const float4* in, float4* out) {
-    *out = trunc(*in);
-}
diff --git a/tests/src/android/renderscript/cts/trunc_f32_relaxed.rs b/tests/src/android/renderscript/cts/trunc_f32_relaxed.rs
deleted file mode 100644
index f55c8b3..0000000
--- a/tests/src/android/renderscript/cts/trunc_f32_relaxed.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "trunc_f32.rs"
-#pragma rs_fp_relaxed
diff --git a/tests/src/android/rsg/cts/graphics_runner.rs b/tests/src/android/rsg/cts/graphics_runner.rs
deleted file mode 100644
index 18e1f76..0000000
--- a/tests/src/android/rsg/cts/graphics_runner.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-// 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.
-
-#include "shared.rsh"
-#include "rs_graphics.rsh"
-
-#include "structs.rsh"
-
-static void drawQuad() {
-    float startX = 0, startY = 0;
-    float width = 4, height = 4;
-    rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
-                         startX, startY + height, 0, 0, 1,
-                         startX + width, startY + height, 0, 1, 1,
-                         startX + width, startY, 0, 1, 0);
-}
-
-void testProgramVertex(rs_program_vertex pv) {
-    rsDebug("Set Program Vertex, drew quad", 0);
-    rsgBindProgramVertex(pv);
-    drawQuad();
-}
-
-void testProgramFragment(rs_program_fragment pf) {
-    rsDebug("Set Program Fragment, drew quad", 0);
-    rsgBindProgramFragment(pf);
-    drawQuad();
-}
-
-// Just draw a quad with previously setup state
-int root(void) {
-    rsDebug("Running script", 0);
-    return 0;
-}
diff --git a/tests/src/android/rsg/cts/shared.rsh b/tests/src/android/rsg/cts/shared.rsh
deleted file mode 100644
index f33b708..0000000
--- a/tests/src/android/rsg/cts/shared.rsh
+++ /dev/null
@@ -1,27 +0,0 @@
-#pragma version(1)
-#pragma rs java_package_name(android.renderscriptgraphics.cts)
-
-static int64_t g_time;
-
-static void start(void) {
-    g_time = rsUptimeMillis();
-}
-
-static float end(void) {
-    int64_t t = rsUptimeMillis() - g_time;
-    return ((float)t) / 1000.f;
-}
-
-#define _RS_ASSERT(b) \
-do { \
-    if (!(b)) { \
-        failed = true; \
-        rsDebug(#b " FAILED", 0); \
-    } \
-\
-} while (0)
-
-/* These constants must match those in UnitTest.java */
-static const int RS_MSG_TEST_PASSED = 100;
-static const int RS_MSG_TEST_FAILED = 101;
-
diff --git a/tests/src/android/rsg/cts/structs.rsh b/tests/src/android/rsg/cts/structs.rsh
deleted file mode 100755
index e7d2efd..0000000
--- a/tests/src/android/rsg/cts/structs.rsh
+++ /dev/null
@@ -1,56 +0,0 @@
-// 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.
-
-typedef struct ConstMatrix {
-    rs_matrix4x4 MATRIX;
-} ConstMatrix_s;
-ConstMatrix_s *c1;
-
-typedef struct ConstComplex {
-    rs_matrix4x4 MATRIX;
-    rs_matrix4x4 EXTRA;
-    float extra1;
-    float2 extra2;
-    float3 extra3;
-    float4 extra4;
-} ConstComplex_s;
-ConstComplex_s *c2;
-
-typedef struct ConstExtra {
-    rs_matrix4x4 EXTRA;
-    float extra1;
-    float2 extra2;
-    float3 extra3;
-    float4 extra4;
-} ConstExtra_s;
-ConstExtra_s *c3;
-
-typedef struct AllVectorTypes {
-    char2 b2;
-    char3 b3;
-    char4 b4;
-
-    short2 s2;
-    short3 s3;
-    short4 s4;
-
-    int2 i2;
-    int3 i3;
-    int4 i4;
-
-    float2 f2;
-    float3 f3;
-    float4 f4;
-} AllVectorTypes_s;
-AllVectorTypes_s *avt;
diff --git a/tests/src/android/rsg/cts/stub_activity.rs b/tests/src/android/rsg/cts/stub_activity.rs
deleted file mode 100644
index f5efce6..0000000
--- a/tests/src/android/rsg/cts/stub_activity.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-// 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.
-
-#pragma version(1)
-
-// Tell which java package name the reflected files should belong to
-#pragma rs java_package_name(android.renderscriptgraphics.cts)
-
-// Built-in header with graphics API's
-#include "rs_graphics.rsh"
-
-int root(void) {
-
-    // Clear the background color
-    rsgClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-    // Tell the runtime what the font color should be
-    rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
-    // Introuduce ourselves to the world
-    rsgDrawText("Hello World!", 50, 50);
-
-    // Return value tells RS roughly how often to redraw
-    // in this case 20 ms
-    return 20;
-}
diff --git a/tests/src/android/text/EmojiStubActivity.java b/tests/src/android/text/EmojiStubActivity.java
deleted file mode 100644
index 8d09250..0000000
--- a/tests/src/android/text/EmojiStubActivity.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2013 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.text.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.webkit.WebView;
-import android.webkit.cts.NullWebViewUtils;
-
-public class EmojiStubActivity extends Activity {
-    private WebView mWebView;
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        try {
-            super.onCreate(savedInstanceState);
-            setContentView(R.layout.webview_layout);
-            mWebView = (WebView) findViewById(R.id.web_page);
-        } catch (Exception e) {
-            NullWebViewUtils.determineIfWebViewAvailable(this, e);
-        }
-    }
-
-    public WebView getWebView() {
-        return mWebView;
-    }
-
-    @Override
-    public void onDestroy() {
-        if (mWebView != null) {
-            mWebView.destroy();
-        }
-        super.onDestroy();
-    }
-}
diff --git a/tests/src/android/text/method/cts/KeyListenerStubActivity.java b/tests/src/android/text/method/cts/KeyListenerStubActivity.java
deleted file mode 100644
index 149ad87..0000000
--- a/tests/src/android/text/method/cts/KeyListenerStubActivity.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2009 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.text.method.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.os.SystemClock;
-import android.text.method.BaseKeyListener;
-import android.text.method.DateKeyListener;
-import android.text.method.DateTimeKeyListener;
-import android.text.method.DigitsKeyListener;
-import android.text.method.MultiTapKeyListener;
-import android.text.method.NumberKeyListener;
-import android.text.method.QwertyKeyListener;
-import android.text.method.TextKeyListener;
-import android.text.method.TimeKeyListener;
-import android.util.Log;
-
-/**
- * This Activity is used for testing:
- * {@link DigitsKeyListener}
- * {@link BaseKeyListener}
- * {@link MultiTapKeyListener}
- * {@link NumberKeyListener}
- * {@link QwertyKeyListener}
- * {@link TextKeyListener}
- * {@link DateKeyListener}
- * {@link DateTimeKeyListener}
- * {@link TimeKeyListener}
- *
- * @see DigitsKeyListener
- * @see BaseKeyListener
- * @see MultiTapKeyListener
- * @see NumberKeyListener
- * @see QwertyKeyListener
- * @see TextKeyListener
- * @see DateKeyListener
- * @see DateTimeKeyListener
- * @see TimeKeyListener
- */
-
-public class KeyListenerStubActivity extends Activity {
-    private boolean mHasWindowFocus = false;
-    private Object mHasWindowFocusLock = new Object();
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.keylistener_layout);
-    }
-
-    @Override
-    public void onWindowFocusChanged(boolean hasFocus) {
-        super.onWindowFocusChanged(hasFocus);
-        if (!hasFocus) {
-            Log.w("KeyListenerStubActivity", "KeyListenerStubActivity lost window focus");
-        }
-        synchronized(mHasWindowFocusLock) {
-            mHasWindowFocus = hasFocus;
-            mHasWindowFocusLock.notify();
-        }
-    }
-
-    /**
-     * Blocks the calling thread until the {@link KeyListenerStubActivity} has window focus or the
-     * specified duration (in milliseconds) has passed.
-     */
-    public boolean waitForWindowFocus(long durationMillis) {
-        long elapsedMillis = SystemClock.elapsedRealtime();
-        synchronized(mHasWindowFocusLock) {
-            mHasWindowFocus = hasWindowFocus();
-            while (!mHasWindowFocus && durationMillis > 0) {
-                long newElapsedMillis = SystemClock.elapsedRealtime();
-                durationMillis -= (newElapsedMillis - elapsedMillis);
-                elapsedMillis = newElapsedMillis;
-                if (durationMillis > 0) {
-                    try {
-                        mHasWindowFocusLock.wait(durationMillis);
-                    } catch (InterruptedException e) {
-                    }
-                }
-            }
-            return mHasWindowFocus;
-        }
-    }
-}
diff --git a/tests/src/android/text/method/cts/StubActivity.java b/tests/src/android/text/method/cts/StubActivity.java
deleted file mode 100644
index f3dad52..0000000
--- a/tests/src/android/text/method/cts/StubActivity.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2009 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.text.method.cts;
-
-import android.app.Activity;
-import android.text.method.ArrowKeyMovementMethod;
-import android.text.method.LinkMovementMethod;
-import android.text.method.ScrollingMovementMethod;
-
-/**
- * This Activity is used for testing:
- * {@link LinkMovementMethod}
- * {@link ArrowKeyMovementMethod}
- * {@link ScrollingMovementMethod}
- *
- * The content view will be set in the test cases.
- *
- * @see LinkMovementMethodTest
- * @see ArrowKeyMovementMethodTest
- * @see ScrollingMovementMethodTest
- */
-public class StubActivity extends Activity {
-}
diff --git a/tests/src/android/text/style/cts/MockURLSpanTestActivity.java b/tests/src/android/text/style/cts/MockURLSpanTestActivity.java
deleted file mode 100644
index 1edb3e0..0000000
--- a/tests/src/android/text/style/cts/MockURLSpanTestActivity.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2009 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.text.style.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-/**
- * A Mock application for {@link URLSpan} test.
- */
-public class MockURLSpanTestActivity extends Activity {
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.urlspan_layout);
-    }
-}
diff --git a/tests/src/android/text/style/cts/URLSpanStubActivity.java b/tests/src/android/text/style/cts/URLSpanStubActivity.java
deleted file mode 100644
index a09a83e..0000000
--- a/tests/src/android/text/style/cts/URLSpanStubActivity.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2008 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.text.style.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-/**
- * A minimal application for {@link URLSpan} test.
- */
-public class URLSpanStubActivity extends Activity {
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.urlspan_layout);
-    }
-}
diff --git a/tests/src/android/view/animation/cts/AnimationTestStubActivity.java b/tests/src/android/view/animation/cts/AnimationTestStubActivity.java
deleted file mode 100644
index 68d0da3..0000000
--- a/tests/src/android/view/animation/cts/AnimationTestStubActivity.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2008 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.view.animation.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-public class AnimationTestStubActivity extends Activity {
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.anim_layout);
-    }
-}
diff --git a/tests/src/android/view/animation/cts/GridLayoutAnimStubActivity.java b/tests/src/android/view/animation/cts/GridLayoutAnimStubActivity.java
deleted file mode 100644
index 7fb79c3..0000000
--- a/tests/src/android/view/animation/cts/GridLayoutAnimStubActivity.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2009 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.view.animation.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.database.DataSetObserver;
-import android.os.Bundle;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AbsListView;
-import android.widget.GridView;
-import android.widget.ImageView;
-import android.widget.ListAdapter;
-
-public class GridLayoutAnimStubActivity extends Activity {
-
-    private GridView mGridView;
-    private static final int GRID_NUM = 9;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.gridlayout_anim_controller_layout);
-        mGridView = (GridView) findViewById(R.id.gridlayout_anim_gridview);
-        mGridView.setAdapter(new MockGridViewAdapter(GRID_NUM));
-    }
-
-    public GridView getGridView() {
-        return mGridView;
-    }
-
-    private class MockGridViewAdapter implements ListAdapter {
-        private final int mCount;
-
-        MockGridViewAdapter(int count) {
-            mCount = count;
-        }
-
-        MockGridViewAdapter() {
-            this(1);
-        }
-
-        public boolean areAllItemsEnabled() {
-            return true;
-        }
-
-        public boolean isEnabled(int position) {
-            return true;
-        }
-
-        public void registerDataSetObserver(DataSetObserver observer) {
-        }
-
-        public void unregisterDataSetObserver(DataSetObserver observer) {
-        }
-
-        public int getCount() {
-            return mCount;
-        }
-
-        public Object getItem(int position) {
-            return position;
-        }
-
-        public long getItemId(int position) {
-            return position;
-        }
-
-        public boolean hasStableIds() {
-            return false;
-        }
-
-        public View getView(int position, View convertView, ViewGroup parent) {
-            if ((convertView != null) && (convertView instanceof ImageView)) {
-                ((ImageView) convertView).setImageResource(R.drawable.size_48x48);
-                return convertView;
-            }
-
-            ImageView newView = new ImageView(GridLayoutAnimStubActivity.this);
-            AbsListView.LayoutParams params = new AbsListView.LayoutParams(
-                    AbsListView.LayoutParams.WRAP_CONTENT, AbsListView.LayoutParams.WRAP_CONTENT);
-            newView.setLayoutParams(params);
-            newView.setImageResource(R.drawable.size_48x48);
-            return newView;
-        }
-
-        public int getItemViewType(int position) {
-            return 0;
-        }
-
-        public int getViewTypeCount() {
-            return 1;
-        }
-
-        public boolean isEmpty() {
-            return false;
-        }
-    }
-}
diff --git a/tests/src/android/view/animation/cts/LayoutAnimStubActivity.java b/tests/src/android/view/animation/cts/LayoutAnimStubActivity.java
deleted file mode 100644
index e647820..0000000
--- a/tests/src/android/view/animation/cts/LayoutAnimStubActivity.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2009 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.view.animation.cts;
-
-import android.app.ListActivity;
-import android.os.Bundle;
-import android.widget.ArrayAdapter;
-
-
-public class LayoutAnimStubActivity extends ListActivity {
-
-    private String[] mStrings = {
-            "Android",
-            "CTS",
-            "Test",
-    };
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setListAdapter(new ArrayAdapter<String>(this,
-                android.R.layout.simple_list_item_1, mStrings));
-    }
-}
diff --git a/tests/src/android/view/cts/FocusFinderStubActivity.java b/tests/src/android/view/cts/FocusFinderStubActivity.java
deleted file mode 100644
index c5b215f..0000000
--- a/tests/src/android/view/cts/FocusFinderStubActivity.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2008 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.view.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.content.Context;
-import android.os.Bundle;
-import android.util.AttributeSet;
-import android.view.ViewGroup;
-import android.widget.Button;
-
-public class FocusFinderStubActivity extends Activity {
-
-    public ViewGroup layout;
-
-    public Button topLeftButton;
-
-    public Button topRightButton;
-
-    public Button bottomLeftButton;
-
-    public Button bottomRightButton;
-
-    @Override
-    protected void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-        setContentView(R.layout.focus_finder_layout);
-        layout = (ViewGroup) findViewById(R.id.layout);
-        topLeftButton = (Button) findViewById(R.id.top_left_button);
-        topRightButton = (Button) findViewById(R.id.top_right_button);
-        bottomLeftButton = (Button) findViewById(R.id.bottom_left_button);
-        bottomRightButton = (Button) findViewById(R.id.bottom_right_button);
-    }
-}
-
diff --git a/tests/src/android/view/cts/FocusHandlingStubActivity.java b/tests/src/android/view/cts/FocusHandlingStubActivity.java
deleted file mode 100644
index 9faa609..0000000
--- a/tests/src/android/view/cts/FocusHandlingStubActivity.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2009 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.view.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-/**
- * A simple activity to test "Focus Handling"
- */
-public class FocusHandlingStubActivity extends Activity {
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setTheme(android.R.style.Theme_Holo_NoActionBar);
-        setContentView(R.layout.focus_handling_layout);
-    }
-}
diff --git a/tests/src/android/view/cts/GestureDetectorStubActivity.java b/tests/src/android/view/cts/GestureDetectorStubActivity.java
deleted file mode 100644
index e82b787..0000000
--- a/tests/src/android/view/cts/GestureDetectorStubActivity.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2009 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.view.cts;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.os.Handler;
-import android.view.GestureDetector;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.GestureDetector.SimpleOnGestureListener;
-import android.view.View.OnTouchListener;
-import android.widget.Button;
-
-public class GestureDetectorStubActivity extends Activity {
-
-    public boolean isDown;
-    public boolean isScroll;
-    public boolean isFling;
-    public boolean isSingleTapUp;
-    public boolean onShowPress;
-    public boolean onLongPress;
-    public boolean onDoubleTap;
-    public boolean onDoubleTapEvent;
-    public boolean onSingleTapConfirmed;
-
-    private GestureDetector mGestureDetector;
-    private MockOnGestureListener mOnGestureListener;
-    private Handler mHandler;
-    private View mView;
-    private Button mTop;
-    private Button mButton;
-    private ViewGroup mViewGroup;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        mOnGestureListener = new MockOnGestureListener();
-        mHandler = new Handler();
-
-        mGestureDetector = new GestureDetector(this, mOnGestureListener, mHandler);
-        mGestureDetector.setOnDoubleTapListener(mOnGestureListener);
-        mView = new View(this);
-        mButton = new Button(this);
-        mTop = new Button(this);
-        mView.setOnTouchListener(new MockOnTouchListener());
-
-        mViewGroup = new ViewGroup(this) {
-            @Override
-            protected void onLayout(boolean changed, int l, int t, int r, int b) {
-            }
-        };
-        mViewGroup.addView(mView);
-        mViewGroup.addView(mTop);
-        mViewGroup.addView(mButton);
-        mViewGroup.setOnTouchListener(new MockOnTouchListener());
-        setContentView(mViewGroup);
-
-    }
-
-    public View getView() {
-        return mView;
-    }
-
-    public ViewGroup getViewGroup() {
-        return mViewGroup;
-    }
-
-    public GestureDetector getGestureDetector() {
-        return mGestureDetector;
-    }
-
-    public class MockOnGestureListener extends SimpleOnGestureListener {
-        public boolean onDown(MotionEvent e) {
-            isDown = true;
-            return true;
-        }
-
-        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
-            isFling = true;
-            return true;
-        }
-
-        public void onLongPress(MotionEvent e) {
-            onLongPress = true;
-        }
-
-        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
-            isScroll = true;
-            return true;
-        }
-
-        public void onShowPress(MotionEvent e) {
-            onShowPress = true;
-        }
-
-        public boolean onSingleTapUp(MotionEvent e) {
-            isSingleTapUp = true;
-            return true;
-        }
-
-        public boolean onDoubleTap(MotionEvent e) {
-            onDoubleTap = true;
-            return false;
-        }
-
-        public boolean onDoubleTapEvent(MotionEvent e) {
-            onDoubleTapEvent = true;
-            return false;
-        }
-
-        public boolean onSingleTapConfirmed(MotionEvent e) {
-            onSingleTapConfirmed = true;
-            return false;
-        }
-    }
-
-    class MockOnTouchListener implements OnTouchListener {
-
-        public boolean onTouch(View v, MotionEvent event) {
-            mGestureDetector.onTouchEvent(event);
-            return true;
-        }
-    }
-
-}
diff --git a/tests/src/android/view/cts/MenuInflaterStubActivity.java b/tests/src/android/view/cts/MenuInflaterStubActivity.java
deleted file mode 100644
index 693fe13..0000000
--- a/tests/src/android/view/cts/MenuInflaterStubActivity.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2008 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.view.cts;
-
-import android.app.Activity;
-import android.view.MenuInflater;
-
-/**
- * Stub activity for testing {@link MenuInflater}.
- *
- * @see MenuInflaterTest
- */
-public class MenuInflaterStubActivity extends Activity {
-}
diff --git a/tests/src/android/view/cts/SurfaceViewStubActivity.java b/tests/src/android/view/cts/SurfaceViewStubActivity.java
deleted file mode 100644
index 75d5ff6..0000000
--- a/tests/src/android/view/cts/SurfaceViewStubActivity.java
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Copyright (C) 2009 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.view.cts;
-
-import android.app.Activity;
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.PorterDuff.Mode;
-import android.os.Bundle;
-import android.view.SurfaceHolder;
-import android.view.SurfaceView;
-
-public class SurfaceViewStubActivity extends Activity {
-    private MockSurfaceView mSurfaceView;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        // New a MockSurfaceView
-        mSurfaceView = new MockSurfaceView(this);
-        setContentView(mSurfaceView);
-    }
-
-    public MockSurfaceView getSurfaceView() {
-        return mSurfaceView;
-    }
-
-    public class MockSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
-        private static final int FIX_WIDTH = 240;
-        private static final int FIX_HEIGHT = 240;
-        private static final int BITMAP_WIDTH = 100;
-        private static final int BITMAP_HEIGHT = 100;
-        private static final int RECT_LEFT = 20;
-        private static final int RECT_TOP = 100;
-        private static final int RECT_RIGHT = 200;
-        private static final int RECT_BOTTOM = 200;
-
-        private SurfaceHolder mHolder;
-        private MockCanvas mCanvas;
-
-        private boolean mIsDraw;
-        private boolean mIsAttachedToWindow;
-        private boolean mIsDetachedFromWindow;
-        private boolean mIsOnMeasure;
-        private boolean mIsOnScrollChanged;
-        private boolean mIsOnSizeChanged;
-        private boolean mIsOnWindowVisibilityChanged;
-        private boolean mIsDispatchDraw;
-        private boolean mIsSurfaceChanged;
-
-        private int mWidthInOnMeasure;
-        private int mHeightInOnMeasure;
-        private int mOldLOnScrollChanged;
-        private int mOldTOnScrollChanged;
-        private int mOldWOnSizeChanged;
-        private int mOldHOnSizeChanged;
-        private int mVisibilityOnWindowVisibilityChanged;
-
-        public MockSurfaceView(Context context) {
-            super(context);
-            mHolder = getHolder();
-            mHolder.addCallback(this);
-            mHolder.setFixedSize(FIX_WIDTH, FIX_HEIGHT);
-        }
-
-        @Override
-        public void onWindowVisibilityChanged(int visibility) {
-            super.onWindowVisibilityChanged(visibility);
-            mVisibilityOnWindowVisibilityChanged = visibility;
-            mIsOnWindowVisibilityChanged = true;
-        }
-
-        public int getVInOnWindowVisibilityChanged() {
-            return mVisibilityOnWindowVisibilityChanged;
-        }
-
-        @Override
-        public void draw(Canvas canvas) {
-            super.draw(canvas);
-            mIsDraw = true;
-        }
-
-        @Override
-        public void onAttachedToWindow() {
-            super.onAttachedToWindow();
-            mIsAttachedToWindow = true;
-        }
-
-        @Override
-        public void onDetachedFromWindow() {
-            super.onDetachedFromWindow();
-            mIsDetachedFromWindow = true;
-        }
-
-        @Override
-        public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-            mWidthInOnMeasure = getDefaultSize(FIX_WIDTH, widthMeasureSpec);
-            mHeightInOnMeasure = getDefaultSize(FIX_HEIGHT, heightMeasureSpec);
-            mIsOnMeasure = true;
-        }
-
-        public int getWidthInOnMeasure() {
-            return mWidthInOnMeasure;
-        }
-
-        public int getHeightInOnMeasure() {
-            return mHeightInOnMeasure;
-        }
-
-        @Override
-        public void onScrollChanged(int l, int t, int oldl, int oldt) {
-            super.onScrollChanged(l, t, oldl, oldt);
-
-            mOldLOnScrollChanged = oldl;
-            mOldTOnScrollChanged = oldt;
-            mIsOnScrollChanged = true;
-        }
-
-        public int getOldHorizontal() {
-            return mOldLOnScrollChanged;
-        }
-
-        public int getOldVertical() {
-            return mOldTOnScrollChanged;
-        }
-
-        @Override
-        public void onSizeChanged(int w, int h, int oldw, int oldh) {
-            super.onSizeChanged(w, h, oldw, oldh);
-
-            mOldWOnSizeChanged = oldw;
-            mOldHOnSizeChanged = oldh;
-            mIsOnSizeChanged = true;
-        }
-
-        public int getOldWidth() {
-            return mOldWOnSizeChanged;
-        }
-
-        public int getOldHeight() {
-            return mOldHOnSizeChanged;
-        }
-
-        @Override
-        protected void dispatchDraw(Canvas canvas) {
-            super.dispatchDraw(canvas);
-            mIsDispatchDraw = true;
-        }
-
-        public void setFormat(int format) {
-            getHolder().setFormat(format);
-        }
-
-        public void surfaceCreated(SurfaceHolder holder) {
-            // Use mock canvas listening to the drawColor() calling.
-            mCanvas = new MockCanvas(Bitmap.createBitmap( BITMAP_WIDTH,
-                                                          BITMAP_HEIGHT,
-                                                          Bitmap.Config.ARGB_8888));
-            draw(mCanvas);
-
-            // Lock the surface, this returns a Canvas that can be used to render into.
-            Canvas canvas = mHolder.lockCanvas();
-            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
-            paint.setColor(Color.BLUE);
-            canvas.drawRect(RECT_LEFT, RECT_TOP, RECT_RIGHT, RECT_BOTTOM, paint);
-
-            // And finally unlock and post the surface.
-            mHolder.unlockCanvasAndPost(canvas);
-        }
-
-        public void surfaceDestroyed(SurfaceHolder holder) {
-        }
-
-        public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
-            mIsSurfaceChanged = true;
-        }
-
-        public boolean isDraw() {
-            return mIsDraw;
-        }
-
-        public boolean isOnAttachedToWindow() {
-            return mIsAttachedToWindow;
-        }
-
-        public boolean isDetachedFromWindow() {
-            return mIsDetachedFromWindow;
-        }
-
-        public boolean isOnMeasureCalled() {
-            return mIsOnMeasure;
-        }
-
-        public boolean isOnScrollChanged() {
-            return mIsOnScrollChanged;
-        }
-
-        public boolean isOnSizeChangedCalled() {
-            return mIsOnSizeChanged;
-        }
-
-        public void resetOnSizeChangedFlag(boolean b) {
-            mIsOnSizeChanged = b;
-        }
-
-        public boolean isOnWindowVisibilityChanged() {
-            return mIsOnWindowVisibilityChanged;
-        }
-
-        public boolean isDispatchDraw() {
-            return mIsDispatchDraw;
-        }
-
-        public boolean isDrawColor() {
-            if (mCanvas != null) {
-                return mCanvas.isDrawColor();
-            } else {
-                return false;
-            }
-        }
-
-        public boolean isSurfaceChanged() {
-            return mIsSurfaceChanged;
-        }
-
-        public void setDrawColor(boolean isDrawColor) {
-            if (mCanvas != null) {
-                mCanvas.setDrawColor(isDrawColor);
-            }
-        }
-    }
-
-    class MockCanvas extends Canvas {
-        private boolean mIsDrawColor;
-
-        public MockCanvas(Bitmap bitmap) {
-            super(bitmap);
-        }
-
-        @Override
-        public void drawColor(int color, Mode mode) {
-            super.drawColor(color, mode);
-            mIsDrawColor = true;
-        }
-
-        public boolean isDrawColor() {
-            return mIsDrawColor;
-        }
-
-        public void setDrawColor(boolean isDrawColor) {
-            this.mIsDrawColor = isDrawColor;
-        }
-    }
-}
diff --git a/tests/src/android/view/cts/UsingViewsStubActivity.java b/tests/src/android/view/cts/UsingViewsStubActivity.java
deleted file mode 100644
index eb3aba7..0000000
--- a/tests/src/android/view/cts/UsingViewsStubActivity.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2009 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.view.cts;
-
-import android.app.Activity;
-import android.os.Bundle;
-import com.android.cts.stub.R;
-
-/**
- * A simple activity to test "Using Views"
- */
-public class UsingViewsStubActivity extends Activity {
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.using_views_layout);
-    }
-}
diff --git a/tests/src/android/view/cts/ViewLayoutPositionTestStubActivity.java b/tests/src/android/view/cts/ViewLayoutPositionTestStubActivity.java
deleted file mode 100644
index d7ce635..0000000
--- a/tests/src/android/view/cts/ViewLayoutPositionTestStubActivity.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2008 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.view.cts;
-
-import android.app.Activity;
-import android.os.Bundle;
-import com.android.cts.stub.R;
-
-public class ViewLayoutPositionTestStubActivity extends Activity {
-    @Override
-    protected void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-        setContentView(R.layout.view_layout_position);
-    }
-}
diff --git a/tests/src/android/view/cts/ViewStubStubActivity.java b/tests/src/android/view/cts/ViewStubStubActivity.java
deleted file mode 100644
index 2a05f8e..0000000
--- a/tests/src/android/view/cts/ViewStubStubActivity.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2008 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.view.cts;
-
-import android.app.Activity;
-import android.os.Bundle;
-import com.android.cts.stub.R;
-
-public class ViewStubStubActivity extends Activity {
-    @Override
-    protected void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-        setContentView(R.layout.viewstub_layout);
-    }
-}
diff --git a/tests/src/android/view/cts/ViewTestStubActivity.java b/tests/src/android/view/cts/ViewTestStubActivity.java
deleted file mode 100644
index 69676cb..0000000
--- a/tests/src/android/view/cts/ViewTestStubActivity.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2008 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.view.cts;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.os.SystemClock;
-import android.util.Log;
-import com.android.cts.stub.R;
-
-public class ViewTestStubActivity extends Activity {
-    private boolean mHasWindowFocus = false;
-    private Object mHasWindowFocusLock = new Object();
-
-    @Override
-    protected void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-        setContentView(R.layout.view_layout);
-    }
-
-    @Override
-    public void onWindowFocusChanged(boolean hasFocus) {
-        super.onWindowFocusChanged(hasFocus);
-        if (!hasFocus) {
-            Log.w("ViewTestStubActivity", "ViewTestStubActivity lost window focus");
-        }
-        synchronized(mHasWindowFocusLock) {
-            mHasWindowFocus = hasFocus;
-            mHasWindowFocusLock.notify();
-        }
-    }
-
-    /**
-     * Blocks the calling thread until the {@link ViewTestStubActivity} has window focus or the
-     * specified duration (in milliseconds) has passed.
-     */
-    public boolean waitForWindowFocus(long durationMillis) {
-        long elapsedMillis = SystemClock.elapsedRealtime();
-        synchronized(mHasWindowFocusLock) {
-            mHasWindowFocus = hasWindowFocus();
-            while (!mHasWindowFocus && durationMillis > 0) {
-                long newElapsedMillis = SystemClock.elapsedRealtime();
-                durationMillis -= (newElapsedMillis - elapsedMillis);
-                elapsedMillis = newElapsedMillis;
-                if (durationMillis > 0) {
-                    try {
-                        mHasWindowFocusLock.wait(durationMillis);
-                    } catch (InterruptedException e) {
-                    }
-                }
-            }
-            return mHasWindowFocus;
-        }
-    }
-}
diff --git a/tests/src/android/view/cts/WindowStubActivity.java b/tests/src/android/view/cts/WindowStubActivity.java
deleted file mode 100644
index 502c947..0000000
--- a/tests/src/android/view/cts/WindowStubActivity.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2008 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.view.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.Window;
-
-public class WindowStubActivity extends Activity {
-
-    private static boolean mIsOnCreateOptionsMenuCalled;
-    private static boolean mIsOnOptionsMenuClosedCalled;
-    private static boolean mIsOnKeyDownCalled;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        getWindow().requestFeature(Window.FEATURE_LEFT_ICON);
-        setContentView(R.layout.windowstub_layout);
-    }
-
-    @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        menu.add(Menu.NONE, Menu.NONE, Menu.NONE, "Quit").setShortcut('1', 'q');
-        menu.add(Menu.NONE, Menu.NONE, Menu.NONE, "Action").setShortcut('2', 'a');
-        mIsOnCreateOptionsMenuCalled = true;
-        return super.onCreateOptionsMenu(menu);
-    }
-
-    @Override
-    public void onOptionsMenuClosed(Menu menu) {
-        super.onOptionsMenuClosed(menu);
-        mIsOnOptionsMenuClosedCalled = true;
-    }
-
-    @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
-        mIsOnKeyDownCalled = true;
-        return super.onKeyDown(keyCode, event);
-    }
-
-    public boolean isOnCreateOptionsMenuCalled() {
-        return mIsOnCreateOptionsMenuCalled;
-    }
-
-    public boolean isOnOptionsMenuClosedCalled() {
-        return mIsOnOptionsMenuClosedCalled;
-    }
-
-    public boolean isOnKeyDownCalled() {
-        return mIsOnKeyDownCalled;
-    }
-
-    public void setFlagFalse() {
-        mIsOnCreateOptionsMenuCalled = false;
-        mIsOnOptionsMenuClosedCalled = false;
-    }
-}
diff --git a/tests/src/android/view/inputmethod/cts/InputMethodStubActivity.java b/tests/src/android/view/inputmethod/cts/InputMethodStubActivity.java
deleted file mode 100644
index 8117918..0000000
--- a/tests/src/android/view/inputmethod/cts/InputMethodStubActivity.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2008 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.view.inputmethod.cts;
-
-import android.app.Activity;
-import android.os.Bundle;
-import com.android.cts.stub.R;
-
-public class InputMethodStubActivity extends Activity {
-    @Override
-    protected void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-        setContentView(R.layout.inputmethod_edittext);
-    }
-}
diff --git a/tests/src/android/webkit/cts/CookieSyncManagerStubActivity.java b/tests/src/android/webkit/cts/CookieSyncManagerStubActivity.java
deleted file mode 100644
index a5ac6ec..0000000
--- a/tests/src/android/webkit/cts/CookieSyncManagerStubActivity.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2009 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.webkit.cts;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.webkit.CookieSyncManager;
-import android.webkit.WebView;
-
-public class CookieSyncManagerStubActivity extends Activity {
-    private WebView mWebView;
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        try {
-            CookieSyncManager.createInstance(this);
-
-            mWebView = new WebView(this);
-            setContentView(mWebView);
-        } catch (Exception e) {
-            NullWebViewUtils.determineIfWebViewAvailable(this, e);
-        }
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        try {
-            CookieSyncManager.getInstance().startSync();
-        } catch (Exception e) {
-            // May throw on a device with no webview, OK to ignore at this point.
-        }
-    }
-
-    @Override
-    protected void onStop() {
-        super.onStop();
-        try {
-            CookieSyncManager.getInstance().stopSync();
-        } catch (Exception e) {
-            // May throw on a device with no webview, OK to ignore at this point.
-        }
-    }
-
-    public WebView getWebView(){
-        return mWebView;
-    }
-}
diff --git a/tests/src/android/webkit/cts/NullWebViewUtils.java b/tests/src/android/webkit/cts/NullWebViewUtils.java
deleted file mode 100644
index c52219f..0000000
--- a/tests/src/android/webkit/cts/NullWebViewUtils.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2010 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.webkit.cts;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-
-/**
- * Utilities to enable the android.webkit.* CTS tests (and others that rely on a functioning
- * android.webkit.WebView implementation) to determine whether a functioning WebView is present
- * on the device or not.
- *
- * Test cases that require android.webkit.* classes should wrap their first usage of WebView in a
- * try catch block, and pass any exception that is thrown to
- * NullWebViewUtils.determineIfWebViewAvailable. The return value of
- * NullWebViewUtils.isWebViewAvailable will then determine if the test should expect to be able to
- * use a WebView.
- */
-public class NullWebViewUtils {
-
-    private static boolean sWebViewUnavailable;
-
-    /**
-     * @param context Current Activity context, used to query the PackageManager.
-     * @param t       An exception thrown by trying to invoke android.webkit.* APIs.
-     */
-    public static void determineIfWebViewAvailable(Context context, Throwable t) {
-        sWebViewUnavailable = !hasWebViewFeature(context) && checkCauseWasUnsupportedOperation(t);
-    }
-
-    /**
-     * After calling determineIfWebViewAvailable, this returns whether a WebView is available on the
-     * device and wheter the test can rely on it.
-     * @return True iff. PackageManager determined that there is no WebView on the device and the
-     *         exception thrown from android.webkit.* was UnsupportedOperationException.
-     */
-    public static boolean isWebViewAvailable() {
-        return !sWebViewUnavailable;
-    }
-
-    private static boolean hasWebViewFeature(Context context) {
-        // Query the system property that determins if there is a functional WebView on the device.
-        PackageManager pm = context.getPackageManager();
-        return pm.hasSystemFeature(PackageManager.FEATURE_WEBVIEW);
-    }
-
-    private static boolean checkCauseWasUnsupportedOperation(Throwable t) {
-        if (t == null) return false;
-        while (t.getCause() != null) {
-            t = t.getCause();
-        }
-        return t instanceof UnsupportedOperationException;
-    }
-
-    /**
-     * Some CTS tests (by design) first use android.webkit.* from a background thread. This helper
-     * allows the test to catch the UnsupportedOperationException from that background thread, and
-     * then query the result from the test main thread.
-     */
-    public static class NullWebViewFromThreadExceptionHandler
-            implements Thread.UncaughtExceptionHandler {
-        private Throwable mPendingException;
-
-        @Override
-        public void uncaughtException(Thread t, Throwable e) {
-            mPendingException = e;
-        }
-
-        public boolean isWebViewAvailable(Context context) {
-            return hasWebViewFeature(context) ||
-                    !checkCauseWasUnsupportedOperation(mPendingException);
-        }
-    }
-}
\ No newline at end of file
diff --git a/tests/src/android/webkit/cts/WebViewOnUiThread.java b/tests/src/android/webkit/cts/WebViewOnUiThread.java
deleted file mode 100644
index f638ba8..0000000
--- a/tests/src/android/webkit/cts/WebViewOnUiThread.java
+++ /dev/null
@@ -1,933 +0,0 @@
-/*
- * 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.
- */
-
-package android.webkit.cts;
-
-import android.cts.util.PollingCheck;
-import android.graphics.Bitmap;
-import android.graphics.Picture;
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.os.Looper;
-import android.os.Message;
-import android.os.SystemClock;
-import android.print.PrintDocumentAdapter;
-import android.test.InstrumentationTestCase;
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewParent;
-import android.webkit.DownloadListener;
-import android.webkit.ValueCallback;
-import android.webkit.WebBackForwardList;
-import android.webkit.WebChromeClient;
-import android.webkit.WebSettings;
-import android.webkit.WebView.HitTestResult;
-import android.webkit.WebView.PictureListener;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-
-import junit.framework.Assert;
-
-import java.io.File;
-import java.util.concurrent.Callable;
-import java.util.Map;
-
-/**
- * Many tests need to run WebView code in the UI thread. This class
- * wraps a WebView so that calls are ensured to arrive on the UI thread.
- *
- * All methods may be run on either the UI thread or test thread.
- */
-public class WebViewOnUiThread {
-    /**
-     * The maximum time, in milliseconds (10 seconds) to wait for a load
-     * to be triggered.
-     */
-    private static final long LOAD_TIMEOUT = 10000;
-
-    /**
-     * Set to true after onPageFinished is called.
-     */
-    private boolean mLoaded;
-
-    /**
-     * Set to true after onNewPicture is called. Reset when onPageStarted
-     * is called.
-     */
-    private boolean mNewPicture;
-
-    /**
-     * The progress, in percentage, of the page load. Valid values are between
-     * 0 and 100.
-     */
-    private int mProgress;
-
-    /**
-     * The test that this class is being used in. Used for runTestOnUiThread.
-     */
-    private InstrumentationTestCase mTest;
-
-    /**
-     * The WebView that calls will be made on.
-     */
-    private WebView mWebView;
-
-    /**
-     * Initializes the webView with a WebViewClient, WebChromeClient,
-     * and PictureListener to prepare for loadUrlAndWaitForCompletion.
-     *
-     * A new WebViewOnUiThread should be called during setUp so as to
-     * reinitialize between calls.
-     *
-     * @param test The test in which this is being run.
-     * @param webView The webView that the methods should call.
-     * @see loadUrlAndWaitForCompletion
-     */
-    public WebViewOnUiThread(InstrumentationTestCase test, WebView webView) {
-        mTest = test;
-        mWebView = webView;
-        final WebViewClient webViewClient = new WaitForLoadedClient(this);
-        final WebChromeClient webChromeClient = new WaitForProgressClient(this);
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.setWebViewClient(webViewClient);
-                mWebView.setWebChromeClient(webChromeClient);
-                mWebView.setPictureListener(new WaitForNewPicture());
-            }
-        });
-    }
-
-    /**
-     * Called after a test is complete and the WebView should be disengaged from
-     * the tests.
-     */
-    public void cleanUp() {
-        clearHistory();
-        clearCache(true);
-        setPictureListener(null);
-        setWebChromeClient(null);
-        setWebViewClient(null);
-    }
-
-    /**
-     * Called from WaitForNewPicture, this is used to indicate that
-     * the page has been drawn.
-     */
-    synchronized public void onNewPicture() {
-        mNewPicture = true;
-        this.notifyAll();
-    }
-
-    /**
-     * Called from WaitForLoadedClient, this is used to clear the picture
-     * draw state so that draws before the URL begins loading don't count.
-     */
-    synchronized public void onPageStarted() {
-        mNewPicture = false; // Earlier paints won't count.
-    }
-
-    /**
-     * Called from WaitForLoadedClient, this is used to indicate that
-     * the page is loaded, but not drawn yet.
-     */
-    synchronized public void onPageFinished() {
-        mLoaded = true;
-        this.notifyAll();
-    }
-
-    /**
-     * Called from the WebChrome client, this sets the current progress
-     * for a page.
-     * @param progress The progress made so far between 0 and 100.
-     */
-    synchronized public void onProgressChanged(int progress) {
-        mProgress = progress;
-        this.notifyAll();
-    }
-
-    public void setWebViewClient(final WebViewClient webViewClient) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.setWebViewClient(webViewClient);
-            }
-        });
-    }
-
-    public void setWebChromeClient(final WebChromeClient webChromeClient) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.setWebChromeClient(webChromeClient);
-            }
-        });
-    }
-
-    public void setPictureListener(final PictureListener pictureListener) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.setPictureListener(pictureListener);
-            }
-        });
-    }
-
-    public void setNetworkAvailable(final boolean available) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.setNetworkAvailable(available);
-            }
-        });
-    }
-
-    public void setDownloadListener(final DownloadListener listener) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.setDownloadListener(listener);
-            }
-        });
-    }
-
-    public void setBackgroundColor(final int color) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.setBackgroundColor(color);
-            }
-        });
-    }
-
-    public void clearCache(final boolean includeDiskFiles) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.clearCache(includeDiskFiles);
-            }
-        });
-    }
-
-    public void clearHistory() {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.clearHistory();
-            }
-        });
-    }
-
-    public void requestFocus() {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.requestFocus();
-            }
-        });
-    }
-
-    public boolean canZoomIn() {
-        return getValue(new ValueGetter<Boolean>() {
-            @Override
-            public Boolean capture() {
-                return mWebView.canZoomIn();
-            }
-        });
-    }
-
-    public boolean zoomIn() {
-        return getValue(new ValueGetter<Boolean>() {
-            @Override
-            public Boolean capture() {
-                return mWebView.zoomIn();
-            }
-        });
-    }
-
-    public boolean zoomOut() {
-        return getValue(new ValueGetter<Boolean>() {
-            @Override
-            public Boolean capture() {
-                return mWebView.zoomOut();
-            }
-        });
-    }
-
-    public void setFindListener(final WebView.FindListener listener) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.setFindListener(listener);
-            }
-        });
-    }
-
-    public void removeJavascriptInterface(final String interfaceName) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.removeJavascriptInterface(interfaceName);
-            }
-        });
-    }
-
-    public void addJavascriptInterface(final Object object, final String name) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.addJavascriptInterface(object, name);
-            }
-        });
-    }
-
-    public void flingScroll(final int vx, final int vy) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.flingScroll(vx, vy);
-            }
-        });
-    }
-
-    public void requestFocusNodeHref(final Message hrefMsg) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.requestFocusNodeHref(hrefMsg);
-            }
-        });
-    }
-
-    public void requestImageRef(final Message msg) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.requestImageRef(msg);
-            }
-        });
-    }
-
-    public void setInitialScale(final int scaleInPercent) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.setInitialScale(scaleInPercent);
-            }
-        });
-    }
-
-    public void clearSslPreferences() {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.clearSslPreferences();
-            }
-        });
-    }
-
-    public void resumeTimers() {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.resumeTimers();
-            }
-        });
-    }
-
-    public void findNext(final boolean forward) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.findNext(forward);
-            }
-        });
-    }
-
-    public void clearMatches() {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.clearMatches();
-            }
-        });
-    }
-
-    /**
-     * Calls loadUrl on the WebView and then waits onPageFinished,
-     * onNewPicture and onProgressChange to reach 100.
-     * Test fails if the load timeout elapses.
-     * @param url The URL to load.
-     */
-    public void loadUrlAndWaitForCompletion(final String url) {
-        callAndWait(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.loadUrl(url);
-            }
-        });
-    }
-
-    /**
-     * Calls loadUrl on the WebView and then waits onPageFinished,
-     * onNewPicture and onProgressChange to reach 100.
-     * Test fails if the load timeout elapses.
-     * @param url The URL to load.
-     */
-    public void loadUrlAndWaitForCompletion(final String url,
-            final Map<String, String> extraHeaders) {
-        callAndWait(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.loadUrl(url, extraHeaders);
-            }
-        });
-    }
-
-    public void loadUrl(final String url) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.loadUrl(url);
-            }
-        });
-    }
-
-    public void stopLoading() {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.stopLoading();
-            }
-        });
-    }
-
-    public void loadDataAndWaitForCompletion(final String data,
-            final String mimeType, final String encoding) {
-        callAndWait(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.loadData(data, mimeType, encoding);
-            }
-        });
-    }
-
-    public void loadDataWithBaseURLAndWaitForCompletion(final String baseUrl,
-            final String data, final String mimeType, final String encoding,
-            final String historyUrl) {
-        callAndWait(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.loadDataWithBaseURL(baseUrl, data, mimeType, encoding,
-                        historyUrl);
-            }
-        });
-    }
-
-    /**
-     * Reloads a page and waits for it to complete reloading. Use reload
-     * if it is a form resubmission and the onFormResubmission responds
-     * by telling WebView not to resubmit it.
-     */
-    public void reloadAndWaitForCompletion() {
-        callAndWait(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.reload();
-            }
-        });
-    }
-
-    /**
-     * Reload the previous URL. Use reloadAndWaitForCompletion unless
-     * it is a form resubmission and the onFormResubmission responds
-     * by telling WebView not to resubmit it.
-     */
-    public void reload() {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.reload();
-            }
-        });
-    }
-
-    /**
-     * Use this only when JavaScript causes a page load to wait for the
-     * page load to complete. Otherwise use loadUrlAndWaitForCompletion or
-     * similar functions.
-     */
-    public void waitForLoadCompletion() {
-        waitForCriteria(LOAD_TIMEOUT,
-                new Callable<Boolean>() {
-                    @Override
-                    public Boolean call() {
-                        return isLoaded();
-                    }
-                });
-        clearLoad();
-    }
-
-    private void waitForCriteria(long timeout, Callable<Boolean> doneCriteria) {
-        if (isUiThread()) {
-            waitOnUiThread(timeout, doneCriteria);
-        } else {
-            waitOnTestThread(timeout, doneCriteria);
-        }
-    }
-
-    public String getTitle() {
-        return getValue(new ValueGetter<String>() {
-            @Override
-            public String capture() {
-                return mWebView.getTitle();
-            }
-        });
-    }
-
-    public WebSettings getSettings() {
-        return getValue(new ValueGetter<WebSettings>() {
-            @Override
-            public WebSettings capture() {
-                return mWebView.getSettings();
-            }
-        });
-    }
-
-    public WebBackForwardList copyBackForwardList() {
-        return getValue(new ValueGetter<WebBackForwardList>() {
-            @Override
-            public WebBackForwardList capture() {
-                return mWebView.copyBackForwardList();
-            }
-        });
-    }
-
-    public Bitmap getFavicon() {
-        return getValue(new ValueGetter<Bitmap>() {
-            @Override
-            public Bitmap capture() {
-                return mWebView.getFavicon();
-            }
-        });
-    }
-
-    public String getUrl() {
-        return getValue(new ValueGetter<String>() {
-            @Override
-            public String capture() {
-                return mWebView.getUrl();
-            }
-        });
-    }
-
-    public int getProgress() {
-        return getValue(new ValueGetter<Integer>() {
-            @Override
-            public Integer capture() {
-                return mWebView.getProgress();
-            }
-        });
-    }
-
-    public int getHeight() {
-        return getValue(new ValueGetter<Integer>() {
-            @Override
-            public Integer capture() {
-                return mWebView.getHeight();
-            }
-        });
-    }
-
-    public int getContentHeight() {
-        return getValue(new ValueGetter<Integer>() {
-            @Override
-            public Integer capture() {
-                return mWebView.getContentHeight();
-            }
-        });
-    }
-
-    public boolean savePicture(final Bundle b, final File dest) {
-        return getValue(new ValueGetter<Boolean>() {
-            @Override
-            public Boolean capture() {
-                return mWebView.savePicture(b, dest);
-            }
-        });
-    }
-
-    public boolean pageUp(final boolean top) {
-        return getValue(new ValueGetter<Boolean>() {
-            @Override
-            public Boolean capture() {
-                return mWebView.pageUp(top);
-            }
-        });
-    }
-
-    public boolean pageDown(final boolean bottom) {
-        return getValue(new ValueGetter<Boolean>() {
-            @Override
-            public Boolean capture() {
-                return mWebView.pageDown(bottom);
-            }
-        });
-    }
-
-    public int[] getLocationOnScreen() {
-        final int[] location = new int[2];
-        return getValue(new ValueGetter<int[]>() {
-            @Override
-            public int[] capture() {
-                mWebView.getLocationOnScreen(location);
-                return location;
-            }
-        });
-    }
-
-    public float getScale() {
-        return getValue(new ValueGetter<Float>() {
-            @Override
-            public Float capture() {
-                return mWebView.getScale();
-            }
-        });
-    }
-
-    public boolean requestFocus(final int direction,
-            final Rect previouslyFocusedRect) {
-        return getValue(new ValueGetter<Boolean>() {
-            @Override
-            public Boolean capture() {
-                return mWebView.requestFocus(direction, previouslyFocusedRect);
-            }
-        });
-    }
-
-    public HitTestResult getHitTestResult() {
-        return getValue(new ValueGetter<HitTestResult>() {
-            @Override
-            public HitTestResult capture() {
-                return mWebView.getHitTestResult();
-            }
-        });
-    }
-
-    public int getScrollX() {
-        return getValue(new ValueGetter<Integer>() {
-            @Override
-            public Integer capture() {
-                return mWebView.getScrollX();
-            }
-        });
-    }
-
-    public int getScrollY() {
-        return getValue(new ValueGetter<Integer>() {
-            @Override
-            public Integer capture() {
-                return mWebView.getScrollY();
-            }
-        });
-    }
-
-    public final DisplayMetrics getDisplayMetrics() {
-        return getValue(new ValueGetter<DisplayMetrics>() {
-            @Override
-            public DisplayMetrics capture() {
-                return mWebView.getContext().getResources().getDisplayMetrics();
-            }
-        });
-    }
-
-    public boolean requestChildRectangleOnScreen(final View child,
-            final Rect rect,
-            final boolean immediate) {
-        return getValue(new ValueGetter<Boolean>() {
-            @Override
-            public Boolean capture() {
-                return mWebView.requestChildRectangleOnScreen(child, rect,
-                        immediate);
-            }
-        });
-    }
-
-    public int findAll(final String find) {
-        return getValue(new ValueGetter<Integer>() {
-            @Override
-            public Integer capture() {
-                return mWebView.findAll(find);
-            }
-        });
-    }
-
-    public Picture capturePicture() {
-        return getValue(new ValueGetter<Picture>() {
-            @Override
-            public Picture capture() {
-                return mWebView.capturePicture();
-            }
-        });
-    }
-
-    public void evaluateJavascript(final String script, final ValueCallback<String> result) {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                mWebView.evaluateJavascript(script, result);
-            }
-        });
-    }
-
-    public PrintDocumentAdapter createPrintDocumentAdapter() {
-        return getValue(new ValueGetter<PrintDocumentAdapter>() {
-            @Override
-            public PrintDocumentAdapter capture() {
-                return mWebView.createPrintDocumentAdapter();
-            }
-        });
-    }
-
-    public void setLayoutHeightToMatchParent() {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                ViewParent parent = mWebView.getParent();
-                if (parent instanceof ViewGroup) {
-                    ((ViewGroup) parent).getLayoutParams().height =
-                        ViewGroup.LayoutParams.MATCH_PARENT;
-                }
-                mWebView.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
-                mWebView.requestLayout();
-            }
-        });
-    }
-
-    /**
-     * Helper for running code on the UI thread where an exception is
-     * a test failure. If this is already the UI thread then it runs
-     * the code immediately.
-     *
-     * @see runTestOnUiThread
-     * @param r The code to run in the UI thread
-     */
-    public void runOnUiThread(Runnable r) {
-        try {
-            if (isUiThread()) {
-                r.run();
-            } else {
-                mTest.runTestOnUiThread(r);
-            }
-        } catch (Throwable t) {
-            Assert.fail("Unexpected error while running on UI thread: "
-                    + t.getMessage());
-        }
-    }
-
-    /**
-     * Accessor for underlying WebView.
-     * @return The WebView being wrapped by this class.
-     */
-    public WebView getWebView() {
-        return mWebView;
-    }
-
-    private <T> T getValue(ValueGetter<T> getter) {
-        runOnUiThread(getter);
-        return getter.getValue();
-    }
-
-    private abstract class ValueGetter<T> implements Runnable {
-        private T mValue;
-
-        @Override
-        public void run() {
-            mValue = capture();
-        }
-
-        protected abstract T capture();
-
-        public T getValue() {
-           return mValue;
-        }
-    }
-
-    /**
-     * Returns true if the current thread is the UI thread based on the
-     * Looper.
-     */
-    private static boolean isUiThread() {
-        return (Looper.myLooper() == Looper.getMainLooper());
-    }
-
-    /**
-     * @return Whether or not the load has finished.
-     */
-    private synchronized boolean isLoaded() {
-        return mLoaded && mNewPicture && mProgress == 100;
-    }
-
-    /**
-     * Makes a WebView call, waits for completion and then resets the
-     * load state in preparation for the next load call.
-     * @param call The call to make on the UI thread prior to waiting.
-     */
-    private void callAndWait(Runnable call) {
-        Assert.assertTrue("WebViewOnUiThread.load*AndWaitForCompletion calls "
-                + "may not be mixed with load* calls directly on WebView "
-                + "without calling waitForLoadCompletion after the load",
-                !isLoaded());
-        clearLoad(); // clear any extraneous signals from a previous load.
-        runOnUiThread(call);
-        waitForLoadCompletion();
-    }
-
-    /**
-     * Called whenever a load has been completed so that a subsequent call to
-     * waitForLoadCompletion doesn't return immediately.
-     */
-    synchronized private void clearLoad() {
-        mLoaded = false;
-        mNewPicture = false;
-        mProgress = 0;
-    }
-
-    /**
-     * Uses a polling mechanism, while pumping messages to check when the
-     * criteria is met.
-     */
-    private void waitOnUiThread(long timeout, final Callable<Boolean> doneCriteria) {
-        new PollingCheck(timeout) {
-            @Override
-            protected boolean check() {
-                pumpMessages();
-                try {
-                    return doneCriteria.call();
-                } catch (Exception e) {
-                    Assert.fail("Unexpected error while checking the criteria: "
-                            + e.getMessage());
-                    return true;
-                }
-            }
-        }.run();
-    }
-
-    /**
-     * Uses a wait/notify to check when the criteria is met.
-     */
-    private synchronized void waitOnTestThread(long timeout, Callable<Boolean> doneCriteria) {
-        try {
-            long waitEnd = SystemClock.uptimeMillis() + timeout;
-            long timeRemaining = timeout;
-            while (!doneCriteria.call() && timeRemaining > 0) {
-                this.wait(timeRemaining);
-                timeRemaining = waitEnd - SystemClock.uptimeMillis();
-            }
-            Assert.assertTrue("Action failed to complete before timeout", doneCriteria.call());
-        } catch (InterruptedException e) {
-            // We'll just drop out of the loop and fail
-        } catch (Exception e) {
-            Assert.fail("Unexpected error while checking the criteria: "
-                    + e.getMessage());
-        }
-    }
-
-    /**
-     * Pumps all currently-queued messages in the UI thread and then exits.
-     * This is useful to force processing while running tests in the UI thread.
-     */
-    private void pumpMessages() {
-        class ExitLoopException extends RuntimeException {
-        }
-
-        // Force loop to exit when processing this. Loop.quit() doesn't
-        // work because this is the main Loop.
-        mWebView.getHandler().post(new Runnable() {
-            @Override
-            public void run() {
-                throw new ExitLoopException(); // exit loop!
-            }
-        });
-        try {
-            // Pump messages until our message gets through.
-            Looper.loop();
-        } catch (ExitLoopException e) {
-        }
-    }
-
-    /**
-     * A WebChromeClient used to capture the onProgressChanged for use
-     * in waitFor functions. If a test must override the WebChromeClient,
-     * it can derive from this class or call onProgressChanged
-     * directly.
-     */
-    public static class WaitForProgressClient extends WebChromeClient {
-        private WebViewOnUiThread mOnUiThread;
-
-        public WaitForProgressClient(WebViewOnUiThread onUiThread) {
-            mOnUiThread = onUiThread;
-        }
-
-        @Override
-        public void onProgressChanged(WebView view, int newProgress) {
-            super.onProgressChanged(view, newProgress);
-            mOnUiThread.onProgressChanged(newProgress);
-        }
-    }
-
-    /**
-     * A WebViewClient that captures the onPageFinished for use in
-     * waitFor functions. Using initializeWebView sets the WaitForLoadedClient
-     * into the WebView. If a test needs to set a specific WebViewClient and
-     * needs the waitForCompletion capability then it should derive from
-     * WaitForLoadedClient or call WebViewOnUiThread.onPageFinished.
-     */
-    public static class WaitForLoadedClient extends WebViewClient {
-        private WebViewOnUiThread mOnUiThread;
-
-        public WaitForLoadedClient(WebViewOnUiThread onUiThread) {
-            mOnUiThread = onUiThread;
-        }
-
-        @Override
-        public void onPageFinished(WebView view, String url) {
-            super.onPageFinished(view, url);
-            mOnUiThread.onPageFinished();
-        }
-
-        @Override
-        public void onPageStarted(WebView view, String url, Bitmap favicon) {
-            super.onPageStarted(view, url, favicon);
-            mOnUiThread.onPageStarted();
-        }
-    }
-
-    /**
-     * A PictureListener that captures the onNewPicture for use in
-     * waitForLoadCompletion. Using initializeWebView sets the PictureListener
-     * into the WebView. If a test needs to set a specific PictureListener and
-     * needs the waitForCompletion capability then it should call
-     * WebViewOnUiThread.onNewPicture.
-     */
-    private class WaitForNewPicture implements PictureListener {
-        @Override
-        public void onNewPicture(WebView view, Picture picture) {
-            WebViewOnUiThread.this.onNewPicture();
-        }
-    }
-}
diff --git a/tests/src/android/webkit/cts/WebViewStartupStubActivity.java b/tests/src/android/webkit/cts/WebViewStartupStubActivity.java
deleted file mode 100644
index f902a48..0000000
--- a/tests/src/android/webkit/cts/WebViewStartupStubActivity.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2013 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.webkit.cts;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.view.ViewGroup;
-import android.webkit.WebView;
-
-public class WebViewStartupStubActivity extends Activity {
-    private WebView mWebView;
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-    }
-
-    public WebView createAndAttachWebView() {
-        mWebView = new WebView(this);
-        setContentView(mWebView);
-        return mWebView;
-    }
-
-    public WebView getWebView() {
-        return mWebView;
-    }
-
-    public void detachAndDestroyWebView() {
-        if (mWebView != null) {
-            ViewGroup vg = (ViewGroup)mWebView.getParent();
-            vg.removeView(mWebView);
-            mWebView.destroy();
-        }
-    }
-
-    @Override
-    public void onDestroy() {
-        detachAndDestroyWebView();
-        super.onDestroy();
-    }
-}
diff --git a/tests/src/android/webkit/cts/WebViewStubActivity.java b/tests/src/android/webkit/cts/WebViewStubActivity.java
deleted file mode 100644
index 62adc39..0000000
--- a/tests/src/android/webkit/cts/WebViewStubActivity.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2009 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.webkit.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.view.ViewGroup;
-import android.view.ViewParent;
-import android.webkit.WebView;
-
-public class WebViewStubActivity extends Activity {
-    private WebView mWebView;
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        try {
-            super.onCreate(savedInstanceState);
-            setContentView(R.layout.webview_layout);
-            mWebView = (WebView) findViewById(R.id.web_page);
-        } catch (Exception e) {
-            NullWebViewUtils.determineIfWebViewAvailable(this, e);
-        }
-    }
-
-    public WebView getWebView() {
-        return mWebView;
-    }
-
-    @Override
-    public void onDestroy() {
-        if (mWebView != null) {
-            ViewParent parent =  mWebView.getParent();
-            if (parent instanceof ViewGroup) {
-                ((ViewGroup) parent).removeView(mWebView);
-            }
-            mWebView.destroy();
-        }
-        super.onDestroy();
-    }
-}
diff --git a/tests/src/android/widget/cts/AdapterViewStubActivity.java b/tests/src/android/widget/cts/AdapterViewStubActivity.java
deleted file mode 100644
index edcf13d..0000000
--- a/tests/src/android/widget/cts/AdapterViewStubActivity.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2008 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.widget.cts;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
-
-import com.android.cts.stub.R;
-
-/**
- * A minimal application for AdapterView test.
- */
-public class AdapterViewStubActivity extends Activity {
-    private ListView mView;
-
-    /**
-     * Called with the activity is first created.
-     */
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        mView = new ListView(this);
-        mView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
-                LayoutParams.WRAP_CONTENT));
-        setContentView(mView);
-    }
-
-    public ListView getListView() {
-        return mView;
-    }
-
-    public ArrayAdapter<String> getArrayAdapter() {
-        final List<String> list = new ArrayList<String>();
-        for (int i = 0; i < 4; i++) {
-            list.add("test:" + i);
-        }
-        return new ArrayAdapter<String>(this, R.layout.adapterview_layout, list);
-    }
-}
diff --git a/tests/src/android/widget/cts/AutoCompleteStubActivity.java b/tests/src/android/widget/cts/AutoCompleteStubActivity.java
deleted file mode 100644
index a23b6eb..0000000
--- a/tests/src/android/widget/cts/AutoCompleteStubActivity.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2008 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.widget.cts;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-import com.android.cts.stub.R;
-
-/**
- * A minimal application for AutoCompleteTextView test.
- */
-public class AutoCompleteStubActivity extends Activity {
-    /**
-     * Called with the activity is first created.
-     */
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.autocompletetextview_layout);
-    }
-}
diff --git a/tests/src/android/widget/cts/CheckedTextViewStubActivity.java b/tests/src/android/widget/cts/CheckedTextViewStubActivity.java
deleted file mode 100644
index 1c8d63e..0000000
--- a/tests/src/android/widget/cts/CheckedTextViewStubActivity.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2009 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.widget.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-/**
- * A minimal application for CheckedTextView test.
- */
-public class CheckedTextViewStubActivity extends Activity {
-    /**
-     * Called with the activity is first created.
-     */
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.checkedtextview_layout);
-    }
-}
diff --git a/tests/src/android/widget/cts/ChronometerStubActivity.java b/tests/src/android/widget/cts/ChronometerStubActivity.java
deleted file mode 100644
index f72a427..0000000
--- a/tests/src/android/widget/cts/ChronometerStubActivity.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2008 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.widget.cts;
-
-import com.android.cts.stub.R;
-import android.app.Activity;
-import android.os.Bundle;
-import android.view.ViewGroup;
-import android.widget.Chronometer;
-
-public class ChronometerStubActivity extends Activity {
-
-    private Chronometer chronometer;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.chronometer_stub_layout);
-        chronometer = (Chronometer) findViewById(R.id.test_chronometer);
-    }
-
-    public Chronometer getChronometer() {
-        return chronometer;
-    }
-
-    public ViewGroup getViewGroup() {
-        return (ViewGroup) findViewById(R.id.chronometer_view_group);
-    }
-
-}
-
diff --git a/tests/src/android/widget/cts/DialerFilterStubActivity.java b/tests/src/android/widget/cts/DialerFilterStubActivity.java
deleted file mode 100644
index b67803a..0000000
--- a/tests/src/android/widget/cts/DialerFilterStubActivity.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2008 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.widget.cts;
-
-import android.app.Activity;
-import android.os.Bundle;
-import com.android.cts.stub.R;
-
-/**
- * A minimal application for DialerFilter test.
- */
-public class DialerFilterStubActivity extends Activity {
-    /**
-     * Called with the activity is first created.
-     */
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.dialerfilter_layout);
-    }
-}
diff --git a/tests/src/android/widget/cts/DigitalClockStubActivity.java b/tests/src/android/widget/cts/DigitalClockStubActivity.java
deleted file mode 100644
index 2351bc2..0000000
--- a/tests/src/android/widget/cts/DigitalClockStubActivity.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2008 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.widget.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-/**
- * A minimal application for TextView test.
- */
-public class DigitalClockStubActivity extends Activity {
-    /**
-     * Called with the activity is first created.
-     */
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.digitalclock_simplelayout);
-    }
-}
diff --git a/tests/src/android/widget/cts/FrameLayoutStubActivity.java b/tests/src/android/widget/cts/FrameLayoutStubActivity.java
deleted file mode 100644
index 76482da..0000000
--- a/tests/src/android/widget/cts/FrameLayoutStubActivity.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2008 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.widget.cts;
-
-import android.app.Activity;
-import android.os.Bundle;
-import com.android.cts.stub.R;
-
-/**
- * A minimal application for frame layout test.
- */
-public class FrameLayoutStubActivity extends Activity {
-    /**
-     * Called with the activity is first created.
-     */
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.framelayout_layout);
-    }
-}
-
diff --git a/tests/src/android/widget/cts/GalleryStubActivity.java b/tests/src/android/widget/cts/GalleryStubActivity.java
deleted file mode 100644
index 8e0dd93..0000000
--- a/tests/src/android/widget/cts/GalleryStubActivity.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2008 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.widget.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.content.Context;
-import android.os.Bundle;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.Gallery;
-import android.widget.ImageView;
-
-/**
- * A minimal application for {@link Gallery} test.
- */
-public class GalleryStubActivity extends Activity {
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.gallery_test);
-
-        Gallery gallery = (Gallery) findViewById(R.id.gallery_test);
-        ImageAdapter adapter = new ImageAdapter(this);
-        gallery.setAdapter(adapter);
-    }
-
-    private static class ImageAdapter extends BaseAdapter {
-        public ImageAdapter(Context c) {
-            mContext = c;
-        }
-
-        public int getCount() {
-            return mImageIds.length;
-        }
-
-        public Object getItem(int position) {
-            return position;
-        }
-
-        public long getItemId(int position) {
-            return position;
-        }
-
-        public View getView(int position, View convertView, ViewGroup parent) {
-            ImageView i = new ImageView(mContext);
-
-            i.setImageResource(mImageIds[position]);
-            i.setScaleType(ImageView.ScaleType.FIT_XY);
-            // let the item's width be 136, height be 88
-            i.setLayoutParams(new Gallery.LayoutParams(136, 88));
-
-            return i;
-        }
-
-        private Context mContext;
-
-        private Integer[] mImageIds = {
-                R.drawable.faces,
-                R.drawable.scenery,
-                R.drawable.testimage,
-                R.drawable.faces,
-                R.drawable.scenery,
-                R.drawable.testimage,
-                R.drawable.faces,
-                R.drawable.scenery,
-                R.drawable.testimage,
-        };
-    }
-}
diff --git a/tests/src/android/widget/cts/GridLayoutStubActivity.java b/tests/src/android/widget/cts/GridLayoutStubActivity.java
deleted file mode 100644
index 3fa0f28..0000000
--- a/tests/src/android/widget/cts/GridLayoutStubActivity.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2012 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.widget.cts;
-
-import android.app.Activity;
-import android.os.Bundle;
-import com.android.cts.stub.R;
-
-/**
- * A minimal application for {@link android.widget.GridLayout} test.
- */
-public class GridLayoutStubActivity extends Activity {
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.gridlayout_layout);
-    }
-}
diff --git a/tests/src/android/widget/cts/GridViewStubActivity.java b/tests/src/android/widget/cts/GridViewStubActivity.java
deleted file mode 100644
index f58b7df..0000000
--- a/tests/src/android/widget/cts/GridViewStubActivity.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2008 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.widget.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-/**
- * A minimal application for {@link GridView} test.
- */
-public class GridViewStubActivity extends Activity {
-    /**
-     * Called with the activity is first created.
-     */
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.gridview_layout);
-    }
-}
-
diff --git a/tests/src/android/widget/cts/HorizontalScrollViewStubActivity.java b/tests/src/android/widget/cts/HorizontalScrollViewStubActivity.java
deleted file mode 100644
index 8dd6911..0000000
--- a/tests/src/android/widget/cts/HorizontalScrollViewStubActivity.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2009 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.widget.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-public class HorizontalScrollViewStubActivity extends Activity {
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.horizontal_scrollview);
-    }
-}
diff --git a/tests/src/android/widget/cts/ImageViewStubActivity.java b/tests/src/android/widget/cts/ImageViewStubActivity.java
deleted file mode 100644
index 7b93168..0000000
--- a/tests/src/android/widget/cts/ImageViewStubActivity.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2008 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.widget.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-/**
- * A minimal application for {@link ImageView} test.
- */
-public class ImageViewStubActivity extends Activity {
-    /**
-     * Called with the activity is first created.
-     */
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.imageview_layout);
-    }
-}
-
diff --git a/tests/src/android/widget/cts/LayoutDirectionStubActivity.java b/tests/src/android/widget/cts/LayoutDirectionStubActivity.java
deleted file mode 100644
index 66f24f74..0000000
--- a/tests/src/android/widget/cts/LayoutDirectionStubActivity.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2012 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.widget.cts;
-
-import android.app.Activity;
-import android.os.Bundle;
-import com.android.cts.stub.R;
-
-/**
- * A minimal application for layout direction test.
- */
-public class LayoutDirectionStubActivity extends Activity {
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.layoutdirection_layout);
-    }
-}
diff --git a/tests/src/android/widget/cts/LinearLayoutStubActivity.java b/tests/src/android/widget/cts/LinearLayoutStubActivity.java
deleted file mode 100644
index 8f4c5da..0000000
--- a/tests/src/android/widget/cts/LinearLayoutStubActivity.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2008 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.widget.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-/**
- * A minimal application for {@link LinearLayout} test.
- */
-public class LinearLayoutStubActivity extends Activity {
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.linearlayout_layout);
-    }
-}
diff --git a/tests/src/android/widget/cts/ListViewStubActivity.java b/tests/src/android/widget/cts/ListViewStubActivity.java
deleted file mode 100644
index 77c3e5e..0000000
--- a/tests/src/android/widget/cts/ListViewStubActivity.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2009 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.widget.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-public class ListViewStubActivity extends Activity {
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.listview_layout);
-    }
-}
diff --git a/tests/src/android/widget/cts/MediaControllerStubActivity.java b/tests/src/android/widget/cts/MediaControllerStubActivity.java
deleted file mode 100644
index 0e353be..0000000
--- a/tests/src/android/widget/cts/MediaControllerStubActivity.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2008 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.widget.cts;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.widget.MediaController;
-
-import com.android.cts.stub.R;
-
-/**
- * A minimal application for {@link MediaController} test.
- */
-public class MediaControllerStubActivity extends Activity {
-    /**
-     * Called with the activity is first created.
-     */
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.mediacontroller_layout);
-    }
-}
diff --git a/tests/src/android/widget/cts/MockPopupWindowStubActivity.java b/tests/src/android/widget/cts/MockPopupWindowStubActivity.java
deleted file mode 100644
index 2ca81de..0000000
--- a/tests/src/android/widget/cts/MockPopupWindowStubActivity.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2008 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.widget.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.widget.PopupWindow;
-
-/**
- * Stub activity for testing {@link PopupWindow}
- */
-public class MockPopupWindowStubActivity extends Activity {
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.popupwindow);
-    }
-}
-
diff --git a/tests/src/android/widget/cts/MultiAutoCompleteTextViewStubActivity.java b/tests/src/android/widget/cts/MultiAutoCompleteTextViewStubActivity.java
deleted file mode 100644
index fa973a6..0000000
--- a/tests/src/android/widget/cts/MultiAutoCompleteTextViewStubActivity.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2009 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.widget.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-/**
- * A minimal application for MultiAutoCompleteTextView test.
- */
-public class MultiAutoCompleteTextViewStubActivity extends Activity {
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.multi_auto_complete_text_view_layout);
-    }
-}
diff --git a/tests/src/android/widget/cts/ProgressBarStubActivity.java b/tests/src/android/widget/cts/ProgressBarStubActivity.java
deleted file mode 100644
index 57cfa1a..0000000
--- a/tests/src/android/widget/cts/ProgressBarStubActivity.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2008 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.widget.cts;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-/**
- * An application for ProgressBar test
- *
- */
-public class ProgressBarStubActivity extends Activity {
-    /**
-     * Called with the activity is first created.
-     */
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-    }
-}
diff --git a/tests/src/android/widget/cts/RatingBarStubActivity.java b/tests/src/android/widget/cts/RatingBarStubActivity.java
deleted file mode 100644
index 9635252..0000000
--- a/tests/src/android/widget/cts/RatingBarStubActivity.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2008 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.widget.cts;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-import com.android.cts.stub.R;
-
-/**
- * An application for ProgressBar test
- *
- */
-public class RatingBarStubActivity extends Activity {
-    /**
-     * Called with the activity is first created.
-     */
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.ratingbar_layout);
-    }
-}
diff --git a/tests/src/android/widget/cts/RelativeLayoutStubActivity.java b/tests/src/android/widget/cts/RelativeLayoutStubActivity.java
deleted file mode 100644
index d4bd474..0000000
--- a/tests/src/android/widget/cts/RelativeLayoutStubActivity.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2008 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.widget.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-/**
- * A minimal application for RelativeLayout test.
- */
-public class RelativeLayoutStubActivity extends Activity {
-    /**
-     * Called with the activity is first created.
-     */
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.relative_layout);
-    }
-}
-
diff --git a/tests/src/android/widget/cts/RemoteViewsStubActivity.java b/tests/src/android/widget/cts/RemoteViewsStubActivity.java
deleted file mode 100644
index f16ae13..0000000
--- a/tests/src/android/widget/cts/RemoteViewsStubActivity.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2008 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.widget.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.webkit.cts.NullWebViewUtils;
-import android.widget.RemoteViews;
-
-/**
- * Stub activity for testing {@link RemoteViews}
- */
-public class RemoteViewsStubActivity extends Activity {
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        try {
-            super.onCreate(savedInstanceState);
-            setContentView(R.layout.remoteviews_host);
-        } catch (Exception e) {
-            NullWebViewUtils.determineIfWebViewAvailable(this, e);
-        }
-    }
-}
diff --git a/tests/src/android/widget/cts/ScrollViewStubActivity.java b/tests/src/android/widget/cts/ScrollViewStubActivity.java
deleted file mode 100644
index 4daeb9f..0000000
--- a/tests/src/android/widget/cts/ScrollViewStubActivity.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2009 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.widget.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-public class ScrollViewStubActivity extends Activity {
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.scrollview_layout);
-    }
-}
diff --git a/tests/src/android/widget/cts/SeekBarStubActivity.java b/tests/src/android/widget/cts/SeekBarStubActivity.java
deleted file mode 100644
index 84274dc..0000000
--- a/tests/src/android/widget/cts/SeekBarStubActivity.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2008 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.widget.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.view.View;
-import android.widget.SeekBar;
-
-/**
- * Stub activity for testing {@link SeekBar}
- */
-public class SeekBarStubActivity extends Activity {
-    /**
-     * Called with the activity is first created.
-     */
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.seekbar);
-
-        View v = findViewById(R.id.seekBar);
-        v.setEnabled(true);
-        v.setFocusable(true);
-        v.setFocusableInTouchMode(true);
-        v.requestFocus();
-    }
-}
diff --git a/tests/src/android/widget/cts/SlidingDrawerStubActivity.java b/tests/src/android/widget/cts/SlidingDrawerStubActivity.java
deleted file mode 100644
index d19b9b1..0000000
--- a/tests/src/android/widget/cts/SlidingDrawerStubActivity.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2009 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.widget.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-public class SlidingDrawerStubActivity extends Activity {
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.sliding_drawer_layout);
-    }
-}
diff --git a/tests/src/android/widget/cts/StubActivity.java b/tests/src/android/widget/cts/StubActivity.java
deleted file mode 100644
index fe4002c..0000000
--- a/tests/src/android/widget/cts/StubActivity.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2009 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.widget.cts;
-
-import android.app.Activity;
-
-/**
- * Stub activity for helping test. It's an empty activity.
- */
-public class StubActivity extends Activity {
-
-}
diff --git a/tests/src/android/widget/cts/TabHostStubActivity.java b/tests/src/android/widget/cts/TabHostStubActivity.java
deleted file mode 100644
index 78e08941..0000000
--- a/tests/src/android/widget/cts/TabHostStubActivity.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2009 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.widget.cts;
-
-import android.app.TabActivity;
-import android.os.Bundle;
-import android.view.View;
-import android.widget.TabHost;
-import android.widget.TextView;
-
-import com.android.cts.stub.R;
-
-/**
- * A minimal application for TabHost test.
- * It contains an initial tab whose tag is INITIAL_TAB_TAG and label is INITIAL_TAB_LABEL.
- */
-public class TabHostStubActivity extends TabActivity {
-    public static final String INITIAL_TAB_TAG = "initial tag";
-    public static final String INITIAL_TAB_LABEL = "initial label";
-    public static final String INITIAL_VIEW_TEXT = "initial view text";
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.tabhost_layout);
-
-        TabHost tabHost = getTabHost();
-
-        // at least one tab
-        tabHost.addTab(tabHost.newTabSpec(INITIAL_TAB_TAG)
-                .setIndicator(INITIAL_TAB_LABEL)
-                .setContent(new MyTabContentFactory()));
-    }
-
-    private class MyTabContentFactory implements TabHost.TabContentFactory {
-        public View createTabContent(String tag) {
-            final TextView tv = new TextView(getApplicationContext());
-            tv.setText(INITIAL_VIEW_TEXT);
-            return tv;
-        }
-    }
-}
diff --git a/tests/src/android/widget/cts/TableStubActivity.java b/tests/src/android/widget/cts/TableStubActivity.java
deleted file mode 100644
index 0edc513..0000000
--- a/tests/src/android/widget/cts/TableStubActivity.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2008 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.widget.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-/**
- * A minimal application for TableLayout test.
- */
-public class TableStubActivity extends Activity {
-    /**
-     * Called with the activity is first created.
-     */
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.table_layout_1);
-    }
-}
diff --git a/tests/src/android/widget/cts/TextViewStubActivity.java b/tests/src/android/widget/cts/TextViewStubActivity.java
deleted file mode 100644
index 956e264..0000000
--- a/tests/src/android/widget/cts/TextViewStubActivity.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2008 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.widget.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-/**
- * A minimal application for TextView test.
- */
-public class TextViewStubActivity extends Activity {
-    /**
-     * Called with the activity is first created.
-     */
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.textview_layout);
-    }
-}
-
diff --git a/tests/src/android/widget/cts/TwoLineListItemStubActivity.java b/tests/src/android/widget/cts/TwoLineListItemStubActivity.java
deleted file mode 100644
index 380cefb..0000000
--- a/tests/src/android/widget/cts/TwoLineListItemStubActivity.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2008 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.widget.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.widget.TwoLineListItem;
-
-/**
- * Stub activity for testing {@link TwoLineListItem}
- */
-public class TwoLineListItemStubActivity extends Activity {
-    /**
-     * Called with the activity is first created.
-     */
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.twolinelistitem);
-    }
-}
diff --git a/tests/src/android/widget/cts/VideoViewStubActivity.java b/tests/src/android/widget/cts/VideoViewStubActivity.java
deleted file mode 100644
index 73c7756..0000000
--- a/tests/src/android/widget/cts/VideoViewStubActivity.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2009 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.widget.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.widget.VideoView;
-
-/**
- * A minimal application for {@link VideoView} test.
- */
-public class VideoViewStubActivity extends Activity {
-    /**
-     * Called with the activity is first created.
-     */
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.videoview_layout);
-    }
-}
diff --git a/tests/src/android/widget/cts/ViewAnimatorStubActivity.java b/tests/src/android/widget/cts/ViewAnimatorStubActivity.java
deleted file mode 100644
index 634f531..0000000
--- a/tests/src/android/widget/cts/ViewAnimatorStubActivity.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2008 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.widget.cts;
-
-import android.app.Activity;
-import android.os.Bundle;
-import com.android.cts.stub.R;
-
-/**
- * A minimal application for ViewAnimator test.
- */
-public class ViewAnimatorStubActivity extends Activity {
-    /**
-     * Called with the activity is first created.
-     */
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.viewanimator_layout);
-    }
-}
-
diff --git a/tests/src/android/widget/cts/ViewFlipperStubActivity.java b/tests/src/android/widget/cts/ViewFlipperStubActivity.java
deleted file mode 100644
index 2ac331e..0000000
--- a/tests/src/android/widget/cts/ViewFlipperStubActivity.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2008 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.widget.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-public class ViewFlipperStubActivity extends Activity {
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        setContentView(R.layout.viewflipper_layout);
-    }
-}
-
diff --git a/tests/src/android/widget/cts/ViewGroupStubActivity.java b/tests/src/android/widget/cts/ViewGroupStubActivity.java
deleted file mode 100644
index 346c067..0000000
--- a/tests/src/android/widget/cts/ViewGroupStubActivity.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2008 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.widget.cts;
-
-import android.app.Activity;
-import android.app.cts.CTSResult;
-import android.os.Bundle;
-import android.os.Handler;
-import android.widget.TextView;
-
-public class ViewGroupStubActivity extends Activity {
-
-    public static final String ACTION_INVALIDATE_CHILD = "invalidateChild";
-
-    private final Handler mHandler = new Handler();
-    private static CTSResult sResult;
-    public static void setResult(CTSResult result) {
-        sResult = result;
-    }
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(com.android.cts.stub.R.layout.viewgrouptest_stub);
-        TextView textView = (TextView)findViewById(com.android.cts.stub.R.id.viewgrouptest_stub);
-        textView.setText("test");
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-
-        String action = getIntent().getAction();
-        if (action.equals(ACTION_INVALIDATE_CHILD)) {
-            mHandler.postDelayed(new Runnable() {
-                public void run() {
-                    MockLinearLayout mll =
-                        (MockLinearLayout) findViewById(com.android.cts.stub.R.id.
-                                                                        mocklinearlayout);
-                    if (!mll.mIsInvalidateChildInParentCalled) {
-                        fail();
-                        return;
-                    }
-                    sResult.setResult(CTSResult.RESULT_OK);
-                    finish();
-                }
-            }, 2000);
-        }
-    }
-
-    private void fail() {
-        sResult.setResult(CTSResult.RESULT_FAIL);
-        finish();
-    }
-}
-
diff --git a/tests/src/android/widget/cts/WidgetTestUtils.java b/tests/src/android/widget/cts/WidgetTestUtils.java
deleted file mode 100644
index 2df6629..0000000
--- a/tests/src/android/widget/cts/WidgetTestUtils.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2008 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.widget.cts;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-
-import java.io.IOException;
-
-import junit.framework.Assert;
-
-/**
- * The useful methods for widget test.
- */
-public class WidgetTestUtils {
-    /**
-     * Assert that two bitmaps are equal.
-     *
-     * @param Bitmap b1 the first bitmap which needs to compare.
-     * @param Bitmap b2 the second bitmap which needs to compare.
-     */
-    public static void assertEquals(Bitmap b1, Bitmap b2) {
-        if (b1 == b2) {
-            return;
-        }
-
-        if (b1 == null || b2 == null) {
-            Assert.fail("the bitmaps are not equal");
-        }
-
-        // b1 and b2 are all not null.
-        if (b1.getWidth() != b2.getWidth() || b1.getHeight() != b2.getHeight()
-            || b1.getConfig() != b2.getConfig()) {
-            Assert.fail("the bitmaps are not equal");
-        }
-
-        int w = b1.getWidth();
-        int h = b1.getHeight();
-        int s = w * h;
-        int[] pixels1 = new int[s];
-        int[] pixels2 = new int[s];
-
-        b1.getPixels(pixels1, 0, w, 0, 0, w, h);
-        b2.getPixels(pixels2, 0, w, 0, 0, w, h);
-
-        for (int i = 0; i < s; i++) {
-            if (pixels1[i] != pixels2[i]) {
-                Assert.fail("the bitmaps are not equal");
-            }
-        }
-    }
-
-    /**
-     * Find beginning of the special element.
-     * @param parser XmlPullParser will be parsed.
-     * @param firstElementName the target element name.
-     *
-     * @throws XmlPullParserException if XML Pull Parser related faults occur.
-     * @throws IOException if I/O-related error occur when parsing.
-     */
-    public static final void beginDocument(XmlPullParser parser, String firstElementName)
-            throws XmlPullParserException, IOException {
-        Assert.assertNotNull(parser);
-        Assert.assertNotNull(firstElementName);
-
-        int type;
-        while ((type = parser.next()) != XmlPullParser.START_TAG
-                && type != XmlPullParser.END_DOCUMENT) {
-            ;
-        }
-
-        if (!parser.getName().equals(firstElementName)) {
-            throw new XmlPullParserException("Unexpected start tag: found " + parser.getName()
-                    + ", expected " + firstElementName);
-        }
-    }
-
-    /**
-     * Compare the expected pixels with actual, scaling for the target context density
-     *
-     * @throws AssertionFailedError
-     */
-    public static void assertScaledPixels(int expected, int actual, Context context) {
-        Assert.assertEquals(expected * context.getResources().getDisplayMetrics().density,
-                actual, 3);
-    }
-
-    /** Converts dips into pixels using the {@link Context}'s density. */
-    public static int convertDipToPixels(Context context, int dip) {
-      float density = context.getResources().getDisplayMetrics().density;
-      return Math.round(density * dip);
-    }
-
-    /**
-     * Retrieve a bitmap that can be used for comparison on any density
-     * @param resources
-     * @return the {@link Bitmap} or <code>null</code>
-     */
-    public static Bitmap getUnscaledBitmap(Resources resources, int resId) {
-        BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inScaled = false;
-        return BitmapFactory.decodeResource(resources, resId, options);
-    }
-
-    /**
-     * Retrieve a dithered bitmap that can be used for comparison on any density
-     * @param resources
-     * @param config the preferred config for the returning bitmap
-     * @return the {@link Bitmap} or <code>null</code>
-     */
-    public static Bitmap getUnscaledAndDitheredBitmap(Resources resources,
-            int resId, Bitmap.Config config) {
-        BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inDither = true;
-        options.inScaled = false;
-        options.inPreferredConfig = config;
-        return BitmapFactory.decodeResource(resources, resId, options);
-    }
-}
diff --git a/tests/src/android/widget/cts/ZoomButtonStubActivity.java b/tests/src/android/widget/cts/ZoomButtonStubActivity.java
deleted file mode 100644
index a49df7a..0000000
--- a/tests/src/android/widget/cts/ZoomButtonStubActivity.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2009 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.widget.cts;
-
-import com.android.cts.stub.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-/**
- * A minimal application for {@link ZoomButton} test.
- */
-public class ZoomButtonStubActivity extends Activity {
-    /**
-     * Called with the activity is first created.
-     */
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.zoombutton_layout);
-    }
-}
diff --git a/tests/systemAppTest/test/Android.mk b/tests/systemAppTest/test/Android.mk
index 3354886..9be491c 100644
--- a/tests/systemAppTest/test/Android.mk
+++ b/tests/systemAppTest/test/Android.mk
@@ -24,8 +24,6 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_APPS_PRIVILEGED)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner ctsdeviceutil
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/acceleration/Android.mk b/tests/tests/acceleration/Android.mk
index 30a1f51..d417371 100644
--- a/tests/tests/acceleration/Android.mk
+++ b/tests/tests/acceleration/Android.mk
@@ -20,8 +20,6 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/acceleration/AndroidManifest.xml b/tests/tests/acceleration/AndroidManifest.xml
index d08827e..0dd2722 100644
--- a/tests/tests/acceleration/AndroidManifest.xml
+++ b/tests/tests/acceleration/AndroidManifest.xml
@@ -24,8 +24,11 @@
       <uses-library android:name="android.test.runner" />
   </application>
 
-  <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+  <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                    android:targetPackage="com.android.cts.acceleration.stub"
-                   android:label="Tests for the Hardware Acceleration APIs." />
+                   android:label="Tests for the Hardware Acceleration APIs." >
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
diff --git a/tests/tests/accessibility/Android.mk b/tests/tests/accessibility/Android.mk
index abd6f4b..9f98b16 100644
--- a/tests/tests/accessibility/Android.mk
+++ b/tests/tests/accessibility/Android.mk
@@ -20,8 +20,6 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsAccessibilityTestCases
diff --git a/tests/tests/accessibility/AndroidManifest.xml b/tests/tests/accessibility/AndroidManifest.xml
index 53b9cc3..319fb49 100644
--- a/tests/tests/accessibility/AndroidManifest.xml
+++ b/tests/tests/accessibility/AndroidManifest.xml
@@ -24,8 +24,11 @@
       <uses-library android:name="android.test.runner"/>
   </application>
 
-  <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+  <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                    android:targetPackage="android.view.cts.accessibility"
-                   android:label="Tests for the accessibility APIs."/>
+                   android:label="Tests for the accessibility APIs.">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
diff --git a/tests/tests/accessibility/res/values/ids.xml b/tests/tests/accessibility/res/values/ids.xml
new file mode 100644
index 0000000..23edb2b8
--- /dev/null
+++ b/tests/tests/accessibility/res/values/ids.xml
@@ -0,0 +1,18 @@
+<!-- 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.
+-->
+
+<resources>
+    <item type="id" name="foo_custom_action" />
+</resources>
diff --git a/tests/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java b/tests/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java
index ae7cc9b..87f0238 100644
--- a/tests/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java
+++ b/tests/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java
@@ -23,6 +23,11 @@
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
+import android.view.cts.accessibility.R;
+
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Class for testing {@link AccessibilityNodeInfo}.
@@ -30,7 +35,7 @@
 public class AccessibilityNodeInfoTest extends AndroidTestCase {
 
     /** The number of properties of the {@link AccessibilityNodeInfo} class. */
-    private static final int NON_STATIC_FIELD_COUNT = 26;
+    private static final int NON_STATIC_FIELD_COUNT = 28;
 
     @SmallTest
     public void testMarshaling() throws Exception {
@@ -94,6 +99,70 @@
     }
 
     /**
+     * Tests whether accessibility actions are properly added.
+     */
+    @SmallTest
+    public void testAddActions() {
+        List<AccessibilityAction> customActions = new ArrayList<AccessibilityAction>();
+        customActions.add(new AccessibilityAction(AccessibilityNodeInfo.ACTION_FOCUS, "Foo"));
+        customActions.add(new AccessibilityAction(R.id.foo_custom_action, "Foo"));
+
+        AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
+        info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
+        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
+        for (AccessibilityAction customAction : customActions) {
+            info.addAction(customAction);
+        }
+
+        assertSame(info.getActions(), (AccessibilityNodeInfo.ACTION_FOCUS
+                | AccessibilityNodeInfo.ACTION_CLEAR_FOCUS));
+
+        List<AccessibilityAction> allActions = new ArrayList<AccessibilityAction>();
+        allActions.add(AccessibilityAction.ACTION_CLEAR_FOCUS);
+        allActions.addAll(customActions);
+        assertEquals(info.getActionList(), allActions);
+    }
+
+    /**
+     * Tests whether we catch addition of an action with invalid id.
+     */
+    @SmallTest
+    public void testCreateInvalidActionId() {
+        try {
+            new AccessibilityAction(3, null);
+        } catch (IllegalArgumentException iae) {
+            /* expected */
+        }
+    }
+
+    /**
+     * Tests whether accessibility actions are properly removed.
+     */
+    @SmallTest
+    public void testRemoveActions() {
+        AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
+
+        info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
+        assertSame(info.getActions(), AccessibilityNodeInfo.ACTION_FOCUS);
+
+        info.removeAction(AccessibilityNodeInfo.ACTION_FOCUS);
+        assertSame(info.getActions(), 0);
+        assertTrue(info.getActionList().isEmpty());
+
+        AccessibilityAction customFocus = new AccessibilityAction(
+                AccessibilityNodeInfo.ACTION_FOCUS, "Foo");
+        info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
+        info.addAction(customFocus);
+        assertSame(info.getActionList().size(), 1);
+        assertEquals(info.getActionList().get(0), customFocus);
+        assertSame(info.getActions(), AccessibilityNodeInfo.ACTION_FOCUS);
+
+        info.removeAction(customFocus);
+        assertSame(info.getActions(), 0);
+        assertTrue(info.getActionList().isEmpty());
+    }
+
+    /**
      * Fully populates the {@link AccessibilityNodeInfo} to marshal.
      *
      * @param info The node info to populate.
@@ -119,7 +188,10 @@
         info.setPassword(true);
         info.setScrollable(true);
         info.setSelected(true);
+        info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
+        info.addAction(new AccessibilityAction(AccessibilityNodeInfo.ACTION_FOCUS, "Foo"));
+        info.addAction(new AccessibilityAction(R.id.foo_custom_action, "Foo"));
         info.setAccessibilityFocused(true);
         info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
         info.setLabeledBy(new View(getContext()));
@@ -171,6 +243,8 @@
                 receivedInfo.isSelected());
         assertSame("actions has incorrect value", expectedInfo.getActions(),
                 receivedInfo.getActions());
+        assertEquals("actionsSet has incorrect value", expectedInfo.getActionList(),
+                receivedInfo.getActionList());
         assertSame("childCount has incorrect value", expectedInfo.getChildCount(),
                 receivedInfo.getChildCount());
         assertSame("childCount has incorrect value", expectedInfo.getChildCount(),
diff --git a/tests/tests/accessibility/src/android/view/accessibility/cts/AccessibilityRecordTest.java b/tests/tests/accessibility/src/android/view/accessibility/cts/AccessibilityRecordTest.java
index 3aaf54e..7862cb4 100644
--- a/tests/tests/accessibility/src/android/view/accessibility/cts/AccessibilityRecordTest.java
+++ b/tests/tests/accessibility/src/android/view/accessibility/cts/AccessibilityRecordTest.java
@@ -204,7 +204,7 @@
     static void assertNoNewNonStaticFieldsAdded(Class<?> clazz, int expectedCount) {
         int nonStaticFieldCount = 0;
 
-        while (clazz != null) {
+        while (clazz != Object.class) {
             for (Field field : clazz.getDeclaredFields()) {
                 if ((field.getModifiers() & Modifier.STATIC) == 0) {
                     nonStaticFieldCount++;
diff --git a/tests/tests/accessibilityservice/Android.mk b/tests/tests/accessibilityservice/Android.mk
index 73cd288..b27dbcc 100644
--- a/tests/tests/accessibilityservice/Android.mk
+++ b/tests/tests/accessibilityservice/Android.mk
@@ -18,12 +18,12 @@
 
 LOCAL_MODULE_TAGS := optional
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsAccessibilityServiceTestCases
 
+LOCAL_SDK_VERSION := current
+
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/accessibilityservice/AndroidManifest.xml b/tests/tests/accessibilityservice/AndroidManifest.xml
index 13c44b5..e172913 100644
--- a/tests/tests/accessibilityservice/AndroidManifest.xml
+++ b/tests/tests/accessibilityservice/AndroidManifest.xml
@@ -19,9 +19,9 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.android.cts.accessibilityservice">
 
-  <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
 
-  <application android:theme="@android:style/Theme.Holo.NoActionBar" >
+    <application android:theme="@android:style/Theme.Holo.NoActionBar" >
 
       <uses-library android:name="android.test.runner"/>
 
@@ -42,8 +42,11 @@
 
   </application>
 
-  <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+  <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                    android:targetPackage="com.android.cts.accessibilityservice"
-                   android:label="Tests for the accessibility APIs."/>
+                   android:label="Tests for the accessibility APIs.">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
diff --git a/tests/tests/accessibilityservice/res/values/ids.xml b/tests/tests/accessibilityservice/res/values/ids.xml
new file mode 100644
index 0000000..23edb2b8
--- /dev/null
+++ b/tests/tests/accessibilityservice/res/values/ids.xml
@@ -0,0 +1,18 @@
+<!-- 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.
+-->
+
+<resources>
+    <item type="id" name="foo_custom_action" />
+</resources>
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
index f0f0dd7..39b116a 100644
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
+++ b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEndToEndTest.java
@@ -46,10 +46,8 @@
 
     /**
      * Creates a new instance for testing {@link AccessibilityEndToEndActivity}.
-     *
-     * @throws Exception If any error occurs.
      */
-    public AccessibilityEndToEndTest() throws Exception {
+    public AccessibilityEndToEndTest() {
         super(AccessibilityEndToEndActivity.class);
     }
 
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTestActivity.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTestActivity.java
index 4d9b97d..42a4375 100644
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTestActivity.java
+++ b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTestActivity.java
@@ -25,6 +25,7 @@
         super.onCreate(savedInstanceState);
 
         getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
-                | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
+                | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
+                | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
     }
 }
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalTest.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalTest.java
index bdc0cd5..cb0877d 100644
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalTest.java
+++ b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalTest.java
@@ -4532,7 +4532,7 @@
                 AccessibilityNodeInfo.ACTION_PASTE));
 
         // Verify the content.
-        assertEquals(editText.getText().toString(), textContent + " " + textContent);
+        assertEquals(editText.getText().toString(), textContent + textContent);
 
         // Select all text.
         arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 0);
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryActivity.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryActivity.java
index b0cedf6..aa66a45 100644
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryActivity.java
+++ b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryActivity.java
@@ -17,13 +17,15 @@
 import android.os.Bundle;
 import android.view.View;
 
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 import com.android.cts.accessibilityservice.R;
 
 /**
  * Activity for testing the accessibility APIs for querying of
  * the screen content. These APIs allow exploring the screen and
  * requesting an action to be performed on a given view from an
- * AccessiiblityService.
+ * AccessibilityService.
  */
 public class AccessibilityWindowQueryActivity extends AccessibilityTestActivity {
 
@@ -42,5 +44,21 @@
                 return true;
             }
         });
+
+        findViewById(R.id.button5).setAccessibilityDelegate(new View.AccessibilityDelegate() {
+            @Override
+            public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
+                super.onInitializeAccessibilityNodeInfo(host, info);
+                info.addAction(new AccessibilityAction(R.id.foo_custom_action, "Foo"));
+            }
+
+            @Override
+            public boolean performAccessibilityAction(View host, int action, Bundle args) {
+                if (action == R.id.foo_custom_action) {
+                    return true;
+                }
+                return super.performAccessibilityAction(host, action, args);
+            }
+        });
     }
 }
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java
index 492b99b..f8cf4dd 100644
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java
+++ b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryTest.java
@@ -27,25 +27,34 @@
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.app.UiAutomation;
 import android.graphics.Rect;
+import android.os.SystemClock;
 import android.test.suitebuilder.annotation.MediumTest;
+import android.view.Gravity;
+import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
+import android.view.accessibility.AccessibilityWindowInfo;
 
+import android.widget.Button;
 import com.android.cts.accessibilityservice.R;
 
 import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Queue;
+import java.util.concurrent.TimeoutException;
 
 /**
  * Test cases for testing the accessibility APIs for querying of the screen content.
  * These APIs allow exploring the screen and requesting an action to be performed
- * on a given view from an AccessiiblityService.
+ * on a given view from an AccessibilityService.
  */
 public class AccessibilityWindowQueryTest
         extends AccessibilityActivityTestCase<AccessibilityWindowQueryActivity> {
 
+    private static final long TIMEOUT_WINDOW_STATE_IDLE = 500;
+
     public AccessibilityWindowQueryTest() {
         super(AccessibilityWindowQueryActivity.class);
     }
@@ -69,62 +78,221 @@
 
     @MediumTest
     public void testTraverseWindow() throws Exception {
+        verifyNodesInAppWindow(getInstrumentation().getUiAutomation().getRootInActiveWindow());
+    }
+
+    @MediumTest
+    public void testNoWindowsAccessIfFlagNotSet() throws Exception {
+        // Make sure the windows cannot be accessed.
+        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
+        assertTrue(uiAutomation.getWindows().isEmpty());
+
+        // Find a button to click on.
+        final AccessibilityNodeInfo button1 = uiAutomation.getRootInActiveWindow()
+                .findAccessibilityNodeInfosByViewId(
+                        "com.android.cts.accessibilityservice:id/button1").get(0);
+
+        // Argh...
+        final List<AccessibilityEvent> events = new ArrayList<AccessibilityEvent>();
+
+        // Click the button.
+        uiAutomation.executeAndWaitForEvent(new Runnable() {
+            @Override
+            public void run() {
+                button1.performAction(AccessibilityNodeInfo.ACTION_CLICK);
+            }
+        },
+        new UiAutomation.AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_CLICKED) {
+                    events.add(event);
+                    return true;
+                }
+                return false;
+            }
+        },
+        TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure the source window cannot be accessed.
+        AccessibilityEvent event = events.get(0);
+        assertNull(event.getSource().getWindow());
+    }
+
+    @MediumTest
+    public void testTraverseAllWindows() throws Exception {
+        setAccessInteractiveWindowsFlag();
         try {
-            AccessibilityServiceInfo info = getInstrumentation().getUiAutomation().getServiceInfo();
-            info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
-            getInstrumentation().getUiAutomation().setServiceInfo(info);
+            UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
 
-            // make list of expected nodes
-            List<String> classNameAndTextList = new ArrayList<String>();
-            classNameAndTextList.add("android.widget.LinearLayout");
-            classNameAndTextList.add("android.widget.LinearLayout");
-            classNameAndTextList.add("android.widget.LinearLayout");
-            classNameAndTextList.add("android.widget.LinearLayout");
-            classNameAndTextList.add("android.widget.ButtonB1");
-            classNameAndTextList.add("android.widget.ButtonB2");
-            classNameAndTextList.add("android.widget.ButtonB3");
-            classNameAndTextList.add("android.widget.ButtonB4");
-            classNameAndTextList.add("android.widget.ButtonB5");
-            classNameAndTextList.add("android.widget.ButtonB6");
-            classNameAndTextList.add("android.widget.ButtonB7");
-            classNameAndTextList.add("android.widget.ButtonB8");
-            classNameAndTextList.add("android.widget.ButtonB9");
+            List<AccessibilityWindowInfo> windows = uiAutomation.getWindows();
+            Rect boundsInScreen = new Rect();
 
-            String contentViewIdResName = "com.android.cts.accessibilityservice:id/added_content";
-            boolean verifyContent = false;
+            final int windowCount = windows.size();
+            for (int i = 0; i < windowCount; i++) {
+                AccessibilityWindowInfo window = windows.get(i);
 
-            Queue<AccessibilityNodeInfo> fringe = new LinkedList<AccessibilityNodeInfo>();
-            fringe.add(getInstrumentation().getUiAutomation().getRootInActiveWindow());
+                window.getBoundsInScreen(boundsInScreen);
+                assertFalse(boundsInScreen.isEmpty()); // Varies on screen size, emptiness check.
+                assertNull(window.getParent());
+                assertSame(0, window.getChildCount());
+                assertNull(window.getParent());
+                assertNotNull(window.getRoot());
 
-            // do a BFS traversal and check nodes
-            while (!fringe.isEmpty()) {
-                AccessibilityNodeInfo current = fringe.poll();
-
-                if (!verifyContent
-                        && contentViewIdResName.equals(current.getViewIdResourceName())) {
-                    verifyContent = true;
-                }
-
-                if (verifyContent) {
-                    CharSequence text = current.getText();
-                    String receivedClassNameAndText = current.getClassName().toString()
-                            + ((text != null) ? text.toString() : "");
-                    String expectedClassNameAndText = classNameAndTextList.remove(0);
-
-                    assertEquals("Did not get the expected node info",
-                            expectedClassNameAndText, receivedClassNameAndText);
-                }
-
-                final int childCount = current.getChildCount();
-                for (int i = 0; i < childCount; i++) {
-                    AccessibilityNodeInfo child = current.getChild(i);
-                    fringe.add(child);
+                if (window.getType() == AccessibilityWindowInfo.TYPE_APPLICATION) {
+                    assertTrue(window.isFocused());
+                    assertTrue(window.isActive());
+                    verifyNodesInAppWindow(window.getRoot());
+                } else if (window.getType() == AccessibilityWindowInfo.TYPE_SYSTEM) {
+                    assertFalse(window.isFocused());
+                    assertFalse(window.isActive());
                 }
             }
         } finally {
-            AccessibilityServiceInfo info = getInstrumentation().getUiAutomation().getServiceInfo();
-            info.flags &= ~AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
-            getInstrumentation().getUiAutomation().setServiceInfo(info);
+            clearAccessInteractiveWindowsFlag();
+        }
+    }
+
+    @MediumTest
+    public void testTraverseWindowFromEvent() throws Exception {
+        setAccessInteractiveWindowsFlag();
+        try {
+            UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
+
+            // Find a button to click on.
+            final AccessibilityNodeInfo button1 = uiAutomation.getRootInActiveWindow()
+                    .findAccessibilityNodeInfosByViewId(
+                            "com.android.cts.accessibilityservice:id/button1").get(0);
+
+            // Argh...
+            final List<AccessibilityEvent> events = new ArrayList<AccessibilityEvent>();
+
+            // Click the button.
+            uiAutomation.executeAndWaitForEvent(new Runnable() {
+                @Override
+                public void run() {
+                    button1.performAction(AccessibilityNodeInfo.ACTION_CLICK);
+                }
+            },
+            new UiAutomation.AccessibilityEventFilter() {
+                @Override
+                public boolean accept(AccessibilityEvent event) {
+                    if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_CLICKED) {
+                        events.add(event);
+                        return true;
+                    }
+                    return false;
+                }
+            },
+            TIMEOUT_ASYNC_PROCESSING);
+
+            // Get the source window.
+            AccessibilityEvent event = events.get(0);
+            AccessibilityWindowInfo window = event.getSource().getWindow();
+
+            // Verify the application window.
+            Rect boundsInScreen = new Rect();
+            window.getBoundsInScreen(boundsInScreen);
+            assertFalse(boundsInScreen.isEmpty()); // Varies on screen size, so just emptiness check.
+            assertSame(window.getType(), AccessibilityWindowInfo.TYPE_APPLICATION);
+            assertTrue(window.isFocused());
+            assertTrue(window.isActive());
+            assertNull(window.getParent());
+            assertSame(0, window.getChildCount());
+            assertNotNull(window.getRoot());
+
+            // Verify the window content.
+            verifyNodesInAppWindow(window.getRoot());
+        } finally {
+            clearAccessInteractiveWindowsFlag();
+        }
+    }
+
+    @MediumTest
+    public void testInteractWithAppWindow() throws Exception {
+        setAccessInteractiveWindowsFlag();
+        try {
+            UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
+
+            // Find a button to click on.
+            final AccessibilityNodeInfo button1 = uiAutomation.getRootInActiveWindow()
+                    .findAccessibilityNodeInfosByViewId(
+                            "com.android.cts.accessibilityservice:id/button1").get(0);
+
+            // Argh...
+            final List<AccessibilityEvent> events = new ArrayList<AccessibilityEvent>();
+
+            // Click the button.
+            uiAutomation.executeAndWaitForEvent(new Runnable() {
+                @Override
+                public void run() {
+                    button1.performAction(AccessibilityNodeInfo.ACTION_CLICK);
+                }
+            },
+            new UiAutomation.AccessibilityEventFilter() {
+                @Override
+                public boolean accept(AccessibilityEvent event) {
+                    if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_CLICKED) {
+                        events.add(event);
+                        return true;
+                    }
+                    return false;
+                }
+            },
+            TIMEOUT_ASYNC_PROCESSING);
+
+            // Get the source window.
+            AccessibilityEvent event = events.get(0);
+            AccessibilityWindowInfo window = event.getSource().getWindow();
+
+            // Find a another button from the event's window.
+            final AccessibilityNodeInfo button2 = window.getRoot()
+                    .findAccessibilityNodeInfosByViewId(
+                            "com.android.cts.accessibilityservice:id/button2").get(0);
+
+            // Click the second button.
+            uiAutomation.executeAndWaitForEvent(new Runnable() {
+                @Override
+                public void run() {
+                    button2.performAction(AccessibilityNodeInfo.ACTION_CLICK);
+                }
+            },
+            new UiAutomation.AccessibilityEventFilter() {
+                @Override
+                public boolean accept(AccessibilityEvent event) {
+                    return event.getEventType() == AccessibilityEvent.TYPE_VIEW_CLICKED;
+                }
+            },
+            TIMEOUT_ASYNC_PROCESSING);
+        } finally {
+            clearAccessInteractiveWindowsFlag();
+        }
+    }
+
+    @MediumTest
+    public void testSingleAccessibilityFocusAcrossWindows() throws Exception {
+        setAccessInteractiveWindowsFlag();
+        try {
+            // Add two more windows.
+            addTwoAppPanelWindows();
+
+            // Put accessibility focus in the first app window.
+            ensureAppWindowFocusedOrFail(0);
+            // Make sure there only one accessibility focus.
+            assertSingleAccessibilityFocus();
+
+            // Put accessibility focus in the second app window.
+            ensureAppWindowFocusedOrFail(1);
+            // Make sure there only one accessibility focus.
+            assertSingleAccessibilityFocus();
+
+            // Put accessibility focus in the third app window.
+            ensureAppWindowFocusedOrFail(2);
+            // Make sure there only one accessibility focus.
+            assertSingleAccessibilityFocus();
+        } finally {
+            ensureAccessibilityFocusCleared();
+            clearAccessInteractiveWindowsFlag();
         }
     }
 
@@ -267,6 +435,28 @@
         assertNotNull(expected);
     }
 
+
+    @MediumTest
+    public void testPerformCustomAction() throws Exception {
+        // find a view and make sure it is not selected
+        AccessibilityNodeInfo button = getInstrumentation().getUiAutomation()
+                .getRootInActiveWindow().findAccessibilityNodeInfosByText(
+                        getString(R.string.button5)).get(0);
+
+        // find the custom action and perform it
+        List<AccessibilityAction> actions = button.getActionList();
+        final int actionCount = actions.size();
+        for (int i = 0; i < actionCount; i++) {
+            AccessibilityAction action = actions.get(i);
+            if (action.getId() == R.id.foo_custom_action) {
+                assertSame(action.getLabel(), "Foo");
+                // perform the action
+                assertTrue(button.performAction(action.getId()));
+                return;
+            }
+        }
+    }
+
     @MediumTest
     public void testGetEventSource() throws Exception {
         // find a view and make sure it is not focused
@@ -354,6 +544,10 @@
         // Sleep a bit so the UI is settles.
         waitForIdle();
 
+        // This is a necessary since the back action does not
+        // dismiss recents until they stop animating. Sigh...
+        SystemClock.sleep(5000);
+
         // Clean up.
         getInstrumentation().getUiAutomation().performGlobalAction(
                 AccessibilityService.GLOBAL_ACTION_BACK);
@@ -397,6 +591,23 @@
     }
 
     @MediumTest
+    public void testPerformGlobalActionPowerDialog() throws Exception {
+        // Check whether the action succeeded.
+        assertTrue(getInstrumentation().getUiAutomation().performGlobalAction(
+                AccessibilityService.GLOBAL_ACTION_POWER_DIALOG));
+
+        // Sleep a bit so the UI is settles.
+        waitForIdle();
+
+        // Clean up.
+        getInstrumentation().getUiAutomation().performGlobalAction(
+                AccessibilityService.GLOBAL_ACTION_BACK);
+
+        // Sleep a bit so the UI is settles.
+        waitForIdle();
+    }
+
+    @MediumTest
     public void testObjectContract() throws Exception {
         try {
             AccessibilityServiceInfo info = getInstrumentation().getUiAutomation().getServiceInfo();
@@ -426,6 +637,256 @@
         }
     }
 
+    private void assertSingleAccessibilityFocus() {
+        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
+        List<AccessibilityWindowInfo> windows = uiAutomation.getWindows();
+        AccessibilityWindowInfo focused = null;
+
+        final int windowCount = windows.size();
+        for (int i = 0; i < windowCount; i++) {
+            AccessibilityWindowInfo window = windows.get(i);
+
+            if (window.isAccessibilityFocused()) {
+                if (focused == null) {
+                    focused = window;
+
+                    AccessibilityNodeInfo root = window.getRoot();
+                    assertEquals(uiAutomation.findFocus(
+                            AccessibilityNodeInfo.FOCUS_ACCESSIBILITY), root);
+                    assertEquals(root.findFocus(
+                            AccessibilityNodeInfo.FOCUS_ACCESSIBILITY), root);
+                } else {
+                    throw new AssertionError("Duplicate accessibility focus");
+                }
+            } else {
+                assertNull(window.getRoot().findFocus(
+                        AccessibilityNodeInfo.FOCUS_ACCESSIBILITY));
+            }
+        }
+    }
+
+    private void ensureAppWindowFocusedOrFail(int appWindowIndex) throws TimeoutException {
+        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
+        List<AccessibilityWindowInfo> windows = uiAutomation.getWindows();
+        AccessibilityWindowInfo focusTareget = null;
+
+        int visitedAppWindows = -1;
+        final int windowCount = windows.size();
+        for (int i = 0; i < windowCount; i++) {
+            AccessibilityWindowInfo window = windows.get(i);
+            if (window.getType() == AccessibilityWindowInfo.TYPE_APPLICATION) {
+                visitedAppWindows++;
+                if (appWindowIndex <= visitedAppWindows) {
+                    focusTareget = window;
+                    break;
+                }
+            }
+        }
+
+        if (focusTareget == null) {
+            throw new IllegalStateException("Couldn't find app window: " + appWindowIndex);
+        }
+
+        if (focusTareget.isAccessibilityFocused()) {
+            return;
+        }
+
+        final AccessibilityWindowInfo finalFocusTarget = focusTareget;
+        uiAutomation.executeAndWaitForEvent(new Runnable() {
+            @Override
+            public void run() {
+                assertTrue(finalFocusTarget.getRoot().performAction(
+                        AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS));
+            }
+        }, new UiAutomation.AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return event.getEventType() == AccessibilityEvent.TYPE_WINDOWS_CHANGED;
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        windows = uiAutomation.getWindows();
+        for (int i = 0; i < windowCount; i++) {
+            AccessibilityWindowInfo window = windows.get(i);
+            if (window.getId() == focusTareget.getId()) {
+                assertTrue(window.isAccessibilityFocused());
+                break;
+            }
+        }
+    }
+
+    private void addTwoAppPanelWindows() throws TimeoutException {
+        final UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
+
+        uiAutomation.waitForIdle(TIMEOUT_WINDOW_STATE_IDLE, TIMEOUT_ASYNC_PROCESSING);
+
+        // Add the first window.
+        uiAutomation.executeAndWaitForEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInstrumentation().runOnMainSync(new Runnable() {
+                    @Override
+                    public void run() {
+                        WindowManager.LayoutParams params = new WindowManager.LayoutParams();
+                        params.gravity = Gravity.TOP;
+                        params.width = WindowManager.LayoutParams.MATCH_PARENT;
+                        params.height = WindowManager.LayoutParams.WRAP_CONTENT;
+                        params.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                                | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
+                                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                                | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+                        params.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
+                        params.token = getActivity().getWindow().getDecorView().getWindowToken();
+
+                        Button button = new Button(getActivity());
+                        button.setText(R.string.button1);
+                        getActivity().getWindowManager().addView(button, params);
+                    }
+                });
+            }
+        }, new UiAutomation.AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return event.getEventType() == AccessibilityEvent.TYPE_WINDOWS_CHANGED;
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Add the second window.
+        uiAutomation.executeAndWaitForEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInstrumentation().runOnMainSync(new Runnable() {
+                    @Override
+                    public void run() {
+                        WindowManager.LayoutParams params = new WindowManager.LayoutParams();
+                        params.gravity = Gravity.BOTTOM;
+                        params.width = WindowManager.LayoutParams.MATCH_PARENT;
+                        params.height = WindowManager.LayoutParams.WRAP_CONTENT;
+                        params.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                                | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
+                                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                                | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+                        params.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
+                        params.token = getActivity().getWindow().getDecorView().getWindowToken();
+
+                        Button button = new Button(getActivity());
+                        button.setText(R.string.button2);
+                        getActivity().getWindowManager().addView(button, params);
+                    }
+                });
+            }
+        }, new UiAutomation.AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return event.getEventType() == AccessibilityEvent.TYPE_WINDOWS_CHANGED;
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+    }
+
+    private void setAccessInteractiveWindowsFlag () {
+        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
+        AccessibilityServiceInfo info = uiAutomation.getServiceInfo();
+        info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
+        uiAutomation.setServiceInfo(info);
+    }
+
+    private void clearAccessInteractiveWindowsFlag () {
+        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
+        AccessibilityServiceInfo info = uiAutomation.getServiceInfo();
+        info.flags &= ~AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
+        uiAutomation.setServiceInfo(info);
+    }
+
+    private void ensureAccessibilityFocusCleared() {
+        try {
+            final UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
+            uiAutomation.executeAndWaitForEvent(new Runnable() {
+                @Override
+                public void run() {
+                    List<AccessibilityWindowInfo> windows = uiAutomation.getWindows();
+                    final int windowCount = windows.size();
+                    for (int i = 0; i < windowCount; i++) {
+                        AccessibilityWindowInfo window = windows.get(i);
+                        if (window.isAccessibilityFocused()) {
+                            window.getRoot().performAction(
+                                    AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
+                        }
+                    }
+                }
+            }, new UiAutomation.AccessibilityEventFilter() {
+                @Override
+                public boolean accept(AccessibilityEvent event) {
+                    return event.getEventType() ==
+                            AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED;
+                }
+            }, TIMEOUT_ASYNC_PROCESSING);
+        } catch (TimeoutException te) {
+            /* ignore */
+        }
+    }
+
+    private void verifyNodesInAppWindow(AccessibilityNodeInfo root) throws Exception {
+        try {
+            AccessibilityServiceInfo info = getInstrumentation().getUiAutomation().getServiceInfo();
+            info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
+            getInstrumentation().getUiAutomation().setServiceInfo(info);
+
+            root.refresh();
+
+            // make list of expected nodes
+            List<String> classNameAndTextList = new ArrayList<String>();
+            classNameAndTextList.add("android.widget.LinearLayout");
+            classNameAndTextList.add("android.widget.LinearLayout");
+            classNameAndTextList.add("android.widget.LinearLayout");
+            classNameAndTextList.add("android.widget.LinearLayout");
+            classNameAndTextList.add("android.widget.ButtonB1");
+            classNameAndTextList.add("android.widget.ButtonB2");
+            classNameAndTextList.add("android.widget.ButtonB3");
+            classNameAndTextList.add("android.widget.ButtonB4");
+            classNameAndTextList.add("android.widget.ButtonB5");
+            classNameAndTextList.add("android.widget.ButtonB6");
+            classNameAndTextList.add("android.widget.ButtonB7");
+            classNameAndTextList.add("android.widget.ButtonB8");
+            classNameAndTextList.add("android.widget.ButtonB9");
+
+            String contentViewIdResName = "com.android.cts.accessibilityservice:id/added_content";
+            boolean verifyContent = false;
+
+            Queue<AccessibilityNodeInfo> fringe = new LinkedList<AccessibilityNodeInfo>();
+            fringe.add(root);
+
+            // do a BFS traversal and check nodes
+            while (!fringe.isEmpty()) {
+                AccessibilityNodeInfo current = fringe.poll();
+
+                if (!verifyContent
+                        && contentViewIdResName.equals(current.getViewIdResourceName())) {
+                    verifyContent = true;
+                }
+
+                if (verifyContent) {
+                    CharSequence text = current.getText();
+                    String receivedClassNameAndText = current.getClassName().toString()
+                            + ((text != null) ? text.toString() : "");
+                    String expectedClassNameAndText = classNameAndTextList.remove(0);
+
+                    assertEquals("Did not get the expected node info",
+                            expectedClassNameAndText, receivedClassNameAndText);
+                }
+
+                final int childCount = current.getChildCount();
+                for (int i = 0; i < childCount; i++) {
+                    AccessibilityNodeInfo child = current.getChild(i);
+                    fringe.add(child);
+                }
+            }
+        } finally {
+            AccessibilityServiceInfo info = getInstrumentation().getUiAutomation().getServiceInfo();
+            info.flags &= ~AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
+            getInstrumentation().getUiAutomation().setServiceInfo(info);
+        }
+    }
+
     @Override
     protected void scrubClass(Class<?> testCaseClass) {
         /* intentionally do not scrub */
diff --git a/tests/tests/accounts/Android.mk b/tests/tests/accounts/Android.mk
index e4536d4..1579822 100644
--- a/tests/tests/accounts/Android.mk
+++ b/tests/tests/accounts/Android.mk
@@ -21,12 +21,12 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
-LOCAL_STATIC_JAVA_LIBRARIES += android-common ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsAccountManagerTestCases
 
+LOCAL_SDK_VERSION := current
+
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/accounts/AndroidManifest.xml b/tests/tests/accounts/AndroidManifest.xml
index 6020636..22362ab 100644
--- a/tests/tests/accounts/AndroidManifest.xml
+++ b/tests/tests/accounts/AndroidManifest.xml
@@ -28,6 +28,13 @@
     <application>
         <uses-library android:name="android.test.runner" />
 
+        <activity android:name="android.accounts.cts.AccountDummyActivity" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
         <service android:name="MockAccountService" android:exported="true"
                  android:process="android.accounts.cts">
             <intent-filter>
@@ -39,9 +46,12 @@
         </service>
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="android.accounts.cts"
-                     android:label="CTS tests for android.accounts"/>
+                     android:label="CTS tests for android.accounts">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/tests/accounts/src/android/accounts/cts/AccountDummyActivity.java b/tests/tests/accounts/src/android/accounts/cts/AccountDummyActivity.java
new file mode 100644
index 0000000..a345dcc
--- /dev/null
+++ b/tests/tests/accounts/src/android/accounts/cts/AccountDummyActivity.java
@@ -0,0 +1,25 @@
+/*
+ * 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.accounts.cts;
+
+import android.app.Activity;
+
+/**
+ * An activity.
+ */
+public class AccountDummyActivity extends Activity {
+}
diff --git a/tests/tests/accounts/src/android/accounts/cts/AccountManagerTest.java b/tests/tests/accounts/src/android/accounts/cts/AccountManagerTest.java
index 5315cec..e5cc45a 100644
--- a/tests/tests/accounts/src/android/accounts/cts/AccountManagerTest.java
+++ b/tests/tests/accounts/src/android/accounts/cts/AccountManagerTest.java
@@ -28,8 +28,9 @@
 import android.content.Context;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.StrictMode;
-import android.test.AndroidTestCase;
+import android.test.ActivityInstrumentationTestCase2;
 
 import java.io.IOException;
 import java.util.concurrent.CountDownLatch;
@@ -41,11 +42,12 @@
  *  adb shell am instrument
  *   -e debug false -w
  *   -e class android.accounts.cts.AccountManagerTest
- * android.accounts.cts/android.test.InstrumentationTestRunner
+ * android.accounts.cts/android.support.test.runner.AndroidJUnitRunner
  */
-public class AccountManagerTest extends AndroidTestCase {
+public class AccountManagerTest extends ActivityInstrumentationTestCase2<AccountDummyActivity> {
 
     public static final String ACCOUNT_NAME = "android.accounts.cts.account.name";
+    public static final String ACCOUNT_NEW_NAME = "android.accounts.cts.account.name.rename";
     public static final String ACCOUNT_NAME_OTHER = "android.accounts.cts.account.name.other";
 
     public static final String ACCOUNT_TYPE = "android.accounts.cts.account.type";
@@ -69,7 +71,6 @@
 
     public static final String[] REQUIRED_FEATURES = new String[] { FEATURE_1, FEATURE_2 };
 
-    public static final Activity ACTIVITY = new Activity();
     public static final Bundle OPTIONS_BUNDLE = new Bundle();
 
     public static final Bundle USERDATA_BUNDLE = new Bundle();
@@ -93,18 +94,27 @@
         return mockAuthenticator;
     }
 
+    private Activity mActivity;
+    private Context mContext;
+
+    public AccountManagerTest() {
+        super(AccountDummyActivity.class);
+    }
+
     @Override
     public void setUp() throws Exception {
         super.setUp();
+        mActivity = getActivity();
+        mContext = getInstrumentation().getTargetContext();
 
         OPTIONS_BUNDLE.putString(OPTION_NAME_1, OPTION_VALUE_1);
         OPTIONS_BUNDLE.putString(OPTION_NAME_2, OPTION_VALUE_2);
 
         USERDATA_BUNDLE.putString(USERDATA_NAME_1, USERDATA_VALUE_1);
 
-        getMockAuthenticator(getContext());
+        getMockAuthenticator(mContext);
 
-        am = AccountManager.get(getContext());
+        am = AccountManager.get(mContext);
     }
 
     @Override
@@ -196,6 +206,16 @@
         return resultBundle;
     }
 
+    private Account renameAccount(AccountManager am, Account account, String newName)
+            throws OperationCanceledException, AuthenticatorException, IOException {
+        AccountManagerFuture<Account> futureAccount = am.renameAccount(
+                account, newName, null /* callback */, null /* handler */);
+        Account renamedAccount = futureAccount.getResult();
+        assertTrue(futureAccount.isDone());
+        assertNotNull(renamedAccount);
+        return renamedAccount;
+    }
+
     private boolean removeAccount(AccountManager am, Account account,
             AccountManagerCallback<Boolean> callback) throws IOException, AuthenticatorException,
                 OperationCanceledException {
@@ -253,7 +273,7 @@
      * Test singleton
      */
     public void testGet() {
-        assertNotNull(AccountManager.get(getContext()));
+        assertNotNull(AccountManager.get(mContext));
     }
 
     /**
@@ -267,7 +287,7 @@
                 AUTH_TOKEN_TYPE,
                 REQUIRED_FEATURES,
                 OPTIONS_BUNDLE,
-                ACTIVITY,
+                mActivity,
                 null /* callback */,
                 null /* handler */);
 
@@ -291,7 +311,7 @@
             AuthenticatorException, OperationCanceledException {
 
         testAddAccountWithCallbackAndHandler(null /* handler */);
-        testAddAccountWithCallbackAndHandler(new Handler());
+        testAddAccountWithCallbackAndHandler(new Handler(Looper.getMainLooper()));
     }
 
     private void testAddAccountWithCallbackAndHandler(Handler handler) throws IOException,
@@ -332,7 +352,7 @@
                 AUTH_TOKEN_TYPE,
                 REQUIRED_FEATURES,
                 OPTIONS_BUNDLE,
-                ACTIVITY,
+                mActivity,
                 callback,
                 handler);
 
@@ -345,35 +365,78 @@
     }
 
     /**
-     * Test addAccountExplicitly() and removeAccount()
+     * Test addAccountExplicitly(), renameAccount() and removeAccount().
      */
     public void testAddAccountExplicitlyAndRemoveAccount() throws IOException,
             AuthenticatorException, OperationCanceledException {
 
-        final int accountsCount = getAccountsCount();
+        final int expectedAccountsCount = getAccountsCount();
 
         addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);
 
         // Assert that we have one more account
         Account[] accounts = am.getAccounts();
         assertNotNull(accounts);
-        assertEquals(1 + accountsCount, accounts.length);
+        assertEquals(1 + expectedAccountsCount, accounts.length);
         assertTrue(isAccountPresent(am.getAccounts(), ACCOUNT));
-
         // Need to clean up
         assertTrue(removeAccount(am, ACCOUNT, null /* callback */));
 
         // and verify that we go back to the initial state
         accounts = am.getAccounts();
         assertNotNull(accounts);
-        assertEquals(accountsCount, accounts.length);
+        assertEquals(expectedAccountsCount, accounts.length);
+    }
+
+    /**
+     * Test setUserData() and getUserData().
+     */
+    public void testAccountRenameAndGetPreviousName()
+            throws OperationCanceledException, AuthenticatorException, IOException {
+        // Add a first account
+        boolean result = am.addAccountExplicitly(ACCOUNT,
+                                ACCOUNT_PASSWORD,
+                                USERDATA_BUNDLE);
+        assertTrue(result);
+
+        // Prior to a renmae, the previous name should be null.
+        String nullName = am.getPreviousName(ACCOUNT);
+        assertNull(nullName);
+
+        final int expectedAccountsCount = getAccountsCount();
+
+        Account renamedAccount = renameAccount(am, ACCOUNT, ACCOUNT_NEW_NAME);
+
+        /*
+         *  Make sure that the resultant renamed account has the correct name
+         *  and is associated with the correct account type.
+         */
+        assertEquals(ACCOUNT_NEW_NAME, renamedAccount.name);
+        assertEquals(ACCOUNT.type, renamedAccount.type);
+
+        // Make sure the total number of accounts is the same.
+        Account[] accounts = am.getAccounts();
+        assertEquals(expectedAccountsCount, accounts.length);
+
+        // Make sure the old account isn't present.
+        assertFalse(isAccountPresent(am.getAccounts(), ACCOUNT));
+
+        // But that the new one is.
+        assertTrue(isAccountPresent(am.getAccounts(), renamedAccount));
+
+        // Check that the UserData is still present.
+        assertEquals(USERDATA_VALUE_1, am.getUserData(renamedAccount, USERDATA_NAME_1));
+
+        assertEquals(ACCOUNT.name, am.getPreviousName(renamedAccount));
+
+       // Need to clean up
+        assertTrue(removeAccount(am, renamedAccount, null /* callback */));
     }
 
     /**
      * Test getAccounts() and getAccountsByType()
      */
-    public void testGetAccountsAndGetAccountsByType() throws IOException, AuthenticatorException,
-            OperationCanceledException {
+    public void testGetAccountsAndGetAccountsByType() {
 
         assertEquals(false, isAccountPresent(am.getAccounts(), ACCOUNT));
         assertEquals(false, isAccountPresent(am.getAccounts(), ACCOUNT_SAME_TYPE));
@@ -495,7 +558,7 @@
         addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);
 
         testGetAccountsByTypeAndFeaturesWithCallbackAndHandler(null /* handler */);
-        testGetAccountsByTypeAndFeaturesWithCallbackAndHandler(new Handler());
+        testGetAccountsByTypeAndFeaturesWithCallbackAndHandler(new Handler(Looper.getMainLooper()));
     }
 
     private void testGetAccountsByTypeAndFeaturesWithCallbackAndHandler(Handler handler) throws
@@ -648,7 +711,7 @@
         addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);
 
         testGetAuthTokenWithCallbackAndHandler(null /* handler */);
-        testGetAuthTokenWithCallbackAndHandler(new Handler());
+        testGetAuthTokenWithCallbackAndHandler(new Handler(Looper.getMainLooper()));
     }
 
     private void testGetAuthTokenWithCallbackAndHandler(Handler handler) throws IOException,
@@ -710,7 +773,7 @@
         AccountManagerFuture<Bundle> futureBundle = am.getAuthToken(ACCOUNT,
                 AUTH_TOKEN_TYPE,
                 OPTIONS_BUNDLE,
-                ACTIVITY,
+                mActivity,
                 null /* no callback */,
                 null /* no handler */
         );
@@ -739,7 +802,7 @@
         addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);
 
         testGetAuthTokenWithOptionsAndCallbackAndHandler(null /* handler */);
-        testGetAuthTokenWithOptionsAndCallbackAndHandler(new Handler());
+        testGetAuthTokenWithOptionsAndCallbackAndHandler(new Handler(Looper.getMainLooper()));
     }
 
     private void testGetAuthTokenWithOptionsAndCallbackAndHandler(Handler handler) throws
@@ -773,7 +836,7 @@
         AccountManagerFuture<Bundle> futureBundle = am.getAuthToken(ACCOUNT,
                 AUTH_TOKEN_TYPE,
                 OPTIONS_BUNDLE,
-                ACTIVITY,
+                mActivity,
                 callback,
                 handler
         );
@@ -817,7 +880,7 @@
         // Now test with existing features and an activity
         resultBundle = getAuthTokenByFeature(
                 new String[] { NON_EXISTING_FEATURE },
-                ACTIVITY
+                mActivity
         );
 
         // Assert returned result
@@ -849,7 +912,7 @@
         // Now test with existing features and an activity
         resultBundle = getAuthTokenByFeature(
                 REQUIRED_FEATURES,
-                ACTIVITY
+                mActivity
         );
 
         // Assert returned result
@@ -872,7 +935,7 @@
 
         AccountManagerFuture<Bundle> futureBundle = am.confirmCredentials(ACCOUNT,
                 OPTIONS_BUNDLE,
-                ACTIVITY,
+                mActivity,
                 null /* callback*/,
                 null /* handler */);
 
@@ -891,7 +954,7 @@
         addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);
 
         testConfirmCredentialsWithCallbackAndHandler(null /* handler */);
-        testConfirmCredentialsWithCallbackAndHandler(new Handler());
+        testConfirmCredentialsWithCallbackAndHandler(new Handler(Looper.getMainLooper()));
     }
 
     private void testConfirmCredentialsWithCallbackAndHandler(Handler handler) throws IOException,
@@ -925,7 +988,7 @@
 
         AccountManagerFuture<Bundle> futureBundle = am.confirmCredentials(ACCOUNT,
                 OPTIONS_BUNDLE,
-                ACTIVITY,
+                mActivity,
                 callback,
                 handler);
 
@@ -950,7 +1013,7 @@
         AccountManagerFuture<Bundle> futureBundle = am.updateCredentials(ACCOUNT,
                 AUTH_TOKEN_TYPE,
                 OPTIONS_BUNDLE,
-                ACTIVITY,
+                mActivity,
                 null /* callback*/,
                 null /* handler */);
 
@@ -971,7 +1034,7 @@
         addAccountExplicitly(ACCOUNT, ACCOUNT_PASSWORD, null /* userData */);
 
         testUpdateCredentialsWithCallbackAndHandler(null /* handler */);
-        testUpdateCredentialsWithCallbackAndHandler(new Handler());
+        testUpdateCredentialsWithCallbackAndHandler(new Handler(Looper.getMainLooper()));
     }
 
     private void testUpdateCredentialsWithCallbackAndHandler(Handler handler) throws IOException,
@@ -1006,7 +1069,7 @@
         AccountManagerFuture<Bundle> futureBundle = am.updateCredentials(ACCOUNT,
                 AUTH_TOKEN_TYPE,
                 OPTIONS_BUNDLE,
-                ACTIVITY,
+                mActivity,
                 callback,
                 handler);
 
@@ -1027,7 +1090,7 @@
             OperationCanceledException {
 
         AccountManagerFuture<Bundle> futureBundle = am.editProperties(ACCOUNT_TYPE,
-                ACTIVITY,
+                mActivity,
                 null /* callback */,
                 null /* handler*/);
 
@@ -1044,7 +1107,7 @@
      */
     public void testEditPropertiesWithCallbackAndHandler() {
         testEditPropertiesWithCallbackAndHandler(null /* handler */);
-        testEditPropertiesWithCallbackAndHandler(new Handler());
+        testEditPropertiesWithCallbackAndHandler(new Handler(Looper.getMainLooper()));
     }
 
     private void testEditPropertiesWithCallbackAndHandler(Handler handler) {
@@ -1063,7 +1126,7 @@
         };
 
         AccountManagerFuture<Bundle> futureBundle = am.editProperties(ACCOUNT_TYPE,
-                ACTIVITY,
+                mActivity,
                 callback,
                 handler);
 
@@ -1093,13 +1156,13 @@
         // Need to cleanup intermediate state
         assertTrue(removeAccount(am, ACCOUNT, null /* callback */));
 
-        testAddOnAccountsUpdatedListenerWithHandler(new Handler(),
+        testAddOnAccountsUpdatedListenerWithHandler(new Handler(Looper.getMainLooper()),
                 false /* updateImmediately */);
 
         // Need to cleanup intermediate state
         assertTrue(removeAccount(am, ACCOUNT, null /* callback */));
 
-        testAddOnAccountsUpdatedListenerWithHandler(new Handler(),
+        testAddOnAccountsUpdatedListenerWithHandler(new Handler(Looper.getMainLooper()),
                 true /* updateImmediately */);
     }
 
@@ -1143,7 +1206,7 @@
         // Need to cleanup intermediate state
         assertTrue(removeAccount(am, ACCOUNT, null /* callback */));
 
-        testRemoveOnAccountsUpdatedListenerWithHandler(new Handler());
+        testRemoveOnAccountsUpdatedListenerWithHandler(new Handler(Looper.getMainLooper()));
     }
 
     private void testRemoveOnAccountsUpdatedListenerWithHandler(Handler handler) {
@@ -1180,10 +1243,10 @@
             throws IOException, AuthenticatorException, OperationCanceledException {
 
         assertHasFeature(null /* handler */);
-        assertHasFeature(new Handler());
+        assertHasFeature(new Handler(Looper.getMainLooper()));
 
         assertHasFeatureWithCallback(null /* handler */);
-        assertHasFeatureWithCallback(new Handler());
+        assertHasFeatureWithCallback(new Handler(Looper.getMainLooper()));
     }
 
     private void assertHasFeature(Handler handler)
@@ -1193,7 +1256,7 @@
                 AUTH_TOKEN_TYPE,
                 REQUIRED_FEATURES,
                 OPTIONS_BUNDLE,
-                ACTIVITY,
+                mActivity,
                 null /* callback */,
                 null /* handler */);
 
@@ -1284,7 +1347,7 @@
                 AUTH_TOKEN_TYPE,
                 REQUIRED_FEATURES,
                 OPTIONS_BUNDLE,
-                ACTIVITY,
+                mActivity,
                 null /* callback */,
                 null /* handler */);
 
diff --git a/tests/tests/admin/Android.mk b/tests/tests/admin/Android.mk
index c3645cc..7a5ae34 100644
--- a/tests/tests/admin/Android.mk
+++ b/tests/tests/admin/Android.mk
@@ -20,8 +20,6 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner mockito-target
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/admin/AndroidManifest.xml b/tests/tests/admin/AndroidManifest.xml
index 7ce29aa..bbd7918 100644
--- a/tests/tests/admin/AndroidManifest.xml
+++ b/tests/tests/admin/AndroidManifest.xml
@@ -26,8 +26,11 @@
 
   </application>
 
-  <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+  <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                    android:targetPackage="android.deviceadmin.cts"
-                   android:label="Tests for the admin APIs."/>
+                   android:label="Tests for the admin APIs.">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
diff --git a/tests/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java b/tests/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
index e953305..d0255f3 100644
--- a/tests/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
+++ b/tests/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
@@ -19,12 +19,18 @@
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.PackageManager;
+import android.os.UserManager;
+import android.provider.Settings;
 import android.test.AndroidTestCase;
 import android.util.Log;
 
 import java.util.List;
 
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
+
 /**
  * Test that exercises {@link DevicePolicyManager}. The test requires that the
  * CtsDeviceAdminReceiver be installed via the CtsDeviceAdmin.apk and be
@@ -36,14 +42,33 @@
 
     private DevicePolicyManager mDevicePolicyManager;
     private ComponentName mComponent;
+    private ComponentName mSecondComponent;
     private boolean mDeviceAdmin;
 
+    private static final String TEST_CA_STRING1 =
+            "-----BEGIN CERTIFICATE-----\n" +
+            "MIICVzCCAgGgAwIBAgIJAMvnLHnnfO/IMA0GCSqGSIb3DQEBBQUAMIGGMQswCQYD\n" +
+            "VQQGEwJJTjELMAkGA1UECAwCQVAxDDAKBgNVBAcMA0hZRDEVMBMGA1UECgwMSU1G\n" +
+            "TCBQVlQgTFREMRAwDgYDVQQLDAdJTUZMIE9VMRIwEAYDVQQDDAlJTUZMLklORk8x\n" +
+            "HzAdBgkqhkiG9w0BCQEWEHJhbWVzaEBpbWZsLmluZm8wHhcNMTMwODI4MDk0NDA5\n" +
+            "WhcNMjMwODI2MDk0NDA5WjCBhjELMAkGA1UEBhMCSU4xCzAJBgNVBAgMAkFQMQww\n" +
+            "CgYDVQQHDANIWUQxFTATBgNVBAoMDElNRkwgUFZUIExURDEQMA4GA1UECwwHSU1G\n" +
+            "TCBPVTESMBAGA1UEAwwJSU1GTC5JTkZPMR8wHQYJKoZIhvcNAQkBFhByYW1lc2hA\n" +
+            "aW1mbC5pbmZvMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJ738cbTQlNIO7O6nV/f\n" +
+            "DJTMvWbPkyHYX8CQ7yXiAzEiZ5bzKJjDJmpRAkUrVinljKns2l6C4++l/5A7pFOO\n" +
+            "33kCAwEAAaNQME4wHQYDVR0OBBYEFOdbZP7LaMbgeZYPuds2CeSonmYxMB8GA1Ud\n" +
+            "IwQYMBaAFOdbZP7LaMbgeZYPuds2CeSonmYxMAwGA1UdEwQFMAMBAf8wDQYJKoZI\n" +
+            "hvcNAQEFBQADQQBdrk6J9koyylMtl/zRfiMAc2zgeC825fgP6421NTxs1rjLs1HG\n" +
+            "VcUyQ1/e7WQgOaBHi9TefUJi+4PSVSluOXon\n" +
+            "-----END CERTIFICATE-----";
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
         mDevicePolicyManager = (DevicePolicyManager)
                 mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
         mComponent = DeviceAdminInfoTest.getReceiverComponent();
+        mSecondComponent = DeviceAdminInfoTest.getSecondReceiverComponent();
         mDeviceAdmin =
                 mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN);
         setBlankPassword();
@@ -220,4 +245,691 @@
         assertFalse(mDevicePolicyManager.resetPassword("abcd", 0));
         assertTrue(mDevicePolicyManager.resetPassword("abcd123", 0));
     }
+
+    public void testPasswordQuality_complexUpperCase() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testPasswordQuality_complexUpperCase");
+            return;
+        }
+
+        mDevicePolicyManager.setPasswordQuality(mComponent, PASSWORD_QUALITY_COMPLEX);
+        assertEquals(PASSWORD_QUALITY_COMPLEX, mDevicePolicyManager.getPasswordQuality(mComponent));
+        resetComplexPasswordRestrictions();
+
+        String caseDescription = "minimum UpperCase=0";
+        assertPasswordSucceeds("abc", caseDescription);
+        assertPasswordSucceeds("aBc", caseDescription);
+        assertPasswordSucceeds("ABC", caseDescription);
+        assertPasswordSucceeds("ABCD", caseDescription);
+
+        mDevicePolicyManager.setPasswordMinimumUpperCase(mComponent, 1);
+        assertEquals(1, mDevicePolicyManager.getPasswordMinimumUpperCase(mComponent));
+        caseDescription = "minimum UpperCase=1";
+        assertPasswordFails("abc", caseDescription);
+        assertPasswordSucceeds("aBc", caseDescription);
+        assertPasswordSucceeds("ABC", caseDescription);
+        assertPasswordSucceeds("ABCD", caseDescription);
+
+        mDevicePolicyManager.setPasswordMinimumUpperCase(mComponent, 3);
+        assertEquals(3, mDevicePolicyManager.getPasswordMinimumUpperCase(mComponent));
+        caseDescription = "minimum UpperCase=3";
+        assertPasswordFails("abc", caseDescription);
+        assertPasswordFails("aBC", caseDescription);
+        assertPasswordSucceeds("ABC", caseDescription);
+        assertPasswordSucceeds("ABCD", caseDescription);
+    }
+
+    public void testPasswordQuality_complexLowerCase() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testPasswordQuality_complexLowerCase");
+            return;
+        }
+
+        mDevicePolicyManager.setPasswordQuality(mComponent, PASSWORD_QUALITY_COMPLEX);
+        assertEquals(PASSWORD_QUALITY_COMPLEX, mDevicePolicyManager.getPasswordQuality(mComponent));
+        resetComplexPasswordRestrictions();
+
+        String caseDescription = "minimum LowerCase=0";
+        assertPasswordSucceeds("ABCD", caseDescription);
+        assertPasswordSucceeds("aBC", caseDescription);
+        assertPasswordSucceeds("abc", caseDescription);
+        assertPasswordSucceeds("abcd", caseDescription);
+
+        mDevicePolicyManager.setPasswordMinimumLowerCase(mComponent, 1);
+        assertEquals(1, mDevicePolicyManager.getPasswordMinimumLowerCase(mComponent));
+        caseDescription = "minimum LowerCase=1";
+        assertPasswordFails("ABCD", caseDescription);
+        assertPasswordSucceeds("aBC", caseDescription);
+        assertPasswordSucceeds("abc", caseDescription);
+        assertPasswordSucceeds("abcd", caseDescription);
+
+        mDevicePolicyManager.setPasswordMinimumLowerCase(mComponent, 3);
+        assertEquals(3, mDevicePolicyManager.getPasswordMinimumLowerCase(mComponent));
+        caseDescription = "minimum LowerCase=3";
+        assertPasswordFails("ABCD", caseDescription);
+        assertPasswordFails("aBC", caseDescription);
+        assertPasswordSucceeds("abc", caseDescription);
+        assertPasswordSucceeds("abcd", caseDescription);
+    }
+
+    public void testPasswordQuality_complexLetters() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testPasswordQuality_complexLetters");
+            return;
+        }
+
+        mDevicePolicyManager.setPasswordQuality(mComponent, PASSWORD_QUALITY_COMPLEX);
+        assertEquals(PASSWORD_QUALITY_COMPLEX, mDevicePolicyManager.getPasswordQuality(mComponent));
+        resetComplexPasswordRestrictions();
+
+        String caseDescription = "minimum Letters=0";
+        assertPasswordSucceeds("1234", caseDescription);
+        assertPasswordSucceeds("a23", caseDescription);
+        assertPasswordSucceeds("abc", caseDescription);
+        assertPasswordSucceeds("abcd", caseDescription);
+
+        mDevicePolicyManager.setPasswordMinimumLetters(mComponent, 1);
+        assertEquals(1, mDevicePolicyManager.getPasswordMinimumLetters(mComponent));
+        caseDescription = "minimum Letters=1";
+        assertPasswordFails("1234", caseDescription);
+        assertPasswordSucceeds("a23", caseDescription);
+        assertPasswordSucceeds("abc", caseDescription);
+        assertPasswordSucceeds("abcd", caseDescription);
+
+        mDevicePolicyManager.setPasswordMinimumLetters(mComponent, 3);
+        assertEquals(3, mDevicePolicyManager.getPasswordMinimumLetters(mComponent));
+        caseDescription = "minimum Letters=3";
+        assertPasswordFails("1234", caseDescription);
+        assertPasswordFails("a23", caseDescription);
+        assertPasswordSucceeds("abc", caseDescription);
+        assertPasswordSucceeds("abcd", caseDescription);
+    }
+
+    public void testPasswordQuality_complexNumeric() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testPasswordQuality_complexNumeric");
+            return;
+        }
+
+        mDevicePolicyManager.setPasswordQuality(mComponent, PASSWORD_QUALITY_COMPLEX);
+        assertEquals(PASSWORD_QUALITY_COMPLEX, mDevicePolicyManager.getPasswordQuality(mComponent));
+        resetComplexPasswordRestrictions();
+
+        String caseDescription = "minimum Numeric=0";
+        assertPasswordSucceeds("abcd", caseDescription);
+        assertPasswordSucceeds("1bc", caseDescription);
+        assertPasswordSucceeds("123", caseDescription);
+        assertPasswordSucceeds("1234", caseDescription);
+
+        mDevicePolicyManager.setPasswordMinimumNumeric(mComponent, 1);
+        assertEquals(1, mDevicePolicyManager.getPasswordMinimumNumeric(mComponent));
+        caseDescription = "minimum Numeric=1";
+        assertPasswordFails("abcd", caseDescription);
+        assertPasswordSucceeds("1bc", caseDescription);
+        assertPasswordSucceeds("123", caseDescription);
+        assertPasswordSucceeds("1234", caseDescription);
+
+        mDevicePolicyManager.setPasswordMinimumNumeric(mComponent, 3);
+        assertEquals(3, mDevicePolicyManager.getPasswordMinimumNumeric(mComponent));
+        caseDescription = "minimum Numeric=3";
+        assertPasswordFails("abcd", caseDescription);
+        assertPasswordFails("1bc", caseDescription);
+        assertPasswordSucceeds("123", caseDescription);
+        assertPasswordSucceeds("1234", caseDescription);
+    }
+
+    public void testPasswordQuality_complexSymbols() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testPasswordQuality_complexSymbols");
+            return;
+        }
+
+        mDevicePolicyManager.setPasswordQuality(mComponent, PASSWORD_QUALITY_COMPLEX);
+        assertEquals(PASSWORD_QUALITY_COMPLEX, mDevicePolicyManager.getPasswordQuality(mComponent));
+        resetComplexPasswordRestrictions();
+
+        String caseDescription = "minimum Symbols=0";
+        assertPasswordSucceeds("abcd", caseDescription);
+        assertPasswordSucceeds("_bc", caseDescription);
+        assertPasswordSucceeds("@#!", caseDescription);
+        assertPasswordSucceeds("_@#!", caseDescription);
+
+        mDevicePolicyManager.setPasswordMinimumSymbols(mComponent, 1);
+        assertEquals(1, mDevicePolicyManager.getPasswordMinimumSymbols(mComponent));
+        caseDescription = "minimum Symbols=1";
+        assertPasswordFails("abcd", caseDescription);
+        assertPasswordSucceeds("_bc", caseDescription);
+        assertPasswordSucceeds("@#!", caseDescription);
+        assertPasswordSucceeds("_@#!", caseDescription);
+
+        mDevicePolicyManager.setPasswordMinimumSymbols(mComponent, 3);
+        assertEquals(3, mDevicePolicyManager.getPasswordMinimumSymbols(mComponent));
+        caseDescription = "minimum Symbols=3";
+        assertPasswordFails("abcd", caseDescription);
+        assertPasswordFails("_bc", caseDescription);
+        assertPasswordSucceeds("@#!", caseDescription);
+        assertPasswordSucceeds("_@#!", caseDescription);
+    }
+
+    public void testPasswordQuality_complexNonLetter() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testPasswordQuality_complexNonLetter");
+            return;
+        }
+
+        mDevicePolicyManager.setPasswordQuality(mComponent, PASSWORD_QUALITY_COMPLEX);
+        assertEquals(PASSWORD_QUALITY_COMPLEX, mDevicePolicyManager.getPasswordQuality(mComponent));
+        resetComplexPasswordRestrictions();
+
+        String caseDescription = "minimum NonLetter=0";
+        assertPasswordSucceeds("Abcd", caseDescription);
+        assertPasswordSucceeds("_bcd", caseDescription);
+        assertPasswordSucceeds("3bcd", caseDescription);
+        assertPasswordSucceeds("_@3c", caseDescription);
+        assertPasswordSucceeds("_25!", caseDescription);
+
+        mDevicePolicyManager.setPasswordMinimumNonLetter(mComponent, 1);
+        assertEquals(1, mDevicePolicyManager.getPasswordMinimumNonLetter(mComponent));
+        caseDescription = "minimum NonLetter=1";
+        assertPasswordFails("Abcd", caseDescription);
+        assertPasswordSucceeds("_bcd", caseDescription);
+        assertPasswordSucceeds("3bcd", caseDescription);
+        assertPasswordSucceeds("_@3c", caseDescription);
+        assertPasswordSucceeds("_25!", caseDescription);
+
+        mDevicePolicyManager.setPasswordMinimumNonLetter(mComponent, 3);
+        assertEquals(3, mDevicePolicyManager.getPasswordMinimumNonLetter(mComponent));
+        caseDescription = "minimum NonLetter=3";
+        assertPasswordFails("Abcd", caseDescription);
+        assertPasswordFails("_bcd", caseDescription);
+        assertPasswordFails("3bcd", caseDescription);
+        assertPasswordSucceeds("c_@3c", caseDescription);
+        assertPasswordSucceeds("_25!", caseDescription);
+    }
+
+    public void testPasswordHistoryLength() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testPasswordHistoryLength");
+            return;
+        }
+        // Password history length restriction is only imposed if password quality is at least
+        // numeric.
+        mDevicePolicyManager.setPasswordQuality(mComponent,
+                DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC);
+        int originalValue = mDevicePolicyManager.getPasswordHistoryLength(mComponent);
+        try {
+            mDevicePolicyManager.setPasswordHistoryLength(mComponent, 3);
+            assertEquals(3, mDevicePolicyManager.getPasswordHistoryLength(mComponent));
+            // Although it would make sense we cannot test if password history restrictions
+            // are enforced as DevicePolicyManagerService.resetPassword fails to do so at the
+            // moment. See b/17707820
+        } finally {
+            mDevicePolicyManager.setPasswordHistoryLength(mComponent, originalValue);
+        }
+    }
+
+    public void testPasswordExpirationTimeout() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testPasswordExpirationTimeout");
+            return;
+        }
+        long originalValue = mDevicePolicyManager.getPasswordExpirationTimeout(mComponent);
+        try {
+            for (long testLength : new long[] {
+                    0L, 864000000L /* ten days */, 8640000000L /* 100 days */}) {
+                mDevicePolicyManager.setPasswordExpirationTimeout(mComponent, testLength);
+                assertEquals(testLength,
+                        mDevicePolicyManager.getPasswordExpirationTimeout(mComponent));
+            }
+        } finally {
+            mDevicePolicyManager.setPasswordExpirationTimeout(mComponent, originalValue);
+        }
+    }
+
+    public void testMaximumTimeToLock() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testMaximumTimeToLock");
+            return;
+        }
+        long originalValue = mDevicePolicyManager.getMaximumTimeToLock(mComponent);
+        try {
+            for (long testLength : new long[] {
+                    5000L /* 5 sec */, 60000L /* 1 min */, 1800000 /* 30 min */}) {
+                mDevicePolicyManager.setMaximumTimeToLock(mComponent, testLength);
+                assertEquals(testLength,
+                        mDevicePolicyManager.getMaximumTimeToLock(mComponent));
+            }
+        } finally {
+            mDevicePolicyManager.setMaximumTimeToLock(mComponent, originalValue);
+        }
+    }
+
+    public void testCreateUser_failIfNotDeviceOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testCreateUser_failIfNotDeviceOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.createUser(mComponent, "user name");
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertDeviceOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testRemoveUser_failIfNotDeviceOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testRemoveUser_failIfNotDeviceOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.removeUser(mComponent, null);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertDeviceOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testSetApplicationHidden_failIfNotDeviceOrProfileOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSetApplicationHidden_failIfNotDeviceOrProfileOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.setApplicationHidden(mComponent, "com.google.anything", true);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertProfileOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testIsApplicationHidden_failIfNotDeviceOrProfileOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testIsApplicationHidden_failIfNotDeviceOrProfileOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.isApplicationHidden(mComponent, "com.google.anything");
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertProfileOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testSetGlobalSetting_failIfNotDeviceOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSetGlobalSetting_failIfNotDeviceOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.setGlobalSetting(mComponent,
+                    Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, "1");
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertDeviceOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testSetSecureSetting_failIfNotDeviceOrProfileOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSetSecureSetting_failIfNotDeviceOrProfileOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.setSecureSetting(mComponent,
+                    Settings.Secure.INSTALL_NON_MARKET_APPS, "1");
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertProfileOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testSetMasterVolumeMuted_failIfNotDeviceOrProfileOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSetMasterVolumeMuted_failIfNotDeviceOrProfileOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.setMasterVolumeMuted(mComponent, true);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertProfileOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testIsMasterVolumeMuted_failIfNotDeviceOrProfileOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSetMasterVolumeMuted_failIfNotDeviceOrProfileOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.isMasterVolumeMuted(mComponent);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertProfileOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testSetRecommendedGlobalProxy_failIfNotDeviceOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSetRecommendedGlobalProxy_failIfNotDeviceOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.setRecommendedGlobalProxy(mComponent, null);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertDeviceOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testSetLockTaskPackages_failIfNotDeviceOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSetLockTaskPackages_failIfNotDeviceOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.setLockTaskPackages(mComponent, new String[] {"package"});
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+        }
+    }
+
+    public void testClearDeviceOwnerApp_failIfNotDeviceOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testClearDeviceOwnerApp_failIfNotDeviceOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.clearDeviceOwnerApp("android.deviceadmin.cts");
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertDeviceOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testSwitchUser_failIfNotDeviceOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSwitchUser_failIfNotDeviceOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.switchUser(mComponent, null);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertDeviceOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testCreateAndInitializeUser_failIfNotDeviceOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testCreateAndInitializeUser_failIfNotDeviceOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.createAndInitializeUser(mComponent, "name", "admin name",
+                        mComponent, null);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertDeviceOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testInstallCaCert_failIfNotProfileOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testInstallCaCert_failIfNotProfileOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.installCaCert(mComponent,
+                    TEST_CA_STRING1.getBytes());
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertProfileOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testUninstallCaCert_failIfNotProfileOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testUninstallCaCert_failIfNotProfileOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.uninstallCaCert(mComponent,
+                    TEST_CA_STRING1.getBytes());
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertProfileOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testGetInstalledCaCerts_failIfNotProfileOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testGetInstalledCaCerts_failIfNotProfileOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.getInstalledCaCerts(mComponent);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertProfileOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testHasCaCertInstalled_failIfNotProfileOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testHasCaCertInstalled_failIfNotProfileOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.hasCaCertInstalled(mComponent,
+                    TEST_CA_STRING1.getBytes());
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertProfileOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testUninstallAllUserCaCerts_failIfNotProfileOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testUninstallAllUserCaCerts_failIfNotProfileOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.uninstallAllUserCaCerts(mComponent);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertProfileOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testSetScreenCaptureDisabled_failIfNotProfileOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSetScreenCaptureDisabled_failIfNotProfileOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.setScreenCaptureDisabled(mComponent, true);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertProfileOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testSetAutoTimeRequired_failIfNotDeviceOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSetAutoTimeRequired_failIfNotDeviceOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.setAutoTimeRequired(mComponent, true);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertDeviceOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testAddPersistentPreferredActivity_failIfNotProfileOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testAddPersistentPreferredActivity_failIfNotProfileOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.addPersistentPreferredActivity(mComponent,
+                    new IntentFilter(Intent.ACTION_MAIN),
+                    new ComponentName("android.admin.cts", "dummy"));
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertProfileOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testClearPackagePersistentPreferredActivities_failIfNotProfileOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testClearPackagePersistentPreferredActivities_failIfNotProfileOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.clearPackagePersistentPreferredActivities(mComponent,
+                    "android.admin.cts");
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertProfileOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testSetApplicationRestrictions_failIfNotProfileOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSetApplicationRestrictions_failIfNotProfileOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.setApplicationRestrictions(mComponent,
+                    "android.admin.cts", null);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertProfileOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testAddUserRestriction_failIfNotProfileOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testAddUserRestriction_failIfNotProfileOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.addUserRestriction(mComponent,
+                    UserManager.DISALLOW_SMS);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertProfileOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testSetAccountManagementDisabled_failIfNotProfileOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSetAccountManagementDisabled_failIfNotProfileOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.setAccountManagementDisabled(mComponent,
+                    "dummy", true);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertProfileOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testSetRestrictionsProvider_failIfNotProfileOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSetRestrictionsProvider_failIfNotProfileOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.setRestrictionsProvider(mComponent,
+                    new ComponentName("android.admin.cts", "dummy"));
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertProfileOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testSetUninstallBlocked_failIfNotProfileOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSetUninstallBlocked_failIfNotProfileOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.setUninstallBlocked(mComponent,
+                    "android.admin.cts", true);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertProfileOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testSetPermittedAccessibilityServices_failIfNotProfileOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSetPermittedAccessibilityServices_failIfNotProfileOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.setPermittedAccessibilityServices(mComponent, null);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertProfileOwnerMessage(e.getMessage());
+        }
+    }
+
+    public void testSetPermittedInputMethods_failIfNotProfileOwner() {
+        if (!mDeviceAdmin) {
+            Log.w(TAG, "Skipping testSetPermittedInputMethods_failIfNotProfileOwner");
+            return;
+        }
+        try {
+            mDevicePolicyManager.setPermittedInputMethods(mComponent, null);
+            fail("did not throw expected SecurityException");
+        } catch (SecurityException e) {
+            assertProfileOwnerMessage(e.getMessage());
+        }
+    }
+
+    private void assertDeviceOwnerMessage(String message) {
+        assertTrue("message is: "+ message, message.contains("does not own the device")
+                || message.contains("can only be called by the device owner"));
+    }
+
+    private void assertProfileOwnerMessage(String message) {
+        assertTrue("message is: "+ message,
+                message.contains("does not own the profile"));
+    }
+
+    private void resetComplexPasswordRestrictions() {
+        /**
+         * Not enough to reset only mComponent as
+         * {@link DevicePolicyManager#resetPassword(String, int)} checks restrictions across all
+         * admin components.
+         */
+        for (ComponentName adminComponent : new ComponentName[] {mComponent, mSecondComponent}) {
+            mDevicePolicyManager.setPasswordMinimumLength(adminComponent, 0);
+            mDevicePolicyManager.setPasswordMinimumUpperCase(adminComponent, 0);
+            mDevicePolicyManager.setPasswordMinimumLowerCase(adminComponent, 0);
+            mDevicePolicyManager.setPasswordMinimumLetters(adminComponent, 0);
+            mDevicePolicyManager.setPasswordMinimumNumeric(adminComponent, 0);
+            mDevicePolicyManager.setPasswordMinimumSymbols(adminComponent, 0);
+            mDevicePolicyManager.setPasswordMinimumNonLetter(adminComponent, 0);
+        }
+    }
+
+    private void assertPasswordFails(String password, String restriction) {
+        boolean passwordResetResult = mDevicePolicyManager.resetPassword(password, /* flags= */0);
+        assertFalse("Password '" + password + "' should have failed on " + restriction,
+                passwordResetResult);
+    }
+
+    private void assertPasswordSucceeds(String password, String restriction) {
+        boolean passwordResetResult = mDevicePolicyManager.resetPassword(password, /* flags= */0);
+        assertTrue("Password '" + password + "' failed on " + restriction, passwordResetResult);
+        assertTrue(mDevicePolicyManager.isActivePasswordSufficient());
+    }
 }
diff --git a/tests/tests/animation/Android.mk b/tests/tests/animation/Android.mk
index a83bb65..3d8daf7 100644
--- a/tests/tests/animation/Android.mk
+++ b/tests/tests/animation/Android.mk
@@ -24,9 +24,6 @@
 # When built, explicitly put it in the data partition.
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-# All tests should include android.test.runner.
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/animation/AndroidManifest.xml b/tests/tests/animation/AndroidManifest.xml
index 2212643..fdc5ad9 100644
--- a/tests/tests/animation/AndroidManifest.xml
+++ b/tests/tests/animation/AndroidManifest.xml
@@ -27,8 +27,11 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.cts.animation"
-                     android:label="CTS tests for android.animation package"/>
+                     android:label="CTS tests for android.animation package">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 </manifest>
 
diff --git a/tests/tests/animation/src/android/animation/cts/AnimationActivity.java b/tests/tests/animation/src/android/animation/cts/AnimationActivity.java
index 555ab15..225a97e 100644
--- a/tests/tests/animation/src/android/animation/cts/AnimationActivity.java
+++ b/tests/tests/animation/src/android/animation/cts/AnimationActivity.java
@@ -145,6 +145,11 @@
         view.animateBall();
     }
 
+    public void startSingleAnimation(Animator animator) {
+        animator.setTarget(view.newBall);
+        animator.start();
+    }
+
     public void startAnimation(ValueAnimator valueAnimator){
         view.bounceYAnimator = valueAnimator;
         view.startColorAnimator();
diff --git a/tests/tests/animation/src/android/animation/cts/AnimatorTest.java b/tests/tests/animation/src/android/animation/cts/AnimatorTest.java
index 5f07afb..fac9ff9 100644
--- a/tests/tests/animation/src/android/animation/cts/AnimatorTest.java
+++ b/tests/tests/animation/src/android/animation/cts/AnimatorTest.java
@@ -19,6 +19,7 @@
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
 import android.view.animation.AccelerateInterpolator;
 
 import java.util.List;
@@ -55,7 +56,8 @@
         assertEquals(startDelay, mAnimator.getStartDelay());
     }
 
-    public void testStart() {
+    @UiThreadTest
+    public void testStart() throws Exception {
         mAnimator.start();
         assertTrue(mAnimator.isRunning());
         assertTrue(mAnimator.isStarted());
@@ -135,10 +137,20 @@
         assertFalse(listener.mEnd);
         assertTrue(listener.mRepeat >= 0);
 
-        mAnimator.cancel();
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mAnimator.cancel();
+            }
+        });
+        getInstrumentation().waitForIdleSync();
         assertTrue(listener.mCancel);
 
-        mAnimator.end();
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mAnimator.end();
+            }
+        });
+        getInstrumentation().waitForIdleSync();
         assertTrue(listener.mEnd);
     }
 
diff --git a/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java b/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java
index f8f1f43..f0db168 100644
--- a/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java
+++ b/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java
@@ -88,13 +88,18 @@
         int startColor = mActivity.view.RED;
         int endColor = mActivity.view.BLUE;
 
-        ObjectAnimator colorAnimator = ObjectAnimator.ofInt(object, property,
+        final ObjectAnimator colorAnimator = ObjectAnimator.ofInt(object, property,
                 startColor, endColor);
         colorAnimator.setDuration(1000);
         colorAnimator.setEvaluator(new ArgbEvaluator());
         colorAnimator.setRepeatCount(1);
         colorAnimator.setRepeatMode(ValueAnimator.REVERSE);
-        colorAnimator.start();
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                colorAnimator.start();
+            }
+        });
+        getInstrumentation().waitForIdleSync();
         startAnimation(mObjectAnimator, colorAnimator);
         Thread.sleep(100);
         Integer i = (Integer) colorAnimator.getAnimatedValue();
@@ -110,12 +115,17 @@
         int endColor = mActivity.view.BLUE;
         Object[] values = {new Integer(startColor), new Integer(endColor)};
         ArgbEvaluator evaluator = new ArgbEvaluator();
-        ObjectAnimator colorAnimator = ObjectAnimator.ofObject(object, property,
+        final ObjectAnimator colorAnimator = ObjectAnimator.ofObject(object, property,
                 evaluator, values);
         colorAnimator.setDuration(1000);
         colorAnimator.setRepeatCount(1);
         colorAnimator.setRepeatMode(ValueAnimator.REVERSE);
-        colorAnimator.start();
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                colorAnimator.start();
+            }
+        });
+        getInstrumentation().waitForIdleSync();
         startAnimation(mObjectAnimator, colorAnimator);
         Thread.sleep(100);
         Integer i = (Integer) colorAnimator.getAnimatedValue();
@@ -132,12 +142,17 @@
         int values[] = {startColor, endColor};
         ArgbEvaluator evaluator = new ArgbEvaluator();
         PropertyValuesHolder propertyValuesHolder = PropertyValuesHolder.ofInt(propertyName, values);
-        ObjectAnimator colorAnimator = ObjectAnimator.ofPropertyValuesHolder(object,
+        final ObjectAnimator colorAnimator = ObjectAnimator.ofPropertyValuesHolder(object,
             propertyValuesHolder);
         colorAnimator.setDuration(1000);
         colorAnimator.setRepeatCount(1);
         colorAnimator.setRepeatMode(ValueAnimator.REVERSE);
-        colorAnimator.start();
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                colorAnimator.start();
+            }
+        });
+        getInstrumentation().waitForIdleSync();
         startAnimation(mObjectAnimator, colorAnimator);
         Thread.sleep(100);
         Integer i = (Integer) colorAnimator.getAnimatedValue();
diff --git a/tests/tests/animation/src/android/animation/cts/PropertyValuesHolderTest.java b/tests/tests/animation/src/android/animation/cts/PropertyValuesHolderTest.java
index 26db933..200ebce 100644
--- a/tests/tests/animation/src/android/animation/cts/PropertyValuesHolderTest.java
+++ b/tests/tests/animation/src/android/animation/cts/PropertyValuesHolderTest.java
@@ -16,15 +16,21 @@
 package android.animation.cts;
 
 import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.ArgbEvaluator;
+import android.animation.Keyframe;
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
 import android.animation.ValueAnimator;
+import android.graphics.drawable.ShapeDrawable;
 import android.test.ActivityInstrumentationTestCase2;
 import android.util.Property;
 import android.view.View;
 import android.view.animation.AccelerateInterpolator;
 
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
 public class PropertyValuesHolderTest extends
         ActivityInstrumentationTestCase2<AnimationActivity> {
     private AnimationActivity mActivity;
@@ -86,6 +92,113 @@
         assertResults(yArray, mStartY, mEndY);
     }
 
+    private ObjectAnimator createAnimator(Keyframe... keyframes) {
+        PropertyValuesHolder pVHolder = PropertyValuesHolder.ofKeyframe(mProperty, keyframes);
+        ObjectAnimator objAnimator = ObjectAnimator.ofPropertyValuesHolder(mObject,pVHolder);
+        objAnimator.setDuration(mDuration);
+        objAnimator.setInterpolator(new AccelerateInterpolator());
+        return objAnimator;
+    }
+
+    private void waitUntilFinished(ObjectAnimator objectAnimator, long timeoutMilliseconds)
+            throws InterruptedException {
+        final CountDownLatch latch = new CountDownLatch(1);
+        objectAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                super.onAnimationEnd(animation);
+                latch.countDown();
+            }
+        });
+        latch.await(timeoutMilliseconds, TimeUnit.MILLISECONDS);
+        getInstrumentation().waitForIdleSync();
+    }
+
+    private void setTarget(final Animator animator, final Object target) throws Throwable {
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                animator.setTarget(target);
+            }
+        });
+    }
+
+    private void startSingleAnimation(final Animator animator) throws Throwable {
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mActivity.startSingleAnimation(animator);
+            }
+        });
+    }
+
+    public void testResetValues() throws Throwable {
+        final float initialY = mActivity.view.newBall.getY();
+        Keyframe emptyKeyframe1 = Keyframe.ofFloat(.0f);
+        ObjectAnimator objAnimator1 = createAnimator(emptyKeyframe1, Keyframe.ofFloat(1f, 100f));
+        startSingleAnimation(objAnimator1);
+        assertTrue("Keyframe should be assigned a value", emptyKeyframe1.hasValue());
+        assertEquals("Keyframe should get the value from the target", emptyKeyframe1.getValue(),
+                initialY);
+        waitUntilFinished(objAnimator1, mDuration * 2);
+        assertEquals(100f, mActivity.view.newBall.getY());
+        startSingleAnimation(objAnimator1);
+        waitUntilFinished(objAnimator1, mDuration * 2);
+
+        // run another ObjectAnimator that will move the Y value to something else
+        Keyframe emptyKeyframe2 = Keyframe.ofFloat(.0f);
+        ObjectAnimator objAnimator2 = createAnimator(emptyKeyframe2, Keyframe.ofFloat(1f, 200f));
+        startSingleAnimation(objAnimator2);
+        assertTrue("Keyframe should be assigned a value", emptyKeyframe2.hasValue());
+        assertEquals("Keyframe should get the value from the target", emptyKeyframe2.getValue(), 100f);
+        waitUntilFinished(objAnimator2, mDuration * 2);
+        assertEquals(200f, mActivity.view.newBall.getY());
+
+        // re-run first object animator. since its target did not change, it should have the same
+        // start value for kf1
+        startSingleAnimation(objAnimator1);
+        assertEquals(emptyKeyframe1.getValue(), initialY);
+        waitUntilFinished(objAnimator1, mDuration * 2);
+
+        Keyframe fullKeyframe = Keyframe.ofFloat(.0f, 333f);
+        ObjectAnimator objAnimator3 = createAnimator(fullKeyframe, Keyframe.ofFloat(1f, 500f));
+        startSingleAnimation(objAnimator3);
+        assertEquals("When keyframe has value, should not be assigned from the target object",
+                fullKeyframe.getValue(), 333f);
+        waitUntilFinished(objAnimator3, mDuration * 2);
+
+        // now, null out the target of the first animator
+        float updatedY = mActivity.view.newBall.getY();
+        setTarget(objAnimator1, null);
+        startSingleAnimation(objAnimator1);
+        assertTrue("Keyframe should get a value", emptyKeyframe1.hasValue());
+        assertEquals("Keyframe should get the updated Y value", emptyKeyframe1.getValue(), updatedY);
+        waitUntilFinished(objAnimator1, mDuration * 2);
+        assertEquals("Animation should run as expected", 100f, mActivity.view.newBall.getY());
+
+        // now, reset the target of the fully defined animation.
+        setTarget(objAnimator3, null);
+        startSingleAnimation(objAnimator3);
+        assertEquals("When keyframe is fully defined, its value should not change when target is"
+                + " reset", fullKeyframe.getValue(), 333f);
+        waitUntilFinished(objAnimator3, mDuration * 2);
+
+        // run the other one to change Y value
+        startSingleAnimation(objAnimator2);
+        waitUntilFinished(objAnimator2, mDuration * 2);
+        // now, set another target w/ the same View type. it should still reset
+        ShapeHolder view = new ShapeHolder(new ShapeDrawable());
+        updatedY = mActivity.view.newBall.getY();
+        setTarget(objAnimator1, view);
+        startSingleAnimation(objAnimator1);
+        assertTrue("Keyframe should get a value when target is set to another view of the same"
+                + " class", emptyKeyframe1.hasValue());
+        assertEquals("Keyframe should get the updated Y value when target is set to another view"
+                + " of the same class", emptyKeyframe1.getValue(), updatedY);
+        waitUntilFinished(objAnimator1, mDuration * 2);
+        assertEquals("Animation should run as expected", 100f, mActivity.view.newBall.getY());
+    }
+
     public void testOffloat() throws Throwable {
         float[] values = {mStartY, mEndY};
         PropertyValuesHolder pVHolder = PropertyValuesHolder.ofFloat(mProperty, values);
diff --git a/tests/tests/app.usage/Android.mk b/tests/tests/app.usage/Android.mk
new file mode 100644
index 0000000..f245e5f
--- /dev/null
+++ b/tests/tests/app.usage/Android.mk
@@ -0,0 +1,33 @@
+# 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsUsageStatsTestCases
+
+# 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_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/app.usage/AndroidManifest.xml b/tests/tests/app.usage/AndroidManifest.xml
new file mode 100644
index 0000000..11065d4
--- /dev/null
+++ b/tests/tests/app.usage/AndroidManifest.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2007 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.app.usage.cts">
+
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
+    <uses-permission android:name="android.permission.SET_TIME" />
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+
+        <activity android:name=".Activities$ActivityOne" />
+        <activity android:name=".Activities$ActivityTwo" />
+        <activity android:name=".Activities$ActivityThree" />
+        <activity android:name=".Activities$ActivityFour" />
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="android.app.usage.cts"
+                     android:label="CTS tests of android.app.usage">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
+
+</manifest>
+
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/Activities.java b/tests/tests/app.usage/src/android/app/usage/cts/Activities.java
new file mode 100644
index 0000000..35c7904
--- /dev/null
+++ b/tests/tests/app.usage/src/android/app/usage/cts/Activities.java
@@ -0,0 +1,38 @@
+/**
+ * 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.app.usage.cts;
+
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.WindowManager;
+
+public final class Activities {
+    private static class KeepScreenOnActivity extends Activity {
+        @Override
+        protected void onCreate(@Nullable Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+        }
+    }
+
+    public static class ActivityOne extends KeepScreenOnActivity {}
+    public static class ActivityTwo extends KeepScreenOnActivity {}
+    public static class ActivityThree extends KeepScreenOnActivity {}
+    public static class ActivityFour extends KeepScreenOnActivity {}
+
+    private Activities() {}
+}
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
new file mode 100644
index 0000000..5b1909a
--- /dev/null
+++ b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
@@ -0,0 +1,304 @@
+/**
+ * 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.app.usage.cts;
+
+import android.app.Activity;
+import android.app.AppOpsManager;
+import android.app.Instrumentation;
+import android.app.usage.UsageEvents;
+import android.app.usage.UsageStats;
+import android.app.usage.UsageStatsManager;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
+import android.os.SystemClock;
+import android.test.InstrumentationTestCase;
+
+import java.io.FileInputStream;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import android.util.SparseLongArray;
+import junit.framework.AssertionFailedError;
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+import org.junit.Ignore;
+
+/**
+ * Test the UsageStats API. It is difficult to test the entire surface area
+ * of the API, as a lot of the testing depends on what data is already present
+ * on the device and for how long that data has been aggregating.
+ *
+ * These tests perform simple checks that each interval is of the correct duration,
+ * and that events do appear in the event log.
+ *
+ * Tests to add that are difficult to add now:
+ * - Invoking a device configuration change and then watching for it in the event log.
+ * - Changing the system time and verifying that all data has been correctly shifted
+ *   along with the new time.
+ * - Proper eviction of old data.
+ */
+public class UsageStatsTest extends InstrumentationTestCase {
+    private static final String APPOPS_SET_SHELL_COMMAND = "appops set {0} " +
+            AppOpsManager.OPSTR_GET_USAGE_STATS + " {1}";
+
+    private static final long MINUTE = 1000 * 60;
+    private static final long DAY = MINUTE * 60 * 24;
+    private static final long WEEK = 7 * DAY;
+    private static final long MONTH = 30 * DAY;
+    private static final long YEAR = 365 * DAY;
+    private static final long TIME_DIFF_THRESHOLD = 200;
+
+    private UsageStatsManager mUsageStatsManager;
+    private String mTargetPackage;
+    private ArrayList<Activity> mStartedActivities = new ArrayList<>();
+
+    @Override
+    protected void setUp() throws Exception {
+        mUsageStatsManager = (UsageStatsManager) getInstrumentation().getContext()
+                .getSystemService(Context.USAGE_STATS_SERVICE);
+        mTargetPackage = getInstrumentation().getContext().getPackageName();
+
+        setAppOpsMode("allow");
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        for (Activity activity : mStartedActivities) {
+            activity.finish();
+        }
+    }
+
+    private static void assertLessThan(long left, long right) {
+        if (left >= right) {
+            throw new AssertionFailedError("Expected " + left + " to be less than " + right);
+        }
+    }
+
+    private static void assertLessThanOrEqual(long left, long right) {
+        if (left > right) {
+            throw new AssertionFailedError("Expected " + left + " to be less than or equal to " + right);
+        }
+    }
+
+    private void setAppOpsMode(String mode) throws Exception {
+        final String command = MessageFormat.format(APPOPS_SET_SHELL_COMMAND,
+                getInstrumentation().getContext().getPackageName(), mode);
+        ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation()
+                .executeShellCommand(command);
+        try {
+            Streams.readFully(new FileInputStream(pfd.getFileDescriptor()));
+        } finally {
+            IoUtils.closeQuietly(pfd.getFileDescriptor());
+        }
+    }
+
+    private void launchSubActivity(Class<? extends Activity> clazz) {
+        final Instrumentation.ActivityResult result = new Instrumentation.ActivityResult(0, new Intent());
+        final Instrumentation.ActivityMonitor monitor = new Instrumentation.ActivityMonitor(clazz.getName(), result, false);
+        getInstrumentation().addMonitor(monitor);
+        launchActivity(mTargetPackage, clazz, null);
+        mStartedActivities.add(monitor.waitForActivity());
+    }
+
+    private void launchSubActivities(Class<? extends Activity>[] activityClasses) {
+        for (Class<? extends Activity> clazz : activityClasses) {
+            launchSubActivity(clazz);
+        }
+    }
+
+    public void testOrderedActivityLaunchSequenceInEventLog() throws Exception {
+        @SuppressWarnings("unchecked")
+        Class<? extends Activity>[] activitySequence = new Class[] {
+                Activities.ActivityOne.class,
+                Activities.ActivityTwo.class,
+                Activities.ActivityThree.class,
+        };
+
+        // Launch the series of Activities.
+        launchSubActivities(activitySequence);
+
+        final long endTime = System.currentTimeMillis();
+        final long startTime = endTime - DAY;
+        UsageEvents events = mUsageStatsManager.queryEvents(startTime, endTime);
+
+        // Consume all the events.
+        ArrayList<UsageEvents.Event> eventList = new ArrayList<>();
+        while (events.hasNextEvent()) {
+            UsageEvents.Event event = new UsageEvents.Event();
+            assertTrue(events.getNextEvent(event));
+            eventList.add(event);
+        }
+
+        // We expect 2 events per Activity launched (foreground + background)
+        // except for the last Activity, which was in the foreground when
+        // we queried the event log.
+        assertTrue(eventList.size() >= (activitySequence.length * 2) - 1);
+        final int offset = eventList.size() - ((activitySequence.length * 2) - 1);
+
+        final int activityCount = activitySequence.length;
+        for (int i = 0; i < activityCount; i++) {
+            int index = offset + (i * 2);
+
+            // Check for foreground event.
+            UsageEvents.Event event = eventList.get(index);
+            assertEquals(mTargetPackage, event.getPackageName());
+            assertEquals(activitySequence[i].getName(), event.getClassName());
+            assertEquals(UsageEvents.Event.MOVE_TO_FOREGROUND, event.getEventType());
+
+            index += 1;
+            if (i < activityCount - 1) {
+                // Check for background event.
+                event = eventList.get(index);
+                assertEquals(mTargetPackage, event.getPackageName());
+                assertEquals(activitySequence[i].getName(), event.getClassName());
+                assertEquals(UsageEvents.Event.MOVE_TO_BACKGROUND, event.getEventType());
+            }
+        }
+    }
+
+    /**
+     * We can't run this test because we are unable to change the system time.
+     * It would be nice to add a shell command or other to allow the shell user
+     * to set the time, thereby allowing this test to set the time using the UIAutomator.
+     */
+    @Ignore
+    public void ignore_testStatsAreShiftedInTimeWhenSystemTimeChanges() throws Exception {
+        launchSubActivity(Activities.ActivityOne.class);
+
+        long endTime = System.currentTimeMillis();
+        long startTime = endTime - MINUTE;
+        Map<String, UsageStats> statsMap = mUsageStatsManager.queryAndAggregateUsageStats(startTime, endTime);
+        assertFalse(statsMap.isEmpty());
+        assertTrue(statsMap.containsKey(mTargetPackage));
+        final UsageStats before = statsMap.get(mTargetPackage);
+
+        SystemClock.setCurrentTimeMillis(System.currentTimeMillis() - (DAY / 2));
+        try {
+            endTime = System.currentTimeMillis();
+            startTime = endTime - MINUTE;
+            statsMap = mUsageStatsManager.queryAndAggregateUsageStats(startTime, endTime);
+            assertFalse(statsMap.isEmpty());
+            assertTrue(statsMap.containsKey(mTargetPackage));
+            final UsageStats after = statsMap.get(mTargetPackage);
+            assertEquals(before.getPackageName(), after.getPackageName());
+
+            long diff = before.getFirstTimeStamp() - after.getFirstTimeStamp();
+            assertLessThan(Math.abs(diff - (DAY / 2)), TIME_DIFF_THRESHOLD);
+
+            assertEquals(before.getLastTimeStamp() - before.getFirstTimeStamp(),
+                    after.getLastTimeStamp() - after.getFirstTimeStamp());
+            assertEquals(before.getLastTimeUsed() - before.getFirstTimeStamp(),
+                    after.getLastTimeUsed() - after.getFirstTimeStamp());
+            assertEquals(before.getTotalTimeInForeground(), after.getTotalTimeInForeground());
+        } finally {
+            SystemClock.setCurrentTimeMillis(System.currentTimeMillis() + (DAY / 2));
+        }
+    }
+
+    public void testUsageEventsParceling() throws Exception {
+        final long startTime = System.currentTimeMillis();
+
+        @SuppressWarnings("unchecked")
+        Class<? extends Activity>[] activityClasses = new Class[] {
+                Activities.ActivityOne.class,
+                Activities.ActivityThree.class,
+                Activities.ActivityTwo.class,
+        };
+        launchSubActivities(activityClasses);
+
+        final long endTime = System.currentTimeMillis();
+        UsageEvents events = mUsageStatsManager.queryEvents(startTime - TIME_DIFF_THRESHOLD, endTime);
+        assertTrue(events.getNextEvent(new UsageEvents.Event()));
+
+        Parcel p = Parcel.obtain();
+        p.setDataPosition(0);
+        events.writeToParcel(p, 0);
+        p.setDataPosition(0);
+
+        UsageEvents reparceledEvents = UsageEvents.CREATOR.createFromParcel(p);
+
+        UsageEvents.Event e1 = new UsageEvents.Event();
+        UsageEvents.Event e2 = new UsageEvents.Event();
+        while (events.hasNextEvent() && reparceledEvents.hasNextEvent()) {
+            events.getNextEvent(e1);
+            reparceledEvents.getNextEvent(e2);
+            assertEquals(e1.getPackageName(), e2.getPackageName());
+            assertEquals(e1.getClassName(), e2.getClassName());
+            assertEquals(e1.getConfiguration(), e2.getConfiguration());
+            assertEquals(e1.getEventType(), e2.getEventType());
+            assertEquals(e1.getTimeStamp(), e2.getTimeStamp());
+        }
+
+        assertEquals(events.hasNextEvent(), reparceledEvents.hasNextEvent());
+    }
+
+    public void testPackageUsageStatsIntervals() throws Exception {
+        final long beforeTime = System.currentTimeMillis();
+
+        // Launch an Activity.
+        launchSubActivity(Activities.ActivityFour.class);
+
+        final long endTime = System.currentTimeMillis();
+
+        final SparseLongArray intervalLengths = new SparseLongArray();
+        intervalLengths.put(UsageStatsManager.INTERVAL_DAILY, DAY);
+        intervalLengths.put(UsageStatsManager.INTERVAL_WEEKLY, WEEK);
+        intervalLengths.put(UsageStatsManager.INTERVAL_MONTHLY, MONTH);
+        intervalLengths.put(UsageStatsManager.INTERVAL_YEARLY, YEAR);
+
+        final int intervalCount = intervalLengths.size();
+        for (int i = 0; i < intervalCount; i++) {
+            final int intervalType = intervalLengths.keyAt(i);
+            final long intervalDuration = intervalLengths.valueAt(i);
+            final long startTime = endTime - (2 * intervalDuration);
+            final List<UsageStats> statsList = mUsageStatsManager.queryUsageStats(intervalType, startTime, endTime);
+            assertFalse(statsList.isEmpty());
+
+            boolean foundPackage = false;
+            for (UsageStats stats : statsList) {
+                // Verify that each period is a day long.
+                assertLessThanOrEqual(stats.getLastTimeStamp() - stats.getFirstTimeStamp(), intervalDuration);
+                if (stats.getPackageName().equals(mTargetPackage) &&
+                        stats.getLastTimeUsed() >= beforeTime - TIME_DIFF_THRESHOLD) {
+                    foundPackage = true;
+                }
+            }
+
+            assertTrue("Did not find package " + mTargetPackage + " in interval " + intervalType, foundPackage);
+        }
+    }
+
+    public void testNoAccessSilentlyFails() throws Exception {
+        launchSubActivity(Activities.ActivityOne.class);
+
+        final long endTime = System.currentTimeMillis();
+        final long startTime = endTime - MINUTE;
+        List<UsageStats> stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_BEST,
+                startTime, endTime);
+        assertFalse(stats.isEmpty());
+
+        setAppOpsMode("default");
+
+        stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_BEST,
+                startTime, endTime);
+        assertTrue(stats.isEmpty());
+    }
+}
diff --git a/tests/tests/app/Android.mk b/tests/tests/app/Android.mk
index d4387b4..39be0dc 100644
--- a/tests/tests/app/Android.mk
+++ b/tests/tests/app/Android.mk
@@ -23,12 +23,12 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common voip-common
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner ctstestserver
 
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
 
 LOCAL_PACKAGE_NAME := CtsAppTestCases
 
-LOCAL_INSTRUMENTATION_FOR := CtsTestStubs
+LOCAL_INSTRUMENTATION_FOR := CtsAppTestStubs
 
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/app/AndroidManifest.xml b/tests/tests/app/AndroidManifest.xml
index acfc3c8..08b0dda 100644
--- a/tests/tests/app/AndroidManifest.xml
+++ b/tests/tests/app/AndroidManifest.xml
@@ -16,16 +16,20 @@
  -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.app.cts">
+    package="com.android.cts.app">
 
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+
     <application>
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="com.android.cts.stub"
-                     android:label="CTS tests of android.app"/>
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.app.stub"
+                     android:label="CTS tests of android.app">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/tests/app/src/android/app/backup/cts/BackupManagerTest.java b/tests/tests/app/src/android/app/backup/cts/BackupManagerTest.java
index f21f847..1b0a401 100644
--- a/tests/tests/app/src/android/app/backup/cts/BackupManagerTest.java
+++ b/tests/tests/app/src/android/app/backup/cts/BackupManagerTest.java
@@ -26,7 +26,7 @@
         // Check that these don't crash as if they were called in an app...
         BackupManager backupManager = new BackupManager(mContext);
         backupManager.dataChanged();
-        BackupManager.dataChanged("com.android.cts.stub");
+        BackupManager.dataChanged("com.android.cts.app.stub");
 
         // Backup isn't expected to work in this test but check for obvious bugs...
         int result = backupManager.requestRestore(new RestoreObserver() {});
diff --git a/tests/tests/app/src/android/app/cts/ActivityManagerMemoryClassTest.java b/tests/tests/app/src/android/app/cts/ActivityManagerMemoryClassTest.java
index 408efe7..7d3fc5e 100644
--- a/tests/tests/app/src/android/app/cts/ActivityManagerMemoryClassTest.java
+++ b/tests/tests/app/src/android/app/cts/ActivityManagerMemoryClassTest.java
@@ -98,6 +98,10 @@
                 expectedMinimumMemory = isXLarge ? 256 : 128;
                 break;
 
+            case DisplayMetrics.DENSITY_560:
+                expectedMinimumMemory = isXLarge ? 512 : 256;
+                break;
+
             case DisplayMetrics.DENSITY_XXXHIGH:
                 expectedMinimumMemory = isXLarge ? 512 : 256;
                 break;
diff --git a/tests/tests/app/src/android/app/cts/ActivityManagerTest.java b/tests/tests/app/src/android/app/cts/ActivityManagerTest.java
index 8b1a153..e633f1f 100644
--- a/tests/tests/app/src/android/app/cts/ActivityManagerTest.java
+++ b/tests/tests/app/src/android/app/cts/ActivityManagerTest.java
@@ -35,7 +35,7 @@
 import android.test.InstrumentationTestCase;
 
 public class ActivityManagerTest extends InstrumentationTestCase {
-    private static final String STUB_PACKAGE_NAME = "com.android.cts.stub";
+    private static final String STUB_PACKAGE_NAME = "com.android.cts.app.stub";
     private static final int WAITFOR_MSEC = 5000;
     private static final String SERVICE_NAME = "android.app.cts.MockService";
     private static final int WAIT_TIME = 2000;
@@ -222,12 +222,13 @@
         assertTrue(hasSystemProcess && hasTestProcess);
 
         for (RunningAppProcessInfo ra : list) {
-            if (ra.processName.equals("com.android.cts.stub:remote")) {
-                fail("should be no process named com.android.cts.stub:remote");
+            if (ra.processName.equals("com.android.cts.app.stub:remote")) {
+                fail("should be no process named com.android.cts.app.stub:remote");
             }
         }
         // start a new process
         mIntent = new Intent("android.app.REMOTESERVICE");
+        mIntent.setPackage("com.android.cts.app.stub");
         mInstrumentation.getTargetContext().startService(mIntent);
         Thread.sleep(WAITFOR_MSEC);
 
@@ -235,11 +236,11 @@
         assertTrue(list.size() <= listNew.size());
 
         for (RunningAppProcessInfo ra : listNew) {
-            if (ra.processName.equals("com.android.cts.stub:remote")) {
+            if (ra.processName.equals("com.android.cts.app.stub:remote")) {
                 return;
             }
         }
-        fail("com.android.cts.stub:remote process should be available");
+        fail("com.android.cts.app.stub:remote process should be available");
     }
 
     public void testGetProcessInErrorState() throws Exception {
diff --git a/tests/tests/app/src/android/app/cts/AlarmManagerTest.java b/tests/tests/app/src/android/app/cts/AlarmManagerTest.java
index 0780101..bfc3e1d 100644
--- a/tests/tests/app/src/android/app/cts/AlarmManagerTest.java
+++ b/tests/tests/app/src/android/app/cts/AlarmManagerTest.java
@@ -25,45 +25,86 @@
 import android.cts.util.PollingCheck;
 import android.os.SystemClock;
 import android.test.AndroidTestCase;
+import android.util.Log;
 
 public class AlarmManagerTest extends AndroidTestCase {
-    private AlarmManager mAlarmManager;
+    public static final String MOCKACTION = "android.app.AlarmManagerTest.TEST_ALARMRECEIVER";
+    public static final String MOCKACTION2 = "android.app.AlarmManagerTest.TEST_ALARMRECEIVER2";
+
+    private AlarmManager mAm;
     private Intent mIntent;
     private PendingIntent mSender;
-    private Intent mServiceIntent;
+    private Intent mIntent2;
+    private PendingIntent mSender2;
 
     /*
      *  The default snooze delay: 5 seconds
      */
-    private final long SNOOZE_DELAY = 5 * 1000L;
+    private static final long SNOOZE_DELAY = 5 * 1000L;
     private long mWakeupTime;
     private MockAlarmReceiver mMockAlarmReceiver;
+    private MockAlarmReceiver mMockAlarmReceiver2;
 
-    private final int TIME_DELTA = 1000;
-    private final int TIME_DELAY = 5000;
+    private static final int TIME_DELTA = 1000;
+    private static final int TIME_DELAY = 10000;
 
-    class Sync {
-        public boolean mIsConnected;
-        public boolean mIsDisConnected;
-    }
+    // Receiver registration/unregistration between tests races with the system process, so
+    // we add a little buffer time here to allow the system to process before we proceed.
+    // This value is in milliseconds.
+    private static final long REGISTER_PAUSE = 250;
+
+    // Constants used for validating exact vs inexact alarm batching immunity.  We run a few
+    // trials of an exact alarm that is placed within an inexact alarm's window of opportunity,
+    // and mandate that the average observed delivery skew between the two be statistically
+    // significant -- i.e. that the two alarms are not being coalesced.  We also place an
+    // additional exact alarm only a short time after the inexact alarm's nominal trigger time.
+    // If exact alarms are allowed to batch with inexact ones this will tend to have no effect,
+    // but in the correct behavior -- inexact alarms not permitted to batch with exact ones --
+    // this additional exact alarm will have the effect of guaranteeing that the inexact alarm
+    // must fire no later than it -- i.e. a considerable time before the significant, later
+    // exact alarm.
+    //
+    // The test essentially amounts to requiring that the inexact MOCKACTION alarm and
+    // the much later exact MOCKACTION2 alarm fire far apart, always; with an implicit
+    // insistence that alarm batches are delivered at the head of their window.
+    private static final long TEST_WINDOW_LENGTH = 5 * 1000L;
+    private static final long TEST_ALARM_FUTURITY = 6 * 1000L;
+    private static final long FAIL_DELTA = 50;
+    private static final long NUM_TRIALS = 5;
+    private static final long MAX_NEAR_DELIVERIES = 2;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
-        mIntent = new Intent(MockAlarmReceiver.MOCKACTION);
+
+        mAm = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
+
+        mIntent = new Intent(MOCKACTION)
+                .addFlags(Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_REGISTERED_ONLY);
         mSender = PendingIntent.getBroadcast(mContext, 0, mIntent, 0);
-        mMockAlarmReceiver = new MockAlarmReceiver();
-        IntentFilter filter = new IntentFilter(MockAlarmReceiver.MOCKACTION);
+        mMockAlarmReceiver = new MockAlarmReceiver(mIntent.getAction());
+
+        mIntent2 = new Intent(MOCKACTION2)
+                .addFlags(Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+        mSender2 = PendingIntent.getBroadcast(mContext, 0, mIntent2, 0);
+        mMockAlarmReceiver2 = new MockAlarmReceiver(mIntent2.getAction());
+
+        IntentFilter filter = new IntentFilter(mIntent.getAction());
         mContext.registerReceiver(mMockAlarmReceiver, filter);
+
+        IntentFilter filter2 = new IntentFilter(mIntent2.getAction());
+        mContext.registerReceiver(mMockAlarmReceiver2, filter2);
+
+        Thread.sleep(REGISTER_PAUSE);
     }
 
     @Override
     protected void tearDown() throws Exception {
         super.tearDown();
-        if (mServiceIntent != null) {
-            mContext.stopService(mServiceIntent);
-        }
+        mContext.unregisterReceiver(mMockAlarmReceiver);
+        mContext.unregisterReceiver(mMockAlarmReceiver2);
+
+        Thread.sleep(REGISTER_PAUSE);
     }
 
     public void testSetTypes() throws Exception {
@@ -73,7 +114,7 @@
         // test parameter type is RTC_WAKEUP
         mMockAlarmReceiver.setAlarmedFalse();
         mWakeupTime = System.currentTimeMillis() + SNOOZE_DELAY;
-        mAlarmManager.set(AlarmManager.RTC_WAKEUP, mWakeupTime, mSender);
+        mAm.setExact(AlarmManager.RTC_WAKEUP, mWakeupTime, mSender);
         new PollingCheck(SNOOZE_DELAY + TIME_DELAY) {
             @Override
             protected boolean check() {
@@ -85,7 +126,7 @@
         // test parameter type is RTC
         mMockAlarmReceiver.setAlarmedFalse();
         mWakeupTime = System.currentTimeMillis() + SNOOZE_DELAY;
-        mAlarmManager.set(AlarmManager.RTC, mWakeupTime, mSender);
+        mAm.setExact(AlarmManager.RTC, mWakeupTime, mSender);
         new PollingCheck(SNOOZE_DELAY + TIME_DELAY) {
             @Override
             protected boolean check() {
@@ -97,7 +138,7 @@
         // test parameter type is ELAPSED_REALTIME
         mMockAlarmReceiver.setAlarmedFalse();
         mWakeupTime = SystemClock.elapsedRealtime() + SNOOZE_DELAY;
-        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, mWakeupTime, mSender);
+        mAm.setExact(AlarmManager.ELAPSED_REALTIME, mWakeupTime, mSender);
         new PollingCheck(SNOOZE_DELAY + TIME_DELAY) {
             @Override
             protected boolean check() {
@@ -109,7 +150,7 @@
         // test parameter type is ELAPSED_REALTIME_WAKEUP
         mMockAlarmReceiver.setAlarmedFalse();
         mWakeupTime = SystemClock.elapsedRealtime() + SNOOZE_DELAY;
-        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, mWakeupTime, mSender);
+        mAm.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, mWakeupTime, mSender);
         new PollingCheck(SNOOZE_DELAY + TIME_DELAY) {
             @Override
             protected boolean check() {
@@ -125,7 +166,7 @@
         // that would instead cause such alarms to never be triggered.
         mMockAlarmReceiver.setAlarmedFalse();
         mWakeupTime = -1000;
-        mAlarmManager.set(AlarmManager.RTC, mWakeupTime, mSender);
+        mAm.set(AlarmManager.RTC, mWakeupTime, mSender);
         new PollingCheck(TIME_DELAY) {
             @Override
             protected boolean check() {
@@ -134,10 +175,54 @@
         }.run();
     }
 
+    public void testExactAlarmBatching() throws Exception {
+        int deliveriesTogether = 0;
+        for (int i = 0; i < NUM_TRIALS; i++) {
+            final long now = System.currentTimeMillis();
+            final long windowStart = now + TEST_ALARM_FUTURITY;
+            final long exactStart = windowStart + TEST_WINDOW_LENGTH - 1;
+
+            mMockAlarmReceiver.setAlarmedFalse();
+            mMockAlarmReceiver2.setAlarmedFalse();
+            mAm.setWindow(AlarmManager.RTC_WAKEUP, windowStart, TEST_WINDOW_LENGTH, mSender);
+            mAm.setExact(AlarmManager.RTC_WAKEUP, exactStart, mSender2);
+
+            // Wait until a half-second beyond its target window, just to provide a
+            // little safety slop.
+            new PollingCheck(TEST_WINDOW_LENGTH + (windowStart - now) + 500) {
+                @Override
+                protected boolean check() {
+                    return mMockAlarmReceiver.alarmed;
+                }
+            }.run();
+
+            // Now wait until 1 sec beyond the expected exact alarm fire time, or for at
+            // least one second if we're already past the nominal exact alarm fire time
+            long timeToExact = Math.max(exactStart - System.currentTimeMillis() + 1000, 1000);
+            new PollingCheck(timeToExact) {
+                @Override
+                protected boolean check() {
+                    return mMockAlarmReceiver2.alarmed;
+                }
+            }.run();
+
+            // Success when we observe that the exact and windowed alarm are not being often
+            // delivered close together -- that is, when we can be confident that they are not
+            // being coalesced.
+            final long delta = Math.abs(mMockAlarmReceiver2.rtcTime - mMockAlarmReceiver.rtcTime);
+            Log.i("TEST", "[" + i + "]  delta = " + delta);
+            if (delta < FAIL_DELTA) {
+                deliveriesTogether++;
+                assertTrue("Exact alarms appear to be coalescing with inexact alarms",
+                        deliveriesTogether <= MAX_NEAR_DELIVERIES);
+            }
+        }
+    }
+
     public void testSetRepeating() throws Exception {
         mMockAlarmReceiver.setAlarmedFalse();
         mWakeupTime = System.currentTimeMillis() + SNOOZE_DELAY;
-        mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, mWakeupTime, TIME_DELAY / 2, mSender);
+        mAm.setRepeating(AlarmManager.RTC_WAKEUP, mWakeupTime, TIME_DELAY / 2, mSender);
         new PollingCheck(SNOOZE_DELAY + TIME_DELAY) {
             @Override
             protected boolean check() {
@@ -151,13 +236,13 @@
                 return mMockAlarmReceiver.alarmed;
             }
         }.run();
-        mAlarmManager.cancel(mSender);
+        mAm.cancel(mSender);
     }
 
     public void testCancel() throws Exception {
         mMockAlarmReceiver.setAlarmedFalse();
         mWakeupTime = System.currentTimeMillis() + SNOOZE_DELAY;
-        mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, mWakeupTime, 1000, mSender);
+        mAm.setRepeating(AlarmManager.RTC_WAKEUP, mWakeupTime, 1000, mSender);
         new PollingCheck(SNOOZE_DELAY + TIME_DELAY) {
             @Override
             protected boolean check() {
@@ -171,7 +256,7 @@
                 return mMockAlarmReceiver.alarmed;
             }
         }.run();
-        mAlarmManager.cancel(mSender);
+        mAm.cancel(mSender);
         Thread.sleep(TIME_DELAY);
         mMockAlarmReceiver.setAlarmedFalse();
         Thread.sleep(TIME_DELAY * 5);
@@ -179,8 +264,7 @@
     }
 
     public void testSetInexactRepeating() throws Exception {
-
-        mAlarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),
+        mAm.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),
                 AlarmManager.INTERVAL_FIFTEEN_MINUTES, mSender);
         SystemClock.setCurrentTimeMillis(System.currentTimeMillis()
                 + AlarmManager.INTERVAL_FIFTEEN_MINUTES);
diff --git a/tests/tests/app/src/android/app/cts/AlertDialogTest.java b/tests/tests/app/src/android/app/cts/AlertDialogTest.java
index aefcf01..3e9f3b2 100644
--- a/tests/tests/app/src/android/app/cts/AlertDialogTest.java
+++ b/tests/tests/app/src/android/app/cts/AlertDialogTest.java
@@ -45,7 +45,7 @@
     private Button mNeutralButton;
 
     public AlertDialogTest() {
-        super("com.android.cts.stub", DialogStubActivity.class);
+        super("com.android.cts.app.stub", DialogStubActivity.class);
     }
 
     @Override
@@ -75,17 +75,17 @@
         mPositiveButton = ((AlertDialog) (mActivity.getDialog())).getButton(
                 DialogInterface.BUTTON_POSITIVE);
         assertNotNull(mPositiveButton);
-        assertEquals(mActivity.getString(com.android.cts.stub.R.string.alert_dialog_positive),
+        assertEquals(mActivity.getString(com.android.cts.app.stub.R.string.alert_dialog_positive),
                 mPositiveButton.getText());
         mNeutralButton = ((AlertDialog) (mActivity.getDialog())).getButton(
                 DialogInterface.BUTTON_NEUTRAL);
         assertNotNull(mNeutralButton);
-        assertEquals(mActivity.getString(com.android.cts.stub.R.string.alert_dialog_neutral),
+        assertEquals(mActivity.getString(com.android.cts.app.stub.R.string.alert_dialog_neutral),
                 mNeutralButton.getText());
         mNegativeButton = ((AlertDialog) (mActivity.getDialog())).getButton(
                 DialogInterface.BUTTON_NEGATIVE);
         assertNotNull(mNegativeButton);
-        assertEquals(mActivity.getString(com.android.cts.stub.R.string.alert_dialog_negative),
+        assertEquals(mActivity.getString(com.android.cts.app.stub.R.string.alert_dialog_negative),
                 mNegativeButton.getText());
 
         assertFalse(mActivity.isPositiveButtonClicked);
@@ -112,17 +112,17 @@
         mPositiveButton = ((AlertDialog) (mActivity.getDialog())).getButton(
                 DialogInterface.BUTTON_POSITIVE);
         assertNotNull(mPositiveButton);
-        assertEquals(mActivity.getString(com.android.cts.stub.R.string.alert_dialog_positive),
+        assertEquals(mActivity.getString(com.android.cts.app.stub.R.string.alert_dialog_positive),
                 mPositiveButton.getText());
         mNegativeButton = ((AlertDialog) (mActivity.getDialog())).getButton(
                 DialogInterface.BUTTON_NEGATIVE);
         assertNotNull(mNegativeButton);
-        assertEquals(mActivity.getString(com.android.cts.stub.R.string.alert_dialog_negative),
+        assertEquals(mActivity.getString(com.android.cts.app.stub.R.string.alert_dialog_negative),
                 mNegativeButton.getText());
         mNeutralButton = ((AlertDialog) (mActivity.getDialog())).getButton(
                 DialogInterface.BUTTON_NEUTRAL);
         assertNotNull(mNeutralButton);
-        assertEquals(mActivity.getString(com.android.cts.stub.R.string.alert_dialog_neutral),
+        assertEquals(mActivity.getString(com.android.cts.app.stub.R.string.alert_dialog_neutral),
                 mNeutralButton.getText());
 
         DialogStubActivity.buttonIndex = 0;
diff --git a/tests/tests/app/src/android/app/cts/AlertDialog_BuilderTest.java b/tests/tests/app/src/android/app/cts/AlertDialog_BuilderTest.java
index 5f826eb..9554438 100644
--- a/tests/tests/app/src/android/app/cts/AlertDialog_BuilderTest.java
+++ b/tests/tests/app/src/android/app/cts/AlertDialog_BuilderTest.java
@@ -127,7 +127,7 @@
     }
 
     public AlertDialog_BuilderTest() {
-        super("com.android.cts.stub", DialogStubActivity.class);
+        super("com.android.cts.app.stub", DialogStubActivity.class);
     }
 
     public void testConstructor() {
@@ -208,14 +208,14 @@
         runTestOnUiThread(new Runnable() {
             public void run() {
                 mBuilder = new AlertDialog.Builder(mContext);
-                mBuilder.setNegativeButton(com.android.cts.stub.R.string.notify, mOnClickListener);
+                mBuilder.setNegativeButton(com.android.cts.app.stub.R.string.notify, mOnClickListener);
                 mDialog = mBuilder.show();
                 mButton = mDialog.getButton(DialogInterface.BUTTON_NEGATIVE);
                 mButton.performClick();
             }
         });
         mInstrumentation.waitForIdleSync();
-        assertEquals(mContext.getText(com.android.cts.stub.R.string.notify), mButton.getText());
+        assertEquals(mContext.getText(com.android.cts.app.stub.R.string.notify), mButton.getText());
         assertTrue(mResult);
     }
 
@@ -223,14 +223,14 @@
         runTestOnUiThread(new Runnable() {
             public void run() {
                 mBuilder = new AlertDialog.Builder(mContext);
-                mBuilder.setNeutralButton(com.android.cts.stub.R.string.notify, mOnClickListener);
+                mBuilder.setNeutralButton(com.android.cts.app.stub.R.string.notify, mOnClickListener);
                 mDialog = mBuilder.show();
                 mButton = mDialog.getButton(DialogInterface.BUTTON_NEUTRAL);
                 mButton.performClick();
             }
         });
         mInstrumentation.waitForIdleSync();
-        assertEquals(mContext.getText(com.android.cts.stub.R.string.notify), mButton.getText());
+        assertEquals(mContext.getText(com.android.cts.app.stub.R.string.notify), mButton.getText());
         assertTrue(mResult);
     }
 
@@ -321,7 +321,7 @@
         runTestOnUiThread(new Runnable() {
             public void run() {
                 mBuilder = new AlertDialog.Builder(mContext);
-                mBuilder.setItems(com.android.cts.stub.R.array.difficultyLevel, mOnClickListener);
+                mBuilder.setItems(com.android.cts.app.stub.R.array.difficultyLevel, mOnClickListener);
                 mDialog = mBuilder.show();
                 mListView = mDialog.getListView();
             }
@@ -329,13 +329,13 @@
         mInstrumentation.waitForIdleSync();
 
         final CharSequence[] levels = mContext.getResources().getTextArray(
-                com.android.cts.stub.R.array.difficultyLevel);
+                com.android.cts.app.stub.R.array.difficultyLevel);
         assertEquals(levels[0], mListView.getItemAtPosition(0));
     }
 
     public void testSetItemsWithParamCharSequence() throws Throwable {
         final CharSequence[] expect = mContext.getResources().getTextArray(
-                com.android.cts.stub.R.array.difficultyLevel);
+                com.android.cts.app.stub.R.array.difficultyLevel);
 
         runTestOnUiThread(new Runnable() {
             public void run() {
@@ -386,12 +386,12 @@
     public void testSetMultiChoiceItemsWithParamInt() throws Throwable {
 
         final CharSequence[] items = mContext.getResources().getTextArray(
-                com.android.cts.stub.R.array.difficultyLevel);
+                com.android.cts.app.stub.R.array.difficultyLevel);
 
         runTestOnUiThread(new Runnable() {
             public void run() {
                 mBuilder = new AlertDialog.Builder(mContext);
-                mBuilder.setMultiChoiceItems(com.android.cts.stub.R.array.difficultyLevel, null,
+                mBuilder.setMultiChoiceItems(com.android.cts.app.stub.R.array.difficultyLevel, null,
                         mOnMultiChoiceClickListener);
                 mDialog = mBuilder.show();
                 mListView = mDialog.getListView();
@@ -409,7 +409,7 @@
 
     public void testSetMultiChoiceItemsWithParamCharSequence() throws Throwable {
         final CharSequence[] items = mContext.getResources().getTextArray(
-                com.android.cts.stub.R.array.difficultyLevel);
+                com.android.cts.app.stub.R.array.difficultyLevel);
 
         runTestOnUiThread(new Runnable() {
             public void run() {
@@ -454,12 +454,12 @@
 
     public void testSetSingleChoiceItemsWithParamInt() throws Throwable {
         final CharSequence[] items = mContext.getResources().getTextArray(
-                com.android.cts.stub.R.array.difficultyLevel);
+                com.android.cts.app.stub.R.array.difficultyLevel);
 
         runTestOnUiThread(new Runnable() {
             public void run() {
                 mBuilder = new AlertDialog.Builder(mContext);
-                mBuilder.setSingleChoiceItems(com.android.cts.stub.R.array.difficultyLevel, 0,
+                mBuilder.setSingleChoiceItems(com.android.cts.app.stub.R.array.difficultyLevel, 0,
                         mOnClickListener);
                 mDialog = mBuilder.show();
                 mListView = mDialog.getListView();
@@ -507,7 +507,7 @@
 
     public void testSetSingleChoiceItemsWithParamCharSequence() throws Throwable {
         final CharSequence[] items = mContext.getResources().getTextArray(
-                com.android.cts.stub.R.array.difficultyLevel);
+                com.android.cts.app.stub.R.array.difficultyLevel);
 
         runTestOnUiThread(new Runnable() {
             public void run() {
@@ -527,7 +527,7 @@
 
     public void testSetSingleChoiceItems() throws Throwable {
         final CharSequence[] items = mContext.getResources().getTextArray(
-                com.android.cts.stub.R.array.difficultyLevel);
+                com.android.cts.app.stub.R.array.difficultyLevel);
 
         runTestOnUiThread(new Runnable() {
             public void run() {
@@ -552,7 +552,7 @@
             public void run() {
                 mBuilder = new AlertDialog.Builder(mContext);
                 mBuilder.setOnItemSelectedListener(mOnItemSelectedListener);
-                mBuilder.setItems(com.android.cts.stub.R.array.difficultyLevel, mOnClickListener);
+                mBuilder.setItems(com.android.cts.app.stub.R.array.difficultyLevel, mOnClickListener);
                 mDialog = mBuilder.show();
                 mListView = mDialog.getListView();
                 mListView.pointToPosition(0, 0);
diff --git a/tests/tests/app/src/android/app/cts/AliasActivityTest.java b/tests/tests/app/src/android/app/cts/AliasActivityTest.java
index e668496..d44050f 100644
--- a/tests/tests/app/src/android/app/cts/AliasActivityTest.java
+++ b/tests/tests/app/src/android/app/cts/AliasActivityTest.java
@@ -17,23 +17,31 @@
 package android.app.cts;
 
 import android.app.AliasActivity;
+import android.app.Instrumentation;
+import android.content.Context;
 import android.content.Intent;
-import android.test.AndroidTestCase;
+import android.test.InstrumentationTestCase;
 
-public class AliasActivityTest extends AndroidTestCase {
+public class AliasActivityTest extends InstrumentationTestCase {
 
     private static final long SLEEP_TIME = 1000;
 
-    public void testAliasActivity() throws InterruptedException {
-        new AliasActivity();
+    public void testAliasActivity() throws Throwable {
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                new AliasActivity();
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+        Context context = getInstrumentation().getTargetContext();
 
         Intent intent = new Intent();
-        intent.setClass(getContext(), AliasActivityStub.class);
+        intent.setClass(context, AliasActivityStub.class);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 
         assertFalse(ChildActivity.isStarted);
         assertFalse(AliasActivityStub.isOnCreateCalled);
-        getContext().startActivity(intent);
+        context.startActivity(intent);
         Thread.sleep(SLEEP_TIME);
         assertTrue(AliasActivityStub.isOnCreateCalled);
         assertTrue(ChildActivity.isStarted);
diff --git a/tests/tests/app/src/android/app/cts/CTSActivityTestCaseBase.java b/tests/tests/app/src/android/app/cts/CTSActivityTestCaseBase.java
deleted file mode 100644
index 9ab1965..0000000
--- a/tests/tests/app/src/android/app/cts/CTSActivityTestCaseBase.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2008 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.app.cts;
-
-import android.test.InstrumentationTestCase;
-
-public class CTSActivityTestCaseBase extends InstrumentationTestCase implements CTSResult {
-
-    private Sync mSync;
-    static class Sync {
-        public boolean mHasNotify;
-        public int mResult;
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mSync = new Sync();
-    }
-
-    public void setResult(int resultCode) {
-        synchronized (mSync) {
-            mSync.mHasNotify = true;
-            mSync.mResult = resultCode;
-            mSync.notify();
-        }
-    }
-
-    protected void waitForResult() throws InterruptedException {
-        synchronized (mSync) {
-            while (!mSync.mHasNotify) {
-                mSync.wait();
-            }
-            assertEquals(CTSResult.RESULT_OK, mSync.mResult);
-        }
-    }
-}
diff --git a/tests/tests/app/src/android/app/cts/DialogTest.java b/tests/tests/app/src/android/app/cts/DialogTest.java
index 4f2e197..56e731b 100644
--- a/tests/tests/app/src/android/app/cts/DialogTest.java
+++ b/tests/tests/app/src/android/app/cts/DialogTest.java
@@ -15,7 +15,7 @@
  */
 package android.app.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.app.stub.R;
 
 import android.app.Dialog;
 import android.app.Instrumentation;
@@ -38,6 +38,7 @@
 import android.os.Message;
 import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
@@ -52,7 +53,7 @@
 public class DialogTest extends ActivityInstrumentationTestCase2<DialogStubActivity> {
 
     protected static final long SLEEP_TIME = 200;
-    private static final String STUB_ACTIVITY_PACKAGE = "com.android.cts.stub";
+    private static final String STUB_ACTIVITY_PACKAGE = "com.android.cts.app.stub";
     private static final long TEST_TIMEOUT = 1000L;
 
     /**
@@ -86,7 +87,8 @@
         mActivity = DialogStubActivity.startDialogActivity(this, dialogNumber);
     }
 
-    public void testConstructor(){
+    @UiThreadTest
+    public void testConstructor() {
         new Dialog(mContext);
         Dialog d = new Dialog(mContext, 0);
         // According to javadoc of constructors, it will set theme to system default theme,
@@ -151,7 +153,7 @@
         assertTrue(d.isOnStopCalled);
     }
 
-    public void testAccessOwnerActivity() {
+    public void testAccessOwnerActivity() throws Throwable {
         startDialogActivity(DialogStubActivity.TEST_DIALOG_WITHOUT_THEME);
         Dialog d = mActivity.getDialog();
         assertNotNull(d);
@@ -166,8 +168,13 @@
             // expected
         }
 
-        d = new Dialog(mContext);
-        assertNull(d.getOwnerActivity());
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                Dialog dialog = new Dialog(mContext);
+                assertNull(dialog.getOwnerActivity());
+            }
+        });
+        mInstrumentation.waitForIdleSync();
     }
 
     public void testShow() throws Throwable {
@@ -812,11 +819,9 @@
         assertTrue(d.isShowing());
         assertFalse(mCalledCallback);
         dialogDismiss(d);
-        Thread.sleep(SLEEP_TIME);
+        ht.join(100);
         assertTrue(mCalledCallback);
         assertFalse(d.isShowing());
-
-        ht.join(100);
     }
 
     private void dialogDismiss(final Dialog d) throws Throwable {
diff --git a/tests/tests/app/src/android/app/cts/InstrumentationTest.java b/tests/tests/app/src/android/app/cts/InstrumentationTest.java
index 30cdd5f..0c2e9fa 100644
--- a/tests/tests/app/src/android/app/cts/InstrumentationTest.java
+++ b/tests/tests/app/src/android/app/cts/InstrumentationTest.java
@@ -16,8 +16,7 @@
 
 package android.app.cts;
 
-import com.android.cts.stub.R;
-
+import com.android.cts.app.stub.R;
 
 import android.app.Activity;
 import android.app.Application;
@@ -38,6 +37,7 @@
 import android.os.IBinder;
 import android.os.SystemClock;
 import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
 import android.view.InputQueue;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
@@ -58,6 +58,7 @@
     private Intent mIntent;
     private boolean mRunOnMainSyncResult;
     private Context mContext;
+    private MockActivity mMockActivity;
 
     @Override
     protected void setUp() throws Exception {
@@ -254,14 +255,19 @@
     }
 
     public void testInvokeContextMenuAction() throws Exception {
-        MockActivity activity = new MockActivity();
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mMockActivity = new MockActivity();
+            }
+        });
+        mInstrumentation.waitForIdleSync();
         final int id = 1;
         final int flag = 2;
-        mInstrumentation.invokeContextMenuAction(activity, id, flag);
+        mInstrumentation.invokeContextMenuAction(mMockActivity, id, flag);
         mInstrumentation.waitForIdleSync();
 
-        assertEquals(id, activity.mWindow.mId);
-        assertEquals(flag, activity.mWindow.mFlags);
+        assertEquals(id, mMockActivity.mWindow.mId);
+        assertEquals(flag, mMockActivity.mWindow.mFlags);
     }
 
     public void testSendStringSync() {
@@ -365,6 +371,7 @@
         assertEquals(KeyEvent.KEYCODE_0, mActivity.getKeyDownList().get(0).getKeyCode());
     }
 
+    @UiThreadTest
     public void testNewActivity() throws Exception {
         Intent intent = new Intent();
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -667,6 +674,24 @@
             @Override
             public void takeInputQueue(InputQueue.Callback queue) {
             }
+
+            @Override
+            public void setStatusBarColor(int color) {
+            }
+
+            @Override
+            public int getStatusBarColor() {
+                return 0;
+            }
+
+            @Override
+            public void setNavigationBarColor(int color) {
+            }
+
+            @Override
+            public int getNavigationBarColor() {
+                return 0;
+            }
         }
     }
 
diff --git a/tests/tests/app/src/android/app/cts/KeyguardManagerTest.java b/tests/tests/app/src/android/app/cts/KeyguardManagerTest.java
index 13264ac..cb7cd4a 100644
--- a/tests/tests/app/src/android/app/cts/KeyguardManagerTest.java
+++ b/tests/tests/app/src/android/app/cts/KeyguardManagerTest.java
@@ -27,7 +27,7 @@
     private static final String TAG = "KeyguardManagerTest";
 
     public KeyguardManagerTest() {
-        super("com.android.cts.stub", KeyguardManagerActivity.class);
+        super("com.android.cts.app.stub", KeyguardManagerActivity.class);
     }
 
     public void testNewKeyguardLock() {
diff --git a/tests/tests/app/src/android/app/cts/LauncherActivityTest.java b/tests/tests/app/src/android/app/cts/LauncherActivityTest.java
index a7e0481..3eea0b7 100644
--- a/tests/tests/app/src/android/app/cts/LauncherActivityTest.java
+++ b/tests/tests/app/src/android/app/cts/LauncherActivityTest.java
@@ -16,59 +16,54 @@
 
 package android.app.cts;
 
-
+import android.app.Activity;
 import android.app.Instrumentation;
 import android.app.LauncherActivity;
 import android.app.LauncherActivity.ListItem;
+import android.content.Context;
 import android.content.Intent;
 import android.test.InstrumentationTestCase;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
 import android.view.KeyEvent;
 
 import java.util.List;
 
-public class LauncherActivityTest extends InstrumentationTestCase {
+public class LauncherActivityTest
+        extends ActivityInstrumentationTestCase2<LauncherActivityStub> {
+
     private Instrumentation mInstrumentation;
     private LauncherActivityStub mActivity;
 
+    public LauncherActivityTest() {
+        super("com.android.cts.app.stub", LauncherActivityStub.class);
+    }
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
         mInstrumentation = getInstrumentation();
+        mActivity = getActivity();
     }
 
-    @Override
-    protected void tearDown() throws Exception {
-        if (mActivity != null) {
-            if (!mActivity.isFinishing()) {
-                mActivity.finish();
+    public void testLaunchActivity() throws Throwable {
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                // Test getTargetIntent. LaunchActivity#getTargetIntent() just returns a Intent() instance
+                // with no content, so we use LaunchActivityStub#getSuperIntent() to get the default Intent,
+                // and create a new intent for other tests.
+                assertNotNull(mActivity.getSuperIntent());
+
+                // Test makeListItems. Make sure the size > 0. The sorted order is related to the sort
+                // way, so it's mutable.
+                final List<ListItem> list = mActivity.makeListItems();
+                assertTrue(list.size() > 0);
+
+                // There should be an activity(but with uncertain content) in position 0.
+                assertNotNull(mActivity.intentForPosition(0));
             }
-        }
-        super.tearDown();
-    }
-
-    public void testLaunchActivity() {
-        // Constructor of LaunchActivity can't be invoked directly.
-        new LauncherActivityStub();
-        final String packageName = "com.android.cts.stub";
-        final Intent intent = new Intent(Intent.ACTION_MAIN);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        intent.setClassName(packageName, LauncherActivityStub.class.getName());
-        mActivity = (LauncherActivityStub) mInstrumentation.startActivitySync(intent);
-        // Test onCreate
-        assertTrue(mActivity.isOnCreateCalled);
-
-        // Test getTargetIntent. LaunchActivity#getTargetIntent() just returns a Intent() instance
-        // with no content, so we use LaunchActivityStub#getSuperIntent() to get the default Intent,
-        // and create a new intent for other tests.
-        assertNotNull(mActivity.getSuperIntent());
-
-        // Test makeListItems. Make sure the size > 0. The sorted order is related to the sort
-        // way, so it's mutable.
-        final List<ListItem> list = mActivity.makeListItems();
-        assertTrue(list.size() > 0);
-
-        // There should be an activity(but with uncertain content) in position 0.
-        assertNotNull(mActivity.intentForPosition(0));
+        });
+        mInstrumentation.waitForIdleSync();
         // Test onListItemClick
         sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
         sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
diff --git a/tests/tests/app/src/android/app/cts/LauncherActivity_IconResizerTest.java b/tests/tests/app/src/android/app/cts/LauncherActivity_IconResizerTest.java
index 695050a..2fdc8ec 100644
--- a/tests/tests/app/src/android/app/cts/LauncherActivity_IconResizerTest.java
+++ b/tests/tests/app/src/android/app/cts/LauncherActivity_IconResizerTest.java
@@ -16,7 +16,7 @@
 
 package android.app.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.app.stub.R;
 
 
 import android.app.LauncherActivity;
@@ -27,7 +27,7 @@
 public class LauncherActivity_IconResizerTest extends
         ActivityInstrumentationTestCase2<LauncherActivityStub> {
 
-    private static final String PACKAGE = "com.android.cts.stub";
+    private static final String PACKAGE = "com.android.cts.app.stub";
     private LauncherActivityStub mActivity;
 
     public LauncherActivity_IconResizerTest() {
diff --git a/tests/tests/app/src/android/app/cts/LocalActivityManagerTest.java b/tests/tests/app/src/android/app/cts/LocalActivityManagerTest.java
index 237a198..db3baba 100644
--- a/tests/tests/app/src/android/app/cts/LocalActivityManagerTest.java
+++ b/tests/tests/app/src/android/app/cts/LocalActivityManagerTest.java
@@ -20,7 +20,9 @@
 import android.app.Instrumentation;
 import android.app.LocalActivityManager;
 import android.content.Intent;
+import android.cts.util.CTSResult;
 import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
 
 public class LocalActivityManagerTest extends InstrumentationTestCase implements CTSResult {
 
@@ -46,6 +48,7 @@
         mInstrumentation.getTargetContext().startActivity(intent);
     }
 
+    @UiThreadTest
     public void testConstructor() {
         new LocalActivityManager(new Activity(), true);
         new LocalActivityManager(new Activity(), false);
diff --git a/tests/tests/app/src/android/app/cts/NotificationManagerTest.java b/tests/tests/app/src/android/app/cts/NotificationManagerTest.java
index 4add582..9a895ea 100644
--- a/tests/tests/app/src/android/app/cts/NotificationManagerTest.java
+++ b/tests/tests/app/src/android/app/cts/NotificationManagerTest.java
@@ -24,7 +24,7 @@
 import android.provider.Telephony.Threads;
 import android.test.AndroidTestCase;
 
-import com.android.cts.stub.R;
+import com.android.cts.app.stub.R;
 
 
 public class NotificationManagerTest extends AndroidTestCase {
diff --git a/tests/tests/app/src/android/app/cts/ProgressDialogTest.java b/tests/tests/app/src/android/app/cts/ProgressDialogTest.java
index 1d08d30..038b57b 100644
--- a/tests/tests/app/src/android/app/cts/ProgressDialogTest.java
+++ b/tests/tests/app/src/android/app/cts/ProgressDialogTest.java
@@ -48,10 +48,9 @@
     private Context mContext;
     private Instrumentation mInstrumentation;
     private MockActivity mActivity;
-    private ProgressDialog mProgressDialog;
 
     public ProgressDialogTest() {
-        super("com.android.cts.stub", MockActivity.class);
+        super("com.android.cts.app.stub", MockActivity.class);
     }
 
     @Override
@@ -62,19 +61,21 @@
         mInstrumentation = getInstrumentation();
         mActivity = getActivity();
         mContext = mActivity;
-        mProgressDialog = new ProgressDialog(mContext);
         mDrawable = getActivity().getResources().getDrawable(
-                com.android.cts.stub.R.drawable.yellow);
+                com.android.cts.app.stub.R.drawable.yellow);
     }
 
+    @UiThreadTest
     public void testProgressDialog1(){
         new ProgressDialog(mContext);
     }
 
+    @UiThreadTest
     public void testProgressDialog2(){
-        new ProgressDialog(mContext, com.android.cts.stub.R.style.Theme_AlertDialog);
+        new ProgressDialog(mContext, com.android.cts.app.stub.R.style.Theme_AlertDialog);
     }
 
+    @UiThreadTest
     public void testOnStartCreateStop() {
         MockProgressDialog pd = new MockProgressDialog(mContext);
 
@@ -91,21 +92,22 @@
 
     @UiThreadTest
     public void testShow1() {
-        mProgressDialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
+        ProgressDialog.show(mContext, TITLE, MESSAGE);
     }
 
     @UiThreadTest
     public void testShow2() {
-        mProgressDialog = ProgressDialog.show(mContext, TITLE, MESSAGE, false);
+        ProgressDialog dialog = buildDialog();
+        dialog = ProgressDialog.show(mContext, TITLE, MESSAGE, false);
 
         /*
          * note: the progress bar's style only supports indeterminate mode,
          * so can't change indeterminate
          */
-        assertTrue(mProgressDialog.isIndeterminate());
+        assertTrue(dialog.isIndeterminate());
 
-        mProgressDialog = ProgressDialog.show(mContext, TITLE, MESSAGE, true);
-        assertTrue(mProgressDialog.isIndeterminate());
+        dialog = ProgressDialog.show(mContext, TITLE, MESSAGE, true);
+        assertTrue(dialog.isIndeterminate());
     }
 
     public void testShow3() throws Throwable {
@@ -118,10 +120,11 @@
         // cancelable is false
         runTestOnUiThread(new Runnable() {
             public void run() {
-                mProgressDialog = ProgressDialog.show(mContext, TITLE, MESSAGE, true, false);
+                ProgressDialog dialog = buildDialog();
+                dialog = ProgressDialog.show(mContext, TITLE, MESSAGE, true, false);
 
-                mProgressDialog.setOnCancelListener(cL);
-                mProgressDialog.onBackPressed();
+                dialog.setOnCancelListener(cL);
+                dialog.onBackPressed();
             }
         });
         mInstrumentation.waitForIdleSync();
@@ -131,11 +134,11 @@
         // cancelable is true
         runTestOnUiThread(new Runnable() {
             public void run() {
-                mProgressDialog = ProgressDialog.show(mContext, TITLE, MESSAGE, true, true);
-
+                ProgressDialog dialog = buildDialog();
+                dialog = ProgressDialog.show(mContext, TITLE, MESSAGE, true, true);
                 assertFalse(mCanceled);
-                mProgressDialog.setOnCancelListener(cL);
-                mProgressDialog.onBackPressed();
+                dialog.setOnCancelListener(cL);
+                dialog.onBackPressed();
             }
         });
         mInstrumentation.waitForIdleSync();
@@ -153,9 +156,10 @@
         // cancelable is false
         runTestOnUiThread(new Runnable() {
             public void run() {
-                mProgressDialog = ProgressDialog.show(mContext, TITLE, MESSAGE, true, false, cL);
+                ProgressDialog dialog = buildDialog();
+                dialog = ProgressDialog.show(mContext, TITLE, MESSAGE, true, false, cL);
 
-                mProgressDialog.onBackPressed();
+                dialog.onBackPressed();
             }
         });
         mInstrumentation.waitForIdleSync();
@@ -165,10 +169,11 @@
         // cancelable is true
         runTestOnUiThread(new Runnable() {
             public void run() {
-                mProgressDialog = ProgressDialog.show(mContext, TITLE, MESSAGE, true, true, cL);
+                ProgressDialog dialog = buildDialog();
+                dialog = ProgressDialog.show(mContext, TITLE, MESSAGE, true, true, cL);
 
                 assertFalse(mCanceled);
-                mProgressDialog.onBackPressed();
+                dialog.onBackPressed();
             }
         });
         mInstrumentation.waitForIdleSync();
@@ -178,180 +183,152 @@
 
     @UiThreadTest
     public void testAccessMax() {
-        // mProgress is null
-        mProgressDialog.setMax(2008);
-        assertEquals(2008, mProgressDialog.getMax());
+        // progressDialog is null
+        ProgressDialog progressDialog = buildDialog();
+        progressDialog.setMax(2008);
+        assertEquals(2008, progressDialog.getMax());
 
-        // mProgress is not null
-        mProgressDialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
-        mProgressDialog.setMax(2009);
-        assertEquals(2009, mProgressDialog.getMax());
+        // progressDialog is not null
+        progressDialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
+        progressDialog.setMax(2009);
+        assertEquals(2009, progressDialog.getMax());
     }
 
     @UiThreadTest
     public void testAccessProgress() {
-        // mProgress is null
-        mProgressDialog.setProgress(11);
-        assertEquals(11, mProgressDialog.getProgress());
+        // progressDialog is null
+        ProgressDialog progressDialog = buildDialog();
+        progressDialog.setProgress(11);
+        assertEquals(11, progressDialog.getProgress());
 
-        /* mProgress is not null
+        /* progressDialog is not null
          * note: the progress bar's style only supports indeterminate mode,
          * so can't change progress
          */
-        mProgressDialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
-        mProgressDialog.setProgress(12);
-        assertEquals(0, mProgressDialog.getProgress());
+        progressDialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
+        progressDialog.setProgress(12);
+        assertEquals(0, progressDialog.getProgress());
     }
 
     @UiThreadTest
     public void testAccessSecondaryProgress() {
-        // mProgress is null
-        mProgressDialog.setSecondaryProgress(17);
-        assertEquals(17, mProgressDialog.getSecondaryProgress());
+        // dialog is null
+        ProgressDialog dialog = buildDialog();
+        dialog.setSecondaryProgress(17);
+        assertEquals(17, dialog.getSecondaryProgress());
 
         /* mProgress is not null
          * note: the progress bar's style only supports indeterminate mode,
          * so can't change secondary progress
          */
-        mProgressDialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
-        mProgressDialog.setSecondaryProgress(18);
-        assertEquals(0, mProgressDialog.getSecondaryProgress());
+        dialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
+        dialog.setSecondaryProgress(18);
+        assertEquals(0, dialog.getSecondaryProgress());
     }
 
     @UiThreadTest
     public void testSetIndeterminate() {
-        // mProgress is null
-        mProgressDialog.setIndeterminate(true);
-        assertTrue(mProgressDialog.isIndeterminate());
-        mProgressDialog.setIndeterminate(false);
-        assertFalse(mProgressDialog.isIndeterminate());
+        // progress is null
+        ProgressDialog dialog = buildDialog();
+        dialog.setIndeterminate(true);
+        assertTrue(dialog.isIndeterminate());
+        dialog.setIndeterminate(false);
+        assertFalse(dialog.isIndeterminate());
 
         /* mProgress is not null
          * note: the progress bar's style only supports indeterminate mode,
          * so can't change indeterminate
          */
-        mProgressDialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
-        mProgressDialog.setIndeterminate(true);
-        assertTrue(mProgressDialog.isIndeterminate());
-        mProgressDialog.setIndeterminate(false);
-        assertTrue(mProgressDialog.isIndeterminate());
+        dialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
+        dialog.setIndeterminate(true);
+        assertTrue(dialog.isIndeterminate());
+        dialog.setIndeterminate(false);
+        assertTrue(dialog.isIndeterminate());
     }
 
+    @UiThreadTest
     public void testIncrementProgressBy() throws Throwable {
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                mProgressDialog = new ProgressDialog(mContext);
-                mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
-                mProgressDialog.show();
-                mProgressDialog.setProgress(10);
-                mProgress1 = mProgressDialog.getProgress();
-                mProgressDialog.incrementProgressBy(60);
-                mProgress2 = mProgressDialog.getProgress();
-                mProgressDialog.cancel();
-            }
-        });
-        mInstrumentation.waitForIdleSync();
+        ProgressDialog dialog = new ProgressDialog(mContext);
+        dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
+        dialog.show();
+        dialog.setProgress(10);
+        mProgress1 = dialog.getProgress();
+        dialog.incrementProgressBy(60);
+        mProgress2 = dialog.getProgress();
+        dialog.cancel();
 
         assertEquals(10, mProgress1);
         assertEquals(70, mProgress2);
     }
 
+    @UiThreadTest
     public void testIncrementSecondaryProgressBy() throws Throwable {
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                mProgressDialog = new ProgressDialog(mContext);
-                mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
-                mProgressDialog.show();
-                mProgressDialog.setSecondaryProgress(10);
-                mProgress1 = mProgressDialog.getSecondaryProgress();
-                mProgressDialog.incrementSecondaryProgressBy(60);
-                mProgress2 = mProgressDialog.getSecondaryProgress();
-            }
-        });
-        mInstrumentation.waitForIdleSync();
+        ProgressDialog dialog = new ProgressDialog(mContext);
+        dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
+        dialog.show();
+        dialog.setSecondaryProgress(10);
+        mProgress1 = dialog.getSecondaryProgress();
+        dialog.incrementSecondaryProgressBy(60);
+        mProgress2 = dialog.getSecondaryProgress();
 
         assertEquals(10, mProgress1);
         assertEquals(70, mProgress2);
     }
 
+    @UiThreadTest
     public void testSetProgressDrawable() throws Throwable {
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                mProgressDialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
-                final Window w = mProgressDialog.getWindow();
-                final ProgressBar progressBar = (ProgressBar) w.findViewById(android.R.id.progress);
+        ProgressDialog dialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
+        Window w = dialog.getWindow();
+        ProgressBar progressBar = (ProgressBar) w.findViewById(android.R.id.progress);
 
-                mProgressDialog.setProgressDrawable(mDrawable);
-                mActualDrawable = progressBar.getProgressDrawable();
+        dialog.setProgressDrawable(mDrawable);
+        mActualDrawable = progressBar.getProgressDrawable();
 
-                mProgressDialog.setProgressDrawable(null);
-                mActualDrawableNull = progressBar.getProgressDrawable();
-            }
-        });
-        mInstrumentation.waitForIdleSync();
+        dialog.setProgressDrawable(null);
+        mActualDrawableNull = progressBar.getProgressDrawable();
         assertEquals(mDrawable, mActualDrawable);
         assertEquals(null, mActualDrawableNull);
     }
 
+    @UiThreadTest
     public void testSetIndeterminateDrawable() throws Throwable {
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                mProgressDialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
-                final Window w = mProgressDialog.getWindow();
-                mProgressBar = (ProgressBar) w.findViewById(android.R.id.progress);
+        ProgressDialog dialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
+        Window w = dialog.getWindow();
+        mProgressBar = (ProgressBar) w.findViewById(android.R.id.progress);
 
-                mProgressDialog.setIndeterminateDrawable(mDrawable);
-                mActualDrawable = mProgressBar.getIndeterminateDrawable();
-                assertEquals(mDrawable, mActualDrawable);
+        dialog.setIndeterminateDrawable(mDrawable);
+        mActualDrawable = mProgressBar.getIndeterminateDrawable();
+        assertEquals(mDrawable, mActualDrawable);
 
-                mProgressDialog.setIndeterminateDrawable(null);
-                mActualDrawableNull = mProgressBar.getIndeterminateDrawable();
-                assertEquals(null, mActualDrawableNull);
-            }
-        });
-        mInstrumentation.waitForIdleSync();
+        dialog.setIndeterminateDrawable(null);
+        mActualDrawableNull = mProgressBar.getIndeterminateDrawable();
+        assertEquals(null, mActualDrawableNull);
     }
 
+    @UiThreadTest
     public void testSetMessage() throws Throwable {
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                // mProgress is null
-                mProgressDialog = new ProgressDialog(mContext);
-                mProgressDialog.setMessage(MESSAGE);
-                mProgressDialog.show();
-            }
-        });
-        mInstrumentation.waitForIdleSync();
-
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                // mProgress is not null
-                mProgressDialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
-                mProgressDialog.setMessage("Bruce Li");
-            }
-        });
-        mInstrumentation.waitForIdleSync();
+        ProgressDialog dialog = new ProgressDialog(mContext);
+        dialog = new ProgressDialog(mContext);
+        dialog.setMessage(MESSAGE);
+        dialog.show();
+        // dialog is not null
+        dialog = ProgressDialog.show(mContext, TITLE, MESSAGE);
+        dialog.setMessage("Chuck Norris");
     }
 
+    @UiThreadTest
     public void testSetProgressStyle() throws Throwable {
-        setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
-
-        setProgressStyle(ProgressDialog.STYLE_SPINNER);
-        setProgressStyle(100);
+        ProgressDialog dialog = new ProgressDialog(mContext);
+        setProgressStyle(dialog, ProgressDialog.STYLE_HORIZONTAL);
+        setProgressStyle(dialog, ProgressDialog.STYLE_SPINNER);
+        setProgressStyle(dialog, 100);
     }
 
-    private void setProgressStyle(final int style) throws Throwable {
-        runTestOnUiThread(new Runnable() {
-            public void run() {
-                mProgressDialog = new ProgressDialog(mContext);
-                mProgressDialog.setProgressStyle(style);
-
-                mProgressDialog.show();
-                mProgressDialog.setProgress(10);
-                mProgressDialog.setMax(100);
-            }
-        });
-        mInstrumentation.waitForIdleSync();
+    private void setProgressStyle(ProgressDialog dialog, int style) {
+        dialog.setProgressStyle(style);
+        dialog.show();
+        dialog.setProgress(10);
+        dialog.setMax(100);
     }
 
     private static class MockProgressDialog extends ProgressDialog {
@@ -381,4 +358,8 @@
             mIsOnStopCalled = true;
         }
     }
+
+    private ProgressDialog buildDialog() {
+        return new ProgressDialog(mContext);
+    }
 }
diff --git a/tests/tests/app/src/android/app/cts/SearchManagerTest.java b/tests/tests/app/src/android/app/cts/SearchManagerTest.java
index 8e465e8..1cece76 100644
--- a/tests/tests/app/src/android/app/cts/SearchManagerTest.java
+++ b/tests/tests/app/src/android/app/cts/SearchManagerTest.java
@@ -17,6 +17,7 @@
 package android.app.cts;
 
 import android.content.Intent;
+import android.cts.util.CTSResult;
 
 public class SearchManagerTest extends CTSActivityTestCaseBase {
 
diff --git a/tests/tests/app/src/android/app/cts/ServiceTest.java b/tests/tests/app/src/android/app/cts/ServiceTest.java
index f9a81e6..b66f4c8 100644
--- a/tests/tests/app/src/android/app/cts/ServiceTest.java
+++ b/tests/tests/app/src/android/app/cts/ServiceTest.java
@@ -16,12 +16,11 @@
 
 package android.app.cts;
 
-
-import android.app.Service;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.cts.util.IBinderParcelable;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -51,9 +50,11 @@
     private IBinder mStateReceiver;
 
     private static class EmptyConnection implements ServiceConnection {
+        @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
         }
 
+        @Override
         public void onServiceDisconnected(ComponentName name) {
         }
     }
@@ -74,6 +75,7 @@
             mMonitor = v;
         }
 
+        @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
             if (mSetReporter) {
                 Parcel data = Parcel.obtain();
@@ -109,6 +111,7 @@
             }
         }
 
+        @Override
         public void onServiceDisconnected(ComponentName name) {
             if (mMonitor) {
                 if (mExpectedServiceState == STATE_DESTROY) {
@@ -150,15 +153,6 @@
         waitForResultOrThrow(DELAY, "service to be destroyed");
     }
 
-    private void startExpectNoPermission(Intent service) {
-        try {
-            mContext.startService(service);
-            fail("Expected security exception when starting " + service);
-        } catch (SecurityException e) {
-            // expected
-        }
-    }
-
     /**
      * test the service lifecycle, a service can be used in two ways:
      * 1  It can be started and allowed to run until someone stops it or it stops itself.
@@ -294,18 +288,6 @@
         waitForResultOrThrow(DELAY, "disconnecting from service");
     }
 
-    private void bindExpectNoPermission(Intent service) {
-        TestConnection conn = new TestConnection(false, false);
-        try {
-            mContext.bindService(service, conn, Context.BIND_AUTO_CREATE);
-            fail("Expected security exception when binding " + service);
-        } catch (SecurityException e) {
-            // expected
-        } finally {
-            mContext.unbindService(conn);
-        }
-    }
-
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -313,8 +295,10 @@
         mLocalService = new Intent(mContext, LocalService.class);
         mLocalDeniedService = new Intent(mContext, LocalDeniedService.class);
         mLocalGrantedService = new Intent(mContext, LocalGrantedService.class);
-        mLocalService_ApplicationHasPermission = new Intent(LocalService.SERVICE_LOCAL_GRANTED);
-        mLocalService_ApplicationDoesNotHavePermission = new Intent(LocalService.SERVICE_LOCAL_DENIED);
+        mLocalService_ApplicationHasPermission = new Intent(
+                LocalService.SERVICE_LOCAL_GRANTED, null /*uri*/, mContext, LocalService.class);
+        mLocalService_ApplicationDoesNotHavePermission = new Intent(
+                LocalService.SERVICE_LOCAL_DENIED, null /*uri*/, mContext, LocalService.class);
         mStateReceiver = new MockBinder();
     }
 
@@ -392,7 +376,8 @@
     }
 
     public void testLocalStartAction() throws Exception {
-        startExpectResult(new Intent(LocalService.SERVICE_LOCAL));
+        startExpectResult(new Intent(
+                LocalService.SERVICE_LOCAL, null /*uri*/, mContext, LocalService.class));
     }
 
     public void testLocalBindClass() throws Exception {
@@ -401,7 +386,8 @@
 
     @MediumTest
     public void testLocalBindAction() throws Exception {
-        bindExpectResult(new Intent(LocalService.SERVICE_LOCAL));
+        bindExpectResult(new Intent(
+                LocalService.SERVICE_LOCAL, null /*uri*/, mContext, LocalService.class));
     }
 
     @MediumTest
@@ -411,7 +397,8 @@
 
     @MediumTest
     public void testLocalBindAutoAction() throws Exception {
-        bindAutoExpectResult(new Intent(LocalService.SERVICE_LOCAL));
+        bindAutoExpectResult(new Intent(
+                LocalService.SERVICE_LOCAL, null /*uri*/, mContext, LocalService.class));
     }
 
     @MediumTest
diff --git a/tests/tests/app/src/android/app/cts/SystemFeaturesTest.java b/tests/tests/app/src/android/app/cts/SystemFeaturesTest.java
index c4318d8..165e67b 100644
--- a/tests/tests/app/src/android/app/cts/SystemFeaturesTest.java
+++ b/tests/tests/app/src/android/app/cts/SystemFeaturesTest.java
@@ -136,9 +136,15 @@
         }
 
         if (frontCameraId > -1) {
-            assertAvailable(PackageManager.FEATURE_CAMERA_FRONT);
+            assertTrue("Device has front-facing camera but does not report either " +
+                    "the FEATURE_CAMERA_FRONT or FEATURE_CAMERA_EXTERNAL feature",
+                    mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT) ||
+                    mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL));
         } else {
-            assertNotAvailable(PackageManager.FEATURE_CAMERA_FRONT);
+            assertFalse("Device does not have front-facing camera but reports either " +
+                    "the FEATURE_CAMERA_FRONT or FEATURE_CAMERA_EXTERNAL feature",
+                    mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT) ||
+                    mPackageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_EXTERNAL));
         }
     }
 
@@ -239,6 +245,12 @@
                 Sensor.TYPE_STEP_DETECTOR);
         assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_HEART_RATE,
                 Sensor.TYPE_HEART_RATE);
+        assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_HEART_RATE_ECG,
+                Sensor.TYPE_HEART_RATE);
+        assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_AMBIENT_TEMPERATURE,
+                Sensor.TYPE_AMBIENT_TEMPERATURE);
+        assertFeatureForSensor(featuresLeft, PackageManager.FEATURE_SENSOR_RELATIVE_HUMIDITY,
+                Sensor.TYPE_RELATIVE_HUMIDITY);
 
         assertTrue("Assertions need to be added to this test for " + featuresLeft,
                 featuresLeft.isEmpty());
diff --git a/tests/tests/app/src/android/app/cts/TabActivityTest.java b/tests/tests/app/src/android/app/cts/TabActivityTest.java
index 04741b7..9c028a1 100644
--- a/tests/tests/app/src/android/app/cts/TabActivityTest.java
+++ b/tests/tests/app/src/android/app/cts/TabActivityTest.java
@@ -25,6 +25,7 @@
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
 import android.widget.TabHost;
 
 public class TabActivityTest extends InstrumentationTestCase {
@@ -53,10 +54,14 @@
     }
 
     public void testTabActivity() throws Throwable {
-        // Test constructor
-        new TabActivity();
-
-        final String packageName = "com.android.cts.stub";
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                // Test constructor
+                new TabActivity();
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+        final String packageName = "com.android.cts.app.stub";
         final Intent intent = new Intent(Intent.ACTION_MAIN);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         intent.setClassName(packageName, MockTabActivity.class.getName());
@@ -77,6 +82,7 @@
         assertNotNull(tabHost.getTabWidget());
     }
 
+    @UiThreadTest
     public void testChildTitleCallback() throws Exception {
         final Context context = mInstrumentation.getTargetContext();
         final Intent intent = new Intent(context, MockTabActivity.class);
diff --git a/tests/tests/app/src/android/app/cts/TimePickerDialogTest.java b/tests/tests/app/src/android/app/cts/TimePickerDialogTest.java
index 01073f7..79a91a1 100644
--- a/tests/tests/app/src/android/app/cts/TimePickerDialogTest.java
+++ b/tests/tests/app/src/android/app/cts/TimePickerDialogTest.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.os.Bundle;
 import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
 import android.widget.TimePicker;
 
 /**
@@ -42,10 +43,9 @@
 
     private Context mContext;
     private DialogStubActivity mActivity;
-    private TimePickerDialog mTimePickerDialog;
 
     public TimePickerDialogTest() {
-        super("com.android.cts.stub", DialogStubActivity.class);
+        super("com.android.cts.app.stub", DialogStubActivity.class);
     }
 
     @Override
@@ -59,13 +59,12 @@
                 mCallbackMinute = minute;
             }
         };
-        mTimePickerDialog = new TimePickerDialog( mContext, mOnTimeSetListener, TARGET_HOUR,
-                TARGET_MINUTE, true);
     }
 
-    public void testSaveInstanceState(){
-        TimePickerDialog tD = new TimePickerDialog( mContext, mOnTimeSetListener, TARGET_HOUR,
-                TARGET_MINUTE, true);
+    @UiThreadTest
+    public void testSaveInstanceState() {
+        TimePickerDialog tD = new TimePickerDialog(
+            mContext, mOnTimeSetListener, TARGET_HOUR, TARGET_MINUTE, true);
 
         Bundle b = tD.onSaveInstanceState();
 
@@ -74,8 +73,9 @@
         assertTrue(b.getBoolean(IS_24_HOUR));
 
         int minute = 13;
-        tD = new TimePickerDialog( mContext, com.android.cts.stub.R.style.Theme_AlertDialog,
-                mOnTimeSetListener, TARGET_HOUR, minute, false);
+        tD = new TimePickerDialog(
+                mContext, com.android.cts.app.stub.R.style.Theme_AlertDialog,
+                    mOnTimeSetListener, TARGET_HOUR, minute, false);
 
         b = tD.onSaveInstanceState();
 
@@ -84,8 +84,10 @@
         assertFalse(b.getBoolean(IS_24_HOUR));
     }
 
-    public void testOnClick(){
-        mTimePickerDialog.onClick(null, 0);
+    @UiThreadTest
+    public void testOnClick() {
+        TimePickerDialog timePickerDialog = buildDialog();
+        timePickerDialog.onClick(null, TimePickerDialog.BUTTON_POSITIVE);
 
         assertEquals(TARGET_HOUR, mCallbackHour);
         assertEquals(TARGET_MINUTE, mCallbackMinute);
@@ -105,28 +107,32 @@
 
     }
 
-    public void testUpdateTime(){
+    @UiThreadTest
+    public void testUpdateTime() {
+        TimePickerDialog timePickerDialog = buildDialog();
         int minute = 18;
-        mTimePickerDialog.updateTime(TARGET_HOUR, minute);
+        timePickerDialog.updateTime(TARGET_HOUR, minute);
 
-        //here call onSaveInstanceState is to check the data put by updateTime
-        Bundle b = mTimePickerDialog.onSaveInstanceState();
+        // here call onSaveInstanceState is to check the data put by updateTime
+        Bundle b = timePickerDialog.onSaveInstanceState();
 
         assertEquals(TARGET_HOUR, b.getInt(HOUR));
         assertEquals(minute, b.getInt(MINUTE));
     }
 
-    public void testOnRestoreInstanceState(){
+    @UiThreadTest
+    public void testOnRestoreInstanceState() {
         int minute = 27;
         Bundle b1 = new Bundle();
         b1.putInt(HOUR, TARGET_HOUR);
         b1.putInt(MINUTE, minute);
         b1.putBoolean(IS_24_HOUR, false);
 
-        mTimePickerDialog.onRestoreInstanceState(b1);
+        TimePickerDialog timePickerDialog = buildDialog();
+        timePickerDialog.onRestoreInstanceState(b1);
 
         //here call onSaveInstanceState is to check the data put by onRestoreInstanceState
-        Bundle b2 = mTimePickerDialog.onSaveInstanceState();
+        Bundle b2 = timePickerDialog.onSaveInstanceState();
 
         assertEquals(TARGET_HOUR, b2.getInt(HOUR));
         assertEquals(minute, b2.getInt(MINUTE));
@@ -136,4 +142,9 @@
     private void startDialogActivity(int dialogNumber) {
         mActivity = DialogStubActivity.startDialogActivity(this, dialogNumber);
     }
+
+    private TimePickerDialog buildDialog() {
+        return new TimePickerDialog(
+                mContext, mOnTimeSetListener, TARGET_HOUR, TARGET_MINUTE, true);
+    }
 }
diff --git a/tests/tests/appwidget/Android.mk b/tests/tests/appwidget/Android.mk
new file mode 100644
index 0000000..8641d53
--- /dev/null
+++ b/tests/tests/appwidget/Android.mk
@@ -0,0 +1,29 @@
+# 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsAppWidgetTestCases
+
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target ctstestrunner
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/appwidget/AndroidManifest.xml b/tests/tests/appwidget/AndroidManifest.xml
new file mode 100644
index 0000000..4d9b61d
--- /dev/null
+++ b/tests/tests/appwidget/AndroidManifest.xml
@@ -0,0 +1,54 @@
+<?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.cts.appwidget">
+
+  <application>
+      <uses-library android:name="android.test.runner"/>
+
+      <receiver android:name="android.appwidget.cts.provider.FirstAppWidgetProvider" >
+          <intent-filter>
+              <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+          </intent-filter>
+          <meta-data android:name="android.appwidget.provider"
+              android:resource="@xml/first_appwidget_info" />
+      </receiver>
+
+      <receiver android:name="android.appwidget.cts.provider.SecondAppWidgetProvider" >
+          <intent-filter>
+              <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+          </intent-filter>
+          <meta-data android:name="android.appwidget.provider"
+              android:resource="@xml/second_appwidget_info" />
+      </receiver>
+
+      <service android:name="android.appwidget.cts.service.MyAppWidgetService"
+          android:permission="android.permission.BIND_REMOTEVIEWS">
+      </service>
+
+  </application>
+
+  <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+      android:targetPackage="android.cts.appwidget"
+      android:label="Tests for the app widget APIs.">
+      <meta-data android:name="listener"
+          android:value="com.android.cts.runner.CtsTestRunListener" />
+  </instrumentation>
+
+</manifest>
diff --git a/tests/tests/appwidget/res/drawable/first_android_icon.png b/tests/tests/appwidget/res/drawable/first_android_icon.png
new file mode 100644
index 0000000..4ba97a5
--- /dev/null
+++ b/tests/tests/appwidget/res/drawable/first_android_icon.png
Binary files differ
diff --git a/tests/tests/appwidget/res/drawable/second_android_icon.png b/tests/tests/appwidget/res/drawable/second_android_icon.png
new file mode 100644
index 0000000..4ba97a5
--- /dev/null
+++ b/tests/tests/appwidget/res/drawable/second_android_icon.png
Binary files differ
diff --git a/tests/tests/appwidget/res/layout/collection_widget_item_layout.xml b/tests/tests/appwidget/res/layout/collection_widget_item_layout.xml
new file mode 100644
index 0000000..50f49c1
--- /dev/null
+++ b/tests/tests/appwidget/res/layout/collection_widget_item_layout.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/text_view"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
+</TextView>
diff --git a/tests/tests/appwidget/res/layout/collection_widget_layout.xml b/tests/tests/appwidget/res/layout/collection_widget_layout.xml
new file mode 100644
index 0000000..0489bca
--- /dev/null
+++ b/tests/tests/appwidget/res/layout/collection_widget_layout.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+
+<StackView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/stack_view"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+</StackView>
diff --git a/tests/tests/appwidget/res/layout/first_initial_keyguard_layout.xml b/tests/tests/appwidget/res/layout/first_initial_keyguard_layout.xml
new file mode 100644
index 0000000..bebec9f
--- /dev/null
+++ b/tests/tests/appwidget/res/layout/first_initial_keyguard_layout.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+
+<Button xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
+</Button>
diff --git a/tests/tests/appwidget/res/layout/first_initial_layout.xml b/tests/tests/appwidget/res/layout/first_initial_layout.xml
new file mode 100644
index 0000000..bebec9f
--- /dev/null
+++ b/tests/tests/appwidget/res/layout/first_initial_layout.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+
+<Button xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
+</Button>
diff --git a/tests/tests/appwidget/res/layout/second_initial_keyguard_layout.xml b/tests/tests/appwidget/res/layout/second_initial_keyguard_layout.xml
new file mode 100644
index 0000000..bebec9f
--- /dev/null
+++ b/tests/tests/appwidget/res/layout/second_initial_keyguard_layout.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+
+<Button xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
+</Button>
diff --git a/tests/tests/appwidget/res/layout/second_initial_layout.xml b/tests/tests/appwidget/res/layout/second_initial_layout.xml
new file mode 100644
index 0000000..bebec9f
--- /dev/null
+++ b/tests/tests/appwidget/res/layout/second_initial_layout.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+
+<Button xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
+</Button>
diff --git a/tests/tests/appwidget/res/values/constants.xml b/tests/tests/appwidget/res/values/constants.xml
new file mode 100644
index 0000000..375dae3
--- /dev/null
+++ b/tests/tests/appwidget/res/values/constants.xml
@@ -0,0 +1,51 @@
+<?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.
+-->
+
+<resources>
+
+    <!-- First widget provider -->
+
+    <dimen name="first_min_appwidget_size">40dp</dimen>
+
+    <dimen name="first_min_resize_appwidget_size">60dp</dimen>
+
+    <integer name="first_update_period_millis">86400000</integer>
+
+    <integer name="first_resize_mode">3</integer>
+
+    <integer name="first_widget_category">3</integer>
+
+    <item type="id" name="first_auto_advance_view_id"/>
+
+    <!-- Second widget provider -->
+
+    <dimen name="second_min_appwidget_size">50dp</dimen>
+
+    <dimen name="second_min_resize_appwidget_size">70dp</dimen>
+
+    <integer name="second_update_period_millis">86500000</integer>
+
+    <integer name="second_resize_mode">1</integer>
+
+    <integer name="second_widget_category">1</integer>
+
+    <item type="id" name="second_auto_advance_view_id"/>
+
+    <string name="foo">Foo</string>
+
+</resources>
diff --git a/tests/tests/appwidget/res/xml/first_appwidget_info.xml b/tests/tests/appwidget/res/xml/first_appwidget_info.xml
new file mode 100644
index 0000000..d7c1028
--- /dev/null
+++ b/tests/tests/appwidget/res/xml/first_appwidget_info.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
+    android:minWidth="@dimen/first_min_appwidget_size"
+    android:minHeight="@dimen/first_min_appwidget_size"
+    android:minResizeWidth="@dimen/first_min_resize_appwidget_size"
+    android:minResizeHeight="@dimen/first_min_resize_appwidget_size"
+    android:updatePeriodMillis="@integer/first_update_period_millis"
+    android:configure="android.appwidget.cts.provider.FirstAppWidgetConfigureActivity"
+    android:resizeMode="horizontal|vertical"
+    android:widgetCategory="home_screen|keyguard"
+    android:initialLayout="@layout/first_initial_layout"
+    android:initialKeyguardLayout="@layout/first_initial_keyguard_layout"
+    android:previewImage="@drawable/first_android_icon"
+    android:autoAdvanceViewId="@id/first_auto_advance_view_id">
+</appwidget-provider>
diff --git a/tests/tests/appwidget/res/xml/second_appwidget_info.xml b/tests/tests/appwidget/res/xml/second_appwidget_info.xml
new file mode 100644
index 0000000..d192b10
--- /dev/null
+++ b/tests/tests/appwidget/res/xml/second_appwidget_info.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
+    android:minWidth="@dimen/second_min_appwidget_size"
+    android:minHeight="@dimen/second_min_appwidget_size"
+    android:minResizeWidth="@dimen/second_min_resize_appwidget_size"
+    android:minResizeHeight="@dimen/second_min_resize_appwidget_size"
+    android:updatePeriodMillis="@integer/second_update_period_millis"
+    android:configure="android.appwidget.cts.provider.SecondAppWidgetConfigureActivity"
+    android:resizeMode="horizontal"
+    android:widgetCategory="home_screen"
+    android:initialLayout="@layout/second_initial_layout"
+    android:initialKeyguardLayout="@layout/second_initial_keyguard_layout"
+    android:previewImage="@drawable/second_android_icon"
+    android:autoAdvanceViewId="@id/second_auto_advance_view_id">
+</appwidget-provider>
diff --git a/tests/tests/appwidget/src/android/appwidget/cts/AppWidgetTest.java b/tests/tests/appwidget/src/android/appwidget/cts/AppWidgetTest.java
new file mode 100644
index 0000000..5e72a78
--- /dev/null
+++ b/tests/tests/appwidget/src/android/appwidget/cts/AppWidgetTest.java
@@ -0,0 +1,1559 @@
+/*
+ * 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.appwidget.cts;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.same;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.appwidget.AppWidgetHost;
+import android.appwidget.AppWidgetHostView;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
+import android.appwidget.cts.provider.AppWidgetProviderCallbacks;
+import android.appwidget.cts.provider.FirstAppWidgetProvider;
+import android.appwidget.cts.provider.SecondAppWidgetProvider;
+import android.appwidget.cts.service.MyAppWidgetService;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.cts.appwidget.R;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
+import android.os.Process;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.test.InstrumentationTestCase;
+import android.text.TextUtils;
+import android.util.DisplayMetrics;
+import android.widget.RemoteViews;
+import android.widget.RemoteViewsService.RemoteViewsFactory;
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.mockito.InOrder;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class AppWidgetTest extends InstrumentationTestCase {
+
+    private static final long OPERATION_TIMEOUT = 20 * 1000; // 20 sec
+
+    private static final String FIRST_APP_WIDGET_CONFIGURE_ACTIVITY =
+            "android.appwidget.cts.provider.FirstAppWidgetConfigureActivity";
+
+    private static final String SECOND_APP_WIDGET_CONFIGURE_ACTIVITY =
+            "android.appwidget.cts.provider.SecondAppWidgetConfigureActivity";
+
+    private final Object mLock = new Object();
+
+    @Override
+    public void setUp() throws Exception {
+        // Workaround for dexmaker bug: https://code.google.com/p/dexmaker/issues/detail?id=2
+        // Dexmaker is used by mockito.
+        System.setProperty("dexmaker.dexcache", getInstrumentation()
+                .getTargetContext().getCacheDir().getPath());
+    }
+
+    private static final String GRANT_BIND_APP_WIDGET_PERMISSION_COMMAND =
+            "appwidget grantbind --package android.cts.appwidget --user 0";
+
+    private static final String REVOKE_BIND_APP_WIDGET_PERMISSION_COMMAND =
+            "appwidget revokebind --package android.cts.appwidget --user 0";
+
+    public void testGetAppInstalledProvidersForCurrentUserLegacy() throws Exception {
+        // By default we should get only providers for the current user.
+        List<AppWidgetProviderInfo> providers = getAppWidgetManager().getInstalledProviders();
+
+        // Make sure we have our two providers in the list.
+        assertExpectedInstalledProviders(providers);
+    }
+
+    public void testGetAppInstalledProvidersForCurrentUserNewCurrentProfile() throws Exception {
+        // We ask only for providers for the current user.
+        List<AppWidgetProviderInfo> providers = getAppWidgetManager()
+                .getInstalledProvidersForProfile(Process.myUserHandle());
+
+        // Make sure we have our two providers in the list.
+        assertExpectedInstalledProviders(providers);
+    }
+
+    public void testGetAppInstalledProvidersForCurrentUserNewAllProfiles() throws Exception {
+        // We ask only for providers for all current user's profiles
+        UserManager userManager = (UserManager) getInstrumentation()
+                .getTargetContext().getSystemService(Context.USER_SERVICE);
+
+        List<AppWidgetProviderInfo> allProviders = new ArrayList<>();
+
+        List<UserHandle> profiles = userManager.getUserProfiles();
+        final int profileCount = profiles.size();
+        for (int i = 0; i < profileCount; i++) {
+            UserHandle profile = profiles.get(i);
+            List<AppWidgetProviderInfo> providers = getAppWidgetManager()
+                    .getInstalledProvidersForProfile(profile);
+            allProviders.addAll(providers);
+        }
+
+        // Make sure we have our two providers in the list.
+        assertExpectedInstalledProviders(allProviders);
+    }
+
+    public void testBindAppWidget() throws Exception {
+        // Create a host and start listening.
+        AppWidgetHost host = new AppWidgetHost(getInstrumentation().getTargetContext(), 0);
+        host.deleteHost();
+        host.startListening();
+
+        // Allocate an app widget id to bind.
+        final int appWidgetId = host.allocateAppWidgetId();
+
+        // Grab a provider we defined to be bound.
+        AppWidgetProviderInfo provider = getFirstAppWidgetProviderInfo();
+
+        // Bind the widget.
+        boolean widgetBound = getAppWidgetManager().bindAppWidgetIdIfAllowed(appWidgetId,
+                provider.getProfile(), provider.provider, null);
+        assertFalse(widgetBound);
+
+        // Well, app do not have this permission unless explicitly granted
+        // by the user. Now we will pretend for the user and grant it.
+        grantBindAppWidgetPermission();
+
+        try {
+            // Bind the widget as we have a permission for that.
+            widgetBound = getAppWidgetManager().bindAppWidgetIdIfAllowed(
+                    appWidgetId, provider.getProfile(), provider.provider, null);
+            assertTrue(widgetBound);
+
+            // Deallocate the app widget id.
+            host.deleteAppWidgetId(appWidgetId);
+        } finally {
+            // Clean up.
+            host.deleteAppWidgetId(appWidgetId);
+            host.deleteHost();
+            revokeBindAppWidgetPermission();
+        }
+    }
+
+    public void testAppWidgetProviderCallbacks() throws Exception {
+        AtomicInteger invocationCounter = new AtomicInteger();
+
+        // Set a mock to intercept provider callbacks.
+        AppWidgetProviderCallbacks callbacks = createAppWidgetProviderCallbacks(invocationCounter);
+        FirstAppWidgetProvider.setCallbacks(callbacks);
+
+        int firstAppWidgetId = 0;
+        int secondAppWidgetId = 0;
+
+        final Bundle firstOptions;
+        final Bundle secondOptions;
+
+        // Create a host and start listening.
+        AppWidgetHost host = spy(new AppWidgetHost(getInstrumentation().getTargetContext(), 0));
+        host.deleteHost();
+        host.startListening();
+
+        // We want to bind a widget.
+        grantBindAppWidgetPermission();
+        try {
+            // Allocate the first widget id to bind.
+            firstAppWidgetId = host.allocateAppWidgetId();
+
+            // Grab a provider we defined to be bound.
+            AppWidgetProviderInfo provider = getFirstAppWidgetProviderInfo();
+
+            // Bind the first widget.
+            getAppWidgetManager().bindAppWidgetIdIfAllowed(firstAppWidgetId,
+                    provider.getProfile(), provider.provider, null);
+
+            // Wait for onEnabled and onUpdate
+            waitForCallCount(invocationCounter, 2);
+
+            // Update the first widget options.
+            firstOptions = new Bundle();
+            firstOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, 1);
+            firstOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, 2);
+            firstOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, 3);
+            firstOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, 4);
+            getAppWidgetManager().updateAppWidgetOptions(firstAppWidgetId, firstOptions);
+
+            // Wait for onAppWidgetOptionsChanged
+            waitForCallCount(invocationCounter, 3);
+
+            // Allocate the second app widget id to bind.
+            secondAppWidgetId = host.allocateAppWidgetId();
+
+            // Bind the second widget.
+            getAppWidgetManager().bindAppWidgetIdIfAllowed(secondAppWidgetId,
+                    provider.getProfile(), provider.provider, null);
+
+            // Wait for onUpdate
+            waitForCallCount(invocationCounter, 4);
+
+            // Update the second widget options.
+            secondOptions = new Bundle();
+            secondOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, 5);
+            secondOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, 6);
+            secondOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, 7);
+            secondOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, 8);
+            getAppWidgetManager().updateAppWidgetOptions(secondAppWidgetId, secondOptions);
+
+            // Wait for onAppWidgetOptionsChanged
+            waitForCallCount(invocationCounter, 5);
+
+            // Delete the first widget.
+            host.deleteAppWidgetId(firstAppWidgetId);
+
+            // Wait for onDeleted
+            waitForCallCount(invocationCounter, 6);
+
+            // Delete the second widget.
+            host.deleteAppWidgetId(secondAppWidgetId);
+
+            // Wait for onDeleted and onDisabled
+            waitForCallCount(invocationCounter, 8);
+
+            // Make sure the provider callbacks are correct.
+            InOrder inOrder = inOrder(callbacks);
+
+            inOrder.verify(callbacks).onEnabled(any(Context.class));
+            inOrder.verify(callbacks).onUpdate(any(Context.class),
+                    any(AppWidgetManager.class), eq(new int[] {firstAppWidgetId}));
+            inOrder.verify(callbacks).onAppWidgetOptionsChanged(any(Context.class),
+                    any(AppWidgetManager.class), same(firstAppWidgetId), argThat(
+                            new OptionsMatcher(firstOptions)));
+            inOrder.verify(callbacks).onUpdate(any(Context.class),
+                    any(AppWidgetManager.class), eq(new int[] {secondAppWidgetId}));
+            inOrder.verify(callbacks).onAppWidgetOptionsChanged(any(Context.class),
+                    any(AppWidgetManager.class), same(secondAppWidgetId), argThat(
+                            new OptionsMatcher(secondOptions)));
+            inOrder.verify(callbacks).onDeleted(any(Context.class),
+                    argThat(new WidgetIdsMatcher(new int[]{firstAppWidgetId})));
+            inOrder.verify(callbacks).onDeleted(any(Context.class),
+                    argThat(new WidgetIdsMatcher(new int[]{secondAppWidgetId})));
+            inOrder.verify(callbacks).onDisabled(any(Context.class));
+        } finally {
+            // Clean up.
+            host.deleteAppWidgetId(firstAppWidgetId);
+            host.deleteAppWidgetId(secondAppWidgetId);
+            host.deleteHost();
+            FirstAppWidgetProvider.setCallbacks(null);
+            revokeBindAppWidgetPermission();
+        }
+    }
+
+    public void testTwoAppWidgetProviderCallbacks() throws Exception {
+        AtomicInteger invocationCounter = new AtomicInteger();
+
+        // Set a mock to intercept first provider callbacks.
+        AppWidgetProviderCallbacks firstCallbacks = createAppWidgetProviderCallbacks(
+                invocationCounter);
+        FirstAppWidgetProvider.setCallbacks(firstCallbacks);
+
+        // Set a mock to intercept second provider callbacks.
+        AppWidgetProviderCallbacks secondCallbacks = createAppWidgetProviderCallbacks(
+                invocationCounter);
+        SecondAppWidgetProvider.setCallbacks(secondCallbacks);
+
+        int firstAppWidgetId = 0;
+        int secondAppWidgetId = 0;
+
+        // Create a host and start listening.
+        AppWidgetHost host = spy(new AppWidgetHost(
+                getInstrumentation().getTargetContext(), 0));
+        host.deleteHost();
+        host.startListening();
+
+        // We want to bind widgets.
+        grantBindAppWidgetPermission();
+        try {
+            // Allocate the first widget id to bind.
+            firstAppWidgetId = host.allocateAppWidgetId();
+
+            // Allocate the second widget id to bind.
+            secondAppWidgetId = host.allocateAppWidgetId();
+
+            // Grab the first provider we defined to be bound.
+            AppWidgetProviderInfo firstProvider = getFirstAppWidgetProviderInfo();
+
+            // Bind the first widget.
+            getAppWidgetManager().bindAppWidgetIdIfAllowed(firstAppWidgetId,
+                    firstProvider.getProfile(), firstProvider.provider, null);
+
+            // Wait for onEnabled and onUpdate
+            waitForCallCount(invocationCounter, 2);
+
+            // Grab the second provider we defined to be bound.
+            AppWidgetProviderInfo secondProvider = getSecondAppWidgetProviderInfo();
+
+            // Bind the second widget.
+            getAppWidgetManager().bindAppWidgetIdIfAllowed(secondAppWidgetId,
+                    secondProvider.getProfile(), secondProvider.provider, null);
+
+            // Wait for onEnabled and onUpdate
+            waitForCallCount(invocationCounter, 4);
+
+            // Delete the first widget.
+            host.deleteAppWidgetId(firstAppWidgetId);
+
+            // Wait for onDeleted and onDisabled
+            waitForCallCount(invocationCounter, 6);
+
+            // Delete the second widget.
+            host.deleteAppWidgetId(secondAppWidgetId);
+
+            // Wait for onDeleted and onDisabled
+            waitForCallCount(invocationCounter, 8);
+
+            // Make sure the first provider callbacks are correct.
+            InOrder firstInOrder = inOrder(firstCallbacks);
+            firstInOrder.verify(firstCallbacks).onEnabled(any(Context.class));
+            firstInOrder.verify(firstCallbacks).onUpdate(any(Context.class),
+                    any(AppWidgetManager.class), eq(new int[]{firstAppWidgetId}));
+            firstInOrder.verify(firstCallbacks).onDeleted(any(Context.class),
+                    argThat(new WidgetIdsMatcher(new int[]{firstAppWidgetId})));
+            firstInOrder.verify(firstCallbacks).onDisabled(any(Context.class));
+
+            // Make sure the second provider callbacks are correct.
+            InOrder secondInOrder = inOrder(secondCallbacks);
+            secondInOrder.verify(secondCallbacks).onEnabled(any(Context.class));
+            secondInOrder.verify(secondCallbacks).onUpdate(any(Context.class),
+                    any(AppWidgetManager.class), eq(new int[]{secondAppWidgetId}));
+            secondInOrder.verify(secondCallbacks).onDeleted(any(Context.class),
+                    argThat(new WidgetIdsMatcher(new int[] {secondAppWidgetId})));
+            secondInOrder.verify(secondCallbacks).onDisabled(any(Context.class));
+        } finally {
+            // Clean up.
+            host.deleteAppWidgetId(firstAppWidgetId);
+            host.deleteAppWidgetId(secondAppWidgetId);
+            host.deleteHost();
+            FirstAppWidgetProvider.setCallbacks(null);
+            SecondAppWidgetProvider.setCallbacks(null);
+            revokeBindAppWidgetPermission();
+        }
+    }
+
+    public void testGetAppWidgetIds() throws Exception {
+        // We want to bind widgets.
+        grantBindAppWidgetPermission();
+
+        // Create a host and start listening.
+        AppWidgetHost host = new AppWidgetHost(
+                getInstrumentation().getTargetContext(), 0);
+        host.deleteHost();
+        host.startListening();
+
+        int firstAppWidgetId = 0;
+        int secondAppWidgetId = 0;
+
+        try {
+            // Grab the provider we defined to be bound.
+            AppWidgetProviderInfo provider = getFirstAppWidgetProviderInfo();
+
+            // Initially we have no widgets.
+            int[] widgetsIds = getAppWidgetManager().getAppWidgetIds(provider.provider);
+            assertTrue(widgetsIds.length == 0);
+
+            // Allocate the first widget id to bind.
+            firstAppWidgetId = host.allocateAppWidgetId();
+
+            // Bind the first widget.
+            getAppWidgetManager().bindAppWidgetIdIfAllowed(firstAppWidgetId,
+                    provider.getProfile(), provider.provider, null);
+
+            // Allocate the second widget id to bind.
+            secondAppWidgetId = host.allocateAppWidgetId();
+
+            // Bind the second widget.
+            getAppWidgetManager().bindAppWidgetIdIfAllowed(secondAppWidgetId,
+                    provider.getProfile(), provider.provider, null);
+
+            // Now we have two widgets,
+            widgetsIds = getAppWidgetManager().getAppWidgetIds(provider.provider);
+            assertTrue(Arrays.equals(widgetsIds, new int[]{firstAppWidgetId, secondAppWidgetId}));
+        } finally {
+            // Clean up.
+            host.deleteAppWidgetId(firstAppWidgetId);
+            host.deleteAppWidgetId(secondAppWidgetId);
+            host.deleteHost();
+            revokeBindAppWidgetPermission();
+        }
+    }
+
+    public void testGetAppWidgetInfo() throws Exception {
+        // We want to bind widgets.
+        grantBindAppWidgetPermission();
+
+        // Create a host and start listening.
+        AppWidgetHost host = new AppWidgetHost(
+                getInstrumentation().getTargetContext(), 0);
+        host.deleteHost();
+        host.startListening();
+
+        int appWidgetId = 0;
+
+        try {
+            // Allocate an widget id to bind.
+            appWidgetId = host.allocateAppWidgetId();
+
+            // The widget is not bound, so no info.
+            AppWidgetProviderInfo foundProvider = getAppWidgetManager()
+                    .getAppWidgetInfo(appWidgetId);
+            assertNull(foundProvider);
+
+            // Grab the provider we defined to be bound.
+            AppWidgetProviderInfo provider = getFirstAppWidgetProviderInfo();
+
+            // Bind the app widget.
+            getAppWidgetManager().bindAppWidgetIdIfAllowed(appWidgetId,
+                    provider.getProfile(), provider.provider, null);
+
+            // The widget is bound, so the provider info should be there.
+            foundProvider = getAppWidgetManager().getAppWidgetInfo(appWidgetId);
+            assertEquals(provider.provider, foundProvider.provider);
+            assertEquals(provider.getProfile(), foundProvider.getProfile());
+
+            Context context = getInstrumentation().getTargetContext();
+
+            // Let us make sure the provider info is sane.
+            String label = foundProvider.loadLabel(context.getPackageManager());
+            assertTrue(!TextUtils.isEmpty(label));
+
+            Drawable icon = foundProvider.loadIcon(context, DisplayMetrics.DENSITY_DEFAULT);
+            assertNotNull(icon);
+
+            Drawable previewImage = foundProvider.loadPreviewImage(context, 0);
+            assertNotNull(previewImage);
+        } finally {
+            // Clean up.
+            host.deleteAppWidgetId(appWidgetId);
+            host.deleteHost();
+            revokeBindAppWidgetPermission();
+        }
+    }
+
+    public void testGetAppWidgetOptions() throws Exception {
+        // We want to bind widgets.
+        grantBindAppWidgetPermission();
+
+        // Create a host and start listening.
+        AppWidgetHost host = new AppWidgetHost(
+                getInstrumentation().getTargetContext(), 0);
+        host.deleteHost();
+        host.startListening();
+
+        int appWidgetId = 0;
+
+        try {
+            // Grab the provider we defined to be bound.
+            AppWidgetProviderInfo provider = getFirstAppWidgetProviderInfo();
+
+            // Allocate an widget id to bind.
+            appWidgetId = host.allocateAppWidgetId();
+
+            // Initially we have no options.
+            Bundle foundOptions = getAppWidgetManager().getAppWidgetOptions(appWidgetId);
+            assertTrue(foundOptions.isEmpty());
+
+            // We want to set the options when binding.
+            Bundle setOptions = new Bundle();
+            setOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, 1);
+            setOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, 2);
+            setOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, 3);
+            setOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, 4);
+
+            // Bind the app widget.
+            getAppWidgetManager().bindAppWidgetIdIfAllowed(appWidgetId,
+                    provider.getProfile(), provider.provider, setOptions);
+
+            // Make sure we get the options used when binding.
+            foundOptions = getAppWidgetManager().getAppWidgetOptions(appWidgetId);
+            assertTrue(equalOptions(setOptions, foundOptions));
+        } finally {
+            // Clean up.
+            host.deleteAppWidgetId(appWidgetId);
+            host.deleteHost();
+            revokeBindAppWidgetPermission();
+        }
+    }
+
+    public void testDeleteHost() throws Exception {
+        // We want to bind widgets.
+        grantBindAppWidgetPermission();
+
+        // Create a host and start listening.
+        AppWidgetHost host = new AppWidgetHost(
+                getInstrumentation().getTargetContext(), 0);
+        host.deleteHost();
+        host.startListening();
+
+        int appWidgetId = 0;
+
+        try {
+            // Allocate an widget id to bind.
+            appWidgetId = host.allocateAppWidgetId();
+
+            // Grab the provider we defined to be bound.
+            AppWidgetProviderInfo provider = getFirstAppWidgetProviderInfo();
+
+            // Bind the app widget.
+            getAppWidgetManager().bindAppWidgetIdIfAllowed(appWidgetId,
+                    provider.getProfile(), provider.provider, null);
+
+            // The widget should be there.
+            int[] widgetIds = getAppWidgetManager().getAppWidgetIds(provider.provider);
+            assertTrue(Arrays.equals(widgetIds, new int[]{appWidgetId}));
+
+            // Delete the host.
+            host.deleteHost();
+
+            // The host is gone and with it the widgets.
+            widgetIds = getAppWidgetManager().getAppWidgetIds(provider.provider);
+            assertTrue(widgetIds.length == 0);
+        } finally {
+            // Clean up.
+            host.deleteAppWidgetId(appWidgetId);
+            host.deleteHost();
+            revokeBindAppWidgetPermission();
+        }
+    }
+
+    public void testDeleteHosts() throws Exception {
+        // We want to bind widgets.
+        grantBindAppWidgetPermission();
+
+        // Create the first host and start listening.
+        AppWidgetHost firstHost = new AppWidgetHost(
+                getInstrumentation().getTargetContext(), 0);
+        firstHost.deleteHost();
+        firstHost.startListening();
+
+        // Create the second host and start listening.
+        AppWidgetHost secondHost = new AppWidgetHost(
+                getInstrumentation().getTargetContext(), 1);
+        secondHost.deleteHost();
+        secondHost.startListening();
+
+        int firstAppWidgetId = 0;
+        int secondAppWidgetId = 0;
+
+        try {
+            // Grab the provider we defined to be bound.
+            AppWidgetProviderInfo provider = getFirstAppWidgetProviderInfo();
+
+            // Allocate the first widget id to bind.
+            firstAppWidgetId = firstHost.allocateAppWidgetId();
+
+            // Bind the first app widget.
+            getAppWidgetManager().bindAppWidgetIdIfAllowed(firstAppWidgetId,
+                    provider.getProfile(), provider.provider, null);
+
+            // Allocate the second widget id to bind.
+            secondAppWidgetId = secondHost.allocateAppWidgetId();
+
+            // Bind the second app widget.
+            getAppWidgetManager().bindAppWidgetIdIfAllowed(secondAppWidgetId,
+                    provider.getProfile(), provider.provider, null);
+
+            // The widgets should be there.
+            int[] widgetIds = getAppWidgetManager().getAppWidgetIds(provider.provider);
+            assertTrue(Arrays.equals(widgetIds, new int[]{firstAppWidgetId, secondAppWidgetId}));
+
+            // Delete all hosts.
+            AppWidgetHost.deleteAllHosts();
+
+            // The hosts are gone and with it the widgets.
+            widgetIds = getAppWidgetManager().getAppWidgetIds(provider.provider);
+            assertTrue(widgetIds.length == 0);
+        } finally {
+            // Clean up.
+            firstHost.deleteAppWidgetId(firstAppWidgetId);
+            secondHost.deleteAppWidgetId(secondAppWidgetId);
+            AppWidgetHost.deleteAllHosts();
+            revokeBindAppWidgetPermission();
+        }
+    }
+
+    public void testOnProvidersChanged() throws Exception {
+        // We want to bind widgets.
+        grantBindAppWidgetPermission();
+
+        final AtomicInteger onProvidersChangedCallCounter = new AtomicInteger();
+
+        // Create a host and start listening.
+        AppWidgetHost host = new AppWidgetHost(
+                getInstrumentation().getTargetContext(), 0) {
+            @Override
+            public void onProvidersChanged() {
+                synchronized (mLock) {
+                    onProvidersChangedCallCounter.incrementAndGet();
+                    mLock.notifyAll();
+                }
+            }
+        };
+        host.deleteHost();
+        host.startListening();
+
+        int appWidgetId = 0;
+
+        try {
+            // Grab the provider we defined to be bound.
+            AppWidgetProviderInfo firstLookupProvider = getFirstAppWidgetProviderInfo();
+
+            // Allocate a widget id to bind.
+            appWidgetId = host.allocateAppWidgetId();
+
+            // Bind the first app widget.
+            getAppWidgetManager().bindAppWidgetIdIfAllowed(appWidgetId,
+                    firstLookupProvider.getProfile(), firstLookupProvider.provider, null);
+
+            // Disable the provider we just bound to.
+            PackageManager packageManager = getInstrumentation().getTargetContext()
+                    .getApplicationContext().getPackageManager();
+            packageManager.setComponentEnabledSetting(firstLookupProvider.provider,
+                    PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+                    PackageManager.DONT_KILL_APP);
+
+            // Wait for the package change to propagate.
+            waitForCallCount(onProvidersChangedCallCounter, 1);
+
+            // The provider should not be present anymore.
+            AppWidgetProviderInfo secondLookupProvider = getFirstAppWidgetProviderInfo();
+            assertNull(secondLookupProvider);
+
+            // Enable the provider we disabled.
+            packageManager.setComponentEnabledSetting(firstLookupProvider.provider,
+                    PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+                    PackageManager.DONT_KILL_APP);
+
+            // Wait for the package change to propagate.
+            waitForCallCount(onProvidersChangedCallCounter, 2);
+        } finally {
+            // Clean up.
+            host.deleteAppWidgetId(appWidgetId);
+            host.deleteHost();
+            revokeBindAppWidgetPermission();
+        }
+    }
+
+    public void testUpdateAppWidgetViaComponentName() throws Exception {
+        // We want to bind widgets.
+        grantBindAppWidgetPermission();
+
+        final AtomicInteger updateAppWidgetCallCount = new AtomicInteger();
+
+        // Create a host and start listening.
+        AppWidgetHost host = new AppWidgetHost(
+                getInstrumentation().getTargetContext(), 0) {
+            @Override
+            protected AppWidgetHostView onCreateView(Context context, int appWidgetId,
+                    AppWidgetProviderInfo appWidget) {
+                return new MyAppWidgetHostView(context);
+            }
+        };
+        host.deleteHost();
+        host.startListening();
+
+        int firstAppWidgetId = 0;
+        int secondAppWidgetId = 0;
+
+        try {
+            // Grab the provider to be bound.
+            AppWidgetProviderInfo provider = getFirstAppWidgetProviderInfo();
+
+            // Allocate the first widget id to bind.
+            firstAppWidgetId = host.allocateAppWidgetId();
+
+            // Bind the first app widget.
+            getAppWidgetManager().bindAppWidgetIdIfAllowed(firstAppWidgetId,
+                    provider.getProfile(), provider.provider, null);
+
+            // Create the first host view.
+            MyAppWidgetHostView firstHostView = (MyAppWidgetHostView) host.createView(
+                    getInstrumentation().getContext(), firstAppWidgetId, provider);
+            MyAppWidgetHostView.OnUpdateAppWidgetListener firstAppHostViewListener =
+                    mock(MyAppWidgetHostView.OnUpdateAppWidgetListener.class);
+            firstHostView.setOnUpdateAppWidgetListener(firstAppHostViewListener);
+
+            // Allocate the second widget id to bind.
+            secondAppWidgetId = host.allocateAppWidgetId();
+
+            // Bind the second app widget.
+            getAppWidgetManager().bindAppWidgetIdIfAllowed(secondAppWidgetId,
+                    provider.getProfile(), provider.provider, null);
+
+            // Create the second host view.
+            MyAppWidgetHostView secondHostView = (MyAppWidgetHostView) host.createView(
+                    getInstrumentation().getContext(), secondAppWidgetId, provider);
+            MyAppWidgetHostView.OnUpdateAppWidgetListener secondAppHostViewListener =
+                    mock(MyAppWidgetHostView.OnUpdateAppWidgetListener.class);
+            doAnswer(new Answer<Void>() {
+                @Override
+                public Void answer(InvocationOnMock invocation) throws Throwable {
+                    synchronized (mLock) {
+                        updateAppWidgetCallCount.incrementAndGet();
+                        mLock.notifyAll();
+                    }
+                    return null;
+                }
+            }).when(secondAppHostViewListener).onUpdateAppWidget(any(RemoteViews.class));
+            secondHostView.setOnUpdateAppWidgetListener(secondAppHostViewListener);
+
+            // Update all app widgets.
+            final RemoteViews content = new RemoteViews(
+                    getInstrumentation().getContext().getPackageName(),
+                    R.layout.second_initial_layout);
+            getAppWidgetManager().updateAppWidget(provider.provider, content);
+
+            waitForCallCount(updateAppWidgetCallCount, 1);
+
+            // Verify the expected callbacks.
+            InOrder firstInOrder = inOrder(firstAppHostViewListener);
+            firstInOrder.verify(firstAppHostViewListener).onUpdateAppWidget(argThat(
+                    new RemoteViewsMatcher(content.getLayoutId(),
+                            provider.provider.getPackageName())));
+
+            InOrder secondInOrder = inOrder(secondAppHostViewListener);
+            secondInOrder.verify(secondAppHostViewListener).onUpdateAppWidget(argThat(
+                    new RemoteViewsMatcher(content.getLayoutId(),
+                            provider.provider.getPackageName())));
+        } finally {
+            // Clean up.
+            host.deleteAppWidgetId(firstAppWidgetId);
+            host.deleteAppWidgetId(secondAppWidgetId);
+            host.deleteHost();
+            revokeBindAppWidgetPermission();
+        }
+    }
+
+    public void testUpdateAppWidgetViaWidgetId() throws Exception {
+        // We want to bind widgets.
+        grantBindAppWidgetPermission();
+
+        final AtomicInteger updateAppWidgetCallCount = new AtomicInteger();
+
+        // Create a host and start listening.
+        AppWidgetHost host = new AppWidgetHost(
+                getInstrumentation().getTargetContext(), 0) {
+            @Override
+            protected AppWidgetHostView onCreateView(Context context, int appWidgetId,
+                    AppWidgetProviderInfo appWidget) {
+                return new MyAppWidgetHostView(context);
+            }
+        };
+        host.deleteHost();
+        host.startListening();
+
+        int firstAppWidgetId = 0;
+
+        try {
+            // Grab the provider to be bound.
+            AppWidgetProviderInfo provider = getFirstAppWidgetProviderInfo();
+
+            // Allocate the first widget id to bind.
+            firstAppWidgetId = host.allocateAppWidgetId();
+
+            // Bind the first app widget.
+            getAppWidgetManager().bindAppWidgetIdIfAllowed(firstAppWidgetId,
+                    provider.getProfile(), provider.provider, null);
+
+            // Create the first host view.
+            MyAppWidgetHostView hostView = (MyAppWidgetHostView) host.createView(
+                    getInstrumentation().getContext(), firstAppWidgetId, provider);
+            MyAppWidgetHostView.OnUpdateAppWidgetListener appHostViewListener =
+                    mock(MyAppWidgetHostView.OnUpdateAppWidgetListener.class);
+            doAnswer(new Answer<Void>() {
+                @Override
+                public Void answer(InvocationOnMock invocation) throws Throwable {
+                    synchronized (mLock) {
+                        updateAppWidgetCallCount.incrementAndGet();
+                        mLock.notifyAll();
+                    }
+                    return null;
+                }
+            }).when(appHostViewListener).onUpdateAppWidget(any(RemoteViews.class));
+            hostView.setOnUpdateAppWidgetListener(appHostViewListener);
+
+            // Update all app widgets.
+            RemoteViews content = new RemoteViews(
+                    getInstrumentation().getContext().getPackageName(),
+                    R.layout.second_initial_layout);
+            getAppWidgetManager().updateAppWidget(firstAppWidgetId, content);
+
+            waitForCallCount(updateAppWidgetCallCount, 1);
+
+            // Verify the expected callbacks.
+            InOrder inOrder = inOrder(appHostViewListener);
+            inOrder.verify(appHostViewListener).onUpdateAppWidget(argThat(
+                    new RemoteViewsMatcher(content.getLayoutId(),
+                            provider.provider.getPackageName())
+            ));
+        } finally {
+            // Clean up.
+            host.deleteAppWidgetId(firstAppWidgetId);
+            host.deleteHost();
+            revokeBindAppWidgetPermission();
+        }
+    }
+
+    public void testUpdateAppWidgetViaWidgetIds() throws Exception {
+        // We want to bind widgets.
+        grantBindAppWidgetPermission();
+
+        final AtomicInteger onUpdateAppWidgetCallCount = new AtomicInteger();
+
+        // Create a host and start listening.
+        AppWidgetHost host = new AppWidgetHost(
+                getInstrumentation().getTargetContext(), 0) {
+            @Override
+            protected AppWidgetHostView onCreateView(Context context, int appWidgetId,
+                    AppWidgetProviderInfo appWidget) {
+                return new MyAppWidgetHostView(context);
+            }
+        };
+        host.deleteHost();
+        host.startListening();
+
+        int firstAppWidgetId = 0;
+        int secondAppWidgetId = 0;
+
+        try {
+            // Grab the provider to be bound.
+            AppWidgetProviderInfo provider = getFirstAppWidgetProviderInfo();
+
+            // Allocate the first widget id to bind.
+            firstAppWidgetId = host.allocateAppWidgetId();
+
+            // Bind the first app widget.
+            getAppWidgetManager().bindAppWidgetIdIfAllowed(firstAppWidgetId,
+                    provider.getProfile(), provider.provider, null);
+
+            // Create the first host view.
+            MyAppWidgetHostView firstHostView = (MyAppWidgetHostView) host.createView(
+                    getInstrumentation().getContext(), firstAppWidgetId, provider);
+            MyAppWidgetHostView.OnUpdateAppWidgetListener firstAppHostViewListener =
+                    mock(MyAppWidgetHostView.OnUpdateAppWidgetListener.class);
+            firstHostView.setOnUpdateAppWidgetListener(firstAppHostViewListener);
+
+            // Allocate the second widget id to bind.
+            secondAppWidgetId = host.allocateAppWidgetId();
+
+            // Bind the second app widget.
+            getAppWidgetManager().bindAppWidgetIdIfAllowed(secondAppWidgetId,
+                    provider.getProfile(), provider.provider, null);
+
+            // Create the second host view.
+            MyAppWidgetHostView secondHostView = (MyAppWidgetHostView) host.createView(
+                    getInstrumentation().getContext(), secondAppWidgetId, provider);
+            MyAppWidgetHostView.OnUpdateAppWidgetListener secondAppHostViewListener =
+                    mock(MyAppWidgetHostView.OnUpdateAppWidgetListener.class);
+            doAnswer(new Answer<Void>() {
+                @Override
+                public Void answer(InvocationOnMock invocation) throws Throwable {
+                    synchronized (mLock) {
+                        onUpdateAppWidgetCallCount.incrementAndGet();
+                        mLock.notifyAll();
+                    }
+                    return null;
+                }
+            }).when(secondAppHostViewListener).onUpdateAppWidget(any(RemoteViews.class));
+            secondHostView.setOnUpdateAppWidgetListener(secondAppHostViewListener);
+
+            // Update all app widgets.
+            RemoteViews content = new RemoteViews(
+                    getInstrumentation().getContext().getPackageName(),
+                    R.layout.second_initial_layout);
+            getAppWidgetManager().updateAppWidget(new int[] {firstAppWidgetId,
+                    secondAppWidgetId}, content);
+
+            waitForCallCount(onUpdateAppWidgetCallCount, 1);
+
+            // Verify the expected callbacks.
+            InOrder firstInOrder = inOrder(firstAppHostViewListener);
+            firstInOrder.verify(firstAppHostViewListener).onUpdateAppWidget(
+                    argThat(new RemoteViewsMatcher(content.getLayoutId(),
+                            provider.provider.getPackageName())));
+
+            InOrder secondInOrder = inOrder(secondAppHostViewListener);
+            secondInOrder.verify(secondAppHostViewListener).onUpdateAppWidget(
+                    argThat(new RemoteViewsMatcher(content.getLayoutId(),
+                            provider.provider.getPackageName()))
+            );
+        } finally {
+            // Clean up.
+            host.deleteAppWidgetId(firstAppWidgetId);
+            host.deleteAppWidgetId(secondAppWidgetId);
+            host.deleteHost();
+            revokeBindAppWidgetPermission();
+        }
+    }
+
+    public void testPartiallyUpdateAppWidgetViaWidgetId() throws Exception {
+        // We want to bind widgets.
+        grantBindAppWidgetPermission();
+
+        final AtomicInteger updateAppWidgetCallCount = new AtomicInteger();
+
+        // Create a host and start listening.
+        AppWidgetHost host = new AppWidgetHost(
+                getInstrumentation().getTargetContext(), 0) {
+            @Override
+            protected AppWidgetHostView onCreateView(Context context, int appWidgetId,
+                    AppWidgetProviderInfo appWidget) {
+                return new MyAppWidgetHostView(context);
+            }
+        };
+        host.deleteHost();
+        host.startListening();
+
+        int firstAppWidgetId = 0;
+
+        try {
+            // Grab the provider to be bound.
+            AppWidgetProviderInfo provider = getFirstAppWidgetProviderInfo();
+
+            // Allocate the first widget id to bind.
+            firstAppWidgetId = host.allocateAppWidgetId();
+
+            // Bind the first app widget.
+            getAppWidgetManager().bindAppWidgetIdIfAllowed(firstAppWidgetId,
+                    provider.getProfile(), provider.provider, null);
+
+            // Create the first host view.
+            MyAppWidgetHostView hostView = (MyAppWidgetHostView) host.createView(
+                    getInstrumentation().getContext(), firstAppWidgetId, provider);
+            MyAppWidgetHostView.OnUpdateAppWidgetListener appHostViewListener =
+                    mock(MyAppWidgetHostView.OnUpdateAppWidgetListener.class);
+            doAnswer(new Answer<Void>() {
+                @Override
+                public Void answer(InvocationOnMock invocation) throws Throwable {
+                    synchronized (mLock) {
+                        updateAppWidgetCallCount.incrementAndGet();
+                        mLock.notifyAll();
+                    }
+                    return null;
+                }
+            }).when(appHostViewListener).onUpdateAppWidget(any(RemoteViews.class));
+            hostView.setOnUpdateAppWidgetListener(appHostViewListener);
+
+            // Set the content for all app widgets.
+            RemoteViews content = new RemoteViews(
+                    getInstrumentation().getContext().getPackageName(),
+                    R.layout.first_initial_layout);
+            getAppWidgetManager().updateAppWidget(firstAppWidgetId, content);
+
+            waitForCallCount(updateAppWidgetCallCount, 1);
+
+            // Partially update the content for all app widgets (pretend we changed something).
+            getAppWidgetManager().partiallyUpdateAppWidget(firstAppWidgetId, content);
+
+            waitForCallCount(updateAppWidgetCallCount, 2);
+
+            // Verify the expected callbacks.
+            InOrder inOrder = inOrder(appHostViewListener);
+            inOrder.verify(appHostViewListener, times(2)).onUpdateAppWidget(
+                    argThat(new RemoteViewsMatcher(content.getLayoutId(),
+                            provider.provider.getPackageName())));
+        } finally {
+            // Clean up.
+            host.deleteAppWidgetId(firstAppWidgetId);
+            host.deleteHost();
+            revokeBindAppWidgetPermission();
+        }
+    }
+
+    public void testPartiallyUpdateAppWidgetViaWidgetIds() throws Exception {
+        // We want to bind widgets.
+        grantBindAppWidgetPermission();
+
+        final AtomicInteger firstAppWidgetCallCounter = new AtomicInteger();
+        final AtomicInteger secondAppWidgetCallCounter = new AtomicInteger();
+
+        // Create a host and start listening.
+        AppWidgetHost host = new AppWidgetHost(
+                getInstrumentation().getTargetContext(), 0) {
+            @Override
+            protected AppWidgetHostView onCreateView(Context context, int appWidgetId,
+                    AppWidgetProviderInfo appWidget) {
+                return new MyAppWidgetHostView(context);
+            }
+        };
+        host.deleteHost();
+        host.startListening();
+
+        int firstAppWidgetId = 0;
+        int secondAppWidgetId = 0;
+
+        try {
+            // Grab the provider to be bound.
+            AppWidgetProviderInfo provider = getFirstAppWidgetProviderInfo();
+
+            // Allocate the first widget id to bind.
+            firstAppWidgetId = host.allocateAppWidgetId();
+
+            // Bind the first app widget.
+            getAppWidgetManager().bindAppWidgetIdIfAllowed(firstAppWidgetId,
+                    provider.getProfile(), provider.provider, null);
+
+            // Create the first host view.
+            MyAppWidgetHostView firstHostView = (MyAppWidgetHostView) host.createView(
+                    getInstrumentation().getContext(), firstAppWidgetId, provider);
+            MyAppWidgetHostView.OnUpdateAppWidgetListener firstAppHostViewListener =
+                    mock(MyAppWidgetHostView.OnUpdateAppWidgetListener.class);
+            doAnswer(new Answer<Void>() {
+                @Override
+                public Void answer(InvocationOnMock invocation) throws Throwable {
+                    synchronized (mLock) {
+                        firstAppWidgetCallCounter.incrementAndGet();
+                        mLock.notifyAll();
+                    }
+                    return null;
+                }
+            }).when(firstAppHostViewListener).onUpdateAppWidget(any(RemoteViews.class));
+            firstHostView.setOnUpdateAppWidgetListener(firstAppHostViewListener);
+
+            // Allocate the second widget id to bind.
+            secondAppWidgetId = host.allocateAppWidgetId();
+
+            // Bind the second app widget.
+            getAppWidgetManager().bindAppWidgetIdIfAllowed(secondAppWidgetId,
+                    provider.getProfile(), provider.provider, null);
+
+            // Create the second host view.
+            MyAppWidgetHostView secondHostView = (MyAppWidgetHostView) host.createView(
+                    getInstrumentation().getContext(), secondAppWidgetId, provider);
+            MyAppWidgetHostView.OnUpdateAppWidgetListener secondAppHostViewListener =
+                    mock(MyAppWidgetHostView.OnUpdateAppWidgetListener.class);
+            doAnswer(new Answer<Void>() {
+                @Override
+                public Void answer(InvocationOnMock invocation) throws Throwable {
+                    synchronized (mLock) {
+                        secondAppWidgetCallCounter.incrementAndGet();
+                        mLock.notifyAll();
+                    }
+                    return null;
+                }
+            }).when(secondAppHostViewListener).onUpdateAppWidget(any(RemoteViews.class));
+            secondHostView.setOnUpdateAppWidgetListener(secondAppHostViewListener);
+
+            // Set the content for all app widgets.
+            RemoteViews content = new RemoteViews(
+                    getInstrumentation().getContext().getPackageName(),
+                    R.layout.first_initial_layout);
+            getAppWidgetManager().updateAppWidget(new int[]{firstAppWidgetId,
+                    secondAppWidgetId}, content);
+
+            waitForCallCount(firstAppWidgetCallCounter, 1);
+            waitForCallCount(secondAppWidgetCallCounter, 1);
+
+            // Partially update the content for all app widgets (pretend we changed something).
+            getAppWidgetManager().partiallyUpdateAppWidget(new int[] {firstAppWidgetId,
+                    secondAppWidgetId}, content);
+
+            waitForCallCount(firstAppWidgetCallCounter, 2);
+            waitForCallCount(secondAppWidgetCallCounter, 2);
+
+            // Verify the expected callbacks.
+            InOrder firstInOrder = inOrder(firstAppHostViewListener);
+            firstInOrder.verify(firstAppHostViewListener, times(2)).onUpdateAppWidget(
+                    argThat(new RemoteViewsMatcher(content.getLayoutId(),
+                            provider.provider.getPackageName())));
+
+            InOrder secondInOrder = inOrder(secondAppHostViewListener);
+            secondInOrder.verify(secondAppHostViewListener, times(2)).onUpdateAppWidget(
+                    argThat(new RemoteViewsMatcher(content.getLayoutId(),
+                            provider.provider.getPackageName())));
+        } finally {
+            // Clean up.
+            host.deleteAppWidgetId(firstAppWidgetId);
+            host.deleteAppWidgetId(secondAppWidgetId);
+            host.deleteHost();
+            revokeBindAppWidgetPermission();
+        }
+    }
+
+    public void testCollectionWidgets() throws Exception {
+        // We want to bind widgets.
+        grantBindAppWidgetPermission();
+
+        final AtomicInteger invocationCounter = new AtomicInteger();
+        final Context context = getInstrumentation().getTargetContext();
+
+        // Create a host and start listening.
+        final AppWidgetHost host = new AppWidgetHost(context, 0);
+        host.deleteHost();
+        host.startListening();
+
+        final int appWidgetId;
+
+        try {
+            // Configure the provider behavior.
+            AppWidgetProviderCallbacks callbacks = createAppWidgetProviderCallbacks(
+                    invocationCounter);
+            doAnswer(new Answer<Void>() {
+                @Override
+                public Void answer(InvocationOnMock invocation) throws Throwable {
+                    final int appWidgetId = ((int[]) invocation.getArguments()[2])[0];
+
+                    Intent intent = new Intent(context, MyAppWidgetService.class);
+                    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
+                    intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
+
+                    RemoteViews removeViews = new RemoteViews(context.getPackageName(),
+                            R.layout.collection_widget_layout);
+                    removeViews.setRemoteAdapter(R.id.stack_view, intent);
+
+                    getAppWidgetManager().updateAppWidget(appWidgetId, removeViews);
+
+                    synchronized (mLock) {
+                        invocationCounter.incrementAndGet();
+                        mLock.notifyAll();
+                    }
+
+                    return null;
+                }
+            }).when(callbacks).onUpdate(any(Context.class), any(AppWidgetManager.class),
+                    any(int[].class));
+            FirstAppWidgetProvider.setCallbacks(callbacks);
+
+            // Grab the provider to be bound.
+            final AppWidgetProviderInfo provider = getFirstAppWidgetProviderInfo();
+
+            // Allocate a widget id to bind.
+            appWidgetId = host.allocateAppWidgetId();
+
+            // Bind the app widget.
+            getAppWidgetManager().bindAppWidgetIdIfAllowed(appWidgetId,
+                    provider.getProfile(), provider.provider, null);
+
+            // Wait for onEnabled and onUpdate
+            waitForCallCount(invocationCounter, 2);
+
+            // Configure the app widget service behavior.
+            RemoteViewsFactory factory = mock(RemoteViewsFactory.class);
+            doAnswer(new Answer<Integer>() {
+                @Override
+                public Integer answer(InvocationOnMock invocation) throws Throwable {
+                    return 1;
+                }
+            }).when(factory).getCount();
+            doAnswer(new Answer<RemoteViews>() {
+                @Override
+                public RemoteViews answer(InvocationOnMock invocation) throws Throwable {
+                    RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
+                            R.layout.collection_widget_item_layout);
+                    remoteViews.setTextViewText(R.id.text_view, context.getText(R.string.foo));
+                    synchronized (mLock) {
+                        invocationCounter.incrementAndGet();
+                    }
+                    return remoteViews;
+                }
+            }).when(factory).getViewAt(any(int.class));
+            doAnswer(new Answer<Integer>() {
+                @Override
+                public Integer answer(InvocationOnMock invocation) throws Throwable {
+                    return 1;
+                }
+            }).when(factory).getViewTypeCount();
+            MyAppWidgetService.setFactory(factory);
+
+            getInstrumentation().runOnMainSync(new Runnable() {
+                @Override
+                public void run() {
+                    host.createView(context, appWidgetId, provider);
+                }
+            });
+
+            // Wait for the interactions to occur.
+            waitForCallCount(invocationCounter, 3);
+
+            // Verify the interactions.
+            verify(factory, atLeastOnce()).hasStableIds();
+            verify(factory, atLeastOnce()).getViewTypeCount();
+            verify(factory, atLeastOnce()).getCount();
+            verify(factory, atLeastOnce()).getLoadingView();
+            verify(factory, atLeastOnce()).getViewAt(same(0));
+        } finally {
+            // Clean up.
+            FirstAppWidgetProvider.setCallbacks(null);
+            host.deleteHost();
+            revokeBindAppWidgetPermission();
+        }
+    }
+
+    private void waitForCallCount(AtomicInteger counter, int expectedCount) {
+        synchronized (mLock) {
+            final long startTimeMillis = SystemClock.uptimeMillis();
+            while (counter.get() < expectedCount) {
+                final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
+                final long remainingTimeMillis = OPERATION_TIMEOUT - elapsedTimeMillis;
+                if (remainingTimeMillis <= 0) {
+                    fail("Did not get expected call");
+                }
+                try {
+                    mLock.wait(remainingTimeMillis);
+                } catch (InterruptedException ie) {
+                        /* ignore */
+                }
+            }
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    private void assertExpectedInstalledProviders(List<AppWidgetProviderInfo> providers) {
+        boolean firstProviderVerified = false;
+        boolean secondProviderVerified = false;
+
+        ComponentName firstComponentName = new ComponentName(
+                getInstrumentation().getTargetContext().getPackageName(),
+                FirstAppWidgetProvider.class.getName());
+
+        ComponentName secondComponentName = new ComponentName(
+                getInstrumentation().getTargetContext().getPackageName(),
+                SecondAppWidgetProvider.class.getName());
+
+        final int providerCount = providers.size();
+        for (int i = 0; i < providerCount; i++) {
+            AppWidgetProviderInfo provider = providers.get(i);
+
+            if (firstComponentName.equals(provider.provider)
+                    && android.os.Process.myUserHandle().equals(provider.getProfile())) {
+                assertEquals(getNormalizedDimensionResource(R.dimen.first_min_appwidget_size),
+                        provider.minWidth);
+                assertEquals(getNormalizedDimensionResource(R.dimen.first_min_appwidget_size),
+                        provider.minHeight);
+                assertEquals(getNormalizedDimensionResource(
+                        R.dimen.first_min_resize_appwidget_size), provider.minResizeWidth);
+                assertEquals(getNormalizedDimensionResource(
+                        R.dimen.first_min_resize_appwidget_size), provider.minResizeHeight);
+                assertEquals(getIntResource(R.integer.first_update_period_millis),
+                        provider.updatePeriodMillis);
+                assertEquals(getInstrumentation().getTargetContext().getPackageName(),
+                        provider.configure.getPackageName());
+                assertEquals(FIRST_APP_WIDGET_CONFIGURE_ACTIVITY,
+                        provider.configure.getClassName());
+                assertEquals(getIntResource(R.integer.first_resize_mode),
+                        provider.resizeMode);
+                assertEquals(getIntResource(R.integer.first_widget_category),
+                        provider.widgetCategory);
+                assertEquals(R.layout.first_initial_layout,
+                        provider.initialLayout);
+                assertEquals(R.layout.first_initial_keyguard_layout,
+                        provider.initialKeyguardLayout);
+                assertEquals(R.drawable.first_android_icon,
+                        provider.previewImage);
+                assertEquals(R.id.first_auto_advance_view_id,
+                        provider.autoAdvanceViewId);
+                firstProviderVerified = true;
+            } else if (secondComponentName.equals(provider.provider)
+                    && android.os.Process.myUserHandle().equals(provider.getProfile())) {
+                assertEquals(getNormalizedDimensionResource(R.dimen.second_min_appwidget_size),
+                        provider.minWidth);
+                assertEquals(getNormalizedDimensionResource(R.dimen.second_min_appwidget_size),
+                        provider.minHeight);
+                assertEquals(getNormalizedDimensionResource(
+                        R.dimen.second_min_resize_appwidget_size), provider.minResizeWidth);
+                assertEquals(getNormalizedDimensionResource(
+                        R.dimen.second_min_resize_appwidget_size), provider.minResizeHeight);
+                assertEquals(getIntResource(R.integer.second_update_period_millis),
+                        provider.updatePeriodMillis);
+                assertEquals(getInstrumentation().getTargetContext().getPackageName(),
+                        provider.configure.getPackageName());
+                assertEquals(SECOND_APP_WIDGET_CONFIGURE_ACTIVITY,
+                        provider.configure.getClassName());
+                assertEquals(getIntResource(R.integer.second_resize_mode),
+                        provider.resizeMode);
+                assertEquals(getIntResource(R.integer.second_widget_category),
+                        provider.widgetCategory);
+                assertEquals(R.layout.second_initial_layout,
+                        provider.initialLayout);
+                assertEquals(R.layout.second_initial_keyguard_layout,
+                        provider.initialKeyguardLayout);
+                assertEquals(R.drawable.second_android_icon,
+                        provider.previewImage);
+                assertEquals(R.id.second_auto_advance_view_id,
+                        provider.autoAdvanceViewId);
+                secondProviderVerified = true;
+            }
+        }
+
+        assertTrue(firstProviderVerified && secondProviderVerified);
+    }
+
+    private void grantBindAppWidgetPermission() {
+        executeShellCommandIgnoreOutput(GRANT_BIND_APP_WIDGET_PERMISSION_COMMAND);
+    }
+
+    private void revokeBindAppWidgetPermission() {
+        executeShellCommandIgnoreOutput(REVOKE_BIND_APP_WIDGET_PERMISSION_COMMAND);
+    }
+
+    private void executeShellCommandIgnoreOutput(String command) {
+        ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation()
+                .executeShellCommand(command);
+        try {
+            Streams.readFully(new FileInputStream(pfd.getFileDescriptor()));
+        } catch (IOException ioe) {
+            IoUtils.closeQuietly(pfd);
+        }
+    }
+
+    private AppWidgetProviderInfo getFirstAppWidgetProviderInfo() {
+        ComponentName firstComponentName = new ComponentName(
+                getInstrumentation().getTargetContext().getPackageName(),
+                FirstAppWidgetProvider.class.getName());
+
+        return getProviderInfo(firstComponentName);
+    }
+
+    private AppWidgetProviderInfo getSecondAppWidgetProviderInfo() {
+        ComponentName secondComponentName = new ComponentName(
+                getInstrumentation().getTargetContext().getPackageName(),
+                SecondAppWidgetProvider.class.getName());
+
+        return getProviderInfo(secondComponentName);
+    }
+
+    private AppWidgetProviderInfo getProviderInfo(ComponentName componentName) {
+        List<AppWidgetProviderInfo> providers = getAppWidgetManager().getInstalledProviders();
+
+        final int providerCount = providers.size();
+        for (int i = 0; i < providerCount; i++) {
+            AppWidgetProviderInfo provider = providers.get(i);
+            if (componentName.equals(provider.provider)
+                    && Process.myUserHandle().equals(provider.getProfile())) {
+                return provider;
+
+            }
+        }
+
+        return null;
+    }
+
+    private int getNormalizedDimensionResource(int resId) {
+        return getInstrumentation().getTargetContext().getResources()
+                .getDimensionPixelSize(resId);
+    }
+
+    private int getIntResource(int resId) {
+        return getInstrumentation().getTargetContext().getResources().getInteger(resId);
+    }
+
+    private AppWidgetManager getAppWidgetManager() {
+        return (AppWidgetManager) getInstrumentation().getTargetContext()
+                .getSystemService(Context.APPWIDGET_SERVICE);
+    }
+
+    private AppWidgetProviderCallbacks createAppWidgetProviderCallbacks(
+            final AtomicInteger callCounter) {
+        // Set a mock to intercept provider callbacks.
+        AppWidgetProviderCallbacks callbacks = mock(AppWidgetProviderCallbacks.class);
+
+        // onEnabled
+        doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                synchronized (mLock) {
+                    callCounter.incrementAndGet();
+                    mLock.notifyAll();
+                }
+                return null;
+            }
+        }).when(callbacks).onEnabled(any(Context.class));
+
+        // onUpdate
+        doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                synchronized (mLock) {
+                    callCounter.incrementAndGet();
+                    mLock.notifyAll();
+                }
+                return null;
+            }
+        }).when(callbacks).onUpdate(any(Context.class), any(AppWidgetManager.class),
+                any(int[].class));
+
+        // onAppWidgetOptionsChanged
+        doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                synchronized (mLock) {
+                    callCounter.incrementAndGet();
+                    mLock.notifyAll();
+                }
+                return null;
+            }
+        }).when(callbacks).onAppWidgetOptionsChanged(any(Context.class),
+                any(AppWidgetManager.class), any(int.class), any(Bundle.class));
+
+        // onDeleted
+        doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                synchronized (mLock) {
+                    callCounter.incrementAndGet();
+                    mLock.notifyAll();
+                }
+                return null;
+            }
+        }).when(callbacks).onDeleted(any(Context.class), any(int[].class));
+
+        // onDisabled
+        doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                synchronized (mLock) {
+                    callCounter.incrementAndGet();
+                    mLock.notifyAll();
+                }
+                return null;
+            }
+        }).when(callbacks).onDisabled(any(Context.class));
+
+        // onRestored
+        doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                synchronized (mLock) {
+                    callCounter.incrementAndGet();
+                    mLock.notifyAll();
+                }
+                return null;
+            }
+        }).when(callbacks).onRestored(any(Context.class), any(int[].class),
+                any(int[].class));
+
+        return callbacks;
+    }
+
+    private static boolean equalOptions(Bundle first, Bundle second) {
+        return first.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH)
+                       == second.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH)
+                && first.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT)
+                       == second.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT)
+                && first.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH)
+                       == second.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH)
+                && first.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT)
+                       == second.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT);
+    }
+
+    private static final class OptionsMatcher extends BaseMatcher<Bundle> {
+        private Bundle mOptions;
+
+        public OptionsMatcher(Bundle options) {
+            mOptions = options;
+        }
+
+        @Override
+        public boolean matches(Object item) {
+            Bundle options = (Bundle) item;
+            return equalOptions(mOptions, options);
+        }
+
+        @Override
+        public void describeTo(Description description) {
+            /* do nothing */
+        }
+    }
+
+    private static final class WidgetIdsMatcher extends BaseMatcher<int[]> {
+        private final int[] mWidgetIds;
+
+        public WidgetIdsMatcher(int[] widgetIds) {
+            mWidgetIds = widgetIds;
+        }
+
+        @Override
+        public boolean matches(Object item) {
+            final int[] widgetIds = (int[]) item;
+            return Arrays.equals(widgetIds, mWidgetIds);
+        }
+
+        @Override
+        public void describeTo(Description description) {
+            /* do nothing */
+        }
+    }
+
+    private static final class RemoteViewsMatcher extends BaseMatcher<RemoteViews> {
+        private final int mLayoutId;
+        private final String mPackageName;
+
+        public RemoteViewsMatcher(int layoutId, String packageName) {
+            mLayoutId = layoutId;
+            mPackageName = packageName;
+        }
+
+        @Override
+        public boolean matches(Object item) {
+            final RemoteViews remoteViews = (RemoteViews) item;
+            return remoteViews != null && remoteViews.getLayoutId() == mLayoutId
+                    && remoteViews.getPackage().equals(mPackageName);
+        }
+
+        @Override
+        public void describeTo(Description description) {
+            /* do nothing */
+        }
+    }
+
+    private static class MyAppWidgetHostView extends AppWidgetHostView {
+        private OnUpdateAppWidgetListener mOnUpdateAppWidgetListener;
+
+
+        public interface OnUpdateAppWidgetListener {
+            public void onUpdateAppWidget(RemoteViews remoteViews);
+        }
+
+        private MyAppWidgetHostView(Context context) {
+            super(context);
+        }
+
+        public void setOnUpdateAppWidgetListener(OnUpdateAppWidgetListener listener) {
+            mOnUpdateAppWidgetListener = listener;
+        }
+
+        @Override
+        public void updateAppWidget(RemoteViews remoteViews) {
+            super.updateAppWidget(remoteViews);
+            if (mOnUpdateAppWidgetListener != null) {
+                mOnUpdateAppWidgetListener.onUpdateAppWidget(remoteViews);
+            }
+        }
+    }
+}
diff --git a/tests/tests/appwidget/src/android/appwidget/cts/provider/AppWidgetProviderCallbacks.java b/tests/tests/appwidget/src/android/appwidget/cts/provider/AppWidgetProviderCallbacks.java
new file mode 100644
index 0000000..0657a42
--- /dev/null
+++ b/tests/tests/appwidget/src/android/appwidget/cts/provider/AppWidgetProviderCallbacks.java
@@ -0,0 +1,49 @@
+/*
+ * 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.appwidget.cts.provider;
+
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProvider;
+import android.content.Context;
+import android.os.Bundle;
+
+public abstract class AppWidgetProviderCallbacks {
+
+    private AppWidgetProvider mProvider;
+
+    public final AppWidgetProvider getProvider() {
+        return mProvider;
+    }
+
+    public final void setProvider(AppWidgetProvider provider) {
+        mProvider = provider;
+    }
+
+    public abstract void onUpdate(Context context, AppWidgetManager appWidgetManager,
+             int[] appWidgetIds);
+
+    public abstract void onAppWidgetOptionsChanged(Context context,
+            AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions);
+
+    public abstract void onDeleted(Context context, int[] appWidgetIds);
+
+    public abstract void onEnabled(Context context);
+
+    public abstract void onDisabled(Context context);
+
+    public abstract void onRestored(Context context, int[] oldWidgetIds, int[] newWidgetIds);
+}
diff --git a/tests/tests/appwidget/src/android/appwidget/cts/provider/FirstAppWidgetProvider.java b/tests/tests/appwidget/src/android/appwidget/cts/provider/FirstAppWidgetProvider.java
new file mode 100644
index 0000000..7396ca2
--- /dev/null
+++ b/tests/tests/appwidget/src/android/appwidget/cts/provider/FirstAppWidgetProvider.java
@@ -0,0 +1,39 @@
+/*
+ * 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.appwidget.cts.provider;
+
+public final class FirstAppWidgetProvider extends StubbableAppWidgetProvider {
+    private static final Object sLock = new Object();
+
+    private static AppWidgetProviderCallbacks sCallbacks;
+
+    public static void setCallbacks(AppWidgetProviderCallbacks callbacks) {
+        synchronized (sLock) {
+            sCallbacks = callbacks;
+        }
+    }
+
+    @Override
+    protected AppWidgetProviderCallbacks getCallbacks() {
+        synchronized (sLock) {
+            if (sCallbacks != null) {
+                sCallbacks.setProvider(this);
+            }
+            return sCallbacks;
+        }
+    }
+}
diff --git a/tests/tests/appwidget/src/android/appwidget/cts/provider/SecondAppWidgetProvider.java b/tests/tests/appwidget/src/android/appwidget/cts/provider/SecondAppWidgetProvider.java
new file mode 100644
index 0000000..223f8f0
--- /dev/null
+++ b/tests/tests/appwidget/src/android/appwidget/cts/provider/SecondAppWidgetProvider.java
@@ -0,0 +1,39 @@
+/*
+ * 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.appwidget.cts.provider;
+
+public final class SecondAppWidgetProvider extends StubbableAppWidgetProvider {
+    private static final Object sLock = new Object();
+
+    private static AppWidgetProviderCallbacks sCallbacks;
+
+    public static void setCallbacks(AppWidgetProviderCallbacks callbacks) {
+        synchronized (sLock) {
+            sCallbacks = callbacks;
+        }
+    }
+
+    @Override
+    protected AppWidgetProviderCallbacks getCallbacks() {
+        synchronized (sLock) {
+            if (sCallbacks != null) {
+                sCallbacks.setProvider(this);
+            }
+            return sCallbacks;
+        }
+    }
+}
diff --git a/tests/tests/appwidget/src/android/appwidget/cts/provider/StubbableAppWidgetProvider.java b/tests/tests/appwidget/src/android/appwidget/cts/provider/StubbableAppWidgetProvider.java
new file mode 100644
index 0000000..9023902
--- /dev/null
+++ b/tests/tests/appwidget/src/android/appwidget/cts/provider/StubbableAppWidgetProvider.java
@@ -0,0 +1,75 @@
+/*
+ * 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.appwidget.cts.provider;
+
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProvider;
+import android.content.Context;
+import android.os.Bundle;
+
+public abstract class StubbableAppWidgetProvider extends AppWidgetProvider {
+    @Override
+    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
+        AppWidgetProviderCallbacks callbacks = getCallbacks();
+        if (callbacks != null) {
+            callbacks.onUpdate(context, appWidgetManager, appWidgetIds);
+        }
+    }
+
+    @Override
+    public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager,
+            int appWidgetId, Bundle newOptions) {
+        AppWidgetProviderCallbacks callbacks = getCallbacks();
+        if (callbacks != null) {
+            callbacks.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
+        }
+    }
+
+    @Override
+    public void onDeleted(Context context, int[] appWidgetIds) {
+        AppWidgetProviderCallbacks callbacks = getCallbacks();
+        if (callbacks != null) {
+            callbacks.onDeleted(context, appWidgetIds);
+        }
+    }
+
+    @Override
+    public void onEnabled(Context context) {
+        AppWidgetProviderCallbacks callbacks = getCallbacks();
+        if (callbacks != null) {
+            callbacks.onEnabled(context);
+        }
+    }
+
+    @Override
+    public void onDisabled(Context context) {
+        AppWidgetProviderCallbacks callbacks = getCallbacks();
+        if (callbacks != null) {
+            callbacks.onDisabled(context);
+        }
+    }
+
+    @Override
+    public void onRestored(Context context, int[] oldWidgetIds, int[] newWidgetIds) {
+        AppWidgetProviderCallbacks callbacks = getCallbacks();
+        if (callbacks != null) {
+            super.onRestored(context, oldWidgetIds, newWidgetIds);
+        }
+    }
+
+    protected abstract AppWidgetProviderCallbacks getCallbacks();
+}
diff --git a/tests/tests/appwidget/src/android/appwidget/cts/service/MyAppWidgetService.java b/tests/tests/appwidget/src/android/appwidget/cts/service/MyAppWidgetService.java
new file mode 100644
index 0000000..313855b
--- /dev/null
+++ b/tests/tests/appwidget/src/android/appwidget/cts/service/MyAppWidgetService.java
@@ -0,0 +1,39 @@
+/*
+ * 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.appwidget.cts.service;
+
+import android.content.Intent;
+import android.widget.RemoteViewsService;
+
+public class MyAppWidgetService extends RemoteViewsService {
+    private static final Object sLock = new Object();
+
+    private static RemoteViewsFactory sFactory;
+
+    public static void setFactory(RemoteViewsFactory factory) {
+        synchronized (sLock) {
+            sFactory = factory;
+        }
+    }
+
+    @Override
+    public RemoteViewsFactory onGetViewFactory(Intent intent) {
+        synchronized (sLock) {
+            return sFactory;
+        }
+    }
+}
diff --git a/tests/tests/bionic/Android.mk b/tests/tests/bionic/Android.mk
index 326fd56..e1afd50 100644
--- a/tests/tests/bionic/Android.mk
+++ b/tests/tests/bionic/Android.mk
@@ -1,12 +1,16 @@
 LOCAL_PATH := $(call my-dir)
 
 test_executable := bionic-unit-tests-cts
+list_executable := $(test_executable)_list
 
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := $(test_executable)
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativetest
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
 
 LOCAL_ADDITION_DEPENDENCIES := \
     $(LOCAL_PATH)/Android.mk \
@@ -24,3 +28,29 @@
 
 LOCAL_CTS_TEST_PACKAGE := android.bionic
 include $(BUILD_CTS_EXECUTABLE)
+
+ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x86_64))
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := $(list_executable)
+LOCAL_MULTILIB := both
+# Use the 32 bit list executable since it will include some 32 bit only tests.
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
+
+LOCAL_ADDITION_DEPENDENCIES := \
+    $(LOCAL_PATH)/Android.mk \
+
+# A main without the extra output from the gtest main.
+LOCAL_SRC_FILES := \
+    main.cpp \
+
+LOCAL_LDLIBS += \
+    -lrt \
+
+LOCAL_WHOLE_STATIC_LIBRARIES += \
+    libBionicTests \
+
+include $(BUILD_HOST_NATIVE_TEST)
+endif  # ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x86_64))
diff --git a/tests/tests/bionic/bionic-unit-tests-cts_list.txt b/tests/tests/bionic/bionic-unit-tests-cts_list.txt
deleted file mode 100644
index 370bb9e..0000000
--- a/tests/tests/bionic/bionic-unit-tests-cts_list.txt
+++ /dev/null
@@ -1,576 +0,0 @@
-Fortify1_Gcc_DeathTest.
-  strcpy_fortified
-  strcpy2_fortified
-  strcpy3_fortified
-  strcpy4_fortified
-  strlen_fortified
-  strchr_fortified
-  strrchr_fortified
-  strlcpy_fortified
-  strlcat_fortified
-  sprintf_fortified
-  sprintf2_fortified
-  vsprintf_fortified
-  vsprintf2_fortified
-  vsnprintf_fortified
-  vsnprintf2_fortified
-  strncat_fortified
-  strncat2_fortified
-  strcat_fortified
-  memmove_fortified
-  memcpy_fortified
-  strncpy_fortified
-  snprintf_fortified
-  bzero_fortified
-  umask_fortified
-Fortify2_Gcc_DeathTest.
-  strncpy_fortified2
-  sprintf_fortified2
-  sprintf2_fortified2
-  vsprintf_fortified2
-  vsprintf2_fortified2
-  vsnprintf_fortified2
-  vsnprintf2_fortified2
-  strcpy_fortified2
-  strcpy2_fortified2
-  strcpy3_fortified2
-  strchr_fortified2
-  strrchr_fortified2
-  strlcpy_fortified2
-  strlcat_fortified2
-  strncat_fortified2
-  strncat2_fortified2
-  strncat3_fortified2
-  strcat_fortified2
-  strcat2_fortified2
-  snprintf_fortified2
-  bzero_fortified2
-  strcpy_fortified
-  strcpy2_fortified
-  strcpy3_fortified
-  strcpy4_fortified
-  strlen_fortified
-  strchr_fortified
-  strrchr_fortified
-  strlcpy_fortified
-  strlcat_fortified
-  sprintf_fortified
-  sprintf2_fortified
-  vsprintf_fortified
-  vsprintf2_fortified
-  vsnprintf_fortified
-  vsnprintf2_fortified
-  strncat_fortified
-  strncat2_fortified
-  strcat_fortified
-  memmove_fortified
-  memcpy_fortified
-  strncpy_fortified
-  snprintf_fortified
-  bzero_fortified
-  umask_fortified
-Fortify1_Clang_DeathTest.
-  strcpy_fortified
-  strcpy2_fortified
-  strcpy3_fortified
-  strcpy4_fortified
-  strlen_fortified
-  strchr_fortified
-  strrchr_fortified
-  strlcpy_fortified
-  strlcat_fortified
-  sprintf_fortified
-  sprintf2_fortified
-  vsprintf_fortified
-  vsprintf2_fortified
-  vsnprintf_fortified
-  vsnprintf2_fortified
-  strncat_fortified
-  strncat2_fortified
-  strcat_fortified
-  memmove_fortified
-  memcpy_fortified
-  strncpy_fortified
-  snprintf_fortified
-  bzero_fortified
-  umask_fortified
-Fortify2_Clang_DeathTest.
-  strncat3_fortified2
-  strcat2_fortified2
-  snprintf_fortified2
-  bzero_fortified2
-  strcpy_fortified
-  strcpy2_fortified
-  strcpy3_fortified
-  strcpy4_fortified
-  strlen_fortified
-  strchr_fortified
-  strrchr_fortified
-  strlcpy_fortified
-  strlcat_fortified
-  sprintf_fortified
-  sprintf2_fortified
-  vsprintf_fortified
-  vsprintf2_fortified
-  vsnprintf_fortified
-  vsnprintf2_fortified
-  strncat_fortified
-  strncat2_fortified
-  strcat_fortified
-  memmove_fortified
-  memcpy_fortified
-  strncpy_fortified
-  snprintf_fortified
-  bzero_fortified
-  umask_fortified
-pthread_DeathTest.
-  pthread_bug_37410
-stack_protector_DeathTest.
-  modify_stack_protector
-properties_DeathTest.
-  read_only
-Fortify1_Gcc.
-  strncat
-  strncat2
-  strncat3
-  strncat4
-  strncat5
-  strncat6
-  strcat
-  strcat2
-  strcat_chk_max_int_size
-  strcpy_chk_max_int_size
-  memcpy_chk_max_int_size
-Fortify2_Gcc.
-  strncat
-  strncat2
-  strncat3
-  strncat4
-  strncat5
-  strncat6
-  strcat
-  strcat2
-  strcat_chk_max_int_size
-  strcpy_chk_max_int_size
-  memcpy_chk_max_int_size
-Fortify1_Clang.
-  strncat
-  strncat2
-  strncat3
-  strncat4
-  strncat5
-  strncat6
-  strcat
-  strcat2
-  strcat_chk_max_int_size
-  strcpy_chk_max_int_size
-  memcpy_chk_max_int_size
-Fortify2_Clang.
-  strncat
-  strncat2
-  strncat3
-  strncat4
-  strncat5
-  strncat6
-  strcat
-  strcat2
-  strcat_chk_max_int_size
-  strcpy_chk_max_int_size
-  memcpy_chk_max_int_size
-dirent.
-  scandir
-  fdopendir_invalid
-  fdopendir
-  opendir_invalid
-  opendir
-  closedir_invalid
-  closedir
-  readdir
-  readdir_r
-  rewinddir
-eventfd.
-  smoke
-fenv.
-  fesetround_fegetround_FE_TONEAREST
-  fesetround_fegetround_FE_TOWARDZERO
-  fesetround_fegetround_FE_UPWARD
-  fesetround_fegetround_FE_DOWNWARD
-  feclearexcept_fetestexcept
-  FE_DFL_ENV_macro
-getauxval.
-  expected_values
-  unexpected_values
-getcwd.
-  auto_full
-  auto_reasonable
-  auto_too_small
-  auto_too_large
-  manual_too_small
-  manual_zero
-  manual_path_max
-inttypes.
-  misc
-libc_logging.
-  smoke
-  d_INT_MAX
-  d_INT_MIN
-  ld_LONG_MAX
-  ld_LONG_MIN
-  lld_LLONG_MAX
-  lld_LLONG_MIN
-libgen.
-  basename
-  dirname
-  basename_r
-  dirname_r
-malloc.
-  malloc_std
-  calloc_std
-  memalign_multiple
-  memalign_realloc
-  malloc_realloc_larger
-  malloc_realloc_smaller
-  malloc_multiple_realloc
-  calloc_realloc_larger
-  calloc_realloc_smaller
-  calloc_multiple_realloc
-math.
-  fpclassify
-  isinf
-  isnan
-  isnormal
-  __fpclassifyd
-  __fpclassifyf
-  __fpclassifyl
-  finitef
-  __isfinite
-  __isfinitef
-  __isfinitel
-  finite
-  __isinff
-  __isinfl
-  __isnanf
-  __isnanl
-  isnanf
-  __isnormal
-  __isnormalf
-  __isnormall
-  __signbit
-  __signbitf
-  __signbitl
-  acos
-  acosf
-  acosl
-  asin
-  asinf
-  asinl
-  atan
-  atanf
-  atanl
-  atan2
-  atan2f
-  atan2l
-  cos
-  cosf
-  cosl
-  sin
-  sinf
-  sinl
-  tan
-  tanf
-  tanl
-  acosh
-  acoshf
-  acoshl
-  asinh
-  asinhf
-  asinhl
-  atanh
-  atanhf
-  atanhl
-  cosh
-  coshf
-  coshl
-  sinh
-  sinhf
-  sinhl
-  tanh
-  tanhf
-  tanhl
-  log
-  logf
-  logl
-  log2
-  log2f
-  log2l
-  log10
-  log10f
-  log10l
-  cbrt
-  cbrtf
-  cbrtl
-  sqrt
-  sqrtf
-  sqrtl
-  exp
-  expf
-  expl
-  exp2
-  exp2f
-  exp2l
-  expm1
-  expm1f
-  expm1l
-  pow
-  powf
-  powl
-  ceil
-  ceilf
-  ceill
-  floor
-  floorf
-  floorl
-  fabs
-  fabsf
-  fabsl
-  ldexp
-  ldexpf
-  ldexpl
-  fmod
-  fmodf
-  fmodl
-  remainder
-  remainderf
-  remainderl
-  drem
-  dremf
-  fmax
-  fmaxf
-  fmaxl
-  fmin
-  fminf
-  fminl
-  fma
-  fmaf
-  fmal
-  hypot
-  hypotf
-  hypotl
-  erf
-  erff
-  erfl
-  erfc
-  erfcf
-  erfcl
-  lrint
-  rint
-  nearbyint
-  lround
-  llround
-  ilogb
-  ilogbf
-  ilogbl
-  logb
-  logbf
-  logbl
-  log1p
-  log1pf
-  log1pl
-  fdim
-  fdimf
-  fdiml
-  round
-  roundf
-  roundl
-  trunc
-  truncf
-  truncl
-  nextafter
-  nextafterf
-  nextafterl
-  copysign
-  copysignf
-  copysignl
-  significand
-  significandf
-  significandl
-  scalb
-  scalbf
-  scalbln
-  scalblnf
-  scalblnl
-  scalbn
-  scalbnf
-  scalbnl
-  gamma
-  gammaf
-  gamma_r
-  gammaf_r
-  lgamma
-  lgammaf
-  lgammal
-  lgamma_r
-  lgammaf_r
-  tgamma
-  tgammaf
-  tgammal
-  j0
-  j0f
-  j1
-  j1f
-  jn
-  jnf
-  y0
-  y0f
-  y1
-  y1f
-  yn
-  ynf
-  frexp
-  frexpf
-  frexpl
-  modf
-  modff
-  modfl
-  remquo
-  remquof
-  remquol
-  frexpf_public_bug_6697
-netdb.
-  getaddrinfo_NULL_hints
-  getnameinfo_salen
-pthread.
-  pthread_key_create
-  pthread_key_create_lots
-  pthread_create
-  pthread_create_EAGAIN
-  pthread_no_join_after_detach
-  pthread_no_op_detach_after_join
-  pthread_join_self
-  pthread_sigmask
-  __bionic_clone
-  pthread_setname_np__too_long
-  pthread_setname_np__self
-  pthread_setname_np__other
-  pthread_setname_np__no_such_thread
-  pthread_kill__0
-  pthread_kill__invalid_signal
-  pthread_kill__in_signal_handler
-  pthread_detach__no_such_thread
-  pthread_getcpuclockid__clock_gettime
-  pthread_getcpuclockid__no_such_thread
-  pthread_getschedparam__no_such_thread
-  pthread_setschedparam__no_such_thread
-  pthread_join__no_such_thread
-  pthread_kill__no_such_thread
-  pthread_join__multijoin
-  pthread_attr_setguardsize
-  pthread_attr_setstacksize
-regex.
-  smoke
-signal.
-  sigismember_invalid
-  sigaddset_invalid
-  sigdelset_invalid
-  sigemptyset_invalid
-  sigfillset_invalid
-  raise_invalid
-  raise_in_signal_handler
-  sigwait
-stack_protector.
-  global_guard
-statvfs.
-  statvfs
-  fstatvfs
-stdio.
-  tmpfile_fileno_fprintf_rewind_fgets
-  getdelim
-  getdelim_invalid
-  getline
-  getline_invalid
-  printf_ssize_t
-  popen
-  getc
-  putc
-stdlib.
-  drand48
-  lrand48_random_rand
-  mrand48
-  posix_memalign
-  realpath__NULL_filename
-  realpath__empty_filename
-  realpath__ENOENT
-  realpath
-  qsort
-string.
-  strerror
-  strerror_concurrent
-  strerror_r
-  strsignal
-  strsignal_concurrent
-  strcat
-  strcpy2
-  strcpy3
-  strcpy4
-  strcat2
-  strcat3
-  strncat2
-  strncat3
-  strncat4
-  strncat5
-  strchr_with_0
-  strchr
-  strcmp
-  strcpy
-  strlcat
-  strlcpy
-  strncat
-  strncmp
-  strncpy
-  strrchr
-  memchr
-  memrchr
-  memcmp
-  __memcmp16
-  wmemcmp
-  memcpy
-  memset
-  memmove
-  bcopy
-  bzero
-strings.
-  ffs
-getpwnam.
-  system_id_root
-  system_id_system
-  app_id_radio
-  app_id_nobody
-  app_id_all_a0
-  app_id_u1_a40000
-  app_id_u0_a0
-  app_id_u0_a1234
-  app_id_u0_a9999
-  app_id_u1_root
-  app_id_u1_radio
-  app_id_u1_a0
-  app_id_u1_i0
-sys_stat.
-  futimens
-  futimens_EBADF
-properties.
-  add
-  update
-  fill
-  foreach
-  find_nth
-  fill_hierarchical
-  errors
-  serial
-  wait
-time.
-  mktime_tz
-  gmtime
-  mktime_10310929
-unistd.
-  sysconf_SC_MONOTONIC_CLOCK
-  sbrk
diff --git a/tests/tests/bionic/main.cpp b/tests/tests/bionic/main.cpp
new file mode 100644
index 0000000..b661af4
--- /dev/null
+++ b/tests/tests/bionic/main.cpp
@@ -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.
+ */
+
+#include <gtest/gtest.h>
+
+int main(int argc, char **argv) {
+  // Do not use gtest_main to avoid the Running main() ... output.
+  testing::InitGoogleTest(&argc, argv);
+
+  return RUN_ALL_TESTS();
+}
diff --git a/tests/tests/bluetooth/Android.mk b/tests/tests/bluetooth/Android.mk
index 701730d..4f837fc 100644
--- a/tests/tests/bluetooth/Android.mk
+++ b/tests/tests/bluetooth/Android.mk
@@ -18,16 +18,12 @@
 
 LOCAL_PACKAGE_NAME := CtsBluetoothTestCases
 
-
 # Don't include this package in any target.
 LOCAL_MODULE_TAGS := optional
 
 # When built, explicitly put it in the data partition.
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-# All tests should include android.test.runner.
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/bluetooth/AndroidManifest.xml b/tests/tests/bluetooth/AndroidManifest.xml
index 9caa267..c9ad122 100644
--- a/tests/tests/bluetooth/AndroidManifest.xml
+++ b/tests/tests/bluetooth/AndroidManifest.xml
@@ -26,9 +26,12 @@
     </application>
 
     <!-- This is a self-instrumenting test package. -->
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.cts.bluetooth"
-                     android:label="CTS tests of bluetooth component"/>
+                     android:label="CTS tests of bluetooth component">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/tests/calendarcommon/Android.mk b/tests/tests/calendarcommon/Android.mk
index c825c32..fa4b6c5 100644
--- a/tests/tests/calendarcommon/Android.mk
+++ b/tests/tests/calendarcommon/Android.mk
@@ -25,9 +25,6 @@
 # When built, explicitly put it in the data partition.
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-# All tests should include android.test.runner.
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/calendarcommon/AndroidManifest.xml b/tests/tests/calendarcommon/AndroidManifest.xml
index dc95af5..17520a3 100644
--- a/tests/tests/calendarcommon/AndroidManifest.xml
+++ b/tests/tests/calendarcommon/AndroidManifest.xml
@@ -23,9 +23,12 @@
     </application>
 
     <!-- This is a self-instrumenting test package. -->
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.cts.calendarcommon2"
-                     android:label="CTS tests of calendarcommon"/>
+                     android:label="CTS tests of calendarcommon">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
     <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="15"></uses-sdk>
 
diff --git a/tests/tests/calendarcommon/src/android/calendarcommon2/cts/Calendarcommon2Test.java b/tests/tests/calendarcommon/src/android/calendarcommon2/cts/Calendarcommon2Test.java
index a17e3b8..24a04a5 100644
--- a/tests/tests/calendarcommon/src/android/calendarcommon2/cts/Calendarcommon2Test.java
+++ b/tests/tests/calendarcommon/src/android/calendarcommon2/cts/Calendarcommon2Test.java
@@ -16,7 +16,6 @@
 
 package android.calendarcommon2.cts;
 
-import android.test.InstrumentationCtsTestRunner;
 import android.test.InstrumentationTestCase;
 import android.test.suitebuilder.annotation.MediumTest;
 import com.android.calendarcommon2.RecurrenceSet;
diff --git a/tests/tests/content/Android.mk b/tests/tests/content/Android.mk
index 6f883b6..2c185d9 100644
--- a/tests/tests/content/Android.mk
+++ b/tests/tests/content/Android.mk
@@ -23,12 +23,15 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
+
+# Resource unit tests use a private locale and some densities
+LOCAL_AAPT_FLAGS = -c xx_YY -c cs -c small -c normal -c large -c xlarge \
+        -c 320dpi -c 240dpi -c 160dpi -c 32dpi \
+        -c kok,kok_IN,kok_419,kok_419_VARIANT,kok_Knda_419,kok_Knda_419_VARIANT,kok_VARIANT,kok_Knda,tgl,tgl_PH
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsContentTestCases
 
-LOCAL_INSTRUMENTATION_FOR := CtsTestStubs
-
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/content/AndroidManifest.xml b/tests/tests/content/AndroidManifest.xml
index 5af05eb..d54bc02 100644
--- a/tests/tests/content/AndroidManifest.xml
+++ b/tests/tests/content/AndroidManifest.xml
@@ -18,9 +18,53 @@
     package="com.android.cts.content">
 
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+    <!-- content sync tests -->
+    <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
+    <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
+    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
+    <uses-permission android:name="android.permission.USE_CREDENTIALS" />
+    <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
+    <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
+    <uses-permission android:name="android.permission.READ_SYNC_STATS" />
+    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+    <uses-permission android:name="android.permission.SET_WALLPAPER" />
+    <uses-permission android:name="android.permission.BROADCAST_STICKY" />
+    <uses-permission android:name="android.content.cts.permission.TEST_GRANTED" />
 
-    <application>
-        <activity android:name="android.app.cts.MockActivity">
+    <!-- Used for PackageManager test, don't delete this INTERNET permission -->
+    <uses-permission android:name="android.permission.INTERNET" />
+
+    <!-- Used for PackageManager test, don't delete this permission-tree -->
+    <permission-tree android:name="com.android.cts.content.permission.TEST_DYNAMIC"
+                    android:label="Test Tree"/>
+
+    <!-- Used for PackageManager test, don't delete this permission-group -->
+    <permission-group android:name="android.permission-group.COST_MONEY"/>
+    <!-- Used for PackageManager test, don't delete! -->
+    <uses-configuration/>
+    <uses-feature android:name="android.hardware.camera" />
+    <uses-feature android:glEsVersion="0x00020000" />
+    <feature-group/>
+    <feature-group>
+        <uses-feature android:glEsVersion="0x00030000" />
+        <uses-feature android:name="android.hardware.location" />
+    </feature-group>
+    <feature-group>
+        <uses-feature android:glEsVersion="0x00010001" />
+        <uses-feature android:name="android.hardware.camera" />
+    </feature-group>
+
+    <application android:label="Android TestCase"
+                android:icon="@drawable/size_48x48"
+                android:maxRecents="1"
+                android:multiArch="true"
+                android:name="android.content.cts.MockApplication"
+                android:supportsRtl="true">
+        <activity android:name="android.content.cts.MockActivity">
+            <meta-data android:name="android.app.alias"
+                android:resource="@xml/alias" />
+            <meta-data android:name="android.app.intent.filter"
+                android:resource="@xml/intentfilter" />
             <intent-filter>
                 <action android:name="com.android.cts.content.action.TEST_ACTION" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -28,8 +72,8 @@
             </intent-filter>
         </activity>
 
-        <activity-alias android:name="android.app.cts.MockActivity2"
-                android:targetActivity="android.app.cts.MockActivity">
+        <activity-alias android:name="android.content.cts.MockActivity2"
+                android:targetActivity="android.content.cts.MockActivity">
             <intent-filter>
                 <action android:name="com.android.cts.content.action.TEST_ACTION" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -37,10 +81,132 @@
         </activity-alias>
 
         <uses-library android:name="android.test.runner" />
+
+        <service android:name="android.content.cts.MockContextWrapperService" />
+        <activity android:name=".content.ContextWrapperCtsActivity"
+            android:label="ContextWrapperCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+            </intent-filter>
+        </activity>
+
+        <receiver android:name="android.content.cts.MockReceiverFirst">
+            <intent-filter android:priority="3">
+                <action android:name="android.content.cts.BroadcastReceiverTest.BROADCAST_TESTABORT" />
+            </intent-filter>
+        </receiver>
+        <receiver android:name="android.content.cts.MockReceiverAbort">
+            <intent-filter android:priority="2">
+                <action android:name="android.content.cts.BroadcastReceiverTest.BROADCAST_TESTABORT" />
+            </intent-filter>
+        </receiver>
+        <receiver android:name="android.content.cts.MockReceiver">
+            <intent-filter android:priority="1">
+                <action android:name="android.content.cts.BroadcastReceiverTest.BROADCAST_MOCKTEST" />
+                <action android:name="android.content.cts.BroadcastReceiverTest.BROADCAST_TESTABORT" />
+                <action android:name="android.content.cts.ContextWrapperTest.BROADCAST_TESTORDER" />
+            </intent-filter>
+        </receiver>
+
+        <activity android:name="android.content.cts.AvailableIntentsActivity"
+            android:label="AvailableIntentsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <!--Test for PackageManager-->
+        <activity android:name="android.content.pm.cts.TestPmActivity"
+                android:icon="@drawable/start">
+            <intent-filter>
+                <action android:name="android.intent.action.PMTEST" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+            <meta-data android:name="android.content.pm.cts.xmltest" android:resource="@xml/pm_test" />
+        </activity>
+        <activity android:name="android.content.pm.cts.TestPmCompare">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.INFO" />
+            </intent-filter>
+        </activity>
+        <!--Test for PackageManager-->
+        <service android:name="android.content.pm.cts.TestPmService">
+            <intent-filter>
+                <action android:name="android.content.pm.cts.activity.PMTEST_SERVICE" />
+            </intent-filter>
+        </service>
+        <!--Test for PackageManager-->
+        <receiver android:name="android.content.pm.cts.PmTestReceiver">
+            <intent-filter>
+                <action android:name="android.content.pm.cts.PackageManagerTest.PMTEST_RECEIVER" />
+            </intent-filter>
+        </receiver>
+
+        <!-- Used for PackageManager test, don't delete this MockContentProvider provider -->
+        <provider android:name="android.content.cts.MockContentProvider" android:authorities="ctstest"
+            android:multiprocess="false" />
+        <provider android:name="android.content.cts.DummyProvider"
+            android:authorities="android.content.cts.dummyprovider"
+            android:multiprocess="true" />
+        <provider android:name="android.content.cts.MockRemoteContentProvider"
+            android:authorities="remotectstest"
+            android:process=":remoteprovider" android:multiprocess="false" />
+
+        <service android:name="android.content.cts.MockService" />
+
+        <service android:name="android.content.cts.MockSyncAdapterService" android:exported="true">
+            <intent-filter>
+                <action android:name="android.content.SyncAdapter" />
+            </intent-filter>
+
+            <meta-data android:name="android.content.SyncAdapter"
+                       android:resource="@xml/syncadapter" />
+        </service>
+
+        <service android:name="android.content.cts.MockAccountService" android:exported="true"
+                 >
+            <intent-filter>
+                <action android:name="android.accounts.AccountAuthenticator" />
+            </intent-filter>
+
+            <meta-data android:name="android.accounts.AccountAuthenticator"
+                       android:resource="@xml/authenticator" />
+        </service>
+
+        <activity android:name="android.content.cts.ClipboardManagerListenerActivity"/>
+
+        <activity android:name="com.android.cts.content.ImageCaptureActivity"
+                  android:exported="true">
+            <intent-filter>
+                <action android:name="android.media.action.IMAGE_CAPTURE" />
+                <action android:name="android.media.action.IMAGE_CAPTURE_SECURE" />
+                <action android:name="android.media.action.VIDEO_CAPTURE" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="com.android.cts.content.ReadableFileReceiverActivity"
+                  android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.SEND" />
+                <action android:name="android.intent.action.SEND_MULTIPLE" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="com.android.cts.stub"
-                     android:label="CTS tests of android.content"/>
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.content"
+                     android:label="CTS tests of android.content">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
+
+    <instrumentation android:name="android.content.pm.cts.TestPmInstrumentation"
+        android:targetPackage="android"
+        android:label="PackageManager Instrumentation Test" />
 </manifest>
 
diff --git a/tests/assets/text.txt b/tests/tests/content/assets/text.txt
similarity index 100%
rename from tests/assets/text.txt
rename to tests/tests/content/assets/text.txt
diff --git a/tests/res/anim/anim_rotate.xml b/tests/tests/content/res/anim/anim_rotate.xml
similarity index 100%
copy from tests/res/anim/anim_rotate.xml
copy to tests/tests/content/res/anim/anim_rotate.xml
diff --git a/tests/res/color/color1.xml b/tests/tests/content/res/color/color1.xml
similarity index 100%
rename from tests/res/color/color1.xml
rename to tests/tests/content/res/color/color1.xml
diff --git a/tests/res/drawable/ic_cts_minitab_selected.png b/tests/tests/content/res/drawable/ic_cts_minitab_selected.png
similarity index 100%
rename from tests/res/drawable/ic_cts_minitab_selected.png
rename to tests/tests/content/res/drawable/ic_cts_minitab_selected.png
Binary files differ
diff --git a/tests/res/drawable/ic_cts_selected.png b/tests/tests/content/res/drawable/ic_cts_selected.png
similarity index 100%
rename from tests/res/drawable/ic_cts_selected.png
rename to tests/tests/content/res/drawable/ic_cts_selected.png
Binary files differ
diff --git a/tests/res/drawable/icon_black.jpg b/tests/tests/content/res/drawable/icon_black.jpg
similarity index 100%
copy from tests/res/drawable/icon_black.jpg
copy to tests/tests/content/res/drawable/icon_black.jpg
Binary files differ
diff --git a/tests/res/drawable/ninepatch_0.9.png b/tests/tests/content/res/drawable/ninepatch_0.9.png
similarity index 100%
copy from tests/res/drawable/ninepatch_0.9.png
copy to tests/tests/content/res/drawable/ninepatch_0.9.png
Binary files differ
diff --git a/tests/res/drawable/ninepatch_1.9.png b/tests/tests/content/res/drawable/ninepatch_1.9.png
similarity index 100%
copy from tests/res/drawable/ninepatch_1.9.png
copy to tests/tests/content/res/drawable/ninepatch_1.9.png
Binary files differ
diff --git a/tests/res/drawable/pass.jpg b/tests/tests/content/res/drawable/pass.jpg
similarity index 100%
copy from tests/res/drawable/pass.jpg
copy to tests/tests/content/res/drawable/pass.jpg
Binary files differ
diff --git a/tests/res/drawable/scenery.jpg b/tests/tests/content/res/drawable/scenery.jpg
similarity index 100%
copy from tests/res/drawable/scenery.jpg
copy to tests/tests/content/res/drawable/scenery.jpg
Binary files differ
diff --git a/tests/res/drawable/size_48x48.jpg b/tests/tests/content/res/drawable/size_48x48.jpg
similarity index 100%
copy from tests/res/drawable/size_48x48.jpg
copy to tests/tests/content/res/drawable/size_48x48.jpg
Binary files differ
diff --git a/tests/res/drawable/start.jpg b/tests/tests/content/res/drawable/start.jpg
similarity index 100%
copy from tests/res/drawable/start.jpg
copy to tests/tests/content/res/drawable/start.jpg
Binary files differ
diff --git a/tests/res/drawable/testcolor.xml b/tests/tests/content/res/drawable/testcolor.xml
similarity index 100%
rename from tests/res/drawable/testcolor.xml
rename to tests/tests/content/res/drawable/testcolor.xml
diff --git a/tests/res/drawable/testimage.jpg b/tests/tests/content/res/drawable/testimage.jpg
similarity index 100%
rename from tests/res/drawable/testimage.jpg
rename to tests/tests/content/res/drawable/testimage.jpg
Binary files differ
diff --git a/tests/res/layout/abslistview_layout.xml b/tests/tests/content/res/layout/abslistview_layout.xml
similarity index 100%
copy from tests/res/layout/abslistview_layout.xml
copy to tests/tests/content/res/layout/abslistview_layout.xml
diff --git a/tests/res/layout/available_intents_layout.xml b/tests/tests/content/res/layout/available_intents_layout.xml
similarity index 100%
rename from tests/res/layout/available_intents_layout.xml
rename to tests/tests/content/res/layout/available_intents_layout.xml
diff --git a/tests/res/layout/context_layout.xml b/tests/tests/content/res/layout/context_layout.xml
similarity index 100%
rename from tests/res/layout/context_layout.xml
rename to tests/tests/content/res/layout/context_layout.xml
diff --git a/tests/res/layout/local_sample.xml b/tests/tests/content/res/layout/local_sample.xml
similarity index 100%
rename from tests/res/layout/local_sample.xml
rename to tests/tests/content/res/layout/local_sample.xml
diff --git a/tests/res/raw/testimage.jpg b/tests/tests/content/res/raw/testimage.jpg
similarity index 100%
rename from tests/res/raw/testimage.jpg
rename to tests/tests/content/res/raw/testimage.jpg
Binary files differ
diff --git a/tests/res/raw/testmp3.mp3 b/tests/tests/content/res/raw/testmp3.mp3
similarity index 100%
rename from tests/res/raw/testmp3.mp3
rename to tests/tests/content/res/raw/testmp3.mp3
Binary files differ
diff --git a/tests/res/raw/text.txt b/tests/tests/content/res/raw/text.txt
similarity index 100%
rename from tests/res/raw/text.txt
rename to tests/tests/content/res/raw/text.txt
diff --git a/tests/res/values-12key-63x57/configVarying.xml b/tests/tests/content/res/values-12key-63x57/configVarying.xml
similarity index 100%
rename from tests/res/values-12key-63x57/configVarying.xml
rename to tests/tests/content/res/values-12key-63x57/configVarying.xml
diff --git a/tests/res/values-12key-dpad/configVarying.xml b/tests/tests/content/res/values-12key-dpad/configVarying.xml
similarity index 100%
rename from tests/res/values-12key-dpad/configVarying.xml
rename to tests/tests/content/res/values-12key-dpad/configVarying.xml
diff --git a/tests/res/values-12key/configVarying.xml b/tests/tests/content/res/values-12key/configVarying.xml
similarity index 100%
rename from tests/res/values-12key/configVarying.xml
rename to tests/tests/content/res/values-12key/configVarying.xml
diff --git a/tests/res/values-240dpi/configVarying.xml b/tests/tests/content/res/values-240dpi/configVarying.xml
similarity index 100%
rename from tests/res/values-240dpi/configVarying.xml
rename to tests/tests/content/res/values-240dpi/configVarying.xml
diff --git a/tests/res/values-32dpi-keysexposed/configVarying.xml b/tests/tests/content/res/values-32dpi-keysexposed/configVarying.xml
similarity index 100%
rename from tests/res/values-32dpi-keysexposed/configVarying.xml
rename to tests/tests/content/res/values-32dpi-keysexposed/configVarying.xml
diff --git a/tests/res/values-32dpi-stylus/configVarying.xml b/tests/tests/content/res/values-32dpi-stylus/configVarying.xml
similarity index 100%
rename from tests/res/values-32dpi-stylus/configVarying.xml
rename to tests/tests/content/res/values-32dpi-stylus/configVarying.xml
diff --git a/tests/res/values-32dpi/configVarying.xml b/tests/tests/content/res/values-32dpi/configVarying.xml
similarity index 100%
rename from tests/res/values-32dpi/configVarying.xml
rename to tests/tests/content/res/values-32dpi/configVarying.xml
diff --git a/tests/res/values-480x320/configVarying.xml b/tests/tests/content/res/values-480x320/configVarying.xml
similarity index 100%
rename from tests/res/values-480x320/configVarying.xml
rename to tests/tests/content/res/values-480x320/configVarying.xml
diff --git a/tests/res/values-640x400/configVarying.xml b/tests/tests/content/res/values-640x400/configVarying.xml
similarity index 100%
rename from tests/res/values-640x400/configVarying.xml
rename to tests/tests/content/res/values-640x400/configVarying.xml
diff --git a/tests/tests/content/res/values-b+kok+419+VARIANT/configVarying.xml b/tests/tests/content/res/values-b+kok+419+VARIANT/configVarying.xml
new file mode 100644
index 0000000..3560279
--- /dev/null
+++ b/tests/tests/content/res/values-b+kok+419+VARIANT/configVarying.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple kok 419 VARIANT</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag kok 419 VARIANT</item>
+    </bag>
+</resources>
diff --git a/tests/tests/content/res/values-b+kok+419/configVarying.xml b/tests/tests/content/res/values-b+kok+419/configVarying.xml
new file mode 100644
index 0000000..b6f37f9
--- /dev/null
+++ b/tests/tests/content/res/values-b+kok+419/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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>
+    <item type="configVarying" name="simple">simple kok 419</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag kok 419</item>
+    </bag>
+</resources>
diff --git a/tests/tests/content/res/values-b+kok+IN/configVarying.xml b/tests/tests/content/res/values-b+kok+IN/configVarying.xml
new file mode 100644
index 0000000..967ea47
--- /dev/null
+++ b/tests/tests/content/res/values-b+kok+IN/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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>
+    <item type="configVarying" name="simple">simple kok IN</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag kok IN</item>
+    </bag>
+</resources>
diff --git a/tests/tests/content/res/values-b+kok+Knda+419+VARIANT/configVarying.xml b/tests/tests/content/res/values-b+kok+Knda+419+VARIANT/configVarying.xml
new file mode 100644
index 0000000..2b2bcea
--- /dev/null
+++ b/tests/tests/content/res/values-b+kok+Knda+419+VARIANT/configVarying.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple kok Knda 419 VARIANT</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag kok Knda 419 VARIANT</item>
+    </bag>
+</resources>
diff --git a/tests/tests/content/res/values-b+kok+Knda+419/configVarying.xml b/tests/tests/content/res/values-b+kok+Knda+419/configVarying.xml
new file mode 100644
index 0000000..cbc53b9
--- /dev/null
+++ b/tests/tests/content/res/values-b+kok+Knda+419/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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>
+    <item type="configVarying" name="simple">simple kok Knda 419</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag kok Knda 419</item>
+    </bag>
+</resources>
diff --git a/tests/tests/content/res/values-b+kok+Knda/configVarying.xml b/tests/tests/content/res/values-b+kok+Knda/configVarying.xml
new file mode 100644
index 0000000..f735749
--- /dev/null
+++ b/tests/tests/content/res/values-b+kok+Knda/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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>
+    <item type="configVarying" name="simple">simple kok Knda</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag kok Knda</item>
+    </bag>
+</resources>
diff --git a/tests/tests/content/res/values-b+kok+VARIANT/configVarying.xml b/tests/tests/content/res/values-b+kok+VARIANT/configVarying.xml
new file mode 100644
index 0000000..6743b7f
--- /dev/null
+++ b/tests/tests/content/res/values-b+kok+VARIANT/configVarying.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple kok VARIANT</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag kok VARIANT</item>
+    </bag>
+</resources>
diff --git a/tests/tests/content/res/values-b+kok/configVarying.xml b/tests/tests/content/res/values-b+kok/configVarying.xml
new file mode 100644
index 0000000..e1bafa1
--- /dev/null
+++ b/tests/tests/content/res/values-b+kok/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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>
+    <item type="configVarying" name="simple">simple kok</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag kok</item>
+    </bag>
+</resources>
diff --git a/tests/tests/content/res/values-b+tgl+PH/configVarying.xml b/tests/tests/content/res/values-b+tgl+PH/configVarying.xml
new file mode 100644
index 0000000..e6b9e25
--- /dev/null
+++ b/tests/tests/content/res/values-b+tgl+PH/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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>
+    <item type="configVarying" name="simple">simple tgl PH</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag tgl PH</item>
+    </bag>
+</resources>
diff --git a/tests/tests/content/res/values-b+tgl/configVarying.xml b/tests/tests/content/res/values-b+tgl/configVarying.xml
new file mode 100644
index 0000000..ac7e051
--- /dev/null
+++ b/tests/tests/content/res/values-b+tgl/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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>
+    <item type="configVarying" name="simple">simple tgl</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag tgl</item>
+    </bag>
+</resources>
diff --git a/tests/res/values-cs/strings.xml b/tests/tests/content/res/values-cs/strings.xml
similarity index 100%
rename from tests/res/values-cs/strings.xml
rename to tests/tests/content/res/values-cs/strings.xml
diff --git a/tests/res/values-dpad-63x57/configVarying.xml b/tests/tests/content/res/values-dpad-63x57/configVarying.xml
similarity index 100%
rename from tests/res/values-dpad-63x57/configVarying.xml
rename to tests/tests/content/res/values-dpad-63x57/configVarying.xml
diff --git a/tests/res/values-dpad/configVarying.xml b/tests/tests/content/res/values-dpad/configVarying.xml
similarity index 100%
rename from tests/res/values-dpad/configVarying.xml
rename to tests/tests/content/res/values-dpad/configVarying.xml
diff --git a/tests/res/values-fr-rFR/configVarying.xml b/tests/tests/content/res/values-fr-rFR/configVarying.xml
similarity index 100%
rename from tests/res/values-fr-rFR/configVarying.xml
rename to tests/tests/content/res/values-fr-rFR/configVarying.xml
diff --git a/tests/res/values-fr/configVarying.xml b/tests/tests/content/res/values-fr/configVarying.xml
similarity index 100%
rename from tests/res/values-fr/configVarying.xml
rename to tests/tests/content/res/values-fr/configVarying.xml
diff --git a/tests/res/values-h550dp/configVarying.xml b/tests/tests/content/res/values-h550dp/configVarying.xml
similarity index 100%
rename from tests/res/values-h550dp/configVarying.xml
rename to tests/tests/content/res/values-h550dp/configVarying.xml
diff --git a/tests/res/values-h670dp/configVarying.xml b/tests/tests/content/res/values-h670dp/configVarying.xml
similarity index 100%
rename from tests/res/values-h670dp/configVarying.xml
rename to tests/tests/content/res/values-h670dp/configVarying.xml
diff --git a/tests/res/values-keysexposed-12key/configVarying.xml b/tests/tests/content/res/values-keysexposed-12key/configVarying.xml
similarity index 100%
rename from tests/res/values-keysexposed-12key/configVarying.xml
rename to tests/tests/content/res/values-keysexposed-12key/configVarying.xml
diff --git a/tests/res/values-keysexposed-dpad/configVarying.xml b/tests/tests/content/res/values-keysexposed-dpad/configVarying.xml
similarity index 100%
rename from tests/res/values-keysexposed-dpad/configVarying.xml
rename to tests/tests/content/res/values-keysexposed-dpad/configVarying.xml
diff --git a/tests/res/values-keysexposed/configVarying.xml b/tests/tests/content/res/values-keysexposed/configVarying.xml
similarity index 100%
rename from tests/res/values-keysexposed/configVarying.xml
rename to tests/tests/content/res/values-keysexposed/configVarying.xml
diff --git a/tests/res/values-land/configVarying.xml b/tests/tests/content/res/values-land/configVarying.xml
similarity index 100%
rename from tests/res/values-land/configVarying.xml
rename to tests/tests/content/res/values-land/configVarying.xml
diff --git a/tests/res/values-land/dimens.xml b/tests/tests/content/res/values-land/dimens.xml
similarity index 100%
rename from tests/res/values-land/dimens.xml
rename to tests/tests/content/res/values-land/dimens.xml
diff --git a/tests/res/values-large/configVarying.xml b/tests/tests/content/res/values-large/configVarying.xml
similarity index 100%
rename from tests/res/values-large/configVarying.xml
rename to tests/tests/content/res/values-large/configVarying.xml
diff --git a/tests/res/values-mcc110-xx/configVarying.xml b/tests/tests/content/res/values-mcc110-xx/configVarying.xml
similarity index 100%
rename from tests/res/values-mcc110-xx/configVarying.xml
rename to tests/tests/content/res/values-mcc110-xx/configVarying.xml
diff --git a/tests/res/values-mcc111-mnc222/configVarying.xml b/tests/tests/content/res/values-mcc111-mnc222/configVarying.xml
similarity index 100%
rename from tests/res/values-mcc111-mnc222/configVarying.xml
rename to tests/tests/content/res/values-mcc111-mnc222/configVarying.xml
diff --git a/tests/res/values-mcc111-xx-rYY/configVarying.xml b/tests/tests/content/res/values-mcc111-xx-rYY/configVarying.xml
similarity index 100%
rename from tests/res/values-mcc111-xx-rYY/configVarying.xml
rename to tests/tests/content/res/values-mcc111-xx-rYY/configVarying.xml
diff --git a/tests/res/values-mcc111-xx/configVarying.xml b/tests/tests/content/res/values-mcc111-xx/configVarying.xml
similarity index 100%
rename from tests/res/values-mcc111-xx/configVarying.xml
rename to tests/tests/content/res/values-mcc111-xx/configVarying.xml
diff --git a/tests/res/values-mcc111/configVarying.xml b/tests/tests/content/res/values-mcc111/configVarying.xml
similarity index 100%
rename from tests/res/values-mcc111/configVarying.xml
rename to tests/tests/content/res/values-mcc111/configVarying.xml
diff --git a/tests/res/values-mcc112/configVarying.xml b/tests/tests/content/res/values-mcc112/configVarying.xml
similarity index 100%
rename from tests/res/values-mcc112/configVarying.xml
rename to tests/tests/content/res/values-mcc112/configVarying.xml
diff --git a/tests/res/values-mnc220-xx/configVarying.xml b/tests/tests/content/res/values-mnc220-xx/configVarying.xml
similarity index 100%
rename from tests/res/values-mnc220-xx/configVarying.xml
rename to tests/tests/content/res/values-mnc220-xx/configVarying.xml
diff --git a/tests/res/values-mnc222-32dpi/configVarying.xml b/tests/tests/content/res/values-mnc222-32dpi/configVarying.xml
similarity index 100%
rename from tests/res/values-mnc222-32dpi/configVarying.xml
rename to tests/tests/content/res/values-mnc222-32dpi/configVarying.xml
diff --git a/tests/res/values-mnc222-square/configVarying.xml b/tests/tests/content/res/values-mnc222-square/configVarying.xml
similarity index 100%
rename from tests/res/values-mnc222-square/configVarying.xml
rename to tests/tests/content/res/values-mnc222-square/configVarying.xml
diff --git a/tests/res/values-mnc222-xx/configVarying.xml b/tests/tests/content/res/values-mnc222-xx/configVarying.xml
similarity index 100%
rename from tests/res/values-mnc222-xx/configVarying.xml
rename to tests/tests/content/res/values-mnc222-xx/configVarying.xml
diff --git a/tests/res/values-mnc222/configVarying.xml b/tests/tests/content/res/values-mnc222/configVarying.xml
similarity index 100%
rename from tests/res/values-mnc222/configVarying.xml
rename to tests/tests/content/res/values-mnc222/configVarying.xml
diff --git a/tests/res/values-mnc223/configVarying.xml b/tests/tests/content/res/values-mnc223/configVarying.xml
similarity index 100%
rename from tests/res/values-mnc223/configVarying.xml
rename to tests/tests/content/res/values-mnc223/configVarying.xml
diff --git a/tests/res/values-nokeys/configVarying.xml b/tests/tests/content/res/values-nokeys/configVarying.xml
similarity index 100%
rename from tests/res/values-nokeys/configVarying.xml
rename to tests/tests/content/res/values-nokeys/configVarying.xml
diff --git a/tests/res/values-nonav/configVarying.xml b/tests/tests/content/res/values-nonav/configVarying.xml
similarity index 100%
rename from tests/res/values-nonav/configVarying.xml
rename to tests/tests/content/res/values-nonav/configVarying.xml
diff --git a/tests/res/values-normal/configVarying.xml b/tests/tests/content/res/values-normal/configVarying.xml
similarity index 100%
rename from tests/res/values-normal/configVarying.xml
rename to tests/tests/content/res/values-normal/configVarying.xml
diff --git a/tests/res/values-notouch/configVarying.xml b/tests/tests/content/res/values-notouch/configVarying.xml
similarity index 100%
rename from tests/res/values-notouch/configVarying.xml
rename to tests/tests/content/res/values-notouch/configVarying.xml
diff --git a/tests/res/values-small/configVarying.xml b/tests/tests/content/res/values-small/configVarying.xml
similarity index 100%
rename from tests/res/values-small/configVarying.xml
rename to tests/tests/content/res/values-small/configVarying.xml
diff --git a/tests/res/values-square-32dpi/configVarying.xml b/tests/tests/content/res/values-square-32dpi/configVarying.xml
similarity index 100%
rename from tests/res/values-square-32dpi/configVarying.xml
rename to tests/tests/content/res/values-square-32dpi/configVarying.xml
diff --git a/tests/res/values-square-stylus/configVarying.xml b/tests/tests/content/res/values-square-stylus/configVarying.xml
similarity index 100%
rename from tests/res/values-square-stylus/configVarying.xml
rename to tests/tests/content/res/values-square-stylus/configVarying.xml
diff --git a/tests/res/values-square/configVarying.xml b/tests/tests/content/res/values-square/configVarying.xml
similarity index 100%
rename from tests/res/values-square/configVarying.xml
rename to tests/tests/content/res/values-square/configVarying.xml
diff --git a/tests/res/values-stylus-12key/configVarying.xml b/tests/tests/content/res/values-stylus-12key/configVarying.xml
similarity index 100%
rename from tests/res/values-stylus-12key/configVarying.xml
rename to tests/tests/content/res/values-stylus-12key/configVarying.xml
diff --git a/tests/res/values-stylus-keysexposed/configVarying.xml b/tests/tests/content/res/values-stylus-keysexposed/configVarying.xml
similarity index 100%
rename from tests/res/values-stylus-keysexposed/configVarying.xml
rename to tests/tests/content/res/values-stylus-keysexposed/configVarying.xml
diff --git a/tests/res/values-stylus/configVarying.xml b/tests/tests/content/res/values-stylus/configVarying.xml
similarity index 100%
rename from tests/res/values-stylus/configVarying.xml
rename to tests/tests/content/res/values-stylus/configVarying.xml
diff --git a/tests/res/values-sw590dp-hdpi/configVarying.xml b/tests/tests/content/res/values-sw590dp-hdpi/configVarying.xml
similarity index 100%
rename from tests/res/values-sw590dp-hdpi/configVarying.xml
rename to tests/tests/content/res/values-sw590dp-hdpi/configVarying.xml
diff --git a/tests/res/values-sw590dp-mdpi/configVarying.xml b/tests/tests/content/res/values-sw590dp-mdpi/configVarying.xml
similarity index 100%
rename from tests/res/values-sw590dp-mdpi/configVarying.xml
rename to tests/tests/content/res/values-sw590dp-mdpi/configVarying.xml
diff --git a/tests/res/values-sw590dp-xhdpi/configVarying.xml b/tests/tests/content/res/values-sw590dp-xhdpi/configVarying.xml
similarity index 100%
rename from tests/res/values-sw590dp-xhdpi/configVarying.xml
rename to tests/tests/content/res/values-sw590dp-xhdpi/configVarying.xml
diff --git a/tests/res/values-sw590dp/configVarying.xml b/tests/tests/content/res/values-sw590dp/configVarying.xml
similarity index 100%
rename from tests/res/values-sw590dp/configVarying.xml
rename to tests/tests/content/res/values-sw590dp/configVarying.xml
diff --git a/tests/res/values-sw591dp-hdpi/configVarying.xml b/tests/tests/content/res/values-sw591dp-hdpi/configVarying.xml
similarity index 100%
rename from tests/res/values-sw591dp-hdpi/configVarying.xml
rename to tests/tests/content/res/values-sw591dp-hdpi/configVarying.xml
diff --git a/tests/res/values-sw591dp/configVarying.xml b/tests/tests/content/res/values-sw591dp/configVarying.xml
similarity index 100%
rename from tests/res/values-sw591dp/configVarying.xml
rename to tests/tests/content/res/values-sw591dp/configVarying.xml
diff --git a/tests/res/values-sw600dp-land/configVarying.xml b/tests/tests/content/res/values-sw600dp-land/configVarying.xml
similarity index 100%
rename from tests/res/values-sw600dp-land/configVarying.xml
rename to tests/tests/content/res/values-sw600dp-land/configVarying.xml
diff --git a/tests/res/values-sw600dp-land/dimens.xml b/tests/tests/content/res/values-sw600dp-land/dimens.xml
similarity index 100%
rename from tests/res/values-sw600dp-land/dimens.xml
rename to tests/tests/content/res/values-sw600dp-land/dimens.xml
diff --git a/tests/res/values-sw600dp/configVarying.xml b/tests/tests/content/res/values-sw600dp/configVarying.xml
similarity index 100%
rename from tests/res/values-sw600dp/configVarying.xml
rename to tests/tests/content/res/values-sw600dp/configVarying.xml
diff --git a/tests/res/values-sw600dp/dimens.xml b/tests/tests/content/res/values-sw600dp/dimens.xml
similarity index 100%
rename from tests/res/values-sw600dp/dimens.xml
rename to tests/tests/content/res/values-sw600dp/dimens.xml
diff --git a/tests/res/values-sw720dp/configVarying.xml b/tests/tests/content/res/values-sw720dp/configVarying.xml
similarity index 100%
rename from tests/res/values-sw720dp/configVarying.xml
rename to tests/tests/content/res/values-sw720dp/configVarying.xml
diff --git a/tests/tests/content/res/values-tl-rPH/configVarying.xml b/tests/tests/content/res/values-tl-rPH/configVarying.xml
new file mode 100644
index 0000000..034d2ab
--- /dev/null
+++ b/tests/tests/content/res/values-tl-rPH/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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>
+    <item type="configVarying" name="simple">simple tl PH</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag tl PH</item>
+    </bag>
+</resources>
diff --git a/tests/tests/content/res/values-tl/configVarying.xml b/tests/tests/content/res/values-tl/configVarying.xml
new file mode 100644
index 0000000..4fc5012
--- /dev/null
+++ b/tests/tests/content/res/values-tl/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 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>
+    <item type="configVarying" name="simple">simple tl</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag tl</item>
+    </bag>
+</resources>
diff --git a/tests/res/values-v10/strings.xml b/tests/tests/content/res/values-v10/strings.xml
similarity index 100%
rename from tests/res/values-v10/strings.xml
rename to tests/tests/content/res/values-v10/strings.xml
diff --git a/tests/res/values-v11/strings.xml b/tests/tests/content/res/values-v11/strings.xml
similarity index 100%
rename from tests/res/values-v11/strings.xml
rename to tests/tests/content/res/values-v11/strings.xml
diff --git a/tests/res/values-v12/strings.xml b/tests/tests/content/res/values-v12/strings.xml
similarity index 100%
rename from tests/res/values-v12/strings.xml
rename to tests/tests/content/res/values-v12/strings.xml
diff --git a/tests/res/values-v13/strings.xml b/tests/tests/content/res/values-v13/strings.xml
similarity index 100%
rename from tests/res/values-v13/strings.xml
rename to tests/tests/content/res/values-v13/strings.xml
diff --git a/tests/res/values-v14/strings.xml b/tests/tests/content/res/values-v14/strings.xml
similarity index 100%
rename from tests/res/values-v14/strings.xml
rename to tests/tests/content/res/values-v14/strings.xml
diff --git a/tests/res/values-v15/strings.xml b/tests/tests/content/res/values-v15/strings.xml
similarity index 100%
rename from tests/res/values-v15/strings.xml
rename to tests/tests/content/res/values-v15/strings.xml
diff --git a/tests/res/values-v16/strings.xml b/tests/tests/content/res/values-v16/strings.xml
similarity index 100%
rename from tests/res/values-v16/strings.xml
rename to tests/tests/content/res/values-v16/strings.xml
diff --git a/tests/res/values-v17/strings.xml b/tests/tests/content/res/values-v17/strings.xml
similarity index 100%
rename from tests/res/values-v17/strings.xml
rename to tests/tests/content/res/values-v17/strings.xml
diff --git a/tests/res/values-v18/strings.xml b/tests/tests/content/res/values-v18/strings.xml
similarity index 100%
rename from tests/res/values-v18/strings.xml
rename to tests/tests/content/res/values-v18/strings.xml
diff --git a/tests/res/values-v19/strings.xml b/tests/tests/content/res/values-v19/strings.xml
similarity index 100%
rename from tests/res/values-v19/strings.xml
rename to tests/tests/content/res/values-v19/strings.xml
diff --git a/tests/res/values-v20/strings.xml b/tests/tests/content/res/values-v20/strings.xml
similarity index 100%
rename from tests/res/values-v20/strings.xml
rename to tests/tests/content/res/values-v20/strings.xml
diff --git a/tests/res/values-v21/strings.xml b/tests/tests/content/res/values-v21/strings.xml
similarity index 100%
rename from tests/res/values-v21/strings.xml
rename to tests/tests/content/res/values-v21/strings.xml
diff --git a/tests/res/values-v22/strings.xml b/tests/tests/content/res/values-v22/strings.xml
similarity index 100%
rename from tests/res/values-v22/strings.xml
rename to tests/tests/content/res/values-v22/strings.xml
diff --git a/tests/res/values-v3/strings.xml b/tests/tests/content/res/values-v3/strings.xml
similarity index 100%
rename from tests/res/values-v3/strings.xml
rename to tests/tests/content/res/values-v3/strings.xml
diff --git a/tests/res/values-v4/strings.xml b/tests/tests/content/res/values-v4/strings.xml
similarity index 100%
rename from tests/res/values-v4/strings.xml
rename to tests/tests/content/res/values-v4/strings.xml
diff --git a/tests/res/values-v5/strings.xml b/tests/tests/content/res/values-v5/strings.xml
similarity index 100%
rename from tests/res/values-v5/strings.xml
rename to tests/tests/content/res/values-v5/strings.xml
diff --git a/tests/res/values-v6/strings.xml b/tests/tests/content/res/values-v6/strings.xml
similarity index 100%
rename from tests/res/values-v6/strings.xml
rename to tests/tests/content/res/values-v6/strings.xml
diff --git a/tests/res/values-v7/strings.xml b/tests/tests/content/res/values-v7/strings.xml
similarity index 100%
rename from tests/res/values-v7/strings.xml
rename to tests/tests/content/res/values-v7/strings.xml
diff --git a/tests/res/values-v8/strings.xml b/tests/tests/content/res/values-v8/strings.xml
similarity index 100%
rename from tests/res/values-v8/strings.xml
rename to tests/tests/content/res/values-v8/strings.xml
diff --git a/tests/res/values-v9/strings.xml b/tests/tests/content/res/values-v9/strings.xml
similarity index 100%
rename from tests/res/values-v9/strings.xml
rename to tests/tests/content/res/values-v9/strings.xml
diff --git a/tests/res/values-w600dp-h550dp/configVarying.xml b/tests/tests/content/res/values-w600dp-h550dp/configVarying.xml
similarity index 100%
rename from tests/res/values-w600dp-h550dp/configVarying.xml
rename to tests/tests/content/res/values-w600dp-h550dp/configVarying.xml
diff --git a/tests/res/values-w600dp/configVarying.xml b/tests/tests/content/res/values-w600dp/configVarying.xml
similarity index 100%
rename from tests/res/values-w600dp/configVarying.xml
rename to tests/tests/content/res/values-w600dp/configVarying.xml
diff --git a/tests/res/values-w720dp-h670dp/configVarying.xml b/tests/tests/content/res/values-w720dp-h670dp/configVarying.xml
similarity index 100%
rename from tests/res/values-w720dp-h670dp/configVarying.xml
rename to tests/tests/content/res/values-w720dp-h670dp/configVarying.xml
diff --git a/tests/res/values-w720dp/configVarying.xml b/tests/tests/content/res/values-w720dp/configVarying.xml
similarity index 100%
rename from tests/res/values-w720dp/configVarying.xml
rename to tests/tests/content/res/values-w720dp/configVarying.xml
diff --git a/tests/res/values-wheel/configVarying.xml b/tests/tests/content/res/values-wheel/configVarying.xml
similarity index 100%
rename from tests/res/values-wheel/configVarying.xml
rename to tests/tests/content/res/values-wheel/configVarying.xml
diff --git a/tests/res/values-xlarge/configVarying.xml b/tests/tests/content/res/values-xlarge/configVarying.xml
similarity index 100%
rename from tests/res/values-xlarge/configVarying.xml
rename to tests/tests/content/res/values-xlarge/configVarying.xml
diff --git a/tests/res/values-xx-32dpi/configVarying.xml b/tests/tests/content/res/values-xx-32dpi/configVarying.xml
similarity index 100%
rename from tests/res/values-xx-32dpi/configVarying.xml
rename to tests/tests/content/res/values-xx-32dpi/configVarying.xml
diff --git a/tests/res/values-xx-rYY/configVarying.xml b/tests/tests/content/res/values-xx-rYY/configVarying.xml
similarity index 100%
rename from tests/res/values-xx-rYY/configVarying.xml
rename to tests/tests/content/res/values-xx-rYY/configVarying.xml
diff --git a/tests/res/values-xx-square/configVarying.xml b/tests/tests/content/res/values-xx-square/configVarying.xml
similarity index 100%
rename from tests/res/values-xx-square/configVarying.xml
rename to tests/tests/content/res/values-xx-square/configVarying.xml
diff --git a/tests/res/values-xx/configVarying.xml b/tests/tests/content/res/values-xx/configVarying.xml
similarity index 100%
rename from tests/res/values-xx/configVarying.xml
rename to tests/tests/content/res/values-xx/configVarying.xml
diff --git a/tests/res/values/arrays.xml b/tests/tests/content/res/values/arrays.xml
similarity index 100%
copy from tests/res/values/arrays.xml
copy to tests/tests/content/res/values/arrays.xml
diff --git a/tests/tests/content/res/values/attrs.xml b/tests/tests/content/res/values/attrs.xml
new file mode 100644
index 0000000..4c3d9db
--- /dev/null
+++ b/tests/tests/content/res/values/attrs.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2008 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>
+    <declare-styleable name="Style1">
+        <attr name="Type1" format="integer">
+            <enum name="type" value="28" />
+            <enum name="data" value="0xff00ff00" />
+            <enum name="asset_cookie" value="0" />
+            <enum name="resource_id" value="0" />
+            <enum name="changing_config" value="0" />
+        </attr>
+        <attr name="Type2" format="integer">
+            <enum name="type" value="28" />
+            <enum name="data" value="0xff0000ff" />
+            <enum name="asset_cookie" value="0" />
+            <enum name="resource_id" value="0" />
+            <enum name="changing_config" value="0" />
+        </attr>
+    </declare-styleable>
+    <attr name="type1" format="boolean"/>
+    <attr name="type2" format="boolean"/>
+    <attr name="type3" format="color"/>
+    <attr name="type4" format="reference|color"/>
+    <attr name="type5" format="dimension"/>
+    <attr name="type6" format="dimension"/>
+    <attr name="type7" format="dimension"/>
+    <attr name="type8" format="reference"/>
+    <attr name="type9" format="float"/>
+    <attr name="type10" format="fraction"/>
+    <attr name="type11" format="integer"/>
+    <attr name="type12" format="integer"/>
+    <attr name="type13" format="reference|string"/>
+    <attr name="type14" format="string"/>
+    <attr name="type15" format="reference"/>
+    <attr name="type16" format="string"/>
+    <declare-styleable name="style1">
+        <attr name="type1"/>
+        <attr name="type2"/>
+        <attr name="type3"/>
+        <attr name="type4"/>
+        <attr name="type5"/>
+        <attr name="type6"/>
+        <attr name="type7"/>
+        <attr name="type8"/>
+        <attr name="type9"/>
+        <attr name="type10"/>
+        <attr name="type11"/>
+        <attr name="type12"/>
+        <attr name="type13"/>
+        <attr name="type14"/>
+        <attr name="type15"/>
+        <attr name="type16"/>
+    </declare-styleable>
+    <attr name="testEnum">
+        <enum name="val1" value="1" />
+        <enum name="val2" value="2" />
+        <enum name="val10" value="10" />
+    </attr>
+    <attr name="testFlags">
+        <flag name="bit1" value="0x1" />
+        <flag name="bit2" value="0x2" />
+        <flag name="bit31" value="0x40000000" />
+    </attr>
+    <attr name="testString" format="string" />
+    <declare-styleable name="EnumStyle">
+        <attr name="testEnum" />
+    </declare-styleable>
+    <declare-styleable name="FlagStyle">
+        <attr name="testFlags" />
+    </declare-styleable>
+    <declare-styleable name="TestConfig">
+        <attr name="testString" />
+    </declare-styleable>
+    <!-- Size of text. Recommended dimension type for text is "sp" for scaled-pixels (example: 15sp).
+         Supported values include the following:<p/>
+    <ul>
+        <li><b>px</b> Pixels</li>
+        <li><b>sp</b> Scaled pixels (scaled to relative pixel size on screen). See {@link android.util.DisplayMetrics} for more information.</li>
+        <li><b>pt</b> Points</li>
+        <li><b>dip</b> Device independent pixels. See {@link android.util.DisplayMetrics} for more information.</li>
+    </ul>
+    -->
+    <attr name="textSize" format="dimension" />
+    <attr name="typeface">
+        <enum name="normal" value="0" />
+        <enum name="sans" value="1" />
+        <enum name="serif" value="2" />
+        <enum name="monospace" value="3" />
+    </attr>
+    <!-- Default text typeface style. -->
+    <attr name="textStyle">
+        <flag name="normal" value="0" />
+        <flag name="bold" value="1" />
+        <flag name="italic" value="2" />
+    </attr>
+    <!-- Color of text (usually same as colorForeground). -->
+    <attr name="textColor" format="reference|color" />
+    <!-- Color of highlighted text. -->
+    <attr name="textColorHighlight" format="reference|color" />
+    <!-- Color of hint text (displayed when the field is empty). -->
+    <attr name="textColorHint" format="reference|color" />
+    <!-- Color of link text (URLs). -->
+    <attr name="textColorLink" format="reference|color" />
+    <declare-styleable name="TextAppearance">
+        <attr name="textColor"/>
+        <attr name="textSize"/>
+        <attr name="textStyle"/>
+        <attr name="typeface"/>
+        <attr name="textColorHighlight"/>
+        <attr name="textColorHint"/>
+        <attr name="textColorLink"/>
+    </declare-styleable>
+    <!-- Integer used to uniquely identify theme overrides. -->
+    <attr name="themeType" format="integer"/>
+    <!-- Theme reference used to override parent theme. -->
+    <attr name="themeOverrideAttr" format="reference"/>
+
+    <!-- Drawable theming attributes -->
+    <attr name="themeBoolean" />
+    <attr name="themeColor" />
+    <attr name="themeFloat" />
+    <attr name="themeInteger" />
+    <attr name="themeDimension" />
+    <attr name="themeDrawable" />
+    <attr name="themeBitmap" />
+    <attr name="themeNinePatch" />
+    <attr name="themeGravity" />
+    <attr name="themeTileMode" />
+    <attr name="themeAngle" />
+</resources>
diff --git a/tests/res/values/bools.xml b/tests/tests/content/res/values/bools.xml
similarity index 100%
rename from tests/res/values/bools.xml
rename to tests/tests/content/res/values/bools.xml
diff --git a/tests/res/values/colors.xml b/tests/tests/content/res/values/colors.xml
similarity index 100%
copy from tests/res/values/colors.xml
copy to tests/tests/content/res/values/colors.xml
diff --git a/tests/res/values/configVarying.xml b/tests/tests/content/res/values/configVarying.xml
similarity index 100%
rename from tests/res/values/configVarying.xml
rename to tests/tests/content/res/values/configVarying.xml
diff --git a/tests/res/values/dimens.xml b/tests/tests/content/res/values/dimens.xml
similarity index 100%
rename from tests/res/values/dimens.xml
rename to tests/tests/content/res/values/dimens.xml
diff --git a/tests/res/values/resources_test.xml b/tests/tests/content/res/values/resources_test.xml
similarity index 100%
rename from tests/res/values/resources_test.xml
rename to tests/tests/content/res/values/resources_test.xml
diff --git a/tests/tests/content/res/values/strings.xml b/tests/tests/content/res/values/strings.xml
new file mode 100644
index 0000000..c167278
--- /dev/null
+++ b/tests/tests/content/res/values/strings.xml
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="permlab_testGranted">Test Granted</string>
+    <string name="permdesc_testGranted">Used for running CTS tests, for testing operations
+        where we have the permission.</string>
+    <string name="permlab_testDynamic">Test Dynamic</string>
+    <string name="permdesc_testDynamic">Used for running CTS tests, for testing adding
+        dynamic permissions.</string>
+    <string name="permlab_testDenied">Test Denied</string>
+    <string name="permdesc_testDenied">Used for running CTS tests, for testing operations
+        where we do not have the permission.</string>
+    <string name="explain">1. click start. \n2. if above image shaked, then press pass button,
+         else press failed button.</string>
+    <string name="text_view_hello">Hello! Text view!</string>
+    <string name="text_view_hello_two_lines">Hello! \nText view!</string>
+    <string name="text_view_simple_hint">This is a hint.</string>
+    <string name="text_view_hint">This is a string for testing hint of textview.</string>
+    <string name="activity_forwarding">App/Forwarding</string>
+    <string name="forwarding">$$$</string>
+    <string name="go">Go</string>
+    <string name="back">Back</string>
+    <string name="forward_target">
+        Press back button and notice we don\'t see the previous activity.
+    </string>
+    <string name="edit_text">testing</string>
+    <string name="text">DialogTest</string>
+    <string name="text_country">Country</string>
+    <string name="text_name">Name</string>
+    <string name="hello_world">Hello, World!</string>
+    <string name="hello_android">Hello, Android!</string>
+    <string name="alert_dialog_username">Name:</string>
+    <string name="alert_dialog_password">Password:</string>
+    <string name="alert_dialog_positive">Positive</string>
+    <string name="alert_dialog_negative">Negative</string>
+    <string name="alert_dialog_neutral">Neutral</string>
+    <string name="notify">Notify </string>
+    <string name="tabs_1">testing</string>
+    <string name="table_layout_first">first</string>
+    <string name="table_layout_second">second</string>
+    <string name="table_layout_third">third</string>
+    <string name="table_layout_long">Very long to make the string out of the screen</string>
+    <string name="chronometer_text">Test Chronometer</string>
+    <string name="am">AM</string>
+    <string name="pm">PM</string>
+    <string name="viewgroup_test">ViewGroup test</string>
+    <string name="viewanimator_test">ViewAnimator test</string>
+    <string name="id_ok">OK</string>
+    <string name="id_cancel">Cancel</string>
+    <string name="context_test_string1">This is %s string.</string>
+    <string name="context_test_string2">This is test string.</string>
+    <string name="animationutils_test_instructions">Choose different animations</string>
+    <string name="animationutils_test_alpha">Alpha animation</string>
+    <string name="animationutils_test_scale">Scale animation</string>
+    <string name="animationutils_test_rotate">Rotate animation</string>
+    <string name="animationutils_test_translate">Translate animation</string>
+    <string name="animationutils_test_set">Animation set</string>
+    <string name="animationutils_test_layout">Layout animation</string>
+    <string name="animationutils_test_gridlayout">Grid layout animation</string>
+    <string name="twolinelistitem_test_text1">text1</string>
+    <string name="twolinelistitem_test_text2">text2</string>
+    <string name="metadata_text">metadata text</string>
+    <string name="horizontal_text_1">horizontal 1</string>
+    <string name="horizontal_text_2">horizontal 2</string>
+    <string name="horizontal_text_3">horizontal 3</string>
+    <string name="vertical_text_1">vertical 1</string>
+    <string name="vertical_text_2">vertical 2</string>
+    <string name="vertical_text_3">vertical 3</string>
+    <string name="reference">here</string>
+    <string name="coerceIntegerToString">100</string>
+    <string name="coerceBooleanToString">true</string>
+    <string name="coerceColorToString">#fff</string>
+    <string name="coerceFloatToString">100.0</string>
+    <string name="coerceDimensionToString">100px</string>
+    <string name="coerceFractionToString">100<xliff:g id="percent">%</xliff:g></string>
+    <string name="formattedStringNone">Format[]</string>
+    <string name="formattedStringOne">Format[<xliff:g id="format">%d</xliff:g>]</string>
+    <string name="formattedStringTwo">Format[<xliff:g id="format">%3$d,%2$s</xliff:g>]</string>
+    <string name="checkboxpref_key">checkboxpref_key</string>
+   <string name="checkboxpref_title">title of preference</string>
+   <string name="checkboxpref_summary">summary of preference</string>
+   <string name="checkboxpref_summary_on">summary on of preference</string>
+   <string name="checkboxpref_summary_off">summary off of preference</string>
+   <string name="checkboxpref_depend">checkboxpref_depend</string>
+   <string name="checkboxpref_depend_title"> depend title of preference</string>
+   <string name="checkboxpref_depend_summary"> depend summary of preference</string>
+   <string name="edittextpref_key">edittextpref_key</string>
+   <string name="edittextpref_default_value">default value of preference</string>
+   <string name="edittextpref_title">title of edit text preference</string>
+   <string name="edittextpref_summary">summary of edit text preference</string>
+   <string name="edittextpref_dialog_title">dialog title of edit text preference</string>
+   <string name="edittextpref_text">text of  edit text preference</string>
+   <string name="listpref_key">listpref_key</string>
+   <string name="listpref_title">title of list preference</string>
+   <string name="listpref_summary">summary of list preference</string>
+   <string name="listpref_dialogtitle">dialog title of list preference</string>
+   <string name="easy">Easy</string>
+   <string name="medium">Medium</string>
+   <string name="hard">Hard</string>
+   <string name="footer_view">Footer view</string>
+   <string name="header_view">Header view</string>
+   <string name="dialogpref_title">title of dialog preference </string>
+   <string name="dialogpref_dialog_title">dialog title of dialog preference </string>
+   <string name="dialogpref_key">dialogpref_key</string>
+   <string name="dialogpref_default_value">default value of dialog preference</string>
+   <string name="dialogpref_summary">summary of dialog preference</string>
+   <string name="dialogpref_message">message of dialog preference</string>
+   <string name="dialogpref_sure">Sure</string>
+   <string name="dialogpref_cancel">Cancel</string>
+   <string name="pref_key">pref_key</string>
+   <string name="pref_title">title of preference</string>
+   <string name="pref_summary">summary of preference</string>
+   <string name="pref_depend_key">pref_depend_key</string>
+   <string name="pref_depend_title"> depend title of preference</string>
+   <string name="pref_depend_summary"> depend summary of preference</string>
+   <string name="android_intent_action_preference">android.intent.action.PREFERENCE</string>
+   <string name="def_pref_key">def_pref_key</string>
+   <string name="def_pref_title">default preference</string>
+   <string name="def_pref_summary">This is default preference of cts</string>
+   <string name="relative_view1">view 1</string>
+   <string name="relative_view2">view 2</string>
+   <string name="relative_view3">view 3</string>
+   <string name="relative_view4">view 4</string>
+   <string name="relative_view5">view 5</string>
+   <string name="relative_view6">view 6</string>
+   <string name="relative_view7">view 7</string>
+   <string name="relative_view8">view 8</string>
+   <string name="relative_view9">view 9</string>
+   <string name="relative_view10">view 10</string>
+   <string name="relative_view11">view 11</string>
+   <string name="relative_view12">view 12</string>
+   <string name="relative_view13">view 13</string>
+   <string name="country">Country:</string>
+   <string name="symbol">Symbol:</string>
+   <string name="country_warning">No such country registered</string>
+   <string name="version_cur">base</string>
+   <string name="version_old">base</string>
+   <string name="version_v3">base</string>
+   <string name="authenticator_label">Android CTS</string>
+   <string name="search_label">Android CTS</string>
+   <string name="tag1">tag 1</string>
+   <string name="tag2">tag 2</string>
+
+   <string name="button">Button</string>
+   <string name="holo_test">Holo Test</string>
+   <string name="holo_generator">Holo Generator</string>
+   <string name="holo_light_test">Holo Light Test</string>
+   <string name="holo_light_generator">Holo Light Generator</string>
+   <string name="reference_image">Reference Image: </string>
+   <string name="generated_image">Generated Image: </string>
+   <string name="themes_prompt">Select a Theme:</string>
+   <string name="sample_text">Sample text goes here. I wanted something creative and whimsical
+but then I just got bored...</string>
+    <string name="long_text">This is a really long string which exceeds the width of the view.
+New devices have a much larger screen which actually enables long strings to be displayed
+with no fading. I have made this string longer to fix this case. If you are correcting this
+text, I would love to see the kind of devices you guys now use! Guys, maybe some devices need longer string!
+I think so, so how about double this string, like copy and paste!
+This is a really long string which exceeds the width of the view.
+New devices have a much larger screen which actually enables long strings to be displayed
+with no fading. I have made this string longer to fix this case. If you are correcting this
+text, I would love to see the kind of devices you guys now use! Guys, maybe some devices need longer string!
+I think so, so how about double this string, like copy and paste! </string>
+    <string name="rectangle200">"M 0,0 l 200,0 l 0, 200 l -200, 0 z"</string>
+</resources>
diff --git a/tests/tests/content/res/values/styles.xml b/tests/tests/content/res/values/styles.xml
new file mode 100644
index 0000000..20c80f8
--- /dev/null
+++ b/tests/tests/content/res/values/styles.xml
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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 xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <style name="Whatever">
+        <item name="type1">true</item>
+        <item name="type2">false</item>
+        <item name="type3">#ff0000ff</item>
+        <item name="type4">#ff00ff00</item>
+        <item name="type5">0.75px</item>
+        <item name="type6">10px</item>
+        <item name="type7">18px</item>
+        <item name="type8">@drawable/pass</item>
+        <item name="type9">3.14</item>
+        <item name="type10">100%</item>
+        <item name="type11">365</item>
+        <item name="type12">86400</item>
+        <item name="type13">@string/hello_android</item>
+        <item name="type14">TypedArray Test!</item>
+        <item name="type15">@array/difficultyLevel</item>
+        <item name="type16">Typed Value!</item>
+    </style>
+
+    <style name="TextViewWithoutColorAndAppearance">
+        <item name="android:textSize">18sp</item>
+    </style>
+
+    <style name="TextViewWithColorButWithOutAppearance">
+        <item name="android:textColor">#ff0000ff</item>
+    </style>
+
+    <style name="TextViewWithColorAndAppearance">
+        <item name="android:textColor">#ff0000ff</item>
+        <item name="android:textAppearance">@style/TextAppearance.WithColor</item>
+    </style>
+
+    <style name="TextViewWithoutColorButWithAppearance">
+        <item name="android:textAppearance">@style/TextAppearance.WithColor</item>
+    </style>
+
+    <style name="TextAppearance" parent="android:TextAppearance">
+    </style>
+
+    <style name="TextAppearance.WithColor">
+        <item name="android:textColor">#ffff0000</item>
+    </style>
+
+    <style name="TextAppearance.All">
+        <item name="android:textColor">@drawable/black</item>
+        <item name="android:textSize">20px</item>
+        <item name="android:textStyle">bold</item>
+        <item name="android:textColorHint">@drawable/red</item>
+        <item name="android:textColorLink">@drawable/blue</item>
+        <item name="android:textColorHighlight">@drawable/yellow</item>
+    </style>
+
+    <style name="TextAppearance.Colors">
+        <item name="android:textColor">@drawable/black</item>
+        <item name="android:textColorHint">@drawable/blue</item>
+        <item name="android:textColorLink">@drawable/yellow</item>
+        <item name="android:textColorHighlight">@drawable/red</item>
+    </style>
+
+    <style name="TextAppearance.NotColors">
+        <item name="android:textSize">17px</item>
+        <item name="android:typeface">sans</item>
+        <item name="android:textStyle">normal</item>
+    </style>
+
+    <style name="TextAppearance.Style">
+        <item name="android:textStyle">normal</item>
+    </style>
+
+    <style name="TestEnum1">
+        <item name="testEnum">val1</item>
+    </style>
+
+    <style name="TestEnum2">
+        <item name="testEnum">val2</item>
+    </style>
+
+    <style name="TestEnum10">
+        <item name="testEnum">val10</item>
+    </style>
+
+    <style name="TestFlag1">
+        <item name="testFlags">bit1</item>
+    </style>
+
+    <style name="TestFlag2">
+        <item name="testFlags">bit2</item>
+    </style>
+
+    <style name="TestFlag31">
+        <item name="testFlags">bit31</item>
+    </style>
+
+    <style name="TestFlag1And2">
+        <item name="testFlags">bit1|bit2</item>
+    </style>
+
+    <style name="TestFlag1And2And31">
+        <item name="testFlags">bit1|bit2|bit31</item>
+    </style>
+
+    <style name="TestEnum1.EmptyInherit" />
+
+    <style name="Theme_AlertDialog">
+        <item name="android:textSize">18sp</item>
+    </style>
+
+    <style name="TestProgressBar">
+        <item name="android:indeterminateOnly">false</item>
+        <item name="android:progressDrawable">?android:drawable/progress_horizontal</item>
+        <item name="android:indeterminateDrawable">?android:drawable/progress_horizontal</item>
+        <item name="android:minHeight">20dip</item>
+        <item name="android:maxHeight">20dip</item>
+        <item name="android:focusable">true</item>
+    </style>
+
+    <style name="Test_Theme">
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:panelColorForeground">#ff000000</item>
+        <item name="android:panelColorBackground">#ffffffff</item>
+    </style>
+
+    <style name="Theme_OverrideOuter">
+        <item name="themeType">1</item>
+    </style>
+
+    <style name="Theme_OverrideInner">
+        <item name="themeType">2</item>
+        <item name="themeOverrideAttr">@style/Theme_OverrideAttr</item>
+    </style>
+
+    <style name="Theme_OverrideAttr">
+        <item name="themeType">3</item>
+    </style>
+    
+    <style name="Theme_ThemedDrawableTest">
+        <item name="themeBoolean">true</item>
+        <item name="themeColor">@android:color/black</item>
+        <item name="themeFloat">1.0</item>
+        <item name="themeAngle">45.0</item>
+        <item name="themeInteger">1</item>
+        <item name="themeDimension">1px</item>
+        <item name="themeDrawable">@drawable/icon_black</item>
+        <item name="themeBitmap">@drawable/icon_black</item>
+        <item name="themeNinePatch">@drawable/ninepatch_0</item>
+        <item name="themeGravity">48</item>
+        <item name="themeTileMode">2</item>
+    </style>
+
+    <style name="Theme_NoSwipeDismiss">
+        <item name="android:windowSwipeToDismiss">false</item>
+    </style>
+
+</resources>
diff --git a/tests/tests/content/res/xml/alias.xml b/tests/tests/content/res/xml/alias.xml
new file mode 100644
index 0000000..c245ba8
--- /dev/null
+++ b/tests/tests/content/res/xml/alias.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2008 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.
+ */
+-->
+
+<alias xmlns:android="http://schemas.android.com/apk/res/android">
+    <intent android:action="android.intent.action.MAIN"
+        android:targetPackage="com.android.cts.content"
+        android:targetClass="android.content.cts.ChildActivity"
+        android:data="http://www.google.com/">
+    </intent>
+</alias>
+
diff --git a/tests/res/xml/authenticator.xml b/tests/tests/content/res/xml/authenticator.xml
similarity index 100%
rename from tests/res/xml/authenticator.xml
rename to tests/tests/content/res/xml/authenticator.xml
diff --git a/tests/res/xml/colors.xml b/tests/tests/content/res/xml/colors.xml
similarity index 100%
rename from tests/res/xml/colors.xml
rename to tests/tests/content/res/xml/colors.xml
diff --git a/tests/res/xml/extra.xml b/tests/tests/content/res/xml/extra.xml
similarity index 100%
rename from tests/res/xml/extra.xml
rename to tests/tests/content/res/xml/extra.xml
diff --git a/tests/res/xml/intentfilter.xml b/tests/tests/content/res/xml/intentfilter.xml
similarity index 100%
copy from tests/res/xml/intentfilter.xml
copy to tests/tests/content/res/xml/intentfilter.xml
diff --git a/tests/res/xml/pm_test.xml b/tests/tests/content/res/xml/pm_test.xml
similarity index 100%
rename from tests/res/xml/pm_test.xml
rename to tests/tests/content/res/xml/pm_test.xml
diff --git a/tests/res/xml/syncadapter.xml b/tests/tests/content/res/xml/syncadapter.xml
similarity index 100%
rename from tests/res/xml/syncadapter.xml
rename to tests/tests/content/res/xml/syncadapter.xml
diff --git a/tests/res/xml/test_color.xml b/tests/tests/content/res/xml/test_color.xml
similarity index 100%
rename from tests/res/xml/test_color.xml
rename to tests/tests/content/res/xml/test_color.xml
diff --git a/tests/tests/content/src/android/content/cts/AsyncQueryHandlerTest.java b/tests/tests/content/src/android/content/cts/AsyncQueryHandlerTest.java
index 18e0b2e..3d4ca81 100644
--- a/tests/tests/content/src/android/content/cts/AsyncQueryHandlerTest.java
+++ b/tests/tests/content/src/android/content/cts/AsyncQueryHandlerTest.java
@@ -25,14 +25,15 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
-import android.test.AndroidTestCase;
+import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
 
 /**
  * Test {@link AsyncQueryHandler} and {@link WorkerHandler}}.
  *
  * @see DummyProvider
  */
-public class AsyncQueryHandlerTest extends AndroidTestCase {
+public class AsyncQueryHandlerTest extends InstrumentationTestCase {
     private static final long TEST_TIME_OUT = DummyProvider.MOCK_OPERATION_SLEEP_TIME + 5000;
 
     private static final int INSERT_TOKEN_1    = 100;
@@ -74,7 +75,7 @@
     protected void setUp() throws Exception {
         super.setUp();
 
-        mResolver = mContext.getContentResolver();
+        mResolver = getInstrumentation().getTargetContext().getContentResolver();
 
         ContentValues values0 = new ContentValues();
         values0.put(DummyProvider.NAME, NAME0);
@@ -96,9 +97,9 @@
         super.tearDown();
     }
 
+    @UiThreadTest
     public void testConstructor() {
         new AsyncQueryHandler(mResolver) {};
-
         new AsyncQueryHandler(null) {};
     }
 
@@ -257,9 +258,10 @@
         }
     }
 
+    @UiThreadTest
     public void testCreateHandler() {
         MockAsyncQueryHandler wrapper = new MockAsyncQueryHandler(mResolver);
-        Handler result = wrapper.createHandler(Looper.myLooper());
+        Handler result = wrapper.createHandler(Looper.getMainLooper());
         assertNotNull(result);
         assertSame(Looper.myLooper(), result.getLooper());
 
diff --git a/tests/tests/content/src/android/content/cts/AvailableIntentsActivity.java b/tests/tests/content/src/android/content/cts/AvailableIntentsActivity.java
new file mode 100644
index 0000000..773defc
--- /dev/null
+++ b/tests/tests/content/src/android/content/cts/AvailableIntentsActivity.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2008 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.content.cts;
+
+import com.android.cts.content.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * This is a stub activity for test available intents. We do not care about
+ * what it layouts. We only need an activity even if it's empty for this test.
+ */
+public class AvailableIntentsActivity extends Activity {
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.available_intents_layout);
+    }
+}
diff --git a/tests/tests/content/src/android/content/cts/BroadcastReceiverTest.java b/tests/tests/content/src/android/content/cts/BroadcastReceiverTest.java
index 2865f9e..526087b 100644
--- a/tests/tests/content/src/android/content/cts/BroadcastReceiverTest.java
+++ b/tests/tests/content/src/android/content/cts/BroadcastReceiverTest.java
@@ -18,8 +18,6 @@
 
 
 import android.app.Service;
-import android.app.cts.MockActivity;
-import android.app.cts.MockService;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -52,7 +50,7 @@
     private static final long START_SERVICE_TIMEOUT  = 3000;
 
     public BroadcastReceiverTest() {
-        super("com.android.cts.stub", MockActivity.class);
+        super("com.android.cts.content", MockActivity.class);
     }
 
     @Override
diff --git a/tests/tests/content/src/android/content/cts/ChildActivity.java b/tests/tests/content/src/android/content/cts/ChildActivity.java
new file mode 100644
index 0000000..c8092ed
--- /dev/null
+++ b/tests/tests/content/src/android/content/cts/ChildActivity.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2009 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.content.cts;
+
+import android.app.Activity;
+
+public class ChildActivity extends Activity {
+
+    public static boolean isStarted = false;
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+        isStarted = true;
+    }
+}
diff --git a/tests/src/android/content/cts/ClipboardManagerListenerActivity.java b/tests/tests/content/src/android/content/cts/ClipboardManagerListenerActivity.java
similarity index 100%
rename from tests/src/android/content/cts/ClipboardManagerListenerActivity.java
rename to tests/tests/content/src/android/content/cts/ClipboardManagerListenerActivity.java
diff --git a/tests/tests/content/src/android/content/cts/ClipboardManagerTest.java b/tests/tests/content/src/android/content/cts/ClipboardManagerTest.java
index bf0a175..e92834c 100644
--- a/tests/tests/content/src/android/content/cts/ClipboardManagerTest.java
+++ b/tests/tests/content/src/android/content/cts/ClipboardManagerTest.java
@@ -23,39 +23,44 @@
 import android.content.Intent;
 import android.content.ClipData.Item;
 import android.net.Uri;
-import android.test.AndroidTestCase;
+import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
 
-public class ClipboardManagerTest extends AndroidTestCase {
-
-    private ClipboardManager mClipboardManager;
+public class ClipboardManagerTest extends InstrumentationTestCase {
+    private Context mContext;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mClipboardManager = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
+        mContext = getInstrumentation().getTargetContext();
     }
 
+    @UiThreadTest
     public void testSetGetText() {
-        mClipboardManager.setText("Test Text 1");
-        assertEquals("Test Text 1", mClipboardManager.getText());
+        ClipboardManager clipboardManager = makeClipboardManager();
+        clipboardManager.setText("Test Text 1");
+        assertEquals("Test Text 1", clipboardManager.getText());
 
-        mClipboardManager.setText("Test Text 2");
-        assertEquals("Test Text 2", mClipboardManager.getText());
+        clipboardManager.setText("Test Text 2");
+        assertEquals("Test Text 2", clipboardManager.getText());
     }
 
+    @UiThreadTest
     public void testHasPrimaryClip() {
-        if (mClipboardManager.hasPrimaryClip()) {
-            assertNotNull(mClipboardManager.getPrimaryClip());
-            assertNotNull(mClipboardManager.getPrimaryClipDescription());
+        ClipboardManager clipboardManager = makeClipboardManager();
+        if (clipboardManager.hasPrimaryClip()) {
+            assertNotNull(clipboardManager.getPrimaryClip());
+            assertNotNull(clipboardManager.getPrimaryClipDescription());
         } else {
-            assertNull(mClipboardManager.getPrimaryClip());
-            assertNull(mClipboardManager.getPrimaryClipDescription());
+            assertNull(clipboardManager.getPrimaryClip());
+            assertNull(clipboardManager.getPrimaryClipDescription());
         }
 
-        mClipboardManager.setPrimaryClip(ClipData.newPlainText("Label", "Text"));
-        assertTrue(mClipboardManager.hasPrimaryClip());
+        clipboardManager.setPrimaryClip(ClipData.newPlainText("Label", "Text"));
+        assertTrue(clipboardManager.hasPrimaryClip());
     }
 
+    @UiThreadTest
     public void testSetPrimaryClip_plainText() {
         ClipData textData = ClipData.newPlainText("TextLabel", "Text");
         assertSetPrimaryClip(textData, "TextLabel",
@@ -63,6 +68,7 @@
                 new ExpectedClipItem("Text", null, null));
     }
 
+    @UiThreadTest
     public void testSetPrimaryClip_intent() {
         Intent intent = new Intent(mContext, ClipboardManagerTest.class);
         ClipData intentData = ClipData.newIntent("IntentLabel", intent);
@@ -71,6 +77,7 @@
                 new ExpectedClipItem(null, intent, null));
     }
 
+    @UiThreadTest
     public void testSetPrimaryClip_rawUri() {
         Uri uri = Uri.parse("http://www.google.com");
         ClipData uriData = ClipData.newRawUri("UriLabel", uri);
@@ -79,15 +86,17 @@
                 new ExpectedClipItem(null, null, uri));
     }
 
+    @UiThreadTest
     public void testSetPrimaryClip_contentUri() {
         Uri contentUri = Uri.parse("content://cts/test/for/clipboardmanager");
-        ClipData contentUriData = ClipData.newUri(getContext().getContentResolver(),
+        ClipData contentUriData = ClipData.newUri(mContext.getContentResolver(),
                 "ContentUriLabel", contentUri);
         assertSetPrimaryClip(contentUriData, "ContentUriLabel",
                 new String[] {ClipDescription.MIMETYPE_TEXT_URILIST},
                 new ExpectedClipItem(null, null, contentUri));
     }
 
+    @UiThreadTest
     public void testSetPrimaryClip_complexItem() {
         Intent intent = new Intent(mContext, ClipboardManagerTest.class);
         Uri uri = Uri.parse("http://www.google.com");
@@ -103,6 +112,7 @@
                 new ExpectedClipItem("Text", intent, uri));
     }
 
+    @UiThreadTest
     public void testSetPrimaryClip_multipleItems() {
         Intent intent = new Intent(mContext, ClipboardManagerTest.class);
         Uri uri = Uri.parse("http://www.google.com");
@@ -134,22 +144,23 @@
             String expectedLabel,
             String[] expectedMimeTypes,
             ExpectedClipItem... expectedClipItems) {
+        ClipboardManager clipboardManager = makeClipboardManager();
 
-        mClipboardManager.setPrimaryClip(clipData);
-        assertTrue(mClipboardManager.hasPrimaryClip());
+        clipboardManager.setPrimaryClip(clipData);
+        assertTrue(clipboardManager.hasPrimaryClip());
 
         if (expectedClipItems != null
                 && expectedClipItems.length > 0
                 && expectedClipItems[0].mText != null) {
-            assertTrue(mClipboardManager.hasText());
+            assertTrue(clipboardManager.hasText());
         } else {
-            assertFalse(mClipboardManager.hasText());
+            assertFalse(clipboardManager.hasText());
         }
 
-        assertNotNull(mClipboardManager.getPrimaryClip());
-        assertNotNull(mClipboardManager.getPrimaryClipDescription());
+        assertNotNull(clipboardManager.getPrimaryClip());
+        assertNotNull(clipboardManager.getPrimaryClipDescription());
 
-        ClipData data = mClipboardManager.getPrimaryClip();
+        ClipData data = clipboardManager.getPrimaryClip();
         if (expectedClipItems != null) {
             assertEquals(expectedClipItems.length, data.getItemCount());
             for (int i = 0; i < expectedClipItems.length; i++) {
@@ -162,7 +173,7 @@
         assertClipDescription(data.getDescription(),
                 expectedLabel, expectedMimeTypes);
 
-        assertClipDescription(mClipboardManager.getPrimaryClipDescription(),
+        assertClipDescription(clipboardManager.getPrimaryClipDescription(),
                 expectedLabel, expectedMimeTypes);
     }
 
@@ -189,4 +200,8 @@
             assertNull(item.getUri());
         }
     }
+
+    private ClipboardManager makeClipboardManager() {
+        return (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
+    }
 }
diff --git a/tests/tests/content/src/android/content/cts/ComponentNameTest.java b/tests/tests/content/src/android/content/cts/ComponentNameTest.java
index d14a95b..6277bd6 100644
--- a/tests/tests/content/src/android/content/cts/ComponentNameTest.java
+++ b/tests/tests/content/src/android/content/cts/ComponentNameTest.java
@@ -85,7 +85,7 @@
     }
 
     public void testFlattenToString() {
-        assertEquals("com.android.cts.stub/android.content.cts.ComponentNameTest",
+        assertEquals("com.android.cts.content/android.content.cts.ComponentNameTest",
                 getComponentName().flattenToString());
     }
 
@@ -121,7 +121,7 @@
 
     public void testGetPackageName() {
         final String actual = getComponentName().getPackageName();
-        assertEquals("com.android.cts.stub", actual);
+        assertEquals("com.android.cts.content", actual);
     }
 
     public void testUnflattenFromString() {
@@ -135,7 +135,7 @@
     public void testFlattenToShortString() {
         // Test normal
         String actual = getComponentName().flattenToShortString();
-        assertEquals("com.android.cts.stub/android.content.cts.ComponentNameTest", actual);
+        assertEquals("com.android.cts.content/android.content.cts.ComponentNameTest", actual);
 
         // Test long class name
         final ComponentName componentName = new ComponentName("com.android.view",
@@ -168,7 +168,7 @@
     public void testToShortString() {
         // Test normal string
         final String shortString = getComponentName().toShortString();
-        assertEquals("{com.android.cts.stub/android.content.cts.ComponentNameTest}", shortString);
+        assertEquals("{com.android.cts.content/android.content.cts.ComponentNameTest}", shortString);
     }
 
     public void testGetClassName() {
@@ -196,7 +196,7 @@
         ComponentName.writeToParcel(componentName, parcel);
         parcel.setDataPosition(0);
         assertFalse(0 == parcel.dataAvail());
-        assertEquals("com.android.cts.stub", parcel.readString());
+        assertEquals("com.android.cts.content", parcel.readString());
         assertEquals("android.content.cts.ComponentNameTest", parcel.readString());
 
         // Test null data
diff --git a/tests/tests/content/src/android/content/cts/ContentProviderTest.java b/tests/tests/content/src/android/content/cts/ContentProviderTest.java
index 5ced37c..0b4d9aa 100644
--- a/tests/tests/content/src/android/content/cts/ContentProviderTest.java
+++ b/tests/tests/content/src/android/content/cts/ContentProviderTest.java
@@ -27,7 +27,7 @@
 import android.os.ParcelFileDescriptor;
 import android.test.AndroidTestCase;
 
-import com.android.cts.stub.R;
+import com.android.cts.content.R;
 
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -37,7 +37,7 @@
  * Test {@link ContentProvider}.
  */
 public class ContentProviderTest extends AndroidTestCase {
-    private static final String TEST_PACKAGE_NAME = "com.android.cts.stub";
+    private static final String TEST_PACKAGE_NAME = "com.android.cts.content";
     private static final String TEST_FILE_NAME = "testFile.tmp";
     private static final String TEST_DB_NAME = "test.db";
 
diff --git a/tests/tests/content/src/android/content/cts/ContentQueryMapTest.java b/tests/tests/content/src/android/content/cts/ContentQueryMapTest.java
index ac23a5b..2385b0f 100644
--- a/tests/tests/content/src/android/content/cts/ContentQueryMapTest.java
+++ b/tests/tests/content/src/android/content/cts/ContentQueryMapTest.java
@@ -20,11 +20,13 @@
 import android.content.ContentQueryMap;
 import android.content.ContentResolver;
 import android.content.ContentValues;
+import android.content.Context;
 import android.database.Cursor;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
-import android.test.AndroidTestCase;
+import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
 
 import java.util.Map;
 import java.util.Observable;
@@ -33,7 +35,7 @@
 /**
  * Test {@link ContentQueryMap}.
  */
-public class ContentQueryMapTest extends AndroidTestCase {
+public class ContentQueryMapTest extends InstrumentationTestCase {
     private static final int TEST_TIME_OUT = 5000;
 
     private static final String NAME0  = "name0";
@@ -52,10 +54,12 @@
     private ContentResolver mResolver;
     private Cursor mCursor;
     private ContentQueryMap mContentQueryMap;
+    private Context mContext;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+        mContext = getInstrumentation().getTargetContext();
         mResolver = mContext.getContentResolver();
 
         ContentValues values0 = new ContentValues();
@@ -88,6 +92,7 @@
         super.tearDown();
     }
 
+    @UiThreadTest
     public void testConstructor() {
         new ContentQueryMap(mCursor, DummyProvider.NAME, true, null);
 
@@ -106,6 +111,7 @@
         }
     }
 
+    @UiThreadTest
     public void testGetRows() {
         // handler can be null
         mContentQueryMap = new ContentQueryMap(mCursor, DummyProvider.NAME, true, null);
diff --git a/tests/tests/content/src/android/content/cts/ContentResolverTest.java b/tests/tests/content/src/android/content/cts/ContentResolverTest.java
index 47371cc..4176da3 100644
--- a/tests/tests/content/src/android/content/cts/ContentResolverTest.java
+++ b/tests/tests/content/src/android/content/cts/ContentResolverTest.java
@@ -16,7 +16,7 @@
 
 package android.content.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.content.R;
 
 
 import android.accounts.Account;
@@ -75,7 +75,7 @@
     private static final int VALUE2 = 2;
     private static final int VALUE3 = 3;
 
-    private static final String TEST_PACKAGE_NAME = "com.android.cts.stub";
+    private static final String TEST_PACKAGE_NAME = "com.android.cts.content";
 
     private Context mContext;
     private ContentResolver mContentResolver;
diff --git a/tests/tests/content/src/android/content/cts/ContextTest.java b/tests/tests/content/src/android/content/cts/ContextTest.java
index 70abe1f..7c5dc50 100644
--- a/tests/tests/content/src/android/content/cts/ContextTest.java
+++ b/tests/tests/content/src/android/content/cts/ContextTest.java
@@ -16,7 +16,7 @@
 
 package android.content.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.content.R;
 import com.android.internal.util.XmlUtils;
 
 
diff --git a/tests/tests/content/src/android/content/cts/ContextWrapperCtsActivity.java b/tests/tests/content/src/android/content/cts/ContextWrapperCtsActivity.java
new file mode 100644
index 0000000..9ff4df9
--- /dev/null
+++ b/tests/tests/content/src/android/content/cts/ContextWrapperCtsActivity.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2008 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.content.cts;
+
+// Need the following import to get access to the app resources, since this
+// class is in a sub-package.
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.cts.content.R;
+
+public class ContextWrapperCtsActivity extends Activity {
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.local_sample);
+    }
+}
+
diff --git a/tests/tests/content/src/android/content/cts/ContextWrapperTest.java b/tests/tests/content/src/android/content/cts/ContextWrapperTest.java
index 59fae2f..62fc83a 100644
--- a/tests/tests/content/src/android/content/cts/ContextWrapperTest.java
+++ b/tests/tests/content/src/android/content/cts/ContextWrapperTest.java
@@ -16,7 +16,7 @@
 
 package android.content.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.content.R;
 
 
 import android.content.ActivityNotFoundException;
@@ -79,8 +79,8 @@
     private final static String MOCK_ACTION1 = ACTION_BROADCAST_TESTORDER + "1";
     private final static String MOCK_ACTION2 = ACTION_BROADCAST_TESTORDER + "2";
 
-    public static final String PERMISSION_GRANTED = "android.app.cts.permission.TEST_GRANTED";
-    public static final String PERMISSION_DENIED = "android.app.cts.permission.TEST_DENIED";
+    public static final String PERMISSION_GRANTED = "android.content.cts.permission.TEST_GRANTED";
+    public static final String PERMISSION_DENIED = "android.content.cts.permission.TEST_DENIED";
 
     private static final int BROADCAST_TIMEOUT = 10000;
 
@@ -402,7 +402,7 @@
     }
 
     public void testStartActivity() {
-        Intent intent = new Intent(mContext, ContextWrapperStubActivity.class);
+        Intent intent = new Intent(mContext, ContextWrapperCtsActivity.class);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         try {
             mContextWrapper.startActivity(intent);
@@ -474,7 +474,7 @@
     }
 
     public void testGetPackageName() {
-        assertEquals("com.android.cts.stub", mContextWrapper.getPackageName());
+        assertEquals("com.android.cts.content", mContextWrapper.getPackageName());
     }
 
     public void testGetCacheDir() {
@@ -641,7 +641,8 @@
     }
 
     public void testCheckCallingOrSelfPermission() {
-        int retValue = mContextWrapper.checkCallingOrSelfPermission("android.permission.GET_TASKS");
+        int retValue = mContextWrapper.checkCallingOrSelfPermission(
+                "android.permission.SET_WALLPAPER");
         assertEquals(PackageManager.PERMISSION_GRANTED, retValue);
     }
 
@@ -705,7 +706,7 @@
         }
 
         // Test with invalid uid and included granted permission.
-        returnValue = mContextWrapper.checkPermission("android.permission.GET_TASKS", 1, -11);
+        returnValue = mContextWrapper.checkPermission("android.permission.SET_WALLPAPER", 1, -11);
         assertEquals(PackageManager.PERMISSION_DENIED, returnValue);
     }
 
diff --git a/tests/src/android/content/cts/DummyProvider.java b/tests/tests/content/src/android/content/cts/DummyProvider.java
similarity index 100%
rename from tests/src/android/content/cts/DummyProvider.java
rename to tests/tests/content/src/android/content/cts/DummyProvider.java
diff --git a/tests/src/android/content/cts/HighPriorityBroadcastReceiver.java b/tests/tests/content/src/android/content/cts/HighPriorityBroadcastReceiver.java
similarity index 100%
rename from tests/src/android/content/cts/HighPriorityBroadcastReceiver.java
rename to tests/tests/content/src/android/content/cts/HighPriorityBroadcastReceiver.java
diff --git a/tests/tests/content/src/android/content/cts/ImageCaptureActivity.java b/tests/tests/content/src/android/content/cts/ImageCaptureActivity.java
new file mode 100644
index 0000000..71bf250
--- /dev/null
+++ b/tests/tests/content/src/android/content/cts/ImageCaptureActivity.java
@@ -0,0 +1,103 @@
+/*
+ * 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 com.android.cts.content;
+
+import android.app.Activity;
+import android.content.ClipData;
+import android.content.ClipData.Item;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.MediaStore;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+
+public class ImageCaptureActivity extends Activity {
+    public static final String ACTION_FILE_READY = "com.android.cts.content.action.file_ready";
+    private static final String TAG = ImageCaptureUriExtraToClipDataTest.TAG;
+
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Intent intent = getIntent();
+
+        // Check action.
+        String action = intent.getAction();
+        if ((MediaStore.ACTION_IMAGE_CAPTURE.equals(action)
+                        || MediaStore.ACTION_IMAGE_CAPTURE_SECURE.equals(action)
+                        || MediaStore.ACTION_VIDEO_CAPTURE.equals(action))) {
+            writeToClipDataUri(intent);
+        }
+
+        finish();
+    }
+
+    // Sends ACTION_FILE_READY intent when write to clipdata uri is succesful.
+    private void writeToClipDataUri(Intent intent) {
+        if ((intent.getFlags() & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0) {
+
+            // Note: since this activity is in the same package as the test we can write to the file
+            // regardless of this permission, but in general this permission is required.
+            Log.e(TAG, "Intent.FLAG_GRANT_WRITE_URI_PERMISSION was not granted.");
+            return;
+        }
+
+        File file = getFileFromIntent(intent);
+        if (file == null) {
+            Log.e(TAG, "Could not get file from clipdata.");
+            return;
+        }
+        try {
+            FileWriter writer = new FileWriter(file);
+            writer.write(ImageCaptureUriExtraToClipDataTest.TEST_INPUT);
+            writer.flush();
+            writer.close();
+        } catch (IOException e) {
+            Log.e(TAG, "File IO failure while writing.");
+            return;
+        }
+        Intent fileReady = new Intent(ACTION_FILE_READY);
+        sendBroadcast(fileReady);
+    }
+
+    private File getFileFromIntent(Intent intent) {
+        ClipData clipData = intent.getClipData();
+        if (clipData == null) {
+            Log.e(TAG, "ClipData missing.");
+            return null;
+        }
+        if (clipData.getItemCount() == 0) {
+            Log.e(TAG, "Uri missing in ClipData.");
+            return null;
+        }
+
+        Uri filePath = clipData.getItemAt(0).getUri();
+        if (filePath == null) {
+            Log.e(TAG, "Uri missing in ClipData.");
+            return null;
+        }
+
+        try {
+            return new File(filePath.getPath());
+        } catch (IllegalArgumentException e) {
+            Log.e(TAG, "Cannot get file at Uri.");
+            return null;
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/content/src/android/content/cts/ImageCaptureUriExtraToClipDataTest.java b/tests/tests/content/src/android/content/cts/ImageCaptureUriExtraToClipDataTest.java
new file mode 100644
index 0000000..bb2a43d
--- /dev/null
+++ b/tests/tests/content/src/android/content/cts/ImageCaptureUriExtraToClipDataTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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 com.android.cts.content;
+
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+import android.provider.MediaStore;
+import android.test.AndroidTestCase;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+public class ImageCaptureUriExtraToClipDataTest extends AndroidTestCase {
+    private static final String FILE_NAME = "testFile.txt";
+    private File mTestFile;
+    private final Semaphore mFileReadySemaphore = new Semaphore(0);
+
+    public static final String TEST_INPUT = "testString";
+    public static final String TAG = "ImageCaptureUriExtraToClipDataTest";
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        assertEquals(0, mFileReadySemaphore.availablePermits());
+
+        BroadcastReceiver mReceiver = new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    mFileReadySemaphore.release();
+                }
+            };
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(ImageCaptureActivity.ACTION_FILE_READY);
+        getContext().registerReceiver(mReceiver, filter);
+
+        mTestFile = new File(getContext().getFilesDir() + File.separator + FILE_NAME);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mTestFile.exists()) {
+            assertTrue(mTestFile.delete());
+        }
+        super.tearDown();
+    }
+
+
+    public void testUriExtraOutputMigratedToClipData_imageCaptureIntent() {
+        startActivityWithAction(MediaStore.ACTION_IMAGE_CAPTURE);
+        waitForFileReady();
+        testFileContents();
+    }
+
+    public void testUriExtraOutputMigratedToClipData_imageCaptureSecureIntent() {
+        startActivityWithAction(MediaStore.ACTION_IMAGE_CAPTURE_SECURE);
+        waitForFileReady();
+        testFileContents();
+    }
+
+    public void testUriExtraOutputMigratedToClipData_videoCaptureIntent() {
+        startActivityWithAction(MediaStore.ACTION_VIDEO_CAPTURE);
+        waitForFileReady();
+        testFileContents();
+    }
+
+    private void startActivityWithAction(String action) {
+        Intent intent = new Intent(action);
+        intent.setComponent(new ComponentName("com.android.cts.content",
+                        "com.android.cts.content.ImageCaptureActivity"));
+        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTestFile));
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        getContext().startActivity(intent);
+    }
+
+    private void waitForFileReady() {
+        try {
+            assertTrue(mFileReadySemaphore.tryAcquire(5, TimeUnit.SECONDS));
+        } catch (InterruptedException e) {
+            fail(e.toString());
+        }
+    }
+
+    private void testFileContents() {
+        char[] buffer = new char[TEST_INPUT.length()];
+        try {
+            FileReader reader = new FileReader(mTestFile);
+            reader.read(buffer);
+            reader.close();
+        } catch (IOException e) {
+            // Problem
+            fail(e.toString());
+        }
+        String fileContents = new String(buffer);
+        assertEquals(TEST_INPUT, fileContents);
+    }
+}
diff --git a/tests/tests/content/src/android/content/cts/IntentFilterTest.java b/tests/tests/content/src/android/content/cts/IntentFilterTest.java
index d067b9e5..d0e70f2 100644
--- a/tests/tests/content/src/android/content/cts/IntentFilterTest.java
+++ b/tests/tests/content/src/android/content/cts/IntentFilterTest.java
@@ -33,7 +33,6 @@
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
-import android.app.cts.MockActivity;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Intent;
diff --git a/tests/tests/content/src/android/content/cts/IntentTest.java b/tests/tests/content/src/android/content/cts/IntentTest.java
index d7bf6f4..d4fac55 100644
--- a/tests/tests/content/src/android/content/cts/IntentTest.java
+++ b/tests/tests/content/src/android/content/cts/IntentTest.java
@@ -22,8 +22,6 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
-import android.app.cts.MockActivity;
-import android.app.cts.MockReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -730,18 +728,18 @@
         // Should only have one activity responding to narrow category
         final ComponentName target = intent.resolveActivity(mPm);
         assertEquals("com.android.cts.content", target.getPackageName());
-        assertEquals("android.app.cts.MockActivity", target.getClassName());
+        assertEquals("android.content.cts.MockActivity", target.getClassName());
     }
 
     public void testResolveActivityShortcutMatch() {
         final Intent intent = new Intent("com.android.cts.content.action.TEST_ACTION");
         intent.setComponent(
-                new ComponentName("com.android.cts.content", "android.app.cts.MockActivity2"));
+                new ComponentName("com.android.cts.content", "android.content.cts.MockActivity2"));
 
         // Multiple activities match, but we asked for explicit component
         final ComponentName target = intent.resolveActivity(mPm);
         assertEquals("com.android.cts.content", target.getPackageName());
-        assertEquals("android.app.cts.MockActivity2", target.getClassName());
+        assertEquals("android.content.cts.MockActivity2", target.getClassName());
     }
 
     public void testResolveActivityMultipleMatch() {
diff --git a/tests/tests/content/src/android/content/cts/Intent_ShortcutIconResourceTest.java b/tests/tests/content/src/android/content/cts/Intent_ShortcutIconResourceTest.java
index b38f3fc..062ef90 100644
--- a/tests/tests/content/src/android/content/cts/Intent_ShortcutIconResourceTest.java
+++ b/tests/tests/content/src/android/content/cts/Intent_ShortcutIconResourceTest.java
@@ -29,7 +29,7 @@
 
     ShortcutIconResource mShortcutIconResource;
     Context mContext;
-    final int resourceId = com.android.cts.stub.R.string.notify;
+    final int resourceId = com.android.cts.content.R.string.notify;
 
     @Override
     protected void setUp() throws Exception {
@@ -63,7 +63,7 @@
     public void testWriteToParcel() {
 
         mShortcutIconResource = ShortcutIconResource.fromContext(mContext,
-                com.android.cts.stub.R.string.notify);
+                com.android.cts.content.R.string.notify);
         assertNotNull(mShortcutIconResource);
         Parcel parce = Parcel.obtain();
         mShortcutIconResource.writeToParcel(parce, 1);
diff --git a/tests/src/android/content/cts/LowPriorityBroadcastReceiver.java b/tests/tests/content/src/android/content/cts/LowPriorityBroadcastReceiver.java
similarity index 100%
rename from tests/src/android/content/cts/LowPriorityBroadcastReceiver.java
rename to tests/tests/content/src/android/content/cts/LowPriorityBroadcastReceiver.java
diff --git a/tests/src/android/content/cts/MockAccountAuthenticator.java b/tests/tests/content/src/android/content/cts/MockAccountAuthenticator.java
similarity index 100%
rename from tests/src/android/content/cts/MockAccountAuthenticator.java
rename to tests/tests/content/src/android/content/cts/MockAccountAuthenticator.java
diff --git a/tests/src/android/content/cts/MockAccountService.java b/tests/tests/content/src/android/content/cts/MockAccountService.java
similarity index 100%
rename from tests/src/android/content/cts/MockAccountService.java
rename to tests/tests/content/src/android/content/cts/MockAccountService.java
diff --git a/tests/tests/content/src/android/content/cts/MockActivity.java b/tests/tests/content/src/android/content/cts/MockActivity.java
new file mode 100644
index 0000000..19834df
--- /dev/null
+++ b/tests/tests/content/src/android/content/cts/MockActivity.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2008 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.content.cts;
+
+import android.app.Activity;
+
+public class MockActivity extends Activity {
+
+}
diff --git a/tests/tests/content/src/android/content/cts/MockApplication.java b/tests/tests/content/src/android/content/cts/MockApplication.java
new file mode 100644
index 0000000..cca34d6
--- /dev/null
+++ b/tests/tests/content/src/android/content/cts/MockApplication.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2008 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.content.cts;
+
+import android.app.Application;
+import android.content.res.Configuration;
+
+
+public class MockApplication extends Application {
+
+    public boolean isOnCreateCalled;
+    public boolean isConstructorCalled;
+    public boolean isOnConfigurationChangedCalled;
+    public boolean isOnLowMemoryCalled;
+
+    public MockApplication() {
+        super();
+        isConstructorCalled = true;
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        isOnCreateCalled = true;
+    }
+
+    @Override
+    public void onTerminate() {
+        super.onTerminate();
+        // The documentation states that one cannot rely on this method being called. No need to
+        // test it here.
+    }
+
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        isOnConfigurationChangedCalled = true;
+    }
+
+    @Override
+    public void onLowMemory() {
+        super.onLowMemory();
+        isOnLowMemoryCalled = true;
+    }
+}
diff --git a/tests/src/android/content/cts/MockContentProvider.java b/tests/tests/content/src/android/content/cts/MockContentProvider.java
similarity index 100%
rename from tests/src/android/content/cts/MockContentProvider.java
rename to tests/tests/content/src/android/content/cts/MockContentProvider.java
diff --git a/tests/src/android/content/cts/MockContextWrapperService.java b/tests/tests/content/src/android/content/cts/MockContextWrapperService.java
similarity index 100%
rename from tests/src/android/content/cts/MockContextWrapperService.java
rename to tests/tests/content/src/android/content/cts/MockContextWrapperService.java
diff --git a/tests/src/android/content/cts/MockReceiver.java b/tests/tests/content/src/android/content/cts/MockReceiver.java
similarity index 100%
rename from tests/src/android/content/cts/MockReceiver.java
rename to tests/tests/content/src/android/content/cts/MockReceiver.java
diff --git a/tests/src/android/content/cts/MockReceiverAbort.java b/tests/tests/content/src/android/content/cts/MockReceiverAbort.java
similarity index 100%
rename from tests/src/android/content/cts/MockReceiverAbort.java
rename to tests/tests/content/src/android/content/cts/MockReceiverAbort.java
diff --git a/tests/src/android/content/cts/MockReceiverFirst.java b/tests/tests/content/src/android/content/cts/MockReceiverFirst.java
similarity index 100%
rename from tests/src/android/content/cts/MockReceiverFirst.java
rename to tests/tests/content/src/android/content/cts/MockReceiverFirst.java
diff --git a/tests/src/android/content/cts/MockRemoteContentProvider.java b/tests/tests/content/src/android/content/cts/MockRemoteContentProvider.java
similarity index 100%
rename from tests/src/android/content/cts/MockRemoteContentProvider.java
rename to tests/tests/content/src/android/content/cts/MockRemoteContentProvider.java
diff --git a/tests/src/android/content/cts/MockSRSProvider.java b/tests/tests/content/src/android/content/cts/MockSRSProvider.java
similarity index 100%
rename from tests/src/android/content/cts/MockSRSProvider.java
rename to tests/tests/content/src/android/content/cts/MockSRSProvider.java
diff --git a/tests/tests/content/src/android/content/cts/MockService.java b/tests/tests/content/src/android/content/cts/MockService.java
new file mode 100644
index 0000000..6726f8b
--- /dev/null
+++ b/tests/tests/content/src/android/content/cts/MockService.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2008 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.content.cts;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IBinder;
+
+public class MockService extends Service {
+    public static boolean result = false;
+    private final IBinder mBinder = new MockBinder();
+
+    public class MockBinder extends Binder {
+        MockService getService() {
+            return MockService.this;
+        }
+    }
+
+    /**
+     * set the result as true when service bind
+     */
+    @Override
+    public IBinder onBind(Intent intent) {
+        result = true;
+        return mBinder;
+    }
+
+    /**
+     * set the result as true when service start
+     */
+    @Override
+    public void onStart(Intent intent, int startId) {
+        super.onStart(intent, startId);
+        result = true;
+    }
+}
+
diff --git a/tests/src/android/content/cts/MockSyncAdapter.java b/tests/tests/content/src/android/content/cts/MockSyncAdapter.java
similarity index 100%
rename from tests/src/android/content/cts/MockSyncAdapter.java
rename to tests/tests/content/src/android/content/cts/MockSyncAdapter.java
diff --git a/tests/src/android/content/cts/MockSyncAdapterService.java b/tests/tests/content/src/android/content/cts/MockSyncAdapterService.java
similarity index 100%
rename from tests/src/android/content/cts/MockSyncAdapterService.java
rename to tests/tests/content/src/android/content/cts/MockSyncAdapterService.java
diff --git a/tests/tests/content/src/android/content/cts/MutableContextWrapperTest.java b/tests/tests/content/src/android/content/cts/MutableContextWrapperTest.java
index b81ca71..e7288af 100644
--- a/tests/tests/content/src/android/content/cts/MutableContextWrapperTest.java
+++ b/tests/tests/content/src/android/content/cts/MutableContextWrapperTest.java
@@ -16,12 +16,12 @@
 
 package android.content.cts;
 
-import android.app.cts.MockActivity;
 import android.content.Context;
 import android.content.MutableContextWrapper;
-import android.test.AndroidTestCase;
+import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
 
-public class MutableContextWrapperTest extends AndroidTestCase {
+public class MutableContextWrapperTest extends InstrumentationTestCase {
 
     MutableContextWrapper mMutableContextWrapper;
     Context mContext;
@@ -30,7 +30,7 @@
     protected void setUp() throws Exception {
         super.setUp();
         mMutableContextWrapper = null;
-        mContext = getContext();
+        mContext = getInstrumentation().getTargetContext();
     }
 
     public void testConstructor() {
@@ -39,6 +39,7 @@
         assertNotNull(mMutableContextWrapper);
     }
 
+    @UiThreadTest
     public void testSetBaseContext() {
         mMutableContextWrapper = new MutableContextWrapper(mContext);
         assertTrue(mContext.equals(mMutableContextWrapper.getBaseContext()));
diff --git a/tests/tests/content/src/android/content/cts/ReadableFileReceiverActivity.java b/tests/tests/content/src/android/content/cts/ReadableFileReceiverActivity.java
new file mode 100644
index 0000000..bab516e
--- /dev/null
+++ b/tests/tests/content/src/android/content/cts/ReadableFileReceiverActivity.java
@@ -0,0 +1,120 @@
+/*
+ * 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 com.android.cts.content;
+
+import android.app.Activity;
+import android.content.ClipData;
+import android.content.ClipData.Item;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ReadableFileReceiverActivity extends Activity {
+    public static final String ACTION_CONFIRM_READ_SUCCESS
+        = "com.android.cts.content.action.CONFIRM_READ_SUCCESS";
+    private static final String TAG = ReadableUriExtraToClipDataTest.TAG;
+
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Intent intent = getIntent();
+
+        // Check action.
+        String action = intent.getAction();
+        if (Intent.ACTION_SEND.equals(action)
+                || Intent.ACTION_SEND_MULTIPLE.equals(action)) {
+            readFilesFromClipDataUri(intent);
+        }
+
+        finish();
+    }
+
+    // Sends ACTION_FILE_READY intent when read from clipdata uri is succesful
+    // and read data matches the data written by the test.
+    private void readFilesFromClipDataUri(Intent intent) {
+        if ((intent.getFlags() & Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
+
+            // Note: since this activity is in the same package as the test we can read from the
+            // file regardless of this permission, but in general this permission is required.
+            Log.e(TAG, "Intent.FLAG_GRANT_READ_URI_PERMISSION was not granted.");
+            return;
+        }
+
+        List<File> files = getFilesFromIntent(intent);
+        if (files == null) {
+            Log.e(TAG, "Could not get files from clipdata.");
+            return;
+        }
+        for (File file : files) {
+            if (!testFileContents(file)) {
+                Log.e(TAG, "File contents of " + file.getPath()
+                        + " is incorrect or could not be verified.");
+                return;
+            }
+        }
+        Intent confirmIntent = new Intent(ACTION_CONFIRM_READ_SUCCESS);
+        sendBroadcast(confirmIntent);
+    }
+
+    private ArrayList<File> getFilesFromIntent(Intent intent) {
+        ClipData clipData = intent.getClipData();
+        if (clipData == null) {
+            Log.e(TAG, "ClipData missing.");
+            return null;
+        }
+        if (clipData.getItemCount() == 0) {
+            Log.e(TAG, "Uri missing in ClipData.");
+            return null;
+        }
+
+        ArrayList<File> result = new ArrayList<File>();
+        for (int i = 0; i < clipData.getItemCount(); i++) {
+            Uri filePath = clipData.getItemAt(i).getUri();
+            if (filePath == null) {
+                Log.e(TAG, "Uri missing in ClipData.");
+                return null;
+            }
+            try {
+                result.add(new File(filePath.getPath()));
+            } catch (IllegalArgumentException e) {
+                Log.e(TAG, "Cannot get file at Uri.");
+                return null;
+            }
+        }
+        return result;
+    }
+
+    private boolean testFileContents(File file) {
+        char[] buffer = new char[ReadableUriExtraToClipDataTest.TEST_INPUT.length()];
+        try {
+            FileReader reader = new FileReader(file);
+            reader.read(buffer);
+            reader.close();
+        } catch (IOException e) {
+            Log.e(TAG, "Error while reading file " + file.getPath() + ".");
+            return false;
+        }
+        String fileContents = new String(buffer);
+        return ReadableUriExtraToClipDataTest.TEST_INPUT.equals(fileContents);
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/content/src/android/content/cts/ReadableUriExtraToClipDataTest.java b/tests/tests/content/src/android/content/cts/ReadableUriExtraToClipDataTest.java
new file mode 100644
index 0000000..129d964
--- /dev/null
+++ b/tests/tests/content/src/android/content/cts/ReadableUriExtraToClipDataTest.java
@@ -0,0 +1,125 @@
+/*
+ * 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 com.android.cts.content;
+
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+import android.provider.MediaStore;
+import android.test.AndroidTestCase;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.List;
+
+public class ReadableUriExtraToClipDataTest extends AndroidTestCase {
+    private static final List<String> FILE_NAMES = Arrays.asList("testFile1.txt", "testFile2.txt");
+    private static final List<File> mTestFiles = new ArrayList<File>();
+    private static final ArrayList<Uri> mTestFileUris = new ArrayList<Uri>();
+    private final Semaphore mReadSuccessSemaphore = new Semaphore(0);
+
+    public static final String TEST_INPUT = "testString";
+    public static final String TAG = "ReadableUriExtraToClipDataTest";
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        assertEquals(0, mReadSuccessSemaphore.availablePermits());
+
+        BroadcastReceiver mReceiver = new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    mReadSuccessSemaphore.release();
+                }
+            };
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(ReadableFileReceiverActivity.ACTION_CONFIRM_READ_SUCCESS);
+        getContext().registerReceiver(mReceiver, filter);
+
+        for (String fileName : FILE_NAMES) {
+            File testFile = new File(getContext().getFilesDir() + File.separator + fileName);
+            writeTestInputToFile(testFile);
+            mTestFiles.add(testFile);
+            mTestFileUris.add(Uri.fromFile(testFile));
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        for (File testFile : mTestFiles) {
+            if (testFile.exists()) {
+                assertTrue(testFile.delete());
+            }
+        }
+        mTestFiles.clear();
+        mTestFileUris.clear();
+        super.tearDown();
+    }
+
+    public void testUriExtraStreamMigratedToClipData_sendIntent() {
+        Intent intent = new Intent(Intent.ACTION_SEND);
+        intent.setComponent(new ComponentName(getContext(), ReadableFileReceiverActivity.class));
+        intent.putExtra(Intent.EXTRA_STREAM, mTestFileUris.get(0));
+        intent.setType("*/*");
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+        getContext().startActivity(intent);
+
+        waitForConfirmationReadSuccess();
+    }
+
+    public void testUriExtraStreamMigratedToClipData_sendMultipleIntent() {
+        Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
+        intent.setComponent(new ComponentName(getContext(), ReadableFileReceiverActivity.class));
+        intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, mTestFileUris);
+        intent.setType("*/*");
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+        getContext().startActivity(intent);
+
+        waitForConfirmationReadSuccess();
+    }
+
+    private void writeTestInputToFile(File file) {
+        try {
+            FileWriter writer = new FileWriter(file);
+            writer.write(TEST_INPUT);
+            writer.flush();
+            writer.close();
+        } catch (IOException e) {
+            fail(e.toString());
+            return;
+        }
+    }
+
+    private void waitForConfirmationReadSuccess() {
+        try {
+            assertTrue(mReadSuccessSemaphore.tryAcquire(5, TimeUnit.SECONDS));
+        } catch (InterruptedException e) {
+            fail(e.toString());
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/android/content/cts/ResultReceiver.java b/tests/tests/content/src/android/content/cts/ResultReceiver.java
similarity index 100%
rename from tests/src/android/content/cts/ResultReceiver.java
rename to tests/tests/content/src/android/content/cts/ResultReceiver.java
diff --git a/tests/tests/content/src/android/content/cts/SharedPreferencesTest.java b/tests/tests/content/src/android/content/cts/SharedPreferencesTest.java
index 2354926..c271483 100644
--- a/tests/tests/content/src/android/content/cts/SharedPreferencesTest.java
+++ b/tests/tests/content/src/android/content/cts/SharedPreferencesTest.java
@@ -54,8 +54,8 @@
 
         // Duplicated from ContextImpl.java.  Not ideal, but there wasn't a better
         // way to reach into Context{Wrapper,Impl} to ask where this file lives.
-        mPrefsFile = new File("/data/data/com.android.cts.stub/shared_prefs",
-                              "com.android.cts.stub_preferences.xml");
+        mPrefsFile = new File("/data/data/com.android.cts.content/shared_prefs",
+                              "com.android.cts.content_preferences.xml");
         mPrefsFile.delete();
     }
 
diff --git a/tests/tests/content/src/android/content/pm/cts/ActivityInfoTest.java b/tests/tests/content/src/android/content/pm/cts/ActivityInfoTest.java
index 6c1ae40..caabdb4 100644
--- a/tests/tests/content/src/android/content/pm/cts/ActivityInfoTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/ActivityInfoTest.java
@@ -17,7 +17,7 @@
 package android.content.pm.cts;
 
 
-import android.app.cts.MockActivity;
+import android.content.cts.MockActivity;
 import android.content.ComponentName;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
diff --git a/tests/tests/content/src/android/content/pm/cts/ApplicationInfoTest.java b/tests/tests/content/src/android/content/pm/cts/ApplicationInfoTest.java
index 3055e57..1e9f5a2 100644
--- a/tests/tests/content/src/android/content/pm/cts/ApplicationInfoTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/ApplicationInfoTest.java
@@ -16,7 +16,7 @@
 
 package android.content.pm.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.content.R;
 
 
 import android.content.pm.ApplicationInfo;
diff --git a/tests/tests/content/src/android/content/pm/cts/ApplicationInfo_DisplayNameComparatorTest.java b/tests/tests/content/src/android/content/pm/cts/ApplicationInfo_DisplayNameComparatorTest.java
index ebd75cc..211a2ca 100644
--- a/tests/tests/content/src/android/content/pm/cts/ApplicationInfo_DisplayNameComparatorTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/ApplicationInfo_DisplayNameComparatorTest.java
@@ -26,7 +26,7 @@
  * Test {@link DisplayNameComparator}.
  */
 public class ApplicationInfo_DisplayNameComparatorTest extends AndroidTestCase {
-    private static final String PACKAGE_NAME = "com.android.cts.stub";
+    private static final String PACKAGE_NAME = "com.android.cts.content";
     DisplayNameComparator mDisplayNameComparator;
 
     @Override
diff --git a/tests/tests/content/src/android/content/pm/cts/ComponentInfoTest.java b/tests/tests/content/src/android/content/pm/cts/ComponentInfoTest.java
index 7850e1e..14a42c01 100644
--- a/tests/tests/content/src/android/content/pm/cts/ComponentInfoTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/ComponentInfoTest.java
@@ -20,22 +20,22 @@
 import android.content.pm.ComponentInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.cts.util.WidgetTestUtils;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Parcel;
 import android.test.AndroidTestCase;
 import android.util.Printer;
 import android.util.StringBuilderPrinter;
-import android.widget.cts.WidgetTestUtils;
 
-import com.android.cts.stub.R;
+import com.android.cts.content.R;
 
 
 /**
  * Test {@link ComponentInfo}.
  */
 public class ComponentInfoTest extends AndroidTestCase {
-    private final String PACKAGE_NAME = "com.android.cts.stub";
+    private final String PACKAGE_NAME = "com.android.cts.content";
     private ComponentInfo mComponentInfo;
 
     public void testConstructor() {
diff --git a/tests/tests/content/src/android/content/pm/cts/FeatureGroupInfoTest.java b/tests/tests/content/src/android/content/pm/cts/FeatureGroupInfoTest.java
new file mode 100644
index 0000000..0b9de54
--- /dev/null
+++ b/tests/tests/content/src/android/content/pm/cts/FeatureGroupInfoTest.java
@@ -0,0 +1,175 @@
+/**
+ * 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.content.pm.cts;
+
+import android.content.pm.FeatureGroupInfo;
+import android.content.pm.FeatureInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.test.AndroidTestCase;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+public class FeatureGroupInfoTest extends AndroidTestCase {
+
+    private PackageManager mPackageManager;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mPackageManager = getContext().getPackageManager();
+    }
+
+    public void testFeatureGroupsAreCorrect() throws Exception {
+        FeatureInfo[] expectedFeatures = new FeatureInfo[] {
+                createFeatureInfo("android.hardware.camera", true),
+                createFeatureInfo(0x00020000, true)
+        };
+
+        FeatureGroupInfo[] expectedGroups = new FeatureGroupInfo[] {
+                createFeatureGroup(new FeatureInfo[] {
+                }),
+                createFeatureGroup(new FeatureInfo[] {
+                        createFeatureInfo("android.hardware.location", true),
+                        createFeatureInfo(0x00030000, true)
+                }),
+                createFeatureGroup(new FeatureInfo[] {
+                        createFeatureInfo("android.hardware.camera", true),
+                        createFeatureInfo(0x00010001, true)
+                })
+        };
+
+        PackageInfo pi = mPackageManager.getPackageInfo(getContext().getPackageName(),
+                PackageManager.GET_CONFIGURATIONS);
+        assertNotNull(pi);
+        assertNotNull(pi.reqFeatures);
+        assertNotNull(pi.featureGroups);
+
+        assertFeatureInfosMatch(pi.reqFeatures, expectedFeatures);
+        assertFeatureGroupsMatch(pi.featureGroups, expectedGroups);
+    }
+
+    private static void assertFeatureInfosMatch(FeatureInfo[] actualFeatures,
+            FeatureInfo[] expectedFeatures) {
+        // We're going to do linear comparisons, so sort everything first.
+        Arrays.sort(actualFeatures, sFeatureInfoComparator);
+        Arrays.sort(expectedFeatures, sFeatureInfoComparator);
+
+        assertEquals(0, compareFeatureInfoArrays(actualFeatures, expectedFeatures));
+    }
+
+    private static void assertFeatureGroupsMatch(FeatureGroupInfo[] actualGroups,
+            FeatureGroupInfo[] expectedGroups) {
+        // We're going to do linear comparisons, so sort everything first.
+        sortFeatureInfos(actualGroups);
+        sortFeatureInfos(expectedGroups);
+
+        Arrays.sort(actualGroups, sFeatureGroupComparator);
+        Arrays.sort(expectedGroups, sFeatureGroupComparator);
+
+        assertEquals(expectedGroups.length, actualGroups.length);
+        final int N = expectedGroups.length;
+        for (int i = 0; i < N; i++) {
+            assertEquals(0, sFeatureGroupComparator.compare(expectedGroups[i], actualGroups[i]));
+        }
+    }
+
+    /**
+     * Helper method to create FeatureInfo objects.
+     */
+    private static FeatureInfo createFeatureInfo(String name, boolean required) {
+        FeatureInfo fi = new FeatureInfo();
+        fi.name = name;
+        if (required) {
+            fi.flags |= FeatureInfo.FLAG_REQUIRED;
+        }
+        return fi;
+    }
+
+    /**
+     * Helper method to create OpenGL FeatureInfo objects.
+     */
+    private static FeatureInfo createFeatureInfo(int glEsVersion, boolean required) {
+        FeatureInfo fi = new FeatureInfo();
+        fi.reqGlEsVersion = glEsVersion;
+        if (required) {
+            fi.flags |= FeatureInfo.FLAG_REQUIRED;
+        }
+        return fi;
+    }
+
+    private static FeatureGroupInfo createFeatureGroup(FeatureInfo[] featureInfos) {
+        FeatureGroupInfo group = new FeatureGroupInfo();
+        group.features = featureInfos;
+        return group;
+    }
+
+    private static void sortFeatureInfos(FeatureGroupInfo[] group) {
+        for (FeatureGroupInfo g : group) {
+            if (g.features != null) {
+                Arrays.sort(g.features, sFeatureInfoComparator);
+            }
+        }
+    }
+
+    private static int compareFeatureInfoArrays(FeatureInfo[] a, FeatureInfo[] b) {
+        final int aCount = a != null ? a.length : 0;
+        final int bCount = b != null ? b.length : 0;
+        final int N = Math.min(aCount, bCount);
+        for (int i = 0; i < N; i++) {
+            int diff = sFeatureInfoComparator.compare(a[i], b[i]);
+            if (diff != 0) {
+                return diff;
+            }
+        }
+        return Integer.compare(aCount, bCount);
+    }
+
+    /**
+     * A Comparator for FeatureGroups that assumes that the FeatureInfo array is
+     * already sorted.
+     */
+    private static final Comparator<FeatureGroupInfo> sFeatureGroupComparator =
+            new Comparator<FeatureGroupInfo>() {
+                @Override
+                public int compare(FeatureGroupInfo o1, FeatureGroupInfo o2) {
+                    return compareFeatureInfoArrays(o1.features, o2.features);
+                }
+            };
+
+    private static final Comparator<FeatureInfo> sFeatureInfoComparator =
+            new Comparator<FeatureInfo>() {
+                @Override
+                public int compare(FeatureInfo o1, FeatureInfo o2) {
+                    final int diff;
+                    if (o1.name == null && o2.name != null) {
+                        diff = -1;
+                    } else if (o1.name != null && o2.name == null) {
+                        diff = 1;
+                    } else if (o1.name == null && o2.name == null) {
+                        diff = Integer.compare(o1.reqGlEsVersion, o2.reqGlEsVersion);
+                    } else {
+                        diff = o1.name.compareTo(o2.name);
+                    }
+
+                    if (diff == 0) {
+                        return Integer.compare(o1.flags, o2.flags);
+                    }
+                    return diff;
+                }
+            };
+}
diff --git a/tests/tests/content/src/android/content/pm/cts/FeatureTest.java b/tests/tests/content/src/android/content/pm/cts/FeatureTest.java
new file mode 100644
index 0000000..19bf128
--- /dev/null
+++ b/tests/tests/content/src/android/content/pm/cts/FeatureTest.java
@@ -0,0 +1,53 @@
+/**
+ * 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.content.pm.cts;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.FeatureGroupInfo;
+import android.content.pm.FeatureInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+public class FeatureTest extends AndroidTestCase {
+
+    private static final String TAG = "FeatureTest";
+
+    private PackageManager mPackageManager;
+    private ActivityManager mActivityManager;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mPackageManager = getContext().getPackageManager();
+        mActivityManager = (ActivityManager)getContext().getSystemService(Context.ACTIVITY_SERVICE);
+    }
+
+    public void testNoManagedUsersIfLowRamDevice() {
+        if (mPackageManager == null || mActivityManager == null) {
+            Log.w(TAG, "Skipping testNoManagedUsersIfLowRamDevice");
+            return;
+        }
+        if (mActivityManager.isLowRamDevice()) {
+            assertFalse(mPackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS));
+        }
+    }
+}
diff --git a/tests/tests/content/src/android/content/pm/cts/InstrumentationInfoTest.java b/tests/tests/content/src/android/content/pm/cts/InstrumentationInfoTest.java
index 4656949..5b7747d 100644
--- a/tests/tests/content/src/android/content/pm/cts/InstrumentationInfoTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/InstrumentationInfoTest.java
@@ -25,7 +25,7 @@
 import android.test.AndroidTestCase;
 
 public class InstrumentationInfoTest extends AndroidTestCase {
-    private static final String PACKAGE_NAME = "com.android.cts.stub";
+    private static final String PACKAGE_NAME = "com.android.cts.content";
     private static final String INSTRUMENTATION_NAME =
             "android.content.pm.cts.TestPmInstrumentation";
 
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageInfoTest.java b/tests/tests/content/src/android/content/pm/cts/PackageInfoTest.java
index cefe1a6..0540e0b 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageInfoTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageInfoTest.java
@@ -32,7 +32,7 @@
     private PackageManager mPackageManager;
     private PackageInfo mPackageInfo;
     private PackageInfo mPackageInfoCmp;
-    private static final String PACKAGE_NAME = "com.android.cts.stub";
+    private static final String PACKAGE_NAME = "com.android.cts.content";
 
     @Override
     protected void setUp() throws Exception {
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageItemInfoTest.java b/tests/tests/content/src/android/content/pm/cts/PackageItemInfoTest.java
index d3372c6..53e69da 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageItemInfoTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageItemInfoTest.java
@@ -16,7 +16,7 @@
 
 package android.content.pm.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.content.R;
 
 
 import android.content.ComponentName;
@@ -30,7 +30,7 @@
 import android.util.Printer;
 
 public class PackageItemInfoTest extends AndroidTestCase {
-    private static final String PACKAGE_NAME = "com.android.cts.stub";
+    private static final String PACKAGE_NAME = "com.android.cts.content";
     private static final String ACTIVITY_NAME = "android.content.pm.cts.TestPmActivity";
     private static final String METADATA_NAME = "android.content.pm.cts.xmltest";
     private PackageManager mPackageManager;
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageItemInfo_DisplayNameComparatorTest.java b/tests/tests/content/src/android/content/pm/cts/PackageItemInfo_DisplayNameComparatorTest.java
index f332d6e..0cfd1dd 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageItemInfo_DisplayNameComparatorTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageItemInfo_DisplayNameComparatorTest.java
@@ -26,7 +26,7 @@
 import android.test.AndroidTestCase;
 
 public class PackageItemInfo_DisplayNameComparatorTest extends AndroidTestCase {
-    private static final String PACKAGE_NAME = "com.android.cts.stub";
+    private static final String PACKAGE_NAME = "com.android.cts.content";
     private static final String ACTIVITY_NAME = "android.content.pm.cts.TestPmActivity";
     private static final String CMPACTIVITY_NAME = "android.content.pm.cts.TestPmCompare";
 
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java b/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
index d1e1252..aaab8c4 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageManagerTest.java
@@ -16,7 +16,7 @@
 
 package android.content.pm.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.content.R;
 
 
 import android.content.ComponentName;
@@ -44,7 +44,7 @@
  */
 public class PackageManagerTest extends AndroidTestCase {
     private PackageManager mPackageManager;
-    private static final String PACKAGE_NAME = "com.android.cts.stub";
+    private static final String PACKAGE_NAME = "com.android.cts.content";
     private static final String CONTENT_PKG_NAME = "com.android.cts.content";
     private static final String ACTIVITY_ACTION_NAME = "android.intent.action.PMTEST";
     private static final String MAIN_ACTION_NAME = "android.intent.action.MAIN";
@@ -395,7 +395,7 @@
 
     public void testOpPermission() {
         PermissionInfo permissionInfo = new PermissionInfo();
-        String permissionName = "com.android.cts.stub.permission.TEST_DYNAMIC.ADD";
+        String permissionName = "com.android.cts.content.permission.TEST_DYNAMIC.ADD";
         permissionInfo.name = permissionName;
         permissionInfo.labelRes = R.string.permlab_testDynamic;
         permissionInfo.nonLocalizedLabel = "Test Tree";
@@ -450,7 +450,7 @@
     public void testGetResources() throws NameNotFoundException {
         ComponentName componentName = new ComponentName(PACKAGE_NAME, ACTIVITY_NAME);
         int resourceId = R.xml.pm_test;
-        String xmlName = "com.android.cts.stub:xml/pm_test";
+        String xmlName = "com.android.cts.content:xml/pm_test";
         ApplicationInfo appInfo = mPackageManager.getApplicationInfo(PACKAGE_NAME, 0);
         assertNotNull(mPackageManager.getXml(PACKAGE_NAME, resourceId, appInfo));
         assertEquals(xmlName, mPackageManager.getResourcesForActivity(componentName)
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageStatsTest.java b/tests/tests/content/src/android/content/pm/cts/PackageStatsTest.java
index dca51e9..6425209 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageStatsTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageStatsTest.java
@@ -22,7 +22,7 @@
 import android.test.AndroidTestCase;
 
 public class PackageStatsTest extends AndroidTestCase {
-    private static final String PACKAGE_NAME = "com.android.cts.stub";
+    private static final String PACKAGE_NAME = "com.android.cts.content";
 
     public void testPackageStats() {
         // Set mock data to make sure the functionality of constructor
diff --git a/tests/tests/content/src/android/content/pm/cts/ProviderInfoTest.java b/tests/tests/content/src/android/content/pm/cts/ProviderInfoTest.java
index c585568..6256a69 100644
--- a/tests/tests/content/src/android/content/pm/cts/ProviderInfoTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/ProviderInfoTest.java
@@ -28,7 +28,7 @@
 import java.util.List;
 
 public class ProviderInfoTest extends AndroidTestCase {
-    private static final String PACKAGE_NAME = "com.android.cts.stub";
+    private static final String PACKAGE_NAME = "com.android.cts.content";
     private static final String PROVIDER_NAME = "android.content.cts.MockContentProvider";
 
     public void testProviderInfo() throws NameNotFoundException {
diff --git a/tests/tests/content/src/android/content/pm/cts/ResolveInfoTest.java b/tests/tests/content/src/android/content/pm/cts/ResolveInfoTest.java
index 3501e86..af3f161 100644
--- a/tests/tests/content/src/android/content/pm/cts/ResolveInfoTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/ResolveInfoTest.java
@@ -26,7 +26,7 @@
 import android.util.Printer;
 
 public class ResolveInfoTest extends AndroidTestCase {
-    private static final String PACKAGE_NAME = "com.android.cts.stub";
+    private static final String PACKAGE_NAME = "com.android.cts.content";
     private static final String MAIN_ACTION_NAME = "android.intent.action.MAIN";
     private static final String ACTIVITY_NAME = "android.content.pm.cts.TestPmActivity";
     private static final String SERVICE_NAME = "android.content.pm.cts.activity.PMTEST_SERVICE";
diff --git a/tests/tests/content/src/android/content/pm/cts/ServiceInfoTest.java b/tests/tests/content/src/android/content/pm/cts/ServiceInfoTest.java
index 8508c15..297ab69 100644
--- a/tests/tests/content/src/android/content/pm/cts/ServiceInfoTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/ServiceInfoTest.java
@@ -25,7 +25,7 @@
 import android.test.AndroidTestCase;
 
 public class ServiceInfoTest extends AndroidTestCase {
-    private static final String PACKAGE_NAME = "com.android.cts.stub";
+    private static final String PACKAGE_NAME = "com.android.cts.content";
     private static final String SERVICE_NAME = "android.content.pm.cts.TestPmService";
 
     public void testServiceInfo() throws NameNotFoundException {
diff --git a/tests/tests/content/src/android/content/res/cts/ArrayTest.java b/tests/tests/content/src/android/content/res/cts/ArrayTest.java
index 1b1fcdf..909fbf6 100644
--- a/tests/tests/content/src/android/content/res/cts/ArrayTest.java
+++ b/tests/tests/content/src/android/content/res/cts/ArrayTest.java
@@ -20,7 +20,7 @@
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
-import com.android.cts.stub.R;
+import com.android.cts.content.R;
 
 public class ArrayTest extends AndroidTestCase {
     private Resources mResources;
diff --git a/tests/tests/content/src/android/content/res/cts/AssetManagerTest.java b/tests/tests/content/src/android/content/res/cts/AssetManagerTest.java
index cbf20ec..2870fee 100644
--- a/tests/tests/content/src/android/content/res/cts/AssetManagerTest.java
+++ b/tests/tests/content/src/android/content/res/cts/AssetManagerTest.java
@@ -30,7 +30,7 @@
 import android.test.AndroidTestCase;
 import android.util.TypedValue;
 
-import com.android.cts.stub.R;
+import com.android.cts.content.R;
 import com.android.internal.util.XmlUtils;
 
 
diff --git a/tests/tests/content/src/android/content/res/cts/AssetManager_AssetInputStreamTest.java b/tests/tests/content/src/android/content/res/cts/AssetManager_AssetInputStreamTest.java
index 0100a7a..32c1a3a 100644
--- a/tests/tests/content/src/android/content/res/cts/AssetManager_AssetInputStreamTest.java
+++ b/tests/tests/content/src/android/content/res/cts/AssetManager_AssetInputStreamTest.java
@@ -42,8 +42,12 @@
     }
 
     public void testGetAssetInt() {
-        // the return value of getAssetInt is a random number
-        mAssetInputStream.getAssetInt();
+        try {
+            // getAssetInt is no longer supported.
+            mAssetInputStream.getAssetInt();
+            fail();
+        } catch (UnsupportedOperationException expected) {
+        }
     }
 
     public void testMarkReset() throws IOException {
diff --git a/tests/tests/content/src/android/content/res/cts/ColorStateListTest.java b/tests/tests/content/src/android/content/res/cts/ColorStateListTest.java
index cd1ac8b..88f5798 100644
--- a/tests/tests/content/src/android/content/res/cts/ColorStateListTest.java
+++ b/tests/tests/content/src/android/content/res/cts/ColorStateListTest.java
@@ -27,7 +27,7 @@
 import android.os.Parcel;
 import android.test.AndroidTestCase;
 
-import com.android.cts.stub.R;
+import com.android.cts.content.R;
 
 
 public class ColorStateListTest extends AndroidTestCase {
diff --git a/tests/tests/content/src/android/content/res/cts/ConfigTest.java b/tests/tests/content/src/android/content/res/cts/ConfigTest.java
index bcfabe1..0b94b6f 100644
--- a/tests/tests/content/src/android/content/res/cts/ConfigTest.java
+++ b/tests/tests/content/src/android/content/res/cts/ConfigTest.java
@@ -16,6 +16,8 @@
 
 package android.content.res.cts;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Locale;
 
 import android.content.res.AssetManager;
@@ -29,12 +31,14 @@
 import android.util.DisplayMetrics;
 import android.util.Log;
 
-import com.android.cts.stub.R;
+import com.android.cts.content.R;
 
 public class ConfigTest extends AndroidTestCase {
     enum Properties {
         LANGUAGE,
         COUNTRY,
+        SCRIPT,
+        VARIANT,
         MCC,
         MNC,
         TOUCHSCREEN,
@@ -88,7 +92,7 @@
         public TotalConfig() {
             mConfig = new Configuration();
             mMetrics = new DisplayMetrics();
-            mConfig.locale = new Locale("++", "++");
+            mConfig.locale = Locale.ROOT;
         }
 
         public void setProperty(final Properties p, final int value) {
@@ -149,12 +153,28 @@
         public void setProperty(final Properties p, final String value) {
             switch(p) {
                 case LANGUAGE:
-                    final String oldCountry = mConfig.locale.getCountry();
-                    mConfig.locale = new Locale(value, oldCountry);
+                    mConfig.locale = new Locale.Builder()
+                            .setLocale(mConfig.locale)
+                            .setLanguage(value)
+                            .build();
                     break;
                 case COUNTRY:
-                    final String oldLanguage = mConfig.locale.getLanguage();
-                    mConfig.locale = new Locale(oldLanguage, value);
+                    mConfig.locale = new Locale.Builder()
+                            .setLocale(mConfig.locale)
+                            .setRegion(value)
+                            .build();
+                    break;
+                case SCRIPT:
+                    mConfig.locale = new Locale.Builder()
+                            .setLocale(mConfig.locale)
+                            .setScript(value)
+                            .build();
+                    break;
+                case VARIANT:
+                    mConfig.locale = new Locale.Builder()
+                            .setLocale(mConfig.locale)
+                            .setVariant(value)
+                            .build();
                     break;
                 default:
                     assert(false);
@@ -1131,4 +1151,133 @@
         assertEquals("base",  mContext.getResources().getString(R.string.version_old));
         assertEquals("v3",  mContext.getResources().getString(R.string.version_v3));
     }
+
+    @MediumTest
+    public void testExtendedLocales() {
+        TotalConfig config = makeClassicConfig();
+        // BCP 47 Locale kok
+        config.setProperty(Properties.LANGUAGE, "kok");
+        Resources res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple kok");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag kok"});
+
+        // BCP 47 Locale kok-IN
+        config.setProperty(Properties.COUNTRY, "IN");
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple kok IN");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag kok IN"});
+
+        // BCP 47 Locale kok-419
+        config.setProperty(Properties.COUNTRY, "419");
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple kok 419");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag kok 419"});
+
+
+        // BCP 47 Locale kok-419-VARIANT
+        config.setProperty(Properties.VARIANT, "VARIANT");
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple kok 419 VARIANT");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag kok 419 VARIANT"});
+
+        // BCP 47 Locale kok-Knda
+        config = makeClassicConfig();
+        config.setProperty(Properties.LANGUAGE, "kok");
+        config.setProperty(Properties.SCRIPT, "Knda");
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple kok Knda");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag kok Knda"});
+
+        // BCP 47 Locale kok-Knda-419
+        config.setProperty(Properties.COUNTRY, "419");
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple kok Knda 419");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag kok Knda 419"});
+
+        // BCP 47 Locale kok-Knda-419-VARIANT
+        config.setProperty(Properties.VARIANT, "VARIANT");
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple kok Knda 419 VARIANT");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag kok Knda 419 VARIANT"});
+
+        // BCP 47 Locale kok-VARIANT
+        config = makeClassicConfig();
+        config.setProperty(Properties.LANGUAGE, "kok");
+        config.setProperty(Properties.VARIANT, "VARIANT");
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple kok VARIANT");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag kok VARIANT"});
+    }
+
+    @MediumTest
+    public void testTlAndFilConversion() {
+        TotalConfig config = makeClassicConfig();
+
+        // Ensure that "fil" is mapped to "tl" correctly.
+        config.setProperty(Properties.LANGUAGE, "fil");
+        config.setProperty(Properties.COUNTRY, "US");
+        Resources res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple tl");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[] { "bag tl" });
+
+        // Ensure that "fil-PH" is mapped to "tl-PH" correctly.
+        config = makeClassicConfig();
+        config.setProperty(Properties.LANGUAGE, "fil");
+        config.setProperty(Properties.COUNTRY, "PH");
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple tl PH");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[] { "bag tl PH" });
+
+        config = makeClassicConfig();
+        config.setProperty(Properties.LANGUAGE, "tgl");
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple tgl");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[] { "bag tgl" });
+
+        config = makeClassicConfig();
+        config.setProperty(Properties.LANGUAGE, "tgl");
+        config.setProperty(Properties.COUNTRY, "PH");
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple tgl PH");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[] { "bag tgl PH" });
+    }
+
+    @MediumTest
+    public void testGetLocalesConvertsTlToFil() {
+        TotalConfig config = makeClassicConfig();
+
+        // Check that the list of locales doesn't contain any of the
+        // "tl" variants. They should've been converted to "fil"
+        // locales.
+        AssetManager am = config.getResources().getAssets();
+        String[] locales = am.getLocales();
+        final List<String> tlLocales = new ArrayList<String>(4);
+        final List<String> filLocales = new ArrayList<String>(4);
+        for (String locale : locales) {
+            if (locale.startsWith("tl-") || locale.equals("tl")) {
+                tlLocales.add(locale);
+            }
+
+            if (locale.startsWith("fil-") || locale.equals("fil")) {
+                filLocales.add(locale);
+            }
+        }
+
+        assertEquals(0, tlLocales.size());
+        assertEquals(2, filLocales.size());
+        assertTrue(filLocales.contains("fil"));
+        assertTrue(filLocales.contains("fil-PH"));
+    }
 }
diff --git a/tests/tests/content/src/android/content/res/cts/FractionTest.java b/tests/tests/content/src/android/content/res/cts/FractionTest.java
index 9fa896c..2c3e797 100644
--- a/tests/tests/content/src/android/content/res/cts/FractionTest.java
+++ b/tests/tests/content/src/android/content/res/cts/FractionTest.java
@@ -20,7 +20,7 @@
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.TypedValue;
-import com.android.cts.stub.R;
+import com.android.cts.content.R;
 
 public class FractionTest extends AndroidTestCase {
 
diff --git a/tests/tests/content/src/android/content/res/cts/PluralResourcesTest.java b/tests/tests/content/src/android/content/res/cts/PluralResourcesTest.java
index 074d10a..1fd204d 100644
--- a/tests/tests/content/src/android/content/res/cts/PluralResourcesTest.java
+++ b/tests/tests/content/src/android/content/res/cts/PluralResourcesTest.java
@@ -25,7 +25,7 @@
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
 
-import com.android.cts.stub.R;
+import com.android.cts.content.R;
 
 public class PluralResourcesTest extends AndroidTestCase {
     public static boolean DEBUG = false;
diff --git a/tests/tests/content/src/android/content/res/cts/PrimitiveTest.java b/tests/tests/content/src/android/content/res/cts/PrimitiveTest.java
index c7da6d8d..8eeb086 100644
--- a/tests/tests/content/src/android/content/res/cts/PrimitiveTest.java
+++ b/tests/tests/content/src/android/content/res/cts/PrimitiveTest.java
@@ -21,7 +21,7 @@
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.TypedValue;
-import com.android.cts.stub.R;
+import com.android.cts.content.R;
 
 public class PrimitiveTest extends AndroidTestCase {
     private Resources mResources;
diff --git a/tests/tests/content/src/android/content/res/cts/RawResourceTest.java b/tests/tests/content/src/android/content/res/cts/RawResourceTest.java
index 9c8dae0..c92efc7 100644
--- a/tests/tests/content/src/android/content/res/cts/RawResourceTest.java
+++ b/tests/tests/content/src/android/content/res/cts/RawResourceTest.java
@@ -19,7 +19,7 @@
 import android.content.res.Resources;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
-import com.android.cts.stub.R;
+import com.android.cts.content.R;
 
 import java.io.IOException;
 import java.io.InputStream;
diff --git a/tests/tests/content/src/android/content/res/cts/ResourceNameTest.java b/tests/tests/content/src/android/content/res/cts/ResourceNameTest.java
index eacf00d..a7cc03b 100644
--- a/tests/tests/content/src/android/content/res/cts/ResourceNameTest.java
+++ b/tests/tests/content/src/android/content/res/cts/ResourceNameTest.java
@@ -20,7 +20,7 @@
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
-import com.android.cts.stub.R;
+import com.android.cts.content.R;
 
 public class ResourceNameTest extends AndroidTestCase {
 
@@ -29,10 +29,10 @@
         final Resources res = mContext.getResources();
 
         final String fullName = res.getResourceName(R.configVarying.simple);
-        assertEquals("com.android.cts.stub:configVarying/simple", fullName);
+        assertEquals("com.android.cts.content:configVarying/simple", fullName);
 
         final String packageName = res.getResourcePackageName(R.configVarying.simple);
-        assertEquals("com.android.cts.stub", packageName);
+        assertEquals("com.android.cts.content", packageName);
 
         final String typeName = res.getResourceTypeName(R.configVarying.simple);
         assertEquals("configVarying", typeName);
@@ -45,16 +45,16 @@
     public void testGetResourceIdentifier() {
         final Resources res = mContext.getResources();
         int resid = res.getIdentifier(
-                "com.android.cts.stub:configVarying/simple",
+                "com.android.cts.content:configVarying/simple",
                 null, null);
         assertEquals(R.configVarying.simple, resid);
 
         resid = res.getIdentifier("configVarying/simple", null,
-                "com.android.cts.stub");
+                "com.android.cts.content");
         assertEquals(R.configVarying.simple, resid);
 
         resid = res.getIdentifier("simple", "configVarying",
-                "com.android.cts.stub");
+                "com.android.cts.content");
         assertEquals(R.configVarying.simple, resid);
     }
 }
diff --git a/tests/tests/content/src/android/content/res/cts/ResourcesTest.java b/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
index 058076c..88caa6f 100644
--- a/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
+++ b/tests/tests/content/src/android/content/res/cts/ResourcesTest.java
@@ -16,7 +16,7 @@
 
 package android.content.res.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.content.R;
 import com.android.internal.util.XmlUtils;
 
 
@@ -49,9 +49,9 @@
     private static final String CONFIG_VARYING = "configVarying";
     private static final String SIMPLE = "simple";
     private static final String CONFIG_VARYING_SIMPLE = "configVarying/simple";
-    private static final String PACKAGE_NAME = "com.android.cts.stub";
+    private static final String PACKAGE_NAME = "com.android.cts.content";
     private static final String COM_ANDROID_CTS_STUB_IDENTIFIER =
-                "com.android.cts.stub:configVarying/simple";
+                "com.android.cts.content:configVarying/simple";
     private Resources mResources;
 
     @Override
@@ -320,7 +320,7 @@
             //expected
         }
 
-        mResources.getValue("com.android.cts.stub:raw/text", tv, false);
+        mResources.getValue("com.android.cts.content:raw/text", tv, false);
         assertNotNull(tv);
         assertEquals("res/raw/text.txt", tv.coerceToString());
     }
diff --git a/tests/tests/content/src/android/content/res/cts/Resources_ThemeTest.java b/tests/tests/content/src/android/content/res/cts/Resources_ThemeTest.java
index 4a4991f..349cb47 100644
--- a/tests/tests/content/src/android/content/res/cts/Resources_ThemeTest.java
+++ b/tests/tests/content/src/android/content/res/cts/Resources_ThemeTest.java
@@ -26,7 +26,7 @@
 import android.util.TypedValue;
 import android.util.Xml;
 
-import com.android.cts.stub.R;
+import com.android.cts.content.R;
 
 
 public class Resources_ThemeTest extends AndroidTestCase {
diff --git a/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java b/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java
index c51405a..cc6c5ec 100644
--- a/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java
+++ b/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java
@@ -27,7 +27,7 @@
 import android.util.TypedValue;
 import android.view.ContextThemeWrapper;
 
-import com.android.cts.stub.R;
+import com.android.cts.content.R;
 import com.android.internal.util.XmlUtils;
 
 
diff --git a/tests/tests/database/AndroidManifest.xml b/tests/tests/database/AndroidManifest.xml
index 602f783..fefcc1f 100644
--- a/tests/tests/database/AndroidManifest.xml
+++ b/tests/tests/database/AndroidManifest.xml
@@ -23,9 +23,12 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.cts.database"
-                     android:label="CTS tests of android.database"/>
+                     android:label="CTS tests of android.database">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/tests/database/src/android/database/sqlite/cts/SQLiteQueryBuilderTest.java b/tests/tests/database/src/android/database/sqlite/cts/SQLiteQueryBuilderTest.java
index 09903df..97b0b8f 100644
--- a/tests/tests/database/src/android/database/sqlite/cts/SQLiteQueryBuilderTest.java
+++ b/tests/tests/database/src/android/database/sqlite/cts/SQLiteQueryBuilderTest.java
@@ -109,15 +109,19 @@
 
         sql = sqliteQueryBuilder.buildQuery(null, // projectionIn is null
                 null, null, null, null, null, null);
-        // TODO: implement an order-independent way of doing the projection columns comparison
-        expected = "SELECT age, name, address FROM " + TEST_TABLE_NAME;
-        assertEquals(expected, sql);
+        assertTrue(sql.matches("SELECT (age|name|address), (age|name|address), (age|name|address) "
+                + "FROM " + TEST_TABLE_NAME));
+        assertTrue(sql.contains("age"));
+        assertTrue(sql.contains("name"));
+        assertTrue(sql.contains("address"));
 
         sqliteQueryBuilder.setProjectionMap(null);
         sql = sqliteQueryBuilder.buildQuery(new String[] { "name", "address" },
                 null, null, null, null, null, null);
-        expected = "SELECT name, address FROM " + TEST_TABLE_NAME;
-        assertEquals(expected, sql);
+        assertTrue(sql.matches("SELECT (name|address), (name|address) "
+                + "FROM " + TEST_TABLE_NAME));
+        assertTrue(sql.contains("name"));
+        assertTrue(sql.contains("address"));
     }
 
     public void testSetCursorFactory() {
diff --git a/tests/tests/deqp/Android.mk b/tests/tests/deqp/Android.mk
new file mode 100644
index 0000000..d8a4dda
--- /dev/null
+++ b/tests/tests/deqp/Android.mk
@@ -0,0 +1,26 @@
+# 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.
+
+# Dummy target to make dEQP test list generation consistent with other tests.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# All APIs share the same package
+LOCAL_PACKAGE_NAME := com.drawelements.deqp
+
+include $(LOCAL_PATH)/deqp_gles2.mk
+include $(LOCAL_PATH)/deqp_gles3.mk
+include $(LOCAL_PATH)/deqp_gles31.mk
diff --git a/tests/tests/deqp/deqp_gles2.mk b/tests/tests/deqp/deqp_gles2.mk
new file mode 100644
index 0000000..3cd60da
--- /dev/null
+++ b/tests/tests/deqp/deqp_gles2.mk
@@ -0,0 +1,21 @@
+# 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.
+
+# Dummy target to make dEQP GLES2 test list generation consistent with other
+# tests.
+
+DEQP_API := gles2
+DEQP_TEST_NAME := dEQP-GLES2
+
+include $(BUILD_CTS_DEQP_PACKAGE)
diff --git a/tests/tests/deqp/deqp_gles3.mk b/tests/tests/deqp/deqp_gles3.mk
new file mode 100644
index 0000000..07dfdae
--- /dev/null
+++ b/tests/tests/deqp/deqp_gles3.mk
@@ -0,0 +1,21 @@
+# 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.
+
+# Dummy target to make dEQP GLES3 test list generation consistent with other
+# tests.
+
+DEQP_API := gles3
+DEQP_TEST_NAME := dEQP-GLES3
+
+include $(BUILD_CTS_DEQP_PACKAGE)
diff --git a/tests/tests/deqp/deqp_gles31.mk b/tests/tests/deqp/deqp_gles31.mk
new file mode 100644
index 0000000..7e45413
--- /dev/null
+++ b/tests/tests/deqp/deqp_gles31.mk
@@ -0,0 +1,21 @@
+# 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.
+
+# Dummy target to make dEQP GLES31 test list generation consistent with other
+# tests.
+
+DEQP_API := gles31
+DEQP_TEST_NAME := dEQP-GLES31
+
+include $(BUILD_CTS_DEQP_PACKAGE)
diff --git a/tests/tests/display/Android.mk b/tests/tests/display/Android.mk
index ec5b40d..a48a8e3 100644
--- a/tests/tests/display/Android.mk
+++ b/tests/tests/display/Android.mk
@@ -21,8 +21,6 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/display/AndroidManifest.xml b/tests/tests/display/AndroidManifest.xml
index d1386d1..0b24754 100644
--- a/tests/tests/display/AndroidManifest.xml
+++ b/tests/tests/display/AndroidManifest.xml
@@ -24,9 +24,13 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.cts.display"
-                     android:label="CTS tests of android.view.display"/>
+                     android:label="CTS tests of android.view.display">
+        <meta-data
+            android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/tests/dpi/Android.mk b/tests/tests/dpi/Android.mk
index a9dbcc3..4c05ecf 100644
--- a/tests/tests/dpi/Android.mk
+++ b/tests/tests/dpi/Android.mk
@@ -17,8 +17,6 @@
 
 include $(CLEAR_VARS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
@@ -44,8 +42,6 @@
 
 LOCAL_MODULE_TAGS := optional
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_MODULE := android.cts.dpi
 
 include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tests/tests/dpi/AndroidManifest.xml b/tests/tests/dpi/AndroidManifest.xml
index bacfe4a..0197056 100644
--- a/tests/tests/dpi/AndroidManifest.xml
+++ b/tests/tests/dpi/AndroidManifest.xml
@@ -26,7 +26,10 @@
                 android:configChanges="orientation" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.cts.dpi"
-                     android:label="CTS tests for DPI"/>
+                     android:label="CTS tests for DPI">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 </manifest>
diff --git a/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java b/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java
index e2f75c6..82e3204 100644
--- a/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java
+++ b/tests/tests/dpi/src/android/dpi/cts/ConfigurationTest.java
@@ -60,6 +60,7 @@
         allowedDensities.add(DisplayMetrics.DENSITY_XHIGH);
         allowedDensities.add(DisplayMetrics.DENSITY_400);
         allowedDensities.add(DisplayMetrics.DENSITY_XXHIGH);
+        allowedDensities.add(DisplayMetrics.DENSITY_560);
         allowedDensities.add(DisplayMetrics.DENSITY_XXXHIGH);
         assertTrue("DisplayMetrics#densityDpi must be one of the DisplayMetrics.DENSITY_* values: "
                 + allowedDensities, allowedDensities.contains(metrics.densityDpi));
diff --git a/tests/tests/dpi2/Android.mk b/tests/tests/dpi2/Android.mk
index 92ba992..03a687d 100644
--- a/tests/tests/dpi2/Android.mk
+++ b/tests/tests/dpi2/Android.mk
@@ -17,7 +17,6 @@
 
 include $(CLEAR_VARS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
 # We use the DefaultManifestAttributesTest from the android.cts.dpi package.
 LOCAL_STATIC_JAVA_LIBRARIES := android.cts.dpi ctstestrunner
 
@@ -29,8 +28,6 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-# We would set LOCAL_SDK_VERSION := 3 here, but the build system
-# doesn't currently support setting LOCAL_SDK_VERSION to anything but
-# current.
+LOCAL_SDK_VERSION := current
 
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/dpi2/AndroidManifest.xml b/tests/tests/dpi2/AndroidManifest.xml
index 0364b10..6dbdc23 100644
--- a/tests/tests/dpi2/AndroidManifest.xml
+++ b/tests/tests/dpi2/AndroidManifest.xml
@@ -27,7 +27,10 @@
          properly for the screen size attributes. -->
     <uses-sdk android:targetSdkVersion="3" />
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.cts.dpi2"
-                     android:label="CTS tests for DPI"/>
+                     android:label="CTS tests for DPI">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 </manifest>
diff --git a/tests/tests/dreams/Android.mk b/tests/tests/dreams/Android.mk
index c630d8a..eca3d83 100644
--- a/tests/tests/dreams/Android.mk
+++ b/tests/tests/dreams/Android.mk
@@ -24,14 +24,11 @@
 # When built, explicitly put it in the data partition.
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-# All tests should include android.test.runner.
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-# Need access to ServiceManager
+# Need access to ServiceManager - see b/13307221
 #LOCAL_SDK_VERSION := current
 
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/dreams/AndroidManifest.xml b/tests/tests/dreams/AndroidManifest.xml
index fb3e564..b395a4f 100644
--- a/tests/tests/dreams/AndroidManifest.xml
+++ b/tests/tests/dreams/AndroidManifest.xml
@@ -22,9 +22,12 @@
     </application>
 
     <!-- This is a self-instrumenting test package. -->
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.cts.dreams"
-                     android:label="CTS tests for the android.service.dreams package"/>
+                     android:label="CTS tests for the android.service.dreams package">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/tests/drm/Android.mk b/tests/tests/drm/Android.mk
index 8b76cd8..6272e9c 100644
--- a/tests/tests/drm/Android.mk
+++ b/tests/tests/drm/Android.mk
@@ -16,27 +16,25 @@
 
 include $(CLEAR_VARS)
 
+# Include both the 32 and 64 bit versions of libs
+LOCAL_MULTILIB := both
+
 LOCAL_MODULE_TAGS := tests
 
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsDrmTestCases
 
-LOCAL_INSTRUMENTATION_FOR := CtsTestStubs
-
 LOCAL_JNI_SHARED_LIBRARIES := \
 	libctsdrm_jni \
 	libdrmtestplugin
 
-# uncomment when dalvik.annotation.Test* are removed or part of SDK
-#LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := current
 
 include $(BUILD_CTS_PACKAGE)
 
diff --git a/tests/tests/drm/AndroidManifest.xml b/tests/tests/drm/AndroidManifest.xml
index 1fc8968..527d498 100644
--- a/tests/tests/drm/AndroidManifest.xml
+++ b/tests/tests/drm/AndroidManifest.xml
@@ -22,9 +22,12 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="com.android.cts.stub"
-                     android:label="CTS tests of android.drm"/>
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.drm"
+                     android:label="CTS tests of android.drm">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/tests/effect/Android.mk b/tests/tests/effect/Android.mk
index 9e27769..6a9778e 100644
--- a/tests/tests/effect/Android.mk
+++ b/tests/tests/effect/Android.mk
@@ -24,9 +24,6 @@
 # When built, explicitly put it in the data partition.
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-# All tests should include android.test.runner.
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/effect/AndroidManifest.xml b/tests/tests/effect/AndroidManifest.xml
index 1a346ae..481be14 100644
--- a/tests/tests/effect/AndroidManifest.xml
+++ b/tests/tests/effect/AndroidManifest.xml
@@ -23,9 +23,12 @@
     </application>
 
     <!-- This is a self-instrumenting test package. -->
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.cts.effect"
-                     android:label="CTS tests of android.media.effect component"/>
+                     android:label="CTS tests of android.media.effect component">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/tests/gesture/Android.mk b/tests/tests/gesture/Android.mk
index 5d44cfc..4a97931 100755
--- a/tests/tests/gesture/Android.mk
+++ b/tests/tests/gesture/Android.mk
@@ -21,8 +21,6 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/gesture/AndroidManifest.xml b/tests/tests/gesture/AndroidManifest.xml
index 39e2b90..b288cd2 100755
--- a/tests/tests/gesture/AndroidManifest.xml
+++ b/tests/tests/gesture/AndroidManifest.xml
@@ -24,9 +24,12 @@
     </application>
 
     <!--  self-instrumenting test package. -->
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.cts.gesture"
-                     android:label="CTS tests of android.gesture"/>
+                     android:label="CTS tests of android.gesture">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/tests/graphics/Android.mk b/tests/tests/graphics/Android.mk
index 811267a..773b47d 100644
--- a/tests/tests/graphics/Android.mk
+++ b/tests/tests/graphics/Android.mk
@@ -16,22 +16,14 @@
 
 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_JAVA_LIBRARIES := android.test.runner
-
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsGraphicsTestCases
 
-LOCAL_INSTRUMENTATION_FOR := CtsTestStubs
-
-# uncomment when dalvik.annotation.Test* are removed or part of SDK
-#LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := current
 
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/graphics/AndroidManifest.xml b/tests/tests/graphics/AndroidManifest.xml
index c052a15..0006634 100644
--- a/tests/tests/graphics/AndroidManifest.xml
+++ b/tests/tests/graphics/AndroidManifest.xml
@@ -19,13 +19,45 @@
     package="com.android.cts.graphics">
 
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <application>
         <uses-library android:name="android.test.runner" />
+
+        <activity android:name="android.graphics.cts.ImageViewCtsActivity"
+            android:label="ImageViewCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.graphics.cts.MockActivity" android:label="MockActivity" />
+
+        <activity android:name="android.opengl.cts.CompressedTextureCtsActivity"
+            android:label="CompressedTextureCtsActivity"
+            android:screenOrientation="nosensor">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.opengl.cts.EglConfigCtsActivity"
+            android:configChanges="keyboardHidden|orientation|screenSize|uiMode" />
+
+        <activity android:name="android.opengl.cts.GLSurfaceViewCtsActivity"
+                  android:label="GLSurfaceViewCts"/>
+
+        <activity android:name="android.opengl.cts.OpenGlEsVersionCtsActivity"/>
+
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="com.android.cts.stub"
-                     android:label="CTS tests of android.graphics"/>
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.graphics"
+                     android:label="CTS tests of android.graphics">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/assets/samplefont.ttf b/tests/tests/graphics/assets/samplefont.ttf
similarity index 100%
rename from tests/assets/samplefont.ttf
rename to tests/tests/graphics/assets/samplefont.ttf
Binary files differ
diff --git a/tests/tests/graphics/res/anim/animation_grouping_1_01.xml b/tests/tests/graphics/res/anim/animation_grouping_1_01.xml
new file mode 100644
index 0000000..8cc9f92
--- /dev/null
+++ b/tests/tests/graphics/res/anim/animation_grouping_1_01.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <objectAnimator
+        android:duration="3300"
+        android:propertyName="rotation"
+        android:valueFrom="0"
+        android:valueTo="180"
+        android:repeatCount="-1" />
+</set>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_clip_path_1_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_clip_path_1_golden.png
new file mode 100644
index 0000000..be487d1
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_clip_path_1_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_create_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_create_golden.png
new file mode 100644
index 0000000..943fce5
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_create_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_delete_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_delete_golden.png
new file mode 100644
index 0000000..b46363e
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_delete_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_heart_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_heart_golden.png
new file mode 100644
index 0000000..7450751
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_heart_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_random_path_1_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_random_path_1_golden.png
new file mode 100644
index 0000000..91776a9
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_random_path_1_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_random_path_2_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_random_path_2_golden.png
new file mode 100644
index 0000000..9af40a3
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_random_path_2_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_render_order_1_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_render_order_1_golden.png
new file mode 100644
index 0000000..2fca8eb
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_render_order_1_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_render_order_2_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_render_order_2_golden.png
new file mode 100644
index 0000000..f317901
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_render_order_2_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_1_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_1_golden.png
new file mode 100644
index 0000000..b3acfe7
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_1_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_2_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_2_golden.png
new file mode 100644
index 0000000..bbc84b9
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_a_2_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_cq_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_cq_golden.png
new file mode 100644
index 0000000..8d73cfd
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_cq_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_st_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_st_golden.png
new file mode 100644
index 0000000..6094a9a
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_repeated_st_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_schedule_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_schedule_golden.png
new file mode 100644
index 0000000..9822bc2
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_schedule_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_settings_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_settings_golden.png
new file mode 100644
index 0000000..d12b142
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_settings_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_stroke_1_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_stroke_1_golden.png
new file mode 100644
index 0000000..c57ad20
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_stroke_1_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_stroke_2_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_stroke_2_golden.png
new file mode 100644
index 0000000..aee8ff5
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_stroke_2_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_stroke_3_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_stroke_3_golden.png
new file mode 100644
index 0000000..1212fb3
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_stroke_3_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_transformation_1_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_transformation_1_golden.png
new file mode 100644
index 0000000..baf418d
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_transformation_1_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_transformation_2_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_transformation_2_golden.png
new file mode 100644
index 0000000..e0e14f3
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_transformation_2_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_transformation_3_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_transformation_3_golden.png
new file mode 100644
index 0000000..b6798c2
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_transformation_3_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_transformation_4_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_transformation_4_golden.png
new file mode 100644
index 0000000..a5d4d33
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_transformation_4_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_transformation_5_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_transformation_5_golden.png
new file mode 100644
index 0000000..0d8ded1
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_transformation_5_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable-nodpi/vector_icon_transformation_6_golden.png b/tests/tests/graphics/res/drawable-nodpi/vector_icon_transformation_6_golden.png
new file mode 100644
index 0000000..3da7969
--- /dev/null
+++ b/tests/tests/graphics/res/drawable-nodpi/vector_icon_transformation_6_golden.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable/alpha.png b/tests/tests/graphics/res/drawable/alpha.png
new file mode 100644
index 0000000..8a88548
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/alpha.png
Binary files differ
diff --git a/tests/res/drawable/animated.gif b/tests/tests/graphics/res/drawable/animated.gif
similarity index 100%
rename from tests/res/drawable/animated.gif
rename to tests/tests/graphics/res/drawable/animated.gif
Binary files differ
diff --git a/tests/tests/graphics/res/drawable/animation_vector_drawable_grouping_1.xml b/tests/tests/graphics/res/drawable/animation_vector_drawable_grouping_1.xml
new file mode 100644
index 0000000..4a7e4f6
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/animation_vector_drawable_grouping_1.xml
@@ -0,0 +1,26 @@
+<!--
+ 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.
+-->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:drawable="@drawable/vector_drawable_grouping_1" >
+
+    <target
+        android:name="sun"
+        android:animation="@anim/animation_grouping_1_01" />
+    <target
+        android:name="earth"
+        android:animation="@anim/animation_grouping_1_01" />
+
+</animated-vector>
\ No newline at end of file
diff --git a/tests/res/drawable/animationdrawable.xml b/tests/tests/graphics/res/drawable/animationdrawable.xml
similarity index 100%
rename from tests/res/drawable/animationdrawable.xml
rename to tests/tests/graphics/res/drawable/animationdrawable.xml
diff --git a/tests/res/drawable/baseline_jpeg.jpg b/tests/tests/graphics/res/drawable/baseline_jpeg.jpg
similarity index 100%
rename from tests/res/drawable/baseline_jpeg.jpg
rename to tests/tests/graphics/res/drawable/baseline_jpeg.jpg
Binary files differ
diff --git a/tests/res/drawable/baseline_restart_jpeg.jpg b/tests/tests/graphics/res/drawable/baseline_restart_jpeg.jpg
similarity index 100%
rename from tests/res/drawable/baseline_restart_jpeg.jpg
rename to tests/tests/graphics/res/drawable/baseline_restart_jpeg.jpg
Binary files differ
diff --git a/tests/tests/graphics/res/drawable/bitmapdrawable_theme.xml b/tests/tests/graphics/res/drawable/bitmapdrawable_theme.xml
new file mode 100644
index 0000000..6df36b3
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/bitmapdrawable_theme.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:antialias="?attr/themeBoolean"
+    android:autoMirrored="?attr/themeBoolean"
+    android:dither="?attr/themeBoolean"
+    android:filter="?attr/themeBoolean"
+    android:gravity="?attr/themeGravity"
+    android:mipMap="?attr/themeBoolean"
+    android:src="?attr/themeBitmap"
+    android:tileMode="?attr/themeTileMode" />
diff --git a/tests/res/drawable/bmp_test.bmp b/tests/tests/graphics/res/drawable/bmp_test.bmp
similarity index 100%
rename from tests/res/drawable/bmp_test.bmp
rename to tests/tests/graphics/res/drawable/bmp_test.bmp
Binary files differ
diff --git a/tests/res/drawable/colordrawable_test.xml b/tests/tests/graphics/res/drawable/colordrawable_test.xml
similarity index 100%
rename from tests/res/drawable/colordrawable_test.xml
rename to tests/tests/graphics/res/drawable/colordrawable_test.xml
diff --git a/tests/tests/graphics/res/drawable/colordrawable_theme.xml b/tests/tests/graphics/res/drawable/colordrawable_theme.xml
new file mode 100644
index 0000000..00c6fe7
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/colordrawable_theme.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<color xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="?attr/themeColor" />
diff --git a/tests/res/drawable/colorstatelist_test.xml b/tests/tests/graphics/res/drawable/colorstatelist_test.xml
similarity index 100%
rename from tests/res/drawable/colorstatelist_test.xml
rename to tests/tests/graphics/res/drawable/colorstatelist_test.xml
diff --git a/tests/res/drawable/faces.jpg b/tests/tests/graphics/res/drawable/faces.jpg
similarity index 100%
copy from tests/res/drawable/faces.jpg
copy to tests/tests/graphics/res/drawable/faces.jpg
Binary files differ
diff --git a/tests/res/drawable/failed.jpg b/tests/tests/graphics/res/drawable/failed.jpg
similarity index 100%
copy from tests/res/drawable/failed.jpg
copy to tests/tests/graphics/res/drawable/failed.jpg
Binary files differ
diff --git a/tests/res/drawable/gif_test.gif b/tests/tests/graphics/res/drawable/gif_test.gif
similarity index 100%
rename from tests/res/drawable/gif_test.gif
rename to tests/tests/graphics/res/drawable/gif_test.gif
Binary files differ
diff --git a/tests/tests/graphics/res/drawable/google_logo_1.png b/tests/tests/graphics/res/drawable/google_logo_1.png
new file mode 100644
index 0000000..6e038fc
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/google_logo_1.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable/google_logo_2.webp b/tests/tests/graphics/res/drawable/google_logo_2.webp
new file mode 100644
index 0000000..f92c42b
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/google_logo_2.webp
Binary files differ
diff --git a/tests/res/drawable/gradientdrawable.xml b/tests/tests/graphics/res/drawable/gradientdrawable.xml
similarity index 100%
rename from tests/res/drawable/gradientdrawable.xml
rename to tests/tests/graphics/res/drawable/gradientdrawable.xml
diff --git a/tests/tests/graphics/res/drawable/gradientdrawable_radius_base.xml b/tests/tests/graphics/res/drawable/gradientdrawable_radius_base.xml
new file mode 100644
index 0000000..ecd50f8
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/gradientdrawable_radius_base.xml
@@ -0,0 +1,39 @@
+<?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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <gradient
+        android:centerColor="#ffff0000"
+        android:endColor="#0000ffff"
+        android:gradientRadius="50%"
+        android:startColor="#ffffffff"
+        android:type="radial" />
+
+    <corners android:radius="8px" />
+
+    <padding
+        android:bottom="10px"
+        android:left="4px"
+        android:right="6px"
+        android:top="2px" />
+
+    <size
+        android:height="50px"
+        android:width="50px" />
+
+</shape>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/gradientdrawable_radius_parent.xml b/tests/tests/graphics/res/drawable/gradientdrawable_radius_parent.xml
new file mode 100644
index 0000000..73d116a
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/gradientdrawable_radius_parent.xml
@@ -0,0 +1,39 @@
+<?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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <gradient
+        android:centerColor="#ffff0000"
+        android:endColor="#0000ffff"
+        android:gradientRadius="50%p"
+        android:startColor="#ffffffff"
+        android:type="radial" />
+
+    <corners android:radius="8px" />
+
+    <padding
+        android:bottom="10px"
+        android:left="4px"
+        android:right="6px"
+        android:top="2px" />
+
+    <size
+        android:height="50px"
+        android:width="50px" />
+
+</shape>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/gradientdrawable_theme.xml b/tests/tests/graphics/res/drawable/gradientdrawable_theme.xml
new file mode 100644
index 0000000..68cec62
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/gradientdrawable_theme.xml
@@ -0,0 +1,50 @@
+<?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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <corners
+        android:bottomLeftRadius="?attr/themeDimension"
+        android:bottomRightRadius="?attr/themeDimension"
+        android:topLeftRadius="?attr/themeDimension"
+        android:topRightRadius="?attr/themeDimension" />
+
+    <gradient
+        android:angle="?attr/themeAngle"
+        android:centerColor="?attr/themeColor"
+        android:centerX="?attr/themeFloat"
+        android:centerY="?attr/themeFloat"
+        android:endColor="?attr/themeColor"
+        android:gradientRadius="?attr/themeFloat"
+        android:startColor="?attr/themeColor"
+        android:useLevel="?attr/themeBoolean" />
+
+    <padding
+        android:bottom="?attr/themeDimension"
+        android:left="?attr/themeDimension"
+        android:right="?attr/themeDimension"
+        android:top="?attr/themeDimension" />
+
+    <size
+        android:height="?attr/themeDimension"
+        android:width="?attr/themeDimension" />
+
+    <solid android:color="?attr/themeColor" />
+
+    <stroke android:color="?attr/themeColor" />
+
+</shape>
diff --git a/tests/res/drawable/ic_cts_minitab_selected.png b/tests/tests/graphics/res/drawable/ic_cts_minitab_selected.png
similarity index 100%
copy from tests/res/drawable/ic_cts_minitab_selected.png
copy to tests/tests/graphics/res/drawable/ic_cts_minitab_selected.png
Binary files differ
diff --git a/tests/res/drawable/ic_cts_selected.png b/tests/tests/graphics/res/drawable/ic_cts_selected.png
similarity index 100%
copy from tests/res/drawable/ic_cts_selected.png
copy to tests/tests/graphics/res/drawable/ic_cts_selected.png
Binary files differ
diff --git a/tests/res/drawable/icon_black.jpg b/tests/tests/graphics/res/drawable/icon_black.jpg
similarity index 100%
copy from tests/res/drawable/icon_black.jpg
copy to tests/tests/graphics/res/drawable/icon_black.jpg
Binary files differ
diff --git a/tests/res/drawable/icon_blue.jpg b/tests/tests/graphics/res/drawable/icon_blue.jpg
similarity index 100%
copy from tests/res/drawable/icon_blue.jpg
copy to tests/tests/graphics/res/drawable/icon_blue.jpg
Binary files differ
diff --git a/tests/res/drawable/icon_green.jpg b/tests/tests/graphics/res/drawable/icon_green.jpg
similarity index 100%
copy from tests/res/drawable/icon_green.jpg
copy to tests/tests/graphics/res/drawable/icon_green.jpg
Binary files differ
diff --git a/tests/res/drawable/icon_red.jpg b/tests/tests/graphics/res/drawable/icon_red.jpg
similarity index 100%
copy from tests/res/drawable/icon_red.jpg
copy to tests/tests/graphics/res/drawable/icon_red.jpg
Binary files differ
diff --git a/tests/res/drawable/icon_yellow.jpg b/tests/tests/graphics/res/drawable/icon_yellow.jpg
similarity index 100%
copy from tests/res/drawable/icon_yellow.jpg
copy to tests/tests/graphics/res/drawable/icon_yellow.jpg
Binary files differ
diff --git a/tests/res/drawable/insetdrawable.xml b/tests/tests/graphics/res/drawable/insetdrawable.xml
similarity index 100%
rename from tests/res/drawable/insetdrawable.xml
rename to tests/tests/graphics/res/drawable/insetdrawable.xml
diff --git a/tests/res/drawable/layerdrawable.xml b/tests/tests/graphics/res/drawable/layerdrawable.xml
similarity index 100%
rename from tests/res/drawable/layerdrawable.xml
rename to tests/tests/graphics/res/drawable/layerdrawable.xml
diff --git a/tests/tests/graphics/res/drawable/layerdrawable_theme.xml b/tests/tests/graphics/res/drawable/layerdrawable_theme.xml
new file mode 100644
index 0000000..2a678ff
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/layerdrawable_theme.xml
@@ -0,0 +1,29 @@
+<?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.
+-->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
+    android:autoMirrored="?attr/themeBoolean" >
+
+    <item android:drawable="@drawable/bitmapdrawable_theme"/>
+    <item>
+        <nine-patch
+            android:autoMirrored="?attr/themeBoolean"
+            android:dither="?attr/themeBoolean"
+            android:src="?attr/themeNinePatch" />
+    </item>
+
+</layer-list>
\ No newline at end of file
diff --git a/tests/res/drawable/levellistdrawable.xml b/tests/tests/graphics/res/drawable/levellistdrawable.xml
similarity index 100%
rename from tests/res/drawable/levellistdrawable.xml
rename to tests/tests/graphics/res/drawable/levellistdrawable.xml
diff --git a/tests/res/drawable/ninepatch_0.9.png b/tests/tests/graphics/res/drawable/ninepatch_0.9.png
similarity index 100%
copy from tests/res/drawable/ninepatch_0.9.png
copy to tests/tests/graphics/res/drawable/ninepatch_0.9.png
Binary files differ
diff --git a/tests/res/drawable/ninepatch_1.9.png b/tests/tests/graphics/res/drawable/ninepatch_1.9.png
similarity index 100%
copy from tests/res/drawable/ninepatch_1.9.png
copy to tests/tests/graphics/res/drawable/ninepatch_1.9.png
Binary files differ
diff --git a/tests/res/drawable/ninepatchdrawable.xml b/tests/tests/graphics/res/drawable/ninepatchdrawable.xml
similarity index 100%
rename from tests/res/drawable/ninepatchdrawable.xml
rename to tests/tests/graphics/res/drawable/ninepatchdrawable.xml
diff --git a/tests/tests/graphics/res/drawable/ninepatchdrawable_theme.xml b/tests/tests/graphics/res/drawable/ninepatchdrawable_theme.xml
new file mode 100644
index 0000000..bb031a5
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/ninepatchdrawable_theme.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+
+<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
+    android:autoMirrored="?attr/themeBoolean"
+    android:dither="?attr/themeBoolean"
+    android:src="?attr/themeNinePatch" />
diff --git a/tests/res/drawable/no_padding.png b/tests/tests/graphics/res/drawable/no_padding.png
similarity index 100%
copy from tests/res/drawable/no_padding.png
copy to tests/tests/graphics/res/drawable/no_padding.png
Binary files differ
diff --git a/tests/res/drawable/opaque.9.png b/tests/tests/graphics/res/drawable/opaque.9.png
similarity index 100%
rename from tests/res/drawable/opaque.9.png
rename to tests/tests/graphics/res/drawable/opaque.9.png
Binary files differ
diff --git a/tests/res/drawable/padding_0.9.png b/tests/tests/graphics/res/drawable/padding_0.9.png
similarity index 100%
copy from tests/res/drawable/padding_0.9.png
copy to tests/tests/graphics/res/drawable/padding_0.9.png
Binary files differ
diff --git a/tests/res/drawable/paintdrawable_attr.xml b/tests/tests/graphics/res/drawable/paintdrawable_attr.xml
similarity index 100%
rename from tests/res/drawable/paintdrawable_attr.xml
rename to tests/tests/graphics/res/drawable/paintdrawable_attr.xml
diff --git a/tests/res/drawable/pass.jpg b/tests/tests/graphics/res/drawable/pass.jpg
similarity index 100%
copy from tests/res/drawable/pass.jpg
copy to tests/tests/graphics/res/drawable/pass.jpg
Binary files differ
diff --git a/tests/res/drawable/png_test.png b/tests/tests/graphics/res/drawable/png_test.png
similarity index 100%
rename from tests/res/drawable/png_test.png
rename to tests/tests/graphics/res/drawable/png_test.png
Binary files differ
diff --git a/tests/res/drawable/premul_data.png b/tests/tests/graphics/res/drawable/premul_data.png
similarity index 100%
rename from tests/res/drawable/premul_data.png
rename to tests/tests/graphics/res/drawable/premul_data.png
Binary files differ
diff --git a/tests/res/drawable/progressive_jpeg.jpg b/tests/tests/graphics/res/drawable/progressive_jpeg.jpg
similarity index 100%
rename from tests/res/drawable/progressive_jpeg.jpg
rename to tests/tests/graphics/res/drawable/progressive_jpeg.jpg
Binary files differ
diff --git a/tests/res/drawable/progressive_restart_jpeg.jpg b/tests/tests/graphics/res/drawable/progressive_restart_jpeg.jpg
similarity index 100%
rename from tests/res/drawable/progressive_restart_jpeg.jpg
rename to tests/tests/graphics/res/drawable/progressive_restart_jpeg.jpg
Binary files differ
diff --git a/tests/tests/graphics/res/drawable/rippledrawable_theme.xml b/tests/tests/graphics/res/drawable/rippledrawable_theme.xml
new file mode 100644
index 0000000..a49b820
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/rippledrawable_theme.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="?attr/themeColor" />
diff --git a/tests/res/drawable/robot.png b/tests/tests/graphics/res/drawable/robot.png
similarity index 100%
copy from tests/res/drawable/robot.png
copy to tests/tests/graphics/res/drawable/robot.png
Binary files differ
diff --git a/tests/res/drawable/rotatedrawable.xml b/tests/tests/graphics/res/drawable/rotatedrawable.xml
similarity index 100%
rename from tests/res/drawable/rotatedrawable.xml
rename to tests/tests/graphics/res/drawable/rotatedrawable.xml
diff --git a/tests/res/drawable/scaled1.png b/tests/tests/graphics/res/drawable/scaled1.png
similarity index 100%
rename from tests/res/drawable/scaled1.png
rename to tests/tests/graphics/res/drawable/scaled1.png
Binary files differ
diff --git a/tests/res/drawable/scaled2.png b/tests/tests/graphics/res/drawable/scaled2.png
similarity index 100%
rename from tests/res/drawable/scaled2.png
rename to tests/tests/graphics/res/drawable/scaled2.png
Binary files differ
diff --git a/tests/res/drawable/scaledrawable.xml b/tests/tests/graphics/res/drawable/scaledrawable.xml
similarity index 100%
rename from tests/res/drawable/scaledrawable.xml
rename to tests/tests/graphics/res/drawable/scaledrawable.xml
diff --git a/tests/res/drawable/scenery.jpg b/tests/tests/graphics/res/drawable/scenery.jpg
similarity index 100%
copy from tests/res/drawable/scenery.jpg
copy to tests/tests/graphics/res/drawable/scenery.jpg
Binary files differ
diff --git a/tests/res/drawable/shapedrawable_test.xml b/tests/tests/graphics/res/drawable/shapedrawable_test.xml
similarity index 100%
rename from tests/res/drawable/shapedrawable_test.xml
rename to tests/tests/graphics/res/drawable/shapedrawable_test.xml
diff --git a/tests/res/drawable/size_48x48.jpg b/tests/tests/graphics/res/drawable/size_48x48.jpg
similarity index 100%
copy from tests/res/drawable/size_48x48.jpg
copy to tests/tests/graphics/res/drawable/size_48x48.jpg
Binary files differ
diff --git a/tests/res/drawable/start.jpg b/tests/tests/graphics/res/drawable/start.jpg
similarity index 100%
copy from tests/res/drawable/start.jpg
copy to tests/tests/graphics/res/drawable/start.jpg
Binary files differ
diff --git a/tests/res/drawable/testimage.jpg b/tests/tests/graphics/res/drawable/statelist_testimage.jpg
similarity index 100%
copy from tests/res/drawable/testimage.jpg
copy to tests/tests/graphics/res/drawable/statelist_testimage.jpg
Binary files differ
diff --git a/tests/tests/graphics/res/drawable/statelistdrawable.xml b/tests/tests/graphics/res/drawable/statelistdrawable.xml
new file mode 100644
index 0000000..b867904
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/statelistdrawable.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2009 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.
+ -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+   <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/testcolor.xml b/tests/tests/graphics/res/drawable/testcolor.xml
similarity index 100%
copy from tests/res/drawable/testcolor.xml
copy to tests/tests/graphics/res/drawable/testcolor.xml
diff --git a/tests/res/drawable/testimage.jpg b/tests/tests/graphics/res/drawable/testimage.jpg
similarity index 100%
copy from tests/res/drawable/testimage.jpg
copy to tests/tests/graphics/res/drawable/testimage.jpg
Binary files differ
diff --git a/tests/res/drawable/transition_test.xml b/tests/tests/graphics/res/drawable/transition_test.xml
similarity index 100%
rename from tests/res/drawable/transition_test.xml
rename to tests/tests/graphics/res/drawable/transition_test.xml
diff --git a/tests/res/drawable/transparent_border.9.png b/tests/tests/graphics/res/drawable/transparent_border.9.png
similarity index 100%
rename from tests/res/drawable/transparent_border.9.png
rename to tests/tests/graphics/res/drawable/transparent_border.9.png
Binary files differ
diff --git a/tests/res/drawable/transparent_right.9.png b/tests/tests/graphics/res/drawable/transparent_right.9.png
similarity index 100%
rename from tests/res/drawable/transparent_right.9.png
rename to tests/tests/graphics/res/drawable/transparent_right.9.png
Binary files differ
diff --git a/tests/res/drawable/typeface_test.png b/tests/tests/graphics/res/drawable/typeface_test.png
similarity index 100%
rename from tests/res/drawable/typeface_test.png
rename to tests/tests/graphics/res/drawable/typeface_test.png
Binary files differ
diff --git a/tests/tests/graphics/res/drawable/vector_drawable_grouping_1.xml b/tests/tests/graphics/res/drawable/vector_drawable_grouping_1.xml
new file mode 100644
index 0000000..7839ad1
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_drawable_grouping_1.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"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="256"
+        android:viewportWidth="256" >
+
+    <group
+        android:name="shape_layer_1"
+        android:translateX="128"
+        android:translateY="128" >
+        <group android:name="sun" >
+            <path
+                android:name="ellipse_path_1"
+                android:fillColor="#ffff8000"
+                android:pathData="m -25 0 a 25,25 0 1,0 50,0 a 25,25 0 1,0 -50,0" />
+
+            <group
+                android:name="earth"
+                android:translateX="75" >
+                <path
+                    android:name="ellipse_path_1_1"
+                    android:fillColor="#ff5656ea"
+                    android:pathData="m -10 0 a 10,10 0 1,0 20,0 a 10,10 0 1,0 -20,0" />
+
+                <group
+                    android:name="moon"
+                    android:translateX="25" >
+                    <path
+                        android:name="ellipse_path_1_2"
+                        android:fillColor="#ffadadad"
+                        android:pathData="m -5 0 a 5,5 0 1,0 10,0 a 5,5 0 1,0 -10,0" />
+                </group>
+            </group>
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_clip_path_1.xml b/tests/tests/graphics/res/drawable/vector_icon_clip_path_1.xml
new file mode 100644
index 0000000..c2ab429
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_clip_path_1.xml
@@ -0,0 +1,71 @@
+<!--
+ 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"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="12.25"
+        android:viewportWidth="7.30625" >
+
+    <group
+        android:pivotX="3.65"
+        android:pivotY="6.125"
+        android:rotation="-30" >
+        <clip-path
+            android:name="clip1"
+            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:fillColor="#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" >
+        <clip-path
+            android:name="clip2"
+            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:fillColor="#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/tests/graphics/res/drawable/vector_icon_create.xml b/tests/tests/graphics/res/drawable/vector_icon_create.xml
new file mode 100644
index 0000000..7db4ad5
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_create.xml
@@ -0,0 +1,29 @@
+<?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.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="24"
+        android:viewportWidth="24" >
+
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M3.0,17.25L3.0,21.0l3.75,0.0L17.813995,9.936001l-3.75-3.75L3.0,17.25zM20.707,7.0429993c0.391-0.391 0.391-1.023 0.0-1.414l-2.336-2.336c-0.391-0.391-1.023-0.391 -1.414,0.0l-1.832,1.832l3.75,3.75L20.707,7.0429993z" />
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_delete.xml b/tests/tests/graphics/res/drawable/vector_icon_delete.xml
new file mode 100644
index 0000000..8d9c21c
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_delete.xml
@@ -0,0 +1,29 @@
+<?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.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="24"
+        android:viewportWidth="24" >
+
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M6.0,19.0c0.0,1.104 0.896,2.0 2.0,2.0l8.0,0.0c1.104,0.0 2.0-0.896 2.0-2.0l0.0-12.0L6.0,7.0L6.0,19.0zM18.0,4.0l-2.5,0.0l-1.0-1.0l-5.0,0.0l-1.0,1.0L6.0,4.0C5.4469986,4.0 5.0,4.4469986 5.0,5.0l0.0,1.0l14.0,0.0l0.0-1.0C19.0,4.4469986 18.552002,4.0 18.0,4.0z" />
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_heart.xml b/tests/tests/graphics/res/drawable/vector_icon_heart.xml
new file mode 100644
index 0000000..ff55fe5
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_heart.xml
@@ -0,0 +1,29 @@
+<?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.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="24"
+        android:viewportWidth="24" >
+
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M16.0,5.0c-1.955,0.0 -3.83,1.268 -4.5,3.0c-0.67-1.732 -2.547-3.0 -4.5-3.0C4.4570007,5.0 2.5,6.931999 2.5,9.5c0.0,3.529 3.793,6.258 9.0,11.5c5.207-5.242 9.0-7.971 9.0-11.5C20.5,6.931999 18.543,5.0 16.0,5.0z" />
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_random_path_1.xml b/tests/tests/graphics/res/drawable/vector_icon_random_path_1.xml
new file mode 100644
index 0000000..5c55294
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_random_path_1.xml
@@ -0,0 +1,49 @@
+<!--
+ 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"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="128"
+        android:viewportWidth="128" >
+
+    <path
+        android:fillColor="#FF00FF00"
+        android:pathData="
+                 m 0.0 0.0
+                 c 58.357853 57.648304 47.260395 2.2044754 3.0 3.0
+                 s 61.29288 10.748665 6.0 6.0
+                 s 0.12015152 45.193787 9.0 9.0
+                 s 32.573513 46.862522 12.0 12.0
+                 C 52.051823 62.050003 14.197739 51.99994 15.0 15.0
+                 S 58.365482 51.877937 18.0 18.0
+                 S 26.692455 3.9604378 21.0 21.0
+                 S 21.433464 52.17514 24.0 24.0
+                 M 27.0 27.0
+                 s 0.77630234 20.606667 30.0 30.0
+                 M 33.0 33.0
+                 S 31.06879 21.506374 36.0 36.0
+                 m 39.0 39.0
+                 s 11.699013 23.684185 42.0 42.0
+                 m 45.0 45.0
+                 S 3.7642136 38.589584 48.0 48.0
+                 Q 27.203026 53.329338 51.0 51.0
+                 s 39.229023 15.1781845 54.0 54.0
+                 Q 47.946877 23.706299 57.0 57.0
+                 S 45.63452 56.15198 60.0 60.0 "
+        android:strokeColor="#FF0000FF"
+        android:strokeWidth="1" />
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_random_path_2.xml b/tests/tests/graphics/res/drawable/vector_icon_random_path_2.xml
new file mode 100644
index 0000000..95e0a54
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_random_path_2.xml
@@ -0,0 +1,49 @@
+<!--
+ 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"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="128"
+        android:viewportWidth="128" >
+
+    <path
+        android:fillColor="#FF00FF00"
+        android:pathData="
+                 m 0.0 0.0
+                 q 4.7088394 36.956432 3.0 3.0
+                 s 29.470345 16.754963 6.0 6.0
+                 q 20.278355 7.4670525 9.0 9.0
+                 S 30.897224 17.732414 12.0 12.0
+                 T 15.0 15.0
+                 s 63.47204 45.67142 18.0 18.0
+                 T 21.0 21.0
+                 S 0.3184204 24.808247 24.0 24.0
+                 t 27.0 27.0
+                 s 39.02275 38.261158 30.0 30.0
+                 t 33.0 33.0
+                 S 50.709816 16.067192 36.0 36.0
+                 a 62.50911 7.7131805 51.932335 0 0 39.0 39.0
+                 s 5.155651 15.749123 42.0 42.0
+                 a 51.87415 40.30564 49.804344 0 0 45.0 45.0
+                 S 16.16534 62.55986 48.0 48.0
+                 A 39.90161 43.904438 41.642593 1 0 51.0 51.0
+                 s 46.258068 32.12831 54.0 54.0
+                 A 22.962704 55.05604 42.912285 1 1 57.0 57.0
+                 S 36.47731 54.216763 60.0 60.0 "
+        android:strokeColor="#FF0000FF"
+        android:strokeWidth="1" />
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_render_order_1.xml b/tests/tests/graphics/res/drawable/vector_icon_render_order_1.xml
new file mode 100644
index 0000000..d4472e2
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_render_order_1.xml
@@ -0,0 +1,89 @@
+<!--
+ 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"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="400"
+        android:viewportWidth="400" >
+
+    <group
+        android:name="FirstLevelGroup"
+        android:translateX="100.0"
+        android:translateY="0.0" >
+        <path
+            android:fillColor="#FFFF0000"
+            android:fillAlpha="0.9"
+            android:pathData="@string/rectangle200" />
+
+        <group
+            android:name="SecondLevelGroup1"
+            android:translateX="-100.0"
+            android:translateY="50.0" >
+            <path
+                android:fillColor="#FF00FF00"
+                android:fillAlpha="0.81"
+                android:pathData="@string/rectangle200" />
+
+            <group
+                android:name="ThridLevelGroup1"
+                android:translateX="-100.0"
+                android:translateY="50.0" >
+                <path
+                    android:fillColor="#FF0000FF"
+                    android:fillAlpha="0.729"
+                    android:pathData="@string/rectangle200" />
+            </group>
+            <group
+                android:name="ThridLevelGroup2"
+                android:translateX="100.0"
+                android:translateY="50.0" >
+                <path
+                    android:fillAlpha="0.72"
+                    android:fillColor="#FF000000"
+                    android:pathData="@string/rectangle200" />
+            </group>
+        </group>
+        <group
+            android:name="SecondLevelGroup2"
+            android:translateX="100.0"
+            android:translateY="50.0" >
+            <path
+                android:fillColor="#FF0000FF"
+                android:fillAlpha="0.72"
+                android:pathData="@string/rectangle200" />
+
+            <group
+                android:name="ThridLevelGroup3"
+                android:translateX="-100.0"
+                android:translateY="50.0" >
+                <path
+                    android:fillAlpha="0.648"
+                    android:fillColor="#FFFF0000"
+                    android:pathData="@string/rectangle200" />
+            </group>
+            <group
+                android:name="ThridLevelGroup4"
+                android:translateX="100.0"
+                android:translateY="50.0" >
+                <path
+                    android:fillAlpha="0.576"
+                    android:fillColor="#FF00FF00"
+                    android:pathData="@string/rectangle200" />
+            </group>
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_render_order_2.xml b/tests/tests/graphics/res/drawable/vector_icon_render_order_2.xml
new file mode 100644
index 0000000..6fcb355
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_render_order_2.xml
@@ -0,0 +1,89 @@
+<!--
+ 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"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="400"
+        android:viewportWidth="400" >
+
+    <group
+        android:name="FirstLevelGroup"
+        android:translateX="100.0"
+        android:translateY="0.0" >
+        <group
+            android:name="SecondLevelGroup1"
+            android:translateX="-100.0"
+            android:translateY="50.0" >
+            <path
+                android:fillAlpha="0.81"
+                android:fillColor="#FF00FF00"
+                android:pathData="@string/rectangle200" />
+
+            <group
+                android:name="ThridLevelGroup1"
+                android:translateX="-100.0"
+                android:translateY="50.0" >
+                <path
+                    android:fillAlpha="0.729"
+                    android:fillColor="#FF0000FF"
+                    android:pathData="@string/rectangle200" />
+            </group>
+            <group
+                android:name="ThridLevelGroup2"
+                android:translateX="100.0"
+                android:translateY="50.0" >
+                <path
+                    android:fillAlpha="0.648"
+                    android:fillColor="#FF000000"
+                    android:pathData="@string/rectangle200" />
+            </group>
+        </group>
+        <group
+            android:name="SecondLevelGroup2"
+            android:translateX="100.0"
+            android:translateY="50.0" >
+            <path
+                android:fillAlpha="0.72"
+                android:fillColor="#FF0000FF"
+                android:pathData="@string/rectangle200" />
+
+            <group
+                android:name="ThridLevelGroup3"
+                android:translateX="-100.0"
+                android:translateY="50.0" >
+                <path
+                    android:fillAlpha="0.648"
+                    android:fillColor="#FFFF0000"
+                    android:pathData="@string/rectangle200" />
+            </group>
+            <group
+                android:name="ThridLevelGroup4"
+                android:translateX="100.0"
+                android:translateY="50.0" >
+                <path
+                    android:fillAlpha="0.576"
+                    android:fillColor="#FF00FF00"
+                    android:pathData="@string/rectangle200" />
+            </group>
+        </group>
+
+        <path
+            android:fillAlpha="0.9"
+            android:fillColor="#FFFF0000"
+            android:pathData="@string/rectangle200" />
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_repeated_a_1.xml b/tests/tests/graphics/res/drawable/vector_icon_repeated_a_1.xml
new file mode 100644
index 0000000..e27464b
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_repeated_a_1.xml
@@ -0,0 +1,43 @@
+<!--
+ 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"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="128"
+        android:viewportWidth="128" >
+
+    <path
+        android:fillColor="#FF00FF00"
+        android:pathData="m 45.712063 19.109837
+                H 24.509682
+                a 59.3415 26.877445 22.398209 1 1 3.3506432 1.6524277
+                a 34.922844 36.72583 13.569004 0 0 24.409462 20.931156
+                a 43.47134 32.61542 52.534607 1 0 7.187504 61.509724
+                A 30.621132 41.44202 50.885685 0 0 23.235489 26.638653
+                A 7.251148 15.767811 44.704533 1 1 19.989803 21.33052
+                A 55.645584 46.20288 19.40316 0 1 32.881298 53.410923
+                c 30.649612 4.8525085 21.96682 1.3304634 17.300182 14.747681
+                a 9.375069 44.365055 57.169727 0 0 56.01326 52.59596
+                A 50.071907 37.331825 56.301754 1 0 14.676102 62.04976
+                C 36.531925 4.6217957 47.59332 54.793385 13.562473 13.753647
+                A 2.3695297 42.578487 54.250687 0 1 33.1337 41.511288
+                a 39.4827 38.844944 54.52335 1 1 13.549484 46.81581
+                c 56.943657 51.96854 27.938824 61.148792 24.168636 46.642727
+                "
+        android:strokeColor="#FF0000FF"
+        android:strokeWidth="1" />
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_repeated_a_2.xml b/tests/tests/graphics/res/drawable/vector_icon_repeated_a_2.xml
new file mode 100644
index 0000000..924ba1b
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_repeated_a_2.xml
@@ -0,0 +1,45 @@
+<!--
+ 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"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="128"
+        android:viewportWidth="128" >
+
+    <path
+        android:fillColor="#FF00FF00"
+        android:pathData="m 45.712063 19.109837
+                H 24.509682
+                A 37.689938 2.3916092 17.462616 1 0 24.958328 48.110596
+                q 45.248383 30.396336 5.777027 3.4086685
+                a 30.966236 62.67946 50.532032 1 0 29.213684 60.63014
+                L 56.16764 8.342098
+                Q 61.172253 1.4613304 4.4721107 38.287144
+                A 6.284897 22.991482 47.409508 1 1 44.10166 60.998764
+                t 36.36881 55.68292
+                a 51.938667 35.22107 22.272938 1 1 28.572739 60.848858
+                A 19.610851 11.569599 51.407906 1 1 56.82705 24.386292
+                T 36.918854 59.542286
+                a 33.191364 10.553429 53.047726 1 0 54.874985 7.409252
+                s 30.186714 42.154182 59.73551 35.50219
+                A 47.9379 5.776497 28.307701 1 1 3.3323975 30.113499
+                a 22.462494 28.096004 55.76455 0 0 25.58981 30.816948
+                S 43.91107 54.679676 19.540264 0.34284973
+                "
+        android:strokeColor="#FF0000FF"
+        android:strokeWidth="1" />
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_repeated_cq.xml b/tests/tests/graphics/res/drawable/vector_icon_repeated_cq.xml
new file mode 100644
index 0000000..e0848f0
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_repeated_cq.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"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="128"
+        android:viewportWidth="128" >
+
+    <path
+        android:fillColor="#FF00FF00"
+        android:pathData="m 30.81895 41.37989
+                v 31.00579
+                c 24.291603 52.03364 40.6086 24.840137 29.56704 6.5204926
+                45.133224 22.913471 33.052887 21.727486 33.369 61.60278
+                9.647232 22.098152 48.939598 47.470215 53.653687 62.32235
+                C 2.0560722 1.4615479 7.0928993 26.005287 40.137558 36.75628
+                11.246731 32.178127 59.367462 60.34823 57.254383 37.357815
+                47.75605 11.424667 3.3105545 51.886635 56.63027 17.12133
+                q 28.37534 32.85535 25.85654 33.57151
+                10.356537 51.850616 54.085087 35.653175
+                12.530029 52.87991 17.44696 11.780586
+                Q 2.585228 51.92801 60.000664 56.79912
+                54.18275 51.500694 9.375679 23.836113
+                60.35329 59.026245 31.058632 35.14934
+                "
+        android:strokeColor="#FF0000FF"
+        android:strokeWidth="1" />
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_repeated_st.xml b/tests/tests/graphics/res/drawable/vector_icon_repeated_st.xml
new file mode 100644
index 0000000..b104349
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_repeated_st.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"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="128"
+        android:viewportWidth="128" >
+
+    <path
+        android:fillColor="#FF00FF00"
+        android:pathData="m 20.20005 8.139153
+                h 10.053165
+                s 14.2943 49.612846 35.520653 54.904068
+                50.1405 17.044182 5.470337 40.180553
+                3.125019 34.221123 53.212563 32.862965
+                S 35.985264 35.74349 0.15337753 59.27337
+                2.2951508 44.56783 51.089413 29.829689
+                8.5599785 22.649555 4.3914986 28.139206
+                t 11.932453 44.041077
+                62.629326 7.40921
+                23.302986 54.116184
+                T 43.560753 63.370514
+                40.156204 17.60786
+                40.12051 60.803394
+                "
+        android:strokeColor="#FF0000FF"
+        android:strokeWidth="1" />
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_schedule.xml b/tests/tests/graphics/res/drawable/vector_icon_schedule.xml
new file mode 100644
index 0000000..64d19e8
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_schedule.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.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="24"
+        android:viewportWidth="24" >
+
+    <path
+        android:fillColor="#E6000000"
+        android:pathData="M11.994999,2.0C6.4679985,2.0 2.0,6.4780006 2.0,12.0s4.468,10.0 9.995,10.0S22.0,17.522 22.0,12.0S17.521,2.0 11.994999,2.0zM12.0,20.0c-4.42,0.0 -8.0-3.582-8.0-8.0s3.58-8.0 8.0-8.0s8.0,3.582 8.0,8.0S16.419998,20.0 12.0,20.0z" />
+    <path
+        android:fillColor="#E6000000"
+        android:pathData="M12.5,6.0l-1.5,0.0 0.0,7.0 5.3029995,3.1819992 0.75-1.249999-4.5529995-2.7320004z" />
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_settings.xml b/tests/tests/graphics/res/drawable/vector_icon_settings.xml
new file mode 100644
index 0000000..13d7f05
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_settings.xml
@@ -0,0 +1,29 @@
+<?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.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="24"
+        android:viewportWidth="24" >
+
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M19.429,12.975998c0.042-0.32 0.07-0.645 0.07-0.976s-0.029-0.655-0.07-0.976l2.113-1.654c0.188-0.151 0.243-0.422 0.118-0.639l-2.0-3.463c-0.125-0.217-0.386-0.304-0.612-0.218l-2.49,1.004c-0.516-0.396-1.081-0.731-1.69-0.984l-0.375-2.648C14.456,2.1829987 14.25,2.0 14.0,2.0l-4.0,0.0C9.75,2.0 9.544,2.1829987 9.506,2.422001L9.131,5.0699997C8.521,5.322998 7.957,5.6570015 7.44,6.054001L4.952,5.0509987C4.726,4.965 4.464,5.052002 4.34,5.269001l-2.0,3.463C2.2150002,8.947998 2.27,9.219002 2.4580002,9.369999l2.112,1.653C4.528,11.344002 4.5,11.668999 4.5,12.0s0.029,0.656 0.071,0.977L2.4580002,14.630001c-0.188,0.151-0.243,0.422-0.118,0.639l2.0,3.463c0.125,0.217 0.386,0.304 0.612,0.218l2.489-1.004c0.516,0.396 1.081,0.731 1.69,0.984l0.375,2.648C9.544,21.817001 9.75,22.0 10.0,22.0l4.0,0.0c0.25,0.0 0.456-0.183 0.494-0.422l0.375-2.648c0.609-0.253 1.174-0.588 1.689-0.984l2.49,1.004c0.226,0.086 0.487-0.001 0.612-0.218l2.0-3.463c0.125-0.217 0.07-0.487-0.118-0.639L19.429,12.975998zM12.0,16.0c-2.21,0.0-4.0-1.791-4.0-4.0c0.0-2.21 1.79-4.0 4.0-4.0c2.208,0.0 4.0,1.79 4.0,4.0C16.0,14.209 14.208,16.0 12.0,16.0z" />
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_stroke_1.xml b/tests/tests/graphics/res/drawable/vector_icon_stroke_1.xml
new file mode 100644
index 0000000..af351f1
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_stroke_1.xml
@@ -0,0 +1,46 @@
+<!--
+ 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"
+    android:height="64dp"
+    android:viewportHeight="200"
+    android:viewportWidth="200"
+    android:width="64dp" >
+
+    <group>
+        <path
+            android:name="background1"
+            android:fillColor="#FF000000"
+            android:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z" />
+        <path
+            android:name="background2"
+            android:fillColor="#FF000000"
+            android:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
+    </group>
+    <group
+        android:translateX="50"
+        android:translateY="50" >
+        <path
+            android:name="twoLines"
+            android:pathData="M 100,20 l 0 80 l -30 -80"
+            android:fillColor="#FF000000"
+            android:strokeColor="#FF00FF00"
+            android:strokeLineCap="butt"
+            android:strokeLineJoin="miter"
+            android:strokeMiterLimit="6"
+            android:strokeWidth="20" />
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_stroke_2.xml b/tests/tests/graphics/res/drawable/vector_icon_stroke_2.xml
new file mode 100644
index 0000000..f85d5fc
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_stroke_2.xml
@@ -0,0 +1,46 @@
+<!--
+ 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"
+    android:height="64dp"
+    android:viewportHeight="200"
+    android:viewportWidth="200"
+    android:width="64dp" >
+
+    <group>
+        <path
+            android:name="background1"
+            android:fillColor="#FF000000"
+            android:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z" />
+        <path
+            android:name="background2"
+            android:fillColor="#FF000000"
+            android:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
+    </group>
+    <group
+        android:translateX="50"
+        android:translateY="50" >
+        <path
+            android:name="twoLines"
+            android:pathData="M 100,20 l 0 80 l -30 -80"
+            android:fillColor="#FF000000"
+            android:strokeColor="#FF00FF00"
+            android:strokeLineCap="round"
+            android:strokeLineJoin="round"
+            android:strokeMiterLimit="10"
+            android:strokeWidth="20" />
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_stroke_3.xml b/tests/tests/graphics/res/drawable/vector_icon_stroke_3.xml
new file mode 100644
index 0000000..8f3d47e
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_stroke_3.xml
@@ -0,0 +1,46 @@
+<!--
+ 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"
+    android:height="64dp"
+    android:viewportHeight="200"
+    android:viewportWidth="200"
+    android:width="64dp" >
+
+    <group>
+        <path
+            android:name="background1"
+            android:fillColor="#FF000000"
+            android:pathData="M 0,0 l 100,0 l 0, 100 l -100, 0 z" />
+        <path
+            android:name="background2"
+            android:fillColor="#FF000000"
+            android:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z" />
+    </group>
+    <group
+        android:translateX="50"
+        android:translateY="50" >
+        <path
+            android:name="twoLines"
+            android:pathData="M 100,20 l 0 80 l -30 -80"
+            android:fillColor="#FF000000"
+            android:strokeColor="#FF00FF00"
+            android:strokeLineCap="square"
+            android:strokeLineJoin="bevel"
+            android:strokeMiterLimit="10"
+            android:strokeWidth="20" />
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_transformation_1.xml b/tests/tests/graphics/res/drawable/vector_icon_transformation_1.xml
new file mode 100644
index 0000000..f6623d0
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_transformation_1.xml
@@ -0,0 +1,38 @@
+<!--
+ 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"
+        android:height="64dp"
+        android:width="64dp"
+        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:fillColor="#00000000"
+            android:strokeColor="#FF00FF00"
+            android:strokeWidth="10" />
+    </group>
+
+</vector>
diff --git a/tests/tests/graphics/res/drawable/vector_icon_transformation_2.xml b/tests/tests/graphics/res/drawable/vector_icon_transformation_2.xml
new file mode 100644
index 0000000..87da0bb
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_transformation_2.xml
@@ -0,0 +1,48 @@
+<!--
+ 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"
+        android:height="64dp"
+        android:width="64dp"
+        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:fillColor="#FF000000"/>
+        <path
+            android:name="background2"
+            android:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z"
+            android:fillColor="#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:fillColor="#00000000"
+            android:strokeColor="#FF00FF00"
+            android:strokeWidth="10" />
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_transformation_3.xml b/tests/tests/graphics/res/drawable/vector_icon_transformation_3.xml
new file mode 100644
index 0000000..fc30af3
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_transformation_3.xml
@@ -0,0 +1,48 @@
+<!--
+ 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"
+        android:height="64dp"
+        android:width="64dp"
+        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:fillColor="#FF000000"/>
+        <path
+            android:name="background2"
+            android:pathData="M 100,100 l 100,0 l 0, 100 l -100, 0 z"
+            android:fillColor="#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:fillColor="#00000000"
+            android:strokeColor="#FF00FF00"
+            android:strokeWidth="10" />
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_transformation_4.xml b/tests/tests/graphics/res/drawable/vector_icon_transformation_4.xml
new file mode 100644
index 0000000..5b40d0d
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_transformation_4.xml
@@ -0,0 +1,68 @@
+<!--
+ 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"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="400"
+        android:viewportWidth="400" >
+
+    <group android:name="backgroundGroup" >
+        <path
+            android:name="background1"
+            android:fillColor="#80000000"
+            android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+        <path
+            android:name="background2"
+            android:fillColor="#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:strokeColor="#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:strokeColor="#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:strokeColor="#FF0000FF"
+                        android:strokeWidth="20" />
+                </group>
+            </group>
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_transformation_5.xml b/tests/tests/graphics/res/drawable/vector_icon_transformation_5.xml
new file mode 100644
index 0000000..4a27754
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_transformation_5.xml
@@ -0,0 +1,81 @@
+<!--
+ 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"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="400"
+        android:viewportWidth="400" >
+
+    <group android:name="backgroundGroup" >
+        <path
+            android:name="background1"
+            android:fillColor="#80000000"
+            android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+        <path
+            android:name="background2"
+            android:fillColor="#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:strokeColor="#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:strokeColor="#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:strokeColor="#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:strokeColor="#FF0000FF"
+                        android:strokeWidth="20" />
+                </group>
+            </group>
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_transformation_6.xml b/tests/tests/graphics/res/drawable/vector_icon_transformation_6.xml
new file mode 100644
index 0000000..2c174fb
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/vector_icon_transformation_6.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"
+        android:height="64dp"
+        android:width="64dp"
+        android:viewportHeight="400"
+        android:viewportWidth="400"
+        android:alpha = "0.5" >
+
+    <group android:name="backgroundGroup">
+        <path
+            android:name="background1"
+            android:fillColor="#FF000000"
+            android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+        <path
+            android:name="background2"
+            android:fillColor="#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">
+        <path
+            android:name="twoLines"
+            android:pathData="M 0,0 v 100 M 0,0 h 100"
+            android:strokeColor="#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:strokeColor="#FF00FF00"
+                android:strokeWidth="20"
+                android:strokeAlpha="0.5" />
+
+            <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:strokeColor="#FF0000FF"
+                        android:strokeWidth="20"
+                        android:strokeAlpha="0.25" />
+                </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:strokeColor="#FF0000FF"
+                        android:strokeWidth="20"
+                        android:strokeAlpha="0.5" />
+                </group>
+            </group>
+        </group>
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/res/drawable/webp_test.webp b/tests/tests/graphics/res/drawable/webp_test.webp
similarity index 100%
rename from tests/res/drawable/webp_test.webp
rename to tests/tests/graphics/res/drawable/webp_test.webp
Binary files differ
diff --git a/tests/res/drawable/window_test_drawable.xml b/tests/tests/graphics/res/drawable/window_test_drawable.xml
similarity index 100%
rename from tests/res/drawable/window_test_drawable.xml
rename to tests/tests/graphics/res/drawable/window_test_drawable.xml
diff --git a/tests/tests/graphics/res/layout/framelayout_layout.xml b/tests/tests/graphics/res/layout/framelayout_layout.xml
new file mode 100644
index 0000000..78b7b47
--- /dev/null
+++ b/tests/tests/graphics/res/layout/framelayout_layout.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2008 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.
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:id="@+id/framelayout_container"
+                android:background="@drawable/red"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_gravity="bottom"
+                android:orientation="vertical">
+
+    <FrameLayout
+        android:layout_width="100dip"
+        android:layout_height="100dip"
+        android:background="@drawable/yellow"
+        android:id="@+id/framelayout">
+    </FrameLayout>
+
+    <FrameLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:background="@drawable/yellow"
+        android:id="@+id/framelayout_measureall">
+
+        <TextView android:id="@+id/framelayout_textview"
+            android:background="@drawable/blue"
+            android:layout_width="60dip"
+            android:layout_height="30dip"
+            android:text="@string/hello_world"/>
+
+        <Button android:id="@+id/framelayout_button"
+            android:layout_width="50dip"
+            android:layout_height="15dip"
+            android:text="@string/go"/>
+
+    </FrameLayout>
+
+    <FrameLayout
+        android:id="@+id/foreground_tint"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:foregroundTint="@android:color/white"
+        android:foregroundTintMode="src_over" />
+
+</LinearLayout>
diff --git a/tests/tests/graphics/res/layout/imageview_layout.xml b/tests/tests/graphics/res/layout/imageview_layout.xml
new file mode 100644
index 0000000..e56a9c9
--- /dev/null
+++ b/tests/tests/graphics/res/layout/imageview_layout.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2008 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.
+ */
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <ImageView
+        android:id="@+id/imageview"
+        android:layout_width="320px"
+        android:layout_height="240px"/>
+
+    <ImageView
+        android:id="@+id/image_tint"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:tint="@android:color/white"
+        android:tintMode="src_over" />
+
+</LinearLayout>
+
diff --git a/tests/res/raw/basetex.png b/tests/tests/graphics/res/raw/basetex.png
similarity index 100%
rename from tests/res/raw/basetex.png
rename to tests/tests/graphics/res/raw/basetex.png
Binary files differ
diff --git a/tests/res/raw/ddstex.dds b/tests/tests/graphics/res/raw/ddstex.dds
similarity index 100%
rename from tests/res/raw/ddstex.dds
rename to tests/tests/graphics/res/raw/ddstex.dds
Binary files differ
diff --git a/tests/res/raw/pvrtex.pvr b/tests/tests/graphics/res/raw/pvrtex.pvr
similarity index 100%
rename from tests/res/raw/pvrtex.pvr
rename to tests/tests/graphics/res/raw/pvrtex.pvr
Binary files differ
diff --git a/tests/res/raw/testimage.jpg b/tests/tests/graphics/res/raw/testimage.jpg
similarity index 100%
copy from tests/res/raw/testimage.jpg
copy to tests/tests/graphics/res/raw/testimage.jpg
Binary files differ
diff --git a/tests/res/values/arrays.xml b/tests/tests/graphics/res/values/arrays.xml
similarity index 100%
copy from tests/res/values/arrays.xml
copy to tests/tests/graphics/res/values/arrays.xml
diff --git a/tests/tests/graphics/res/values/attrs.xml b/tests/tests/graphics/res/values/attrs.xml
new file mode 100644
index 0000000..4c3d9db
--- /dev/null
+++ b/tests/tests/graphics/res/values/attrs.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2008 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>
+    <declare-styleable name="Style1">
+        <attr name="Type1" format="integer">
+            <enum name="type" value="28" />
+            <enum name="data" value="0xff00ff00" />
+            <enum name="asset_cookie" value="0" />
+            <enum name="resource_id" value="0" />
+            <enum name="changing_config" value="0" />
+        </attr>
+        <attr name="Type2" format="integer">
+            <enum name="type" value="28" />
+            <enum name="data" value="0xff0000ff" />
+            <enum name="asset_cookie" value="0" />
+            <enum name="resource_id" value="0" />
+            <enum name="changing_config" value="0" />
+        </attr>
+    </declare-styleable>
+    <attr name="type1" format="boolean"/>
+    <attr name="type2" format="boolean"/>
+    <attr name="type3" format="color"/>
+    <attr name="type4" format="reference|color"/>
+    <attr name="type5" format="dimension"/>
+    <attr name="type6" format="dimension"/>
+    <attr name="type7" format="dimension"/>
+    <attr name="type8" format="reference"/>
+    <attr name="type9" format="float"/>
+    <attr name="type10" format="fraction"/>
+    <attr name="type11" format="integer"/>
+    <attr name="type12" format="integer"/>
+    <attr name="type13" format="reference|string"/>
+    <attr name="type14" format="string"/>
+    <attr name="type15" format="reference"/>
+    <attr name="type16" format="string"/>
+    <declare-styleable name="style1">
+        <attr name="type1"/>
+        <attr name="type2"/>
+        <attr name="type3"/>
+        <attr name="type4"/>
+        <attr name="type5"/>
+        <attr name="type6"/>
+        <attr name="type7"/>
+        <attr name="type8"/>
+        <attr name="type9"/>
+        <attr name="type10"/>
+        <attr name="type11"/>
+        <attr name="type12"/>
+        <attr name="type13"/>
+        <attr name="type14"/>
+        <attr name="type15"/>
+        <attr name="type16"/>
+    </declare-styleable>
+    <attr name="testEnum">
+        <enum name="val1" value="1" />
+        <enum name="val2" value="2" />
+        <enum name="val10" value="10" />
+    </attr>
+    <attr name="testFlags">
+        <flag name="bit1" value="0x1" />
+        <flag name="bit2" value="0x2" />
+        <flag name="bit31" value="0x40000000" />
+    </attr>
+    <attr name="testString" format="string" />
+    <declare-styleable name="EnumStyle">
+        <attr name="testEnum" />
+    </declare-styleable>
+    <declare-styleable name="FlagStyle">
+        <attr name="testFlags" />
+    </declare-styleable>
+    <declare-styleable name="TestConfig">
+        <attr name="testString" />
+    </declare-styleable>
+    <!-- Size of text. Recommended dimension type for text is "sp" for scaled-pixels (example: 15sp).
+         Supported values include the following:<p/>
+    <ul>
+        <li><b>px</b> Pixels</li>
+        <li><b>sp</b> Scaled pixels (scaled to relative pixel size on screen). See {@link android.util.DisplayMetrics} for more information.</li>
+        <li><b>pt</b> Points</li>
+        <li><b>dip</b> Device independent pixels. See {@link android.util.DisplayMetrics} for more information.</li>
+    </ul>
+    -->
+    <attr name="textSize" format="dimension" />
+    <attr name="typeface">
+        <enum name="normal" value="0" />
+        <enum name="sans" value="1" />
+        <enum name="serif" value="2" />
+        <enum name="monospace" value="3" />
+    </attr>
+    <!-- Default text typeface style. -->
+    <attr name="textStyle">
+        <flag name="normal" value="0" />
+        <flag name="bold" value="1" />
+        <flag name="italic" value="2" />
+    </attr>
+    <!-- Color of text (usually same as colorForeground). -->
+    <attr name="textColor" format="reference|color" />
+    <!-- Color of highlighted text. -->
+    <attr name="textColorHighlight" format="reference|color" />
+    <!-- Color of hint text (displayed when the field is empty). -->
+    <attr name="textColorHint" format="reference|color" />
+    <!-- Color of link text (URLs). -->
+    <attr name="textColorLink" format="reference|color" />
+    <declare-styleable name="TextAppearance">
+        <attr name="textColor"/>
+        <attr name="textSize"/>
+        <attr name="textStyle"/>
+        <attr name="typeface"/>
+        <attr name="textColorHighlight"/>
+        <attr name="textColorHint"/>
+        <attr name="textColorLink"/>
+    </declare-styleable>
+    <!-- Integer used to uniquely identify theme overrides. -->
+    <attr name="themeType" format="integer"/>
+    <!-- Theme reference used to override parent theme. -->
+    <attr name="themeOverrideAttr" format="reference"/>
+
+    <!-- Drawable theming attributes -->
+    <attr name="themeBoolean" />
+    <attr name="themeColor" />
+    <attr name="themeFloat" />
+    <attr name="themeInteger" />
+    <attr name="themeDimension" />
+    <attr name="themeDrawable" />
+    <attr name="themeBitmap" />
+    <attr name="themeNinePatch" />
+    <attr name="themeGravity" />
+    <attr name="themeTileMode" />
+    <attr name="themeAngle" />
+</resources>
diff --git a/tests/res/values/bools.xml b/tests/tests/graphics/res/values/bools.xml
similarity index 100%
copy from tests/res/values/bools.xml
copy to tests/tests/graphics/res/values/bools.xml
diff --git a/tests/res/values/colors.xml b/tests/tests/graphics/res/values/colors.xml
similarity index 100%
copy from tests/res/values/colors.xml
copy to tests/tests/graphics/res/values/colors.xml
diff --git a/tests/res/values/configVarying.xml b/tests/tests/graphics/res/values/configVarying.xml
similarity index 100%
copy from tests/res/values/configVarying.xml
copy to tests/tests/graphics/res/values/configVarying.xml
diff --git a/tests/res/values/dimens.xml b/tests/tests/graphics/res/values/dimens.xml
similarity index 100%
copy from tests/res/values/dimens.xml
copy to tests/tests/graphics/res/values/dimens.xml
diff --git a/tests/res/values/ids.xml b/tests/tests/graphics/res/values/ids.xml
similarity index 100%
rename from tests/res/values/ids.xml
rename to tests/tests/graphics/res/values/ids.xml
diff --git a/tests/res/values/resources_test.xml b/tests/tests/graphics/res/values/resources_test.xml
similarity index 100%
copy from tests/res/values/resources_test.xml
copy to tests/tests/graphics/res/values/resources_test.xml
diff --git a/tests/tests/graphics/res/values/strings.xml b/tests/tests/graphics/res/values/strings.xml
new file mode 100644
index 0000000..c167278
--- /dev/null
+++ b/tests/tests/graphics/res/values/strings.xml
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="permlab_testGranted">Test Granted</string>
+    <string name="permdesc_testGranted">Used for running CTS tests, for testing operations
+        where we have the permission.</string>
+    <string name="permlab_testDynamic">Test Dynamic</string>
+    <string name="permdesc_testDynamic">Used for running CTS tests, for testing adding
+        dynamic permissions.</string>
+    <string name="permlab_testDenied">Test Denied</string>
+    <string name="permdesc_testDenied">Used for running CTS tests, for testing operations
+        where we do not have the permission.</string>
+    <string name="explain">1. click start. \n2. if above image shaked, then press pass button,
+         else press failed button.</string>
+    <string name="text_view_hello">Hello! Text view!</string>
+    <string name="text_view_hello_two_lines">Hello! \nText view!</string>
+    <string name="text_view_simple_hint">This is a hint.</string>
+    <string name="text_view_hint">This is a string for testing hint of textview.</string>
+    <string name="activity_forwarding">App/Forwarding</string>
+    <string name="forwarding">$$$</string>
+    <string name="go">Go</string>
+    <string name="back">Back</string>
+    <string name="forward_target">
+        Press back button and notice we don\'t see the previous activity.
+    </string>
+    <string name="edit_text">testing</string>
+    <string name="text">DialogTest</string>
+    <string name="text_country">Country</string>
+    <string name="text_name">Name</string>
+    <string name="hello_world">Hello, World!</string>
+    <string name="hello_android">Hello, Android!</string>
+    <string name="alert_dialog_username">Name:</string>
+    <string name="alert_dialog_password">Password:</string>
+    <string name="alert_dialog_positive">Positive</string>
+    <string name="alert_dialog_negative">Negative</string>
+    <string name="alert_dialog_neutral">Neutral</string>
+    <string name="notify">Notify </string>
+    <string name="tabs_1">testing</string>
+    <string name="table_layout_first">first</string>
+    <string name="table_layout_second">second</string>
+    <string name="table_layout_third">third</string>
+    <string name="table_layout_long">Very long to make the string out of the screen</string>
+    <string name="chronometer_text">Test Chronometer</string>
+    <string name="am">AM</string>
+    <string name="pm">PM</string>
+    <string name="viewgroup_test">ViewGroup test</string>
+    <string name="viewanimator_test">ViewAnimator test</string>
+    <string name="id_ok">OK</string>
+    <string name="id_cancel">Cancel</string>
+    <string name="context_test_string1">This is %s string.</string>
+    <string name="context_test_string2">This is test string.</string>
+    <string name="animationutils_test_instructions">Choose different animations</string>
+    <string name="animationutils_test_alpha">Alpha animation</string>
+    <string name="animationutils_test_scale">Scale animation</string>
+    <string name="animationutils_test_rotate">Rotate animation</string>
+    <string name="animationutils_test_translate">Translate animation</string>
+    <string name="animationutils_test_set">Animation set</string>
+    <string name="animationutils_test_layout">Layout animation</string>
+    <string name="animationutils_test_gridlayout">Grid layout animation</string>
+    <string name="twolinelistitem_test_text1">text1</string>
+    <string name="twolinelistitem_test_text2">text2</string>
+    <string name="metadata_text">metadata text</string>
+    <string name="horizontal_text_1">horizontal 1</string>
+    <string name="horizontal_text_2">horizontal 2</string>
+    <string name="horizontal_text_3">horizontal 3</string>
+    <string name="vertical_text_1">vertical 1</string>
+    <string name="vertical_text_2">vertical 2</string>
+    <string name="vertical_text_3">vertical 3</string>
+    <string name="reference">here</string>
+    <string name="coerceIntegerToString">100</string>
+    <string name="coerceBooleanToString">true</string>
+    <string name="coerceColorToString">#fff</string>
+    <string name="coerceFloatToString">100.0</string>
+    <string name="coerceDimensionToString">100px</string>
+    <string name="coerceFractionToString">100<xliff:g id="percent">%</xliff:g></string>
+    <string name="formattedStringNone">Format[]</string>
+    <string name="formattedStringOne">Format[<xliff:g id="format">%d</xliff:g>]</string>
+    <string name="formattedStringTwo">Format[<xliff:g id="format">%3$d,%2$s</xliff:g>]</string>
+    <string name="checkboxpref_key">checkboxpref_key</string>
+   <string name="checkboxpref_title">title of preference</string>
+   <string name="checkboxpref_summary">summary of preference</string>
+   <string name="checkboxpref_summary_on">summary on of preference</string>
+   <string name="checkboxpref_summary_off">summary off of preference</string>
+   <string name="checkboxpref_depend">checkboxpref_depend</string>
+   <string name="checkboxpref_depend_title"> depend title of preference</string>
+   <string name="checkboxpref_depend_summary"> depend summary of preference</string>
+   <string name="edittextpref_key">edittextpref_key</string>
+   <string name="edittextpref_default_value">default value of preference</string>
+   <string name="edittextpref_title">title of edit text preference</string>
+   <string name="edittextpref_summary">summary of edit text preference</string>
+   <string name="edittextpref_dialog_title">dialog title of edit text preference</string>
+   <string name="edittextpref_text">text of  edit text preference</string>
+   <string name="listpref_key">listpref_key</string>
+   <string name="listpref_title">title of list preference</string>
+   <string name="listpref_summary">summary of list preference</string>
+   <string name="listpref_dialogtitle">dialog title of list preference</string>
+   <string name="easy">Easy</string>
+   <string name="medium">Medium</string>
+   <string name="hard">Hard</string>
+   <string name="footer_view">Footer view</string>
+   <string name="header_view">Header view</string>
+   <string name="dialogpref_title">title of dialog preference </string>
+   <string name="dialogpref_dialog_title">dialog title of dialog preference </string>
+   <string name="dialogpref_key">dialogpref_key</string>
+   <string name="dialogpref_default_value">default value of dialog preference</string>
+   <string name="dialogpref_summary">summary of dialog preference</string>
+   <string name="dialogpref_message">message of dialog preference</string>
+   <string name="dialogpref_sure">Sure</string>
+   <string name="dialogpref_cancel">Cancel</string>
+   <string name="pref_key">pref_key</string>
+   <string name="pref_title">title of preference</string>
+   <string name="pref_summary">summary of preference</string>
+   <string name="pref_depend_key">pref_depend_key</string>
+   <string name="pref_depend_title"> depend title of preference</string>
+   <string name="pref_depend_summary"> depend summary of preference</string>
+   <string name="android_intent_action_preference">android.intent.action.PREFERENCE</string>
+   <string name="def_pref_key">def_pref_key</string>
+   <string name="def_pref_title">default preference</string>
+   <string name="def_pref_summary">This is default preference of cts</string>
+   <string name="relative_view1">view 1</string>
+   <string name="relative_view2">view 2</string>
+   <string name="relative_view3">view 3</string>
+   <string name="relative_view4">view 4</string>
+   <string name="relative_view5">view 5</string>
+   <string name="relative_view6">view 6</string>
+   <string name="relative_view7">view 7</string>
+   <string name="relative_view8">view 8</string>
+   <string name="relative_view9">view 9</string>
+   <string name="relative_view10">view 10</string>
+   <string name="relative_view11">view 11</string>
+   <string name="relative_view12">view 12</string>
+   <string name="relative_view13">view 13</string>
+   <string name="country">Country:</string>
+   <string name="symbol">Symbol:</string>
+   <string name="country_warning">No such country registered</string>
+   <string name="version_cur">base</string>
+   <string name="version_old">base</string>
+   <string name="version_v3">base</string>
+   <string name="authenticator_label">Android CTS</string>
+   <string name="search_label">Android CTS</string>
+   <string name="tag1">tag 1</string>
+   <string name="tag2">tag 2</string>
+
+   <string name="button">Button</string>
+   <string name="holo_test">Holo Test</string>
+   <string name="holo_generator">Holo Generator</string>
+   <string name="holo_light_test">Holo Light Test</string>
+   <string name="holo_light_generator">Holo Light Generator</string>
+   <string name="reference_image">Reference Image: </string>
+   <string name="generated_image">Generated Image: </string>
+   <string name="themes_prompt">Select a Theme:</string>
+   <string name="sample_text">Sample text goes here. I wanted something creative and whimsical
+but then I just got bored...</string>
+    <string name="long_text">This is a really long string which exceeds the width of the view.
+New devices have a much larger screen which actually enables long strings to be displayed
+with no fading. I have made this string longer to fix this case. If you are correcting this
+text, I would love to see the kind of devices you guys now use! Guys, maybe some devices need longer string!
+I think so, so how about double this string, like copy and paste!
+This is a really long string which exceeds the width of the view.
+New devices have a much larger screen which actually enables long strings to be displayed
+with no fading. I have made this string longer to fix this case. If you are correcting this
+text, I would love to see the kind of devices you guys now use! Guys, maybe some devices need longer string!
+I think so, so how about double this string, like copy and paste! </string>
+    <string name="rectangle200">"M 0,0 l 200,0 l 0, 200 l -200, 0 z"</string>
+</resources>
diff --git a/tests/tests/graphics/res/values/styles.xml b/tests/tests/graphics/res/values/styles.xml
new file mode 100644
index 0000000..20c80f8
--- /dev/null
+++ b/tests/tests/graphics/res/values/styles.xml
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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 xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <style name="Whatever">
+        <item name="type1">true</item>
+        <item name="type2">false</item>
+        <item name="type3">#ff0000ff</item>
+        <item name="type4">#ff00ff00</item>
+        <item name="type5">0.75px</item>
+        <item name="type6">10px</item>
+        <item name="type7">18px</item>
+        <item name="type8">@drawable/pass</item>
+        <item name="type9">3.14</item>
+        <item name="type10">100%</item>
+        <item name="type11">365</item>
+        <item name="type12">86400</item>
+        <item name="type13">@string/hello_android</item>
+        <item name="type14">TypedArray Test!</item>
+        <item name="type15">@array/difficultyLevel</item>
+        <item name="type16">Typed Value!</item>
+    </style>
+
+    <style name="TextViewWithoutColorAndAppearance">
+        <item name="android:textSize">18sp</item>
+    </style>
+
+    <style name="TextViewWithColorButWithOutAppearance">
+        <item name="android:textColor">#ff0000ff</item>
+    </style>
+
+    <style name="TextViewWithColorAndAppearance">
+        <item name="android:textColor">#ff0000ff</item>
+        <item name="android:textAppearance">@style/TextAppearance.WithColor</item>
+    </style>
+
+    <style name="TextViewWithoutColorButWithAppearance">
+        <item name="android:textAppearance">@style/TextAppearance.WithColor</item>
+    </style>
+
+    <style name="TextAppearance" parent="android:TextAppearance">
+    </style>
+
+    <style name="TextAppearance.WithColor">
+        <item name="android:textColor">#ffff0000</item>
+    </style>
+
+    <style name="TextAppearance.All">
+        <item name="android:textColor">@drawable/black</item>
+        <item name="android:textSize">20px</item>
+        <item name="android:textStyle">bold</item>
+        <item name="android:textColorHint">@drawable/red</item>
+        <item name="android:textColorLink">@drawable/blue</item>
+        <item name="android:textColorHighlight">@drawable/yellow</item>
+    </style>
+
+    <style name="TextAppearance.Colors">
+        <item name="android:textColor">@drawable/black</item>
+        <item name="android:textColorHint">@drawable/blue</item>
+        <item name="android:textColorLink">@drawable/yellow</item>
+        <item name="android:textColorHighlight">@drawable/red</item>
+    </style>
+
+    <style name="TextAppearance.NotColors">
+        <item name="android:textSize">17px</item>
+        <item name="android:typeface">sans</item>
+        <item name="android:textStyle">normal</item>
+    </style>
+
+    <style name="TextAppearance.Style">
+        <item name="android:textStyle">normal</item>
+    </style>
+
+    <style name="TestEnum1">
+        <item name="testEnum">val1</item>
+    </style>
+
+    <style name="TestEnum2">
+        <item name="testEnum">val2</item>
+    </style>
+
+    <style name="TestEnum10">
+        <item name="testEnum">val10</item>
+    </style>
+
+    <style name="TestFlag1">
+        <item name="testFlags">bit1</item>
+    </style>
+
+    <style name="TestFlag2">
+        <item name="testFlags">bit2</item>
+    </style>
+
+    <style name="TestFlag31">
+        <item name="testFlags">bit31</item>
+    </style>
+
+    <style name="TestFlag1And2">
+        <item name="testFlags">bit1|bit2</item>
+    </style>
+
+    <style name="TestFlag1And2And31">
+        <item name="testFlags">bit1|bit2|bit31</item>
+    </style>
+
+    <style name="TestEnum1.EmptyInherit" />
+
+    <style name="Theme_AlertDialog">
+        <item name="android:textSize">18sp</item>
+    </style>
+
+    <style name="TestProgressBar">
+        <item name="android:indeterminateOnly">false</item>
+        <item name="android:progressDrawable">?android:drawable/progress_horizontal</item>
+        <item name="android:indeterminateDrawable">?android:drawable/progress_horizontal</item>
+        <item name="android:minHeight">20dip</item>
+        <item name="android:maxHeight">20dip</item>
+        <item name="android:focusable">true</item>
+    </style>
+
+    <style name="Test_Theme">
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:panelColorForeground">#ff000000</item>
+        <item name="android:panelColorBackground">#ffffffff</item>
+    </style>
+
+    <style name="Theme_OverrideOuter">
+        <item name="themeType">1</item>
+    </style>
+
+    <style name="Theme_OverrideInner">
+        <item name="themeType">2</item>
+        <item name="themeOverrideAttr">@style/Theme_OverrideAttr</item>
+    </style>
+
+    <style name="Theme_OverrideAttr">
+        <item name="themeType">3</item>
+    </style>
+    
+    <style name="Theme_ThemedDrawableTest">
+        <item name="themeBoolean">true</item>
+        <item name="themeColor">@android:color/black</item>
+        <item name="themeFloat">1.0</item>
+        <item name="themeAngle">45.0</item>
+        <item name="themeInteger">1</item>
+        <item name="themeDimension">1px</item>
+        <item name="themeDrawable">@drawable/icon_black</item>
+        <item name="themeBitmap">@drawable/icon_black</item>
+        <item name="themeNinePatch">@drawable/ninepatch_0</item>
+        <item name="themeGravity">48</item>
+        <item name="themeTileMode">2</item>
+    </style>
+
+    <style name="Theme_NoSwipeDismiss">
+        <item name="android:windowSwipeToDismiss">false</item>
+    </style>
+
+</resources>
diff --git a/tests/res/xml/anim_list_correct.xml b/tests/tests/graphics/res/xml/anim_list_correct.xml
similarity index 100%
rename from tests/res/xml/anim_list_correct.xml
rename to tests/tests/graphics/res/xml/anim_list_correct.xml
diff --git a/tests/res/xml/anim_list_missing_item_drawable.xml b/tests/tests/graphics/res/xml/anim_list_missing_item_drawable.xml
similarity index 100%
rename from tests/res/xml/anim_list_missing_item_drawable.xml
rename to tests/tests/graphics/res/xml/anim_list_missing_item_drawable.xml
diff --git a/tests/res/xml/anim_list_missing_item_duration.xml b/tests/tests/graphics/res/xml/anim_list_missing_item_duration.xml
similarity index 100%
rename from tests/res/xml/anim_list_missing_item_duration.xml
rename to tests/tests/graphics/res/xml/anim_list_missing_item_duration.xml
diff --git a/tests/res/xml/anim_list_missing_list_attrs.xml b/tests/tests/graphics/res/xml/anim_list_missing_list_attrs.xml
similarity index 100%
rename from tests/res/xml/anim_list_missing_list_attrs.xml
rename to tests/tests/graphics/res/xml/anim_list_missing_list_attrs.xml
diff --git a/tests/res/xml/bitmapdrawable.xml b/tests/tests/graphics/res/xml/bitmapdrawable.xml
similarity index 100%
rename from tests/res/xml/bitmapdrawable.xml
rename to tests/tests/graphics/res/xml/bitmapdrawable.xml
diff --git a/tests/res/xml/drawable_test.xml b/tests/tests/graphics/res/xml/drawable_test.xml
similarity index 100%
rename from tests/res/xml/drawable_test.xml
rename to tests/tests/graphics/res/xml/drawable_test.xml
diff --git a/tests/res/xml/layerdrawable.xml b/tests/tests/graphics/res/xml/layerdrawable.xml
similarity index 100%
rename from tests/res/xml/layerdrawable.xml
rename to tests/tests/graphics/res/xml/layerdrawable.xml
diff --git a/tests/res/xml/level_list_correct.xml b/tests/tests/graphics/res/xml/level_list_correct.xml
similarity index 100%
rename from tests/res/xml/level_list_correct.xml
rename to tests/tests/graphics/res/xml/level_list_correct.xml
diff --git a/tests/res/xml/level_list_missing_item_drawable.xml b/tests/tests/graphics/res/xml/level_list_missing_item_drawable.xml
similarity index 100%
rename from tests/res/xml/level_list_missing_item_drawable.xml
rename to tests/tests/graphics/res/xml/level_list_missing_item_drawable.xml
diff --git a/tests/res/xml/level_list_missing_item_minlevel_maxlevel.xml b/tests/tests/graphics/res/xml/level_list_missing_item_minlevel_maxlevel.xml
similarity index 100%
rename from tests/res/xml/level_list_missing_item_minlevel_maxlevel.xml
rename to tests/tests/graphics/res/xml/level_list_missing_item_minlevel_maxlevel.xml
diff --git a/tests/res/xml/scaledrawable.xml b/tests/tests/graphics/res/xml/scaledrawable.xml
similarity index 100%
rename from tests/res/xml/scaledrawable.xml
rename to tests/tests/graphics/res/xml/scaledrawable.xml
diff --git a/tests/res/xml/selector_correct.xml b/tests/tests/graphics/res/xml/selector_correct.xml
similarity index 100%
rename from tests/res/xml/selector_correct.xml
rename to tests/tests/graphics/res/xml/selector_correct.xml
diff --git a/tests/res/xml/selector_missing_item_drawable.xml b/tests/tests/graphics/res/xml/selector_missing_item_drawable.xml
similarity index 100%
rename from tests/res/xml/selector_missing_item_drawable.xml
rename to tests/tests/graphics/res/xml/selector_missing_item_drawable.xml
diff --git a/tests/res/xml/selector_missing_selector_attrs.xml b/tests/tests/graphics/res/xml/selector_missing_selector_attrs.xml
similarity index 100%
rename from tests/res/xml/selector_missing_selector_attrs.xml
rename to tests/tests/graphics/res/xml/selector_missing_selector_attrs.xml
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java
index a80d2e2..2314ffb 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java
@@ -16,7 +16,7 @@
 
 package android.graphics.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.graphics.R;
 
 
 import android.content.res.Resources;
@@ -39,7 +39,6 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.OutputStream;
 import java.io.RandomAccessFile;
 
 public class BitmapFactoryTest extends InstrumentationTestCase {
@@ -69,6 +68,10 @@
         Config.ARGB_4444};
     private static int[] COLOR_TOLS = new int[] {16, 49, 576};
 
+    private static Config[] COLOR_CONFIGS_RGBA = new Config[] {Config.ARGB_8888,
+        Config.ARGB_4444};
+    private static int[] COLOR_TOLS_RGBA = new int[] {72, 124};
+
     private static int[] RAW_COLORS = new int[] {
         // raw data from R.drawable.premul_data
         Color.argb(255, 0, 0, 0),
@@ -197,11 +200,15 @@
             Bitmap bPng = BitmapFactory.decodeStream(iStreamPng, null, options);
             assertNotNull(bPng);
             assertEquals(bPng.getConfig(), COLOR_CONFIGS[k]);
+            assertFalse(bPng.isPremultiplied());
+            assertFalse(bPng.hasAlpha());
 
             InputStream iStreamWebp1 = obtainInputStream(R.drawable.webp_test);
             Bitmap bWebp1 = BitmapFactory.decodeStream(iStreamWebp1, null, options);
             assertNotNull(bWebp1);
-            compareBitmaps(bPng, bWebp1, COLOR_TOLS[k], true);
+            assertFalse(bWebp1.isPremultiplied());
+            assertFalse(bWebp1.hasAlpha());
+            compareBitmaps(bPng, bWebp1, COLOR_TOLS[k], true, bPng.isPremultiplied());
 
             // Compress the PNG image to WebP format (Quality=90) and decode it back.
             // This will test end-to-end WebP encoding and decoding.
@@ -210,7 +217,46 @@
             InputStream iStreamWebp2 = new ByteArrayInputStream(oStreamWebp.toByteArray());
             Bitmap bWebp2 = BitmapFactory.decodeStream(iStreamWebp2, null, options);
             assertNotNull(bWebp2);
-            compareBitmaps(bPng, bWebp2, COLOR_TOLS[k], true);
+            assertFalse(bWebp2.isPremultiplied());
+            assertFalse(bWebp2.hasAlpha());
+            compareBitmaps(bPng, bWebp2, COLOR_TOLS[k], true, bPng.isPremultiplied());
+        }
+    }
+
+    public void testDecodeStream5() throws IOException {
+        BitmapFactory.Options options = new BitmapFactory.Options();
+        for (int k = 0; k < COLOR_CONFIGS_RGBA.length; ++k) {
+            options.inPreferredConfig = COLOR_CONFIGS_RGBA[k];
+
+            // Decode the PNG & WebP (google_logo) images. The WebP image has
+            // been encoded from PNG image.
+            InputStream iStreamPng = obtainInputStream(R.drawable.google_logo_1);
+            Bitmap bPng = BitmapFactory.decodeStream(iStreamPng, null, options);
+            assertNotNull(bPng);
+            assertEquals(bPng.getConfig(), COLOR_CONFIGS_RGBA[k]);
+            assertTrue(bPng.isPremultiplied());
+            assertTrue(bPng.hasAlpha());
+
+            // Decode the corresponding WebP (transparent) image (google_logo_2.webp).
+            InputStream iStreamWebP1 = obtainInputStream(R.drawable.google_logo_2);
+            Bitmap bWebP1 = BitmapFactory.decodeStream(iStreamWebP1, null, options);
+            assertNotNull(bWebP1);
+            assertEquals(bWebP1.getConfig(), COLOR_CONFIGS_RGBA[k]);
+            assertTrue(bWebP1.isPremultiplied());
+            assertTrue(bWebP1.hasAlpha());
+            compareBitmaps(bPng, bWebP1, COLOR_TOLS_RGBA[k], true, bPng.isPremultiplied());
+
+            // Compress the PNG image to WebP format (Quality=90) and decode it back.
+            // This will test end-to-end WebP encoding and decoding.
+            ByteArrayOutputStream oStreamWebp = new ByteArrayOutputStream();
+            assertTrue(bPng.compress(CompressFormat.WEBP, 90, oStreamWebp));
+            InputStream iStreamWebp2 = new ByteArrayInputStream(oStreamWebp.toByteArray());
+            Bitmap bWebP2 = BitmapFactory.decodeStream(iStreamWebp2, null, options);
+            assertNotNull(bWebP2);
+            assertEquals(bWebP2.getConfig(), COLOR_CONFIGS_RGBA[k]);
+            assertTrue(bWebP2.isPremultiplied());
+            assertTrue(bWebP2.hasAlpha());
+            compareBitmaps(bPng, bWebP2, COLOR_TOLS_RGBA[k], true, bPng.isPremultiplied());
         }
     }
 
@@ -237,6 +283,50 @@
         assertEquals(START_WIDTH, b.getWidth());
     }
 
+    public void testDecodeFileDescriptor3() throws IOException {
+        // Arbitrary offsets to use. If the offset of the FD matches the offset of the image,
+        // decoding should succeed, but if they do not match, decoding should fail.
+        long ACTUAL_OFFSETS[] = new long[] { 0, 17 };
+        for (int RES_ID : RES_IDS) {
+            for (int j = 0; j < ACTUAL_OFFSETS.length; ++j) {
+                // FIXME: The purgeable test should attempt to purge the memory
+                // to force a re-decode.
+                for (boolean TEST_PURGEABLE : new boolean[] { false, true }) {
+                    BitmapFactory.Options opts = new BitmapFactory.Options();
+                    opts.inPurgeable = TEST_PURGEABLE;
+                    opts.inInputShareable = TEST_PURGEABLE;
+
+                    long actualOffset = ACTUAL_OFFSETS[j];
+                    String path = obtainPath(RES_ID, actualOffset);
+                    RandomAccessFile file = new RandomAccessFile(path, "r");
+                    FileDescriptor fd = file.getFD();
+                    assertTrue(fd.valid());
+
+                    // Set the offset to ACTUAL_OFFSET
+                    file.seek(actualOffset);
+                    assertEquals(file.getFilePointer(), actualOffset);
+
+                    // Now decode. This should be successful and leave the offset
+                    // unchanged.
+                    Bitmap b = BitmapFactory.decodeFileDescriptor(fd, null, opts);
+                    assertNotNull(b);
+                    assertEquals(file.getFilePointer(), actualOffset);
+
+                    // Now use the other offset. It should fail to decode, and
+                    // the offset should remain unchanged.
+                    long otherOffset = ACTUAL_OFFSETS[(j + 1) % ACTUAL_OFFSETS.length];
+                    assertFalse(otherOffset == actualOffset);
+                    file.seek(otherOffset);
+                    assertEquals(file.getFilePointer(), otherOffset);
+
+                    b = BitmapFactory.decodeFileDescriptor(fd, null, opts);
+                    assertNull(b);
+                    assertEquals(file.getFilePointer(), otherOffset);
+                }
+            }
+        }
+    }
+
     public void testDecodeFile1() throws IOException {
         Bitmap b = BitmapFactory.decodeFile(obtainPath(), mOpt1);
         assertNotNull(b);
@@ -275,6 +365,50 @@
         assertTrue(pass.isMutable());
     }
 
+    /**
+     * Create bitmap sized to load unscaled resources: start, pass, and alpha
+     */
+    private Bitmap createBitmapForReuse(int pixelCount) {
+        Bitmap bitmap = Bitmap.createBitmap(pixelCount, 1, Config.ARGB_8888);
+        bitmap.eraseColor(Color.BLACK);
+        bitmap.setHasAlpha(false);
+        return bitmap;
+    }
+
+    /**
+     * Decode resource with ResId into reuse bitmap without scaling, verifying expected hasAlpha
+     */
+    private void decodeResourceWithReuse(Bitmap reuse, int resId, boolean hasAlpha) {
+        BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inMutable = true;
+        options.inSampleSize = 1;
+        options.inScaled = false;
+        options.inBitmap = reuse;
+        Bitmap output = BitmapFactory.decodeResource(mRes, resId, options);
+        assertSame(reuse, output);
+        assertEquals(output.hasAlpha(), hasAlpha);
+    }
+
+    public void testDecodeReuseHasAlpha() throws IOException {
+        final int bitmapSize = 31; // size in pixels of start, pass, and alpha resources
+        final int pixelCount = bitmapSize * bitmapSize;
+
+        // Test reuse, hasAlpha false and true
+        Bitmap bitmap = createBitmapForReuse(pixelCount);
+        decodeResourceWithReuse(bitmap, R.drawable.start, false);
+        decodeResourceWithReuse(bitmap, R.drawable.alpha, true);
+
+        // Test pre-reconfigure, hasAlpha false and true
+        bitmap = createBitmapForReuse(pixelCount);
+        bitmap.reconfigure(bitmapSize, bitmapSize, Config.ARGB_8888);
+        bitmap.setHasAlpha(true);
+        decodeResourceWithReuse(bitmap, R.drawable.start, false);
+
+        bitmap = createBitmapForReuse(pixelCount);
+        bitmap.reconfigure(bitmapSize, bitmapSize, Config.ARGB_8888);
+        decodeResourceWithReuse(bitmap, R.drawable.alpha, true);
+    }
+
     public void testDecodeReuseFormats() throws IOException {
         // reuse should support all image formats
         for (int i = 0; i < RES_IDS.length; ++i) {
@@ -464,17 +598,32 @@
     }
 
     private String obtainPath() throws IOException {
+        return obtainPath(R.drawable.start, 0);
+    }
+
+    /*
+     * Create a new file and return a path to it.
+     * @param resId Original file. It will be copied into the new file.
+     * @param offset Number of zeroes to write to the new file before the
+     *               copied file. This allows testing decodeFileDescriptor
+     *               with an offset. Must be less than or equal to 1024
+     */
+    private String obtainPath(int resId, long offset) throws IOException {
         File dir = getInstrumentation().getTargetContext().getFilesDir();
         dir.mkdirs();
+        // The suffix does not necessarily represent theactual file type.
         File file = new File(dir, "test.jpg");
         if (!file.createNewFile()) {
             if (!file.exists()) {
                 fail("Failed to create new File!");
             }
         }
-        InputStream is = obtainInputStream();
+        InputStream is = obtainInputStream(resId);
         FileOutputStream fOutput = new FileOutputStream(file);
         byte[] dataBuffer = new byte[1024];
+        // Write a bunch of zeroes before the image.
+        assertTrue(offset <= 1024);
+        fOutput.write(dataBuffer, 0, (int) offset);
         int readLength = 0;
         while ((readLength = is.read(dataBuffer)) != -1) {
             fOutput.write(dataBuffer, 0, readLength);
@@ -488,7 +637,7 @@
     // lessThanMargin is to indicate whether we expect the mean square error
     // to be "less than" or "no less than".
     private void compareBitmaps(Bitmap expected, Bitmap actual,
-            int mseMargin, boolean lessThanMargin) {
+            int mseMargin, boolean lessThanMargin, boolean isPremultiplied) {
         final int width = expected.getWidth();
         final int height = expected.getHeight();
 
@@ -501,30 +650,49 @@
         int[] expectedColors = new int [width * height];
         int[] actualColors = new int [width * height];
 
+        // Bitmap.getPixels() returns colors with non-premultiplied ARGB values.
         expected.getPixels(expectedColors, 0, width, 0, 0, width, height);
         actual.getPixels(actualColors, 0, width, 0, 0, width, height);
 
         for (int row = 0; row < height; ++row) {
             for (int col = 0; col < width; ++col) {
                 int idx = row * width + col;
-                mse += distance(expectedColors[idx], actualColors[idx]);
+                mse += distance(expectedColors[idx], actualColors[idx], isPremultiplied);
             }
         }
         mse /= width * height;
 
         if (lessThanMargin) {
-            assertTrue("MSE too large for normal case: " + mse,
+            assertTrue("MSE " + mse +  "larger than the threshold: " + mseMargin,
                     mse <= mseMargin);
         } else {
-            assertFalse("MSE too small for abnormal case: " + mse,
+            assertFalse("MSE " + mse +  "smaller than the threshold: " + mseMargin,
                     mse <= mseMargin);
         }
     }
 
-    private double distance(int expect, int actual) {
-        final int r = Color.red(actual) - Color.red(expect);
-        final int g = Color.green(actual) - Color.green(expect);
-        final int b = Color.blue(actual) - Color.blue(expect);
-        return r * r + g * g + b * b;
+    private int multiplyAlpha(int color, int alpha) {
+        return (color * alpha + 127) / 255;
+    }
+
+    // For the Bitmap with Alpha, multiply the Alpha values to get the effective
+    // RGB colors and then compute the color-distance.
+    private double distance(int expect, int actual, boolean isPremultiplied) {
+        if (isPremultiplied) {
+            final int a1 = Color.alpha(actual);
+            final int a2 = Color.alpha(expect);
+            final int r = multiplyAlpha(Color.red(actual), a1) -
+                    multiplyAlpha(Color.red(expect), a2);
+            final int g = multiplyAlpha(Color.green(actual), a1) -
+                    multiplyAlpha(Color.green(expect), a2);
+            final int b = multiplyAlpha(Color.blue(actual), a1) -
+                    multiplyAlpha(Color.blue(expect), a2);
+            return r * r + g * g + b * b;
+        } else {
+            final int r = Color.red(actual) - Color.red(expect);
+            final int g = Color.green(actual) - Color.green(expect);
+            final int b = Color.blue(actual) - Color.blue(expect);
+            return r * r + g * g + b * b;
+        }
     }
 }
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapRegionDecoderTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapRegionDecoderTest.java
index c981db3..adce1c4 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapRegionDecoderTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapRegionDecoderTest.java
@@ -29,7 +29,7 @@
 import android.test.InstrumentationTestCase;
 import android.util.Log;
 
-import com.android.cts.stub.R;
+import com.android.cts.graphics.R;
 
 
 import java.io.ByteArrayOutputStream;
@@ -88,7 +88,7 @@
     private int mMseMargin = 3 * (1 * 1);
 
     // MSE margin for WebP Region-Decoding for 'Config.RGB_565' is little bigger.
-    private int mMseMarginWebPConfigRgb565 = 5;
+    private int mMseMarginWebPConfigRgb565 = 8;
 
 
     @Override
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java
index 997560d..f58b871 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java
@@ -15,10 +15,11 @@
  */
 package android.graphics.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.graphics.R;
 
 
 import android.content.res.Resources;
+import android.cts.util.WidgetTestUtils;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
@@ -30,7 +31,6 @@
 import android.os.Parcel;
 import android.test.AndroidTestCase;
 import android.util.DisplayMetrics;
-import android.widget.cts.WidgetTestUtils;
 
 import java.io.ByteArrayOutputStream;
 import java.nio.ByteBuffer;
@@ -513,6 +513,102 @@
         }
     }
 
+    // Used by testAlphaAndPremul. FIXME: Should we also test Index8? That would require decoding a
+    // Bitmap, since one cannot be created directly. It will also have a Config of null, since it
+    // has no Java equivalent.
+    private static Config[] CONFIGS = new Config[] { Config.ALPHA_8, Config.ARGB_4444,
+            Config.ARGB_8888, Config.RGB_565 };
+
+    // test that reconfigure, setHasAlpha, and setPremultiplied behave as expected with
+    // respect to alpha and premultiplied.
+    public void testAlphaAndPremul() {
+        boolean falseTrue[] = new boolean[] { false, true };
+        for (Config fromConfig : CONFIGS) {
+            for (Config toConfig : CONFIGS) {
+                for (boolean hasAlpha : falseTrue) {
+                    for (boolean isPremul : falseTrue) {
+                        Bitmap bitmap = Bitmap.createBitmap(10, 10, fromConfig);
+
+                        // 4444 is deprecated, and will convert to 8888. No need to
+                        // attempt a reconfigure, which will be tested when fromConfig
+                        // is 8888.
+                        if (fromConfig == Config.ARGB_4444) {
+                            assertEquals(bitmap.getConfig(), Config.ARGB_8888);
+                            break;
+                        }
+
+                        bitmap.setHasAlpha(hasAlpha);
+                        bitmap.setPremultiplied(isPremul);
+
+                        checkAlphaAndPremul(bitmap, hasAlpha, isPremul, false);
+
+                        // reconfigure to a smaller size so the function will still succeed when
+                        // going to a Config that requires more bits.
+                        bitmap.reconfigure(1, 1, toConfig);
+                        if (toConfig == Config.ARGB_4444) {
+                            assertEquals(bitmap.getConfig(), Config.ARGB_8888);
+                        } else {
+                            assertEquals(bitmap.getConfig(), toConfig);
+                        }
+
+                        // Check that the alpha and premultiplied state has not changed (unless
+                        // we expected it to).
+                        checkAlphaAndPremul(bitmap, hasAlpha, isPremul, fromConfig == Config.RGB_565);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     *  Assert that bitmap returns the appropriate values for hasAlpha() and isPremultiplied().
+     *  @param bitmap Bitmap to check.
+     *  @param expectedAlpha Expected return value from bitmap.hasAlpha(). Note that this is based
+     *          on what was set, but may be different from the actual return value depending on the
+     *          Config and convertedFrom565.
+     *  @param expectedPremul Expected return value from bitmap.isPremultiplied(). Similar to
+     *          expectedAlpha, this is based on what was set, but may be different from the actual
+     *          return value depending on the Config.
+     *  @param convertedFrom565 Whether bitmap was converted to its current Config by being
+     *          reconfigured from RGB_565. If true, and bitmap is now a Config that supports alpha,
+     *          hasAlpha() is expected to be true even if expectedAlpha is false.
+     */
+    private void checkAlphaAndPremul(Bitmap bitmap, boolean expectedAlpha, boolean expectedPremul,
+            boolean convertedFrom565) {
+        switch (bitmap.getConfig()) {
+            case ARGB_4444:
+                // This shouldn't happen, since we don't allow creating or converting
+                // to 4444.
+                assertFalse(true);
+                break;
+            case RGB_565:
+                assertFalse(bitmap.hasAlpha());
+                assertFalse(bitmap.isPremultiplied());
+                break;
+            case ALPHA_8:
+                // ALPHA_8 behaves mostly the same as 8888, except for premultiplied. Fall through.
+            case ARGB_8888:
+                // Since 565 is necessarily opaque, we revert to hasAlpha when switching to a type
+                // that can have alpha.
+                if (convertedFrom565) {
+                    assertTrue(bitmap.hasAlpha());
+                } else {
+                    assertEquals(bitmap.hasAlpha(), expectedAlpha);
+                }
+
+                if (bitmap.hasAlpha()) {
+                    // ALPHA_8's premultiplied status is undefined.
+                    if (bitmap.getConfig() != Config.ALPHA_8) {
+                        assertEquals(bitmap.isPremultiplied(), expectedPremul);
+                    }
+                } else {
+                    // Opaque bitmap is never considered premultiplied.
+                    assertFalse(bitmap.isPremultiplied());
+                }
+                break;
+        }
+    }
+
     public void testSetConfig() {
         mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);
         int alloc = mBitmap.getAllocationByteCount();
diff --git a/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java b/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
index 4102957..d5391a3 100644
--- a/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
@@ -41,8 +41,9 @@
 import android.text.SpannableStringBuilder;
 import android.text.SpannedString;
 
-import com.android.cts.stub.R;
+import com.android.cts.graphics.R;
 
+import java.util.Vector;
 
 public class CanvasTest extends InstrumentationTestCase {
     private final static int PAINT_COLOR = 0xff00ff00;
@@ -267,6 +268,86 @@
         }
     }
 
+    public void testSaveFlags1() {
+        int[] flags = {
+            Canvas.MATRIX_SAVE_FLAG,
+        };
+        verifySaveFlagsSequence(flags);
+    }
+
+    public void testSaveFlags2() {
+        int[] flags = {
+            Canvas.CLIP_SAVE_FLAG,
+        };
+        verifySaveFlagsSequence(flags);
+    }
+
+    public void testSaveFlags3() {
+        int[] flags = {
+            Canvas.ALL_SAVE_FLAG,
+            Canvas.MATRIX_SAVE_FLAG,
+            Canvas.MATRIX_SAVE_FLAG,
+        };
+        verifySaveFlagsSequence(flags);
+    }
+
+    public void testSaveFlags4() {
+        int[] flags = {
+            Canvas.ALL_SAVE_FLAG,
+            Canvas.CLIP_SAVE_FLAG,
+            Canvas.CLIP_SAVE_FLAG,
+        };
+        verifySaveFlagsSequence(flags);
+    }
+
+    public void testSaveFlags5() {
+        int[] flags = {
+            Canvas.MATRIX_SAVE_FLAG,
+            Canvas.MATRIX_SAVE_FLAG,
+            Canvas.CLIP_SAVE_FLAG,
+            Canvas.CLIP_SAVE_FLAG,
+            Canvas.MATRIX_SAVE_FLAG,
+            Canvas.MATRIX_SAVE_FLAG,
+        };
+        verifySaveFlagsSequence(flags);
+    }
+
+    public void testSaveFlags6() {
+        int[] flags = {
+            Canvas.CLIP_SAVE_FLAG,
+            Canvas.CLIP_SAVE_FLAG,
+            Canvas.MATRIX_SAVE_FLAG,
+            Canvas.MATRIX_SAVE_FLAG,
+            Canvas.CLIP_SAVE_FLAG,
+            Canvas.CLIP_SAVE_FLAG,
+        };
+        verifySaveFlagsSequence(flags);
+    }
+
+    public void testSaveFlags7() {
+        int[] flags = {
+            Canvas.MATRIX_SAVE_FLAG,
+            Canvas.MATRIX_SAVE_FLAG,
+            Canvas.ALL_SAVE_FLAG,
+            Canvas.ALL_SAVE_FLAG,
+            Canvas.CLIP_SAVE_FLAG,
+            Canvas.CLIP_SAVE_FLAG,
+        };
+        verifySaveFlagsSequence(flags);
+    }
+
+    public void testSaveFlags8() {
+        int[] flags = {
+            Canvas.MATRIX_SAVE_FLAG,
+            Canvas.CLIP_SAVE_FLAG,
+            Canvas.ALL_SAVE_FLAG,
+            Canvas.MATRIX_SAVE_FLAG,
+            Canvas.CLIP_SAVE_FLAG,
+            Canvas.ALL_SAVE_FLAG,
+        };
+        verifySaveFlagsSequence(flags);
+    }
+
     public void testSaveLayer1() {
         final Paint p = new Paint();
         final RectF rF = new RectF(0, 10, 31, 0);
@@ -906,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();
@@ -1727,4 +1832,49 @@
         assertEquals(0.0f, values[7]);
         assertEquals(1.0f, values[8]);
     }
+
+    private RectF getDeviceClip() {
+        final RectF clip = new RectF(mCanvas.getClipBounds());
+        mCanvas.getMatrix().mapRect(clip);
+        return clip;
+    }
+
+    // Loops through the passed flags, applying each in order with successive calls
+    // to save, verifying the clip and matrix values when restoring.
+    private void verifySaveFlagsSequence(int[] saveFlags) {
+        final Vector<RectF> clips = new Vector<RectF>();
+        final Vector<Matrix> matrices = new Vector<Matrix>();
+
+        assertTrue(BITMAP_WIDTH > saveFlags.length);
+        assertTrue(BITMAP_HEIGHT > saveFlags.length);
+
+        for (int i = 0; i < saveFlags.length; ++i) {
+            clips.add(getDeviceClip());
+            matrices.add(mCanvas.getMatrix());
+            mCanvas.save(saveFlags[i]);
+
+            mCanvas.translate(1, 1);
+            mCanvas.clipRect(0, 0, BITMAP_WIDTH - i - 1, BITMAP_HEIGHT - i - 1);
+
+            if (i  > 0) {
+                // We are mutating the state on each iteration.
+                assertFalse(clips.elementAt(i).equals(clips.elementAt(i - 1)));
+                assertFalse(matrices.elementAt(i).equals(matrices.elementAt(i - 1)));
+            }
+        }
+
+        for (int i = saveFlags.length - 1; i >= 0; --i) {
+            // If clip/matrix flags are not set, the associated state should be preserved.
+            if ((saveFlags[i] & Canvas.CLIP_SAVE_FLAG) == 0) {
+                clips.elementAt(i).set(getDeviceClip());
+            }
+            if ((saveFlags[i] & Canvas.MATRIX_SAVE_FLAG) == 0) {
+                matrices.elementAt(i).set(mCanvas.getMatrix());
+            }
+
+            mCanvas.restore();
+            assertEquals(clips.elementAt(i), getDeviceClip());
+            assertEquals(matrices.elementAt(i), mCanvas.getMatrix());
+        }
+    }
 }
diff --git a/tests/tests/graphics/src/android/graphics/cts/ImageViewCtsActivity.java b/tests/tests/graphics/src/android/graphics/cts/ImageViewCtsActivity.java
new file mode 100644
index 0000000..b9887b7
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/cts/ImageViewCtsActivity.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2008 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.cts;
+
+import com.android.cts.graphics.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * A minimal application for {@link ImageView} test.
+ */
+public class ImageViewCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.imageview_layout);
+    }
+}
+
diff --git a/tests/tests/graphics/src/android/graphics/cts/LayerRasterizerTest.java b/tests/tests/graphics/src/android/graphics/cts/LayerRasterizerTest.java
index 4309ac5..289ee77 100644
--- a/tests/tests/graphics/src/android/graphics/cts/LayerRasterizerTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/LayerRasterizerTest.java
@@ -17,32 +17,44 @@
 package android.graphics.cts;
 
 import junit.framework.TestCase;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
 import android.graphics.LayerRasterizer;
 import android.graphics.Paint;
+import android.graphics.Rasterizer;
 
 public class LayerRasterizerTest extends TestCase {
+    private final static int BITMAP_WIDTH = 16;
+    private final static int BITMAP_HEIGHT = 16;
+
+    private void exerciseRasterizer(Rasterizer rasterizer) {
+        Bitmap bm = Bitmap.createBitmap(BITMAP_WIDTH, BITMAP_HEIGHT, Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(bm);
+        Paint paint = new Paint();
+
+        // just want to confirm that we don't crash or throw an exception
+        paint.setRasterizer(rasterizer);
+        canvas.drawCircle(BITMAP_WIDTH/2, BITMAP_WIDTH/2, BITMAP_WIDTH/2, paint);
+    }
 
     public void testConstructor() {
-
-        // new the LayerRasterizer instance
-        new LayerRasterizer();
+        exerciseRasterizer(new LayerRasterizer());
     }
 
     public void testAddLayer1() {
-        // new the LayerRasterizer instance
         LayerRasterizer layerRasterizer = new LayerRasterizer();
         Paint p = new Paint();
         layerRasterizer.addLayer(p);
-        // this function called a native function and this test just make sure
-        // it doesn't throw out any exception.
+        exerciseRasterizer(layerRasterizer);
     }
 
     public void testAddLayer2() {
-        // new the LayerRasterizer instance
         LayerRasterizer layerRasterizer = new LayerRasterizer();
         layerRasterizer.addLayer(new Paint(), 1.0f, 1.0f);
-        // this function called a native function and this test just make sure
-        // it doesn't throw out any exception.
+        exerciseRasterizer(layerRasterizer);
+        // explicitly add another layer and draw again
+        layerRasterizer.addLayer(new Paint(), 2.0f, 2.0f);
+        exerciseRasterizer(layerRasterizer);
     }
 
 }
diff --git a/tests/tests/graphics/src/android/graphics/cts/MockActivity.java b/tests/tests/graphics/src/android/graphics/cts/MockActivity.java
new file mode 100644
index 0000000..addc6d3
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/cts/MockActivity.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2008 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.cts;
+
+import android.app.Activity;
+
+public class MockActivity extends Activity {
+
+}
diff --git a/tests/tests/graphics/src/android/graphics/cts/MovieTest.java b/tests/tests/graphics/src/android/graphics/cts/MovieTest.java
index f129035..b18b800 100644
--- a/tests/tests/graphics/src/android/graphics/cts/MovieTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/MovieTest.java
@@ -23,21 +23,19 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 
-import android.app.cts.MockActivity;
 import android.content.Context;
+import android.cts.util.WidgetTestUtils;
 import android.graphics.Canvas;
 import android.graphics.Movie;
 import android.graphics.Paint;
 import android.test.ActivityInstrumentationTestCase2;
-import android.widget.cts.WidgetTestUtils;
-
 
 public class MovieTest extends ActivityInstrumentationTestCase2<MockActivity> {
     private Movie mMovie;
-    private final int MOVIE = com.android.cts.stub.R.drawable.animated;
+    private final int MOVIE = com.android.cts.graphics.R.drawable.animated;
 
     public MovieTest() {
-        super("com.android.cts.stub", MockActivity.class);
+        super("com.android.cts.graphics", MockActivity.class);
     }
 
     @Override
diff --git a/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java b/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java
index d5fcc62..d37ec90 100644
--- a/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/NinePatchTest.java
@@ -16,7 +16,7 @@
 
 package android.graphics.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.graphics.R;
 
 
 import android.content.res.Resources;
diff --git a/tests/tests/graphics/src/android/graphics/cts/PaintFlagsDrawFilterTest.java b/tests/tests/graphics/src/android/graphics/cts/PaintFlagsDrawFilterTest.java
index 31dbf16..ee3ec7c 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PaintFlagsDrawFilterTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PaintFlagsDrawFilterTest.java
@@ -107,4 +107,82 @@
         // underline is under the text or at least at the bottom of it
         assertTrue(rect.top >= TEXT_Y);
     }
+
+    // Tests that FILTER_BITMAP_FLAG is handled properly.
+    public void testPaintFlagsDrawFilter2() {
+        // Create a bitmap with alternating black and white pixels.
+        int kWidth = 5;
+        int kHeight = 5;
+        int colors[] = new int [] { Color.WHITE, Color.BLACK };
+        int k = 0;
+        Bitmap grid = Bitmap.createBitmap(kWidth, kHeight, Config.ARGB_8888);
+        for (int i = 0; i < kWidth; ++i) {
+            for (int j = 0; j < kHeight; ++j) {
+                grid.setPixel(i, j, colors[k]);
+                k = (k + 1) % 2;
+            }
+        }
+
+        // Setup a scaled canvas for drawing the bitmap, with and without FILTER_BITMAP_FLAG set.
+        // When the flag is set, there will be gray pixels. When the flag is not set, all pixels
+        // will be either black or white.
+        int kScale = 5;
+        Bitmap dst = Bitmap.createBitmap(kWidth * kScale, kHeight * kScale, Config.ARGB_8888);
+        Canvas canvas = new Canvas(dst);
+        canvas.scale(kScale, kScale);
+
+        // Drawn without FILTER_BITMAP_FLAG, all pixels will be black or white.
+        Paint simplePaint = new Paint();
+        canvas.drawBitmap(grid, 0, 0, simplePaint);
+
+        assertContainsOnlyBlackAndWhite(dst);
+
+        // Drawn with FILTER_BITMAP_FLAG, some pixels will be somewhere in between.
+        Paint filterBitmapPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
+        canvas.drawBitmap(grid, 0, 0, filterBitmapPaint);
+
+        assertContainsNonBW(dst);
+
+        // Drawing with a paint that FILTER_BITMAP_FLAG set and a DrawFilter that removes
+        // FILTER_BITMAP_FLAG should remove the effect of the flag, resulting in all pixels being
+        // either black or white.
+        canvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.FILTER_BITMAP_FLAG, 0));
+        canvas.drawBitmap(grid, 0, 0, filterBitmapPaint);
+
+        assertContainsOnlyBlackAndWhite(dst);
+
+        // Likewise, drawing with a DrawFilter that sets FILTER_BITMAP_FLAG should filter,
+        // resulting in gray pixels.
+        canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.FILTER_BITMAP_FLAG));
+        canvas.drawBitmap(grid, 0, 0, simplePaint);
+
+        assertContainsNonBW(dst);
+    }
+
+    // Assert that at least one pixel is neither black nor white. This is used to verify that
+    // filtering was done, since the original bitmap only contained black and white pixels.
+    private void assertContainsNonBW(Bitmap bitmap) {
+        for (int i = 0; i < bitmap.getWidth(); ++i) {
+            for (int j = 0; j < bitmap.getHeight(); ++j) {
+                int color = bitmap.getPixel(i, j);
+                if (color != Color.BLACK && color != Color.WHITE) {
+                    // Filtering must have been done.
+                    return;
+                }
+            }
+        }
+        // Filtering did not happen.
+        assertTrue(false);
+    }
+
+    // Assert that every pixel is either black or white. Used to verify that no filtering was
+    // done, since the original bitmap contained only black and white pixels.
+    private void assertContainsOnlyBlackAndWhite(Bitmap bitmap) {
+        for (int i = 0; i < bitmap.getWidth(); ++i) {
+            for (int j = 0; j < bitmap.getHeight(); ++j) {
+                int color = bitmap.getPixel(i, j);
+                assertTrue(color == Color.BLACK || color == Color.WHITE);
+            }
+        }
+    }
 }
diff --git a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
index f4904fc..1f709d3 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
@@ -112,6 +112,30 @@
         // Reverse measure substring in the middle and restrict width to the last 2 characters.
         assertBreakText(text, textChars, textSpan, 2, 5, false, widths[3] + widths[4],
                 2, widths[3] + widths[4]);
+
+        // a single Emoji (U+1f601)
+        String emoji = "\ud83d\ude01";
+        char[] emojiChars = emoji.toCharArray();
+        SpannedString emojiSpan = new SpannedString(emoji);
+
+        float[] emojiWidths = new float[emoji.length()];
+        assertEquals(emoji.length(), p.getTextWidths(emoji, emojiWidths));
+
+        // Measure substring with a cluster
+        assertBreakText(emoji, emojiChars, emojiSpan, 0, 2, true, 0,
+                0, 0);
+
+        // Measure substring with a cluster
+        assertBreakText(emoji, emojiChars, emojiSpan, 0, 2, true, emojiWidths[0],
+                2, emojiWidths[0]);
+
+        // Reverse measure substring with a cluster
+        assertBreakText(emoji, emojiChars, emojiSpan, 0, 2, false, 0,
+                0, 0);
+
+        // Measure substring with a cluster
+        assertBreakText(emoji, emojiChars, emojiSpan, 0, 2, false, emojiWidths[0],
+                2, emojiWidths[0]);
     }
 
     private void assertBreakText(String text, char[] textChars, SpannedString textSpan,
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/cts/YuvImageTest.java b/tests/tests/graphics/src/android/graphics/cts/YuvImageTest.java
index f0ffc13..02b3afa 100644
--- a/tests/tests/graphics/src/android/graphics/cts/YuvImageTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/YuvImageTest.java
@@ -33,7 +33,7 @@
 import android.test.AndroidTestCase;
 import android.util.Log;
 
-import com.android.cts.stub.R;
+import com.android.cts.graphics.R;
 
 
 public class YuvImageTest extends AndroidTestCase {
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
new file mode 100644
index 0000000..b4c64e2
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
@@ -0,0 +1,186 @@
+/*
+ * 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.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.AnimatedVectorDrawable;
+import android.graphics.drawable.Drawable.ConstantState;
+import android.test.AndroidTestCase;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Xml;
+
+import com.android.cts.graphics.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+public class AnimatedVectorDrawableTest extends AndroidTestCase {
+    private static final String LOGTAG = AnimatedVectorDrawableTest.class.getSimpleName();
+
+    private static final int IMAGE_WIDTH = 64;
+    private static final int IMAGE_HEIGHT = 64;
+
+    private Resources mResources;
+    private AnimatedVectorDrawable mAnimatedVectorDrawable;
+    private Bitmap mBitmap;
+    private Canvas mCanvas;
+    private static final boolean DBG_DUMP_PNG = false;
+    private int mResId = R.drawable.animation_vector_drawable_grouping_1;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mBitmap = Bitmap.createBitmap(IMAGE_WIDTH, IMAGE_HEIGHT, Bitmap.Config.ARGB_8888);
+        mCanvas = new Canvas(mBitmap);
+        mAnimatedVectorDrawable = new AnimatedVectorDrawable();
+
+        mResources = mContext.getResources();
+    }
+
+    // This is only for debugging or golden image (re)generation purpose.
+    private void saveVectorDrawableIntoPNG(Bitmap bitmap, int resId) throws IOException {
+        // 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(resId);
+            File originalFile = new File(originalFilePath);
+            String fileFullName = originalFile.getName();
+            String fileTitle = fileFullName.substring(0, fileFullName.lastIndexOf("."));
+            String outputFilename = outputFolder + fileTitle + "_golden.png";
+            File outputFile = new File(outputFilename);
+            if (!outputFile.exists()) {
+                outputFile.createNewFile();
+            }
+
+            out = new FileOutputStream(outputFile, false);
+            bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
+            Log.v(LOGTAG, "Write test No." + outputFilename + " to file successfully.");
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            if (out != null) {
+                out.close();
+            }
+        }
+    }
+
+    public void testInflate() throws Exception {
+        // Setup AnimatedVectorDrawable from xml file
+        XmlPullParser parser = mResources.getXml(mResId);
+        AttributeSet attrs = Xml.asAttributeSet(parser);
+
+        int type;
+        while ((type=parser.next()) != XmlPullParser.START_TAG &&
+                type != XmlPullParser.END_DOCUMENT) {
+            // Empty loop
+        }
+
+        if (type != XmlPullParser.START_TAG) {
+            throw new XmlPullParserException("No start tag found");
+        }
+
+        mAnimatedVectorDrawable.inflate(mResources, parser, attrs);
+        mAnimatedVectorDrawable.setBounds(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
+        mBitmap.eraseColor(0);
+        mAnimatedVectorDrawable.draw(mCanvas);
+        int sunColor = mBitmap.getPixel(IMAGE_WIDTH / 2, IMAGE_HEIGHT / 2);
+        int earthColor = mBitmap.getPixel(IMAGE_WIDTH * 3 / 4 + 2, IMAGE_HEIGHT / 2);
+        assertTrue(sunColor == 0xFFFF8000);
+        assertTrue(earthColor == 0xFF5656EA);
+
+        if (DBG_DUMP_PNG) {
+            saveVectorDrawableIntoPNG(mBitmap, mResId);
+        }
+    }
+
+    public void testGetChangingConfigurations() {
+        AnimatedVectorDrawable avd = new AnimatedVectorDrawable();
+        ConstantState constantState = avd.getConstantState();
+
+        // default
+        assertEquals(0, constantState.getChangingConfigurations());
+        assertEquals(0, avd.getChangingConfigurations());
+
+        // change the drawable's configuration does not affect the state's configuration
+        avd.setChangingConfigurations(0xff);
+        assertEquals(0xff, avd.getChangingConfigurations());
+        assertEquals(0, constantState.getChangingConfigurations());
+
+        // the state's configuration get refreshed
+        constantState = avd.getConstantState();
+        assertEquals(0xff,  constantState.getChangingConfigurations());
+
+        // set a new configuration to drawable
+        avd.setChangingConfigurations(0xff00);
+        assertEquals(0xff,  constantState.getChangingConfigurations());
+        assertEquals(0xffff,  avd.getChangingConfigurations());
+    }
+
+    public void testGetConstantState() {
+        AnimatedVectorDrawable AnimatedVectorDrawable = new AnimatedVectorDrawable();
+        ConstantState constantState = AnimatedVectorDrawable.getConstantState();
+        assertNotNull(constantState);
+        assertEquals(0, constantState.getChangingConfigurations());
+
+        AnimatedVectorDrawable.setChangingConfigurations(1);
+        constantState = AnimatedVectorDrawable.getConstantState();
+        assertNotNull(constantState);
+        assertEquals(1, constantState.getChangingConfigurations());
+    }
+
+    public void testMutate() {
+        Resources resources = mContext.getResources();
+
+        AnimatedVectorDrawable d1 = (AnimatedVectorDrawable) resources.getDrawable(mResId);
+        AnimatedVectorDrawable d2 = (AnimatedVectorDrawable) resources.getDrawable(mResId);
+        AnimatedVectorDrawable d3 = (AnimatedVectorDrawable) resources.getDrawable(mResId);
+        int originalAlpha = d2.getAlpha();
+        int newAlpha = (originalAlpha + 1) % 255;
+
+        // AVD is different than VectorDrawable. Every instance of it is a deep copy
+        // of the VectorDrawable.
+        // So every setAlpha operation will happen only to that specific object.
+        d1.setAlpha(newAlpha);
+        assertEquals(newAlpha, d1.getAlpha());
+        assertEquals(originalAlpha, d2.getAlpha());
+        assertEquals(originalAlpha, d3.getAlpha());
+
+        d1.mutate();
+        d1.setAlpha(0x40);
+        assertEquals(0x40, d1.getAlpha());
+        assertEquals(originalAlpha, d2.getAlpha());
+        assertEquals(originalAlpha, d3.getAlpha());
+
+        d2.setAlpha(0x20);
+        assertEquals(0x40, d1.getAlpha());
+        assertEquals(0x20, d2.getAlpha());
+        assertEquals(originalAlpha, d3.getAlpha());
+    }
+}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimationDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimationDrawableTest.java
index fc9efdd..c278ed2 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimationDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimationDrawableTest.java
@@ -16,7 +16,7 @@
 
 package android.graphics.drawable.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.graphics.R;
 
 
 import org.xmlpull.v1.XmlPullParser;
@@ -32,11 +32,11 @@
 import android.test.ActivityInstrumentationTestCase2;
 import android.util.Xml;
 import android.widget.ImageView;
-import android.widget.cts.ImageViewStubActivity;
+import android.graphics.cts.ImageViewCtsActivity;
 
 import java.io.IOException;
 
-public class AnimationDrawableTest extends ActivityInstrumentationTestCase2<ImageViewStubActivity> {
+public class AnimationDrawableTest extends ActivityInstrumentationTestCase2<ImageViewCtsActivity> {
     private static final int FRAMES_COUNT        = 3;
     private static final int FIRST_FRAME_INDEX   = 0;
     private static final int SECOND_FRAME_INDEX  = 1;
@@ -50,7 +50,7 @@
     private Resources mResources;
 
     public AnimationDrawableTest() {
-        super("com.android.cts.stub", ImageViewStubActivity.class);
+        super("com.android.cts.graphics", ImageViewCtsActivity.class);
     }
 
     @Override
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..c895d0d 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/BitmapDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/BitmapDrawableTest.java
@@ -16,21 +16,23 @@
 
 package android.graphics.drawable.cts;
 
-import com.android.cts.stub.R;
-
+import com.android.cts.graphics.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,18 @@
         assertNull(bitmapDrawable.getPaint().getColorFilter());
     }
 
+    public void testSetTint() {
+        final InputStream source = mContext.getResources().openRawResource(R.raw.testimage);
+        final BitmapDrawable d = new BitmapDrawable(source);
+
+        d.setTint(Color.BLACK);
+        d.setTintMode(Mode.SRC_OVER);
+        assertEquals("Nine-patch is tinted", Color.BLACK, DrawableTestingUtils.getPixel(d, 0, 0));
+
+        d.setTintList(null);
+        d.setTintMode(null);
+    }
+
     public void testGetOpacity() {
         BitmapDrawable bitmapDrawable = new BitmapDrawable();
         assertEquals(Gravity.FILL, bitmapDrawable.getGravity());
@@ -343,6 +357,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 +366,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/ClipDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/ClipDrawableTest.java
index 5af5607..7e3294d 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/ClipDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/ClipDrawableTest.java
@@ -16,7 +16,7 @@
 
 package android.graphics.drawable.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.graphics.R;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
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..465a476 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.graphics.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
 import java.io.IOException;
 
 public class ColorDrawableTest extends AndroidTestCase {
@@ -120,9 +119,20 @@
     }
 
     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(Color.BLACK);
+        d.setTintMode(Mode.SRC_OVER);
+        assertEquals(Color.BLACK, DrawableTestingUtils.getPixel(d, 0, 0));
     }
 }
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerStateTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerStateTest.java
index 2adc587..701071b 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerStateTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerStateTest.java
@@ -130,9 +130,9 @@
         assertNull(mDrawableContainerState.getConstantPadding());
 
         /*
-         * TODO: the behavior of getConstantPadding when variable padding is 
+         * TODO: the behavior of getConstantPadding when variable padding is
          * false is undefined
-         * 
+         *
         mDrawableContainerState.setVariablePadding(false);
         Rect padding = mDrawableContainerState.getConstantPadding();
         assertNotNull(padding);
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 0672db6..036c756 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;
@@ -186,10 +189,10 @@
         assertConstantStateNotSet();
         assertNull(mDrawableContainer.getCurrent());
 
+        mDrawableContainer.setConstantState(mDrawableContainerState);
         mDrawableContainer.setColorFilter(null);
         mDrawableContainer.setColorFilter(new ColorFilter());
 
-        mDrawableContainer.setConstantState(mDrawableContainerState);
         MockDrawable dr = new MockDrawable();
         addAndSelectDrawable(dr);
 
@@ -204,6 +207,25 @@
         assertTrue(dr.hasSetColorFilterCalled());
     }
 
+    public void testSetTint() {
+        assertConstantStateNotSet();
+        assertNull(mDrawableContainer.getCurrent());
+
+        mDrawableContainer.setConstantState(mDrawableContainerState);
+        mDrawableContainer.setTint(Color.BLACK);
+        mDrawableContainer.setTintMode(Mode.SRC_OVER);
+
+        MockDrawable dr = new MockDrawable();
+        addAndSelectDrawable(dr);
+
+        assertEquals("Initial tint propagates", Mode.SRC_OVER, dr.getTintMode());
+
+        dr.reset();
+        mDrawableContainer.setTintList(null);
+        mDrawableContainer.setTintMode(null);
+        assertTrue("setImageTintList() propagates", dr.hasSetTintCalled());
+    }
+
     public void testOnBoundsChange() {
         assertConstantStateNotSet();
         assertNull(mDrawableContainer.getCurrent());
@@ -753,35 +775,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 +805,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 +852,18 @@
             return mIntrinsicWidth;
         }
 
+        @Override
         public Drawable mutate() {
             mHasCalledMutate = true;
             return this;
         }
 
+        @Override
+        public void setTintMode(Mode tintMode) {
+            mTintMode = tintMode;
+            mHasCalledSetTint = true;
+        }
+
         public void setMinimumHeight(int h) {
             mMinimumHeight = h;
         }
@@ -873,6 +900,10 @@
             return mHasCalledSetDither;
         }
 
+        public boolean hasSetTintCalled() {
+            return mHasCalledSetTint;
+        }
+
         public boolean hasOnBoundsChangedCalled() {
             return mHasCalledOnBoundsChanged;
         }
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTest.java
index df29211..a48372e 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTest.java
@@ -16,7 +16,7 @@
 
 package android.graphics.drawable.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.graphics.R;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTestUtils.java b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTestUtils.java
new file mode 100644
index 0000000..a0fa634
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTestUtils.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2008 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.content.res.XmlResourceParser;
+import android.util.AttributeSet;
+import android.util.Xml;
+
+import java.io.IOException;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+/**
+ * The useful methods for graphics.drawable test.
+ */
+public class DrawableTestUtils {
+
+    public static void skipCurrentTag(XmlPullParser parser)
+            throws XmlPullParserException, IOException {
+        int outerDepth = parser.getDepth();
+        int type;
+        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+               && (type != XmlPullParser.END_TAG
+                       || parser.getDepth() > outerDepth)) {
+        }
+    }
+
+    /**
+     * Retrieve an AttributeSet from a XML.
+     *
+     * @param parser the XmlPullParser to use for the xml parsing.
+     * @param searchedNodeName the name of the target node.
+     * @return the AttributeSet retrieved from specified node.
+     * @throws IOException
+     * @throws XmlPullParserException
+     */
+    public static AttributeSet getAttributeSet(XmlResourceParser parser, String searchedNodeName)
+            throws XmlPullParserException, IOException {
+        AttributeSet attrs = null;
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && type != XmlPullParser.START_TAG) {
+        }
+        String nodeName = parser.getName();
+        if (!"alias".equals(nodeName)) {
+            throw new RuntimeException();
+        }
+        int outerDepth = parser.getDepth();
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+            nodeName = parser.getName();
+            if (searchedNodeName.equals(nodeName)) {
+                outerDepth = parser.getDepth();
+                while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                        && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+                    if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                        continue;
+                    }
+                    nodeName = parser.getName();
+                    attrs = Xml.asAttributeSet(parser);
+                    break;
+                }
+                break;
+            } else {
+                skipCurrentTag(parser);
+            }
+        }
+        return attrs;
+    }
+}
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/GradientDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/GradientDrawableTest.java
index f2d7b82..e7a38c5 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/GradientDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/GradientDrawableTest.java
@@ -16,13 +16,13 @@
 
 package android.graphics.drawable.cts;
 
-import com.android.cts.stub.R;
-
+import com.android.cts.graphics.R;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
 import android.content.res.Resources;
+import android.content.res.Resources.Theme;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
 import android.graphics.PixelFormat;
@@ -248,6 +248,26 @@
         }
     }
 
+    public void testInflateGradientRadius() throws XmlPullParserException, IOException {
+        Rect parentBounds = new Rect(0, 0, 100, 100);
+        Resources resources = mContext.getResources();
+
+        GradientDrawable gradientDrawable;
+        float radius;
+
+        gradientDrawable = (GradientDrawable) resources.getDrawable(
+                R.drawable.gradientdrawable_radius_base);
+        gradientDrawable.setBounds(parentBounds);
+        radius = gradientDrawable.getGradientRadius();
+        assertEquals(25.0f, radius, 0.0f);
+
+        gradientDrawable = (GradientDrawable) resources.getDrawable(
+                R.drawable.gradientdrawable_radius_parent);
+        gradientDrawable.setBounds(parentBounds);
+        radius = gradientDrawable.getGradientRadius();
+        assertEquals(50.0f, radius, 0.0f);
+    }
+
     public void testGetIntrinsicWidth() {
         GradientDrawable gradientDrawable = new GradientDrawable();
         gradientDrawable.setSize(6, 4);
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/InsetDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/InsetDrawableTest.java
index 767d89d..1edd36e 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/InsetDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/InsetDrawableTest.java
@@ -16,7 +16,7 @@
 
 package android.graphics.drawable.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.graphics.R;
 
 
 import org.xmlpull.v1.XmlPullParser;
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..5aa3083 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java
@@ -16,7 +16,7 @@
 
 package android.graphics.drawable.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.graphics.R;
 
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -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/LevelListDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/LevelListDrawableTest.java
index 191e0d3..11186b0 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/LevelListDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/LevelListDrawableTest.java
@@ -31,7 +31,7 @@
 import android.test.InstrumentationTestCase;
 import android.util.Xml;
 
-import com.android.cts.stub.R;
+import com.android.cts.graphics.R;
 
 
 public class LevelListDrawableTest extends InstrumentationTestCase {
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 b23c7fa..39ed55c 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/NinePatchDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/NinePatchDrawableTest.java
@@ -16,13 +16,12 @@
 
 package android.graphics.drawable.cts;
 
-import com.android.cts.stub.R;
-
-import dalvik.annotation.KnownFailure;
+import com.android.cts.graphics.R;
 
 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;
@@ -36,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;
@@ -180,6 +182,16 @@
         assertNull(mNinePatchDrawable.getPaint().getColorFilter());
     }
 
+    public void testSetTint() {
+        mNinePatchDrawable.setTint(Color.BLACK);
+        mNinePatchDrawable.setTintMode(Mode.SRC_OVER);
+        assertEquals("Nine-patch is tinted", Color.BLACK,
+                DrawableTestingUtils.getPixel(mNinePatchDrawable, 0, 0));
+
+        mNinePatchDrawable.setTintList(null);
+        mNinePatchDrawable.setTintMode(null);
+    }
+
     public void testSetDither() {
         mNinePatchDrawable.setDither(false);
         assertFalse(mNinePatchDrawable.getPaint().isDither());
@@ -239,9 +251,9 @@
         assertEquals(9, mNinePatchDrawable.getMinimumHeight());
     }
 
-    @KnownFailure("Bug 2834281 - Bitmap#hasAlpha seems to return true for "
-        + "images without alpha.")
-    public void testGetOpacity() {
+    // Known failure: Bug 2834281 - Bitmap#hasAlpha seems to return true for
+    // images without alpha
+    public void suppress_testGetOpacity() {
         assertEquals(PixelFormat.OPAQUE, mNinePatchDrawable.getOpacity());
 
         mNinePatchDrawable = getNinePatchDrawable(R.drawable.ninepatch_1);
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/PaintDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/PaintDrawableTest.java
index 71fa06c..a440dab 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/PaintDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/PaintDrawableTest.java
@@ -16,7 +16,7 @@
 
 package android.graphics.drawable.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.graphics.R;
 
 
 import org.xmlpull.v1.XmlPullParser;
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/RotateDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/RotateDrawableTest.java
index a3398f6..cf25857 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/RotateDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/RotateDrawableTest.java
@@ -16,7 +16,7 @@
 
 package android.graphics.drawable.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.graphics.R;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/ScaleDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/ScaleDrawableTest.java
index e0cd2ee..190fffa 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/ScaleDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/ScaleDrawableTest.java
@@ -16,7 +16,7 @@
 
 package android.graphics.drawable.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.graphics.R;
 
 import org.xmlpull.v1.XmlPullParserException;
 
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..b77139a 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.graphics.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
 import java.io.IOException;
 
 public class ShapeDrawableTest extends AndroidTestCase {
@@ -314,6 +316,13 @@
         assertNull(shapeDrawable.getPaint().getColorFilter());
     }
 
+    public void testSetTint() {
+        final ShapeDrawable d = new ShapeDrawable(new RectShape());
+        d.setTint(Color.BLACK);
+        d.setTintMode(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/StateListDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/StateListDrawableTest.java
index 891ce5e..d55b91d 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/StateListDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/StateListDrawableTest.java
@@ -34,7 +34,7 @@
 import android.util.StateSet;
 import android.util.Xml;
 
-import com.android.cts.stub.R;
+import com.android.cts.graphics.R;
 
 
 public class StateListDrawableTest extends InstrumentationTestCase {
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/ThemedDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/ThemedDrawableTest.java
new file mode 100644
index 0000000..8cee91e
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/ThemedDrawableTest.java
@@ -0,0 +1,149 @@
+/*
+ * 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.annotation.TargetApi;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.graphics.Shader.TileMode;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.GradientDrawable;
+import android.graphics.drawable.LayerDrawable;
+import android.graphics.drawable.NinePatchDrawable;
+import android.graphics.drawable.RippleDrawable;
+import android.test.AndroidTestCase;
+import android.util.SparseIntArray;
+import android.view.ContextThemeWrapper;
+import android.view.Gravity;
+
+import com.android.cts.graphics.R;
+
+@TargetApi(19)
+public class ThemedDrawableTest extends AndroidTestCase {
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mContext.setTheme(R.style.Theme_ThemedDrawableTest);
+    }
+
+    public void testBitmapDrawable() {
+        BitmapDrawable d = (BitmapDrawable) mContext.getDrawable(R.drawable.bitmapdrawable_theme);
+
+        internalTestBitmapDrawable(d);
+    }
+
+    private void internalTestBitmapDrawable(BitmapDrawable d) {
+        assertEquals(true, d.hasAntiAlias());
+        assertEquals(true, d.isAutoMirrored());
+        // assertEquals(true, d.hasDither());
+        // assertEquals(true, d.hasFilter());
+        assertEquals(Gravity.TOP, d.getGravity());
+        assertEquals(true, d.hasMipMap());
+        assertNotNull(d.getBitmap());
+        assertEquals(TileMode.MIRROR, d.getTileModeX());
+        assertEquals(TileMode.MIRROR, d.getTileModeY());
+    }
+
+    public void testColorDrawable() {
+        ColorDrawable d = (ColorDrawable) mContext.getDrawable(R.drawable.colordrawable_theme);
+
+        assertEquals(Color.BLACK, d.getColor());
+    }
+
+    public void testGradientDrawable() {
+        GradientDrawable d = (GradientDrawable) mContext.getDrawable(
+                R.drawable.gradientdrawable_theme);
+
+        // Corners
+        // assertEquals(1, d.getCornerRadius(0));
+        // assertEquals(1, d.getCornerRadius(1));
+        // assertEquals(1, d.getCornerRadius(2));
+        // assertEquals(1, d.getCornerRadius(3));
+
+        // Gradient
+        // int[] colors = d.getColors(null);
+        // for (int i = 0; i < color.length; i++) {
+        // assertEquals(Color.BLACK, colors[i]);
+        // }
+        // assertEquals(1.0f, d.getGradientAngle());
+        // assertEquals(1.0, d.getGradientCenterX());
+        // assertEquals(1.0, d.getGradientCenterY());
+        // assertEquals(1.0, d.getGradientRadius());
+        // assertEquals(false, d.getUseLevel());
+
+        // Padding
+        Rect padding = new Rect();
+        assertTrue(d.getPadding(padding));
+        assertEquals(1, padding.left);
+        assertEquals(1, padding.top);
+        assertEquals(1, padding.bottom);
+        assertEquals(1, padding.right);
+
+        // Size
+        assertEquals(1, d.getIntrinsicHeight());
+        assertEquals(1, d.getIntrinsicWidth());
+
+        // Solid
+        // assertEquals(true, d.hasSolidColor());
+        // assertEquals(Color.BLACK, d.getColor());
+
+        // Stroke
+        // assertEquals(1.0, d.getStrokeWidth());
+        // assertEquals(Color.BLACK, d.getStrokeColor());
+        // assertEquals(1.0, d.getStrokeDashWidth());
+        // assertEquals(1.0, d.getStrokeDashGap());
+    }
+
+    public void testNinePatchDrawable() {
+        NinePatchDrawable d = (NinePatchDrawable) mContext.getDrawable(
+                R.drawable.ninepatchdrawable_theme);
+
+        internalTestNinePatchDrawable(d);
+    }
+
+    private void internalTestNinePatchDrawable(NinePatchDrawable d) {
+        assertEquals(true, d.isAutoMirrored());
+        // assertEquals(true, d.hasDither());
+        // assertNotNull(d.getNinePatch());
+    }
+
+    public void testRippleDrawable() {
+        RippleDrawable d = (RippleDrawable) mContext.getDrawable(
+                R.drawable.rippledrawable_theme);
+
+        // assertEquals(Color.BLACK, d.getColor());
+    }
+
+    public void testLayerDrawable() {
+        LayerDrawable d = (LayerDrawable) mContext.getDrawable(R.drawable.layerdrawable_theme);
+
+        // Layer autoMirror values are set to the parent's autoMirror value, so
+        // make sure the container is using the expected value.
+        assertEquals(true, d.isAutoMirrored());
+
+        BitmapDrawable bitmapDrawable  = (BitmapDrawable) d.getDrawable(0);
+        internalTestBitmapDrawable(bitmapDrawable);
+
+        NinePatchDrawable ninePatchDrawable = (NinePatchDrawable) d.getDrawable(1);
+        internalTestNinePatchDrawable(ninePatchDrawable);
+    }
+}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/TransitionDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/TransitionDrawableTest.java
index ab47974..f2a22a2 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/TransitionDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/TransitionDrawableTest.java
@@ -16,7 +16,7 @@
 
 package android.graphics.drawable.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.graphics.R;
 
 import android.content.res.Resources;
 import android.graphics.Bitmap;
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java
new file mode 100644
index 0000000..3578d3c
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java
@@ -0,0 +1,286 @@
+/*
+ * 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.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.drawable.VectorDrawable;
+import android.graphics.drawable.Drawable.ConstantState;
+import android.test.AndroidTestCase;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Xml;
+
+import com.android.cts.graphics.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+public class VectorDrawableTest extends AndroidTestCase {
+    private static final String LOGTAG = VectorDrawableTest.class.getSimpleName();
+    private int[] mIconResIds = new int[] {
+            R.drawable.vector_icon_create,
+            R.drawable.vector_icon_delete,
+            R.drawable.vector_icon_heart,
+            R.drawable.vector_icon_schedule,
+            R.drawable.vector_icon_settings,
+            R.drawable.vector_icon_random_path_1,
+            R.drawable.vector_icon_random_path_2,
+            R.drawable.vector_icon_repeated_cq,
+            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,
+            R.drawable.vector_icon_render_order_1,
+            R.drawable.vector_icon_render_order_2,
+            R.drawable.vector_icon_stroke_1,
+            R.drawable.vector_icon_stroke_2,
+            R.drawable.vector_icon_stroke_3,
+    };
+
+    private int[] mGoldenImages = new int[] {
+            R.drawable.vector_icon_create_golden,
+            R.drawable.vector_icon_delete_golden,
+            R.drawable.vector_icon_heart_golden,
+            R.drawable.vector_icon_schedule_golden,
+            R.drawable.vector_icon_settings_golden,
+            R.drawable.vector_icon_random_path_1_golden,
+            R.drawable.vector_icon_random_path_2_golden,
+            R.drawable.vector_icon_repeated_cq_golden,
+            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,
+            R.drawable.vector_icon_render_order_1_golden,
+            R.drawable.vector_icon_render_order_2_golden,
+            R.drawable.vector_icon_stroke_1_golden,
+            R.drawable.vector_icon_stroke_2_golden,
+            R.drawable.vector_icon_stroke_3_golden,
+    };
+
+    private static final int IMAGE_WIDTH = 64;
+    private static final int IMAGE_HEIGHT = 64;
+    // A small value is actually making sure that the values are matching
+    // exactly with the golden image.
+    // We can increase the threshold if the Skia is drawing with some variance
+    // on different devices. So far, the tests show they are matching correctly.
+    private static final float PIXEL_ERROR_THRESHOLD = 0.00001f;
+
+    private static final boolean DBG_DUMP_PNG = false;
+
+    private Resources mResources;
+    private VectorDrawable mVectorDrawable;
+    private Bitmap mBitmap;
+    private Canvas mCanvas;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        final int width = IMAGE_WIDTH;
+        final int height = IMAGE_HEIGHT;
+
+        mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        mCanvas = new Canvas(mBitmap);
+        mVectorDrawable = new VectorDrawable();
+        mVectorDrawable.setBounds(0, 0, width, height);
+
+        mResources = mContext.getResources();
+    }
+
+    public void testSimpleVectorDrawables() throws Exception {
+        verifyVectorDrawables(mIconResIds, mGoldenImages, 0);
+    }
+
+    private void verifyVectorDrawables(int[] resIds, int[] goldenImages, float fraction) throws Exception {
+        for (int i = 0; i < resIds.length; i++) {
+            // Setup VectorDrawable from xml file and draw into the bitmap.
+            XmlPullParser parser = mResources.getXml(resIds[i]);
+            AttributeSet attrs = Xml.asAttributeSet(parser);
+
+            int type;
+            while ((type=parser.next()) != XmlPullParser.START_TAG &&
+                    type != XmlPullParser.END_DOCUMENT) {
+                // Empty loop
+            }
+
+            if (type != XmlPullParser.START_TAG) {
+                throw new XmlPullParserException("No start tag found");
+            }
+
+            mVectorDrawable.inflate(mResources, parser, attrs);
+
+            mBitmap.eraseColor(0);
+            mVectorDrawable.draw(mCanvas);
+
+            if (DBG_DUMP_PNG) {
+                saveVectorDrawableIntoPNG(mBitmap, resIds, i);
+            } else {
+                // Start to compare
+                Bitmap golden = BitmapFactory.decodeResource(mResources, goldenImages[i]);
+                compareImages(mBitmap, golden, mResources.getString(resIds[i]));
+            }
+        }
+    }
+
+    // This is only for debugging or golden image (re)generation purpose.
+    private void saveVectorDrawableIntoPNG(Bitmap bitmap, int[] resIds, int index) throws IOException {
+        // 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 = outputFolder + fileTitle + "_golden.png";
+            File outputFile = new File(outputFilename);
+            if (!outputFile.exists()) {
+                outputFile.createNewFile();
+            }
+
+            out = new FileOutputStream(outputFile, false);
+            bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
+            Log.v(LOGTAG, "Write test No." + index + " to file successfully.");
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            if (out != null) {
+                out.close();
+            }
+        }
+    }
+
+    private void compareImages(Bitmap ideal, Bitmap given, String filename) {
+        int idealWidth = ideal.getWidth();
+        int idealHeight = ideal.getHeight();
+
+        assertTrue(idealWidth == given.getWidth());
+        assertTrue(idealHeight == given.getHeight());
+
+        int totalDiffPixelCount = 0;
+        float totalPixelCount = idealWidth * idealHeight;
+        for (int x = 0; x < idealWidth; x++) {
+            for (int y = 0; y < idealHeight; y++) {
+                int idealColor = ideal.getPixel(x, y);
+                int givenColor = given.getPixel(x, y);
+                if (idealColor == givenColor)
+                    continue;
+
+                float totalError = 0;
+                totalError += Math.abs(Color.red(idealColor) - Color.red(givenColor));
+                totalError += Math.abs(Color.green(idealColor) - Color.green(givenColor));
+                totalError += Math.abs(Color.blue(idealColor) - Color.blue(givenColor));
+                totalError += Math.abs(Color.alpha(idealColor) - Color.alpha(givenColor));
+
+                if ((totalError / 1024.0f) >= PIXEL_ERROR_THRESHOLD) {
+                    fail((filename + ": totalError is " + totalError));
+                }
+
+                totalDiffPixelCount++;
+            }
+        }
+        if ((totalDiffPixelCount / totalPixelCount) >= PIXEL_ERROR_THRESHOLD) {
+            fail((filename +": totalDiffPixelCount is " + totalDiffPixelCount));
+        }
+
+    }
+
+    public void testGetChangingConfigurations() {
+        VectorDrawable vectorDrawable = new VectorDrawable();
+        ConstantState constantState = vectorDrawable.getConstantState();
+
+        // default
+        assertEquals(0, constantState.getChangingConfigurations());
+        assertEquals(0, vectorDrawable.getChangingConfigurations());
+
+        // change the drawable's configuration does not affect the state's configuration
+        vectorDrawable.setChangingConfigurations(0xff);
+        assertEquals(0xff, vectorDrawable.getChangingConfigurations());
+        assertEquals(0, constantState.getChangingConfigurations());
+
+        // the state's configuration get refreshed
+        constantState = vectorDrawable.getConstantState();
+        assertEquals(0xff,  constantState.getChangingConfigurations());
+
+        // set a new configuration to drawable
+        vectorDrawable.setChangingConfigurations(0xff00);
+        assertEquals(0xff,  constantState.getChangingConfigurations());
+        assertEquals(0xffff,  vectorDrawable.getChangingConfigurations());
+    }
+
+    public void testGetConstantState() {
+        VectorDrawable vectorDrawable = new VectorDrawable();
+        ConstantState constantState = vectorDrawable.getConstantState();
+        assertNotNull(constantState);
+        assertEquals(0, constantState.getChangingConfigurations());
+
+        vectorDrawable.setChangingConfigurations(1);
+        constantState = vectorDrawable.getConstantState();
+        assertNotNull(constantState);
+        assertEquals(1, constantState.getChangingConfigurations());
+    }
+
+    public void testMutate() {
+        Resources resources = mContext.getResources();
+        // d1 will be mutated, while d2 / d3 will not.
+        VectorDrawable d1 = (VectorDrawable) resources.getDrawable(R.drawable.vector_icon_create);
+        VectorDrawable d2 = (VectorDrawable) resources.getDrawable(R.drawable.vector_icon_create);
+        VectorDrawable d3 = (VectorDrawable) resources.getDrawable(R.drawable.vector_icon_create);
+        int originalAlpha = d2.getAlpha();
+
+        d1.setAlpha(0x80);
+        assertEquals(0x80, d1.getAlpha());
+        assertEquals(0x80, d2.getAlpha());
+        assertEquals(0x80, d3.getAlpha());
+
+        d1.mutate();
+        d1.setAlpha(0x40);
+        assertEquals(0x40, d1.getAlpha());
+        assertEquals(0x80, d2.getAlpha());
+        assertEquals(0x80, d3.getAlpha());
+
+        d2.setAlpha(0x20);
+        assertEquals(0x40, d1.getAlpha());
+        assertEquals(0x20, d2.getAlpha());
+        assertEquals(0x20, d3.getAlpha());
+
+        d2.setAlpha(originalAlpha);
+    }
+}
diff --git a/tests/tests/graphics/src/android/opengl/cts/CompressedTextureCtsActivity.java b/tests/tests/graphics/src/android/opengl/cts/CompressedTextureCtsActivity.java
new file mode 100644
index 0000000..533508a
--- /dev/null
+++ b/tests/tests/graphics/src/android/opengl/cts/CompressedTextureCtsActivity.java
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+package android.opengl.cts;
+
+import com.android.cts.graphics.R;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.BitmapFactory;
+import android.os.Bundle;
+import android.util.Log;
+
+public class CompressedTextureCtsActivity extends Activity {
+
+    private static final String TAG = "CompressedTextureCtsActivity";
+
+    protected Resources mResources;
+
+    private CompressedTextureSurfaceView mCompressedTextureView = null;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        Bundle extras = getIntent().getExtras();
+        String formatTest = extras.getString("TextureFormat", null);
+
+        Log.i(TAG, "Testing format " + formatTest);
+
+        mResources = getResources();
+
+        CompressedTextureLoader.Texture compressed = null;
+
+        BitmapFactory.Options optionsRGB = new BitmapFactory.Options();
+        optionsRGB.inPreferredConfig = Bitmap.Config.RGB_565;
+        optionsRGB.inScaled = false;
+        Bitmap bitmap = BitmapFactory.decodeResource(mResources, R.raw.basetex, optionsRGB);
+
+        if (formatTest.equals(CompressedTextureLoader.TEXTURE_ETC1)) {
+            compressed = CompressedTextureLoader.createFromUncompressedETC1(bitmap);
+        } else if (formatTest.equals(CompressedTextureLoader.TEXTURE_S3TC)) {
+            compressed = CompressedTextureLoader.loadTextureDXT(mResources, R.raw.ddstex);
+        } else if (formatTest.equals(CompressedTextureLoader.TEXTURE_ATC)) {
+            compressed = CompressedTextureLoader.loadTextureATC(mResources, 0); //cts for now
+        } else if (formatTest.equals(CompressedTextureLoader.TEXTURE_PVRTC)) {
+            compressed = CompressedTextureLoader.loadTexturePVRTC(mResources, R.raw.pvrtex);
+        }
+
+        mCompressedTextureView = new CompressedTextureSurfaceView(this, bitmap, compressed);
+        setContentView(mCompressedTextureView);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        mCompressedTextureView.onResume();
+    }
+
+    public boolean getPassed() throws InterruptedException {
+        return mCompressedTextureView.getTestPassed();
+    }
+}
diff --git a/tests/tests/graphics/src/android/opengl/cts/CompressedTextureLoader.java b/tests/tests/graphics/src/android/opengl/cts/CompressedTextureLoader.java
new file mode 100644
index 0000000..1524f99
--- /dev/null
+++ b/tests/tests/graphics/src/android/opengl/cts/CompressedTextureLoader.java
@@ -0,0 +1,485 @@
+/*
+ * 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.
+ */
+package android.opengl.cts;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.Buffer;
+import java.nio.ByteOrder;
+import java.util.HashMap;
+
+import com.android.cts.graphics.R;
+
+import android.app.Activity;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.util.Log;
+
+import android.opengl.ETC1;
+import android.opengl.ETC1Util;
+import android.opengl.GLES20;
+
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.BitmapFactory;
+
+public class CompressedTextureLoader {
+    private static final String TAG = "CompressedTextureLoader";
+
+    public static final String TEXTURE_UNCOMPRESSED = "UNCOMPRESSED";
+    public static final String TEXTURE_ETC1 = "ETC1";
+    public static final String TEXTURE_S3TC = "S3TC";
+    public static final String TEXTURE_ATC = "ATC";
+    public static final String TEXTURE_PVRTC = "PVRTC";
+
+    public static class Texture {
+        public Texture(int width, int height, int internalformat, ByteBuffer data,
+                       String formatName) {
+            mWidth = width;
+            mHeight = height;
+            mInternalFormat = internalformat;
+            mData = data;
+            mFormatName = formatName;
+        }
+
+        /**
+         * Get the width of the texture in pixels.
+         * @return the width of the texture in pixels.
+         */
+        public int getWidth() { return mWidth; }
+
+        /**
+         * Get the height of the texture in pixels.
+         * @return the width of the texture in pixels.
+         */
+        public int getHeight() { return mHeight; }
+
+        /**
+         * Get the compressed data of the texture.
+         * @return the texture data.
+         */
+        public ByteBuffer getData() { return mData; }
+
+        /**
+         * Get the format of the texture.
+         * @return the internal format.
+         */
+        public int getFormat() { return mInternalFormat; }
+
+        /**
+         * Get the format of the texture.
+         * @return the internal format.
+         */
+        public boolean isSupported() { return isFormatSupported(mFormatName); }
+
+        private int mWidth;
+        private int mHeight;
+        private int mInternalFormat;
+        private ByteBuffer mData;
+        private String mFormatName;
+    }
+
+    /*  .pvr header is described by the following c struct
+        typedef struct PVR_TEXTURE_HEADER_TAG{
+            unsigned int  dwHeaderSize;   // size of the structure
+            unsigned int  dwHeight;    // height of surface to be created
+            unsigned int  dwWidth;    // width of input surface
+            unsigned int  dwMipMapCount;   // number of MIP-map levels requested
+            unsigned int  dwpfFlags;   // pixel format flags
+            unsigned int  dwDataSize;   // Size of the compress data
+            unsigned int  dwBitCount;   // number of bits per pixel
+            unsigned int  dwRBitMask;   // mask for red bit
+            unsigned int  dwGBitMask;   // mask for green bits
+            unsigned int  dwBBitMask;   // mask for blue bits
+            unsigned int  dwAlphaBitMask;   // mask for alpha channel
+            unsigned int  dwPVR;    // should be 'P' 'V' 'R' '!'
+            unsigned int  dwNumSurfs;   //number of slices for volume textures or skyboxes
+        } PVR_TEXTURE_HEADER;
+    */
+    static final int PVR_HEADER_SIZE = 13 * 4;
+    static final int PVR_2BPP = 24;
+    static final int PVR_4BPP = 25;
+    static final int PVR_MAGIC_NUMBER = 559044176;
+
+    static final int GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00;
+    static final int GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG = 0x8C01;
+    static final int GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02;
+    static final int GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03;
+
+    static class PVRHeader {
+        int mHeaderSize;   // size of the structure
+        int mHeight;    // height of surface to be created
+        int mWidth;    // width of input surface
+        int mMipMapCount;   // number of MIP-map levels requested
+        int mpfFlags;   // pixel format flags
+        int mDataSize;   // Size of the compress data
+        int mBitCount;   // number of bits per pixel
+        int mRBitMask;   // mask for red bit
+        int mGBitMask;   // mask for green bits
+        int mBBitMask;   // mask for blue bits
+        int mAlphaBitMask;   // mask for alpha channel
+        int mPVR;    // should be 'P' 'V' 'R' '!'
+        int mNumSurfs;   //number of slices for volume textures or skyboxes
+    }
+
+    protected static PVRHeader readPVRHeader(InputStream is) {
+
+        byte[] headerData = new byte[PVR_HEADER_SIZE];
+        try {
+            is.read(headerData);
+        } catch (Exception e) {
+            throw new RuntimeException("Unable to read data");
+        }
+
+        ByteBuffer headerBuffer = ByteBuffer.allocateDirect(PVR_HEADER_SIZE)
+                .order(ByteOrder.nativeOrder());
+        headerBuffer.put(headerData, 0, PVR_HEADER_SIZE).position(0);
+
+        PVRHeader header = new PVRHeader();
+
+        header.mHeaderSize = headerBuffer.getInt();
+        header.mHeight = headerBuffer.getInt();
+        header.mWidth = headerBuffer.getInt();
+        header.mMipMapCount = headerBuffer.getInt();
+        header.mpfFlags = headerBuffer.getInt();
+        header.mDataSize = headerBuffer.getInt();
+        header.mBitCount = headerBuffer.getInt();
+        header.mRBitMask = headerBuffer.getInt();
+        header.mGBitMask = headerBuffer.getInt();
+        header.mBBitMask = headerBuffer.getInt();
+        header.mAlphaBitMask = headerBuffer.getInt();
+        header.mPVR = headerBuffer.getInt();
+        header.mNumSurfs = headerBuffer.getInt();
+
+        if (header.mHeaderSize != PVR_HEADER_SIZE ||
+            header.mPVR != PVR_MAGIC_NUMBER) {
+            throw new RuntimeException("Invalid header data");
+        }
+
+        return header;
+    }
+
+    public static Texture loadTextureATC(Resources res, int id) {
+        Texture tex = new Texture(0, 0, 0, null, "Cts!");
+        return tex;
+    }
+
+    private static ETC1Util.ETC1Texture compressTexture(Buffer input,
+                                                        int width, int height,
+                                                        int pixelSize, int stride){
+        int encodedImageSize = ETC1.getEncodedDataSize(width, height);
+        ByteBuffer compressedImage = ByteBuffer.allocateDirect(encodedImageSize).
+            order(ByteOrder.nativeOrder());
+        ETC1.encodeImage(input, width, height, pixelSize, stride, compressedImage);
+        return new ETC1Util.ETC1Texture(width, height, compressedImage);
+    }
+
+    public static Texture createFromUncompressedETC1(Bitmap bitmap) {
+        int dataSize = bitmap.getRowBytes() * bitmap.getHeight();
+
+        ByteBuffer dataBuffer;
+        dataBuffer = ByteBuffer.allocateDirect(dataSize).order(ByteOrder.nativeOrder());
+        bitmap.copyPixelsToBuffer(dataBuffer);
+        dataBuffer.position(0);
+
+        int bytesPerPixel = bitmap.getRowBytes() / bitmap.getWidth();
+        ETC1Util.ETC1Texture compressed = compressTexture(dataBuffer,
+                                                          bitmap.getWidth(),
+                                                          bitmap.getHeight(),
+                                                          bytesPerPixel,
+                                                          bitmap.getRowBytes());
+
+        Texture tex = new Texture(compressed.getWidth(), compressed.getHeight(),
+                                  ETC1.ETC1_RGB8_OES, compressed.getData(), TEXTURE_ETC1);
+
+        return tex;
+    }
+
+    private static ByteBuffer read(InputStream is, int dataSize) {
+        ByteBuffer dataBuffer;
+        dataBuffer = ByteBuffer.allocateDirect(dataSize).order(ByteOrder.nativeOrder());
+        byte[] ioBuffer = new byte[4096];
+        for (int i = 0; i < dataSize; ) {
+            int chunkSize = Math.min(ioBuffer.length, dataSize - i);
+            try {
+                is.read(ioBuffer, 0, chunkSize);
+            } catch (Exception e) {
+                throw new RuntimeException("Unable to read data");
+            }
+            dataBuffer.put(ioBuffer, 0, chunkSize);
+            i += chunkSize;
+        }
+        dataBuffer.position(0);
+        return dataBuffer;
+    }
+
+    public static Texture loadTexturePVRTC(Resources res, int id) {
+        InputStream is = null;
+        try {
+            is = res.openRawResource(id);
+        } catch (Exception e) {
+            throw new RuntimeException("Unable to open resource " + id);
+        }
+
+        PVRHeader header = readPVRHeader(is);
+
+        int format = header.mpfFlags & 0xFF;
+        int internalFormat = 0;
+        if (format == PVR_2BPP && header.mAlphaBitMask == 1) {
+            internalFormat = GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
+        } else if (format == PVR_2BPP && header.mAlphaBitMask == 0) {
+            internalFormat = GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
+        } else if (format == PVR_4BPP && header.mAlphaBitMask == 1) {
+            internalFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
+        } else if (format == PVR_4BPP && header.mAlphaBitMask == 0) {
+            internalFormat = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
+        }
+
+        // only load the first mip level for now
+        int dataSize = (header.mWidth * header.mHeight * header.mBitCount) >> 3;
+        ByteBuffer dataBuffer = read(is, dataSize);
+        Texture tex = new Texture(header.mWidth, header.mHeight,
+                                  internalFormat, dataBuffer,
+                                  TEXTURE_PVRTC);
+        try {
+            is.close();
+        } catch (Exception e) {
+            throw new RuntimeException("Unable to close resource stream " + id);
+        }
+        return tex;
+    }
+
+    /* DDS Header is described by the following structs
+       typedef struct {
+          DWORD           dwSize;
+          DWORD           dwFlags;
+          DWORD           dwHeight;
+          DWORD           dwWidth;
+          DWORD           dwPitchOrLinearSize;
+          DWORD           dwDepth;
+          DWORD           dwMipMapCount;
+          DWORD           dwReserved1[11];
+          DDS_PIXELFORMAT ddspf;
+          DWORD           dwCaps;
+          DWORD           dwCaps2;
+          DWORD           dwCaps3;
+          DWORD           dwCaps4;
+          DWORD           dwReserved2;
+        } DDS_HEADER;
+
+        struct DDS_PIXELFORMAT {
+          DWORD dwSize;
+          DWORD dwFlags;
+          DWORD dwFourCC;
+          DWORD dwRGBBitCount;
+          DWORD dwRBitMask;
+          DWORD dwGBitMask;
+          DWORD dwBBitMask;
+          DWORD dwABitMask;
+        };
+
+        In the file it looks like this
+        DWORD               dwMagic;
+        DDS_HEADER          header;
+        DDS_HEADER_DXT10    header10; // If the DDS_PIXELFORMAT dwFlags is set to DDPF_FOURCC
+                                      // and dwFourCC is DX10
+
+    */
+
+    static final int DDS_HEADER_STRUCT_SIZE = 124;
+    static final int DDS_PIXELFORMAT_STRUCT_SIZE = 32;
+    static final int DDS_HEADER_SIZE = 128;
+    static final int DDS_MAGIC_NUMBER = 0x20534444;
+    static final int DDS_DDPF_FOURCC = 0x4;
+    static final int DDS_DXT1 = 0x31545844;
+    static final int DDS_DXT5 = 0x35545844;
+
+    static final int COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0;
+    static final int COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1;
+    static final int COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3;
+
+    static class DDSHeader {
+        int mMagic;
+        int mSize;
+        int mFlags;
+        int mHeight;
+        int mWidth;
+        int mPitchOrLinearSize;
+        int mDepth;
+        int mMipMapCount;
+        int[] mReserved1;
+        // struct DDS_PIXELFORMAT {
+            int mPixelFormatSize;
+            int mPixelFormatFlags;
+            int mPixelFormatFourCC;
+            int mPixelFormatRGBBitCount;
+            int mPixelFormatRBitMask;
+            int mPixelFormatGBitMask;
+            int mPixelFormatBBitMask;
+            int mPixelFormatABitMask;
+        // };
+        int mCaps;
+        int mCaps2;
+        int mCaps3;
+        int mCaps4;
+        int mReserved2;
+
+        DDSHeader() {
+            mReserved1 = new int[11];
+        }
+    }
+
+    protected static DDSHeader readDDSHeader(InputStream is) {
+
+        byte[] headerData = new byte[DDS_HEADER_SIZE];
+        try {
+            is.read(headerData);
+        } catch (Exception e) {
+            throw new RuntimeException("Unable to read data");
+        }
+
+        ByteBuffer headerBuffer = ByteBuffer.allocateDirect(DDS_HEADER_SIZE)
+                .order(ByteOrder.nativeOrder());
+        headerBuffer.put(headerData, 0, DDS_HEADER_SIZE).position(0);
+
+        DDSHeader header = new DDSHeader();
+
+        header.mMagic = headerBuffer.getInt();
+        header.mSize = headerBuffer.getInt();
+        header.mFlags = headerBuffer.getInt();
+        header.mHeight = headerBuffer.getInt();
+        header.mWidth = headerBuffer.getInt();
+        header.mPitchOrLinearSize = headerBuffer.getInt();
+        header.mDepth = headerBuffer.getInt();
+        header.mMipMapCount = headerBuffer.getInt();
+        for (int i = 0; i < header.mReserved1.length; i ++) {
+            header.mReserved1[i] = headerBuffer.getInt();
+        }
+        // struct DDS_PIXELFORMAT {
+            header.mPixelFormatSize = headerBuffer.getInt();
+            header.mPixelFormatFlags = headerBuffer.getInt();
+            header.mPixelFormatFourCC = headerBuffer.getInt();
+            header.mPixelFormatRGBBitCount = headerBuffer.getInt();
+            header.mPixelFormatRBitMask = headerBuffer.getInt();
+            header.mPixelFormatGBitMask = headerBuffer.getInt();
+            header.mPixelFormatBBitMask = headerBuffer.getInt();
+            header.mPixelFormatABitMask = headerBuffer.getInt();
+        // };
+        header.mCaps = headerBuffer.getInt();
+        header.mCaps2 = headerBuffer.getInt();
+        header.mCaps3 = headerBuffer.getInt();
+        header.mCaps4 = headerBuffer.getInt();
+        header.mReserved2 = headerBuffer.getInt();
+
+        if (header.mSize != DDS_HEADER_STRUCT_SIZE ||
+            header.mPixelFormatSize != DDS_PIXELFORMAT_STRUCT_SIZE ||
+            header.mMagic != DDS_MAGIC_NUMBER) {
+            throw new RuntimeException("Invalid header data");
+        }
+
+        return header;
+    }
+
+    // Very simple loader that only reads in the header and a DXT1 mip level 0
+    public static Texture loadTextureDXT(Resources res, int id) {
+        InputStream is = null;
+        try {
+            is = res.openRawResource(id);
+        } catch (Exception e) {
+            throw new RuntimeException("Unable to open resource " + id);
+        }
+
+        DDSHeader header = readDDSHeader(is);
+
+        if (header.mPixelFormatFlags != DDS_DDPF_FOURCC) {
+            throw new RuntimeException("Unsupported DXT data");
+        }
+
+        int internalFormat = 0;
+        int bpp = 0;
+        switch (header.mPixelFormatFourCC) {
+        case DDS_DXT1:
+            internalFormat = COMPRESSED_RGB_S3TC_DXT1_EXT;
+            bpp = 4;
+            break;
+        case DDS_DXT5:
+            internalFormat = COMPRESSED_RGBA_S3TC_DXT5_EXT;
+            bpp = 8;
+            break;
+        default:
+            throw new RuntimeException("Unsupported DXT data");
+        }
+
+        // only load the first mip level for now
+        int dataSize = (header.mWidth * header.mHeight * bpp) >> 3;
+        if (dataSize != header.mPitchOrLinearSize) {
+            throw new RuntimeException("Expected data and header mismatch");
+        }
+        ByteBuffer dataBuffer = read(is, dataSize);
+
+        Texture tex = new Texture(header.mWidth, header.mHeight, internalFormat,
+                                  dataBuffer, TEXTURE_S3TC);
+        return tex;
+    }
+
+    static HashMap<String, Boolean> sExtensionMap;
+    static HashMap<String, Boolean> sFormatMap;
+
+    private static synchronized void updateSupportedFormats() {
+        if (sExtensionMap != null) {
+            return;
+        }
+
+        sExtensionMap = new HashMap<String, Boolean>();
+        sFormatMap = new HashMap<String, Boolean>();
+        String extensionList = GLES20.glGetString(GLES20.GL_EXTENSIONS);
+
+        for (String extension : extensionList.split(" ")) {
+            sExtensionMap.put(extension, true);
+        }
+
+        // Check ETC1
+        sFormatMap.put(TEXTURE_ETC1, ETC1Util.isETC1Supported());
+        // Check ATC
+        if (sExtensionMap.get("GL_AMD_compressed_ATC_texture") != null ||
+            sExtensionMap.get("GL_ATI_compressed_texture_atitc") != null ||
+            sExtensionMap.get("GL_ATI_texture_compression_atitc") != null) {
+            sFormatMap.put(TEXTURE_ATC, true);
+        }
+        // Check DXT
+        if (sExtensionMap.get("GL_EXT_texture_compression_dxt1") != null ||
+            sExtensionMap.get("GL_EXT_texture_compression_s3tc") != null ||
+            sExtensionMap.get("OES_texture_compression_S3TC") != null) {
+            sFormatMap.put(TEXTURE_S3TC, true);
+        }
+        // Check DXT
+        if (sExtensionMap.get("GL_IMG_texture_compression_pvrtc") != null) {
+            sFormatMap.put(TEXTURE_PVRTC, true);
+        }
+
+        /*Log.i(TAG, "mIsSupportedETC1 " + sFormatMap.get(TEXTURE_ETC1));
+        Log.i(TAG, "mIsSupportedATC " + sFormatMap.get(TEXTURE_ATC));
+        Log.i(TAG, "mIsSupportedDXT " + sFormatMap.get(TEXTURE_S3TC));
+        Log.i(TAG, "mIsSupportedPVRTC " + sFormatMap.get(TEXTURE_PVRTC));*/
+    }
+
+    private static boolean isFormatSupported(String format) {
+        updateSupportedFormats();
+        Boolean supported = sFormatMap.get(format);
+        return supported != null ? supported : false;
+    }
+}
diff --git a/tests/tests/graphics/src/android/opengl/cts/CompressedTextureSurfaceView.java b/tests/tests/graphics/src/android/opengl/cts/CompressedTextureSurfaceView.java
new file mode 100644
index 0000000..84aae10
--- /dev/null
+++ b/tests/tests/graphics/src/android/opengl/cts/CompressedTextureSurfaceView.java
@@ -0,0 +1,423 @@
+/*
+ * 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.
+ */
+
+package android.opengl.cts;
+
+import java.io.IOException;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import com.android.cts.graphics.R;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
+import android.graphics.SurfaceTexture;
+import android.opengl.ETC1;
+import android.opengl.ETC1Util;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+import android.opengl.GLUtils;
+import android.opengl.Matrix;
+import android.util.Log;
+import android.view.Surface;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+class CompressedTextureSurfaceView extends GLSurfaceView {
+    private static final String TAG = "CompressedTextureSurfaceView";
+    private static final int SLEEP_TIME_MS = 1000;
+
+    CompressedTextureRender mRenderer;
+
+    public CompressedTextureSurfaceView(Context context,
+                                        Bitmap base,
+                                        CompressedTextureLoader.Texture compressed) {
+        super(context);
+
+        setEGLContextClientVersion(2);
+        mRenderer = new CompressedTextureRender(context, base, compressed);
+        setRenderer(mRenderer);
+        setRenderMode(RENDERMODE_WHEN_DIRTY);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+    }
+
+    public boolean getTestPassed() throws InterruptedException {
+        return mRenderer.getTestPassed();
+    }
+
+    private static class CompressedTextureRender implements GLSurfaceView.Renderer {
+        private static String TAG = "CompressedTextureRender";
+
+        private static final int ALLOWED_DELTA = 25;
+        private static final int FBO_PIXEL_SIZE_BYTES = 4;
+        private static final int FLOAT_SIZE_BYTES = 4;
+        private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
+        private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
+        private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
+        private final float[] mTriangleVerticesData = {
+            // X, Y, Z, U, V
+            -1.0f, -1.0f, 0, 0.f, 0.f,
+            1.0f, -1.0f, 0, 1.f, 0.f,
+            -1.0f,  1.0f, 0, 0.f, 1.f,
+            1.0f,  1.0f, 0, 1.f, 1.f,
+        };
+
+        private FloatBuffer mTriangleVertices;
+
+        private final String mVertexShader =
+                "uniform mat4 uMVPMatrix;\n" +
+                "attribute vec4 aPosition;\n" +
+                "attribute vec4 aTextureCoord;\n" +
+                "varying vec2 vTextureCoord;\n" +
+                "void main() {\n" +
+                "  gl_Position = uMVPMatrix * aPosition;\n" +
+                "  vTextureCoord = aTextureCoord.xy;\n" +
+                "}\n";
+
+        private final String mFragmentShader =
+                "precision mediump float;\n" +
+                "varying vec2 vTextureCoord;\n" +
+                "uniform sampler2D sTexture;\n" +
+                "void main() {\n" +
+                "  gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
+                "}\n";
+
+        private float[] mMVPMatrix = new float[16];
+        private float[] mSTMatrix = new float[16];
+
+        private int mProgram;
+        private int mTextureID;
+        private int muMVPMatrixHandle;
+        private int maPositionHandle;
+        private int maTextureHandle;
+        private int msTextureHandle;
+
+        private int mColorTargetID;
+        private int mFrameBufferObjectID;
+
+        private boolean updateSurface = false;
+
+        private boolean mTestPassed;
+        private CountDownLatch mDoneSignal;
+
+        Bitmap mBaseTexture;
+        CompressedTextureLoader.Texture mCompressedTexture;
+
+        int mWidth;
+        int mHeight;
+
+        ByteBuffer mReadBackBuffer;
+
+        boolean getTestPassed() throws InterruptedException {
+            if (!mDoneSignal.await(2000L, TimeUnit.MILLISECONDS)) {
+                throw new IllegalStateException("Coudn't finish drawing frames!");
+            }
+
+            return mTestPassed;
+        }
+
+        public CompressedTextureRender(Context context,
+                                       Bitmap base,
+                                       CompressedTextureLoader.Texture compressed) {
+            mBaseTexture = base;
+            mCompressedTexture = compressed;
+            mTriangleVertices = ByteBuffer.allocateDirect(
+                mTriangleVerticesData.length * FLOAT_SIZE_BYTES)
+                    .order(ByteOrder.nativeOrder()).asFloatBuffer();
+            mTriangleVertices.put(mTriangleVerticesData).position(0);
+
+            Matrix.setIdentityM(mSTMatrix, 0);
+
+            int byteBufferSize = mBaseTexture.getWidth() *
+                                 mBaseTexture.getHeight() *
+                                 FBO_PIXEL_SIZE_BYTES;
+            mReadBackBuffer = ByteBuffer.allocateDirect(byteBufferSize);
+
+            mDoneSignal = new CountDownLatch(1);
+        }
+
+        private void renderQuad(int textureID) {
+            GLES20.glUseProgram(mProgram);
+            checkGlError("glUseProgram");
+
+            GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
+            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureID);
+
+            mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
+            GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false,
+                TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
+            checkGlError("glVertexAttribPointer maPosition");
+            GLES20.glEnableVertexAttribArray(maPositionHandle);
+            checkGlError("glEnableVertexAttribArray maPositionHandle");
+
+            mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
+            GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false,
+                TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
+            checkGlError("glVertexAttribPointer maTextureHandle");
+            GLES20.glEnableVertexAttribArray(maTextureHandle);
+            checkGlError("glEnableVertexAttribArray maTextureHandle");
+
+            Matrix.setIdentityM(mMVPMatrix, 0);
+            GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
+
+            GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
+            checkGlError("glDrawArrays");
+        }
+
+        private int getUnsignedByte(byte val) {
+            return 0xFF & ((int)val);
+        }
+
+        private boolean comparePixel(int x, int y) {
+            int w = mBaseTexture.getWidth();
+            int sampleStart = (y * w + x) * FBO_PIXEL_SIZE_BYTES;
+
+            int R = getUnsignedByte(mReadBackBuffer.get(sampleStart));
+            int G = getUnsignedByte(mReadBackBuffer.get(sampleStart + 1));
+            int B = getUnsignedByte(mReadBackBuffer.get(sampleStart + 2));
+
+            int original = mBaseTexture.getPixel(x, y);
+
+            int deltaR = Math.abs(R - Color.red(original));
+            int deltaG = Math.abs(G - Color.green(original));
+            int deltaB = Math.abs(B - Color.blue(original));
+
+            if (deltaR <= ALLOWED_DELTA &&
+                deltaG <= ALLOWED_DELTA &&
+                deltaB <= ALLOWED_DELTA) {
+                return true;
+            }
+
+            Log.i("PIXEL DELTA", "R: " + deltaR + " G: " + deltaG + " B: " + deltaB);
+
+            return false;
+        }
+
+        private void comparePixels() {
+            int w = mBaseTexture.getWidth();
+            int h = mBaseTexture.getWidth();
+            int wOver4 = w / 4;
+            int hOver4 = h / 4;
+
+            // Sample 4 points in the image. Test is designed so that
+            // sample areas are low frequency and easy to compare
+            boolean sample1Matches = comparePixel(wOver4, hOver4);
+            boolean sample2Matches = comparePixel(wOver4 * 3, hOver4);
+            boolean sample3Matches = comparePixel(wOver4, hOver4 * 3);
+            boolean sample4Matches = comparePixel(wOver4 * 3, hOver4 * 3);
+
+            mTestPassed = sample1Matches && sample2Matches && sample3Matches && sample4Matches;
+            mDoneSignal.countDown();
+        }
+
+        public void onDrawFrame(GL10 glUnused) {
+            if (mProgram == 0) {
+                return;
+            }
+
+            GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBufferObjectID);
+            GLES20.glViewport(0, 0, mBaseTexture.getWidth(), mBaseTexture.getHeight());
+            GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+            renderQuad(mTextureID);
+            GLES20.glReadPixels(0, 0, mBaseTexture.getWidth(), mBaseTexture.getHeight(),
+                                GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, mReadBackBuffer);
+            comparePixels();
+            GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
+
+            GLES20.glViewport(0, 0, mWidth, mHeight);
+            GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
+            GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+
+            renderQuad(mColorTargetID);
+
+            GLES20.glFinish();
+        }
+
+        public void onSurfaceChanged(GL10 glUnused, int width, int height) {
+            mWidth = width;
+            mHeight = height;
+        }
+
+        private void setupSamplers() {
+            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
+                    GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
+            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
+                    GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
+            GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
+                    GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
+            GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
+                    GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
+        }
+
+        private void initFBO() {
+            int[] textures = new int[1];
+            GLES20.glGenTextures(1, textures, 0);
+
+            mColorTargetID = textures[0];
+            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mColorTargetID);
+            checkGlError("glBindTexture mColorTargetID");
+            setupSamplers();
+            GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA,
+                                mBaseTexture.getWidth(), mBaseTexture.getHeight(), 0,
+                                GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
+            checkGlError("glTexImage2D mColorTargetID");
+
+            GLES20.glGenFramebuffers(1, textures, 0);
+            mFrameBufferObjectID = textures[0];
+            GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBufferObjectID);
+
+            GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
+                                          GLES20.GL_TEXTURE_2D, mColorTargetID, 0);
+
+            int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
+            if(status != GLES20.GL_FRAMEBUFFER_COMPLETE) {
+                throw new RuntimeException("Failed to initialize framebuffer object");
+            }
+
+            GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
+        }
+
+        public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
+            if (mCompressedTexture != null && !mCompressedTexture.isSupported()) {
+                mTestPassed = true;
+                mDoneSignal.countDown();
+                return;
+            }
+
+            initFBO();
+
+            mProgram = createProgram(mVertexShader, mFragmentShader);
+            if (mProgram == 0) {
+                return;
+            }
+            maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
+            checkGlError("glGetAttribLocation aPosition");
+            if (maPositionHandle == -1) {
+                throw new RuntimeException("Could not get attrib location for aPosition");
+            }
+            maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord");
+            checkGlError("glGetAttribLocation aTextureCoord");
+            if (maTextureHandle == -1) {
+                throw new RuntimeException("Could not get attrib location for aTextureCoord");
+            }
+
+            muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
+            checkGlError("glGetUniformLocation uMVPMatrix");
+            if (muMVPMatrixHandle == -1) {
+                throw new RuntimeException("Could not get attrib location for uMVPMatrix");
+            }
+
+            int[] textures = new int[1];
+            GLES20.glGenTextures(1, textures, 0);
+
+            mTextureID = textures[0];
+            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);
+            checkGlError("glBindTexture mTextureID");
+            setupSamplers();
+
+            if (mCompressedTexture == null) {
+                GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, mBaseTexture, 0);
+                checkGlError("texImage2D mBaseTexture");
+            } else {
+                GLES20.glCompressedTexImage2D(GLES20.GL_TEXTURE_2D,
+                                              0,
+                                              mCompressedTexture.getFormat(),
+                                              mCompressedTexture.getWidth(),
+                                              mCompressedTexture.getHeight(),
+                                              0,
+                                              mCompressedTexture.getData().remaining(),
+                                              mCompressedTexture.getData());
+                checkGlError("glCompressedTexImage2D mTextureID");
+            }
+        }
+
+        synchronized public void onFrameAvailable(SurfaceTexture surface) {
+            updateSurface = true;
+        }
+
+        private int loadShader(int shaderType, String source) {
+            int shader = GLES20.glCreateShader(shaderType);
+            if (shader != 0) {
+                GLES20.glShaderSource(shader, source);
+                GLES20.glCompileShader(shader);
+                int[] compiled = new int[1];
+                GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
+                if (compiled[0] == 0) {
+                    Log.e(TAG, "Could not compile shader " + shaderType + ":");
+                    Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
+                    GLES20.glDeleteShader(shader);
+                    shader = 0;
+                }
+            }
+            return shader;
+        }
+
+        private int createProgram(String vertexSource, String fragmentSource) {
+            int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
+            if (vertexShader == 0) {
+                return 0;
+            }
+            int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
+            if (pixelShader == 0) {
+                return 0;
+            }
+
+            int program = GLES20.glCreateProgram();
+            if (program != 0) {
+                GLES20.glAttachShader(program, vertexShader);
+                checkGlError("glAttachShader");
+                GLES20.glAttachShader(program, pixelShader);
+                checkGlError("glAttachShader");
+                GLES20.glLinkProgram(program);
+                int[] linkStatus = new int[1];
+                GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
+                if (linkStatus[0] != GLES20.GL_TRUE) {
+                    Log.e(TAG, "Could not link program: ");
+                    Log.e(TAG, GLES20.glGetProgramInfoLog(program));
+                    GLES20.glDeleteProgram(program);
+                    program = 0;
+                }
+            }
+            return program;
+        }
+
+        private void checkGlError(String op) {
+            int error;
+            while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
+                Log.e(TAG, op + ": glError " + error);
+                throw new RuntimeException(op + ": glError " + error);
+            }
+        }
+
+    }  // End of class CompressedTextureRender.
+
+}  // End of class CompressedTextureSurfaceView.
diff --git a/tests/tests/graphics/src/android/opengl/cts/CompressedTextureTest.java b/tests/tests/graphics/src/android/opengl/cts/CompressedTextureTest.java
index 3ed9131..c153712 100644
--- a/tests/tests/graphics/src/android/opengl/cts/CompressedTextureTest.java
+++ b/tests/tests/graphics/src/android/opengl/cts/CompressedTextureTest.java
@@ -21,17 +21,17 @@
 
 /**
  */
-public class CompressedTextureTest extends ActivityInstrumentationTestCase2<CompressedTextureStubActivity> {
+public class CompressedTextureTest extends ActivityInstrumentationTestCase2<CompressedTextureCtsActivity> {
 
     public CompressedTextureTest() {
-        super("com.android.cts.stub", CompressedTextureStubActivity.class);
+        super("com.android.cts.graphics", CompressedTextureCtsActivity.class);
     }
 
     private void launchTest(String format) throws Exception {
         Bundle extras = new Bundle();
         extras.putString("TextureFormat", format);
-        CompressedTextureStubActivity activity = launchActivity("com.android.cts.stub",
-                CompressedTextureStubActivity.class, extras);
+        CompressedTextureCtsActivity activity = launchActivity("com.android.cts.graphics",
+                CompressedTextureCtsActivity.class, extras);
         activity.finish();
         assertTrue(activity.getPassed());
     }
diff --git a/tests/tests/graphics/src/android/opengl/cts/EglConfigCtsActivity.java b/tests/tests/graphics/src/android/opengl/cts/EglConfigCtsActivity.java
new file mode 100644
index 0000000..cef9e2f
--- /dev/null
+++ b/tests/tests/graphics/src/android/opengl/cts/EglConfigCtsActivity.java
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+package android.opengl.cts;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.view.WindowManager;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * {@link Activity} with a {@link GLSurfaceView} that chooses a specific configuration.
+ */
+public class EglConfigCtsActivity extends Activity {
+
+    public static final String CONFIG_ID_EXTRA = "eglConfigId";
+
+    public static final String CONTEXT_CLIENT_VERSION_EXTRA = "eglContextClientVersion";
+
+    private EglConfigGLSurfaceView mView;
+
+    private CountDownLatch mFinishedDrawing;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        int configId = getConfigId();
+        int contextClientVersion = getContextClientVersion();
+        setTitle("EGL Config Id: " + configId + " Client Version: " + contextClientVersion);
+
+        // Dismiss keyguard and keep screen on while this test is on.
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
+                WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
+                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+
+        mFinishedDrawing = new CountDownLatch(1);
+        mView = new EglConfigGLSurfaceView(this, configId, contextClientVersion, new Runnable() {
+            @Override
+            public void run() {
+                mFinishedDrawing.countDown();
+            }
+        });
+        setContentView(mView);
+    }
+
+    private int getConfigId() {
+        Intent intent = getIntent();
+        if (intent != null) {
+            return intent.getIntExtra(CONFIG_ID_EXTRA, 0);
+        } else {
+            return 0;
+        }
+    }
+
+    private int getContextClientVersion() {
+        Intent intent = getIntent();
+        if (intent != null) {
+            return intent.getIntExtra(CONTEXT_CLIENT_VERSION_EXTRA, 0);
+        } else {
+            return 0;
+        }
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        mView.onResume();
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        mView.onPause();
+    }
+
+    public void waitToFinishDrawing() throws InterruptedException {
+        if (!mFinishedDrawing.await(3, TimeUnit.SECONDS)) {
+            throw new IllegalStateException("Coudn't finish drawing frames!");
+        }
+    }
+}
diff --git a/tests/src/android/opengl/cts/EglConfigGLSurfaceView.java b/tests/tests/graphics/src/android/opengl/cts/EglConfigGLSurfaceView.java
similarity index 100%
rename from tests/src/android/opengl/cts/EglConfigGLSurfaceView.java
rename to tests/tests/graphics/src/android/opengl/cts/EglConfigGLSurfaceView.java
diff --git a/tests/tests/graphics/src/android/opengl/cts/EglConfigTest.java b/tests/tests/graphics/src/android/opengl/cts/EglConfigTest.java
index 2f918db..14c8e10 100644
--- a/tests/tests/graphics/src/android/opengl/cts/EglConfigTest.java
+++ b/tests/tests/graphics/src/android/opengl/cts/EglConfigTest.java
@@ -28,7 +28,7 @@
 /**
  * Test that gets a list of EGL configurations and tries to use each one in a GLSurfaceView.
  */
-public class EglConfigTest extends ActivityInstrumentationTestCase2<EglConfigStubActivity> {
+public class EglConfigTest extends ActivityInstrumentationTestCase2<EglConfigCtsActivity> {
 
     private static final int EGL_OPENGL_ES_BIT = 0x1;
 
@@ -37,7 +37,7 @@
     private Instrumentation mInstrumentation;
 
     public EglConfigTest() {
-        super("com.android.cts.stub", EglConfigStubActivity.class);
+        super("com.android.cts.graphics", EglConfigCtsActivity.class);
     }
 
     @Override
@@ -58,10 +58,10 @@
             throws InterruptedException {
         for (int configId : configIds) {
             Bundle extras = new Bundle();
-            extras.putInt(EglConfigStubActivity.CONFIG_ID_EXTRA, configId);
-            extras.putInt(EglConfigStubActivity.CONTEXT_CLIENT_VERSION_EXTRA, contextClientVersion);
-            EglConfigStubActivity activity = launchActivity("com.android.cts.stub",
-                    EglConfigStubActivity.class, extras);
+            extras.putInt(EglConfigCtsActivity.CONFIG_ID_EXTRA, configId);
+            extras.putInt(EglConfigCtsActivity.CONTEXT_CLIENT_VERSION_EXTRA, contextClientVersion);
+            EglConfigCtsActivity activity = launchActivity("com.android.cts.graphics",
+                    EglConfigCtsActivity.class, extras);
             activity.waitToFinishDrawing();
             activity.finish();
             mInstrumentation.waitForIdleSync();
diff --git a/tests/tests/graphics/src/android/opengl/cts/GLSurfaceViewCtsActivity.java b/tests/tests/graphics/src/android/opengl/cts/GLSurfaceViewCtsActivity.java
new file mode 100644
index 0000000..9557406
--- /dev/null
+++ b/tests/tests/graphics/src/android/opengl/cts/GLSurfaceViewCtsActivity.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2010 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.opengl.cts;
+
+import android.app.Activity;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.view.Window;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+/**
+ * A minimal activity for testing {@link android.opengl.GLSurfaceView}.
+ * Also accepts non-blank renderers to allow its use for more complex tests.
+ */
+public class GLSurfaceViewCtsActivity extends Activity {
+
+    private static class Renderer implements GLSurfaceView.Renderer {
+
+        public void onDrawFrame(GL10 gl) {
+            // Do nothing.
+        }
+
+        public void onSurfaceChanged(GL10 gl, int width, int height) {
+            // Do nothing.
+        }
+
+        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+            // Do nothing.
+        }
+    }
+
+    private GLSurfaceView mView;
+
+    /** To override the blank renderer, or other settings, these
+     * static set* methods must be called before onCreate() is called.
+     * If using ActivityInstrumentationTestCase2, that means the set
+     * methods need to be called before calling getActivity in the
+     * test setUp().
+     */
+    private static GLSurfaceView.Renderer mRenderer = null;
+    public static void setRenderer(GLSurfaceView.Renderer renderer) {
+        mRenderer = renderer;
+    }
+    public static void resetRenderer() {
+        mRenderer = null;
+    }
+
+    private static int mRenderMode = 0;
+    private static boolean mRenderModeSet = false;
+    public static void setRenderMode(int renderMode) {
+        mRenderModeSet = true;
+        mRenderMode = renderMode;
+    }
+    public static void resetRenderMode() {
+        mRenderModeSet = false;
+        mRenderMode = 0;
+    }
+
+    private static int mGlVersion = 0;
+    private static boolean mGlVersionSet = false;
+    public static void setGlVersion(int glVersion) {
+        mGlVersionSet = true;
+        mGlVersion = glVersion;
+    }
+    public static void resetGlVersion() {
+        mGlVersionSet = false;
+        mGlVersion = 0;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mView = new GLSurfaceView(this);
+        // Only set this if explicitly asked for
+        if (mGlVersionSet) {
+            mView.setEGLContextClientVersion(mGlVersion);
+        }
+        // Use no-op renderer by default
+        if (mRenderer == null) {
+            mView.setRenderer(new Renderer());
+        } else {
+            mView.setRenderer(mRenderer);
+        }
+        // Only set this if explicitly asked for
+        if (mRenderModeSet) {
+            mView.setRenderMode(mRenderMode);
+        }
+        this.requestWindowFeature(Window.FEATURE_NO_TITLE);
+        setContentView(mView);
+    }
+
+    public GLSurfaceView getView() {
+        return mView;
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        mView.onResume();
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        mView.onPause();
+    }
+}
diff --git a/tests/tests/graphics/src/android/opengl/cts/GLSurfaceViewTest.java b/tests/tests/graphics/src/android/opengl/cts/GLSurfaceViewTest.java
index 2a8d698..87995fb 100644
--- a/tests/tests/graphics/src/android/opengl/cts/GLSurfaceViewTest.java
+++ b/tests/tests/graphics/src/android/opengl/cts/GLSurfaceViewTest.java
@@ -26,7 +26,7 @@
  * Tests for the GLSurfaceView class.
  */
 public class GLSurfaceViewTest extends
-        ActivityInstrumentationTestCase2<GLSurfaceViewStubActivity> {
+        ActivityInstrumentationTestCase2<GLSurfaceViewCtsActivity> {
 
     private static final int NUM_PAUSE_RESUME_ITERATIONS_WITHOUT_DELAY = 1000;
 
@@ -38,10 +38,10 @@
 
     private static final String TAG = "GLSurfaceViewTest";
 
-    private GLSurfaceViewStubActivity mActivity;
+    private GLSurfaceViewCtsActivity mActivity;
 
     public GLSurfaceViewTest() {
-        super("com.android.cts.stub", GLSurfaceViewStubActivity.class);
+        super("com.android.cts.graphics", GLSurfaceViewCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionCtsActivity.java b/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionCtsActivity.java
new file mode 100644
index 0000000..8a85555
--- /dev/null
+++ b/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionCtsActivity.java
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2010 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.opengl.cts;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.opengl.GLES31;
+import android.opengl.GLES31Ext;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.util.Log;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+/**
+ * {@link Activity} that queries the device's display attributes to determine what version of
+ * OpenGL ES is supported and returns what the GL version string reports.
+ */
+public class OpenGlEsVersionCtsActivity extends Activity {
+    private static String TAG = "OpenGlEsVersionCtsActivity";
+
+    private static final String EGL_CONTEXT_CLIENT_VERSION = "eglContextClientVersion";
+
+    /** Timeout to wait for the surface to be created and the version queried. */
+    private static final int TIMEOUT_SECONDS = 10;
+
+    /** Version string reported by glGetString. */
+    private String mVersionString;
+
+    /** Extensions string reported by glGetString. */
+    private String mExtensionsString;
+
+    /** Whether GL_ANDROID_extension_pack_es31a is correctly supported. */
+    private boolean mAepEs31Support = false;
+
+    /** Latch that is unlocked when the activity is done finding the version. */
+    private CountDownLatch mSurfaceCreatedLatch = new CountDownLatch(1);
+
+    public static Intent createIntent(int eglContextClientVersion) {
+        Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.putExtra(EGL_CONTEXT_CLIENT_VERSION, eglContextClientVersion);
+        return intent;
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        GLSurfaceView view = new GLSurfaceView(this);
+
+        Intent intent = getIntent();
+        int eglContextClientVersion = intent.getIntExtra(EGL_CONTEXT_CLIENT_VERSION, -1);
+        if (eglContextClientVersion > 0) {
+            view.setEGLContextClientVersion(eglContextClientVersion);
+        }
+
+        view.setRenderer(new Renderer());
+        setContentView(view);
+    }
+
+    public String getVersionString() throws InterruptedException {
+        mSurfaceCreatedLatch.await(TIMEOUT_SECONDS, TimeUnit.SECONDS);
+        synchronized (this) {
+            return mVersionString;
+        }
+    }
+
+    public String getExtensionsString() throws InterruptedException {
+        mSurfaceCreatedLatch.await(TIMEOUT_SECONDS, TimeUnit.SECONDS);
+        synchronized (this) {
+            return mExtensionsString;
+        }
+    }
+
+    public boolean getAepEs31Support() throws InterruptedException {
+        mSurfaceCreatedLatch.await(TIMEOUT_SECONDS, TimeUnit.SECONDS);
+        synchronized (this) {
+            return mAepEs31Support;
+        }
+    }
+
+    public static boolean hasExtension(String extensions, String name) {
+        int start = extensions.indexOf(name);
+        while (start >= 0) {
+            // check that we didn't find a prefix of a longer extension name
+            int end = start + name.length();
+            if (end == extensions.length() || extensions.charAt(end) == ' ') {
+                return true;
+            }
+            start = extensions.indexOf(name, end);
+        }
+        return false;
+    }
+
+    private class Renderer implements GLSurfaceView.Renderer {
+        /**
+         * These shaders test at least one feature of each of the underlying extension, to verify
+         * that enabling GL_ANDROID_extension_pack_es31a correctly enables all of them.
+         */
+        private final String mAepEs31VertexShader =
+                "#version 310 es\n" +
+                "#extension GL_ANDROID_extension_pack_es31a : require\n" +
+                "void main() {\n" +
+                "  gl_Position = vec4(1, 0, 0, 1);\n" +
+                "}\n";
+
+        private final String mAepEs31TessellationControlShader =
+                "#version 310 es\n" +
+                "#extension GL_ANDROID_extension_pack_es31a : require\n" +
+                "layout(vertices = 3) out;\n" +  // GL_EXT_tessellation_shader
+                "void main() {\n" +
+                "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" +  // GL_EXT_shader_io_blocks
+                "  if (gl_InvocationID == 0) {\n" +
+                "    gl_BoundingBoxEXT[0] = gl_in[0].gl_Position;\n" +  // GL_EXT_primitive_bounding_box
+                "    gl_BoundingBoxEXT[1] = gl_in[1].gl_Position;\n" +
+                "  }\n" +
+                "}\n";
+
+        private final String mAepEs31TessellationEvaluationShader =
+                "#version 310 es\n" +
+                "#extension GL_ANDROID_extension_pack_es31a : require\n" +
+                "layout(triangles, equal_spacing, cw) in;\n" +
+                "void main() {\n" +
+                "  gl_Position = gl_in[0].gl_Position * gl_TessCoord.x +\n" +
+                "      gl_in[1].gl_Position * gl_TessCoord.y +\n" +
+                "      gl_in[2].gl_Position * gl_TessCoord.z;\n" +
+                "}\n";
+
+        private final String mAepEs31GeometryShader =
+                "#version 310 es\n" +
+                "#extension GL_ANDROID_extension_pack_es31a : require\n" +
+                "layout(triangles) in;\n" +  // GL_EXT_geometry_shader
+                "layout(triangle_strip, max_vertices = 3) out;\n" +
+                "sample out vec4 perSampleColor;\n" +
+                "void main() {\n" +
+                "  for (int i = 0; i < gl_in.length(); ++i) {\n" +
+                "    gl_Position = gl_in[i].gl_Position;\n" +
+                "    perSampleColor = gl_in[i].gl_Position;\n" +
+                "    EmitVertex();\n" +
+                "  }\n" +
+                "}\n";
+
+        private final String mAepEs31FragmentShader =
+                "#version 310 es\n" +
+                "#extension GL_ANDROID_extension_pack_es31a : require\n" +
+                "precision mediump float;\n" +
+                "layout(blend_support_all_equations) out;\n" +  // GL_KHR_blend_equation_advanced
+                "sample in vec4 perSampleColor;\n" +  // GL_OES_shader_multisample_interpolation
+                "layout(r32ui) coherent uniform mediump uimage2D image;\n" +
+                "uniform mediump sampler2DMSArray mySamplerMSArray;\n" +  // GL_OES_texture_storage_multisample_2d_array
+                "uniform mediump samplerBuffer mySamplerBuffer;\n" +  // GL_EXT_texture_buffer
+                "uniform mediump samplerCubeArray mySamplerCubeArray;\n" +  // GL_EXT_texture_cube_map_array
+                "out vec4 color;\n" +
+                "void main() {\n" +
+                "  imageAtomicAdd(image, ivec2(1, 1), 1u);\n" +  // GL_OES_shader_image_atomic
+                "  vec4 color = vec4(gl_SamplePosition.x, 0, 0, 1);\n" +  // GL_OES_sample_variables
+                "  vec4 color2 = texelFetch(mySamplerMSArray, ivec3(1, 1, 1), 3);\n" +
+                "  vec4 color3 = texelFetch(mySamplerBuffer, 3);\n" +
+                "  vec4 color4 = texture(mySamplerCubeArray, vec4(1, 1, 1, 1));\n" +
+                "  color = fma(color + color2, color3 + color4, perSampleColor);" +  // GL_EXT_gpu_shader5
+                "}\n";
+
+        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+            synchronized (OpenGlEsVersionCtsActivity.this) {
+                try {
+                    mVersionString = gl.glGetString(GL10.GL_VERSION);
+                    mExtensionsString = gl.glGetString(GL10.GL_EXTENSIONS);
+                    if (hasExtension(mExtensionsString, "ANDROID_extension_pack_es31a"))
+                        mAepEs31Support = checkAepEs31Support();
+                } finally {
+                    mSurfaceCreatedLatch.countDown();
+                }
+            }
+        }
+
+        public void onSurfaceChanged(GL10 gl, int width, int height) {
+        }
+
+        public void onDrawFrame(GL10 gl) {
+        }
+
+        private boolean compileShaderAndAttach(int program, int shaderType, String source) {
+            int shader = GLES31.glCreateShader(shaderType);
+            if (shader == 0) {
+                Log.e(TAG, "Unable to create shaders of type " + shaderType);
+                return false;
+            }
+            GLES31.glShaderSource(shader, source);
+            GLES31.glCompileShader(shader);
+            int[] compiled = new int[1];
+            GLES31.glGetShaderiv(shader, GLES31.GL_COMPILE_STATUS, compiled, 0);
+            if (compiled[0] == 0) {
+                Log.e(TAG, "Unable to compile shader " + shaderType + ":");
+                Log.e(TAG, GLES31.glGetShaderInfoLog(shader));
+                GLES31.glDeleteShader(shader);
+                return false;
+            }
+            GLES31.glAttachShader(program, shader);
+            GLES31.glDeleteShader(shader);
+            return true;
+        }
+
+        private boolean checkAepEs31Support() {
+            final String requiredList[] = {
+                "EXT_copy_image",
+                "EXT_draw_buffers_indexed",
+                "EXT_geometry_shader",
+                "EXT_gpu_shader5",
+                "EXT_primitive_bounding_box",
+                "EXT_shader_io_blocks",
+                "EXT_tessellation_shader",
+                "EXT_texture_border_clamp",
+                "EXT_texture_buffer",
+                "EXT_texture_cube_map_array",
+                "EXT_texture_sRGB_decode",
+                "KHR_blend_equation_advanced",
+                "KHR_debug",
+                "KHR_texture_compression_astc_ldr",
+                "OES_sample_shading",
+                "OES_sample_variables",
+                "OES_shader_image_atomic",
+                "OES_shader_multisample_interpolation",
+                "OES_texture_stencil8",
+                "OES_texture_storage_multisample_2d_array"
+            };
+
+            for (int i = 0; i < requiredList.length; ++i) {
+                if (!hasExtension(mExtensionsString, requiredList[i])) {
+                    Log.e(TAG,"ANDROID_extension_pack_es31a is present but extension " +
+                            requiredList[i] + " is missing");
+                    return false;
+                }
+            }
+
+            int[] value = new int[1];
+            GLES31.glGetIntegerv(GLES31.GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, value, 0);
+            if (value[0] < 1) {
+                Log.e(TAG, "ANDROID_extension_pack_es31a is present, but the " +
+                        "GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS value is " + value[0] + " < 1");
+                return false;
+            }
+            GLES31.glGetIntegerv(GLES31.GL_MAX_FRAGMENT_ATOMIC_COUNTERS, value, 0);
+            if (value[0] < 8) {
+                Log.e(TAG, "ANDROID_extension_pack_es31a is present, but the " +
+                        "GL_MAX_FRAGMENT_ATOMIC_COUNTERS value is " + value[0] + " < 8");
+                return false;
+            }
+            GLES31.glGetIntegerv(GLES31.GL_MAX_FRAGMENT_IMAGE_UNIFORMS, value, 0);
+            if (value[0] < 4) {
+                Log.e(TAG, "ANDROID_extension_pack_es31a is present, but the " +
+                        "GL_MAX_FRAGMENT_IMAGE_UNIFORMS value is " + value[0] + " < 4");
+                return false;
+            }
+            GLES31.glGetIntegerv(GLES31.GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, value, 0);
+            if (value[0] < 4) {
+                Log.e(TAG, "ANDROID_extension_pack_es31a is present, but the " +
+                        "GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS value is " + value[0] + " < 4");
+                return false;
+            }
+
+            int program = GLES31.glCreateProgram();
+            try {
+                if (!compileShaderAndAttach(program, GLES31.GL_VERTEX_SHADER, mAepEs31VertexShader) ||
+                    !compileShaderAndAttach(program, GLES31Ext.GL_TESS_CONTROL_SHADER_EXT, mAepEs31TessellationControlShader) ||
+                    !compileShaderAndAttach(program, GLES31Ext.GL_TESS_EVALUATION_SHADER_EXT, mAepEs31TessellationEvaluationShader) ||
+                    !compileShaderAndAttach(program, GLES31Ext.GL_GEOMETRY_SHADER_EXT, mAepEs31GeometryShader) ||
+                    !compileShaderAndAttach(program, GLES31.GL_FRAGMENT_SHADER, mAepEs31FragmentShader))
+                    return false;
+
+                GLES31.glLinkProgram(program);
+                GLES31.glGetProgramiv(program, GLES31.GL_LINK_STATUS, value, 0);
+                if (value[0] == 0) {
+                    Log.e(TAG, "Unable to link program :");
+                    Log.e(TAG, GLES31.glGetProgramInfoLog(program));
+                    return false;
+                }
+            } finally {
+                GLES31.glDeleteProgram(program);
+            }
+            return true;
+        }
+    }
+}
diff --git a/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionTest.java b/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionTest.java
index 85159a8..28ac5c0 100644
--- a/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionTest.java
+++ b/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionTest.java
@@ -36,7 +36,7 @@
  * Test for checking whether the ro.opengles.version property is set to the correct value.
  */
 public class OpenGlEsVersionTest
-        extends ActivityInstrumentationTestCase2<OpenGlEsVersionStubActivity> {
+        extends ActivityInstrumentationTestCase2<OpenGlEsVersionCtsActivity> {
 
     private static final String TAG = OpenGlEsVersionTest.class.getSimpleName();
 
@@ -45,10 +45,10 @@
     private static final int EGL_OPENGL_ES2_BIT = 0x0004;
     private static final int EGL_OPENGL_ES3_BIT_KHR = 0x0040;
 
-    private OpenGlEsVersionStubActivity mActivity;
+    private OpenGlEsVersionCtsActivity mActivity;
 
     public OpenGlEsVersionTest() {
-        super("com.android.cts.stub", OpenGlEsVersionStubActivity.class);
+        super("com.android.cts.graphics", OpenGlEsVersionCtsActivity.class);
     }
 
     @Override
@@ -58,40 +58,89 @@
     }
 
     public void testOpenGlEsVersion() throws InterruptedException {
-        int detectedVersion = getDetectedVersion();
+        int detectedMajorVersion = getDetectedMajorVersion();
         int reportedVersion = getVersionFromActivityManager(mActivity);
 
-        assertEquals("Detected OpenGL ES major version " + detectedVersion
-                + " but Activity Manager is reporting " +  reportedVersion
-                + " (Check ro.opengles.version)", detectedVersion, reportedVersion);
+        assertEquals("Detected OpenGL ES major version " + detectedMajorVersion
+                + " but Activity Manager is reporting " +  getMajorVersion(reportedVersion)
+                + " (Check ro.opengles.version)",
+                detectedMajorVersion, getMajorVersion(reportedVersion));
         assertEquals("Reported OpenGL ES version from ActivityManager differs from PackageManager",
                 reportedVersion, getVersionFromPackageManager(mActivity));
 
         assertGlVersionString(1);
-        if (detectedVersion == 2) {
+        if (detectedMajorVersion == 2) {
             restartActivityWithClientVersion(2);
             assertGlVersionString(2);
-        } else if (detectedVersion == 3) {
+        } else if (detectedMajorVersion == 3) {
             restartActivityWithClientVersion(3);
             assertGlVersionString(3);
         }
     }
 
-    private static boolean hasExtension(String extensions, String name) {
-        int start = extensions.indexOf(name);
-        while (start >= 0) {
-            // check that we didn't find a prefix of a longer extension name
-            int end = start + name.length();
-            if (end == extensions.length() || extensions.charAt(end) == ' ') {
-                return true;
-            }
-            start = extensions.indexOf(name, end);
+    public void testRequiredExtensions() throws InterruptedException {
+        int reportedVersion = getVersionFromActivityManager(mActivity);
+        // We only have required extensions on ES3.1
+        if (getMajorVersion(reportedVersion) != 3 || getMinorVersion(reportedVersion) != 1)
+            return;
+
+        restartActivityWithClientVersion(3);
+
+        String extensions = mActivity.getExtensionsString();
+        final String requiredList[] = {
+            "EXT_texture_sRGB_decode",
+            "KHR_blend_equation_advanced",
+            "KHR_debug",
+            "OES_shader_image_atomic",
+            "OES_texture_stencil8",
+            "OES_texture_storage_multisample_2d_array"
+        };
+
+        for (int i = 0; i < requiredList.length; ++i) {
+            assertTrue("OpenGL ES version 3.1 is missing extension " + requiredList[i],
+                    hasExtension(extensions, requiredList[i]));
         }
-        return false;
+    }
+
+    public void testExtensionPack() throws InterruptedException {
+        // Requirements:
+        // 1. If the device claims support for the system feature, the extension must be available.
+        // 2. If the extension is available, it must be correct:
+        //    - ES 3.1 must be supported
+        //    - All included extensions must be available
+        //
+        // Supporting the extension but not claiming support for the system feature is allowed,
+        // just like the ES context version can be higher than the ro.opengles.version property.
+
+        int reportedVersion = getVersionFromActivityManager(mActivity);
+        boolean hasAepFeature = mActivity.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_OPENGLES_EXTENSION_PACK);
+
+        if (getMajorVersion(reportedVersion) != 3 || getMinorVersion(reportedVersion) != 1) {
+            assertFalse("FEATURE_OPENGLES_EXTENSION_PACK is available without OpenGL ES 3.1",
+                    hasAepFeature);
+            return;
+        }
+
+        restartActivityWithClientVersion(3);
+
+        String extensions = mActivity.getExtensionsString();
+        if (!hasExtension(extensions, "ANDROID_extension_pack_es31a")) {
+            assertFalse("FEATURE_OPENGLES_EXTENSION_PACK is available but ANDROID_extension_pack_es31a isn't in the extension list",
+                    hasAepFeature);
+            return;
+        }
+
+        assertTrue("ANDROID_extension_pack_es31a is present, but support is incomplete",
+                mActivity.getAepEs31Support());
+    }
+
+    private static boolean hasExtension(String extensions, String name) {
+        return OpenGlEsVersionCtsActivity.hasExtension(extensions, name);
     }
 
     /** @return OpenGL ES major version 1, 2, or 3 or some non-positive number for error */
-    private static int getDetectedVersion() {
+    private static int getDetectedMajorVersion() {
         /*
          * Get all the device configurations and check the EGL_RENDERABLE_TYPE attribute
          * to determine the highest ES version supported by any config. The
@@ -156,9 +205,9 @@
             (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
         ConfigurationInfo configInfo = activityManager.getDeviceConfigurationInfo();
         if (configInfo.reqGlEsVersion != ConfigurationInfo.GL_ES_VERSION_UNDEFINED) {
-            return getMajorVersion(configInfo.reqGlEsVersion);
+            return configInfo.reqGlEsVersion;
         } else {
-            return 1; // Lack of property means OpenGL ES version 1
+            return 1 << 16; // Lack of property means OpenGL ES version 1
         }
     }
 
@@ -170,9 +219,9 @@
                 // Null feature name means this feature is the open gl es version feature.
                 if (featureInfo.name == null) {
                     if (featureInfo.reqGlEsVersion != FeatureInfo.GL_ES_VERSION_UNDEFINED) {
-                        return getMajorVersion(featureInfo.reqGlEsVersion);
+                        return featureInfo.reqGlEsVersion;
                     } else {
-                        return 1; // Lack of property means OpenGL ES version 1
+                        return 1 << 16; // Lack of property means OpenGL ES version 1
                     }
                 }
             }
@@ -185,6 +234,11 @@
         return ((glEsVersion & 0xffff0000) >> 16);
     }
 
+    /** @see FeatureInfo#getGlEsVersion() */
+    private static int getMinorVersion(int glEsVersion) {
+        return glEsVersion & 0xffff;
+    }
+
     /**
      * Check that the version string has some form of "Open GL ES X.Y" in it where X is the major
      * version and Y must be some digit.
@@ -197,13 +251,13 @@
                 mActivity.getVersionString()));
     }
 
-    /** Restart {@link GLSurfaceViewStubActivity} with a specific client version. */
+    /** Restart {@link GLSurfaceViewCtsActivity} with a specific client version. */
     private void restartActivityWithClientVersion(int version) {
         mActivity.finish();
         setActivity(null);
 
         try {
-            Intent intent = OpenGlEsVersionStubActivity.createIntent(version);
+            Intent intent = OpenGlEsVersionCtsActivity.createIntent(version);
             setActivityIntent(intent);
             mActivity = getActivity();
         } finally {
diff --git a/tests/tests/graphics2/Android.mk b/tests/tests/graphics2/Android.mk
index b3e7340..a3cdafa 100644
--- a/tests/tests/graphics2/Android.mk
+++ b/tests/tests/graphics2/Android.mk
@@ -21,8 +21,6 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/graphics2/AndroidManifest.xml b/tests/tests/graphics2/AndroidManifest.xml
index 2392100..67557ad 100644
--- a/tests/tests/graphics2/AndroidManifest.xml
+++ b/tests/tests/graphics2/AndroidManifest.xml
@@ -24,7 +24,10 @@
 
     <instrumentation
         android:targetPackage="com.android.cts.graphics2"
-        android:name="android.test.InstrumentationCtsTestRunner" />
+        android:name="android.support.test.runner.AndroidJUnitRunner" >
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
     <application>
         <uses-library android:name="android.test.runner" />
diff --git a/tests/tests/hardware/Android.mk b/tests/tests/hardware/Android.mk
index e0ad6e5..e5203e5 100644
--- a/tests/tests/hardware/Android.mk
+++ b/tests/tests/hardware/Android.mk
@@ -21,7 +21,18 @@
 LOCAL_MODULE := cts-sensors-tests
 LOCAL_MODULE_TAGS := tests
 
+LOCAL_SDK_VERSION := current
+
+# TODO: sensors need to be refactored out into their own namespace: android.hardware.sensors.cts
 LOCAL_SRC_FILES := $(call all-java-files-under, src/android/hardware/cts/helpers)
+LOCAL_SRC_FILES += \
+    src/android/hardware/cts/SensorTestCase.java \
+    src/android/hardware/cts/SingleSensorTests.java \
+    src/android/hardware/cts/SensorIntegrationTests.java \
+    src/android/hardware/cts/SensorBatchingTests.java \
+    src/android/hardware/cts/SensorTest.java \
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil
 
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
@@ -32,17 +43,17 @@
 
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner mockito-target android-ex-camera2
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner mockito-target android-ex-camera2
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsHardwareTestCases
 
-LOCAL_INSTRUMENTATION_FOR := CtsTestStubs
-
-# uncomment when dalvik.annotation.Test* are removed or part of SDK
-#LOCAL_SDK_VERSION := current
+# uncomment when b/13281332 is fixed
+# please also uncomment the equivalent code in
+# cts/apps/CtsVerifiers/Android.mk
+#
+# LOCAL_SDK_VERSION := current
+LOCAL_JAVA_LIBRARIES := android.test.runner
 
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/hardware/AndroidManifest.xml b/tests/tests/hardware/AndroidManifest.xml
index 971d6c7..ca148f9 100644
--- a/tests/tests/hardware/AndroidManifest.xml
+++ b/tests/tests/hardware/AndroidManifest.xml
@@ -19,13 +19,43 @@
     package="com.android.cts.hardware">
 
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+    <uses-permission android:name="android.permission.CAMERA" />
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
     <application>
         <uses-library android:name="android.test.runner" />
+
+        <activity android:name="android.hardware.cts.CameraCtsActivity"
+            android:label="CameraCtsActivity"
+            android:screenOrientation="landscape"
+            android:configChanges="keyboardHidden|orientation|screenSize">
+        </activity>
+
+        <activity android:name="android.hardware.camera2.cts.Camera2SurfaceViewCtsActivity"
+            android:label="Camera2CtsActivity"
+            android:screenOrientation="landscape"
+            android:configChanges="keyboardHidden|orientation|screenSize">
+        </activity>
+
+        <activity android:name="android.hardware.camera2.cts.Camera2MultiViewCtsActivity"
+            android:label="Camera2MultiViewCtsActivity"
+            android:screenOrientation="landscape"
+            android:configChanges="keyboardHidden|orientation|screenSize">
+        </activity>
+
+        <activity android:name="android.hardware.cts.GLSurfaceViewCtsActivity"
+            android:label="GLSurfaceViewCtsActivity"/>
+
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="com.android.cts.stub"
-                     android:label="CTS tests of android.hardware"/>
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.hardware"
+                     android:label="CTS tests of android.hardware">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/tests/hardware/res/layout/multi_view.xml b/tests/tests/hardware/res/layout/multi_view.xml
new file mode 100644
index 0000000..4f335d3
--- /dev/null
+++ b/tests/tests/hardware/res/layout/multi_view.xml
@@ -0,0 +1,42 @@
+<?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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <TextureView
+        android:id="@+id/texture_view_1"
+        android:layout_width="160dp"
+        android:layout_height="120dp"/>
+
+    <TextureView
+        android:id="@+id/texture_view_2"
+        android:layout_width="160dp"
+        android:layout_height="120dp"/>
+    <SurfaceView
+        android:id="@+id/surface_view_1"
+        android:layout_width="160dp"
+        android:layout_height="120dp"/>
+
+    <SurfaceView
+        android:id="@+id/surface_view_2"
+        android:layout_width="160dp"
+        android:layout_height="120dp"/>
+
+</LinearLayout>
diff --git a/tests/tests/hardware/res/layout/surface_view.xml b/tests/tests/hardware/res/layout/surface_view.xml
new file mode 100644
index 0000000..8ba939b
--- /dev/null
+++ b/tests/tests/hardware/res/layout/surface_view.xml
@@ -0,0 +1,27 @@
+<?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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <SurfaceView
+        android:id="@+id/surface_view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"/>
+
+</LinearLayout>
diff --git a/tests/tests/hardware/res/layout/surface_view_2.xml b/tests/tests/hardware/res/layout/surface_view_2.xml
new file mode 100644
index 0000000..fe53c71
--- /dev/null
+++ b/tests/tests/hardware/res/layout/surface_view_2.xml
@@ -0,0 +1,28 @@
+<?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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <SurfaceView
+        android:id="@+id/surface_view"
+        android:layout_width="320dp"
+        android:layout_height="240dp"/>
+
+</LinearLayout>
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/AllocationTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/AllocationTest.java
new file mode 100644
index 0000000..92a5e58
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/AllocationTest.java
@@ -0,0 +1,860 @@
+/*
+ * 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 static android.graphics.ImageFormat.YUV_420_888;
+import static android.hardware.camera2.cts.helpers.Preconditions.*;
+import static android.hardware.camera2.cts.helpers.AssertHelpers.*;
+import static android.hardware.camera2.cts.CameraTestUtils.*;
+import static com.android.ex.camera2.blocking.BlockingStateCallback.*;
+
+import android.content.Context;
+import android.graphics.ImageFormat;
+import android.graphics.RectF;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.CameraMetadata;
+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;
+import android.hardware.camera2.cts.rs.RenderScriptSingleton;
+import android.hardware.camera2.cts.rs.ScriptGraph;
+import android.hardware.camera2.cts.rs.ScriptYuvCrop;
+import android.hardware.camera2.cts.rs.ScriptYuvMeans1d;
+import android.hardware.camera2.cts.rs.ScriptYuvMeans2dTo1d;
+import android.hardware.camera2.cts.rs.ScriptYuvToRgb;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.renderscript.Allocation;
+import android.renderscript.Script.LaunchOptions;
+import android.test.AndroidTestCase;
+import android.util.Log;
+import android.util.Rational;
+import android.view.Surface;
+
+import com.android.ex.camera2.blocking.BlockingCameraManager.BlockingOpenException;
+import com.android.ex.camera2.blocking.BlockingStateCallback;
+import com.android.ex.camera2.blocking.BlockingSessionCallback;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Suite of tests for camera2 -> RenderScript APIs.
+ *
+ * <p>It uses CameraDevice as producer, camera sends the data to the surface provided by
+ * Allocation. Only the below format is tested:</p>
+ *
+ * <p>YUV_420_888: flexible YUV420, it is a mandatory format for camera.</p>
+ */
+public class AllocationTest extends AndroidTestCase {
+    private static final String TAG = "AllocationTest";
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+
+    private CameraManager mCameraManager;
+    private CameraDevice mCamera;
+    private CameraCaptureSession mSession;
+    private BlockingStateCallback mCameraListener;
+    private BlockingSessionCallback mSessionListener;
+
+    private String[] mCameraIds;
+
+    private Handler mHandler;
+    private HandlerThread mHandlerThread;
+
+    private CameraIterable mCameraIterable;
+    private SizeIterable mSizeIterable;
+    private ResultIterable mResultIterable;
+
+    @Override
+    public synchronized void setContext(Context context) {
+        super.setContext(context);
+        mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
+        assertNotNull("Can't connect to camera manager!", mCameraManager);
+
+        RenderScriptSingleton.setContext(context);
+        // TODO: call clearContext
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mCameraIds = mCameraManager.getCameraIdList();
+        mHandlerThread = new HandlerThread("AllocationTest");
+        mHandlerThread.start();
+        mHandler = new Handler(mHandlerThread.getLooper());
+        mCameraListener = new BlockingStateCallback();
+
+        mCameraIterable = new CameraIterable();
+        mSizeIterable = new SizeIterable();
+        mResultIterable = new ResultIterable();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        MaybeNull.close(mCamera);
+
+        // TODO: Clean up RenderScript context in a static test run finished method.
+        // Or alternatively count the # of test methods that are in this test,
+        // once we reach that count, it's time to call the last tear down
+
+        mHandlerThread.quitSafely();
+        mHandler = null;
+        super.tearDown();
+    }
+
+    /**
+     * Update the request with a default manual request template.
+     *
+     * @param request A builder for a CaptureRequest
+     * @param sensitivity ISO gain units (e.g. 100)
+     * @param expTimeNs Exposure time in nanoseconds
+     */
+    private static void setManualCaptureRequest(CaptureRequest.Builder request, int sensitivity,
+            long expTimeNs) {
+        final Rational ONE = new Rational(1, 1);
+        final Rational ZERO = new Rational(0, 1);
+
+        if (VERBOSE) {
+            Log.v(TAG, String.format("Create manual capture request, sensitivity = %d, expTime = %f",
+                    sensitivity, expTimeNs / (1000.0 * 1000)));
+        }
+
+        request.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_OFF);
+        request.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
+        request.set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest.CONTROL_AWB_MODE_OFF);
+        request.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF);
+        request.set(CaptureRequest.CONTROL_EFFECT_MODE, CaptureRequest.CONTROL_EFFECT_MODE_OFF);
+        request.set(CaptureRequest.SENSOR_FRAME_DURATION, 0L);
+        request.set(CaptureRequest.SENSOR_SENSITIVITY, sensitivity);
+        request.set(CaptureRequest.SENSOR_EXPOSURE_TIME, expTimeNs);
+        request.set(CaptureRequest.COLOR_CORRECTION_MODE,
+                CaptureRequest.COLOR_CORRECTION_MODE_TRANSFORM_MATRIX);
+
+        // Identity transform
+        request.set(CaptureRequest.COLOR_CORRECTION_TRANSFORM,
+            new ColorSpaceTransform(new Rational[] {
+                ONE, ZERO, ZERO,
+                ZERO, ONE, ZERO,
+                ZERO, ZERO, ONE
+            }));
+
+        // Identity gains
+        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);
+    }
+
+    /**
+     * Calculate the absolute crop window from a {@link Size},
+     * and configure {@link LaunchOptions} for it.
+     */
+    // TODO: split patch crop window and the application against a particular size into 2 classes
+    public static class Patch {
+        /**
+         * Create a new {@link Patch} from relative crop coordinates.
+         *
+         * <p>All float values must be normalized coordinates between [0, 1].</p>
+         *
+         * @param size Size of the original rectangle that is being cropped.
+         * @param xNorm The X coordinate defining the left side of the rectangle (in [0, 1]).
+         * @param yNorm The Y coordinate defining the top side of the rectangle (in [0, 1]).
+         * @param wNorm The width of the crop rectangle (normalized between [0, 1]).
+         * @param hNorm The height of the crop rectangle (normalized between [0, 1]).
+         *
+         * @throws NullPointerException if size was {@code null}.
+         * @throws AssertionError if any of the normalized coordinates were out of range
+         */
+        public Patch(Size size, float xNorm, float yNorm, float wNorm, float hNorm) {
+            checkNotNull("size", size);
+
+            assertInRange(xNorm, 0.0f, 1.0f);
+            assertInRange(yNorm, 0.0f, 1.0f);
+            assertInRange(wNorm, 0.0f, 1.0f);
+            assertInRange(hNorm, 0.0f, 1.0f);
+
+            wFull = size.getWidth();
+            hFull = size.getWidth();
+
+            xTile = (int)Math.ceil(xNorm * wFull);
+            yTile = (int)Math.ceil(yNorm * hFull);
+
+            wTile = (int)Math.ceil(wNorm * wFull);
+            hTile = (int)Math.ceil(hNorm * hFull);
+
+            mSourceSize = size;
+        }
+
+        /**
+         * Get the original size used to create this {@link Patch}.
+         *
+         * @return source size
+         */
+        public Size getSourceSize() {
+            return mSourceSize;
+        }
+
+        /**
+         * Get the cropped size after applying the normalized crop window.
+         *
+         * @return cropped size
+         */
+        public Size getSize() {
+            return new Size(wFull, hFull);
+        }
+
+        /**
+         * Get the {@link LaunchOptions} that can be used with a {@link android.renderscript.Script}
+         * to apply a kernel over a subset of an {@link Allocation}.
+         *
+         * @return launch options
+         */
+        public LaunchOptions getLaunchOptions() {
+            return (new LaunchOptions())
+                    .setX(xTile, xTile + wTile)
+                    .setY(yTile, yTile + hTile);
+        }
+
+        /**
+         * Get the cropped width after applying the normalized crop window.
+         *
+         * @return cropped width
+         */
+        public int getWidth() {
+            return wTile;
+        }
+
+        /**
+         * Get the cropped height after applying the normalized crop window.
+         *
+         * @return cropped height
+         */
+        public int getHeight() {
+            return hTile;
+        }
+
+        /**
+         * Convert to a {@link RectF} where each corner is represented by a
+         * normalized coordinate in between [0.0, 1.0] inclusive.
+         *
+         * @return a new rectangle
+         */
+        public RectF toRectF() {
+            return new RectF(
+                    xTile * 1.0f / wFull,
+                    yTile * 1.0f / hFull,
+                    (xTile + wTile) * 1.0f / wFull,
+                    (yTile + hTile) * 1.0f / hFull);
+        }
+
+        private final Size mSourceSize;
+        private final int wFull;
+        private final int hFull;
+        private final int xTile;
+        private final int yTile;
+        private final int wTile;
+        private final int hTile;
+    }
+
+    /**
+     * Convert a single YUV pixel (3 byte elements) to an RGB pixel.
+     *
+     * <p>The color channels must be in the following order:
+     * <ul><li>Y - 0th channel
+     * <li>U - 1st channel
+     * <li>V - 2nd channel
+     * </ul></p>
+     *
+     * <p>Each channel has data in the range 0-255.</p>
+     *
+     * <p>Output data is a 3-element pixel with each channel in the range of [0,1].
+     * Each channel is saturated to avoid over/underflow.</p>
+     *
+     * <p>The conversion is done using JFIF File Interchange Format's "Conversion to and from RGB":
+     * <ul>
+     * <li>R = Y + 1.042 (Cr - 128)
+     * <li>G = Y - 0.34414 (Cb - 128) - 0.71414 (Cr - 128)
+     * <li>B = Y + 1.772 (Cb - 128)
+     * </ul>
+     *
+     * Where Cr and Cb are aliases of V and U respectively.
+     * </p>
+     *
+     * @param yuvData An array of a YUV pixel (at least 3 bytes large)
+     *
+     * @return an RGB888 pixel with each channel in the range of [0,1]
+     */
+    private static float[] convertPixelYuvToRgb(byte[] yuvData) {
+        final int CHANNELS = 3; // yuv
+        final float COLOR_RANGE = 256f;
+
+        assertTrue("YUV pixel must be at least 3 bytes large", CHANNELS <= yuvData.length);
+
+        float[] rgb = new float[CHANNELS];
+
+        float y = yuvData[0] & 0xFF;  // Y channel
+        float cb = yuvData[1] & 0xFF; // U channel
+        float cr = yuvData[2] & 0xFF; // V channel
+
+        // convert YUV -> RGB (from JFIF's "Conversion to and from RGB" section)
+        float r = y + 1.402f * (cr - 128);
+        float g = y - 0.34414f * (cb - 128) - 0.71414f * (cr - 128);
+        float b = y + 1.772f * (cb - 128);
+
+        // normalize [0,255] -> [0,1]
+        rgb[0] = r / COLOR_RANGE;
+        rgb[1] = g / COLOR_RANGE;
+        rgb[2] = b / COLOR_RANGE;
+
+        // Clamp to range [0,1]
+        for (int i = 0; i < CHANNELS; ++i) {
+            rgb[i] = Math.max(0.0f, Math.min(1.0f, rgb[i]));
+        }
+
+        if (VERBOSE) {
+            Log.v(TAG, String.format("RGB calculated (r,g,b) = (%f, %f, %f)", rgb[0], rgb[1],
+                    rgb[2]));
+        }
+
+        return rgb;
+    }
+
+    /**
+     * Configure the camera with the target surface;
+     * create a capture request builder with {@code cameraTarget} as the sole surface target.
+     *
+     * <p>Outputs are configured with the new surface targets, and this function blocks until
+     * the camera has finished configuring.</p>
+     *
+     * <p>The capture request is created from the {@link CameraDevice#TEMPLATE_PREVIEW} template.
+     * No other keys are set.
+     * </p>
+     */
+    private CaptureRequest.Builder configureAndCreateRequestForSurface(Surface cameraTarget)
+            throws CameraAccessException {
+        List<Surface> outputSurfaces = new ArrayList<Surface>(/*capacity*/1);
+        assertNotNull("Failed to get Surface", cameraTarget);
+        outputSurfaces.add(cameraTarget);
+
+        mSessionListener = new BlockingSessionCallback();
+        mCamera.createCaptureSession(outputSurfaces, mSessionListener, mHandler);
+        mSession = mSessionListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
+        CaptureRequest.Builder captureBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        assertNotNull("Fail to create captureRequest", captureBuilder);
+        captureBuilder.addTarget(cameraTarget);
+
+        if (VERBOSE) Log.v(TAG, "configureAndCreateRequestForSurface - done");
+
+        return captureBuilder;
+    }
+
+    /**
+     * Submit a single request to the camera, block until the buffer is available.
+     *
+     * <p>Upon return from this function, script has been executed against the latest buffer.
+     * </p>
+     */
+    private void captureSingleShotAndExecute(CaptureRequest request, ScriptGraph graph)
+            throws CameraAccessException {
+        checkNotNull("request", request);
+        checkNotNull("graph", graph);
+
+        mSession.capture(request, new CameraCaptureSession.CaptureCallback() {
+            @Override
+            public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
+                    TotalCaptureResult result) {
+                if (VERBOSE) Log.v(TAG, "Capture completed");
+            }
+        }, mHandler);
+
+        if (VERBOSE) Log.v(TAG, "Waiting for single shot buffer");
+        graph.advanceInputWaiting();
+        if (VERBOSE) Log.v(TAG, "Got the buffer");
+        graph.execute();
+    }
+
+    private void stopCapture() throws CameraAccessException {
+        if (VERBOSE) Log.v(TAG, "Stopping capture and waiting for idle");
+        // Stop repeat, wait for captures to complete, and disconnect from surfaces
+        mSession.close();
+        mSessionListener.getStateWaiter().waitForState(BlockingSessionCallback.SESSION_CLOSED,
+                SESSION_CLOSE_TIMEOUT_MS);
+        mSession = null;
+        mSessionListener = null;
+    }
+
+    /**
+     * Extremely dumb validator. Makes sure there is at least one non-zero RGB pixel value.
+     */
+    private void validateInputOutputNotZeroes(ScriptGraph scriptGraph, Size size) {
+        final int BPP = 8; // bits per pixel
+
+        int width = size.getWidth();
+        int height = size.getHeight();
+        /**
+         * Check the input allocation is sane.
+         * - Byte size matches what we expect.
+         * - The input is not all zeroes.
+         */
+
+        // Check that input data was updated first. If it wasn't, the rest of the test will fail.
+        byte[] data = scriptGraph.getInputData();
+        assertArrayNotAllZeroes("Input allocation data was not updated", data);
+
+        // Minimal required size to represent YUV 4:2:0 image
+        int packedSize =
+                width * height * ImageFormat.getBitsPerPixel(YUV_420_888) / BPP;
+        if (VERBOSE) Log.v(TAG, "Expected image size = " + packedSize);
+        int actualSize = data.length;
+        // Actual size may be larger due to strides or planes being non-contiguous
+        assertTrue(
+                String.format(
+                        "YUV 420 packed size (%d) should be at least as large as the actual size " +
+                        "(%d)", packedSize, actualSize), packedSize <= actualSize);
+        /**
+         * Check the output allocation by converting to RGBA.
+         * - Byte size matches what we expect
+         * - The output is not all zeroes
+         */
+        final int RGBA_CHANNELS = 4;
+
+        int actualSizeOut = scriptGraph.getOutputAllocation().getBytesSize();
+        int packedSizeOut = width * height * RGBA_CHANNELS;
+
+        byte[] dataOut = scriptGraph.getOutputData();
+        assertEquals("RGB mismatched byte[] and expected size",
+                packedSizeOut, dataOut.length);
+
+        if (VERBOSE) {
+            Log.v(TAG, "checkAllocationByConvertingToRgba - RGB data size " + dataOut.length);
+        }
+
+        assertArrayNotAllZeroes("RGBA data was not updated", dataOut);
+        // RGBA8888 stride should be equal to the width
+        assertEquals("RGBA 8888 mismatched byte[] and expected size", packedSizeOut, actualSizeOut);
+
+        if (VERBOSE) Log.v(TAG, "validating Buffer , size = " + actualSize);
+    }
+
+    public void testAllocationFromCameraFlexibleYuv() throws Exception {
+
+        /** number of frame (for streaming requests) to be verified. */
+        final int NUM_FRAME_VERIFIED = 1;
+
+        mCameraIterable.forEachCamera(new CameraBlock() {
+            @Override
+            public void run(CameraDevice camera) throws CameraAccessException {
+
+                // Iterate over each size in the camera
+                mSizeIterable.forEachSize(YUV_420_888, new SizeBlock() {
+                    @Override
+                    public void run(final Size size) throws CameraAccessException {
+                        // Create a script graph that converts YUV to RGB
+                        final ScriptGraph scriptGraph = ScriptGraph.create()
+                                .configureInputWithSurface(size, YUV_420_888)
+                                .chainScript(ScriptYuvToRgb.class)
+                                .buildGraph();
+
+                        if (VERBOSE) Log.v(TAG, "Prepared ScriptYuvToRgb for size " + size);
+
+                        // Run the graph against camera input and validate we get some input
+                        try {
+                            CaptureRequest request =
+                                    configureAndCreateRequestForSurface(scriptGraph.getInputSurface()).build();
+
+                            // Block until we get 1 result, then iterate over the result
+                            mResultIterable.forEachResultRepeating(
+                                    request, NUM_FRAME_VERIFIED, new ResultBlock() {
+                                @Override
+                                public void run(CaptureResult result) throws CameraAccessException {
+                                    scriptGraph.advanceInputWaiting();
+                                    scriptGraph.execute();
+                                    validateInputOutputNotZeroes(scriptGraph, size);
+                                    scriptGraph.advanceInputAndDrop();
+                                }
+                            });
+
+                            stopCapture();
+                        } finally {
+                            scriptGraph.close();
+                        }
+                    }
+                });
+            }
+        });
+    }
+
+    /**
+     * Take two shots and ensure per-frame-control with exposure/gain is working correctly.
+     *
+     * <p>Takes a shot with very low ISO and exposure time. Expect it to be black.</p>
+     *
+     * <p>Take a shot with very high ISO and exposure time. Expect it to be white.</p>
+     *
+     * @throws Exception
+     */
+    public void testBlackWhite() throws CameraAccessException {
+
+        /** low iso + low exposure (first shot) */
+        final float THRESHOLD_LOW = 0.025f;
+        /** high iso + high exposure (second shot) */
+        final float THRESHOLD_HIGH = 0.975f;
+
+        mCameraIterable.forEachCamera(/*fullHwLevel*/false, new CameraBlock() {
+            @Override
+            public void run(CameraDevice camera) throws CameraAccessException {
+                final StaticMetadata staticInfo =
+                        new StaticMetadata(mCameraManager.getCameraCharacteristics(camera.getId()));
+
+                // This test requires PFC and manual sensor control
+                if (!staticInfo.isCapabilitySupported(
+                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR) ||
+                        !staticInfo.isPerFrameControlSupported()) {
+                    return;
+                }
+
+                final Size maxSize = getMaxSize(
+                        getSupportedSizeForFormat(YUV_420_888, camera.getId(), mCameraManager));
+
+                ScriptGraph scriptGraph = createGraphForYuvCroppedMeans(maxSize);
+
+                CaptureRequest.Builder req =
+                        configureAndCreateRequestForSurface(scriptGraph.getInputSurface());
+
+                // Take a shot with very low ISO and exposure time. Expect it to be black.
+                int minimumSensitivity = staticInfo.getSensitivityMinimumOrDefault();
+                long minimumExposure = staticInfo.getExposureMinimumOrDefault();
+                setManualCaptureRequest(req, minimumSensitivity, minimumExposure);
+
+                CaptureRequest lowIsoExposureShot = req.build();
+                captureSingleShotAndExecute(lowIsoExposureShot, scriptGraph);
+
+                float[] blackMeans = convertPixelYuvToRgb(scriptGraph.getOutputData());
+
+                // Take a shot with very high ISO and exposure time. Expect it to be white.
+                int maximumSensitivity = staticInfo.getSensitivityMaximumOrDefault();
+                long maximumExposure = staticInfo.getExposureMaximumOrDefault();
+                setManualCaptureRequest(req, maximumSensitivity, maximumExposure);
+
+                CaptureRequest highIsoExposureShot = req.build();
+                captureSingleShotAndExecute(highIsoExposureShot, scriptGraph);
+
+                float[] whiteMeans = convertPixelYuvToRgb(scriptGraph.getOutputData());
+
+                // low iso + low exposure (first shot)
+                assertArrayWithinUpperBound("Black means too high", blackMeans, THRESHOLD_LOW);
+
+                // high iso + high exposure (second shot)
+                assertArrayWithinLowerBound("White means too low", whiteMeans, THRESHOLD_HIGH);
+            }
+        });
+    }
+
+    /**
+     * Test that the android.sensitivity.parameter is applied.
+     */
+    public void testParamSensitivity() throws CameraAccessException {
+        final float THRESHOLD_MAX_MIN_DIFF = 0.3f;
+        final float THRESHOLD_MAX_MIN_RATIO = 2.0f;
+        final int NUM_STEPS = 5;
+        final long EXPOSURE_TIME_NS = 2000000; // 2 seconds
+        final int RGB_CHANNELS = 3;
+
+        mCameraIterable.forEachCamera(/*fullHwLevel*/false, new CameraBlock() {
+
+
+            @Override
+            public void run(CameraDevice camera) throws CameraAccessException {
+                final StaticMetadata staticInfo =
+                        new StaticMetadata(mCameraManager.getCameraCharacteristics(camera.getId()));
+                // This test requires PFC and manual sensor control
+                if (!staticInfo.isCapabilitySupported(
+                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR) ||
+                        !staticInfo.isPerFrameControlSupported()) {
+                    return;
+                }
+
+                final List<float[]> rgbMeans = new ArrayList<float[]>();
+                final Size maxSize = getMaxSize(
+                        getSupportedSizeForFormat(YUV_420_888, camera.getId(), mCameraManager));
+
+                final int sensitivityMin = staticInfo.getSensitivityMinimumOrDefault();
+                final int sensitivityMax = staticInfo.getSensitivityMaximumOrDefault();
+
+                // List each sensitivity from min-max in NUM_STEPS increments
+                int[] sensitivities = new int[NUM_STEPS];
+                for (int i = 0; i < NUM_STEPS; ++i) {
+                    int delta = (sensitivityMax - sensitivityMin) / (NUM_STEPS - 1);
+                    sensitivities[i] = sensitivityMin + delta * i;
+                }
+
+                ScriptGraph scriptGraph = createGraphForYuvCroppedMeans(maxSize);
+
+                CaptureRequest.Builder req =
+                        configureAndCreateRequestForSurface(scriptGraph.getInputSurface());
+
+                // Take burst shots with increasing sensitivity one after other.
+                for (int i = 0; i < NUM_STEPS; ++i) {
+                    setManualCaptureRequest(req, sensitivities[i], EXPOSURE_TIME_NS);
+                    captureSingleShotAndExecute(req.build(), scriptGraph);
+                    float[] means = convertPixelYuvToRgb(scriptGraph.getOutputData());
+                    rgbMeans.add(means);
+
+                    if (VERBOSE) {
+                        Log.v(TAG, "testParamSensitivity - captured image " + i +
+                                " with RGB means: " + Arrays.toString(means));
+                    }
+                }
+
+                // Test that every consecutive image gets brighter.
+                for (int i = 0; i < rgbMeans.size() - 1; ++i) {
+                    float[] curMeans = rgbMeans.get(i);
+                    float[] nextMeans = rgbMeans.get(i+1);
+
+                    assertArrayNotGreater(
+                            String.format("Shot with sensitivity %d should not have higher " +
+                                    "average means than shot with sensitivity %d",
+                                    sensitivities[i], sensitivities[i+1]),
+                            curMeans, nextMeans);
+                }
+
+                // Test the min-max diff and ratios are within expected thresholds
+                float[] lastMeans = rgbMeans.get(NUM_STEPS - 1);
+                float[] firstMeans = rgbMeans.get(/*location*/0);
+                for (int i = 0; i < RGB_CHANNELS; ++i) {
+                    assertTrue(
+                            String.format("Sensitivity max-min diff too small (max=%f, min=%f)",
+                                    lastMeans[i], firstMeans[i]),
+                            lastMeans[i] - firstMeans[i] > THRESHOLD_MAX_MIN_DIFF);
+                    assertTrue(
+                            String.format("Sensitivity max-min ratio too small (max=%f, min=%f)",
+                                    lastMeans[i], firstMeans[i]),
+                            lastMeans[i] / firstMeans[i] > THRESHOLD_MAX_MIN_RATIO);
+                }
+            }
+        });
+
+    }
+
+    /**
+     * Common script graph for manual-capture based tests that determine the average pixel
+     * values of a cropped sub-region.
+     *
+     * <p>Processing chain:
+     *
+     * <pre>
+     * input:  YUV_420_888 surface
+     * output: mean YUV value of a central section of the image,
+     *         YUV 4:4:4 encoded as U8_3
+     * steps:
+     *      1) crop [0.45,0.45] - [0.55, 0.55]
+     *      2) average columns
+     *      3) average rows
+     * </pre>
+     * </p>
+     */
+    private static ScriptGraph createGraphForYuvCroppedMeans(final Size size) {
+        ScriptGraph scriptGraph = ScriptGraph.create()
+                .configureInputWithSurface(size, YUV_420_888)
+                .configureScript(ScriptYuvCrop.class)
+                    .set(ScriptYuvCrop.CROP_WINDOW,
+                            new Patch(size, /*x*/0.45f, /*y*/0.45f, /*w*/0.1f, /*h*/0.1f).toRectF())
+                    .buildScript()
+                .chainScript(ScriptYuvMeans2dTo1d.class)
+                .chainScript(ScriptYuvMeans1d.class)
+                // TODO: Make a script for YUV 444 -> RGB 888 conversion
+                .buildGraph();
+        return scriptGraph;
+    }
+
+    /*
+     * TODO: Refactor below code into separate classes and to not depend on AllocationTest
+     * inner variables.
+     *
+     * TODO: add javadocs to below methods
+     *
+     * TODO: Figure out if there's some elegant way to compose these forEaches together, so that
+     * the callers don't have to do a ton of nesting
+     */
+
+    interface CameraBlock {
+        void run(CameraDevice camera) throws CameraAccessException;
+    }
+
+    class CameraIterable {
+        public void forEachCamera(CameraBlock runnable)
+                throws CameraAccessException {
+            forEachCamera(/*fullHwLevel*/false, runnable);
+        }
+
+        public void forEachCamera(boolean fullHwLevel, CameraBlock runnable)
+                throws CameraAccessException {
+            assertNotNull("No camera manager", mCameraManager);
+            assertNotNull("No camera IDs", mCameraIds);
+
+            for (int i = 0; i < mCameraIds.length; i++) {
+                // Don't execute the runnable against non-FULL cameras if FULL is required
+                CameraCharacteristics properties =
+                        mCameraManager.getCameraCharacteristics(mCameraIds[i]);
+                StaticMetadata staticInfo = new StaticMetadata(properties);
+                if (fullHwLevel && !staticInfo.isHardwareLevelFull()) {
+                    Log.i(TAG, String.format(
+                            "Skipping this test for camera %s, needs FULL hw level",
+                            mCameraIds[i]));
+                    continue;
+                }
+
+                // Open camera and execute test
+                Log.i(TAG, "Testing Camera " + mCameraIds[i]);
+                try {
+                    openDevice(mCameraIds[i]);
+
+                    runnable.run(mCamera);
+                } finally {
+                    closeDevice(mCameraIds[i]);
+                }
+            }
+        }
+
+        private void openDevice(String cameraId) {
+            if (mCamera != null) {
+                throw new IllegalStateException("Already have open camera device");
+            }
+            try {
+                mCamera = openCamera(
+                    mCameraManager, cameraId, mCameraListener, mHandler);
+            } catch (CameraAccessException e) {
+                fail("Fail to open camera synchronously, " + Log.getStackTraceString(e));
+            } catch (BlockingOpenException e) {
+                fail("Fail to open camera asynchronously, " + Log.getStackTraceString(e));
+            }
+            mCameraListener.waitForState(STATE_OPENED, CAMERA_OPEN_TIMEOUT_MS);
+        }
+
+        private void closeDevice(String cameraId) {
+            if (mCamera != null) {
+                mCamera.close();
+                mCameraListener.waitForState(STATE_CLOSED, CAMERA_CLOSE_TIMEOUT_MS);
+                mCamera = null;
+            }
+        }
+    }
+
+    interface SizeBlock {
+        void run(Size size) throws CameraAccessException;
+    }
+
+    class SizeIterable {
+        public void forEachSize(int format, SizeBlock runnable) throws CameraAccessException {
+            assertNotNull("No camera opened", mCamera);
+            assertNotNull("No camera manager", mCameraManager);
+
+            CameraCharacteristics properties =
+                    mCameraManager.getCameraCharacteristics(mCamera.getId());
+
+            assertNotNull("Can't get camera properties!", properties);
+
+            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(availableOutputFormats),
+                    Arrays.binarySearch(availableOutputFormats, format) >= 0);
+
+            Size[] availableSizes = getSupportedSizeForFormat(format, mCamera.getId(),
+                    mCameraManager);
+            assertArrayNotEmpty(availableSizes, "availableSizes should not be empty");
+
+            for (Size size : availableSizes) {
+
+                if (VERBOSE) {
+                    Log.v(TAG, "Testing size " + size.toString() +
+                            " for camera " + mCamera.getId());
+                }
+                runnable.run(size);
+            }
+        }
+    }
+
+    interface ResultBlock {
+        void run(CaptureResult result) throws CameraAccessException;
+    }
+
+    class ResultIterable {
+        public void forEachResultOnce(CaptureRequest request, ResultBlock block)
+                throws CameraAccessException {
+            forEachResult(request, /*count*/1, /*repeating*/false, block);
+        }
+
+        public void forEachResultRepeating(CaptureRequest request, int count, ResultBlock block)
+                throws CameraAccessException {
+            forEachResult(request, count, /*repeating*/true, block);
+        }
+
+        public void forEachResult(CaptureRequest request, int count, boolean repeating,
+                ResultBlock block) throws CameraAccessException {
+
+            // TODO: start capture, i.e. configureOutputs
+
+            SimpleCaptureCallback listener = new SimpleCaptureCallback();
+
+            if (!repeating) {
+                for (int i = 0; i < count; ++i) {
+                    mSession.capture(request, listener, mHandler);
+                }
+            } else {
+                mSession.setRepeatingRequest(request, listener, mHandler);
+            }
+
+            // Assume that the device is already IDLE.
+            mSessionListener.getStateWaiter().waitForState(BlockingSessionCallback.SESSION_ACTIVE,
+                    CAMERA_ACTIVE_TIMEOUT_MS);
+
+            for (int i = 0; i < count; ++i) {
+                if (VERBOSE) {
+                    Log.v(TAG, String.format("Testing with result %d of %d for camera %s",
+                            i, count, mCamera.getId()));
+                }
+
+                CaptureResult result = listener.getCaptureResult(CAPTURE_RESULT_TIMEOUT_MS);
+                block.run(result);
+            }
+
+            if (repeating) {
+                mSession.stopRepeating();
+                mSessionListener.getStateWaiter().waitForState(
+                    BlockingSessionCallback.SESSION_READY, CAMERA_IDLE_TIMEOUT_MS);
+            }
+
+            // TODO: Make a Configure decorator or some such for configureOutputs
+        }
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/Camera2MultiViewCtsActivity.java b/tests/tests/hardware/src/android/hardware/camera2/cts/Camera2MultiViewCtsActivity.java
new file mode 100644
index 0000000..16d2301
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/Camera2MultiViewCtsActivity.java
@@ -0,0 +1,59 @@
+/*
+ * 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.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.SurfaceView;
+import android.view.TextureView;
+import android.view.WindowManager;
+
+import com.android.cts.hardware.R;
+
+public class Camera2MultiViewCtsActivity extends Activity {
+    private final static String TAG = "Camera2MultiViewCtsActivity";
+    private TextureView[] mTextureView = new TextureView[2];
+    private SurfaceView[] mSurfaceView = new SurfaceView[2];
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.multi_view);
+        mTextureView[0] = (TextureView) findViewById(R.id.texture_view_1);
+        mTextureView[1] = (TextureView) findViewById(R.id.texture_view_2);
+        mSurfaceView[0] = (SurfaceView) findViewById(R.id.surface_view_1);
+        mSurfaceView[1] = (SurfaceView) findViewById(R.id.surface_view_2);
+
+        //Make sure screen is on when this activity window is visible to the user.
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+    }
+
+    public TextureView getTextureView(int index) {
+        if (index < 0 || index > 1) {
+            throw new IllegalArgumentException("Texture view index must be 0 or 1");
+        }
+        return mTextureView[index];
+    }
+
+    public SurfaceView getSurfaceView(int index) {
+        if (index < 0 || index > 1) {
+            throw new IllegalArgumentException("Surface view index must be 0 or 1");
+        }
+        return mSurfaceView[index];
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/Camera2SurfaceViewCtsActivity.java b/tests/tests/hardware/src/android/hardware/camera2/cts/Camera2SurfaceViewCtsActivity.java
new file mode 100644
index 0000000..936883e
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/Camera2SurfaceViewCtsActivity.java
@@ -0,0 +1,97 @@
+/*
+ * 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.app.Activity;
+import android.os.Bundle;
+import android.os.ConditionVariable;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import com.android.cts.hardware.R;
+
+public class Camera2SurfaceViewCtsActivity extends Activity implements SurfaceHolder.Callback {
+    private final static String TAG = "Camera2SurfaceViewCtsActivity";
+    private final ConditionVariable surfaceChangedDone = new ConditionVariable();
+
+    private SurfaceView mSurfaceView;
+    private int currentWidth = 0;
+    private int currentHeight = 0;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.surface_view_2);
+        mSurfaceView = (SurfaceView) findViewById(R.id.surface_view);
+        mSurfaceView.getHolder().addCallback(this);
+    }
+
+    public SurfaceView getSurfaceView() {
+        return mSurfaceView;
+    }
+
+    public boolean waitForSurfaceSizeChanged(int timeOutMs, int expectWidth, int expectHeight) {
+        if (timeOutMs <= 0 || expectWidth <= 0 || expectHeight <= 0) {
+            throw new IllegalArgumentException(
+                    String.format(
+                            "timeout(%d), expectWidth(%d), and expectHeight(%d) " +
+                            "should all be positive numbers",
+                            timeOutMs, expectWidth, expectHeight));
+        }
+
+        int waitTimeMs = timeOutMs;
+        boolean changeSucceeded = false;
+        while (!changeSucceeded && waitTimeMs > 0) {
+            long startTimeMs = System.currentTimeMillis();
+            changeSucceeded = surfaceChangedDone.block(waitTimeMs);
+            if (!changeSucceeded) {
+                Log.e(TAG, "Wait for surface change timed out after " + timeOutMs + " ms");
+                return changeSucceeded;
+            } else {
+                // Get a surface change callback, need to check if the size is expected.
+                surfaceChangedDone.close();
+                if (currentWidth == expectWidth && currentHeight == expectHeight) {
+                    return changeSucceeded;
+                }
+                // Do a further iteration surface change check as surfaceChanged could be called
+                // again.
+                changeSucceeded = false;
+            }
+            waitTimeMs -= (System.currentTimeMillis() - startTimeMs);
+        }
+
+        // Couldn't get expected surface size change.
+        return false;
+     }
+
+    @Override
+    public void surfaceCreated(SurfaceHolder holder) {
+    }
+
+    @Override
+    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+        Log.i(TAG, "Surface Changed to: " + width + "x" + height);
+        currentWidth = width;
+        currentHeight = height;
+        surfaceChangedDone.open();
+    }
+
+    @Override
+    public void surfaceDestroyed(SurfaceHolder holder) {
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraCaptureResultTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraCaptureResultTest.java
deleted file mode 100644
index 6a708e3..0000000
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraCaptureResultTest.java
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * Copyright 2013 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.content.Context;
-import android.graphics.ImageFormat;
-import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.CameraDevice;
-import android.hardware.camera2.CameraManager;
-import android.hardware.camera2.CameraMetadata;
-import android.hardware.camera2.CaptureFailure;
-import android.hardware.camera2.CaptureRequest;
-import android.hardware.camera2.CaptureResult;
-import android.hardware.camera2.Size;
-import static android.hardware.camera2.cts.CameraTestUtils.*;
-import android.media.ImageReader;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.test.AndroidTestCase;
-import android.util.Log;
-import android.view.Surface;
-
-import com.android.ex.camera2.blocking.BlockingStateListener;
-import static com.android.ex.camera2.blocking.BlockingStateListener.*;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
-
-public class CameraCaptureResultTest extends AndroidTestCase {
-    private static final String TAG = "CameraCaptureResultTest";
-    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
-
-    private CameraManager mCameraManager;
-    private HandlerThread mHandlerThread;
-    private Handler mHandler;
-    private ImageReader mImageReader;
-    private Surface mSurface;
-    private BlockingStateListener mCameraListener;
-
-    private static final int MAX_NUM_IMAGES = 5;
-    private static final int NUM_FRAMES_VERIFIED = 300;
-    private static final long WAIT_FOR_RESULT_TIMEOUT_MS = 3000;
-
-    // List that includes all public keys from CaptureResult
-    List<CameraMetadata.Key<?>> mAllKeys;
-
-    // List tracking the failed test keys.
-    List<CameraMetadata.Key<?>> mFailedKeys = new ArrayList<CameraMetadata.Key<?>>();
-
-    @Override
-    public void setContext(Context context) {
-        mAllKeys = getAllCaptureResultKeys();
-        super.setContext(context);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
-        assertNotNull("Can't connect to camera manager", mCameraManager);
-        mHandlerThread = new HandlerThread(TAG);
-        mHandlerThread.start();
-        mHandler = new Handler(mHandlerThread.getLooper());
-        mCameraListener = new BlockingStateListener();
-        mFailedKeys.clear();
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        mHandlerThread.quitSafely();
-        super.tearDown();
-    }
-
-    public void testCameraCaptureResultAllKeys() throws Exception {
-        /**
-         * Hardcode a key waiver list for the keys we want to skip the sanity check.
-         * FIXME: We need get ride of this list, see bug 11116270.
-         */
-        List<CameraMetadata.Key<?>> waiverkeys = new ArrayList<CameraMetadata.Key<?>>();
-        waiverkeys.add(CaptureResult.EDGE_MODE);
-        waiverkeys.add(CaptureResult.JPEG_GPS_COORDINATES);
-        waiverkeys.add(CaptureResult.JPEG_GPS_PROCESSING_METHOD);
-        waiverkeys.add(CaptureResult.JPEG_GPS_TIMESTAMP);
-        waiverkeys.add(CaptureResult.JPEG_ORIENTATION);
-        waiverkeys.add(CaptureResult.JPEG_QUALITY);
-        waiverkeys.add(CaptureResult.JPEG_THUMBNAIL_QUALITY);
-        waiverkeys.add(CaptureResult.JPEG_THUMBNAIL_SIZE);
-        waiverkeys.add(CaptureResult.SENSOR_TEMPERATURE);
-        waiverkeys.add(CaptureResult.TONEMAP_CURVE_BLUE);
-        waiverkeys.add(CaptureResult.TONEMAP_CURVE_GREEN);
-        waiverkeys.add(CaptureResult.TONEMAP_CURVE_RED);
-        waiverkeys.add(CaptureResult.TONEMAP_MODE);
-        waiverkeys.add(CaptureResult.STATISTICS_PREDICTED_COLOR_GAINS);
-        waiverkeys.add(CaptureResult.STATISTICS_PREDICTED_COLOR_TRANSFORM);
-        waiverkeys.add(CaptureResult.STATISTICS_SCENE_FLICKER);
-
-        String[] ids = mCameraManager.getCameraIdList();
-        for (int i = 0; i < ids.length; i++) {
-            CameraCharacteristics props = mCameraManager.getCameraCharacteristics(ids[i]);
-            assertNotNull("CameraCharacteristics shouldn't be null", props);
-            Integer hwLevel = props.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
-            if (hwLevel != CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL) {
-                continue;
-            }
-            // TODO: check for LIMITED keys
-
-            CameraDevice camera = null;
-            try {
-                Size[] sizes = CameraTestUtils.getSupportedSizeForFormat(
-                        ImageFormat.YUV_420_888, ids[i], mCameraManager);
-                CameraTestUtils.assertArrayNotEmpty(sizes, "Available sizes shouldn't be empty");
-                createDefaultSurface(sizes[0]);
-
-                if (VERBOSE) {
-                    Log.v(TAG, "Testing camera " + ids[i] + "for size " + sizes[0].toString());
-                }
-
-                camera = CameraTestUtils.openCamera(
-                        mCameraManager, ids[i], mCameraListener, mHandler);
-                assertNotNull(
-                        String.format("Failed to open camera device %s", ids[i]), camera);
-                mCameraListener.waitForState(STATE_UNCONFIGURED, CAMERA_OPEN_TIMEOUT_MS);
-
-                List<Surface> outputSurfaces = new ArrayList<Surface>(1);
-                outputSurfaces.add(mSurface);
-                camera.configureOutputs(outputSurfaces);
-                mCameraListener.waitForState(STATE_BUSY, CAMERA_BUSY_TIMEOUT_MS);
-                mCameraListener.waitForState(STATE_IDLE, CAMERA_IDLE_TIMEOUT_MS);
-
-                CaptureRequest.Builder requestBuilder =
-                        camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
-                assertNotNull("Failed to create capture request", requestBuilder);
-                requestBuilder.addTarget(mSurface);
-
-                // Enable face detection if supported
-                byte[] faceModes = props.get(
-                        CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES);
-                assertNotNull("Available face detection modes shouldn't be null", faceModes);
-                for (int m = 0; m < faceModes.length; m++) {
-                    if (faceModes[m] == CameraMetadata.STATISTICS_FACE_DETECT_MODE_FULL) {
-                        if (VERBOSE) {
-                            Log.v(TAG, "testCameraCaptureResultAllKeys - " +
-                                    "setting facedetection mode to full");
-                        }
-                        requestBuilder.set(CaptureRequest.STATISTICS_FACE_DETECT_MODE,
-                                (int)faceModes[m]);
-                    }
-                }
-
-                // Enable lensShading mode, it should be supported by full mode device.
-                requestBuilder.set(CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE,
-                        CameraMetadata.STATISTICS_LENS_SHADING_MAP_MODE_ON);
-
-                SimpleCaptureListener captureListener = new SimpleCaptureListener();
-                camera.setRepeatingRequest(requestBuilder.build(), captureListener, mHandler);
-
-                for (int m = 0; m < NUM_FRAMES_VERIFIED; m++) {
-                    if(VERBOSE) {
-                        Log.v(TAG, "Testing frame " + m);
-                    }
-                    validateCaptureResult(
-                            captureListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS),
-                            waiverkeys);
-                }
-
-                // Stop repeat, wait for captures to complete, and disconnect from surfaces
-                camera.configureOutputs(/*outputs*/ null);
-                mCameraListener.waitForState(STATE_BUSY, CAMERA_BUSY_TIMEOUT_MS);
-                mCameraListener.waitForState(STATE_UNCONFIGURED, CAMERA_IDLE_TIMEOUT_MS);
-                // Camera has disconnected, clear out the reader
-                mSurface.release();
-                mImageReader.close();
-            } finally {
-                if (camera != null) {
-                    camera.close();
-                }
-            }
-
-        }
-    }
-
-    private void validateCaptureResult(CaptureResult result,
-            List<CameraMetadata.Key<?>> skippedKeys) throws Exception {
-        for (CameraMetadata.Key<?> key : mAllKeys) {
-            if (!skippedKeys.contains(key) && result.get(key) == null) {
-                mFailedKeys.add(key);
-            }
-        }
-
-        StringBuffer failedKeyNames = new StringBuffer("Below Keys have null values:\n");
-        for (CameraMetadata.Key<?> key : mFailedKeys) {
-            failedKeyNames.append(key.getName() + "\n");
-        }
-
-        assertTrue("Some keys have null values, " + failedKeyNames.toString(),
-                mFailedKeys.isEmpty());
-    }
-
-    private static class SimpleCaptureListener extends CameraDevice.CaptureListener {
-        LinkedBlockingQueue<CaptureResult> mQueue = new LinkedBlockingQueue<CaptureResult>();
-
-        @Override
-        public void onCaptureStarted(CameraDevice camera, CaptureRequest request, long timestamp)
-        {
-        }
-
-        @Override
-        public void onCaptureCompleted(CameraDevice camera, CaptureRequest request,
-                CaptureResult result) {
-            try {
-                mQueue.put(result);
-            } catch (InterruptedException e) {
-                throw new UnsupportedOperationException(
-                        "Can't handle InterruptedException in onCaptureCompleted");
-            }
-        }
-
-        @Override
-        public void onCaptureFailed(CameraDevice camera, CaptureRequest request,
-                CaptureFailure failure) {
-        }
-
-        @Override
-        public void onCaptureSequenceCompleted(CameraDevice camera, int sequenceId,
-                int frameNumber) {
-        }
-
-        public CaptureResult getCaptureResult(long timeout) throws InterruptedException {
-            CaptureResult result = mQueue.poll(timeout, TimeUnit.MILLISECONDS);
-            assertNotNull("Wait for a capture result timed out in " + timeout + "ms", result);
-            return result;
-        }
-    }
-
-    private void createDefaultSurface(Size sz) {
-        mImageReader =
-                ImageReader.newInstance(sz.getWidth(),
-                        sz.getHeight(),
-                        ImageFormat.YUV_420_888,
-                        MAX_NUM_IMAGES);
-        mImageReader.setOnImageAvailableListener(new ImageDropperListener(), mHandler);
-        mSurface = mImageReader.getSurface();
-    }
-
-    /**
-     * TODO: Use CameraCharacteristics.getAvailableCaptureResultKeys() once we can filter out
-     * @hide keys.
-     *
-     */
-
-    /*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
-     * The key entries below this point are generated from metadata
-     * definitions in /system/media/camera/docs. Do not modify by hand or
-     * modify the comment blocks at the start or end.
-     *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~*/
-
-    private static List<CameraMetadata.Key<?>> getAllCaptureResultKeys() {
-        ArrayList<CameraMetadata.Key<?>> resultKeys = new ArrayList<CameraMetadata.Key<?>>();
-        resultKeys.add(CaptureResult.COLOR_CORRECTION_TRANSFORM);
-        resultKeys.add(CaptureResult.COLOR_CORRECTION_GAINS);
-        resultKeys.add(CaptureResult.CONTROL_AE_REGIONS);
-        resultKeys.add(CaptureResult.CONTROL_AF_MODE);
-        resultKeys.add(CaptureResult.CONTROL_AF_REGIONS);
-        resultKeys.add(CaptureResult.CONTROL_AWB_MODE);
-        resultKeys.add(CaptureResult.CONTROL_AWB_REGIONS);
-        resultKeys.add(CaptureResult.CONTROL_MODE);
-        resultKeys.add(CaptureResult.CONTROL_AE_STATE);
-        resultKeys.add(CaptureResult.CONTROL_AF_STATE);
-        resultKeys.add(CaptureResult.CONTROL_AWB_STATE);
-        resultKeys.add(CaptureResult.EDGE_MODE);
-        resultKeys.add(CaptureResult.FLASH_MODE);
-        resultKeys.add(CaptureResult.FLASH_STATE);
-        resultKeys.add(CaptureResult.JPEG_GPS_COORDINATES);
-        resultKeys.add(CaptureResult.JPEG_GPS_PROCESSING_METHOD);
-        resultKeys.add(CaptureResult.JPEG_GPS_TIMESTAMP);
-        resultKeys.add(CaptureResult.JPEG_ORIENTATION);
-        resultKeys.add(CaptureResult.JPEG_QUALITY);
-        resultKeys.add(CaptureResult.JPEG_THUMBNAIL_QUALITY);
-        resultKeys.add(CaptureResult.JPEG_THUMBNAIL_SIZE);
-        resultKeys.add(CaptureResult.LENS_APERTURE);
-        resultKeys.add(CaptureResult.LENS_FILTER_DENSITY);
-        resultKeys.add(CaptureResult.LENS_FOCAL_LENGTH);
-        resultKeys.add(CaptureResult.LENS_FOCUS_DISTANCE);
-        resultKeys.add(CaptureResult.LENS_OPTICAL_STABILIZATION_MODE);
-        resultKeys.add(CaptureResult.LENS_FOCUS_RANGE);
-        resultKeys.add(CaptureResult.LENS_STATE);
-        resultKeys.add(CaptureResult.NOISE_REDUCTION_MODE);
-        resultKeys.add(CaptureResult.REQUEST_FRAME_COUNT);
-        resultKeys.add(CaptureResult.SCALER_CROP_REGION);
-        resultKeys.add(CaptureResult.SENSOR_EXPOSURE_TIME);
-        resultKeys.add(CaptureResult.SENSOR_FRAME_DURATION);
-        resultKeys.add(CaptureResult.SENSOR_SENSITIVITY);
-        resultKeys.add(CaptureResult.SENSOR_TIMESTAMP);
-        resultKeys.add(CaptureResult.SENSOR_TEMPERATURE);
-        resultKeys.add(CaptureResult.STATISTICS_FACE_DETECT_MODE);
-        resultKeys.add(CaptureResult.STATISTICS_FACE_IDS);
-        resultKeys.add(CaptureResult.STATISTICS_FACE_LANDMARKS);
-        resultKeys.add(CaptureResult.STATISTICS_FACE_RECTANGLES);
-        resultKeys.add(CaptureResult.STATISTICS_FACE_SCORES);
-        resultKeys.add(CaptureResult.STATISTICS_LENS_SHADING_MAP);
-        resultKeys.add(CaptureResult.STATISTICS_PREDICTED_COLOR_GAINS);
-        resultKeys.add(CaptureResult.STATISTICS_PREDICTED_COLOR_TRANSFORM);
-        resultKeys.add(CaptureResult.STATISTICS_SCENE_FLICKER);
-        resultKeys.add(CaptureResult.TONEMAP_CURVE_BLUE);
-        resultKeys.add(CaptureResult.TONEMAP_CURVE_GREEN);
-        resultKeys.add(CaptureResult.TONEMAP_CURVE_RED);
-        resultKeys.add(CaptureResult.TONEMAP_MODE);
-        resultKeys.add(CaptureResult.BLACK_LEVEL_LOCK);
-
-        // Add STATISTICS_FACES key separately here because it is not
-        // defined in metadata xml file.
-        resultKeys.add(CaptureResult.STATISTICS_FACES);
-
-        return resultKeys;
-    }
-
-    /*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
-     * End generated code
-     *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
-}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraCharacteristicsTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraCharacteristicsTest.java
deleted file mode 100644
index 1b892ba..0000000
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraCharacteristicsTest.java
+++ /dev/null
@@ -1,965 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-/**
- * ! Do not edit this file directly !
- *
- * Generated automatically from system/media/camera/docs/CameraCharacteristicsTest.mako.
- * This file contains only the auto-generated CameraCharacteristics CTS tests; it does
- * not contain any additional manual tests, which would be in a separate file.
- */
-
-package android.hardware.camera2.cts;
-
-import android.content.Context;
-import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.CameraManager;
-import android.hardware.camera2.CameraMetadata.Key;
-import android.test.AndroidTestCase;
-import android.util.Log;
-
-import java.util.List;
-
-/**
- * Auto-generated CTS test for CameraCharacteristics fields.
- */
-public class CameraCharacteristicsTest extends AndroidTestCase {
-    private CameraManager mCameraManager;
-    private static final String TAG = "CameraCharacteristicsTest";
-
-    @Override
-    public void setContext(Context context) {
-        super.setContext(context);
-        mCameraManager = (CameraManager)context.getSystemService(Context.CAMERA_SERVICE);
-        assertNotNull("Can't connect to camera manager", mCameraManager);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
-    }
-
-    public void testCameraCharacteristicsAndroidControlAeAvailableAntibandingModes() 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.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));
-                assertTrue("Key not in keys list: android.control.aeAvailableAntibandingModes", allKeys.contains(
-                        CameraCharacteristics.CONTROL_AE_AVAILABLE_ANTIBANDING_MODES));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidControlAeAvailableTargetFpsRanges() 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.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));
-                assertTrue("Key not in keys list: android.control.aeAvailableTargetFpsRanges", allKeys.contains(
-                        CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidControlAeCompensationRange() 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.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));
-                assertTrue("Key not in keys list: android.control.aeCompensationRange", allKeys.contains(
-                        CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidControlAeCompensationStep() 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.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));
-                assertTrue("Key not in keys list: android.control.aeCompensationStep", allKeys.contains(
-                        CameraCharacteristics.CONTROL_AE_COMPENSATION_STEP));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidControlAfAvailableModes() 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.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));
-                assertTrue("Key not in keys list: android.control.afAvailableModes", allKeys.contains(
-                        CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidControlAvailableEffects() 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.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));
-                assertTrue("Key not in keys list: android.control.availableEffects", allKeys.contains(
-                        CameraCharacteristics.CONTROL_AVAILABLE_EFFECTS));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidControlAvailableSceneModes() 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.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));
-                assertTrue("Key not in keys list: android.control.availableSceneModes", allKeys.contains(
-                        CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidControlAvailableVideoStabilizationModes() 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.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));
-                assertTrue("Key not in keys list: android.control.availableVideoStabilizationModes", allKeys.contains(
-                        CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidControlAwbAvailableModes() 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.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));
-                assertTrue("Key not in keys list: android.control.awbAvailableModes", allKeys.contains(
-                        CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidControlMaxRegions() 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.maxRegions",
-                        props.get(CameraCharacteristics.CONTROL_MAX_REGIONS));
-
-                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));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidFlashInfoAvailable() 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.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));
-                assertTrue("Key not in keys list: android.flash.info.available", allKeys.contains(
-                        CameraCharacteristics.FLASH_INFO_AVAILABLE));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidJpegAvailableThumbnailSizes() 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.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));
-                assertTrue("Key not in keys list: android.jpeg.availableThumbnailSizes", allKeys.contains(
-                        CameraCharacteristics.JPEG_AVAILABLE_THUMBNAIL_SIZES));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidLensFacing() 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.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));
-                assertTrue("Key not in keys list: android.lens.facing", allKeys.contains(
-                        CameraCharacteristics.LENS_FACING));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidLensInfoAvailableApertures() 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.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));
-                assertTrue("Key not in keys list: android.lens.info.availableApertures", allKeys.contains(
-                        CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidLensInfoAvailableFilterDensities() 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.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));
-                assertTrue("Key not in keys list: android.lens.info.availableFilterDensities", allKeys.contains(
-                        CameraCharacteristics.LENS_INFO_AVAILABLE_FILTER_DENSITIES));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidLensInfoAvailableFocalLengths() 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.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));
-                assertTrue("Key not in keys list: android.lens.info.availableFocalLengths", allKeys.contains(
-                        CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidLensInfoAvailableOpticalStabilization() 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.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));
-                assertTrue("Key not in keys list: android.lens.info.availableOpticalStabilization", allKeys.contains(
-                        CameraCharacteristics.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidLensInfoHyperfocalDistance() 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.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));
-                assertTrue("Key not in keys list: android.lens.info.hyperfocalDistance", allKeys.contains(
-                        CameraCharacteristics.LENS_INFO_HYPERFOCAL_DISTANCE));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidLensInfoMinimumFocusDistance() 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.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));
-                assertTrue("Key not in keys list: android.lens.info.minimumFocusDistance", allKeys.contains(
-                        CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE));
-
-            }
-
-        }
-    }
-
-    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 testCameraCharacteristicsAndroidRequestMaxNumOutputStreams() 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.maxNumOutputStreams",
-                        props.get(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_STREAMS));
-
-                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));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidScalerAvailableFormats() 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.scaler.availableFormats",
-                        props.get(CameraCharacteristics.SCALER_AVAILABLE_FORMATS));
-
-                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.scaler.availableFormats", allKeys.contains(
-                        CameraCharacteristics.SCALER_AVAILABLE_FORMATS));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidScalerAvailableJpegMinDurations() 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.scaler.availableJpegMinDurations",
-                        props.get(CameraCharacteristics.SCALER_AVAILABLE_JPEG_MIN_DURATIONS));
-
-                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.scaler.availableJpegMinDurations", allKeys.contains(
-                        CameraCharacteristics.SCALER_AVAILABLE_JPEG_MIN_DURATIONS));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidScalerAvailableJpegSizes() 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.scaler.availableJpegSizes",
-                        props.get(CameraCharacteristics.SCALER_AVAILABLE_JPEG_SIZES));
-
-                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.scaler.availableJpegSizes", allKeys.contains(
-                        CameraCharacteristics.SCALER_AVAILABLE_JPEG_SIZES));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidScalerAvailableMaxDigitalZoom() 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.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));
-                assertTrue("Key not in keys list: android.scaler.availableMaxDigitalZoom", allKeys.contains(
-                        CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidScalerAvailableProcessedMinDurations() 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.scaler.availableProcessedMinDurations",
-                        props.get(CameraCharacteristics.SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS));
-
-                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.scaler.availableProcessedMinDurations", allKeys.contains(
-                        CameraCharacteristics.SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidScalerAvailableProcessedSizes() 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.scaler.availableProcessedSizes",
-                        props.get(CameraCharacteristics.SCALER_AVAILABLE_PROCESSED_SIZES));
-
-                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.scaler.availableProcessedSizes", allKeys.contains(
-                        CameraCharacteristics.SCALER_AVAILABLE_PROCESSED_SIZES));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidSensorBaseGainFactor() 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);
-
-            Integer hwLevel = props.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
-            assertNotNull("No hardware level reported! android.info.supportedHardwareLevel",
-                    hwLevel);
-            if (hwLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)
-            {
-
-                assertNotNull("Invalid property: android.sensor.baseGainFactor",
-                        props.get(CameraCharacteristics.SENSOR_BASE_GAIN_FACTOR));
-
-                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.sensor.baseGainFactor", allKeys.contains(
-                        CameraCharacteristics.SENSOR_BASE_GAIN_FACTOR));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidSensorMaxAnalogSensitivity() 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);
-
-            Integer hwLevel = props.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
-            assertNotNull("No hardware level reported! android.info.supportedHardwareLevel",
-                    hwLevel);
-            if (hwLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)
-            {
-
-                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));
-                assertTrue("Key not in keys list: android.sensor.maxAnalogSensitivity", allKeys.contains(
-                        CameraCharacteristics.SENSOR_MAX_ANALOG_SENSITIVITY));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidSensorOrientation() 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.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));
-                assertTrue("Key not in keys list: android.sensor.orientation", allKeys.contains(
-                        CameraCharacteristics.SENSOR_ORIENTATION));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidSensorInfoActiveArraySize() 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.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));
-                assertTrue("Key not in keys list: android.sensor.info.activeArraySize", allKeys.contains(
-                        CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidSensorInfoSensitivityRange() 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.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));
-                assertTrue("Key not in keys list: android.sensor.info.sensitivityRange", allKeys.contains(
-                        CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidSensorInfoExposureTimeRange() 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.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));
-                assertTrue("Key not in keys list: android.sensor.info.exposureTimeRange", allKeys.contains(
-                        CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidSensorInfoMaxFrameDuration() 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.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));
-                assertTrue("Key not in keys list: android.sensor.info.maxFrameDuration", allKeys.contains(
-                        CameraCharacteristics.SENSOR_INFO_MAX_FRAME_DURATION));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidSensorInfoPhysicalSize() 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.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));
-                assertTrue("Key not in keys list: android.sensor.info.physicalSize", allKeys.contains(
-                        CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidStatisticsInfoAvailableFaceDetectModes() 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.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));
-                assertTrue("Key not in keys list: android.statistics.info.availableFaceDetectModes", allKeys.contains(
-                        CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidStatisticsInfoMaxFaceCount() 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.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));
-                assertTrue("Key not in keys list: android.statistics.info.maxFaceCount", allKeys.contains(
-                        CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidTonemapMaxCurvePoints() 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.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));
-                assertTrue("Key not in keys list: android.tonemap.maxCurvePoints", allKeys.contains(
-                        CameraCharacteristics.TONEMAP_MAX_CURVE_POINTS));
-
-            }
-
-        }
-    }
-
-    public void testCameraCharacteristicsAndroidInfoSupportedHardwareLevel() 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.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));
-                assertTrue("Key not in keys list: android.info.supportedHardwareLevel", allKeys.contains(
-                        CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL));
-
-            }
-
-        }
-    }
-}
-
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 f68b10a..9f50b43 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraDeviceTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraDeviceTest.java
@@ -17,88 +17,95 @@
 package android.hardware.camera2.cts;
 
 import static android.hardware.camera2.cts.CameraTestUtils.*;
-import static com.android.ex.camera2.blocking.BlockingStateListener.*;
+import static com.android.ex.camera2.blocking.BlockingStateCallback.*;
+import static com.android.ex.camera2.blocking.BlockingSessionCallback.*;
 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.CameraManager;
-import android.hardware.camera2.CameraMetadata;
 import android.hardware.camera2.CaptureFailure;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.CaptureResult;
-import android.media.Image;
-import android.media.ImageReader;
+import android.hardware.camera2.TotalCaptureResult;
+import android.hardware.camera2.cts.testcases.Camera2AndroidTestCase;
+import android.hardware.camera2.params.MeteringRectangle;
 import android.os.Handler;
 import android.os.SystemClock;
-import android.test.AndroidTestCase;
 import android.util.Log;
+import android.util.Range;
 import android.view.Surface;
 
-import com.android.ex.camera2.blocking.BlockingStateListener;
+import com.android.ex.camera2.blocking.BlockingSessionCallback;
+import com.android.ex.camera2.blocking.BlockingStateCallback;
+import com.android.ex.camera2.utils.StateWaiter;
+
 import org.mockito.ArgumentMatcher;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
 
 /**
  * <p>Basic test for CameraDevice APIs.</p>
  */
-public class CameraDeviceTest extends AndroidTestCase {
+public class CameraDeviceTest extends Camera2AndroidTestCase {
     private static final String TAG = "CameraDeviceTest";
     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
-
-    private CameraManager mCameraManager;
-    private BlockingStateListener mCameraListener;
-    private CameraTestThread mLooperThread;
-    private Handler mCallbackHandler;
-    private int mLatestState = STATE_UNINITIALIZED;
-
-    /**
-     * The error triggered flag starts out as false, and it will flip to true if any errors
-     * are ever caught; it won't be reset to false after that happens. This is due to the
-     * fact that when multiple tests are run back to back (as they are here), it's hard
-     * to associate the asynchronous error with the test that caused it (so we won't even try).
-     */
-    private boolean mErrorTriggered = false;
-    private ImageReader mReader;
-    private CameraTestThread mDummyThread;
-    private Surface mSurface;
-
-    private static final int CAMERA_CONFIGURE_TIMEOUT_MS = 2000;
-    private static final int CAPTURE_WAIT_TIMEOUT_MS = 2000;
     private static final int ERROR_LISTENER_WAIT_TIMEOUT_MS = 1000;
     private static final int REPEATING_CAPTURE_EXPECTED_RESULT_COUNT = 5;
-    // VGA size capture is required by CDD.
-    private static final int DEFAULT_CAPTURE_WIDTH = 640;
-    private static final int DEFAULT_CAPTURE_HEIGHT = 480;
     private static final int MAX_NUM_IMAGES = 5;
+    private static final int MIN_FPS_REQUIRED_FOR_STREAMING = 20;
 
-    private static int[] mTemplates = new int[] {
+    private CameraCaptureSession mSession;
+
+    private BlockingStateCallback mCameraMockListener;
+    private int mLatestDeviceState = STATE_UNINITIALIZED;
+    private BlockingSessionCallback mSessionMockListener;
+    private StateWaiter mSessionWaiter;
+    private int mLatestSessionState = -1; // uninitialized
+
+    private static int[] sTemplates = new int[] {
             CameraDevice.TEMPLATE_PREVIEW,
             CameraDevice.TEMPLATE_RECORD,
             CameraDevice.TEMPLATE_STILL_CAPTURE,
             CameraDevice.TEMPLATE_VIDEO_SNAPSHOT
     };
 
+    // Request templates that are unsupported by LEGACY mode.
+    private static Set<Integer> sLegacySkipTemplates = new HashSet<>();
+    static {
+        sLegacySkipTemplates.add(CameraDevice.TEMPLATE_VIDEO_SNAPSHOT);
+        sLegacySkipTemplates.add(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG);
+        sLegacySkipTemplates.add(CameraDevice.TEMPLATE_MANUAL);
+    }
+
     @Override
     public void setContext(Context context) {
         super.setContext(context);
+
         /**
          * Workaround for mockito and JB-MR2 incompatibility
          *
          * Avoid java.lang.IllegalArgumentException: dexcache == null
          * https://code.google.com/p/dexmaker/issues/detail?id=2
          */
-        System.setProperty("dexmaker.dexcache", mContext.getCacheDir().toString());
+        System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString());
+
         /**
-         * Create errorlistener in context scope, to catch asynchronous device error.
+         * Create error listener in context scope, to catch asynchronous device error.
          * Use spy object here since we want to use the SimpleDeviceListener callback
          * implementation (spy doesn't stub the functions unless we ask it to do so).
          */
-        mCameraListener = spy(new BlockingStateListener());
+        mCameraMockListener = spy(new BlockingStateCallback());
     }
 
     @Override
@@ -110,113 +117,583 @@
          * fail the rest of the tests. This is especially needed when error
          * callback is fired too late.
          */
-        verify(mCameraListener, never())
+        verify(mCameraMockListener, never())
                 .onError(
                     any(CameraDevice.class),
                     anyInt());
-        verify(mCameraListener, never())
+        verify(mCameraMockListener, never())
                 .onDisconnected(
                     any(CameraDevice.class));
 
-        mCameraManager = (CameraManager)mContext.getSystemService(Context.CAMERA_SERVICE);
-        assertNotNull("Can't connect to camera manager", mCameraManager);
-        createDefaultSurface();
-        mLooperThread = new CameraTestThread();
-        mCallbackHandler = mLooperThread.start();
+        mCameraListener = mCameraMockListener;
+        createDefaultImageReader(DEFAULT_CAPTURE_SIZE, ImageFormat.YUV_420_888, MAX_NUM_IMAGES,
+                new ImageDropperListener());
     }
 
     @Override
     protected void tearDown() throws Exception {
-        mDummyThread.close();
-        mReader.close();
         super.tearDown();
     }
 
-    public void testCameraDeviceCreateCaptureBuilder() throws Exception {
-        String[] ids = mCameraManager.getCameraIdList();
-        for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = null;
-            try {
-                camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mCallbackHandler);
-                assertNotNull(
-                        String.format("Failed to open camera device ID: %s", ids[i]), camera);
+    /**
+     * <p>
+     * Test camera capture request preview capture template.
+     * </p>
+     *
+     * <p>
+     * The request template returned by the camera device must include a
+     * necessary set of metadata keys, and their values must be set correctly.
+     * It mainly requires below settings:
+     * </p>
+     * <ul>
+     * <li>All 3A settings are auto.</li>
+     * <li>All sensor settings are not null.</li>
+     * <li>All ISP processing settings should be non-manual, and the camera
+     * device should make sure the stable frame rate is guaranteed for the given
+     * settings.</li>
+     * </ul>
+     */
+    public void testCameraDevicePreviewTemplate() throws Exception {
+        for (int i = 0; i < mCameraIds.length; i++) {
+            captureTemplateTestByCamera(mCameraIds[i], CameraDevice.TEMPLATE_PREVIEW);
+        }
 
+        // TODO: test the frame rate sustainability in preview use case test.
+    }
+
+    /**
+     * <p>
+     * Test camera capture request still capture template.
+     * </p>
+     *
+     * <p>
+     * The request template returned by the camera device must include a
+     * necessary set of metadata keys, and their values must be set correctly.
+     * It mainly requires below settings:
+     * </p>
+     * <ul>
+     * <li>All 3A settings are auto.</li>
+     * <li>All sensor settings are not null.</li>
+     * <li>All ISP processing settings should be non-manual, and the camera
+     * device should make sure the high quality takes priority to the stable
+     * frame rate for the given settings.</li>
+     * </ul>
+     */
+    public void testCameraDeviceStillTemplate() throws Exception {
+        for (int i = 0; i < mCameraIds.length; i++) {
+            captureTemplateTestByCamera(mCameraIds[i], CameraDevice.TEMPLATE_STILL_CAPTURE);
+        }
+    }
+
+    /**
+     * <p>
+     * Test camera capture video recording template.
+     * </p>
+     *
+     * <p>
+     * The request template returned by the camera device must include a
+     * necessary set of metadata keys, and their values must be set correctly.
+     * It has the similar requirement as preview, with one difference:
+     * </p>
+     * <ul>
+     * <li>Frame rate should be stable, for example, wide fps range like [7, 30]
+     * is a bad setting.</li>
+     */
+    public void testCameraDeviceRecordingTemplate() throws Exception {
+        for (int i = 0; i < mCameraIds.length; i++) {
+            captureTemplateTestByCamera(mCameraIds[i], CameraDevice.TEMPLATE_RECORD);
+        }
+
+        // TODO: test the frame rate sustainability in recording use case test.
+    }
+
+    /**
+     *<p>Test camera capture video snapshot template.</p>
+     *
+     * <p>The request template returned by the camera device must include a necessary set of
+     * metadata keys, and their values must be set correctly. It has the similar requirement
+     * as recording, with an additional requirement: the settings should maximize image quality
+     * without compromising stable frame rate.</p>
+     */
+    public void testCameraDeviceVideoSnapShotTemplate() throws Exception {
+        for (int i = 0; i < mCameraIds.length; i++) {
+            captureTemplateTestByCamera(mCameraIds[i], CameraDevice.TEMPLATE_VIDEO_SNAPSHOT);
+        }
+
+        // TODO: test the frame rate sustainability in video snapshot use case test.
+    }
+
+    /**
+     *<p>Test camera capture request zero shutter lag template.</p>
+     *
+     * <p>The request template returned by the camera device must include a necessary set of
+     * metadata keys, and their values must be set correctly. It has the similar requirement
+     * as preview, with an additional requirement: </p>
+     */
+    public void testCameraDeviceZSLTemplate() throws Exception {
+        for (int i = 0; i < mCameraIds.length; i++) {
+            captureTemplateTestByCamera(mCameraIds[i], CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG);
+        }
+    }
+
+    /**
+     * <p>
+     * Test camera capture request manual template.
+     * </p>
+     *
+     * <p>
+     * The request template returned by the camera device must include a
+     * necessary set of metadata keys, and their values must be set correctly. It
+     * mainly requires below settings:
+     * </p>
+     * <ul>
+     * <li>All 3A settings are manual.</li>
+     * <li>ISP processing parameters are set to preview quality.</li>
+     * <li>The manual capture parameters (exposure, sensitivity, and so on) are
+     * set to reasonable defaults.</li>
+     * </ul>
+     */
+    public void testCameraDeviceManualTemplate() throws Exception {
+        for (int i = 0; i < mCameraIds.length; i++) {
+            captureTemplateTestByCamera(mCameraIds[i], CameraDevice.TEMPLATE_MANUAL);
+        }
+    }
+
+    public void testCameraDeviceCreateCaptureBuilder() throws Exception {
+        for (int i = 0; i < mCameraIds.length; i++) {
+            try {
+                openDevice(mCameraIds[i], mCameraMockListener);
                 /**
                  * Test: that each template type is supported, and that its required fields are
                  * present.
                  */
-                for (int j = 0; j < mTemplates.length; j++) {
-                    CaptureRequest.Builder capReq = camera.createCaptureRequest(mTemplates[j]);
+                for (int j = 0; j < sTemplates.length; j++) {
+                    // Skip video snapshots for LEGACY mode
+                    if (mStaticInfo.isHardwareLevelLegacy() &&
+                            sTemplates[j] == CameraDevice.TEMPLATE_VIDEO_SNAPSHOT) {
+                        continue;
+                    }
+                    CaptureRequest.Builder capReq = mCamera.createCaptureRequest(sTemplates[j]);
                     assertNotNull("Failed to create capture request", capReq);
-                    assertNotNull("Missing field: SENSOR_EXPOSURE_TIME",
-                            capReq.get(CaptureRequest.SENSOR_EXPOSURE_TIME));
-                    assertNotNull("Missing field: SENSOR_SENSITIVITY",
-                            capReq.get(CaptureRequest.SENSOR_SENSITIVITY));
-
-                    // TODO: Add more tests to check more fields.
+                    if (mStaticInfo.areKeysAvailable(CaptureRequest.SENSOR_EXPOSURE_TIME)) {
+                        assertNotNull("Missing field: SENSOR_EXPOSURE_TIME",
+                                capReq.get(CaptureRequest.SENSOR_EXPOSURE_TIME));
+                    }
+                    if (mStaticInfo.areKeysAvailable(CaptureRequest.SENSOR_SENSITIVITY)) {
+                        assertNotNull("Missing field: SENSOR_SENSITIVITY",
+                                capReq.get(CaptureRequest.SENSOR_SENSITIVITY));
+                    }
                 }
             }
             finally {
-                if (camera != null) {
-                    camera.close();
+                try {
+                    closeSession();
+                } finally {
+                    closeDevice(mCameraIds[i], mCameraMockListener);
                 }
             }
         }
     }
 
     public void testCameraDeviceSetErrorListener() throws Exception {
-        String[] ids = mCameraManager.getCameraIdList();
-        for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = null;
+        for (int i = 0; i < mCameraIds.length; i++) {
             try {
-                camera = CameraTestUtils.openCamera(mCameraManager, ids[i],
-                        mCameraListener, mCallbackHandler);
-                assertNotNull(
-                        String.format("Failed to open camera device %s", ids[i]), camera);
-
+                openDevice(mCameraIds[i], mCameraMockListener);
                 /**
                  * Test: that the error listener can be set without problems.
                  * Also, wait some time to check if device doesn't run into error.
                  */
                 SystemClock.sleep(ERROR_LISTENER_WAIT_TIMEOUT_MS);
-                verify(mCameraListener, never())
+                verify(mCameraMockListener, never())
                         .onError(
                                 any(CameraDevice.class),
                                 anyInt());
             }
             finally {
-                if (camera != null) {
-                    camera.close();
+                try {
+                    closeSession();
+                } finally {
+                    closeDevice(mCameraIds[i], mCameraMockListener);
                 }
             }
         }
     }
 
     public void testCameraDeviceCapture() throws Exception {
-        runCaptureTest(false, false);
+        runCaptureTest(/*burst*/false, /*repeating*/false, /*abort*/false);
     }
 
     public void testCameraDeviceCaptureBurst() throws Exception {
-        runCaptureTest(true, false);
+        runCaptureTest(/*burst*/true, /*repeating*/false, /*abort*/false);
     }
 
     public void testCameraDeviceRepeatingRequest() throws Exception {
-        runCaptureTest(false, true);
+        runCaptureTest(/*burst*/false, /*repeating*/true, /*abort*/false);
     }
 
     public void testCameraDeviceRepeatingBurst() throws Exception {
-        runCaptureTest(true, true);
+        runCaptureTest(/*burst*/true, /*repeating*/true, /*abort*/false);
     }
 
-    private class IsCameraMetadataNotEmpty<T extends CameraMetadata>
-            extends ArgumentMatcher<T> {
+    /**
+     * Test {@link android.hardware.camera2.CameraCaptureSession#abortCaptures} API.
+     *
+     * <p>Abort is the fastest way to idle the camera device for reconfiguration with
+     * {@link android.hardware.camera2.CameraCaptureSession#abortCaptures}, at the cost of
+     * discarding in-progress work. Once the abort is complete, the idle callback will be called.
+     * </p>
+     */
+    public void testCameraDeviceAbort() throws Exception {
+        runCaptureTest(/*burst*/false, /*repeating*/true, /*abort*/true);
+        runCaptureTest(/*burst*/true, /*repeating*/true, /*abort*/true);
+        /**
+         * TODO: this is only basic test of abort. we probably should also test below cases:
+         *
+         * 1. Performance. Make sure abort is faster than stopRepeating, we can test each one a
+         * couple of times, then compare the average. Also, for abortCaptures() alone, we should
+         * make sure it doesn't take too long time (e.g. <100ms for full devices, <500ms for limited
+         * devices), after the abort, we should be able to get all results back very quickly.  This
+         * can be done in performance test.
+         *
+         * 2. Make sure all in-flight request comes back after abort, e.g. submit a couple of
+         * long exposure single captures, then abort, then check if we can get the pending
+         * request back quickly.
+         *
+         * 3. Also need check onCaptureSequenceCompleted for repeating burst after abortCaptures().
+         */
+    }
+
+    /**
+     * Test invalid capture (e.g. null or empty capture request).
+     */
+    public void testInvalidCapture() throws Exception {
+        for (int i = 0; i < mCameraIds.length; i++) {
+            try {
+                openDevice(mCameraIds[i], mCameraMockListener);
+                waitForDeviceState(STATE_OPENED, CAMERA_OPEN_TIMEOUT_MS);
+
+                prepareCapture();
+
+                invalidRequestCaptureTestByCamera();
+
+                closeSession();
+            }
+            finally {
+                try {
+
+                } finally {
+                    closeDevice(mCameraIds[i], mCameraMockListener);
+                }
+            }
+        }
+    }
+
+    /**
+     * Test to ensure that we can call camera2 API methods inside callbacks.
+     *
+     * Tests:
+     *  onOpened -> createCaptureSession, createCaptureRequest
+     *  onConfigured -> getDevice, abortCaptures,
+     *     createCaptureRequest, capture, setRepeatingRequest, stopRepeating
+     *  onCaptureCompleted -> createCaptureRequest, getDevice, abortCaptures,
+     *     capture, setRepeatingRequest, stopRepeating, session+device.close
+     */
+    public void testChainedOperation() throws Throwable {
+
+        // Set up single dummy target
+        createDefaultImageReader(DEFAULT_CAPTURE_SIZE, ImageFormat.YUV_420_888, MAX_NUM_IMAGES,
+                /*listener*/ null);
+        final ArrayList<Surface> outputs = new ArrayList<>();
+        outputs.add(mReaderSurface);
+
+        // A queue for the chained listeners to push results to
+        // A success Throwable indicates no errors; other Throwables detail a test failure;
+        // nulls indicate timeouts.
+        final Throwable success = new Throwable("Success");
+        final LinkedBlockingQueue<Throwable> results = new LinkedBlockingQueue<>();
+
+        // Define listeners
+        // A cascade of Device->Session->Capture listeners, each of which invokes at least one
+        // method on the camera device or session.
+
+        class ChainedCaptureCallback extends CameraCaptureSession.CaptureCallback {
+            public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
+                    TotalCaptureResult result) {
+                try {
+                    CaptureRequest.Builder request2 =
+                            session.getDevice().createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+                    request2.addTarget(mReaderSurface);
+
+                    // Some calls to the camera for coverage
+                    session.abortCaptures();
+                    session.capture(request2.build(),
+                            /*listener*/ null, /*handler*/ null);
+                    session.setRepeatingRequest(request2.build(),
+                            /*listener*/ null, /*handler*/ null);
+                    session.stopRepeating();
+
+                    CameraDevice camera = session.getDevice();
+                    session.close();
+                    camera.close();
+
+                    results.offer(success);
+                } catch (Throwable t) {
+                    results.offer(t);
+                }
+            }
+
+            public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request,
+                    CaptureFailure failure) {
+                try {
+                    CameraDevice camera = session.getDevice();
+                    session.close();
+                    camera.close();
+                    fail("onCaptureFailed invoked with failure reason: " + failure.getReason());
+                } catch (Throwable t) {
+                    results.offer(t);
+                }
+            }
+        }
+
+        class ChainedSessionListener extends CameraCaptureSession.StateCallback {
+            private final ChainedCaptureCallback mCaptureCallback = new ChainedCaptureCallback();
+
+            public void onConfigured(CameraCaptureSession session) {
+                try {
+                    CaptureRequest.Builder request =
+                            session.getDevice().createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+                    request.addTarget(mReaderSurface);
+                    // Some calls to the camera for coverage
+                    session.getDevice();
+                    session.abortCaptures();
+                    // The important call for the next level of chaining
+                    session.capture(request.build(), mCaptureCallback, mHandler);
+                    // Some more calls
+                    session.setRepeatingRequest(request.build(),
+                            /*listener*/ null, /*handler*/ null);
+                    session.stopRepeating();
+                    results.offer(success);
+                } catch (Throwable t) {
+                    results.offer(t);
+                }
+            }
+
+            public void onConfigureFailed(CameraCaptureSession session) {
+                try {
+                    CameraDevice camera = session.getDevice();
+                    session.close();
+                    camera.close();
+                    fail("onConfigureFailed was invoked");
+                } catch (Throwable t) {
+                    results.offer(t);
+                }
+            }
+        }
+
+        class ChainedCameraListener extends CameraDevice.StateCallback {
+            private final ChainedSessionListener mSessionListener = new ChainedSessionListener();
+
+            public CameraDevice cameraDevice;
+
+            public void onOpened(CameraDevice camera) {
+
+                cameraDevice = camera;
+                try {
+                    // Some calls for coverage
+                    camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+                    // The important call for next level of chaining
+                    camera.createCaptureSession(outputs, mSessionListener, mHandler);
+                    results.offer(success);
+                } catch (Throwable t) {
+                    try {
+                        camera.close();
+                        results.offer(t);
+                    } catch (Throwable t2) {
+                        Log.e(TAG,
+                                "Second failure reached; discarding first exception with trace " +
+                                Log.getStackTraceString(t));
+                        results.offer(t2);
+                    }
+                }
+            }
+
+            public void onDisconnected(CameraDevice camera) {
+                try {
+                    camera.close();
+                    fail("onDisconnected invoked");
+                } catch (Throwable t) {
+                    results.offer(t);
+                }
+            }
+
+            public void onError(CameraDevice camera, int error) {
+                try {
+                    camera.close();
+                    fail("onError invoked with error code: " + error);
+                } catch (Throwable t) {
+                    results.offer(t);
+                }
+            }
+        }
+
+        // Actual test code
+
+        for (int i = 0; i < mCameraIds.length; i++) {
+            Throwable result;
+
+            // Start chained cascade
+            ChainedCameraListener cameraListener = new ChainedCameraListener();
+            mCameraManager.openCamera(mCameraIds[i], cameraListener, mHandler);
+
+            // Check if open succeeded
+            result = results.poll(CAMERA_OPEN_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+            if (result != success) {
+                if (cameraListener.cameraDevice != null) cameraListener.cameraDevice.close();
+                if (result == null) {
+                    fail("Timeout waiting for camera open");
+                } else {
+                    throw result;
+                }
+            }
+
+            // Check if configure succeeded
+            result = results.poll(SESSION_CONFIGURE_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+            if (result != success) {
+                if (cameraListener.cameraDevice != null) cameraListener.cameraDevice.close();
+                if (result == null) {
+                    fail("Timeout waiting for session configure");
+                } else {
+                    throw result;
+                }
+            }
+
+            // Check if capture succeeded
+            result = results.poll(CAPTURE_RESULT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+            if (result != success) {
+                if (cameraListener.cameraDevice != null) cameraListener.cameraDevice.close();
+                if (result == null) {
+                    fail("Timeout waiting for capture completion");
+                } else {
+                    throw result;
+                }
+            }
+        }
+    }
+
+    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);
+        CaptureRequest unConfiguredRequest = requestBuilder.build();
+        List<CaptureRequest> unConfiguredRequests = new ArrayList<CaptureRequest>();
+        unConfiguredRequests.add(unConfiguredRequest);
+
+        try {
+            // Test: CameraCaptureSession capture should throw IAE for null request.
+            mSession.capture(/*request*/null, /*listener*/null, mHandler);
+            mCollector.addMessage(
+                    "Session capture should throw IllegalArgumentException for null request");
+        } catch (IllegalArgumentException e) {
+            // Pass.
+        }
+
+        try {
+            // Test: CameraCaptureSession capture should throw IAE for request
+            // without surface configured.
+            mSession.capture(unConfiguredRequest, /*listener*/null, mHandler);
+            mCollector.addMessage("Session capture should throw " +
+                    "IllegalArgumentException for request without surface configured");
+        } catch (IllegalArgumentException e) {
+            // Pass.
+        }
+
+        try {
+            // Test: CameraCaptureSession setRepeatingRequest should throw IAE for null request.
+            mSession.setRepeatingRequest(/*request*/null, /*listener*/null, mHandler);
+            mCollector.addMessage("Session setRepeatingRequest should throw " +
+                    "IllegalArgumentException for null request");
+        } catch (IllegalArgumentException e) {
+            // Pass.
+        }
+
+        try {
+            // Test: CameraCaptureSession setRepeatingRequest should throw IAE for for request
+            // without surface configured.
+            mSession.setRepeatingRequest(unConfiguredRequest, /*listener*/null, mHandler);
+            mCollector.addMessage("Capture zero burst should throw IllegalArgumentException " +
+                    "for request without surface configured");
+        } catch (IllegalArgumentException e) {
+            // Pass.
+        }
+
+        try {
+            // Test: CameraCaptureSession captureBurst should throw IAE for null request list.
+            mSession.captureBurst(/*requests*/null, /*listener*/null, mHandler);
+            mCollector.addMessage("Session captureBurst should throw " +
+                    "IllegalArgumentException for null request list");
+        } catch (IllegalArgumentException e) {
+            // Pass.
+        }
+
+        try {
+            // Test: CameraCaptureSession captureBurst should throw IAE for empty request list.
+            mSession.captureBurst(emptyRequests, /*listener*/null, mHandler);
+            mCollector.addMessage("Session captureBurst should throw " +
+                    " IllegalArgumentException for empty request list");
+        } catch (IllegalArgumentException e) {
+            // Pass.
+        }
+
+        try {
+            // Test: CameraCaptureSession captureBurst should throw IAE for request
+            // without surface configured.
+            mSession.captureBurst(unConfiguredRequests, /*listener*/null, mHandler);
+            fail("Session captureBurst should throw IllegalArgumentException " +
+                    "for null request list");
+        } catch (IllegalArgumentException e) {
+            // Pass.
+        }
+
+        try {
+            // Test: CameraCaptureSession setRepeatingBurst should throw IAE for null request list.
+            mSession.setRepeatingBurst(/*requests*/null, /*listener*/null, mHandler);
+            mCollector.addMessage("Session setRepeatingBurst should throw " +
+                    "IllegalArgumentException for null request list");
+        } catch (IllegalArgumentException e) {
+            // Pass.
+        }
+
+        try {
+            // Test: CameraCaptureSession setRepeatingBurst should throw IAE for empty request list.
+            mSession.setRepeatingBurst(emptyRequests, /*listener*/null, mHandler);
+            mCollector.addMessage("Session setRepeatingBurst should throw " +
+                    "IllegalArgumentException for empty request list");
+        } catch (IllegalArgumentException e) {
+            // Pass.
+        }
+
+        try {
+            // Test: CameraCaptureSession setRepeatingBurst should throw IAE for request
+            // without surface configured.
+            mSession.setRepeatingBurst(unConfiguredRequests, /*listener*/null, mHandler);
+            mCollector.addMessage("Session setRepeatingBurst should throw " +
+                    "IllegalArgumentException for request without surface configured");
+        } catch (IllegalArgumentException e) {
+            // Pass.
+        }
+    }
+
+    private class IsCaptureResultNotEmpty
+            extends ArgumentMatcher<TotalCaptureResult> {
         @Override
         public boolean matches(Object obj) {
             /**
              * Do the simple verification here. Only verify the timestamp for now.
              * TODO: verify more required capture result metadata fields.
              */
-            CameraMetadata result = (CameraMetadata) obj;
+            TotalCaptureResult result = (TotalCaptureResult) obj;
             Long timeStamp = result.get(CaptureResult.SENSOR_TIMESTAMP);
             if (timeStamp != null && timeStamp.longValue() > 0L) {
                 return true;
@@ -225,31 +702,38 @@
         }
     }
 
-    private void runCaptureTest(boolean burst, boolean repeating) throws Exception {
-        String[] ids = mCameraManager.getCameraIdList();
-        for (int i = 0; i < ids.length; i++) {
-            CameraDevice camera = null;
+    /**
+     * Run capture test with different test configurations.
+     *
+     * @param burst If the test uses {@link CameraCaptureSession#captureBurst} or
+     * {@link CameraCaptureSession#setRepeatingBurst} to capture the burst.
+     * @param repeating If the test uses {@link CameraCaptureSession#setRepeatingBurst} or
+     * {@link CameraCaptureSession#setRepeatingRequest} for repeating capture.
+     * @param abort If the test uses {@link CameraCaptureSession#abortCaptures} to stop the
+     * repeating capture.  It has no effect if repeating is false.
+     */
+    private void runCaptureTest(boolean burst, boolean repeating, boolean abort) throws Exception {
+        for (int i = 0; i < mCameraIds.length; i++) {
             try {
-                camera = CameraTestUtils.openCamera(mCameraManager, ids[i],
-                        mCameraListener, mCallbackHandler);
-                assertNotNull(
-                        String.format("Failed to open camera device %s", ids[i]), camera);
-                waitForState(STATE_UNCONFIGURED, CAMERA_OPEN_TIMEOUT_MS);
+                openDevice(mCameraIds[i], mCameraMockListener);
+                waitForDeviceState(STATE_OPENED, CAMERA_OPEN_TIMEOUT_MS);
 
-                prepareCapture(camera);
+                prepareCapture();
 
                 if (!burst) {
                     // Test: that a single capture of each template type succeeds.
-                    for (int j = 0; j < mTemplates.length; j++) {
-                        captureSingleShot(camera, ids[i], mTemplates[j], repeating);
+                    for (int j = 0; j < sTemplates.length; j++) {
+                        // Skip video snapshots for LEGACY mode
+                        if (mStaticInfo.isHardwareLevelLegacy() &&
+                                sTemplates[j] == CameraDevice.TEMPLATE_VIDEO_SNAPSHOT) {
+                            continue;
+                        }
+                        captureSingleShot(mCameraIds[i], sTemplates[j], repeating, abort);
                     }
                 }
                 else {
-                    // Test: burst of zero shots
-                    captureBurstShot(camera, ids[i], mTemplates, 0, repeating);
-
                     // Test: burst of one shot
-                    captureBurstShot(camera, ids[i], mTemplates, 1, repeating);
+                    captureBurstShot(mCameraIds[i], sTemplates, 1, repeating, abort);
 
                     int[] templates = new int[] {
                             CameraDevice.TEMPLATE_STILL_CAPTURE,
@@ -260,181 +744,620 @@
                             };
 
                     // Test: burst of 5 shots of the same template type
-                    captureBurstShot(camera, ids[i], templates, templates.length, repeating);
+                    captureBurstShot(mCameraIds[i], templates, templates.length, repeating, abort);
 
                     // Test: burst of 5 shots of different template types
-                    captureBurstShot(camera, ids[i], mTemplates, mTemplates.length, repeating);
+                    captureBurstShot(
+                            mCameraIds[i], sTemplates, sTemplates.length, repeating, abort);
                 }
-                verify(mCameraListener, never())
+                verify(mCameraMockListener, never())
                         .onError(
                                 any(CameraDevice.class),
                                 anyInt());
-            }
-            finally {
-                if (camera != null) {
-                    camera.close();
+            } catch (Exception e) {
+                mCollector.addError(e);
+            } finally {
+                try {
+                    closeSession();
+                } catch (Exception e) {
+                    mCollector.addError(e);
+                }finally {
+                    closeDevice(mCameraIds[i], mCameraMockListener);
                 }
             }
         }
     }
 
     private void captureSingleShot(
-            CameraDevice camera,
             String id,
             int template,
-            boolean repeating) throws Exception {
+            boolean repeating, boolean abort) throws Exception {
 
         assertEquals("Bad initial state for preparing to capture",
-                mLatestState, STATE_IDLE);
+                mLatestSessionState, SESSION_READY);
 
-        CaptureRequest.Builder requestBuilder = camera.createCaptureRequest(template);
+        CaptureRequest.Builder requestBuilder = mCamera.createCaptureRequest(template);
         assertNotNull("Failed to create capture request", requestBuilder);
-        requestBuilder.addTarget(mSurface);
-        CameraDevice.CaptureListener mockCaptureListener =
-                mock(CameraDevice.CaptureListener.class);
+        requestBuilder.addTarget(mReaderSurface);
+        CameraCaptureSession.CaptureCallback mockCaptureCallback =
+                mock(CameraCaptureSession.CaptureCallback.class);
 
         if (VERBOSE) {
             Log.v(TAG, String.format("Capturing shot for device %s, template %d",
                     id, template));
         }
-        if (!repeating) {
-            camera.capture(requestBuilder.build(), mockCaptureListener, mCallbackHandler);
-        }
-        else {
-            camera.setRepeatingRequest(requestBuilder.build(), mockCaptureListener,
-                    mCallbackHandler);
-        }
-        waitForState(STATE_ACTIVE, CAMERA_CONFIGURE_TIMEOUT_MS);
+
+        startCapture(requestBuilder.build(), repeating, mockCaptureCallback, mHandler);
+        waitForSessionState(SESSION_ACTIVE, SESSION_ACTIVE_TIMEOUT_MS);
 
         int expectedCaptureResultCount = repeating ? REPEATING_CAPTURE_EXPECTED_RESULT_COUNT : 1;
-        verifyCaptureResults(camera, mockCaptureListener, expectedCaptureResultCount);
+        verifyCaptureResults(mockCaptureCallback, expectedCaptureResultCount);
 
         if (repeating) {
-            camera.stopRepeating();
+            if (abort) {
+                mSession.abortCaptures();
+            } else {
+                mSession.stopRepeating();
+            }
         }
-        waitForState(STATE_IDLE, CAMERA_CONFIGURE_TIMEOUT_MS);
+        waitForSessionState(SESSION_READY, SESSION_READY_TIMEOUT_MS);
     }
 
     private void captureBurstShot(
-            CameraDevice camera,
             String id,
             int[] templates,
             int len,
-            boolean repeating) throws Exception {
+            boolean repeating,
+            boolean abort) 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>();
         for (int i = 0; i < len; i++) {
-            CaptureRequest.Builder requestBuilder = camera.createCaptureRequest(templates[i]);
+            // Skip video snapshots for LEGACY mode
+            if (mStaticInfo.isHardwareLevelLegacy() &&
+                    templates[i] == CameraDevice.TEMPLATE_VIDEO_SNAPSHOT) {
+                continue;
+            }
+            CaptureRequest.Builder requestBuilder = mCamera.createCaptureRequest(templates[i]);
             assertNotNull("Failed to create capture request", requestBuilder);
-            requestBuilder.addTarget(mSurface);
+            requestBuilder.addTarget(mReaderSurface);
             requests.add(requestBuilder.build());
         }
-        CameraDevice.CaptureListener mockCaptureListener =
-                mock(CameraDevice.CaptureListener.class);
+        CameraCaptureSession.CaptureCallback mockCaptureCallback =
+                mock(CameraCaptureSession.CaptureCallback.class);
 
         if (VERBOSE) {
             Log.v(TAG, String.format("Capturing burst shot for device %s", id));
         }
 
         if (!repeating) {
-            camera.captureBurst(requests, mockCaptureListener, mCallbackHandler);
+            mSession.captureBurst(requests, mockCaptureCallback, mHandler);
         }
         else {
-            camera.setRepeatingBurst(requests, mockCaptureListener, mCallbackHandler);
+            mSession.setRepeatingBurst(requests, mockCaptureCallback, mHandler);
         }
-        waitForState(STATE_ACTIVE, CAMERA_CONFIGURE_TIMEOUT_MS);
+        waitForSessionState(SESSION_ACTIVE, SESSION_READY_TIMEOUT_MS);
 
-        int expectedResultCount = len;
+        int expectedResultCount = requests.size();
         if (repeating) {
             expectedResultCount *= REPEATING_CAPTURE_EXPECTED_RESULT_COUNT;
         }
 
-        verifyCaptureResults(camera, mockCaptureListener, expectedResultCount);
+        verifyCaptureResults(mockCaptureCallback, expectedResultCount);
 
         if (repeating) {
-            camera.stopRepeating();
+            if (abort) {
+                mSession.abortCaptures();
+            } else {
+                mSession.stopRepeating();
+            }
         }
-        waitForState(STATE_IDLE, CAMERA_CONFIGURE_TIMEOUT_MS);
-    }
-
-    // Precondition: Device must be in known IDLE/UNCONFIGURED state (has been waited for)
-    private void prepareCapture(CameraDevice camera) throws Exception {
-        assertTrue("Bad initial state for preparing to capture",
-                mLatestState == STATE_IDLE || mLatestState == STATE_UNCONFIGURED);
-
-        List<Surface> outputSurfaces = new ArrayList<Surface>(1);
-        outputSurfaces.add(mSurface);
-        camera.configureOutputs(outputSurfaces);
-        waitForState(STATE_BUSY, CAMERA_BUSY_TIMEOUT_MS);
-        waitForState(STATE_IDLE, CAMERA_IDLE_TIMEOUT_MS);
+        waitForSessionState(SESSION_READY, SESSION_READY_TIMEOUT_MS);
     }
 
     /**
-     * Dummy listener that release the image immediately once it is available.
-     * It can be used for the case where we don't care the image data at all.
-     * TODO: move it to the CameraTestUtil class.
-     */
-    private class ImageDropperListener implements ImageReader.OnImageAvailableListener {
-        @Override
-        public void onImageAvailable(ImageReader reader) {
-            Image image = null;
-            try {
-                image = reader.acquireNextImage();
-            } finally {
-                if (image != null) {
-                    image.close();
-                }
-            }
+     * 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 {
+        if (VERBOSE) Log.v(TAG, "prepareCapture");
+
+        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 BlockingSessionCallback());
+        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 waitForDeviceState(int state, long timeoutMs) {
+        mCameraMockListener.waitForState(state, timeoutMs);
+        mLatestDeviceState = state;
     }
 
-    private void createDefaultSurface() throws Exception {
-        mReader =
-                ImageReader.newInstance(DEFAULT_CAPTURE_WIDTH,
-                        DEFAULT_CAPTURE_HEIGHT,
-                        ImageFormat.YUV_420_888,
-                        MAX_NUM_IMAGES);
-        mSurface = mReader.getSurface();
-        // Create dummy image listener since we don't care the image data in this test.
-        ImageReader.OnImageAvailableListener listener = new ImageDropperListener();
-        mDummyThread = new CameraTestThread();
-        mReader.setOnImageAvailableListener(listener, mDummyThread.start());
-    }
-
-    private void waitForState(int state, long timeout) {
-        mCameraListener.waitForState(state, timeout);
-        mLatestState = state;
+    private void waitForSessionState(int state, long timeoutMs) {
+        mSessionWaiter.waitForState(state, timeoutMs);
+        mLatestSessionState = state;
     }
 
     private void verifyCaptureResults(
-            CameraDevice camera,
-            CameraDevice.CaptureListener mockListener,
+            CameraCaptureSession.CaptureCallback mockListener,
             int expectResultCount) {
+        final int TIMEOUT_PER_RESULT_MS = 2000;
         // Should receive expected number of capture results.
         verify(mockListener,
-                timeout(CAPTURE_WAIT_TIMEOUT_MS).atLeast(expectResultCount))
+                timeout(TIMEOUT_PER_RESULT_MS * expectResultCount).atLeast(expectResultCount))
                         .onCaptureCompleted(
-                                eq(camera),
+                                eq(mSession),
                                 isA(CaptureRequest.class),
-                                argThat(new IsCameraMetadataNotEmpty<CaptureResult>()));
+                                argThat(new IsCaptureResultNotEmpty()));
         // Should not receive any capture failed callbacks.
         verify(mockListener, never())
                         .onCaptureFailed(
-                                eq(camera),
-                                argThat(new IsCameraMetadataNotEmpty<CaptureRequest>()),
+                                eq(mSession),
+                                isA(CaptureRequest.class),
                                 isA(CaptureFailure.class));
         // Should receive expected number of capture shutter calls
         verify(mockListener,
                 atLeast(expectResultCount))
                         .onCaptureStarted(
-                               eq(camera),
+                               eq(mSession),
                                isA(CaptureRequest.class),
+                               anyLong(),
                                anyLong());
-
     }
 
+    private void checkFpsRange(CaptureRequest.Builder request, int template,
+            CameraCharacteristics props) {
+        CaptureRequest.Key<Range<Integer>> fpsRangeKey = CONTROL_AE_TARGET_FPS_RANGE;
+        Range<Integer> fpsRange;
+        if ((fpsRange = mCollector.expectKeyValueNotNull(request, fpsRangeKey)) == null) {
+            return;
+        }
+
+        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 += 1) {
+            if (minFps == availableFpsRange[i].getLower()
+                    && maxFps == availableFpsRange[i].getUpper()) {
+                foundRange = true;
+                break;
+            }
+        }
+        if (!foundRange) {
+            mCollector.addMessage(String.format("Unable to find the fps range (%d, %d)",
+                    minFps, maxFps));
+            return;
+        }
+
+
+        if (template != CameraDevice.TEMPLATE_MANUAL &&
+                template != CameraDevice.TEMPLATE_STILL_CAPTURE) {
+            if (maxFps < MIN_FPS_REQUIRED_FOR_STREAMING) {
+                mCollector.addMessage("Max fps should be at least "
+                        + MIN_FPS_REQUIRED_FOR_STREAMING);
+                return;
+            }
+
+            // Relax framerate constraints on legacy mode
+            if (mStaticInfo.isHardwareLevelLimitedOrBetter()) {
+                // Need give fixed frame rate for video recording template.
+                if (template == CameraDevice.TEMPLATE_RECORD) {
+                    if (maxFps != minFps) {
+                        mCollector.addMessage("Video recording frame rate should be fixed");
+                    }
+                }
+            }
+        }
+    }
+
+    private void checkAfMode(CaptureRequest.Builder request, int template,
+            CameraCharacteristics props) {
+        boolean hasFocuser = !props.getKeys().contains(CameraCharacteristics.
+                LENS_INFO_MINIMUM_FOCUS_DISTANCE) ||
+                props.get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE) > 0f;
+
+        if (!hasFocuser) {
+            return;
+        }
+
+        int targetAfMode = CaptureRequest.CONTROL_AF_MODE_AUTO;
+        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) {
+            // Default to CONTINUOUS_PICTURE if it is available, otherwise AUTO.
+            for (int i = 0; i < availableAfMode.length; i++) {
+                if (availableAfMode[i] == CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE) {
+                    targetAfMode = CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE;
+                    break;
+                }
+            }
+        } else if (template == CameraDevice.TEMPLATE_RECORD ||
+                template == CameraDevice.TEMPLATE_VIDEO_SNAPSHOT) {
+            // Default to CONTINUOUS_VIDEO if it is available, otherwise AUTO.
+            for (int i = 0; i < availableAfMode.length; i++) {
+                if (availableAfMode[i] == CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO) {
+                    targetAfMode = CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO;
+                    break;
+                }
+            }
+        } else if (template == CameraDevice.TEMPLATE_MANUAL) {
+            targetAfMode = CaptureRequest.CONTROL_AF_MODE_OFF;
+        }
+
+        mCollector.expectKeyValueEquals(request, CONTROL_AF_MODE, targetAfMode);
+        if (mStaticInfo.areKeysAvailable(CaptureRequest.LENS_FOCUS_DISTANCE)) {
+            mCollector.expectKeyValueNotNull(request, LENS_FOCUS_DISTANCE);
+        }
+    }
+
+    /**
+     * <p>Check if 3A metering settings are "up to HAL" in request template</p>
+     *
+     * <p>This function doesn't fail the test immediately, it updates the
+     * test pass/fail status and appends the failure message to the error collector each key.</p>
+     *
+     * @param regions The metering rectangles to be checked
+     */
+    private void checkMeteringRect(MeteringRectangle[] regions) {
+        if (regions == null) {
+            return;
+        }
+        mCollector.expectNotEquals("Number of metering region should not be 0", 0, regions.length);
+        for (int i = 0; i < regions.length; i++) {
+            mCollector.expectEquals("Default metering regions should have all zero weight",
+                    0, regions[i].getMeteringWeight());
+        }
+    }
+
+    /**
+     * <p>Check if the request settings are suitable for a given request template.</p>
+     *
+     * <p>This function doesn't fail the test immediately, it updates the
+     * test pass/fail status and appends the failure message to the error collector each key.</p>
+     *
+     * @param request The request to be checked.
+     * @param template The capture template targeted by this request.
+     * @param props The CameraCharacteristics this request is checked against with.
+     */
+    private void checkRequestForTemplate(CaptureRequest.Builder request, int template,
+            CameraCharacteristics props) {
+        // 3A settings--control.mode.
+        if (template != CameraDevice.TEMPLATE_MANUAL) {
+            mCollector.expectKeyValueEquals(request, CONTROL_MODE,
+                    CaptureRequest.CONTROL_MODE_AUTO);
+        }
+
+        // 3A settings--AE/AWB/AF.
+        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);
+            mCollector.expectKeyValueNotEquals(request, CONTROL_AE_ANTIBANDING_MODE,
+                    CaptureRequest.CONTROL_AE_ANTIBANDING_MODE_OFF);
+            mCollector.expectKeyValueEquals(request, CONTROL_AE_EXPOSURE_COMPENSATION, 0);
+            mCollector.expectKeyValueEquals(request, CONTROL_AE_LOCK, false);
+            mCollector.expectKeyValueEquals(request, CONTROL_AE_PRECAPTURE_TRIGGER,
+                    CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_IDLE);
+
+            mCollector.expectKeyValueEquals(request, CONTROL_AF_TRIGGER,
+                    CaptureRequest.CONTROL_AF_TRIGGER_IDLE);
+
+            mCollector.expectKeyValueEquals(request, CONTROL_AWB_MODE,
+                    CaptureRequest.CONTROL_AWB_MODE_AUTO);
+            mCollector.expectKeyValueEquals(request, CONTROL_AWB_LOCK, false);
+
+            // Check 3A regions.
+            if (VERBOSE) {
+                Log.v(TAG, String.format("maxRegions is: {AE: %s, AWB: %s, AF: %s}",
+                        maxRegionsAe, maxRegionsAwb, maxRegionsAf));
+            }
+            if (maxRegionsAe > 0) {
+                mCollector.expectKeyValueNotNull(request, CONTROL_AE_REGIONS);
+                MeteringRectangle[] aeRegions = request.get(CONTROL_AE_REGIONS);
+                checkMeteringRect(aeRegions);
+            }
+            if (maxRegionsAwb > 0) {
+                mCollector.expectKeyValueNotNull(request, CONTROL_AWB_REGIONS);
+                MeteringRectangle[] awbRegions = request.get(CONTROL_AWB_REGIONS);
+                checkMeteringRect(awbRegions);
+            }
+            if (maxRegionsAf > 0) {
+                mCollector.expectKeyValueNotNull(request, CONTROL_AF_REGIONS);
+                MeteringRectangle[] afRegions = request.get(CONTROL_AF_REGIONS);
+                checkMeteringRect(afRegions);
+            }
+        }
+
+        // Sensor settings.
+
+        mCollector.expectEquals("Lens aperture must be present in request if available apertures " +
+                        "are present in metadata, and vice-versa.",
+                mStaticInfo.areKeysAvailable(CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES),
+                mStaticInfo.areKeysAvailable(CaptureRequest.LENS_APERTURE));
+        if (mStaticInfo.areKeysAvailable(CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES)) {
+            float[] availableApertures =
+                    props.get(CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES);
+            if (availableApertures.length > 1) {
+                mCollector.expectKeyValueNotNull(request, LENS_APERTURE);
+            }
+        }
+
+        mCollector.expectEquals("Lens filter density must be present in request if available " +
+                        "filter densities are present in metadata, and vice-versa.",
+                mStaticInfo.areKeysAvailable(CameraCharacteristics.
+                        LENS_INFO_AVAILABLE_FILTER_DENSITIES),
+                mStaticInfo.areKeysAvailable(CaptureRequest.LENS_FILTER_DENSITY));
+        if (mStaticInfo.areKeysAvailable(CameraCharacteristics.
+                LENS_INFO_AVAILABLE_FILTER_DENSITIES)) {
+            float[] availableFilters =
+                    props.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FILTER_DENSITIES);
+            if (availableFilters.length > 1) {
+                mCollector.expectKeyValueNotNull(request, LENS_FILTER_DENSITY);
+            }
+        }
+
+        float[] availableFocalLen =
+                props.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS);
+        if (availableFocalLen.length > 1) {
+            mCollector.expectKeyValueNotNull(request, LENS_FOCAL_LENGTH);
+        }
+
+        mCollector.expectEquals("Lens optical stabilization must be present in request if " +
+                        "available optical stabilizations are present in metadata, and vice-versa.",
+                mStaticInfo.areKeysAvailable(CameraCharacteristics.
+                        LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION),
+                mStaticInfo.areKeysAvailable(CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE));
+        if (mStaticInfo.areKeysAvailable(CameraCharacteristics.
+                LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION)) {
+            int[] availableOIS =
+                    props.get(CameraCharacteristics.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION);
+            if (availableOIS.length > 1) {
+                mCollector.expectKeyValueNotNull(request, LENS_OPTICAL_STABILIZATION_MODE);
+            }
+        }
+
+        if (mStaticInfo.areKeysAvailable(BLACK_LEVEL_LOCK)) {
+            mCollector.expectKeyValueEquals(request, BLACK_LEVEL_LOCK, false);
+        }
+
+        if (mStaticInfo.areKeysAvailable(SENSOR_FRAME_DURATION)) {
+            mCollector.expectKeyValueNotNull(request, SENSOR_FRAME_DURATION);
+        }
+
+        if (mStaticInfo.areKeysAvailable(SENSOR_EXPOSURE_TIME)) {
+            mCollector.expectKeyValueNotNull(request, SENSOR_EXPOSURE_TIME);
+        }
+
+        if (mStaticInfo.areKeysAvailable(SENSOR_SENSITIVITY)) {
+            mCollector.expectKeyValueNotNull(request, SENSOR_SENSITIVITY);
+        }
+
+        // ISP-processing settings.
+        mCollector.expectKeyValueEquals(
+                request, STATISTICS_FACE_DETECT_MODE,
+                CaptureRequest.STATISTICS_FACE_DETECT_MODE_OFF);
+        mCollector.expectKeyValueEquals(request, FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
+
+        List<Integer> availableCaps = mStaticInfo.getAvailableCapabilitiesChecked();
+        if (mStaticInfo.areKeysAvailable(STATISTICS_LENS_SHADING_MAP_MODE)) {
+            // If the device doesn't support RAW, all template should have OFF as default.
+            if (!availableCaps.contains(REQUEST_AVAILABLE_CAPABILITIES_RAW)) {
+                mCollector.expectKeyValueEquals(
+                        request, STATISTICS_LENS_SHADING_MAP_MODE,
+                        CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE_OFF);
+            }
+        }
+
+        if (template == CameraDevice.TEMPLATE_STILL_CAPTURE) {
+            // Not enforce high quality here, as some devices may not effectively have high quality
+            // mode.
+            if (mStaticInfo.areKeysAvailable(COLOR_CORRECTION_MODE)) {
+                mCollector.expectKeyValueNotEquals(
+                        request, COLOR_CORRECTION_MODE,
+                        CaptureRequest.COLOR_CORRECTION_MODE_TRANSFORM_MATRIX);
+            }
+
+            mCollector.expectEquals("Edge mode must be present in request if " +
+                            "available edge modes are present in metadata, and vice-versa.",
+                    mStaticInfo.areKeysAvailable(CameraCharacteristics.
+                            EDGE_AVAILABLE_EDGE_MODES),
+                    mStaticInfo.areKeysAvailable(CaptureRequest.EDGE_MODE));
+            if (mStaticInfo.areKeysAvailable(EDGE_MODE)) {
+                List<Integer> availableEdgeModes =
+                        Arrays.asList(toObject(mStaticInfo.getAvailableEdgeModesChecked()));
+                if (availableEdgeModes.contains(CaptureRequest.EDGE_MODE_HIGH_QUALITY)) {
+                    mCollector.expectKeyValueEquals(request, EDGE_MODE,
+                            CaptureRequest.EDGE_MODE_HIGH_QUALITY);
+                } 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);
+                }
+            }
+
+            mCollector.expectEquals("Noise reduction mode must be present in request if " +
+                            "available noise reductions are present in metadata, and vice-versa.",
+                    mStaticInfo.areKeysAvailable(CameraCharacteristics.
+                            NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES),
+                    mStaticInfo.areKeysAvailable(CaptureRequest.NOISE_REDUCTION_MODE));
+            if (mStaticInfo.areKeysAvailable(
+                    CameraCharacteristics.NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES)) {
+                List<Integer> availableNoiseReductionModes =
+                        Arrays.asList(toObject(mStaticInfo.getAvailableNoiseReductionModesChecked()));
+                if (availableNoiseReductionModes
+                        .contains(CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY)) {
+                    mCollector.expectKeyValueEquals(
+                            request, NOISE_REDUCTION_MODE,
+                            CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY);
+                } else if (availableNoiseReductionModes
+                        .contains(CaptureRequest.NOISE_REDUCTION_MODE_FAST)) {
+                    mCollector.expectKeyValueEquals(
+                            request, NOISE_REDUCTION_MODE, CaptureRequest.NOISE_REDUCTION_MODE_FAST);
+                } else {
+                    mCollector.expectKeyValueEquals(
+                            request, NOISE_REDUCTION_MODE, CaptureRequest.NOISE_REDUCTION_MODE_OFF);
+                }
+            }
+
+            mCollector.expectEquals("Tonemap mode must be present in request if " +
+                            "available tonemap modes are present in metadata, and vice-versa.",
+                    mStaticInfo.areKeysAvailable(CameraCharacteristics.
+                            TONEMAP_AVAILABLE_TONE_MAP_MODES),
+                    mStaticInfo.areKeysAvailable(CaptureRequest.TONEMAP_MODE));
+            if (mStaticInfo.areKeysAvailable(
+                    CameraCharacteristics.TONEMAP_AVAILABLE_TONE_MAP_MODES)) {
+                List<Integer> availableToneMapModes =
+                        Arrays.asList(toObject(mStaticInfo.getAvailableToneMapModesChecked()));
+                if (availableToneMapModes.contains(CaptureRequest.TONEMAP_MODE_HIGH_QUALITY)) {
+                    mCollector.expectKeyValueEquals(request, TONEMAP_MODE,
+                            CaptureRequest.TONEMAP_MODE_HIGH_QUALITY);
+                } else {
+                    mCollector.expectKeyValueEquals(request, TONEMAP_MODE,
+                            CaptureRequest.TONEMAP_MODE_FAST);
+                }
+            }
+
+            // Still capture template should have android.statistics.lensShadingMapMode ON when
+            // RAW capability is supported.
+            if (mStaticInfo.areKeysAvailable(STATISTICS_LENS_SHADING_MAP_MODE) &&
+                    availableCaps.contains(REQUEST_AVAILABLE_CAPABILITIES_RAW)) {
+                    mCollector.expectKeyValueEquals(request, STATISTICS_LENS_SHADING_MAP_MODE,
+                            STATISTICS_LENS_SHADING_MAP_MODE_ON);
+            }
+        } else {
+            if (mStaticInfo.areKeysAvailable(EDGE_MODE)) {
+                mCollector.expectKeyValueNotNull(request, EDGE_MODE);
+            }
+
+            if (mStaticInfo.areKeysAvailable(NOISE_REDUCTION_MODE)) {
+                mCollector.expectKeyValueNotNull(request, NOISE_REDUCTION_MODE);
+            }
+
+            if (mStaticInfo.areKeysAvailable(TONEMAP_MODE)) {
+                mCollector.expectKeyValueNotEquals(request, TONEMAP_MODE,
+                        CaptureRequest.TONEMAP_MODE_CONTRAST_CURVE);
+            }
+            if (mStaticInfo.areKeysAvailable(STATISTICS_LENS_SHADING_MAP_MODE)) {
+                mCollector.expectKeyValueNotNull(request, STATISTICS_LENS_SHADING_MAP_MODE);
+            }
+        }
+
+        mCollector.expectKeyValueEquals(request, CONTROL_CAPTURE_INTENT, template);
+
+        // TODO: use the list of keys from CameraCharacteristics to avoid expecting
+        //       keys which are not available by this CameraDevice.
+    }
+
+    private void captureTemplateTestByCamera(String cameraId, int template) throws Exception {
+        try {
+            openDevice(cameraId, mCameraMockListener);
+
+            assertTrue("Camera template " + template + " is out of range!",
+                    template >= CameraDevice.TEMPLATE_PREVIEW
+                            && template <= CameraDevice.TEMPLATE_MANUAL);
+
+            mCollector.setCameraId(cameraId);
+
+            try {
+                CaptureRequest.Builder request = mCamera.createCaptureRequest(template);
+                assertNotNull("Failed to create capture request for template " + template, request);
+
+                CameraCharacteristics props = mStaticInfo.getCharacteristics();
+                checkRequestForTemplate(request, template, props);
+            } catch (IllegalArgumentException e) {
+                if (template == CameraDevice.TEMPLATE_MANUAL &&
+                        !mStaticInfo.isCapabilitySupported(CameraCharacteristics.
+                                REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
+                    // OK
+                } else if (sLegacySkipTemplates.contains(template) &&
+                        mStaticInfo.isHardwareLevelLegacy()) {
+                    // OK
+                } else {
+                    throw e; // rethrow
+                }
+            }
+        }
+        finally {
+            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 #CaptureCallback} camera device used to notify callbacks.
+     * @param handler The handler camera device used to post callbacks.
+     */
+    protected void startCapture(CaptureRequest request, boolean repeating,
+            CameraCaptureSession.CaptureCallback 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.StateCallback#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 7091cac..192fb85 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraManagerTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraManagerTest.java
@@ -16,17 +16,32 @@
 
 package android.hardware.camera2.cts;
 
+import static org.mockito.Mockito.*;
+import static org.mockito.AdditionalMatchers.not;
+import static org.mockito.AdditionalMatchers.and;
+
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.hardware.camera2.CameraAccessException;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraDevice.StateCallback;
 import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.cts.CameraTestUtils.MockStateCallback;
+import android.hardware.camera2.cts.helpers.CameraErrorCollector;
 import android.os.Handler;
+import android.os.HandlerThread;
 import android.test.AndroidTestCase;
 import android.util.Log;
 
+import com.android.ex.camera2.blocking.BlockingStateCallback;
+
+import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
+
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 
 /**
  * <p>Basic test for CameraManager class.</p>
@@ -34,14 +49,15 @@
 public class CameraManagerTest extends AndroidTestCase {
     private static final String TAG = "CameraManagerTest";
     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
-
     private static final int NUM_CAMERA_REOPENS = 10;
 
     private PackageManager mPackageManager;
     private CameraManager mCameraManager;
     private NoopCameraListener mListener;
-    private CameraTestThread mLooperThread;
+    private HandlerThread mHandlerThread;
     private Handler mHandler;
+    private BlockingStateCallback mCameraListener;
+    private CameraErrorCollector mCollector;
 
     @Override
     public void setContext(Context context) {
@@ -57,16 +73,53 @@
     protected void setUp() throws Exception {
         super.setUp();
 
-        mLooperThread = new CameraTestThread();
-        mHandler = mLooperThread.start();
+        /**
+         * Workaround for mockito and JB-MR2 incompatibility
+         *
+         * Avoid java.lang.IllegalArgumentException: dexcache == null
+         * https://code.google.com/p/dexmaker/issues/detail?id=2
+         */
+        System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString());
+
+        mCameraListener = spy(new BlockingStateCallback());
+
+        mHandlerThread = new HandlerThread(TAG);
+        mHandlerThread.start();
+        mHandler = new Handler(mHandlerThread.getLooper());
+        mCollector = new CameraErrorCollector();
     }
 
     @Override
     protected void tearDown() throws Exception {
-        mLooperThread.close();
+        mHandlerThread.quitSafely();
         mHandler = null;
 
-        super.tearDown();
+        try {
+            mCollector.verify();
+        } catch (Throwable e) {
+            // When new Exception(e) is used, exception info will be printed twice.
+            throw new Exception(e.getMessage());
+        } finally {
+            super.tearDown();
+        }
+    }
+
+    /**
+     * Verifies that the reason is in the range of public-only codes.
+     */
+    private static int checkCameraAccessExceptionReason(CameraAccessException e) {
+        int reason = e.getReason();
+
+        switch (reason) {
+            case CameraAccessException.CAMERA_DISABLED:
+            case CameraAccessException.CAMERA_DISCONNECTED:
+            case CameraAccessException.CAMERA_ERROR:
+                return reason;
+        }
+
+        fail("Invalid CameraAccessException code: " + reason);
+
+        return -1; // unreachable
     }
 
     public void testCameraManagerGetDeviceIdList() throws Exception {
@@ -135,12 +188,12 @@
         for (int i = 0; i < ids.length; i++) {
             invalidId.append(ids[i]);
         }
+
         try {
-            CameraCharacteristics props = mCameraManager.getCameraCharacteristics(
+            mCameraManager.getCameraCharacteristics(
                 invalidId.toString());
             fail(String.format("Accepted invalid camera ID: %s", invalidId.toString()));
-        }
-        catch (IllegalArgumentException e) {
+        } catch (IllegalArgumentException e) {
             // This is the exception that should be thrown in this case.
         }
     }
@@ -150,90 +203,265 @@
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
             for (int j = 0; j < NUM_CAMERA_REOPENS; j++) {
-                CameraDevice camera = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
-                assertNotNull(
-                    String.format("Failed to open camera device ID: %s", ids[i]), camera);
-                camera.close();
-            }
-        }
-    }
-
-    /**
-     * Test: that all camera devices can be open at the same time, or the appropriate
-     * exception is thrown if this can't be done.
-     */
-    public void testCameraManagerOpenAllCameras() throws Exception {
-        String[] ids = mCameraManager.getCameraIdList();
-        CameraDevice[] cameras = new CameraDevice[ids.length];
-        try {
-            for (int i = 0; i < ids.length; i++) {
+                CameraDevice camera = null;
                 try {
-                    cameras[i] = CameraTestUtils.openCamera(mCameraManager, ids[i], mHandler);
+                    MockStateCallback mockListener = MockStateCallback.mock();
+                    mCameraListener = new BlockingStateCallback(mockListener);
 
-                    /**
-                     * If the camera can't be opened, should throw an exception, rather than
-                     * returning null.
-                     */
-                    assertNotNull(
-                        String.format("Failed to open camera device ID: %s", ids[i]),
-                        cameras[i]);
-                }
-                catch (CameraAccessException e) {
-                    /**
-                     * This is the expected behavior if the camera can't be opened due to
-                     * limitations on how many devices can be open simultaneously.
-                     */
-                    assertEquals(
-                        String.format("Invalid exception reason: %s", e.getReason()),
-                        CameraAccessException.MAX_CAMERAS_IN_USE, e.getReason());
-                }
-            }
-        }
-        finally {
-            for (int i = 0; i < ids.length; i++) {
-                if (cameras[i] != null) {
-                    cameras[i].close();
-                }
-            }
-        }
-    }
+                    mCameraManager.openCamera(ids[i], mCameraListener, mHandler);
 
-    // Test: that opening the same device multiple times throws the right exception.
-    public void testCameraManagerOpenCameraTwice() throws Exception {
-        String[] ids = mCameraManager.getCameraIdList();
-        CameraDevice[] cameras = new CameraDevice[2];
-        if (ids.length > 0) {
-            try {
-                cameras[0] = CameraTestUtils.openCamera(mCameraManager, ids[0], mHandler);
-                assertNotNull(
-                    String.format("Failed to open camera device ID: %s", ids[0]),
-                    cameras[0]);
-                try {
-                    cameras[1] = CameraTestUtils.openCamera(mCameraManager, ids[0], mHandler);
-                    fail(String.format("Opened the same camera device twice ID: %s",
-                        ids[0]));
-                }
-                catch (CameraAccessException e) {
-                    /**
-                     * This is the expected behavior if the camera device is attempted to
-                     * be opened more than once.
-                     */
-                    assertEquals(
-                        String.format("Invalid exception reason: %s", e.getReason()),
-                        CameraAccessException.CAMERA_IN_USE, e.getReason());
-                }
-            }
-            finally {
-                for (int i = 0; i < 2; i++) {
-                    if (cameras[i] != null) {
-                        cameras[i].close();
+                    // Block until unConfigured
+                    mCameraListener.waitForState(BlockingStateCallback.STATE_OPENED,
+                            CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
+
+                    // Ensure state transitions are in right order:
+                    // -- 1) Opened
+                    // Ensure no other state transitions have occurred:
+                    camera = verifyCameraStateOpened(ids[i], mockListener);
+                } finally {
+                    if (camera != null) {
+                        camera.close();
                     }
                 }
             }
         }
     }
 
-    private class NoopCameraListener extends CameraManager.AvailabilityListener {
+    /**
+     * Test: one or more camera devices can be open at the same time, or the right error state
+     * is set if this can't be done.
+     */
+    public void testCameraManagerOpenAllCameras() throws Exception {
+        String[] ids = mCameraManager.getCameraIdList();
+        assertNotNull("Camera ids shouldn't be null", ids);
+
+        // Skip test if the device doesn't have multiple cameras.
+        if (ids.length <= 1) {
+            return;
+        }
+
+        List<CameraDevice> cameraList = new ArrayList<CameraDevice>();
+        List<MockStateCallback> listenerList = new ArrayList<MockStateCallback>();
+        List<BlockingStateCallback> blockingListenerList = new ArrayList<BlockingStateCallback>();
+        try {
+            for (int i = 0; i < ids.length; i++) {
+                // Ignore state changes from other cameras
+                MockStateCallback mockListener = MockStateCallback.mock();
+                mCameraListener = new BlockingStateCallback(mockListener);
+
+                /**
+                 * Track whether or not we got a synchronous error from openCamera.
+                 *
+                 * A synchronous error must also be accompanied by an asynchronous
+                 * StateCallback#onError callback.
+                 */
+                boolean expectingError = false;
+
+                String cameraId = ids[i];
+                try {
+                    mCameraManager.openCamera(cameraId, mCameraListener,
+                            mHandler);
+                } catch (CameraAccessException e) {
+                    if (checkCameraAccessExceptionReason(e) == CameraAccessException.CAMERA_ERROR) {
+                        expectingError = true;
+                    } else {
+                        // TODO: We should handle a Disabled camera by passing here and elsewhere
+                        fail("Camera must not be disconnected or disabled for this test" + ids[i]);
+                    }
+                }
+
+                List<Integer> expectedStates = new ArrayList<Integer>();
+                expectedStates.add(BlockingStateCallback.STATE_OPENED);
+                expectedStates.add(BlockingStateCallback.STATE_ERROR);
+                int state = mCameraListener.waitForAnyOfStates(
+                        expectedStates, CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
+
+                // It's possible that we got an asynchronous error transition only. This is ok.
+                if (expectingError) {
+                    assertEquals("Throwing a CAMERA_ERROR exception must be accompanied with a " +
+                            "StateCallback#onError callback",
+                            BlockingStateCallback.STATE_ERROR, state);
+                }
+
+                /**
+                 * Two situations are considered passing:
+                 * 1) The camera opened successfully.
+                 *     => No error must be set.
+                 * 2) The camera did not open because there were too many other cameras opened.
+                 *     => Only MAX_CAMERAS_IN_USE error must be set.
+                 *
+                 * Any other situation is considered a failure.
+                 *
+                 * For simplicity we treat disconnecting asynchronously as a failure, so
+                 * camera devices should not be physically unplugged during this test.
+                 */
+
+                CameraDevice camera;
+                if (state == BlockingStateCallback.STATE_ERROR) {
+                    // Camera did not open because too many other cameras were opened
+                    // => onError called exactly once with a non-null camera
+                    assertTrue("At least one camera must be opened successfully",
+                            cameraList.size() > 0);
+
+                    ArgumentCaptor<CameraDevice> argument =
+                            ArgumentCaptor.forClass(CameraDevice.class);
+
+                    verify(mockListener)
+                            .onError(
+                                    argument.capture(),
+                                    eq(CameraDevice.StateCallback.ERROR_MAX_CAMERAS_IN_USE));
+                    verifyNoMoreInteractions(mockListener);
+
+                    camera = argument.getValue();
+                    assertNotNull("Expected a non-null camera for the error transition for ID: "
+                            + ids[i], camera);
+                } else if (state == BlockingStateCallback.STATE_OPENED) {
+                    // Camera opened successfully.
+                    // => onOpened called exactly once
+                    camera = verifyCameraStateOpened(cameraId,
+                            mockListener);
+                } else {
+                    fail("Unexpected state " + state);
+                    camera = null; // unreachable. but need this for java compiler
+                }
+
+                // 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 (BlockingStateCallback blockingListener : blockingListenerList) {
+                blockingListener.waitForState(
+                        BlockingStateCallback.STATE_CLOSED,
+                        CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
+            }
+        }
+
+        /*
+         * Ensure that no state transitions have bled through from one camera to another
+         * after closing the cameras.
+         */
+        int i = 0;
+        for (MockStateCallback listener : listenerList) {
+            CameraDevice camera = cameraList.get(i);
+
+            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.
+        }
+    }
+
+    /**
+     * Verifies the camera in this listener was opened and then unconfigured exactly once.
+     *
+     * <p>This assumes that no other action to the camera has been done (e.g.
+     * it hasn't been configured, or closed, or disconnected). Verification is
+     * performed immediately without any timeouts.</p>
+     *
+     * <p>This checks that the state has previously changed first for opened and then unconfigured.
+     * Any other state transitions will fail. A test failure is thrown if verification fails.</p>
+     *
+     * @param cameraId Camera identifier
+     * @param listener Listener which was passed to {@link CameraManager#openCamera}
+     *
+     * @return The camera device (non-{@code null}).
+     */
+    private static CameraDevice verifyCameraStateOpened(String cameraId,
+            MockStateCallback listener) {
+        ArgumentCaptor<CameraDevice> argument =
+                ArgumentCaptor.forClass(CameraDevice.class);
+        InOrder inOrder = inOrder(listener);
+
+        /**
+         * State transitions (in that order):
+         *  1) onOpened
+         *
+         * No other transitions must occur for successful #openCamera
+         */
+        inOrder.verify(listener)
+                .onOpened(argument.capture());
+
+        CameraDevice camera = argument.getValue();
+        assertNotNull(
+                String.format("Failed to open camera device ID: %s", cameraId),
+                camera);
+
+        // Do not use inOrder here since that would skip anything called before onOpened
+        verifyNoMoreInteractions(listener);
+
+        return camera;
+    }
+
+    /**
+     * Test: that opening the same device multiple times and make sure the right
+     * error state is set.
+     */
+    public void testCameraManagerOpenCameraTwice() throws Exception {
+        String[] ids = mCameraManager.getCameraIdList();
+
+        // Test across every camera device.
+        for (int i = 0; i < ids.length; ++i) {
+            CameraDevice successCamera = null;
+            mCollector.setCameraId(ids[i]);
+
+            try {
+                MockStateCallback mockSuccessListener = MockStateCallback.mock();
+                MockStateCallback mockFailListener = MockStateCallback.mock();
+
+                BlockingStateCallback successListener =
+                        new BlockingStateCallback(mockSuccessListener);
+                BlockingStateCallback failListener =
+                        new BlockingStateCallback(mockFailListener);
+
+                mCameraManager.openCamera(ids[i], successListener, mHandler);
+
+                try {
+                    mCameraManager.openCamera(ids[i], failListener,
+                            mHandler);
+                } catch (CameraAccessException e) {
+                    // Optional (but common). Camera might fail asynchronously only.
+                    // Don't assert here, otherwise, all subsequent tests will fail because the
+                    // opened camera is never closed.
+                    mCollector.expectEquals(
+                            "If second camera open fails immediately, must be due to"
+                            + "camera being busy for ID: " + ids[i],
+                            CameraAccessException.CAMERA_ERROR, e.getReason());
+                }
+
+                successListener.waitForState(BlockingStateCallback.STATE_OPENED,
+                        CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
+                // Have to get the successCamera here, otherwise, it won't be
+                // closed if STATE_ERROR timeout exception occurs.
+                ArgumentCaptor<CameraDevice> argument =
+                        ArgumentCaptor.forClass(CameraDevice.class);
+                verify(mockSuccessListener, atLeastOnce()).onOpened(argument.capture());
+
+                failListener.waitForState(BlockingStateCallback.STATE_ERROR,
+                        CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
+
+                successCamera = verifyCameraStateOpened(
+                        ids[i], mockSuccessListener);
+
+                verify(mockFailListener)
+                        .onError(
+                                and(notNull(CameraDevice.class), not(eq(successCamera))),
+                                eq(StateCallback.ERROR_CAMERA_IN_USE));
+                verifyNoMoreInteractions(mockFailListener);
+            } finally {
+                if (successCamera != null) {
+                    successCamera.close();
+                }
+            }
+        }
+    }
+
+    private class NoopCameraListener extends CameraManager.AvailabilityCallback {
         @Override
         public void onCameraAvailable(String cameraId) {
             // No-op
@@ -252,13 +480,12 @@
      * a listener that isn't registered should have no effect.
      */
     public void testCameraManagerListener() throws Exception {
-        CameraTestThread callbackThread = new CameraTestThread();
-        Handler callbackHandler = callbackThread.start();
+        mCameraManager.unregisterAvailabilityCallback(mListener);
+        mCameraManager.registerAvailabilityCallback(mListener, mHandler);
+        mCameraManager.registerAvailabilityCallback(mListener, mHandler);
+        mCameraManager.unregisterAvailabilityCallback(mListener);
+        mCameraManager.unregisterAvailabilityCallback(mListener);
 
-        mCameraManager.removeAvailabilityListener(mListener);
-        mCameraManager.addAvailabilityListener(mListener, callbackHandler);
-        mCameraManager.addAvailabilityListener(mListener, callbackHandler);
-        mCameraManager.removeAvailabilityListener(mListener);
-        mCameraManager.removeAvailabilityListener(mListener);
+        // TODO: test the listener callbacks
     }
 }
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestThread.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestThread.java
deleted file mode 100644
index 9516ead..0000000
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestThread.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright 2013 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.os.ConditionVariable;
-import android.os.Handler;
-import android.os.Looper;
-import android.util.Log;
-
-import java.util.concurrent.TimeoutException;
-
-/**
- * Camera test thread wrapper for handling camera callbacks
- */
-public class CameraTestThread implements AutoCloseable {
-    private static final String TAG = "CameraTestThread";
-    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
-    // Timeout for initializing looper and opening camera in Milliseconds.
-    private static final long WAIT_FOR_COMMAND_TO_COMPLETE = 5000;
-    private Looper mLooper = null;
-    private Handler mHandler = null;
-
-    /**
-     * Create and start a looper thread, return the Handler
-     */
-    public synchronized Handler start() throws Exception {
-        final ConditionVariable startDone = new ConditionVariable();
-        if (mLooper != null || mHandler !=null) {
-            Log.w(TAG, "Looper thread already started");
-            return mHandler;
-        }
-
-        new Thread() {
-            @Override
-            public void run() {
-                if (VERBOSE) Log.v(TAG, "start loopRun");
-                Looper.prepare();
-                // Save the looper so that we can terminate this thread
-                // after we are done with it.
-                mLooper = Looper.myLooper();
-                mHandler = new Handler();
-                startDone.open();
-                Looper.loop();
-                if (VERBOSE) Log.v(TAG, "createLooperThread: finished");
-            }
-        }.start();
-
-        if (VERBOSE) Log.v(TAG, "start waiting for looper");
-        if (!startDone.block(WAIT_FOR_COMMAND_TO_COMPLETE)) {
-            throw new TimeoutException("createLooperThread: start timeout");
-        }
-        return mHandler;
-    }
-
-    /**
-     * Terminate the looper thread
-     */
-    public synchronized void close() throws Exception {
-        if (mLooper == null || mHandler == null) {
-            Log.w(TAG, "Looper thread doesn't start yet");
-            return;
-        }
-
-        if (VERBOSE) Log.v(TAG, "Terminate looper thread");
-        mLooper.quit();
-        mLooper.getThread().join();
-        mLooper = null;
-        mHandler = null;
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            close();
-        } finally {
-            super.finalize();
-        }
-    }
-}
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 7f10cb8..0c36832 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -16,43 +16,118 @@
 
 package android.hardware.camera2.cts;
 
+import static com.android.ex.camera2.blocking.BlockingStateCallback.*;
+
+import android.graphics.BitmapFactory;
 import android.graphics.ImageFormat;
+import android.graphics.PointF;
+import android.graphics.Rect;
 import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCaptureSession;
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CameraManager;
-import android.hardware.camera2.CameraMetadata;
 import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.Size;
+import android.hardware.camera2.CaptureFailure;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.TotalCaptureResult;
+import android.hardware.cts.helpers.CameraUtils;
+import android.util.Size;
+import android.hardware.camera2.params.MeteringRectangle;
+import android.hardware.camera2.params.StreamConfigurationMap;
 import android.media.Image;
 import android.media.ImageReader;
 import android.media.Image.Plane;
 import android.os.Handler;
 import android.util.Log;
+import android.view.Surface;
 
 import com.android.ex.camera2.blocking.BlockingCameraManager;
 import com.android.ex.camera2.blocking.BlockingCameraManager.BlockingOpenException;
+import com.android.ex.camera2.blocking.BlockingSessionCallback;
+import com.android.ex.camera2.blocking.BlockingStateCallback;
+import com.android.ex.camera2.exceptions.TimeoutRuntimeException;
 
 import junit.framework.Assert;
 
+import org.mockito.Mockito;
+
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.lang.reflect.Array;
 import java.nio.ByteBuffer;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
 
 /**
  * A package private utility class for wrapping up the camera2 cts test common utility functions
  */
-class CameraTestUtils extends Assert {
+public class CameraTestUtils extends Assert {
     private static final String TAG = "CameraTestUtils";
     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
-
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    public static final Size SIZE_BOUND_1080P = new Size(1920, 1088);
+    public static final Size SIZE_BOUND_2160P = new Size(3840, 2160);
+    // Only test the preview size that is no larger than 1080p.
+    public static final Size PREVIEW_SIZE_BOUND = SIZE_BOUND_1080P;
     // Default timeouts for reaching various states
-    public static final int CAMERA_OPEN_TIMEOUT_MS = 500;
-    public static final int CAMERA_IDLE_TIMEOUT_MS = 2000;
-    public static final int CAMERA_ACTIVE_TIMEOUT_MS = 500;
-    public static final int CAMERA_BUSY_TIMEOUT_MS = 500;
+    public static final int CAMERA_OPEN_TIMEOUT_MS = 3000;
+    public static final int CAMERA_CLOSE_TIMEOUT_MS = 3000;
+    public static final int CAMERA_IDLE_TIMEOUT_MS = 3000;
+    public static final int CAMERA_ACTIVE_TIMEOUT_MS = 1000;
+    public static final int CAMERA_BUSY_TIMEOUT_MS = 1000;
+    public static final int CAMERA_UNCONFIGURED_TIMEOUT_MS = 1000;
+    public static final int CAMERA_CONFIGURE_TIMEOUT_MS = 3000;
+    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 = 3000;
+    public static final int SESSION_CLOSE_TIMEOUT_MS = 3000;
+    public static final int SESSION_READY_TIMEOUT_MS = 3000;
+    public static final int SESSION_ACTIVE_TIMEOUT_MS = 1000;
+
+    public static final int MAX_READER_IMAGES = 5;
+
+    /**
+     * Create an {@link android.media.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.
+     */
+    public 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);
+        return reader;
+    }
+
+    /**
+     * Close pending images and clean up an {@link android.media.ImageReader} object.
+     * @param reader an {@link android.media.ImageReader} to close.
+     */
+    public static void closeImageReader(ImageReader reader) {
+        if (reader != null) {
+            reader.close();
+        }
+    }
+
+    /**
+     * Dummy listener that release the image immediately once it is available.
+     *
+     * <p>
+     * It can be used for the case where we don't care the image data at all.
+     * </p>
+     */
     public static class ImageDropperListener implements ImageReader.OnImageAvailableListener {
         @Override
         public void onImageAvailable(ImageReader reader) {
@@ -68,18 +143,158 @@
     }
 
     /**
+     * Image listener that release the image immediately after validating the image
+     */
+    public static class ImageVerifierListener implements ImageReader.OnImageAvailableListener {
+        private Size mSize;
+        private int mFormat;
+
+        public ImageVerifierListener(Size sz, int format) {
+            mSize = sz;
+            mFormat = format;
+        }
+
+        @Override
+        public void onImageAvailable(ImageReader reader) {
+            Image image = null;
+            try {
+                image = reader.acquireNextImage();
+            } finally {
+                if (image != null) {
+                    validateImage(image, mSize.getWidth(), mSize.getHeight(), mFormat, null);
+                    image.close();
+                }
+            }
+        }
+    }
+
+    public static class SimpleImageReaderListener
+            implements ImageReader.OnImageAvailableListener {
+        private final LinkedBlockingQueue<Image> mQueue =
+                new LinkedBlockingQueue<Image>();
+
+        @Override
+        public void onImageAvailable(ImageReader reader) {
+            try {
+                mQueue.put(reader.acquireNextImage());
+            } catch (InterruptedException e) {
+                throw new UnsupportedOperationException(
+                        "Can't handle InterruptedException in onImageAvailable");
+            }
+        }
+
+        /**
+         * Get an image from the image reader.
+         *
+         * @param timeout Timeout value for the wait.
+         * @return The image from the image reader.
+         */
+        public Image getImage(long timeout) throws InterruptedException {
+            Image image = mQueue.poll(timeout, TimeUnit.MILLISECONDS);
+            assertNotNull("Wait for an image timed out in " + timeout + "ms", image);
+            return image;
+        }
+    }
+
+    public static class SimpleCaptureCallback extends CameraCaptureSession.CaptureCallback {
+        private final LinkedBlockingQueue<CaptureResult> mQueue =
+                new LinkedBlockingQueue<CaptureResult>();
+
+        @Override
+        public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request,
+                long timestamp, long frameNumber)
+        {
+        }
+
+        @Override
+        public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
+                TotalCaptureResult result) {
+            try {
+                mQueue.put(result);
+            } catch (InterruptedException e) {
+                throw new UnsupportedOperationException(
+                        "Can't handle InterruptedException in onCaptureCompleted");
+            }
+        }
+
+        @Override
+        public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request,
+                CaptureFailure failure) {
+        }
+
+        @Override
+        public void onCaptureSequenceCompleted(CameraCaptureSession session, int sequenceId,
+                long frameNumber) {
+        }
+
+        public CaptureResult getCaptureResult(long timeout) {
+            try {
+                CaptureResult result = mQueue.poll(timeout, TimeUnit.MILLISECONDS);
+                assertNotNull("Wait for a capture result timed out in " + timeout + "ms", result);
+                return result;
+            } catch (InterruptedException e) {
+                throw new UnsupportedOperationException("Unhandled interrupted exception", e);
+            }
+        }
+
+        /**
+         * Get the {@link #CaptureResult capture result} for a given
+         * {@link #CaptureRequest capture request}.
+         *
+         * @param myRequest The {@link #CaptureRequest capture request} whose
+         *            corresponding {@link #CaptureResult capture result} was
+         *            being waited for
+         * @param numResultsWait Number of frames to wait for the capture result
+         *            before timeout.
+         * @throws TimeoutRuntimeException If more than numResultsWait results are
+         *            seen before the result matching myRequest arrives, or each
+         *            individual wait for result times out after
+         *            {@value #CAPTURE_RESULT_TIMEOUT_MS}ms.
+         */
+        public CaptureResult getCaptureResultForRequest(CaptureRequest myRequest,
+                int numResultsWait) {
+            if (numResultsWait < 0) {
+                throw new IllegalArgumentException("numResultsWait must be no less than 0");
+            }
+
+            CaptureResult result;
+            int i = 0;
+            do {
+                result = getCaptureResult(CAPTURE_RESULT_TIMEOUT_MS);
+                if (result.getRequest().equals(myRequest)) {
+                    return result;
+                }
+            } while (i++ < numResultsWait);
+
+            throw new TimeoutRuntimeException("Unable to get the expected capture result after "
+                    + "waiting for " + numResultsWait + " results");
+        }
+
+        public boolean hasMoreResults()
+        {
+            return mQueue.isEmpty();
+        }
+    }
+
+    /**
      * Block until the camera is opened.
      *
      * <p>Don't use this to test #onDisconnected/#onError since this will throw
      * an AssertionError if it fails to open the camera device.</p>
      *
      * @return CameraDevice opened camera device
-     * @throws BlockingOpenException
      *
-     * @throws AssertionError if the camera fails to open (or times out)
+     * @throws IllegalArgumentException
+     *            If the handler is null, or if the handler's looper is current.
+     * @throws CameraAccessException
+     *            If open fails immediately.
+     * @throws BlockingOpenException
+     *            If open fails after blocking for some amount of time.
+     * @throws TimeoutRuntimeException
+     *            If opening times out. Typically unrecoverable.
      */
     public static CameraDevice openCamera(CameraManager manager, String cameraId,
-            CameraDevice.StateListener listener, Handler handler) throws CameraAccessException,
+            CameraDevice.StateCallback listener, Handler handler) throws CameraAccessException,
             BlockingOpenException {
 
         /**
@@ -101,9 +316,14 @@
      * <p>Don't use this to test #onDisconnected/#onError since this will throw
      * an AssertionError if it fails to open the camera device.</p>
      *
-     * @return CameraDevice opened camera device
-     *
-     * @throws AssertionError if the camera fails to open (or times out)
+     * @throws IllegalArgumentException
+     *            If the handler is null, or if the handler's looper is current.
+     * @throws CameraAccessException
+     *            If open fails immediately.
+     * @throws BlockingOpenException
+     *            If open fails after blocking for some amount of time.
+     * @throws TimeoutRuntimeException
+     *            If opening times out. Typically unrecoverable.
      */
     public static CameraDevice openCamera(CameraManager manager, String cameraId, Handler handler)
             throws CameraAccessException,
@@ -111,6 +331,23 @@
         return openCamera(manager, cameraId, /*listener*/null, handler);
     }
 
+    /**
+     * Configure a new camera session with output surfaces.
+     *
+     * @param camera The CameraDevice to be configured.
+     * @param outputSurfaces The surface list that used for camera output.
+     * @param listener The callback CameraDevice will notify when capture results are available.
+     */
+    public static CameraCaptureSession configureCameraSession(CameraDevice camera,
+            List<Surface> outputSurfaces,
+            CameraCaptureSession.StateCallback listener, Handler handler)
+            throws CameraAccessException {
+        BlockingSessionCallback sessionListener = new BlockingSessionCallback(listener);
+        camera.createCaptureSession(outputSurfaces, sessionListener, handler);
+
+        return sessionListener.waitAndGetSession(SESSION_CONFIGURE_TIMEOUT_MS);
+    }
+
     public static <T> void assertArrayNotEmpty(T arr, String message) {
         assertTrue(message, arr != null && Array.getLength(arr) > 0);
     }
@@ -121,9 +358,7 @@
     public static void checkYuvFormat(int format) {
         if ((format != ImageFormat.YUV_420_888) &&
                 (format != ImageFormat.NV21) &&
-                (format != ImageFormat.YV12) &&
-                (format != ImageFormat.Y8) &&
-                (format != ImageFormat.Y16)) {
+                (format != ImageFormat.YV12)) {
             fail("Wrong formats: " + format);
         }
     }
@@ -170,20 +405,26 @@
         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;
         }
 
         int offset = 0;
         data = new byte[width * height * ImageFormat.getBitsPerPixel(format) / 8];
-        byte[] rowData = new byte[planes[0].getRowStride()];
+        int maxRowSize = planes[0].getRowStride();
+        for (int i = 0; i < planes.length; i++) {
+            if (maxRowSize < planes[i].getRowStride()) {
+                maxRowSize = planes[i].getRowStride();
+            }
+        }
+        byte[] rowData = new byte[maxRowSize];
         if(VERBOSE) Log.v(TAG, "get data from " + planes.length + " planes");
         for (int i = 0; i < planes.length; i++) {
             buffer = planes[i].getBuffer();
             assertNotNull("Fail to get bytebuffer from plane", buffer);
             rowStride = planes[i].getRowStride();
-            assertTrue("rowStride should be no less than width", rowStride >= width);
             pixelStride = planes[i].getPixelStride();
             assertTrue("pixel stride " + pixelStride + " is invalid", pixelStride > 0);
             if (VERBOSE) {
@@ -216,6 +457,7 @@
                 }
             }
             if (VERBOSE) Log.v(TAG, "Finished reading data from plane " + i);
+            buffer.rewind();
         }
         return data;
     }
@@ -223,7 +465,7 @@
     /**
      * <p>Check android image format validity for an image, only support below formats:</p>
      *
-     * <p>YUV_420_888/NV21/YV12/Y8/Y16, can add more for future</p>
+     * <p>YUV_420_888/NV21/YV12, can add more for future</p>
      */
     public static void checkAndroidImageFormat(Image image) {
         int format = image.getFormat();
@@ -234,11 +476,8 @@
             case ImageFormat.YV12:
                 assertEquals("YUV420 format Images should have 3 planes", 3, planes.length);
                 break;
-            case ImageFormat.Y8:
-            case ImageFormat.Y16:
-                assertEquals("Y8/Y16 Image should have 1 plane", 1, planes.length);
-                break;
             case ImageFormat.JPEG:
+            case ImageFormat.RAW_SENSOR:
                 assertEquals("Jpeg Image should have one plane", 1, planes.length);
                 break;
             default:
@@ -263,31 +502,475 @@
         }
     }
 
+    /**
+     * Get the available output sizes for the user-defined {@code format}.
+     *
+     * <p>Note that implementation-defined/hidden formats are not supported.</p>
+     */
     public static Size[] getSupportedSizeForFormat(int format, String cameraId,
-            CameraManager cameraManager) throws Exception {
-        CameraMetadata.Key<Size[]> key = null;
+            CameraManager cameraManager) throws CameraAccessException {
         CameraCharacteristics properties = cameraManager.getCameraCharacteristics(cameraId);
         assertNotNull("Can't get camera characteristics!", properties);
         if (VERBOSE) {
             Log.v(TAG, "get camera characteristics for camera: " + cameraId);
         }
-        switch (format) {
-            case ImageFormat.JPEG:
-                key = CameraCharacteristics.SCALER_AVAILABLE_JPEG_SIZES;
-                break;
-            case ImageFormat.YUV_420_888:
-            case ImageFormat.YV12:
-            case ImageFormat.NV21:
-            case ImageFormat.Y8:
-            case ImageFormat.Y16:
-                key = CameraCharacteristics.SCALER_AVAILABLE_PROCESSED_SIZES;
-                break;
-            default:
-                throw new UnsupportedOperationException(
-                        String.format("Invalid format specified 0x%x", format));
-        }
-        Size[] availableSizes = properties.get(key);
+        StreamConfigurationMap configMap =
+                properties.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+        Size[] availableSizes = configMap.getOutputSizes(format);
+        assertArrayNotEmpty(availableSizes, "availableSizes should not be empty");
         if (VERBOSE) Log.v(TAG, "Supported sizes are: " + Arrays.deepToString(availableSizes));
         return availableSizes;
     }
-}
\ No newline at end of file
+
+    /**
+     * Size comparator that compares the number of pixels it covers.
+     *
+     * <p>If two the areas of two sizes are same, compare the widths.</p>
+     */
+    public static class SizeComparator implements Comparator<Size> {
+        @Override
+        public int compare(Size lhs, Size rhs) {
+            return CameraUtils
+                    .compareSizes(lhs.getWidth(), lhs.getHeight(), rhs.getWidth(), rhs.getHeight());
+        }
+    }
+
+    /**
+     * Get sorted size list in descending order. Remove the sizes larger than
+     * the bound. If the bound is null, don't do the size bound filtering.
+     */
+    static public List<Size> getSupportedPreviewSizes(String cameraId,
+            CameraManager cameraManager, Size bound) throws CameraAccessException {
+        return getSortedSizesForFormat(cameraId, cameraManager, ImageFormat.YUV_420_888, bound);
+    }
+
+    /**
+     * Get a sorted list of sizes from a given size list.
+     *
+     * <p>
+     * The size is compare by area it covers, if the areas are same, then
+     * compare the widths.
+     * </p>
+     *
+     * @param sizeList The input size list to be sorted
+     * @param ascending True if the order is ascending, otherwise descending order
+     * @return The ordered list of sizes
+     */
+    static public List<Size> getAscendingOrderSizes(final List<Size> sizeList, boolean ascending) {
+        if (sizeList == null) {
+            throw new IllegalArgumentException("sizeList shouldn't be null");
+        }
+
+        Comparator<Size> comparator = new SizeComparator();
+        List<Size> sortedSizes = new ArrayList<Size>();
+        sortedSizes.addAll(sizeList);
+        Collections.sort(sortedSizes, comparator);
+        if (!ascending) {
+            Collections.reverse(sortedSizes);
+        }
+
+        return sortedSizes;
+    }
+
+    /**
+     * Get sorted (descending order) size list for given format. Remove the sizes larger than
+     * the bound. If the bound is null, don't do the size bound filtering.
+     */
+    static private List<Size> getSortedSizesForFormat(String cameraId,
+            CameraManager cameraManager, int format, Size bound) throws CameraAccessException {
+        Comparator<Size> comparator = new SizeComparator();
+        Size[] sizes = getSupportedSizeForFormat(format, cameraId, cameraManager);
+        List<Size> sortedSizes = null;
+        if (bound != null) {
+            sortedSizes = new ArrayList<Size>(/*capacity*/1);
+            for (Size sz : sizes) {
+                if (comparator.compare(sz, bound) <= 0) {
+                    sortedSizes.add(sz);
+                }
+            }
+        } else {
+            sortedSizes = Arrays.asList(sizes);
+        }
+        assertTrue("Supported size list should have at least one element",
+                sortedSizes.size() > 0);
+
+        Collections.sort(sortedSizes, comparator);
+        // Make it in descending order.
+        Collections.reverse(sortedSizes);
+        return sortedSizes;
+    }
+
+    /**
+     * Get supported video size list for a given camera device.
+     *
+     * <p>
+     * Filter out the sizes that are larger than the bound. If the bound is
+     * null, don't do the size bound filtering.
+     * </p>
+     */
+    static public List<Size> getSupportedVideoSizes(String cameraId,
+            CameraManager cameraManager, Size bound) throws CameraAccessException {
+        return getSortedSizesForFormat(cameraId, cameraManager, ImageFormat.YUV_420_888, bound);
+    }
+
+    /**
+     * Get supported video size list (descending order) for a given camera device.
+     *
+     * <p>
+     * Filter out the sizes that are larger than the bound. If the bound is
+     * null, don't do the size bound filtering.
+     * </p>
+     */
+    static public List<Size> getSupportedStillSizes(String cameraId,
+            CameraManager cameraManager, Size bound) throws CameraAccessException {
+        return getSortedSizesForFormat(cameraId, cameraManager, ImageFormat.JPEG, bound);
+    }
+
+    static public Size getMinPreviewSize(String cameraId, CameraManager cameraManager)
+            throws CameraAccessException {
+        List<Size> sizes = getSupportedPreviewSizes(cameraId, cameraManager, null);
+        return sizes.get(sizes.size() - 1);
+    }
+
+    /**
+     * Get max supported preview size for a camera device.
+     */
+    static public Size getMaxPreviewSize(String cameraId, CameraManager cameraManager)
+            throws CameraAccessException {
+        return getMaxPreviewSize(cameraId, cameraManager, /*bound*/null);
+    }
+
+    /**
+     * Get max preview size for a camera device in the supported sizes that are no larger
+     * than the bound.
+     */
+    static public Size getMaxPreviewSize(String cameraId, CameraManager cameraManager, Size bound)
+            throws CameraAccessException {
+        List<Size> sizes = getSupportedPreviewSizes(cameraId, cameraManager, bound);
+        return sizes.get(0);
+    }
+
+    /**
+     * Get the largest size by area.
+     *
+     * @param sizes an array of sizes, must have at least 1 element
+     *
+     * @return Largest Size
+     *
+     * @throws IllegalArgumentException if sizes was null or had 0 elements
+     */
+    public static Size getMaxSize(Size[] sizes) {
+        if (sizes == null || sizes.length == 0) {
+            throw new IllegalArgumentException("sizes was empty");
+        }
+
+        Size sz = sizes[0];
+        for (Size size : sizes) {
+            if (size.getWidth() * size.getHeight() > sz.getWidth() * sz.getHeight()) {
+                sz = size;
+            }
+        }
+
+        return sz;
+    }
+
+    /**
+     * Get object array from byte array.
+     *
+     * @param array Input byte array to be converted
+     * @return Byte object array converted from input byte array
+     */
+    public static Byte[] toObject(byte[] array) {
+        return convertPrimitiveArrayToObjectArray(array, Byte.class);
+    }
+
+    /**
+     * Get object array from int array.
+     *
+     * @param array Input int array to be converted
+     * @return Integer object array converted from input int array
+     */
+    public static Integer[] toObject(int[] array) {
+        return convertPrimitiveArrayToObjectArray(array, Integer.class);
+    }
+
+    /**
+     * Get object array from float array.
+     *
+     * @param array Input float array to be converted
+     * @return Float object array converted from input float array
+     */
+    public static Float[] toObject(float[] array) {
+        return convertPrimitiveArrayToObjectArray(array, Float.class);
+    }
+
+    /**
+     * Get object array from double array.
+     *
+     * @param array Input double array to be converted
+     * @return Double object array converted from input double array
+     */
+    public static Double[] toObject(double[] array) {
+        return convertPrimitiveArrayToObjectArray(array, Double.class);
+    }
+
+    /**
+     * Convert a primitive input array into its object array version (e.g. from int[] to Integer[]).
+     *
+     * @param array Input array object
+     * @param wrapperClass The boxed class it converts to
+     * @return Boxed version of primitive array
+     */
+    private static <T> T[] convertPrimitiveArrayToObjectArray(final Object array,
+            final Class<T> wrapperClass) {
+        // getLength does the null check and isArray check already.
+        int arrayLength = Array.getLength(array);
+        if (arrayLength == 0) {
+            throw new IllegalArgumentException("Input array shouldn't be empty");
+        }
+
+        @SuppressWarnings("unchecked")
+        final T[] result = (T[]) Array.newInstance(wrapperClass, arrayLength);
+        for (int i = 0; i < arrayLength; i++) {
+            Array.set(result, i, Array.get(array, i));
+        }
+        return result;
+    }
+
+    /**
+     * Validate image based on format and size.
+     * <p>
+     * Only RAW_SENSOR, YUV420_888 and JPEG formats are supported. Calling this
+     * method with other formats will cause a UnsupportedOperationException.
+     * </p>
+     *
+     * @param image The image to be validated.
+     * @param width The image width.
+     * @param height The image height.
+     * @param format The image format.
+     * @param filePath The debug dump file path, null if don't want to dump to
+     *            file.
+     * @throws UnsupportedOperationException if calling with format other than
+     *             RAW_SENSOR, YUV420_888 or JPEG.
+     */
+    public static void validateImage(Image image, int width, int height, int format,
+            String filePath) {
+        checkImage(image, width, height, format);
+
+        /**
+         * TODO: validate timestamp:
+         * 1. capture result timestamp against the image timestamp (need
+         * consider frame drops)
+         * 2. timestamps should be monotonically increasing for different requests
+         */
+        if(VERBOSE) Log.v(TAG, "validating Image");
+        byte[] data = getDataFromImage(image);
+        assertTrue("Invalid image data", data != null && data.length > 0);
+
+        switch (format) {
+            case ImageFormat.JPEG:
+                validateJpegData(data, width, height, filePath);
+                break;
+            case ImageFormat.YUV_420_888:
+                validateYuvData(data, width, height, format, image.getTimestamp(), filePath);
+                break;
+            case ImageFormat.RAW_SENSOR:
+                validateRaw16Data(data, width, height, format, image.getTimestamp(), filePath);
+                break;
+            default:
+                throw new UnsupportedOperationException("Unsupported format for validation: "
+                        + format);
+        }
+    }
+
+    /**
+     * Provide a mock for {@link CameraDevice.StateCallback}.
+     *
+     * <p>Only useful because mockito can't mock {@link CameraDevice.StateCallback} which is an
+     * abstract class.</p>
+     *
+     * <p>
+     * Use this instead of other classes when needing to verify interactions, since
+     * trying to spy on {@link BlockingStateCallback} (or others) will cause unnecessary extra
+     * interactions which will cause false test failures.
+     * </p>
+     *
+     */
+    public static class MockStateCallback extends CameraDevice.StateCallback {
+
+        @Override
+        public void onOpened(CameraDevice camera) {
+        }
+
+        @Override
+        public void onDisconnected(CameraDevice camera) {
+        }
+
+        @Override
+        public void onError(CameraDevice camera, int error) {
+        }
+
+        private MockStateCallback() {}
+
+        /**
+         * Create a Mockito-ready mocked StateCallback.
+         */
+        public static MockStateCallback mock() {
+            return Mockito.spy(new MockStateCallback());
+        }
+    }
+
+    private static void validateJpegData(byte[] jpegData, int width, int height, String filePath) {
+        BitmapFactory.Options bmpOptions = new BitmapFactory.Options();
+        // DecodeBound mode: only parse the frame header to get width/height.
+        // it doesn't decode the pixel.
+        bmpOptions.inJustDecodeBounds = true;
+        BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, bmpOptions);
+        assertEquals(width, bmpOptions.outWidth);
+        assertEquals(height, bmpOptions.outHeight);
+
+        // Pixel decoding mode: decode whole image. check if the image data
+        // is decodable here.
+        assertNotNull("Decoding jpeg failed",
+                BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length));
+        if (DEBUG && filePath != null) {
+            String fileName =
+                    filePath + "/" + width + "x" + height + ".jpeg";
+            dumpFile(fileName, jpegData);
+        }
+    }
+
+    private static void validateYuvData(byte[] yuvData, int width, int height, int format,
+            long ts, String filePath) {
+        checkYuvFormat(format);
+        if (VERBOSE) Log.v(TAG, "Validating YUV data");
+        int expectedSize = width * height * ImageFormat.getBitsPerPixel(format) / 8;
+        assertEquals("Yuv data doesn't match", expectedSize, yuvData.length);
+
+        // TODO: Can add data validation for test pattern.
+
+        if (DEBUG && filePath != null) {
+            String fileName =
+                    filePath + "/" + width + "x" + height + "_" + ts / 1e6 + ".yuv";
+            dumpFile(fileName, yuvData);
+        }
+    }
+
+    private static void validateRaw16Data(byte[] rawData, int width, int height, int format,
+            long ts, String filePath) {
+        if (VERBOSE) Log.v(TAG, "Validating raw data");
+        int expectedSize = width * height * ImageFormat.getBitsPerPixel(format) / 8;
+        assertEquals("Yuv data doesn't match", expectedSize, rawData.length);
+
+        // TODO: Can add data validation for test pattern.
+
+        if (DEBUG && filePath != null) {
+            String fileName =
+                    filePath + "/" + width + "x" + height + "_" + ts / 1e6 + ".raw16";
+            dumpFile(fileName, rawData);
+        }
+
+        return;
+    }
+
+    public static <T> T getValueNotNull(CaptureResult result, CaptureResult.Key<T> key) {
+        if (result == null) {
+            throw new IllegalArgumentException("Result must not be null");
+        }
+
+        T value = result.get(key);
+        assertNotNull("Value of Key " + key.getName() + "shouldn't be null", value);
+        return value;
+    }
+
+    /**
+     * Get a crop region for a given zoom factor and center position.
+     * <p>
+     * The center position is normalized position in range of [0, 1.0], where
+     * (0, 0) represents top left corner, (1.0. 1.0) represents bottom right
+     * corner. The center position could limit the effective minimal zoom
+     * factor, for example, if the center position is (0.75, 0.75), the
+     * effective minimal zoom position becomes 2.0. If the requested zoom factor
+     * is smaller than 2.0, a crop region with 2.0 zoom factor will be returned.
+     * </p>
+     * <p>
+     * The aspect ratio of the crop region is maintained the same as the aspect
+     * ratio of active array.
+     * </p>
+     *
+     * @param zoomFactor The zoom factor to generate the crop region, it must be
+     *            >= 1.0
+     * @param center The normalized zoom center point that is in the range of [0, 1].
+     * @param maxZoom The max zoom factor supported by this device.
+     * @param activeArray The active array size of this device.
+     * @return crop region for the given normalized center and zoom factor.
+     */
+    public static Rect getCropRegionForZoom(float zoomFactor, final PointF center,
+            final float maxZoom, final Rect activeArray) {
+        if (zoomFactor < 1.0) {
+            throw new IllegalArgumentException("zoom factor " + zoomFactor + " should be >= 1.0");
+        }
+        if (center.x > 1.0 || center.x < 0) {
+            throw new IllegalArgumentException("center.x " + center.x
+                    + " should be in range of [0, 1.0]");
+        }
+        if (center.y > 1.0 || center.y < 0) {
+            throw new IllegalArgumentException("center.y " + center.y
+                    + " should be in range of [0, 1.0]");
+        }
+        if (maxZoom < 1.0) {
+            throw new IllegalArgumentException("max zoom factor " + maxZoom + " should be >= 1.0");
+        }
+        if (activeArray == null) {
+            throw new IllegalArgumentException("activeArray must not be null");
+        }
+
+        float minCenterLength = Math.min(Math.min(center.x, 1.0f - center.x),
+                Math.min(center.y, 1.0f - center.y));
+        float minEffectiveZoom =  0.5f / minCenterLength;
+        if (minEffectiveZoom > maxZoom) {
+            throw new IllegalArgumentException("Requested center " + center.toString() +
+                    " has minimal zoomable factor " + minEffectiveZoom + ", which exceeds max"
+                            + " zoom factor " + maxZoom);
+        }
+
+        if (zoomFactor < minEffectiveZoom) {
+            Log.w(TAG, "Requested zoomFactor " + zoomFactor + " > minimal zoomable factor "
+                    + minEffectiveZoom + ". It will be overwritten by " + minEffectiveZoom);
+            zoomFactor = minEffectiveZoom;
+        }
+
+        int cropCenterX = (int)(activeArray.width() * center.x);
+        int cropCenterY = (int)(activeArray.height() * center.y);
+        int cropWidth = (int) (activeArray.width() / zoomFactor);
+        int cropHeight = (int) (activeArray.height() / zoomFactor);
+
+        return new Rect(
+                /*left*/cropCenterX - cropWidth / 2,
+                /*top*/cropCenterY - cropHeight / 2,
+                /*right*/ cropCenterX + cropWidth / 2 - 1,
+                /*bottom*/cropCenterY + cropHeight / 2 - 1);
+    }
+
+    /**
+     * Calculate output 3A region from the intersection of input 3A region and cropped region.
+     *
+     * @param requestRegions The input 3A regions
+     * @param cropRect The cropped region
+     * @return expected 3A regions output in capture result
+     */
+    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
new file mode 100644
index 0000000..5346ae1
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
@@ -0,0 +1,2251 @@
+/*
+ * 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 static android.hardware.camera2.cts.CameraTestUtils.*;
+import static android.hardware.camera2.CameraCharacteristics.*;
+
+import android.graphics.Point;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraMetadata;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.cts.CameraTestUtils.SimpleCaptureCallback;
+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;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * <p>
+ * Basic test for camera CaptureRequest key controls.
+ * </p>
+ * <p>
+ * Several test categories are covered: manual sensor control, 3A control,
+ * manual ISP control and other per-frame control and synchronization.
+ * </p>
+ */
+public class CaptureRequestTest extends Camera2SurfaceViewTestCase {
+    private static final String TAG = "CaptureRequestTest";
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+    private static final int NUM_FRAMES_VERIFIED = 15;
+    private static final int NUM_FACE_DETECTION_FRAMES_VERIFIED = 60;
+    /** 30ms exposure time must be supported by full capability devices. */
+    private static final long DEFAULT_EXP_TIME_NS = 30000000L;
+    private static final int DEFAULT_SENSITIVITY = 100;
+    private static final int RGGB_COLOR_CHANNEL_COUNT = 4;
+    private static final int MAX_SHADING_MAP_SIZE = 64 * 64 * RGGB_COLOR_CHANNEL_COUNT;
+    private static final int MIN_SHADING_MAP_SIZE = 1 * 1 * RGGB_COLOR_CHANNEL_COUNT;
+    private static final long IGNORE_REQUESTED_EXPOSURE_TIME_CHECK = -1L;
+    private static final long EXPOSURE_TIME_BOUNDARY_50HZ_NS = 10000000L; // 10ms
+    private static final long EXPOSURE_TIME_BOUNDARY_60HZ_NS = 8333333L; // 8.3ms, Approximation.
+    private static final long EXPOSURE_TIME_ERROR_MARGIN_NS = 100000L; // 100us, Approximation.
+    private static final int SENSITIVITY_ERROR_MARGIN = 10; // 10
+    private static final int DEFAULT_NUM_EXPOSURE_TIME_STEPS = 3;
+    private static final int DEFAULT_NUM_SENSITIVITY_STEPS = 16;
+    private static final int DEFAULT_SENSITIVITY_STEP_SIZE = 100;
+    private static final int NUM_RESULTS_WAIT_TIMEOUT = 100;
+    private static final int NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY = 8;
+    private static final int NUM_TEST_FOCUS_DISTANCES = 10;
+    // 5 percent error margin for calibrated device
+    private static final float FOCUS_DISTANCE_ERROR_PERCENT_CALIBRATED = 0.05f;
+    // 25 percent error margin for uncalibrated device
+    private static final float FOCUS_DISTANCE_ERROR_PERCENT_UNCALIBRATED = 0.25f;
+    // 10 percent error margin for approximate device
+    private static final float FOCUS_DISTANCE_ERROR_PERCENT_APPROXIMATE = 0.10f;
+    private static final int ANTI_FLICKERING_50HZ = 1;
+    private static final int ANTI_FLICKERING_60HZ = 2;
+
+    // 5 percent error margin for resulting crop regions
+    private static final float CROP_REGION_ERROR_PERCENT_DELTA = 0.05f;
+    // 1 percent error margin for centering the crop region
+    private static final float CROP_REGION_ERROR_PERCENT_CENTERED = 0.01f;
+
+    // Linear tone mapping curve example.
+    private static final float[] TONEMAP_CURVE_LINEAR = {0, 0, 1.0f, 1.0f};
+    // Standard sRGB tone mapping, per IEC 61966-2-1:1999, with 16 control points.
+    private static final float[] TONEMAP_CURVE_SRGB = {
+            0.0000f, 0.0000f, 0.0667f, 0.2864f, 0.1333f, 0.4007f, 0.2000f, 0.4845f,
+            0.2667f, 0.5532f, 0.3333f, 0.6125f, 0.4000f, 0.6652f, 0.4667f, 0.7130f,
+            0.5333f, 0.7569f, 0.6000f, 0.7977f, 0.6667f, 0.8360f, 0.7333f, 0.8721f,
+            0.8000f, 0.9063f, 0.8667f, 0.9389f, 0.9333f, 0.9701f, 1.0000f, 1.0000f
+    };
+    private final Rational ZERO_R = new Rational(0, 1);
+    private final Rational ONE_R = new Rational(1, 1);
+
+    private final int NUM_ALGORITHMS = 3; // AE, AWB and AF
+    private final int INDEX_ALGORITHM_AE = 0;
+    private final int INDEX_ALGORITHM_AWB = 1;
+    private final int INDEX_ALGORITHM_AF = 2;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    /**
+     * Test black level lock when exposure value change.
+     * <p>
+     * When {@link CaptureRequest#BLACK_LEVEL_LOCK} is true in a request, the
+     * camera device should lock the black level. When the exposure values are changed,
+     * the camera may require reset black level Since changes to certain capture
+     * parameters (such as exposure time) may require resetting of black level
+     * compensation. However, the black level must remain locked after exposure
+     * value changes (when requests have lock ON).
+     * </p>
+     */
+    public void testBlackLevelLock() throws Exception {
+        for (int i = 0; i < mCameraIds.length; i++) {
+            try {
+                openDevice(mCameraIds[i]);
+
+                if (!mStaticInfo.isCapabilitySupported(
+                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
+                    continue;
+                }
+
+                SimpleCaptureCallback listener = new SimpleCaptureCallback();
+                CaptureRequest.Builder requestBuilder =
+                        mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+
+                // Start with default manual exposure time, with black level being locked.
+                requestBuilder.set(CaptureRequest.BLACK_LEVEL_LOCK, true);
+                changeExposure(requestBuilder, DEFAULT_EXP_TIME_NS, DEFAULT_SENSITIVITY);
+
+                Size previewSz =
+                        getMaxPreviewSize(mCamera.getId(), mCameraManager, PREVIEW_SIZE_BOUND);
+
+                startPreview(requestBuilder, previewSz, listener);
+                waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+                // No lock OFF state is allowed as the exposure is not changed.
+                verifyBlackLevelLockResults(listener, NUM_FRAMES_VERIFIED, /*maxLockOffCnt*/0);
+
+                // Double the exposure time and gain, with black level still being locked.
+                changeExposure(requestBuilder, DEFAULT_EXP_TIME_NS * 2, DEFAULT_SENSITIVITY * 2);
+                listener = new SimpleCaptureCallback();
+                startPreview(requestBuilder, previewSz, listener);
+                waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+                // Allow at most one lock OFF state as the exposure is changed once.
+                verifyBlackLevelLockResults(listener, NUM_FRAMES_VERIFIED, /*maxLockOffCnt*/1);
+
+                stopPreview();
+            } finally {
+                closeDevice();
+            }
+        }
+    }
+
+    /**
+     * Basic lens shading map request test.
+     * <p>
+     * When {@link CaptureRequest#SHADING_MODE} is set to OFF, no lens shading correction will
+     * be applied by the camera device, and an identity lens shading map data
+     * will be provided if {@link CaptureRequest#STATISTICS_LENS_SHADING_MAP_MODE} is ON.
+     * </p>
+     * <p>
+     * When {@link CaptureRequest#SHADING_MODE} is set to other modes, lens shading correction
+     * will be applied by the camera device. The lens shading map data can be
+     * requested by setting {@link CaptureRequest#STATISTICS_LENS_SHADING_MAP_MODE} to ON.
+     * </p>
+     */
+    public void testLensShadingMap() throws Exception {
+        for (int i = 0; i < mCameraIds.length; i++) {
+            try {
+                openDevice(mCameraIds[i]);
+
+                if (!mStaticInfo.isManualLensShadingMapSupported()) {
+                    continue;
+                }
+
+                SimpleCaptureCallback listener = new SimpleCaptureCallback();
+                CaptureRequest.Builder requestBuilder =
+                        mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+
+                // Shading map mode OFF, lensShadingMapMode ON, camera device
+                // should output unity maps.
+                requestBuilder.set(CaptureRequest.SHADING_MODE, SHADING_MODE_OFF);
+                requestBuilder.set(CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE,
+                        STATISTICS_LENS_SHADING_MAP_MODE_ON);
+
+                Size previewSz =
+                        getMaxPreviewSize(mCamera.getId(), mCameraManager, PREVIEW_SIZE_BOUND);
+
+                listener = new SimpleCaptureCallback();
+                startPreview(requestBuilder, previewSz, listener);
+                waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+                verifyShadingMap(listener, NUM_FRAMES_VERIFIED, SHADING_MODE_OFF);
+
+                // Shading map mode FAST, lensShadingMapMode ON, camera device
+                // should output valid maps.
+                requestBuilder.set(CaptureRequest.SHADING_MODE, SHADING_MODE_FAST);
+
+                listener = new SimpleCaptureCallback();
+                startPreview(requestBuilder, previewSz, listener);
+                waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+                // Allow at most one lock OFF state as the exposure is changed once.
+                verifyShadingMap(listener, NUM_FRAMES_VERIFIED, SHADING_MODE_FAST);
+
+                // Shading map mode HIGH_QUALITY, lensShadingMapMode ON, camera device
+                // should output valid maps.
+                requestBuilder.set(CaptureRequest.SHADING_MODE, SHADING_MODE_HIGH_QUALITY);
+
+                listener = new SimpleCaptureCallback();
+                startPreview(requestBuilder, previewSz, listener);
+                waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+                verifyShadingMap(listener, NUM_FRAMES_VERIFIED, SHADING_MODE_HIGH_QUALITY);
+
+                stopPreview();
+            } finally {
+                closeDevice();
+            }
+        }
+    }
+
+    /**
+     * Test {@link CaptureRequest#CONTROL_AE_ANTIBANDING_MODE} control.
+     * <p>
+     * Test all available anti-banding modes, check if the exposure time adjustment is
+     * correct.
+     * </p>
+     */
+    public void testAntiBandingModes() throws Exception {
+        for (int i = 0; i < mCameraIds.length; i++) {
+            try {
+                openDevice(mCameraIds[i]);
+
+                // Without manual sensor control, exposure time cannot be verified
+                if (!mStaticInfo.isCapabilitySupported(
+                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
+                    return;
+                }
+
+                int[] modes = mStaticInfo.getAeAvailableAntiBandingModesChecked();
+
+                Size previewSz =
+                        getMaxPreviewSize(mCamera.getId(), mCameraManager, PREVIEW_SIZE_BOUND);
+
+                for (int mode : modes) {
+                    antiBandingTestByMode(previewSz, mode);
+                }
+            } finally {
+                closeDevice();
+            }
+        }
+
+    }
+
+    /**
+     * Test AE mode and lock.
+     *
+     * <p>
+     * For AE lock, when it is locked, exposure parameters shouldn't be changed.
+     * For AE modes, each mode should satisfy the per frame controls defined in
+     * API specifications.
+     * </p>
+     */
+    public void testAeModeAndLock() throws Exception {
+        for (int i = 0; i < mCameraIds.length; i++) {
+            try {
+                openDevice(mCameraIds[i]);
+
+                if (mStaticInfo.isHardwareLevelLegacy()) {
+                    Log.i(TAG, "Skipping test on legacy devices");
+                    continue;
+                }
+
+                Size maxPreviewSz = mOrderedPreviewSizes.get(0); // Max preview size.
+
+                // Update preview surface with given size for all sub-tests.
+                updatePreviewSurface(maxPreviewSz);
+
+                // Test aeMode and lock
+                int[] aeModes = mStaticInfo.getAeAvailableModesChecked();
+                for (int mode : aeModes) {
+                    aeModeAndLockTestByMode(mode);
+                }
+            } finally {
+                closeDevice();
+            }
+        }
+    }
+
+    /** Test {@link CaptureRequest#FLASH_MODE} control.
+     * <p>
+     * For each {@link CaptureRequest#FLASH_MODE} mode, test the flash control
+     * and {@link CaptureResult#FLASH_STATE} result.
+     * </p>
+     */
+    public void testFlashControl() throws Exception {
+        for (int i = 0; i < mCameraIds.length; i++) {
+            try {
+                openDevice(mCameraIds[i]);
+
+                SimpleCaptureCallback listener = new SimpleCaptureCallback();
+                CaptureRequest.Builder requestBuilder =
+                        mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+
+                Size maxPreviewSz = mOrderedPreviewSizes.get(0); // Max preview size.
+
+                startPreview(requestBuilder, maxPreviewSz, listener);
+
+                // Flash control can only be used when the AE mode is ON or OFF.
+                flashTestByAeMode(listener, CaptureRequest.CONTROL_AE_MODE_ON);
+
+                // LEGACY won't support AE mode OFF
+                if (mStaticInfo.isHardwareLevelLimitedOrBetter()) {
+                    flashTestByAeMode(listener, CaptureRequest.CONTROL_AE_MODE_OFF);
+                }
+
+                stopPreview();
+            } finally {
+                closeDevice();
+            }
+        }
+    }
+
+    /**
+     * Test face detection modes and results.
+     */
+    public void testFaceDetection() throws Exception {
+        for (int i = 0; i < mCameraIds.length; i++) {
+            try {
+                openDevice(mCameraIds[i]);
+
+                if (mStaticInfo.isHardwareLevelLegacy()) {
+                    Log.i(TAG, "Skipping test on legacy devices");
+                    continue;
+                }
+
+                faceDetectionTestByCamera();
+            } finally {
+                closeDevice();
+            }
+        }
+    }
+
+    /**
+     * Test tone map modes and controls.
+     */
+    public void testToneMapControl() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                openDevice(id);
+                if (!mStaticInfo.isManualToneMapSupported()) {
+                    Log.i(TAG, "Camera " + id +
+                            " doesn't support tone mapping controls, skipping test");
+                    continue;
+                }
+                toneMapTestByCamera();
+            } finally {
+                closeDevice();
+            }
+        }
+    }
+
+    /**
+     * Test color correction modes and controls.
+     */
+    public void testColorCorrectionControl() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                openDevice(id);
+                if (!mStaticInfo.isManualColorCorrectionSupported()) {
+                    Log.i(TAG, "Camera " + id +
+                            " doesn't support color correction controls, skipping test");
+                    continue;
+                }
+                colorCorrectionTestByCamera();
+            } finally {
+                closeDevice();
+            }
+        }
+    }
+
+    public void testEdgeModeControl() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                openDevice(id);
+                if (!mStaticInfo.isEdgeModeControlSupported()) {
+                    Log.i(TAG, "Camera " + id +
+                            " doesn't support EDGE_MODE controls, skipping test");
+                    continue;
+                }
+
+                edgeModesTestByCamera();
+            } finally {
+                closeDevice();
+            }
+        }
+    }
+
+    /**
+     * Test focus distance control.
+     */
+    public void testFocusDistanceControl() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                openDevice(id);
+                if (!mStaticInfo.hasFocuser()) {
+                    Log.i(TAG, "Camera " + id + " has no focuser, skipping test");
+                    continue;
+                }
+
+                if (!mStaticInfo.isCapabilitySupported(
+                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
+                    Log.i(TAG, "Camera " + id +
+                            " does not support MANUAL_SENSOR, skipping test");
+                    continue;
+                }
+
+                focusDistanceTestByCamera();
+            } finally {
+                closeDevice();
+            }
+        }
+    }
+
+    public void testNoiseReductionModeControl() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                openDevice(id);
+                if (!mStaticInfo.isNoiseReductionModeControlSupported()) {
+                    Log.i(TAG, "Camera " + id +
+                            " doesn't support noise reduction mode, skipping test");
+                    continue;
+                }
+
+                noiseReductionModeTestByCamera();
+            } finally {
+                closeDevice();
+            }
+        }
+    }
+
+    /**
+     * Test AWB lock control.
+     *
+     * <p>The color correction gain and transform shouldn't be changed when AWB is locked.</p>
+     */
+    public void testAwbModeAndLock() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                openDevice(id);
+
+                awbModeAndLockTestByCamera();
+            } finally {
+                closeDevice();
+            }
+        }
+    }
+
+    /**
+     * Test different AF modes.
+     */
+    public void testAfModes() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                openDevice(id);
+
+                afModeTestByCamera();
+            } finally {
+                closeDevice();
+            }
+        }
+    }
+
+    /**
+     * Test video and optical stabilizations.
+     */
+    public void testCameraStabilizations() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                openDevice(id);
+                List<Key<?>> keys = mStaticInfo.getCharacteristics().getKeys();
+                if (!(keys.contains(
+                        CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES) ||
+                        keys.contains(
+                                CameraCharacteristics.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION))) {
+                    Log.i(TAG, "Camera " + id + " doesn't support any stabilization modes");
+                    continue;
+                }
+
+                stabilizationTestByCamera();
+            } finally {
+                closeDevice();
+            }
+        }
+    }
+
+    /**
+     * 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) {
+            try {
+                openDevice(id);
+
+                Size maxPreviewSize = mOrderedPreviewSizes.get(0);
+                digitalZoomTestByCamera(maxPreviewSize);
+            } finally {
+                closeDevice();
+            }
+        }
+    }
+
+    /**
+     * 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);
+
+                digitalZoomPreviewCombinationTestByCamera();
+            } finally {
+                closeDevice();
+            }
+        }
+    }
+
+    /**
+     * Test scene mode controls.
+     */
+    public void testSceneModes() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                openDevice(id);
+
+                sceneModeTestByCamera();
+            } finally {
+                closeDevice();
+            }
+        }
+    }
+
+    /**
+     * Test effect mode controls.
+     */
+    public void testEffectModes() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                openDevice(id);
+
+                effectModeTestByCamera();
+            } finally {
+                closeDevice();
+            }
+        }
+    }
+
+    // TODO: add 3A state machine test.
+
+    private void noiseReductionModeTestByCamera() throws Exception {
+        Size maxPrevSize = mOrderedPreviewSizes.get(0);
+        CaptureRequest.Builder requestBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        int[] availableModes = mStaticInfo.getAvailableNoiseReductionModesChecked();
+        SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
+        startPreview(requestBuilder, maxPrevSize, resultListener);
+
+        for (int mode : availableModes) {
+            requestBuilder.set(CaptureRequest.NOISE_REDUCTION_MODE, mode);
+            resultListener = new SimpleCaptureCallback();
+            mSession.setRepeatingRequest(requestBuilder.build(), resultListener, mHandler);
+            waitForSettingsApplied(resultListener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+
+            verifyCaptureResultForKey(CaptureResult.NOISE_REDUCTION_MODE, mode,
+                    resultListener, NUM_FRAMES_VERIFIED);
+
+            // Test that OFF and FAST mode should not slow down the frame rate.
+            if (mode == CaptureRequest.NOISE_REDUCTION_MODE_OFF ||
+                    mode == CaptureRequest.NOISE_REDUCTION_MODE_FAST) {
+                verifyFpsNotSlowDown(requestBuilder, NUM_FRAMES_VERIFIED);
+            }
+        }
+
+        stopPreview();
+    }
+
+    private void focusDistanceTestByCamera() throws Exception {
+        Size maxPrevSize = mOrderedPreviewSizes.get(0);
+        float[] testDistances = getFocusDistanceTestValuesInOrder();
+        CaptureRequest.Builder requestBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        requestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF);
+        SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
+        startPreview(requestBuilder, maxPrevSize, resultListener);
+
+        CaptureRequest request;
+        float[] resultDistances = new float[testDistances.length];
+        for (int i = 0; i < testDistances.length; i++) {
+            requestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, testDistances[i]);
+            request = requestBuilder.build();
+            resultListener = new SimpleCaptureCallback();
+            mSession.setRepeatingRequest(request, resultListener, mHandler);
+            waitForSettingsApplied(resultListener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+            resultDistances[i] = verifyFocusDistanceControl(testDistances[i], request,
+                    resultListener);
+            if (VERBOSE) {
+                Log.v(TAG, "Capture request focus distance: " + testDistances[i] + " result: "
+                        + resultDistances[i]);
+            }
+        }
+
+        // Verify the monotonicity
+        mCollector.checkArrayMonotonicityAndNotAllEqual(CameraTestUtils.toObject(resultDistances),
+                /*ascendingOrder*/true);
+
+        if (mStaticInfo.getCharacteristics().getKeys().
+                contains(CameraCharacteristics.LENS_INFO_HYPERFOCAL_DISTANCE)) {
+
+            // Test hyperfocal distance optionally
+            float hyperFocalDistance = mStaticInfo.getHyperfocalDistanceChecked();
+            if (hyperFocalDistance > 0) {
+                requestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, hyperFocalDistance);
+                request = requestBuilder.build();
+                resultListener = new SimpleCaptureCallback();
+                mSession.setRepeatingRequest(request, resultListener, mHandler);
+                waitForSettingsApplied(resultListener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+
+                // Then wait for the lens.state to be stationary.
+                waitForResultValue(resultListener, CaptureResult.LENS_STATE,
+                        CaptureResult.LENS_STATE_STATIONARY, NUM_RESULTS_WAIT_TIMEOUT);
+                // Need get reasonably accurate value.
+                CaptureResult result = resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+                Float focusDistance = getValueNotNull(result, CaptureResult.LENS_FOCUS_DISTANCE);
+                float errorMargin = FOCUS_DISTANCE_ERROR_PERCENT_UNCALIBRATED;
+                int calibrationStatus = mStaticInfo.getFocusDistanceCalibrationChecked();
+                if (calibrationStatus ==
+                        CameraMetadata.LENS_INFO_FOCUS_DISTANCE_CALIBRATION_CALIBRATED) {
+                    errorMargin = FOCUS_DISTANCE_ERROR_PERCENT_CALIBRATED;
+                } else if (calibrationStatus ==
+                        CameraMetadata.LENS_INFO_FOCUS_DISTANCE_CALIBRATION_APPROXIMATE) {
+                    errorMargin = FOCUS_DISTANCE_ERROR_PERCENT_APPROXIMATE;
+                }
+                mCollector.expectInRange("Focus distance for hyper focal should be close enough to" +
+                                "requested value", focusDistance,
+                        hyperFocalDistance * (1.0f - errorMargin),
+                        hyperFocalDistance * (1.0f + errorMargin)
+                );
+            }
+        }
+    }
+
+    /**
+     * Verify focus distance control.
+     *
+     * @param distance The focus distance requested
+     * @param request The capture request to control the manual focus distance
+     * @param resultListener The capture listener to recieve capture result callbacks
+     * @return the result focus distance
+     */
+    private float verifyFocusDistanceControl(float distance, CaptureRequest request,
+            SimpleCaptureCallback resultListener) {
+        // Need make sure the result corresponding to the request is back, then check.
+        CaptureResult result =
+                resultListener.getCaptureResultForRequest(request, NUM_RESULTS_WAIT_TIMEOUT);
+        // Then wait for the lens.state to be stationary.
+        waitForResultValue(resultListener, CaptureResult.LENS_STATE,
+                CaptureResult.LENS_STATE_STATIONARY, NUM_RESULTS_WAIT_TIMEOUT);
+        // Then check the focus distance.
+        result = resultListener.getCaptureResultForRequest(request, NUM_RESULTS_WAIT_TIMEOUT);
+        Float resultDistance = getValueNotNull(result, CaptureResult.LENS_FOCUS_DISTANCE);
+        if (mStaticInfo.getFocusDistanceCalibrationChecked() ==
+                CameraCharacteristics.LENS_INFO_FOCUS_DISTANCE_CALIBRATION_CALIBRATED) {
+            // TODO: what's more to test for CALIBRATED devices?
+        }
+
+        float minValue = 0;
+        float maxValue = mStaticInfo.getMinimumFocusDistanceChecked();
+        mCollector.expectInRange("Result focus distance is out of range",
+                resultDistance, minValue, maxValue);
+
+        return resultDistance;
+    }
+
+    /**
+     * Verify edge mode control results.
+     */
+    private void edgeModesTestByCamera() throws Exception {
+        Size maxPrevSize = mOrderedPreviewSizes.get(0);
+        int[] edgeModes = mStaticInfo.getAvailableEdgeModesChecked();
+        CaptureRequest.Builder requestBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
+        startPreview(requestBuilder, maxPrevSize, resultListener);
+
+        for (int mode : edgeModes) {
+            requestBuilder.set(CaptureRequest.EDGE_MODE, mode);
+            resultListener = new SimpleCaptureCallback();
+            mSession.setRepeatingRequest(requestBuilder.build(), resultListener, mHandler);
+            waitForSettingsApplied(resultListener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+
+            verifyCaptureResultForKey(CaptureResult.EDGE_MODE, mode, resultListener,
+                    NUM_FRAMES_VERIFIED);
+
+            // Test that OFF and FAST mode should not slow down the frame rate.
+            if (mode == CaptureRequest.EDGE_MODE_OFF ||
+                    mode == CaptureRequest.EDGE_MODE_FAST) {
+                verifyFpsNotSlowDown(requestBuilder, NUM_FRAMES_VERIFIED);
+            }
+        }
+
+        stopPreview();
+    }
+
+    /**
+     * Test color correction controls.
+     *
+     * <p>Test different color correction modes. For TRANSFORM_MATRIX, only test
+     * the unit gain and identity transform.</p>
+     */
+    private void colorCorrectionTestByCamera() throws Exception {
+        CaptureRequest request;
+        CaptureResult result;
+        Size maxPreviewSz = mOrderedPreviewSizes.get(0); // Max preview size.
+        updatePreviewSurface(maxPreviewSz);
+        CaptureRequest.Builder manualRequestBuilder = createRequestForPreview();
+        CaptureRequest.Builder previewRequestBuilder = createRequestForPreview();
+        SimpleCaptureCallback listener = new SimpleCaptureCallback();
+
+        startPreview(previewRequestBuilder, maxPreviewSz, listener);
+
+        // Default preview result should give valid color correction metadata.
+        result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+        validateColorCorrectionResult(result,
+                previewRequestBuilder.get(CaptureRequest.COLOR_CORRECTION_MODE));
+
+        // TRANSFORM_MATRIX mode
+        // Only test unit gain and 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, colorCorrectionMode);
+        manualRequestBuilder.set(CaptureRequest.COLOR_CORRECTION_GAINS, UNIT_GAIN);
+        manualRequestBuilder.set(CaptureRequest.COLOR_CORRECTION_TRANSFORM, IDENTITY_TRANSFORM);
+        request = manualRequestBuilder.build();
+        mSession.capture(request, listener, mHandler);
+        result = listener.getCaptureResultForRequest(request, NUM_RESULTS_WAIT_TIMEOUT);
+        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",
+                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, colorCorrectionMode);
+        request = manualRequestBuilder.build();
+        mSession.capture(request, listener, mHandler);
+        result = listener.getCaptureResultForRequest(request, NUM_RESULTS_WAIT_TIMEOUT);
+        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, colorCorrectionMode);
+        request = manualRequestBuilder.build();
+        mSession.capture(request, listener, mHandler);
+        result = listener.getCaptureResultForRequest(request, NUM_RESULTS_WAIT_TIMEOUT);
+        validateColorCorrectionResult(result, colorCorrectionMode);
+        mCollector.expectEquals("control mode result/request mismatch",
+                CaptureResult.CONTROL_MODE_AUTO, result.get(CaptureResult.CONTROL_MODE));
+    }
+
+    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);
+
+        RggbChannelVector resultGain;
+        if ((resultGain = mCollector.expectKeyValueNotNull(result,
+                CaptureResult.COLOR_CORRECTION_GAINS)) != null) {
+            mCollector.expectKeyValueNotEquals(result,
+                    CaptureResult.COLOR_CORRECTION_GAINS, ZERO_GAINS);
+        }
+
+        ColorSpaceTransform resultTransform;
+        if ((resultTransform = mCollector.expectKeyValueNotNull(result,
+                CaptureResult.COLOR_CORRECTION_TRANSFORM)) != null) {
+            mCollector.expectKeyValueNotEquals(result,
+                    CaptureResult.COLOR_CORRECTION_TRANSFORM, ZERO_TRANSFORM);
+        }
+
+        mCollector.expectEquals("color correction mode result/request mismatch",
+                colorCorrectionMode, result.get(CaptureResult.COLOR_CORRECTION_MODE));
+    }
+
+    /**
+     * Test flash mode control by AE mode.
+     * <p>
+     * Only allow AE mode ON or OFF, because other AE mode could run into conflict with
+     * flash manual control. This function expects the camera to already have an active
+     * repeating request and be sending results to the listener.
+     * </p>
+     *
+     * @param listener The Capture listener that is used to wait for capture result
+     * @param aeMode The AE mode for flash to test with
+     */
+    private void flashTestByAeMode(SimpleCaptureCallback listener, int aeMode) throws Exception {
+        CaptureResult result;
+        final int NUM_FLASH_REQUESTS_TESTED = 10;
+        CaptureRequest.Builder requestBuilder = createRequestForPreview();
+
+        if (aeMode == CaptureRequest.CONTROL_AE_MODE_ON) {
+            requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, aeMode);
+        } else if (aeMode == CaptureRequest.CONTROL_AE_MODE_OFF) {
+            changeExposure(requestBuilder, DEFAULT_EXP_TIME_NS, DEFAULT_SENSITIVITY);
+        } else {
+            throw new IllegalArgumentException("This test only works when AE mode is ON or OFF");
+        }
+
+        mSession.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
+        waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+
+        // For camera that doesn't have flash unit, flash state should always be UNAVAILABLE.
+        if (mStaticInfo.getFlashInfoChecked() == false) {
+            for (int i = 0; i < NUM_FLASH_REQUESTS_TESTED; i++) {
+                result = listener.getCaptureResult(CAPTURE_RESULT_TIMEOUT_MS);
+                mCollector.expectEquals("No flash unit available, flash state must be UNAVAILABLE"
+                        + "for AE mode " + aeMode, CaptureResult.FLASH_STATE_UNAVAILABLE,
+                        result.get(CaptureResult.FLASH_STATE));
+            }
+
+            return;
+        }
+
+        // Test flash SINGLE mode control. Wait for flash state to be READY first.
+        if (mStaticInfo.isHardwareLevelLimitedOrBetter()) {
+            waitForResultValue(listener, CaptureResult.FLASH_STATE, CaptureResult.FLASH_STATE_READY,
+                    NUM_RESULTS_WAIT_TIMEOUT);
+        } // else the settings were already waited on earlier
+
+        requestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_SINGLE);
+        CaptureRequest flashSinglerequest = requestBuilder.build();
+
+        int flashModeSingleRequests = captureRequestsSynchronized(
+                flashSinglerequest, listener, mHandler);
+        waitForNumResults(listener, flashModeSingleRequests - 1);
+        result = listener.getCaptureResultForRequest(flashSinglerequest, NUM_RESULTS_WAIT_TIMEOUT);
+        // Result mode must be SINGLE, state must be FIRED.
+        mCollector.expectEquals("Flash mode result must be SINGLE",
+                CaptureResult.FLASH_MODE_SINGLE, result.get(CaptureResult.FLASH_MODE));
+        mCollector.expectEquals("Flash state result must be FIRED",
+                CaptureResult.FLASH_STATE_FIRED, result.get(CaptureResult.FLASH_STATE));
+
+        // Test flash TORCH mode control.
+        requestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
+        CaptureRequest torchRequest = requestBuilder.build();
+
+        int flashModeTorchRequests = captureRequestsSynchronized(torchRequest,
+                NUM_FLASH_REQUESTS_TESTED, listener, mHandler);
+        waitForNumResults(listener, flashModeTorchRequests - NUM_FLASH_REQUESTS_TESTED);
+
+        // Verify the results
+        for (int i = 0; i < NUM_FLASH_REQUESTS_TESTED; i++) {
+            result = listener.getCaptureResultForRequest(torchRequest,
+                    NUM_RESULTS_WAIT_TIMEOUT);
+
+            // Result mode must be TORCH, state must be FIRED
+            mCollector.expectEquals("Flash mode result must be TORCH",
+                    CaptureResult.FLASH_MODE_TORCH, result.get(CaptureResult.FLASH_MODE));
+            mCollector.expectEquals("Flash state result must be FIRED",
+                    CaptureResult.FLASH_STATE_FIRED, result.get(CaptureResult.FLASH_STATE));
+        }
+
+        // Test flash OFF mode control
+        requestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
+        CaptureRequest flashOffrequest = requestBuilder.build();
+
+        int flashModeOffRequests = captureRequestsSynchronized(flashOffrequest, listener, mHandler);
+        waitForNumResults(listener, flashModeOffRequests - 1);
+        result = listener.getCaptureResultForRequest(flashOffrequest, NUM_RESULTS_WAIT_TIMEOUT);
+        mCollector.expectEquals("Flash mode result must be OFF", CaptureResult.FLASH_MODE_OFF,
+                result.get(CaptureResult.FLASH_MODE));
+    }
+
+    private void verifyAntiBandingMode(SimpleCaptureCallback listener, int numFramesVerified,
+            int mode, boolean isAeManual, long requestExpTime) throws Exception {
+        // Skip the first a couple of frames as antibanding may not be fully up yet.
+        final int NUM_FRAMES_SKIPPED = 5;
+        for (int i = 0; i < NUM_FRAMES_SKIPPED; i++) {
+            listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+        }
+
+        for (int i = 0; i < numFramesVerified; i++) {
+            CaptureResult result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+            Long resultExpTime = result.get(CaptureResult.SENSOR_EXPOSURE_TIME);
+            assertNotNull("Exposure time shouldn't be null", resultExpTime);
+            Integer flicker = result.get(CaptureResult.STATISTICS_SCENE_FLICKER);
+            // Scene flicker result should be always available.
+            assertNotNull("Scene flicker must not be null", flicker);
+            assertTrue("Scene flicker is invalid", flicker >= STATISTICS_SCENE_FLICKER_NONE &&
+                    flicker <= STATISTICS_SCENE_FLICKER_60HZ);
+
+            if (isAeManual) {
+                // First, round down not up, second, need close enough.
+                validateExposureTime(requestExpTime, resultExpTime);
+                return;
+            }
+
+            long expectedExpTime = resultExpTime; // Default, no exposure adjustment.
+            if (mode == CONTROL_AE_ANTIBANDING_MODE_50HZ) {
+                // result exposure time must be adjusted by 50Hz illuminant source.
+                expectedExpTime =
+                        getAntiFlickeringExposureTime(ANTI_FLICKERING_50HZ, resultExpTime);
+            } else if (mode == CONTROL_AE_ANTIBANDING_MODE_60HZ) {
+                // result exposure time must be adjusted by 60Hz illuminant source.
+                expectedExpTime =
+                        getAntiFlickeringExposureTime(ANTI_FLICKERING_60HZ, resultExpTime);
+            } else if (mode == CONTROL_AE_ANTIBANDING_MODE_AUTO){
+                /**
+                 * Use STATISTICS_SCENE_FLICKER to tell the illuminant source
+                 * and do the exposure adjustment.
+                 */
+                expectedExpTime = resultExpTime;
+                if (flicker == STATISTICS_SCENE_FLICKER_60HZ) {
+                    expectedExpTime =
+                            getAntiFlickeringExposureTime(ANTI_FLICKERING_60HZ, resultExpTime);
+                } else if (flicker == STATISTICS_SCENE_FLICKER_50HZ) {
+                    expectedExpTime =
+                            getAntiFlickeringExposureTime(ANTI_FLICKERING_50HZ, resultExpTime);
+                }
+            }
+
+            if (Math.abs(resultExpTime - expectedExpTime) > EXPOSURE_TIME_ERROR_MARGIN_NS) {
+                mCollector.addMessage(String.format("Result exposure time %dns diverges too much"
+                        + " from expected exposure time %dns for mode %d when AE is auto",
+                        resultExpTime, expectedExpTime, mode));
+            }
+        }
+    }
+
+    private void antiBandingTestByMode(Size size, int mode)
+            throws Exception {
+        if(VERBOSE) {
+            Log.v(TAG, "Anti-banding test for mode " + mode + " for camera " + mCamera.getId());
+        }
+        CaptureRequest.Builder requestBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+
+        requestBuilder.set(CaptureRequest.CONTROL_AE_ANTIBANDING_MODE, mode);
+
+        // Test auto AE mode anti-banding behavior
+        SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
+        startPreview(requestBuilder, size, resultListener);
+        waitForSettingsApplied(resultListener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+        verifyAntiBandingMode(resultListener, NUM_FRAMES_VERIFIED, mode, /*isAeManual*/false,
+                IGNORE_REQUESTED_EXPOSURE_TIME_CHECK);
+
+        // Test manual AE mode anti-banding behavior
+        // 65ms, must be supported by full capability devices.
+        final long TEST_MANUAL_EXP_TIME_NS = 65000000L;
+        long manualExpTime = mStaticInfo.getExposureClampToRange(TEST_MANUAL_EXP_TIME_NS);
+        changeExposure(requestBuilder, manualExpTime);
+        resultListener = new SimpleCaptureCallback();
+        startPreview(requestBuilder, size, resultListener);
+        waitForSettingsApplied(resultListener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+        verifyAntiBandingMode(resultListener, NUM_FRAMES_VERIFIED, mode, /*isAeManual*/true,
+                manualExpTime);
+
+        stopPreview();
+    }
+
+    /**
+     * Test the all available AE modes and AE lock.
+     * <p>
+     * For manual AE mode, test iterates through different sensitivities and
+     * exposure times, validate the result exposure time correctness. For
+     * CONTROL_AE_MODE_ON_ALWAYS_FLASH mode, the AE lock and flash are tested.
+     * For the rest of the AUTO mode, AE lock is tested.
+     * </p>
+     *
+     * @param mode
+     */
+    private void aeModeAndLockTestByMode(int mode)
+            throws Exception {
+        switch (mode) {
+            case CONTROL_AE_MODE_OFF:
+                if (mStaticInfo.isCapabilitySupported(
+                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
+                    // Test manual exposure control.
+                    aeManualControlTest();
+                } else {
+                    Log.w(TAG,
+                            "aeModeAndLockTestByMode - can't test AE mode OFF without " +
+                            "manual sensor control");
+                }
+                break;
+            case CONTROL_AE_MODE_ON:
+            case CONTROL_AE_MODE_ON_AUTO_FLASH:
+            case CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE:
+            case CONTROL_AE_MODE_ON_ALWAYS_FLASH:
+                // Test AE lock for above AUTO modes.
+                aeAutoModeTestLock(mode);
+                break;
+            default:
+                throw new UnsupportedOperationException("Unhandled AE mode " + mode);
+        }
+    }
+
+    /**
+     * Test AE auto modes.
+     * <p>
+     * Use single request rather than repeating request to test AE lock per frame control.
+     * </p>
+     */
+    private void aeAutoModeTestLock(int mode) throws Exception {
+        CaptureRequest.Builder requestBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        requestBuilder.set(CaptureRequest.CONTROL_AE_LOCK, false);
+        requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, mode);
+        configurePreviewOutput(requestBuilder);
+
+        final int MAX_NUM_CAPTURES_DURING_LOCK = 5;
+        for (int i = 1; i <= MAX_NUM_CAPTURES_DURING_LOCK; i++) {
+            autoAeMultipleCapturesThenTestLock(requestBuilder, mode, i);
+        }
+    }
+
+    /**
+     * Issue multiple auto AE captures, then lock AE, validate the AE lock vs.
+     * the first capture result after the AE lock. The right AE lock behavior is:
+     * When it is locked, it locks to the current exposure value, and all subsequent
+     * request with lock ON will have the same exposure value locked.
+     */
+    private void autoAeMultipleCapturesThenTestLock(
+            CaptureRequest.Builder requestBuilder, int aeMode, int numCapturesDuringLock)
+            throws Exception {
+        if (numCapturesDuringLock < 1) {
+            throw new IllegalArgumentException("numCapturesBeforeLock must be no less than 1");
+        }
+        if (VERBOSE) {
+            Log.v(TAG, "Camera " + mCamera.getId() + ": Testing auto AE mode and lock for mode "
+                    + aeMode + " with " + numCapturesDuringLock + " captures before lock");
+        }
+
+        final int NUM_CAPTURES_BEFORE_LOCK = 2;
+        SimpleCaptureCallback listener =  new SimpleCaptureCallback();
+
+        CaptureResult[] resultsDuringLock = new CaptureResult[numCapturesDuringLock];
+
+        // Reset the AE lock to OFF, since we are reusing this builder many times
+        requestBuilder.set(CaptureRequest.CONTROL_AE_LOCK, false);
+
+        // Just send several captures with auto AE, lock off.
+        CaptureRequest request = requestBuilder.build();
+        for (int i = 0; i < NUM_CAPTURES_BEFORE_LOCK; i++) {
+            mSession.capture(request, listener, mHandler);
+        }
+        waitForNumResults(listener, NUM_CAPTURES_BEFORE_LOCK);
+
+        // Then fire several capture to lock the AE.
+        requestBuilder.set(CaptureRequest.CONTROL_AE_LOCK, true);
+
+        int requestCount = captureRequestsSynchronized(
+                requestBuilder.build(), numCapturesDuringLock, listener, mHandler);
+
+        int[] sensitivities = new int[numCapturesDuringLock];
+        long[] expTimes = new long[numCapturesDuringLock];
+        Arrays.fill(sensitivities, -1);
+        Arrays.fill(expTimes, -1L);
+
+        // Get the AE lock on result and validate the exposure values.
+        waitForNumResults(listener, requestCount - numCapturesDuringLock);
+        for (int i = 0; i < resultsDuringLock.length; i++) {
+            resultsDuringLock[i] = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+        }
+
+        for (int i = 0; i < numCapturesDuringLock; i++) {
+            mCollector.expectKeyValueEquals(
+                    resultsDuringLock[i], CaptureResult.CONTROL_AE_LOCK, true);
+        }
+
+        // Can't read manual sensor/exposure settings without manual sensor
+        if (mStaticInfo.isCapabilitySupported(
+                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
+            int sensitivityLocked =
+                    getValueNotNull(resultsDuringLock[0], CaptureResult.SENSOR_SENSITIVITY);
+            long expTimeLocked =
+                    getValueNotNull(resultsDuringLock[0], CaptureResult.SENSOR_EXPOSURE_TIME);
+            for (int i = 1; i < resultsDuringLock.length; i++) {
+                mCollector.expectKeyValueEquals(
+                        resultsDuringLock[i], CaptureResult.SENSOR_EXPOSURE_TIME, expTimeLocked);
+                mCollector.expectKeyValueEquals(
+                        resultsDuringLock[i], CaptureResult.SENSOR_SENSITIVITY, sensitivityLocked);
+            }
+        }
+    }
+
+    /**
+     * Iterate through exposure times and sensitivities for manual AE control.
+     * <p>
+     * Use single request rather than repeating request to test manual exposure
+     * value change per frame control.
+     * </p>
+     */
+    private void aeManualControlTest()
+            throws Exception {
+        CaptureRequest.Builder requestBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+
+        requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CONTROL_AE_MODE_OFF);
+        configurePreviewOutput(requestBuilder);
+        SimpleCaptureCallback listener =  new SimpleCaptureCallback();
+
+        long[] expTimes = getExposureTimeTestValues();
+        int[] sensitivities = getSensitivityTestValues();
+        // Submit single request at a time, then verify the result.
+        for (int i = 0; i < expTimes.length; i++) {
+            for (int j = 0; j < sensitivities.length; j++) {
+                if (VERBOSE) {
+                    Log.v(TAG, "Camera " + mCamera.getId() + ": Testing sensitivity "
+                            + sensitivities[j] + ", exposure time " + expTimes[i] + "ns");
+                }
+
+                changeExposure(requestBuilder, expTimes[i], sensitivities[j]);
+                mSession.capture(requestBuilder.build(), listener, mHandler);
+
+                CaptureResult result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+                long resultExpTime = getValueNotNull(result, CaptureResult.SENSOR_EXPOSURE_TIME);
+                int resultSensitivity = getValueNotNull(result, CaptureResult.SENSOR_SENSITIVITY);
+                validateExposureTime(expTimes[i], resultExpTime);
+                validateSensitivity(sensitivities[j], resultSensitivity);
+                validateFrameDurationForCapture(result);
+            }
+        }
+        // TODO: Add another case to test where we can submit all requests, then wait for
+        // results, which will hide the pipeline latency. this is not only faster, but also
+        // test high speed per frame control and synchronization.
+    }
+
+
+    /**
+     * Verify black level lock control.
+     */
+    private void verifyBlackLevelLockResults(SimpleCaptureCallback listener, int numFramesVerified,
+            int maxLockOffCnt) throws Exception {
+        int noLockCnt = 0;
+        for (int i = 0; i < numFramesVerified; i++) {
+            CaptureResult result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+            Boolean blackLevelLock = result.get(CaptureResult.BLACK_LEVEL_LOCK);
+            assertNotNull("Black level lock result shouldn't be null", blackLevelLock);
+
+            // Count the lock == false result, which could possibly occur at most once.
+            if (blackLevelLock == false) {
+                noLockCnt++;
+            }
+
+            if(VERBOSE) {
+                Log.v(TAG, "Black level lock result: " + blackLevelLock);
+            }
+        }
+        assertTrue("Black level lock OFF occurs " + noLockCnt + " times,  expect at most "
+                + maxLockOffCnt + " for camera " + mCamera.getId(), noLockCnt <= maxLockOffCnt);
+    }
+
+    /**
+     * Verify shading map for different shading modes.
+     */
+    private void verifyShadingMap(SimpleCaptureCallback listener, int numFramesVerified,
+            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));
+            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);
+            assertFalse(String.format(
+                    "Map size %d should be less than %d", numElementsInMap, MAX_SHADING_MAP_SIZE),
+                    numElementsInMap >= MAX_SHADING_MAP_SIZE);
+            assertFalse(String.format("Map size %d should be no less than %d", numElementsInMap,
+                    MIN_SHADING_MAP_SIZE), numElementsInMap < MIN_SHADING_MAP_SIZE);
+
+            if (shadingMode == CaptureRequest.SHADING_MODE_FAST ||
+                    shadingMode == CaptureRequest.SHADING_MODE_HIGH_QUALITY) {
+                // shading mode is FAST or HIGH_QUALITY, expect to receive a map with all
+                // elements >= 1.0f
+
+                int badValueCnt = 0;
+                // Detect the bad values of the map data.
+                for (int j = 0; j < numElementsInMap; j++) {
+                    if (Float.isNaN(map[j]) || map[j] < 1.0f) {
+                        badValueCnt++;
+                    }
+                }
+                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));
+            }
+        }
+    }
+
+    /**
+     * Test face detection for a camera.
+     */
+    private void faceDetectionTestByCamera() throws Exception {
+        int[] faceDetectModes = mStaticInfo.getAvailableFaceDetectModesChecked();
+
+        SimpleCaptureCallback listener;
+        CaptureRequest.Builder requestBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+
+        Size maxPreviewSz = mOrderedPreviewSizes.get(0); // Max preview size.
+        for (int mode : faceDetectModes) {
+            requestBuilder.set(CaptureRequest.STATISTICS_FACE_DETECT_MODE, mode);
+            if (VERBOSE) {
+                Log.v(TAG, "Start testing face detection mode " + mode);
+            }
+
+            // Create a new listener for each run to avoid the results from one run spill
+            // into another run.
+            listener = new SimpleCaptureCallback();
+            startPreview(requestBuilder, maxPreviewSz, listener);
+            waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+            verifyFaceDetectionResults(listener, NUM_FACE_DETECTION_FRAMES_VERIFIED, mode);
+        }
+
+        stopPreview();
+    }
+
+    /**
+     * Verify face detection results for different face detection modes.
+     *
+     * @param listener The listener to get capture result
+     * @param numFramesVerified Number of results to be verified
+     * @param faceDetectionMode Face detection mode to be verified against
+     */
+    private void verifyFaceDetectionResults(SimpleCaptureCallback listener, int numFramesVerified,
+            int faceDetectionMode) {
+        for (int i = 0; i < numFramesVerified; i++) {
+            CaptureResult result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+            mCollector.expectEquals("Result face detection mode should match the request",
+                    faceDetectionMode, result.get(CaptureResult.STATISTICS_FACE_DETECT_MODE));
+
+            Face[] faces = result.get(CaptureResult.STATISTICS_FACES);
+            List<Integer> faceIds = new ArrayList<Integer>(faces.length);
+            List<Integer> faceScores = new ArrayList<Integer>(faces.length);
+            if (faceDetectionMode == CaptureResult.STATISTICS_FACE_DETECT_MODE_OFF) {
+                mCollector.expectEquals("Number of detection faces should always 0 for OFF mode",
+                        0, faces.length);
+            } else if (faceDetectionMode == CaptureResult.STATISTICS_FACE_DETECT_MODE_SIMPLE) {
+                for (Face face : faces) {
+                    mCollector.expectNotNull("Face rectangle shouldn't be null", face.getBounds());
+                    faceScores.add(face.getScore());
+                    mCollector.expectTrue("Face id is expected to be -1 for SIMPLE mode",
+                            face.getId() == Face.ID_UNSUPPORTED);
+                }
+            } else if (faceDetectionMode == CaptureResult.STATISTICS_FACE_DETECT_MODE_FULL) {
+                if (VERBOSE) {
+                    Log.v(TAG, "Number of faces detected: " + faces.length);
+                }
+
+                for (Face face : faces) {
+                    Rect faceBound;
+                    boolean faceRectAvailable =  mCollector.expectTrue("Face rectangle "
+                            + "shouldn't be null", face.getBounds() != null);
+                    if (!faceRectAvailable) {
+                        continue;
+                    }
+                    faceBound = face.getBounds();
+
+                    faceScores.add(face.getScore());
+                    faceIds.add(face.getId());
+
+                    mCollector.expectTrue("Face id is shouldn't be -1 for FULL mode",
+                            face.getId() != Face.ID_UNSUPPORTED);
+                    boolean leftEyeAvailable =
+                            mCollector.expectTrue("Left eye position shouldn't be null",
+                                    face.getLeftEyePosition() != null);
+                    boolean rightEyeAvailable =
+                            mCollector.expectTrue("Right eye position shouldn't be null",
+                                    face.getRightEyePosition() != null);
+                    boolean mouthAvailable =
+                            mCollector.expectTrue("Mouth position shouldn't be null",
+                            face.getMouthPosition() != null);
+                    // Eyes/mouth position should be inside of the face rect.
+                    if (leftEyeAvailable) {
+                        Point leftEye = face.getLeftEyePosition();
+                        mCollector.expectTrue("Left eye " + leftEye + "should be"
+                                + "inside of face rect " + faceBound,
+                                faceBound.contains(leftEye.x, leftEye.y));
+                    }
+                    if (rightEyeAvailable) {
+                        Point rightEye = face.getRightEyePosition();
+                        mCollector.expectTrue("Right eye " + rightEye + "should be"
+                                + "inside of face rect " + faceBound,
+                                faceBound.contains(rightEye.x, rightEye.y));
+                    }
+                    if (mouthAvailable) {
+                        Point mouth = face.getMouthPosition();
+                        mCollector.expectTrue("Mouth " + mouth +  " should be inside of"
+                                + " face rect " + faceBound,
+                                faceBound.contains(mouth.x, mouth.y));
+                    }
+                }
+            }
+            mCollector.expectValuesInRange("Face scores are invalid", faceIds,
+                    Face.SCORE_MIN, Face.SCORE_MAX);
+            mCollector.expectValuesUnique("Face ids are invalid", faceIds);
+        }
+    }
+
+    /**
+     * Test tone map mode and result by camera
+     */
+    private void toneMapTestByCamera() throws Exception {
+        if (!mStaticInfo.isManualToneMapSupported()) {
+            return;
+        }
+
+        SimpleCaptureCallback listener;
+        CaptureRequest.Builder requestBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+
+        Size maxPreviewSz = mOrderedPreviewSizes.get(0); // Max preview size.
+
+        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) {
+                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 SimpleCaptureCallback();
+                startPreview(requestBuilder, maxPreviewSz, listener);
+                waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+                verifyToneMapModeResults(listener, NUM_FRAMES_VERIFIED, mode,
+                        TONEMAP_CURVE_LINEAR);
+
+                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 SimpleCaptureCallback();
+                startPreview(requestBuilder, maxPreviewSz, listener);
+                waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+                verifyToneMapModeResults(listener, NUM_FRAMES_VERIFIED, mode,
+                        TONEMAP_CURVE_SRGB);
+            } else {
+                // Create a new listener for each run to avoid the results from one run spill
+                // into another run.
+                listener = new SimpleCaptureCallback();
+                startPreview(requestBuilder, maxPreviewSz, listener);
+                waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+                verifyToneMapModeResults(listener, NUM_FRAMES_VERIFIED, mode,
+                        /*inputToneCurve*/null);
+            }
+        }
+
+        stopPreview();
+    }
+
+    /**
+     * Verify tonemap results.
+     * <p>
+     * Assumes R,G,B channels use the same tone curve
+     * </p>
+     *
+     * @param listener The capture listener used to get the capture results
+     * @param numFramesVerified Number of results to be verified
+     * @param tonemapMode Tonemap mode to verify
+     * @param inputToneCurve Tonemap curve used by all 3 channels, ignored when
+     * map mode is not CONTRAST_CURVE.
+     */
+    private void verifyToneMapModeResults(SimpleCaptureCallback listener, int numFramesVerified,
+            int tonemapMode, float[] inputToneCurve) {
+        final int MIN_TONEMAP_CURVE_POINTS = 2;
+        final Float ZERO = new Float(0);
+        final Float ONE = new Float(1.0f);
+
+        int maxCurvePoints = mStaticInfo.getMaxTonemapCurvePointChecked();
+        for (int i = 0; i < numFramesVerified; i++) {
+            CaptureResult result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+            mCollector.expectEquals("Capture result tonemap mode should match request", tonemapMode,
+                    result.get(CaptureResult.TONEMAP_MODE));
+            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
+                 * between request and result, as they may have different array
+                 * size.
+                 */
+            }
+
+            // Tonemap curve result availability and basic sanity check for all modes.
+            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);
+        }
+    }
+
+    /**
+     * Test awb mode control.
+     * <p>
+     * Test each supported AWB mode, verify the AWB mode in capture result
+     * matches request. When AWB is locked, the color correction gains and
+     * transform should remain unchanged.
+     * </p>
+     */
+    private void awbModeAndLockTestByCamera() throws Exception {
+        int[] awbModes = mStaticInfo.getAwbAvailableModesChecked();
+        Size maxPreviewSize = mOrderedPreviewSizes.get(0);
+        CaptureRequest.Builder requestBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        startPreview(requestBuilder, maxPreviewSize, /*listener*/null);
+
+        for (int mode : awbModes) {
+            SimpleCaptureCallback listener;
+            requestBuilder.set(CaptureRequest.CONTROL_AWB_MODE, mode);
+            listener = new SimpleCaptureCallback();
+            mSession.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
+            waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+
+            // Verify AWB mode in capture result.
+            verifyCaptureResultForKey(CaptureResult.CONTROL_AWB_MODE, mode, listener,
+                    NUM_FRAMES_VERIFIED);
+
+            if (mode == CameraMetadata.CONTROL_AWB_MODE_AUTO) {
+                // Verify color correction transform and gains stay unchanged after a lock.
+                requestBuilder.set(CaptureRequest.CONTROL_AWB_LOCK, true);
+                listener = new SimpleCaptureCallback();
+                mSession.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
+                waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+
+                if (mStaticInfo.areKeysAvailable(CaptureResult.CONTROL_AWB_STATE)) {
+                    waitForResultValue(listener, CaptureResult.CONTROL_AWB_STATE,
+                            CaptureResult.CONTROL_AWB_STATE_LOCKED, NUM_RESULTS_WAIT_TIMEOUT);
+                }
+
+            }
+            verifyAwbCaptureResultUnchanged(listener, NUM_FRAMES_VERIFIED);
+        }
+    }
+
+    private void verifyAwbCaptureResultUnchanged(SimpleCaptureCallback listener,
+            int numFramesVerified) {
+        // Skip check if cc gains/transform/mode are not available
+        if (!mStaticInfo.areKeysAvailable(
+                CaptureResult.COLOR_CORRECTION_GAINS,
+                CaptureResult.COLOR_CORRECTION_TRANSFORM,
+                CaptureResult.COLOR_CORRECTION_MODE)) {
+            return;
+        }
+
+        CaptureResult result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+        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);
+            // Color correction mode check is skipped here, as it is checked in colorCorrectionTest.
+            validateColorCorrectionResult(result, result.get(CaptureResult.COLOR_CORRECTION_MODE));
+
+            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",
+                    lockedGains, gains);
+            mCollector.expectEquals("Color correction transform should remain unchanged after"
+                    + " awb lock", lockedTransform, transform);
+        }
+    }
+
+    /**
+     * Test AF mode control.
+     * <p>
+     * Test all supported AF modes, verify the AF mode in capture result matches
+     * request. When AF mode is one of the CONTROL_AF_MODE_CONTINUOUS_* mode,
+     * verify if the AF can converge to PASSIVE_FOCUSED or PASSIVE_UNFOCUSED
+     * state within certain amount of frames.
+     * </p>
+     */
+    private void afModeTestByCamera() throws Exception {
+        int[] afModes = mStaticInfo.getAfAvailableModesChecked();
+        Size maxPreviewSize = mOrderedPreviewSizes.get(0);
+        CaptureRequest.Builder requestBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        startPreview(requestBuilder, maxPreviewSize, /*listener*/null);
+
+        for (int mode : afModes) {
+            SimpleCaptureCallback listener;
+            requestBuilder.set(CaptureRequest.CONTROL_AF_MODE, mode);
+            listener = new SimpleCaptureCallback();
+            mSession.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
+            waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+
+            // Verify AF mode in capture result.
+            verifyCaptureResultForKey(CaptureResult.CONTROL_AF_MODE, mode, listener,
+                    NUM_FRAMES_VERIFIED);
+
+            // Verify AF can finish a scan for CONTROL_AF_MODE_CONTINUOUS_* modes.
+            // In LEGACY mode, a transition to one of the continuous AF modes does not necessarily
+            // result in a passive AF call if the camera has already been focused, and the scene has
+            // not changed enough to trigger an AF pass.  Skip this constraint for LEGACY.
+            if (mStaticInfo.isHardwareLevelLimitedOrBetter() &&
+                    (mode == CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE ||
+                    mode == CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO)) {
+                List<Integer> afStateList = new ArrayList<Integer>();
+                afStateList.add(CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED);
+                afStateList.add(CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED);
+                waitForAnyResultValue(listener, CaptureResult.CONTROL_AF_STATE, afStateList,
+                        NUM_RESULTS_WAIT_TIMEOUT);
+            }
+        }
+    }
+
+    /**
+     * Test video and optical stabilizations if they are supported by a given camera.
+     */
+    private void stabilizationTestByCamera() throws Exception {
+        // video stabilization test.
+        List<Key<?>> keys = mStaticInfo.getCharacteristics().getKeys();
+
+        int[] videoStabModes = (keys.contains(CameraCharacteristics.
+                CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES)) ?
+                mStaticInfo.getAvailableVideoStabilizationModesChecked() : new int[0];
+        int[] opticalStabModes = (keys.contains(
+                CameraCharacteristics.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION)) ?
+                mStaticInfo.getAvailableOpticalStabilizationChecked() : new int[0];
+
+        Size maxPreviewSize = mOrderedPreviewSizes.get(0);
+        CaptureRequest.Builder requestBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        SimpleCaptureCallback listener = new SimpleCaptureCallback();
+        startPreview(requestBuilder, maxPreviewSize, listener);
+
+        for (int mode : videoStabModes) {
+            listener = new SimpleCaptureCallback();
+            requestBuilder.set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE, mode);
+            mSession.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
+            waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+            verifyCaptureResultForKey(CaptureResult.CONTROL_VIDEO_STABILIZATION_MODE, mode,
+                    listener, NUM_FRAMES_VERIFIED);
+        }
+
+        for (int mode : opticalStabModes) {
+            listener = new SimpleCaptureCallback();
+            requestBuilder.set(CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE, mode);
+            mSession.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
+            waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+            verifyCaptureResultForKey(CaptureResult.LENS_OPTICAL_STABILIZATION_MODE, mode,
+                    listener, NUM_FRAMES_VERIFIED);
+        }
+
+        stopPreview();
+    }
+
+    private void digitalZoomTestByCamera(Size previewSize) throws Exception {
+        final int ZOOM_STEPS = 15;
+        final PointF[] TEST_ZOOM_CENTERS;
+
+        final int croppingType = mStaticInfo.getScalerCroppingTypeChecked();
+        if (croppingType ==
+                CameraCharacteristics.SCALER_CROPPING_TYPE_FREEFORM) {
+            TEST_ZOOM_CENTERS = new PointF[] {
+                new PointF(0.5f, 0.5f),   // Center point
+                new PointF(0.25f, 0.25f), // top left corner zoom, minimal zoom: 2x
+                new PointF(0.75f, 0.25f), // top right corner zoom, minimal zoom: 2x
+                new PointF(0.25f, 0.75f), // bottom left corner zoom, minimal zoom: 2x
+                new PointF(0.75f, 0.75f), // bottom right corner zoom, minimal zoom: 2x
+            };
+
+            if (VERBOSE) {
+                Log.v(TAG, "Testing zoom with CROPPING_TYPE = FREEFORM");
+            }
+        } else {
+            // CENTER_ONLY
+            TEST_ZOOM_CENTERS = new PointF[] {
+                    new PointF(0.5f, 0.5f),   // Center point
+            };
+
+            if (VERBOSE) {
+                Log.v(TAG, "Testing zoom with CROPPING_TYPE = CENTER_ONLY");
+            }
+        }
+
+        final float maxZoom = mStaticInfo.getAvailableMaxDigitalZoomChecked();
+        final Rect activeArraySize = mStaticInfo.getActiveArraySizeChecked();
+        Rect[] cropRegions = new Rect[ZOOM_STEPS];
+        MeteringRectangle[][] expectRegions = new MeteringRectangle[ZOOM_STEPS][];
+        CaptureRequest.Builder requestBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        SimpleCaptureCallback listener = new SimpleCaptureCallback();
+
+        updatePreviewSurface(previewSize);
+        configurePreviewOutput(requestBuilder);
+
+        CaptureRequest[] requests = new CaptureRequest[ZOOM_STEPS];
+
+        // Set algorithm regions to full active region
+        // TODO: test more different 3A regions
+        final MeteringRectangle[] defaultMeteringRect = new MeteringRectangle[] {
+                new MeteringRectangle (
+                        /*x*/0, /*y*/0, activeArraySize.width(), activeArraySize.height(),
+                        /*meteringWeight*/1)
+        };
+
+        for (int algo = 0; algo < NUM_ALGORITHMS; algo++) {
+            update3aRegion(requestBuilder, algo,  defaultMeteringRect);
+        }
+
+        final int CAPTURE_SUBMIT_REPEAT;
+        {
+            int maxLatency = mStaticInfo.getSyncMaxLatency();
+            if (maxLatency == CameraMetadata.SYNC_MAX_LATENCY_UNKNOWN) {
+                CAPTURE_SUBMIT_REPEAT = NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY + 1;
+            } else {
+                CAPTURE_SUBMIT_REPEAT = maxLatency + 1;
+            }
+        }
+
+        if (VERBOSE) {
+            Log.v(TAG, "Testing zoom with CAPTURE_SUBMIT_REPEAT = " + CAPTURE_SUBMIT_REPEAT);
+        }
+
+        for (PointF center : TEST_ZOOM_CENTERS) {
+            Rect previousCrop = null;
+
+            for (int i = 0; i < ZOOM_STEPS; i++) {
+                /*
+                 * Submit capture request
+                 */
+                float zoomFactor = (float) (1.0f + (maxZoom - 1.0) * i / ZOOM_STEPS);
+                cropRegions[i] = getCropRegionForZoom(zoomFactor, center, maxZoom, activeArraySize);
+                if (VERBOSE) {
+                    Log.v(TAG, "Testing Zoom for factor " + zoomFactor + " and center " +
+                            center + " The cropRegion is " + cropRegions[i] +
+                            " Preview size is " + previewSize);
+                }
+                requestBuilder.set(CaptureRequest.SCALER_CROP_REGION, cropRegions[i]);
+                requests[i] = requestBuilder.build();
+                for (int j = 0; j < CAPTURE_SUBMIT_REPEAT; ++j) {
+                    if (VERBOSE) {
+                        Log.v(TAG, "submit crop region " + cropRegions[i]);
+                    }
+                    mSession.capture(requests[i], listener, mHandler);
+                }
+
+                /*
+                 * Validate capture result
+                 */
+                waitForNumResults(listener, CAPTURE_SUBMIT_REPEAT - 1); // Drop first few frames
+                CaptureResult result = listener.getCaptureResultForRequest(
+                        requests[i], NUM_RESULTS_WAIT_TIMEOUT);
+                Rect cropRegion = getValueNotNull(result, CaptureResult.SCALER_CROP_REGION);
+
+                /*
+                 * Validate resulting crop regions
+                 */
+                if (previousCrop != null) {
+                    Rect currentCrop = cropRegion;
+                    mCollector.expectTrue(String.format(
+                            "Crop region should shrink or stay the same " +
+                                    "(previous = %s, current = %s)",
+                                    previousCrop, currentCrop),
+                            previousCrop.equals(currentCrop) ||
+                                (previousCrop.width() > currentCrop.width() &&
+                                 previousCrop.height() > currentCrop.height()));
+                }
+
+                if (mStaticInfo.isHardwareLevelLimitedOrBetter()) {
+                    mCollector.expectRectsAreSimilar(
+                            "Request and result crop region should be similar",
+                            cropRegions[i], cropRegion, CROP_REGION_ERROR_PERCENT_DELTA);
+                }
+
+                if (croppingType == SCALER_CROPPING_TYPE_CENTER_ONLY) {
+                    mCollector.expectRectCentered(
+                            "Result crop region should be centered inside the active array",
+                            new Size(activeArraySize.width(), activeArraySize.height()),
+                            cropRegion, CROP_REGION_ERROR_PERCENT_CENTERED);
+                }
+
+                /*
+                 * Validate resulting metering regions
+                 */
+
+                // Use the actual reported crop region to calculate the resulting metering region
+                expectRegions[i] = getExpectedOutputRegion(
+                        /*requestRegion*/defaultMeteringRect,
+                        /*cropRect*/     cropRegion);
+
+                // 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]);
+                }
+
+                previousCrop = cropRegion;
+            }
+
+            if (maxZoom > 1.0f) {
+                mCollector.expectTrue(
+                        String.format("Most zoomed-in crop region should be smaller" +
+                                        "than active array w/h" +
+                                        "(last crop = %s, active array = %s)",
+                                        previousCrop, activeArraySize),
+                            (previousCrop.width() < activeArraySize.width() &&
+                             previousCrop.height() < activeArraySize.height()));
+            }
+        }
+    }
+
+    private void digitalZoomPreviewCombinationTestByCamera() throws Exception {
+        final double ASPECT_RATIO_THRESHOLD = 0.001;
+        List<Double> aspectRatiosTested = new ArrayList<Double>();
+        Size maxPreviewSize = mOrderedPreviewSizes.get(0);
+        aspectRatiosTested.add((double)(maxPreviewSize.getWidth()) / maxPreviewSize.getHeight());
+
+        for (Size size : mOrderedPreviewSizes) {
+            // Max preview size was already tested in testDigitalZoom test. skip it.
+            if (size.equals(maxPreviewSize)) {
+                continue;
+            }
+
+            // Only test the largest size for each aspect ratio.
+            double aspectRatio = (double)(size.getWidth()) / size.getHeight();
+            if (isAspectRatioContained(aspectRatiosTested, aspectRatio, ASPECT_RATIO_THRESHOLD)) {
+                continue;
+            }
+
+            if (VERBOSE) {
+                Log.v(TAG, "Test preview size " + size.toString() + " digital zoom");
+            }
+
+            aspectRatiosTested.add(aspectRatio);
+            digitalZoomTestByCamera(size);
+        }
+    }
+
+    private static boolean isAspectRatioContained(List<Double> aspectRatioList,
+            double aspectRatio, double delta) {
+        for (Double ratio : aspectRatioList) {
+            if (Math.abs(ratio - aspectRatio) < delta) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    private void sceneModeTestByCamera() throws Exception {
+        int[] sceneModes = mStaticInfo.getAvailableSceneModesChecked();
+        Size maxPreviewSize = mOrderedPreviewSizes.get(0);
+        CaptureRequest.Builder requestBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        SimpleCaptureCallback listener = new SimpleCaptureCallback();
+        requestBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_USE_SCENE_MODE);
+        startPreview(requestBuilder, maxPreviewSize, listener);
+
+        for(int mode : sceneModes) {
+            requestBuilder.set(CaptureRequest.CONTROL_SCENE_MODE, mode);
+            listener = new SimpleCaptureCallback();
+            mSession.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
+            waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+
+            verifyCaptureResultForKey(CaptureResult.CONTROL_SCENE_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_USE_SCENE_MODE, listener, NUM_FRAMES_VERIFIED);
+        }
+    }
+
+    private void effectModeTestByCamera() throws Exception {
+        int[] effectModes = mStaticInfo.getAvailableEffectModesChecked();
+        Size maxPreviewSize = mOrderedPreviewSizes.get(0);
+        CaptureRequest.Builder requestBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        requestBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
+        SimpleCaptureCallback listener = new SimpleCaptureCallback();
+        startPreview(requestBuilder, maxPreviewSize, listener);
+
+        for(int mode : effectModes) {
+            requestBuilder.set(CaptureRequest.CONTROL_EFFECT_MODE, mode);
+            listener = new SimpleCaptureCallback();
+            mSession.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
+            waitForSettingsApplied(listener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+
+            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);
+        }
+    }
+
+    //----------------------------------------------------------------
+    //---------Below are common functions for all tests.--------------
+    //----------------------------------------------------------------
+
+    /**
+     * Enable exposure manual control and change exposure and sensitivity and
+     * clamp the value into the supported range.
+     */
+    private void changeExposure(CaptureRequest.Builder requestBuilder,
+            long expTime, int sensitivity) {
+        // Check if the max analog sensitivity is available and no larger than max sensitivity.
+        // The max analog sensitivity is not actually used here. This is only an extra sanity check.
+        mStaticInfo.getMaxAnalogSensitivityChecked();
+
+        expTime = mStaticInfo.getExposureClampToRange(expTime);
+        sensitivity = mStaticInfo.getSensitivityClampToRange(sensitivity);
+
+        requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CONTROL_AE_MODE_OFF);
+        requestBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, expTime);
+        requestBuilder.set(CaptureRequest.SENSOR_SENSITIVITY, sensitivity);
+    }
+    /**
+     * Enable exposure manual control and change exposure time and
+     * clamp the value into the supported range.
+     *
+     * <p>The sensitivity is set to default value.</p>
+     */
+    private void changeExposure(CaptureRequest.Builder requestBuilder, long expTime) {
+        changeExposure(requestBuilder, expTime, DEFAULT_SENSITIVITY);
+    }
+
+    /**
+     * Get the exposure time array that contains multiple exposure time steps in
+     * the exposure time range.
+     */
+    private long[] getExposureTimeTestValues() {
+        long[] testValues = new long[DEFAULT_NUM_EXPOSURE_TIME_STEPS + 1];
+        long maxExpTime = mStaticInfo.getExposureMaximumOrDefault(DEFAULT_EXP_TIME_NS);
+        long minxExpTime = mStaticInfo.getExposureMinimumOrDefault(DEFAULT_EXP_TIME_NS);
+
+        long range = maxExpTime - minxExpTime;
+        double stepSize = range / (double)DEFAULT_NUM_EXPOSURE_TIME_STEPS;
+        for (int i = 0; i < testValues.length; i++) {
+            testValues[i] = minxExpTime + (long)(stepSize * i);
+            testValues[i] = mStaticInfo.getExposureClampToRange(testValues[i]);
+        }
+
+        return testValues;
+    }
+
+    /**
+     * Generate test focus distances in range of [0, minFocusDistance] in increasing order.
+     */
+    private float[] getFocusDistanceTestValuesInOrder() {
+        float[] testValues = new float[NUM_TEST_FOCUS_DISTANCES + 1];
+        float minValue = 0;
+        float maxValue = mStaticInfo.getMinimumFocusDistanceChecked();
+
+        float range = maxValue - minValue;
+        float stepSize = range / NUM_TEST_FOCUS_DISTANCES;
+        for (int i = 0; i < testValues.length; i++) {
+            testValues[i] = minValue + stepSize * i;
+        }
+
+        return testValues;
+    }
+
+    /**
+     * Get the sensitivity array that contains multiple sensitivity steps in the
+     * sensitivity range.
+     * <p>
+     * Sensitivity number of test values is determined by
+     * {@value #DEFAULT_SENSITIVITY_STEP_SIZE} and sensitivity range, and
+     * bounded by {@value #DEFAULT_NUM_SENSITIVITY_STEPS}.
+     * </p>
+     */
+    private int[] getSensitivityTestValues() {
+        int maxSensitivity = mStaticInfo.getSensitivityMaximumOrDefault(
+                DEFAULT_SENSITIVITY);
+        int minSensitivity = mStaticInfo.getSensitivityMinimumOrDefault(
+                DEFAULT_SENSITIVITY);
+
+        int range = maxSensitivity - minSensitivity;
+        int stepSize = DEFAULT_SENSITIVITY_STEP_SIZE;
+        int numSteps = range / stepSize;
+        // Bound the test steps to avoid supper long test.
+        if (numSteps > DEFAULT_NUM_SENSITIVITY_STEPS) {
+            numSteps = DEFAULT_NUM_SENSITIVITY_STEPS;
+            stepSize = range / numSteps;
+        }
+        int[] testValues = new int[numSteps + 1];
+        for (int i = 0; i < testValues.length; i++) {
+            testValues[i] = minSensitivity + stepSize * i;
+            testValues[i] = mStaticInfo.getSensitivityClampToRange(testValues[i]);
+        }
+
+        return testValues;
+    }
+
+    /**
+     * Validate the AE manual control exposure time.
+     *
+     * <p>Exposure should be close enough, and only round down if they are not equal.</p>
+     *
+     * @param request Request exposure time
+     * @param result Result exposure time
+     */
+    private void validateExposureTime(long request, long result) {
+        long expTimeDelta = request - result;
+        // First, round down not up, second, need close enough.
+        mCollector.expectTrue("Exposture time is invalid for AE manaul control test, request: "
+                + request + " result: " + result,
+                expTimeDelta < EXPOSURE_TIME_ERROR_MARGIN_NS && expTimeDelta >= 0);
+    }
+
+    /**
+     * Validate AE manual control sensitivity.
+     *
+     * @param request Request sensitivity
+     * @param result Result sensitivity
+     */
+    private void validateSensitivity(int request, int result) {
+        int sensitivityDelta = request - result;
+        // First, round down not up, second, need close enough.
+        mCollector.expectTrue("Sensitivity is invalid for AE manaul control test, request: "
+                + request + " result: " + result,
+                sensitivityDelta < SENSITIVITY_ERROR_MARGIN && sensitivityDelta >= 0);
+    }
+
+    /**
+     * Validate frame duration for a given capture.
+     *
+     * <p>Frame duration should be longer than exposure time.</p>
+     *
+     * @param result The capture result for a given capture
+     */
+    private void validateFrameDurationForCapture(CaptureResult result) {
+        long expTime = getValueNotNull(result, CaptureResult.SENSOR_EXPOSURE_TIME);
+        long frameDuration = getValueNotNull(result, CaptureResult.SENSOR_FRAME_DURATION);
+        if (VERBOSE) {
+            Log.v(TAG, "frame duration: " + frameDuration + " Exposure time: " + expTime);
+        }
+
+        mCollector.expectTrue(String.format("Frame duration (%d) should be longer than exposure"
+                + " time (%d) for a given capture", frameDuration, expTime),
+                frameDuration >= expTime);
+
+        validatePipelineDepth(result);
+    }
+
+    private <T> T getValueNotNull(CaptureResult result, CaptureResult.Key<T> key) {
+        T value = result.get(key);
+        assertNotNull("Value of Key " + key.getName() + " shouldn't be null", value);
+        return value;
+    }
+
+    /**
+     * Basic verification for the control mode capture result.
+     *
+     * @param key The capture result key to be verified against
+     * @param requestMode The request mode for this result
+     * @param listener The capture listener to get capture results
+     * @param numFramesVerified The number of capture results to be verified
+     */
+    private <T> void verifyCaptureResultForKey(CaptureResult.Key<T> key, T requestMode,
+            SimpleCaptureCallback listener, int numFramesVerified) {
+        for (int i = 0; i < numFramesVerified; i++) {
+            CaptureResult result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+            validatePipelineDepth(result);
+            T resultMode = getValueNotNull(result, key);
+            if (VERBOSE) {
+                Log.v(TAG, "Expect value: " + requestMode.toString() + " result value: "
+                        + resultMode.toString());
+            }
+            mCollector.expectEquals("Key " + key.getName() + " result should match request",
+                    requestMode, resultMode);
+        }
+    }
+
+    /**
+     * Verify if the fps is slow down for given input request with certain
+     * controls inside.
+     * <p>
+     * This method selects a max preview size for each fps range, and then
+     * configure the preview stream. Preview is started with the max preview
+     * size, and then verify if the result frame duration is in the frame
+     * duration range.
+     * </p>
+     *
+     * @param requestBuilder The request builder that contains post-processing
+     *            controls that could impact the output frame rate, such as
+     *            {@link CaptureRequest.NOISE_REDUCTION_MODE}. The value of
+     *            these controls must be set to some values such that the frame
+     *            rate is not slow down.
+     * @param numFramesVerified The number of frames to be verified
+     */
+    private void verifyFpsNotSlowDown(CaptureRequest.Builder requestBuilder,
+            int numFramesVerified)  throws Exception {
+        Range<Integer>[] fpsRanges = mStaticInfo.getAeAvailableTargetFpsRangesChecked();
+        boolean antiBandingOffIsSupported = mStaticInfo.isAntiBandingOffModeSupported();
+        Range<Integer> fpsRange;
+        SimpleCaptureCallback resultListener;
+
+        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 (previewSz == null) {
+                if (mStaticInfo.isCapabilitySupported(
+                    CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
+                    mCollector.addMessage(String.format(
+                            "Unable to find a preview size supporting given fps range %s",
+                            fpsRange));
+                }
+                continue;
+            }
+
+            if (VERBOSE) {
+                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
+            // from antibanding algorithm.
+            if (antiBandingOffIsSupported) {
+                requestBuilder.set(CaptureRequest.CONTROL_AE_ANTIBANDING_MODE,
+                        CaptureRequest.CONTROL_AE_ANTIBANDING_MODE_OFF);
+            } else {
+                // The device doesn't implement the OFF mode, test continues. It need make sure
+                // that the antibanding algorithm doesn't slow down the fps.
+                Log.i(TAG, "OFF antibanding mode is not supported, the camera device output must" +
+                        " not slow down the frame rate regardless of its current antibanding" +
+                        " mode");
+            }
+
+            resultListener = new SimpleCaptureCallback();
+            startPreview(requestBuilder, previewSz, resultListener);
+            long[] frameDurationRange =
+                    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);
+                validatePipelineDepth(result);
+                long frameDuration = getValueNotNull(result, CaptureResult.SENSOR_FRAME_DURATION);
+                mCollector.expectInRange(
+                        "Frame duration must be in the range of " + Arrays.toString(frameDurationRange),
+                        frameDuration,
+                        (long) (frameDurationRange[0] * (1 - FRAME_DURATION_ERROR_MARGIN)),
+                        (long) (frameDurationRange[1] * (1 + FRAME_DURATION_ERROR_MARGIN)));
+            }
+        }
+
+        mSession.stopRepeating();
+    }
+
+    /**
+     * Validate the pipeline depth result.
+     *
+     * @param result The capture result to get pipeline depth data
+     */
+    private void validatePipelineDepth(CaptureResult result) {
+        final byte MIN_PIPELINE_DEPTH = 1;
+        byte maxPipelineDepth = mStaticInfo.getPipelineMaxDepthChecked();
+        Byte pipelineDepth = getValueNotNull(result, CaptureResult.REQUEST_PIPELINE_DEPTH);
+        mCollector.expectInRange(String.format("Pipeline depth must be in the range of [%d, %d]",
+                MIN_PIPELINE_DEPTH, maxPipelineDepth), pipelineDepth, MIN_PIPELINE_DEPTH,
+                maxPipelineDepth);
+    }
+
+    /**
+     * Calculate the anti-flickering corrected exposure time.
+     * <p>
+     * If the input exposure time is very short (shorter than flickering
+     * boundary), which indicate the scene is bright and very likely at outdoor
+     * environment, skip the correction, as it doesn't make much sense by doing so.
+     * </p>
+     * <p>
+     * For long exposure time (larger than the flickering boundary), find the
+     * exposure time that is closest to the flickering boundary.
+     * </p>
+     *
+     * @param flickeringMode The flickering mode
+     * @param exposureTime The input exposureTime to be corrected
+     * @return anti-flickering corrected exposure time
+     */
+    private long getAntiFlickeringExposureTime(int flickeringMode, long exposureTime) {
+        if (flickeringMode != ANTI_FLICKERING_50HZ && flickeringMode != ANTI_FLICKERING_60HZ) {
+            throw new IllegalArgumentException("Input anti-flickering mode must be 50 or 60Hz");
+        }
+        long flickeringBoundary = EXPOSURE_TIME_BOUNDARY_50HZ_NS;
+        if (flickeringMode == ANTI_FLICKERING_60HZ) {
+            flickeringBoundary = EXPOSURE_TIME_BOUNDARY_60HZ_NS;
+        }
+
+        if (exposureTime <= flickeringBoundary) {
+            return exposureTime;
+        }
+
+        // Find the closest anti-flickering corrected exposure time
+        long correctedExpTime = exposureTime + (flickeringBoundary / 2);
+        correctedExpTime = correctedExpTime - (correctedExpTime % flickeringBoundary);
+        return correctedExpTime;
+    }
+
+    /**
+     * Update one 3A region in capture request builder if that region is supported. Do nothing
+     * 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 regions The 3A regions to be set
+     */
+    private void update3aRegion(
+            CaptureRequest.Builder requestBuilder, int algoIdx, MeteringRectangle[] regions)
+    {
+        int maxRegions;
+        CaptureRequest.Key<MeteringRectangle[]> key;
+
+        if (regions == null || regions.length == 0) {
+            throw new IllegalArgumentException("Invalid input 3A region!");
+        }
+
+        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);
+        }
+    }
+
+    /**
+     * Validate one 3A region in capture result equals to expected region if that region is
+     * 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 expectRegions The 3A regions expected in capture result
+     */
+    private void validate3aRegion(
+            CaptureResult result, int algoIdx, MeteringRectangle[] expectRegions)
+    {
+        int maxRegions;
+        CaptureResult.Key<MeteringRectangle[]> key;
+        MeteringRectangle[] actualRegion;
+
+        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 > 0)
+        {
+            actualRegion = getValueNotNull(result, key);
+            mCollector.expectEquals(
+                    "Expected 3A regions: " + Arrays.toString(expectRegions) +
+                    " does not match actual one: " + Arrays.toString(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
new file mode 100644
index 0000000..61bf36c
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureResultTest.java
@@ -0,0 +1,723 @@
+/*
+ * Copyright 2013 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.content.Context;
+import android.graphics.ImageFormat;
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.TotalCaptureResult;
+import android.media.Image;
+import android.media.ImageReader;
+import android.os.SystemClock;
+import android.util.Pair;
+import android.util.Size;
+import android.hardware.camera2.cts.testcases.Camera2AndroidTestCase;
+
+import static android.hardware.camera2.cts.CameraTestUtils.*;
+import static android.hardware.camera2.cts.helpers.CameraSessionUtils.*;
+
+import android.util.Log;
+import android.view.Surface;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+public class CaptureResultTest extends Camera2AndroidTestCase {
+    private static final String TAG = "CaptureResultTest";
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+    private static final int MAX_NUM_IMAGES = MAX_READER_IMAGES;
+    private static final int NUM_FRAMES_VERIFIED = 30;
+    private static final long WAIT_FOR_RESULT_TIMEOUT_MS = 3000;
+
+    // List that includes all public keys from CaptureResult
+    List<CaptureResult.Key<?>> mAllKeys;
+
+    // List tracking the failed test keys.
+
+    @Override
+    public void setContext(Context context) {
+        mAllKeys = getAllCaptureResultKeys();
+        super.setContext(context);
+
+        /**
+         * Workaround for mockito and JB-MR2 incompatibility
+         *
+         * Avoid java.lang.IllegalArgumentException: dexcache == null
+         * https://code.google.com/p/dexmaker/issues/detail?id=2
+         */
+        System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString());
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    /**
+     * <p>
+     * Basic non-null check test for multiple capture results.
+     * </p>
+     * <p>
+     * When capturing many frames, some camera devices may return some results that have null keys
+     * randomly, which is an API violation and could cause application crash randomly. This test
+     * runs a typical flexible yuv capture many times, and checks if there is any null entries in
+     * a capture result.
+     * </p>
+     */
+    public void testCameraCaptureResultAllKeys() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                openDevice(id);
+                // Create image reader and surface.
+                Size size = mOrderedPreviewSizes.get(0);
+                createDefaultImageReader(size, ImageFormat.YUV_420_888, MAX_NUM_IMAGES,
+                        new ImageDropperListener());
+
+                // Configure output streams.
+                List<Surface> outputSurfaces = new ArrayList<Surface>(1);
+                outputSurfaces.add(mReaderSurface);
+                createSession(outputSurfaces);
+
+                CaptureRequest.Builder requestBuilder =
+                        mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+                assertNotNull("Failed to create capture request", requestBuilder);
+                requestBuilder.addTarget(mReaderSurface);
+
+                // Start capture
+                SimpleCaptureCallback captureListener = new SimpleCaptureCallback();
+                startCapture(requestBuilder.build(), /*repeating*/true, captureListener, mHandler);
+
+                // Get the waived keys for current camera device
+                List<CaptureResult.Key<?>> waiverkeys = getWaiverKeysForCamera();
+
+                // Verify results
+                validateCaptureResult(captureListener, waiverkeys, requestBuilder,
+                        NUM_FRAMES_VERIFIED);
+
+                stopCapture(/*fast*/false);
+            } finally {
+                closeDevice(id);
+                closeDefaultImageReader();
+            }
+        }
+    }
+
+    /**
+     * Check partial results conform to its specification.
+     * <p>
+     * The test is skipped if partial result is not supported on device. </p>
+     * <p>Test summary:<ul>
+     * <li>1. Number of partial results is less than or equal to
+     * {@link CameraCharacteristics#REQUEST_PARTIAL_RESULT_COUNT}.
+     * <li>2. Each key appeared in partial results must be unique across all partial results.
+     * <li>3. All keys appeared in partial results must be present in TotalCaptureResult
+     * <li>4. Also test onCaptureComplete callback always happen after onCaptureStart or
+     * onCaptureProgressed callbacks.
+     * </ul></p>
+     */
+    public void testPartialResult() throws Exception {
+        final int NUM_FRAMES_TESTED = 30;
+        final int WAIT_FOR_RESULT_TIMOUT_MS = 2000;
+        for (String id : mCameraIds) {
+            try {
+                openDevice(id);
+
+                // Skip the test if partial result is not supported
+                int partialResultCount = mStaticInfo.getPartialResultCount();
+                if (partialResultCount == 1) {
+                    continue;
+                }
+
+                // Create image reader and surface.
+                Size size = mOrderedPreviewSizes.get(0);
+                createDefaultImageReader(size, ImageFormat.YUV_420_888, MAX_NUM_IMAGES,
+                        new ImageDropperListener());
+
+                // Configure output streams.
+                List<Surface> outputSurfaces = new ArrayList<Surface>(1);
+                outputSurfaces.add(mReaderSurface);
+                createSession(outputSurfaces);
+
+                CaptureRequest.Builder requestBuilder =
+                        mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+                assertNotNull("Failed to create capture request", requestBuilder);
+                requestBuilder.addTarget(mReaderSurface);
+                TotalAndPartialResultListener listener =
+                        new TotalAndPartialResultListener();
+
+                // Start capture
+                for (Integer frame = 0; frame < NUM_FRAMES_TESTED; frame++) {
+                    // Set a different tag for each request so the listener can group
+                    // partial results by each request
+                    requestBuilder.setTag(frame);
+                    startCapture(
+                            requestBuilder.build(), /*repeating*/false,
+                            listener, mHandler);
+                }
+
+                // Verify capture results
+                for (int frame = 0; frame < NUM_FRAMES_TESTED; frame++) {
+                    Pair<TotalCaptureResult, List<CaptureResult>> resultPair =
+                            listener.getCaptureResultPairs(WAIT_FOR_RESULT_TIMOUT_MS);
+
+                    List<CaptureResult> partialResults = resultPair.second;
+
+                    if (partialResults == null) {
+                        // HAL only sends total result is legal
+                        partialResults = new ArrayList<>();
+                    }
+
+                    TotalCaptureResult totalResult = resultPair.first;
+
+                    mCollector.expectLessOrEqual("Too many partial results",
+                            partialResultCount, partialResults.size());
+                    Set<CaptureResult.Key<?>> appearedPartialKeys =
+                            new HashSet<CaptureResult.Key<?>>();
+                    for (CaptureResult partialResult : partialResults) {
+                        List<CaptureResult.Key<?>> partialKeys = partialResult.getKeys();
+                        mCollector.expectValuesUnique("Partial result keys: ", partialKeys);
+                        for (CaptureResult.Key<?> key : partialKeys) {
+                            mCollector.expectTrue(
+                                    String.format("Key %s appears in multiple partial results",
+                                            key.getName()),
+                                    !appearedPartialKeys.contains(key));
+                        }
+                        appearedPartialKeys.addAll(partialKeys);
+                    }
+
+                    // Test total result against the partial results
+                    List<CaptureResult.Key<?>> totalResultKeys = totalResult.getKeys();
+                    mCollector.expectTrue(
+                            "TotalCaptureResult must be a super set of partial capture results",
+                            totalResultKeys.containsAll(appearedPartialKeys));
+
+                    List<CaptureResult> totalResultPartials = totalResult.getPartialResults();
+                    mCollector.expectEquals("TotalCaptureResult's partial results must match " +
+                            "the ones observed by #onCaptureProgressed",
+                            partialResults, totalResultPartials);
+
+                    if (VERBOSE) {
+                        Log.v(TAG, "testPartialResult - Observed " +
+                                partialResults.size() + "; queried for " +
+                                totalResultPartials.size());
+                    }
+                }
+
+                int errorCode = listener.getErrorCode();
+                if ((errorCode & TotalAndPartialResultListener.ERROR_DUPLICATED_REQUEST) != 0) {
+                    mCollector.addMessage("Listener received multiple onCaptureComplete" +
+                            " callback for the same request");
+                }
+                if ((errorCode & TotalAndPartialResultListener.ERROR_WRONG_CALLBACK_ORDER) != 0) {
+                    mCollector.addMessage("Listener received onCaptureStart or" +
+                            " onCaptureProgressed after onCaptureComplete");
+                }
+
+                stopCapture(/*fast*/false);
+            } finally {
+                closeDevice(id);
+                closeDefaultImageReader();
+            }
+        }
+    }
+
+    /**
+     * Check that the timestamps passed in the results, buffers, and capture callbacks match for
+     * a single request, and increase monotonically
+     */
+    public void testResultTimestamps() throws Exception {
+        for (String id : mCameraIds) {
+            ImageReader previewReader = null;
+            ImageReader jpegReader = null;
+
+            SimpleImageReaderListener jpegListener = new SimpleImageReaderListener();
+            SimpleImageReaderListener prevListener = new SimpleImageReaderListener();
+            try {
+                openDevice(id);
+
+                CaptureRequest.Builder previewBuilder =
+                        mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+                CaptureRequest.Builder multiBuilder =
+                        mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
+
+                // Create image reader and surface.
+                Size previewSize = mOrderedPreviewSizes.get(0);
+                Size jpegSize = mOrderedStillSizes.get(0);
+
+                // Create ImageReaders.
+                previewReader = makeImageReader(previewSize, ImageFormat.YUV_420_888,
+                        MAX_NUM_IMAGES, prevListener, mHandler);
+                jpegReader = makeImageReader(jpegSize, ImageFormat.JPEG,
+                        MAX_NUM_IMAGES, jpegListener, mHandler);
+
+                // Configure output streams with preview and jpeg streams.
+                List<Surface> outputSurfaces = new ArrayList<>(Arrays.asList(
+                        previewReader.getSurface(), jpegReader.getSurface()));
+
+                SessionListener mockSessionListener = getMockSessionListener();
+
+                CameraCaptureSession session = configureAndVerifySession(mockSessionListener,
+                        mCamera, outputSurfaces, mHandler);
+
+                // Configure the requests.
+                previewBuilder.addTarget(previewReader.getSurface());
+                multiBuilder.addTarget(previewReader.getSurface());
+                multiBuilder.addTarget(jpegReader.getSurface());
+
+                CaptureCallback mockCaptureCallback = getMockCaptureListener();
+
+                // Capture targeting only preview
+                Pair<TotalCaptureResult, Long> result = captureAndVerifyResult(mockCaptureCallback,
+                        session, previewBuilder.build(), mHandler);
+
+                // Check if all timestamps are the same
+                validateTimestamps("Result 1", result.first,
+                        prevListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS), result.second);
+
+                // Capture targeting both jpeg and preview
+                Pair<TotalCaptureResult, Long> result2 = captureAndVerifyResult(mockCaptureCallback,
+                        session, multiBuilder.build(), mHandler);
+
+                // Check if all timestamps are the same
+                validateTimestamps("Result 2 Preview", result2.first,
+                        prevListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS), result2.second);
+                validateTimestamps("Result 2 Jpeg", result2.first,
+                        jpegListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS), result2.second);
+
+                // Check if timestamps are increasing
+                mCollector.expectGreater("Timestamps must be increasing.", result.second,
+                        result2.second);
+
+                // Capture two preview frames
+                long startTime = SystemClock.elapsedRealtimeNanos();
+                Pair<TotalCaptureResult, Long> result3 = captureAndVerifyResult(mockCaptureCallback,
+                        session, previewBuilder.build(), mHandler);
+                Pair<TotalCaptureResult, Long> result4 = captureAndVerifyResult(mockCaptureCallback,
+                        session, previewBuilder.build(), mHandler);
+                long clockDiff = SystemClock.elapsedRealtimeNanos() - startTime;
+                long resultDiff = result4.second - result3.second;
+
+                // Check if all timestamps are the same
+                validateTimestamps("Result 3", result3.first,
+                        prevListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS), result3.second);
+                validateTimestamps("Result 4", result4.first,
+                        prevListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS), result4.second);
+
+                // Check that the timestamps monotonically increase at a reasonable rate
+                mCollector.expectGreaterOrEqual("Timestamps increase faster than system clock.",
+                        resultDiff, clockDiff);
+                mCollector.expectGreater("Timestamps must be increasing.", result3.second,
+                        result4.second);
+            } finally {
+                closeDevice(id);
+                closeImageReader(previewReader);
+                closeImageReader(jpegReader);
+            }
+        }
+    }
+
+    private void validateTimestamps(String msg, TotalCaptureResult result, Image resultImage,
+                                    long captureTime) {
+        mCollector.expectKeyValueEquals(result, CaptureResult.SENSOR_TIMESTAMP, captureTime);
+        mCollector.expectEquals(msg + ": Capture timestamp must be same as resultImage timestamp",
+                resultImage.getTimestamp(), captureTime);
+    }
+
+    private void validateCaptureResult(SimpleCaptureCallback captureListener,
+            List<CaptureResult.Key<?>> skippedKeys, CaptureRequest.Builder requestBuilder,
+            int numFramesVerified) throws Exception {
+        CaptureResult result = null;
+        for (int i = 0; i < numFramesVerified; i++) {
+            String failMsg = "Failed capture result " + i + " test ";
+            result = captureListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+
+            for (CaptureResult.Key<?> key : mAllKeys) {
+                if (!skippedKeys.contains(key)) {
+                    /**
+                     * Check the critical tags here.
+                     * TODO: Can use the same key for request and result when request/result
+                     * becomes symmetric (b/14059883). Then below check can be wrapped into
+                     * a generic function.
+                     */
+                    String msg = failMsg + "for key " + key.getName();
+                    if (key.equals(CaptureResult.CONTROL_AE_MODE)) {
+                        mCollector.expectEquals(msg,
+                                requestBuilder.get(CaptureRequest.CONTROL_AE_MODE),
+                                result.get(CaptureResult.CONTROL_AE_MODE));
+                    } else if (key.equals(CaptureResult.CONTROL_AF_MODE)) {
+                        mCollector.expectEquals(msg,
+                                requestBuilder.get(CaptureRequest.CONTROL_AF_MODE),
+                                result.get(CaptureResult.CONTROL_AF_MODE));
+                    } else if (key.equals(CaptureResult.CONTROL_AWB_MODE)) {
+                        mCollector.expectEquals(msg,
+                                requestBuilder.get(CaptureRequest.CONTROL_AWB_MODE),
+                                result.get(CaptureResult.CONTROL_AWB_MODE));
+                    } else if (key.equals(CaptureResult.CONTROL_MODE)) {
+                        mCollector.expectEquals(msg,
+                                requestBuilder.get(CaptureRequest.CONTROL_MODE),
+                                result.get(CaptureResult.CONTROL_MODE));
+                    } else if (key.equals(CaptureResult.STATISTICS_FACE_DETECT_MODE)) {
+                        mCollector.expectEquals(msg,
+                                requestBuilder.get(CaptureRequest.STATISTICS_FACE_DETECT_MODE),
+                                result.get(CaptureResult.STATISTICS_FACE_DETECT_MODE));
+                    } else if (key.equals(CaptureResult.NOISE_REDUCTION_MODE)) {
+                        mCollector.expectEquals(msg,
+                                requestBuilder.get(CaptureRequest.NOISE_REDUCTION_MODE),
+                                result.get(CaptureResult.NOISE_REDUCTION_MODE));
+                    } else if (key.equals(CaptureResult.NOISE_REDUCTION_MODE)) {
+                        mCollector.expectEquals(msg,
+                                requestBuilder.get(CaptureRequest.NOISE_REDUCTION_MODE),
+                                result.get(CaptureResult.NOISE_REDUCTION_MODE));
+                    } else if (key.equals(CaptureResult.REQUEST_PIPELINE_DEPTH)) {
+
+                    } else {
+                        // Only do non-null check for the rest of keys.
+                        mCollector.expectKeyValueNotNull(failMsg, result, key);
+                    }
+                } else {
+                    // These keys should always be null
+                    if (key.equals(CaptureResult.CONTROL_AE_REGIONS)) {
+                        mCollector.expectNull(
+                                "Capture result contains AE regions but aeMaxRegions is 0",
+                                result.get(CaptureResult.CONTROL_AE_REGIONS));
+                    } else if (key.equals(CaptureResult.CONTROL_AWB_REGIONS)) {
+                        mCollector.expectNull(
+                                "Capture result contains AWB regions but awbMaxRegions is 0",
+                                result.get(CaptureResult.CONTROL_AWB_REGIONS));
+                    } else if (key.equals(CaptureResult.CONTROL_AF_REGIONS)) {
+                        mCollector.expectNull(
+                                "Capture result contains AF regions but afMaxRegions is 0",
+                                result.get(CaptureResult.CONTROL_AF_REGIONS));
+                    }
+                }
+            }
+        }
+    }
+
+    /*
+     * Add waiver keys per camera device hardware level and capability.
+     *
+     * Must be called after camera device is opened.
+     */
+    private List<CaptureResult.Key<?>> getWaiverKeysForCamera() {
+        List<CaptureResult.Key<?>> waiverKeys = new ArrayList<>();
+
+        // Global waiver keys
+        waiverKeys.add(CaptureResult.JPEG_GPS_LOCATION);
+        waiverKeys.add(CaptureResult.JPEG_ORIENTATION);
+        waiverKeys.add(CaptureResult.JPEG_QUALITY);
+        waiverKeys.add(CaptureResult.JPEG_THUMBNAIL_QUALITY);
+        waiverKeys.add(CaptureResult.JPEG_THUMBNAIL_SIZE);
+
+        // Keys only present when corresponding control is on are being
+        // verified in its own functional test
+        // Only present when tone mapping mode is CONTRAST_CURVE
+        waiverKeys.add(CaptureResult.TONEMAP_CURVE);
+        // Only present when test pattern mode is SOLID_COLOR.
+        // TODO: verify this key in test pattern test later
+        waiverKeys.add(CaptureResult.SENSOR_TEST_PATTERN_DATA);
+        // Only present when STATISTICS_LENS_SHADING_MAP_MODE is ON
+        waiverKeys.add(CaptureResult.STATISTICS_LENS_SHADING_CORRECTION_MAP);
+        //  Only present when STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES is ON
+        waiverKeys.add(CaptureResult.STATISTICS_HOT_PIXEL_MAP);
+        //  Only present when face detection is on
+        waiverKeys.add(CaptureResult.STATISTICS_FACES);
+
+        //Keys not required if RAW is not supported
+        if (!mStaticInfo.isCapabilitySupported(
+                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)) {
+            waiverKeys.add(CaptureResult.SENSOR_NEUTRAL_COLOR_POINT);
+            waiverKeys.add(CaptureResult.SENSOR_GREEN_SPLIT);
+            waiverKeys.add(CaptureResult.SENSOR_NOISE_PROFILE);
+        }
+
+        if (mStaticInfo.getAeMaxRegionsChecked() == 0) {
+            waiverKeys.add(CaptureResult.CONTROL_AE_REGIONS);
+        }
+        if (mStaticInfo.getAwbMaxRegionsChecked() == 0) {
+            waiverKeys.add(CaptureResult.CONTROL_AWB_REGIONS);
+        }
+        if (mStaticInfo.getAfMaxRegionsChecked() == 0) {
+            waiverKeys.add(CaptureResult.CONTROL_AF_REGIONS);
+        }
+
+        if (mStaticInfo.isHardwareLevelFull()) {
+            return waiverKeys;
+        }
+
+        /*
+         * Hardware Level = LIMITED or LEGACY
+         */
+        // Key not present if certain control is not supported
+        if (!mStaticInfo.isManualColorCorrectionSupported()) {
+            waiverKeys.add(CaptureResult.COLOR_CORRECTION_GAINS);
+            waiverKeys.add(CaptureResult.COLOR_CORRECTION_MODE);
+            waiverKeys.add(CaptureResult.COLOR_CORRECTION_TRANSFORM);
+        }
+
+        if (!mStaticInfo.isManualColorAberrationControlSupported()) {
+            waiverKeys.add(CaptureResult.COLOR_CORRECTION_ABERRATION_MODE);
+        }
+
+        if (!mStaticInfo.isManualToneMapSupported()) {
+            waiverKeys.add(CaptureResult.TONEMAP_MODE);
+        }
+
+        if (!mStaticInfo.isEdgeModeControlSupported()) {
+            waiverKeys.add(CaptureResult.EDGE_MODE);
+        }
+
+        if (!mStaticInfo.isHotPixelMapModeControlSupported()) {
+            waiverKeys.add(CaptureResult.HOT_PIXEL_MODE);
+        }
+
+        if (!mStaticInfo.isNoiseReductionModeControlSupported()) {
+            waiverKeys.add(CaptureResult.NOISE_REDUCTION_MODE);
+        }
+
+        if (!mStaticInfo.isManualLensShadingMapSupported()) {
+            waiverKeys.add(CaptureResult.SHADING_MODE);
+        }
+
+        //Keys not required if manual sensor control is not supported
+        if (!mStaticInfo.isCapabilitySupported(
+                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
+            waiverKeys.add(CaptureResult.SENSOR_EXPOSURE_TIME);
+            waiverKeys.add(CaptureResult.SENSOR_FRAME_DURATION);
+            waiverKeys.add(CaptureResult.SENSOR_SENSITIVITY);
+            waiverKeys.add(CaptureResult.BLACK_LEVEL_LOCK);
+            waiverKeys.add(CaptureResult.LENS_FOCUS_RANGE);
+            waiverKeys.add(CaptureResult.LENS_FOCUS_DISTANCE);
+            waiverKeys.add(CaptureResult.LENS_STATE);
+            waiverKeys.add(CaptureResult.LENS_APERTURE);
+            waiverKeys.add(CaptureResult.LENS_FILTER_DENSITY);
+        }
+
+        if (mStaticInfo.isHardwareLevelLimited()) {
+            return waiverKeys;
+        }
+
+        /*
+         * Hardware Level = LEGACY
+         */
+        waiverKeys.add(CaptureResult.CONTROL_AE_PRECAPTURE_TRIGGER);
+        waiverKeys.add(CaptureResult.CONTROL_AE_STATE);
+        waiverKeys.add(CaptureResult.CONTROL_AWB_STATE);
+        waiverKeys.add(CaptureResult.FLASH_STATE);
+        waiverKeys.add(CaptureResult.LENS_OPTICAL_STABILIZATION_MODE);
+        waiverKeys.add(CaptureResult.SENSOR_ROLLING_SHUTTER_SKEW);
+        waiverKeys.add(CaptureResult.STATISTICS_LENS_SHADING_MAP_MODE);
+        waiverKeys.add(CaptureResult.STATISTICS_SCENE_FLICKER);
+        waiverKeys.add(CaptureResult.STATISTICS_HOT_PIXEL_MAP_MODE);
+        waiverKeys.add(CaptureResult.CONTROL_AE_TARGET_FPS_RANGE);
+        waiverKeys.add(CaptureResult.CONTROL_AF_TRIGGER);
+
+        return waiverKeys;
+    }
+
+    /**
+     * A capture listener implementation for collecting both partial and total results.
+     *
+     * <p> This is not a full-blown class and has some implicit assumptions. The class groups
+     * capture results by capture request, so the user must guarantee each request this listener
+     * is listening is unique. This class is not thread safe, so don't attach an instance object
+     * with multiple handlers.</p>
+     * */
+    private static class TotalAndPartialResultListener
+            extends CameraCaptureSession.CaptureCallback {
+        static final int ERROR_DUPLICATED_REQUEST = 1 << 0;
+        static final int ERROR_WRONG_CALLBACK_ORDER = 1 << 1;
+
+        private final LinkedBlockingQueue<Pair<TotalCaptureResult, List<CaptureResult>> > mQueue =
+                new LinkedBlockingQueue<>();
+        private final HashMap<CaptureRequest, List<CaptureResult>> mPartialResultsMap =
+                new HashMap<CaptureRequest, List<CaptureResult>>();
+        private final HashSet<CaptureRequest> completedRequests = new HashSet<>();
+        private int errorCode = 0;
+
+        @Override
+        public void onCaptureStarted(
+            CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber)
+        {
+            checkCallbackOrder(request);
+            createMapEntryIfNecessary(request);
+        }
+
+        @Override
+        public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
+                TotalCaptureResult result) {
+            try {
+                List<CaptureResult> partialResultsList = mPartialResultsMap.get(request);
+                if (partialResultsList == null) {
+                    Log.w(TAG, "onCaptureCompleted: unknown request");
+                }
+                mQueue.put(new Pair<TotalCaptureResult, List<CaptureResult>>(
+                        result, partialResultsList));
+                mPartialResultsMap.remove(request);
+                boolean newEntryAdded = completedRequests.add(request);
+                if (!newEntryAdded) {
+                    Integer frame = (Integer) request.getTag();
+                    Log.e(TAG, "Frame " + frame + "ERROR_DUPLICATED_REQUEST");
+                    errorCode |= ERROR_DUPLICATED_REQUEST;
+                }
+            } catch (InterruptedException e) {
+                throw new UnsupportedOperationException(
+                        "Can't handle InterruptedException in onCaptureCompleted");
+            }
+        }
+
+        @Override
+        public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request,
+                CaptureResult partialResult) {
+            createMapEntryIfNecessary(request);
+            List<CaptureResult> partialResultsList = mPartialResultsMap.get(request);
+            partialResultsList.add(partialResult);
+        }
+
+        private void createMapEntryIfNecessary(CaptureRequest request) {
+            if (!mPartialResultsMap.containsKey(request)) {
+                // create a new entry in the map
+                mPartialResultsMap.put(request, new ArrayList<CaptureResult>());
+            }
+        }
+
+        private void checkCallbackOrder(CaptureRequest request) {
+            if (completedRequests.contains(request)) {
+                Integer frame = (Integer) request.getTag();
+                Log.e(TAG, "Frame " + frame + "ERROR_WRONG_CALLBACK_ORDER");
+                errorCode |= ERROR_WRONG_CALLBACK_ORDER;
+            }
+        }
+
+        public Pair<TotalCaptureResult, List<CaptureResult>> getCaptureResultPairs(long timeout) {
+            try {
+                Pair<TotalCaptureResult, List<CaptureResult>> result =
+                        mQueue.poll(timeout, TimeUnit.MILLISECONDS);
+                assertNotNull("Wait for a capture result timed out in " + timeout + "ms", result);
+                return result;
+            } catch (InterruptedException e) {
+                throw new UnsupportedOperationException("Unhandled interrupted exception", e);
+            }
+        }
+
+        public int getErrorCode() {
+            return errorCode;
+        }
+    }
+
+    /**
+     * TODO: Use CameraCharacteristics.getAvailableCaptureResultKeys() once we can filter out
+     * @hide keys.
+     *
+     */
+
+    /*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
+     * The key entries below this point are generated from metadata
+     * definitions in /system/media/camera/docs. Do not modify by hand or
+     * modify the comment blocks at the start or end.
+     *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~*/
+
+    private static List<CaptureResult.Key<?>> getAllCaptureResultKeys() {
+        ArrayList<CaptureResult.Key<?>> resultKeys = new ArrayList<CaptureResult.Key<?>>();
+        resultKeys.add(CaptureResult.COLOR_CORRECTION_MODE);
+        resultKeys.add(CaptureResult.COLOR_CORRECTION_TRANSFORM);
+        resultKeys.add(CaptureResult.COLOR_CORRECTION_GAINS);
+        resultKeys.add(CaptureResult.COLOR_CORRECTION_ABERRATION_MODE);
+        resultKeys.add(CaptureResult.CONTROL_AE_ANTIBANDING_MODE);
+        resultKeys.add(CaptureResult.CONTROL_AE_EXPOSURE_COMPENSATION);
+        resultKeys.add(CaptureResult.CONTROL_AE_LOCK);
+        resultKeys.add(CaptureResult.CONTROL_AE_MODE);
+        resultKeys.add(CaptureResult.CONTROL_AE_REGIONS);
+        resultKeys.add(CaptureResult.CONTROL_AE_TARGET_FPS_RANGE);
+        resultKeys.add(CaptureResult.CONTROL_AE_PRECAPTURE_TRIGGER);
+        resultKeys.add(CaptureResult.CONTROL_AF_MODE);
+        resultKeys.add(CaptureResult.CONTROL_AF_REGIONS);
+        resultKeys.add(CaptureResult.CONTROL_AF_TRIGGER);
+        resultKeys.add(CaptureResult.CONTROL_AWB_LOCK);
+        resultKeys.add(CaptureResult.CONTROL_AWB_MODE);
+        resultKeys.add(CaptureResult.CONTROL_AWB_REGIONS);
+        resultKeys.add(CaptureResult.CONTROL_CAPTURE_INTENT);
+        resultKeys.add(CaptureResult.CONTROL_EFFECT_MODE);
+        resultKeys.add(CaptureResult.CONTROL_MODE);
+        resultKeys.add(CaptureResult.CONTROL_SCENE_MODE);
+        resultKeys.add(CaptureResult.CONTROL_VIDEO_STABILIZATION_MODE);
+        resultKeys.add(CaptureResult.CONTROL_AE_STATE);
+        resultKeys.add(CaptureResult.CONTROL_AF_STATE);
+        resultKeys.add(CaptureResult.CONTROL_AWB_STATE);
+        resultKeys.add(CaptureResult.EDGE_MODE);
+        resultKeys.add(CaptureResult.FLASH_MODE);
+        resultKeys.add(CaptureResult.FLASH_STATE);
+        resultKeys.add(CaptureResult.HOT_PIXEL_MODE);
+        resultKeys.add(CaptureResult.JPEG_GPS_LOCATION);
+        resultKeys.add(CaptureResult.JPEG_ORIENTATION);
+        resultKeys.add(CaptureResult.JPEG_QUALITY);
+        resultKeys.add(CaptureResult.JPEG_THUMBNAIL_QUALITY);
+        resultKeys.add(CaptureResult.JPEG_THUMBNAIL_SIZE);
+        resultKeys.add(CaptureResult.LENS_APERTURE);
+        resultKeys.add(CaptureResult.LENS_FILTER_DENSITY);
+        resultKeys.add(CaptureResult.LENS_FOCAL_LENGTH);
+        resultKeys.add(CaptureResult.LENS_FOCUS_DISTANCE);
+        resultKeys.add(CaptureResult.LENS_OPTICAL_STABILIZATION_MODE);
+        resultKeys.add(CaptureResult.LENS_FOCUS_RANGE);
+        resultKeys.add(CaptureResult.LENS_STATE);
+        resultKeys.add(CaptureResult.NOISE_REDUCTION_MODE);
+        resultKeys.add(CaptureResult.REQUEST_PIPELINE_DEPTH);
+        resultKeys.add(CaptureResult.SCALER_CROP_REGION);
+        resultKeys.add(CaptureResult.SENSOR_EXPOSURE_TIME);
+        resultKeys.add(CaptureResult.SENSOR_FRAME_DURATION);
+        resultKeys.add(CaptureResult.SENSOR_SENSITIVITY);
+        resultKeys.add(CaptureResult.SENSOR_TIMESTAMP);
+        resultKeys.add(CaptureResult.SENSOR_NEUTRAL_COLOR_POINT);
+        resultKeys.add(CaptureResult.SENSOR_NOISE_PROFILE);
+        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_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);
+        resultKeys.add(CaptureResult.TONEMAP_MODE);
+        resultKeys.add(CaptureResult.BLACK_LEVEL_LOCK);
+
+        return resultKeys;
+    }
+
+    /*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
+     * End generated code
+     *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
+}
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..9ec649e
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/DngCreatorTest.java
@@ -0,0 +1,347 @@
+/*
+ * 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.graphics.Rect;
+import android.hardware.camera2.CameraCaptureSession;
+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.location.Location;
+import android.media.ExifInterface;
+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.configureCameraSession;
+import static android.hardware.camera2.cts.helpers.AssertHelpers.*;
+
+/**
+ * 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);
+
+                if (!mStaticInfo.isCapabilitySupported(
+                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)) {
+                    Log.i(TAG, "RAW capability is not supported in camera " + mCameraIds[i] +
+                            ". Skip the test.");
+                    continue;
+                }
+
+                Size[] targetCaptureSizes =
+                        mStaticInfo.getAvailableSizesForFormatChecked(ImageFormat.RAW_SENSOR,
+                                StaticMetadata.StreamDirection.Output);
+
+                assertTrue("No capture sizes available for RAW format!",
+                        targetCaptureSizes.length != 0);
+                Rect activeArray = mStaticInfo.getActiveArraySizeChecked();
+                Size activeArraySize = new Size(activeArray.width(), activeArray.height());
+                assertTrue("Missing ActiveArraySize", activeArray.width() > 0 &&
+                        activeArray.height() > 0);
+                // TODO: Allow PixelArraySize also.
+                assertArrayContains("Available sizes for RAW format must include ActiveArraySize",
+                        targetCaptureSizes, activeArraySize);
+
+                // Create capture image reader
+                CameraTestUtils.SimpleImageReaderListener captureListener
+                        = new CameraTestUtils.SimpleImageReaderListener();
+                captureReader = createImageReader(activeArraySize, ImageFormat.RAW_SENSOR, 2,
+                        captureListener);
+                Pair<Image, CaptureResult> resultPair = captureSingleRawShot(activeArraySize,
+                        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) {
+                    String filePath = DEBUG_FILE_NAME_BASE + "camera_" + deviceId + "_" +
+                            DEBUG_DNG_FILE;
+                    // Write out captured DNG file for the first camera device if setprop is enabled
+                    fileStream = new FileOutputStream(filePath);
+                    fileStream.write(outputStream.toByteArray());
+                    fileStream.flush();
+                    fileStream.close();
+                    Log.v(TAG, "Test DNG file for camera " + deviceId + " saved to " + filePath);
+                }
+            } finally {
+                closeDevice(deviceId);
+                closeImageReader(captureReader);
+
+                if (outputStream != null) {
+                    outputStream.close();
+                }
+
+                if (fileStream != null) {
+                    fileStream.close();
+                }
+            }
+        }
+    }
+
+    /**
+     * Test basic raw capture and DNG saving with a thumbnail, rotation, usercomment, and GPS tags
+     * set.
+     *
+     * <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 testSingleImageThumbnail() throws Exception {
+        for (int i = 0; i < mCameraIds.length; i++) {
+            String deviceId = mCameraIds[i];
+            List<ImageReader> captureReaders = new ArrayList<ImageReader>();
+            List<CameraTestUtils.SimpleImageReaderListener> captureListeners =
+                    new ArrayList<CameraTestUtils.SimpleImageReaderListener>();
+            FileOutputStream fileStream = null;
+            ByteArrayOutputStream outputStream = null;
+            try {
+                openDevice(deviceId);
+
+                if (!mStaticInfo.isCapabilitySupported(
+                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)) {
+                    Log.i(TAG, "RAW capability is not supported in camera " + mCameraIds[i] +
+                            ". Skip the test.");
+                    continue;
+                }
+
+                Size[] targetCaptureSizes =
+                        mStaticInfo.getAvailableSizesForFormatChecked(ImageFormat.RAW_SENSOR,
+                                StaticMetadata.StreamDirection.Output);
+
+                assertTrue("No capture sizes available for RAW format!",
+                        targetCaptureSizes.length != 0);
+                Rect activeArray = mStaticInfo.getActiveArraySizeChecked();
+                Size activeArraySize = new Size(activeArray.width(), activeArray.height());
+                assertTrue("Missing ActiveArraySize", activeArray.width() > 0 &&
+                        activeArray.height() > 0);
+                // TODO: Allow PixelArraySize also.
+                assertArrayContains("Available sizes for RAW format must include ActiveArraySize",
+                        targetCaptureSizes, activeArraySize);
+
+                Size[] targetPreviewSizes =
+                        mStaticInfo.getAvailableSizesForFormatChecked(ImageFormat.YUV_420_888,
+                                StaticMetadata.StreamDirection.Output);
+                // Get smallest preview size
+                Size previewSize = mOrderedPreviewSizes.get(mOrderedPreviewSizes.size() - 1);
+
+                // Create capture image reader
+                CameraTestUtils.SimpleImageReaderListener captureListener
+                        = new CameraTestUtils.SimpleImageReaderListener();
+                captureReaders.add(createImageReader(activeArraySize, ImageFormat.RAW_SENSOR, 2,
+                        captureListener));
+                captureListeners.add(captureListener);
+
+                CameraTestUtils.SimpleImageReaderListener previewListener
+                        = new CameraTestUtils.SimpleImageReaderListener();
+
+                captureReaders.add(createImageReader(previewSize, ImageFormat.YUV_420_888, 2,
+                        previewListener));
+                captureListeners.add(previewListener);
+
+                Pair<List<Image>, CaptureResult> resultPair = captureSingleRawShot(activeArraySize,
+                        captureReaders, captureListeners);
+                CameraCharacteristics characteristics = mStaticInfo.getCharacteristics();
+
+                // Test simple writeImage, no header checks
+                DngCreator dngCreator = new DngCreator(characteristics, resultPair.second);
+                Location l = new Location("test");
+                l.reset();
+                l.setLatitude(37.420016);
+                l.setLongitude(-122.081987);
+                l.setTime(System.currentTimeMillis());
+                dngCreator.setLocation(l);
+
+                dngCreator.setDescription("helloworld");
+                dngCreator.setOrientation(ExifInterface.ORIENTATION_FLIP_VERTICAL);
+                dngCreator.setThumbnail(resultPair.first.get(1));
+                outputStream = new ByteArrayOutputStream();
+                dngCreator.writeImage(outputStream, resultPair.first.get(0));
+
+                if (VERBOSE) {
+                    String filePath = DEBUG_FILE_NAME_BASE + "camera_" + deviceId + "_" +
+                            DEBUG_DNG_FILE;
+                    // Write out captured DNG file for the first camera device if setprop is enabled
+                    fileStream = new FileOutputStream(filePath);
+                    fileStream.write(outputStream.toByteArray());
+                    fileStream.flush();
+                    fileStream.close();
+                    Log.v(TAG, "Test DNG file for camera " + deviceId + " saved to " + filePath);
+                }
+            } finally {
+                closeDevice(deviceId);
+                for (ImageReader r : captureReaders) {
+                    closeImageReader(r);
+                }
+
+                if (outputStream != null) {
+                    outputStream.close();
+                }
+
+                if (fileStream != null) {
+                    fileStream.close();
+                }
+            }
+        }
+    }
+
+    private Pair<Image, CaptureResult> captureSingleRawShot(Size s, ImageReader captureReader,
+            CameraTestUtils.SimpleImageReaderListener captureListener) throws Exception {
+        List<ImageReader> readers = new ArrayList<ImageReader>();
+        readers.add(captureReader);
+        List<CameraTestUtils.SimpleImageReaderListener> listeners =
+                new ArrayList<CameraTestUtils.SimpleImageReaderListener>();
+        listeners.add(captureListener);
+        Pair<List<Image>, CaptureResult> res = captureSingleRawShot(s, readers, listeners);
+        return new Pair<Image, CaptureResult>(res.first.get(0), res.second);
+    }
+
+    /**
+     * 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<List<Image>, CaptureResult> captureSingleRawShot(Size s, List<ImageReader> captureReaders,
+            List<CameraTestUtils.SimpleImageReaderListener> captureListeners) 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);
+
+
+        // Capture images.
+        List<Surface> outputSurfaces = new ArrayList<Surface>();
+        for (ImageReader captureReader : captureReaders) {
+            Surface captureSurface = captureReader.getSurface();
+            outputSurfaces.add(captureSurface);
+        }
+
+        CaptureRequest.Builder request = prepareCaptureRequestForSurfaces(outputSurfaces);
+        request.set(CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE,
+                CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE_ON);
+        CameraTestUtils.SimpleCaptureCallback resultListener =
+                new CameraTestUtils.SimpleCaptureCallback();
+
+        startCapture(request.build(), /*repeating*/false, resultListener, mHandler);
+
+        // Verify capture result and images
+        CaptureResult result = resultListener.getCaptureResult(CAPTURE_WAIT_TIMEOUT_MS);
+
+        List<Image> resultImages = new ArrayList<Image>();
+        for (CameraTestUtils.SimpleImageReaderListener captureListener : captureListeners) {
+            Image captureImage = captureListener.getImage(CAPTURE_WAIT_TIMEOUT_MS);
+
+            /*CameraTestUtils.validateImage(captureImage, s.getWidth(), s.getHeight(),
+                    ImageFormat.RAW_SENSOR, null);*/
+            resultImages.add(captureImage);
+        }
+        // Stop capture, delete the streams.
+        stopCapture(/*fast*/false);
+
+        return new Pair<List<Image>, CaptureResult>(resultImages, result);
+    }
+
+    private CaptureRequest.Builder prepareCaptureRequestForSurfaces(List<Surface> surfaces)
+            throws Exception {
+        createSession(surfaces);
+
+        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/ExtendedCameraCharacteristicsTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
new file mode 100644
index 0000000..1a00d9e
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
@@ -0,0 +1,497 @@
+/*
+ * 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 android.content.Context;
+import android.graphics.ImageFormat;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraCharacteristics.Key;
+import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.cts.helpers.CameraErrorCollector;
+import android.hardware.camera2.params.BlackLevelPattern;
+import android.hardware.camera2.params.ColorSpaceTransform;
+import android.hardware.camera2.params.StreamConfigurationMap;
+import android.test.AndroidTestCase;
+import android.util.Log;
+import android.util.Rational;
+import android.util.Size;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+import static android.hardware.camera2.cts.helpers.AssertHelpers.*;
+
+/**
+ * Extended tests for static camera characteristics.
+ */
+public class ExtendedCameraCharacteristicsTest extends AndroidTestCase {
+    private static final String TAG = "ExChrsTest"; // must be short so next line doesn't throw
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+
+    private static final String PREFIX_ANDROID = "android";
+    private static final String PREFIX_VENDOR = "com";
+
+    /*
+     * Constants for static RAW metadata.
+     */
+    private static final int MIN_ALLOWABLE_WHITELEVEL = 32; // must have sensor bit depth > 5
+
+    private CameraManager mCameraManager;
+    private List<CameraCharacteristics> mCharacteristics;
+    private String[] mIds;
+    private CameraErrorCollector mCollector;
+
+    private static final Size VGA = new Size(640, 480);
+
+    /*
+     * HW Levels short hand
+     */
+    private static final int LEGACY = CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY;
+    private static final int LIMITED = CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
+    private static final int FULL = CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL;
+    private static final int OPT = Integer.MAX_VALUE;  // For keys that are optional on all hardware levels.
+
+    /*
+     * Capabilities short hand
+     */
+    private static final int NONE = -1;
+    private static final int BC =
+            CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE;
+    private static final int MANUAL_SENSOR =
+            CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR;
+    private static final int RAW =
+            CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW;
+
+    @Override
+    public void setContext(Context context) {
+        super.setContext(context);
+        mCameraManager = (CameraManager)context.getSystemService(Context.CAMERA_SERVICE);
+        assertNotNull("Can't connect to camera manager", mCameraManager);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mIds = mCameraManager.getCameraIdList();
+        mCharacteristics = new ArrayList<>();
+        mCollector = new CameraErrorCollector();
+        for (int i = 0; i < mIds.length; i++) {
+            CameraCharacteristics props = mCameraManager.getCameraCharacteristics(mIds[i]);
+            assertNotNull(String.format("Can't get camera characteristics from: ID %s", mIds[i]),
+                    props);
+            mCharacteristics.add(props);
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mCharacteristics = null;
+
+        try {
+            mCollector.verify();
+        } catch (Throwable e) {
+            // When new Exception(e) is used, exception info will be printed twice.
+            throw new Exception(e.getMessage());
+        } finally {
+            super.tearDown();
+        }
+    }
+
+    /**
+     * Test that the available stream configurations contain a few required formats and sizes.
+     */
+    public void testAvailableStreamConfigs() {
+        int counter = 0;
+        for (CameraCharacteristics c : mCharacteristics) {
+            StreamConfigurationMap config =
+                    c.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+            assertNotNull(String.format("No stream configuration map found for: ID %s",
+                    mIds[counter]), config);
+            int[] outputFormats = config.getOutputFormats();
+
+            // Check required formats exist (JPEG, and YUV_420_888).
+            assertArrayContains(
+                    String.format("No valid YUV_420_888 preview formats found for: ID %s",
+                            mIds[counter]), outputFormats, ImageFormat.YUV_420_888);
+            assertArrayContains(String.format("No JPEG image format for: ID %s",
+                    mIds[counter]), outputFormats, ImageFormat.JPEG);
+
+            Size[] sizes = config.getOutputSizes(ImageFormat.YUV_420_888);
+            CameraTestUtils.assertArrayNotEmpty(sizes,
+                    String.format("No sizes for preview format %x for: ID %s",
+                            ImageFormat.YUV_420_888, mIds[counter]));
+
+            assertArrayContains(String.format(
+                            "Required VGA size not found for format %x for: ID %s",
+                            ImageFormat.YUV_420_888, mIds[counter]), sizes, VGA);
+
+            counter++;
+        }
+    }
+
+    /**
+     * Test {@link CameraCharacteristics#getKeys}
+     */
+    public void testKeys() {
+        int counter = 0;
+        for (CameraCharacteristics c : mCharacteristics) {
+            mCollector.setCameraId(mIds[counter]);
+
+            if (VERBOSE) {
+                Log.v(TAG, "testKeys - testing characteristics for camera " + mIds[counter]);
+            }
+
+            List<CameraCharacteristics.Key<?>> allKeys = c.getKeys();
+            assertNotNull("Camera characteristics keys must not be null", allKeys);
+            assertFalse("Camera characteristics keys must have at least 1 key",
+                    allKeys.isEmpty());
+
+            for (CameraCharacteristics.Key<?> key : allKeys) {
+                assertKeyPrefixValid(key.getName());
+
+                // All characteristics keys listed must never be null
+                mCollector.expectKeyValueNotNull(c, key);
+
+                // TODO: add a check that key must not be @hide
+            }
+
+            /*
+             * List of keys that must be present in camera characteristics (not null).
+             *
+             * Keys for LIMITED, FULL devices might be available despite lacking either
+             * the hardware level or the capability. This is *OK*. This only lists the
+             * *minimal* requirements for a key to be listed.
+             *
+             * LEGACY devices are a bit special since they map to api1 devices, so we know
+             * for a fact most keys are going to be illegal there so they should never be
+             * available.
+             *
+             * (TODO: Codegen this)
+             */
+            {
+                //                                           (Key Name)                                     (HW Level)  (Capabilities <Var-Arg>)
+                expectKeyAvailable(c, CameraCharacteristics.COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES     , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.CONTROL_AE_AVAILABLE_ANTIBANDING_MODES          , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES                      , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES          , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE                   , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.CONTROL_AE_COMPENSATION_STEP                    , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES                      , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.CONTROL_AVAILABLE_EFFECTS                       , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES                   , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES     , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES                     , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.CONTROL_MAX_REGIONS_AE                          , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.CONTROL_MAX_REGIONS_AF                          , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.CONTROL_MAX_REGIONS_AWB                         , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.EDGE_AVAILABLE_EDGE_MODES                       , FULL     ,   NONE                 );
+                expectKeyAvailable(c, CameraCharacteristics.FLASH_INFO_AVAILABLE                            , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES             , OPT      ,   RAW                  );
+                expectKeyAvailable(c, CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL                   , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.JPEG_AVAILABLE_THUMBNAIL_SIZES                  , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.LENS_FACING                                     , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES                   , FULL     ,   MANUAL_SENSOR        );
+                expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_AVAILABLE_FILTER_DENSITIES            , FULL     ,   MANUAL_SENSOR        );
+                expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS               , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION       , LIMITED  ,   MANUAL_SENSOR        );
+                expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_FOCUS_DISTANCE_CALIBRATION            , LIMITED  ,   MANUAL_SENSOR        );
+                expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_HYPERFOCAL_DISTANCE                   , LIMITED  ,   MANUAL_SENSOR        );
+                expectKeyAvailable(c, CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE                , LIMITED  ,   NONE                 );
+                expectKeyAvailable(c, CameraCharacteristics.NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES                  , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC                     , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC_STALLING            , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_RAW                      , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.REQUEST_PARTIAL_RESULT_COUNT                    , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.REQUEST_PIPELINE_MAX_DEPTH                      , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM               , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP                 , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.SCALER_CROPPING_TYPE                            , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.SENSOR_AVAILABLE_TEST_PATTERN_MODES             , LEGACY   ,   NONE                 );
+                expectKeyAvailable(c, CameraCharacteristics.SENSOR_BLACK_LEVEL_PATTERN                      , FULL     ,   MANUAL_SENSOR, RAW   );
+                expectKeyAvailable(c, CameraCharacteristics.SENSOR_CALIBRATION_TRANSFORM1                   , OPT      ,   RAW                  );
+                expectKeyAvailable(c, CameraCharacteristics.SENSOR_CALIBRATION_TRANSFORM2                   , OPT      ,   RAW                  );
+                expectKeyAvailable(c, CameraCharacteristics.SENSOR_COLOR_TRANSFORM1                         , OPT      ,   RAW                  );
+                expectKeyAvailable(c, CameraCharacteristics.SENSOR_COLOR_TRANSFORM2                         , OPT      ,   RAW                  );
+                expectKeyAvailable(c, CameraCharacteristics.SENSOR_FORWARD_MATRIX1                          , OPT      ,   RAW                  );
+                expectKeyAvailable(c, CameraCharacteristics.SENSOR_FORWARD_MATRIX2                          , OPT      ,   RAW                  );
+                expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE                   , LEGACY   ,   BC, RAW              );
+                expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT            , FULL     ,   RAW                  );
+                expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE                 , FULL     ,   MANUAL_SENSOR        );
+                expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_MAX_FRAME_DURATION                  , FULL     ,   MANUAL_SENSOR        );
+                expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE                       , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE                    , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE                   , FULL     ,   MANUAL_SENSOR        );
+                expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_WHITE_LEVEL                         , OPT      ,   RAW                  );
+                expectKeyAvailable(c, CameraCharacteristics.SENSOR_INFO_TIMESTAMP_SOURCE                    , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.SENSOR_MAX_ANALOG_SENSITIVITY                   , FULL     ,   MANUAL_SENSOR        );
+                expectKeyAvailable(c, CameraCharacteristics.SENSOR_ORIENTATION                              , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1                    , OPT      ,   RAW                  );
+                expectKeyAvailable(c, CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT2                    , OPT      ,   RAW                  );
+                expectKeyAvailable(c, CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES     , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES   , OPT      ,   RAW                  );
+                expectKeyAvailable(c, CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT                  , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.SYNC_MAX_LATENCY                                , LEGACY   ,   BC                   );
+                expectKeyAvailable(c, CameraCharacteristics.TONEMAP_AVAILABLE_TONE_MAP_MODES                , FULL     ,   MANUAL_SENSOR        );
+                expectKeyAvailable(c, CameraCharacteristics.TONEMAP_MAX_CURVE_POINTS                        , FULL     ,   MANUAL_SENSOR        );
+
+                // Future: Use column editors for modifying above, ignore line length to keep 1 key per line
+
+                // TODO: check that no other 'android' keys are listed in #getKeys if they aren't in the above list
+            }
+
+            counter++;
+        }
+    }
+
+    /**
+     * Test values for static metadata used by the RAW capability.
+     */
+    public void testStaticRawCharacteristics() {
+        int counter = 0;
+        for (CameraCharacteristics c : mCharacteristics) {
+            int[] actualCapabilities = c.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
+            assertNotNull("android.request.availableCapabilities must never be null");
+            if (!arrayContains(actualCapabilities,
+                    CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)) {
+                Log.i(TAG, "RAW capability is not supported in camera " + counter++ +
+                        ". Skip the test.");
+                continue;
+            }
+
+            Integer actualHwLevel = c.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
+            if (actualHwLevel != null && actualHwLevel == FULL) {
+                mCollector.expectKeyValueContains(c,
+                        CameraCharacteristics.HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES,
+                        CameraCharacteristics.HOT_PIXEL_MODE_FAST);
+            }
+            mCollector.expectKeyValueContains(c,
+                    CameraCharacteristics.STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES, false);
+            mCollector.expectKeyValueGreaterThan(c, CameraCharacteristics.SENSOR_INFO_WHITE_LEVEL,
+                    MIN_ALLOWABLE_WHITELEVEL);
+
+            mCollector.expectKeyValueIsIn(c,
+                    CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,
+                    CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB,
+                    CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG,
+                    CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG,
+                    CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR);
+            // TODO: SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB isn't supported yet.
+
+            mCollector.expectKeyValueInRange(c, CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1,
+                    CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT,
+                    CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1_ISO_STUDIO_TUNGSTEN);
+            mCollector.expectKeyValueInRange(c, CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT2,
+                    (byte) CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT,
+                    (byte) CameraCharacteristics.SENSOR_REFERENCE_ILLUMINANT1_ISO_STUDIO_TUNGSTEN);
+
+            Rational[] zeroes = new Rational[9];
+            Arrays.fill(zeroes, Rational.ZERO);
+
+            ColorSpaceTransform zeroed = new ColorSpaceTransform(zeroes);
+            mCollector.expectNotEquals("Forward Matrix1 should not contain all zeroes.", zeroed,
+                    c.get(CameraCharacteristics.SENSOR_FORWARD_MATRIX1));
+            mCollector.expectNotEquals("Forward Matrix2 should not contain all zeroes.", zeroed,
+                    c.get(CameraCharacteristics.SENSOR_FORWARD_MATRIX2));
+            mCollector.expectNotEquals("Calibration Transform1 should not contain all zeroes.",
+                    zeroed, c.get(CameraCharacteristics.SENSOR_CALIBRATION_TRANSFORM1));
+            mCollector.expectNotEquals("Calibration Transform2 should not contain all zeroes.",
+                    zeroed, c.get(CameraCharacteristics.SENSOR_CALIBRATION_TRANSFORM2));
+            mCollector.expectNotEquals("Color Transform1 should not contain all zeroes.",
+                    zeroed, c.get(CameraCharacteristics.SENSOR_COLOR_TRANSFORM1));
+            mCollector.expectNotEquals("Color Transform2 should not contain all zeroes.",
+                    zeroed, c.get(CameraCharacteristics.SENSOR_COLOR_TRANSFORM2));
+
+            BlackLevelPattern blackLevel = mCollector.expectKeyValueNotNull(c,
+                    CameraCharacteristics.SENSOR_BLACK_LEVEL_PATTERN);
+            if (blackLevel != null) {
+                int[] blackLevelPattern = new int[BlackLevelPattern.COUNT];
+                blackLevel.copyTo(blackLevelPattern, /*offset*/0);
+                Integer whitelevel = c.get(CameraCharacteristics.SENSOR_INFO_WHITE_LEVEL);
+                if (whitelevel != null) {
+                    mCollector.expectValuesInRange("BlackLevelPattern", blackLevelPattern, 0,
+                            whitelevel);
+                } else {
+                    mCollector.addMessage(
+                            "No WhiteLevel available, cannot check BlackLevelPattern range.");
+                }
+            }
+
+            // TODO: profileHueSatMap, and profileToneCurve aren't supported yet.
+            counter++;
+        }
+    }
+
+    /**
+     * Check key is present in characteristics if the hardware level is at least {@code hwLevel};
+     * check that the key is present if the actual capabilities are one of {@code capabilities}.
+     *
+     * @return value of the {@code key} from {@code c}
+     */
+    private <T> T expectKeyAvailable(CameraCharacteristics c, CameraCharacteristics.Key<T> key,
+            int hwLevel, int... capabilities) {
+
+        Integer actualHwLevel = c.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
+        assertNotNull("android.info.supportedHardwareLevel must never be null", actualHwLevel);
+
+        int[] actualCapabilities = c.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
+        assertNotNull("android.request.availableCapabilities must never be null");
+
+        List<Key<?>> allKeys = c.getKeys();
+
+        T value = c.get(key);
+
+        if (compareHardwareLevel(actualHwLevel, hwLevel) >= 0) {
+            mCollector.expectTrue(
+                    String.format("Key (%s) must be in characteristics for this hardware level " +
+                            "(required minimal HW level %s, actual HW level %s)",
+                            key.getName(), toStringHardwareLevel(hwLevel),
+                            toStringHardwareLevel(actualHwLevel)),
+                    value != null);
+            mCollector.expectTrue(
+                    String.format("Key (%s) must be in characteristics list of keys for this " +
+                            "hardware level (required minimal HW level %s, actual HW level %s)",
+                            key.getName(), toStringHardwareLevel(hwLevel),
+                            toStringHardwareLevel(actualHwLevel)),
+                    allKeys.contains(key));
+        } else if (arrayContainsAnyOf(actualCapabilities, capabilities)) {
+            mCollector.expectTrue(
+                    String.format("Key (%s) must be in characteristics for these capabilities " +
+                            "(required capabilities %s, actual capabilities %s)",
+                            key.getName(), Arrays.toString(capabilities),
+                            Arrays.toString(actualCapabilities)),
+                    value != null);
+            mCollector.expectTrue(
+                    String.format("Key (%s) must be in characteristics list of keys for " +
+                            "these capabilities (required capabilities %s, actual capabilities %s)",
+                            key.getName(), Arrays.toString(capabilities),
+                            Arrays.toString(actualCapabilities)),
+                    allKeys.contains(key));
+        } else {
+            if (actualHwLevel == LEGACY && hwLevel != OPT) {
+                if (value != null || allKeys.contains(key)) {
+                    Log.w(TAG, String.format(
+                            "Key (%s) is not required for LEGACY devices but still appears",
+                            key.getName()));
+                }
+            }
+            // OK: Key may or may not be present.
+        }
+        return value;
+    }
+
+    private static boolean arrayContains(int[] arr, int needle) {
+        if (arr == null) {
+            return false;
+        }
+
+        for (int elem : arr) {
+            if (elem == needle) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    private static boolean arrayContainsAnyOf(int[] arr, int[] needles) {
+        for (int needle : needles) {
+            if (arrayContains(arr, needle)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * The key name has a prefix of either "android." or "com."; other prefixes are not valid.
+     */
+    private static void assertKeyPrefixValid(String keyName) {
+        assertStartsWithAnyOf(
+                "All metadata keys must start with 'android.' (built-in keys) " +
+                "or 'com.' (vendor-extended keys)", new String[] {
+                        PREFIX_ANDROID + ".",
+                        PREFIX_VENDOR + ".",
+                }, keyName);
+    }
+
+    private static void assertTrueForKey(String msg, CameraCharacteristics.Key<?> key,
+            boolean actual) {
+        assertTrue(msg + " (key = '" + key.getName() + "')", actual);
+    }
+
+    private static <T> void assertOneOf(String msg, T[] expected, T actual) {
+        for (int i = 0; i < expected.length; ++i) {
+            if (Objects.equals(expected[i], actual)) {
+                return;
+            }
+        }
+
+        fail(String.format("%s: (expected one of %s, actual %s)",
+                msg, Arrays.toString(expected), actual));
+    }
+
+    private static <T> void assertStartsWithAnyOf(String msg, String[] expected, String actual) {
+        for (int i = 0; i < expected.length; ++i) {
+            if (actual.startsWith(expected[i])) {
+                return;
+            }
+        }
+
+        fail(String.format("%s: (expected to start with any of %s, but value was %s)",
+                msg, Arrays.toString(expected), actual));
+    }
+
+    /** Return a positive int if left > right, 0 if left==right, negative int if left < right */
+    private static int compareHardwareLevel(int left, int right) {
+        return remapHardwareLevel(left) - remapHardwareLevel(right);
+    }
+
+    /** Remap HW levels worst<->best, 0 = worst, 2 = best */
+    private static int remapHardwareLevel(int level) {
+        switch (level) {
+            case OPT:
+                return Integer.MAX_VALUE;
+            case LEGACY:
+                return 0; // lowest
+            case LIMITED:
+                return 1; // second lowest
+            case FULL:
+                return 2; // best
+        }
+
+        fail("Unknown HW level: " + level);
+        return -1;
+    }
+
+    private static String toStringHardwareLevel(int level) {
+        switch (level) {
+            case LEGACY:
+                return "LEGACY";
+            case LIMITED:
+                return "LIMITED";
+            case FULL:
+                return "FULL";
+        }
+
+        // unknown
+        Log.w(TAG, "Unknown hardware level " + level);
+        return Integer.toString(level);
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/ImageReaderTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/ImageReaderTest.java
index 28cb13e..61f25fb 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/ImageReaderTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/ImageReaderTest.java
@@ -17,30 +17,23 @@
 package android.hardware.camera2.cts;
 
 import static android.hardware.camera2.cts.CameraTestUtils.*;
-import static com.android.ex.camera2.blocking.BlockingStateListener.*;
 
 import android.content.Context;
-import android.graphics.BitmapFactory;
 import android.graphics.ImageFormat;
-import android.hardware.camera2.CameraAccessException;
 import android.hardware.camera2.CameraDevice;
-import android.hardware.camera2.CameraManager;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CaptureRequest;
-import android.hardware.camera2.Size;
+import android.hardware.camera2.CaptureResult;
+import android.util.Size;
+import android.hardware.camera2.cts.helpers.StaticMetadata;
+import android.hardware.camera2.cts.testcases.Camera2AndroidTestCase;
 import android.media.Image;
 import android.media.ImageReader;
-import android.os.Environment;
-import android.os.Handler;
-import android.test.AndroidTestCase;
+import android.os.ConditionVariable;
 import android.util.Log;
 import android.view.Surface;
 
-import com.android.ex.camera2.blocking.BlockingCameraManager.BlockingOpenException;
-import com.android.ex.camera2.blocking.BlockingStateListener;
-
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -53,305 +46,397 @@
  * <p>Some invalid access test. </p>
  * <p>TODO: Add more format tests? </p>
  */
-public class ImageReaderTest extends AndroidTestCase {
+public class ImageReaderTest extends Camera2AndroidTestCase {
     private static final String TAG = "ImageReaderTest";
     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
-    private static final boolean DUMP_FILE = false;
-    private static final String DEBUG_FILE_NAME_BASE =
-            Environment.getExternalStorageDirectory().getPath();
     // number of frame (for streaming requests) to be verified.
-    // TODO: Need extend it to bigger number
-    private static final int NUM_FRAME_VERIFIED = 1;
+    private static final int NUM_FRAME_VERIFIED = 2;
     // Max number of images can be accessed simultaneously from ImageReader.
     private static final int MAX_NUM_IMAGES = 5;
 
-    private CameraManager mCameraManager;
-    private CameraDevice mCamera;
-    private BlockingStateListener mCameraListener;
-    private String[] mCameraIds;
-    private ImageReader mReader = null;
-    private Handler mHandler = null;
-    private SimpleImageListener mListener = null;
-    private CameraTestThread mLooperThread = null;
+    private SimpleImageListener mListener;
 
     @Override
     public void setContext(Context context) {
         super.setContext(context);
-        mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
-        assertNotNull("Can't connect to camera manager!", mCameraManager);
     }
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mCameraIds = mCameraManager.getCameraIdList();
-        mLooperThread = new CameraTestThread();
-        mHandler = mLooperThread.start();
-        mCameraListener = new BlockingStateListener();
     }
 
     @Override
     protected void tearDown() throws Exception {
-        if (mCamera != null) {
-            mCamera.close();
-            mCamera = null;
-        }
-        if (mReader != null) {
-            mReader.close();
-            mReader = null;
-        }
-        mLooperThread.close();
-        mHandler = null;
         super.tearDown();
     }
 
-    public void testImageReaderFromCameraFlexibleYuv() throws Exception {
-        for (int i = 0; i < mCameraIds.length; i++) {
-            Log.i(TAG, "Testing Camera " + mCameraIds[i]);
-            openDevice(mCameraIds[i]);
-            bufferFormatTestByCamera(ImageFormat.YUV_420_888, mCameraIds[i]);
-            closeDevice(mCameraIds[i]);
+    public void testFlexibleYuv() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                Log.i(TAG, "Testing Camera " + id);
+                openDevice(id);
+                bufferFormatTestByCamera(ImageFormat.YUV_420_888, /*repeating*/true);
+            } finally {
+                closeDevice(id);
+            }
         }
     }
 
-    public void testImageReaderFromCameraJpeg() throws Exception {
-        for (int i = 0; i < mCameraIds.length; i++) {
-            Log.v(TAG, "Testing Camera " + mCameraIds[i]);
-            openDevice(mCameraIds[i]);
-            bufferFormatTestByCamera(ImageFormat.JPEG, mCameraIds[i]);
-            closeDevice(mCameraIds[i]);
+    public void testJpeg() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                Log.v(TAG, "Testing jpeg capture for Camera " + id);
+                openDevice(id);
+                if (mStaticInfo.isHardwareLevelLegacy()) {
+                    Log.i(TAG, "Skipping test on legacy devices");
+                    continue;
+                }
+                bufferFormatTestByCamera(ImageFormat.JPEG, /*repeating*/false);
+            } finally {
+                closeDevice(id);
+            }
         }
     }
 
-    public void testImageReaderFromCameraRaw() {
-        // TODO: can test this once raw is supported
+    public void testRaw() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                Log.v(TAG, "Testing raw capture for camera " + id);
+                openDevice(id);
+
+                bufferFormatTestByCamera(ImageFormat.RAW_SENSOR, /*repeating*/false);
+            } finally {
+                closeDevice(id);
+            }
+        }
     }
 
-    public void testImageReaderInvalidAccessTest() {
+    public void testRepeatingJpeg() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                Log.v(TAG, "Testing repeating jpeg capture for Camera " + id);
+                openDevice(id);
+                if (mStaticInfo.isHardwareLevelLegacy()) {
+                    Log.i(TAG, "Skipping test on legacy devices");
+                    continue;
+                }
+                bufferFormatTestByCamera(ImageFormat.JPEG, /*repeating*/true);
+            } finally {
+                closeDevice(id);
+            }
+        }
+    }
+
+    public void testRepeatingRaw() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                Log.v(TAG, "Testing repeating raw capture for camera " + id);
+                openDevice(id);
+
+                bufferFormatTestByCamera(ImageFormat.RAW_SENSOR, /*repeating*/true);
+            } finally {
+                closeDevice(id);
+            }
+        }
+    }
+
+    public void testInvalidAccessTest() {
         // TODO: test invalid access case, see if we can receive expected
         // exceptions
     }
 
-    private void bufferFormatTestByCamera(int format, String cameraId) throws Exception {
-        CameraCharacteristics properties = mCameraManager.getCameraCharacteristics(cameraId);
-        assertNotNull("Can't get camera properties!", properties);
+    /**
+     * Test two image stream (YUV420_888 and JPEG) capture by using ImageReader.
+     *
+     * <p>Both stream formats are mandatory for Camera2 API</p>
+     */
+    public void testYuvAndJpeg() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                Log.v(TAG, "YUV and JPEG testing for camera " + id);
+                openDevice(id);
+                if (mStaticInfo.isHardwareLevelLegacy()) {
+                    Log.i(TAG, "Skipping test on legacy devices");
+                    continue;
+                }
+                bufferFormatWithYuvTestByCamera(ImageFormat.JPEG);
+            } finally {
+                closeDevice(id);
+            }
+        }
+    }
 
-        /**
-         * TODO: cleanup the color format mess, we probably need define formats
-         * in Image class instead of using ImageFormat for camera. also,
-         * probably make sense to change the available format type from Enum[]
-         * to int[]. It'll also be nice to put this into a helper function and
-         * move to util class.
-         */
-        int[] availableFormats = properties.get(CameraCharacteristics.SCALER_AVAILABLE_FORMATS);
-        assertArrayNotEmpty(availableFormats,
-                "availableFormats should not be empty");
-        Arrays.sort(availableFormats);
-        assertTrue("Can't find the format " + format + " in supported formats " +
-                Arrays.toString(availableFormats),
-                Arrays.binarySearch(availableFormats, format) >= 0);
+    /**
+     * Test two image stream (YUV420_888 and RAW_SENSOR) capture by using ImageReader.
+     *
+     */
+    public void testImageReaderYuvAndRaw() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                Log.v(TAG, "YUV and RAW testing for camera " + id);
+                openDevice(id);
 
-        Size[] availableSizes = getSupportedSizeForFormat(format, mCamera.getId(), mCameraManager);
-        assertArrayNotEmpty(availableSizes, "availableSizes should not be empty");
+                bufferFormatWithYuvTestByCamera(ImageFormat.RAW_SENSOR);
+            } finally {
+                closeDevice(id);
+            }
+        }
+    }
+
+
+    /**
+     * Test capture a given format stream with yuv stream simultaneously.
+     *
+     * <p>Use fixed yuv size, varies targeted format capture size. Single capture is tested.</p>
+     *
+     * @param format The capture format to be tested along with yuv format.
+     */
+    private void bufferFormatWithYuvTestByCamera(int format) throws Exception {
+        if (format != ImageFormat.JPEG && format != ImageFormat.RAW_SENSOR
+                && format != ImageFormat.YUV_420_888) {
+            throw new IllegalArgumentException("Unsupported format: " + format);
+        }
+
+        final int NUM_SINGLE_CAPTURE_TESTED = MAX_NUM_IMAGES - 1;
+        Size maxYuvSz = mOrderedPreviewSizes.get(0);
+        Size[] targetCaptureSizes = mStaticInfo.getAvailableSizesForFormatChecked(format,
+                StaticMetadata.StreamDirection.Output);
+
+        for (Size captureSz : targetCaptureSizes) {
+            if (VERBOSE) {
+                Log.v(TAG, "Testing yuv size " + maxYuvSz.toString() + " and capture size "
+                        + captureSz.toString() + " for camera " + mCamera.getId());
+            }
+
+            ImageReader captureReader = null;
+            ImageReader yuvReader = null;
+            try {
+                // Create YUV image reader
+                SimpleImageReaderListener yuvListener  = new SimpleImageReaderListener();
+                yuvReader = createImageReader(maxYuvSz, ImageFormat.YUV_420_888, MAX_NUM_IMAGES,
+                        yuvListener);
+                Surface yuvSurface = yuvReader.getSurface();
+
+                // Create capture image reader
+                SimpleImageReaderListener captureListener = new SimpleImageReaderListener();
+                captureReader = createImageReader(captureSz, format, MAX_NUM_IMAGES,
+                        captureListener);
+                Surface captureSurface = captureReader.getSurface();
+
+                // Capture images.
+                List<Surface> outputSurfaces = new ArrayList<Surface>();
+                outputSurfaces.add(yuvSurface);
+                outputSurfaces.add(captureSurface);
+                CaptureRequest.Builder request = prepareCaptureRequestForSurfaces(outputSurfaces);
+                SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
+
+                for (int i = 0; i < NUM_SINGLE_CAPTURE_TESTED; i++) {
+                    startCapture(request.build(), /*repeating*/false, resultListener, mHandler);
+                }
+
+                // Verify capture result and images
+                for (int i = 0; i < NUM_SINGLE_CAPTURE_TESTED; i++) {
+                    resultListener.getCaptureResult(CAPTURE_WAIT_TIMEOUT_MS);
+                    if (VERBOSE) {
+                        Log.v(TAG, " Got the capture result back for " + i + "th capture");
+                    }
+
+                    Image yuvImage = yuvListener.getImage(CAPTURE_WAIT_TIMEOUT_MS);
+                    if (VERBOSE) {
+                        Log.v(TAG, " Got the yuv image back for " + i + "th capture");
+                    }
+
+                    Image captureImage = captureListener.getImage(CAPTURE_WAIT_TIMEOUT_MS);
+                    if (VERBOSE) {
+                        Log.v(TAG, " Got the capture image back for " + i + "th capture");
+                    }
+
+                    //Validate captured images.
+                    CameraTestUtils.validateImage(yuvImage, maxYuvSz.getWidth(),
+                            maxYuvSz.getHeight(), ImageFormat.YUV_420_888, /*filePath*/null);
+                    CameraTestUtils.validateImage(captureImage, captureSz.getWidth(),
+                            captureSz.getHeight(), format, /*filePath*/null);
+                }
+
+                // Stop capture, delete the streams.
+                stopCapture(/*fast*/false);
+            } finally {
+                closeImageReader(captureReader);
+                captureReader = null;
+                closeImageReader(yuvReader);
+                yuvReader = null;
+            }
+        }
+    }
+
+    private void bufferFormatTestByCamera(int format, boolean repeating) throws Exception {
+
+        Size[] availableSizes = mStaticInfo.getAvailableSizesForFormatChecked(format,
+                StaticMetadata.StreamDirection.Output);
 
         // for each resolution, test imageReader:
         for (Size sz : availableSizes) {
-            if (VERBOSE) Log.v(TAG, "Testing size " + sz.toString() + " for camera " + cameraId);
+            try {
+                if (VERBOSE) {
+                    Log.v(TAG, "Testing size " + sz.toString() + " format " + format
+                            + " for camera " + mCamera.getId());
+                }
 
-            prepareImageReader(sz, format);
+                // Create ImageReader.
+                mListener  = new SimpleImageListener();
+                createDefaultImageReader(sz, format, MAX_NUM_IMAGES, mListener);
 
-            CaptureRequest request = prepareCaptureRequest(format);
+                // Start capture.
+                CaptureRequest request = prepareCaptureRequest();
+                SimpleCaptureCallback listener = new SimpleCaptureCallback();
+                startCapture(request, repeating, listener, mHandler);
 
-            captureAndValidateImage(request, sz, format);
+                int numFrameVerified = repeating ? NUM_FRAME_VERIFIED : 1;
 
-            stopCapture();
+                // Validate images.
+                validateImage(sz, format, numFrameVerified, repeating);
+
+                // Validate capture result.
+                validateCaptureResult(format, sz, listener, numFrameVerified);
+
+                // stop capture.
+                stopCapture(/*fast*/false);
+            } finally {
+                closeDefaultImageReader();
+            }
+
         }
     }
 
-    private class SimpleImageListener implements ImageReader.OnImageAvailableListener {
-        private int mPendingImages = 0;
-        private final Object mImageSyncObject = new Object();
+    /**
+     * Validate capture results.
+     *
+     * @param format The format of this capture.
+     * @param size The capture size.
+     * @param listener The capture listener to get capture result callbacks.
+     */
+    private void validateCaptureResult(int format, Size size, SimpleCaptureCallback listener,
+            int numFrameVerified) {
+        for (int i = 0; i < numFrameVerified; i++) {
+            CaptureResult result = listener.getCaptureResult(CAPTURE_RESULT_TIMEOUT_MS);
 
+            // TODO: Update this to use availableResultKeys once shim supports this.
+            if (mStaticInfo.isCapabilitySupported(
+                    CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
+                Long exposureTime = getValueNotNull(result, CaptureResult.SENSOR_EXPOSURE_TIME);
+                Integer sensitivity = getValueNotNull(result, CaptureResult.SENSOR_SENSITIVITY);
+                mCollector.expectInRange(
+                        String.format(
+                                "Capture for format %d, size %s exposure time is invalid.",
+                                format, size.toString()),
+                        exposureTime,
+                        mStaticInfo.getExposureMinimumOrDefault(),
+                        mStaticInfo.getExposureMaximumOrDefault()
+                );
+                mCollector.expectInRange(
+                        String.format("Capture for format %d, size %s sensitivity is invalid.",
+                                format, size.toString()),
+                        sensitivity,
+                        mStaticInfo.getSensitivityMinimumOrDefault(),
+                        mStaticInfo.getSensitivityMaximumOrDefault()
+                );
+            }
+            // TODO: add more key validations.
+        }
+    }
+
+    private final class SimpleImageListener implements ImageReader.OnImageAvailableListener {
+        private final ConditionVariable imageAvailable = new ConditionVariable();
         @Override
         public void onImageAvailable(ImageReader reader) {
+            if (mReader != reader) {
+                return;
+            }
+
             if (VERBOSE) Log.v(TAG, "new image available");
-            synchronized (mImageSyncObject) {
-                mPendingImages++;
-                mImageSyncObject.notifyAll();
+            imageAvailable.open();
+        }
+
+        public void waitForAnyImageAvailable(long timeout) {
+            if (imageAvailable.block(timeout)) {
+                imageAvailable.close();
+            } else {
+                fail("wait for image available timed out after " + timeout + "ms");
             }
         }
 
-        public boolean isImagePending() {
-            synchronized (mImageSyncObject) {
-                return (mPendingImages > 0);
-            }
-        }
-
-        public void waitForImage() {
-            final int TIMEOUT_MS = 5000;
-            synchronized (mImageSyncObject) {
-                while (mPendingImages == 0) {
-                    try {
-                        if (VERBOSE)
-                            Log.d(TAG, "waiting for next image");
-                        mImageSyncObject.wait(TIMEOUT_MS);
-                        if (mPendingImages == 0) {
-                            fail("wait for next image timed out");
-                        }
-                    } catch (InterruptedException ie) {
-                        throw new RuntimeException(ie);
-                    }
-                }
-                mPendingImages--;
+        public void closePendingImages() {
+            Image image = mReader.acquireLatestImage();
+            if (image != null) {
+                image.close();
             }
         }
     }
 
-    private void prepareImageReader(Size sz, int format) throws Exception {
-        int width = sz.getWidth();
-        int height = sz.getHeight();
-        mReader = ImageReader.newInstance(width, height, format, MAX_NUM_IMAGES);
-        mListener  = new SimpleImageListener();
-        mReader.setOnImageAvailableListener(mListener, mHandler);
-        if (VERBOSE) Log.v(TAG, "Preparing ImageReader size " + sz.toString());
-    }
-
-    private CaptureRequest prepareCaptureRequest(int format) throws Exception {
-        List<Surface> outputSurfaces = new ArrayList<Surface>(1);
+    private CaptureRequest prepareCaptureRequest() throws Exception {
+        List<Surface> outputSurfaces = new ArrayList<Surface>();
         Surface surface = mReader.getSurface();
         assertNotNull("Fail to get surface from ImageReader", surface);
         outputSurfaces.add(surface);
-        mCamera.configureOutputs(outputSurfaces);
-        mCameraListener.waitForState(STATE_BUSY, CAMERA_BUSY_TIMEOUT_MS);
-        mCameraListener.waitForState(STATE_IDLE, CAMERA_IDLE_TIMEOUT_MS);
+        return prepareCaptureRequestForSurfaces(outputSurfaces).build();
+    }
+
+    private CaptureRequest.Builder prepareCaptureRequestForSurfaces(List<Surface> surfaces)
+            throws Exception {
+        createSession(surfaces);
 
         CaptureRequest.Builder captureBuilder =
                 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
         assertNotNull("Fail to get captureRequest", captureBuilder);
-        captureBuilder.addTarget(mReader.getSurface());
+        for (Surface surface : surfaces) {
+            captureBuilder.addTarget(surface);
+        }
 
-        return captureBuilder.build();
+        return captureBuilder;
     }
 
-    private void captureAndValidateImage(CaptureRequest request,
-            Size sz, int format) throws Exception {
+    private void validateImage(Size sz, int format, int captureCount,  boolean repeating)
+            throws Exception {
         // TODO: Add more format here, and wrap each one as a function.
         Image img;
-        int captureCount = NUM_FRAME_VERIFIED;
-
-        // Only verify single image for still capture
-        if (format == ImageFormat.JPEG) {
-            captureCount = 1;
-            mCamera.capture(request, null, null);
-        } else {
-            mCamera.setRepeatingRequest(request, null, null);
-        }
-
-        for (int i = 0; i < captureCount; i++) {
+        final int MAX_RETRY_COUNT = 20;
+        int numImageVerified = 0;
+        int reTryCount = 0;
+        while (numImageVerified < captureCount) {
             assertNotNull("Image listener is null", mListener);
             if (VERBOSE) Log.v(TAG, "Waiting for an Image");
-            mListener.waitForImage();
-            img = mReader.acquireNextImage();
-            if (VERBOSE) Log.v(TAG, "Got next image");
-            validateImage(img, sz.getWidth(), sz.getHeight(), format);
-            img.close();
-            // Return the pending images to producer in case the validation is slower
-            // than the image producing rate. Otherwise, it could cause the producer
-            // starvation.
-            while (mListener.isImagePending()) {
-                mListener.waitForImage();
+            mListener.waitForAnyImageAvailable(CAPTURE_WAIT_TIMEOUT_MS);
+            if (repeating) {
+                /**
+                 * Acquire the latest image in case the validation is slower than
+                 * the image producing rate.
+                 */
+                img = mReader.acquireLatestImage();
+                /**
+                 * Sometimes if multiple onImageAvailable callbacks being queued,
+                 * acquireLatestImage will clear all buffer before corresponding callback is
+                 * executed. Wait for a new frame in that case.
+                 */
+                if (img == null && reTryCount < MAX_RETRY_COUNT) {
+                    reTryCount++;
+                    continue;
+                }
+            } else {
                 img = mReader.acquireNextImage();
-                img.close();
             }
+            assertNotNull("Unable to acquire the latest image", img);
+            if (VERBOSE) Log.v(TAG, "Got the latest image");
+            CameraTestUtils.validateImage(img, sz.getWidth(), sz.getHeight(), format,
+                    DEBUG_FILE_NAME_BASE);
+            if (VERBOSE) Log.v(TAG, "finish vaildation of image " + numImageVerified);
+            img.close();
+            numImageVerified++;
+            reTryCount = 0;
         }
-    }
 
-    private void stopCapture() throws CameraAccessException {
-        if (VERBOSE) Log.v(TAG, "Stopping capture and waiting for idle");
-        // Stop repeat, wait for captures to complete, and disconnect from surfaces
-        mCamera.configureOutputs(/*outputs*/ null);
-        mCameraListener.waitForState(STATE_BUSY, CAMERA_BUSY_TIMEOUT_MS);
-        mCameraListener.waitForState(STATE_UNCONFIGURED, CAMERA_IDLE_TIMEOUT_MS);
-        // Camera has disconnected, clear out the reader
-        mReader.close();
-        mReader = null;
-        mListener = null;
-    }
-
-    private void openDevice(String cameraId) {
-        if (mCamera != null) {
-            throw new IllegalStateException("Already have open camera device");
-        }
-        try {
-            mCamera = CameraTestUtils.openCamera(
-                mCameraManager, cameraId, mCameraListener, mHandler);
-        } catch (CameraAccessException e) {
-            mCamera = null;
-            fail("Fail to open camera, " + Log.getStackTraceString(e));
-        } catch (BlockingOpenException e) {
-            mCamera = null;
-            fail("Fail to open camera, " + Log.getStackTraceString(e));
-        }
-        mCameraListener.waitForState(STATE_UNCONFIGURED, CAMERA_OPEN_TIMEOUT_MS);
-    }
-
-    private void closeDevice(String cameraId) {
-        mCamera.close();
-        mCamera = null;
-    }
-
-    private void validateImage(Image image, int width, int height, int format) {
-        checkImage(image, width, height, format);
-
-        /**
-         * TODO: validate timestamp:
-         * 1. capture result timestamp against the image timestamp (need
-         * consider frame drops)
-         * 2. timestamps should be monotonically increasing for different requests
-         */
-        if(VERBOSE) Log.v(TAG, "validating Image");
-        byte[] data = getDataFromImage(image);
-        assertTrue("Invalid image data", data != null && data.length > 0);
-
-        if (format == ImageFormat.JPEG) {
-            validateJpegData(data, width, height);
-        } else {
-            validateYuvData(data, width, height, format, image.getTimestamp());
-        }
-    }
-
-    private void validateJpegData(byte[] jpegData, int width, int height) {
-        BitmapFactory.Options bmpOptions = new BitmapFactory.Options();
-        // DecodeBound mode: only parse the frame header to get width/height.
-        // it doesn't decode the pixel.
-        bmpOptions.inJustDecodeBounds = true;
-        BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, bmpOptions);
-        assertEquals(width, bmpOptions.outWidth);
-        assertEquals(height, bmpOptions.outHeight);
-
-        // Pixel decoding mode: decode whole image. check if the image data
-        // is decodable here.
-        assertNotNull("Decoding jpeg failed",
-                BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length));
-        if (DUMP_FILE) {
-            String fileName =
-                    DEBUG_FILE_NAME_BASE + width + "x" + height + ".yuv";
-            dumpFile(fileName, jpegData);
-        }
-    }
-
-    private void validateYuvData(byte[] yuvData, int width, int height, int format, long ts) {
-        checkYuvFormat(format);
-        if (VERBOSE) Log.v(TAG, "Validating YUV data");
-        int expectedSize = width * height * ImageFormat.getBitsPerPixel(format) / 8;
-        assertEquals("Yuv data doesn't match", expectedSize, yuvData.length);
-
-        // TODO: Can add data validation if we have test pattern(tracked by b/9625427)
-
-        if (DUMP_FILE) {
-            String fileName =
-                    DEBUG_FILE_NAME_BASE + "/" + width + "x" + height + "_" + ts / 1e6 + ".yuv";
-            dumpFile(fileName, yuvData);
-        }
+        // Return all pending images to the ImageReader as the validateImage may
+        // take a while to return and there could be many images pending.
+        mListener.closePendingImages();
     }
 }
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/MultiViewTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/MultiViewTest.java
new file mode 100644
index 0000000..0d0ecb4
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/MultiViewTest.java
@@ -0,0 +1,245 @@
+/*
+ * 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.cts.CameraTestUtils.*;
+
+import android.graphics.ImageFormat;
+import android.graphics.SurfaceTexture;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.cts.CameraTestUtils.ImageVerifierListener;
+import android.hardware.camera2.cts.testcases.Camera2MultiViewTestCase;
+import android.hardware.camera2.cts.testcases.Camera2MultiViewTestCase.CameraPreviewListener;
+import android.media.ImageReader;
+import android.os.SystemClock;
+import android.util.Log;
+import android.util.Size;
+import android.view.Surface;
+import android.view.TextureView;
+
+import com.android.ex.camera2.blocking.BlockingCameraManager.BlockingOpenException;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * CameraDevice test by using combination of SurfaceView, TextureView and ImageReader
+ */
+public class MultiViewTest extends Camera2MultiViewTestCase {
+    private static final String TAG = "MultiViewTest";
+    private final static long WAIT_FOR_COMMAND_TO_COMPLETE = 2000;
+    private final static long PREVIEW_TIME_MS = 2000;
+
+    public void testTextureViewPreview() throws Exception {
+        for (String cameraId : mCameraIds) {
+            openCamera(cameraId);
+            List<TextureView> views = Arrays.asList(mTextureView[0]);
+            textureViewPreview(cameraId, views, /*ImageReader*/null);
+            closeCamera(cameraId);
+        }
+    }
+
+    public void testTextureViewPreviewWithImageReader() throws Exception {
+        for (String cameraId : mCameraIds) {
+            Exception prior = null;
+
+            ImageVerifierListener yuvListener;
+            ImageReader yuvReader;
+
+            try {
+                openCamera(cameraId);
+                Size previewSize = getOrderedPreviewSizes(cameraId).get(0);
+                yuvListener =
+                        new ImageVerifierListener(previewSize, ImageFormat.YUV_420_888);
+                yuvReader = makeImageReader(previewSize,
+                        ImageFormat.YUV_420_888, MAX_READER_IMAGES, yuvListener, mHandler);
+                int maxNumStreamsProc =
+                        getStaticInfo(cameraId).getMaxNumOutputStreamsProcessedChecked();
+                if (maxNumStreamsProc < 2) {
+                    continue;
+                }
+                List<TextureView> views = Arrays.asList(mTextureView[0]);
+                textureViewPreview(cameraId, views, yuvReader);
+            } catch (Exception e) {
+                prior = e;
+            } finally {
+                try {
+                    closeCamera(cameraId);
+                } catch (Exception e) {
+                    if (prior != null) {
+                        Log.e(TAG, "Prior exception received: " + prior);
+                    }
+                    prior = e;
+                }
+                if (prior != null) throw prior; // Rethrow last exception.
+            }
+        }
+    }
+
+    public void testDualTextureViewPreview() throws Exception {
+        for (String cameraId : mCameraIds) {
+            Exception prior = null;
+            try {
+                openCamera(cameraId);
+                int maxNumStreamsProc =
+                        getStaticInfo(cameraId).getMaxNumOutputStreamsProcessedChecked();
+                if (maxNumStreamsProc < 2) {
+                    continue;
+                }
+                List<TextureView> views = Arrays.asList(mTextureView[0], mTextureView[1]);
+                textureViewPreview(cameraId, views, /*ImageReader*/null);
+            } catch (Exception e) {
+                prior = e;
+            } finally {
+                try {
+                    closeCamera(cameraId);
+                } catch (Exception e) {
+                    if (prior != null) {
+                        Log.e(TAG, "Prior exception received: " + prior);
+                    }
+                    prior = e;
+                }
+                if (prior != null) throw prior; // Rethrow last exception.
+            }
+        }
+    }
+
+    public void testDualTextureViewAndImageReaderPreview() throws Exception {
+        for (String cameraId : mCameraIds) {
+            Exception prior = null;
+
+            ImageVerifierListener yuvListener;
+            ImageReader yuvReader;
+
+            try {
+                openCamera(cameraId);
+                Size previewSize = getOrderedPreviewSizes(cameraId).get(0);
+                yuvListener =
+                        new ImageVerifierListener(previewSize, ImageFormat.YUV_420_888);
+                yuvReader = makeImageReader(previewSize,
+                        ImageFormat.YUV_420_888, MAX_READER_IMAGES, yuvListener, mHandler);
+                int maxNumStreamsProc =
+                        getStaticInfo(cameraId).getMaxNumOutputStreamsProcessedChecked();
+                if (maxNumStreamsProc < 3) {
+                    continue;
+                }
+                List<TextureView> views = Arrays.asList(mTextureView[0], mTextureView[1]);
+                textureViewPreview(cameraId, views, yuvReader);
+            } catch (Exception e) {
+                prior = e;
+            } finally {
+                try {
+                    closeCamera(cameraId);
+                } catch (Exception e) {
+                    if (prior != null) {
+                        Log.e(TAG, "Prior exception received: " + prior);
+                    }
+                    prior = e;
+                }
+                if (prior != null) throw prior; // Rethrow last exception.
+            }
+        }
+    }
+
+    public void testDualCameraPreview() throws Exception {
+        final int NUM_CAMERAS_TESTED = 2;
+        if (mCameraIds.length < NUM_CAMERAS_TESTED) {
+            return;
+        }
+
+        try {
+            for (int i = 0; i < NUM_CAMERAS_TESTED; i++) {
+                openCamera(mCameraIds[i]);
+                List<TextureView> views = Arrays.asList(mTextureView[i]);
+
+                startTextureViewPreview(mCameraIds[i], views, /*ImageReader*/null);
+            }
+            // TODO: check the framerate is correct
+            SystemClock.sleep(PREVIEW_TIME_MS);
+            for (int i = 0; i < NUM_CAMERAS_TESTED; i++) {
+                stopPreview(mCameraIds[i]);
+            }
+        } catch (BlockingOpenException e) {
+            // The only error accepted is ERROR_MAX_CAMERAS_IN_USE, which means HAL doesn't support
+            // concurrent camera streaming
+            assertEquals("Camera device open failed",
+                    CameraDevice.StateCallback.ERROR_MAX_CAMERAS_IN_USE, e.getCode());
+            Log.i(TAG, "Camera HAL does not support dual camera preview. Skip the test");
+        } finally {
+            for (int i = 0; i < NUM_CAMERAS_TESTED; i++) {
+                closeCamera(mCameraIds[i]);
+            }
+        }
+    }
+
+    /**
+     * Start camera preview using input texture views and/or one image reader
+     */
+    private void startTextureViewPreview(
+            String cameraId, List<TextureView> views, ImageReader imageReader)
+            throws Exception {
+        int numPreview = views.size();
+        Size previewSize = getOrderedPreviewSizes(cameraId).get(0);
+        CameraPreviewListener[] previewListener =
+                new CameraPreviewListener[numPreview];
+        SurfaceTexture[] previewTexture = new SurfaceTexture[numPreview];
+        List<Surface> surfaces = new ArrayList<Surface>();
+
+        // Prepare preview surface.
+        int i = 0;
+        for (TextureView view : views) {
+            previewListener[i] = new CameraPreviewListener();
+            view.setSurfaceTextureListener(previewListener[i]);
+            previewTexture[i] = getAvailableSurfaceTexture(WAIT_FOR_COMMAND_TO_COMPLETE, view);
+            assertNotNull("Unable to get preview surface texture", previewTexture[i]);
+            previewTexture[i].setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
+            // Correct the preview display rotation.
+            updatePreviewDisplayRotation(previewSize, view);
+            surfaces.add(new Surface(previewTexture[i]));
+            i++;
+        }
+        if (imageReader != null) {
+            surfaces.add(imageReader.getSurface());
+        }
+
+        startPreview(cameraId, surfaces, null);
+
+        i = 0;
+        for (TextureView view : views) {
+            boolean previewDone =
+                    previewListener[i].waitForPreviewDone(WAIT_FOR_COMMAND_TO_COMPLETE);
+            assertTrue("Unable to start preview " + i, previewDone);
+            view.setSurfaceTextureListener(null);
+            i++;
+        }
+    }
+
+    /**
+     * Test camera preview using input texture views and/or one image reader
+     */
+    private void textureViewPreview(
+            String cameraId, List<TextureView> views, ImageReader testImagerReader)
+            throws Exception {
+        startTextureViewPreview(cameraId, views, testImagerReader);
+
+        // TODO: check the framerate is correct
+        SystemClock.sleep(PREVIEW_TIME_MS);
+
+        stopPreview(cameraId);
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/PerformanceTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/PerformanceTest.java
new file mode 100644
index 0000000..8b8f2f6
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/PerformanceTest.java
@@ -0,0 +1,504 @@
+/*
+ * 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 com.android.ex.camera2.blocking.BlockingSessionCallback.*;
+
+import android.graphics.ImageFormat;
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CameraCaptureSession.CaptureCallback;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.TotalCaptureResult;
+import android.hardware.camera2.cts.CameraTestUtils.SimpleImageReaderListener;
+import android.hardware.camera2.cts.helpers.StaticMetadata;
+import android.hardware.camera2.cts.helpers.StaticMetadata.CheckLevel;
+import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
+import android.util.Log;
+import android.util.Pair;
+import android.util.Size;
+import android.view.Surface;
+import android.cts.util.DeviceReportLog;
+import android.media.Image;
+import android.media.ImageReader;
+import android.os.ConditionVariable;
+import android.os.SystemClock;
+
+import com.android.cts.util.ReportLog;
+import com.android.cts.util.ResultType;
+import com.android.cts.util.ResultUnit;
+import com.android.cts.util.Stat;
+import com.android.ex.camera2.blocking.BlockingSessionCallback;
+import com.android.ex.camera2.exceptions.TimeoutRuntimeException;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Test camera2 API use case performance KPIs, such as camera open time, session creation time,
+ * shutter lag etc. The KPI data will be reported in cts results.
+ */
+public class PerformanceTest extends Camera2SurfaceViewTestCase {
+    private static final String TAG = "PerformanceTest";
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+    private static final int NUM_TEST_LOOPS = 5;
+    private static final int NUM_MAX_IMAGES = 4;
+    private static final int NUM_RESULTS_WAIT = 30;
+
+    private DeviceReportLog mReportLog;
+
+    @Override
+    protected void setUp() throws Exception {
+        mReportLog = new DeviceReportLog();
+        super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        // Deliver the report to host will automatically clear the report log.
+        mReportLog.deliverReportToHost(getInstrumentation());
+        super.tearDown();
+    }
+
+    /**
+     * Test camera launch KPI: the time duration between a camera device is
+     * being opened and first preview frame is available.
+     * <p>
+     * It includes camera open time, session creation time, and sending first
+     * preview request processing latency etc. For the SurfaceView based preview use
+     * case, there is no way for client to know the exact preview frame
+     * arrival time. To approximate this time, a companion YUV420_888 stream is
+     * created. The first YUV420_888 Image coming out of the ImageReader is treated
+     * as the first preview arrival time.
+     * </p>
+     */
+    public void testCameraLaunch() throws Exception {
+        double[] cameraOpenTimes = new double[NUM_TEST_LOOPS];
+        double[] configureStreamTimes = new double[NUM_TEST_LOOPS];
+        double[] startPreviewTimes = new double[NUM_TEST_LOOPS];
+        double[] stopPreviewTimes = new double[NUM_TEST_LOOPS];
+        double[] cameraCloseTimes = new double[NUM_TEST_LOOPS];
+        double[] cameraLaunchTimes = new double[NUM_TEST_LOOPS];
+
+        for (String id : mCameraIds) {
+            try {
+                initializeImageReader(id, ImageFormat.YUV_420_888);
+                SimpleImageListener imageListener = null;
+                long startTimeMs, openTimeMs, configureTimeMs, previewStartedTimeMs;
+                for (int i = 0; i < NUM_TEST_LOOPS; i++) {
+                    try {
+                        // Need create a new listener every iteration to be able to wait
+                        // for the first image comes out.
+                        imageListener = new SimpleImageListener();
+                        mReader.setOnImageAvailableListener(imageListener, mHandler);
+                        startTimeMs = SystemClock.elapsedRealtime();
+
+                        // Blocking open camera
+                        simpleOpenCamera(id);
+                        openTimeMs = SystemClock.elapsedRealtime();
+                        cameraOpenTimes[i] = openTimeMs - startTimeMs;
+
+                        // Blocking configure outputs.
+                        configureReaderAndPreviewOutputs();
+                        configureTimeMs = SystemClock.elapsedRealtime();
+                        configureStreamTimes[i] = configureTimeMs - openTimeMs;
+
+                        // Blocking start preview (start preview to first image arrives)
+                        CameraTestUtils.SimpleCaptureCallback resultListener =
+                                new CameraTestUtils.SimpleCaptureCallback();
+                        blockingStartPreview(resultListener, imageListener);
+                        previewStartedTimeMs = SystemClock.elapsedRealtime();
+                        startPreviewTimes[i] = previewStartedTimeMs - configureTimeMs;
+                        cameraLaunchTimes[i] = previewStartedTimeMs - startTimeMs;
+
+                        // Let preview on for a couple of frames
+                        waitForNumResults(resultListener, NUM_RESULTS_WAIT);
+
+                        // Blocking stop preview
+                        startTimeMs = SystemClock.elapsedRealtime();
+                        blockingStopPreview();
+                        stopPreviewTimes[i] = SystemClock.elapsedRealtime() - startTimeMs;
+                    }
+                    finally {
+                        // Blocking camera close
+                        startTimeMs = SystemClock.elapsedRealtime();
+                        closeDevice();
+                        cameraCloseTimes[i] = SystemClock.elapsedRealtime() - startTimeMs;
+                    }
+                }
+
+                // Finish the data collection, report the KPIs.
+                mReportLog.printArray("Camera " + id
+                        + ": Camera open time", cameraOpenTimes,
+                        ResultType.LOWER_BETTER, ResultUnit.MS);
+                mReportLog.printArray("Camera " + id
+                        + ": Camera configure stream time", configureStreamTimes,
+                        ResultType.LOWER_BETTER, ResultUnit.MS);
+                mReportLog.printArray("Camera " + id
+                        + ": Camera start preview time", startPreviewTimes,
+                        ResultType.LOWER_BETTER, ResultUnit.MS);
+                mReportLog.printArray("Camera " + id
+                        + ": Camera stop preview", stopPreviewTimes,
+                        ResultType.LOWER_BETTER, ResultUnit.MS);
+                mReportLog.printArray("Camera " + id
+                        + ": Camera close time", cameraCloseTimes,
+                        ResultType.LOWER_BETTER, ResultUnit.MS);
+                mReportLog.printArray("Camera " + id
+                        + ": Camera launch time", cameraLaunchTimes,
+                        ResultType.LOWER_BETTER, ResultUnit.MS);
+                mReportLog.printSummary("Camera launch average time for Camera " + id,
+                        Stat.getAverage(cameraLaunchTimes),
+                        ResultType.LOWER_BETTER, ResultUnit.MS);
+            }
+            finally {
+                closeImageReader();
+            }
+        }
+    }
+
+    /**
+     * Test camera capture KPI for YUV_420_888 format: the time duration between
+     * sending out a single image capture request and receiving image data and
+     * capture result.
+     * <p>
+     * It enumerates the following metrics: capture latency, computed by
+     * measuring the time between sending out the capture request and getting
+     * the image data; partial result latency, computed by measuring the time
+     * between sending out the capture request and getting the partial result;
+     * capture result latency, computed by measuring the time between sending
+     * out the capture request and getting the full capture result.
+     * </p>
+     */
+    public void testSingleCapture() throws Exception {
+        double[] captureTimes = new double[NUM_TEST_LOOPS];
+        double[] getPartialTimes = new double[NUM_TEST_LOOPS];
+        double[] getResultTimes = new double[NUM_TEST_LOOPS];
+
+        for (String id : mCameraIds) {
+            try {
+                openDevice(id);
+
+                if (mStaticInfo.isHardwareLevelLegacy()) {
+                    Log.i(TAG, "Skipping test on legacy devices");
+                    continue;
+                }
+
+                boolean partialsExpected = mStaticInfo.getPartialResultCount() > 1;
+                long startTimeMs;
+                boolean isPartialTimingValid = partialsExpected;
+                for (int i = 0; i < NUM_TEST_LOOPS; i++) {
+
+                    // setup builders and listeners
+                    CaptureRequest.Builder previewBuilder =
+                            mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+                    CaptureRequest.Builder captureBuilder =
+                            mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
+                    CameraTestUtils.SimpleCaptureCallback previewResultListener =
+                            new CameraTestUtils.SimpleCaptureCallback();
+                    SimpleTimingResultListener captureResultListener =
+                            new SimpleTimingResultListener();
+                    SimpleImageListener imageListener = new SimpleImageListener();
+
+                    Size maxYuvSize = CameraTestUtils.getSupportedPreviewSizes(id, mCameraManager,
+                            /*bound*/null).get(0);
+
+                    prepareCaptureAndStartPreview(previewBuilder, captureBuilder,
+                            mOrderedPreviewSizes.get(0), maxYuvSize,
+                            ImageFormat.YUV_420_888, previewResultListener,
+                            NUM_MAX_IMAGES, imageListener);
+
+                    // Capture an image and get image data
+                    startTimeMs = SystemClock.elapsedRealtime();
+                    CaptureRequest request = captureBuilder.build();
+                    mSession.capture(request, captureResultListener, mHandler);
+
+                    Pair<CaptureResult, Long> partialResultNTime = null;
+                    if (partialsExpected) {
+                        partialResultNTime = captureResultListener.getPartialResultNTimeForRequest(
+                            request, NUM_RESULTS_WAIT);
+                        // Even if maxPartials > 1, may not see partials for some devices
+                        if (partialResultNTime == null) {
+                            partialsExpected = false;
+                            isPartialTimingValid = false;
+                        }
+                    }
+                    Pair<CaptureResult, Long> captureResultNTime =
+                            captureResultListener.getCaptureResultNTimeForRequest(
+                                    request, NUM_RESULTS_WAIT);
+                    imageListener.waitForImageAvailable(
+                            CameraTestUtils.CAPTURE_IMAGE_TIMEOUT_MS);
+
+                    captureTimes[i] = imageListener.getTimeReceivedImage() - startTimeMs;
+                    if (partialsExpected) {
+                        getPartialTimes[i] = partialResultNTime.second - startTimeMs;
+                        if (getPartialTimes[i] < 0) {
+                            isPartialTimingValid = false;
+                        }
+                    }
+                    getResultTimes[i] = captureResultNTime.second - startTimeMs;
+
+                    // simulate real scenario (preview runs a bit)
+                    waitForNumResults(previewResultListener, NUM_RESULTS_WAIT);
+
+                    stopPreview();
+
+                }
+                mReportLog.printArray("Camera " + id
+                        + ": Camera capture latency", captureTimes,
+                        ResultType.LOWER_BETTER, ResultUnit.MS);
+                // If any of the partial results do not contain AE and AF state, then no report
+                if (isPartialTimingValid) {
+                    mReportLog.printArray("Camera " + id
+                            + ": Camera partial result latency", getPartialTimes,
+                            ResultType.LOWER_BETTER, ResultUnit.MS);
+                }
+                mReportLog.printArray("Camera " + id
+                        + ": Camera capture result latency", getResultTimes,
+                        ResultType.LOWER_BETTER, ResultUnit.MS);
+            }
+            finally {
+                closeImageReader();
+                closeDevice();
+            }
+        }
+    }
+
+    private void blockingStopPreview() throws Exception {
+        stopPreview();
+        mSessionListener.getStateWaiter().waitForState(SESSION_CLOSED,
+                CameraTestUtils.SESSION_CLOSE_TIMEOUT_MS);
+    }
+
+    private void blockingStartPreview(CaptureCallback listener, SimpleImageListener imageListener)
+            throws Exception {
+        if (mPreviewSurface == null || mReaderSurface == null) {
+            throw new IllegalStateException("preview and reader surface must be initilized first");
+        }
+
+        CaptureRequest.Builder previewBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        previewBuilder.addTarget(mPreviewSurface);
+        previewBuilder.addTarget(mReaderSurface);
+        mSession.setRepeatingRequest(previewBuilder.build(), listener, mHandler);
+        imageListener.waitForImageAvailable(CameraTestUtils.CAPTURE_IMAGE_TIMEOUT_MS);
+    }
+
+    private void blockingCaptureImage(CaptureCallback listener,
+            SimpleImageListener imageListener) throws Exception {
+        if (mReaderSurface == null) {
+            throw new IllegalStateException("reader surface must be initialized first");
+        }
+
+        CaptureRequest.Builder captureBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
+        captureBuilder.addTarget(mReaderSurface);
+        mSession.capture(captureBuilder.build(), listener, mHandler);
+        imageListener.waitForImageAvailable(CameraTestUtils.CAPTURE_IMAGE_TIMEOUT_MS);
+    }
+
+    /**
+     * Configure reader and preview outputs and wait until done.
+     */
+    private void configureReaderAndPreviewOutputs() throws Exception {
+        if (mPreviewSurface == null || mReaderSurface == null) {
+            throw new IllegalStateException("preview and reader surface must be initilized first");
+        }
+        mSessionListener = new BlockingSessionCallback();
+        List<Surface> outputSurfaces = new ArrayList<>();
+        outputSurfaces.add(mPreviewSurface);
+        outputSurfaces.add(mReaderSurface);
+        mSession = CameraTestUtils.configureCameraSession(mCamera, outputSurfaces,
+                mSessionListener, mHandler);
+    }
+
+    /**
+     * Initialize the ImageReader instance and preview surface.
+     * @param cameraId The camera to be opened.
+     * @param format The format used to create ImageReader instance.
+     */
+    private void initializeImageReader(String cameraId, int format) throws Exception {
+        mOrderedPreviewSizes = CameraTestUtils.getSupportedPreviewSizes(
+                cameraId, mCameraManager, CameraTestUtils.PREVIEW_SIZE_BOUND);
+        Size maxPreviewSize = mOrderedPreviewSizes.get(0);
+        createImageReader(maxPreviewSize, format, NUM_MAX_IMAGES, /*listener*/null);
+        updatePreviewSurface(maxPreviewSize);
+    }
+
+    private void simpleOpenCamera(String cameraId) throws Exception {
+        mCamera = CameraTestUtils.openCamera(
+                mCameraManager, cameraId, mCameraListener, mHandler);
+        mCollector.setCameraId(cameraId);
+        mStaticInfo = new StaticMetadata(mCameraManager.getCameraCharacteristics(cameraId),
+                CheckLevel.ASSERT, /*collector*/null);
+        mMinPreviewFrameDurationMap =
+                mStaticInfo.getAvailableMinFrameDurationsForFormatChecked(ImageFormat.YUV_420_888);
+    }
+
+    /**
+     * Simple image listener that can be used to time the availability of first image.
+     *
+     */
+    private static class SimpleImageListener implements ImageReader.OnImageAvailableListener {
+        private ConditionVariable imageAvailable = new ConditionVariable();
+        private boolean imageReceived = false;
+        private long mTimeReceivedImage = 0;
+
+        @Override
+        public void onImageAvailable(ImageReader reader) {
+            Image image = null;
+            if (!imageReceived) {
+                if (VERBOSE) {
+                    Log.v(TAG, "First image arrives");
+                }
+                imageReceived = true;
+                mTimeReceivedImage = SystemClock.elapsedRealtime();
+                imageAvailable.open();
+            }
+            image = reader.acquireNextImage();
+            if (image != null) {
+                image.close();
+            }
+        }
+
+        /**
+         * Wait for image available, return immediately if the image was already
+         * received, otherwise wait until an image arrives.
+         */
+        public void waitForImageAvailable(long timeout) {
+            if (imageReceived) {
+                imageReceived = false;
+                return;
+            }
+
+            if (imageAvailable.block(timeout)) {
+                imageAvailable.close();
+                imageReceived = false;
+            } else {
+                throw new TimeoutRuntimeException("Unable to get the first image after "
+                        + CameraTestUtils.CAPTURE_IMAGE_TIMEOUT_MS + "ms");
+            }
+        }
+
+        public long getTimeReceivedImage() {
+            return mTimeReceivedImage;
+        }
+    }
+
+    private static class SimpleTimingResultListener
+            extends CameraCaptureSession.CaptureCallback {
+        private final LinkedBlockingQueue<Pair<CaptureResult, Long> > mPartialResultQueue =
+                new LinkedBlockingQueue<Pair<CaptureResult, Long> >();
+        private final LinkedBlockingQueue<Pair<CaptureResult, Long> > mResultQueue =
+                new LinkedBlockingQueue<Pair<CaptureResult, Long> > ();
+
+        @Override
+        public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
+                TotalCaptureResult result) {
+            try {
+                Long time = SystemClock.elapsedRealtime();
+                mResultQueue.put(new Pair<CaptureResult, Long>(result, time));
+            } catch (InterruptedException e) {
+                throw new UnsupportedOperationException(
+                        "Can't handle InterruptedException in onCaptureCompleted");
+            }
+        }
+
+        @Override
+        public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request,
+                CaptureResult partialResult) {
+            try {
+                // check if AE and AF state exists
+                Long time = -1L;
+                if (partialResult.get(CaptureResult.CONTROL_AE_STATE) != null &&
+                        partialResult.get(CaptureResult.CONTROL_AF_STATE) != null) {
+                    time = SystemClock.elapsedRealtime();
+                }
+                mPartialResultQueue.put(new Pair<CaptureResult, Long>(partialResult, time));
+            } catch (InterruptedException e) {
+                throw new UnsupportedOperationException(
+                        "Can't handle InterruptedException in onCaptureProgressed");
+            }
+        }
+
+        public Pair<CaptureResult, Long> getPartialResultNTime(long timeout) {
+            try {
+                Pair<CaptureResult, Long> result =
+                        mPartialResultQueue.poll(timeout, TimeUnit.MILLISECONDS);
+                return result;
+            } catch (InterruptedException e) {
+                throw new UnsupportedOperationException("Unhandled interrupted exception", e);
+            }
+        }
+
+        public Pair<CaptureResult, Long> getCaptureResultNTime(long timeout) {
+            try {
+                Pair<CaptureResult, Long> result =
+                        mResultQueue.poll(timeout, TimeUnit.MILLISECONDS);
+                assertNotNull("Wait for a capture result timed out in " + timeout + "ms", result);
+                return result;
+            } catch (InterruptedException e) {
+                throw new UnsupportedOperationException("Unhandled interrupted exception", e);
+            }
+        }
+
+        public Pair<CaptureResult, Long> getPartialResultNTimeForRequest(CaptureRequest myRequest,
+                int numResultsWait) {
+            if (numResultsWait < 0) {
+                throw new IllegalArgumentException("numResultsWait must be no less than 0");
+            }
+
+            Pair<CaptureResult, Long> result;
+            int i = 0;
+            do {
+                result = getPartialResultNTime(CameraTestUtils.CAPTURE_RESULT_TIMEOUT_MS);
+                // The result may be null if no partials are produced on this particular path, so
+                // stop trying
+                if (result == null) break;
+                if (result.first.getRequest().equals(myRequest)) {
+                    return result;
+                }
+            } while (i++ < numResultsWait);
+
+            // No partials produced - this may not be an error, since a given device may not
+            // produce any partials on this testing path
+            return null;
+        }
+
+        public Pair<CaptureResult, Long> getCaptureResultNTimeForRequest(CaptureRequest myRequest,
+                int numResultsWait) {
+            if (numResultsWait < 0) {
+                throw new IllegalArgumentException("numResultsWait must be no less than 0");
+            }
+
+            Pair<CaptureResult, Long> result;
+            int i = 0;
+            do {
+                result = getCaptureResultNTime(CameraTestUtils.CAPTURE_RESULT_TIMEOUT_MS);
+                if (result.first.getRequest().equals(myRequest)) {
+                    return result;
+                }
+            } while (i++ < numResultsWait);
+
+            throw new TimeoutRuntimeException("Unable to get the expected capture result after "
+                    + "waiting for " + numResultsWait + " results");
+        }
+
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java
new file mode 100644
index 0000000..90cb18a
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java
@@ -0,0 +1,1163 @@
+/*
+ * 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.cts.CameraTestUtils.*;
+import static com.android.ex.camera2.blocking.BlockingSessionCallback.*;
+
+import android.graphics.ImageFormat;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.params.StreamConfigurationMap;
+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.SystemClock;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+import android.util.Range;
+import android.view.Surface;
+
+import com.android.ex.camera2.blocking.BlockingSessionCallback;
+
+import junit.framework.AssertionFailedError;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * CameraDevice video recording use case tests by using MediaRecorder and
+ * MediaCodec.
+ */
+@LargeTest
+public class RecordingTest extends Camera2SurfaceViewTestCase {
+    private static final String TAG = "RecordingTest";
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+    private static final boolean DEBUG_DUMP = Log.isLoggable(TAG, Log.DEBUG);
+    private static final int RECORDING_DURATION_MS = 3000;
+    private static final int DURATION_MARGIN_MS = 600;
+    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,
+            CamcorderProfile.QUALITY_CIF,
+            CamcorderProfile.QUALITY_LOW,
+            CamcorderProfile.QUALITY_HIGH,
+            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 static final int SLOWMO_SLOW_FACTOR = 4;
+    private List<Size> mSupportedVideoSizes;
+    private Surface mRecordingSurface;
+    private MediaRecorder mMediaRecorder;
+    private String mOutMediaFileName;
+    private int mVideoFrameRate;
+    private Size mVideoSize;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    /**
+     * <p>
+     * Test basic camera recording.
+     * </p>
+     * <p>
+     * This test covers the typical basic use case of camera recording.
+     * MediaRecorder is used to record the audio and video, CamcorderProfile is
+     * used to configure the MediaRecorder. It goes through the pre-defined
+     * CamcorderProfile list, test each profile configuration and validate the
+     * recorded video. Preview is set to the video size.
+     * </p>
+     */
+    public void testBasicRecording() throws Exception {
+        for (int i = 0; i < mCameraIds.length; i++) {
+            try {
+                Log.i(TAG, "Testing basic recording for camera " + mCameraIds[i]);
+                // Re-use the MediaRecorder object for the same camera device.
+                mMediaRecorder = new MediaRecorder();
+                openDevice(mCameraIds[i]);
+
+                initSupportedVideoSize(mCameraIds[i]);
+
+                basicRecordingTestByCamera();
+            } finally {
+                closeDevice();
+                releaseRecorder();
+            }
+        }
+    }
+
+    /**
+     * <p>
+     * Test camera recording for all supported sizes by using MediaRecorder.
+     * </p>
+     * <p>
+     * This test covers camera recording for all supported sizes by camera. MediaRecorder
+     * is used to encode the video. Preview is set to the video size. Recorded videos are
+     * validated according to the recording configuration.
+     * </p>
+     */
+    public void testSupportedVideoSizes() throws Exception {
+        for (int i = 0; i < mCameraIds.length; i++) {
+            try {
+                Log.i(TAG, "Testing supported video size recording for camera " + mCameraIds[i]);
+                // Re-use the MediaRecorder object for the same camera device.
+                mMediaRecorder = new MediaRecorder();
+                openDevice(mCameraIds[i]);
+
+                initSupportedVideoSize(mCameraIds[i]);
+
+                recordingSizeTestByCamera();
+            } finally {
+                closeDevice();
+                releaseRecorder();
+            }
+        }
+    }
+
+    /**
+     * Test different start/stop orders of Camera and Recorder.
+     *
+     * <p>The recording should be working fine for any kind of start/stop orders.</p>
+     */
+    public void testCameraRecorderOrdering() {
+        // TODO: need implement
+    }
+
+    /**
+     * <p>
+     * Test camera recording for all supported sizes by using MediaCodec.
+     * </p>
+     * <p>
+     * This test covers video only recording for all supported sizes (camera and
+     * encoder). MediaCodec is used to encode the video. The recorded videos are
+     * validated according to the recording configuration.
+     * </p>
+     */
+    public void testMediaCodecRecording() throws Exception {
+        // TODO. Need implement.
+    }
+
+    /**
+     * <p>
+     * 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 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 {
+        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);
+    }
+
+    /**
+     * Test timelapse recording, where capture rate is slower than video (playback) frame rate.
+     */
+    public void testTimelapseRecording() throws Exception {
+        // TODO. Need implement.
+    }
+
+    public void testSlowMotionRecording() throws Exception {
+        slowMotionRecording();
+    }
+
+    /**
+     * Test slow motion recording where capture rate (camera output) is different with
+     * video (playback) frame rate for each camera if high speed recording is supported
+     * by both camera and encoder.
+     *
+     * <p>
+     * Normal recording use cases make the capture rate (camera output frame
+     * rate) the same as the video (playback) frame rate. This guarantees that
+     * the motions in the scene play at the normal speed. If the capture rate is
+     * faster than video frame rate, for a given time duration, more number of
+     * frames are captured than it can be played in the same time duration. This
+     * generates "slow motion" effect during playback.
+     * </p>
+     */
+    private void slowMotionRecording() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                Log.i(TAG, "Testing slow motion recording for camera " + id);
+                // Re-use the MediaRecorder object for the same camera device.
+                mMediaRecorder = new MediaRecorder();
+                openDevice(id);
+
+                if (!mStaticInfo.isHighSpeedVideoSupported()) {
+                    continue;
+                }
+
+                StreamConfigurationMap config =
+                        mStaticInfo.getValueFromKeyNonNull(
+                                CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+                Size[] highSpeedVideoSizes = config.getHighSpeedVideoSizes();
+                for (Size size : highSpeedVideoSizes) {
+                    Range<Integer> fpsRange = getHighestHighSpeedFixedFpsRangeForSize(config, size);
+                    mCollector.expectNotNull("Unable to find the fixed frame rate fps range for " +
+                            "size " + size, fpsRange);
+                    if (fpsRange == null) {
+                        continue;
+                    }
+
+                    int captureRate = fpsRange.getLower();
+                    int videoFramerate = captureRate / SLOWMO_SLOW_FACTOR;
+                    /**
+                     * Check if encoder support this. TODO: use HIGH_SPEED_720p
+                     * CamCorderProfile to get the performance guarantee. Also
+                     * add the test in StaticMetadataTest to check: 1. Camera
+                     * high speed recording metadata is correctly reported 2.
+                     * Encoder profile/level info is correctly reported. After
+                     * that, we only need check the CamcorderProfile before
+                     * skipping the test.
+                     */
+                    if (!isSupportedByAVCEncoder(size, captureRate)) {
+                        Log.i(TAG, "high speed recording " + size + "@" + captureRate + "fps"
+                                + " is not supported by AVC encoder");
+                        continue;
+                    }
+
+                    mOutMediaFileName = VIDEO_FILE_PATH + "/test_slowMo_video.mp4";
+                    if (DEBUG_DUMP) {
+                        mOutMediaFileName = VIDEO_FILE_PATH + "/test_slowMo_video_" + id + "_"
+                                + size.toString() + ".mp4";
+                    }
+
+                    prepareRecording(size, videoFramerate, captureRate);
+
+                    // prepare preview surface by using video size.
+                    updatePreviewSurfaceWithVideoSize(size);
+
+                    // Start recording
+                    startSlowMotionRecording(/*useMediaRecorder*/true, videoFramerate, captureRate,
+                            fpsRange);
+                    long startTime = SystemClock.elapsedRealtime();
+
+                    // Record certain duration.
+                    SystemClock.sleep(RECORDING_DURATION_MS);
+
+                    // Stop recording and preview
+                    stopRecording(/*useMediaRecorder*/true);
+                    int duration = (int) (SystemClock.elapsedRealtime() - startTime);
+
+                    // Validation.
+                    validateRecording(size, duration * SLOWMO_SLOW_FACTOR);
+
+                }
+
+            } finally {
+                closeDevice();
+                releaseRecorder();
+            }
+        }
+    }
+
+    private Range<Integer> getHighestHighSpeedFixedFpsRangeForSize(StreamConfigurationMap config,
+            Size size) {
+        Range<Integer>[] availableFpsRanges = config.getHighSpeedVideoFpsRangesFor(size);
+        Range<Integer> maxRange = availableFpsRanges[0];
+        boolean foundRange = false;
+        for (Range<Integer> range : availableFpsRanges) {
+            if (range.getLower() == range.getUpper() && range.getLower() >= maxRange.getLower()) {
+                foundRange = true;
+                maxRange = range;
+            }
+        }
+
+        if (!foundRange) {
+            return null;
+        }
+        return maxRange;
+    }
+
+    private void startSlowMotionRecording(boolean useMediaRecorder, int videoFrameRate,
+            int captureRate, Range<Integer> fpsRange) 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);
+        }
+        mSessionListener = new BlockingSessionCallback();
+        mSession = configureCameraSession(mCamera, outputSurfaces, mSessionListener, mHandler);
+
+        CaptureRequest.Builder recordingRequestBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
+        recordingRequestBuilder.set(CaptureRequest.CONTROL_MODE,
+                CaptureRequest.CONTROL_MODE_USE_SCENE_MODE);
+        recordingRequestBuilder.set(CaptureRequest.CONTROL_SCENE_MODE,
+                CaptureRequest.CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO);
+
+        CaptureRequest.Builder recordingOnlyBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
+        recordingOnlyBuilder.set(CaptureRequest.CONTROL_MODE,
+                CaptureRequest.CONTROL_MODE_USE_SCENE_MODE);
+        recordingOnlyBuilder.set(CaptureRequest.CONTROL_SCENE_MODE,
+                CaptureRequest.CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO);
+        int slowMotionFactor = captureRate / videoFrameRate;
+
+        // Make sure camera output frame rate is set to correct value.
+        recordingRequestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, fpsRange);
+        recordingRequestBuilder.addTarget(mRecordingSurface);
+        recordingRequestBuilder.addTarget(mPreviewSurface);
+        recordingOnlyBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, fpsRange);
+        recordingOnlyBuilder.addTarget(mRecordingSurface);
+
+        List<CaptureRequest> slowMoRequests = new ArrayList<CaptureRequest>();
+        slowMoRequests.add(recordingRequestBuilder.build());// Preview + recording.
+
+        for (int i = 0; i < slowMotionFactor - 1; i++) {
+            slowMoRequests.add(recordingOnlyBuilder.build()); // Recording only.
+        }
+        mSession.setRepeatingBurst(slowMoRequests, null, null);
+
+        if (useMediaRecorder) {
+            mMediaRecorder.start();
+        } else {
+            // TODO: need implement MediaCodec path.
+        }
+
+    }
+
+    /**
+     * Test camera recording by using each available CamcorderProfile for a
+     * given camera. preview size is set to the video size.
+     */
+    private void basicRecordingTestByCamera() throws Exception {
+        for (int profileId : mCamcorderProfileList) {
+            int cameraId = Integer.valueOf(mCamera.getId());
+            if (!CamcorderProfile.hasProfile(cameraId, profileId) ||
+                    allowedUnsupported(cameraId, profileId)) {
+                continue;
+            }
+
+            CamcorderProfile profile = CamcorderProfile.get(cameraId, profileId);
+            Size videoSz = new Size(profile.videoFrameWidth, profile.videoFrameHeight);
+            assertTrue("Video size " + videoSz.toString() + " for profile ID " + profileId +
+                            " 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 preview surface by using video size.
+            updatePreviewSurfaceWithVideoSize(videoSz);
+
+            // Start recording
+            startRecording(/* useMediaRecorder */true);
+            long startTime = SystemClock.elapsedRealtime();
+
+            // Record certain duration.
+            SystemClock.sleep(RECORDING_DURATION_MS);
+
+            // Stop recording and preview
+            stopRecording(/* useMediaRecorder */true);
+            int duration = (int) (SystemClock.elapsedRealtime() - startTime);
+
+            // Validation.
+            validateRecording(videoSz, duration);
+        }
+    }
+
+    /**
+     * Test camera recording for each supported video size by camera, preview
+     * size is set to the video size.
+     */
+    private void recordingSizeTestByCamera() throws Exception {
+        for (Size sz : mSupportedVideoSizes) {
+            if (!isSupported(sz, VIDEO_FRAME_RATE, VIDEO_FRAME_RATE)) {
+                continue;
+            }
+
+            if (VERBOSE) {
+                Log.v(TAG, "Testing camera recording with video size " + sz.toString());
+            }
+
+            // Configure preview and recording surfaces.
+            mOutMediaFileName = VIDEO_FILE_PATH + "/test_video.mp4";
+            if (DEBUG_DUMP) {
+                mOutMediaFileName = VIDEO_FILE_PATH + "/test_video_" + mCamera.getId() + "_"
+                        + sz.toString() + ".mp4";
+            }
+
+            // Use AVC and AAC a/v compression format.
+            prepareRecording(sz, VIDEO_FRAME_RATE, VIDEO_FRAME_RATE);
+
+            // prepare preview surface by using video size.
+            updatePreviewSurfaceWithVideoSize(sz);
+
+            // Start recording
+            startRecording(/* useMediaRecorder */true);
+            long startTime = SystemClock.elapsedRealtime();
+
+            // Record certain duration.
+            SystemClock.sleep(RECORDING_DURATION_MS);
+
+            // Stop recording and preview
+            stopRecording(/* useMediaRecorder */true);
+            int duration = (int) (SystemClock.elapsedRealtime() - startTime);
+
+            // Validation.
+            validateRecording(sz, duration);
+        }
+    }
+
+    /**
+     * Initialize the supported video sizes.
+     */
+    private void initSupportedVideoSize(String cameraId)  throws Exception {
+        Size maxVideoSize = SIZE_BOUND_1080P;
+        if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_2160P)) {
+            maxVideoSize = SIZE_BOUND_2160P;
+        }
+        mSupportedVideoSizes =
+                getSupportedVideoSizes(cameraId, mCameraManager, maxVideoSize);
+    }
+
+    /**
+     * 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);
+
+                    if (mStaticInfo.isHardwareLevelLegacy()) {
+                        Log.i(TAG, "Skipping test on legacy devices");
+                        continue;
+                    }
+
+                    initSupportedVideoSize(id);
+
+                    videoSnapshotTestByCamera(burstTest);
+                } finally {
+                    closeDevice();
+                    releaseRecorder();
+                }
+            }
+    }
+
+    /**
+     * Returns {@code true} if the {@link CamcorderProfile} ID is allowed to be unsupported.
+     *
+     * <p>This only allows unsupported profiles when using the LEGACY mode of the Camera API.</p>
+     *
+     * @param profileId a {@link CamcorderProfile} ID to check.
+     * @return {@code true} if supported.
+     */
+    private boolean allowedUnsupported(int cameraId, int profileId) {
+        if (!mStaticInfo.isHardwareLevelLegacy()) {
+            return false;
+        }
+
+        switch(profileId) {
+            case CamcorderProfile.QUALITY_2160P:
+            case CamcorderProfile.QUALITY_1080P:
+            case CamcorderProfile.QUALITY_HIGH:
+                return !CamcorderProfile.hasProfile(cameraId, profileId) ||
+                        CamcorderProfile.get(cameraId, profileId).videoFrameWidth >= 1080;
+        }
+        return false;
+    }
+
+    /**
+     * 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 burstTest Perform burst capture or single capture. For burst capture
+     *                  {@value #BURST_VIDEO_SNAPSHOT_NUM} capture requests will be sent.
+     */
+    private void videoSnapshotTestByCamera(boolean burstTest)
+            throws Exception {
+        final int NUM_SINGLE_SHOT_TEST = 5;
+        final int FRAMEDROP_TOLERANCE = 8;
+        for (int profileId : mCamcorderProfileList) {
+            int cameraId = Integer.valueOf(mCamera.getId());
+            if (!CamcorderProfile.hasProfile(cameraId, profileId) ||
+                    allowedUnsupported(cameraId, profileId)) {
+                continue;
+            }
+
+            CamcorderProfile profile = CamcorderProfile.get(cameraId, profileId);
+            Size videoSz = new Size(profile.videoFrameWidth, profile.videoFrameHeight);
+            if (!mSupportedVideoSizes.contains(videoSz)) {
+                mCollector.addMessage("Video size " + videoSz.toString() + " for profile ID " +
+                        profileId + " must be one of the camera device supported video size!");
+                continue;
+            }
+
+            Size maxPreviewSize = mOrderedPreviewSizes.get(0);
+
+            // For LEGACY, find closest supported smaller or equal JPEG size to the current video
+            // size; if no size is smaller than the video, pick the smallest JPEG size.  The assert
+            // for video size above guarantees that for LIMITED or FULL, we select videoSz here.
+            Size videoSnapshotSz = mOrderedStillSizes.get(mOrderedStillSizes.size() - 1);
+            for (int i = mOrderedStillSizes.size() - 2; i >= 0; i--) {
+                Size candidateSize = mOrderedStillSizes.get(i);
+                if (candidateSize.getWidth() <= videoSz.getWidth() &&
+                        candidateSize.getHeight() <= videoSz.getHeight()) {
+                    videoSnapshotSz = candidateSize;
+                }
+            }
+
+            /**
+             * Only test full res snapshot when below conditions are all true.
+             * 1. Camera is a FULL device
+             * 2. video size is up to max preview size, which will be bounded by 1080p.
+             */
+            if (mStaticInfo.isHardwareLevelFull() &&
+                    videoSz.getWidth() <= maxPreviewSize.getWidth() &&
+                    videoSz.getHeight() <= maxPreviewSize.getHeight()) {
+                videoSnapshotSz = mOrderedStillSizes.get(0);
+            }
+
+            createImageReader(
+                    videoSnapshotSz, ImageFormat.JPEG,
+                    MAX_VIDEO_SNAPSHOT_IMAGES, /*listener*/null);
+
+            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";
+            }
+
+            int numTestIterations = burstTest ? 1 : NUM_SINGLE_SHOT_TEST;
+            int totalDroppedFrames = 0;
+
+            for (int numTested = 0; numTested < numTestIterations; numTested++) {
+                prepareRecordingWithProfile(profile);
+
+                // prepare video snapshot
+                SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
+                SimpleImageReaderListener imageListener = new SimpleImageReaderListener();
+                CaptureRequest.Builder videoSnapshotRequestBuilder =
+                        mCamera.createCaptureRequest((mStaticInfo.isHardwareLevelLegacy()) ?
+                                CameraDevice.TEMPLATE_RECORD :
+                                CameraDevice.TEMPLATE_VIDEO_SNAPSHOT);
+
+                // prepare preview surface by using video size.
+                updatePreviewSurfaceWithVideoSize(videoSz);
+
+                prepareVideoSnapshot(videoSnapshotRequestBuilder, imageListener);
+                CaptureRequest request = videoSnapshotRequestBuilder.build();
+
+                // Start recording
+                startRecording(/* useMediaRecorder */true, resultListener);
+                long startTime = SystemClock.elapsedRealtime();
+
+                // Record certain duration.
+                SystemClock.sleep(RECORDING_DURATION_MS / 2);
+
+                // take video snapshot
+                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);
+                    }
+                    mSession.captureBurst(requests, resultListener, mHandler);
+                } else {
+                    mSession.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);
+                int duration = (int) (SystemClock.elapsedRealtime() - startTime);
+
+                // Validation recorded video
+                validateRecording(videoSz, duration);
+
+                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
+                    totalDroppedFrames +=  validateFrameDropAroundVideoSnapshot(
+                            resultListener, image.getTimestamp());
+
+                    //TODO: validate jittering. Should move to PTS
+                    //validateJittering(resultListener);
+
+                    image.close();
+                }
+            }
+
+            if (!burstTest) {
+                Log.w(TAG, String.format("Camera %d Video size %s: Number of dropped frames " +
+                        "detected in %d trials is %d frames.", cameraId, videoSz.toString(),
+                        numTestIterations, totalDroppedFrames));
+                mCollector.expectLessOrEqual(
+                        String.format(
+                                "Camera %d Video size %s: Number of dropped frames %d must not"
+                                + " be larger than %d",
+                                cameraId, videoSz.toString(), totalDroppedFrames,
+                                FRAMEDROP_TOLERANCE),
+                        FRAMEDROP_TOLERANCE, totalDroppedFrames);
+            }
+            closeImageReader();
+        }
+    }
+
+    /**
+     * 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);
+        assertNotNull("Recording surface must be non-null!", mRecordingSurface);
+        requestBuilder.addTarget(mRecordingSurface);
+        assertNotNull("Preview surface must be non-null!", mPreviewSurface);
+        requestBuilder.addTarget(mPreviewSurface);
+        assertNotNull("Reader surface must be non-null!", mReaderSurface);
+        requestBuilder.addTarget(mReaderSurface);
+    }
+
+    /**
+     * Update preview size with video size.
+     *
+     * <p>Preview size will be capped with max preview size.</p>
+     *
+     * @param videoSize The video size used for preview.
+     */
+    private void updatePreviewSurfaceWithVideoSize(Size videoSize) {
+        if (mOrderedPreviewSizes == null) {
+            throw new IllegalStateException("supported preview size list is not initialized yet");
+        }
+        Size maxPreviewSize = mOrderedPreviewSizes.get(0);
+        Size previewSize = videoSize;
+        if (videoSize.getWidth() > maxPreviewSize.getWidth() ||
+                videoSize.getHeight() > maxPreviewSize.getHeight()) {
+            Log.w(TAG, "Overwrite preview size from " + videoSize.toString() +
+                    " to " + maxPreviewSize.toString());
+            previewSize = maxPreviewSize;
+        }
+
+        updatePreviewSurface(previewSize);
+    }
+
+    /**
+     * Configure MediaRecorder recording session with CamcorderProfile, prepare
+     * the recording surface.
+     */
+    private void prepareRecordingWithProfile(CamcorderProfile profile)
+            throws Exception {
+        // Prepare MediaRecorder.
+        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
+        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
+        mMediaRecorder.setProfile(profile);
+        mMediaRecorder.setOutputFile(mOutMediaFileName);
+        mMediaRecorder.prepare();
+        mRecordingSurface = mMediaRecorder.getSurface();
+        assertNotNull("Recording surface must be non-null!", mRecordingSurface);
+        mVideoFrameRate = profile.videoFrameRate;
+        mVideoSize = new Size(profile.videoFrameWidth, profile.videoFrameHeight);
+    }
+
+    /**
+     * Configure MediaRecorder recording session with CamcorderProfile, prepare
+     * the recording surface. Use AVC for video compression, AAC for audio compression.
+     * Both are required for android devices by android CDD.
+     */
+    private void prepareRecording(Size sz, int videoFrameRate, int captureRate)
+            throws Exception {
+        // Prepare MediaRecorder.
+        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
+        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
+        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
+        mMediaRecorder.setOutputFile(mOutMediaFileName);
+        mMediaRecorder.setVideoEncodingBitRate(getVideoBitRate(sz));
+        mMediaRecorder.setVideoFrameRate(videoFrameRate);
+        mMediaRecorder.setCaptureRate(captureRate);
+        mMediaRecorder.setVideoSize(sz.getWidth(), sz.getHeight());
+        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
+        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
+        mMediaRecorder.prepare();
+        mRecordingSurface = mMediaRecorder.getSurface();
+        assertNotNull("Recording surface must be non-null!", mRecordingSurface);
+        mVideoFrameRate = videoFrameRate;
+        mVideoSize = sz;
+    }
+
+    private void startRecording(boolean useMediaRecorder,
+            CameraCaptureSession.CaptureCallback 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);
+        }
+        mSessionListener = new BlockingSessionCallback();
+        mSession = configureCameraSession(mCamera, outputSurfaces, mSessionListener, mHandler);
+
+        CaptureRequest.Builder recordingRequestBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
+        // Make sure camera output frame rate is set to correct value.
+        Range<Integer> fpsRange = Range.create(mVideoFrameRate, mVideoFrameRate);
+        recordingRequestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, fpsRange);
+        recordingRequestBuilder.addTarget(mRecordingSurface);
+        recordingRequestBuilder.addTarget(mPreviewSurface);
+        mSession.setRepeatingRequest(recordingRequestBuilder.build(), listener, mHandler);
+
+        if (useMediaRecorder) {
+            mMediaRecorder.start();
+        } else {
+            // TODO: need implement MediaCodec path.
+        }
+    }
+
+    private void startRecording(boolean useMediaRecorder)  throws Exception {
+        startRecording(useMediaRecorder, null);
+    }
+
+    private void stopCameraStreaming() throws Exception {
+        if (VERBOSE) {
+            Log.v(TAG, "Stopping camera streaming and waiting for idle");
+        }
+        // Stop repeating, wait for captures to complete, and disconnect from
+        // surfaces
+        mSession.close();
+        mSessionListener.getStateWaiter().waitForState(SESSION_CLOSED, SESSION_CLOSE_TIMEOUT_MS);
+    }
+
+    private void stopRecording(boolean useMediaRecorder) throws Exception {
+        if (useMediaRecorder) {
+            stopCameraStreaming();
+
+            mMediaRecorder.stop();
+            // Can reuse the MediaRecorder object after reset.
+            mMediaRecorder.reset();
+        } else {
+            // TODO: need implement MediaCodec path.
+        }
+        if (mRecordingSurface != null) {
+            mRecordingSurface.release();
+            mRecordingSurface = null;
+        }
+    }
+
+    private void releaseRecorder() {
+        if (mMediaRecorder != null) {
+            mMediaRecorder.release();
+            mMediaRecorder = null;
+        }
+    }
+
+    private void validateRecording(Size sz, int durationMs) throws Exception {
+        File outFile = new File(mOutMediaFileName);
+        assertTrue("No video is recorded", outFile.exists());
+
+        MediaPlayer mediaPlayer = new MediaPlayer();
+        try {
+            mediaPlayer.setDataSource(mOutMediaFileName);
+            mediaPlayer.prepare();
+            Size videoSz = new Size(mediaPlayer.getVideoWidth(), mediaPlayer.getVideoHeight());
+            assertTrue("Video size doesn't match, expected " + sz.toString() +
+                    " got " + videoSz.toString(), videoSz.equals(sz));
+            int duration = mediaPlayer.getDuration();
+            if (VERBOSE) {
+                Log.v(TAG, String.format("Video duration: recorded %dms, expected %dms",
+                                         duration, durationMs));
+            }
+
+            // TODO: Don't skip this for video snapshot
+            if (!mStaticInfo.isHardwareLevelLegacy()) {
+                assertTrue(String.format(
+                        "Video duration doesn't match: recorded %dms, expected %dms", duration,
+                        durationMs), Math.abs(duration - durationMs) < DURATION_MARGIN_MS);
+            }
+        } finally {
+            mediaPlayer.release();
+            if (!DEBUG_DUMP) {
+                outFile.delete();
+            }
+        }
+    }
+
+    /**
+     * 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.
+     * Return the estimated number of frames dropped during video snapshot
+     */
+    private int validateFrameDropAroundVideoSnapshot(
+            SimpleCaptureCallback 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;
+                int totalFramesDropped = 0;
+
+                // Snapshots in legacy mode pause the preview briefly.  Skip the duration
+                // requirements for legacy mode unless this is fixed.
+                if (!mStaticInfo.isHardwareLevelLegacy()) {
+                    // Log a warning is there is any frame drop detected.
+                    if (durationMs >= expectedDurationMs * 2) {
+                        Log.w(TAG, String.format(
+                                "Video %dx%d Frame drop detected before video snapshot: " +
+                                        "duration %dms (expected %dms)",
+                                mVideoSize.getWidth(), mVideoSize.getHeight(),
+                                durationMs, expectedDurationMs
+                        ));
+                    }
+
+                    durationMs = (int) (nextTS - currentTS) / 1000000;
+                    // Log a warning is there is any frame drop detected.
+                    if (durationMs >= expectedDurationMs * 2) {
+                        Log.w(TAG, String.format(
+                                "Video %dx%d Frame drop detected after video snapshot: " +
+                                        "duration %dms (expected %dms)",
+                                mVideoSize.getWidth(), mVideoSize.getHeight(),
+                                durationMs, expectedDurationMs
+                        ));
+                    }
+
+                    int totalDurationMs = (int) (nextTS - prevTS) / 1000000;
+                    // Rounding and minus 2 for the expected 2 frames interval
+                    totalFramesDropped =
+                            (totalDurationMs + expectedDurationMs / 2) /expectedDurationMs - 2;
+                    if (totalFramesDropped < 0) {
+                        Log.w(TAG, "totalFrameDropped is " + totalFramesDropped +
+                                ". Video frame rate might be too fast.");
+                    }
+                    totalFramesDropped = Math.max(0, totalFramesDropped);
+                }
+                return totalFramesDropped;
+            }
+            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(SimpleCaptureCallback 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);
+            long 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.
+     */
+    private int getVideoBitRate(Size sz) {
+        int rate = BIT_RATE_1080P;
+        float scaleFactor = sz.getHeight() * sz.getWidth() / (float)(1920 * 1080);
+        rate = (int)(rate * scaleFactor);
+
+        // Clamp to the MIN, MAX range.
+        return Math.max(BIT_RATE_MIN, Math.min(BIT_RATE_MAX, rate));
+    }
+
+    /**
+     * Check if the encoder and camera are able to support this size and frame rate.
+     * Assume the video compression format is AVC.
+     */
+    private boolean isSupported(Size sz, int captureRate, int encodingRate) throws Exception {
+        // Check camera capability.
+        if (!isSupportedByCamera(sz, captureRate)) {
+            return false;
+        }
+
+        // Check encode capability.
+        if (!isSupportedByAVCEncoder(sz, encodingRate)){
+            return false;
+        }
+
+        if(VERBOSE) {
+            Log.v(TAG, "Both encoder and camera support " + sz.toString() + "@" + encodingRate + "@"
+                    + getVideoBitRate(sz) / 1000 + "Kbps");
+        }
+
+        return true;
+    }
+
+    private boolean isSupportedByCamera(Size sz, int frameRate) {
+        // Check if camera can support this sz and frame rate combination.
+        StreamConfigurationMap config = mStaticInfo.
+                getValueFromKeyNonNull(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+
+        long minDuration = config.getOutputMinFrameDuration(MediaRecorder.class, sz);
+        if (minDuration == 0) {
+            return false;
+        }
+
+        int maxFrameRate = (int) (1e9f / minDuration);
+        return maxFrameRate >= frameRate;
+    }
+
+    /**
+     * Check if encoder can support this size and frame rate combination by querying
+     * MediaCodec capability. Check is based on size and frame rate. Ignore the bit rate
+     * as the bit rates targeted in this test are well below the bit rate max value specified
+     * by AVC specification for certain level.
+     */
+    private static boolean isSupportedByAVCEncoder(Size sz, int frameRate) {
+        String mimeType = "video/avc";
+        MediaCodecInfo codecInfo = getEncoderInfo(mimeType);
+        if (codecInfo == null) {
+            return false;
+        }
+        CodecCapabilities cap = codecInfo.getCapabilitiesForType(mimeType);
+        if (cap == null) {
+            return false;
+        }
+
+        int highestLevel = 0;
+        for (CodecProfileLevel lvl : cap.profileLevels) {
+            if (lvl.level > highestLevel) {
+                highestLevel = lvl.level;
+            }
+        }
+        // Don't support anything meaningful for level 1 or 2.
+        if (highestLevel <= CodecProfileLevel.AVCLevel2) {
+            return false;
+        }
+
+        if(VERBOSE) {
+            Log.v(TAG, "The highest level supported by encoder is: " + highestLevel);
+        }
+
+        // Put bitRate here for future use.
+        int maxW, maxH, bitRate;
+        // Max encoding speed.
+        int maxMacroblocksPerSecond = 0;
+        switch(highestLevel) {
+            case CodecProfileLevel.AVCLevel21:
+                maxW = 352;
+                maxH = 576;
+                bitRate = 4000000;
+                maxMacroblocksPerSecond = 19800;
+                break;
+            case CodecProfileLevel.AVCLevel22:
+                maxW = 720;
+                maxH = 480;
+                bitRate = 4000000;
+                maxMacroblocksPerSecond = 20250;
+                break;
+            case CodecProfileLevel.AVCLevel3:
+                maxW = 720;
+                maxH = 480;
+                bitRate = 10000000;
+                maxMacroblocksPerSecond = 40500;
+                break;
+            case CodecProfileLevel.AVCLevel31:
+                maxW = 1280;
+                maxH = 720;
+                bitRate = 14000000;
+                maxMacroblocksPerSecond = 108000;
+                break;
+            case CodecProfileLevel.AVCLevel32:
+                maxW = 1280;
+                maxH = 720;
+                bitRate = 20000000;
+                maxMacroblocksPerSecond = 216000;
+                break;
+            case CodecProfileLevel.AVCLevel4:
+                maxW = 1920;
+                maxH = 1088; // It should be 1088 in terms of AVC capability.
+                bitRate = 20000000;
+                maxMacroblocksPerSecond = 245760;
+                break;
+            case CodecProfileLevel.AVCLevel41:
+                maxW = 1920;
+                maxH = 1088; // It should be 1088 in terms of AVC capability.
+                bitRate = 50000000;
+                maxMacroblocksPerSecond = 245760;
+                break;
+            case CodecProfileLevel.AVCLevel42:
+                maxW = 2048;
+                maxH = 1088; // It should be 1088 in terms of AVC capability.
+                bitRate = 50000000;
+                maxMacroblocksPerSecond = 522240;
+                break;
+            case CodecProfileLevel.AVCLevel5:
+                maxW = 3672;
+                maxH = 1536;
+                bitRate = 135000000;
+                maxMacroblocksPerSecond = 589824;
+                break;
+            case CodecProfileLevel.AVCLevel51:
+            default:
+                maxW = 4096;
+                maxH = 2304;
+                bitRate = 240000000;
+                maxMacroblocksPerSecond = 983040;
+                break;
+        }
+
+        // Check size limit.
+        if (sz.getWidth() > maxW || sz.getHeight() > maxH) {
+            Log.i(TAG, "Requested resolution " + sz.toString() + " exceeds (" +
+                    maxW + "," + maxH + ")");
+            return false;
+        }
+
+        // Check frame rate limit.
+        Size sizeInMb = new Size((sz.getWidth() + 15) / 16, (sz.getHeight() + 15) / 16);
+        int maxFps = maxMacroblocksPerSecond / (sizeInMb.getWidth() * sizeInMb.getHeight());
+        if (frameRate > maxFps) {
+            Log.i(TAG, "Requested frame rate " + frameRate + " exceeds " + maxFps);
+            return false;
+        }
+
+        return true;
+    }
+
+    private static MediaCodecInfo getEncoderInfo(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 codecInfo;
+                }
+            }
+        }
+        return null;
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/RobustnessTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/RobustnessTest.java
new file mode 100644
index 0000000..7960200
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/RobustnessTest.java
@@ -0,0 +1,505 @@
+/*
+ * 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 static android.hardware.camera2.cts.CameraTestUtils.*;
+import static android.hardware.camera2.cts.RobustnessTest.MaxOutputSizes.*;
+
+import android.graphics.ImageFormat;
+import android.graphics.SurfaceTexture;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.TotalCaptureResult;
+import android.hardware.camera2.CaptureFailure;
+import android.hardware.camera2.params.StreamConfigurationMap;
+import android.hardware.camera2.cts.CameraTestUtils;
+import android.hardware.camera2.cts.helpers.StaticMetadata;
+import android.hardware.camera2.cts.testcases.Camera2AndroidTestCase;
+import android.media.CamcorderProfile;
+import android.media.ImageReader;
+import android.util.Log;
+import android.util.Size;
+import android.view.Surface;
+
+import com.android.ex.camera2.blocking.BlockingSessionCallback;
+
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.mockito.Mockito.*;
+
+/**
+ * Tests exercising edge cases in camera setup, configuration, and usage.
+ */
+public class RobustnessTest extends Camera2AndroidTestCase {
+    private static final String TAG = "RobustnessTest";
+
+    private static final int FAILED_CONFIGURE_TIMEOUT = 5000; //ms
+
+    /**
+     * Test that a {@link CameraCaptureSession} configured with a {@link Surface} with invalid
+     * dimensions fails gracefully.
+     */
+    public void testBadSurfaceDimensions() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                Log.i(TAG, "Testing Camera " + id);
+                openDevice(id);
+
+                // Setup Surface with unconfigured dimensions.
+                SurfaceTexture surfaceTexture = new SurfaceTexture(0);
+                Surface surface = new Surface(surfaceTexture);
+                List<Surface> surfaces = new ArrayList<>();
+                surfaces.add(surface);
+
+                // Setup a capture request and listener
+                CaptureRequest.Builder request =
+                        mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+                request.addTarget(surface);
+                CameraCaptureSession.CaptureCallback mockCaptureListener =
+                        mock(CameraCaptureSession.CaptureCallback.class);
+
+                // Check that correct session callback is hit.
+                CameraCaptureSession.StateCallback sessionListener =
+                        mock(CameraCaptureSession.StateCallback.class);
+                mCamera.createCaptureSession(surfaces, sessionListener, mHandler);
+                verify(sessionListener, timeout(FAILED_CONFIGURE_TIMEOUT).atLeastOnce()).
+                        onConfigureFailed(any(CameraCaptureSession.class));
+                verify(sessionListener, never()).onConfigured(any(CameraCaptureSession.class));
+                verify(sessionListener, never()).onActive(any(CameraCaptureSession.class));
+                verify(sessionListener, never()).onReady(any(CameraCaptureSession.class));
+                verify(sessionListener, never()).onClosed(any(CameraCaptureSession.class));
+            } finally {
+                closeDevice(id);
+            }
+        }
+    }
+
+    /**
+     * Test for making sure the required output combinations for each hardware level and capability
+     * work as expected.
+     */
+    public void testMandatoryOutputCombinations() throws Exception {
+        /**
+         * Tables for maximum sizes to try for each hardware level and capability.
+         *
+         * Keep in sync with the tables in
+         * frameworks/base/core/java/android/hardware/camera2/CameraDevice.java#createCaptureSession
+         *
+         * Each row of the table is a set of (format, max resolution) pairs, using the below consts
+         */
+
+        // Enum values are defined in MaxOutputSizes
+        final int[][] LEGACY_COMBINATIONS = {
+            {PRIV, MAXIMUM}, // Simple preview, GPU video processing, or no-preview video recording
+            {JPEG, MAXIMUM}, // No-viewfinder still image capture
+            {YUV,  MAXIMUM}, // In-application video/image processing
+            {PRIV, PREVIEW,  JPEG, MAXIMUM}, // Standard still imaging.
+            {YUV,  PREVIEW,  JPEG, MAXIMUM}, // In-app processing plus still capture.
+            {PRIV, PREVIEW,  PRIV, PREVIEW}, // Standard recording.
+            {PRIV, PREVIEW,  YUV,  PREVIEW}, // Preview plus in-app processing.
+            {PRIV, PREVIEW,  YUV,  PREVIEW,  JPEG, MAXIMUM} // Still capture plus in-app processing.
+        };
+
+        final int[][] LIMITED_COMBINATIONS = {
+            {PRIV, PREVIEW,  PRIV, RECORD }, // High-resolution video recording with preview.
+            {PRIV, PREVIEW,  YUV , RECORD }, // High-resolution in-app video processing with preview.
+            {YUV , PREVIEW,  YUV , RECORD }, // Two-input in-app video processing.
+            {PRIV, PREVIEW,  PRIV, RECORD,   JPEG, RECORD  }, // High-resolution recording with video snapshot.
+            {PRIV, PREVIEW,  YUV,  RECORD,   JPEG, RECORD  }, // High-resolution in-app processing with video snapshot.
+            {YUV , PREVIEW,  YUV,  PREVIEW,  JPEG, MAXIMUM }  // Two-input in-app processing with still capture.
+        };
+
+        final int[][] FULL_COMBINATIONS = {
+            {PRIV, PREVIEW,  PRIV, MAXIMUM }, // Maximum-resolution GPU processing with preview.
+            {PRIV, PREVIEW,  YUV,  MAXIMUM }, // Maximum-resolution in-app processing with preview.
+            {YUV,  PREVIEW,  YUV,  MAXIMUM }, // Maximum-resolution two-input in-app processsing.
+            {PRIV, PREVIEW,  PRIV, PREVIEW,  JPEG, MAXIMUM }, //Video recording with maximum-size video snapshot.
+            {YUV,  VGA,      PRIV, PREVIEW,  YUV,  MAXIMUM }, // Standard video recording plus maximum-resolution in-app processing.
+            {YUV,  VGA,      YUV,  PREVIEW,  YUV,  MAXIMUM } // Preview plus two-input maximum-resolution in-app processing.
+        };
+
+        final int[][] RAW_COMBINATIONS = {
+            {RAW,  MAXIMUM }, // No-preview DNG capture.
+            {PRIV, PREVIEW,  RAW,  MAXIMUM }, // Standard DNG capture.
+            {YUV,  PREVIEW,  RAW,  MAXIMUM }, // In-app processing plus DNG capture.
+            {PRIV, PREVIEW,  PRIV, PREVIEW,  RAW, MAXIMUM}, // Video recording with DNG capture.
+            {PRIV, PREVIEW,  YUV,  PREVIEW,  RAW, MAXIMUM}, // Preview with in-app processing and DNG capture.
+            {YUV,  PREVIEW,  YUV,  PREVIEW,  RAW, MAXIMUM}, // Two-input in-app processing plus DNG capture.
+            {PRIV, PREVIEW,  JPEG, MAXIMUM,  RAW, MAXIMUM}, // Still capture with simultaneous JPEG and DNG.
+            {YUV,  PREVIEW,  JPEG, MAXIMUM,  RAW, MAXIMUM}  // In-app processing with simultaneous JPEG and DNG.
+        };
+
+        final int[][][] TABLES =
+                { LEGACY_COMBINATIONS, LIMITED_COMBINATIONS, FULL_COMBINATIONS, RAW_COMBINATIONS };
+
+        // Sanity check the tables
+        int tableIdx = 0;
+        for (int[][] table : TABLES) {
+            int rowIdx = 0;
+            for (int[] row : table) {
+                assertTrue(String.format("Odd number of entries for table %d row %d: %s ",
+                                tableIdx, rowIdx, Arrays.toString(row)),
+                        (row.length % 2) == 0);
+                for (int i = 0; i < row.length; i += 2) {
+                    int format = row[i];
+                    int maxSize = row[i + 1];
+                    assertTrue(String.format("table %d row %d index %d format not valid: %d",
+                                    tableIdx, rowIdx, i, format),
+                            format == PRIV || format == JPEG || format == YUV || format == RAW);
+                    assertTrue(String.format("table %d row %d index %d max size not valid: %d",
+                                    tableIdx, rowIdx, i + 1, maxSize),
+                            maxSize == PREVIEW || maxSize == RECORD ||
+                            maxSize == MAXIMUM || maxSize == VGA);
+                }
+                rowIdx++;
+            }
+            tableIdx++;
+        }
+
+        for (String id : mCameraIds) {
+
+            // Find the concrete max sizes for each format/resolution combination
+
+            CameraCharacteristics cc = mCameraManager.getCameraCharacteristics(id);
+
+            MaxOutputSizes maxSizes = new MaxOutputSizes(cc, id);
+
+            final StaticMetadata staticInfo = new StaticMetadata(cc);
+
+            if (staticInfo.isHardwareLevelLegacy()) {
+                Log.i(TAG, "Skipping test on legacy devices");
+                continue;
+            }
+
+            openDevice(id);
+
+            // Always run legacy-level tests
+
+            for (int[] config : LEGACY_COMBINATIONS) {
+                testOutputCombination(id, config, maxSizes);
+            }
+
+            // Then run higher-level tests if applicable
+
+            if (!staticInfo.isHardwareLevelLegacy()) {
+
+                // If not legacy, at least limited, so run limited-level tests
+
+                for (int[] config : LIMITED_COMBINATIONS) {
+                    testOutputCombination(id, config, maxSizes);
+                }
+
+                // Check for FULL and RAW and run those if appropriate
+
+                if (staticInfo.isHardwareLevelFull()) {
+                    for (int[] config : FULL_COMBINATIONS) {
+                        testOutputCombination(id, config, maxSizes);
+                    }
+                }
+
+                if (staticInfo.isCapabilitySupported(
+                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)) {
+                    for (int[] config : RAW_COMBINATIONS) {
+                        testOutputCombination(id, config, maxSizes);
+                    }
+                }
+            }
+
+            closeDevice(id);
+        }
+    }
+
+    /**
+     * Simple holder for resolutions to use for different camera outputs and size limits.
+     */
+    static class MaxOutputSizes {
+        // Format shorthands
+        static final int PRIV = -1;
+        static final int JPEG = ImageFormat.JPEG;
+        static final int YUV  = ImageFormat.YUV_420_888;
+        static final int RAW  = ImageFormat.RAW_SENSOR;
+
+        // Max resolution indices
+        static final int PREVIEW = 0;
+        static final int RECORD  = 1;
+        static final int MAXIMUM = 2;
+        static final int VGA = 3;
+        static final int RESOLUTION_COUNT = 4;
+
+        public MaxOutputSizes(CameraCharacteristics cc, String cameraId) {
+            StreamConfigurationMap configs =
+                    cc.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+            Size[] privSizes = configs.getOutputSizes(SurfaceTexture.class);
+            Size[] yuvSizes = configs.getOutputSizes(ImageFormat.YUV_420_888);
+            Size[] jpegSizes = configs.getOutputSizes(ImageFormat.JPEG);
+            Size[] rawSizes = configs.getOutputSizes(ImageFormat.RAW_SENSOR);
+
+            maxRawSize = (rawSizes != null) ? CameraTestUtils.getMaxSize(rawSizes) : null;
+
+            maxPrivSizes[PREVIEW] = getMaxSize(privSizes, PREVIEW_SIZE_BOUND);
+            maxYuvSizes[PREVIEW]  = getMaxSize(yuvSizes, PREVIEW_SIZE_BOUND);
+            maxJpegSizes[PREVIEW] = getMaxSize(jpegSizes, PREVIEW_SIZE_BOUND);
+
+            maxPrivSizes[RECORD] = getMaxRecordingSize(cameraId);
+            maxYuvSizes[RECORD]  = getMaxRecordingSize(cameraId);
+            maxJpegSizes[RECORD] = getMaxRecordingSize(cameraId);
+
+            maxPrivSizes[MAXIMUM] = CameraTestUtils.getMaxSize(privSizes);
+            maxYuvSizes[MAXIMUM] = CameraTestUtils.getMaxSize(yuvSizes);
+            maxJpegSizes[MAXIMUM] = CameraTestUtils.getMaxSize(jpegSizes);
+
+            // Must always be supported, add unconditionally
+            final Size vgaSize = new Size(640, 480);
+            maxPrivSizes[VGA] = vgaSize;
+            maxJpegSizes[VGA] = vgaSize;
+            maxYuvSizes[VGA] = vgaSize;
+        }
+
+        public final Size[] maxPrivSizes = new Size[RESOLUTION_COUNT];
+        public final Size[] maxJpegSizes = new Size[RESOLUTION_COUNT];
+        public final Size[] maxYuvSizes = new Size[RESOLUTION_COUNT];
+        public final Size maxRawSize;
+
+        static public String configToString(int[] config) {
+            StringBuilder b = new StringBuilder("{ ");
+            for (int i = 0; i < config.length; i += 2) {
+                int format = config[i];
+                int sizeLimit = config[i + 1];
+                switch (format) {
+                    case PRIV:
+                        b.append("[PRIV, ");
+                        break;
+                    case JPEG:
+                        b.append("[JPEG, ");
+                        break;
+                    case YUV:
+                        b.append("[YUV, ");
+                        break;
+                    case RAW:
+                        b.append("[RAW, ");
+                        break;
+                    default:
+                        b.append("[UNK, ");
+                        break;
+                }
+                switch (sizeLimit) {
+                    case PREVIEW:
+                        b.append("PREVIEW] ");
+                        break;
+                    case RECORD:
+                        b.append("RECORD] ");
+                        break;
+                    case MAXIMUM:
+                        b.append("MAXIMUM] ");
+                        break;
+                    case VGA:
+                        b.append("VGA] ");
+                        break;
+                    default:
+                        b.append("UNK] ");
+                        break;
+                }
+            }
+            b.append("}");
+            return b.toString();
+        }
+    }
+
+    private void testOutputCombination(String cameraId, int[] config, MaxOutputSizes maxSizes)
+            throws Exception {
+
+        Log.i(TAG, String.format("Testing Camera %s, config %s",
+                        cameraId, MaxOutputSizes.configToString(config)));
+
+        final int TIMEOUT_FOR_RESULT_MS = 1000;
+        final int MIN_RESULT_COUNT = 3;
+
+        // Set up outputs
+        List<Object> outputTargets = new ArrayList<>();
+        List<Surface> outputSurfaces = new ArrayList<>();
+        List<SurfaceTexture> privTargets = new ArrayList<SurfaceTexture>();
+        List<ImageReader> jpegTargets = new ArrayList<ImageReader>();
+        List<ImageReader> yuvTargets = new ArrayList<ImageReader>();
+        List<ImageReader> rawTargets = new ArrayList<ImageReader>();
+        for (int i = 0; i < config.length; i += 2) {
+            int format = config[i];
+            int sizeLimit = config[i + 1];
+
+            switch (format) {
+                case PRIV: {
+                    Size targetSize = maxSizes.maxPrivSizes[sizeLimit];
+                    SurfaceTexture target = new SurfaceTexture(/*random int*/1);
+                    target.setDefaultBufferSize(targetSize.getWidth(), targetSize.getHeight());
+                    outputTargets.add(target);
+                    outputSurfaces.add(new Surface(target));
+                    privTargets.add(target);
+                    break;
+                }
+                case JPEG: {
+                    Size targetSize = maxSizes.maxJpegSizes[sizeLimit];
+                    ImageReader target = ImageReader.newInstance(
+                        targetSize.getWidth(), targetSize.getHeight(), JPEG, MIN_RESULT_COUNT);
+                    outputTargets.add(target);
+                    outputSurfaces.add(target.getSurface());
+                    jpegTargets.add(target);
+                    break;
+                }
+                case YUV: {
+                    Size targetSize = maxSizes.maxYuvSizes[sizeLimit];
+                    ImageReader target = ImageReader.newInstance(
+                        targetSize.getWidth(), targetSize.getHeight(), YUV, MIN_RESULT_COUNT);
+                    outputTargets.add(target);
+                    outputSurfaces.add(target.getSurface());
+                    yuvTargets.add(target);
+                    break;
+                }
+                case RAW: {
+                    Size targetSize = maxSizes.maxRawSize;
+                    ImageReader target = ImageReader.newInstance(
+                        targetSize.getWidth(), targetSize.getHeight(), RAW, MIN_RESULT_COUNT);
+                    outputTargets.add(target);
+                    outputSurfaces.add(target.getSurface());
+                    rawTargets.add(target);
+                    break;
+                }
+                default:
+                    fail("Unknown output format " + format);
+            }
+        }
+
+        boolean haveSession = false;
+        try {
+            CaptureRequest.Builder requestBuilder =
+                    mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+
+            for (Surface s : outputSurfaces) {
+                requestBuilder.addTarget(s);
+            }
+
+            CameraCaptureSession.CaptureCallback mockCaptureCallback =
+                    mock(CameraCaptureSession.CaptureCallback.class);
+
+            createSession(outputSurfaces);
+            haveSession = true;
+            CaptureRequest request = requestBuilder.build();
+            mCameraSession.setRepeatingRequest(request, mockCaptureCallback, mHandler);
+
+            verify(mockCaptureCallback,
+                    timeout(TIMEOUT_FOR_RESULT_MS * MIN_RESULT_COUNT).atLeast(MIN_RESULT_COUNT))
+                    .onCaptureCompleted(
+                        eq(mCameraSession),
+                        eq(request),
+                        isA(TotalCaptureResult.class));
+            verify(mockCaptureCallback, never()).
+                    onCaptureFailed(
+                        eq(mCameraSession),
+                        eq(request),
+                        isA(CaptureFailure.class));
+
+        } catch (Throwable e) {
+            mCollector.addMessage(String.format("Output combination %s failed due to: %s",
+                    MaxOutputSizes.configToString(config), e.getMessage()));
+        }
+        if (haveSession) {
+            try {
+                Log.i(TAG, String.format("Done with camera %s, config %s, closing session",
+                                cameraId, MaxOutputSizes.configToString(config)));
+                stopCapture(/*fast*/false);
+            } catch (Throwable e) {
+                mCollector.addMessage(
+                    String.format("Closing down for output combination %s failed due to: %s",
+                            MaxOutputSizes.configToString(config), e.getMessage()));
+            }
+        }
+
+        for (SurfaceTexture target : privTargets) {
+            target.release();
+        }
+        for (ImageReader target : jpegTargets) {
+            target.close();
+        }
+        for (ImageReader target : yuvTargets) {
+            target.close();
+        }
+        for (ImageReader target : rawTargets) {
+            target.close();
+        }
+    }
+
+    private static Size getMaxRecordingSize(String cameraId) {
+        int id = Integer.valueOf(cameraId);
+
+        int quality =
+                CamcorderProfile.hasProfile(id, CamcorderProfile.QUALITY_2160P) ?
+                    CamcorderProfile.QUALITY_2160P :
+                CamcorderProfile.hasProfile(id, CamcorderProfile.QUALITY_1080P) ?
+                    CamcorderProfile.QUALITY_1080P :
+                CamcorderProfile.hasProfile(id, CamcorderProfile.QUALITY_720P) ?
+                    CamcorderProfile.QUALITY_720P :
+                CamcorderProfile.hasProfile(id, CamcorderProfile.QUALITY_480P) ?
+                    CamcorderProfile.QUALITY_480P :
+                CamcorderProfile.hasProfile(id, CamcorderProfile.QUALITY_QVGA) ?
+                    CamcorderProfile.QUALITY_QVGA :
+                CamcorderProfile.hasProfile(id, CamcorderProfile.QUALITY_CIF) ?
+                    CamcorderProfile.QUALITY_CIF :
+                CamcorderProfile.hasProfile(id, CamcorderProfile.QUALITY_QCIF) ?
+                    CamcorderProfile.QUALITY_QCIF :
+                    -1;
+
+        assertTrue("No recording supported for camera id " + cameraId, quality != -1);
+
+        CamcorderProfile maxProfile = CamcorderProfile.get(id, quality);
+        return new Size(maxProfile.videoFrameWidth, maxProfile.videoFrameHeight);
+    }
+
+    /**
+     * Get maximum size in list that's equal or smaller to than the bound.
+     * Returns null if no size is smaller than or equal to the bound.
+     */
+    private static Size getMaxSize(Size[] sizes, Size bound) {
+        if (sizes == null || sizes.length == 0) {
+            throw new IllegalArgumentException("sizes was empty");
+        }
+
+        Size sz = null;
+        for (Size size : sizes) {
+            if (size.getWidth() <= bound.getWidth() && size.getHeight() <= bound.getHeight()) {
+
+                if (sz == null) {
+                    sz = size;
+                } else {
+                    long curArea = sz.getWidth() * (long) sz.getHeight();
+                    long newArea = size.getWidth() * (long) size.getHeight();
+                    if ( newArea > curArea ) {
+                        sz = size;
+                    }
+                }
+            }
+        }
+
+        assertTrue("No size under bound found: " + Arrays.toString(sizes) + " bound " + bound,
+                sz != null);
+
+        return sz;
+    }
+
+}
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..ec7ecf8
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/StaticMetadataTest.java
@@ -0,0 +1,416 @@
+/*
+ * 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.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+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 junit.framework.Assert;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * <p>
+ * This class covers the {@link CameraCharacteristics} tests that are not
+ * covered by {@link CaptureRequestTest} and {@link ExtendedCameraCharacteristicsTest}
+ * </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;
+    private String mCameraId;
+
+    /**
+     * Test the available capability for different hardware support level devices.
+     */
+    public void testHwSupportedLevel() throws Exception {
+        for (String id : mCameraIds) {
+            initStaticMetadata(id);
+            List<Integer> availableCaps = mStaticInfo.getAvailableCapabilitiesChecked();
+
+            mCollector.expectTrue("All device must contains BACKWARD_COMPATIBLE capability",
+                    availableCaps.contains(REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE));
+
+            if (mStaticInfo.isHardwareLevelFull()) {
+                // Capability advertisement must be right.
+                mCollector.expectTrue("Full device must contains MANUAL_SENSOR capability",
+                        availableCaps.contains(REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR));
+                mCollector.expectTrue("Full device must contains MANUAL_POST_PROCESSING capability",
+                        availableCaps.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 advertised capability does match available keys and vice versa
+     */
+    public void testCapabilities() throws Exception {
+        for (String id : mCameraIds) {
+            initStaticMetadata(id);
+            List<Integer> availableCaps = mStaticInfo.getAvailableCapabilitiesChecked();
+
+            for (Integer capability = REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE;
+                    capability <= REQUEST_AVAILABLE_CAPABILITIES_RAW; capability++) {
+                boolean isCapabilityAvailable = availableCaps.contains(capability);
+                validateCapability(capability, isCapabilityAvailable);
+            }
+            // Note: Static metadata for capabilities is tested in ExtendedCameraCharacteristicsTest
+        }
+    }
+
+    /**
+     * Check if request keys' presence match expectation.
+     *
+     * @param capabilityName The name string of capability being tested. Used for output messages.
+     * @param requestKeys The capture request keys to be checked
+     * @param expectedPresence Expected presence of {@code requestKeys}. {@code true} for expecting
+     *        all keys are available. Otherwise {@code false}
+     * @return {@code true} if request keys' presence match expectation. Otherwise {@code false}
+     */
+    private boolean validateRequestKeysPresence(String capabilityName,
+            Collection<CaptureRequest.Key<?>> requestKeys, boolean expectedPresence) {
+        boolean actualPresence = mStaticInfo.areRequestKeysAvailable(requestKeys);
+        if (expectedPresence != actualPresence) {
+            if (expectedPresence) {
+                for (CaptureRequest.Key<?> key : requestKeys) {
+                    if (!mStaticInfo.areKeysAvailable(key)) {
+                        mCollector.addMessage(String.format(
+                                "Camera %s list capability %s but doesn't contain request key %s",
+                                mCameraId, capabilityName, key.getName()));
+                    }
+                }
+            } else {
+                Log.w(TAG, String.format(
+                        "Camera %s doesn't list capability %s but contain all required keys",
+                        mCameraId, capabilityName));
+            }
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Check if result keys' presence match expectation.
+     *
+     * @param capabilityName The name string of capability being tested. Used for output messages.
+     * @param resultKeys The capture result keys to be checked
+     * @param expectedPresence Expected presence of {@code resultKeys}. {@code true} for expecting
+     *        all keys are available. Otherwise {@code false}
+     * @return {@code true} if result keys' presence match expectation. Otherwise {@code false}
+     */
+    private boolean validateResultKeysPresence(String capabilityName,
+            Collection<CaptureResult.Key<?>> resultKeys, boolean expectedPresence) {
+        boolean actualPresence = mStaticInfo.areResultKeysAvailable(resultKeys);
+        if (expectedPresence != actualPresence) {
+            if (expectedPresence) {
+                for (CaptureResult.Key<?> key : resultKeys) {
+                    if (!mStaticInfo.areKeysAvailable(key)) {
+                        mCollector.addMessage(String.format(
+                                "Camera %s list capability %s but doesn't contain result key %s",
+                                mCameraId, capabilityName, key.getName()));
+                    }
+                }
+            } else {
+                Log.w(TAG, String.format(
+                        "Camera %s doesn't list capability %s but contain all required keys",
+                        mCameraId, capabilityName));
+            }
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Check if characteristics keys' presence match expectation.
+     *
+     * @param capabilityName The name string of capability being tested. Used for output messages.
+     * @param characteristicsKeys The characteristics keys to be checked
+     * @param expectedPresence Expected presence of {@code characteristicsKeys}. {@code true} for
+     *        expecting all keys are available. Otherwise {@code false}
+     * @return {@code true} if characteristics keys' presence match expectation.
+     *         Otherwise {@code false}
+     */
+    private boolean validateCharacteristicsKeysPresence(String capabilityName,
+            Collection<CameraCharacteristics.Key<?>> characteristicsKeys,
+            boolean expectedPresence) {
+        boolean actualPresence = mStaticInfo.areCharacteristicsKeysAvailable(characteristicsKeys);
+        if (expectedPresence != actualPresence) {
+            if (expectedPresence) {
+                for (CameraCharacteristics.Key<?> key : characteristicsKeys) {
+                    if (!mStaticInfo.areKeysAvailable(key)) {
+                        mCollector.addMessage(String.format(
+                                "Camera %s list capability %s but doesn't contain" +
+                                "characteristics key %s",
+                                mCameraId, capabilityName, key.getName()));
+                    }
+                }
+            } else {
+                Log.w(TAG, String.format(
+                        "Camera %s doesn't list capability %s but contain all required keys",
+                        mCameraId, capabilityName));
+            }
+            return false;
+        }
+        return true;
+    }
+
+    private void validateCapability(Integer capability, boolean isCapabilityAvailable) {
+        List<CaptureRequest.Key<?>> requestKeys = new ArrayList<>();
+        /* For available capabilities, only check request keys in this test
+           Characteristics keys are tested in ExtendedCameraCharacteristicsTest
+           Result keys are tested in CaptureResultTest */
+        String capabilityName;
+        switch (capability) {
+            case REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE:
+                capabilityName = "REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE";
+                requestKeys.add(CaptureRequest.CONTROL_AE_ANTIBANDING_MODE);
+                requestKeys.add(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION);
+                requestKeys.add(CaptureRequest.CONTROL_AE_LOCK);
+                requestKeys.add(CaptureRequest.CONTROL_AE_MODE);
+                requestKeys.add(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE);
+                requestKeys.add(CaptureRequest.CONTROL_AF_MODE);
+                requestKeys.add(CaptureRequest.CONTROL_AF_TRIGGER);
+                requestKeys.add(CaptureRequest.CONTROL_AWB_LOCK);
+                requestKeys.add(CaptureRequest.CONTROL_AWB_MODE);
+                requestKeys.add(CaptureRequest.CONTROL_CAPTURE_INTENT);
+                requestKeys.add(CaptureRequest.CONTROL_EFFECT_MODE);
+                requestKeys.add(CaptureRequest.CONTROL_MODE);
+                requestKeys.add(CaptureRequest.CONTROL_SCENE_MODE);
+                requestKeys.add(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE);
+                requestKeys.add(CaptureRequest.FLASH_MODE);
+                requestKeys.add(CaptureRequest.JPEG_GPS_LOCATION);
+                requestKeys.add(CaptureRequest.JPEG_ORIENTATION);
+                requestKeys.add(CaptureRequest.JPEG_QUALITY);
+                requestKeys.add(CaptureRequest.JPEG_THUMBNAIL_QUALITY);
+                requestKeys.add(CaptureRequest.JPEG_THUMBNAIL_SIZE);
+                requestKeys.add(CaptureRequest.SCALER_CROP_REGION);
+                requestKeys.add(CaptureRequest.STATISTICS_FACE_DETECT_MODE);
+                if (mStaticInfo.getAeMaxRegionsChecked() > 0) {
+                    requestKeys.add(CaptureRequest.CONTROL_AE_REGIONS);
+                } else {
+                    mCollector.expectTrue(
+                            "CONTROL_AE_REGIONS is available but aeMaxRegion is 0",
+                            !mStaticInfo.areKeysAvailable(CaptureRequest.CONTROL_AE_REGIONS));
+                }
+                if (mStaticInfo.getAwbMaxRegionsChecked() > 0) {
+                    requestKeys.add(CaptureRequest.CONTROL_AWB_REGIONS);
+                } else {
+                    mCollector.expectTrue(
+                            "CONTROL_AWB_REGIONS is available but awbMaxRegion is 0",
+                            !mStaticInfo.areKeysAvailable(CaptureRequest.CONTROL_AWB_REGIONS));
+                }
+                if (mStaticInfo.getAfMaxRegionsChecked() > 0) {
+                    requestKeys.add(CaptureRequest.CONTROL_AF_REGIONS);
+                } else {
+                    mCollector.expectTrue(
+                            "CONTROL_AF_REGIONS is available but afMaxRegion is 0",
+                            !mStaticInfo.areKeysAvailable(CaptureRequest.CONTROL_AF_REGIONS));
+                }
+                break;
+            case REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING:
+                capabilityName = "REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING";
+                requestKeys.add(CaptureRequest.TONEMAP_MODE);
+                requestKeys.add(CaptureRequest.COLOR_CORRECTION_GAINS);
+                requestKeys.add(CaptureRequest.COLOR_CORRECTION_TRANSFORM);
+                requestKeys.add(CaptureRequest.SHADING_MODE);
+                requestKeys.add(CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE);
+                if (mStaticInfo.isHardwareLevelFull()) {
+                    requestKeys.add(CaptureRequest.TONEMAP_CURVE);
+                    requestKeys.add(CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE);
+                }
+
+                break;
+            case REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR:
+                capabilityName = "REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR";
+                requestKeys.add(CaptureRequest.SENSOR_FRAME_DURATION);
+                requestKeys.add(CaptureRequest.SENSOR_EXPOSURE_TIME);
+                requestKeys.add(CaptureRequest.SENSOR_SENSITIVITY);
+                if (mStaticInfo.hasFocuser()) {
+                    requestKeys.add(CaptureRequest.LENS_APERTURE);
+                    requestKeys.add(CaptureRequest.LENS_FILTER_DENSITY);
+                    requestKeys.add(CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE);
+                }
+                requestKeys.add(CaptureRequest.BLACK_LEVEL_LOCK);
+                break;
+            case REQUEST_AVAILABLE_CAPABILITIES_RAW:
+                // RAW_CAPABILITY needs to check for not just capture request keys
+                validateRawCapability(isCapabilityAvailable);
+                return;
+            default:
+                capabilityName = "Unknown";
+                Assert.fail(String.format("Unknown capability: %d", capability));
+        }
+
+        boolean matchExpectation =
+                validateRequestKeysPresence(capabilityName, requestKeys, isCapabilityAvailable);
+        // In case of isCapabilityAvailable == true, error has been filed in
+        // validateRequestKeysPresence
+        if (!matchExpectation && !isCapabilityAvailable) {
+            mCollector.addMessage(String.format(
+                    "Camera %s doesn't list capability %s but contain all required keys",
+                    mCameraId, capabilityName));
+        }
+    }
+
+    private void validateRawCapability(boolean isCapabilityAvailable) {
+        String capabilityName = "REQUEST_AVAILABLE_CAPABILITIES_RAW";
+
+        Set<CaptureRequest.Key<?>> requestKeys = new HashSet<>();
+        requestKeys.add(CaptureRequest.HOT_PIXEL_MODE);
+        requestKeys.add(CaptureRequest.STATISTICS_HOT_PIXEL_MAP_MODE);
+
+        Set<CameraCharacteristics.Key<?>> characteristicsKeys = new HashSet<>();
+        characteristicsKeys.add(HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES);
+        characteristicsKeys.add(SENSOR_BLACK_LEVEL_PATTERN);
+        characteristicsKeys.add(SENSOR_CALIBRATION_TRANSFORM1);
+        characteristicsKeys.add(SENSOR_CALIBRATION_TRANSFORM2);
+        characteristicsKeys.add(SENSOR_COLOR_TRANSFORM1);
+        characteristicsKeys.add(SENSOR_COLOR_TRANSFORM2);
+        characteristicsKeys.add(SENSOR_FORWARD_MATRIX1);
+        characteristicsKeys.add(SENSOR_FORWARD_MATRIX2);
+        characteristicsKeys.add(SENSOR_INFO_ACTIVE_ARRAY_SIZE);
+        characteristicsKeys.add(SENSOR_INFO_COLOR_FILTER_ARRANGEMENT);
+        characteristicsKeys.add(SENSOR_INFO_WHITE_LEVEL);
+        characteristicsKeys.add(SENSOR_REFERENCE_ILLUMINANT1);
+        characteristicsKeys.add(SENSOR_REFERENCE_ILLUMINANT2);
+        characteristicsKeys.add(STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES);
+
+        Set<CaptureResult.Key<?>> resultKeys = new HashSet<>();
+        resultKeys.add(CaptureResult.SENSOR_NEUTRAL_COLOR_POINT);
+        resultKeys.add(CaptureResult.SENSOR_GREEN_SPLIT);
+        resultKeys.add(CaptureResult.SENSOR_NOISE_PROFILE);
+
+        boolean rawOutputSupported = mStaticInfo.getRawOutputSizesChecked().length > 0;
+        boolean requestKeysPresent = mStaticInfo.areRequestKeysAvailable(requestKeys);
+        boolean characteristicsKeysPresent =
+                mStaticInfo.areCharacteristicsKeysAvailable(characteristicsKeys);
+        boolean resultKeysPresent = mStaticInfo.areResultKeysAvailable(resultKeys);
+        boolean expectCapabilityPresent = rawOutputSupported && requestKeysPresent &&
+                characteristicsKeysPresent && resultKeysPresent;
+
+        if (isCapabilityAvailable != expectCapabilityPresent) {
+            if (isCapabilityAvailable) {
+                mCollector.expectTrue(
+                        "REQUEST_AVAILABLE_CAPABILITIES_RAW should support RAW_SENSOR output",
+                        rawOutputSupported);
+                validateRequestKeysPresence(capabilityName, requestKeys, isCapabilityAvailable);
+                validateResultKeysPresence(capabilityName, resultKeys, isCapabilityAvailable);
+                validateCharacteristicsKeysPresence(capabilityName, characteristicsKeys,
+                        isCapabilityAvailable);
+            } else {
+                mCollector.addMessage(String.format(
+                        "Camera %s doesn't list capability %s but contain all required keys" +
+                        " and RAW format output",
+                        mCameraId, capabilityName));
+            }
+        }
+    }
+
+    /**
+     * 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 {
+        mCameraId = cameraId;
+        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
new file mode 100644
index 0000000..f18a1cf
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/StillCaptureTest.java
@@ -0,0 +1,1608 @@
+/*
+ * 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.cts.CameraTestUtils.*;
+import static android.hardware.camera2.cts.helpers.AssertHelpers.assertArrayContains;
+import static junit.framework.Assert.assertNotNull;
+
+import android.graphics.ImageFormat;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.hardware.camera2.CameraCharacteristics;
+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.Pair;
+import android.util.Size;
+import android.hardware.camera2.cts.CameraTestUtils.SimpleCaptureCallback;
+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.blocking.BlockingSessionCallback;
+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;
+
+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);
+    // 60 second to accommodate the possible long exposure time.
+    private static final int EXIF_DATETIME_ERROR_MARGIN_SEC = 60;
+    private static final float EXIF_FOCAL_LENGTH_ERROR_MARGIN = 0.001f;
+    private static final float EXIF_EXPOSURE_TIME_ERROR_MARGIN_RATIO = 0.05f;
+    private static final float EXIF_EXPOSURE_TIME_MIN_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(
+                    /*gpsLocation*/ sTestLocation0,
+                    /* orientation */90,
+                    /* jpgQuality */(byte) 80,
+                    /* thumbQuality */(byte) 75),
+            new ExifTestData(
+                    /*gpsLocation*/ sTestLocation1,
+                    /* orientation */180,
+                    /* jpgQuality */(byte) 90,
+                    /* thumbQuality */(byte) 85),
+            new ExifTestData(
+                    /*gpsLocation*/ sTestLocation2,
+                    /* orientation */270,
+                    /* jpgQuality */(byte) 100,
+                    /* thumbQuality */(byte) 100)
+    };
+
+    // Some exif tags that are not defined by ExifInterface but supported.
+    private static final String TAG_DATETIME_DIGITIZED = "DateTimeDigitized";
+    private static final String TAG_SUBSEC_TIME = "SubSecTime";
+    private static final String TAG_SUBSEC_TIME_ORIG = "SubSecTimeOriginal";
+    private static final String TAG_SUBSEC_TIME_DIG = "SubSecTimeDigitized";
+    private static final int EXIF_DATETIME_LENGTH = 19;
+    private static final int MAX_REGIONS_AE_INDEX = 0;
+    private static final int MAX_REGIONS_AWB_INDEX = 1;
+    private static final int MAX_REGIONS_AF_INDEX = 2;
+    private static final int WAIT_FOR_FOCUS_DONE_TIMEOUT_MS = 3000;
+    private static final double AE_COMPENSATION_ERROR_TOLERANCE = 0.2;
+    private static final int NUM_FRAMES_WAITED = 30;
+    // 5 percent error margin for resulting metering regions
+    private static final float METERING_REGION_ERROR_PERCENT_DELTA = 0.05f;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    /**
+     * Test JPEG capture exif fields for each camera.
+     */
+    public void testJpegExif() throws Exception {
+        for (int i = 0; i < mCameraIds.length; i++) {
+            try {
+                Log.i(TAG, "Testing JPEG exif for Camera " + mCameraIds[i]);
+                openDevice(mCameraIds[i]);
+
+                jpegExifTestByCamera();
+            } finally {
+                closeDevice();
+                closeImageReader();
+            }
+        }
+    }
+
+    /**
+     * Test normal still capture sequence.
+     * <p>
+     * Preview and and jpeg output streams are configured. Max still capture
+     * size is used for jpeg capture. The sequence of still capture being test
+     * is: start preview, auto focus, precapture metering (if AE is not
+     * converged), then capture jpeg. The AWB and AE are in auto modes. AF mode
+     * is CONTINUOUS_PICTURE.
+     * </p>
+     */
+    public void testTakePicture() throws Exception{
+        for (String id : mCameraIds) {
+            try {
+                Log.i(TAG, "Testing touch for focus for Camera " + id);
+                openDevice(id);
+
+                takePictureTestByCamera(/*aeRegions*/null, /*awbRegions*/null, /*afRegions*/null);
+            } finally {
+                closeDevice();
+                closeImageReader();
+            }
+        }
+    }
+
+    /**
+     * Test basic Raw capture. Raw buffer avaiablility is checked, but raw buffer data is not.
+     */
+    public void testBasicRawCapture()  throws Exception {
+       for (int i = 0; i < mCameraIds.length; i++) {
+           try {
+               Log.i(TAG, "Testing raw capture for Camera " + mCameraIds[i]);
+               openDevice(mCameraIds[i]);
+
+               if (!mStaticInfo.isCapabilitySupported(
+                       CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)) {
+                   Log.i(TAG, "RAW capability is not supported in camera " + mCameraIds[i] +
+                           ". Skip the test.");
+                   continue;
+               }
+
+               rawCaptureTestByCamera();
+           } finally {
+               closeDevice();
+               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]);
+                if (!mStaticInfo.isCapabilitySupported(
+                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)) {
+                    Log.i(TAG, "RAW capability is not supported in camera " + mCameraIds[i] +
+                            ". Skip the test.");
+                    continue;
+                }
+
+                fullRawCaptureTestByCamera();
+            } finally {
+                closeDevice();
+                closeImageReader();
+            }
+        }
+    }
+    /**
+     * Test touch for focus.
+     * <p>
+     * AF is in CAF mode when preview is started, test uses several pre-selected
+     * regions to simulate touches. Active scan is triggered to make sure the AF
+     * converges in reasonable time.
+     * </p>
+     */
+    public void testTouchForFocus() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                Log.i(TAG, "Testing touch for focus for Camera " + id);
+                openDevice(id);
+                int maxAfRegions = mStaticInfo.getAfMaxRegionsChecked();
+                if (!(mStaticInfo.hasFocuser() && maxAfRegions > 0)) {
+                    continue;
+                }
+
+                touchForFocusTestByCamera();
+            } finally {
+                closeDevice();
+                closeImageReader();
+            }
+        }
+    }
+
+    /**
+     * Test all combination of available preview sizes and still sizes.
+     * <p>
+     * For each still capture, Only the jpeg buffer is validated, capture
+     * result validation is covered by {@link #jpegExifTestByCamera} test.
+     * </p>
+     */
+    public void testStillPreviewCombination() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                Log.i(TAG, "Testing Still preview capture combination for Camera " + id);
+                openDevice(id);
+
+                if (mStaticInfo.isHardwareLevelLegacy()) {
+                    Log.i(TAG, "Skipping test for legacy devices");
+                    continue;
+                }
+
+                previewStillCombinationTestByCamera();
+            } finally {
+                closeDevice();
+                closeImageReader();
+            }
+        }
+    }
+
+    /**
+     * Test AE compensation.
+     * <p>
+     * For each integer EV compensation setting: retrieve the exposure value (exposure time *
+     * sensitivity) with or without compensation, verify if the exposure value is legal (conformed
+     * to what static info has) and the ratio between two exposure values matches EV compensation
+     * setting. Also test for the behavior that exposure settings should be changed when AE
+     * compensation settings is changed, even when AE lock is ON.
+     * </p>
+     */
+    public void testAeCompensation() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                Log.i(TAG, "Testing AE compensation for Camera " + id);
+                openDevice(id);
+                aeCompensationTestByCamera();
+            } finally {
+                closeDevice();
+                closeImageReader();
+            }
+        }
+    }
+
+    /**
+     * Test Ae region for still capture.
+     */
+    public void testAeRegions() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                Log.i(TAG, "Testing AE regions for Camera " + id);
+                openDevice(id);
+
+                if (mStaticInfo.isHardwareLevelLegacy()) {
+                    Log.i(TAG, "Skipping test on legacy devices");
+                    continue;
+                }
+
+                boolean aeRegionsSupported = isRegionsSupportedFor3A(MAX_REGIONS_AE_INDEX);
+                if (!aeRegionsSupported) {
+                    continue;
+                }
+
+                ArrayList<MeteringRectangle[]> aeRegionTestCases = get3ARegionTestCasesForCamera();
+                for (MeteringRectangle[] aeRegions : aeRegionTestCases) {
+                    takePictureTestByCamera(aeRegions, /*awbRegions*/null, /*afRegions*/null);
+                }
+            } finally {
+                closeDevice();
+                closeImageReader();
+            }
+        }
+    }
+
+    /**
+     * Test AWB region for still capture.
+     */
+    public void testAwbRegions() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                Log.i(TAG, "Testing AE regions for Camera " + id);
+                openDevice(id);
+
+                boolean awbRegionsSupported = isRegionsSupportedFor3A(MAX_REGIONS_AWB_INDEX);
+                if (!awbRegionsSupported) {
+                    continue;
+                }
+
+                ArrayList<MeteringRectangle[]> awbRegionTestCases = get3ARegionTestCasesForCamera();
+                for (MeteringRectangle[] awbRegions : awbRegionTestCases) {
+                    takePictureTestByCamera(/*aeRegions*/null, awbRegions, /*afRegions*/null);
+                }
+            } finally {
+                closeDevice();
+                closeImageReader();
+            }
+        }
+    }
+
+    /**
+     * Test Af region for still capture.
+     */
+    public void testAfRegions() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                Log.i(TAG, "Testing AF regions for Camera " + id);
+                openDevice(id);
+
+                if (mStaticInfo.isHardwareLevelLegacy()) {
+                    Log.i(TAG, "Skipping test on legacy devices");
+                    continue;
+                }
+
+                boolean afRegionsSupported = isRegionsSupportedFor3A(MAX_REGIONS_AF_INDEX);
+                if (!afRegionsSupported) {
+                    continue;
+                }
+
+                ArrayList<MeteringRectangle[]> afRegionTestCases = get3ARegionTestCasesForCamera();
+                for (MeteringRectangle[] afRegions : afRegionTestCases) {
+                    takePictureTestByCamera(/*aeRegions*/null, /*awbRegions*/null, afRegions);
+                }
+            } finally {
+                closeDevice();
+                closeImageReader();
+            }
+        }
+    }
+
+    /**
+     * Test preview is still running after a still request
+     */
+    public void testPreviewPersistence() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                Log.i(TAG, "Testing preview persistence for Camera " + id);
+                openDevice(id);
+                previewPersistenceTestByCamera();
+            } finally {
+                closeDevice();
+                closeImageReader();
+            }
+        }
+    }
+
+    /**
+     * Start preview,take a picture and test preview is still running after snapshot
+     */
+    private void previewPersistenceTestByCamera() throws Exception {
+        Size maxStillSz = mOrderedStillSizes.get(0);
+        Size maxPreviewSz = mOrderedPreviewSizes.get(0);
+
+        SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
+        SimpleCaptureCallback stillResultListener = new SimpleCaptureCallback();
+        SimpleImageReaderListener imageListener = new SimpleImageReaderListener();
+        CaptureRequest.Builder previewRequest =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        CaptureRequest.Builder stillRequest =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
+        prepareStillCaptureAndStartPreview(previewRequest, stillRequest, maxPreviewSz,
+                maxStillSz, resultListener, imageListener);
+
+        // make sure preview is actually running
+        waitForNumResults(resultListener, NUM_FRAMES_WAITED);
+
+        // take a picture
+        CaptureRequest request = stillRequest.build();
+        mSession.capture(request, stillResultListener, mHandler);
+        stillResultListener.getCaptureResultForRequest(request,
+                WAIT_FOR_RESULT_TIMEOUT_MS);
+
+        // validate image
+        Image image = imageListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
+        validateJpegCapture(image, maxStillSz);
+
+        // make sure preview is still running after still capture
+        waitForNumResults(resultListener, NUM_FRAMES_WAITED);
+
+        stopPreview();
+        return;
+    }
+
+    /**
+     * Take a picture for a given set of 3A regions for a particular camera.
+     * <p>
+     * Before take a still capture, it triggers an auto focus and lock it first,
+     * then wait for AWB to converge and lock it, then trigger a precapture
+     * metering sequence and wait for AE converged. After capture is received, the
+     * capture result and image are validated.
+     * </p>
+     *
+     * @param aeRegions AE regions for this capture
+     * @param awbRegions AWB regions for this capture
+     * @param afRegions AF regions for this capture
+     */
+    private void takePictureTestByCamera(
+            MeteringRectangle[] aeRegions, MeteringRectangle[] awbRegions,
+            MeteringRectangle[] afRegions) throws Exception {
+
+        boolean hasFocuser = mStaticInfo.hasFocuser();
+
+        Size maxStillSz = mOrderedStillSizes.get(0);
+        Size maxPreviewSz = mOrderedPreviewSizes.get(0);
+        CaptureResult result;
+        SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
+        SimpleImageReaderListener imageListener = new SimpleImageReaderListener();
+        CaptureRequest.Builder previewRequest =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        CaptureRequest.Builder stillRequest =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
+        prepareStillCaptureAndStartPreview(previewRequest, stillRequest, maxPreviewSz,
+                maxStillSz, resultListener, imageListener);
+
+        // Set AE mode to ON_AUTO_FLASH if flash is available.
+        if (mStaticInfo.hasFlash()) {
+            previewRequest.set(CaptureRequest.CONTROL_AE_MODE,
+                    CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
+            stillRequest.set(CaptureRequest.CONTROL_AE_MODE,
+                    CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
+        }
+
+        Camera2Focuser focuser = null;
+        /**
+         * Step 1: trigger an auto focus run, and wait for AF locked.
+         */
+        boolean canSetAfRegion = hasFocuser && (afRegions != null) &&
+                isRegionsSupportedFor3A(MAX_REGIONS_AF_INDEX);
+        if (hasFocuser) {
+            SimpleAutoFocusListener afListener = new SimpleAutoFocusListener();
+            focuser = new Camera2Focuser(mCamera, mSession, mPreviewSurface, afListener,
+                    mStaticInfo.getCharacteristics(), mHandler);
+            if (canSetAfRegion) {
+                stillRequest.set(CaptureRequest.CONTROL_AF_REGIONS, afRegions);
+            }
+            focuser.startAutoFocus(afRegions);
+            afListener.waitForAutoFocusDone(WAIT_FOR_FOCUS_DONE_TIMEOUT_MS);
+        }
+
+        /**
+         * Have to get the current AF mode to be used for other 3A repeating
+         * request, otherwise, the new AF mode in AE/AWB request could be
+         * different with existing repeating requests being sent by focuser,
+         * then it could make AF unlocked too early. Beside that, for still
+         * capture, AF mode must not be different with the one in current
+         * repeating request, otherwise, the still capture itself would trigger
+         * an AF mode change, and the AF lock would be lost for this capture.
+         */
+        int currentAfMode = CaptureRequest.CONTROL_AF_MODE_OFF;
+        if (hasFocuser) {
+            currentAfMode = focuser.getCurrentAfMode();
+        }
+        previewRequest.set(CaptureRequest.CONTROL_AF_MODE, currentAfMode);
+        stillRequest.set(CaptureRequest.CONTROL_AF_MODE, currentAfMode);
+
+        /**
+         * Step 2: AF is already locked, wait for AWB converged, then lock it.
+         */
+        resultListener = new SimpleCaptureCallback();
+        boolean canSetAwbRegion =
+                (awbRegions != null) && isRegionsSupportedFor3A(MAX_REGIONS_AWB_INDEX);
+        if (canSetAwbRegion) {
+            previewRequest.set(CaptureRequest.CONTROL_AWB_REGIONS, awbRegions);
+            stillRequest.set(CaptureRequest.CONTROL_AWB_REGIONS, awbRegions);
+        }
+        mSession.setRepeatingRequest(previewRequest.build(), resultListener, mHandler);
+        if (mStaticInfo.isHardwareLevelLimitedOrBetter()) {
+            waitForResultValue(resultListener, CaptureResult.CONTROL_AWB_STATE,
+                    CaptureResult.CONTROL_AWB_STATE_CONVERGED, NUM_RESULTS_WAIT_TIMEOUT);
+        } else {
+            // LEGACY Devices don't have the AWB_STATE reported in results, so just wait
+            waitForSettingsApplied(resultListener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+        }
+        previewRequest.set(CaptureRequest.CONTROL_AWB_LOCK, true);
+        mSession.setRepeatingRequest(previewRequest.build(), resultListener, mHandler);
+        // Validate the next result immediately for region and mode.
+        result = resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+        mCollector.expectEquals("AWB mode in result and request should be same",
+                previewRequest.get(CaptureRequest.CONTROL_AWB_MODE),
+                result.get(CaptureResult.CONTROL_AWB_MODE));
+        if (canSetAwbRegion) {
+            MeteringRectangle[] resultAwbRegions =
+                    getValueNotNull(result, CaptureResult.CONTROL_AWB_REGIONS);
+            mCollector.expectEquals("AWB regions in result and request should be same",
+                    awbRegions, resultAwbRegions);
+        }
+
+        /**
+         * Step 3: trigger an AE precapture metering sequence and wait for AE converged.
+         */
+        resultListener = new SimpleCaptureCallback();
+        boolean canSetAeRegion =
+                (aeRegions != null) && isRegionsSupportedFor3A(MAX_REGIONS_AE_INDEX);
+        if (canSetAeRegion) {
+            previewRequest.set(CaptureRequest.CONTROL_AE_REGIONS, aeRegions);
+            stillRequest.set(CaptureRequest.CONTROL_AE_REGIONS, aeRegions);
+        }
+        mSession.setRepeatingRequest(previewRequest.build(), resultListener, mHandler);
+        previewRequest.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
+                CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
+        mSession.capture(previewRequest.build(), resultListener, mHandler);
+        waitForAeStable(resultListener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+
+        // Validate the next result immediately for region and mode.
+        result = resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+        mCollector.expectEquals("AE mode in result and request should be same",
+                previewRequest.get(CaptureRequest.CONTROL_AE_MODE),
+                result.get(CaptureResult.CONTROL_AE_MODE));
+        if (canSetAeRegion) {
+            MeteringRectangle[] resultAeRegions =
+                    getValueNotNull(result, CaptureResult.CONTROL_AE_REGIONS);
+
+            mCollector.expectMeteringRegionsAreSimilar(
+                    "AE regions in result and request should be similar",
+                    aeRegions,
+                    resultAeRegions,
+                    METERING_REGION_ERROR_PERCENT_DELTA);
+        }
+
+        /**
+         * Step 4: take a picture when all 3A are in good state.
+         */
+        resultListener = new SimpleCaptureCallback();
+        CaptureRequest request = stillRequest.build();
+        mSession.capture(request, resultListener, mHandler);
+        // Validate the next result immediately for region and mode.
+        result = resultListener.getCaptureResultForRequest(request, WAIT_FOR_RESULT_TIMEOUT_MS);
+        mCollector.expectEquals("AF mode in result and request should be same",
+                stillRequest.get(CaptureRequest.CONTROL_AF_MODE),
+                result.get(CaptureResult.CONTROL_AF_MODE));
+        if (canSetAfRegion) {
+            MeteringRectangle[] resultAfRegions =
+                    getValueNotNull(result, CaptureResult.CONTROL_AF_REGIONS);
+            mCollector.expectMeteringRegionsAreSimilar(
+                    "AF regions in result and request should be similar",
+                    afRegions,
+                    resultAfRegions,
+                    METERING_REGION_ERROR_PERCENT_DELTA);
+        }
+
+        if (hasFocuser) {
+            // Unlock auto focus.
+            focuser.cancelAutoFocus();
+        }
+
+        // validate image
+        Image image = imageListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
+        validateJpegCapture(image, maxStillSz);
+
+        stopPreview();
+    }
+
+    /**
+     * Test touch region for focus by camera.
+     */
+    private void touchForFocusTestByCamera() throws Exception {
+        SimpleCaptureCallback listener = new SimpleCaptureCallback();
+        CaptureRequest.Builder requestBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        Size maxPreviewSz = mOrderedPreviewSizes.get(0);
+        startPreview(requestBuilder, maxPreviewSz, listener);
+
+        SimpleAutoFocusListener afListener = new SimpleAutoFocusListener();
+        Camera2Focuser focuser = new Camera2Focuser(mCamera, mSession, mPreviewSurface, afListener,
+                mStaticInfo.getCharacteristics(), mHandler);
+        ArrayList<MeteringRectangle[]> testAfRegions = get3ARegionTestCasesForCamera();
+
+        for (MeteringRectangle[] afRegions : testAfRegions) {
+            focuser.touchForAutoFocus(afRegions);
+            afListener.waitForAutoFocusDone(WAIT_FOR_FOCUS_DONE_TIMEOUT_MS);
+            focuser.cancelAutoFocus();
+        }
+    }
+
+    private void previewStillCombinationTestByCamera() throws Exception {
+        SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
+        SimpleImageReaderListener imageListener = new SimpleImageReaderListener();
+
+        for (Size stillSz : mOrderedStillSizes)
+            for (Size previewSz : mOrderedPreviewSizes) {
+                if (VERBOSE) {
+                    Log.v(TAG, "Testing JPEG capture size " + stillSz.toString()
+                            + " with preview size " + previewSz.toString() + " for camera "
+                            + mCamera.getId());
+                }
+                CaptureRequest.Builder previewRequest =
+                        mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+                CaptureRequest.Builder stillRequest =
+                        mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
+                prepareStillCaptureAndStartPreview(previewRequest, stillRequest, previewSz,
+                        stillSz, resultListener, imageListener);
+                mSession.capture(stillRequest.build(), resultListener, mHandler);
+                Image image = imageListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
+                validateJpegCapture(image, stillSz);
+                // stopPreview must be called here to make sure next time a preview stream
+                // is created with new size.
+                stopPreview();
+            }
+    }
+
+    /**
+     * Basic raw capture test for each camera.
+     */
+    private void rawCaptureTestByCamera() throws Exception {
+        Size maxPreviewSz = mOrderedPreviewSizes.get(0);
+        Size[] rawSizes = mStaticInfo.getRawOutputSizesChecked();
+
+        assertTrue("No capture sizes available for RAW format!",
+                rawSizes.length != 0);
+        Rect activeArray = mStaticInfo.getActiveArraySizeChecked();
+        Size size = new Size(activeArray.width(), activeArray.height());
+        assertTrue("Missing ActiveArraySize", activeArray.width() > 0 &&
+                activeArray.height() > 0);
+        assertArrayContains("Available sizes for RAW format must include ActiveArraySize",
+                rawSizes, size);
+
+        // Prepare raw capture and start preview.
+        CaptureRequest.Builder previewBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        CaptureRequest.Builder rawBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
+        SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
+        SimpleImageReaderListener imageListener = new SimpleImageReaderListener();
+        prepareRawCaptureAndStartPreview(previewBuilder, rawBuilder, maxPreviewSz, size,
+                resultListener, imageListener);
+
+        if (VERBOSE) {
+            Log.v(TAG, "Testing Raw capture with size " + size.toString()
+                    + ", preview size " + maxPreviewSz);
+        }
+
+        CaptureRequest rawRequest = rawBuilder.build();
+        mSession.capture(rawRequest, resultListener, mHandler);
+
+        Image image = imageListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
+        validateRaw16Image(image, size);
+        if (DEBUG) {
+            byte[] rawBuffer = getDataFromImage(image);
+            String rawFileName = DEBUG_FILE_NAME_BASE + "/test" + "_" + size.toString() + "_cam" +
+                    mCamera.getId() + ".raw16";
+            Log.d(TAG, "Dump raw file into " + rawFileName);
+            dumpFile(rawFileName, rawBuffer);
+        }
+
+        stopPreview();
+    }
+
+    private void fullRawCaptureTestByCamera() throws Exception {
+        Size maxPreviewSz = mOrderedPreviewSizes.get(0);
+        Size maxStillSz = mOrderedStillSizes.get(0);
+        Size[] rawSizes = mStaticInfo.getRawOutputSizesChecked();
+
+        SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
+        SimpleImageReaderListener jpegListener = new SimpleImageReaderListener();
+        SimpleImageReaderListener rawListener = new SimpleImageReaderListener();
+
+        assertTrue("No capture sizes available for RAW format!",
+                rawSizes.length != 0);
+        Rect activeArray = mStaticInfo.getActiveArraySizeChecked();
+        Size size = new Size(activeArray.width(), activeArray.height());
+        assertTrue("Missing ActiveArraySize", activeArray.width() > 0 &&
+                activeArray.height() > 0);
+        assertArrayContains("Available sizes for RAW format must include ActiveArraySize",
+                rawSizes, size);
+
+        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);
+
+        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);
+            updatePreviewSurface(maxPreviewSz);
+
+            // 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);
+            mSessionListener = new BlockingSessionCallback();
+            mSession = configureCameraSession(mCamera, outputSurfaces,
+                    mSessionListener, mHandler);
+
+            // Configure the requests.
+            previewBuilder.addTarget(mPreviewSurface);
+            multiBuilder.addTarget(mPreviewSurface);
+            multiBuilder.addTarget(rawReader.getSurface());
+            multiBuilder.addTarget(jpegReader.getSurface());
+
+            // Start preview.
+            mSession.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();
+
+            mSession.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);
+            verifyRawCaptureResult(multiRequest, result);
+
+
+            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+            try (DngCreator dngCreator = new DngCreator(mStaticInfo.getCharacteristics(), result)) {
+                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 {
+            CameraTestUtils.closeImageReader(rawReader);
+            CameraTestUtils.closeImageReader(jpegReader);
+            rawReader = null;
+            jpegReader = null;
+        }
+    }
+
+    /**
+     * Validate that raw {@link CaptureResult}.
+     *
+     * @param rawRequest a {@link CaptureRequest} use to capture a RAW16 image.
+     * @param rawResult the {@link CaptureResult} corresponding to the given request.
+     */
+    private void verifyRawCaptureResult(CaptureRequest rawRequest, CaptureResult rawResult) {
+        assertNotNull(rawRequest);
+        assertNotNull(rawResult);
+
+        Rational[] empty = new Rational[] { Rational.ZERO, Rational.ZERO, Rational.ZERO};
+        Rational[] neutralColorPoint = mCollector.expectKeyValueNotNull("NeutralColorPoint",
+                rawResult, CaptureResult.SENSOR_NEUTRAL_COLOR_POINT);
+        if (neutralColorPoint != null) {
+            mCollector.expectEquals("NeutralColorPoint length", empty.length,
+                    neutralColorPoint.length);
+            mCollector.expectNotEquals("NeutralColorPoint cannot be all zeroes, ", empty,
+                    neutralColorPoint);
+            mCollector.expectValuesGreaterOrEqual("NeutralColorPoint", neutralColorPoint,
+                    Rational.ZERO);
+        }
+
+        mCollector.expectKeyValueGreaterOrEqual(rawResult, CaptureResult.SENSOR_GREEN_SPLIT, 0.0f);
+
+        Pair<Double, Double>[] noiseProfile = mCollector.expectKeyValueNotNull("NoiseProfile",
+                rawResult, CaptureResult.SENSOR_NOISE_PROFILE);
+        if (noiseProfile != null) {
+            mCollector.expectEquals("NoiseProfile length", noiseProfile.length,
+                /*Num CFA channels*/4);
+            for (Pair<Double, Double> p : noiseProfile) {
+                mCollector.expectTrue("NoiseProfile coefficients " + p +
+                        " must have: S > 0, O >= 0", p.first > 0 && p.second >= 0);
+            }
+        }
+
+        Integer hotPixelMode = mCollector.expectKeyValueNotNull("HotPixelMode", rawResult,
+                CaptureResult.HOT_PIXEL_MODE);
+        Boolean hotPixelMapMode = mCollector.expectKeyValueNotNull("HotPixelMapMode", rawResult,
+                CaptureResult.STATISTICS_HOT_PIXEL_MAP_MODE);
+        Point[] hotPixelMap = rawResult.get(CaptureResult.STATISTICS_HOT_PIXEL_MAP);
+
+        Size pixelArraySize = mStaticInfo.getPixelArraySizeChecked();
+        boolean[] availableHotPixelMapModes = mStaticInfo.getValueFromKeyNonNull(
+                        CameraCharacteristics.STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES);
+
+        if (hotPixelMode != null) {
+            Integer requestMode = mCollector.expectKeyValueNotNull(rawRequest,
+                    CaptureRequest.HOT_PIXEL_MODE);
+            if (requestMode != null) {
+                mCollector.expectKeyValueEquals(rawResult, CaptureResult.HOT_PIXEL_MODE,
+                        requestMode);
+            }
+        }
+
+        if (hotPixelMapMode != null) {
+            Boolean requestMapMode = mCollector.expectKeyValueNotNull(rawRequest,
+                    CaptureRequest.STATISTICS_HOT_PIXEL_MAP_MODE);
+            if (requestMapMode != null) {
+                mCollector.expectKeyValueEquals(rawResult,
+                        CaptureResult.STATISTICS_HOT_PIXEL_MAP_MODE, requestMapMode);
+            }
+
+            if (!hotPixelMapMode) {
+                mCollector.expectTrue("HotPixelMap must be empty", hotPixelMap == null ||
+                        hotPixelMap.length == 0);
+            } else {
+                mCollector.expectTrue("HotPixelMap must not be empty", hotPixelMap != null);
+                mCollector.expectNotNull("AvailableHotPixelMapModes must not be null",
+                        availableHotPixelMapModes);
+                if (availableHotPixelMapModes != null) {
+                    mCollector.expectContains("HotPixelMapMode", availableHotPixelMapModes, true);
+                }
+
+                int height = pixelArraySize.getHeight();
+                int width = pixelArraySize.getWidth();
+                for (Point p : hotPixelMap) {
+                    mCollector.expectTrue("Hotpixel " + p + " must be in pixelArray " +
+                            pixelArraySize, p.x >= 0 && p.x < width && p.y >= 0 && p.y < height);
+                }
+            }
+        }
+        // TODO: profileHueSatMap, and profileToneCurve aren't supported yet.
+
+    }
+
+    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>
+     * TODO: Differentiate full and limited device, some of the checks rely on
+     * per frame control and synchronization, most of them don't.
+     * </p>
+     */
+    private void jpegExifTestByCamera() throws Exception {
+        Size maxPreviewSz = mOrderedPreviewSizes.get(0);
+        Size maxStillSz = mOrderedStillSizes.get(0);
+        if (VERBOSE) {
+            Log.v(TAG, "Testing JPEG exif with jpeg size " + maxStillSz.toString()
+                    + ", preview size " + maxPreviewSz);
+        }
+
+        // prepare capture and start preview.
+        CaptureRequest.Builder previewBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        CaptureRequest.Builder stillBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
+        SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
+        SimpleImageReaderListener imageListener = new SimpleImageReaderListener();
+        prepareStillCaptureAndStartPreview(previewBuilder, stillBuilder, maxPreviewSz, maxStillSz,
+                resultListener, imageListener);
+
+        // Set the jpeg keys, then issue a capture
+        Size[] thumbnailSizes = mStaticInfo.getAvailableThumbnailSizesChecked();
+        Size maxThumbnailSize = thumbnailSizes[thumbnailSizes.length - 1];
+        Size[] testThumbnailSizes = new Size[EXIF_TEST_DATA.length];
+        Arrays.fill(testThumbnailSizes, maxThumbnailSize);
+        // Make sure thumbnail size (0, 0) is covered.
+        testThumbnailSizes[0] = new Size(0, 0);
+
+        for (int i = 0; i < EXIF_TEST_DATA.length; i++) {
+            /**
+             * Capture multiple shots.
+             *
+             * Verify that:
+             * - Capture request get values are same as were set.
+             * - capture result's exif data is the same as was set by
+             *   the capture request.
+             * - new tags in the result set by the camera service are
+             *   present and semantically correct.
+             */
+            stillBuilder.set(CaptureRequest.JPEG_THUMBNAIL_SIZE, testThumbnailSizes[i]);
+            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,
+                    EXIF_TEST_DATA[i].thumbnailQuality);
+
+            // Validate request set and get.
+            mCollector.expectEquals("JPEG thumbnail size request set and get should match",
+                    testThumbnailSizes[i],
+                    stillBuilder.get(CaptureRequest.JPEG_THUMBNAIL_SIZE));
+            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));
+            mCollector.expectEquals("JPEG quality request set and get should match",
+                    EXIF_TEST_DATA[i].jpegQuality, stillBuilder.get(CaptureRequest.JPEG_QUALITY));
+            mCollector.expectEquals("JPEG thumbnail quality request set and get should match",
+                    EXIF_TEST_DATA[i].thumbnailQuality,
+                    stillBuilder.get(CaptureRequest.JPEG_THUMBNAIL_QUALITY));
+
+            // Capture a jpeg image.
+            CaptureRequest request = stillBuilder.build();
+            mSession.capture(request, resultListener, mHandler);
+            CaptureResult stillResult =
+                    resultListener.getCaptureResultForRequest(request, NUM_RESULTS_WAIT_TIMEOUT);
+            Image image = imageListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
+            basicValidateJpegImage(image, maxStillSz);
+
+            byte[] jpegBuffer = getDataFromImage(image);
+            // Have to dump into a file to be able to use ExifInterface
+            String jpegFileName =
+                    DEBUG_FILE_NAME_BASE + "/Camera_" + mCamera.getId() + "_test.jpeg";
+            dumpFile(jpegFileName, jpegBuffer);
+            ExifInterface exif = new ExifInterface(jpegFileName);
+
+            if (testThumbnailSizes[i].equals(new Size(0,0))) {
+                mCollector.expectTrue(
+                        "Jpeg shouldn't have thumbnail when thumbnail size is (0, 0)",
+                        !exif.hasThumbnail());
+            } else {
+                mCollector.expectTrue(
+                        "Jpeg must have thumbnail for thumbnail size " + testThumbnailSizes[i],
+                        exif.hasThumbnail());
+            }
+
+            // Validate capture result vs. request
+            mCollector.expectEquals("JPEG thumbnail size result and request should match",
+                    testThumbnailSizes[i],
+                    stillResult.get(CaptureResult.JPEG_THUMBNAIL_SIZE));
+            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("JPEG orientation result and request should match",
+                    EXIF_TEST_DATA[i].jpegOrientation,
+                    stillResult.get(CaptureResult.JPEG_ORIENTATION));
+            mCollector.expectEquals("JPEG quality result and request should match",
+                    EXIF_TEST_DATA[i].jpegQuality, stillResult.get(CaptureResult.JPEG_QUALITY));
+            mCollector.expectEquals("JPEG thumbnail quality result and request should match",
+                    EXIF_TEST_DATA[i].thumbnailQuality,
+                    stillResult.get(CaptureResult.JPEG_THUMBNAIL_QUALITY));
+
+            // Validate other exif tags for all non-legacy devices
+            if (!mStaticInfo.isHardwareLevelLegacy()) {
+                jpegTestExifExtraTags(exif, maxStillSz, stillResult);
+            }
+        }
+    }
+
+    private void jpegTestExifExtraTags(ExifInterface exif, Size jpegSize, CaptureResult result)
+            throws ParseException {
+        /**
+         * TAG_IMAGE_WIDTH and TAG_IMAGE_LENGTH and TAG_ORIENTATION.
+         * Orientation and exif width/height need to be tested carefully, two cases:
+         *
+         * 1. Device rotate the image buffer physically, then exif width/height may not match
+         * the requested still capture size, we need swap them to check.
+         *
+         * 2. Device use the exif tag to record the image orientation, it doesn't rotate
+         * the jpeg image buffer itself. In this case, the exif width/height should always match
+         * the requested still capture size, and the exif orientation should always match the
+         * requested orientation.
+         *
+         */
+        int exifWidth = exif.getAttributeInt(ExifInterface.TAG_IMAGE_WIDTH, /*defaultValue*/0);
+        int exifHeight = exif.getAttributeInt(ExifInterface.TAG_IMAGE_LENGTH, /*defaultValue*/0);
+        Size exifSize = new Size(exifWidth, exifHeight);
+        // Orientation could be missing, which is ok, default to 0.
+        int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
+                /*defaultValue*/-1);
+        // Get requested orientation from result, because they should be same.
+        if (mCollector.expectKeyValueNotNull(result, CaptureResult.JPEG_ORIENTATION) != null) {
+            int requestedOrientation = result.get(CaptureResult.JPEG_ORIENTATION);
+            final int ORIENTATION_MIN = ExifInterface.ORIENTATION_UNDEFINED;
+            final int ORIENTATION_MAX = ExifInterface.ORIENTATION_ROTATE_270;
+            boolean orientationValid = mCollector.expectTrue(String.format(
+                    "Exif orientation must be in range of [%d, %d]",
+                    ORIENTATION_MIN, ORIENTATION_MAX),
+                    exifOrientation >= ORIENTATION_MIN && exifOrientation <= ORIENTATION_MAX);
+            if (orientationValid) {
+                /**
+                 * Device captured image doesn't respect the requested orientation,
+                 * which means it rotates the image buffer physically. Then we
+                 * should swap the exif width/height accordingly to compare.
+                 */
+                boolean deviceRotatedImage = exifOrientation == ExifInterface.ORIENTATION_UNDEFINED;
+
+                if (deviceRotatedImage) {
+                    // Case 1.
+                    boolean needSwap = (requestedOrientation % 180 == 90);
+                    if (needSwap) {
+                        exifSize = new Size(exifHeight, exifWidth);
+                    }
+                } else {
+                    // Case 2.
+                    mCollector.expectEquals("Exif orientaiton should match requested orientation",
+                            requestedOrientation, getExifOrientationInDegress(exifOrientation));
+                }
+            }
+        }
+
+        /**
+         * Ideally, need check exifSize == jpegSize == actual buffer size. But
+         * jpegSize == jpeg decode bounds size(from jpeg jpeg frame
+         * header, not exif) was validated in ImageReaderTest, no need to
+         * validate again here.
+         */
+        mCollector.expectEquals("Exif size should match jpeg capture size", jpegSize, exifSize);
+
+        // TAG_DATETIME, it should be local time
+        long currentTimeInMs = System.currentTimeMillis();
+        long currentTimeInSecond = currentTimeInMs / 1000;
+        Date date = new Date(currentTimeInMs);
+        String localDatetime = new SimpleDateFormat("yyyy:MM:dd HH:").format(date);
+        String dateTime = exif.getAttribute(ExifInterface.TAG_DATETIME);
+        if (mCollector.expectTrue("Exif TAG_DATETIME shouldn't be null", dateTime != null)) {
+            mCollector.expectTrue("Exif TAG_DATETIME is wrong",
+                    dateTime.length() == EXIF_DATETIME_LENGTH);
+            long exifTimeInSecond =
+                    new SimpleDateFormat("yyyy:MM:dd HH:mm:ss").parse(dateTime).getTime() / 1000;
+            long delta = currentTimeInSecond - exifTimeInSecond;
+            mCollector.expectTrue("Capture time deviates too much from the current time",
+                    Math.abs(delta) < EXIF_DATETIME_ERROR_MARGIN_SEC);
+            // It should be local time.
+            mCollector.expectTrue("Exif date time should be local time",
+                    dateTime.startsWith(localDatetime));
+        }
+
+        // TAG_FOCAL_LENGTH.
+        float[] focalLengths = mStaticInfo.getAvailableFocalLengthsChecked();
+        float exifFocalLength = (float)exif.getAttributeDouble(ExifInterface.TAG_FOCAL_LENGTH, -1);
+        mCollector.expectEquals("Focal length should match",
+                getClosestValueInArray(focalLengths, exifFocalLength),
+                exifFocalLength, EXIF_FOCAL_LENGTH_ERROR_MARGIN);
+        // More checks for focal length.
+        mCollector.expectEquals("Exif focal length should match capture result",
+                validateFocalLength(result), exifFocalLength);
+
+        // TAG_EXPOSURE_TIME
+        // ExifInterface API gives exposure time value in the form of float instead of rational
+        String exposureTime = exif.getAttribute(ExifInterface.TAG_EXPOSURE_TIME);
+        mCollector.expectNotNull("Exif TAG_EXPOSURE_TIME shouldn't be null", exposureTime);
+        if (mStaticInfo.areKeysAvailable(CaptureResult.SENSOR_EXPOSURE_TIME)) {
+            if (exposureTime != null) {
+                double exposureTimeValue = Double.parseDouble(exposureTime);
+                long expTimeResult = result.get(CaptureResult.SENSOR_EXPOSURE_TIME);
+                double expected = expTimeResult / 1e9;
+                double tolerance = expected * EXIF_EXPOSURE_TIME_ERROR_MARGIN_RATIO;
+                tolerance = Math.max(tolerance, EXIF_EXPOSURE_TIME_MIN_ERROR_MARGIN_SEC);
+                mCollector.expectEquals("Exif exposure time doesn't match", expected,
+                        exposureTimeValue, tolerance);
+            }
+        }
+
+        // TAG_APERTURE
+        // ExifInterface API gives aperture value in the form of float instead of rational
+        String exifAperture = exif.getAttribute(ExifInterface.TAG_APERTURE);
+        mCollector.expectNotNull("Exif TAG_APERTURE shouldn't be null", exifAperture);
+        if (mStaticInfo.areKeysAvailable(CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES)) {
+            float[] apertures = mStaticInfo.getAvailableAperturesChecked();
+            if (exifAperture != null) {
+                float apertureValue = Float.parseFloat(exifAperture);
+                mCollector.expectEquals("Aperture value should match",
+                        getClosestValueInArray(apertures, apertureValue),
+                        apertureValue, EXIF_APERTURE_ERROR_MARGIN);
+                // More checks for aperture.
+                mCollector.expectEquals("Exif aperture length should match capture result",
+                        validateAperture(result), apertureValue);
+            }
+        }
+
+        /**
+         * TAG_FLASH. TODO: For full devices, can check a lot more info
+         * (http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html#Flash)
+         */
+        String flash = exif.getAttribute(ExifInterface.TAG_FLASH);
+        mCollector.expectNotNull("Exif TAG_FLASH shouldn't be null", flash);
+
+        /**
+         * TAG_WHITE_BALANCE. TODO: For full devices, with the DNG tags, we
+         * should be able to cross-check android.sensor.referenceIlluminant.
+         */
+        String whiteBalance = exif.getAttribute(ExifInterface.TAG_WHITE_BALANCE);
+        mCollector.expectNotNull("Exif TAG_WHITE_BALANCE shouldn't be null", whiteBalance);
+
+        // TAG_MAKE
+        String make = exif.getAttribute(ExifInterface.TAG_MAKE);
+        mCollector.expectEquals("Exif TAG_MAKE is incorrect", Build.MANUFACTURER, make);
+
+        // TAG_MODEL
+        String model = exif.getAttribute(ExifInterface.TAG_MODEL);
+        mCollector.expectEquals("Exif TAG_MODEL is incorrect", Build.MODEL, model);
+
+
+        // TAG_ISO
+        int iso = exif.getAttributeInt(ExifInterface.TAG_ISO, /*defaultValue*/-1);
+        if (mStaticInfo.areKeysAvailable(CaptureResult.SENSOR_SENSITIVITY)) {
+            int expectedIso = result.get(CaptureResult.SENSOR_SENSITIVITY);
+            mCollector.expectEquals("Exif TAG_ISO is incorrect", expectedIso, iso);
+        }
+
+        // TAG_DATETIME_DIGITIZED (a.k.a Create time for digital cameras).
+        String digitizedTime = exif.getAttribute(TAG_DATETIME_DIGITIZED);
+        mCollector.expectNotNull("Exif TAG_DATETIME_DIGITIZED shouldn't be null", digitizedTime);
+        if (digitizedTime != null) {
+            String expectedDateTime = exif.getAttribute(ExifInterface.TAG_DATETIME);
+            mCollector.expectNotNull("Exif TAG_DATETIME shouldn't be null", expectedDateTime);
+            if (expectedDateTime != null) {
+                mCollector.expectEquals("dataTime should match digitizedTime",
+                        expectedDateTime, digitizedTime);
+            }
+        }
+
+        /**
+         * TAG_SUBSEC_TIME. Since the sub second tag strings are truncated to at
+         * most 9 digits in ExifInterface implementation, use getAttributeInt to
+         * sanitize it. When the default value -1 is returned, it means that
+         * this exif tag either doesn't exist or is a non-numerical invalid
+         * string. Same rule applies to the rest of sub second tags.
+         */
+        int subSecTime = exif.getAttributeInt(TAG_SUBSEC_TIME, /*defaultValue*/-1);
+        mCollector.expectTrue("Exif TAG_SUBSEC_TIME value is null or invalid!", subSecTime > 0);
+
+        // TAG_SUBSEC_TIME_ORIG
+        int subSecTimeOrig = exif.getAttributeInt(TAG_SUBSEC_TIME_ORIG, /*defaultValue*/-1);
+        mCollector.expectTrue("Exif TAG_SUBSEC_TIME_ORIG value is null or invalid!",
+                subSecTimeOrig > 0);
+
+        // TAG_SUBSEC_TIME_DIG
+        int subSecTimeDig = exif.getAttributeInt(TAG_SUBSEC_TIME_DIG, /*defaultValue*/-1);
+        mCollector.expectTrue(
+                "Exif TAG_SUBSEC_TIME_DIG value is null or invalid!", subSecTimeDig > 0);
+    }
+
+    private int getExifOrientationInDegress(int exifOrientation) {
+        switch (exifOrientation) {
+            case ExifInterface.ORIENTATION_NORMAL:
+                return 0;
+            case ExifInterface.ORIENTATION_ROTATE_90:
+                return 90;
+            case ExifInterface.ORIENTATION_ROTATE_180:
+                return 180;
+            case ExifInterface.ORIENTATION_ROTATE_270:
+                return 270;
+            default:
+                mCollector.addMessage("It is impossible to get non 0, 90, 180, 270 degress exif" +
+                        "info based on the request orientation range");
+                return 0;
+        }
+    }
+    /**
+     * Immutable class wrapping the exif test data.
+     */
+    private static class ExifTestData {
+        public final Location gpsLocation;
+        public final int jpegOrientation;
+        public final byte jpegQuality;
+        public final byte thumbnailQuality;
+
+        public ExifTestData(Location location, int orientation,
+                byte jpgQuality, byte thumbQuality) {
+            gpsLocation = location;
+            jpegOrientation = orientation;
+            jpegQuality = jpgQuality;
+            thumbnailQuality = thumbQuality;
+        }
+    }
+
+    private void aeCompensationTestByCamera() throws Exception {
+        Range<Integer> compensationRange = mStaticInfo.getAeCompensationRangeChecked();
+        Rational step = mStaticInfo.getAeCompensationStepChecked();
+        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);
+        SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
+        SimpleImageReaderListener imageListener = new SimpleImageReaderListener();
+        CaptureRequest.Builder previewRequest =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        CaptureRequest.Builder stillRequest =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
+        stillRequest.set(CaptureRequest.CONTROL_AE_LOCK, true);
+
+        // The following variables should only be read under the MANUAL_SENSOR capability guard:
+        long minExposureValue = -1;
+        long maxExposureTimeUs = -1;
+        long maxExposureValuePreview = -1;
+        long maxExposureValueStill = -1;
+        if (mStaticInfo.isCapabilitySupported(
+                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
+            // Minimum exposure settings is mostly static while maximum exposure setting depends on
+            // frame rate range which in term depends on capture request.
+            minExposureValue = mStaticInfo.getSensitivityMinimumOrDefault() *
+                    mStaticInfo.getExposureMinimumOrDefault() / 1000;
+            long maxSensitivity = mStaticInfo.getSensitivityMaximumOrDefault();
+            maxExposureTimeUs = mStaticInfo.getExposureMaximumOrDefault() / 1000;
+            maxExposureValuePreview = getMaxExposureValue(previewRequest, maxExposureTimeUs,
+                    maxSensitivity);
+            maxExposureValueStill = getMaxExposureValue(stillRequest, maxExposureTimeUs,
+                    maxSensitivity);
+        }
+
+        // Set the max number of images to be same as the burst count, as the verification
+        // could be much slower than producing rate, and we don't want to starve producer.
+        prepareStillCaptureAndStartPreview(previewRequest, stillRequest, maxPreviewSz,
+                maxStillSz, resultListener, numSteps, imageListener);
+
+        for (int i = 0; i <= numSteps; i++) {
+            int exposureCompensation = i * stepsPerEv + compensationRange.getLower();
+            double expectedRatio = Math.pow(2.0, exposureCompensation / stepsPerEv);
+
+            // Wait for AE to be stabilized before capture: CONVERGED or FLASH_REQUIRED.
+            waitForAeStable(resultListener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+            CaptureResult result = resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+
+            long normalExposureValue = -1;
+            if (mStaticInfo.isCapabilitySupported(
+                    CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
+                // get and check if current exposure value is valid
+                normalExposureValue = getExposureValue(result);
+                mCollector.expectInRange("Exposure setting out of bound", normalExposureValue,
+                        minExposureValue, maxExposureValuePreview);
+
+                // Only run the test if expectedExposureValue is within valid range
+                long expectedExposureValue = (long) (normalExposureValue * expectedRatio);
+                if (expectedExposureValue < minExposureValue ||
+                    expectedExposureValue > maxExposureValueStill) {
+                    continue;
+                }
+            }
+
+            // Now issue exposure compensation and wait for AE locked. AE could take a few
+            // frames to go back to locked state
+            previewRequest.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION,
+                    exposureCompensation);
+            previewRequest.set(CaptureRequest.CONTROL_AE_LOCK, true);
+            mSession.setRepeatingRequest(previewRequest.build(), resultListener, mHandler);
+            waitForAeLocked(resultListener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+
+            // Issue still capture
+            if (VERBOSE) {
+                Log.v(TAG, "Verifying capture result for ae compensation value "
+                        + exposureCompensation);
+            }
+
+            stillRequest.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, exposureCompensation);
+            CaptureRequest request = stillRequest.build();
+            mSession.capture(request, resultListener, mHandler);
+
+            result = resultListener.getCaptureResultForRequest(request, WAIT_FOR_RESULT_TIMEOUT_MS);
+
+            if (mStaticInfo.isCapabilitySupported(
+                    CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
+                // Verify the exposure value compensates as requested
+                long compensatedExposureValue = getExposureValue(result);
+                mCollector.expectInRange("Exposure setting out of bound", compensatedExposureValue,
+                        minExposureValue, maxExposureValueStill);
+                double observedRatio = (double) compensatedExposureValue / normalExposureValue;
+                double error = observedRatio / expectedRatio;
+                mCollector.expectInRange(String.format(
+                        "Exposure compensation ratio exceeds error tolerence:"
+                        + " expected(%f) observed(%f) ", expectedRatio, observedRatio),
+                        error,
+                        1.0 - AE_COMPENSATION_ERROR_TOLERANCE,
+                        1.0 + AE_COMPENSATION_ERROR_TOLERANCE);
+            }
+
+            mCollector.expectEquals("Exposure compensation result should match requested value.",
+                    exposureCompensation,
+                    result.get(CaptureResult.CONTROL_AE_EXPOSURE_COMPENSATION));
+            mCollector.expectTrue("Exposure lock should be set",
+                    result.get(CaptureResult.CONTROL_AE_LOCK));
+
+            Image image = imageListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
+            validateJpegCapture(image, maxStillSz);
+            image.close();
+
+            // Recover AE compensation and lock
+            previewRequest.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 0);
+            previewRequest.set(CaptureRequest.CONTROL_AE_LOCK, false);
+            mSession.setRepeatingRequest(previewRequest.build(), resultListener, mHandler);
+        }
+    }
+
+    private long getExposureValue(CaptureResult result) throws Exception {
+        int expTimeUs = (int) (getValueNotNull(result, CaptureResult.SENSOR_EXPOSURE_TIME) / 1000);
+        int sensitivity = getValueNotNull(result, CaptureResult.SENSOR_SENSITIVITY);
+        return expTimeUs * sensitivity;
+    }
+
+    private long getMaxExposureValue(CaptureRequest.Builder request, long maxExposureTimeUs,
+                long maxSensitivity)  throws Exception {
+        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;
+    }
+
+
+    //----------------------------------------------------------------
+    //---------Below are common functions for all tests.--------------
+    //----------------------------------------------------------------
+
+    /**
+     * Simple validation of JPEG image size and format.
+     * <p>
+     * Only validate the image object sanity. It is fast, but doesn't actually
+     * check the buffer data. Assert is used here as it make no sense to
+     * continue the test if the jpeg image captured has some serious failures.
+     * </p>
+     *
+     * @param image The captured jpeg image
+     * @param expectedSize Expected capture jpeg size
+     */
+    private static void basicValidateJpegImage(Image image, Size expectedSize) {
+        Size imageSz = new Size(image.getWidth(), image.getHeight());
+        assertTrue(
+                String.format("Image size doesn't match (expected %s, actual %s) ",
+                        expectedSize.toString(), imageSz.toString()), expectedSize.equals(imageSz));
+        assertEquals("Image format should be JPEG", ImageFormat.JPEG, image.getFormat());
+        assertNotNull("Image plane shouldn't be null", image.getPlanes());
+        assertEquals("Image plane number should be 1", 1, image.getPlanes().length);
+
+        // Jpeg decoding validate was done in ImageReaderTest, no need to duplicate the test here.
+    }
+
+    /**
+     * Validate standard raw (RAW16) capture image.
+     *
+     * @param image The raw16 format image captured
+     * @param rawSize The expected raw size
+     */
+    private static void validateRaw16Image(Image image, Size rawSize) {
+        CameraTestUtils.validateImage(image, rawSize.getWidth(), rawSize.getHeight(),
+                ImageFormat.RAW_SENSOR, /*filePath*/null);
+    }
+
+    /**
+     * Validate JPEG capture image object sanity and test.
+     * <p>
+     * In addition to image object sanity, this function also does the decoding
+     * test, which is slower.
+     * </p>
+     *
+     * @param image The JPEG image to be verified.
+     * @param jpegSize The JPEG capture size to be verified against.
+     */
+    private static void validateJpegCapture(Image image, Size jpegSize) {
+        CameraTestUtils.validateImage(image, jpegSize.getWidth(), jpegSize.getHeight(),
+                ImageFormat.JPEG, /*filePath*/null);
+    }
+
+    private static float getClosestValueInArray(float[] values, float target) {
+        int minIdx = 0;
+        float minDistance = Math.abs(values[0] - target);
+        for(int i = 0; i < values.length; i++) {
+            float distance = Math.abs(values[i] - target);
+            if (minDistance > distance) {
+                minDistance = distance;
+                minIdx = i;
+            }
+        }
+
+        return values[minIdx];
+    }
+
+    /**
+     * Validate and return the focal length.
+     *
+     * @param result Capture result to get the focal length
+     * @return Focal length from capture result or -1 if focal length is not available.
+     */
+    private float validateFocalLength(CaptureResult result) {
+        float[] focalLengths = mStaticInfo.getAvailableFocalLengthsChecked();
+        Float resultFocalLength = result.get(CaptureResult.LENS_FOCAL_LENGTH);
+        if (mCollector.expectTrue("Focal length is invalid",
+                resultFocalLength != null && resultFocalLength > 0)) {
+            List<Float> focalLengthList =
+                    Arrays.asList(CameraTestUtils.toObject(focalLengths));
+            mCollector.expectTrue("Focal length should be one of the available focal length",
+                    focalLengthList.contains(resultFocalLength));
+            return resultFocalLength;
+        }
+        return -1;
+    }
+
+    /**
+     * Validate and return the aperture.
+     *
+     * @param result Capture result to get the aperture
+     * @return Aperture from capture result or -1 if aperture is not available.
+     */
+    private float validateAperture(CaptureResult result) {
+        float[] apertures = mStaticInfo.getAvailableAperturesChecked();
+        Float resultAperture = result.get(CaptureResult.LENS_APERTURE);
+        if (mCollector.expectTrue("Capture result aperture is invalid",
+                resultAperture != null && resultAperture > 0)) {
+            List<Float> apertureList =
+                    Arrays.asList(CameraTestUtils.toObject(apertures));
+            mCollector.expectTrue("Aperture should be one of the available apertures",
+                    apertureList.contains(resultAperture));
+            return resultAperture;
+        }
+        return -1;
+    }
+
+    private static class SimpleAutoFocusListener implements Camera2Focuser.AutoFocusListener {
+        final ConditionVariable focusDone = new ConditionVariable();
+        @Override
+        public void onAutoFocusLocked(boolean success) {
+            focusDone.open();
+        }
+
+        public void waitForAutoFocusDone(long timeoutMs) {
+            if (focusDone.block(timeoutMs)) {
+                focusDone.close();
+            } else {
+                throw new TimeoutRuntimeException("Wait for auto focus done timed out after "
+                        + timeoutMs + "ms");
+            }
+        }
+    }
+
+    /**
+     * 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 ArrayList<MeteringRectangle[]> get3ARegionTestCasesForCamera() {
+        final int TEST_3A_REGION_NUM = 5;
+        final int DEFAULT_REGION_WEIGHT = 30;
+        final int DEFAULT_REGION_SCALE_RATIO = 8;
+        ArrayList<MeteringRectangle[]> testCases =
+                new ArrayList<MeteringRectangle[]>(TEST_3A_REGION_NUM);
+        final Rect activeArraySize = mStaticInfo.getActiveArraySizeChecked();
+        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
+        testCases.add(
+                new MeteringRectangle[] {
+                    new MeteringRectangle(
+                            centerX - regionWidth / 2,  // x
+                            centerY - regionHeight / 2, // y
+                            regionWidth,                // width
+                            regionHeight,               // height
+                            DEFAULT_REGION_WEIGHT)});
+
+        // Upper left corner
+        testCases.add(
+                new MeteringRectangle[] {
+                    new MeteringRectangle(
+                            0,                // x
+                            0,                // y
+                            regionWidth,      // width
+                            regionHeight,     // height
+                            DEFAULT_REGION_WEIGHT)});
+
+        // Upper right corner
+        testCases.add(
+                new MeteringRectangle[] {
+                    new MeteringRectangle(
+                            bottomRightX - regionWidth, // x
+                            0,                          // y
+                            regionWidth,                // width
+                            regionHeight,               // height
+                            DEFAULT_REGION_WEIGHT)});
+
+        // Bottom left corner
+        testCases.add(
+                new MeteringRectangle[] {
+                    new MeteringRectangle(
+                            0,                           // x
+                            bottomRightY - regionHeight, // y
+                            regionWidth,                 // width
+                            regionHeight,                // height
+                            DEFAULT_REGION_WEIGHT)});
+
+        // Bottom right corner
+        testCases.add(
+                new MeteringRectangle[] {
+                    new MeteringRectangle(
+                            bottomRightX - regionWidth,  // x
+                            bottomRightY - regionHeight, // y
+                            regionWidth,                 // width
+                            regionHeight,                // height
+                            DEFAULT_REGION_WEIGHT)});
+
+        if (VERBOSE) {
+            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 testCases;
+    }
+
+    private boolean isRegionsSupportedFor3A(int index) {
+        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!",
+                    mStaticInfo.hasFocuser());
+            isRegionsSupported = isRegionsSupported && mStaticInfo.hasFocuser();
+        }
+
+        return isRegionsSupported;
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java
new file mode 100644
index 0000000..b3d4cf9
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java
@@ -0,0 +1,311 @@
+/*
+ * 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.cts.CameraTestUtils.*;
+
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CameraCaptureSession.CaptureCallback;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CaptureFailure;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.TotalCaptureResult;
+import android.util.Size;
+import android.hardware.camera2.cts.CameraTestUtils.SimpleCaptureCallback;
+import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
+import android.util.Log;
+import android.util.Range;
+
+import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatcher;
+
+import static org.mockito.Mockito.*;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * CameraDevice preview test by using SurfaceView.
+ */
+public class SurfaceViewPreviewTest extends Camera2SurfaceViewTestCase {
+    private static final String TAG = "SurfaceViewPreviewTest";
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+    private static final int FRAME_TIMEOUT_MS = 1000;
+    private static final int NUM_FRAMES_VERIFIED = 30;
+    private static final int NUM_TEST_PATTERN_FRAMES_VERIFIED = 60;
+    private static final float FRAME_DURATION_ERROR_MARGIN = 0.005f; // 0.5 percent error margin.
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    /**
+     * Test all supported preview sizes for each camera device.
+     * <p>
+     * For the first  {@link #NUM_FRAMES_VERIFIED}  of capture results,
+     * the {@link CaptureCallback} callback availability and the capture timestamp
+     * (monotonically increasing) ordering are verified.
+     * </p>
+     */
+    public void testCameraPreview() throws Exception {
+        for (int i = 0; i < mCameraIds.length; i++) {
+            try {
+                Log.i(TAG, "Testing preview for Camera " + mCameraIds[i]);
+                openDevice(mCameraIds[i]);
+
+                if (mStaticInfo.isHardwareLevelLegacy()) {
+                    Log.i(TAG, "Skipping test on legacy devices");
+                    continue;
+                }
+
+                previewTestByCamera();
+            } finally {
+                closeDevice();
+            }
+        }
+    }
+
+    /**
+     * Basic test pattern mode preview.
+     * <p>
+     * Only test the test pattern preview and capture result, the image buffer
+     * is not validated.
+     * </p>
+     */
+    public void testBasicTestPatternPreview() throws Exception{
+        for (int i = 0; i < mCameraIds.length; i++) {
+            try {
+                Log.i(TAG, "Testing preview for Camera " + mCameraIds[i]);
+                openDevice(mCameraIds[i]);
+
+                previewTestPatternTestByCamera();
+            } finally {
+                closeDevice();
+            }
+        }
+    }
+
+    /**
+     * Test {@link CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE} for preview, validate the preview
+     * frame duration and exposure time.
+     */
+    public void testPreviewFpsRange() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                openDevice(id);
+
+                previewFpsRangeTestByCamera();
+            } finally {
+                closeDevice();
+            }
+        }
+    }
+
+    /**
+     * Test preview fps range for all supported ranges. The exposure time are frame duration are
+     * validated.
+     */
+    private void previewFpsRangeTestByCamera() throws Exception {
+        final int FPS_RANGE_SIZE = 2;
+        Size maxPreviewSz = mOrderedPreviewSizes.get(0);
+        Range<Integer>[] fpsRanges = mStaticInfo.getAeAvailableTargetFpsRangesChecked();
+        boolean antiBandingOffIsSupported = mStaticInfo.isAntiBandingOffModeSupported();
+        Range<Integer> fpsRange;
+        CaptureRequest.Builder requestBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
+        startPreview(requestBuilder, maxPreviewSz, resultListener);
+
+        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
+            // from antibanding algorithm.
+            if (antiBandingOffIsSupported) {
+                requestBuilder.set(CaptureRequest.CONTROL_AE_ANTIBANDING_MODE,
+                        CaptureRequest.CONTROL_AE_ANTIBANDING_MODE_OFF);
+            } else {
+                // The device doesn't implement the OFF mode, test continues. It need make sure
+                // that the antibanding algorithm doesn't interfere with the fps range control.
+                Log.i(TAG, "OFF antibanding mode is not supported, the camera device output must" +
+                        " satisfy the specified fps range regardless of its current antibanding" +
+                        " mode");
+            }
+
+            resultListener = new SimpleCaptureCallback();
+            mSession.setRepeatingRequest(requestBuilder.build(), resultListener, mHandler);
+
+            verifyPreviewTargetFpsRange(resultListener, NUM_FRAMES_VERIFIED, fpsRange,
+                    maxPreviewSz);
+        }
+
+        stopPreview();
+    }
+
+    private void verifyPreviewTargetFpsRange(SimpleCaptureCallback resultListener,
+            int numFramesVerified, Range<Integer> fpsRange, Size previewSz) {
+        CaptureResult result = resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+        List<Integer> capabilities = mStaticInfo.getAvailableCapabilitiesChecked();
+
+        if (capabilities.contains(CaptureRequest.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
+            long frameDuration = getValueNotNull(result, CaptureResult.SENSOR_FRAME_DURATION);
+            long[] frameDurationRange =
+                    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)),
+                    (long) (frameDurationRange[1] * (1 + FRAME_DURATION_ERROR_MARGIN)));
+            long expTime = getValueNotNull(result, CaptureResult.SENSOR_EXPOSURE_TIME);
+            mCollector.expectTrue(String.format("Exposure time %d must be no larger than frame"
+                    + "duration %d", expTime, frameDuration), expTime <= frameDuration);
+
+            Long minFrameDuration = mMinPreviewFrameDurationMap.get(previewSz);
+            boolean findDuration = mCollector.expectTrue("Unable to find minFrameDuration for size "
+                    + previewSz.toString(), minFrameDuration != null);
+            if (findDuration) {
+                mCollector.expectTrue("Frame duration " + frameDuration + " must be no smaller than"
+                        + " minFrameDuration " + minFrameDuration, frameDuration >= minFrameDuration);
+            }
+        } else {
+            Log.i(TAG, "verifyPreviewTargetFpsRange - MANUAL_SENSOR control is not supported," +
+                    " skipping duration and exposure time check.");
+        }
+    }
+
+    /**
+     * Test all supported preview sizes for a camera device
+     *
+     * @throws Exception
+     */
+    private void previewTestByCamera() throws Exception {
+        List<Size> previewSizes = getSupportedPreviewSizes(
+                mCamera.getId(), mCameraManager, PREVIEW_SIZE_BOUND);
+
+        for (final Size sz : previewSizes) {
+            if (VERBOSE) {
+                Log.v(TAG, "Testing camera preview size: " + sz.toString());
+            }
+
+            // TODO: vary the different settings like crop region to cover more cases.
+            CaptureRequest.Builder requestBuilder =
+                    mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+            CaptureCallback mockCaptureCallback =
+                    mock(CameraCaptureSession.CaptureCallback.class);
+
+            startPreview(requestBuilder, sz, mockCaptureCallback);
+            verifyCaptureResults(mSession, mockCaptureCallback, NUM_FRAMES_VERIFIED,
+                    NUM_FRAMES_VERIFIED * FRAME_TIMEOUT_MS);
+            stopPreview();
+        }
+    }
+
+    private void previewTestPatternTestByCamera() throws Exception {
+        Size maxPreviewSize = mOrderedPreviewSizes.get(0);
+        int[] testPatternModes = mStaticInfo.getAvailableTestPatternModesChecked();
+        CaptureRequest.Builder requestBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        CaptureCallback mockCaptureCallback;
+
+        final int[] TEST_PATTERN_DATA = {0, 0xFFFFFFFF, 0xFFFFFFFF, 0}; // G:100%, RB:0.
+        for (int mode : testPatternModes) {
+            if (VERBOSE) {
+                Log.v(TAG, "Test pattern mode: " + mode);
+            }
+            requestBuilder.set(CaptureRequest.SENSOR_TEST_PATTERN_MODE, mode);
+            if (mode == CaptureRequest.SENSOR_TEST_PATTERN_MODE_SOLID_COLOR) {
+                // Assign color pattern to SENSOR_TEST_PATTERN_MODE_DATA
+                requestBuilder.set(CaptureRequest.SENSOR_TEST_PATTERN_DATA, TEST_PATTERN_DATA);
+            }
+            mockCaptureCallback = mock(CaptureCallback.class);
+            startPreview(requestBuilder, maxPreviewSize, mockCaptureCallback);
+            verifyCaptureResults(mSession, mockCaptureCallback, NUM_TEST_PATTERN_FRAMES_VERIFIED,
+                    NUM_TEST_PATTERN_FRAMES_VERIFIED * FRAME_TIMEOUT_MS);
+        }
+
+        stopPreview();
+    }
+
+    private class IsCaptureResultValid extends ArgumentMatcher<TotalCaptureResult> {
+        @Override
+        public boolean matches(Object obj) {
+            TotalCaptureResult result = (TotalCaptureResult)obj;
+            Long timeStamp = result.get(CaptureResult.SENSOR_TIMESTAMP);
+            if (timeStamp != null && timeStamp.longValue() > 0L) {
+                return true;
+            }
+            return false;
+        }
+    }
+
+    private void verifyCaptureResults(
+            CameraCaptureSession session,
+            CaptureCallback mockListener,
+            int expectResultCount,
+            int timeOutMs) {
+        // Should receive expected number of onCaptureStarted callbacks.
+        ArgumentCaptor<Long> timestamps = ArgumentCaptor.forClass(Long.class);
+        ArgumentCaptor<Long> frameNumbers = ArgumentCaptor.forClass(Long.class);
+        verify(mockListener,
+                timeout(timeOutMs).atLeast(expectResultCount))
+                        .onCaptureStarted(
+                                eq(session),
+                                isA(CaptureRequest.class),
+                                timestamps.capture(),
+                                frameNumbers.capture());
+
+        // Validate timestamps: all timestamps should be larger than 0 and monotonically increase.
+        long timestamp = 0;
+        for (Long nextTimestamp : timestamps.getAllValues()) {
+            assertNotNull("Next timestamp is null!", nextTimestamp);
+            assertTrue("Captures are out of order", timestamp < nextTimestamp);
+            timestamp = nextTimestamp;
+        }
+
+        // Validate framenumbers: all framenumbers should be consecutive and positive
+        long frameNumber = -1;
+        for (Long nextFrameNumber : frameNumbers.getAllValues()) {
+            assertNotNull("Next frame number is null!", nextFrameNumber);
+            assertTrue("Captures are out of order",
+                    (frameNumber == -1) || (frameNumber + 1 == nextFrameNumber));
+            frameNumber = nextFrameNumber;
+        }
+
+        // Should receive expected number of capture results.
+        verify(mockListener,
+                timeout(timeOutMs).atLeast(expectResultCount))
+                        .onCaptureCompleted(
+                                eq(session),
+                                isA(CaptureRequest.class),
+                                argThat(new IsCaptureResultValid()));
+
+        // Should not receive any capture failed callbacks.
+        verify(mockListener, never())
+                        .onCaptureFailed(
+                                eq(session),
+                                isA(CaptureRequest.class),
+                                isA(CaptureFailure.class));
+    }
+
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/common.rs b/tests/tests/hardware/src/android/hardware/camera2/cts/common.rs
new file mode 100644
index 0000000..4c134b3
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/common.rs
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_CAMERA2_CTS_COMMON_RS
+#define ANDROID_HARDWARE_CAMERA2_CTS_COMMON_RS
+
+#pragma version(1)
+#pragma rs java_package_name(android.hardware.camera2.cts)
+#pragma rs_fp_relaxed
+
+typedef uchar3 yuvx_444; // interleaved YUV. (y,u,v) per pixel. use .x/.y/.z to read
+typedef uchar3 yuvf_420; // flexible YUV (4:2:0). use rsGetElementAtYuv to read.
+
+#define convert_yuvx_444 convert_uchar3
+#define convert_yuvf_420 __error_cant_output_flexible_yuv__
+
+#define rsGetElementAt_yuvx_444 rsGetElementAt_uchar3
+#define rsGetElementAt_yuvf_420 __error_cant_output_flexible_yuv__
+
+#define RS_KERNEL __attribute__((kernel))
+
+#ifndef LOG_DEBUG
+#define LOG_DEBUG 0
+#endif
+
+#if LOG_DEBUG
+#define LOGD(string, expr) rsDebug((string), (expr))
+#else
+#define LOGD(string, expr) if (0) rsDebug((string), (expr))
+#endif
+
+#endif // header guard
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/crop_yuvf_420_to_yuvx_444.rs b/tests/tests/hardware/src/android/hardware/camera2/cts/crop_yuvf_420_to_yuvx_444.rs
new file mode 100644
index 0000000..f930f58
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/crop_yuvf_420_to_yuvx_444.rs
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#include "common.rs"
+
+// Must be YUV 420 888 (flexible YUV)
+rs_allocation mInput;
+
+// Input globals
+uint32_t src_x;
+uint32_t src_y;
+
+// Crop each pixel from mInput
+yuvx_444 RS_KERNEL crop(uint32_t x, uint32_t y) {
+
+    uchar py = rsGetElementAtYuv_uchar_Y(mInput, x + src_x, y + src_y);
+    uchar pu = rsGetElementAtYuv_uchar_U(mInput, x + src_x, y + src_y);
+    uchar pv = rsGetElementAtYuv_uchar_V(mInput, x + src_x, y + src_y);
+
+    yuvx_444 yuv = { py, pu, pv };
+
+    return yuv;
+}
+
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/AssertHelpers.java b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/AssertHelpers.java
new file mode 100644
index 0000000..a2e6a91
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/AssertHelpers.java
@@ -0,0 +1,233 @@
+/*
+ * 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.helpers;
+
+import static junit.framework.Assert.*;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Helper set of methods to add extra useful assert functionality missing in junit.
+ */
+public class AssertHelpers {
+
+    private static final int MAX_FORMAT_STRING = 50;
+
+    /**
+     * Assert that at least one of the elements in data is non-zero.
+     *
+     * <p>An empty or a null array always fails.</p>
+     */
+    public static void assertArrayNotAllZeroes(String message, byte[] data) {
+        int size = data.length;
+
+        int i = 0;
+        for (i = 0; i < size; ++i) {
+            if (data[i] != 0) {
+                break;
+            }
+        }
+
+        assertTrue(message, i < size);
+    }
+
+    /**
+     * Assert that every element in left is less than or equals to the corresponding element in
+     * right.
+     *
+     * <p>Array sizes must match.</p>
+     *
+     * @param message Message to use in case the assertion fails
+     * @param left Left array
+     * @param right Right array
+     */
+    public static void assertArrayNotGreater(String message, float[] left, float[] right) {
+        assertEquals("Array lengths did not match", left.length, right.length);
+
+        String leftString = Arrays.toString(left);
+        String rightString = Arrays.toString(right);
+
+        for (int i = 0; i < left.length; ++i) {
+            String msg = String.format(
+                    "%s: (%s should be less than or equals than %s; item index %d; left = %s; " +
+                    "right = %s)",
+                    message, left[i], right[i], i, leftString, rightString);
+
+            assertTrue(msg, left[i] <= right[i]);
+        }
+    }
+
+    /**
+     * Assert that every element in the value array is greater than the lower bound (exclusive).
+     *
+     * @param value an array of items
+     * @param lowerBound the exclusive lower bound
+     */
+    public static void assertArrayWithinLowerBound(String message, float[] value, float lowerBound)
+    {
+        for (int i = 0; i < value.length; ++i) {
+            assertTrue(
+                    String.format("%s: (%s should be greater than than %s; item index %d in %s)",
+                            message, value[i], lowerBound, i, Arrays.toString(value)),
+                    value[i] > lowerBound);
+        }
+    }
+
+    /**
+     * Assert that every element in the value array is less than the upper bound (exclusive).
+     *
+     * @param value an array of items
+     * @param upperBound the exclusive upper bound
+     */
+    public static void assertArrayWithinUpperBound(String message, float[] value, float upperBound)
+    {
+        for (int i = 0; i < value.length; ++i) {
+            assertTrue(
+                    String.format("%s: (%s should be less than than %s; item index %d in %s)",
+                            message, value[i], upperBound, i, Arrays.toString(value)),
+                    value[i] < upperBound);
+        }
+    }
+
+    /**
+     * Assert that {@code low <= value <= high}
+     */
+    public static void assertInRange(float value, float low, float high) {
+        assertTrue(
+                String.format("Value %s must be greater or equal to %s, but was lower", value, low),
+                value >= low);
+        assertTrue(
+                String.format("Value %s must be less than or equal to %s, but was higher",
+                        value, high),
+                value <= high);
+
+        // TODO: generic by using comparators
+    }
+
+    /**
+     * Assert that the given array contains the given value.
+     *
+     * @param message message to print on failure.
+     * @param actual array to test.
+     * @param checkVals value to check for array membership.
+     */
+    public static <T> void assertArrayContains(String message, T[] actual, T checkVals) {
+        assertCollectionContainsAnyOf(message, buildList(actual), Arrays.asList(checkVals));
+    }
+
+
+    /**
+     * Assert that the given array contains the given value.
+     *
+     * @param message message to print on failure.
+     * @param actual array to test.
+     * @param checkVals value to check for array membership.
+     */
+    public static void assertArrayContains(String message, int[] actual, int checkVals) {
+        assertCollectionContainsAnyOf(message, buildList(actual), Arrays.asList(checkVals));
+    }
+
+    /**
+     * Assert that the given array contains at least one of the given values.
+     *
+     * @param message message to print on failure.
+     * @param actual array to test
+     * @param checkVals values to check for array membership.
+     * @return the value contained, or null.
+     */
+    public static <T> T assertArrayContainsAnyOf(String message, T[] actual, T[] checkVals) {
+        return assertCollectionContainsAnyOf(message, buildList(actual), buildList(checkVals));
+    }
+
+    /**
+     * Assert that the given array contains at least one of the given values.
+     *
+     * @param message message to print on failure.
+     * @param actual array to test
+     * @param checkVals values to check for array membership.
+     * @return the value contained.
+     */
+    public static int assertArrayContainsAnyOf(String message, int[] actual, int[] checkVals) {
+        return assertCollectionContainsAnyOf(message, buildList(actual), buildList(checkVals));
+    }
+
+    /**
+     * Assert that the given {@link Collection} contains at least one of the given values.
+     *
+     * @param message message to print on failure.
+     * @param actual {@link Collection} to test.
+     * @param checkVals a {@link Collection} of values to check for membership.
+     * @return the value contained, or null.
+     */
+    public static <T> T assertCollectionContainsAnyOf(String message, Collection<T> actual,
+                                                      Collection<T> checkVals) {
+        boolean contains = false;
+        T selected = null;
+        for (T check : checkVals) {
+            contains = actual.contains(check);
+            if (contains) {
+                selected = check;
+                break;
+            }
+        }
+
+        if (!contains) {
+            fail(String.format("%s : No elements from %s in %s", message,
+                    formatCollection(actual, MAX_FORMAT_STRING),
+                    formatCollection(checkVals, MAX_FORMAT_STRING)));
+        }
+        return selected;
+    }
+
+    private static <T> List<T> buildList(T[] array) {
+        return new ArrayList<T>(Arrays.asList(array));
+    }
+
+    private static List<Integer> buildList(int[] array) {
+        List<Integer> list = new ArrayList<Integer>(array.length);
+        for (Integer val : array) {
+            list.add(val);
+        }
+        return list;
+    }
+
+    private static <T> String formatCollection(Collection<T> collection, int maxLen) {
+        StringBuilder builder = new StringBuilder();
+        builder.append("[");
+
+        boolean first = true;
+        for (T elem : collection) {
+            String val = ((first) ? ", " : "") + ((elem != null) ? elem.toString() : "null");
+            first = false;
+            if ((builder.length() + val.length()) > maxLen - "...]".length()) {
+                builder.append("...");
+                break;
+            } else {
+                builder.append(val);
+            }
+        }
+        builder.append("]");
+        return builder.toString();
+    }
+
+
+    // Suppress default constructor for noninstantiability
+    private AssertHelpers() { throw new AssertionError(); }
+}
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
new file mode 100644
index 0000000..1c42629
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/Camera2Focuser.java
@@ -0,0 +1,392 @@
+/*
+ * 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.helpers;
+
+import android.graphics.Rect;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CameraCaptureSession.CaptureCallback;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.params.MeteringRectangle;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.TotalCaptureResult;
+import android.os.Handler;
+import android.util.Log;
+import android.view.Surface;
+
+import com.android.ex.camera2.pos.AutoFocusStateMachine;
+import com.android.ex.camera2.pos.AutoFocusStateMachine.AutoFocusStateListener;
+
+/**
+ * A focuser utility class to assist camera to do auto focus.
+ * <p>
+ * This class need create repeating request and single request to do auto focus.
+ * The repeating request is used to get the auto focus states; the single
+ * request is used to trigger the auto focus. This class assumes the camera device
+ * supports auto-focus. Don't use this class if the camera device doesn't have focuser
+ * unit.
+ * </p>
+ */
+public class Camera2Focuser implements AutoFocusStateListener {
+    private static final String TAG = "Focuser";
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+
+    private final AutoFocusStateMachine mAutoFocus = new AutoFocusStateMachine(this);
+    private final Handler mHandler;
+    private final AutoFocusListener mAutoFocusListener;
+    private final CameraDevice mCamera;
+    private final CameraCaptureSession mSession;
+    private final Surface mRequestSurface;
+    private final StaticMetadata mStaticInfo;
+
+    private int mAfRun = 0;
+    private MeteringRectangle[] mAfRegions;
+    private boolean mLocked = false;
+    private boolean mSuccess = false;
+    private CaptureRequest.Builder mRepeatingBuilder;
+
+    /**
+     * The callback interface to notify auto focus result.
+     */
+    public interface AutoFocusListener {
+        /**
+         * This callback is called when auto focus completes and locked.
+         *
+         * @param success true if focus was successful, false if otherwise
+         */
+        void onAutoFocusLocked(boolean success);
+    }
+
+    /**
+     * Construct a focuser object, with given capture requestSurface, listener
+     * and handler.
+     * <p>
+     * The focuser object will use camera and requestSurface to submit capture
+     * request and receive focus state changes. The {@link AutoFocusListener} is
+     * used to notify the auto focus callback.
+     * </p>
+     *
+     * @param camera The camera device associated with this focuser
+     * @param session The camera capture session associated with this focuser
+     * @param requestSurface The surface to issue the capture request with
+     * @param listener The auto focus listener to notify AF result
+     * @param staticInfo The CameraCharacteristics of the camera device
+     * @param handler The handler used to post auto focus callbacks
+     * @throws CameraAccessException
+     */
+    public Camera2Focuser(CameraDevice camera, CameraCaptureSession session, Surface requestSurface,
+            AutoFocusListener listener, CameraCharacteristics staticInfo, Handler handler)
+            throws CameraAccessException {
+        if (camera == null) {
+            throw new IllegalArgumentException("camera must not be null");
+        }
+        if (session == null) {
+            throw new IllegalArgumentException("session must not be null");
+        }
+        if (listener == null) {
+            throw new IllegalArgumentException("listener must not be null");
+        }
+        if (handler == null) {
+            throw new IllegalArgumentException("handler must not be null");
+        }
+        if (requestSurface == null) {
+            throw new IllegalArgumentException("requestSurface must not be null");
+        }
+        if (staticInfo == null) {
+            throw new IllegalArgumentException("staticInfo must not be null");
+        }
+
+        mCamera = camera;
+        mSession = session;
+        mRequestSurface = requestSurface;
+        mAutoFocusListener = listener;
+        mStaticInfo = new StaticMetadata(staticInfo,
+                StaticMetadata.CheckLevel.ASSERT, /*collector*/null);
+        mHandler = handler;
+
+        if (!mStaticInfo.hasFocuser()) {
+            throw new IllegalArgumentException("this camera doesn't have a focuser");
+        }
+
+        /**
+         * Begin by always being in passive auto focus.
+         */
+        cancelAutoFocus();
+    }
+
+    @Override
+    public synchronized void onAutoFocusSuccess(CaptureResult result, boolean locked) {
+        mSuccess = true;
+        mLocked = locked;
+
+        if (locked) {
+            dispatchAutoFocusStatusLocked(/*success*/true);
+        }
+    }
+
+    @Override
+    public synchronized void onAutoFocusFail(CaptureResult result, boolean locked) {
+        mSuccess = false;
+        mLocked = locked;
+
+        if (locked) {
+            dispatchAutoFocusStatusLocked(/*success*/false);
+        }
+    }
+
+    @Override
+    public synchronized void onAutoFocusScan(CaptureResult result) {
+        mSuccess = false;
+        mLocked = false;
+    }
+
+    @Override
+    public synchronized void onAutoFocusInactive(CaptureResult result) {
+        mSuccess = false;
+        mLocked = false;
+    }
+
+    /**
+     * Start a active auto focus scan based on the given regions.
+     *
+     * <p>This is usually used for touch for focus, it can make the auto-focus converge based
+     * on some particular region aggressively. But it is usually slow as a full active scan
+     * is initiated. After the auto focus is converged, the {@link cancelAutoFocus} must be called
+     * to resume the continuous auto-focus.</p>
+     *
+     * @param afRegions The AF regions used by focuser auto focus, full active
+     * array size is used if afRegions is null.
+     * @throws CameraAccessException
+     */
+    public synchronized void touchForAutoFocus(MeteringRectangle[] afRegions)
+            throws CameraAccessException {
+        startAutoFocusLocked(/*active*/true, afRegions);
+    }
+
+    /**
+     * Start auto focus scan.
+     * <p>
+     * Start an auto focus scan if it was not done yet. If AF passively focused,
+     * lock it. If AF is already locked, return. Otherwise, initiate a full
+     * active scan. This is suitable for still capture: focus should need to be
+     * accurate, but the AF latency also need to be as short as possible.
+     * </p>
+     *
+     * @param afRegions The AF regions used by focuser auto focus, full active
+     *            array size is used if afRegions is null.
+     * @throws CameraAccessException
+     */
+    public synchronized void startAutoFocus(MeteringRectangle[] afRegions)
+            throws CameraAccessException {
+        startAutoFocusLocked(/*forceActive*/false, afRegions);
+    }
+
+    /**
+     * Cancel ongoing auto focus, unlock the auto-focus if it was locked, and
+     * resume to passive continuous auto focus.
+     *
+     * @throws CameraAccessException
+     */
+    public synchronized void cancelAutoFocus() throws CameraAccessException {
+        mSuccess = false;
+        mLocked = false;
+
+        // reset the AF regions:
+        setAfRegions(null);
+
+        // Create request builders, the af regions are automatically updated.
+        mRepeatingBuilder = createRequestBuilder();
+        CaptureRequest.Builder requestBuilder = createRequestBuilder();
+        mAutoFocus.setPassiveAutoFocus(/*picture*/true, mRepeatingBuilder);
+        mAutoFocus.unlockAutoFocus(mRepeatingBuilder, requestBuilder);
+        CaptureCallback listener = createCaptureListener();
+        mSession.setRepeatingRequest(mRepeatingBuilder.build(), listener, mHandler);
+        mSession.capture(requestBuilder.build(), listener, mHandler);
+    }
+
+    /**
+     * Get current AF mode.
+     * @return current AF mode
+     * @throws IllegalStateException if there auto focus is not running.
+     */
+    public synchronized int getCurrentAfMode() {
+        if (mRepeatingBuilder == null) {
+            throw new IllegalStateException("Auto focus is not running, unable to get AF mode");
+        }
+
+        return mRepeatingBuilder.get(CaptureRequest.CONTROL_AF_MODE);
+    }
+
+    private void startAutoFocusLocked(
+            boolean forceActive, MeteringRectangle[] afRegions) throws CameraAccessException {
+
+        setAfRegions(afRegions);
+        mAfRun++;
+
+        // Create request builders, the af regions are automatically updated.
+        mRepeatingBuilder = createRequestBuilder();
+        CaptureRequest.Builder requestBuilder = createRequestBuilder();
+        if (forceActive) {
+            startAutoFocusFullActiveLocked();
+        } else {
+            // Not forcing a full active scan. If AF passively focused, lock it. If AF is already
+            // locked, return. Otherwise, initiate a full active scan.
+            if (mSuccess && mLocked) {
+                dispatchAutoFocusStatusLocked(/*success*/true);
+                return;
+            } else if (mSuccess) {
+                mAutoFocus.lockAutoFocus(mRepeatingBuilder, requestBuilder);
+                CaptureCallback listener = createCaptureListener();
+                mSession.setRepeatingRequest(mRepeatingBuilder.build(), listener, mHandler);
+                mSession.capture(requestBuilder.build(), listener, mHandler);
+            } else {
+                startAutoFocusFullActiveLocked();
+            }
+        }
+    }
+
+    private void startAutoFocusFullActiveLocked() throws CameraAccessException {
+        // Create request builders, the af regions are automatically updated.
+        mRepeatingBuilder = createRequestBuilder();
+        CaptureRequest.Builder requestBuilder = createRequestBuilder();
+        mAutoFocus.setActiveAutoFocus(mRepeatingBuilder, requestBuilder);
+        if (mRepeatingBuilder.get(CaptureRequest.CONTROL_AF_TRIGGER)
+                != CaptureRequest.CONTROL_AF_TRIGGER_IDLE) {
+            throw new AssertionError("Wrong trigger set in repeating request");
+        }
+        if (requestBuilder.get(CaptureRequest.CONTROL_AF_TRIGGER)
+                != CaptureRequest.CONTROL_AF_TRIGGER_START) {
+            throw new AssertionError("Wrong trigger set in queued request");
+        }
+        mAutoFocus.resetState();
+
+        CaptureCallback listener = createCaptureListener();
+        mSession.setRepeatingRequest(mRepeatingBuilder.build(), listener, mHandler);
+        mSession.capture(requestBuilder.build(), listener, mHandler);
+    }
+
+    private void dispatchAutoFocusStatusLocked(final boolean success) {
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mAutoFocusListener.onAutoFocusLocked(success);
+            }
+        });
+    }
+
+    /**
+     * Create request builder, set the af regions.
+     * @throws CameraAccessException
+     */
+    private CaptureRequest.Builder createRequestBuilder() throws CameraAccessException {
+        CaptureRequest.Builder requestBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+
+        requestBuilder.set(CaptureRequest.CONTROL_AF_REGIONS, mAfRegions);
+        requestBuilder.addTarget(mRequestSurface);
+
+        return requestBuilder;
+    }
+
+    /**
+     * 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).
+     */
+    private void setAfRegions(MeteringRectangle[] afRegions) {
+        if (afRegions == null) {
+            setDefaultAfRegions();
+            return;
+        }
+        // Throw IAE if AF regions are malformed.
+        if (afRegions.length == 0) {
+            throw new IllegalArgumentException("afRegions is malformed, length: 0");
+        }
+
+        mAfRegions = afRegions;
+    }
+
+    /**
+     * Set default AF region to full active array size.
+     */
+    private void setDefaultAfRegions() {
+        // Initialize AF regions with all zeros, meaning that it is up to camera device to device
+        // the regions used by AF.
+        mAfRegions = new MeteringRectangle[] {
+                new MeteringRectangle(0, 0, 0, 0, MeteringRectangle.METERING_WEIGHT_DONT_CARE)};
+    }
+    private CaptureCallback createCaptureListener() {
+
+        int thisAfRun;
+        synchronized (this) {
+            thisAfRun = mAfRun;
+        }
+
+        final int finalAfRun = thisAfRun;
+
+        return new CaptureCallback() {
+            private long mLatestFrameCount = -1;
+
+            @Override
+            public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request,
+                    CaptureResult result) {
+                // In case of a partial result, send to focuser if necessary
+                // 3A fields are present
+                if (result.get(CaptureResult.CONTROL_AF_STATE) != null &&
+                        result.get(CaptureResult.CONTROL_AF_MODE) != null) {
+                    if (VERBOSE) {
+                        Log.v(TAG, "Focuser - got early AF state");
+                    }
+
+                    dispatchToFocuser(result);
+                }
+            }
+
+            @Override
+            public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
+                    TotalCaptureResult result) {
+                    dispatchToFocuser(result);
+            }
+
+            private void dispatchToFocuser(CaptureResult result) {
+                int afRun;
+                synchronized (Camera2Focuser.this) {
+                    // In case of partial results, don't send AF update twice
+                    long frameCount = result.getFrameNumber();
+                    if (frameCount <= mLatestFrameCount) return;
+                    mLatestFrameCount = frameCount;
+
+                    afRun = mAfRun;
+                }
+
+                if (afRun != finalAfRun) {
+                    if (VERBOSE) {
+                        Log.w(TAG,
+                                "onCaptureCompleted - Ignoring results from previous AF run "
+                                + finalAfRun);
+                    }
+                    return;
+                }
+
+                mAutoFocus.onCaptureCompleted(result);
+            }
+        };
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/CameraErrorCollector.java b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/CameraErrorCollector.java
new file mode 100644
index 0000000..7cf4089
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/CameraErrorCollector.java
@@ -0,0 +1,1004 @@
+/*
+ * 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.helpers;
+
+import android.graphics.Rect;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureRequest.Builder;
+import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.params.MeteringRectangle;
+import android.util.Log;
+import android.util.Size;
+
+import org.hamcrest.CoreMatchers;
+import org.hamcrest.Matcher;
+import org.junit.rules.ErrorCollector;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * A camera test ErrorCollector class to gather the test failures during a test,
+ * instead of failing the test immediately for each failure.
+ */
+public class CameraErrorCollector extends ErrorCollector {
+
+    private static final String TAG = "CameraErrorCollector";
+    private static final boolean LOG_ERRORS = Log.isLoggable(TAG, Log.ERROR);
+
+    private String mCameraMsg = "";
+
+    @Override
+    public void verify() throws Throwable {
+        // Do not remove if using JUnit 3 test runners. super.verify() is protected.
+        super.verify();
+    }
+
+    /**
+     * Adds an unconditional error to the table.
+     *
+     * <p>Execution continues, but test will fail at the end.</p>
+     *
+     * @param message A string containing the failure reason.
+     */
+    public void addMessage(String message) {
+        addErrorSuper(new Throwable(mCameraMsg + message));
+    }
+
+    /**
+     * Adds a Throwable to the table. <p>Execution continues, but the test will fail at the end.</p>
+     */
+    @Override
+    public void addError(Throwable error) {
+        addErrorSuper(new Throwable(mCameraMsg + error.getMessage(), error));
+    }
+
+    private void addErrorSuper(Throwable error) {
+        if (LOG_ERRORS) Log.e(TAG, error.getMessage());
+        super.addError(error);
+    }
+
+    /**
+     * Adds a failure to the table if {@code matcher} does not match {@code value}.
+     * Execution continues, but the test will fail at the end if the match fails.
+     * The camera id is included into the failure log.
+     */
+    @Override
+    public <T> void checkThat(final T value, final Matcher<T> matcher) {
+        super.checkThat(mCameraMsg, value, matcher);
+    }
+
+    /**
+     * Adds a failure with the given {@code reason} to the table if
+     * {@code matcher} does not match {@code value}. Execution continues, but
+     * the test will fail at the end if the match fails. The camera id is
+     * included into the failure log.
+     */
+    @Override
+    public <T> void checkThat(final String reason, final T value, final Matcher<T> matcher) {
+        super.checkThat(mCameraMsg + reason, value, matcher);
+    }
+
+    /**
+     * Set the camera id to this error collector object for logging purpose.
+     *
+     * @param id The camera id to be set.
+     */
+    public void setCameraId(String id) {
+        if (id != null) {
+            mCameraMsg = "Test failed for camera " + id + ": ";
+        } else {
+            mCameraMsg = "";
+        }
+    }
+
+    /**
+     * Adds a failure to the table if {@code condition} is not {@code true}.
+     * <p>
+     * Execution continues, but the test will fail at the end if the condition
+     * failed.
+     * </p>
+     *
+     * @param msg Message to be logged when check fails.
+     * @param condition Log the failure if it is not true.
+     */
+    public boolean expectTrue(String msg, boolean condition) {
+        if (!condition) {
+            addMessage(msg);
+        }
+
+        return condition;
+    }
+
+    /**
+     * Check if the two values are equal.
+     *
+     * @param msg Message to be logged when check fails.
+     * @param expected Expected value to be checked against.
+     * @param actual Actual value to be checked.
+     * @return {@code true} if the two values are equal, {@code false} otherwise.
+     *
+     * @throws IllegalArgumentException if {@code expected} was {@code null}
+     */
+    public <T> boolean expectEquals(String msg, T expected, T actual) {
+        if (expected == null) {
+            throw new IllegalArgumentException("expected value shouldn't be null");
+        }
+
+        if (!Objects.equals(expected, actual)) {
+            addMessage(String.format("%s (expected = %s, actual = %s) ", msg, expected,
+                    actual));
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Check if the two values are not equal.
+     *
+     * @param msg Message to be logged when check fails.
+     * @param expected Expected value to be checked against.
+     * @param actual Actual value to be checked.
+     * @return {@code true} if the two values are not equal, {@code false} otherwise.
+     */
+    public <T> boolean expectNotEquals(String msg, T expected, T actual) {
+        if (Objects.equals(expected, actual)) {
+            addMessage(String.format("%s (expected = %s, actual = %s) ", msg, expected,
+                    actual));
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Check if the two arrays of values are deeply equal.
+     *
+     * @param msg Message to be logged when check fails.
+     * @param expected Expected array of values to be checked against.
+     * @param actual Actual array of values to be checked.
+     * @return {@code true} if the two arrays of values are deeply equal, {@code false} otherwise.
+     *
+     * @throws IllegalArgumentException if {@code expected} was {@code null}
+     */
+    public <T> boolean expectEquals(String msg, T[] expected, T[] actual) {
+        if (expected == null) {
+            throw new IllegalArgumentException("expected value shouldn't be null");
+        }
+
+        if (!Arrays.deepEquals(expected, actual)) {
+            addMessage(String.format("%s (expected = %s, actual = %s) ", msg,
+                    Arrays.deepToString(expected), Arrays.deepToString(actual)));
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Check if the two arrays of values are not deeply equal.
+     *
+     * @param msg Message to be logged when check fails.
+     * @param expected Expected array of values to be checked against.
+     * @param actual Actual array of values to be checked.
+     * @return {@code true} if the two arrays of values are not deeply equal, {@code false}
+     *          otherwise.
+     *
+     * @throws IllegalArgumentException if {@code expected} was {@code null}
+     */
+    public <T> boolean expectNotEquals(String msg, T[] expected, T[] actual) {
+        if (expected == null) {
+            throw new IllegalArgumentException("expected value shouldn't be null");
+        }
+
+        if (Arrays.deepEquals(expected, actual)) {
+            addMessage(String.format("%s (expected = %s, actual = %s) ", msg,
+                    Arrays.deepToString(expected), Arrays.deepToString(actual)));
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Check that the {@code actual} value is greater than the {@code expected} value.
+     *
+     * @param msg Message to be logged when check fails.
+     * @param expected The expected value to check that the actual value is larger than.
+     * @param actual Actual value to check.
+     * @return {@code true} if {@code actual} is greater than {@code expected}.
+     */
+    public <T extends Comparable<? super T>> boolean expectGreater(String msg, T expected,
+            T actual) {
+        return expectTrue(String.format("%s: (expected = %s was not greater than actual = %s) ",
+                msg, expected, actual), actual.compareTo(expected) > 0);
+    }
+
+    /**
+     * Check that the {@code actual} value is greater than or equal to the {@code expected} value.
+     *
+     * @param msg Message to be logged when check fails.
+     * @param expected The expected value to check that the actual value is larger than or equal to.
+     * @param actual Actual value to check.
+     * @return {@code true} if {@code actual} is greater than or equal to {@code expected}.
+     */
+    public <T extends Comparable<? super T>> boolean expectGreaterOrEqual(String msg, T expected,
+                                                                       T actual) {
+        return expectTrue(String.format("%s: (expected = %s was not greater than actual = %s) ",
+                msg, expected, actual), actual.compareTo(expected) >= 0);
+    }
+
+    /**
+     * Check that the {@code actual} value is less than the {@code expected} value.
+     *
+     * @param msg Message to be logged when check fails.
+     * @param expected The expected value to check that the actual value is less than.
+     * @param actual Actual value to check.
+     * @return {@code true} if {@code actual} is less than {@code expected}.
+     */
+    public <T extends Comparable<? super T>> boolean expectLess(String msg, T expected,
+            T actual) {
+        return expectTrue(String.format("%s: (expected = %s was not greater than actual = %s) ",
+                msg, expected, actual), actual.compareTo(expected) < 0);
+    }
+
+    /**
+     * Check that the {@code actual} value is less than or equal to the {@code expected} value.
+     *
+     * @param msg Message to be logged when check fails.
+     * @param expected The expected value to check that the actual value is less than or equal to.
+     * @param actual Actual value to check.
+     * @return {@code true} if {@code actual} is less than or equal to {@code expected}.
+     */
+    public <T extends Comparable<? super T>> boolean expectLessOrEqual(String msg, T expected,
+            T actual) {
+        return expectTrue(String.format("%s: (expected = %s was not greater than actual = %s) ",
+                msg, expected, actual), actual.compareTo(expected) <= 0);
+    }
+
+    /**
+     * Check if the two float values are equal with given error tolerance.
+     *
+     * @param msg Message to be logged when check fails.
+     * @param expected Expected value to be checked against.
+     * @param actual Actual value to be checked.
+     * @param tolerance The error margin for the equality check.
+     * @return {@code true} if the two values are equal, {@code false} otherwise.
+     */
+    public <T> boolean expectEquals(String msg, float expected, float actual, float tolerance) {
+        if (expected == actual) {
+            return true;
+        }
+
+        if (!(Math.abs(expected - actual) <= tolerance)) {
+            addMessage(String.format("%s (expected = %s, actual = %s, tolerance = %s) ", msg,
+                    expected, actual, tolerance));
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Check if the two double values are equal with given error tolerance.
+     *
+     * @param msg Message to be logged when check fails.
+     * @param expected Expected value to be checked against.
+     * @param actual Actual value to be checked.
+     * @param tolerance The error margin for the equality check
+     * @return {@code true} if the two values are equal, {@code false} otherwise.
+     */
+    public <T> boolean expectEquals(String msg, double expected, double actual, double tolerance) {
+        if (expected == actual) {
+            return true;
+        }
+
+        if (!(Math.abs(expected - actual) <= tolerance)) {
+            addMessage(String.format("%s (expected = %s, actual = %s, tolerance = %s) ", msg,
+                    expected, actual, tolerance));
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Check that all values in the list are greater than or equal to the min value.
+     *
+     * @param msg Message to be logged when check fails
+     * @param list The list of values to be checked
+     * @param min The smallest allowed value
+     */
+    public <T extends Comparable<? super T>> void expectValuesGreaterOrEqual(String msg,
+            List<T> list, T min) {
+        for (T value : list) {
+            expectTrue(msg + String.format(", array value " + value.toString() +
+                                    " is less than %s",
+                            min.toString()), value.compareTo(min) >= 0);
+        }
+    }
+
+    /**
+     * Check that all values in the array are greater than or equal to the min value.
+     *
+     * @param msg Message to be logged when check fails
+     * @param array The array of values to be checked
+     * @param min The smallest allowed value
+     */
+    public <T extends Comparable<? super T>> void expectValuesGreaterOrEqual(String msg,
+                                                                             T[] array, T min) {
+        expectValuesGreaterOrEqual(msg, Arrays.asList(array), min);
+    }
+
+    /**
+     * Expect the list of values are in the range.
+     *
+     * @param msg Message to be logged
+     * @param list The list of values to be checked
+     * @param min The min value of the range
+     * @param max The max value of the range
+     */
+    public <T extends Comparable<? super T>> void expectValuesInRange(String msg, List<T> list,
+            T min, T max) {
+        for (T value : list) {
+            expectTrue(msg + String.format(", array value " + value.toString() +
+                    " is out of range [%s, %s]",
+                    min.toString(), max.toString()),
+                    value.compareTo(max)<= 0 && value.compareTo(min) >= 0);
+        }
+    }
+
+    /**
+     * Expect the array of values are in the range.
+     *
+     * @param msg Message to be logged
+     * @param array The array of values to be checked
+     * @param min The min value of the range
+     * @param max The max value of the range
+     */
+    public <T extends Comparable<? super T>> void expectValuesInRange(String msg, T[] array,
+            T min, T max) {
+        expectValuesInRange(msg, Arrays.asList(array), min, max);
+    }
+
+    /**
+     * Expect the array of values are in the range.
+     *
+     * @param msg Message to be logged
+     * @param array The array of values to be checked
+     * @param min The min value of the range
+     * @param max The max value of the range
+     */
+    public void expectValuesInRange(String msg, int[] array, int min, int max) {
+        ArrayList<Integer> l = new ArrayList<>(array.length);
+        for (int i : array) {
+            l.add(i);
+        }
+        expectValuesInRange(msg, l, min, max);
+    }
+
+    /**
+     * Expect the value is in the range.
+     *
+     * @param msg Message to be logged
+     * @param value The value to be checked
+     * @param min The min value of the range
+     * @param max The max value of the range
+     *
+     * @return {@code true} if the value was in range, {@code false} otherwise
+     */
+    public <T extends Comparable<? super T>> boolean expectInRange(String msg, T value,
+            T min, T max) {
+        return expectTrue(msg + String.format(", value " + value.toString()
+                + " is out of range [%s, %s]",
+                min.toString(), max.toString()),
+                value.compareTo(max)<= 0 && value.compareTo(min) >= 0);
+    }
+
+
+    /**
+     * Check that two metering region arrays are similar enough by ensuring that each of their width,
+     * height, and all corners are within {@code errorPercent} of each other.
+     *
+     * <p>Note that the length of the arrays must be the same, and each weight must be the same
+     * as well. We assume the order is also equivalent.</p>
+     *
+     * <p>At most 1 error per each dissimilar metering region is collected.</p>
+     *
+     * @param msg Message to be logged
+     * @param expected The reference 'expected' values to be used to check against
+     * @param actual The actual values that were received
+     * @param errorPercent Within how many percent the components should be
+     *
+     * @return {@code true} if all expects passed, {@code false} otherwise
+     */
+    public boolean expectMeteringRegionsAreSimilar(String msg,
+            MeteringRectangle[] expected, MeteringRectangle[] actual,
+            float errorPercent) {
+        String expectedActualMsg = String.format("expected (%s), actual (%s)",
+                Arrays.deepToString(expected), Arrays.deepToString(actual));
+
+        String differentSizesMsg = String.format(
+                "%s: rect lists are different sizes; %s",
+                msg, expectedActualMsg);
+
+        String differentWeightsMsg = String.format(
+                "%s: rect weights are different; %s",
+                msg, expectedActualMsg);
+
+        if (!expectTrue(differentSizesMsg, actual != null)) {
+            return false;
+        }
+
+        if (!expectEquals(differentSizesMsg, expected.length, actual.length)) return false;
+
+        boolean succ = true;
+        for (int i = 0; i < expected.length; ++i) {
+            if (i < actual.length) {
+                // Avoid printing multiple errors for the same rectangle
+                if (!expectRectsAreSimilar(
+                        msg, expected[i].getRect(), actual[i].getRect(), errorPercent)) {
+                    succ = false;
+                    continue;
+                }
+                if (!expectEquals(differentWeightsMsg,
+                        expected[i].getMeteringWeight(), actual[i].getMeteringWeight())) {
+                    succ = false;
+                    continue;
+                }
+            }
+        }
+
+        return succ;
+    }
+
+    /**
+     * Check that two rectangles are similar enough by ensuring that their width, height,
+     * and all corners are within {@code errorPercent} of each other.
+     *
+     * <p>Only the first error is collected, to avoid spamming several error messages when
+     * the rectangle is hugely dissimilar.</p>
+     *
+     * @param msg Message to be logged
+     * @param expected The reference 'expected' value to be used to check against
+     * @param actual The actual value that was received
+     * @param errorPercent Within how many percent the components should be
+     *
+     * @return {@code true} if all expects passed, {@code false} otherwise
+     */
+    public boolean expectRectsAreSimilar(String msg, Rect expected, Rect actual,
+            float errorPercent) {
+        String formattedMsg = String.format("%s: rects are not similar enough; expected (%s), " +
+                "actual (%s), error percent (%s), reason: ",
+                msg, expected, actual, errorPercent);
+
+        if (!expectSimilarValues(
+                formattedMsg, "too wide", "too narrow", actual.width(), expected.width(),
+                errorPercent)) return false;
+
+        if (!expectSimilarValues(
+                formattedMsg, "too tall", "too short", actual.height(), expected.height(),
+                errorPercent)) return false;
+
+        if (!expectSimilarValues(
+                formattedMsg, "left pt too right", "left pt too left", actual.left, expected.left,
+                errorPercent)) return false;
+
+        if (!expectSimilarValues(
+                formattedMsg, "right pt too right", "right pt too left",
+                actual.right, expected.right, errorPercent)) return false;
+
+        if (!expectSimilarValues(
+                formattedMsg, "top pt too low", "top pt too high", actual.top, expected.top,
+                errorPercent)) return false;
+
+        if (!expectSimilarValues(
+                formattedMsg, "bottom pt too low", "bottom pt too high", actual.top, expected.top,
+                errorPercent)) return false;
+
+        return true;
+    }
+
+    /**
+     * Check that the rectangle is centered within a certain tolerance of {@code errorPercent},
+     * with respect to the {@code bounds} bounding rectangle.
+     *
+     * @param msg Message to be logged
+     * @param expectedBounds The width/height of the bounding rectangle
+     * @param actual The actual value that was received
+     * @param errorPercent Within how many percent the centering should be
+     */
+    public void expectRectCentered(String msg, Size expectedBounds, Rect actual,
+            float errorPercent) {
+        String formattedMsg = String.format("%s: rect should be centered; expected bounds (%s), " +
+                "actual (%s), error percent (%s), reason: ",
+                msg, expectedBounds, actual, errorPercent);
+
+        int centerBoundX = expectedBounds.getWidth() / 2;
+        int centerBoundY = expectedBounds.getHeight() / 2;
+
+        expectSimilarValues(
+                formattedMsg, "too low", "too high", actual.centerY(), centerBoundY,
+                errorPercent);
+
+        expectSimilarValues(
+                formattedMsg, "too right", "too left", actual.centerX(), centerBoundX,
+                errorPercent);
+    }
+
+    private boolean expectSimilarValues(
+            String formattedMsg, String tooSmall, String tooLarge, int actualValue,
+            int expectedValue, float errorPercent) {
+        boolean succ = true;
+        succ = expectTrue(formattedMsg + tooLarge,
+                actualValue <= (expectedValue * (1.0f + errorPercent))) && succ;
+        succ = expectTrue(formattedMsg + tooSmall,
+                actualValue >= (expectedValue * (1.0f - errorPercent))) && succ;
+
+        return succ;
+    }
+
+    public void expectNotNull(String msg, Object obj) {
+        checkThat(msg, obj, CoreMatchers.notNullValue());
+    }
+
+    public void expectNull(String msg, Object obj) {
+        if (obj != null) {
+            addMessage(msg);
+        }
+    }
+
+    /**
+     * Check if the values in the array are monotonically increasing (decreasing) and not all
+     * equal.
+     *
+     * @param array The array of values to be checked
+     * @param ascendingOrder The monotonicity ordering to be checked with
+     */
+    public <T extends Comparable<? super T>>  void checkArrayMonotonicityAndNotAllEqual(T[] array,
+            boolean ascendingOrder) {
+        String orderMsg = ascendingOrder ? ("increasing order") : ("decreasing order");
+        for (int i = 0; i < array.length - 1; i++) {
+            int compareResult = array[i + 1].compareTo(array[i]);
+            boolean condition = compareResult >= 0;
+            if (!ascendingOrder) {
+                condition = compareResult <= 0;
+            }
+
+            expectTrue(String.format("Adjacent values (%s and %s) %s monotonicity is broken",
+                    array[i].toString(), array[i + 1].toString(), orderMsg), condition);
+        }
+
+        expectTrue("All values of this array are equal: " + array[0].toString(),
+                array[0].compareTo(array[array.length - 1]) != 0);
+    }
+
+    /**
+     * Check if the key value is not null and return the value.
+     *
+     * @param characteristics The {@link CameraCharacteristics} to get the key from.
+     * @param key The {@link CameraCharacteristics} key to be checked.
+     *
+     * @return The value of the key.
+     */
+    public <T> T expectKeyValueNotNull(CameraCharacteristics characteristics,
+            CameraCharacteristics.Key<T> key) {
+
+        T value = characteristics.get(key);
+        if (value == null) {
+            addMessage("Key " + key.getName() + " shouldn't be null");
+        }
+
+        return value;
+    }
+
+    /**
+     * Check if the key value is not null and return the value.
+     *
+     * @param request The {@link CaptureRequest} to get the key from.
+     * @param key The {@link CaptureRequest} key to be checked.
+     *
+     * @return The value of the key.
+     */
+    public <T> T expectKeyValueNotNull(CaptureRequest request,
+                                       CaptureRequest.Key<T> key) {
+
+        T value = request.get(key);
+        if (value == null) {
+            addMessage("Key " + key.getName() + " shouldn't be null");
+        }
+
+        return value;
+    }
+
+    /**
+     * Check if the key value is not null and return the value.
+     *
+     * @param request The {@link CaptureRequest#Builder} to get the key from.
+     * @param key The {@link CaptureRequest} key to be checked.
+     * @return The value of the key.
+     */
+    public <T> T expectKeyValueNotNull(Builder request, CaptureRequest.Key<T> key) {
+
+        T value = request.get(key);
+        if (value == null) {
+            addMessage("Key " + key.getName() + " shouldn't be null");
+        }
+
+        return value;
+    }
+
+    /**
+     * Check if the key value is not null and return the value.
+     *
+     * @param result The {@link CaptureResult} to get the key from.
+     * @param key The {@link CaptureResult} key to be checked.
+     * @return The value of the key.
+     */
+    public <T> T expectKeyValueNotNull(CaptureResult result, CaptureResult.Key<T> key) {
+        return expectKeyValueNotNull("", result, key);
+    }
+
+    /**
+     * Check if the key value is not null and return the value.
+     *
+     * @param msg The message to be logged.
+     * @param result The {@link CaptureResult} to get the key from.
+     * @param key The {@link CaptureResult} key to be checked.
+     * @return The value of the key.
+     */
+    public <T> T expectKeyValueNotNull(String msg, CaptureResult result, CaptureResult.Key<T> key) {
+
+        T value = result.get(key);
+        if (value == null) {
+            addMessage(msg + " Key " + key.getName() + " shouldn't be null");
+        }
+
+        return value;
+    }
+
+    /**
+     * Check if the key is non-null and the value is not equal to target.
+     *
+     * @param request The The {@link CaptureRequest#Builder} to get the key from.
+     * @param key The {@link CaptureRequest} key to be checked.
+     * @param expected The expected value of the CaptureRequest key.
+     */
+    public <T> void expectKeyValueNotEquals(
+            Builder request, CaptureRequest.Key<T> key, T expected) {
+        if (request == null || key == null || expected == null) {
+            throw new IllegalArgumentException("request, key and expected shouldn't be null");
+        }
+
+        T value;
+        if ((value = expectKeyValueNotNull(request, key)) == null) {
+            return;
+        }
+
+        String reason = "Key " + key.getName() + " shouldn't have value " + value.toString();
+        checkThat(reason, value, CoreMatchers.not(expected));
+    }
+
+    /**
+     * Check if the key is non-null and the value is not equal to target.
+     *
+     * @param result The {@link CaptureResult} to get the key from.
+     * @param key The {@link CaptureResult} key to be checked.
+     * @param expected The expected value of the CaptureResult key.
+     */
+    public <T> void expectKeyValueNotEquals(
+            CaptureResult result, CaptureResult.Key<T> key, T expected) {
+        if (result == null || key == null || expected == null) {
+            throw new IllegalArgumentException("result, key and expected shouldn't be null");
+        }
+
+        T value;
+        if ((value = expectKeyValueNotNull(result, key)) == null) {
+            return;
+        }
+
+        String reason = "Key " + key.getName() + " shouldn't have value " + value.toString();
+        checkThat(reason, value, CoreMatchers.not(expected));
+    }
+
+    /**
+     * Check if the value is non-null and the value is equal to target.
+     *
+     * @param result The  {@link CaptureResult} to lookup the value in.
+     * @param key The {@link CaptureResult} key to be checked.
+     * @param expected The expected value of the {@link CaptureResult} key.
+     */
+    public <T> void expectKeyValueEquals(CaptureResult result, CaptureResult.Key<T> key,
+            T expected) {
+        if (result == null || key == null || expected == null) {
+            throw new IllegalArgumentException("request, key and expected shouldn't be null");
+        }
+
+        T value;
+        if ((value = expectKeyValueNotNull(result, key)) == null) {
+            return;
+        }
+
+        String reason = "Key " + key.getName() + " value " + value.toString()
+                + " doesn't match the expected value " + expected.toString();
+        checkThat(reason, value, CoreMatchers.equalTo(expected));
+    }
+
+    /**
+     * Check if the key is non-null and the value is equal to target.
+     *
+     * <p>Only check non-null if the target is null.</p>
+     *
+     * @param request The The {@link CaptureRequest#Builder} to get the key from.
+     * @param key The {@link CaptureRequest} key to be checked.
+     * @param expected The expected value of the CaptureRequest key.
+     */
+    public <T> void expectKeyValueEquals(Builder request, CaptureRequest.Key<T> key, T expected) {
+        if (request == null || key == null || expected == null) {
+            throw new IllegalArgumentException("request, key and expected shouldn't be null");
+        }
+
+        T value;
+        if ((value = expectKeyValueNotNull(request, key)) == null) {
+            return;
+        }
+
+        String reason = "Key " + key.getName() + " value " + value.toString()
+                + " doesn't match the expected value " + expected.toString();
+        checkThat(reason, value, CoreMatchers.equalTo(expected));
+    }
+
+    /**
+     * Check if the key is non-null, and the key value is greater than the expected value.
+     *
+     * @param result {@link CaptureResult} to check.
+     * @param key The {@link CaptureResult} key to be checked.
+     * @param expected The expected to be compared to the value for the given key.
+     */
+    public <T extends Comparable<? super T>> void expectKeyValueGreaterOrEqual(
+            CaptureResult result, CaptureResult.Key<T> key, T expected) {
+        T value;
+        if ((value = expectKeyValueNotNull(result, key)) == null) {
+            return;
+        }
+
+        expectGreaterOrEqual(key.getName(), expected, value);
+    }
+
+    /**
+     * Check if the key is non-null, and the key value is greater than the expected value.
+     *
+     * @param characteristics {@link CameraCharacteristics} to check.
+     * @param key The {@link CameraCharacteristics} key to be checked.
+     * @param expected The expected to be compared to the value for the given key.
+     */
+    public <T extends Comparable<? super T>> void expectKeyValueGreaterThan(
+            CameraCharacteristics characteristics, CameraCharacteristics.Key<T> key, T expected) {
+        T value;
+        if ((value = expectKeyValueNotNull(characteristics, key)) == null) {
+            return;
+        }
+
+        expectGreater(key.getName(), expected, value);
+    }
+
+    /**
+     * Check if the key is non-null, and the key value is in the expected range.
+     *
+     * @param characteristics {@link CameraCharacteristics} to check.
+     * @param key The {@link CameraCharacteristics} key to be checked.
+     * @param min The min value of the range
+     * @param max The max value of the range
+     */
+    public <T extends Comparable<? super T>> void expectKeyValueInRange(
+            CameraCharacteristics characteristics, CameraCharacteristics.Key<T> key, T min, T max) {
+        T value;
+        if ((value = expectKeyValueNotNull(characteristics, key)) == null) {
+            return;
+        }
+        expectInRange(key.getName(), value, min, max);
+    }
+
+    /**
+     * Check if the key is non-null, and the key value is one of the expected values.
+     *
+     * @param characteristics {@link CameraCharacteristics} to check.
+     * @param key The {@link CameraCharacteristics} key to be checked.
+     * @param expected The expected values for the given key.
+     */
+    public <T> void expectKeyValueIsIn(CameraCharacteristics characteristics,
+                                       CameraCharacteristics.Key<T> key, T... expected) {
+        T value;
+        if ((value = expectKeyValueNotNull(characteristics, key)) == null) {
+            return;
+        }
+        String reason = "Key " + key.getName() + " value " + value
+                + " isn't one of the expected values " + Arrays.deepToString(expected);
+        expectContains(reason, expected, value);
+    }
+
+    /**
+     * Check if the key is non-null, and the key value contains the expected element.
+     *
+     * @param characteristics {@link CameraCharacteristics} to check.
+     * @param key The {@link CameraCharacteristics} key to be checked.
+     * @param expected The expected element to be contained in the value for the given key.
+     */
+    public <T> void expectKeyValueContains(CameraCharacteristics characteristics,
+                                           CameraCharacteristics.Key<T[]> key, T expected) {
+        T[] value;
+        if ((value = expectKeyValueNotNull(characteristics, key)) == null) {
+            return;
+        }
+        String reason = "Key " + key.getName() + " value " + value
+                + " doesn't contain the expected value " + expected;
+        expectContains(reason, value, expected);
+    }
+
+    /**
+     * Check if the key is non-null, and the key value contains the expected element.
+     *
+     * @param characteristics {@link CameraCharacteristics} to check.
+     * @param key The {@link CameraCharacteristics} key to be checked.
+     * @param expected The expected element to be contained in the value for the given key.
+     */
+    public void expectKeyValueContains(CameraCharacteristics characteristics,
+                                           CameraCharacteristics.Key<int[]> key, int expected) {
+        int[] value;
+        if ((value = expectKeyValueNotNull(characteristics, key)) == null) {
+            return;
+        }
+        String reason = "Key " + key.getName() + " value " + value
+                + " doesn't contain the expected value " + expected;
+        expectContains(reason, value, expected);
+    }
+
+    /**
+     * Check if the key is non-null, and the key value contains the expected element.
+     *
+     * @param characteristics {@link CameraCharacteristics} to check.
+     * @param key The {@link CameraCharacteristics} key to be checked.
+     * @param expected The expected element to be contained in the value for the given key.
+     */
+    public void expectKeyValueContains(CameraCharacteristics characteristics,
+                                       CameraCharacteristics.Key<boolean[]> key, boolean expected) {
+        boolean[] value;
+        if ((value = expectKeyValueNotNull(characteristics, key)) == null) {
+            return;
+        }
+        String reason = "Key " + key.getName() + " value " + value
+                + " doesn't contain the expected value " + expected;
+        expectContains(reason, value, expected);
+    }
+
+    /**
+     * Check if the {@code values} array contains the expected element.
+     *
+     * @param reason reason to print for failure.
+     * @param values array to check for membership in.
+     * @param expected the value to check.
+     */
+    public <T> void expectContains(String reason, T[] values, T expected) {
+        if (values == null) {
+            throw new NullPointerException();
+        }
+        checkThat(reason, expected, InMatcher.in(values));
+    }
+
+    public <T> void expectContains(T[] values, T expected) {
+        String reason = "Expected value " + expected
+                + " is not contained in the given values " + values;
+        expectContains(reason, values, expected);
+    }
+
+    /**
+     * Specialize {@link InMatcher} class for integer primitive array.
+     */
+    private static class IntInMatcher extends InMatcher<Integer> {
+        public IntInMatcher(int[] values) {
+            Preconditions.checkNotNull("values", values);
+            mValues = new ArrayList<>(values.length);
+            for (int i : values) {
+                mValues.add(i);
+            }
+        }
+    }
+
+    /**
+     * Check if the {@code values} array contains the expected element.
+     *
+     * <p>Specialized for primitive int arrays</p>
+     *
+     * @param reason reason to print for failure.
+     * @param values array to check for membership in.
+     * @param expected the value to check.
+     */
+    public void expectContains(String reason, int[] values, int expected) {
+        if (values == null) {
+            throw new NullPointerException();
+        }
+
+        checkThat(reason, expected, new IntInMatcher(values));
+    }
+
+    public void expectContains(int[] values, int expected) {
+        String reason = "Expected value " + expected
+                + " is not contained in the given values " + values;
+        expectContains(reason, values, expected);
+    }
+
+    /**
+     * Specialize {@link BooleanInMatcher} class for boolean primitive array.
+     */
+    private static class BooleanInMatcher extends InMatcher<Boolean> {
+        public BooleanInMatcher(boolean[] values) {
+            Preconditions.checkNotNull("values", values);
+            mValues = new ArrayList<>(values.length);
+            for (boolean i : values) {
+                mValues.add(i);
+            }
+        }
+    }
+
+    /**
+     * Check if the {@code values} array contains the expected element.
+     *
+     * <p>Specialized for primitive boolean arrays</p>
+     *
+     * @param reason reason to print for failure.
+     * @param values array to check for membership in.
+     * @param expected the value to check.
+     */
+    public void expectContains(String reason, boolean[] values, boolean expected) {
+        if (values == null) {
+            throw new NullPointerException();
+        }
+
+        checkThat(reason, expected, new BooleanInMatcher(values));
+    }
+
+    /**
+     * Check if the {@code values} array contains the expected element.
+     *
+     * <p>Specialized for primitive boolean arrays</p>
+     *
+     * @param values array to check for membership in.
+     * @param expected the value to check.
+     */
+    public void expectContains(boolean[] values, boolean expected) {
+        String reason = "Expected value " + expected
+                + " is not contained in the given values " + values;
+        expectContains(reason, values, expected);
+    }
+
+    /**
+     * Check if the element inside of the list are unique.
+     *
+     * @param msg The message to be logged
+     * @param list The list of values to be checked
+     */
+    public <T> void expectValuesUnique(String msg, List<T> list) {
+        Set<T> sizeSet = new HashSet<T>(list);
+        expectTrue(msg + " each element must be distinct", sizeSet.size() == list.size());
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/CameraSessionUtils.java b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/CameraSessionUtils.java
new file mode 100644
index 0000000..2506be9
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/CameraSessionUtils.java
@@ -0,0 +1,237 @@
+/*
+ * 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.helpers;
+
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CaptureFailure;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.TotalCaptureResult;
+import android.hardware.camera2.cts.CameraTestUtils;
+import android.os.Handler;
+import android.util.Log;
+import android.util.Pair;
+import android.view.Surface;
+
+import com.android.ex.camera2.blocking.BlockingCaptureCallback;
+import com.android.ex.camera2.blocking.BlockingSessionCallback;
+import com.android.ex.camera2.exceptions.TimeoutRuntimeException;
+
+import junit.framework.Assert;
+
+import org.mockito.internal.util.MockUtil;
+
+import java.util.List;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import static android.hardware.camera2.cts.helpers.Preconditions.*;
+import static org.mockito.Mockito.*;
+
+/**
+ * A utility class with common functions setting up sessions and capturing.
+ */
+public class CameraSessionUtils extends Assert {
+    private static final String TAG = "CameraSessionUtils";
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+
+    /**
+     * A blocking listener class for synchronously opening and configuring sessions.
+     */
+    public static class SessionListener extends BlockingSessionCallback {
+        private final LinkedBlockingQueue<CameraCaptureSession> mSessionQueue =
+                new LinkedBlockingQueue<>();
+
+        /**
+         * Get a new configured {@link CameraCaptureSession}.
+         *
+         * <p>
+         * This method is blocking, and will time out after
+         * {@link CameraTestUtils#SESSION_CONFIGURE_TIMEOUT_MS}.
+         * </p>
+         *
+         * @param device the {@link CameraDevice} to open a session for.
+         * @param outputs the {@link Surface} outputs to configure.
+         * @param handler the {@link Handler} to use for callbacks.
+         * @return a configured {@link CameraCaptureSession}.
+         *
+         * @throws CameraAccessException if any of the {@link CameraDevice} methods fail.
+         * @throws TimeoutRuntimeException if no result was received before the timeout.
+         */
+        public synchronized CameraCaptureSession getConfiguredSession(CameraDevice device,
+                                                                      List<Surface> outputs,
+                                                                      Handler handler)
+                throws CameraAccessException {
+            device.createCaptureSession(outputs, this, handler);
+            getStateWaiter().waitForState(SESSION_CONFIGURED,
+                    CameraTestUtils.SESSION_CONFIGURE_TIMEOUT_MS);
+            return mSessionQueue.poll();
+        }
+
+        @Override
+        public void onConfigured(CameraCaptureSession session) {
+            mSessionQueue.offer(session);
+            super.onConfigured(session);
+        }
+    }
+
+    /**
+     * A blocking listener class for synchronously capturing and results with a session.
+     */
+    public static class CaptureCallback extends BlockingCaptureCallback {
+        private final LinkedBlockingQueue<TotalCaptureResult> mResultQueue =
+                new LinkedBlockingQueue<>();
+        private final LinkedBlockingQueue<Long> mCaptureTimeQueue =
+                new LinkedBlockingQueue<>();
+
+        /**
+         * Capture a new result with the given {@link CameraCaptureSession}.
+         *
+         * <p>
+         * This method is blocking, and will time out after
+         * {@link CameraTestUtils#CAPTURE_RESULT_TIMEOUT_MS}.
+         * </p>
+         *
+         * @param session the {@link CameraCaptureSession} to use.
+         * @param request the {@link CaptureRequest} to capture with.
+         * @param handler the {@link Handler} to use for callbacks.
+         * @return a {@link Pair} containing the capture result and capture time.
+         *
+         * @throws CameraAccessException if any of the {@link CameraDevice} methods fail.
+         * @throws TimeoutRuntimeException if no result was received before the timeout.
+         */
+        public synchronized Pair<TotalCaptureResult, Long> getCapturedResult(
+                CameraCaptureSession session, CaptureRequest request, Handler handler)
+                throws CameraAccessException {
+            session.capture(request, this, handler);
+            getStateWaiter().waitForState(CAPTURE_COMPLETED,
+                    CameraTestUtils.CAPTURE_RESULT_TIMEOUT_MS);
+            return new Pair<>(mResultQueue.poll(), mCaptureTimeQueue.poll());
+        }
+
+        @Override
+        public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request,
+                                     long timestamp, long frameNumber) {
+            mCaptureTimeQueue.offer(timestamp);
+            super.onCaptureStarted(session, request, timestamp, frameNumber);
+        }
+
+        @Override
+        public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
+                                       TotalCaptureResult result) {
+            mResultQueue.offer(result);
+            super.onCaptureCompleted(session, request, result);
+        }
+    }
+
+    /**
+     * Get a mocked {@link CaptureCallback}.
+     */
+    public static CaptureCallback getMockCaptureListener() {
+        return spy(new CaptureCallback());
+    }
+
+    /**
+     * Get a mocked {@link CaptureCallback}.
+     */
+    public static SessionListener getMockSessionListener() {
+        return spy(new SessionListener());
+    }
+
+    /**
+     * Configure and return a new {@link CameraCaptureSession}.
+     *
+     * <p>
+     * This will verify that the correct session callbacks are called if a mocked listener is
+     * passed as the {@code listener} argument. This method is blocking, and will time out after
+     * {@link CameraTestUtils#SESSION_CONFIGURE_TIMEOUT_MS}.
+     * </p>
+     *
+     * @param listener a {@link SessionListener} to use for callbacks.
+     * @param device the {@link CameraDevice} to use.
+     * @param outputs the {@link Surface} outputs to configure.
+     * @param handler the {@link Handler} to call callbacks on.
+     * @return a configured {@link CameraCaptureSession}.
+     *
+     * @throws CameraAccessException if any of the {@link CameraDevice} methods fail.
+     * @throws TimeoutRuntimeException if no result was received before the timeout.
+     */
+    public static CameraCaptureSession configureAndVerifySession(SessionListener listener,
+                                                                 CameraDevice device,
+                                                                 List<Surface> outputs,
+                                                                 Handler handler)
+            throws CameraAccessException {
+        checkNotNull(listener);
+        checkNotNull(device);
+        checkNotNull(handler);
+        checkCollectionNotEmpty(outputs, "outputs");
+        checkCollectionElementsNotNull(outputs, "outputs");
+
+        CameraCaptureSession session = listener.getConfiguredSession(device, outputs, handler);
+        if (new MockUtil().isMock(listener)) {
+            verify(listener, never()).onConfigureFailed(any(CameraCaptureSession.class));
+            verify(listener, never()).onClosed(eq(session));
+            verify(listener, atLeastOnce()).onConfigured(eq(session));
+        }
+
+        checkNotNull(session);
+        return session;
+    }
+
+    /**
+     * Capture and return a new {@link TotalCaptureResult}.
+     *
+     * <p>
+     * This will verify that the correct capture callbacks are called if a mocked listener is
+     * passed as the {@code listener} argument. This method is blocking, and will time out after
+     * {@link CameraTestUtils#CAPTURE_RESULT_TIMEOUT_MS}.
+     * </p>
+     *
+     * @param listener a {@link CaptureCallback} to use for callbacks.
+     * @param session the {@link CameraCaptureSession} to use.
+     * @param request the {@link CaptureRequest} to capture with.
+     * @param handler the {@link Handler} to call callbacks on.
+     * @return a {@link Pair} containing the capture result and capture time.
+     *
+     * @throws CameraAccessException if any of the {@link CameraDevice} methods fail.
+     * @throws TimeoutRuntimeException if no result was received before the timeout.
+     */
+    public static Pair<TotalCaptureResult, Long> captureAndVerifyResult(CaptureCallback listener,
+            CameraCaptureSession session, CaptureRequest request, Handler handler)
+            throws CameraAccessException {
+        checkNotNull(listener);
+        checkNotNull(session);
+        checkNotNull(request);
+        checkNotNull(handler);
+
+        Pair<TotalCaptureResult, Long> result = listener.getCapturedResult(session, request,
+                handler);
+        if (new MockUtil().isMock(listener)) {
+            verify(listener, never()).onCaptureFailed(any(CameraCaptureSession.class),
+                    any(CaptureRequest.class), any(CaptureFailure.class));
+            verify(listener, atLeastOnce()).onCaptureStarted(eq(session), eq(request),
+                    anyLong(), anyLong());
+            verify(listener, atLeastOnce()).onCaptureCompleted(eq(session), eq(request),
+                    eq(result.first));
+        }
+
+        checkNotNull(result);
+        return result;
+    }
+
+    // Suppress default constructor for noninstantiability
+    private CameraSessionUtils() { throw new AssertionError(); }
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/InMatcher.java b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/InMatcher.java
new file mode 100644
index 0000000..aae4ac3
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/InMatcher.java
@@ -0,0 +1,70 @@
+/*
+ * 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.helpers;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Factory;
+import org.hamcrest.Matcher;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Objects;
+
+/**
+ * A {@link Matcher} class for checking if value contained in a {@link Collection} or array.
+ */
+public class InMatcher<T> extends BaseMatcher<T> {
+
+    protected Collection<T> mValues;
+
+    public InMatcher(Collection<T> values) {
+        Preconditions.checkNotNull("values", values);
+        mValues = values;
+    }
+
+    public InMatcher(T... values) {
+        Preconditions.checkNotNull(values);
+        mValues = Arrays.asList(values);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public boolean matches(Object o) {
+        T obj = (T) o;
+        for (T elem : mValues) {
+            if (Objects.equals(o, elem)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public void describeTo(Description description) {
+        description.appendText("in(").appendValue(mValues).appendText(")");
+    }
+
+    @Factory
+    public static <T> Matcher<T> in(T... operand) {
+        return new InMatcher<T>(operand);
+    }
+
+    @Factory
+    public static <T> Matcher<T> in(Collection<T> operand) {
+        return new InMatcher<T>(operand);
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/MaybeNull.java b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/MaybeNull.java
new file mode 100644
index 0000000..029ab03
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/MaybeNull.java
@@ -0,0 +1,76 @@
+/*
+ * 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.helpers;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+/**
+ * Helper set of methods for dealing with objects that are sometimes {@code null}.
+ *
+ * <p>Used to remove common patterns like: <pre>{@code
+ * if (obj != null) {
+ *     obj.doSomething();
+ * }</pre>
+ *
+ * If this is common, consider adding {@code doSomething} to this class so that the code
+ * looks more like <pre>{@code
+ * MaybeNull.doSomething(obj);
+ * }</pre>
+ */
+public class MaybeNull {
+    /**
+     * Close the underlying {@link AutoCloseable}, if it's not {@code null}.
+     *
+     * @param closeable An object which implements {@link AutoCloseable}.
+     * @throws Exception If {@link AutoCloseable#close} fails.
+     */
+    public static <T extends AutoCloseable> void close(T closeable) throws Exception {
+        if (closeable != null) {
+            closeable.close();
+        }
+    }
+
+    /**
+     * Close the underlying {@link UncheckedCloseable}, if it's not {@code null}.
+     *
+     * <p>No checked exceptions are thrown. An unknown runtime exception might still
+     * be raised.</p>
+     *
+     * @param closeable An object which implements {@link UncheckedCloseable}.
+     */
+    public static <T extends UncheckedCloseable> void close(T closeable) {
+        if (closeable != null) {
+            closeable.close();
+        }
+    }
+
+    /**
+     * Close the underlying {@link Closeable}, if it's not {@code null}.
+     *
+     * @param closeable An object which implements {@link Closeable}.
+     * @throws Exception If {@link Closeable#close} fails.
+     */
+    public static <T extends Closeable> void close(T closeable) throws IOException {
+        if (closeable != null) {
+            closeable.close();
+        }
+    }
+
+    // Suppress default constructor for noninstantiability
+    private MaybeNull() { throw new AssertionError(); }
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/Preconditions.java b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/Preconditions.java
new file mode 100644
index 0000000..cb9e522
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/Preconditions.java
@@ -0,0 +1,180 @@
+/*
+ * 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.helpers;
+
+import java.util.Collection;
+import java.util.Objects;
+
+/**
+ * Helper set of methods to perform precondition checks before starting method execution.
+ *
+ * <p>Typically used to sanity check arguments or the current object state.</p>
+ */
+public final class Preconditions {
+
+    /**
+     * Checks that the value has the expected bitwise flags set.
+     *
+     * @param argName Name of the argument
+     * @param arg Argument to check
+     * @param flagsName Name of the bitwise flags
+     * @param flags Bit flags to check.
+     * @return arg
+     *
+     * @throws IllegalArgumentException if the bitwise flags weren't set
+     */
+    public static int checkBitFlags(String argName, int arg, String flagsName, int flags) {
+        if ((arg & flags) == 0) {
+            throw new IllegalArgumentException(
+                    String.format("Argument '%s' must have flags '%s' set", argName, flagsName));
+        }
+
+        return arg;
+    }
+
+    /**
+     * Checks that the value is {@link Object#equals equal} to the expected value.
+     *
+     * @param argName Name of the argument
+     * @param arg Argument to check
+     * @param expectedName Name of the expected value
+     * @param expectedValue Expected value
+     * @return arg
+     *
+     * @throws IllegalArgumentException if the values were not equal
+     */
+    public static <T> T checkEquals(String argName, T arg,
+            String expectedName, T expectedValue) {
+        if (!Objects.equals(arg, expectedValue)) {
+            throw new IllegalArgumentException(
+                    String.format(
+                            "Argument '%s' must be equal to '%s' (was '%s', but expected '%s')",
+                            argName, expectedName, arg, expectedValue));
+        }
+
+        return arg;
+    }
+
+    /**
+     * Checks that the value is not {@code null}.
+     *
+     * <p>
+     * Returns the value directly, so you can use {@code checkNotNull("value", value)} inline.
+     * </p>
+     *
+     * @param argName Name of the argument
+     * @param arg Argument to check
+     * @return arg
+     *
+     * @throws NullPointerException if arg was {@code null}
+     */
+    public static <T> T checkNotNull(String argName, T arg) {
+        if (arg == null) {
+            throw new NullPointerException("Argument '" + argName + "' must not be null");
+        }
+
+        return arg;
+    }
+
+    /**
+     * Checks that the value is not {@code null}.
+     *
+     * <p>
+     * Returns the value directly, so you can use {@code checkNotNull("value", value)} inline.
+     * </p>
+     *
+     * @param arg Argument to check
+     * @return arg
+     *
+     * @throws NullPointerException if arg was {@code null}
+     */
+    public static <T> T checkNotNull(T arg) {
+        return checkNotNull("", arg);
+    }
+
+    /**
+     * Checks that the state is currently {@link true}.
+     *
+     * @param message Message to raise an exception with if the state checking fails.
+     * @param state State to check
+     *
+     * @throws IllegalStateException if state was {@code false}
+     *
+     * @return The state value (always {@code true}).
+     */
+    public static boolean checkState(String message, boolean state) {
+        if (!state) {
+            throw new IllegalStateException(message);
+        }
+
+        return state;
+    }
+
+        /**
+     * Ensures that the {@link Collection} is not {@code null}, and none of its elements are
+     * {@code null}.
+     *
+     * @param value a {@link Collection} of boxed objects
+     * @param valueName the name of the argument to use if the check fails
+     *
+     * @return the validated {@link Collection}
+     *
+     * @throws NullPointerException if the {@code value} or any of its elements were {@code null}
+     */
+    public static <T> Collection<T> checkCollectionElementsNotNull(final Collection<T> value,
+            final String valueName) {
+        if (value == null) {
+            throw new NullPointerException(valueName + " must not be null");
+        }
+
+        long ctr = 0;
+        for (T elem : value) {
+            if (elem == null) {
+                throw new NullPointerException(
+                        String.format("%s[%d] must not be null", valueName, ctr));
+            }
+            ++ctr;
+        }
+
+        return value;
+    }
+
+    /**
+     * Ensures that the {@link Collection} is not {@code null}, and contains at least one element.
+     *
+     * @param value a {@link Collection} of boxed elements.
+     * @param valueName the name of the argument to use if the check fails.
+
+     * @return the validated {@link Collection}
+     *
+     * @throws NullPointerException if the {@code value} was {@code null}
+     * @throws IllegalArgumentException if the {@code value} was empty
+     */
+    public static <T> Collection<T> checkCollectionNotEmpty(final Collection<T> value,
+            final String valueName) {
+        if (value == null) {
+            throw new NullPointerException(valueName + " must not be null");
+        }
+        if (value.isEmpty()) {
+            throw new IllegalArgumentException(valueName + " is empty");
+        }
+        return value;
+    }
+
+    // Suppress default constructor for noninstantiability
+    private Preconditions() { throw new AssertionError(); }
+}
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
new file mode 100644
index 0000000..a5c7083
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
@@ -0,0 +1,1939 @@
+/*
+ * 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.helpers;
+
+import android.graphics.Rect;
+import android.graphics.ImageFormat;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraCharacteristics.Key;
+import android.hardware.camera2.CameraMetadata;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.cts.CameraTestUtils;
+import android.hardware.camera2.params.StreamConfigurationMap;
+import android.util.Range;
+import android.util.Size;
+import android.util.Log;
+import android.util.Rational;
+
+import junit.framework.Assert;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Helpers to get common static info out of the camera.
+ *
+ * <p>Avoid boiler plate by putting repetitive get/set patterns in this class.</p>
+ *
+ * <p>Attempt to be durable against the camera device having bad or missing metadata
+ * by providing reasonable defaults and logging warnings when that happens.</p>
+ */
+public class StaticMetadata {
+
+    private static final String TAG = "StaticMetadata";
+    private static final int IGNORE_SIZE_CHECK = -1;
+
+    private static final long SENSOR_INFO_EXPOSURE_TIME_RANGE_MIN_AT_MOST = 100000L; // 100us
+    private static final long SENSOR_INFO_EXPOSURE_TIME_RANGE_MAX_AT_LEAST = 100000000; // 100ms
+    private static final int SENSOR_INFO_SENSITIVITY_RANGE_MIN_AT_MOST = 100;
+    private static final int SENSOR_INFO_SENSITIVITY_RANGE_MAX_AT_LEAST = 800;
+    private static final int STATISTICS_INFO_MAX_FACE_COUNT_MIN_AT_LEAST = 4;
+    private static final int TONEMAP_MAX_CURVE_POINTS_AT_LEAST = 64;
+    private static final int CONTROL_AE_COMPENSATION_RANGE_DEFAULT_MIN = -2;
+    private static final int CONTROL_AE_COMPENSATION_RANGE_DEFAULT_MAX = 2;
+    private static final Rational CONTROL_AE_COMPENSATION_STEP_DEFAULT = new Rational(1, 2);
+    private static final byte REQUEST_PIPELINE_MAX_DEPTH_MAX = 8;
+
+    // TODO: Consider making this work across any metadata object, not just camera characteristics
+    private final CameraCharacteristics mCharacteristics;
+    private final CheckLevel mLevel;
+    private final CameraErrorCollector mCollector;
+
+    public enum CheckLevel {
+        /** Only log warnings for metadata check failures. Execution continues. */
+        WARN,
+        /**
+         * Use ErrorCollector to collect the metadata check failures, Execution
+         * continues.
+         */
+        COLLECT,
+        /** Assert the metadata check failures. Execution aborts. */
+        ASSERT
+    }
+
+    /**
+     * Construct a new StaticMetadata object.
+     *
+     *<p> Default constructor, only log warnings for the static metadata check failures</p>
+     *
+     * @param characteristics static info for a camera
+     * @throws IllegalArgumentException if characteristics was null
+     */
+    public StaticMetadata(CameraCharacteristics characteristics) {
+        this(characteristics, CheckLevel.WARN, /*collector*/null);
+    }
+
+    /**
+     * Construct a new StaticMetadata object with {@link CameraErrorCollector}.
+     * <p>
+     * When level is not {@link CheckLevel.COLLECT}, the {@link CameraErrorCollector} will be
+     * ignored, otherwise, it will be used to log the check failures.
+     * </p>
+     *
+     * @param characteristics static info for a camera
+     * @param collector The {@link CameraErrorCollector} used by this StaticMetadata
+     * @throws IllegalArgumentException if characteristics or collector was null.
+     */
+    public StaticMetadata(CameraCharacteristics characteristics, CameraErrorCollector collector) {
+        this(characteristics, CheckLevel.COLLECT, collector);
+    }
+
+    /**
+     * Construct a new StaticMetadata object with {@link CheckLevel} and
+     * {@link CameraErrorCollector}.
+     * <p>
+     * When level is not {@link CheckLevel.COLLECT}, the {@link CameraErrorCollector} will be
+     * ignored, otherwise, it will be used to log the check failures.
+     * </p>
+     *
+     * @param characteristics static info for a camera
+     * @param level The {@link CheckLevel} of this StaticMetadata
+     * @param collector The {@link CameraErrorCollector} used by this StaticMetadata
+     * @throws IllegalArgumentException if characteristics was null or level was
+     *         {@link CheckLevel.COLLECT} but collector was null.
+     */
+    public StaticMetadata(CameraCharacteristics characteristics, CheckLevel level,
+            CameraErrorCollector collector) {
+        if (characteristics == null) {
+            throw new IllegalArgumentException("characteristics was null");
+        }
+        if (level == CheckLevel.COLLECT && collector == null) {
+            throw new IllegalArgumentException("collector must valid when COLLECT level is set");
+        }
+
+        mCharacteristics = characteristics;
+        mLevel = level;
+        mCollector = collector;
+    }
+
+    /**
+     * Get the CameraCharacteristics associated with this StaticMetadata.
+     *
+     * @return A non-null CameraCharacteristics object
+     */
+    public CameraCharacteristics getCharacteristics() {
+        return mCharacteristics;
+    }
+
+    /**
+     * Whether or not the hardware level reported by android.info.supportedHardwareLevel
+     * is {@value CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL}.
+     *
+     * <p>If the camera device is not reporting the hardwareLevel, this
+     * will cause the test to fail.</p>
+     *
+     * @return {@code true} if the device is {@code FULL}, {@code false} otherwise.
+     */
+    public boolean isHardwareLevelFull() {
+        return getHardwareLevelChecked() == CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_FULL;
+    }
+
+    /**
+     * Whether or not the hardware level reported by android.info.supportedHardwareLevel
+     * Return the supported hardware level of the device, or fail if no value is reported.
+     *
+     * @return the supported hardware level as a constant defined for
+     *      {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}.
+     */
+    public int getHardwareLevelChecked() {
+        Integer hwLevel = getValueFromKeyNonNull(
+                CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
+        if (hwLevel == null) {
+            Assert.fail("No supported hardware level reported.");
+        }
+        return hwLevel;
+    }
+
+    /**
+     * Whether or not the hardware level reported by android.info.supportedHardwareLevel
+     * is {@value CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY}.
+     *
+     * <p>If the camera device is not reporting the hardwareLevel, this
+     * will cause the test to fail.</p>
+     *
+     * @return {@code true} if the device is {@code LEGACY}, {@code false} otherwise.
+     */
+    public boolean isHardwareLevelLegacy() {
+        return getHardwareLevelChecked() == CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY;
+    }
+
+    /**
+     * Whether or not the per frame control is supported by the camera device.
+     *
+     * @return {@code true} if per frame control is supported, {@code false} otherwise.
+     */
+    public boolean isPerFrameControlSupported() {
+        return getSyncMaxLatency() == CameraMetadata.SYNC_MAX_LATENCY_PER_FRAME_CONTROL;
+    }
+
+    /**
+     * Get the maximum number of frames to wait for a request settings being applied
+     *
+     * @return CameraMetadata.SYNC_MAX_LATENCY_UNKNOWN for unknown latency
+     *         CameraMetadata.SYNC_MAX_LATENCY_PER_FRAME_CONTROL for per frame control
+     *         a positive int otherwise
+     */
+    public int getSyncMaxLatency() {
+        Integer value = getValueFromKeyNonNull(CameraCharacteristics.SYNC_MAX_LATENCY);
+        if (value == null) {
+            return CameraMetadata.SYNC_MAX_LATENCY_UNKNOWN;
+        }
+        return value;
+    }
+
+    /**
+     * Whether or not the hardware level reported by android.info.supportedHardwareLevel
+     * is {@value CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED}.
+     *
+     * <p>If the camera device is incorrectly reporting the hardwareLevel, this
+     * will always return {@code true}.</p>
+     *
+     * @return {@code true} if the device is {@code LIMITED}, {@code false} otherwise.
+     */
+    public boolean isHardwareLevelLimited() {
+        return getHardwareLevelChecked() == CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
+    }
+
+    /**
+     * Whether or not the hardware level reported by {@code android.info.supportedHardwareLevel}
+     * is at least {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED}.
+     *
+     * <p>If the camera device is incorrectly reporting the hardwareLevel, this
+     * will always return {@code false}.</p>
+     *
+     * @return
+     *          {@code true} if the device is {@code LIMITED} or {@code FULL},
+     *          {@code false} otherwise (i.e. LEGACY).
+     */
+    public boolean isHardwareLevelLimitedOrBetter() {
+        Integer hwLevel = getValueFromKeyNonNull(
+                CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
+
+        if (hwLevel == null) {
+            return false;
+        }
+
+        // Normal. Device could be limited.
+        int hwLevelInt = hwLevel;
+        return hwLevelInt == CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_FULL ||
+                hwLevelInt == CameraMetadata.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED;
+    }
+
+    /**
+     * Get the maximum number of partial result a request can expect
+     *
+     * @return 1 if partial result is not supported.
+     *         a integer value larger than 1 if partial result is supported.
+     */
+    public int getPartialResultCount() {
+        Integer value = mCharacteristics.get(CameraCharacteristics.REQUEST_PARTIAL_RESULT_COUNT);
+        if (value == null) {
+            // Optional key. Default value is 1 if key is missing.
+            return 1;
+        }
+        return value;
+    }
+
+    /**
+     * Get the exposure time value and clamp to the range if needed.
+     *
+     * @param exposure Input exposure time value to check.
+     * @return Exposure value in the legal range.
+     */
+    public long getExposureClampToRange(long exposure) {
+        long minExposure = getExposureMinimumOrDefault(Long.MAX_VALUE);
+        long maxExposure = getExposureMaximumOrDefault(Long.MIN_VALUE);
+        if (minExposure > SENSOR_INFO_EXPOSURE_TIME_RANGE_MIN_AT_MOST) {
+            failKeyCheck(CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE,
+                    String.format(
+                    "Min value %d is too large, set to maximal legal value %d",
+                    minExposure, SENSOR_INFO_EXPOSURE_TIME_RANGE_MIN_AT_MOST));
+            minExposure = SENSOR_INFO_EXPOSURE_TIME_RANGE_MIN_AT_MOST;
+        }
+        if (maxExposure < SENSOR_INFO_EXPOSURE_TIME_RANGE_MAX_AT_LEAST) {
+            failKeyCheck(CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE,
+                    String.format(
+                    "Max value %d is too small, set to minimal legal value %d",
+                    maxExposure, SENSOR_INFO_EXPOSURE_TIME_RANGE_MAX_AT_LEAST));
+            maxExposure = SENSOR_INFO_EXPOSURE_TIME_RANGE_MAX_AT_LEAST;
+        }
+
+        return Math.max(minExposure, Math.min(maxExposure, exposure));
+    }
+
+    /**
+     * Check if the camera device support focuser.
+     *
+     * @return true if camera device support focuser, false otherwise.
+     */
+    public boolean hasFocuser() {
+        if (areKeysAvailable(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE)) {
+            // LEGACY devices don't have lens.info.minimumFocusDistance, so guard this query
+            return (getMinimumFocusDistanceChecked() > 0);
+        } else {
+            // Check available AF modes
+            int[] availableAfModes = mCharacteristics.get(
+                    CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES);
+
+            if (availableAfModes == null) {
+                return false;
+            }
+
+            // Assume that if we have an AF mode which doesn't ignore AF trigger, we have a focuser
+            boolean hasFocuser = false;
+            loop: for (int mode : availableAfModes) {
+                switch (mode) {
+                    case CameraMetadata.CONTROL_AF_MODE_AUTO:
+                    case CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_PICTURE:
+                    case CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_VIDEO:
+                    case CameraMetadata.CONTROL_AF_MODE_MACRO:
+                        hasFocuser = true;
+                        break loop;
+                }
+            }
+
+            return hasFocuser;
+        }
+    }
+
+    /**
+     * Check if the camera device has flash unit.
+     * @return true if flash unit is available, false otherwise.
+     */
+    public boolean hasFlash() {
+        return getFlashInfoChecked();
+    }
+
+    /**
+     * Get minimum focus distance.
+     *
+     * @return minimum focus distance, 0 if minimum focus distance is invalid.
+     */
+    public float getMinimumFocusDistanceChecked() {
+        Key<Float> key = CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE;
+        Float minFocusDistance;
+
+        /**
+         * android.lens.info.minimumFocusDistance - required for FULL and MANUAL_SENSOR-capable
+         *   devices; optional for all other devices.
+         */
+        if (isHardwareLevelFull() || isCapabilitySupported(
+                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
+            minFocusDistance = getValueFromKeyNonNull(key);
+        } else {
+            minFocusDistance = mCharacteristics.get(key);
+        }
+
+        if (minFocusDistance == null) {
+            return 0.0f;
+        }
+
+        checkTrueForKey(key, " minFocusDistance value shouldn't be negative",
+                minFocusDistance >= 0);
+        if (minFocusDistance < 0) {
+            minFocusDistance = 0.0f;
+        }
+
+        return minFocusDistance;
+    }
+
+    /**
+     * Get focusDistanceCalibration.
+     *
+     * @return focusDistanceCalibration, UNCALIBRATED if value is invalid.
+     */
+    public int getFocusDistanceCalibrationChecked() {
+        Key<Integer> key = CameraCharacteristics.LENS_INFO_FOCUS_DISTANCE_CALIBRATION;
+        Integer calibration = getValueFromKeyNonNull(key);
+
+        if (calibration == null) {
+            return CameraMetadata.LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED;
+        }
+
+        checkTrueForKey(key, " value is out of range" ,
+                calibration >= CameraMetadata.LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED &&
+                calibration <= CameraMetadata.LENS_INFO_FOCUS_DISTANCE_CALIBRATION_CALIBRATED);
+
+        return calibration;
+    }
+
+    /**
+     * Get max AE regions and do sanity check.
+     *
+     * @return AE max regions supported by the camera device
+     */
+    public int getAeMaxRegionsChecked() {
+        Integer regionCount = getValueFromKeyNonNull(CameraCharacteristics.CONTROL_MAX_REGIONS_AE);
+        if (regionCount == null) {
+            return 0;
+        }
+        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 int[] getAeAvailableAntiBandingModesChecked() {
+        Key<int[]> key = CameraCharacteristics.CONTROL_AE_AVAILABLE_ANTIBANDING_MODES;
+        int[] modes = getValueFromKeyNonNull(key);
+
+        boolean foundAuto = false;
+        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);
+            if (mode == CameraMetadata.CONTROL_AE_ANTIBANDING_MODE_AUTO) {
+                foundAuto = true;
+                return modes;
+            }
+        }
+        // Must contain AUTO mode.
+        checkTrueForKey(key, "AUTO mode is missing", foundAuto);
+
+        return modes;
+    }
+
+    /**
+     * Check if the antibanding OFF mode is supported.
+     *
+     * @return true if antibanding OFF mode is supported, false otherwise.
+     */
+    public boolean isAntiBandingOffModeSupported() {
+        List<Integer> antiBandingModes =
+                Arrays.asList(CameraTestUtils.toObject(getAeAvailableAntiBandingModesChecked()));
+
+        return antiBandingModes.contains(CameraMetadata.CONTROL_AE_ANTIBANDING_MODE_OFF);
+    }
+
+    public Boolean getFlashInfoChecked() {
+        Key<Boolean> key = CameraCharacteristics.FLASH_INFO_AVAILABLE;
+        Boolean hasFlash = getValueFromKeyNonNull(key);
+
+        // In case the failOnKey only gives warning.
+        if (hasFlash == null) {
+            return false;
+        }
+
+        return hasFlash;
+    }
+
+    public int[] getAvailableTestPatternModesChecked() {
+        Key<int[]> key =
+                CameraCharacteristics.SENSOR_AVAILABLE_TEST_PATTERN_MODES;
+        int[] modes = getValueFromKeyNonNull(key);
+
+        if (modes == null) {
+            return new int[0];
+        }
+
+        int expectValue = CameraCharacteristics.SENSOR_TEST_PATTERN_MODE_OFF;
+        Integer[] boxedModes = CameraTestUtils.toObject(modes);
+        checkTrueForKey(key, " value must contain OFF mode",
+                Arrays.asList(boxedModes).contains(expectValue));
+
+        return modes;
+    }
+
+    /**
+     * Get available thumbnail sizes and do the sanity check.
+     *
+     * @return The array of available thumbnail sizes
+     */
+    public Size[] getAvailableThumbnailSizesChecked() {
+        Key<Size[]> key = CameraCharacteristics.JPEG_AVAILABLE_THUMBNAIL_SIZES;
+        Size[] sizes = getValueFromKeyNonNull(key);
+        final List<Size> sizeList = Arrays.asList(sizes);
+
+        // Size must contain (0, 0).
+        checkTrueForKey(key, "size should contain (0, 0)", sizeList.contains(new Size(0, 0)));
+
+        // Each size must be distinct.
+        checkElementDistinct(key, sizeList);
+
+        // Must be sorted in ascending order by area, by width if areas are same.
+        List<Size> orderedSizes =
+                CameraTestUtils.getAscendingOrderSizes(sizeList, /*ascending*/true);
+        checkTrueForKey(key, "Sizes should be in ascending order: Original " + sizeList.toString()
+                + ", Expected " + orderedSizes.toString(), orderedSizes.equals(sizeList));
+
+        // TODO: Aspect ratio match, need wait for android.scaler.availableStreamConfigurations
+        // implementation see b/12958122.
+
+        return sizes;
+    }
+
+    /**
+     * Get available focal lengths and do the sanity check.
+     *
+     * @return The array of available focal lengths
+     */
+    public float[] getAvailableFocalLengthsChecked() {
+        Key<float[]> key = CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS;
+        float[] focalLengths = getValueFromKeyNonNull(key);
+
+        checkTrueForKey(key, "Array should contain at least one element", focalLengths.length >= 1);
+
+        for (int i = 0; i < focalLengths.length; i++) {
+            checkTrueForKey(key,
+                    String.format("focalLength[%d] %f should be positive.", i, focalLengths[i]),
+                    focalLengths[i] > 0);
+        }
+        checkElementDistinct(key, Arrays.asList(CameraTestUtils.toObject(focalLengths)));
+
+        return focalLengths;
+    }
+
+    /**
+     * Get available apertures and do the sanity check.
+     *
+     * @return The non-null array of available apertures
+     */
+    public float[] getAvailableAperturesChecked() {
+        Key<float[]> key = CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES;
+        float[] apertures = getValueFromKeyNonNull(key);
+
+        checkTrueForKey(key, "Array should contain at least one element", apertures.length >= 1);
+
+        for (int i = 0; i < apertures.length; i++) {
+            checkTrueForKey(key,
+                    String.format("apertures[%d] %f should be positive.", i, apertures[i]),
+                    apertures[i] > 0);
+        }
+        checkElementDistinct(key, Arrays.asList(CameraTestUtils.toObject(apertures)));
+
+        return apertures;
+    }
+
+    /**
+     * Get and check the available hot pixel map modes.
+     *
+     * @return the available hot pixel map modes
+     */
+    public int[] getAvailableHotPixelModesChecked() {
+        Key<int[]> key = CameraCharacteristics.HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES;
+        int[] modes = getValueFromKeyNonNull(key);
+
+        if (modes == null) {
+            return new int[0];
+        }
+
+        List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes));
+        if (isHardwareLevelFull()) {
+            checkTrueForKey(key, "Full-capability camera devices must support FAST mode",
+                    modeList.contains(CameraMetadata.HOT_PIXEL_MODE_FAST));
+        }
+        checkElementDistinct(key, modeList);
+        checkArrayValuesInRange(key, modes, CameraMetadata.HOT_PIXEL_MODE_OFF,
+                CameraMetadata.HOT_PIXEL_MODE_HIGH_QUALITY);
+
+        return modes;
+    }
+
+    /**
+     * Get and check available face detection modes.
+     *
+     * @return The non-null array of available face detection modes
+     */
+    public int[] getAvailableFaceDetectModesChecked() {
+        Key<int[]> key = CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES;
+        int[] modes = getValueFromKeyNonNull(key);
+
+        if (modes == null) {
+            return new int[0];
+        }
+
+        List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes));
+        checkTrueForKey(key, "Array should contain OFF mode",
+                modeList.contains(CameraMetadata.STATISTICS_FACE_DETECT_MODE_OFF));
+        checkElementDistinct(key, modeList);
+        checkArrayValuesInRange(key, modes, CameraMetadata.STATISTICS_FACE_DETECT_MODE_OFF,
+                CameraMetadata.STATISTICS_FACE_DETECT_MODE_FULL);
+
+        return modes;
+    }
+
+    /**
+     * Get and check max face detected count.
+     *
+     * @return max number of faces that can be detected
+     */
+    public int getMaxFaceCountChecked() {
+        Key<Integer> key = CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT;
+        Integer count = getValueFromKeyNonNull(key);
+
+        if (count == null) {
+            return 0;
+        }
+
+        List<Integer> faceDetectModes =
+                Arrays.asList(CameraTestUtils.toObject(getAvailableFaceDetectModesChecked()));
+        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);
+        } else {
+            int maxFaceCountAtLeast = STATISTICS_INFO_MAX_FACE_COUNT_MIN_AT_LEAST;
+
+            // Legacy mode may support fewer than STATISTICS_INFO_MAX_FACE_COUNT_MIN_AT_LEAST faces.
+            if (isHardwareLevelLegacy()) {
+                maxFaceCountAtLeast = 1;
+            }
+            checkTrueForKey(key, " value must be no less than " + maxFaceCountAtLeast + " if SIMPLE"
+                    + "or FULL is also supported in availableFaceDetectionModes",
+                    count >= maxFaceCountAtLeast);
+        }
+
+        return count;
+    }
+
+    /**
+     * Get and check the available tone map modes.
+     *
+     * @return the available tone map modes
+     */
+    public int[] getAvailableToneMapModesChecked() {
+        Key<int[]> key = CameraCharacteristics.TONEMAP_AVAILABLE_TONE_MAP_MODES;
+        int[] modes = getValueFromKeyNonNull(key);
+
+        if (modes == null) {
+            return new int[0];
+        }
+
+        List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes));
+        checkTrueForKey(key, " Camera devices must always support FAST mode",
+                modeList.contains(CameraMetadata.TONEMAP_MODE_FAST));
+        if (isHardwareLevelFull()) {
+            checkTrueForKey(key, "Full-capability camera devices must support"
+                    + "CONTRAST_CURVE mode",
+                    modeList.contains(CameraMetadata.TONEMAP_MODE_CONTRAST_CURVE) &&
+                    modeList.contains(CameraMetadata.TONEMAP_MODE_FAST));
+        }
+        checkElementDistinct(key, modeList);
+        checkArrayValuesInRange(key, modes, CameraMetadata.TONEMAP_MODE_CONTRAST_CURVE,
+                CameraMetadata.TONEMAP_MODE_HIGH_QUALITY);
+
+        return modes;
+    }
+
+    /**
+     * Get and check max tonemap curve point.
+     *
+     * @return Max tonemap curve points.
+     */
+    public int getMaxTonemapCurvePointChecked() {
+        Key<Integer> key = CameraCharacteristics.TONEMAP_MAX_CURVE_POINTS;
+        Integer count = getValueFromKeyNonNull(key);
+
+        if (count == null) {
+            return 0;
+        }
+
+        List<Integer> modeList =
+                Arrays.asList(CameraTestUtils.toObject(getAvailableToneMapModesChecked()));
+        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);
+        }
+
+        return count;
+    }
+
+    /**
+     * Get and check pixel array size.
+     */
+    public Size getPixelArraySizeChecked() {
+        Key<Size> key = CameraCharacteristics.SENSOR_INFO_PIXEL_ARRAY_SIZE;
+        Size pixelArray = getValueFromKeyNonNull(key);
+        if (pixelArray == null) {
+            return new Size(0, 0);
+        }
+
+        return pixelArray;
+    }
+
+    /**
+     * Get and check active array size.
+     */
+    public Rect getActiveArraySizeChecked() {
+        Key<Rect> key = CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE;
+        Rect activeArray = getValueFromKeyNonNull(key);
+
+        if (activeArray == null) {
+            return new Rect(0, 0, 0, 0);
+        }
+
+        Size pixelArraySize = getPixelArraySizeChecked();
+        checkTrueForKey(key, "values left/top are invalid", activeArray.left >= 0 && activeArray.top >= 0);
+        checkTrueForKey(key, "values width/height are invalid",
+                activeArray.width() <= pixelArraySize.getWidth() &&
+                activeArray.height() <= pixelArraySize.getHeight());
+
+        return activeArray;
+    }
+
+    /**
+     * Get the sensitivity value and clamp to the range if needed.
+     *
+     * @param sensitivity Input sensitivity value to check.
+     * @return Sensitivity value in legal range.
+     */
+    public int getSensitivityClampToRange(int sensitivity) {
+        int minSensitivity = getSensitivityMinimumOrDefault(Integer.MAX_VALUE);
+        int maxSensitivity = getSensitivityMaximumOrDefault(Integer.MIN_VALUE);
+        if (minSensitivity > SENSOR_INFO_SENSITIVITY_RANGE_MIN_AT_MOST) {
+            failKeyCheck(CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE,
+                    String.format(
+                    "Min value %d is too large, set to maximal legal value %d",
+                    minSensitivity, SENSOR_INFO_SENSITIVITY_RANGE_MIN_AT_MOST));
+            minSensitivity = SENSOR_INFO_SENSITIVITY_RANGE_MIN_AT_MOST;
+        }
+        if (maxSensitivity < SENSOR_INFO_SENSITIVITY_RANGE_MAX_AT_LEAST) {
+            failKeyCheck(CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE,
+                    String.format(
+                    "Max value %d is too small, set to minimal legal value %d",
+                    maxSensitivity, SENSOR_INFO_SENSITIVITY_RANGE_MAX_AT_LEAST));
+            maxSensitivity = SENSOR_INFO_SENSITIVITY_RANGE_MAX_AT_LEAST;
+        }
+
+        return Math.max(minSensitivity, Math.min(maxSensitivity, sensitivity));
+    }
+
+    /**
+     * Get maxAnalogSensitivity for a camera device.
+     * <p>
+     * This is only available for FULL capability device, return 0 if it is unavailable.
+     * </p>
+     *
+     * @return maxAnalogSensitivity, 0 if it is not available.
+     */
+    public int getMaxAnalogSensitivityChecked() {
+
+        Key<Integer> key = CameraCharacteristics.SENSOR_MAX_ANALOG_SENSITIVITY;
+        Integer maxAnalogsensitivity = mCharacteristics.get(key);
+        if (maxAnalogsensitivity == null) {
+            if (isHardwareLevelFull()) {
+                Assert.fail("Full device should report max analog sensitivity");
+            }
+            return 0;
+        }
+
+        int minSensitivity = getSensitivityMinimumOrDefault();
+        int maxSensitivity = getSensitivityMaximumOrDefault();
+        checkTrueForKey(key, " Max analog sensitivity " + maxAnalogsensitivity
+                + " should be no larger than max sensitivity " + maxSensitivity,
+                maxAnalogsensitivity <= maxSensitivity);
+        checkTrueForKey(key, " Max analog sensitivity " + maxAnalogsensitivity
+                + " should be larger than min sensitivity " + maxSensitivity,
+                maxAnalogsensitivity > minSensitivity);
+
+        return maxAnalogsensitivity;
+    }
+
+    /**
+     * Get hyperfocalDistance and do the sanity check.
+     * <p>
+     * Note that, this tag is optional, will return -1 if this tag is not
+     * available.
+     * </p>
+     *
+     * @return hyperfocalDistance of this device, -1 if this tag is not available.
+     */
+    public float getHyperfocalDistanceChecked() {
+        Key<Float> key = CameraCharacteristics.LENS_INFO_HYPERFOCAL_DISTANCE;
+        Float hyperfocalDistance = getValueFromKeyNonNull(key);
+        if (hyperfocalDistance == null) {
+            return -1;
+        }
+
+        if (hasFocuser()) {
+            float minFocusDistance = getMinimumFocusDistanceChecked();
+            checkTrueForKey(key, String.format(" hyperfocal distance %f should be in the range of"
+                    + " should be in the range of (%f, %f]", hyperfocalDistance, 0.0f,
+                    minFocusDistance),
+                    hyperfocalDistance > 0 && hyperfocalDistance <= minFocusDistance);
+        }
+
+        return hyperfocalDistance;
+    }
+
+    /**
+     * Get the minimum value for a sensitivity range from android.sensor.info.sensitivityRange.
+     *
+     * <p>If the camera is incorrectly reporting values, log a warning and return
+     * the default value instead, which is the largest minimum value required to be supported
+     * by all camera devices.</p>
+     *
+     * @return The value reported by the camera device or the defaultValue otherwise.
+     */
+    public int getSensitivityMinimumOrDefault() {
+        return getSensitivityMinimumOrDefault(SENSOR_INFO_SENSITIVITY_RANGE_MIN_AT_MOST);
+    }
+
+    /**
+     * Get the minimum value for a sensitivity range from android.sensor.info.sensitivityRange.
+     *
+     * <p>If the camera is incorrectly reporting values, log a warning and return
+     * the default value instead.</p>
+     *
+     * @param defaultValue Value to return if no legal value is available
+     * @return The value reported by the camera device or the defaultValue otherwise.
+     */
+    public int getSensitivityMinimumOrDefault(int defaultValue) {
+        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();
+    }
+
+    /**
+     * Get the maximum value for a sensitivity range from android.sensor.info.sensitivityRange.
+     *
+     * <p>If the camera is incorrectly reporting values, log a warning and return
+     * the default value instead, which is the smallest maximum value required to be supported
+     * by all camera devices.</p>
+     *
+     * @return The value reported by the camera device or the defaultValue otherwise.
+     */
+    public int getSensitivityMaximumOrDefault() {
+        return getSensitivityMaximumOrDefault(SENSOR_INFO_SENSITIVITY_RANGE_MAX_AT_LEAST);
+    }
+
+    /**
+     * Get the maximum value for a sensitivity range from android.sensor.info.sensitivityRange.
+     *
+     * <p>If the camera is incorrectly reporting values, log a warning and return
+     * the default value instead.</p>
+     *
+     * @param defaultValue Value to return if no legal value is available
+     * @return The value reported by the camera device or the defaultValue otherwise.
+     */
+    public int getSensitivityMaximumOrDefault(int defaultValue) {
+        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();
+    }
+
+    /**
+     * Get the minimum value for an exposure range from android.sensor.info.exposureTimeRange.
+     *
+     * <p>If the camera is incorrectly reporting values, log a warning and return
+     * the default value instead.</p>
+     *
+     * @param defaultValue Value to return if no legal value is available
+     * @return The value reported by the camera device or the defaultValue otherwise.
+     */
+    public long getExposureMinimumOrDefault(long defaultValue) {
+        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();
+    }
+
+    /**
+     * Get the minimum value for an exposure range from android.sensor.info.exposureTimeRange.
+     *
+     * <p>If the camera is incorrectly reporting values, log a warning and return
+     * the default value instead, which is the largest minimum value required to be supported
+     * by all camera devices.</p>
+     *
+     * @return The value reported by the camera device or the defaultValue otherwise.
+     */
+    public long getExposureMinimumOrDefault() {
+        return getExposureMinimumOrDefault(SENSOR_INFO_EXPOSURE_TIME_RANGE_MIN_AT_MOST);
+    }
+
+    /**
+     * Get the maximum value for an exposure range from android.sensor.info.exposureTimeRange.
+     *
+     * <p>If the camera is incorrectly reporting values, log a warning and return
+     * the default value instead.</p>
+     *
+     * @param defaultValue Value to return if no legal value is available
+     * @return The value reported by the camera device or the defaultValue otherwise.
+     */
+    public long getExposureMaximumOrDefault(long defaultValue) {
+        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();
+    }
+
+    /**
+     * Get the maximum value for an exposure range from android.sensor.info.exposureTimeRange.
+     *
+     * <p>If the camera is incorrectly reporting values, log a warning and return
+     * the default value instead, which is the smallest maximum value required to be supported
+     * by all camera devices.</p>
+     *
+     * @return The value reported by the camera device or the defaultValue otherwise.
+     */
+    public long getExposureMaximumOrDefault() {
+        return getExposureMaximumOrDefault(SENSOR_INFO_EXPOSURE_TIME_RANGE_MAX_AT_LEAST);
+    }
+
+    /**
+     * Get aeAvailableModes and do the sanity check.
+     *
+     * <p>Depending on the check level this class has, for WAR or COLLECT levels,
+     * If the aeMode list is invalid, return an empty mode array. The the caller doesn't
+     * have to abort the execution even the aeMode list is invalid.</p>
+     * @return AE available modes
+     */
+    public int[] getAeAvailableModesChecked() {
+        Key<int[]> modesKey = CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES;
+        int[] modes = getValueFromKeyNonNull(modesKey);
+        if (modes == null) {
+            modes = new int[0];
+        }
+        List<Integer> modeList = new ArrayList<Integer>();
+        for (int mode : modes) {
+            modeList.add(mode);
+        }
+        checkTrueForKey(modesKey, "value is empty", !modeList.isEmpty());
+
+        // All camera device must support ON
+        checkTrueForKey(modesKey, "values " + modeList.toString() + " must contain ON mode",
+                modeList.contains(CameraMetadata.CONTROL_AE_MODE_ON));
+
+        // All camera devices with flash units support ON_AUTO_FLASH and ON_ALWAYS_FLASH
+        Key<Boolean> flashKey= CameraCharacteristics.FLASH_INFO_AVAILABLE;
+        Boolean hasFlash = getValueFromKeyNonNull(flashKey);
+        if (hasFlash == null) {
+            hasFlash = false;
+        }
+        if (hasFlash) {
+            boolean flashModeConsistentWithFlash =
+                    modeList.contains(CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH) &&
+                    modeList.contains(CameraMetadata.CONTROL_AE_MODE_ON_ALWAYS_FLASH);
+            checkTrueForKey(modesKey,
+                    "value must contain ON_AUTO_FLASH and ON_ALWAYS_FLASH and  when flash is" +
+                    "available", flashModeConsistentWithFlash);
+        } else {
+            boolean flashModeConsistentWithoutFlash =
+                    !(modeList.contains(CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH) ||
+                    modeList.contains(CameraMetadata.CONTROL_AE_MODE_ON_ALWAYS_FLASH) ||
+                    modeList.contains(CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE));
+            checkTrueForKey(modesKey,
+                    "value must not contain ON_AUTO_FLASH, ON_ALWAYS_FLASH and" +
+                    "ON_AUTO_FLASH_REDEYE when flash is unavailable",
+                    flashModeConsistentWithoutFlash);
+        }
+
+        // FULL mode camera devices always support OFF mode.
+        boolean condition =
+                !isHardwareLevelFull() || modeList.contains(CameraMetadata.CONTROL_AE_MODE_OFF);
+        checkTrueForKey(modesKey, "Full capability device must have OFF mode", condition);
+
+        // Boundary check.
+        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);
+        }
+
+        return modes;
+    }
+
+    /**
+     * Get available AWB modes and do the sanity check.
+     *
+     * @return array that contains available AWB modes, empty array if awbAvailableModes is
+     * unavailable.
+     */
+    public int[] getAwbAvailableModesChecked() {
+        Key<int[]> key =
+                CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES;
+        int[] awbModes = getValueFromKeyNonNull(key);
+
+        if (awbModes == null) {
+            return new int[0];
+        }
+
+        List<Integer> modesList = Arrays.asList(CameraTestUtils.toObject(awbModes));
+        checkTrueForKey(key, " All camera devices must support AUTO mode",
+                modesList.contains(CameraMetadata.CONTROL_AWB_MODE_AUTO));
+        if (isHardwareLevelFull()) {
+            checkTrueForKey(key, " Full capability camera devices must support OFF mode",
+                    modesList.contains(CameraMetadata.CONTROL_AWB_MODE_OFF));
+        }
+
+        return awbModes;
+    }
+
+    /**
+     * Get available AF modes and do the sanity check.
+     *
+     * @return array that contains available AF modes, empty array if afAvailableModes is
+     * unavailable.
+     */
+    public int[] getAfAvailableModesChecked() {
+        Key<int[]> key =
+                CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES;
+        int[] afModes = getValueFromKeyNonNull(key);
+
+        if (afModes == null) {
+            return new int[0];
+        }
+
+        List<Integer> modesList = Arrays.asList(CameraTestUtils.toObject(afModes));
+        if (isHardwareLevelLimitedOrBetter()) {
+            // Some LEGACY mode devices do not support AF OFF
+            checkTrueForKey(key, " All camera devices must support OFF mode",
+                    modesList.contains(CameraMetadata.CONTROL_AF_MODE_OFF));
+        }
+        if (hasFocuser()) {
+            checkTrueForKey(key, " Camera devices that have focuser units must support AUTO mode",
+                    modesList.contains(CameraMetadata.CONTROL_AF_MODE_AUTO));
+        }
+
+        return afModes;
+    }
+
+    /**
+     * Get supported raw output sizes and do the check.
+     *
+     * @return Empty size array if raw output is not supported
+     */
+    public Size[] getRawOutputSizesChecked() {
+        return getAvailableSizesForFormatChecked(ImageFormat.RAW_SENSOR,
+                StreamDirection.Output);
+    }
+
+    /**
+     * Get supported jpeg output sizes and do the check.
+     *
+     * @return Empty size array if jpeg output is not supported
+     */
+    public Size[] getJpegOutputSizeChecked() {
+        return getAvailableSizesForFormatChecked(ImageFormat.JPEG,
+                StreamDirection.Output);
+    }
+
+    /**
+     * Used to determine the stream direction for various helpers that look up
+     * format or size information.
+     */
+    public enum StreamDirection {
+        /** Stream is used with {@link android.hardware.camera2.CameraDevice#configureOutputs} */
+        Output,
+        /** Stream is used with {@code CameraDevice#configureInputs} -- NOT YET PUBLIC */
+        Input
+    }
+
+    /**
+     * Get available sizes for given user-defined format.
+     *
+     * <p><strong>Does not</strong> work with implementation-defined format.</p>
+     *
+     * @param format The format for the requested size array.
+     * @param direction The stream direction, input or output.
+     * @return The sizes of the given format, empty array if no available size is found.
+     */
+    public Size[] getAvailableSizesForFormatChecked(int format, StreamDirection direction) {
+        Key<StreamConfigurationMap> key =
+                CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP;
+        StreamConfigurationMap config = getValueFromKeyNonNull(key);
+
+        if (config == null) {
+            return new Size[0];
+        }
+
+        android.util.Size[] utilSizes;
+
+        switch (direction) {
+            case Output:
+                utilSizes = config.getOutputSizes(format);
+                break;
+            case Input:
+                utilSizes = null;
+                break;
+            default:
+                throw new IllegalArgumentException("direction must be output or input");
+        }
+
+        // TODO: Get rid of android.util.Size
+        if (utilSizes == null) {
+            Log.i(TAG, "This camera doesn't support format " + format + " for " + direction);
+            return new Size[0];
+        }
+
+        Size[] sizes = new Size[utilSizes.length];
+        for (int i = 0; i < utilSizes.length; ++i) {
+            sizes[i] = new Size(utilSizes[i].getWidth(), utilSizes[i].getHeight());
+        }
+
+        return sizes;
+    }
+
+    /**
+     * Get available AE target fps ranges.
+     *
+     * @return Empty int array if aeAvailableTargetFpsRanges is invalid.
+     */
+    @SuppressWarnings("raw")
+    public Range<Integer>[] getAeAvailableTargetFpsRangesChecked() {
+        Key<Range<Integer>[]> key =
+                CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES;
+        Range<Integer>[] fpsRanges = getValueFromKeyNonNull(key);
+
+        if (fpsRanges == null) {
+            return new 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;
+        int minFps, maxFps;
+        long maxFrameDuration = getMaxFrameDurationChecked();
+        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);
+            checkTrueForKey(key, String.format(
+                    " the frame duration %d for min fps %d must smaller than maxFrameDuration %d",
+                    maxDuration, minFps, maxFrameDuration), maxDuration <= maxFrameDuration);
+        }
+
+        return fpsRanges;
+    }
+
+    /**
+     * Get max frame duration.
+     *
+     * @return 0 if maxFrameDuration is null
+     */
+    public long getMaxFrameDurationChecked() {
+        Key<Long> key =
+                CameraCharacteristics.SENSOR_INFO_MAX_FRAME_DURATION;
+        Long maxDuration = getValueFromKeyNonNull(key);
+
+        if (maxDuration == null) {
+            return 0;
+        }
+
+        return maxDuration;
+    }
+
+    /**
+     * Get available minimal frame durations for a given user-defined format.
+     *
+     * <p><strong>Does not</strong> work with implementation-defined format.</p>
+     *
+     * @param format One of the format from {@link ImageFormat}.
+     * @return HashMap of minimal frame durations for different sizes, empty HashMap
+     *         if availableMinFrameDurations is null.
+     */
+    public HashMap<Size, Long> getAvailableMinFrameDurationsForFormatChecked(int format) {
+
+        HashMap<Size, Long> minDurationMap = new HashMap<Size, Long>();
+
+        Key<StreamConfigurationMap> key =
+                CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP;
+        StreamConfigurationMap config = getValueFromKeyNonNull(key);
+
+        if (config == null) {
+            return minDurationMap;
+        }
+
+        for (android.util.Size size : config.getOutputSizes(format)) {
+            long minFrameDuration = config.getOutputMinFrameDuration(format, size);
+
+            if (minFrameDuration != 0) {
+                minDurationMap.put(new Size(size.getWidth(), size.getHeight()), minFrameDuration);
+            }
+        }
+
+        return minDurationMap;
+    }
+
+    public int[] getAvailableEdgeModesChecked() {
+        Key<int[]> key = CameraCharacteristics.EDGE_AVAILABLE_EDGE_MODES;
+        int[] edgeModes = getValueFromKeyNonNull(key);
+
+        if (edgeModes == null) {
+            return new int[0];
+        }
+
+        // Full device should always include OFF and FAST
+        if (isHardwareLevelFull()) {
+            List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(edgeModes));
+            checkTrueForKey(key, "Full device must contain OFF and FAST edge modes",
+                    modeList.contains(CameraMetadata.EDGE_MODE_OFF) &&
+                    modeList.contains(CameraMetadata.EDGE_MODE_FAST));
+        }
+
+        return edgeModes;
+    }
+
+    public int[] getAvailableNoiseReductionModesChecked() {
+        Key<int[]> key =
+                CameraCharacteristics.NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES;
+        int[] noiseReductionModes = getValueFromKeyNonNull(key);
+
+        if (noiseReductionModes == null) {
+            return new int[0];
+        }
+
+        // Full device should always include OFF and FAST
+        if (isHardwareLevelFull()) {
+            List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(noiseReductionModes));
+            checkTrueForKey(key, "Full device must contain OFF and FAST noise reduction modes",
+                    modeList.contains(CameraMetadata.NOISE_REDUCTION_MODE_OFF) &&
+                    modeList.contains(CameraMetadata.NOISE_REDUCTION_MODE_FAST));
+        }
+
+        return noiseReductionModes;
+    }
+
+    /**
+     * Get value of key android.control.aeCompensationStep and do the sanity check.
+     *
+     * @return default value if the value is null.
+     */
+    public Rational getAeCompensationStepChecked() {
+        Key<Rational> key =
+                CameraCharacteristics.CONTROL_AE_COMPENSATION_STEP;
+        Rational compensationStep = getValueFromKeyNonNull(key);
+
+        if (compensationStep == null) {
+            // Return default step.
+            return CONTROL_AE_COMPENSATION_STEP_DEFAULT;
+        }
+
+        // Legacy devices don't have a minimum step requirement
+        if (isHardwareLevelLimitedOrBetter()) {
+            float compensationStepF =
+                    (float) compensationStep.getNumerator() / compensationStep.getDenominator();
+            checkTrueForKey(key, " value must be no more than 1/2", compensationStepF <= 0.5f);
+        }
+
+        return compensationStep;
+    }
+
+    /**
+     * Get value of key android.control.aeCompensationRange and do the sanity check.
+     *
+     * @return default value if the value is null or malformed.
+     */
+    public Range<Integer> getAeCompensationRangeChecked() {
+        Key<Range<Integer>> key =
+                CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE;
+        Range<Integer> compensationRange = getValueFromKeyNonNull(key);
+        Rational compensationStep = getAeCompensationStepChecked();
+        float compensationStepF = compensationStep.floatValue();
+        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;
+        }
+
+        // Legacy devices don't have a minimum range requirement
+        if (isHardwareLevelLimitedOrBetter()) {
+            checkTrueForKey(key, " range value must be at least " + DEFAULT_RANGE
+                    + ", actual " + compensationRange + ", compensation step " + compensationStep,
+                   compensationRange.getLower() <= DEFAULT_RANGE.getLower() &&
+                   compensationRange.getUpper() >= DEFAULT_RANGE.getUpper());
+        }
+
+        return compensationRange;
+    }
+
+    /**
+     * Get availableVideoStabilizationModes and do the sanity check.
+     *
+     * @return available video stabilization modes, empty array if it is unavailable.
+     */
+    public int[] getAvailableVideoStabilizationModesChecked() {
+        Key<int[]> key =
+                CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES;
+        int[] modes = getValueFromKeyNonNull(key);
+
+        if (modes == null) {
+            return new int[0];
+        }
+
+        List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes));
+        checkTrueForKey(key, " All device should support OFF mode",
+                modeList.contains(CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_OFF));
+        checkArrayValuesInRange(key, modes,
+                CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_OFF,
+                CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_ON);
+
+        return modes;
+    }
+
+    /**
+     * Get availableOpticalStabilization and do the sanity check.
+     *
+     * @return available optical stabilization modes, empty array if it is unavailable.
+     */
+    public int[] getAvailableOpticalStabilizationChecked() {
+        Key<int[]> key =
+                CameraCharacteristics.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION;
+        int[] modes = getValueFromKeyNonNull(key);
+
+        if (modes == null) {
+            return new int[0];
+        }
+
+        checkArrayValuesInRange(key, modes,
+                CameraMetadata.LENS_OPTICAL_STABILIZATION_MODE_OFF,
+                CameraMetadata.LENS_OPTICAL_STABILIZATION_MODE_ON);
+
+        return modes;
+    }
+
+    /**
+     * Get the scaler's max digital zoom ({@code >= 1.0f}) ratio between crop and active array
+     * @return the max zoom ratio, or {@code 1.0f} if the value is unavailable
+     */
+    public float getAvailableMaxDigitalZoomChecked() {
+        Key<Float> key =
+                CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM;
+
+        Float maxZoom = getValueFromKeyNonNull(key);
+        if (maxZoom == null) {
+            return 1.0f;
+        }
+
+        checkTrueForKey(key, " max digital zoom should be no less than 1",
+                maxZoom >= 1.0f && !Float.isNaN(maxZoom) && !Float.isInfinite(maxZoom));
+
+        return maxZoom;
+    }
+
+    public int[] getAvailableSceneModesChecked() {
+        Key<int[]> key =
+                CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES;
+        int[] modes = getValueFromKeyNonNull(key);
+
+        if (modes == null) {
+            return new int[0];
+        }
+
+        List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes));
+        // FACE_PRIORITY must be included if face detection is supported.
+        if (areKeysAvailable(CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT) &&
+                getMaxFaceCountChecked() > 0) {
+            checkTrueForKey(key, " FACE_PRIORITY must be included if face detection is supported",
+                    modeList.contains(CameraMetadata.CONTROL_SCENE_MODE_FACE_PRIORITY));
+        }
+
+        return modes;
+    }
+
+    public int[] getAvailableEffectModesChecked() {
+        Key<int[]> key =
+                CameraCharacteristics.CONTROL_AVAILABLE_EFFECTS;
+        int[] modes = getValueFromKeyNonNull(key);
+
+        if (modes == null) {
+            return new int[0];
+        }
+
+        List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes));
+        // OFF must be included.
+        checkTrueForKey(key, " OFF must be included",
+                modeList.contains(CameraMetadata.CONTROL_EFFECT_MODE_OFF));
+
+        return modes;
+    }
+
+    /**
+     * Get and check the available color aberration modes
+     *
+     * @return the available color aberration modes
+     */
+    public int[] getAvailableColorAberrationModesChecked() {
+        Key<int[]> key =
+                CameraCharacteristics.COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES;
+        int[] modes = getValueFromKeyNonNull(key);
+
+        if (modes == null) {
+            return new int[0];
+        }
+
+        List<Integer> modeList = Arrays.asList(CameraTestUtils.toObject(modes));
+        checkTrueForKey(key, " Camera devices must always support OFF mode",
+                modeList.contains(CameraMetadata.COLOR_CORRECTION_ABERRATION_MODE_OFF));
+        checkElementDistinct(key, modeList);
+        checkArrayValuesInRange(key, modes,
+                CameraMetadata.COLOR_CORRECTION_ABERRATION_MODE_OFF,
+                CameraMetadata.COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY);
+
+        return modes;
+    }
+
+    /**
+     * Get max pipeline depth and do the sanity check.
+     *
+     * @return max pipeline depth, default value if it is not available.
+     */
+    public byte getPipelineMaxDepthChecked() {
+        Key<Byte> key =
+                CameraCharacteristics.REQUEST_PIPELINE_MAX_DEPTH;
+        Byte maxDepth = getValueFromKeyNonNull(key);
+
+        if (maxDepth == null) {
+            return REQUEST_PIPELINE_MAX_DEPTH_MAX;
+        }
+
+        checkTrueForKey(key, " max pipeline depth should be no larger than "
+                + REQUEST_PIPELINE_MAX_DEPTH_MAX, maxDepth <= REQUEST_PIPELINE_MAX_DEPTH_MAX);
+
+        return maxDepth;
+    }
+
+    /**
+     * 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>();
+        }
+
+        checkArrayValuesInRange(key, availableCaps,
+                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,
+                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW);
+        capList = Arrays.asList(CameraTestUtils.toObject(availableCaps));
+        return capList;
+    }
+
+    /**
+     * Determine whether the current device supports a capability or not.
+     *
+     * @param capability (non-negative)
+     *
+     * @return {@code true} if the capability is supported, {@code false} otherwise.
+     *
+     * @throws IllegalArgumentException if {@code capability} was negative
+     *
+     * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+     */
+    public boolean isCapabilitySupported(int capability) {
+        if (capability < 0) {
+            throw new IllegalArgumentException("capability must be non-negative");
+        }
+
+        List<Integer> availableCapabilities = getAvailableCapabilitiesChecked();
+
+        return availableCapabilities.contains(capability);
+    }
+
+    /**
+     * Determine whether or not all the {@code keys} are available characteristics keys
+     * (as in {@link CameraCharacteristics#getKeys}.
+     *
+     * <p>If this returns {@code true}, then querying for this key from a characteristics
+     * object will always return a non-{@code null} value.</p>
+     *
+     * @param keys collection of camera characteristics keys
+     * @return whether or not all characteristics keys are available
+     */
+    public final boolean areCharacteristicsKeysAvailable(
+            Collection<CameraCharacteristics.Key<?>> keys) {
+        return mCharacteristics.getKeys().containsAll(keys);
+    }
+
+    /**
+     * Determine whether or not all the {@code keys} are available result keys
+     * (as in {@link CameraCharacteristics#getAvailableCaptureResultKeys}.
+     *
+     * <p>If this returns {@code true}, then querying for this key from a result
+     * object will almost always return a non-{@code null} value.</p>
+     *
+     * <p>In some cases (e.g. lens shading map), the request must have additional settings
+     * configured in order for the key to correspond to a value.</p>
+     *
+     * @param keys collection of capture result keys
+     * @return whether or not all result keys are available
+     */
+    public final boolean areResultKeysAvailable(Collection<CaptureResult.Key<?>> keys) {
+        return mCharacteristics.getAvailableCaptureResultKeys().containsAll(keys);
+    }
+
+    /**
+     * Determine whether or not all the {@code keys} are available request keys
+     * (as in {@link CameraCharacteristics#getAvailableCaptureRequestKeys}.
+     *
+     * <p>If this returns {@code true}, then setting this key in the request builder
+     * may have some effect (and if it's {@code false}, then the camera device will
+     * definitely ignore it).</p>
+     *
+     * <p>In some cases (e.g. manual control of exposure), other keys must be also be set
+     * in order for a key to take effect (e.g. control.mode set to OFF).</p>
+     *
+     * @param keys collection of capture request keys
+     * @return whether or not all result keys are available
+     */
+    public final boolean areRequestKeysAvailable(Collection<CaptureRequest.Key<?>> keys) {
+        return mCharacteristics.getAvailableCaptureRequestKeys().containsAll(keys);
+    }
+
+    /**
+     * Determine whether or not all the {@code keys} are available characteristics keys
+     * (as in {@link CameraCharacteristics#getKeys}.
+     *
+     * <p>If this returns {@code true}, then querying for this key from a characteristics
+     * object will always return a non-{@code null} value.</p>
+     *
+     * @param keys one or more camera characteristic keys
+     * @return whether or not all characteristics keys are available
+     */
+    @SafeVarargs
+    public final boolean areKeysAvailable(CameraCharacteristics.Key<?>... keys) {
+        return areCharacteristicsKeysAvailable(Arrays.asList(keys));
+    }
+
+    /**
+     * Determine whether or not all the {@code keys} are available result keys
+     * (as in {@link CameraCharacteristics#getAvailableCaptureResultKeys}.
+     *
+     * <p>If this returns {@code true}, then querying for this key from a result
+     * object will almost always return a non-{@code null} value.</p>
+     *
+     * <p>In some cases (e.g. lens shading map), the request must have additional settings
+     * configured in order for the key to correspond to a value.</p>
+     *
+     * @param keys one or more capture result keys
+     * @return whether or not all result keys are available
+     */
+    @SafeVarargs
+    public final boolean areKeysAvailable(CaptureResult.Key<?>... keys) {
+        return areResultKeysAvailable(Arrays.asList(keys));
+    }
+
+    /**
+     * Determine whether or not all the {@code keys} are available request keys
+     * (as in {@link CameraCharacteristics#getAvailableCaptureRequestKeys}.
+     *
+     * <p>If this returns {@code true}, then setting this key in the request builder
+     * may have some effect (and if it's {@code false}, then the camera device will
+     * definitely ignore it).</p>
+     *
+     * <p>In some cases (e.g. manual control of exposure), other keys must be also be set
+     * in order for a key to take effect (e.g. control.mode set to OFF).</p>
+     *
+     * @param keys one or more capture request keys
+     * @return whether or not all result keys are available
+     */
+    @SafeVarargs
+    public final boolean areKeysAvailable(CaptureRequest.Key<?>... keys) {
+        return areRequestKeysAvailable(Arrays.asList(keys));
+    }
+
+    /*
+     * Determine if camera device support manual lens shading map control
+     *
+     * @return {@code true} if manual lens shading map control is supported
+     */
+    public boolean isManualLensShadingMapSupported() {
+        return areKeysAvailable(CaptureRequest.SHADING_MODE);
+    }
+
+    /**
+     * Determine if camera device support manual color correction control
+     *
+     * @return {@code true} if manual color correction control is supported
+     */
+    public boolean isManualColorCorrectionSupported() {
+        return areKeysAvailable(CaptureRequest.COLOR_CORRECTION_MODE);
+    }
+
+    /**
+     * Determine if camera device support manual tone mapping control
+     *
+     * @return {@code true} if manual tone mapping control is supported
+     */
+    public boolean isManualToneMapSupported() {
+        return areKeysAvailable(CaptureRequest.TONEMAP_MODE);
+    }
+
+    /**
+     * Determine if camera device support manual color aberration control
+     *
+     * @return {@code true} if manual color aberration control is supported
+     */
+    public boolean isManualColorAberrationControlSupported() {
+        return areKeysAvailable(CaptureRequest.COLOR_CORRECTION_ABERRATION_MODE);
+    }
+
+    /**
+     * Determine if camera device support edge mode control
+     *
+     * @return {@code true} if edge mode control is supported
+     */
+    public boolean isEdgeModeControlSupported() {
+        return areKeysAvailable(CaptureRequest.EDGE_MODE);
+    }
+
+    /**
+     * Determine if camera device support hot pixel mode control
+     *
+     * @return {@code true} if hot pixel mode control is supported
+     */
+    public boolean isHotPixelMapModeControlSupported() {
+        return areKeysAvailable(CaptureRequest.HOT_PIXEL_MODE);
+    }
+
+    /**
+     * Determine if camera device support noise reduction mode control
+     *
+     * @return {@code true} if noise reduction mode control is supported
+     */
+    public boolean isNoiseReductionModeControlSupported() {
+        return areKeysAvailable(CaptureRequest.NOISE_REDUCTION_MODE);
+    }
+
+    /**
+     * 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 scaler's cropping type (center only or freeform)
+     * @return cropping type, return default value (CENTER_ONLY) if value is unavailable
+     */
+    public int getScalerCroppingTypeChecked() {
+        Key<Integer> key =
+                CameraCharacteristics.SCALER_CROPPING_TYPE;
+        Integer value = getValueFromKeyNonNull(key);
+
+        if (value == null) {
+            return CameraCharacteristics.SCALER_CROPPING_TYPE_CENTER_ONLY;
+        }
+
+        checkTrueForKey(key, " value is out of range ",
+                value >= CameraCharacteristics.SCALER_CROPPING_TYPE_CENTER_ONLY &&
+                value <= CameraCharacteristics.SCALER_CROPPING_TYPE_FREEFORM);
+
+        return value;
+    }
+
+    /**
+     * Check if high speed video is supported (HIGH_SPEED_VIDEO scene mode is
+     * supported, supported high speed fps ranges and sizes are valid).
+     *
+     * @return true if high speed video is supported.
+     */
+    public boolean isHighSpeedVideoSupported() {
+        List<Integer> sceneModes =
+                Arrays.asList(CameraTestUtils.toObject(getAvailableSceneModesChecked()));
+        if (sceneModes.contains(CameraCharacteristics.CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO)) {
+            StreamConfigurationMap config =
+                    getValueFromKeyNonNull(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+            if (config == null) {
+                return false;
+            }
+            Size[] availableSizes = config.getHighSpeedVideoSizes();
+            if (availableSizes.length == 0) {
+                return false;
+            }
+
+            for (Size size : availableSizes) {
+                Range<Integer>[] availableFpsRanges = config.getHighSpeedVideoFpsRangesFor(size);
+                if (availableFpsRanges.length == 0) {
+                    return false;
+                }
+            }
+
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * 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
+     * the default value instead.</p>
+     *
+     * @param key Key to fetch
+     * @param defaultValue Default value to return if camera device uses invalid values
+     * @param name Human-readable name for the array index (logging only)
+     * @param index Array index of the subelement
+     * @param size Expected fixed size of the array
+     *
+     * @return The value reported by the camera device, or the defaultValue otherwise.
+     */
+    private <T> T getArrayElementOrDefault(Key<?> key, T defaultValue, String name, int index,
+            int size) {
+        T elementValue = getArrayElementCheckRangeNonNull(
+                key,
+                index,
+                size);
+
+        if (elementValue == null) {
+            failKeyCheck(key,
+                    "had no valid " + name + " value; using default of " + defaultValue);
+            elementValue = defaultValue;
+        }
+
+        return elementValue;
+    }
+
+    /**
+     * Fetch an array sub-element from an array value given by a key.
+     *
+     * <p>
+     * Prints a warning if the sub-element was null.
+     * </p>
+     *
+     * <p>Use for variable-size arrays since this does not check the array size.</p>
+     *
+     * @param key Metadata key to look up
+     * @param element A non-negative index value.
+     * @return The array sub-element, or null if the checking failed.
+     */
+    private <T> T getArrayElementNonNull(Key<?> key, int element) {
+        return getArrayElementCheckRangeNonNull(key, element, IGNORE_SIZE_CHECK);
+    }
+
+    /**
+     * Fetch an array sub-element from an array value given by a key.
+     *
+     * <p>
+     * Prints a warning if the array size does not match the size, or if the sub-element was null.
+     * </p>
+     *
+     * @param key Metadata key to look up
+     * @param element The index in [0,size)
+     * @param size A positive size value or otherwise {@value #IGNORE_SIZE_CHECK}
+     * @return The array sub-element, or null if the checking failed.
+     */
+    private <T> T getArrayElementCheckRangeNonNull(Key<?> key, int element, int size) {
+        Object array = getValueFromKeyNonNull(key);
+
+        if (array == null) {
+            // Warning already printed
+            return null;
+        }
+
+        if (size != IGNORE_SIZE_CHECK) {
+            int actualLength = Array.getLength(array);
+            if (actualLength != size) {
+                failKeyCheck(key,
+                        String.format("had the wrong number of elements (%d), expected (%d)",
+                                actualLength, size));
+                return null;
+            }
+        }
+
+        @SuppressWarnings("unchecked")
+        T val = (T) Array.get(array, element);
+
+        if (val == null) {
+            failKeyCheck(key, "had a null element at index" + element);
+            return null;
+        }
+
+        return val;
+    }
+
+    /**
+     * Gets the key, logging warnings for null values.
+     */
+    public <T> T getValueFromKeyNonNull(Key<T> key) {
+        if (key == null) {
+            throw new IllegalArgumentException("key was null");
+        }
+
+        T value = mCharacteristics.get(key);
+
+        if (value == null) {
+            failKeyCheck(key, "was null");
+        }
+
+        return value;
+    }
+
+    private void checkArrayValuesInRange(Key<int[]> key, int[] array, int min, int max) {
+        for (int value : array) {
+            checkTrueForKey(key, String.format(" value is out of range [%d, %d]", min, max),
+                    value <= max && value >= min);
+        }
+    }
+
+    private void checkArrayValuesInRange(Key<byte[]> key, byte[] array, byte min, byte max) {
+        for (byte value : array) {
+            checkTrueForKey(key, String.format(" value is out of range [%d, %d]", min, max),
+                    value <= max && value >= min);
+        }
+    }
+
+    /**
+     * Check the uniqueness of the values in a list.
+     *
+     * @param key The key to be checked
+     * @param list The list contains the value of the key
+     */
+    private <U, T> void checkElementDistinct(Key<U> key, List<T> list) {
+        // Each size must be distinct.
+        Set<T> sizeSet = new HashSet<T>(list);
+        checkTrueForKey(key, "Each size must be distinct", sizeSet.size() == list.size());
+    }
+
+    private <T> void checkTrueForKey(Key<T> key, String message, boolean condition) {
+        if (!condition) {
+            failKeyCheck(key, message);
+        }
+    }
+
+    private <T> void failKeyCheck(Key<T> key, String message) {
+        // TODO: Consider only warning once per key/message combination if it's too spammy.
+        // TODO: Consider offering other options such as throwing an assertion exception
+        String failureCause = String.format("The static info key '%s' %s", key.getName(), message);
+        switch (mLevel) {
+            case WARN:
+                Log.w(TAG, failureCause);
+                break;
+            case COLLECT:
+                mCollector.addMessage(failureCause);
+                break;
+            case ASSERT:
+                Assert.fail(failureCause);
+            default:
+                throw new UnsupportedOperationException("Unhandled level " + mLevel);
+        }
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/UncheckedCloseable.java b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/UncheckedCloseable.java
new file mode 100644
index 0000000..570ef2c
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/UncheckedCloseable.java
@@ -0,0 +1,48 @@
+/*
+ * 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.helpers;
+
+/**
+ * Defines an interface for classes that can (or need to) be closed once they
+ * are not used any longer; calling the {@code close} method releases resources
+ * that the object holds.</p>
+ *
+ * <p>This signifies that the implementor will never throw checked exceptions when closing,
+ * allowing for more fine grained exception handling at call sites handling this interface
+ * generically.</p>
+ *
+ * <p>A common pattern for using an {@code UncheckedCloseable} resource:
+ * <pre>   {@code
+ *   // where <Foo extends UncheckedCloseable>
+ *   UncheckedCloseable foo = new Foo();
+ *   try {
+ *      ...;
+ *   } finally {
+ *      foo.close();
+ *   }
+ * }</pre>
+ */
+public interface UncheckedCloseable extends AutoCloseable {
+
+    /**
+     * Closes the object and release any system resources it holds.
+     *
+     * <p>Does not throw any checked exceptions.</p>
+     */
+    @Override
+    void close();
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/means_yuvx_444_1d_to_single.rs b/tests/tests/hardware/src/android/hardware/camera2/cts/means_yuvx_444_1d_to_single.rs
new file mode 100644
index 0000000..052052f
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/means_yuvx_444_1d_to_single.rs
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#include "common.rs"
+
+// #define LOG_DEBUG 1
+
+// Must be yuvx_444 (interleaved yuv)
+rs_allocation mInput;
+
+uint32_t width;
+float inv_width; // must be set to 1/w
+
+// Average 1D array -> Single element
+// Input: mInput must be yuvx_444
+yuvx_444 RS_KERNEL means_yuvx_444(void) {
+
+    uint3 sum  = { 0, 0, 0 };
+
+    LOGD("width", width);
+
+    for (uint32_t i = 0; i < width; ++i) {
+        yuvx_444 elem = rsGetElementAt_yuvx_444(mInput, i);
+
+        LOGD("elem", elem);
+        LOGD("i", i);
+
+        sum.x += elem.x;
+        sum.y += elem.y;
+        sum.z += elem.z;
+    }
+
+    sum.x *= inv_width; // multiply by 1/w
+    sum.y *= inv_width; // multiply by 1/w
+    sum.z *= inv_width; // multiply by 1/w
+
+    yuvx_444 avg = convert_yuvx_444(sum);
+
+    return avg;
+}
+
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/means_yuvx_444_2d_to_1d.rs b/tests/tests/hardware/src/android/hardware/camera2/cts/means_yuvx_444_2d_to_1d.rs
new file mode 100644
index 0000000..7dc4e0d
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/means_yuvx_444_2d_to_1d.rs
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+#include "common.rs"
+
+// #define LOG_DEBUG 1
+
+// Must be YUV 420 888 (flexible YUV)
+rs_allocation mInput;
+
+uint32_t width;
+float inv_width; // 1/w
+uint32_t src_x; // x-offset from mInput
+uint32_t src_y; // y-offset from mInput
+
+// Average a 2D array -> 1D array (by each row)
+// Input: mInput must be yuvf_420
+yuvx_444 RS_KERNEL means_yuvf_420(uint32_t x) {
+
+    LOGD("x", x);
+
+    uint3 sum = { 0, 0, 0 };
+
+    for (uint32_t i = 0; i < width; ++i) {
+        uchar py = rsGetElementAtYuv_uchar_Y(mInput, src_x + i, src_y + x);
+        uchar pu = rsGetElementAtYuv_uchar_U(mInput, src_x + i, src_y + x);
+        uchar pv = rsGetElementAtYuv_uchar_V(mInput, src_x + i, src_y + x);
+
+        yuvx_444 elem = { py, pu, pv };
+
+        LOGD("elem", elem);
+
+        sum.x += elem.x;
+        sum.y += elem.y;
+        sum.z += elem.z;
+    }
+
+    sum.x *= inv_width; // multiply by 1/w
+    sum.y *= inv_width; // multiply by 1/w
+    sum.z *= inv_width; // multiply by 1/w
+
+    yuvx_444 avg = convert_yuvx_444(sum);
+
+    return avg;
+}
+
+// Average a 2D array -> 1D array (by each row)
+// Input: mInput must be yuvx_444
+yuvx_444 RS_KERNEL means_yuvx_444(uint32_t x) {
+
+    LOGD("x", x);
+
+    uint3 sum = { 0, 0, 0 };
+
+    for (uint32_t i = 0; i < width; ++i) {
+        yuvx_444 elem = rsGetElementAt_yuvx_444(mInput, src_x + i, src_y + x);
+
+        LOGD("elem", elem);
+
+        sum.x += elem.x;
+        sum.y += elem.y;
+        sum.z += elem.z;
+    }
+
+    sum.x *= inv_width; // multiply by 1/w
+    sum.y *= inv_width; // multiply by 1/w
+    sum.z *= inv_width; // multiply by 1/w
+
+    yuvx_444 avg = convert_yuvx_444(sum);
+
+    return avg;
+}
+
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/rs/AllocationCache.java b/tests/tests/hardware/src/android/hardware/camera2/cts/rs/AllocationCache.java
new file mode 100644
index 0000000..b89f9bb
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/rs/AllocationCache.java
@@ -0,0 +1,238 @@
+/*
+ * 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.rs;
+
+import android.hardware.camera2.cts.helpers.UncheckedCloseable;
+import android.renderscript.Allocation;
+import android.renderscript.RenderScript;
+import android.renderscript.Type;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static android.hardware.camera2.cts.helpers.Preconditions.*;
+
+/**
+ * Cache {@link Allocation} objects based on their type and usage.
+ *
+ * <p>This avoids expensive re-allocation of objects when they are used over and over again
+ * by different scripts.</p>
+ */
+public class AllocationCache implements UncheckedCloseable {
+
+    private static final String TAG = "AllocationCache";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    private static int sDebugHits = 0;
+    private static int sDebugMisses = 0;
+
+    private final RenderScript mRS;
+    private final HashMap<AllocationKey, List<Allocation>> mAllocationMap =
+            new HashMap<AllocationKey, List<Allocation>>();
+    private boolean mClosed = false;
+
+    /**
+     * Create a new cache with the specified RenderScript context.
+     *
+     * @param rs A non-{@code null} RenderScript context.
+     *
+     * @throws NullPointerException if rs was null
+     */
+    public AllocationCache(RenderScript rs) {
+        mRS = checkNotNull("rs", rs);
+    }
+
+    /**
+     * Returns the {@link RenderScript} context associated with this AllocationCache.
+     *
+     * @return A non-{@code null} RenderScript value.
+     */
+    public RenderScript getRenderScript() {
+        return mRS;
+    }
+
+    /**
+     * Try to lookup a compatible Allocation from the cache, create one if none exist.
+     *
+     * @param type A non-{@code null} RenderScript Type.
+     * @throws NullPointerException if type was null
+     * @throws IllegalStateException if the cache was closed with {@link #close}
+     */
+    public Allocation getOrCreateTyped(Type type, int usage) {
+        synchronized (this) {
+          checkNotNull("type", type);
+          checkNotClosed();
+
+          AllocationKey key = new AllocationKey(type, usage);
+          List<Allocation> list = mAllocationMap.get(key);
+
+          if (list != null && !list.isEmpty()) {
+              Allocation alloc = list.remove(list.size() - 1);
+              if (DEBUG) {
+                  sDebugHits++;
+                  Log.d(TAG, String.format(
+                      "Cache HIT (%d): type = '%s', usage = '%x'", sDebugHits, type, usage));
+              }
+              return alloc;
+          }
+          if (DEBUG) {
+              sDebugMisses++;
+              Log.d(TAG, String.format(
+                  "Cache MISS (%d): type = '%s', usage = '%x'", sDebugMisses, type, usage));
+          }
+        }
+        return Allocation.createTyped(mRS, type, usage);
+    }
+
+    /**
+     * Return the Allocation to the cache.
+     *
+     * <p>Future calls to getOrCreateTyped with the same type and usage may
+     * return this allocation.</p>
+     *
+     * <p>Allocations that have usage {@link Allocation#USAGE_IO_INPUT} get their
+     * listeners reset. Those that have {@link Allocation#USAGE_IO_OUTPUT} get their
+     * surfaces reset.</p>
+     *
+     * @param allocation A non-{@code null} RenderScript {@link Allocation}
+     * @throws NullPointerException if allocation was null
+     * @throws IllegalArgumentException if the allocation was already returned previously
+     * @throws IllegalStateException if the cache was closed with {@link #close}
+     */
+    public synchronized void returnToCache(Allocation allocation) {
+        checkNotNull("allocation", allocation);
+        checkNotClosed();
+
+        int usage = allocation.getUsage();
+        AllocationKey key = new AllocationKey(allocation.getType(), usage);
+        List<Allocation> value = mAllocationMap.get(key);
+
+        if (value != null && value.contains(allocation)) {
+            throw new IllegalArgumentException("allocation was already returned to the cache");
+        }
+
+        if ((usage & Allocation.USAGE_IO_INPUT) != 0) {
+            allocation.setOnBufferAvailableListener(null);
+        }
+        if ((usage & Allocation.USAGE_IO_OUTPUT) != 0) {
+            allocation.setSurface(null);
+        }
+
+        if (value == null) {
+            value = new ArrayList<Allocation>(/*capacity*/1);
+            mAllocationMap.put(key, value);
+        }
+
+        value.add(allocation);
+
+        // TODO: Evict existing allocations from cache when we get too many items in it,
+        // to avoid running out of memory
+
+        // TODO: move to using android.util.LruCache under the hood
+    }
+
+    /**
+     * Return the allocation to the cache, if it wasn't {@code null}.
+     *
+     * <p>Future calls to getOrCreateTyped with the same type and usage may
+     * return this allocation.</p>
+     *
+     * <p>Allocations that have usage {@link Allocation#USAGE_IO_INPUT} get their
+     * listeners reset. Those that have {@link Allocation#USAGE_IO_OUTPUT} get their
+     * surfaces reset.</p>
+     *
+     * <p>{@code null} values are a no-op.</p>
+     *
+     * @param allocation A potentially {@code null} RenderScript {@link Allocation}
+     * @throws IllegalArgumentException if the allocation was already returned previously
+     * @throws IllegalStateException if the cache was closed with {@link #close}
+     */
+    public synchronized void returnToCacheIfNotNull(Allocation allocation) {
+        if (allocation != null) {
+            returnToCache(allocation);
+        }
+    }
+
+    /**
+     * Closes the object and destroys any Allocations still in the cache.
+     */
+    @Override
+    public synchronized void close() {
+        if (mClosed) return;
+
+        for (Map.Entry<AllocationKey, List<Allocation>> entry : mAllocationMap.entrySet()) {
+            List<Allocation> value = entry.getValue();
+
+            for (Allocation alloc : value) {
+                alloc.destroy();
+            }
+
+            value.clear();
+        }
+
+        mAllocationMap.clear();
+        mClosed = true;
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            close();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    /**
+     * Holder class to check if one allocation is compatible with another.
+     *
+     * <p>An Allocation is considered compatible if both it's Type and usage is equivalent.</p>
+     */
+    private static class AllocationKey {
+        private final Type mType;
+        private final int mUsage;
+
+        public AllocationKey(Type type, int usage) {
+            mType = type;
+            mUsage = usage;
+        }
+
+        @Override
+        public int hashCode() {
+            return mType.hashCode() ^ mUsage;
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (other instanceof AllocationKey){
+                AllocationKey otherKey = (AllocationKey) other;
+
+                return otherKey.mType.equals(mType) && otherKey.mUsage == otherKey.mUsage;
+            }
+
+            return false;
+        }
+    }
+
+    private void checkNotClosed() {
+        if (mClosed == true) {
+            throw new IllegalStateException("AllocationCache has already been closed");
+        }
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/rs/AllocationInfo.java b/tests/tests/hardware/src/android/hardware/camera2/cts/rs/AllocationInfo.java
new file mode 100644
index 0000000..3324783
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/rs/AllocationInfo.java
@@ -0,0 +1,441 @@
+/*
+ * 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.rs;
+
+import static android.hardware.camera2.cts.helpers.Preconditions.*;
+
+import android.graphics.ImageFormat;
+import android.graphics.PixelFormat;
+import android.util.Size;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Type;
+import android.util.Log;
+
+/**
+ * Abstract the information necessary to create new {@link Allocation allocations} with
+ * their size, element, type, and usage.
+ *
+ * <p>This also includes convenience functions for printing to a string, something RenderScript
+ * lacks at the time of writing.</p>
+ *
+ * <p>Note that when creating a new {@link AllocationInfo} the usage flags <b>always</b> get ORd
+ * to {@link Allocation#USAGE_IO_SCRIPT}.</p>
+ */
+public class AllocationInfo {
+
+    private final RenderScript mRS = RenderScriptSingleton.getRS();
+
+    private final Size mSize;
+    private final Element mElement;
+    private final Type mType;
+    private final int mUsage;
+
+    private static final String TAG = "AllocationInfo";
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+
+    /**
+     * Create a new {@link AllocationInfo} holding the element, size, and usage
+     * from an existing {@link Allocation}.
+     *
+     * @param allocation {@link Allocation}
+     *
+     * @return A new {@link AllocationInfo}
+     *
+     * @throws NullPointerException if allocation was {@code null}.
+     */
+    public static AllocationInfo newInstance(Allocation allocation) {
+        checkNotNull("allocation", allocation);
+
+        return new AllocationInfo(allocation.getElement(),
+                new Size(allocation.getType().getX(), allocation.getType().getY()),
+                allocation.getUsage());
+    }
+
+    /**
+     * Create a new {@link AllocationInfo} holding the specified format, {@link Size},
+     * and {@link Allocation#USAGE_SCRIPT usage}.
+     *
+     * <p>The usage is always ORd with {@link Allocation#USAGE_SCRIPT}.</p>
+     *
+     * <p>The closest {@link Element} possible is created from the format.</p>
+     *
+     * @param size {@link Size}
+     * @param format An int format
+     * @param usage Usage flags
+     *
+     * @return A new {@link AllocationInfo} holding the given arguments.
+     *
+     * @throws NullPointerException if size was {@code null}.
+     *
+     * @see ImageFormat
+     * @see PixelFormat
+     */
+    public static AllocationInfo newInstance(Size size, int format, int usage) {
+        RenderScript rs = RenderScriptSingleton.getRS();
+
+        Element element;
+        switch (format) {
+            case ImageFormat.YUV_420_888:
+                element = Element.YUV(rs);
+                break;
+            case PixelFormat.RGBA_8888:
+                element = Element.RGBA_8888(rs);
+                break;
+            // TODO: map more formats here
+            default:
+                throw new UnsupportedOperationException("Unsupported format " + format);
+        }
+
+        return new AllocationInfo(element, size, usage);
+    }
+
+
+    /**
+     * Create a new {@link AllocationInfo} holding the specified format, {@link Size},
+     * with the default usage.
+     *
+     * <p>The default usage is always {@link Allocation#USAGE_SCRIPT}.</p>
+     *
+     * <p>The closest {@link Element} possible is created from the format.</p>
+     *
+     * @param size {@link Size}
+     * @param format An int format
+     *
+     * @return A new {@link AllocationInfo} holding the given arguments.
+     *
+     * @throws NullPointerException if size was {@code null}.
+     *
+     * @see ImageFormat
+     * @see PixelFormat
+     */
+    public static AllocationInfo newInstance(Size size, int format) {
+        return newInstance(size, format, Allocation.USAGE_SCRIPT);
+    }
+
+    /**
+     * Create a new {@link AllocationInfo} holding the specified {@link Element}, {@link Size},
+     * with the default usage.
+     *
+     * <p>The default usage is always {@link Allocation#USAGE_SCRIPT}.</p>
+     *
+     * @param element {@link Element}
+     * @param size {@link Size}
+     *
+     * @return A new {@link AllocationInfo} holding the given arguments.
+     *
+     * @throws NullPointerException if size was {@code null}.
+     * @throws NullPointerException if element was {@code null}.
+     */
+    public static AllocationInfo newInstance(Element element, Size size) {
+        return new AllocationInfo(element, size, Allocation.USAGE_SCRIPT);
+    }
+
+    /**
+     * Create a new {@link AllocationInfo} holding the specified {@link Element}, {@link Size},
+     * and {@link Allocation#USAGE_SCRIPT usage}.
+     *
+     * <p>The usage is always ORd with {@link Allocation#USAGE_SCRIPT}.</p>
+     *
+     * @param element {@link Element}
+     * @param size {@link Size}
+     * @param usage usage flags
+     *
+     * @return A new {@link AllocationInfo} holding the given arguments.
+     *
+     * @throws NullPointerException if size was {@code null}.
+     * @throws NullPointerException if element was {@code null}.
+     */
+    public static AllocationInfo newInstance(Element element, Size size, int usage) {
+        return new AllocationInfo(element, size, usage);
+    }
+
+    /**
+     * Create a new {@link AllocationInfo} by copying the existing data but appending
+     * the new usage flags to the old usage flags.
+     *
+     * @param usage usage flags
+     *
+     * @return A new {@link AllocationInfo} with new usage flags ORd to the old ones.
+     */
+    public AllocationInfo addExtraUsage(int usage) {
+        return new AllocationInfo(mElement, mSize, mUsage | usage);
+    }
+
+    /**
+     * Create a new {@link AllocationInfo} by copying the existing data but changing the format,
+     * and appending the new usage flags to the old usage flags.
+     *
+     * @param format Format
+     * @param usage usage flags
+     *
+     * @return A new {@link AllocationInfo} with new format/usage.
+     *
+     * @see ImageFormat
+     * @see PixelFormat
+     */
+    public AllocationInfo changeFormatAndUsage(int format, int usage) {
+        return newInstance(getSize(), format, usage);
+    }
+
+    /**
+     * Create a new {@link AllocationInfo} by copying the existing data but replacing the old
+     * usage with the new usage flags.
+     *
+     * @param usage usage flags
+     *
+     * @return A new {@link AllocationInfo} with new format/usage.
+     *
+     * @see ImageFormat
+     * @see PixelFormat
+     */
+    public AllocationInfo changeElementWithDefaultUsage(Element element) {
+        return newInstance(element, getSize());
+    }
+
+    /**
+     * Create a new {@link AllocationInfo} by copying the existing data but changing the format,
+     * and replacing the old usage flags with default usage flags.
+     *
+     * @param format Format
+     *
+     * @return A new {@link AllocationInfo} with new format/usage.
+     *
+     * @see ImageFormat
+     * @see PixelFormat
+     */
+    public AllocationInfo changeFormatWithDefaultUsage(int format) {
+        return newInstance(getSize(), format, Allocation.USAGE_SCRIPT);
+    }
+
+    private AllocationInfo(Element element, Size size, int usage) {
+        checkNotNull("element", element);
+        checkNotNull("size", size);
+
+        mElement = element;
+        mSize = size;
+        mUsage = usage;
+
+        Type.Builder typeBuilder = typeBuilder(element, size);
+
+        if (element.equals(Element.YUV(mRS))) {
+            typeBuilder.setYuvFormat(ImageFormat.YUV_420_888);
+        }
+
+        mType = typeBuilder.create();
+    }
+
+    /**
+     * Get the {@link Type type} for this info.
+     *
+     * <p>Note that this is the same type that would get used by the {@link Allocation}
+     * created with {@link #createAllocation()}.
+     *
+     * @return The type (never {@code null}).
+     */
+    public Type getType() {
+        return mType;
+    }
+
+    /**
+     * Get the usage.
+     *
+     * <p>The bit for {@link Allocation#USAGE_SCRIPT} will always be set to 1.</p>
+     *
+     * @return usage flags
+     */
+    public int getUsage() {
+        return mUsage;
+    }
+
+    /**
+     * Get the size.
+     *
+     * @return The size (never {@code null}).
+     */
+    public Size getSize() {
+        return mSize;
+    }
+
+    /**
+     * Get the {@link Element}.
+     *
+     * @return The element (never {@code null}).
+     */
+    public Element getElement() {
+        return mElement;
+    }
+
+    /**
+     * Convenience enum to represent commonly-used elements without needing a RenderScript object.
+     */
+    public enum ElementInfo {
+        YUV,
+        RGBA_8888,
+        U8_3,
+        U8_4;
+
+        private static final String TAG = "ElementInfo";
+
+        /**
+         * Create an {@link ElementInfo} by converting it from a {@link Element}.
+         *
+         * @param element The element for which you want to get an enum for.
+         *
+         * @return The element info is a corresponding one exists, or {@code null} otherwise.
+         */
+        public static ElementInfo fromElement(Element element) {
+            checkNotNull("element", element);
+
+            if (element.equals(Element.YUV(RenderScriptSingleton.getRS()))) {
+                return YUV;
+            } else if (element.equals(Element.RGBA_8888(RenderScriptSingleton.getRS()))) {
+                return RGBA_8888;
+            } else if (element.equals(Element.U8_3(RenderScriptSingleton.getRS()))) {
+                return U8_3;
+            } else if (element.equals(Element.U8_4(RenderScriptSingleton.getRS()))) {
+                return U8_4;
+            }
+            // TODO: add more comparisons here as necessary
+
+            Log.w(TAG, "Unknown element of data kind " + element.getDataKind());
+            return null;
+        }
+    }
+
+    /**
+     * Compare the current element against the suggested element (info).
+     *
+     * @param element The other element to compare against.
+     *
+     * @return true if the elements are equal, false otherwise.
+     */
+    public boolean isElementEqualTo(ElementInfo element) {
+        checkNotNull("element", element);
+
+        Element comparison;
+        switch (element) {
+            case YUV:
+                comparison = Element.YUV(mRS);
+                break;
+            case RGBA_8888:
+                comparison = Element.RGBA_8888(mRS);
+                break;
+            case U8_3:
+                comparison = Element.U8_3(mRS);
+                break;
+            case U8_4:
+                comparison = Element.U8_4(mRS);
+                break;
+            default:
+            // TODO: add more comparisons here as necessary
+                comparison = null;
+        }
+
+        return mElement.equals(comparison);
+    }
+
+    /**
+     * Human-readable representation of this info.
+     */
+    @Override
+    public String toString() {
+        return String.format("Size: %s, Element: %s, Usage: %x", mSize,
+                ElementInfo.fromElement(mElement), mUsage);
+    }
+
+    /**
+     * Compare against another object.
+     *
+     * <p>Comparisons against objects that are not instances of {@link AllocationInfo}
+     * always return {@code false}.</p>
+     *
+     * <p>Two {@link AllocationInfo infos} are considered equal only if their elements,
+     * sizes, and usage flags are also equal.</p>
+     *
+     * @param other Another info object
+     *
+     * @return true if this is equal to other
+     */
+    @Override
+    public boolean equals(Object other) {
+        if (other instanceof AllocationInfo) {
+            return equals((AllocationInfo)other);
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Compare against another object.
+     *
+     * <p>Two {@link AllocationInfo infos} are considered equal only if their elements,
+     * sizes, and usage flags are also equal.</p>
+     *
+     * @param other Another info object
+     *
+     * @return true if this is equal to other
+     */
+    public boolean equals(AllocationInfo other) {
+        if (other == null) {
+            return false;
+        }
+
+        // Element, Size equality is already incorporated into Type equality
+        return mType.equals(other.mType) && mUsage == other.mUsage;
+    }
+
+    /**
+     * Create a new {@link Allocation} using the {@link #getType type} and {@link #getUsage usage}
+     * from this info object.
+     *
+     * <p>The allocation is always created from a {@link AllocationCache cache}. If possible,
+     * return it to the cache once done (although this is not necessary).</p>
+     *
+     * @return a new {@link Allocation}
+     */
+    public Allocation createAllocation() {
+        if (VERBOSE) Log.v(TAG, "createAllocation - for info =" + toString());
+        return RenderScriptSingleton.getCache().getOrCreateTyped(mType, mUsage);
+    }
+
+    /**
+     * Create a new {@link Allocation} using the {@link #getType type} and {@link #getUsage usage}
+     * from this info object; immediately wrap inside a new {@link BlockingInputAllocation}.
+     *
+     * <p>The allocation is always created from a {@link AllocationCache cache}. If possible,
+     * return it to the cache once done (although this is not necessary).</p>
+     *
+     * @return a new {@link Allocation}
+     *
+     * @throws IllegalArgumentException
+     *            If the usage did not have one of {@code USAGE_IO_INPUT} or {@code USAGE_IO_OUTPUT}
+     */
+    public BlockingInputAllocation createBlockingInputAllocation() {
+        Allocation alloc = createAllocation();
+        return BlockingInputAllocation.wrap(alloc);
+    }
+
+    private static Type.Builder typeBuilder(Element element, Size size) {
+        Type.Builder builder = (new Type.Builder(RenderScriptSingleton.getRS(), element))
+                .setX(size.getWidth())
+                .setY(size.getHeight());
+
+        return builder;
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/rs/BlockingInputAllocation.java b/tests/tests/hardware/src/android/hardware/camera2/cts/rs/BlockingInputAllocation.java
new file mode 100644
index 0000000..0305540
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/rs/BlockingInputAllocation.java
@@ -0,0 +1,206 @@
+/*
+ * 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.rs;
+
+import static android.hardware.camera2.cts.helpers.Preconditions.*;
+
+import android.hardware.camera2.cts.helpers.UncheckedCloseable;
+import android.renderscript.Allocation;
+import android.util.Log;
+
+import com.android.ex.camera2.exceptions.TimeoutRuntimeException;
+
+/**
+ * An {@link Allocation} wrapper that can be used to block until new buffers are available.
+ *
+ * <p>Can only be used only with {@link Allocation#USAGE_IO_INPUT} usage Allocations.</p>
+ *
+ * <p>When used with a {@link android.hardware.camera2.CameraDevice CameraDevice} this
+ * must be used as an output surface.</p>
+ */
+class BlockingInputAllocation implements UncheckedCloseable {
+
+    private static final String TAG = BlockingInputAllocation.class.getSimpleName();
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+
+    private final Allocation mAllocation;
+    private final OnBufferAvailableListener mListener;
+    private boolean mClosed;
+
+    /**
+     * Wrap an existing Allocation with this {@link BlockingInputAllocation}.
+     *
+     * <p>Doing this will clear any existing associated buffer listeners and replace
+     * it with a new one.</p>
+     *
+     * @param allocation A non-{@code null} {@link Allocation allocation}
+     * @return a new {@link BlockingInputAllocation} instance
+     *
+     * @throws NullPointerException
+     *           If {@code allocation} was {@code null}
+     * @throws IllegalArgumentException
+     *           If {@code allocation}'s usage did not have one of USAGE_IO_INPUT or USAGE_IO_OUTPUT
+     * @throws IllegalStateException
+     *           If this object has already been {@link #close closed}
+     */
+    public static BlockingInputAllocation wrap(Allocation allocation) {
+        checkNotNull("allocation", allocation);
+        checkBitFlags("usage", allocation.getUsage(), "USAGE_IO_INPUT", Allocation.USAGE_IO_INPUT);
+
+        return new BlockingInputAllocation(allocation);
+    }
+
+    /**
+     * Get the Allocation backing this {@link BlockingInputAllocation}.
+     *
+     * @return Allocation instance (non-{@code null}).
+     *
+     * @throws IllegalStateException If this object has already been {@link #close closed}
+     */
+    public Allocation getAllocation() {
+        checkNotClosed();
+
+        return mAllocation;
+    }
+
+    /**
+     * Waits for a buffer to become available, then immediately
+     * {@link Allocation#ioReceive receives} it.
+     *
+     * <p>After calling this, the next script used with this allocation will use the
+     * newer buffer.</p>
+     *
+     * @throws TimeoutRuntimeException If waiting for the buffer has timed out.
+     * @throws IllegalStateException If this object has already been {@link #close closed}
+     */
+    public synchronized void waitForBufferAndReceive() {
+        checkNotClosed();
+
+        if (VERBOSE) Log.v(TAG, "waitForBufferAndReceive - begin");
+
+        mListener.waitForBuffer();
+        mAllocation.ioReceive();
+
+        if (VERBOSE) Log.v(TAG, "waitForBufferAndReceive - Allocation#ioReceive");
+    }
+
+    /**
+     * If there are multiple pending buffers, {@link Allocation#ioReceive receive} the latest one.
+     *
+     * <p>Does not block if there are no currently pending buffers.</p>
+     *
+     * @return {@code true} only if any buffers were received.
+     *
+     * @throws IllegalStateException If this object has already been {@link #close closed}
+     */
+    public synchronized boolean receiveLatestAvailableBuffers() {
+        checkNotClosed();
+
+        int updatedBuffers = 0;
+        while (mListener.isBufferPending()) {
+            mListener.waitForBuffer();
+            mAllocation.ioReceive();
+            updatedBuffers++;
+        }
+
+        if (VERBOSE) Log.v(TAG, "receiveLatestAvailableBuffers - updated = " + updatedBuffers);
+
+        return updatedBuffers > 0;
+    }
+
+    /**
+     * Closes the object and detaches the listener from the {@link Allocation}.
+     *
+     * <p>This has a side effect of calling {@link #receiveLatestAvailableBuffers}
+     *
+     * <p>Does <i>not</i> destroy the underlying {@link Allocation}.</p>
+     */
+    @Override
+    public synchronized void close() {
+        if (mClosed) return;
+
+        receiveLatestAvailableBuffers();
+        mAllocation.setOnBufferAvailableListener(/*callback*/null);
+        mClosed = true;
+    }
+
+    protected void checkNotClosed() {
+        if (mClosed) {
+            throw new IllegalStateException(TAG + " has been closed");
+        }
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            close();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    private BlockingInputAllocation(Allocation allocation) {
+        mAllocation = allocation;
+
+        mListener = new OnBufferAvailableListener();
+        mAllocation.setOnBufferAvailableListener(mListener);
+    }
+
+    // TODO: refactor with the ImageReader Listener code to use a LinkedBlockingQueue
+    private static class OnBufferAvailableListener implements Allocation.OnBufferAvailableListener {
+        private int mPendingBuffers = 0;
+        private final Object mBufferSyncObject = new Object();
+        private static final int TIMEOUT_MS = 5000;
+
+        public boolean isBufferPending() {
+            synchronized (mBufferSyncObject) {
+                return (mPendingBuffers > 0);
+            }
+        }
+
+        /**
+         * Waits for a buffer. Caller must call ioReceive exactly once after calling this.
+         *
+         * @throws TimeoutRuntimeException If waiting for the buffer has timed out.
+         */
+        public void waitForBuffer() {
+            synchronized (mBufferSyncObject) {
+                while (mPendingBuffers == 0) {
+                    try {
+                        if (VERBOSE) Log.v(TAG, "waiting for next buffer");
+                        mBufferSyncObject.wait(TIMEOUT_MS);
+                        if (mPendingBuffers == 0) {
+                            throw new TimeoutRuntimeException("wait for buffer image timed out");
+                        }
+                    } catch (InterruptedException ie) {
+                        throw new AssertionError(ie);
+                    }
+                }
+                mPendingBuffers--;
+            }
+        }
+
+        @Override
+        public void onBufferAvailable(Allocation a) {
+            if (VERBOSE) Log.v(TAG, "new buffer in allocation available");
+            synchronized (mBufferSyncObject) {
+                mPendingBuffers++;
+                mBufferSyncObject.notifyAll();
+            }
+        }
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/rs/RenderScriptSingleton.java b/tests/tests/hardware/src/android/hardware/camera2/cts/rs/RenderScriptSingleton.java
new file mode 100644
index 0000000..8e4c8e9
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/rs/RenderScriptSingleton.java
@@ -0,0 +1,110 @@
+/*
+ * 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.rs;
+
+import android.content.Context;
+import android.renderscript.RenderScript;
+import android.util.Log;
+
+// TODO : Replace with dependency injection
+/**
+ * Singleton to hold {@link RenderScript} and {@link AllocationCache} objects.
+ *
+ * <p>The test method must call {@link #setContext} before attempting to retrieve
+ * the underlying objects.</p> *
+ */
+public class RenderScriptSingleton {
+
+    private static final String TAG = "RenderScriptSingleton";
+
+    private static Context sContext;
+    private static RenderScript sRS;
+    private static AllocationCache sCache;
+
+    /**
+     * Initialize the singletons from the given context; the
+     * {@link RenderScript} and {@link AllocationCache} objects are instantiated.
+     *
+     * @param context a non-{@code null} Context.
+     *
+     * @throws IllegalStateException If this was called repeatedly without {@link #clearContext}
+     */
+    public static synchronized void setContext(Context context) {
+        if (context.equals(sContext)) {
+            return;
+        } else if (sContext != null) {
+            Log.v(TAG,
+                    "Trying to set new context " + context +
+                    ", before clearing previous "+ sContext);
+            throw new IllegalStateException(
+                    "Call #clearContext before trying to set a new context");
+        }
+
+        sRS = RenderScript.create(context);
+        sContext = context;
+        sCache = new AllocationCache(sRS);
+    }
+
+    /**
+     * Clean up the singletons from the given context; the
+     * {@link RenderScript} and {@link AllocationCache} objects are destroyed.
+     *
+     * <p>Safe to call multiple times; subsequent invocations have no effect.</p>
+     */
+    public static synchronized void clearContext() {
+        if (sContext != null) {
+            sCache.close();
+            sCache = null;
+
+            sRS.destroy();
+            sRS = null;
+            sContext = null;
+        }
+    }
+
+    /**
+     * Get the current {@link RenderScript} singleton.
+     *
+     * @return A non-{@code null} {@link RenderScript} object.
+     *
+     * @throws IllegalStateException if {@link #setContext} was not called prior to this
+     */
+    public static synchronized RenderScript getRS() {
+        if (sRS == null) {
+            throw new IllegalStateException("Call #setContext before using #get");
+        }
+
+        return sRS;
+    }
+    /**
+     * Get the current {@link AllocationCache} singleton.
+     *
+     * @return A non-{@code null} {@link AllocationCache} object.
+     *
+     * @throws IllegalStateException if {@link #setContext} was not called prior to this
+     */
+    public static synchronized AllocationCache getCache() {
+        if (sCache == null) {
+            throw new IllegalStateException("Call #setContext before using #getCache");
+        }
+
+        return sCache;
+    }
+
+    // Suppress default constructor for noninstantiability
+    private RenderScriptSingleton() { throw new AssertionError(); }
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/rs/Script.java b/tests/tests/hardware/src/android/hardware/camera2/cts/rs/Script.java
new file mode 100644
index 0000000..92ff1cb
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/rs/Script.java
@@ -0,0 +1,368 @@
+/*
+ * 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.rs;
+
+import static android.hardware.camera2.cts.helpers.Preconditions.*;
+
+import android.hardware.camera2.cts.helpers.UncheckedCloseable;
+import android.renderscript.Allocation;
+import android.renderscript.RenderScript;
+import android.util.Log;
+
+import java.util.HashMap;
+
+/**
+ * Base class for all renderscript script abstractions.
+ *
+ * <p>Each script has exactly one input and one output allocation, and is able to execute
+ * one {@link android.renderscript.Script} script file.</p>
+ *
+ * <p>Each script owns it's input allocation, but not the output allocation.</p>
+ *
+ * <p>Subclasses of this class must implement exactly one of two constructors:
+ * <ul>
+ * <li>{@code ScriptSubclass(AllocationInfo inputInfo)}
+ *  - if it expects 0 parameters
+ * <li>{@code ScriptSubclass(AllocationInfo inputInfo, ParameterMap<T> parameterMap))}
+ *  - if it expects 1 or more parameters
+ * </ul>
+ *
+ * @param <T> A concrete subclass of {@link android.renderscript.Script}
+ */
+public abstract class Script<T extends android.renderscript.Script> implements UncheckedCloseable {
+
+    /**
+     * A type-safe heterogenous parameter map for script parameters.
+     *
+     * @param <ScriptT> A concrete subclass of {@link Script}.
+     */
+    public static class ParameterMap<ScriptT extends Script<?>> {
+        private final HashMap<Script.ScriptParameter<ScriptT, ?>, Object> mParameterMap =
+                new HashMap<Script.ScriptParameter<ScriptT, ?>, Object>();
+
+        /**
+         * Create a new parameter map with 0 parameters.</p>
+         */
+        public ParameterMap() {}
+
+        /**
+         * Get the value associated with the given parameter key.
+         *
+         * @param parameter A type-safe key corresponding to a parameter.
+         *
+         * @return The value, or {@code null} if none was set.
+         *
+         * @param <T> The type of the value
+         *
+         * @throws NullPointerException if parameter was {@code null}
+         */
+        @SuppressWarnings("unchecked")
+        public <T> T get(Script.ScriptParameter<ScriptT, T> parameter) {
+            checkNotNull("parameter", parameter);
+
+            return (T) mParameterMap.get(parameter);
+        }
+
+        /**
+         * Sets the value associated with the given parameter key.
+         *
+         * @param parameter A type-safe key corresponding to a parameter.
+         * @param value The value
+         *
+         * @param <T> The type of the value
+         *
+         * @throws NullPointerException if parameter was {@code null}
+         * @throws NullPointerException if value was {@code null}
+         */
+        public <T> void set(Script.ScriptParameter<ScriptT, T> parameter, T value) {
+            checkNotNull("parameter", parameter);
+            checkNotNull("value", value);
+
+            if (!parameter.getValueClass().isInstance(value)) {
+                throw new IllegalArgumentException(
+                        "Runtime type mismatch between " + parameter + " and value " + value);
+            }
+
+            mParameterMap.put(parameter, value);
+        }
+
+        /**
+         * Whether or not at least one parameter has been {@link #set}.
+         *
+         * @return true if there is at least one element in the map
+         */
+        public boolean isEmpty() {
+            return mParameterMap.isEmpty();
+        }
+
+        /**
+         * Check if the parameter has been {@link #set} to a value.
+         *
+         * @param parameter A type-safe key corresponding to a parameter.
+         * @return true if there is a value corresponding to this parameter, false otherwise.
+         */
+        public boolean contains(Script.ScriptParameter<ScriptT, ?> parameter) {
+            checkNotNull("parameter", parameter);
+
+            return mParameterMap.containsKey(parameter);
+        }
+    }
+
+    /**
+     * A type-safe parameter key to be used with {@link ParameterMap}.
+     *
+     * @param <J> A concrete subclass of {@link Script}.
+     * @param <K> The type of the value that the parameter holds.
+     */
+    public static class ScriptParameter<J extends Script<?>, K> {
+        private final Class<J> mScriptClass;
+        private final Class<K> mValueClass;
+
+        ScriptParameter(Class<J> jClass, Class<K> kClass) {
+            checkNotNull("jClass", jClass);
+            checkNotNull("kClass", kClass);
+
+            mScriptClass = jClass;
+            mValueClass = kClass;
+        }
+
+        /**
+         * Get the runtime class associated with the value.
+         */
+        public Class<K> getValueClass() {
+            return mValueClass;
+        }
+
+        /**
+         * Compare with another object.
+         *
+         * <p>Two script parameters are considered equal only if their script class and value
+         * class are both equal.</p>
+         */
+        @SuppressWarnings("unchecked")
+        @Override
+        public boolean equals(Object other) {
+            if (other instanceof ScriptParameter) {
+                ScriptParameter<J, K> otherParam = (ScriptParameter<J,K>) other;
+
+                return mScriptClass.equals(otherParam.mScriptClass) &&
+                        mValueClass.equals(otherParam.mValueClass);
+            }
+
+            return false;
+        }
+
+        /**
+         * Gets the hash code for this object.
+         */
+        @Override
+        public int hashCode() {
+            return mScriptClass.hashCode() ^ mValueClass.hashCode();
+        }
+    }
+
+    private static final String TAG = "Script";
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+
+    protected final AllocationCache mCache = RenderScriptSingleton.getCache();
+    protected final RenderScript mRS = RenderScriptSingleton.getRS();
+
+    protected final AllocationInfo mInputInfo;
+    protected final AllocationInfo mOutputInfo;
+
+    protected Allocation mOutputAllocation;
+    protected Allocation mInputAllocation;
+
+    protected final T mScript;
+    private boolean mClosed = false;
+
+    /**
+     * Gets the {@link AllocationInfo info} associated with this script's input.
+     *
+     * @return A non-{@code null} {@link AllocationInfo} object.
+     *
+     * @throws IllegalStateException If the script has already been {@link #close closed}.
+     */
+    public AllocationInfo getInputInfo() {
+        checkNotClosed();
+
+        return mInputInfo;
+    }
+    /**
+     * Gets the {@link AllocationInfo info} associated with this script's output.
+     *
+     * @return A non-{@code null} {@link AllocationInfo} object.
+     *
+     * @throws IllegalStateException If the script has already been {@link #close closed}.
+     */
+    public AllocationInfo getOutputInfo() {
+        checkNotClosed();
+
+        return mOutputInfo;
+    }
+
+    /**
+     * Set the input.
+     *
+     * <p>Must be called before executing any scripts.</p>
+     *
+     * @throws IllegalStateException If the script has already been {@link #close closed}.
+     */
+    void setInput(Allocation allocation) {
+        checkNotClosed();
+        checkNotNull("allocation", allocation);
+        checkEquals("allocation info", AllocationInfo.newInstance(allocation),
+                "input info", mInputInfo);
+
+        // Scripts own the input, so return old input to cache if the input changes
+        if (mInputAllocation != allocation) {
+            mCache.returnToCacheIfNotNull(mInputAllocation);
+        }
+
+        mInputAllocation = allocation;
+        updateScriptInput();
+    }
+
+    protected abstract void updateScriptInput();
+
+    /**
+     * Set the output.
+     *
+     * <p>Must be called before executing any scripts.</p>
+     *
+     * @throws IllegalStateException If the script has already been {@link #close closed}.
+     */
+    void setOutput(Allocation allocation) {
+        checkNotClosed();
+        checkNotNull("allocation", allocation);
+        checkEquals("allocation info", AllocationInfo.newInstance(allocation),
+                "output info", mOutputInfo);
+
+        // Scripts do not own the output, simply set a reference to the new one.
+        mOutputAllocation = allocation;
+    }
+
+    protected Script(AllocationInfo inputInfo, AllocationInfo outputInfo, T rsScript) {
+        checkNotNull("inputInfo", inputInfo);
+        checkNotNull("outputInfo", outputInfo);
+        checkNotNull("rsScript", rsScript);
+
+        mInputInfo = inputInfo;
+        mOutputInfo = outputInfo;
+        mScript = rsScript;
+
+        if (VERBOSE) {
+            Log.v(TAG, String.format("%s - inputInfo = %s, outputInfo = %s, rsScript = %s",
+                    getName(), inputInfo, outputInfo, rsScript));
+        }
+    }
+
+    /**
+     * Get the {@link Allocation} associated with this script's input.</p>
+     *
+     * @return The input {@link Allocation}, which is never {@code null}.
+     *
+     * @throws IllegalStateException If the script has already been {@link #close closed}.
+     */
+    public Allocation getInput() {
+        checkNotClosed();
+
+        return mInputAllocation;
+    }
+    /**
+     * Get the {@link Allocation} associated with this script's output.</p>
+     *
+     * @return The output {@link Allocation}, which is never {@code null}.
+     *
+     * @throws IllegalStateException If the script has already been {@link #close closed}.
+     */
+    public Allocation getOutput() {
+        checkNotClosed();
+
+        return mOutputAllocation;
+    }
+
+    /**
+     * Execute the script's kernel against the input/output {@link Allocation allocations}.
+     *
+     * <p>Once this is complete, the output will have the new data available (for either
+     * the next script, or to read out with a copy).</p>
+     *
+     * @throws IllegalStateException If the script has already been {@link #close closed}.
+     */
+    public void execute() {
+        checkNotClosed();
+
+        if (mInputAllocation == null || mOutputAllocation == null) {
+            throw new IllegalStateException("Both inputs and outputs must have been set");
+        }
+
+        executeUnchecked();
+    }
+
+    /**
+     * Get the name of this script.
+     *
+     * <p>The name is the short hand name of the concrete class backing this script.</p>
+     *
+     * <p>This method works even if the script has already been {@link #close closed}.</p>
+     *
+     * @return A string representing the script name.
+     */
+    public String getName() {
+        return getClass().getSimpleName();
+    }
+
+    protected abstract void executeUnchecked();
+
+    protected void checkNotClosed() {
+        if (mClosed) {
+            throw new IllegalStateException("Script has been closed");
+        }
+    }
+
+    /**
+     * Destroy the underlying script object and return the input allocation back to the
+     * {@link AllocationCache cache}.
+     *
+     * <p>This method has no effect if called more than once.</p>
+     */
+    @Override
+    public void close() {
+        if (mClosed) return;
+
+        // Scripts own the input allocation. They do NOT own outputs.
+        mCache.returnToCacheIfNotNull(mInputAllocation);
+
+        mScript.destroy();
+
+        mClosed = true;
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            close();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    protected static RenderScript getRS() {
+        return RenderScriptSingleton.getRS();
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/rs/ScriptGraph.java b/tests/tests/hardware/src/android/hardware/camera2/cts/rs/ScriptGraph.java
new file mode 100644
index 0000000..56d8703
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/rs/ScriptGraph.java
@@ -0,0 +1,656 @@
+/*
+ * 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.rs;
+
+import static android.hardware.camera2.cts.helpers.Preconditions.*;
+import static junit.framework.Assert.*;
+
+import android.graphics.ImageFormat;
+import android.graphics.PixelFormat;
+import android.util.Size;
+import android.hardware.camera2.cts.helpers.MaybeNull;
+import android.hardware.camera2.cts.helpers.UncheckedCloseable;
+import android.hardware.camera2.cts.rs.Script.ParameterMap;
+import android.renderscript.Allocation;
+import android.util.Log;
+import android.view.Surface;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+import com.android.ex.camera2.exceptions.TimeoutRuntimeException;
+
+/**
+ * An abstraction to simplify chaining together the execution of multiple RenderScript
+ * {@link android.renderscript.Script scripts} and managing their {@link Allocation allocations}.
+ *
+ * <p>Create a new script graph by using {@link #create}, configure the input with
+ * {@link Builder#configureInput}, then configure one or more scripts with
+ * {@link Builder#configureScript} or {@link Builder#chainScript}. Finally, freeze the graph
+ * with {@link Builder#buildGraph}.</p>
+ *
+ * <p>Once a script graph has been built, all underlying scripts and allocations are instantiated.
+ * Each script may be executed with {@link #execute}. Scripts are executed in the order that they
+ * were configured, with each previous script's output used as the input for the next script.
+ * </p>
+ *
+ * <p>In case the input {@link Allocation} is actually backed by a {@link Surface}, convenience
+ * methods ({@link #advanceInputWaiting} and {@link #advanceInputAndDrop} are provided to
+ * automatically update the {@link Allocation allocation} with the latest buffer available.</p>
+ *
+ * <p>All resources are managed by the {@link ScriptGraph} and {@link #close closing} the graph
+ * will release all underlying resources. See {@link #close} for more details.</p>
+ */
+public class ScriptGraph implements UncheckedCloseable {
+
+    private static final String TAG = "ScriptGraph";
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+
+    private static final int INPUT_SCRIPT_LOCATION = 0;
+    private final int OUTPUT_SCRIPT_LOCATION; // calculated in constructor
+
+    private final AllocationCache mCache = RenderScriptSingleton.getCache();
+
+    private final Size mSize;
+    private final int mFormat;
+    private final int mUsage;
+    private final List<Script<?>> mScripts;
+
+    private final BlockingInputAllocation mInputBlocker;
+    private final Allocation mOutputAllocation;
+    private boolean mClosed = false;
+
+    /**
+     * Create a new {@link Builder} that will be used to configure the graph's inputs
+     * and scripts (and parameters).
+     *
+     * <p>Once a graph has been fully built, the configuration is immutable.</p>
+     *
+     * @return a {@link Builder} that will be used to configure the graph settings
+     */
+    public static Builder create() {
+        return new Builder();
+    }
+
+    /**
+     * Wait until another buffer is produced into the input {@link Surface}, then
+     * update the backing input {@link Allocation} with the latest buffer with
+     * {@link Allocation#ioReceive ioReceive}.
+     *
+     * @throws IllegalArgumentException
+     *            if the graph wasn't configured with
+     *            {@link Builder#configureInputWithSurface configureInputWithSurface}
+     * @throws TimeoutRuntimeException
+     *            if waiting for the buffer times out
+     */
+    public void advanceInputWaiting() {
+        checkNotClosed();
+        if (!isInputFromSurface()) {
+            throw new IllegalArgumentException("Graph was not configured with USAGE_IO_INPUT");
+        }
+
+        mInputBlocker.waitForBufferAndReceive();
+    }
+
+    /**
+     * Update the backing input {@link Allocation} with the latest buffer with
+     * {@link Allocation#ioReceive ioReceive} repeatedly until no more buffers are pending.
+     *
+     * <p>Does not wait for new buffers to become available if none are currently available
+     * (i.e. {@code false} is returned immediately).</p>
+     *
+     * @return true if any buffers were pending
+     *
+     * @throws IllegalArgumentException
+     *            if the graph wasn't configured with
+     *            {@link Builder#configureInputWithSurface configureInputWithSurface}
+     * @throws TimeoutRuntimeException
+     *            if waiting for the buffer times out
+     */
+    public boolean advanceInputAndDrop() {
+        checkNotClosed();
+        if (!isInputFromSurface()) {
+            throw new IllegalArgumentException("Graph was not configured with USAGE_IO_INPUT");
+        }
+
+        return mInputBlocker.receiveLatestAvailableBuffers();
+    }
+
+    /**
+     * Execute each script in the graph, with each next script's input using the
+     * previous script's output.
+     *
+     * <p>Scripts are executed in the same order that they were configured by the {@link Builder}.
+     * </p>
+     *
+     * @throws IllegalStateException if the graph was already {@link #close closed}
+     */
+    public void execute() {
+        checkNotClosed();
+
+        // TODO: Can we use android.renderscript.ScriptGroup here to make it faster?
+
+        int i = 0;
+        for (Script<?> script : mScripts) {
+            script.execute();
+            i++;
+        }
+
+        if (VERBOSE) Log.v(TAG, "execute - invoked " + i + " scripts");
+    }
+
+    /**
+     * Copies the data from the last script's output {@link Allocation} into a byte array.
+     *
+     * <p>The output allocation must be of an 8 bit integer
+     * {@link android.renderscript.Element Element} type.</p>
+     *
+     * @return A byte[] copy.
+     *
+     * @throws IllegalStateException if the graph was already {@link #close closed}
+     */
+    public byte[] getOutputData() {
+        checkNotClosed();
+
+        Allocation outputAllocation = getOutputAllocation();
+
+        byte[] destination = new byte[outputAllocation.getBytesSize()];
+        outputAllocation.copyTo(destination);
+
+        return destination;
+    }
+
+    /**
+     * Copies the data from the first script's input {@link Allocation} into a byte array.
+     *
+     * <p>The input allocation must be of an 8 bit integer
+     * {@link android.renderscript.Element Element} type.</p>
+     *
+     * @return A byte[] copy.
+     *
+     * @throws IllegalStateException if the graph was already {@link #close closed}
+     */
+    public byte[] getInputData() {
+        checkNotClosed();
+
+        Allocation inputAllocation = getInputAllocation();
+
+        byte[] destination = new byte[inputAllocation.getBytesSize()];
+        inputAllocation.copyTo(destination);
+
+        return destination;
+    }
+
+    /**
+     * Builds a {@link ScriptGraph} by configuring input size/format/usage,
+     * the script classes in the graph, and the parameters passed to the scripts.
+     *
+     * @see ScriptGraph#create
+     */
+    public static class Builder {
+
+        private Size mSize;
+        private int mFormat;
+        private int mUsage;
+
+        private final List<ScriptBuilder<? extends Script<?>>> mChainedScriptBuilders =
+                new ArrayList<ScriptBuilder<? extends Script<?>>>();
+
+        /**
+         * Configure the {@link Allocation} that will be used as the input to the first
+         * script, using the default usage.
+         *
+         * <p>Short hand for calling {@link #configureInput(int, int, int, int)} with a
+         * {@code 0} usage.</p>
+         *
+         * @param width Width in pixels
+         * @param height Height in pixels
+         * @param format Format from {@link ImageFormat} or {@link PixelFormat}
+         *
+         * @return The current builder ({@code this}). Use for chaining method calls.
+         */
+        public Builder configureInput(int width, int height, int format) {
+            return configureInput(new Size(width, height), format, /*usage*/0);
+        }
+
+        /**
+         * Configure the {@link Allocation} that will be used as the input to the first
+         * script.
+         *
+         * <p>The {@code usage} is always ORd together with {@link Allocation#USAGE_SCRIPT}.</p>
+         *
+         * @param width Width in pixels
+         * @param height Height in pixels
+         * @param format Format from {@link ImageFormat} or {@link PixelFormat}
+         * @param usage Usage flags such as {@link Allocation#USAGE_IO_INPUT}
+         *
+         * @return The current builder ({@code this}). Use for chaining method calls.
+         */
+        public Builder configureInput(int width, int height, int format, int usage) {
+            return configureInput(new Size(width, height), format, usage);
+        }
+
+        /**
+         * Configure the {@link Allocation} that will be used as the input to the first
+         * script, using the default usage.
+         *
+         * <p>Short hand for calling {@link #configureInput(Size, int, int)} with a
+         * {@code 0} usage.</p>
+         *
+         * @param size Size (width, height)
+         * @param format Format from {@link ImageFormat} or {@link PixelFormat}
+         *
+         * @return The current builder ({@code this}). Use for chaining method calls.
+         *
+         * @throws NullPointerException if size was {@code null}
+         */
+        public Builder configureInput(Size size, int format) {
+            return configureInput(size, format, /*usage*/0);
+        }
+
+        /**
+         * Configure the {@link Allocation} that will use a {@link Surface} to produce input into
+         * the first script.
+         *
+         * <p>Short hand for calling {@link #configureInput(Size, int, int)} with the
+         * {@link Allocation#USAGE_IO_INPUT} usage.</p>
+         *
+         * <p>The {@code usage} is always ORd together with {@link Allocation#USAGE_SCRIPT}.</p>
+         *
+         * @param size Size (width, height)
+         * @param format Format from {@link ImageFormat} or {@link PixelFormat}
+         *
+         * @return The current builder ({@code this}). Use for chaining method calls.
+         *
+         * @throws NullPointerException if size was {@code null}
+         */
+        public Builder configureInputWithSurface(Size size, int format) {
+            return configureInput(size, format, Allocation.USAGE_IO_INPUT);
+        }
+
+        /**
+         * Configure the {@link Allocation} that will be used as the input to the first
+         * script.
+         *
+         * <p>The {@code usage} is always ORd together with {@link Allocation#USAGE_SCRIPT}.</p>
+         *
+         * @param size Size (width, height)
+         * @param format Format from {@link ImageFormat} or {@link PixelFormat}
+         * @param usage Usage flags such as {@link Allocation#USAGE_IO_INPUT}
+         *
+         * @return The current builder ({@code this}). Use for chaining method calls.
+         *
+         * @throws NullPointerException if size was {@code null}
+         */
+        public Builder configureInput(Size size, int format, int usage) {
+            checkNotNull("size", size);
+
+            mSize = size;
+            mFormat = format;
+            mUsage = usage | Allocation.USAGE_SCRIPT;
+
+            return this;
+        }
+
+        /**
+         * Build a {@link Script} by setting parameters it might require for execution.
+         *
+         * <p>Refer to the documentation for {@code T} to see if there are any
+         * {@link Script.ScriptParameter parameters} in it.
+         * </p>
+         *
+         * @param <T> Concrete type subclassing the {@link Script} class.
+         */
+        public class ScriptBuilder<T extends Script<?>> {
+
+            private final Class<T> mScriptClass;
+
+            private ScriptBuilder(Class<T> scriptClass) {
+                mScriptClass = scriptClass;
+            }
+
+            private final ParameterMap<T> mParameterMap = new ParameterMap<T>();
+
+            /**
+             * Set a script parameter to the specified value.
+             *
+             * @param parameter The {@link Script.ScriptParameter parameter key} in {@code T}
+             * @param value A value of type {@code K} that the script expects.
+             * @param <K> The type of the parameter {@code value}.
+             *
+             * @return The current builder ({@code this}). Use to chain method calls.
+             *
+             * @throws NullPointerException if parameter was {@code null}
+             * @throws NullPointerException if value was {@code null}
+             * @throws IllegalStateException if the parameter was already {@link #set}
+             */
+            public <K> ScriptBuilder<T> set(Script.ScriptParameter<T, K> parameter, K value) {
+                checkNotNull("parameter", parameter);
+                checkNotNull("value", value);
+                checkState("Parameter has already been set", !mParameterMap.contains(parameter));
+
+                mParameterMap.set(parameter, value);
+
+                return this;
+            }
+
+            ParameterMap<T> getParameterMap() {
+                return mParameterMap;
+            }
+
+            Class<T> getScriptClass() {
+                return mScriptClass;
+            }
+
+            /**
+             * Build the script and freeze the parameter list to what was {@link #set}.
+             *
+             * @return
+             *            The {@link ScriptGraph#Builder} that was used to configure
+             *            {@link this} script.</p>
+             */
+            public Builder buildScript() {
+                mChainedScriptBuilders.add(this);
+
+                return Builder.this;
+            }
+        }
+
+        /**
+         * Configure the script with no parameters.
+         *
+         * <p>Short hand for invoking {@link #configureScript} immediately followed by
+         * {@link ScriptBuilder#buildScript()}.
+         *
+         * @param scriptClass A concrete class that subclasses {@link Script}
+         * @return The current builder ({@code this}). Use to chain method calls.
+         *
+         * @throws NullPointerException if {@code scriptClass} was {@code null}
+         */
+        public <T extends Script<?>> Builder chainScript(Class<T> scriptClass) {
+            checkNotNull("scriptClass", scriptClass);
+
+            return (new ScriptBuilder<T>(scriptClass)).buildScript();
+        }
+
+        /**
+         * Configure the script with parameters.
+         *
+         * <p>Only useful when the {@code scriptClass} has one or more
+         * {@link Script.ScriptParameter script parameters} defined.</p>
+         *
+         * @param scriptClass A concrete class that subclasses {@link Script}
+         * @return A script configuration {@link ScriptBuilder builder}. Use to chain method calls.
+         *
+         * @throws NullPointerException if {@code scriptClass} was {@code null}
+         */
+        public <T extends Script<?>> ScriptBuilder<T> configureScript(Class<T> scriptClass) {
+            checkNotNull("scriptClass", scriptClass);
+
+            return new ScriptBuilder<T>(scriptClass);
+        }
+
+        /**
+         * Finish configuring the graph and freeze the settings, instantiating all
+         * the {@link Script scripts} and {@link Allocation allocations}.
+         *
+         * @return A constructed {@link ScriptGraph}.
+         */
+        public ScriptGraph buildGraph() {
+            return new ScriptGraph(this);
+        }
+
+        private Builder() {}
+    }
+
+    private ScriptGraph(Builder builder) {
+        mSize = builder.mSize;
+        mFormat = builder.mFormat;
+        mUsage = builder.mUsage;
+        List<Builder.ScriptBuilder<? extends Script<?>>> chainedScriptBuilders =
+                builder.mChainedScriptBuilders;
+        mScripts = new ArrayList<Script<?>>(/*capacity*/chainedScriptBuilders.size());
+        OUTPUT_SCRIPT_LOCATION = chainedScriptBuilders.size() - 1;
+
+        if (mSize == null) {
+            throw new IllegalArgumentException("Inputs were not configured");
+        }
+
+        if (chainedScriptBuilders.isEmpty()) {
+            throw new IllegalArgumentException("At least one script should be chained");
+        }
+
+        /*
+         * The first input is special since it could be USAGE_IO_INPUT.
+         */
+        AllocationInfo inputInfo = AllocationInfo.newInstance(mSize, mFormat, mUsage);
+        Allocation inputAllocation;
+
+        // Create an Allocation with a Surface if the input to the graph requires it
+        if (isInputFromSurface()) {
+            mInputBlocker = inputInfo.createBlockingInputAllocation();
+            inputAllocation = mInputBlocker.getAllocation();
+        } else {
+            mInputBlocker = null;
+            inputAllocation = inputInfo.createAllocation();
+        }
+
+        if (VERBOSE) Log.v(TAG, "ScriptGraph() - Instantiating all script classes");
+
+        // Create all scripts.
+        for (Builder.ScriptBuilder<? extends Script<?>> scriptBuilder: chainedScriptBuilders) {
+
+            @SuppressWarnings("unchecked")
+            Class<Script<?>> scriptClass = (Class<Script<?>>) scriptBuilder.getScriptClass();
+
+            @SuppressWarnings("unchecked")
+            ParameterMap<Script<?>> parameters = (ParameterMap<Script<?>>)
+                    scriptBuilder.getParameterMap();
+
+            Script<?> script = instantiateScript(scriptClass, inputInfo, parameters);
+            mScripts.add(script);
+
+            // The next script's input info is the current script's output info
+            inputInfo = script.getOutputInfo();
+        }
+
+        if (VERBOSE) Log.v(TAG, "ScriptGraph() - Creating all inputs");
+
+        // Create and wire up all inputs.
+        int i = 0;
+        Script<?> inputScript = mScripts.get(INPUT_SCRIPT_LOCATION);
+        do {
+            if (VERBOSE) {
+                Log.v(TAG, "ScriptGraph() - Setting input for script " + inputScript.getName());
+            }
+
+            inputScript.setInput(inputAllocation);
+
+            i++;
+
+            if (i >= mScripts.size()) {
+                break;
+            }
+
+            // Use the graph input for the first loop iteration
+            inputScript = mScripts.get(i);
+            inputInfo = inputScript.getInputInfo();
+            inputAllocation = inputInfo.createAllocation();
+        } while (true);
+
+        if (VERBOSE) Log.v(TAG, "ScriptGraph() - Creating all outputs");
+
+        // Create and wire up all outputs.
+        Allocation lastOutput = null;
+        for (i = 0; i < mScripts.size(); ++i) {
+            Script<?> script = mScripts.get(i);
+            Script<?> nextScript = (i + 1 < mScripts.size()) ? mScripts.get(i + 1) : null;
+
+            // Each script's output uses the next script's input.
+            // -- Since the last script has no next script, we own its output allocation.
+            lastOutput = (nextScript != null) ? nextScript.getInput()
+                                              : script.getOutputInfo().createAllocation();
+
+            if (VERBOSE) {
+                Log.v(TAG, "ScriptGraph() - Setting output for script " + script.getName());
+            }
+
+            script.setOutput(lastOutput);
+        }
+        mOutputAllocation = checkNotNull("lastOutput", lastOutput);
+
+        // Done. Safe to execute the graph now.
+
+        if (VERBOSE) Log.v(TAG, "ScriptGraph() - Graph has been built");
+    }
+
+    /**
+     * Construct the script by instantiating it via reflection.
+     *
+     * <p>The {@link Script scriptClass} should have a {@code Script(AllocationInfo inputInfo)}
+     * constructor if it expects an empty parameter map.</p>
+     *
+     * <p>If it expects a non-empty parameter map, it should have a
+     * {@code Script(AllocationInfo inputInfo, ParameterMap<T> parameterMap)} constructor.</p>
+     */
+    private static <T extends Script<?>> T instantiateScript(
+            Class<T> scriptClass, AllocationInfo inputInfo, ParameterMap<T> parameterMap) {
+
+        Constructor<T> ctor;
+        try {
+            // TODO: Would be better if we looked at the script class to see if it expects params
+            if (parameterMap.isEmpty()) {
+                // Script(AllocationInfo inputInfo)
+                ctor = scriptClass.getConstructor(AllocationInfo.class);
+            } else {
+                // Script(AllocationInfo inputInfo, ParameterMap<T> parameterMap)
+                ctor = scriptClass.getConstructor(AllocationInfo.class, ParameterMap.class);
+            }
+        } catch (NoSuchMethodException e) {
+            throw new UnsupportedOperationException(
+                    "Script class " + scriptClass + " must have a matching constructor", e);
+        }
+
+        try {
+            if (parameterMap.isEmpty()) {
+                return ctor.newInstance(inputInfo);
+            } else {
+                return ctor.newInstance(inputInfo, parameterMap);
+            }
+        } catch (InstantiationException e) {
+            throw new UnsupportedOperationException(e);
+        } catch (IllegalAccessException e) {
+            throw new UnsupportedOperationException(e);
+        } catch (IllegalArgumentException e) {
+            throw new UnsupportedOperationException(e);
+        } catch (InvocationTargetException e) {
+            throw new UnsupportedOperationException(e);
+        }
+    }
+
+    private boolean isInputFromSurface() {
+        return (mUsage & Allocation.USAGE_IO_INPUT) != 0;
+    }
+
+    /**
+     * Get the input {@link Allocation} that is used by the first script as the input.
+     *
+     * @return An {@link Allocation} (never {@code null}).
+     *
+     * @throws IllegalStateException if the graph was already {@link #close closed}
+     */
+    public Allocation getInputAllocation() {
+        checkNotClosed();
+
+        return mScripts.get(INPUT_SCRIPT_LOCATION).getInput();
+    }
+
+    /**
+     * Get the output {@link Allocation} that is used by the last script as the output.
+     *
+     * @return An {@link Allocation} (never {@code null}).
+     *
+     * @throws IllegalStateException if the graph was already {@link #close closed}
+     */
+    public Allocation getOutputAllocation() {
+        checkNotClosed();
+        Allocation output = mScripts.get(OUTPUT_SCRIPT_LOCATION).getOutput();
+
+        assertEquals("Graph's output should match last script's output", mOutputAllocation, output);
+
+        return output;
+    }
+
+    /**
+     * Get the {@link Surface} that can be used produce buffers into the
+     * {@link #getInputAllocation input allocation}.
+     *
+     * @throws IllegalStateException
+     *            if input wasn't configured with {@link Allocation#USAGE_IO_INPUT} {@code usage}.
+     * @throws IllegalStateException
+     *            if the graph was already {@link #close closed}
+     *
+     * @return A {@link Surface} (never {@code null}).
+     */
+    public Surface getInputSurface() {
+        checkNotClosed();
+        checkState("This graph was not configured with IO_USAGE_INPUT", isInputFromSurface());
+
+        return getInputAllocation().getSurface();
+    }
+
+    private void checkNotClosed() {
+        checkState("ScriptGraph has been closed", !mClosed);
+    }
+
+    /**
+     * Releases all underlying resources associated with this {@link ScriptGraph}.
+     *
+     * <p>In particular, all underlying {@link Script scripts} and all
+     * {@link Allocation allocations} are also closed.</p>
+     *
+     * <p>All further calls to any other public methods (other than {@link #close}) will throw
+     * an {@link IllegalStateException}.</p>
+     *
+     * <p>This method is idempotent; calling it more than once will
+     * have no further effect.</p>
+     */
+    @Override
+    public synchronized void close() {
+        if (mClosed) return;
+
+        for (Script<?> script : mScripts) {
+            script.close();
+        }
+        mScripts.clear();
+
+        MaybeNull.close(mInputBlocker);
+        mCache.returnToCache(mOutputAllocation);
+
+        mClosed = true;
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            close();
+        } finally {
+            super.finalize();
+        }
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/rs/ScriptYuvCrop.java b/tests/tests/hardware/src/android/hardware/camera2/cts/rs/ScriptYuvCrop.java
new file mode 100644
index 0000000..ae55cc9
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/rs/ScriptYuvCrop.java
@@ -0,0 +1,109 @@
+/*
+ * 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.rs;
+
+import static android.hardware.camera2.cts.helpers.Preconditions.*;
+
+import android.graphics.ImageFormat;
+import android.graphics.RectF;
+import android.util.Size;
+import android.hardware.camera2.cts.ScriptC_crop_yuvf_420_to_yuvx_444;
+import android.hardware.camera2.cts.rs.AllocationInfo.ElementInfo;
+import android.renderscript.Element;
+import android.util.Log;
+
+/**
+ * Crop {@link ImageFormat#YUV_420_888 flexible-YUV} {@link Allocation allocations} into
+ * a {@link ElementInfo#U8_3 U8_3} {@link Allocation allocation}.
+ *
+ * <p>Users of this script must configure it with the
+ * {@link ScriptYuvCrop#CROP_WINDOW crop window} parameter.</p>
+ *
+ */
+public class ScriptYuvCrop extends Script<ScriptC_crop_yuvf_420_to_yuvx_444> {
+    private static final String TAG = "ScriptYuvCrop";
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+
+    /**
+     * A rectangle holding the top,left,right,bottom normalized coordinates each within [0,1].
+     *
+     * <p>The output will be a cropped copy of the input to only this crop window.</p>
+     */
+    // TODO: Change this to use Patch
+    public static final Script.ScriptParameter<ScriptYuvCrop, RectF> CROP_WINDOW =
+            new Script.ScriptParameter<ScriptYuvCrop, RectF>(ScriptYuvCrop.class,
+                    RectF.class);
+
+    private final RectF mCropWindow;
+
+    private static AllocationInfo createOutputInfo(AllocationInfo inputInfo,
+            ParameterMap<ScriptYuvCrop> parameters) {
+        checkNotNull("inputInfo", inputInfo);
+        checkNotNull("parameters", parameters);
+
+        if (!parameters.contains(CROP_WINDOW)) {
+            throw new IllegalArgumentException("Script's CROP_WINDOW was not set");
+        }
+
+        Size inputSize = inputInfo.getSize();
+        RectF crop = parameters.get(CROP_WINDOW);
+        Size outputSize = new Size(
+                (int)(crop.width() * inputSize.getWidth()),
+                (int)(crop.height() * inputSize.getHeight()));
+
+        if (VERBOSE) Log.v(TAG, String.format("createOutputInfo - outputSize is %s", outputSize));
+
+        /**
+         * Input  YUV  W     x H
+         * Output U8_3 CropW x CropH
+         */
+        return AllocationInfo.newInstance(Element.U8_3(getRS()), outputSize);
+    }
+
+    public ScriptYuvCrop(AllocationInfo inputInfo,
+            ParameterMap<ScriptYuvCrop> parameterMap) {
+        super(inputInfo,
+              createOutputInfo(inputInfo, parameterMap),
+              new ScriptC_crop_yuvf_420_to_yuvx_444(getRS()));
+
+        // YUV_420_888 is the only supported format here
+        if (!inputInfo.isElementEqualTo(ElementInfo.YUV)) {
+            throw new UnsupportedOperationException("Unsupported element "
+                    + inputInfo.getElement());
+        }
+
+        mCropWindow = parameterMap.get(CROP_WINDOW);
+    }
+
+    @Override
+    protected void executeUnchecked() {
+        mScript.forEach_crop(mOutputAllocation);
+
+        if (VERBOSE) { Log.v(TAG, "executeUnchecked - forEach_crop done"); }
+    }
+
+    @Override
+    protected void updateScriptInput() {
+        int x = (int)(mCropWindow.left * mInputInfo.getSize().getWidth());
+        int y = (int)(mCropWindow.top * mInputInfo.getSize().getHeight());
+
+        mScript.set_src_x(x);
+        mScript.set_src_y(y);
+
+        mScript.set_mInput(mInputAllocation);
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/rs/ScriptYuvMeans1d.java b/tests/tests/hardware/src/android/hardware/camera2/cts/rs/ScriptYuvMeans1d.java
new file mode 100644
index 0000000..fb76196
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/rs/ScriptYuvMeans1d.java
@@ -0,0 +1,69 @@
+/*
+ * 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.rs;
+
+import static android.hardware.camera2.cts.helpers.Preconditions.*;
+
+import android.util.Size;
+import android.hardware.camera2.cts.ScriptC_means_yuvx_444_1d_to_single;
+import android.hardware.camera2.cts.rs.AllocationInfo.ElementInfo;
+import android.renderscript.Element;
+
+/**
+ * Average a {@code Hx1} {@link ElementInfo#U8_3 U8_3} {@link Allocation allocation} into a 1x1
+ * {@code U8x3} {@link Allocation allocation}.
+ *
+ * <p>Users of this script should chain {@link ScriptYuvMeans1d} immediately before this
+ * to average the input down to a 1x1 element.</p>
+ */
+public class ScriptYuvMeans1d extends Script<ScriptC_means_yuvx_444_1d_to_single>{
+    private static final String TAG = "ScriptYuvMeans1d";
+
+    private static final Size UNIT_SQUARE = new Size(/*width*/1, /*height*/1);
+
+    private static AllocationInfo createOutputInfo(AllocationInfo inputInfo) {
+        checkNotNull("inputInfo", inputInfo);
+        // (input) Hx1 -> 1x1
+        return AllocationInfo.newInstance(Element.U8_3(getRS()), UNIT_SQUARE);
+    }
+
+    public ScriptYuvMeans1d(AllocationInfo inputInfo) {
+        super(inputInfo,
+              createOutputInfo(inputInfo),
+              new ScriptC_means_yuvx_444_1d_to_single(getRS()));
+
+        // U8x3 is the only supported element here
+        if (!inputInfo.isElementEqualTo(ElementInfo.U8_3)) {
+            throw new UnsupportedOperationException("Unsupported element "
+                    + inputInfo.getElement());
+        }
+    }
+
+    @Override
+    protected void executeUnchecked() {
+        mScript.forEach_means_yuvx_444(mOutputAllocation);
+    }
+
+    @Override
+    protected void updateScriptInput() {
+        mScript.set_mInput(mInputAllocation);
+
+        int width = mInputAllocation.getType().getX();
+        mScript.set_width(width);
+        mScript.set_inv_width(1.0f / width);
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/rs/ScriptYuvMeans2dTo1d.java b/tests/tests/hardware/src/android/hardware/camera2/cts/rs/ScriptYuvMeans2dTo1d.java
new file mode 100644
index 0000000..2776f96
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/rs/ScriptYuvMeans2dTo1d.java
@@ -0,0 +1,90 @@
+/*
+ * 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.rs;
+
+import static android.hardware.camera2.cts.helpers.Preconditions.*;
+
+import android.graphics.ImageFormat;
+import android.graphics.RectF;
+import android.util.Size;
+import android.hardware.camera2.cts.ScriptC_means_yuvx_444_2d_to_1d;
+import android.hardware.camera2.cts.rs.AllocationInfo.ElementInfo;
+import android.util.Log;
+
+/**
+ * Average pixels from a {@link ImageFormat#YUV_420_888 flexible-YUV} or
+ * {@link ElementInfo#U8_3 U8_3} {@link Allocation allocations} into a 1D Hx1
+ * {@link ElementInfo#U8_3 U8_3} {@link Allocation allocation}.
+ *
+ * <p>Users of this script should chain {@link ScriptYuvMeans1d} immediately afterwards
+ * to average the output down to a 1x1 element.</p>
+ */
+public class ScriptYuvMeans2dTo1d extends Script<ScriptC_means_yuvx_444_2d_to_1d> {
+
+    private static final String TAG = "ScriptYuvMeans2dTo1d";
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+
+    private static AllocationInfo createOutputInfo(AllocationInfo inputInfo) {
+        checkNotNull("inputInfo", inputInfo);
+        // (input) WxH -> (output) Hx1
+        return AllocationInfo.newInstance(inputInfo.getElement(),
+                new Size(inputInfo.getSize().getHeight(), /*height*/1));
+    }
+
+    public ScriptYuvMeans2dTo1d(AllocationInfo inputInfo) {
+        super(inputInfo,
+              createOutputInfo(inputInfo),
+              new ScriptC_means_yuvx_444_2d_to_1d(getRS()));
+
+        // YUV_420_888 and U8_3 is the only supported format here
+        if (!inputInfo.isElementEqualTo(ElementInfo.YUV) &&
+                !inputInfo.isElementEqualTo(ElementInfo.U8_3)) {
+            throw new UnsupportedOperationException("Unsupported element "
+                    + inputInfo.getElement());
+        }
+    }
+
+    @Override
+    protected void executeUnchecked() {
+        // TODO: replace with switch statement
+        if (mInputInfo.isElementEqualTo(ElementInfo.YUV)) {
+            mScript.forEach_means_yuvf_420(mOutputAllocation);
+
+            if (VERBOSE) Log.v(TAG, "executeUnchecked - forEach_means_yuvf_420");
+        } else if (mInputInfo.isElementEqualTo(ElementInfo.U8_3)) {
+            mScript.forEach_means_yuvx_444(mOutputAllocation);
+
+            if (VERBOSE) Log.v(TAG, "executeUnchecked - forEach_means_yuvx_444");
+        } else {
+            throw new UnsupportedOperationException("Unsupported element "
+                    + mInputInfo.getElement());
+        }
+    }
+
+    @Override
+    protected void updateScriptInput() {
+        mScript.set_mInput(mInputAllocation);
+
+        int width = mInputAllocation.getType().getX();
+        mScript.set_width(width);
+        mScript.set_inv_width(1.0f / width);
+
+        // Do not crop. Those who want to crop should use ScriptYuvCrop.class
+        mScript.set_src_x(0);
+        mScript.set_src_y(0);
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/rs/ScriptYuvToRgb.java b/tests/tests/hardware/src/android/hardware/camera2/cts/rs/ScriptYuvToRgb.java
new file mode 100644
index 0000000..5cdc0a0
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/rs/ScriptYuvToRgb.java
@@ -0,0 +1,64 @@
+/*
+ * 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.rs;
+
+import static android.hardware.camera2.cts.helpers.Preconditions.*;
+
+import android.graphics.ImageFormat;
+import android.graphics.PixelFormat;
+import android.hardware.camera2.cts.rs.AllocationInfo.ElementInfo;
+import android.renderscript.Element;
+import android.renderscript.ScriptIntrinsicYuvToRGB;
+import android.util.Log;
+
+/**
+ * Convert {@link ImageFormat#YUV_420_888 flexible-YUV} {@link Allocation allocations} into
+ * a {@link ElementInfo#RGBA_8888 RGBA_8888} {@link Allocation allocation}.
+ */
+public class ScriptYuvToRgb extends Script<ScriptIntrinsicYuvToRGB> {
+    private static final String TAG = "ScriptYuvToRgb";
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+
+    private static AllocationInfo createOutputInfo(AllocationInfo outputInfo) {
+        checkNotNull("outputInfo", outputInfo);
+        return outputInfo.changeFormatWithDefaultUsage(PixelFormat.RGBA_8888);
+    }
+
+    public ScriptYuvToRgb(AllocationInfo inputInfo) {
+        super(inputInfo,
+              createOutputInfo(inputInfo),
+              ScriptIntrinsicYuvToRGB.create(getRS(), Element.YUV(getRS())));
+
+        // YUV_420_888 is the only supported format here
+        //      XX: Supports any YUV 4:2:0 such as NV21/YV12 or just YUV_420_888 ?
+        if (!inputInfo.isElementEqualTo(ElementInfo.YUV)) {
+            throw new UnsupportedOperationException("Unsupported element "
+                    + inputInfo.getElement());
+        }
+    }
+
+    @Override
+    protected void executeUnchecked() {
+        mScript.forEach(mOutputAllocation);
+
+        if (VERBOSE) { Log.v(TAG, "executeUnchecked - forEach done"); }
+    }
+
+    @Override
+    protected void updateScriptInput() {
+        mScript.setInput(mInputAllocation);
+    }
+}
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
new file mode 100644
index 0000000..5fc6321
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2AndroidTestCase.java
@@ -0,0 +1,326 @@
+/*
+ * 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.testcases;
+
+import static android.hardware.camera2.cts.CameraTestUtils.*;
+import static com.android.ex.camera2.blocking.BlockingStateCallback.*;
+
+import android.content.Context;
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CameraCaptureSession.CaptureCallback;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.CaptureRequest;
+import android.util.Size;
+import android.hardware.camera2.cts.CameraTestUtils;
+import android.hardware.camera2.cts.helpers.CameraErrorCollector;
+import android.hardware.camera2.cts.helpers.StaticMetadata;
+import android.hardware.camera2.cts.helpers.StaticMetadata.CheckLevel;
+import android.media.Image;
+import android.media.ImageReader;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.test.AndroidTestCase;
+import android.util.Log;
+import android.view.Surface;
+
+import com.android.ex.camera2.blocking.BlockingSessionCallback;
+import com.android.ex.camera2.blocking.BlockingStateCallback;
+
+import java.util.List;
+
+public class Camera2AndroidTestCase extends AndroidTestCase {
+    private static final String TAG = "Camera2AndroidTestCase";
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+
+    protected static final String DEBUG_FILE_NAME_BASE =
+            Environment.getExternalStorageDirectory().getPath();
+    // Default capture size: VGA size is required by CDD.
+    protected static final Size DEFAULT_CAPTURE_SIZE = new Size(640, 480);
+    protected static final int CAPTURE_WAIT_TIMEOUT_MS = 5000;
+
+    protected CameraManager mCameraManager;
+    protected CameraDevice mCamera;
+    protected CameraCaptureSession mCameraSession;
+    protected BlockingSessionCallback mCameraSessionListener;
+    protected BlockingStateCallback mCameraListener;
+    protected String[] mCameraIds;
+    protected ImageReader mReader;
+    protected Surface mReaderSurface;
+    protected Handler mHandler;
+    protected HandlerThread mHandlerThread;
+    protected StaticMetadata mStaticInfo;
+    protected CameraErrorCollector mCollector;
+    protected List<Size> mOrderedPreviewSizes; // In descending order.
+    protected List<Size> mOrderedVideoSizes; // In descending order.
+    protected List<Size> mOrderedStillSizes; // In descending order.
+
+    @Override
+    public void setContext(Context context) {
+        super.setContext(context);
+        mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
+        assertNotNull("Can't connect to camera manager!", mCameraManager);
+    }
+
+    /**
+     * Set up the camera2 test case required environments, including CameraManager,
+     * HandlerThread, Camera IDs, and CameraStateCallback etc.
+     */
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        /**
+         * Workaround for mockito and JB-MR2 incompatibility
+         *
+         * Avoid java.lang.IllegalArgumentException: dexcache == null
+         * https://code.google.com/p/dexmaker/issues/detail?id=2
+         */
+        System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString());
+
+        mCameraIds = mCameraManager.getCameraIdList();
+        assertNotNull("Camera ids shouldn't be null", mCameraIds);
+        mHandlerThread = new HandlerThread(TAG);
+        mHandlerThread.start();
+        mHandler = new Handler(mHandlerThread.getLooper());
+        mCameraListener = new BlockingStateCallback();
+        mCollector = new CameraErrorCollector();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mHandlerThread.quitSafely();
+        mHandler = null;
+        closeDefaultImageReader();
+
+        try {
+            mCollector.verify();
+        } catch (Throwable e) {
+            // When new Exception(e) is used, exception info will be printed twice.
+            throw new Exception(e.getMessage());
+        } finally {
+            super.tearDown();
+        }
+    }
+
+    /**
+     * 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 #CaptureCallback} camera device used to notify callbacks.
+     * @param handler The handler camera device used to post callbacks.
+     */
+    protected void startCapture(CaptureRequest request, boolean repeating,
+            CaptureCallback listener, Handler handler) throws Exception {
+        if (VERBOSE) Log.v(TAG, "Starting capture from device");
+
+        if (repeating) {
+            mCameraSession.setRepeatingRequest(request, listener, handler);
+        } else {
+            mCameraSession.capture(request, listener, handler);
+        }
+    }
+
+    /**
+     * Stop the current active capture.
+     *
+     * @param fast When it is true, {@link CameraDevice#flush} is called, the stop capture
+     * could be faster.
+     */
+    protected void stopCapture(boolean fast) throws Exception {
+        if (VERBOSE) Log.v(TAG, "Stopping capture");
+
+        if (fast) {
+            /**
+             * Flush is useful for canceling long exposure single capture, it also could help
+             * to make the streaming capture stop sooner.
+             */
+            mCameraSession.abortCaptures();
+            mCameraSessionListener.getStateWaiter().
+                    waitForState(BlockingSessionCallback.SESSION_READY, CAMERA_IDLE_TIMEOUT_MS);
+        } else {
+            mCameraSession.close();
+            mCameraSessionListener.getStateWaiter().
+                    waitForState(BlockingSessionCallback.SESSION_CLOSED, CAMERA_IDLE_TIMEOUT_MS);
+        }
+    }
+
+    /**
+     * Open a {@link #CameraDevice camera device} and get the StaticMetadata for a given camera id.
+     * The default mCameraListener is used to wait for states.
+     *
+     * @param cameraId The id of the camera device to be opened.
+     */
+    protected void openDevice(String cameraId) throws Exception {
+        openDevice(cameraId, mCameraListener);
+    }
+
+    /**
+     * Open a {@link #CameraDevice} and get the StaticMetadata for a given camera id and listener.
+     *
+     * @param cameraId The id of the camera device to be opened.
+     * @param listener The {@link #BlockingStateCallback} used to wait for states.
+     */
+    protected void openDevice(String cameraId, BlockingStateCallback listener) throws Exception {
+        mCamera = CameraTestUtils.openCamera(
+                mCameraManager, cameraId, listener, mHandler);
+        mCollector.setCameraId(cameraId);
+        mStaticInfo = new StaticMetadata(mCameraManager.getCameraCharacteristics(cameraId),
+                CheckLevel.ASSERT, /*collector*/null);
+        mOrderedPreviewSizes = getSupportedPreviewSizes(
+                cameraId, mCameraManager, PREVIEW_SIZE_BOUND);
+        mOrderedVideoSizes = getSupportedVideoSizes(cameraId, mCameraManager, PREVIEW_SIZE_BOUND);
+        mOrderedStillSizes = getSupportedStillSizes(cameraId, mCameraManager, null);
+
+        if (VERBOSE) {
+            Log.v(TAG, "Camera " + cameraId + " is opened");
+        }
+    }
+
+    /**
+     * Create a {@link #CameraCaptureSession} using the currently open camera.
+     *
+     * @param outputSurfaces The set of output surfaces to configure for this session
+     */
+    protected void createSession(List<Surface> outputSurfaces) throws Exception {
+        mCameraSessionListener = new BlockingSessionCallback();
+        mCameraSession = CameraTestUtils.configureCameraSession(mCamera, outputSurfaces,
+                mCameraSessionListener, mHandler);
+    }
+
+    /**
+     * Close a {@link #CameraDevice camera device} and clear the associated StaticInfo field for a
+     * given camera id. The default mCameraListener is used to wait for states.
+     * <p>
+     * This function must be used along with the {@link #openDevice} for the
+     * same camera id.
+     * </p>
+     *
+     * @param cameraId The id of the {@link #CameraDevice camera device} to be closed.
+     */
+    protected void closeDevice(String cameraId) {
+        closeDevice(cameraId, mCameraListener);
+    }
+
+    /**
+     * Close a {@link #CameraDevice camera device} and clear the associated StaticInfo field for a
+     * given camera id and listener.
+     * <p>
+     * This function must be used along with the {@link #openDevice} for the
+     * same camera id.
+     * </p>
+     *
+     * @param cameraId The id of the camera device to be closed.
+     * @param listener The BlockingStateCallback used to wait for states.
+     */
+    protected void closeDevice(String cameraId, BlockingStateCallback listener) {
+        if (mCamera != null) {
+            if (!cameraId.equals(mCamera.getId())) {
+                throw new IllegalStateException("Try to close a device that is not opened yet");
+            }
+            mCamera.close();
+            listener.waitForState(STATE_CLOSED, CAMERA_CLOSE_TIMEOUT_MS);
+            mCamera = null;
+            mCameraSession = null;
+            mCameraSessionListener = null;
+            mStaticInfo = null;
+            mOrderedPreviewSizes = null;
+            mOrderedVideoSizes = null;
+            mOrderedStillSizes = null;
+
+            if (VERBOSE) {
+                Log.v(TAG, "Camera " + cameraId + " is closed");
+            }
+        }
+    }
+
+    /**
+     * Create an {@link ImageReader} object and get the surface.
+     * <p>
+     * This function creates {@link ImageReader} object and surface, then assign
+     * to the default {@link mReader} and {@link mReaderSurface}. It closes the
+     * current default active {@link ImageReader} if it exists.
+     * </p>
+     *
+     * @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.
+     */
+    protected void createDefaultImageReader(Size size, int format, int maxNumImages,
+            ImageReader.OnImageAvailableListener listener) throws Exception {
+        closeDefaultImageReader();
+
+        mReader = createImageReader(size, format, maxNumImages, listener);
+        mReaderSurface = mReader.getSurface();
+        if (VERBOSE) Log.v(TAG, "Created ImageReader size " + size.toString());
+    }
+
+    /**
+     * Create an {@link ImageReader} object.
+     *
+     * <p>This function creates image reader object for given format, maxImages, and size.</p>
+     *
+     * @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.
+     */
+
+    protected ImageReader createImageReader(Size size, int format, int maxNumImages,
+            ImageReader.OnImageAvailableListener listener) throws Exception {
+
+        ImageReader reader = ImageReader.newInstance(size.getWidth(), size.getHeight(),
+                format, maxNumImages);
+        reader.setOnImageAvailableListener(listener, mHandler);
+        if (VERBOSE) Log.v(TAG, "Created ImageReader size " + size.toString());
+        return reader;
+    }
+
+    /**
+     * Close the pending images then close current default {@link ImageReader} object.
+     */
+    protected void closeDefaultImageReader() {
+        closeImageReader(mReader);
+        mReader = null;
+        mReaderSurface = null;
+    }
+
+    /**
+     * Close an image reader instance.
+     *
+     * @param reader
+     */
+    protected void closeImageReader(ImageReader reader) {
+        if (reader != null) {
+            try {
+                // Close all possible pending images first.
+                Image image = reader.acquireLatestImage();
+                if (image != null) {
+                    image.close();
+                }
+            } finally {
+                reader.close();
+                reader = null;
+            }
+        }
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2MultiViewTestCase.java b/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2MultiViewTestCase.java
new file mode 100644
index 0000000..03e9647
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2MultiViewTestCase.java
@@ -0,0 +1,412 @@
+/*
+ * 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.testcases;
+
+import static android.hardware.camera2.cts.CameraTestUtils.*;
+import static com.android.ex.camera2.blocking.BlockingSessionCallback.*;
+import static com.android.ex.camera2.blocking.BlockingStateCallback.*;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Matrix;
+import android.graphics.RectF;
+import android.graphics.SurfaceTexture;
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CameraCaptureSession.CaptureCallback;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.cts.Camera2MultiViewCtsActivity;
+import android.hardware.camera2.cts.helpers.StaticMetadata;
+import android.hardware.camera2.cts.helpers.StaticMetadata.CheckLevel;
+import android.os.ConditionVariable;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.SystemClock;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+import android.util.Size;
+import android.view.Surface;
+import android.view.TextureView;
+
+import com.android.ex.camera2.blocking.BlockingCameraManager;
+import com.android.ex.camera2.blocking.BlockingSessionCallback;
+import com.android.ex.camera2.blocking.BlockingStateCallback;
+
+import junit.framework.Assert;
+
+import java.util.List;
+import java.util.HashMap;
+
+/**
+ * Camera2 test case base class by using mixed SurfaceView and TextureView as rendering target.
+ */
+public class Camera2MultiViewTestCase extends
+        ActivityInstrumentationTestCase2<Camera2MultiViewCtsActivity> {
+    private static final String TAG = "MultiViewTestCase";
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+
+
+    private static final long SHORT_SLEEP_WAIT_TIME_MS = 100;
+
+    protected TextureView[] mTextureView = new TextureView[2];
+    protected String[] mCameraIds;
+    protected Handler mHandler;
+
+    private CameraManager mCameraManager;
+    private BlockingStateCallback mCameraListener;
+    private HandlerThread mHandlerThread;
+    private Context mContext;
+
+    private CameraHolder[] mCameraHolders;
+    private HashMap<String, Integer> mCameraIdMap;
+
+    public Camera2MultiViewTestCase() {
+        super(Camera2MultiViewCtsActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mContext = getActivity();
+        assertNotNull("Unable to get activity", mContext);
+        mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
+        assertNotNull("Unable to get CameraManager", mCameraManager);
+        mCameraIds = mCameraManager.getCameraIdList();
+        assertNotNull("Unable to get camera ids", mCameraIds);
+        mHandlerThread = new HandlerThread(TAG);
+        mHandlerThread.start();
+        mHandler = new Handler(mHandlerThread.getLooper());
+        mCameraListener = new BlockingStateCallback();
+        Camera2MultiViewCtsActivity activity = (Camera2MultiViewCtsActivity) mContext;
+        mTextureView[0] = activity.getTextureView(0);
+        mTextureView[1] = activity.getTextureView(1);
+        assertNotNull("Unable to get texture view", mTextureView);
+        mCameraIdMap = new HashMap<String, Integer>();
+        int numCameras = mCameraIds.length;
+        mCameraHolders = new CameraHolder[numCameras];
+        for (int i = 0; i < numCameras; i++) {
+            mCameraHolders[i] = new CameraHolder(mCameraIds[i]);
+            mCameraIdMap.put(mCameraIds[i], i);
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mHandlerThread.quitSafely();
+        mHandler = null;
+        mCameraListener = null;
+        for (CameraHolder camera : mCameraHolders) {
+            if (camera.isOpenned()) {
+                camera.close();
+                camera = null;
+            }
+        }
+        super.tearDown();
+    }
+
+    /**
+     * Update preview TextureView rotation to accommodate discrepancy between preview
+     * buffer and the view window orientation.
+     *
+     * Assumptions:
+     * - Aspect ratio for the sensor buffers is in landscape orientation,
+     * - Dimensions of buffers received are rotated to the natural device orientation.
+     * - The contents of each buffer are rotated by the inverse of the display rotation.
+     * - Surface scales the buffer to fit the current view bounds.
+     * TODO: Make this method works for all orientations
+     *
+     */
+    protected void updatePreviewDisplayRotation(Size previewSize, TextureView textureView) {
+        int rotationDegrees = 0;
+        Camera2MultiViewCtsActivity activity = (Camera2MultiViewCtsActivity) mContext;
+        int displayRotation = activity.getWindowManager().getDefaultDisplay().getRotation();
+        Configuration config = activity.getResources().getConfiguration();
+
+        // Get UI display rotation
+        switch (displayRotation) {
+            case Surface.ROTATION_0:
+                rotationDegrees = 0;
+                break;
+            case Surface.ROTATION_90:
+                rotationDegrees = 90;
+            break;
+            case Surface.ROTATION_180:
+                rotationDegrees = 180;
+            break;
+            case Surface.ROTATION_270:
+                rotationDegrees = 270;
+            break;
+        }
+
+        // Get device natural orientation
+        int deviceOrientation = Configuration.ORIENTATION_PORTRAIT;
+        if ((rotationDegrees % 180 == 0 &&
+                config.orientation == Configuration.ORIENTATION_LANDSCAPE) ||
+                ((rotationDegrees % 180 != 0 &&
+                config.orientation == Configuration.ORIENTATION_PORTRAIT))) {
+            deviceOrientation = Configuration.ORIENTATION_LANDSCAPE;
+        }
+
+        // Rotate the buffer dimensions if device orientation is portrait.
+        int effectiveWidth = previewSize.getWidth();
+        int effectiveHeight = previewSize.getHeight();
+        if (deviceOrientation == Configuration.ORIENTATION_PORTRAIT) {
+            effectiveWidth = previewSize.getHeight();
+            effectiveHeight = previewSize.getWidth();
+        }
+
+        // Find and center view rect and buffer rect
+        Matrix transformMatrix =  textureView.getTransform(null);
+        int viewWidth = textureView.getWidth();
+        int viewHeight = textureView.getHeight();
+        RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
+        RectF bufRect = new RectF(0, 0, effectiveWidth, effectiveHeight);
+        float centerX = viewRect.centerX();
+        float centerY = viewRect.centerY();
+        bufRect.offset(centerX - bufRect.centerX(), centerY - bufRect.centerY());
+
+        // Undo ScaleToFit.FILL done by the surface
+        transformMatrix.setRectToRect(viewRect, bufRect, Matrix.ScaleToFit.FILL);
+
+        // Rotate buffer contents to proper orientation
+        transformMatrix.postRotate((360 - rotationDegrees) % 360, centerX, centerY);
+        if ((rotationDegrees % 180) == 90) {
+            int temp = effectiveWidth;
+            effectiveWidth = effectiveHeight;
+            effectiveHeight = temp;
+        }
+
+        // Scale to fit view, cropping the longest dimension
+        float scale =
+                Math.max(viewWidth / (float) effectiveWidth, viewHeight / (float) effectiveHeight);
+        transformMatrix.postScale(scale, scale, centerX, centerY);
+
+        Handler handler = new Handler(Looper.getMainLooper());
+        class TransformUpdater implements Runnable {
+            TextureView mView;
+            Matrix mTransformMatrix;
+            TransformUpdater(TextureView view, Matrix matrix) {
+                mView = view;
+                mTransformMatrix = matrix;
+            }
+
+            @Override
+            public void run() {
+                mView.setTransform(mTransformMatrix);
+            }
+        }
+        handler.post(new TransformUpdater(textureView, transformMatrix));
+    }
+
+    protected void openCamera(String cameraId) throws Exception {
+        CameraHolder camera = getCameraHolder(cameraId);
+        assertFalse("Camera has already opened", camera.isOpenned());
+        camera.open();
+        return;
+    }
+
+    protected void closeCamera(String cameraId) throws Exception {
+        CameraHolder camera = getCameraHolder(cameraId);
+        camera.close();
+    }
+
+    protected void startPreview(
+            String cameraId, List<Surface> outputSurfaces, CaptureCallback listener)
+            throws Exception {
+        CameraHolder camera = getCameraHolder(cameraId);
+        assertTrue("Camera " + cameraId + " is not openned", camera.isOpenned());
+        camera.startPreview(outputSurfaces, listener);
+    }
+
+    protected void stopPreview(String cameraId) throws Exception {
+        CameraHolder camera = getCameraHolder(cameraId);
+        assertTrue("Camera " + cameraId + " preview is not running", camera.isPreviewStarted());
+        camera.stopPreview();
+    }
+
+    protected StaticMetadata getStaticInfo(String cameraId) {
+        CameraHolder camera = getCameraHolder(cameraId);
+        assertTrue("Camera is not openned", camera.isOpenned());
+        return camera.getStaticInfo();
+    }
+
+    protected List<Size> getOrderedPreviewSizes(String cameraId) {
+        CameraHolder camera = getCameraHolder(cameraId);
+        assertTrue("Camera is not openned", camera.isOpenned());
+        return camera.getOrderedPreviewSizes();
+    }
+
+    /**
+     * Wait until the SurfaceTexture available from the TextureView, then return it.
+     * Return null if the wait times out.
+     *
+     * @param timeOutMs The timeout value for the wait
+     * @return The available SurfaceTexture, return null if the wait times out.
+     */
+    protected SurfaceTexture getAvailableSurfaceTexture(long timeOutMs, TextureView view) {
+        long waitTime = timeOutMs;
+
+        while (!view.isAvailable() && waitTime > 0) {
+            long startTimeMs = SystemClock.elapsedRealtime();
+            SystemClock.sleep(SHORT_SLEEP_WAIT_TIME_MS);
+            waitTime -= (SystemClock.elapsedRealtime() - startTimeMs);
+        }
+
+        if (view.isAvailable()) {
+            return view.getSurfaceTexture();
+        } else {
+            Log.w(TAG, "Wait for SurfaceTexture available timed out after " + timeOutMs + "ms");
+            return null;
+        }
+    }
+
+    public static class CameraPreviewListener implements TextureView.SurfaceTextureListener {
+        private boolean mFirstPreviewAvailable = false;
+        private final ConditionVariable mPreviewDone = new ConditionVariable();
+
+        @Override
+        public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
+            // Ignored. The SurfaceTexture is polled by getAvailableSurfaceTexture.
+        }
+
+        @Override
+        public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+            // Ignored. The CameraDevice should already know the changed size.
+        }
+
+        @Override
+        public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
+            /**
+             * Return true, assume that client detaches the surface before it is
+             * destroyed. For example, CameraDevice should detach this surface when
+             * stopping preview. No need to release the SurfaceTexture here as it
+             * is released by TextureView after onSurfaceTextureDestroyed is called.
+             */
+            Log.i(TAG, "onSurfaceTextureDestroyed called.");
+            return true;
+        }
+
+        @Override
+        public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+            // Invoked every time there's a new Camera preview frame
+            if (!mFirstPreviewAvailable) {
+                mFirstPreviewAvailable = true;
+                mPreviewDone.open();
+            }
+        }
+
+        /** Waits until the camera preview is up running */
+        public boolean waitForPreviewDone(long timeOutMs) {
+            if (!mPreviewDone.block(timeOutMs)) {
+                // timeout could be expected or unexpected. The caller will decide.
+                Log.w(TAG, "waitForPreviewDone timed out after " + timeOutMs + "ms");
+                return false;
+            }
+            mPreviewDone.close();
+            return true;
+        }
+    }
+
+    private CameraHolder getCameraHolder(String cameraId) {
+        Integer cameraIdx = mCameraIdMap.get(cameraId);
+        if (cameraIdx == null) {
+            Assert.fail("Unknown camera Id");
+        }
+        return mCameraHolders[cameraIdx];
+    }
+
+    // Per device fields
+    private class CameraHolder {
+        private String mCameraId;
+        private CameraCaptureSession mSession;
+        private CameraDevice mCamera;
+        private StaticMetadata mStaticInfo;
+        private List<Size> mOrderedPreviewSizes;
+        private BlockingSessionCallback mSessionListener;
+
+        public CameraHolder(String id){
+            mCameraId = id;
+        }
+
+        public StaticMetadata getStaticInfo() {
+            return mStaticInfo;
+        }
+
+        public List<Size> getOrderedPreviewSizes() {
+            return mOrderedPreviewSizes;
+        }
+
+        public void open() throws Exception {
+            assertNull("Camera is already opened", mCamera);
+            mCamera = (new BlockingCameraManager(mCameraManager)).openCamera(
+                    mCameraId, mCameraListener, mHandler);
+            mStaticInfo = new StaticMetadata(mCameraManager.getCameraCharacteristics(mCameraId),
+                    CheckLevel.ASSERT, /*collector*/null);
+            mOrderedPreviewSizes = getSupportedPreviewSizes(
+                    mCameraId, mCameraManager, PREVIEW_SIZE_BOUND);
+            assertNotNull(String.format("Failed to open camera device ID: %s", mCameraId), mCamera);
+        }
+
+        public boolean isOpenned() {
+            return (mCamera != null);
+        }
+
+        public void close() throws Exception {
+            if (!isOpenned()) {
+                return;
+            }
+            mCamera.close();
+            mCameraListener.waitForState(STATE_CLOSED, CAMERA_CLOSE_TIMEOUT_MS);
+            mCamera = null;
+            mSession = null;
+            mStaticInfo = null;
+            mOrderedPreviewSizes = null;
+        }
+
+        public void startPreview(List<Surface> outputSurfaces, CaptureCallback listener)
+                throws Exception {
+            mSessionListener = new BlockingSessionCallback();
+            mSession = configureCameraSession(mCamera, outputSurfaces, mSessionListener, mHandler);
+
+            // TODO: vary the different settings like crop region to cover more cases.
+            CaptureRequest.Builder captureBuilder =
+                    mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+
+            for (Surface surface : outputSurfaces) {
+                captureBuilder.addTarget(surface);
+            }
+            mSession.setRepeatingRequest(captureBuilder.build(), listener, mHandler);
+        }
+
+        public boolean isPreviewStarted() {
+            return (mSession != null);
+        }
+
+        public void stopPreview() throws Exception {
+            if (VERBOSE) Log.v(TAG,
+                    "Stopping camera " + mCameraId +" preview and waiting for idle");
+            // Stop repeat, wait for captures to complete, and disconnect from surfaces
+            mSession.close();
+            mSessionListener.getStateWaiter().waitForState(
+                    SESSION_CLOSED, SESSION_CLOSE_TIMEOUT_MS);
+            mSessionListener = null;
+        }
+    }
+}
+
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
new file mode 100644
index 0000000..bcc4061
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
@@ -0,0 +1,697 @@
+/*
+ * 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.testcases;
+
+import static android.hardware.camera2.cts.CameraTestUtils.*;
+import static com.android.ex.camera2.blocking.BlockingStateCallback.STATE_CLOSED;
+
+import android.hardware.camera2.params.StreamConfigurationMap;
+import android.media.ImageReader;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.content.Context;
+import android.graphics.ImageFormat;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CameraCaptureSession.CaptureCallback;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.CameraMetadata;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.util.Size;
+import android.util.Range;
+import android.hardware.camera2.cts.Camera2SurfaceViewCtsActivity;
+import android.hardware.camera2.cts.CameraTestUtils;
+import android.hardware.camera2.cts.CameraTestUtils.SimpleCaptureCallback;
+import android.hardware.camera2.cts.helpers.CameraErrorCollector;
+import android.hardware.camera2.cts.helpers.StaticMetadata;
+import android.hardware.camera2.cts.helpers.StaticMetadata.CheckLevel;
+
+import com.android.ex.camera2.blocking.BlockingSessionCallback;
+import com.android.ex.camera2.blocking.BlockingStateCallback;
+import com.android.ex.camera2.exceptions.TimeoutRuntimeException;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Camera2 Preview test case base class by using SurfaceView as rendering target.
+ *
+ * <p>This class encapsulates the SurfaceView based preview common functionalities.
+ * The setup and teardown of CameraManager, test HandlerThread, Activity, Camera IDs
+ * and CameraStateCallback are handled in this class. Some basic preview related utility
+ * functions are provided to facilitate the derived preview-based test classes.
+ * </p>
+ */
+
+public class Camera2SurfaceViewTestCase extends
+        ActivityInstrumentationTestCase2<Camera2SurfaceViewCtsActivity> {
+    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;
+
+    // TODO: Use internal storage for this to make sure the file is only visible to test.
+    protected static final String DEBUG_FILE_NAME_BASE =
+            Environment.getExternalStorageDirectory().getPath();
+    protected static final int WAIT_FOR_RESULT_TIMEOUT_MS = 3000;
+    protected static final float FRAME_DURATION_ERROR_MARGIN = 0.005f; // 0.5 percent error margin.
+    protected static final int NUM_RESULTS_WAIT_TIMEOUT = 100;
+    protected static final int NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY = 8;
+
+    protected Context mContext;
+    protected CameraManager mCameraManager;
+    protected String[] mCameraIds;
+    protected HandlerThread mHandlerThread;
+    protected Handler mHandler;
+    protected BlockingStateCallback mCameraListener;
+    protected BlockingSessionCallback mSessionListener;
+    protected CameraErrorCollector mCollector;
+    // Per device fields:
+    protected StaticMetadata mStaticInfo;
+    protected CameraDevice mCamera;
+    protected CameraCaptureSession mSession;
+    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.
+    protected HashMap<Size, Long> mMinPreviewFrameDurationMap;
+
+
+    public Camera2SurfaceViewTestCase() {
+        super(Camera2SurfaceViewCtsActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        /**
+         * Set up the camera preview required environments, including activity,
+         * CameraManager, HandlerThread, Camera IDs, and CameraStateCallback.
+         */
+        super.setUp();
+        mContext = getActivity();
+        /**
+         * Workaround for mockito and JB-MR2 incompatibility
+         *
+         * Avoid java.lang.IllegalArgumentException: dexcache == null
+         * https://code.google.com/p/dexmaker/issues/detail?id=2
+         */
+        System.setProperty("dexmaker.dexcache", mContext.getCacheDir().toString());
+        mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
+        assertNotNull("Unable to get CameraManager", mCameraManager);
+        mCameraIds = mCameraManager.getCameraIdList();
+        assertNotNull("Unable to get camera ids", mCameraIds);
+        mHandlerThread = new HandlerThread(TAG);
+        mHandlerThread.start();
+        mHandler = new Handler(mHandlerThread.getLooper());
+        mCameraListener = new BlockingStateCallback();
+        mCollector = new CameraErrorCollector();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        // Teardown the camera preview required environments.
+        mHandlerThread.quitSafely();
+        mHandler = null;
+        mCameraListener = null;
+
+        try {
+            mCollector.verify();
+        } catch (Throwable e) {
+            // When new Exception(e) is used, exception info will be printed twice.
+            throw new Exception(e.getMessage());
+        } finally {
+            super.tearDown();
+        }
+    }
+
+    /**
+     * Start camera preview by using the given request, preview size and capture
+     * listener.
+     * <p>
+     * If preview is already started, calling this function will stop the
+     * current preview stream and start a new preview stream with given
+     * parameters. No need to call stopPreview between two startPreview calls.
+     * </p>
+     *
+     * @param request The request builder used to start the preview.
+     * @param previewSz The size of the camera device output preview stream.
+     * @param listener The callbacks the camera device will notify when preview
+     *            capture is available.
+     */
+    protected void startPreview(CaptureRequest.Builder request, Size previewSz,
+            CaptureCallback listener) throws Exception {
+        // Update preview size.
+        updatePreviewSurface(previewSz);
+        if (VERBOSE) {
+            Log.v(TAG, "start preview with size " + mPreviewSize.toString());
+        }
+
+        configurePreviewOutput(request);
+
+        mSession.setRepeatingRequest(request.build(), listener, mHandler);
+    }
+
+    /**
+     * Configure the preview output stream.
+     *
+     * @param request The request to be configured with preview surface
+     */
+    protected void configurePreviewOutput(CaptureRequest.Builder request)
+            throws CameraAccessException {
+        List<Surface> outputSurfaces = new ArrayList<Surface>(/*capacity*/1);
+        outputSurfaces.add(mPreviewSurface);
+        mSessionListener = new BlockingSessionCallback();
+        mSession = configureCameraSession(mCamera, outputSurfaces, mSessionListener, mHandler);
+
+        request.addTarget(mPreviewSurface);
+    }
+
+    /**
+     * Create a {@link CaptureRequest#Builder} and add the default preview surface.
+     *
+     * @return The {@link CaptureRequest#Builder} to be created
+     * @throws CameraAccessException When create capture request from camera fails
+     */
+    protected CaptureRequest.Builder createRequestForPreview() throws CameraAccessException {
+        if (mPreviewSurface == null) {
+            throw new IllegalStateException(
+                    "Preview surface is not set yet, call updatePreviewSurface or startPreview"
+                    + "first to set the preview surface properly.");
+        }
+        CaptureRequest.Builder requestBuilder =
+                mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+        requestBuilder.addTarget(mPreviewSurface);
+        return requestBuilder;
+    }
+
+    /**
+     * Stop preview for current camera device.
+     */
+    protected void stopPreview() throws Exception {
+        if (VERBOSE) Log.v(TAG, "Stopping preview and waiting for idle");
+        // Stop repeat, wait for captures to complete, and disconnect from surfaces
+        mSession.close();
+    }
+
+    /**
+     * Setup still (JPEG) capture configuration and start preview.
+     * <p>
+     * The default max number of image is set to image reader.
+     * </p>
+     *
+     * @param previewRequest The capture request to be used for preview
+     * @param stillRequest The capture request to be used for still capture
+     * @param previewSz Preview size
+     * @param stillSz The still capture size
+     * @param resultListener Capture result listener
+     * @param imageListener The still capture image listener
+     */
+    protected void prepareStillCaptureAndStartPreview(CaptureRequest.Builder previewRequest,
+            CaptureRequest.Builder stillRequest, Size previewSz, Size stillSz,
+            CaptureCallback resultListener,
+            ImageReader.OnImageAvailableListener imageListener) throws Exception {
+        prepareCaptureAndStartPreview(previewRequest, stillRequest, previewSz, stillSz,
+                ImageFormat.JPEG, resultListener, MAX_READER_IMAGES, imageListener);
+    }
+
+    /**
+     * Setup still (JPEG) capture configuration and start preview.
+     *
+     * @param previewRequest The capture request to be used for preview
+     * @param stillRequest The capture request to be used for still capture
+     * @param previewSz Preview size
+     * @param stillSz The still capture size
+     * @param resultListener Capture result listener
+     * @param maxNumImages The max number of images set to the image reader
+     * @param imageListener The still capture image listener
+     */
+    protected void prepareStillCaptureAndStartPreview(CaptureRequest.Builder previewRequest,
+            CaptureRequest.Builder stillRequest, Size previewSz, Size stillSz,
+            CaptureCallback resultListener, int maxNumImages,
+            ImageReader.OnImageAvailableListener imageListener) throws Exception {
+        prepareCaptureAndStartPreview(previewRequest, stillRequest, previewSz, stillSz,
+                ImageFormat.JPEG, resultListener, maxNumImages, imageListener);
+    }
+
+    /**
+     * Setup raw capture configuration and start preview.
+     *
+     * <p>
+     * The default max number of image is set to image reader.
+     * </p>
+     *
+     * @param previewRequest The capture request to be used for preview
+     * @param rawRequest The capture request to be used for raw capture
+     * @param previewSz Preview size
+     * @param rawSz The raw capture size
+     * @param resultListener Capture result listener
+     * @param imageListener The raw capture image listener
+     */
+    protected void prepareRawCaptureAndStartPreview(CaptureRequest.Builder previewRequest,
+            CaptureRequest.Builder rawRequest, Size previewSz, Size rawSz,
+            CaptureCallback resultListener,
+            ImageReader.OnImageAvailableListener imageListener) throws Exception {
+        prepareCaptureAndStartPreview(previewRequest, rawRequest, previewSz, rawSz,
+                ImageFormat.RAW_SENSOR, resultListener, MAX_READER_IMAGES, imageListener);
+    }
+
+    /**
+     * Wait for expected result key value available in a certain number of results.
+     *
+     * <p>
+     * Check the result immediately if numFramesWait is 0.
+     * </p>
+     *
+     * @param listener The capture listener to get capture result
+     * @param resultKey The capture result key associated with the result value
+     * @param expectedValue The result value need to be waited for
+     * @param numResultsWait Number of frame to wait before times out
+     * @throws TimeoutRuntimeException If more than numResultsWait results are
+     * seen before the result matching myRequest arrives, or each individual wait
+     * for result times out after {@value #WAIT_FOR_RESULT_TIMEOUT_MS}ms.
+     */
+    protected static <T> void waitForResultValue(SimpleCaptureCallback listener,
+            CaptureResult.Key<T> resultKey,
+            T expectedValue, int numResultsWait) {
+        List<T> expectedValues = new ArrayList<T>();
+        expectedValues.add(expectedValue);
+        waitForAnyResultValue(listener, resultKey, expectedValues, numResultsWait);
+    }
+
+    /**
+     * Wait for any expected result key values available in a certain number of results.
+     *
+     * <p>
+     * Check the result immediately if numFramesWait is 0.
+     * </p>
+     *
+     * @param listener The capture listener to get capture result.
+     * @param resultKey The capture result key associated with the result value.
+     * @param expectedValues The list of result value need to be waited for,
+     * return immediately if the list is empty.
+     * @param numResultsWait Number of frame to wait before times out.
+     * @throws TimeoutRuntimeException If more than numResultsWait results are.
+     * seen before the result matching myRequest arrives, or each individual wait
+     * for result times out after {@value #WAIT_FOR_RESULT_TIMEOUT_MS}ms.
+     */
+    protected static <T> void waitForAnyResultValue(SimpleCaptureCallback listener,
+            CaptureResult.Key<T> resultKey,
+            List<T> expectedValues, int numResultsWait) {
+        if (numResultsWait < 0 || listener == null || expectedValues == null) {
+            throw new IllegalArgumentException(
+                    "Input must be non-negative number and listener/expectedValues "
+                    + "must be non-null");
+        }
+
+        int i = 0;
+        CaptureResult result;
+        do {
+            result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+            T value = result.get(resultKey);
+            for ( T expectedValue : expectedValues) {
+                if (VERBOSE) {
+                    Log.v(TAG, "Current result value for key " + resultKey.getName() + " is: "
+                            + value.toString());
+                }
+                if (value.equals(expectedValue)) {
+                    return;
+                }
+            }
+        } while (i++ < numResultsWait);
+
+        throw new TimeoutRuntimeException(
+                "Unable to get the expected result value " + expectedValues + " for key " +
+                        resultKey.getName() + " after waiting for " + numResultsWait + " results");
+    }
+
+    /**
+     * Submit a capture once, then submit additional captures in order to ensure that
+     * the camera will be synchronized.
+     *
+     * <p>
+     * The additional capture count is determined by android.sync.maxLatency (or
+     * a fixed {@value #NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY}) captures if maxLatency is unknown).
+     * </p>
+     *
+     * <p>Returns the number of captures that were submitted (at least 1), which is useful
+     * with {@link #waitForNumResults}.</p>
+     *
+     * @param request capture request to forward to {@link CameraDevice#capture}
+     * @param listener request listener to forward to {@link CameraDevice#capture}
+     * @param handler handler to forward to {@link CameraDevice#capture}
+     *
+     * @return the number of captures that were submitted
+     *
+     * @throws CameraAccessException if capturing failed
+     */
+    protected int captureRequestsSynchronized(
+            CaptureRequest request, CaptureCallback listener, Handler handler)
+                    throws CameraAccessException {
+        return captureRequestsSynchronized(request, /*count*/1, listener, handler);
+    }
+
+    /**
+     * Submit a capture {@code count} times, then submit additional captures in order to ensure that
+     * the camera will be synchronized.
+     *
+     * <p>
+     * The additional capture count is determined by android.sync.maxLatency (or
+     * a fixed {@value #NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY}) captures if maxLatency is unknown).
+     * </p>
+     *
+     * <p>Returns the number of captures that were submitted (at least 1), which is useful
+     * with {@link #waitForNumResults}.</p>
+     *
+     * @param request capture request to forward to {@link CameraDevice#capture}
+     * @param count the number of times to submit the request (minimally), must be at least 1
+     * @param listener request listener to forward to {@link CameraDevice#capture}
+     * @param handler handler to forward to {@link CameraDevice#capture}
+     *
+     * @return the number of captures that were submitted
+     *
+     * @throws IllegalArgumentException if {@code count} was not at least 1
+     * @throws CameraAccessException if capturing failed
+     */
+    protected int captureRequestsSynchronized(
+            CaptureRequest request, int count, CaptureCallback listener, Handler handler)
+                    throws CameraAccessException {
+        if (count < 1) {
+            throw new IllegalArgumentException("count must be positive");
+        }
+
+        int maxLatency = mStaticInfo.getSyncMaxLatency();
+        if (maxLatency == CameraMetadata.SYNC_MAX_LATENCY_UNKNOWN) {
+            maxLatency = NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY;
+        }
+
+        assertTrue("maxLatency is non-negative", maxLatency >= 0);
+
+        int numCaptures = maxLatency + count;
+
+        for (int i = 0; i < numCaptures; ++i) {
+            mSession.capture(request, listener, handler);
+        }
+
+        return numCaptures;
+    }
+
+    /**
+     * Wait for numResultWait frames
+     *
+     * @param resultListener The capture listener to get capture result back.
+     * @param numResultsWait Number of frame to wait
+     *
+     * @return the last result, or {@code null} if there was none
+     */
+    protected static CaptureResult waitForNumResults(SimpleCaptureCallback resultListener,
+            int numResultsWait) {
+        if (numResultsWait < 0 || resultListener == null) {
+            throw new IllegalArgumentException(
+                    "Input must be positive number and listener must be non-null");
+        }
+
+        CaptureResult result = null;
+        for (int i = 0; i < numResultsWait; i++) {
+            result = resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
+        }
+
+        return result;
+    }
+
+    /**
+     * Wait for enough results for settings to be applied
+     *
+     * @param resultListener The capture listener to get capture result back.
+     * @param numResultWaitForUnknownLatency Number of frame to wait if camera device latency is
+     *                                       unknown.
+     */
+    protected void waitForSettingsApplied(SimpleCaptureCallback resultListener,
+            int numResultWaitForUnknownLatency) {
+        int maxLatency = mStaticInfo.getSyncMaxLatency();
+        if (maxLatency == CameraMetadata.SYNC_MAX_LATENCY_UNKNOWN) {
+            maxLatency = numResultWaitForUnknownLatency;
+        }
+        // Wait for settings to take effect
+        waitForNumResults(resultListener, maxLatency);
+    }
+
+
+    /**
+     * Wait for AE to be stabilized before capture: CONVERGED or FLASH_REQUIRED.
+     *
+     * <p>Waits for {@code android.sync.maxLatency} number of results first, to make sure
+     * that the result is synchronized (or {@code numResultWaitForUnknownLatency} if the latency
+     * is unknown.</p>
+     *
+     * <p>This is a no-op for {@code LEGACY} devices since they don't report
+     * the {@code aeState} result.</p>
+     *
+     * @param resultListener The capture listener to get capture result back.
+     * @param numResultWaitForUnknownLatency Number of frame to wait if camera device latency is
+     *                                       unknown.
+     */
+    protected void waitForAeStable(SimpleCaptureCallback resultListener,
+            int numResultWaitForUnknownLatency) {
+        waitForSettingsApplied(resultListener, numResultWaitForUnknownLatency);
+
+        if (!mStaticInfo.isHardwareLevelLimitedOrBetter()) {
+            // No-op for metadata
+            return;
+        }
+        List<Integer> expectedAeStates = new ArrayList<Integer>();
+        expectedAeStates.add(new Integer(CaptureResult.CONTROL_AE_STATE_CONVERGED));
+        expectedAeStates.add(new Integer(CaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED));
+        waitForAnyResultValue(resultListener, CaptureResult.CONTROL_AE_STATE, expectedAeStates,
+                NUM_RESULTS_WAIT_TIMEOUT);
+    }
+
+    /**
+     * Wait for AE to be: LOCKED
+     *
+     * <p>Waits for {@code android.sync.maxLatency} number of results first, to make sure
+     * that the result is synchronized (or {@code numResultWaitForUnknownLatency} if the latency
+     * is unknown.</p>
+     *
+     * <p>This is a no-op for {@code LEGACY} devices since they don't report
+     * the {@code aeState} result.</p>
+     *
+     * @param resultListener The capture listener to get capture result back.
+     * @param numResultWaitForUnknownLatency Number of frame to wait if camera device latency is
+     *                                       unknown.
+     */
+    protected void waitForAeLocked(SimpleCaptureCallback resultListener,
+            int numResultWaitForUnknownLatency) {
+
+        waitForSettingsApplied(resultListener, numResultWaitForUnknownLatency);
+
+        if (!mStaticInfo.isHardwareLevelLimitedOrBetter()) {
+            // No-op for legacy devices
+            return;
+        }
+
+        List<Integer> expectedAeStates = new ArrayList<Integer>();
+        expectedAeStates.add(new Integer(CaptureResult.CONTROL_AE_STATE_LOCKED));
+        waitForAnyResultValue(resultListener, CaptureResult.CONTROL_AE_STATE, expectedAeStates,
+                NUM_RESULTS_WAIT_TIMEOUT);
+    }
+
+    /**
+     * 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.
+     */
+    protected void createImageReader(Size size, int format, int maxNumImages,
+            ImageReader.OnImageAvailableListener listener) throws Exception {
+        closeImageReader();
+
+        ImageReader r = makeImageReader(size, format, maxNumImages, listener,
+                mHandler);
+        mReader = r;
+        mReaderSurface = r.getSurface();
+    }
+
+    /**
+     * Close the pending images then close current active {@link ImageReader} object.
+     */
+    protected void closeImageReader() {
+        CameraTestUtils.closeImageReader(mReader);
+        mReader = null;
+        mReaderSurface = null;
+    }
+
+    /**
+     * Open a camera device and get the StaticMetadata for a given camera id.
+     *
+     * @param cameraId The id of the camera device to be opened.
+     */
+    protected void openDevice(String cameraId) throws Exception {
+        mCamera = CameraTestUtils.openCamera(
+                mCameraManager, cameraId, mCameraListener, mHandler);
+        mCollector.setCameraId(cameraId);
+        mStaticInfo = new StaticMetadata(mCameraManager.getCameraCharacteristics(cameraId),
+                CheckLevel.ASSERT, /*collector*/null);
+        mOrderedPreviewSizes = getSupportedPreviewSizes(cameraId, mCameraManager, PREVIEW_SIZE_BOUND);
+        mOrderedVideoSizes = getSupportedVideoSizes(cameraId, mCameraManager, PREVIEW_SIZE_BOUND);
+        mOrderedStillSizes = getSupportedStillSizes(cameraId, mCameraManager, null);
+        // Use ImageFormat.YUV_420_888 for now. TODO: need figure out what's format for preview
+        // in public API side.
+        mMinPreviewFrameDurationMap =
+                mStaticInfo.getAvailableMinFrameDurationsForFormatChecked(ImageFormat.YUV_420_888);
+    }
+
+    /**
+     * Close the current actively used camera device.
+     */
+    protected void closeDevice() {
+        if (mCamera != null) {
+            mCamera.close();
+            mCameraListener.waitForState(STATE_CLOSED, CAMERA_CLOSE_TIMEOUT_MS);
+            mCamera = null;
+            mSession = null;
+            mSessionListener = null;
+            mStaticInfo = null;
+            mOrderedPreviewSizes = null;
+            mOrderedVideoSizes = null;
+            mOrderedStillSizes = null;
+        }
+    }
+
+    /**
+     * Update the preview surface size.
+     *
+     * @param size The preview size to be updated.
+     */
+    protected void updatePreviewSurface(Size size) {
+        if (size.equals(mPreviewSize) && mPreviewSurface != null) {
+            Log.w(TAG, "Skipping update preview surface size...");
+            return;
+        }
+
+        mPreviewSize = size;
+        Camera2SurfaceViewCtsActivity ctsActivity = getActivity();
+        final SurfaceHolder holder = ctsActivity.getSurfaceView().getHolder();
+        Handler handler = new Handler(Looper.getMainLooper());
+        handler.post(new Runnable() {
+            @Override
+            public void run() {
+                holder.setFixedSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
+            }
+        });
+
+        boolean res = ctsActivity.waitForSurfaceSizeChanged(
+                WAIT_FOR_SURFACE_CHANGE_TIMEOUT_MS, mPreviewSize.getWidth(),
+                mPreviewSize.getHeight());
+        assertTrue("wait for surface change to " + mPreviewSize.toString() + " timed out", res);
+        mPreviewSurface = holder.getSurface();
+        assertTrue("Preview surface is invalid", mPreviewSurface.isValid());
+        assertNotNull("Preview surface is null", mPreviewSurface);
+    }
+
+    /**
+     * Setup single capture configuration and start preview.
+     *
+     * @param previewRequest The capture request to be used for preview
+     * @param stillRequest The capture request to be used for still capture
+     * @param previewSz Preview size
+     * @param captureSz Still capture size
+     * @param format The single capture image format
+     * @param resultListener Capture result listener
+     * @param maxNumImages The max number of images set to the image reader
+     * @param imageListener The single capture capture image listener
+     */
+    protected void prepareCaptureAndStartPreview(CaptureRequest.Builder previewRequest,
+            CaptureRequest.Builder stillRequest, Size previewSz, Size captureSz, int format,
+            CaptureCallback resultListener, int maxNumImages,
+            ImageReader.OnImageAvailableListener imageListener) throws Exception {
+        if (VERBOSE) {
+            Log.v(TAG, String.format("Prepare single capture (%s) and preview (%s)",
+                    captureSz.toString(), previewSz.toString()));
+        }
+
+        // Update preview size.
+        updatePreviewSurface(previewSz);
+
+        // Create ImageReader.
+        createImageReader(captureSz, format, maxNumImages, imageListener);
+
+        // Configure output streams with preview and jpeg streams.
+        List<Surface> outputSurfaces = new ArrayList<Surface>();
+        outputSurfaces.add(mPreviewSurface);
+        outputSurfaces.add(mReaderSurface);
+        mSessionListener = new BlockingSessionCallback();
+        mSession = configureCameraSession(mCamera, outputSurfaces, mSessionListener, mHandler);
+
+        // Configure the requests.
+        previewRequest.addTarget(mPreviewSurface);
+        stillRequest.addTarget(mPreviewSurface);
+        stillRequest.addTarget(mReaderSurface);
+
+        // Start preview.
+        mSession.setRepeatingRequest(previewRequest.build(), resultListener, mHandler);
+    }
+
+    /**
+     * Get the max preview size that supports the given fpsRange.
+     *
+     * @param fpsRange The fps range the returned size must support.
+     * @return max size that support the given fps range.
+     */
+    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) {
+            throw new IllegalStateException("mOrderedPreviewSizes and mMinPreviewFrameDurationMap"
+                    + " must be initialized");
+        }
+
+        long[] frameDurationRange =
+                new long[]{(long) (1e9 / fpsRange.getUpper()), (long) (1e9 / fpsRange.getLower())};
+        for (Size size : mOrderedPreviewSizes) {
+            Long minDuration = mMinPreviewFrameDurationMap.get(size);
+            if (minDuration == null ||
+                    minDuration == 0) {
+                if (mStaticInfo.isCapabilitySupported(
+                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
+                    throw new IllegalArgumentException(
+                            "No min frame duration available for the size " + size);
+                }
+                continue;
+            }
+            if (minDuration <= frameDurationRange[0]) {
+                return size;
+            }
+        }
+
+        return null;
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/CameraCtsActivity.java b/tests/tests/hardware/src/android/hardware/cts/CameraCtsActivity.java
new file mode 100644
index 0000000..1153cac
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/CameraCtsActivity.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.ViewGroup;
+import com.android.cts.hardware.R;
+
+public class CameraCtsActivity extends Activity {
+    private SurfaceView mSurfaceView;
+    private final int LAYOUT_WIDTH = 480;
+    private final int LAYOUT_HEIGHT = 320;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.surface_view);
+        mSurfaceView = (SurfaceView)findViewById(R.id.surface_view);
+        ViewGroup.LayoutParams lp = mSurfaceView.getLayoutParams();
+        lp.width = LAYOUT_WIDTH;
+        lp.height = LAYOUT_HEIGHT;
+        mSurfaceView.setLayoutParams(lp);
+        mSurfaceView.getHolder().setFixedSize(LAYOUT_WIDTH, LAYOUT_HEIGHT);
+        mSurfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
+    }
+
+    public SurfaceView getSurfaceView() {
+        return mSurfaceView;
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/CameraGLTest.java b/tests/tests/hardware/src/android/hardware/cts/CameraGLTest.java
old mode 100644
new mode 100755
index c1809b8..d8f8a1d
--- a/tests/tests/hardware/src/android/hardware/cts/CameraGLTest.java
+++ b/tests/tests/hardware/src/android/hardware/cts/CameraGLTest.java
@@ -25,7 +25,6 @@
 import android.opengl.GLES20;
 import android.opengl.GLSurfaceView;
 import android.opengl.Matrix;
-import android.opengl.cts.GLSurfaceViewStubActivity;
 
 import android.os.ConditionVariable;
 import android.os.Environment;
@@ -61,9 +60,9 @@
  * This test case must run with hardware. It can't be tested in emulator
  */
 @LargeTest
-public class CameraGLTest extends ActivityInstrumentationTestCase2<GLSurfaceViewStubActivity> {
+public class CameraGLTest extends ActivityInstrumentationTestCase2<GLSurfaceViewCtsActivity> {
     private static final String TAG = "CameraGLTest";
-    private static final String PACKAGE = "com.android.cts.stub";
+    private static final String PACKAGE = "com.android.cts.hardware";
     private static final boolean LOGV = false;
     private static final boolean LOGVV = false;
     private static final int EGL_OPENGL_ES2_BIT = 0x0004;
@@ -84,11 +83,12 @@
 
     Camera mCamera;
     SurfaceTexture mSurfaceTexture;
+    private final Object mSurfaceTextureSyncLock = new Object();
     Renderer mRenderer;
     GLSurfaceView mGLView;
 
     public CameraGLTest() {
-        super(PACKAGE, GLSurfaceViewStubActivity.class);
+        super(PACKAGE, GLSurfaceViewCtsActivity.class);
         if (LOGV) Log.v(TAG, "CameraGLTest Constructor");
     }
 
@@ -97,13 +97,13 @@
         super.setUp();
         // Set up renderer instance
         mRenderer = this.new Renderer();
-        GLSurfaceViewStubActivity.setRenderer(mRenderer);
-        GLSurfaceViewStubActivity.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
-        GLSurfaceViewStubActivity.setGlVersion(2);
-        // Start CameraStubActivity.
-        GLSurfaceViewStubActivity stubActivity = getActivity();
+        GLSurfaceViewCtsActivity.setRenderer(mRenderer);
+        GLSurfaceViewCtsActivity.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
+        GLSurfaceViewCtsActivity.setGlVersion(2);
+        // Start CameraCtsActivity.
+        GLSurfaceViewCtsActivity ctsActivity = getActivity();
         // Store a link to the view so we can redraw it when needed
-        mGLView = stubActivity.getView();
+        mGLView = ctsActivity.getView();
     }
 
     @Override
@@ -111,10 +111,10 @@
         if (mCamera != null) {
             terminateMessageLooper();
         }
-        // Clean up static values in stub so it can be reused
-        GLSurfaceViewStubActivity.resetRenderMode();
-        GLSurfaceViewStubActivity.resetRenderer();
-        GLSurfaceViewStubActivity.resetGlVersion();
+        // Clean up static values in cts so it can be reused
+        GLSurfaceViewCtsActivity.resetRenderMode();
+        GLSurfaceViewCtsActivity.resetRenderer();
+        GLSurfaceViewCtsActivity.resetGlVersion();
 
         super.tearDown();
     }
@@ -165,7 +165,9 @@
         // the method. So we need to join the looper thread here.
         mLooper.getThread().join();
         mCamera = null;
-        mSurfaceTexture = null;
+        synchronized(mSurfaceTextureSyncLock) {
+            mSurfaceTexture = null;
+        }
         if (LOGV) Log.v(TAG, "Shutdown of camera complete.");
     }
 
@@ -662,10 +664,12 @@
 
         public void onDrawFrame(GL10 glUnused) {
             if (LOGVV) Log.v(TAG, "onDrawFrame()");
-            if (CameraGLTest.this.mSurfaceTexture != null) {
-                CameraGLTest.this.mSurfaceTexture.updateTexImage();
-                CameraGLTest.this.mSurfaceTexture.getTransformMatrix(mSTMatrix);
-                mDrawDone.open();
+            synchronized(mSurfaceTextureSyncLock) {
+                if (CameraGLTest.this.mSurfaceTexture != null) {
+                    CameraGLTest.this.mSurfaceTexture.updateTexImage();
+                    CameraGLTest.this.mSurfaceTexture.getTransformMatrix(mSTMatrix);
+                    mDrawDone.open();
+                }
             }
 
             // Ignore the passed-in GL10 interface, and use the GLES20
diff --git a/tests/tests/hardware/src/android/hardware/cts/CameraTest.java b/tests/tests/hardware/src/android/hardware/cts/CameraTest.java
index c6e28f7..019bd21 100644
--- a/tests/tests/hardware/src/android/hardware/cts/CameraTest.java
+++ b/tests/tests/hardware/src/android/hardware/cts/CameraTest.java
@@ -33,6 +33,7 @@
 import android.media.CamcorderProfile;
 import android.media.ExifInterface;
 import android.media.MediaRecorder;
+import android.os.Build;
 import android.os.ConditionVariable;
 import android.os.Environment;
 import android.os.Looper;
@@ -47,12 +48,14 @@
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.text.ParsePosition;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.Iterator;
 import java.util.List;
+import java.util.TimeZone;
 
 import junit.framework.AssertionFailedError;
 
@@ -60,10 +63,10 @@
  * This test case must run with hardware. It can't be tested in emulator
  */
 @LargeTest
-public class CameraTest extends ActivityInstrumentationTestCase2<CameraStubActivity> {
+public class CameraTest extends ActivityInstrumentationTestCase2<CameraCtsActivity> {
     private static String TAG = "CameraTest";
-    private static final String PACKAGE = "com.android.cts.stub";
-    private static final boolean LOGV = false;
+    private static final String PACKAGE = "com.android.cts.hardware";
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
     private final String JPEG_PATH = Environment.getExternalStorageDirectory().getPath() +
             "/test.jpg";
     private byte[] mJpegData;
@@ -91,6 +94,13 @@
     private static final int AUTOEXPOSURE_LOCK = 0;
     private static final int AUTOWHITEBALANCE_LOCK = 1;
 
+    // Some exif tags that are not defined by ExifInterface but supported.
+    private static final String TAG_DATETIME_DIGITIZED = "DateTimeDigitized";
+    private static final String TAG_SUBSEC_TIME = "SubSecTime";
+    private static final String TAG_SUBSEC_TIME_ORIG = "SubSecTimeOriginal";
+    private static final String TAG_SUBSEC_TIME_DIG = "SubSecTimeDigitized";
+
+
     private PreviewCallback mPreviewCallback = new PreviewCallback();
     private TestShutterCallback mShutterCallback = new TestShutterCallback();
     private RawPictureCallback mRawPictureCallback = new RawPictureCallback();
@@ -107,14 +117,14 @@
     Camera mCamera;
 
     public CameraTest() {
-        super(PACKAGE, CameraStubActivity.class);
-        if (LOGV) Log.v(TAG, "Camera Constructor");
+        super(PACKAGE, CameraCtsActivity.class);
+        if (VERBOSE) Log.v(TAG, "Camera Constructor");
     }
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        // to start CameraStubActivity.
+        // to starCtsActivity.
         getActivity();
     }
 
@@ -151,7 +161,7 @@
                 Log.v(TAG, "camera is opened");
                 startDone.open();
                 Looper.loop(); // Blocks forever until Looper.quit() is called.
-                if (LOGV) Log.v(TAG, "initializeMessageLooper: quit.");
+                if (VERBOSE) Log.v(TAG, "initializeMessageLooper: quit.");
             }
         }.start();
 
@@ -187,7 +197,7 @@
     private static int calculateBufferSize(int width, int height,
                                            int format, int bpp) {
 
-        if (LOGV) {
+        if (VERBOSE) {
             Log.v(TAG, "calculateBufferSize: w=" + width + ",h=" + height
             + ",f=" + format + ",bpp=" + bpp);
         }
@@ -204,7 +214,7 @@
             int c_size = c_stride * height/2;
             int size = y_size + c_size * 2;
 
-            if (LOGV) {
+            if (VERBOSE) {
                 Log.v(TAG, "calculateBufferSize: YV12 size= " + size);
             }
 
@@ -238,9 +248,9 @@
             }
             mPreviewCallbackResult = PREVIEW_CALLBACK_RECEIVED;
             mCamera.stopPreview();
-            if (LOGV) Log.v(TAG, "notify the preview callback");
+            if (VERBOSE) Log.v(TAG, "notify the preview callback");
             mPreviewDone.open();
-            if (LOGV) Log.v(TAG, "Preview callback stop");
+            if (VERBOSE) Log.v(TAG, "Preview callback stop");
         }
     }
 
@@ -248,7 +258,7 @@
     private final class TestShutterCallback implements ShutterCallback {
         public void onShutter() {
             mShutterCallbackResult = true;
-            if (LOGV) Log.v(TAG, "onShutter called");
+            if (VERBOSE) Log.v(TAG, "onShutter called");
         }
     }
 
@@ -256,7 +266,7 @@
     private final class RawPictureCallback implements PictureCallback {
         public void onPictureTaken(byte [] rawData, Camera camera) {
             mRawPictureCallbackResult = true;
-            if (LOGV) Log.v(TAG, "RawPictureCallback callback");
+            if (VERBOSE) Log.v(TAG, "RawPictureCallback callback");
         }
     }
 
@@ -273,14 +283,14 @@
                     outStream.close();
                     mJpegPictureCallbackResult = true;
 
-                    if (LOGV) {
+                    if (VERBOSE) {
                         Log.v(TAG, "JpegPictureCallback rawDataLength = " + rawData.length);
                     }
                 } else {
                     mJpegPictureCallbackResult = false;
                 }
                 mSnapshotDone.open();
-                if (LOGV) Log.v(TAG, "Jpeg Picture callback");
+                if (VERBOSE) Log.v(TAG, "Jpeg Picture callback");
             } catch (IOException e) {
                 // no need to fail here; callback worked fine
                 Log.w(TAG, "Error writing picture to sd card.");
@@ -313,7 +323,7 @@
     }
 
     private void waitForPreviewDone() {
-        if (LOGV) Log.v(TAG, "Wait for preview callback");
+        if (VERBOSE) Log.v(TAG, "Wait for preview callback");
         if (!mPreviewDone.block(WAIT_FOR_COMMAND_TO_COMPLETE)) {
             // timeout could be expected or unexpected. The caller will decide.
             Log.v(TAG, "waitForPreviewDone: timeout");
@@ -340,7 +350,18 @@
     }
 
     private void checkPreviewCallback() throws Exception {
-        if (LOGV) Log.v(TAG, "check preview callback");
+        if (VERBOSE) Log.v(TAG, "check preview callback");
+        mCamera.startPreview();
+        waitForPreviewDone();
+        mCamera.setPreviewCallback(null);
+    }
+
+    /**
+     * Start preview and wait for the first preview callback, which indicates the
+     * preview becomes active.
+     */
+    private void blockingStartPreview() {
+        mCamera.setPreviewCallback(new SimplePreviewStreamCb(/*Id*/0));
         mCamera.startPreview();
         waitForPreviewDone();
         mCamera.setPreviewCallback(null);
@@ -385,7 +406,7 @@
             assertEquals(pictureSize.height, bmpOptions.outHeight);
         } else {
             int realArea = bmpOptions.outWidth * bmpOptions.outHeight;
-            if (LOGV) Log.v(TAG, "Video snapshot is " +
+            if (VERBOSE) Log.v(TAG, "Video snapshot is " +
                     bmpOptions.outWidth + " x " + bmpOptions.outHeight +
                     ", video size is " + videoWidth + " x " + videoHeight);
             assertTrue ("Video snapshot too small! Expected at least " +
@@ -810,6 +831,21 @@
         assertTrue(mJpegPictureCallbackResult);
         exif = new ExifInterface(JPEG_PATH);
         assertFalse(exif.hasThumbnail());
+        // Primary image should still be valid for no thumbnail capture.
+        BitmapFactory.decodeFile(JPEG_PATH, bmpOptions);
+        if (!recording) {
+            assertTrue("Jpeg primary image size should match requested size",
+                    bmpOptions.outWidth == pictureSize.width &&
+                    bmpOptions.outHeight == pictureSize.height);
+        } else {
+            assertTrue(bmpOptions.outWidth >= recordingWidth ||
+                    bmpOptions.outWidth == size.width);
+            assertTrue(bmpOptions.outHeight >= recordingHeight ||
+                    bmpOptions.outHeight == size.height);
+        }
+
+        assertNotNull("Jpeg primary image data should be decodable",
+                BitmapFactory.decodeFile(JPEG_PATH));
     }
 
     @UiThreadTest
@@ -835,8 +871,10 @@
 
         // Test various exif tags.
         ExifInterface exif = new ExifInterface(JPEG_PATH);
-        assertNotNull(exif.getAttribute(ExifInterface.TAG_MAKE));
-        assertNotNull(exif.getAttribute(ExifInterface.TAG_MODEL));
+        StringBuffer failedCause = new StringBuffer("Jpeg exif test failed:\n");
+        boolean extraExiftestPassed = checkExtraExifTagsSucceeds(failedCause, exif);
+
+        if (VERBOSE) Log.v(TAG, "Testing exif tag TAG_DATETIME");
         String datetime = exif.getAttribute(ExifInterface.TAG_DATETIME);
         assertNotNull(datetime);
         // Datetime should be local time.
@@ -849,6 +887,7 @@
         assertBitmapAndJpegSizeEqual(mJpegData, exif);
 
         // Test gps exif tags.
+        if (VERBOSE) Log.v(TAG, "Testing exif GPS tags");
         testGpsExifValues(parameters, 37.736071, -122.441983, 21, 1199145600,
             "GPS NETWORK HYBRID ARE ALL FINE.");
         testGpsExifValues(parameters, 0.736071, 0.441983, 1, 1199145601, "GPS");
@@ -856,6 +895,7 @@
 
         // Test gps tags do not exist after calling removeGpsData. Also check if
         // image width and height exif match the jpeg when jpeg rotation is set.
+        if (VERBOSE) Log.v(TAG, "Testing exif GPS tag removal");
         if (!recording) mCamera.startPreview();
         parameters.removeGpsData();
         parameters.setRotation(90); // For testing image width and height exif.
@@ -870,6 +910,158 @@
         mCamera.setParameters(parameters);
     }
 
+    /**
+     * Sanity check of some extra exif tags.
+     * <p>
+     * Sanity check some extra exif tags without asserting the check failures
+     * immediately. When a failure is detected, the failure cause is logged,
+     * the rest of the tests are still executed. The caller can assert with the
+     * failure cause based on the returned test status.
+     * </p>
+     *
+     * @param logBuf Log failure cause to this StringBuffer if there is
+     * any failure.
+     * @param exif The exif data associated with a jpeg image being tested.
+     * @return true if no test failure is found, false if there is any failure.
+     */
+    private boolean checkExtraExifTagsSucceeds(StringBuffer logBuf, ExifInterface exif) {
+        if (logBuf == null || exif == null) {
+            throw new IllegalArgumentException("failureCause and exif shouldn't be null");
+        }
+
+        if (VERBOSE) Log.v(TAG, "Testing extra exif tags");
+        boolean allTestsPassed = true;
+        boolean passedSoFar = true;
+        String failureMsg;
+
+        // TAG_EXPOSURE_TIME
+        // ExifInterface API gives exposure time value in the form of float instead of rational
+        String exposureTime = exif.getAttribute(ExifInterface.TAG_EXPOSURE_TIME);
+        passedSoFar = expectNotNull("Exif TAG_EXPOSURE_TIME is null!", logBuf, exposureTime);
+        if (passedSoFar) {
+            double exposureTimeValue = Double.parseDouble(exposureTime);
+            failureMsg = "Exif exposure time " + exposureTime + " should be a positive value";
+            passedSoFar = expectTrue(failureMsg, logBuf, exposureTimeValue > 0);
+        }
+        allTestsPassed = allTestsPassed && passedSoFar;
+
+        // TAG_APERTURE
+        // ExifInterface API gives aperture value in the form of float instead of rational
+        String aperture = exif.getAttribute(ExifInterface.TAG_APERTURE);
+        passedSoFar = expectNotNull("Exif TAG_APERTURE is null!", logBuf, aperture);
+        if (passedSoFar) {
+            double apertureValue = Double.parseDouble(aperture);
+            passedSoFar = expectTrue("Exif TAG_APERTURE value " + aperture + " should be positive!",
+                    logBuf, apertureValue > 0);
+        }
+        allTestsPassed = allTestsPassed && passedSoFar;
+
+        // TAG_FLASH
+        String flash = exif.getAttribute(ExifInterface.TAG_FLASH);
+        passedSoFar = expectNotNull("Exif TAG_FLASH is null!", logBuf, flash);
+        allTestsPassed = allTestsPassed && passedSoFar;
+
+        // TAG_WHITE_BALANCE
+        String whiteBalance = exif.getAttribute(ExifInterface.TAG_WHITE_BALANCE);
+        passedSoFar = expectNotNull("Exif TAG_WHITE_BALANCE is null!", logBuf, whiteBalance);
+        allTestsPassed = allTestsPassed && passedSoFar;
+
+        // TAG_MAKE
+        String make = exif.getAttribute(ExifInterface.TAG_MAKE);
+        passedSoFar = expectNotNull("Exif TAG_MAKE is null!", logBuf, make);
+        if (passedSoFar) {
+            passedSoFar = expectTrue("Exif TAG_MODEL value: " + make
+                    + " should match build manufacturer: " + Build.MANUFACTURER, logBuf,
+                    make.equals(Build.MANUFACTURER));
+        }
+        allTestsPassed = allTestsPassed && passedSoFar;
+
+        // TAG_MODEL
+        String model = exif.getAttribute(ExifInterface.TAG_MODEL);
+        passedSoFar = expectNotNull("Exif TAG_MODEL is null!", logBuf, model);
+        if (passedSoFar) {
+            passedSoFar = expectTrue("Exif TAG_MODEL value: " + model
+                    + " should match build manufacturer: " + Build.MODEL, logBuf,
+                    model.equals(Build.MODEL));
+        }
+        allTestsPassed = allTestsPassed && passedSoFar;
+
+        // TAG_ISO
+        int iso = exif.getAttributeInt(ExifInterface.TAG_ISO, -1);
+        passedSoFar = expectTrue("Exif ISO value " + iso + " is invalid", logBuf, iso > 0);
+        allTestsPassed = allTestsPassed && passedSoFar;
+
+        // TAG_DATETIME_DIGITIZED (a.k.a Create time for digital cameras).
+        String digitizedTime = exif.getAttribute(TAG_DATETIME_DIGITIZED);
+        passedSoFar = expectNotNull("Exif TAG_DATETIME_DIGITIZED is null!", logBuf, digitizedTime);
+        if (passedSoFar) {
+            String datetime = exif.getAttribute(ExifInterface.TAG_DATETIME);
+            passedSoFar = expectNotNull("Exif TAG_DATETIME is null!", logBuf, datetime);
+            if (passedSoFar) {
+                passedSoFar = expectTrue("dataTime should match digitizedTime", logBuf,
+                        digitizedTime.equals(datetime));
+            }
+        }
+        allTestsPassed = allTestsPassed && passedSoFar;
+
+        /**
+         * TAG_SUBSEC_TIME. Since the sub second tag strings are truncated to at
+         * most 9 digits in ExifInterface implementation, use getAttributeInt to
+         * sanitize it. When the default value -1 is returned, it means that
+         * this exif tag either doesn't exist or is a non-numerical invalid
+         * string. Same rule applies to the rest of sub second tags.
+         */
+        int subSecTime = exif.getAttributeInt(TAG_SUBSEC_TIME, -1);
+        passedSoFar = expectTrue(
+                "Exif TAG_SUBSEC_TIME value is null or invalid!", logBuf, subSecTime > 0);
+        allTestsPassed = allTestsPassed && passedSoFar;
+
+        // TAG_SUBSEC_TIME_ORIG
+        int subSecTimeOrig = exif.getAttributeInt(TAG_SUBSEC_TIME_ORIG, -1);
+        passedSoFar = expectTrue(
+                "Exif TAG_SUBSEC_TIME_ORIG value is null or invalid!", logBuf, subSecTimeOrig > 0);
+        allTestsPassed = allTestsPassed && passedSoFar;
+
+        // TAG_SUBSEC_TIME_DIG
+        int subSecTimeDig = exif.getAttributeInt(TAG_SUBSEC_TIME_DIG, -1);
+        passedSoFar = expectTrue(
+                "Exif TAG_SUBSEC_TIME_DIG value is null or invalid!", logBuf, subSecTimeDig > 0);
+        allTestsPassed = allTestsPassed && passedSoFar;
+
+        return allTestsPassed;
+    }
+
+    /**
+     * Check if object is null and log failure msg.
+     *
+     * @param msg Failure msg.
+     * @param logBuffer StringBuffer to log the failure msg.
+     * @param obj Object to test.
+     * @return true if object is not null, otherwise return false.
+     */
+    private boolean expectNotNull(String msg, StringBuffer logBuffer, Object obj)
+    {
+        if (obj == null) {
+            logBuffer.append(msg + "\n");
+        }
+        return (obj != null);
+    }
+
+    /**
+     * Check if condition is false and log failure msg.
+     *
+     * @param msg Failure msg.
+     * @param logBuffer StringBuffer to log the failure msg.
+     * @param condition Condition to test.
+     * @return The value of the condition.
+     */
+    private boolean expectTrue(String msg, StringBuffer logBuffer, boolean condition) {
+        if (!condition) {
+            logBuffer.append(msg + "\n");
+        }
+        return condition;
+    }
+
     private void assertBitmapAndJpegSizeEqual(byte[] jpegData, ExifInterface exif) {
         int exifWidth = exif.getAttributeInt(ExifInterface.TAG_IMAGE_WIDTH, 0);
         int exifHeight = exif.getAttributeInt(ExifInterface.TAG_IMAGE_LENGTH, 0);
@@ -906,7 +1098,26 @@
         assertEquals((float)latitude, latLong[0], 0.0001f);
         assertEquals((float)longitude, latLong[1], 0.0001f);
         assertEquals(altitude, exif.getAltitude(-1), 1);
-        assertEquals(timestamp, exif.getGpsDateTime() / 1000);
+        assertEquals(timestamp, getGpsDateTimeFromJpeg(exif) / 1000);
+    }
+
+    private long getGpsDateTimeFromJpeg(ExifInterface exif) {
+        String date = exif.getAttribute(ExifInterface.TAG_GPS_DATESTAMP);
+        String time = exif.getAttribute(ExifInterface.TAG_GPS_TIMESTAMP);
+        if (date == null || time == null) return -1;
+
+        String dateTimeString = date + ' ' + time;
+        ParsePosition pos = new ParsePosition(0);
+        try {
+            SimpleDateFormat formatter = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
+            formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
+
+            Date datetime = formatter.parse(dateTimeString, pos);
+            if (datetime == null) return -1;
+            return datetime.getTime();
+        } catch (IllegalArgumentException ex) {
+            return -1;
+        }
     }
 
     private void checkGpsDataNull(ExifInterface exif) {
@@ -1153,8 +1364,7 @@
             for (int i = 0; i < ratios.size() - 1; i++) {
                 assertTrue(ratios.get(i) < ratios.get(i + 1));
             }
-            mCamera.startPreview();
-            waitForPreviewDone();
+            blockingStartPreview();
 
             // Test each zoom step.
             for (int i = 0; i <= maxZoom; i++) {
@@ -1317,8 +1527,8 @@
 
     private void testFocusDistancesByCamera(int cameraId) throws Exception {
         initializeMessageLooper(cameraId);
-        mCamera.startPreview();
-        waitForPreviewDone();
+        blockingStartPreview();
+
         Parameters parameters = mCamera.getParameters();
 
         // Test every supported focus mode.
@@ -1649,6 +1859,7 @@
         initializeMessageLooper(cameraId);
 
         // Test if the parameters exists and minimum fps <= maximum fps.
+        final int INTERVAL_ERROR_THRESHOLD = 10;
         int[] defaultFps = new int[2];
         Parameters parameters = mCamera.getParameters();
         parameters.getPreviewFpsRange(defaultFps);
@@ -1709,6 +1920,13 @@
             // See if any frame duration violations occurred during preview run
             AssertionFailedError e = callback.getDurationException();
             if (e != null) throw(e);
+            int numIntervalError = callback.getNumIntervalError();
+            if (numIntervalError > INTERVAL_ERROR_THRESHOLD) {
+                fail(String.format(
+                        "Too many preview callback frame intervals out of bounds: " +
+                                "Count is %d, limit is %d",
+                        numIntervalError, INTERVAL_ERROR_THRESHOLD));
+            }
         }
 
         // Test the invalid fps cases.
@@ -1738,6 +1956,7 @@
         private ArrayList<Long> mFrames = new ArrayList<Long>();
         private long firstFrameArrivalTime;
         private AssertionFailedError mDurationException = null;
+        private int numIntervalError;
 
         public void reset(double minFps, double maxFps) {
             this.mMinFps = minFps;
@@ -1750,6 +1969,7 @@
             mFrames.clear();
             firstFrameArrivalTime = 0;
             mDurationException = null;
+            numIntervalError = 0;
         }
 
         // This method tests if the actual fps is between minimum and maximum.
@@ -1786,19 +2006,16 @@
                 double intervalMargin = 0.9;
                 long lastArrivalTime = mFrames.get(mFrames.size() - 1);
                 double interval = arrivalTime - lastArrivalTime;
-                if (LOGV) Log.v(TAG, "Frame interval=" + interval);
-                try {
-                    assertTrue("Frame interval (" + interval + "ms) is too " +
-                            "large. mMaxFrameInterval=" +
-                             mMaxFrameInterval + "ms",
-                            interval < mMaxFrameInterval *
-                            (1.0 + intervalMargin));
-                    assertTrue("Frame interval (" + interval + "ms) is too " +
-                            "small. mMinFrameInterval=" +
-                            mMinFrameInterval + "ms",
-                            interval > mMinFrameInterval *
-                            (1.0 - intervalMargin));
+                if (VERBOSE) Log.v(TAG, "Frame interval=" + interval);
 
+                try {
+                    if (interval > mMaxFrameInterval * (1.0 + intervalMargin) ||
+                            interval < mMinFrameInterval * (1.0 - intervalMargin)) {
+                        Log.i(TAG, "Bad frame interval=" + interval + "ms. Out out range " +
+                                mMinFrameInterval * (1.0 - intervalMargin) + "/" +
+                                mMaxFrameInterval * (1.0 + intervalMargin));
+                        numIntervalError++;
+                    }
                     // Check if the fps is within range.
                     double fpsMargin = 0.5; // x100 = percent
                     double avgInterval = (double)(arrivalTime - mFrames.get(0))
@@ -1825,6 +2042,9 @@
         public AssertionFailedError getDurationException() {
             return mDurationException;
         }
+        public int getNumIntervalError() {
+            return numIntervalError;
+        }
     }
 
     private void assertEquals(Size expected, Size actual) {
@@ -1891,8 +2111,7 @@
 
             // Make sure scene mode settings are consistent before preview and
             // after preview.
-            mCamera.startPreview();
-            waitForPreviewDone();
+            blockingStartPreview();
             for (int i = 0; i < supportedSceneModes.size(); i++) {
                 String sceneMode = supportedSceneModes.get(i);
                 parameters.setSceneMode(sceneMode);
@@ -2065,7 +2284,7 @@
     @UiThreadTest
     public void testMultiCameraRelease() throws Exception {
         // Verify that multiple cameras exist, and that they can be opened at the same time
-        if (LOGV) Log.v(TAG, "testMultiCameraRelease: Checking pre-conditions.");
+        if (VERBOSE) Log.v(TAG, "testMultiCameraRelease: Checking pre-conditions.");
         int nCameras = Camera.getNumberOfCameras();
         if (nCameras < 2) {
             Log.i(TAG, "Test multi-camera release: Skipping test because only 1 camera available");
@@ -2087,11 +2306,11 @@
         testCamera1.release();
 
         // Start first camera
-        if (LOGV) Log.v(TAG, "testMultiCameraRelease: Opening camera 0");
+        if (VERBOSE) Log.v(TAG, "testMultiCameraRelease: Opening camera 0");
         initializeMessageLooper(0);
         SimplePreviewStreamCb callback0 = new SimplePreviewStreamCb(0);
         mCamera.setPreviewCallback(callback0);
-        if (LOGV) Log.v(TAG, "testMultiCameraRelease: Starting preview on camera 0");
+        if (VERBOSE) Log.v(TAG, "testMultiCameraRelease: Starting preview on camera 0");
         mCamera.startPreview();
         // Run preview for a bit
         for (int f = 0; f < 100; f++) {
@@ -2099,7 +2318,7 @@
             assertTrue("testMultiCameraRelease: First camera preview timed out on frame " + f + "!",
                        mPreviewDone.block( WAIT_FOR_COMMAND_TO_COMPLETE));
         }
-        if (LOGV) Log.v(TAG, "testMultiCameraRelease: Stopping preview on camera 0");
+        if (VERBOSE) Log.v(TAG, "testMultiCameraRelease: Stopping preview on camera 0");
         mCamera.stopPreview();
         // Save message looper and camera to deterministically release them, instead
         // of letting GC do it at some point.
@@ -2111,11 +2330,11 @@
 
         // Start second camera without releasing the first one (will
         // set mCamera and mLooper to new objects)
-        if (LOGV) Log.v(TAG, "testMultiCameraRelease: Opening camera 1");
+        if (VERBOSE) Log.v(TAG, "testMultiCameraRelease: Opening camera 1");
         initializeMessageLooper(1);
         SimplePreviewStreamCb callback1 = new SimplePreviewStreamCb(1);
         mCamera.setPreviewCallback(callback1);
-        if (LOGV) Log.v(TAG, "testMultiCameraRelease: Starting preview on camera 1");
+        if (VERBOSE) Log.v(TAG, "testMultiCameraRelease: Starting preview on camera 1");
         mCamera.startPreview();
         // Run preview for a bit - GC of first camera instance should not impact the second's
         // operation.
@@ -2125,11 +2344,11 @@
                        mPreviewDone.block( WAIT_FOR_COMMAND_TO_COMPLETE));
             if (f == 50) {
                 // Release first camera mid-preview, should cause no problems
-                if (LOGV) Log.v(TAG, "testMultiCameraRelease: Releasing camera 0");
+                if (VERBOSE) Log.v(TAG, "testMultiCameraRelease: Releasing camera 0");
                 firstCamera.release();
             }
         }
-        if (LOGV) Log.v(TAG, "testMultiCameraRelease: Stopping preview on camera 0");
+        if (VERBOSE) Log.v(TAG, "testMultiCameraRelease: Stopping preview on camera 0");
         mCamera.stopPreview();
 
         firstLooper.quit();
@@ -2145,7 +2364,7 @@
             mId = id;
         }
         public void onPreviewFrame(byte[] data, android.hardware.Camera camera) {
-            if (LOGV) Log.v(TAG, "Preview frame callback, id " + mId + ".");
+            if (VERBOSE) Log.v(TAG, "Preview frame callback, id " + mId + ".");
             mPreviewDone.open();
         }
     }
@@ -2786,6 +3005,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/Camera_SizeTest.java b/tests/tests/hardware/src/android/hardware/cts/Camera_SizeTest.java
index 72d4ba3..2f9c94b 100644
--- a/tests/tests/hardware/src/android/hardware/cts/Camera_SizeTest.java
+++ b/tests/tests/hardware/src/android/hardware/cts/Camera_SizeTest.java
@@ -17,14 +17,21 @@
 package android.hardware.cts;
 
 
+import android.cts.util.CtsAndroidTestCase;
 import android.hardware.Camera;
 import android.hardware.Camera.Parameters;
+import android.hardware.cts.helpers.CameraUtils;
 import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
 
-import junit.framework.TestCase;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import java.util.Collections;
+import java.util.List;
 
 @LargeTest
-public class Camera_SizeTest extends TestCase {
+public class Camera_SizeTest extends CtsAndroidTestCase {
 
     private final int HEIGHT1 = 320;
     private final int WIDTH1 = 240;
@@ -33,6 +40,10 @@
     private final int HEIGHT3 = 640;
     private final int WIDTH3 = 480;
 
+    private static final float ASPECT_RATIO_TOLERANCE = 0.05f;
+
+    private static final String TAG = "Camera_SizeTest";
+
     public void testConstructor() {
         if (Camera.getNumberOfCameras() < 1) {
             return;
@@ -48,10 +59,61 @@
         camera.release();
     }
 
+    /**
+     * Check that the largest available preview and jpeg outputs have the same aspect ratio.  This
+     * aspect ratio must be the same as the physical camera sensor, and the FOV for these outputs
+     * must not be cropped.
+     *
+     * This is only required for backward compatibility of the Camera2 API when running in LEGACY
+     * mode.
+     *
+     * @see {@link android.hardware.camera2.CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
+     */
+    public void testMaxAspectRatios() throws Exception {
+        for (int id = 0; id < Camera.getNumberOfCameras(); ++id) {
+            if (CameraUtils.isLegacyHAL(getContext(), id)) {
+
+                Camera camera = Camera.open(id);
+                Parameters parameters = camera.getParameters();
+
+                List<Camera.Size> supportedJpegDimens = parameters.getSupportedPictureSizes();
+                List<Camera.Size> supportedPreviewDimens = parameters.getSupportedPreviewSizes();
+
+                Collections.sort(supportedJpegDimens, new CameraUtils.LegacySizeComparator());
+                Collections.sort(supportedPreviewDimens, new CameraUtils.LegacySizeComparator());
+
+                Camera.Size largestJpegDimen =
+                        supportedJpegDimens.get(supportedJpegDimens.size() - 1);
+                Camera.Size largestPreviewDimen =
+                        supportedPreviewDimens.get(supportedPreviewDimens.size() - 1);
+
+                float jpegAspect = largestJpegDimen.width / (float) largestJpegDimen.height;
+                float previewAspect =
+                        largestPreviewDimen.width / (float) largestPreviewDimen.height;
+
+                if (Math.abs(jpegAspect - previewAspect) >= ASPECT_RATIO_TOLERANCE) {
+                    Log.w(TAG,
+                            "Largest preview dimension (w=" + largestPreviewDimen.width + ", h=" +
+                            largestPreviewDimen.height + ") should have the same aspect ratio " +
+                            "as the largest Jpeg dimension (w=" + largestJpegDimen.width +
+                            ", h=" + largestJpegDimen.height + ")");
+                }
+
+
+                camera.release();
+            }
+        }
+    }
+
     private void checkSize(Parameters parameters, int width, int height) {
         parameters.setPictureSize(width, height);
         assertEquals(width, parameters.getPictureSize().width);
         assertEquals(height, parameters.getPictureSize().height);
     }
-}
 
+    private static void addTestToSuite(TestSuite testSuite, String testName) {
+        Camera_SizeTest test = new Camera_SizeTest();
+        test.setName(testName);
+        testSuite.addTest(test);
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/GLSurfaceViewCtsActivity.java b/tests/tests/hardware/src/android/hardware/cts/GLSurfaceViewCtsActivity.java
new file mode 100644
index 0000000..fa2a0e5
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/GLSurfaceViewCtsActivity.java
@@ -0,0 +1,123 @@
+/*
+ * 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.cts;
+
+import android.app.Activity;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.view.Window;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+/**
+ * A minimal activity for testing {@link android.opengl.GLSurfaceView}.
+ * Also accepts non-blank renderers to allow its use for more complex tests.
+ */
+public class GLSurfaceViewCtsActivity extends Activity {
+
+    private static class Renderer implements GLSurfaceView.Renderer {
+
+        public void onDrawFrame(GL10 gl) {
+            // Do nothing.
+        }
+
+        public void onSurfaceChanged(GL10 gl, int width, int height) {
+            // Do nothing.
+        }
+
+        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+            // Do nothing.
+        }
+    }
+
+    private GLSurfaceView mView;
+
+    /** To override the blank renderer, or other settings, these
+     * static set* methods must be called before onCreate() is called.
+     * If using ActivityInstrumentationTestCase2, that means the set
+     * methods need to be called before calling getActivity in the
+     * test setUp().
+     */
+    private static GLSurfaceView.Renderer mRenderer = null;
+    public static void setRenderer(GLSurfaceView.Renderer renderer) {
+        mRenderer = renderer;
+    }
+    public static void resetRenderer() {
+        mRenderer = null;
+    }
+
+    private static int mRenderMode = 0;
+    private static boolean mRenderModeSet = false;
+    public static void setRenderMode(int renderMode) {
+        mRenderModeSet = true;
+        mRenderMode = renderMode;
+    }
+    public static void resetRenderMode() {
+        mRenderModeSet = false;
+        mRenderMode = 0;
+    }
+
+    private static int mGlVersion = 0;
+    private static boolean mGlVersionSet = false;
+    public static void setGlVersion(int glVersion) {
+        mGlVersionSet = true;
+        mGlVersion = glVersion;
+    }
+    public static void resetGlVersion() {
+        mGlVersionSet = false;
+        mGlVersion = 0;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mView = new GLSurfaceView(this);
+        // Only set this if explicitly asked for
+        if (mGlVersionSet) {
+            mView.setEGLContextClientVersion(mGlVersion);
+        }
+        // Use no-op renderer by default
+        if (mRenderer == null) {
+            mView.setRenderer(new Renderer());
+        } else {
+            mView.setRenderer(mRenderer);
+        }
+        // Only set this if explicitly asked for
+        if (mRenderModeSet) {
+            mView.setRenderMode(mRenderMode);
+        }
+        this.requestWindowFeature(Window.FEATURE_NO_TITLE);
+        setContentView(mView);
+    }
+
+    public GLSurfaceView getView() {
+        return mView;
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        mView.onResume();
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        mView.onPause();
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorBatchingTests.java b/tests/tests/hardware/src/android/hardware/cts/SensorBatchingTests.java
new file mode 100644
index 0000000..687826c
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorBatchingTests.java
@@ -0,0 +1,317 @@
+/*
+ * 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.cts;
+
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.sensoroperations.TestSensorFlushOperation;
+import android.hardware.cts.helpers.sensoroperations.TestSensorOperation;
+import android.hardware.cts.helpers.sensoroperations.VerifiableSensorOperation;
+import android.hardware.cts.helpers.sensorverification.ISensorVerification;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Set of tests to verify that sensors operate correctly when operating in batching mode.
+ * This class defines tests for continuous sensors when the device is awake.
+ * On-change and special sensors are tested separately inside CtsVerifier, and they are defined in:
+ * {@link com.android.cts.verifier.sensors.BatchingTestActivity}.
+ *
+ * Each test is expected to pass even if batching is not supported for a particular sensor. This is
+ * usually achieved by ensuring that {@link ISensorVerification}s fallback accordingly.
+ *
+ * <p>To execute these test cases, the following command can be used:</p>
+ * <pre>
+ * adb shell am instrument -e class android.hardware.cts.SensorBatchingTests \
+ *     -w com.android.cts.hardware/android.test.AndroidJUnitRunner
+ * </pre>
+ */
+public class SensorBatchingTests extends SensorTestCase {
+    private static final String TAG = "SensorBatchingTests";
+
+    private static final int BATCHING_10S = 10;
+    private static final int RATE_50HZ = 20000;
+    private static final int RATE_FASTEST = SensorManager.SENSOR_DELAY_FASTEST;
+
+    /**
+     * An arbitrary 'padding' time slot to wait for events after batching latency expires.
+     * This allows for the test to wait for event arrivals after batching was expected.
+     */
+    private static final int BATCHING_PADDING_TIME_S = 2;
+
+    public void testAccelerometer_fastest_batching() throws Throwable {
+        runBatchingSensorTest(Sensor.TYPE_ACCELEROMETER, RATE_FASTEST, BATCHING_10S);
+    }
+
+    public void testAccelerometer_50hz_batching() throws Throwable {
+        runBatchingSensorTest(Sensor.TYPE_ACCELEROMETER, RATE_50HZ, BATCHING_10S);
+    }
+
+    public void testAccelerometer_fastest_flush() throws Throwable {
+        runFlushSensorTest(Sensor.TYPE_ACCELEROMETER, RATE_FASTEST, BATCHING_10S);
+    }
+
+    public void testAccelerometer_50hz_flush() throws Throwable {
+        runFlushSensorTest(Sensor.TYPE_ACCELEROMETER, RATE_50HZ, BATCHING_10S);
+    }
+
+    public void testMagneticField_fastest_batching() throws Throwable {
+        runBatchingSensorTest(Sensor.TYPE_MAGNETIC_FIELD, RATE_FASTEST, BATCHING_10S);
+    }
+
+    public void testMagneticField_50hz_batching() throws Throwable {
+        runBatchingSensorTest(Sensor.TYPE_MAGNETIC_FIELD, RATE_50HZ, BATCHING_10S);
+    }
+
+    public void testMagneticField_fastest_flush() throws Throwable {
+        runFlushSensorTest(Sensor.TYPE_MAGNETIC_FIELD, RATE_FASTEST, BATCHING_10S);
+    }
+
+    public void testMagneticField_50hz_flush() throws Throwable {
+        runFlushSensorTest(Sensor.TYPE_MAGNETIC_FIELD, RATE_50HZ, BATCHING_10S);
+    }
+
+    @SuppressWarnings("deprecation")
+    public void testOrientation_fastest_batching() throws Throwable {
+        runBatchingSensorTest(Sensor.TYPE_ORIENTATION, RATE_FASTEST, BATCHING_10S);
+    }
+
+    @SuppressWarnings("deprecation")
+    public void testOrientation_50hz_batching() throws Throwable {
+        runBatchingSensorTest(Sensor.TYPE_ORIENTATION, RATE_50HZ, BATCHING_10S);
+    }
+
+    @SuppressWarnings("deprecation")
+    public void testOrientation_fastest_flush() throws Throwable {
+        runFlushSensorTest(Sensor.TYPE_ORIENTATION, RATE_FASTEST, BATCHING_10S);
+    }
+
+    @SuppressWarnings("deprecation")
+    public void testOrientation_50hz_flush() throws Throwable {
+        runFlushSensorTest(Sensor.TYPE_ORIENTATION, RATE_50HZ, BATCHING_10S);
+    }
+
+    public void testGyroscope_fastest_batching() throws Throwable {
+        runBatchingSensorTest(Sensor.TYPE_GYROSCOPE, RATE_FASTEST, BATCHING_10S);
+    }
+
+    public void testGyroscope_50hz_batching() throws Throwable {
+        runBatchingSensorTest(Sensor.TYPE_GYROSCOPE, RATE_50HZ, BATCHING_10S);
+    }
+
+    public void testGyroscope_fastest_flush() throws Throwable {
+        runFlushSensorTest(Sensor.TYPE_GYROSCOPE, SensorManager.SENSOR_DELAY_FASTEST, BATCHING_10S);
+    }
+
+    public void testGyroscope_50hz_flush() throws Throwable {
+        runFlushSensorTest(Sensor.TYPE_GYROSCOPE, RATE_50HZ, BATCHING_10S);
+    }
+
+    public void testPressure_fastest_batching() throws Throwable {
+        runBatchingSensorTest(Sensor.TYPE_PRESSURE, RATE_FASTEST, BATCHING_10S);
+    }
+
+    public void testPressure_50hz_batching() throws Throwable {
+        runBatchingSensorTest(Sensor.TYPE_PRESSURE, RATE_50HZ, BATCHING_10S);
+    }
+
+    public void testPressure_fastest_flush() throws Throwable {
+        runFlushSensorTest(Sensor.TYPE_PRESSURE, SensorManager.SENSOR_DELAY_FASTEST, BATCHING_10S);
+    }
+
+    public void testPressure_50hz_flush() throws Throwable {
+        runFlushSensorTest(Sensor.TYPE_PRESSURE, RATE_50HZ, BATCHING_10S);
+    }
+
+    public void testGravity_fastest_batching() throws Throwable {
+        runBatchingSensorTest(Sensor.TYPE_GRAVITY, RATE_FASTEST, BATCHING_10S);
+    }
+
+    public void testGravity_50hz_batching() throws Throwable {
+        runBatchingSensorTest(Sensor.TYPE_GRAVITY, RATE_50HZ, BATCHING_10S);
+    }
+
+    public void testGravity_fastest_flush() throws Throwable {
+        runFlushSensorTest(Sensor.TYPE_GRAVITY, SensorManager.SENSOR_DELAY_FASTEST, BATCHING_10S);
+    }
+
+    public void testGravity_50hz_flush() throws Throwable {
+        runFlushSensorTest(Sensor.TYPE_GRAVITY, RATE_50HZ, BATCHING_10S);
+    }
+
+    public void testRotationVector_fastest_batching() throws Throwable {
+        runBatchingSensorTest(Sensor.TYPE_ROTATION_VECTOR, RATE_FASTEST, BATCHING_10S);
+    }
+
+    public void testRotationVector_50hz_batching() throws Throwable {
+        runBatchingSensorTest(Sensor.TYPE_ROTATION_VECTOR, RATE_50HZ, BATCHING_10S);
+    }
+
+    public void testRotationVector_fastest_flush() throws Throwable {
+        runFlushSensorTest(Sensor.TYPE_ROTATION_VECTOR, RATE_FASTEST, BATCHING_10S);
+    }
+
+    public void testRotationVector_50hz_flush() throws Throwable {
+        runFlushSensorTest(Sensor.TYPE_ROTATION_VECTOR, RATE_50HZ, BATCHING_10S);
+    }
+
+    public void testMagneticFieldUncalibrated_fastest_batching() throws Throwable {
+        runBatchingSensorTest(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, RATE_FASTEST, BATCHING_10S);
+    }
+
+    public void testMagneticFieldUncalibrated_50hz_batching() throws Throwable {
+        runBatchingSensorTest(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, RATE_50HZ, BATCHING_10S);
+    }
+
+    public void testMagneticFieldUncalibrated_fastest_flush() throws Throwable {
+        runFlushSensorTest(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, RATE_FASTEST, BATCHING_10S);
+    }
+
+    public void testMagneticFieldUncalibrated_50hz_flush() throws Throwable {
+        runFlushSensorTest(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, RATE_50HZ, BATCHING_10S);
+    }
+
+    public void testGameRotationVector_fastest_batching() throws Throwable {
+        runBatchingSensorTest(Sensor.TYPE_GAME_ROTATION_VECTOR, RATE_FASTEST, BATCHING_10S);
+    }
+
+    public void testGameRotationVector_50hz_batching() throws Throwable {
+        runBatchingSensorTest(Sensor.TYPE_GAME_ROTATION_VECTOR, RATE_50HZ, BATCHING_10S);
+    }
+
+    public void testGameRotationVector_fastest_flush() throws Throwable {
+        runFlushSensorTest(Sensor.TYPE_GAME_ROTATION_VECTOR, RATE_FASTEST, BATCHING_10S);
+    }
+
+    public void testGameRotationVector_50hz_flush() throws Throwable {
+        runFlushSensorTest(Sensor.TYPE_GAME_ROTATION_VECTOR, RATE_50HZ, BATCHING_10S);
+    }
+
+    public void testGyroscopeUncalibrated_fastest_batching() throws Throwable {
+        runBatchingSensorTest(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, RATE_FASTEST, BATCHING_10S);
+    }
+
+    public void testGyroscopeUncalibrated_50hz_batching() throws Throwable {
+        runBatchingSensorTest(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, RATE_50HZ, BATCHING_10S);
+    }
+
+    public void testGyroscopeUncalibrated_fastest_flush() throws Throwable {
+        runFlushSensorTest(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, RATE_FASTEST, BATCHING_10S);
+    }
+
+    public void testGyroscopeUncalibrated_50hz_flush() throws Throwable {
+        runFlushSensorTest(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, RATE_50HZ, BATCHING_10S);
+    }
+
+    public void testLinearAcceleration_fastest_batching() throws Throwable {
+        runBatchingSensorTest(Sensor.TYPE_LINEAR_ACCELERATION, RATE_FASTEST, BATCHING_10S);
+    }
+
+    public void testLinearAcceleration_50hz_batching() throws Throwable {
+        runBatchingSensorTest(Sensor.TYPE_LINEAR_ACCELERATION, RATE_50HZ, BATCHING_10S);
+    }
+
+    public void testLinearAcceleration_fastest_flush() throws Throwable {
+        runFlushSensorTest(Sensor.TYPE_LINEAR_ACCELERATION, RATE_FASTEST, BATCHING_10S);
+    }
+
+    public void testLinearAcceleration_50hz_flush() throws Throwable {
+        runFlushSensorTest(Sensor.TYPE_LINEAR_ACCELERATION, RATE_50HZ, BATCHING_10S);
+    }
+
+    public void testGeomagneticRotationVector_fastest_batching() throws Throwable {
+        runBatchingSensorTest(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, RATE_FASTEST, BATCHING_10S);
+    }
+
+    public void testGeomagneticRotationVector_50hz_batching() throws Throwable {
+        runBatchingSensorTest(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, RATE_50HZ, BATCHING_10S);
+    }
+
+    public void testGeomagneticRotationVector_fastest_flush() throws Throwable {
+        runFlushSensorTest(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, RATE_FASTEST, BATCHING_10S);
+    }
+
+    public void testGeomagneticRotationVector_50hz_flush() throws Throwable {
+        runFlushSensorTest(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, RATE_50HZ, BATCHING_10S);
+    }
+
+    private void runBatchingSensorTest(int sensorType, int rateUs, int maxBatchReportLatencySec)
+            throws Throwable {
+        int maxBatchReportLatencyUs = (int) TimeUnit.SECONDS.toMicros(maxBatchReportLatencySec);
+        int testDurationSec = maxBatchReportLatencySec + BATCHING_PADDING_TIME_S;
+
+        TestSensorEnvironment environment = new TestSensorEnvironment(
+                getContext(),
+                sensorType,
+                shouldEmulateSensorUnderLoad(),
+                rateUs,
+                maxBatchReportLatencyUs);
+        TestSensorOperation operation =
+                new TestSensorOperation(environment, testDurationSec, TimeUnit.SECONDS);
+
+        executeTest(environment, operation, false /* flushExpected */);
+    }
+
+    private void runFlushSensorTest(int sensorType, int rateUs, int maxBatchReportLatencySec)
+            throws Throwable {
+        int maxBatchReportLatencyUs = (int) TimeUnit.SECONDS.toMicros(maxBatchReportLatencySec);
+        int flushDurationSec = maxBatchReportLatencySec / 2;
+
+        TestSensorEnvironment environment = new TestSensorEnvironment(
+                getContext(),
+                sensorType,
+                shouldEmulateSensorUnderLoad(),
+                rateUs,
+                maxBatchReportLatencyUs);
+        TestSensorFlushOperation operation =
+                new TestSensorFlushOperation(environment, flushDurationSec, TimeUnit.SECONDS);
+
+        executeTest(environment, operation, true /* flushExpected */);
+    }
+
+    private void executeTest(
+            TestSensorEnvironment environment,
+            VerifiableSensorOperation operation,
+            boolean flushExpected) throws Throwable {
+        operation.addDefaultVerifications();
+        operation.setLogEvents(true);
+
+        try {
+            operation.execute();
+        } finally {
+            SensorStats.logStats(TAG, operation.getStats());
+
+            String sensorRate;
+            if (environment.getRequestedSamplingPeriodUs() == SensorManager.SENSOR_DELAY_FASTEST) {
+                sensorRate = "fastest";
+            } else {
+                sensorRate = String.format("%.0fhz", environment.getFrequencyHz());
+            }
+            String batching = environment.getMaxReportLatencyUs() > 0 ? "_batching" : "";
+            String flush = flushExpected ? "_flush" : "";
+            String fileName = String.format(
+                    "batching_%s_%s%s%s.txt",
+                    SensorStats.getSanitizedSensorName(environment.getSensor()),
+                    sensorRate,
+                    batching,
+                    flush);
+            SensorStats.logStatsToFile(fileName, operation.getStats());
+        }
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorEventOrderingTests.java b/tests/tests/hardware/src/android/hardware/cts/SensorEventOrderingTests.java
deleted file mode 100644
index 116ac80..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/SensorEventOrderingTests.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.cts;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-import android.hardware.Sensor;
-import android.hardware.SensorManager;
-
-import android.hardware.cts.helpers.SensorTestCase;
-
-import android.hardware.cts.helpers.sensorTestOperations.VerifyEventOrderingOperation;
-
-/**
- * Verifies the proper ordering in time of sensor events.
- */
-public class SensorEventOrderingTests extends SensorTestCase {
-    /**
-     * Builder for the test suite.
-     * This is the method that will build dynamically the set of test cases to execute.
-     * Each 'base' test case is composed by three parts:
-     * - the matrix definition
-     * - the test method that will execute the test case
-     * - a static method that will combine both and add test case instances to the test suite
-     */
-    public static Test suite() {
-        TestSuite testSuite = new TestSuite();
-
-        // add test generation routines
-        createEventOrderingTestCases(testSuite);
-
-        return testSuite;
-    }
-
-    /**
-     * Event ordering test cases.
-     */
-    private int mSensorType;
-    private int mSamplingRateInUs;
-    private int mReportLatencyInUs;
-
-    private static void createEventOrderingTestCases(TestSuite testSuite) {
-        int testDefinitionMatrix[][] = {
-                // { SensorType, SamplingRateInUs, ReportLatencyInUs },
-                { Sensor.TYPE_ACCELEROMETER, SensorManager.SENSOR_DELAY_FASTEST, 0 },
-                { Sensor.TYPE_GYROSCOPE, SensorManager.SENSOR_DELAY_FASTEST, 0 },
-                { Sensor.TYPE_MAGNETIC_FIELD, SensorManager.SENSOR_DELAY_FASTEST, 0 },
-                { Sensor.TYPE_PRESSURE, SensorManager.SENSOR_DELAY_FASTEST, 0 },
-                { Sensor.TYPE_GRAVITY, SensorManager.SENSOR_DELAY_FASTEST, 0 },
-                { Sensor.TYPE_LINEAR_ACCELERATION, SensorManager.SENSOR_DELAY_FASTEST, 0 },
-                { Sensor.TYPE_ROTATION_VECTOR, SensorManager.SENSOR_DELAY_FASTEST, 0 },
-                { Sensor.TYPE_RELATIVE_HUMIDITY, SensorManager.SENSOR_DELAY_FASTEST, 0 },
-                { Sensor.TYPE_AMBIENT_TEMPERATURE, SensorManager.SENSOR_DELAY_FASTEST, 0 },
-                { Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, SensorManager.SENSOR_DELAY_FASTEST, 0 },
-                { Sensor.TYPE_GAME_ROTATION_VECTOR, SensorManager.SENSOR_DELAY_FASTEST, 0 },
-                { Sensor.TYPE_GYROSCOPE_UNCALIBRATED, SensorManager.SENSOR_DELAY_FASTEST, 0 },
-                { Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, SensorManager.SENSOR_DELAY_FASTEST,0 },
-        };
-
-        for(int definition[] : testDefinitionMatrix) {
-            SensorEventOrderingTests test = new SensorEventOrderingTests();
-            test.mSensorType = definition[0];
-            test.mSamplingRateInUs = definition[1];
-            test.mReportLatencyInUs = definition[2];
-            test.setName("testEventOrdering");
-            testSuite.addTest(test);
-        }
-    }
-
-    /**
-     * This test verifies the ordering of the sampled data reported by the Sensor under test.
-     * This test is used to guarantee that sensor data is reported in the order it occurs, and that
-     * events are always reported in order.
-     *
-     * The test takes a set of samples from the Sensor under test, and then it verifies that each
-     * event's timestamp is in the future compared with the previous event. At the end of the
-     * validation, the full set of events is verified to be ordered by timestamp as they are
-     * generated.
-     *
-     * The test can be susceptible to errors if the sensor sampled data is not timestamped at the
-     * Hardware level. Or events sampled at high rates are added to the FIFO without controlling the
-     * appropriate ordering of the events.
-     *
-     * The assertion associated with the test provides the information of the two consecutive events
-     * that cause the test to fail.
-     */
-    public void testEventOrdering() throws Throwable {
-        VerifyEventOrderingOperation operation = new VerifyEventOrderingOperation(
-                this.getContext(),
-                mSensorType,
-                mSamplingRateInUs,
-                mReportLatencyInUs);
-        operation.execute();
-    }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorFrequencyTests.java b/tests/tests/hardware/src/android/hardware/cts/SensorFrequencyTests.java
deleted file mode 100644
index b35f515..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/SensorFrequencyTests.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.cts;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-import android.hardware.Sensor;
-
-import android.hardware.cts.helpers.SensorCtsHelper;
-import android.hardware.cts.helpers.SensorTestCase;
-
-import android.hardware.cts.helpers.sensorTestOperations.VerifyJitteringOperation;
-import android.hardware.cts.helpers.sensorTestOperations.VerifyMaximumFrequencyOperation;
-
-/**
- * Verifies several properties of the sampling rate of the different sensors in the platform.
- */
-public class SensorFrequencyTests extends SensorTestCase {
-    private int mSensorType;
-    private int mReportLatencyInUs;
-    private int mThresholdPercentageOfNs;
-
-    /**
-     * Builder for the test suite.
-     * This is the method that will build dynamically the set of test cases to execute.
-     * Each 'base' test case is composed by three parts:
-     * - the matrix definition
-     * - the test method that will execute the test case
-     * - a static method that will combine both and add test case instances to the test suite
-     */
-    public static Test suite() {
-        TestSuite testSuite = new TestSuite();
-
-        // add test generation routines
-        createMaxFrequencyExpectedTestCases(testSuite);
-        // TODO: tests are a unreliable in the lab
-        //createMaxFrequencyTestCases(testSuite);
-        //createJitteringTestCases(testSuite);
-
-        return testSuite;
-    }
-
-    /**
-     * Max frequency test cases.
-     */
-    private static void createMaxFrequencyTestCases(TestSuite testSuite) {
-        int testDefinitionMatrix[][] = {
-                // { SensorType, ReportLatencyInUs, ThresholdPercentageOfNs },
-                { Sensor.TYPE_ACCELEROMETER, 0, 10 },
-                { Sensor.TYPE_GYROSCOPE, 0, 10 },
-                { Sensor.TYPE_MAGNETIC_FIELD, 0, 10 },
-        };
-
-        for(int definition[] : testDefinitionMatrix) {
-            SensorFrequencyTests test = new SensorFrequencyTests();
-            test.mSensorType = definition[0];
-            test.mReportLatencyInUs = definition[1];
-            test.mThresholdPercentageOfNs = definition[2];
-            test.setName("testMaxFrequency");
-            testSuite.addTest(test);
-        }
-    }
-
-    /**
-     * This test verifies that the Sensor under test can sample and report data at the Maximum
-     * frequency (sampling rate) it advertises.
-     *
-     * The test takes a set of samples from the sensor under test, and calculates the mean of the
-     * frequency at which the events are reported. The frequency between events is calculated by
-     * looking at the delta between the timestamps associated with each event.
-     *
-     * The test is susceptible to errors if the Sensor is not capable to sample data at the maximum
-     * rate it supports, or the sensor events are not timestamped at the Hardware level.
-     *
-     * The assertion associated with the test provides the required data to identify:
-     * - the thread id on which the failure occurred
-     * - the sensor type and sensor handle that caused the failure
-     * - the expected frequency
-     * - the observed frequency
-     * In addition to that, the device's debug output (adb logcat) dumps the set of timestamp deltas
-     * associated with the set of data gathered from the Sensor under test.
-     */
-    public void testMaxFrequency() throws Throwable {
-        VerifyMaximumFrequencyOperation operation = new VerifyMaximumFrequencyOperation(
-                this.getContext(),
-                mSensorType,
-                mReportLatencyInUs,
-                mThresholdPercentageOfNs);
-        operation.execute();
-    }
-
-    /**
-     * Jittering test cases.
-     */
-    private static void createJitteringTestCases(TestSuite testSuite) {
-        int testDefinitionMatrix[][] = {
-                // { SensorType, ReportLatencyInUs, ThresholdPercentageOfNs },
-                { Sensor.TYPE_ACCELEROMETER, 0, 10 },
-                { Sensor.TYPE_GYROSCOPE, 0, 10 },
-                { Sensor.TYPE_MAGNETIC_FIELD, 0, 10 },
-        };
-
-        for(int definition[] : testDefinitionMatrix) {
-            SensorFrequencyTests test = new SensorFrequencyTests();
-            test.mSensorType = definition[0];
-            test.mReportLatencyInUs = definition[1];
-            test.mThresholdPercentageOfNs = definition[2];
-            test.setName("testJittering");
-            testSuite.addTest(test);
-        }
-    }
-
-    /**
-     * This test verifies that the event jittering associated with the sampled data reported by the
-     * Sensor under test, aligns with the requirements imposed in the CDD.
-     * This test characterizes how the sensor behaves while sampling data at a specific rate.
-     *
-     * The test takes a set of samples from the sensor under test, using the maximum sampling rate
-     * advertised by the Sensor under test. It then compares the 95%ile associated with the
-     * jittering of the timestamps, with an expected value.
-     *
-     * The test is susceptible to errors if the sensor events are not timestamped at the Hardware
-     * level.
-     *
-     * The assertion associated with the failure provides the following information:
-     * - the thread id on which the failure occurred
-     * - the sensor type and sensor handle that caused the failure
-     * - the expectation of the test with respect of the 95%ile
-     * - the calculated 95%ile jittering
-     * Additionally, the device's debug output (adb logcat) dumps the set of jitter values
-     * calculated.
-     */
-    public void testJittering() throws Throwable {
-        VerifyJitteringOperation operation = new VerifyJitteringOperation(
-                this.getContext(),
-                mSensorType,
-                mReportLatencyInUs,
-                mThresholdPercentageOfNs);
-        operation.execute();
-    }
-
-    /**
-     * Max Frequency expected Test Cases.
-     */
-    private int mExpectedSamplingRateInUs;
-
-    private static void createMaxFrequencyExpectedTestCases(TestSuite testSuite) {
-        int testDefinitionMatrix[][] = {
-                // { SensorType, ExpectedSamplingRateInUs },
-                { Sensor.TYPE_ACCELEROMETER, 10000 /* 100 Hz */ },
-                { Sensor.TYPE_GYROSCOPE, 10000 /* 100 Hz */ },
-                { Sensor.TYPE_MAGNETIC_FIELD, 100000 /* 10 Hz */ },
-        };
-
-        for(int definition[] : testDefinitionMatrix) {
-            SensorFrequencyTests test = new SensorFrequencyTests();
-            test.mSensorType = definition[0];
-            test.mExpectedSamplingRateInUs = definition[1];
-            test.setName("testMaxFrequencyExpected");
-            testSuite.addTest(test);
-        }
-    }
-
-    /**
-     * This test verifies that the sensor's maximum advertised frequency (sampling rate) complies
-     * with the required frequency set in the CDD.
-     * This characterizes that the sensor is able to provide data at the rate the platform requires
-     * it.
-     *
-     * The test simply compares the sampling rate specified in the CDD with the maximum sampling
-     * rate advertised by the Sensor under test.
-     *
-     * The test can fail if the Sensor Hardware does not support the sampling rate required by the
-     * platform.
-     *
-     * The assertion associated with the test failure contains:
-     * - the thread id on which the failure occurred
-     * - the sensor type and sensor handle that caused the failure
-     * - the expected maximum sampling rate
-     * - the observed maximum sampling rate
-     */
-    public void testMaxFrequencyExpected() {
-        Sensor sensor = SensorCtsHelper.getSensor(this.getContext(), mSensorType);
-        int samplingRateInUs = sensor.getMinDelay();
-        String message = String.format(
-                "samplingRateInUs| expected:%d, actual:%d",
-                mExpectedSamplingRateInUs,
-                samplingRateInUs);
-        assertTrue(message, mExpectedSamplingRateInUs >= samplingRateInUs);
-    }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java b/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java
index a1aa760..50cb12d 100644
--- a/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorIntegrationTests.java
@@ -15,25 +15,20 @@
  */
 package android.hardware.cts;
 
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
 import android.content.Context;
-
 import android.hardware.Sensor;
 import android.hardware.SensorManager;
-
-import android.hardware.cts.helpers.SensorCtsHelper;
-import android.hardware.cts.helpers.SensorTestCase;
-import android.hardware.cts.helpers.SensorTestInformation;
-import android.hardware.cts.helpers.SensorTestOperation;
-
-import android.hardware.cts.helpers.sensorTestOperations.ParallelCompositeSensorTestOperation;
-import android.hardware.cts.helpers.sensorTestOperations.RepeatingSensorTestOperation;
-import android.hardware.cts.helpers.sensorTestOperations.SequentialCompositeSensorTestOperation;
-import android.hardware.cts.helpers.sensorTestOperations.VerifyEventOrderingOperation;
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.sensoroperations.ParallelSensorOperation;
+import android.hardware.cts.helpers.sensoroperations.RepeatingSensorOperation;
+import android.hardware.cts.helpers.sensoroperations.SequentialSensorOperation;
+import android.hardware.cts.helpers.sensoroperations.TestSensorOperation;
+import android.hardware.cts.helpers.sensoroperations.VerifiableSensorOperation;
+import android.hardware.cts.helpers.sensorverification.EventOrderingVerification;
 
 import java.util.Random;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Set of tests that verifies proper interaction of the sensors in the platform.
@@ -43,24 +38,7 @@
  *          -w com.android.cts.hardware/android.test.InstrumentationCtsTestRunner
  */
 public class SensorIntegrationTests extends SensorTestCase {
-    /**
-     * Builder for the test suite.
-     * This is the method that will build dynamically the set of test cases to execute.
-     * Each 'base' test case is composed by three parts:
-     * - the matrix definition
-     * - the test method that will execute the test case
-     * - a static method that will combine both and add test case instances to the test suite
-     */
-    public static Test suite() {
-        TestSuite testSuite = new TestSuite();
-
-        // add test generation routines
-        addTestToSuite(testSuite, "testSensorsWithSeveralClients");
-        addTestToSuite(testSuite, "testSensorsMovingRates");
-        createStoppingTestCases(testSuite);
-
-        return testSuite;
-    }
+    private static final String TAG = "SensorIntegrationTests";
 
     /**
      * This test focuses in the interaction of continuous and batching clients for the same Sensor
@@ -87,31 +65,40 @@
      */
     public void testSensorsWithSeveralClients() throws Throwable {
         final int ITERATIONS = 50;
-        final int BATCHING_RATE_IN_SECONDS = 5;
-        final Context context = this.getContext();
+        final int MAX_REPORTING_LATENCY_US = (int) TimeUnit.SECONDS.toMicros(5);
+        final Context context = getContext();
 
         int sensorTypes[] = {
                 Sensor.TYPE_ACCELEROMETER,
                 Sensor.TYPE_MAGNETIC_FIELD,
                 Sensor.TYPE_GYROSCOPE };
 
-        ParallelCompositeSensorTestOperation operation = new ParallelCompositeSensorTestOperation();
+        ParallelSensorOperation operation = new ParallelSensorOperation();
         for(int sensorType : sensorTypes) {
-            SensorTestOperation continuousOperation = new VerifyEventOrderingOperation(
+            TestSensorEnvironment environment = new TestSensorEnvironment(
                     context,
                     sensorType,
-                    SensorManager.SENSOR_DELAY_NORMAL,
-                    0 /* reportLatencyInUs */);
-            operation.add(new RepeatingSensorTestOperation(continuousOperation, ITERATIONS));
+                    shouldEmulateSensorUnderLoad(),
+                    SensorManager.SENSOR_DELAY_FASTEST);
+            TestSensorOperation continuousOperation =
+                    new TestSensorOperation(environment, 100 /* eventCount */);
+            continuousOperation.addVerification(new EventOrderingVerification());
+            operation.add(new RepeatingSensorOperation(continuousOperation, ITERATIONS));
 
-            SensorTestOperation batchingOperation = new VerifyEventOrderingOperation(
+            Sensor sensor = TestSensorEnvironment.getSensor(context, sensorType);
+            TestSensorEnvironment batchingEnvironment = new TestSensorEnvironment(
                     context,
                     sensorType,
-                    SensorTestInformation.getMaxSamplingRateInUs(context, sensorType),
-                    SensorCtsHelper.getSecondsAsMicroSeconds(BATCHING_RATE_IN_SECONDS));
-            operation.add(new RepeatingSensorTestOperation(batchingOperation, ITERATIONS));
+                    shouldEmulateSensorUnderLoad(),
+                    sensor.getMinDelay(),
+                    MAX_REPORTING_LATENCY_US);
+            TestSensorOperation batchingOperation =
+                    new TestSensorOperation(batchingEnvironment, 100 /* eventCount */);
+            batchingOperation.addVerification(new EventOrderingVerification());
+            operation.add(new RepeatingSensorOperation(batchingOperation, ITERATIONS));
         }
         operation.execute();
+        SensorStats.logStats(TAG, operation.getStats());
     }
 
     /**
@@ -140,22 +127,26 @@
         final int INSTANCES_TO_USE = 5;
         final int ITERATIONS_TO_EXECUTE = 100;
 
-        ParallelCompositeSensorTestOperation operation = new ParallelCompositeSensorTestOperation();
+        ParallelSensorOperation operation = new ParallelSensorOperation();
         int sensorTypes[] = {
                 Sensor.TYPE_ACCELEROMETER,
                 Sensor.TYPE_MAGNETIC_FIELD,
                 Sensor.TYPE_GYROSCOPE };
 
+        Context context = getContext();
         for(int sensorType : sensorTypes) {
             for(int instance = 0; instance < INSTANCES_TO_USE; ++instance) {
-                SequentialCompositeSensorTestOperation sequentialOperation =
-                        new SequentialCompositeSensorTestOperation();
+                SequentialSensorOperation sequentialOperation = new SequentialSensorOperation();
                 for(int iteration = 0; iteration < ITERATIONS_TO_EXECUTE; ++iteration) {
-                    VerifyEventOrderingOperation sensorOperation = new VerifyEventOrderingOperation(
-                            this.getContext(),
+                    TestSensorEnvironment environment = new TestSensorEnvironment(
+                            context,
                             sensorType,
-                            this.generateSamplingRateInUs(sensorType),
-                            this.generateReportLatencyInUs());
+                            shouldEmulateSensorUnderLoad(),
+                            generateSamplingRateInUs(sensorType),
+                            generateReportLatencyInUs());
+                    TestSensorOperation sensorOperation =
+                            new TestSensorOperation(environment, 100 /* eventCount */);
+                    sensorOperation.addVerification(new EventOrderingVerification());
                     sequentialOperation.add(sensorOperation);
                 }
                 operation.add(sequentialOperation);
@@ -163,30 +154,48 @@
         }
 
         operation.execute();
+        SensorStats.logStats(TAG, operation.getStats());
     }
 
     /**
      * Regress:
      * - b/10641388
      */
-    private int mSensorTypeTester;
-    private int mSensorTypeTestee;
 
-    private static void createStoppingTestCases(TestSuite testSuite) {
-        int sensorTypes[] = {
-                Sensor.TYPE_ACCELEROMETER,
-                Sensor.TYPE_GYROSCOPE,
-                Sensor.TYPE_MAGNETIC_FIELD};
+    public void testAccelerometerAccelerometerStopping()  throws Throwable {
+        verifySensorStoppingInteraction(Sensor.TYPE_ACCELEROMETER, Sensor.TYPE_ACCELEROMETER);
+    }
 
-        for(int sensorTypeTester : sensorTypes) {
-            for(int sensorTypeTestee : sensorTypes) {
-                SensorIntegrationTests test = new SensorIntegrationTests();
-                test.mSensorTypeTester = sensorTypeTester;
-                test.mSensorTypeTestee = sensorTypeTestee;
-                test.setName("testSensorStoppingInteraction");
-                testSuite.addTest(test);
-            }
-        }
+    public void testAccelerometerGyroscopeStopping()  throws Throwable {
+        verifySensorStoppingInteraction(Sensor.TYPE_ACCELEROMETER, Sensor.TYPE_GYROSCOPE);
+    }
+
+    public void testAccelerometerMagneticFieldStopping()  throws Throwable {
+        verifySensorStoppingInteraction(Sensor.TYPE_ACCELEROMETER, Sensor.TYPE_MAGNETIC_FIELD);
+    }
+
+    public void testGyroscopeAccelerometerStopping()  throws Throwable {
+        verifySensorStoppingInteraction(Sensor.TYPE_GYROSCOPE, Sensor.TYPE_ACCELEROMETER);
+    }
+
+    public void testGyroscopeGyroscopeStopping()  throws Throwable {
+        verifySensorStoppingInteraction(Sensor.TYPE_GYROSCOPE, Sensor.TYPE_GYROSCOPE);
+    }
+
+    public void testGyroscopeMagneticFieldStopping()  throws Throwable {
+        verifySensorStoppingInteraction(Sensor.TYPE_GYROSCOPE, Sensor.TYPE_MAGNETIC_FIELD);
+    }
+
+    public void testMagneticFieldAccelerometerStopping()  throws Throwable {
+        verifySensorStoppingInteraction(Sensor.TYPE_MAGNETIC_FIELD, Sensor.TYPE_ACCELEROMETER);
+    }
+
+    public void testMagneticFieldGyroscopeStopping()  throws Throwable {
+        verifySensorStoppingInteraction(Sensor.TYPE_MAGNETIC_FIELD, Sensor.TYPE_GYROSCOPE);
+    }
+
+    public void testMagneticFieldMagneticFieldStopping()  throws Throwable {
+        verifySensorStoppingInteraction(Sensor.TYPE_MAGNETIC_FIELD, Sensor.TYPE_MAGNETIC_FIELD);
     }
 
     /**
@@ -209,27 +218,37 @@
      * It is important to look at the internals of the Sensor HAL to identify how the interaction
      * of several clients can lead to the failing state.
      */
-    public void testSensorStoppingInteraction() throws Throwable {
-        Context context = this.getContext();
+    public void verifySensorStoppingInteraction(
+            int sensorTypeTestee,
+            int sensorTypeTester) throws Throwable {
+        Context context = getContext();
 
-        SensorTestOperation tester = new VerifyEventOrderingOperation(
+        TestSensorEnvironment testerEnvironment = new TestSensorEnvironment(
                 context,
-                mSensorTypeTester,
-                SensorManager.SENSOR_DELAY_NORMAL,
-                0 /*reportLatencyInUs*/);
-        tester.start();
+                sensorTypeTester,
+                shouldEmulateSensorUnderLoad(),
+                SensorManager.SENSOR_DELAY_FASTEST);
+        TestSensorOperation tester =
+                new TestSensorOperation(testerEnvironment, 100 /* event count */);
+        tester.addVerification(new EventOrderingVerification());
 
-        SensorTestOperation testee = new VerifyEventOrderingOperation(
+        TestSensorEnvironment testeeEnvironment = new TestSensorEnvironment(
                 context,
-                mSensorTypeTestee,
-                SensorManager.SENSOR_DELAY_UI,
-                0 /*reportLatencyInUs*/);
-        testee.start();
+                sensorTypeTestee,
+                shouldEmulateSensorUnderLoad(),
+                SensorManager.SENSOR_DELAY_FASTEST);
+        VerifiableSensorOperation testee =
+                new TestSensorOperation(testeeEnvironment, 100 /* event count */);
+        testee.addVerification(new EventOrderingVerification());
 
-        testee.waitForCompletion();
-        tester.waitForCompletion();
+        ParallelSensorOperation operation = new ParallelSensorOperation();
+        operation.add(tester, testee);
+        operation.execute();
+        SensorStats.logStats(TAG, operation.getStats());
 
+        testee = testee.clone();
         testee.execute();
+        SensorStats.logStats(TAG, testee.getStats());
     }
 
     /**
@@ -243,34 +262,16 @@
             case 0:
                 rate = SensorManager.SENSOR_DELAY_FASTEST;
                 break;
-            case 1:
-                rate = SensorManager.SENSOR_DELAY_GAME;
-                break;
-            case 2:
-                rate = SensorManager.SENSOR_DELAY_NORMAL;
-                break;
-            case 3:
-                rate = SensorManager.SENSOR_DELAY_UI;
-                break;
-            case 4:
             default:
-                int maxSamplingRate = SensorTestInformation.getMaxSamplingRateInUs(
-                        this.getContext(),
-                        sensorType);
+                Sensor sensor = TestSensorEnvironment.getSensor(getContext(), sensorType);
+                int maxSamplingRate = sensor.getMinDelay();
                 rate = maxSamplingRate * mGenerator.nextInt(10);
         }
         return rate;
     }
 
     private int generateReportLatencyInUs() {
-        int reportLatency = SensorCtsHelper.getSecondsAsMicroSeconds(
-                mGenerator.nextInt(5) + 1);
-        return reportLatency;
-    }
-
-    private static void addTestToSuite(TestSuite testSuite, String testName) {
-        SensorIntegrationTests test = new SensorIntegrationTests();
-        test.setName(testName);
-        testSuite.addTest(test);
+        long reportLatencyUs = TimeUnit.SECONDS.toMicros(mGenerator.nextInt(5) + 1);
+        return (int) reportLatencyUs;
     }
 }
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorMeasurementTests.java b/tests/tests/hardware/src/android/hardware/cts/SensorMeasurementTests.java
deleted file mode 100644
index 859b26d..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/SensorMeasurementTests.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.cts;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-import android.hardware.Sensor;
-import android.hardware.SensorManager;
-
-import android.hardware.cts.helpers.SensorTestCase;
-
-import android.hardware.cts.helpers.sensorTestOperations.VerifyMagnitudeOperation;
-import android.hardware.cts.helpers.sensorTestOperations.VerifyStandardDeviationOperation;
-
-/**
- * Verifies several properties of the sensor measurements.
- */
-public class SensorMeasurementTests extends SensorTestCase {
-    private int mSensorType;
-    private int mSamplingRateInUs;
-
-    /**
-     * Builder for the test suite.
-     * This is the method that will build dynamically the set of test cases to execute.
-     * Each 'base' test case is composed by three parts:
-     * - the matrix definition
-     * - the test method that will execute the test case
-     * - a static method that will combine both and add test case instances to the test suite
-     */
-    public static Test suite() {
-        TestSuite testSuite = new TestSuite();
-
-        // add test generation routines
-        createEventNormTestCases(testSuite);
-        createStandardDeviationTestCases(testSuite);
-
-        return testSuite;
-    }
-
-    /**
-     * SensorEvent Norm test cases.
-     *
-     * Regress:
-     * - b/9503957
-     * - b/9611609
-     */
-    private float mReferenceValue;
-    private float mThreshold;
-
-    private static void createEventNormTestCases(TestSuite testSuite) {
-        Object testDefinitionMatrix[][] = {
-                // { SensorType, SamplingRateInUs, ReferenceValue, Threshold },
-                { Sensor.TYPE_ACCELEROMETER,
-                        SensorManager.SENSOR_DELAY_FASTEST,
-                        SensorManager.STANDARD_GRAVITY,
-                        1.5f /* m / s^2 */},
-                { Sensor.TYPE_GYROSCOPE, SensorManager.SENSOR_DELAY_FASTEST, 0.0f, 2.5f /* dps */ },
-        };
-
-        for(Object definition[] : testDefinitionMatrix)  {
-            SensorMeasurementTests test = new SensorMeasurementTests();
-            test.mSensorType = (Integer)definition[0];
-            test.mSamplingRateInUs = (Integer)definition[1];
-            test.mReferenceValue = (Float)definition[2];
-            test.mThreshold = (Float)definition[3];
-            test.setName("testEventNorm");
-            testSuite.addTest(test);
-        }
-    }
-
-    /**
-     * This test verifies that the Norm of the sensor data is close to the expected reference value.
-     * The units of the reference value are dependent on the type of sensor.
-     * This test is used to verify that the data reported by the sensor is close to the expected
-     * range and scale.
-     *
-     * The test takes a sample from the sensor under test and calculates the Euclidean Norm of the
-     * vector represented by the sampled data. It then compares it against the test expectations
-     * that are represented by a reference value and a threshold.
-     *
-     * The test is susceptible to errors when the Sensor under test is uncalibrated, or the units in
-     * which the data are reported and the expectations are set are different.
-     *
-     * The assertion associated with the test provides the required data needed to identify any
-     * possible issue. It provides:
-     * - the thread id on which the failure occurred
-     * - the sensor type and sensor handle that caused the failure
-     * - the values representing the expectation of the test
-     * - the values sampled from the sensor
-     */
-    public void testEventNorm() throws Throwable {
-        VerifyMagnitudeOperation operation = new VerifyMagnitudeOperation(
-                this.getContext(),
-                mSensorType,
-                mSamplingRateInUs,
-                mReferenceValue,
-                mThreshold);
-        operation.execute();
-    }
-
-    /**
-     * SensorEvent Standard Deviation test cases.
-     */
-    private int mReportLatencyInUs;
-    private float mExpectedStandardDeviation;
-
-    private static void createStandardDeviationTestCases(TestSuite testSuite) {
-        Object testDefinitionMatrix[][] = {
-                // { SensorType, SamplingRateInUs, ReportLatencyInUs, ExpectedStandardDeviation },
-                { Sensor.TYPE_ACCELEROMETER, SensorManager.SENSOR_DELAY_FASTEST, 0, 1f /* m/s^2 */ },
-                { Sensor.TYPE_GYROSCOPE, SensorManager.SENSOR_DELAY_FASTEST, 0, 0.5f /* dps */ },
-        };
-
-        for(Object definition[] : testDefinitionMatrix) {
-            SensorMeasurementTests test = new SensorMeasurementTests();
-            test.mSensorType = (Integer)definition[0];
-            test.mSamplingRateInUs = (Integer)definition[1];
-            test.mReportLatencyInUs = (Integer)definition[2];
-            test.mExpectedStandardDeviation = (Float)definition[3];
-            test.setName("testStandardDeviation");
-            testSuite.addTest(test);
-        }
-    }
-
-    /**
-     * This test verifies that the standard deviation of a set of sampled data from a particular
-     * sensor falls into the expectations defined in the CDD. The verification applies to each axis
-     * of the sampled data reported by the Sensor under test.
-     * This test is used to validate the requirement imposed by the CDD to Sensors in Android. And
-     * characterizes how the Sensor behaves while static.
-     *
-     * The test takes a set of samples from the sensor under test, and calculates the Standard
-     * Deviation for each of the axes the Sensor reports data for. The StdDev is compared against
-     * the expected value documented in the CDD.
-     *
-     * The test is susceptible to errors if the device is moving while the test is running, or if
-     * the Sensor's sampled data indeed falls into a large StdDev.
-     *
-     * The assertion associated with the test provides the required data to identify any possible
-     * issue. It provides:
-     * - the thread id on which the failure occurred
-     * - the sensor type and sensor handle that caused the failure
-     * - the expectation of the test
-     * - the std dev calculated and the axis it applies to
-     * Additionally, the device's debug output (adb logcat) dumps the set of values associated with
-     * the failure to help track down the issue.
-     */
-    public void testStandardDeviation() throws Throwable {
-        VerifyStandardDeviationOperation operation = new VerifyStandardDeviationOperation(
-                this.getContext(),
-                mSensorType,
-                mSamplingRateInUs,
-                mReportLatencyInUs,
-                mExpectedStandardDeviation);
-        operation.execute();
-    }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorTest.java b/tests/tests/hardware/src/android/hardware/cts/SensorTest.java
index b1691c3..d8b8e51 100644
--- a/tests/tests/hardware/src/android/hardware/cts/SensorTest.java
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorTest.java
@@ -16,12 +16,7 @@
 
 package android.hardware.cts;
 
-import java.lang.IllegalArgumentException;
-import java.lang.Override;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
+import com.android.cts.util.TimeoutReq;
 
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -35,19 +30,23 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.PowerManager;
-import android.test.AndroidTestCase;
+import android.os.SystemClock;
 import android.util.Log;
 
-public class SensorTest extends AndroidTestCase {
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class SensorTest extends SensorTestCase {
     private SensorManager mSensorManager;
     private TriggerListener mTriggerListener;
     private SensorListener mSensorListener;
     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_S = 40;
-
+    private static final int MAX_OFFICIAL_ANDROID_SENSOR_TYPE = 100;
+    private static final long TIMEOUT_TOLERANCE_US = TimeUnit.SECONDS.toMicros(5);
+    private static final double MIN_SAMPLING_FREQUENCY_MULTIPLIER_TOLERANCE = 0.9;
     private PowerManager.WakeLock mWakeLock;
 
     @Override
@@ -137,10 +136,71 @@
     }
 
     public void testValuesForAllSensors() {
-        for (int i = Sensor.TYPE_ACCELEROMETER; i <= Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR; ++i) {
-            Sensor sensor = mSensorManager.getDefaultSensor(i);
-            if (sensor != null) {
-                assertSensorValues(sensor);
+        for (Sensor sensor : mSensorList) {
+            assertSensorValues(sensor);
+        }
+    }
+
+    private void hasOnlyOneWakeUpSensorOrEmpty(List<Sensor> sensors) {
+        if (sensors == null || sensors.isEmpty()) return;
+        if (sensors.size() > 1) {
+            fail("More than one " + sensors.get(0).getName() + " defined.");
+            return;
+        }
+        assertTrue(sensors.get(0).getName() + " defined as non-wake-up sensor",
+                sensors.get(0).isWakeUpSensor());
+        return;
+    }
+
+    // Some sensors like proximity, significant motion etc. are defined as wake-up sensors by
+    // default. Check if the wake-up flag is set correctly.
+    public void testWakeUpFlags() {
+        final int TYPE_WAKE_GESTURE = 23;
+        final int TYPE_GLANCE_GESTURE = 24;
+        final int TYPE_PICK_UP_GESTURE = 25;
+
+        hasOnlyOneWakeUpSensorOrEmpty(mSensorManager.getSensorList(Sensor.TYPE_SIGNIFICANT_MOTION));
+        hasOnlyOneWakeUpSensorOrEmpty(mSensorManager.getSensorList(TYPE_WAKE_GESTURE));
+        hasOnlyOneWakeUpSensorOrEmpty(mSensorManager.getSensorList(TYPE_GLANCE_GESTURE));
+        hasOnlyOneWakeUpSensorOrEmpty(mSensorManager.getSensorList(TYPE_PICK_UP_GESTURE));
+
+        List<Sensor> proximity_sensors = mSensorManager.getSensorList(Sensor.TYPE_PROXIMITY);
+        if (proximity_sensors.isEmpty()) return;
+        boolean hasWakeUpProximitySensor = false;
+        for (Sensor sensor : proximity_sensors) {
+            if (sensor.isWakeUpSensor()) {
+                hasWakeUpProximitySensor = true;
+                break;
+            }
+        }
+        assertTrue("No wake-up proximity sensors implemented", hasWakeUpProximitySensor);
+    }
+
+    public void testGetDefaultSensorWithWakeUpFlag() {
+        // With wake-up flags set to false, the sensor returned should be a non wake-up sensor.
+        for (Sensor sensor : mSensorList) {
+            Sensor curr_sensor = mSensorManager.getDefaultSensor(sensor.getType(), false);
+            if (curr_sensor != null) {
+                assertFalse("getDefaultSensor wakeup=false returns a wake-up sensor" +
+                        curr_sensor.getName(),
+                        curr_sensor.isWakeUpSensor());
+            }
+
+            curr_sensor = mSensorManager.getDefaultSensor(sensor.getType(), true);
+            if (curr_sensor != null) {
+                assertTrue("getDefaultSensor wake-up returns non wake sensor" +
+                        curr_sensor.getName(),
+                        curr_sensor.isWakeUpSensor());
+            }
+        }
+    }
+
+    public void testSensorStringTypes() {
+        for (Sensor sensor : mSensorList) {
+            if (sensor.getType() < MAX_OFFICIAL_ANDROID_SENSOR_TYPE &&
+                    !sensor.getStringType().startsWith("android.sensor.")) {
+                fail("StringType not set correctly for android defined sensor " +
+                        sensor.getName() + " " + sensor.getStringType());
             }
         }
     }
@@ -186,17 +246,147 @@
         }
     }
 
-    // Register for updates from each continuous mode sensor, wait for 25 events, call flush and
+    class SensorEventTimeStampListener implements SensorEventListener {
+        SensorEventTimeStampListener(long eventReportLatencyNs, CountDownLatch latch) {
+            mEventReportLatencyNs = eventReportLatencyNs;
+            mPrevTimeStampNs = -1;
+            mLatch = latch;
+            numErrors = 0;
+        }
+
+        @Override
+        public void onSensorChanged(SensorEvent event) {
+            if (mPrevTimeStampNs == -1) {
+                mPrevTimeStampNs = event.timestamp;
+                return;
+            }
+            long currTimeStampNs = event.timestamp;
+            if (currTimeStampNs <= mPrevTimeStampNs) {
+                Log.w(TAG, "Timestamps not monotonically increasing curr_ts_ns=" +
+                        event.timestamp + " prev_ts_ns=" + mPrevTimeStampNs);
+                numErrors++;
+                mPrevTimeStampNs = currTimeStampNs;
+                return;
+            }
+            mLatch.countDown();
+
+            final long elapsedRealtimeNs = SystemClock.elapsedRealtimeNanos();
+
+            if (elapsedRealtimeNs <= currTimeStampNs) {
+                Log.w(TAG, "Timestamps into the future curr elapsedRealTimeNs=" + elapsedRealtimeNs
+                         + " current sensor ts_ns=" + currTimeStampNs);
+                ++numErrors;
+            } else if (elapsedRealtimeNs-currTimeStampNs > SYNC_TOLERANCE + mEventReportLatencyNs) {
+                Log.w(TAG, "Timestamp sync error elapsedRealTimeNs=" + elapsedRealtimeNs +
+                        " curr_ts_ns=" + currTimeStampNs +
+                        " diff_ns=" + (elapsedRealtimeNs - currTimeStampNs) +
+                        " SYNC_TOLERANCE_NS=" + SYNC_TOLERANCE +
+                        " eventReportLatencyNs=" + mEventReportLatencyNs);
+                ++numErrors;
+            }
+            mPrevTimeStampNs = currTimeStampNs;
+        }
+
+        public int getNumErrors() {
+            return numErrors;
+        }
+
+        @Override
+        public void onAccuracyChanged(Sensor sensor, int accuracy) {
+        }
+
+        private int numErrors;
+        private long mEventReportLatencyNs;
+        private long mPrevTimeStampNs;
+        private final CountDownLatch mLatch;
+        private final long SYNC_TOLERANCE = 500000000L; // 500 milli seconds approx.
+    }
+
+    // Register for each sensor and compare the timestamps of SensorEvents that you get with
+    // elapsedRealTimeNano.
+    @TimeoutReq(minutes=60)
+    public void testSensorTimeStamps() throws Exception {
+        final int numEvents = 2000;
+        try {
+            mWakeLock.acquire();
+            int numErrors = 0;
+            for (Sensor sensor : mSensorList) {
+                // Skip OEM defined sensors and non continuous sensors.
+                if (sensor.getReportingMode() != Sensor.REPORTING_MODE_CONTINUOUS) {
+                    continue;
+                }
+
+                for (int iterations = 0; iterations < 2; ++iterations) {
+                    // Test in both batch mode and non-batch mode for every sensor.
+                    long maxBatchReportLatencyNs = 10000000000L; // 10 secs
+                    if (iterations % 2 == 0) maxBatchReportLatencyNs = 0;
+
+                    final long samplingPeriodNs = (long)(TimeUnit.MICROSECONDS.toNanos(
+                            sensor.getMinDelay())/MIN_SAMPLING_FREQUENCY_MULTIPLIER_TOLERANCE);
+                    // If there is a FIFO and a wake-lock is held, events will be reported when
+                    // the batch timeout expires or when the FIFO is full which ever occurs
+                    // earlier.
+                    final long eventReportLatencyNs = Math.min(maxBatchReportLatencyNs,
+                            sensor.getFifoMaxEventCount() * samplingPeriodNs);
+
+                    final CountDownLatch eventsRemaining = new CountDownLatch(numEvents);
+                    SensorEventTimeStampListener listener = new SensorEventTimeStampListener(
+                            eventReportLatencyNs, eventsRemaining);
+
+                    Log.i(TAG, "Running timeStamp test on " + sensor.getName());
+                    boolean result = mSensorManager.registerListener(listener, sensor,
+                            SensorManager.SENSOR_DELAY_FASTEST,
+                            (int)maxBatchReportLatencyNs/1000);
+                    assertTrue("Sensor registerListener failed ", result);
+
+                    long timeToWaitUs = samplingPeriodNs/1000 + eventReportLatencyNs/1000 +
+                            TIMEOUT_TOLERANCE_US;
+                    long totalTimeWaitedUs = waitToCollectAllEvents(timeToWaitUs,
+                            (int)(eventReportLatencyNs/1000), eventsRemaining);
+
+                    mSensorManager.unregisterListener(listener);
+                    if (eventsRemaining.getCount() > 0) {
+                        failTimedOut(sensor.getName(), (double) totalTimeWaitedUs/1000,
+                                numEvents, (double) sensor.getMinDelay()/1000,
+                                eventsRemaining.getCount(),
+                                numEvents - eventsRemaining.getCount());
+                    }
+                    if (listener.getNumErrors() > 5) {
+                        fail("Check logcat. Timestamp test failed. numErrors=" +
+                                listener.getNumErrors() + " " + sensor.getName() +
+                                " maxBatchReportLatencyNs=" + maxBatchReportLatencyNs +
+                                " samplingPeriodNs=" + sensor.getMinDelay());
+                        numErrors += listener.getNumErrors();
+                    } else {
+                        Log.i(TAG, "TimeStamp test PASS'd on " + sensor.getName());
+                    }
+                }
+            }
+        } finally {
+            mWakeLock.release();
+        }
+    }
+
+    private void failTimedOut(String sensorName, double totalTimeWaitedMs, int numEvents,
+            double minDelayMs, long eventsRemaining, long eventsReceived) {
+        final String TIMED_OUT_FORMAT = "Timed out waiting for events from %s " +
+                "waited for time=%.1fms to receive totalEvents=%d at samplingRate=%.1fHz" +
+                " remainingEvents=%d  received events=%d";
+        fail(String.format(TIMED_OUT_FORMAT, sensorName, totalTimeWaitedMs, numEvents,
+                1000/minDelayMs, eventsRemaining, eventsReceived));
+    }
+
+    // Register for updates from each continuous mode sensor, wait for N events, call flush and
     // wait for flushCompleteEvent before unregistering for the sensor.
+    @TimeoutReq(minutes=20)
     public void testBatchAndFlush() throws Exception {
         try {
             mWakeLock.acquire();
             for (Sensor sensor : mSensorList) {
-                // Skip OEM defined sensors and trigger sensors.
-                if (sensor.getType() > MAX_SENSOR_TYPE || sensor.getMinDelay() < 0) {
-                    continue;
+                // Skip ONLY one-shot sensors.
+                if (sensor.getReportingMode() != Sensor.REPORTING_MODE_ONE_SHOT) {
+                    registerListenerCallFlush(sensor, null);
                 }
-                registerListenerCallFlush(sensor, null);
             }
         } finally {
             mWakeLock.release();
@@ -205,6 +395,7 @@
 
     // Same as testBatchAndFlush but using Handler version of the API to register for sensors.
     // onSensorChanged is now called on a background thread.
+    @TimeoutReq(minutes=10)
     public void testBatchAndFlushWithHandler() throws Exception {
         try {
             mWakeLock.acquire();
@@ -212,11 +403,10 @@
             handlerThread.start();
             Handler handler = new Handler(handlerThread.getLooper());
             for (Sensor sensor : mSensorList) {
-                // Skip OEM defined sensors and trigger sensors.
-                if (sensor.getType() > MAX_SENSOR_TYPE || sensor.getMinDelay() < 0) {
-                    continue;
+                // Skip ONLY one-shot sensors.
+                if (sensor.getReportingMode() != Sensor.REPORTING_MODE_ONE_SHOT) {
+                    registerListenerCallFlush(sensor, handler);
                 }
-                registerListenerCallFlush(sensor, handler);
             }
         }  finally {
             mWakeLock.release();
@@ -225,12 +415,18 @@
 
     private void registerListenerCallFlush(Sensor sensor, Handler handler)
             throws InterruptedException {
-        final CountDownLatch eventReceived = new CountDownLatch(25);
+        if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
+            return;
+        }
+        final int numEvents = 500;
+        final int rateUs = 0; // DELAY_FASTEST
+        final int maxBatchReportLatencyUs = 10000000;
+        final CountDownLatch eventsRemaining = new CountDownLatch(numEvents);
         final CountDownLatch flushReceived = new CountDownLatch(1);
         SensorEventListener2 listener = new SensorEventListener2() {
             @Override
             public void onSensorChanged(SensorEvent event) {
-                eventReceived.countDown();
+                eventsRemaining.countDown();
             }
 
             @Override
@@ -244,30 +440,63 @@
         };
         // Consider only continuous mode sensors for testing registerListener.
         // For on-change sensors, call registerListener() so that the listener is associated
-        // with the sensor and flush(listener) can be called on it.
-        if (sensor.getMinDelay() >= 0) {
+        // with the sensor so that flush(listener) can be called on it.
+        try {
             Log.i(TAG, "testBatch " + sensor.getName());
             boolean result = mSensorManager.registerListener(listener, sensor,
-                    SensorManager.SENSOR_DELAY_NORMAL, 10000000, handler);
+                    rateUs, maxBatchReportLatencyUs, 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_S, TimeUnit.SECONDS);
-                if (!countZero) {
-                    fail("Timed out waiting for events from " + sensor.getName());
+
+            // Wait for 500 events or N seconds before the test times out.
+            if (sensor.getReportingMode() == Sensor.REPORTING_MODE_CONTINUOUS) {
+                // Wait for approximately the time required to generate these events + a tolerance
+                // of 10 seconds.
+                long timeToWaitUs =
+                  numEvents*(long)(sensor.getMinDelay()/MIN_SAMPLING_FREQUENCY_MULTIPLIER_TOLERANCE)
+                        + maxBatchReportLatencyUs + TIMEOUT_TOLERANCE_US;
+
+                long totalTimeWaitedUs = waitToCollectAllEvents(timeToWaitUs,
+                        maxBatchReportLatencyUs, eventsRemaining);
+                if (eventsRemaining.getCount() > 0) {
+                    failTimedOut(sensor.getName(), (double)totalTimeWaitedUs/1000, numEvents,
+                            (double)sensor.getMinDelay()/1000,
+                            eventsRemaining.getCount(), numEvents - eventsRemaining.getCount());
                 }
             }
+            Log.i(TAG, "testFlush " + sensor.getName());
+            result = mSensorManager.flush(listener);
+            assertTrue("flush failed " + sensor.getName(), result);
+            boolean collectedAllEvents = flushReceived.await(TIMEOUT_TOLERANCE_US,
+                    TimeUnit.MICROSECONDS);
+            if (!collectedAllEvents) {
+                fail("Timed out waiting for flushCompleteEvent from " + sensor.getName() +
+                        " waitedFor="+ TIMEOUT_TOLERANCE_US/1000 + "ms");
+            }
+            Log.i(TAG, "testBatchAndFlush PASS " + sensor.getName());
+        } finally {
+            mSensorManager.unregisterListener(listener);
         }
+    }
 
-        Log.i(TAG, "testFlush " + sensor.getName());
-        boolean result = mSensorManager.flush(listener);
-        assertTrue("flush failed " + sensor.getName(), result);
-        boolean countZero = flushReceived.await(TIMEOUT_S, TimeUnit.SECONDS);
-        if (!countZero) {
-            fail("Timed out waiting for flushCompleteEvent from " + sensor.getName());
-        }
-        mSensorManager.unregisterListener(listener);
-        Log.i(TAG, "testBatchAndFlush pass " + sensor.getName());
+    // Wait till the CountDownLatch counts down to zero. If the events are not delivered within
+    // timetoWaitUs, wait an additional maxReportLantencyUs and check if the sensor is streaming
+    // data or not. If the sensor is not streaming at all, fail the test or else wait in increments
+    // of maxReportLantencyUs to collect sensor events.
+    private long waitToCollectAllEvents(long timeToWaitUs, int maxReportLatencyUs,
+            CountDownLatch eventsRemaining)
+            throws InterruptedException {
+        boolean collectedAllEvents = false;
+        long totalTimeWaitedUs = 0;
+        long remainingEvents;
+        final long INCREMENTAL_WAIT_US = maxReportLatencyUs + TimeUnit.SECONDS.toMicros(1);
+        do {
+            totalTimeWaitedUs += timeToWaitUs;
+            remainingEvents = eventsRemaining.getCount();
+            collectedAllEvents = eventsRemaining.await(timeToWaitUs, TimeUnit.MICROSECONDS);
+            timeToWaitUs = INCREMENTAL_WAIT_US;
+        } while (!collectedAllEvents &&
+                (remainingEvents - eventsRemaining.getCount() >=(long)INCREMENTAL_WAIT_US/1000000));
+        return totalTimeWaitedUs;
     }
 
     // Call registerListener for multiple sensors at a time and call flush.
@@ -277,12 +506,15 @@
         if (numSensors == 0) {
             return;
         }
-        final CountDownLatch eventReceived = new CountDownLatch(numSensors * 50);
+        final int numEvents = 500;
+        int rateUs = 0; // DELAY_FASTEST
+        final int maxBatchReportLatencyUs = 10000000;
+        final CountDownLatch eventsRemaining = new CountDownLatch(numSensors * numEvents);
         final CountDownLatch flushReceived = new CountDownLatch(numSensors);
         SensorEventListener2 listener = new SensorEventListener2() {
             @Override
             public void onSensorChanged(SensorEvent event) {
-                eventReceived.countDown();
+                eventsRemaining.countDown();
             }
 
             @Override
@@ -300,11 +532,12 @@
             StringBuilder registeredSensors = new StringBuilder(30);
             for (Sensor sensor : mSensorList) {
                 // Skip all non-continuous sensors.
-                if (sensor.getMinDelay() <= 0 || sensor.getType() > MAX_SENSOR_TYPE) {
+                if (sensor.getReportingMode() != Sensor.REPORTING_MODE_CONTINUOUS) {
                     continue;
                 }
+                rateUs = Math.max(sensor.getMinDelay(), rateUs);
                 boolean result = mSensorManager.registerListener(listener, sensor,
-                        SensorManager.SENSOR_DELAY_GAME, 10000000);
+                        SensorManager.SENSOR_DELAY_FASTEST, maxBatchReportLatencyUs);
                 assertTrue("registerListener failed for " + sensor.getName(), result);
                 registeredSensors.append(sensor.getName());
                 registeredSensors.append(" ");
@@ -317,33 +550,52 @@
             }
 
             Log.i(TAG, "testBatchAndFlushWithMutipleSensors " + registeredSensors);
-            // Wait for numSensors * 50 events or 40 seconds.
-            boolean countZero = eventReceived.await(TIMEOUT_S, TimeUnit.SECONDS);
-            if (!countZero) {
-                fail("Timed out waiting for events from " + registeredSensors.toString());
+            long timeToWaitUs =
+                    numEvents*(long)(rateUs/MIN_SAMPLING_FREQUENCY_MULTIPLIER_TOLERANCE) +
+                    maxBatchReportLatencyUs + TIMEOUT_TOLERANCE_US;
+            long totalTimeWaitedUs = waitToCollectAllEvents(timeToWaitUs, maxBatchReportLatencyUs,
+                    eventsRemaining);
+            if (eventsRemaining.getCount() > 0) {
+                failTimedOut(registeredSensors.toString(), (double)totalTimeWaitedUs/1000,
+                        numEvents, (double)rateUs/1000, eventsRemaining.getCount(),
+                        numEvents - eventsRemaining.getCount());
             }
             boolean result = mSensorManager.flush(listener);
             assertTrue("flush failed " + registeredSensors.toString(), result);
-            countZero = flushReceived.await(TIMEOUT_S, TimeUnit.SECONDS);
-            if (!countZero) {
+            boolean collectedFlushEvent =
+                    flushReceived.await(TIMEOUT_TOLERANCE_US, TimeUnit.MICROSECONDS);
+            if (!collectedFlushEvent) {
                 fail("Timed out waiting for flushCompleteEvent from " +
-                      registeredSensors.toString());
+                      registeredSensors.toString() + " waited for=" + timeToWaitUs/1000 + "ms");
             }
-            mSensorManager.unregisterListener(listener);
-            Log.i(TAG, "testBatchAndFlushWithMutipleSensors passed");
+            Log.i(TAG, "testBatchAndFlushWithMutipleSensors PASS'd");
         } finally {
+            mSensorManager.unregisterListener(listener);
             mWakeLock.release();
         }
     }
 
     private void assertSensorValues(Sensor sensor) {
-        assertTrue(sensor.getMaximumRange() >= 0);
-        assertTrue(sensor.getPower() >= 0);
-        assertTrue(sensor.getResolution() >= 0);
-        assertNotNull(sensor.getVendor());
-        assertTrue(sensor.getVersion() > 0);
-        assertTrue(sensor.getFifoMaxEventCount() >= 0);
-        assertTrue(sensor.getFifoReservedEventCount() >= 0);
+        assertTrue("Max range must be positive. Range=" + sensor.getMaximumRange()
+                + " " + sensor.getName(), sensor.getMaximumRange() >= 0);
+        assertTrue("Max power must be positive. Power=" + sensor.getPower() + " " +
+                sensor.getName(), sensor.getPower() >= 0);
+        assertTrue("Max resolution must be positive. Resolution=" + sensor.getResolution() +
+                " " + sensor.getName(), sensor.getResolution() >= 0);
+        assertNotNull("Vendor name must not be null " + sensor.getName(), sensor.getVendor());
+        assertTrue("Version must be positive version="  + sensor.getVersion() + " " +
+                    sensor.getName(), sensor.getVersion() > 0);
+        int fifoMaxEventCount = sensor.getFifoMaxEventCount();
+        int fifoReservedEventCount = sensor.getFifoReservedEventCount();
+        assertTrue(fifoMaxEventCount >= 0);
+        assertTrue(fifoReservedEventCount >= 0);
+        assertTrue(fifoReservedEventCount <= fifoMaxEventCount);
+        if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
+            assertTrue("One shot sensors should have zero FIFO Size " + sensor.getName(),
+                    sensor.getFifoMaxEventCount() == 0);
+            assertTrue("One shot sensors should have zero FIFO Size "  + sensor.getName(),
+                    sensor.getFifoReservedEventCount() == 0);
+        }
     }
 
     @SuppressWarnings("deprecation")
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorTestCase.java b/tests/tests/hardware/src/android/hardware/cts/SensorTestCase.java
new file mode 100644
index 0000000..6454678
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorTestCase.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts;
+
+import com.android.cts.util.ReportLog;
+import com.android.cts.util.ResultType;
+import com.android.cts.util.ResultUnit;
+
+import android.app.Instrumentation;
+import android.cts.util.DeviceReportLog;
+import android.hardware.Sensor;
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.SensorTestStateNotSupportedException;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.sensoroperations.ISensorOperation;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+/**
+ * Test Case class that handles gracefully sensors that are not available in the device.
+ */
+public abstract class SensorTestCase extends AndroidTestCase {
+    // TODO: consolidate all log tags
+    protected final String LOG_TAG = "TestRunner";
+
+    /**
+     * By default tests need to run in a {@link TestSensorEnvironment} that assumes each sensor is
+     * running with a load of several listeners, requesting data at different rates.
+     *
+     * In a better world the component acting as builder of {@link ISensorOperation} would compute
+     * this value based on the tests composed.
+     *
+     * Ideally, each {@link Sensor} object would expose this information to clients.
+     */
+    private volatile boolean mEmulateSensorUnderLoad = true;
+
+    protected SensorTestCase() {}
+
+    @Override
+    public void runTest() throws Throwable {
+        try {
+            super.runTest();
+        } catch (SensorTestStateNotSupportedException e) {
+            // the sensor state is not supported in the device, log a warning and skip the test
+            Log.w(LOG_TAG, e.getMessage());
+        }
+    }
+
+    public void setEmulateSensorUnderLoad(boolean value) {
+        mEmulateSensorUnderLoad = value;
+    }
+
+    protected boolean shouldEmulateSensorUnderLoad() {
+        return mEmulateSensorUnderLoad;
+    }
+
+    /**
+     * Utility method to log selected stats to a {@link ReportLog} object.  The stats must be
+     * a number or an array of numbers.
+     */
+    public static void logSelectedStatsToReportLog(Instrumentation instrumentation, int depth,
+            String[] keys, SensorStats stats) {
+        DeviceReportLog reportLog = new DeviceReportLog(depth);
+
+        for (String key : keys) {
+            Object value = stats.getValue(key);
+            if (value instanceof Integer) {
+                reportLog.printValue(key, (Integer) value, ResultType.NEUTRAL, ResultUnit.NONE);
+            } else if (value instanceof Double) {
+                reportLog.printValue(key, (Double) value, ResultType.NEUTRAL, ResultUnit.NONE);
+            } else if (value instanceof Float) {
+                reportLog.printValue(key, (Float) value, ResultType.NEUTRAL, ResultUnit.NONE);
+            } else if (value instanceof double[]) {
+                reportLog.printArray(key, (double[]) value, ResultType.NEUTRAL, ResultUnit.NONE);
+            } else if (value instanceof float[]) {
+                float[] tmpFloat = (float[]) value;
+                double[] tmpDouble = new double[tmpFloat.length];
+                for (int i = 0; i < tmpDouble.length; i++) tmpDouble[i] = tmpFloat[i];
+                reportLog.printArray(key, tmpDouble, ResultType.NEUTRAL, ResultUnit.NONE);
+            }
+        }
+
+        reportLog.printSummary("summary", 0, ResultType.NEUTRAL, ResultUnit.NONE);
+        reportLog.deliverReportToHost(instrumentation);
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/SingleSensorTests.java b/tests/tests/hardware/src/android/hardware/cts/SingleSensorTests.java
new file mode 100644
index 0000000..3bd4a03
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/SingleSensorTests.java
@@ -0,0 +1,565 @@
+/*
+ * 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.cts;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.sensoroperations.TestSensorOperation;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Set of tests to verify that sensors operate correctly when operating alone.
+ * <p>
+ * To execute these test cases, the following command can be used:
+ * </p><pre>
+ * adb shell am instrument -e class android.hardware.cts.SingleSensorTests \
+ *     -w com.android.cts.hardware/android.test.AndroidJUnitRunner
+ * </pre><p>
+ * For each sensor that reports continuously, it takes a set of samples. The test suite verifies
+ * that the event ordering, frequency, and jitter pass for the collected sensor events. It
+ * additionally tests that the mean, standard deviation, and magnitude are correct for the sensor
+ * event values, where applicable for a device in a static environment.
+ * </p><p>
+ * The event ordering test verifies the ordering of the sampled data reported by the Sensor under
+ * test. This test is used to guarantee that sensor data is reported in the order it occurs, and
+ * that events are always reported in order. It verifies that each event's timestamp is in the
+ * future compared with the previous event. At the end of the validation, the full set of events is
+ * verified to be ordered by timestamp as they are generated. The test can be susceptible to errors
+ * if the sensor sampled data is not timestamped at the hardware level. Or events sampled at high
+ * rates are added to the FIFO without controlling the appropriate ordering of the events.
+ * </p><p>
+ * The frequency test verifies that the sensor under test can sample and report data at the maximum
+ * frequency (sampling rate) it advertises. The frequency between events is calculated by looking at
+ * the delta between the timestamps associated with each event to get the period. The test is
+ * susceptible to errors if the sensor is not capable to sample data at the maximum rate it
+ * supports, or the sensor events are not timestamped at the hardware level.
+ * </p><p>
+ * The jitter test verifies that the event jittering associated with the sampled data reported by
+ * the sensor under test aligns with the requirements imposed in the CDD. This test characterizes
+ * how the sensor behaves while sampling data at a specific rate. It compares the 95th percentile of
+ * the jittering with a certain percentage of the minimum period. The test is susceptible to errors
+ * if the sensor events are not timestamped at the hardware level.
+ * </p><p>
+ * The mean test verifies that the mean of a set of sampled data from a particular sensor falls into
+ * the expectations defined in the CDD. The verification applies to each axis of the sampled data
+ * reported by the sensor under test. This test is used to validate the requirement imposed by the
+ * CDD to Sensors in Android and characterizes how the Sensor behaves while static. The test is
+ * susceptible to errors if the device is moving while the test is running, or if the sensor's
+ * sampled data indeed varies from the expected mean.
+ * </p><p>
+ * The magnitude test verifies that the magnitude of the sensor data is close to the expected
+ * reference value. The units of the reference value are dependent on the type of sensor.
+ * This test is used to verify that the data reported by the sensor is close to the expected
+ * range and scale. The test calculates the Euclidean norm of the vector represented by the sampled
+ * data and compares it against the test expectations. The test is susceptible to errors when the
+ * sensor under test is uncalibrated, or the units between the data and expectations are different.
+ * </p><p>
+ * The standard deviation test verifies that the standard deviation of a set of sampled data from a
+ * particular sensor falls into the expectations defined in the CDD. The verification applies to
+ * each axis of the sampled data reported by the sensor under test. This test is used to validate
+ * the requirement imposed by the CDD to Sensors in Android and characterizes how the Sensor behaves
+ * while static. The test is susceptible to errors if the device is moving while the test is
+ * running, or if the sensor's sampled data indeed falls into a large standard deviation.
+ * </p>
+ */
+public class SingleSensorTests extends SensorTestCase {
+    private static final String TAG = "SingleSensorTests";
+
+    private static final int RATE_200HZ = 5000;
+    private static final int RATE_100HZ = 10000;
+    private static final int RATE_50HZ = 20000;
+    private static final int RATE_25HZ = 40000;
+    private static final int RATE_15HZ = 66667;
+    private static final int RATE_10HZ = 100000;
+    private static final int RATE_5HZ = 200000;
+    private static final int RATE_1HZ = 1000000;
+
+    /**
+     * This test verifies that the sensor's properties complies with the required properties set in
+     * the CDD.
+     * <p>
+     * It checks that the sampling rate advertised by the sensor under test matches that which is
+     * required by the CDD.
+     * </p>
+     */
+    public void testSensorProperties() {
+        // sensor type: [getMinDelay()]
+        Map<Integer, Object[]> expectedProperties = new HashMap<Integer, Object[]>(3);
+        expectedProperties.put(Sensor.TYPE_ACCELEROMETER, new Object[]{10000});
+        expectedProperties.put(Sensor.TYPE_GYROSCOPE, new Object[]{10000});
+        expectedProperties.put(Sensor.TYPE_MAGNETIC_FIELD, new Object[]{100000});
+
+        SensorManager sensorManager =
+                (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
+        assertNotNull("SensorManager not present in the system.", sensorManager);
+        for (Entry<Integer, Object[]> entry : expectedProperties.entrySet()) {
+            Sensor sensor = sensorManager.getDefaultSensor(entry.getKey());
+            if (sensor != null) {
+                if (entry.getValue()[0] != null) {
+                    int expected = (Integer) entry.getValue()[0];
+                    String msg = String.format(
+                            "%s: min delay %dus expected to be less than or equal to %dus",
+                            sensor.getName(),
+                            sensor.getMinDelay(),
+                            expected);
+                    assertTrue(msg, sensor.getMinDelay() <= expected);
+                }
+            }
+        }
+    }
+
+    // TODO: Figure out if a better way to enumerate test cases programmatically exists that works
+    // with CTS framework.
+    public void testAccelerometer_fastest() throws Throwable {
+        runSensorTest(Sensor.TYPE_ACCELEROMETER, SensorManager.SENSOR_DELAY_FASTEST);
+    }
+
+    public void testAccelerometer_100hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ACCELEROMETER, RATE_100HZ);
+    }
+
+    public void testAccelerometer_200hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ACCELEROMETER, RATE_200HZ);
+    }
+
+    public void testAccelerometer_50hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ACCELEROMETER, RATE_50HZ);
+    }
+
+    public void testAccelerometer_25hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ACCELEROMETER, RATE_25HZ);
+    }
+
+    public void testAccelerometer_15hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ACCELEROMETER, RATE_15HZ);
+    }
+
+    public void testAccelerometer_10hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ACCELEROMETER, RATE_10HZ);
+    }
+
+    public void testAccelerometer_5hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ACCELEROMETER, RATE_5HZ);
+    }
+
+    public void testAccelerometer_1hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ACCELEROMETER, RATE_1HZ);
+    }
+
+    public void testMagneticField_fastest() throws Throwable {
+        runSensorTest(Sensor.TYPE_MAGNETIC_FIELD, SensorManager.SENSOR_DELAY_FASTEST);
+    }
+
+    public void testMagneticField_200hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_MAGNETIC_FIELD, RATE_200HZ);
+    }
+
+    public void testMagneticField_100hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_MAGNETIC_FIELD, RATE_100HZ);
+    }
+
+    public void testMagneticField_50hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_MAGNETIC_FIELD, RATE_50HZ);
+    }
+
+    public void testMagneticField_25hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_MAGNETIC_FIELD, RATE_25HZ);
+    }
+
+    public void testMagneticField_15hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_MAGNETIC_FIELD, RATE_15HZ);
+    }
+
+    public void testMagneticField_10hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_MAGNETIC_FIELD, RATE_10HZ);
+    }
+
+    public void testMagneticField_5hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_MAGNETIC_FIELD, RATE_5HZ);
+    }
+
+    public void testMagneticField_1hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_MAGNETIC_FIELD, RATE_1HZ);
+    }
+
+    @SuppressWarnings("deprecation")
+    public void testOrientation_fastest() throws Throwable {
+        runSensorTest(Sensor.TYPE_ORIENTATION, SensorManager.SENSOR_DELAY_FASTEST);
+    }
+
+    @SuppressWarnings("deprecation")
+    public void testOrientation_200hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ORIENTATION, RATE_200HZ);
+    }
+    @SuppressWarnings("deprecation")
+    public void testOrientation_100hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ORIENTATION, RATE_100HZ);
+    }
+
+    @SuppressWarnings("deprecation")
+    public void testOrientation_50hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ORIENTATION, RATE_50HZ);
+    }
+
+    @SuppressWarnings("deprecation")
+    public void testOrientation_25hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ORIENTATION, RATE_25HZ);
+    }
+
+    @SuppressWarnings("deprecation")
+    public void testOrientation_15hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ORIENTATION, RATE_15HZ);
+    }
+
+    @SuppressWarnings("deprecation")
+    public void testOrientation_10hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ORIENTATION, RATE_10HZ);
+    }
+
+    @SuppressWarnings("deprecation")
+    public void testOrientation_5hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ORIENTATION, RATE_5HZ);
+    }
+
+    @SuppressWarnings("deprecation")
+    public void testOrientation_1hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ORIENTATION, RATE_1HZ);
+    }
+
+    public void testGyroscope_fastest() throws Throwable {
+        runSensorTest(Sensor.TYPE_GYROSCOPE, SensorManager.SENSOR_DELAY_FASTEST);
+    }
+
+    public void testGyroscope_200hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GYROSCOPE, RATE_200HZ);
+    }
+
+    public void testGyroscope_100hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GYROSCOPE, RATE_100HZ);
+    }
+
+    public void testGyroscope_50hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GYROSCOPE, RATE_50HZ);
+    }
+
+    public void testGyroscope_25hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GYROSCOPE, RATE_25HZ);
+    }
+
+    public void testGyroscope_15hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GYROSCOPE, RATE_15HZ);
+    }
+
+    public void testGyroscope_10hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GYROSCOPE, RATE_10HZ);
+    }
+
+    public void testGyroscope_5hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GYROSCOPE, RATE_5HZ);
+    }
+
+    public void testGyroscope_1hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GYROSCOPE, RATE_1HZ);
+    }
+
+    public void testPressure_fastest() throws Throwable {
+        runSensorTest(Sensor.TYPE_PRESSURE, SensorManager.SENSOR_DELAY_FASTEST);
+    }
+
+    public void testPressure_200hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_PRESSURE, RATE_200HZ);
+    }
+
+    public void testPressure_100hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_PRESSURE, RATE_100HZ);
+    }
+
+    public void testPressure_50hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_PRESSURE, RATE_50HZ);
+    }
+
+    public void testPressure_25hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_PRESSURE, RATE_25HZ);
+    }
+
+    public void testPressure_15hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_PRESSURE, RATE_15HZ);
+    }
+
+    public void testPressure_10hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_PRESSURE, RATE_10HZ);
+    }
+
+    public void testPressure_5hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_PRESSURE, RATE_5HZ);
+    }
+
+    public void testPressure_1hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_PRESSURE, RATE_1HZ);
+    }
+
+    public void testGravity_fastest() throws Throwable {
+        runSensorTest(Sensor.TYPE_GRAVITY, SensorManager.SENSOR_DELAY_FASTEST);
+    }
+
+    public void testGravity_200hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GRAVITY, RATE_200HZ);
+    }
+
+    public void testGravity_100hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GRAVITY, RATE_100HZ);
+    }
+
+    public void testGravity_50hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GRAVITY, RATE_50HZ);
+    }
+
+    public void testGravity_25hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GRAVITY, RATE_25HZ);
+    }
+
+    public void testGravity_15hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GRAVITY, RATE_15HZ);
+    }
+
+    public void testGravity_10hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GRAVITY, RATE_10HZ);
+    }
+
+    public void testGravity_5hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GRAVITY, RATE_5HZ);
+    }
+
+    public void testGravity_1hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GRAVITY, RATE_1HZ);
+    }
+
+    public void testRotationVector_fastest() throws Throwable {
+        runSensorTest(Sensor.TYPE_ROTATION_VECTOR, SensorManager.SENSOR_DELAY_FASTEST);
+    }
+
+    public void testRotationVector_200hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ROTATION_VECTOR, RATE_200HZ);
+    }
+
+    public void testRotationVector_100hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ROTATION_VECTOR, RATE_100HZ);
+    }
+
+    public void testRotationVector_50hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ROTATION_VECTOR, RATE_50HZ);
+    }
+
+    public void testRotationVector_25hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ROTATION_VECTOR, RATE_25HZ);
+    }
+
+    public void testRotationVector_15hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ROTATION_VECTOR, RATE_15HZ);
+    }
+
+    public void testRotationVector_10hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ROTATION_VECTOR, RATE_10HZ);
+    }
+
+    public void testRotationVector_5hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ROTATION_VECTOR, RATE_5HZ);
+    }
+
+    public void testRotationVector_1hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_ROTATION_VECTOR, RATE_1HZ);
+    }
+
+    public void testMagneticFieldUncalibrated_fastest() throws Throwable {
+        runSensorTest(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, SensorManager.SENSOR_DELAY_FASTEST);
+    }
+
+    public void testMagneticFieldUncalibrated_200hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, RATE_200HZ);
+    }
+
+    public void testMagneticFieldUncalibrated_100hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, RATE_100HZ);
+    }
+
+    public void testMagneticFieldUncalibrated_50hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, RATE_50HZ);
+    }
+
+    public void testMagneticFieldUncalibrated_25hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, RATE_25HZ);
+    }
+
+    public void testMagneticFieldUncalibrated_15hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, RATE_15HZ);
+    }
+
+    public void testMagneticFieldUncalibrated_10hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, RATE_10HZ);
+    }
+
+    public void testMagneticFieldUncalibrated_5hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, RATE_5HZ);
+    }
+
+    public void testMagneticFieldUncalibrated_1hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, RATE_1HZ);
+    }
+
+    public void testGameRotationVector_fastest() throws Throwable {
+        runSensorTest(Sensor.TYPE_GAME_ROTATION_VECTOR, SensorManager.SENSOR_DELAY_FASTEST);
+    }
+
+    public void testGameRotationVector_200hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GAME_ROTATION_VECTOR, RATE_200HZ);
+    }
+
+    public void testGameRotationVector_100hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GAME_ROTATION_VECTOR, RATE_100HZ);
+    }
+
+    public void testGameRotationVector_50hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GAME_ROTATION_VECTOR, RATE_50HZ);
+    }
+
+    public void testGameRotationVector_25hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GAME_ROTATION_VECTOR, RATE_25HZ);
+    }
+
+    public void testGameRotationVector_15hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GAME_ROTATION_VECTOR, RATE_15HZ);
+    }
+
+    public void testGameRotationVector_10hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GAME_ROTATION_VECTOR, RATE_10HZ);
+    }
+
+    public void testGameRotationVector_5hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GAME_ROTATION_VECTOR, RATE_5HZ);
+    }
+
+    public void testGameRotationVector_1hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GAME_ROTATION_VECTOR, RATE_1HZ);
+    }
+
+    public void testGyroscopeUncalibrated_fastest() throws Throwable {
+        runSensorTest(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, SensorManager.SENSOR_DELAY_FASTEST);
+    }
+
+    public void testGyroscopeUncalibrated_200hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, RATE_200HZ);
+    }
+
+    public void testGyroscopeUncalibrated_100hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, RATE_100HZ);
+    }
+
+    public void testGyroscopeUncalibrated_50hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, RATE_50HZ);
+    }
+
+    public void testGyroscopeUncalibrated_25hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, RATE_25HZ);
+    }
+
+    public void testGyroscopeUncalibrated_15hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, RATE_15HZ);
+    }
+
+    public void testGyroscopeUncalibrated_10hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, RATE_10HZ);
+    }
+
+    public void testGyroscopeUncalibrated_5hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, RATE_5HZ);
+    }
+
+    public void testGyroscopeUncalibrated_1hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, RATE_1HZ);
+    }
+
+    public void  testGeomagneticRotationVector_fastest() throws Throwable {
+        runSensorTest(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, SensorManager.SENSOR_DELAY_FASTEST);
+    }
+
+    public void  testLinearAcceleration_200hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_LINEAR_ACCELERATION, RATE_200HZ);
+    }
+
+    public void  testLinearAcceleration_100hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_LINEAR_ACCELERATION, RATE_100HZ);
+    }
+
+    public void testLinearAcceleration_50hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_LINEAR_ACCELERATION, RATE_50HZ);
+    }
+
+    public void testLinearAcceleration_25hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_LINEAR_ACCELERATION, RATE_25HZ);
+    }
+
+    public void testLinearAcceleration_15hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_LINEAR_ACCELERATION, RATE_15HZ);
+    }
+
+    public void testLinearAcceleration_10hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_LINEAR_ACCELERATION, RATE_10HZ);
+    }
+
+    public void testLinearAcceleration_5hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_LINEAR_ACCELERATION, RATE_5HZ);
+    }
+
+    public void testLinearAcceleration_1hz() throws Throwable {
+        runSensorTest(Sensor.TYPE_LINEAR_ACCELERATION, RATE_1HZ);
+    }
+
+    private void runSensorTest(int sensorType, int rateUs) throws Throwable {
+        TestSensorEnvironment environment = new TestSensorEnvironment(
+                getContext(),
+                sensorType,
+                shouldEmulateSensorUnderLoad(),
+                rateUs);
+        TestSensorOperation op = new TestSensorOperation(environment, 5, TimeUnit.SECONDS);
+        op.addDefaultVerifications();
+        op.setLogEvents(true);
+        try {
+            op.execute();
+        } finally {
+            SensorStats.logStats(TAG, op.getStats());
+
+            String sensorRate;
+            if (rateUs == SensorManager.SENSOR_DELAY_FASTEST) {
+                sensorRate = "fastest";
+            } else {
+                sensorRate = String.format("%.0fhz", environment.getFrequencyHz());
+            }
+            String fileName = String.format(
+                    "single_%s_%s.txt",
+                    SensorStats.getSanitizedSensorName(environment.getSensor()),
+                    sensorRate);
+            SensorStats.logStatsToFile(fileName, op.getStats());
+        }
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/ActivityResultMultiplexedLatch.java b/tests/tests/hardware/src/android/hardware/cts/helpers/ActivityResultMultiplexedLatch.java
new file mode 100644
index 0000000..093a659
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/ActivityResultMultiplexedLatch.java
@@ -0,0 +1,120 @@
+/*
+ * 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.cts.helpers;
+
+import java.util.HashMap;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * An abstraction on top of {@link CountDownLatch} to synchronize the results of Activities
+ * started by a parent activity.
+ *
+ * It holds a {@link CountDownLatch} latch for each thread that requests synchronization.
+ *
+ * Each thread requests a {@link Latch} to synchronize an Activity that will be started, by invoking
+ * {@link #bindThread()}, this guarantees that a latch is associated with the thread, and the result
+ * can be retrieved.
+ */
+public class ActivityResultMultiplexedLatch {
+    private static final String TAG = "ActivityResultMultiplexedLatch";
+
+    private final HashMap<Integer, Entry> mActivityEntries = new HashMap<Integer, Entry>();
+
+    /**
+     * A latch for a bound thread.
+     * Applications get an instance by invoking {@link ActivityResultMultiplexedLatch#bindThread()}.
+     */
+    public class Latch {
+        private Entry mEntry;
+
+        private Latch(Entry entry) {
+            mEntry = entry;
+        }
+
+        /**
+         * Awaits for the Activity bound to unblock the current thread.
+         *
+         * @return The result code of the Activity executed.
+         */
+        public int await() throws InterruptedException {
+            mEntry.latch.await();
+            return mEntry.resultCode;
+        }
+
+        /**
+         * @return A request code for the bound thread. It can be passed to the Activity to start.
+         */
+        public int getRequestCode() {
+            return mEntry.requestCode;
+        }
+    }
+
+    /**
+     * A class that represents the state for each thread/Activity being tracked.
+     */
+    private class Entry {
+        public final CountDownLatch latch = new CountDownLatch(1);
+        public final int requestCode;
+
+        public volatile int resultCode;
+
+        public Entry(int requestCode) {
+            this.requestCode = requestCode;
+        }
+    }
+
+    /**
+     * Binds a thread with this object.
+     *
+     * @return A request code (or session Id) for the bound thread.
+     */
+    public Latch bindThread() {
+        Entry entry;
+        int requestCode = getRequestCode();
+
+        synchronized (mActivityEntries) {
+            if (mActivityEntries.containsKey(requestCode)) {
+                throw new IllegalStateException("The thread has already been bound.");
+            }
+            entry = new Entry(requestCode);
+            mActivityEntries.put(requestCode, entry);
+        }
+
+        return new Latch(entry);
+    }
+
+    /**
+     * Used by the owner of the instance to record an Activity's result.
+     */
+    public void onActivityResult(int requestCode, int resultCode) {
+        Entry entry;
+        synchronized (mActivityEntries) {
+            entry = mActivityEntries.remove(requestCode);
+        }
+        if (entry == null) {
+            return;
+        }
+
+        entry.resultCode = resultCode;
+        entry.latch.countDown();
+    }
+
+    // there is no need for a better request Id, only one Activity can be launched at any time
+    private int getRequestCode() {
+        return Thread.currentThread().hashCode();
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/CameraUtils.java b/tests/tests/hardware/src/android/hardware/cts/helpers/CameraUtils.java
new file mode 100644
index 0000000..aaf9590
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/CameraUtils.java
@@ -0,0 +1,76 @@
+/*
+ * 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.cts.helpers;
+
+import android.content.Context;
+import android.hardware.Camera;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraManager;
+
+import java.util.Comparator;
+
+/**
+ * Utility class containing helper functions for the Camera CTS tests.
+ */
+public class CameraUtils {
+
+    /**
+     * Returns {@code true} if this device only supports {@code LEGACY} mode operation in the
+     * Camera2 API for the given camera ID.
+     *
+     * @param context {@link Context} to access the {@link CameraManager} in.
+     * @param cameraId the ID of the camera device to check.
+     * @return {@code true} if this device only supports {@code LEGACY} mode.
+     */
+    public static boolean isLegacyHAL(Context context, int cameraId) throws Exception {
+        CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
+        CameraCharacteristics characteristics =
+                manager.getCameraCharacteristics(Integer.toString(cameraId));
+
+        return characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) ==
+                CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY;
+    }
+
+    /**
+     * Shared size comparison method used by size comparators.
+     *
+     * <p>Compares the number of pixels it covers.If two the areas of two sizes are same, compare
+     * the widths.</p>
+     */
+     public static int compareSizes(int widthA, int heightA, int widthB, int heightB) {
+        long left = widthA * (long) heightA;
+        long right = widthB * (long) heightB;
+        if (left == right) {
+            left = widthA;
+            right = widthB;
+        }
+        return (left < right) ? -1 : (left > right ? 1 : 0);
+    }
+
+    /**
+     * Size comparator that compares the number of pixels it covers.
+     *
+     * <p>If two the areas of two sizes are same, compare the widths.</p>
+     */
+    public static class LegacySizeComparator implements Comparator<Camera.Size> {
+        @Override
+        public int compare(Camera.Size lhs, Camera.Size rhs) {
+            return compareSizes(lhs.width, lhs.height, rhs.width, rhs.height);
+        }
+    }
+
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/CollectingSensorEventListener.java b/tests/tests/hardware/src/android/hardware/cts/helpers/CollectingSensorEventListener.java
new file mode 100644
index 0000000..ca7d133
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/CollectingSensorEventListener.java
@@ -0,0 +1,101 @@
+/*
+ * 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.cts.helpers;
+
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener2;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A {@link TestSensorEventListener} which collects events to be processed after the test is run.
+ * This should only be used for short tests.
+ */
+public class CollectingSensorEventListener extends TestSensorEventListener {
+    private final ArrayList<TestSensorEvent> mSensorEventsList = new ArrayList<TestSensorEvent>();
+
+    /**
+     * Constructs a {@link CollectingSensorEventListener} with an additional
+     * {@link SensorEventListener2}.
+     */
+    public CollectingSensorEventListener(SensorEventListener2 listener) {
+        super(listener);
+    }
+
+    /**
+     * Constructs a {@link CollectingSensorEventListener}.
+     */
+    public CollectingSensorEventListener() {
+        this(null);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onSensorChanged(SensorEvent event) {
+        super.onSensorChanged(event);
+        synchronized (mSensorEventsList) {
+            mSensorEventsList.add(new TestSensorEvent(event));
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * <p>
+     * Clears the event queue before starting.
+     * </p>
+     */
+    @Override
+    public void waitForEvents(int eventCount) throws InterruptedException {
+        clearEvents();
+        super.waitForEvents(eventCount);
+    }
+
+    /**
+     * {@inheritDoc}
+     * <p>
+     * Clears the event queue before starting.
+     * </p>
+     */
+    @Override
+    public void waitForEvents(long duration, TimeUnit timeUnit) throws InterruptedException {
+        clearEvents();
+        super.waitForEvents(duration, timeUnit);
+    }
+
+    /**
+     * Get the {@link TestSensorEvent} array from the event queue.
+     */
+    public List<TestSensorEvent> getEvents() {
+        synchronized (mSensorEventsList) {
+            return Collections.unmodifiableList(mSensorEventsList);
+        }
+    }
+
+    /**
+     * Clear the event queue.
+     */
+    public void clearEvents() {
+        synchronized (mSensorEventsList) {
+            mSensorEventsList.clear();
+        }
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/FrameworkUnitTests.java b/tests/tests/hardware/src/android/hardware/cts/helpers/FrameworkUnitTests.java
new file mode 100644
index 0000000..e620955
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/FrameworkUnitTests.java
@@ -0,0 +1,59 @@
+/*
+ * 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.cts.helpers;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import android.hardware.cts.helpers.sensoroperations.SensorOperationTest;
+import android.hardware.cts.helpers.sensorverification.EventGapVerificationTest;
+import android.hardware.cts.helpers.sensorverification.EventOrderingVerificationTest;
+import android.hardware.cts.helpers.sensorverification.FrequencyVerificationTest;
+import android.hardware.cts.helpers.sensorverification.JitterVerificationTest;
+import android.hardware.cts.helpers.sensorverification.MagnitudeVerificationTest;
+import android.hardware.cts.helpers.sensorverification.MeanVerificationTest;
+import android.hardware.cts.helpers.sensorverification.StandardDeviationVerificationTest;
+
+/**
+ * Unit test suite for the CTS sensor framework.
+ */
+public class FrameworkUnitTests extends TestSuite {
+
+    public FrameworkUnitTests() {
+        super();
+
+        // helpers
+        addTestSuite(SensorCtsHelperTest.class);
+        addTestSuite(SensorStatsTest.class);
+
+        // sensorverification
+        addTestSuite(EventOrderingVerificationTest.class);
+        addTestSuite(FrequencyVerificationTest.class);
+        addTestSuite(JitterVerificationTest.class);
+        addTestSuite(MagnitudeVerificationTest.class);
+        addTestSuite(MeanVerificationTest.class);
+        addTestSuite(EventGapVerificationTest.class);
+        addTestSuite(StandardDeviationVerificationTest.class);
+
+        // sensorOperations
+        addTestSuite(SensorOperationTest.class);
+    }
+
+    public static Test suite() {
+        return new FrameworkUnitTests();
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/MovementDetectorHelper.java b/tests/tests/hardware/src/android/hardware/cts/helpers/MovementDetectorHelper.java
new file mode 100644
index 0000000..0eb1141
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/MovementDetectorHelper.java
@@ -0,0 +1,110 @@
+/*
+ * 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.cts.helpers;
+
+import junit.framework.Assert;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+
+/**
+ * Helper class that provides a way to identify if movement has been detected in the device.
+ *
+ * Notes:
+ * Alpha is calculated as:
+ *      t / ( t + dT)
+ * Where
+ *       t - low-pass filter's time-constant
+ *      dT - event delivery rate
+ */
+public abstract class MovementDetectorHelper implements SensorEventListener {
+    private static final float MOVEMENT_DETECTION_ACCELERATION_THRESHOLD = 4.0f;
+    private static final float ALPHA = 0.8f;
+
+    private final float[] mGravity = {0.0f, 0.0f, 0.0f};
+
+    private final SensorManager mSensorManager;
+    private final Sensor mAccelerometer;
+
+    private boolean mInitialized;
+
+    public MovementDetectorHelper(Context context) {
+        mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
+        Assert.assertNotNull("SensorManager", mSensorManager);
+
+        mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+        if (mAccelerometer == null) {
+            throw new SensorNotSupportedException(Sensor.TYPE_ACCELEROMETER);
+        }
+    }
+
+    public synchronized void start() {
+        if (mInitialized) {
+            return;
+        }
+
+        mInitialized = mSensorManager
+                .registerListener(this, mAccelerometer,SensorManager.SENSOR_DELAY_NORMAL);
+        Assert.assertTrue(mInitialized);
+    }
+
+    public synchronized void stop() {
+        if (!mInitialized) {
+            return;
+        }
+
+        mSensorManager.unregisterListener(this);
+        mInitialized = false;
+    }
+
+    protected abstract void onMovementDetected();
+
+    @Override
+    public void onAccuracyChanged(Sensor sensor, int accuracy) {}
+
+    @Override
+    public void onSensorChanged(SensorEvent event) {
+        float[] linearAcceleration = {0.0f, 0.0f, 0.0f};
+
+        if (mGravity[0] == 0f && mGravity[2] == 0f) {
+            mGravity[0] = event.values[0];
+            mGravity[1] = event.values[1];
+            mGravity[2] = event.values[2];
+        } else {
+            // Isolate the force of gravity with the low-pass filter.
+            mGravity[0] = ALPHA * mGravity[0] + (1 - ALPHA) * event.values[0];
+            mGravity[1] = ALPHA * mGravity[1] + (1 - ALPHA) * event.values[1];
+            mGravity[2] = ALPHA * mGravity[2] + (1 - ALPHA) * event.values[2];
+        }
+
+        // Remove the gravity contribution with the high-pass filter.
+        linearAcceleration[0] = event.values[0] - mGravity[0];
+        linearAcceleration[1] = event.values[1] - mGravity[1];
+        linearAcceleration[2] = event.values[2] - mGravity[2];
+
+        float totalAcceleration = Math.abs(linearAcceleration[0])
+                + Math.abs(linearAcceleration[1])
+                + Math.abs(linearAcceleration[2]);
+
+        if (totalAcceleration > MOVEMENT_DETECTION_ACCELERATION_THRESHOLD) {
+            onMovementDetected();
+        }
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCalibratedUncalibratedVerifier.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCalibratedUncalibratedVerifier.java
new file mode 100644
index 0000000..b3b8559
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCalibratedUncalibratedVerifier.java
@@ -0,0 +1,128 @@
+/*
+ * 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.cts.helpers;
+
+import junit.framework.Assert;
+
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A bundled sensor test operation/verification.
+ *
+ * It verifies the relationship between measurements from calibrated sensors and their corresponding
+ * uncalibrated sensors comply to the following equation:
+ *  calibrated = uncalibrated - bias
+ */
+// TODO: refactor into proper test operation/verification classes:
+// currently this is the only verification that requires input from multiple sensors, and the class
+// is factored into: operation, verification, and listener as other sensor test operations
+public class SensorCalibratedUncalibratedVerifier {
+
+    private final TestSensorManager mCalibratedSensorManager;
+    private final TestSensorManager mUncalibratedSensorManager;
+    private final float mThreshold;
+
+    public SensorCalibratedUncalibratedVerifier(
+            TestSensorEnvironment calibratedEnvironment,
+            TestSensorEnvironment uncalibratedEnvironment,
+            float threshold) {
+        mCalibratedSensorManager = new TestSensorManager(calibratedEnvironment);
+        mUncalibratedSensorManager = new TestSensorManager(uncalibratedEnvironment);
+        mThreshold = threshold;
+    }
+
+    /**
+     * Executes the operation: it collects the data and run verifications on it.
+     */
+    public void execute() throws Throwable {
+        CollectingSensorEventListener calibratedTestListener = new CollectingSensorEventListener();
+        CollectingSensorEventListener uncalibratedTestListener = new CollectingSensorEventListener();
+        mCalibratedSensorManager.registerListener(calibratedTestListener);
+        mUncalibratedSensorManager.registerListener(uncalibratedTestListener);
+
+        Thread.sleep(TimeUnit.SECONDS.toMillis(10));
+
+        mCalibratedSensorManager.unregisterListener();
+        mUncalibratedSensorManager.unregisterListener();
+
+        verifyMeasurements(
+                calibratedTestListener.getEvents(),
+                uncalibratedTestListener.getEvents(),
+                mThreshold);
+    }
+
+    private void verifyMeasurements(
+            List<TestSensorEvent> calibratedEvents,
+            List<TestSensorEvent> uncalibratedEvents,
+            float threshold) {
+        long measuredSamplingPeriodNs = SensorCtsHelper.getSamplingPeriodNs(calibratedEvents);
+        long synchronizationPeriodNs = measuredSamplingPeriodNs / 2;
+        int eventsValidated = 0;
+
+        // TODO: this makes the algorithm O(n^2) when we could have it O(n), but it has little
+        // impact on the overall test duration because the data collection is what takes the most
+        // time
+        for (TestSensorEvent calibratedEvent : calibratedEvents) {
+            long calibratedTimestampNs = calibratedEvent.timestamp;
+            long lowerTimestampThresholdNs = calibratedTimestampNs - synchronizationPeriodNs;
+            long upperTimestampThresholdNs = calibratedTimestampNs + synchronizationPeriodNs;
+
+            for (TestSensorEvent uncalibratedEvent : uncalibratedEvents) {
+                long uncalibratedTimestampNs = uncalibratedEvent.timestamp;
+                if (uncalibratedTimestampNs > lowerTimestampThresholdNs
+                        && uncalibratedTimestampNs < upperTimestampThresholdNs) {
+                    // perform validation
+                    verifyCalibratedUncalibratedPair(
+                            calibratedEvent,
+                            uncalibratedEvent,
+                            threshold);
+                    ++eventsValidated;
+                }
+            }
+        }
+
+        String eventsValidatedMessage = String.format(
+                "Expected to find at least one Calibrated/Uncalibrated event pair for validation."
+                        + " Found=%d",
+                eventsValidated);
+        Assert.assertTrue(eventsValidatedMessage, eventsValidated > 0);
+    }
+
+    private void verifyCalibratedUncalibratedPair(
+            TestSensorEvent calibratedEvent,
+            TestSensorEvent uncalibratedEvent,
+            float threshold) {
+        for (int i = 0; i < 3; ++i) {
+            float calibrated = calibratedEvent.values[i];
+            float uncalibrated = uncalibratedEvent.values[i];
+            float bias = uncalibratedEvent.values[i + 3];
+            String message = String.format(
+                    "Calibrated (%s) and Uncalibrated (%s) sensor readings are expected to satisfy:"
+                            + " calibrated = uncalibrated - bias. Axis=%d, Calibrated=%s, "
+                            + "Uncalibrated=%s, Bias=%s, Threshold=%s",
+                    calibratedEvent.sensor.getName(),
+                    uncalibratedEvent.sensor.getName(),
+                    i,
+                    calibrated,
+                    uncalibrated,
+                    bias,
+                    threshold);
+            Assert.assertEquals(message, calibrated, uncalibrated - bias, threshold);
+        }
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java
index 9d860cd..a79e5b1 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java
@@ -15,27 +15,22 @@
  */
 package android.hardware.cts.helpers;
 
-import android.content.Context;
-import android.hardware.Sensor;
-import android.hardware.SensorManager;
-import android.os.Environment;
-import android.util.Log;
-
-import java.io.DataOutputStream;
+import java.io.File;
 import java.io.IOException;
-import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Date;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 
 /**
  * Set of static helper methods for CTS tests.
  */
+//TODO: Refactor this class into several more well defined helper classes, look at StatisticsUtils
 public class SensorCtsHelper {
 
+    private static final long NANOS_PER_MILLI = 1000000;
+
     /**
      * Private constructor for static class.
      */
@@ -60,61 +55,6 @@
     }
 
     /**
-     * Calculates the mean for each of the values in the set of TestSensorEvents.
-     *
-     * @throws IllegalArgumentException if there are no events
-     */
-    public static double[] getMeans(TestSensorEvent[] events) {
-        if (events.length == 0) {
-            throw new IllegalArgumentException("Events cannot be empty");
-        }
-
-        double[] means = new double[events[0].values.length];
-        for (TestSensorEvent event : events) {
-            for (int i = 0; i < means.length; i++) {
-                means[i] += event.values[i];
-            }
-        }
-        for (int i = 0; i < means.length; i++) {
-            means[i] /= events.length;
-        }
-        return means;
-    }
-
-    /**
-     * Calculates the variance for each of the values in the set of TestSensorEvents.
-     *
-     * @throws IllegalArgumentException if there are no events
-     */
-    public static double[] getVariances(TestSensorEvent[] events) {
-        double[] means = getMeans(events);
-        double[] variances = new double[means.length];
-        for (int i = 0; i < means.length; i++) {
-            Collection<Double> squaredDiffs = new ArrayList<Double>(events.length);
-            for (TestSensorEvent event : events) {
-                double diff = event.values[i] - means[i];
-                squaredDiffs.add(diff * diff);
-            }
-            variances[i] = getMean(squaredDiffs);
-        }
-        return variances;
-    }
-
-    /**
-     * Calculates the standard deviation for each of the values in the set of TestSensorEvents.
-     *
-     * @throws IllegalArgumentException if there are no events
-     */
-    public static double[] getStandardDeviations(TestSensorEvent[] events) {
-        double[] variances = getVariances(events);
-        double[] stdDevs = new double[variances.length];
-        for (int i = 0; i < variances.length; i++) {
-            stdDevs[i] = Math.sqrt(variances[i]);
-        }
-        return stdDevs;
-    }
-
-    /**
      * Calculate the mean of a collection.
      *
      * @throws IllegalArgumentException if the collection is null or empty
@@ -130,7 +70,7 @@
     }
 
     /**
-     * Calculate the variance of a collection.
+     * Calculate the bias-corrected sample variance of a collection.
      *
      * @throws IllegalArgumentException if the collection is null or empty
      */
@@ -138,17 +78,34 @@
         validateCollection(collection);
 
         double mean = getMean(collection);
-        ArrayList<Double> squaredDifferences = new ArrayList<Double>();
+        ArrayList<Double> squaredDiffs = new ArrayList<Double>();
         for(TValue value : collection) {
             double difference = mean - value.doubleValue();
-            squaredDifferences.add(Math.pow(difference, 2));
+            squaredDiffs.add(Math.pow(difference, 2));
         }
 
-        return getMean(squaredDifferences);
+        double sum = 0.0;
+        for (Double value : squaredDiffs) {
+            sum += value;
+        }
+        return sum / (squaredDiffs.size() - 1);
     }
 
     /**
-     * Calculate the standard deviation of a collection.
+     * @return The (measured) sampling rate of a collection of {@link TestSensorEvent}.
+     */
+    public static long getSamplingPeriodNs(List<TestSensorEvent> collection) {
+        int collectionSize = collection.size();
+        if (collectionSize < 2) {
+            return 0;
+        }
+        TestSensorEvent firstEvent = collection.get(0);
+        TestSensorEvent lastEvent = collection.get(collectionSize - 1);
+        return (lastEvent.timestamp - firstEvent.timestamp) / (collectionSize - 1);
+    }
+
+    /**
+     * Calculate the bias-corrected standard deviation of a collection.
      *
      * @throws IllegalArgumentException if the collection is null or empty
      */
@@ -158,113 +115,6 @@
     }
 
     /**
-     * Get a list containing the delay between sensor events.
-     *
-     * @param events The array of {@link TestSensorEvent}.
-     * @return A list containing the delay between sensor events in nanoseconds.
-     */
-    public static List<Long> getTimestampDelayValues(TestSensorEvent[] events) {
-        if (events.length < 2) {
-            return new ArrayList<Long>();
-        }
-        List<Long> timestampDelayValues = new ArrayList<Long>(events.length - 1);
-        for (int i = 1; i < events.length; i++) {
-            timestampDelayValues.add(events[i].timestamp - events[i - 1].timestamp);
-        }
-        return timestampDelayValues;
-    }
-
-    /**
-     * Get a list containing the jitter values for a collection of sensor events.
-     *
-     * @param events The array of {@link TestSensorEvent}.
-     * @return A list containing the jitter values between each event.
-     * @throws IllegalArgumentException if the number of events is less that 2.
-     */
-    public static List<Double> getJitterValues(TestSensorEvent[] events) {
-        List<Long> timestampDelayValues = getTimestampDelayValues(events);
-        double averageTimestampDelay = getMean(timestampDelayValues);
-
-        List<Double> jitterValues = new ArrayList<Double>(timestampDelayValues.size());
-        for (long timestampDelay : timestampDelayValues) {
-            jitterValues.add(Math.abs(timestampDelay - averageTimestampDelay));
-        }
-        return jitterValues;
-    }
-
-    /**
-     * NOTE:
-     * - The bug report is usually written to /sdcard/Downloads
-     * - In order for the test Instrumentation to gather useful data the following permissions are
-     *   required:
-     *      . android.permission.READ_LOGS
-     *      . android.permission.DUMP
-     */
-    public static String collectBugreport(String collectorId)
-            throws IOException, InterruptedException {
-        String commands[] = new String[] {
-                "dumpstate",
-                "dumpsys",
-                "logcat -d -v threadtime",
-                "exit"
-        };
-
-        SimpleDateFormat dateFormat = new SimpleDateFormat("M-d-y_H:m:s.S");
-        String outputFile = String.format(
-                "%s/%s_%s",
-                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
-                collectorId,
-                dateFormat.format(new Date()));
-
-        DataOutputStream processOutput = null;
-        try {
-            Process process = Runtime.getRuntime().exec("/system/bin/sh -");
-            processOutput = new DataOutputStream(process.getOutputStream());
-
-            for(String command : commands) {
-                processOutput.writeBytes(String.format("%s >> %s\n", command, outputFile));
-            }
-
-            processOutput.flush();
-            process.waitFor();
-
-            Log.d(collectorId, String.format("Bug-Report collected at: %s", outputFile));
-        } finally {
-            if(processOutput != null) {
-                try {
-                    processOutput.close();
-                } catch(IOException e) {}
-            }
-        }
-
-        return outputFile;
-    }
-
-    /**
-     * Get the default sensor for a given type.
-     */
-    public static Sensor getSensor(Context context, int sensorType) {
-        SensorManager sensorManager = getSensorManager(context);
-        Sensor sensor = sensorManager.getDefaultSensor(sensorType);
-        if(sensor == null) {
-            throw new SensorNotSupportedException(sensorType);
-        }
-        return sensor;
-    }
-
-    /**
-     * Get all the sensors for a given type.
-     */
-    public static List<Sensor> getSensors(Context context, int sensorType) {
-        SensorManager sensorManager = getSensorManager(context);
-        List<Sensor> sensors = sensorManager.getSensorList(sensorType);
-        if (sensors.size() == 0) {
-            throw new SensorNotSupportedException(sensorType);
-        }
-        return sensors;
-    }
-
-    /**
      * Convert a period to frequency in Hz.
      */
     public static <TValue extends Number> double getFrequency(TValue period, TimeUnit unit) {
@@ -279,64 +129,105 @@
     }
 
     /**
-     * Convert number of seconds to number of microseconds.
+     * @return The magnitude (norm) represented by the given array of values.
      */
-    public static int getSecondsAsMicroSeconds(int seconds) {
-        return (int) TimeUnit.MICROSECONDS.convert(seconds, TimeUnit.SECONDS);
-    }
-
-    /**
-     * Format an assertion message.
-     *
-     * @param verificationName The verification name
-     * @param sensor The sensor under test
-     * @param format The additional format string, use "" if blank
-     * @param params The additional format params
-     * @return The formatted string.
-     */
-    public static String formatAssertionMessage(
-            String verificationName,
-            Sensor sensor,
-            String format,
-            Object ... params) {
-        return formatAssertionMessage(verificationName, null, sensor, format, params);
-    }
-
-    /**
-     * Format an assertion message.
-     *
-     * @param verificationName The verification name
-     * @param test The test, optional
-     * @param sensor The sensor under test
-     * @param format The additional format string, use "" if blank
-     * @param params The additional format params
-     * @return The formatted string.
-     */
-    public static String formatAssertionMessage(
-            String verificationName,
-            SensorTestOperation test,
-            Sensor sensor,
-            String format,
-            Object ... params) {
-        StringBuilder builder = new StringBuilder();
-
-        // identify the verification
-        builder.append(verificationName);
-        builder.append("| ");
-        // add test context information
-        if(test != null) {
-            builder.append(test.toString());
-            builder.append("| ");
+    public static double getMagnitude(float[] values) {
+        float sumOfSquares = 0.0f;
+        for (float value : values) {
+            sumOfSquares += value * value;
         }
-        // add context information
-        builder.append(SensorTestInformation.getSensorName(sensor.getType()));
-        builder.append(", handle:");
-        builder.append(sensor.getHandle());
-        builder.append("| ");
-        // add the custom formatting
-        builder.append(String.format(format, params));
+        double magnitude = Math.sqrt(sumOfSquares);
+        return magnitude;
+    }
 
-        return builder.toString();
+    /**
+     * Helper method to sleep for a given duration.
+     */
+    public static void sleep(long duration, TimeUnit timeUnit) throws InterruptedException {
+        long durationNs = TimeUnit.NANOSECONDS.convert(duration, timeUnit);
+        Thread.sleep(durationNs / NANOS_PER_MILLI, (int) (durationNs % NANOS_PER_MILLI));
+    }
+
+    /**
+     * Format an assertion message.
+     *
+     * @param label the verification name
+     * @param environment the environment of the test
+     *
+     * @return The formatted string
+     */
+    public static String formatAssertionMessage(String label, TestSensorEnvironment environment) {
+        return formatAssertionMessage(label, environment, "Failed");
+    }
+
+    /**
+     * Format an assertion message with a custom message.
+     *
+     * @param label the verification name
+     * @param environment the environment of the test
+     * @param format the additional format string
+     * @param params the additional format params
+     *
+     * @return The formatted string
+     */
+    public static String formatAssertionMessage(
+            String label,
+            TestSensorEnvironment environment,
+            String format,
+            Object ... params) {
+        return formatAssertionMessage(label, environment, String.format(format, params));
+    }
+
+    /**
+     * Format an assertion message.
+     *
+     * @param label the verification name
+     * @param environment the environment of the test
+     * @param extras the additional information for the assertion
+     *
+     * @return The formatted string
+     */
+    public static String formatAssertionMessage(
+            String label,
+            TestSensorEnvironment environment,
+            String extras) {
+        return String.format(
+                "%s | sensor='%s', samplingPeriodUs=%d, maxReportLatencyUs=%d | %s",
+                label,
+                environment.getSensor().getName(),
+                environment.getRequestedSamplingPeriodUs(),
+                environment.getMaxReportLatencyUs(),
+                extras);
+    }
+
+    /**
+     * @return A {@link File} representing a root directory to store sensor tests data.
+     */
+    public static File getSensorTestDataDirectory() throws IOException {
+        File dataDirectory = new File(System.getenv("EXTERNAL_STORAGE"), "sensorTests/");
+        return createDirectoryStructure(dataDirectory);
+    }
+
+    /**
+     * Creates the directory structure for the given sensor test data sub-directory.
+     *
+     * @param subdirectory The sub-directory's name.
+     */
+    public static File getSensorTestDataDirectory(String subdirectory) throws IOException {
+        File subdirectoryFile = new File(getSensorTestDataDirectory(), subdirectory);
+        return createDirectoryStructure(subdirectoryFile);
+    }
+
+    /**
+     * Ensures that the directory structure represented by the given {@link File} is created.
+     */
+    private static File createDirectoryStructure(File directoryStructure) throws IOException {
+        directoryStructure.mkdirs();
+        if (!directoryStructure.isDirectory()) {
+            throw new IOException("Unable to create directory structure for "
+                    + directoryStructure.getAbsolutePath());
+        }
+        return directoryStructure;
     }
 
     /**
@@ -349,18 +240,4 @@
             throw new IllegalStateException("Collection cannot be null or empty");
         }
     }
-
-    /**
-     * Get the SensorManager.
-     *
-     * @throws IllegalStateException if the SensorManager is not present in the system.
-     */
-    private static SensorManager getSensorManager(Context context) {
-        SensorManager sensorManager = (SensorManager) context.getSystemService(
-                Context.SENSOR_SERVICE);
-        if(sensorManager == null) {
-            throw new IllegalStateException("SensorService is not present in the system.");
-        }
-        return sensorManager;
-    }
 }
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelperTest.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelperTest.java
index ccfaf2a..6f99692 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelperTest.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelperTest.java
@@ -53,73 +53,6 @@
     }
 
     /**
-     * Test {@link SensorCtsHelper#getMeans(TestSensorEvent[])}.
-     */
-    public void testGetMeans() {
-        long[] timestamps = {0, 1, 2, 3, 4};
-
-        float[] values = {0, 1, 2, 3, 4};  // 2.0
-        double[] means = SensorCtsHelper.getMeans(getSensorEvents(timestamps, values));
-        assertEquals(1, means.length);
-        assertEquals(2.0, means[0], 0.00001);
-
-        float[] values1 = {0, 1, 2, 3, 4};  // 2.0
-        float[] values2 = {1, 2, 3, 4, 5};  // 3.0
-        float[] values3 = {0, 1, 4, 9, 16};  // 6.0
-        means = SensorCtsHelper.getMeans(
-                getSensorEvents(timestamps, values1, values2, values3));
-        assertEquals(3, means.length);
-        assertEquals(2.0, means[0], 0.00001);
-        assertEquals(3.0, means[1], 0.00001);
-        assertEquals(6.0, means[2], 0.00001);
-    }
-
-    /**
-     * Test {@link SensorCtsHelper#getVariances(TestSensorEvent[])}.
-     */
-    public void testGetVariences() {
-        long[] timestamps = {0, 1, 2, 3, 4};
-
-        float[] values = {0, 1, 2, 3, 4};  // 2.0
-        double[] variances = SensorCtsHelper.getVariances(getSensorEvents(timestamps, values));
-        assertEquals(1, variances.length);
-        assertEquals(2.0, variances[0], 0.00001);
-
-        float[] values1 = {0, 1, 2, 3, 4};  // 2.0
-        float[] values2 = {1, 2, 3, 4, 5};  // 2.0
-        float[] values3 = {0, 2, 4, 6, 8};  // 8.0
-        variances = SensorCtsHelper.getVariances(
-                getSensorEvents(timestamps, values1, values2, values3));
-        assertEquals(3, variances.length);
-        assertEquals(2.0, variances[0], 0.00001);
-        assertEquals(2.0, variances[1], 0.00001);
-        assertEquals(8.0, variances[2], 0.00001);
-    }
-
-    /**
-     * Test {@link SensorCtsHelper#getStandardDeviations(TestSensorEvent[])}.
-     */
-    public void testGetStandardDeviations() {
-        long[] timestamps = {0, 1, 2, 3, 4};
-
-        float[] values = {0, 1, 2, 3, 4};  // sqrt(2.0)
-        double[] stddev = SensorCtsHelper.getStandardDeviations(
-                getSensorEvents(timestamps, values));
-        assertEquals(1, stddev.length);
-        assertEquals(Math.sqrt(2.0), stddev[0], 0.00001);
-
-        float[] values1 = {0, 1, 2, 3, 4};  // sqrt(2.0)
-        float[] values2 = {1, 2, 3, 4, 5};  // sqrt(2.0)
-        float[] values3 = {0, 2, 4, 6, 8};  // sqrt(8.0)
-        stddev = SensorCtsHelper.getStandardDeviations(
-                getSensorEvents(timestamps, values1, values2, values3));
-        assertEquals(3, stddev.length);
-        assertEquals(Math.sqrt(2.0), stddev[0], 0.00001);
-        assertEquals(Math.sqrt(2.0), stddev[1], 0.00001);
-        assertEquals(Math.sqrt(8.0), stddev[2], 0.00001);
-    }
-
-    /**
      * Test {@link SensorCtsHelper#getMean(Collection)}.
      */
     public void testGetMean() {
@@ -142,15 +75,15 @@
     public void testGetVariance() {
         List<Integer> values = Arrays.asList(0, 1, 2, 3, 4);
         double variance = SensorCtsHelper.getVariance(values);
-        assertEquals(2.0, variance, 0.00001);
+        assertEquals(2.5, variance, 0.00001);
 
         values = Arrays.asList(1, 2, 3, 4, 5);
         variance = SensorCtsHelper.getVariance(values);
-        assertEquals(2.0, variance, 0.00001);
+        assertEquals(2.5, variance, 0.00001);
 
         values = Arrays.asList(0, 2, 4, 6, 8);
         variance = SensorCtsHelper.getVariance(values);
-        assertEquals(8.0, variance, 0.00001);
+        assertEquals(10.0, variance, 0.00001);
     }
 
     /**
@@ -159,31 +92,15 @@
     public void testGetStandardDeviation() {
         List<Integer> values = Arrays.asList(0, 1, 2, 3, 4);
         double stddev = SensorCtsHelper.getStandardDeviation(values);
-        assertEquals(Math.sqrt(2.0), stddev, 0.00001);
+        assertEquals(Math.sqrt(2.5), stddev, 0.00001);
 
         values = Arrays.asList(1, 2, 3, 4, 5);
         stddev = SensorCtsHelper.getStandardDeviation(values);
-        assertEquals(Math.sqrt(2.0), stddev, 0.00001);
+        assertEquals(Math.sqrt(2.5), stddev, 0.00001);
 
         values = Arrays.asList(0, 2, 4, 6, 8);
         stddev = SensorCtsHelper.getStandardDeviation(values);
-        assertEquals(Math.sqrt(8.0), stddev, 0.00001);
-    }
-
-    /**
-     * Test {@link SensorCtsHelper#getTimestampDelayValues(TestSensorEvent[])}.
-     */
-    public void testGetTimestampDelayValues() {
-        float[] values = {0, 1, 2, 3, 4};
-
-        long[] timestamps = {0, 0, 1, 3, 100};
-        List<Long> timestampDelayValues = SensorCtsHelper.getTimestampDelayValues(
-                getSensorEvents(timestamps, values));
-        assertEquals(4, timestampDelayValues.size());
-        assertEquals(0, (long) timestampDelayValues.get(0));
-        assertEquals(1, (long) timestampDelayValues.get(1));
-        assertEquals(2, (long) timestampDelayValues.get(2));
-        assertEquals(97, (long) timestampDelayValues.get(3));
+        assertEquals(Math.sqrt(10.0), stddev, 0.00001);
     }
 
     /**
@@ -217,50 +134,4 @@
         assertEquals(100, SensorCtsHelper.getPeriod(10000000, TimeUnit.NANOSECONDS), 0.001);
         assertEquals(1, SensorCtsHelper.getPeriod(1000000000, TimeUnit.NANOSECONDS), 0.001);
     }
-
-    /**
-     * Test {@link SensorCtsHelper#getJitterValues(TestSensorEvent[])}.
-     */
-    public void testGetJitterValues() {
-        float[] values = {0, 1, 2, 3, 4};
-
-        long[] timestamps1 = {0, 1, 2, 3, 4};
-        List<Double> jitterValues = SensorCtsHelper.getJitterValues(
-                getSensorEvents(timestamps1, values));
-        assertEquals(4, jitterValues.size());
-        assertEquals(0.0, (double) jitterValues.get(0));
-        assertEquals(0.0, (double) jitterValues.get(1));
-        assertEquals(0.0, (double) jitterValues.get(2));
-        assertEquals(0.0, (double) jitterValues.get(3));
-
-        long[] timestamps2 = {0, 0, 2, 4, 4};
-        jitterValues = SensorCtsHelper.getJitterValues(
-                getSensorEvents(timestamps2, values));
-        assertEquals(4, jitterValues.size());
-        assertEquals(1.0, (double) jitterValues.get(0));
-        assertEquals(1.0, (double) jitterValues.get(1));
-        assertEquals(1.0, (double) jitterValues.get(2));
-        assertEquals(1.0, (double) jitterValues.get(3));
-
-        long[] timestamps3 = {0, 1, 4, 9, 16};
-        jitterValues = SensorCtsHelper.getJitterValues(
-                getSensorEvents(timestamps3, values));
-        assertEquals(4, jitterValues.size());
-        assertEquals(3.0, (double) jitterValues.get(0));
-        assertEquals(1.0, (double) jitterValues.get(1));
-        assertEquals(1.0, (double) jitterValues.get(2));
-        assertEquals(3.0, (double) jitterValues.get(3));
-    }
-
-    private TestSensorEvent[] getSensorEvents(long[] timestamps, float[] ... values) {
-        TestSensorEvent[] events = new TestSensorEvent[timestamps.length];
-        for (int i = 0; i < timestamps.length; i++) {
-            float[] eventValues = new float[values.length];
-            for (int j = 0; j < values.length; j++) {
-                eventValues[j] = values[j][i];
-            }
-            events[i] = new TestSensorEvent(null, timestamps[i], 0, eventValues);
-        }
-        return events;
-    }
 }
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorManagerTestVerifier.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorManagerTestVerifier.java
deleted file mode 100644
index 85f4f0e..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorManagerTestVerifier.java
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.cts.helpers;
-
-import android.content.Context;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener2;
-import android.hardware.SensorManager;
-
-import junit.framework.Assert;
-
-import java.io.Closeable;
-import java.security.InvalidParameterException;
-import java.util.concurrent.ConcurrentLinkedDeque;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Test class to wrap SensorManager with verifications and test checks.
- * This class allows to perform operations in the Sensor Manager and performs all the expected test
- * verification on behalf of the owner.
- * An object can be used to quickly writing tests that focus on the scenario that needs to be
- * verified, and not in the implicit verifications that need to take place at any step.
- */
-public class SensorManagerTestVerifier implements Closeable, SensorEventListener2 {
-    private final int WAIT_TIMEOUT_IN_SECONDS = 30;
-
-    private final SensorManager mSensorManager;
-    private final Sensor mSensorUnderTest;
-    private final int mSamplingRateInUs;
-    private final int mReportLatencyInUs;
-
-    private TestSensorListener mEventListener;
-
-    /**
-     * Construction methods.
-     */
-    public SensorManagerTestVerifier(
-            Context context,
-            int sensorType,
-            int samplingRateInUs,
-            int reportLatencyInUs) {
-        mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
-        mSensorUnderTest = SensorCtsHelper.getSensor(context, sensorType);
-        mSamplingRateInUs = samplingRateInUs;
-        mReportLatencyInUs = reportLatencyInUs;
-
-        mEventListener = new TestSensorListener(mSensorUnderTest, this);
-    }
-
-    /**
-     * {@inheritDoc}
-     * <p>
-     * Available for subclasses to implement if they need access to the raw eventing model.
-     * </p>
-     */
-    @Override
-    public void onAccuracyChanged(Sensor sensor, int accuracy) {}
-
-    /**
-     * {@inheritDoc}
-     * <p>
-     * Available for subclasses to implement if they need access to the raw eventing model.
-     * </p>
-     */
-    @Override
-    public void onSensorChanged(SensorEvent event) {}
-
-    /**
-     * {@inheritDoc}
-     * <p>
-     * Available for subclasses to implement if they need access to the raw eventing model.
-     * </p>
-     */
-    @Override
-    public void onFlushCompleted(Sensor sensor) {}
-
-    /**
-     * Closes the {@link SensorManagerTestVerifier} and unregister the listener.
-     */
-    @Override
-    public void close() {
-        this.unregisterListener();
-        mEventListener = null;
-    }
-
-    /**
-     * Get the sensor under test.
-     */
-    public Sensor getUnderlyingSensor() {
-        return mSensorUnderTest;
-    }
-
-    /**
-     * Register the
-     * @param debugInfo
-     */
-    public void registerListener(String debugInfo) {
-        boolean result = mSensorManager.registerListener(
-                mEventListener,
-                mSensorUnderTest,
-                mSamplingRateInUs,
-                mReportLatencyInUs);
-        String message = SensorCtsHelper.formatAssertionMessage(
-                "registerListener",
-                mSensorUnderTest,
-                debugInfo);
-        Assert.assertTrue(message, result);
-    }
-
-    public void registerListener() {
-        this.registerListener("");
-    }
-
-    public void unregisterListener() {
-        mSensorManager.unregisterListener(mEventListener, mSensorUnderTest);
-    }
-
-    public TestSensorEvent[] getEvents(int count, String debugInfo) {
-        mEventListener.waitForEvents(count, debugInfo);
-        TestSensorEvent[] events = mEventListener.getAllEvents();
-        mEventListener.clearEvents();
-
-        return events;
-    }
-
-    public TestSensorEvent[] getEvents(int count) {
-        return this.getEvents(count, "");
-    }
-
-    public TestSensorEvent[] getQueuedEvents() {
-        return mEventListener.getAllEvents();
-    }
-
-    public TestSensorEvent[] collectEvents(int eventCount, String debugInfo) {
-        this.registerListener(debugInfo);
-        TestSensorEvent[] events = this.getEvents(eventCount, debugInfo);
-        this.unregisterListener();
-
-        return events;
-    }
-
-    public TestSensorEvent[] collectEvents(int eventCount) {
-        return this.collectEvents(eventCount, "");
-    }
-
-    public void startFlush() {
-        String message = SensorCtsHelper.formatAssertionMessage(
-                "Flush",
-                mSensorUnderTest,
-                "" /* format */);
-        Assert.assertTrue(message, mSensorManager.flush(mEventListener));
-    }
-
-    public void waitForFlush() throws InterruptedException {
-        mEventListener.waitForFlushComplete();
-    }
-
-    public void flush() throws InterruptedException {
-        this.startFlush();
-        this.waitForFlush();
-    }
-
-    /**
-     * Definition of support test classes.
-     */
-    private class TestSensorListener implements SensorEventListener2 {
-        private final Sensor mSensorUnderTest;
-        private final SensorEventListener2 mListener;
-
-        private final ConcurrentLinkedDeque<TestSensorEvent> mSensorEventsList =
-                new ConcurrentLinkedDeque<TestSensorEvent>();
-
-        private volatile CountDownLatch mEventLatch;
-        private volatile CountDownLatch mFlushLatch = new CountDownLatch(1);
-
-        public TestSensorListener(Sensor sensor, SensorEventListener2 listener) {
-            if(sensor == null) {
-                throw new InvalidParameterException("sensor cannot be null");
-            }
-            if(listener == null) {
-                throw new InvalidParameterException("listener cannot be null");
-            }
-            mSensorUnderTest = sensor;
-            mListener = listener;
-        }
-
-        @Override
-        public void onSensorChanged(SensorEvent event) {
-            // copy the event because there is no better way to do this in the platform
-            mSensorEventsList.addLast(new TestSensorEvent(event));
-            if(mEventLatch != null) {
-                mEventLatch.countDown();
-            }
-            mListener.onSensorChanged(event);
-        }
-
-        @Override
-        public void onAccuracyChanged(Sensor sensor, int accuracy) {
-            mListener.onAccuracyChanged(sensor, accuracy);
-        }
-
-        @Override
-        public void onFlushCompleted(Sensor sensor) {
-            CountDownLatch latch = mFlushLatch;
-            mFlushLatch = new CountDownLatch(1);
-            if(latch != null) {
-                latch.countDown();
-            }
-            mListener.onFlushCompleted(sensor);
-        }
-
-        public void waitForFlushComplete() throws InterruptedException {
-            CountDownLatch latch = mFlushLatch;
-            if(latch != null) {
-                String message = SensorCtsHelper.formatAssertionMessage(
-                        "WaitForFlush",
-                        mSensorUnderTest,
-                        "" /* format */);
-                Assert.assertTrue(message, latch.await(WAIT_TIMEOUT_IN_SECONDS, TimeUnit.SECONDS));
-            }
-        }
-
-        public void waitForEvents(int eventCount, String timeoutInfo) {
-            mEventLatch = new CountDownLatch(eventCount);
-            this.clearEvents();
-            try {
-                boolean awaitCompleted = mEventLatch.await(WAIT_TIMEOUT_IN_SECONDS, TimeUnit.SECONDS);
-                // TODO: can we collect bug reports on error based only if needed? env var?
-
-                String message = SensorCtsHelper.formatAssertionMessage(
-                        "WaitForEvents",
-                        mSensorUnderTest,
-                        "count:%d, available:%d, %s",
-                        eventCount,
-                        mSensorEventsList.size(),
-                        timeoutInfo);
-                Assert.assertTrue(message, awaitCompleted);
-            } catch(InterruptedException e) {
-            } finally {
-                mEventLatch = null;
-            }
-        }
-
-        public TestSensorEvent[] getAllEvents() {
-            return mSensorEventsList.toArray(new TestSensorEvent[0]);
-        }
-
-        public void clearEvents() {
-            mSensorEventsList.clear();
-        }
-    }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorNotSupportedException.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorNotSupportedException.java
index 4c413d7..e727092 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorNotSupportedException.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorNotSupportedException.java
@@ -16,16 +16,65 @@
 
 package android.hardware.cts.helpers;
 
+import android.hardware.Sensor;
+
 /**
  * Exception that indicates that a given sensor is not supported in the device.
- * This exception can be caught in tests to safely ignore test cases that are not necessary in a
- * given environment.
  */
-public class SensorNotSupportedException extends RuntimeException {
+public class SensorNotSupportedException extends SensorTestStateNotSupportedException {
     public SensorNotSupportedException(int sensorType) {
-        super(String.format(
-                "Sensor '%s' of type %d is not supported.",
-                SensorTestInformation.getSensorName(sensorType),
-                sensorType));
+        super("Sensor '%s' of type %d is not supported.", getSensorName(sensorType), sensorType);
+    }
+
+    private static String getSensorName(int sensorType) {
+        return String.format("%s (%d)", getSimpleSensorName(sensorType), sensorType);
+    }
+
+    @SuppressWarnings("deprecation")
+    private static String getSimpleSensorName(int sensorType) {
+        switch(sensorType) {
+            case Sensor.TYPE_ACCELEROMETER:
+                return "Accelerometer";
+            case Sensor.TYPE_MAGNETIC_FIELD:
+                return "Magnetic Field";
+            case Sensor.TYPE_ORIENTATION:
+                return "Orientation";
+            case Sensor.TYPE_GYROSCOPE:
+                return "Gyroscope";
+            case Sensor.TYPE_LIGHT:
+                return "Light";
+            case Sensor.TYPE_PRESSURE:
+                return "Pressure";
+            case Sensor.TYPE_TEMPERATURE:
+                return "Temperature";
+            case Sensor.TYPE_PROXIMITY:
+                return "Proximity";
+            case Sensor.TYPE_GRAVITY:
+                return "Gravity";
+            case Sensor.TYPE_LINEAR_ACCELERATION:
+                return "Linear Acceleration";
+            case Sensor.TYPE_ROTATION_VECTOR:
+                return "Rotation Vector";
+            case Sensor.TYPE_RELATIVE_HUMIDITY:
+                return "Relative Humidity";
+            case Sensor.TYPE_AMBIENT_TEMPERATURE:
+                return "Ambient Temperature";
+            case Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED:
+                return "Magnetic Field Uncalibrated";
+            case Sensor.TYPE_GAME_ROTATION_VECTOR:
+                return "Game Rotation Vector";
+            case Sensor.TYPE_GYROSCOPE_UNCALIBRATED:
+                return "Gyroscope Uncalibrated";
+            case Sensor.TYPE_SIGNIFICANT_MOTION:
+                return "Significant Motion";
+            case Sensor.TYPE_STEP_DETECTOR:
+                return "Step Detector";
+            case Sensor.TYPE_STEP_COUNTER:
+                return "Step Counter";
+            case Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR:
+                return "Geomagnetic Rotation Vector";
+            default:
+                return "<Unknown>";
+        }
     }
 }
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorStats.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorStats.java
new file mode 100644
index 0000000..7be6c0c
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorStats.java
@@ -0,0 +1,198 @@
+/*
+ * 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.cts.helpers;
+
+import android.hardware.Sensor;
+import android.hardware.cts.helpers.sensoroperations.ISensorOperation;
+import android.util.Log;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * Class used to store stats related to {@link ISensorOperation}s.  Sensor stats may be linked
+ * together so that they form a tree.
+ */
+public class SensorStats {
+    public static final String DELIMITER = "__";
+
+    public static final String FIRST_TIMESTAMP_KEY = "first_timestamp";
+    public static final String LAST_TIMESTAMP_KEY = "last_timestamp";
+    public static final String ERROR = "error";
+    public static final String EVENT_COUNT_KEY = "event_count";
+    public static final String EVENT_GAP_COUNT_KEY = "event_gap_count";
+    public static final String EVENT_GAP_POSITIONS_KEY = "event_gap_positions";
+    public static final String EVENT_OUT_OF_ORDER_COUNT_KEY = "event_out_of_order_count";
+    public static final String EVENT_OUT_OF_ORDER_POSITIONS_KEY = "event_out_of_order_positions";
+    public static final String FREQUENCY_KEY = "frequency";
+    public static final String JITTER_95_PERCENTILE_PERCENT_KEY = "jitter_95_percentile_percent";
+    public static final String MEAN_KEY = "mean";
+    public static final String STANDARD_DEVIATION_KEY = "standard_deviation";
+    public static final String MAGNITUDE_KEY = "magnitude";
+
+    private final Map<String, Object> mValues = new HashMap<String, Object>();
+    private final Map<String, SensorStats> mSensorStats = new HashMap<String, SensorStats>();
+
+    /**
+     * Add a value.
+     *
+     * @param key the key.
+     * @param value the value as an {@link Object}.
+     */
+    public synchronized void addValue(String key, Object value) {
+        if (value == null) {
+            return;
+        }
+        mValues.put(key, value);
+    }
+
+    /**
+     * Add a nested {@link SensorStats}. This is useful for keeping track of stats in a
+     * {@link ISensorOperation} tree.
+     *
+     * @param key the key
+     * @param stats the sub {@link SensorStats} object.
+     */
+    public synchronized void addSensorStats(String key, SensorStats stats) {
+        if (stats == null) {
+            return;
+        }
+        mSensorStats.put(key, stats);
+    }
+
+    /**
+     * Get the keys from the values table. Will not get the keys from the nested
+     * {@link SensorStats}.
+     */
+    public synchronized Set<String> getKeys() {
+        return mValues.keySet();
+    }
+
+    /**
+     * Get a value from the values table. Will not attempt to get values from nested
+     * {@link SensorStats}.
+     */
+    public synchronized Object getValue(String key) {
+        return mValues.get(key);
+    }
+
+    /**
+     * Flattens the map and all sub {@link SensorStats} objects. Keys will be flattened using
+     * {@value #DELIMITER}. For example, if a sub {@link SensorStats} is added with key
+     * {@code "key1"} containing the key value pair {@code ("key2", "value")}, the flattened map
+     * will contain the entry {@code ("key1__key2", "value")}.
+     *
+     * @return a {@link Map} containing all stats from the value and sub {@link SensorStats}.
+     */
+    public synchronized Map<String, Object> flatten() {
+        final Map<String, Object> flattenedMap = new HashMap<String, Object>(mValues);
+        for (Entry<String, SensorStats> statsEntry : mSensorStats.entrySet()) {
+            for (Entry<String, Object> valueEntry : statsEntry.getValue().flatten().entrySet()) {
+                String key = statsEntry.getKey() + DELIMITER + valueEntry.getKey();
+                flattenedMap.put(key, valueEntry.getValue());
+            }
+        }
+        return flattenedMap;
+    }
+
+    /**
+     * Utility method to log the stats to the logcat.
+     */
+    public static void logStats(String tag, SensorStats stats) {
+        final Map<String, Object> flattened = stats.flatten();
+        for (String key : getSortedKeys(flattened)) {
+            Object value = flattened.get(key);
+            Log.v(tag, String.format("%s: %s", key, getValueString(value)));
+        }
+    }
+
+    /**
+     * Utility method to log the stats to a file. Will overwrite the file if it already exists.
+     */
+    public static void logStatsToFile(String fileName, SensorStats stats) throws IOException {
+        File statsDirectory = SensorCtsHelper.getSensorTestDataDirectory("stats/");
+        File logFile = new File(statsDirectory, fileName);
+        final BufferedWriter writer =
+                new BufferedWriter(new FileWriter(logFile, false /* append */));
+        final Map<String, Object> flattened = stats.flatten();
+        try {
+            for (String key : getSortedKeys(flattened)) {
+                Object value = flattened.get(key);
+                writer.write(String.format("%s: %s\n", key, getValueString(value)));
+            }
+        } finally {
+            writer.flush();
+            writer.close();
+        }
+    }
+
+    /**
+     * Provides a sanitized sensor name, that can be used in file names.
+     * See {@link #logStatsToFile(String, SensorStats)}.
+     */
+    public static String getSanitizedSensorName(Sensor sensor) throws IOException {
+        String sensorType = sensor.getStringType();
+        String sanitizedSensorType = sensorType.replaceAll("[^a-zA-Z0-9_\\-]", "_");
+        if (sanitizedSensorType.matches("_*")) {
+            throw new IOException("Unable to sanitize sensor type (" + sensorType + "). This is a"
+                    + " 'test framework' issue and the sanitation routine must be fixed.");
+        }
+        return sanitizedSensorType;
+    }
+
+    private static List<String> getSortedKeys(Map<String, Object> flattenedStats) {
+        List<String> keys = new ArrayList<String>(flattenedStats.keySet());
+        Collections.sort(keys);
+        return keys;
+    }
+
+    private static String getValueString(Object value) {
+        if (value == null) {
+            return "";
+        } else if (value instanceof boolean[]) {
+            return Arrays.toString((boolean[]) value);
+        } else if (value instanceof byte[]) {
+            return Arrays.toString((byte[]) value);
+        } else if (value instanceof char[]) {
+            return Arrays.toString((char[]) value);
+        } else if (value instanceof double[]) {
+            return Arrays.toString((double[]) value);
+        } else if (value instanceof float[]) {
+            return Arrays.toString((float[]) value);
+        } else if (value instanceof int[]) {
+            return Arrays.toString((int[]) value);
+        } else if (value instanceof long[]) {
+            return Arrays.toString((long[]) value);
+        } else if (value instanceof short[]) {
+            return Arrays.toString((short[]) value);
+        } else if (value instanceof Object[]) {
+            return Arrays.toString((Object[]) value);
+        } else {
+            return value.toString();
+        }
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorStatsTest.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorStatsTest.java
new file mode 100644
index 0000000..8ba0f41
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorStatsTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.cts.helpers;
+
+import junit.framework.TestCase;
+
+import java.util.Map;
+
+/**
+ * Unit tests for the {@link SensorStats} class.
+ */
+public class SensorStatsTest extends TestCase {
+
+    /**
+     * Test that {@link SensorStats#flatten()} works correctly.
+     */
+    public void testFlatten() {
+        SensorStats stats = new SensorStats();
+        stats.addValue("value0", 0);
+        stats.addValue("value1", 1);
+
+        SensorStats subStats = new SensorStats();
+        subStats.addValue("value2", 2);
+        subStats.addValue("value3", 3);
+
+        SensorStats subSubStats = new SensorStats();
+        subSubStats.addValue("value4", 4);
+        subSubStats.addValue("value5", 5);
+
+        subStats.addSensorStats("stats1", subSubStats);
+        stats.addSensorStats("stats0", subStats);
+
+        // Add empty stats, expect no value in flattened map
+        stats.addSensorStats("stats2", new SensorStats());
+
+        // Add null values, expect no value in flattened map
+        stats.addSensorStats("stats3", null);
+        stats.addValue("value6", null);
+
+        Map<String, Object> flattened = stats.flatten();
+
+        assertEquals(6, flattened.size());
+        assertEquals(0, (int) (Integer) flattened.get("value0"));
+        assertEquals(1, (int) (Integer) flattened.get("value1"));
+        assertEquals(2, (int) (Integer) flattened.get("stats0__value2"));
+        assertEquals(3, (int) (Integer) flattened.get("stats0__value3"));
+        assertEquals(4, (int) (Integer) flattened.get("stats0__stats1__value4"));
+        assertEquals(5, (int) (Integer) flattened.get("stats0__stats1__value5"));
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestCase.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestCase.java
deleted file mode 100644
index 4bd0eed..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestCase.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.cts.helpers;
-
-import android.test.AndroidTestCase;
-
-import android.util.Log;
-
-/**
- * Test Case class that handles gracefully sensors that are not available in the device.
- */
-public abstract class SensorTestCase extends AndroidTestCase {
-    protected final String LOG_TAG = "TestRunner";
-
-    protected SensorTestCase() {}
-
-    @Override
-    public void runTest() throws Throwable {
-        try {
-            super.runTest();
-        } catch (SensorNotSupportedException e) {
-            // the sensor is not supported/available in the device, log a warning and skip the test
-            Log.w(LOG_TAG, e.getMessage());
-        }
-    }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestInformation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestInformation.java
deleted file mode 100644
index 90e0706..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestInformation.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.cts.helpers;
-
-import android.content.Context;
-
-import android.hardware.Sensor;
-
-import java.security.InvalidParameterException;
-
-/**
- * A 'property' bag of sensor information used for testing purposes.
- */
-public class SensorTestInformation {
-    private SensorTestInformation() {}
-
-    public static int getAxisCount(int sensorType) {
-        switch(sensorType) {
-            case Sensor.TYPE_ACCELEROMETER:
-                return 3;
-            case Sensor.TYPE_MAGNETIC_FIELD:
-                return 3;
-//            case Sensor.TYPE_ORIENTATION:
-//                return "Orientation";
-            case Sensor.TYPE_GYROSCOPE:
-                return 3;
-//            case Sensor.TYPE_LIGHT:
-//                return "Light";
-//            case Sensor.TYPE_PRESSURE:
-//                return "Pressure";
-//            case Sensor.TYPE_TEMPERATURE:
-//                return "Temperature";
-//            case Sensor.TYPE_PROXIMITY:
-//                return "Proximity";
-            case Sensor.TYPE_GRAVITY:
-                return 3;
-            case Sensor.TYPE_LINEAR_ACCELERATION:
-                return 3;
-//            case Sensor.TYPE_ROTATION_VECTOR:
-//                return "Rotation Vector";
-//            case Sensor.TYPE_RELATIVE_HUMIDITY:
-//                return "Relative Humidity";
-//            case Sensor.TYPE_AMBIENT_TEMPERATURE:
-//                return "Ambient Temperature";
-//            case Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED:
-//                return "Magnetic Field Uncalibrated";
-//            case Sensor.TYPE_GAME_ROTATION_VECTOR:
-//                return "Game Rotation Vector";
-//            case Sensor.TYPE_GYROSCOPE_UNCALIBRATED:
-//                return "Gyroscope Uncalibrated";
-//            case Sensor.TYPE_SIGNIFICANT_MOTION:
-//                return "Significant Motion";
-//            case Sensor.TYPE_STEP_DETECTOR:
-//                return "Step Detector";
-//            case Sensor.TYPE_STEP_COUNTER:
-//                return "Step Counter";
-//            case Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR:
-//                return "Geomagnetic Rotation Vector";
-            default:
-                throw new InvalidParameterException(
-                        String.format("Invalid sensorType:%d. Unable to find axis count.", sensorType));
-        }
-    }
-
-    public static String getSensorName(int sensorType) {
-        String name;
-        switch(sensorType) {
-            case Sensor.TYPE_ACCELEROMETER:
-                name = "Accelerometer";
-                break;
-            case Sensor.TYPE_MAGNETIC_FIELD:
-                name = "Magnetic Field";
-                break;
-            case Sensor.TYPE_ORIENTATION:
-                name = "Orientation";
-                break;
-            case Sensor.TYPE_GYROSCOPE:
-                name = "Gyroscope";
-                break;
-            case Sensor.TYPE_LIGHT:
-                name = "Light";
-                break;
-            case Sensor.TYPE_PRESSURE:
-                name = "Pressure";
-                break;
-            case Sensor.TYPE_TEMPERATURE:
-                name = "Temperature";
-                break;
-            case Sensor.TYPE_PROXIMITY:
-                name = "Proximity";
-                break;
-            case Sensor.TYPE_GRAVITY:
-                name = "Gravity";
-                break;
-            case Sensor.TYPE_LINEAR_ACCELERATION:
-                name = "Linear Acceleration";
-                break;
-            case Sensor.TYPE_ROTATION_VECTOR:
-                name = "Rotation Vector";
-                break;
-            case Sensor.TYPE_RELATIVE_HUMIDITY:
-                name = "Relative Humidity";
-                break;
-            case Sensor.TYPE_AMBIENT_TEMPERATURE:
-                name = "Ambient Temperature";
-                break;
-            case Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED:
-                name = "Magnetic Field Uncalibrated";
-                break;
-            case Sensor.TYPE_GAME_ROTATION_VECTOR:
-                name = "Game Rotation Vector";
-                break;
-            case Sensor.TYPE_GYROSCOPE_UNCALIBRATED:
-                name = "Gyroscope Uncalibrated";
-                break;
-            case Sensor.TYPE_SIGNIFICANT_MOTION:
-                name = "Significant Motion";
-                break;
-            case Sensor.TYPE_STEP_DETECTOR:
-                name = "Step Detector";
-                break;
-            case Sensor.TYPE_STEP_COUNTER:
-                name = "Step Counter";
-                break;
-            case Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR:
-                name = "Geomagnetic Rotation Vector";
-                break;
-            default:
-                name = "<Unknown>";
-        }
-        return String.format("%s (%d)", name, sensorType);
-    }
-
-    public static int getMaxSamplingRateInUs(Context context, int sensorType) {
-        Sensor sensor = SensorCtsHelper.getSensor(context, sensorType);
-        return sensor.getMinDelay();
-    }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestOperation.java
deleted file mode 100644
index 902c8024..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestOperation.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.cts.helpers;
-
-import junit.framework.Assert;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * Base test class that supports a basic test operation performed in a sensor.
- * The class follows a command patter as a base for its work.
- *
- * Remarks:
- * - The class wraps verifications and test checks that are needed to verify the operation.
- * - The operation runs in a background thread where it performs the bulk of its work.
- */
-public abstract class SensorTestOperation {
-    private final SensorTestExceptionHandler mExceptionHandler = new SensorTestExceptionHandler();
-
-    protected final String LOG_TAG = "TestRunner";
-    protected final long WAIT_TIMEOUT_IN_MILLISECONDS =
-            TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES);
-
-    private Thread mThread;
-
-    protected int mIterationCount;
-
-    /**
-     * Public API definition.
-     */
-    public synchronized void start() throws Throwable {
-        if(mThread != null) {
-            throw new IllegalStateException("The operation has already been started.");
-        }
-
-        mThread = new Thread() {
-            @Override
-            public void run() {
-                try {
-                    doWork();
-                } catch (Throwable e) {
-                    // log the exception so it can be sent back to the appropriate test thread
-                    this.getUncaughtExceptionHandler().uncaughtException(this, e);
-                }
-            }
-        };
-
-        ++mIterationCount;
-        mThread.setUncaughtExceptionHandler(mExceptionHandler);
-        mThread.start();
-    }
-
-    public synchronized void waitForCompletion() throws Throwable {
-        if(mThread == null) {
-            // let a wait on a stopped operation to be no-op
-            return;
-        }
-        mThread.join(WAIT_TIMEOUT_IN_MILLISECONDS);
-        if(mThread.isAlive()) {
-            // the test is hung so collect the state of the system and fail
-            String operationName = this.getClass().getSimpleName();
-            String message = String.format(
-                    "%s hung. %s. BugReport collected at: %s",
-                    operationName,
-                    this.toString(),
-                    SensorCtsHelper.collectBugreport(operationName));
-            Assert.fail(message);
-        }
-        mThread = null;
-        mExceptionHandler.rethrow();
-    }
-
-    public void execute() throws Throwable {
-        this.start();
-        this.waitForCompletion();
-    }
-
-    @Override
-    public String toString() {
-        return String.format("ThreadId:%d, Iteration:%d", mThread.getId(), mIterationCount);
-    }
-
-    /**
-     * Subclasses implement this method to perform the work associated with the operation they
-     * represent.
-     */
-    protected abstract void doWork() throws Throwable;
-
-    /**
-     * Private helpers.
-     */
-    private class SensorTestExceptionHandler implements Thread.UncaughtExceptionHandler {
-        private final Object mLock = new Object();
-
-        private Throwable mThrowable;
-
-        @Override
-        public void uncaughtException(Thread thread, Throwable throwable) {
-            synchronized(mLock) {
-                // the fist exception is in general the one that is more interesting
-                if(mThrowable != null) {
-                    return;
-                }
-                mThrowable = throwable;
-            }
-        }
-
-        public void rethrow() throws Throwable {
-            Throwable throwable;
-            synchronized(mLock) {
-                throwable = mThrowable;
-                mThrowable = null;
-            }
-            if(throwable != null) {
-                throw throwable;
-            }
-        }
-    }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestStateNotSupportedException.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestStateNotSupportedException.java
new file mode 100644
index 0000000..435632d
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorTestStateNotSupportedException.java
@@ -0,0 +1,32 @@
+/*
+ * 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.cts.helpers;
+
+/**
+ * Exception that indicates that a given state in sensor tests is not supported in the device.
+ * This exception can be caught in tests to safely ignore test cases that are not necessary in a
+ * given environment.
+ */
+public class SensorTestStateNotSupportedException extends RuntimeException {
+    public SensorTestStateNotSupportedException(String format, Object ... params) {
+        super(String.format(format, params));
+    }
+
+    public SensorTestStateNotSupportedException(String message) {
+        super(message);
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorVerificationHelper.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorVerificationHelper.java
deleted file mode 100644
index d1013e0..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorVerificationHelper.java
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.hardware.cts.helpers;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Set of static helper methods to verify sensor CTS tests.
- */
-public class SensorVerificationHelper {
-
-    private static final int MESSAGE_LENGTH = 3;
-
-    /**
-     * Class which holds results from the verification.
-     */
-    public static class VerificationResult {
-        private boolean mFailed = false;
-        private String mMessage = null;
-        private Map<String, Object> mValueMap = new HashMap<String, Object>();
-
-        public void fail(String messageFormat, Object ... args) {
-            mFailed = true;
-            mMessage = String.format(messageFormat, args);
-        }
-
-        public boolean isFailed() {
-            return mFailed;
-        }
-
-        public String getFailureMessage() {
-            return mMessage;
-        }
-
-        public void putValue(String key, Object value) {
-            mValueMap.put(key, value);
-        }
-
-        public Object getValue(String key) {
-            return mValueMap.get(key);
-        }
-    }
-
-    /**
-     * Private constructor for static class.
-     */
-    private SensorVerificationHelper() {}
-
-    /**
-     * Verify that the events are in the correct order.
-     *
-     * @param events The array of {@link TestSensorEvent}
-     * @return a {@link VerificationResult} containing the verification info including the keys
-     *     "count" which is the number of events out of order and "positions" which contains an
-     *     array of indexes that were out of order.
-     * @throws IllegalStateException if number of events less than 1.
-     */
-    public static VerificationResult verifyEventOrdering(TestSensorEvent[] events) {
-        VerificationResult result = new VerificationResult();
-        List<Integer> indices = new ArrayList<Integer>();
-        long maxTimestamp = events[0].timestamp;
-        for (int i = 1; i < events.length; i++) {
-            long currentTimestamp = events[i].timestamp;
-            if (currentTimestamp < maxTimestamp) {
-                indices.add(i);
-            } else if (currentTimestamp > maxTimestamp) {
-                maxTimestamp = currentTimestamp;
-            }
-        }
-
-        result.putValue("count", indices.size());
-        result.putValue("positions", indices);
-
-        if (indices.size() > 0) {
-            StringBuilder sb = new StringBuilder();
-            sb.append(indices.size()).append(" events out of order: ");
-            for (int i = 0; i < Math.min(indices.size(), MESSAGE_LENGTH); i++) {
-                int index = indices.get(i);
-                sb.append(String.format("position=%d, previous=%d, timestamp=%d; ", index,
-                        events[index - 1].timestamp, events[index].timestamp));
-            }
-            if (indices.size() > MESSAGE_LENGTH) {
-                sb.append(indices.size() - MESSAGE_LENGTH).append(" more");
-            } else {
-                // Delete the "; "
-                sb.delete(sb.length() - 2, sb.length());
-            }
-
-            result.fail(sb.toString());
-        }
-
-        return result;
-    }
-
-    /**
-     * Verify that the sensor frequency matches the expected frequency.
-     *
-     * @param events The array of {@link TestSensorEvent}
-     * @param expected The expected frequency in Hz
-     * @param threshold The acceptable margin of error in Hz
-     * @return a {@link VerificationResult} containing the verification info including the key
-     *     "frequency" which is the computed frequency of the events in Hz.
-     * @throws IllegalStateException if number of events less than 1.
-     */
-    public static VerificationResult verifyFrequency(TestSensorEvent[] events, double expected,
-            double threshold) {
-        VerificationResult result = new VerificationResult();
-        List<Long> timestampDelayValues = SensorCtsHelper.getTimestampDelayValues(events);
-        double frequency = SensorCtsHelper.getFrequency(
-                SensorCtsHelper.getMean(timestampDelayValues), TimeUnit.NANOSECONDS);
-        result.putValue("frequency", frequency);
-
-        if (Math.abs(frequency - expected) > threshold) {
-            result.fail("Frequency out of range: frequency=%.2fHz, expected=%.2f+/-%.2fHz",
-                    frequency, expected, threshold);
-        }
-        return result;
-    }
-
-    /**
-     * Verify that the jitter is in an acceptable range
-     *
-     * @param events The array of {@link TestSensorEvent}
-     * @param threshold The acceptable margin of error in nanoseconds
-     * @return a {@link VerificationResult} containing the verification info including the keys
-     *     "jitter" which is the list of computed jitter values and "jitter95Percentile" which is
-     *     95th percentile of the jitter values.
-     * @throws IllegalStateException if number of events less than 2.
-     */
-    public static VerificationResult verifyJitter(TestSensorEvent[] events, double threshold) {
-        VerificationResult result = new VerificationResult();
-        List<Double> jitterValues = SensorCtsHelper.getJitterValues(events);
-        double jitter95Percentile = SensorCtsHelper.get95PercentileValue(jitterValues);
-        result.putValue("jitter", jitterValues);
-        result.putValue("jitter95Percentile", jitter95Percentile);
-
-        if (jitter95Percentile > threshold) {
-            result.fail("Jitter out of range: jitter at 95th percentile=%.0fns, expected=<%.0fns",
-                    jitter95Percentile, threshold);
-        }
-        return result;
-    }
-
-    /**
-     * Verify that the means matches the expected measurement.
-     *
-     * @param events The array of {@link TestSensorEvent}
-     * @param expected The array of expected values
-     * @param threshold The array of thresholds
-     * @return a {@link VerificationResult} containing the verification info including the key
-     *     "mean" which is the computed means for each value of the sensor.
-     * @throws IllegalStateException if number of events less than 1.
-     */
-    public static VerificationResult verifyMean(TestSensorEvent[] events, double[] expected,
-            double[] threshold) {
-        VerificationResult result = new VerificationResult();
-        double[] means = SensorCtsHelper.getMeans(events);
-        result.putValue("means", means);
-
-        boolean failed = false;
-        StringBuilder meanSb = new StringBuilder();
-        StringBuilder expectedSb = new StringBuilder();
-
-        if (means.length > 1) {
-            meanSb.append("(");
-            expectedSb.append("(");
-        }
-        for (int i = 0; i < means.length && !failed; i++) {
-            if (Math.abs(means[i] - expected[i]) > threshold[i]) {
-                failed = true;
-            }
-            meanSb.append(String.format("%.2f", means[i]));
-            if (i != means.length - 1) meanSb.append(", ");
-            expectedSb.append(String.format("%.2f+/-%.2f", expected[i], threshold[i]));
-            if (i != means.length - 1) expectedSb.append(", ");
-        }
-        if (means.length > 1) {
-            meanSb.append(")");
-            expectedSb.append(")");
-        }
-
-        if (failed) {
-            result.fail("Mean out of range: mean=%s, expected=%s",
-                    meanSb.toString(), expectedSb.toString());
-        }
-        return result;
-    }
-
-    /**
-     * Verify that the mean of the magnitude of the sensors vector is within the expected range.
-     *
-     * @param events The array of {@link TestSensorEvent}
-     * @param expected The expected value
-     * @param threshold The threshold
-     * @return a {@link VerificationResult} containing the verification info including the key
-     *     "magnitude" which is the mean of the computed magnitude of the sensor values.
-     * @throws IllegalStateException if number of events less than 1.
-     */
-    public static VerificationResult verifyMagnitude(TestSensorEvent[] events, double expected,
-            double threshold) {
-        VerificationResult result = new VerificationResult();
-        Collection<Double> magnitudes = new ArrayList<Double>(events.length);
-
-        for (TestSensorEvent event : events) {
-            double norm = 0;
-            for (int i = 0; i < event.values.length; i++) {
-                norm += event.values[i] * event.values[i];
-            }
-            magnitudes.add(Math.sqrt(norm));
-        }
-
-        double mean = SensorCtsHelper.getMean(magnitudes);
-        result.putValue("magnitude", mean);
-
-        if (Math.abs(mean - expected) > threshold) {
-            result.fail(String.format("Magnitude mean out of range: mean=%s, expected=%s+/-%s",
-                    mean, expected, threshold));
-        }
-        return result;
-    }
-
-    /**
-     * Verify that the sign of each of the sensor values is correct.
-     * <p>
-     * If the value of the measurement is in [-threshold, threshold], the sign is considered 0. If
-     * it is less than -threshold, it is considered -1. If it is greater than threshold, it is
-     * considered 1.
-     * </p>
-     *
-     * @param events
-     * @param threshold The threshold that needs to be crossed to consider a measurement nonzero
-     * @return a {@link VerificationResult} containing the verification info including the key
-     *     "mean" which is the computed means for each value of the sensor.
-     * @throws IllegalStateException if number of events less than 1.
-     */
-    public static VerificationResult verifySignum(TestSensorEvent[] events, int[] expected,
-            double[] threshold) {
-        VerificationResult result = new VerificationResult();
-        for (int i = 0; i < expected.length; i++) {
-            if (!(expected[i] == -1 || expected[i] == 0 || expected[i] == 1)) {
-                throw new IllegalArgumentException("Expected value must be -1, 0, or 1");
-            }
-        }
-        double[] means = SensorCtsHelper.getMeans(events);
-        result.putValue("means", means);
-
-        boolean failed = false;
-        StringBuilder meanSb = new StringBuilder();
-        StringBuilder expectedSb = new StringBuilder();
-
-        if (means.length > 1) {
-            meanSb.append("(");
-            expectedSb.append("(");
-        }
-        for (int i = 0; i < means.length; i++) {
-            meanSb.append(String.format("%.2f", means[i]));
-            if (i != means.length - 1) meanSb.append(", ");
-
-            if (expected[i] == 0) {
-                if (Math.abs(means[i]) > threshold[i]) {
-                    failed = true;
-                }
-                expectedSb.append(String.format("[%.2f, %.2f]", -threshold[i], threshold[i]));
-            } else {
-                if (expected[i] > 0) {
-                    if (means[i] <= threshold[i]) {
-                        failed = true;
-                    }
-                    expectedSb.append(String.format("(%.2f, inf)", threshold[i]));
-                } else {
-                    if (means[i] >= -1 * threshold[i]) {
-                        failed = true;
-                    }
-                    expectedSb.append(String.format("(-inf, %.2f)", -1 * threshold[i]));
-                }
-            }
-            if (i != means.length - 1) expectedSb.append(", ");
-        }
-        if (means.length > 1) {
-            meanSb.append(")");
-            expectedSb.append(")");
-        }
-
-        if (failed) {
-            result.fail("Signum out of range: mean=%s, expected=%s",
-                    meanSb.toString(), expectedSb.toString());
-        }
-        return result;
-    }
-
-    /**
-     * Verify that the standard deviations is within the expected range.
-     *
-     * @param events The array of {@link TestSensorEvent}
-     * @param threshold The array of thresholds
-     * @return a {@link VerificationResult} containing the verification info including the key
-     *     "stddevs" which is the computed standard deviations for each value of the sensor.
-     * @throws IllegalStateException if number of events less than 1.
-     */
-    public static VerificationResult verifyStandardDeviation(TestSensorEvent[] events,
-            double[] threshold) {
-        VerificationResult result = new VerificationResult();
-        double[] standardDeviations = SensorCtsHelper.getStandardDeviations(events);
-        result.putValue("stddevs", standardDeviations);
-
-        boolean failed = false;
-        StringBuilder meanSb = new StringBuilder();
-        StringBuilder expectedSb = new StringBuilder();
-
-        if (standardDeviations.length > 1) {
-            meanSb.append("(");
-            expectedSb.append("(");
-        }
-        for (int i = 0; i < standardDeviations.length && !failed; i++) {
-            if (standardDeviations[i] > threshold[i]) {
-                failed = true;
-            }
-            meanSb.append(String.format("%.2f", standardDeviations[i]));
-            if (i != standardDeviations.length - 1) meanSb.append(", ");
-            expectedSb.append(String.format("0+/-%.2f", threshold[i]));
-            if (i != standardDeviations.length - 1) expectedSb.append(", ");
-        }
-        if (standardDeviations.length > 1) {
-            meanSb.append(")");
-            expectedSb.append(")");
-        }
-
-        if (failed) {
-            result.fail("Standard deviation out of range: mean=%s, expected=%s",
-                    meanSb.toString(), expectedSb.toString());
-        }
-        return result;
-    }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorVerificationHelperTest.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorVerificationHelperTest.java
deleted file mode 100644
index 875fa7f..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorVerificationHelperTest.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * 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.cts.helpers;
-
-import android.hardware.cts.helpers.SensorVerificationHelper.VerificationResult;
-
-import junit.framework.TestCase;
-
-import java.util.List;
-
-/**
- * Unit tests for the {@link SensorVerificationHelper} class.
- */
-public class SensorVerificationHelperTest extends TestCase {
-
-    /**
-     * Test {@link SensorVerificationHelper#verifyEventOrdering(TestSensorEvent[])}.
-     */
-    @SuppressWarnings("unchecked")
-    public void testVerifyEventOrdering() {
-        float[] values = {0, 1, 2, 3, 4};
-
-        long[] timestamps1 = {0, 0, 0, 0, 0};
-        TestSensorEvent[] events1 = getSensorEvents(timestamps1, values);
-        VerificationResult result = SensorVerificationHelper.verifyEventOrdering(events1);
-        assertFalse(result.isFailed());
-        assertEquals(0, result.getValue("count"));
-
-        long[] timestamps2 = {0, 1, 2, 3, 4};
-        TestSensorEvent[] events2 = getSensorEvents(timestamps2, values);
-        result = SensorVerificationHelper.verifyEventOrdering(events2);
-        assertFalse(result.isFailed());
-        assertEquals(0, result.getValue("count"));
-
-        long[] timestamps3 = {0, 2, 1, 3, 4};
-        TestSensorEvent[] events3 = getSensorEvents(timestamps3, values);
-        result = SensorVerificationHelper.verifyEventOrdering(events3);
-        assertTrue(result.isFailed());
-        assertEquals(1, result.getValue("count"));
-        List<Integer> indices = (List<Integer>) result.getValue("positions");
-        assertTrue(indices.contains(2));
-
-        long[] timestamps4 = {4, 0, 1, 2, 3};
-        TestSensorEvent[] events4 = getSensorEvents(timestamps4, values);
-        result = SensorVerificationHelper.verifyEventOrdering(events4);
-        assertTrue(result.isFailed());
-        assertEquals(4, result.getValue("count"));
-        indices = (List<Integer>) result.getValue("positions");
-        assertTrue(indices.contains(1));
-        assertTrue(indices.contains(2));
-        assertTrue(indices.contains(3));
-        assertTrue(indices.contains(4));
-    }
-
-    /**
-     * Test {@link SensorVerificationHelper#verifyFrequency(TestSensorEvent[], double, double)}.
-     */
-    public void testVerifyFrequency() {
-        float[] values = {0, 1, 2, 3, 4};
-        long[] timestamps = {0, 1000000, 2000000, 3000000, 4000000};  // 1000Hz
-        TestSensorEvent[] events = getSensorEvents(timestamps, values);
-
-        VerificationResult result = SensorVerificationHelper.verifyFrequency(events, 1000.0, 1.0);
-        assertFalse(result.isFailed());
-        assertEquals(1000.0, (Double) result.getValue("frequency"), 0.01);
-
-        result = SensorVerificationHelper.verifyFrequency(events, 950.0, 100.0);
-        assertFalse(result.isFailed());
-        assertEquals(1000.0, (Double) result.getValue("frequency"), 0.01);
-
-        result = SensorVerificationHelper.verifyFrequency(events, 1050.0, 100.0);
-        assertFalse(result.isFailed());
-        assertEquals(1000.0, (Double) result.getValue("frequency"), 0.01);
-
-        result = SensorVerificationHelper.verifyFrequency(events, 950.0, 25.0);
-        assertTrue(result.isFailed());
-        assertEquals(1000.0, (Double) result.getValue("frequency"), 0.01);
-    }
-
-    /**
-     * Test {@link SensorVerificationHelper#verifyJitter(TestSensorEvent[], double)}.
-     */
-    public void testVerifyJitter() {
-        final int SAMPLE_SIZE = 100;
-        float[] values = new float[SAMPLE_SIZE];
-        for (int i = 0; i < SAMPLE_SIZE; i++) {
-            values[i] = i;
-        }
-
-        long[] timestamps1 = new long[SAMPLE_SIZE];  // 100 samples at 1000Hz
-        for (int i = 0; i < SAMPLE_SIZE; i++) {
-            timestamps1[i] = i * 100000;
-        }
-        TestSensorEvent[] events1 = getSensorEvents(timestamps1, values);
-        VerificationResult result = SensorVerificationHelper.verifyJitter(events1, 100000);
-        assertFalse(result.isFailed());
-        assertEquals(0.0, (Double) result.getValue("jitter95Percentile"), 0.01);
-
-        long[] timestamps2 = new long[SAMPLE_SIZE];  // 90 samples at 1000Hz, 10 samples at 2000Hz
-        long timestamp = 0;
-        for (int i = 0; i < SAMPLE_SIZE; i++) {
-            timestamps2[i] = timestamp;
-            timestamp += (i % 10 == 0) ? 500000 : 1000000;
-        }
-        TestSensorEvent[] events2 = getSensorEvents(timestamps2, values);
-        result = SensorVerificationHelper.verifyJitter(events2, 100000);
-        assertTrue(result.isFailed());
-        assertNotNull(result.getValue("jitter"));
-        assertNotNull(result.getValue("jitter95Percentile"));
-    }
-
-    /**
-     * Test {@link SensorVerificationHelper#verifyMean(TestSensorEvent[], double[], double[])}.
-     */
-    public void testVerifyMean() {
-        long[] timestamps = {0, 1, 2, 3, 4};
-        float[] values1 = {0, 1, 2, 3, 4};
-        float[] values2 = {1, 2, 3, 4, 5};
-        float[] values3 = {0, 1, 4, 9, 16};
-        TestSensorEvent[] events = getSensorEvents(timestamps, values1, values2, values3);
-
-        double[] expected1 = {2.0, 3.0, 6.0};
-        double[] threshold1 = {0.1, 0.1, 0.1};
-        VerificationResult result = SensorVerificationHelper.verifyMean(events, expected1,
-                threshold1);
-        assertFalse(result.isFailed());
-        double[] means = (double[]) result.getValue("means");
-        assertEquals(2.0, means[0], 0.01);
-        assertEquals(3.0, means[1], 0.01);
-        assertEquals(6.0, means[2], 0.01);
-
-        double[] expected2 = {2.5, 2.5, 5.5};
-        double[] threshold2 = {0.6, 0.6, 0.6};
-        result = SensorVerificationHelper.verifyMean(events, expected2, threshold2);
-        assertFalse(result.isFailed());
-
-        double[] expected3 = {2.5, 2.5, 5.5};
-        double[] threshold3 = {0.1, 0.6, 0.6};
-        result = SensorVerificationHelper.verifyMean(events, expected3, threshold3);
-        assertTrue(result.isFailed());
-
-        double[] expected4 = {2.5, 2.5, 5.5};
-        double[] threshold4 = {0.6, 0.1, 0.6};
-        result = SensorVerificationHelper.verifyMean(events, expected4, threshold4);
-        assertTrue(result.isFailed());
-
-        double[] expected5 = {2.5, 2.5, 5.5};
-        double[] threshold5 = {0.6, 0.6, 0.1};
-        result = SensorVerificationHelper.verifyMean(events, expected5, threshold5);
-        assertTrue(result.isFailed());
-    }
-
-    /**
-     * Test {@link SensorVerificationHelper#verifyMagnitude(TestSensorEvent[], double, double)}.
-     */
-    public void testVerifyMagnitude() {
-        long[] timestamps = {0, 1, 2, 3, 4};
-        float[] values1 = {0, 4, 3, 0, 6};
-        float[] values2 = {3, 0, 4, 0, 0};
-        float[] values3 = {4, 3, 0, 4, 0};
-        TestSensorEvent[] events = getSensorEvents(timestamps, values1, values2, values3);
-
-        double expected = 5.0;
-        double threshold = 0.1;
-        VerificationResult result = SensorVerificationHelper.verifyMagnitude(events, expected,
-                threshold);
-        assertFalse(result.isFailed());
-        assertEquals(5.0, (Double) result.getValue("magnitude"), 0.01);
-
-        expected = 4.5;
-        threshold = 0.6;
-        result = SensorVerificationHelper.verifyMagnitude(events, expected, threshold);
-        assertFalse(result.isFailed());
-
-        expected = 5.5;
-        threshold = 0.6;
-        result = SensorVerificationHelper.verifyMagnitude(events, expected, threshold);
-        assertFalse(result.isFailed());
-
-        expected = 4.5;
-        threshold = 0.1;
-        result = SensorVerificationHelper.verifyMagnitude(events, expected, threshold);
-        assertTrue(result.isFailed());
-
-        expected = 5.5;
-        threshold = 0.1;
-        result = SensorVerificationHelper.verifyMagnitude(events, expected, threshold);
-        assertTrue(result.isFailed());
-    }
-
-    /**
-     * Test {@link SensorVerificationHelper#verifySignum(TestSensorEvent[], int[], double[])}.
-     */
-    public void testVerifySignum() {
-        long[] timestamps = {0};
-        float[][] values = {{1}, {0.2f}, {0}, {-0.2f}, {-1}};
-        TestSensorEvent[] events = getSensorEvents(timestamps, values);
-
-        int[] expected1 = {1, 1, 0, -1, -1};
-        double[] threshold1 = {0.1, 0.1, 0.1, 0.1, 0.1};
-        VerificationResult result = SensorVerificationHelper.verifySignum(events, expected1,
-                threshold1);
-        assertFalse(result.isFailed());
-        assertNotNull(result.getValue("means"));
-
-        int[] expected2 = {1, 0, 0, 0, -1};
-        double[] threshold2 = {0.5, 0.5, 0.5, 0.5, 0.5};
-        result = SensorVerificationHelper.verifySignum(events, expected2, threshold2);
-        assertFalse(result.isFailed());
-
-        int[] expected3 = {0, 1, 0, -1, 0};
-        double[] threshold3 = {1.5, 0.1, 0.1, 0.1, 1.5};
-        result = SensorVerificationHelper.verifySignum(events, expected3, threshold3);
-        assertFalse(result.isFailed());
-
-        int[] expected4 = {1, 0, 0, 0, 1};
-        double[] threshold4 = {0.5, 0.5, 0.5, 0.5, 0.5};
-        result = SensorVerificationHelper.verifySignum(events, expected4, threshold4);
-        assertTrue(result.isFailed());
-
-        int[] expected5 = {-1, 0, 0, 0, -1};
-        double[] threshold5 = {0.5, 0.5, 0.5, 0.5, 0.5};
-        result = SensorVerificationHelper.verifySignum(events, expected5, threshold5);
-        assertTrue(result.isFailed());
-    }
-
-    /**
-     * Test {@link SensorVerificationHelper#verifyStandardDeviation(TestSensorEvent[], double[])}.
-     */
-    public void testVerifyStandardDeviation() {
-        long[] timestamps = {0, 1, 2, 3, 4};
-        float[] values1 = {0, 1, 2, 3, 4};  // sqrt(2.0)
-        float[] values2 = {1, 2, 3, 4, 5};  // sqrt(2.0)
-        float[] values3 = {0, 2, 4, 6, 8};  // sqrt(8.0)
-        TestSensorEvent[] events = getSensorEvents(timestamps, values1, values2, values3);
-
-        double[] threshold1 = {2, 2, 3};
-        VerificationResult result = SensorVerificationHelper.verifyStandardDeviation(events,
-                threshold1);
-        assertFalse(result.isFailed());
-        double[] means = (double[]) result.getValue("stddevs");
-        assertEquals(Math.sqrt(2.0), means[0], 0.01);
-        assertEquals(Math.sqrt(2.0), means[1], 0.01);
-        assertEquals(Math.sqrt(8.0), means[2], 0.01);
-
-        double[] threshold2 = {1, 2, 3};
-        result = SensorVerificationHelper.verifyStandardDeviation(events, threshold2);
-        assertTrue(result.isFailed());
-
-        double[] threshold3 = {2, 1, 3};
-        result = SensorVerificationHelper.verifyStandardDeviation(events, threshold3);
-        assertTrue(result.isFailed());
-
-        double[] threshold4 = {2, 2, 2};
-        result = SensorVerificationHelper.verifyStandardDeviation(events, threshold4);
-        assertTrue(result.isFailed());
-    }
-
-    private TestSensorEvent[] getSensorEvents(long[] timestamps, float[] ... values) {
-        TestSensorEvent[] events = new TestSensorEvent[timestamps.length];
-        for (int i = 0; i < timestamps.length; i++) {
-            float[] eventValues = new float[values.length];
-            for (int j = 0; j < values.length; j++) {
-                eventValues[j] = values[j][i];
-            }
-            events[i] = new TestSensorEvent(null, timestamps[i], 0, eventValues);
-        }
-        return events;
-    }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEnvironment.java b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEnvironment.java
new file mode 100644
index 0000000..8f33f92
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEnvironment.java
@@ -0,0 +1,280 @@
+/*
+ * 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.cts.helpers;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.hardware.cts.helpers.sensoroperations.ISensorOperation;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A class that encapsulates base environment information for the {@link ISensorOperation}.
+ * The environment is self contained and carries its state around all the sensor test framework.
+ */
+public class TestSensorEnvironment {
+    private final Context mContext;
+    private final Sensor mSensor;
+    private final boolean mSensorMightHaveMoreListeners;
+    private final int mSamplingPeriodUs;
+    private final int mMaxReportLatencyUs;
+
+    /**
+     * Constructs an environment for sensor testing.
+     *
+     * @param context The context for the test
+     * @param sensorType The type of the sensor under test
+     * @param samplingPeriodUs The requested collection period for the sensor under test
+     */
+    public TestSensorEnvironment(Context context, int sensorType, int samplingPeriodUs) {
+        this(context, sensorType, false /* sensorMightHaveMoreListeners */, samplingPeriodUs);
+    }
+
+    /**
+     * Constructs an environment for sensor testing.
+     *
+     * @param context The context for the test
+     * @param sensorType The type of the sensor under test
+     * @param samplingPeriodUs The requested collection period for the sensor under test
+     * @param maxReportLatencyUs The requested collection report latency for the sensor under test
+     */
+    public TestSensorEnvironment(
+            Context context,
+            int sensorType,
+            int samplingPeriodUs,
+            int maxReportLatencyUs) {
+        this(context,
+                sensorType,
+                false /* sensorMightHaveMoreListeners */,
+                samplingPeriodUs,
+                maxReportLatencyUs);
+    }
+
+    /**
+     * Constructs an environment for sensor testing.
+     *
+     * @param context The context for the test
+     * @param sensorType The type of the sensor under test
+     * @param sensorMightHaveMoreListeners Whether the sensor under test is acting under load
+     * @param samplingPeriodUs The requested collection period for the sensor under test
+     */
+    public TestSensorEnvironment(
+            Context context,
+            int sensorType,
+            boolean sensorMightHaveMoreListeners,
+            int samplingPeriodUs) {
+        this(context,
+                sensorType,
+                sensorMightHaveMoreListeners,
+                samplingPeriodUs,
+                0 /* maxReportLatencyUs */);
+    }
+
+    /**
+     * Constructs an environment for sensor testing.
+     *
+     * @param context The context for the test
+     * @param sensorType The type of the sensor under test
+     * @param sensorMightHaveMoreListeners Whether the sensor under test is acting under load
+     * @param samplingPeriodUs The requested collection period for the sensor under test
+     * @param maxReportLatencyUs The requested collection report latency for the sensor under test
+     */
+    public TestSensorEnvironment(
+            Context context,
+            int sensorType,
+            boolean sensorMightHaveMoreListeners,
+            int samplingPeriodUs,
+            int maxReportLatencyUs) {
+        this(context,
+                getSensor(context, sensorType),
+                sensorMightHaveMoreListeners,
+                samplingPeriodUs,
+                maxReportLatencyUs);
+    }
+
+    /**
+     * Constructs an environment for sensor testing.
+     *
+     * @param context The context for the test
+     * @param sensor The sensor under test
+     * @param sensorMightHaveMoreListeners Whether the sensor under test is acting under load (this
+     *                                     usually implies that there are several listeners
+     *                                     requesting different sampling periods)
+     * @param samplingPeriodUs The requested collection period for the sensor under test
+     * @param maxReportLatencyUs The requested collection report latency for the sensor under test
+     */
+    public TestSensorEnvironment(
+            Context context,
+            Sensor sensor,
+            boolean sensorMightHaveMoreListeners,
+            int samplingPeriodUs,
+            int maxReportLatencyUs) {
+        mContext = context;
+        mSensor = sensor;
+        mSensorMightHaveMoreListeners = sensorMightHaveMoreListeners;
+        mSamplingPeriodUs = samplingPeriodUs;
+        mMaxReportLatencyUs = maxReportLatencyUs;
+    }
+
+    /**
+     * @return The context instance associated with the test.
+     */
+    public Context getContext() {
+        return mContext;
+    }
+
+    /**
+     * @return The sensor under test.
+     */
+    public Sensor getSensor() {
+        return mSensor;
+    }
+
+    /**
+     * @return The requested collection rate in microseconds.
+     */
+    public int getRequestedSamplingPeriodUs() {
+        return mSamplingPeriodUs;
+    }
+
+    /**
+     * @return The frequency equivalent to {@link #getRequestedSamplingPeriodUs()}.
+     */
+    public double getFrequencyHz() {
+        return SensorCtsHelper.getFrequency(mSamplingPeriodUs, TimeUnit.MICROSECONDS);
+    }
+
+    /**
+     * @return The requested collection max batch report latency in microseconds.
+     */
+    public int getMaxReportLatencyUs() {
+        return mMaxReportLatencyUs;
+    }
+
+    /**
+     * Returns {@code true} if there might be other listeners of {@link #getSensor()} requesting
+     * data at different sampling rates (the rates are unknown); false otherwise.
+     */
+    public boolean isSensorSamplingRateOverloaded() {
+        return mSensorMightHaveMoreListeners && mSamplingPeriodUs != SensorManager.SENSOR_DELAY_FASTEST;
+    }
+
+    /**
+     * Convert the {@link #getRequestedSamplingPeriodUs()} into delay in microseconds.
+     * <p>
+     * The flags SensorManager.SENSOR_DELAY_[GAME|UI|NORMAL] are not supported since the CDD does
+     * not specify values for these flags. The rate is set to the max of
+     * {@link Sensor#getMinDelay()} and the rate given.
+     * </p>
+     */
+    public int getExpectedSamplingPeriodUs() {
+        if (!isDelayRateTestable()) {
+            throw new IllegalArgumentException("rateUs cannot be SENSOR_DELAY_[GAME|UI|NORMAL]");
+        }
+
+        int expectedSamplingPeriodUs = mSamplingPeriodUs;
+        int sensorMaxDelay = mSensor.getMaxDelay();
+        if (sensorMaxDelay > 0) {
+            expectedSamplingPeriodUs = Math.min(expectedSamplingPeriodUs, sensorMaxDelay);
+        }
+
+        return Math.max(expectedSamplingPeriodUs, mSensor.getMinDelay());
+    }
+
+    /**
+     * @return The number of axes in the coordinate system of the sensor under test.
+     */
+    public int getSensorAxesCount() {
+        switch (mSensor.getType()) {
+            case Sensor.TYPE_GYROSCOPE:
+                return 3;
+            default:
+                throw new IllegalStateException("Axes count needs to be defined for sensor type: "
+                        + mSensor.getStringType());
+        }
+    }
+
+    /**
+     * Get the default sensor for a given type.
+     *
+     * @deprecated Used for historical reasons, sensor tests must be written around Sensor objects,
+     * so all sensors of a given type are exercised.
+     */
+    @Deprecated
+    public static Sensor getSensor(Context context, int sensorType) {
+        SensorManager sensorManager =
+                (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
+        if (sensorManager == null) {
+            throw new IllegalStateException("SensorService is not present in the system.");
+        }
+
+        Sensor sensor = sensorManager.getDefaultSensor(sensorType);
+        if(sensor == null) {
+            throw new SensorNotSupportedException(sensorType);
+        }
+        return sensor;
+    }
+
+    /**
+     * @return The maximum latency of a given sensor, on top of {@link #getMaxReportLatencyUs()}.
+     *
+     * NOTE: The latency is defined as the time between the event happens and the time the event is
+     * generated.
+     *
+     * - At time event_time (reported in the sensor event), the physical event happens
+     * - At time event_time + detection_latency, the physical event is detected and the event is
+     *   saved in the hardware fifo
+     * - At time event_time + detection_latency + report_latency, the event is reported through the
+     *   HAL
+     *
+     * Soon after that, the event is piped through the framework to the application. This time may
+     * vary depending on the CPU load. The time 'detection_latency' must be less than
+     * {@link #getSensorMaxDetectionLatencyNs(Sensor)}, and 'report_latency' must be less than
+     * {@link #getMaxReportLatencyUs()} passed through batch() at the HAL level.
+     */
+    // TODO: when all tests are moved to use the Sensor test framework, make this method non-static
+    public static long getSensorMaxDetectionLatencyNs(Sensor sensor) {
+        int reportLatencySec;
+        switch (sensor.getType()) {
+            case Sensor.TYPE_STEP_DETECTOR:
+                reportLatencySec = 2;
+                break;
+            case Sensor.TYPE_STEP_COUNTER:
+                reportLatencySec = 10;
+                break;
+            case Sensor.TYPE_SIGNIFICANT_MOTION:
+                reportLatencySec = 10;
+                break;
+            default:
+                reportLatencySec = 0;
+        }
+        return TimeUnit.SECONDS.toNanos(reportLatencySec);
+    }
+
+    /**
+     * Return true if {@link #getRequestedSamplingPeriodUs()} is not one of
+     * {@link SensorManager#SENSOR_DELAY_GAME}, {@link SensorManager#SENSOR_DELAY_UI}, or
+     * {@link SensorManager#SENSOR_DELAY_NORMAL}.
+     */
+    private boolean isDelayRateTestable() {
+        return (mSamplingPeriodUs >= 0
+                && mSamplingPeriodUs != SensorManager.SENSOR_DELAY_GAME
+                && mSamplingPeriodUs != SensorManager.SENSOR_DELAY_UI
+                && mSamplingPeriodUs != SensorManager.SENSOR_DELAY_NORMAL);
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEvent.java b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEvent.java
index 48bc1d3..e8500f1 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEvent.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEvent.java
@@ -18,33 +18,60 @@
 
 import android.hardware.Sensor;
 import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener2;
+import android.os.SystemClock;
 
 /**
- * Test class to wrap SensorEvent.
- * It currently only provides a way to clone SensorEvent data, but in the future it can contain
- * verifications and test checks.
+ * Class for holding information about individual {@link SensorEvent}s.
  */
 public class TestSensorEvent {
     public final Sensor sensor;
     public final long timestamp;
+    public final long receivedTimestamp;
     public final int accuracy;
     public final float values[];
 
+    /**
+     * Constructor that sets {@link #receivedTimestamp} to
+     * {@link SystemClock#elapsedRealtimeNanos()}
+     *
+     * @param event the received sensor event
+     */
     public TestSensorEvent(SensorEvent event) {
-        values = new float[event.values.length];
-        System.arraycopy(event.values, 0, values, 0, event.values.length);
+        this(event, SystemClock.elapsedRealtimeNanos());
+    }
 
+    /**
+     * Construct a TestSensorEvent from {@link SensorEvent} data and a received timestamp.
+     *
+     * @param event the {@link SensorEvent} to be cloned
+     * @param receivedTimestamp the timestamp when
+     * {@link SensorEventListener2#onSensorChanged(SensorEvent)} was called, in nanoseconds.
+     */
+    public TestSensorEvent(SensorEvent event, long receivedTimestamp) {
+        values = event.values.clone();
         sensor = event.sensor;
         timestamp = event.timestamp;
         accuracy = event.accuracy;
+
+        this.receivedTimestamp = receivedTimestamp;
     }
 
     /**
      * Constructor for TestSensorEvent. Exposed for unit testing.
      */
-    protected TestSensorEvent(Sensor sensor, long timestamp, int accuracy, float[] values) {
+    public TestSensorEvent(Sensor sensor, long timestamp, int accuracy, float[] values) {
+        this(sensor, timestamp, timestamp, accuracy, values);
+    }
+
+    /**
+     * Constructor for TestSensorEvent. Exposed for unit testing.
+     */
+    public TestSensorEvent(Sensor sensor, long timestamp, long receivedTimestamp, int accuracy,
+            float[] values) {
         this.sensor = sensor;
         this.timestamp = timestamp;
+        this.receivedTimestamp = receivedTimestamp;
         this.accuracy = accuracy;
         this.values = values;
     }
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEventListener.java b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEventListener.java
new file mode 100644
index 0000000..9b3a5e4
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEventListener.java
@@ -0,0 +1,174 @@
+/*
+ * 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.cts.helpers;
+
+import junit.framework.Assert;
+
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener2;
+import android.os.SystemClock;
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A {@link SensorEventListener2} which performs operations such as waiting for a specific number of
+ * events or for a specific time, or waiting for a flush to complete. This class performs
+ * verifications and will throw {@link AssertionError}s if there are any errors. It may also wrap
+ * another {@link SensorEventListener2}.
+ */
+public class TestSensorEventListener implements SensorEventListener2 {
+    public static final String LOG_TAG = "TestSensorEventListener";
+    private static final long EVENT_TIMEOUT_US = TimeUnit.MICROSECONDS.convert(5, TimeUnit.SECONDS);
+    private static final long FLUSH_TIMEOUT_US = TimeUnit.MICROSECONDS.convert(5, TimeUnit.SECONDS);
+
+    private final SensorEventListener2 mListener;
+
+    private volatile CountDownLatch mEventLatch;
+    private volatile CountDownLatch mFlushLatch = new CountDownLatch(1);
+    private volatile TestSensorEnvironment mEnvironment;
+    private volatile boolean mLogEvents;
+
+    /**
+     * Construct a {@link TestSensorEventListener}.
+     */
+    public TestSensorEventListener() {
+        this(null);
+    }
+
+    /**
+     * Construct a {@link TestSensorEventListener} that wraps a {@link SensorEventListener2}.
+     */
+    public TestSensorEventListener(SensorEventListener2 listener) {
+        if (listener != null) {
+            mListener = listener;
+        } else {
+            // use a Null Object to simplify handling the listener
+            mListener = new SensorEventListener2() {
+                public void onFlushCompleted(Sensor sensor) {}
+                public void onSensorChanged(SensorEvent sensorEvent) {}
+                public void onAccuracyChanged(Sensor sensor, int i) {}
+            };
+        }
+    }
+
+    /**
+     * Set the sensor, rate, and batch report latency used for the assertions.
+     */
+    public void setEnvironment(TestSensorEnvironment environment) {
+        mEnvironment = environment;
+    }
+
+    /**
+     * Set whether or not to log events
+     */
+    public void setLogEvents(boolean log) {
+        mLogEvents = log;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onSensorChanged(SensorEvent event) {
+        mListener.onSensorChanged(event);
+        if (mLogEvents) {
+            Log.v(LOG_TAG, String.format(
+                    "Sensor %d: sensor_timestamp=%dns, received_timestamp=%dns, values=%s",
+                    mEnvironment.getSensor().getType(),
+                    event.timestamp,
+                    SystemClock.elapsedRealtimeNanos(),
+                    Arrays.toString(event.values)));
+        }
+
+        CountDownLatch eventLatch = mEventLatch;
+        if(eventLatch != null) {
+            eventLatch.countDown();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onAccuracyChanged(Sensor sensor, int accuracy) {
+        mListener.onAccuracyChanged(sensor, accuracy);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onFlushCompleted(Sensor sensor) {
+        CountDownLatch latch = mFlushLatch;
+        mFlushLatch = new CountDownLatch(1);
+        if(latch != null) {
+            latch.countDown();
+        }
+        mListener.onFlushCompleted(sensor);
+    }
+
+    /**
+     * Wait for {@link #onFlushCompleted(Sensor)} to be called.
+     *
+     * @throws AssertionError if there was a timeout after {@link #FLUSH_TIMEOUT_US} &micro;s
+     */
+    public void waitForFlushComplete() throws InterruptedException {
+        CountDownLatch latch = mFlushLatch;
+        if(latch == null) {
+            return;
+        }
+        Assert.assertTrue(
+                SensorCtsHelper.formatAssertionMessage("WaitForFlush", mEnvironment),
+                latch.await(FLUSH_TIMEOUT_US, TimeUnit.MICROSECONDS));
+    }
+
+    /**
+     * Collect a specific number of {@link TestSensorEvent}s.
+     *
+     * @throws AssertionError if there was a timeout after {@link #FLUSH_TIMEOUT_US} &micro;s
+     */
+    public void waitForEvents(int eventCount) throws InterruptedException {
+        mEventLatch = new CountDownLatch(eventCount);
+        try {
+            int rateUs = mEnvironment.getExpectedSamplingPeriodUs();
+            // Timeout is 2 * event count * expected period + batch timeout + default wait
+            long timeoutUs = (2 * eventCount * rateUs)
+                    + mEnvironment.getMaxReportLatencyUs()
+                    + EVENT_TIMEOUT_US;
+            String message = SensorCtsHelper.formatAssertionMessage(
+                    "WaitForEvents",
+                    mEnvironment,
+                    "requested:%d, received:%d",
+                    eventCount,
+                    eventCount - mEventLatch.getCount());
+            Assert.assertTrue(message, mEventLatch.await(timeoutUs, TimeUnit.MICROSECONDS));
+        } finally {
+            mEventLatch = null;
+        }
+    }
+
+    /**
+     * Collect {@link TestSensorEvent} for a specific duration.
+     */
+    public void waitForEvents(long duration, TimeUnit timeUnit) throws InterruptedException {
+        SensorCtsHelper.sleep(duration, timeUnit);
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorManager.java b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorManager.java
new file mode 100644
index 0000000..dc40ff4
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorManager.java
@@ -0,0 +1,245 @@
+/*
+ * 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.cts.helpers;
+
+import junit.framework.Assert;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorEventListener2;
+import android.hardware.SensorManager;
+import android.util.Log;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A test class that performs the actions of {@link SensorManager} on a single sensor. This
+ * class allows for a single sensor to be registered and unregistered as well as performing
+ * operations such as flushing the sensor events and gathering events. This class also manages
+ * performing the test verifications for the sensor manager.
+ * <p>
+ * This class requires that operations are performed in the following order:
+ * <p><ul>
+ * <li>{@link #registerListener(TestSensorEventListener)}</li>
+ * <li>{@link #startFlush()}, {@link #waitForFlushCompleted()}, or {@link #flush()}.
+ * <li>{@link #unregisterListener()}</li>
+ * </ul><p>Or:</p><ul>
+ * <li>{@link #runSensor(TestSensorEventListener, int)}</li>
+ * </ul><p>Or:</p><ul>
+ * <li>{@link #runSensor(TestSensorEventListener, long, TimeUnit)}</li>
+ * </ul><p>
+ * If methods are called outside of this order, they will print a warning to the log and then
+ * return. Both {@link #runSensor(TestSensorEventListener, int)}} and
+ * {@link #runSensor(TestSensorEventListener, long, TimeUnit)} will perform the appropriate
+ * set up and tear down.
+ * <p>
+ */
+public class TestSensorManager {
+    private static final String LOG_TAG = "TestSensorManager";
+
+    private final SensorManager mSensorManager;
+    private final TestSensorEnvironment mEnvironment;
+
+    private TestSensorEventListener mTestSensorEventListener;
+
+    /**
+     * @deprecated Use {@link #TestSensorManager(TestSensorEnvironment)} instead.
+     */
+    @Deprecated
+    public TestSensorManager(
+            Context context,
+            int sensorType,
+            int rateUs,
+            int maxBatchReportLatencyUs) {
+        this(new TestSensorEnvironment(context, sensorType, rateUs, maxBatchReportLatencyUs));
+    }
+
+    /**
+     * Construct a {@link TestSensorManager}.
+     */
+    public TestSensorManager(TestSensorEnvironment environment) {
+        mSensorManager =
+                (SensorManager) environment.getContext().getSystemService(Context.SENSOR_SERVICE);
+        mEnvironment = environment;
+    }
+
+    /**
+     * Register the listener. This method will perform a no-op if the sensor is already registered.
+     *
+     * @throws AssertionError if there was an error registering the listener with the
+     * {@link SensorManager}
+     */
+    public void registerListener(TestSensorEventListener listener) {
+        if (mTestSensorEventListener != null) {
+            Log.w(LOG_TAG, "Listener already registered, returning.");
+            return;
+        }
+
+        mTestSensorEventListener = listener != null ? listener : new TestSensorEventListener();
+        mTestSensorEventListener.setEnvironment(mEnvironment);
+
+        String message = SensorCtsHelper.formatAssertionMessage("registerListener", mEnvironment);
+        boolean result = mSensorManager.registerListener(
+                mTestSensorEventListener,
+                mEnvironment.getSensor(),
+                mEnvironment.getRequestedSamplingPeriodUs(),
+                mEnvironment.getMaxReportLatencyUs());
+        Assert.assertTrue(message, result);
+    }
+
+    /**
+     * Unregister the listener. This method will perform a no-op if the sensor is not registered.
+     */
+    public void unregisterListener() {
+        if (mTestSensorEventListener == null) {
+            Log.w(LOG_TAG, "No listener registered, returning.");
+            return;
+        }
+
+        mSensorManager.unregisterListener(
+                mTestSensorEventListener,
+                mEnvironment.getSensor());
+        mTestSensorEventListener = null;
+    }
+
+    /**
+     * Wait for a specific number of events.
+     */
+    public void waitForEvents(int eventCount) throws InterruptedException {
+        if (mTestSensorEventListener == null) {
+            Log.w(LOG_TAG, "No listener registered, returning.");
+            return;
+        }
+        mTestSensorEventListener.waitForEvents(eventCount);
+    }
+
+    /**
+     * Wait for a specific duration.
+     */
+    public void waitForEvents(long duration, TimeUnit timeUnit) throws InterruptedException {
+        if (mTestSensorEventListener == null) {
+            Log.w(LOG_TAG, "No listener registered, returning.");
+            return;
+        }
+        mTestSensorEventListener.waitForEvents(duration, timeUnit);
+    }
+
+    /**
+     * Call {@link SensorManager#flush(SensorEventListener)}. This method will perform a no-op if
+     * the sensor is not registered.
+     *
+     * @throws AssertionError if {@link SensorManager#flush(SensorEventListener)} returns false
+     */
+    public void startFlush() {
+        if (mTestSensorEventListener == null) {
+            return;
+        }
+
+        Assert.assertTrue(
+                SensorCtsHelper.formatAssertionMessage("Flush", mEnvironment),
+                mSensorManager.flush(mTestSensorEventListener));
+    }
+
+    /**
+     * Wait for {@link SensorEventListener2#onFlushCompleted(Sensor)} to be called. This method will
+     * perform a no-op if the sensor is not registered.
+     *
+     * @throws AssertionError if there is a time out
+     * @throws InterruptedException if the thread was interrupted
+     */
+    public void waitForFlushCompleted() throws InterruptedException {
+        if (mTestSensorEventListener == null) {
+            return;
+        }
+        mTestSensorEventListener.waitForFlushComplete();
+    }
+
+    /**
+     * Call {@link SensorManager#flush(SensorEventListener)} and wait for
+     * {@link SensorEventListener2#onFlushCompleted(Sensor)} to be called. This method will perform
+     * a no-op if the sensor is not registered.
+     *
+     * @throws AssertionError if {@link SensorManager#flush(SensorEventListener)} returns false or
+     * if there is a time out
+     * @throws InterruptedException if the thread was interrupted
+     */
+    public void flush() throws InterruptedException {
+        if (mTestSensorEventListener == null) {
+            return;
+        }
+        startFlush();
+        waitForFlushCompleted();
+    }
+
+    /**
+     * Register a listener, wait for a specific number of events, and then unregister the listener.
+     */
+    public void runSensor(TestSensorEventListener listener, int eventCount)
+            throws InterruptedException {
+        if (mTestSensorEventListener != null) {
+            Log.w(LOG_TAG, "Listener already registered, returning.");
+            return;
+        }
+        try {
+            registerListener(listener);
+            waitForEvents(eventCount);
+        } finally {
+            unregisterListener();
+        }
+    }
+
+    /**
+     * Register a listener, wait for a specific duration, and then unregister the listener.
+     */
+    public void runSensor(TestSensorEventListener listener, long duration, TimeUnit timeUnit)
+            throws InterruptedException {
+        if (mTestSensorEventListener != null) {
+            Log.w(LOG_TAG, "Listener already registered, returning.");
+            return;
+        }
+        try {
+            registerListener(listener);
+            waitForEvents(duration, timeUnit);
+        } finally {
+            unregisterListener();
+        }
+    }
+
+    /**
+     * Registers a listener, waits for a specific duration, calls flush, and waits for flush to
+     * complete.
+     */
+    public void runSensorAndFlush(
+            TestSensorEventListener listener,
+            long duration,
+            TimeUnit timeUnit) throws InterruptedException {
+        if (mTestSensorEventListener != null) {
+            Log.w(LOG_TAG, "Listener already registered, returning.");
+            return;
+        }
+
+        try {
+            registerListener(listener);
+            SensorCtsHelper.sleep(duration, timeUnit);
+            startFlush();
+            listener.waitForFlushComplete();
+        } finally {
+            unregisterListener();
+        }
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/ValidatingSensorEventListener.java b/tests/tests/hardware/src/android/hardware/cts/helpers/ValidatingSensorEventListener.java
new file mode 100644
index 0000000..299f470
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/ValidatingSensorEventListener.java
@@ -0,0 +1,82 @@
+/*
+ * 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.cts.helpers;
+
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener2;
+import android.hardware.cts.helpers.sensorverification.ISensorVerification;
+
+import java.util.Collection;
+import java.util.LinkedList;
+
+/**
+ * A {@link TestSensorEventListener} which performs validations on the received events on the fly.
+ * This class is useful for long running tests where it is not practical to store all the events to
+ * be processed after.
+ */
+public class ValidatingSensorEventListener extends TestSensorEventListener {
+
+    private final Collection<ISensorVerification> mVerifications =
+            new LinkedList<ISensorVerification>();
+
+    /**
+     * Construct a {@link ValidatingSensorEventListener} with an additional
+     * {@link SensorEventListener2}.
+     */
+    public ValidatingSensorEventListener(SensorEventListener2 listener,
+            ISensorVerification ... verifications) {
+        super(listener);
+        for (ISensorVerification verification : verifications) {
+            mVerifications.add(verification);
+        }
+    }
+
+    /**
+     * Construct a {@link ValidatingSensorEventListener} with an additional
+     * {@link SensorEventListener2}.
+     */
+    public ValidatingSensorEventListener(SensorEventListener2 listener,
+            Collection<ISensorVerification> verifications) {
+        this(listener, verifications.toArray(new ISensorVerification[0]));
+    }
+
+    /**
+     * Construct a {@link ValidatingSensorEventListener}.
+     */
+    public ValidatingSensorEventListener(ISensorVerification ... verifications) {
+        this(null, verifications);
+    }
+
+    /**
+     * Construct a {@link ValidatingSensorEventListener}.
+     */
+    public ValidatingSensorEventListener(Collection<ISensorVerification> verifications) {
+        this(null, verifications);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onSensorChanged(SensorEvent event) {
+        TestSensorEvent testEvent = new TestSensorEvent(event);
+        for (ISensorVerification verification : mVerifications) {
+            verification.addSensorEvent(testEvent);
+        }
+        super.onSensorChanged(event);
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/ParallelCompositeSensorTestOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/ParallelCompositeSensorTestOperation.java
deleted file mode 100644
index 3730f4b..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/ParallelCompositeSensorTestOperation.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.cts.helpers.sensorTestOperations;
-
-import android.hardware.cts.helpers.SensorTestOperation;
-
-import java.util.ArrayList;
-
-/**
- * A test operation that groups a set of SensorTestOperations and allows to execute them all in
- * parallel.
- * This class can be combined to compose other primitive SensorTestOperations.
- */
-public class ParallelCompositeSensorTestOperation extends SensorTestOperation {
-    private final ArrayList<SensorTestOperation> mOperations = new ArrayList<SensorTestOperation>();
-
-    /**
-     * There is no synchronization
-     * @param operations
-     */
-    public void add(SensorTestOperation ... operations) {
-        synchronized (mOperations) {
-            for(SensorTestOperation operation : operations) {
-                mOperations.add(operation);
-            }
-        }
-    }
-
-    @Override
-    protected void doWork() throws Throwable {
-        synchronized (mOperations) {
-            for(SensorTestOperation operation : mOperations) {
-                operation.start();
-            }
-            for(SensorTestOperation operation : mOperations) {
-                operation.waitForCompletion();
-            }
-        }
-    }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/RepeatingSensorTestOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/RepeatingSensorTestOperation.java
deleted file mode 100644
index 7a3c450..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/RepeatingSensorTestOperation.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.cts.helpers.sensorTestOperations;
-
-import android.hardware.cts.helpers.SensorTestOperation;
-
-/**
- * High level SensorTestOperation that executes the inner operation in a loop.
- */
-public class RepeatingSensorTestOperation extends SensorTestOperation {
-    private final SensorTestOperation mSensorTestOperation;
-    private final int mRepetitionCount;
-
-    public RepeatingSensorTestOperation(SensorTestOperation operation, int repetitionCount) {
-        mSensorTestOperation = operation;
-        mRepetitionCount = repetitionCount;
-    }
-
-    @Override
-    protected void doWork() throws Throwable {
-        for(int i = 0; i < mRepetitionCount; ++i) {
-            mSensorTestOperation.execute();
-        }
-    }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/SequentialCompositeSensorTestOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/SequentialCompositeSensorTestOperation.java
deleted file mode 100644
index 4b921680..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/SequentialCompositeSensorTestOperation.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.cts.helpers.sensorTestOperations;
-
-import android.hardware.cts.helpers.SensorTestOperation;
-
-import java.util.ArrayList;
-
-/**
- * A test operation that groups a set of SensorTestOperations and allows to execute them in a
- * sequence, each operation executes in the order they are added to the composite container.
- * This class can be combined to compose other primitive SensorTestOperations.
- */
-public class SequentialCompositeSensorTestOperation extends SensorTestOperation {
-    private final ArrayList<SensorTestOperation> mOperations = new ArrayList<SensorTestOperation>();
-
-    /**
-     * There is no synchronization
-     * @param operations
-     */
-    public void add(SensorTestOperation ... operations) {
-        synchronized (mOperations) {
-            for(SensorTestOperation operation : operations) {
-                mOperations.add(operation);
-            }
-        }
-    }
-
-    @Override
-    protected void doWork() throws Throwable {
-        synchronized (mOperations) {
-            for(SensorTestOperation operation : mOperations) {
-                operation.execute();
-            }
-        }
-    }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyEventOrderingOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyEventOrderingOperation.java
deleted file mode 100644
index 03d0f9af..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyEventOrderingOperation.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.cts.helpers.sensorTestOperations;
-
-import android.content.Context;
-import android.hardware.cts.helpers.SensorCtsHelper;
-import android.hardware.cts.helpers.SensorManagerTestVerifier;
-import android.hardware.cts.helpers.SensorTestOperation;
-import android.hardware.cts.helpers.SensorVerificationHelper;
-import android.hardware.cts.helpers.SensorVerificationHelper.VerificationResult;
-import android.hardware.cts.helpers.TestSensorEvent;
-
-import junit.framework.Assert;
-
-/**
- * Test Operation class that validates the ordering of sensor events.
- */
-public class VerifyEventOrderingOperation extends SensorTestOperation {
-    private SensorManagerTestVerifier mSensor;
-
-    public VerifyEventOrderingOperation(
-            Context context,
-            int sensorType,
-            int samplingRateInUs,
-            int reportLatencyInUs) {
-        mSensor = new SensorManagerTestVerifier(
-                context,
-                sensorType,
-                samplingRateInUs,
-                reportLatencyInUs);
-    }
-
-    @Override
-    public void doWork() {
-        TestSensorEvent[] events = mSensor.collectEvents(100);
-        VerificationResult result = SensorVerificationHelper.verifyEventOrdering(events);
-        if (result.isFailed()) {
-            Assert.fail(SensorCtsHelper.formatAssertionMessage(
-                    "Ordering",
-                    this,
-                    mSensor.getUnderlyingSensor(),
-                    result.getFailureMessage()));
-        }
-    }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyJitteringOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyJitteringOperation.java
deleted file mode 100644
index 303dc9b..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyJitteringOperation.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.cts.helpers.sensorTestOperations;
-
-import android.content.Context;
-import android.hardware.cts.helpers.SensorCtsHelper;
-import android.hardware.cts.helpers.SensorManagerTestVerifier;
-import android.hardware.cts.helpers.SensorTestInformation;
-import android.hardware.cts.helpers.SensorTestOperation;
-import android.hardware.cts.helpers.SensorVerificationHelper;
-import android.hardware.cts.helpers.SensorVerificationHelper.VerificationResult;
-import android.hardware.cts.helpers.TestSensorEvent;
-
-import junit.framework.Assert;
-
-import java.security.InvalidParameterException;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Test Operation class that validates the sampling rate jittering of a given sensor.
- *
- * Remarks:
- * - In order to guarantee proper results in any environment, the maximum sampling rate supported by
- *   the Sensor is used, this guarantees the frequency reference for the test.
- */
-public class VerifyJitteringOperation extends SensorTestOperation {
-    protected SensorManagerTestVerifier mSensor;
-    protected long mExpectedtimestampInNs;
-    protected long mThresholdPercentage;
-    protected long mThresholdInNs;
-
-    public VerifyJitteringOperation(
-            Context context,
-            int sensorType,
-            int reportLatencyInUs,
-            int thresholdPercentageOfNs) throws InvalidParameterException {
-        if(thresholdPercentageOfNs < 0) {
-            throw new InvalidParameterException("thresholdPercentageOfNs needs to be >= 0");
-        }
-        // use the max sampling frequency the sensor reports to guarantee the results
-        int maxSamplingRateInUs = SensorTestInformation.getMaxSamplingRateInUs(context, sensorType);
-        mSensor = new SensorManagerTestVerifier(
-                context,
-                sensorType,
-                maxSamplingRateInUs,
-                reportLatencyInUs);
-        // set expectations
-        mExpectedtimestampInNs = TimeUnit.NANOSECONDS.convert(
-                maxSamplingRateInUs,
-                TimeUnit.MICROSECONDS);
-        mThresholdPercentage = thresholdPercentageOfNs;
-        mThresholdInNs = mExpectedtimestampInNs / mThresholdPercentage;
-    }
-
-    @Override
-    public void doWork() {
-        TestSensorEvent[] events = mSensor.collectEvents(100);
-        VerificationResult result = SensorVerificationHelper.verifyJitter(events, mThresholdInNs);
-        if (result.isFailed()) {
-            Assert.fail(SensorCtsHelper.formatAssertionMessage(
-                    "Jitter(95%ile)",
-                    this,
-                    mSensor.getUnderlyingSensor(),
-                    result.getFailureMessage()));
-        }
-    }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyMagnitudeOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyMagnitudeOperation.java
deleted file mode 100644
index cbcff6a..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyMagnitudeOperation.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.cts.helpers.sensorTestOperations;
-
-import android.content.Context;
-import android.hardware.cts.helpers.SensorCtsHelper;
-import android.hardware.cts.helpers.SensorManagerTestVerifier;
-import android.hardware.cts.helpers.SensorTestInformation;
-import android.hardware.cts.helpers.SensorTestOperation;
-import android.hardware.cts.helpers.SensorVerificationHelper;
-import android.hardware.cts.helpers.SensorVerificationHelper.VerificationResult;
-import android.hardware.cts.helpers.TestSensorEvent;
-
-import junit.framework.Assert;
-
-/**
- * Test Operation class that validates the norm of a given sensor.
- * The operation relies in the number of axes each sensor type reports.
- */
-public class VerifyMagnitudeOperation extends SensorTestOperation {
-    private SensorManagerTestVerifier mSensor;
-    private int mAxisCount;
-    private double mReferenceValue;
-    private double mThreshold;
-
-    public VerifyMagnitudeOperation(
-            Context context,
-            int sensorType,
-            int samplingRateInUs,
-            float referenceValue,
-            float threshold) {
-        mSensor = new SensorManagerTestVerifier(
-                context,
-                sensorType,
-                samplingRateInUs,
-                0 /*reportLatencyInUs*/);
-        // set expectations
-        mAxisCount = SensorTestInformation.getAxisCount(mSensor.getUnderlyingSensor().getType());
-        mReferenceValue = referenceValue;
-        mThreshold = threshold;
-    }
-
-    @Override
-    public void doWork() {
-        TestSensorEvent[] events = mSensor.collectEvents(1);
-        VerificationResult result = SensorVerificationHelper.verifyMagnitude(events, mReferenceValue,
-                mThreshold);
-        if (result.isFailed()) {
-            Assert.fail(SensorCtsHelper.formatAssertionMessage(
-                    "Norm",
-                    this,
-                    mSensor.getUnderlyingSensor(),
-                    result.getFailureMessage()));
-        }
-    }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyMaximumFrequencyOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyMaximumFrequencyOperation.java
deleted file mode 100644
index 0af15a24..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyMaximumFrequencyOperation.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.cts.helpers.sensorTestOperations;
-
-import android.content.Context;
-import android.hardware.cts.helpers.SensorCtsHelper;
-import android.hardware.cts.helpers.SensorManagerTestVerifier;
-import android.hardware.cts.helpers.SensorTestInformation;
-import android.hardware.cts.helpers.SensorTestOperation;
-import android.hardware.cts.helpers.SensorVerificationHelper;
-import android.hardware.cts.helpers.SensorVerificationHelper.VerificationResult;
-import android.hardware.cts.helpers.TestSensorEvent;
-
-import junit.framework.Assert;
-
-import java.security.InvalidParameterException;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Test Operation class that validates the max sampling rate of a given sensor.
- *
- * Remarks:
- * - In order to guarantee proper results in any environment, the maximum sampling rate supported by
- *   the Sensor is used, this guarantees the frequency reference for the test.
- */
-public class VerifyMaximumFrequencyOperation extends SensorTestOperation {
-    protected SensorManagerTestVerifier mSensor;
-    protected long mExpectedTimestampInNs;
-    protected long mThresholdPercentage;
-    protected long mThresholdInNs;
-
-    public VerifyMaximumFrequencyOperation(
-            Context context,
-            int sensorType,
-            int reportLatencyInUs,
-            int thresholdPercentageOfNs) throws InvalidParameterException {
-        if(thresholdPercentageOfNs < 0) {
-            throw new InvalidParameterException("thresholdPercentageOfNs needs to be >= 0");
-        }
-        // use the max sampling frequency the sensor reports to guarantee the results
-        int maxSamplingRateInUs = SensorTestInformation.getMaxSamplingRateInUs(context, sensorType);
-        mSensor = new SensorManagerTestVerifier(
-                context,
-                sensorType,
-                maxSamplingRateInUs,
-                reportLatencyInUs);
-        // set expectations
-        mExpectedTimestampInNs = TimeUnit.NANOSECONDS.convert(
-                maxSamplingRateInUs,
-                TimeUnit.MICROSECONDS);
-        mThresholdPercentage = thresholdPercentageOfNs;
-        mThresholdInNs = mExpectedTimestampInNs / mThresholdPercentage;
-    }
-
-    @Override
-    public void doWork() {
-        TestSensorEvent[] events = mSensor.collectEvents(100);
-        VerificationResult result = SensorVerificationHelper.verifyFrequency(events,
-                mExpectedTimestampInNs, mThresholdInNs);
-        if (result.isFailed()) {
-            Assert.fail(SensorCtsHelper.formatAssertionMessage(
-                    "Frequency",
-                    this,
-                    mSensor.getUnderlyingSensor(),
-                    result.getFailureMessage()));
-        }
-    }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyMeasurementsOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyMeasurementsOperation.java
deleted file mode 100644
index 2368eb4..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyMeasurementsOperation.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.cts.helpers.sensorTestOperations;
-
-import android.content.Context;
-import android.hardware.cts.helpers.SensorCtsHelper;
-import android.hardware.cts.helpers.SensorManagerTestVerifier;
-import android.hardware.cts.helpers.SensorTestInformation;
-import android.hardware.cts.helpers.SensorTestOperation;
-import android.hardware.cts.helpers.SensorVerificationHelper;
-import android.hardware.cts.helpers.SensorVerificationHelper.VerificationResult;
-import android.hardware.cts.helpers.TestSensorEvent;
-
-import junit.framework.Assert;
-
-import java.security.InvalidParameterException;
-
-/**
- * Test Operation class that validates the measurements of a a given sensor.
- * The operation relies on the number of axes each sensor type reports.
- * The verification calculates the mean for each axis on the measurements, and verifies that they
- * fall into the expected intervals.
- */
-public class VerifyMeasurementsOperation extends SensorTestOperation {
-    private final SensorManagerTestVerifier mSensor;
-    private final int mAxisCount;
-    private final double[] mReferenceValues;
-    private final double[] mThreshold;
-
-    public VerifyMeasurementsOperation(
-            Context context,
-            int sensorType,
-            int samplingRateInUs,
-            int reportLatencyInUs,
-            double referenceValues[],
-            float threshold) {
-        mAxisCount = SensorTestInformation.getAxisCount(sensorType);
-        if(mAxisCount != referenceValues.length) {
-            throw new InvalidParameterException(
-                    String.format("%d reference values are expected.", mAxisCount));
-        }
-        mSensor = new SensorManagerTestVerifier(
-                context,
-                sensorType,
-                samplingRateInUs,
-                reportLatencyInUs);
-        // set expectations
-        mReferenceValues = referenceValues;
-        mThreshold = new double[mAxisCount];
-        for (int i = 0; i < mThreshold.length; i++) {
-            mThreshold[i] = threshold;
-        }
-    }
-
-    @Override
-    public void doWork() {
-        TestSensorEvent[] events = mSensor.collectEvents(100);
-        VerificationResult result = SensorVerificationHelper.verifyMean(events, mReferenceValues,
-                mThreshold);
-        if (result.isFailed()) {
-            Assert.fail(SensorCtsHelper.formatAssertionMessage(
-                    "Measurement",
-                    this,
-                    mSensor.getUnderlyingSensor(),
-                    result.getFailureMessage()));
-        }
-    }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifySignumOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifySignumOperation.java
deleted file mode 100644
index f58baa1..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifySignumOperation.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.cts.helpers.sensorTestOperations;
-
-import android.content.Context;
-import android.hardware.cts.helpers.SensorCtsHelper;
-import android.hardware.cts.helpers.SensorManagerTestVerifier;
-import android.hardware.cts.helpers.SensorTestInformation;
-import android.hardware.cts.helpers.SensorTestOperation;
-import android.hardware.cts.helpers.SensorVerificationHelper;
-import android.hardware.cts.helpers.SensorVerificationHelper.VerificationResult;
-import android.hardware.cts.helpers.TestSensorEvent;
-
-import junit.framework.Assert;
-
-import java.security.InvalidParameterException;
-
-/**
- * Test Operation class that validates the sign of measurements of a a given sensor.
- * The operation relies in the number of axes each sensor type reports.
- */
-public class VerifySignumOperation extends SensorTestOperation {
-    private final SensorManagerTestVerifier mSensor;
-    private final int mAxisCount;
-    private final int mReferenceValues[];
-    private final double mNoiseThresholds[];
-
-    /**
-     * @param noiseThreshold Defines the threshold that needs to be crossed to consider a
-     *                       measurement different from zero
-     */
-    public VerifySignumOperation(
-            Context context,
-            int sensorType,
-            int samplingRateInUs,
-            int referenceValues[],
-            double noiseThreshold) {
-        mAxisCount = SensorTestInformation.getAxisCount(sensorType);
-        if(mAxisCount != referenceValues.length) {
-            throw new InvalidParameterException(
-                    String.format("%d reference values are expected.", mAxisCount));
-        }
-        for(int i = 0; i < referenceValues.length; ++i) {
-            int value = referenceValues[i];
-            if(value != 0 && value != -1 && value != +1) {
-                throw new InvalidParameterException(
-                        "A ReferenceValue can only be one of the following: -1, 0, +1");
-            }
-        }
-        mSensor = new SensorManagerTestVerifier(
-                context,
-                sensorType,
-                samplingRateInUs,
-                0 /*reportLatencyInUs*/);
-        // set expectations
-        mReferenceValues = referenceValues;
-        mNoiseThresholds = new double[mReferenceValues.length];
-        for (int i = 0; i < mNoiseThresholds.length; i++) {
-            mNoiseThresholds[i] = noiseThreshold;
-        }
-    }
-
-    @Override
-    public void doWork() {
-        TestSensorEvent[] events = mSensor.collectEvents(100);
-        VerificationResult result = SensorVerificationHelper.verifySignum(events, mReferenceValues,
-                mNoiseThresholds);
-        if (result.isFailed()) {
-            Assert.fail(SensorCtsHelper.formatAssertionMessage(
-                    "Measurement",
-                    this,
-                    mSensor.getUnderlyingSensor(),
-                    result.getFailureMessage()));
-        }
-    }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyStandardDeviationOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyStandardDeviationOperation.java
deleted file mode 100644
index 05b92e0..0000000
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorTestOperations/VerifyStandardDeviationOperation.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.cts.helpers.sensorTestOperations;
-
-import android.content.Context;
-import android.hardware.cts.helpers.SensorCtsHelper;
-import android.hardware.cts.helpers.SensorManagerTestVerifier;
-import android.hardware.cts.helpers.SensorTestInformation;
-import android.hardware.cts.helpers.SensorTestOperation;
-import android.hardware.cts.helpers.SensorVerificationHelper;
-import android.hardware.cts.helpers.SensorVerificationHelper.VerificationResult;
-import android.hardware.cts.helpers.TestSensorEvent;
-
-import junit.framework.Assert;
-
-/**
- * Test Operation class that validates the standard deviation of a given sensor.
- */
-public class VerifyStandardDeviationOperation extends SensorTestOperation {
-    private SensorManagerTestVerifier mSensor;
-    private int mAxisCount;
-    private double[] mExpectedStandardDeviation;
-
-    public VerifyStandardDeviationOperation(
-            Context context,
-            int sensorType,
-            int samplingRateInUs,
-            int reportLatencyInUs,
-            float expectedStandardDeviation) {
-        mSensor = new SensorManagerTestVerifier(
-                context,
-                sensorType,
-                samplingRateInUs,
-                reportLatencyInUs);
-        // set expectations
-        mAxisCount = SensorTestInformation.getAxisCount(mSensor.getUnderlyingSensor().getType());
-        mExpectedStandardDeviation = new double[mAxisCount];
-        for (int i = 0; i < mExpectedStandardDeviation.length; i++) {
-            mExpectedStandardDeviation[i] = expectedStandardDeviation;
-        }
-    }
-
-    @Override
-    public void doWork() {
-        TestSensorEvent[] events = mSensor.collectEvents(100);
-        VerificationResult result = SensorVerificationHelper.verifyStandardDeviation(events,
-                mExpectedStandardDeviation);
-        if (result.isFailed()) {
-            Assert.fail(SensorCtsHelper.formatAssertionMessage(
-                    "StandardDeviation",
-                    this,
-                    mSensor.getUnderlyingSensor(),
-                    result.getFailureMessage()));
-        }
-    }
-}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/AbstractSensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/AbstractSensorOperation.java
new file mode 100644
index 0000000..5b969f2
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/AbstractSensorOperation.java
@@ -0,0 +1,60 @@
+/*
+ * 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.cts.helpers.sensoroperations;
+
+import android.hardware.cts.helpers.SensorStats;
+
+/**
+ * A {@link ISensorOperation} which contains a common implementation for gathering
+ * {@link SensorStats}.
+ */
+public abstract class AbstractSensorOperation implements ISensorOperation {
+
+    private final SensorStats mStats = new SensorStats();
+
+    /**
+     * Wrapper around {@link SensorStats#addSensorStats(String, SensorStats)}
+     */
+    protected void addSensorStats(String key, SensorStats stats) {
+        mStats.addSensorStats(key, stats);
+    }
+
+    /**
+     * Wrapper around {@link SensorStats#addSensorStats(String, SensorStats)} that allows an index
+     * to be added. This is useful for {@link ISensorOperation}s that have many iterations or child
+     * operations. The key added is in the form {@code key + "_" + index} where index may be zero
+     * padded.
+     */
+    protected void addSensorStats(String key, int index, SensorStats stats) {
+        addSensorStats(String.format("%s_%03d", key, index), stats);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public SensorStats getStats() {
+        return mStats;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public abstract ISensorOperation clone();
+
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/AlarmOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/AlarmOperation.java
new file mode 100644
index 0000000..88e4954
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/AlarmOperation.java
@@ -0,0 +1,140 @@
+/*
+ * 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.cts.helpers.sensoroperations;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.cts.helpers.SensorStats;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An {@link ISensorOperation} which performs another {@link ISensorOperation} and then wakes up
+ * after a specified period of time and waits for the child operation to complete.
+ * <p>
+ * This operation can be used to allow the device to go to sleep and wake it up after a specified
+ * period of time. After the device wakes up, this operation will hold a wake lock until the child
+ * operation finishes. This operation will not force the device into suspend, so if another
+ * operation is holding a wake lock, the device will stay awake.  Also, if the child operation
+ * finishes before the specified period, this operation return when the child operation finishes
+ * but wake the device one time at the specified period.
+ * </p>
+ */
+public class AlarmOperation extends AbstractSensorOperation {
+    private static final String ACTION = "AlarmOperationAction";
+    private static final String WAKE_LOCK_TAG = "AlarmOperationWakeLock";
+
+    private final ISensorOperation mOperation;
+    private final Context mContext;
+    private final long mSleepDuration;
+    private final TimeUnit mTimeUnit;
+
+    private boolean mCompleted = false;
+    private WakeLock mWakeLock = null;
+
+    /**
+     * Constructor for {@link DelaySensorOperation}
+     *
+     * @param operation the child {@link ISensorOperation} to perform after the delay
+     * @param context the context used to access the alarm manager
+     * @param sleepDuration the amount of time to sleep
+     * @param timeUnit the unit of the duration
+     */
+    public AlarmOperation(ISensorOperation operation, Context context, long sleepDuration,
+            TimeUnit timeUnit) {
+        mOperation = operation;
+        mContext = context;
+        mSleepDuration = sleepDuration;
+        mTimeUnit = timeUnit;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void execute() throws InterruptedException {
+        // Start alarm
+        IntentFilter intentFilter = new IntentFilter(ACTION);
+        BroadcastReceiver receiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                acquireWakeLock();
+            }
+        };
+        mContext.registerReceiver(receiver, intentFilter);
+
+        AlarmManager am = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
+        long wakeupTimeMs = (System.currentTimeMillis()
+                + TimeUnit.MILLISECONDS.convert(mSleepDuration, mTimeUnit));
+        Intent intent = new Intent(ACTION);
+        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
+        am.setExact(AlarmManager.RTC_WAKEUP, wakeupTimeMs, pendingIntent);
+
+        // Execute operation
+        try {
+            mOperation.execute();
+        } finally {
+            releaseWakeLock();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public SensorStats getStats() {
+        return mOperation.getStats();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public AlarmOperation clone() {
+        return new AlarmOperation(mOperation, mContext, mSleepDuration, mTimeUnit);
+    }
+
+    /**
+     * Method that acquires a wake lock if a wake lock has not already been acquired and if the
+     * operation has not yet completed.
+     */
+    private synchronized void acquireWakeLock() {
+        // Don't acquire wake lock if the operation has already completed.
+        if (mCompleted == true || mWakeLock != null) {
+            return;
+        }
+        PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKE_LOCK_TAG);
+    }
+
+    /**
+     * Method that releases the wake lock if it has been acquired.
+     */
+    private synchronized void releaseWakeLock() {
+        mCompleted = true;
+        if (mWakeLock != null) {
+            mWakeLock.release();
+        }
+        mWakeLock = null;
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/DelaySensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/DelaySensorOperation.java
new file mode 100644
index 0000000..b4d1f23
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/DelaySensorOperation.java
@@ -0,0 +1,73 @@
+/*
+ * 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.cts.helpers.sensoroperations;
+
+import android.hardware.cts.helpers.SensorCtsHelper;
+import android.hardware.cts.helpers.SensorStats;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An {@link ISensorOperation} which delays for a specified period of time before performing another
+ * {@link ISensorOperation}.
+ */
+public class DelaySensorOperation implements ISensorOperation {
+    private final ISensorOperation mOperation;
+    private final long mDelay;
+    private final TimeUnit mTimeUnit;
+
+    /**
+     * Constructor for {@link DelaySensorOperation}
+     *
+     * @param operation the child {@link ISensorOperation} to perform after the delay
+     * @param delay the amount of time to delay
+     * @param timeUnit the unit of the delay
+     */
+    public DelaySensorOperation(ISensorOperation operation, long delay, TimeUnit timeUnit) {
+        if (operation == null || timeUnit == null) {
+            throw new IllegalArgumentException("Arguments cannot be null");
+        }
+        mOperation = operation;
+        mDelay = delay;
+        mTimeUnit = timeUnit;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void execute() throws InterruptedException {
+        SensorCtsHelper.sleep(mDelay, mTimeUnit);
+        mOperation.execute();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public SensorStats getStats() {
+        return mOperation.getStats();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public DelaySensorOperation clone() {
+        return new DelaySensorOperation(mOperation.clone(), mDelay, mTimeUnit);
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/FakeSensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/FakeSensorOperation.java
new file mode 100644
index 0000000..bb64dfa
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/FakeSensorOperation.java
@@ -0,0 +1,88 @@
+/*
+ * 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.cts.helpers.sensoroperations;
+
+import android.hardware.cts.helpers.SensorStats;
+
+import junit.framework.Assert;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A fake {@ISensorOperation} that will run for a specified time and then pass or fail. Useful when
+ * debugging the framework.
+ */
+public class FakeSensorOperation extends AbstractSensorOperation {
+    private static final int NANOS_PER_MILLI = 1000000;
+
+    private final boolean mFail;
+    private final long mDelay;
+    private final TimeUnit mTimeUnit;
+
+    /**
+     * Constructor for {@link FakeSensorOperation} that passes
+     */
+    public FakeSensorOperation(long delay, TimeUnit timeUnit) {
+        this(false, delay, timeUnit);
+    }
+
+    /**
+     * Constructor for {@link FakeSensorOperation}
+     */
+    public FakeSensorOperation(boolean fail, long delay, TimeUnit timeUnit) {
+        if (timeUnit == null) {
+            throw new IllegalArgumentException("Arguments cannot be null");
+        }
+        mFail = fail;
+        mDelay = delay;
+        mTimeUnit = timeUnit;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void execute() {
+        long delayNs = TimeUnit.NANOSECONDS.convert(mDelay, mTimeUnit);
+        try {
+            Thread.sleep(delayNs / NANOS_PER_MILLI, (int) (delayNs % NANOS_PER_MILLI));
+            getStats().addValue("executed", true);
+            if (mFail) {
+                doFail();
+            }
+        }catch (InterruptedException e) {
+            // Ignore
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public FakeSensorOperation clone() {
+        return new FakeSensorOperation(mFail, mDelay, mTimeUnit);
+    }
+
+    /**
+     * Fails the operation.
+     */
+    protected void doFail() {
+        String msg = "FakeSensorOperation failed";
+        getStats().addValue(SensorStats.ERROR, msg);
+        Assert.fail(msg);
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ISensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ISensorOperation.java
new file mode 100644
index 0000000..62a4e9e
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ISensorOperation.java
@@ -0,0 +1,63 @@
+/*
+ * 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.cts.helpers.sensoroperations;
+
+import android.hardware.cts.helpers.SensorStats;
+
+/**
+ * Interface used by all sensor operations. This allows for complex operations such as chaining
+ * operations together or running operations in parallel.
+ * <p>
+ * Certain restrictions exist for {@link ISensorOperation}s:
+ * <p><ul>
+ * <li>{@link #execute()} should only be called once and behavior is undefined for subsequent calls.
+ * Once {@link #execute()} is called, the class should not be modified. Generally, there is no
+ * synchronization for operations.</li>
+ * <li>{@link #getStats()} should only be called after {@link #execute()}. If it is called before,
+ * the returned value is undefined.</li>
+ * <li>{@link #clone()} may be called any time and should return an operation with the same
+ * parameters as the original.</li>
+ * </ul>
+ */
+public interface ISensorOperation {
+
+    /**
+     * Executes the sensor operation.  This may throw {@link RuntimeException}s such as
+     * {@link AssertionError}s.
+     *
+     * NOTE: the operation is expected to handle interruption by:
+     * - cleaning up on {@link InterruptedException}
+     * - propagating the exception down the stack
+     */
+    public void execute() throws InterruptedException;
+
+    /**
+     * Get the stats for the operation.
+     *
+     * @return The {@link SensorStats} for the operation.
+     */
+    public SensorStats getStats();
+
+    /**
+     * Clones the {@link ISensorOperation}. The implementation should also clone all child
+     * operations, so that a cloned operation will run with the exact same parameters as the
+     * original. The stats should not be cloned.
+     *
+     * @return The cloned {@link ISensorOperation}
+     */
+    public ISensorOperation clone();
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ParallelSensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ParallelSensorOperation.java
new file mode 100644
index 0000000..5a4466c
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ParallelSensorOperation.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensoroperations;
+
+import junit.framework.Assert;
+
+import android.hardware.cts.helpers.SensorStats;
+import android.os.SystemClock;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * A {@link ISensorOperation} that executes a set of children {@link ISensorOperation}s in parallel.
+ * The children are run in parallel but are given an index label in the order they are added. This
+ * class can be combined to compose complex {@link ISensorOperation}s.
+ */
+public class ParallelSensorOperation extends AbstractSensorOperation {
+    public static final String STATS_TAG = "parallel";
+
+    private final List<ISensorOperation> mOperations = new LinkedList<ISensorOperation>();
+    private final Long mTimeout;
+    private final TimeUnit mTimeUnit;
+
+    /**
+     * Constructor for the {@link ParallelSensorOperation} without a timeout.
+     */
+    // TODO: sensor tests must always provide a timeout to prevent tests from running forever
+    public ParallelSensorOperation() {
+        mTimeout = null;
+        mTimeUnit = null;
+    }
+
+    /**
+     * Constructor for the {@link ParallelSensorOperation} with a timeout.
+     */
+    public ParallelSensorOperation(long timeout, TimeUnit timeUnit) {
+        if (timeUnit == null) {
+            throw new IllegalArgumentException("Arguments cannot be null");
+        }
+        mTimeout = timeout;
+        mTimeUnit = timeUnit;
+    }
+
+    /**
+     * Add a set of {@link ISensorOperation}s.
+     */
+    public void add(ISensorOperation ... operations) {
+        for (ISensorOperation operation : operations) {
+            if (operation == null) {
+                throw new IllegalArgumentException("Arguments cannot be null");
+            }
+            mOperations.add(operation);
+        }
+    }
+
+    /**
+     * Executes the {@link ISensorOperation}s in parallel. If an exception occurs one or more
+     * operations, the first exception will be thrown once all operations are completed.
+     */
+    @Override
+    public void execute() throws InterruptedException {
+        int operationsCount = mOperations.size();
+        ThreadPoolExecutor executor = new ThreadPoolExecutor(
+                operationsCount,
+                operationsCount,
+                1 /* keepAliveTime */,
+                TimeUnit.SECONDS,
+                new LinkedBlockingQueue<Runnable>());
+        executor.allowCoreThreadTimeOut(true);
+        executor.prestartAllCoreThreads();
+
+        ArrayList<Future<ISensorOperation>> futures = new ArrayList<Future<ISensorOperation>>();
+        for (final ISensorOperation operation : mOperations) {
+            Future<ISensorOperation> future = executor.submit(new Callable<ISensorOperation>() {
+                @Override
+                public ISensorOperation call() throws Exception {
+                    operation.execute();
+                    return operation;
+                }
+            });
+            futures.add(future);
+        }
+
+        Long executionTimeNs = null;
+        if (mTimeout != null) {
+            executionTimeNs = SystemClock.elapsedRealtimeNanos()
+                    + TimeUnit.NANOSECONDS.convert(mTimeout, mTimeUnit);
+        }
+
+        boolean hasAssertionErrors = false;
+        ArrayList<Integer> timeoutIndices = new ArrayList<Integer>();
+        ArrayList<Throwable> exceptions = new ArrayList<Throwable>();
+        for (int i = 0; i < operationsCount; ++i) {
+            Future<ISensorOperation> future = futures.get(i);
+            try {
+                ISensorOperation operation = getFutureResult(future, executionTimeNs);
+                addSensorStats(STATS_TAG, i, operation.getStats());
+            } catch (ExecutionException e) {
+                // extract the exception thrown by the worker thread
+                Throwable cause = e.getCause();
+                hasAssertionErrors |= (cause instanceof AssertionError);
+                exceptions.add(e.getCause());
+                addSensorStats(STATS_TAG, i, mOperations.get(i).getStats());
+            } catch (TimeoutException e) {
+                // we log, but we also need to interrupt the operation to terminate cleanly
+                timeoutIndices.add(i);
+                future.cancel(true /* mayInterruptIfRunning */);
+            } catch (InterruptedException e) {
+                // clean-up after ourselves by interrupting all the worker threads, and propagate
+                // the interruption status, so we stop the outer loop as well
+                executor.shutdownNow();
+                throw e;
+            }
+        }
+
+        String summary = getSummaryMessage(exceptions, timeoutIndices);
+        if (hasAssertionErrors) {
+            getStats().addValue(SensorStats.ERROR, summary);
+        }
+        if (!exceptions.isEmpty() || !timeoutIndices.isEmpty()) {
+            Assert.fail(summary);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public ParallelSensorOperation clone() {
+        ParallelSensorOperation operation = new ParallelSensorOperation();
+        for (ISensorOperation subOperation : mOperations) {
+            operation.add(subOperation.clone());
+        }
+        return operation;
+    }
+
+    /**
+     * Helper method that waits for a {@link Future} to complete, and returns its result.
+     */
+    private ISensorOperation getFutureResult(Future<ISensorOperation> future, Long timeoutNs)
+            throws ExecutionException, TimeoutException, InterruptedException {
+        if (timeoutNs == null) {
+            return future.get();
+        }
+        // cap timeout to 1ns so that join doesn't block indefinitely
+        long waitTimeNs = Math.max(timeoutNs - SystemClock.elapsedRealtimeNanos(), 1);
+        return future.get(waitTimeNs, TimeUnit.NANOSECONDS);
+    }
+
+    /**
+     * Helper method for joining the exception and timeout messages used in assertions.
+     */
+    private String getSummaryMessage(List<Throwable> exceptions, List<Integer> timeoutIndices) {
+        StringBuilder sb = new StringBuilder();
+        for (Throwable exception : exceptions) {
+            sb.append(exception.toString()).append(", ");
+        }
+
+        if (!timeoutIndices.isEmpty()) {
+            sb.append("Operation");
+            if (timeoutIndices.size() != 1) {
+                sb.append("s");
+            }
+            sb.append(" [");
+            for (Integer index : timeoutIndices) {
+                sb.append(index).append(", ");
+            }
+            sb.append("] timed out");
+        }
+
+        return sb.toString();
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/RepeatingSensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/RepeatingSensorOperation.java
new file mode 100644
index 0000000..3d682fe
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/RepeatingSensorOperation.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensoroperations;
+
+import android.hardware.cts.helpers.SensorStats;
+
+/**
+ * A {@link ISensorOperation} that executes a single {@link ISensorOperation} a given number of
+ * times. This class can be combined to compose complex {@link ISensorOperation}s.
+ */
+public class RepeatingSensorOperation extends AbstractSensorOperation {
+    public static final String STATS_TAG = "repeating";
+
+    private final ISensorOperation mOperation;
+    private final int mIterations;
+
+    /**
+     * Constructor for {@link RepeatingSensorOperation}.
+     *
+     * @param operation the {@link ISensorOperation} to run.
+     * @param iterations the number of iterations to run the operation for.
+     */
+    public RepeatingSensorOperation(ISensorOperation operation, int iterations) {
+        if (operation == null) {
+            throw new IllegalArgumentException("Arguments cannot be null");
+        }
+        mOperation = operation;
+        mIterations = iterations;
+
+    }
+
+    /**
+     * Executes the {@link ISensorOperation}s the given number of times. If an exception occurs
+     * in one iterations, it is thrown and all subsequent iterations will not run.
+     */
+    @Override
+    public void execute() throws InterruptedException {
+        for(int i = 0; i < mIterations; ++i) {
+            ISensorOperation operation = mOperation.clone();
+            try {
+                operation.execute();
+            } catch (AssertionError e) {
+                String msg = String.format("Iteration %d failed: \"%s\"", i, e.getMessage());
+                getStats().addValue(SensorStats.ERROR, msg);
+                throw new AssertionError(msg, e);
+            } finally {
+                addSensorStats(STATS_TAG, i, operation.getStats());
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public RepeatingSensorOperation clone() {
+        return new RepeatingSensorOperation(mOperation.clone(), mIterations);
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SensorOperationTest.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SensorOperationTest.java
new file mode 100644
index 0000000..bc48725
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SensorOperationTest.java
@@ -0,0 +1,345 @@
+/*
+ * 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.cts.helpers.sensoroperations;
+
+import junit.framework.TestCase;
+
+import android.hardware.cts.helpers.SensorStats;
+
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Tests for the primitive {@link ISensorOperation}s including {@link DelaySensorOperation},
+ * {@link ParallelSensorOperation}, {@link RepeatingSensorOperation} and
+ * {@link SequentialSensorOperation}.
+ */
+public class SensorOperationTest extends TestCase {
+    private static final long TEST_DURATION_THRESHOLD_MS = TimeUnit.SECONDS.toMillis(5);
+
+    /**
+     * Test that the {@link FakeSensorOperation} functions correctly. Other tests in this class
+     * rely on this operation.
+     */
+    public void testFakeSensorOperation() throws InterruptedException {
+        final int opDurationMs = 100;
+
+        ISensorOperation op = new FakeSensorOperation(opDurationMs, TimeUnit.MILLISECONDS);
+
+        assertFalse(op.getStats().flatten().containsKey("executed"));
+        long start = System.currentTimeMillis();
+        op.execute();
+        long duration = System.currentTimeMillis() - start;
+        assertTrue(Math.abs(opDurationMs - duration) < TEST_DURATION_THRESHOLD_MS);
+        assertTrue(op.getStats().flatten().containsKey("executed"));
+
+        op = new FakeSensorOperation(true, 0, TimeUnit.MILLISECONDS);
+        try {
+            op.execute();
+            fail("AssertionError expected");
+        } catch (AssertionError e) {
+            // Expected
+        }
+        assertTrue(op.getStats().flatten().keySet().contains(SensorStats.ERROR));
+    }
+
+    /**
+     * Test that the {@link DelaySensorOperation} functions correctly.
+     */
+    public void testDelaySensorOperation() throws InterruptedException {
+        final int opDurationMs = 500;
+        final int subOpDurationMs = 100;
+
+        FakeSensorOperation subOp = new FakeSensorOperation(subOpDurationMs, TimeUnit.MILLISECONDS);
+        ISensorOperation op = new DelaySensorOperation(subOp, opDurationMs, TimeUnit.MILLISECONDS);
+
+        long startMs = System.currentTimeMillis();
+        op.execute();
+        long dirationMs = System.currentTimeMillis() - startMs;
+        long durationDeltaMs = Math.abs(opDurationMs + subOpDurationMs - dirationMs);
+        assertTrue(durationDeltaMs < TEST_DURATION_THRESHOLD_MS);
+    }
+
+    /**
+     * Test that the {@link ParallelSensorOperation} functions correctly.
+     */
+    public void testParallelSensorOperation() throws InterruptedException {
+        final int subOpCount = 100;
+        final int subOpDurationMs = 500;
+
+        ParallelSensorOperation op = new ParallelSensorOperation();
+        for (int i = 0; i < subOpCount; i++) {
+            ISensorOperation subOp = new FakeSensorOperation(subOpDurationMs,
+                    TimeUnit.MILLISECONDS);
+            op.add(subOp);
+        }
+
+        Set<String> statsKeys = op.getStats().flatten().keySet();
+        assertEquals(0, statsKeys.size());
+
+        long start = System.currentTimeMillis();
+        op.execute();
+        long durationMs = System.currentTimeMillis() - start;
+        long durationDeltaMs = Math.abs(subOpDurationMs - durationMs);
+        String message = String.format(
+                "Expected duration=%sms, observed=%sms, delta=%sms, thresold=%sms",
+                subOpDurationMs,
+                durationMs,
+                durationDeltaMs,
+                TEST_DURATION_THRESHOLD_MS);
+        // starting threads might have an impact in the order of 100s ms, depending on the load of
+        // the system, so we relax the benchmark part of the test, and we just expect all operations
+        // to complete
+        assertTrue(message, durationDeltaMs < TEST_DURATION_THRESHOLD_MS);
+
+        statsKeys = op.getStats().flatten().keySet();
+        assertEquals(subOpCount, statsKeys.size());
+        for (int i = 0; i < subOpCount; i++) {
+            assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted",
+                    ParallelSensorOperation.STATS_TAG, i, SensorStats.DELIMITER)));
+        }
+    }
+
+    /**
+     * Test that the {@link ParallelSensorOperation} functions correctly if there is a failure in
+     * a child operation.
+     */
+    public void testParallelSensorOperation_fail() throws InterruptedException {
+        final int subOpCount = 100;
+
+        ParallelSensorOperation op = new ParallelSensorOperation();
+        for (int i = 0; i < subOpCount; i++) {
+            // Trigger failures in the 5th, 55th operations at t=5ms, t=55ms
+            ISensorOperation subOp = new FakeSensorOperation(i % 50 == 5, i, TimeUnit.MILLISECONDS);
+            op.add(subOp);
+        }
+
+        Set<String> statsKeys = op.getStats().flatten().keySet();
+        assertEquals(0, statsKeys.size());
+
+        try {
+            op.execute();
+            fail("AssertionError expected");
+        } catch (AssertionError e) {
+            // Expected
+            System.out.println(e.getMessage());
+        }
+
+        statsKeys = op.getStats().flatten().keySet();
+        assertEquals(subOpCount + 3, statsKeys.size());
+        for (int i = 0; i < subOpCount; i++) {
+            assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted",
+                    ParallelSensorOperation.STATS_TAG, i, SensorStats.DELIMITER)));
+            if (i % 50 == 5) {
+                assertTrue(statsKeys.contains(String.format("%s_%03d%s%s",
+                        ParallelSensorOperation.STATS_TAG, i, SensorStats.DELIMITER,
+                        SensorStats.ERROR)));
+            }
+
+        }
+        assertTrue(statsKeys.contains(SensorStats.ERROR));
+    }
+
+    /**
+     * Test that the {@link ParallelSensorOperation} functions correctly if a child exceeds the
+     * timeout.
+     */
+    public void testParallelSensorOperation_timeout() throws InterruptedException {
+        final int subOpCount = 100;
+
+        ParallelSensorOperation op = new ParallelSensorOperation(1, TimeUnit.SECONDS);
+        for (int i = 0; i < subOpCount; i++) {
+            // Trigger timeouts in the 5th, 55th operations (5 seconds vs 1 seconds)
+            ISensorOperation subOp = new FakeSensorOperation(i % 50 == 5 ? 5 : 0, TimeUnit.SECONDS);
+            op.add(subOp);
+        }
+
+        Set<String> statsKeys = op.getStats().flatten().keySet();
+        assertEquals(0, statsKeys.size());
+
+        try {
+            op.execute();
+            fail("AssertionError expected");
+        } catch (AssertionError e) {
+            // Expected
+            System.out.println(e.getMessage());
+        }
+
+        statsKeys = op.getStats().flatten().keySet();
+        assertEquals(subOpCount - 2, statsKeys.size());
+        for (int i = 0; i < subOpCount; i++) {
+            if (i % 50 != 5) {
+                assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted",
+                        ParallelSensorOperation.STATS_TAG, i, SensorStats.DELIMITER)));
+            }
+        }
+    }
+
+    /**
+     * Test that the {@link RepeatingSensorOperation} functions correctly.
+     */
+    public void testRepeatingSensorOperation() throws InterruptedException {
+        final int iterations = 10;
+        final int subOpDurationMs = 100;
+
+        ISensorOperation subOp = new FakeSensorOperation(subOpDurationMs, TimeUnit.MILLISECONDS);
+        ISensorOperation op = new RepeatingSensorOperation(subOp, iterations);
+
+        Set<String> statsKeys = op.getStats().flatten().keySet();
+        assertEquals(0, statsKeys.size());
+
+        long start = System.currentTimeMillis();
+        op.execute();
+        long duration = System.currentTimeMillis() - start;
+        assertTrue(Math.abs(subOpDurationMs * iterations - duration) < TEST_DURATION_THRESHOLD_MS);
+
+        statsKeys = op.getStats().flatten().keySet();
+        assertEquals(iterations, statsKeys.size());
+        for (int i = 0; i < iterations; i++) {
+            assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted",
+                    RepeatingSensorOperation.STATS_TAG, i, SensorStats.DELIMITER)));
+        }
+    }
+
+    /**
+     * Test that the {@link RepeatingSensorOperation} functions correctly if there is a failure in
+     * a child operation.
+     */
+    public void testRepeatingSensorOperation_fail() throws InterruptedException {
+        final int iterations = 100;
+        final int failCount = 75;
+
+        ISensorOperation subOp = new FakeSensorOperation(0, TimeUnit.MILLISECONDS) {
+            private int mExecutedCount = 0;
+            private SensorStats mFakeStats = new SensorStats();
+
+            @Override
+            public void execute() {
+                super.execute();
+                mExecutedCount++;
+
+                if (failCount == mExecutedCount) {
+                    doFail();
+                }
+            }
+
+            @Override
+            public FakeSensorOperation clone() {
+                // Don't clone
+                mFakeStats = new SensorStats();
+                return this;
+            }
+
+            @Override
+            public SensorStats getStats() {
+                return mFakeStats;
+            }
+        };
+        ISensorOperation op = new RepeatingSensorOperation(subOp, iterations);
+
+        Set<String> statsKeys = op.getStats().flatten().keySet();
+        assertEquals(0, statsKeys.size());
+
+        try {
+            op.execute();
+            fail("AssertionError expected");
+        } catch (AssertionError e) {
+            // Expected
+            System.out.println(e.getMessage());
+        }
+
+        statsKeys = op.getStats().flatten().keySet();
+        assertEquals(failCount + 2, statsKeys.size());
+        for (int i = 0; i < failCount; i++) {
+            assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted",
+                    RepeatingSensorOperation.STATS_TAG, i, SensorStats.DELIMITER)));
+        }
+        assertTrue(statsKeys.contains(String.format("%s_%03d%s%s",
+                RepeatingSensorOperation.STATS_TAG, failCount - 1, SensorStats.DELIMITER,
+                SensorStats.ERROR)));
+        assertTrue(statsKeys.contains(SensorStats.ERROR));
+    }
+
+    /**
+     * Test that the {@link SequentialSensorOperation} functions correctly.
+     */
+    public void testSequentialSensorOperation() throws InterruptedException {
+        final int subOpCount = 10;
+        final int subOpDurationMs = 100;
+
+        SequentialSensorOperation op = new SequentialSensorOperation();
+        for (int i = 0; i < subOpCount; i++) {
+            ISensorOperation subOp = new FakeSensorOperation(subOpDurationMs,
+                    TimeUnit.MILLISECONDS);
+            op.add(subOp);
+        }
+
+        Set<String> statsKeys = op.getStats().flatten().keySet();
+        assertEquals(0, statsKeys.size());
+
+        long start = System.currentTimeMillis();
+        op.execute();
+        long duration = System.currentTimeMillis() - start;
+        assertTrue(Math.abs(subOpDurationMs * subOpCount - duration) < TEST_DURATION_THRESHOLD_MS);
+
+        statsKeys = op.getStats().flatten().keySet();
+        assertEquals(subOpCount, statsKeys.size());
+        for (int i = 0; i < subOpCount; i++) {
+            assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted",
+                    SequentialSensorOperation.STATS_TAG, i, SensorStats.DELIMITER)));
+        }
+    }
+
+    /**
+     * Test that the {@link SequentialSensorOperation} functions correctly if there is a failure in
+     * a child operation.
+     */
+    public void testSequentialSensorOperation_fail() throws InterruptedException {
+        final int subOpCount = 100;
+        final int failCount = 75;
+
+        SequentialSensorOperation op = new SequentialSensorOperation();
+        for (int i = 0; i < subOpCount; i++) {
+            // Trigger a failure in the 75th operation only
+            ISensorOperation subOp = new FakeSensorOperation(i + 1 == failCount, 0,
+                    TimeUnit.MILLISECONDS);
+            op.add(subOp);
+        }
+
+        Set<String> statsKeys = op.getStats().flatten().keySet();
+        assertEquals(0, statsKeys.size());
+
+        try {
+            op.execute();
+            fail("AssertionError expected");
+        } catch (AssertionError e) {
+            // Expected
+            System.out.println(e.getMessage());
+        }
+
+        statsKeys = op.getStats().flatten().keySet();
+        assertEquals(failCount + 2, statsKeys.size());
+        for (int i = 0; i < failCount; i++) {
+            assertTrue(statsKeys.contains(String.format("%s_%03d%sexecuted",
+                    SequentialSensorOperation.STATS_TAG, i, SensorStats.DELIMITER)));
+        }
+        assertTrue(statsKeys.contains(String.format("%s_%03d%s%s",
+                SequentialSensorOperation.STATS_TAG, failCount - 1, SensorStats.DELIMITER,
+                SensorStats.ERROR)));
+        assertTrue(statsKeys.contains(SensorStats.ERROR));
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SequentialSensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SequentialSensorOperation.java
new file mode 100644
index 0000000..2ed0ca6
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SequentialSensorOperation.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cts.helpers.sensoroperations;
+
+import android.hardware.cts.helpers.SensorStats;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * A {@link ISensorOperation} that executes a set of children {@link ISensorOperation}s in a
+ * sequence. The children are executed in the order they are added. This class can be combined to
+ * compose complex {@link ISensorOperation}s.
+ */
+public class SequentialSensorOperation extends AbstractSensorOperation {
+    public static final String STATS_TAG = "sequential";
+
+    private final List<ISensorOperation> mOperations = new LinkedList<ISensorOperation>();
+
+    /**
+     * Add a set of {@link ISensorOperation}s.
+     */
+    public void add(ISensorOperation ... operations) {
+        for (ISensorOperation operation : operations) {
+            if (operation == null) {
+                throw new IllegalArgumentException("Arguments cannot be null");
+            }
+            mOperations.add(operation);
+        }
+    }
+
+    /**
+     * Executes the {@link ISensorOperation}s in the order they were added. If an exception occurs
+     * in one operation, it is thrown and all subsequent operations will not run.
+     */
+    @Override
+    public void execute() throws InterruptedException {
+        for (int i = 0; i < mOperations.size(); i++) {
+            ISensorOperation operation = mOperations.get(i);
+            try {
+                operation.execute();
+            } catch (AssertionError e) {
+                String msg = String.format("Operation %d failed: \"%s\"", i, e.getMessage());
+                getStats().addValue(SensorStats.ERROR, msg);
+                throw new AssertionError(msg, e);
+            } finally {
+                addSensorStats(STATS_TAG, i, operation.getStats());
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public SequentialSensorOperation clone() {
+        SequentialSensorOperation operation = new SequentialSensorOperation();
+        for (ISensorOperation subOperation : mOperations) {
+            operation.add(subOperation.clone());
+        }
+        return operation;
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorFlushOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorFlushOperation.java
new file mode 100644
index 0000000..d5aa4b9
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorFlushOperation.java
@@ -0,0 +1,67 @@
+/*
+ * 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.cts.helpers.sensoroperations;
+
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.TestSensorEventListener;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A {@link ISensorOperation} used to verify that sensor events and sensor values are correct.
+ * <p>
+ * Provides methods to set test expectations as well as providing a set of default expectations
+ * depending on sensor type.  When {{@link #execute()} is called, the sensor will collect the
+ * events, call flush, and then run all the tests.
+ * </p>
+ */
+public class TestSensorFlushOperation extends VerifiableSensorOperation {
+    private final Long mDuration;
+    private final TimeUnit mTimeUnit;
+
+    /**
+     * Create a {@link TestSensorOperation}.
+     *
+     * @param environment the test environment
+     * @param duration the duration to gather events before calling {@code SensorManager.flush()}
+     * @param timeUnit the time unit of the duration
+     */
+    public TestSensorFlushOperation(
+            TestSensorEnvironment environment,
+            long duration,
+            TimeUnit timeUnit) {
+        super(environment);
+        mDuration = duration;
+        mTimeUnit = timeUnit;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void doExecute(TestSensorEventListener listener) throws InterruptedException {
+        mSensorManager.runSensorAndFlush(listener, mDuration, mTimeUnit);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected VerifiableSensorOperation doClone() {
+        return new TestSensorFlushOperation(mEnvironment, mDuration,mTimeUnit);
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorOperation.java
new file mode 100644
index 0000000..695e1a7
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorOperation.java
@@ -0,0 +1,98 @@
+/*
+ * 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.cts.helpers.sensoroperations;
+
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.TestSensorEventListener;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A {@link ISensorOperation} used to verify that sensor events and sensor values are correct.
+ * <p>
+ * Provides methods to set test expectations as well as providing a set of default expectations
+ * depending on sensor type.  When {{@link #execute()} is called, the sensor will collect the
+ * events and then run all the tests.
+ * </p>
+ */
+public class TestSensorOperation extends VerifiableSensorOperation {
+    private final Integer mEventCount;
+    private final Long mDuration;
+    private final TimeUnit mTimeUnit;
+
+    /**
+     * Create a {@link TestSensorOperation}.
+     *
+     * @param environment the test environment
+     * @param eventCount the number of events to gather
+     */
+    public TestSensorOperation(TestSensorEnvironment environment, int eventCount) {
+        this(environment, eventCount, null /* duration */, null /* timeUnit */);
+    }
+
+    /**
+     * Create a {@link TestSensorOperation}.
+     *
+     * @param environment the test environment
+     * @param duration the duration to gather events for
+     * @param timeUnit the time unit of the duration
+     */
+    public TestSensorOperation(
+            TestSensorEnvironment environment,
+            long duration,
+            TimeUnit timeUnit) {
+        this(environment, null /* eventCount */, duration, timeUnit);
+    }
+
+    /**
+     * Private helper constructor.
+     */
+    private TestSensorOperation(
+            TestSensorEnvironment environment,
+            Integer eventCount,
+            Long duration,
+            TimeUnit timeUnit) {
+        super(environment);
+        mEventCount = eventCount;
+        mDuration = duration;
+        mTimeUnit = timeUnit;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void doExecute(TestSensorEventListener listener) throws InterruptedException {
+        if (mEventCount != null) {
+            mSensorManager.runSensor(listener, mEventCount);
+        } else {
+            mSensorManager.runSensor(listener, mDuration, mTimeUnit);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected VerifiableSensorOperation doClone() {
+        if (mEventCount != null) {
+            return new TestSensorOperation(mEnvironment, mEventCount);
+        } else {
+            return new TestSensorOperation(mEnvironment, mDuration, mTimeUnit);
+        }
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/VerifiableSensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/VerifiableSensorOperation.java
new file mode 100644
index 0000000..57018eb
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/VerifiableSensorOperation.java
@@ -0,0 +1,156 @@
+/*
+ * 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.cts.helpers.sensoroperations;
+
+import junit.framework.Assert;
+
+import android.hardware.cts.helpers.SensorCtsHelper;
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.TestSensorEventListener;
+import android.hardware.cts.helpers.TestSensorManager;
+import android.hardware.cts.helpers.ValidatingSensorEventListener;
+import android.hardware.cts.helpers.sensorverification.EventGapVerification;
+import android.hardware.cts.helpers.sensorverification.EventOrderingVerification;
+import android.hardware.cts.helpers.sensorverification.FrequencyVerification;
+import android.hardware.cts.helpers.sensorverification.ISensorVerification;
+import android.hardware.cts.helpers.sensorverification.JitterVerification;
+import android.hardware.cts.helpers.sensorverification.MagnitudeVerification;
+import android.hardware.cts.helpers.sensorverification.MeanVerification;
+import android.hardware.cts.helpers.sensorverification.StandardDeviationVerification;
+
+import java.util.Collection;
+import java.util.HashSet;
+
+/**
+ * A {@link ISensorOperation} used to verify that sensor events and sensor values are correct.
+ * <p>
+ * Provides methods to set test expectations as well as providing a set of default expectations
+ * depending on sensor type.  When {{@link #execute()} is called, the sensor will collect the
+ * events and then run all the tests.
+ * </p>
+ */
+public abstract class VerifiableSensorOperation extends AbstractSensorOperation {
+    protected final TestSensorManager mSensorManager;
+    protected final TestSensorEnvironment mEnvironment;
+
+    private final Collection<ISensorVerification> mVerifications =
+            new HashSet<ISensorVerification>();
+
+    private boolean mLogEvents = false;
+
+    /**
+     * Create a {@link TestSensorOperation}.
+     *
+     * @param environment the test environment
+     */
+    public VerifiableSensorOperation(TestSensorEnvironment environment) {
+        mEnvironment = environment;
+        mSensorManager = new TestSensorManager(mEnvironment);
+    }
+
+    /**
+     * Set whether to log events.
+     */
+    public void setLogEvents(boolean logEvents) {
+        mLogEvents = logEvents;
+    }
+
+    /**
+     * Set all of the default test expectations.
+     */
+    public void addDefaultVerifications() {
+        addVerification(EventGapVerification.getDefault(mEnvironment));
+        addVerification(EventOrderingVerification.getDefault(mEnvironment));
+        addVerification(FrequencyVerification.getDefault(mEnvironment));
+        addVerification(JitterVerification.getDefault(mEnvironment));
+        addVerification(MagnitudeVerification.getDefault(mEnvironment));
+        addVerification(MeanVerification.getDefault(mEnvironment));
+        // Skip SigNumVerification since it has no default
+        addVerification(StandardDeviationVerification.getDefault(mEnvironment));
+    }
+
+    public void addVerification(ISensorVerification verification) {
+        if (verification != null) {
+            mVerifications.add(verification);
+        }
+    }
+
+    /**
+     * Collect the specified number of events from the sensor and run all enabled verifications.
+     */
+    @Override
+    public void execute() throws InterruptedException {
+        getStats().addValue("sensor_name", mEnvironment.getSensor().getName());
+
+        ValidatingSensorEventListener listener = new ValidatingSensorEventListener(mVerifications);
+        listener.setLogEvents(mLogEvents);
+
+        doExecute(listener);
+
+        boolean failed = false;
+        StringBuilder sb = new StringBuilder();
+        for (ISensorVerification verification : mVerifications) {
+            failed |= evaluateResults(verification, sb);
+        }
+
+        if (failed) {
+            String msg = SensorCtsHelper
+                    .formatAssertionMessage("VerifySensorOperation", mEnvironment, sb.toString());
+            getStats().addValue(SensorStats.ERROR, msg);
+            Assert.fail(msg);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public VerifiableSensorOperation clone() {
+        VerifiableSensorOperation operation = doClone();
+        for (ISensorVerification verification : mVerifications) {
+            operation.addVerification(verification.clone());
+        }
+        return operation;
+    }
+
+    /**
+     * Execute operations in a {@link TestSensorManager}.
+     */
+    protected abstract void doExecute(TestSensorEventListener listener) throws InterruptedException;
+
+    /**
+     * Clone the subclass operation.
+     */
+    protected abstract VerifiableSensorOperation doClone();
+
+    /**
+     * Evaluate the results of a test, aggregate the stats, and build the error message.
+     */
+    private boolean evaluateResults(ISensorVerification verification, StringBuilder sb) {
+        try {
+            verification.verify(mEnvironment, getStats());
+        } catch (AssertionError e) {
+            if (sb.length() > 0) {
+                sb.append(", ");
+            }
+            sb.append(e.getMessage());
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/WakeLockOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/WakeLockOperation.java
new file mode 100644
index 0000000..b500ea7
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/WakeLockOperation.java
@@ -0,0 +1,89 @@
+/*
+ * 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.cts.helpers.sensoroperations;
+
+import android.content.Context;
+import android.hardware.cts.helpers.SensorStats;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
+
+/**
+ * An {@link ISensorOperation} which holds a wakelock while performing another
+ * {@link ISensorOperation}.
+ */
+public class WakeLockOperation extends AbstractSensorOperation {
+    private static final String TAG = "WakeLockOperation";
+
+    private final ISensorOperation mOperation;
+    private final Context mContext;
+    private final int mWakelockFlags;
+
+    /**
+     * Constructor for {@link WakeLockOperation}.
+     *
+     * @param operation the child {@link ISensorOperation} to perform after the delay
+     * @param context the context used to access the power manager
+     * @param wakelockFlags the flags used when acquiring the wakelock
+     */
+    public WakeLockOperation(ISensorOperation operation, Context context, int wakelockFlags) {
+        mOperation = operation;
+        mContext = context;
+        mWakelockFlags = wakelockFlags;
+    }
+
+    /**
+     * Constructor for {@link WakeLockOperation}.
+     *
+     * @param operation the child {@link ISensorOperation} to perform after the delay
+     * @param context the context used to access the power manager
+     */
+    public WakeLockOperation(ISensorOperation operation, Context context) {
+        this(operation, context, PowerManager.PARTIAL_WAKE_LOCK);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void execute() throws InterruptedException {
+        PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+        WakeLock wakeLock = pm.newWakeLock(mWakelockFlags, TAG);
+
+        wakeLock.acquire();
+        try {
+            mOperation.execute();
+        } finally {
+            wakeLock.release();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public SensorStats getStats() {
+        return mOperation.getStats();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public ISensorOperation clone() {
+        return new WakeLockOperation(mOperation, mContext, mWakelockFlags);
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/AbstractMeanVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/AbstractMeanVerification.java
new file mode 100644
index 0000000..b755304
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/AbstractMeanVerification.java
@@ -0,0 +1,66 @@
+/*
+ * 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.cts.helpers.sensorverification;
+
+import junit.framework.Assert;
+
+import android.hardware.cts.helpers.TestSensorEvent;
+
+/**
+ * Abstract class that calculates of the mean event values.
+ */
+public abstract class AbstractMeanVerification extends AbstractSensorVerification {
+    private float[] mSums = null;
+    private int mCount = 0;
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void addSensorEventInternal(TestSensorEvent event) {
+        if (mSums == null) {
+            mSums = new float[event.values.length];
+        }
+        Assert.assertEquals(mSums.length, event.values.length);
+        for (int i = 0; i < mSums.length; i++) {
+            mSums[i] += event.values[i];
+        }
+        mCount++;
+    }
+
+    /**
+     * Return the number of events.
+     */
+    protected int getCount() {
+        return mCount;
+    }
+
+    /**
+     * Return the means of the event values.
+     */
+    protected float[] getMeans() {
+        if (mCount < 0) {
+            return null;
+        }
+
+        float[] means = new float[mSums.length];
+        for (int i = 0; i < mSums.length; i++) {
+            means[i] = mSums[i] / mCount;
+        }
+        return means;
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/AbstractSensorVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/AbstractSensorVerification.java
new file mode 100644
index 0000000..911ae3a
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/AbstractSensorVerification.java
@@ -0,0 +1,70 @@
+/*
+ * 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.cts.helpers.sensorverification;
+
+import android.hardware.cts.helpers.TestSensorEvent;
+
+/**
+ * Abstract class that deals with the synchronization of the sensor verifications.
+ */
+public abstract class AbstractSensorVerification implements ISensorVerification {
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public synchronized void addSensorEvents(TestSensorEvent ... events) {
+        for (TestSensorEvent event : events) {
+            addSensorEventInternal(event);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public synchronized void addSensorEvent(TestSensorEvent event) {
+        addSensorEventInternal(event);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public abstract ISensorVerification clone();
+
+    /**
+     * Used by implementing classes to add a sensor event.
+     */
+    protected abstract void addSensorEventInternal(TestSensorEvent event);
+
+    /**
+     * Helper class to store the index, previous event, and current event.
+     */
+    protected class IndexedEventPair {
+        public final int index;
+        public final TestSensorEvent event;
+        public final TestSensorEvent previousEvent;
+
+        public IndexedEventPair(int index, TestSensorEvent event,
+                TestSensorEvent previousEvent) {
+            this.index = index;
+            this.event = event;
+            this.previousEvent = previousEvent;
+        }
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventGapVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventGapVerification.java
new file mode 100644
index 0000000..156afa8
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventGapVerification.java
@@ -0,0 +1,123 @@
+package android.hardware.cts.helpers.sensorverification;
+
+import junit.framework.Assert;
+
+import android.hardware.Sensor;
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A {@link ISensorVerification} which verifies that there are no missing events. This is done by
+ * checking the last received sensor timestamp and checking that it is within 1.8 * the expected
+ * period.
+ */
+public class EventGapVerification extends AbstractSensorVerification {
+    public static final String PASSED_KEY = "missing_event_passed";
+
+    // Fail if no events are delivered within 1.8 times the expected interval
+    private static final double THRESHOLD = 1.8;
+
+    // Number of indices to print in assert message before truncating
+    private static final int TRUNCATE_MESSAGE_LENGTH = 3;
+
+    // Number of events to truncate (discard) from the initial events received
+    private static final int TRUNCATE_EVENTS_COUNT = 1;
+
+    private final int mExpectedDelayUs;
+
+    private final List<IndexedEventPair> mEventGaps = new LinkedList<IndexedEventPair>();
+    private TestSensorEvent mPreviousEvent = null;
+    private int mIndex = 0;
+
+    /**
+     * Construct a {@link EventGapVerification}
+     *
+     * @param expectedDelayUs the expected period in us.
+     */
+    public EventGapVerification(int expectedDelayUs) {
+        mExpectedDelayUs = expectedDelayUs;
+    }
+
+    /**
+     * Get the default {@link EventGapVerification}.
+     *
+     * @param environment the test environment
+     * @return the verification or null if the verification is not a continuous mode sensor.
+     */
+    public static EventGapVerification getDefault(TestSensorEnvironment environment) {
+        if (environment.getSensor().getReportingMode() != Sensor.REPORTING_MODE_CONTINUOUS) {
+            return null;
+        }
+        return new EventGapVerification(environment.getExpectedSamplingPeriodUs());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void verify(TestSensorEnvironment environment, SensorStats stats) {
+        if (environment.isSensorSamplingRateOverloaded()) {
+            // the verification is not reliable on environments under load
+            stats.addValue(PASSED_KEY, true);
+            return;
+        }
+
+        final int count = mEventGaps.size();
+        stats.addValue(PASSED_KEY, count == 0);
+        stats.addValue(SensorStats.EVENT_GAP_COUNT_KEY, count);
+
+        final int[] indices = new int[count];
+        for (int i = 0; i < indices.length; i++) {
+            indices[i] = mEventGaps.get(i).index;
+        }
+        stats.addValue(SensorStats.EVENT_GAP_POSITIONS_KEY, indices);
+
+        if (count > 0) {
+            StringBuilder sb = new StringBuilder();
+            sb.append(count).append(" events gaps: ");
+            for (int i = 0; i < Math.min(count, TRUNCATE_MESSAGE_LENGTH); i++) {
+                IndexedEventPair info = mEventGaps.get(i);
+                sb.append(String.format("position=%d, delta_time=%dns; ", info.index,
+                        info.event.timestamp - info.previousEvent.timestamp));
+            }
+            if (count > TRUNCATE_MESSAGE_LENGTH) {
+                sb.append(count - TRUNCATE_MESSAGE_LENGTH).append(" more; ");
+            }
+            sb.append(String.format("(expected <%dns)",
+                    TimeUnit.NANOSECONDS.convert((int) (THRESHOLD * mExpectedDelayUs),
+                            TimeUnit.MICROSECONDS)));
+            Assert.fail(sb.toString());
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public EventGapVerification clone() {
+        return new EventGapVerification(mExpectedDelayUs);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void addSensorEventInternal(TestSensorEvent event) {
+        if (mIndex >= TRUNCATE_EVENTS_COUNT) {
+            if (mPreviousEvent != null) {
+                long deltaNs = event.timestamp - mPreviousEvent.timestamp;
+                long deltaUs = TimeUnit.MICROSECONDS.convert(deltaNs, TimeUnit.NANOSECONDS);
+                if (deltaUs > mExpectedDelayUs * THRESHOLD) {
+                    mEventGaps.add(new IndexedEventPair(mIndex, event, mPreviousEvent));
+                }
+            }
+            mPreviousEvent = event;
+        }
+        mIndex++;
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventGapVerificationTest.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventGapVerificationTest.java
new file mode 100644
index 0000000..d01e108
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventGapVerificationTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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.cts.helpers.sensorverification;
+
+import junit.framework.TestCase;
+
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+/**
+ * Tests for {@link EventGapVerification}.
+ */
+public class EventGapVerificationTest extends TestCase {
+
+    /**
+     * Test that the verification passes when there are no results.
+     */
+    public void testVerify_no_events() {
+        // Timestamps in ns, expected in us
+        runVerification(1000, new long[]{}, true, new int[]{});
+    }
+
+    /**
+     * Test that the verification passes when there are not missing events.
+     */
+    public void testVerify_correct() {
+        // Timestamps in ns, expected in us
+        long[] timestamps = {1000000, 2000000, 3000000, 4000000, 5000000};
+        runVerification(1000, timestamps, true, new int[]{});
+    }
+
+    /**
+     * Test that the verification passes when there are not missing events but some jitter.
+     */
+    public void testVerify_jitter() {
+        // Timestamps in ns, expected in us
+        long[] timestamps = {1100000, 2050000, 2990000, 4000000, 4950000};
+        runVerification(1000, timestamps, true, new int[]{});
+    }
+
+    /**
+     * Test that the verification fails when there are missing events.
+     */
+    public void testVerify_missing_events() {
+        // Timestamps in ns, expected in us
+        long[] timestamps = {1000000, 2000000, 3000000, 5000000, 6000000};
+        runVerification(1000, timestamps, false, new int[]{3});
+    }
+
+    private void runVerification(int expected, long[] timestamps, boolean pass,
+            int[] indices) {
+        SensorStats stats = new SensorStats();
+        ISensorVerification verification = getVerification(expected, timestamps);
+        TestSensorEnvironment environment = new TestSensorEnvironment(null, null, false, 0, 0);
+        if (pass) {
+            verification.verify(environment, stats);
+        } else {
+            boolean failed = false;
+            try {
+                verification.verify(environment, stats);
+            } catch (AssertionError e) {
+                // Expected;
+                failed = true;
+            }
+            assertTrue("Expected an AssertionError", failed);
+        }
+        assertEquals(pass, stats.getValue(EventGapVerification.PASSED_KEY));
+        assertEquals(indices.length, stats.getValue(SensorStats.EVENT_GAP_COUNT_KEY));
+        assertNotNull(stats.getValue(SensorStats.EVENT_GAP_POSITIONS_KEY));
+        int[] actualIndices = (int[]) stats.getValue(SensorStats.EVENT_GAP_POSITIONS_KEY);
+        assertEquals(indices.length, actualIndices.length);
+
+        for (int i = 0; i < indices.length; i++) {
+            assertEquals(indices[i], actualIndices[i]);
+        }
+    }
+
+    private ISensorVerification getVerification(int expected, long ... timestamps) {
+        ISensorVerification verification = new EventGapVerification(expected);
+        for (long timestamp : timestamps) {
+            verification.addSensorEvent(new TestSensorEvent(null, timestamp, 0, null));
+        }
+        return verification;
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventOrderingVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventOrderingVerification.java
new file mode 100644
index 0000000..6598725
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventOrderingVerification.java
@@ -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.
+ */
+
+package android.hardware.cts.helpers.sensorverification;
+
+import junit.framework.Assert;
+
+import android.hardware.Sensor;
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * A {@link ISensorVerification} which verifies that all events are received in the correct order.
+ */
+public class EventOrderingVerification extends AbstractSensorVerification {
+    public static final String PASSED_KEY = "event_out_of_order_passed";
+
+    // Number of indices to print in assert message before truncating
+    private static final int TRUNCATE_MESSAGE_LENGTH = 3;
+
+    private Long mMaxTimestamp = null;
+    private final List<IndexedEventPair> mOutOfOrderEvents = new LinkedList<IndexedEventPair>();
+    private TestSensorEvent mPreviousEvent = null;
+    private int mIndex = 0;
+
+    /**
+     * Get the default {@link EventOrderingVerification} for a sensor.
+     *
+     * @param environment the test environment
+     * @return the verification or null if the verification does not apply to the sensor.
+     */
+    @SuppressWarnings("deprecation")
+    public static EventOrderingVerification getDefault(TestSensorEnvironment environment) {
+        int reportingMode = environment.getSensor().getReportingMode();
+        if (reportingMode != Sensor.REPORTING_MODE_CONTINUOUS
+                && reportingMode != Sensor.REPORTING_MODE_ON_CHANGE) {
+            return null;
+        }
+        return new EventOrderingVerification();
+    }
+
+    /**
+     * Verify that the events are in the correct order.  Add {@value #PASSED_KEY},
+     * {@value SensorStats#EVENT_OUT_OF_ORDER_COUNT_KEY}, and
+     * {@value SensorStats#EVENT_OUT_OF_ORDER_POSITIONS_KEY} keys to {@link SensorStats}.
+     *
+     * @throws AssertionError if the verification failed.
+     */
+    @Override
+    public void verify(TestSensorEnvironment environment, SensorStats stats) {
+        verify(stats);
+    }
+
+    /**
+     * Visible for unit tests only.
+     */
+    void verify(SensorStats stats) {
+        final int count = mOutOfOrderEvents.size();
+        stats.addValue(PASSED_KEY, count == 0);
+        stats.addValue(SensorStats.EVENT_OUT_OF_ORDER_COUNT_KEY, count);
+
+        final int[] indices = new int[count];
+        for (int i = 0; i < indices.length; i++) {
+            indices[i] = mOutOfOrderEvents.get(i).index;
+        }
+        stats.addValue(SensorStats.EVENT_OUT_OF_ORDER_POSITIONS_KEY, indices);
+
+        if (count > 0) {
+            StringBuilder sb = new StringBuilder();
+            sb.append(count).append(" events out of order: ");
+            for (int i = 0; i < Math.min(count, TRUNCATE_MESSAGE_LENGTH); i++) {
+                IndexedEventPair info = mOutOfOrderEvents.get(i);
+                sb.append(String.format("position=%d, previous=%d, timestamp=%d; ", info.index,
+                        info.previousEvent.timestamp, info.event.timestamp));
+            }
+            if (count > TRUNCATE_MESSAGE_LENGTH) {
+                sb.append(count - TRUNCATE_MESSAGE_LENGTH).append(" more");
+            } else {
+                // Delete the trailing "; "
+                sb.delete(sb.length() - 2, sb.length());
+            }
+
+            Assert.fail(sb.toString());
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public EventOrderingVerification clone() {
+        return new EventOrderingVerification();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void addSensorEventInternal(TestSensorEvent event) {
+        if (mPreviousEvent == null) {
+            mMaxTimestamp = event.timestamp;
+        } else {
+            if (event.timestamp < mMaxTimestamp) {
+                mOutOfOrderEvents.add(new IndexedEventPair(mIndex, event, mPreviousEvent));
+            } else if (event.timestamp > mMaxTimestamp) {
+                mMaxTimestamp = event.timestamp;
+            }
+        }
+
+        mPreviousEvent = event;
+        mIndex++;
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventOrderingVerificationTest.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventOrderingVerificationTest.java
new file mode 100644
index 0000000..88d5c19
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/EventOrderingVerificationTest.java
@@ -0,0 +1,122 @@
+/*
+ * 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.cts.helpers.sensorverification;
+
+import junit.framework.TestCase;
+
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tests for {@link EventOrderingVerification}.
+ */
+public class EventOrderingVerificationTest extends TestCase {
+
+    /**
+     * Test that the verification passes when there are no results.
+     */
+    public void testNoEvents() {
+        SensorStats stats = new SensorStats();
+        EventOrderingVerification verification = getVerification();
+        verification.verify(stats);
+        verifyStats(stats, true, 0);
+    }
+
+    /**
+     * Test that the verification passes when the timestamps are the same.
+     */
+    public void testSameTimestamp() {
+        SensorStats stats = new SensorStats();
+        EventOrderingVerification verification = getVerification(0, 0, 0, 0, 0);
+        verification.verify(stats);
+        verifyStats(stats, true, 0);
+    }
+
+    /**
+     * Test that the verification passes when the timestamps are increasing.
+     */
+    public void testSequentialTimestamp() {
+        SensorStats stats = new SensorStats();
+        EventOrderingVerification verification = getVerification(0, 1, 2, 3, 4);
+        verification.verify(stats);
+        verifyStats(stats, true, 0);
+    }
+
+    /**
+     * Test that the verification fails when there is one event out of order.
+     */
+    public void testSingleOutofOrder() {
+        SensorStats stats = new SensorStats();
+        EventOrderingVerification verification = getVerification(0, 2, 1, 3, 4);
+        try {
+            verification.verify(stats);
+            fail("Expected an AssertionError");
+        } catch (AssertionError e) {
+            // Expected;
+        }
+        verifyStats(stats, false, 1);
+        List<Integer> indices = getIndices(stats);
+        assertTrue(indices.contains(2));
+    }
+
+    /**
+     * Test that the verification fails when there are multiple events out of order.
+     */
+    public void testMultipleOutOfOrder() {
+        SensorStats stats = new SensorStats();
+        EventOrderingVerification verification = getVerification(4, 0, 1, 2, 3);
+        try {
+            verification.verify(stats);
+            fail("Expected an AssertionError");
+        } catch (AssertionError e) {
+            // Expected;
+        }
+        verifyStats(stats, false, 4);
+        List<Integer> indices = getIndices(stats);
+        assertTrue(indices.contains(1));
+        assertTrue(indices.contains(2));
+        assertTrue(indices.contains(3));
+        assertTrue(indices.contains(4));
+    }
+
+    private EventOrderingVerification getVerification(long ... timestamps) {
+        EventOrderingVerification verification = new EventOrderingVerification();
+        for (long timestamp : timestamps) {
+            verification.addSensorEvent(new TestSensorEvent(null, timestamp, 0, null));
+        }
+        return verification;
+    }
+
+    private void verifyStats(SensorStats stats, boolean passed, int count) {
+        assertEquals(passed, stats.getValue(EventOrderingVerification.PASSED_KEY));
+        assertEquals(count, stats.getValue(SensorStats.EVENT_OUT_OF_ORDER_COUNT_KEY));
+        assertNotNull(stats.getValue(SensorStats.EVENT_OUT_OF_ORDER_POSITIONS_KEY));
+    }
+
+    private List<Integer> getIndices(SensorStats stats) {
+        int[] primitiveIndices = (int[]) stats.getValue(
+                SensorStats.EVENT_OUT_OF_ORDER_POSITIONS_KEY);
+        List<Integer> indices = new ArrayList<Integer>(primitiveIndices.length);
+        for (int index : primitiveIndices) {
+            indices.add(index);
+        }
+        return indices;
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/FrequencyVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/FrequencyVerification.java
new file mode 100644
index 0000000..cf34f28
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/FrequencyVerification.java
@@ -0,0 +1,172 @@
+/*
+ * 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.cts.helpers.sensorverification;
+
+import junit.framework.Assert;
+
+import android.hardware.Sensor;
+import android.hardware.cts.helpers.SensorCtsHelper;
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.TestSensorEvent;
+import android.util.Log;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A {@link ISensorVerification} which verifies that the sensor frequency are within the expected
+ * range.
+ */
+public class FrequencyVerification extends AbstractSensorVerification {
+    public static final String PASSED_KEY = "frequency_passed";
+    private static final String LOG_TAG = FrequencyVerification.class.getSimpleName();
+
+    // Lowest acceptable frequency, as percentage of the requested one.
+    private static final int DEFAULT_LOWER_THRESHOLD = 90;
+    // Highest acceptable frequency, as percentage of the requested one.
+    private static final int DEFAULT_UPPER_THRESHOLD = 220;
+
+    private final double mLowerThresholdHz;
+    private final double mUpperThresholdHz;
+
+    private long mMinTimestamp = 0;
+    private long mMaxTimestamp = 0;
+    private int mCount = 0;
+
+    /**
+     * Construct a {@link FrequencyVerification}.
+     *
+     * @param lowerTheshold Lowest acceptable frequency Hz.
+     * @param upperThreshold Highest acceptable frequency Hz.
+     */
+    public FrequencyVerification(double lowerTheshold, double upperThreshold) {
+        mLowerThresholdHz = lowerTheshold;
+        mUpperThresholdHz = upperThreshold;
+    }
+
+    /**
+     * Get the default {@link FrequencyVerification} for a sensor.
+     *
+     * @param environment the test environment
+     * @return the verification or null if the verification does not apply to the sensor.
+     */
+    public static FrequencyVerification getDefault(TestSensorEnvironment environment) {
+        Sensor sensor = environment.getSensor();
+        if (sensor.getReportingMode() != Sensor.REPORTING_MODE_CONTINUOUS) {
+            return null;
+        }
+
+        Log.i(LOG_TAG, String.format(
+                "Preparing frequency test for \"%s\" for which minDelay=%dus and maxDelay=%dus",
+                sensor.getName(),
+                sensor.getMinDelay(),
+                sensor.getMaxDelay()));
+        double maxDelayUs = sensor.getMaxDelay();
+        if (maxDelayUs <= 0) {
+            // This sensor didn't report its maxDelay.
+            // It might be only capable of producing its max rate.
+            // Do as if it reported its minDelay as its maxDelay.
+            Log.w(LOG_TAG, "This sensor (" + sensor.getName() + ") didn't report its maxDelay."
+                    + "Please update it in the sensor HAL to avoid failures in coming "
+                    + "android releases.");
+            maxDelayUs = sensor.getMinDelay();
+        }
+
+        if (environment.isSensorSamplingRateOverloaded()) {
+            maxDelayUs = sensor.getMinDelay();
+        }
+
+        // Convert the rateUs parameter into a delay in microseconds and rate in Hz.
+        double delayUs = environment.getRequestedSamplingPeriodUs();
+
+        // When rateUs > maxDelay, the sensor can do as if we requested maxDelay.
+        double upperExpectedHz = SensorCtsHelper.getFrequency(
+                Math.min(delayUs, maxDelayUs), TimeUnit.MICROSECONDS);
+        // When rateUs < minDelay, the sensor can do as if we requested minDelay
+        double lowerExpectedHz = SensorCtsHelper.getFrequency(
+                Math.max(delayUs, sensor.getMinDelay()), TimeUnit.MICROSECONDS);
+
+        // Set the pass thresholds based on default multipliers.
+        double lowerThresholdHz = lowerExpectedHz * DEFAULT_LOWER_THRESHOLD / 100;
+        double upperThresholdHz = upperExpectedHz * DEFAULT_UPPER_THRESHOLD / 100;
+
+        return new FrequencyVerification(lowerThresholdHz, upperThresholdHz);
+    }
+
+    /**
+     * Verify that the frequency is correct. Add {@value #PASSED_KEY} and
+     * {@value SensorStats#FREQUENCY_KEY} keys to {@link SensorStats}.
+     *
+     * @throws AssertionError if the verification failed.
+     */
+    @Override
+    public void verify(TestSensorEnvironment environment, SensorStats stats) {
+        if (mCount < 2) {
+            stats.addValue(PASSED_KEY, true);
+            return;
+        }
+
+        double measuredFrequencyHz = SensorCtsHelper.getFrequency(
+                ((double) (mMaxTimestamp - mMinTimestamp)) / (mCount - 1), TimeUnit.NANOSECONDS);
+        boolean failed = (measuredFrequencyHz <= mLowerThresholdHz
+                || measuredFrequencyHz >= mUpperThresholdHz);
+
+        stats.addValue(SensorStats.FREQUENCY_KEY, measuredFrequencyHz);
+        stats.addValue(PASSED_KEY, !failed);
+        String resultString = String.format(
+                "Requested \"%s\" at %.2fHz (expecting between %.2fHz and %.2fHz, measured %.2fHz)",
+                environment.getSensor().getName(),
+                environment.getFrequencyHz(),
+                mLowerThresholdHz,
+                mUpperThresholdHz,
+                measuredFrequencyHz);
+
+        if (failed) {
+            Log.e(LOG_TAG, "Frequency test FAIL: " + resultString);
+            Assert.fail(String.format("Frequency out of range: " + resultString));
+        } else {
+            Log.i(LOG_TAG, "Frequency test pass: " + resultString);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public FrequencyVerification clone() {
+        return new FrequencyVerification(mLowerThresholdHz, mUpperThresholdHz);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void addSensorEventInternal(TestSensorEvent event) {
+        if (mCount == 0) {
+            mMinTimestamp = event.timestamp;
+            mMaxTimestamp = event.timestamp;
+        } else {
+            if (mMinTimestamp > event.timestamp) {
+                mMinTimestamp = event.timestamp;
+            }
+            if (mMaxTimestamp < event.timestamp) {
+                mMaxTimestamp = event.timestamp;
+            }
+        }
+        mCount++;
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/FrequencyVerificationTest.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/FrequencyVerificationTest.java
new file mode 100644
index 0000000..24349ce
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/FrequencyVerificationTest.java
@@ -0,0 +1,92 @@
+/*
+ * 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.cts.helpers.sensorverification;
+
+import android.hardware.Sensor;
+import android.hardware.cts.SensorTestCase;
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+/**
+ * Tests for {@link EventOrderingVerification}.
+ */
+public class FrequencyVerificationTest extends SensorTestCase {
+
+    /**
+     * Test that the verifications passes/fails based on threshold given.
+     */
+    public void testVerifification() {
+        long[] timestamps = {0, 1000000, 2000000, 3000000, 4000000};  // 1000Hz
+
+        SensorStats stats = new SensorStats();
+        ISensorVerification verification = getVerification(999.0, 1001.0, timestamps);
+        verification.verify(getEnvironment(1000), stats);
+        verifyStats(stats, true, 1000.0);
+
+        stats = new SensorStats();
+        verification = getVerification(850.0, 1050.0, timestamps);
+        verification.verify(getEnvironment(950), stats);
+        verifyStats(stats, true, 1000.0);
+
+        stats = new SensorStats();
+        verification = getVerification(950.0, 1150.0, timestamps);
+        verification.verify(getEnvironment(1050), stats);
+        verifyStats(stats, true, 1000.0);
+
+        stats = new SensorStats();
+        verification = getVerification(850.0, 975.0, timestamps);
+        try {
+            verification.verify(getEnvironment(950), stats);
+            fail("Expected an AssertionError");
+        } catch (AssertionError e) {
+            // Expected;
+        }
+        verifyStats(stats, false, 1000.0);
+
+        stats = new SensorStats();
+        verification = getVerification(1025.0, 1150.0, timestamps);
+        try {
+            verification.verify(getEnvironment(1050), stats);
+            fail("Expected an AssertionError");
+        } catch (AssertionError e) {
+            // Expected;
+        }
+        verifyStats(stats, false, 1000.0);
+    }
+
+    private TestSensorEnvironment getEnvironment(int rateUs) {
+        return new TestSensorEnvironment(getContext(), Sensor.TYPE_ALL, rateUs);
+    }
+
+    private ISensorVerification getVerification(
+            double lowerThreshold,
+            double upperThreshold,
+            long ... timestamps) {
+        ISensorVerification verification =
+                new FrequencyVerification(lowerThreshold, upperThreshold);
+        for (long timestamp : timestamps) {
+            verification.addSensorEvent(new TestSensorEvent(null, timestamp, 0, null));
+        }
+        return verification;
+    }
+
+    private void verifyStats(SensorStats stats, boolean passed, double frequency) {
+        assertEquals(passed, stats.getValue(FrequencyVerification.PASSED_KEY));
+        assertEquals(frequency, stats.getValue(SensorStats.FREQUENCY_KEY));
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/GyroscopeIntegrationVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/GyroscopeIntegrationVerification.java
new file mode 100644
index 0000000..b46c2dc
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/GyroscopeIntegrationVerification.java
@@ -0,0 +1,115 @@
+/*
+ * 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.cts.helpers.sensorverification;
+
+import junit.framework.Assert;
+
+import android.hardware.Sensor;
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A {@link ISensorVerification} that verifies the measurements of the sensors:
+ * - {@link Sensor#TYPE_GYROSCOPE}
+ * - {@link Sensor#TYPE_GYROSCOPE_UNCALIBRATED}
+ *
+ * It uses a routine to integrate gyroscope's data, and that they correspond to expected angular
+ * positions.
+ */
+public class GyroscopeIntegrationVerification extends AbstractSensorVerification {
+    public static final String PASSED_KEY = "gyroscope_integration_passed";
+
+    private static final long ONE_SECOND_AS_NANOS = TimeUnit.SECONDS.toNanos(1);
+
+    private final double[] mIntermediatesDeg;
+    private final int[] mExpectationsDeg;
+    private final float[] mThresholdsDeg;
+
+    private volatile Long mLastTimestampNs;
+
+    public GyroscopeIntegrationVerification(int[] expectationsDeg, float[] thresholdsDeg) {
+        mIntermediatesDeg = new double[expectationsDeg.length];
+        mExpectationsDeg = expectationsDeg;
+        mThresholdsDeg = thresholdsDeg;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void verify(TestSensorEnvironment environment, SensorStats stats) {
+        int sensorType = environment.getSensor().getType();
+        if (sensorType != Sensor.TYPE_GYROSCOPE
+                && sensorType != Sensor.TYPE_GYROSCOPE_UNCALIBRATED) {
+            // the verification does not apply, so no-op
+            stats.addValue(PASSED_KEY, true);
+        }
+
+        boolean success = true;
+        int gyroscopeAxes = environment.getSensorAxesCount();
+        StringBuilder builder = new StringBuilder("Gyroscope Integration | failures:");
+        for (int i = 0; i < gyroscopeAxes; ++i) {
+            double integrationDeg = Math.toDegrees(mIntermediatesDeg[i]);
+            double integrationDelta = Math.abs(integrationDeg - mExpectationsDeg[i]);
+            if (integrationDelta > mThresholdsDeg[i]) {
+                success = false;
+                String message = String.format(
+                        "\naxis=%s, expected=%sdeg, observed=%sdeg, delta=%sdeg, threshold=%sdeg",
+                        i,
+                        mExpectationsDeg[i],
+                        integrationDeg,
+                        integrationDelta,
+                        mThresholdsDeg[i]);
+                builder.append(message);
+            }
+        }
+
+        stats.addValue(PASSED_KEY, success);
+        Assert.assertTrue(builder.toString(), success);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public GyroscopeIntegrationVerification clone() {
+        return new GyroscopeIntegrationVerification(mExpectationsDeg, mThresholdsDeg);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void addSensorEventInternal(TestSensorEvent event) {
+        float[] eventValues = event.values.clone();
+        long eventTimestampNs = event.timestamp;
+        if (mLastTimestampNs == null) {
+            mLastTimestampNs = eventTimestampNs;
+            return;
+        }
+
+        int intermediatesLength = mIntermediatesDeg.length;
+        long timestampDeltaNs = eventTimestampNs - mLastTimestampNs;
+        for (int i = 0; i < intermediatesLength; ++i) {
+            mIntermediatesDeg[i] += eventValues[i] * timestampDeltaNs / ONE_SECOND_AS_NANOS;
+        }
+        mLastTimestampNs = eventTimestampNs;
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/ISensorVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/ISensorVerification.java
new file mode 100644
index 0000000..4f7b65a
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/ISensorVerification.java
@@ -0,0 +1,54 @@
+/*
+ * 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.cts.helpers.sensorverification;
+
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+/**
+ * Interface describing the sensor verification. This class was designed for to handle streaming
+ * events. The methods {@link #addSensorEvent(TestSensorEvent)} and
+ * {@link #addSensorEvents(TestSensorEvent...)} should be called in the order that the events are
+ * received. The method {@link #verify(TestSensorEnvironment, SensorStats)} should be called after
+ * all events are added.
+ */
+public interface ISensorVerification {
+
+    /**
+     * Add a single {@link TestSensorEvent} to be evaluated.
+     */
+    public void addSensorEvent(TestSensorEvent event);
+
+    /**
+     * Add multiple {@link TestSensorEvent}s to be evaluated.
+     */
+    public void addSensorEvents(TestSensorEvent ... events);
+
+    /**
+     * Evaluate all added {@link TestSensorEvent}s and update stats.
+     *
+     * @param stats a {@link SensorStats} object used to keep track of the stats.
+     * @throws AssertionError if the verification fails.
+     */
+    public void verify(TestSensorEnvironment environment, SensorStats stats);
+
+    /**
+     * Clones the {@link ISensorVerification}
+     */
+    public ISensorVerification clone();
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/JitterVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/JitterVerification.java
new file mode 100644
index 0000000..f95ea0b
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/JitterVerification.java
@@ -0,0 +1,157 @@
+/*
+ * 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.cts.helpers.sensorverification;
+
+import junit.framework.Assert;
+
+import android.hardware.Sensor;
+import android.hardware.cts.helpers.SensorCtsHelper;
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.TestSensorEvent;
+import android.util.SparseIntArray;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * A {@link ISensorVerification} which verifies that the sensor jitter is in an acceptable range.
+ */
+public class JitterVerification extends AbstractSensorVerification {
+    public static final String PASSED_KEY = "jitter_passed";
+
+    // sensorType: threshold (% of expected period)
+    private static final SparseIntArray DEFAULTS = new SparseIntArray(12);
+    static {
+        // Use a method so that the @deprecation warning can be set for that method only
+        setDefaults();
+    }
+
+    private final int mThresholdAsPercentage;
+    private final List<Long> mTimestamps = new LinkedList<Long>();
+
+    /**
+     * Construct a {@link JitterVerification}
+     *
+     * @param thresholdAsPercentage the acceptable margin of error as a percentage
+     */
+    public JitterVerification(int thresholdAsPercentage) {
+        mThresholdAsPercentage = thresholdAsPercentage;
+    }
+
+    /**
+     * Get the default {@link JitterVerification} for a sensor.
+     *
+     * @param environment the test environment
+     * @return the verification or null if the verification does not apply to the sensor.
+     */
+    public static JitterVerification getDefault(TestSensorEnvironment environment) {
+        int sensorType = environment.getSensor().getType();
+        int threshold = DEFAULTS.get(sensorType, -1);
+        if (threshold == -1) {
+            return null;
+        }
+        return new JitterVerification(threshold);
+    }
+
+    /**
+     * Verify that the 95th percentile of the jitter is in the acceptable range. Add
+     * {@value #PASSED_KEY} and {@value SensorStats#JITTER_95_PERCENTILE_PERCENT_KEY} keys to
+     * {@link SensorStats}.
+     *
+     * @throws AssertionError if the verification failed.
+     */
+    @Override
+    public void verify(TestSensorEnvironment environment, SensorStats stats) {
+        int timestampsCount = mTimestamps.size();
+        if (timestampsCount < 2 || environment.isSensorSamplingRateOverloaded()) {
+            // the verification is not reliable in environments under load
+            stats.addValue(PASSED_KEY, true);
+            return;
+        }
+
+        List<Double> jitters = getJitterValues();
+        double jitter95PercentileNs = SensorCtsHelper.get95PercentileValue(jitters);
+        long firstTimestamp = mTimestamps.get(0);
+        long lastTimestamp = mTimestamps.get(timestampsCount - 1);
+        long measuredPeriodNs = (lastTimestamp - firstTimestamp) / (timestampsCount - 1);
+        double jitter95PercentilePercent = (jitter95PercentileNs * 100.0) / measuredPeriodNs;
+        stats.addValue(SensorStats.JITTER_95_PERCENTILE_PERCENT_KEY, jitter95PercentilePercent);
+
+        boolean success = (jitter95PercentilePercent < mThresholdAsPercentage);
+        stats.addValue(PASSED_KEY, success);
+
+        if (!success) {
+            String message = String.format(
+                    "Jitter out of range: measured period=%dns, jitter(95th percentile)=%.2f%%"
+                            + " (expected < %d%%)",
+                    measuredPeriodNs,
+                    jitter95PercentilePercent,
+                    mThresholdAsPercentage);
+            Assert.fail(message);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public JitterVerification clone() {
+        return new JitterVerification(mThresholdAsPercentage);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void addSensorEventInternal(TestSensorEvent event) {
+        mTimestamps.add(event.timestamp);
+    }
+
+    /**
+     * Get the list of all jitter values. Exposed for unit testing.
+     */
+    List<Double> getJitterValues() {
+        List<Long> deltas = new ArrayList<Long>(mTimestamps.size() - 1);
+        for (int i = 1; i < mTimestamps.size(); i++) {
+            deltas.add(mTimestamps.get(i) - mTimestamps.get(i - 1));
+        }
+        double deltaMean = SensorCtsHelper.getMean(deltas);
+        List<Double> jitters = new ArrayList<Double>(deltas.size());
+        for (long delta : deltas) {
+            jitters.add(Math.abs(delta - deltaMean));
+        }
+        return jitters;
+    }
+
+    @SuppressWarnings("deprecation")
+    private static void setDefaults() {
+        DEFAULTS.put(Sensor.TYPE_ACCELEROMETER, Integer.MAX_VALUE);
+        DEFAULTS.put(Sensor.TYPE_MAGNETIC_FIELD, Integer.MAX_VALUE);
+        DEFAULTS.put(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED, Integer.MAX_VALUE);
+        DEFAULTS.put(Sensor.TYPE_GYROSCOPE, Integer.MAX_VALUE);
+        DEFAULTS.put(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, Integer.MAX_VALUE);
+        DEFAULTS.put(Sensor.TYPE_ORIENTATION, Integer.MAX_VALUE);
+        DEFAULTS.put(Sensor.TYPE_PRESSURE, Integer.MAX_VALUE);
+        DEFAULTS.put(Sensor.TYPE_GRAVITY, Integer.MAX_VALUE);
+        DEFAULTS.put(Sensor.TYPE_LINEAR_ACCELERATION, Integer.MAX_VALUE);
+        DEFAULTS.put(Sensor.TYPE_ROTATION_VECTOR, Integer.MAX_VALUE);
+        DEFAULTS.put(Sensor.TYPE_GAME_ROTATION_VECTOR, Integer.MAX_VALUE);
+        DEFAULTS.put(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR, Integer.MAX_VALUE);
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/JitterVerificationTest.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/JitterVerificationTest.java
new file mode 100644
index 0000000..0c85b63
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/JitterVerificationTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.cts.helpers.sensorverification;
+
+import junit.framework.TestCase;
+
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import java.util.List;
+
+/**
+ * Tests for {@link EventOrderingVerification}.
+ */
+public class JitterVerificationTest extends TestCase {
+
+
+    public void testVerify() {
+        final int SAMPLE_SIZE = 100;
+        // for unit testing the verification, only the parameter 'sensorMightHaveMoreListeners' is
+        // required
+        TestSensorEnvironment environment = new TestSensorEnvironment(
+                null /* context */,
+                null /* sensor */,
+                false /* sensorMightHaveMoreListeners */,
+                0 /*samplingPeriodUs */,
+                0 /* maxReportLatencyUs */);
+
+        // 100 samples at 1000Hz
+        long[] timestamps = new long[SAMPLE_SIZE];
+        for (int i = 0; i < SAMPLE_SIZE; i++) {
+            timestamps[i] = i * 100000;
+        }
+        SensorStats stats = new SensorStats();
+        ISensorVerification verification = getVerification(1, timestamps);
+        verification.verify(environment, stats);
+        verifyStats(stats, true, 0.0);
+
+        // 90 samples at 1000Hz, 10 samples at 2000Hz
+        long timestamp = 0;
+        for (int i = 0; i < SAMPLE_SIZE; i++) {
+            timestamps[i] = timestamp;
+            timestamp += (i % 10 == 0) ? 500000 : 1000000;
+        }
+        stats = new SensorStats();
+        verification = getVerification(1, timestamps);
+        try {
+            verification.verify(environment, stats);
+            fail("Expected an AssertionError");
+        } catch (AssertionError e) {
+            // Expected;
+        }
+        verifyStats(stats, false, 47.34);
+    }
+
+    public void testCalculateJitter() {
+        long[] timestamps = new long[]{0, 1, 2, 3, 4};
+        JitterVerification verification = getVerification(1, timestamps);
+        List<Double> jitterValues = verification.getJitterValues();
+        assertEquals(4, jitterValues.size());
+        assertEquals(0.0, jitterValues.get(0));
+        assertEquals(0.0, jitterValues.get(1));
+        assertEquals(0.0, jitterValues.get(2));
+        assertEquals(0.0, jitterValues.get(3));
+
+        timestamps = new long[]{0, 0, 2, 4, 4};
+        verification = getVerification(1, timestamps);
+        jitterValues = verification.getJitterValues();
+        assertEquals(4, jitterValues.size());
+        assertEquals(1.0, jitterValues.get(0));
+        assertEquals(1.0, jitterValues.get(1));
+        assertEquals(1.0, jitterValues.get(2));
+        assertEquals(1.0, jitterValues.get(3));
+
+        timestamps = new long[]{0, 1, 4, 9, 16};
+        verification = getVerification(1, timestamps);
+        jitterValues = verification.getJitterValues();
+        assertEquals(4, jitterValues.size());
+        assertEquals(4, jitterValues.size());
+        assertEquals(3.0, jitterValues.get(0));
+        assertEquals(1.0, jitterValues.get(1));
+        assertEquals(1.0, jitterValues.get(2));
+        assertEquals(3.0, jitterValues.get(3));
+    }
+
+    private JitterVerification getVerification(int threshold, long ... timestamps) {
+        JitterVerification verification = new JitterVerification(threshold);
+        for (long timestamp : timestamps) {
+            verification.addSensorEvent(new TestSensorEvent(null, timestamp, 0, null));
+        }
+        return verification;
+    }
+
+    private void verifyStats(SensorStats stats, boolean passed, double jitter95) {
+        assertEquals(passed, stats.getValue(JitterVerification.PASSED_KEY));
+        assertEquals(
+                jitter95,
+                (Double) stats.getValue(SensorStats.JITTER_95_PERCENTILE_PERCENT_KEY),
+                0.1);
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/MagnitudeVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/MagnitudeVerification.java
new file mode 100644
index 0000000..db8037d
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/MagnitudeVerification.java
@@ -0,0 +1,135 @@
+/*
+ * 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.cts.helpers.sensorverification;
+
+import junit.framework.Assert;
+
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.hardware.cts.helpers.SensorCtsHelper;
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A {@link ISensorVerification} which verifies that the mean of the magnitude of the sensors vector
+ * is within the expected range.
+ */
+public class MagnitudeVerification extends AbstractSensorVerification {
+    public static final String PASSED_KEY = "magnitude_passed";
+
+    // sensorType: {expected, threshold}
+    private static Map<Integer, Float[]> DEFAULTS = new HashMap<Integer, Float[]>(3);
+    static {
+        // Use a method so that the @deprecation warning can be set for that method only
+        setDefaults();
+    }
+
+    private final float mExpected;
+    private final float mThreshold;
+
+    private float mSum = 0.0f;
+    private int mCount = 0;
+
+    /**
+     * Construct a {@link MagnitudeVerification}
+     *
+     * @param expected the expected value
+     * @param threshold the threshold
+     */
+    public MagnitudeVerification(float expected, float threshold) {
+        mExpected = expected;
+        mThreshold = threshold;
+    }
+
+    /**
+     * Get the default {@link MagnitudeVerification} for a sensor.
+     *
+     * @param environment the test environment
+     * @return the verification or null if the verification does not apply to the sensor.
+     */
+    public static MagnitudeVerification getDefault(TestSensorEnvironment environment) {
+        int sensorType = environment.getSensor().getType();
+        if (!DEFAULTS.containsKey(sensorType)) {
+            return null;
+        }
+        Float expected = DEFAULTS.get(sensorType)[0];
+        Float threshold = DEFAULTS.get(sensorType)[1];
+        return new MagnitudeVerification(expected, threshold);
+    }
+
+    /**
+     * Verify that the magnitude is in the acceptable range. Add {@value #PASSED_KEY} and
+     * {@value SensorStats#MAGNITUDE_KEY} keys to {@link SensorStats}.
+     *
+     * @throws AssertionError if the verification failed.
+     */
+    @Override
+    public void verify(TestSensorEnvironment environment, SensorStats stats) {
+        verify(stats);
+    }
+
+    /**
+     * Visible for unit tests only.
+     */
+    void verify(SensorStats stats) {
+        if (mCount < 1) {
+            stats.addValue(PASSED_KEY, true);
+            return;
+        }
+
+        float mean = mSum / mCount;
+        boolean failed = Math.abs(mean - mExpected) > mThreshold;
+
+        stats.addValue(PASSED_KEY, !failed);
+        stats.addValue(SensorStats.MAGNITUDE_KEY, mean);
+
+        if (failed) {
+            Assert.fail(String.format("Magnitude mean out of range: mean=%s (expected %s+/-%s)",
+                    mean, mExpected, mThreshold));
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public MagnitudeVerification clone() {
+        return new MagnitudeVerification(mExpected, mThreshold);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void addSensorEventInternal(TestSensorEvent event) {
+        mSum += SensorCtsHelper.getMagnitude(event.values);
+        mCount++;
+    }
+
+    @SuppressWarnings("deprecation")
+    private static void setDefaults() {
+        DEFAULTS.put(Sensor.TYPE_ACCELEROMETER, new Float[]{SensorManager.STANDARD_GRAVITY, 1.5f});
+        DEFAULTS.put(Sensor.TYPE_GYROSCOPE, new Float[]{0.0f, 1.5f});
+        // Sensors that we don't want to test at this time but still want to record the values.
+        DEFAULTS.put(Sensor.TYPE_GRAVITY,
+                new Float[]{SensorManager.STANDARD_GRAVITY, Float.MAX_VALUE});
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/MagnitudeVerificationTest.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/MagnitudeVerificationTest.java
new file mode 100644
index 0000000..bb29330
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/MagnitudeVerificationTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.cts.helpers.sensorverification;
+
+import junit.framework.TestCase;
+
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+/**
+ * Tests for {@link MagnitudeVerification}.
+ */
+public class MagnitudeVerificationTest extends TestCase {
+
+    /**
+     * Test {@link MagnitudeVerification#verify(TestSensorEnvironment, SensorStats)}.
+     */
+    public void testVerify() {
+        float[][] values = {
+                {0, 3, 4},
+                {4, 0, 3},
+                {3, 4, 0},
+                {0, 0, 4},
+                {6, 0, 0},
+        };
+
+        runStats(5.0f, 0.1f, values, true, 5.0f);
+        runStats(4.5f, 0.6f, values, true, 5.0f);
+        runStats(5.5f, 0.6f, values, true, 5.0f);
+        runStats(4.5f, 0.1f, values, false, 5.0f);
+        runStats(5.5f, 0.1f, values, false, 5.0f);
+    }
+
+    private void runStats(float expected, float threshold, float[][] values, boolean pass, float magnitude) {
+        SensorStats stats = new SensorStats();
+        MagnitudeVerification verification = getVerification(expected, threshold, values);
+        if (pass) {
+            verification.verify(stats);
+        } else {
+            try {
+                verification.verify(stats);
+                fail("Expected an AssertionError");
+            } catch (AssertionError e) {
+                // Expected;
+            }
+        }
+        assertEquals(pass, stats.getValue(MagnitudeVerification.PASSED_KEY));
+        assertEquals(magnitude, (Float) stats.getValue(SensorStats.MAGNITUDE_KEY), 0.01);
+    }
+
+    private MagnitudeVerification getVerification(float expected, float threshold,
+            float[] ... values) {
+        MagnitudeVerification verification = new MagnitudeVerification(expected, threshold);
+        for (float[] value : values) {
+            verification.addSensorEvent(new TestSensorEvent(null, 0, 0, value));
+        }
+        return verification;
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/MeanVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/MeanVerification.java
new file mode 100644
index 0000000..6603895
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/MeanVerification.java
@@ -0,0 +1,157 @@
+/*
+ * 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.cts.helpers.sensorverification;
+
+import junit.framework.Assert;
+
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A {@link ISensorVerification} which verifies that the means matches the expected measurement.
+ */
+public class MeanVerification extends AbstractMeanVerification {
+    public static final String PASSED_KEY = "mean_passed";
+
+    // sensorType: {expected, threshold}
+    private static final Map<Integer, Object[]> DEFAULTS = new HashMap<Integer, Object[]>(5);
+    static {
+        // Use a method so that the @deprecation warning can be set for that method only
+        setDefaults();
+    }
+
+    private final float[] mExpected;
+    private final float[] mThreshold;
+
+    /**
+     * Construct a {@link MeanVerification}
+     *
+     * @param expected the expected values
+     * @param threshold the thresholds
+     */
+    public MeanVerification(float[] expected, float[] threshold) {
+        mExpected = expected;
+        mThreshold = threshold;
+    }
+
+    /**
+     * Get the default {@link MeanVerification} for a sensor.
+     *
+     * @param environment the test environment
+     * @return the verification or null if the verification does not apply to the sensor.
+     */
+    public static MeanVerification getDefault(TestSensorEnvironment environment) {
+        int sensorType = environment.getSensor().getType();
+        if (!DEFAULTS.containsKey(sensorType)) {
+            return null;
+        }
+        float[] expected = (float[]) DEFAULTS.get(sensorType)[0];
+        float[] threshold = (float[]) DEFAULTS.get(sensorType)[1];
+        return new MeanVerification(expected, threshold);
+    }
+
+    /**
+     * Verify that the mean is in the acceptable range. Add {@value #PASSED_KEY} and
+     * {@value SensorStats#MEAN_KEY} keys to {@link SensorStats}.
+     *
+     * @throws AssertionError if the verification failed.
+     */
+    @Override
+    public void verify(TestSensorEnvironment environment, SensorStats stats) {
+        verify(stats);
+    }
+
+    /**
+     * Visible for unit tests only.
+     */
+    void verify(SensorStats stats) {
+        if (getCount() < 1) {
+            stats.addValue(PASSED_KEY, true);
+            return;
+        }
+
+        float[] means = getMeans();
+
+        boolean failed = false;
+        StringBuilder meanSb = new StringBuilder();
+        StringBuilder expectedSb = new StringBuilder();
+
+        if (means.length > 1) {
+            meanSb.append("(");
+            expectedSb.append("(");
+        }
+        for (int i = 0; i < means.length; i++) {
+            if (Math.abs(means[i] - mExpected[i]) > mThreshold[i]) {
+                failed = true;
+            }
+            meanSb.append(String.format("%.2f", means[i]));
+            if (i != means.length - 1) meanSb.append(", ");
+            expectedSb.append(String.format("%.2f+/-%.2f", mExpected[i], mThreshold[i]));
+            if (i != means.length - 1) expectedSb.append(", ");
+        }
+        if (means.length > 1) {
+            meanSb.append(")");
+            expectedSb.append(")");
+        }
+
+        stats.addValue(PASSED_KEY, !failed);
+        stats.addValue(SensorStats.MEAN_KEY, means);
+
+        if (failed) {
+            Assert.fail(String.format("Mean out of range: mean=%s (expected %s)", meanSb.toString(),
+                    expectedSb.toString()));
+        }
+    }
+
+    @Override
+    public MeanVerification clone() {
+        return new MeanVerification(mExpected, mThreshold);
+    }
+
+    @SuppressWarnings("deprecation")
+    private static void setDefaults() {
+        // Sensors that we don't want to test at this time but still want to record the values.
+        // Gyroscope should be 0 for a static device
+        DEFAULTS.put(Sensor.TYPE_GYROSCOPE, new Object[]{
+                new float[]{0.0f, 0.0f, 0.0f},
+                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE}});
+        // Pressure will not be exact in a controlled environment but should be relatively close to
+        // sea level. Second values should always be 0.
+        DEFAULTS.put(Sensor.TYPE_PRESSURE, new Object[]{
+                new float[]{SensorManager.PRESSURE_STANDARD_ATMOSPHERE, 0.0f, 0.0f},
+                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE}});
+        // Linear acceleration should be 0 in all directions for a static device
+        DEFAULTS.put(Sensor.TYPE_LINEAR_ACCELERATION, new Object[]{
+                new float[]{0.0f, 0.0f, 0.0f},
+                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE}});
+        // Game rotation vector should be (0, 0, 0, 1, 0) for a static device
+        DEFAULTS.put(Sensor.TYPE_GAME_ROTATION_VECTOR, new Object[]{
+                new float[]{0.0f, 0.0f, 0.0f, 1.0f, 0.0f},
+                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE,
+                        Float.MAX_VALUE}});
+        // Uncalibrated gyroscope should be 0 for a static device but allow a bigger threshold
+        DEFAULTS.put(Sensor.TYPE_GYROSCOPE_UNCALIBRATED, new Object[]{
+                new float[]{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
+                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE,
+                        Float.MAX_VALUE, Float.MAX_VALUE}});
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/MeanVerificationTest.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/MeanVerificationTest.java
new file mode 100644
index 0000000..b07ea50
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/MeanVerificationTest.java
@@ -0,0 +1,108 @@
+/*
+ * 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.cts.helpers.sensorverification;
+
+import junit.framework.TestCase;
+
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+/**
+ * Tests for {@link MeanVerification}.
+ */
+public class MeanVerificationTest extends TestCase {
+
+    /**
+     * Test {@link MeanVerification#verify(TestSensorEnvironment, SensorStats)}.
+     */
+    public void testVerify() {
+        float[][] values = {
+                {0, 1, 0},
+                {1, 2, 1},
+                {2, 3, 4},
+                {3, 4, 9},
+                {4, 5, 16},
+        };
+
+        float[] expected = {2.0f, 3.0f, 6.0f};
+        float[] threshold = {0.1f, 0.1f, 0.1f};
+        SensorStats stats = new SensorStats();
+        MeanVerification verification = getVerification(expected, threshold, values);
+        verification.verify(stats);
+        verifyStats(stats, true, new float[]{2.0f, 3.0f, 6.0f});
+
+        expected = new float[]{2.5f, 2.5f, 5.5f};
+        threshold = new float[]{0.6f, 0.6f, 0.6f};
+        stats = new SensorStats();
+        verification = getVerification(expected, threshold, values);
+        verification.verify(stats);
+        verifyStats(stats, true, new float[]{2.0f, 3.0f, 6.0f});
+
+        expected = new float[]{2.5f, 2.5f, 5.5f};
+        threshold = new float[]{0.1f, 0.6f, 0.6f};
+        stats = new SensorStats();
+        verification = getVerification(expected, threshold, values);
+        try {
+            verification.verify(stats);
+            fail("Expected an AssertionError");
+        } catch (AssertionError e) {
+            // Expected;
+        }
+        verifyStats(stats, false, new float[]{2.0f, 3.0f, 6.0f});
+
+        expected = new float[]{2.5f, 2.5f, 5.5f};
+        threshold = new float[]{0.6f, 0.1f, 0.6f};
+        stats = new SensorStats();
+        verification = getVerification(expected, threshold, values);
+        try {
+            verification.verify(stats);
+            fail("Expected an AssertionError");
+        } catch (AssertionError e) {
+            // Expected;
+        }
+        verifyStats(stats, false, new float[]{2.0f, 3.0f, 6.0f});
+
+        threshold = new float[]{0.6f, 0.6f, 0.1f};
+        stats = new SensorStats();
+        verification = getVerification(expected, threshold, values);
+        try {
+            verification.verify(stats);
+            fail("Expected an AssertionError");
+        } catch (AssertionError e) {
+            // Expected;
+        }
+        verifyStats(stats, false, new float[]{2.0f, 3.0f, 6.0f});
+    }
+
+    private MeanVerification getVerification(float[] expected, float[] threshold,
+            float[] ... values) {
+        MeanVerification verification = new MeanVerification(expected, threshold);
+        for (float[] value : values) {
+            verification.addSensorEvent(new TestSensorEvent(null, 0, 0, value));
+        }
+        return verification;
+    }
+
+    private void verifyStats(SensorStats stats, boolean passed, float[] means) {
+        assertEquals(passed, stats.getValue(MeanVerification.PASSED_KEY));
+        float[] actual = (float[]) stats.getValue(SensorStats.MEAN_KEY);
+        for (int i = 0; i < means.length; i++) {
+            assertEquals(means[i], actual[i], 0.1);
+        }
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/StandardDeviationVerification.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/StandardDeviationVerification.java
new file mode 100644
index 0000000..f7c2c53
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/StandardDeviationVerification.java
@@ -0,0 +1,195 @@
+/*
+ * 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.cts.helpers.sensorverification;
+
+import junit.framework.Assert;
+
+import android.hardware.Sensor;
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A {@link ISensorVerification} which verifies that the standard deviations is within the expected
+ * range.
+ */
+public class StandardDeviationVerification extends AbstractSensorVerification {
+    public static final String PASSED_KEY = "standard_deviation_passed";
+
+    // sensorType: threshold
+    private static final Map<Integer, float[]> DEFAULTS = new HashMap<Integer, float[]>(12);
+    static {
+        // Use a method so that the @deprecation warning can be set for that method only
+        setDefaults();
+    }
+
+    private final float[] mThreshold;
+
+    private float[] mMeans = null;
+    private float[] mM2s = null;
+    private int mCount = 0;
+
+    /**
+     * Construct a {@link StandardDeviationVerification}
+     *
+     * @param threshold the thresholds
+     */
+    public StandardDeviationVerification(float[] threshold) {
+        mThreshold = threshold;
+    }
+
+    /**
+     * Get the default {@link StandardDeviationVerification} for a sensor.
+     *
+     * @param environment the test environment
+     * @return the verification or null if the verification does not apply to the sensor.
+     */
+    public static StandardDeviationVerification getDefault(TestSensorEnvironment environment) {
+        int sensorType = environment.getSensor().getType();
+        if (!DEFAULTS.containsKey(sensorType)) {
+            return null;
+        }
+
+        return new StandardDeviationVerification(DEFAULTS.get(sensorType));
+    }
+
+    /**
+     * Verify that the standard deviation is in the acceptable range. Add {@value #PASSED_KEY} and
+     * {@value SensorStats#STANDARD_DEVIATION_KEY} keys to {@link SensorStats}.
+     *
+     * @throws AssertionError if the verification failed.
+     */
+    @Override
+    public void verify(TestSensorEnvironment environment, SensorStats stats) {
+        verify(stats);
+    }
+
+    /**
+     * Visible for unit tests only.
+     */
+    void verify(SensorStats stats) {
+        if (mCount < 2) {
+            stats.addValue(PASSED_KEY, true);
+            return;
+        }
+
+        float[] stdDevs = new float[mM2s.length];
+        for (int i = 0; i < mM2s.length; i++) {
+            stdDevs[i] = (float) Math.sqrt(mM2s[i] / (mCount - 1));
+        }
+
+        boolean failed = false;
+        StringBuilder stddevSb = new StringBuilder();
+        StringBuilder expectedSb = new StringBuilder();
+
+        if (stdDevs.length > 1) {
+            stddevSb.append("(");
+            expectedSb.append("(");
+        }
+        for (int i = 0; i < stdDevs.length; i++) {
+            if (stdDevs[i] > mThreshold[i]) {
+                failed = true;
+            }
+            stddevSb.append(String.format("%.2f", stdDevs[i]));
+            if (i != stdDevs.length - 1) stddevSb.append(", ");
+            expectedSb.append(String.format("<%.2f", mThreshold[i]));
+            if (i != stdDevs.length - 1) expectedSb.append(", ");
+        }
+        if (stdDevs.length > 1) {
+            stddevSb.append(")");
+            expectedSb.append(")");
+        }
+
+        stats.addValue(PASSED_KEY, !failed);
+        stats.addValue(SensorStats.STANDARD_DEVIATION_KEY, stdDevs);
+
+        if (failed) {
+            Assert.fail(String.format("Standard deviation out of range: stddev=%s (expected %s)",
+                    stddevSb.toString(), expectedSb.toString()));
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public StandardDeviationVerification clone() {
+        return new StandardDeviationVerification(mThreshold);
+    }
+
+    /**
+     * {@inheritDoc}
+     * <p>
+     * Computes the standard deviation using
+     * <a href="http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#On-line_algorithm">
+     * Welford's algorith</a>.
+     * </p>
+     */
+    @Override
+    protected void addSensorEventInternal(TestSensorEvent event) {
+        if (mMeans == null || mM2s == null) {
+            mMeans = new float[event.values.length];
+            mM2s = new float[event.values.length];
+        }
+
+        Assert.assertEquals(mMeans.length, event.values.length);
+        Assert.assertEquals(mM2s.length, event.values.length);
+
+        mCount++;
+
+        for (int i = 0; i < event.values.length; i++) {
+            float delta = event.values[i] - mMeans[i];
+            mMeans[i] += delta / mCount;
+            mM2s[i] += delta * (event.values[i] - mMeans[i]);
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    private static void setDefaults() {
+        DEFAULTS.put(Sensor.TYPE_ACCELEROMETER, new float[]{1.0f, 1.0f, 1.0f});
+        DEFAULTS.put(Sensor.TYPE_GYROSCOPE, new float[]{0.5f, 0.5f, 0.5f});
+        // Sensors that we don't want to test at this time but still want to record the values.
+        DEFAULTS.put(Sensor.TYPE_MAGNETIC_FIELD,
+                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE});
+        DEFAULTS.put(Sensor.TYPE_ORIENTATION,
+                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE});
+        DEFAULTS.put(Sensor.TYPE_PRESSURE,
+                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE});
+        DEFAULTS.put(Sensor.TYPE_GRAVITY,
+                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE});
+        DEFAULTS.put(Sensor.TYPE_LINEAR_ACCELERATION,
+                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE});
+        DEFAULTS.put(Sensor.TYPE_ROTATION_VECTOR,
+                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE,
+                Float.MAX_VALUE});
+        DEFAULTS.put(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED,
+                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE,
+                Float.MAX_VALUE, Float.MAX_VALUE});
+        DEFAULTS.put(Sensor.TYPE_GAME_ROTATION_VECTOR,
+                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE,
+                Float.MAX_VALUE});
+        DEFAULTS.put(Sensor.TYPE_GYROSCOPE_UNCALIBRATED,
+                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE,
+                Float.MAX_VALUE, Float.MAX_VALUE});
+        DEFAULTS.put(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR,
+                new float[]{Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE,
+                Float.MAX_VALUE});
+    }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/StandardDeviationVerificationTest.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/StandardDeviationVerificationTest.java
new file mode 100644
index 0000000..5d958f5
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensorverification/StandardDeviationVerificationTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.cts.helpers.sensorverification;
+
+import junit.framework.TestCase;
+
+import android.hardware.cts.helpers.SensorStats;
+import android.hardware.cts.helpers.TestSensorEnvironment;
+import android.hardware.cts.helpers.TestSensorEvent;
+
+/**
+ * Tests for {@link StandardDeviationVerification}.
+ */
+public class StandardDeviationVerificationTest extends TestCase {
+
+    /**
+     * Test {@link StandardDeviationVerification#verify(TestSensorEnvironment, SensorStats)}.
+     */
+    public void testVerify() {
+        // Stddev should be {sqrt(2.5), sqrt(2.5), sqrt(2.5)}
+        float[][] values = {
+                {0, 1, 0},
+                {1, 2, 2},
+                {2, 3, 4},
+                {3, 4, 6},
+                {4, 5, 8},
+        };
+        float[] standardDeviations = {
+                (float) Math.sqrt(2.5), (float) Math.sqrt(2.5), (float) Math.sqrt(10.0)
+        };
+
+        float[] threshold = {2, 2, 4};
+        runVerification(threshold, values, true, standardDeviations);
+
+        threshold = new float[]{1, 2, 4};
+        runVerification(threshold, values, false, standardDeviations);
+
+        threshold = new float[]{2, 1, 4};
+        runVerification(threshold, values, false, standardDeviations);
+
+        threshold = new float[]{2, 2, 3};
+        runVerification(threshold, values, false, standardDeviations);
+    }
+
+    private void runVerification(float[] threshold, float[][] values, boolean pass,
+            float[] standardDeviations) {
+        SensorStats stats = new SensorStats();
+        StandardDeviationVerification verification = getVerification(threshold, values);
+        if (pass) {
+            verification.verify(stats);
+        } else {
+            boolean failed = false;
+            try {
+                verification.verify(stats);
+            } catch (AssertionError e) {
+                // Expected;
+                failed = true;
+            }
+            assertTrue("Expected an AssertionError", failed);
+        }
+        assertEquals(pass, stats.getValue(StandardDeviationVerification.PASSED_KEY));
+        float[] actual = (float[]) stats.getValue(SensorStats.STANDARD_DEVIATION_KEY);
+        for (int i = 0; i < standardDeviations.length; i++) {
+            assertEquals(standardDeviations[i], actual[i], 0.1);
+        }
+    }
+
+    private StandardDeviationVerification getVerification(float[] threshold, float[] ... values) {
+        StandardDeviationVerification verification = new StandardDeviationVerification(threshold);
+        for (float[] value : values) {
+            verification.addSensorEvent(new TestSensorEvent(null, 0, 0, value));
+        }
+        return verification;
+    }
+}
diff --git a/tests/tests/jni/Android.mk b/tests/tests/jni/Android.mk
index 4f44e15..1aeb8b7 100644
--- a/tests/tests/jni/Android.mk
+++ b/tests/tests/jni/Android.mk
@@ -18,16 +18,15 @@
 
 LOCAL_PACKAGE_NAME := CtsJniTestCases
 
-
 # Don't include this package in any target.
 LOCAL_MODULE_TAGS := optional
 
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
 # When built, explicitly put it in the data partition.
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-# All tests should include android.test.runner.
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
 LOCAL_JNI_SHARED_LIBRARIES := libjnitest
diff --git a/tests/tests/jni/AndroidManifest.xml b/tests/tests/jni/AndroidManifest.xml
index c3407d1..843b322 100644
--- a/tests/tests/jni/AndroidManifest.xml
+++ b/tests/tests/jni/AndroidManifest.xml
@@ -23,9 +23,12 @@
     </application>
 
     <!-- This is a self-instrumenting test package. -->
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.cts.jni"
-                     android:label="CTS tests of calling native code via JNI"/>
+                     android:label="CTS tests of calling native code via JNI">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/tests/keystore/Android.mk b/tests/tests/keystore/Android.mk
index f2dae38..0f2cd03 100644
--- a/tests/tests/keystore/Android.mk
+++ b/tests/tests/keystore/Android.mk
@@ -18,8 +18,6 @@
 
 LOCAL_MODULE_TAGS := optional
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner core-tests-support
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/keystore/AndroidManifest.xml b/tests/tests/keystore/AndroidManifest.xml
index 0ce9f09..106a0dc 100644
--- a/tests/tests/keystore/AndroidManifest.xml
+++ b/tests/tests/keystore/AndroidManifest.xml
@@ -24,9 +24,12 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.cts.keystore"
-                     android:label="CTS tests of com.android.cts.keystore"/>
+                     android:label="CTS tests of com.android.cts.keystore">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyChainTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyChainTest.java
index db6d6ba..7aa6a9d 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyChainTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyChainTest.java
@@ -16,10 +16,11 @@
 
 package android.keystore.cts;
 
+import android.content.pm.PackageManager;
 import android.security.KeyChain;
-import junit.framework.TestCase;
+import android.test.AndroidTestCase;
 
-public class KeyChainTest extends TestCase {
+public class KeyChainTest extends AndroidTestCase {
     public void testIsKeyAlgorithmSupported_RequiredAlgorithmsSupported() throws Exception {
         assertTrue("DSA must be supported", KeyChain.isKeyAlgorithmSupported("DSA"));
         assertTrue("EC must be supported", KeyChain.isKeyAlgorithmSupported("EC"));
@@ -34,11 +35,21 @@
      * tests in hardware/libhardware/tests/keymaster/
      */
     public void testIsBoundKeyAlgorithm_RequiredAlgorithmsSupported() throws Exception {
-        assertTrue("RSA must be hardware-backed by a hardware-specific Keymaster HAL",
-                KeyChain.isBoundKeyAlgorithm("RSA"));
+        if (isLeanbackOnly()) {
+            KeyChain.isBoundKeyAlgorithm("RSA");
+        }
+        else {
+            assertTrue("RSA must be hardware-backed by a hardware-specific Keymaster HAL",
+                       KeyChain.isBoundKeyAlgorithm("RSA"));
+        }
 
         // These are not required, but must not throw an exception
         KeyChain.isBoundKeyAlgorithm("DSA");
         KeyChain.isBoundKeyAlgorithm("EC");
     }
+
+    private boolean isLeanbackOnly() {
+        PackageManager pm = getContext().getPackageManager();
+        return (pm != null && pm.hasSystemFeature("android.software.leanback_only"));
+    }
 }
diff --git a/tests/tests/location/Android.mk b/tests/tests/location/Android.mk
index b76672c..02de2f2 100644
--- a/tests/tests/location/Android.mk
+++ b/tests/tests/location/Android.mk
@@ -21,17 +21,12 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsLocationTestCases
 
-LOCAL_INSTRUMENTATION_FOR := CtsTestStubs
-
-# uncomment when dalvik.annotation.Test* are removed or part of SDK
-#LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := current
 
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/location/AndroidManifest.xml b/tests/tests/location/AndroidManifest.xml
index 147f0ba..5016f49 100644
--- a/tests/tests/location/AndroidManifest.xml
+++ b/tests/tests/location/AndroidManifest.xml
@@ -27,8 +27,11 @@
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
     <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.cts.location"
-                     android:label="CTS tests of android.location"/>
+                     android:label="CTS tests of android.location">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 </manifest>
 
diff --git a/tests/tests/location/src/android/location/cts/LocationManagerTest.java b/tests/tests/location/src/android/location/cts/LocationManagerTest.java
index 64b15dc..a985aee 100644
--- a/tests/tests/location/src/android/location/cts/LocationManagerTest.java
+++ b/tests/tests/location/src/android/location/cts/LocationManagerTest.java
@@ -37,6 +37,7 @@
 import android.os.SystemClock;
 import android.provider.Settings;
 import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
 
 import java.util.List;
 
@@ -81,7 +82,7 @@
         // remove test provider if left over from an aborted run
         LocationProvider lp = mManager.getProvider(TEST_MOCK_PROVIDER_NAME);
         if (lp != null) {
-            removeTestProvider(TEST_MOCK_PROVIDER_NAME);
+            mManager.removeTestProvider(TEST_MOCK_PROVIDER_NAME);
         }
 
         addTestProvider(TEST_MOCK_PROVIDER_NAME);
@@ -107,7 +108,7 @@
     protected void tearDown() throws Exception {
         LocationProvider provider = mManager.getProvider(TEST_MOCK_PROVIDER_NAME);
         if (provider != null) {
-            removeTestProvider(TEST_MOCK_PROVIDER_NAME);
+            mManager.removeTestProvider(TEST_MOCK_PROVIDER_NAME);
         }
         if (mPendingIntent != null) {
             mManager.removeProximityAlert(mPendingIntent);
@@ -138,12 +139,12 @@
             // expected
         }
 
-        removeTestProvider(TEST_MOCK_PROVIDER_NAME);
+        mManager.removeTestProvider(TEST_MOCK_PROVIDER_NAME);
         provider = mManager.getProvider(TEST_MOCK_PROVIDER_NAME);
         assertNull(provider);
 
         try {
-            removeTestProvider(UNKNOWN_PROVIDER_NAME);
+            mManager.removeTestProvider(UNKNOWN_PROVIDER_NAME);
             fail("Should throw IllegalArgumentException when no provider exists!");
         } catch (IllegalArgumentException e) {
             // expected
@@ -177,7 +178,7 @@
         assertEquals(oldSizeAllProviders, providers.size());
         assertTrue(hasTestProvider(providers));
 
-        removeTestProvider(TEST_MOCK_PROVIDER_NAME);
+        mManager.removeTestProvider(TEST_MOCK_PROVIDER_NAME);
         providers = mManager.getAllProviders();
         assertEquals(oldSizeAllProviders - 1, providers.size());
         assertFalse(hasTestProvider(providers));
@@ -277,8 +278,8 @@
 
         // Find out location manager's opinion on the matter, making sure we dont' get spurious
         // results from test versions of the two providers.
-        forceClearTestProvider(LocationManager.GPS_PROVIDER);
-        forceClearTestProvider(LocationManager.NETWORK_PROVIDER);
+        forceRemoveTestProvider(LocationManager.GPS_PROVIDER);
+        forceRemoveTestProvider(LocationManager.NETWORK_PROVIDER);
         boolean lmGps = mManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
         boolean lmNlp = mManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
 
@@ -330,20 +331,12 @@
     }
 
     /**
-     * Clears the test provider. Works around b/11446702 by temporarily adding the test provider
-     * so we are allowed to clear it.
+     * Ensures the test provider is removed. {@link LocationManager#removeTestProvider(String)}
+     * throws an {@link java.lang.IllegalArgumentException} if there is no such test provider,
+     * so we have to add it before we clear it.
      */
-    private void forceClearTestProvider(String provider) {
+    private void forceRemoveTestProvider(String provider) {
         addTestProvider(provider);
-        mManager.clearTestProviderEnabled(provider);
-        removeTestProvider(provider);
-    }
-
-    /**
-     * Work around b/11446702 by clearing the test provider before removing it
-     */
-    private void removeTestProvider(String provider) {
-        mManager.clearTestProviderEnabled(provider);
         mManager.removeTestProvider(provider);
     }
 
@@ -623,6 +616,7 @@
         }
     }
 
+    @UiThreadTest
     public void testGpsStatusListener() {
         MockGpsStatusListener listener = new MockGpsStatusListener();
         mManager.addGpsStatusListener(listener);
diff --git a/tests/tests/location2/Android.mk b/tests/tests/location2/Android.mk
index e89204d..5b227b2 100644
--- a/tests/tests/location2/Android.mk
+++ b/tests/tests/location2/Android.mk
@@ -21,17 +21,13 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsLocation2TestCases
 
-LOCAL_INSTRUMENTATION_FOR := CtsTestStubs
-
-# uncomment when dalvik.annotation.Test* are removed or part of SDK
-#LOCAL_SDK_VERSION := current
+# uncomment when Location.EXTRA_NO_GPS_LOCATION is removed
+#LOCAL_SDK_VERSION := curren
 
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/location2/AndroidManifest.xml b/tests/tests/location2/AndroidManifest.xml
index 118278b..ad77b7e 100644
--- a/tests/tests/location2/AndroidManifest.xml
+++ b/tests/tests/location2/AndroidManifest.xml
@@ -27,8 +27,11 @@
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
     <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.cts.location2"
-                     android:label="CTS tests of android.location"/>
+                     android:label="CTS tests of android.location">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 </manifest>
 
diff --git a/tests/tests/location2/src/android/location2/cts/LocationManagerTest.java b/tests/tests/location2/src/android/location2/cts/LocationManagerTest.java
index 6bf5c62..3765809 100644
--- a/tests/tests/location2/src/android/location2/cts/LocationManagerTest.java
+++ b/tests/tests/location2/src/android/location2/cts/LocationManagerTest.java
@@ -36,6 +36,7 @@
 import android.os.SystemClock;
 import android.provider.Settings;
 import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
 
 import java.util.List;
 import java.lang.Thread;
@@ -223,17 +224,21 @@
         return false;
     }
 
+    @UiThreadTest
     public void testGpsStatusListener() {
         try {
-            mManager.addGpsStatusListener(new MockGpsStatusListener());
-            fail("Should have failed to add a gps status listener");
+            // .addGpsStatusListener returns true if the listener added successfully
+            if (mManager.addGpsStatusListener(new MockGpsStatusListener())) {
+                fail("Should have failed to add a gps status listener");
+            }
         } catch (SecurityException e) {
             // expected
         }
 
         try {
-            mManager.addGpsStatusListener(null);
-            fail("Should have failed to add a gps status listener");
+            if (mManager.addGpsStatusListener(null)) {
+                fail("Should have failed to add null as a gps status listener");
+            }
         } catch (SecurityException e) {
             // expected
         }
diff --git a/tests/tests/media/Android.mk b/tests/tests/media/Android.mk
index 4474b4a..15237a8 100644
--- a/tests/tests/media/Android.mk
+++ b/tests/tests/media/Android.mk
@@ -21,14 +21,21 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
+# include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
 LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestserver ctstestrunner
 
+LOCAL_JNI_SHARED_LIBRARIES := libctsmediacodec_jni
+
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsMediaTestCases
 
-# uncomment when dalvik.annotation.Test* are removed or part of SDK
+# uncomment when b/13249737 is fixed
 #LOCAL_SDK_VERSION := current
+LOCAL_JAVA_LIBRARIES += android.test.runner
 
 include $(BUILD_CTS_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/media/AndroidManifest.xml b/tests/tests/media/AndroidManifest.xml
index 90024c4..d53b2c6 100644
--- a/tests/tests/media/AndroidManifest.xml
+++ b/tests/tests/media/AndroidManifest.xml
@@ -66,9 +66,12 @@
         </service>
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.cts.media"
-                     android:label="CTS tests of android.media"/>
+                     android:label="CTS tests of android.media">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/tests/media/libmediandkjni/Android.mk b/tests/tests/media/libmediandkjni/Android.mk
new file mode 100644
index 0000000..2d2033f
--- /dev/null
+++ b/tests/tests/media/libmediandkjni/Android.mk
@@ -0,0 +1,31 @@
+# Copyright (C) 2012 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE    := libctsmediacodec_jni
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := native-media-jni.cpp
+
+LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
+
+LOCAL_C_INCLUDES += $(call include-path-for, mediandk)
+
+LOCAL_SHARED_LIBRARIES := libandroid libnativehelper liblog libmediandk
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/media/libmediandkjni/native-media-jni.cpp b/tests/tests/media/libmediandkjni/native-media-jni.cpp
new file mode 100644
index 0000000..850932f1
--- /dev/null
+++ b/tests/tests/media/libmediandkjni/native-media-jni.cpp
@@ -0,0 +1,662 @@
+/*
+ * 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.
+ */
+
+/* Original code copied from NDK Native-media sample code */
+
+#undef NDEBUG
+#include <assert.h>
+#include <jni.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <semaphore.h>
+
+#include <android/native_window_jni.h>
+
+// for __android_log_print(ANDROID_LOG_INFO, "YourApp", "formatted message");
+#include <android/log.h>
+#define TAG "NativeMedia"
+#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__)
+#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
+#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
+
+#include "ndk/NdkMediaExtractor.h"
+#include "ndk/NdkMediaCodec.h"
+#include "ndk/NdkMediaCrypto.h"
+#include "ndk/NdkMediaFormat.h"
+#include "ndk/NdkMediaMuxer.h"
+
+template <class T>
+class simplevector {
+    T *storage;
+    int capacity;
+    int numfilled;
+public:
+    simplevector() {
+        capacity = 16;
+        numfilled = 0;
+        storage = new T[capacity];
+    }
+    ~simplevector() {
+        delete[] storage;
+    }
+
+    void add(T item) {
+        if (numfilled == capacity) {
+            T *old = storage;
+            capacity *= 2;
+            storage = new T[capacity];
+            for (int i = 0; i < numfilled; i++) {
+                storage[i] = old[i];
+            }
+            delete[] old;
+        }
+        storage[numfilled] = item;
+        numfilled++;
+    }
+
+    int size() {
+        return numfilled;
+    }
+
+    T* data() {
+        return storage;
+    }
+};
+
+
+
+jobject testExtractor(AMediaExtractor *ex, JNIEnv *env) {
+
+    simplevector<int> sizes;
+    int numtracks = AMediaExtractor_getTrackCount(ex);
+    sizes.add(numtracks);
+    for (int i = 0; i < numtracks; i++) {
+        AMediaFormat *format = AMediaExtractor_getTrackFormat(ex, i);
+        const char *s = AMediaFormat_toString(format);
+        ALOGI("track %d format: %s", i, s);
+        const char *mime;
+        if (!AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime)) {
+            ALOGE("no mime type");
+            return NULL;
+        } else if (!strncmp(mime, "audio/", 6)) {
+            sizes.add(0);
+            int32_t val32;
+            int64_t val64;
+            AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &val32);
+            sizes.add(val32);
+            AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, &val32);
+            sizes.add(val32);
+            AMediaFormat_getInt64(format, AMEDIAFORMAT_KEY_DURATION, &val64);
+            sizes.add(val64);
+        } else if (!strncmp(mime, "video/", 6)) {
+            sizes.add(1);
+            int32_t val32;
+            int64_t val64;
+            AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, &val32);
+            sizes.add(val32);
+            AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, &val32);
+            sizes.add(val32);
+            AMediaFormat_getInt64(format, AMEDIAFORMAT_KEY_DURATION, &val64);
+            sizes.add(val64);
+        } else {
+            ALOGE("expected audio or video mime type, got %s", mime);
+        }
+        AMediaFormat_delete(format);
+        AMediaExtractor_selectTrack(ex, i);
+    }
+    int bufsize = 1024*1024;
+    uint8_t *buf = new uint8_t[bufsize];
+    while(true) {
+        int n = AMediaExtractor_readSampleData(ex, buf, bufsize);
+        if (n < 0) {
+            break;
+        }
+        sizes.add(n);
+        sizes.add(AMediaExtractor_getSampleTrackIndex(ex));
+        sizes.add(AMediaExtractor_getSampleFlags(ex));
+        sizes.add(AMediaExtractor_getSampleTime(ex));
+        AMediaExtractor_advance(ex);
+    }
+
+    // allocate java int array for result and return it
+    int *data = sizes.data();
+    int numsamples = sizes.size();
+    jintArray ret = env->NewIntArray(numsamples);
+    jboolean isCopy;
+    jint *dst = env->GetIntArrayElements(ret, &isCopy);
+    for (int i = 0; i < numsamples; ++i) {
+        dst[i] = data[i];
+    }
+    env->ReleaseIntArrayElements(ret, dst, 0);
+
+    delete[] buf;
+    AMediaExtractor_delete(ex);
+    return ret;
+}
+
+
+// get the sample sizes for the file
+extern "C" jobject Java_android_media_cts_NativeDecoderTest_getSampleSizesNative(JNIEnv *env,
+        jclass /*clazz*/, int fd, jlong offset, jlong size)
+{
+    AMediaExtractor *ex = AMediaExtractor_new();
+    int err = AMediaExtractor_setDataSourceFd(ex, fd, offset, size);
+    if (err != 0) {
+        ALOGE("setDataSource error: %d", err);
+        return NULL;
+    }
+    return testExtractor(ex, env);
+}
+
+// get the sample sizes for the path
+extern "C" jobject Java_android_media_cts_NativeDecoderTest_getSampleSizesNativePath(JNIEnv *env,
+        jclass /*clazz*/, jstring jpath)
+{
+    AMediaExtractor *ex = AMediaExtractor_new();
+
+    const char *tmp = env->GetStringUTFChars(jpath, NULL);
+    if (tmp == NULL) {  // Out of memory
+        return NULL;
+    }
+
+    int err = AMediaExtractor_setDataSource(ex, tmp);
+
+    env->ReleaseStringUTFChars(jpath, tmp);
+
+    if (err != 0) {
+        ALOGE("setDataSource error: %d", err);
+        return NULL;
+    }
+    return testExtractor(ex, env);
+}
+
+static int adler32(const uint8_t *input, int len) {
+
+    int a = 1;
+    int b = 0;
+    for (int i = 0; i < len; i++) {
+        a += input[i];
+        b += a;
+    }
+    a = a % 65521;
+    b = b % 65521;
+    int ret = b * 65536 + a;
+    ALOGV("adler %d/%d", len, ret);
+    return ret;
+}
+
+static int checksum(const uint8_t *in, int len, AMediaFormat *format) {
+    int width, stride, height;
+    if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, &width)) {
+        width = len;
+    }
+    if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_STRIDE, &stride)) {
+        stride = width;
+    }
+    if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, &height)) {
+        height = 1;
+    }
+    uint8_t *bb = new uint8_t[width * height];
+    for (int i = 0; i < height; i++) {
+        memcpy(bb + i * width, in + i * stride, width);
+    }
+    // bb is filled with data
+    int sum = adler32(bb, width * height);
+    delete[] bb;
+    return sum;
+}
+
+extern "C" jobject Java_android_media_cts_NativeDecoderTest_getDecodedDataNative(JNIEnv *env,
+        jclass /*clazz*/, int fd, jlong offset, jlong size) {
+    ALOGV("getDecodedDataNative");
+
+    AMediaExtractor *ex = AMediaExtractor_new();
+    int err = AMediaExtractor_setDataSourceFd(ex, fd, offset, size);
+    if (err != 0) {
+        ALOGE("setDataSource error: %d", err);
+        return NULL;
+    }
+
+    int numtracks = AMediaExtractor_getTrackCount(ex);
+
+    AMediaCodec **codec = new AMediaCodec*[numtracks];
+    AMediaFormat **format = new AMediaFormat*[numtracks];
+    bool *sawInputEOS = new bool[numtracks];
+    bool *sawOutputEOS = new bool[numtracks];
+    simplevector<int> sizes[numtracks];
+
+    ALOGV("input has %d tracks", numtracks);
+    for (int i = 0; i < numtracks; i++) {
+        AMediaFormat *format = AMediaExtractor_getTrackFormat(ex, i);
+        const char *s = AMediaFormat_toString(format);
+        ALOGI("track %d format: %s", i, s);
+        const char *mime;
+        if (!AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime)) {
+            ALOGE("no mime type");
+            return NULL;
+        } else if (!strncmp(mime, "audio/", 6) || !strncmp(mime, "video/", 6)) {
+            codec[i] = AMediaCodec_createDecoderByType(mime);
+            AMediaCodec_configure(codec[i], format, NULL /* surface */, NULL /* crypto */, 0);
+            AMediaCodec_start(codec[i]);
+            sawInputEOS[i] = false;
+            sawOutputEOS[i] = false;
+        } else {
+            ALOGE("expected audio or video mime type, got %s", mime);
+            return NULL;
+        }
+        AMediaFormat_delete(format);
+        AMediaExtractor_selectTrack(ex, i);
+    }
+    int eosCount = 0;
+    while(eosCount < numtracks) {
+        int t = AMediaExtractor_getSampleTrackIndex(ex);
+        if (t >=0) {
+            ssize_t bufidx = AMediaCodec_dequeueInputBuffer(codec[t], 5000);
+            ALOGV("track %d, input buffer %d", t, bufidx);
+            if (bufidx >= 0) {
+                size_t bufsize;
+                uint8_t *buf = AMediaCodec_getInputBuffer(codec[t], bufidx, &bufsize);
+                int sampleSize = AMediaExtractor_readSampleData(ex, buf, bufsize);
+                ALOGV("read %d", sampleSize);
+                if (sampleSize < 0) {
+                    sampleSize = 0;
+                    sawInputEOS[t] = true;
+                    ALOGV("EOS");
+                    //break;
+                }
+                int64_t presentationTimeUs = AMediaExtractor_getSampleTime(ex);
+
+                AMediaCodec_queueInputBuffer(codec[t], bufidx, 0, sampleSize, presentationTimeUs,
+                        sawInputEOS[t] ? AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM : 0);
+                AMediaExtractor_advance(ex);
+            }
+        } else {
+            ALOGV("@@@@ no more input samples");
+            for (int tt = 0; tt < numtracks; tt++) {
+                if (!sawInputEOS[tt]) {
+                    // we ran out of samples without ever signaling EOS to the codec,
+                    // so do that now
+                    int bufidx = AMediaCodec_dequeueInputBuffer(codec[tt], 5000);
+                    if (bufidx >= 0) {
+                        AMediaCodec_queueInputBuffer(codec[tt], bufidx, 0, 0, 0,
+                                AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM);
+                        sawInputEOS[tt] = true;
+                    }
+                }
+            }
+        }
+
+        // check all codecs for available data
+        AMediaCodecBufferInfo info;
+        for (int tt = 0; tt < numtracks; tt++) {
+            if (!sawOutputEOS[tt]) {
+                int status = AMediaCodec_dequeueOutputBuffer(codec[tt], &info, 1);
+                ALOGV("dequeueoutput on track %d: %d", tt, status);
+                if (status >= 0) {
+                    if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) {
+                        ALOGV("EOS on track %d", tt);
+                        sawOutputEOS[tt] = true;
+                        eosCount++;
+                    }
+                    ALOGV("got decoded buffer for track %d, size %d", tt, info.size);
+                    if (info.size > 0) {
+                        size_t bufsize;
+                        uint8_t *buf = AMediaCodec_getOutputBuffer(codec[tt], status, &bufsize);
+                        int adler = checksum(buf, info.size, format[tt]);
+                        sizes[tt].add(adler);
+                    }
+                    AMediaCodec_releaseOutputBuffer(codec[tt], status, false);
+                } else if (status == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) {
+                    ALOGV("output buffers changed for track %d", tt);
+                } else if (status == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) {
+                    format[tt] = AMediaCodec_getOutputFormat(codec[tt]);
+                    ALOGV("format changed for track %d: %s", tt, AMediaFormat_toString(format[tt]));
+                } else if (status == AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
+                    ALOGV("no output buffer right now for track %d", tt);
+                } else {
+                    ALOGV("unexpected info code for track %d : %d", tt, status);
+                }
+            } else {
+                ALOGV("already at EOS on track %d", tt);
+            }
+        }
+    }
+    ALOGV("decoding loop done");
+
+    // allocate java int array for result and return it
+    int numsamples = 0;
+    for (int i = 0; i < numtracks; i++) {
+        numsamples += sizes[i].size();
+    }
+    ALOGV("checksums: %d", numsamples);
+    jintArray ret = env->NewIntArray(numsamples);
+    jboolean isCopy;
+    jint *org = env->GetIntArrayElements(ret, &isCopy);
+    jint *dst = org;
+    for (int i = 0; i < numtracks; i++) {
+        int *data = sizes[i].data();
+        int len = sizes[i].size();
+        ALOGV("copying %d", len);
+        for (int j = 0; j < len; j++) {
+            *dst++ = data[j];
+        }
+    }
+    env->ReleaseIntArrayElements(ret, org, 0);
+
+    delete[] sawInputEOS;
+    for (int i = 0; i < numtracks; i++) {
+        AMediaFormat_delete(format[i]);
+        AMediaCodec_stop(codec[i]);
+        AMediaCodec_delete(codec[i]);
+    }
+    delete[] format;
+    delete[] codec;
+    AMediaExtractor_delete(ex);
+    return ret;
+}
+
+extern "C" jboolean Java_android_media_cts_NativeDecoderTest_testPlaybackNative(JNIEnv *env,
+        jclass /*clazz*/, jobject surface, int fd, jlong offset, jlong size) {
+
+    ANativeWindow *window = ANativeWindow_fromSurface(env, surface);
+    ALOGI("@@@@ native window: %p", window);
+
+    AMediaExtractor *ex = AMediaExtractor_new();
+    int err = AMediaExtractor_setDataSourceFd(ex, fd, offset, size);
+    if (err != 0) {
+        ALOGE("setDataSource error: %d", err);
+        return false;
+    }
+
+    int numtracks = AMediaExtractor_getTrackCount(ex);
+
+    AMediaCodec *codec = NULL;
+    AMediaFormat *format = NULL;
+    bool sawInputEOS = false;
+    bool sawOutputEOS = false;
+
+    ALOGV("input has %d tracks", numtracks);
+    for (int i = 0; i < numtracks; i++) {
+        AMediaFormat *format = AMediaExtractor_getTrackFormat(ex, i);
+        const char *s = AMediaFormat_toString(format);
+        ALOGI("track %d format: %s", i, s);
+        const char *mime;
+        if (!AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime)) {
+            ALOGE("no mime type");
+            return false;
+        } else if (!strncmp(mime, "video/", 6)) {
+            codec = AMediaCodec_createDecoderByType(mime);
+            AMediaCodec_configure(codec, format, window, NULL, 0);
+            AMediaCodec_start(codec);
+            AMediaExtractor_selectTrack(ex, i);
+        }
+        AMediaFormat_delete(format);
+    }
+
+    while (!sawOutputEOS) {
+        ssize_t bufidx = AMediaCodec_dequeueInputBuffer(codec, 5000);
+        ALOGV("input buffer %d", bufidx);
+        if (bufidx >= 0) {
+            size_t bufsize;
+            uint8_t *buf = AMediaCodec_getInputBuffer(codec, bufidx, &bufsize);
+            int sampleSize = AMediaExtractor_readSampleData(ex, buf, bufsize);
+            ALOGV("read %d", sampleSize);
+            if (sampleSize < 0) {
+                sampleSize = 0;
+                sawInputEOS = true;
+                ALOGV("EOS");
+            }
+            int64_t presentationTimeUs = AMediaExtractor_getSampleTime(ex);
+
+            AMediaCodec_queueInputBuffer(codec, bufidx, 0, sampleSize, presentationTimeUs,
+                    sawInputEOS ? AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM : 0);
+            AMediaExtractor_advance(ex);
+        }
+
+        AMediaCodecBufferInfo info;
+        int status = AMediaCodec_dequeueOutputBuffer(codec, &info, 1);
+        ALOGV("dequeueoutput returned: %d", status);
+        if (status >= 0) {
+            if (info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) {
+                ALOGV("output EOS");
+                sawOutputEOS = true;
+            }
+            ALOGV("got decoded buffer size %d", info.size);
+            AMediaCodec_releaseOutputBuffer(codec, status, true);
+            usleep(20000);
+        } else if (status == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) {
+            ALOGV("output buffers changed");
+        } else if (status == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) {
+            format = AMediaCodec_getOutputFormat(codec);
+            ALOGV("format changed to: %s", AMediaFormat_toString(format));
+        } else if (status == AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
+            ALOGV("no output buffer right now");
+        } else {
+            ALOGV("unexpected info code: %d", status);
+        }
+    }
+
+    AMediaCodec_stop(codec);
+    AMediaCodec_delete(codec);
+    AMediaExtractor_delete(ex);
+    return true;
+}
+
+extern "C" jboolean Java_android_media_cts_NativeDecoderTest_testMuxerNative(JNIEnv */*env*/,
+        jclass /*clazz*/, int infd, jlong inoffset, jlong insize, int outfd, jboolean webm) {
+
+
+    AMediaMuxer *muxer = AMediaMuxer_new(outfd,
+            webm ? AMEDIAMUXER_OUTPUT_FORMAT_WEBM : AMEDIAMUXER_OUTPUT_FORMAT_MPEG_4);
+
+    AMediaExtractor *ex = AMediaExtractor_new();
+    int err = AMediaExtractor_setDataSourceFd(ex, infd, inoffset, insize);
+    if (err != 0) {
+        ALOGE("setDataSource error: %d", err);
+        return false;
+    }
+
+    int numtracks = AMediaExtractor_getTrackCount(ex);
+    ALOGI("input tracks: %d", numtracks);
+    for (int i = 0; i < numtracks; i++) {
+        AMediaFormat *format = AMediaExtractor_getTrackFormat(ex, i);
+        const char *s = AMediaFormat_toString(format);
+        ALOGI("track %d format: %s", i, s);
+        const char *mime;
+        if (!AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime)) {
+            ALOGE("no mime type");
+            return false;
+        } else if (!strncmp(mime, "audio/", 6) || !strncmp(mime, "video/", 6)) {
+            ssize_t tidx = AMediaMuxer_addTrack(muxer, format);
+            ALOGI("track %d -> %d format %s", i, tidx, s);
+            AMediaExtractor_selectTrack(ex, i);
+        } else {
+            ALOGE("expected audio or video mime type, got %s", mime);
+            return false;
+        }
+        AMediaFormat_delete(format);
+        AMediaExtractor_selectTrack(ex, i);
+    }
+    AMediaMuxer_start(muxer);
+
+    int bufsize = 1024*1024;
+    uint8_t *buf = new uint8_t[bufsize];
+    AMediaCodecBufferInfo info;
+    while(true) {
+        int n = AMediaExtractor_readSampleData(ex, buf, bufsize);
+        if (n < 0) {
+            break;
+        }
+        info.offset = 0;
+        info.size = n;
+        info.presentationTimeUs = AMediaExtractor_getSampleTime(ex);
+        info.flags = AMediaExtractor_getSampleFlags(ex);
+
+        size_t idx = (size_t) AMediaExtractor_getSampleTrackIndex(ex);
+        AMediaMuxer_writeSampleData(muxer, idx, buf, &info);
+
+        AMediaExtractor_advance(ex);
+    }
+
+    AMediaExtractor_delete(ex);
+    AMediaMuxer_stop(muxer);
+    AMediaMuxer_delete(muxer);
+    return true;
+
+}
+
+extern "C" jboolean Java_android_media_cts_NativeDecoderTest_testFormatNative(JNIEnv * /*env*/,
+        jclass /*clazz*/) {
+    AMediaFormat* format = AMediaFormat_new();
+    if (!format) {
+        return false;
+    }
+
+    AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, 8000);
+    int32_t bitrate = 0;
+    if (!AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, &bitrate) || bitrate != 8000) {
+        ALOGE("AMediaFormat_getInt32 fail: %d", bitrate);
+        return false;
+    }
+
+    AMediaFormat_setInt64(format, AMEDIAFORMAT_KEY_DURATION, 123456789123456789ll);
+    int64_t duration = 0;
+    if (!AMediaFormat_getInt64(format, AMEDIAFORMAT_KEY_DURATION, &duration)
+            || duration != 123456789123456789ll) {
+        ALOGE("AMediaFormat_getInt64 fail: %lld", duration);
+        return false;
+    }
+
+    AMediaFormat_setFloat(format, AMEDIAFORMAT_KEY_FRAME_RATE, 25.0f);
+    float framerate = 0.0f;
+    if (!AMediaFormat_getFloat(format, AMEDIAFORMAT_KEY_FRAME_RATE, &framerate)
+            || framerate != 25.0f) {
+        ALOGE("AMediaFormat_getFloat fail: %f", framerate);
+        return false;
+    }
+
+    const char* value = "audio/mpeg";
+    AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME, value);
+    const char* readback = NULL;
+    if (!AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &readback)
+            || strcmp(value, readback) || value == readback) {
+        ALOGE("AMediaFormat_getString fail");
+        return false;
+    }
+
+    uint32_t foo = 0xdeadbeef;
+    AMediaFormat_setBuffer(format, "csd-0", &foo, sizeof(foo));
+    foo = 0xabadcafe;
+    void *bytes;
+    size_t bytesize = 0;
+    if(!AMediaFormat_getBuffer(format, "csd-0", &bytes, &bytesize)
+            || bytesize != sizeof(foo) || *((uint32_t*)bytes) != 0xdeadbeef) {
+        ALOGE("AMediaFormat_getBuffer fail");
+        return false;
+    }
+
+    return true;
+}
+
+
+extern "C" jboolean Java_android_media_cts_NativeDecoderTest_testPsshNative(JNIEnv * /*env*/,
+        jclass /*clazz*/, int fd, jlong offset, jlong size) {
+
+    AMediaExtractor *ex = AMediaExtractor_new();
+    int err = AMediaExtractor_setDataSourceFd(ex, fd, offset, size);
+    if (err != 0) {
+        ALOGE("setDataSource error: %d", err);
+        return false;
+    }
+
+    PsshInfo* info = AMediaExtractor_getPsshInfo(ex);
+    if (info == NULL) {
+        ALOGI("null pssh");
+        return false;
+    }
+
+    ALOGI("pssh has %zd entries", info->numentries);
+    if (info->numentries != 2) {
+        return false;
+    }
+
+    for (size_t i = 0; i < info->numentries; i++) {
+        PsshEntry *entry = &info->entries[i];
+        ALOGI("entry uuid %02x%02x..%02x%02x, data size %zd",
+                entry->uuid[0],
+                entry->uuid[1],
+                entry->uuid[14],
+                entry->uuid[15],
+                entry->datalen);
+
+        AMediaCrypto *crypto = AMediaCrypto_new(entry->uuid, entry->data, entry->datalen);
+        if (crypto) {
+            ALOGI("got crypto");
+            AMediaCrypto_delete(crypto);
+        } else {
+            ALOGI("no crypto");
+        }
+    }
+    return true;
+}
+
+extern "C" jboolean Java_android_media_cts_NativeDecoderTest_testCryptoInfoNative(JNIEnv * /*env*/,
+        jclass /*clazz*/) {
+
+    size_t numsubsamples = 4;
+    uint8_t key[16] = { 1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4 };
+    uint8_t iv[16] = { 4,3,2,1,4,3,2,1,4,3,2,1,4,3,2,1 };
+    size_t clearbytes[4] = { 5, 6, 7, 8 };
+    size_t encryptedbytes[4] = { 8, 7, 6, 5 };
+
+    AMediaCodecCryptoInfo *ci =
+            AMediaCodecCryptoInfo_new(numsubsamples, key, iv, AMEDIACODECRYPTOINFO_MODE_CLEAR, clearbytes, encryptedbytes);
+
+    if (AMediaCodecCryptoInfo_getNumSubSamples(ci) != 4) {
+        ALOGE("numsubsamples mismatch");
+        return false;
+    }
+    uint8_t bytes[16];
+    AMediaCodecCryptoInfo_getKey(ci, bytes);
+    if (memcmp(key, bytes, 16) != 0) {
+        ALOGE("key mismatch");
+        return false;
+    }
+    AMediaCodecCryptoInfo_getIV(ci, bytes);
+    if (memcmp(iv, bytes, 16) != 0) {
+        ALOGE("IV mismatch");
+        return false;
+    }
+    if (AMediaCodecCryptoInfo_getMode(ci) != AMEDIACODECRYPTOINFO_MODE_CLEAR) {
+        ALOGE("mode mismatch");
+        return false;
+    }
+    size_t sizes[numsubsamples];
+    AMediaCodecCryptoInfo_getClearBytes(ci, sizes);
+    if (memcmp(clearbytes, sizes, sizeof(size_t) * numsubsamples)) {
+        ALOGE("clear size mismatch");
+        return false;
+    }
+    AMediaCodecCryptoInfo_getEncryptedBytes(ci, sizes);
+    if (memcmp(encryptedbytes, sizes, sizeof(size_t) * numsubsamples)) {
+        ALOGE("encrypted size mismatch");
+        return false;
+    }
+    return true;
+}
+
diff --git a/tests/tests/media/res/raw/big5_1.mp3 b/tests/tests/media/res/raw/big5_1.mp3
new file mode 100644
index 0000000..faa3eb4
--- /dev/null
+++ b/tests/tests/media/res/raw/big5_1.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/big5_2.mp3 b/tests/tests/media/res/raw/big5_2.mp3
new file mode 100644
index 0000000..a69da4f
--- /dev/null
+++ b/tests/tests/media/res/raw/big5_2.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/camera_click.ogg b/tests/tests/media/res/raw/camera_click.ogg
new file mode 100644
index 0000000..b836e10
--- /dev/null
+++ b/tests/tests/media/res/raw/camera_click.ogg
Binary files differ
diff --git a/tests/tests/media/res/raw/cp1251_3.mp3 b/tests/tests/media/res/raw/cp1251_3.mp3
new file mode 100644
index 0000000..179a1a5
--- /dev/null
+++ b/tests/tests/media/res/raw/cp1251_3.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/cp1251_4.mp3 b/tests/tests/media/res/raw/cp1251_4.mp3
new file mode 100644
index 0000000..3df1d32
--- /dev/null
+++ b/tests/tests/media/res/raw/cp1251_4.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/cp1251_5.mp3 b/tests/tests/media/res/raw/cp1251_5.mp3
new file mode 100644
index 0000000..46df442
--- /dev/null
+++ b/tests/tests/media/res/raw/cp1251_5.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/cp1251_6.mp3 b/tests/tests/media/res/raw/cp1251_6.mp3
new file mode 100644
index 0000000..545834d
--- /dev/null
+++ b/tests/tests/media/res/raw/cp1251_6.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/cp1251_7.mp3 b/tests/tests/media/res/raw/cp1251_7.mp3
new file mode 100644
index 0000000..d1c492b
--- /dev/null
+++ b/tests/tests/media/res/raw/cp1251_7.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/cp1251_8.mp3 b/tests/tests/media/res/raw/cp1251_8.mp3
new file mode 100644
index 0000000..17f7e31
--- /dev/null
+++ b/tests/tests/media/res/raw/cp1251_8.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/cp1251_v1.mp3 b/tests/tests/media/res/raw/cp1251_v1.mp3
new file mode 100644
index 0000000..173d970
--- /dev/null
+++ b/tests/tests/media/res/raw/cp1251_v1.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/cp1251_v1v2.mp3 b/tests/tests/media/res/raw/cp1251_v1v2.mp3
new file mode 100644
index 0000000..abffa92
--- /dev/null
+++ b/tests/tests/media/res/raw/cp1251_v1v2.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/football_qvga.yuv b/tests/tests/media/res/raw/football_qvga.yuv
new file mode 100644
index 0000000..f18f676
--- /dev/null
+++ b/tests/tests/media/res/raw/football_qvga.yuv
Binary files differ
diff --git a/tests/tests/media/res/raw/football_qvga_desc.txt b/tests/tests/media/res/raw/football_qvga_desc.txt
new file mode 100644
index 0000000..f6b44b2
--- /dev/null
+++ b/tests/tests/media/res/raw/football_qvga_desc.txt
@@ -0,0 +1,2 @@
+Football_qvga.yuv contains 3 seconds of raw 320x240 yuv420 video @ 30 fps.
+Extracted from http://media.xiph.org/video/derf/y4m/football_cif.y4m.
\ No newline at end of file
diff --git a/tests/tests/media/res/raw/gb18030_1.mp3 b/tests/tests/media/res/raw/gb18030_1.mp3
new file mode 100644
index 0000000..dc63de5
--- /dev/null
+++ b/tests/tests/media/res/raw/gb18030_1.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/gb18030_2.mp3 b/tests/tests/media/res/raw/gb18030_2.mp3
new file mode 100644
index 0000000..6109c97
--- /dev/null
+++ b/tests/tests/media/res/raw/gb18030_2.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/gb18030_3.mp3 b/tests/tests/media/res/raw/gb18030_3.mp3
new file mode 100644
index 0000000..4fcb22f
--- /dev/null
+++ b/tests/tests/media/res/raw/gb18030_3.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/gb18030_4.mp3 b/tests/tests/media/res/raw/gb18030_4.mp3
new file mode 100644
index 0000000..fedffd7
--- /dev/null
+++ b/tests/tests/media/res/raw/gb18030_4.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/gb18030_5.mp3 b/tests/tests/media/res/raw/gb18030_5.mp3
new file mode 100644
index 0000000..70f76ce
--- /dev/null
+++ b/tests/tests/media/res/raw/gb18030_5.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/gb18030_6.mp3 b/tests/tests/media/res/raw/gb18030_6.mp3
new file mode 100644
index 0000000..b4817b2
--- /dev/null
+++ b/tests/tests/media/res/raw/gb18030_6.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/gb18030_7.mp3 b/tests/tests/media/res/raw/gb18030_7.mp3
new file mode 100644
index 0000000..7932596
--- /dev/null
+++ b/tests/tests/media/res/raw/gb18030_7.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/gb18030_8.mp3 b/tests/tests/media/res/raw/gb18030_8.mp3
new file mode 100644
index 0000000..f5f54de
--- /dev/null
+++ b/tests/tests/media/res/raw/gb18030_8.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/hebrew.mp3 b/tests/tests/media/res/raw/hebrew.mp3
new file mode 100644
index 0000000..59d76d8
--- /dev/null
+++ b/tests/tests/media/res/raw/hebrew.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/hebrew2.mp3 b/tests/tests/media/res/raw/hebrew2.mp3
new file mode 100644
index 0000000..d48cad2
--- /dev/null
+++ b/tests/tests/media/res/raw/hebrew2.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/iso88591_1.ogg b/tests/tests/media/res/raw/iso88591_1.ogg
new file mode 100644
index 0000000..c20bf34
--- /dev/null
+++ b/tests/tests/media/res/raw/iso88591_1.ogg
Binary files differ
diff --git a/tests/tests/media/res/raw/iso88591_10.mp3 b/tests/tests/media/res/raw/iso88591_10.mp3
new file mode 100644
index 0000000..4d43200
--- /dev/null
+++ b/tests/tests/media/res/raw/iso88591_10.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/iso88591_11.mp3 b/tests/tests/media/res/raw/iso88591_11.mp3
new file mode 100644
index 0000000..3760238
--- /dev/null
+++ b/tests/tests/media/res/raw/iso88591_11.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/iso88591_12.mp3 b/tests/tests/media/res/raw/iso88591_12.mp3
new file mode 100644
index 0000000..1ffcc0c9
--- /dev/null
+++ b/tests/tests/media/res/raw/iso88591_12.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/iso88591_13.mp3 b/tests/tests/media/res/raw/iso88591_13.mp3
new file mode 100644
index 0000000..91987c1
--- /dev/null
+++ b/tests/tests/media/res/raw/iso88591_13.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/iso88591_2.mp3 b/tests/tests/media/res/raw/iso88591_2.mp3
new file mode 100644
index 0000000..bcfdaad
--- /dev/null
+++ b/tests/tests/media/res/raw/iso88591_2.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/iso88591_3.mp3 b/tests/tests/media/res/raw/iso88591_3.mp3
new file mode 100644
index 0000000..2b6a03f
--- /dev/null
+++ b/tests/tests/media/res/raw/iso88591_3.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/iso88591_4.mp3 b/tests/tests/media/res/raw/iso88591_4.mp3
new file mode 100644
index 0000000..0623fff
--- /dev/null
+++ b/tests/tests/media/res/raw/iso88591_4.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/iso88591_5.mp3 b/tests/tests/media/res/raw/iso88591_5.mp3
new file mode 100644
index 0000000..8051af5
--- /dev/null
+++ b/tests/tests/media/res/raw/iso88591_5.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/iso88591_6.mp3 b/tests/tests/media/res/raw/iso88591_6.mp3
new file mode 100644
index 0000000..4dc2b49
--- /dev/null
+++ b/tests/tests/media/res/raw/iso88591_6.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/iso88591_7.mp3 b/tests/tests/media/res/raw/iso88591_7.mp3
new file mode 100644
index 0000000..72f5c5b
--- /dev/null
+++ b/tests/tests/media/res/raw/iso88591_7.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/iso88591_8.mp3 b/tests/tests/media/res/raw/iso88591_8.mp3
new file mode 100644
index 0000000..f841d59
--- /dev/null
+++ b/tests/tests/media/res/raw/iso88591_8.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/iso88591_9.mp3 b/tests/tests/media/res/raw/iso88591_9.mp3
new file mode 100644
index 0000000..8f93d488
--- /dev/null
+++ b/tests/tests/media/res/raw/iso88591_9.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/psshtest.mp4 b/tests/tests/media/res/raw/psshtest.mp4
new file mode 100644
index 0000000..98ffeb0
--- /dev/null
+++ b/tests/tests/media/res/raw/psshtest.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/shiftjis1.mp3 b/tests/tests/media/res/raw/shiftjis1.mp3
new file mode 100644
index 0000000..1c50c76
--- /dev/null
+++ b/tests/tests/media/res/raw/shiftjis1.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/shiftjis2.mp3 b/tests/tests/media/res/raw/shiftjis2.mp3
new file mode 100644
index 0000000..808c597
--- /dev/null
+++ b/tests/tests/media/res/raw/shiftjis2.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/shiftjis3.mp3 b/tests/tests/media/res/raw/shiftjis3.mp3
new file mode 100644
index 0000000..820631b
--- /dev/null
+++ b/tests/tests/media/res/raw/shiftjis3.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/shiftjis4.mp3 b/tests/tests/media/res/raw/shiftjis4.mp3
new file mode 100644
index 0000000..3fbc25e
--- /dev/null
+++ b/tests/tests/media/res/raw/shiftjis4.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/shiftjis5.mp3 b/tests/tests/media/res/raw/shiftjis5.mp3
new file mode 100644
index 0000000..90520f8
--- /dev/null
+++ b/tests/tests/media/res/raw/shiftjis5.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/shiftjis6.mp3 b/tests/tests/media/res/raw/shiftjis6.mp3
new file mode 100644
index 0000000..5310936
--- /dev/null
+++ b/tests/tests/media/res/raw/shiftjis6.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/shiftjis7.mp3 b/tests/tests/media/res/raw/shiftjis7.mp3
new file mode 100644
index 0000000..6143126
--- /dev/null
+++ b/tests/tests/media/res/raw/shiftjis7.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/shiftjis8.mp3 b/tests/tests/media/res/raw/shiftjis8.mp3
new file mode 100644
index 0000000..c45c130
--- /dev/null
+++ b/tests/tests/media/res/raw/shiftjis8.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/sinesweep51m4a.m4a b/tests/tests/media/res/raw/sinesweep51m4a.m4a
new file mode 100644
index 0000000..1e35934
--- /dev/null
+++ b/tests/tests/media/res/raw/sinesweep51m4a.m4a
Binary files differ
diff --git a/tests/tests/media/res/raw/sinesweeptsaac.m4a b/tests/tests/media/res/raw/sinesweeptsaac.m4a
new file mode 100644
index 0000000..f583012
--- /dev/null
+++ b/tests/tests/media/res/raw/sinesweeptsaac.m4a
Binary files differ
diff --git a/tests/tests/media/res/raw/testmp3_3.raw b/tests/tests/media/res/raw/testmp3_3.raw
new file mode 100644
index 0000000..1d5ee19
--- /dev/null
+++ b/tests/tests/media/res/raw/testmp3_3.raw
@@ -0,0 +1 @@
+SUQzBABAAAAAegAAAAwBIAUPNyZSM1RQRTEAAAAOAAAATmV3IFdhdmUgTGFic1RJVDIAAAAPAAAAVW5jb21tb24gU3RvcnlDT01NAAAAMwAAAAAAAAAoYykgQ29weXJpZ2h0IDIwMDggQW5kcm9pZCBPcGVuIFNvdXJjZSBQcm9qZWN0//pwBDV5AAABqxzGvSTAAD9DmHGnsACJ3IV9uUoQETYQrXc1IAIgBAWoAHtdG2ogYXCgYQRXFYrbUAYDTYgQIZZBDLJ388RH93rE77Z71rJ2Udz4ICQ4D6nfwwEGoafUbm2IYqFOJoLgdEVPlvJ2hakADAOW0gkCIJCg7BoTHTszfymrFiztXr32DM/+lNbfoZn74gDHUCBRwP4DgcDgcDgcDgYAAAAAAJKgbF6umkB5UoGyQJWgZIQAcM8DSlQMWH8BgGBYQAkP+AoTAxgoDEBAtM/xygbqBfQAYWG3/+RMzJ83My/++D78BgMBgMBgMBgKAAAAAAabN7JmcJXTG7HmYGSrGziBgiOH5duAfqDYLXdMOXDjAvm2+Fp4NkA20EAFNsnkOD4BHgXBil//K6Zums3/fB9MQf/6cgTaUgANgiQ+Vx88oARCRksH55QAiAzJVGw8p9EAnSqM9Ik6ABd3Aa1SH2V0YlB7IWiFbGlh73twkBhYOKPGu5WbGuHw6wACw1XG/rzXFb/+V5V1//Ra0KQ5WIb/8w26OVDDUvFh/UHgHABy7gZOBwuqS6Qha25y3BvTWeugYPAMOFRqiSU7BMqFHkd1b9ptAFEQ7dH+LGGlLWXf/1epSzVGfqBmJTINU7uoAKcjKHEoG1ZQ5sw8YfSjWDslm1pGlHXqKLaBe8lfrzbQFcmEQJZVX1fWNBRA+v+LWUdN//NShkNEh389jRLt9QBM3AGAzw7mZBBjCSgZhZ4xgQTDjXPA+88I2ZR0SpTv+uJG2aPkWame+9A8uCHR//QE5t7//q99UMZhnT31XIGTEFNRTMuOTcAAAAAA//pwBOp9AAyCFyNTmww8JERHWoNlgk6IOI1SbDCn0QgRqpz0iTMAObADFtkjB9TSwuVAKwwdHcYq78pk1DcsrCSnNhNDLVWmrsb5esBv+Pw4IbFrer2zGEgxnNf1dS5I1X11FYMD2fbaADdwBMockXHliie6kSMBQV7DR5IWVrSkxcWhzGox4o2vSfacLUorxlPsmLf81+Kt/2MLOyo6My9fypa6/Vqps6stBlWAJfwBjICCCWUKJEv2iyGJMdEFeiSQWCp+RRft5Fs3yv1JExnLAbN+r+gCB5yuj32dR51njawqJjYDABIoh80BBZIQU9+AMBHTOKRtBCjYEhEggWdSbLJG1s0HGieVmE9yWJOV9psEOJfHqsGclVGY+n4tAzZZG/vq76kddCIi69/Pa/aYgpqKZlxybv/6cgR03QAIghM6VBsJE7RCArqnPwkiiLTDVOkwRZkWCmnNh60iALv4A1LyHEOQcrhLqSplRqTs+5Zr3La+WcBtw5GSPfV7Hh/MOMJqzL61biDUVP5Kran9GzkU53QhSMLamiXRlecIwAQibvwOFcnytWjRamTibaBhPLXpph1L6RIUX2d+Vytj+A2wizntEWkZM/IHTJz+N1kEgQuwXYTAAWWUsmhYyQRisQVL/wJMAmAdhwlCYNwTPlY5u8cZgo2SS0pnXmXZHDGYDGqpWT1Sy1BGN/0NRr/zJr3oZQ4OQmlX05S7ShTt6PtXfilDegUZtgNCzSwFisYFBICxEAqj2V0TNniTVUaNU94pWa3AnnpVYgKxXb5WAmkTEwG74xjmv8yZWHGBx5lr2kzOy8VZFo7XMuTEFNRQ//pwBBnqAAiCESLU0wkSdEPlumNlYkzIZI9K7KSykQqYKtzziVoAAAglLvgNTMKKCy5QZUNM1mdaCD8mlEE5YBywn2zzc83E+r6Kj63yOTzrnJgblbf1YEFDq/bqkiy3khR4LLJJvReAnPwB0ebJSaXQyIugPZTwWKH66MjwigwLzlDaShH5mevRwznEUWFfb5xVLEMpWp/Qd3/6FV2RVFItgCjRBlX/dbEHDYglXYAZ2hGuRQy0Rzo+vYm5QzylUslt6ST7ZsKeG5li3dXbza0q9dewECSFPFoq/6pdRf/5QkLSQ5Dru4qDpFaL/uTEF3f8CopBQreGclAh5GoaAhyJrAwaNKOGk99YAeDHBdvdW7sKAZ3T6oURKiU23si7JRpwZYJzr4FOJQywWfQR1IWlMQU1FAAAAP/6cgQ3PgAJghoi1VMMKURCBKqXYOZfiDjLVOwcbdEUGKkNhJ3LAAwAJvf8D5aVUvLtEEMzRG/ca1KpbiMyj2CxDNvo4liRBbO6djjzvcRDa/9BiwicZpmFtWLFAwbOUwfUtxyumYn6ZAAIJ0sAGki2wtTqqNwSJSbd2ma3neJhqBIlHjQktzdYTGsqHmq7p275TAxNz7V/pZHHTY3VkrE0K5MOizA0KGxFcmILm+nIBvPfSMZNJoBq5Ri1P5Q2OrOUO2S+kdz2XZ/nnq+UDSN/3o4WMoJod9CvubZmxwjIh84KOFkWk5ufrUq9iABJsAJkGMgQrHLkZUjwXQcKthEdsWGXI8s9VdZuaAETuGVZKqoCVY9prN/bSgbJEFo29c25zX/2bbmnnlCJ7xHv1pgy/UxBTUUzLjk3//pwBP+kAAiR+yNUOwwRVEHGGqo9AluIyMlS56RHOQQYaiTxihcAIKV2wH2FootzQywEBzEA5cHaqOpfGWbzlAFUvdKwLKprR/r8gpf/eKDagrYlT2zx0o2u+deZItUsotbrmL1AAIGSQ7IBINEoEFETh/ByqhlIczmeNCwqbfB3dl0PqlYDmkxlqG289TUf/7ueXp9brpIlnxIfLI7WCTwuSdyKIAYUEuSQD1LoKpUkvIaKoLNBEBTspB9FO8NqDpr6wFpziVcIOj+3ugMb/mI5ToJp3vv61SxEUoysVcELVwNaoVx32/aJ5qFUqRA/KCaFOVT8sj+A9nseqcYYz/bW8MxjmXMOTGQa7w4g4YZZkb7ht2UUXRW+aSRQ1Pq93dHNYpYsBARDvfrlEr+JiCmopmXHJuAAAP/6cgRSzAAMghYwVVHpEbY/4SqqPEZQiJh1Tmwwp5ENEupc9BVaAAAYJTf8Dvg+DibQH87TkG0jIgXdzo5mFc1Rz799XQ6gnT0p1c4nT+ZbOOVv2TRX3fEKTV4P36blbt+hsy54zzu6YAAAIFS/8DAsJUTYUylNKNcjmBx7jQGHAXFi5B4oXo3aEuFRA9GgHq3ZcIpMnXgyIgZMH3yDX3vGDFVlwGkk+KgqXbAfICqyHIPWFW8UJUlw3La1AlkNm5oXP2dMOpFFl2Vyi7rT9HQzxgONHX8GipN188szS9rSBkR1EkrKrQq5bi0ZseMJrbbDhlGEgHFtZRqL6KVscluFB0dRHHJCeltWM0lOtaUt/8w0GnIPlkOFCuKwDywMEQtAy0CiAXRmFGwniLN5vF9CYgpqKZlxybgA//pwBB5iAAiCGSXS0wcb1j6Eqqc1hQjIqJtVp5hHuQMS6ujyoVYAAAgDbsAMoWMoKAw4IpInKrx7BTl9dQn441GksGyL0GpSTORHVcu3/v6RqOZar2HHsxetbPR9fiFugSoTJbKLT/8KgBBc//Ag+Jg2VoaQuwpAzQ1FKQg0SI2VPSbVi906Wl1HM//FlBHUQIWZ5QY/yf1yA+b0O7cpfIsrRr86v47oAEBUtkA7A+IjIiypDtoWkKKngSO7zX/6wdeIFAn4Qceyv+90QrHO9PoYzFsIgrOfKsH50uImBnltHu2Zn+Gvb5L7nvvgAZTlsgFh/qdAwJdoKjaqpEHczwnP9pHp5WDr65VojRX+fbFeK5b1x/6bLaiNBV7FiOceaQoLIQ+cw2ndzKHKqLpiCmopmXHJuAAAAP/6cgR/lgAAkhUi1dCvEExDREqHPWVDyMg1SOwwylEIkypo84lvAEAcJu2QCFlGasYn5ol8hyrFQTwRwbQURUQczYKm52Mc7r8qCXKdbf84UXEAseaeNOfi8lY02JGMvS4+KSrrzrUqWAEFSWQCCEcChoF6xsagal8SJIP7BHDouM2u+kJZhyyvsnatyGOJJ/iuhRXdv094Y/9a0T08Mqekwa/sb3e6dV23CYYAQQ5baM3eKn4dfkUu7Qvl/Yw1HjQ3xCKI8eU4GsxYskuAUpQKmtOTEHqJ7NS6ios5llZ19YiJOrOqVc9olLZh41SkGaL1iGSnZBIwerOtajKl/CPFrh9DTGiA4Wp0u88Lsw+NmR7ebZEPL/wrkoqIEt3niwLp66Xx1Pnfwgo7sVd+Fui80n5CkxBTUUAA//pwBCTPAAiCFSNT0eMTpEJDioo9JRmImHdQ5+EEcQ8KqN2HpFoAAAgVNtqMIaBtK+OZAaoQ9ean7+Vaz3c7OsfxUJerfvbdPU1tRbrf/CnFQyTAp+xS3PCY8YepQnTULkYrrVaHWgVYAABAlSNsShJgoJDxIMIhONlCeC5qcemLEB87mtRy6grMyPb2toP+gRxYWmnnjMYEYpYhpJ1O03nkNz652tj+9D/aUtSRwDn2yjbXgSEbHnT1oLkDW5sQatrv6a/+UhwcOJIqRO9fzUrOwsTB4EGXvNLFelceq5wBfa2/axgcEh8OiqDRFbCoQkbbQJg1JTlKRqcPpUHYwOAqk8MiTJmik+H1SJfpVsc2t+wsypdrOfUXJhn5VBcGQ0cKnK6yGcrSBaCFjl22O2PWPWmIKaigAP/6cgTOAwAIghgcVNHjKexEZKqKPGVpiCyRV0ecy/EKkipo9IinAABcFOSRjowgBrKk6ick4C0U6iJcJYVS5PFUtLiQImb73pUgqjyhZZ8A+fsboLCip4y4PB60TLQtAs4BCIRMHIb/6wAASJMljYlAtEAFUxOTRLI1woemjFQWOiMMp2zhAjYmIHE1pv0bSolF3N+7odnGIoSpWPbrUbB1AqTaHFAyCST7d3/9AJtPWyAdnHtZzKNoGbErElluc7LblXMOdCwpGTyYMsn9UuiHiFKvLmd3f/+sSuaofOPeZSw4Uta56GwvIHlmS0goAgU7ZANA8A+DyVKZZaL2OYkzdujQEh0uV7Ulwg5M1OwJ953Iz/5gQEM8yUn7r/KjpRdd/sZHZFvFPvpf8utiGf78qYgpqKZlxybg//pwBFhOAAiCCBxUUeY5rEJjieNp6CyIZHFPR5RrcRWUqejxFT8AABgSpJGMqwU5AOAYppDjFUNo5F7CvU5dzTX9ndAz1f83Spb6QuVDRt/VpRFGXhiTyDz4wYKBRwtNKQtPpRzLbQQXIAH+OqVEMxlgsHR5IWBbLCTwDyXYjDfiqyfzhIO/AWUbUSop7GwLo4CSCWFer/4jqtR5P0itPRW9qHYoljUtvUAQSUjYGWsZQbi+WwdYNJVsz/AwXoLlaIR+jDn8JWjIKUL0/5M0NRjvoJOUJQ8o0tqiq5UwatHQ0Zep5w68ogstT96BCKTlkAbQBQIMWjZAV6qPZiA1BD0UjOMcUvvyhiGARhaODb3TZ5g1//ciUP9sU6F7jp8zvFJftWddBlCoAYvAdW83bxv0mIKaigAAAP/6cgTslQAIgfccVNHmKmxCRgqaPOJNyHBzTUegSXEYE6ldhJUaAABcluVwDLc+G0qhBGsdCR479f6ynhJGn6Oo77+A6tPc1Fb1upD0BXfGl0KC1sqKLGZoVTq+stW8WNKJmGOWAAAaKdsgEgf74iHFsqeD+MH0Luk549IdWI7IEpCdTL+g29Trf/UxDuRFJBde9k3dQa+bIpIp3fojhvzn/yhC5B/0AOAnJGxs/QhYNU8BZhMAjKEKEiZblrtQzmTj4etMKkpl/3vUK6jncjjgG5xk8YXW2KocoDwqSNEXoVtzqa6rrdIxPLBBc22ooRGZRdQlzo29DWWkxkNLdrJdV2DagLrm8em5fXsMKV0YjjS9vuiVZyMPS8AsicUStqBpd4UWsaGkvT32MsDBX1dKYgpqKZlxybgA//pwBNaBAAGCFhzUUekaTEOFmmc8wlWIJJVVR5hpcRAOKc0HjCMAAKylJZAO+BJpVjGGeAW5hRxb273lwmOGo1I8JNCqIxP4jJdv5ze9gQS15uDOmXSwHp8+VQXf2pJBKHWMWYGVvaq0CIBjrYEgApB6l5ePYwZY7G9GQy0FvgicQOF2d3bCRJkZzafo9VUOJK5kL653qrH/QqEmQQ8+ETx9KjTr21wj0TKtY4AFXynb3opq3OKaf64T740xlS2RmimnHD1l7UWKYIppDpf4yy7oQSb/24uVDGxpkT+1yTQMhxAqRLLqJPx2qtT9ITe/4CYE4HGzq1cJktyCVyNeGMUwPIVD6l/4TfBwGalPymrQgo////wdBx++k7ydjJUvZ0xhVhkmZqYA+zX7Q6adt1uJiCmooAAAAP/6cgRN8gAIghU0UznjEuxAw4qKPGZsiNUPRuwkqpD/Dmpo8wleAGEVJGBhmFlCzPE4RrhMiyqhNvkFtDhE5PDEXLLMP0MtGWCwZa3q2Ocn/IqA5s7a/6LvdrWooISAUyLDAsfOf0hY0ABBQbm/4GgSpITbc3biFgRlgZ7RHGNmIyC5xgFSM+6/GFUEQ1/stItBxD4WSNWeYhMewaSdRQK7xWYr22GbBqXBBLu2A1DrACi8PDHFBkw0bHJh56+Lp2L9zKdg+7M97kuMdmO7q36PUYZf+6jTmmZjr6OxFZisSylT8jmR01vtvsSvqSNmaoaCUtkA4XbYa8RTpA5TQen3DMvH2qwzX3Ryd1vOkrMcb6G2mAgwL+Cw9pvKJWSYGDYqk1fDcTHRddjK61scxD0xBTUUzLjk3AAA//pwBBImAAiCFCTSOwIz7kLkelpgYlyISKtCbKSq2QgOKR2DCV4BIBcsAGpOOIKBRgRwVoSuS2dd7Icp8qklpr6HIoBZyLtcUrK4vvb6O1A4x6f+wbVrFI7E/GsUgdvpraxKdKP6nqBgAACCcu2AlJkAOAZtZlMDE00qmtw9MBjtQHM7PRqSlL5xOKDGnnBC7LcwJjTf46jb2WjgVjgeyy0nXITscPYzYh9dQBd2AHv4QWK+nSz5FCogIw2VO6yJCYI0wgzFqCQM5aiO3cBTvHs8v966Bu/+pAmzsWeazkYRyK8vgYlbd/Z6AWoopUAFxsCaBKSFUOT7CFppFDIZtVnVLp1CHW2BmaS+aEQ6M+3966i3/bOtfKBWdFksaBGAJCFteKiIAlS4xwpknqJPWmIKaimZccm4AP/6cASXkQAIghYj0rsPKTZD44qKPMVTiHynTueY6NkHDioo8SV/ACC3tsBuRFVzaXSpNlXxZWiOi6zREBUs5gPlu3hSRBxLf5aVsYG/+c4DMB02znk1/cHM9va1vYagfjzAg7/tp136wAAZclqSRiUNoojagIpWh4SrIbT2sd9H1dC48x9CzkezUd/a7mZhwaj7hHF+dFqs7g6UCqWhY6ostqXFRxVgo1osi7ytA5N/wMsgUIPEEM0p2IukWlEpHtrbkWS/92lBYF2JGv50m8sapJ2/7ur/alpca+mip6cbJrkKnNdNuaZWdZSJhhWTrrFMFS2QCQGyxlbRTn4SUolNBhJS4DtH5mUiI3BCHzf32gglItr/jI5QtIOYyPhGedr+RkC6mekWun+pkvq1+6Nb/FMQU1FAAAD/+nIEAoIACIIDE9LTBjrcQAOKmjxiU4iwcVNHmEixHI4qqPCVYwAATBKkbA7K4GKGvMIgKSg5kUH3oCzq67Ss6Q329jzjZc6KDlSR7hjBge8EmiaBk3Ota8il2+YkiuWYeIN1tXJAAKMS3JJBwrijSsNIqYWs52JH3QfhgWiivtnYHM43v9WRnoP+UcnvwBQL5QwMQEBcmF2GmRRgovUjQgDaE0LyVLkq2yQeAQMhrYFM8VaLjWLImEp03DouRakYyl3G3R/01oEMH3axhkREjhCXQfDcmGYHQaLpHBlVYESRpn5J5nmuA3VIPgGJN//xgSpU5jvE+Q5hgpb3KHM12Q0a01BSIdHRtb540HBfvfXIWguvfSXMpe065JD79ZPSBpf7/6h+R3dKWbv37Sdv9d7cTEFNRQAAAP/6cAQk7gAIkhEc1WnmEexAg4qaPGdPiLxzUUeYSXEDEanphIjfAAARSgKtskHhinrL1XIGQFRrEkTW7a5u6/PMXWzpxvf9suJnxd46KtGNXekgDwZiponpxcWE5CtXGgQTss73VRb1AAAOE5bIBYJszUvo9j1IQkGsMudh/pjcuTHEMslHlZ//eZQ0NAC/KrMoAKCqWA0eHFRdGNRICI8ocwbEqEC/YKI2S5LIx5AdrmtBtngfSIqgKKtvv3iO2WBVuRtw7QYlu/0CqhbB3ML6EuG1qQJoqdJhsCrS4/WQlTZoagecIiRZAgpxXZ6lWCTtUuhON9RUbkD0V1xyldpbduORamRuCmwQoPE/+XQV/9gw2CQGA/HAOiZfIRZNXQgMM+AZiJjKex38PcX5vBMQU1FMy45NwAD/+nIESIkACAIPHVVR4xJMQgOZ+mUiWojgTTpsvMjBFo5qdPSIzgAIrKdtkg8EqUu6Ha5I99GVxI/TsQUNbhVd3pLkd62/FS6AnFtD2bKAdA9M9Jj2tePS3byQrCq2n6axz1p+LKj2XgAAEAnJIA8RtzkhREUuMqmkCxppoIXlX645UxaXUfwzJrMPFlNrNdeVJgm33pvIKkT2VFAk+xyV+QsVuo1bMb0r1AGf/8ZorCJUfiQRhAgG/AYQjDZ0P8trGyZSKEIRTkZmgtMU+zPKir2ltXySiAlKHPLgIYTfFT6GEUEO76GMQQpMO9vRoIOWAACCFCnLZIJRdDY3h6zgehrssRuHsaZJ3IZGWuzB1Mv5CU46s8wLnzrZtJQOJWJkDRa04bIqINHSlqbkqNoY2rtDA+7UhMQU0P/6cATyjgAIghQc0FMmE6RB44oHZSJGh9SbU0eMSXEMjiq08RU+AAAIAuSSDSvU5CLNFYqyNPDpGWy1k0EfB3MHyepaQSlLbOHU1AmLqOn/vlYoxw5fnGhKu5i9jVClTOv7WCtSKv+2oAIAckkEFGFCOkKwK9IBiEsKENXdYOFlB10eKJ2R22REMya5hk2//UWDLE6A+w269Ua/GoFBlaGoE6lebt78nfrxoLkt2yQdyKhLJQuyGHSwVQ0LlczBZz3l4jI++yf2sVlb/9SG2xw6IQawCgwlG1Wl6FpoXHo8RPgZC/WNQA1JJSgLlskGRcrOnbE6ERewIMEd8cUcQcXRrnP01Gf/oy6jQ1noHHRcxJIippNI1SBMRWi0BjtKYofdoFo58csTiE/45aYgpqKZlxybgAAAAAD/+nIEBWwAAIHnHM+7LxG0QUR6mjzCOIksNVFHmEZxIQzn6Zeg2gAgJySQUKVhLYz5AWFSSYQTTLkhwTKdalXldEWw0sTFLe9iJO2yPf1R3uFnfuHGzDtCl8zRq2e86xje9dQAA1hy//8cQFrcWxFpBIxCymX/oLO0WiI7OzddRP/ZF7EFJ/6MDQL2pmxrFNULQylzil6LpeaWx90zNLNPJnafiwAINgu2yQdnGUmlURlMm8LOEoOPUezHiVjHTLBtFL6xMMcCgJP2lweAg+SUEWiFQqw4Q1nS5QVLCeNa8YwdYHjzEc49JtmxR9KACCTkkglxPcMkvagNLmpnE8xLoZTl7YTWjWkIwe5MghMN9uyWM4CUI1Hzd/xsO6gaPX4sdS6tQjxZd1pzoSlnFS1eRle81dxVMQU1FP/6cAQw8gAIkh8RVOnoEcxD44qNPSU5iERxTUegSbD4Eqoo8xTnAAACRhTlskHVimNpoVrkNo2A3c3hk4h6Wxe7mstgSisHdS9NfSWoCgy57AACCXlbUIpdZPkGCCo9jC7RfaLvKovucxwAAALMKctkAqIApXJCz4RaHTXehXf/YXWjpYV4m+oytiBqHrX5ztoOIublEiUs5osZdULOLmcQlyxlArMGBDWseyx2VBdFSRtiyLO8iELMAlQt8BtCKyaxo6G0kZ6Mq8EWAmh9uv/+iizpt+lSUDMybe8XUKCgpV64uSomA+8+n60YqLi7Vo2UpbCH0Z1IfzKQxE0gIL3/VS2UB+bujOkYYatf6X0HM3f45RakZj8uf3qbk1vO/VX7lwG2/qt8T++n6ZK2mIKaimZccm4AAAD/+nIEN3YACIIWHNRQ7xBMQKOKOWHlDYgwc0tHjErREo4o6YSU5gAAbBktkghQs0axGFDDe3KsZjbA7mjbqhq7av/utjneUQxH3k3JcxWaLoF1nzAwpDpBFb0tILCTCcUcE5kuW05GtaAAADB/qI6IDHYoh0mGWwOWlC0Q+Dry2TxrqLbOZqWRmOwz/29AxCuUmTKlRy+wzSlYqpzGHR889lSM8+9VqKtVILAub7YYL6IKlSlVxOQYkVqMWYy4QQY7LaWuk3H/9BvjO3yqwteeh08LGDh4uGFzYo4kkLEGmxcwRem6En3Rvk8cAQCjaTFAMFfa0vdhMNIlth4CRZd3vAdzE7FOQ0rY21l0+6avEwUGjSUtIknOqKu7J1jKWsb0vsO/p4lMlbgm484s0yHUxBTUUzLjk3AAAP/6cARo4wAAAfQZ0DsMEjRDA5pKPMJTiMyNTUwYSvEKjir0wxTuAiA5LbBdL5FVMLSvLzl/DoGMNEAeSliO9kZKf5jR1eiL4Ncf/qEFkAAiPhTt9FFh8aPodVlhySRbQT9z6v6QAECBVkbQlANmNlSSgOsl066R6mlUPxDQiCe5m9M413M3612IBgYRqFRMLGXKJ4YcUlENcJxjHohcnY9NA9spEE4uoASLynLZGPb2AYHiT0xoaXI7755kaV+Lr0iwEkx5aK16DpZH+hlTKN/9lBoCbyQseI2sJkBY24RvKDDIq6xo7Cz3IAL1/9AABFKbUltkgkDMOKS5ppFhywCbvxe9OE29lfuxqhYqVSBFfYpqrUdk8UIJGMmnC0xuS19DJgILS6KMqZtb5iLo2UDExBTUUzLjk3D/+nIErfEACIIIHE0TLyqkQkOJo2snHgicc1FFvEDxEBXp9PQdPgb/yPjb6wAlMDzVIGLKduzK1ZXwVyhcRmo9OFA3GW/MEk22GqHDHK73G/16oOd9SB62jmo5Ltczo3N/t07exm/sALotoh4JhEg9axzjgYozBDgDZSSBhAywFNn+LFGcz91W2XRagqzxzbT7MFRlVYv9lZUSPjAcp7Op///RT9nXI/3a4fSdtkgkNF5aR7FUHQ8qICRi4I8ZwCjGbrCMmTb+e2gtwgbo2ikNh9KBkNqaTaXUWuGBYsTMqHBb0ubOpADbXK1jFCjEsBRNWWQDItEV+uDDgI+raFGRFgc3jM/Wn7lEtKQHBOiWIJjf/KggOGNTZ3u9fenR5yDkyOXnBxxZmckHrpSMUBBtDhAmIKaigAAAAP/6cAT6YgAIAggT0LMJGcxBo4mjZMKECJhPSUwZCPEbkWmo8IlmACC/0Vi5bMo2zx6CoAqlGkS4nd6+CuWB6lvWy+EDI5hnM1saVf9s0c6lCjIrpeRCgUEZ2BQuOmzxz2WUeoUY9+sAPbbB0j7hYUwA8BTAbAy4GqXlEBsFOnc5EnodWd3PMDpauTdxvoFjqtIgeijf9pQv+2YnN9moMXV0/0IX23Ve30QuSpI2xdYRnxtZ22NedvTiU8P7gqE2o+fhrmpwmqRlFu90mCxrpQ08HmOcwYXNgwQLiSElvc12tK2NTQuB+5iO5RAYQSACC6KtsjGRJGxmHmdjOjI68rYRTJtUwHhQ2nEh2d1elv37sEV133yAnqeLA0RMiQsYDS3ZCPYLB5lyEIeWAaXkmmbWVVM60xBTUUD/+nIEqQ0ACIIVHE4bBxQgPcOKmi0iCYikcUNMGEkRGY5pHPMVVgHP/+KAQZT/ZMLTe4UecIKldWTMgnsKnLDCKK3M2RoumdH4XagwXj/nmSw5/6isOHFXEfJoQnYf7YzIN2762/uGH3AAI2k5bJBAvOKnAegZVgP6j0dSzROVfVhDaDVX/2oM70plAHmkBYRhfk2AA6yqKDZooA5sa+ncej0V8Uel4JAyW60VUEz4vPBEEv4NpUMv0tBW/kpvDA3+HaqrJ26v0IiEs8UD13AIol9zzwXSxCMCih0gQsA6ix9qyTEO0YpptV84gwKkjbEoVTEjBKqtKVUjWeV+PZkgLdkoctF/D6VYzdfdr6hlKrZ1ywCgapyQiYQok0NnyJVdhoyKxzrTV5OROJxxnOqi9NKYgpqKZlxybv/6cAR3twAAghocU1HpEdxBA5o3PSIpiMSPT0eMSLEHjqp0pIguAACsFy2RjA4YrtllSRCz7U16y721YOSAvbkjSVe26afr9RkdcKjia0nhYqrA4KgusylyhyT8sFEBNAuGVkMQGoQ/54AJJkiTFAHFtQgOcabl2hsSbM1OniNNBezN1OIM1UKzN/9RMWdsY5pww5sVzYCJE3u37V61p/0rSXLSJNoKGybaAARXKctkg5NpIztrYxjHvMgSHg2jXUNsze9pyLKtPtZstP+0cxQXOimtbMMm96GMaMKCiwuLmlE7VsDjH8BEBUXHoAVYnWiREnrZIIHl0IWKvbO4Lcu+GJaqv0Ik7uCZUlqjf0Zs4gSIB6DICx5eepSFFAyhBFsTG1qXOb4aZPas6qXcWUuAO1MQU1FAAAD/+nIE3LAACJH1Fk6bLBpEPmOKiimCB4j4kU9HhE8Y/g5qNMENXgi5JILIt4jJaVghhOcJUQGNBq3cb2Qx85n9qaz70L+WnrqrQWC64mPfljRxJNq+y+/qWtysYLSwolNW9zV/WAAgwUtskEIEvBCcK2mGBMGR0cNopNE/6IZKfonuEB+m8qtR9KjofgukjIInlJDz1MzCJx6dVhtZEfouPpspWsSb//jknXUz9MLg5TOjz5ljejrsCsjQk/LJmwkQvmm1EHdLL1k4+KaUpVL4aouwa3ct7FfVtWm/728zfO3V23u2Dg6/20+ggiJyXArQ1QfkLlCZpXKjNh7C2G8lBQ4cK58hf/vnbBnf4dCohoTJTr3LUspecQg8GqxVtSj19KqbmCxFnaLmkxBTUUzLjk3AAAAAAAAAAP/6cATa+wAAoggT09HhGtxDI4o6PWUyiMRNOGwwqMD2jinowwjeABRcKSyNjJOJHUBJPCPQ+fcI1JG04ikSfjyEI/hEY02dc/nD4wMoMjgIXQtYtOImjo8IHCT2r61UmHUrcvUpeioAAAgnbtqIIXjicZGlWZBYQzSCVx24ELDqCu6zKq10cqqf+SbQFC7ELjhZeuudU9km4gXRPHlIcIQAKD3ZVtTlLLtLAS//8R4y9kSQLSUZzEMkIIMqcAY7lPl4/vReQXypXtuOY4SDGX0lmMLAX7Sws121x5bXLvr4RnThkg0VSzSESmNZtY29GhSrJBg0lx4DIn0F4KRrWfusKeCQdtP10c23/ZqjB7qUpUqoDHnGygaCjHKQ3MH06iDr1MSfAaKqzCkJz4GWmIKaimZccm4AAAD/+nIEIWgAAIIPE04bL0IgQ0OKajDCRYhcTVWkhMixAhJpqMOVVgFf/+IiVYk7XMfYQ3xQfNAAycJWMuH+tldAVgGNEwn3/ZyZQmcL8ppBb1iEsESA5ucxddErbHd9tNO5KbF+kjQ/GAAIOUrI3BIJCYsCM5JYfEBDDZS++icPHTvsjkzDM5Tf39RCTLSThVlStf0v8uXMaEKsOUPakvLpNA4QHg4cmwGYMOQAACS1W5rZIKAVXIiETIweeN3N9wKQz+2zvUaCzQENJCi8IlBxdI0ydQQQUSN9XRsh43FVsvGOGCpJrb19d95wtqHPCtJyxtiQpEwfSAkOwMK3kWXrKGuGXSVll5hPGsSc30R7pQFunX3u49j484RRi7V4uneae/RpWLto2972UJTXGKTEFNRTMuOTcAAAAP/6cATrlAAIggcc02nlGlxBA4nmYSJHiKgvU6ewZHEGjmp0wIk2AAAIBibsjbGRcm/cYWRNl6LezA8RqrLjfIsYaCHPMEVWZ0/7M7wekAxQoY5uipTb3Na3DSG01L3WktSuoCcl5hYAwalTMSkw4eYGJQ+TIDSigYcVIyprpuJ5UIoKWM1u5FKzDqqP62WaokPu1lMiVuQL9wvLPRNnEOqK79HsTq9/NotVOW2SDl5rfBVIlApdbUQmMimIFHD48XIkGB9JHhNsg59EsUUYsCCjLSDJF6HuP4pC6zTnNSLGC94o4+RaxL8MJeTKS5IVTltkgkiF9Eb3SB+xznmkpx8jQjB242jr3RbVKMdafPGEhwygo4HBG/VL2hgqLMwCbQB6aUILlBGJxZw4X22vpTEFNRTMuOTcAAD/+nAE7N8AAMILHFLRrxC8QyJ6KmGCM4iotUtHoEhxC4nnTZMNGgAALKlkbYggnUspcpFCShQsnRqTPTwiyVRitUV3f2RHd5gEF7hQWY1jK6nDhqkXtBtSfTxRaCAsxqUJZe59vWtFQAABAqNpIZKbkI4jADosLFrAeQYmFGqM+Q4rq1KTUK489qeiKhFLlmnguxiFJvFmNvQoUi4pQp6h3vRrcjvUxLX6MUEARYN2VtioZEXajBDuKFDuWgrs63B6sL1Vvvq7sV3I2lt6mMDor5FXPZvO6KY9rlEpBo6eGq5NClvROUVo/e48MG5x1KAU5JIJksoSVotBgsClUk4iiQGDEZkMWaoAXCRafUJjI81JRctxR4qh1/eaWCebSKj6ktTdX76pMNlOtS44keeTTt9aYgpqKAAA//pyBJ/aAAmCHxzS0eMq/EODmn08ZVuHsFNLR4yqsQeOKaj0iNoAAag5ZG2LBz7jyCKmO4F/UT/OcgwhVoUEXKX/37Jjp+pxnJSlDJ9MTOCIVSyaqUsnW5j1XHLmcU17AwlavWhzn2vF1AAAMFQp6WNjCTO0103CXARLhp3nEp5sVo3nVXtMHejy6f6dAOzmMLr3udUNFbxKggHELjzZQFBIdYLta2j2567r6EVROG3MiSVsyieFqxlDMluDNYUMSuC9Wf01ljQ4105u+kXZDTmoJEmtpxZL2hrtvU0kgUChR556qR+w4zcyKdMHb/9hk/kQRacuewaZEualkNSwQkqg2yf9B3didaoxjugQf6RVThK0+H9gkcYBVR8sKijz8KoFhbrJbumta/GLuTEFNRTMuOTcAAAAAAD/+nAEA8sAAIIDHdVp4ipcQ8OaWmBiVYhUTUEsHGqxDoqnHaYNUAgAWmo3dbJBhJy5ciq1CeQQWIgjzKFML++jnRFdKa7UBy7kVBqb3rFXPexEEiyUAFay58LoR/+5zGS+95qdcr1gAYuErI2x7uodG2d3F0xpUbryDjnJgjNIXe57JpM14J/o/oKImMFkLASQBeh/Nkl6r3JNQk8PMIt0UrjB55T9Vo849QAADDVVFCDUVKFaiEoeYRETao1PVUNw3uUhH8yOcNYUHaLcStcR/0PZ77xSiFWNJOaDGxKHUDbCahUmPI0UCqbZ5LQhT//8UIKLEMpQAmLJkDBE2hZxXcJiEHe5MC0C9MPlgtqyHJ5AuUQnhlZGbNIY3j6SaLepQ9N5/Ta9qlqvX/Z+pG5FqYgpqKZlxybg//pyBMwCAAgCERxMm0wSsD2DKik3BwmIXGVLp5hIsR8I5l2mCVgBW22h4DfL2QImAwWYvmClgXIoBy7y8Xi/IBrD5VX34oqv0fVwSoihCdP1M0+JBNvZOcVmUF1Tj7pNhPWlO93//vcACo0/9xCEHTFAHclS0A1soeiI2zGzwkNlabJ7MENXvr9DiYsgCm/756jYc9vQtWt4uiBiQgDQQGgWN1d/UiVCXJG2NiBQqoIDaXsRJJ4H1PcsZmFojq2h0ku43/xDhUE7PFT14u9JJS1HHl2DzRMImkPGilXRFYE69j3GWNSkVpACAdttg7RmQIkXJ0KqpbsgVHtXtXYwGO2pOINdoAEb8JC9Ran7JJDKBADbz1QnfJuFp9q9Qvet19LVsKTdykXT4UrcNarphNMQU1FMy45NwAD/+nAElRgAAAIHHFTpaROcQGJqnTyjRYigcT1MsEiRFonpaPGlbgQAEXMlJbJBhFklgeBOHimuma9b2A1WVZMKkQ6OPqN7/rQlB/wqgIskHiNEypzM/ATzxprUrnkGV3+7SLkMklE+AAAQ1W5rZIOyFWsztanEajww3fqmK0v2EdpLmgx5HIiihUHDiwZJjCkSsXWSFHjm0zAxlFS24pcazBAx13+9xAABAgnJJIKYHdz0acEk+TeDPWAWRYoaixh1tLsOsYirbKuJW7N2YgFYRMPoNqy4cIOULpvKqPn6GMoS0Wfv2OGdXXT0ZIAFm03ZHGMIsEi/eTFGBKRVypHFx9CALliSc59vUmHHWQIfbVqAYWaMxhkEiqbr0UIrXGKVYvKgYgAR8ebY9OfvvdxhCpiYgpqKAAAA//pyBLZSAAiCCATUaYx4HD2CejphgjSIXHFLp4ynsREOJ6WTIVYEABEmGTWyQaBxy5aAscBJ7CEOWOWqOfsUOMB8PT4TRQ0kVMqhFqj4uQS2kk97zTVqUVkpJyW08Vcdtm7Ebza16wAITEet2o28SOqtdlsjCA9JYWhBdn/S5qK+wQzGJ9RakjL5R1ZlZEHwQF+i3R/AaWMDjAi6y54yXTjLT6q0CIU7I2xgb8KCeALsekGkLZ1HH/h6QvIDdSPCaukbdX/S1VExGYIoNpSdc2q2c7hLA8NPqEA9U0KhDPJctcWxiG7dQBD9KmCXqYhRE4zDhgw4yX6gBM2mkZjWRV+W3Dvbrxk9Ght56/rkJDz7eWPDrw++9ai5baOUzs/bTtUrYqiq9ypvJ2dSYgpqKZlxybgAAAAAAAD/+nAEvkMACYIWINLRuBAsQ2OZ6WUCWYeclUtHhOqxDA4pKQeIXgAITRekbYWGDcw8ZAV2xYADFBBbPc7s8fcHTVBhZGgv+muDAh6OrCTiAbJ0New7VkNqFSrs3TlQFxcOsTpKLUy1rKwAACC6VMUNhhweCe1MtAifIDnsigGkwptYkfmQpMnFre63sGH6/ghTpqLU8A0TI2m7uTfLK9Yyq2NhOVqTZqT9TXLKA2U7cEhw9Qo+g5hDYlcR0uFIzFSzFtrd1ufr/PTqHSk3mdztHHQSWAno0VRRtVFSEpa8wxQYaKtJp3M/FBDCckbYYbwRiYbT1I2BKStyXqjbr0E7M7Km2jv6+jo/FDarWgqqg+ZA7G0pdLz0WGpOGlFAsEUYELz5LOrr0oawai5MQU1FMy45NwAAAAAA//pyBHt6AACCHhPT6eMx7ESBqbpnSRYIiHU4dZKAAQmM52awgAYEABhmNx2yQZLleZYCgIUDXFOSwTfkJSG/vbC5n0IDxZ7lu+F0OW+80Qbi4CEayIuAI+FgpBwsNucuafNBKJLRtDm4EAAAMI///jIWTC9w9Ys5TAVCHWEsVf0WFQ+MI6g0p2dDxPuIQs9wdhY4royKmplueyLq/Ww3RTchD0Jdc5Tcav3MoAt6gX//+F0G4Kre7CRZn3GMaS0LUdJzWAUE/n+5eLD2GAOc66a1xg//+2ixR6d0hK1WNOs1oXe8XKKcyvPsJUsaNW9iO9awCC6VJlXCkhtCpBxA5Q8pcpjcev0EL7ruSSowN9nPrSes11N13/oMLw+4y8YM3vWKuu0zG+wVEdXInkW0IQiriyvUmIKaigD/+nAEXuUAAAImJ1S2PkAAQ+TqUMxMAAhw7WlchQARB51sj5agAgACAQwwwAEvIeJmocW0EDBRzYHgivmuRACX55Y0xo+ecGx8G3APg9A0ThkcXCQw79vL50tkmY//kmRhMmxWO/xxRP/1IZ+0CSs0hlAkjdkHFiaURb7XcehkEF6jRYe+IN7lo+AcsAhAHxHmhEE4AIw20UgR/0Fvk2WSuPZR//K5QLpsbL/jv/9AAQAAJOXcaWx5LOB5BQsGJeOT7C91UVSDDwFA4scJzTzNEP1IXyDPNFjU58jXUk1M5nm9v/06f5GflSryDu6co+T2dYBLkvHEqF7Wmgri3BQTKfbTz5DUqD4nmlAwA6OFjRZJ2VXRCj6mvpqR+nP2I2Pnmcznt1//Tp/kfKut6JT8hfV7aExBTUUA//pyBBrtAAACFz3aUakWDELHu0owwqSIxQdg40RH0QIiLKi2ncogMhAICi4Ka1nkUy8HRNRwXDaxwleROXTWsZhnU8OUlnG3IVeDh5VCJgjG4ntwfVeD6Pyc3+/L/+z6k47cpv+hYi/TgCKALLt3GLd9B2Yj3nsC40m2Lf3jCZ0cSjul4sz3Jb2M/YVv5pKqoKfHK3Py8rcXzcravy+PqJ9u+pH3bUV5CR/rSiAAlSbjmc6wKxgZHLxrFOQ1FfWOW2RhLKY2CvPssmW0G1TUC69E4E2z6gHJ76F69Opud9W/vwYfgLfoLcVf0xeKVuUyBKEAhABJLv470zRjrDK7YPQW9Q/yX1BQAkqipnoBXck2U6kObxxtSXO6N/9P/1fKj3ObTxo2BvT35z2Qf91cYyd6UxBTUUAAAAD/+nAED3cAAAIkPdjR6zrkQserKjUqkIh5CWOjPOeRFSIsaGac8hAhARIVm48sm7QqPSassaouW9UfvyZfQhDCICsFjGLD6vMprfLfDPR9CHN/oLf6voS/+pXlX5v8q2pTjduXqq7W0J75JAIQQSHbuLKSIJybiqyCIxxa6jbjw1BRCSFFgY3A++VbI30FHO5T2/jIUc3n8i//MOyo/5rfoMeY+heit89Zy8Cu+sIAQEEABKXgc4qcvBwZzueI3Tfyoz/s2s6cjagYYRESzws2V8vxnu+CgV42fFbaH9/f//zOOF9X68wtlRvxJ/qOYecQgBEAABO/jplUF7LBJE5iGMg6n4y+S46KSMBEZUAjbyr6E+nE3+/PLczt//6NsNvbVdDnwjL5x3bsmpPRMJe8mPbQ42BqkxBA//pyBOlYAAACAT3ZUG0R9EPnqxoxolyI0QlfR6hUkRqerKi1CXMgKQAAFbuNYIoOmCjQNZOKOcHjzHizF5U4TeM/XqPxPV9B+nX05f6m/+gPhx9W/mGwYbh3ulN3Ws4KgdyTKY4LYBgAAA7NxqyDV0MugHaU3D6n0+MjWJqa4sBWuoad/Kz/Nw/BdG5eFXQT36+/9BtD9f8VyvoL4GcvFBQUaYUWNFNaQ6kgFEACFJsO5X1iDdoCOPY1WquPZb1vvt/IUM8caalc+Bh7eLymgrJjwU83B/683tqN/9G4R/6dW1PqCFt1oFyB7KtuJa+iqAIBAAXb+NsNLG3IRa54VRTqX4n5wsNgiCl4iunF76n4z5n0F83IPo/Tg20/36AH9OpeLHqgEYHXtts73/X70JdXVfNs3dkmIID/+nAEID0AAAIaOVhQb2m0Q6ebLS1Cesh072dGpPIRC56sqDeoyhAkAABNm4xqWEajqZq7XDl/Kzcw1gRpumxMIzY72uvojZz/Kn5nzD27//v/9Rb0n7/zDE1D2pn7V9gwTjnCzKwukAJQBECAAACs3G7Y1C3AJHpiiPuIpI4mcnLJB4W9SXvyvUWORcG/N/R/69ff+Uft/+TlegQ1+8FT9fzvOOf3S2WO82sV9EBKAQDNdxTOrcym4bJ5lDQf0SBy/xNR+8WDb4iPq+hHjXp1D/9tW4/1bQtX0XrtHP/zuo3w7mxNvGLyZoZQsyDqLkEYAgAAKcu4yuOxOSGasISBtxzjfg+fhWCPQk6+2LgWea2DI7qbyJtH79un/6Py3R/0P5xexQ6tYsenPdBNKSVQuVWxCYgpqKAA//pyBOHbAAACGCNVGTlpcENHezoFpzTIhQ9pRChLWQciLKg2nOogB+cDhhOYIbGXIEUD/2uJ+YZ/MO73+tQtcyf1NmbvM/DjiGyja7sW5wpPUB7N3ysmdPnW1n5R6s/8WcWq9MtAG5nohDEAAK67izMA0QfHLWKnygt5biKG1jwJcb9OUbhrvwqX5nK9zNSn8o3/shmr//n8qX8d//Nzv8/9cjI86ri94FhaOkQNQGAZZ+N9lnUAG0sGRbQb8Vmyg7lQpBq6j99H0EcB6dRPbr1N06N//5f6P/R+eSKGoRzuoXOEGYOMz1ydm7nn6u4zmAcoEFPTYUrkD1DbUyhjFDOEO8p6g6C5bi5ZUDlt4g5UWcU8dO0I9upbt0+qKjW8qMMv0/06PoenVOiuW0bIqjdMpiCmooAAAAD/+nAEHfEAAAISO1YZbzl0PuPq1w3qPIjQ9WTmpFgRHh6tdJOV2gAE3IJMEFwmrZHgIJw449kB/d9r5DFv/GTf52AWSCoCxMVcDAKtOBc+Km78l0bm9/8//6J06f578la7J55Sr9BVWyEgBBbtG9akKIG4w4zDr/dBV+a/MACaPCBbL5qAEWvbBEN8hLNiM+Ubl/Jddf4lp/w/AmwpVQOpepoo5q62zIKCIZpsKKlmFM4EmPtIhG1nuLDk8tycMtJo5/5wp7LlhbcEQc+oI5fb+A++ptLL8ED/2/lfnsgU2baqlaHZ9AuhMaLhp7C7RQcRBICn348qa1KWj0nWAUGt51bkOI4MRCh/BL+MfQd/Cm/m6l7fyj9CETZFYNYiNxn+GOsUH8duPhw4GsUGMDZ/GHR94pemIKaA//pwBKVZAAACIz1bUQo7fEPnexotpVjITQ9m4SDg2QgZLSgWHI4QNgQE1JINoQ31A+DYKBj14/bF4nrUWuNP6idwqv2w8BBbd8XltPO9///JcuWqi1Y5sk7qwTJkwo1bA+aIHUJh7nbLYpAEgAALl2HUXpUuBCdWgfC3WWcp6w6o5wh6gnG8KH6Af+FNr43o+j9v//R9E79OiceP1n6FxjeaosrOtud9FetKXc761EEBS38RoQL6OAor3DuZxY+KQatSzYa6dU5T+PBvlOrZQnzOj9P/z+O9U/if10IF6MymZ6kHgfG2g0e79HwN6PLa3gGIhJJqkFlR1oKvJxN0FvFnEkvw96Fdxo+PJlQFdOPNyHTlH/pziC3R9UdB4kbkerPzKQWlVanmhCOnFldyqY6fcmIKaigAAP/6cgQNrgAEghQ7WFFtE9RER3s6DWc2yBD1aUQk5JEGnazoM5TiABIAAB23DM9Ew9wDRdckGHPUNeOZskA1nazPlHnG1o8r/zdf6CuH/y+vNqEXVNfZFiSaj7EIjLvLpHqg6FmnkgM4ugJgABHd+NAQAoOKC8PgVFnmBP4b4qfKh/fndW5HryZ7xMF+RfKP/+3/1bXStr+dRC5L/zacOYtavm710FTZt0mlbPdsCMBKb/jSUCvmArhiIhGOG+O8DA9amc721fjj5j9ento3M69P/bN5FWNZedZC4cymlLoUWsDFsTPI2LdYeMZEkpTAWZduO0h4w4DDSULAhoLuHOhQDfCxbU3XjQyoQDnAj6v36d36d+rf/VsTK9Xf0jTI8VF3MruzXuS1OkXPESQZKpiCmopmXHJuAAAA//pwBNofAAACETBZUW0T3ELHaxok4m6ItMFSZ8ipwRUerGizlcsBMQiSCy4N6sD/ewUJONFa3qpc49QqCdIn1i11l1sinsrHpslyp+P/toL/r7f/iPfyWq78ghUHBM5gNMOECi3ixM5ACJACT12Hq7pK2gnJ2Li3qS4N4SPiEzi3+VGNBH424hGdT+V4N/5ejlruqskQI1H5H/UTzDqzKigopKzdcYM2cuXWAyvvxz8TJ3hfN+7ClqJawjJV0BNHzA0qBOhkDA2UU1VGr5GtoCoskDlwGY0LCXD/VuDd/5h6adOgmQQ+y6GKVK+jmPT+qAIgACpb+Ns5ltOB5oyaLy31W8M6AY2FjuD/1Hagbs2Fj9U/hEfycz4x//jG5//ycRfcfRCmqcZDj9xLWahLpYl3KDZ+6TEFNP/6cgS4owAAAhc72dDnE3RDx3rnGaU8iGzvZ0McS5kFpOxchQluASJEhOffiquDGeIrPBV8TCvjfioOR5LjZv0Xcav+OgjyD5jak4X23N7Z1dUDWpshaqSk3QXnRZYnP9BiAo4URszGLggABVtw+ucTFwNDsk6waUdfidbD2GxSjqOoE7dRXhnPyvxX/ftydH/k7vsHnREMlNEPw8PezqvpU9gRCySBB0+ZLHhwGQnIBO/8eucA22DsriEvw1yxepwIo7C3gtX+/N09e/BNz9Orc//4/3QMLRp3TdIQEmw3nF0MQlvup9uibsp9H/g/eoUgEFqQdbiNLHgP7cMRvq3GuoZjVEKtoMeGbBnwQHxL6N36dG79+d//q+i83vz9XqGpcs1meput6PYc0LobPsXzCYgpqKZlxybg//pwBEV2AAACDjjUGw85UEHIKyodYpGIaPdlRBxLkRKg7CiVFTcAB/8DTkvA1sINLpoZ90icEiHvHX1Z68hTVEsiiDxx9QCnsJ2x8X5QAktiM2VM5bk2x9P5XqX7J7RX0Tp/jzyO76YAhCABUcguiixDyQkKcopBvLclwqJ3tVQbAuram6cF0LydW0E9OFfBk9teFTf29+G6EUzGe7ahjrXiZjZnNNqtMqAzFJAKbfjOGSCE0xmOcdD+GeNeJxflD9Q7+r8fr2fi+Xs2o/J0f10owVrIvM2jaqzuEfieLhlSBWB2tYqTSQFFjYumAEhQAE1IPCqQpRMBpotNBO5hPxAl8VQ6ps1sQO41uXifM3Tn6+/CfV9V//L79v530eqAK/KaYc9ZlG6Fy7uH+GLTB/dpiCmooAAAAP/6cgSJNAAAAiQ42NEnK6Y/p3saBYcWiLzzYUawshkXIiwoo457ASIVgF3fjuSUIfdGpZpQO/nFec+NQ9aF2cYAZhGvG9Sf0fU3fjG1J/t2+kn0uXutUBfFvi27PSUGNGPvlz2eafR/25/ZAgFAKe+4jKq+jIpidsOA3+IExMHrjPKdepfjT20DHM/25n9U7L+hCrCY+aqvXRCAyeg8O5Oqmnfrw8tZEqsMgBhGQi7fxKamEi9hwsmTg+FLn7zDUNARbdpB5u3G9gFbGvjH1bk4xuX+o7/4z/P1fQ3JsNARuNMafGref78dNvDn5pLf+kACCILlv4pNJCsdAcV4uC1dzdQX2xcGswnxW36pyfM4gCFKHNo2UJ9+vt/9D/6v/R++oJYmKOVeFFGavvpve1Xtp1KqsnExBTUU//pwBFGkAAACGyfUmw0TVEQnGtc9ZUbIlPdjRZxUuQCdqgzzFhIABN2j3ErtJYBzVghNPduFVj8bnTbURXWoCmGxBTpMyz7VETlbYIRwj4Ifk78N5ODyX/neXloBNJ80SSZ2tutPsQi5EKkCFbsPXNFbBfyDjZqgQhq5ef/DQfiz8eLtAD+oZxXhQ7Qf/tobv19enbpTJ17aRr+OSIpP3Xm5GJ71/qe/xfddd3XAAiGKJccA01aGmt4F2NgRho7k5+p8ksIqRTNAy2D8skUtuAe+c2Z9BPLw73BAO4J8nRq9avTrd6W1DPQQ9FFPz2pLafQQCVJB7NdCuXEYxQACXmnFOMb5lp/w6lX8HPyxVTFBmhNqoBdA53DNQG4pxo7RuX///v09SbdjYwXlvY5P0ez60xBTUUAAAP/6cgSZ6QAIAgI72NFnEvw+xGrKIwowiHj1ZUUw8LEiHuwoN5zOACEMkkxyDUVgn8uAga6jgZ25XicCpyj41ucG3x3z8qBnHWw78fv1fv/BdHdvqb+R/ym3HFUO0NODngNSab9M0pAMACAFZcNRsoGBlkJJGewMPsW1ANfICfQTDnQqWyr6PyZtW5/f+hPLblNj3NUJP8/EFHX7cCpGUkwKIhm1DCPZJVcgkKni1sG5zKJYm6NylN0SVd6uwWfZAp16Py/AN78Tvqn9i/9+c7smpyVdGnMf39+JPZ8oThlaHrd1Fnv8fc+jAJgkQVHINrkxDifyVsChfM8LcoGlcQAFjyRszMOl/4i9WyoJdujai7o2raHUmWt1flf8/UUtdB+sfg2hC4CigQVde9t7HqYHUxBTUUzLjk3A//pwBFIUAAACGDjYaQw5pEIHOwoFhxfIiONjp6RJcRQh7CgWFFIAAIEQoFO78YtuFOFAK7aENVM7cVkSpQRn1F70FP++gu68KvqvO6P35v+/9G/mb+hCl4mFgNeeWQaloGWZeLvEt/LJgCYEAJRyCjft1oBha9wgWjl+K2xM/G3HU0fTxG6NgaARp7ltW5Xq2//8Ybbp19C2g6au8O/Hzb2Qc775FH8fqf/UAAEDLQILrkHi4tBz7DCnkXB3fqSP/iCrgca+DZrm0CcGK5+E4PycvOmoLu+FfVzWq2Novdv0FysWLcd2C1SY40lKqlOgDeJAF/fi76H+AGVGUzzAcDcc+FAiGCwRkh4v9+I9G4L369T9P5hZ3OukiIh7RPo+yanHaPIxZEe70PQZLBR982g3d2LTEFNRQP/6cgTSewAAAhQ7VRlzEeRCB6sKDaU9yKTtX0G85vELHusdAx0TABUuoxmQTgvLyeEbkQPRQo2+f4y+xm64/oLs2ZsG2oLi2wgjQLzcG3L0//9T6M9WbtuLeod0BSNS0KoaJCoiRru+uUFWiinHAMoLdGcFCePWP9uYJVjuIKpWXVwBec71Gh7nfcM0F3wFfZsLAz7kwod/9vLyv+69myC0hRZ+u1MM6U89QAJzCADZAMAihJQAFhDtqKgvuHC40dlB6+JyzLMbK9W0DPN5Ru/8q3/yDVRmMdTGcqH3RUU0V7umVCyVGHKIG6jDmRK0fCoAA27C5YTQJRywAtFFKbH+2DcbFsqW1CRse6vq3ETq3IdPbt/+b9E0yXXrvfjxvWkg+DoAh+XKLn/fk/j9a+n/r2mIKaigAAAA//pwBByEAAwCFTBWOeoTfEJnatc9RW7IRONUZODmEQgdquj1CboEgIJibHY9zLMlGUAbU1bLhLfLcQfGHF4o5Ok4al8gI2nAr7vhWHP5/K3G/yf1JYIKaj3rOyKZtbVvLH+tAokcga1cKiAptgPRqo6hTaEbV1dytPmPxJL5ZsgDUkeMej/xX6tiMDTzW3Lan4r/MK0nKxKq07bHfsSndpWBzwb3dvx+n7lUIBNuosYTYXLqCcWy7pIwDhnQjOURNAUGEqHGPB5ynEwzqPczlDdX7dG/+Vbsmvct26v00LUvgkseHSaBO4i0gd/0gBAIgCrqB9tURVscz8Aco2maIP5PoBhJxFw8ArjJkYuso/8RD6Ni4T+R9W5Ob3+Vyf1NqZ1zttcgALIDBCKnOSN0piCmopmXHJuAAP/6cgTR8wAAAiMw0ZtLajBDp7rHJiI+iEj3YUG0R9EQnKqdhokzABdoAuKqvjYb5ur/rDG1iIHWwCz3tMBPvYatgt4olSjE1QcqEta62w+BnVJo4dhxHtJPWPDpPk4jalc526v9Z7dZxFKQqQAd2w8JISIZmoDXFd5KDa1oaxzzXdtMTIrHkjA/p08W27aG5P6Cf6Pp+leondE72drkDOkw7WD/yNrjENuPLnlWkRUVjYKm/4xQN2R1AwTzSe/P1TfkUnrYd5TUhCy/oPoAcHw4+heTnG4vryH0/ylXH6v31A1xVZxz02ycR6MUIuQiqqARIBmwH3a9E1GzRzIVTNIuHQV+3ESWoIoIrUM4xEce5/M2gvl4MbRefo2j9f8X/vybJZqFMgpCyC0QCSqRuLViSUa8yYgpqKAA//pwBOeBAAQCDzrVuTgppkOnKwos5XzITOtc4z1GGQWcrGizib4BAAMtwHEsXmDkCQUdT5bjsj+Ik4pwKGrCIcfFOfjB+gD/wsN6c+oi2NGWmbGH/vxB+vR+2cZZBD81Y3YMlI825uCARmIBP/8cKwT1LXBg67EIz6hvB8LHcm+oIlsSP9+Z17hvr3LaE6f1Sl7/MAP2Uj6eEh9iA0Bc+/1Lc11V1+9+fd/dsFAp3fjh2qdhwbcI12FPJeX4jPw0LUK2r05UL7+Qjui83kHVuv/09H/o3ZK9h9ZZMDzlwKfHSM0Qfkt4ZGEPW5p9u6BgUgEZJBqqpmyVMA8vsEK/8UrUTjNQoFySoE7f24u/iEHXM5Utof+vv/WtDfojI9mSccVQRLvWff1W98rllqHj0xBTUUzLjk3AAP/6cgTLTQAIAg4419DPOYxDJyraLecmyJD5XUG85pkQnGsc1JZKACIAgAxuDoNo8/rHg9OcKDNEHeW482JgRLOhfmdC2oItp79/5T/8q7ei+f3vo2i8jQdstRWxupbGjwRccVWpoZBlAEiEAVd8NythCYj0NelbFlrzj+BhK5gzoNj8h/VuJP8qMd/bkuf/Ul/6V7poWc35pLXMEzTEECV0ZQlDbX1b77v7tEQwS9vxi4oRXQOpmrgzLd0J8luKWwUFo5QfnfQtofz+jczmdH7f1f6XeYK7Jbn6+iXYp6jjVs8Rw9mx3O/i0benrfT8gKWAHdsLMSQl4/sWg6C6fh+I2sj8e7ZweuZQlJG8I7h+/Abr1Xl/25Ojat9tenEEPsl1bEg5XY5jn0kVgA8iRQZACdqExBTUUAAA//pwBPidAATCCSVZUYMrJELHWxMkYqKIMOti56RLkQcS68z0ndKAAAAAptuJpixSxCZhK5DGQK5WAGwg3RcrChfib6op0Yj0Jq+QUnt31dMQJD9BRxOFnOygDLswIsPLf/t4fnRStIAUu3HmkgE1rk48sq8YZq5ElWoe9tpbe83OhzPeUX6PYRq+FCTze1UTCEzu3p+fSvyMc4frVSQYGdE/+nlwowwAZ9MAALt2HhxTfc25qI8qNnNcHDEVhsS+RC/pm0sUikaz0CF+32kgrweKAl+41vl1VczZC/Pq2V/VW1/8uQFD/qf4pUAA7Lh8rx0l4bCoJuneQ9bRDLJK1CgamdMadE5b5p0VNmFz2JoVTHBmgbPlXa5av/vlC1CJhCwwNOVoo9bhNT/+lCYgpqKZlxybgAAAAP/6cgSCmQAIAhtJ2JnnEvRDiTsqPSc6iJkpYOwcS9EEnqyc84oiAClu49oZvRthsIIu8ApdEgZlVxVqXHyy42bAfy9BLScXjQENXxhpzL34UVlLt/1Lu/b5//EaCcr///bQuDEu+VN7A5AACgAMt3GL4nYZBBEscOiLpGPxgEZtiHIAepTZoScq9Xx3R6BTXjhtf+pRpQ/P/83tp106/pxrqv+vrSnXUai+/YVQEABy7j8cF2yDEqiljsXGv9A8EMTok3VwVUpHEaoQY49RVj7zAX7Pn//vhOv5O//RsF300fQ279PX7fROLckaYUCqaERkBAAXd+PjvE3YNal8EN1I4f2GvNa7fKh2koLXwp3xVfmgf+Hf/8H0y/gun/cRgn304Z7jtUfehc4uHSyJ+ypTDyExBTUUAAAA//pwBC3vAAiCHjzYuecT5EMnixcl5yqIlOtkZTzjcQYebJz2iPoA5ATuwHtkk0Og5iGLbGP658xdeqMRhs24ih5VSgvagEWlHxrlcuDrTUSnlHbv6YJs35++nV3VsrIn8DVg4iwPp95eVgAADLuB52NiiyBFJDhDrjYm+Emf1NVkoGc+UD3wX/inVpwUejY5p/1R5QWtOO+nfv3ubu+Z31L1ChsqE0Vjhr2yaCQAKjkFoJOWDfIlWwRaNHzD/akC8TvRxQ/Db4lPQ+hJZrROHaajBed/1Fue2b6Oun9XROVmJ+pmVI3bnPreMWIEELNh/oEAC9vx8Srypq+IlisQy5rohlePjsVHVUM25KPRsFq2DanR6f+2h//1GzE1oyJKP/yD5B5RRtyN9DXKMiF9rbVK6ExBTUUAAP/6cATk1gAMAhY8WJnpEsZD52sHPOVciIkfYmC84ZEOHGxo84oiIKmvA98D/eZBJo1PLo9cA6f2wOFdyBT+nloVzpp4MVrzr5BteQft/UbI2Re7iLAmzNMjOC5qJ/6j4MXb5FA63/SeLgAAC7vh6ysJj8ozxfSBczKWxAB9xKCV0GUYvUi2GmlOVuVa4npxMfR/+bRNP06dtci6D0nfN3wOZYKJSHyBdlmSp99IATu/EGScKmUEKj22GHqfSi17DXNhO2Mj7LE5mgZ71Ra5gxpyD0+n8pz0++j6/9V7V6GvKps1E6qypZu15CJk7nRdZRUACCAFTb4e2XJdYGy6b4Qje4MX/ZTaybL5JxRh2r8HuUfPWVaYCjUfCJ0/wugjcnunPZS6jYrP2XXBuEsTJTp1Jih1SYgpqKD/+nIED1AADAIGOtkZ5xx0QqSqs2EthojFIWBnqK7RAx5sHPYpWgAnv8PnB/rd06RcRtJZVsadddoVrSt3UZKykqMcPyj0FurThL/J9vfy+d0+f0TfvWKKANaEc+w9Qikw8lalbOugACSQD7NRkqLOBAeKrCNFEQqW7M94+LKPwWI1/Kdp4aoPiifoia4eP+gEi5XJ4fdT5mj/7KTeRCVgg9+qna1f3Q0twAN24HtKX5isEIFVdMBGaJhT5wepNEYJySopaVxrwpMZoD5GjQC7Zmr/xENuq1L+KUjnkornRHoLd/x+MDcVpm9kbQn3HGggSE9eB58Hkhd0Sea21BWza7HNRb+Asefj8LLMDnFzRcO4E829BK/Z6t/00P1/IHqxqo+7Xf9/7Z2aTTOpLsJDExBTUUzLjk3AAP/6cAQiogAMkhA6V5sPOrY/R2snPOJciL0fXmwkrtEHHaxcw5WrAAcvA/HSuWzTBIyGspUPLo0lEn7wPNsmHB7W5XiqhugO8eao9lMdDm+a3/52Y+379v/76t9TcoZnSmgexe0gSvVEgQCFN+B9YaFdeiWYcDP3HMoJdQJm1LleUH+K84vgs01C9thFW/5moTa/m5e+Z+t2WXR2c4zOEHWG1gJjiHiqSCndwP71X0N3CFCoJl6Vkbmn01t8I7bwwi53Tryvr77AS+rYqlMQFdm1HT/J4rjO/5deT9XeK6l347CAF2JVMtTavep9h2AQZN8J4w5CeE5DARWApRYlYLScqcr7g3hB+C8xinfVs7f/UbjBXM/70No3PYeU1lQVvNKIOpAiZsbNLDqT6//qhpiCmopmXHJuAAD/+nIE5BEACQIXLdg56Su0Q8erFz1Cboho8WBnrKvRFJ5sDNKjUgIIA3bgfXKxHZRwWMKADViQ9TduIuMiZXp4w9b07dUCsM6Ij8wpn47X/iYaiCzb29tXxeXQZaxb2zMGnCA13PrHC9sCgSp9wPTn4p8JKGp2ocNMSzPJaBgTReJhjnSpFxbahapIdKNYSGq2LD//V3gheR+zBHqpphmSBSpmbN/4HgxP775I2QXPnBC0IegbyGs66EDsqQM5WBqspU5owhuot8L//CcWpybDr9G+Ai8j+vG8uqfY2pMrasp2S6VZ/Q+NFDRru3ScmhgBU34FahNxKnJxSKEC2fUO16yHkseyMpztZB5BfPaF1NNxHvVxcm/+oE0NmX2JxDrqVXWOUizK7to7jBQbY2zegw5UWiVMQU1FAP/6cARlgAAJgg86WNILEfRCR1sHPOJsiDztYGecb9ERHWwos6KiAAQhAKb8CpYpAisI5iWEUBKWnF8ikzpRPVOk6vUr1R3VCahkcE9QLTinp/1TCPl/L+r7Kyslud9HUCqFcoxU73OSAIAObcD4yujE1bCuaxwas0TypTCpriYanOOUN4laFsbqcjWEGnGLQf/U+CEZS+dX11fpdvSt15HkCG0CkWSpm8P3EBz55sn3sMUh8bQeZpGr+VK55SriekTE+DnRsW571Lb8eL/26DGKn3/azgvqfJPNySEo9QvB3gcdIaNPYCSUuNWoCEgK/8DbjtIPYsQJQAr42X44X5NuF5XJ9Rb1CHRsWK3OFLU5hf/6kLiAJ8/60uo/U7u1iPxiwjTN6bj6kIgvarOG9ucTEFNRTMuOTcD/+nIEr3YACIIlOti55yteQeeq4z0iXIiM42VHnEtREJ4r3PWVqoMAEuSAe2UObNnINaKvF/3JXVgz1rNcrKC98HWjUCew66DD5eJPS38YKzOep0+mg+/S6KjN2IuRoK9RC6kh01KtWFX/mQE7uB7ZOIeW1JpOXEanTEDFnCPdTP/movQ7TLf8H2l/xfxt5TPTjm/p5dB9bebd/9GaxuZ/W9Qr2GPgNgjKG0rhwkCEpv+PrnCleKYqpLl63I5wxic6spShcvQJeWqW4YbRsbdv9W2H0XrLp0vLlZSn0Ojmqgay8kFYxepDGnnsrWmwlesYIEObcD6wcJeKt1HcMmmmthm3jKoHhvLFF0uCev6Hw7wTeFR+IN8AWqOT+iaE0dvY+zojc6KO73+1ExrRF47iI6crHhhMQU1FAP/6cAQF/wAIwhA5Vpg4OFQ95UrzKScciJzJXOeccZkekuvM1KiaAAduovqNTT7g6xvJLHVIcm5zscGMIGrSK6hovglq1TULXuBd68/X/+UfN9a6Zh93VaNmJ2boTqzodcRQ9zxRc3/pABu3AvA8AuSHBlQb42Fd50g+EyDjhcrUPL5/0GyFlL0EP5z1b/R7iAf5/WUgRLLw+lT9tsKCURoVYQlGsixACXtwPqg1EKwPoRCSRQ4X8/tWb3QuDVlYTVOL4w+mWQsVaFQMWvPb/6dH/wmtBHIZ/IRiNpmS/t5bljs3sFJKIYx2uxwAntuKEZApOuHBiwNcPufYIXUMyvFzs5Us+bq2qGq8jEb9Uq3p/QvVzw5t4usOBsi+Cj0GCiytiZde0WUoBEDQeIohkikywkmIKaigAAD/+nIEgH8AAJIfO1cZ6zp2QmYbJwUlDoiQ7WLnpEdRBhnsTMEOYiAXtwPeEQsxKhjipc7CayBX9IZzjbHrRq9IGdqKMqK4PxSLYFW+rV/6dX39NjKGHt0ITTEc+r7+Ocg/FzD4voXUuPcsA4Auf/idBcUYXZb57prbZwv9FjWQKbir4k1W2j7xAJtVsaO/p79N29Z6zKrNjjkSou1ph8apIcPWVsYgrEZz1K8GIBAFTfgZswE4bTfB9uJI056oWPaXCXwPTnKKRSJFKOo4ig1TaMoIXbeUDr/0JsOp2+nUjX6NQQkS5DtrwFiKKxddDfxcAm7YqCATRzAXh4uZjQyso+5tODVO/0AzJOV1CiMbNNaHR2Vj5//4AHpVHVL5lNqy8UnIyYQWFRNcTmC9/Qhb6noTEFNRQAAAAP/6cARabgAGAgUx2LnmE7RBJns6MMKEiLxzYmYlp5EbHWvM9ZXagAAC9uBmzAbqWHwPlBqOO43ozHHGlOD4TQeuYm/HBYpcgMN42JWlUp3qb/6vo/8tEdSJbrwjyWxuSoogle8mLWQAAgAFN/xtkhiRwKDijP40W74fvcabJLRPvZN2qxG4sYzDZeyyfzOj/9O6otNUS++n6DXE20FDqDm3Voy0WR4zp2/E4mKh4Ow6BuAFxlYPEYLWkDP7LfloeP+kYnM3hWrlbVOv1lvvM2+t/3jQPnBWA5NnTRegaaSUFR48qMqvDCUtrDcRtIAAS7gfCSYEQPUSUpxXXSjxI/EkrIo94YrthexqqGQH68VhaEFcSug5SBO6N33/xr/KWrV369t8x2Qz/NmvFKh6YiC6SqitCYgpqKD/+nIEsaIADIH7HNiZ6RJkQWZbFz2CaIi45WJnnE2RFRVs6MCO2gCXtwPpvLyoSMmA5FFGXOjSAM4cf9Wh/oeP4cIye38ifwvq1oGALMCHqN9b1v4CXNmi2Iot66bmsFhK69jWJeAgACfcD6uhKEhtqhBFBDefFijy5KnCp8u2henItHKPRWaz1CqkacJpfJ/9W+n0lPZdHdLOc48tbP6XihjEgZ8TqAKm/A+zPRyXcC/TEzylm5qbHKUL43P4WLuJhWJxMMyPetWRlMCXVHhxNG/wSZB0f5v17XSgUuz7u5qiDgxR1qWEyAiekVJEAGf/ifTnRbCUJlRPXHt80Or8Hs4ZOZXtpMES8lRypik36qj9yD/8l956Kw4VKio1hBTF0mhQQPA7zbd7d9TBbSu7i6UxBTUUzLjk3P/6cAQAAAAMgeoZWBnpWsRCA6rDYeY+iLxzXmewq1ERmSwo84mjAKe3A+TtVLUVT50XBhMhSyIfdCe7yHlktwsdFIpOxvvj9aai6cXxas+a9Ej9zAjkio8qPFuZU6EQ8pYEQkAB2gD7zVVNWlClhGqTBeqkVbBJAASdYafc75sTzZcevVax9H3ziaOWO7mGT+yRVZzW8JdH6SjGKngoRJXirTf0xcAGb8D7iDzQKvTsQsSmLimE4krObF07l9t0y9Ayeh0o1ar1dBfumlVyhqzHS4uoyXjgeUPI50BhsPPCzYHFBXniqaFOY8qYAAV34Hu1msgAtQjhiFlKdEfGBYgnhapp87PlC4kiYZhxsGPh73qRO0zbenBk6al717v+tRbUm34ZRxr34e/o+f/tWWTEFNRTMuOTcAD/+nIEnsgACAIWI1gZ6RLUPYY7Kj2HKIh0k2bgMOFRIY5r3BwsKgQJvwPhIIpXolhySGgz0mHxAX51B4uhaXpzNXhoWoQP4N5w0daHF9dR//g1k2WIKMEWtjAaFX2CrgaCYZHHwkLfGa4ADQAKu/A1A0qGMRdEGxm0cuTgMVNn6su6l6Eh1Hgc1XzO6RHfvcN7f6kefaya7u6J/SW1uqUbQyw3tp2mCBJX/8CchqmGqChDLiFDY+sLXrVHUsdoPloqaj2Iy6VKgsWivUv/8xMoOonkqdKNhKTo0sCVvNXNIgs0VQ97mnNdZFwCAgntwJ3F7woUKiex1/aqzotzNT66gk4OJdMMS7y4nt8WGUD27klsVVvcQH83okq/q3v2kUOShYVBYyZ9KVDnBQ+MSBBs1KvTEFNRQAAAAP/6cATVtQAIghUjWRnmK1RChssXPWVaiEzrXuecVJkWliuNhJWiKDv34+G544QmrRzyENXMrGfWNP868LLDS+4JV6DMdHbevdgX9Db/5B0rc5S4IOOmi51n3uviqowewybFsYEF09O3aAgEGb8D4kQhUBmBVqldVLArcxEjXB78qbxmLOXnlVsiGWdto9XlC+uo7/6E6f9dG30nZSLQt3ccEXtoJ3VFyB++9KASZ+APVjKVWwYbggGoNM7tPy52XpPhup4jTDTVszso0aIWn6ZcfOQVAmd2hG/+bx7b7lGOyMSS8pns7XNY3yJBoXBDm2A/Gaa3iI2CALbw3JGjulzbB6OgVCIDsemzoQqNuEY5xEeo5aGVOYJWVmjhN1Hn6Nofv69nSwvIIUNg4fYryJn5kbQmIKaigAD/+nIEc8IACMISHNg4DDhkQaSq8z0ldshQcWBnpKsRHo6rjYWJagEAFT/gBeqKKQVohCK4ARBgaIWoV8Vn2GSodMJCKJi1Nf1apJM9kFBajlWqe7DKJ+1pxdgoSJKLjQi5cLR0BsStA4FK/gD25gJsDXCQjbZYI6j1w3H55TE2wqb8X8Ob8sVi3Ud3PSo7UBSijMWiATt7d3qD6IGerdK2V+ZsTTLz8XxLqAkzfgep2wWCOYLOXWKFsuFlgJyn/sZUX2LdJEdcMro0pEsyjQd9cY5ng1N+q5LkrWMBcuKmC408UNipAo1iGk0WtSAFLth964yGDhRb7KIzFVUD0KDcQeoRdwKOhGFCFhzUR3jjPzxev4d/hAGl9EjJpVSujeqMa5aDNA5BoWjRZO8VQ9tVwpdNaExBTUUAAP/6cATzVAANgfgc2BlpKtRApZsnPSU6iNjJXGek7RkbGevNhYl6BKm3A7WCZCiGSQuLCCAHItrhLba/RP97Z5JKRcu7nd9qFRkaIgB1xjK9dY9Da9cTT5p1CKEr2wEQKKTNgZAAAIETf+B93T1R8CfJbrAOI1G1PpN+GmPbktEDqhko+cNxlOQQ0XQf/+P5L7ZXuriMXJpJiQERtjHjmCF+vbe1KVAAz4KA/kLThZHkn2MGkf0speMTN/jJn30z0zkjo3nVP2V7oy5wS/v/+Pl81yqa/ZVmOrHTkZRp93N8tfI37z0MpAqxrZrigJV34H8xabDwygcNUu1WJPoYFb9WuQfbni2LmDYrWLcqM+T3q7K9Mrri6xYLb063xahs/f0V1Ub0GEwaoSaaAV9A171WlM2mIKaigAD/+nIEnzYACFITI1i4DzhUQiZLAzzCWshkyWBmKE24+ZFsHQecmgBFB3fgGw2vkkRiZxYReMOYSvlUxwlY8qWMKVC7oBAXKISUrKGNoM/lX2TvxokiS9dxftJBdijIswisUFlnBHRsvWEXN+B7ymtEFvCSFZqpHK8Cn+UPyCTlP8Zkx6s8B+HHwyVyJpawfE/8neWnZK73RT3fcfHZsGwWy83lzmOa3zLX+VAJckAnCsWEAlhYUD4pBKVmHytYNMnJbOqnpUjLwnGZPWkpUqK1kZoV6f8UvWdHf9dklemhh6k5Kar0XaPfi9/3p6/kAaVmB0aBMglo4aj58ZbI3PHKYHYRNMLxihMw15QZqZqgy25tr6nb/5Q8sUPB2PO0KJ5U8YLPnlEYoueTph1MQU1FMy45NwAAAAAAAP/6cAR/XAAMwfQx2JnpEuxDRGsDPMJ4iKi5WmegT1ESEqsNgx3aKDdkA/Y01KiVGmq7IdKUoS8oJfsZVj+/P6YfEiFqLN7TFWtgz62gx509fbV45Vb00K9Qw+2Djl7xW2tXr3jQ0rvwPnnGtC2CbkNb5TuW5HiV+FX+LnzrK/Wi6+UvnK93x11h3a5Jxv/oNSA7EpHrSNdYFkjWMMly6HnGMQxd62MNIBLe2A/I3cxhyA+zxskR6Go+IBt9dCXVijRg0NuFy5sUTw5rZuH+bgQwCTpNRSF+Tg+r/0XOQ+4UczaZPScgu6mm5j2VkACpbgPywaw+grgcW6sssJ8t7Hpa0Ps242c3GvBBO7pOw/JB+jZ3qoRNMOaYtX9PNORS4LX7Fum7RKYc1HfQxMDzrXxKhMQU1FAAAAD/+nAEWr4ACYIULti4DyhkQOXbBz2HNIhou2JgMOGZGJ+rnYUJswCBGX/gJGV4nh2x4tDpitT1k7eeTMxkEx8NzEFcY0aPqZW4wC/mJQ/vyE7pf7H59RAfCARQgooew97RYSmg4aNBHsAMAZP+B6wD/cSFgwVtM0LzLD0PKh2cNpx4mDfWX3p1+gi6Jkzqn+c3O+32qjullMJEJdBQG4xN4gWqgJFacXQhwadSlE9B8OSOmeGf+gL8KZ5ayDd0GaHINXoWikNuYx5EeeYHvplFq/+UN1dLfc61maTO5ppXe89PP/DtrQyhKNVxv9CAKu3A+1QN2jZItbK34/XiEM9nGvuhHmFcdGQJrUjJC9Mo+naoXWl5T7/3CG1oT6V9kZtNNp0Re6MtqsrqyK4ahjvu3rsZMQU1FAAA//pyBN8NAAyCDi/YmSMtlEPl+wcwwmjIvL1eZ6RJmRQaq8zzCPoBObcC1gwCRGOioCxPqzMyRrUwjde6R4kf2pNGZQO5CWGTFmgszI0PqYqe+4h1/3pWi1IYLFiV6lvdcgK2UCj9HFgEABTbgQtGBZQxED4I3jgkwWdJFEyEsKQZ/o4/vqmg1mNIdTN4X+7qT+4T9X96edluFHHJFude67i4x3+bJGh0nOek2ARLuA1ockIL0eyqPdHMg7xtC7UUYrJOtdgs/UteZ3QVas6khDNodnTVKf+DFk2pX1vb6QBb38bAX8vjS7I0ZvfpnNN2qpAKl3Ab2YsZ7tAPo2G0gaDS6gPGucB+5anoprUosnOIElYEKPuozm1QWZpp/uFFNuiF9X/6AhNKCDJVRA5LyqUrqK608WTEFND/+nAEEF4ADpIMJ1eZ6RNEPuRbBySjtIgcyV5nmEfZFg7rnPQJMwArtwGtmL05ujfKkz0E6j8zUXLq2pe3Rz1spRm7jKprBDshm+1dLh8tvu3d3inljQqrNsY5s84l4aHsuKk5p7iREAgAV2+B1CBQDIgHJARErzOJuS9mvoKt+s+xvuyjq7ppSMc3vXzhFf/AhqOc+lHHB203el+iOWOuITA41KF9//Aa2Visxn6UY+wuVsQTSvseXmZctt53hyAhaJt3Zuy09AT/9SrqpWb8tDpMcMhnZ4LshywrhOjtX/r/UdljhWREAnZTFFQOFck9RatQEYew3fwpWBkSR1vMeNUG44x2a8RZYiEMUawQfBq/6DnmkP61z/0GDb8tVV//bm4IzA6zaVoMR+3tMQU1FMy45NwAAAAA//pyBO4UAAkB8h1YGYMrRECjmuc9Ij6IXL1e54ytkRMOa5z0CTsBO/8DUAbVQgcOAA3n3dXJnPVKxZczPeigwpxaq9mbRx8u9gVgwnUA51ukgLMHkQ4E4bLH3WIHzeAjkdtFY8AgCd24EBCDtHU1HYd+hyDGJ6SUoZRQA0EKhtf33zWOI2WwZFdveDc2joEAqux+Czr2J6I/tHtoXIJJtS+x7EpegBzQFR54KOD8IO1xq4bXe8maP4uSEVMxAWxvfNCzjhTaQ8Bg65adc4grsR0pRr3vWlhyCgmDAtJ2EEcRj3qdsOhuXBAAXd+AvQRVkQxq45aI3MqQWfnBHLBladhJ3yzmjMchNn8snzP1iiMTf/o96Mpd4r//ndP0yvlNIN+iS9Es0303XVvl1MQU1FMy45NwAAAAAAD/+nAEpYYABFIQEte56RnGQGOq9zBmeIh8TVhnmSYQ+pGrTPYgewQAN3/gNVTqxFGmGsbpTYTBwugzHJ1mGVuMd94Ria31PaDQ7hBN13/7Nvd/PX2i3+L0g4QL+QxR1/vNcu+/u3J35AQAN7/gJhDEAGbgnnqPLXYysFXz5YAGZGEiUicb982Ks++2N0ttz0ni26g7XJLWScPlZ9KFttAVLxx4Z0i4T6FgE3bULo60QgUcYgR4GKDwYOBYwF4cfKbu4/LufmYm0mC0dSPlQ7Qx1Z35+1/S0cKJBQwZelLlRRiWjXsMVuF3vegIY8FPbOIMkhCM9eFxfq83CxDx6PiFhC/HmYMmeXMRPiRzDXCK7TDNpF+YNuNP/4z/iPours7L8SEqq/utr9sGTpiCmopmXHJuAAAAAAAA//pyBN1lAAzB9BVYmYIbNEOE2uM8qHyI5L1YbBhNGRoSqozzFhIJTf/j0E56ILiGFLlXoYWF0WQ9ZW70GuEhbU0CBxq2vlxW3nFuZpegyATpRwobbqzjw0lbU+KCN2sRNqXczoAM//AazqHmX96vQmaSqxTMJqxRAi6q5Rqu4saWKjB1PuO8K94ug+c/7XskggOHMDYokSPa8VDMu9tQ6KKWyeIlps/qATu2AkrzMrgSVKZjA2U0V6MTFJm3pZIA5+ldTdbxWF6mBhundNooMzVwEql/0HNT3+12YxClWHQLuF0+tpp0t3LVU3l00pUAHdsAeq+CeDuTEdEQUKdmm/qzq3JxClvbsLSkZRNJASkfQUDhnPTRDHTcL/cZZfTRyGRhFTJYcuYYNKVn1MgZJvodL3jsmmIKaij/+nAEBn0ACcIEGVe56BLUPoMbFzDCOIhc1VxniG/ZFBLrjMGJ6gCAJ7/gNdWdnXxdQ+0PaIDLKyhHmHNk30k3UFXLkjar2v4CRzRK5nWsKi+wu8+tqAIZhQLgOaasVNaBxMdUZI6wCAqb/8QmoQEltnF4G4FDPXwVDuvRXLd5Qa0S3MmoJ+CHxdp+5VbZOkuAxY31rWJ81IBm9dU0hNpQrptSoYoFvQUqlYS4JAUY83HaPw11bMOuyq9pLImKBFdVR7O9oQ6Vbiu7fOc72drp8n627anCcnshQh9V5f233LXdvLkzv2J4C3dtxQRA5Bsx3vkiR1fvV/FI6mFrdYGYqrxic7YVRXh8vEM8q7/52ZlEeFzAu1MBUjRd3jvSXR2GxSBT40c4sRCzOEw4mIKaimZccm4AAAAA//pyBPavAAjCHR1XGeYaJkMjGoNh6RiIZJda55Rt0Q2OKwzxlaoFzf8CiUdNbeOYthD1mCAD4oJKTrtPlhEmcJw2cYc5lOmB0rlgxjOd9+CdU90dQa4yfBVeZtzvlmumESdOtb/Vn+2v6AA7aA0RxSkadLimG6Z/ODyqerNlYJAUraUPmKoEyp4zASjDWkSctpfEFeunZZ+27lRRKChI1z4zsaKBzRcBmNMocHyAp7fgNTpLHEqBPwUCDiNxYXjdlagxSkn2OUh2zqWyIP7I9QNelDin/vJnR6SaObLqScWxYoONYNOQUEsTKrsa5QhWAXdtgki3k4LWWOkIJcdDospH26BPMDE+VLxGCEQ4tM7dfhWnET/2PLtJ1scxG5V7VLQk4PuFUZoWPjLUrWcXewPK5NMQU1FAAAD/+nAEeLMACIH4HNe54yrMQMOatz0laIiwsWDnoEbxFo5rHPSVagAgFSyANT9dNDOcoszrPMePkIsH5ZyVamoWLHd9HrrlDOlFHfFTYlWhVy2lCyjzXh8OGVRrVCNxtGeLvOIOEwBkFzbAQixA/TEYqnsxHI3D7yd2ErzNS5Xadl6pTLZYdyFpL1j1bCelJRBfq4zFUKJNCpGp4qs8PWV3ZrS9Rka4QKUskEJbYGeYoD+SuSDidPmpss670ULK796L0MA9NS/+yGRU5r6FYmDGEgahMG2ElLNmBxUNHRGS3mBQdaKlVwo3ze1jSAp7bYL5YhfnWy3hIQwwSDW1UTytfOMP+zTbv5FJyV5q9VIo6UIX1w6tHYmYUUU8ilaskfrsIpakTIoe11JF7UYZiuLbVpiCmopmXHJu//pyBDEGAAyB+xHWmY8yBEShuscl6QiIWHNQbCRLUQwTK5zzCVsFO67CEfnwoLwzHEPX2hexz5apDM+tmP6/ac0Qz0KOvkbYn6oCe7wq0QqaHgggzR9mKmH6BYVIKalTXUpK9mLAGBTu3wA86JkpO1qdGONBQ1UiJO9L4iuVWHz4FecBmh72uBtyXFoC8XW/vWqwe8XabZVWhgiXKoSeNlAbCNBSjRc9mygAqW0BssDNTYSsCKNLBWCwp2hKcYB1Ay0TMoy4y35wm895KlHtqf0ZjK9rHppBjqfytTX5ApILPZ4I67nVtS7aTtQoQSv/4DWjRmJ1moxwHzkOuwEYT8q/L+bYsdkoRla4TkYnn9oorXL0zIbtHiDDN/Ov6lvx285UE43sOqosxvq/dWtQlTEFNRTMuOTcAAD/+nAEnVQACMHmHFaZgxKkQsS6szzFWog4Y1zmPGgRGg6qyPQJpgTLt8EqAlIBWCQOyr6Ual9ZNjTBR7KLLqCcKbYjWL9/xcOOu7L6DrmMkI0xupYpUABoAlWQ5EJu5S9X97wVdtgNDgHaplg2EixMbWJ5UUMFPpNu9X2LWeXTRZb/DO12W+BKojwFOVyu2dpRN1aMnBF9L2AehiVW0NA0Dn5x1mAEAqbbcVKBiJOh0eks+UDxiA37Ice+UFn/EilxPy56hKppb+0qWKNQ2LvXUq02y4Yx+KJZpHe7HnjYgCAGhQwkUPLB/vEgoQV6pep9OrTkoBDaQ3T2pCJ0baBnDVbDyFPo6/YU7wgj9wNyzOSYNPPUhltU/YjM7UVEh4RKPAZa4WlVHYrpU64mQTEFNRTMuOTcAAAA//pyBLH2AAiCIRjXGSwQREIDirM8IniIiHNc5ITs8Q8ObCjEjG4FTb/hIcTh8oB9QT22ANxhD85bWQgJ/q5myZ/mEuuD/ztDl3LhhNTEgAPDZg+J3iNTWHaBE0CLcUOA+wQHUBDfeJ0JDgJd21CSL+hBrpYzbqpLVCavqKrsVQASNIxASMImiHV5BRvUX+KZb0LFEFqkHQML3JPCYfIzYuphZbRRDyV5aAGf9YQFJZGDibYRJxKKiEkRgNy0H4CiyV1qSUaFqtpboG/yZcIpeuw2pynTpIIJF6QkC41JUMjgrY5ZuwgeCrCJ4aDWjZ395KBKWyQWNhbkECzza4MfuM4iEYIyU4c+kUGk9jugxUfcTzngJsFKrBygAfJUOqraEPSaJjhBqFJNOo2FFi/aYHIagzSmIKaigAD/+nAE52IACIH7GNYZ4zLMQ4Xa5zBldYiEY19GIOtw/YysHJCVzgS3GwG5HsBN4A2EwcrK+F7l4IIgb7kPKHHLz1FkwzWivm9//YhxaEoAq2FnFt6GjCjxbGiNhp9HUGzIo/is1eAYFOWQBDHYZEd0VA56NcXebqgz6CHsI3oImyGcd6ezHNKA7qiYeS/+6b2mqtKNVmnZx4econSHWrBU7za2plxxJwfUqSKdskGmzBMoqMNNMF+JKVJSySfUWNC701qUUBE1VpvWrAJ4dcmqA0MB52gWFGw8GxZoFHVIrmjLBoc9FqaA8Jlq+yhAClskB2YAkmy4OHmtCWp2giqsppLapBw1lX9NWiYG6D6OgGpGOWCigOL1nz6iNSnDgA4mhTIntrnwtdqcr7kpiCmopmXHJuAAAAAA//pyBMZXAAjCJCNWuek5dkTjKsM9hRqIVI1WZhircO6OKoz0CaICoSn/4DWtK5jXYnbY4gQgJpZDeRuFCDY3qb9yb7TvZLnroA79Lbfnj5nGqsRO1GNLtHoyKeHM/d9OZsYtwPSf+7/mGbCMu2wazhEwQ1omkYGKCYhR0LyWalAyMzObJCA5c92ViGK5OGdZy7mQp6lJBF45aDpwXIYuQB6RcH2FWDufdvQHrF7BooAJI2AXVBSBodBsBsMBpoA12wxKD0vwaFuxe53qr6OwuhZrygL+HBNlZ7zbHHSxgUa8Dk3p2NGa6Re0gwZUl6aGOeoBS22jQxBcUQ4HwMs6UKZCW4lcldZAejdkepSVkMHRvLJ9doIHqmHIKvNTLkK0uurFRIPoyef/Tsjf32JiCmopmXHJuAAAAAD/+nAEMy4ACIH7HVe54yrcQIRqszzCWIi8fVJnmKyZFZKrXMMJpgBoJ2yQZWHqtoPZrdKydLWqFmXh9NLv1BZO2/va9Ap+tg390FCSrRghudiaYXDaUj33KQofFzxVKlqHu77WYoArdsAuEoCfQnbGLqxpuMQ/iBw3Srbu+tJWLooKcjXKvL2RH1TILIZ20C5QW2uNYXjAqZC0XSEm1wkhSKIs/tRSApbsA2FYOc7pSHhAWlVTnArZaKqwARZkbnctkwxRRbU7X6A7crKOPIIr98LUH296uXPo/X6M0+hi34ao11hDRs8Qkb7MTMA5bIAXh7Rjf4SCZsnZe0pf3685WREVFO1HjTt+++gzgYRSBDNMjXfo8glVKQYeHbYij5RiVzs0CwsPrWIglVQKhhjEiyYgpqKAAAAA//pwBF6oAAiCIBjTmwwZxD4DGto9gxiIgJ1U57BHGRIRqtzxlZoAmW2hqj6tff26SXJWrjAqLB5HqG4wgNR/q0J1jrBSWAgqjFBuHxuf0T0/TdLMSwRG0FDYc6WC6XgZFW9P7SL31eOpkQABhCc3/AhLYqHUWLBLL3hjjTN48auJ51EaMD7/C+3BHcKetBH4nzCcWijcDi5gkoVeKuFEB2HYwox8sPrsICptsAkkLTSCoWAfZDxM5UU6XI+E8tO433BudUHjUbd7aNk6PEkRH+11UzmGdxVwrWi3OjNrXpi852wz5+2xazZlW/MwKm22Eo/lebceyYLmxtRz6w6fVnXU8JQuRRhr0bbU+9Qb8KI6/TiKsPwgLvYZS0eKvw8SKMM50Snr12tQRsuZZFJKapTEFNRTMuOTcP/6cgTyEwAIgewY17nmGbxCg4raPMhbiPBhUOfgxREgmWscxJV3AKS1bJB1qLXlUpEGXblM4x2GMoX8qfM4ZQjzPRihZh95L4NYtJ0jb2hUPBZz7mJiFA6IOWIjc5fQqvS8nvAABklSRwBfaRSmTe15jZIKFTsQR+aVmdhS27tGiVtkQ9V1etxIIccTlHSDJq8URXPPogZD0UtvbVWl5x1ITSYILUsJDduwCZKYfxavB1hQyhbHbkggOb27/HUa69xSomKS7ZLGBa5//3bZC1E1nFPQ/SOCZq229i4vUdkiR85cCTBIhqh888+MYRGUZbIAUyaBAutNQE3YRZVfPSHL/l0t84d050kD0Yl1XPa11blZvQMOiN2ynMaFCqtulZ3TdKbMjFEygy0+uOk/mhsWLzuVvLJiCmoo//pwBLy2AAiCECxV0ewZzEBjmtc8whuI6GNW5jzDeRMe6ozxneIAAMAFLYAFy4mAyN4UoUKAJDUKRnSZi8Mx8uqVPHn5mo4IY//G2hat9LxJFIV95hKRUyebNwtKQM5ALjIs9KUozZoAYJcsjEE4Bipwu+CkaBaNL7OMJnMY2VSuZ5BnW0Ercn9RVPDUaCz5BbhLMgVWbBQ45j3HN6iBwYgYYqICiUf9RAUpZAGRYHim6BC+QCE5Zn7ZRR9nUlomY3WV8a0jV627Gfh3j5hmfqynu//w02/2PNY6dXJDjDZ+7iF8B7s/79yrUQTo0TrYKl2wDYWADTM1qiPUPryurnNOzKkV4pM0puqD9BlzJF+tPF/aoVDH9ecj1N2RE9bog4smru923O313etkfLvFnikeKL2piCmooP/6cgR8bAAIggIYVjnpEjRDRbrDPMUaiFSlWuYYSfEIlWsc9AlfAICrv+BIlFGmpBTEUYiM44geoKLYDMLXxlgudD1K9G2rwbcsdKvsnCC5lKSDo+pYBhQ2EyjBYa42gLBNi0KOZEKTf8BMJEkx1JijB4ALCNuu5IeI1dnVGcsjsoj7ILWRomAh2GDnUaOy/5dhja25FVOLkD55Z15xp5loaCb7GxzGjdqyhJ2yAISUtu1H4sBQigC0wNhfja0ju52uvuJ47L+jFNb0W0Eki9E/+zWmUjqrg2FhVRMRKmYYEiRBVjZNiaWgeVdLiCLtkAXSvDcNGZjSDQq5GXreqhaIzukcZHoLa72WqLJlL+drP/IClUEM5lS6K4uWeeTErqa58lt4n//u1V5CR3plUxBTUUzLjk3AAAAA//pwBORrAAiR8BRWmeYpvEDDitcwwjeJCI1W56RnWRiS6xz0CTcJO2QBuZzp1sbK7MgjhyGEwLVrWMpa7c5KD7ghQVD5IuaW8s3y5p6jAOGbRq6DDT7SJW1Sr5lKR5UXjntF6gAguWyASFQkhU+tJRFBZHcq9w2lq74MYZpjjSPS8l8ggY5lXGYkN5UGDL0h0ckMF0LjVoddYi9TCo1CJx7HyLBR4Lv/4GziJjHoeA+ycKWy0WVK+hJG0TmfqhirLV2PyPTTG6Xc5hUOwsvLCA3fYLxwnIogdXvZ0CFDJuWCz7IjHEClr70615LbOSrWs8gnj6ipBXspfrjN6NosKIqHxCiDMtpIiofeCR7ernf4RYWeiyzBUBnUZI+EpjV+LTwK8H7QTy5bQ/uQ/6+GTma27iYgpqKAAP/6cgRFiwAJQgoc1zmCGrxBorqjPSJEiISNV0eMsLkYkWrc8ZU3AWS5LJBCqH9HIPCaVFX2dDwLDpB3wSXlWVWXsxeuNQQCdmXhJj1i1dRc7YhhBZclNmgNC9UYpMinXFKhQQr2v0qBL22wTJ6jsJOnlsJbKO+ZnpyJ7WBkeZ2RrvjWrpeOqngDs+IUKDZgoJmHqD4YQ9LyqiaLbRIOxt4zVcKKduuFddYQAp1fem4l5znJCijjrl89YoOcUb+yLcMoMk83QyZJYJfSBrZYkI/+aN2B8VmgTLK1ONaK+NtXNyTv/xh5WhPo0/WO8gQE7ZAFycAL0lilGyDvfk8zFxwlCC81PynODOQcKfvJqPQPBP8Qff+gbpOiI1H5WeCktNEe8rQ0WBr1CTWMkQsbdWoYc+KmIKaigAAA//pwBCETAAySIxVTmekzFEPEqscwQ3vHREtIZ+EjEQKOayjzCR4EK3YBIi0ARGJoCEkDFyBXIall8wDqeckX9CKrdgINXabHnTktnZMYmd574GcouSSu+l11JoclTg8RIFVNc94bBopUscAcA22QDgOAHHNITAXD8d1y+a+tnEaQxpmdnggq2R/tZdBWvNdWNUzyBBmWKCmv+tr/L127ru7iu3bEt+CyK+uX78rtgBySAMADQByW4dQwc9SRO+C2KRBwonLUkx5KkdQWkcMs1CcwnPHSRO3i3KLDvhtSBRDk1WamevoWmolQlIuE6JY5n5Ai+C/VMEPpVjvJLMLmjMSxhZpgWRKuEKM0o726iku7j1ppkVSZFmmHpPNeaOQTtalxRTBfS9comIKaimZccm4AAAAAAAAAAP/6cgTQQgAIkg4l1jmDEuxAo5rHPCVjyPQlWOSwwPkNkyro8x03AGE5bIAhGIEqIxUcHYZ3O/odM0+6wyvMdRVUtVNg1Nx4Yrb4vU1/rCKYwOxQizAoxowoCT2jfUAD4XF6V6AuD4usBgLksgC6TIdBbWQ5wxDWObrHk6wgpwOlBybmZW06o+pTPNqFgjf/m6d/W/f4qh16of+IS8KPeiNdztf0859+d6QJO2SAaJwYFlwrlwTwZaKcyr8Fzmv9/wXzYC16p+H+/h9//9TJhKC9jh067wVT+SXv/PuyfMqzpzb++CGCHdft/2//ZyKFKBcBMsIyg6SXPxZQNyBP9kCaAsJ0WhjUihYOkqf9pWJfom913P/Kh1vtlT7Z5X9w5tJLdMypcDw3770LgOnu5/n23f9JiCmooAAA//pwBN3jAAmCDglVuWxITEHCOto9AzOIJHVXR5hK+RecKpzzCW8AwKUsjDg2C1YtKpkKSOiFtDiS1Kj0MBkWfGyDzCENSGWVs+xTZCVLuaGxwqIRO4uYKgN7BRoUXaZHtMRAhhYnojAAAZJLlkglOIWs2oJPB9ENY0EuDAs1bVBKdEw/cSYyHzuEuS+cJJtoLA4oexIkDy0LetUORGlGYHr484n1MS6vMoCUBSNZ9iXZXaQVZKb6R8cpi9TGbNFIxrDnmu09vPe9glfIKaz//nv6xp+Kdhf0Wm7K99U/ypJYolsp3NgU3TKwsUAuSQBfL+JsKWfwnx7hKVGpy+bdA1+HNfZ3sYGv+z0evNB/pnEfnT/3dkdHt3pZJ90yS3cxy5XdZyAobt3e5unc1r3C3aTEFNRTMuOTcP/6cgTRkAAIgeUY1BnsEbxCAxqDYSJYiPiVVUekaLEZFesphIluAKkbAPlfJYq2A3h7hmjAzHBQhVMtSGryOOfdNzMzK/ksnB2vH/kxhJYLGnsSgqGbGpKLGJxa1m1IkFeRaCndsA+L5FHEfHdQ5liqgM9DyvZw7FboUCV5st4ePSlN4NpBrPujJVBPIfKGdDIZHo2EgUDNNwrrHGBQogItB5awCAxLlsgC5LAFyeChRYyTDMRmAnawS9gnpzRbTOKGQEyimp/TwSSDHAa+FBObF/Ppt3HOhxQEtUDNAfg0FQZGMTIvXiVRVCV9gEpN2yAVWuPrAen9JTuHhTPPfTuP7p+WO+HxaqT1uLlxZxn2Qe8EBNvhP/qcurURmZro8UFJ0wGiRs8LXilqkpxYYZUMR2piCmooAAAA//pwBCjvAAjCFx1VOeMTnkCiynNhiTCH3GdXR6BokRERak2DCVcA4CVsgGiwB1nGj1KPc6yOYHdcaWqSqpCsWYc/kGUJ39k6Mys2N///wXpMTqv++GLKnoLeNtpr+XzyNdK8T1D1ORk0EldsBEHNJzorQelMKPA1wIGoKDofoe0sEYSL+/gfd6Vdfsv9Xz9SmqD+r8bZP3uC6DsAJKPkD+boAUo5Vz2pSTCUKTf8BeQ0sSsbGprciOaHOTCm4aNFU7KPenlYXDLTOFtjaHAl9o/pjzTz62CNZtQvEKblKxAUWKiohIGVsWAnK4A+C+VgErYcgZTQOvBz8LVo5JK4gLqiGvheoyMURdf+dNCpBE39dhdlReu+cZUx4aJF3M5/4Wv39wdwO3SZyNO4omIKaimZccm4AAAAAP/6cgRpYwAIggwq1dHmKjxAxYqnYYI2yMhjSGwwqVEYkWlNlhVbAADQFy2QBdMYoEysrpcKIxbkCNYFux5M9q0EH5DDlRqPqqWZQt/mK3/s53teyWogyNAgcfkbR44w16Rd90lsHzjgBBO7/gR6FkQVXULVRxCQZFWAbdgfizRkWPRWR22SnZ9dZzDcrVF77fX2X7ntQP5zOjfbrusdJ3G34yVs3dekRsAu20CJBCkPS8yl8PocC2yGqvgBQeO1oCLVLTt96fdHiP74egYVpa70ltQZxtPaLGaGFliwwKkAbU17RSL2WrfMNXauxNbAVNsAMwUEBQQU4/a6BDw1lJFy1Hm+9DX4KycsdMb02K4PlIYivjHabVlILvUuHRjo6b9RV5khT1u7nWBeHsSys/6AXbgNSmIKaigA//pwBKreAAiCCCTV0ewQ3D8iendh6zKIxHFQ56RKeRyMqpz2FN8AAkQnLJAGs1hGjtaQyANSh4M09fT5CkMqdgSVQDMSm1FCzKMp19qE1SvqrQcFdazFYbrkmoLIYtRXOxd5IZPUkgBAp3bAQavcSkAhwYWBDtBZJEnEJVGoZtlIMXRUyk1qL38VdVXSnGXFroa+Wqdy5AIDlQ2wSr7KyFZqfdS9tSAS5ZAD5U4kg4jFimcPhDlSJgwFNC20ysNocMzYsEFh0mbd9tvwR/P/+S9Q7X+1sGt3omTC62O3AF3jEcxBmAhuDs0/MiXCE5bIAmWEWgRRxQ/YTIwMgzMmmHZoMUjX4gGutT5ri7ckzFIMZf8TTHfPoVUOso2wk+COhCQP7v9sYxGF0OemX07/98EN9CmIKaigAP/6cgT9IgAIgfYjVenhG+xDZWqHYQVpiKRzW0YErvENjmso8wluAAAEAARtsgC5OAeJiq/TcuELeHrHhYZWpe+b2SzScnGE5wEsf4xUPKth4NHgqteqXNpAMK1GGoMHGDmLfY2kAJScsYEEq4RFQxf9JUZWkyySy8URj+4VhgntI/EIq0c49xsUw5MaR1aoTXTUWo3pol6tt6PElA8VF9B8iooXFo0JdRgFO2yQcPgfjdcxixG2DKkNnr4tzaN10gEbid5XVB1gJ7xEspRY94oKM5woR2EA+Hw+1rxdYXMGHbDBTmAQOLbrA497+sJknLZIKIQOscTcrAZdVlwRsLOM9B8Ydu7h8IaXQtppsYt1dEagS9HxLvCi1GVRNl1uCz0obAbaNjktdXYKi2Swz0dyYgpqKZlxybgA//pwBCARAAiR/RxSGwYTxENEWrc9AkvIwNNS55hNcPOOKujzCRYJSSQBRpFVBYbAjC+069iST3j4Je6EXab+4XJmpWbBmXBW0zCF8tS/rJa1xbOtYUjTHKYzSb/cYMcXa5L6ez9YAwnbZAF45S5CArJvBilefTwIyWgbud6005LrjaZkJqrwmjkYXJR4IU7NzdwZrTkvcn/h22J1ne5LTpr/HG3bte9/SlDckjAPZjFSHWzscCKf64J3EXWYzOQxnynU2eqip4FvOCUMIooPiSs6y3Gbtrtd6/Wvt3qvSYqOYE5cFyJIFXAVzkvsI9AykuVdK8VAq7nOlBrLM6VPIVZaDEWyQj1VgBTm15e+Zi7wh84/LOSpRw696HQOpjS4ES2plRkgl8g4/NZRMQU1FMy45NwAAAAAAP/6cgRc4gAIshoYU5noMqxBYfp3YeY0iGQrVOew5LEKDGlBhgziCSkbAbhShsgOh9n6+cSoTorzMLkrlBW9KV8ZTerO/oP9kNrM7q6Rii31BsGQZUwPpcPFH9iUAm9loMjDYuKLY87qYoBILlttE0j8lqEAc9W0qoTiJqtqmWSiAwsjrzkvwLO9ohjW949ZVzzhpWjAKDDG3JHzxt51SXuFNCYov2vray7/QYIu2RiU1xrCPnAwXUn+AxWtOoE7SoDDqJs8UeH3iJbl8t8TEiqnDklg0OpFjYReKBcIoOtDLw2GwrZW5jUGXizE9aILKBi8jOlcA4QZ1DQMFyJp9IFcraMwtY5bL5iSGi5ZHelqQMGaSdLhV1NaLxLAwBc4tWoOy2POilyIK7Fyyaj0TWITEFNRTMuOTcAA//pwBHlSAAgCFg3UuegyjECjqqo8InnIiI9RR6xrORUMaM2WFOIAoJcjjCZV5cA1mdiZFk0ZEu3BjfSxTYR9Py0TgOB1MM49wty/xRrgcJuYN24qBOl2+5oCCIEaGknDQJioEu5Z4tckAIAQVLZAEypyUB3WWh7Hgs0gUzWF+6KNPOzEFK8/rwDThwXv//lZampNXRkVfEa/XBJnziNSWgMYaW453P0tJIAwLtsACRLAJUGCzn+k1QVF1JK5ZS8YzqXUURS1eZRZungiL9tYEBqalcGGzCA181apRGSxU6kxZFZm2T3lpyu3PSbvSAlbaArKXoKSDMRRXHBW/HlACOkr08QU6dMr7UqzOxnJGkJXJ2tZUCaKiXyRUwsLuDUBhM+pRUXAbGKpVWYe9LpNqxe+LpiCmooAAP/6cATJzAAIkg4c0RsMKlRDRMqXPMI/yChPXUYESbEHHmoM8Q3/ATkkgjIcwHjObkTFbRUboCMsYBqYEFQQYykA+D259qIuorc7ZXCB3jG9rzJWz4qr0OKKcBx8n+gXoIMVzjtEe/40A5KlsgEEcAmYVx2JwkZqgGYw2x2tsNeZm3UfcKiAPPvF6cV+omv+pCoUNH4dFnWOqtwe+id9zjcEJ/6Zu623XvL8/AZLmtkggPTIGKGkL7SjRSixYcjS6yC4S8o0eTlWBkThAYYcoQKUkKHGLeh0XaQjYssxfUxiZsUWSSgxtu2qmo5iQjIkBwhFAeTlO4ZNlBve4D+J9O3l9bbK0L6AyMxuvvCvBofq99KLtrQrN397copJnEL3dTZKO3a5hKQCbjq0/evzTEFNRTMuOTcAAAD/+nIEBGIACIIQHVEbBhO0QGWahzxDX4jYR1dHpEjxGY4pnPMV5gVJJIEll9kcCfZeZAUW5QHBgoegGzQUq6d2XstwKD4TAnW9P1lgeuEHz01iG3yDOacPUwNJaHSsh1fp1qLo+r9i6ACEmytgGcdoNQFezF3J6lmvcSo9kBoUqLWx9BnUG2DVrNXk94HWEMn71YXdV+Z9V4SYMGRNBgmxuktrvMVbDf3FCU5bJBCOJEk0infFRyLq/3EmasPwsjM7o/MosKeReZvBMZak3qmDKioSNKGBcshCSqnAERGhraBg9h0eoKJVdrng61jbyQSVJGwDuDqAIQEw4kNhKpK9D2ZhjUxdoZ3j/iHW5Q3Kk6GNuWv7r0A6d4dGNa1osSHilkkasrcKGgFtW51JJSrryhQVabkkxBTUUP/6cAQueQAJghYdVVHhG6xBIjpDYegYiFBzUOewSLkHjGqo9IxeAAIUp22QCU2xrkvQ0/T+RxzVdfOk1WdPYUgitNIh9Xrp7H573659BYjyNLiQobEouGhE8XGuj1o6Cx4NGDoG12eLqBUt1AlY1IneFTg1RsCRYPhjNJhKC+qKN9Ht8JhzbYyoJcIhjXvFuEy6dAu1phBVDmrt3k7CBARAuwqCIm7VK44igFWnyozkJAOISAZTmPOAn3eF/0hWCZzsr7Ow8M9Sd16BE3xgPyHfemnZiKX9D/JptCs7yskdfa+6cst0on5ey+NfY2hSWyAJlCy/DCF0RSYfoOUOuQI6bVhhAGNw8EWGLZ/Y8O1HDpFnHPhkKFSCCJwDnKxa88x0PMQ0wdNFxa0UpUrlkxBTUUzLjk3AAAD/+nIEsjYACIH/G1PR4RPMQkNamj0iJYjc/07noE15GB8p3PSIagACAAckbAPUkgNUTkto+g/E6q3FahYyZEWZixLRuSEFwo61FclBnuMoXEnQgeqsXoWFxGLXj3rWvesK7/svexgAAJAy2yAHyjAOAVrOkZtkCQG7AdkHrdtWUh2BDWbXbUZXEFuCPg4BC66ljbRIeFaBjFSBFwvIhuEovfkbJI8GlrU8FSRwB6KQHOHEdAQswB+mVlCIPwabWX4xVqyN4Vp8Jh0Iv3JstjF+cd1Y36vo60u+/bmNQy9Hoi7bonLY4OpXsC7HVQWJjhhO7b4IkIwSMF8ABhGSvXAFRaryLWaVFK6GVjNXU/7QZ+mrTHZ0rq8xbHI/5l629yov0Vn5f1IpIlQCBZpYmESLksxG75JMQU1FAP/6cASGPwAIwh4YzJNZeaA/AypDYeMYiLxjV0esy3EWjGjI9BVGEcABRQcxaeV4d56c86bKqDwZ0F4jTBUxoBigEdfgzKm16xNuU+nkupFMB0IYzxmeRVvGovgW0jErZvFo/h61hnqhL7wXbbaHgGgk6g6A5Uk9MEuLwEdV+w8qJeBGNj+lZSrn9LKcK4BQOKFSp1B9QkhVBrOLVbw9bQw0xncLY6j69yTSUctkgSTWTQ21QUB/qFQRlqHwYwiT/af/UMu7p73kAHKOkZBPIPz8hw186DFS2vNjLaRosl43rU0MuWlFnRbvex6K32ygH9QDiAkQBgAFixKtSGmK4vAY7AaSXM0xsw+rLZRRAQfSyJfxXhkbbQLLY1jCjA4Uubxp4cfc/QJ8dHJL0rvXUlaa0SFKUxBTUUD/+nIE1RgACRIPElZphTK8Q4OqujzCXYg4P1dFvMExDA5qaPGVTwAABCYU5bJA0OxJBhg5AqyeOHjGEkAUBsY3Cg2JQm+llKIyqSc/qb6GG1NGsewlpvSh3U4M1EHMexAsyK5en4hkFAgK2m9bJAulodJ+UccXg1T3Mav7/nZ68cP4e70GX7n7eLKzD28MOgTWlSXD1G2LHCLSlUOEZdjEpfenf3vc6yN9GXHjWW7ZC5FGWpx3kxaVSyKW7YRjFfjyG5pyDN1kw2YCoqfYPF+hraECQk4qgQ920kdLIQilMa5LWpoeabZpa37WsRQAAaYb1sLUOs3Ubid6mtENocVmDLATuiGIx1emKFMoqsz6t2hYcKBBkO+v92lFlkJ4j49tAD3wO350/bt70x9/1/O1piCmopmXHJuAAP/6cATOGAAIgh4T1NHiOp49g5qHPMJRiHBzWaekpbEdDGjNhIlSAAFkOS2QBMqM/CeHoSk5yxI2UrnjsBUA8KnszqzVVdLuV843oUOmuI///625e/Xvad7ucXeN5znjjNd06j/3zlFFzFABhOSNsLseYaQsSbjsbC8bh/3A7SzpHZ92opzvZro3q7xvaozrkOD6CLdo+UW9HIC4W55KH3N+cvDjNOr6QVSW7bJA1qgxUS2lANAUybBid3H2iqhBupwi3u09ley98/8HU3UxBkWFKHmh6RrEvEzBh9SnVeQQt8yEWsLHzqM776wpLbaE24ZEqCTbl5ma60RXjS+jRBMIeyDeIdqgNmRTqPBNLaZ+wwUDMUVS7SHJIy2sVPgA33PLvdh48tDVJp4oxi7NrtKK6kxBTUUAAAD/+nIEa3sACIIhFFXRgxKcPyMahzxlUoikK09HjEpxFplqqPKJdgAApLMtkgZDwRwSoIwFBKWHRDchMZjLAm2RkxkGkeDFOYBcjZ2eh9r9aSS07oUBsWbTVHGmDDVsi2aFGi7axridaGOJADDm3/ASI/CclOyL0FBoywzWUUgfitCtI1iIp70aiMzX6AyM6fmSa0JHX6gHUSpUVeYejawPCFwjIIWpjht6AICMkbYSAxQ6gjKqAfwxCqZkqHUjmGFuCLClRCQiEIiJ6Twca8B8qAjbt0kZqQhS9uumWZQZsbkAgsifPrra0DqS91elALJuWyQUNQm6chv3kZohHXYs1R5p+qsdLh4XKcMhBHjHfuJ/ca/+qEd3ZbU3ruZju7ZPDlB3qoakMCdF7koVc1jKKSDdKExBTUUAAP/6cAS/fwAIkg8P0znlSyxCA4qqJCJRiCg3V0eoxjEEDmrowYluAGErI2AVR8hEAci4lKBWEIL2SUNxDV9ggWB0kdybs9D6hI8+oHGvBhORFFnXHApaLTae5qZpT1aLlzLIhoeWc2ZYAAEoStskAHAZB4LolQegORBKNhuICqAs3t0oDaCbN9H/DHQjygfAdrLYsTBctRxYXMosKC9tjgi4GDz7XN62iazYFpclskDcjk6QxiLJFHAHXBzoY/23lLtVC1RM9Q8mda9ws7N+1pd6QihV8XtXecIImKU9gENjmuONbrXfpXHre8+DxbtLy8GCFEXCFjvFDPH2s5FWO7SFN6+Ya6aNn/BUIyzefeBQAhBVSlKoFR5cKDIqXR2ioRGmTTHSqN5wYAlLxiYgpqKZlxybgAAAAAD/+nIE69EACMIWHVXR5Rs8QeOaYzzCU4iQczxsrE0BDQ5nzYYhSAAAtLmtkgyaxXj/hu3qAONnQqWTMDLUa1UCI7teT8/WspcoxXm4AwXYIFPQQa80wUEje3Y51uLNbp0uGXkfTIIRmKwVJE0FMGUtmTBUR2HIssRl1i4eBzVvbXq5SO5f02CacEZUWqUGSDR6wbIBFJFZdL3/bsoYQkQSAQCQKKKPd9736UgL//8FUkOPFADikCACTsVzDIQds18PATQa27KGNCACZU+YXh5SMVOF03pNfo+ayNj/mHCZ58crtehV6Pu9/6UX/4p6TYU///CyyfQn5QJb5I9YcJQ4rXyzUDDU+Y8UHdxhx0CI0FLAbuoe6aYSZr6OEHeeND7i+kKsO8jYyq2xd2/9f993vv0piCmooAAAAP/6cAQ8pAAAAhkc0h1goARC4xp6p4gBiMSZUPmGgAEZmO/3FtASCdttoW2rgmiMjZ2sKDYtNL1Pow+Jymu5WGeCod9Y5VmO9OjxFXSxgx3XsOQB1CtSNlKRk9s7keLXKWpyVVxXbp329YAAUhKStsF3Wz6LROOBIy8OOUBqT0xnZkc7IMXOUeed9dLdhXNfQEtgvcCRRgTBdp09lepaq1MUwWFVWGE91Bm6w6wAAECAcDgAAAB5VMgqNApZgGQmpGLrigI4tSJ/N20F24JXhXBzXVOsoHeNJCT6HLDUe5c/8FqAGgP4Jgl//x6FR5wx/ewBggkSDQ2qhgQDgcAAAAfMCITK6w3CL+4BHKGdOJ8OWtVnAoYsSEr+LQlRhyQ/8E6ABQNYEAHn/+B6B+G1Iehr//m8uLIBfSD/+nIEPH4ADOIWMFgfPOAEQWOK4+ekAIhU9V5sNE9RExgrTYec6gA3f+JGVmclDKnTPJFKqWF1GeNbLhBwHJqjpEZSOnnsRen/0KE+zESZzH1bKGa//r/R+OnwAESntg1E1G6Oke6ptjgQlN+MKiMQAailN0LWJZNOlKsK9/pARNKAFuKZ4/sSrc7VlX++/f8N9HG89uxgIV1V/+RiV63lPbxN171EerP2dYATn/FBuQSp8pLdgsojLrtRcNm9k/WsJFzN8mOucbU+ptTaYnXVNB//v3//8VzPOaqoaVz130VMQ9TuQgJyanSMj7rrxQRWVIfJMy3AlGTB0s1IisGKs4rRWa9T2tiIimjQukcTKMaar0FRLKl2RxvyPdtv/zP78UhM8GpO5/M0f/eOrZMuZuTEFNRTMuOTcP/6cARB8gAJAgw715ntK2REB2rnYSpGiGjVXOeccdEMmiuc/CjKJEe/AkcqrBqRIxZA0Z7roudrLKPCQ8cCs+1kj2cfOFn6xac2isCD8KHadP/0fjqjQ7cgAC23Rv71oLIOZmkSzkGAEAh2/gUG4wlNAtBBjGSJlZCHhDXWU3yC+4SeLfHzZEWzy2vGAmaixLQuOPv0Jn1M6f/KtkI5nLuY6U3poUeKdWcmGLCSJe0pYtx4rzYQIMusZdilbmxb/Ah3wD2xFvC5HH3ygdoZlBvxJmnFDs4YSvTzP6vzeImgLjFiJ8H32NQKwrpbYGpWAAIc34DcgsCCF7nTCIHk02dYOnYtvKgvagTLjTleRjmaW1bEYe6CzPKCB7cxv7f37tYYjlyFHnNuUffwXGLlfdDCGJiCmooAAAD/+nIEFsEACAH8O9a7DTskQ4dq5z1FiIjIw19GLU0xFxhr3PaV7wAgh2/AXZ+kXJZtyiNkUrNyOo0WerO6wQnhzTZp5PFL4XL48R1I6JxGvCJtW1b9B/+v9B3kG1N0M6ejTibf+ZAQAHb+BladjYFG1twkBy+Nl3+uzm34A/cYA3jbs+a2QFteMg30JpkA3P3bX10bl6+fgnWeyLpO6EzC8RoSZfoE4EcQAIEJyQCGh6IRHQ7BqVpdKQNe6Sd8APr4DJnZMdWxeaFYd3J8qT5UI3xV4lt27aedz/fXlCLiDaaImXoSLoGBCPFrWDBduiCJATkgC+05TAiTZYoBf1jS03WAbWqwpnw5XHKhQJzqYvnsqIGd7hfu+o/t16dfPub9RgOtBH5heFz7R+Uv44+X/dntI6hMQU1FAP/6cATGnAAEggMu1zntE2RAh1rnPaJ4iOzVWGecstEfmGuM9h0bBACHr+BVkYzcK+k6dFBGqzCJz3UInWIzrFVeTucdbEUX8rS76xKO7JEPo3bMM1V5H/txeZi1J0OZ5odHnZ7ncYBAELT8BriMNwS7EwvAa0HEGTMaxl7wRhnhyeXu3GtPNx0zvV9XtEc39hGDEc3/0fQnP32OqTNaCRQHhqM0xYAUQI98BIqWZDwdS6ypAaN4B8mBXWxa/eEnt/BINtCM3LupoEQ/KkPygC+OOUSAY2cM1H/2/jX6lZQg+OHtchVYTV0aQMaez2IADv/AqsSm+DqU65TJTV7SJNE4hfrAAf4Az5raMsRRnE5bXqT4sqg37c/uZqb3zB/3o7HGgcAS5F8lBa9KRvNf9qkKru/tCwYmIID/+nIEBKsACIIMMFe550P0QMYK9xnnDojYuVhjPOGRGZ2rDYaVcgAoBz/gSVdQy1vVdKvV4gzabyWzNh/hObi0vjhc1WL6lu/G3Kzpjat3/v/03yPdVlYkB1SkHlmEIiOxjjzMIjxC4AIIl34DDbEDGs9b0m2e7U4+9CJiYlMz4PWyb5XhQNYpN/Kl9Fi5htx/jr69X7bp15VseHnm4oaeyVkbEPEd/IIAFt2AKHaEFJtDzIU2naSGParULLJJB2oOT6Ac2KOhfltDtR3iiNmALDjmMI4nDVCqPVerWX05ahxgwLkkP3AIhXHClqXiiQg7vgKCliBKNtnw2+8h1YrBZvJwFHzIIq2Sz5c5ce4xh4PLrZzhZODTRBsU5H2bGpy8jZU1HM4QBdiEsrrQ7n9xd/bdesQJiCmooP/6cARX7AAAghI8V7mNE3Y9x4r3PYcdyF0bX0ecT1EOIuuc8446IAGXb+BKM+FazpZYlxOFV+WE6XYhcnczbPtpocxzI9nBgG1uyyt9P+rdP6/yPuB5LVcc4JFshK7KNf33UD7TxQHegBABNyASR5BorH3F57R2EXXpCCV9kPvqLOT4uogjjGU6NqDNdpXv069W/+nM48/rppMs861FLYhf//KE00EDECQQ7v8JZ4BdSkxbbjuHBMTX0ROsJe5HGr4hJ4XJ9P0Bf1vI+V+3bl/RenDK8ondnQ/3Z6mz6nRvV0Wx0W0E5rdUEEOb8DtMYXUjki3bVmHbWcHvUVP8qa+Ou0MviK+Ols59Ohur2ijtzOv/99jsRBnHuZFm5pfaxSq8C1yYjXk/7J4YdamIKaimZccm4AAAAAD/+nAE5ZwACAIXMFe57RL2Q0dq5zzihogUwV9HnQ/RFRhsaPSoogAgGbfgS0mhio1m63uNISKpwN98ZXM+ZO80Lcilv98nhanzlTM+CH1GyebYFbbR0sBaCPn1I+h7vY93JOW1Q631QUgBQw5vwJXdzNDwrGKIhOYDYTXW2oudsvmfGKuEzYg54Sub0fqmojQL27tp7/26cM+T2KrzI7OrvsxAq0iBu6fGg8bJAEAHv+BlwfoYIjrK+tadUS2NSm57AV45aONgocsUh/f9Ql60j3v2aczf2axu1xS7iu7AnCwoPvFM46LRd8e0llUAAZDN3/4a9Vgkc3UoOUykG/iYa9i+gXJuPb3bGYK0p18FHJciEVxl1bP60RV579mkbJFxNaJTJ5NZb2EqTFoutW43YylMQU1FAAAA//pyBLwOAAiCJTJW0eoTxD+juvcZ6haIhMNaZ5xPURkMqxz2NRIAAAgArvsMLMcZQqa3SJLKS3VGtyEF1cC7j+0uWx8WWaHdffQ3Tg+v327fys3XSYoXDHSQDgUQSW4Y5f6YrtvzTUrpFUAGID22wcZIoVi7gpiHtbhgeeoalpo8bHedoQDixNHf/GAatR7qX27BWg2JEIcMXcqKJRO6W3xjIoiqq6hkf8UILu2waqsoMhW4yugeNp9Pa0uSbdgKtjTldSAwqigG9tCWUB715Xyvq++31e1LbqzorCCrWxljXql5/ppqbfCMWtfK8eEAGW7Cia2RgN1Osa4EbbS8QQMVyAz6kSPLnLq6w206YYClr6uLhP6Ouj3TnJ0Vr30vqKgc2lCUtaSWLm0AxE4sKbwAIBRiYgpqKAD/+nAEs+YAAIIBRlg55xL0PcQqsz0qYIkcwVTsNKvRCB7sNLEO2obgB7/gSOWSiPPGEkdO6Ydj4IthriXxxMKFtCXbtqH/06P3ZltVunOzn1U7GOYCR1XYiurMt12oDRSOzU/f4FUAHLbQ1MsgyitMC6TA9VPFgHTN9DW1BqfEHznZwSFJjhKGnbRsSgVPk9Gbmclev8/rD8KhHrWrpDe37E8tHABBDltA9859JYm/LogyIefyn4UWQODB8jcZJ9o8zyaAnwoOzlzo6ZrlYThsytDOZ9R5avq38rVdiYo1RN1jwlS0k4kAVPX62lwSYAJv/go/FTzY4H8nQfSJ/qnb5ISvJG3RLCmAWZ7xu3bBCNUjW4/M+7797V9bl3Q2hnCLOTJc59K9m+gccd+p6q0xBTUUzLjk3AAA//pyBKv6AAiCAiFWGwlqJEIj6qdho16IpGdfR52pERSW6+j1FXoAOy6i7PUkbKL07wN3GhXkWif3qDajfji5N0QrxtUxPIGt9fMB96NlF7qfOOwcf/AsEMdF7uTIPCAXZamDyDaqwAgBySQVnz2whk7Y8GNjSMKCnD0fZRQzhJvjjZpm9EDuQXmhZk89qbEcV6yyMwAXRMTGp4pv1ZBQaaKM6E7mf9upYyAFbbYS0od4iWV47To0MKOUUm2Q4VXMNYqpqYfyzW/bODieet6FsChQwhAHMHIoHS5oZHi6lLJpW5T2o5FUYwygxQL+kkQArtsMu7qZBTbYA84cZRYxgM9RW5i4w4XJPi4tlf5EB9/1/ktR9f7mad9ApYOouNHHiqhqTIYSLMfwfodOCi35cZbpQmIKaigAAAD/+nAEe9EACIIQO1nR5hJkQQMq9z0rXIhQ62RnpEtRChLsjMOJ2gAACACu3482z3VVGxUFpcHSDYfQQh3u++7DHK/NX+LGzvnahD/J/9jneQjf5NiZz9VV6ETt6EaQQ8LCKq0DMn5uGAAgAy2gS4h4PtcMA5DphmXOOOR6HhJKzrftHOqXz0NbvFZiFrt+5+xomHBgon0A+aEHgCibtNnyjlajhQMpu/vpABdu4xqRJxNkaHoOHBbMvfCYeEs97Xs3Lr//kDRmxtrByUVqCyOfn//mztr+fnzv23z9fqPxcP9P2gAqfFhYn2B2kAF67jaMEpH4qLwM0NJ+Ma3AluJnlRefP7ZEwQyVbbQDANs9v/pxq8gBVbAGYD8/aqWOF2J170UUAksBmXMSWwkLDkxBTUUzLjk3AAAA//pyBEj0AAxCEjtaOYkpxESpSyM84nqH0GNkZ7TqURck7FzziXqAAAL2/EFZE00qVwoBtIZ8vljQN3pzKmyJwkwNERbUujUBGl5v/59W0/vQW2e6ZuK6m+pdBaVey5ithBQfnrwJavpAAd3480JIucq/kpoAvdRrY8F9itonO2ObH4vNE5zYu71CwS1Laf/wvE/9nx9H/TCto/WpanGnY/0fK/0e5meGa83O69AADs3Eke8MrKidrA1pRRXPc6HplCPUnnn0UCZoxCg2bbKZQVv3L9Z5Tkc4qrb/KWU/TpiBAgSbaJmRcylQ0rAADJdxI44Zo1TDU6ukED2QKtc3CpeVBDrwqMg5cqc1TdHwIgm6ttW//BPvq/07f+fRsn4TiGqb712+y9LxAbWksVmMgTWmIKaimZccm4D/+nAEAZMAAqIYJVebCxL0P+SrBz0KgIg442bnnEtQ9x1sTPMpSgAnJMPo9O6lhsgGytfzwqaWafwKI3UwNF/NPQOamPpdGPSi3kP9+8JRq95bkf/UTmGu0yFmun1VH1//loX1jiZWsokAIADsuEl+QWkhGUPKRclR5oO/K0/BMLaBStqsPBOCUyEGpbKcF4VNmn9/+nJLKi0hZSvd4dnlt2fRe8oupHtfBHb8ZjdXGr1aZbxsJLQ6sTghYHTUPypekLT6lbANWqMNXiNP/6tv+ui5i6bcuz/MHQDEyxYIPVchkQZGxzjKtSiVuwxPdbWLqUxkbIHTRONaQBYUjkoL9ewYOFXJNSLKNiqQ96f/zuWzv/P0b3Vu3/V8o8TPoYMex9Rp8Er0fWmIKaimZccm4AAAAAAAAAAA//pyBIctAAQCBjrZUecqpD5kaxc9ZWiJHM9k55xL2SCdrSi0iOOAAAACZbuF+By+JXB6HmgGIde0KVHglqAnQ2hedgEkK2HdGlHAtHof/9C7Nk/b8v1tk/83FbetNFthkSgJVhWzqAgABLbhmeVGpqVEE2c4Qb930ltAS28UZ4NvQ+KIJYotUF4C6NoSlq//xGKwxqer2ylGkRQ2tv+zmDAT+NWL0AAvb8SuGTmgyFVCPFvP67u0RFoBB6CX07MJ48ZlSWj0Ej8Vp/76N/x9RGH0M7q1x0ob5ud0eyl9QxTvuf/41Zv0oop76ZqJV4AIQACv34MXZcRoChc0qFLyTusJ7kQPz5/ONYGJbDfhj/T/+bUm7bPM6r1FVdJGanTVc74dutL40PgfkdpSMfes2CK97LjaCiYgpoD/+nAEDloAAQImOto55TrmPodbWj0HNohZH2ZklE2ZFQyrzPQdwoAgJXb8ebJ2R+unldFbpxuhsHbFt151CUTI1fLxMA8prVtP+rZxag7+vbbv++j/kcqn26RkiNJNbcqJ1anvTaqqq+meRgAgQAK//iVw7Y6wWVbgFui3khE0e5bb1Y+VNbX8dT/t/zGoHY7+p9y1ldtW6y6d6PHaOODAV4vc1ym6v127gBJWVIJ+ZIfLAb7s2HuAL1B9PFXAGEXavXUDN9pzjf69WzftquiKqUfcmlvkerLlYy7I68qMlluMZzUtdZzHgrqyGgAXbsO6wnnvDaFYsbD1GmxNhFi0MoTm0GcbNzCwdEI1GKjZ6vgSGsoXkPTEPqemitLlPR2OOFQ7Wi03S+Em2IUgwaPMctMQU1FAAAAA//pyBAYBAAkCBDraOWU7xEBHWwM9JXaIbJdkZ6SqWReWLNz1nOIAQBU2/EXj0Ocxo8qG3KnoH6BLCwbXwpBaQ7bfKhIbTlv/7Zjf99X7W26frrJ6l3GjFL2g/iCoyE7zrQPSFowgoAB27DE2D4c4K2IhVrJxqPneUQSXdV3zN/la/67gSxVh1TNUfgKajHk//l0fX8z5/7fv/1bHvJWTMfYqsx5Wr6AAZ59KFBdtruCUmjbeUmE8a0a+MfgOUVhQnwfTs/z//o+JDuH/5Pr/c/Mzx9mtfc//iZyDvMazcozFno3RldxoDu2uYGADv/4kviZN0KNAvgdtRPqCdtmFxONtPC6hDs2V1fd9sbz7/856BjKP1qXQ0ccQcDAkKLlnseGlk1vb1dEzIr3kxVF9zExBTUUzLjk3AAD/+nAEQQkAAIIPONnRKBPMP0Sq12HnPoi862bllHORHYyrzMwcooEARABcbgTHuBYS6B70hDcjt0RkyU3jfsQ15kFNp2t40Se+gjXitf/5xqBfuyyNlfuyWpr+oKyxlNNPVtSxDlOX0gEACkkA1I68aUZtFWb8t1g9XrWPQ/wgzhNXXbUpr31/HO1NlltsDtQM1eo8dQto8qXr+g0OcTBLZ+nvR8hDV0BgC7v+Fbx0l2k0zxNZYy8xEBDSm9U5UYlYxxf6l1agB/7lf/V9mzerG0fV7/vqXb87QE4CaUQXVetiDBwrbCk/IXFx7RQAF27DUcIpCJOSHbeiqvxh8xlqIrMdh5pgZ17iIHhdhMHPhf8Fpa4pJ+mRsxz8F2L0kPQ8OLIShwLLPOWUJoDB5jRQAoquRYmIKaig//pyBJweAAQB6zjZuYcT1EKHWyc9JT6I5ONiZJxNmRISrSh2HEogQBk33G9ITvb5y8yTMqhTqwMXijUrqveOSjcvy0qEz172M//bBd/+hsj+SZpXnenIJEqmod0ftIjzAB+xMQwAZtuJbVU7lkwSPtQh/LOtYCd5f84Z33vvQ9sPIF4z8Bj/P//LoTXzLfNqbfN7f8nEJLv3MZuIgITFDMJINiRCEAFTb8d1mTFg+B6CAE0E0boKCd3BfqQ0TdonnG6E9GlQYXrxtf/4Jtv23Imz7btc1vo4p+tTWzZCXWnt8ZJkZVd58CuTBOcRQABYgq7/hSEKuYVA3GZfPaOBtnIPQNYoafHmKSpHn9sRU3zP/76EZmu1EhYo+5JSBRGReGc8KKQt4ofkjTQkgfSq8BbUxBTUUzLjk3D/+nAEPAcACAIRGNo5KyqUQqdbEyXlGIgI8WRjvEVRGZjs6PMI4wAgp7b8VkgdFuH0YQo2meV9IJs4Y9R/ek8SjRHQZ8gROEbSj+LB0i4R88LGOptrKE4nuYTTMP2NUIkMLgDayQNnTwAU23HdQ2gJAoBjtPdZyv6hMAsS4nn+zxoK2L9sx999P/TR87/SkkqNqhi9VopH20uJnh/fc/jjwiUJTw5iEEGJJEQCrvsEsDoGXquLTdpViBvrs4taT2oNvpK4WFPoJ+hW++b/z5OfpRbO1+7VK5ZFdDybszoDSMu1429rdBXWzb0KQCSAAPf/iSLip9cNaDHN/BR/6OyFjcFt6MWpW07cm+XRv9A7QQLAB/Kr3eptaRn66i+DtrRRV/99nk7X7hZJtT32n+0332mIKaigAAAA//pyBD1QAAAB/iVYmYsrhD/DKuMnBxaJGOtnRKxF0RuTrKiXnEoAObbjI8BiMZIAPDruwFlCnCCOkNFfGj8njJogd8H04v+eqt/qbGb6h9r0Y40UeqwlcdTelXo7ws0ycqJsOtYgAFW3BLcDy4eEJFaGo9pMoECUiTqBr4rxs2hMsFphZqiX+Io1vRZ+iyu8RWqi/21XGDlP20OAEIiUkgmsCC6pxAAAyDbv+O/QaM8VCIJ9ihe+toR8kXyt4e0KTgZVm6po9QL2hlcIN99S3DNt+iVb7UZdjZqNORAaMCHLtbNpbcXLp3jw+nbfxYAICAAft+KfogWaJ4eAS0SKmyGKHyD1SjCc0flG5b8Ri/3/+YhBmCxVlIFlhoWebkqO7ycKFw1wVCD2kL2i49YaQClwo5iEpiCmooD/+nAERVgAAAIZOVnRLykUQ+MbJzzFNIiEk2RnpKmRBIns3PKNIoAQEBCu/4OtWBh1JJoI/SnBleFAXBmqOydyxTvl3fFW+3/6k1/9tWs/tKp53QxtERBJ1MNkZs4ZNga5zmC7W/TEpgxBQAG7fjLvK6rg7x4D3O6yYygK8PNmyPGRFw44wVehtHwFdnf2XlnOelLl3NNIQje8g6PeEJwYmCxxiC4feQZfFAjJkwSbtsM1Yzjgp86yclc4i83bDCj94V/7vB+TkspqJhQTehtdB4Zq9CV/8TqMHBH1pWVcqkm0paJmCGSRnmY9Qym5up72AEABm/4zdjXn6fFnSqPiLYJkYwPhbZcMnDIjAhEUedU8tyH7al7dLBeousTta2C5lDOFW7QCLi4uohfFDjohkHNTEFNRQAAA//pwBI7ZAAhh/CVYmekTREPDiuNhhz6H0Mls4LDhUQyZ7Jz0iTIAGW7DOlgwNmCDbHyQidGSvWwxfNv8LbfxQcdLrFnRChhYK+f9C94Rt/9RWCnGMvpt1i6neNTtax9JRWe/vZkwAHbaN0rM1JL/U7BrXjfHwK1J7CDFQlKX139p0j5fi2dD0ImBwLJBaM76F7IMal5R3xPQQ1XrS/YdmGu0BN/9+vp/5MQBN//FITNgcFZ2gNLYPwju75ukoWdKDxaEbKa/71Jr9P/zPo+bvstNGWlWIsompdwZQYv3naCql7G9S9IeqB23HmiHkgi6DvOM6KVF6QX8wZ26/d0h32foVHsLHuFfN3sUXrx///3/0nRbd2ymwai9pCJOh5Ds6CbiAmCwoC+tpNiYgpqKZlxybgAAAAAAAP/6cgQivwAIkhci1rsMK0Q+46szMEd0iOhzXGww7REBDKyc9JTiAIAFJABcxyWlLi4RdkWEJduJBunLtoqVNXPq7M2oJw2ctJSLQetgpxdEA3DuFvEQEXGtChZytT8ecKKOEberWyz7kAFXb8ZwODuRgWJoZEWzPWwuaxfahYITUeNmiAtN5vfHhRq2PUeLDaGHlj67ImiD/TNDhWXRABqDalspdXUyZABdto1fkqvZWMtS8LlXInBEQ5kwFiGs/X5jbKRFsn9oexbY5RMCMXxdlawKlsrmkFeg6q7svHnESl++9obRJuZraYVxPZOOYCTMce0FbN80CTFebmxwFpMeurxDwoXrUyQm+2HtWwiHa1t+JaOt5te6WRObz+fx72CBQAE5elTxOPHgQpRQipMQU1FMy45NwAAA//pwBIKQAAgCGBjaOC84REIDG1oFhQ2IbHNo54UOkRUMrSjDCdoAgJN/3FypbZ0izKYk+Ea31CZy70HNzELVeJxyI7IPat2VCcrJfLvS46qdFnhdR1rSKlPD4ecEiTqv/5G4eLtc6k2XAAGAAF2SCy8JPkEaj5Blzq6ZS+gsQ7XoPVeLMAgbI2XVriTFvE31tVdy1XYED5Nqhdbxce+bSjLraYdbYjUqEW0IQGlv/xndVRYaBAlSTbo9q9HVXBUY5zJTdXUM3If1iX9qhij/75HXcpWA2lb3xosbnSEco+mtjBfydeLlEruMDaADdUgANIBF//Ev3JrhwC1S1kL0cjrK0mNIXrxO1DYxpPFr6N9WvByV3ylKbYBD17EOGGUElgELSRlVIiGvIyLCdVzl11lVO0JiCmooAP/6cgR5mQAAMegc21EjKrxCwzs3MCaCiOh1XGwwq1EJmGzgwo4ygACQIqWSBOFE+kyADJMqWX4+gkzEnYn3UwjDA0hx8i4m04O/zjlO5l6liHjGmIrJl9C91Dt1yvMqbXkLr4DAk3/8Q+JokkQahqJuXVM5cXfYs3ucfREnkWfsh+VnL3989GnZOr/Qp3DoweMuKpB5C8WqIE9xIqM3wgsU9tZabjwA3baN2MmYSsqvHSlrUoLBQRpEZXt4jAz2ySmuNt+txHVGcWHJGUg48z6tGhBa2i4uc16LCT6kt0JRT0v7LmkX+nOufm87mgAAg3hNjKC9YRSzU8TRcNpgH/rNRdK3GBOPQNiGratgMHfo//5dD7+UOsay7+eDAaTOdpJWsW6dK+dAphbs6aT5UimIKaimZccm4AAA//pwBMXUAASCARlZGE84REEDOwM9ImiIvJdo57DmkRcMbKjDCdoAG77CNhEzn0BNsI2m461O47qBZo3yzlXOR0B+0QTzO/bFuSKv+J7xLfGqJ0HxosDh0AA+MY9wteh/or+uKfFlgBTbYeKiWZAnqe54IRZcr95B10Hwt+v/UUm616QXLakL8j6/gI/Kr9dR4wrFkCp21YJm1aZJdkXI4AmbnljidPTAClv/xjWVdGIEO04ha2LklGOjpDIbOVc1HQR8qxXq2lCgbGaK00v/7mJsTiRcyNKvfJDj5/Mqpy94shTn3LmqFU7L1uNKCAEmfbjOOAqU1Hs8V+PxcjwKJ8ipyRX47B+62B25y+z6aPgVDk/uVVsKICIfOBhDbmLb0mNIsKc5vNBkRjxdwuJy74WJrTEFNRQAAP/6cgSoVwABggMc2jnmEpQ9hJs3JQVSiLiTaOC8QVEXkuzckYmjgAEXf/xjeVbtRngSZnqgGvKX6G4+VwbolA4uCsPoulJn+UV8s8o8rnCGacmTnz7fCzK6S4DS6TTc9TQEHn1LfRAAEvbbhKQOB6aQ3xXEcG0sH9D8Z3UNq8PtR5uunL2aVMv+iM4xrXIfrv+h1/YuuhCDFq6DAKkp0w5Sxds2AUMTXtpuUI0EcecBctl5XkEs66wY6lgo8IyDrDGy6n/c1H/2bDDyOPwsbCZ1AoLiWxz5YWW5QoRDSmM2CmMFClQEZUKMcQEu//ing8WH0lWxFyMgZOgpnPFlHMG3euhPx2305RPziaf+2g+zvvza/R3fFYO/7j+GL1zE/A+Wva22rSG6Q1+1Z/4OH6TEFNRTMuOTcAAA//pwBJvHAAGB3hjaGC8oREOiuzckonaIyItrRhTrUR6ZK0z2FWoIrf/i6LOzkEWcVFk8mN42g/bWFvWgwWnZX0Pk1DlUMK9rS58z3FX1tC6nmDBi4Xpat1Z3mLehiUahVqAEBB3/8d6wYDtYja1ETzsb6iHXOQayLoRguMDDY9Us/OK+28brExw+YEYEGh8cReAz59ZaNecD0wpxOkXvI1Tz+dYtEAA7BJaHMM8B4hB7sJMYoHsGLEm2Cw1QiPoeE8vqmjxwA19GmN/8ocWODxe0gnNkQ0L7R5B6C4CY3CzeSWMWtAbKMzS112ggO20S2PU0RVK9qV4crobRiHyEAr7EfcY/cRJUB+vSxWINVaEEAzfJwFN22/+hP/usjna9GPzqPzJBR1dRtybWCzN+qvT05BMQU1FAAP/6cgRbJgAAghMu2TmPKTQ/QxsHMQV2iPxnaUeYqlESEy0ogwhyAICHdthvXMFIFypHiakiEy6wlapl2ca9R61h0XGI+O10B/wov/1XR0d7bIYqmdsY50OgqSZ64cfpOktTvHjNKCJJABAindsN4Hz0bib64QLDugxJiTMKqqbkxc1Y9htBkfACCtT/h5pZwVUf917/4jyodqCRhVq0htPQU9KPyGi0mgASALe//HmyuXRuiRumSyXkdwu01a017qxoxzCn64WBhzLsV6SJZ762AFQUAQHMBQfXBoWuEEPj45VNQgurFjaFOVMD1BQaoJA0dt+NRKGaQTOAdnI/a7jKwzJE0R5lgx4ThN+Fahn3/85ROplCE2mH+FWZmI/ag0OKDgicBkglJkaca15a80HlsYNvTEFNRQAA//pwBJnFAAAB8AjaOM8wpEFjm0okI4aIxItjR4zskR+Mq9zGiYKBgJV//DYaAoiII2qlLU4vXBOpqFE8eGSyznid2/5WtTu0TPGAkmacScNZOOYMBJLA7wRD64oylkmtYvStagAAgCc3/4rFSdgHINzwyipOPUJZ63mznZizcnjzO6APDFYNFu6AmyLFaTILVhgzQVYtKALyWVUJLgLllP1K2OchcAAAAp3bYNU/WWgvx4jyXVUJpvCdgeeGKB5LI5UUZs05q/joBDOiPNIV/49KjqYu1uy4YfF26bSR4Djx/a1iUpIXvecYzvgACFNtghWoQRgRx0NxqsRzHawTYKdnC7iQZGjgwjuR99NeYfWfJeQpR51CSixMSEY9hmMaIhh0459rBjimWADnS6zahSwRpamIKaigAP/6cgRJXQAIgiEl1xnpK7RBhNs6MGWFiGCNaOC8oPEQjmycw5WKABttoxO3D+ZQ2wRgURTsSHy6uXq75Abxv0jml9W06NIeptP+uMArfUd/8qrQeMeS2kqT/foU2VE45jtouhd4p2dnIvSAAGgAcjbGedKjUNSl8P0a/H5hTUcWI+NRpnRDm5V++vESfCxCq/1Ei6kcXRh2PunlFe+111a/Q+q0xWlzb2F77UEBCtkguAoMspReDUz4ZEC3DjzsM9TikJMqclF0DW+o6v/HjxzQYHiCAhofxjUHbYUPsaXIvVEj6GplU3lGJKtvWlVZAE9tuJjQjxSahM4t6sLmHlQKvCzZ0DKvZJWV2374DFpegLZ0nTwaFXVsGPoAwMpWtOZahdBH3TvEB6AhzxhMCnCsIk0xBTUUAAAA//pwBOD6AAAB+RlX0ewp5EBjqxM8wjqJJJlnRJRUkRwTbOiUCbIAAAgCpbaM2gR3IUwWYtA0bUUlon54Z96rtvEUtjfxkRa44gxtfjQoV1nW+dtRr8eMXoY1D3Pv0fZsa1Cfe7UAZtthm0C0QTg7kodzgJHg/FBf4vPdFCa7JOMrt/yk+EA6/GyJNKECi+ACKFpQKD2OfNMWJq3Dw0xOt50U7RS+tAEAwW9/+LguFD7yoREdMT21OjJv0Pv4ljIjep1oMHZvQLKV66vT/QM9mxsoLPJCIYlxGDbmDRGVYVciaFuLMUfGFlD3VLUvsNAAgkRHt9xcJkHJjIcn81uzmreK39DBqljuEoSjtq+/0yjAnu3bQ3/uC7uwyvsRxRGHhELqcGlC6YaTzApsXXDraAADTXYiQmIKaP/6cgQdxQAIgiQlWlAsKGw8xGsTPQI0iAxxZ0CkQdEVEezo8xziAAUIAO2SCoWYxPE1a53ZPLZWmmJdhmJuMZKzlbb8U/Cx+/9mBXiUkLJscQfuGSrIRPhvLsk4sD5w09KDY216G5e48SFgVNtsPFh4finlWmqlpKwljnwWwwIdNUEwbTNjfgQr8D3/lBaiJx2LqYwwM1i8uKXMSB2rfDEdeL1ilSf6wgAT334pVo0YB+ZzW0/TXizKyd3BauhPVW/wQCT4N7fAr0k0rUKOBGF4Prp11JoUJEgJ7Xk2yA59zFEkFanPH3jAG3//xir1qdqkkeitQgNwbqOaUlTDZdeYRq056DaraANLVV6kv/VJYsLKYlyxdbj5MLCm5RJ88F8PlFt3WZp1o1nunxqYgpqKZlxybgAAAAAA//pwBJCgAAgCGCLXuYUT1EIDmvM8ZXSINI1k5IRMMRISrJzBHaqAAIN22EHuiC8KlJsA3XoO+nruwK+KBT48YKN2G/Xwb9f/wsSD6HrDYmFxSYMRZjlbyKhritqBglWxmxaxjmhdcXbpBKu2wk7axo4KQO8x1HhX4Y8Ib4bR4PjAVFJTgIGStV8vbA3V5RT5Vk2eniA41MtFSTloqe9TY5JpvKZpMZfjt1+cgAHLJBT1hPqMUEQk44rp3IFgXdNHQSIrMnfTUj/Lu3+g8iL20wZIjzwQxKgXeB2wWdItXNmxR2pDp1bYqWOpNqEMBA29/+MR2RvE4RQzpW3G3n1D5HufNdBhr5zUV81FBz11N/+hJqkkMfOAmJLXCrQhWjVeYYJxTViI01anDnEwG60VotYmIKaigAAAAP/6cgR0nQAIghAV1ZnpEtRCxGs6PYIpiJiVXuY8ptEQjmuc8wmaABlto7mbApNSQl2JkF2riVorWW8SBv6GcuzEuycfQVQdV6btiKpJ+b+Gq/F4asCG0iqtDgUo6yChSi8ws19JhFcUAAJAAqWSDzwJY5RmA3WYa3clTzsGC5NbpGlZT83fI/aif+wLboQEhUCWaxQXFDpcNsWhjHQw409gvNcLJKWiOxgboIAnttxvsCtQkfwm7acTXWSN7rTId1WrGR4RGxB0O2veQENTs238pquIvfUttDxt3R6BY42SVeE8+KLB5BtAifAQ80RUswAd12EtmxX3G6CNFiQ18ZcRQ0QfSJ57x82R7F8ockMNO2uj52+QB+Aj6ws3IkHuWwax9uptuOaUPgUKkDb1qpqspMzCYgpqKAAA//pwBOVgAAiCFhjXOek6lEAEu0o8xziIQI1eZ4jvGRaSa8xnlGoAgBV22GaKdkTTU9M8OqCSSR6w5y8LXmjBVjUqKZwglF53eg35L5VxR7sNnqxfrQ5ZtI2pLIG7GPfQ2l7VOe6VAyxQAAtAW//+M6tFoYBRQJc6g/Qw0GjCCs0qXrulWu2nfCQ38v/9bopdRGAyKFWTJky1ya51poOOcuiK/jzLvgy/oAS3/w9W9faG+ITPTUcsvhqv1ccFsMDGMuwqKZy9u8qDoX/bX/oT8bMZ/6vgolPmyJ/ovGQZW1n3dMnod/rLADd/7IL22wcacLcR9BiGoY2ECwwssf7Rh/jAs0ucNDEHXbXvg/6G/9xrogicDQqIx/egGV4saLuAq4FFka5IextraAZK7b2GsemIKaimZccm4P/6cgSpEAAEAhwY1psFQ1RAxGr3GecYh6RzY0ekSFD9iGzoxBzmBLu2w1ZlLlSbjYIJIkdXFWnMYhUUwvIGBYIURe54dYaV9tb1Cr8N/Q9Y4e+LlR7S6UipjqZYplQxzkSGEGaCXW9vSRAIClttgykQh0LvAF6g4Sbbk1WFje4tL5opFlqDojt30TvUO0tVv/WXWtVCmIWLJmNGWN6zz1qkXC71Xbt7nMT6JAAVN/+JKPJItl0nC0uGLxJWZsJowMZFeHz/trkC+0W6vSkXHG7xRJlzRSK3E01teRFGVKo3U6z76FaynXAAMhKkskCF27UcRDD0zId4XcW0AqKMpZNAhB+B1k7rhEzBie9q3myzSMqWIlHaRbUKi5As7H2GE2y9DoztZjExBTUUzLjk3AAAAAAAAAAAAAAA//pwBCQGAAiCIR5XOek6VEIEWzo9BTWIRHdnQLDhkRIeLBz2FOMAgBt22GNpI6o7a5iuE9kAyo3om6k/ZO6krOnoKvoLk6N9/VGbtdmMJuSp5hrL6pW4zel4ge4o9o2AGjdo2XsfZu2r9AAASAJWyQY3uTn4O9UghBqHQ0rPBx1HQd0Gj3LVX17XAO++O/9xpOgICoulZJJQUZejMCxBJtZevSPFmXduh6me5ZIBS//8WhOfQhpBlJRv+oqVexq9KtV0V668ztHgCy9na7Sj+UaAxwaQFBRS2EhZDJh5e94mcxloqXcfX3pYtX03Y0gKv/4Hj1h2JEEJZhbhuvUa7PuTo8/j0rcYLizmxr5NWuBPwGC6E+uIi6LRE790ZdKq1rIdtXOlVPp6DvCmjcfllIcOaTEFNRQAAP/6cATItQAFkfck2TjPKRREAysDPMU2h/BlZGCwQVEEE2wcZ5xawACrv/w9FYsUeqvI+CEGIgHmbCXdWS6DBaNdTvl+o9/oszf7OsaO7RCbWcQfFWONeg0ULNoqahtpRupvTXTUAlv/xmz1iySMYJNguUFSW3MnCDzujo7oLu61Xr2wdtT/pcQCKd4DYtSAgwGAHHutLvGlHCouZK8yuYJB+NhRzUtIvCYSeOnURnZyCZa4szFqagvB9lZUdATyOkej6tUTyr/ikB9LlhUGSxMasUmUmSFwbBV7HopKGnmXTQthEQPrmrVGBTzwmJ2T1uIpBaa4zqTqH42LKo4mry97yvTVsY/XRv76+XbNkCSB4SFJ4WDUqdHDZQhpC9W1tbB6ByaSD3qSs0mIKaimZccm4AAAAAAAAAD/+nIEuO0ACAIWGVSbDypkQwRbFzzCOIfom2VAvEGxFY5raYYU4gAZJIMZ1N9qr5qqoEAKUMg+wsaYUbUHS8SI8tdinxJWXsEk8iKe8orLoIP+2ItYXez61C1rde1Lc+31sE0Z7bur/6YGBl//8ZccM2yYECR4VaRvZumAPgHllRq1MErhxqNl5v4//sDM4CUOeiwk9L0H2iBZJF7SbZhxQMXuWtC1DHhwxG+wIASrZIKbXOyQLLjV3JeN1vysiFCNRrn7tDNCcmjbN9f/urOwvGaYvHOjrm9bVzQstazBhtqXGHUGKa0pcQeaAACAIy22jVFGIFpEthQ0fIuDZNtjmTwPX3jxHYgUCorKQYy7NQVez1d/iYABN9zxCH7Ji3dfbdcfZP5sw1iIQNs7cnl9CYgpqKZlxybgAP/6cARw7wAAAiIY2VGIEixCg5rXPWdUiHRzXOekqlEEDGx0wxTiQACEJOWSDO5fx0FggC2xukinAVdQNqY5FqqQbKrYPNwM+LSS/CtamKtHtKngIJiR55ZL0ALprddcqgiJN4sF8Yt1IuRgKCnbbg1UhJaCFrBcFIWmH7XpkrPCenFXuJhvPahranaENHmBht+JK3+QvQWkszXPqvzlf1Ckyz4aFnjVcoHniwqwAgKl22GNrpLxRlswXhY9n3zODPOCecUxJ4adamxjS831Fh/xRfqS2tjQkPMkjzxglYwFkTox6bkf0WirselKLnyIweAAADCAVP/+MjXFioKloINskVjovoNIaFZQkG+ZfM++j4bwEvx7hWkE3Gn1C8MkUlN9IRMA2BqicVDjmaTs9omS6YgpqKAAAAD/+nIE19IACIIHM1e55RvsQsOK+jynVoh8+2BnmEmRFJGsDPMI6gCABSyAfaS1MhIwzgCegsWL9m90c0uYfDauoe0HHJ2/Ff0F//imR6Fy/tTyzZDqk5KdMw03OgwmEZUUEioG5IXcAADAKl22Hj0zCJAQcrTr04Sng0orkaQKMH9SXyRfbR8Y/KBJpztSUxwlDOQM4HQOsv8tFm3tQ+tbIJnBGELSe8SIeAXNuBKztjmsEyE5JWQ9lDFp6rk3RbvepOO76+4xbQRrI31LcroIcWUy/uFMUl1T639HdUOwoS9f/9UXMswl0hMezdFQApduJXNSxpiDCQp9Iilm6rpk1cH9vsitVFUKgRLqjfTfQaf/uUcSJKP+I1njISE+uejAspzWK3XYLXGh5Y6ZCRqyZBR6YgpqKAAAAP/6cARpEAAMwfswWRmDEmRDZkrzPSI+iLSXYmeYSNECESwM8xTiAKm34hgLhaiEcCoN0TvTHKixllc8VRR099wpgmTt9OR0Gn1/crqiV/bp1lMoI4ZR+ZMuqBx7nAkZQSFe7vR9QATu2DafjFCQ4LWEJXAUahFNqcoGGcKbneR/x26iNy0PMLo4349kggEpHq33UbvX/+qrdyhnUME76B0FjKDK7VN2VawUtv+MxCMK6coZ1klm0DJ2nSAtwp6PH3q41w4kPKrL7vogcZP/QMLKqCjuZviz2QCs6fHHy8ulgkn2tEYqEbWlk2MYn7Fgp3b8c0duoJPVGQ0gk5SeV6BNysdJC9SIHHjGEVKg76iFUcYGmXt8WSVK7/SsFoduX+0YJmB+zQFSyUQ2/rLl2JiCmopmXHJuAAD/+nIEJI8ADIH0I1eZ6So0QoMq0z0FSoiAc15njOmRDIyrnPSM4gFN/wPOH0nKD4GEmi8vjKNWsvjdYR3W53ugw4OkbTX5xb2KOFCaflQeMC07SdLAmq50AKPkZRxCxQfsHL1hgBG7cDkub3BaDYGEEHNmlnoOCilAHZwPVIslaepIMHxzxmTvUWAphhv6BcDN1WZRoNKIpHzyptqWkmBpyjbljVPCiwDdtuO8LsWBbDaLooi+wBYl0OkALjH2wynhkAG0c3b8s3oERwKLDDIPji8UayrHHyyEvRdeqm19Xq4o8UAqUtNuPQEVKCrd+BgpUiyyDmYAKR0zFVzIn6FqDQZP2bPMbigNXHBoc8z8KYhiwIqE1aS1XL3OQOk5UULsSsckEFF0CIc1iAMczCYgpqKZlxybgAAAAP/6cASUUQAIkhgc1pnmEpRBgmrXPWNGh/hjXueUy7EJFyrNhJTqAUt2wxKnyILUb6BJ8ZWlpJfBnQBngRBljXXBuHa7mp+YoklMIKV5W6yuy90raoqRCwoPMmkpOrLNay80mQ1kSVaUbgAgBXbYYHmd7O9J+lQgg5pzNA9JIgyCHAu22Cj2ElC6yDuK9mh/xLALEOvzRcQpqqPIPmzZKphhhs3JqZ3i5sfaoICUkcHsQNCWkPk31QeV3beqnwto1C3cnUhxh5TtRPjUKPnhpH4oYArtKvoUlqo02EQJqpv+lyEELQG121gWSsAu7Wo8Mi2naxgOiGx8Gj8lkJRYQ3xW4cy2zSYmxmKMBmzN6M9+VD/+QzolC67m1o6MIg6GhYoOUeYTi5eWa1D/doTEFNRTMuOTcAAAAAD/+nIEbEUACJIjGNcZ5hm0QcJ69z0iSIhocWDnmKWRDQyr3MMVSglNt+O9DvXaWQguadC5MQ2afQbNGF1wRdzj2cAbKXp+LZmg14YeNc9VUVKW926ZQ9rXCqhc04YQKqaNPhFDwTD42pt1AAgTN/+OadVuJFTwx0S9QfO1R8Cvysl9yLes+gpvLuwq3xZ504hz3w84SPLpOXirws4mi4MRiyVA221N0P3LDFDlkBc3/4+zNQ9mGwwWGwadjKedr06T7jV0Z0uV/3jQCauo9zeoTWttTF3vAQQWF1NVNDHPPRjULUo0aNtQ0hbsFnjtouEIvaPDB9VoewJKIihuSNcnOIOLcFTVZBlBYqU/Di5X60iiFBTJOUyG0BsyGoCCLBzqxIXCFDRqqgigJpYKFyM3Y5VCYgpqKAAAAP/6cAQO9QAMggcc1pgvKGQ/I4rnPShEiOBlUmekTREdjGmNhJXaCMu2wpOjHwaRYEucm1W366v7gjdxpBt2q6mECWGs0rU8E+o+E39VKvFUiboFRIaK1hkNi3Ywwi80JldhFKuPY1AAQnd/wOdqYc/IuQmEk+Xc/mk6BlcrMng2+utm4ObWL/4ADldXwYACHMAGYt1sg2C8Jm2pgWGaWF2pYqITxqsAqW2jvxOA0zaA3heKJToecykcm09qJAa3I4HDsZHs+2jD6FG6BjZ/hAo6JY99IS/FlGkuaICwSCyLULEO/2UP3ML3VyatKgCpJINhUBYM8U2xhPQQFXXAxQJd2GpbVVgZk29dAKStg5OM3fKOlc53qI9qhh9yg3dzj1J0vbWVHO6gGpLGp5+9mwb419uhaYgpqKD/+nIE0FUACBHQHFi5gRNkRGR7GjDHO4kAc1zgsEGZE5grTPGV3wDBK7/8TgnH7o0n0peIn/ZSBMkMgmFLzCw8P+Qn8MJvefVX3A2sZcnGbFISypjWOepEkeapKEvd8qkEBJAHLZIMJpSdftwbgZtG52aU6w3F/IfaaidenLUOCScYiEe391LqwJBw8achUsG3OJWpMjTKUiY1mV0TL395p/mqMqUFXb7iENKqFAVh4SGErMXjNraNBIPZhmR8Mz98v7v3uLF9t/hsaN7uppZudt322GricaSGkxt//HH3+68uv7hZxX7TQuX3isArNlMxNHX0iXx5BSknlgyR5SI6kJh7l0MqEDP17WUI1IyhrB5CrNnOrikxDy/LJTRaO5xlwR+NqE7m16/4pv733fJW0FMQU1FMy45NwP/6cARvRQAIAhcc2DmCM1xABHqzPSI2iHRzUGeEsBEaDqwckpm3AOS5LJBPic6oCxDNMsRmK3JiD6i1NaxuQOL69H84kKz7cUjINL6mXJXKEgygSizrxRrKCzDCXtItRomxfKSGbSPb1AJW24ZIY3k1uwrsInqIWJFxjmwQwF1S2jVcq1P07yjp8//5B2MY1bei+59mBSCTNc5WzNUuSIxUUUIYCM0gmpQIdttHZB3B0ESF8JUHWSOUyEKOtdEZug2bHTt1QpUoyMER8T1d0TVvw6UO+cDQJQaYxq/lh6EOxAwwKSCCkfv60O/+soYKsskHDY2ytTYbUWprNVUzvGcXfRlezPFyfR7AiaVCjZXjPyPG9pl+pNJEp+SV3F31FRSWW+T/uVdob/J1P0x9JvN39LxMQU1FAAD/+nIEIxEACYISHNdRbyjEQwR6wz0iNohccVrgvEFQ8o4rXMKJjgAANCd2245TEmRd1aTZBUYXs9VEc5cKjVQRdL2ejyi2b6CpPUVjVdYrYq2qtU9sUpVvWtbWzCCteNA6RZriSFnCuoFTb/DJbCNxZoCLFqxYjBW5CKzCHAxrmRerq+gvro+La+oQf/0cdyAaWkWJvZualREc5+s2qBUhpqQuFQFbBtei3+YCC7pGGqND5WkogpTWfOoqVBoIwNiZXW8jOj07dlRRvKHIgx1nTtHvySCoFUodfLKHLW466y5rzzJJBo8pokmkqOjnqALkcYwawtLfplJgTamwnfxikVLC46rfrYB0dv3y9KiVeoSBQ3tKuRZm9qLHsdqDrCINhMEhWJg7ZqRvpTEFNRTMuOTcAAAAAAAAAP/6cAQ7SgAOgfkeVhnpGcRDBIqjPYJUiJhzWmeMSlEUH6rc8wmTCd22wwwiDvJxdCVCGlCoIRxAbTYf+Zob3PzwiQEUZvFlSIoHXy2ZcxLNAuxKDhtLnVNY9Gmwgn9qVO2/0ggLgqbbAZJEUJD0ZISDa4YToRfOiVthd3LLoUZR+DGYEZpjZ++Y3eJVET+yGHZIKDSyg6CSkpMC+eyyloMXhSBmphpyiO247soTXZh3JwhZqSFLYUcoi4Eh7K+9mn1eqsqaC/qQSA1q58KKF0JGLap60Flss7lqaKTq7G9amHiqjwoLiQiJgCk8LlBV23AwQk5CPVLGQAvQzmIsM2NITzTKkKjMYtFsoyVbPk/IXsoYIVSr6yJPrKbW99mRmto1Sfeu+T7nSgM5kdcwSVaYRpiCmooAAAD/+nIEe4wACIIhIta56BIUQeRrCjAidYfkZ1zhPEExEZarKPQJUgAhJ7bceaKY2i/nKXIarcAfY9bGxMewMdUdSt4h9WROM/7f+4UWNitNRqukXMoF1TgsvYmWQtkO0Wy9h0REFLOihsJVAALIC5bJBI7CYg+yXnT+xv9ny1nGuFDma8ay0Z6/SOasqhCpb+jCSaE5AMRO2wfWLz1qRQwrmEFGVoFIvsF7k+buWCpLJBFnog35gpMXBG3R3ZxaFFbqSIDj0qV7YBz/QGI1GhF9jjYWTSXieAhoqXUQchy2RAmmlj7bnxb2IZXHBAA5vvhkjhBMLEFiJahEq6kzgRhi1dSzSRtqA7bP++ILtVne3+5n2/RTpNOUYPhguSE11uutJCWF1AkXLxR5tL+mhvF0xBTUUzLjk3AAAP/6cARSJAAMkh4UVZnmErRAgyr3MCJ1iNhzVGwYqFDxEauoxIjmCD22wywB3MyuTiHD8MdrVHlIk2l/CsDRjj+hb1DDRXmsq/1GDiWHiq0m0uJm2Cm15u0XPvH1EmMcNFiCh90coVcx1CACgtWyQSLweNGanaIfJNYdxXMaNQV1JQSujRjad6DsBEI+lqzBM4MFyg8PjAuTZtYaUen1uPme4KY9WpfWh96KQXLdsPmVtOLOtidJIMrHeEnpuAcKuFmGkZXpuSR1Htp2NEBql3KMea7zb1PYylD9Zs2GijBEHWrkhYrNBUbs0FZZqEJbjugZQVZoHGhsuSD2YCWTbEXEljZaTK1HzNTDEc07Kqe9ABXfilV2/weji63IHJCrydaRs6G3EVV80JH0KeSTEFNRTMuOTcAAAAD/+nIEY7kACIIgGVXRhRMkQkPa6jEoCYhUc17mBKsxBJGqDPSJEgAACBU2+wlMQh0fGo9GQNqroMdad1whBkqAOw6zM9TNX+HNoJelKjakgZhiSK0wqaMkjyVCQVCRYCsnlpbcW1UW+teRAACIJa2QDAnEYccNAqHi+NPpC/DUU738Dlj9NaU4jtq4vgSr8+YZdyUICAkU8LnR6Dqk5eHDISMk5QT76XENj7LKUAuyyQTU7H1ZdQHpYxF6UwDzMFmt42V6N+04CFsZ5xhU41Ce7IkQQi4dNQ6dGCiDzrAkQoeRWsFr2my9alwPXJpRHgiW20NoMoHqmkLL+eKiIdMyeNRBJMKAS5mOmCZE1aZwg7Ut8V+QZn9H6DMAgytttRZUq9aVISQdNLfd02erbambTEFNRTMuOTcAAP/6cAQ4rQAMghwjVBsJEtQ+xLrXMKNZiPytUGwYStENCevotIgmBUtto+RDp4EbVGduEAl+aZr9Q+1+LXDwozNp7ve9srq3oi1tjVF/lZSszP8oxgUWEmzyUYpHuSfZFEvI1M1WJ6k/+NACEZbIBgAoWvvF0vDuH1z9+4LQNzW0Yu62vsFu5Fr9I/+uU5l/6hDa0SxZ5VkNQKNInnk2ZJxOtMSttVHlo8Au66j4yVG5zY4NT6Y0fkr7Rsks4oJvOzJ28DQdRYwtaMmvbL+bt/VzyMlivoxTGDFypsQrAlb2dyWKNoBQeDpJoVeXNrd7ygMlKWyQYbHTcVCwNo7Wy49hWWtgzJqjSbDiZt5VmFEeAlFwUMC6w8QL3NmiASRk3GQsUMoWWGkBG2pAXIM1KcM2R6XJiCmooAD/+nAEKSsACIIaHFY57BFEQyR6xzWCC4hwcVTpMKUQ9Q4r6LCVRgCgO7b8ecgJFRB8B+Ig34oInerj+blS3Wsjrt/ykXbFgiwj5N4nUkWfYymgCz7dVabBOKJITaWoCSQ+kXqSXNFEMeUACCZI2wwZXCOrVFIfCK6MG91RBlw19GbXhtGpqvVvcPdWb3lZQQMERr5ZgSToOhUipLI7NY0USfqnlx4x03eh665FwwU7tsJ4gge9BrREAaPUAfnV4j71zuqliyUUisR1qOLr+R/gwz4AotUReIXnw69wxDnGQhGBl0ji48J9yXvv71tCB9ANFKSyQYnMF3SoER4cqgkeR41XeRkxquZmdhanXr9Q1h/ykg7bF02gdxIVqZHGBQ1DulJ9lLRS95inHtrNpiCmopmXHJuAAAAA//pyBHMcAAiCFRzXUYMrTEGDqoM8RnqH+HNQbBiskRUMa2jxiW4AAFgWpZIJ8LBkqH8PS3l122lFTFkYT3tOIXyXrNmfpDUvlH/jTb0j7RceeUMPFBAKSK5pbz5+19z7WNLbnIke22lASlttEEFQZjtwZFUOM63IaybmePtrEd4hS7+quxaufJ+EI3IHhTidCjECExEzyXucmWXtiKqhjmVzCkzdhtqRfbaCpLbR8sKiI9DZDlYF1lKZx5caS+25agbMplSZ6p3G6lTN+Aq+oQHh5j9V3gNCD6GtsWyfaotXopQje6yv5enQBYSskkHL+uqWbEmQ5JvXkUelFCln2lsoMuGbFDCnp8wx2WICY8aW0F5piHV6Ev7hQUcFUNNrMIQYCusFUoth19K1BTlVJiCmopmXHJuAAAD/+nAE6Q4ADYIfGNQbDCokPgOa6jBiWYiQc05sGE0REIfpjYYJIgFJbaNZkpmgvOW5T7oGQVRmweowGUGI2QpUF2HR31GF7f8JPEKwUNpYmqxfCwZQOUfMsFosLkH2nOOCbHPpSu235l/WAABQRtskGiZBFa5VEQua77XgoJ5aESqd4CXyPk/M/xFtGOignQmThd03gY6iTGKNka6xcJaspc5SSAY1WdACt1UR2JkxYRSRSg9xp9/KaL6WHFDwv69pFI0rWx9xNsZn/bT3RxhC9pq1oQK1Lcw24caSxSrqwWvpcaTYLL4CQh6UIQCZbbRcBAaGQWmfsgG0smh4MiqYUtY6Ee3v47nXthACFB4Vt0vfD7EKlqgMLvFCi0lWpkiRI2yNcoyLXS72NX9F2QR5hMQU1FMy45Nw//pyBJVZAAiR5RlRmykTQECDquckQ12JFHFa56RHeRwOa2j0HOYBX/8Dr7qZg8FyAbgAClxI2wUvljOUgLmJCIEqtmYkLE4enNZ3WWYQMUMv+wnSIDPwygBUIRyTt9f7LvioBypLZIOBouy9UFgNge5iQyYsW2my30Egunmql6BRyPDuPPLNBM6TjjAowOqSHK6+sBDWIF+iH1UVvvPI9AWYhbwXJZIPQgZ4umcyHmc0o6A30cftVGR+hdGmejRBv3eddcB/f//jO8tT31tKEgHryxWMxlvnuQqr/3jot7vq5LDqXXsZ9Pb/7HAwKcmCarmHOpGMVQGUKkPpnizEIMfX0FhceMmulG0dISrV3Vy7vQ9OfUi+MKtAC4fMJWZYs00g4cGQQjnACpxIuSFUpehoHTEFNRQAAAD/+nAEBQ4ACMIdHFbR5ilEPyOaxz2CDIi0j1tGsENRBQxqjYSU3gABhDm3348EKd6mh7ooB3QrbEOc1lZ1ePo32UUMyHer1CjaNEg8pPRuc26TKJLjAghmuuyo8BXBo69iryrwmlXc3clQBg3dtsMEPL7cioOQaE543uj3d1Shainq3QkvctDZ+KH+BGh/akETZApS1Iqq9FaaHt0oWxB+LL54WT2WS3xYlw3f/+MFCLZSKSfVByFn6pamrLVUhRCoQJPatW7vXqX4Mr1/li5F6BHijBLaMGqB9V4DmB4eS6HRa2Meh6i1CWzCXmSVIKcjbHFYIjA9hrb8DSQC2iVS1q2Ai8ijr26NFkoMM6I3qCvY0IUczJoUaoFXPoUeNBEV3NnkEUisd7krFfRl2ClKYgpqKZlxybgA//pyBA2/AAOSARzVOekRtEBjmuowwjmIbI1QrD0DGROOq2jzCN8B4Tu22Hgk9CaWE4S9QugiSzAtT0CueUrOM6cqMyyvf6CTvtcU3THBEJDVvIJsHuF2IrTKKQy/Ly/+tyUbK2r0AABKE5bJBgN2FcjSPQhqlWq6vCe6BY1rfBy0Cd22oV6tifwiSeggMU7jZmPexVKF3B8zXXcBaGAJxNq2Crr6ICBDuXKGCSnoOA/1eNSj2P5E7jCrzLvXpb4mS5r0hb9fwjiKeoGkV8d8/NmC9amrIG95aXS2GPHpu6Y3DHvV3rO30Z+0BQKslMBej0Vi0Hoh5iar4HwdWZSOuiO9ydtdG+goW4RV8TRnbf7s985ckX/Uj7mOAvywGu6tsZrrlVrXb9yz/vYy/+r1MQU1FMy45NwAAAD/+nAEVdQADAIXHVObDDm0QuPK6jBiT4hol1BsCQnRCAxojaeNEAFbdgMZwkgiM5yISvWHC19+GKNC9SlSIzUHqHL3KNt/4LDZ+hcdUXDIdXQLIhSZ2B481sIRC4OpXScYSDLkpEpbe1IAIlBrWyQSOJS6INCmPC55YLzgVvnoN0v5CvTU0vSbF/mdziwsPNixkXC49iVHiEVQjeOehdpKwIKF0N307lu+K35EF3bYDciLDoCg9NNfjwMnrjCA4MSgwVoNsSlfDHTGPr74AXK4Sbe2Wv/6VJhZH4WJmasYbeH3qFjCKlUvIMOED48f6gF//+KExI5HZUErQHCxEbIhUi7hTN6icT8kYSsFqtYIMpD5xAMhPKXG+F0E5VsMHqlmxWatMVUM7bBZPgfI///9aUxBTUUzLjk3//pyBIrtAAiSIRzV0eYqVkQieqo9IzWIVNlQZ5hqUQkOKp2EjN4AAJgpt/wMsgUx9HGJyxNZrfavGa4n++wZpa1tM1lDNPOigAW6socGEud+/TLX847+ju1c3Ac/HqNT/X9/dzkzm7GP/gAA0hCSOMYDpa2iAJ2fhZgIylZiCGMAnA5wJTy+EDVujSZLUe4wNoUsBFh5JyjSUn0VGDpmSZF0HmFAmRcNUDUPpXNawXNvgPDFmA8jyNQeRd0VhUSwgTcco+aSwWecY0yBjN+f8KJb9Gpz//3WW5vLyeX2Fved/Og3zJlCGwSgE+/uauu0COCdmStTxyCKshecmOAJpDTsJqSQkQTODpn82jdO1EbO7weHNgAMiQ4RfIqeggvallY9AbfYo+3rOPDZhgGLpefWDCYgpqKAAAD/+nAEn9AACIIVGNS55iokQqOa2ikiC4hMcVVHmKtxDhTojZSJ2gCBObfYd4SMGiwBQFWqRmWFsrsWUReUlB6j/MtWUUdt+kJ8NhTxUe83cRyhuw2gQAIAmYYOnlPD/fcbMITdR2qvT2gABMU7bJBA4MvbBQEw0FebzeZsY0t7xyrBAh5ZB2/tOb1EOXXyThKdMYAdSk4XsD9KnRRcKULSsXMRcWtQARSbV0pBIJSRtjDWDjLzUuyEoYPG6WstZr4Pz2+uuzviLnXj5JB+j/Cu2LDbKh5gkVAS9qhax0VU5Ms8ObAFLNGp+mv33J94JckkEqNMViKn2eDMSmgSwLKMpYRG41PJRWou9da1bF0kP7XODT63VlcirRHxH4g238q9+vwVjChNRhB/sRLXaG/9NSYgpqKAAAAA//pyBN5QAAuCHBzW0eMqTEHjmqo9IkuHIJVbBYRPMQUK62jzHSYAAJSXbZIPYaLbEXbivM8ohTdtQyXqO1HeMOiVI//Cb74irLJKgKCI6ZItNoRUwSBM016VWvFhUGUKKoHDm3da77LusAAXQlZHAJSQNi00KoWxCacGczRy1msp3VTXmfz+g3qFHI6O6Pi/sHFiBzWEANcYejXjK34zW26seFiwIAGLODThoQaIUjIcCLJ4L53rOw0ybESpL0x1QcvwTZ2i3N33+V2GKINB9jmRhGAxh+uoXUa2UMGso77em1pVAfJqWyQdIt0JzMN4Uyr2P1+m01rbw+QaMroFmPK0c9GKxep+9/mjRwrokFwOUFXu6IhBdUwPIaZlMYmixRKzS5NKYgpqKZlxybgAAAAAAAAAAAAAAAD/+nAEk3QACYIREVbQTBBsQsOayjBiV4fgL1tBMEFxDxZpzPCJ+gABlJjtkgiloydrGhj9lN3lWPL8YwuWy84Jg8SOcqDVSXemcHlRGGWD8VZPTaQ2SHrqABsY5pEfaq0G5Efctsf5JYAAMlOWyQaISZ3AVEsrDPTinpHvtWxaj7wSsV7pY+ugVPi3+Hg7FxgcKwyOvFdzlNcQFHgKlGVOGmsYh63Z1il6Y5AlBO2MPARQIViSWMrn8iuK0ggiRZFgisQ35V94Vdi0BFyjHhlsmSM2pa98OhJNaRYNtV20ILqABMWepD5XQpAKl22EgQWCyLAQAcYDSWJsMWD4kHuSxmYDK96HdnL8gq8hunL+T/KnQE7tFZokxm1ZGXUKjgHJE3PSdcFixelz0/agcmIKaimZccm4AAAA//pyBNOEAAiCFxjUueUbJEKjKndgxVTIhHVQ57BFUQ6MqhzzHVIAIcm+2GUsHcd0VdabRU2aWOnS9QJidpu9SWregQnVuGUopzIG+s9MD3IB6HybAwSEITig1TnV2fqSE0C9TJw+12rWAQJ23YCsk1K7MXHUPkqm8lxe9bvDhCq8Uy0f5iPQ7XTmwOnHU3RXo9X7aV//1z/vtXSam808iZg2RfD/avVP806pVgTu22FToChI4X7mcgWD1OfLHLCysBTnz17KrbIq1xWq9sB/EA0UpUokBTL0mXFHC4oRfEdMuuXJXxWQUAb3yDkKW+1bQpdtsOLyVLrxLxih2jUb09tniDhb6m1Wnb58yhbt1RQgHS5MsH9MiRBUqXOJJEJzF+Ta0C1Kgcy6fFEpX7Gr1IUhGhMQU1FAAAD/+nAE3ygACIHeGNQ5rBDkP8Jqh2ECUoiIdVVGJEjxERFrKJCNtgFAO63YRLwYhQA0cnIIAzhNH1+C/qo+xNMghRuh6H3/8NaoKiJ9NyEJWKClkxMbfr/40SBCKGuipGkWoACEZddhkruUXHVKhXhZk2vVu1Yhc4N4i9ldZkNvUQwvyeUs9kwttOKmQ5NBBdzvWqOfIgOMG1EEBLoWQWuloEGQF2RtiSomCW62yGG9DMNsSeYw/iNzoe3izOnTXplI3ix3DpEITx5iSZZTlQCNeDpJAHBcyZBIlkWPxb3PfQrUXWu7oBYJW1yCwEUonEo8KF0hXX7UIkn0OVkJwTBmL5teQgy+cqamOSHBs0eFkuFiSBUzuF2e+wJNMR5YJwKYelLTSK1KfZaSTEFNRTMuOTcAAAAAAAAA//pyBJGhAAiCGhNSuewZtESDmsoh5ReIGE1TR6RikQgMa7SRIVYBATlktEhQkjEqQ5XSgWwLLi2vcqBvtOzwrsYuCfOmd9xgdE0usBw0JmT77Q8hKr3+v+25raToshzjrTaTrSVztx1rQAAmKdskgwyUa3EYO6dpqxXqGSihivpO6kxZ67p29QsV0xUwQks0Agaass3H20MsCUeETceog5QrWTvfUEzRJjtaZlGkQg3dtsOhR3kxDFHSAGKFJcQcC/Ms4pU7xsqAhsTuJyOVFmNVQs4gXUMnR5hzgLTFip4Zm1C7iTErT6F7qoy+yYALhc1skFlvjIiIDYq09DF42SzOGR4x7i5tvmeGr/Gg44gsyDRsQIrNNhMPy6CZsu2Ab0s5BNnPhdMWat+Re5nejrTEFNRTMuOTcAD/+nAEOHcAAIIDI9bRgypcQ0MaqjGFCYgYT07mPKLREoxrKJEV1gAWrDdtkgk9S2NcoMSzJDnDdCIpFs9rLStQia7tvYqf7Xq9p4yfBxzhGXYu1WNGkC1AGc9xlF17jS1jk9lNXoLAAAuUZI2xgUoeH4XqFp+mJ97gJGHZw/4WPYO0MEKNvSyroC8gV+iBSio5LSMsXWpJ4eSqVOocXF7mX2bSioB0rTcgoAEKW23DQiQxWmrrgUb7MeKk1g3PHqpj7bMtRrQ5oC4EHAu0GAsHGgMoSBygLAQmERxRoZp/dpZpX99DFNsBy7JjOWrbJBwaXtoQkYlBlUTf6nazVwC2DNC3Y9Wu7zsp9A3hoUc49EahG4DvPEFgYKEnGgALF22sJT+uxy0NOtrxRjyHQm9MQU1FMy45NwAA//pwBHcsAAiCBhxVOYMSLEKh2no841CIjE9XpgjHcRSG6Vz2CNoCoUskcEjCAGwwZThUfyMy1JZoqWm9AGWpy69sCMtjoJFWB5qECdIwyxDapxNilgZ5gIVD9i6amruvomZsVYhuZAAAIFS27DBEKWdAQR9rA9DePCDcIrBXLKZA9BJUqC9/lm5J3iY+saXi0uv73e0D0PCx+XNjhRixfWuNDAfNikM1MUATClZZIMJ6RQe5CEAKdZ3uJzxvKUnGmBNvruhZleBbVoorXyA4+B2xUyUSbePasVS5ZgFFLFxKFUoKgIBZhAqgrDZjrQC5bbhCCV7nP8nhI0OBuEwALDPkGi9rNHdwd61ByFr7RZ7FB53UOekKRc1IOWnWvc1xusXWadWLorzHDzhdzTABKra4OpiCmooAAP/6cgSxGAAMggsZTxsME7BDAxoTYGJ2iHRjPmwwqYEEDmsoYJ4eBNttopTMpDgcYIjOenYQNUHqMqerbvz9WmYPvAUgLdlswyxTjAW3RR49q5muHpQUob37UIqvfaS/3/1IX39C/t0ApySAR0twzBoayh1S4UmhkLdBqd+hxZlnLqXILZHS24MNVfBM+j/GNigDCowWolkFhuSMIAwAEzc66i1be1S5feu5IK222FADVqmA+FYXJdcj8wF7QMkslmRIZJYHlnh3q6Frb8xFljS2fI5fm0AR+968UXF4Avo93pLRld8ZZ1Vd7moFuu49i5LZIOLKgamQHCiyX3CMhCX5Fe0+YgCK0CRd54NM2mS/0FkiiliYPsNXjC829Zo4aedFGk3uZbS88rrVRsL9yExBTUUzLjk3AAAA//pwBFBqAAyB/BzTmewpRkMjmsolhQeIrGVCbDEoSPuIahzBic4N27ajJhc8hfxV4kCj/d6kO0NFiFvo0zdRz0fdsDkryii7za8PvdzxHQeTujVaqb//65v/UgV8rnWEnkZMtJ1QAAqSltkgsag98aYPXXDOG1dIldR7v1F2YrNWifEwget0i0nM1uOEyxdCEC4owyOctqnNYp7RtZAmjF1I1UvaJrI7eHNv+BULcsBGqF0kllsIUqrypgrICAKMAgB5UXydMTdaWXq8F8TnvrHZ8qxLvfbFwav2Ym79pld2avIYk3/ebc997X1vXDlGSNsYBmAsNKR+Io147uSLO9yKHso7P7gwXHKNH1UPwy54tkzLpznhyWEzB40XqejGdrp9Kzh1hp/t0UPnUpiCmopmXHJuAAAAAP/6cgQtMQAAEh8M1lEmELw/ASrKJQYJiFxxTGekRRENDir0kQ2eABB0N2WSDhpcL+jB85bvC1HamGOQ1rh+DN5Z+LCq1Eb29yw2EUA4DocEh1csNILgQLBsSKLrSNYOmgsJgypK5+9K9NAAIlpvWyQUPFm0BzGmU3lE+oZcNhlgiDZMHz4PKTM3qa4nHBYcSais3SkaLNV0JUZZKqnUusAiF6WuZWxsWioku22FBSWs0FWTMQli1uis0NU2SYPML1vndc45XEijFfCgFuCWYlVQykLC2SHBYAFsjW9qS/U1N3eKTjGkkigB11ZYAAAExFzXjgfYe9zZbdrzLQwDceEcSDG38ini3fL6aAwd1mociPYBSD3mYvMmFNS3Cri7lrSp5FVaSOYneFt7qW6LLUxBTUUzLjk3AAAA//pwBAblAAgR/hNSGeUbpEDDmrokRl2I0HFA7DzFEREOKlzElR4JS26iwPNxBRmgTFXlalY8eiahInMjK8j4ajk9McGUFtLQ3B3QSd5FI9CP21B/q9wwiFEiMrKhFyiCyvervF+4AMDC7rZIOJwfOwKq6nJARPAaD7SKW3lOUFoSm29LCD9RjdW4ceozARAcsVDQ88dSkUthIz887GPmluW3VtYMRoIEpJJBVB2HhFSBxS8hXuDItnNQ/1YLlfR5+zJkSDI7r/6cs3PqLbPea/BEvLfBpc0KqH1GPXteg1M0jNzes9V352yxlKvuIOU7dMCCMj1LCeGNHXtGuyLxp9NoO3kYSSiD7+9gVK8axoGuJCIy5gJAhGg6C50eJRqyrnDLHbk0naJ1I91tabZHNprTEFNRQAAAAP/6cgQd9QAMwhEY0BsGK1RD4yqXJCV3iChzQGwgTRD9DynM9gxuDUkggyAT4sIiv0hOjK6lU4wpx7NrzXX0C8GvQkJXkt3Wzfn3B0GD3zhM66CsqACKjx9IYqFhMSN61cWXYQSr//s3AHKdtkg4fQCdq0jJBRufi6k1KK6JbMoQrHVX4kLhmRIoaHqSCS7QxEwOOdAbyaQg2hutLSNxsljDDkHVnnG48m+xYugBSSSCUgg04ATDUHpd27AUYd+OtcqtCw9EzsX1YUXSLkejvjR+/epx23UUwVGktR+dI2qWhKdaetKH3qo16BnX+oN2RxjKKKAr1jB0MjJeq7onckoa3bf2nfgLxgI4tX4yDEV4MZBzGTps28ZpvfONSyvatdgBx6qHBR6RBW3R/rTEFNRTMuOTcAAAAAAA//pwBD9JAAiCIRlVUSYQ3ESDGoo9Ih2IEHFM57CjEPsOKej0iG4AAqSXbZIKA9QdFwa52jmR6ELW8qi0X67EqP/fQRpFHYRFQ85LSUkBBySCRU0ggMZUhTQGRMhEQoQhqZhUVLnGNjNqNYAAdBOSOQdQjYUBKsuDQJ8Wr43SiHZt602U9YdEah9exoILqm35Lef2KSxJ5KWavpa2VE5xw5LBdhhLFiyADUNJoRlgyoF3XbDIwmIYwGj49NzFti6uxPhwFzQIjr2VldMf/fEfx4eKisRmQiVGGXOd1L8iccg9NLWPFekbc9tJp6PGwFcEISsjbHQoaR4jzZUSGYCubrSpY2SJV3rN0K6sobb9BH4GfNBq98E6y4wULqLEZKmmbsWrSq0UXxqq31Pb+lKYgpqKZlxybgAAAP/6cgSFNwAIghol1DmHG95Cg5ozYeUYiHBxSuewRRD8Ceno8ZlmAeQ7bIBgEUIbGoP0YNbIHWlZah+0sioZbaaYPmMj/y+ET6XYVyQvKMurXIGb7vfW1PXLjtp/TkTjGd818H6revoFv0J222jS4IeGiFgTswoRySnNqPpWx4BZVvVi8SCUbiRKW8wOO1oJzA+bFDAmsQPMXPTudcbQ4ktLLPfXaxNL1pqZ9yyBO7bYcLpqKYf5PQNGTi4ltouM6NnyQKZGt9Kbn7/C+8d3UsRvEQiFljGC4fljLWkkP1CjT5LcVUi99jGscvQ5ou5CASKMkbYwjxdytet0BbT+EDgdhVfasRfjBpyhef5Z9y6ebVtcbBG4tavB+xrYU0qocaA0VVIRZqHwnb26FCtT0xBTUUzLjk3AAAAA//pwBFk+AAiSEAzRGwwRtEEhKiNh5haIRGVS5jxC8QyOaN2GDGoFS22jhQyqTBTCFEMSXcL14DikcyXJVhA8HaLAbHiYZH05amcajx1i4DOFwAt59jR41OKqNqmDYol6RBpaKFzbWRQFS22j2WDuYARzHCEST8QOs/xBancFYFg04LsKrcVZ5rKGIfQ1SDrAq6CSFDrGZzUWCwuoLHTDyvoA7Jmlx6yqlRypbZIMBn5mgCBKhULXdSiqqCB3Z6jnH9Q6vuj07XILuYHnP1CFQ4GACOAlYsnUbStuJwI5iUIMMZyXLtaaiJatuwQUl0yMca0MYDi0wBIewHEg0rnLWmYuouPw6MKjej8/hRQDhQ4I/rFyLj9E+pMZDJQppcZQokMqacBNWx/1oCOLGG0piCmopmXHJuAAAP/6cgSI+wAJkhEZ01HpEbxAQ5qtMMVXiARJTOwkpTEIDmposwh+AAAIJORtjIuDCZBli3loTUTcTqQuu4TZtXUERKqWlDbB/oUVyf33LUkwm2IxdDhRd8USHW3l3oSPaXhfj777w/P0gAAFOIpa2SDUxyEVWIB9rpEvNSxNR0h8pDURbdQ5VuTf9PwSpxQNPJ3nwT6UFjGFqRVUUYaFkGFWPbq70Jq3/WUouaYH7pxwgOGwDmJhR7NzpdiULarQxOJs4m4WcpTZru+LJtcXFIRsGvPiVpQpMG1120tHW3KeE1zlCWPU576QtKmuTQUEyRwgFCDCKCe7yhv5G7iXfqAL1XZvyidyKJIIg+de0JmyCRI47WihQsoZvFXqKxaaxax1Y9xJ9M019HkUxBTUUzLjk3AAAAAAAAAA//pwBEkLAAiB/xjQGwkq1ELiehNl4xyIjFdPR5hKsReKqij0lOYJSSQCSkppGjYHJDAAa4cJ1YssWGSZ8LCwBb6lTpnxv7dlew+yK/S0oK/Ol0ta4QGaYxL+ggsvNIYu81FW3rueE5bbRxiRVgXccDAUIZQlVMNZHvpWyqkaftu/ZTmYNE3IGHMsG9dQuE2WY1Vg5Q+mVgMiRLxI80LENUZ3tuRy7kuvqDUNSRuDBKZV81wpl2SzVk3WqvqHIbcGvfexR0eEIYgSyIuFGK3GWEji7RS0xgchbilFFTkYgre7a5YGHoeTLDhGwgMIBMW5bJBhZGkcDHDM1JK+nOpD3i8dQ9q3XUospZQdVUZZfln/fSMFASP1CkOD7lnw4BQuJwmUcfiou55BiwNezM06x65NSUxBTUUAAP/6cgQcKAAIgd8SUBsCM6RAo5qKPMU3iLxlQuwkZtEUjiqoJggmCUkkgyBRmxsqTkLvCwEVV/S1/ICs2ohhD9Jqw1itvYRcLSKsvhPSYE4oQWBjj2sLo3nPxrdeOo/TVuXUAAK4jsjcGFtyK1HN6RQgez7LB7PSzot0ZDRsb0KHo1KI/01cHMDA0zoMt1eituqw3Zz012M8qoXFBUJAmBhMuXGG5bbRcFivi8apSUq1BN4TwQiOpABtI8arCZmVofgkh9HUFT/+irFjtDy4ZKD1ucm3S1BGwqoRiqk3OHBJhZ25T2p+Nu0gOrLbJBEA+GKzml59pvh4iUml1x11QICI5wADGCo16SNfinu8BB+IhpZIaPWMUulYCWblUlE2wAABVjCpMqnFGsWTuH6ExBTUUzLjk3AAAAAA//pwBBKiAAiCFRlROeMTLEMDGnM8wjeITGU8dZKAERMMqR6wIAYAgLjiYGwRcw6htg7T/CqPC7EyeUynUDQiguWvvUKxtKo/2AhgSDoDCN7jKrarxMNhsTi6VnG+q1MqPag00cfMnbiBLtjcHT4O9U3XjYKfgYpNbH/A2va/qY4di+34d9Rs+LspKCgMg00Lg+bteaWd5ub8xjLGptoFDFAcaLiFp8mUAAocUCpJJBDoKYcBNtIhIVJInVYj1vabKUIiy+NTocmUSIHBNK8BY6qjrLpsBXZQJRU8KlrzG5zC8h21XOPNWza73MZsmQguNpMRN9hg8HxaeWw+zQZlWizY5QVIxLZzWjKKoxGOjbJR+0OGRjihSx5i61uoEFOY51VWux4p/tVFKGIcSCSRoPrZrTEFNRQAAP/6cgQmTwAAAiI+WVYZoAREx8wNwUQCiKjXf1hWkBEWGvA3CtICAAABDCAoFAoFAAA24qzAvkuiPbPyAR5eKH4VcE8AzP8c4Tgmjz/8K8ToKoB5iAf/hcAuhGHOMgk//83N1IJIf///eboAAAAACAnFAwHA4HAAA+/iBfkJ5kafjNibBBlvw1eAqBqiP//GfJIZgTmOj/8QAEBBvDNiwE3//lcvpGiRo3//9brTk+gAABCCDAcDgcAAABBSmHgZasNR4pc93DAFuFNanoOHITYpP0OCOBOwbAHqE+/8CggZ41gchxkT/8jkkkzUv/8+tcopDcdAAAABAYEAwHA4HAAAAtfcGWsajyXPeBCAjwINan3ABYPM8F+/wdAXMJACshdv/BsgpY1g/DvIn/5aTkmal//umtZRSIR0//pwBAUsAAACER1Yvz3gBEPHexfntACH7QllQz1G0Qkg7JymHkJAQDCjuGMybcoT1xKRQ1kO41ZdZn/ydkLfeKqvYwdcaz5NxcfO/8uW3sBqm9khP8+b9slTVW2e5Kv9lkv56S/eVZRAABBSUDE0jcy5vsv9LQlUQ17XMZs0VSA+IZECOk6ykkzGfOH6JifooljqRMfbp9jbodLoJdu3trR6P9ZzpmzrfycR0kBkACkZNx6OGoH4ofUaPhuPrHlUHEW1iN6AyGS1Fnml8qZxX79CHj18Y9X6/1O6/5bnP3/u+hNx7/l937FBmkFACTl/FyiCfGcFhXNA2EOVLcb8FoiUywu0BDm9HypN8nzC2hXkH0M0N5vt2/oWyolc9+3IthA9hOLf7EpF33JDUVTEFNRTMuOTcAAAAP/6cgSfHwAAAgI9WmhtOexD52sHLadciOEJWGw9SVESHaxoxp0iCAEKABJKagGriKDMWKrGqaYkFzg288+P5/MQ1C10FCYoL6keIOVfQSOI38Qijjz8vyP/0fqX7/zS+UI8bv1nZuFAJDlvHChqSlDGQNu1QLJB1lmobNYKMbVKMEtQXN6RU+lzQec18o3JfxHDtC/P6t/9y3Evs+nQSeSOk/z30wE9TOL1gAGOgfIrvJFLIvAQUNHbVXZEwswkf/zS18g7yH3qNAOFKgqJaC58qN+FC+Y+LhN49bPbUa8zo+nr/Qh5A/9+j5QmpLP/JMnoEQAJJ13GndlKBnPgxrJ4QJDQTl3jfpiAk1UDCeoCMsfx9soDno+CjatyjZVv/mm9e3E5PQp3fvoNuNMl1uWf+qKb+LJiCmoo//pwBN+oAAAB8zvZ0ExQVD/nqxoxp2aJBQdU7Eit0RGZKs2JlbIQNgAApb+I0O4hZEL3q+lQKxmBFyHiSFtZEGz4iX06vyL+Mgp+74vbn8V+j6L/+Td30f+R8oNcP8UlH2dErXAGIAADt3GtbRuFh4BT0XjyN66HHTSJAjrRH4JfQAXfypbQZ5RsTf68dbUvzvfv/UvoO8z+pPiM2pP9lPyrr+TRAAAG4B79zcr+GoYa2YFtBwzmXytSiLBZIpH2ksFXI+WRrI4WNMxpaofI4NhlWxfp6Q7uWGzFuTt/Qf/9V4QfR+3EehuMf+LgAJuAfZktloUy8VscbLLOTIECdR0C1dxDmWgITFaw5YVkW2SDGT0DPi7HjWnxy2wk/BOR8K6k5G0f/83FJbct0xFup60xBTUUzLjk3P/6cARkCQAAAgs9WNBPUNQ/J1saPaVmiE0HX0e1TlEPIOsc+BW6EBJABKWfCEvqWr4QSPP6Rf1YSV8g4YAmuL+C7v7B9MOEWXnhNFPJeJbdtBV0O4v9P/qQc7o39G0Jax465YfmEf34AkAAC7NxjcstIEKgsl5+bC1WVE3kHnXxDg/LUF7cLDNQbir4mP0X+MfUvPxj//MO1X/8nGOn+H4l/qPebaHCAxAAAUuw8uI0Vty4gw4UWRIOHxIefL/CIDZXGYdfCc+jYuHvCgbQvxv09uX6der//m8gbQ3n8ZlunHzfqPJZy3/VCAABSUDEzXHcW7qkAHt1GoPq0a5C8W7QEJD64RxykXUTnLHI0q7B9GyLPj+W+lznGPydurdv6hmrd2/QL5x3FunGtKJiCmopmXHJuAAAAAD/+nIEY0sAAAILQ9nRajvkQ0h7KjFHZojE41bsPUlRCaHsKPUJ6mEmRADv340lHP3SMDrIEYaNiY/ca8Kx04XiI5X20L8Z++I4Fz6NkZbtwN5jZUJP98oNOSLa+nIFtA7li39uVd/AFQSAAFW3gZdlWrb3ggZc4hGlak3GuYFYthiFhsb8/z8TAL7NgaH9+PtlyTygS6En1b/6m8v2bT34oLaG99hwtdB1K1ggIAMco+I0GMQmL8uAJHmZ6j2FBvUFKY+jS16FFEpagqUyg3LxLLYwEJwDC+VL5UTOf1bl+nt16/0H/ZtW/lHKw91+/oUhcFUCAXbgPuA5wm2XQmTNH79Zn7WyaCG2C7FBkSQ1LSoStjeUE/PC+fObCj9OXh+g/CdW/+QfTztp1AuONdB/5m0EJiCmooAAAP/6cASwmwAAAh9D1hl4UaRAqHr3PaVciFT1W0e0TZEWoiuomCjCAAUmAx+UJAlUaiQLnMNQUoR6nD3gZ5EWRxGFXQQCNGPEYX8RbZhfm8l9tSnM9tDP/qdzm1N69WygmZqtqiohyHxm9FUIAAXLwPtqvNmV+DNcbZK2QyzW2sD+nmJK6AwLauVC/jRXiPInHd+Fv/O2jf/R9Dcrd9RXhwdMMMryvKIj9Bto8AIBAEFJcOs5eIXusQFg9o9fis3Uf4sHrME84Qkqxh9SL5kHt1mZJm7RmLeTm6NqJ5/6L/9X5W1H6cI+gPhX89M+pcAAIAEOTYWiD0HXawQRuWmVlCVXQe7gDQjIzRme9AjfXi4O5CDZyj5Qt35nIU47zeUb//y3P/yTkxa5QlX9H0LXv+KMu6kxBTUUAAD/+nIEeB0AAAIHQlc56it2P0drOhlHLIkM7V9CvUFRJR7rXPaVsgEgEuTgdzh1V2fci2a+D3Inc1OF22IAUq6jbheP+MwVPYGzo+UFHN9tU4r0fm/+o7n6+nN0Am4MGoiS1Gt0b2PisEqBAc3/Hw4ZcIoA9CsSGShPybQMBcsTmaiJ06F9CP8DgZ05NsoW1Trzv/x8tqKGxr1bHB9jVDAIyKNNTPo3AAiGQE/bxBJaLNfcgsWFKVZq+68aPQMBUjcXifwVtrxeNOP/4jCL5G+rcTOd0fKEf6c+NTHjF+vN5pexwqynu/FFPjYy8XYm2AAAKs2HrDcXcjVHAlGFywfCxWshccugDeKCkh9B8bJFs3bKjbUJF9XCgXUX5eMHdenV9l/UaO1Dvf+i8PDsaCWLhqI2No41vj0xBP/6cAQB8wAAAgREV7kNKfRCJKsaPSpEiLEJYUecTbETIexo04myASQDLOBi404A/KBoTPMEGL2s25LcWQ2IOdMUsber6h3in9AbjP4UAPCmzPx//0FffR/4x+KUUSqbd0GUQYqCcXlCIggqWfjGknFeWxYm0YwwsLbRVbi1qF2OJMCFqE3K9C2VFTo2cbqPO/GQo5JL1v+cib89JFxKX1Rx5aqDlildiEgJEIACWpB4Hhq740b9n9yzdYwxx3iMHJV0oEzbF8qXeglcq/bh+CbQ3B9X5P/oK7dE6cOPwuwA3rcdIOMNtzEueaKV3tQgExCCUt/FZW5quwRU1KMScWuOhjiTngNbEASo5UXqtOgxsD1sLthx+A8nOXQT/v/8E+p+bp1PwzYUJ/Q1kFwP6Hv1X9SYgpqKAAD/+nIENIQACEIRO1W58FIUQ+d7GhnnNIgo91bnwOuRBJ6rXGec0gEAAKTAYXOH4iETezxZTkI6KcXCroMuE8IUQ0aGuoqti4vkIUnHvNL8W/6NoW6dX1f+vn87oW/kJfQghh04s/DSScAIgEIz78dZqQ99QHduNkz6+hbiVxM2ICbrEjv0GMTEOWfKl9H78qT0Jc3oZ/WkRi74a6Np1DuPlmWE14fkaNC6NNnpIQgpKBlPSNxf4WbCTRouQlj2YZJsqYtWJWVc4VUKkHXKXMBstPB2SwoGqFQ1zPbQX8zo+pD/6jb/N+s5NCPJ+UpgIBVuw+CB5zaLB90iXE5R+KLwG8SxhGCwFnoEfZtAzoJfO4VD9D+bzBn+nQt/8dL6H9eraDnIFsqSQpaGXqJ8xQmIKaimZccm4AAAAP/6cAQi1QAAAgg9VrmNOkRAqErnHac8yEkPYUWIt1ELHuxok4m+ASQS5cBJ6kThV/Qifh+DCL5jOnNZnxYk1NFTmVB02nEw34QNu+JxI5P+eJXL9fN/+pvHm1O/hct0uhELc48nE40BJAJu4FxASDkUZBWDFGJqKbVePbWKqacqIWoRd/Laj3bml9SXfo/f+pbr/V9B7szV48C/QSyFh0hPZ2uhHncyGAiKyALu/GeUWBiaksaceIo1x5b+aflIzlqSD6sAV/9BXD9X1E9unVeXr5P/wnVsGI/iRHbhMfZ/K9Rj37s5MznKUogkKSUo5B4HFCOrgHWm5FAl6eNeD0Ez1KHNg5ZFEL5VeBVsm2JkyoY404Z9Sc/tqn9G5evTzdhrRe1wOuEyMXRzbEJiCmopmXHJuAAAAAD/+nIEAQIAAAIUPdhRaTsEQecqtz2iWojhEVhnnU3ZG57r6GaU/gIDNKCe/AzLKCDlJRm3MQ62Y0F+SGJVRduG+ANoOaD5z450fKncl0bUv/Xjg1/+OCT0rNGvbPCYJaO+YOPKpvE56aBAAArLR8rpZPK1FkG6ywrALAetR/j23BQDcnMBzvkLhHwaaD8K+g3XvwZO3Lwh3cuqJww1ZP6NqGaBUp5I2tsj8sATNeB0fLoS3tAb/PtOEfvGeEug0LrE4J8Crb8rygK8RuzchyvJSZqCxxY4VnV0SjWPcMn689+2o9bzUIhrfRnW7mkjCTD4cAJBkAhqQeDxoQ7UEyPmrBoNrOlyviOJkpEsI0+NvCn1FeO4x9D8INjW1L/Tobv/R/fv15R3FKRz7QOkCPULxPuIVbzCBcXTAP/6cAS78AAIghND1jnnK2ZCB2rnPUVoiBz1XUeY7FkSnutc84n6BYAAreB1BKwksxaiengUE4QU0TkmY4HWgKGUEITaButuJ24Tc3jH0X+jaF7876evd+Tkf8gJztNM6y3jTuqiK8w7QIUSHb8PlfiQa2dh/wL4LKJ/oKnDINEcqTnK4WmeJNq/AzYx9Cc/8abl6PovL/n4z3/jG4dSWS8XayH2qIM6Lzfi4aEAO7gdjlajpx8ofSDCDuxfuqLA1bDIxiEhqU6cq2pb+Ufv/ltC/8q/f+VL9ec9UfKF2VSYwtw445nhCkg9cijQgE5th9pG7TJuguDLA0YTR/76iW2KgYkqHnGHhgt+pDjX3xAAa2QfRs0CnO6v3//NzcERHm2MMhoThG0vq33NvG27XzaYgpqKZlxybgD/+nIEpXUAAAIgQlYZ7RN2QWd66gWHBsh071zmHE25GZ8rXNMWhyAXrwMr0sIX98xycSz0E6NS2a87rDujUPotGRWaNnedboc7ycf1p9JsGN/B8QKTvkbEitfBenPxI1jhaOt8SYvSnuOoQAIhgl28CFDXsQURAGLR8LB2rcSS7Hg/GKDoSFihgO2/QY0EbmPlA309tBr05V+nTp1N5nR/5nkdEU/9yEIzPLUAoJJLcAk5qdkrd4f7OcuDCWReKtQIi8+oZMdBq1yJfFNomBzoIj4IfU3Btq2o/J/v16E1P3ZK7OGtFCLNrlH1d16/ZgdIAFuAXlpdTQMwC6WF5ahWdp7jibNSzJgeRizADgiIcKEeVsK8Dd+raCXE/fU/f34huZqDDcjrCnqcSWoaO11x+WFK7VEJiCmooP/6cAQ2TQAAAgE7VjnqE3ZBB6saJaU9iNTvXUaU+rkUnKxoBhw2RASC7eB1FaUtKYcRwuMXQ7yt3Q/hQ6BID89VKuyDrvErs/D/nc/xr/CdRH87fX4Ib+CbX1bEjeGr/hQNwIv/0/ALgoBKuQWwMBLU7WCSJnmKyMxql5XziNYzDDg0wuyUbQfxPp0K2HerYwM5P40QbVqoq2At/2/nfjpoiiwyiQ0VggECCQY4BKKjYT96QTI+6waSiy1Jcd2oQyqiKYJtNOZtUZ8mhOG2bC30P/Cupe/Gt1pJsZdH4+1pmwc+NiyrD5O1L/3Pz2QQTARBckgg+jl+AeuXzDF9YnuOco24JC8xyhFmOLdOIntw3zujXEAP+nHy3N1bo+iblU2a+pijhdQvLwIKofFxX5p9+pCYgpqKAAD/+nIEBToAAIIfOtfRLzmkQ6d7CgmHFYho5V1EvUa5AZ6rqDecwgAiEYKd3459Kx6+8gdKZKlz09+EPEotlQQIuOCWen1bQa92xC/O5TlPM5v//q+jdfbKI2Oua9rSE4QqP1jV3B4WRXrXABQLARjkFgXoNqA1SdC4ZSvn8QBhIhEQRRoeVZqtobwf/wPAOepvOLc7v1bRP/oT1Mf/6PqWuOwOgWciZq1E3LZtNJADEBAgxwDklHRJVqDAzR+iUH5r8KLi8tkAJK5hOyz+Ly2RC0+JL5XqT8/nvobzuQf0+O2+Q9F0Ff4z4Yn+EFaH3cpokCCpt8NwRGyighTsixt1LmcjwODkmi1sebX34kPpxOCDa9W0LNjX20Wys38bZ576s07WJy/ebG5o8a3B8kK7NSYgpqKZlxybgP/6cAQAvQAAAhc7VdHtK6REp8rqPOVbyKDtYUGw5rEDnqt09IkyACEgAJS4DCv28QmSjoNNih2Tha6xLjiCoqcYRsQgZW3fK+NDNRfiHFBRo0BOO6j9H5On/6J29/4k+E2kY2bbPsIsLyAtIQCZIB8SOGs1uELgP7RY0gzzinEYGJmrgtdPzaG4V1DvGdW0PzdG5k70Ss4nqKOlXVkPoOFmYIledB5/6AGmi7/psQIiCADJIMFVHeOHtbNCcq5It4qfEpsFDUeZynKtqNO/KNzf8v/fz6f9C2q0kXZ9pUbUUWEXgipzM+DSmmiLDQqpLEuxYAEEwgIBPbgf+a8uLCGPUozPSV4r+0iz2NhyuoJIegSh/xuL4JuC4Po2o/J0b6L6vRQDm9/4dsGK4AB1vDjHA12JiCmooAD/+nIENU4ACAHzPdhQbDmcP2fayj1CfMiE92FHpOixJhyrqDec+xAzACJLUgwqn12AVG7wWzChbinUD+IA2+dxcWeVJpKA55vEBbR+U6P35vX/9W/nf5H+OE9mTEd/bGzK3MJ9UAJAIAuXgekOLbNrBpMzLi82cTuWoz1BkTUURgvTKhQrr0XjntoH3To2pOH/3//Lyf6cK3acoEUG4HhfqBb39cAAFySDvsxZtbqRmZnBp1Y0P8e4Qi9Y8GnoW5XqX0F3P4qLaLx/kmspDu+p3/mq6acyi+gkOlK0ILTNVQGhND9PG2IWgE4DBTu/HQZDIGcT2aNuDNjL23+GD/rmv1Yh6WzZSVg16eAc34mFPM6tqT7f1b/8hzuideOFta8sbbLuLRDxdvU9oTzfee+tUYmIKaimZccm4P/6cASEmQAAAg09WFHnE7RDZ2sKDeU0iMTrX0Msp9kRHaxolZWmABtAgp7fjxc28mNEgzvLe0Viv4XHeEAyuX4b/31JyPoXj/1b+nZE6bz0H12m/oLbsjoAlFCJc0H1sHxu4VS9OxV0AaAMAz/8cB4sFIUGWzTfFztxfjXwsAg+jgxP0bh3p0H8/8aM/o+6nUpkbtGBN3U23zpU4q6FFI14aqcxqE/G45am6xAxDQSd344eSG1FgFuaeRm/W/v4CoHBo4RjCtUHFf75ScAmxo/Un8a3J/t/9H0Nyt03O9BjiZFwtc4bC/5usPlOeK1r985qGxiAakkFRTbRShwTkrY3m8T+dM2sVr0RgQq9FFfxh+JcY2FBBsCcQHagvf/b0s/RNN/ej4ozMUCvSfrNraiisU7tHQmIKaD/+nIE+p4ACQIROVXR6hPWREcbGgUnGYeE71RHtOzRDZ3saJOJvgAmAAAduA6xRznXdXMMlliYXEaJBke8ebCGDQgkQU+gv5nUvoKOQ9R/6co2hf5xv68H0a22lahth3Jt7Wgcyb/4EiCbGIkuOQXZ5PIillbQ+/M7jYgfPbKA9MPcCZLvoH8xty2hP+jan8avq/N1/5Pvrr7qPOsaEVixBlSUh8PmqNC+EAgpgDdR2eRFyxsAE85QaHxEvn+O/WKpBVMwp+JXHm1fQA/+VD+nH+ON3681t028UmaetK2qbypbNJWLXsqQvQKgCAVJIPijSNPcBbfYHj+5vK8fbQPdoo/zuJ31bUNf1biObq+ifeyWkrTdmKRnuzFaUS442x5QebXYy5hZIpuVJxyYgpqKZlxybgAAAAAAAP/6cARsTgAEAhA41tDPUaxAp7sKIYVQyMjrVueoS9EJHesow5XLACEAAERtjmM6hGyJDEr151ip3FTiBfEcNnqS8jbMbKiR15UbaG++Ub/7TqTdVRiVloeqV0foNJZw/26GJUp17ujpQDoIgOffjsY4fI7hOy6UZdvxDhYZZQlxP/bjP4WHOKcraCvJ78pLoRT3JdET5T/xnY3GMexu1vWzgL2ct+wfV+goBO3Ydr1CS6SiWBQQ59D4OLUk4g+QOsEY2PaSvmvlG4s9OENoL7PhhuP36O01foCZnfqV0t08G5Gxg4ww5awu0UXMdlooAGwBICt2E0QoggLkLxQdv1Cj33/jdsQvnD5khz35eE20bUvf+j8/93Z5L39v0V//xX3S2Daj2X2jM9/d7GVd5Vv+JiCmooAAAAD/+nAEefIADEHaHNiZJhpUQyMrGiTDPIjw6WBnpE8RCBKsDPSJYgApb+PJcjaXIxOCdezw1sQU+mEPEP+wlCcQusTvFco4Ge7+CGVlqJQ4U9RzVwx+IIEL7XULRS9h8Xz6YAAAACev4gujbRzEbZ1eymtiCn0xDxBe/ljpxCKwnfJy8DNbZtjpCQiCuh6wQsnFSjvOKDJdTlK3jAIKip9ByZsdTQAApdx5YBLHBcjLbkDo0oK/LJBPae6GV+HoL7HVRx22fhC82CBK71BOzdm//H7b/ro+f6I9Rbb61IuCPoDTbLeeWeS9KTAaGAAu3YY67cDybw+zjlyVz9RJegUBuenWOchepwVDA2BMRZA5kKHGqYXBnxIjb7aD6CI/C8jJWCJ6XG7YEU9YY/2WXpiCmopmXHJuAAAA//pyBBngAAiCD0lZOaIttEOHmwc9Z3SIuOtaZ6xNkQkcbFzziioBAAUu3F4c9NYNJLjmMhEsRT+VPk5UqdB0qzRsg4NqAaQbKKA877jdv6D4Uarfpobb+/mRPor1AiTM/+v/z2EwT90AAAXZsMXlVKgawZJD4jaf2aWrqcVdY8t0hrfzoBxsaNVsicpVp4Yer5Mjt/x7QjmepzNktW513//+U5F/uZLvLvU9AACktHmlE8SzEI6B7JCkAw50SY+swLPTnKjMgmGvLFuAneY3qj16JljtB1ecvgZq/9DZG2/Jo2v6vk0f82omGhXi3XV99RAApruPiVme5P0a+IA8dYv8JlIUmu/ngktomF74P9WxtdcwEvwGH1r08U1HwxG7GGwHn62XBP/wUq8p/r1iBhTt8imIKaigAAD/+nAEgGkACAISOtg56VLEQadbKg3nHIjQ82BonE+ZFByrzYYpUgDAAqXYePgoWSwshDjsXZJrqBP85Oe07nGm3S6dNUTMhPxZyBkKho0i0H+t/9tG1/P0b/330f9cqXkK+3YgvI+5u1ACFAQnd+O0Q02MArqwiX7pBr9DVnzRsiEeWlw0+GHlWwErvUJe2TTdOjc3ma/q2Z3/JZz7/u+JbCvYrql3Fgn6UIEzX4UFiFidhKGQ60Q2hh+J56Qt6uJ3oxVsqWNigF5iXySymFgulWxc9H9fF5xsUXoyZnzPy359P4nBphxu20fS/VUt4X4ABS3Af3TjxigJBNSxjrMs862iYK9eKj8qJjRfKkHAubfEFlHkAX3bMNy/26PKCbqa3a2f061ZKvm/ml1hpZyosgvRYgMJiCmg//pyBLzsAAwCGUfZGW8pXEOnqzo9oj6INO1eZ6yrGQWdbOizihIAJyRjmA1L8To1IjUicJiFrt6C1RSeg5eoZxd6JWt6mA35A2Y7/0Fsq1VX1YmpMn1GkZQJUxbroHqlE8Yzev+2fQfJQAQAAS9/xmbDAy4I1JUF9ZM03FJpuUc9oZrxw6vg7pqDajaPv/yadf0b6M1M4+w7u17WQ1hAk0ToaPthColbYA262DAAXb8PjirV1D7Cwcn4HKMKkWwFYeIWBHWzAym19AOahDXorM1gPp0ft/viHInz6js7bPL//i/H9sm2VtA1+O/tiugBAoAM2/HcG5DyLhhbgbtVj8xJG0imzIqsTofwtqP9OI053//PyZDe1sn6HuzN6fh3wKqeFRdvFzqHJFBQU9UwYTEFNRTMuOTcAAD/+nAEiGwADAICHFiZ6TukQIcbFzxHhojMeWRnnNERAh2tKDSIegCXduPXJNEpQPsxXq5IRpuUO/UakrDL+cyGs84Z0EXH3oRVhyghBdo2Ws2USF9SJL5gvRrYUlDH/va1qefazPvAkADLth9YbGKsYhsrabnzi30Uu+nG+hg7DUEcK1R8JZGmC/9v/5HKB2cn2bN1/qqlfpsw1iQ0QyDlcUFCKfv1MADm34+8GW/2FK5xmwfutqi3XBw72d00TTpKJieoPs18X6PcO14WhzofbEMPdWTi62D3KV1hFTiyIkS5zZoCmqjJlzWYq3VAIopAV2/G8AT2DZlJQCc6Wc4K/yJBtMJw0EAvh3q+H+42vPo3+ivBB8J+jZu9L5Pv/tg8MC6OgpNsrFjhNnYYWmIKaimZccm4AAAA//pyBPX3AAyCFxjZGec0NECkarNh6liIzM9eZ6TwURwdbFzDlXMAmbfj6yiFqGO018Qhf7a3lOkkfnZ3xomL5Ggv4S6PUpqtzAedmvqcUcWbvWeVlTCznlYpMD0rSUQysWYpqE9iStMgACpIB+FdQJg9YsHkE9GiK9qJ4v2LVqUTtT6XmVtna6xhayagBRIxRoTEJuSAqxe+VSjf8pFJruTLQsslt5JIetAAV2w95BynBBL4Hb0iZ0NIrubxgsq2Lg95wXSw16foCWUOxJuVeglfq3/76dvV2/9WoWdCqsXEDD4OF2FiCKL2aFi1S/pQYECbfidkdTLxTUxZEDUFOVIYZNiYJ75USuE/bCPKvcuvZv/ztQEys/drSGZG5dEq2jfI2KOohmPf791fxC9JVqrncHx3f6yYgpr/+nAEE7YABAINOtmYLyhkQccrNx0lKIhw62TlPEORCZ1tKLKOMiCpv+JZNJ7IKYlq0HjqWXfb1VYDGoPdi06gn03vU+vO3b+pszb+j9Fan0QjTdW9hao0VO0rm0WnSKhG1SwBQ6x3RAgEC7/ikPDFU2UoCc6F9Jr4SNhqWqCNgr/EJ1fJr3//QRxhc/0T9G5LjkVGstWkcYKvIZoLL1GAIqlRkymsuKhxMBBV2/FYEKXhCDPHzcWO2m7fbUZ6qVlxwc1H0b897w4Frxtf+h9T53+fQf1oif76arqPPPOkFB1d2aGtSlcwYYTHti8AAqABz/8bcfE/LjdwzuTS9VKM3OxpkvQV4Df7q+P/BHq//6Plf9JZXzYvbZD5Z5ykeZVMcewVm6UsUlIurbWirYQTEFNRTMuOTcAA//pyBPTeAAACDTrZuWkRxEKjGyck6YSIjJVeYLzhEROO68wWHDqARAc3/HGJ1JFIIFUwNbS2eAR/ONVMFfQfgb71NrxvxI8r/6dH0/bQ390S7llbtqIVQZo57JhYuL0qYwwoutnzCkwGBKm348qBMTbVMqghFMgz0ObZDNyoYytCfCH1/69wt/SCPDi/snFaHWLe2NiScTUkq4geLDhdikElmEUOK2KsJ3pACl2wqUOgpWEkYqUQ2h4mcV4gHbkxJ44+cH6iDMfDOOtMH9OPP369DcphvyE6km0VILIvaLNULxthJto21ziVqF1tdNABu7YVggAw7Lh00CMl+qLUIr7+MUDKRRnPhZ8vjSWXUNadB9ypZanWqd5DW+8BChAzKkTLiriIsSJjIsPaoq9SKxXZYPTEFNRQAAD/+nAEkGYAAIImOtk55xLmQOcrBy2iZIiAY2LniOsRGJ5sTLOJq4AEBXb8feDTVfFPcWdqU+CpuUF2YdSk6pc+gEdHyaUbN+Z/6dTfT+56NmdJZ2m6p+jaCnmbicveCe/k+GTj9dj+6r/rkAEADLth3BBjzwXi9gNWIYizTFJs3WVGOdp33bfF9sTp2f/99D6f22a/qr0ZGZ2dfKOdPTAq5+PZhIoTatIBFe1ACCCptuPqp6KqwyVtYyXq4MM8MPh1oPlqcvgDPKaojJqPyEOq9brkvhlQnrNRCKPbViKIGnMjQlGlCwIuaAh2BHRUWOAgzb8bJBKGWoeDwqPmRUV4nB5YoRdHWbUZL687DFI2T83/9u2tu1t3leSymdKvsz+jlhMFRxhFO2Nq5GrFH9xssV/ZcbupMQU0//pyBGMwAAyR/STYmYU65Dily0cFIgyJQONgZ5xNmRkdrNyTijIBKbbibwAVImkkMz7R8qNDeL4CGx6zVj8C5uVNorCDPbLZ3/VMpKZGupsBF9R9yxPENNbu3NS5BJCLMe5z0iRMAiQ9/+I6DJJ1Ofknzq2+ARecNwdKkH25MVa2P+FWjf99CZV6a78c2HgAeKRTUH1E3mOqv3zt7sXBCm34+OLk25LobZ+0Tvq71HwbiW1RnHasXxK00ICazUDOvB//kGwTa+81Abam7IUdprm9KiC1mJySzFVVvBH3Cea3SzXLWQ+kjxRBe9cCiXh7hXGudJssaA39TX2KutAy+Kmo2t5aYGfznp/1FmUZpVGyrvJJshjPVZh3d+ZIV2gbER4lVSB+4uE4u3QYSb6UxBTUUzLjk3AAAAD/+nAEqTQADIIMOVeZ4jwkP2WLSgElDIi45WBnsEcRFp8sjJOV0wAntsPnQtKCsFJCM6Mltti1+vvtaQ28GKw2QeoD+TRymPBP+V0v/T//ZtW/elTa71XjSKhsw9S0AsnGpffuZntpkAACAC7/+OLD+nGAOm7pm88x7IMdHEHxg18J6Nte1wN/FP/y6HyGbU67iKzTGGBUa1umLgouxnW2pSJM2nYj2AAzYce8ch7AXwWRNDWxErLiMwiqEGYNWQ9CHUWCAxdEo9U0eoFzvU9f+ZtH3tse9X0p9Gsd5r9A9Yb//tSDaxQsInOicSgAzb8ebwLKBQKCwjSTbVE5JlhjKH3cojq4eH3UIJRd18pf1X/6E5P+T1m81Op8jXTG3ptKNPWn2m336na5xxf7+2+sNUZTEFNRQAAA//pyBAp1AAzB+xzYGe8R9EFiOyMxDHSIpONeZ6xNER0Ma8z0vZoAF67D3P0UhGivoWYgui20bSTAeOsMPyi6+HqixJLF28jVFfj7M+J71VXn3FL9dVybB5cO7yKrfTT/rsvR131AAzb8TpyBwfQLmYwHBG58nw+9KXyzZfGBSJVnI+Dt5G5zx3EX1vU5yc9N58qpwx1d5xPWkqskE2xqrTwGdFhW6IQAJtgPkzyVoM4Rb0CDDanBuSSGEPtQ27Hw9vrDmVtO3chwh5CcdW0YA4PVv/ovqye8ppJ5jl7IBIoMq818UJixZvuxl9wIDt2Hye58l7MkQtKjjjXhNSqES2kX6FFbUTgR24mWpb4yXeZp/JGzfz+87Z0T/tU9q7LgRC+RVXuzq6dqi7BzLNimzJTSpKYgpqKAAAD/+nAE6lgACKH5Mlk55iokQQZa42FnaIiQ62LnpKmZDg5r3PMp0gFAEzbgfSRXUIqj1ySSqZpwYAYUfh5tiBkLYOiboo+b1ZHmArYi8aO3/yP6uvpXRjbfUc9/WTVQRahCTFka9IADtoGrLRYIdIgMm/MrFitJySTyQFafBAKonJIiLbe4bg7AKmcs9CKpLzwl6vUzf/QnolPp0WmrW1l5PTQd+77VGBBm/A+3pvppnQl2P6ceIlyUh8wnlgLv/SPUdkQrn+CW9m6jkeYH/Ud/8STSpntnporU9dTVR363RqDH2/U1PLb1r0LSLth7tphloPUDZQYUJybctT4Oe0qq/XnR0oO1rQBuDsfvbpLXkQtdXoS/sVftPdlxU8IRwsGwyoaDVJmmjl3VdTFe5KYgpqKZlxybgAAA//pyBPBFAAgCCTHXmekTtEMEutNhKmaItMVjR6BO2ROJbLTAmcoAGbYD4RAczGMlsS4GqqS8KVJrK1ZfYswpn32ZmdRHSwvgBW/bGsroFBdGhy//K+lW/ZfJf3dBMvULPvQlaH2dNIADttH3LCRTWxmKtqhaCPKB5RJOoBMVFvZ3El5UiXTFQZApAnCby3Q3lRZvUtR//quheNVJMKDljZ8ecZf6vb/9e7QEAAN/4H5mHitMCehB9PmFuTMCfdUAdRN942klnAdcFD9OfWjF9rP/8O+6q4ifUcyykVWa00NesoM0cz1/elX6312vduH1AAAQAAFTb8TdCJJaASThkNlqhvMDtpQScDuWcs4mSD8CV0XPcCSbggr171bUzt2Scl3qsOBF04lQSCpUqNzKXPEIrXxqYgpqKAD/+nAEJ44ADAIFHNm5gzs0PaObIz2FNojQc2BnpKtRGpjsnPSVEgCAk3/8TheVuF61QL2G6GlePMEAnBumVN84IzRBlGzle1jOrTS/yryj3qiNjASPGzdEkUKUKPHBgzu2WdPF6qNAAd2/Hw3KpUBCB3LQTLkNzIRq3HNm4xjLBzD8Mx2/az/iQHUOq6hjbmCsYNz4hP9fnSUgzuEbVS1GPcpyOsAGbbj9+Ohlb3tx0J00EkqGwv1hfrL6nWJn4eqRHuHjFGarK+okC9dR93LMU96NE2eJrhkwZO5+yY55e67rAanPWITxCEZqBoIV//HrImoIwhgWM/jxr2AsFgvMYS4UdRodDOMDKBm1bY79Qb/8mh48ldHfms9kchIwms8de9CSTlzba1LQjYhPe5rJssmIKaigAAAA//pwBKbgAADCHjlZOYcTZEEHeyM84l6IsGNe56EtUQgMas2HpTKAgRd/4E+Xy+jOdjCo6BiVYLnWSpdTGKjJ9J7RWWiORqaVLlcwE3zcoqrf5S6P7fdQaF+WgZ1q+6s+w2PeKqJXxZinqCKn/A++0tIi5PFhWVUD10AKqEzTl5QvUsLWLUDkKEaErntMDXtKI/+vvb6mrvKapaJ0cNZr+jnoJLapIXFnuyAwBABM22HqVK6am5ITiOwAuy/Ly6Lyhc+LVIpQZBlZIF1qRKutfzc5R0aaqHF+mschNpwXdqiaNVrVS9t/JnNaihndeZNbggFbQPvR9PBoAIyXqJiK6d42R6qHcDR0uQiLQVOyb7hc1psvI8c1PBI7CW6uhVQJ52x1Is4Sr9bvxEw5ud/1U9P60xBTUUAAAP/6cgT9VAAI0e842VAsKGQ/gtsnBeUKiQTHYOC8oVEQHaxMF5Q6AAIAAi/8C2SuphE5QFiGPRdgsR40qzE8jjQ2NQPiDRX/oyqBV00b/7Ns6f2XP1pSrEtfT2i43eZJX2Cymx0AAi7/wLyzxRPDjNVc5QpS+dajABxUfIw0emYXDImGXFs0dgJOpbKs7PkyksbPi6IPJvNqdQ5SrRclW28cKOMMAKv/wkiCxM8ymTRP5AnUxttQwsMwAeR1DYWoDhAdH/9KuHMiNEAWrN/M2MMj09avHm0Uy2YXQF7AhBxwhCSCilJFFNRL7P7AUrBlWJYLUO1KvNHgmMMbR5Gn4XqyOFoNuoOGSjo199HUwfUydAzb/QnH3Knk573MSquw/szO5lXRLjWXDAuRN2Mc+WTEFNRTMuOTcAAA//pwBPrjAAjCAjLZUAwoRENmOxM9JTyIrLlk55xNkRWXaw2GFWoAAkAUb/8BoLLSEQ0SxCCtKpAtI7Dzbq8acTQdEXo23qEABSayI3/2P9qtoW1HPkOVdVHMQU+LC1gy/ePWtu1qwC7/wPfKneCfhJXaywXD9TP9cX/RwrvTdC9RjwyMavXR1cU7NCQTo//L2Wlt6OkioNO7OMqIgGZEInNJscg6cfquZJkCEv/4+F1t1DIzpmbyxMXsrnkKhXyruVPKlS0wvctRkfqM/nPBI3XoPq8ZfLutiOoQ+1RgJWn7zr3MvsZFCjK63oWro5IAB22j6ldojLRFcVWlnG5tXTPCkdQyQRwyocr8M1UJrGhtp6GsjR0iY7GSI8oP04t/+/ya9rtL4+JJjqOLlun1CPZV6PLpiCmooP/6cgQEqwAAAhAyWJnrKuRAxNsnNWI+iHi5ZUYkp/EQGSyc8xVyCJn/A/fnhDSJGUerYIoE7FjHULfKL/MbbNomNQRPTW44cph8BPz//jH72+lsx1KxzSNMHsRICDLlHWLShgSzdSAVAEEZt+BXKy0JoQxTbQxHtRKOBjeUXJucrlWi05WRKw42HsTMN7ztQzfwXK6A0IP+YoUfJGQtOPFC49VrnSVrVlsAAVJBlkAtYhoao4YDdY4DpFWCfpCe9bzw+PlHVQPboEghAJtUkfrAv43/8T91vf1RL1YODiBU48w4VqPrqgwtf0ChGAgRd3/Hthmag2ieG21QkPYALTeUA/oND4p9Z4lX4rPau8brZX/UH1f/HdZn/99jfx4YeL6oRNsrQsc3hIujlB6LKGl0xBTUUzLjk3AA//pwBFJPAAiB8hxYOesTTEBkatNhB3SIpMdi56BPcSGY612EndsAIALjgH5mvmQ3gxEdB2KJtkqnNMJVmtwzUhGH3S8iOtg9T36E1TBuZ5K0WW5aF3gbvqswvehwYJqciIipO8EuW2j8aBxXVLrhQzfR2u1p14MjsBcrsGSgyuYaGUyTA2VeBxa7ZBSXcf/HxRkm/lW1kmJzTCxu5x1rftrvu/9RAUnZAPttjvUWIIlNNZkQt6Ye1qyKEnCWMpuYTxX6vkUibuAcAttY8GWrf4N8rq3113oUZqpcYO1obFINmGx9gXWLra+wgJM2wH36zjO2KREZH4luKoYRBU64P0LmbF119D454syLv4w7ufUbq3QJPfI//Vu8xb91TR+OKx5qFaNX9B+Tq38yq3NlzXnrJiCmooAAAP/6cgQLPAAMggsu2NHsKeRAhdsHPOVmiMSZZHTygBEaEaxqnnAGAACAkO/8D9sRzmrSVFovYD12Hi1PBi9zP5kcHbtWBVvtQtu4b/erenEOlf9lW2wk1IFCBE3abGi61NwKEyrSyMDAGALv/A+pE0+FsEyKR9ZLrTVMhVBPocjowdsaNHzd8necH98fs/Toy2H1/Q2s9hIoHEYFD1Q+SQLsqa8sje1r0Aqb/8fCQzheLeUjyRBTy4ddsgkFxciO4U07ELnarYtbhYAN8gO6ftme6KouBnxjiYAKmSy58ACwsylTkC7drkrXTobuuSsqAC5JAPe0eIGM/IZFyvOMkQ8X8c6qGFZQsBgtSqiKSVHq9S7b0DHZ6Pmmv2zi0NCJR9aSS2jHxYLLULjyubQAkWjDVT7o9MQU1FAA//pwBAkhAAACIVxingVABEFrjEPAqADIBAN/vAGAARIB73eEMAAACsVCgUCj9d/////////3RlU93mW/nkjR4YZVT//z0YjC7EOWPf///kY/Fhh4AmcPAbwKf/t//xDg3j4WAK46PBcLFAAFYqFAoFHzX/////////3MZ1PfM/55I0eMZVT//3RiMRYtlj3///1IyckMHgF5xIIsG/////FsRZMPAvy48KEnBAEqN9v7aIoGnCUPGFh9D1FRMazqHlmgsrAqGhRpV4+TOpOgMBGgEg9O7uma48l/DZnhNzSpGtmIyzBy9x7TrGoBhmWWXfRFGYrQocqWmDxNa0iEXEATCz49L1yqD5omCrwqpp2dMgsaASD07u6ZrjyX86Z4TdApatmXLMHLRcHH05catyYgpqKZlxybgP/6cgS7QwAAAgEc4GgjEixDYtrgPMJMCJE1aOQEVdEeFu4okJTWJIEcbabqaANmpFUPpJFlHbVW34NHmR5De7+1AZ4RB6GvywiBoShoKGluBUKnVhIcPLLARb+R8K/7SOiS62lXdq5Vwlx62EchpIo1Z0ccNeUnPlfZm0l4hMwSlSKq2OKyyrSv/yyf4luu/0rcp4dPagZOlXZE7Oh0FYlhorUBQVKnciGgFAJb/+jWDdowGKFDh8Bgi4tY08bXX+TAKj4vgKeeL/zQX8N8l3ImcEpubQTBGMfNWY0HYx09bnDqzfRB1mT9SRpt/hkUG3iVLrbLikHlBEpRXJKNA2jFjiO1ndRAfMr7O1sVr7BQs90/HLdVRr90mKdUjIzZeLQnSTeNlx6B7zesoqZhQqf2AcRSnqTEFNRQ//pwBJgiAAgCCBxZOSMSfEPDmzowwiaIELlk5KxE0RqObzQwidYBIBTjbSrJBBsD2g4DLSUWMnZaGLSaoh7BgIlWQqUvxM2kOL0aqOtDBaVDBjikjDjw6rY+554VJrEe+ote/e9/7AAgIBUu34lEMCrcviBB+IQ01jVdJmBdtAWzHdkr3AvSgAr0PW9TaBdlh06vpQwzyQ1iiiB6CYWraKPQYPDzsakwCaRVAKl22vMDjNEgZkYSeoiayyskHnrO/Ehd3QiMj8wq1M4o5Nt92N0/avZiQW3nBkWDzK98fcfICtSxZ70b1s7/h4glxJNpLb7axHYlZAK9irpczVkganMJiktX8v4oBWHXYEHjQAswiFnNUKESW8chpZQGAC2CJeLqE1TB7Ug9BWWFhj1iRLfWmIKaigAAAP/6cgQSlgAEAh0c3NChHDxB5KtaJCKFiC1vdOGEV/kbkuxMwYjqAEa8mXa2tGPjAuOatn3eMsB2JFTJIGor9ChosT3FWJXCRksOwXXKPtGpTPBUofPHjb3lV6DbCiiFx1ws8i0M1Z9hH1gBLSClbJGkuJiWRybD++p41VvvpPYBtS70HG2P0N65//I5M4wYek1faBrxViey96hdB21UOSayAqMWmzOqNsCV/tBSk2tum/uFHGygOF6XfJ5sVhxqKGVlju4WbGsgz/xDM/w4t3wwspdLjpkHPy/6ym0/Wz+8tn2vzLy3OjDo27nd5AObbatH4UFGq5ng6s9gnFpYxykHZOjxOvWmQoYq72Y+v6GnNHJUokKklNS5g9Y5Y5aiVaBVr0zp8glsLlxwxNbgrxrBnqetMQU1FAAA//pwBJLqAAACCRLXGeETlELEi2cYJVmIzL15Qwym8QUMrEzxiPoEm22uRHnSzvihUg8liyFr6lcofiPRNI1uMW6QgMaEouuJEZn4QfB14jfmHVVmwunedU/KoeqtIUPMXZoGIXxv9QPQXLpY+kRGMWb24zCEzIyI3zSWixnvWK+AJuac2v+mNInYxZYHARDY4ihK2rsHsEtpQ2lBxKAEFGhkszUiS2sez9gwt/qO/7a/Z1wQqhPJHaYpZ76K66I4RxhKMcXJoX9Xr/utVW0qM2mi12iA42LBGWJmHtS0KhIlUuTqpPvhsUSKRDYYNE/ngU9ttWtVE3QuWsvzAzBUSQyXXOSiTP4wOkVugtNgL2fD4OhUVCzjChzaBZ5Ml45VKq0DcVHvrvuWIHiuoigd+a6ExBTUUAAAAP/6cgRSsAAIAgMcWrjMESxDQ5taDCIviKFtXGY8RRELBaxo8KBCAGA5bJG9EtgUJixjEVct+vQIzr4VXr99hhS2JhVnesOhAUPnRt1rZvm0EQ8DCKYu5InyZvQIgRRcadx7GE2nPaBglBKdskdVgiBhpRIguzCwkjpPsFCmY689Ee4C30G+1ggBkzB1Aut1LR0Pw2bBqKm2zTCY0c6L1sGB9yBUmt2rSM9YEdttiVEDyszFZ3CUXb442KWzTeznrqwIbqqBATlb13QWZwAwgaor/4OrdVVDF8+y3fV//fb017+1rN/Vbevtr+3X/8G4AAQAp3ba5aC0XbZkJAVbq5OKILFSYKAG4KBxzyg1JVmo/6ycl8XirWPGJ4dQMFFMlnjTStxIANSrNjXVi2tDVcz9aYgpqKZlxybg//pwBOJpAAACGg5a0SMxzD3GO2oMI7eIuGNi5LxksRsMbBzEjGYAAagnLZJLcwxAqC44IoFZpRM1VOyJ4bRy3HgMSkqWBep1+oFp0xYcNrLhcieYJUm0PNmGClSc9Y1dnS+weAsW1K+GQBEZJVukkxDhitiYvkTJe5Gyw/z1BIRlxouX82kJvlmRAnNehkZyM8ecXC/Ij05ZeKoe6wkEEKvfffmxb+oI4KcjbNDiZC0QCdzWofUB8LFG65egUlL0FgxvpDVsvgSlMyn1GyxAAdjQwPsFmlgkRXOmH2OUcUhbaJktQ+5hN5m5jm+oA4DcjbSElAcYwwPpbZRY5i8oq08s4P6tt+TZakvKgGFTrhGsx2i0LhzXTQGFixWrnXC6hdB4Y00WcRY5ili0LgOlrGY93qTEFNRQAP/6cgS7XwAMAgMdVxnsEbREIxtaGGU9iKBzYGeMStEchuvctIyeBNttrXEVRsTiXYLSWrqYD6Gl8+yyBg9JJqZoSx7T/O/4UdAfKhs0WREpXjAqhd9r7GB6far5TUY7H1kdt+tLvQCAP6Ml0kjWEVbF0+t1mORWrkK0fIapQI+3Z7MExjZwt88PRnnCzwRMlAKeMmg+hVTkqYhdAoRmBWRXAaL3rYcN6qPW4F3batqfyssI/2gtcXVULMas5yF2yXq0M1bW9XTo6HGhcUQTGANZA0VDQxoYUGnxqmvTDYhE5srShAkWImCrjSSfTR/+sBABbjbWCcBKOEsqEt0eStleoP8bvBmTgjXknQR4XHNc103oW5yTxoogNmbh44oZLsLAMRIMvh08FhgLjo9R0RAe4+9zpb9aYgpo//pwBN/PAACCEFtZuYYRrEPie0okYjmIqW1zQwxHcPsOLFw0iJoC4KsjbmI1qOFaNSDjhnZe2HwaWq7v3CB2+qNq3Xhjox7UZ2r7WarV+lPtSfS//+j/1oevXTN7U+39K10/wouihesAAVg1LZJLaAueUofYysIFqXuuQEMz3I9nhiCEdjuGKOsUEZkSGEkqRr4ywGZ9xEZOKnqnLQJUsaq9d4xiEOjnFf38IqC1clrtba6VwxQrxLARzU5l7pXXhrhb+6c4sKY5jiFCf/ebZSX5DUVmY31tK1ykq+re/R6odMu+i/Y6JfPon5tX5Kf8I5QndttAYUNK4KG50mlrCGg2F9Ff2VHh+3qt02gY5LGiqUzaSmYJLlou5acJTqVXFqXNFEkEuQhreiSSsim/2JiCmopmXHJuAP/6cgR4bgAIoh5bVzmGEdRCYjsqMMM5iHxxZPSSgDEHhyxqmCAGAEC3bbYlsZCOnMhMGJFAo8C+M6DvTbAaB60DMDV29UdWQ55qVDPT/d9lt7crtrMTXtr27/oS3/rTZtf19Nq/b20/4JgABYBTkbc1EMX40MTNbGsuR2lE/ZWKhoZfxgbSb3vsZcZV9Yq4E0Oalm58/P3Kxlk3qCMwpSyz2oIMvsq3XZZ2p80slOWNtN0CmB9cld7qs9baVV0HCA9l3BBAzqvRH7k/GP+LHUuYguPERMNkXgkASoiAx4YOMjwqHg10MXbNVaze1P2eHgIjbbBMbR0WB0e3r3Q8inXt2FIrD5dAdg4UdUG9J5HUXiRTjNagK1iGAzpLRYZaL8qYiEXatAuclnvkz7WOnh7PJJiCmopmXHJu//pwBJ54AAACBBnYPjBgBEJrvAPAlACI7ZV0GDKAARmyrkMMIAAAAdNS2i22AAA9LJ8eDgPwgvH5yGRtuKscmMKY0BdDpktB1szyN/y5gjR0ilFMWUkHDwIEzbulum1bb1irz1h6kADUaDQZjMiIjndf////////9/LOZf8UZjndSq5f/kJiAoLnc5CkNIU//3IR5BdGcQ9E2d//+KMsDh8XU9lF6CwD157EhIMci58/p///p/9bf/2NWv96XZ1c5Fdv/znIRXIQWRVGqIf/Y8hDnOc4hcUkEUuYBf/+wmdB7PF9RfExcaIMKmFzDDGF7OBCinGuuo3H7MU1bp///p/9bf/21r/dSbVc5Ftp37zuiK6MZFU6k/+x5CBzqdwmIkCpdAH//sc5BynU+ovOLBhGEoeQzjpiCP/6cAQ3awAAAhgrXu8UYABECGu94ogACDRlZ6MErsD9DK40UZXi6rZ9/3/tiAAwTsqs5KwiQt0LkOG59LWa/dfY91bjrcucMy/5V/046t0/QVczLUuPEhFWGmHvyyuLHdmjmt7aWEc7kQCV3JttrYiBMzRoWUkWdaoh0Ml86WZWNbW2bVkopaEpQzt6K3koctSvkFen5u+bZDdSskz/9OKU9sJHdmjv3tlmJzuRAIAUQEv9MRDLgdZZVIyFc2XxjePZvzaAyQ1SrVKgcygoIjxEJbF+JTsO/w6RgrUDR4r6agqQ5IkVO/WDWr/PSp1IAAJMbltjjSUwvkC3Zhzb3BleuSnSkQ4JV+X5TdcwIwwGtLW2fEp2Hf4dIuDVQNHhD6agZIckhbvrI//PSp0smIKaimZccm4AAAD/+nIEAZ4ACIIdWtexKxFMP8OaozzCdojFbVpmHE9RCAysXMCV3gEC3/aY9YRYQCpJZYISnU1aWpKuo/no3M1j7YB00X/5T+nMv9X8tnM3Rbs71R9OctK0MZlyHKS6FZrN9+n//f9IdzdYJckkZ6rkp3BzH0YoWSaOA34TdgxNItXTJDVWWBunmJXjVruTd36Af8V9hhoYpqTeqA3b/bZa4hZ7tugjyXX9YLV1tiV4tj/peGg4jXAPwp4z3VSxzqxV3W4/Uxn97S1AHpnd//abu+nUY0lX73yJZr/R0TkVPfot6t23df2tu/eZd9v/hXKApI25CpIq/2xQqPdVbONzqISEXNicWNWvT6gbw93LBNZLAZnmlnmTym3K9gcSaAjTaHsr62UL32E7lCd4CudFEJTEFNRTMuOTcP/6cAS8fQAAgiFa2DkhE0RCYxqTYMV2CEFrcUKEW3EPCOvcZgg2ASDFdtaq5lB1w8JCqYWmn9AEsQdGgTnNpJ9bOFi9DV/+qvX9EzUZqnp83dVSyFqlFWrMTLzU1Rtbqzf2//679PwhqrWAv//5eTUVLcisOjpH8e151mSigmWtV6jav5tKqNSmXKbJAshHeO+oZbLsqJoceuzhHY3sMNo2cAbrl/lXL9y4ur6gQGuTk2tssx5bJHVtfqhaq3YaxRMMMjVSLeIfkv/ABnA6OPPewEqYaSAMjDSI8p5RpPV0wGnqcrzspn58hpbuP/ghAFuNNiFAyP5gJRYUnye+ca9B+khXT0sgsBsvvJd3XeQRiPOjFAEohxMqwiIBCu4Qb6UUJ6qQoJmkRqTKGNQL+WOI+hMQU1FAAAD/+nIENxsAAAIaW1rQoRc8QoMbWhgjdYh9a3GihF0xEIxrGPYUbgAA+LdtkdRjJRRwvB333oQe6HVnoqsijqu6KpewT/YZr+zjKRy4WRlVKBZ/yJ53KW+0fOzLPG9S9P///t1yTjHrGWJBAGtKW2SVrAmqi0EOk36/C1GaLTTJVMRWv8+miDcaoK3LArXCy7A4tC9as3behb4xDqbFd2ymXzxJFrcwsZNNi0q8AgAtxuTbWWJMs41mVOSKmoJWOU8m5RQwmGIoa89+4V24rV008DPnNAWKGih5Hmp50U8kHGf/z/y+Yt4dpqZohfEX/BgBRfqYSWGqnXGQ1JBZNR0O9dMMda2JuNYe7q1QHR9rWXjuR/Y1ou0VS+k6o/0TIuScEzNCFDoeVac0JSLNuSfUekS3rTEFNRQAAP/6cASWBAAAAfdbX2ihFtxCoxttDCN3iMFtWueET9EKDipM9hVKKJBUtku/+29yJUbSXnQ7U3ZDuvrES49J76lAXpk2bP115FVH/94f88jbnOU//SFMvKjl+a/++567mVgEfoRUAQAU1E3brJaKA5pYRKmiw6yE9pwCGdlVbpQiLYXzdlVl7QPOCEXFQ0MDBoBSAnWwMrWFEDXUKGL0UYo4j/S/boN+4AoRlttmUdDVN04VZ9nzg1oeeuM7nKFgIV7VEWbkE94vxgL50U7GOz16MVvlullld+l+vnonmutba3Sh3al9vbrfaqf/gnATkkiPVXhZGTO3xDSeviPLmn4fnyOM2jUeLDJ0Z2aXQ2fupwM3aKOMbcVbC6FvjKJZ1u+xqKs3nHC7JFCh7FO9n+xMQU1FMy45NwD/+nIEp0UAAKH+W15oQRdMP8Oaoz0jGoi1a1rmDK5RFy1sKJGIfkQAi7JLf/rsrn0u0QmtmWV90brcMAlq5p5L3P+wOrNp7JeBgCWiPN0+jDWs7Jq4bf+vLv/TNgY/G8rICYv/4ZgXJJJFyWEMgh6xCIgSEpOgAwMrsJqoqpOO5w8yaUE+Zw+cpwoqL+QtBKTijcYjRfhoa366OTob/rf6/RZ00RrwHBOS22JVJVWyZiABo+sV7wcVqOq5rirQTeWcj0ty3UgJ/NT/+v12ctqKlHp9Of7m3Wn9aL5F6N1ut5nez1X0oq7f8Td0ItG28DAMklBMChqHJyxIyEdQuPlDMY7bI9uyBW24Yn/c927uqzkR/SltDtX6q2rulG1yWWRGZb5qorJd75Z+ddddZ8v/BpiCmopmXHJuAP/6cAQ77wAIAhFa21BBFtw945sqJCUZiN1taUKEXTEeDGscwwjiABX8qbWySwV4MMZZmOoDdnuwhSpa7Fren3tFt+EaJUXKAAjuQJIBYKm1zPnCRGApsSeIIgf8ry//+eSH6BxIjX/BgCIkE7I24k4Ok8ZwgYGx2DHTbRGeRqpom9+4v+JA7ghXKMuXimvn+NKP97atdgkT4q5VyZw2pLmUtGm1o+8nynbZJUY7oIBIwlK6qLOgf1iKLepnG6Ptr2sL19RBUdutQ4gaUKAREEsmvGbBmud/p5PL3UwTayWZLLvOSvP8su+rCkz60gBBTttsE4ewLCBYgwowT4DxtMDAc07HajMkpHQ+v/iOAviMBDBjDCnqfHPMLFjxitdzVnUDHqTGOKFtDAzAa20pEgvMv6n9KYgpqKD/+nIEz3kACAH8ENpRIRIMQgtrvRQi24i0dWtDBEaxIo5rJPGI9gAXuTctkiq1n8aGKfrTRKiQSyR1fdbgxCnkpF8Ccr8adKrY4WMEGwsQIpKN7FkytzGNITrCXWsA0vOXKvYp3qAKSajql2+u1xyyI59DWmDUdnd6n1KTbV9LdBXLye//R9l8AYgoqKSdlcBG/kCIzSL8j+/8+FSZq4gyGtkbIn9eCqP9Sa2ORtIfkxGDpyZnDtFMT+RSzPITNkaUjJmsIUmKvMoEFYDEsoHcrjQO7OjWTyXHCHQX+LBUSQ2AXhsE54RrNfNPOKWAAAwv01KS4ozewnkRQRYHBwXQYFbamajjr0INacr2TXc37jFD+bJCeSEKhdn9CjCJ8Rk3obdcmfd1jJAqHAks8fLNJTjOXcitMQU1FP/6cAQsRAAAAfxa3+hhF0xDa2u9FCLXiEFtZUSMqXEdj2xokJXeTBVcm1//+220TsJtlBmR5fdcpEpKfBLZp0OpwrQ5FTnBv//8jfyZe2fs5+mb6ET+uRFfWXOWa1/6znnS9S/4MgBtqOyb7XXK48tUY+l0lkKttH3EVDHM5E69o47646FlrK5PIVUef6m5/7v87ka91EudGKVaFru2nWn/X6/2+DcV7tIAK9pOyNtp6JndAbEpu4ajz3eozHIr+1kN+1uQZ+Egmysi3WWqlRCom+/e7t3+l9rf5msmmnpSlu2n3U/27fr/8a4AIVBOyNuJqiQekgaZddR+x9sMhs062Zo04mfftOG/qiR511rIMcwmeLGW2PFHHzjYojFgg4VvHkk1BOjJFfGVKQt33qdyJpMQU1FAAAD/+nIE+i8AAAIkW1ZVPEAIQeMrKqSUAYiYX2NY8oARFC7utwRQAAAAPMt/22XbKnFRYkRRk1j6xNAng/dCzWZ0OhnqqhW3zoerqF7biv/v1197y6tZtfX6L9v/yaVaTvsm/6tS/0X+nTqEcAKKynEySrEgMnpolYKfYKPf/HKz9KuyyDLkPb2qCEXuB9YWXV6w8HwwoEAIEWu5TEAnz8/1BhPWc2VHG6tQY7PyYAAAsn0jtmo1FAbCJcFP1YuyIgzO0fbfx896sIsSeiastwXOLG4ssXZKFFDJJYBY+Lm0Pc4O+cJoY4cdJK9UrHp//0/3gAAABiAWUD0eDsdDAcAiiw5Q4mVjfanL/uz+1P+jao1f9+81P/D6RN91p/877HV+6e3/yK5zmB6lD////+PQhAObIyMLpiCmgP/6cAQ3ogAAAgxd3xYEoARCwctdxIwACNENd7wxABEWFKwrljAGwM8888mOGu//////T///Oqo5v53nxiEIW39vzzKPOKsjC+v9XbPchLi8RExJSi4N/9iXFCVehGxooIjR4o7GYijgAAAFJJbB5BWAgAAACYEZEZKjlUrEm+1/l1TVLoQVY0wrLjBYRqQjh0NndfvoQ34rAvWz6yQ9yKn6LfXWMvilUiU7SSCm5LLI2klFM6lNCLCNWfPodasoUSVXMrVZ5EZOpbGV1Z02oZ/+yGNTsKff//7/1KYz/69BRV2oFRpVudoka3C0jRkcREgACaTkaABUMQ0IOhQJAgtzYiuXsvD+AiM9xBw28pAyP/WY7fi7MdX8/bil6qtCtBp8RfwVDv/iIGvUJQmd/Erv/dWCqgaTEED/+nIE+dwAAIIUGN7oYR0cRAtqg2GCNgita19GDEmxDBHs6JGI9iAUlLbL/a25DL5HIrzM2UzVW2cS1Igi0qViHbooCnZ2FZUA87hqWJZ6w7dDobdLD/5Z7GaywlI09QF4doth1T4lSWCm///uIpF/VFrivwsJS4DrYRnadAUdz7SDMzoMjIcJm2u5fcp/0TT67J/32//96+3v9PVFPdqe97fb/f/dUb/9Qh+igAAGinHGkpJyG1y8UEc10dwyDZH+gkpSLQleXfZ2dLFQBsqZ06WTz/19yluVHaxZWKtCb9Hk7mPJ6aX/vun/o36fa1P/BFeXLbI3bQdQxGQeQIaS/qEnGVqwxN0FlwV6X7u+z7yfOh1cSUBCEVWWvF7swIdMePCEDjgocSQNoYNEd7TqV776f9SYgpqKAP/6cAR3jQAIgg9bXehBFtxEIgqTPYM3CGltbaMIrjEKLWuc8Ip+JIBMcs2/1uyuKeoK1u5g/q9rHS8iIzO7sZy2lAtOh2RfrDGNnkdmv/80X2VzP+5bOfw/6TebaJBlCWdnMR/8M3bWFNbJKmS7jSEaUQVAEkBQPWh9L40vLrRFl6GIeyEf0MAg8pxS0QmlsuA7GjZFb7rmpxZbM81XRes9b28x+v7Ri67EempNyNz2ySlyAGYwUgrp38GdYzIEGSWJmQ5wx3Xr+X9TO4xylot1fXnfsT6XTvoXrpndaTJ3Ra3p/9P9OXv/bpZmL8JjlhONpJyrA2kBy7ZKSJpak1Pq0af/G7Y8il0Z7zmsiWF6Z05/GZmdepdbuZDdfPq5cpU/R2l/2b5Pf6ezk//4ey5GWTEFNRQAAAD/+nIE1YwAAAILW1dRgRT0QwI6Yz8JCAiRbXOihFmxHQyuNICN3gAAKDlttsZJgxUuJi8Hho4kpPH/0rMzd3/11Kj5NEBj6J+VNsG1tH3idESv//yykupO/35ZltVvuy/f6ff92/8G4b222zoDIX/L5xUZWS/DgPxFWUPiWH2piYJ+jlseeu9WkrUDpo6aK675EVeUPyj+kn0Ij/Ummr/1+aj1/rb8a8WVTcAgSW5Hb9rbrD3ONUhWLyWBuz3V1TZhqYm/OZ8xe5inebAV5LOOUGcud9H/+XIiXrLvyDLmA13J975XkRz9tWIPe/PDVkAIpxt3ba22FE8ahPCosJdTI/iVn4AIk8y3U6dDCGWKLcrqKpYY0LEZogLvS1ybXyMVYeSUTvIsFhdYDOnyK1jFjrsVFfZ1piCmgP/6cASC4wAIAgcY2FEhE8xBa1vdFCK/iHxJRsykzFEelS50IojeAAJYKWNtFIqKjMkwfClzHs9Ecm2OLnAXRFm/W8Q2MDp0AlhcwtLwuaHtus7UlCSVXj1ijlmHLIFy4UphLrV+/9RADJlsc3/23RSLRXZ3pyimEBZ3f6E0y6/fLMf/gjZnimbMjJReedRHm/KqAf4O5ge4vQPgh7ynad7g9pbYYZRtSlANVUo8n2TmszZI8BIuW4Hh1RhxEBROUoeEZASzxYKzR7wuB8dRwMsVNlU0Nx5L3kmaEU71PoUzQ/zP6PtRZb/12Bz0AAIpuyW/e264k12FXo5dgV5mc4700GJD4ojI9uja+PbZiyXumVKaq4Q7Ai0ACciJChBUnH2EyzUs+VoSxF/S/AVbK2B7wK+tMQU1FAD/+nIE8+oAAAIGGNPp5hMAQkILWiRiNYiFb3GhhLfxDghsaPGI9gAABAAFdttnBBjBCyCKVTBskuGeuBXz9e1KkwJlpAlTINu17Op7UtzAlk4cpJUKLjtIv4sT9vV9b9vRdSneX/+sASa2prZJLaNnudGCZotUY5uV+rroIWHV06j/WNNLFQkeAwjRJtFqypDYRItW4o4UrY0n0OVirlIcVLQLrCjrn9vqAYBOrjt21s1MdxXTbaTgoM3QwPshfy8BcVSPzH3gH/2KfKREyWtpC3DKZsjfJF9/c7mU58iZb//+Xlf022DobEsK7hGAAh5Usjbkr9RI+7wgTYaCwzIWz/Pd67FIEkrd6Dj5o/YyLHhzHWnm03pKtdc+SXhbheLYlGppisubKK7Fp3zhR4u8emIKaimZccm4AP/6cAReHgAAAhBbWNEhKsxAojudDCY5iM1tbaKEW3EWAyxoZKwGAAOdKWRttOIYWheNm8MpwBkHJuirI7IF/p3nABqvx5rtRdF/6rXfLb2rrSim0XIpqJf7dbr59H1+y9/6s7tS//EHIAJRd8m+1tlIYRwEIojP3m8zlBR+dICVB1W94mNC7zcKCgntAiDz3BFj6ylnFm3XMVUo06XJWsn2rSc7awFa/1AEoKpxya6WRRQVKU6HO7osSOcN7pHZtjVFHkfSe9Bv7BBiKpaI+oswGCEYLlbv665G6OcSZ2GOFBTM52xQyHl1OX/kf/gmAAl8tyxtyQhCI3puCD9ZAIwlMAMRBAVjHqQtxEuy3YDTKAQFQ8DoWDATeQpJNQ1Ts6GJ/M7lo636lUVoS+gZU0+YhyhBZMQU1FD/+nAEXZIACIILGVQZ4jNQQOMbCjxiM4jVa1tGGKTxHIfpDY0YmA5///mAmgJcWJLOKmNNDo5cE+wPWVg/jlRWZeRQb6I1jmtlitbhQhL2KQqe/NCzP0uUyyyVVY9bT66Bm+PeZb/DwACNBOyNN0dIM/u2lGgFMevEbbu7QdqstV3bfvieTJETUYBgTAb1ISX4WXj0MiiksQkfsWj2XLODLzlrULLOR4DDEJxtJIpFUchbhcYL2BKFo7ijmOj3snRFXbra0OgCtHaciEWRubJ3l7d2ddOt9bZXRKJptvnqi9E2957s/VKe6eu5tf10GgO222p+CgRQxsS6SlA7Ha43CRteeiW6a/sBPs1Fe2im/kYYCFtyx4jbidQYAr03IXld/Sa0Ndo6W5XO/2UJFbYo3xUAv+KoTEFN//pyBME9AACB7ltc6KEVfEFjGjNlImYI7WtjRARbcR6trCjBlP4gpE2zSzbWzI452dlLM68IAK8tNFNdhZqeZF8v4cvPeqF+ZnnSu5YZlwtEGnyF6rneU0n//0////qIH5WgWAckkkTuXsUmgbpnKdQI/DsmkwwvWAaCdXJ1CZLCN8E+W2qgJATBjNrn1oguo6zrY0ZZj/X/usU/7f//q5DqVzrEgAdepbI23h8HYeOJRkpI6hVE2O/pbh+Zq7Hd1K3NR7ulBarrHpc2M5HbA3y+DzQffPs+dl0XnJpnjtcyI5ryOfc658kf+ngiqTdkbck+MxhZDPQiSP3CxhrF1+fxAwiqRHE5P3T8jyt00+Y6NZKejMlem3L1p+X/dfTvtyr1s/fTSWvZrEUuisyhTJl0qoSmIKaigAD/+nAEMZkACAIKW1GTCTrEQ4IbXRgjdYixbUz1gQABFgkp2rAgAAaqpmI0sfsZ05skRWi1eHnXiwXxmDwn/37dnYQt04cyqidPmi1/2np+lK0b7W32////29P7en//3/0+vr/x4g1aAAEi425bbJK6xwW7AQ5PV2/SvUwCk63LRjbhtK4RstXbjGKU0ZSH3DCIfTilUVWUiCv6kkErWnU7s6VPoQAwi4NuNGiAPbbasbfFCxBAwwgE0R/IzeuUr4162/lh3Qu68rEZiPRv2oBUXkFrp27PvZf8/o//T3v9/r+/r6PNT/t/83/r8OViLWJAEX9Vt3bKgSAgFyL4KtmTQ3NznZmneW7cywbjpWi6srjFhViUr7UF4j4f1QycYsLl/y59ZTU6Q8/5RmTxP84RCJ8pav5xMQU0//pyBMOEAAACKCVa1hhABEJhK93CjACItA1vvDEAAOcMqWuwYAAABHr/uW7XabTY2M1RdiAtX7Bv3z6yHadalqp0Z37ZDdujNiMWdU0MqO24uGzu5EycIJkvPVXOMEKyl9+4/3ep36PPjOkAABuWO6uDf7ejXDUbZWVUO81okxYTKEjjkB8NvFZTrDTQ0F0GNisspCr/zuuZiIUAyfwyC9B9Lm/12CQKvHUaKuLgAmSX7aRoknIW0DiA+CIsFEj3rDcIF1Cpo5nVtQfS5EUble8XcXSAytnnzSqnPOSiKZlZtzyCKrXCrnnR4tF3GrDjWO4bAAAYTaQACIKwAJ4VAyiLIbEVYbl0W3HLcMTUdiUSlsmWXsa+6qhP76k1ZpXfTKKE0vgyBGu/bI1srTEFNRTMuOTcAAAAAAD/+nAE4yQAAAIcQ1tooRXUQMMrTRhGY4ikZWujCMexBobvNDEZzgACU65I2iSShUFXY9ytWQzh8HQaazbMrTKFDpqJ6+cnJ8TKFfzkITnyF//oXmvyES//1Eu4iJZHBWpbqJJ5JNaj2CqQCEmXK7tbGAxpxFjD1E8aBTH3GwpcZYGPvJeXLL3kUtkbma2QfYWegUpZB1Y0WUTSkGEQqBTo+mULi6nqPB765gAAouRy2xlFtoxLgRbmvu8oAkE8jqz92LFBjkpySmfvkI6hjXoPN5kiVOjjzw7t/hL2fiIkeDuPJf87lnw7NMcdWGiJUYggpJLrd/9tpSNTvNnnKGXTuDDxIMOPZuiRuuM8VipUBre9goUEaHqU4MoOPHEWrHMOR70NW1IurSFePKMoR5d1qUxBTUUzLjk3//pyBDlhAAACEVrdaEMXnEOBuvowYjWIcC1bRhhG8RCH7GiRlGYAlxTSXX7623shynO7drBzT97JyMUEynfVG6mb8Vr3p/S+isVWax2eUjmXmpEb2musMoFdt/trR/0+/o9v33yJ/8GAChxTjjaeFpDFi5kgox4MgJSo+vcKPKBgCXxzo/mXtIJRGqtOrCcQvYDgCG0mIeHExcC2nmJFgiRDcpIBIb2ebv78qACVRSjaSUJuEQVnIW1LcedbU6TFLCy7ysc4PCr6ajusVW98YCEWoGwiNLPpDeuPjGMeOXSZK3PUsqCSTUqhTdrv7Q2AAn6csjblnw6TqhDrvXX3xQz4QHqrCgcKmmxbAF16Sa5iKvQoX3uil8LoWlLEZaSVDjhKswpSCO/Yh7ECNbtw6JH9uhMQU1FAAAD/+nAE1h8AAAIVW1bRARX8Q+Macz0iNghha1VHjEfhBIDudBEMBgAS5KcbSSEEkAgAAoPAVB+RR89pwNVHPvif+7SRmpPVcbb3Mygx+58+q5/Oyb7Bsryf3mV3i2Z/8nvPzwGi5/0/wjhX//9lSf5LA4EMSRAFcIGyJIZQbRdppitgrKzOyO7pz90QTL3HpudS1gOoU6he99L6V32CouvFppHrvRICcq1kXIq+oAA6ip/9bW0yBikjVYpxGH4nESblQk2QsgZ3uy1+J1/f9fnRZ3TSz2W/51SyX9L3JSu3p/7fpv6r7V9W9v+zdPhnPqAKRblsu+1txoYTiYRoWHC7kFUh5YgNFHonFyzC8ikCjjQfj9yWNyoxbrHtels+z19LrZKjIlUJT2sQY0nXsYcVSmIKaimZccm4//pyBIZFAAgCEFrQEywSYEHCelNhIhoIjKdjpJRJsRcMbGiRlXYmoqaYEUHWOORD0AkeZEy1S/LrDiZqnXL4t/Mma6NL/7sKi9X/1bsRnR9N/fv36f0/3///////9///7v1///6BzOkQ7bXKGQwhb8ukCgVJy2UCZRcRom8FrGaWFetNAWYYwdPSHESr6Ci1qHF6mpMoADX3PfRLelmKMsZUuu2pK6koR6ynInbK20khRFXjJY8x3rTHrlMkIu5WtGLq2XkKLPlboZpqve331XnDgEwFWiIOA44Xe15RTiuKsqOva5+uePtZX3PX9YIJfqOyNuJEomZyCeywenctBPpOk5nOMUYoHGLi/wfnES7xBZhUTMWGkj0ESmf8iwe0SPM7WNc/Wsi8mbbpdWa42Nfxw1SYgpqKAAD/+nAEGIMACIIHEdCTOEDAQkMadzxlZQiwTVlHjQexBq1r6FCLbhv/8qhLHK7DNOT3BwAFYX4x17UxInGJdQoEoBkyCkYdNJJqlnFbxLPKkp3d777f0o27OxVPSmz/oVYzvFG8ob/SAEG62SQexugtCvbdummGyjEmYHy3hD5C6VftaOZ1/4TCRt2AkuLbQd1OuezTzJBDRiVKaRpeZ03ZvXr11beUXdT2A+m42khIcSnLCpB7LtAAODSc8bzpqVGWdCd4N4NGCV6FMrQeONFxMOuFmIWQPmWzahqbUMtmcVQeikGEP+wDK1UqDLlfYM5jkjTYwDAUEFoQH0DtJN222UNpFeeh0qpHtUV/6rh0o4TsXg4KERTntFpHDCA6fvl///nCR7YUVzhIHWBs/0gq0xBTUUzLjk3A//pyBJfYAAgB+BBZ6MJBzELBuuotAxuIXWtlpARX8Q0tbGgwizYAAgpWuXWtuOscOPTEoTj16Lqlwc6i3wGZ9uUWWflgKIUPNWHBYcdCoqPGkHCYZZu0Xbu/X6f+rSXvw412xBUAA6inW0k8ahmSxzAUlODPOXakHU+EDHiEgWKnbbiXNGgdBN4DFEahEnsUajHLRa110pcdsSqxLkULUfJ/705d2jc4hSuWyRtjZFBEgJQLge5mrx9/320GHJoGR2bwTTcyjiNVvIdFNZEcOfdb5yNn+SLYQDPiG9/701ylIty9vPWUw//8OCA9yksjblFigxUMIVwDLBZ27FwgZ/My1zbKQ7CmP+D0AjfnMM949+d8TH/m5d3e3wX+8WW+7kc6Zcjqttl9AeLbHi6YgpqKZlxybgAAAAD/+nAEFFQAAAH8WtxoYRX8QkMaijzCUwilbWmhBFtxGK1uNHCLbgCAU7a7ftbbUJzQGZ953sQkXpessvt5NQ/n+ij06AAKfXGXj15dFu4bqFSikyI9k/zrGYAZarVz5wS2V/+FfqAAAsTa2SU9XAVBkqt6nyGMjUOl1WCc0OleoN1Khw7ed9ruewAwFVIdAIp1Vd+zQ5rUezZ3Vmr/vcTzsUremliH6KAAAEo2rdbJJECwAoYo7saZOJPBG20Shy7SGaZV1YF7SPeKhBRkbPsiWjMcHWYG6w8/nZRepgzKeuw3mfWek+Ra2Vf8I9IJKTlvl32ttmK9CrGIG3WdKkqGNZB9RRU4f2sr9ee5F/hmOhkBEMjqd5KZjz24ymXutciZ3RI7U9n5eYUv/5akRSAj2v+CTEFNRQAA//pyBFOHAAgSExjY0MEa3EQCOx0ZIyGH5W1towRX8QatbHRQizYAAf1ZZG2WIkgdI9Aet1c+h2eQTZk00YljGSg53gNuJUi45oCNKUWD8YxU/sbL3oJFVn4regUQ1Tn0P9ZpNTyRy71AEAEtRy2RtxlB1TYy0ShimJ6hFX506hwzIHMxVxBiheRHMPNOvaOYbGvqUhaofSXRtux16KE1XIt7HtXY1b2uVqdrw2nbJdtZJW6mcsq91/G53qPK7bX3+rZ80NyFv5hGe1yQpn+VGOMhOV/8sr/8/tdRcp8t55ZfNeV88sir0TnGspAAIAkhcsGCLC7jREGVhXvjg8WZzlvv58ZzfjPvHrfPPPhv+Y6qUiwdbl5J4gJBmrPIsueZ+cz8o/a1INei0Du29aYgpqKZlxybgAAAAAD/+nAEQ+AACIIdINjpIhm8QytqrSwivwikST5MsMpBFojnyYyMoAAACY2pdI21RpMhgoNLipoJ3uwtWmTZpm04YxsRZmvXUEfZ5mZE5lRBuHtK2uRqePSsnZvH108o+ueKhUzTjlMTRZ9YAAAFLmv2FuMCHAlJjiQIgOnngT+aJmoimeRT/jfz2ySy5apB7l1xkwagUjb7Kn1/Pf////8//l//n/f6f2qiwb57raqqmEj2QnEbpwsWI6hTgwD0ckgR5WSBN5YWlwmmvoybnNLz5FHEhqAEBA6GfKJXelpCpNisrbqqp2f09cvTo/K6FVxYNg1VXAnRpCXzX4VUCK4FDLjYOnM/UB1FD/dImLEjhwJKPRARSHwGByLZ90D2wgEX2rmLH3ii6O0hze9pVP+Sb+/3VZ7lHoTA//pyBOXVAAACIVtabQhADD8jGuqkiAGJCTd5uBKAERoSbHcScAIABEqVu3WyOLECZwgCMz9902Mrpf3q2zoeW5UBv+RnKlln7bK1Gz3rMqoqn2dqVRF/oa7qdapT3W9Wfeqnq/////+cI4AAXJuNpJLnyKW2B0H4z7uXtpmyrVu5Ho7bujHPx+tiUT55BJsyRjKTw1WhwmXSooKnSin+e0w6b3VxSX/q+oAAAI0OW7UagYDAYDAWZjjOL5RtmwIKPuiHEAAQ+d8EHhwU/TiYfFxT/+fnT//I+xG///PcgcFBc7///+c52U4okMf/8vB/KOAAAABAKLjrdttttlAEPQhMRNv0eg4zeZSMnNd4kGLmLoNN0LvYMFxEEhUvXwfg/JiRuvWuhN2ntqRDFvbT793PoeT////qTEH/+nAEyYoAAAIUM11uJOAARAVLncNIAIi0c3NchQAxDYyqz7KwAgAAABgIBQOBwOBwOBwMY2OSOspLh43u/J0NglKqa4ac3m2d6/5wFBWYt/993//qdY7//8geAAb/6T5dZo7/6lMPooAAAAEARESxPA/oAAAAxDX6QlEosVdb8lY5wnE6tGS6ZipltmxuiYv1bEGAnAYTFkJU1tdBWQ4hyaRxf/9SnWcMQWEm4AJiilJEk4qHObEgcscoQfQQ1i6cicY9G0b9DMoBa1SI0shGbiE6HHBIwVWHTANSxM8dlXYc89+VcJXVPo/lcSrO69bpJYIJcklxvYDERbDJE+LZBcF2s4ilZTU2b/fpMrkZzWPbWtMjztxa2alrZPeYj7BiFXlpar/1yHX9yPv/7lJr9NKOG76kxBTQ//pwBARcAAACGTDe0ScTfEFEawc84laI4Pd3VIKAMRgW7SqWUAOcLn3Fdttq+RPz9H/qQVq5LifnNjj5xbUtiZ9OgJ9LRV7/qNy0ZG7ekobh3n1pnVHmQzYScqZFE6UMjixmxVtiPKP1AIBDs2wki8jJDILWVQ6dx4AFc0i9RL4Y4Bw3D8F14N9Bp4FwvbYHVYz5OI7Cva0owWWeWNwpOZBaKcKzTBGLCjXRBsO2tvsJB0yhMyI3TBv5rxLjeLahMdlWgQB3pxoAcIsOIKjsQH/VVt9dyEoZ3iekAB688rHYxPtVcg1rBGg4bDIaj2f//UgAwJIe//BQ9EihA4wQhB1cEPPlnUOcN3F2xNsr6fxpND0iv/36P/Q90ow0pQU+j9XU/fbsumeZ0Y3eGxa5CN9z6sP4p/ypgP/6cgSzvgAAAhgQWr4xIARDR8t6xhQAiLV3lngDgBELrvJPAHACAACAIY222AoAgU8+dpFJJGolm7730lAwuyB6arzXtj2e7RxYEwyE4tURQOf2/hABRpNYxRw9HO51qUmw+IP/uDBN6QAAEAGQAAL9/wMALHtSjCYDUjP7Dyp/fz6nDoTiJiMo545qvmar1xVOP8UX///+kiq0Xb2Gu1NLWRNO7GfFxB/+cJvAAoFdotFo////////7o3/9EPPNMfZvz3n6nkio2caGL/2PdrE3nuaaTHSg0Gw+SIhT/+hhhjKfV+okioah4kER8cMHxUcABQKLRaLR////////3dv/6Ieeaz/+e8/U84qNnGhh//Y92ybz3NNLmlBoPD5IiFP/6MhjT6v1EkTDUNCQRKjiD4qOTEFNRQA//pwBLuzAAACIBlgbxUABERIa83ilAAIPNt3Q5RvcRCbbGj1CeBoEtNuSttIkqRkbQrmEg/uG+BKqyJrbq9m5UJNRkCJDPfweutlIhqyU6xk9t63FaX4iPM/ESOJa5FklqNdrUIIypHErGCA3G59dokSroMHLEUsq6gTQC8U5cxylYUFqDHSvGP7lRWo6F5q6tUtIzMZ/L//7/zGo//XQWQewVr8lqNdtCCMqnErEAqrKVjIAs6NoTyoBz4SPiT4G4U34U2MHfqEOTRLqTTlWlD9mPnVKNxr/GP9mW7fwwruxL/EXzx4qAq+wOpnWf8RABICCPbEjLShUKmkNSlb5suG8yMOrgefE/kXTiQmLuvQnLVgpWMblb/8uahvv6OVWN0cKd2Jf4i+ePFS1fh3kfv4iQRTEFNRQP/6cgRXfgAIAiJbWTlnE2REBbs6MOUriLR1XnTDgBEBDKyqmHACAKEbvtrB1wjHa7E3ogxWgD0urYQ8bt+UGMQEf0EXl7VbDNqOu3Tl5ikQ584klBh/bb7ddruyXsn29VZe313629vf/hmABAIASSSDYvDR/CsOQ9BZqCXBDjuObE6Q8OzN+FCvHzQ8+Rsb76JyXb341ixqjjQItAoPj4WAeQaQcpCCcBsWVcfnukEO3axjTQFCe95fYmg8Dje52D0SEBqfiB8an5TobiY99+S5Zj3Kv1mhR8XuneOlhyrYdsWgqUZkGAMmeQoIqbsqp2Eb/DwACBBG3baTXAcF6+rS2cYL9+hJnUB/y/G/Z8Vh2e22gUCc+LIB9xdyH910H7bS5PNnbO8ItH+16Ew9/n7FLa/2piCmooAA//pwBCIVAAACE13ingFABEOLvKPAKACIsK17vGGAAQ+VrzeMUAAACgUCgUCj///////8kcww8g//khOhg8b///KBcCwcPC3//+LBIeLBgiAp0YLgCh////iEBsFgkAbEOYLhYYYAsA0AAYDgdjgcf///////tsen/8kJ0MFRv//1jAGwQhwqFt39v/iwSEYsEAXgK0g2AFP///8KQCoIgWACYX5ALhYYYAsAgalpxzZ+2sgDp2Wv1r+ZM1nHdYFyq/Byvf8V3JqX1QA+zKyk3/5NrTnFDHGL0Ho0arCS8Sih79Bp7Yq+rhXu67RERXPYVREDHXrlpbCSG1+tqqbc0lrOH5UAVS2rHstfFq2e2pUfSyos35HtdMqPRsg+VbK/JdAoe/QaedcKvSpGDNczQ/pI57CqExBTQP/6cgQOMwAAAgApYGhnGvw946taCScICSjBZ0Qco1kkGC1okoomZLdadprsRINPo/2YuC3iziNzHx3s+hI3fXlActpLLsa6qX7Xh7M0AuHf4axL+34SAz8jKnf+ocHTvW4NR506JUCx/bOzkRj6uHdSpONKhjUSGsNuS5HhR89+2vVf5Glt1mDSj0O/w1iX7m/CQGNTwdlTvdVwEOPO63Hazp0qACA4Qm3/soaB4uowYmFBfoDvcAeLdB7QrhQp/8G78P9fbWq3TK8iL9JuMs6i7oU3a/XYRehLvtPSlINQW2FGEM71K8p3cv//8gAC8giWySXtFx65U/4kKanQpyDbswLzczZB+ra8aD98MK5erGVbF2qiZLMbMLZnKINs9qEGWuCwYHgWcsKiNVTjVzHzLNV/D3YmIKaA//pwBJkeAAAB9x3Z1SzgBD/DO2qklAGJJZV8eCOAARkyr4sCcAIAABwFdttdZcXmjIKB95el7yJVQfGNNfMdY82Ji3/lQ5chuLS8MPEsNRpRXUtwlcSe92/XRGx3jNvnXV9/5d0AI/hh2yVnWOXahuH/qx/fx7WIK6D3wFXZsKAAUIIttwmJefs57KKSAhRVJ0rFUUpWir1bfturaEhYk8DT4r9YAAoFAolAsZD0udm1mlX//+//////j5xh7//40Q+Op///IIQJjccGg+v//38iPER8bigHg4QGoBf////7ikH48BYSRkqSU0Xg4ADDDDDgnECIzu///r9/7e/p//2HzjD3//xoh8qn//8ghAbjccGh6///+RHiI+NxQDwcLDUA/////9xSD8eCYSS5UkpoyDhMQU1FAP/6cgTKGwAAAfkZ3u8IQAA+Yyvd4YgACNxlc+KJEoEhna28sI8YqCGjUrkkQABC1GrHoZeK5uuZ+jdtO+iDXcRKGyZ1SHBwCIW+3+pKaDQrjewPCqc27w01bWzqgkgJrEC69AXMEIBvT9eyskjLqPamVG+AK5LsFzPJK+ozMlyGajiTHvZWascWcccTrT/ZfMjG0N1Fxh99Jr1jYuKysVri3bmUEAFGREl27WIlB6kDNRKWHCqoZqC8KYK4gqTDddH9eUAeUHzolw61Sxh6HORwVGhIOxKREWaCn9gmflSXw7rOyoLfuPVHg0YAACZkdrvWwgKHdUyp+OIfBNqYX/f+baJ7LOBZHop1oXuhc+p4Zh8T5TRC5L8mLhCE1jH9WHG/zIMn+Jn5VHyOs7WEv56o8GkxBTUUAAAA//pwBONDAAACFB3YUeY6FD7jKtoZ6haIzIdrpJyr0RwM73QzHRYAGAgBLbZe7nMArYEsMZmLoFipPi7itsvwuMak//UVdeVw3OWVOWiGyaxc5C2PtPP6Mx4hah6er++MSo1S7EwqZQBQAADACkkkAky0RQHxKNAF7dysN3qX4w4q3YZqRMCGKLM+UbtlRYitEtUVU7Rd1oXFE7DP/5kX+ie//xfWKIHgEBKFEBb/f29wPIa5YGd2w1qHEsjwePrxP5f/zQc8e3EDNPkcEFhZxVzT9BwDljowVT9nJtJvMEw890QPemIR8xUQUi1nrcIEms6Zu220HoYb4/GBX4kVFBDxtQ8IXHFAiuPvlC2nQY91twsiy3447PIeBQ4IV0FVmiD0zo9JNZE8WGpE8nIjDAJ6keulMQU1FP/6cgTVUgAAAh0V28jBM5xCoyrDPwwwiI0NdOOET1ETlu2cgRXiAAAcDtmeMEJvZILu9iO93t4qbsm3ld3Af+EOXdZhEHz96M/iC6IBoOAg6f4IOEAIeIBoOLB+TKOILBwMeoEJfwff/1gAuSAZVSkFkGoZ5zkeRrgkD5+weKISCT6tkc/+Xa3nL4wKEZ2+NJvfGDTrv9OicIrJQuf1QQdV+lihR9leo4XHLfqguAXZJJZ3LzSYfGljXlS8zcm5eTUnkuphHIs//zUuQlQ6FdGaz1ZPT7vvlp7kVjeVfSrDAcVc0TGtzGjr5gr3MFe/FWwSBLv3+lodUFQ7AkoePSJEnY2g6U97SC1VQr0bAgPImJvV/7uLrGPib95FoPaMA6BUnJrol2lIu/x6HljaErF3WdVtXqTEFNRQ//pwBDamAAACIjrcOGkQtD9kq0clZUSIlKltRLDkkQudrajAlUrAYIVmt0UhB+gcJzVEffgxGTQVn9I8E+nTV3+b/9OGM8nTo//9WbUqgLoZWsYSCv6gaDXOuuyp2LCXaBQVh1QKiICnZEAIAD13F5wpiw0CoYOBr03hItwZqgzudqTw/ChfUQ/AcGo2n/8mg/y7ybiGJd5XnZNZ263sbPFAeWTDO1I1rE4AQqCHfv8MM4jF+FxyohH65I/gicoy1CeYnH5CPDXrlOLPw6xj/8Zz3191Jng0ubSOdcR5y9DhbPG6UR+4XNLulKrvh6UBBQApv+KopVq7oSIi2GfoLp4ReNEtk41xRxh+XR8QBKcv/83N/eNfHafIpSb95G0HXD6Cq1MLPeaIllXPcwHfeeQmIKaigAAAAP/6cgTr1gAAAiE621GCK7RD51uKGEVoiIzrcUScrPEXjm30YpUogAgEAu7f2BHLKPSsajHRZ3VpsC24C+bOfldYcr1T4wInpeuM/6kWw//t3yNqyHbf/1oo559pC5HMipOGFyRNowZ1j/XAAogJd227Kcpb6EIuCfY2YmEeDG/3FZ+XR8Jifz6N/10XJ+tU+/v16fnZY4z+LE0VoA5ComaQpXvSEQ4DiA+7fBYyEMgcbBElkF4/R1FhcwZWEPxSMoM4W0GuNCDlHGTxEo+gF14MP+BLnbb7FwgPqLfQyUH52TarVTTfod40sl9Q3///pKD9dAACgCAUtjbKvlh8ByA9gBuMxgXiTYr9Ixw7U/Jo+FG+M3eLXqoCIoCZQwfRQqXFT5QPFJTHeGGMzhqnLhGlMIzSFrNK+pMA//pwBHaJAAACFEDeaMUTTEEoa50cIp4ImHFm5hRKkRwMrNyXnKKFBCFJolXXWGpe0OXA+w/yoqLYDtQ2c1HOUKZEeg+mpXrz//yZnxv9ETL0REa5K+nAtTb6dVDi6j5QkEAotvr6h36qAAIlUBF9dYgzcvC7EoakLXGcR2lCiT8opvj6zPan/9y4pQhksXQv/v7/hQQs/1SWhgoCbBoVDq1MwFWtm5v53JQRACm22ZpJJImik+IyURKuF4fTBXgl0LSWAw76CNNVb4r9cn4Oh4hNrOgtL0Fzo9q4q4N0s+TbL397DC3RUZQsOWCuUbBAAiWSS30AppcjKjiQSwaewf4LzB6Xx/M85irKHvkNOFxyWV9aZWakB5YS+Skagrm7P0FluyIiWGvx7qyzyNZISjD1QdUDSYgpoP/6cgR9JQAAAh9bWzknE3RA51tqHMKgiLTtYmecS9ETjKxc8x1SggAVf/9bubPfDZqAZ882a2NtH/5KVP5ur0Dm7W1/8VkHz/ukEV1SSWdaq5NdSKUQlDrIyl7l9Sft1SV9LyNr9rW/8O0AADIBz7+lUiOyhUEyBQIZfoGcQPjmTKN0tR9iB33/CF+v//319N2RnVDvarv2/vR8HKmhE1LTTISYKIAWpiP/rADm2sxNzwNrC8o6QiH3QTY62BHKC/P81wKxEJvmZV5QR3r8oV/9T4J837pQ+6FR2KZXQI1a6vSgIdFmc26TcNeKblf/8nAAAFW7CC4c5UphSDOZbjOfmduIAf0eqg+0if7DSJg8vUtrwuLqF2+un1y0tcTqc/ph6LlS5oVCIwWLNUokwAKnCY+3c5MQU1FA//pwBNXXAAACHCbY0ScT1EIjKxI9pVQIqLd3phxK8Q6VsHQjFYaAAAAArrhRhDwmEcA5UdOg5z25rbGKHoGsc8QGBuFjC9T/w0Z3jf/ZQC5xdRNZEJLOMEzCybV1S8hZhpt29Sf//XEg8CpV7q6vNpsDYLW8EmlCiy5mKTR90XEi92A8KHvimr4U1JS31Xbyg3nH/E59Z9b5+4T6svOXfBCID8ocEdpNlpzxBAmkg2yS7rbEJBlhTJ0pdwW0UrozqMth+HJwMoi4h6ppqw1OL1/8LhR6E9VM8GSwcNVN0Oy0QoPISoa82PNFpfZf5el31RAJORop2MkoEJUjQV0Bxe4sAWGPj9fW2/XV9WpwHNUqUZWm0etnYWo2g9Q4jSqjJcsLup0qEyXZY9VZFn1d7nyqNmFUxBTUUP/6cgRCzgAAAh8cV9GJOpREJsuKDWUSiFTrgaGgrTD3HK3okR4aCAAAAF22yUdmW3k7vJgrsPOfwQQ3Fuozih+C0u0UjmgZz9TDfUbU+Wkb9qy5Rwo888TUl6xDFGzvFzqESiOpZC+n/D0ggfAm6WSAnoEti4snA0ybArqHHhYbkfq5t+O152pwp0Qu3lKpcXZ3age5n//lL0cRDp53Z+Coh5Xb0Vlnyyg72+s6JYG2k7I03vt7R+C6uNRV548LqcH98x5a/gUwvp76tQEf7af9T5n09/UfsZfurLqhfl1HMNav7CI8qBBYkHjeMFiI71oCFUCrf/xT+cjREEI2Y+V7IhX9IsgyZlrRwtX4/4gJ0fHGcUPX+b3/3V+9Hz+m5+it5WgwKADVut9FcZVzKYgpqKZlxybgAAAA//pwBGl7AAACGCVfaGEoXEOnezc8o46IjOtk5ZxPUQGOLaiXlISAoAqRJvb7ag2pyJVXcGYgE1E9POwlOV40mQdGAclOKXFm/daYmPuVAVsiTi54Qj0hKpix5jIrqjhWkANOwdtFeW/pAIADN9x58LznzvIl3h/jN6/C1rxZsE+sKjI19S/hZPrp/6fr9qWNVHLs1eq/VkO7ETm42jt8CZkyMFRIePC7w6FB70wGAKu20RWw2HMKDwjCqiqt42oWJNUzVa2g9lXeVbRqgHG1Zo3/8TRh8T+7I29luWvfZ7KzRcqj3sFPfUk453dN2WMT6sAALANrSKTao4P2VbKaJXG4iTD+i660aym1N2wkX4hT6wfOCAYNBx3BA5ydQIQQcXWfUCGJ3nIgUcE4Ibvn+XPpiCmooAAAAP/6cAS8awAIAgVa3FDhFyxCxWwdFCOLiG1rb0SMSJEcC6xM1QjogBSYFSWAVi0WF8wvJS6ajCKKXz9NZ8Spg89S3yoSE5ugl3Hi3+XJ7/Ry1NspM2eiIl42Zn////////+mnaGdv0OkItNtJWMkpWOUfGqKWoV7lwx5Hl5o8Tn6w/mp8lfpXudME8yXUdYAdTpsBnmh7K28Avc6LHn3YUeqYW0Q3MY/fjWgWAXv//Bnit9p4L2lk8EJwXJtkllgk5/2f5tf/531p72IbKy2uqNT3JqoTR3s3602VF7U+yH/abe+1HkfP4NpFFUqWAEtqcnllYioGkMwQIP6iQ8x6BKbFbPq7MJeKeonQaB11W/qhJ4caHasRSoakioNBWZBd34iArvldZ3ulQWJQpEow8CtR4ktMQU1FAD/+nIEuOIAAAIRJNrQxRGEQQVbaixnNIh4ZWdGJKcRBpLtaKAfQoQAGALv/9KtwhJgMWDWjLhD4fi8+kFNcnTTQb/l/98G8pmBKIlovagYJVJMNKiJREu0ZFLAuMFKHgas+56Xn4CR9cASshF7/8KFuYr2dEy72Bhs7EJaoX2+w9o9R7RsodX9W/52ov09JVoVMOyi9Qo8uqYc8asgWY2lR5s3felLXCKLIAosQZNvrj+Cbnsj2gplZVW+kLx121Jhw/A4qWNZsV0egH6km9XJzutZpSHzLgEhylKL9LGgySQsECS1t4pqoxZrfDMAIkAgb/+lD1F6KEwFQnyOytRcq+LD09ZWvj38qW/2icNVpjDobQFQGkJw8BiCH1A4gzumSzUsvFRYo7XTOx6znqTEFNRTMuOTcAAAAP/6cAS8owAAAh4x3NCpFQxCxNsDQAjQiKCTYGeY6ZERjG2owxTylCW5EuayuPgMyocMnMPTUWwk1Xzkq2FZCjIF77vhj/bV/6ej5vWjtaVyWSgcj2jgIkmWBUSq+i3oLKkRscSoELhQ16gANbqFH4uyQQCMNMWJjBInyVTrJOogBtmzV6j5Knx0TrNl7vkob/hTyTAyKVJRFfmaXoxZFeKQ48JFTYrW+1H9qdygCpJJK7yK6x0NhRDpykWTCyiEoXxKuwQq82DUztAe22vK5gORnU8yfMf+3QfeXicBwfE4eD8/W+XPz/+8uP/9RDV/S76kBAWBUv/42OV7uBclVEundRjPwZD9WXDRDq56mbXj7BZEVBwGwI362rzLyZ4ibWHw455BhLpeK8vLtTFlpc5lhJ6VoyqYgpr/+nIEkWIAAAIcIdzRIRIkQuO7qiSreYfUwWrlnEqRF5gtnPGdNsAAADN22+jnb2kkA5SNtNqg2idavkqEaxk9FH5KmEhsrYe4CrNFCS4lfQ8o5jZaaTERQRJt8yxyYUfBtUFZUmQHtR64gEKBUdtsuudZ1ZCLfbqVVrsR0CRHibR6OWrt9V+HjO4lRiz5Ue23v9C63w2VCoscVICgU3qc/RLx5I1ECFOo6EK9YEABNvtescL2kGA+2fVGnFjYJcPyVfD1N21ehTaLHmXC/Q6WuVC63pUuqEww5owCoMB5akoJnm/3v6K+z/4bgMAY5JBmJ0nEzDSg1bIoBCwIPcOfCL/ooM06c31J0gZRBYp7uPF5rZVtmqn/9tTNx996z4qk6w+QDL25lgCI8m9qUfi7UJiCmopmXHJuAP/6cAQTFQAAAdIu2ZmHEtQ/5gtTCYUGiSzBavTzgBExly4qllACADu20zpCtHU7CQI9PuDOgrMqGOInPqXSI0cds+r4vx5FVNP7f7ciNa5wQ0RMY+bbrIJy2mQqf//v+oES/7iNg8jCo1hIJPnICrhgNhzh/60mzNQur6gXvGREz7a92qXT9mKVTKg1sECwGh0eBqZgOf7Z7W57AJFaCkfRQEO//2B8qyNldvCu1EpBlvdXamA/0FfbdWGsoe2ZrqhP5qmW//H2ad7qfW7vaiBtMsPNWBwqQYcQDChdI5Z5hwe22XMXcVv+yAAGCgrrdkDumOIIo8Cej0F8+bseH+CH9WSHd+n6C3atP/87+2R0IKKdyOKH1eOAa96k2nOJ++TsPmQQBc4QOCpA+XFRAZCDybiCKyCYgpr/+nIEpgMAAAIYYV2eJKAGQ6a7p8YIAIi8b3e8M4ABApLsj56AA0AAAIBAIBKclVPFE0mguxrtb7E5F3223r96REBF4r7//////IhJ0b//8jRQTF1P///9hMXZCHRh5P////7qLh8+To8ABwkiC3WiwUDznT6poEi+6sO0CPvZ5CK4AcMV7CmciIGfXp4yaH9/+n/2Q6vpMtNWuiIplmFVLi/4gMiJI+//rfPMQQQEgp79a20s8NAahwhP7cp6ZwrNNRnKRROsZjciu2IRojmEL5tTNh2MZNlDppn6Sp5Z2xGP3ND0yKqCz7MsiKJunU4zVoBV2AAxO+J8PFWnKLOTJwP2Kan8JWt7HAA1rB2/L/ii1gRfGmfiZZGhFUKuHBoqWbQr9KzMMq5HOjQbakurSrkGpiCmooAAAP/6cARaRQAAghM629DKEbRC5gt6LONviLh5YGwsq1EHGG1ctojqhAQIkxpEk2uAZNMJhBJLn46TYPhNVrFs0E2DbVqFG55jblYzVUu2nQ1XzG//0Nlzb8sMAv1hoFeee3lXfrcr1uliyACBAF3SSSviId4JYQteCuLi4ljTjmpZ7nsZi1qluWxwO6yv/yKluaYXt3ZS/p1mpjnAOEn1O8UTMCn2WdJnvqdf5EASSSS7hm0K/MKyN2Hkyp9duVtELDRtKr1B5+ENV5Jz2bijV6tgfqaEI4JuuUfkrNCdjSXwLj/3aFGuzLXdKMKHuKIZpas4Ae3/CrsXF8GBUFK5QkLkY0sPN8k9A1XB0qM2N21F9Ian/mRt9O/u/tsDllWtOT5UUdONQ95oYLWAFqUlSHkoxqExBTUUAAD/+nIEx/gAAAIkHFYdYYAAQWPLN6ecAIi8c2h484ARFghtTx6QAAAt+BqsUqIkxeSFVgUctHImFTt5ENPoylZvryAeUKRStKUr3E95NZFgW/FOZ01i0vnRhTddmJKdVFtv7It9HR/////hwAQBkkkmaYIATedIFQp3je3sFPRXxcUMYYGH1qXNfKlm2/OFDY7EWeOVhlX0xJIKODnfE4P/OS4f5D0l/h9FlThGAJBLNsBABAbm5C6mWbx/BI4BEoZpaiobhmJjQCJQKiURQyTNQgXd6DhZZOlRb/oQoRTf+2hD9kq9xYDlYoFhAFAyz/84bAOwv/++H4qWLBDF4lZdjyQ94SlWOLY0LvTc9gq4P7uQ2owtoGY9o6VYo9L0dlvTgFj6LGon1iKFNvWYigvCKv9jLEL9W9MQQP/6cATlbgAAAhNd4x4EoARDw5t6xgwAiKkPavzCgAELEq2rmJAGAAgtFotFo/Kyr/////////r/sc8+UWECFVf/5CSQIYziYkI/8jSYvIc5HD7CJhiEYM/+5zyEZT5CYw6DwUOWMcgkgAAAADCS1mw2GAAEIjaMcHceOJQ/EM8uyqXK1oU40Ysvp7HZimmZeYoz7w8xiZdqRIH5dtBZRo4o67vDQ97FRf6kwWRAEl2EonPsPdeC8ujtU/Zen5ZVUCy0fRqvfcv/QSB9HuWjzOpfvrM8q+hv/+3q3+hSlbR/QxhIex1dbvpbPMddHp3SWSLYAVeUbaGAkb0eRdbTksY2yJWvWDLspFnXBpqUIc6eUqXOC0/Sf9b/oG9/Z4r0Za/c++q+qn+nTyCJxiQEZi7v//s1piCmooD/+nIEUEEAAAIOHVrJDDksQ6S7Nz0FRIicZW1AsOExGAytKLGc6lAAGU/Vt8HjHGkllisGhhMfTL6F9RtnAYYdIFv01GTu9I4HP2NRDbA7UmhHnfZ+SIqVqESCJ34seqs1sLPIyoCUPgOAHttxiPYmaq8sQhuxbBhLk26maND2rsrGbQd/40K5pIzp9HsyjlDY0UPLaiydaZ6WiLeW7LwzcylLCZ9o9L0rLLIIAAuCVbJJfGMW1VjbDWAj1LTRI5e0aykR2SUIN+0qBAjRK+VAETPFhYi9LWB1QX2j03ipl5zet2lMXioKtIvFUM6b2eaAACAAy263tgFSzVIABxMcF7z1Xq+vFbakf/KAGuKrLmFV7iaReJAxcfB9vC61BhlRCmCBxwXFw+IxOPUvVXOZyiXPv6/k0xBTQP/6cATh1gAAAiAk21UkQARDw8vKoSgBiK13enhTgAERIK9rBlACQABsID//y/MmMKCAmEtI5G5/1lAPQAyGgol8OJbTXQY///zmWoMHiOPKT94nYEhCZeXbPI5q4YLqU08ftJque58uj+uAG7wnbG3Fw4jQe8U7SCdePDJxBWQvqNW376gqq509VUtYpKRQmo49syst8ZYBbobCB2klrKLe9iAy+NZF3VchoQ7ZrAAwHA4HA4tZBQNMUVDDvfbT6aaW7d+/t7/+r5//9BeZHDf//nnkypxYsjaf//UeIqPlBKYweI/+d//3FA0NCRyCDSaUFgAEszCtk/3A/HA4GJx8QE2MGisltMZEIjWOyPQWbH9zZ0bUYz4RdJBKjTiFXsn2Nlf//WNS5pcrf/9hF0gf/9TAmYepKYD/+nIEAN4AAIIXGV3vGKAIQWQrB+esAMiw22BnlE7BGQyrjPSpEoCADq67fEAC0dJFjkE/nQ/OAe4joTJuys1gd99KsNAx4qsck8ISLLrwKMNlQW/9l8qATv4kArHyr6+RqmdzKJLPZJABwlLgAMOoTsJ1lgm6nJoupYO/MqlqNa4AeHnGiOqcFTuFRpLd5DN5bwIoCV8EnJbUNfMP0h+Dosxu3hJuKCDeFwAfaNvFIInjjV2apTUhtSh/lUXoFYwHzpUcIMsKHevR6gfvIV0NTZL/M9SspdHK3l1R9DdHMBNxE78SuZz0RP+s7/5W0GgApbaJIj0KQStG+CKyzdJKbIRgw8fNhaa5mKBBFlmtqb31BJxZSU3KpqskHijCYcKhZwXtFgcNn3Q01ZkvfUhPcLtQshYMTEFNRf/6cARBzgAAAhElWtEjKZRBoysHJKd4iGS7b0OcbfEOk+yc9JRqhABZETf/1R+yboHyVsVA3gnAfRMceoYAYqaLPr07H+WRNf2bGxbS5seHyiA4oCIq3saHgKcLrjE3CFSdemLiu38PQhACl1wOPmAhLR0sKbhUUvYeJXhHgC8p4wMjiRBtTflAd0ade9HpRh1K3jSIWwiCbqzsSSi6I4q7PGkrHLPisyq1ACpyS7pI7wiLxCpayg+ygDw+4YfGcXDSVIgRJtV/00BaLu//1nHLi9rf9ptSNAoo4Os/zh5dzjL7EMVKUKqiZGyr1ggBC224xPOSI300Qv523udkfuJaBL6MIMeFBjxvtjRn//W6XZR2eMY5uu0qlCDEUYpSdwQtxAthSYcSKGmh402LBhDkxBTUUzLjk3D/+nIEboYAABIXHde56yrQQ2UrFyzlhIjRbXVBiKpRAhJsnLOO0gAgD///5niIEr4ZdUG0Ye1HDd41Htg7q5M/Ov1aFB05IPx+mgBgn1eIHykza6qo1n7L+sc4g0nEG596gx4z5RPU794BwA7tsNdgeAndLl3ExPk8nUw5WC9qZRxUMM4gBXqX+vyydOvIbf+L1CowuZU5DjLLzJ1YuJC+2tlCHi9JpSnqHoKjoCsrCV/3/sxQ/Bxo8CrjMiher5mrfoXt+oZ2vdP+pnlLKis6GZiC0pSuyb/TTb+nb9dKxZjLaVkOZWSqb6/oxu+/vcKfZkgbgGaXUCcF9Rc5tYQrbzhCbSfWq699caZk7MBa9TPzAccySl2LXbVpWVAYIupMipFcpaUZzCMhqL6upumiBvyiUxBTUUAAAP/6cATgSgAAwhsdW1EjEbQ8xKrDPUKyiFxxa0SYRtEhEOsM86LCQJAcFX//680lF6D2pHz+ONiNR8poSD7jPUv1HE6LJGJLrteS3DRhFZIhYlT7HDRCKRjljkUWVMyyA6HW941abO4OfeAHJJA2xHZaBPWOxXMP1I54/gp3e1TP5WD+LC1iog737YgU6jHltAX+fLAUGo223UZbF6Pp66V2GPf7fRTAEgIJv//uGaC4vxqAZzr7Rwa8fVvp8GzwfvjN8SI3KqeSMAgMCgBTJBsSVmkDxYICh4KY1E5cqpcpD88qVF/Y1V/tAEkkjqstwQ8rn5AMnlquXLH6eNvWEV/Vkm8KXyOiYpfG7hlqj3X2ADX8adHG7GcjHHkigkbl2HB7866jusFW7WsuZ2j/9Hb60xBTUUAAAAD/+nIEhDsAAAH9Mlk5JRvkRGM7OiEihIitbWVGhFtREJZr3POJaoAECb7awdgZNXIUM9j5ftgO4Lq/WMczvDr433yjv7nb/yTZIZGt5wj9O7JVWIDXaWj+TfQIhvWeRVO1fa4r8NwgoySHtvgQItGtQYNaTpM/WOS66QBd6+ak5AL/2XUf8o3s9wigAPKaduOUSLUl6n7SQlEJoOIAoghwVJgidCIzbK2S6oAEIBL221JjOHcoSeSBuoz0XUTyFUlrID1oTlDqNsxS1H8vEHv5/+MjazUPWsCbnvOZmQSIw9ovxev8Kk/2kXS+vZf/CPAQAy62yT7KN1RJH0lNMmCO5cjjV5QVZh0pCxfFA+DftgRut6lfa19VszL03drjMAQfWHK02PeLRRq70o9r7/rVdkmepMQU1FAAAP/6cARjZgAAAhtbXehHFgxEI+tqGEc9iIx1bUCkQZEOj+ycFhwaZABShJU29tqHdxq3j6YcQjCm3+kM2p9G4zUFBH1F1o5HryPm7PVHzgindTq97FK66WyzWv5dFp/y1r2Sn/6f+n/XBNAAkwS1skDJ6yvYQNWP25nwPMsEXusKBMXicaNrUwM86KDR8deROmnFxIQYLUsn4tK3uUL0cJD2saKIQmq6Z3kinnkh1ACfQlf//rxCLfrn7Y8qy8HXYLgynq0FD9h3o+vQfXaI6klFsDEe8+wIR5hVY5IraiTGqS57WNJmTh9BtjfQt5gnazw8AcM3bbW6HKKo1mCu4amdzNuIjzTaFxx2cQBMG4pFbb5gTvmx2ytHGobjyFJ5dhgB0GNpwetrVk2M/Q4X17StrkDa/rTEFND/+nAEteAAAIImQtg55yrkQSMrSjCnTIg4d21EmEURBIytaBSUGgCgmW7V5tU0iO8h7q6RCeTXKEbu9RdlBtKRgvhQo8qQ1agEJ9Zb371XX/9/nLqyvRlMytPdKXWyHy9XbFHlR0Bfd6KfrAAQsJXbb3c0yd0a7oOglV0XfgZowxrhVIUWL1IaPjcIJYutCXJch5incUAHn7I8+zFaZdav8H0KHHQZIIQIcPfbABzQK3//sa0gFvpozh+ZNc4PkwYnULw3MI16tR17UJCIF0IYcEcgISCAJiP7RaoyTaoB9yUyw++t6a0rL2joHT961hKf7+1p7OMitqhs16huObAXkdZmxgK+P/HAXLK/KgMOBkJCQ8DLyoFGm82vd0OyTiAVsVGEjJ0WFj6dY4UEX7ExBTUUzLjk3AAA//pyBB+GAAASClra0UEWZEKDm1okp0+I0RdzooRcsRgU7SiVFP+AAugQ9//mLIIIli9g4pBLdxtUT8qdoUrI2ypbV9eJ/3/9vti+Q76JxsExCmJL6k322qLJn86iX/EvI73Isr/u4RECQwlLZI+7k09VE45xadMaIZ+bdGGMEx2YFTB/wdA+7RrD3n1paLFWliaWqeoIyNsioJ3xynWPNvfqz9SJiL4jV6mEAFGyCrtbYQdCAPGiQLFYmkocXDrxo76u3EX766lBu8fbm6zCxER65olZM5DpB6Ti+RXkVLdkUiIx6fiDz0KYuqpKb4v6oAEWBLqh7CTbGB4NYomJxzHj1NypHKKJK8fw3V8o35v/0Y5G1S+IJU5fg6uL8fzqjsSl0lvH0yUbfrRpg36s+3v9Hq5/bNMQU0D/+nAEMJAAAIH7W15ooRdMRIM7Fz0nNoh0d3eiiRDxFQytXMKJFoAAAk4lPvrcRKD8SPPflfGcdzxo80lH066hF+8xCjEKX+JnN64jGYjVGbcAKhJWlBRWXyy//+9/l7l5/L7eHLAABS7bSTe1t3xsH8KZBervOUXxs22mjmvy+pftSEXCeSwmHFZG59ZeDJ8kiJ4eLCQDJFgWhSSSu0Ua174eZGlrhk2n1oAANOQufa2y8YGxhg1TKJNnSoB6isjQo5OcU85+nAVuOfncoItaVgEwxopC6xZAv+ti3jFNbkA0WL28bW9iD9rGjP6zgAWySY/7n4Jhwr0PXXOG4XQm6Y6PghWr9txP/EhMKCrAqYEl1LTggmkqBitShdh0sACBZF7ohUsPDiqyxsMhKxrmeG+xMQU1FAAA//pyBHhYAAACICVe0EcS/EMLW4oFJR2IkFNrRaTlEQmMbAz0lNqgCfyrv9trsUeCUe0Y9shyPO3O7HavxiJguddWkouT5ZNhiJIEhQvEtrBRjVpJGo1rR7KQVSONTZITFVMVXtjxDfOeGQQL7JItlltDlRwyf7vmbbYgrDr6D8rso87rChbX+Uf//+ZeTnS6d21PfSh/Xs1ul72NNVN1RXL6kRk0/9/Sv/14x+lACCQjf//JdRuF9YBSal6IZZ4OzuE3K0cryg80q+4t2hN77B6hd08HWPNlzzmkkHqRRguuH2ode+XPUN5R5FEDqehF3qALu20zGqwalZxilqFe2l+ZCLwhz6LV1HpCjdu2LHL2/1OPLxEDRNYtCUDIocoKupWLb31k1G3gySYkjdPi5cXcV9SYgpqKAAD/+nAENg4ACAIcE1rRJRKEQ6OLmhhFO8gQT2tGNEZREwyvdGEoPkABWBM3/+v6MhLjYVBjmtDdHPcvE7hKOR8whyaJzSn6a28JmQwpx8Dk0OGjYswVe8YKuWfD6VBAieFVSr5dzC2tlPmoQI7KW2tofNfJFojTZmmXFtUN2jYQfGG0ftiKfEFhfv/uc0NEpZ02Vz/fDdz4uzf6J6Yxr6/X0x+WBM51fFP+T/c6jSVAq//+bXBWq0TdFaUFhqRQ8gz4E9gOkNwYmp6nKfdF/kCFY4UMLiIwkcsU3iS4XGoMD6qLyDnofpkSZJVwtT9cLBMLlbe/21kbSgONGkO1nwupVtHKmBkWuc+hf9BRlF1ajKFAyG71OC0zp2IizhIPiNwiBKElhw80886sRk2QOVit932piCmooAAA//pyBFZKAAgCERlZ0YUSlESjK10sR1mITH1tQ4jLMRWMqp2ENVJAABgVd9vZioFrkjyIwtaS8GcMNm4njUg2wq6PpoI8oGRZy12PHaC8qKg+gFdMbSp6WpquV+0BgdhsPD0GC9rSfw2iQAQViS7ZJGGSxruFpDPgv64cmj4iMACAoBEcO5+hf84J9avLkC4oFHMcT4lcSFk6Lr1CzqkRMhxYnIU6W1vMC0moz6UbSdtkjRoKhiKAHE4yherZdDbCoNAMu8iv9j9t5QWhjtPhjzvy2lUMCoKhUnTGuc1TN0BO/RpMxzKLHuJn09Ebt8iAEAKSSK5yfadIomzkost6UvttFYsDgI3TXlJs4yRfDCavJ5f5t+TR81JZwBexj9iYo02qoxFPqEKFWsRu4acml7U5nb7ExBTUUAD/+nAElccAAAIgWtg9PEAERGMrGqeUAIfxF4U4E4ARERxwdwJwAABhG2220y/O8UCsD4Q4bbWwUd/e30XFaCXyqHI74czQq7agXvCnAis6UXe9f/Zf9KN+3/////X2Sn92/+uv79wwylXtAAWkAzbbDF7OO6F0Ju70qffGKK2PcjVAVc9XK+ov/4wO63sVWXGAkWaoHqVEXoYKZF0Q55gLCt6LyrWtJo7loJW0WDWAAAEEEGGGGGGVcArYf+YK68Jxuip883/55i2/+7mVT//QbuMC8///2OIDUXnmoZ///lCB8AAef//KCg1I8CAsAAAEBQGAgGBQKBQKBRkcnKn17hPbgAC4uKiXzTWT/sSNm//KR41V//og3lib//+xcgNSYOiD/xAfGAef//KCg0yPHAsmIKaigAAA//pyBOI4AAwB9w7dFyXgAEOBvArhlAEIkENgLJtHCR8r7mj1FOwCl/YSFYXARGhEqhLJCNGo18768us1E7SkLI0BGqxEK0EZ0goKjDyj2JlxFxFW7vwNIz3JLUm0S5UzXo//y1QABgFutpylA4GEMhkVlDHUqzVbGAU9GPlREeKkiM6QGBUBHhE/ExWIuDWm6+oGnkZ4NViVak2lcq6t1dMS0LtivLNAwuLDGMgC9mzssRXTFVKJ3QApOzDthN0exKHxiSmO7dW5f5dMCC041yAoghcEentyZF1kd801dEnFt2fb33Q35003///2ACgYi9rtz4ggOpRwFe4VOdTGfd721DIADhs9E1WykdF9MZR2KiHfTvGtX/8rajOZPfUrdMq6e9rsPvW3pla3on///QWf2e1CYgpqKAD/+nAE/oUADAICDtmbAsIwRGPLE2DTNggA12JszElBFKvvqNUIvgCU5aEqAEoaEyiBoLcF838yGDotHBafqxIyKTim4yFRh9QNrXmWtXkSOhJA7lkuSlQNZakiJDdaiw3xjxo1H/pAFqtFLmHUwtKApc2VyXascYerJZxTJNvD8gC3kyXmsZJ3Wpdd/15nn0WWYCZ9J0DNwke8ru2Bpy+jZKv+oz//rZrtZ1AmWS7MSE91lwxfemC3eiNMZscQ3M1Tq6ycAVkYmhNPSTMyZfq7zc31p0Pp/7br231/0G1t5TTb+9vo27N3qJdQgfwJzNtyJCmm9all2VWnma+MwVN0YttLpunMZwBpGPRRijIvo/7fp8W3evrLZymbR//oP9vqiv32p9r6sqn/EuVW+GOhMQU1FMy45NwA//pyBNvvAAAB8UDe0OEVXEFIC1c9ojyJFH1mbDRLISAb7eT0CL4FL0k1G23AqDwrLmDyLLnHTMtp1EUNHq3GUKDiP4f0+38n39P5/lv9TkK9Y1a9O98FihtVr1Ur6L/rduuDtIEAnHE5BORCIc/1dlQY/oKqR0L4QIWhM109Cvddy1qDBBdmdQTFqftNb1+ySaFH8j/79un/4Z/2v3t9OT1B7SLdai0ityspOF/ZPJ3qgzkaxv1113S1qakEkFutb7BizCXam3UbsrS6CTzwobqqflH3BJXlnw6nsfLsJNObrQHamWGsyKPoTVVaHwAlUV6azNB4Mm/I4Ji13HPMP7JSWCACLz5itoW3/JIK2daEdVN1oWnkb7vo013/KlHegVzx2tMFipVLdTI3xd+hmHaecDepjUxBTUX/+nAEe60AAAIaId1R6hpsQMsMDRwix4h9X3FHnEXxFpAsTYeMuABUyLdbSclG14+7U890Mt1mq+gVgQDLpbnzp8b79MjKqUiGx2QG15U5Y/BqkfDfWAILR29mfT/ccVdQa13oAVbt4bsCRSiRCjsklyhxS6KcfarbPr48M/ryL6fx6zg/5lMMua/Nenl96wzZBMGmj+ZN+blptXUvkb5WVd+WZ5IFnWfcHAAJQCUbSUYxUtUfbepq2vayZnYVAxP9RTK9/nak91wRmnaSa117Nvwb9iH0/vsR75E+/Sqv1l/b//6r/9CiOALiM8RUFPnP+yMjhAVTsrZCJUMSLeNj4esH+txpYiTBBTRP3KF0Sn/59oSo5nC6+SBnNDzy9XXp/KtvJewKExs83YM/UjqRu9KOpMQU1FAA//pyBPPSAAgCEBnZUwlo1EOD23o8yguHzFdcbJpnARCgcPSAiuYACAAk43JB0JRRuUTeAoDsseacGG+2/dbY0hCkzVX1H1bqX3SLIkIv2NLgFAs2DPXtZs29r82twm7tbbv306l0VZEAGEAVEknCjEqlOFnE498ErM16UoMQLEb6Vb+3NqZVjjkKkJqKllM2dOzkFBkDRhVa+t2jzd6ppTD66KKBG8fU0IG+kMS24YdrFkWFM5mF8O3bIdjMVDjke+uTizIT2A2wjD1UmOkdNajZxeg7gSdRWWdZ8N1G+dgVNI8O+un7///SE0lLapL9btxq9VVnN3mv2cHdcIsDQ/Ct/2Ws+v+ZiwuLzAI6OFhfyH+f357Uoot6I+Vf6EVUCshV9Mr/OuL2YNd2myhMQU1FMy45NwAAAAD/+nAEQLMAAAINEN1RYFOMQwl7hzxnDYhs53lDKG7xEqAtqLaKDgEeATckclClddtJHOerWq5p3GYap2LpWWuSliSUDtYptwu2hTqg7Q9gzHC4VQUH8sSUcadlXEph1Cu11FDuy61nSHAFVxSQjNaXHEV2r3zb+IgO79X7f6Z+m4sSYY5Vnur90+9tzD255vr/MbtRF9EVaGKO5lTDeyKifyg4deD5yvo/f1iDeEpNbJaiOucePnl067vf6hPBtRGqMfHXZbCL+as0RRc3pXt2dtnLhdh/xPyjzh//w1TuOeN66lAkmn/VxTkjVf/oBASAoxtNwdoTVukkC2aW4q9aHTU7D2D0irUotKCG+nk13cyPOzPZSK9vp9zfKmh9NWn2rZv8rIZgcV1z2U+lG3t8+rzyYgpqKAAA//pyBMvpAAACB0Ff6KEV3EIIG8ok5XWIAQVkR8BLMSEgLajDig4EJJwAuXXXYBB1aphZLzPUc/8BQ1V4wfuPJcoCMxGA4YiszdMPn39sayAvJx86GFm3n+dNrAlYROH4qW4ffiyF0infgmtbLaIGo7nrZVdOhdKkN38Thr1I+gI3/l0wWpRGiNupy7L+T0fxttdWokj5moOv7oejRN0GTOM7l9rdX+D30C91gZzgu7Uis7VfdrnnzVtdrhYkO5Z590aQ6ULXzPbsPqlVzNZNH/plWZDI/NkTVyPqJ3Vv26sJ7PpXI1p3kzAEtQAGOOQAWU1enWSsqmO7/9J1lepnA0Ai3Be3/o+rR3K62Vm0NNdd+8HZUa07ao9KmVRi0Qem3Uro/BsDjjqYfe8iyY1MxQcmIKaimZccm4D/+nAEdgQAAAIZP9q55jhsQmarFz4CWIf0ZWNGLElREaAtHJUNPgcBONuQDvWS6wCsZb7k72mMzjoPQZfo2UNPnlqVsYHuvtpVr1qqq9NP5R/+1pqXY52ZWlW+j1YyPiFo1CUio3dXlwCEQFSS3AB7cKT2llQL7NqunmqD0mZBMcwCyfXulKjf37b9Es5T+kpGROn918j/2cyQjBcOihBk9cKz9nnhZrF2ldywAACBUlmwAKbHp95WUJTatQf+Lns/8PCgey8+srP0EPt2THtQkUAQrkXL3WkzkHnD3fXR1uNkjNJzhvta5k11lQBVccgACPKN7c1XejPufr4tAXsdu5r1La+9qXo3qobBM2lsrNkT/mfnmdb7BtO3/14HU7S8p/5bcOB5l2uS2NZHkaLExBTUUzLjk3AA//pwBB5zAAgCDxjaUak4LEMICwc+AmaIjNVUbCBUkPUM7GjBNRoAAIQnHHIBUZA1pdgTjayvo7TyCZgUAuz818qQ0L8+aVOFjZ8eYEDVuAwafdo5K2hCz6RKoWdKF0A0di2lj9SEZ9YEAVJLsA1ixIjTva7RzL9XrTdjdqtahFRKRo1dE5e3FZmz4wz5pV9p1t1/q3R+vVnQrh+ve/uZVmUW8OXvz1G3UnTeCk3IAuuVpPTzvocXf20CtAlWKWfyo9ZZc1bzniUTPJZ/dsB28ip8bNUxep+8VU2fa/WTy9H9rP1Vtes90ECS1Xa1ZfsAICAJ227A/GAnOx4lgPshbYMARVJxNQpEj1dTdFW3TVUWu2CARChceESMDJlwEu2VZ60OWiP2yt+vlffxZMQU1FMy45NwAAAAAP/6cgRiVgAAAgM3Wj0lQAxDKAsapDQBiNTxcVhlABkZGa4rDFACA4kpHJA3hzGkDZkdqPZ/+xz+wtAcfqTlkYifTpdTS7p3qjGMvzFZN7XX6fb/VqmEbHSGNDOxg1J4UXxVPT9MtaABAARbbjAsIZQayKcLbw8twbuqggOwEy6b2c9qWgr3ZdaHrUkiuzr9tnv1f2buj/tWqp2XQu62bXTSRU888Uuj1f6QAKgALXJ9v/xwAACAIog5hOoQQu4Z060WgTySLIswyHds9e/M6ELZw6mVNLUNJHQ02apE76kJxqOxiU1U5mvY5rp/+hZR6oAEoIF8s3///4AACkJUMiug5fXWHu79jgc0BR0WZWXHGxzc6ElEGpHM+iI8RHHDpVF0OZCknno1YorqiNOqIPfaKnMuQOVJiCmg//pwBILJAAACGlfhHgTgAkQq/CPAnABIlOFwXPKAARUb7p+eIAAYDj8fv8fj54b/+s/XT///3f/5yOyGf6uQM1FI+MjpP/MmGMfnQ4Rip5xI/Wb2bPPcxswTmJZjTzL///mN+RifhHEoRQOPx+/x+D///7zM55Vv//+7//OR2Qz/VxoZqKR8ZHSf+ZMMY/OhwjFTziR+s3s2ee5jZgnMSzGnmX///Mb8jE/COJQgPX8UgYMc+EmaKnYnydebTrLS3mKxkdBIHBBI0xjK1HSVi9Stly1LQxv0TSlDGTREN1MdvWno6aipS11Yx6vwC7p//5UAQTjblujvFjXS+oX8KAw02rXuLZmLMY11FEeYz26SqWUylLtQpVLQxpf/No/0N6Hb9PR01Ezy8SiKz5UNSW+xT9d9CedTAP/6cgQovgAAwiQlWMsjijBB4dryaM9GCHjZYswoR6ECiesJpkEgACAABa8a8Qzkx7eOyr1oTewPTOVWsCDbIaSimE6Mi6aqdNqj7K09Va097X1af385Wsku5yXOmkEEBJT1zSSyA1dR6f7Rv39dRUgjx9oDopAridxr8uCmTwtgZB+UunqYYxIUyAIfGtlxrFxWRYIb5EudZtySFhzurAMjbw6VMBzTsv0V//1gIABq2GhK4utGdgxypWIiOj4nOdOztk4BAKdTdSrU3Qy80qO381HNy5v+hWfWbYpabWcpnjJJNnWbzMqVY9tbF8l+xAt/mFApzw6nwsFVojzbX2p5PvP497V979+ycKQJpPm7ZS0lnVDgZFVJqqNLDvLLRF1Ke5SxWjSvIVr6YMf///+tMQU1FMy45NwA//pwBNdKAAACBjVbUeMoTEMoG1pBAi+I6QFfTRxHgRqgsTRiiX4AGpEnGiU0mAVLCCEw2lGvi3LaYSN8KMWrmay7WUdNqRaTiP0bppVX+q+6LZf8QO3ifzlX+gqx3MpQ2vR3oEz+TECpAtxElMX4B8zoqGu0slGJwI3v/AOBH37HLqKo012qQkgyqyzva3+T1J/+M/ff66Q/uv/oN+k5oG6NKz/cveoPryIABABzW3bCAGUiW0fqBa0tdwLnDVi15cP0eaNCAYrWGbUV1b063Qt6K/anT8b+71dC0r+qKK5mV169/DjFO+17/aj9HYVEtQkktucu32l3cMEah5Rjoa59WlGdAkAxE2EU07M2+wJd/0K3/VfUT+yetmkf+r6jvdH/N4Ua+9lo9pY8aXjRJi+hF8s1j149MP/6cgTCaAAIgiIrVxssKPBDwzr3ZY0JCHxnXuyY5yEMlyvNligkBdse2IACPl9IGfFZJUjN1Bt18nrZ1K/MYOAPeqOy1Ho/3k7u1qSW9fkV3p/Gcf8s+dT32EhahtLrGUIljJ3Yv2aV1YYAIU9EnKQAEdCl8MXUI9MYHYUOpB56uwTMEArWeQ7qpfaxw1sjmCR4oa0teW4nxvz2LPe91bp7KeuK1YuYO5zx3OhzkyFTRpykiBGq3ap7RYnA4CczOvfKvdtUwBQ2n5pVlqL2Rf0cPdw8LnSh4qi+Tofq3Eg35iFVPfMMTOau7Yi+ghr6e/fQEpEZcVEBNERrIEC4M0XPwK+YVyeqOIUEF9WX3ZTWbbO/e//6zloqt+r+TuV6nWE/PPGvfksMihKZ1uZrQ55vtTtirkxBTUUA//pwBG31AAgCGEBYuwgR+EPm+601Ai+IdQFUbTxFwRMZb7SAidYBlV0ttxCgfLTSDOxL7ZDG9J8L6z0wTBT/HKLxSj0L8sKATO8d9Lel/T/7H6HJb/oQlkIzon9JKBHKm8MGK7/6/7ELABSjQbcsicoshQdmyUU7Zb12M8z/GBeb+QpaXq3UsNpkqSrk+jM606f2FdSJen+Xxl1alXJ+P0AZ7xRgScuKN9drH9IBVjtAJFDa1nSjDbFQEkHpBYx5yu969Xf8C+9PRTC82n17qbHLt+YTo1//WTs7muWnurZwx1b2+dfat/u8zQXTz1v5IJlSRkyz223MFURZzHxMrrzD41xP2BK9JaotORtNCCThQ5ykd1v29Cfu/iV+cZ5wDJNjz156pxla9cDKaMWnPsq/Ztd6kxBTQP/6cgRNDQAIAh8uWlHoEfxDiBuaJOVZiChnXsw0abEYqG1o84l/AAqJNVotgWcSqve7bmDa0mQfyd0tR+GACEP8iGVM0OWpVVm0TXIxItWZ1tPfX3/T4l2nsmE6TjzRQyynUNXc+tV1rjAb/Zu2yOQAuEYwa1RCqexJy2Yu5/KhF6hOkwIjsZJrkCQncTRvyOntZK+v7G6FrrV/Uflly29qMfMPqLUxpbL7YtKyJCvlgl2sVncZ943YuSrZru08u12WmLIVledT5u2I7kkYOYMHzoUZyhIuDI4ojIxYPmhj33EZYa/WjZp+RQh77W9AAKQNyxJwBTnDB38YW5P7omz5byxb3EkZypp1H1LUEwe7FldXUiMOrLe90MVn0/T5v6dYgvNorf6rM/zei9arl2kd1OCPyTEFNRQA//pwBJTzAAgCGS5WmwsS9EJIK2o84j+ICGdlR4zm8RmgLGj0CTYNyRyAQXGhqOyuTLZpnktdo7sXO93dfogfDWHcV38oO1Hsr21I/W2kqMeyFLRbOe8ifdPOTVQQJjHs7riXa+J2vu/2gg7Ao7Y5AUKDzC3uWMfZiZ7Ir0P8oHfFXUxWZn+778y3qy6XKkLoyIN+T4WyHoXpFv2W1euVeEHU9fh2WJuZVJUyVABuNJwCSDOXLm6is7iF5HXxk36AtL+yPqQPVjUdWVB8EWNhkY88/foi/bt7LU2XXpCzT4fVX3gogAl7MBHxTJAABSk42WwF4S5whRm+UpG3V/PEmQgzRbB8H7aoktkoYRJn1e53JLnEpK5vVKVo3/urcRfX/bsmNT1Q8zsEeYYcyL4A9aeRTEFNRQAAAP/6cgSnQQAMAg9A1hsoKbRCiBsXYUJLiNitTGy8R4EFGqppl5UoBTcdoEcTcKVmzmKKMjvBdTWhL3NqWOiQBAdWpGP2198YfN+t/Wtdf7LiA70JabX/zb/o7UoJvnDKIaqPlXVNFGIWDYNxtNgdJPXLV+lmn5mMSa6aDjst3YVQ2/bUZTq5oXiXVX3szufs6G7v/9jdxbro9eWVdRstvJ0SGHXT1MjEXtjdQIu2wBx7h6IgKQHKICpQUNYOIdO0nq8gU663ncP5izJ8Vb+P5DhmO6DGVlRvMbbddDFz9le5UzJduGCcso64WnBEFdv2iveAEAAM+24BoxoGLDNpAy0F5By6xp+Ht9CphXLn7gf0XAOwUjVdyTNryfmC0oSysIoRC3P25V6f5erlTv/EGW++0smIKaigAAAA//pwBIC7AAECDDlZUeoSXEKoGtJg5UuH4E9lR6UCsP8XLOjDldYAmkinZHIBg0PRiu/ZVXazGLzSLToJAKl72Sg2zN9A+9EbNFErd+ZjM8G3TUnQRSVrtvl6XjFO5gjfSfst2sZqZoG+qAs124aob8FQCr568mYsbi4Py/PAsAah1GPXFsidUQLDGPftSmuroqUK7nenqP8i9ftQP0oZmHI7ryJfEDI+n/WADeKbsHY0phgbA9QeM9WTWzkuC1+QeBCL9kz7g10BqOQHS4wHwMJWuWKPUcejcQco+33B5AieEiUykqNDvrWADUKbsjkAKCVel21o+Rd1FNZ1efWN6geCavqEXyOtV1rRvqY9JyVs3vZ6m/K/ILrXbg+7YW2PQUaaQy+ccr8kmIKaimZccm4AAAAAAAAAAP/6cgRJbwAAggM1WNGKEexDhvqTYec8iLDfY1SVADEKFuoesRACABrIp2RwA2aKRYVrRVAOXK2OWqmubxIDVydqg7XPonapyujciGBsV0N0vS2lF8Ivuuvf0GPQyojuD7BIBMNZ06EnHKAmETFhl2ZUgRgoOKUGNvo77yw1jH3u3hkQFku5cZhS1FZzDnafQhext533XTtXo9Pv7L+3satJIUW6ZeXsXvfWAE1RTlsgBtlsIEwgAZg33/b9pVmucccF0BeY75rvYn7/khNTnIdb+eqqYx5itLvXV1PzGRKGUu7rH5LnFws0DjkqXOK9hAVJJAFMl/tJjTiN6qYI+1+Tz/ZF3l3kCs60UFE4E8Gba6zMnj3XqR7pSug7u6R48ykV19fXWyq3//MESvWIonvd3JiCmopmXHJu//pwBLzMAAACHSPZVjEABD/Hm0rEiACIHDdzXGOAEQqb7reGIAIABVACqybXZisBgAWggJI+HbD1i1Ym0tTru9Fx/HBdQHDxJ3slar5AQpVQz1093lp86XQ5gKZsQbTIOQsH/0dZtn//SAAgqBfHP9s7oBAAOqRKBwiDXDMRNDP7yqNqapHU+3LLs1Rfp1E3kGuikKqkUzTFRqv/a/Of3/297K4tjv/7gOqLe6iRAJWyBm7szHzu3ab16DwIhRZZypEaEfU9qmtH9kV4hx9t22Xn9ISLsNJcX6DzzXx/dSYh4VFAicMpIKCrgSC26i40gSVHzgYhCeql8HO5D8QT6PoxUdrffmR66L3VK9FyH/Rvdf28wM1otwWbSrNJl+hlHx/dSYmlsFThmQUFXJiCmopmXHJuAAAAAP/6cgR7+QAAAhY5WFGBKjBB64tdGOJ0CKUDd6OEWrEaIGuoxQkoAADIUoAAJeehaV6DWNJ6RLHHx1T4WCp6toj5Wf/0+hq6/1KyG/v1Fei69WEi0UmJA0erDTlu25b0NV+V2mcOxFsUOBAK0Ae7qJTpwiMwWYNj60Z/d/wMBzfmbVnlK3/0emYyrZf9t//qJ6f8zcmZDP6lZtW+v/f9lzf/y+tnphniJthYcQADFTldoylLKeyra8w3szI/Kj4rG5+vQ11T3W4aPY690bw9Z6Dt+oUu+9X9RPlqX9DOhqAxJGJbxFd2f+xYSrIqHm4NLAAgAbbQMZCFbT68HTYjw6jszabcwGoOmHdOpzVL1waPNf77drq1l3f2qVsj96/q3l/6O96KMRiW8s93/9p5Z15cioebg0VTEFNA//pwBNkOAAACHR/b6Eko3EGoGpM9olgIpW9/o4RXMRUgbnQjlg4AAtyIu21pOEx3Vsm7UxmPiYCLu9ZA8P9slDm5fwTKikTxltFsaJOFdQbDHWFagOVyC3ySXfWxa+BGuFko9Kj1QIUKWGY2pIhIuUJGPhuAwwgx55dRT/KJfrN6qYCyFqZtAniv18//s/2/6vranoetF/0631/dX0DiGUuqEz693cn+/UzkESRLLJb/Y7MjI7IjvFsXvnH6dwjD16itz9/05nRMQ/Gc/X+f8z+PX/YfRqunuWzs0Wsx6b0TSuu/+1aL/qi68dSgf1kh4YBkUat2jScUpAsErDw93z8nQUBn4BlcVGJQxKLRAmARSsRXmxNrruv+op+/wYr7vb/kHPrT+2Jt9SD9aVfTOaqq2wzxCmIKaP/6cgQ84AAIAiAn1tHoOaBEaAq6MOJMB4Stb6GcqzEUCayokKlSACgAW6xW6O8HsYR9QjcRYPIW5EdiWtJMBgTHryr8ubVO3M23+9abftkXbHkCil+fl195YfOsmfy1WlZ6u+W4Eng7TU8AEApbY05UMIkpwvLQBAEjLkVnzCG26g6AqOJQqEJfcnG252mt9GbT/2VS6+nkO7W/1bTuv9LYlz/u2WVU6NDLrXqevQ0xHJIylKQII9lGygktqmniYHd+OB7oDNX27ej/L9fmYdRfxJ2NEzeSrcn0y2xlOg96kM9aU0RMgo9UaaEKiFy2NS2BiN8bGA2ipmR1SK/CeJ/uJD8tJZMgHjApcHXnfQXPaz9KvrqPJ97SLm39RxRozeMCL2mBLeGTZR6pEqyMUOTEFNRTMuOTcAAA//pwBEoLAABB+xvaaMcyfEQl2xcZQkyI3XtxoZRR8RMXasz1CdQAAAlGF2NApvZRAO+mDefJ+bp0Cw4JATKjFH0JN++2eMn+ijmnFH2DiqsWzbgW/RH8V2a/vYlbsn70prv22FlgkctjUtoL9YJJUrn/O3bqEkdXuN21EtX1Sw7HdUaVtXXp9Lpb9X8ZGM85Sv2jkmS2u4eMFRpcI9d089KZgalx0wtCwSIAJcjTd0ibu1EH6PWob9VLfxoQDnlCujt++QVyK5ea0io/+mzVtILtqBK0X/Tfyf+tUEVmlb7u/Vbf9X9fyNq93CPNKPYhBU0QTqTQzE0c3EeEwgcvvWnyzLed2C4DZWx2XW+/1FbXmuerWfs3WiW/Q3Qex/jokW5fWsimvWrWjZCtcJulcaxAw7bKpiCmgP/6cATrdQAIAiBBVWnoEshEBdqzPMc3CGkFY0SUSXEToC10I4j2AAAAgBMrQTki+RtoCfRS+yCJvUZECs+xV2n5AGAFhuFQv9vzv0VvT9//L/VtAZVp3+bqudf3fdVE20aQm0W/TcztXh1a1oqVtL++jq4jSZK1CQjFt3kdm8oFgnXjI8+ynsqTLVEghn071dv/2nGf38v78PRdbPjzn4BU5ykZ4XcMk6UyShz3m62TlRKTtoPoRNJVGJqLA75Tu514kDkNR2tWu/yhB50VB3MlWKiIZ///p8z/RuqqXVmUVbqS0mwzutpjqrtF/VvXprrDABTcTl0abkMohnCjvW61FKbzjCwlAkr4qWp+pfgig3QuWVHKxkmR/+i/kM2oJOrI3qjTSZU/kdKAuZvYz+pE6v9JJHemIID/+nIEkKEAAIITOFdRJRK8Qoaq5zDiPYidCWNEnKvxCCAqDPCK7AAAgCcaJQtCCoXbTKjZJTdm7qzq/CYJO/oM1W70j5VpRq6NiqslkYrs6+Z+pGW2jdpE1DjC11p1Rd27oS9yCSqnc0BQJxklLCbWV41jyPwTy8sby2OdAgBNV3V+Pqf6GH3oS9kN7TvzWZifmXyr+W9Yl4WHgwFexSnbt8hvYiUJTxD/p9oAc4JyRpsQP2jffcHORYLeyIc53FZH5W1yJ2d3yoSef2qvTVXz3SiL40j6CZtHdW9Ky7QXTs7uqoIlj6g9JJQhTqKLL6TJqxIG8ym+dmHyhzeroqMpFgW7I477fnfsEmQymPiO4z135oLcuasKHyO9YnP3kf0DlIcmr+Lykvr+oYay7rib66UxBTUUzLjk3P/6cAT3DAAAAhRR2VDDOV5CiBsKICLFiIUFTOe0sgEHICvok4l+BC/ZyWNOBkChYRMYT2DFJdoXmsPr4QOdUMPVWrxwf3VDKo6vtdr9qVX3m/M69etU5Bk/1atGf2T/RGZNt9aOxbR6MQBpU3YymJEymjgkA4khlx/wQJ6sZcag+CN3+BTTlj41v9Yz+3nLTkk3NkcDP3txyKs/+VuejW9b+CbT0ZkpZec1mgGAzVX8RzTEETYNXsYhQb8Wkq3n4oy4xP9WgosI9XCTLUdq3fYY/td6J6v81v+jf/RPjeh2O9/dyewvYPZxxJLk8ajNAABAVK2mxxP3zGgcczJ/OXuzkTONSfx/qT7dXQIQ1U6hId9LvV99rf+K5BK6l07Ic1FRUp5kUtcEde92yfRtXSzSmIKaimZccm7/+nIE7XkAAIIMONY5JxLMPsb6kzziXojRAWFGKK7xEKZr9IOKXwcBONJMRDAHHmatgGu7DDaW07gRD18OMlRPE90gTLeolWmddtpbdrk/cvq3aZbJZqUwoY0FixkEslp3Ht6iWLLc4JyOSBfNB5ZaN9xLgSV62cMM6EzrvfEQFhjOtuhN9+fiOEhqa79X6q1PLQv6l6Jf/zDHrEgIIj60gaQ1aO/6wh+iTukcgxtpgIFmMtY+8718y9z+4qBsRrwqrqObTukaJtziKIyRZUIVn/tVvykNqDlsVnv+TQOYZ+zszMooeznDqNLcaHjEAW62nBIhxNAaB4oRjtW3KT6e9AfDk92ziz1O01hnd1VUzPoi+1bb/qO2jkda/4En5Vf7I7Yppf/s1VdrOC271Gm+zpiCmopmXHJuAP/6cATQAgAAgho62FDIK+xDhcsaLQWXiIERW0QUdzkLGqsoxAnWADmJy6RwBjrGE2ZNXamr9e1mT+EwJd+LByGy+amZL6Q6mGgS110kmUVq/30afsX9CNqCqXb/Qt6aqLPLpLDjxVC64wAB81LrHINKN9D2kvb9e9QffplfisC3epv73Dx+et18SBVYoyAZSaO27JVWsYun7P3FWj+1R2cIo55IsGz1/CyUM95EAIVinY3AMORBsCR5BAi45duabofpwcRt50D00tV9PBOkxkPRX6H7Wd1RvxjfbXynlAFNiCLUsXyWhyXICGl7QI/uXCtQCdbTYgMcPYA0ZVE+r2vQZh/T2T4D0LOvvZpXSjtVndD8rmnaEqjNO370f+P4qj+9tgsWCwdIVE2MDQBTJe26mtTExBTUUAD/+nIEH9AAAAIjQNS9LKAMQgW6+qScAYh8h2dYgQAREorudwwiQgwAuNpgG4OhaOKENISLIPz91mpzFecUb3K56DiVdqNjgB0Y46tkb0evnsw/vnV8Tc1UvP8DKq2WdWI1HYsxFQcpUXZDggKttyyOQaalcSIKNyi63Z7Wjm9wdDY0xGJq5p5x58oe1c2ONzFd1q/03pVr9tT/KiaVnpcnEbwpuUmLi0xoKX/i4AiIsHTC/Ww+ABAIq4+VD/sNs/T/UJssdEK1Nyrc2nv/pc7h38EYMGHJqK0hwOyiHvBA8OaIRVT4Ab//k3OOf/8DxoHAAAARDAMdbmz2WxAYCCbTE44VwAufmffl0pXCPO1zbS3FnEb4YB8c3RQ6gqhqmBeUQfMgKtYhWUwB//Q8PuOBH//m7jaYgpqKAP/6cATjQQAIAiYFXk8YYAA/YVuR5IwACIjhakwMTcEUG/CkcYi+AAMIblv8YUCBBDLIAMLBh4gGjjgDQJz+IBp+H0Fz7ShARtPjKxqSh/UdlXLpy7lNSnWcYKufdpHsS1mswy9I2a2KrV4w59hFIEAwKGFxQ5duofegAIE4gGH4PvqDBO97hOuxTV2UNeCfEOGiJ+/DxYQ3vpEihYkmh1hsWj1dozv/2s6GAKNV0kAPgViqtq7lqYmZTEXJjMtEkJ9gR0qGARJM1UulxjL6VUslVu/GY5bzJmSrObpr83/6tzCrRcZXitVjJv/b/8RAAtdX01xMGCVk5qolVUiyjMZSKpM5Sl+aXLUralf0MamX6G2Q36+gp9n0+3QUtYlZaLgJsiWGCoiV74NLLPloVs4CPD3JiCmooAD/+nIENxIADgIQJVcLJhowQwga0mTCSggM11ZNGKbBD6Av9ICWtgMRDOmQNBJhpkQApwtaksiGgkn6axykdsjyTRsMQWlBLb4U90LS7ZoeUIOf+S5xwTxKWEaVsbMYYhZjFnGoR4vKEwWqgRhnncD0Sg6uFgUoXCm5ORBETUnGiEEfeVVo5W4aWqKatZjoxmmtR+V3+x3SZP96619NGT5tSssl/7MUKxH9/+saABnIibAUMWoy1gsiAVWWCh/KsQ7cUQMtKQxjOhjOpbqpZSlSvylaUrIY3+rcu6t7u6ZumYfrX6EO1IpVR8rywSLcckktkclA2ySa1tm5V/6+p+hUf/xSyFXh0KkS3MPy/rOHtEuYGeP/828p+u1giadYxosGnb2bXoHbZEqxT1tcxYTTEFNRTMuOTcAAAP/6cASTZgAIAhI11rNJKMhBSBrTaSIKCMTfTA2wR4EbICtplJwYARXyLF4T4Boq3ISh8aaTuuNtdJ7o1FGg98YrN2aqvqlivsb56Wq3+f+yrVnLMyf4iSge/QvPpPV67xf03M+/TmKaipUXLS8J8hAMllSFUVDOTpg9dFym4QnWMy60o++rUv1rGulvv9v/yp+/06hN0Zfr4Mf3TzonufS1yVN701yocskjCJI1hLYikC/rSVDmkFVIkOydKzNtWzd9xGPIbttX0peioWVEzpoyzt0ZKdWaur2Et8JSuKV3t9Y5eFHqqpyP/+1Wr++7aIABBUjZlogqNA9GZSZgEECbyb1MLs53cRg7sYlPd/MnOyUfvc1c+19Gq+b/T7OlW/o3IN/1vx5739Jt+SbjxDs6dYlSX70JiCD/+nIE1HYAAIIfH1jTBhAoQyIaommIFAigO4WjBKOxC5dqJbMJKBADjUdkEmIdKjBkjhAMofUh1la8uiIxXktoxjshv+ZVS3C2swKSLcRDcqDzeVdenS+xgy0/VkgbtJ0Pb1Utk+b3gQWSF1fiPUJM1HIZUNkIWiU8KKDbbVtKn2AeFY6uSw8qeLwDh19oSeLP0DXDn0F5AYQN88uQGvullQ0L0De39l+/TX3J6BE3ZtPdvrLcBLkqULghcmFkxcYExBAqFXKGkWjOx7XgBkuKPFA2EgKNxbMQl4m73RwjKjw8RlNZtzWKU6WDmq5Pvj00lQDAkOyxJC1Ola+MIocmbuXO2citVHhqZcNjgEminMMg70s7U57/Z6Ov/9Zdv7+KoZ4brW7iUqBWCZXcMPav93/P2R6YgpqKAP/6cATJxQAAAhtA2tIjEFxDYhv9JCIbh9xBTk2ZCMEIGSqJphRkAa+pJxIpMJYT8hm4CFBEJjEMzN1yoOvYqaNQ/S7l3mInOzOVkJ+a+36O2gtV//OzT7W9p6NDkgqWy6Gx+7V+Y98jTUIk7JXrrrHLgOeV1TZSEH04S/QECNw1ITChcbY95dw0uZISgCYwcxWIqzH4cpX3VXk6tI2fCJl7mNGR6hR9da2MHnO0WkvILgWCmlvBDiaLC4LajEk9odrVWySv3LBZE8kJPAyLC7Y89CL0FRRd75FFuhESMVRq2l/YhZ36GW/939NImi2SdF/Fv3edPnw2Ehc5hz20KrirZQ+GI2VyHqulvr9noyHdzb1t7TE/v479R0WJ1RItO9BZ354ld1KTYp36kI9qYgpqKZlxybgAAAD/+nIEM9YAAMISK1nR6BH8QkaqQW3iLgi9AW20sQAxFpvqCrJwBAAmubcaKTA7DocK5mvg2mWLrueIR/DgK98yEjJUZ3cr+ptXKartZ8yytQpc169Q2VSmTr58nrYcaXDOymZUq33f+objE7g1gqHhJJKIJHCnE5OGMdaYirLuzlGr3sOsKGJyLySt7IHKaVUmvsqPrY31L+m6ei/ob1/V/iD4SPCqfbd//rABTiarksabgJ4QMt0XCsPdbnzdzH7GChLFhhm3KY+erpe4V9FO8jb3NWQystn/+eWVf2lVcHUn611g7Z6+Z5FlS//TX8PC8tBwkh/BfRxqd/3odaW7l3ZrDvdcU5FmQyBV3eimNTm26GGtRP7HJWhhuqm/+7t5zXqk6tY+daRLDH6oXKIQWxb1effvTEFNRf/6cASIdgAAAg0N3W4tIAREBKt9x4wAiIhNd7ySgDERBy/3hiAGAAASUSpMlu221G22wACzCtwNOdft7Z3XHd9cESVYiuZSYrMGTBYuSSIjQB4nJx2HAzY3xwGJZgq1zwqKzD/P+p9wAQKTSSKtlt21ttlGAA1MrvYvpZNV9qaxr31TzkFzX2LK9zT8+krPDg78rbshHCJUhC4k49ooawE4hp41Ib0Kz//soGhNJVy2W1opQZP7s9y2szlc33DWjw6BBFlYqCq0Fk2JowjFQG70tn9Z6Xcv1Z0R9jmFTzZ/SBe3q3C2acppULpU1TjIMgtuW5+7atN0KbZloesU/V0ObwYEEY0N0LPMTpIiq6bQqMaWOgQ/rfFf1VHRXscERCxs/pAqEW9SMWzTizSoPkVNU5wMpiCmooD/+nIEnXgAAAIRE11pARDcQycK3WElCwixA11HnEzxEZrq5YQI/ggG4q5LdGnKAxledAIyEDqwTucv7JQUpgorWeERwoImQ62VaMfqdLdOV3li2WDr7V272BIO0HVPFwnuK7Q1hqGtlAAABCOcegCdBkla5oBcYUi391rbnR3buKmFwsz0kpV2+n78iIY21HXqpVZH//N/f69BaIk6Q69bf2OPdT/O+GsNTvoAAplJxopAAXETPh61vla0bjXvTUoszyoXF/nEHXehbslqqykK5V5lqesxZ1eyHJ+cr6s9kbT0dWq1W/qRSwphXe/2bvSoAFEleRQyqQMfWEy6tGJ8fJ5YjRWlXC/4YCF6+yXT6o39256IZUg7LZUZpjqzGWn26qnZv0D5K7FTpVYStK30Ydq1KpUmIKaigP/6cASNAAAIAggu0ptJElBDBYngceI8CIUBVMecTPEUIOxoxIg+BlkuwBtkgEu80FjzcGbsmX7mGEMV5Vya43n8iEJL3lKYmpqI/kU2zsxK1prSvRF1b8qdBLtdcJeLOCb+mzL+7+gwrIzMxJMDCckAKTY6GV2pfH+QMLJTg9kJW1wsCAwk+cTFaEiwVSBevtZghg9SzDoxGQ6IXS/6a/6Lq/8dqDX1V6Prq3y0AlBLPHdD4PVEKvcGkat77eoUGV0cEIyEUyCnxikO13U67lOm190lJahf0J5v/fRrKzR7dz32QSMJWMJMbusqHpWAdOzksakAtfQtvVXYiXQclz+W3otHlF+5nNkA6MyIdHv0Ds50zXnzTWWSpL+j9DMlf+EfVKP+012Q54ZZiKrFHNDF78umIKaigAD/+nIEjMEAAAINK9lpKBJsREcLHSTiS4hUn0h1hQAhGiAstoxwBgAAU2a5LI5ACT9zNiy/t0nMLpFfAkBYj3oy/AzIzrRy5ds1VVFb+ibKqN+41Rafv1wuLwle0yInirACmWmUJ9LPaAAQizHJZE4ASR63JKeN4WndC5sXvwoAQamZi5SK7ItEJEcy6Jq8qrXadVPR6umgvoyGsT/+NIp5NpZ7bOtiptusSLtSCpEZAQEMgHEtZMjgQtm82MC8s8vcx7OeecThKD5Ds1UaUGjI83071OVEdDm7fd1ZGYvwnULi6/Dup/KmJ9H+73EuwAAJGJSzWSQCAo5PAL3rG3X/fVHRRrEYOfVBsclyKljXVUrJc6rmFjZ42Rr09t5NG+f6XSj5s3dzKHEc66fMpkbL1dv5ZmhMQU1FAP/6cAS4XgAAAiBlWZYg4ABCrKtjwpQACLlBgbgigAkXKC+3AlABDCDCDDAKbcrV5kiMP/3fxoOLtmDcn/uTPf/57mN//mUM//2qTGgkf//3HCAOxLcxT////JozK9rmf////yGee5AxphACAQCgMCgUCIBIucjilT+r+Qi7ZDn/53//O5P/+SQn/+SofAACf//3EBQAw+5FP///4ujMc7tMT////+KZzuKEaICgAADAwEAgGAwGAwGAwH6UfE3pIO7h8RBmWhzjK16P0dl/85lZyf/soWoBDU//zCR2DwcUVJun/+IOtxkqOv///jonoclIYAAAAQBAgFAoFAoFAoDgDYJO1fRvOosyuh4U6ovT0dl/85lZyf/soWoBDU9v+YSOweDiipN0/6+IOtxkqOv///jonoclIYD/+nAEez0AAAIbHNrXLQAARAOLauQgAAhdBWtFtE6RDK3u6DOJJwASABrSMddUsbENFrLyshW1DPw4bgWD28JQwzMD5rX/jTtVFf1uFJMql3X9nF63WTuZlbNSS0jYnSVv//rLNiJ6qn1ABCADk0pc12Si3Vs2A8Rfg3+vgG4VagNEjX3+nyo/Vb9j6gkn3yPU/W2SqlawUfOq+eU/fvOiIOpVt8Kb2g3UHbEkc8ICQgKEjkvc2v7hQl2RSN6ifL7Vr7BkbEPa2DG0EcF7f19UxbdurKjt3XP0+r6CnW2SuZS0DCk5W389+9OWmg1I3MqkiOAKJMp2NSGja9RPqUP5LiHgxuI4ZuPqL4A2rcnC8z9+vW1H6e/f/oav/qWgYf/b/S1eb2pt3zX0Md3YK7j5sphEiYgpqKAA//pyBIEcAAACDDXeUGIpHEKIGycxqlCI0Nde58TpQR2vrahwnsf+NxUS1HJRiWJVi7QsdqG9uR8KAUlBJtfbn/oTgLy+P5f99V+RFEv5GUe26tpMKuSDbDri62lBzotx6TjP9FQR0rBACAm5JViFhehdgqj7Q6jfoX4s54NobqoxGtUEHuM20fUvz+jc3pyN+3v3/orbn0P/6Nalvn3xlMU609S/s/X1J5ABAABk26YZ8v6y5ehgqlli9KudLmoc7cSxqx1BXl6g/5XqfwcdW0FnHvbU7//p702TT3KlqY/rTOMf+4XR0vr+/MwgH6Yu8AIQQSAilLFZI9oR2c0P78lwMDSxWL9QXaTyWoSc18o3ft1f//t6EnZOhn08nel/Y++FGT3r1c4/z7f3/ovTR7o+p61Ylq8kmIL/+nAEjsEAAAH3IVeRL2mEQuSrWgUnGIjpjXWjHEsxHrFtqIOJYgFr8aJKafc6A7O3jFbUNvHbqCIICkhrCfLxsfW+dVxz9BsiE/otmZ6Sqq6nZ1HQWdONi++Xiv6zjOXltnT60oJEAAVI7aObYTugEvaKD3s/EnQIjMQncSf9tB33xAW/ndi/IIFDvZIECDdCq3pti5l60ve5rkzvZn04jbUlLovKP6UYRFECACmm6zs5gj6L80VzwsA/lOUGElRbxX+I5OjaD9ev+v+2rfdL9PlXtQdGpqTSt+rJ6ej++33M3/MinfRkruhOj0UMqIAxAAJct2WtlW8I2koQF9X424+2ISHH/xtDcFwXv16N//0X3Vbat1a+UGrDzlfzP0frV/1QrqY13r0Ozt7m3vO9LeUsrdlWOmII//pyBAS4AAACCTlYuG9RhELEa4oY4kqI2QN/oZxLMRYkLmhjiX5EgBSbkgMCDUoUJIynZbUTmqQcVgSKSo/4Nv8oJuhRsSxzQpxhzW5nTr/ZPd3Q1P9Up5eXjiR8Qv27WVXN1P2f9ckbqIFxzblMVWtrjcmAcZisbcSeQ5UMNUA/24vn531Ec3Qan6tH68421awkOCrDyZ5CDGgzpVyqVnUE3MQZEEYsYxDbY0rSJUlluomKWSNvGFmJwWc/j4xqnAv6LwPg+4Hzto2i8nX+ZW1EJvyfV1W1SWVOyyLILQGkOlxr4ul3Kvpa9ZDqedbZXgnahBKaktmN+2MDbbBEHZoY424qbhzZvX21FXI8G/L/Qb+383o+z/8zcsL23yyKcSyGvLtmKLRUkeSbGrbcKc7YKKUK9SYgpoD/+nAESxUAAAIaQVrRZxN0RCXLChmqPIiJBWlFnE9REJ6uKDSU2hApQAClm23XC07wpqoIMaOwt5HiEtmB3Hf6F+Q68qGu3tobj/58jNoDOj+7enpnSp6QaUVQQqfWGrECNAid8jneheRACEAgFtyQDwqET1WBpPKWZkbMBt49eJOUVRoCxMoVdrPlT9AUtvxeO6Hc7qalX5zfo3QuOI0+4UVP72Le93uT9St//WCGQKATt2GtLE/cBSXNTW9An8e4VaaIAfusRn06Jxn+DAO3VtG5f99yeK5rMranpfcObBhqOcQj7DlbJEk2rFJ+p5TvTwncJBU2/wVTEd4MeojZn8svwNwiL4UvFunV9Afk6v369X7dPfMZtRJtkonWKPMo2YquV9x4beEQIfFU7b8/0ouUe/QlMQU0//pyBMu2AAACHExaUScTNkLqK0oco7qIbOVjRZxNkQ+crBzTiloIMQEAXbuLndEVfAbaTmdd8lxPyvhofCNp0PxPXqJ7/0f/9de0ivErn6OVUejhSVU+WtcF7ytR6kXZUWFe96syId9SAAJECCpLuEqzsdAHONcU9C/I8aDKyj8MdeNDdQ9zN31N/IG/zt+vy6tx3JE881m3fKiHYdF/lV/+f7ylr67XrUTeTWAEIgBMkuEnFVDLh4ApbEitbqQ4EDsfbKpxP7ag3QRuV9+J6N34ZtW/Y3nvJoX0paWglImir5ZjJjQiOcg6LgVcYdauGJCDktBk5WikVJQpC6bUG1lLU+oIIbNCwkIpQAdPxODcDR/UIW0bt/BD9uXr5N7LPSpeaTuqEGWGyybVj2MCDW8z/2JiCmooAAD/+nAEIbsAAAIAJVg4zTmkQmgbGjDldojdBWlDqFhxFh2s6MOJugUAMOS0MfJIBs9Aljd1hjT5uwO2ypbUhwp7YnG1xJB+Rx0u2Q53Rv5Xocp9A8VJF3quYfJReImlmO3ku4pqvWiAJUCAHJcLuQ/0FaAGe6BCUT0Llo9wfCxImGGqET5+NDeBP6N/To/X+rdm7tTqb0+iK0yPkMm8o+tfqPpSchY0a7UIIkEAk2pAhRHF2oEzmgqX53I8qMIxoxwj/lQxoCC/fGAUrZjbltX6Pgm/Vvpm6v3drzU6irqErOgMZzBVKxVqpAupalPbcqEOQAU5buORbarddBXlOLyhNhjjvC5bEx/I8x9SWJgP6viYGaNyrYdtH4T/foV4J9T/dleyG4N4M2Xv90gdMJJreATyBiExBTUU//pyBIiDAAACEDlZ0UkshkBnKvcZ6jaIuO9c56hNERwgrOizidMBIQyApbuJVHGmomGllBkU9tB9xHHYOiFeAD9uK838YD8J9W1Hcn+2v7Yv79v5h3zb2ZVi5+ve55m/dVR9BPmB41kBAALktHxljwN4B2X3lJuPxI94gtQuT6iUG70O4y5A3EN28l5f+Ly389sz20mTfk3z60eXaZjXi5d73ucrWnR9IIQQFJcOzN0iH/HH05R7mCR+s/hV4IxPVjBEPjdsONxT4X+huE6eXv/Q/um9lJr6teiLZso+GHsbrouHhwmwCKMsA4QmiaIRCEFvX8TSmlVyB+KkQ3+kX8RdCj6B779eCG1G6cGuoLq+rd/6MkIdke5UB+vXfoqrh31ADlkoLL+cVj3HQjfxk4tC/rD+JiCmooD/+nAEQesAAAIdONlRZxNmP6cbKizlRIhk92dFnFoxCR2sqIOVugAhBIZdu4zsIj9xiLs1Q71Jcc4pDaxMHcj18hmCB8VvovP0bpy+/Tk6t1bdu5E+Cey7x2s15tMe7/Ux7bEclWWOq47gAImEIO3cdqMWU1wcNZQNDfJcBrFBn1BnxTl4UO4o2E21f+nt26/zepcq6G+j2rDjwI9R3Min0LWsXdefU/JmwAytRhKcg19pCfRIbcMDvyQl/ZzgbSPOYG7OENmjflAgaQPHGOxRHLdQT685tBv6P3//blbVDrpmfvRBcY6Vekh83WgEJBCTu3ENCO1QBJntQZ6+IvHS+qaFf4mbKDXtyof/PbGf6dX0fobRsYXRtkOpkUxjB8NtabJayRgxjoKhpgulK3piCmopmXHJuAAA//pyBLUXAAACFSVUHWGgAEEnaxelnADI3ZWMeAUAESAyrw8EcAAAhSQDjmU67E9ZfG7KvpHqAC+g9+H+zEO3UT1yoQANaKzYF43TTJfsfxYBvn1m48+gkyY/j8gyjz9s4d5hv/l6f09cACAnbuIe9p6WHAIVtAPg1v/zxGMoKC+pbPEr+U8v/HQ11/lPb+p/fm7p0T9vRXyL9m/3f1zFj/7R69DnNJ6rkKwABAMBgMBv////////2PPn//8wsBONgIzD///x4BIFIAUCwTjEL9P///AoBeEg+JQvyU5iQVP////wvCcjH5UmFgmVy5CF+AAGBgMBgNbwUEeYeSJ299dP//////zz6v//mMC8kBcw///8aAsCQAAWHlRLT///wGCQYcREsijGDn////4kEzyanDQ5XLmiWmD/+nAEuZMAAAIhLl3/FEAAREcLjeKUAAhc517EtKaA8AfvtGCJhiIDNThmNyVkpyRZKyZgofcolzNhuojm/qTm66OrTIrWZWt25lb6p40rRlmqeIyXY1h1Fm11Z1qOi4saWlyayANFmlq1UkhCGSxsgEpWVC7iaOYKbtzaB4FMikSgmXP5NF76GZpjLtVv+ZW+NTqObL2+LLoLxGSbsaw6ie2u7fRlkLTTkAMWlq1AGgkFujVEQI+9a8MBS47iPEG0BUwBL/HaArZeXqY1X//Q38raCz5tTeoqbdKCyprOhR4keKEtI3xkFfLaypY9anolc2xVG2koiCX0n0Oz1HrAIN6XC8GNqNVXunrYhtDosN7Ii699i34CqUe50KRJktLvGQV9WsSgI9aRcuiJUxBTUUzLjk3AAAAA//pyBFxkAAACEUFd6KI13EOoGuoxoloIiNdhpYjsQQ4ga2iWlOgkMwVtsFxluUmH0M10GNjAF5uJtjBx8G/24v+jcn7GpV7zP+Kf0TVv9epf9tau7SaNoJTu1s8AXPDUw8SfiVs7tsTACIKINZl0u8+eQc4Bo+d4fhW78fOLpGUy25P69X4X36cnVrTpnvR/eZ/d+3/6l/0oaqFKJAtfy1ySu76pUNOK1rpUbAABBgUBNu28IqJlW6D3wFQw8csoniEXrEwYZFGE/QtqPfynt/K9W6/2X7sz/rZhyKBV7pFeYuoRWtLUcDteP/ylwWoqgAAFgGSS29SaEs0CYEpLDefFHtrHG2LEdaCFxQ/8E4h76AnP/V+XqP7Z040e7yH2+XqfZHVv+Ijn76yb9CveSs/6OTTEFNRQAAD/+nAE8zgAAAIcNda5jzmgQkga5xmlOAi9A3OhnKoxDBwt8BKc9gGIAJqW6fJmAh7KImtNOQrNseS68YD1UTBl6W06C3Uj35T/9f9X/Rulasn+pGhw/Ci8+x79kqBy5XpIMO7d/hEQrTFAAkNViW+CqHnskBoMzJZWLX+RnxE9RgF4kT8YC7gO2JvhQjy9GmtenGm/p1HM///t/8/hNkUa2sl0X27Zrv1n1GukEoQuFtFtFqZSC+lNVC4xqzlU3CgaoUJmWE+Zu3J14l9NerdlyM3z/m//Em52/u960HMgFDO57Elq8+TO1WIY9bwELDxkiwSCYGa7muykbh8zRo7g/M2N8HdpXrxUE+6PicvoH9OjdecqOy/06nr/1sUfQi5E8zAdDn7FRrLDbX5LEepN6VlF11piCmoo//pyBIR7AAAB8xjaSUY8nENjWs0Z6zAIvXtrISir8QkxrKgWiPIAIZpmReXqNqnjO6gyb2ehDxKGMwEOTZwrdlf5QK5FRunlHT7n8JaEP87JqHdjrEUb8w5V/f2kxuPF1z9hQqAAAICEEUk7ewpQSYmNBurK+KzLqXfIizyrXAjgaXZaD51b+R+9hp/S9VNbu1yeQqOfamKXv09lXjI7qhLsatf2kaJIBImWrmuSURVwDUKpfTyLk45lCTjXs+vUDz/hb8n6jLZqlVm+noRm0/1aqsyD09FMrGqJNWSMf1Yu+jLT8qb6S/f6+0ZsTACojBLSkpBJMjIOx9KP57ZuYPYz50eEcghe+rcfo/P2/xv6/0+//9fff/VnYt0/7WV/sv+3Xr6XZSXsrXq+7SlC0piCmopmXHJuAAD/+nAEydcAAAIjXlnRBxPkQ4aq2g4FPAhxA2dBoEaRC6AuNDOJvhAzQBLckt3fX6EdncQQ33S8U8TtlCPfp1bUh/EPm8zp/r/ULogc6N6/OiGUzKRF+2rzDfv9n9lpr9Dt7lb3btsC8FFNiAJAEA227ZUSzBQMCKcOpky11o8+2Ps/mApUmB+j6n4F/qDc3RsxenX+rdTFZFXX4k0aeBc0nk0q+xlLWa0sUz3baCwAQCIJSS3aXH5Q9W7QN/4LhXwQt6hv6toXmbB/77+r2p/s2oE2TpqrkXV2Q6P7FNuhxl77irBxD63JRjHjSrlIk07CEKITaKBEbTd1pbqYArYW9H5vKl8TE+3TqnO/gqDw1/nltE68pP0ZNSN0onq73n0/3e8FfdzpLvqXtvWpC8DCMohth1MQU1FA//pwBFUsAAACHC5WOe0rMEKIC/0U4omIqQGBoKCocRUgbGhnnMoBAAdr3+FLWG8zaMFU5awUBjaqR5F1GCVEyBndorzNqGaeN69BPl3vqTt/Gs2o5S0I+QT2nDyg1kVZq/lkI7Eb7paquxwWyxt2Wy33C7rc0cguZd9zcUl9CXJf1GNgWty+onr1bQvb2/Pbhf0b4z6Eoq/yzOoLYcuazsqlmWd1NBIsJmXz6XVBXo1FNtdvFJRs6wGL6G4zn6j6Ibr7cfycYO1A3d8KH8trt/tuJk636GYr2nZU15K7IJhAYOJ0mHpuJMqUdtFn9XVrxeUJbAWpJbWsD3yVZMdS3NbdGsOPcKjOi83+gtzjy+ODOr8p7VQN/7fmr0JLZu/MjdkTRenaY9mHG+pVzl9Yietb/9ximUTEEP/6cgRJrwAAAgw52dDiLKxECBq3JeU8iMkFTmw0TcENoCuow4m6ECKRIkpOCaiUmAIV2FTbvxXxTwYotRa4kfBl4E5ug7tydH/r/Q3p31b8juppRWalki6wXBObfuegGZlizoITUyFAFEAJuQfSp9tIaoFxBtWtfWZ1/5d/DYg89jHmLNBunGC/CTaPwTr06i3RtW/U3uY0xtPkfZKknXKXrQJMWUu1CavxabABUWw9qVaJT1qMRUBTfbnvE1DNaS+ROGwR1pgwhfGrLmxO5mU84OPocqI3Q6Tbvov/zK+h2Svf6eSn+xasDjyNrMA9nkehQBgGAo5KNmhu9AhRATt2N5qSPM4mGcQhQamD4sGr087if+JgDee/argz4Xdm/s3Z//VKZBdRMyPpNtDO2fJvZllH9aYgpqKA//pwBAB/AAACE0FYUWcrlEKoCtctpXaImQVnpBxPcQwgbOhhFZYQJsAAlZsM5TNWHiVtyVmXtclgrxATGgvX+r83XmHaNy9X/+nCzIsxzorNRvm/O/yNK5GGlDbAC68PWlRrmuFCrMRQoQBUlomChcy4WCx11wt24/y3kQ2uiEKRk6zy/o3Cur4wH5OvUf/T05+wsU72aX0MW03snVdsZuOuuaZFHSCnrdYSCIDMRSLajkG7FWtsAtd5Ncmju/JhyIOs7GgFVbyozicIVxh6g10A+74Uf+vXt7O9bb2rXbO5v0RNlFDx63cXkclUmlxHUPhWAW3IMQK57vgC1pPGNU3Lwz4UEwg8HZfofr783P/GhzkLoXvoTz3+/wHI6KzFIjXzOeZIcFUhog7ScMVq5uLqvTEFNRQAAP/6cgRYEgAAghE62FBtKfRBI1raGe0yiMEPY0WcTfEUIitow4m7IDuFAGXbjCMIOOQVrHkh8Zp5uYcZ08nukqMDX9X5OnV+/J2H6i3L17mTglLZk33F0OcUO4YgoVCTqJzEP3PFh2RLIAsISCpLg2gUpOByMmJXCJR0yhx+apZ/MhSfLr3X5S7848VoqdOz/E0QuUAns7idsY3CNRpHylw0JC70PWMFIJrICcAApxyDV07U2Ao+8iLaX5/GpfKmcv16vlBF68qDdfLtQEI1Ec/vh3LoZ4RWydHEdUOAnQvkU1zIISV8XvFQvMQMyvvnWMABcuwzrRGnIdgEVtPmnsj8LmoeaXxWNuKv6mcadPBPp7am7e/9uhq1zdI5DaiFIyinPnBGdjIOW80F6h4GiXdxv7ma0xBTUUAA//pwBFG3AAACFDjY0QoS/EOnGtok4m6IiI1UdPaAERSa6+qScAIUN0SSTHINpVnRwAcLAeCZRS/IOLhssXiitnzHzG1Db24/Tl9v6fwq9Jpl7Ud0FvqhgA4PHFwM42aKvbljiafIi3FkAmAACduw802EdJyCTUbB8WtKcaPjj46McT/5vEv+IQdd+pbUR/R+nLrGbTvahELRFUENUwaKgYNkH1YoB8SXOQ0KdAAKktFFbeWKvtjUE4msw3ZDIlM/UT64kyCCY7wchogpuZc42socx6kua931nqOlxRySB9LdRTFmpdWTNJQwec2Bup/9MAJDEhS7cXq6ZN4UFc8y+eqZ5IzFQw54rGvFD/35DpxOHNm/4t7to+zZh/s++dfMNKEBGIXBgy9JJGmvqVNE4x5hJ1s0lMQU0P/6cgTccwAAAhkvWb4loAA+Zfthw0AAiKFpe1wlADEXJy2rktACABAAACAgEAgA2cYSkNDzzQlGzPH+WDd0VCfAA8XLEC4URJy6Nnd06knNij9vPGlJf/6RxNBFL//Onq2f8KkgMEv/9YBJDq98orlaEC8784LscPC6BPXl9ZmLmJk09003Jo6YE8ry+nN3QOGSi9/T8+klS//bWW0QVBT/ho8eT//5PgBQSVJJX5XAqAhi0nawPvB0Nkvo2o/6sqotEKF2quSau/fsVqYX3Wpxv31/us/m9fc3vboy2ttsuY3/X/1f9SA46sk+mAAACA46I6hZq0g8OXM1O5Za9KVJUT0AXCSSRSnDyrpoL9q1tu22xhTfm1qNn3VUtax+EwKT9X/pf7v0///////ojiDv+hMQU1FAAAAA//pwBFr5AAACAlLfUSoR/ENJy/0gLaeIiU1o5cyuWR0sLzSQKcbtHwklJrrab4lxJZySWHp+VbwfO60viZ3qKRwZHMI/jUf26CsE+2pqLryHvZL5H/rNQWd6dUo/6cz//gzfzVH6KiEkgGkXPbJDcXsOVRA5f1CnzjA9rMjGBG+pPNzW81jX7/bP/mYbIwVJA6MfRdnSQRN37a396taO399qv+//rG13+SoAAHLbxsxlKofxwS3CDsgT/y/NiyEujjZNjUM+B9OO7UD+vDB1X++bnH/UqK+3aTI3k/94gd9P///6t3cQHGWTbCw9zpIIaARCNkFsj9XDpulTPtvecDJwF5e2VEM+R98zmi8uDa9WzP/mSMesxMs5rkIIVuZ2q/9l/7Z3////Ibd3ZRGBtT+P/+VMTEFNRf/6cgQp4wAAAhJS3DlwE9RDKxsqPweAiNVNdUQoTbEVqS6odpWSgygndvtvyzkXrHJS0TP1Y2cOhGKy7VIayAau+pCXRxaL1AelunOTBvn1JJulJKI915+X6tFt7a/1ptXVf//tqN068AEAACTgdpEwxRciDrN7FPvTlvwin1bUZqo6yR7ZZUCj4id8b+rAu/Ed6MbT9H/6CxvfT+//9WzH//////l/9/+VLtmBKCBUktkxi5Shk9sTZAWrJM9wMCc3o2gktTppRRM04p6f6nE5B6kbCoX3q1d17Ot99ZKIfZv10R+mtW79nBVFp6SB9Z2TwF0AJTfj6Ts8QuxoiUErOl7uYApLaZefTimjo4A6cQajJRrbHVYP1aoCi6O+5BA6gz2dLX3b0Rjx7//////QLEPzhr/E6Ygg//pwBDifAAACG1Nd0EY4zEAFK60sSZuIqTtoZbSuURio73RwitbEBAkVLZbJYTGwPLH8pfoW2QFHpyh/Jfm2vQd+owMupk+7dS7R4kzroWEOps3TRzl9Fq3/Q6pn9KP/vpSzejsZ7cv9MBCDABALkldlncaK7EDXg98mXxRECf1o/G7b6O7Bu+CPRm2K2iD4pnO+wmebqkk3jBbUgVtS0vAXSxcC/K8n8mQXbtx3BA7gUGpBUNrIk+YJ3LzB2KDPaMB9RL9rcSJ+IBsjOr+5R+JvIRruDD00bWlyupWQvZfnmQVf/+v/rfVry0AtuLREMVEolK266sWNQujl445koNcfiAJGsZpxtkvk1feb/+QF2sRGoMpO11ZSsmNRHW1/Q6uzSG09Sm2zNStv/UX9AT9lZ7+pMQU1FP/6cgRySgAMAgpO2hmrKdQ+ScuaFOUfiK1LZmY86tEZJ25oEZwOACd34ssYY+sNCkZBiio5e4Z1lNiojLTNhugrpz2TIL/ij//vq+/hg+tPkvWxEO93/Sqd1N9L9C7tRUretdkB0Ro0AgEAtySyRQd4gLqokUTQZzTwsAW9np4jo30dDAv4oSeRap6aPp4lTZ+22hUTzfo+bN////u6/CIQfUM24nACk24n8D1yoPET4C7kJ5+3o7VFJQsnk3m1F3DWUap2jyo205PVv+WzH/OJP/b+xI4opypX2aVS1W///13R6UVEFSfqWzewvgkJyy0Q0AaCB5QFtz2iEAbKIcA57G5NM7Tv2UagFaNj61vWnQgbUXZngDFr7vMsxtJhxxhyN/c9Jx1Eb+v/9v/UMN2UpiCmopmXHJuA//pwBEMQAAQCHVLZuWk6tEDjytNhJ5CIFOtmZbylkQYnLWiWngKgAAcu3GzCSJoTwtbwatNDnOklYT2C2u86p3DGjZHV8Y/JFpv16Nu/8VMiKqafuZVT1Svobj5bv///+1qdkCFnp5YtUACjBB+rrI53iSzNI1PjzqPcT/V1qPcXfisPhvXsg1yVB8NNhA0o9Qy5zso8AToW1LyubREdt9H+QWOR2uO///lwEZd8OZDReCNrOJVBpre7/QPyy1yE3vMVr0A+rY/VyhABUlLUrf/lxr5U0s+pf/JlMv9DY0fct97VvsSJTPz2lEIFAAh3f6+PON9YdXiBHpU/ah32ViNYKuvqLGx/R8lrzu2WIV9/TofmpqHlk0Nrzr5xu60enukV876f2+v/9C3/SmIKaimZccm4AAAAAP/6cgQQrgAEwhc42bnyE7RDByrjPiKGiDTrZ0ZATLEVpyyM15YCgAgVLvh8YOeBcgLPeRCe1wN9qZbk1EZguR9qVazVjoxjrVtF8EbTq1f+o+UXm8/3m201ZzOn+LnEFr2i5wvXv+vsJAAp20fchMX2UmlVI2DlpRcW+32rF8RwciEcXzqacoDItjMPXydW5ZdFXjYsTsnT04/8rf9fqZ2dqfUOrBVW7/Z8R9MAAIKjiE10eFMJVI6ywv+q7pwk8sohPDfnVbPwHtVQZHewH+Jaj/69H184htR2rNU7juqLU36pIJZ+5gojYKq/+SACt24tGGPSKUDZwsnUTmqaw7pUCGz3dowHfDW+bGvQV/Dj0r07gzlGh53U743fVmtuizKi0r+XUUShv//7da9rxoDcXD6YgpqKAAAA//pwBIRbAAAB+znZGTArJECqW0olpWSIfOdo5pxzUSCpbRx3lgMguXeD7QKm+CgdtMt6XysetA+EGKnSY1X0O9Gxy1JFwNr7wlatt05+TxGbXdVb5pWs/fKiDDijapYDNaJVf/0JAAAAXNvx9oSl+qyhiDGVPM3zrDUEuUmmqLcO9vq6nALvjyRj/bvy6eLK7vT0Q/Wvc/9sxbd1X9P2Tf/2FW06jIIoJTf8WjDGyhHGxqw20jF51W6IPInTJ8q+oDtGz9SCmgzNfOf/9sq+viRd+WZfsUjVLYxcz9XAwEkT6Po5OmfFb3gjQgEyb/iZBouq4oQT0E+VErVLFRN61biXHZbK8gA99hrDBZHdieV8f/Dhqe7vMhEQejU6pWcrLOLXf1bV/InpolP1LXRImC9bTEFNRQAAAP/6cgSstgAAQgRS2blsFARD6ls3LgVkiEk5XmecUpkOqWzcloofgQAnL/h3AalkC4sNkif8Xokb2mwIHld6twHVs2gykA9HwTyX7e+z/wVvt/uYrotmLbYOyjOZqdX9PqWqW/+X/HgACXdvhzjAs1XH7EFqHV6yQ1HywBNLWIa9dB2Hk6OAXfIG0daU3j3jRbTqKTPI1plPVe3pp2bEetfSrK36vZP/RP4qwATt2HpYPTHmMahswUO7bGp8Rf7xAqiS+jnR0WthM8q2GbpzfmeZvf3zPv5LuyOrmye//rm/1+f82nv0vXeK1Ll0hQCEnJB64Fp9O0MRzpEG9Il3YWPgM777PpvUexMdBpQvfc1bbW1JqXVeP9//ejE3ZyvSu2/106X5F2srybfpdwg7GT9TEFNRTMuOTcAA//pwBEqJAAhCHinXOew6VEJKO0clBUiIgONYZ5y0kRacrMx3lgIBAASl2HvkLhLSmefRMJQg6E/7YVk47Y4G/tetnjHgzK6E5fniXpy2VN3t/Xt5Jv3l1gl61Nlt0owSGLFMqIGRrrolooAAXt/x7sKGudeWkXwRWwX+EAoABzaheT82g7FX+KtX/nXg7sVeNXt0rurT0JOrOz7tMlP/X2SpHfq7ZPpfoHkIkQAW7aPiEA7nRMH29FzXTft4tfwEp+xTFAOiP+xakRLzg3rz4yzRSIFpztb/0wt/5Wb//lRyd7viiyQXboyGtod/Ma2uAK3/4vAmQicZFcbZrR8JrD6lkX/GXTD/H98t0HUAL8z1/zHfEwNnO2UzOzsVHlZk2OYe21PGPMmzW17+pTYirQCLD16A0mIKaP/6cgTxVgAAAigpWj0k4ARCRlsDp7QAiMDzenhjgAEWrbEPAlADggiJt/x42CjNFXnsa4w/9KOVMCAffN1L1LP55104t/PZn3zXueQUxn1TYqToepaHpFHNSoUJODwYocoYnd2CVsWYtUobACd2w9YZMnGkyXVkVlzdW67WajsSJmHKAvkGdbLN0GQHqnOpdNJTUSRT+tXX/WrW23v9df/TNIMFF0xGz/t3en0ngAAhQKRQKmxp6ZW5qeb2lwWPECoZLf0////f//srP/54+TGhC1VOVP+fMG43cgY04uOsX+XSQE8Hdv/LqAYfBByIVe5xC8ACAVCoUiv7/5mqihByf//////4mdl//vExcAAI2VTKn/F0FADA4uBA4SjlTX/8ofc6EOeofX///+LyEOc4cEcMyn1rJ0qY//pwBOpuAAAB/xJcNzBAAEQD66rmlAAIxH97IyCjsRIP7ImEldgERVA1O6fYcMe5Ls5Vx0TwDCRLwIDMr9ivDj3L4pQ3Y/tJICgK8O0StGLHhKRIke6o8ue35qnkkYlDV7uKrLMVAACJjbITlaylJAmOhbmiKITAIipmGg9R+suFvs9bevsv0H+1CBwK89RK+o8thFPdUeXPb7jVPJIyQaU9zMQlQEeFKyvCQJNejbWaE1Ypt7euSCDLNqD1eiMjwEDatmRlfP7Rumg/e6uDQF2Zue8FZWe1maiOrUVU86sROAt55EqWahCjx09eu0SuN9L9dmYrOxZlFI7V/Otuo6OMoHXv4foQgticqrb03uB2yimEp1eQqcsq0jAbZ8RP2Zue8NSt6KzNRFVXK3uqr/To5760xBTUUP/6cARMZgAAAhdAXTjhFkRCiBvaFGJziKTXa0Y8rJEWoG/0UR42FCElbbtoLjxOcwpuqqSjgBt0ULhquhnpj7VZG4Qc1NffyX+/w/m34vIQMmrrpp4IKmPOSDnKHB1ZtCY6dRY1gaT3WgBJKEU4nLx7haMNk4eqAQjR4AlW9x6D7a2V7G/v0/o3/7Vp4s7/f0N6b59W9IIUAH+iVRERa202IjZW5RRxU7YtsngAAABUckmVLhYeWP0FG5ZDq5k9inrb4Kk++1vQguIvD2vpvMC9WqO33byftffzL9Lv/eHCrIEhz6FOyh+Xk9zU9V//4egAEIaYZdqcs6NZ2JFFxXAoRcSQEKeNUgOPv7ojK9y/xHR/mQ5b8px9WZDE5UNIbl2//M6zv25Sp/sNXpVoRStvequUIcmmIID/+nIEGhwAAAIVQOHQZxMsQegLVzzCeIig34WhoEyxFxwtqJgJWhtp/Ldtdu+OQKk+VreMmzYnDVdGOV5f3Sugv8GX3d/b/mb6+8eu/9353v/nIuCZ4gqsSswXUp9Dzgou2t+iPIycUHwADKjbk+GpX0Khdumbc+M5R28AFRLvliN//wvA/hfPH2zFW70De2Xp+yO/1U39OrM3/1fR+tvu3Dfxzb2d29v9sUpaCbcaUtsl2uih1y3ij3CcOtIYARqjspB4b/rUobpseuS/q/e1W/K/qy2v94gfOEHL/bWb11LNzL4MDW0PZ1vNmjrpOUgABAEqRy3xoUWTALEQ5C6yEwsNKMxWiNGt9jsPM9R89/L+hun9H76uX+61Z3Yv+9eg7b87K/70TAvWXBVUSZal9pkVfcPTEFNRQP/6cAQlXAAAAhgT2RgMiFBEQrrTBy8MCKznf0AMoTEOF23oZ4lSCB9n/L4gm483wCT58lYM7LNQeS2itEPyJGq1ExJQ2lI9M2S5CxPVDf3MthY5iLlg/+hS9woqH0Uar319CX02/5+lSwAWVBIs1U5GOqigLZ0tMHdjG8xIe1MniwioWrpIIuSrNWRldKlaqkXXlaf3mWDRppLwZq8309G78MS96tKtEt7v///6AsFrLcskmpsh0HlEtGHd8YC0vVRLVoWelWTEw5qjVDd6W6H61fZvn+S+1G+bWrmHqLY5YqTWEVP+qp2IvfM1CgUjkwysagAEAKVkt3xwLACFrXq9/VlJR+4euUIISjUs2rVfP2wL+P/5mc3ujs/1J4+zx8WW9F6SoqHmVbjWpT/7GVT15lwenoumIID/+nIE/gIAAAINQV5QZxNsRIXLaRnlH4hsuXtADKExFSBvtFSVjsMAqCTkblzqlKwTeyPhstVRQVYpatGlc19lZcoGW/Hrp+jfav9StuHMv173ZXcrsyo33poPRTkW0W+S2PsddI1PVAAABP7W1uC8oITt7Wk3wp7rglE/916XyDqXIOhY6Ii2HHc7KgF6NEQlZlZ/deqWc6/lXnFkgX11nU2ylguq73/p//m0goBGkpY5djvbvtMkaJMUQpZLoplLDHo+ytqQH/RKU39X63TZ/V24k1VOV0iNFIFsLPbTQ5RJDoBFEFg1a0uvWiRevqiABAZZjdjs0igaYjpK+noRmdwwJGoCzO6Do1pdB5SWlA1kTVv/0vbqT9W6kX9/trTT+hiDJBFxoxtLw0r+yjz1yS7HJk0xBTUUAP/6cATJvQAMghQuVxsDLKA9wttKPSNyiFEDaGYIc9EWIG5oZYmOAK2mw/rCG8i1SSxdjsZUg4NeWsN1FSfkDTsb9bEgg6PEQIPBngEPw/KlGUPgF7xAd/5PX7/s7VUcXWK/tT3Ox36O2AAIQi5JbffqmYgactfbk9zKpcbBRW4u2XFsSpMbwbBl29uNxDvSoe/sv+C7oS7sNV2mNa2htblf1+r/7vpBStuwmS8vc+qMyaSptqPzY0CDZ92RqzseisE3/fR4ctlR0Qb/4Prp0T0J4cr7/2ksqVT9hSWICdDir0DnuTjuStiUMQ0pHJO3W4KSyehTulyLXItTV6D9Qg1WkLcgIqPpb5Ov6HPqkmz9WN6GOsrvXpAnmQ0rXPu9qoUGKQZJW80GO2/u/3u6ExBTUUzLjk3AAAD/+nIEP1gAAAIcHV44AzhMQ+OrjQliHQiAc3tBpKyxDI5vKICKViBlttJOaWzuPchQN6UL0eisONZ6vVPuJGyPOLf6s5qORA7ZWOGgM+CAIajiS5/8Ph8ufBAM4fBDE46TqDDKwffhgPk4AAAGUW/pLvWIsRDZaOUZhvAYPcokQAeOuoANtR9733/MJoJ6tGc1HIgG6dDhp8AFMoclz7OmfD63zOHyGJ3+c5fnA+CCEwbrZTn1TScohvfpiaGF4lzXp6So1NXy31DgF0NmFQ6s8P/I8K1BaCvkqFP6ysOrr+tEZQbOuTAz1HlOUDYoFXSNOBCbAtxlObb5VV20bRwGX3JGTe1QALW9d5hOjvQffoLVCwdbhyoWhryUkp+iVg0uv2rxlAdOuBqDTyx5TlA2Igq6RpTEFNRQAP/6cARF/AAAwgci3lAJKEw+w5snPMV0iNjrZmS8qREYoK0Mx5WOBGBMouxS1PYLVk6EqHSNDLEcLejoJMIlHQk1H3v4/87/+wk9Yx4GK5bfZ4d79QFAViojyRUYFTLx6zs8OalX6zsBAE43BPXCGMo7z9aIfdNeY8HUcFlciYSqvlMggKaDt83dDgbx8XErkXqNLnwoj1HrLsOys9qllEdehbv//1hJzbYfSqrIjTPZSDfeiE+hNIXjVMGNq1bKItOOjD3dTI8TCHXER/V7evt/KiRJH1st2buhc6RgxjmkHqYVEohFEfv+5KrdQJbbcE/iG+HI5xdz7GXY8EqXmpJws7IyoyXjAzfEb6IHbewnUij9NlPqO8vvVPVV++uHqoJO6sp00NsWkW/0osIhqihx0UTEFNRQAAD/+nIEZTgAAAINFto4DDBkQMMa02Hidoikr2bnrK5RD6AtKMKKWgAhk278UIz5VFaK0KEzvFHy4Ev02jWx8Z5cv8TnKzXh1tEvb/KKcdsqzrd9wPJFQmMC0yDbzALXGlLvkE0MWJEvQCS3IB96uz6VCISc9eCs5qG5iXtLrRwyCe6fZeh4cd3o1VZmOfwmjD6BjpdIZDImufrP/xLUYd8FEkFDRT3B1X0wACUuu4+1xSEiDPj1ojbN+WSsIhzV0MKCxaWXYuvS4rVXkAnbGkYaqqzn8uiI22ypUWMCAsPv52XvAup/3bjYosvOr9S0AAkCb224m8mLgdGKtua0glJqYO17zLrSedH0VFfajaM3UHbvjb/1YclTRtqJeFZd3cldfarcXRrP9PDWftLNaSiDrSmIKaimZccm4P/6cASR6AAIAgc12rgJOGw/xdr3YSV2iQB1YHT0ABEYHu0qnnACAIEm25AHpuRCkflRPZ2SfXJrHoFiDKyZiNTN4bOZalBF14+bR03bomrJ2/T9tv+XaDKhvACUh8XtRFmiCqp1ltQBACnZaPwutOp092mwqQco6OgoHR1QhxjjuiIK1M161whf8d043XIC/13v/Ttf/lKr3HIiP9Rb4sbmdWpGhfxoRct2HynjohkZJQQ/TGhVmFHqLS+Uh7xQTBAohiJoMQ+sv0ulFCK/YLf/ofngTnpO76XSo8Rj+JW7J5E+1YHpFLDLGllO6U9UAAIgKXb8UzVZ2btnN9fVd3V0CIMUMGuPlBvKot0Hc7Tp3ni7rodnTmp183S/v/NvnTf5O999tMaG1HxSQDsVLKjEDKE/cmIKaij/+nIE4BEAAAIoW+DWFOACQqkcF8OUAAhIP3RcwYABCI9uB56AAAAAAACAAOBwOBwOLWoP7aqsE2r//uuv///5h4+ee//8xhHQbCR9f/jQdB2FwnMOId9//8H5M89FLE9P///8g6nqjMPvDAAAgwMBgMBgMOlH21Q9IVeLM3oZf5pyf9naIen4iNc41G//UofcwcP6//FCgcJg8wp33//w+L1RRx7P/yg8LkAG8CAUN9BwAwaDuIhKkkoeJS9G4VhHLZqGYnI65GGB0g9wVFqCLgETWRCT2HVjCxUsP5HfbfWYiK9OVXZle+mvqRqv+p4zwC6ByKAl50J6OpV94pUU/etofSwoVKOFVS1cyynJi/9pWLu/vnaW52EqPPOxMVEQ/kc9b1uiKPTlVlmZV///v+pMQU1FMy45N//6cATHiQAAAg07WzsPKGBBZzw6HCd7iLDveSOEdzEYoDJ0MR1+BAAmm7bDQicq103oQrmKSeNMweinDtfKKGUIJT0VSjNeW9EMn9/Rq3tfXs/VkRr5dzU/3/8VRxY6h1r4dcv7f99Ai4ttyRpyoFC6WOc6pvgRe83w8YEKXnE4J1ndMFz/2ubVF3//N53/+3K+pbLUUlSz50s19bhYlIiWojYEhVSx5asAUCkqmgBAChcSNuhtqNKgUGLYqEs50pS5g8xxfydhq8WBinyZkQQ3s0EtHPNCfbzWxr/Szyo5zEXPKErmlVStz442nlqwY7gXrJtvdvIZqjHFYX4Z7YUIOa/qR9Otpmmo2iJg5X/Vv7rZG6qrEGdUV/0Tr0qa82tFNUTBgko9w96WKoXJXrbrW49bUmIKaij/+nIEtoUAAAH1DNo7DHhQRGxMTRglFcjse2tMJE5hHK8xtDAVRgQhS+z/qVANYuTxDxYqQZfW1MJ2ArRe2d28NLbXtBkw96nwUKucCNgby1mH+/Sl/k+ucJFNyH0ddrej//dTUEiqAHlJbZN6C6RkVxVvCKehcq5aJ1Zmufetf6AZP/p53/J6FPe/+mlGxj3/5G+v62rerVTpvuZEI2bUixvUp7lavQSnEBAICayW5RMu9btbtYzFv8+7vclRQpp6r/EHz99GTlBrVb1v4m/qbOJBspbrjO3Kl1+BqI9J2lMPXPVc6gmVX7wpsrd4w11BtPAKWW7aXetRZ2b7FGbamq/aqFqt3ebRhj/tgCdtPvKq5W6bk6D99/9tBXiTfpfEx1v+isvmlq66bn3oVvq32Uiqo1wpUOTEEP/6cATIHwAIAhMQ2bovWGhC49sjYMVyCHhjZGwcboEFHO4k9pRuACBI2pKEuFa0byfOVxeDarHTRVifC1UtThabfz9PXIAJbxV7AHPDlz7Pscjmcil3hKJn563GtUY9Q37AJrc3dv9tYKer/5UWTVnn0lMpmp2g7+q+rd0Zi3Sg76Wnjv3RipRjvZj1aX++DfRCoYC/fjUfJRWp2J3Qi5Is3ojdvZt2OMdzukLPWf8qFJyWsbksl0ckW+Zwb9NOBpZQZdQhtV/UpoRUilmwCoNYopEMewqcc0Zg1yz/Xaoc6Z5FFOt5i5V+j9NVe7WSACAZb6rLMbWJVKdFO76EG4Oe2gEqPXSZhtUPZVSisv9FKCNb9DlclrGt6t1MS3+0rsyFqPrd5MhWrIDv6+/T+npTEFNRTMuOTcD/+nIEXGUAAAIRQ99RIyhMQmPLE2DFcgiVAX+khPLxFg9wKJGUPhFwrTksclGw4G+RH3LZA+GXdAE1R1ScrLplVezPfbPhb/oyNctyWo3X50V6/6aeZGvLMa9BnK8bpfmlq4v7rve5lqE2U/460nK3kGUs1Vsy3nMNVdygZSzBQVugQHUu56ajqbbFucogy9SujAKIDG9i03a9H5Zk81uu8VV679zeiqV/ToDRaIiiktjlw2edGiO4Ip7tfbNTajkC2fkrnGFz4zGpsH7vUQf5/TarbevmLf/069kLW960Hj/7BdDGLZpuc6R3yNM9iou4dtS2y3h9zr1Sm7/4SxX0NsTmMNp/eVGEf0sYDK58qUDFweXpNqCd1mCqWwdU99ag+wj0ApOVcKCtVND3gJSA8EEXJIpiCmooAP/6cAQgzgAIAgUeV5svEPBC6CvNMKI3iG0DYOwYTlEPF21c0IpeCbtv/KlLyztInx8jvkQvLqaPU5CYgFCvexIuFM0XlIW87hZj9SK72IX+9RLuyrsrNSrlUd02lm+1VqvX9Xt/00AKJAFJNtxyYNavfaF+isQngGKHNoBrZe5SuzNnUpLsqP/xP//7dM9tD01xusjSX2V0J6V0H1Jv925a0XXyxtOaSpqwhJRyQCjUgpXdsN0ksH2sq9/lyJrIDwruM284zS9XQ6BA2hLKDa7jN/dYH/Z61Wybr6P71r/SVD5B7mZHuSXwXXbv1CABSbKcBKjeXCxlJpWW5irAcgwdGpRS09MRNPQJmbJH79Rz/24tO1lfdjtwzrtfh+Qoe3UKkdOrixa3A5wtX+9zz9taYgpqKZlxybj/+nIENI4AAAH1Hl7QwzPcQggrmigi44h87VxsDO9RFyBsDYKd4iCwrbtslohKN9Rq3bP+UTDOZ9G7T/ltysP6W5VSk7xD4CI64NlRcoSq0Mz+ok8OiShR6Kh8NuWQlmp9Oo9qUBCBRTkjkA8Gw1LuhqHTvQBcxjtxY2MoforMuqWu5+9tnnhSftnNHPvI4vNBNhbm+E1U9mIZn3qxqEHbftSsxp6MiCk45AIuQE+VJDK21FK1vk7bq+2rtgOUlFhcgAS0+2GZT+GaZchDb3y6BCf/VlzXs27K92ObP1Ovf9P2vJ7EC9vtIf6AW5JaBiEadeGPt57lfZ2tnvmQIFkUCoVQvrmRDWdXc1T5B7elnhr/dVcxX1z26PbZL11bWe1UXLFD+6T9kKF0jhmwZp27UxBTUUzLjk3AAP/6cATAIwAIweklWRHiO9w/5vqzZSJ0CMkBaOeErjERD2sNlgnKGqbB6jxnvCZTeWI258ZytFmTAnZWaYX3TKlNbn1UueSd6Z4WN/o3Hmq68kvRrzqUqn8T6me0tDtzRiFRR4CFtoBjkBgKxmlyyllUrlV114BbHnHWwnTCwomDUqVBKEZwtzClpZXqhTVZA397jf7XuVSW99U8z//u+g8Y/5EISTikAncWN5UhZov6fHiMAHklyjSg+1bdGlnFClStCe+1QF/3PnS0btTCh5EyKVCWT9a+rrlqPuVsJnGKfF3MoGsRLoO6ACW3KBHC2FEh9qfCapZ6u7E1M2o9KToWLa1JsOtC2LX5VZyZ5WsJpdf1Ni/SJFMMmlrrwVf9tWhiKFkflq4rVSoXpiqkxBTUUzLjk3AAAAD/+nAE/JwACoIFQNm55xOcQuga42DifIhku2JnjFLxEp0s3POJzgAgtNqQIBLuswGdEusYrj2azYBVoyjsFwSyJtMloL7WBIXMzp4p/9dFVpX3PmR+1b///Y+PK7MzvF7OCucWXuzYJcjtCtAsZwZbzCtKcdRGh+mlM0bUp1IDpng11c5Lnsg49bVvWpn6sxoYS21bGZjqzqtG6+rf/0/7evfCG1aU6lr5ppwCRd7ZjRJV4zqfybsf4DUNS81OZq18ZWZdpc/k68CJN4f1EHv/RinVqN+1uKnaeIVCWNOHCW/ke60lLPQVErBU7MjBUjTgKJySzljF4tO5Yzvew4Hs1JUC7taquxwjsm6Lkm/rRBZVvLo5i2OMhDOduDL1en/0b6YlNTyIo933ONLfQiRbQhMQU1FAAAAA//pyBJf+AAiCG0DaOS0qTDxCOuM/C2CItOtWbLBOmRmdLNyXlZYAJSkrkA3beMKHTWRQnLDSCEEVTIyKfqLo7YnrZoxbZ/yGsIvRb7NZSn3bM2UNMVbFuRu/nJ+YoZLkX46iJPccX6NNIKckoBMzJL4gdNxmtrjVAStbtwjppC7C5sqswAyda5qZ1VDbHHDbTtspGegYyx523CZ5t+2YVe5HBplfSAVJIAyu/TKfkTtLkViyl0R1MWImmQcCYQkWRfbx8KPNRR77wRQxH9aOinU35nnAn37JImdzEyuR4Z11pYuv4RaK2rDIdoZTcrgEwgLb1w+2ZpfLe/gfF/UtexImvHGsVh0Scjy3PsJ2R92sxB7trlrqZXKtiEKsVHJmFiMzLT9bqQm6hpXnizTqT7xiYgpqKZlxybj/+nAErN4AAAHnLNm9POAMPQPbN6eUAYmBd4FYI4ARLC7xNwKgAgAgpuOAK2kSlZUg+zuf71DfAlmpzEMCxfZ1d0dW0OvTowt16PYSS/+qNvb51z5TCrfi1KhRsVPgaHMu9lYAQk5XAFhwW4mKwVuaPG3562EbRCGSoGoxVbobVKoer0N/ogjdpLRDMoU0GbnhcQObtdhk89hJThgipURSAAAAEAIBAGBAIBB+97NGnp/+df//6KpEz/44PGuOGf/2OFZ4nHjP//FwQhMCwHYjsJB///+JIyxEwTFzjC45////jdT2ViiFCA+glggAAAEAOQCgUCgQCAUYu/1daf957+//0VSUz/5ARGuQGf/yxwUZ4YisPP//LkJMPB+exIf///kpezFHOMcz////H6nsrFEKEhGgtpiC//pyBEvuAAACJDlcnzBAAERBG6PmCAAIqCV3J4jE8QSgsTSAiu4AJpuToQAx3HwdnDVK3F5jz2FhaYpWMhpXLKhnbqyO+ireletDWplLSiGlb+j+Xro3yrothRV2SPNcqHNz5Kbr2e35adBTpctohgmO5YJxwpWw0fMaLroIdBUsBlgUqWAtYwRQreeJviKIlnYmCglAPZne7CcVng1rAS0WFgVoTFXKfbLeN088VABCpqUbhMgzmejsSppvYWHSDTFRVTGl1iMMKHguSOi9AQcgw+lxZLYvlnK8s+epvWlpdyTbLKw0iGniNrMNXbHC5hmlyiAUko9bdYpKyCe+0244/DUwsNxxaospZ3MmNeLMzmjm8RJF7MaNqQnfP8XL/ifF/1XK0411gCe0FaLfw1dUzQzJpiCmooD/+nAEmLsACAIQH9YDKRuQQ6IawmkicghU12DtPEPhAKBvNPGUFjCKP9IFfKQX8yFLWX09PIYlG5HddsJCnmzE+SCS0rOYlQqKwY1olyrCjYCVun/BRClOqJFhCCu0k9BWs7TIkY5T6wn/MABDgkgFae1pzDZSvx/dy12nqmsmMExNHhtZFdgBiWddoMFEJGmVg0BHKVQh+4yAbSJ0xRWfcl6VW+vXkv0f//9YUm4VJWnk4J45ZhdJlb+75lj4Kkkslq1yxS/ux89ByF5Uk5RtafG6e+idlf/+u//DpJjT+1j6yrFFPefR9g31O0VkQSSSG4482nLcbbJwOV7I2quNoJgxovW1FXNK4gze35x9QH2uzf/f/6o3//z//9RMd9ZB82aGupRTTqch+VD9skmIKaimZccm4AAA//pyBMlFAACCGEBh6QEUrEFICvNkIp8IzDFYbT8BQQ8b7B2XlDQRuRiyy/7O3DTAnvtT2io7nSriIwv4tTlU9Aq6gjIVLHZsUz06o/pej/VXqslat/ZuT/5nbB19aZFbH94h2f2pKuuoBciBcFETiGb2k3TrZtfb1TU0hwoVVoxjhY78g/22RowEmWhnigciDm9BXy5hlHL+XMLef+XPsv6eFd/2P9GW/orBTbdtGBo29FDHVphlQWseqngsFkcxoKFTz7C6fcFqF7hryBU0BidGNTFjVXiNbtT9SG9blPTxqarmPp2hOghQ9+/7E668mENxxSVfJSydM27p1VWpd7K6zAExju5oQE6GZanojNRSp9urflTv/7z/1fsZna/0PTqK3qyxKaGKWM1Cl12z3+W7Q50JiCmooAD/+nAEq9cAAIIHOWBo5RBsQsIao2njcgiVBV5ssEdBDBysKZWIfAUXEWrLdrJdBl5BkqiRtoGe2DH1vlvGobBqybE3/sy6aWT3CLP8yP7oZyf7voag7O15S79CPmj+5Nxu0hQWcuw8AW0ZIsgn+jQ9x37qtwZNA0JvwpRuWyKOAYMr6MyMNdlPtdGRjOY4TOoSc09kPJ9Mcb7c634flFv3oNqivzLv/u//WHLtv+1obZcq5g8S2LGWKELWPhaAkOLUp4mm2bNuXVqTujvdovX+e31+9n3+pm0GtVf9VrTRP32oCERWzR2yepmrR7dywDSUrcud4jFlml3ipI3WpYi22gAQTd6kMBE4GZkKZ1D6ZlRlqxP02Z/1vbshf6p4r/+RtFg6KNyH/Y7aHenbbusTQlMQU1FAAAAA//pyBMT5AAACGEDd6YMoTEQD2zZhJQ2IpQODo4xUcQqgMLQzigYABEBuKTSOSpxs32FWFzwIKoyuHQ2pm9mZuLlK5uwh1ykKggQrKt/7Zf9W4vT5dNt0TLf6JNxVTVVRrbl+qhaatG+SIC181r7JknnxstBv7qcvQGhNY8YAv0YxYq8qKioq2l0XtceqDUWUYNBY+N0ml3KtXcgUW/pVOClNcDrY9a9inq/qz5gEppJS7b/3YCctarlnVF1QH518QEsuv1gYSceVaL8ztpqNIsrU3NevMzWXlMXUIKeR9/m6cUj+crK9mEJqc+pg9idnWomFHJFZrt/rtwan1DIU8Ki5iRq5ahNudAVJBVlZld3Shh/7TkVK91ZSehxv1RtRCe19VS959l/kV8NY3ft/Umdu/Ie5MQU1FAD/+nAEL7YACAILN9pKDChsPyaq8mHlDYgpAW1GHENxEyAtXMQUfgAAKL/vAklst7LBXRP47TJabAsO7NgMOOjp0ZS6S0kuRG1dpO/92r9f0obx1p1/Ii9Bg966hUq1DHKtmHEmIN99IVSwSffElTHey5ixrRbSb8gmzOhqlBd6IPWcRdV6XjlNvvU+ev6aP7N6SO2gmvXT3FjywyKN7BcU/d7kZQzekLi5JHIBxGT9qCG8uqTYBIqIa7u4Z96FU3qrRMxWFNU5ZksMuv+m6L+yEfju1b/72S6jXt2d6FBnXehyVSJ2u2+so5TkjkASlE0pSrZ8Pw3IZHy8pAX9+9lV68rVYyN9zvUQ9+1FZLupf0b3R3K7V5oqWjFsOSfIs8tQow1rqQohBSyV0pjExBTUUzLjk3AAAAAA//pyBDU2AAyCChlWEwYTvEQKCzc9Qh+IIGNObTBOwQoOa9mHlH4GYUAnhYTNYH+XqKwO5WbuUle/F2jTCIqUr4gNFa/tilYffVt5tWEcwdLk6tWaoA6wyaELSzfdN+46ZYOfPct/WkA5TcicASQ6mGCphj1Oo9QnFpZWjDfV2YgJ22LO6Ndb11fW/92OiZ7etBROGIiVanzPyY129X3hG+v0tPld9EqqMEZkAE7JQDHyAwRDikouz9ZIkDSvki8X/dh32cOGBs9heWjl5ILEX/fY3GIkzD+q2VWbIBq62fqQ9dg2oO0X6Is9/1JCV9WCFTeNPfrMKlI2XDwJfoTVnxPn3RvwPY5UuYINeSc49Kx/XGu5iNqC4GAhjqwmxfiBIhnXJWVVYj+p6PJjbSJBMQU1FMy45NwAAAD/+nAEKYEACIHxOVcTDyhsQearSjxlGYjY5WVGGE6xFxzs6MCWdh+qgLrThJVi0GQ45+zUXu3pMBsOuOEDhIVr0aqI+1TaKwmFOqOeYuNbO9f0vX+Mf3b/pqVJVjUorY9h67u0AgoEXLI5AMNhgOLB73WMTIAyL1H0eyqUUKJte7jHfdwxaq0qLUmzdbWu7Wr9W0MY5f/E88ohQxIWLDBHb2xbb+YtBYtyRyACL5UilhIfvTF9sswIJaityB/8RLLHejUmnMqMW2iZdFL03yuklvo2xmuiq5uvKvqd4yM1nDzJEXMscrijbTLxIJkqJdkkgBEXFBW3WH4Jj1nIpM32LXlaOm2fNKWf8yIfNSGciGJbkRSIT8OUyXEDnZU1OBXVHNYci03vgypxXcIXOqMOxiqUxBTUUAAA//pyBKo9AACCFTpaUego/EEIKuI9hQ+I2PVc5MCssQEMa6T2GG4AQEk5bZICyncJthALLieIUSCIby/IX9j5jn1iVFRXpEA65JnsHbo8lG69rkPW99CcAWJt+lh695UFXZ5BaQnf7d9i/9gCEEyHcdGC8ybJ9+1Lm/hQTL1Z8gT+qjUU7EL19daLQmor6JVZlV7um7caraDaTF0+j93Nd/zWZRQVUNpxsDABKTkTAA2JgBi1nRgZJOg0HMo2AnlCkpx1ijP1ZkOQOGzNLFLFUDfx9CE/MimLuhVIz7RAGKyI7EjP9xb70T49WigsdMX9IJNf3h1xRjIe3YwPjitezSZoBzPNKw8PrVWPvwxpf79UzfbsPqYKg103Kssc3PD2rvUFIEUP1otACvoxRd+Qo3JiCmopmXHJuAD/+nAE8gwAAAIgNdi9MKAMRGPLGqYgAYho9WtYkoAZCJvttxIgAwQlOSyMEvTN3qtJXPvyZ2iGBQqsXCIat/Se1K3dZmHAV61uSce9/Nb7Mjd2mfmIdmKUfa6Shg8XMkiQHtKi9A3si//oADAZOSSQB8dR8KlKoVo5W2ykOhIeXL5YKDOvpBzCw7jhmbqCzw7FK4SZv8wjltTGP52Vz4fEzRpgRiA2JWC62O22LpGgAAAU3yXbbcbAAAATopfunWFrUlajSJwyPDgsLMIi05XK6oKtj9w0xHR9UdscxaD/iz9bU9XX0pK50dbf/dV/IOdOoAAAAAACVHbdf//8AAAQnlYhh7cH4xaQrWYsvDqFEW3x9uDK8VwpEvnqVWqI+32qTdg8qWUs1ncktnQqqvVB6fc4ATEFNRQA//pyBMuvAAACG13hHgSgAEPLvHPAHACIPDVzvHOAERKJbiuGMAIcDj8fj8fjP/8q/////1a7//IrOpP/D54ooTIEA8O/sc4oRjncoiOCRxhxxP+d53+ocNdhGh5f/u3Rjv+Q5EPVCu7CIgFFotFotH/////3//MVnUz/xufIKFzAoNi39jyY0MY89yI1ICMeUPLDn/Pee++o0JXYdofN/+7dGPP/MPHEPqhruw6SSCAXHY2SkzyJclRyxt9sPIdAiIoUBYTTDVho4BHrllkrSK+yJRh98s+W/BvOiYO6h51fM63SXW5bvqaZjwkDRGsEYK5W2Sk2Cwmek5nPPFlfUKI8k5kzOJh4xZbrcss8S6qw0IyOHc9byx+VWDT8GhKpuVfkq3XSUSursFxGh5MSiIGn21JiCmooAAD/+nAECx8AAAIZQNxooR5MQYgb/SAjn4i4u29CjObxFaztqICWViAAQGo5IyCWijONI19qgAsrMg5kOy2IyCbyjrpfwl4Tby/mi0eIR/NeHl/3ycw/6pbbAyR3lix7qV+mRYsZGNHPlcgQyojJZbo03Ymrcmdu5njRm+FC/ozAzmeSk+/81sT1/55P+vDy/4lk5h/1S22CkiueERY91K7KkwaYszCTXvlZYOACo25ZGm4RBThaCDTo1lFXxwsyO+5yoQ2a79aB715/zP3/Mzv06XHyCfBRYoB0OkwGVAQKmHpWtwxRNhedgmhzf18ciW3AghcnIkVJRw0xCO76idceHst7gMnXnrGtegoK+3yr//9/f9CP32+vT1/7MgWrf+k7EKqnIJuhaVlrZ1mI3ZOMepihWxZNMQU0//pwBLadAAACEV7XUeEU6EMsW2okwhuIhQFzo4xScRWgr3RgiG4AAA1JUglJ2JLrGclmookkupXHcIt5t+u/CcN9qdQMHw+6/AH3vv/Mf5nx07L/MN9f7z+ft6f03W/996L//9t4s/WACE6cjJKibxefOjdx3fd4wcRbuJxnWVXj5ed+hhf/mdvsn7VFf/Rf7fXSvX/8O//927nvT13fer+0i3N0S4Yh6n2iiCCCC7JNGm4VvepKz1ZlOIWwoGXshl14Arq+7v0/Rr4yMuqv+SpH+r/H6fS4jzMv7bOuIekjboHjzkjjAtk0ZHtKJq2tAlIN2b6xSUDNMKmV2Uav1KPUaRMzB3r0UgWo4os7b8Zf/sslRv5Ohmvt/vx3vf8rlyDzt4pKhl9yVR8P4vyN0VLij15tMQU1FP/6cgSuAQAAggxA2lDKEkxDY8saMMMhiGxXW0Y9RSEQF2qM9ImQBABtNxIIstEbHYwK2SSrOwcFWfiUeiMfsKQzIrsxHq/+jP4P/+2X8Ef2ZEb/m8u/2ZdaCmQtGa0faj+9alHboclAAASJjJBK5QGJ75VBpF0RY3QjGuap3LhzYKd//LOsrKVpNwx03ehb9b48O+KqesRE7ci9YAYdI8Jn0MT0o0c3bjFs1gAAEJbGU4yPgSpXbEAOpLxkzCl08SBXHUyHzwV0ZnVUerd5SscTt6vdYFiT8dlZryk9e/SihFWp1zk3YE13fdHH6FqEsqctsPwTceToGYX5CUE0vWJMWfMnAPQKJUkF/njvBkeu1G2Z9el7f+bRzmp+vwStb5qJlsG5VBlgrr0LLU/7Xf6LZJMQU1FAAAAA//pwBEVzAACB0S7bUGYpLEMlyvowJXEIzQV5Q4RS8Rsa7GjAim4EAA1JW0lJi2sAmT1J1rD5/UN2TkdV0Z2SW9CfVC+1P/6/ymbUWW32qEE4f3pWSvW+r/i/4BprGsJ0AAA2rfWJdhyDI0kSkS1HG9WCuwB6TBtx4BOlkUzyBJ7vQbq12+hdHtb3/Tb8qeKu+jc3ta0TK+kL7XV0ItkduxSV+9sDr3v7JLkUoa6oz2rHioPjLYhDWvJ6wqiHgGNHoDphiclP9qt/VuMifNoqhaMllDqb8lagxPTpFCBqxSNtx50i9bIaoryQTFONEpwH5MM7ibCy9PW/vwIk/26/HnSbMJWyzzFwmR/O6EZHFr5wzBL3H4J0b2NrZBSXrFFdch+pZp6kWnbhlmbtuDJx/UmIKaimZccm4P/6cgQyVQAAghQuVhnoE5hDqBsaGQJNiKUBb0GYUDEPIGsc8IpUMusUlfIMiFrWnxeSucEPa8UZW0JkvPKsDoJJA3mNdntnVLFb+jNX9G+j+/2N0HahiNTJgTamucs4+lKabbqk+3+isAAFklEikygoJBGCCZY5TrKagQGaxkA14t+UHvR9V7fd/y7Mpf//L+qdBa9MbrFvaXLb1qYlIyopTF+U8JSsj3PqfbYOKnbl1jlGKFiFlV1DSEchm2YIHxm7mHdLJyPr++g6OjtkovbRmozehvNSql9Uuq5mUmnBIfJBhK9q9JoITQFWgk2eEAZCZ7m7bDRxFl9eCRK1TptUvo0u68r1PrH+zG3himTdJvRmsFclt17/0/tZH+j9Sf1+jUY1Et90dCWGUsjl/T4Gd/9/lkxBTUUA//pwBLxXAAACGUDX0SUTnEHIG2oMZQ+IYLlhRISycQ8gbGiUFWYIAAynGi0InwKRt2HyFbRKd+ZIA4nLoAxKPUp9Q90belUQ/81zL++30W6fI/Errr9ZL2xPfOzNUEJIh4bWF1G2a1b1IAJ2ntY5ADVhWHJ3xu2YmWpjQSjtoh6M37WEzCiT3YqqQQZ6tZW/O6x30b2MjqmbQ0R1tRrp2mTuGDUp71zP33rcCACxcjaTFnhwkYgdVTaPpfLTDRSmMuR7aGZpJlc47N1RgG36lda9tLdaW/jUfUScWJE9R9UijtlH53rNiZ7l6iCqkgABOU7GmwmeDgR4KtEb2kdeuDYtk4GhHwPVtBlHb125z7cqYfL21eutKt+7txp0SmvVTGqU1BWR9kKiWuCXDLKf2296YgpqKAAAAP/6cgTJDwAAgg9A1JsIK5RD6CsKMSUtiNkDZUSMovELIGwok4juCbjUgmVeLleGv2CYJfjF1INmpbWpRZIkEp5xwVvf0ojxrMyegkEaLrTf25LaWRDfkL1Kt5f9PNv+VvUQddn1s+rWAAExUjabHHkI/4KBou9s1P9rimsnG7EHS6DjRIrejc7h0Y8yUSjJ/XbW3/KM6DCaW/kLqOpr1WtcoLc5vGuDrno1diwgAHTmkkgg4TrGHrojxWoBkfiQ7c2iTEHxps9uJhLXpPETPVru5vM1f4Sf2dzXmW1ZjFphEUS/dkiTDQgLXsWwirdXnDFJUBi3Y04KZCQowNCAqiiztBcY6cCs4Z0QtwfVCsOnVROvTcOh9O7l0QtxD/r1ZCt/6JRFol/RdMoi+7wdIrGWKOy005MQU1FA//pwBCD0AAiCFUBW0S8TJEQoGxow4kmIZLthRIizcP8PaxzHiYYAAIg5bbsA8NkAVqJfRTEsudY9zzHXFs9iNjjrka6J3nd5OsgXo85t/t/2r/Vn2Dvcz/XKfRXjIydSP1AO3ShPbniAAALFyyKQQNnBf8aWjH6EeqANJofmjNWoi2ZNtSW0MLZmXMqzN/alHt/w4E2oUxEm/wq9/fynuTAxKlqbiY8wArHYwHQnSlscgSPjo9GlXw6GF1+SDXPZEPZ+XxB1DClV9eiht9JEx1+hbDZ5ViH+iNwGc8K6YWQInnz8gULPQqDTq7pVVzouEJRpJhCH4DIPMjoI4HdobZvvbDqRoWsGAVZ0Q6Mh81XLXzflTCqetarcIu2tlimrDoPQiKPZqjzS/ouv7Fns2mIKaimZccm4AP/6cgSt3wAAAfor1DHhFKxBJOr6LCKXiPTXX1SVADEWmqwqklAGACN0oNYtRNyGNj9ZRz+xrM8sHSQAHIL2FH3VPGXbuKJMY2XLZNQNZ0W60GZzN9evt7wgqsN2TuEaFhk9ozSqAAAmLekUYx+BPBFQD8KymJie2KjtEzpbqEv3KNqVjRE7eB5dgByo8z3Mz094IlrPS4qNcnVY8iiuHzgKjGNSzNVACAknHI5AXbBIT2mo3sWMuMUgNDs889Q691ecYsxzyB3eiWSLJpy+2//+pjIv5z9T1Wqp+xC0OvH8eEgnMtIJS5WHui1ZdhEAFN05bJIC7ZoGpkYhRx7NQ27UFhUVAdTAFmTOJsi2bU69Tne/Uczb67tfdW3f9m2Md95E0jhjBcPFiFlzyp0/bXfZtU5KYgpqKAAA//pwBGhAAAACDixdbhyghESkq73EjJCIjJ93vDEAEQgGbneKUAAAgAgAAh1Tzcf5/QBgQ20VCx5iLYegbPchAGZX22lU2Re2wuisZ60U+//4p29OowTnaX09ZEPi0TnzH//f//99DqACAAAAW5Jbd/7ndAIBQqVxCWYlEknvpOlvb0eFxaxBFJ7NGf3/Q+9nnVf0/655kUEI26FopfT7G3F3o//fv//9L0IcYQUjGglJEkAStCBuEmLWfrkxWwop6vl8jGcqUP/6a6HayS3Z63VBn4hrZ+GYrP6kKWZQ9DtB566uM7qTEGYDEzTSD5YqQAQnce+6ZAJck8QR3ndLKAyNxgFk9K0GxIg/6rVB5DO16OIayLTV+GYrCzakKWZQ9DtB566uM7qTEGYDEzTSD5YqQTEFNRQAAP/6cgRM7wAAAhU52ejAE4A9olvdBSOAiIkDaUGUUBEboGxoYIraAANABnyTAJbKHnZpkx5b/WCVEH26mWhU9Hb/zfMb9elDOTT/qAtl6eZzaCqCkDuBlrI5Z2uV91+udrKxCo8FQkWbSQQozJtpIU3KZWVUVOFWfQltvUvYCEi2NzbvLYiPVLqUHTivneyodLQoewMtZHLO1yvuv1ztZWIVHh4SLNpAFDeWyJNyWCYDipJ/xhqbEEibJyDIoyPPUldH+f75Wo+m6aP+X0N00b7l1EtX6ValQQolBrLa3KX/2nkhqBiQ8YGiuTABCdytopMo0CE0JOVX9tn6R/1TFhHfdb9tsRXtGInmVmKzXvDly2WT/K3QVzPRvuXUuv0q1KghyURZa5bq/+1kNSzVqcVyaYgpqKZlxybg//pwBDUFAACB+jXa6QEU7EAIGnI9InIIuN97oJiwsSGxalzzldgAAohOOyNEpxZo96uh0Lzrnv34wGKhBsqmrQpgR438IPQNZf3irxfgpP/YRrRs4dQ+rrOMJ8BseCdHql6w/Tvb0HzuK8CiPpSl0JWQ1c1kbNtD3Jqki3oudAHtvup7BpEfa/Rv/Qv7/339v1Ft3//V+v/4J/qE3J/kGs9ecHt6CQimZPt9I27Y1I0r4pOvhv7prOCwz4rS2qnsZZHuXzvVu/+p3+VeimKx0/aEg6ixw8LPni+cQ6vUuL+17n+LcotYILRFrgm6kguXFqEnJq2J4oXFgtFla4loHO9pWaIN92Jt99l8wvsu93Ocdd5//V/39RI/b/Xydf/wh/b0WfnP19fpqn6duhFsJtrqoqmIKaigAP/6cgR9QwAIgftA2VDhFPREKAraMOJWCHitY6SEUyEUiGpM9iBoAACt2xpRxS4uEtS4iy1uagPTG3QMc8mkHlCG+ZyOwC9FqV/vL8v1/+nz/3rMbFFFzRDG6W+hTa+WfcVnQ1ISwAAJTbVqWoZuG43unOX74/Ato3CA+iICP0YW9pkyMvzb/0ZZG/90k/p1Lb/6voIa5f5XfFXegYZTO2LaQ2toIopKuX6AIrPLYZMnEkQRA87J2zz99PHN/mke/U4WpZXd/+T+f/yqapfwzqTYY8s+8i2pdBUfQ+l0gI7UVpb1LSmxpBIHclzAslWxkpw+WUWhCFChpBUOtIadulSANaVcuEd/8QdAiQ21tuYoGPI+sKAu7E9Qql/OiKKXu1PpVKu4pGba791Bt4CwC4K0rQmIKaigAAAA//pwBNoEAAACE17Y6SEVeEQm+zoMIrWIhQ9zoaRQMQYXbfRwim4AAACO/byGXWSMrtGEbTHrf3WiQzl9Dzv89+dUbLr9/IvL8/nU7+ZfEaNf9Z5M/SjSo3X/Kmr003+i/W3f9F1vBaFgSB25IyCnRAznAxtlL+DCOcYGAfq3BXg1zeK/WPYYVI/NUUz1YbFfq/hd//M3DrfypApK+weMY4YM6q1H3pq1Xm0NQRABKIss1zbbmRzBExEpeehvDg0jrttkhNFZh69G+dbUls5f/r/R24yJ9/sRSqe4RT9rrMiMLo+CdKG3x6/VoQ+Y67iEkAqShJJLYinLF0Zz63VTtFdp4oA/dSYGFzev/wOx4UfEx8o4VP0N47/huWX61KDRD47CI2bF0HZJbWSsULnSI890JiCmooAAAP/6cgRxsgAAAgZBW20MoAxDRbrdpJQBCGiBdbgxABEcni13DCACAAIABk1kRTksXcQ1U/ygM/g71WrLYYVjIVxFmbUW+X6fVPnpK1P24uv7fX11X+lWRBayzSNaS1i1BBc9kt3XXkQAAAAJLNGm6UEIDEslV56ukko/MGWu6AbHnpeUYqEd/9/pq6qnr/6o35+NHvMJdCyVDVhT1ubp4BU77hR6aaU3rscYABBIAASet+32ttt2uwcOT9PuZc02kmdX21aLNcq5NikK725GtK4hxLqnsOHD667DzlKu2IxK1zGCxml0E6G/0N8gmsAAAkEqNNvWS1ySSSW0HuKiO+bub/jsykQ5iDzGs10yroTBmMUi729vVEXX3VqW2vPXIxKskh/odF14oQVmfV9vovs470bNiYgpqKAA//pwBDV6AAACHSjf7jEAAEKkjA3ErACIkDFgXZMAAQ8H64+0gAAAAAAAAAbDYbDUCgAAD6RGZcGPuHNW7dqD30RGaf97b/l3FyADB9/uWfUhwFwHFiJ/7ihmKCgs5NVP/6IYcDEa//ubSAAAQCQyJBIJAwAAAABsMJygR8CWK8s0/m2aMJ3xRxh9dL/klk8dZIAaBC/5TPskkEMB5E5/7zQ5mhoO5Etg1rjAwoBK8a0OPH8OX5aAie9TXno3VkO9VsI5NrjjZDhUmSIA2sDjqEjmFXLqqEMYSFDqDcRgsMApEqdVdvm0IQGo/pR0SU9duASbkgXMMMjsEwgqrQDQ7Rl1LwjNLFa1BUuwQ7tmMJjgjZ95NQsF7QpMNEAhJCobFD2oCLYQte1CCN6/htNTl6fq7U6ExBTUUP/6cgS7IAAIAhMfVyspQbBEQZwNGCY1iIQzZ6wIxWENnCnFt4h4ACBhkQAqkHkoqv877uRVVkydZW6QjCcLLBgqvheLdbbK2ZZr27Nn4WvsZZZkyJHvPO2H546UBnescs+ppBDatVTNQCSTdussjTcBERs1rSkjMn9SrNOPCEQkGgVBtKCI4aoEjZKvYHs4G06Ba8nhn8nFVOdQKqWCakJ3lFW7o8z2/vQPqatQGktdlcvEZBUsqprUlIQVHrxxDRaHBk5eKB06poNhrInalliDStYTDXnRC4WJTq356WU/iJ8UXKv8s+qSo8JO3llnVjA3MngjIYElBGRK4ozNIlWPVVHY0MYMM5k18NnXKJj3fc5xCE3eyM139f2o/syVKv39/fBts/+bxUj1B2LHs79n/Z/JJiCmooAA//pwBB1nAAiCGQzYMy8wDEGCGpZvCQUIaK9UbRhOURAa6w2liHoA6VTYvM/xibLDDApW6hReYXY37j0GorgRG9dAaaKpDmfM0PCzRCG1rLX3qI2RcZEt+KhpCjV4TNvI1RVASUsVLTi1gCBmfAaInjngk53IVSsjh0EROsyIEZDyAina3KkWzjn9PTETmGmTlph+AYvwFIBKXj6grZ1hiSTfSNQsO67+439QBSbkAjyp9Ns79lO69Dtunn901We2uiu9lVAbGSNZa+rzeq6FIRTvoKNzL5dLu29ECoNE5BD7lIba522GXn2zf0qq0glNyUDMd1la6dI2FuWEpFhbnrTHf22Maal31NrooTJ7c6PtuRrpsm41CuQujo8+sxbfyWBtJBAa91ZF4Z/5TFaRzmvSmIKaigAAAP/6cAStNAAAwhYUWtIGKCxD4ipjbekaCECXZUwgo/D1hmpNthhoAcBtNxtyAJ47Axm2RlJEdM4+9SBmyGRRl30ihkOlFuSkRIUAQKcCdQNGwu3UxZUIu5HJVls8hwkWKqvLWJVm5UinqABLewGccmXCYYbuWNJrkrjImPJDjSh+GdQ5DiGrRheofZ7dyZPpFwwfLmLdb3LdzJsPPUXJaA8nkV5xnih4QMaQO9tAAgMlFtpwEN1uTMpoJRDWqmdL2bXgJB0wyc1PkRjf63l5NzMqIQtyhKIURdAhdFSXrLV2Y9DZ1UbrqQI0rciI3Px6Bkt/ANjRZBRRYiqE86CIxUKEN9R2k0QcPuQMQ54mLrbQYHRVFqQu4mH2oStjFmpEVB/mfZiFSuKj7f+z60xBTUUzLjk3AAAAAAD/+nIEwmsAAAIVEdQdbQAAQcBrKqwIAYjIOZG48aQRDJ2sQzCgAAU5P+DCa1LhyUhoMXQvN34En3+5yZfi67qeEwRgYp6a18XA+pgSzkgwbBgNsFV1kCY+bnXxhrSiCq2qbc4q6mrs/2gAAummm3AM5gSbt43BEgJiSFGnwReJBOTPvKg4ZBhN6rkDWgR9ynubQldyEPHAzPhioSpelVx4tz3nrWMcsscUkuAAGBQG3ZZJbdtfqBQMPxwHTTfxqbfxrOcxInCvSjCQC8+VQOeH5aecX2G49inTiXCWlR8pGoNhmT2qkw///2HP//unz6z5qNOgLLuB541R6nLMIlt6rnTs7gdChaIsZvZsWwBAFT/EIBXFt//djxYHn/5h7x+f//uYrse///48Mh///hg5//92fTEFNRQAAP/6cASdNQAAAg4a3J8wQABDg6xt4ZQBiIyBc0YgQVEILm8olYjaRMQKTWj85B+407+2VAXd+fuHZZ6Fbs6GXvN7o04wrESgKHV9jkdGGr5F0MrEg4++lCBwMoeXfrd18X7q9NinmbZYuFEJuNOoglqK4LvF+6jtI1SyqUqEZupTGMYycrULAW00SNCMFg6oO+Z7pV1ym0PnBVPcksddN9v9bdG108pZFD10hUEAAmhYS2xQqUjWCgTXkoCI+74LdbOBlkcj2f0HX1g+5QbmDARgS24aa87ry3QSp2iLwaPETmTywUGB2mo8O7d50lg1cAAbbQsScgw1Gm/RyflygdMjVOZ6EWyuVWAKr6/+bqM+YCpUv1+X8vob+oro/rQ3+l6W//Q1kM/fobN+v3llauYVQmIKaigAAAD/+nIETzcAAAH2QNq55ysUPqgbI2BFZAjE13bkCPHRIDEw9DSdTgAgCCKCBrOsPtySN5eta0lAxqKRLYVq68R6/+/qHoifGlDrkq////ktqKpiTthf+j/9NS0UVFkgWNLFf//VpCGGdGLBJNPzS37m26KvxtYwIOQJjEFJUXiwLUvfjGoM69EgChMeK8b///tt6l6OxRrF/ob/6FbUdlf///p9BI0hd9vzzaQe2NToYNAfX14zSE6dX06Or/anLDPkdPI32o/aocHqUo4VIGXB6Db4srGgV9F0ledL9T5Pi84K7+VHF8MUquLKEOibZu7u7k1H7nxOB1B8y7Ehs3nde7Z3+07vL/9mbMsxyeYT0dJUJHPMF4uaoIt///oXfUgf/6W9FV2SlParL/+jczmfoUTEFNRTMuOTcP/6cAQg0gAAAf4y3FFpEhRD5vwdHQfxiNzLb0MkprEaIG/ocJaOABAZEW124KV7evO0ceWaCD5j4WaB3+z5+j2+9LzQjSBpnPs0nrO++ReNBrW+CfZT5Je/+qL+S2+p+JnjAXorvBILFbSh00dxXUvqdZ4WLCsRnoN6mjbr06tq+nTa9x8WT1a1f/35SNf0wWjnRTLcTCH13k1DffD36MugY/0LZqr6wzyIgADgCNhKAAelAfLMJf7JABQW+JbBjsxV041+9v55aIH2sMbvZb6M8z7UGMbVRbOhsZmZTzHO0d2aVvlZ6viI+l4FeEjdEXBGOtta1SYcer6kLZwc4wNcpxrynF0qJ5NjA2Y+VBU8x6mV/vRjMjVa8S0mV7n4b69X/3yvxVkUe3/fXwgOJqCYKlQ7IoSPTEH/+nIEjaMAAAINH1/oZxtsQSZbajyjfof4y2bnlE7RF5ltqPOV4gUAwU42NY5MxdHnDzCKD7crsJVo++PNYQjOiIqe9eLoWFgxjHl6Vyet2NQ+SljyrNOwteVZ/9L+tTEyc1U9bgicQEAAKQksop/X2vvn1bpq3+SBjVteNgXYPajerZ2oMFtPFrdpX1tT/7e5aP7EFiG7EQNLsS3u1DPSOxzv/+9Ha2mkAJAkjkh6rL1rtatzG/sgxXGnDHNiWUIndxR92eER9Gv8RR8GQEisjFbT73XfbZPszKNoH0SKh/Ts18f92n/+0AIQgja3dl+ul91mkJx99ZBDo261XDWpHUcP/Kk8QOu3zWqgNzMRLoit2dZv0+b/HbJS/YjSj5tZWMfsOT97CqaVjr0awAmIKaimZccm4AAAAP/6cASZHwAAggQz2JmPKbA/xlsHPyVWCSjLdUEcSzEZoC5olpTWgH/3HV4rB1RvF9u9GtJBAjwhn9V2GsjBDiTbCodKHQ3Rr+gfkMtu2y5L3rdte2h24uf9AiP0J2dalkNff///vpACgNtcAr1BcsyIipJFX/zSiko0PSNpW1i3mO9Q98j6BF2go/Ev6g9kPMrCqLKaTZfsv+ibFHF34wTfDcV/f/oQXC9EWxS0Q842o0GQiF2kbOs5hu1Qv0bBD6f6TUkmI0rUsVmO7qhwe6eRmygDLrqCfb2ukxwwAgVVdLliKHEXUjHgMstq8jv+sFwxHDJXO2xakoPqRHCKZBPcDviuR+nGAZZhx2TqPmvRk1M+jf/f8jJxQirKuLP///ncyxAq5pG5B8TIcdYr2rNqRVIqEN6Ygpr/+nIEYNwABAIMMtc54iukQGarCj8HUwjUy2BnnK9RGaAt6IgVehAABSKAMybWFCKiBvCG+dqNMEdHsHtysGoLCnWMPhPmfR44vUso4/E+n2NOx+Ri25TEZ5BWjOJcZ978WAFwh19p0AAAihrJAHyNhaFRfCocs2hQeKMI1Slg1SaBmSL8avUZpEYWPVO+IRyNTWtO5E3P+iW7fp8/ulio0fk3MPlWdtQIljtDeoqnMVuNWjfUNDgwkpsvDp4pxlLRVzXyp/yPoGGPbMYFBmU45UVzMjFszHYx32r0jyNV0xB3U9+tN5RsQ7wt1dyOkAQHg1dr+HXICql0f1JWDPBpLKi8mWrQ1nO3WVXpot86PLH/YdZHS9521t0beylbmWyusgE8i//3kKrnEDlblT7K7JWLEtCYgpqKAP/6cAT8jQAEwiJAWLpGL4RCaBrzZOV2iGj5YmY8qpETICwM/BVKkCAHNMA5JF4YwkVtVTWQUIbL6iBnrkOZZ/eneRnLJ//1EXt10lZ331fdf5dwaDaTY8Ncs5UXANvX6t1o29UEWnCwe0pBCddAzsW2YNWlD13aPeUdcgh0a5WidycDqjNqP6BYzaqlQ9PLFEJx/9dE//rUiOVBYScoij3B26+v+xnMuolAtG9QAdk2DtVgqP+lpF2UggqCugopz/UvUe15eJDlhEN+/qAXLsIJrLvUjIhbO39H0m5+Inf35/+pxGIhCPzjsXay3rML0BByy0TTwyyevlK/c/5GzCth6EvbabUo7FzvQZwm2JqhLjadSXrdRTr9Lsz9/vdhUVM5g663EGiIs3+So6vrR7xjv+/VUmIKaij/+nIEuakACIIHQVlRjyqUQygbJy8HUIh5A2VHnK7RCplsHYOZ+gAQCAEumAQ4oh4Gf4hQ7vswJpk6ExsBpDJFHmwmO1Df/UC83Adtq1d7UeZl/ZBMUQqFGnjhwrwx//v/dW5R/ZVWAUES67BU80WLp0S1NqVO95Qk8EEdCNUHND2zeJxnX/DFPYx8cOaj5jTdtfogyarnjxGqGKyhK3Z+bm39K0WU6P+76gDIEuvAa6x7EX8ZQd7Xggk4NkfjFMoxWawo4QstA3T20S8vDr59EapprN91VoiKulSuRBBpiARP/v9SxjFnYe15JxSsIAc0wG8sXic/k1TvJl+b3lVZEWtJc2cnU0R9yHFbrGgzp/KAjX3P5/7Odo3T8+YGy8vrJVqC+w3ZT63DVEESgoptiYgpqKZlxybgAP/6cAQKcwAAAhNAWVHnK8xDRltKPOV6iETVaUeVD9EUGa008qX6QAAJANxQCurylr8LlHfX0EMZqqxxxVsUnztCZYdUFA/TauMCNr3iD3G1mZr//pzI8WETow9MwHb+i7X9qZIoxkxEYAAphK73gY125pkkkSv+YgpqV6igVHOOTjydY0fExLRu+Cg3jy6xja3QQSZSZ9mbtjBcdiY0ysYYbB3292oJ2BxMp0ABAuALf+BjcVJpb+CyfN8DecPB3cR2CdHEeJ+/9+DfK9aMLrQdXb9PmuyF0KFj1NpccGQiEVvLOjmrB5TH6p66IqSQAQgIAbvuB4knWr4bIvvRxE7j1evcuwnGqU54DNiTf3xgtLbiLbOVBJqIjWrZ21udb/1Itd5sdpMRPrdecRpDpgW+Zm0xBTUUAAD/+nIEDmwAAAITMtjR5yvUQAZbKjzmfoj4zWNU84ARFxlsap5wBgAQWBFuuAknuYcbMrwrf8QROU1hidsw86MJDqwoXEJPlt3R06hilrlCTGRTIosWa/en3ZDiukUREIQlQFfCFf/xbegAIYBl94FMYhpeDtsR9Z5H4Qkh8R5hpLiaYUKFjlA9tW098TEL22Jc7v/b27y8KTZvY3NSmf3Iv/zwqXNddyVoAhCCbbuBZynIGcETJ2L+s7jGBN2ulBqtSTVPahYN4+GG20XKBHW9DxO9zDmZi9EOT9v69F32mD5eVOmT2JhZIkOxTGMErxKAAAQAbbgDZHyws2L4KbOOnjICfj3zUtVCtyZOYYCIbPPIFseLd5gUH3a9VJNrqzIxnT1/vql29Dio9BmJtEoo6LNZRHqQmIKaiv/6cASzugAAAh5lYL4E4ARErKxzwKgAiJlZk1gFABEUqzPPAtICABAAADAoFAoFq5EznHBEXun+n//////n///zxuTADEv//+NDSY3Jng8B4Q///8geeNCFBpY/////93MIHoYNxuTQaEAAAAOBwOB//ynX////////////j8VxbAFiHf//8WDScRY/JwbAvBp///4sEZOIgaSgsMxH////+5OQEhOhIIsRZOgqCwAABgAAgMBgMBgMAv////f/+TGER5r//jwjDFgwC6Gv/+PR6GgUQXQiIkj///8KElcseKxh5IaRf//+Njx8xrEKGlzmF4AoGAwGAwH/5f///////PzJ0X//JQzDqwfBLiD//kqPUPAmwlw5EBpJP//8TUouaG47kC+SiJl///48ky8yLGKBqfNmH0D/+nIEtZwAAAIeGN9PGEAMRCOL6uKUAYidcXlChFy5DSCvtHEOfoQEuFtG2zsNkDePfcgl2t3bAj7e89XfTRsOxNn61rQDIK4vhqdnqQrDU9qeKDzuzSgcDT5lZbyJUYTFQE8NgFi6w1S6JEfwDGQS13YquyCOFDmYeYweaEgO0h39av2/FE3xIYwsK6ZJoCBU7XlXFZbAzSp0tyKiIl1d5lKfZ+sc0OlTQStiV1EAKTAFRpOoWRoicMUPUAzYayBJpufxskr9tNQ1qcd//GoNvL5VxPE/5gLJvVfZNQrL5v/7LSre/TL1NepSlSgF1eN5+qoUAC2mEE23KaMSJZJzS+NgYcXIYRtjOYn0qbm/O31//r2//9De/6KMaqPnZ27KUOUKNXT3RgEYBwFES87J4lKT1vQMTEFNRf/6cAR0jAAAAggl4WkCO7xDqAs3JeVEiLEDbOWUTZEOo+/0UR5+xpBMThLurtzH7ElQ1Y7xvA0F2DzHyJWStE7d6hg/vJ0Pb+sluWVJbi+VSZ8D6+SFHRi2PWiUU4URxiHr/VTWFuuBAAUjklOofMUIBUTqlgrxIxU7mlwBHxMW6cIQHZTPiuj4AA++71/2o9T5DH9bo/A8tTbfT26f08Ij92LGu7937e13dAEAtuW3XkeC/Fg7nqEvwSHQsEwE3JnWsSZ5k5/oAqU6YP/21+f9PeT/7EFVTuvlLHLaHc+Cji0Uqi9ehzjuzftUsEbLR9BAIhkCTkclCnkal43C2MJhuMqNARqqyUZsj0bQfAyb6a/+TVNL/t6ijdv/0C0p/roFSXTa/cufk69FzVHe9FQQmrZJMQU1FAD/+nIEaNAAAAIbQN/ooRWsQyb7AxsHKAfgZWjmFExRDC+vqGKJxoAAUU4iVa5Ko+7xl4Ngw7HY9kRcgyrhZTV8su19//twtaqn0MxtEVTPf7w/hvTsysxaBHFyKFxmgkpecVpc3fvnnWVAA2S7FLoKDSrM8tyumtWmyHrb6vOo5oOxhRqDnTuNw4JmkNB7KF6mLzI7r/7tVvT+nqnf6vPbQm9/Xnkf/87V7/n+iAIAUbksP0QhvK4smzIedcFbxBcBXkEan7RMnQTp3Gy1vlYhQPbrdvNfdcRZr42lvpXZ0Heqw/IyCBPLONAyzdQrwSpHJmXzE4ODZ1fiQ/ONwjoEz+stWbXTkJ9P/5etrP+i+Cpf+1W0er3/ZlqVqUlZK1qZa0/1Sz/emafp+a490WTEFNRTMuOTcAAAAP/6cAR3aAAIAgYl2zjsKTRBw4wdDOZfiJUFYmecT1EalyyMx5yiAEAjZLcrIIQ+hrbQHM+KMo+EMQP/eG0bR+8aBtu3/0j84rFyfCHlfI6n6gEowaRRrHYotT81xag+4yUH3EVkCq4yUiG4i9Y7fWufRigHxwP3xo9j8gnWkqzadsRxvtgo0v+TW09qyv5R88T7gCHBk71IMWsJdfQlZ1AkkyIeE8Vg0eADbck821Wa2TNYViMRV+QtK7d0eC9ooIZnjSBSFyHbK8MNS1cI/7aYNsn+i+My/fvJtJUlvRXq6BxFMOZIn2eQ27XdtQAUblsNNKw3uNNAeUuWZAcQzuxsUwImy2d9xxhOQLVI6tiIPfXR/9kapDn/0R+X/WcW5tvaIrvQfi0gyOURsUKeGXQKLW5hMQU1FAD/+nAEBBkAAgH9QFiZ5yvEQOMrFz4FVIhNKW1DFE9ZGqCvdLSJjgC43IMRcDdjdc3aJTo06C0x6qyHhzoKBfn+NjAdwqSardowLbY6Cljf8r7NZbfozaC7//unTOn3dt406yzQI0ACABbkkzN1KfbWD1jz1I6ZQQREpUEwdEj2cJExFedwHhZB2TVsBxXVI+Xor6nSe0QLKl3CEcWSa5Ms7+n66bf+mEAFNdwVfAaDwlLBMcQvnh6B6gwfk8bJI7bfgz14v/+2jf62OIZp3KdUI8vSq8kwr8zNTOyejUrragI6TtKLP9uSqwAElxklO2W5At33qr8G/AuMtLDM3kr5Aenq4BXyathDb4Pv/y6vkUv5kJqIX8tuKLy0Kr+iKyOsbaHrp9+Q6E2K9NJEopikxBTUUzLjk3AA//pyBDoTAAACCTfb0SUUFEFG+3okRX6I6Odg57ClURclLSiVlKKBRpgU7tuKfzJ7nFoJG9PivdRj2YrlB+A5OSWh2ofV6q/xWn/qkO2/+vxJy1S+6Ho11DD2C1abmtlvQNYsZtI1zUIAKgFbbcJZRWUlQ7loviIOeR/DPcfP6OPty69O+n/82DEb0b2GlXRRDOix96Qwysg8VOM1zBBVOqt59Y21R08tQBACpJcPPsg5WUeSVhJTaomvUMQ8aq9KDw3Dh9gGIe4jxDG40W71DN2/5sRao7/Yz6OXLr/ftKOpkClYqiAOZwjW+eWfJJi8AgCgBy7cHDdDZiYoBKmjTyLwjlKWTUG28Kh2jcZrxN99W2/6cd/9SdNZbozylgw5UOxooheju76R1a319bqws+UnyNLzaYgpqKD/+nAEdn0ABCIIP9kZgivEQOgbSj0CZIitA2LmHE9Q/yBtKLeImgApbsN+o4DaYaV0i1LAWdmDF5ccmHbYGUVI3E/hn7a/++n/4w/QRnR0ehEVJehXRZvZ1ZSjSLXULXDihgtonn3OQAAoAK27jE+3qU0KYqt4f75VrNuGvaoDkzorZmDY3B/gBPr2/2fTn/2Zui/2TVlopsTfy2q1xrkfN1KeKnTrqzMABMs2DMWFUbay8jw/gLJPRaOTNyjKXJ5j7NDMTGNXo0oEeZa3/6kztr/h2atGXXa/Xoar093XY4IcqWFUruFJ6tzGv1LYEAO78SujjFAU5YpmF+Nl/CAOD1GqYj6stRtTacDX6f/2bJlf/dsion+2DNcozdi82hUqJm0hxaEJGjVqZhXpTEFNRTMuOTcAAAAA//pyBDcEAASCC0DZuYcT1D7mq0ol6iCIUOVgZ5xO0RygbNz1iOKAABku/GuaBZT0EaOXrKyTOrBnldzNdbxdPZq/wm04GkO9/7atm/yq+7/390VXSehUd7LLNUCfrKGQIQsFzzpnvWAAARBW23F+ygRowisLRzCSHWPG2VeduR6yGsXlmr0bHh22v/6s9BNVjj292Rm0VGpdkfyR91GYsu2/FM/oYsAKW7DE2CsiyJBrcsuEqFDKiYRZemjRyiC/pWOQxBUO1TatUT+bK//Ttl/XM91BT6bU8mhca64OjVUoeua7LMaELKUAF678Z1ddOOVOMw7nuBYMmuOePHZcifJBs1V0GpXbJ3/4S4ItiI32R+iemnIgYiUTZGBaOrsQ6AxgEku7EzhV96twZFFkEpiCmopmXHJuAAD/+nAE7hIABBHTFVk5gSukQwj7NzziOoiU1WTmHKyZEhqsqJecaoAgFS78QV0Bz+oS2mVhNAnUynWUKJA15mF5Q/oGULYuiR/ITnnJXgBczMJCYFcp7kmHWEYCZ23ii6lQOAMu347j0xHqJ2bQypSgHAkwithsYxVv2WOys1QDQbAxFWyNQf9s7aYL34a74UiTZPaYuhZN/JbMhyuu/+MxO7zlMIAd2/EEegYV626UM9g1BFXUGYrexPP4WpIw+gvpoGfksb/zZx1D/kjWba+aQp/jneq7ttp3K4+dwX6/8N2d27lBO3+gQBIQALJOgIkHgB/bU3qHWwsjlVVP6hVULCvNXlXGu3H/xof8/v/eugIXKs2uyP6ev1PcrEx5ht/IpmxwcdsPq2kVCBykxBTUUzLjk3AAAAAA//pyBN1SAAgCIRlXuedDhEJEqxc+J1CImGNgZ5jtEQwZbNzyieoAIATt2GJ4wpaCgGGpEDudqZwl0LLxUvAR1TgPJ5gUtO+8aV73jAXsuVnPyVmu5AkcgUgFaX3hxaMDHi9Sn+957FGJy8BgAdtgJJ5Goj9gyR/tlKZOBHDQVhIwkFyGkHolXHC4RUZ8afi877f/OqYxQCsMPTCL5I6UgiNWXeKIKRth2Va2/UATLthl88FsVaHkzQ7q9zulh9zQcPzk87+ITaC8JcX46m6vKg6cMOBxXzhRYX8UWkkiBA0EDLnAGTZA+4PLpa9/JbvSxwCgC7vwMWbJTXV58kWeEdvvQvxEbov4SnOLEI6EUeMhGjPn14KXTDCG/8gTRzw9vvz691jGGYZEBE5BYQOYJ++1ZQ2mIKaigAD/+nAE/0MACJH5GNi55hNEQ4XbNz0iPohMmWlHpEfRDBlsnPWVowCAAS7YZ2tlTHYSxpYk7AwtsAnol9PnNR3/GJ5RgHRM0B2BFbJ6KJclxD9qqOtgAnsVA4JcwBJHrX5bv0fap4BgCrvwPCXkJPPRzEmDJsnjAZDntrONuTvDmTqFrNYndBX+r0NXaQav/QpKCFMzvpSvxTsaVHA1DQBaNB8tU0K01VxhEAE7b8fTanrEAXTOcxtIwDwGEKJv1D0keGD/rE1H8Kv0Lz90kLq0F/9ZqKQGIAzpVSGoZUfuTt6TWkltbd6CnxUWQADM4fjdfC6BLi5F/7qlyjSjbI3mvLqKj+pqkAT6Fq0B3pq9zr2oXb/l46n0vZiat2M4RHk4SgzV5ia/3VIZ+t/9O0xBTUUzLjk3AAAA//pyBCuJAAyCASLXGecthD9DmxM9YmiJFMdebD1FERgZLOjzibIABy2jTqgcLwJEDYRZzWklb2MZOFTj4c/i2Wo+6z6Xygc+N5aSYQl6j2VeMBV00f/43W5Nnm9E007UuQ+79H/1AATbgZmGWW1GD6A2UIdp/i4UaGwdrhK5NNIcyYLqjwXyKdYC2fV7gHTj/uVCRemTAjzm9hWmlbytYrF2P4slYAUu4Gr0cUlQkLTOWRAaLKSclQJlZniaY6YLg/UrF4PDiheyE8vQa1KtOC3oUzjpG/+UfSr/Vd1d/+TgAWpags49ejUqXaomHxgALv348Usz3PowyoMlXXhX0fpTRcMO51GdQ1QvGheJLTeW/Efo8GGqn+Cf5jWzzM90VRavtjb/mszFpmzHCxUgaHL+ZYxMQU1FAAD/+nAERpwACYIRM9k55itEQCOq02GFWoh8x2TnlG/ZEIqsHPEaCoAAFT/gSbkKzmKax0HBuOv2UxSvp/9712UHf65II5NbGfH9kGhItRjTilX/7aVf71RXdpt53pIw5A5kTRJpbMW6NgALtoFyysCnkUBRtYsLFKC2mgSjhMG0SQR90rdi+xTPpgR0WG8gkgYzYG/ARZ0SonT7KC+t0s6hcCwj3GXEP/rYCTbOdjLhAPzehinuzL1UWhe1hSIoyo8iBtHiYrCA9zPVMY0oK+jVHf/N3ZU21zM4yS2fm4q/2ELZJimB7HPe7vutbZAAbvwMbRCOG0TAfY6CS2R8e8IJvC+XqJVSxY6Axl9l2AQzV/yNCGyCzyfFXiESTmoAvF1izA6Knkx7A2ScmSBk1cmI0xBTUUzLjk3A//pyBMa9AAyB9TrYmecTdEIGOwM9gnaINHNgbCStERYWLFz0naIIp78Dzwy4TE3HpkNuqoXPQ1uSCLqc16F6Og6RQDDGJvlsnUxH+odv/r/+j5b3U/NKCFMVc+77NUcq1KvqrMAgTbgecbAtxim8JChh5taHOMYmBCNbIZ/J/2Lt7J7W1MYaIoAwugLRrHPVHxv/001X0k7r9jYpCeic0yQNAVmxLUBFTbgb7i3e6SLW276zqklgrjPozYDEd6Q74Hq20t7FcmPKI8aC1WowMW96iv1PKTWVrDpjFk23U5ZIxIcMT8uXUgQJF/4GYxZEogneTF+Q7ppyiDKL/qAQ+Qo243c7rLXFGrCyQ2L5vawQNSSov/zCbbJR+k5WQvKABQhORdbEqGTpB3Nm/FExBTUUzLjk3AAAAAD/+nAEUVoADVIRGNmZihMUQkWLFz0ndohAZWhnmOtREROsDPSdogQr/+N7St4DB3EtZpsh1K/ywdaMKkGRkBVACQYyE76cXvDf7lR6aTSh4viwliMWY44SLI1POJQlp08dfSssYsax18AASb/wJYTEkEepV2c8SAr2WrsWzxjiyhU757fBLE0yTEhZI4vkfwjZvnf/KLoWn/roxZo8cNFwdVI0m3U0Uxu1E2EjvrCdeBtJxVoCqw1LUthZ3xPPCmU7d4Vze7Ppo8qERZZFb/iFNlzyKyuxIFEgKuESzQaLFqtJStprW85xZBgsvcCVczIslharh8tiMXbE9HZRJehHPYO58gnKSmpkIs6hapfT8KF5/Rdv7HH6Hqg5rUFCjhOH0Aq6YQqxETjmJPvdgIAqWmIKaimZccm4//pyBGmBAASCIx1XGwkrtEFDaxc9hyiIfLllR6TqUQQMq8z1nZIEGbYDVnBS6MgkpfxwkzYk+rYZcvp+PlanEoju8KOSFiiWB8ZFtrVXeo7V1UMbTKP/JQzfkiTBg8qtyLgnb6NxXUL1rWAwJC/8DxT5U5arouEosvE0q2fB6N6GoLRmjFSFHjUMtLIr5XR1hc1zXL3/FopPSqiK0xATKnVMFGiohdOTfrazdAAGpf+A1UqbUEEZLcfj+6CbnAud6glxtjlBhcqFWj9BKdQubY2qIvxOLmVv9C+Upb+6PtLlkpDRFa1qeiZuue8ohKaQCZtsMRS6vyKjG4iid6NtJPQN4YNHL8WOzj1QZQugkhzWvq/dXKl3h9Zz6Yh+VfYpJ0MQ8yuy1rZfS4Js7dnbqrTEFNRTMuOTcAD/+nAE0q0AAAIUFNi5jzjAQcMrvRgih4hQY3NEjO5xGAzsDJOJ0IABmbS3Y++Eb4CoWI4CTtqcYXFUIVKE8doOOgcmVCrxCXd8rVINW84v7N6uHy7xBR4YUCAIOxAGMQO//qBD//ygIOYIAEZBRciThV89bt0vD80dSYR+OVuvqTvPl0G0HfQKOYmcRLvD6gwp3KHAQBAMagQdUc/8piAEAxiB1nEHlBgIBhQAqS1EQS/tkkAWZia7KWrHsSP8TkHhbzS8sMqN80npwniqgwwedSz4ry2e/PV3P1pUeTLaAMedr91WszLKKTw+iIgFYlJaeBwG2DqIQi6wpEDy5Pik8K5MkUFp10cPCOgp6/wYHz8edTf4q7LYdj78KxVTn60ix5MtoAwVcHa+11XdLSk8PoiJMQU1FAAA//pyBFaQAAgB+RlY0eJLEEHl270FIg+IwHFQbL2tQRKgbNyXlUIAADBkvrx87iJ+UB7HypUdCR6+7PcyzHHx9Ioae/2qnwceoubgol7vemUdSW/donstiVy/QeniPTOin93//8iQSANCyS5E5bSVdHYs/Z/D6ANCTNIH7I4N9Q8FQz/9Dft/++jLo/5vUTnfAUsp/eVUz9EO0Y36zpYsVcHFB29YaiIACa4COzGhGIzszrTFRTTFiXRVWfpYizBQp7HVXqqa9XOdytYGp2dlolgfSMRSsd63D+ZXw8lGi2c/DtiPXraWf11u+MPKAYCldvxcizw4UlAMTYYwUDNIL5nsOR0tKLuMoLD6r+ERF96H/+j6Hl/0p0Xu8zfUuUrGp61KgeWIMFYljyKpXE111JVKYgpqKZlxybj/+nAE6y8ACAIaPdiYLxBUQkgbNyWiUIgMeWVBMKGRFyCs6JGVogQrt8DTEdL4DY7W0I6VerL4tsK2+YZRnBOCB5xlCPU2uhv0f/5P/7JS+hmuz+2zE3d8vU7OCuErxMJwIJBgGHWe9sXAUAlfvxeSDgcLMKI5TeoKJrgGC0pdGiR3BUd9u2Yj11f/6Po90vqU27LCKJI8yK1rfnelu7OSmCGIXDthFrfse1qyABcuu4jYWvAGEQtJWl6ZsTwieXsZKIq2SMEXqym1+hgDF9SXdBnwd2n31rYPWRYG+t1zPY5SqaOeSx7NgQvYKIIDICXtvxzKaIyRsQLxpnkQsaB8qNo8JZxRRz3ffVtC9tv/ZVzE1W3vToPH6N9PopNrdnYQkqPBd5whAQHYZcfI1qbQVHpiCmooAAAA//pwBOwRAAgB/zhZuek5RD+G+yck4lSI/OdgdPOAEREMrSqSgAaAgSd23GNQUrkTsQHMs1ZpAEMo9nsiVd0lDXo05vvlQm6tKt/83pVtv1voht3X9JRuVhRm50r6/GuJiqy7iVkvAYEO7bhI8VAJEQtsgNNlqoIVKVCPdATIkEoq+Zql16v877f6m0Wm39d0mpez9mR+IUVO/DSbtVDnvpXW4VS5YRN22Ej9jQtgHiU0RCobg/kO5D/Ag46eg8TUuROlCBdTi05ppOitUJG11b/7t6m7bdDk2k7sya7TVo5eha62mnOpkt+L7r2kIABlBSdkgOTm95QnivvVmIw5CRKiAwI+lEPxYw9urx9fHz8h0KLGTiPTSV8ucGCZRxz21HlCgqtzGgGqrUXa1qFL72aUxBTUUAAAAP/6cgQtvQAAAgZLW4YwoABDLKuiwxQACOTlatxjgAEYFy53kCAAbExkTNKi+qthRFEuLm6tMYkjd3c8itk5/bp6Vf/+qozt/8nhZwmIE/9JPoYMExQim///+OHoABhD//8oJ1jCkFAwwQQw7JYY+SpWNzWAnFyajWTX////o6v//URGM7f/bxpwmQn/7fQw4TFCKb///4IPjhwcYdY/////4oonVhhCKxQ5AW1ABfYC2CwCiZ9ZyBHySaP91JG9DVCpdB5vpo/700f/62qb9R1OpS87t0QmOmnKRoXFWZJwieMWY77KV9nTEVDjwmSo9cogAVlkOVpBN9w9lrYzUkkFJVzGHbe/ou6GbX6GTYszpo//1tUv1Cp1BJLUaTtxFnJOETxizHfZIlbRVk80OxFQ48JkqPXKTEFN//pwBN77AAgCEEDYEekR8EQIC0olZUIIcQFlRIh3YRYgLVxjlcKkgazhsL8yicnzkT7qx8NBLVRb9Bt29M/v222ZuF0gg1X05////69vpXqJbL36Ohtnob/qbBdHU9z5aIuhVC6NjugAIEAraVJblRZsZ16OXFuGdBXCL1dR/o1Ho2mj8r9Ppp9/XtN9epeXv0dDbPQ3/KagwXewxng6hOeUe7mTJ2E6ivErrBkKJ6MmvBEKYCgnbIY0noHmPJf9FnjSb//b0qIH6w1f1Ff3/+9aqzUX9/mTf/UvQ3/nVqzBD09rc9V/u5FosRLWT1DAWgqVuWvlAtECWo5fySsxOgQPVlRdEJR/rpxH8wvVF/ZTWytQnt+id3/qXobdfSpVKkIf0KDqVJepCUjlzWIkQaSLVPUNTEFNRf/6cgRagAAAAh5e21AoEFRDyAt6JKd/iDxjYOYM7oEKoG4oNJVGAAFkIyyy2oFsJkcSdRRD1FYPKcGOqVfNUrf8R+o/r+7fbT8i+jozJ7Is4RJTnKYF96f7e/+9yX/ZlvVf+r6VnrUdqK1ASgBMbRT7oGtLKUp5fjBP3lsDDtlboMIyP82nEm+Jgzssn3/sqH9anPoE5M6pjo37z0V0YrT/yhj8w/eR+/021tV5yAAM1q12RMhh5LMLkFo7bqWrfUseE90o8nRKaRqunR4oCsrNoH2U+X6Gi5VQT8NU38sKw40Xfsqe303Cnr5mETNlcAAslKFlJwaidwiC8vRpBYuNoQqs+geKyPfvpwF/Ggjdv//fTonYPTZX/p1FqVf8hODDk0XLMBaAlX9yZ7XRU5TLaExBTUUzLjk3//pwBJ+WAACCEkBdUEEWvEFG+wowxWYH3HNmYwROUQycrJyQiZqBAtjVIi3Eq7lMg10rmAXcXue6pii0xRJxTqLegr95a+c+OkYl8/3/+JZBl/dW8K0+QOUNY0GTqG0DzarBujQGloqAACAE6yXaDV478GqY9LdD+7iYJdtL0MW1V3NbWAxW0Xr+JfoWm9X/3t/6eq/9Fp1GOeP7phFPSiL+y3fscvsf0MCbjck9iyGmLMJWML0RnYfrZaJQdoJlM22udGqjQn96xaJ+MxYVEHWC8VU997Rzzaa8KOMGDu+wf7Oqq83YssgFttySm7FmUJsSgdNKGFAANhxbZyJxWtFbN1qQz/JT//9H/QT4Qiz/0u+Vajol7gzHsF3SbBMhNOoXToVaas1r3Cj0xBTUUzLjk3AAAAAAAP/6cgRExQAIAhtAWVApEFRDCBuaBMIbiJlxZOSMrJEXG++0UQ9WAACABORyS2QTkijIB4Kpa9uUUxBe50ZdDkmGZ2/1F9KEf/1J7US7b5iE1dmqv+v9/pYzqignl4Y0HqshlXYojZo1vUAAdRKkZblx4ZcqZX2wnUUMmzKSjqY9aN174VvoJo9Pq7NRaXN+YnQBrX/l9qv/o5yFBoS+OMUDn91kCNUrUMe8PW1EBSjctuUEVnc4WmEl+yp0b5yyMmh8aww7V/UE/R//+mzX/UrccqfX67Iu1/tkeEj70M3mkfIqbVtShmTv+Zv41iRR6skyAAbaU3bJLlNSi2vhZjOI4uOlMVvrXZtNXwr+L/9081p3/W+g/+97YGvgnKhZ9yVXiVKuBZ8UWMnggOeWtYt8obWgVTpQmIKa//pwBD/NAAAB9i5YuSUTZEOIK90NJXOIgQNvQIyh8RYxrrRwi14AILkbklwB4Z+FionsMKOGEOGb5Ywct0rLGB3XqyjAFFd9DOtPq/10/z+g7FvVUrOiPQGXMLHqiFEKxT//X6WgCRLUo9W7NSYH2w7Pqlz2NzrGxgd6q65Wqur4X/DyKys29/+pv7e/833eltLfkYY9he4YGlh1R5v603L4dRQESo16ggD2KUkTdoFjNFGgm5s4YYzATljGTVsrnFX+rUFvzN/1f121V+oRTleSYro33TnaP/VFvYY76vfYvd9MZmLiTidqS4XQIAEaZblbk0tSOq5OblS7qG8avWUIpz2f9X1fEz/a1//rCH8/r8lygFM3nXuia0HbRC+p6/19ea+/6pR91MVB7yLo/EIhMQU1FAAAAP/6cgTyrAAAAh9M3NBlE6xAKBtaJOVxiKDlaUMEVvELoGtM9JWaQQJNN2xy3LEluSY8OjFH09NHCwrxUKNo/bR/mG/X9d07uv/YSiV7alldcrKn7OZ6IZVvm7PtZ2N4J7D4q5YHATPu2dUgCohSRpuJHoinlJE7XN08Qt5kMQej9Tk9Xq/I4oOAj9BEn/29+qf1+Xfr3jWtJKyr7VqQsXVZoXd+l6F+O+7pQAGQoyNOBuL1UC4BXOP0QF9FLuLzvIF+3cTvN1kt5Zj/EkbP9SORXJr4IztQ3Yr2/JpZhPChlJUVclnRGPY2oSBtB4eVALjcgk25luZiZE8OcflTQa4AuhFYbT/FbvA8kLx3EziElTvX2oI/mDNv9GbNfM/1N6olV/xj76ilO13rmH3J783t2piCmopmXHJu//pwBM+hAAgCFjhaUekpLEIqDA0gJaOIVQFpTBhDUQsgLamDFGYAAcAjI04IhIxD0QoUehaUUHYThCdpwBF9k0qV91EWr/An52s6/vJqdWmL6Tn8vtv9PHstGx8S9zd50ARJZiYDHSZsAEIS6N3/XcZZ8S6dZtceKRjQdfZXOj5S0Y+uOsAw/4wbv/XbJZuvyNxjpr/slI6orL6S1SMH/b/TVzGP3fjDRGwwQAKn23ElFYlklYgEF6OHsFvJpGUl5uqaVR6VX/ggr/6f4xxB2U8ZlMr+FFeQ970aibstVKorbt3qDdu36xR7cxvSkABpgFJJIKEdOXeZMFCyRhHh9cpCNPcIPM8x0qUlWn/thFPqb/9PtX/P0Kx07lmlRxGpBr1z866Yg9N+0UShti43ehMQU1FMy45NwP/6cgQ2VAAIwg85WRsJKMRBhrrjZeIKiLUBYuYwQ1kXGuoNhYmgCL124lhwGzF2jliI2fTEyWlAalH4jyJJai0qLvvroDfo3/nu9H6P+n3fR962lvIhFGbbSQT/ig0i8g1IlDZMkotcAXZLRAh5LgdTQO4ex1Jwh8FOTQjASqih7ATYqzI6CSMDZD/2wT/Iu/9kKZDuait+hPbWf/B5Fbn6luDPflPS+wDECT1v4PiAB5mRoCxOfaMIffInNrMI85866Jsg776tBoN8jf+8zI7pdB3/Nooan/782yLyU0ZBLzqF9v3wNSs9Ic52Xzu9BB22wU2Q4D1kM28C4GaLChFphiMWpF/oiYMhpog+3OtgnuhdRY3oQyxQWNR9G4j9//p6aJ66CWzBEeRvu9xepz/ceT9frTEFNRQA//pwBN1DAAiB3xbWmeEThD/lewowooWI4NVi5hxvsRIV7FzCibIIOSXB66I0nnaHDkNGIvIls6tLndiMVywMQrE96wwI2TCW9CnfGst5Ot1PnNz3yC3jvqzAOoLhu9hE+lQAASBFtlwVROHnis5JPYqro0jrj9f88R1Y4bvMeFjpi1F985/qRv/e38n8asSh497KVdNUGgK71XCsRjcTqK5QJJdjcH8XEBWNdx9NLEa8SEm1Zuueys90NHWdj25+nCRvkNW/tK6BWqOpGmRav+/Mx/LIvMGaKB4MNOINxW9k7swX2l0ddzzBO7X8e463o8nboY1UWohm0Yegx7Qsf6PVqPV9B6uFJthCmrf77sjsQyl28SgRhTvpRbu3l3Co5o4hQ8stghF3JmkPapMQU1FMy45NwAAAAP/6cgQVmQAAAiMZWL0lAAxD5rr6phQAiHl3hVgjgBEQnHB3DlAAAKCnG5BCpsIiUA4sEV0FXMS+QvVtw46R1JcUdcVzft/wEgHm0F7eWMKLGFO1OlNKcs5DAgpmeaLMtQRQZNBQwm98oeIgABCCpttgxYjjkwIAlnCizcOjWRZW2Og1auExC2KD9lIP+j4Rftc3/q1d1ZUO2uMO9VJozNSiaDhgs9iJNabUU91ui4AAACAgACAQCAQCCki//UR+3/73////2zD0//x8eEgBASdf/5AqDsUg7MLjRt///j555ZxoMmM6////5MshiGkzXqg0AAAAAYAAoFAoFAoFAooies1c4gaGcNFF+r/xQCAOb/iw5wOnX+xFuT/+quKCAp1r/8ii4mLkTkd/g+aAhqr/8u4YXxAmIKaA//pwBPvhAAwCEBDclzxgAEGjm5LnjAAIrG9gLRhvAQgbcCjDlN4BUqobg/EYXNWMT9hUtnqegqQnMXdQU5LKqsZiUNDwoSNxYrHmFEgq6xUQiKIqioSz1t+6RU/YSKypVsA0to//+ioAVqoYA4FQdaoVzG9TuHqHQWwQNosDCATpZiQobNYZebUo2tmvmuWKet3sIxFrCWetvrMLIqeRyRWVQSkqW0f//1KYuYwUAvu2BuaIjNlC4VLtyyihmeGncXnJ5ZHEkPE9LTNx7EFfmVSspWudLBIlBOKGkoUIYecpoqqGm0uew3K7HOqWS+oROL002knLCj4LuR+lyDITCXXaZiNWlxmgszoj1/XQaDf/ez5f//L+hb8zlCRRT1EsstGS63Oevqioikk5IY/vVYtMQU1FMy45N//6cgRjOgAIgf4ZV5MGG7BBZttaPCd6CMhzYuyUbgEQoGxNkonwAFYDBgGwQHkx2WrwZdYk1SdguxSPGbEQ7DMsEbM27tHzuTjRQlPLKKsExMXpAJatwu8xGCYnPPktioxszt/QSAAAIiX28cIAHEdRtuK85oFwtqXTU1AB5wyYF2IyLsaZMu8J0G8gPL6mG/oct16zl3/Qz3/84anfqKrQv9///7P0hDrsG3C4R1nz7B7TCm4PbKO0ditUZ4CB6lTB5colZ2RDwYgP0zXPDAe1pqQ2e0Joi/Zihl/pq9pR2o/KJ1Pd6b3+rrqD3QA09dsFwjpJd6vZgqIROv23q22KGRBHng0A3rJ3SVr620vo9dAsUb//b1bua3ggMddK/piqey/pqFG+oBv/oo9VXUziNMQU1FMy45Nw//pwBIL5AAgCB0Ba0eET6EKIC1pEJ4kH/CF3RgmC8RQObaTxIe4AACgjLXbhsgHTElqv2Ct97teV+A1WuVdMXlMpmWj+L5EfS+nftjP85e089f907Nf/OTg1qc+rYqz0fs0vWWfdIgBAUXHK3eIqDbYnk002G0Zon9y4BTJc87OxdiuzaaKOE9fNDH//fbb7JfQ5m1/7WYtTb/4679+dYyuUy3ZdEMU3sfj6jbRboajZJ8GeXWGIkhA6xwAWiCzSgCYfMwzMI09txpXX1/K59mlz2lFvazbJsYhlaG5FSwwmTFjAGKS4wQqEXAVqobCjGYpIGZYKkkzEeVlig54u8NJZm8xHVAo7HZbPu+vQEUt/jE2MCERC5gz3koh+vPLp9jVb6Rc7nsy9M9OnaVpTEFNRTMuOTcAAAP/6cgREdAAAAiY43ukjKMxC5ys3YgU3CExPYGwUTgEHm+8ogJ3uAACILicsjboHhBLMnKaJwMAfvd+YRSldb2o96Jn1O63YtW9d0Hu9n30+pJnJ/RxtFVxJ5xdmc1/vXdp+lD1rPxhOGliUAREcbs5UGUUvSa9us3pYmmYpgyHtqjSF7e4grbt6XZ7X1EAU3/vM+71b+3o1l/tXolR9GFHDZzNSLG6f6NrvLa4DYEnbd+M3K9OE1akUaenOX6x7Vp4+FTdrkhkd0M68zPsPKwvIcl8umyh+BKwI0X8UVeP70ixBdDqu1S+ItRF9/XOpkhVkrSkjTlA8GLqoYXmF8tAFqzq3KRY0VWfLCLlch4OYzX9rPSZZv1Z+an/5x1Jdb92LEUK8C8Y/jrYVZXWtg8Ub1piCmopmXHJu//pwBN0KAAiCC0Dayw8QbEDjivNkZ3IIVE1cbJRugRugbF2CifQABBiuSslGuBvaNRnCd7/XL2AHTNbNI7I9KHTghYdSqRj8Xpo767/Trrt/t2r/9PTa33PZ0icUdLAc6t+zu+R68iC7bdsO0i1LE4Fwjl1e0psT+WD6v2DG68wTDmhSOt6yprS/9F3pqFA0MBg1vSLgGcTKukb6sqdHtL2dO77/1//6QlNZvyTNXq8ZZMqNrQi0BY0ko7EI8TTU9RFWGIxDcZQ6+wx5KnLDs2JQRT0tQeCjTZqvEbr0dznke2RQc0dy1///1iLjlevKmXRi9exapXUkmNrnzE+OopOGswq2/lZna/sktELRyIFP6/71Xy/c4yti2M+lvs277frREdQyrUVsUCv9jKaPx1+hMQU1FAAAAP/6cASCegAIAhBMW9HpEGxBA5s5PCh7iEkBZSeMT3EWIG1owJYmAASopNtOQoUsQ7qpbJ+OxsZEGOaMREmO+kpta1qjstvzAN/+lLyMn9S/et//S8r3/MpOiN8jb/sZcHD0kWqcz9PqABAYbprCEl6a7Oobxl3fF/ChlW4y202mKY7IjX1aAZN9MDiCD0r0FLlbQWwh34PlBBVqWqeyuTLdfgB6P+9z6JcBhqmwggvquXeKKJTz69T8AQaRbnnPVY6oG/7LxT09/lgQEZ3/9GRrH/6X7EWv/RVSd1J+duVQY3fppXhqWWdsEoBANCopRtNgQAzdertkbLaissWGz1HbV0jaARu0E0RjJJ6x+0FADZ6KqXulFzqtvavsNV16dJMbeVv9rlMMKqpMqla39m+tMQU1FMy45Nz/+nIEz1oACIIJJVUbRhOAP+cq02RldwhZBWtFhO8xEaAtKPGJ7gCrHQApGUucBp1xDomWiQ/dyOR5/pcnMAvaFTjuWDWiLQ7hph0sqaS0PRvuYQn19L0DqGiz0qZLM/YfSj2UvdZ1EqWOQCKRMagZ1rCG4lK7kVknGjURmiRiGmkpUxZMrGKcalGpr0kb4QDdJbe1mxROv5t6111+dpTaiiPap2//6gKKUbUgBGJqnaQ8na5neYgs89nlC0czDJGzOaMnyf5AI3Z+6+7bO2n6n+ay7bfXSQ3v5rtVUJl6klj15iIzRLmi2JweSaTTgLkeLZG8krrOnOHncUI7eD752gHr0FSiRXr8PY1F3kMzDp/+1FZv/EJ0Np/3eqC9r91mqsMdudoYhBJpLLtxRKYgpqKZlxybgAAAAP/6cAQvowAIgeAr1zMDE9xDA5qDaSNyCFzfWmfgrBEWoG1o9An2AEC0oDt4rDW76y3ddePW5FvCs/gPTB18GhHo75zrmdKmll25KKT8oYCf/0BTGYU3t0KOShkNdluNf11JAKkewCs95xEKbs0+IPW3NhD1s6fyVNFRsMTMprTmBJK01Dtd1VAEPf+5eYs9G+dDj79AqBQk4h04Kv+1X1VFRT//6Ai5JaAnCHvdccqqGsiaoyBliOYH3vyw7AF0SXK6xtA8VbOvUjfFVVVt+dliLkJGt+i+d2Y1+V9K1GuOcpGG9Hrf/9INJSyOQLC02RJ/l3fzf3gjD1j23vip/h0q4maWvykS3uNlB0VnlVWJnrMLd2ZL9WxDcqr/8IaHKRysv2Q20Iy6F6+pXM6kxBTUUzLjk3AAAAD/+nIEd8UAAAIHLlY7CROUQcgLNzwle4gwr2mnmK8xGY5pzaMV2ABAoySACrGoWaW2m4yp9IcqPzVoa6joUVIb12CuQcq5c2Es5lrotlMz+hn/92Rju7Ns9rKc1rgRVXco6IzqBN8sCMpNtyAgS3Roj+touIdcrvgZI1c4lrwXcmq0yIJfCIEL/9Wd1tp7bdU6N1ukhUUqTNbzGs9Bxlk/uIoVSHGKkplgQCBCUScccgb4s+qLpsaKQp/uZsEx1/BVNsaZ7y0x6jthTvFN9NMT8BQpkZ5vvvW9PJnFq3WeOqW8ZI1rILlnqTUABZvwKhxooMhxYaoUz1KSWsMpIaicdLyt+dkuuB27OIOEW5w2OlDMrLdXZ6OXnbtYM/gw08I7pLF2VQCo+gwAhnUUu7te1MQU1FMy45NwAP/6cASROgAIQhM21rmYEwY95usXMeU3iLjfXTWBADEUG2xOnnAHACCzLcATy0k5aBcwP24U0fpLB8pFcqKZx6MaScLTbbajGNMtll/+qdVZEesjoz+cjsvcrakWIqYcb/Ocpkm3j+jx5AyQo3GHiSD56u0vPTe9PRnBaueGXO9O6IJmR92v+j/CAdb/m53Q7FR/7dTN9GK2y4fHC1KELFj1rpB7nPoAYW+wabP1q19bLc22kf0tipKYNB0JZxCCaCmKFRYIoJ1oREHaYvI9Ng7d0+pzEOquzFNu/ZtSf2+qI7gxhx1C00JQQXaaKTccYWWo7Yc2mJg3eNuSV+ApKCIhhk4yheelj9FcuYVMR7Y+leFAnPrb9rWRdl/KHp0TRr/lXkceGUeGa2RU3gZt/ptdTEFNRTMuOTf/+nIEbjcAAAHjRdyOIKAEP8u8A8KcAAl4339cYQApL5vx64YgB0kkmXQeQln0xgYCoYFxgJ7Vf+r///7+3+x7X9P7Q+oWYmtLf92HhRZTM6mcj1T/4gVJUxF//0ikYoBiPQMBwMBwOBwt3vvZkFUPDf////9Uv/+zHzE//tG6ic4z//yZEXhYax0kZ///igi5zmkSDmDv///+SQw2w5KMeg/gCDRSrTl2SAyaBLEZeHltS+ytdH1axjK21DV7TdWlKQ0peunUq5n/Q3l/o96iS8SwG5fNM3yfG+IU/eucb+Ebj01/4/cadl/6OBf5DU16crSbhV3RiE2lVmEY5Wuj6tmMrehurtM9SlUqsaFE1KVvqVsz/oby/0fqJLxPA3L4oKVYnxmQhT9zfk/+Cu9NfrH7jbZf/nAv8P/6cATE3wAAgfQLWBMmiaBDRdt6YGI/COB9jaQET3EYCarJp4zgARKFzIABfJJOAE2VWOGDJNXJkAR0upooTYgWGgEFiMNDzZooEBTc9Yrba5b1lWCwoEzKXm19J6+hNKLH/p6wAAPa2sUljTaDSnnsQuHaoEbexAYnyY2vCLVXlynXZURCKlGoKMqp+mxtPX8pWxWea7BqIlP1HkFg2msjln9q+39GMBSUk2slsst8Md3NXXbXBQE+hJnKl9HxefxMh9+Vgox6HwafvBlR4KxE+dWNGB5zU+6alSoGnjxV9+SDT+00Bhs0AWXC7ZKgFqzMIQOieNeWVYwZ2UiW3HjZxV06keA+YjJqK/lhqpCvMOHswwI+0WqLJnjyxDwailZajid0/tY9VTGbK3+mHv//p2NrrTEFNRT/+nIE8WAACAIJNdibIRP4QoxbzTRiCYhlA19MBE+hGi4wtGCK5y6607nvH69x6fm6Z+Obqb+mj6m1nC0t14hIXC5ZAZgMiOwLxfrOnmf7r9d3/wYqmvlNv9bmJfUTOuJ7I52hSyPLgoloOVyaNOVwjsgh4Y2qzCQ3tGnUrUPRyXTX2x/2czMjq/+f1J+nqjf/p5+n/8e//S5O1nf69p6qf9G29UYp3r1BoBQUrRbgpU8GyltN8WeWF5S2zUr0RSGx7IrM4CeYwDzNyPUZFG4I+SR5W1+oz/Xrk9v9ujI/21vhHs+uivRf9XXed6w25CbtdtbJeWgeMflMhsV35v+bTTP8V3mG07JAiZrHGRfN7J3/l5r/4Qtuf+jZx3S7fv4Z//9fLSvr19X+czb5IkI99D+i0xBTUUAAAP/6cARHjQAAAg8RVxsskFBCIlqCbwYOCKBzZymkQbEWl21pJBQ2Kc1W2HBRv0DlFIOCWfkeUFcsYB4A9z6b017M1udXIKK9yGEA7T8mZU3QF1wUDhLlXTrNDHy7H3ewcy2sqzIo9nXWBS1CAnG1QDRfWNP8yJnTE4lQwDEmYqPEMHai/bkM5j9luqdo1GLVE6KVocdhaA/o0/QeentREj69edXV/+9//57oEAAorpbYKkJldGhDkcqPkVBbau21C0dVvxnK/1q9bqowxrlo2EnIfg1kSIW8DuEarsUpPpq+96b4sfdXPIOvqXGhy1IiBARtJtIJxYVEvqZR6uFcsF6+l5kUt1U6hbOWlG55Cp3su//2tq36t0EUJfJ1X8sNSQFtGBBwVHF2ZkHedLIFnvcrWhKxCmIKaij/+nIEkIoAAAIVQFlrDxBoQ+ELrTwmA4iZA3OnoEGxD5bw9DCN1gAAEE4ndbbvRj6Y9YjGnaqz1tChtQ1Kb7pfezMjrjZ/3ckiupj67/3y/f6p0GfVf+52pce2ielQb9un3dDtndydblgkJACRyWJSW5WNs3UdNZ/Q3mAUvLDzomaBQoIXEkXGVLe25y03a9P5Zk6m1NgNEwm5gGSoPg7SaMdRO0sjapiZgnVWwAAlBSt2RpyostHWhsj+7lDCgj/fHdQSKd0Z+Mb9iowlkZWO+36ub2pt/VuL39vp9rW+56tBm18djy1r2qfTqDtFj4a6w43Wbtf//dvRmaTdsj5BXnOm30cc36wYsj2KLlsW2MVkh386RmcOcTnl0/oNhUY12YiJR+7W55JfgBTlq51r0Uf593QmIKaigP/6cAQYiAAAAgMrXemDKFxDiBuNNCKJiLkRb0ekQbERKGwZgInuAQBQDkl1rlA1mt0VjuU2BhX92sq1ESPqOzJVVavfMRkJeZaOvu3d/URPLEgdAhtPbMCPU57S79PWgVY7Nzd4TUAgAA41JI3IAxjlaihPrtnFjteyZtQBlKkQJSYfNs5roKCfX9O6eX9fUQnso/oI1l0v+YiqgMYCqET0NFy2URceAdcgAIlyksjkA0Y6NrEi3h7uSagZz7uRGVvUyF6ld2VVuzYN6iG/9OzL0t0Q2rDWdV+qSpeZo/7qIokHXwdSIdLNeHnJqcuwwAMrpsJLyGOWrd3OpZwvd19Ik5az1QYU8opyRwtj0flgh2fJ/1Z/T9nbQOvXTpFvqaqs/oq0wrd0f1f9KHY60MqQ9S4smIKaigD/+nIEbiYAAIIUHdYbARukP8ga9mAie4itQ2VHhE85AqArCYCJ7gnI3AAQEe9cV9eX0m1B0GW4VSVJRLg8cn4nYCde+YTmuQJerYXtkQR1EBICBEwVYsTMk8g+bMpVkgPQNPa6hwJJ+bAGNc0IYjR6mFqxcajQVrd76ktLz3qTZDxpUSOfJj5AYUBXTD/+46ZmkpJ7m+6XW0ujyN2n09rUNBsqnK1W/frBAAIpttOAEYJspGa88BwzuJatnormt6vrUxBKQAFNnTOn3Fa/5rrTqv5ydGXdcnTJp2vbc6UaRlbl/yky0IxU+YKYg/So3IoBPAoUglddsEAOnQ2nznr9HIAMDtKRhsrXJAZ6NI0dQmAKQRBwAWgZivsqNorHfZf39E//f0qSqdUXaH7O+lMQU1FMy45NwAAAAP/6cAQuTQAMghQT1Rs4GGRBaAsqPWINiDj/WGw8Q1EIoGyo9JQ2CTbUgMORghKJ2oHYWp2uGC8JmxagmVCl5DsyF1qeRRYZ84IYJAibFykMCoJqIur2nopwnUeSj8t99YYVYvRuT4u6sAAGk0204AZyNrs8dDqLYrMVgbOcyKh0KM86ItqCZEcj6Xf6jf/8iP/6k8qpl/S6XjVa/tNfCu29zjrYiXLHkRQcE3JLQCdpMpPNMS5UiLuL7T5/ZguAPnPVWstm9T0oIOhXZNUPu2dPf9CVZS7/wQ+85Zuqe6tfx/6raDIXM0qqf7NQVFtxqQAz8azo2qcQW74rMDNPnOw7UcmiM6XHIaamis345v/ZFV5cYS316GMf/41fr+48m1AjWKC15CGDIt8bUhpFMQU1FMy45NwAAAD/+nIEKdQAAIISJ1lR4RPcQOgbOixld4h9A2FHjE85DJzs6PSINgAEbKkkcgJzGgNE8yLjyfVKxm0mk3OCMw1s5oUgMn4iFSKRxHt+uxmPg3LaWdFgmlppTVMakTZYm42JDtXo2SG9uoAEL01JHIAIS7nRcMLdTKl4ZNvSx1oMRrgwoj4o10N/K3xEM1t+q9bs/3qjcyJq36kSkzWt7MjO6BO2Ovp116VVgCAWW5E4AFJDX0a5HpBc2XH3iCvDvjc89iKd6teJwAZMyM50QnqBCXLdvV6LZ3TJ/+X/fyHWgZ1GUj6mrY0LxuidR5EK1JZJICoR0XQKLKlYbLYzB24Zo7ocQ7IwPN0dQbPRnI1EuUpHyVXpbRq3/Bl6FptOmrkCK6IcyDTuIzKw+qrQj17FJiCmopmXHJuAAP/6cATATgAIAf06WFHhE5xAw5rZPEN7iLjfW1WCgDEVlywqmKAGAAAtNuRwBV8z1bZTJxpe6zXyN4YW86pTdASuQsz497aKgc71ZSG/86+C4JkX2FdDJp39R0vR7sNSGjcRz92fQAAAxP9wjxGJVHU7lKHaf1d5fLiMJ5HaMHkVisxMPbQUh1pp/VhZrXNJFWNEdcSbD7bnpeosWc+TUASsXre6Z/3A0C5G2A79Cm3M0sBsAfqt/a35x0mJOaQmQtVvSrq93vXLUJIQcYqjEKxlVXNvrUYzoh1XzP5LVuZr0hw7KYWLBIpSpGqKAAg227I4AuLrP3K4pMlX91GpO2KvIpZXVSpxlwUDcXFzzHehrKc6Nto5yHpZ/26s856+zNSSilovrcKiSTpWfIoYxBNulMQU1FAAAAD/+nIEUm0AAAIMJNvuGKAEQkLrbcMYAMkBX4Z4E4AZGSvwzwJwAwAAAAkHI5Nt9/+BwAAAksAg55PdD9XMDASgJNUU+xZCnOhEPgxDwHVKFehnXuUtHRXZfi0YTWu04cMjgv/4CEB64AAAAIlp2zW///78AABATJ4AcbK2z5GDYu5n5/Qhu3hiW90VV0GbmX0vntcxZbu3WNb7x5v9/S4m7tf/pgz/maVlokEgkEgkEg/37s/////79DDPzOi1MOM/aYw3PsaKyAUGxD/HyY0MY95EdJHiKTjy/8xpjX5gyarHjyGo7//bmGMfv5ERnuC8FkEgkEgkEg/y//////79GM/M6LUw4z/MYbn5orIBQbEP8fJjQxj3kR0keIpOPL/zGmNfmDJqsePIajv/9uYYx+/kRGe4LwVMQf/6cASxdQABAhxb3m8UQAY8Rzu94YgAiJUFZ0QET9EcoK50UYoeJBaQEssjSbisgtQ9b1UVDPzGf3QMZplVuz/+m9Styr+j9/zG83Xr7lXUlHq3qVk2M/u3zPzP/Nzf/0ez1dQsIKe6/8BIVRkszjKTfEKAoYBwzMg/uvarkdVZnM09FRnT/o81Styr+htH/R/T+vmKupKDwV1jP9KSz+env0opKkQAUXUsmYGDqKB3aTuCQmCNOsF5E5GjZjX7CQRrYsOsK1/kJmfu3l6av6Cn5aV9DGetQQq/KzoKy23JfUemmFQiwjgqdUEQiTJZbYgU5Y9hlA67awE2dpn06tVSgUohRm+aStzI5WthW2ZHdNkM6l9y9RPM+/oby/6I71qCHv9xKInsa0iGv9FArTgGpMQU1FAAAAD/+nAE5DwAAAIHLtnRIROsQqgLvQ0CoYh1eVZnzEwBFaBtNGGJ5gBAbUjaJTYgHqwuQxq8+JKg1/rNmjuGVNR2al345G5W+v1d/tVLeT7hyCeoN1LHOsKm5G764s0jk8cn64yFAxTWSgm07rbo25SHqV6IXaEFwMj884ijk2oZHSvLsy632/j2mb2b+1X9/0J77ei+joa6/W+ENt+GcVhZkalY5XyMUina9W2tSWMcBVHA1lS2mW4Ye66vsCqPe9lbyOJ6rda9WX0X2Sras/9T/nXnsa6f5xGjb/TI/at/X+uiW/t7P/7/Zq4tt0mAAEQpFLGiE3Vd0Blopem57DX81y9I9dwoLhZdKudvHKb3H5H3z39LAyfp4IOnbb/cgzo11/8J/RgBC3UbbO9VTAMGbVEUxBTUUAAA//pyBCovAAQCFCfWUZETAD/IC20MwhOItOVg5KhMMRQb7bRgic4AIG1N61biutaBgqWkoMkWe9YukABvm3W1Y1uHdGk/TmNTVG7tsm30aw3bp3cMS9/LIhy53yAqviFThVfa/Ac4BkEAAAgI47K0Eni7Mmx49Xq4FZ0Z+jJc5B2tKx71J3f9Hnd5Cf9GVRP9uhm6/6dH6f0bQCsubERLa1fRkum6K1P7wiokQCjri4tAoWSZ+x5Y6BIu+Vs6GK6ldGQj/SyC3rkd/f627GPQtPIf2ojf6HLqNBfyt7NGgCWkJYsTVcpVNrARofc0MAgFAJxSVspTxBvMpdfZ7aC/MrTItaoDrpVDv0u/qgx3lam/9Hnf85tTgzHzfrR9AK9+kNLMj5fpFL/u7pdLwitphgtTJpiCmooAAAD/+nAEuq0AAAIcE9nRIRucQcvbnSAif4hdA3ehBFpxEBdrdPCJ1AAEvLdaJTuzrtSSY37LFyglzwAtZ2ycOFBD6qXVXgiChkLCjZkcBX4UysCeBolUOfQw3J69b3izynQzSUoMYs6OPySAQC2pI7rGW7znYwiq7bFigHQ+E5qvIDC6BIfTM3Bipev/3MH6t4JVr/z++/2qh3fq3++dv0/6fv6KzWbs6WYa1QkRSKYlru8jkqCgcUdCvRXExeigczHv0Im0Q9v4y+aFTjCmn/9fqZtRS6/9Vv3MnolJaRawkUdL8Ylb9Tnb66ZewnJVgAAAQxVWIuVrT1kq6L+Tw4VitM+A3j705BEKro7KBKZ1t3k7/me3r7ftt+t+Jb8MRJerUhRJHpADKk32C0R3Hq9W9vSmIKaigAAA//pyBCDgAAAB6y5b6GIpvEElu30UI7WJQQVxoKSm8SegbOhgic4gEhByKXRpOxQZla72wwGAbQR2YiH6EfaKP/w19Kipqpebd/75f6txwpp0VtQnS9goe/bT+jZSIjS2KDVVYICIFkktsSdq49Qi8tkpBNaGrbvIHSEqf5KMvkmTknnerTKwzYA5/uPPBDjgAvwzF7/VP/7vxSimQNuJKGhk4b6gUE2nY5tY5LZsYTTFKq4XBQFa6w9RToPrRH2jk/pBatzNWj0MhnX5pr/lN0H8j0bzGfsyD9tx2ptxdDq0IQsGFCt7WbrxYvXXorEPi9yVpNxh1jKIA7GHCRMkwgPmYonNKYIhTYPnrylbWivNQ7dH/8v6p4/6Deij0kyL9kBKZDgxQ9YloQFFnaa2w88fAXsqe5tFSYD/+nAEQdwACAIMOVKbCROgQ0a7TSAihYiJNWVBnEp5GqCtNDEafhG4nILzuMgTPfCGn3ZK1CPOfHrcUXOJ/efKlRmKxv8eu75n2sfR29H9DOv/fT6/6G96VXbXOtlDtH860UH5zo7OsAAghuOWxpyY7dAwTT9xaqT12N3tAczCzZBXtbqpiq60Intt/t2T9H6kb9ekUkjK+uJ1yWqoAJU9wZHgQeoY7+976KUeTtjTggsFBpj3Ox4qAI3ag6K/o5kzN6aqHd2drjqzJo6dOjOmZPRn4lUrr6rS9mUmvLd7KGMqN/qzW1zOFb6n36sFJQAAUG47dYpBX2osY8kpsIAPuE9S2ZqhWdMI9FJ2nY/gZUPiOjmdEpYxpC/Rk5DEcKjTfE60r/eefMsJHacaczBVYJ/JGVR6Ygpo//pyBMQ4AACCDEFa6WEVzEFoKwow4nuIYQVZJLxMMRSga2jDCT4ElJFSOTSOQcKUf2njaaZpkgDtV7ti9RVVfMos4a2vgXyAqJS3+Opn6mDmLiPP9C6CGjL91JuDUZTsK4lLV29BvpAABdu1spjTyXfC0uINprkp7GffrvUt7Dh7td+2hw+FmV0lQ42jr32T2b/oK8GciUb+Z9T1Gm9Z96j0/vLOP5VPJggAUf80TKrCQalEWF6y+yfEad7qWGSjG60SjiaoJKRqOetrF6t91c9SvRE/ZW1KqPLk9U6O09vunK4jXvjmlfFVEdAVlqNFMSS8eiUhNZdGucIuQvcmHzyB5U3/UT2RReryp4n8KjP/nW2clOnlCeCJorU6SNqlS28nbUUpPpLgUM1vOuGy8khMQU1FMy45NwD/+nAEtgsAAIIMQVloxRR8QcgauTDCTYjE5WNElE8xDSBsdGEWtgCAyGopLI5BynRRdpnydxRYAzXY3bUdZZ2dIwULur20TerO/07U9Hn/hQ/2dzE623XpqO/oWZj2Diddi7adlmlhIAAJ1+mhDHKxYfDQShiV9MJOIHiphojJti9l8rTbrXZ/0RFI9J1b/9PR5v9W1aVkt/P4llp92d3TFodfVqJV8dFrAAkrMmskgpCnT/3qbC8XUAXMsZ1Z7rZFSlAVmUn795wECVysNRD1abcjw7Kvu1cOa5n3RysrHwwBBkKXnQ0YLncj6P5xcqA3VXZHIObDrAjUczJ3sJ1+956sDTLxd7BKhHKp3IT29QomTX197pu/4ME2oVyJf/AVrswyfIyLaCjy6UHnyDqfvctaYgpqKAAA//pyBBu7AAECEDnYUWMr3EClavoZBVOIaRFdQyysMRWaq+iRleYEFL1LZHIIPGLTR2xPf52w26Krj6HtlFThYly5rEtp6HqUFau99/0Wzf06gM5lRf7KZNKiqBqlMJhsvJPY5Ola9A4QEG05q04OFOVlgsiqTXaYDk9tkV0RyIinYotabmztbY4KRMtnMV6Fd1I7xJm8bi1TvfcQTqe5j2W96Tboh0EoqACjSjt400cbNBkJOdhREI0vcm1mXQpZtDFVxRUbP+PF31dOjo94iyMMJXeIA3Ut1TdqZxZUyFmR31KonIjipp+P7yIAAfqOyOQULWy2Nqtr/bgcmB/xjTVwpO/GqsnBwsRG/k/QML9uv9KPT1TzorKTe24kwCBYONoSQPER9JhGZNrpZQbbSLpTEFNRTMuOTcD/+nAEwb0AAAICNdQ1PKAMP8XbCqQgAYkw4XG4wRIRI54utxIiQgBhfUEc23i2XqI7enFGi47GXQU9C3I5zysVG2QqsV5/7Kpvzpd1f0d2PrYqP+Z/Ouq12tAplLLHQOkDGBdRtHrABDty21wCz3dg5OEdVS1sUCRpMnSePSOFMrpqiUi2Z2EAM3f6Mr/1/7f33rF3//RtepzvLK0EFiOsxqRESIzoAABAACaqcd31td0AoEMGHi1mM9sU9gblcXQ4lGsLMY9EZ3fVsi9umW0QkJNK6l3V36ayek/7/v9XDHQ2bE5+n/482XAaP//cnoAAAABLbslc392m1AoFcgmU9CbJVXz6P3p6W2IxwwsyH3GLk9+o88piaqpyUVjOW/tVk1lrb39d57Ob9yiz4AT/95tP//0HE8QA//pyBDjIAAxCGQhclyRgAEMoC4XkiAAIpOFyZ4xLAQ6b7szBiOwCQWq52Iw2Ro0ZJi4rJ5uxOfqOA+fxOH9aYYP2i15wwUeMKN1H4kPDKcofFGiMVx5xAsLss4VrtbQluK7N4rSqlwiJQAGWk5rhcNk5GTihxGKxW3n9lOfyEnOc/qc/v37H+qXft3fkX9DtqINZF3+Q9EB0Oi+6kuyghdjWVwrX9Lf9+lVNRIApJSTUcNQdqpVT+NBjSvRNxzdgJoaqVZqpVL38vNM9VbKUqlK1V/Kq7m66P5ev/dNBURCJ9Zg6LCoSjTsFXKDv/Z/DUkCmSEpz4ABdPVS+MK1CibsZxmZqpKZ9Sl/qXm8pW6spS6lL+VWob8xvXr/3TQUo8mgSgqVFJGJcNRE//V0ptAp0q4tpTEFNRQD/+nAEMHAACsIlCdezKzGAQwga4mmCOAhgf1QNYGGBAqBrCaYIoAEAANCg5s1k/sGx9BEuKoG0ESCihYpM/QsaeIYqETqQ4LAmsmKhalkPhghMFRYNzovGoXfsdeVknNe9xpKmRr6Bdz/vSDU/ormjak5lo74ioJV9wD3LUSnjsQfU2/HpjmZyyo5bU0rMuu3TzM32qW337VK3FfQ38upWr/5pg1vO78qrvuusX0GA2nRenQ46pV7dkwou+HM5my80kTxwzYUqpfKH3YCFLQFS6vaqwMa//qTA1PBIOkYdGEioNWAGVDTS0OoBR+9Y/99K21+FJ5uVIGIl9mrwUGS4atxLEuVCdAtMZj3RW20TVS6l/K15aOsMrapo/6/b9Ry9/pr1frT+2GIP+Ku/Zt//5BMQU1FAAAAA//pyBKGuAAwCAzXUk08QYEHoGxpgwgkIsQFSTbBDQSCgLTWAiHxKQqMEtPlqFdCfnEWJ4yrl+5bucfBf3mW5EiYNUwyW1vr9npsZ/Sr6v/r/XyUs//DFojtZVE41lFu8Z7HXev7jAAQFt3NFyognaQSkGJSGPZzGBQ6PvoWXowzfV750b3ftSPZrfb1b/6kft/r5Ov9bYIZOutLoAq2MtU7W9blQCQvlZZSowouOeNRoJiweDImIDMRw2SkISwsowcquOiTEK9yu+ivOv2ad2O3Uy769PsJ/unQqNT/Y3V//fwblkenGPYzeLf/XqAADIm0++il60AkMhtBGRozGaqzaoTZG1Y32YlmYk9lOr27GNK9q6nyKon+3Vbb/6voIbb/8K5l+0jvPalJxRlLVvKCIoTrjEJiCmor/+nAEpk4AAAIOK1jrCRBoQ4CL/SQjEYigaYGkDEXxFAirtZGY7AAACFU4tGI6VcIwk2pgen5blygwO5Z8o5D7vtI2hSXT/3VlSpQ3p9nYs38EfpHBjyz72d9os97W17fqR69FLNNWaCbUcusl0jkwec1jBB2AgFEhJYHARp0iF8roM0YoIhLM96Entb4IC7+tR5SE055pa2EGUCd6Wp1MRpz6EuF0iUSvuUODSlav1u1rkwYpK1fONUcxfkvFXpO5MCs9ddKJszhT5VcHUHRasTgM4EtLJBICO+7I6BjXCCyzNabUa/zBiwgKIJPKOPNAAAAKsUjAUpJwprJrF+t8uF3pPFUR8LS0u0Kz6PfQPdFgw9pktr7g6A1u15f8s60n13Co9zL0xjXSbe3KIsMTdKV7hIeTEFNA//pyBOSnAAyB+kDVE0ET+ELF2v1lAg0IrQFMTbxBgRoT6p2kiDQHQGIfgcAiErnGYOnA8s+zypEK7KMdIhnMJEXRAU8yS8yyNAK4W9QV4fX5TdCon/5FKp7pf/fCdL93V69f+6RAAAASqjsZcpLk0AwSHyoULSoW6IqkIu62DtoC9SFdEqhn5NyK1GPrq+tnSZvyu+opPw3LLr9jkJ6i+gd56R206u7oEoLwTcAKZJitF7C+JYNdGJJD7tiiaA0WSKUPFuVmalAA6CtjFUn08t15jr0e/Vpcv7/FP+319dV/c1cE/T2SP6d2R3yVIQi0CVBHiCJCr0jLAIwJJJstYR1OCsyMzNecWh6PW5fk7SvVJGZN1LdVSWYR01u1uhYyUGwox1K4bJfHLZ94u5FFA6y5rTKYgpqKAAD/+nAE61EADYITOdKTRhOQQ6grHTwiSwgs4UhVsQABC5qsKqIgBgKWgzMIbwKrP6uhiYWBMmeF93WsP8vuVCxOL3OJBjHymRxNwSbfZelG3rsu9Sotv6X/I/UrbIyv+nPQVyiEXfdf/SAAABHZd7LtxHgQCex4Pc4XZI4M1aLVwKDm0WSmzOzUqZ6sVH/fanr+VPG9HV+sDS5A2VG/Z2PQfHMutdo6kWzv6UqqEo0ONN2CwUeKHJerLKoNDD9w84k1GHcaKWQmpMQINBFeaaoh2XLLaff0VtErf7+dte/obyua//feDk+06xX9Pb1BcUoiSkAmgxEMPOxmfMakaM24ieKHDtKzTSfdm/2R1c9ncBKp2IjaJt/0fo6fmtRwQTSdCwF7GCj9+7Y8NdAF1//7UxBTUUzLjk3A//pwBPNrAAACIh9ebhxgBEPCq33HiACIqXdtuNEAERUu8LcKIgIAEgkyWzbaj//bb7/gAEGEmDT1vajJR7x1q4S96qa6kMTIazv/+blKKINigsoInGAvaI6A4+ePSS+ODKExbBy+wAN8+kAEglJKNyW22622yUAAhkQ6cDXtXV8Y/p64Z3d7QrHJW9qWrDiQHTIcPBkVEwUIRjzsElm8XFFrJOOEmofjGnNPZ5fvAAAACSbcQEAgZDRjAgGZEGpYzprm163uu6FtKahqVO92//tRv/nmc7f6nJ6f/kIff2VX+/9XZTsfQvl/////upkO5qLgwAAgEIHaNp+OJBLNwOAph1ftvq23tTX895rN1vo11b+8xzk/7k9L/+Qh1n9lv9/54xxYwt3IAtZyqzub////dTIdzKi4MP/6cgTcmQAAghcIV29gYAhD5vpi7QgACEivRy1gQYD/imuk8xQ2AABIbku0Jboik6UquU8oifL3e6+pyWGVEU3DBEHDhBahRSanSKRLntKBh7Q6R6cZvDq8seOpRowC6V5bV+9qlBV33LUFRiNSA5CNk0Ps/f5toj2UQPNQBLHjjMOUBq51aXQ6NbRtM1l6305f/pbf8rdH/v9PFAY+SwaXPOpdKhqt1dmz6V5YAAAgvrA5ZAXGqvWulUSSCx2nSnsH3ZuPyxG+huhCAThjNK9EcOfTj06TdjuVdSp639Waf+Gd88kjZW6Sv6lKEv0KBurpsCaNQmsOYkOX5l6czZzK6HulRBwsrNmUejRFVSTWaZW4OcvUF3M4uGHkkir5c6WgzbcS3h0Sw4K4DklGVJiCmopmXHJuAAAA//pwBOIzAAASCjnUsyET/EMICx08Yg2IsPNfR6CgcREa6+jBiT4AZUqoMVrAwqMSF/2W0c/zmGpTTuVR+TNEQTEDjiOQwMbCo5HjFRF4c5Vwpqa66t4BS77SpUvUIyjJ17bl+7UvQkAAAhONytpwAhUN3YNkPmdcjhLG6I4ZZgocp2pL9Gdk1LKhbHC5ybWartV/sHN4JUzf4Xqtmv6dsMw/96FsIh3MJUVABCtuRtNgWwm1k2B8HFpVdIY1LWIi0KaLhCV6oz3aUo8QJZHOrOqJy3m5nlkb9EflIl/+r5Wat/HpUFQ6mBqmv07rzju0ERP1JGAwjpP6Oq23QlgwmGcDmRkUJjpgnX2TJpmoYr7vDkry2L3rdLaT+F9FRaN+8O0SKdoSRWYU9XgIy+QY6BDwxZJMQU1FAP/6cgQzLQAAAgQrWWkBE6xCKBqZPYINiKTjXVSRADEiICuqmDAGAIKabjlrbkALmns0WPTplFg6DPU2qOtEwaurq7nzjTspzkU3R0en+nRvwT9qqU4VWSLCY6gJxcSzRINbkJW7/oAAAZroUAzIYNC1WVWSvShrel7iErR6TtsGc0Idn3BEd3ZE0StyTG0ZarXdiJNBH/UU3IpVOu3/iaUb9X4lk/tt+KABBe2422wiFDDoA4RQd4q2nYaroh56SKzIo4grpsiF3ujyGdDomr2Ru1qWVn/PTkREa30gLVKkMdKTIlVOCtVDaCrF9iQAQrbdjbYEw2XVtDKuLGd2Hmb/kFreZFmaBcj+GcvMkX9OnBCHgNtc4uUNVLFsX/wv8Yr7dXKMSGcDLUNt/+ox8FXMP79dvKqTEFNA//pwBHVLAAACEB9c7jRgBELBC03DDACI1D97/IEAIQwH73+MUAAABMAOGU2L9/z4/oBAIoqWq66kAsE7W7kRy8K+Tp3L8zTyz3VjZC0oi58WabcOnT7lIRnKQzrLHdIfd//QT///f5MAAAkFBwWmxbO0WgAgEIRDSBoX/NeX0xrnjkCp9AfIlBGbAinoS4o4IjkrCrFh8yBM/WjOHKfW3Sf//uQTD9v//f5MyMwpFQhL0QBMiqiX0TbCcecf27uB8K/GNllEa3yaHJDbV1W6orxDUDurmViRTR9YKKUSVX3CsZVuFO+Wc47BckFBZRpBYeZEYQamJKeRKStes7NkfIA11Td3Q/GvRAw2WMh2uoyVcLBtq+3VFeIagd/MxIpr6wUUokqvuFYyrcKd9O2NJBQWvlnpiCmooP/6cgRptgAAAgwcW2hoUbBBw4vNIKZqiEEDb0QcT1EEoG6oMonqAAEDAANcJkpjFyvADtcAXMso3jzi9swFHElb+VTi59dSFk7RFcGlHvln5XI50RcVtFXKvzB3o3Feexh4OqcJUEaySRC0AlW0nI0TB7dRphkeyOD0N40foGIZVmc/G/FLryZ8NNf2SGxT/ln5XTnRF12irt+5vQ9Z0FXZ7GHg6pwlQRrEDEQGlty3eOt1D1WcM3mzfJtjvEwp4m/qWoaOM6gRWao39W0Tk/+3y9On7aG/+ZeFZMt8sbiMtUeklu2QpHRj0LqYTJUKqSW6Hu1uH9wo+1bm4CBqqFAvJxHjeMEuF9ffn5m7df5fl6c35dDf6pMrVCjBmIr0XK2K3/ayHXqWMeVKpSmIKaimZccm4AAAAAAA//pwBDnkAABCETtc6QoS7EDoGxololqI5Xto4bSl0RogbJxnnNJEIVAMEEppumJHcPQTXZYMilntzS9EbOD8vi9tPbl6f5uvBF5/9t/zLEv2+N7fFLLNlY/dpID1e5NnpvW8gQOrY4gAGAAACbcjNZMOEJHMDEcodgpMms9qJHUB+OY1PqIu4J9fP06Nqnbq+h/fT26COz0L/0Zkqxn/4P+niv3s/v1J6QREEJuygrFkm4d0EZiU9SPJJVi+WKURRxLUJutP8G5m5OX+gv//6/Xfp8Yfv/lZBE3D7q5lkvZVptRL1/9P/V9e1CRcy8VGAgEJuSWrDjRF2eVs2Kha6W4jcHwIIg8ZqDrZ+jZUSuvKN2/mF+d16f6KzqzUM+vk7sv7H+IS6aXVhI/KJX9ym63qqYozbIpiCP/6cgT9OAAAAhQdV7jPOeBEyPv9DOVRiHWNdUKEXFEOji2og5ViBAAApNsKBDlK6iQSBht6qrEXC3/lM6+iBoGlFKFiWmACNY5tTOEvXlBbnqJbq6tbE+VfOMkUQ7KPFf1q24UK7P9OqMoVNkkhOuzB7DOJV6EECT/AXjW0HcF/o3b+Mb+nGP/T/I+gw7lO/11fV6Vp3Uj6DB7G7UR1Vhzv2XVcXeajiBwMqbJnqQ5SILlu3iqtWwGdUQNupuThZbDAF4f/24t04wH6dW64v94vpHL/mNo0Ey7cnpa9Wf/pYm36WK/9JVdW3Iqp2bmasQ6AYgAEty7VETDpgdb4qLWtx7jvEwZ4P/GNoflfGO7Z6Tr99dNtGsJkUHqA6wqNa07oUA0tcFXCgZdQWU5xpLcvclQqtMQU1FAA//pwBH51AAACFxrY0M9phEJEu3ogR2WIwQNxQKTm8QcXbWiDlWIAIAAAE3JCw5faTjw2XTJunZZGfS1gwkNbKJbiYPX5wo8u8qaWrr3ztvFuNB23EMOqXeOFSqzWt2Yexqb81quo+MbRImpABSRbhURqNZQn6Rgr0bhdwnEBuo515QtoZxBzjeM9uralvyez8OSl5S8FQZB1jXvK3lQkWebdz+t1KHIx85bJIB3AQk2nIaPKIFLlict5QK8/ikZWjNgXb8oTzmfGwdobxz25Du+r/o7cl/b6NfztG7aNHyHdUZeUGGkMioLDHlzO6mt1tAgQgABOS7Twj06AKS0isYqhPirj74KBvl6dG4Pz8LH8n+38v9DPxWn4biFDy3VPNT1G7AsapAiQhF1Cj+0a1Iw/0piCmooAAP/6cgRBLQAAAh9KW1AoEeRD6PwdFCLjiIEFb0QcT9EOIG40hRXyADEgAGS76zbKgXsrDb7xP+t7CIG54fif8fm6tx//y8n//xq/Ft69EcEVWT1NVkBiZmqzavsdSBleHRHekkw4dFPyVFahQ7bZcUlu3WhaLehQsrpH8R4i+g96ePbMfUOduFhvXk9dcv98ua3H0dOrohh0lyqz7IGZnt6vxKmpUXte+WkKlXbXvIDoAAza/jSmr1BaoxQLDeYWVynKDOpfndf8RfbEIRde4xYcHOJbaeXBJ0cyRCa9P7x9GxRyS5xnO3pQo+tcMRZC9oquIgRIkEKa78GrJtMth7VlhLdKNbkXEA/HeX69XygXvP4xDbQzk7ZS4wT5C/onj/0bki5JnGzskJeZjFR45sv6cp515VMQU1FA//pwBHlLAAACHkBa0Gsp9EQoK1ohQmqIWO1YaSxNkQ4gbOjDiXsENQYApbuK8MPcwWXp5FI8TRl+V/lRn6pMH1ypJNYr5+Jf1DO3VtC8vVv/zEz9e7GS1Hj++rLrGoVOXUNGw4mmfUPaZUDQEgJ3biKL5LpgVW5BJV1Lc3hkJiSMbcTG/F76Cu3j8/L0fv3/m9WWj6jcMwAVHKaQxltqyZ1QRb7qQYeaGlkiodRSAAW5AYkOH6NJMzNgH+WEYvRD59RP4AIPeSiG7YDmuDtzsX8gwle0Ptfa315v8f+vrqj8v2lfrLa06aDWPoss2fb/RAEABDUs3Fth/2WvFPddHugt77CWDERUagP/4hfC5N8HzYImorvwQ/Py/7eyOQ/XrX1rwXVfSNrdH34/IKid1/ufaKwmIKaigP/6cgR5twAAEhQ5WBnqEvRDqBs6LaJ4iI0FXueoTdEHoGykk5W6Ahclww9aqqj5dDge25obzJNwtNkY7oO8fNo+Lx5NFgKMO3CqFkzEcvT05uzc23qmor3+/O4PIyzos9tnuW4M9RGylQKEQCXbuJ2l9oJQKD3Mcd6UfeYaxVKOgS+svfyvgw3Xo3bp0fv/v/g0V6VFetqyIFGltsKMiLcZcv9ZoCDmtJHdJkyCIAlObDD6ysa8Z0LEqq7bCm621BZL1Gofrk3ED75ocbEjq2UE3v0bn69G/Rv9vfVmfm30Jd0aeFCC73GqbZWWyMMtcRgSQAC4sJPotUQByZmNu9BnleBEXqqg3i3vxS3GP5QO/n879uT34l3RVGpz9bOmVDNcIdK34qG0K60jHkXPTCqioqmIKaigAAAA//pwBEcuAAACGDvY0S85pDtkWxcZhzKIqQFlRZxVMQcgLOhklGIAIQCAnbuOzaEJbZscs2bJA+9HV0AlwIB61ZsIvfQjx/+Jhvxz21F3P9te5vVuZaj90ovH+hXC0eDSqdFU6kowoUdqBQAQrNw+AXVc4NnbcIT8qJXEGgEA9YrBLQvyvXlAd8/27fyr/4lrGByo9sy9NBcrMKpfpkg1GuwlIqOgBiGQAmpBrptHzlQCkoYsI+yXfJB/AUA6kvgsawEdxx9CXHP6Euf/KizjTr7f59BPT39FhRtCaSsd4RgYFSa00sxhFuxSoaAIFy78OgKhc7fBKVIwPE/q3C+Az4WLFqZ1p0fUPdnxorjAH53wiP5OXq3N66dC9q1oisyxDmIu8TMudWmc6fJJiCmopmXHJuAAAAAAAP/6cgRepAAAAh49WTkqKsREZxsqMOJeiIjlYGY06XkQnayow4l6BCCjLvx2E6IfWAW1GgRE1bcePQHgsI8g6cK6AnF20bRuTp1Xi7af0J5tH4u2hDrdNAVTDBG7iYUMGHBKGUilm+bpv74AgIQSl345/3bV+4K90mh/LcQaiHicgbNFDZ3KF8qJLYWbBi+K5OyaH/q3fsmnRLJh2XPAHGXFBNOmhI8npKrQ8anatJLJagEvsow3+C4guvDRqUnzbjGFoqo81hq2FhiogCqMJYPT6hGWU1An08o2qc3p0IZ3/P5vRTPWVM1RyGl9OwP9eyNjagJiIIvb8ZYvrXMmwWX/xQH4mEXiHiQ+VGDZQAlNeUL8SGxW2o+v+CG79OT30Q9HfQBTR9XU0KyLGSCVojKNWiRv7taExBTQ//pwBOSrAAACICNVHWIAAELnuxqlnACIoZOaeAgAURaxrs8EcAECBXcDbsWXDWEopjaDVepLCqSK36vwMypiish4hcMwXjhDCDm7zNOtM9mQxXTYzK7rI00YvmZEun/nqOpvy0vU/hiIaEECBIKl3Ah5iw66MD7mICwvuFF+FkaFiGOhmp4Fm/KF9BO+3YPeo42bqPAxs/+U/76+Ym7XSqDkmkobdCyFrlIC2lQAAAHAwHA////////////+gfWbhlscaf//54gY4xZAzBoT5Nm////iyyugM2Qc3JYi5ueIH////+OMiFBImCcIORc3L6QAAAHAwHA91z2QoSPNG2Tc/bfbv26f//////+Y6ngBiW///7COE4DAeEBuNyf///g7LsD8bnlhu7CP////+JZDQcIDcbp0wP/6cgRh1wAAAgtWYh4BQAREqswTwKgAiKhha1yCgAEUDm1rjHAAADAoFAoFA///////RWdTP/xYKg+SAYBuEz//FkLkTAlCOMiMaCp//+C4LUnJAuSoyH7D3///xUH4uQ9iqD0u5oqgBgQCAQCAfk7Puv/TX////5is6mf/jQqGZIGAXQ0//xZECNAXheMiMaCpt//wuBak5gqqREbD3///yAfi5D2KoSl3NFUBZWW3GDJeYJIaYjRhCCvMPxPUT6DmUoCG7aNxB5dwqehqz6n/Ku01B10RB3onlPrTW40JQ1W4q7vChVwUeIippTGxKySwBFupyEyX61Kl3E5rUGz/ePqxpEEjVU1lNEQzTo3P7tRC3V+R/DV18RGqgM/uLSO18SJGgq6ShrpLMDRYio8G3CmsJVuTEFNA//pwBJ0GAAACGjfY0YcS8ESIK2kg4lmIiXlk5ZxM2QAgb3RUlkYAIBEGdJN8es4Le3E/bzhzJL8pqNS+JiLUFf9GygOeNejd+u2tK5n/T0M+Z/9G1Eq8sJYdIyv6VNWM+niUFWFo1ddb8E3GZpG5MGbxdA5sqgyymcc4mDS/gegJtE5OrdeH9unTp/+huZ/9OpZqfoZS0DCkfO9toGCrCQNPO3CQ9rBUYoK251owDpALckudlg//BQ+8XkK+qcd4UOwsL+Bf08f+C6p/K/P1/r+W7P+eYSmjs5X6vXzHue2l9lq/v/ZJKf+p9KTuk4Gdc5kIsRQrMtyNy6MZGU8saC0l78YGsbA4pwR/7cX6+Kcn9D9bZ+/+Dy1Nt826/b9fEnd6mmrRGrtcHKOfW5Shpq+STEFNRQAAAP/6cATs3AAAAh9e3lDlHf5DKBu9DCcXiLUDZ0QIrmEUm6vcB6gYUjvdlttN29TqT7RC023P5QWJHg/kW16dSduFeX/f+r/oveSi/8YP7Mn8zlviDXNfLqvvQl6ejvWv/7T+cs5XCLqS7DcQIhgUTkbScqUZUwyRUjK05r5QWI5QX8l7YmHdwl6NiYCrb9G5L+r/r6nHdtvr0LUa3/xR/MMgRKh3mlN1vRUEJq2SACOWKqRW7MlQpw4aWnDI/OiuAcDDEqDMiEZ7PjHxq8fxn+ml/tt+jei3e/8r6nZP3e7vj4oSTgfEYqu+WEB6Ov+BZ50hUAJBqubZriP13WAMqdoMjV0toC82RNkYf0ce9Og7x9z2yg369OrdLJ/09U/89yupQNw0SyLy7z1zZIJs26pHItoar1u4RTD/+nIETtQACAIKGNnIaTmsQAXcHRTlkYjhAWLnnEvRHZytqGOJNgARSBZF97AvwLNP6pvtfjfiFXQqNufynR9AxnZ6Ky9SJA6DvJZtJzwpap3YpYbZAG6tzPI3eKBdyj6nOC6TRcRjM0xHTrpZa5cjjbq9Z4Xqi9VyPiEUBiGD0lG1BsrNhbaG7f6+zWH/ofmGSD/xT6XyK5bqATgnG7BXnkqS5XPEehKSDbkmYGcJveakx1i7B9r8acRQTVVO1Ep89tDMoC/p19/6ty3UrN9k/1L/ouUrIql7OisegV4Ecbw42AWsRjm4qmtGR1brdAWJYCaKUaS7yN4yTonazjPHHxzqHC1J6Jtq3Xr0L3/qKK0t6p+R/CrYqf4ZePQdKFxY+FXP60m9rP5VMXAJSTEYeAbwrBp6YgpqKP/6cAQI+gAAAiBe29ApKaxC5dpQYe1MCIC5WGeo7kELoC5oU5ZGADpZEpJJycwaGNjAYHsf4f4UGrUXfBOX24e/jX1T+rf1/o7cdX5+8jIyoxTSfbJsL7ZX9NuiV1+pHlzlvyN242hox5L9RFqV0qi3Hjv5M5CZgoKHPo7apPWoLd1vhratcqA5aaw4+yx/LMxJ6sKBtF7OFm+avodbf1/0lPpH9nhKLKPK+780AA47/1deQvOu/AF7VfZGHeZq72C84TkwuDdB/v0GNSPM5V/6dW0b/5jNoTPXq16CCMaeYo9p4sXEr6FZG9zrXztvXimyfNshuNu2RzGZQudwi7Y7l4U2PBt8f16v1/hYG6cZ69OqfkUmovbU5E5UK0xT0HopvvTGvf9pL6Vb1VIPLsAJZCOhMQU1FAD/+nIEhOMACAIXQVWbDRLgQea6k2DKRAhhA1tHnElRGiBsNLOKjAELXtvgXCs6+eMiDkQzloMRAmy24wfMzWoR5lzLrfOFmicCG1fk67k3QX7/mJ1rmTb9ejGf5jyX466V4M19Pup91FQADLtuHYMtxVo8tuAR0MnYf9oQfoC0mGQmXKhfLj1teVEzio+V5UUdPb+vm/ont/b5doAjNN8nUUpq6NkX5H+9zKAIICbck7TjbN7vAPyiNYLB3bhIeppbQKgUXEtguCG5+D4IQ1AH3wTc3/1+JPr/WZFztH/aWpnCHZK7lR0sjt7P7LOlgAACxRtS3fxqejeEyc3nr12uph22EoyjlFsui/HAl0I2DfUvX/b+rfqXpJc/fuoA8hjuUxn9qVQwd10ZVU4kt4Fdv/vu5VMQU1FAAP/6cASr6AAAAhA5WlBMKYxBqBsqLCO6iJDfZ0G9RjETIGzoNZT2EDdRIlNuC0o2UCsRzOGWGF4vxnhgoqO2LNmLqHuTjB3f+jdev9TPoYu2vsWJzHRmGTci9ZZj0n2UprZBiSLtUdeXgAsZkKWbXuKZ3IHVr0y16hLJX6d+qRvVPOdJyXT5Pj/mXLlyDy5r8wLjhhuXx+U3Xe/20KOMHIsDI4hMe5jav/9IyKMIptpwb7BZGHtcuovHO/JORNoNSyTmyvKvmBC2/DIUZ7tkTVc3Ui6H+9H6G3Wm/1fjxYx7oBjkfVAaA+Ve1iBric9wl5TBKacFSACgjgqezIMhGbRj+aR5S36EgKdh5v78Ce/DP6dDd/btszcYuxP0WXi8aSq9ENvER95boQYEgFWxyAcXSCyYgpqKAAD/+nIEOnwAAAIPQVpQbCmURGPqc2HnTAjBDWWlnFGxEiBrnDWU+iQ2lYTm340QQPcwL47YItZTcX41sKFSLD/9egv04kO1fjer9v6tnHNolUtRvYr2TY90LldnSMcMiglIK19FzFNuIsApzYbz3OtnZ9FJkCvgJhoeqN+ZGX7lDTcbZrP8nwXVwvWJe1X0bgm274gEXjd6IrK1eehEU+JT08AU4Xaxb327XuN6AoA0mSQk2pBzCaRrMAGIw0pV963LVtRC+UfkP4nbUbPiPqpvLfzBn+/bhS++iP+lPzD66OYE4OGCidYNyR7QvKptirjapeBTIDtuGlUAcagwauys7bnEf8E1ftC/sJkemHSx2/PxXr0fk/oG9/b9hUubK7q5fwEVpxVo9duY9c4/U73BpSmMYVfUSTEFNP/6cATMugABAh462FHlElRDaisaDSI/iFzlYaG8phEQqKvo9RV6GCGVBJ3bjwsxHCndEOfKZCTy6CnCIOtBz4HT4NsGP2fUfRevR+3Xk9E1BTo6UIulhGog4dFFo5SFOC+jvjSq13sFb6YEiERBLbglsUGSAGfmHXfLS/4Wh/P/nUS8LH2a31JzdX0Jz9PN0/2yDtoltMnTEOlFciiPUl7KQev/22kRFSd73cN0AkCElAgK4m0TwOLbFI4wMcl+LXgIPxgJydOrcU/qG9+nMPxg3n6eTxVqpyaIUXVGVHFSiQlMsGl+iikXNveQqFSNKIAhAIKku4xTPaW2fI96V2HqTJuoY8q+Qho2S/7d20fEgP26NqvE+ifp9e/9mOXilGlYnvJUcaj2TR73orLSfrZYyp8PpiCmooD/+nIE1C4ABFIYNVdIb1EcQiWK1xnqMoiU41J1hoAREx7rXpagAgAgARXvMVWFzLMD6ndiMa1vyXiM+MBQSIYMTM9sq2Lglps2gp78/kb9//nlu15rprfUkOODIQQGJ40wNDmyG7u+3Q8FAILt2Hd7AAIlA+INqg+Tz/gOPkJfKCJ4+6vobyHp1E7me2pf+n9C+LMEsRNhd4QJB4iVW8yFkPPpJ1W70k6xVvQAApKBhIPj8qzoYwSxjl7bC4RzeeqzMSpDJKgYBQDlT1LzF9k60xhu7aj//yt/6XW+y+tBq2U1XdSa+uZnTNRUXutvx7IQS5KTFB0kFbQkZ7wpPU3ZuF+WoYO6DbYe9X52eEoxqvhmBULTxObNLZUWGzOnn6k/VjczRtVRX0WrpMTUqZeeFqGMJoTEFNRQAP/6cASmBQAAAiVN3D4c4AY/5ftix7QAiK0dbHzzgBkZIS0PsHACAABAIDAwGAwAreWMIiZxsN2rDe1gkH5TSg9/ybJX/olv/5gl7f/8bj4mCQaBGL///xLEwSDYgTIDQt///5ZCCCOXJkSQAQQQQHjeJS8GLFmjxaeLpDxc1oHmBqJZWtBiwkSSV2bLC6TjVfo2yVNmZ//yUMB7kgTiv//SNkAfBP/mn//5AAJjbj42x5g5S7n2rMu22qsCIOPFz5rVVC74/9FV/bTtpoRROzf///+1R0dIrR6sYyHHE2OB2BVmOOOVlU37nHKKDvSodAguO0fq5M2KHGFTVDLrc3L6WzLChoAswg0ijKbH7IPrdGHD2PPacReid6IKif3U3WdOzTamr1N26///wm6m2btYObLM//WmIID/+nIE6fQABgHvPNo47zlUQShLiiXnY4jhJ2Jn4OxRIqFsnFwcqoAAAua8IqgoXqw+1DRh8F34I9hbZ52XVRhKZN8adshdWr19vRm9OVbX/20/Xjzt9BNfQejoQr/xLkxV73fXAAkIILikHytjYwanaD2bv2D0xWY2XLW1FxfV6ls/Qtq9G3akoS/UzKkP85HsmnVV+/26PgVehrL3a4gArVbN/+u28fEhPYlg+FEf05X7bGn8ZkPjnZ6ansYH5uXegR57UG92aSBDMbZvRvq2a2d7pZFbv/zf2nMfoyR0Xf//08dcQLWypRNVa4AAAO3YFwIDogVJ8aju6+Rbwg0aJbszOcoLbZUWPml8ttaWmirTmN0/zNS2n91m6azmqjL2z8086IAPd7tWhjswWDHvAry3/JpiCmooAP/6cASDTwAKQhJG2JnnFERCSEsaPwdgiBEnYOecT1EJoSzcbByiABdtA9YZcoOgoSUTLahnTDlmhRgS0WaDFyI652z4gyptRtlGUUCPu2LanZ/V9G3TyKqq9U0yv1VJvVmzPRB//b/AYAAAAAcmAxTruFIFCRkLZFbkWvqPg0oFLlImEtWSUCXjz2bG3aYBHvnv0/y7Z+f+vT/+v6e+BZrOqi93R6hYM0Q6kMkwzvQ8XOhfiOXoBDaGxPXAyQXjkSR3HBcOyhJ8RWldRbjzyoBz1aorVtqaOTDtsvJJ+tenm/1k5Mj///xXoOiAAKW7BrcQNZ4moY3XI5co9bqGBAlux9BnWUG/C/473nir8olaNp5rz0281/O7dEt+Z9UqaBTShgz3aJmRqYJW/u1piCmopmXHJuAAAAD/+nIEA3gADMICO1kZ5yxERAg7Si4nYIf1G2JHpE7xDR7szYEqOgSpbOPrmPCwTM1XOEXuyYe/KkCdc7wc1iboL+dmoyF0u6D4IN6hjy6My8SK8IkmP/m/+jVT/z8Vq/90bpYsSLpgABAAKXbjdKJ/Kxi9QeYUX5wAHiM4ULVJZmS401fHu9B3+bXb7I71IX20n6r/5upuzU55aUBVWSaIz/lDfTYo6hWS5NBug++PxolB6srptL925KT4O4FW3IYr3knVSYdqSbc9Rs6OXOJ/IP2s3UERFYhUOlC1WqddFql5f9Ju//9F/xYBUuvGO901NdY3JsNs2+Y7/ysLGr8i9JVrHqNwNqvroPJevOPVrfoGdvZPl6a+m2VY1T1+zKRgqboS9T/rPZKFwJdMpiCmopmXHJuAAAAAAP/6cATjYAAMQfU62BsHK7Q/Z6s6GeUqiLTrZGeY7pEdHqzcso46ABctw/C4u+3dTdb+5xWm9Xfj7DphBmMAHyowJzTYhDWgYztU2mJBmvI9b2f59B2nqdu//zub69TY00j9/KdcAAAABTW8XXCRjj3zbJeNSb+3gbL6q5h7KzVXh3Gv7o9RL8QN9vqdK3ZPd3djFtN1W60b/o1QXxnp/e9r7yfvACd24+cnpGw4lrVuOfa/FrgzSSHIjL7hp9cDjhO8ry2jzBL1fJ96s6dU1bb56o6P/7szrR/U02xotQkb19KyCREpSVrTXAAFd9x1j8ngqQ6pgIe6dpUPBS4eFONY1Scz16XTIEfxNurfIPPKoJdm07oYyU26REDCCHPplJrgqJJYCWwnTq4MvdqGIWjcmIKaimZccm7/+nIEG2cADAIXOtiZ+DsEPgg7NyYlRMiw62BnnFEREyDtHMgJfgC3bcPjBPViwuh5eGWK6ZUuM3gHok1BcZhyOOyos4BmOvQnqXQRwCnlHxs0o8dZl6tq3+r2RtPcxO3+0zQX2fd1ZJcAEQpd8PtCxqoh1BYsT6SiPBlEGAJqxtaBgrkLGtha+cJfs9HX+rduz61//uvfM3xnAJruIlN8o1Lnj/eHYgAzXAetxcmvQJJ5K2i80mYG5RTgb93I7csgwe42xhqAL1L49ldQ7Tlb/1KIwQl3OTzuVEEupdVJV9u376BLCYyYHubUVWAEEN1wCew/cxIg30IOnLlEHB1h9o7HT6pYO8lXmZ7H5bLaxDdXEhKDhw6/hERjvBp0VnR2oQpkoiXk5f31EaDyduDfyiYgpqKZlxybgP/6cARzxAAMUgRG2ZlxE0RBKEsTLgdSiLUdYmecUTECoWxc9Z3SITu3A7xKZwKQ4PKEnVNqNCfBVGqBMJVNdHZqY6sj7WtQBT4UayK113QOSDZ1M/OxuntpZ6PT/PhFuYiv/tenjoBAm3A7wHisA8XImAZxNmqBfEaLRdQiaX0Br4QbcQq5Vs56c9v/We2Q6fVlR89FftNc52/zT6BXKG1NWnHWj6hcgACo4B9YHnA5/mrfZTW0z1kEHLkyOnOLSKJKvgEtOeiSx2NBZpoAtRj7+CRYVql90dlBtt0aR7V/4LQWk7OX2qUaTdFjKqAAqenL+tc9ojZDH9uAr63qDxMXC71Hxb9U2fBf+UWrVCjUfERff9TboMV+qlTq9X7b2879C9QmIMiW/UTkNxcymIKaimZccm4AAAD/+nIEuuMAAAIWPNiZ+CsGQseLNyXnRIho7WlHnE9xDR1s3JgdggApfwPvj8ccjTVMCVDPJD/X1DwGFQ6akJDi4Zo+vWy7gf8X3Zf6F0Nsvp1b/q7qQ6KOd2Z2sKjQAYojw0zXdX5fzDIAAh3fgedjBjC2L2ampG+9pQ7R6TahdK1GOJD1fZixXif8S0q1/scOnSg+dS+6q7P/9tDrb1Rb1BA2Vc5SwqSrXOmYBQVAJdcA9MIfPk9XODIdOsY+T0FtHnFSskbljqDGozq9SWpaPgOeP8M9f95NBEwtOyDs6lLa9zwf/+Xicee1KrWsVkMQHf+B64hV9sQSC+nK2waAK2EVajKUzUoEzb59l4m/YjVv6R4ypC7mPtVFY9WHGNdFOPdHpqttFd0GTJMCoU9ZngZMQU1FMy45N//6cAQcnAACAeo615gvOHRBJ2rTPwdiiNjzYUwkTtEbISvc8ooaACl2AnKOx9ZlLVWQjH3m2sjKApRY1ZGSBrJExvBDKl8MNMaaCOvHH7L/VqkTnT/3/V3ulGq/pKTUDf93agAGS0D1lEKKa8iMfN4m3LIzN4x4a/ErWFuVMVxXQvqC1avgsQvewVaV5Q+rGfucazIDDpjPXXdNPdNKc7/qNnX9CAASbcD8tMhotNEhVPdmPu298fcoeSGERDdUy+PSfn4/vvQDuCwR/wjw9nunj6t/KGBqaKuzPRSLb+uZR2nDWDGIL9a2AIlAQAKbcD2oLChGpHGDUhuj2bHU8MWFDaYqkcrtQVbEnq+Ad0zGevOP0fTw+CLnL5Ve5kppKdj2dmZPW7WATTj+yVghNKIfHJiCmooAAAD/+nAEbG8ACNISOti4LCh0Qcdq8zzFdMhs62DnnE+RAZ9sDPOWIyCABTb8VoBm8DSzvGs6/9g1AZZbe1IybDR2BNHw9d9G15cr/6Po1C/Qzoyf2dW6b/VsgrOj9MdrGmnCy6HDnSpE0kAp7cD64jTDSEsNUJC8LydmouQaSECCs8wuuxMdhD8ANGlGNXjko6f7/qvU+8tDkV9yp7297NQa2F5rjFdJdPFmDhAhzb4feB0uWD2WGaE57gOWtxQ8knE10Y6O1LlsR8eeaRKl23Cf8Nnyh3btfBNm+jZmppdqM89u3UjUHhbjuo/Mu/3gFT75DE3aVNQ8rrwkN34ICot1jwdxM61GS1RHenJ3RsIfzLR/+ZqAnf2O1FedmoVpVza/o2LNO8TBF/vErUve9TEFNRTMuOTcAAAA//pyBEWWAAACBTlXvTygBEOnyxennACItZVyOGOAERqyrosSUAAAQAcuwHrGFVEhs54MPYqJCe8huHuQXA5aD3YSqJjsQ/HKghUaEGpwtJnEmOq9edv+XT/7HKifph1AiDYjd7WoRAAAu7YDdbFjeQ0msOMRlztYn6kBnjQwKs9BM+VIEDDBIenW6NguMa2Ol6Fzn0559xwW5r9apMHf6JMVP19WeOLWo+WBBJLxxhgZWb4nQKrQFk3LuZ29z/1st7e3t//zzjKN/9tkH1FZhn//5w+QCo8YcNzP///GxF3cfc/Kf////lVPZWMYyho4AECEEEndqQPMbf2PKTGlCwq49wbsuiK6bLm9v///5zEo3/22QTUJkJ//+YTFAiJEMHyf//+HhV3cTc+M/////VT1YjEoUQTEFND/+nAEt3QAAAImK93vDEAAQ4V7meSIAAhUV3WgjKChBA5w9GGcbmACgXCXW0W5swHhweqE0IXhQjMCZFgmTs6Am3qbuphfopS9f+ntlb4Vq2X3YliyjrtAGWGi0i/xWtb976ztrFVLPPBqSgCAg/kr8lkcy4y+OOlvb8hGhjMlwTUd2yNQXntrN+UpbL9Ontlb4Vq2X3YliyjrtAGWGi0i/xWtb976ztrFVLPPBqSoADAaZT2Qd1wJgDmFbyiGC4miLQdno8Bh0j46ubrcGV52V8RP9Z27w7KqPazJVZLToKuDt5KBUuXkgVWIkNQw7lQ1myGlJE3YinK0oVABzmZ2hOgRsIzEWJiNHdMVFqF9vv6tYks5O17pH6zv4dlVHtZlayWnlXJ2wKl3QJViJGw7rDSYgpqKAAAA//pyBNNiAAACDEBfUAMofEHoG3csxSqIsNdk5jyqwR2xbugiib4BMdikq25YuCQw+YmkuCWmJvTQ6cIjolzp6j9V0f/3dvVqHX7/Mm/N6lfMLbt9qIbEQl/QLvw6x1V7mMh1sOlu+SBKCpZJb6hJWFxAODtkvxPLVWEduyC/VHoGUH5tXUwi7+FBlS+n9+qfZDehk3fN6l6GopX/RDY0pv/TjPpq1XFq/RAABD+7+a+QtHMwwKGeeTOEttiFrzaS3zpexhxARHwOtG6Pd1Amo3R//VG/u/5FaqEORmN/nH6rpBTu+j3DUcD3C//rNdeAIMhJxpOywziwAcrLw1AVYypmQfsogPx0z4ijK+A3V6AfT+6F21Vxf6+gs71Sn6axHv/8H//u/1b9d2rr/XnaiKrsZqJw4hMQU0D/+nAEyBcAAAIOGNkYDzhwQ6gbzRRllYc4cYOhhPKxFZwuaBMUIgEdZv12SW5dXLRxRpoq+7daSYtU1Ja8LNHpgtGYY7e61OEmuRX4u5Wl2VtKxvhqXHetEmz9bhAhXc2vrquhEM2VvQACAiQSUabl1FYWMpM+K48Y4MKSYrimg+heXGj15gF6tU3/tTtSpv/zX1/0bQ+yfz2oAr971G2TSFbdqyOuioao9bJAJhIyMqWxyb6ZhBT3NqZdEIMTS4ZIsDj/WbIcGumOW+Z0LMa+Ot5d0Ms0dWTf7HbJeR07kSbDBUxKQAiyCprLdTpYQBlH8Y+DVBSxGjPahSEe/b35RL2lBd//eahSnK9Oicilc1/pmbj2s7XFp65m7YnoI6swSSfJCgWEb0XAJMQU1FMy45NwAAAAAAAA//pyBD42AAgCFhHZmeNLpEOl3A0JImOINEFvQCRB0QmObaSQlg4EmNST7bXCIpotDMvIywJ4+2wao5sXTuc6INs685PqGCzBRxj5k9QbPuzuLFRB66LuKGZghVnZu9V1YYdT+9V5uhBaAAovRFy2OXT2grNOmNlhoipCjQ72pYj2fG1VrIhUzZ33/9KSPj/oXwSN9gfl1NultC1J8Y8boURK6jsuWcOftUpCgwGARVlt0B+18wjpzSWy5wRzE02p3W2oJwbU5Ni35Z3qOWKGo1MtMWoyp4PJLg1SG7mOINN6e1vWd+XOXgUWHXqcHYAA0G9K/CxPInFJ5bWp+Qn/Eq+mkrm5NkeMDVQdiVkZBgCmdfFIq1VT7mP5DO/ulFP7g0OIpVRlcut3bzz6Pe8/bUmIKaimZccm4AD/+nAEoTAAAAIIQNzRATa8QUXbjSzCR4isuWrgJKGREQ5uKBMUPoEAxDSaTc7GDLW8zPWMd4RG2fW/N36xWQP3r0in8sU+ZrEv/vl5//1/5aZYWin9dn9YxYzKvlS7lvV6n1JrPdeRgAAASARTaTkp5o0VkHSuqO4R23bMvUG+5uCHmGwsyMigWtqF//T+q/qz6D3PtXKypY2rxlPzM4NUulrHq/RoYzoACIXZLsHitJS5NNZqsJ+dRszZ2Gy0HK0JcVxVAxcgL+b/7FX2erN926D2aai2kQprXJFXaaUDBIL8Uw6o+1+bWSkll69cAA0hltJuyYnqAPsdO+5PLAc0UqrhY/ORWjB8S1CSiiNQV9qj/r3rFujf370i1/Ss6HExaiJVdWw/XRCYCe6AGhoN2RyYgpqKAAAA//pyBPydAAwCGytaMWgsrEOF2zc9YjiIBQNqYCRB8RcgruhhlsYArH7Z7iQ36HmiMTc6US0CRdqVTKyu1FIK1TBqGjLSKIogb+IvVvLsr9sxl/GnJMooN+yTI63HHLd1aB4q0OVkhV11MAAjJJbfXCkhCnKVbPSoWdEFqildFfWDNyqNBDzG1Rk1FaGyJRfvq/T/6o3EPWp1gdl1hPWVawhGi2KK6nddX/e9llQJTacC4l3JuKUjNXAU9IFX87FVGBtIYMEarex9O6aYP/7M+m5f/7CUSv9ta0eP+nucGjHFbHPMsrALnMIuCckQ0EHcxy2Sj6wnFoLnzvZ+4K2BJP/HQvG8hucvxCrwX5BFMzzn2/opdM9/pKvy5+uh4FIhEMqms323RB1q/gmTe1i5INIaSTEFNRQAAAD/+nAEuSoACAIMGNuwCRBsQ0OcPQTmX4iUcWRgsOHA/4xtXBSUMgCFNLZ19Ur52aZ/HvRNQIbZWpMEaEavJa6gxUWt/8pxSkcCAIKqDEuD4EOPwQwwEK+TLv+GBOfD/5Q4cLnycEC5+kGJ1uOX2uXVKZMrSoPUCDKJRlLNmERij7aXuphBOZFgA4dvV8p1UqDBh3wf9QIYICD2Ey7/UGBOfD/5RzC583BAuHw1anbrILjpXSoz1kfFU6DDk4/05+tmE7IkeYtOLU5+tUDH5VzUfVLEtT5X8s+4qS7QSKufO7QDTIsyycthqQcVCKCvgrAwFKJNy+S6SgGl7QNXbNJErxdpHsiSMOq+2/eoam4MfEr5E+FRuR3fkaI3rU8NJleht9XY/PSplQBgoLuO8qdTEFNRTMuOTcAA//pyBJfyAAAB2RjYmA9IZEJoG3csIoaISOdq4KThkSSga0z2CPoIqNySYx47DHcldInVnEIv9pRifGX/4dy0ukq7g+7qZ8q9hvUL8Pf6r/w7O3Ya1HtQ87V9l1/O/pp6j0TAk9btusugWEEs+GtmY3jX5AzvMoqm5LXeQT+7/+u+iNR3+j9DVl5epQFti0Nb0eV6qIPWZFbr7IT8skjLdR7WSrgEGptvxZRaQwc6fF2qsVWoJc5uVolB3FL1LTGV0e4a/FB9Ppx7oqd/2V+76P9UT0OZy7cSoHCVlNcqoa2PB2lj66wAZJKPeCHY6C+E0LRDqBoOkr5PqlCieHBVi96fYTLzKPpug6jYq95xXvIn/5Uo5hdm7pQR6oZTH/oJfDGe6ffbUo2p2vW8oVbQmIKaimZccm4AAAD/+nAELXYAAIIQLte55hO0QWgLJz0iKoio5WVHnFCxC6AsHPSo+gBAkuS4fA9mGY6ieRYDahizuIKTpJDrGrA0neI5bSxHeiHcGSjVDvDiPeR//r///1DWO8hXY6J4+zKfcwmPza60kIAAl23cemTzuMsqLKTMHbRIN6H8tk7dHEHeo9OVfYv4ID/+pNHov+jNwV7NT83RtkddqFtgJk74uRS283ESGTxF0AAAgkNtweq6YIZnwpr4RsbNEH28eU1KVsyOUWazwsXrz4PDr0ej//O3ZWr/VPKvzdagWqnoDW5c9X3e0OkAhLPMLFmMWQIuSbD5yXDk5G+0E8kYxZoL7Rz4D7rzKMftMzf4P6n0qW5xn6htRE/q33zP7dTTf/0fvt+sxFnDGx79oSrFSHczIuTEFNRQAAAA//pyBIaNAAiCDDXWmeYrpEQICwc85WaIoK1m9MKAMRWbLF6YcAIEGSWj9nEZciaEvSlHwv3TXBIRQzQQGIpEuoMUmW9SLYhqWpKcgJ+j0/5X0dW2/L+m/64o8QqYO1CsxcrRlGRvZpgICXLdh7YL/IHwTOVW1hMcBnRCqI6ONdpQOzi5R9B8a7zWVpx/vCYhRrd/+2vpq2c3V9/l6m2t9VYuPY9xPy16MXQm0gJbjkE6Q+cB4uqObOpriW9Ba51LZhB0uovnejUXegwJn+HhRrenEm0qv9IwpMDFM5FhShjYXaxZg4wiSoc83fGIQipJNwBd23FK6PVwbB6bl6VqxCjHle2qac+ggIplFL0evN7Iwkn/QjRlb+2j+/99TSzGoc30NnkEW8RnWbqOdusYSPiTZASb0piCmor/+nAEq2IAAAILW2SeBOAGREisJ8KUAAiwaX9ckQABAA0vW5gwAAAMBgMhkM///L///////++3//ZzDACxL//+g0IAPEtxIIGbTm//xoWPMKkzCGe/3sx///JjRXOGhA4yT/LAGoNowAAQIHA4HA4HUta5SKiQ4KAG2/8lPzs//0b3/1Y4uOP//c+AYH62/+4gKAcXihG2u3/+HAGNBw4X//g5EAZcUxYEIrEwABLNKNkkQUJFDyOMpzq1hvMk2isaqJIdmFKiexrdrYM2bGHQ0aCtUJPPIkRCsYKy3h1k9z35S7FWtucgbWFULuvrbs0WADG+VKHAkLFB/V5u9GfBVVP1lRls+OUO9/yal5lr4YRPGSUfqCTzwlyuKy3h1k8yg9+i7FWtucVG1j0Luvr7NCYgpqKAAAAA//pyBKBtAAACFiHjaMFMrEPmXC0kInmIpMt7Q5haMQKZbA2BnZgAu1OSNztIg8objaW1Fwjw2/Tqen9YdIR2YRKvJ8z+5EAvfKiFhZYgmP0mOtKRITIFz3nZasYeJREr/ER3nv+S//iUAJMRpJrNkg8oDLvsMhkc8T/WJhHPky7QHhzNF/C8E7GQEgoylL/+5XR0MpbzUUBbQU+MPIkVfBbEQa1Hvq4l6j3+JUgijegYkUmCwYDKocOyTMsIubzrOUIu6To4eRf9/4q9EvKSgVI+HdFR1dS95kPuavMrc0GGkhut1WhApUF3GUor3b79P6wBXSwABBGAISorEH3ay5O5bKs7QiEPmEtUoVyUzNSYZTxMutqsbrfAdxsLixscNvrs+v21d3qsqpjJJpUXf/MSaYgpqKAAAAD/+nAE6BkAAAISNl/Qpj6MQwgbR2BHbgite4WkmKHxDhltXYCV4hAxsJekbdCQDiyVK7zuoT5KJmdP2df9/48ceGI/ZKJS2a6nZr7X+1FbdSrsycKn9CDTAozspq/bV9K/oVJn4qxp2kIAA8+/6CILhcaNdjr40tJu9jkKKUZLAnhEzXWj0Rnfqt/4nlC6o9f/9/1vqLGsrKaVCRv8xtf6eeX+so7Z+37vUjpCRUL0ib8jk1iYl/LavLbob2FprNXUu69V2TsNf+NbFxhHGGBYw116/m//ktt35S/R/965HSqv//Tf+23/1RvT1QWLTFB4CgTXU5HjCRTE72pJa+Pct4Eqn8zxpcR6Jd5qgNS/fD3Fh6HiANPf9/U2NPYSuZTh0WHkIN4r6P3wz+hsqn7s73amySYgpqKA//pwBExbAAiCCiHaugwoVEFmW0dF4gyInIlkbBUtkRIZa82RiagAYBrSkoTyo5TykJl0d81sKqYGLbRNn7pn21b+Ij8PjToMhrMYwi3uR2/qz0srr45Ex8wKVvnk697qiwBniEioowBYJjiggT5EIK1I+guc1M7yCiDsn0sYPcgJtk13Ri/b4nmIqKrTvT7bLL9yJnUIRzLLQXkYr9ZGDykp///umO13aAK22IWJpwSmWU8vfCKwvvNR1P2LsIsRn1q7a2nm9Lfwp8nHFpqRPO9RIKbNrWjQneChyGIlYs4QJ+5f///rI59iCFV5IAeJWYsTkwjrvlH4/LHOvY27eDTybAcFs4wqFxkXLbpEadhTbSgE2ACBKuVBq9tG1W/9vPv8f2X+YVLrR3P/+/U/2J1oTEFNRQAAAP/6cgSjewAAgghAXlGBKCxAY6sDZKNgCLUBZmw8oVETGW0dgwmCAGGpJZxNsL0AamwnmVAEfHH9KrSplq7UzMq/iDYKB5Tjjsdii/5r/XmI2inIy0xNuv9/7o58a8VhrMU7Eamf9uog6xbYZjGgYw+8xVgqex7RVKojZGhZAPcNlHmqXteF8OaXLz4FL6460q0qUWT0mYs1+6V3p6yDVOfbkH9n9CP9ACsZkpVjGWX3Ui7Vr7ONyCfODoB0o1au+qzs/9/4MKJCgAdhERNGscVVdS2aqftbi1P1///77qIsqNaDm36Piz7wySYWjkEGSOWlVctgWMbuVv7q7u6SPi5xEGadqrvyoDPP+/k34IrmYyDo2rPns11/KxtRk3RcByNqvvW5P0WBNat4tV6ZZU4LPTEFNRTMuOTc//pwBFdQAAiCFzPb0egTfD3D2sNoZ4YIQM1i54hvURONbB2ECYoAAPQRWkmxOVuaPSM2w7+vyd83bLCwsTN/uN1j7/mW/78mvDgIWcx2dfK9PSzN6/Z/qVB2iOJhwK+U+7tCotV1u7PUAKyaAIIocKQvbDKZqMSeZlsajETAD0St0j9trluhou10lDCAYVD5b9VPn4Q8sucUCzQgu3KdG7pff/qkk2EBMkckEdA9Hg+nKtSqNstuzcJhE1K0jMQS2vnWCNfqiiOpMO6YJpMhy3zzMqxl5+fqFn8XTlSmCP0p7nV//6//o1EBMicESpIlNnf65N77KvvZ6aaU3ExwJOjG6K7Y8wI9WZ9lXdMU86fABEmNBBwSMuF+3frD74QiG12tyiWK6F///rvvppTEFNRTMuOTcAAAAP/6cgQHOQAAAhIg1ZsmK7BDqCwNGGV5iGzNfaSIcbEQoGxdgRWyAGEODAEAtMzykjLZnKZe7diETNoHJFAl97ULA6Dod6klm5XXaoZ62YMTtihlyZSGMJxn/vh215T/llLcZZLd3//6wE0g7Y4/tNQZueXbL/ziA+SMJAgmG2Z9bWLpLuhy/jmxUSR1Zi3mMU+r/f2n9RBGOjYEfr71/vK1lExytGRzDx1eR9IJRYdkblultD2Q9JLTzzlw/tKEaJo45Fq7Sujl22qhUenFSVP0af1aqb6csQFDWqDB8UHOAZZ3RyRFoo49MUbvy//kwBAmyygFRDqQzA3alBVq8yv5kHlJNA0dHpWuMmrKRm51/HTB0FZDCqsZhXejXN/SUSZrCEil3IdOj1tG6eSeV41qk6lJiCmooAAA//pwBJdOAACCDzNb0SMTTEEmWypgZWmIzMlxRSRBsRQZLA2AleYBUbkVJE5BOEbdc4XLZZQAGiYV0iN1ey5joQIj/dX9yueDFVaWuV0Yiy9D6anPOszpsyxbVZ1fbiB39q5LLr6EfDIAAMgGJBNN+0FzpN3sxZqbsY4kNG8rCKZ29PuhT4sSXp+cMbRxosZ7qQtW//+T1L14t6fqw1op1g8tDlhA+B/Z6gIB6SVkcrB2vdHW07+egDZ5n4CjSpfudphkWrUH7vnckOzMZq7JvVUdrrfyuvtP2BhupOR8kKCgT3RmsGhxIkYfIrlAq/2ACJFIEh4NfCH72eorjlZrXhCAiZnhD+EsjliV1VhoP8TbKGoKhyjC1nV1aq2vv7O2syvsw0rVYxfdYtaWM6lDXWOWjPUpiCmooP/6cgSBJgAAgh4y3ekBFKw+JlrTYKN6iOS7faQMTPEFGWwo8wmSBKBCkaj2rtoofMOKH3G/gbfIocbZts6MuNkagFEjB2bEutQ9FsxX1WUoVDVu6enoRkUjviP37WC91/TFXS2qiSi3y7gDJFAAYAmWlg5FvF43thPXnqx9J8jbPSmUNEHudXJjGqjX+/vhBMcXMlGVqV0Y7yTq88vAC+yS7l4239NEPAlpFWVy/a7QrV6KFJeW4BReVMIOdrwnhm84P90LRJXjjkuaqpOW05bkQtt1t5uQGx6oExknKrOPtWqBHwOzaZcXXtll3m/rFgJWWUAP5RKNfvDTMRwyrJFyH2Eyx5PMSQMw0WLX2WyMl37/ClaOcxBohTyM93TtnyNmGXYOqlYqUDvp7vravorTEFNRTMuOTcAA//pwBERCAACCCjNXOeMrxEHGWyo8ZW2IkMtg5jyoUQQZrag3iU4IAJssgA2Xrw6nY72CsuT6moALmTdFQIl+d5DPNQZ23ynfwg2Aom5AmIsFMrDEXRHdcvRomHnWx2kTLAzSm0un+gAAGAVWywDZepts1VdwouHuYIE2eJ4TQLqagx/zM0Yre2Q6dJOgR/AcVGnUcY5xxFR/rs+mreiLRmoLej9VymDUagDBK2yhmZaFTJ6eo6nzz/yjBaEcA0cQud2tvjBl3OVd+57CbEw0REiiZxFzaO93V0crJS8vO7KyGV8RdbR9qtfbs//+o3QlbXIHGGAeBWLHnGityVXeSLDoo/uydXfk9cQ+w73I17UarK3cltDK3IV/ewVqnARnU2Fyrk3PKJuQ9snsjnmUxBTUUzLjk3AAAP/6cgQWKwAAAhkzWDU8QAxCQ9s6p4gBCMF3j7gTgBEYlvJ3BCACAML/VITGTDNIfEPWdsWGsaDhNlkCg3tdGpkOcrkQ7PuvFeeRkVSpt1O5UnoZe95We52q12cK1TWP2S9K/79/PNR/yABgqlvtEAOlhSxrwojNSrq9jdK9/HtOlmS73Ldyy32Rf4ou2dAA4bfU7D5QH35eGPgg6sH5//B/U4MbFAh6gQcIAwAAAAAABABABQKBQKRT//q//6J//2///tz//8fLkAcMZ//54oFhYmYXb///jg0IF1MMWNye2vp//xoNB9xLG5N88mNNKb1NoAACya3a7QWWCxCMRtHVf6dau+qtmo8vP3eZbFnQ5UPW39ufc/qnq7CPqC1zyADI59n8o68uaKPakp/KDUh+s1JAIBzw5MQQ//pwBMQwAAACGgNg7whgAD/A7ArjCAAI9C1zR5hlARwL7zT0DLIAEERtuTWtIwggo4k2TGgM0aIgqo0h4lIusOsue0OpNPKNIlbWsNSEGbgc7CsilT0xE39I1mSM1PZOrGrOKSzobvzLAACecusaa5hB1o1r7l4BDjRE6ONEHiUi6ROkUzTTycSQ6V9FkGcSeilKnpiJv6RrNBmp7IbWNWEVJY3Kt35ljAAi3idlrSYgfBrPrrAUtCSnYRualHxVaAMBGTG5QowUeusXeeGPcUlrKkGlg0PbqKhpp5ky3qe0KnQ1/363VnWHetwlqCrhKAAQEo5LY20oQ7FVbboWZFrgCkoWGNexjtZStEzTJIcyM2BAiKDyYXSLiYsoO3ukRFs9vgq4sr25FZYSgV3/5LJSvkluiKtyYP/6cgQmDQAAgiEZWtHpGMhAI+rSZwIMCBTVb0wgQfEOoGvdoIngAAGNJpJSUMwGETY4nESK4bGXBpxVJuXlTOUvClsaHLPh3CqXlUPcvA3PGhKdOwWzw5p1si2xepRYqEkWblkdqV865HUF//mI8a9B3AGCgVrTEnlgew/cDRAQyJyX6jpmcOVpVEpcSZW73rabuwl6PeUw2QUt9Sj1GlPf+ztqf9HZ///6gBinKUaKTdoOee+NI1h6gC3qhR+mfVzhCmSrux/NTm1butymrdrpVS3a/6W9Nm/aEO/jCPFrHq05vma/7b5R99hAF41fwqAOWPVdLbMM0Mmi1uNXpQ5ZQcv7iSAAmTg4Rxl/r3wyYbKhdf/2v/+P7f/3//6An/OPlDI+hibVM1VceT1CFMQU1FMy45NwAAAA//pwBDrvAAgCDBzXuw8QaELoC+0kInuIgHNYbTxhwQyb7CmDCYAAQIrQLhUuZ7FjVbWwn8sKh1rKYB8RqQFasEVDOttDNPffNTtg+oyxM4i1PNluL6Yzzcpfy2z+o2I0ffV1a9gatqCSIDkjc1rcp0RI78Njvz86e2KERO5lSjaQk+iL3wVBPRwz63Sy3znm70S7JRma7fqr6tSdv08N/NUn3aoHyPZk011BKtq2jjsfAhwFuhF0UxaQo99qQN5KzxybY7Hgtr7EjQEx8Iz3bPz83m4UaSfZ7yXJ+/yNKuPbtoTitd+6w1p7n+4/xOCAYAU9t/5JMn6v2g527VtVI3ybIet6KQBtVI1GXmorUm03W+OrUuci6p/7z/6ec3/tV9RL7tJ1x1VHUyz/v3PT3s6UxBTUUAAAAP/6cgQ55wAIghcfW1IJEFxDgbrXayIMCLxPVm0kTEEIlesNoYnYAAC4JVopMS0KBBHNXcntegFrGUoU7mIzG6U6sl13+R1ghasUWCMAkTVeJAj+kXU7oOTzEbybQOOp5D6dRzd9rNTr1gIBerW2Kh0TCNzwimFNKZPdfq+9IWzGh4xyvcFZajBSOEq0xM9boL20kGuyEob6M5+QlL+ha6ZZahYWXGe/zn1btikgCyOyiFaPuVKpi6o2VQshgi1FaWCiQpBypIF/Zxrspbug1XYHufKz0EDx80hovw34Ecs5Lf4/a9Syanjn6NXxf9+oY56KQFXXbRGnGyKVTXrNSPx+N7cyQS9IUrNzlvJNy1oWQ/dbD/S62U+r7qzSI3/+vR9Rg+oHEi/i8R3/YHk1bDTKrv/9yYgpqKAA//pwBPaeAAACE0DfaOMVPELFywph5QsIhEda7LxhkQAgb/SBid4BEkpyy32uXBcOdrFXe+N2q++j19NTzBsSUjpZgXqT6CK5OGJyp/pdi/StuAov//ptb/XQf8Diy2Kt55S9ZGguZdJAAEWkdbJcO3EuoYyxsvX8bEPcEgQJZgc2zodimrOEzu7+26ttp1HSoRDo9Lu/vP/Kjti1PWk8o8I9OhP96fp7l/t0ABJEabiKvKBpkzvjAL6L+C9aIMIAlVvZ8xA6pXcgXyJhQGUcMyts2LAAKoa/qJK24V77Dsso+6kkub/Q5qEVEHZdSfrCbaNlll2stwZVvenfvgJDpgTVYXk3aZhRdhkl9aVYTkZatek3u1l1Vjt/bqZem/r8+ifyVoFfuRMf3Nrn/lb6ExBTUUzLjk3AAP/6cgSP9AAAAho4V1MPEGhBBqr3YCJ1COVrfaMMQ/EXoK2oxAh+AADQB+120RZGhE9g6jFsIeuITfSQonLxFgqKGqgOvuDRk6baUyIsxruhk0R/9f8qPyXp+r02gqeRayeRZRdp10e/5kBRS+kuopdLJj0gx3QU+uTnZollSZzl0ptmjqbQwIutUW3R92eFWZ6KvR8reVv1Ty/yfEua5ZH4u9lmf81Tea/7AQSw9NLPtbtA7d6EO7P3ycZAZnUs2qQr1SjO6+uvVV0erKe95a0/V0Z+DK9W/XJW7qaq92d7mT9v+j2S7Lul6auTe//Be3KgIFem7I5AaDeLbhnvfwHBRlPetURORA8zAZXr67b5Sbhl5Sqac9VR66090PvM7XbVaLHdGVarpS6KpHgxRzTdmDhPrtVF0xBA//pwBJegAAACDi5Y0wkZrEKoC3o9AhuIUQNtRIxMsRGc6o2BidAAAEilGykhhDrSim5SrasmMdXErcNPIYsskjpDIVkzlnZ/gHzvVNHhd0y72esKf35DPYIxCPfNo9yEOZf+76N5b6ApSvTdkcgIA+ZcU70u34aYXGNmLaXUbKj0Vnnf21NodHRm0pW/r/TN511TR/E9CQZLPul2sYO8wTCSx7tCOkbQwUMgAjcW7I5GCR5T9QaPQ+6kB0rHPNFMat2SiZh0apehdVJIIzWY/W3e/8tX9W0XP6X1I/8ikRqFjSguNqGN+o+lwr/WEPtvwaZEWFTu/MWI3SxLJ7cbAjGTlp6Z7W1GdLkZUbDPrczr99HwjkVFTyqlKNe3+TxBF3/eq0RajX1oycWTV+p/ioXTEFNRQAAAAP/6cgSK5QAMwg8T1RsvEdA/xrqzZMJiCHC5VGwkTIEUCOlNnRhoBO/38C+6LCxoxfWVRlBg4Yy9SCDHFDO9S1fLK7tfiXXdkCbjxV9M+0eeNbTgOvJg052ZyZcP+y2/J3LK3N/9P1/WEf//wF51AU6mTZzEAX4/qH6aDRmVXuggkvn2KPUirVZyaqn+bXkdh3ZdfXVZkdvbdtMna2uCRZZfVyf13X/TUAePx4PRXu7z20Sq5VahYtzljKZLktuSB8FluQLMbtMljC8z71S/8tLGdqEKWn//u7GLZFFxmpS1SYPNR//fzeTtT/YAJJJCNoFOZuFIsuw4aMj+J6QG17FnphLoc3lFRCozzcQwGGDMUWJuQc4H4hrbHuCgu1En6VqVKVN3d9Nzu9Kf7tQv//UmIKaimZccm4AA//pwBLRIAAACGVtc6QET3EJIG70gInmInNVtRKCmsQyOat2BieIABElOuPayShMq1qE8GReMA4zzXIw2TLEwwSvIJFwb4JLsl2TOQlrqekhb/5H9d277+y7r+9Xyr9v/o/Wmv/t/gm8KAkFF6Ryfa2gSMb3MU/VQobRy4maczT7MWntfTKuDIcp1ft5Ud3mRqv3byVfXTudlQ9EZSvVnfR5x01M3hRbE6rn9SAwvpvWyRiOZX0kB5o3eMH1dH1i2k+yZt3tlTjclIQB6WU2hdFSzsVS/dTPyv00spkFVSZMFBpJ+XuY1596upe5TbBX6ACAlySQKr0yEbqTj6O21GdxwsZvQRbvU8GKrpS0p5ECOl4ZtyvOubqN+X3Gp1KNRkisQJPHRpSCG1Q1lG+lGu7foqamIKaigAP/6cATaQgAAAhYc2VGBE5xD45rqPwJTCHSDa1SSgDEVhO62liACAEBpFWRtlejM48XGIMmJvtwOvT76aEjRETyqAvX/w2ae46TyHliDSoWFXWqeSLjxodtYw1Jqu16S0MOc2nLJR2dnrAACgo61yVXoahTXZmHvBUXtroiIk1j2Mmte6MmwaERnX7++TnGc63B/ygP1wG0f8QOKBhXLn05RxyIFg4c7UOosdOdYAQ/tvWRiEO0++FAab89sFviaJ0CAjnccjZ5wGTWlWXctbEij3UrkGFQHHtFg+4WdQu7WLDkrC4huGupUv67//+3EpsAgoKxyWyNptpZ0pq3PbMVfpCywYDZ9qEPMscKlHh9AOOeJ3g+CBeCGs+cBCGEg4J0fB8+IFvl5c2+71ODP1n/yjvIeIHJiCmj/+nIE0UIAAAIiW99uCEACRIcMTcCUAIhcuX28YYARDZct95IgAAAAAAAAAKBQKAwIBQKL1RBVomqkn///7//mVz//PJMT/+zOUdj62/+UwcMUOojmt//wNnRA4sOhhH/v//xYQhzueB5jwSQABbbRLbZa3C2Qw28cEvuGWVa9n+3Z2vu5mfFlFj9n6JD5xCMb6dkyIPFQYVPr+nJlGHEhcNU/5dVtX+z3s2z+uVagsgtO23WNpJPCVdis393CUmqWfa8hvGcy5CdB91+FDVSrGuW1L1///6Tfb7LPrDueqmpk6Rtb+IwW4aDX2d30yLLcYAACLdr/Yi5JMn33BR++/1hZDD5HpY1UXRf6t2dLGU7era/tmsi/VjdB3acSZ0ijUBWK4bw7CZ2sWH1B3bUeeZwrTU9MQU1FAP/6cAQ2jAAAAfA32+ihHVxDCAtdICO7CNlrZ0YYRrERpC/0IJ3+AABAjbbiIAKMHkwkGD6YSSj1RTWj3ndyBOvfvszCiKeFT/8QovF9HhXn81jFB69Z1K2REjzy3Ker/ETdn5EACAT23X1lzDA5IM2Ay2e/D8EWofe39TaL4wdb3nX/xZr+Ff75C/L9YV/h5Pn9qln0ErO8GrZayeXsrc182LNTOnoiAADlMxolNZU8d/rjEP47i7lFEmkRbttzvQrKYn20793D16Nt23p1KnyL/8N3Rzub119EM6eSn0bbR16Eu+lUdeb1g33FK6iCWg7NLvbLddtQTD2wfYcxc5mZ1T2vuJFAsnbFXP/W/Y35pC+Zt9HztDke3ZUdVEA4cc/ZE55cjgOaTHVv0pyEX4vFTKYgpqKAAAD/+nIEyJkAAAIZXl/oYiz+Q8gbKjDFYoi9a29EBEz4+YStaJCkRomEm9pd/Y5M7LzpD5+ATogcmN2Ov2bGufc895DsgVDqI/q3f/U//9Nm/2H77/VJ/J29f6apZvs+1v/V/Z32UNPvnWsACG6czLcmk4npOqfjG9f3AVj+piL2n1U5I0a3kdrq6urcPlyEMkcDMYacn/q//7f/+0/T/8Qb8W0IdpRes/TfUupPJAAh+5K2UoNs+qwyt7eUuF92byd1AmsrECJvdKuyIvIbVu/0bR/h15kC7I/8c3Rr/6Wzsnf+3vev6vRfv673SCQeTY5f82ABD/LUaBTt48rIH0LWVXTNzbJBcuOWqF1tSIRJbcjRYQZdkFhn1l0T31m7O6Xc/2GXpe1l8MZPpa6Joo8UzqYgpqKZlxybgP/6cASvWgAAAg8oXWjCGfxEQ0qTYeI0B/BHdaCgYzEPly30YYmmIJRDkjs1Zbhb/dcSe8bD4Q5XY7a23pB9J9z4f/r2KZ8IN0rIzfFZ8GJZsqfx6fRnWdaZVtrqNJHZQg3sX5NFKK8mEoyI5SspQMYNL5cMdSLZ51C2yhsgiilFtO5LP1dIQG7Nb+hcPSMQSV9hcPdlBL0Lcsj6w61WdEbcXbbVVTq0UN0EWcwQwghLJJpE5DSTLLoz+FX8y6j36/aawI8lbemeYSU4wwZ0jhY/swUJAn67FDs2XUhP8WEIdKLdSC7krSz19/EQABAUjcWaLceEVezR7bf4IvxDdZef5SGwgW89D/9OhRbMcEMifX33/t4/5TYnTDZ4a94qZcssdonMt4qq0NILNlmHcWTEFNRTMuOTcAD/+nIEjeoAAAInXtlRIRN8Qwb7rRgidYiRbW2jDEyxERcsqPSI1gAAeSVSJLgwjRugkTu6V0AyUZdizHxikSmvXg1zkIVoDEv9q3+cI3AydPbmMrUzIT760Bd1r+//r+ifr7v2eFplg86gTAIQiSx3aNOXwvZkpcP34F9g8btn9AwaPbOVe5DUEiHJmPvX/7Vb9WfVv/7vxK39ZUWamvLpVQmg/PPEcidphPbPz1QBAAKrbWjScaUiroq1Yi3Fv4icVTFqK2YEy22av678xzLVoZkRvvVCkdfb4I6/N2Q3S0ZF/0oCf/+nVP/00zfWneCcjQAIVRarRKcB+rmTtQ9r0wzKxEegT6rtrUmidGI707ZuQ4OgIr7WTXuh6fL6CSZFqtblPS1vIr3e4u5jdSA7OXPRXFFoSmIKaP/6cAS/kQAAgeAS0gsGS5RDCCrtPCJ9CRVra0MMTXEUG+10kYneGVbSPZkAQHYlaKqH9IkSwpO3d/g8AtK8zBBVI4HFbCfa/YDJTIqOzY+qco9Tv9uGu7JUDH5dCrP7///qAAAAMVq9atySWykP+NOJEYtZp4PL4bWbR82mjlMiEIRzKb/WvYcn3r/nG/VvX+3yNWXb+zOlUHspu2dGrarfw41K6wQAvUekTcZJE5WNiPQbg2ePxX7wikDhPMjjHQeU5daRAkEQzPJmXL+5vyo90A52RP3tvM19el60RPrVNt81vrpprTb/4dwyv2AyRx6NtztKpRVRjsbqXRC24k+S/TMWvEIiJnDOXZdO/cXUspDIdP/VD/Y3hk/P0hTuiiguVAlCs2UYzb+c3Pr1bC91nKJiCmooAAD/+nIEk1cAAYISWtnRARX8Q0I6QmNGGggFAWejBHdxEKCs6LCKVggBpSdjTbgRhHFS40HMTMge8OdWR/Uf9pN115frKcB6LJyiO6sRmfyNzZF0j+UzKkYMlJrhNhb7RFp9KpP/PH//4MT5zJAjwifwgHKloBV+DiqcLUlCGGrAmFxjSWmdFYNsJhX1jKivh2cwAij1ecpp5JPF+B8Fb3stPUXOy2R+j//q69ziCQAYmm5C7ocl+QjjmYAVjoMRJIf431pjKL3fO2H4tSsXL8jrajoviBzH0W/mX6vldcjodh5Luuch8D9tyUO8yP5csZbasoG1pC0+s57sFT/Jp7FqfqEGN5kryRP0oHRkR9jOr9nU10Jrb83k9P9W+rX7IqFvQdyqGLejMScXJiyLDn5FMQU1FMy45NwAAP/6cAT4VQAAAhBA2VEjFCxCqBvNJMIviL0DY0SETvEXjm50EwimBAD5N1tNpM8ZFjFbCOGL4qd6Z9lWbL5+tNQ49l1UR5amr1S6yJT9dP9Ttr0vt2rrFb/q3w+aPT+H3n0HZEgJ6aPqKIKM212+0t14LGcnO59ni19gD7BtvHPVLl6SzjJqtB9XF6dxt5/1m+S36iHvHfYxP7+2371toPNdXUjZbpcvx17vQEAHQcjabeGFxOmlaUMXgmB/9PjCm3rZyuxX2E2sZ0YyK51vT+f0ev6Ef02X//1d/mOiHRAZReRpUJEpFLRcV0XjCGPlnIAIJDcrt9ttsA3CUvMz80PlJbM6wehyaK0yWJflJl6iToIlHJZQUgTplRKlq0tKBNQqdteUC7hoM3glepOy9i0mADS5XRMpiCD/+nIETuIAAAIaW1lQwRP8Q6a7bSAieYh4uW+hhHgxFAaqDPyMnAgBvClkbbKRHABMm7XtWwjP01kgiBkzOV69ztY45g3DdEd6gzoq5l1IIydn9XItLqRUfq1Goe3ZL7/fb7/brfb/w/oAAJCUbk9skcKcljAxZtKuEgbrH5QAQXmjZnldufbDccSMOajC5E39Hrbu8A6kKu33qBJIoDC61scCRSrqPVLVxlb/1gJEl2t2fWSSVA4ReXUsWUBhNIrngi/wZmQ+5FGsnWcurtDpv1qZNmleKnV/2P4ONXiyYTcHSqNJAhPZCh+csOv9jfyZJ1kkBZGeCsHOdjOKhL8hFaBqPIRxMSDuAB0YYjYI9ABnWpFNUpQ49tZeaSwKNrcwysq9imGDpR5ADilLKnvfxRyF/TiiYgpqKP/6cAQ2DQAIEh5bVTnnEwhBi2r6PCJ5iKVrXPTBADERjS12jDAGACU/dbLAPI4RTl22W6K7tzbwp2fBjza7IkwerDovWqNn9a5O1qV2/L7Koo65ld/+yo+izJ6v2SR+nvt/X//v/6dwhqgABZKdbSTkZkNXoL1jSjL6flE63pnBaHl6J+coCfNwPlwTVkvZf0kK275NUZkfzey6XpU1///X/Xv/9P9qf8Fwwk5TjaSWlotAjG9nXmjlDBBlipKrSrUw7UdZ9HozRGSis0m7XayVZW2Yre93un0Rlrdw1t9nrW1aU1r6vdOv/2/V+z/+GUAQAG3HLW9B53ReZ8/OGEEQB6EcN9TRATeRFlZBe8ESUS8LHxYIg4CDk9TgcOPwQd7R4XlDjUsX9vlBB0wQyFOCDkdvoTEFNRT/+nIEV7YAAAIlJtjWMGAEQ6NbrcEMAIiNd4h4A4AA8aKwiwJQAgAAAOv5JrbXawIACoN4kEl0WxWrBJagJt2oTM8sKIkqXdWyFPnE5o/wxafd8RH1TR/9kgQJFw2lcJYfrOHte6b//qS82QAAAG25LbtbRZZBJbaEHSdGlvA4iBYkIiuZtXkWXR8jbgZWWuII/HLi9dmhYZ383itvT+pWyfX1PbmBZyFW8rc6Kpp/H4/H4/H4/////fzG/fz0OU07+5hg3JzHEdAyYf/mGc893Hi4hGovVjv+e+YyGajQ4w40u1jz//vzG+eflDzmPopzLKeGeeeeeX85X/////f0b/50NKn+QgfPIoTICof/ITnO5hIHCIiLqQn/OfIzkzigUWFBJ+nlIng2KGzxppxMQU1FMy45NwAAAP/6cAS/hgAAAiYK3O8gQARC64ut4YgAiGUDZ0SMVhETIGyocIsiARLSjbraJJOlvCk6xtAKGvE0oVrC2gs4OOLIklrBY8qdERamsJHssmVDPlSoIywGfK4atrMlaQaPWeebK9dblPOhrFRYEpMJ22tolJ6V8oz5XCmcV6VI4dtxlqzlQtLsv/Nvlaif8vX8z9SP+nlJ5nM/95S6t/9zP0fum3K3/6PL0RxIKkqs8AE38zjSSVReSRpVp3y0hNuoFdkpV1lbn35lJHqiOmJa9v2l6X0/9DKX3b1TLoX7GWolkdf1zYNq09Z1ySre9fkf+IgAhqdsiKTQiHjh48UtMxWMyis5/cq3LK6I9lbNJG2YTiFYIVW8iYzRwsyEf2Hw8K19PMMv9WmoDZERe7t7/kaTteMcWrTEFND/+nIEd/oAAAIcGNlQyCo8QugKpzHlUgiNe2NEjE1REDFtdIGJtgBRvUjRBKZyAPFwSVT8AbWx8s1UOjvmVkRoy5lSrUAMkMEpzPscQ7E85pMv8G+OdSsqMBU4FKbR49DSiMhc3+pkab6wQOSRJyDUKwOBKIC/sPoNs3guQn9dN5V3W9GlS9C3/ilm/aa3v25qP7/prk/06u6Pf9bUCw0ylqUkdxxLb6P6ZeL9QAQXuyNJuU0Sh5tUYIo6lOgo3uK8LUIzndgZeW+RIzVsJ6Ivs1G0/8//9e3+UV2/0ets9Le39dkt/f0X/q/vehIglNA8AIAFxqWIgJwPNaVfX/BwTlWfkkPLoK07PBr53eYQLDdi39n//6j/p6Dt+//k2//h//9n5CWr970Q1T/3sla7FOyJ4JUxBTUUAP/6cAS9ywAAAh433GjBK7w96AtKLCJsiLyvW0eET8EcBqqo9AmIAQSSdburRSf3TUOUzbPYPHdWBgNn7NTypIne4DllLKLe69UT9eZ/r7U2v+w/WJjh/UPmaEb3WEUrxMs9HvdvrHWmLagIh+dlrUkkuP1cTCnE4pRMYEYVmshm551Mfk8v50NrqzZmOhFBf29L6f9tG6f2lxntceoIkt729OL9PLVuUAAF7jlitzXHVxcrNhVHQq+7tkusHHdTJs0bZjIaJZfX/k/i/viCph/CHzBkLeGpNXcLrhxEBuswF9wSdVexdzh75q1YsMAADQWtkuVMo8cRe1FCgZPeJNqQNYrJUAj0SLPg3KCz2KLGtQxFq7b/QKkteXmOpblHqeHa3Mu0qYWbW5RHoua9B4UStTdg5MQU1FD/+nIE8CgAAAIJEdKLDxmwRCXbjRRieYjVe32ghE3xHS9r9PCJvHjZivwaQGdbC5S+gig20JHoZagPBDrphcq+WxX6YmlhpD+LM+1k00JPx2bEQr5eSUp+XRIau9961Pz/6HVY1lKlgFlh217VopxWHEFVuSuFDpAtjRzLWHWcFyfYWGZO0xFfdraoya+3bf9W8Q6PmZe/aVQlxHTlyxWVfmxe6fyQzXpUxICIQLSv1/8sk1WRmnPGtnbSYbMRpQYkUVmrHbZNVO0cy/9enCmbUIdXpvd3medT1FJ93WeqiM2b6u/9P+r36+ir80EyFYE0NgAgAyR/esu+CjHss9b4j7n9FsrZCNoSyGuVnm8dclh7+L6fW8tvhb6HWzf8yc2+n9ame/T9ktWzmp1Wh+3M/9EqhFkhKz0IgP/6cASeRAAIghla2+jBEaxBhcp2YMJiCE1ra7RigDEQoGkGsCACAIACtj1sZTjYtCZF4OLTqOzALxMIOu6adVQlbVT1VvXqdZfRmlT86toAtf2+nVdr/pWoMT//Vb31/9/N9HNq0OZ9lABC/q+GFEES3KeePZWHFp4cw0SXKIwUPh61ko757A+r9Pj76aPSb3T9qv/foKQ9pqwXcVaI2+0p/ahFtilov/1rQTHHbWklGeCbHAer+fgTd0BeMNSgOXRKo0yIrX7vrMnX+N/6tr7P4s/1fvUup4ge7aNa3JTp/6f//r/q2uImwtYpiXHR0QmptJirCS+HJxKqAmIytnY5dPmcpoQqhRT4Qd3vglfd6N6G27b0M3X/1b9U6mT6v8jTU2X/dNBqrtS9PucilrvHpiCmooAAAAD/+nAEhysAAAIZJNuuPSAAQgSLZce8AAiwV2DdkwABGAEx94QgBgAAskgIcZOD8G+BieTkHQpfLc8mIPcxnzcAEJlS0JtuFhA3efL2aY601VpQzw5YyYQrRqUc8P9pDsZIn137gbGf+3QAAFkABDudg/BJwDLVgkZpK0fSooQuOWquc4BQOT1TRH8eZNJCNmn97x4apbn284xr08J6yPba+P/T/4e7my+3+gsAIBK8aOOuk7q64mg4nS6smou4Rrt/KljTSw3yar4z49W3lUy8qcDQVnomVYpqkD0zLR4RAZcJGBFciyyJXPNuS7vd669QBKrl2t2223qNKBpwEW8JMBkGw8aEY0uE1FQ2hwo8KGCr19bgjeg2q8WexzMTqLGZofYOS+7sJi7Wmt9xCQadbdYiQ2KXQmII//pyBL0YAACCFyVXCy8Y0EOhu01gwxkIyEV7pgxgMP+IqqWnjGADjEUPbcBul9D3WSgTZxKllTu0xFrVmI3ZmKe0NnIzjkUfLYyUVE9S/cgmmdSy5Bnph9zWHVBLegfMRMgmmrXQxtvUAAAGVE44y3EbDQkSS+gvJJJI5PMH+PD2nGHNhQimaGPGEQVOBJe05lQTQeqTcqsKsX5CKzj62VBZEv0Ks3Wmvq9vuoBIiT1tkkabpWD0ZdG2czosuiCZ/1OkmwgUxcKtPEsCjOsNHnhoKA0qws1JU7K9qnlWzxXqDp1jVG/qw1/yanmbQaBUlUysAlqC8xcg8SFSL+QkMQ5ROEfDlOFqV1iTZ+LL8KDbCt4aTeKDceGlQ1DtflXUflc8V6g6dFTv/kvFM8gnpyJUkmIKaigAAAD/+nAEVD0ACAITEFObjxhgQcb73TxiBYhoe12ssEGhDiBw9FCLHgCWnJACFjhYJCKQDkMgPoCzViNR44iKx8NRNbkDPAnDGJJAwoxSAGHschCXVLatiqBKfdLG9q/TnSPzyDzkf/9/8mEkmppZLrZbrEXiSRGd5ZOLc4V80j5THQ7Xo82l6VK/YsNmfVtxO0qaN16GR5f3o76jJPbQVLKEmJbtrv11Lfr1dwAjKVluyFXwlYD4Y0Trxa5G800KI/gfXQQ71YXK706MyH/zLVTvUS5Yjz0PvuaHjoufTupFGEnah6d1QHd8B1Uo7P1ByVm7+/fff8aLB+eQhSPpqhUFWdXOVqOT6iATezuZinJaWEbgB3p7ddBAESyGBtl/hvbZN7ylcmBlRnX0XJ17Xuxf1JiCmopmXHJu//pyBESlAACCEglVm0w5qEEjSjFzCQoIqW15pYRR8Q6G6mW3jDQENSSUZqjU6aTPnX1WW3o6VJlFYVrKh4KLcoLuBwsiXP95RKqwaSZdgqle1gotAWH2vQiigrKsp06rH+zfp/SHNHoBgCycrT5zkjk+ijcTR4Z01lmEah4zkI8aD45KYLCrznV0w4hIUQpT34kt5v25393stHXvVe6fSafGCrqjKOhWcQCQU5LJLpbbgrMzrOJ287jV+85tmIAiZ8T1xuWlWILYZxo0BjF+Gj8tkz8F/rMhxnrdHZ0qy299rtaXtf2b/r/+2/hy/1gQB3/BeLEksUBdnZPEmaCriMsNjICL28JUzCgNJR8xOgs8sbvBkWXgcGpAkhdpIJhSSbrLB6Xd1gjGu1os1e+1H+760xBTUUAAAAD/+nAEf/oAAAICDlKVbMAARGFKuq0MAQjQYX+40ZIRFYiu9xowAgG/ILcYCz3rMJBWYoPCADdZLicZM/s0h2fqc04uqQvDqFOcOhY/h04wzEpJFaRj2nbAOHdBFLaDfv6P9ln///tAAAJEtuSUUrjzp4Xvi0PRmGJXYz3E4beTlSvAZYsWWhqjrUvYnKtoBCNes4PCBcl0Bqm6PUt8YBbShqw+jN/fp/rr8NgAAABJt2vSa37TabQCh8WA4Swl6mLr66HPUz5QTnXsFKKy7qcK4Sfahzxc8kyxUq9Q8FhqmmN8kNa1KqqHdlFFl3u///6UgAAACIxyy23bfz9/wCDUiG6iMGm1d6Mwp1U8+amUMyFuMUkS73mYhUgmoTg7gMWqOgHM03wBe+F+h3j88LPuRQh3///SlMQQ//pyBOQ7AAACDAzi7wigDEGCHF3hlAGI4J+HoZxtsQ6NsrQwno4JsxOSyuIgl3Q41nPe7WepwdcRNrChBBCp5Kt9b3rIlhdjeU4hwS/D0opzqSipkrXwOdcr4pRdLDXEVNKsMyKwkPDbMSllriIJecYa0zzpqeepwdqB0fq9BwOgxU8lW+NeaWRSJflOIcEvw9KKc6koqZK18Dud+Kd0s5xFTSrDMisJDwoA3HbItGUmC1xDdbKjzhhLA844SwpnP0bXr5nO6haoUByNaUObMzHRJaoGslfOyo2tT+8XWRLEkppLEC2ViLpXcgit1Z3sEcMd2129jksyYaJT+nmrRVNeIzZRoHktizaghEjKF1hNYK1ndQNPO6n1uTK4abaR6VnRZ4Vc/NnnHs6p/nSsY8lgr1JiCmooAAD/+nAEAMkAAAIOQN1o4RasQWgcPQzCcYis12ZnnK2RB6PvNGQIdgAAQgYSVGUoBww5rZUWWUhoJbY36ahss9fbV++gk9eX/U6qRqfwpcQ8P/Y2gqj/p0qCFITnup//7Cw9YKvdPCISqBILU0rkurl0Lg30VlUzo1Y0IzF8Vzc7avrwYnTeTp/Po1uq+pfNy/+bQ1P6dKoOjv6g6VUtbnqqryz1iV6lvLFUkiWSWivl5tGaK3gChteRQ1tKcATnNm8q+rZUv/DXaeDtib66NRnShnt5vymb/3F48ADnWLxHfR1NaQ54g8Vo9CykYGJWoAgESFhiSOSg6tKNnJTrqLo1JKBFMnAevU+Uf9X78D6/b/p9qNwY9FYn/6Wur/deoQXpY7d1MJukKu8g1n3PeMZyaYgpqKZlxybg//pyBAGuAAACFDXgbQjgDEJoHA2hlAGIiXeOeBUAERau8I8EcAIIgssqWP2OTBXUjaLcw/V8/jt5R5gsDZ55ZcTku+os49JKVaw1LmP29fX9V+m7f5U6lXeuh11PVFPT/vqFVKE8TUjAGQhG44rbJcFPlR6N85hKeD8H4ebZ9g3R9ONFGqmoz/v6U4/vv2Gijk2p+nOPa1//IHD/irIIMHdMgtnetSkwzYosABWKhQKBQ+v/////////75h576/88eGGEA8M0b/8xR+Lwvzi5A3//+aK6E5GUBWotj0Fv////G5cqcA2LQ0IyecFwDQABAIRAIBAO5CDFWVkv/0///////vmHn//zyBhg4QM7f/mKTKg/OLjjf//5o3QmPjgJqNxqA//0//4vJKgBY2Fg+TnAsCRMQU1FAD/+nAE6WkAAAIDDN5vCEAAQMMsDeGUAQis2XlBKFERAZsuqFOJ6gEBAW685CAAZqFWoqVhufQDLgaITLOUNDhUtucwmxps9fKsFSy2rdZ/V5EO/qB01sOuiIrQ+wWJUrwVKugXSdGJsS13TX/IABiMELfgOH9G06APuB107tRer9qBQdDShUCGiJZCQFCSiQdF5Kr/Z4Gf+RDbqiqKjzZmpYq6/Rbtx4o1XPS2NpBWYw+pLAgMNgBcA4Xj66q2IwsOaJA/IiZTdwV6ctJnVW1K1e3m5Sob/UrKX5gIBcN/qDoBTiL/lXVKPOriKeADZuN2xpII5g1ph9yvYYBdRVwk4+2aaqgsL4pL6NiYlpyjvM9S5St9vNylQ3O3lZS/MBGZGG/570/8q6pR51csmIKaimZccm4AAAAA//pyBI3wAAACHkDf6KE3LEEjqxo9ZyiIrW15VGKAMRKQrraMUAZkIROOpP2y3D0o+VrHBjsgW9w+2DM8EH/jG7/qBOe0O9R60b/Od/TWRy+vxy9/yHvszOPUHUOlyDowpbtdofdQgc6TpAAAIESNyRXtU1xtpIiWEq1aD/VjNegBLYl1caO1eIDNhnTlCHL6jSWHIYYfWvw7E1HlnKaIvigqM25p2z0f+ygqIlXbL9jlsdnX/GfSxinsBbYvDvCTaNhJu/bQI8QjRcXd1Eh6sMHP/fT/bUWpfv9OibX63StEFt+39Eo+9d2rO3mb/8Y6AACgSqktG5Lmdw9s9doye5DMG1FKDGdpHRA0E0H/QIB16kswdHMMHJQIMVpW/vkuXouLMEdibxIXLbO8nvq9969U8tPemIKaigD/+nAEy4cAAAIJZVwGGKAAQUyrocMUAIi4K3u8UQABHAzwd5AwArJMR4/aLZ4QGojmDNGK7D1yW/+3/9bJ/+vdP/9ipFHb//9Ti4gOMi///n+UeRhgkiuAH//vv/8OCYsBhwohXUXHAktowkRofLJUm0F3ToiLo6f+jf37+T1//690//2KkUdv//1OLiA4yL//+f5R5GGCSK4Af//3/9xQJmDw4UQrqPHAslhy7WSMgC6CJjPeVH3B2w6C8QjgdN3ZWse4wGlCy9kN1sKywTDVa7L80iWFgLr8MoqHBd1mB2NFTOBg1F3BNSQIyUF1oJxpyS1xtFF65aD1Zlx/dhvJgOlTP7wwE3IBFHtlrPorVBVQstlluxcsEw1rsvzSJYWAv8M9QHc4iKwbYLCEBhWBvCeUygumIKaA//pyBEJOAAACEhlbUMUzRELDK4oIxxqILLlzoojwsQ8gao2HnKhBlBjS0kAKT4tBq5j650dQE4h14S4Q4wdB05pFD/uEcu4RSLcqMes7DT3KfyriJZ2dEx78kIfJK8S1DH1hIDHvluSRVG5NxtkmkGo6bb8to0sE3HM4hx7hRseL9tGxOPRQyDY0BSJLKjHrOw1GKfxK4RFudEx78kIfJK8S1KfWEgMe+W4aQBSBKgqlrkoieIhmw1SW0CO4T5OHGwzYIHhBJHZsTAC9f9u+up7LM7c3pKxIxfdPo8697s9rFWvR/PzQUNcM9zGAB7XbQdI5Ki6REW24Kc8XjjUDwKdtSAfZMWYdYTLhXNAHGFlS/bRsTiPoM6j3TrRl9v//HFSzf0+ZVFT7fKv/p//I9SYgpqKZlxybgAD/+nAEGDQAAAIaK9rVIOAEQQPrOqScAIi9lYR4FQARHLKvTwZwAgAgHCM229EtS4MVNCfUh53Bd4m79WVR8tlC3/nBN0vKvq2rv2znn/eUIrUwRidRpiilqGuJ+BNvFL6yL3sFECoqlnqAABoM3W7CL7LhA9Khz6oruUE9odyLYmtHdRwN3Ktpyof81Ra2P0Gxz0pAdueidjD3Tc4lqhoHFhRVzscj2VdYo8AAQCgUCgWd156v/////////MPP///C8HhIhhn//48MsQCwIsRZP///5OQEjSQuYYXC4/////C8JCNwBYFMQ4zC/J2EGDWAAGBAIBAJlitHlJM0OnP//99G6evv//zL///g8GhBDG///GhmOEBLG5f///yY4WaY5hhMRP////wkID7gBgFiWKwfkzBWDtMA//pyBDS6AAACFlZingVABEPKzFPAKACIjGdvvIKAARCMrveMcAIAQCAQCAQDusv///////+eRs5zf/kJp549Vf/8jYjGg+iwMRv//+cTDcejIQAslBwWw2//9fkoXo8EUKAvziEpguj8AQCgUCgUD//////89bnN/+PSEjJxZVf/8ZmCuJg+cQgxE///8fEwhxZGQUAXowFAtge///8eg0iwDcFkGsoQi6wSRXQQDKlaqlJAAyICYauwa3jfkUYsRKWBXz8T6CpSlfV9AXqDsFcseFTsClZZ/5bGjXaSP8GgV1naes7IMg0sKhryQldLVkohBJ0RyJFHwxQSJfr9zj9k/nci5pxOlOpE0376hk6ix4lOhoOllArInWw7/PSpJvHP/LAy7K4/iWWBYXLB0TCV3w1sTEFNRQD/+nAEyE4AAAIdHVc57FEwRCOrzQxFZ4gkuW9UkoAxBxCq6p6wAACADbaur24gyiHyMAsHOvb9H4xOuPuIJsheoMjfIyf9Ds4Fb5vJ63Ft3ypav+ZFl5YJu+Vihr//xQ8sBWEQk8qROtCrKARSfMetkcCDcwnR+RbzcvAsS4MNAdsoPjR+r41dD3YWlXk3d7HDgKmPD23mQkKsqFzPYoCiooazH/sdCj6bJ2si5r4A1VANtkko1Rwf1JIfyP8oeWZeN6ccD6i/9saAnNIwKLvZtnZbVVn/nnPVY5wQsxMeQBM0dWL8/lGIR9zsWov8OAAAGAL/+AXRdwRoGWc0wLsWyOfTUWsdzlial46q2Dpe9hw+gwAEQb9x76P/3yVjoZWv9f6X51yehvJLYMjPd/Z/SmIKaimZccm4//pwBE1wAAACI1Bc1iSgAEDp+5fDFACI3QFxPJEAAQYgLhuMIAAABioAAFAQBgMDgPosHZE5yZZ4fy7rr6i1Zno1GjHNmHZz9fTs1v//t//6EYUJ///ni6Nb///5hSJgODnO5A5//0OnAwAkEAKBsdkAwFa/nLEokHFJ7yWn9dyXpjNHZLqu/L7+Tn///qn9OhGITt+3/PA6NJ///8xJw+LnO5BD//gCCBRyYAAWBoFvkbNcQISSj3uFeZtoPQrSNoCZMf9OHbXLXVts1W6tdnX0L46rZ6/mLzUKjr3lzKGe1zOKNXZpW3Fd+dYICqmlZYfAMmgWfXO3BCQSyD5m914fQbT3ZJR+mjUiW8tdW2zbdWuz/Qvjqtnr+YvNQt/e2ZQz22cRNX6VtxXfnWCAqppWoKpiCmooAP/6cgTe4AAAAh9A31BGEORCZcuaCGIUCMEBaGWcTtEVIC0cZZTaiA7oJORySSDWxyldfusYDBskT6Cd/1oO22jZD16f//KrZf5pVUbu2byiTaiaCkf7mMbBTzSisFdNURWHU55BYs/rctOAAFkH6qbA3hzjAngewLMTCYITunWWEfRe2KPXgplYrdNH0VWy/zdRqXJxK+dEXg0eV+g7ZihY8DSL5aMPB3pJWvsAAjbk1pIE5ksBgSmIidq+qELCjKNs/E54qiC1HwWhxX2//TvWK6eVm6tlb+g65ndH39WloGed9uDSgrc0SqztGGrDpEl6oAAANpyTDCg+gZAZqgas/1nDXAdowX2X3EoUdqDPwQWry//00fT95W8vK39H6PT/VpaCTzvnUQ6o9cJRKrO0VkmvCTCW5MQQ//pwBBZkAAACExxd0QI7REKMS5oJJQ6IgXtu5YirkRgMrfSQCkDADGQlNdt4XGjsMkPiLoZVBOB4Iu/klyLUfvUNfk7esD3IOv09hnSw0KiAYZBZyhhB6aM5yC2v70K+L2GjCSbLwoLwAVICXbbtGpXbOpmrHO1B3k19Cr8G/pG0O1F74OKV5v/76G0T6UvjGY22318lHVv/iTfb+961vT/XbX++tavrbXQZBMEuSW2L3kbFp4jwP+V6gj3EvR8hqw00GF5tXqBD15tn/6YztO/687PWv+cdo9KJ5Z2fJ1RtfplXv+verf9fq3PFC9dAABJQBGtckUd31EbJ2Ehvunnp35Temb8EwTVqH74hdJMj9zN58clQIDmu+GFO4fw+qt8piBj70NE8T2TgjYfP3sPiDcUQmIKaiv/6cgSo3wAAAh5AX1BFEvxEiGu9DSIrCJTfZuecqpEQCa1cw4lSgRy9FSNyW9hpRbqBZe+A3HZy1hMp5V7aaB0N7Ren/tm2eb9P2/6KUI3DUTSllbqHcoecpelYoeCZPCYsmaR6HMQhly6AAJZAAtm2mCfUpb3Wa80/3if8idBiP9j79OPjp8uj9ProtnKSvVv/9i5Zu/dWKj830WgCVPQ0RPVPwrXMrrdaRZvwKiAQAMjkks9lcgediF2qNrUcoKwmqB/HZE5YJ3wfR6Ob6f/29ioq/ixX7TEUjfdFXjlDe1y0oj+lRo5W+SAzqL9ylL321AaABjbkz9fUecGy3Q2qSbFITYh1EZPBsNUd5emJ8t+qRkiTYlfLr+oGr8h+wRW9Iu0lW546lYCAwdDSBEw7DQ4VaJRKmIKa//pwBLhMAAQCFhjXmG84cEPHK7oIwiuIbQFo5LymURWcLEzzleIADS7YLMhUGLQKEnzUPYmdsxqXY1j0NCeUBmq85wD3C5Lj2e9BHdu+KSjwuTftzcj4WVULr0pSZWlXMWVK5n9Gp1+3ACOiA405QYqQaBVrE+q/3QrhAfC5/CubHfJ+Qnwv/9HoScHN+r+IT/8O2pqD2Khp49X51iWgzyjbVIU8xhxpwD0Q0cgAKklttjkV0NGFm5NtwniorgZqN/aHJRfRddQZfn0/82MyEVf0M2ogiff565KmX857VCB9MOvSgP0HWo1Bvbo6GVPWQDG5JL+zJWgUJYVUpbrVbd5XkJPQDkxVkfQuewoDZeh/bA4jR/2/24wshT/0M+ivRv+ZdRWIp7bEqm2bANnSfMtu/ZpFkxBTQP/6cgSoOAAAAgZA2BnqE2A+4yt6JOJECRTldUMcS9Egla9oExSmAE33/1NKNBL+OhCpXIpE0SJOgzpAysXDXM8XGCDhUH7yiatUTGp0srf2rpz/qjWzAK+sn29KNb3dqVBG+3V//68CAqAM/tlixRzFBoWyIZuj4baHbLhk+tHfbtiBWqj1g+GawP1vB9VcnE4fWfUc4IHPM8uCHxO/bl3nA/ievP8AiyFJt/+ZPQX3jWALU3IYmxNz/WlCz0P+JgEiyPGvF//yavp+kEnin1Vzl6sgZ3iFDDzwFIOeUDzLFqUFlrOurGq7UbsNpqqSZrkExIAGpD2Gyk/B354CZg7oO1/GUfQmrZ2+EzqhUqa16fVL1M8w4kDSHMXVcRXixI9oogZxqdLByq2NcLisrENyRZm3CLUpiCmg//pwBGqnAAACHFreUEgSnEBiO80M4kWIvOF/oKSlcRCgbeixFXLAiqgSpZbQTzD1jmHu9YoGsO0E+Tyy1I9Ta6G/N//Lo//95YSab72dV1DVHo/PeqKCQzK13raysxK6Oiondl13R3/4JghImNAlRolghuD4ca0Rrc0MCmBPBC8npD3qPrcVts+5SiLREVlXZ3iV0cDNlQ39YKnud+W4lyR5QdxEJRE/uDaAZSlcScuu2ungl7UuV+hovNs56D8PpwozypoO14u9eGa/++Mfb/GkeqDUdXnX0sSzDoxWsMC4qg6KERSPu6ZEwYnZj5CqQQJAQ9t+FJk6R8K23RbumCATuG4v+CYJV+I15G+vf/cPs4wNytbu8d0Yt3XJ0jucsaejbPdVVRgsRWB2uj0lrsVWm1KYgpqKAP/6cgS/MgAAAhIZWjUk4AxE49v9oZwBiJz1d1gygBEUsq7fElACAIDff3uhse6VNwBm2M3kQTaOn0fM6l2JMiZQnsyisByZWZ8DtfHdAclH6q1NUGzWo2LnRVzIuTsY57g3a1aFqs+HoiEmZIE9dbsEF1xzBmcF8BFwcgjNHxc82ybPU7l23U8Nk6tqe5pee4TUbT1JrNMWjUBoPLCAytWX/VeeNLInhVjwmun1gAAINUkn3f/f/AAUJRP45pagRWIGdzSXZTnU7sOKZAeyM6Vbx3QdzzmRe7XRZ11s5kUrMR8YqFTdDeWZ3Iutoi8WaeoqAAgAFFAgEAoFvMZs0godTJ68MWqdXX11ao6u2V0qT29udP/I7kb//sTO////kaRv///uICjqcCNDjf////nIpwO9CWOLpiCA//pwBDcgAACCFCVbVyUADERjG23mFAAIHLtiZLzsEQ8a68mGFOjEACQVJGxFUFAvSacX2tJuWcqgrPrRI0v62EfJE9xZvszA8A9VU7wb/N9f/yOrIHvOP0tbMLF0qZqh1bu0q3///+GQAACEYCrYklv1T2hMBdbqzvxTqiUOvlZhCiRGlR7/R6Bp3Jax+t0UYsKlHAVhFXqWxNCS+M33TWcMUZdtOMUdSqMymtoBcttmOsoeVA8RqRCNmhu92Gq8JXofzasriyOO+LO2Dp6Pksc//jz639NU1JzlDitcVC6wfnk7Wni7NX81jSi/qA/wbutNVgS4OIUk/Ar+wr72DmbD1M4a/OtCFcYxQ0fiumoqlOTRv+vexUeptHf+j1lIaXGgERXBX+o8Hf/2lutyn/lkxBTUUAAAAP/6cgTRPAAAAigVWBnsKcRCh1sXLgIoiIzVb0KYQ3ELFyyc8xzaAClu0pFwMFASVZwwgb0sRPaKB1+wq6hPqwQg8JEfAeQWf0T3oh/pKqdJc6ezR9IKmQ7eyJngqk3W95gJqREdyziDz3eaAIAFLbbKyRFCEBGMDehkNN6RWaDGoBZdGO4fHeg2jZD0/Rv+TTo31Qztqyq10ZcvdtXazBk9jJLI3Ff+RMpV5dze+ABBwC5ZYxmBlcyg31kSs5Q/D6C8Q1bsSpOBaPBhv+rf8+w+9NDaE+yOzte7Y495MUQ9obCIUAEBQqKOFAR3MToIU3fbCwEqbbCk2IptVE6NRfbWEL8IVFfK5ROJy5DviVo2GxpTn9v+mnX6Jnby5JA7OgJZI8OsAR869CAFA66TzB4wj/SRamIKaigA//pwBLxWAAACGyVYueZRpEMFu0o85TaIHW11QoRdMQcOK8zzKPIAYAkuumN8hqVlNhEG2ugu8ngeZBCPQmy+Ywx5qaDXPfFGnNuY1v75R7vTE+KMqQ0yFA8BA3+et8qJlHTVBq8eba3ycABSAlb7cSV8ia0pi0eUoKtAnwQfiGuth4/I2HfwUvyf/6RgPiukxkuuKiLQuSBAXSwMccPf707ugxSLDYRE58XaXSiCLRJlskt48cQSI50mbGpYPNi57KdGEHX6PjdAO/x7z//ATedkQxuApugbk1faAM5s5e8f1jf+x19Sxm+l//4RwAnLa8WwPgrYAs4NUABemBAIM5YUhAEh+TvZPs9gYGwiZGYWxW1bFom+T0/pn/GSHQxIwW0RefzMX5Fv1PFditvsTEFNRTMuOTcAAP/6cgQn5QAAghcd2RnjLCRDhhsjNSI+iDSNiaGcS/ESGKwdhh0aBDckk+4aEI2FDeg/4rrxsTwn6ziGX+/Qpk1eCAlDbt7u2o8NdZZjIItOyU5f3qc4gdsteoslMkgC6sdONbWKbP/T1ABS7YXYXBeWB/E4CZGfoeYgsbCFUbz8hburmm45Rb2jZdWwpuWRN6/yfs6/5UovCWB4Klg6tbiSMnqatCsQo5i9ifHYwFuOtyf//+puj2isXST2DBHETUxtMtjWxz1f6hUaanRJQqPXhdA8E57lg5ZEeGloEUeG2JPOpkM1yrVLT++pnh4QBTttG+1WeKMXSwWTkR5lYlDeGzxKJv23ahALsx4cJmNZRzU7UtRgoyuXNSfffXp30/zLJu86W97yzWsIo7yHd9KunpTEFNRQAAAA//pwBF6GAAiCESTbUYcR9ELDayM9hUaImMFs9POAERMM7V6YUAKEBUCBdf/KotSRMieNYBlFGhsoD/OA9qk+fljIaonbXs3aSBO8F3zGwx8qjp891H1JWB9QCnRrKj45yFt7t0DzT/WAHLthmmTuNXicj1i1aZZHTp5QM+xn6E6UDEYTqR6m1fHgXjC6jN63Kp9UDxNLOfBUw+XOw45d7ItdBneKtRe1iK4oUATf/2jhRS6kbU+RO3HU2Pdi1UImyGxlWeWr5+vHfWPnqa9f/VzrXbc1a5g6YmPtRF8aQCgqzNZQWva5Sex9iaiZZfzIgArbbZpQaIbHIByZeWDG0yZtYeZov9GxCran75A3a5vya1VROs/WLJa1GIAy84OlHQffrNrfkj9dhQ48zaIFHxt6r/JpiCmooP/6cgSOcgAAAhct4FYwRIREI0wqwYwAiM13mngCgBEHD26fEjACAAACBSAMA2//A4G83hQdwG8AMTRi+u8rmgNGedXKPO+LMR0ZJ56MmgvzdP//8jEumgYjABJcRrTQSJc//+XP///o0AgIK/9tv/7/7/78b6RXQbhup5y9zMncuDmTpmnNynEnwWyee4/NvgrbMSorU08Kxdo3rYtXiMKBawG2MIrs/LjXi9fpAAA+H4/H4//////////a053Qp0N/1QlBRCRQYFh0VUOiQn/1POdw+hBAOFcOCcPjBjsD//ZUYOMdCUEGxphIeCjjIUOGGIAAuUrbtvxwABYvZ6CoN6KSUSF9XleMgjCLRhyzNCuIfI5cQq9v9S/rfBB+XJoQTSVgNtDKgKRY8bDS1wP6ELDZJCYgpqKA//pwBPrSAAAB8hlh7xSgDEOmG2rmFACIvFV/oZRGMQmOrMzzlcJiAFuPyStEhXvIl7XSoMDFKP4vFVFjDEBxUdV8gbvxAOgEJKNEg00O9agpZEv/ivnjvklhoDdX/u6uRz1Yo+AIBQVf/hYI/ZG7Q1F4d7n0CB1pXIKwFtAcsgzveMZqPolBgJritUKxuugyg1DxpyvSX6oa6B5ic00yH1sijf/o///XCwCi3C1tpJaPiCBRQ2t0xmsNqAaIwKXobBDyUjQgqGF1jrwfJOWcDRJqkRIAegGqFXflkLMJ1GjzvldQ48t0WArjsqMUPAE2248/fkfYznERKrhIx7vhQwsB3AmY7Kw20KZsfo2cX7QaN30FTQN2A0YJGnS9Rg4yGbL0J/8vqGuAZpQnqCVDDqYgpqKZlxybgP/6cgS9RgAAAe4hXdCiKnxBBKszMOJUiTz/d1RhADEYDq8qjFAGyASkta620bh+NUBTRWtFaY3D9aMCfBAGGHwTUBCcfRAUPirpxB6pGf7trgmr1Jrm7num+ecxba7XuodX+GQBbbBZ/gdDLS8CIlU24FrwnDsHPH1LjFfBDNv2xATvEIIO+LkCSSUOPLvLpnyDT5fwfPw+Bz9uzs///Ln+cU7wfmARpIzbbR8cQgaLEjLQxT/1lXbEaBKDOxEAxDVTTR1+0UX9OM6o5ZnN6d9fEZLKRa1M2e7iLnrRAqm9pYCw+4Xn8RgVJM+GEr9UQKOlG2NuP3PJGuaM2nQj+Hw9aAJ9Mcj6CjVN+cvariRZTSixR4mGBEgTeaUPTbmLiN8VmaUUKWozlGPVwo9UwuQuYx+/YmIKaigA//pwBNNfAAAB/l3elhigBEOoK5rEiACI7GVtXJKAARoSqw+wsAIAwwwwxkW7UJkawC3M9+D2dH///fv///VFf//kIeLs///uQggJoKI2v//3KPIRAYjCo/T///7C4gOBRZVF3Uw4AAABmZFbbYbDYACIMUX5MCphOAPLO8ZdUOwc7O7qRRQ0Z1afvzgV6jeXuhrKm6Ms/uXV2Z73/4J6vX3X//DUm512YVGABwSsZJNVYigkyAYCWg7r5ek33BtG0JRlfZ//EQZ5JLhK5Tyrs0FTpAsDOeo1Wpuhogn7hGAmtiUq5bdus9uZZDoiLNw0aJDkgA5LZwvuPMsqPoclU36X/TJxyqiutOoGrBkbOSJp35ggh2lhsZ2w9cQd/vhMn378vzh2tDrl/KM1K5Vsxu2ln1XJgpqTAP/6cAQOSAAAAiMbVhMPOtBEY7udGCcBiFBni6CIo/ELDu5ocZ3CAplKncBYLZpWOCCokc3hTEeldN+rnmovFKSvxS28uXu6L5avbj2p7YVIVlkf6qHHrT8EHakVjxAENH8Or5ao99d3/8OwAAEtkMyIpQwZQdKnB6opRWkdRJaUHfo6M1Cr0Kd8qInMkGFeQpIVgw4hxPKBj8nBB3KBigTn/if+sH+77g+sP4nB8H4aAnJtNdY5NdiSpeWNqUbD6Ab0FY1gCHPmaZu1ABG4sfFP9wrxaoX/Ddd2kqtZ1VL61BV3fufUSix+IoDKnArOywVgADoNWNyVHc4Ox8XSMiu9IGKhLRqV6Eeb+OBLz5OOIMNQN2OFeLVEvzMVjNJVazqqX6mO37XPqbCz4igMCnArOywVTEFNRQD/+nIEuo0AAAIUE15tDQAMRMarmqOUAIixgXx4IQAJGQwuawwgAkEAEksWFGpLtiLGUVjwLD0E8lftpANpEuGZ8hnJth/T/6n/LfkXTxXlgaIiUPRUmqBTqgaljoBOtDvoOw1DgKt2opQAaoI6y228UC3HyDnyd1YMOp+L7pxr6Cv/x/1OHgp6qdadP0f9vm/76CwSUeKgYuwswise1TjE0YYlKmuGPU42ijRe2kAgcfj8ej1HmnEkAjzPe//6aP3///f//zzy/358EMQQGT/3znfhA44MwoodP/ujZBbyM7uxgiHwv//OfEEbo3QUcmI0GRQAAIRAElRdvqLhgGB8OYJFoIGgSVW5bQodlS9SNaQdcWbFNqExPnLpHqzYXAIqRTSoEwCDh0uG7P5EFVbzNJn8s0+aBJ4dTP/6cARtGQAAAh0q2+8k4AA1pCuN5KgBiQzZZOWUTZEvoGyc84l6QAASagUkYBFxiIH2H0ItIzFafo3uX49dso5zbkW/NZRFDC77/nTtvOqhqUaxQ+w3u6Fu1ILf2I1NdaubSyy0b47RpGoEEoqMJW0AC0uNE9dYhkz2dj+P460qDeLLFCQ4ZRIOygFpLr2oLydcnlZ95zZFxYjuAu6kq4AgIjKJO2BHHLQpPCVIdeOK1CGUVegd30cRZoWHW307AvaAOFClspjUebluUpWDdDf/0M+hgYCedgy78NEP/O1qPZ4795Gs7LQPBM220rFs8LXemJB9p7lcF4RMwsbCV6nSkLM9CLUTtwKNkKSh8G2CfR6LuqIq26uqA2VXF7pv3aTq7evIYg731rFyw9S7kdpYw76kxBTUUAD/+nIEUtcAAAH1JNcZ6xH0Peb7Az1FRIkUlW9Uk4AxKJdtqpBwBwBJJI6RdDeI9uP0lyqobGBJSlANT/aHqDu+p1Fzaj+Uh9Oj0DrywE7rQG+7aswMYhHfaLV77a3f2dKvVd//UAHbbXhxiHEK3cBnL1UeWvHASeB+A3Wg9wxJz6F/GAH3nouvd3vWtkZv5uyH0+t66oKZoIVmrGJdnG0fZ/6oAFrBUtkkUrBS/qNPt3Pz8h99BuyDgpeSFRgUcTn99OiR8JwGEDEe/01dsxY7LNfHLKyFxVQ2WOMNh49RuKR929kw0rZqin8OQAKuSXLJAQZQchbGFprzD5Qc5Z8U3OKOODJpE9SwTk5T+Kwib+v6/q7T+voz1jppMlfU/luUHIIXPBUPWI9tvM/Qj38/VRn/b/bTEFNRQP/6cAQiNgAAAhJfXRYM4AJDbKvTwZwACNDhcbxSgAEYHC2zjFAAADDDDDjYcGOKs1U06UXnX3o8x+/vzffyF//892MN//7EyAYG///8wdEsXjRVMb///xLMMZyBrqxX////8nmmJNpaQABQKBQKBedop+aHzfr9v/v26//2//7nuxhv//YmQDAln///mDUJxeJB6jjf//+JZhjFyBF1Yr////+TnucahdTzSioEIAwxOIgApTwKZBIqXtoKjjGGNvoRBIwDNlH99MwQArbq/q32/6t+or0H9DbfIbisQkudYJbbNj1otb26nyUq5pBSjy8DAEFAJRlAB94ATqOUbsPG/mnM1qHbSqOOxgOah/6ff1b7ffq340V6Cz6Ge3yCz4rEIabnWCWSWzY9aLW9up8lKuaQUo8vAwD/+nIEa14AAAIXQNnQ4R6wQKgbNygj1gi1cXFBBFyZFqDv9FCblgBgHBViDcV2ADII4tPVEVaB6435fNPZ4XbFBP9OJif32ah/58w/h+ltb9Gu5C/w+0qDOoSZJ70OtiLbVBpwiQ0JN9QIQFWQ3LsEsTLjhNdCVcuKMrz+vEdsXF+nfcRfSUiZqH//D+f0v36NdyF/n1SoM6hJknvQ62IttUOuESGhJpvepAYGgldJblRRhqlFSfR8A1FfB2fDCXo/6G7RoyaXda8nUkI/F8zwqfyEshLXq6lmWtRO3ZKf/e9f0/V70MaiHCsCV2++oLILjLtDesUlVLNVmiiC/IuIPOGvQOulegO2f8oBcseyo7VTrstSXuL6WFfyFy//157PoupRnXuijtxZPpZKvlgOwrW6VmUxBTUUAP/6cASDlgAAAhw12BnmKRBDyCsHPSc4CJDXgaKcVDEGoLA0UR2eAF913rNGN8iKgYlBgyiUAEWwPqK/C4DXgOCvGP3w83zp7/Q///lt5TvJ+RyCrhOLD3Sakd3qvajgBjhf7CySlYcllqAqALtrtXUZFlppMvD3naL+icJZJrKjmpShcwZx59DPx8Jela9//9UX0V75QYY2hHb76Ie+jq3p1Kl/xQx3M9dX28W6oCym9I29I5LHUHVO09VwdnGgx6g2qQtzWSFWeCfvUAf5kRKNun/5/0XtTe38MPJjh+8sYht73lrUqeKrVovd91b7jNG6AlOOSpTWOSxWjVnmgivRLBeF2OyuUfV9PL4QBvvMpz/p+mhf9r6F377fXqS2T+lsYF10wmKAdim2dK6XaLpOrqNpiCmooAD/+nIEfIsAAAIlQNk5IxKUREb7OhkiHIhodVpnsUNBD47sHPMcaIIEiRqOQdAcHf0hazX1aoNiOJ0WDHDDLI+CJq+z9otFdlP1zNyJZTfmb5Vpb7Wflp+6KzJgTtMDM2MpLb7Or3VgY+/RXCAuoBkbchgaVCWaaMX7NI89ELPkSbQA5aubgx9H/f2uyn2qn+RJXRv06Mnb8kHwYQZVrdNrp6UQgl7eez+1yFPa43pSALGpbTbsDWZrYTDnQg6zH4au3FtsGrIyCJI3CfxXPfN1ehM+h9FJmlKm9K263Y8r4iYp5Bn0DdvuKWez7GWW0vXFTICyB7Lv8bjkiW8AMzhekm/Cr30GWqkrMc+Jw96HfqL+fNjh7rWdz2cVrPs9QYhNTX6HUFKhmFwqMV1oe7OaoNK3tpWTTEFNRf/6cASn7wAAgh5A2OgpKDBBY/tqFOZ7iIkBg6CIqfEJDKxoxJxqAAAgYIC/u/98ABv0WCdBc5CoZ5wTh3IeNcUfCxd9/oqcfPHNr0qn6Jf9E8/Q3+miPqns7Jag2uU1Dtq3OyOpGj7idqwAAtINZCUvDBeMhkluxMaNga/qYKJs0Z7/QsAZzI7xuSfrRBTewt2bv30X51SCxAh7QIE8a7v7XLRNLFQisPLS5EIYVldTn1tuuJ43Hj2o+DfFYcRWG5B3/aob+iMul5W39lz0+7cQZfnVXIqMpSCdhJG9C5ioEWVMyICoazw33Uckzet1ArgFxtyb7ouCUg8MEvIau/BEQrG+gmdjppVihbKB/b8XAry7lcCtJLL9RGIZqvEp5TyJL2I/tLiNrNSG2L+xrDSPemIKaigAAAD/+nIEIEIAAAIXW1aZ7SrQRAT7Ci2lNof9bXmjhFtxD6Bu9DKJpgBqndoNm0nAWd4pUlMrRwVKC603qHxp0ldA/VGOeUsNAx4U+rVAgPq9Uq/sl/9P/8v/9emhb/t5V//oqf////6rG9IAATgBxuSNh4WHMpDwFmdFtP6o3lUILidmV1iY5YUG/+OAL7Safv9pqi3ENRtylMqMFETz9TnAQbRRGL6drHFafdff0sAAFxtJWxyY1p5fUxDbctwXtU7U2jEXVyRB5RtWoNU7Xf/fr5/176OS/Pjk/k6rOXl/C5GfXXf/V/8g46VaOjWEAI1cSbm5NRtx7qPpgqcaEMa+52D5YXC+j9v3L95tP3QyNCGoUv9PN+jeh21epVf+xWqNUQ1er7i20VH2FBVxw5QgqmIKaimZccm4AP/6cASv+AAAAhRa3WjJEyw+5rtaJEV5iOUDeaKYUjESnHC0MJTWaBAMkYStjkuKg1fbA3X7bpHd8wjvOsZvRk6jdu1HG7WjP/9Lb5n+t9iH0b9HdLy4/5Ztzleyfvuv9aadf+v/guyyhIBCwVYklO7DCySYytSvdD/D2E1FbJBwo+cfQbvURATllY5dEWtSNq8+Zvr8qfnujRJ1lF9G8kr//u/VU67y0AAAbWTe1luEB0a+gqqX1DXwGbL1AgwoZpbLqNpzif2o6fYtyc9EdNdjO2DX9vz6WUl/QxNYaQln3PRRLVMe4onRmEhvFlaqYgZbonf/d+CG3GlquYlAIA5gDaNHfVkfV9G7YcAXvS3T/Ns6b+lSM1BRSslqdK/jXi9ZtUNadZq46tTT0KqFFf3XinQmIKaigAD/+nIEljIAAAIgWt7oZxNsQ0gbygziiYiRAW9MJELRGJcrTaSdagACYlInNrLtvCRLHQTUqS3K6lM8/LFGeezzF0eVD9PnBI/+vCdy+tH8j9d+2+o7W/9HQzfbv6FdVsi/tcs2d6P/wacXABj9N3WW7eAAAlgnEYty8yoV9tVyxzpE4flDe2NxK/v0+rrKpUctKezdhy6rf1uXjVabyWkdAYhUdzPVdOvJ7flb+kAAFghft/o+z8omw0GXRkHaN8bq2E5dmqy8G7wSadm/kt9LNZ7XVU/DsW9GtejfZ9Vo/TW89AzdyTknJTKnL1PMs+T/vACkkgSXEZsjxmIGhwFzZAqspfWYneUV9A+CHwkf6Szw/ozb18GQS0ftjQj/T/9ul1VdOS7kQYWSvQg8oPiUgKR7Kwl3atyYgv/6cATgagAIAgJa2jnhE/ZDhruqMOUdiJC7bUScSFERFe0okomqAiAJrts9AHAXRvrL2C3o6r6FL/31cfFspoLwvJf1/GevnPoiIn+VfZtfssrqsqM47L9S8yf+/RPJ/X/p+3e4RYBDPiXtZbKggP3qyRmdmnUZ4RNh/6RDqP/jsB/WSHjNJ0dDMrVNsjm22bkSmX+JFWld1oSKrDw9ewiUNPuVTAMqLX+oKwlvv/TpITcOZZdjA6M8QfBvULjHg6cEK42nAi94zBua/d2orXo6l+boLY+++LFGlhpAMNBJJeOeZQbWTGbaGmEPd/qBAhoFXbbgPigNKtVRVFg75pbY+FtgI9cZGNwbVu2E9Ozaf9rI9Gt4Qzi4OuC/gpxjVsJrhqpy3OSgaCptw4e5RUUhsUTEFNRQAAD/+nIENBAAAAIkNd7ooRcMQuV7bSDiX4io12TlnEvQ/5dr6POJMkgQUE4nP/dsVnMO3HVU3V8nNuSt2SJCmo7RsSDfvYb9Wom4A1Nobz1AFwZGUt/rg11tdGiUcLtaiKytErU2rLEbtcu6gBAAluEK2uRrTCzjZUKQf0y5Jo1L1DbKix5y4d37fmBt/1V9tdWc72nVOVYYsqCwZETuSpuflQNDSGnUsv2xNT27vWAcJ3bbSW4sGOUD0JbEFIY4vSw31I7P1tKi3Kn/ULO6X0Yrqv8iOhHJVPwredUsvSqKGI0yMFXxiGjVITrcSSRvYz82v1gAAOABbbRmIlDhtVvUg8bhEt2mjGPPiS9GcowHluzbd8OAf//NLVWttezSPzCrFT1BFYu8F42YcksirmGJ936UxBTUUAAAAP/6cATVNgAAAh41WT0kQAxEJrvdpBwBiE0njPgjgBELJPFrBFAAgMCHI21CCAPEvDwwTxJFEN+zJ51Cakb0e4qzNk/I/a8//WiVJtZdrSpoKJSrsdL3AQ2k57rgKdfcahsVZPq8FY9bPmUGCXrao7/tgid1HD0vc8GAI4s4RJmykUvqJBb/iIV+vf+a66mpRKv46ejmo7O70Rd2eTY1gI2vFc4ZRovtqSLuddD8OAAgCAQCAQCAQfD7uKfzfH0/nf//qfU//7sPkxoIn/8SAdg/JkBoQzf/4OxLee44NCH//++ePkxIY8aHP/4IQwIChwAAAAAwUDgcDgcDj4fnFP5vU7d8Q/Z//i7zv/+Jh8XFBD/+KAcPi4oHBTL//A4vfQQJ///85xcCMcOHP/4ISAgKHOlMQU1FAAD/+nIEKwMACAIgIOBPIOAIRAG8b+GYAQhs12wMBHVA/Ycy9CCkPgACx+lBpEgSszXNSqquzTedoFgyd2zkNZta/Nb/2aRsFBR99B9T155q9lTBiFrcR3+tr2GIYIooas41ZUiJGLqedYSoACQiJoU97ZI5cEF2Y71VUtmubLf0KH8seMGRcnkvmCtgoKP6Hqet081aLKiIxAXW5P9bXsMTBFG1bCS1kRIKD6nnZKisBOBgqOVznIpZy33nOa5+t73Y1YZ0t2UXMfl//3+c+qNneeFPC5LAwy7wnrLPFKW5Z0kBkIi9dMm8+rPB1tspDjLdYLcl27ssbSUhBQokGboNAAVp6wFz/li1HqAiw+PXoJ3rur5w6y8q8JKnrZJbmOr960rsllD6+pyxVdhLa4YmbTEFNRTMuOTcAP/6cATbPQABAh42XEnwE6BEBsv9IOJnCDTVZky8RcEOGq0JkIqgATVDqqqH2BDP6N1O9iRdX1m28XtqqUZhDkjS1N11fzfd7t8zqGqZ82yddsokqlmfozr6RKHbuzF67MtWjf057grR2awgVLKTpLG24HYAMOky0dO1a20SlMThNbMwcRVlX5u10/zPDOpnzbJ122ZpZn5mdV6RKNuyDMXrsyyFiXf0rh3grR2LrGYG2lmqCH52MsaqeVnvDn/vL/evcXwAoQtvZc9gZGrJfytsZ3/9S6E22720UxZabvo9vBM7PlFV9+1AxfTv/6G9YP/+FYQMNH69+rfh6tnu3ew7/45dt71ukZ6NCTVL+8lyvzW3f95hyJVrirSCaXe9WR7eC9M3yiq+/aYGLd5v6PIN416YgpqKAAD/+nAEdOgACAIXQNzrBjhoQmgLzTxqDQiY12LMQEsBFBCtaPWIuAAAI2CmbG5KMJZuKtjLSS/jfL2QqyaBsMJ5h6Uqxi+239tHq3M/6P9z3/5m/lC3/qqNOPSxW7Sq8wldvnF+JH/NyFQQBEtod31s2DFONnInEP6K5bvj25ZSUFL9kptUzzSzt02tTofZylHW369H9v97rKa/v+i8r+Ll3WhMW51e+tnxLXsCJXfmByP0od2QtKfjB+6th40k0lzucVYxBpmLll8Mh+kG/tRqfN2qXtojX+jWZFVWlU1Sf0F6l1v5n0KzCYe/V2P3+ysAQ0A5JJbQFAcSE0nXVD6rShLPdy1StSPaCWBtj/20agV+QS6u6CfShthHIMSs0uw5BMxuuU/s1j5J+MuZd1NzD1M0J+hMQU1F//pyBIOJAACCIxTYswhZ0EIDCvJhkTgIqF+FoJiqcRAV7OjGidABAt3+DUApcNwLDrC3YmTlNAEo/mhXkujrcAoG1dfiWrdfZdkFF2bXsK0NaNtD1Qd5NHYFq7j6hrk3+m7dRZsu6H+p3WBM1GGgOm2OTy/OdZuSHVIIUvXlBpOvURN4JcLhjQnD+izTh7NvnosLPUnLNebf68kREEa3VN9/vSa96tNCuqgvw2CEjrSnJZG3TIamKWMYYvVhSSH4wNVO6JJwy2guqwxSCZwyREdhJ7ZIHQ85rj4u5EOCTaqq9Vleu57G/TqTm33DtEgWFHmAAW5ZaJo1Du8+lSmUD0mbszjDedZJ3FiBOJFx7qgKg23ofWjbbouV9Ge3+mlRI+0gsmgkHCSlK1tb/2HY5X+zj/utSmIKaij/+nAEtKQAAAIgNdtpLRMwQSI7fSRqVQi9M3uhnE6xGZrvdGKJdgAAIUCHb7t+DqAr2Cj7jvMU/F17WeHYpTJta7YH6hp2ZHXp8yIytdyOU2nalfUq/zMlRLqJ645o/j5xYdY3JqsyPfWSAAABgALtdl4yStN1iZhfdQX5i0ke8XApc5vK3JxFezGjzT8ogqzy2/SCrxGAXAypWeY1nfVQlj1vt05rLur1PRSACQ4wklG0nElPZcvMx9VAN/FAZU5rkldWyew1O/5F3Lzp6t5S2lRuKN33bv6b/bPvq3/vz0RUog4UFKA3i9olG+owwmycCTghQLbjaTkWtKIOAzyO6xM/TxgHmarsIj1FcE+JRkZLXmkRD/Kzum1S7dQilZU19248V0uZ7N3OraoWZO5tTRDgEy/tuQmA//pyBKy+AADCF0bj6KksjkMliuI/B3QIhRl3oahPcRaWK8zHldBtuP6jTX227GMd6lplDSEVXs3oaoTO80Y+ihrbw+5O+rDDKet3W37+vzNW3rVUmknvf/ov1/+PshNTskVR3/8fbnfIBX/ochhPn8e1yPbG1gNGFXyvlZ3m9Tc7VLziXqKOUXsVcKPNxt6C+vP1jnou+bR/o6tow8WHiHbIzntd/v2+yr//6gQYUkCE20m5UDCursxyF0l16AwIQgRtafHvqMkR0T6OnJ3kZ0lTrH6W69dHa0te/+pQz9bJ/qKKErbR6+0qX1iF36H1gJtyWrTktWdOW1kGBsJjt81Ec/+uVmMD5VEzJN0GqEhTwj6hyzYymZ00RpLpdtu0fVsdIvXuadCLXua7X/Uyxkkr21cQuTEFNRT/+nAEgVAAAIIKNV1QZxLsQCO7AzIHkAixU2jENE9xApptZGaKVgxZAKTbSc3BGbTvuWbb91AeDERsxz2bipOYB9eqGf00pVrX6hBT2cjLIb1Mt7RT5jdFHV6MlKqS4NjfoWjGfRqkQBHLbUg5Dhyll8sttHZLv8y8r6d1hmwrAbCkXD2Y4rZXxB82i6+ULh6QHx++o81Tr4uAyMstqFyGR0fGevb9/SBgGZbeQwlwUP1zB6cKn3gG6QXUe0pPp878jvt6TOiGSyb/v4JFZVFlNI1bs7eozFRretLVbr+/xrf4Ry9k26VB3bPX2R8yATLYEEhCuV7fpIEofomPzapbhAIy6TapNe+T/m308E7fuiEb/oSjqQZ1t4X+MWkslc//dQkOlAatypa7s7Cu9MQU1FMy45NwAAAA//pyBOv0AADCFRjXGeU1EESDq0cZQmuIoS9nIxxPcQOaK8y3lggBMm3Yw1ozC8yHZaAjrxFpat8Wi78uJY57AOxb5W5o8sUcT4Q2lgjpG0qYIqjv9Toj+X0KUza2Z2Z6sb3F3dvbt/9QEASiCVKHKUpeB4nB8x7rpUuwrAJscWzowdCegLjeMxNPcIOlcBjPDmS+9CjrmOrpQ/dTtbOnXD3jKboXe9oi4Mxs7gmCAQAKKebMhMdQ1fwi29kielcKgkst0Ht8V+YGVMLv00dOn0+3oN3K/v/0BV3t5K9//v6/BNOyhBRKS6ViZQJBqwjfv8uAW5Z+sDgtJhNIrTg+TYx5jhf+pcWPwD9ElddXQBmGPgG3It7o/p7/Uye3oXwi+lf/GD7Xen6cnhivv8pqVTbZ70xBTUUAAAD/+nAEEO8ACIINS9mxJxL8QcXK8zIHdAh5UWlDHLLxEqus5JUJ7gCAyrZQ2HzMSPoXVhYt3TRlLOFwSlWVVcf3aKPHhLONf+ZUv3XGTo3oXwjrkT7dgR/Vvf//0f2+degkBW+oObv/QCJNdsvHMg0qXysxD54FXfvVczs6VEyaBcUSp6fULmo6wWN3JfbZEN/ejFk0T8nq4PHahYwOOuqHt6cpd+EPmP6dGiAlEkuFWLuSKaavYkWVb7f789GSNRPskx0ugV9wm/2q6cn19H9H833+vdB/r8vy/+nzfCq0Me61f1reIuit5LImac9UC0g2HxYjkeUWaN0qArZqfRF8s8kjACFxn6iyOnOkKN+VFqxSZ7B5Ol+L9H1o/m/+vx//L9fv6fDN5N6bNX/0L8f5H70xBTUUAAAA//pyBJvoAAACGlTdUGcrbEMqm0kk4l2IjSNxVDOAMROr73aMUAZQjo0m1GpeBTIFsM+CFlFtjnigbjcDxerOw8Z4jeOhJ6/v5/p9/i01Dl8U6ubWMB/V/N9//RvX43bFn/578Zw7uq7KAAMQFiH1TqbXOKW12gWUzvnULKJgD1H30QVIr4UblEXL94PXX6ff4/hW1Rvv6v9/T7/f0+vwO1VHMzUevZ3wz5z1fUAJ0BTaabgfg6sQi+DFiJlNV0CgbZXzYr9AenvPHAcnEzH10MLnVmP5qdX+/s+rH/+hf7+vqnv9FRcdd3ymUZ6M/i3/qJZIdBLbrjlzVlJp5MP3nPoGCemIA1XndQHZXwt3yNv9TB0Xfk3y+r/tor9n9W9X9H9fk2/oeuImXij+T/19VR6xF/V8smIKaij/+nAEfhIAAAIgSOE+FKAARKkMAsQUAAhUPXK9A4ABEZrxt4xQBgEABAIBAIBAIEqc4Q0Hh4KxCItsqUzo0v//7s5l/+HDOKOWv/wcPAjjziGnb/kFyITEzf//5kZii48oid/+o9eGwyroMMMMMMm7dwcmkOBsGLyMkzZTPaSwsv/rb7s6LX/hwzijlr/8XEgRx5yadv+Q5EJiZvun/8yMxRdxgcsK/+IqSpp7O65QBYANQtuA+FGQOk0Rp53PukkkldTfCAhcvsZbRbHWpzwoJViGsdUCZA207tZvQnW17CQww7rFyS6i73Vdus4eI+5CAEUmo3GkSQFwMG1nqUfu7VVXOpVV4iCmd+UQS+J2217p/5tFLVPX9HRrrL9TGujHHscDWLp0EPxfyaP9okLAZ7gpRc5KYgpo//pyBIGzAAECDjXl6GEVzEJCm908ZR0IkQGPoRxO8RUbLvTxFHwNuXbO2xtJJ4UBZirNqrZPCNjP8MJkH74JKsBCbmadf+zBjFCU0Hlz3/4bGdtwBdBZ5We0fjyK1rIor0NO4cWpP6AAA5aTYyAAE2BaVbYMoWH0SxlSm0PiA7faEhR+HBEbWSeZs0iSBls+1Iv50s+UXQWeue0frIrrSj0NbUHBdRa1fQoOJu6m3SNwgISU1m0CdQPb1II4z3HgyoyxxpM25L23fS50X2VS+hvvr/ab6A2R9r+VnfqDdkKhEtTa3KoxGGkYNPQnZrAIBkjUkbKBSvKhuilR4rDDLRz24mBAer+cFR8HboM5Ee27+50VOVVL2Q331/tMnoNYRXHpVOt2QqLLtrdoxGGkYNPR2a0xBTUUAAD/+nAExWQAAIIjNVpLJxHwQea7SWUKLAf415fjBO5xFJrrhbYoYAABguv+xVkXtf6Hb9StsYNiOZ40a+Te00vZIrDo2Da2Dy7epvR9Feardu7OWct3t5r3NBBU7W1dlCFoX9lBW//p/fqAwAAYP9fYq6P0u04t+gcs5YDMt+Kerw8gPBUxV9YvLImIn3GdNE9SbXe/pt29q1bT9L6UJlr9/MN9au46n/3+p3IkANDZpd1W/62W4vJzX+1sBCaQfMPwsxWtejBc2xqCxa1Ck5EV3TX93oy/9vmGdK+39Cf1zDiB/97WMs+tPW776nnEdCEPKmreHRBqJ5FddAo8pxYk7ow6eB0FB4VU0cPVdmQVjuwuR6LblbqtfQ9bdda72//tXl+l2tyA8/1nz3FP/FXetCYgpqKAAAAA//pyBAaEAAgB/TZXkwlQ8ESoGylhol0IbNdpR5ihIRGm7nTAlGwQaZOUwMldsWHg+2FAb8QDOYjUVP6tMxEPgnEtt2CaO9RW3oPfv6trv2Mr/9D9J6/X/cfeek+V+hlL3g52dz9AAFAkwgJkKpjBdelocs5BluRkq1ce1TTrwxD1k80utjE+vlTO+H/1gxmTKPa6f37XWH1Wr/3pU3vVf7NwvR7fJfX0O+SbAglJJwcwHIilkJDU/okxeI0THSmULbVgEDU4j8G9fr9PvS1kS1tiq1fXv7VFa4DdM3p+q4LCFkOn38sZtkTq2ZREwCSRF6IvZZNh6CKHYBJWFh0FUF0GigiBh9WvQIP43wmBnjp38aO9G87e3y+u5H+7/qO9tlbJ33//0k/nca2u1zMidX2rTEFNRTMuOTf/+nAEqDMAAAIdNlxpYylYQybLuSAnR4g4jWTmDOrBDBrsTMGdWAAENMQpZLLe0Ne9RBwi4Iw0o4F1amx43rCVOA3jQJR9vX4m2jr16albRTafUvboO9qyIBMVa35JOwi91bupaQ5G21S4Flbd9VchWnqIYmYiexWtopBJSvmg6LWwp5oY2qZ4r+69Sl9Pq3OSv+pk9jqsNexB4Xi7yOy8HhQiqwsf11PH8OfvqMoC3JZsKy6WnnOl6nul/G7F5LCjA1R3600En2GNP5nzFtNIOYGVR86Hd9Clxz9DqC7oi+ca2pgXgHdZdKnNDViwwJt2S0Hx6Ih8ho1Dy69BSw/Yuq4IoJEqWfxC/QU+cb5VvbXTzCzp3pmb3V3azzaFWO/L8k2KXBQ/6NzVAOl/2YA/fpTEFNRQAAAA//pyBK9BAAACASxcyQcVnEQmOzok4lsIyI9SB6VUARaZLqgyid4QSrp9lunFlqenjIpfV+PKCNzQSlL97BxI4z4mCWhFFM83w6Lp/9D7IEdBJ17o1zeq43sd76VlRUeAVfHJqTZ1AAagQCm1ceBsEPxtODWuByXy3SmKg6KH0iIX8f0J6/T3X0X+j0foFs39hKWIBzoPW6mV5edFKhOdYzOqtfY9+066g2WEeBRgpDqUxWuTW2sjOATz6i0qqsa9aldIB0BfwyMMns60BZ6jKgEGe5EFt71OfiOa/M2ZidqnyLyJa0vWSZq6/++jd0f+kEDtEki0nGNMrlZhwaLHmVbztGfAKvAG6L6+x29Pv9/V3RnCOm79TDGJLc4WwjSjFNj5zOsKg1MrWgYWsWs29JhLBNY6DCYgpoD/+nAEL8oAAAIJTVxgZRQMQ4ab2gTio4iopWkhmKUxE5TvtCOWxgAAIYCFLP0LCwWc8AA6mqLGq0ChUEN3C/D+plRat4V+x//v6v665PnamSxHRtN+v/0f09japGjT74UxY3LJ8vq1AUXooy43LMCkIwFA+IO9yHL4n3aA816Ibarev/yW791F0KWSqRCch0vYZahAtRHbvz8srYooTDwdjGKOEkRUKVfMOKgKagDIt2VDDkWreFjLnpTtVoaKRg7GRAf4Q+BGvjt6uq3CI+mZDLU3x+3Na6muFHe56itxbL4MipwGAo/jLEtU3NSmhVpJBNTJcsbclmO1LpcWAFPbt5hVG8AHc/CR2wgJspXOCCnCx9aK/O/r+P16nVNipahfe2ITglWQqCyp0woWadtK1ndCPFExBTUU//pwBNptAAACCC9YOYcTVD+l+0oY4pSI4Ul9oxyycRYpL7QjilYDgIASUkKj63B269PlR9fj/DaVmBgdCEaxMHaMCmuLy3gf19f39f/hOjNXKNczPPv+/14ixGXWSFKbyJGig/szrwAIgCKbbtMoH/LmC30a+O1pRX7ocWNJRvE3wXFvH/9Ter+Av7fCIurfGrKakU7NP27MSwkJW3n1X9b7VwK7oJkJtaSJSJty58f6YS2c5yOx9CH8cw/i8ousQFr4AtXAA9sZ6t9/K/n8x+rP9vR/J9f+8nOo/5rat4xfRzbp8XNkjTbnWqjvakQU1S023G7kHA9bNYMN3GOp1tKIqiYn4WLXwq3iX9Pjer/f1+D73vsJ1k+jdF/3ST//7eQzozBmV9NXQXCiBZZ/bvVJTyYgpqKAAP/6cgQ28AAAAf4kXWhoKpxDpev9BMdjiL1JY0ScTVEaJ6zkkoqWBBDrQJjbSbt6pgghTkCApNAvrvV4x9YSDI+gfH+EmphH4n5TbIg/W8BCTRpyFTNPz7AqyVdODZZ3r1aPU3bcRCSKkyTrljc1DcAjKhhK6AWYbl8cL0L9Tg5CTKIxejxGb1+b7HbIeeiI41euRf29ydpDIMkft3V63R251erRKkcnWd2AAYgICUnKVBqaPCcMXkog+JyytQwe6YslgnVxd5QOk7kxKR2h/p6m9W//6p9/p9vT6f/JT/t9vtylX0PyDYhoI1pqDO2GAAEwEQWw8YWn1rF5y6EX//MT1S4OpExVj3q5AxOAr9Qn8nxXyeX6fN6P8nu3givwT+3yU0X7fG1MjaSv0CH4BxDgnSmoM7UxBTUU//pwBMuGAAACBEbaSQcTXEKpK2og4nuIRN9tQwiu0RQqreRSjr4ADIDBCemJPkC4QngHDxesXoi0VEF0r1nByHGIEpdjUk9C+o3q3lf39V+329W83//dNHQz9EL4dp9u/dV8Dan+kIhcSSWUFMxL3U4usSN+wRo5Oh8Li2JztIUGPKegSPbN+I+3QYdNDMtDH+3y+VrYJiam2m///+vweTxDkNksHcjVzQAm4FhORyNLX5TGVnJkTb8jCsCx6CoPrDjSVBvv9/iv28Z9vIBvTyGHejevkHc1/kA+zDvCI4mQ1hZwgGhYMCQv+0ARsFGlpSk1QcbEx2pQEWKZoReN6R4Z4f+P+/oO/5BnoXyA3kbkT5O1fZv3T//yMJnJfQ3n8qV5TRPL64QQo4HxANOP+tMQU1FMy45NwP/6cgQRQgAAAgUkW4BmHJBEBHuZDCKwCMQ9hUGERkEMB7BkMIzocqZAnU64k4iEemiJvZAbhMmnrxemVDizAxZ+iJlELd3w7v/hBEEFg4YCwDE4gA/LlHB9jA+IMmin/v//8m3+J2jEoAAA1ExlDinXKxEI9NE/oAMQcDfqH1GNhxb6EJoTU55zn8IcKOJkBrHhYM+fDBccouOOVjnLf4/Yn6/9zFjy/1lwvgFIAAQKTlIIIrmESbOO0tFuy9wahM89VYDIFhNDxZDWGggI2CG+RcGRY+96HvEFChWl7vmVVdTmTRdy9lPGjx6pafNgPFoAwAARb4gQRXZEmNiUMjtDXYLXHhw5EBkCwmh4BbDTBGwQqfIuDIsfeaQ94g1L3u9xlVXU5jTSRq9jUr1rHqpn0rxZMQU1FAAA//pwBEgvAAACFRreAYYZcEQg3BoBgwAIuAuFgKQgIRIH71gWDAjuC4AVLcaUcMX9p/UdqZjzo00oci6WF+S70ihJ0wIlqCiRiQIkzF41hF4BEpcqZa+ce2MCho1Rvm+uyyn6zJZrv09AAbIIFptuEIYqgkmEClHBkUQWtSLBxRMzl0DEC5ZuqHRkCJMxeNFGHiouA0Gey1ww8aNdj+1i7H0J+NMlmnRbcKUitCAGQHUirMhzSCTDRIiOewWHwZgRK3FVFo8kNOtOEIjDwxaGx8o/GEAcNMAMsbaWWywqH1LO/2UdzLtTTtRpohF5gwfPHmDwMADKzCNA/4iNihC5Hny0+EhmCx7ioxTR50ad0Unwkt+BZQCUAoQDzWAGm0tZoJqWd6Dex6NjiNKWKPnVTUq1znNexhpMQf/6cgRPyAALAhEGXSkoGJBCIbuoCYMACIyPbqMEagEdFe5kkYmoC4AKbkQBmB2DmpCWBY2DTUAFyBaaOFQ+I3A2DQJsyIHOJKhNxtDxdLW41yLnrWdehbbamPYy5qbbCyO1Wht/HbaFAQAAAMWNRsEq8DqAjZzJu3qYwkM1gogNvQlQMDkVCwOYKgpHuW0fO0ErqbUUOa4rhRIsp6Bt61KU/r3Rsj0scvADCc80SeNHJy0pKsgESkOdUpYdTvbFQisMQywksQ9TU0YbvHgYBMNEZdDx10VrKxRbw2PWtsXF/adRWLd+u0laq18jXZEgAEIIArUsGB+b+9n9E7M6qFt9W96pYU+zmvI1cmS7dHatlZGpRkfU8o8KLdFayrCK3ht/i4uMs3IrExeffUXcTJXqtPNI19SYgpqK//pwBNk8AAgCHitaAecZ4ENCS60MI2YIXF9lJKBpgRCL7SSTCWjUHdWsjDM6fB6SrSiohhg1C+K/jJz1XaoSiVXiN7Up57Nsd5w4faRp4MJAI01Li4CAxIJNDtGCqqHZ1zH6qehmvX+3pAQAhgCBKbcmFjOZsfhaS2h6pE58jAn2vQJSvI5ZkqMCGLrDAFmTWwuAizRYXHKJLiUt547FH19WhFJXWhC48VMLVSiABAFZJ6QnmBQMGTOYAwtH2ctLw7A6G5Lpo2DBkHCh9RBiyhGfAy7GKhZ21C8WErib7tLiVdS++9UkyvI9G3W8o7uWABwCAt/1saSUYM7Pg8Sinkf8zlK4Eh3mGriMZ8E/cS568V15Y7rBXU5K1PnciPOhJRvLBBR9RQhsquFYiouivKOyU8lMQU1FAP/6cgSolgAAAe8oV4MMGfBEgvt9DMIdCPSxdaEYbSEdB630NIzg1veE6QjfmfU2fBWl+m6K+5A2MrQEaCIiT3WQjSmRBEsgAc2KJ5e8Oc86bmZQ/2FF5lNy3n+zbbX/v6///9oEDHWAQCKTUwtlrxGJ57DkPIy82UHnGyZ4EMnSuYU1GlLVg1lTqeTi7RhIh0zaEjlIFjlxETiO9z860Yl7Pzlx5vePbagADb4HX5ZJr1gItH3M3yFtE64Qzd+rszYGhclGtyDnP784ZykhkJKN+Wt/RSaLBsVXEjzZcECok4LG9Gm6dqHelytvRZdK6wAGa8AiJLdvj0Y13S+IT7X8g3JNdbbBlIMuQpbS3apb3DiU8QlZUk8CuETRSxTxWYuZQmlQxrA5UtW/uXLyw+YQaaelpN1b0xBA//pwBJH3AAgCGTLXKegVIECmSvU9JVoIaKVjJhhLQRwL7bRhlcQAgH2mSI14AOxVoGPp0dDzWvZGZ9LaUPwm8aKXFMg8KxXZfU8BxK1di112SX0RUfv3Rntr312x+CtYz+zToyOY1XfGAEF9rWanHEdItzUG5iAMP9oAMXXZldnV5jUc+0UYjRxe9BwAORZhl/RlvtqjfvmfmZvbfH5pszsNUf119H/2f64QEX/5ulOEAFjxO44+R89/B+PHZbslhg18/PDayuIfLF00LuiM+6PVkJdrp7iTwTa+E2b7N/VU5WItTSX0/endyEXqAYAiwBBjbUrr6Hq4U1g41/8Aco8mrjDeEhTyWvFzKkdqEuE4NJSeVas7QcSsmlQNAKdPA81fR+xxVzws2eZaZel9FlTb6JVMQU1FAP/6cgR2BgAIgh8mWEmLOlBAI0rRJedKCHhfY0WY6oETDW10MxSMAACAWr/5h2ExIKgZKauBm4vkss4/18wLHCxk1UDTeeHqZcqSP2KOZ0p3Siui3Ri1Bixi/VXHjSW5HIfaVRzdf6Gd394PshSAXaLEBZibkLReL4W0RnUl5WeCZ8a5mWtSBMMpng/Z2UfbsULLEClAI96L1DlYC1o0oKmv5DAu1npr+v/omAgpOS6EclQi0wbDQdINvoLa3tcTEYHM6vGr+MbVGA2wit4Ecxro9NyyGKMqPqf17mpQMpU48hFGMVEi0faR39Nj0bIyAQW4ndvIIgireDCkmA+saPssJdoRY3DPcU8g697UnIlAgWuQMHERQwMWHx6D0nkb6szdK5JtITJhZDBc46ZFZ742uSTEFNRQAAAA//pwBMcXAADCHUJb4EEXLEKjeqA9iJAIHF91RIxHMQ8L7Mz2FGwgACJkgQjdJmDuMO7gIkOGsCGK7qLRand+HfoX5fVsrDM7VdpZ1687RmADr/Mr/1f8t1Qa2C1r+gJkRtqTpEco0653Vs+D8I5ckjKBXFrWIBRcIeNR0lEnhcwYkgylbgA6unwXNrYFMw2Bgd99WH8n5MFjyQtW8eSdL4sA7D64tOJ3r+K7OkABeiSkiXLRkYbky1bHgTkZMS7LNUREH1o/BG8G2Zw6y9RIuZHaXqapmp+1a7uvRo2aA6FmnSazgth5KiFD6OL0klppytZ/p8TMyJputPnmRk/T62dXaVjpDo+7RbSEhfwiTDCJ+PelD5TLAJB1zie92pZLyy2kMCvsPKf1MQq69C2fq9KYgpqKZlxybv/6cgRgPAAIAhcX19NLKsBEKFsqZOJcCDhfX0ysqsERG6508wguAA4AAAOSBJcEhThlhoVFkyNz1nOdaCTZUk4TXX5hVG60A87q7PegPbCJqC2zf6ck17UJonCtqho50VmsSoo2/vXr1gASIAY5d+z9U5yiLW5QSWzX7xzCfmXygzYsgoJeb6BrwbdjLkyJYrpbo2/xlbVWsy//PtV/+5PVfUZPsZpK60eQ9TfowEEJK21TQyJFvvxaZc2aQQdq2uNW19xdHOVD/IvOoDUzE+LK6wsX95Jei6hsrkr+KPQxYBFHSMsNgLBGYOut0f+kAAisAIhlIuPBZA+fZefw8JJUF/eCztmRa6ivX69VCjVzejW2+99W7/mbsis8oSaukNmdr8NknNMPSZGDwFYa3SLybe9MQU1FAAAA//pwBOqOAACCH0Nb0eE5HD9DSzphigqIxRllTBxL0QeQbB2HqCABDoSSiiVBoEtpW57hSw4u562S+815V+43dNA7sJxn1fyl+b6NapT5x7UVj07ejP7eO/f7ereUbdn8//0goxxLTtgYPgARACkknISGDAurPKdY3J8MXMhzjdlLxkWgyb5G66ix2F5O9pC2WfRsRPbK27qnev5LEmDFYbw/Sbq7vKaP94ACyEFpNyEkIpPW/d2D8rf8ZsRtPDRlkE5BBx4XL88gMroM+oIX5DwR1woTWj26ev7+jf+d9FT1bwzci/X3Hw3Sz7YvVdvgEK3ZsQeVYtMNHTFGiXoPIsupfoVHiiOOQdE87li6nrKt1Fj1M7FS7tkRjhQ1/W9KnRGbl4sTyWQoO5/fQ/0f5rSmIKaigAAAAP/6cgRsnQAAAiVD2VU84ABCqIsdp5wACLEvcHiRABEYEG7fCiACAACAMyWb8CSTUCK4CmOcSelCEv7/6cKl6ixuCpLoFC93URXoYeL2830PTPX0Pb1+dr/t6v/5v26V56v1k40jQc/rf69QAAAEACTbdAAfRaODZtefWh4mMl/v/uCqedDpFjwVEptBATnnoJ3dEHwnILmlfVzH7eqef9/nfb1/f1+29F9U7S9CCC22223IBBKNH0SyMcGDBY9KXy3JutWUhXgt2MbBtkfEU39ptXtq/ZmmntZK2SmtJJ97pb06XR03stP8FM7foweUQ7//pAFHINkkkklg2BUF5sZGEvqyu9WyuwTdjOiA2wh8b38vnYhwYhNi5g68/GaErHGAfvHKsI2BYdeNV5G1tS1f+tTT+ulJZCkw//pwBAU1AAACJl3hHgSgAEILvHPAFACIuNd7vGOAAQWa73eKUAAAVCoWC0Wic5r///////+vYii5BA2i/xQQFDgiCjzdvpB0aeYjFZSq7p9vFN5xRTq5TjZQ8okWf/5D87qdyN1rUyspljQBEIhIJBIP//////2IouQQ6f4oIChwRBR5u38HRp5iMIspVcwl/4pvOKKdXKcbKHlEiz//IL87qdyN1YbGiSspljVE8+9HmgSiH6ryiunfmjob9M6yqLKNVt0Cwknbvvr0O3/5rTd3VHSn0NSbMbb6qd5BUcOmiLbW/U9vII/dYMJKeayoq56QnWfdJogSiHdLqJnPlFmTA5rOgLVqApdAkHTZu7T9E//Zpd3W6U+jJaRtvqpvFFRw6aI7W/vbyCP3WDCSnvyoq56YgpqKAP/6cgQmtwAAAhk13nhIFQBDRsttFCKyCFCHc6KM6uD/kO0kM5UQIQNhdZM/kimm7HJBGnaCEdRhKGVC7bd6OCqJUYztpTVunzGPuu3+/oVdn9DUe9YsXUoSu+36rS1J0NP8NoasSNs7NIACEMAjAAAAh0l1O64DM3FFvRqPGNvEgUhaJrARZrVPmMdLllGrX3utBKtY/oam/F2sWGtOX9MMlZ6VQZ8q8bFwjV1EBIedARskkJXO0whTCdf8clTg/NG8q16jb0DM7PZG/erSpJVrusjEFynsHRITcSRWKPqMolcWPM4i68JnX9o11VsiIQOCkFNQ4YjCGksDX7E6ko10jB3hY7qBm6N6/96s41vd5GQfU9g6JCbmlaxQ9UZKyuLHmahF10BM6/U0a6q2RTEFNRTMuOTcAAAA//pwBPI1AAAB7EBXAeoS4EKGuvk84lwJHQFvowDuIR6bLrBhFa6rLDXTO4Mk8TGA4C/NGm6FAaJxyj8TepKXtho06CEm3b9/VOjTf2+YV2p0fN4Mvvp/9hVK9bvLXpZ//WzgUACAIJAas137s+FJBntxoI+emsTFqkVEcjoVHGtUCvmAe5f762uoJqNpt7UH//m6Axv/ftxKitM8W9HRYp21ykxEG6SyNAQU5JI44Vs0moyfyaG/0pBbVrN5r9Br4+Q9/u+90aYTPtsr2N3WVJbKz7Jab4pAoiLbVsy2mo6bQLNRYOvr99j+GvlnTtpQJFaKC6Cu5V+4Tv8Wkc1BO+1HiB/I3QR4mCed/M9Lu6yPVXkLVVKzqhB72X6rr6jrMz2Sr/sQdWMNCcUXAKoOPasNes6NtpTEEP/6cAQd7AAIAh42VqnnEvA/qbuNDSInCDyvVgecS4EJGu28NZUMAIL9FZMfcMHeh7Iz12Nwjyg3uij41ikigRB3QfLruJD8Qr5jUe1K7Fo7s9/2XQh2cjLqun3hbbG2Ox3f0WOH/pdqIaQhMPGAS5I5JYtwa71o8YY3LD7V0zP0DtwQnyr7fs3M2rTpvdtvBFzI//3oWq+TtzpuCfp66UT2vUGXvj6Jh30KRrRFEuDkHXDOLLIBvDbLOCY2igqDhx0PULgj4GC5WqMawovqHdvfeOvMdWvbZiq+GPFKEdhFdSNLPXsXs0fps/qAQAQljICY42ZqXTRxk8XrKtj23hb3xN/P4wvoDfX2b3P0kOj9deqJzKv30oyC6xrh9r//n46HA127mEQKMXvYRtj0xBTUUzLjk3AAAAD/+nIEna0ACAIYNlbLChLwQWb73QzlN4icr2VGNOZBGKvtfDWU3AAIAAFaqkFVJmOEKnsldNqqgQHx2o7rIQspOVjdFG5ddSf1Dfub8z9EXKl939jdFP7enf4qS8JoxmvtRTQ7v3d/xalIojyNJNppKbS4JFbKCsjnh+kIikuIj/CLroDv4H7383k+jt3+bLUfffeqOj1XNUd6jmjtsinmP57SE0WoUCyHIUegMatmuusc6CZQfPXFVuP86ULUaUfxIfqJHlQmerq/lfm7b+v7zJg5WBGpvPExKgCLcTv5LbUh5OdMsJGoiJVHsKP35EAAACUUCZTEbuiQichR3xWfSrVQ22phAW1MBB66gN8Dffz/L9//XeQVHk/tv547Mm6f+8n/ppV1vI7NdPv0syWuMfc/NaEpiCmooP/6cARDAAAAgg4dWWhvOLBExXsaJaVMCFExd6CYpDEMFmtcx50AAAAqhADkdtoOMUMPmezj+VBFjsSD2WUWc8KegWIdBr6A8bp8qRiz4Lm4O5O0O+wWCthxJ1MchevV0kIpLP/frd+8AAYAFLZdkjcmIg+qRTtg0P2LHvUnMmjU3jU3UBfgre+sLZ81+87ZS/eswwe8ZUJRRyCKmadGe3YTcJ2LcbIN63cNJ/kAwUI6QWkkk5QVAOhsaptgHDkxb+nxIMTGB4f4B//bzP6epPt9P/WtmsfR/inT9v/mqjvNtGHjxW4k44Haie6sY+PqgACk1ImoypUCkngwG+ZDbDB/EczisGuSPhEN97gxNBEekqG//Kiz2fslEzPm82S741eCa2pYCn/xT3GiuzQYfn9+BkxBTUUAAAD/+nIEQe4ACAIZKVhR6xHwQwUrfAUnO4h8pVlHsadBCBTq5PYp0AAAwDLbt2xPvVAZTVEP9khf+hsP7fNNJbSGv/sOQ0Eg9Ydn6r5gpKzH6pXZPgnKHq8miHKwzUHbX4+tvTbWx/RX+zYQAFDEVqVuM8mF/0yPsz9IEfznVMg+M+PjHQbNWVAJJ1efdKEervn0c1aFG3lFT305BlNod+/1alY1SrioshPdTsd3pAAAQZI2NDfGjj/Ia3kZekAg7A5doBazY/YJO8UWOhDaUQcUTjThM8xIn1es+7ab9SD+v53E3yex/tjWRr9+T8p9P+wACIAAayVeP2d8KY2Bhp5+wAbHrU6vQTcw2/pSnUvIqEMGX8eihOSm+D3zPl/V7UT6+xG0ke3Kh7AMRZX7fs+cb+tMQU1FMy45N//6cAQ9DgAAAhkd2BsGUrBBJGwNGGUfiFiBbYwg4/EZK/D0g4pmAKbm/zC6TzNOZnLZYJpYams3LhI1AcIucq0uyyEP/BklRsW/QY/XyqZPZu2UnWKrLnsrRlo41S7I1GbXdjcs/xXZioBSMUabUkcu54DpWV42HgoLmjrtW7jfhNvE/if/ib+d/FkSuKD4vnKG7XsdU/dW6rEJ1SHuYtdUi4tYoWqJUH/FgASEogDM1vWMjY7SqSH7VeFDr1UQTzWy7leX8Kv408fCb0+aycg+IdGI1CgfRP19+dqzT2G8lkVFw1Ud3SmL5PJ/7gCyZfZHLLbfIh186V6N60E55oiRnqS8Tv4VLrxp8Rn6fFL/+3yfdOr+f1/FSLUlsIbZEfzt1KvNJytyMpv9G9X6ij1vq+QTEFNRQAD/+nIE8hIAAAHtHVjTDyhEQ2Oqw2oHSAj1UW+nmEWRHSswtFQV1gRFwIBSTkfgNihrlPM0x5s4KYdq4CMPqNerVFtIUGrxPxo70+M+K5DAu6tler6NOcqCe6Lj1K+Rz6Yx139QAKKlqCgudd15pewFxoEb3cFsqWoj9dPG0owJRqLrpAwZtKAFluVTxz44PlcE8hn85W+s7VoyGH92NzsJsqc/sxbdnAgYKmmyE5bsNAp2aH1xS3jhKZR/QNzf5H8t4JOQQK6ivVf/X/wRf/YnQvl+zVuRHaCcnMU3+tP+6eMnVtJfiqtjKGyj5f9EkGUzrrY3nJdwo4lo5j44FrgCtpCHd3AFCJ6MbqD+NP7/GFLdUP0/+3q3q/svttR/f6edNZie7ryN1YsvosPOvYrYgBaai+vamIKaiv/6cATtYgAAgg1WYehFEsxAKstZQOJPiK1nfbSRADEaF2uqsnAAFTq81jc1tl4JwQqGEXxQGPua+MBqvCfzep/BgXifOBjXdV7Hv29BK+R+C+e+jG7l8sv+v1+T7ev0+I9G8EAZr6NoAG6g0rYQQqSkJNImR/BIXumLjJqFGq6iOMeTficNeFJ43xb9X5TG8nglXq3gv16F+T2p/r9f/jerbU+N9vBOoDCp7rTajckw1tZ12M1TuLrO/fkICaR4X1Hbgx/Yfzeoj3P5Xfm9HT29fmV2k3LBovNT/Bu3I5+rc1+v/ovo3nZ+BN67SgwACGSbA2BiVexTtzgWQwqkliLM///VomuwqIGDhNgWkeooL7iEt5hnjZtlFk255P7+/3bqzcfN11fLI9u71fTiM1Roz39SYgpqKAD/+nIE1ZoAAAITL1qeMEAARGXrg8SIAIi0r3pckQABExXwZ4wgBChAZBQAAAlomoIn0dVlIoryiU4pigrdjODciLUm8qpSWse9rGslrz3uv+7POlbS3LSY45xtmv+kh/9yUBE3//+6kgUYy2ZDAZUhiaVnlh5Z64fdz3jt5XRDTg8nbrWae2ZCpa88xHV/vdtUrbR8245xt93XbpIKer/clARNlJX58Ve++jdSQpVWoCAAA4bEhpeKtMNR35qodb23IWZ53ZS3Wl+9jdrpeLrWj39H3c0SSFWLE0OgWnJ3UipO5PzzpKeTotUixJJzMqbc/cAAF38otBgAQTUu8llVP+aqHVjSZiFYx0u1hnLkfnlN29561o9/Tu5okkKsiaHUU5O6kKk7k9UOHZKeTotVsSSczKm79yYggP/6cATKCAAAge0P3IHmEMBC4fuVYMUaCQjZi6MURfEYmy1BhYi4VwGwTPZxjoGVZOR20IuIvCD1BHlX0rOJ2UtTyQKCxtmwVGA2HOcWmpS4DYQFqCbPjlPYEWAmnncNMvK7f1gEsGGhwS7+mBrgN3Tkdsthb+ENQoHix2lbk5GTUHbgoSBQWNs4qMDrOxaalLgOQFsmz45T2BFgJp7swyHSq3N6FyrgVAVUkzGkSVgCTrT0rkj7DAF73prDXwL/bCOisKZdPUqhamrFb+m+gpHIh07MyV8Lba2RRixzoHhEVedh0+BfOjjtYJxpvWut3DvBr7hU+jxxzpHwgBy3if4h8CkZQ0oGXL06tpTN5ralUtTK02/pvoKRyIdOzMlfC22tkUYsc6B5xbzsOnwL7Rx2sE/11piCmor/+nIE2N4ACAISQFmLKRJgQagcKSTiGYiAe2rMpaGhFxGszaaI+AHEDQHZa5F5xkNu01irwbKC/9E2bYp7GT3lQdBafsQz9aUbCk/y2l48qs3y/9X0T8v+K//LbTDu3VjnruX9f1/640nO+qumsYCJht1aswkIH0NwfDjbCtAr6wVef09rT95St+Xb++iH+X/Fbf8qlSmHbRkzwwkgc1HnQmd5J558rsOoJoAWJxi5kibMQONRHmrZWf/auonKRmJTrKIamzMtXXTq1HDPqfqVmURuFjtvNDWtsfGqxP/LIKnEtaXtvP55H/X2bKouAA2nIIoCEF+UxS7fviwdMrDQacz5OUarDCm8jJax1Prlq1sIL99G5v1CHlXv0FWIFi19lb/+UGetJgjaWhritlVsnwynWmIKaigAAP/6cARiugAAAgo14ukCK+xDRqtaYScGCETXi6KMXjEYpvN0M4neCjFdUabbkjpxtqcVHOyDL/Cbqg8g+ABej+nzgunjXr/d//tWg5KL7yqxaagZZRQvIG+SnhVUIOuZMfV6HVuwlIOAAIQAiSy0MEHNaZQsNUF6iQIwdqKuKUuJIvUwg/CR9OnPKdmyjXt/KHfSiXM9v29a+VPQjY3y7vUxaL0M6frR6h7+sSMJyMtOyuSjYtlZEzI/AvJxj7O+Uf7bZBvXhQir3dmcdVzaEb6vNA6GU6USWp/E1+B5+GvU3GiRKGJv0bAYduz/UNNJfrdJt9t7khyEnm43uF4q4meiE6oC9/07N/BDK/qb3Q6N+prpFuxwyMzppVTajaMSz1ZX2XhW/rSl0SnfBP3R9Mo5Xm0xBTUUAAD/+nIEgH0AAAIeHNvRgTiUQIa8PRQiuYjo13+hlEdxGBruKJKJKhAFwAJbbkdAy+7GoOzoindA9jkG3ED5E7ir59NFKPmPoXq6BgUHUj0pVSXmfITy1VOb/SuUO1hEO6bQ6lqDDlDtD5isyQk1MIqORysCj5Bccz5VbUDdVeb34S+5ZF4eIKdcPP/8uA9szsjEN60EmhxgFToKsoR/SPFmrOB32sO4KmFei0EIA1lkpttuAmM+vS6XxoS68KJDiQvB/Sg9ByNgn6Gw/bVW7p3sj5j+3rYjnnggNjniy15ckQ0NPi6jp4XpSyT0JTM91TZqsCAgAC25JRgJn7w7G0OQ8F9gzjFy6jQbiftR6IvBcG4J0PchnqW/T/0S2/0Yju+guE1KXbFSXpErmHa41H1Hu2pzFhVEOpTEEP/6cATsdwAAAewYWrjLEXBDiQtnJKJmiN0fiaGYTDEOEu7oI48OAYAFb9+FCEdcMvhlePKq/63O2fKjKKTM+Gf2qKpD1YXnLKN6hybG07l3jEsaoMvajV6GEUxBvAvtspDv1uAYAA3JI04/XyfBbeFVX+heFrhDKA4tzeg1Hoorr1f/52R6n0dO+rPv6Va/UJBd2pVE2q9a78zamUUUtYPF9FSHKkVJLMCedTSktt1kfiW+1H7oX0KJKO1FJwfS1WpJ06iv6NqvRvR9XtkqvWVA1mqZHLsM/NIm1kL6Li3K47tFRKEyfukW4a+s0xIkBAAFNpOA1HwSHD4FfR+l5moHbv0QvoeGOnKjKv1p6ptwRlnNUFHHXriISys5WXut/PrWUOrCYopcTDEMEFiDe7NSCYgpqKAAAAD/+nIE9dMAAAIKN1iZjSswRGkL6gziV4iU23tEBFcxD5uv9FSKTiA27dmFghVUE81kABbYRVgz6s25PlOVkG5JBYkwV8xB1T6gG340Udp6ltp6v9/V9KfZrt5Yjsi1vd1Ealt7TH+G7oHqQLbblgYNI5Gnqj8v1QvC41w43AG6atVF6+Ou3P01sf7+p/T6MTW9kBrtb59P6/TSog8QQ0YOKqDF5hCnCc5Qijx9mBtMFJtywLFDsaWjXtF+NT9NtR2gsEbcBN/zc65eHr+S9frm/JeN730JBj5sa0U0IT0PtUwoSBUJRCpdtDWHUOIC+ybRJBkabCrkcsj6pfDwDPqIc14RbtVGznSEOf6tVBXJwQokwPXNT5PstNfM2mymZkx4V3B+fYz/GSo1Vw4W30lN0X019KYgpqKAAP/6cAQ/EwAAghEr3NAmEERBxvsqMOJcCFEZeaEYTDERm63ocIrKAQEgFN23aGM0gvROcaCH43cG1GpFc/W9REGydPRc3Tp8352ZIAYLD2LF6Vl4Rxvr1vgF7xrGJi4L0OqvUVi74lVJAAYgADJv+Xz9Z8sWqFLsgdHy/LcxHiIHqKDz9Q18XROMVi+bo3ff0L7t7v5Pt1Vv1bG3hijUyvKrmpmkVb/072/SCGAISQEm25U1ICEQWKBP4gF5V0ahRHEfJjVEH6eM3/dB25V+/23UM3Uqe9KBtPbU+uX0P4bTasiKnj3JKcLEctpyjoEFOWbDqFrpQIniUVfEQWc+8TY8r8MfU1NA5rQZX+ni/b6v4oRegJupPvWQMLPSS8ppz2GDlgsETyn0FsuLNLUJrKZdMQU1FMy45Nz/+nIED+YAAAIhWF7QQSusQgjMPQyiX4jRX31BHLoxF6vuqGEVNhECURMbbmQpUY7T4kF4/I1JSS0AId56Lnb3woOmH1mEHbQT9E8r9Wb1b6f6R/2f/Q3yfdMlqat6/9bdjihAsg3K2F6VORgvJttySXeQSp976q+JAH0VJmxHoLNpeNbgvToNf69V+n39Rvdvb6U7/L1XTN8J7C2QYeSMOGHbD8VikAb62y+LeQGyUo5Jcc5WdUOXMC8A6y3ajew2stBWEN/KB6l5mn3fuvyPyq/KCV1emraRlHzl/2jvRvGOtnf5XfKT1ZrkTWwiyihO3J1oMCQGk3L0hsoZOCPMg+hutqtUKI5xvXfI/Xwxx5ATR+pn9f/l9R32yZFqqU5/+zDvZtlI+ssvKlVt6yaDPKIsghJXs2E0wP/6cAQJLQAAAiBg2hkqEtRDyMszJOJmh81hd0GUR/EQLXA0kJQeICakuOmZzUg1Aa2xSDA04t8xR2RjkopjZMKNZNtS9OiK090+CfRk/+b7ff/7dSev0b0bu+joT5v/trT5HXi/V21jVhsAJKW0oI0768LA3V2Uf8nxQhOblCoMbBtrJj507cGdSIsyL5vk/9Tfb9etKu7N27K25w1HZoncoJ1gElvksMWJz/3Vv1haAlNJx0KAyCYxDc4SDNQA7rq1H8LHavofEm5zaB0KjVQ3m+n/xPp/6/g69dG0WcF8i3rX3+X//+2C53dKRpBGOIlOSW8DkTbNtYinUBOJoJX0cd2/3y+bqPtfp0JexUpy/Hej+reteWta/9SOvOXLOVeavHff1b0a1wg/cV0ZxsmmIKaimZccm4D/+nAEASIAAAINOF3tIOAMQ6hr/aQcAYh5k3A4YQABDDJuRxJQAgSiA4AAW23JtDHw6VWMgd0QDqXHbV0d+V+u+X/1Dym2c7Tx84hzF/85Ogoe2O+pltSXf6tejP3gTPTITUo5ur+nQkoAa02U5JbbWJggezfAytMBvHLVeYJRtXCf771Obr5dPp56meVvs/jhDsUfzfp0PT5/TvnV5VJYhnzlHpCbpjdX9OVABJcCJcMDGL4OoAhLB9y+otGJMLZQslCPOpaInrpIQh1//cAIST//IBgbuEEf//gZ3bkb///z3Jc53J/////YDP74twASchjUoFbTITAZZp9T1Cmi4sQZc1iu2j3ta3r7EIdf/4oRpP/8gfF7kJ//+BzuTkb///zu4ornO5E/////YPn98XdMQU1FAAAA//pyBF6SAAACI1Zk1hSgBEUKzKrClACImTOHvLEAIRCmcb+OIAQBADSDBgQBgQCAQBCTBMpRyVk+UWTq39FMX/Kh2b/ylGCZ0//LCRiGL//iTi5USNL//+LO0aHlFVRP///MhDqLIqj0QaAABhBgwIAwKBQKBJMEy2Tk+UW+z/1M3+yKzf+VUE3T/9YkZjF//w8PFyoMMJl///Bhdo0BlFRqDP///MQhxoGMdR4xAmAK0rrra20nFRehEyoht3zX9rqjaXv0+ly7uTpp/u91uhqo715DPYrzI/N27IlK5/R/ov7dN9qkW4cghM+OP8RUNyyLjAAJISNCv/7ZJMoXSqoh7VVu65+mdm99VehU2JlM9P93ut0M7o715He1+/fdkyolK5/R/ov7dN9q1waMT6j/BqgllkXGEwD/+nAEQGAAAAIhNd7pgRGYPQbMbRgiFYjQ12SssKMBGaBxtGCIjgAqFLlKmSAVCMbrcgfoeg5eM7SOfyq+ggnU6Vrbu/p0MwgykNl3T29ROl26lb+Ak6Ovt96nkBLlFuvesJFjsSnlE3/IhptTSKRtIkp1DwVCHWQGWjl7Lpr6CRWoMVR9qZn/6M2Q2XdPbwYnS7dSt/AVfGdut/SsipbtyPErD2Ev9QCCHGHD3DXiy80DTI1t7F8TX5jGNxplRphpOGt4vR7CQjqKdG70R6slH3+32lmoZ6l16oLN04VdkSMjlr3Vsb7Q193LKz1oTjM0kbkcTcKHlpvDidQb3QncG223hn6r6OupPtnperJR9/t5SyuY6GeUB19BX/5lLosE4is0jnuKj2E08NhpnufqUuHWk0xBTUUA//pyBLeZAACCCTXbUwkQUEMICyJpYi4IpNdrTCThQRsa7FmmHCACAQCC7LbQp4PUotYjSTrbLFX+j/auDVtS/NvS/PwTPvp1KnZ2rIfqUyJ16qsj0oLO5f1JPsaepzJnO+5Xqd99FYDf+YScbMBEIahVO6RD8WB/meDv7Vb1VtMy+N4MNRaIn+M+n/t9c6OVnOhtLZVWT4/9LX9kuHN05oTL2lf/kLOe3LaAAYBBct2wN4nHyxtC3hf8Kxf5T2RpXNduZ9t5R/blGM/6mMy/tRZ80pnLRXm+3hpblrzGoMwoM1XlkzaKb1KXYMdu00vQh3XmLjDRNO0wkeXDhNhSJxnMF+yFXmkVCpqcl6jDRmh69eUK7OzquzWtXrKHO5p/5ypOT+pK6W/M/U9lMeQ7aupyuSM9DUxBTUX/+nAENdcACAIdNdiR5xNQQugLGUGFCgiAYWDMPWEBBZsw9HCLVgG/8B7AEkGKrCyjWUm9jCVib1cneeUITXlBc3A99VEvegGn9KbaPqRWRGLvRnqqHa788im/Ubjpcw3Dv9Q/Tr/iB/9gAAFANf4EcAcNoYWudQbaExVQZv6hECRpYCCwJqEx/QP1NQf6ePTfQ27zls379eqUt07ak0rv01Z9hJ/tFf3enwz+9CD1+5JAuKxIFmcMHXjhaRcP02qSvzihboXaA5+pMRrfsehcfBQtuW8YdS5QDFxUks4DEeS9vuvs3oo/JJVsu3a3ZH7BJCVKlG5I3LKmkyR7Muar8vsZb0+JAbXcyrZQzq3kqyXLea+DIbV3qBt141xO06v/1oDKGCFYSfWiXEFRF5LLXTKYgpqKAAAA//pyBPaWAACCGjZb0ScR+EQFe0os4qIIiQFpRJyqAQ+b7OiRFSACAgEi5JNUAmfCZ1Dy2Bwq8a8+9NBnwoMrTZGoHf+Dfvs3d3366nepSv2r6s/oD2UWLfHv9bUqEphIQMrmBSJUZv66gAD0LDl22GwAYsqm8B88enr9tLNt8G/FaR9fiAvo4jNNqHP/n5tG6o3p89cO3qKhnNxItRVbJxKUq1tSe4Wb+7S+7UaAAIQguzfcRKiZdamsJtwZCjcAuRSbTgy8ID/PRqDE68a5H/5X00bRid0N/5znt0OtGd2m3ZC1ZhtaxlCVqUiM/5Yz8XIAFOTX8FjI61MqrxXKJYfOK5VFbVBycK6RrdQ4O79QY4+Wtum3tbJSaYv/Kc+iqJLiQ1ddC/7WEjUMGvetj3Sp56vySYgpqKD/+nAEW68ADAIRKVkZhxNAQ8UrGjEFSgiM32BnnEuBGZvtKJMVUgA5Nti+JJkwp/JFPaftKJwl5OLZVohObiB+uCahm7dXkV+bmv6/FJYK+4Nqah7A811wetXZdKqCS2uKOr9/O6cV9QAAYICS22jWckT7Vj8sxYC7X6BWXxaZxo7ljWwMyarth43XjRBSVmQzda5RvqBhsSoqiUslSzs1O988dodW3tqr/2/WAE5dtMYbC4P8v7EAh8sBwZ0CbkOZgaZ4WLarlNArczeZik5+pPr8LXQVvUulnN1l4MxxI4ckiyyZGjXO0E0eaGYr+3qEQnBAJuOVlDUcEFaNbwwvf6Dxtr6tUd4KKe3xNf6ipGm7+0irK+8Rq5iG0/cl6VdrxowqzR/qpS5yWOf6nwTCO6KoNkZkYmII//pyBFxzAAACDSlbUOEdpEIjCuo9B1gI9N11QxxO8R8b7igiiQYAAgUQo5LUMaXHGYR0YPKtuEvdX2mkG5QYMncnt8+SusnvSpnmzX6KyW+sP7AyePb7Xd/StACFLXvT81gGh1S66mgAJACCk7bGgnjDfm8hlzDxUh5J0cGLW8VhO+QBAzQDi3iVl6CDuWBrb4BTVlqz/tbseplOqKJj+oKU7XGXeK9DP6KQLSaKTTdKTJzC86H5E/P2Hdl1zyzNUbhyUOd/YnToxN9Plfr+H2Dl5pS5Fb+fBnLcF3IBh92TJljjaU3x+o0osS81MDFhwaBBUJJSaTigDtDjRGCh32fct6vQQfihvB70KnXxCfp001VuQ7ArrcllbKcSXpUlAZQkhm3bJbB8RA2A3g6SM2tT2BUxvk6qBoD/+nAEpPUAAAITLFlR6xJUQkbbNyTifIiZWXWhHEwxDast6FGLwgACAABTckgM0WtSpvo6o2BEj8MGj95i/RXkg1q4VuoraCYvXozt9/Z/b1K7uUVGx8eLdjWbpzCW84o20SGert2dHWAgANuSQqybiyCrUCLeBpPf5GOhVKvHyIfyJbqd6V68oBVC6MZMKPolby9A7eZ+idzsmrraDFddGTJTmZXM+1Nen3AggOMokstOVJsQOcLgIDygT9FeEHjN4d+DarUR+TmKSo/X//ubqBN19/3fgz/9E86/+5V7O9EJWhmNqb+lwYlG9qbHwEIAwACjsu1x7uID4XgCNfQD9VbeQqc/r86CXbjAd0vEm+3/vy8FoZyzu5ffwbf9G89elO6+3q1EO73qGe3Rng4/k9m5MQU1FAAA//pyBE4MAAACDlDf6GUUfERKGvM9QlwIfN1zoySsMRAv7ihjiT4sMCzFRKuSXRHF4IQc9gJFzHWF9Mzc4QHrjRSrVL78a5HUjKOO+n09TNyg9f6f16jr0p39X/fs/q3ttVuo2IHRT6QBJLf0m0rbO2C7OqG5XIRoSRTqPuPI33hkOAk2RtaLxCbQYwXnbBBillxvR7afRfHf//XrBjt0+/q/r///TX42QdT/6iQQJWQSUW26waM5NHBf6KA2dGRF3QXnarej9QWrRo5O3V327e/r9jdQ1ftzez+IAxFgh3YidTSbWp1Gj5rJ55ij9WUQIAwxJRTbsjorLnr8HKl9T+6F/JlB1sd+Eu1W8vRX9WT3/8vqK+7+XuqMkGjUy0/0vdj/fzN117eb7t3PJe7eeS4JqDKYgpqKAAD/+nAEHTAAAAIdNFedPOAAQsOq06eoAAiJh2zYkQABFjEtSxhQAAADtv4ajjwXAJK50H49fi+gxP817HBo8DWiKOD7zBIfVybq0qWGOd7t9/v/8q2wwTXVGTN9Sp+ROVAKIP3IOZ3Z/F9IIAcuyInZMM4usr8tsFnADSGJu929iogiXFJ4zaC6FMG59B663KE9D8cHiaeXN06fm5QN2s216WRbEGj5zO7KtGNywEAAkQYYZf7AxEHAaC4nmIxBnN8e9aOYhHcM5QY46JKywTpTzt1+3/3v//9sv//+pkbU////7oEHZXVyf//yN/9YtSdQAYYY47232Bo+DU6KapN8P0VwM6jDkgIPi+As3ES4x923VqRv//zX///SWn//6mTqf//v/mQOD2K6nJ///b/3dWFxoi+KpiCA//pyBBAIAAACJxdgbwRgAESi7C3giAAIpJF8JiBpQRQSLwAWIBBQAAJIAEgpykNgIjINs3Nnv2KabmjsnKX/C0FnHwfQTy78TqcwTxO9RzXEawsA0S4WXrD5Dz/Lgglb/3dZ8swves+uPAsZKKYAQKKcuMDIEZKxXGx8516uxzM9SfaQWzJlErgd9QnFnME8TvUc1y6wsA8uFl7Q+GPD3WCBe/b3dZ8sES7HrPrjwZA/JKYVtHsC5bkI9JrUNFhyBOpqDXduAJEWTmzFozMdb5/2GxHSI8dGeakNHZ9q5hiBhUetijxZ+j7o6hNel/fQBqOdq1WNYD2lKEqB3xjrUkwxTWSACOtENPE7QxK1XUw11wUUdci1/fdrFxTErWw8lhVrwVOuPtAcAsKuQtco8s/R/Vp/78DfO1D/+nAEl1MABPIYFV4pLROQQsK7oD2CHgigSXanjacBFIyugPSM8AMCfdAeCk0Kqtlr2e5WzXTj+FMljmRroafUFOIDQPCoTmFtYBjiwGORP1DjIV64cdesnATg4tLjLnyWxG65aK9O6yjMhmixRH5VgjVOSj7urnXe3RZHkCSEmtB0pEA0ES4OC4shxdUOUB8UcB1xEQAyWIhss6Xi+HEuOmkBxNerrmrdu++oIEcSpEjpZ1/KOONMtV26JqKbIVG1HnVQ8dCABKkAiUAWDJmsIm2ohh9g0BHnoY/uvpe7em90xFUZcw1VovTSl4xW3a2v2LNQxWlfunNDBbx8D1SXw4GYfe+iXpcPNCpMi5YzHgLBky9YRNnbXHrFljwXQc1OdfS91Dy97picQ6Xc1VraSpZOrJ8mmIKa//pyBBBLAAACFgxeyGFjgEJoC6U8Ip4H8GFwIzxwARuIMPQhlCxAi4VG79jgdXCi2qUFmTrojgbuZdW9Bixwx7daxOuQa9MYFEBYPjTx6WNNNpFIe6aQ2DJ3aPe/1PUptCCTnOV3yKpkBAP5ypYks0GPAq7lxreZG//2uNvetxrGYiqRsoJE5h8zoxzyhfLV6bbWQuxOabiLtV9+6ugVuTNL2Jqq6LervpVOjv5sxSAgejyLRP7lY8sFCVUvLTvKs45SzJnBCYcwFSQBeBmqekDGHLe+fDqK001UlabDNhF2xj06m+h1NOv/Rii5aDZJZHJoek5Q1xERfA3qBPSPrCVBd5YLE0PJIpCgeVESnOYOHgoPNu00j1UlaWTKBUROtkRzkwM3yBhSVFr1ltkynOkUxBTUUzLjk3D/+nAEwV0ABAIGHFmBLzFgQKZLMD0Clgh4YWzDLEWhHJHt6LCKQLguJVgQEGbmLZj724X1RYtiPogRaZ/yFK7aOaqfLjO1bIV/Lt1A6ZUDLWnk2MQ9hZABDwKETxY85BtLlf///f+iuXqsetA0kFbCJlprPa1B6riU7AJ2NipyTJSAeb6lDK+jXIqk+FK16XZF3VW1nlMiPRNW6O+CPb0jKPr/Z//6PRgCszy5Y4kiDxkrJI02eod5ZaQx5qqDdWfy3uwMxFU44tTSqAg2QtDoGeLFhYQoVPKTZHnsSrQWa2iGkRvZ9EM99NT1QCYgFG5LbqsmlhYyWk5TZHBC3nzQQhVcwWuDuZt1qLDEKxDG0d0MtL/BH6DWxLA0NLBx+4m8NV1NS9Z1iEams0OTo9Mo9XoTEFNRQAAA//pwBDJqAAAB/iReyOEczEADKwE/CIAIqGNrQTCjwR0WbdxnigLAlVVqldUsYrljkFsquhPOoHTOS6vgURExkQy5PL8ldBRHR4iHmDYoIMUMFV0dOswpHtsW1V3pdprU9NTTEnUoHvldNxcooyis9CGIuPFxleOOmWFXpTBFZBYsejkc4DLcZU0tWNO1LYLGb4x+1LnkWboq8VUtcwtPRVR+jX/qpwAAAAmWW2zDrHg7QI7D/dKvmbjedS+hC3GiXROH7pkPpjAyTv71oIPIDwLGOAdpdhFzUSu9blPCJeyta3j1s6NXH8z/nkIEhJtuNLFiE9DJsFxcfuO7PjcU+5JbkbFM4Lkd74T9W0ulO8ztvM1UJzILF0nbhfQ4gwyZnYHjqu2zejvZnSxIyPf1HZVSExBTUUAAAP/6cgR5UgAEAhIY2hlvGPBEBJs3PGeUCIxjaOexCQEVEq60ExRkAMkkg7UDRmQoZMHUqepWN9L7N9JizUgZoZSsKLoBnOUV9NEA5KEBRh0QgqPPEBGckjKx6B9QowK6l0OZS3RTrV17gIAFJuWyY8kVNotxrBT0fUD+Vk+myQ7xuXuoatE6ucPxa8mGhHuqUdH1m/y+sE5djgkm+wfamKFu/hLFVWZxaPezSToCASblt+mo/4SPJiefsGLcB13pR8zj9kHDlEzarZ1cCDG1RZnzUuESBg8NO2JeBAmls6o11ebr35U1Cs07O73Rfs+xX1sgIdACN22zeCFNIvDMGylCGC7qUI18e2OM6PYEdlZYQyrr223349AqVcoVsatiFKDYFKk1qIrtqq/b2kVlLQstNjXN+xCYgpqK//pwBFSmAAACES9eSKgUPECm64oFZSyIyFVqYLIB4Q2SbugziWaABAqe6usYVWDaHRDtjtpQE67Zu6XBcydWxfSrVv1Zc1S6kfZHvppKZ6uuEoipE2NGoJ0PdVF3ZqdSipF69Kt/7YpAAoATTckhhNmzHmCe6lfg/6LkAapj6m5ksbDWVR0oWRZnZW//Z3TeZ2JVUq3p916XIzCKDaj5Crz2shQr1EvuqILbUuuSanPA0NtuWn4Gf9CZmybToLzHKOzLWVZ7z6FmHPiE4WdOEGEDla2mCCBsQRymOz5PlCajjnOc76UPe5/NvtQ79RrQBQQS0inLCGClTKtavppQMMnixsLb1WvO++EZa1c3lRWEE1hrt1WJFLVrpfuOikQdHTOhlD3Hw0GXDmpYVElbnz2lSYgpqKAAAP/6cgSBogAMAhsY2ZnhLKBEROu6DEN8iDhlZmeMsgEPjGzc8RpQBLkv/pmVBMyGDYpEgoBwhPLahH3rDfAlBFV6EQDXNZBFRpIGV2iHck+gu9oprS5SnSMwcK1/WiJQ6gqtt6/vZ8ptrRgAwISllu5LR3GzbEpwygfdgQmjVRunbSy0hNeH1fbq7WhQPNyFNNDFKCUQY5Qlnghqbijrrm5/EVSh8gh6VIdEvwFpSAXLf/jFSkVEUzkpGhN7vMLW4aW165iBZfJLGFtur6QTsxgPVLPHcWWee2sDxVYMyFNqnEZL4sNvekOIpXUp+vp9EAAC5d//ap4NThJhvwj4+Gr7ytfTXRnEu57GWgpsOWja2y8g8hYmricRWOSWkzjlVRcZanpScgikg+C15KOvZsU9PTuTEFNRQAAA//pwBJ1tAAACHCTZmY0rlEKny3oNpXKItQ97Q4RcsPYfLqhwjn4AJtySesT2SuVxszo/Oa33IbFUnBgGGWvQ4a2KR6bh/Rqh78Q0/o20EAzQ4MZQ16iJU7Dr1qW6mSIIaRaklSr0/8ph6ABAAU1JbbwDG5hKESQbojZyKE4nWJo210a69HgI+2hVu//u3v6K1bSUbqyO972Tu+1d0EhrTm4WQe3F3vZwNVOU9GAHTAmOOTKdMdyrJag67qR7Fw7dJ5fvdNSWllLflD5qGK9lV0Rx9LidoK9Uqll4dTll4cpnY3xkBV77lrqV9uEXTeJotkMAFBAKTTdUvHHPu83Ks6C3qOAtq2et2WYu8813//IYeYPeQz1NfLH1XXy7KDBacS+jQ6SVf0b0pFnVE17KkxBTUUzLjk3AAP/6cgTcIwAAAiAVWzkDKrRCwqrzPSWSCEz7d0KEfnD6Hy5oM4mSgaCm5Lt1AP0UGXLgmomU9w8UB4iqF22TbDIdAjtAdY2eTLn5CBDaQS2l7otqQm69DBI/citJ0sF7WsEpA1bdQmvKRaoAJS7bzLgjaHJaSMnZiveQk7PFXjrzZtXBAgztKQ+r5i7v7UaTgDIz5hxQ9oelYjfW/9sfkr2KO4eUVfMbkW9K7f+iABgSU23JbxhUK5L03QU0oTZKs2HzNayrvQM149aNT7qruGvsLv1hM/Tv17Dc1nyQigpTAJoJAWLucrDMopTKnf/IYAACEo7dvlgQzTSpxDqLtDxMCNKVJ1TfDXThPx1mahPf39/bqVqqX19e13/+ihnRatxFHlH2WLs7BBjC1xByYgpqKZlxybgAAAAA//pwBNVLAAACH0NavSTgCEPn25einAGIQTV2GGKAARQmrwcQcAACDJst//qAZNuIDb9YzXfKdUuYIgIsVqqlkngsHiK0MdaXODf5prmzXatXpc5+d5ujGed7P16X2/N8avzX5U9+V3V/0QIATTTlkip4xzoKrTCwJqw8TdfLcxProbOEN25t7bdvOOfV+y+nobWvm/fr+t46fJPKhvxKDZYPkgRNST3nBVUcz1ellufJicw0m59coIUeURDQgO31L0/yK/P5Ti5n/k8TlIYb/q/iAiEDjxgj/yf5xVyFdWN/9//M73D48A//9IVnxZBQEknH7yc7MZJeNmSgADLEwJD7pd5Bi/mdlTfr6yZ3/8q46OHFf/8cHRMeXKDv/b/PIuxrqx3///nO9xuPAP//SFXnxZBRMQU1FP/6cgSpGAAAAh0S4m8UoAhDRBvZ5ZQACGkxdyQEV4EOJi/0gIr04jlh210aRJVLRBGOR3VEwfGOJAjTLSroMFEQFgRFVoBYwtegTMGsE5DwuPMRHI1ZQbXPLMFiyOj3aZD7mqhlN+Im2VYBJS6qq8a1IRU0y9lbhOAxjKUTq7ZuRsiob1yvbluiMyiTBrBOQ8LjzCxHI1LlBtc8swWLGG6Ol2WkPuaqGU34ibZVgKAXwAtpB9n1RmnOPgMgu6fGC/NczEXniZiBYSZlvLn/rE9Gq/5jUP9OV8/zLVsvCT/Pxd8rO4YDa+HV1j8PLrCdN1BBYGUrZIAC65t6pPj78NEzIyBG5TnYp6FwQasycqFlX/rELRow6r41D/TMrLP1MnDcvCT/Pxd8rO4YDa+HV4/JaxtKYgpqKAAA//pwBOqMAAACEjXeyGcTKEPmu/0UIscIxTN9QZRL4RUmb/RQi1QAMES+Vf6IQK5N2XSVBB2ZXD6t24Vqtv9FKxW6+YxXxK+j7ZfmeqfRH+kMn2LI7E1vPCJrRfDf1AYS5IiWFtTWJJJwAKQrj0bSSlVIQadjarFMHIacwpUd2YfCx0o6UZQ/JIK/yaeH5PqH4nMvkT/SGT01kdmt7BRrRfM/UBhLkiJZvaxJJIGaIu7Wu7fXZA/SZ7rQFeaQNq1bPibxuZr7Q3VmmH9arKTmRHr38Glyvs1O/qJ/r9SrS4/2f07WPc0a2ZGRJuxQGvMZ0kQ4ACQsJv2zuyKqmIJ10WH8BAekQVkbyPGttQ+rIYLqVkkfMPmmiEAnMn+PYW6139RP/+2lx//9dlu8a2ZVJPu2PfqdtJEEwP/6cgRamwAAAgk121ErErBByAv5DOJViPEBg6OFGrEdIDE0FImWwAAAFuSSSPKiIGTjLymOhD0sQhB7kcqGWqzKYQd4TLvuqooAtlaj/u+hHt63aXSzb/tl8GI6Iu/u2fTv/8Wd83XgMmzTzXvYMGpoRvjmEYkbHF7JdCDwbedrq+CXtv/8j1e8qP2aUv/9vUb/Zt9XbEJeW0iIduNtduuVrISKGQ8aY1dIZSCSSkbbUYhV1YkfPdF5dqIKDq6nIpeP269aGBKZP1A5Z5SJe5GPiwEeaqfja/lQI/PDyMj5evX0KGXOdQ1nd+yuEdPZfbyC0RWzHZG3Qgm2FipZ/qEtKplQx/q5L146ruprL/JRVRymur6X1q+z4N6k305lVqCffLf0bwzvnivqduqZlRC88igwBmugsmII//pwBOcXAAACCTXamSsSsEDpy2oxolYI0NdzQyxMkQ+a7VyXiVgJSS236cBpAu1yVlpyjKoQwoWp+NxG/UwYIPDn9X0ag/5G+7ErZrbMtyOvVWr0a1v0H1tdIW2/L600I/5R92p1NWAAQAOSXa9eScejTAgl2mtVjuoAZZpeVD19TI48l779Mz6POtPifqr9U66zPoy/99H/t1fOXdWX/6oT/qN17LoZAQSANNtyX8oNBVZXVrGXdCViKFSZffQI9ng2hXsiqTemYautm7tg+Xb7K/b7f4/XSG0PTletdg29Gm1THvKHy50fARKkmRAIDK7bb6UEpYEAGNKW0n5ENo3jKZcZsvPt9jLDOPTV5fKxQSvmpz1z1+vt1pI+Rm5VV1dNYp4y5aXXp/tN88322aPzCYgpqKAAAP/6cgRq9QAAQiIk3lBlFAxCw5szAesMCDC7gaCYo7EJEm0o8ZXQwQDURNJJPsMOZGD3LswShx7WBd20CYJ4NAbHDMfUX0wwnX3V03g7N6i2d0OGrFhzShVwTYaijsjx7rJcg6nXxG/fW2REcckkhHkYY0CAWZ3NYbOxli22okqax5BBzUOMVao68w9M97uIWk4SfmK4OmS6DcUQNNnjNLQ4HlfdKdm/Z/J//t1vALJIiRckjbnRkzUXWvk/h0Dg2o260o01PdNFOEFlXM1Sd+U/EQ4zXYjyMdhJkWPzcmn5GQa4X+2p9QTpf3aX2/koAA25Nds46aJgry+TNrk/v3p45SAJQDPGMPwrSQZhTIfOeyEdQG1Tv9b9dhrI6i4O30yaohMsReKYvJbNbNaDP++1MQU1FMy45NwA//pwBEQYAACCEyXZGYkrsEPjG1oF6QwIWJWBQCChsQySrVyWiZIFR2W2akMcwnUZU/LQwPYWA3wNQec5bBgIZR+Hhal+2LV8iUSOAui7ZS/7PoK1NkQK97Ras6tsb+b7PvPHW5Nv0p0AABAJLNd/XVZvlmxLDY5vqdqTem4DmcfF4fU37XzqZzmXO72qyoU4hgs8NxZTUKztsvNNhKmt1PVv69no9jbKZLX+2kFUa23HJJZgxo6h79OgResYGMgaVbhINiJOtdDUf9eZe3N49/WtK9YwOjlpPBp6DSShCKQ5RH7J1Arf7hr6yW6pdeogSSckn2wwGFBOLSoWnejk6G4St1sT6x10CYJr5GR0ZjASvO/0Tp08frGrDNT5h49Z08FYo8cOOB2498hDJH8jRdknpiCmooAAAP/6cgSiIwAAghMzWRnmO6BAR+uJJCWZiQiXiaCY6PEOJu8ocJZmCL12w/opyTSvoimSqiZcx0jDIwSUetXKI4BB6fpDwzSic623peO/5u5RDUHwlL2Ygj069kObVNi1Yf5KXa8Kf1p9uACIC1te50YaA467mG8tdH7DqmUlTWd8gO5C/0c/oX9aXuUAX2bmV66UOurbN1av7JnXixhCaT3EqkVPGfI+71gllE1tSW23fJhtHVveuw8tIVZ4zuq0fWjbFtVY8v01bt/OdLAczxHuYapreMMxI0xPOY2hA90wyt4JJcsIs74XayYd1LQxh5CbEpJtyz6CK4pzTnnpQGCug6gw1hNkQKYr12mH9L/6PoFf6bPvvxt6KllPmSY1K/pzt29q69ivIYa2RfPhjQzpFStFKYgpqKAA//pwBN79AAwCGCVaGeM8hEJGa5olYlSIhLlaTCSyQQwgbEz0idgFJNy39ecDkfLnVUsxxfo8aJMXKuoel8tdZHSvHLRO83MfuxYJM0zVtfbo/Fe+2YVPU0/oXqcXOyztc07U9y+ycmnIwASEJNy3fFOmDwOlX226My/gN0l1YPrRXMZt97i9XYxve66/6PoH//R+j/pHsPdG1zrf6Dhsuu7qP3KIOIKL6npmAK7DmLMpEELVVY3PzRQJC51rrYBodpJ1CGknakvpSJX2A6K1TZRGEbIRchGvUiteQO393/txj6gI/fQuX4x99NPn/2UgBKb8fOzmCHl5Os19lMhau0kqdvLghzvD5O9PG05pETPw/NnqndlLf0N/9PEe//0R+fqOtUWi+fzpVG0BZ7uSrb+1KYgpqKAAAP/6cgShRAAAAgwl1pMPK7BARKvaBSIfiLEBg6GkTPEcHO/0NAmuEn8OdeNQhGlvYbc9kF5Ph+Y/DyXm30G6Q7xnhdCmqvRljLuz9o52NLxReNHVV2Eg38g/U3N18dkY6KvvSmrd/6KsAa5LUbcmihQHK2vUe1tJgki6WRLb7LYNx61idXob8xc8ubn6Db7+nPvYwoxecqUZDZAMKOU652g79/raMQOeaiBBKjilkst+oOtIcJfq84vcldGjHrDdb0aGujyF1KZXsq0R9P9uEE83Xo3VOR31bO3T29ObUGdKH+txR720/tlYSSOOxWEAEmJKySSXEWKHZDhLOlwFRHkuoN5u58Z+dKwoetdLIUttcfb+g2wIT/Vu/VH0eiK1Q7LgugnyMLxV3pBKPPHD11DQD3aKkxBTUUAA//pwBPONAAACCS3cuOEUnEGIWxM8wngIQQN3VGOAMRwhbuqQUAYA4SbabuJ0FpMcyxfkpwNNow+CLUDiWiQ1BuyqLT3R51SZH0dsVrfrfR8GMWHZGjdJUtLhNZiI3J1z3V+mrCaz1Isrd/Htg1Q5Q2yghR0Att+JDz2vAnwy50ohgGkqcplfEoM2KbFcRYBMzXOUCVRaNJ/nJ1//X/Ty+3t7fqTgnp9/VAAOpbabkvZ7SNrPLdtxxYMXIGnlSzW6j/VT3jq3pHQcGGdk1T2081v7J/W+3TsSvtzF5x1DWqpBYWq8xylXt9fZTACHxTbikvOeLGnVJsJ2nIYAM5ooAIuE2LZBNt2R6r2PAYjVdnaqfyLqAI3m7dWTKWyii6e//+9iDc453j0NoRSsx0fu/O9KYgpqKAAAAP/6cATqggAAAgRI4BYgoARECRvyxBQACNyDlbwxgDEMhvK3kDAGAIIIII/OhXq4Be1rSSjWjP5Gf/2/+jp/0IKIHEZl/4oHw+cUUXyq//w4KN5GT9E/+9nQgHcuHt6/9IYhgHy/rpAEMMMMlMZBt1bAvO5QksDXQUYCKux3Rv29Df/VFT/IyEMzL/xQPh84op7FV//ihG9GT9E/++6ED7rD29f/OQwHy+uukEppK2uRpElcEszHZIzNwWr1VCUnGbt/aKVKdzszUMx88z8zx3EzpU1VnxEbQHVCWp8nqHHmE6TF9HLOvm2s23N2Frn3MkVglNJuWSNIkrg1ma1iIZmgkMCRSusIxg66WBkQuNJbBYOqmzxtLiZ0qa8+KPQRUJanyeocxiaTF9HLOvm2/t2FrtzJFMQU1FD/+nIEcsAAAAIRNmfoYRTsQmbMPSgjfQiM12gMIE5BGJsuJPCVwArJZNdtbI27xsKLmXOfRQ9Ijk6lmbCMCfEF/wf92SJlvh/I0ZNMl5lVFZca49PIO7l/VFGNoAv3AZxUQg+SglsClQIZcL020sblhMH1XOdr7rGK3mPXkgHy6fI8H9d80OD8VeefKVhkcL/s7Mr43PQ5buX9UUY0igCti+4DDEFQuSluOqLzmWbhVY9BL/QzS4Yb7OdpSsj9IbLCQK9Msy3IHbZmf9W+/ytCtL2pbddsolpSfVKJ1jlpHiz6w3pxRp5mJHVsqLXf1iAAXOzXjnAP25wXtt2ouafFbZDapR4NGM9DzjGvbe3qza/PbLl3Z0tuv1K23109Y+9VtbMX76hUspMaGADFq2B0x3tRi2pMQU1FAP/6cATAAwAAAgYT2ANMG5BBRrvKPUIbCHUBkaGAqjEYpHH0YZQeMLNNOQay6K/FkQ+ymQUncKSpF1FAYDL8H124isL/0pmUJhL4IXCb5Se7GCK6EmCiUVlUGtbk5P4NP7Po95L//6gAwvU2sklEXH9eGyIzTX1hiOmNaIbbyI1UP2fZGqZ/wjJmlK71RJkX+jWe/qzTNwb9cRPfs+hbVJeGn/f7PWORkQ49QRLL9bJKFNjMwaqtaPbzhuVm5xvOlE5nEABKJCJ2a+itQ2hUnf5Hf3O9VmSy9ew0N/o1mbnSw2n6X4G7kW9ZD6N4TkYMmlutclEptCpiLH+MYo6s+uxXKpJjjGQrIrPentRQHlnJoV6C6ZLZ2yfT/W2v+vtzpYa7No9eiOOepJ4/3acTOXVUQTEFNRQAAAD/+nIEaOEAAMIbNdzR6yhoQaa7EmTCcge4MX9DBSTxF4isCYMlwAAgCJmllmGAdU9mJi87VMnyKGBe7LUN713QztL7eP2Lv0ZyTUQezea3RrIJclqb79FFLaY9jWwzQgjjRptln6tlvr2gtf4EgLlKsnXmpYDnIdq8rcmqTMQr0aQ7F8frNqtgpnKpX62eX/yF5++dsyLZF0mbJ/eY5lqIodfkz8M//k/inS0oYK0pE0mwYmXsIGwTZdCXc3Mx6wMs442fPFSSwqgmgvQNsaymhOImaj79SjtjGztE3+2QMwWPvrzTdYZ+TCGvgK4tG2WNUUoeOWP9PUV2CqavoCYT5LCXjRq13elcprCLw6opceJ8q7nGEZCus6w03r3SaSKykbAz8amsIuRTflqOsMpiCmopmXHJuAAAAP/6cAQkEgAAwh4r31DFGPxDBGsTPwJkCJiLaUS8TKEJle1MwInsECCdNxtJRwK6dEct2TQDjMzjG27Rp6fA+R1by+cy5fFofaSYovjEupH5XBmNK2ArD7nCvvUe7NPuayn9SdR+obpkySwEm45DZHcM+JKzImc9bP4C6g0qBcbFrlHX7g8vN3qzvP10rX3T1xfrWORwEWK6isTLxQKvNKe2m1v/rLMQ2O/Kf9OsAIAAmii3AVMFmwaEYONhhth/PUpx/FxzNWj515GbGzpQwV2RXZpBuX8Zu14Pe/apdbk9sRdWMOrn8tonbbSe3pwq/1ESdFG5R5HFo/I8K2NJtm7ddoCnGGiZFWAyN1DzcnCMSMBPqAbt4Pdd0f9I5lD1qZxNTPxcUhdmryaz8eZs++xb9+7amIKaigD/+nIETnIAAAINK13JARTMQQa7QyWiUgjcl2ZnjE8BGxcuGGYVhgBQpX7qyGSUorLHvXXIQJcI5Ymu1ksxUYN+UzKS8hPlNgouyI1eU8sKWWRCwsfWHHRfpQkHnNXqeuwQRaty/9f8eDLLt+IAaVZFDM3hehaFqYIWTjPYIMiNkELR+lUVp0kVN9sDqnWd+Tqv6ytv67GRlqJbIqwvF7PzyGXi1u9VH/9ILm2375DodEJTDU6TV5N4dWMAQEuaGZA1Ol4K0oZchZQtbm9tqmJr2Bok4HKiwx5VjgVrHRo9yO80lC9u2iFGiuaIe1P/poEON216wewlq1DU9+fgCE1iyhQvsaSqIuggyvKr3e32uRWXZoTJWva+9yCbuWOSYE8Srr2IQBgkyE3VPuYltJZaKNN3f5R60xBTQP/6cAQjqQAAAh5XYNAgEoxDKZv6FCP1iDCNgUWEb7ETkaxM8wnYEiD9Ox2S6TuFFDQWjOZgbd5h1y97qj87KPXtt6+Nob33OegJspdWMiv+l6VTTdW09/Tv0dnM/VkZ12bWrHbwpLNb3l0JUqTccctV3QfuZ02w+aaim/HnaV6I3e+W/y41+etQzk+2RooK/Yu/dznMvNTAa+77mCdKnU6LE4CcI0ighY/Gb6fXAi3bdckl0v5iZ575q0w2JrCtfiDN1LdkOJGwf2f5uDCodz+sNcuxw0dawOssiNMb3UrUC6HlErpSisw1dydSe8Jgpu7/wFgyESSiDK5m7Q4bL7jTYBo4JotchsL3tJTw+bioyPS70/rgl9nuHQn1z/LmxGdzhWw6KS7xQy5/F96q/C6Kf+WTEFNRQAD/+nIEiRYAAIHgHleZ4xOwP0RrIzyneQkk93NFlE7xIBYtXMeVTgWS5sGN0W1TCAkoY7ksMlSVXKyrBdQBgXhoIoYBnDhhamynd6+zr26Y2iqV9sXUiUYvnm9RUo9Z3V03aAXG3IF5Gsq6NHXfG5RB1guttoDmc5BKqA9XpGtVSPM1Dl9KIrWTKtfLNhSCps8/tQSqSs1e5tiUIQ2z+l/3egBACimy03Z6kh0jluzvNSgESffGC6KQ2LcLY0zmR9IrKjv8WnMq4v+vkkBKPN2jszTp7SW3t3hiRc9iOI7Q5P0tT6uG0a2Jc3HiBSKKUtkbozjgs96zLzfhoIZLRw5XRTNibZp0d9SCKFRufGDPbgGeqvr6IkIjxEQl037zllJMjrcGl9l70xi9m99TDtLb+oLJiCmooAAAAP/6cAQrDgAAggw93TlhFiw9hHtSPEh7iOz1XmeMsgEQH+3okorekOm2mnLTeyYmyVc/zVqBuXTceQ/1X0m6Fbljl7Z8wo++9Vt6Lg9fuENRH43au3P/nswWo4/12YZIislL2qRaR6aEtVvGWR+pOvWXNIOYc3wLGxzXIXbiSOcR09rIdDP+Utitqu0XyEm8yryj1PnIZFkIT752yn8zZIMyfc+/6wXHduDMNM3C+DTL6q8nQnzuyvumQqwaSscnHENtGd8jHUcadb6O573R3bfkoUb0fEB3f2+qhJiyG0fM+9tCe3fi0mrv9X3dIDItlJOT0lQBWkoJW1Vu9gAl4/JN/i0LWJ9bTJvtH7zGHe/FWmEb06AVtP/qG6dFyClqZsie2h+Px/ynCFLZKreUfd0piCmopmXHJuD/+nIE0SgAAIIIP2BQJyssRIZbhySnfYig+2ZmHLGREiTtWJeJllNEubmllwJlZRiamsgWfSH/ucepX0b+/TjB1R4lQ6MsKHcr6tq+w4UejJRmZG2VtF/rsQ+Jmkd1y5545IYbDjUpAEU62lAnhtsTUkw13f57A3dMoeq3c714Uy1o0yI6cKWVUmcSawKEHdhb1Nb6FmSfmIjUIXUCvfKV/o0icYKg3qCI4WjQk3JKLnVjQwXOactFu6HF5AAFP8j/QoSr1JK6HcuRZUZdv5Q/IGzZXhQjx7r3M6DAm1xVs3jrHNob1p9+Nb99EQ9Y2b7CFZV5WZqIkVkeLwRwXZ+BSFi9ffaz89Xuj8MJQaVCGZd+hchWVA/Bf/+CXl6F3EsyitzGt9CVAnwfX07/3E1LWA1DuylMQU1FAP/6cARq0AAAAhJJ3tUg4AxC56uHpggBiMkjgFiSgAEWLXErCnABFxCpK2Ru2d6FRtKM25+wiHzJgqa3KkDXlub/U9nse0wX57HVRz1DbVVf6c42evmtmNr5v/1bmf/t/QgYL1tAGu9zATktppyZVRrutxQam+Ht8Z+hkSLlHaDIjmGfC/sSZpH5+XU3FNy9OjYYTOvhUeC3Xy9/bjNOXb0cYAJsSOEAJ0tW9RhhhhhmanVg5uZMPzxib0GrHy/IxT/z/+Ock1P+RnFDiBl/+UOgchEFHldv/igno0YOSy2X/+1Wh8chJ6tv+UCKwswCeLUgAAAAGDAYDAYDAYapCtjjdjuTvN/m/57/8s5BTv/kCDkCYo//kRqE5hiENf/5AfSjKULf//5ZFaNxhFLP////mGLUmkFImIL/+nIE6e0AAAIED2TvDGAMRQWMLeQIAQjA2YGlhE/hEJst5YYIMAEU2pdI2kSFgwLVaUWqtuRRjZlViWAzuFERAmxwBGoVNHhQSj0JVrBxJQKNLBTnHn1tYpjkrVb60+5/+VY9Hv6QAAU5f9ImkXIFgBpVRtRMzU1J+iXMrIlKsxTzJ6EvpaxWW3uxnRFZ9un1OSOUCjSwU5x59bWKY6tU76y3U5/9ZVj0e/kQSZUqt/GkgmoAqifc2t542vvg3kJ1zFmsyTBiEaFxKNf5kwbFim/rSpDW/RWYztuGVzhxKe4p/LjsBgJ88yZKvkQQyXXUkAAE/QABogIeUz9o9Wq3noJtP0DFAUtoqqOl00yd9+Zrt39Ucm5s1X+2jqQ1v0VmR/DK5zyVhXFL+phfmRj/Mr2BjR9SYgpqKP/6cATgWwAAAhE2XNHpEGA+pCxtICKXiOzVd0gYQaEgpjM0MIpGAQAt6NpJw0xlBZyFzWodz1vTApruxGI+rcpc3v0zqVXr7YpDo+WtN5epS6KX0Wn4D+WJauQyK5Gp/yIaJaltZtNVBpGNySaRopNygbGrXc63HwFrhruR2r6LCeNGoj+6PX2xSBZhVarzu5SMV878sSyznSFRErI1AbXiMNEtVvagCMM5drXHgweFGkUzk3K68b8sbaZLU8Qjz8Pqvsdpf7s9Fuheha63s7GKh2Vs1HS9zQTHVM2nCIBWhfdQpJZ7v9CSLupzzUcG2rL97f9rbqM5G05jlC7QudSvxsiSZuv5bcKv7tlW6O1zaz+7wREfL5HRnYxoIVaj9aWL0distq+0p0Ta7uGHu67tCeLSd+OTEED/+nIE8SMAAAIOQGVoYS3MQCgK8WzCdAhE2VwsPKXBHyavcJGV5g5VYtrt9bbcDIiACLulheUy1BU2/gyPTe7rxwux/zWbki5+v2N6vldi+FCaN92yK7uuwk5KuwwGnOALd+1/DfyuTf0gkQhBabIHilLPLqq8oilPFoEtTK2mDTDVYr1ubSmyMyK9e+vftlXq+RND+2j2R/+vL4I/+/3Twzvy///J29gPniIQltHCQG4rpPEkesdWpoemcDLFt7naEuDHjS6xpeZ0NEHNT35U79vfvszVT21qRDc1v/4N7ZDrd/ZcEe7t/+oAAIlKX9tYZQ5rPruyOW7KIc7bBPpCBAcOZbELnf1fZ9G1bU3M16aKmlkUKu5/e/0x/6J+hz7iY6trd6JZu0jxB/oJcJehT60xBTUUzLjk3P/6cAQOeAAAghwR3eljOThAQorRZekoCIDZdyScQ/EOGy209JQ0AAEQUtn+22w9DPYZ8jGx0Y4Pn6nA3vKC5KFa33PYou8VvcUeg0K2FTyUgw9NKCOMD0wF0PWHmO/rU5+Gjmxak8VdfrH4CqD50tmBpuNTrAM5aQU7CQxybgVSZYgkssT1cYeQ99sR5WU+hBSt8PpIGHSIYarVWSnW/X0Pr/9Qx+hX6tRIQFKnu2ux1dMaUlZrSLKRLtU5A/9U1ehB1evRtfT1uxqCl5bZe6oDCCaXTe39RDdkSFmMG4TftN1NQ59UVSdTh6yyt6gEo65JHNBKwmOghdsgf4VZ6HFKj3RQ9GraN4CuqQ3n6e/J7UPodletvpsVstvW096lFYvtaKd39b7UHE/Xw9Ip0uWAUxBTUUAAAAD/+nIEYS0ACAIZK9iZjyogQ2sLMzDicwhwsW7kiG9hFprt5MSUthE3JJAfEkCaYAVj0RgtZrdoftQ8DIZZgEFqDkw1Mj0E6tTU/Umx8pfZpba/tzRriip11rCqs2+9kVZt6j3Yl/+Md8mU0m1KQz8fCAAn26lB2s1QNwQk9FPUGN6irWd535J7jL+frfbo7/p7SCmb/Unpn/Y3l6/6f6shmWtHZabfXb8E3oQusqs92m7CNuYSXvC2uj3VoG2b1BduNwT6iFq/VEy5/Wp2hFmz/b+pTlIyBkRe14oQIOd1w88A6uzSXtJKAyPjkyJy1GsAEGVZltx9AqEXx41uwpj0hS+1lBvabhnCSa+vX21EOqoqNlLy929K7uj+i2otlFubc5iphunXLPWMYLk6qnx0HEOXOHjaYgpqKP/6cAS6kQAAAh0U3tBlEpxB45sXPYUoCGjVcSSIb3EHGu4kYonOACC9uRtt2OhiCvcW1qhU7biKaRbvHZ6DK9yQGdEMRRBVWdVUjErJHW1bzJbUUNaKD1+pwqQRhlRrtMWKORq3MJNJJIggIUmu2P460yxhKK6+K3r+hGvWACJshzIFOMbMB0ZhNtW/lfRtA/Q9UtF9GTBM4PFLWC8miwUJ7uRy2hZzuT/0/uABCprurudUXSX7GJXWVxSLke6lZOqHaXqJomsF07j/WLoQpImW5feESUwQj2hXpK+nOD1r+1orIqXW7U1DLXu3d9RECMGluqt00oBf3VjT0e5a72CAjCuoJGhX1b+bpzBtjcNSjyTe3rMrU/swh33YYs8stdSAk1KKK1LFH1kGBqjt1G60xBTUUzLjk3D/+nAEH40AAAIeEdiZ7ClIQaa72g0iU4hI13tBhG/xCg5sDMeUoCCU3L2tiYpxYnwpPhMePWEyAyUh/KljrJTwyyixle+2Qor3KDdtu8WhtVaT9iCykcupRRjop51yZUk5jdCXyDzIFzWzCOu0nJG5SGIxXFmUSPexg05Ex4LoJJo+rd/6NxtC9NHI6wrNtoyOptUVdufpjl2o8zsyXoFzb2CmaRWd4F3PeR3wBIS245JMDGlK53HsG6LLzUuSEoUzC+WZc1w67rH4v8L1Hy3/9ZWlIjgGJVEiZZwXpJiQt2rYnj2197sRm4vUpGlQS0u/6QclLIMGfdJxL1Xkp5BXdXoEwJCmaJMR6bhe6/bO2NFAwcSCqaRTZFWCzjVaxqoatq5vkU3XLYYUibY5aP/1JiCmopmXHJuA//pyBJzRAAwCDytYGeErhEKkWxM8Q3qH3K1kRJRQcRsV7yhQjf4ElNyRJoQkYDg2tR1HQ9iUY0pRtBuHiw0gZdsKa0zZKZeXkbV//sr09tllQYfK5FIs0UeqvcpmDuo8mXGjk3u/JdIJjckkisK6541a505eNu6a9kOZEaU4e7YISR78nX25OJGQodmxNAoZGEIYn4RG+NYBgQKhw83gvHvI/tNMLpSj6q6QUls7grQKlAeIglS8wPM8gEJPCVtkaN4Vspmzt+gy0bhH/kfMb/5nxzgruC7Fn3n7rs9+/wZVjFX19kbTtd0AxRqo27JchXQXRXPZgsV3YeOKfIZMx8aRmunnyeX+I+sva2sFQE2jkiY41RkYUKPHjxgU2dT1UNtB8e8sBdDxSIjqtCzTNCYgpqKZlxybgAD/+nAElxwAAAH4I1zQwRUMQ2Y7WRkCKYigsVh1hoABER4sTp4gAgBUbTMcbg67cPRUGzXEv2Zs/gCT5ldxSqMHHZNU278Wmb/EFk79QuER8rF3OOJDTWTNLHqX3bJE66weLmnqkgAgBcrvBQQMBQ9JYUV3Ev4eN0lkfccyKNhQKhCDdu/OTRunmXNoZ6dVK2f0UogQmjq6tiA8DYlWwWS9Vi2vxDclNaUgAu7ARCD1YWVo4PS9TiIVU9itRUcvl5FOhSQKhkiyA5lMhoaZvqNLKPe/bWl0G/9SCX61dmZkD8rqWGVCeRsdcYc3/UKgpOS0bmN060RBXCjFyW59RHd+tysjCY7jkwYgm3E+2ozQYbgm1/oIO7o2vt2WdSPtqMlnXBdL7cSfYDowUbSd6cqYqJpiCmooAAAA//pyBI/jAAACJCxe1ghgBEOC65rEjACImW+AeBKAGQWt8Q8CUAMBAARm6N23bbf/gCs0KFi2RnETsE4Q73pynbvPj/b9u/5T8rryZbZcNavnGS9ihXLDiZ4ezScy4jFRdjSyD165isGKHoAAAAVabckttt2AAUQxk2ZEbBczhl6Cm3IDkY3VSjqt+fGLSlgyTQyABMYPpIoQ1Vo9AVUfXWhkVH22s0ut1TzXvaYrAAAjFgtFoQoGwRN5s507f2///+3///+d9v/3IxNyXbZBR//oQBAIwu5yEE1UaQUBHKYX/+2KDBwuV5FPpGjRosKAdBKIAACAbDYbC/KTJz///////////3//9yMTckXHWYgIL//QgCARjuchBNYmwoCOUwv/9sUGDhcryKfSJjRosKB9BIEmIKaigAD/+nAEot0ABgIOK9+vGGAAQyDMTeGIAAhYk3gHmGXBFwfvpBeMCAQAu/MxyYPUU0Qj/vrVjZbsBqJNsXn39kBmQlhva8PvkyTlbpFlzyPuYOGRRxkmMnVNzr62CqEdlOblP+TybvVspIAEJSJBablnELd9GgQA2BsWB5yhdx4+/NEypqFb2kAYYKsJOdQ9o8gOYh8UKxV0qk1FlNd1JvpNQyM3D9631gT7Kt+qnsG7MtliRgpWO7OnfnG2yD0Bwki6VlNVIIaQc6dhqMf/+3mvnVGVj1LHNCYzcJUnUJNJdeQFUpp/rvvOEv3dP0dYAQAAIs1KYZkzshhmUESzenS9xFYPGGUkF2hIokeRFCRvVSdS0A345oTARqZEqWlZW5htgqB0qS/ZuCbn3ub+65yduhWtiYgpqKAA//pyBJbkAAoBpQ7eAWUYgEKj27AwwyIJkGlyobBggTUGcLQxDQ21QoBsNqFakT/RCXiGn7CCZVaFrODGDh9oRpepZ8e0JNW7FV0Sp3mW6HKUlGytttPI9aborao0A1O0A2wYToLpUrW0xJe6Y/SPLuqNyZwdS6SX8d4SQfPiYJHy5yoVW1EqdscT6GKUwlbra5tO8jpHm1OQK9m75ngaMSgNNKWj9VYw7IWpLTkk/607EVZ00PGRSDkCxmRA5yBRh4wWaFHCjA69Y1BUsTHPAMO0BUkWUeAp4K7EEeWCuPSmlsVqTUPn1IepBI2OxJttFKSguDb0ph25oXXxUtrf9krIq711Go/frBn7JptKDEUD+Ljbze5xy9vvt/5RXPCtg2U22vY/nrBVX7969DeHDb2fuU1mxVVMQU3/+nAEjA0AAgIeIFuBhhlAP2R7cDDDIggsYWymGGTBFARuJBYYCMbdSgZWCCYJec/d6xx2zjK02NS81IOTcj4tYgp2cj70yYQgWSJUlVsFUCTNVOQKnFuIJQiSYsSk+LFvXp1aKky3fbcizZIRi3zEwSnoc/AHc8qk2Im1LVlVybY7iyiR2cj7/DG1qbgzLyYkoGnGEzs1UJHlVONUrGRc6HfPW7//79P3AkP1o0IK3hVG7sCdisPzmgMjzlky50nIoZsODRtqyLrwaFIlW5wpalykVqWeGpcy0rgq6hyGsPNdb+SenfYv2V6wA4mRRq43kIX3OWbdYJ+9IGjweHkY0UHVuRHDnsMkjWFBTDbamFZJiXVMEzWigtCam53bGqrElaPrMz1lRokrUJXOehzExBTUUzLjk3AA//pyBBlfAAACHg/cSSEbiD/kqxA9IjwIhNdix4xOgRMSLiiRiaQAMHZ5KutRLiDVsQ1DU92hK57YY37MUooy6kPAErYzYRHCi3Xplra3E3oCoiWCY4i56RQe5SiNNDPYlGgAnZWqxn9kUyxqIf4bEAu1GbcqIXdNAb/2oImp/9caQzBKZHuqCAzqSjtqjs2q64NxMzCjDyDM+SYEwkOWqRLJ+wUff2L9fMQAUFqs5YDeENgNywbkW+EzSjUgrxtQxSsESqzTCK2vdTyOz7S+6esxpXlfiXZtOq670tzqPnB1S/1lY21zko9LzPK/uACnNFOJKW4mSgIwpyUtkdd+JxLl2XQBJ4/7d5WCPfbN0rTchVDAINiZzqmXOcbV3vcTbcr7qMpNpAiDFiwAIEXQ1y1pNMQU1FAAAAD/+nAEowMADMIXO9eLDClwQ4R7Ej0iZgigfWZFhFLhEgosjMWNEANxlkUdkedTEMmD1zVhrsvbHePt2BCH+m9feRkZAViUYrE3ZCpd9F+3SZLlR+907t9NVslrVNui7WjcpZ//0/p6N1EDN3K8VrCDynX01XFtHu0ZSDL62oa+juVPjyqabBNu0ZZEprblvK1HGBnCLDYd3xVzFIZOC2uB23gSerT7/6tr7/7dAmq3Cy4nAYkxYRVm6ssVJS+zmCPzSPkaUoZFxt4J+SDQNPhIJA6Yx1jFPWlyy0i5zH7S6HrqWLt6zQfjzFCLGPQoOU9VAJSaktYhurAYtC112KnCGW+HW5V6/SPcRnpPBDTKRVoacp6lgOq1Zi4mgQucAceupTlH37KHot0ihfk/YlwoVi8g+RfSmIKa//pyBNJyAADCHxPYEekrkENiCwI9gzoIcK1rRARTYQoM6sD0mcgBq/kevz0J7ZEtSgvPld6h6H6rJV1jg9Z3eGM09Y3AyBCu49PZUJKGAEmowhKsaLF4iT96VGWMc2KYTU/FVFndGl1HHAd3mG9qQBbWQq1o8evUVxZoxtk93Ezk5EkG1EFmodcmTMlB18HCQNCVw1DYSeoJuJnmjiA8WHJRbRUh199bVIk2dPrABDBJtROWHEVwtY1jrTEtxBxveoy+uQYTKQl2JUpMAKIXeMEkcDVi7nyg2rN3MV72Q7EPKv2talFjVqRScdYtqKtkWXksE6IEGkbahFEIK+y7B3wrYGuWm7Z9YE9BW07MCPDk3jkcvqHsQfMxYIHDyyKBEAgMeEkOgS22tlrzmG73////+pMQU1FAAAD/+nAEGBoACAIZE9m4ZhKYQsNLmQyiUYgoWVYkvSGBDgesqMSI3AAkFpJywVUHyFbWiQ6PH7ehmgkwQ26XhqnnAwZe+4jueSAhhZZNQZtny1oA6sKQCxfS246KDcNIegUHGpluUfmanscAEsq1S3sZPQTCOqFvUS6VzQnRrSro3ezsjOLC88uUjSaDx0WD7Fih46pZs+XIKSZuAinkaP6tyGuF1KU0znUSOnRSDhcfJMJuEomYFEKtxfQHhFvlyT4h9RcVKiWhMe3AeDm/TNZScfqSyxRIo8A8JuDKVnmy0aOjzrFqHiy5GRR2a/QAAEABJScuvlqEmOBowGkWaq/2RMqS0HDM0EdnJJxEXQ5T18K4FQQeS++Lw+skm2lFRuEnC++vxpKPKpQLUBO7dSSocmIKaimZccm4//pyBIjQAADR9RHZuSUTmEJCOxM8o0kIoOFcZ6BOgRoW7Aj0iSQEJBablycVAcDPrSFnJlD+cMknMrQvghPHAiqo5rBlizL7oBe67KhZ3UoVL0PFn1el0Y9Dr2ajyLGrVcvs/0ghJlSywUMZEJhHsqB8umQQH4Ai1+DQntYxlRccZNiF9jTorrcZKlFuY5CGRZGMPitqVsdT9tXXFoWHZ9w0Vv3/3dAATbtErg0ELCyh2sItPPQjFryHEqe4CFxyCjckH8UdZ3W+Z3W7slW3fWy/BoXLQ3rQvy9e6d+PjppL1Xhh7HJUtHr6SVkC5VCErY84bGZAYkrWgc70Fp/PiZimB9CSA0Y0PezVR9zf0etNMPB1W26PmDLUKkih7bGnrdQ5iWi9X0i4heLbYRzIt9VVSYgpqKAAAAD/+nAEO3EABAIcK1jRiRJAQCNLigTCD4goV1xnpK5BFg1uqBMIZgAgABUl//xw/EYRHcqHdoaNMezSG95/mOWG0IuI0Z8H4rl6H76pquoM7unTwyj4zMuYwqTi15wgLwg51A9P7abmp7awAl2JTSSUpPTOLwH8QyvwV0L1OsEkyDaCeS1dJ2xmF3reUY55JJtj9QY2w2ZSbg4wowa5JKxbejvpW5/T2x7siAk5NtI9fDNJa3YgnRX620bqcha5UTEBay47CgVXQa9zNjYDKzyPPrcfCgVvsHjx99V/OzUkutahA9LbLKevfY/UAHNaLiacpG0ixeq888N4ECfaadkQIIvDvm/UL2FSoamR7bB8ffGzUvqejOHWo6iCzokhBqqSpMyGhQMFT0fIG3Pt19+lCYgpqKZlxybg//pyBA7nAAHCERXc0EERLEKiSvc8JXAIDJVzNDOAMRQcbE6ecAJBMFim005UsOLcF0+gX1Rq8EfmewdsGcFQcIBp77StcLqf0Oa9D1GrEsolY0wuPOKFEpr0lR91yBHQODripm3jn8qAQASW7+SOWi2P9nN06hJlVH57rNpVCmUdjBWEaxh+JP0VqXThEmQUJ0K3qcVyKhHagZUYU666SWKMe9PSmUo2Rn+hANHZvjVQxTXW5eZPnBADsn6Fz2PHrzeralj8/qZzk01UeU1yjr7ShGI6nL9shIWPS/sUzuNLOAI/pPFzFjyzdKBTbkEBmX2suzQrFodutZSbhNmRuLpHUJ18Pl3kM/2uhj5UzYhzvzR0orSTPVOfzex65xuf9WrqU3WzbRWWhStjfEa1dqYgpqKZlxybgAD/+nAEWgAAAAIUDlkePSAAQmAMCsGIAIjda454EoAJG65yzwBQAwQhJXagIBT4H7gUTGXiFZRRnjPFTLmnbIpgQDq7xDVn3CYeBYGEABIDsMNU65HkAOyy0H/e8ab0GGjU///vT//0vsAABru/cls+v2/wHEJZB5gZGtPOcNWolGtAjS9WQeoZhifFHUwIwGYsxu8cDIfIHBjGuL1Ipb3jekzJvT//y5qyYE+A9Hw/H4/F1//////9G//nFFOuriUv5A+LziAoKlDo0WMn8XRuwmLiJWZzjmD//Z7oQeQjkdxsgejTU/+z/I1X5lGowb4SlgEQsFotFo////6N//cUV/p/kA4fcXEAIKlDo0WMn8HRuUPi4iVmFjjmD//Z50IPECOQePGyAaJmp/8j8khKvzKNIUN0FRko//pwBHTnAAACBg/gfwSgAEKhi73iiAAIzNlvgKRBQRibLzRQilhAAxkyeH9iSaTgmWjmA1hbVQIC/qoIsJH1Pc2oqGyHSVcGyLzz+JhZ7anxc9EiTp0JtMiTT+oXdZJp/dg0rdlkrIAFQtMZABAMjCIQd2G3Ya2r9EDgHOIBORQX2CV7rrw0VHB8snrCpFdhGsTVnAKVKi6B5zHfipKpa3v+jLHjyyHPPaAA+giuQACplgM2nikWqTPdHbqbtwPgrb7n5yko/L9EFpcuTdenTFGd1t5n78Gznjg7odF3dKwwJHNPAIDP8GY2JRDaHdesgFZrZLNstt2cwFqzMaNHbtaqh5vj5e7Y1mak+X6ILJcuTdW0/Ml/5n78Gznjg6qYdF3IpSsMCQY0OgIHjXgzGxKIbQ7r1piCmv/6cgTkPQAAAhhA2dnmEWBBaBs5GaIYCO0Bc6QMSOEMIC20k4kUAAHAaFA4rGVoiVxfBtnSw3dNVfwWjkNqbmJ3/qt2df6VE1K226dHvQ/BrrzU+cC/m6Vb4NtG3tiX8SnX0EQHfXelqQAwEiUAWkKGAWzIrUP1CdLMT6S0G1Bc5O/flLdjLobmRRKAylNbdOZ5teDX839RX9Oiq3wbfbfxL+JTr6CPrvS1JAAZHjm0hMViacII3Ly6N6WkTA2YE3GZ4zYIUuXhKEd3/fUmxiTFvzunlb/+bwa//vnodQUsXGPCMg10rd90qknvqFjp05BkAAIvhBykhF1bBGBjx1fVqMUYMFQzXoNoJ5eEH1a1Mk2XoatHOtqb9/epKbe3N4Nv6e/8EtK9YJl2ucVu/rk/UkXsrTEFNRQA//pwBEqxAAACGUBXkekpcEJoCvY9hSYIsQF/oaRKMRemrTSSiPQYGmwqnpNCM2YNghGfLhyVCkTZv23ebq5Qzz6DG4p1vZK/8mh1p/1pIVKpSln18IjE6VV9b8yuNShvRjJb+/KnfofNAlCZSZFUrS+CasOPGO2lONvjx5nWNDkwYkKFu74x+3NPK/7E6aHZlW7L+i21b/rTGtSvRv18b+wpvMlNSVVa22889gIxmJySJlp0czPhttjbsvRu1eCH1V3UDGo62mspj1t67FVDnqnr0epjHQGtun/E/06uc5kogkekRviMSqQuMf+doUjR6gAAAKGVGkEnbR+YvSWmZoTBcYy7qWNXChfguK8l1P0d6+2gDZWZTI11v7YpkZaX/+N7Z/sqNy/r+SqfZDAn1KeLErqPljSYgv/6cgSjNwAAwhE1WrjHEbBDZCqwPSJ0CLDXaOSYoyEFGyuI9hyYhMDrbrq9wMvDnEWWiG9Bh9o0nBD9u3VqHH0Kj05vOyOb30PM6NqmrdUZfVIJhFZIGYhlpn9qS7migU1vaSerBWn3plPp5aGMxLqASyPHyFOgcZU6CrfkSbTJ/2Hg6ahWxPic76N0/Zx6Yq9pt9wqLzMeQeqoTMSKuAyKrv1FegDP+jWCvrADBIm2pbDI2CFFYZ74lcQ4vOjRLjA14wX5uvE3Sxkof2ag+5S33trmqqD2qj+j5tqBoViNrgEwDqazbtH7Zvt1+5U5U2wGWva3RtE5HhLrg7Knrg7H0DAzaPoMQO5QNaH8v/V3s7bq+qMqTqOztdv51Ep/3vbQvb/FfVRER25L/XA3R8mdepMQU1FAAAAA//pwBMNuAAACDSvZMYMTmEMGuwox4jQIyHFroaxDYRSgbyhwj14EK/c1Li8gBTekRzLWMR7j5vTrR8O+Yfj8J04OtXfJe9KkVjOtvTuaecGPAzHkw88O0i1BDTqRt1XWPaRd2zeBv2gAAGA03JJpYTiMHtd0XV1N2C/lH1Mh4GsxgXNwnTUGmq8n516Hdf1N7Xstm9d99RDZYX12BJrE9YeOuvej87cBv+xIAAAAEJmjkmiigodV2EBdalRuLuJQeR2hyapwf9TuY9ni3JafC7Dqc9YUFDq0bBgVfZoRnJK6MbkShQrW795qJTlrMTjV3IJU8422m5Z2L6CifFTaHdleRfltegR89NSVF965VxaD4T8pbOb5UQkVQ79ffp1XBZ1Dcq0IxQOhpLHNACVoVBRexx1vF0xBTf/6cgTxKgAIgh8tV5npElBB41sGJeU3CKCVYuSUUiEMDSxoZ4hsAcckkbpVQtEso/iDveG6eLJ2QjnyjaQdoiz9Mc43BNrwZtxBKs7UPTVbuib7dvswMBqqaSdJ1V1HVnFjPTAttbv/d9YAYtqtYqKAHAbUsC/hRtTrHy/UbUPFIS8E2HNjON40fuO0IVEhlcdujI9YlfUAwG+RKwqh888W9ur3yPGoo5vdmKQsJttO0aVFhKkqoABVKxt0qMM/2oo/l34YzAgPh21fUR3bRkz9ej1BNEKnrWgeqsAGNQCaQM3KPW7rfXwnqorxpF0lrlQwIabbcZIaCFbrExHMsTKTdb7petNBw7cbQL3bBvgxDIwuvfOirELipCskGiosyZfIQoQXOZ6lXdiWPc5Y7vRKbiJxMQU1FAAA//pwBG7JAAgCDzzXmesRcEPGu0ogwpCIgNdpIqRQsRcNqtz5HNACRubbLSm0EOt+ioDZ47Qt2wT39wiVOzVf1BxxXBvq+oV0UP1atKGIqTEcyN0637bf7d86//h1wOSyPee129yHazQAIZINtyS5x8gHaUAGaaDK/JMRfJ2Sv8wJ5uD69QOilfb30S1CZNpuv1zfJOJK18ZrCD0yGr9akrdazMyHXIZ95QtuQA2tK2pyAUBlUwC3jXxYW5rd0he7LCtFgfQzuw+DTiPfV/0tOQt39WRvTav1ZXTuoyK87fDKf6O4NthzhJKh5p1yN+hgBAWU24F9HmUaYI0xnzUCEyXcRE2y4Qaj5UWsOBvEwJnPN1IhvHRZqOVcwlEZ/mpYwbrrGDnmNocSnJVPukaFL+7ceR+5SYgpoP/6cgQBSQAAAgQr15nnE6BBhXsDPWUmCPzlb0SIrTEYnrB0EojWIMVu3lcFlnB0PG98PqPaq7c9ywXXIlS04vwmdojx+vP0fY3Noojvr/2KU4V7zkzMuI9VRxBAqFE6dU1Z/Ut3RpQelv/l04MgNWKVuBR7KF6/IvIovQfwa8Z0H8urtjHypZEKixzo7nt527ajRi3QhdSrvuCrFm0J2VXpQ8Q9NSia7AAkeJbbSd+TSBPY6jxmR1/iG7gxnV+J0DNnfm4TPmfdu7UtU6u5XPWXpseqsK83R3abVPH2Vuvf6d3fbQpJJRtTnB+w9cqgJpBqO6xua2XekIezywt+MrxQMAgn7czZn6cH07nahmawnVj78jaeDfl5kaj3pWnv+YO55p23QUokxKhskcJgsONgYeMfrStMQU1F//pwBDqGAAACF1FWuww5QEMF240VBWOImWFvRaBMsQko7SjyiXoEgCJlv9BLX+YyCRQWcD+lIp+yGo33C2W50w0hvwT5ctkU67K9Wfp19+Zp9+f5qJJdVt1r/U7+vsn5v+j//+W1qduQAACVCUo00lbOUBqOVnhb9gulQYpfqPfCLZScIynCIuJFDzPZG19cyN/9WoNI9g9OkrkLKYq+yS+v2dXu7BwZOojv0gBJ6C2km7E0kGtKWlMOMV/i1TdArMPr6tmG0Jzjrd+v0qndqL5Ovt267fTk3jd9jvVS/z+up7fr0fQvf2ZSDodNWJR4oAGKhEbkm2K+gvawsSVk4XxECc6j6+KcT9ulSi4aqlatevVKV19G/xtC9fTp/t11X/9X/7ZpnHehHuEE5VAMoNrM1JiCmooAAP/6cgQiEwAAAhI9XFUsoAxC5yvtpBQBiNmBf1gxABkOGGxDHlAAgCn4lxNthAunDsKSvbZIrmyjDkIyBmbGg3G9G0XiA+ltE6s2C9tPIXpqJto/I+dlYjS1WowFoRNBxpfup/fffaoEUQk3K3HbLJdDzB/e3LhOZUsLmw4zVfi94cF9B2g3hQ9kS+nP7dnr6LqmdRzOgtyJZW0a/nitkQy/naaECbfz1qSFFYACq1X9btWy2f7AkTD2X8tLYcbV9aKz2RNU6YJ70/kW+qel3969nRdbNYiv3pey3pa932fpddL/o1PdGazf////yCHwjtfg7BMRRF28SKDdXtUGGgJk++QqjUGuo4RFhgTYTFRxkYykYogjOn2/Iv/5x7OdP/8go5BQT/94HQZ/+USFjBR3//MZvcmIKaig//pwBEf6AAACGCveBzBAAEQle/bkiAAIiFmHpARJIRKNMLSQjeSg4AQHQczh8xPlj7RdHi++4gUNWaVUq196zKzze0cv+a6LWh0tS9klKgpZ1yxYOkQLTis1gIom35pzi37mq8nfpdZtADRLVQIAQJCNSarUH8qIj33EVKzOVZaGUtWoZWT9kdevmvPWjp97bFQUu5YsHQ6BacVeawEUTb805xa33NV2Bu/S6zaAGkardrG0lGAwQeKvMYNiTb1Exdf57PRR3R6gJTYNOlQCQIk7ayIlY2hUXfPTMasc3FPesGSqUuLnBlXQql+S2iz2RKAAkbNtrEik5AoVuWe6lHzTPPVizVyzNXmzWRG0UffA3UuYNOioBIEfWRErOqfffM1rU18U63rBkqlIRLnHPV0DKejt6ExBTf/6cgRa3AAAAiQ14GmFEOhCxrxtJCJ5iHTZasw8ocEDGuzVkYmYAAEDl8yjaKvBV8a3YVqeF5Uw10ehoRf1m0U3qanX7rB5u9HXq1tRlqyN0Rkr4kqWQqu/Z9rqmrMIf4bFcsGxwBdQxlCgkjFbK42kSXybW7zbh4z42e03hoDx56ls35r1NEdfutc3ejr1a2oy1v6I1/iSqkKrv2Wdrm2rMIf5MVyxNQBdQxlCgAqStQwob6fjG+mU7Uo4ttNBMHLUut9o0kXlm5bV9lHN4Ldub2uHnESl9H+320LvorUfoLflg7gJf1UHqvZK/Cv9bhoCBHGECOV3G5y2kp7jLdZ8fksIwzQaniyooC7tDlpR8uVvoDU2b6uGdSt6P9vtoX9Wt6D/g0/PN/q2dVp37ftTQmIKaimZccm4//pwBCkwAAwCAUBZky8QcEAGy0lkwmII7NdiTD1BgSEgLej3iDBT87FOCYQ3UN768MeUHDU/Hk4Zs476b9gk0qNK705xkZ+guDYlv6vVU2W/J7m2K+vTp6P/+mz7iff767/+T+v1gADAR/fjFRWJBrgw5rskjNjuFKODrfBNmLBrsDVELeXgqzs5H8XBW1f9tfX7cjzFXt76N8f/TR+K+u/3en4e9YHT+C1BvR1EBKa9zDH9amTiBgw5Zr4JOrEzLdD4u7NyVGv0rI+mQrV2OV0rbt2oil1t6ucb28v1boihzq3D04H03KT0d9R6kAMgkhdbfw3gKKqa3WPCVW4WOoRtzRXmJ4KsVwXt/6j19GRl5+mRr0Lorc/99XQWnUfT1b+74Z3xChukX1Cy5qKLJ2MrOmWLrTEFNP/6cgR2rwAAAhwr42imFoxBxBuaPWUNCJBlaGew6IEVDu1o+BUYBRNDUuk8rko3UmrWLTbvxHkixkYhQcdoyOnU8IGJ5wfNtrNlV3J27084RQyJVsLsXlKPMTiCSfF13pQn2wLse75yRqADMFp5ySYNmFSo+REl/DMKAlR5PH8by8T6cjaNhZIxDUZGddRRVTXX2jSi0bBQmLRaiuqwUQS663M0SXdPd7t9hgMSyW1lDztWmr5KEdi6EyBM1xvKjGYFmuczUbKjFi7mu/kCzpeiGmECKXIYUcZbdHgw5rlOU9Olu37EtKF8rr79YaleaABMAMay3ZxHj6DVzRrgVafCUO4ok0XsiGwVzcnjiMLhjKnUdXzD3gkVCJd4193Psc9qyBRFFa1Mt12/Yf1NJdmdtEp36UxBTUUA//pwBLhyAACCGCFa0W8qkEJCqwI/K0IIVFVvRLCoURIZrSjHlUAAIAQnpbthYHp7xheUFt7ksSFz76LQfsE9lQ9WSNbEzKnwDoXlNaszC49tFVbioZhHEgwi5RO+2y5ntooqfd3fKftqAp/xIBLleZgTqljK0uE+puXDMA8BjBO6A+6XCHNQ13n6jTq8irNRaUKSz1wOsY9BotTW31DCzpvbjq/7VJ6f6vo6AAAmJEbckaUcoDP5xv/CkDh6K5x2wCOiqY0vLxtGpeFkl4NHWRFXXF2VRQY4KbLukyFECjwvXQeXE6Y0zWUtspCv1AGAI5d+rMC0NBQ6GhJt+ui3AlBYA6qEuEthJGlfG9f6kqjal1Htp6b9ev3Tb0GLFkrDm7F4GQRXtY0u5NNRb1XKWe29SYgpqKAAAP/6cgRBewAIQhINW7ElEwxDRruaJWIuiIDJdUKEWLEMmu7cV5VGBOpKNlVMOGP6HoygeE2QZ6CGRh84OYSJTpA5KzconDVqESlUY+jHDBB1O9toy6yguIC7Swo4vvTHpoLNEaMgaWp6gABbLEjltVx4w6p31wdCsIvSvo14kp6tG7guQdZB6G9u9VGapF2+5m5E0//6YZOo0hVnkDxp1ESaClygpKvjn7Ob/pBYItMpxCGChur4xwFeO4vRy1mKSvUtBiovkD8wUa7P5N56A9KPtkMymGiTcr7z8KLfbPJPIEURK7Fhk46XGzeVUOWqkUIxpJxEhQvK5tLlW4oCti3NqErz9KxhjsnGCtUfcczqWp1fLX0Pdvp+nRiEEPHLIKV0001yya1x1DVmXpR5P5tSampiCmooAAAA//pwBB2MAACCETFYGfg6kEAGeuJlB3IIoHtvRATwkRSZ7J2DidoAONwCQym89Ae8OjXJfMrLhhlTJx7DwDGKC5j3iLIoDxzJhna5/QHc4odqzyrPa9Xoqal2sZtW3vuVcJ66v3+t90yBl4ZTj/raJhrsqhunyv06/yD1S+PMvnqcNPoaNxFkoABzULLP28TBuPMT1Nor1ZTt/79q2f9+uePtB+aR6f6FgEAiEm5JtrjA340b1JgBw05C9B/ZN8RYljGNd/KhEqofq2Vx163DXucPDT73F1izo37FMstt30JJE1hwnZmDT2FaP2EVlBBSbkoXfsTTV6Ca29vPmZwcSRDqxa8xjvNJtQH14absstSehpaavr/K9rak//5N0VXEPBadUd5FTEt7NEOUEvgH2EKq0xBTUUAAAP/6cASF4AAEAgsy2Jn4OiBAxmrzYQJ2CJTPYuwoTREQmfA0Y5ZOCETu4bKSrsJvFWFG03yWhYdPg/tpDgkQo5BmkLzRiwVGO9inhLnmZrY6+a/fXq36M+/bs0cbUs9PW3zUjoPx3/1ABpygSmXPxPER60cgBvP+w1FXhOqdU9z7qRODROA9W5AVXyBtH04Jo5y7O0K+t63q+pe2lt+2UmQW+4t9Mvf0yIIIRSck1Ds66avu15Qtz9XJQOCpobDuBfOMHqZ8yGbYVxtbDH6Csh8yYJsnT+vt016NkdqC9933SE/bdbY8tR2fSQT/oRJSDkbjrjl33HS/Ze63AlwTz7TuYC/fS6QjBTTs0/ChexHua0IPo70/q3rSlejaNsPebnPnLrbZ2dQPFkkTzbOfVZTQmIKaimZccm7/+nIEd6kAAAH9M1m5bCm0QabrAzMHNgkVb29EsEcZHi3u6DOJfiABBJN2prULV6VFhF+8EQAZ7c0clAB1YN5rUfERVo25wr13bGru2nRu+r9v/T3ZFEpT+Xrq6vDSoBDHW4xG03hhK7cQxqBp2JewrHjlNPcSob6nf6jsalw/U5Xl3mAaL6ifcpzgbc7q+c2nT31f9LfT0c4qj6LQqxvAdfVVVdUr+4AAJAi3Jd02dLu9jRb38fCWPN6bF3pQDty8G2u5+orB9uDT9G/UftpXbR+bOVtf/+V7WzN+rabfNq3Xpof0lYjKRLhnc1zuKzACRVhKJJzS2jy0VlXChii3mcacW2jnYZMm++oTTCqzEM8P1ANG76v2/+/R5hPX//s+To39mo1t+fbn2bn7paRogZIaLIi5U0mIIP/6cATvAgAIAiAb1hsseyBBg9t3DYJQiMDNZvTygBEZmaxenqACAALkAqyaCF8vL95hwuXGblCr4cOalgWXr5O/XC7T9LYd8ubn6sFKU3N7zT4tyk1PBZ+p69ynXrZe4tdw2HkQTv+R5KkFYRjku4KGDY1oEdfweIiDGz7B+PPFtghT0urder4J8G+hTlnl++66TEgc5L6bKJOv0lljeTlNwBMlgweGilQL3uOAW3JI2M2284NUU46tVb5FfH3DjTlZWBlVgKc0AQd7tr04wA3Kz8fjeQuILx2rWvqib9+jsgDnCzB59efm+5b7/S2T7f6AAgBJKSRm2c74j2lkn9t7eWMJhgj6qMmU8VtBNPHyASk7ybke6eTzuyK8q+i5Q96ty39P78zkblf1DlihQ6tl9lyW06G/0Jj/+nIEru0AAAH/TdyOJKAEREnrksYUAAi0sXg88QABHZXxN4wwBAACZELyZw4whA422aElNxFqrim4xlGMcSH900ZdE6rnc9P/5CNX//cONIhP//xd/////h88lgO8H//+Bw+IDNyAAAAYdUVF/pGq/2XGmRI0+49UFHZxBoy4kLWmZLVzN25xc7J//IRq//7hxpLf//i7/////A54oRgO8XP//6QfAgIHyiHURYatNoxNq17CmhVbn0XV5pgpd3Uxd0rRpqtdfaj/5UPdEqyN7fUKJuKwo+FHqbLsMhJrzxkZf0Fi6Z4svpXVw6720awAAQE47G0knzwGmgucrGdrz/M6XsdZS2PvMm6UO9sXQf//1j5yFShf1f/qiUTqiMsRiPHIHiqUzTE+4895ae+2zLGlN17nSaYggP/6cATdZAAIghhMXSnmEbA84RuAYSsWCGTZbqekQ0ETGu4k9ggwAMl6vA3lyiONnyHBmC6snnwNUuqdOklBui1fVvq7/vuUzmNoxW92ZHdv6btTHptk3qT0Z2t26KmndnhBd/yOkdZ7qX/Ea0wqIOPFRNJIvWLy/NTokiSKSpQscVW8SuW8m+lLwKHQNIBrDww2N7LmJVlLxJoQijVZfFSbfvzf6N6mDYQ0DjZCI0ICx9U5eineWXuGoHL17sLhxHPn1dqsv/KJeQ2Wj/e2g+xUr2b9hrb+x8V9MVLT2fI+JTgM1hlyjvVpAcBFaehGB3PTyPou02mNaN5VPYvUaZT8FWo3N+rVXT+UTk5aP97aD5SpXs37DLpVqTU33izTxbLljS9YKFjsSGkiH2ZtMQU1FMy45NwAAAD/+nIEbqcAAIIjGVmLD0BgQUMraWGFDghU13knpEFxCRrvKPSIegvHOAt6EmUm1MQKg16E1qyFBbthtrT1DmfDdSErkYSx83OTXh5kWo6jxKRUBU+8cdxKAj44Wf9G0C/qerFVdyyrv+3xoABKgW/5AoOOemUSazn1HyLAsDKrsXVPfkDOTrEI0dquvEh9q/DpJhFQFT7xx3EqT8Wf8rtAv44rsFVesr9qO3xoAKFjXKwLgeSSz8lF9CeUSPKmy0OegMHwlaCmq+TBAJKh9dfRdS1dHdDkF2a5jHUp/ypk0gpC5H70z1Kq2Z7/7vu6ztBMckkA2EmgPp14TpesA7VDt3RSVkSPdeSfJq/bBpr6rVbrff9UfZjPNbL69k4IcVXuR7yM9IqDi6nnvo+67KxuhMQU1FMy45NwAP/6cATJ8wAAAgw12csvKHBAqxytFEV/iIjXg0KEb7EXFvF0cI5uAAAIC//MGZK98URr0RZ0tTWaUJ+dM/fqj0U2kUZmEqsB2ejtjs3Azader59SHsnVuTuO/6l/oDj9Wb7f9mj6ldDgk2lrPJLbLcJaPW98KYw8GwJs1DgkLFjDfp+GXbRevXs+njdrIxP/9PH/1/RH2CLt77Yxb/2S/6+b9VHN4iD1lBCLNIqONuCYgrPGlaGXGbCuPrrMMr9/MDxbXB86EPzLwYnyLjBYaxc1sStn36GvVOlAPcsj6AmqACI1D7HfiA7froa5QSKCj0LdlklUx2Lqqva4WGKDGK80RX1zikuPDw8WEDOB4tkzUONdesQtFFUeQQEEoYJlpcFVLes4dIt+TauNp+FGZQ6vySYgpqKAAAD/+nIEBbEAAIIENd7Q4RY8Qya7qiTCYohw13kjFE7xEBXuHMEd4hAROCLSSUNCGSLyrsg3uP5nMqYR0ftNsuVHM9TbwqIc4+XvrDZlWAutK+qdRhssvMZan1765vZargBg0VypifFAABmBMcjliCvef6a9UvciMI+L+hC6EwS9q0bk/U+uCFvu7IzL9e3RdQmhHNTYzVddRCGwaU7/9i9gi9t+CjL9oHhkgEAfKu9XCWzU5s8c/Q2EksWHVF+/dwaYnLkbEc2M1nI0pXevTp4tpHOWS6larWd93AQOyuuQVZsuW3YaMp2buRfX2McEBNSSVIJTDr2avRafa4Fprmo8Fs+d+r6F5/wsUmF+QdJnNd62p06uyXKIGrSqZfHrwPULVM/ezhwb9V1hEd2DQSY9FyYgpqKZlxybgP/6cAShAgAAghAc2RnoOyBCY5tnMeJUiLFhe0GUTJEMmq4oZgkaAKMttP5ZRyj3ZJK5KsI6IKoEiiZCcA75IpVSHCzB05mqdnZQVn461ygxNVVW6+K69IHbAyDlu5zFo+rhekz/xz/sAMAEW5IuPVL7+sK0CRtzos64hyY0xzTh1s3M5IIrafhS65wylGVPVVU69sBV9emY9ZwUBN2jWeY5Zoul+yx+p6/9AYAvBpy671TQXyFFhUrnzYiCpRet6nbF3Jx307tq2nN06F5rA7f2lN61EizIZt10ej/X/+9/1d0RtP6Ja9hE8QQUiSpyFBKCU5JaBm5i3AklUvx0TVc+a/pdvhsx+Vz1Zt8nDPpkVtW0/ofBF5qKmhlPbVv4NzM98t+5IxpETCoVkG7G5lLGoiBMQU1FAAD/+nIEFU0AAAIKKVtRhhKkPiVrVxmCGoj1OXNDFExxFqXuKDSUZgQAgACTkloh7C99kjPjJo9DOsPM3krak4NySH0NpqXpi1bVu/6PoPoJr3cyOehi3ccL1O7teyyj7sUDdLVy1C3ESAAApxyYE2LeYE5It0nQaejfWm8I9W1JwTgFLZ8FwuqZ1bVv0fvx+J2Ckl03QIzB1zT1/d/2JYNbQ6/ybv1rgBKAEUk4VjHD4eE3M66yV2IC8bQPwj6eN316YpBHG6d+I08f3wnbnegTmd1jdu9L6K+f/2pKoyUGZQpKG3TSUDImepYt1AVIQJAAiilGUaqpHGGrFqPh4XsDNJoGaLxkf+TM+5tNIZx2nvo3JzaeTrqz/oL6t/9Myo3t/bSrJGBkucmMUbiEO7jy2SFaYgpqKAAAAP/6cASUTwAAAiI/3FElE8w9ZStaGYUaiN07ZuYMrpEaLG9oMolfSAAUEIIpSnzQoJ3MXwzci/pUxvQy6iHNWJnqNA91fG6bIVddF/n6cK+CfT+r//L/u7K9wBt6d74u7WdF3/gU+vDyLIkAAAgAJNySwSzXNaRG+Fts2ExViVjIyhATbJxjFt1Pq+MbR7kLz6f0H6eNHlPk6s9d0uJpOO9LWzDr1rT/WAYAlNuSB7lRE1YXy1gz0iOR6Whi1pghy+DlJGSw/Gi2otGAOarj9R/JzduXjWnR2aXQ2ua+jdO/9PfGdf/+i81kFmhuzsk1SAfKKcRmueN1TWVgrds+QN1DMjIMah3lJrwb9+P06clYC6QfYfDahn13/7f/T+n//8yzqZUMBM9j6VlbCalH9fk3BtlZ5kxBTUX/+nIE9VEAAAIEKV7QYivMQemLEz1ldgj1aXlClE3xHSwuKJQVioAApCSbTeBNoNxRHMm9LUNR/Lz1gh2sL11Bm1Syk5eXZtAG1EXqM6q3amqfOdrj01+rTRRLfStAMidDnPYwioFQASrt5WlmahqQCNnKZGEJqsjmMSU0FfydXz739GO6QXbOUHeQNarYUmryKmhev9OXp///voft361m5m///vx1FP1AABUCUmnMhJh2wLa43cfMBaR2glyuaJNjE7VHNQ7cM0fvp4Xm4vmT9W/v30b/0Lwt7//2VnzEFqjGg1araeUrRT2ESDiEwisAEIgSVLdk5SOHuH9PSN/rnsa2wKG0xgylnxi4x9eNbX27//Xm4s2nTn603rfRtXSpuW8Itv/9dUeokXRnjbVtr7XHvKUfUlMQQP/6cARTDgAAAd5MXtCjEMRCSYuaGKJ1iQEHc0MYoVEfG6xM85WiQFGoNSW7+OhAbsE72IccegFxfD1p1AcMHwnL10QSlH/+btoI6df99PfTr/vsObJy//BPg2h5Ymt+TkOgEEVwCSincSYCGuakj2fgatHTh5qnwmF7AXcuidulLdu/8/N24np/T+nvp1/o+z9O3/eG1Bot7xMptWoTSBwjRH0LgABoEuW7exfKVwM4f9dQNkqVPUoE1CE9WeVdTb6Duuwm2R//j9CtOD6Nxnf9D83OTbr0Pc58T0xFxDU8XSBqXm+WDwjVl6uMABSbkatZKhV00WKN4eVkNtxUGNKgTNwxsPcBLnSxWzLThA9BrYnSR/1Nq+MVq9G6d+vP0bD9FeeXW6/1HR6BU6k9fP9El3+hMQU1FAD/+nIE6I8AAIIdL13oJigoQkTrqi0iZIiUj3rDBEkBBBIvZFMM0EGAQFYi5u3IT4q2NWG6FC8rVbIBcg7gO5d9W10A/Jy9OnRj6YxdWJkZXOk48gH/t5d5d+jLh8MYPn9b/lC6gxWfD/9KAB2hFSNtuqlF4UPL/DRWfUG2qslfaDIbVo676ifzv+z6f0Y/wTxIxg03D5AmlXby58u/5cPhjB8P6/ylQIVnw//SQwAAra9j2ZY9BYGRJ5IboBoIDmAOk+ewcQuer6n+dXqc7hDAfcUBB4IAgGD6OH6jmUTwgUAH/nBOD7l8/8wcDxQvd1jyAAAKl0nCqaGNho+RH5Cc+AbEBsEs5uf5BxF9+v9f/3r9dzCEAzUEDhQEAQG3Zd8pzj8owMHP/WD4ety/4ATZ+TTEFNRTMuOTcP/6cARKegAGYhoa3wgsGDBBg1vlBSMGCLhTeKGwYIEDjG7AOBgAAsqGFb7hkX3HBtAIszVQZBa55BXeeJiziVVPdVXxg3yIceKA8HEUUOIkUpAK7HUCEucGEugq79j3K2Modb2Hn9VxmsEAHxnQN6YFSrDi4GH2xKuqgzPUK4sy1hThVV+hQZeJM65B7AeDiKKDJEimYXZoK3KbFKCrkdlj3DH7N32Mf1XOrBOo49gBNmCY5odWgMPecaKgYzFDxMXJ07i0hMLDhrOJ0JHJUVF5Qxl3HnoEaOPstLjk32Vmk0w9aUBYhn9Rt6TbFpspZpCssFIIGELoSrMOS28v42Yl0iVZGL8bOvl6lM23KCPicYHwolQFF6kY9wVWVLo67LVqTffWhNPaUCXbzab2U2bNKYgpqKAAAAD/+nIEiqgACoHsLV2pgxLwQKH7xQUjCgkQgXKkjE2BIYPu2GEYQAEAjRkHQwif51FXPFQCNerPpWLJa32dfKrzNTNiXR+ZW8tnp0r2tqUFNFNa1sotnW6ZPff7tBN0qmint67gEJvYy0gHos5jctOS7usu/T2glIwDFQPDYo8PmmkajuGwXUPFC60T5Jibu1W6krYA48u+Zhmtaz3WaQ069X1+1DbyeuOqAuNkrVOutMw3++aA0wtUQeyuV0cl8XBTtG56yhTrUphkrHlYo8mw8NbLGEBOcS2mkBhVK7BiptbUEalJTSZe/3PskVsFRa3mQaBgZHKp/QwQsKHAASTMz62goLmYsIhZVoKvFoxFqSTVMKkBFbhyAZS87fAoPBt6FAFh4dXGPaxj3qQnz7BPAR5QEalMQU1FAP/6cASRkAAAAhERXMmGEaBA5AtgCYMKCOBjeaQEayEbEG4okIogQACAAVala3rygV6X7lA0fZTm9FyVCAU6BWtFyoIiEqNoGwM1RgKrS9VguhKOhgUuQW3MDf3WufFVVdFZUuSsV8j0wsIND8xFbJY1A5EzCxg3y9UxsIUwKw2q9S0lRWGwpU6gkvjAgsBioNrvSNIiUXSY2TgUzRa10NoZ3UOfX++tFGqAAABhBJpFubS1hgSnpnMgFOqeZyfLt3PWz8mGe+Sa8sNK1VrKA6VjRcmNFDd5aBVma3Z8VgWbMFmNobQ5EqAVHq1WN5UZkkAA0CLaccyJ0gHxgR6ZkbkZiSfW/Jj2GrkZsU1Chi2RG39VvpGKiwEBLmiqi5JtSUmkysMnRKdrkVh6HeuzRQ1Y39jdBVxFMQT/+nAEpWcAAIH+LV3owRRoQgJrMjzmYgjEr3kjCHExHJbtXBYIOIAAAIUCWo5NO8j00B88Nm1P3N6s5qDILaN955N92hcovOTn5IzPo9wx1QJAY9z3bgmhwlYjd2RZXe9abtlHEawBqrEMzUoNZPKlCpe1KRjRaZWKsF7+vWeV1yCwPmpSLhQ6HXk4GUq/Bhzq1GhGRW0+HUiHLGlJsOnItF1f/u0Us7MAA0GmGrXyfAxC8aa0vfE6+1104SDaPxSbsZvZVQb2v5NvL9pWlPKKDrWCAgYpoF93bcrW9ci9bgwBwg2JVEGKjdiqM/tQIAlSSWMpjmRiueGyqhZsURNK0qTX7lSamugSpACDqKtdOpvUmVti/s5Gysv9Qd3OOeJ0E1TtKlFrrrKKHs9bm/c/sVUpRilMQU1F//pyBB1RAAgCBDXbUewpsEFCa1ckRnQIoCt05IxGURWMbyQwig7AAQASI7aIc/RqUThInjnjdlxZ2rlcxa30dkZ4W6i/fc2Pb+/97ohG3apk26fp7tvYaIGy4aVUO5Gy3vIstxQywAQALcttTVBOioHGyah+KzI3zRPgdWXuxzIwX3Sk6J3geWlptjDS3ineaFc1Es4seRsJrWq9LH1KbsEK/kc7/Fe8oSTckqaHqjg0cMLQBmNkHaKpnRgRjg7fQFnrHLZOwkLiU2esIvUqmKME7ybhDKSKbSrOt+HXvIumrf8HniqUsKix0hUyAgeRpluSAxEDUTUPYVjBuhCxVNSFg6Cn3SpsCYp6z0607VPUVKExoMura8mZEMk/K0Mt+LsvdfeLH4ucmGiZ7djEmmkUpiCmooAAAAD/+nAE5soADAITGNqYLxBgQuOrEj0iaAjI1WpnjEuBFpRwKGCKHgipLtq6sIk30SjGeiNex1/OGvFRNSoj7IEESOZDfXjG8u7pUsUF2XnVutsmWnVmn3KrWcA+qoUTee8XZptr+tymsQA9+ZiGctBYpI7mgxJDlVqPmOlQjEvmCu+4qHvJmAoDnO60Z4J2pwFXe9AdxGpQsRGhIVJFatesygJFmTAt+d79HpoCblv/9e3GKTEd8y3hBxhSTHG4nrYagPhDzNZMiLlCA9E7vvl5rl2dk69mY1P0fR+MKGEckRxd+OxdqGrEplaSJ6PprFlZLiku0nG03XUcgruhGr3tvrewJ9kiAiAPp5JyIiBlf79yUv9SJZHZwZFirO8Y+dnPGBVpJ+RnD2OrsvEVNd6xVjWPhw+ityYA//pyBG6TAAAB6xdYEekS0ELGW3ckYmkImFtzRJhE0RmUbaiTCJoQbwxuCFERASQGWZZpJk7jBEhOO2eFvSPLQtHDSze4qJJumRim7oORQOyU3dxVrcsNeuAnikUUcHIyCe2xICSU5LN/lHA5aaBPoCrA0EKicMteHJzp5Ab52TbrrnM9Ss7/e57Ud7Lv09OswRSTKoFXjYpV9elLmkltGvhQ/6N6tEAAoBluS3JP6BwiDD5YaypXQbH1o99S0zopmxcvVALyz3LX0Sxx6lsfxPKlFlBvRJlWsFzCqH8WfWtT+8miHUmr2jiLEwCAACS25KtZ0YFrFmVhZQ1psuHz0HU1HEWa9XbO2p9H2//VbEe2ooiiIzlmTiqYvpqgaWFk8lZ0NaxzVuqShD8oG3ihoNoTEFNRTMuOTcD/+nAEniIAAAIdMtq4LChYQmZbVzBFeohco2zGFEyxBZpsjMeU2AChsqOS3CIVQXHAtImifWIpLJFqJY1hg9X1FXCQoqOqlaIljQp3Qc1Gf/zJZrX4onNVF/IrRyBNGK8y8q3RX/Ns+39UCASW3JMfL5cQObgLV1TaK4szkejztHbos7IKq3KyRzP9H176IhJFS+UEM25KaeTjnFnKT4D6KJeW+prKWq+qq5frgAAqV7NR84kh0hK7nzUT8KR9V1BEdUzGgYxRWVsnE/gh371bVD7MsnBnclsFaZWtXmgOEgWVCDN7CVLdrMFtaUqd3AFK3/7GVQUGyS/mXVKH44i7q2StvnIo/tO40cQ2z/gor2odP2+av85VoqJtXnshiyiIuP3aHqMKjKmgWu5+r/3bkxBTUUzLjk3A//pyBBmLAAACBTNaUeMrJEMGa7oMwkKIbNVlRLykwRMarEzzCdgAAIAAU3JM/peIQA/nRxwUpSr1XQ2UKXMTHim4vCJSG76aO2+nv/X+vRtaquvreIvI0s8RpEDRHKPH26bqSPT8vAgEoSks39PDDRXbvbE+7YLVtW5vFb9u/fMZav3Nq6U/hOfk/lfB5H+XsMCslEcWUCgBQNExcRlgvI1sEkVNVrBmzG4AAAAGrv+rVA44CmVDRasNa6nSR4oVcEpdHEGaLglTgMZqPp37bnbK7KrpSlOvQq179G1u40ZWPelPYIOW6q+v+v3LABdv/zRdDuWUW2rsvV2JkSytPOrAodYvPCPwwvGAwTC5JPzbvuuTn5ep8nk1fj2Xpanu8KIbFyfXER2cLKvLKyUr/L+5MQU1FMy45Nz/+nAEHAoAAAIVV9tRaRFEQSZ7AzzCdgjpQWz0kQARGywwtoYgBoAAQBCSduzkK0D4fEIT5rttt63lDshX3HocX1tRte/Tg+C99PbXoT//ty8nX/spW2Lq3Im16f/2p+reVkHOC4Y7lVAANzbZmSRVPztT5dzLqlWdpXkF4Zr5pP/EunqSmBwfAPMdJC6vsO8Fy9Oj6Onwadu38/LwF5aE/uuejWY992r/rgKCU5LtCPWYMBcH0FsU8qxaTqLq1mWh0vMzT9Ozdqs/f8ypQ+pdz9U+l8FoJHoR17/np0m68vf36vS6EtYQ5Tn1i5VbuvQMgJTKrajssu+J4crzcLw6cOUMfW9c5OZsyaOt27XOm4+6emfUvXrZPbUFqgqgY/d/369+vbv99XPmREKsQTa521U+JaV6aKkw//pyBDGSAAACAU5dBhigAD1py6DDFAAIdCuBvBEAARoQcD+GIADgBgTgTmhCe3SIu0P19GWyFZtn2/7czBxk//Fx5Udv/d8XEgsSQgn/2/xcc9KCf//7eOd0RRUgG//5QVUMFQfKOS4QyfkIP9nGgqYAMZSKalEyk+3I9P2XMwcZP/zj1R2//xcSCxiEE///zjnpn///b2vRRUgG//5QVjBUDqqACT2krSTSVzjUN0MRDeBDDQaTFZcYklmwZSq10WYNIC7/CAw2AzsBVArFhU+JAo0sXJFGt0amMvRJ/c1VgVVyRCZ2QICDATmrsaTSTC9zdDLsKceu4YT1SZlrRtLq2yO4YrvRJbZVCERpAXf4wY8BnYCqCdq2iQKNLLQprdGpjL8n+3YFVckQu2JiCmopmXHJuAAAAAD/+nAEA+0AAAIYTF/oQRRgQamLmRQijAhE2WqklE0BB5rt6JOI4OAVEo2rUmm4ry1RG0OVqcHw1DzlMRTTCFxBiuq+6xOYNF/fCOjrtoV6X5afdprV91Trr01VSrNhTD/SDS82eYAlb5RAwADQAC6hEeIhISXGKopNxvRqfyRsTMDCsg/19pCiaMGi/vhHR120K6pfiaV0dpn1919demqyrNhTD/SbXvYxP1QAQC/YDjggIoH/0zQ02hVwrSo6bQIXKztr/dzOtbdHisq5dkrX6iWmczpoj/xVV7a2ZJ+TSoqJeDTlUJl1ncRUdS8AgoEBJBKuURGYUGoB+cLkNkdBEdUSNTm2V2lDo/8ztydsVl5dta/iWmc3oj/xX4trM63vYdO6jXc/Euo8x2tjbFJiCmopmXHJuAAA//pyBP3bAAwCC0DYAekTsD+GqwA8wnYI7NdiR4ywgRogLeg0iCzNMsJDCfRHH6cKrCHwNoJp+Hc6kEz1IenMN5cQ8VqJROIoh27fVakshpq+3gi0m+hnurYMvvp/+Gf6M9v/3f7+ghnD8uoeDCKg4Sn1GzAJGcFlty8BWOwdhtI96B/o0p9Ef5mRI2dutStZ2mvVbfporp6Ge68G7/ln/GS2n//5PxgVNf5mou41TDYYjyFDqqU7WrqT0deJaMwbBuI7uK6NvoImLGlxratU+hF/VFv1u/p05fCPloo6cQd2eYYTQd03KG1ybvJGI7AABQ0mynKJpcOL8lW8KZGUcg2D2VKvUxtvBM1+FfVtfbXRK06k1V3dH6lpv18K39X7cmwV9XFEuPHgCx9VVWsPUJbDJm+lMQU1FAD/+nAEpuMABAIQQNkxiSlwQmgLAjzFaAi8bVgHsLCBFCvu9GCK9IAAV/+RJC8GJJI4HbHi3Gt6ot6f6k+3ZLExhNjtq23Hvo+nZcj0W6+XtzlEkRD12pu/KGV+vk/jH0IrvI6fxnu/khVmqkzAnBQmaTMkp4Wq1Q3p1NJP0VrYFNuZh5QXlwmu47Lwk+R8nZsQ1f+Wlrto1z2b/XUd/R/17jH/ej3v0ZHo/dTDUGiKEUx9dqYR+ONlHNZMMPubfgPxvC6uNYimKkHl6x0lXY6aKCNQOooxNzjTCiMTpXGMe97QlZU3YTremn9tvf/1s/r5ABG7ajttu5kM6oF4r62vbLBu1Z3v/53Y/55Pa1w88r/Cspmj6UXKFQ76uRC4VkViyJYmWL9fnJ26PVB/u70ofbUE3drTEFNA//pyBLoAAAyCEzZaOCYQSENGyzo8wmgIZNlmZLBFAQ6Oa8j0jZCAAQiSKl2OyoswoJFSsjD1ah+y1DBYO1lvT10doI66A4Rztfq7NVVIup7aW0Nzpd0F2zZGn9vSlJai+vSKdx5rMZLgAGiEm3XLje25wSRUvln0+GA4uef2zPa2zMx4CvWqWql+h2ZPm04/q77Mj7edpN/VXU6K8w8YhrSCf/r5VX6u5/pfWEFDLtj1RLzvYMcGeq/vj71R9TK5tXDVUSujZunfi35vdOU76oeX6//yN4a/I4AawbqfxZA1KwTB+Kuk1ZYN2LTFFlQB+/ucxcVhViejqmgNcSOGsw82/0T/lRMoTGVAReEdKVVPP8CbNi8d1myZwwXsMgmPoQTQKIUlaxylujEav+1H7e/9CYgpqKAAAAD/+nAExWEAAAIXHNi56RJQQia7aiRieIhEy2JmDEzBDJlriPSJoICAiKSSZ22lvn1HRBESgJIeOtd8Oqgy7Zt8T/4Mmc67vpoVsRqImQ8VC/qI2lAu8KulInSpZXQue5P1bYo9H9OTf9KBBQBJttyXsXuO4JmcfryzU4GMgL6s9vq83pdOWNKF5F2Pqd62lqypomi95SPb01dXpEr7vs/PFzqgMaD7t98fAQ4IOS23cqh41oaEWAGJy8x1onoXqCKO6cKJmhr1ffj878mE0J1dczTo+9jTUv+XBnRMhei1VanMn7484vQEH9VL/8iA3/y2ZywmIrRIhjICqoXMhgDU7iXzO72QYoXXY+6DL0qatvdWwB8O9VfmyF3Z6dWzvyu/Uj9ng3WXTHXt2e72/o/7ExBTUUzLjk3A//pyBPLzAAACGw9YmY8xID6Gu3okIkSIxNVw4JhBsRQOsDQzCVYAOW3beQgXi3JAm+EPOfQZO0s7Bt5llrwZxA9TqbJyyTnpC8VVBSZUAADNpUdYbsPIb7Ynr3rTMTxZynXXRr6ztutVUAAChFxyW2z2zxQDkTqDiDb051H607dDZP7cK/6I66MZaqX+i/vy1r490rfrP9Pw3DiRHJCMkScjKiPf5Ko9Q8IpJJSjHVDAQcs54LZ8vAtHV0ehBPMI1ZYf+Zsg/bVrs7GnepK3v2z0d8EqMCPcMFyx0S3OCJzu+uEM8GIt+0C0uydd7IQGU42opI5NjaFJFc/BaH1fkfnV0erCOZngj3P/Nx3lJ2TSEoKUqv1PFGls4pyHUWwGt18w1jlUDArvpTL0BlJsnLOukkxBTUUAAAD/+nAE5tUADAINHViZjzkwPcDrygQjAYjMd2BjPOUBIqttnGSIigA5Nv85MEqJps4e5hqwHFkbZp2EPLlXn7DlDB03TtzG/HxmVmYUilrpuSm8WcDD0noXuF2o1UU0JnyK6xHQmlf/ZgAKxKTbbpAsrEPSEDaAJ2PGnUEJKy2+ck/qOFJJwq8tFn58aLHwSFwyfEo2L2WUU0OuXQMXX+trmNgNlOKgAyXf1oXti5DBH8vFzlW0UjtzzYW2UrUUVHT2Q0Tn5R+1DW76kNlyDXINIrSoN8DipYsSii0WPuAx5TmauyaaRczVUlf/qgOEVJLc26IuXmR6iot5xOGzuoxCNKvKrwS69vfYRzdqFDkqfK5VkF7LRj/sLTSlNfTzJdrgl0ZV7Zt20srskj6P/0jlXWN7somIKaig//pwBCS2AAAB/jRXmeYTQEHJ290MI72I8Yt9oZhOeRQoL2gwiIYABS2jxz3JaebCryQikN44nbcd5iOCE+wnGwp/GqcFE6fJ47wTfiuvn5enXVerYR8yPN/kliYs+asskLLP+uqpAAkhxFJNtzZ9HlVNobnw+CfcA/Moo37jyX4ubyPh5dcLs+B/kv4JQ8ehfyney5f/y94alIQJlMoumyomFY6XFuG2AACZGW205PnXOXGxsifp5ofWYjNSstK0Fafqj521Fc3Xp25+n//slH16Cf82t0NzPu31va/NoJ5fye1wTHszd6IRUVUcGSTgCf0km3JqxOOxoa1xI8pqATY11EskI3fRteXq24/frzLs+vBdL0b6oMiI+pOXt0oyzzLV+nXy/xRpC8Sj0AQhI8YAsu5MQU1FAP/6cgRWwAAAAiU1XtBjEPxDBTw9BOV3iJ0ldUMESnELFK2cFIgu1Ab8xSOSZ2occ7ClmzVhHQXGOUH4/MAOp2sXk68G2q6pb0F8zzlbX/6jUcWsKPJmEunh0odWzp3HgGedD5q7lYOkV0SVBIRUtldlt3GKbMyUeTtZXQqtCdDwB6INmxMFxPp11Gvqmvl6dOI4TqsoSOhODkovDMIxJ1WIAzgM1ZNLkRM5U27uXgAHRJabct5xay3OvjuzVJ1D0cdKl43K2r6fy8J0NhXz9OTqlbLR2r7vgibkdUPV0r0XTq3Zv91ETQaAYuTLlXX+Gk2eoAoJJaTlUI9VXGlba3UoUbBPmtJqCdIxMLzMk/ZsnRdeqaLkTUS97wyYAshJH2Hg9N0xWyL/wI0wCJdofH3q6JLo+xMQU1FA//pwBMtRAAACFTbd1QygDEPFKyqnlACIATV4GPKAARCmrwMeUABEBuSi225co7DbD1JoPMWzglDmTJxV3Ur7my/3yFH/3yE14+5zLtavb50EVWaeKlCkrSss4rX8uNLmVLGqbXRjVf9SAAYAFOOQYdVJCqERIbxxzLMGMuH/1OQPmHRqMOk2Jr6dmykzZBp+bf21K8es4SFxwSNhcYGr1Onp2c4cnmDN/to1NRh5JpsNyFnxiSQd4xRLRasqjvznT75Ji/+k//P0d2Hmf/IRmxUwDlVH/5/8SdWZyGHf//JkvvHBNv//WsewsNL+J54BuN0fWySL+/Sh1JnDjKGdmibp7ORimFi/56XI/8+6OZHMb+xCM2KmAcqo//P/iTqzOQzf//JtfeOCbf/+ta2KWXTEFNRTMuOTcP/6cgSKUAAAAichXjc8QABERCyt4YwBh7ghfaeIwqEODq3ViAjYAFSqKwzYCsVW3s1PBbYvs+Q+LgpWv1Q2bN7o9Xpmf67XoFlgyE2uTeBBCG4CoDtu/JNVEtu+7gtvS8f1oXlVjOoK0HouAmk07HG0iSuCPUp1SJqGLpLykSsxzOMdzND8+ex/8f/PgWqMi4s5N4EEIbgKgOzrFvyTVRLbvu4m6Xj/QvKrd1BWg9WAAJDJFGkQAskadUEPKlTlmHg0edhJjwhk1xmdL/efQ0FJWSa1TjrLhWddOMbM29X50XWJaj2rcldJjEXG0BB4GPjrFe1Ixawp6jznmhrXOld7S02IhjWO/0/nXj6Xn0NEkrRapx0hcKzrpxzYCtZq6s6LrEtR4fFCtyVqSYZEXG0JiCmopmXHJuAA//pwBLgSAAACHTXk6MEovEKmy0BgYnAIqCtrLDHhAQ0a7WWQiegRNuq3W2NpKOWmGkxKjc4CAvjnayI2UyujFHtX8rOqoRK+yuTNy0/f05Wl6LX1i+ji2pmnW5ovi3uUWEusNFeBCUwRQIQiL7YZDKIKm3apal7DsF2RAq1ejiPZrNWgVKv/96tRX9lclTctP3m05SS8i19Yvu1sxR2FKyRVba2CmiwKhrW7+oAKADvv8QzBekgMWjLSoc091++YgV88THjUiphQscUDYspug7GdTB08FGMVaRkNR4oWQTqrqeeTP7Uey8NEu5v2gH18iTAIBwfv/EJ4HCuOTla07n1N67u2XfnbyJhChM1kzIqZ9fcIdAx//99O/rQU6pX0Nk7KK+p702/UrS86S86/2u6lsyJNMQU1FP/6cgT0WAAAgh5AYejFEUxCiAudPCV7CLjXhaSUZfEIIK6o9ZQ0BZaZdbkkibgKPerFyGuqREBPLkQltVddxJH98r9n2bttg7SZilRLJdWF6r6E7+o//7Zle4Lzq2om4Nd67eWM6M29LLAAAEDA3dInKFSG/dmteBqN4/zB5ST/DcYKzaGBpXV2QYKKMLI32fWyt1b0d3Mbzf7+r/09tFfGd/LyLga+t3UZo4FAKKZkbkrjbgwiuts99SKFADuRzSd8ksEdOtmuXwv2KIf5PxStI+5xO/57hVe6fKUk7l9CV1MWcS9AePL67zOIfrLee3eSSlbWWWYNgyoWqbXP7t0LgJV0Jpq+iJJdGK9ikdBKqMmNDOXt++ibtR2VBDp7bVpqTp/TV1exx3I4u13U/TUzmbeVTEFNRQAA//pwBL4BAAAB5w/WgxlIYD5jqxJgwnQIxNWBooRR8SgTbWjHiYA06Kr15sneZeDK2PsTonMlEIqxsFzNfgRaY1307VCaHExgFbTpBc0oqNL9ND4EcSbR5Crla1qr2f1a//4qEXfg0SbsRZfesvvNXZTOc3BVkEXm5xuKiWhoJZ0iOjVEt6d2pasb34ukgeapYpSUvd5iydoqrG/vopV9HUSABKQcTjjbbiiU1LpLaIglsRiaCSzMRFYIQZln3zA6Tm8j0ch5adiBw+QpJOwIwhbTCgyMSeH3te+RSWKY7uXChbfszzi9wAMACF26/kECV0KLNQEkxa+00CEjOFQd422rETUFzsia9/EP+nS+iCzKsSHC4cCRNZJE6KuGKda9ptP9gTLLh0UXsbPM138bSJEpiCmooAAAAP/6cgQKYAAMAhkm2RmPEwBAomsjPCJ0CORnYGe8YYEOGS2ol4mEQccdtBVSOD19PPsmVxZcrBH3kTDKRyKy5BTtIDL+rVS6XSxvuktNFZBUWcRWG3LczcOiL3WmVzn1LPXrJpbs+EnetASLktpdUYhS/d8umNajO79dTAC9UNExDFVn3LeDARr7ljqVGPpUgDLDl62SIvF0Gd6TprJSs/7op5Ji/r5DZke4GNOSQoFwPwgzOkT4qw6VUKM8SIJpmewwpCKJhBJgmFroDU+fgraVHCcBu0jkyF100F3DHyUCLcvTpS9MjsZW4/dbZs05D9AQAaItuR3jEkQqakofJ7feSZJJi6Hayrpo7MjhW/TV2dejK/ej/RsuVquvs1/THCCFurk1+L/4FtBWaylnSCpuKI0d6YgpqKAA//pwBEI8AAACChzZOS8TAEEDu4kZIhuI5KFtRYR2oRoI7ViGGKYAgDbt2BpIkAg+qFmMskTYImAaisd5UqMyg8Eiy2N+rSu9F4ggpiX3ohy4VASrQMydalxSvckWQWWx7PF2C+S/SkEUKVtmujqG2n3PVEnxOAmx5dFBiMHmqhLG367pmI1CD4I3rlLFOPRMZaMlIx7imufoYmbJ06YzXWec+l5L/WakgAQKSll13aVZsvS9XqsysqADtf3dytyTviEGH9gs+kRnmByKpLamR9Ew1+iR4op4CMKUdFDBCIBdqOdTQj9FdbgjojV6mf1AHVRW1MkGbfTFrCLS5T0NX2u52bingVHbJxJb0BgSua5so/0dtzyJcbGyDiCjpeJiiouvLp+upzQgJwSNWuGGEahKi9/RKpiCmv/6cgRmrQAIAg8OWLkvEGBBocszMeJhCKj/XmZgrAEKE28ogInuAEAnJd/gzIdDMeiny76DklVJ3gfludlAWsJoJoTFeeW4dSzhy8uMjg88yOY3Uo01lzLOcdPqfoihWmHljOv/7NcaC2XLcwbvBA9iczs0O9vZaB8e7sD42JoJsAvYJwyONiJnReuOkrvcpiJ5bCizIVuFXxI96xWoO1IrHAHOUEff4r7wAk5v16pOJbxkEvL0MkJ2guIY2iM1LEtFKAx2E2OpNtuXXtazP27UZtsm3Z6v/13qupq/+vdYhreJ6nAdb0Gel23TZ/akJRKS1G05YHb3A0+ZaeLB+axdbzlWBol8+rodWyZhnRrltGgEMFWlOy5+Jb/blEssXVMD0AVRBy1FicMLpsXGirm6ExBTUUzLjk3A//pwBIE/AAgB8QlaOShgpEJFa0Il4kWIlKVkZLxMEReUr2iAjfYAgKSclpc2uIMB5qohr3QlwAfkBj1ylrDqZ69BsR1DnJn9XPFzAllr8TPYVaHw5WpL8aWt6ttIuB2TlLOn9QKy3NcQkD6hGOH1T+MNxzcNtWyanOmVd++UXQ7VvbPq22itLOZKiSwxoEiBtCLwqt5NpPJsxTbrpcGQtOZV2fugbaCSm5bBdUCWQqibkWI1rgIQkWk0jnwfE4KqHuTtVtF3Tp/XTq9CbJBtVBjW9q6jzW8xrWVk42TWgqqBnhws5Jxkdce/74ypWKcccm0kk6o6GDWyJDaVvPhyolMHWWXFRG2plh563KKUE+DBZRg8h6zTWnFMQ9nawekfawArakxVInXpdYp6AIyrhBSYgpqKZlxybv/6cgQRlwAAAgUaWRGQEww/xouqGOIpiPVDdUQEezkjk+90gwoGBQGyovbCKg8Llf+ba88uCiVCrgGFeo+crEBGV922kfjmBMyjvQkg8/ft8lOr/1LHlt71Lr1Bgg1QAW1k8pSf+LhCAsS2m3K5ch08SyHaIDl2y6vV2nojZ9eVZlqP1T2771a6Mk/fZpe/sDagemEntyF63qpj9ADdErTXtLsYkZ1KMpc0mWnaRyEFMtSpnlkAv68Q/Q6Ea8mTSCIHf3+/jZ5j4N1vL8suDJyMpOfea3h8pftze7NTeBS+/tlo7EHu48qFbb39yd0hqNCZpuOOXDYg1nLWLLrgcD37dwodHUrnIfEZ2ZD4PXorH4t6NvVEpaIiNQTKLJvNrcLSV2y9cGkn1vKWXTrAqLrk6G1ngRuWmIKa//pwBG2gAAQCCTJXmeYTpENGu+0kolOIbTdm1PEAORmmbSaeUAYAkpuC6mXQ/1SXdlRqxIofFZDvBDOSw3BOxS2oM3MuQ9n/Js+NrLbbtpq1HweGfTTttxmnI4ejtk+fVRptu2t5ZyESaDScjbkouNNuw7HLHpRhQj3Np+hhYY6qB2O2bK9RDM8tsnbJqSj59H//8qo2otQfc48vfYmcuIXoIrBMBLYg/mlBAorzf5T4cGXD/VnPeV0fgmMaKri6IPc+ZmmZ+XqzdFLVaF3/ftQ270f/n651k/9tO6//9s2opUVjo8ATNoc/8hU/6BABYWJchO25QPKVZ3WViudsgwGborXCj51MJSPZ57Nn06rVBrF30L9WzavV9T63Xn3WbV7+2mj/T9e37nQRU8e4JFVNfuSmIKaigP/6cgRdQwAAAhtYYR4IoAJCySwjwxQACLghct2BAAD8hDJ3jCAGEAoFAoFAoRtAN9gAl44CPvI/7m//b6uR2/+Lggm5Btf/gcVAMHOICml//hwUOxGUTF/t//qjTzoKO3y///7ijsCAgeGBQKBQKBQ2V4J6/YEhuyyK95H/dP/2+rkdv/nBDuQbX/4HFQDFziAppf/4cFDsRlExf7f/6o086ChrK/+BHFAgGA+ASgAAlK8yLauX5qWH6u5YZdu7hxIiDN6wm6HVi1ZCxwxScqRFBg4nW/LHjYTZCnQ5ibFMe9Q+35KbfUYr0Ny0OsyzHKTSAS3FZJW0iSu4+Z/02qqrdGRZesFUQ6PFonIWOGKTlSIoMHE635Y8kJsinuZsVe9Q+35K/UY9DctDp7LCjlJpTEFNRTMuOTcA//pwBO14AAACDTZjaGEcfELGu809ggQInNeFoxxI8RcbLrTzCGwAppKWRtEkhQSKt2JivxgfqQYp8fezOvYliU9F+q7kOX6yZiZ/yGRNykQODhdRKSCV5k8bVeLi4tyrv75IDtkurNgAAgOytkppNeJqDJK3jVXKXmArKwJq7F1c92b90bTXZP2t3of/6OpnX+h2Y1FZgZFjRV0As0/F5HUGvoemtIXrd2UgJtEWxxpEAoHCkm3FS8naTuoXDNSKgTdcKt2orM7aXXb/mzHZaJV3/q2qG9F/w2j35HLa5Nh6DJs9PPUDoifLJKjPfIpAASBkicSIAQ+w6jybl5OeMnmaLx0hxL2kIbfLk08bRHfb+jGzOy0Srv+ys0qG9Fp+Ba3N04o/PZJfUdy2Iwkbzzw0zMpqTEFNRf/6cgSuPQAAAhU1XmnhKLhDxsxdJGIJiKzZXC3goYEULCyNpghoAAgAf220jkoMsiGuLNCM1jGAjcRql5NWGsjmPoaqt2kvfVsyqR/K6fvZ6lt/R9dWGnX7FCLanX30KNm7+u7qnendUA26TNbbY23BsxSgVctUpJ4WwZjKndGBWDvQz1E66Nv23UrOiZXTy332tv+lUdWBiVe3URZJJH9ccmw2bQ/lXeqjsu1G+YBTmEA7ER4zqU19nFuPO/qq66xCoXOQWEhZxh7BO7Kbkd9cQvd1H3vlvPO+R/tlbelt3t07eNFF76IxoE/a+6h/2v5oBttSQKW0VXtWde2UW3I8fEpwD/IsFZNgf7NV/kat1dKn9N16UTtr3tK1/3+2o39X5dUW4A9sz/O0z69pG/7T/3Gku8YpMQU0//pwBAm6AAACEjXdaYY4SELpvH0EwkWIqWF7Q4RVcQYHK4mGPGAACsCux62W3DFQpUt0TjwqonUHVp5xtHxUtT33r23dl5B9/pquboy3oq10Q7t/unsEtkVrM89R9g9ETIl9aLbXf2uCsmkstl1slqpAKCYEbJboNmH72Dazxap7ZteTV/KlUeTsTdXZ6WsLazW/Tvje9E/sThv2+up7uTKaJpQlQRYqly/JAnBMi4mkmIwToTorl1FjTVGEbN75HuYq/rtkHITIeaoZdFeQpM8Y0FhBmRICN0oP1qyu0pTLfYv/6Z731ms/+l/1BPTzICs0CZBK2dDwz+x367QxgeEDhzIZr2dT7w7/ZbgyfEzlwGt4hhgSElrCU8FGCU25UXalj6mLqfoPSH/zXatzv6w6mIKaigAAAP/6cATmPAAAAgA2X+hmEwxDJss6MeJhCJSxb0SIb6EarG4kkInGAQSKkUTjablEGhPexfjCysu7wgrfQ8GEr7Z9H330fNRp0XeZWorV0Kf22p1+L9kBGMvaE37JVTUXb1xvDPZFKwAgAICKScIIDEYEHuS2vAn7GpI3CvQNkfH0R1EPX8+j77tvmo/ay9v7sxqmv62Q87XFdlyab/dUWfaJV+VgUjkaffWAIhyMtttwfZaGbXzKo/7XZApbdMFwmZljadtsE1ZpXS+D0RrM6rIMcuVzbBnP1xQqxzG4NRUu5ZV/0EpFrBhjf9Ib06grQSlmSzqbB1TI4tI/+ngHU/CqaBkma40idtNG01Wg+vXfVdnRtStQ/u16qT+I/m6t0//+lq0V0Kt3onoW6W9R0FdjDzKDKYgpqKD/+nIE2gUAAIIUGl5QxRpMQQO7Az3iDAjIrXujBFCxFKataMSIbBVgrabTScjQ4N5q6cZscER8T0a4CeDVmVLS8vvmXRDWXqnMpIaHh4Moc+ECGP63TY7a+roUgkFlHQSfqPDnSQGmuMACcksPwkb0R5zyemoDe+xGbGsM+Ka6w+GGxOquiXXtl7baJjyCqCwMqOiKErTDtTQytoI6zbr9bfqsPLrIM3/S8gEkmEouONO1dI9q22V+UYF6ufi5LfeL/pqJ1ujVNnZL5dDuj/M6sCHC5ihsXACDq8yFHu/6yqg28Wo0rRTE4+Hj6oUHRrwSSctl3Ol9Qpawt945ffgELn2kejY+p1qlX2zPVs+9lN9H1LSqOuyauEV9FX0uVq7zr1+1vr+/efqvqWCAaFJvv2v0JEyYgpqKAP/6cATYpQAMAh8cWRmJKNA/5krzPKJyCHhfYGeIrmEMpnB0YRSuQU2//bdXjLjSFyagbqxGD4Ai5NYQoMHYY1HZyafnao7TiizucVFhQKRI1g9C150YbS5l+dU/j3IOIrKPY0k09f+sl9RATltsNDXYHpVPH8SGvKWBBGm/DKRLFIEiUDMAbHM6ZPweraatVsuiabtdNO81un2YgR5G8ZW3+z+uSYeV0L5IAAtuVnZlyPDL9WwV01mVfl1QoEqwrFhbOGEzgd7yICrGPR+OlaLldqnum9ZsmNDi8y3SebNsrEdKfZvbHMBL6k5vRqRxiIkrkkkl1VIYHpWSPlctqgbOjYHad8qs/NjWy5G10/XvIub+n/6UP+Op7027eV//t6q90QcSOjWIgVK48ay6pGxCYgpqKZlxybj/+nIELBgAAAIYLFWTAywgQiR66mHiHAjRPW9EhFExGqbu9GKIngA/xy6zRy/b3sbbLCp+uixRYIIGLi76r8/tmMXHMW6EeJDIEDIU+L2IGYl20zbcj3f/p8giy2MtsuOWVql9hz+ylhEAACAAFLKHSgiyHPdtZgvYS+oNOQkBTAa1FD+crmkWZArsU1CaPn2Gzdt9P2egq+1UvAcnwAoYpNSlNUtu36rd6g8AkCpJSTTicFUGp63dB/eB2kl7+QPR8GSOJGueSz/BoyadHsd7PYlfKiLp+d0RrGYh29FtR6E8n6P/+5mc4IUyA9+d1IMfWQwSAYki225m3SBom55cKg/BOzolnxj+vXP1/BpTtRHsq7mb+uF3b+lp+9/roqUt71/9OhlOM9x1BEjrUiLAw4Yw3EofXPKTAP/6cATeVQAMAgUcVpsPEyBBxUudGEN/iHSFXGfgrAEejSrNgZYYABb1wcGtSBx5HqLQfjpoWrhKRJAfukZ6FFiuXWGCYI71ZUGWbQfJo+EstvFhxMVax4fX9DCSBZNt2T7v/HpLnlAUIgFpEtNN3CHAdGMu4Q/AsIMrBSxiQzWKaDntp3yfgsI+fO+Z7Ptfjj2po9j2/QB2khZq5HTfTD6zf8udMaLh/cQG7tgslrkXB8fCuZoUryeY4hqjS78twGDHQqQ+2D1FKq2uo+of0fOSn4gbKJlmDbYUhpNqHKQm5SVJJauy9dUitxTtAALsokjFIaMCMHggqtATxPHlZZ0ngmvADt7yhqcuBzo2zejKGWwD+htQfEJVzMo9AoxVdqzdC5IgZCRpKQmfYWY3U/318u5CYgpqKAD/+nIE0b8AAAIkKlcdYKAAQombmqMUAYiUH31YYYAZGJOu6wwwAiCndsKkDMgSrsulLJmRaltWVjpVcoAMaMjBEdg5zhjogOqKy30qNeJiG7Ys87V5tGr0z6CtjdNuxzezOCknzu5egq5+sJUK0U1G4LyBZ6UIvo78vEdXjWx9RE+PPJa/zj6imbQW115tG+jeoq0yWKdui20dddNaaYosnd6/+9V5MCsKOsJqmwEAKZv21bdt//+APt6+P489ShRFLOWzevtanuFOfilcVHCvwugRiXfT6zcL2TfGt3+nnwH+s0r/bae5/7jd+V6bf8uowAABKrUm5LdtttgAaHfyGtCLU0btT1z4TmxmTTP7yXvkRepEmqdkf4R35pLIO4deJBATD4cFVjpRM6RYbMzSSHeiWpAvQGExBP/6cARX7wAAAh9IW5YkQABDqQtyxIgACHgDibwhgAESgnC3hjAAAAJM88MCVYlCys4MRhoKE5omQhIlyjlMzmZxatqnTuvr57/////q/q5lf/syNjH/28hP9XKw6wqz6hgY+wHwYMDu254AApnnjQMoBKHkzUYNSZWQ2oofKwedTM7iUFnJr+in/89/////1formV/+zWxj/7eQn+rlYdYVZ9QwMfYD4MGFcXuejAAREkEFlNyhTh8MCcyoLiJzzTYxYSL9CmBZpZwM3tJKatiqhZJkNpSs0pRyxr49XtS7Z2Koexra3u6UB9r7hOkLawQgABJABAIKbkAKLiJQ5lIeLGHmmwWCoSA6cqOYFjqXL2klNWzULJAQbSmhSjljXx6vaBnJs4qKUD2NbX9KA+19xNJ/WCCYgpr/+nIEgbEAAAIiFObgYRqMOsNbwDzDPAjsOXpGDEMBKQfwpJGInIG5HI390zkmgKMwoKOwnClTsk39lR1SsplmLDZJKaH8qDSmBMAEnN2jZih1Wbt2sBlbSDRRb0xdju78bsJEl31mSBGIdaMMWB9OtO+ilQ68t5147OnkijYJ6bq9898iZTaUY/rQIlMCZQk5uSXMNNO8nbnWGl2N+vVsT8bFdG9AVa+EpANgo2eM7TFavSYtxj7CR04LgMyVQAo26AFmROlrURG/GJcPvce3azp5zCVa5kfW9DggsO3i0IwGHntFhe5yXpSKrVFk0+0yvuKgTE+DKxHZiLa/NmYrhpwYPg7GhgK0IoOFFnwuucUTigcFDSaZbRdFywAGTC7UGz8nABSLPTQhsPmS6xVqCE2g+8+0imIKaP/6cARDtQACwhYK3UEjEbBAhsuxICKkCFghcsGIyAEHki3AwY0oAAwAAbgRBJdZPE1zdRBFg3GCYCFzljjSA8XCYLmA42YCLnhoRYSKrqpIJvpSwiQYMc+y9C7KLO46/Fn933ix57l2oGuBtgELpbizZobsmms6z3FjaApltqqEMMI0mt7HIDa8qu/q8s9N+jX393dKDoMQQTbTGdlSNBIyrI10V9NKTWPKAqxUMA0WSLB8YcJCjzazoLxfOk2rLg2PHnjKFLWtSWjSys4DgxjW3wmGV1FUsYSZaKVYG98tvScrOs0pWt0lMKPqy6EBFx3Hn+fIhwYYEZyR11MyB3mypTvSjx/jsaGZWd3O1NweE1KD46DimBJ6HxcM6itckxDSPQBk81+cStzOld0kmIKaimZccm4AAAD/+nIEJ4UABIIXF9qBKRjQQOGreSUGNAjYIWzEBSRhDaAtaLCKeHKIgNFk0DOTSnxjgakZjJEoAeiZHDX82I5SUSCR4KsERmJTzw6tqQFJpgVgHRZAhppsaMLXrFzo5RvQqp/u17vu+5oAANAArWIZAGqBR0Wc9BhBBT1r4xaHBRh0jGJvMHQMrPamZWOe0cbGwG3aXIjbyRZhnKpFOe+x7BLzqSskepK+ToFEByLKAKQjY56vLBKEXsuLnRElweAxpzg0hptOtZYUItcaFwhrcVcFA0OQo804CrhftyirjwwftWsr3h1PEKxFpTDT1naAwBJSUc13AGtUSWOvORnzIlqL1f8rdxExVrBWaE1jXp9vnMRXw/oGbkzQhQ/NIIYapfNWoStxytg5ibL8j9YipU/HWpiCmooAAP/6cATMWgAOAhEUWJHsEOBDRbuaIEN/CKhdWgwwbMEOjGvE8ZoQABqrUkIrkIrnD8BPnxNoL4GsskWY1Tu7Pslx70GAgE3hpG43hRC8G3QtU5TiApYHhnORGGl25N7b28w7OuMfDvdKh6ik04427rgSsp4uXjJohmwjbZMw7o+706ikIU7/XZV2bRorIyXvCpyXIUAiazvMOn1iNG5cN921a0OI/bvLPVuFQ1Up5UVohFp3W1mM3Cr+rK/YAzS3qktAtLeWEBduCJBuAoZvVoxcRLD1xVQFhoGnpW1JZ8IqKC1xR8pi1Ukmg3p+rR//31g/dH7BHQT/MFVNMVgg4HfHZnj3W2dY8XDWGXYyScypnlj90xgVopRiMabNYxgcDwWPPJ5FJy0QTGzM5b+u5n2NT+5aExBTUUD/+nIE7NQAAIIiDVt5aRjYQ2FrOj2pJgg8O2DGNMqBAxrsjPCKcDAAIAAIIpJMp2tgzdG23dn8ZPiXv8KVQdhO04FGuMFBehiDg3U6w64mbvASWByTFlU6j1HF6P9EJL3jolT3VgtkaiK6gAAIIKTctlgbIfHa1zJiVVFUdQrrXsqyIDynBccLWoYKLeSrrYMutpn7iDHJ2JqSeudaIaql96RResjyGGq2wW04l1ABAi/32fA5SFeFS2VeMQAshSNkHj/jq8hUF3rNMWxDhq1jBzmywu6ZRxU2tylCtRmnG04yUk6rXDnOfpn/TyPW+SQCckku/0OjTBJLarTnuBrJ6FE/a//N7DGPCM7mQdYZ/32dVEaslkttmhSRAS9nyq4yp5JDWUSlCE5OvY/998j7ExBTUUzLjk3AAP/6cAS9jQAEgd0Y1gMJQxBCo4s9MMJiCJg5Y0Y8yIEjjGuM9hRwnrWAse5bg1yHbp5RS5ECGvkEhHlgKLxR7sCmZc55IeCmSVHZw57GGRQZQgkQFhoADjW1MKt9e9xR6+pIAAAChAMctts1QDfQZdzTzuDQ2ExfcSPoHWF7tTR9eXS6cKwiseyHdcP3C5CN0FUlUMFTQJNrlVbn6ibvleps8z6KAwAC3JbbO0AhDbzl/n9sECVhW9N5Qjf19zi4HbHHNgGCeTNrkCBsDgmEFMCZw4DBYpKSe6g8hCHVChMHile3TtT0Vq1IACLTkkX44JxWrDU2q0DWnAs0tjG8+cPLDbBwthZJVpndGR2jiYjgyMOTO8A8qsFEgo4oIXOHIZQnVfFQ7r2a3HhtKWPq9ZjV2piCmooAAAD/+nIEnygACMIUF9WLCDOiQ0MLAz0iWAh44WznmENhGoxrSYYgqAcp+rYEY5dqojXEptp1v2JqsGlt3daVC5jQF9yc0zZYOzBQaC02daWRknZEEyLaVCsHJf/6tNFMqO2s0Wzv/+5/7yIKblt0+oTOI1pl9W5X75fA0VHrgtt4/2Xh8HVha3ar6PBuvW98FsLlRR3qvimKsD9ilMI7EljnOVnKiKalaclb8j+8zD0ku8NIBeEIB0iCyGjWcDNKA+6y0db6Ozi5G1fRoOk5s1b3tMjbO136v1V9P20Ur3UycYjfaqMXv/UlctbL0aN3XuAa/H3EQDx46MXm/wHDYqQiQwhrCmpB0bxujU6yCMuCVsIR1dvBldPWVyNtg8wxNQ+YUIbyySsp2FbhjSsPXqq+tmN/Zuf1JiCmgP/6cATbYAAEAg0YVxsvENBAgfszYWMaiMxhYuywo2EdDG/0kImmACTcgZGI3g+MMZVUE+Cto3KH5a5CsTLKrCGhmhBVRZ/YW9hysUqBEPGLYVTOKOhQacrQSIvcfvtGqrkNltTvTV9ZBSbkkrISBy0+TzDBq6gRjPQgYr0qXPkuHi0+p6jRxPTNgRAhLoUcqSkGjoAZlTTWGfRDq3giM80e96mN3y39dRACablzOATApclHVxdC3AjtLMYflN/D+46gJQUejZmo/ZRcJsk3MsY4Ixi/TMpvkRVz2SFZlbRzX0Xm+2oPOeqG62097/6gLE2VU1JI5dAFpH3QRM6kd+qzGax7CRLTZOaYLzkHNgFpFdMsNA1qFoehkUrVVRl+aasjmc7nEHwT2MBcmkkfWOR1hhY9NyUxBTT/+nIE7p4ABAIIPdqzBhDcQYDrmjzFFYi4yWDsJKNhH5krzYMJ2igJTNa2BJMZdxVlpbK/2cEL3JrqJzCXQXcujag5UZD01sWzW2bd099nRTzvtNTPZSN/9PdwoaMl2EkTDe6r8rRoCUAgkpNN1ICMvVQRPA5ig3GFCU4LuRReVkLireqj2mCOtCQAPsOtC66qvJjnEg6BlnULvVI1HXWasAOgmHnrK9KyCU3HLiCBNS2smBGdccTUzhegqMt5rjcRBsIibTO4t27oFCiX2R7E3VkVEjTS++7NVN6Uq9R0Yj54AuIMAup3rvR/yqWjyCk25ByRSyRIJ6Ou9Nudkrjb+B4TF4J/wSzS3wt+4nbLraFatQ5YKiu/2zpCaNp3yb2XJnsrMkHuuvOtocKfpV7Ebr4qnn31piCmgP/6cATD4AAAAg0y2T084AQ9onwdowgBiPSbeVhhgBEjEq8rECADIAgm3IAOIPNy/PHjY33ws/sLml2+NozLoSaKA2xrKcvbR7izS81jDrm6PV0VV9U7UTvvz4+PzMHmKW1MQCgXKn9YMjQMajltl31XKIBBiWFq/f9+6uNvvoKqhYmvciqjOKhMDidsanEJZlqVn8n+hR8r+zWNTtAITa8hn2JJBkACRWr9t2223b/AAaqsO1PcjvEngmYROT7I5kb3ysNurZTGL8v4R+wIiLtjfKYeGFjS+2LWmlUIGWgChJFQox0KmUuD59NyEgAAIq3yS27XXf8ABUTRJQ+54pUd4qCss93c2+yLdiWviGawjox5qMXmmewXehI6v82SV9d5oB652/9n/uPtgc/dbwlx3OSGsrpiCmj/+nAEtaMAAAIVWuGeBKACRMtcc8CUAMiQ13WcMQABDYXuZ4wgAAhKLRaLRaLv6suT/////97fk5BFzC5jfkD4fOSx2AQSFRgtp3D538jM7rchif8/VyEY58rHECqdP//ncn9FV4pxAdhBsSCQSCQX////////v/k5CzHMb8UD4fFyIQ7AIJAokLfw+d+hCFdzu5BIU/4u9lchGOd5WOHCjTp/+/ncn9Cq7inEB2gggA6vQEFDxPcpRHsM0LGHlTL+7cs6mb5Wf790VrOblkp9XZCsTvzqt2ogtTz4naEUtkGfWFGzjQTR9ZlrQ0hSnYqgRB0j9yAAe9APNPxnQ/bCm3IPRJXpdOnyEoVMspakVcZDk6cZkxgaDF8+00oRqe8XaxLZBn1hRs40EyGR1hlrQ0hXrQRTEFNA//pyBJvpAAACHzZdaMUSMEGGy40kZTYIqNeDooRzsQ2a7fSAjqgBppBfSNAoleHCrLubYTwsMZGwp0DFnBrZum1Cs3qSGa1PViDkvo+3+lD7J+Z0dPCOPIyMi3V9RNews93rXiImyHdXMgUIBLyskAgLx0NPVTx2v4wdCoFOzh08B+2Ul2otvtT09WYeS+htv9KPsn6Ojp4g49lMi3V/XsLP+teDQLkYd1PzLDTRTskaRJKOa0h5ZsbOnEmRA2beEoCgPZ/DMH/WGZ5o6PZC+8i+ZHJnnArolVaYPVmup56wQtWDydVgTO4iatz6mOeSSBAQAnY2kW23dwIwVPPHhPVb+Mrm9DB+60Xk/zwf9YZnmtHsn95F+RyZ5wK6JVWmH1mveywVasHk6rAmdxE1bn1XPalMQU1FAAD/+nAEn4MAAAIQQFep5ROgQugLTSwimgjFA2tFhKYhFhrs9LSIbABzu5qRRBN4STa4QMqmmRIUec1nJpwypMJNU7tXfXRt7L/zPIlJJTWvW3VhXbbXm8Eb/68lbiXJXq0OSU7//5lj6wIAAGhEpGnYulhJzGF8Qa8gqu6T3R4y85wfkmbkeSwZ8XxN2/N0TMz7yiuz217+Cf//64zq+LTTjIEWz6maKOQU+tcRgKNOppprnsNJcjTY/DgOGSY1ts+gatKIlH5atUr5fZlimjFv+vZMOaLLuxml8JB+v1ekzcqILNOsogY8wjKfl073fDkWAgIAAFJbQCdtcDDNW1sgn+4XjZjBtRs+gGiHRDaXo2XXt3XotFKiEtMq6Mmzez/r6D9XUiHPrgrTUjS8ivsct2VIC4o2xMQQ//pyBIgyAAGCEEBfUEMuPENJu0oNgg0IPGl7QwTrMRGQawWHlHDMof45G0k0JOYGtYjBT2yaNgGhMzM42/PTKspbNP2KfYzmVzL1p51Q9J0mfGTI/0Az10ppensNdvoZYuInfS7s0esEAMEY2ik6OwFcetuV043Cla2Ikg9GyaD0eytm0bepkqnRNAbymkPu0qX6QdXTfYvtxXrn/RX4Nvt+eb/nG7livU36IzxrjccI8pEDfcMBfEhEseSmPYc7GpY2rfRcscyCJoibERKdOqcHHqqNCdLCazqiKD0UCiPbyBSdaUOu8kO1A1s2Ae7r2SALEdbessikCJidaaIZmIHG0zPGBlQ2gSeimdh0TXGLXjtm/x9CRtDaFMpGUJriRwuwSx+1NnyZ9mcJfccREX6UxBTUUzLjk3D/+nAEE1kAAAH2Nd9owSzcQea7rCAiuYkJM3VCjF5xHZsqQYSJ4Ia2gXU242kogOwF0SUOql/v8b/l7h07eYZ8bnzzKkry26c13CnhXZTDerdEfdn1DPdJVp/3W/Ro1k32nNkNtIoBSRO3TXVwHJiRfAf+SOoML2l/X383EnbvP8zpbFS7NHkZdPWdydr/dH9Rv2wiR+sKXKQ8VJs3InzEmfzlQmQeSkulSbiaKatAyBAJO6h7KR04cer0JkH1fDjSro0RPJW20lnUqsbf+e6G80H4tvrDpx/0kp+SLfu/0//X9L3FIfKp1raGnqurIww4DRT6x55Qm8+0vdMW1P8Z3FZEok1O2iCViONnCT0Sv1Vudi2+Jr3uUkh9l22f0ZWdEbZNrSltd+yzv9hfY2R2J/KdKf/mUxBA//pyBIyAAAACCyfa0WYQqEIiuzo9IhsI0MdlR5hDYRYT7Kj2CGwEgIHJrJLpuQsiKKy5EZ1MCe4E1e2ZMfBtky4JDR0vrbede1q+CUwUU9g6hZFEVbTydVmzWMcprxMS+kjh1dWojQGCCCSajk0kNtEqehoQ06KM4Hvik/H1fbRqm30H3MYftyS6fVYFGOeOWhZE5Vyu5QsOM6dMmeUeFCDX/w6bdYx22VCCACmVxuWrhgk4dM2eYEt0WGlB8Lq+fBiQUBD70f5izmT1rbOq3udLXrodVVTIajbJDj0sV7pT3W7hZ4VzpazIKNnZn8jsDIASF2NyWTEMN96pfLMujaZMEcED+AvBj14cS4Mp2Lgn7XLm1Z/R7XvcGvw5zC46dqE6xNKJctD91hH5We3u4tRR+7Bq1MQU1FD/+nAEhr0AAAIfIVhR7CjYQ0Kqw2HlHAi013FDDELw84ctZJMkbgAACbELbctfImjhDLqu1hf8idEgtI8Y9R9hDDoO7A52CAtZ3Xqm3d1b4mOY1FVKgZvAUQRAELlkoZT2xb+tPnH/Q+okQEm5Jbm4iCsTWGiOuAkkX8AdsMexr1wmJ40NlGNAUNl6PGPQtyKfJBVqqqY+CQGghMloSnV5zfFtvkabmvVp/JHbNCIKdFJppuJRwehXPoa3G3ORMGPh3mfNm1Jk5dOTasmFSr/tURsdkDzlM0uRK3rjfgUDRQqlhFt4RdxZM4RTUfGU2JdT2FkiAtCmW3tKADazR00l/qoergInc61+T02KkNAaGVeP0UuKTTGlXCtzzq77xZKv/satFY8ygqs84FXd8v9aYgpqKZlxybgA//pyBGljAAACECbYGw8Q6ENmW7okYh+IrMtxR5xF8REZq92XiHQBtMO6VoCzO0medkqSY2B4gXGELu0bivrddxlKiog6yfR6pobH2LddPv2bXg4cuNFEyKXK0/imgl/bsPMKRF693+wAEXklG25bIwTF0s0yXBkal4PdZUZ8lOj0Jp3/Lp32e1nkWDyE8zv9M24I+LCQWQnr7NmlxBZZQq0SKJPITS85nrXdIAI3lFppursc4Gko9QjHdBviFy8nUiMpI0FGq/OlTtL/fCfXtT7YKQg3ZSZa03XBDUW+wTUi4S049jbo08Ooyu0OAm9/sAEAAU3ch3Aq59vFv4r5IGLGwq/xpucXav/mdzlwB6CfobXtr+T/6bbWS0ZJvVU/e4TOi6/WENTP5hgJDxppiDqpBbFoTEFNRQD/+nAEsx0AAAIOMtWbLBMgQoabJmGFG4ihAYOjHEPxGIxqzaeIcAAgpaC1h9eKjIBpfPtIfrKbZNzMcDIgxYXzKuCgjdhvLiGoPyUG+fRO+drdzOrftn0ZLU0/2oGpsy80glMpp9//uIWCqttcMTHzZhZImv+rJkLUcFUmMH4+oSar6Jjql+pHt3/6tdXe2epmSXT9NGsMdY8ou1N6emn6LguJEkNDodwx+gEmNSax6y3bgUsbWzKWzBk1VwscfE2LzvmWjaajwz6Ll/bVt9dXedsfO1f9HCvv/3V9Vn5gcUQcmFrZDdoSSvncpah+m4AoSjYUnGkKywRCXkJIqpzkSf0gRVrux035mRsJQCGg9HLIJqC1yinE8e9a23rpnxM9JomEnqGiGGyelv/+iQhljLU3t/0JiCmg//pyBGePAABCDTLc0ak4bEElCtdp5RwIrSltVPKAOSCZKo6ycAAI8e4W03JQwPqLGay0k74xs73GxahbI5VGKBKpi9tTMtpzv+2r05r11tU169/jg8beUeN3TzlDrnMvxj1G6qSe/0kAQDluwFIDuO+W67Gymp5S9ZkI0hTBhH/rqagZgK0aDoh1Z9VxugrpztJ+0xVmZoqeLx7VptTeODiZz91jnPd/qBFBZFotOAd2qI3MlvvGP0VEpn2EdGkA2x62OdNsgJQVxfRf9FyaNm1Wo7a91ppoPSXv/+pc2T9nWzU9zh4LLiFAntv/eKAQc2Bn6CxCzDOBlcfWwsXGOpmcm2/eSbg11lMKiyUFhjAHGRCNB01SMq8or1ajb+1fzdu2c8q2y1T6dMlDdv0VWMG9yMDT+hMQU0D/+nAEqU0AAAILB2JuGESEQaErR8YMAIjEQXg8kYABFhYvB5IgAAAQgCTEWnI63K7bv8B1Vof7l725+BA8MHAwGBxhEYKA3MJM0Zh1RLRoPMo5i82/t5e53NaXoWSe/cn//3OJnwfEAAAKJJLJkQiAYxG4/huSyMP8KY609OeKSQrtgACFAwYMGKq1gggm9GY1I0JoOZDmL3m33PUqA7v6fv3f//c4m8+Q0dQUBgKGR8ysqXSYbY/mxCO5rCyo6iMLk0hJApnGwIhoq8+TNX2KKgIXGJzI4fuz6aBzT5ldW0WH55C377l1lyJhOonXivrqBQMBQyLnkSq6TDZjfNhGdblRnZR2Q9V3VLUfkRfSy0V61d236aSsGDqCSbwyOH7s+mhTT7l1cWXnkLfv15dLk6ideKpiCmoo//pyBKRKAAACICFcywYowEPELI0UInuIHNmdooRccRaa7hmDiLgAACBgACGhgAQ2GXTRNCH3mLmUuopzCr1A7Ycf0qR5lqVbbs9rKKsVjiRTrPEwMyVVvnYtWg+7G9+AiKSY1b36clonaAElHJVFGkSUggC3dSreIPjS5rCNZsKOH+tqYTqrs9rKJYQxxIpyoNkweYdKq3zqRatB92E++gBESxMIre/N3EtDjtGsORya/O6yNuXHCxbGe1Dzq2jsrBMUJCxLv9MdpVJHvf0dxrKwqGaL1WYrJp8hUzcVfUxVmzzakrHjaaPJPG4b/1AMCBmn0EluY/UhzInFJZgor1LbGVhdsQt26+2hS5Hvf913Ll2+1tTXJZ+hqPMmBJoET2K1fex5Mk1D53eKguhsqard22KTEFNRQAD/+nAEgscAAAIaQN9p4ygoQ8gLZmEnGghw12AtMKlBFqNwqJKJpgCQ2xSprGo6egvGCu0hZ4V1Hcr1VuCcV6bJ7lud1dRVtOaVS0erL7erd/o/9RX/6f3GOSo1Wi1Yl/OnX0khw7W1iGLAQOy9oeBLJU4KsjjRGszweCnuzOeuoQi9YnDGhHRNraI1z3v9u9TTaPVl2/Vud85/8j///lB7rtiLIud+grx7iPapKgvGJgC8uivaGn9lEUSml4RPDU1MXGs6yNWajKilHcLBBIVACzI1kfhjav/EdVbk7s23fKX/pub47/dP7fHJzv/3fd7Qlf/TjbTUA4I3J+V8+9Y87HViG4CBqxo7g+5tlbBALYl9G69tUbv/3qNlv6bm9Bv/3XZaB3W9aOiwbDnO/R23X63m1yILJiCA//pyBCjAAAACFzXcUecpeEQmu8o8xQMISNdmbDClwRMm7V2ElLgMAQIgHXJRMwRM6xeSoRqQlB2tuP7lCxlA2ZlBm7aeL/7dP7tt/0SKDcy1nYYuvwXqrJySAy1i09bc951Rf3b8JWvWECKbqP+v5pkNSGlNY01RHRufjEaND/ADYayr8X/o3f9DDltIZEpOyLZ9LPlWdbaCq7S7uiGflXn9TwHtdWzuVywfsesAJySQKXceRN/a6l8WRFnFxVV5r8z9P3C8UPxOZcCvVejcCfxAF5Wejbvzuzei1Ndpuquv9BfXr898UrpQR/RtV/tIAADLbsIGvPMN/RVU4grF3B8lP5U/11P9e5rh+WgX/R9SdOMHfya2t1b1tUSspq96d9D/1pfsvEn/+j6/JRB/bH0QB+lMQU1FAAD/+nAEnF8AAAIMNd7IwylsQqa8DRQj1Yi42XFEnFERFy9wNFCLpgwGdUvq4COhhtwxn6DrQD6ZUgMM1HLgN/Q/fr0F+vtcyFKiGbo6NjU77IcnTaoviEe5RJtPt3OAT5ZOQ02REz1+oCEIMkgtRtuRSKDQtaXreghqfrxpOb+jzKKpj2yX89m0IwPRk/M91qy+SFMcaoNDDwVdSko3VU08106R992Ij121FIYQwAtuSSDDWE7Yp8wPxafOb6Jd1Q3xWMNrx39YzqNT6hUZ1AuESilcrL29OVTsG50rW1jeDBN2wptX+1iiku99XVlzf9ZMIQZQCccbdGHcPiwpdbVSqCOidvHdv1QN0DnAV8TVsdTXJ5K+WmyAQf5lA55gWPWTN8kXryy5hFy26//F+7ps/1BLPBpSYgpo//pwBEr8AAACGBzb0McpaEQpi+oIIuOImJdzQxxt0QsOq4j2ndAIAAglLZLh8EABR0uCxWoBzUJ5R9wVBSVRsJbH0EwNxTx+IFl6mnjQs1zAxFz7rWsaBmJEul+7WT+u9b3kk9GnMP+SDSJwgNtuR0chAiOSfDcfQ+4/jN/9+fpwY+nrxihJHk/Viu3+ro73QK99WVX/WZUe1+vkcxzMRDxRsvlxg4qMF5nboXWFEIRAVltpbIH2VVB6umOUsloZxOecyBhsr/Vu/+X/pspbMJZIoPQKCrkvlhoia5Cllc+aqk+yPIHx4SPGGM30p+91aNIB/4TFiWwU7q8R8L52ouYBLj6na1Zj8JY9g/nx+h8ClIYvWVE9HKIsqA47P5UZ7zlhVCuGYUIEdgmIKUe1pZ2L/fyKYgpqKP/6cgQGPwAAAh8g22kJKNhDhstnJEVkiLB1e0MUQPEWjm5oYonKAAGAAJAt2u5Rig4/asArtmkNntp2p9giPGxitp76rwL/GgatNBjSweERBiUJpF0satA8xLawC47tkX9eeFtBX47kfyRAiAnLbViLiCaf0U4e6RfMbrsJHrCjtk/245v4b/fo1Eemj70Nbl87K/dlHrCIRIm3RPXrZWZz6b31pnjDs+7yrluisaIvMhuOS0HlIqOFXoF0Xs6MDHNQXoEJROqc39RsOckWusSsa4DvZeKBzJWkrEiJIsdHstgVYsOfedCddp0qyWDVCddOKpgFCgnLbtbcTYn6Ka+06wEjlJsFOkEO1BP+2h+H8VFpWTdtGUC4IgpqLChsZKFbFGFkq1/lqBrUiYMvlWFXnHVja3YforTA//pwBAf0AAACEj/g6CMoXELjW5oY5nmIJH1kZ7DjEReObAz2LGAmIUlRJOSy31RQnm+lhHvoZo7bV8/TxThFv68R/o1EW+P1vKlrt3VUt9P+mzzlxjESKIvDbyV53S+MzTLiuhEmTWdCAGIhlNJ17oKgptF9f5WuUncf7DwYLIUd8Z/oMcKAb90VqIUdDgZyNuOOY4YVxXFOxf+qhhCSY2V+xhNinPQigOKOgNJuQMGZSOf9M6NlqihCNI3i7hDWPqtTOJH1YoLckNQ0x46Xso049nLooxZwZEDR7bTpHt0RGVErlKXW90XT6/oAhlv4ZVpWBYxJkywCBdHToTf9IJzbSfzIpj7eRBAXyafDtXgje8vvkwdbIMqaK3Boo5TTgopxrIDOnTvcAECIn9bqtzP3piCmooAAAP/6cgTLxgABAg5BXdDHE+RDx5v9HCLzyDihXmeob4EYlK1okIrSSRMJESbf+EeFlY+HMrsrcYf06y/bF/9H6f0DPZtPb0bGaLQrTmTXsU2zentaiJYrnpFxL2DojFr0rHhXU2Ktn8+hCkBFJoqSy3IsmLx9We1DOX5lYpUvExza9a7cz+gd7Z3R3OWcZkGsMvZJM0lX6/yLg27py4zzzmv5fGof2R/u5+U/b7ADydb4Yjh47XMcU1sUeOOi2pEusmEW2GItIyhVeooWXTnDbiX/Fw/5H/oF49UpAEgLELgdL3N3exbETwvb836/+oIARUSHbcIJqgA0RnZilRfnEWdNF/rfvWWm7LBt/tFHiTs/GsvXf8E/rszQpcRx1LgI2bWebYtRCeEo1/2C5IJKedW5+4BJiCmooAAA//pwBBWIAAgB8ilauSI8pEOkWwc9YmaIqP9k5hROkQ8gLeiRFaYBQSTtuBWFDJvc0gs1y4l3Umv45taVHE4Tj4gEyZOED5V9CXM9+/ZeXx6wMjWwA5J3+KJHny4XG/1ufanbhMgABSbkB2InhjxILamxzRiP2ehQx9szmo7OF0jY00gaNUGkYFSDH5OHbDl1AOfgn1uTZe5dRUaIUeVi0Li6Fhpun//WIApSXBlxoDx1KFQjXHziGED3QK1nNGOQHXO1RPsmfimyvo3O2j/3kaN3JQzf+38n0fRZGQKiFDHRHTSMuHFCxWYS996VBggQQkmnAlLQWMiBLQ/a3WMPx+Lgo8tRTVEFutI1+nAr40X4q23v6ijELYy+2u+330T7P9DsVGKMHPP/m0GjZ5mZtzyYgpqKZlxybv/6cgRingAAAhBAWhUwoAxCiZtDpggAiOTtdPhhABEbHa9rDCAChSrLPLApPZg4qrD25DEjplB2PRAgPTGhinEkdVZDnFtUXGD+Dv+M6P9e9k//Vd1lbX2MaiGmdFK1RFCb9ldy+uiWABcu4f5IBFfZNESKmuxjhk69kEUYp3g1bX6V8nN4//774OiD5u3/5tibfMiSbuqgxrBTMR6vaezdWIl48Ikgk115cAR9IRmQbG0AKh4dKb6zoZNGHOCnZHpNg2kfW3O+iu5HZ6Uz5kdGbktJkZ/v+xFc+mtmUqNUxGPFhiUcz0q92f//+Ay73pDAAACCtSKkWx2VBAbDus+nXbPM5rV03uisHaQ8mRWZXoZ9K+U7h3bey7o2TIQ6+LKtkyK53/bL1pxYYlDjP/dn///gMu96QwmA//pwBIEjAAACGyDgzyRACETEHI3giAEIaTeDpgxDoRAmsLTBiHwAATuoAHzC5GiZqTO5OL/m5VropERy72fqU0tW7Tfe9XFl5gV2NlQkWnkFklj1CZB5q8qu5NO8NnpbZXts0EfEj72ybBRak2+2kklRjGIMQaGntVZHqiI5d7P1KktW7TL7zTuLLzArip2VCRaeQWSRPUJkDQFQ8qu5NO8NhWW2V5KzQR8SPvbJgAGCX7yNEhK6GBqNJVuRW53YgZd2JV3wyF9UWkp+U1LfSlWlOXZ/z0Rrp+Tf3aXWhNd/V0//XstyZhgllGprYBTe7UAhKLb/bEkW/TgyjRKrXK3axiv+HYJ3qiF6qi0lXUpqW+lKtZS/+eiNdP03bZ2l1oTVL+rp/+vZbkzDEU1zrhUrQdelCYgpoP/6cgSdhgAIAgM128sGEMBCZruJYSIYCIEBaSywQUD9muxBphRgAAE1kEBigwRg7eB8KSrV4LPD1Jq221W5e+1+65Ut+pVLp0qyftUxUmMqdmbVuKUyrX/1vYqtzHeEiOKnJV21skACIfIKtDgwRk75CbEmiP7iZd+Nq3Bi7KIJld/a/Vcv/XLp0q39tCpQy/ZtW3FKZVr/2iryCq3Md1hIjipyVdtbJFiQBEphSRBGAgXqjNy175MJ8bQZWhX63xDZv9+I0Vv7aGq2pat9vR9X15WMesiifK1dFlLmSDG1RSsz1BX1lXdXyLJWNC0IgHo8NSPCeTD8OLmnwlobtD7RESu4RDTMtc13atE5Fon+RMWq11ard/0eqmy8rOvqO+tbsl+1/ETfaGv/9CYgpqKZlxybgAAAAAAA//pwBH44AAACADXZs0wQUENrzJ0YIhWINQFzSAyhYRKa64WknZgAkb3+BJgkaAkKDVEzh5rMpASspyYUfqdaCBO39Xuh0sRtP6dZ73ZWp9DPN09tLrBsJtnzBzfRuDKr21aPV+/rCcdWntt1skwjaZbcOalzgWqnUhR1yNl5c6LeL6dRHf9Ve+ysr9jUHQ2b36eoyp/f/yff9WdfTfb/t/sRdLVXCTbD0qAiPNMkr0oDwouHG7T0wgEW2IeSlGbJ/V+7Z1xJu/fVNNGyeiCYzlujVL/UM/p0QrssqiYxRVTnmU319uxnDvrbmB3NTeLO8VveeIzcIUBirNq8FMGsexzaKDXtygSQYUDBFI217w891Itv0I9nz2sj67LZ6sztbT7f8t1/h762M8h9XFH/SmIKaimZccm4AP/6cgSELAAIAhxY2tHpEFhCBXsDYYJKCMDZYkeMTyERKjG0MIneAACCAtNpsKU+LETdxfGDPBxG6Qaj9gUsEfIyNTdX1P26f6NV2dbpvt3a1zdKqleqB69Htpv8v/zJ0teq09H/X+4//qJhKSZKmUQIHZhSY18FHK4siKgj99FOTh/09iNL0BmTE5KoYGGXHZVBDlIg/6p+n5vqgVQSmauK9fQ2Gv9fIff7/pFlVkJACWIlMneRzmsq7GcbrrtVc4XqLGFcA/iFuxU4xYhLArb6m5US3mR6s21k9+1/3x61sJRY9u28glWXOu3rbTm5LkaAqzHJXZtbJbrrZm+Fkc+DZLTvGMiBX40qh3kI7OQ1psjfdaGM/2qhM6lW9TN/HrV1mm3/b/9p2KRD1xyyovpXg25v9y0xBTUU//pwBEBjAAACHjXauYkQWEPle1cxJRsISNl1IxRMMRGmbiiTFFQBgLTckpAComBo9Atw/Frlj2wT7Lwd6E0XYu6dCvher9u2qvr6v9FC+1Na3PSUCAFQRiUkfWSZs63oIvIMfTr5/X20JILC5JHMQANNB8aWhR6Iv0mn9J1yCVamSoCBsYztWn4olPq2t0NdWVLKQ1fo4icWfbYRLRnL1OyX1Ws3ob6ksd/gXPCgULUq91aTaMPzJMdD0N1QrQOm5XGo+hvpTxX8GPo7bq0jvWnL7qiDrujtZZzr1C3xe5RRaRT9q4nSLKR2NuoDUU4uEALkeu2v7SFkOK28BrNS8YfOtau2zOMOzKtKeBtDeD9P5lKbtcl9ZCoXN6VOemYVf//rev/6NUi86jmc5l0Ujohc/+RTEFNRQP/6cgQCWQAAghEz2JnsENBAZsuZJMUviM0zf6CgQXEerG1YkRWmICk22RayV5Cz7kPQPpiLxfLH4hfcAPwRxMEBvQT3pR9RPXq/8npvTr7FUz7/XpGoO0j0zJigh6R4RY3I3+lGlyvJAgC9N1Vpq0J5pluJxXYr8qv4bYXiaPKBXjESmjI3EfvGga+pVR9r7W7fVdqfXR60FrawpJcJd29GRS9X/NbcvoJaCbcTTkkks3IMqbrfDK8ETclKXoOagv6UfkfTzcXqu63RXIun0T308hnJSh75MvxDI8srFfTVGehSyJ5h2+1ABwE75KneQKVbdFcAGrnXiCmfTToLhtKO9A2gvXRkPuFGoYmNDGeqb873R5a/syv/0S6Ku9NDTdLb1//1fd1e+QYZult+avQUP6wDRUG0xBTQ//pwBDv/AAACGU1cUKEV7EJjivc8xXYIvHNcZ6TswRea7Fz0lGRJAaCEkknCCDhEVRHDzj40a8YW5S0lpUeO0/k8k8SyWZf5AX/ui5/2SLea+tL1hCW8/P01tTMCUV0SpYNvUBbX66sCkAYUktoevTcB9vKUjF7Ykf7lXF7ct+z55XAk47HDGYxsvsobxA6RjY0+FTjHh0Gka9c9xiJAnOKlUN5UpZ7PFHJ+wAmTbZWMqlC+W8HpODNVpYOfJvn3Rw39xB6egaFeAeJjdevR0dQ983jhaV2noEUeSy8fura1stcQak4VpGh5Hucatu/QzSBAAtOy5IpBWi7NqAdYAWUHsqboDY5oxxjg+DlxfY9akvO/bKIc+7Py7abp12yfnQq3U9BFoFE50sduu/GKImkRGhP09HqTAP/6cgTMrgAAAgs120knE+xB45tXJGVLiHkBbUGkQVEejmwM9Z2aDAKBqqrUlAUonrcHKQ/nHxpLJkd0RpVidCCZ9T0IHHKEha9s4YrTpz2UyXooOmgV7L+bQumFdS/npkX0btXT8p1EpIBSScXdYBUqSgD2hbQI+J7J5yCTBgQnt9duRu3DOqHw8cYTt1vbrUQ0i99EvmGfW4uWEzTZ1CSJsYJ3aharb2oCAIQhOS7YFMFTNfAvT/QPbMB4Po7EqyZv9tAvvxtl5+jNtrOojyJv9WfNa3yHX1w1jIgJw+hDrxLGrWbASDkf8sXd6yClJJIyudhxOpcrBM7Kr6RVuDfkilPMRLF2hBsLN3VfjdNOODsAILUGLhqAAFWHCwGAagVcw7KFEiXgCqz3LsF1PEzRBf34smIKaigA//pwBNUnAAACDxpYUeVDFD6kayowwmiJAGtg57DjURonbeiSiZoIAAQEi5IJFZQcLapWuIWB6rPCI0sYNhb+oHknMSSO5av+bx0qMFrrGMUdY9jpDruk3NT1CAcxVSBvYx3dqZqpn9YAAEMEOSUadaBF9DKbqBEomAVOfkvy47zXS0CANTBgzprtye2j//iE0CrQlBYIDNYvY4iO2otf/+pSCIBfrtIQCi3LRBPGESZHsMQMnmZ0eg22Et5UvuEJM5lTU1uhp7h1zxeuK2WH1etgGOmUGoQB91ubqILNLFn6GmzQCZJ1pNVWieHroUCAIwJy3biB+g0Ko30Wt+mnPFdXZw1qUDX117oJvMXBtmEUteTWHvZ52jpRp766+pN0oV6h5vZNW3oiG/6drHCFuDeH3GFJTEFNRf/6cgQCZQAAAgdOWj0koARBxQtWpIgBiPWVcnhjgBEfsq+fBqACIIQlJbhNNUGX14BWFdMRjlW9kAR8gg4nOR8v+11EDbdh8305zys6I9BXRql/+iJV6rxRF/m7f9/p+RMhonHvA9YBhG7xbWAJZSqBW0oKEefvoIDnVkrUM+EyaQQs7zpr0Pf6bKm1COhBM4kNvOn0nihHfOYiosjSS+7KLQGz82s8sNEAAAQCAQCA20HdZlnJNpGBDA7pO6OzMyM3/6tSv//////0PKGCQv//9hvLULj7////Mh4BkSLkzv////yxpUbA8EsYEk6cVcCehBACigYDAVjMUZ6w0zk1qOdtXsYzf/rp+mv//837f2VGFj///YV0HDjB0V3///+PFDoBCF5PFs7////9jSo+FQblhqdQq6YA//pwBBcDAAAB7ABhbwRAAECknArhCAAJNG1/IJhgwR6FMKgRiChKQgIoElFOTCokCwLl3icCNE4neTKDSjviMQVnykhIswQt4IBgoc8Ry6tYfoLtB/6HZcU//xObWQ1h4QRhyOEBAASU5V2HRs50u9XV1O9XkEK5G/6uh0I2p8mjaP+EES+HwACDgQ9R9Yf4nfhcuf+Y4OHP/VUsPnlDcTjDiBAAEAAALUUQRPSNMTuAqxkYApejTNxWqNiYUh8ZlP6pYyqTFSASJCocSeCgUIIe1qXPcgKPWb3pdNWpVsvEpSpDl914gy4w/VUSpgCxAkFNyRMINWVHOAlN2gAliqqXjDwSUlQddEt3FUBIkxCXsBoOIedCaXPcVCj3m95lyjTGm1eeEpSWQZ33TYgy4wPKVFiVKYgpoP/6cAS32AAA8foOXqnoGNBCwxuwBegGCNA9dqCkwAENDK7AxIxoIBI+bxhVZQwZAx+55IBE87HciGBUNHnunXEDo1ovcOOJChyDByo/WpIVPSpejOUxWXWPmn9Oixil9Wne5n9CrKoRuMyKZZoxGQfVNYA82VOc+orKiLTadX6wttRMmF1txBDpCBhBgd8kKgYTKS4+l0oKi49QbKNbSZ/3qsb2b9H/kAKACSD4JQgBBnSrCm/AgsvzmTeS6NPguRDIUEQIiwPA8ASzUgsxCyDWB1oplh5kcqvGrF5ugZsahdyKk8obfQllNZi1WQ6/umBkaHUnTez2rzpjFKjEpkVIEL6XYZHtsi7QUPAKWpEwrWQaeS0UyY8yaGJXWNtvXGNqaUuOoSpKMobeqcZTW75DrTEFNRQAAAD/+nIELucAAoHhCV0pJligQUgLpSxiegkEgWwGDM8BH5Au9GUVgLDAu9FoI3B4yDTmpzDQaGMWfFhEJY9qR45gIhU4e1Fjy6mLVGJSx4BHVUC1GfRpxVT+ds/yOSazV3TKiIBAfe0lBeLTLKJJ7hX0R5U1jGX5MKU97cmPeTQqqZr60Rza9gXpsl9Ee1/TSqNt52t9/RYbwlI2fURyTWau6lRFnxHYyP2RXVeUm5xR8jzBZyOFCm2nJROyoPWkKkbGG5OO83tV5hSFEg4YNHUTK0ETudkQos2TKsQ1IbvDT9T3NqXs71JosT9OkCAohJJOd3SnRatKQ7K2wTgZLUKXlREUj1vfuWTWu6O8rCoFLIAt7kQEVWl21TAot4mK+G44ltShGqRsz4dUmtzElhe1RPhxKYgpqKAAAP/6cATzCQAEAhkY2zGPGwA+IxtmMgNgCNRjaGWMToEYiq+0YJzMgAiq1auX5FcHVdCug4ncm7KViKYP2BeaKUYXewzL4xhgbwMwbc1a3TAiHSJuLhoAqHmINDr3Iq9dmuz92tH5FvT0RwBABFrvbI0dwVfsnO5ZWWmADkTk/DhZ0ayCr/6r6SizY+Sc6KrGIIkcMr2oryIixdDJ7rs/f9td+3PN0lk7QASnHG5iOEXB9C6BGHxov2QNgCNHAWSmOUoSq93Ze970FUXzB1y1qpWgHqod2hoYE3NKtY8XqHanovRVK2JRppZqkT2/fzNFCAFccltu3U/DGOXqQq+A5HFBiXs6mXxq9VuPPEoddqrvPWg5e0Jc9GMDWJSyTpVxhzwXj4iGzsjDopQp633v9qi09kWuTEFNRQD/+nIEVtwABAIJD9mQz0lAQkR7NjzHdAis12tHpEsA+wVv6DCYnga/9VCAkPRMDWel2Mnnu5+BoPWyGunele9VQ+8o5DXjkgMSbNLRy0PSOTNAEY5MmftoEFjxtZ1n1Jsda729/T01wAAL/3V2BOrOoB95UxHaXcLDY9ADNuA+f9F4g8VxAzLzTa3Yxd+/dfzI45o4+NJCNY4XyxJrYhddHXf7xRDf9t79MAAKTktsWr5HwMkAfSLsx9pmukNyrC/he5sc587RZ8lXKZMOG5N/TpWlPTa/Rza669Xe2O6+9B4IlZ2tanOu/oaxfb+6SiATsotJJRChi8nMc2uxS7BRJBcKuQt5J0e8vycXQAFEVGUMITtRHZJE1hsnYYGovlWmKvf/V7lkYu9eUalRVMQU1FMy45NwAAAAAP/6cAREjAAAAhIZXbgIODhEAxwKFCOFiHRxcOCkQaEHmi1clpUQAC0tfbeScuExmpTJNcEMzWlZrqqigyvINV1YYqaUSFwhEoZOgOaTY0MB4BmRouLFrkt66199+wnWYZAuSuqRhq3lslEqSTbTcRlc0ZVjVfcDs4UbkzobDg1filnwA7MhhQGgmtwqpAkFgteduCrAyUiK6t0RPPGlFS7muxxdOTtvYNQtzPogIQ25JdJMIT8g5pYI9QnyxEFRcVrRklu8BdF664IDf4l1aoNMB48RohoLlLF2Qg1xCXMJ+UfbooUKBW9VTHVIb3WW0AEBLk222iEMHuQZEsJBln8ngdDsDh1bjKSmd5HqXEZV3A/6v6vXRd2ZHsj9NK395HIzqMLGJZCvru6jSMV9OnZ/oTEFNRQAAAD/+nIENYAAAMICGODQoSu8QqObUz0lcgjMYWhjvENBEYxsTPMV0NhkeLUcblrKarVA9D6BtnI0U5qosuoGRiti3a66PIlXF10hrPqY5rSzDoqy+9YZjFEeotp3tNNHMdeXZu1VMdqCcmu/v7I1/4USzGo9wGb1iiz1MZglepNlHPnapZgk2KtAlFLja3EUUzi5eOFblV2izD7rXMV1J/NNnBz0c2j92/fQAXLf/eDXDInMtFyZXXnc8AwRahIgE1WRjXzuJT1GRqwd0RnFtVYFScM0Gkhkgci66r5iTRaUek0ONxqE1rU9Lt6vNM/qUoAFN2iPpIHmrtTLMM5SDZPQ4poCVAnHIAAPcoFKfnBN4Kl9hrsrUGGBaQwIKVCw8p6nucm2KOp06knTzk+8WfZDybvrWmIKaigAAP/6cAQwOAAMAgEY2ZnhHDBDijwaFCP1iJxjYGfhDEEMjGyM8xXQAjl2Ax2NLSyj3QcE/CIiphXbaiYgnI0F/gdGgxtlI/osMYmHz4gDyiqTcTjXl45TgMpr7ZEDgpTWp2xy0kUo9OMC9lOSN3O12n0aj0gORQky2skwvzfo+yqB+zztT798WcoijKqEs0pBfPnvLDl/xeffX8vOcl2I/alsNHiqvgGVYq5IIKjtE856p4+7l4FEuC3FXYoFrVNBQLTP36WuZ0NzsXuF3rjpiWuR3QUSSh1V67BpwnpUISQPHGV0IaiLu7Xvodfev/6wA3bv9bXzmV+HtnzSedkwr6tS2CYXovCinL5U2StEWq97vawE7FR4BkGPuZKoAyTMyu11mrnRRzSe7Xfa3ZcQW53/cmIKaigAAAD/+nIEz9MADAIHGNmZ4xOQQYNMLRwph4jMY1xsJQ6BGZ4t6JCKIgBJt+L6ZBUskAbCWjlmQ7Z8TeUfR9uOCZ+3UD3iHquKSjTAdk4VGtqErR4SeaFZNYeAs/cWfVW6ieQ5xKnQs6vRAmCVE05JZLzdjq6pTnBGjDs7NmY1ycx4/lSDedKpzOkFAILl6ZNYmGHkzl4RQczd4i0W/2zwJ+p0so0cDrsjK21AAJ20ZYtKTDeWaLDm8h1YiVl5hTidelS4NGGWMiYvkGp2RoN5AXTLrUFi4ytQDEmWIXRQoVEpt63uYhniIBI1mE06jVn2LQACABNyXbbOFTHr0IEPWY29BQzcmwWTm96nwc2EFF1VWqV2G20arVf/TQu26yc2/e345I+Io6eantDJAXctsJLlT4ajfTWmIKaigP/6cARbbwAMAf4lWbgsEHRBwrs3MMJ0iGzJaGMwRVEVkqxc8wnSAIAEnJADURi3JKGB8Iwe5YsahlcCSlnbD4ZkhyPhFq+rX1L+StmZX75hoMirULClyKSxgA0KQHFTLJoRs/r/tAIASnJRTngqT43j5sRvuVJQ+Cug8GX4Oyn2FNrXh2vVZDLfPDHNHmdinEGuKTQCe5wHRwIlMslPVQfEw8MU5y4ioAlyWhWiwGdI9kWEUlGU7vIZiGz8Tt2w7LcQ+DNvva8oA33+31sQYgNtl3lSCLfuxCNBnM1+GjgCDpq8ygM+RdseqhcAAAU3IHGCuzLPK97vSYqDR7tzhDYTcyCnR+Hql6GHGnNVsbvh/3qv01NQRBuRrWIXHS1hdy79up4bNnjT3pJJ7JjtKVrTEFNRTMuOTcD/+nIEoTsAAAHqNds9MOAEP6MbuqMUAYjdNXIYkoABJKauQxJwAIAApOW0RShiQo0NYmC41yHFMJ4WdL5rpmceaY9VVkePA5PnNt6fpVTFKmWX867epnz3z6EbQwfNUF7l0/uQRBIJNNuB+WQQ5tsYXy7zwARQp2fXiDu1Gk5y0eUBOZE9qLI0kpqJltqzhVAnU9Dz6HkFiVcNLiP9zTD6EeeXQlOEiSMwVAU0PtIIKis2VHsSHWS59nYvfdtEfmfo5BZf/0Bii5BP//QBgQPqoH///D4xpKCh////WeUXBwHWf/6AiPCzCisBk4OFkM7KtpmmAcYEROXEtw2XLnmS7u5quqaPcrUxPOfpMOX/9CRpMwf//0GwsG6qN///x8o1Mw////1nzSYOA6z//QEYWYUUmIKaigAAAP/6cAS63AAAAgkSYG8MYABEJCv94wgACDBJdSMFDkEKiS5UZB2IiAlIs0rSSKR1x9yNwos6adYlI4XBcPO8xkARw7LHSVKWwgUTZtlBQOGRE4VZRU/DYqre1/4uim4d00Me9d6ezdVAC+U8pE0UUu+r2425VT63YJeEgmYI+yHq5bPo/5mq1VNOs8AMDhdTNtSg5IuXoqfhsVVva/8XRTOgTpoY96708R0uUqAAHaAAHZLVhAUuW3XSN7jMVJsf8Ur0D5q2kTLZ1VfeAizw2RH1400imKv3HmomkqHYq7vpj2vQFNWkjxrSKdbnoANwPcDuAQ6kWXvWbsEXslpxfZnPhfelKlNUeW3eAizw2RH1400hiYqP3Hmomkiw7FXbnrTHtNAEKatId406RTrOvQmIKaimZccm4AD/+nIE0+UAAAIVNdy5IRYwQ8a7rSQixgiFAWhEmE7BDRstCPGV0IRqIkktbdn+NDFS3ap5rUjP9+vtPuGZW8hnePu3Xv6Exa/M2LXX+vCinPy+9Ynr6duu1r0tQocWJKF8DEg7KnbvZIgACAplxlJJv3Eewsp1vBSnmum3nO3V7T7r+L+Du3j7t2++MTFr/Ytdb+vNFDD5fesT19O3Xa15OiOTVwM18qdu0NZETBDU/hRo2Ixg9doMOEYQiHgTmkPH09eRDr7FjnBD0dX6dE0f6qXImVVm9ft/0M8/oK/+jqX2GXvx5hWIxvq+pPnsDRjgmqqfLArGc5046l3FmwzoHMUkhkIePh2LjFDYW9nza7AJRESjfWWpH1ZZv+wqzs3zGefxg/8iS0L+ParEY31fp9mqMTEFNRQAAP/6cARTPgAAAgpA38hhE4xDSAt6LSUqCEjXc0MI8cEXJG60YJYMwXS4n5rFNH65WCTmvR1ZqzhR8in0wlO69/0HpsxZ8hb1Zc7G62+vTt4J/6emx5TC3uPJ1AVJNDEdyjC8QP00h2YQABIKWyW1fJCuKJo8vkn1M/6G605S40iYgcfXJy3XYB7WzC+9lZT0Rr16dXfL0f/30H/1f+fi+ntAlj1Tu/9lnPGulAAKA9tv99Y4IwQfhmrZo1gMRmF8uj7TvLpReoyBwBdsjv0RmvZ/ZP9UNVSU6Jp48GtZc6tFcF/qqThH8Z1P3WNsrwAACjQklssyR1IYQJqM+Q3Q9AW89QdLAJR8uxLpq9w5yPm+jEuvOltvdkn5PtzM2gb76P9CKuHTt7t7GiPrIfFOLB/yobTEFNRQAAD/+nIE9SUACAIVGVoZ4zPAQqV8LRRidYg012+khFIBFBssqPCO4Am3JbfmMcMdTPbp+WA9xEjWgjaign2z4asHHzPXlL5L4ExJi1tCj52h0diIqNdeO9yKScSOMRl92znVH/yVaif1qLRgFJysuRxtxiwHjFvc6OD4HmFrzbhkx3p2v7rP1HqXtQhW9kt/uyKMaCqhzMjFh2Wzi3IEf1FDlazZDnlKqiF+6KKArAruu22cbakXzTGHpWyY5wMrn3KJNWnmiR4R5nmswaqbb0Zt6k0h+jO+7V6q+vzc/xHe9Ru+6u3c5jKejHW019QAAQAFNxyUwiT+hE7EdVZPYrI8kqQimkI+IlKT7lnz4ryPv4m7VnRbHX3+nZKLv+zmWSD8PXOXo3Y1rF//LckP/T32+5aYgpqKZlxybv/6cARL1wAIAfkTWThvSGBDBXsjPMVmCJyvaGYY66EckW20lBVsAICC5HINRlsKUTrNEOpXIWwr7pX9TB6pbLSafnlkUiz+BzHS2VOpUZ2x1zOtIzEh/lEw1oI//tRXWO7tut/1hpOSSTUTJ0qkHCRs2x7XVsHDUYbQLZkdKX83DMUL4wMiBVokZVwgm09n9V33da0/vQTNKTW3rvXz0eTuR7dUZ/O/94iTbbnaSQy0pfwcpTJoSUDc8PMX21YFk3NCP1hmER1aZf3Cfc56Ml23q6n6nf9TkUeeEq0S+rXzToFJfXdFJI9/w45XkoAABESm3LJaZfrUyQ0HQvR/fB5jjViKi/HbI5Q6Cg1F1HHaMZVCet2qn33ioFFiUtjD5EYbvicnLaFO1z7G2dzGqi1/vTlXJiCmooD/+nIEHzsAAAIOGNzowjPIP0MbzQUiBIfAY3MgJKHxHZruJBYIPmCAAaEJrrrv4MpLX0CgMa+o8sUGYC3dBkVZsO0M3R0fTwJJ3FjajinIPwo5UNse1/plnS7H06ms+MOi+Sa70s/1IYABAUIjltt0NXIPKPGiC4moo0dEFCwQ1bp2meXgtAVrzNKGFAiKtRIqnQwJJFymLY0kvR9Vlmv9jf+Z5gaHrAAAiaqaw8bhcdXkul5v/Es1z93dAQrHERPAXtFnmR8CsLybStyxUYpT2IsTD2K0vr/NZOf9wQeyPJN+hOKOgACQmqrjsbRPhxY6yubqqdPayX4buCG3oNUaJJFFdwTVC6r65dWlq19s3yTI8/8u6quAiwcHAFy0PaWcyzVVvLimL0OQuoBJiCmopmXHJuAAAAAAAP/6cARppgAAYhg2XtBhHcxDYbtqMQM0iFR1bmAkoRDpDm0MwwjaBwSlNJuOXwSKQZioq+I4Z0TK5wv6Y+G/oBI3Lzz8tdwgN+XfGFyU/A7FN0xmFSQOlXZ9a5n6bpwT/SbPH7nXVMqXFIAAABSckt3IB8hC0LjQM5xe4iXAvSV8EMKPIXHu5gcWtMdYljQF5AOXhEWiiUPl3tmEelCKdV7DaCZBlp1Q5vK73qJhJyS7LBF9FO1Y4pQA6gfJXRqSjHrl3zr10XERRHB5Lg29o8yhzS8Y7n4kuJ7udtCtx0Y6SQ8tPG3qeapgZhb8cMWNckH7AhqkADwYGSEAjHBfkNguMCZ0wJtrFyXWjAkerqwhhdzUChsUQ920TT76RizjRYerxlakGP28khMQU1FMy45NwAAAAAAAAAD/+nAE/RYAAAIBK11Q4R6EQugcHQgiu4iwq2hnjK7RFBvuHJGI1ggRQDbtu3x8sNpSqCKflJULY+y6NTO1eU0dX54z+aPDrchXLp8KqWtBAwUi+puR31WqGAgukbi/pHP+zUx3PNXAAUmk01JZb32grPOdDJYPnazI5UYobJi48+f8Lw63h01+oezIqXWangmsv3PLakY0s61RVuhxQlna1tTLLirYViuVBRclt3ks2V1TbqNk1tS9DfopT0e3DDTKjjaD5GsytygRtKN777HdmsqvfRnGQIqRWL1sJJyt8UNhZZENKUnOqWyn7FckiBgRSbbnuaPvBUzdkhibBNXt0spsM1HsALB7ButEdrJqy9mdrb9VDVJudjeucyqsUxB5Uq9gIFVFmoTTVOi6ZBv7NP7OlMQU1FAA//pyBO/NAAACEBlYGC9IYEMmu7ogQ3+IbKlzRIR2sRuVLejBlO4JKXcCMEKM5+xmelVC2lwW2uOLVc7EbryZi783Wdy12aByXad9y2b9US4qHjdybTBaxd5VDfbOOnD6pNC6DB1NXUrAAlSk3HIJ5IsMhnTp4k+4G6d7VZWeEaZ5z2V7hfZ7fj1ajKmm2/AvTlmjFSMjNOTxi9i3uJoFhoKh+x0som+0L/TJyAAuUk23BPoTWpndlTMPpj0P5as7+p2oh2C+dFnSNlR5POkJryzRMVhKt6d/HUfUqzKPQcapIiLAR0upee98vFD+2UQADEFJNOD+1Lx6HaC8FiIoB4pgoENc61lthIdJV6Do9UM9dkOTajpa7eu/x6hEDQsoI0E3ZJRFnlz51ymeBgULlD79IwXAiYgpqKD/+nAEawUADIIDI1s5IRxUPiMbRz0iOIjk4W50w4AxI5Crzp6wAgChNSXYfg4PsKJnyvH26kR0mRZFSB2bGVBzVKnUJs6Q0xM/5qgyAaAyVnVqNsLuxz8kLSdCQYbBw2XW1FjUYBMgECSclwtmyu0NhtNtm5CtIoM+Jm7VxdRcFYuCGrUZAS9AlyRM2qSF1ylyLBAKXk/leltrrBpI+nTpKucpvoBSTbg6gmPamWI0K7SyD12QonVnVau2xTXWs5G1PDXWURzqvtVDlf117HnJc+2+62VbZxRZNCsmWcKFBBhe5TKAgoiPzumVUASm5A8ohhyqsTYDAG+dWTpNB9AHqePI9efMX0aDOXS0+ztaH81bHfOV331V06O+K1RjRdZJeDwwaali+eSq3aqwg4e0Xe1WUqTEFNRQ//pyBMZyAAACJ2JeBiSgAjqGC9DGFAAJREl7PPGAAReWMXeMIAQ5hxCcPPxVsSCZNfLFlq4UJ+9Bcn+iH/tJdil/ydClKRDf2ISTDqCZSoX/k/3FUvYSL//8+97uokLGdE/////us4utPIGNyn6J+0WmhGZzvAg7pEAtM9yDRn+cyt9vVrf5OhZSIb+xCSZUGlOnfOeEkxD/l95ssDSmf/9a3iqigAAH/KoFUwOCOrWWuZtQnz5e9rZZvRcjLY+wUxtJZB88dCbOgaeQLTWyUEJkeROixWKtGAi9x4qp+LdEdaI0sWY2HbTE8ASvfu6AAglZ//LIklygjZnHztRyQ2KlDZFs7InQMbQ02f5WN77sym2VN29PIhWHHkTosVj6gRzxW98W6L7RGlizGImoaYngCV79yYgpqKD/+nAE8OYAAAIUNd3J4yigRENMfQjCKYiI2XeHmEMhAw0tAYGJoAACvuplZRdhwsgTWLHeBy4to6Fse9y2P7Ub/C/m7NIyObbMuta6E3/s6pe8XlpWRDX89UoUCh5wlrdovsJC7rexAlAKbVtrjaRJUMJpZi6388MuJaRXVkcWfZvS1Wf+PUWocGCJ5EK8+oMmUVoHnnvPz1qgK7V9bBQRCJBUJyXcmqNDVfVGtAABAjf+KCb4Yq5e5k0hmY4BTqzMO6syu7bTM9SI2s2juUe7z8yMHLL33+/RCl2L8lHbRQCeVrSnETvpLWZ3TkQqdwVpFQgTrLYLltidlF7uWVKQnXC1BFlLlZV9VcIfmazTaO4z7JaHitN956KArAOUssOPV0pxE7TpLWZ3IokQqdwVp70xBTUUAAAA//pyBIj+AAjCFkBaEy8oUDsmyzJkInQI3QFm7DxBgRqgLEmTCYADi/C6oHeXFmZTqRXNGPGag7oR6Sq6q16eNbXYt9r4U6y22XdSt03T/p0b/nZWeK1+n0T40YnWp7l0Flb63UdvuCusCRqCq59hOk0DKb5WtZ0taqQpw3Uzt6GFo2i0QGju9GX2vj/b75f7p//M3/L6Cf5HWr48lmEq8q7/2iogBE1JDA0X2wwIKcM6AeN4bi3iPrPwrSoGdUbe1JEyXV1faTM3nSz0FPRnt+n8+qyre2X0Ef/RrGPuC1bmJeYgr6bekM/MOA9bzKPDY2d3ZfJL1Bqxak2xRMmPpxtDVM28ZzhSirJMHKz7S4jynreZtE5L9L37+7fof0b//ou4J3uokno9Nya4ZttjHN0JiCmopmXHJuD/+nAEROcACIH6NlozDBB0QqZbJmRlZAiYd2ZnjExBE5BsaYMVkACAVVQ5YFCNk2LhOJh5aVzIwR959lm8fTP3Me/SujS5+/uWUzmRW1drr9jg0XT69H2QH7Yg6xlvYhPf9rOn+oBwH1+OWAIqXw5Yp9yiT6xi3HkKExsFY5q3MJtQwx2e03o02/uXdEER9bsxF0RXqnjP/4s2KxWrkz8l6VX+T+z3794AjjkgNoQlJOMKXKEPbbYW4cyocKdyqk8G+xSWqwyqNTfAX3cNJHgYWRcNYMEjWkCEVSoxVaWi3W1rEHf9VKezdwZf/1AQAGinIWeLgrVeOfm+ztffu7KhhQ8pTh897ZDceEXzojNaVm01yfR7NUc67AVWVr8lpeumyhiyXqoDzHkZPnbnIgy9XpTEFNRQAAAA//pyBAWsAACCGCxb0YMTGEGlewJlImQI5TOFoRhaMQqWLJz8CUAAAdURZHHUMEoP7i+45WWtB93UAQg0YvKr0z22H239H7Kx2JVlSZu2u9nSgJp0A2wItb+KVDPmeSQsvf/FNL3WsnXqA6/2qlnmVv9SQxa7BVfTtSQYihpN4slctiZ8LR6Oj+wsxNB+wpuR2NuMeXf/3Twi7s2VFbX71KPenxkGNJ3+z/9hSEQejbekblKxbotCQcr4UWLDiUaruR+oW+xKcnhPWltEeSn4/v5JUu2VlbafrwZXLKJt/5667fN61ounJGa+RfWuszrGVEUAhyO2n6fRXQbN1aK+20TQDLkLBQgO6qkbdQQ+6BXVcQ7L/ZupyWsbdGkZMleTzDWYoo/c6/lVj1mryPXbs/r7/o1JiCmooAD/+nAEGN8ACAIgLF1RARWcQQQL7SCik4hMo2JnhE4BE5pu6MGVlgAA5RMSJTEmbSyNOXsZAGV20sUkPzeMvqiBJeLHuQaxLIznHVVFiDK17+/tdHBtY69bbt6+rVltCbU3mF9R6bw05rOPAKIETTaraTgy0uXWq6jsNHKKTrUPMu6PZjAQG2QexlrfduwVhaQrn2r486haSTiOpZtQw/3/Xq6ILUB2vRZM1hoANyXZmnJriE22OJsbXS7uLff3V4FSC4M0M6WMCpxiruP9tFX1PR2X7/B0rcgdXh5K7fQIdn3CjwpWQYKbplOjVlUicDyWmmkp8HdOv3g+99FZFzFoiCMe16PucK2SAMrYtLiraKfui/an+vxrO1DddStQebpi5K5lXObo9sva75Lprc5QZWcTEFNRQAAA//pyBE9YAACCEDTd0MkSjEKGmwNlJWgIwNNxILCjsQEabBzMnRAEVdSjGknHrNcQVVs8WJGrBJQg3V96lV2ZqAW2S+vSDZWWWR2dJ66anH9e381HqEtKX9v+5homxZ5j+SQ3Cjq3e2oASO22Mw820K+Yt5Vfjz+R8lrSBSQgpLJam/74pPrMVazOEvjps/nVj7qavqn1x/jW1/vZ0iChZC1ku2z4y3X/o1DABB0V/qzG3li5nfH+A85riX4IOjmXR6uwTZ+Ivogn/uwi3IhUU8qoWtWuMBiXRKmTaqixYszw6ThjRcSbPZyp9mUA3/9esgAcVlDiUfhhANTFGedWLSkgnUnSbd1XRSpCeyFC93is90uFX8/xz2Ktstr3a/+j+v/z3JPlStCXh7b/vpvUj6UxBTUUzLjk3AD/+nAEjCQAAAH0NNjRODqAQmOrihnnV4j1a3+hlFExEplr3MwdSAAAgAEttwOtETa4HgsGGlxQVmRCV5Ug6lEoR3iYv0HX8pvkv9XVjrorXnPTZtJTep70VvZ2Wzy6F9rbPu3+kBAaEU0ilGGov7RhuPmxQm3qNCpamKuvXTkSg0D1qgU9Sl6KZq4+AnQC4s7fDDbfbIXvbrrRq2aW357+rUrI1sUS0lAohyJt2SS62J0ypFMSZPZoQUQvTRYU7cJ0dYJ7dUClZMHlZE0S1cMN1R7/54C7qab//fyF8Fbo96LtieX9+6JfulsoJ9VuoAgAblu1UAazJaHKdcjoCA0SpDApFZpoizSooGGOaClFoBz1sD/0I0zm8rt/sZ/0LVuu+3nLLRbFNtj85Vq05Xb9n1f1JiCmooAA//pyBMvHAACCF1dc0Cgo/EPliuMzB0QIxWtvQzyqMQgWbCjMFRAAgvkU2UnUqYY9IQPeAHVeQ5c2IUo+EGq7u9MQ8gijZ68tWr7o9Mx+iN6f/szMv0+n2/9Pp9t8//9tF0jhFIgxRpoaAI7JasC0MhLa0ezYzxuLP5gdsRSxvP8rGxUelmBQhtB+18HnsT81OprrRzHvvbR/Q1noIjpJMtedWNerVo+RyGzf/6BABqJLTSUApXuUb/ZUZKOthFIgyOiXCQJWpczQm/hv/qj9W6p8f6F2USHLnXo6GFkdSX0rz9P5/S/OtM/r//9fR2k3Gu/QQAIs135mHYGDLCRkbyG6zoSQqkfqlt3ckSDY3EgzHQiL+A6e/v7M7k1Znqnq/x9JRYcldZou8l8/t9WX09NH25/WmIKaigD/+nAERGEACIIVNVmZhxNoP8abSTxnd4iZbXFUYQAxFaLtpphwBipW7ty9dPVcX0vrZLL1w9N2jz33pqWq5gmRyrKKuaVCz2jrn7EY6OxFrt6/R/VvT9QSpGvLulKy2H9mG2Wbv6tO0NgAFANKNr7c9cdWgR5+sK/AfEWPdsOAQmj99xulAAerQID6yo0rkW6lL+vm+v0fx1v//LJt3f1OofKZR1vzmz1iySW0k7qU7MvrMubAW4zshZ+0ONnOOREoF8o3m+rJz1e4u1QZGZqP6t5fvUlRpdfv9v/t6fX0/t1+dqMwyX2COFW17gwMpPbfC8bR39h++L4rjkHixw9Ssqd4rFjM0eSOSAHseZNLef8oZui/J+pnoSbY596/erU21+d/9/RvKZcIiQxor2NdO6q0xBTUUAAA//pyBEtsAAACJEHfVgxABEQhG+rDCACItYeAWJEACPykb8cSIAIAFDpmpya3bXb7YDiw5gvU1kwuY5pklkCZ5aTVqyT9gVZwtrkldWMxWs5bO19JldqSTpQmv9GpSmk9a2lgwEneOvynttAAAmRVjdk1u01gFjWls7M86L4zTktEB46q+y1rAdeLISdOx73LmbkllKdigYLvJklrS08zL366e/tcXnP/+DgnB95woASUUUVXy0hvxtGTNpdvrQ2h2/In/y/t+n+djuQhTq038QYIR91CoyP/yE10ZJ1WdSf/fqcQrtciZVQs////n/qhGcbjEdJJK/U1Bvp62TNp9Lk2VaDbvkRP/X8jOy6P/Ox3IELXN/EGACPvLZH/5Ca6E3VdW/+/nEKHoQhMgX/+3qYaxOmIKaigAAD/+nAEDrcAAAIbB97PPEAAQqI73eeIAAh02YekBFcRBgqutPSIaAAC++pQILGHWjfGgQ5s1rWkwiKuhqt9VtBgd2i9ck0QCgo+xtQKxVFxG5ZI8dEolKFd/h5m12ylQisQ2owjTi52YF1AAACuWtpEkiCxhXo3woEs2c1ermtLYK3GJwq8gIVlEOHLTa2uSkBRj7NQTiqNly9xIXQtF/h5m12ylQisQ2qjTt0LAKSTldjbTScCIHyzcpfbyIdfbX7hda8bfrRwi0eMhcyPL2uSILdyO195yWj/bTOnEma4eZkeL/09T3+lCywtN3XjalgAEBmywoAgJJCkCBMNvuFbS9g6fymH4YWssG1sUMTgaPvarNVDA294rd1qchulx7BZrnmaeL/09T3+lC1C03djdaYgpqKAAAAA//pwBCOXAAACEyDeUeNY9EMmvD0lQoeInNVgLTzhgQwa7vWElCwAlvpWkiki/kmVVmcoCUkMQZVnP1DUvV/jHsYspmdN2OvQ2yxlzf/9w02Nh2eKsksjTz/LfkXZnLc8d4LflSL5YO3gptKaR1pIEojExqUpquyshsB/EisW0UmJtpUs3F5LMuHDzHyV+//NmfNlTdW7o/P9j/4r8i7MrlueO8Fu7EpF8sHY9rQrlEnAIVDG0oXkjE4YU2RHoloLw5dQwyYnGN4HkbNKbY/6J9vVboy22+vo6Oa/766you1OsNNsA1i9T2LoRd/pTo0dYABAUsl0sjlIRwIMytW/D7LjBpIeRT1FGpGjt4T9A98Hvsb7eradls9X9qGRy/+urDYuqqJXc98ipjYBca9Hvfur8kmIKaigAP/6cgQoxwAAgiNAXOpHKfhEyAu9YUULCIEBd+SMpWEJoCtBlJWYAAAC2S01kkoJeSrG7U63KqIVxaXmMKiqFOW8Kl8kHLXFKcvkah3U/Jde2z7VvoSvvl8LFv5T9/pEfsoCd6TP3v1EvX2AAACWua/WXYgPK0dq2ysGHZQ6slxyJx3hEfao1rY639hBvOfdCJ7VZNuZ/9+1sb/oz75m4ia34uAxrhxO+rcadUSt7vSAgQAKSpTX7W2BBJ0cSvLpiDzFiURkDXTjvHBqrcOvNQP+vNGPkVV1KaiNNtpRRpT579F/RQT+nR/4g+d05B0LHdnO9AR4spYk5KGxQyyaE4yxVR6iHJJh+A1C5Ys30o2kEd3DgaWkLHvxefTpGUfUm01uZF7XuR7r/+tR3//+Mf6ftv/6PqTEFNRQ//pwBPtlAAACDR1WiwZTIEHDqsBlKmYI1NeFoJRL8RWvsTRiie8HzDI8xa+/fH6c2Rtvaflt6IvFeeo155Y7WnHBCzKoODbxK2qPvPfymUdAI3mRJUIlvc6/Ud7Idcqn5NnsO/v4F0mS8bpLMHWpY01h3rMajaY7+AFIXANOFM7V8An1seiDnuaGV3wwZKGmTs8/yj6mwKb10RQjMslOp3O01f6ldin/80EEiZq5JZI5TAPO6qN55CGE5PHcoN6AK3gv7VYE2l90O77+WtqmCNpfpSfKwYDD6UzgnMv31k+57Aso2mhtoFJYxyhRcqTvCbaOtslksc3i414rN8ctSVjqkRQbaor2D7eE28Fvnf0/fsLZv+Vrn5d/berIYfqy0m/9//RqVdds1L/1635TMlNujxq2SYgpoP/6cgSOMAAOAhw11gsJOzBBhAu8DSdFiGRhViwlbEESGu30ZZ1cJ8gKoRTuPdZ6pVk3aPwArFNCBD39GJMjHCsIfYg+Z1XiK+6gHbygwnqfz/mbZ3r2mPtVv+r5vj3u2VNr1rm+lP/JftBAYFTV3VWDBm+s2fH8ZcTCNjePpK5V7s4PS6rguL3VH81/X45cLOiacZXcjFwFetmpci0qWI/PwkHIoJrvarhn6NpyM6GhNamhgTInlaPptUwcyzTuLkwVtcrFEYaFvHk+59wQTtl0EK/MB32PgxKMgd0HduRkQ8wk6N7/Nuo1/ZT7//SAAALIXFG5fxAPMZCUO0jcH5g4tG3VWa3Uv4HPbFjdG++s1+q+aW9e05/T/1b7yNtb7hjFHtMo06WqPAIXbrvcuIn9v0JiCmooAAAA//pwBGgrAAACDzJb6McsmEOGO/0Mo7eIhKVWTDRSgRcTL/QTFDYAIAHtNxy2/HWApwGQQjrJORR/SpHNgb2zC/hH8Dv3Bran8Z8nyv1/elS95vjkhK5Wh7n4/ZtQLBNiQPDPocZpf9YATAkakbcbllL5ohm2FNEItuiP+D9KgZQ1AD9B99H9Pp8tNfqfJXKdOfwhgq5NbLP21EZddw1RZ6U3UsTWl/HqCVDy4CNVM27VSlEY1KYch7r+IYwYSCl3X1pMKuXZqn3NYfCPnkhyltqxJGXYojzv4YbxZHJp6t5R4wjndqb6vs+xlv2Xf/6CnEDYy4pG5LY+q0Aod/PwOgcENPQd6P1EXrgBVv9/Cmrqz0QSn1FJgN5/btkXvFKhTGGChbXgsI1MhAg1DL8e+gm+RtT6UxBTQP/6cgSNCQAIAhQpVxnsUrBDaZwdJKJ5iGSlZUYg7JENl2zclpVCAJJltayxSuqhikreKeZWjKwD4xyws/ba0b800Kw7sgYJ4g26DXzTPt0Ifn/b5fTszmcP3+8MKEr5bEkqQ2/+p+z+lpxg2VOSOSXVVZEPqvj/XSfTSN9QELNo/QIaYP7C/X6Dev1+3x66P6PpRepGJrpf9Plb39acjXtYcRD+ke7EaKY1adwaBEttyIfvueHBnG1yoT9BUt7FmOahIW4ygvpiosjtDi9MXfN9F9X7sX201KDSsGhsjDx7Oss9rrteJc3kl0afv+zuAICk3HIU0GN8WqSk2NwoCEpw1WogbTMGvwod4CvzgNXKX5d2V9HEnXv6CjLzXxjyxS4aNiyUkch87toeWuZdv/8SfamIKaigAAAA//pwBPfUAACCDFre6ScrTEBHu4os4pWI9SVzoxxRMRMjbCj0FagkEJKNKNptyp079KO73QkFJZzuqKJHxnx4OnWARq4df39H9X9P/i/WttB/oZedl69/5/f7v6PrK/pXl++tfRW8brAAHgklJJzQbWpdTxWKjnJMdxvSmNS82rhycTP4P7/f19ie6ff5dcfyJ4Nn0P/1j4k04noCZSBCEWvepeLury+kAAEmImJpJOvGbh+LvvEBT9x8Rz0En5f1DkRh8IDLugm9S3wjpUrPzP/1G6U+no1qs3r/9qUt/1v3CPj9WU22NdDdgQcJXLGhAIFVN+8Mgm63pmixYlXSSoPojroFbUXeXzwGQ+mfGiaL7FTFW4Q+X5qZW6nFu526l+nyfb1+v/uSnL7erj8jtfZulcqmIKaigP/6cgQxQAAAwhYsX+kJLYxDY2saJedWiHVra0SUTVEGKOzIs4omSBJK0r8ajkyD3vmHb7yfxEEHKRAt96Cn+WCMEDkYMMaaVg7eLehft//1EPjcrow1k/vYx6SrqzzxT69ejP0kX2WYcAACQIhFp1YcaSkVGZtSbC8EqyOx0Ie31uCqvV4pFi3sWn4LmZFl26ku7dUer1a8royTLd2/f98U0a/opJRWOYyAj00AAOhgTcsyjan6RZdv4h4KbQAwGmMoE+O8LDJCwMOO+328EL+3gvt6h/m+/lb1+T6bsv1/L0CIlZ//v6f9Ua3BDaMPPUUC1R2jhrUTFdXstwfED5PSc6FDEzUO3YkDE1E5tcHvyPxfo28J9vn+n3/8H8n//r/8I/UDY1iD+pnvCY87K/RkkxBTUUzLjk3A//pwBKf5AAACHS9Y1TDgAEOFKuOsKAAIiSFyeGEAAROkLg8WIAAAAMAwLdv2uid5MQEOlZHrAiLHUWDs9kI+eCBmeKy0wwcEk+1TvT9/tqeXM9eg4NvU3oOPhjZKN9b/RiHJ/dWe9Xb/SABHLbKX+icDZV7Mjll2q5UbFWw5eyhw1ytzZFUnCAkueFGOWMMHnuF8nR/l/TqeTt0foQE2F85nK2VN9f0bMns3b/UUQCGhU4M0Z3xb24o+SwliTgbvq2HyPAma81qs9r57ZP//7/+9zfR1f/nnciq/vKYvnf9KCTQiwr+t4fDHtFCH2AFLxOAAAERQIKiVIoLTRcnqpqiVcMmguq/Ijh8Q8ClvM7VZ7X/ZP////3379f/POciq/9C//pQSZwiwZ9Vbw+GPaKEPkSqXidMQQP/6cgQq6gAAAiMjYc4UwABDxTw5wpgACJyReBzygAENhy+bniAAAQAoAg88wAIAJzmWhAJSdyNOk47wYr42Ntw6fZ3fPIbUKgQiTdm3P+hyA+GlI0SvCdwWND0FwIxl37l0Vf7g+n0///3AAAQAQeeYAEAe4k9CASIXipZ2/5gxXxprbx0+z2+PIbYqBCJN2bcfuhyA+GlIt53zn8e2WZa4PqVR+i3s/oLv+///9FdHqSB9EiyUbMXrnPtTKxjiRFCgsUEykUfVDGEd3ctlmEUf+sy0s4sDJuPQLCMqxEUQtO8hZHte+705KhA97viTuPJ9yBQIKs3mLNTRqZu+gb3NSfGMElw6VBCQ+cPuLHXG3GCx1+dhVSDZ4DXlRYuVYhKkL70WLW95sk79ZLIF3u+La3DpTuKpiCmg//pwBBQVAA+iEB7dgG8YEEJA+8UF6QAICDt0BIxDwReH7oDEDJhwuQfsWV3GYhFC/qxRGikauc18m0wLbjQ3WTfT+DHBIPB4UIAyfWzE65NslIMAjJhJoQyIzSpbrHp6epirSimL/5IBAGmjNErQnalSeKWo84sEgyYsAy0llFiw4KFwFacocDkHpACn1sy60JpJSDCl6izRC5jrEqGuex6en2bSiq2b9uSuDQ3gQOIsF84Z2/DJcELnINiJoGIlBwEL73BEYbGBU28VLK3pkxQcSYPRJqeLlRRx4ehCnpS6eVSGjVKrr7v+vGSuMLKnqiaPODHHt/3JZgQMScWHRQHjaQADAELk0zIRGJUDaQKcLK3pKk1DmsHopS9pUROePQhRpKXEnqw0ilV19zPQ/WmIKaimZccm4P/6cgTvVAAIIiEaXCjFGYBCpWuFMCN2CEitbkMIbUETjS2UYQ2YAJCbSKOAgY3QXhHD3IQj3zpWwtUnlpidI6BUVxLLSgctY9TjKlrEMPgyGnNah6GAVT1pS3ZkO4A+zza0TVph6u61bgMAgE7QrRbQ4bxTaNZ9kX1d6sKOJTwPIamh2WWrlc4vO97ZDh871FLM4JEixY+gPxQC3rSnsqKu0gGnZQ7onrdVd1GkAEmg6EjhZGnfD8m8i9XL2G0cJ0cNo7AVqkpL2Z/qzNMpG5mv5c8ESLH3FqwqhFl2SEpkUS+09grar5l3bOr70tRpIIePMPQSVbsFw6NSAPU7eMvDBQuGCl9g1UjCgEKhmsFgowsDQxbkDWFgkk/TW9GRRFsqZFC22m2Lln+ZcpimxZbukkjSmIKaigAA//pwBH5CAAyCHR/ZkeYTQD7km1kkwigI7IdcB7BHwQuL7OTCjaiBBqkjO1i47W1izJdWYTFPXzfWkK31KsquKDPRy3u5XN2Shn4OTAzHP1kivF4hrPFYGLB3QuMWtt65IZ2zmWN2+l3/UAAWiLNfjx4Ssh8J2HkJ9hu4WiO6gqcRMaCG9b6By309/3y5I65EkuLxPHpHsNSxY8FH1VVtp+321Fn/uXT+3K2To/9D8NtRNOloZqReWdz65kMBZ+914nDCKZlKULIiAKThxQFvUM0uztc2DLBAgCcQgk+dkpAwcdQjOF0s/o366Oizrp/cGCFf/sJ0M6HKprsfKzIPu2AinZ1BL4wVM7ocM7rLRQz6sxoS8RH0rQYD7w7LH0i9hJiKHARg13JJQSvZOZSi36afrTEFNRQAAP/6cgRudwAAgfAa1wHpNQBB4wrgPYZmCSBhc6GY6yEci+ukwxaAg6OgnGQZR7Mzk6SjJDLazeU19b3h8Y9v4A9mXCW2KQ5JmqtzXWThpzAyl5GoiSASjlx2K+gbsK1Hcs7//+hvmK0nGzAL8zbzYv7CEJQdPAn2Qd8ObMJAH/LfXG130qmZgwvB5gy248KGlBoRrKTZI0oOqJrWdGUzt6Zz/b0s/9IIAAdzl0kjmyQBzGj73Ss7hGyfh4E5X0VsXhUWI04epdwlJhoGAofvUZe0BiMi7e4mKzasuwYSfzEksw1X+97F3W1WUlQjYjVWEACI0lHAexW8BYVJmtUh6glgM+8BD19X4o2edQhl/1gQNVYpGnuBQIWLWLacDrYQeihDHgUxdKNP2k5e+jCN6es51d9yeqhMQU1F//pwBPh5AAyCExrXkexRYEJDWuU9iFIIbIFgZizrAQ+L7CSXoQgASqo0Hka+hdbUP7iUGmgnacS5mfync0C2c2E9jNSdc5RadKISHygmbSs6thtsIHYo+riI5THTVFmz1BN+qScr/6lgEB55y1Ls6Q9OMkrk5izafjKuBfNmunUbC4J2/AfhqImxeY6wbLdxRp5zXKJucg8lq5+KCqFIicRCtu7V7v3av+lIIRbUjCVIeZEfMn3EUF8EGuGTcajd0SwZvRYQnzVYOvNUg2yM/W7ZRxBaDyMpN1ovE6r0ooLIYR/F9lGRjFUL1WX/FgwEr/CiYIALYhVQduxV2ORLVQHWLDIGB4v1Qbi0kDV7nBprxRtCIEJPm0lmiqjilisclA54+cJsNLNBfv+tMpd/dbfWmIKaigAAAP/6cgTKvQAJghYYWUmHRDg+QvrRMwhECHR1WAewbUETDSzoZJUMAACBFmrz1N/s/qpg/CTBq/pV3puJ8UB9coMrxmqSAqqTpuUfWQiqDYZgwytq5SXFzS2qDTL5tW91lSTHU9xvJf9vqDwvG4DQDK0Mvpvy8qpGio6MY4Oiu6gYENfADAJVdUKj19wTp/Q15UHE3MLuQoTlFNWp5UkiVwVfa6YXr6vrb0clkq8QxVqVnTp6Ap20T9Ylsy7K8UhZ08wIz8WTZajy+l8+7cmFVKqdKkHAs24E2Dp6prxh97toVFxmhnYeqGV6f2huSUmVNxwWExFnVGgPYDBy4GSWFHpcAhi3QlnhMfatH4iYWnBbY8ee21H3xiyTiS79vfUMr1dqIvMLSKuIHWMPQlkZAwmIKaimZccm4AAA//pwBAwVAAgCE0BZaYkpMEKqy8oUItvIhMVg5hyuoRMhq9zziagAAACIACOS/wxnzzgmOT3koIUSt1DFZLh2rQsf0M/Gl85fRu6s5aqS93S9vnTjLf7PTp6qj/6fHZXQrj0CwoxN++KMUvykmkk6pwZKEM7QgzBlRXS6eN0x/hYxuJjlrMnl7HuUfX2uX/hMy5amutZr68P18y9a7ZxGt3ZgtNJfhVf2S3urcACETLDUmDCQTQIWXiiAtoVZrB6uwrHHNxoG/GGbGgTwmTtP4jXm1r8376mdF7XxKq6TTutztb3q+i9D6Vp2tUh7FfSAggJOS1rimIgbRz8bHOtRF9oeNV3Gh1Z4YrcYIUzK46CLLg28GX2Pu7/k3f7K2idvyV+ZYNn/UtX8qax3qW1NhDRp1RyYgpqKAP/6cARsfwAIAhdC18nnE2hESivNBKJPiKUDWEwZTIETmOtM9onoAACARErqyPDLhg4VXDiXVgslUnWcHrqVBA26BYkp9RzrB6Ytguf29JslKdU8H9vjo/b7d/q1/8r+GvwiZh9urbvr1AAoBxFJxNKWkOZExxCFtINU6LHeMHb19AXwdtiilvFDlZYo3Wj6/+hvpz29drDf+30+T0b1Oj6GRmn+O6TUwOF9qPsOgDX+EHN+yKoWUW9bsUkMip82sWokGfO5AJjsiBY8Yl1PlQ66YxFRuxP5X5utTKrN+c7Np6r9n+vs//O9S2XDM3l9H/3awC004NJoX5fllNJdQKqegE3kCZS+MQlbnCVUppLhlfkU+7zg535NPe5T1YpOZkSiiEd3X6PwRHr+sam1RLbLHs5WckcTpgD/+nIER7YAAAIUPVm55xNkQyhsHQxFhYida32gnEvxCZetNIOKIgCAmNtyUiwHthlRM61GLpI3aqfbQv54x4o9Q71B7552IYGYjTgBHXEoeh16qX0+z9ae2qRHrlwr+wS4ArO4c+2rLPSCZTzSr0jl0WXl74To/vaVQX4Mbwj1qEh6HaK+pvQEYiDAoQV3Ur9f/jPz9F+329fiP/nDtCMF12PQ+Hm1PqP5vchCIACdRUcjblJoUa8bD7YSDdzsv6lvEBa+ESTFUFzdTdaiH1P8K5mlBNWqffzP5T+ZrUP8vyfEdkP0VvK/d//V/V/T4L6QAAAIAEW23JFho7FhVivB+sT+KOURSkvHQx4ma80QGUaKm6G7UEGK1m2ld+EbobzPtQfJ5B/u3boo/dW+z2k/9m3emIKaigAAAP/6cARHbwAAAhJD2lU8oARDw7v9oZwBiLF5flgSgAEUpC9HBlAAAADQottN32vF5MYce/y0R4u/h+JIoyHE5QzwkGXUTFhyagLfm2mE1WolfsburdS+7ff7+n1+novy/H/Z//U6kx6qUgki/Co44nLGdeqb+NhDPAwfCIOC00h8t48WupppZOBH3O8orVs05LbCZxk590V1a8VtI7Y/YpBUTdgcHHVLm3OIZSkSggiigjIpMmT8i9f+n+iV/yLru22NcwnLZ/ITxVwHETsLXV0Vz/7GciMdjZbrMb8532IVjiUhFb7fk//lVXmRXV4h1tjwkto/vnOHGwsCT3W+ule2iV/yLZXv+NcwnLI7chGbFXCYidha6uiud/7O7OxyG2urGf85+zLOJQQbornPwm0WWKvZrJx6Ygj/+nIEM9oAAAInEl3vDKAAPoHbvOEUAAjM2XHChHcBExsuNFCK2IA0Cw3EQAAAuUgIAZvfD83+D+ZrUMCsJHF3tDqHJI1AVAdMEn9RkTLOnSRelymrQLHBVjolv30JQpKksexeSJPosq3HkFIEAaMgABWMIMESbPM2czmjQZ3xh/ddanfjnyLjJoaZ8g88LrXF74qpo0pais7+57mPYOTt1utDQtczLLOyoAAEAjBt4AgyMdTCjnxzinHMp2Gim0jeEx3iJ1B5+vpCK8TnNdZzAQmnPOcZr+BUkOCx6Suij+hSSjhp0qZf4qvjYuS1qliAgAOlYACQCpBVYwZXFLDshVeN+MH+A4ImERNqtz9fSEV4nOa61gyIZ2PLqz3ReBWjhzJK6KfUko4adKuf4qvjYuS1qqTEFNRQAP/6cAS/GgAAAgpAYWjpFgxCxstsGOKGCK0BYkYcTYEGmquA84mwaLhU0TkSIJVnSo0mZ1NCaSqqR9PhC9aCSa2UEtS2Dfvf+Wq66s3l+2rfVP8T/+8vuCe/xEouReIDvTWCvPDjfbqAJQD6HTK34TOzUMZ+H+htw9qP5V/KP4QmdBJ9CTUO6/2y1XXVm8tdRtW+VH/iW+lGr8RJkXiA701grw6BDZDaloyMAZasWtFV4a3nczQR0h9Uk3Khvwifzi/QNvxN/+2kyaHymUht3H6RNH0683gif/TrsQHava5AuKIL8USp7paqR4ECbnrATYnUOQ12Z7XNG3YUOQXapRR7xCXo0Si/UkvKAWfihm3R/9DGe8+V1Y2821BjIajdebqCd2uZoXr511kvb7/V8ndpTEFNRTMuOTf/+nIE08oAAAIYQNcJ5xNgQogMPQRFEYjU12uhMKFhGqbuNDQIXBfkczxNKCT01lTF+xbp0I3PFmkKgW8i/UgX7A+9xh/+zazE0Zq/3poi6mY9TKmXwwmj+nl6cFtZq0Il/ctPW7fhuipp1hT6RyyNSEacKB1XeIvipaQFH1wiP6s3g/uGffyb7kzDSoiWrTWu1VVvRMt6jNH9f/xn8oyEnktZRTwtw1bzxvjAAQAbSiYWknFXU4KI4u6hZ5rqCr1iluFP44f0F/Gt/0XmVDHVDXq/7WQyEdFK6LREb7IDQgNL2ubmkU3imNpDerleEHVv9AAjAnaIVkcj2o2QL2nhDUeCFI+E+j+F9RXqf0f2tqYPYqMRVe57s26gwVCMZbWZszFoP7a+lUJuZqU19Hsie+Qfa2K00O+lMP/6cATCEQAAAiMr3OjFEvg9wvrRPwdCCODXbaYcS+EJmvB0U4sGYAYN0Tllsl0p6vgyPxnDxuMe7RgPTN8JP0H+Fh/qU79/u+7zVn1mZdlESksXeq8mtw1dZLT9NzxZ8HhXZmWPh3frTMVlO2n2RRe4Z/LFLWpw53xFTlhwqvBQnMxHDHg/L6CENeourRn8DTQDFR7vEtQeyfJuc8tuonfqIne8j2XOyKQJCWhpjbblZlEWOB85yv+axx6F2e5wapq+4+C9+hniEC3dH8v27Sdk9zLoxOlPfdqVABp2t6CL6G7dd1lCdmVY1Yfam/bNNmsF9uORttxTkEKgrLtI+PacqD/C2rUBQ0+oEblQnfOT6v3l6NbRfNtlo/6XurJUROxuepR72vFA4tWhv3up+shc1MQU1FAAAAD/+nIEmf8AAAIeF1npiymQQ2WLfRwi0wiss3GknEvhAg6ttIEVbAAAAIwFFLbbrjpbuCI/27OBK7VHtoFi3qP8BG4wD9gi1gEfUYrpRKimC6GgRZNdJkiMGnXOIo55t9e0mVl9w6r8oR+sAIAW2JSSSTKxZY6SpYNQs8q7NxKPXCEX+EHoIvjoo7nfJ8j5ACDrue9wzNtvNsqJlppElUWGfqWqhF3ytKgyK26B1YAKCeha2ts3+PU4OPlKpmZU+o0dsqQ9S/QeFicbfDFzUf5m+PyJbRuivVWKNQh5VZFNEOxqWeR2ecFXNEJFHp6HrW6slpAAIByBTjjm+Y5Wj7w4QwTYh5EiPQfwIboA3xH7+Mw0+DSfTKoehOo1eessenr+WEs7KjRcDShZDFlazJ9TWe6STEFNRQAAAP/6cARxmwAAAhkX32imUqxD47ttGEdhCJSlZaeg6oEMlKuol50QQCQbzCkbabiFrMCGtMxlfiUHPyS/fyMcRpU0tSoEQZQJ9ObpDjVC+dUySVUteW6CkutyCNbYHOhINh7PI0XTZ2R19oAQAPZSUskuaUkdAnbPQC4ErDkGRigtpuM+FRhON26ipvfWhOkTUsDTz7lNigvVg+utqxdFX07clVuenvMSmk36g1RsAAABpAgldv8l3FdNpA3CePpxTqt6A4f0yhP4+LvC4wjSst1Hf/YefqXaiOyKxqv5TAHyedb5ux2r16D1z3V7L5bkah9QAAQAAJJ2nCokCcCIdpbrJZvXaB3gvheViAS5lxCNvEIx1GvqBv1+d7v5jP77RxUlrVTtdbv/9bI9bxoxeZqpfS7/uTEFNRT/+nIENG8AAKIhMlxoxxQsQ2L6/THnRgiox2WmHFEA/5GrqMepCAQACcgCQkUp9sjyO/fr2J/4OEpBSKjlsr8Qt1D+oA//t/zyl0I/gdqodHbfRFHdacszt7YQdU+Vlhmpeun0NSlmdVvIgAAAQAABKXaBUWSxwriebs/Rscjaz8G/SzzBQcpjoIeVb3fwePq0bdGyg/It30mqyNloB06Pk3MYiQYyhJpYafX3UKAAAAxACl2/+o1ROjE5dWO7AmUOPnU3cntI+Ifgq/jT4P/ZvBN0CvnKvo/kJWSaQjlfNDnql2YilXaM25Y+YdW1vFNOnFQwjttyMUV7YpPl2XZhHqF1j4YGy8oLPkYa1qI79BUblQp/t5jef8qZmdA9BYw9Mi3Z6shretODzZq1qvI06x1SYgpqKAAAAP/6cAS59QAIAhMgWGmPOgBBo7tNGWU4iIR3XGY85METKG1wkxWOAAAAoACcmu0OngtRNYleoyjLcRmeD0vIHlH8Qt4kjK6CP5UQeUM851uhGoS2JdI3nEw7WbKXLUyTH+f2/du8pt91pAAAEIQTbkkLTqGEJResLZTv1T0lNIKeNHVeCBq8P+IjvRvDwZNGEsDmfqfVpfD+ISp9GDTS7az1YvRrdR8hV//oACal2ZPCyG6ocGFhtMlgtFz1zQ7SJm8QlugRDPUTPyoZbub46ZcH4TM5+k7J6MT5Jz+Y3UIhZNNp/+IGuKJrdUOf2YuAEQDCQYVu8dHnCRja4Oc633BpgpJAXwtvEn6hx+op5m0hEu1ft9/duo/7eq+rUdF9WXk+z/+/qbqtD6eIHZQ28q6pX9CYgpqKAAD/+nIE954AAAIfWt3oKSlMQ2or3RxFqYfko32jHK5xFatvNIOKVgAmFY0iWm3LTUSFO49fFPhYQ7sJBnkbw58V8avr8SL7+cnp9idTeNt02lPbQxeNZ/8/1T0VNWb/nu+L/OVOZNlxmV8eS2gFrGVXE5bK8bjF8fo+RJqcaXGr6ACFqYz+I8H9fOLFGMuOXOMnv4gnYXJoE29Pv6P6/X1+v/qjee/+Ltgdij1cgpENp2VxqNxytPvliT82QTrzSktY+Eqcw7oYcmgI/G/T2Dj9l9U9fQdpzm56wKIBMJJQr7dm3dU+h8WbTs2J/USYwXo4TG05en8ShKx85GVfAnTVQy0RhEMUcoJIyfoLfVvTygDcr2ml9fQv38R9V6m+3p/6/Sf/jW5mpZ7VCfdOC7F3bqkxBTUUzLjk3P/6cARZ4QAAAhY21x084ABCBzrnp5wACMQjcviRABEWjm1PGCAAACR1ubIapRFB0kvOt5OrjDhom/7m2eKzqtCoc3G/oMeOkvH/Rfc/0TzPQ/7+/3PeyuzK5V0uJvJk57PbqtWV06GWrAIAGnZs2Nrx3AWEPzPaAFDuvM+9UbPEJO9RCOvwXPxB6mM/H26FaZ5f0X09D26H+c3utqvt/Kt9ue+705VFOQOWrABwSMbbcitdtkQYc4iepBLJSq6daRDrSr2d9w+BEEztQNdeARxoehLGD5ho9y7bq39NpG0cNvAHMZ5zWblpodRNhgHEDiBKzEc/f+/77TiFRNiThodKw/UQ/EjXZwUPCYuwm0Wp4K0Bj+S1xKBNI4vr6lLss4uhGLXuW/0II2vcu5UWMTjHN9bk/L6ExBD/+nIEyhgAAAInMuEWJEAARMZcM8KIAAiYK4W8sYAg+4yyt4YgBgNNPPPPuCvB34KGNl+evYnOQyeZ/9f/9f8iuxDaLo7vYjHEIIdAybdqRaGIEKjTKRXdKYOE6WiYsd/Acu95ysaKsceX1sCMQiQSCQbAOwLYODnNgquU8hk8z/6//Jr/iFOxDLRdPYIxxCCHmTb+LQxAhUaZSId0pg4H6SQmLHfwHLj3nKxqxUaeWACEnrbYkiS4HgGal+xty5/HUSAJ4ydU6tr0QLGjDzvKuOkXpr2MOlZbWmhSHjmAQjKhtrqVyihYWbIIZaxF3JXv1sANICZblt0jSJK4J65IXY/rIiDby6WM5xQVdW3K1ogRHX0thoqp8dbULFbva+5hmKXPiUf+cFRUVqc6tVyOt1PFkxBTUUAAAP/6cAT7TgAAAfw2ZuhGEow9Rrw/JCIfCMDZmaEsWDEOmKyBlhUgCbd1n91rbTk4zk0PhQqqu2ahSlZg7F6U7oqPoYs5HqnsZw7K5dq//Qvv81HmRYu0OsOr9f/CiDSE7YFeNwT+oAQCNDeJ31bjeoNu0TkHMR6kTmSCpdqWYnRPdARdv+afcu1f/oX3+ajzJi1llFbb8X+UyzO/6GxIfezszKhHVHrfbtZI6ggciGS+Zs4RML75Weuqdm7n7hl23r1I9SGBlbosrL+qPo370ullEKaWdG2kcQvdCUqIn9R76/WsrpChWp5scQPhSD44taf9sDF6VUdmgr21szVf7WN7AQe89yjGyt1eMNdif9WqVvWVvrKj2GM9tBZWsI/anEP1iLxQ92wCJU9fsWmIKaimZccm4AAAAAD/+nIENpQAAAIdQFy9ROAIRMgbd6wIAAgVlXYZgoABD7KuQzBQAAGJyxJuBboEZHAcMk1llVR5FPZqiN06N3NO8TexzlQk2M206psc160fY1Oc//vndyrW//s6WJLStVbtqC1+i31fFfAoDAlpZbi8wt11KkWt5+93O0mNXv97gG4nmtXQ7Yb10EWluwv1s7rb6PbnagtdUvpzeo3/7fxVvlTVaXHi3o+y7EzrYiJhwZ4ePkxKUymkpN1qfurf5eJsNS7POtEJ+vX+nfp//9//+x7f//6EIJo5EJ//8/u7OQhpzCf////7uQ4azTyFFgjL7DV6FK6G4xqgn5Xyk/uFXKKCcaJj2ceZEUn/8/m8v//b3//7Lb///QhBNHIhP//n93ZyENOYT/////uQ4aw6eQosmIKaigAAAP/6cARTVAAIAhsrXtcoQABC5Ww94wgBCHjZcUSErsEUDK1cwZVIMALuK2MgAJonnqefQl2M5/DcjtRrWzv376Ud9CXmomqX7dWMhNxhKAHUbr2P1pO/l3D8VbU99j1kXKvYskVP1Nw8kiHA3p7/t9USRKeFp33jMzSt+bUM9hnamxysno/TQXelG76F9+3VjIR7jAqMdRmL2PxVJ38u5+Ktqe+x60uVey1epuSMNqWOFFQAh1pvbSR+emY/EDOfYRytUYhj9X7PcHpTu9VSrfsaytmvK379v6sYWBVzAEG/7AW8krgq6seMiLPe49qDqyABGRtElwCDonlsyuhjazK82OA0wzYNEcb/Poj6JwZHiVh8N5Y0ieHhpgxnfUgGhoayfc7BsFuHZbgrrfiLPI1nT2oOlUxBTUX/+nAEWUkAAAIZNleR6CtQQ4KbIz2HDAh0iYFUVAAxEpst3pIgBAJqoSBdmIWZfy2Rnwb0FNqwm6QnoMp2MuTwahhtLEvNDGYN8ipn5T1ACdV0RNM97fTbrRJfZtU704t6Y1H/aind3/WCG3ZcUC/cHSSXnLBDc2WeXqabbg7ewwOauVvWPl8RmK73KfIOUo0hV3F03pWGQyiWQVE+p1iKOqzuMJ9s92r6g3cVUI0/aMrbbj2PIymUhzYmAXSv2au7n/sZf1X40iiALtKWpubnZKTMt87W3URpPZsRPnXSZt4mSty0b8zgjU9376iOR1LCCUrJLcTjTxslPKJZcJwk62MqAdzNV13wQ9XG0V8W+t1v1Lo53PW1Fbrszk6cqPv0GuelV8vQLOY9sTV6KveVcuRyOlKYgpqK//pyBOD+AAACD2LdlhjgBEGsO6LEFAAI8VuLuAOAER+rcKsCcAAAEEIIKQlVnGSbFtmKxKVdM1qHT13/+n///8z///2MMb//+rmDQgef///8mPuTQaBOhAH4P/////xLG5QgDsH5PE4AAQYYZgLSRdQwdJ8IYpe2SpRNhExaEst1fR+3T291//////yE///7oIEP///+c7nQUB0IHw/////+Li6CgHD74nAAAAEAAAAYDAYEAgEANb////RjP/9v/92Knmqv/+OHg8EY4wWFRE///JmiQNjgIMJiDAM//9fjwTA+CQHwD0PCUXsEQlf/6AAEAOCGBgKBwOBwGrglLur/bf/3/mf/1e3/+7Keaq//5h4PBscxAqIn7//JmiQPHBAxQxgcf/+vx4NCMJA2B+Y4tJxULv3f0Jj/+nAEJSgAAAIfGdvvGOAAQcM7WeSUAAicZVpHsO7BAhPt5GKJzgAQAQYVJGQAx8mDGS7vDrt5BPmUxwlpccTZ9zPawOHLBWNBV3ERolSiIqtGV3nvDv6QVBp9bqeDT4bDUqCpU70ITjxEAAFIv6BeJlgITjHbUTPl4xJPQVLPEB63VyOiCvZujVDPcvvLIR4iaWeslleHPI/pEoNPrdTxE+GyUqCpU70U4VEQF//Fis5IiaBqqO4VB4sJ0ON6Eh+PgP5CR2IVMhil4VGk6Yh9Thq2mUA2nDq1aGH6HmiCWgRLYljM8zr1P6hfT1///1EgBBGE5W3JpAQQm/7T4N1gVWfwpIUcO4E2M9Dl0mxPbn+mRiGQ4ekwipHr0lcgrdXkbcv61PJiot8Vd2P49IqZlExBTUUzLjk3//pyBCE2AAACHiTZPTDgAEPF6xemHAAIxCF2+GEAERMYr6sGIAKAQA9e3+QUBROMnJUWH9o9yfEbkMDJ5R2JFqMp4jjEqgvzS/54TdtUTHVR1Q+bQlLnie3W5diUlV74q+R8Te3a9j//qACAY7thEUS4KDUfk69V4/MjFiNoXPzRo6EDRGFjjzlXCqqo++52k1R8yqH62+9NLHW3/arvqVLDLEqva6u2p6+zO/6gAAgC25JbLlQ8C0oYDeHNinR1ZoUIB5osLjhK8ocL7qcI6l1O3IFSTSy3McFiobPqSWS8miEQ/eSSjFpoI6b9f/+cA5N8gAALyt0UpJbbbrBoZlNdCPBaG7ydAbsdZMxnUxZmw4tNvP5P0r0ZL7JodSK+ZaMjQ6XZZOtynGxttxH2ZtJ//6e6w2l9CYD/+nAEuYoAAAIdE9/vFEAARAMrqeGIAAg9I32hhFrBBqQuqCQKyiSSJc87rYiQug9kQ9qM4kB2eAvsruS1dDD4xbT4tO4DUPYLsRCREXCQpFmmfdWxEowW19oftXFTdGXBaKXB5RlF6fywCCr3fAG/H0yiuOhxXz9Qd2ZXPmDCsjZdUG+0i1bVuQyJRRixVH8WuhBbKm1rA712iQm9LrAdPCzEF3EHmTI4/ah9wMpihSJ23/RtAGRUdJT3VUKhP5+yH3h05Aw/P/XwQzHDMpC+GviOJiEIg5P/NeTymv5CMLdW8z5nMarZQvb+R2fyuWQAEIRtEkAIJZB2oNHKiXHTJ0j1ZpOGMWBZ9mvwwa3f5nR9ys330cxjej//6PpVv6GKVurebmcxq8oX/qfV6NZ3CiYgpqKAAAAA//pyBKdsAACCECTd0GcT3EMjO0okJWII4W13VDKAMQeTrA6YoABAbsQlE0itOim7KBCnD8Cnq2qelXohejvz3wTdb2Ko1wT6J8fZqNPOizpLUBXSREk3OUFRFBVSMkj+R1HfAqcRAWwAAMwHX/9UlJ8XQUUHU0Dz0skOhrEQo1HGR7EQw7++FD7GIRFIpp3ajcNq0ah5mSInd5ySKiIkCtuSQP+sidqO/TqKoIdqSom5KEeg2cqNkVE2ivK+h26MUeRF7+hYmABCWxiczURPv7e3Ivnbr6Prf39mZXAMl2GEaomnR1ylfv5ft1q/6v3GfbWALbd+vLKuEjE+IUAzMBagIcMWuwUKvPFYmJNCjBNUuUGJbRu7UMra5E5rTms/yAmuyFqHV7a8jv903sr/lt1O3+xMQU1FAAD/+nAEwHAAAAISDN9WDGAEQ4Obc8SIAAjUhX7cYQABFBCwp4YgBAAKppVClYrTqtkA8Qbkd6gKtq3Y02IBCQUBsoHI+mvDsCoC7EhTJmrdCGqNjjCSePsqQDiJ8YV9DKpTS7//wA0LABgeD8bABALKUKroyg82UG0L7ucujgkcgllR0OwQ1YruyXDm5u4xgXcHT1hN8kOHoKRMkLGCadbmaH//5Ss2c//8AXgCAd1NXmiwdMMOP81JI3+Nodt2lMubQ6OVJbs/eXWvu48+SASaxg+DQTcSi5F4GrtWQYxF5A8v4sbS9texFytZYaQtUHoxMvAAJf+qMR0OOMKBxYrL6HQ/csplzVd9st2Mk7ymrX3cefQZTWMHwaCbiUJkXgatjViFjH3zy/ixsi8lXsRcrWWcjUSqTWmA//pyBMyNAAiiGDXfSeET8EEmu4BhIhYIaNl7p5hDQRKbLZWEiGgADczuv+PBECWqTQdR9b9Mb9nMM+ynnym+qN5PeYteimqO5TXkqd3Jp5N2fiBS4m4VRlgyvyB5ijLg21vqbmCO/QyYi90HuZs0wKSESwLyIthTtCamT1ZaQa6n1fHHp5tvbVlZWd0lZOR1O7kVDeTdvEM21oyxFfsPVJcTa31NzCd+hkwpWgo04pHg9lXRFEu66H7fBYMxAWrqya1rV+mu6mu10N9YXTm//xW12TRLVbMBq86PDTHM1fpUodEUi6tQFCA58FrdHFO4Q2V/IFyWTwhx7xqeOMUFtB1ZFryoFF6k/I920N9XC6czLTp+K2uyaJarZgNXnQuGmOY+JPzJZQ5ZGRclagKEBz4STEFNRTMuOTf/+nAEBp4ACAIhGVmLL1ggQyWsPCAlGYhs1WrsrKfBDYxuKYMUOAtFLgQCJ4ikAkz9J2JDAPs22spCDmp+rmO9lzovKpND/yt6tcl9EqPPCWGllan1xzthY/EYVK7lsI4CX6GesJfW7/klglESNNr+nAwVIacSq0K4jhfZdK9LH/8TJ9f81SspWrLSY1dWuMAaXBUsfaIwqVzthHARd0VLFWFes79fU8WRoJFb5kwJkbkgg0Uk/T6S2jiEXCzg66VvQEt2jcvarcRc0pmukNeo7tUCLTn2eZ76z/6v6qVW/p01jR/+RRSWxrrXTX1t8h9AAEwAHa2SDHH6ClBuVSbE7avjN2BF0HK/skT35ezQgfRPKYBjCT5p7ZEu46SF5ByZSgFHLaj1Jd8X2dJQENGoH4316ExBTUUA//pyBBn8AAgCHDXcaekoYEMDHA0kYg0IlNdq54zwgRYbMrQSicYAABEQgvbbbAHxkt03o0kZTQTnvs4vhVSiDD1WrPe5X39xgApOz0umpndpX3b0fedSCPWnMX+NFOutsUkP9Gz9XU7+kVEz5RKP/yWgGZ3KTPAooIrrhmoqv7IxLq2Tthz2xVKZzz0yBzBYVpe3lHJoYAsdZQdYy82ZkVpWxIqx7E0OWjSikUgAq5baDtQ66kZ4CSUj/CNeT59LJv9P664IefjBacVnt7Kge0dPyc99UW1bVT1/Z7snRK09Ma8JpXrt+O3IUzK/xR+/yIcUWc0duusuOwIiurH3hNphYJ/ZWftQurLBFrSXR+pPs6dPvYoEhXSS6O9H3VhL0WEPXiI91oES63iXGGxRkNBl9mCrsRJiCmj/+nAELlYAAIIdNd3JARXMQ4MrAmEiPggQ13DkhKpRCAxtqMOJyCAERFqmlBacLnpmD4Puau5bxW/iLmfqMd0TkuitS+/VbBIifN5uzIlLuJZ6HghwOsBgobUi3/dDwAQCSahaVGNfLP9YDX/CAhMupvs0DQQYLAHLyMc2XE2cCRfNFQOGk71IIjNnqIWejdjSACx6u5pa/U/n4dwtrUfnGNb7V/WUponumvUDVIAQS3JJCgaakPMnWTSZNkqNYVqdGT8eq+ujOr6cqU0HV6pq/Tnopg8Rkqt6tZ3oyBrq1SwqQV3I138ndb+Tf9lgBBGa//jwETyZU2hminT7Mzu40oIOomIEuCGuaFR83bDtxYnQRlSyWvZxQg6iwylhapRDfLE+jcn0s8xOOpffzOlSYgpqKZlxybgA//pyBFbsAAgCGhjZGekq0EMjK1cxIjgIuHlm5JyowRcM7mhkCKAAOWy1XKRzOUvTaeqRs9F5m5uaXz2CbPTWk6Hz9TBRYjO9XxmoEvcOHyEqYZfampYwaw8Qm1NXo1ZVzPr1Ktb/wCz7AGAhW2yqiStdVPjXE+I5eXkkiHdFbsgYZ1gt0YGZ9fwgr92aAROt4k3xO9tJ+tw5yc4o41K1vKahOGM5lDny73ezxAEBW3bYHTANgHEwSOiswWBWwpkV4SvGqEyq+wuQJkHj3jX7nGAKSW+8RrjUjkBmFs2FAV81YCVjpDuW1RrfqSplbmf9tvUQADISvtkgGb1roMu2/zqwnwHiw7MtOs7vpo+HG4Qu4YFA5E4eKoFnGhX0MLqeQiwDBPb2mijVLEZijUKyqJ5SU3mFVsqUmIL/+nAEmkIADMIYJNoZ5jrQQ8MbEjFidgfo52pklE7RBQusDPSV2AFNt/6aclK1qqk7q5TWmNrBn4C/Lw3Wfu5unFCkexDuyBNj15NfKv1dtyL2nUxcWYzXSqtG9KC8U22Lvd5Ig7/I6OwAvqdUnZBHc+B0M7Qk72re0SS9DB6+ZFr0lN1oWPCh93qXR8I9jxfb5Ld7Edi3Sx7/XrDR3WE3VZV08JcSoLanpLPrqAKbkkSUeC5DBTspgRj0vFIdw61WCDrjXCEoxCcv1R6tVErs/V72E+I9rqi0/elJiU08fDo5ItDP7TnWK/9jqgCFJNrqlIF/juLoi3XLzqK1x3txWbzvu1DB9O8TecwLnJcoZjHcIQK5TPThuQ3QV2KNKYKWOps1svq7O0XPDt/6ExBTUUzLjk3AAAAA//pyBFQdAAACFT7ZHTygAD/nO1OklACIsF94+GEAESGQbt8MMAMAN38dsy2t6ElZAxWAdN596smFezi2pQGFBhyCIuPFGGFJnEtHdTfjj2eb7+3t08xv9VVSqfv6r0V0NiyFyGS///9IJTkki6TJc8OCAf2Y/5x2RAdJGdglrVzEFEUdqZqcTFp21G739q5S9G5Cok4sRbW3JXflRuotpPDx1e3T9qf+sACdAySuW3bAXSLXgFO7lW5kW5p+0KMckq1uDtZxVJxl3SDlmSAMIIExUQGC4ZPyWLHZJzgRpUtDtgyBTinMaLWp9n//6QAt0jG7JbbsAJIuTwQHhrGwxX+FmTouDI0ok5WK4l6cadL+nw8QXrnBinyV/JopbWtX35vNFJSLHGO4/q+GGuu/xha9946V1gmIKaD/+nAECk8AAAIkHVqeMMAARIu7w8GIAAh4+XFcY4ARCiGt55IgBAA29ZrhgMD9fCDdaBCKi2JcucOLEJaPfoK4jAyaQ7wRjMepWt5Q0tysz8rd/hPcc5l1ziBdK3vQgn484jY+pZL9f//+gAAAUej4fhlIPRAuhmGWThGt3R9za1+fv//f////1VCL/06nvOqGeZSf9CWSIzvi0RlVkAf/yEILRl5BGohAASEsVHIIAACEJRybbxCBBOEr/2yv3GMw3I6FEXKd63yWt1CYvNdpMV2ea/O9TfTz/Z+Z6t/39fM7DoXoQk/EjLabE1upObgDnqwABxG/prRUkY1YddprySz4ZM4Z9whlwUruY5tT63UIaR9V//1LlonWZ//9tEqlW8paP1L0SgYUt2Rr89rI1SP6MKITEFNA//pwBGpAAACCFENb0SUVREKny3cZIgSIlW2FoKRMsRKfq8z0iaAAAKQipLrrM6TYLnKP92S33AdlMrOrXETFV0qWlFnzeRS6dNO/+oP1X1fR34L7dPlf/DENjko1uDBvFf07qvVor27gCgluTXQH6TD1xYqiN2mPk8EITBPkQqPtrb06M9qv/qP6+R970p9v+3/QiIocMChQqGQymwqLsaj1VZUaWbJXCXJVsElqStKWW3cwwGyTjGjrDRf6xtWgGxul51Ib+zlINNyq6tV/+3l8IP4/v/o3gnv/flAV7+f7Nqnn6J1T0bZNbUwZfUmkAGu79MbbTObUuH2gJ8H/DybMFRyL9H75QsEN+aE19RpCUE9Q2Dmhyf3t/a8wi0h82/V/f3/6P3fovKJ1Zvd/2bvVF/1piCmooP/6cgSZXAAAAhIf3lBoO5xCZJtqLKJWCHhff0GEcMEZja7UERhAQJT4FRokpPN0cSlYih2DqwTJsSGS3WvOTtqyoGWlexVzdCwpeU1J32iRztoId+s5D+t/E4PvLg/w+s+rUGInPhgH8AB8CW9ttcdowPyK9fSZK41+CvhYTG6j3a18B1rCFr1Z7Yyd9oRIonflHO2hjv1nIf1+D4PvLg/w+s+p1QYic+GBPAAIAAJJcoJ+GQPJC4mdNEiI3gQ2AF3WQEMRQ/KHC46o+t4niB0MQfD5wllFB+s/+84TEfpwf4gd5c/fl0BBRc+mJ6UgIAc9i4GvkJ8GZvsyGjD03kgomTMIOtriM5RDCYRJPY7EEHh8g0E4PrD4WDEQOE4PgQaNA7wwI3xO91WTKVH+nLn9X/8ptTEFNRQA//pwBJ8eAAAB4SRfACkYMEMArAYFJgIJICuT4YRmISWK75gWDAgogAjEZKRCWBVMqpMDpLy44FqjYzb++qsRRm5abf8pJT42DEvtBU6bYFDxI6+rgW06/rkVfm9tX/Wr+rWBABGqsQBi2ww4jgqEHNHlToVLHg0wFnuaJaiNpvFUE1MEvBU6bFAoeJNehRpUCw8dHcXQRVX5trSSBivTsWpPsQrKqCmdszIksssl1eC4PWTU5GSLMBYIkBoNJKlKlDSy5ZmIKVQbARH9zxRJ0xdAXGlHG1H0azXeSF3CMHBQXa6oUNzUiu8NsSVJzAmBFqpMHiu+04IZxsYzJFhL4IeqFVRiPLhEcwRUsIz5biCbVBsBB2rcxxsKGzrk3loQjShQGlH0Oi6Lr2iVxcPMF1uqUb6ed0aEwP/6cgTKnwAK4fUZXimBGiA+YyuwBeMICQRNciMsZIEijK5EkQ0AAQDOUwGX4w0fs2LbwwI+layxv65cIl1rSoJMAdT0hIVOoHOahgve1oSCjluXHKDT0ant99VfzfZr0272V3R7GewsSraGqRUyuduGwjTj2nbkgosq6cJFKm2uMYeOekTCp0kOcJTDBe9p0YOd46do3H1K76q9tj+x8r/sr4++0TULwRHhLLJELFZLifc1PaQj2xOQLAGDwwNEdRYOrFGzS7xQW2jj47IhBJ6GGCJgtsCUSuPA3EqaSzdzCqFBk+6uq5ZGwdXNOIiDo+ZDxQ/QaIpqPFwXmyj5QMJP6NZk6WlmYokRDmk8sUafNLjxATQgJKg0yRGJPTjFW7GuDU8I7dKa5liCpEy3XUp0RY6tMQU1FAAA//pwBPZ1AAACDyRcCMsZQD/h+4UFIwoIvGVxJJhnARcKsTAxDOYZ8iyAlQuBJEFpxTODKIgv6qbPsXlbzn1iaG2drPSYNqgg0PIgqJcwi9pEwnW5DDqpAj7du4Xc9mbcVZk9ctar5FYEAXhRBITUNOCfMwTSzRGI/pofcEOUfLKDsBCrDxYk5hIy54ROSaniMBPgUbEr1FdR1/XYxtFBt+l87rN39dmlACUSGVW5cnSMtABCOS2a+D3vmaWLYqx0kh1eeL7fUEWslWu1wkmGipyVWgkvTJWLe83eurUXeXyaHq5k4KuMpkn2If+0pQSCklLumsSnW4r3j9WyfsLj5yGpszY7EnxXkjBVTaHnTERih5YudO2sSdKz00wUxLOlHqeFNwsdffGjiIqVili01xx6rWmIKaigAP/6cgRfFAAAAhgr4+hpEwxDIWvKDMIbCMynaGekSQEUie0c9hUQrRBli0kjaSRMYKWqWWd9CxuRm2U6gz1DM6MtDPhVdRAuQqXbsv91Jt5E6jZG11ssoh1d6n1hklWsa7GywK2BXb/LasAKCLcccni4erciM8OY+aS3D4RoMwkXkqUCyBLMrz2G3uYetSdWMYYOlVVhks/fmWCLFWbrUTynaaWYwE1nkEyxerUAEo3J94YV0jw+0wEzCBOHj8AlFnI6/HyBzFgnB6Lztr0Fd5fs66JOy9qs1hzY9pFwLD6aSD2uVWO+vthUgWVR9VjfTvtYuAAASbkmN3L6yNJ3sgzYRJYGPdxq9gA+DhzGuMjaDEH3qU8e9sT0tQpRdqXXsoh95DJpmjSVLqbidodQi5reppL2uf/qQmII//pwBJi+AAACGBVjaGEZzEFCazMt6RYIzMlzQLBC0RaJ7agVjHiohFqOuSSOS0XtnYG8sfB9GQGjNlnFbwYzGjDqSVlXCoXSRIPc9pmsXj0am0M3JJypxSnmxG1IotabkiwB6MP7kIKrACSbcU7Bc1VUVZ7LnmtCE880Nwvtb6ZRZBLUmI7dJPMrahggqnKnSEFZEQvbW0e0W0VXrnrVd7rLv0r0adlNvIugAAEItuSQ5qFUsJwz1FWlQw1AnFg3NoychmhSa872drd7tVUKUsrWdFy7LRNXZV8d+RElLhiWBrz6kIpHNqctbas7U74vXAAAIQkt2xCoS2Yk4LtHxpOTvQryivSMbsQIaHwEOShi6ztpdpJj4we6OByVvNJXSt6zwSknvzvYlKr2BkJeXtdu2I+lOhMQQP/6cgSSiwAAgh0PX+hlEUhD43sSPSKECGhlf+MI1GEJDGxc9Yj46QCcWqk9rbi9gOBThtbLYMLi9YgdQdGGHItHm+dacMpfY+pJFggUYKTiuwH/5QMcQJKOlCnXD7AfOS58SQwQa9h9nLgL/kutZEZguBCwunh6wzErbSdn9xZ/7D4pN2r0jy2+iB2zaHMUMK4aQ2tHrhu4fY4XJGSaVs3iV9w9qNirkMyXtd/WtUEAFDMom3sJT8yp1ARqXrzO6vf1b/pQ44ypa7qFK2L3yeCmT20raZCYdxZ7IcUW/0+49+sbypKt2Ku3Yx7kFtTcJEQkBpuQQdZKgkqoSBdwGMDSA8xdj9c4BhnT0hYZq8pHbd2ZWqD8LCycSvad7SOLSpNTxQjztx6e6kSLLfAXqse1dO9MQU1FAAAA//pwBKTRAAyCGxlZkekqsEICW1olqDAIjP1gbDCpgRSfbIzECWgj/+xnpd8ahzBqRaMnBYfUlFEL3Q1XuQ0OnJs9Rqrhy5poiGUpSuoiyk1Aht0tdAvDSZHXPfVDpMllnejUVcorO/6jwAABsB27f/JDCpg5ganBBgtGom/BUnLCQybkq4qSxr5yqzflGWJBBNmVIgSrnpAmxhodUbg0yzuZVWBUXR2rf73doAajcFz7LsOlFUd08St0eFrJ8moqJq6ai5Fm0KSBlNajKXdx8/D/axQWlrK6buq5Vuq9U75Fmuaq96rddejb+i8bV++oAFyXbKuDUM0ReFAGWkrIpGLC/4ZE3KhgTJGMPeqmx3wPtghNHNs//LTWbT29D9111XX693tp1B4cqy9B66i8pe5/7b/WmIKaiv/6cgQdJwAAAg8V2ZnsOiA/xFtdMOVCCMxni6QYtDEgEm1cso3iCDm22xvZzqJRhrmALS+F+mjfLYXJoCWq5QYvQuI7UH34sSNL8b88heQEiDYJCZqUKWIG1PULIKT8CgX1UXa9nt/VAAAAAABdtuIEfnxG6xcCPQ+RsIpwvjhg69B4m+wv27LYN+Vy+7cSSNNPNJWwgDXvMLataatsV6yl5Spz14ibTaglG7ZHZEk5gkFV3MPtmrbde98mDA1HeHAK9ax/BtLYp3j2iB8Jpm4gAAPwQFx9F92awQlKw+/E459agzieH9BTwQ9Yf5SAwBbbkuXvcJmskGkVN86U1cVDaKMHdA0o/IL83WGYTnP0l+dqqsC4JLjQBVUpXs2dCZ6WYy4FGcQohq99VfHSp0QmQ4pFQqhMQU1F//pwBKFhAAACGEPc0GkRIEJFmxo9hT4IDGV9oQkp8RMm7uhQiRLAACgzq0iVlAX2DQdw9x0lfhOc43VwXR+J95BvozryIjzTXLstoJWkWtLf796s1uqUO3a/fgpN1QX+slamxdK6NGkUAAAwASabCs+jlJtmEdqSgxranodH9whW6B55FmT5GIEe4kB2oHfNFRH69K2owslasm/quQ45Clzf6yVbJJ9lO2z7YAAEUGU40QUXPYEcVWKdkJw/rOlXO1ARdDfsQGkKxHOutETCw+DRueg0j8O4l6A5/EqvJLGaj3xEDKbpFZ0Gq3QAqsEZLr+rRpsoYh0UhvD9w7KtXTRB2oT2oT9n6H0TqvzfeWw3/MV3n0W1jkVpm8PT/+/tZkKysgmktvEQhap0JXGjfSmIKaimZccm4P/6cgQpTAAAwiI+2FHmKtBC6csjMOJ6iM1raPTCgBEUHuzOknACgAEEAK13as3OU/DaBxF9XGzihjC3Fi49Ib3BwkOhPxeZgFY56L4vCg2a/879KGUpaTq3V+P/5v/+3Sz1Fnk/R6tj//qAKTbk2K4pMEHDAdfNp+/N0UUB52EUvbLuWlB4voT6DOA+klnX3qiL1fqnl8ctd30/1X1bkZ9TP39PJ/0NegrnV/7EAFBDcctysnYkHZ8TRtdyjuTRduPepgkguiu58ykxhtLzJbqKuyzasb2Jyn6tuS7VK3J/07t3fyr2rrbT/odOby+3p/TjGJBKbcttnRGEBPMKG735fQMszwn6Cp6T0HWjxM7QhznlRAY03I9TvczU1uavXo1/9v9081ufdXI406vYniNUc/qep6HYpoTA//pwBIN9AAACE07chiSgAESJ26HDFAAIlIN5nDEAARWQb/+GIACxBYniQhXH4RNeHb3MZRllIhd152ztu/pzjlHP/+HBYouRv/8PiIHILiYv//+HzE2ib///+PY+HwwXIa//4ePlwPJgkkuM47CJnT229abfO5HEOOouPtqXV0uvm52Vn//DgsUXFG//w+EQOIC4mL///h8xGtD7///+PY+HwwXIHP/+Hj5cDyeQBMIlpQBIfRI4eLCzv311ZLtCIE2WtPRLKaj6s/eIBs4fFHeFyTxorJbpAbFl2vDRY4xFvSxssQD7ZOKEkl4bBu7KosgwBCYUJ3GkkkgTQ17sg2ZHkdB26EQqttYG56M2iWU1HTb3jGzh8Ud4XJDxorJbpAa8WXa8NFjjEW9LMsgn+lMNg3dlSFiYgv/6cgS08AAAAhI13WihFcBDpsucCCLGCGTZb4ScTsEZmy2kFIggQAKQIkYAAAN4wOiw0yIH3ZN2zdlseZgccogEzCqIw8nP0teKJ0Pa36ZAZH/H/j8q8YSbIa+oe2Pgy30gZ+8tneSn4AAQGaQAAoO4IBMDHZA9kztUrcOJvPB6AzriUVeWfpa8UTp7W/TIDI3+OvXH8NoFRtRl1t6yIlpaWCfRNh3TPSvHuEZAAEADeABb3oBCYxrLNfJQuDst2Md2msFdHH4zd6ylu/6lcM9ulH+/mfczt5/fjX/ZkXbciVUySaqlEXFTNYSeLcdrAAQIYBFukjtxP+YdkXhBODfYZ7Vg3VAY+pPeqFLV1b1KYM9t0o6e/o7XM7efo9Yynr2KsyLtuRKqZJNVSiLipmsJPFnY7WmIKaig//pwBLQzAADCIExZKekq0EIoCyElQnoIiQOJooRY8RMgLEj0nWgAIH1xo3k6NpcK7MEmmtvyYv6BUPUBUxn6+ED8oa6BnknqX/pUtScrX/6IP1N+Z5/GN7/qyPTiLff7+/qIDvUv1MbzqgvuogsFzIwE5lQMWavLVP3DDSFYkpGY6YO0PL6kuszE1mZv5stScu+rf3epn9zPP4Iv9OrI9OFd95ZOJB3q+piO1VIadkdUljTcK1LDDOgjldB4bgK2oWWkIzaIKZi6scAyLx9ZheBSV5BZ8iZy/3/BE/r5dWJMBbj2KRhBlv1LXjnV8wpdQErVXW5ELRhGGdkbB06QZ1jTXwLu9NAOehfGTQHP6kH1J6z5QJ3//rdLbf6M2d1/vbSU/09dUMx51XLG9q+vf5D7jLKkpiCmgP/6cgRXlgAAAhJAX0hDL4xCyButGOJJCJkzeaKEWuEUmyxYxJVo0Q2dbertMaivHkBVvgx9AY7rUjNiW5O5kEv/9Mrpb//Y0Bjab5GhhmzeJAdFbJIbQj/jVpazYlrXlxX6GPoZZrtm0wCCIWm7bHN89LUBQphfN1ZqhCT3FO0GQNoJbUJ3JDpT75tCardfWTRHwjMdt9bUboPt6N27cG2nU93UT76uLV30mowAMUmrNtN/ZhAWeplFN2QvCD5VHrxzt24D+iC/8/vxIUZpI8fMwkKYtFZF/FrKDkLdq9t/+/KyUkCkN0HFxcxgw+/0pgCBXfQc4YjsWQuChahjRcXviBuPoFH+8B83GuqEPnouTgP6Z+nP7ofM8iLsW3Z1R2UoxKdk9cWdGdl4Nyv61chf5FlkMpiCmooA//pwBGLyAAQCExvZUWY6kELkG40Yo18IJNdmZoRYwQmOrzQjjX6AAAAFEo5WXkCFw7IvHwwDGJLcnYbCItjYqXdZQWga+c2g557WfLVLoLPG7ux4o7qWXe0SXU7v7a72tkk7LB1u+zK0AAMsIFeSO4pPnkp0YP43iCQ+nAZtBo/oGE43oHPXBOWSRc7HAioa9ueIKbfal7RIac48Vs0/2tXmhTsYw83ffzdjABJJLbpEmMtJaIQjhxPRcoJI5PPZdOn1oVR2Pk9uU/M3/rzEKMRVpv2VuM3Yaytk6iVaXX9jPWvyBPIv+Zeq7ZIoAAJQoFRIpOPVHBsPeLctapMO1KjK5QsjZV9CfdbiPsmUQaUs6Bkm5vpWQelEX86zfENSnqsVSPeXtJhL8rw/SjQtMQU1FMy45NwAAP/6cATxNgAAAhdM3UhHKSxDJrs3PKI8CHx9g6CcTvD/FO80NBUegACpHpaY8K40oGZDS/hHQzD56GAIc8JvxT0k/2V5HlVSr3TpWjVjVZ7y0382lfZ+RL+tl/+9Ue6kYY505SeJLrv/IgCAEdl2rui+8aSzUoxAIgvh5BfC2xAcGrhRTjVDu9CekgFX3vydmbf5PYy2CkdaMuc/vj9O+Lr/F2azARu2aclr2+mAhFqGJuyRyhzJSGR04fFHocpsURDqg+jdioJbTldnggo97Dj5DeNKXgxYDqz8PMiM0AzTuz6kKgEUHfYFH51pIzUJHpAAIwkEttJSy5ODcbfO9ZZEBy+EH4xxvV9G9aiv1b0X3OlBd9Ctxd58QwFgktZ9qttLpiKbKlxni/7dbOl4J0piCmopmXHJuAD/+nIEphIAAAIcQOFoJRLsQmKrmQTFB4f0ZX2jhEixFZNuaDOJ7qCQEpIo5JJMFTA5O9ZvD+jizIkzEeokbGAul0FN+bz+voa8J6/Wu3OYCczs9bl9+sy0amJyONQ4dkTn0JfeZK6nkWklAAWOmq62UdLSGuLWzWxPsAwIiRJxF+Z4wyJEElmYdl321ZGtaA85hKbPPDYFDK1lyJoVPsUoAQM+9ikO3PzH5p8hQAAlCSm025SAdVi9RlQWoXqJH5fWbV+Cb0hjkVXemvfRUwbxI0ZsfPxEihRd3XWKlVnUqRWpF54+VDWHNr9wyACUAW0klCG2VkAlojpGFRcUeVbq5jyttS3KJOEJx8yonqROidX4+Z9EuFyB56xrC6lB1i7DTFmbVDESVdtGO4TMblLR0piCmopmXHJuAP/6cARrcgAEAgUm2lGCOtRDR7uaGKJciHCvXueY6kEWnvD0UI+WgAAAQltyRhT0QehvorJzAxq6TNwDnDeEdsIMWY0ZBwzlUNU479v/2VF4sOXuS1Ta9kq7qgZLSgK+xddtf3UPv16AK6EpLbcUGlB9EElsj3SZw3Cejp5KZI5oTbotTfMI8rX0eutxvHZJC5q+p603it87PQl8VnProrioZ91G9CVvG+RRAAA5bbA/bAMJxUGWC8RQ444y5QEoYe2PDrMkS5JpIcMyo/0aNGv7e307M+XTdleVNnScqbYw+WCW21yJQn/b3GP0/XUgVbI05Zbbxm5zpeL0MUaNCWIPnXz+Y7NGt30FbtoK+X3XXj8Pmqmfto1M4ER/OEjlEEVHyS22UGpN6zn60zhg01YMBKpMQU1FAAD/+nIEddsACAH3FVvRKxEkQoYreiAimIi5bXlBFF4xIZ9vaFCPVkAAlBTcluhulgRYhgReP23M1QBtQXjQeDdsGKwg5KVNp3S2G3FmFOiTap/8TgohYua6zle6C+yrZWEXTIq70IALICnJbdF5hdiEakh9rOihq8ivQZ4PM1mPvMVrj9/erOnCnfR/bS/jxx9/bFw6LB6Les4yYmB/RVUxbGWHEjRe7ZNARakct4IoyAhMRPqTh+gf0Ymq8GL07v+Kft5/P4Z+nMlMhExECMRigDvVlNdyCaXJxk4//X7ksfZVem3trd9G3mBWnfTIjzRTakk151Qw5lFLrcSXP5/Cqajeot3LElV24vXn5rk+Vyh6A8wFCwgU1Ls+L8Ot9GQLJCV9dOXhAN1OlFlnsDzTYWLrsjqExBTUUP/6cATZjgAAAgs+YWihFcxBCBtaFCLkiOxVXGwx6oEQH290YRXegACjkqTslt6vS1HicfOivMCPnAj3jBxmqrzfnuvXJ+BcK9+/+fjS8ES+nUb2PxLz4QZ2S9jZJ++2qkKHIgHHUK1IAQICUnLcppAsMCwIKoBaFPYNwV8o7xjGapeoP+ry+O8/p9cn43/nzrktl9fdkhX0EeLePYhvrU488YEIuRvcrYACXbvd1XYQtZtZXICbUlGjU7nYoKJG2gATnxIO5Ypn7TSR/lYJ/4LBY5qc5W6zbTuksM1uctjXSuqIm+fp8XfbvR8vh65/uaASiJhbbbk05p/UXibB/keLbDeCEcCGO1StkCXZMOTeb19Pdeoe9uv79SWoVLW9fsmEinBbEe/ycrptZTeFiqThJOmhMQU1FAD/+nIElW4AAAIhP1kdMOAERMfrF6YcAIhFN3YYwoABErEvBxRwAAQk3JN7CkDInj2JoGi+AxYimTN3HUIS2PjcMJlRgx6kn0CG/9fOby3/Tof6NRXfzuavlG6ffzXmy9wiwxR85RjN3W6LwAAKSck13kxwEIa6WoTrsmV8CmoGltRsLKWFo7qXbQf82PCc8r0Zuc3t1Tob6/fzupvco3/9S3HibVUGK6yOy/dW78vVq6YtHN05OD4GYw3doZ0WeYODWo6BwGFNOlVEF/9aGf/8jEVjf/bFA6Hhw4TN/3/w8X1dv///a6ooqIwL//xETKXOJJJ6xmSGs4F4hPH5mroDxcxkG4IFNOk1Rz/5xE45//yxEcVjv/8gOjYsWHx7//8bG6Vdv///a9FIoe5v////6HK5hChCYgpqKP/6cARnVAAA8hYsY/8MoAhEpYug55wACEzZlaKEVXD7hy2BgrxwgCJBJFM99rG3HYIpGx9vG2ZTW6jgf3o9DK3V/GtL1zOyIcrOimMjLvrqqiNhGt1OYzpGRAp11e7FFUztfovpu8jVrvcSQvqVYmZmcpVLM3KKNCjQTlbqFQAhJGrXo6pt/1avXd6TzboqHI3/VVHbCNYyZzGdIyIFCbq92KKphOP9F9NyOHatYCbltLlkbSTnFbs7jrKyWvy8QBvFowbEVcy18qSTaNBiHs8yyJkaC/e2sduHyUKqBl2K7XOUaF1izyqOWtIv1MleNbuWvBXdgOyixILLlIIavneCpQNA2RTZRrqQvMGTSDIjhWLRR7Q2i9LgG6fkoVUDLsV9yjQvFnlUPy2Rf2V8amIKaimZccm4AAD/+nIEhgYAAAIcNl5h7RLIQ4bL7TECLwiA2WQtLFJBDJrsyZCKqAAEImD2qrIsW1hrrWqV9bWUkmfbfYNojKZer2Rn15mbyon/Lm6f/0FbM3z121CKe+RxK/e5QFKyNJgtamRCpnPOT3awgAZFQ7U0kodgRMf1tKnl3raX+NtiQg/3lojnU7cxWeRgZCf8ubpovT6CtmL89dtQiv+zW/1AUrTuVamRCqcOuLcbjwnEIkJJNnhGFaHJA29yRy2pvlLuEY8pPm45NkpcInx/X5iEdNmU6VlbutOf6G65eT3+bQrb/TvE/y2pbV90tQn0/r+bAVakJ4n81qCJK9Mqr19wNSZZ65nnjzXPsy9RQMNl12/ywBYmCPzX17+xbzXLf7eJB99O8Tf1jH5EX9ApCm/3of7XdSYgpqKAAP/6cAQ30QAAAgM12ZMvOXBB6BuaPMoNCOzvi6QIsPEYoHC0gQ62BLvygQpDXjcjC89Pz7r30K+d3h+19ZdZCENt1a7w7qJmW8s/UJDOr+r+nU7fm6fS7f7v/kOqr23Ud2h3/r789WABYAjsjbheAeRrGjEx1Ogmru0ma0ZgyAvkz6qi3mljPJGd8/zf01Xc2z+9ma795unPtoW29e69nyr/Ux9KP/rr5YFNqSpySOSOiQ6bVR7lTFaakhZKVrQwhI96HZHJDpsgFu869Ef/VPo/+jiq+ypSno5A6/RbrQSItPLDOihbnp0/WrvOeg7TUEEjVEk3W23AKFh95Eo0VT6T15NxUCQBZO/uXxJ+hdsfkmYyMUD0XXtnqrbM/b6d3wRej1X26aHug/lUzHSX7oQ54Mb6DrExBTT/+nIEVnwACIIUF9gzD0jwQ4WLWj2ldAigi2dHpLIBExXszPeIuACACtRcYSjBTrKETiqGo1sK0l8KbEd6ERvTZ41XoLsEUA0L1lJs5vuZ+/DZIFjyefija9z7svyafLde2i/0r+n/0uAAgAhty3UlwpLZqEvKhGvZHN3PreKXzCYNNgQCSnRRIi187+CLv+v0N9E7/XVBaeJ6q1KevI11OLP94up7bwsO10eaDAFpySRIhXIifRvrL1GyN5fNX9WpJ+ePrFoIgovZBscxhBkaVOMCKLoK+Iv5vHPrN4YUQeVNtOnlSBOzrR9a+9/9P6PqICTktPUWpscWId6whcSrkwW3nG1vXh6brQUgMWzdrJE0vhPRdaP6v7N0/f/oFzhARIrYJnquijG0ennbrmIXa2eyrv+pMQU1FP/6cAT/ewAAAiE13WkGKShEBrwKDEWHh+jTeYGY6LEMGm0Ml4pAABQQoBU9l25MkNhlbIUsW7cGKYVW8Ihqp9UZNV7iSrpfq7VlZC/RT+lvN6N+rLRlHIqvvchZKLpxywrasl2tyGa7tEiQx3CbjjcllLD0VL2H9nUpnhBdPqe9RbPmNm/q5lejaq1+32bUIOlBxTa6tocg6Kl3MnWM0dUMlx4xB1AffaNnStX79IABEKAr6qwVSNDh3iIQS5Zmf4+G1M0Sjozqc9aAgzsYYndWTcu/T6n+7a0bsn7py+Rr59FuzAy2rYpFmd+R/QCrbtsBxBbprIwYb5kHnb+2e3347RcX00jr+t8SV+J2z6uR0SyrR0dH01baisCdaOnXciNHEbrVVvUyyk5zy9T/T8RJiCmopmXHJuD/+nIE1MoAAAIfGFxpjRnoQCV60mCnogiIpWVHhFUBHJSsqMedKAAwMAAna9rv9VHeKssnjHQN9Zro55iKKSzjc40VU8/wQeDWulB7RLszegyAwwaSF7Fthlrj7WrMDdf0pEls05nx3f8iALUQOyp4Zt20XIMazMzGIwON9wm5Q1/Ln6ifx6YB1Mp1s1SrhQyckPGepQN10JPWUf++ttfr7lHT3yifo/8d6QAIAAElu2eu2GK/W1ncaWcXSWtsar/C2plmyBBrN6SWPMkgws/i3+4im2OQ6kUxfFrQaGDBdA9jp1l/i3X6VmLLa/36QBIACbk22dPFN1pZ4Z9SxAsQfplia/zDxtvB+yZccNlDLrCr9RRS6n9SlPPtpdrdcusQkIl33Ch08eey5iL+In7fb+jzLv0JiCmooP/6cAQTsgAAAg004WhgO4xB5puaGOVZiOEveaGcTnEYCm0clonSKaYiAajssl3QeDVdr0p5JxQXoMJuvcfCJnPRF9etHXv9XN1f0JO1LKmu5za8kbo0IYQ37q3WyJUDdnAz5FPinYtoDkQAlpJKNd9wUmUydiyzbssx1woHbaTt4U3Uv07I79/I9tXvobyN2/orXEhCgwJFmLiOS+E+9bWN9TeBuVFGz7b0SiIkCSmo26Y9eqivMIeSBgG+jw0IQw1kg76rfUf1XoZex/L9TehFYqGYyKlama7rKMxK2trPorc/Zr/Gv/gn/vbvfZ88yPAgAUm5bokaesCB8W1NIQN18g3uorPw7Apay8y6QsvB4JZPDLtK2VuqOMUZc+pGhPkt+a9LnkCoCKA6zNkBzyXbZPFnTVbExBD/+nIEFR4AAIIgRt1QxRRMQ4U6wmEKoAh80W1EGFIxEBpsnPaV0gEJgJbJTde31lUnv0XOf0PzZq6gU8a3YY78i8aADO6lEjanemJfm+rejev/z37dE/6IzqbTqgreo268v/UTrAJF7dcVAC/Imqq8VG8AVwuhw8eqhhvuX0b/t/z53JscX274HtIGYPZhTGAYUKkmAoX3tR9+5T7+l+zehbDboppxDkNsZ3b6/pQAhAAohFwg6HMCSj2lAcZPLFqoZGd2hxOs7IiJwadBPr7EH50eejP5fRvX/7awS0ljDVKan6duxSwiL36qDzVXpz3x8ACm45KubVaUk59KquFXmemqyMm8itEKG46yyykGNI8P+x9n/GN7fMj6VVaFthHqx+110EhYXo2Ct+3fW+UxYUp+zR1piCmooP/6cARsUQAAAgRXXVDFFDxDiuwtDAVxiLElg6KgtHEUK65oY5XWAQzQlJNt1u24nisbC09z8Yubx8RHVfz0bCB+Yev+n17uzdPoVqIEdc/6dyH9WTj+tf9kd+3z+jf//6xOTup8NMSCajBTcstu9WTB6daFfJ10EatKsJlbhz4t9+cYVtSv0Yn/n5gE926SVsh1161f5Pn/1iiLscr8t1q/9UZ/jlapEO+dTBJbibkskm6ECiVdmujvOMCNxF+NDtx/q0uVugy30cNVczNyOmzeIn629H8Z9/r6P5/r8v/p83wp4CPlSr67SuXniWz5oQDkCY0kpS0ilOGSneieubwmFZ+WjwfWh6FdeH24DgZ1WQPD1szNx/z+j+j+b/6/H+r3y///+b4hpIpT66frL8Xe9uR+9MQU1FD/+nIEf6EAAAIbVN5RBRPcQ2U7FzzloIjBI3+0U4AxF6uvdoxwBlEGhKbcbtmxlUKHNXc19QCTRm8aD1fSMYtoeXjQJXQ/ofq/oP7fR32M3KT5vQXbv6ff/0b1+Dk1FW6dzs9WCQe91X0AQBTTTkivIThIMhufz7WiURI33pNf63hA0RYvtLm8j0CyPwENwFBGnjH7KOqqlelU9H+LJHuUjTp+zfvq15fT/sznqZARbhLccslwRWSZkdWQV40BD4+beJxdMfeC8gyTBq71HAez3c76fTyhv9ee2x97uf/6F70v1Vuqa/0+a/lLin0Z/DdWr6SiEFEEXI43c1pqj50L9zvYEI6eVGh5r3We0xkEJ5+OBK56fbbqm9CPu6+7a/v8z1f0f1b0/9Pq/jR7Zj9e/6qz8dN14r96YP/6cAQbmQAAAiJiYb4UQAJC7EwjwogACKyDi7xSgCEWhq5DsIAAAABAApFAqFYsqyoKEXUMq8QJ6u2jzt/6ov///Y53U6vT/3Odld5f/5CfO6lavf/5N0Y53Ja7wZkRf//+Rjv+qI0X2HdAApFIqFYs9A4ysQoI94cJ6v10X/6f/3/2Oc6nV6U/3OdlcylV7/8hPndStXv/8m5CHO5LXeDMiL///yMd/1RGi8HlgABuW/a2NpSgDoa6Pd2KyGeYxqKJg8SFjcY6/ulNnQrIiPTZRwsDBom5xPhA2OI2pmJvKhNtSVN6NTHcMM+vkVPdqDm6+q3QQlbo16Fy+AJFq1L6Wls6y7BTXDMDwmBpkiSv2XhoUI40JiIMjUIW/KEQOEHrGPQ6/ErdjxWl92KI3FBn0N7yKOItFID/+nAEY+oAAAHmEmRoQzjsQSKrmWDFKAk9A5WkiKexGprvNPMUNACo7bJG2kSVCCshOi4VifTO8lokBqjvoUNZOVjGqjE4OE7RJfXKuDJM5lnaTzMzYEsKnfVU9ksW+Tq3tmQAOodQVZIIDIVTkQoZt5kauLfAzqXRVB9/GNugcdL2tVUnBwnaUv5VwZJs0uXNhxmZsCWFTvqqHMiYBbMnVWPbMgzNaZ22xtNyb99D6gnbQpHxd0a0MSo7aGBEpMS0yV2Lb9MSeb9/l8pW2/sn4r/+ZTPeoiy3JPHXhMmpCS4GPWuYDoNYlOiXoPZIBAjaESxpAlk/GeP2qX9/Oytko+4yjSC1Xvi4I1IHJZ0GVyt99MSebbuvl7lFS2b87J+K/hV+SXTzrVaTe10kIsSnRLyr8kmIKaig//pyBE6tAAiCIjVbywkR+EQmu0ZlZS4IONdgLTznwQsgLqmBlBQAAYPZlYd2zqUyfFstu9HcO3nyZB83Kb6Fnr782yo5ynIc+0vX9E1ZV3Jmzf6KiuxmL/rVHBBR/u6FMRrdK0DB/3O/5sCBf/+K6hAUpanp6DZvZ4Fdt+l96j4oSZAnt8IsisoFXwH6lb1H6zlRzMWbft5KNKjL79a3GGT928wKeSZdMEW+j7l9QPmI0go2vpr8PpgM2livgRGCWtM83b+u2tBYcXPRUz51TKLiWZXJNogFFfl/lvM+b8vm7annvn/v/KL11ef/+3/1Xg7dbJKMHdcELgYRWsFOasP9rxMVruqKpGUhm6AJfI/QTauU9phHzpl7aP6P0vamMPr6X+r8P6X4oretv7dbLeed0piCmooAAAD/+nAEPtIACIIONdxRhylIPqgbaj0iLwi0jV7MPKXBExXriYYJ0AAIwDRcclAEEJiviqXOuhZ1qGiMldSQv4RfqIHd0EBH1+renU91y/pRZuT6P/MG9FRm6G5jjaiSYeRKsrRdKH/ZsAAaAFNMtwLwhTJaOn2LdVjbv6sg9p+b+QhPq/87n47dD+j+DZfJ2T66bM6bWT//j//9rYC6atzSfkPr6j/yRAAqoCoC7ZdLZsvO2xGDuzWYaV6lC4s9h0qqcmaeOyppSjAAD2RAFLzCT9x/kZ832H6KkSwHutHvpGs7Oun7KU63f+Zp6QAZoxwBIXKxtFULvvpObe6JW6mPIgyW94PIb8BCA1KeLWBRDn1Afk2o/g2fgl86/220ULSEc5TEz2RpJm3/a5+5H78SPTEFNRTMuOTc//pyBFb2AACCHjXfUMUS7EMGuxo9gi4IbNdiTDRLEQ8V7Jz2FLgWTtU020nHFLVqI9HPih64wATvP1eN+EsUKQID6Ft9vMN5uh/J0WUmU5G1b0fV+oj3Lt2Ue9DhxZCNC2mp2h6q3qZOLAADAAFOOQzRFk3Ea2wIzxXpYIlOnGgj61MQ4sMyJyXZbAl6BPRvT6t5Tej/+VtSVNX0800oymVGVM0fW+e9vtu7/mwFqphMIszsoICVrdLcqq+n6y8EdF7lx3H1UxLb5SuR0VHug3q3kLpZLSCPR/J0nfUr+elqmhV9s2Hs15RS3djP+I/2ECIdstMEwYzDHKg+XvsQgz/tlsy6lpq7pDKGHH14ROtRgCp0+r+n09RVm70aj3QgsGZtC0HmNL84fnb7/RS5yr/rsy6YgpqKAAD/+nAENY0AAAH7IFzJATysQ0L7Gj1lWAipNY2hFHXxEpjt9IKKJBCIgDmWyCi/FhMzVYQmt8nKbHD41U/JVt8LBLqeVd+d8viTbkWCp2RduvOq47VkXW72KQWEY42W9kxEKLU4meAAmACKUmxdD5N9/M+ZUvCq5B0Q+86HD6ym7yxPB5jKxB14anGDtmyXbU3exT5X6OButli2qZXpnhR6iYrZ77rXf5tDQUWgLlttt2Mh9WmxQHyjferwT9Am0UKNAQm4kDn6t1G+pPQ7cteZ9SGbavSOSs+/+U/Lfovzr23YpaaPEHprfQCIB3fUAGBTgFLHbdynfUJxpkdAHKH/i6QW/Eh8Ka+bMWBDO5QoHeRRN+wdvT7v0+r9g3t6IMesRRS1DtWojKKoy1m2lnKmfs6UxBTUUAAA//pyBIbqAAACGUXg6EcVnEBmzC0IwlWIXKVpQz1IURwUraSwiwZENjQEJySSWqi7CmXGFCrhS+r109Qr2divmh78dbwvx62KqPV/lH6FbyJ52vUktLa79/e9NH8FPmXCiEk07CpVHd/1tIoeUlSSSS1hB3ldl2TFdrAUYXvV6N6vvA/Qyosr+Df1byS/6vzK3p5jkddo1rmBR9dKc3nmyNgAGFnrZMH3toAAxAFJqSTr6zgEVsvotX0tskR6DEtFTBgaNSj9BUTqPGbZm6uq5r6nnMi0T2L/PZyKNcr4u+AbSxOI6Q5/926nU70gCRAxK1qWaLsChR9NXE6110ZXdRF6LOFvnQX5qx82xNfWqhR60O9sWz9PjrtyGxNp8ROh2gJsgo5IsRkWpIJikxTUnod6gymIKaigAAD/+nAEbAQAAIIaL1eZ6xUQQwl7ihwj2Yica2TkvSgRFaSszPOJcgQQ5P293pROzDizQvHBq7r9wDFt7dtNqRXYwNItN7jgs3TpE9n6gfoX1N7v0X7fCdVL5Rtmebf6X+vEWDekNU30q0OAArAIklFwoYQsIwwXSwceuPCFXOVMoW/ijqYJRalCdO/m/vw+S+D6+vBqIUu7yf3/5/L+wzoIDEr3qe9Og5MjbPLExKBootyh+QCI2yDMluCTJSlZY7e3loap3Igjvuhp0JNqIWLs4qGN3+RFoSoN1hvP1H/uqyiq/lKU/JZzDDLKnr4m17HXgpNOW2u83UNtQ4zZxVR3OEryh7jJNhQTtiotd4XbhmddAXxF84+rrpn9F9f28n0b1/2yev1/J4g+cj6lkxG08iUZtcp+hMQQ//pyBDh5AASCCUna0MwqJEIF6yM84lsIhUlq5CRLcRInrSjxlVIFTIA0k5LZ0Re0jcvw+nq7Z0ZChKnHzDo0usYOQysGubUPeo31Xr9Uf3+Kd0b5/RvT6P/5//t0t0GNQjbhzdVryoQkbd1Ug2UqDNQaUe4vRn2L6xwSoKkoqBN2qgwmUCHyKG9D/ByvAUlZjnJs3xL9m9R6iGQY0j9u6vW6Owm2v6NnzowIIIKhB4xVJRFrC5EvnTAjWZezFnb42//0sLQdEA76hfp6iuytyr/6p9/p9vT6f/J/9vt0tyr9PQTUIZUMnGmczDLbJQKBakthrOdSEgR1ZPGTL3tAboYQaHGnBugcHJeEX8b9PU3/iL9CfN9/k926CRV6P7fJ6Lpt8V1MjaM3oMzCFEMjpyO1MQU1FMy45Nz/+nAE5eoAAAIVYNzQxxQsQ0o7iizFWYiVJWNHrKsBExSsaPOJ7BMNwLJJTVbTkcMBl79QqfygDtn+1Wjr+gcgpnEgW1vQvq3r6L6fr9vt5W6m+b6emlDGqqW8O1Xr/9vT/vDX4J+nzjkAZiUUig4rL5YGTDO/IivvcPGJVSfAlMXr6BAMrQIGtQCP0Xyin21s/Uf6H+329W9GTVOv///6/G+o9uQvjHVYU1fSABCAYJk/+3je0OCieXd/lqx3wM6dVpHMklmLy/rOGIiqMZu/39W926J/6B77ejen1+3/p/9XVJxnxb75l/UZCIEa/76QAIABBSLlbVmD8jfQl9H1Un9dfMEmm2BY9wQQL7NFwYNTB+f4z8l6DereG9fkFYY2Zzbu/9eHtOmsKUn6qjIRAgsa8ppTEFNA//pyBE/QAAryJBhaqSNCoD/Da0AxIz4IsJF8IYR6AQ+SL0BjDPgCgHl5zYZB+bvUQiivKBJTiLaKQBoRkDnYQVr9YotjyKPhELPAaGggA1DQIICbvLkLUa3k3QsZpDBDc/j+//6rc4y74YYfd/QvbRQywpVzpQh831GeuZQDJOo5uRWOflCDsBhCfSi4OMkAsCADAgRAggJhG/LkLUa91ukMI3fX//7ez+QXcOdDgYd7ioJOLumyKb4oBYUqYdyzI4DcMGgzzwj4g+VnKuoJ4ZKgybMgmCI8mGHuAFImAD0tPvfjyf97JAg9ej+vS75T4friwsnb/WnWnT2lJUr9kgllzGl3mZHAbggyCXnhH2X9JmvK6gg48MlQZeGQTBEeD4YeZKUiynpafvx5P+/IX//X/0JiCmooAAD/+nAEYEgAAKHyIN8J4xJQQuMbwDzDLgjkr30lhE/BGorvFLMMUBP+j5KZtpVtewzRjbaalJA9igTmVorNYmrTmbQr/o9gw4VBIDstZiWMYkDVOmJoi9jRVZsmwxRyLmu2/G9iPUqQ9tqoGKAJPTEnpqryr8xNyjTi1kkH0mqMxCCoKnRCby0FgMFQSA7JJciJXAJiQM9+jvY0VXSwxRyLrttfG1WI9YBDAQDtc0I4wRadp8Wu5vUtqVlsiUaUXOHViMinrNnqZsiZS5dizBQgeOHC1OX6itVlk0bTQ4xlQaO3jaAvRAdAiedZPmWFkXlgvFIoNMlnYsU+h6ocrCgYxsg2aHtzXCjRoGCQo0pJn0Dw+WULVYus4wg5T+XuqRVZzRvQ4AHYhBpso57AfcUmaCN22xKYgpqK//pyBBfaAAISAANdwGxIAEAga7UFYgAItOFwoJhgwRSR7hSTDFACDAADoY5ClYZFQeQHmPBUkVLLACIiD5I+ExgaARw+N1h2gUbLwl4GVRpes4MRQo9t29btpZvKpegWYz3Iok1KEgIcIrJoQDFAMVNBILtEpUcLgAxEzzAecMgI4TQ4mAw6WiJtMZapIGGUaazikKRPbVxamt20sS6EvqYr4ekJZQFE0KJBSCWjviiK5DI9NFRpKpH94cINnYY5cVkpHzvCH7wqmbcszlvC+ZGZ/M6RstMvhjFYuxihELo42/bRm/Ov/fQuB7ACAk0IzGpVIVMFEd6Nnz4KFKqw/UzOEG3KGOTdhVM53ZT7ZMEbeNFTzVOFEPi2WO7HOZVFAq52g6qte6WWXoEsV76bnSyYgpqKZlxybgD/+nAEJNcAAOHWGFsBJhkgQwKbZSQiVAkgYW2kjKzBEpvshMMJ2MSkmjDy1w3BaXxrDwihgRYP+Gh20gpFSsHEpUNKAiFEMYIluZe5SEpYVWkRmEHEMejK6HbHzsRfs9GsCAH4YLilUsaRnqcMhvQdRnBooWfcEatgYshB46Gg2l1R3Bo8SLXknHmNfXCweMlGuBpoSTO2ogZSRyKiK1K1PiX3NQBApIJIRTbqWczazGOno0btUjaecdQ4iOl4V81pI7ywkqIlmSNkRPfaISIuDdFrCYldCjWotL5isBYmUrzZJXLFi2hCEPCh5SP8rugcJ1FSKDQc7qzCbNW9hqkLs9C9OcCadAUuwR2epu1PQ1+RVUnYxl52opksisjlXyVhShMaB9JW2hHV9KK3XP79EYmIKaigAAAA//pyBHnWAACB9yhXgesa0EPCS10ZBlYIOF9pIwUGIRUMLGSRmojDzZyqkw1Q6g5oUcs+hw1RzLCTwKkZQpBib8qIzoShuIESLYVRcuHnST32WN5czC5Bqq3uRpPftR+5f/Z/T9AAAEECYKTjk6B06eNMl9AYqb+Hj5Dw+Bm8oNl3AoMcnmEwpcylVQaqBm5hsvUDaBzXWxiTY8vAYx9H3V9Nl/r6xF0wKgAWgEIuzloIgp6TqQ/9ATR3aQ8kbMkhT70E1+q1+hKIhq2vQRJb1TC2WIPpWywm9ddR1+69+JNAsWft/qbofbS9AYAJVeo2iegCxJEeGAZNZ+oCbK1KUpEROSODsXXMY/OrengbsRVunp05N60CxNh5VqntpuJJUU4zZMLX2G1fUi2u2mSdWmIKaimZccm4AAD/+nAEZi0AAIIHF9eR5llAQ2ZLFjECXgjUX3WijK6hCg2rAMeY+ABVr2uVrQrwGKHUyF+m4AfCPAgYK0mIhGruKISK9GpnYgHUlNE6BxyBZphySbxqnxjU35Kt39mnbchltDDbu+vSBQVa/0rScOOQxm/aKhi8KGOaUYsaWExtzEClfFvKVwCi520/slXI/0/nqb2VpnT8etDlDXTyb3NS6KVx/b27atvyWtAFCXGSyy27y2Yjjn3ZtgPEhz6NoJbh8MIzoHOyC4AeKNeGAoRLC51aOSCRSkcXbmalQHZttkJQ9kIxs+2Fxaim6d6nKJMSsIPDSqBmLxecT1BhA5o1cq858eDt9vFkDQezPnOsG8lZGbQA1slIDutow1eTlmIMERYpDhdwiLKEd7EWsfSh1lf9SYgpqKAA//pwBOVJAACCJRTe4EMpPECCqvkw5aAIRGFvoYiyYP6V7ahhFWJgJmOMtd1cXNBI5DmJEhSxQpxm9cZthbWuPpE1AZziWBmYA51LJE0bQfrJTrHiiyIXuNTbF3Yuwu41TS1my1RK59W6d0gAQAANVMFrTryAfQqKrAYKnsmg6T8H0X2OiJ40dWkLi1OAdglCbhlanzKb9MXJPnJhqKNKRG9n5DNYv/X7b2/0AAAdRBJVyS/KpihhyrAQWiPHOPbODwW2JfwSnFMYHVpQ8Hz0LoKojRHWDSqbWsyMkpL07CC7t2Ratgpt6r1oX6vFJABMTbkaXzAIzEO4cQmwfWo8OsM3l+CW3J6cersqyKLD+e/bydVEkMSmVCk/pRrX8ro1hCJkk73IrHuw1Ver0piCmopmXHJuAAAAAP/6cgSgqwAIghUaVgsMQsBChFqgPYtYCIStc0MMp3ENDW4kkpz+B6bt9pI2Orjr+Vaj5JUqsnKqd12qGL7jk9CfK3VVgfP5wwbaTi4rfTiGdMCAtU8NmSTG4fQZv6BsZe0kjs3Va0fbZsp1eI2eYj4sCaOmGogexF7OPhyysFhpSQhKN4gFvvxbB72PxY23RjvN2dPJa1fdVFQ939omypfL4kL7VObaj/b2di1ElFAqaCAAhAKPjRwInSsiZXArBWAhqaD3aMD3Qa3s3mfVX03RsnzmzDWMvif3NR78V9XMxVGlbK3KUAQwmxxlZVd60SWmW9FBIgQCFupChpTkVGJT0JAEe5CubxMTfiFdZAsGr3vPJhWrjBYTnb2pWNUwis1sp0ZrY+PvbIkrznEbN+5r+VTEFNRQAAAA//pwBOjsAAgCDytXsy0qwEGDSrVpjVgILHdbLKTrAQCKrrTDFC4AgBf5NFWI5Iw5GIDhDjRePYy5xTR2c0LFrZyoosPjKFR11oZswP0CI/sZ/Snf071b03KNUYXcUx9JNG2zO7q//9oCAcbISyjwSTMAWoRRUdGw6PSseEFqPI1kWbXzgX1Xp8Cy1UHTR8yDM6siqtYyapQYsS4Yce3c4qeQK6Pk/s9bvVAAA3mkQeKzVGDxgCgJ4SLm4qqJ/rpCee1weAtYFhbhZm6xodW42pYQnpSvytdmZ3yDoKzfFNy4o6nG04B2ut//pBCQgYARaSTiwDRgfgUvW6HS2dz5Eerzt/xMDLGvrrQAmhlMOHnEe+c9WaQSElvIZ6g7W7oWlSHqAWccQfuse9SYgpqKZlxybgAAAAAAAP/6cgTrbgAIAhpDV7snEvBDKRvdKMcNiLx3WmylqsEUoazphhyiAgQAnJs2IXpcWFRERnv7OU/21ukptRKW9wSisOYLrW4Py/QM9hSLl6v6fb0a2GfzfK6f6M/RvC2/7ereCbdh/P0/5IIpCuElpppywSG30g2y/Uga/unrvMeJ/n+PhI2yn+r+c/t6MnT6fP+3o3/mv/sreeQ8eIdSL+TPwPnq848tOPW6x7lgBlNWouEcty5DpZFLKl7umEgnPul1vmcPy0hNVhRlr1OaEN3mQvtXTGQz808yW9Z5agpnszJPqd5d44WyWHNu3fW+O+v6AEGAKDabkmCiuqaq1WkfdwRO02V6r1MirA0Z8WjKqsfZWqQ9W7Hk33HC1aEk0pXX6v6N0Pfz/V/X6N1N9B/Tmcju2r6TiYgg//pwBAYfAAACCUPZuecS9EOrbC0VIsGIxQ+FtGOAMRigbPaecAQDgRaTchbwatpqBLFq+PUnJd9xafOqW8DS/hR64ik0RITsuq60FkSWxuf0P//9vK/35yv5ele6v1i62VnN/3169QSbFnjUtccvOOdpRamwvWwIL3NDPGj/GP4W9KobZ35ErubC2fKROvz/f5vRv/v6/b0X19o/k9Cej/X7+u1l+GZt+MYsMJmzWOyyOTvlf0hmfnCFd7DlzCKqK1H0icxtBBl3HGJqrKLT01KbVIJZTm9U636t9fT9/u/T53VTvUzupJvkP/XWI8v70gAgI1AIxpO4XVGxLwCgZrX/Q6Fr+7Oclig3Yg6iEaNxBufHiarYHJ/Q7aPmIZVDdNPZ+/0N+/r9H8x/T53y2bbZkN2c9etMQf/6cgQ51gAAAgYwXgYcQABCxfuwwYgACPxLd5xSgAEfiW9/hGAAYqonMCpZWWay9G0da6WS/L0p+WlHVZb+5jMxrOj5L8rhUIpjGBOGyPkTLEnTahYS/oUCIQvYKJR/tkJRzKVPHDMFW6VKpSy+No9wdiSAr9elKeWlHVZf3MZmNZ0fJflcKCIpjGBAUc/qNDoFS8Qip36HAgCgolSiJo5/XU6GCm8iRIECAIRO16Cgo91CIs9VO+hgcxkFyAnnboMHYNuILlieNoIuItmrKwYCwkFBFBUXU+JEHhcAMaLVJb+KPTYH2fWRYweVnWYqofKggKYMcGeiJSJVQ54c4yLV34uql2V9f0r5THBvPSBeWayNoIuItvsrBgLCQUEUJi6nxIg8LgC0WqS38UfsD7PrI2DytzMVUPrA//pwBEHeAAACHzXeeKEVwEOmy60EIgYInNdvhZRLgRWa7rRTilQRATCDYy0aJRToQziA+ZogLMlARbqMLR5PjwSUwmFTI7hOvyORWUwyl/PE6/p0NbhVKSItf/2iolGu+oXO5dSxd1zG0gBMVQGNIFFKTcLTwxecRm9Xo3mGftZqkW8q2vfRVBJdKl6fy1FPb9WdDOyYWKkRx606+v6yQqoXDRIWT4qJX59guS60AAMoAhTVtunWFRZXyN7IkSANpXQf4wcmoW3m9Bv/J3WFRXdkejv/3VqP9SP6LAg4d6hLqIpquWd3yvXtW7DS1ajzkkURiIS+FxNIEst1jCnXCx/RaFUZkyjdRWWoeoTd0+r+3dYVDulHoZ9+tFsyO1dSP/FXeJdRFNVyzrJuV4/at1YaWrUeckihMP/6cgQiWgAAggtMW+DhFpg/qYtsDUUzCP0DcaakpaEbIGxkyBzIEAAxxGOI3KKVcXgzaCw+fUbECKGFE8oWtihV0GPKFvRvEvE2yX6/4P/17+D0//94rpX9+pSJZgrqDr1P9CfSKP0gAAWcrOkb2hVxOmDg7kBNHM91iwrmhBk1DPGAv/p83R3o1y+b1b19+/Qa3/7/x/Sv5tqpswdGsQ7f6PUwUeyWQDYx7AbbcjtO6xVKv38VwuHgLE+262NrGDvG9BITfM4mnt4mT0fSltC/9melE52yrNCxKYtEp1R9c4rULs12IRPfr2lu+shXoAH9/tPdqNL7jPBqqbjYf3YQknKl40N8gWTKBjzy3n/syXNMWh7qqoURF2Wrs2iJ9NvKt/X+i7kX05sEg1RPFO6vlq+kh0JiCmoo//pwBEEuAACCA0DhaGYSXERpy00loj4ISIFcrDBOwQem7TjGlOyQGGrRtttpubWaj8fmDdbsFqHG8/Ir84N9AY7cQ+hRXoTyt6P26MZ/buhtH//1E1/63T3BWM2j4xdZHX0bmvr9IAAFRAAjkktsnlnCjUV1goDzWRHltH9Ct5s/lbcEA/E+FEfbqcXlXZLlsluoIdp3X9t+o1ddf9eCf/60T/oJ6am6Tf5kCAX1ITQxGDCCz9WYryNEjbX/g9KXznW05NHG6clGNPy6ZVNTidVMB9VZ+CboLPJJGiIxoxsa/39Ula3/1f3u9HWRkDAIao/ZrWwqcfekDCgcSyA95FPVYWPtMjrjBT0B/VuzN6ekrpI9dfc7at87/kK6sqWN////5+2h3Ud9xwtFj3tSmIKaimZccm4AAP/6cgTWLwAAAg414GjBPJxCRut9LOJfCKxre4SEsDEKlesVhApYUKg5rabiabnttwkM2c5wZMj+GTlptXdWubekiftBL/zhayUMz53/6+T9fX2vQndXUaoRVbqU5xGbRk9BpND1T+yxgACuEptOSTMej0blt3yCxflBTfE4svlX8q/Hgdn+L33Nb0b/78/02oKuWv1pZHoO8Yl1p/qQtHSPVpy/M2Jy4V3NSCIqxLddfeXKxtmt/GTVpc4jm9WaXk+KPVogurhq+LZLbQ+K6GjQK84ALEPa0sXKIeC8yejG+pQwTxw0kQP1IUWIKj/yIEAfmLDo7gklu/r5Z5ZADNrusOquvfz5av3dCPyA38Zg+XRwHTe+EUfcLfY4jkb53bl0rvMFKSXfSUjv6jnq+N/2a0xBTUUzLjk3//pwBIGaAAACCyxd4Ek6PEEDqy08x1QJATNzJRiwcRyWLrRjlX4kAimMzVVanXAR5ugswyt6NRx1CpWvHm8IiHiT5w43T6/OfnPejP0d60QvmsSPUw8ZOoa8yVoXq2IISUVd+O79HeAABRQAQrJdpHtZ46dcntc2CBLemLBNRvB7l5xfws3im9Xb1+VdPvUJpZ66ahHFWan53sevp0ZURLTrUv8/v9fyRAljq1L9HSGA6rWBdLZ4vH/3vdUhSN8KBEug9/A6e/SO6u65BlpjunctDOZKOq/Wvy6e0U7f//m7ucpkZDDhMQiqwiUHm5/9JISBURSSTRUZm3lDh+NgK3QHuOLLuj5etkDknOIhdGNKh/mt41vZ/N6p8p0uNBmIJy58kopNRcQnP/V6CytW6zMOuwWPKfFkwP/6cgSDZQAIQf4X1gsPStQ/JSrjMWdYCNDtYUecVAEhlOvc9Z1YAypKZbqeGZL8vN7QVzCpa+aNacvuTZQikUiVyFDHnPnyMRWSfEkD53g2k+FcKsabyL7Nlra9ZuWGRI+Wf6fsvAAKct9kenqkZsyds+AEZ16g7pvmjak44CcUjcMpaNtVNBy/dfQ37/denyipj5N+9vDv3xfUd9Z4Zyo5adDfIQgACnN/4GL0Wyto4+waLJv+Go6e/gnDqSfmaWuOKwYmCALohQnp9R+qvq9up/g7ao//Uf0n/4XF2Rd++Wkq4kNemwP7Kf1hEgly/+OuomShS54Pe+IQc+ExOz7QHXRw+TCZ+NRhEyDdxB8zzi/RX7p6r8fa1+7D1RiWvK0dvyC0DyEwS0ihoAgN9Rl92zYlMQU1FAAA//pwBMffAAgB+RhYGw9RcEJi/E0YZXOInF9nTBjqkSKkbmjzlX4AoqXaJtgMBEoGdqOoSnobjOF1aLaLHJJr1teJn22pSP1nhmOJxF30FVt1ffdtxlQl2ZPsuz1O/VoYtGj7P/UQYzHWnHJZd+0ZphUTnvZr8Yssg/NfifoE96h/Rk9tD6ztQZaXvEGvFajWRgNuS2UBKKmFqDRIXcGQSfNPsdZkbUbEgBBLkkeNQ4XtTUb+yPtrXU+Vy3KBUlzsj4iAl1CF6s4idFJbMlnanbs+eCr3F6Bc/LLPiUdZmd+ZqfErqG+cr1nk3/0AAdoimkk5DO4RKm26Je32yE2SYEaF9Bf5X1AiMroDz4RP7eEQeyRiJMg5ORPT437//eioreQyrb8/qXzfEXJMIajDFWt9b+/oTEFNRf/6cgQWtQAIgg0i2dMKMvRCA8tKYUI6iOh3Vk09awEFlGw1k4ngAAiAExNuR3B2TbWMI9PWdb0pcSHvh1kKMfpiMTej9CPxeNG5TtASW+SbJJr5gaq0nZQdE2F9m6UMejK6Mn/Vr0d4AEQAJJOWu4Kue7DNmcVvusC/PuMjmdYprhX8E/QW3DiCcjeg+V2bN+6vWd3tRoze7G52JxVShhheEXyaVOvOep1QAP+KNDqGVw3Yyvh1pK8lWMmaF6pfBZkiki31E1JCmwGMsRqc0yPNttiZWpxHIF/5/v7K3eknSyg5IfdUKVASkt7fv3f06NNCAIGcu2IDAOi4trNLWNyG9ucS4qXt7uOqT4iA2xiDhnmPzwn8Gfzt85ZiqYuCN/42Sw3jcypT6dWLYg7YY/ltGxMQU1FAAAAA//pwBDHsAAACEyDZawsS2EMKy1w9ZTuIbHdztJQAMRmrbraSUAYAABCAEBkxzFRShFvmUEVJ6z+adS7PaFj9U4oW5rK1uuCqvBi/BgXlfw/dQ+t+6Q+za9QSpOypX27c5u9WUyGQ3f1gAAQMkBVLCkG1HvZIPqrRIG4zXyOs6FLI9vaA47qLvwsG9W8v3fqbqZ/J6Kvt4z7r0L9PZ0//1/+3q3p8d9vGDaP9oBKELKSLKScCwtV625ScICUVt/pIzLhBIvNZJkclgrM+BK3c+f/t/5jLNm98s6ROUZ/PGla2SyvJ5n6a9OK5DJPnv6gQCImSiWmlKTCym61DcrmB9SHXWVulcreHB64W3o3m+KH5z+V/N926kbh9vden1+a3+v2/9L6KlLnq1A+7bjkbcUIQY9eKJiCmgP/6cgQAVwAAAiccXB4koARDBIv6wQgAiLVrhHhhAAENmS/HEiACSTSbckkkABku2NtB9wPPe2D7BQ9KJdzDwtmYTyVEmZcyNW81vKjDklxERQxkhYxpw6aLFhZjRdk6t5Bcn+/Sumw/6koQCABTK04rpLN9t9gJvM8MqwbW7HcroyXXJ2vPLNF2wyFs1+6blcdiD5G1yngZW1rzh2aNCFzTj9Udp9ht5VSxJK/P3gBsRiQSCQd2k8Ba4XSYr++llCKusjItv//7f3J5aObR+cAABAtCGQXQ3XwM/u+5HacGv/X87td7IJmSn/5/8/mVXQSsLLG22qqiuCWWG0URrbRzRZhFXPIVFVtffa/vbL7k3lo5rI67kABB0IZBdDda3Fn+kMwvrd60JeMOhRX7+nPNEMuxupkcmIKa//pwBBFRAAACCBHdtzxAAEOGu6XoFAAIeNeDpgRHoROa8HTAiFQBAQKtIrQXkaEuLOXrt/Ai6xjSbXgxVSy4LTcmWe7pKuS9qPDiyIGjn56mXYOY1Espny972sKC3chZnJLnn4sLagHUWcICCMLykVHz9InzA1QqUmysUJi1YJZTI3ejUfo/6s95W3NVLf5mre/R/m8fEbBzBZFKv13mibAILdyFhnrsfizQDQA0wJY20qwK0Vcaq6WiWS4rnnXP/RtKLB+/ql2nK81Kdd1qNpb5nRzPaMpCCtYzX+XkxasNXdIDFkxGQUGNRK4WQwABhfUl6ttusA+iqK6yAhtG5OM+g3Xp0bQhjwaXn9UQW05c1Kdd1q3t8zo6PaMpCCtYzX00l4PCzFhq7pBcWTEZBTtSNqYgpqKAAP/6cASZlgAAAgtAZuhBFqxCiAtyYWIuCKDXbGwsSUEWGu908IgsDOTmkkutkksh0qMJXdGwx+W3qhez9URHoDme7Zr81M1NH7hX1m/xaXog6N8q0mN1sDcdxEkSrqlG7ESpX3e1UfNgVf7RgAKNyypKT+ldF8GXwz9+yBY7ooO9n3gqc/o2r2vlaq3VqX6t9rq7X5tL0QdPy+Y34N3EUSleU9EAlfd5JUfeQEpLasoNrSRrN9YXlGMZLYW/M68wg7vvWcEx2QDH1U+9E/5UPTW2b6H++huz/ut9WQfqq3GziHtyMcB6D7JjX927d0gsAEAMSlFdpv24RlCQGg4TVwgXktDCEQI/FvrDsjZCdfI2TdehOT+e0Nyy+3f0H/2mwxi+AjIoBwGYPirjC5hQpZd68UpDaYgpqKD/+nIESNgACAITNdobDzgwQ8gLd0kihQhY13FHnEfBEKbuXPKI+gAFHJALkfYzR3gQhashUZHJB2gDHxHFBOK8QBCA5ajoz3Ib0F5Hq3o9dfN/JfIPybe1LOzfQZo872571py/vr5b/SAFghRNwB9g6C258jEJQuZEq3NuX6ziM9RRSvzoif++9RQXl6Ne387eqe4zqhB30S275fj8nv+vh3fCwHRxd+nbqZZ1hAUDN/+DNOfddHNNUIWiIraCdXkEeVeUGoc2IhfSzI2Q3Xxr+nQ5//roQpt6ppI31BLENbLjud6VHVVEFk6fNbGv3opIKbjkDNNOFDtHm2H9gt9RfkTCKxIQFOBX8m9BIr3wQ10fdtb3zH1qnkeq29UaYupmk8jqUn+X/9fX146WSKwrzb/pTEFNRQAAAP/6cAS2nwAAQiAcYukiOOxDxst6KCLGCBjZc0SYSxEJG63MkoliNEBqsaSkrktJGR+ozpnAxPFCKAT3CpehhHkvvvQ832yhJ8iakSxUhic+MMrPhYSO9yvJhNT3XbzzIARLsfXtfwao5KkhAAAAd//xGBwQpc0PZw0NjMqO6jzk6F5j5AOcWvn1Lya65K/vYUzhRdnc2TjDdmBW74i0rQCIrvq96y0nTPfKcGv3KAAjgApySQoQu/JTek+8KOr9xi0YIqzords3ifm3zBudtBQZ59na1l5PstEKEfdyk0oR/QS4YsTt/7BWW3a/X/6gE245CgldLkJ/DUsGGDdALxS8z4QLxvtUejDcds4kMKUepS3oXun7u0q22+kj2VZXQSfbv/+JVWxRzNbhH0sRxJepMQU1FMy45Nz/+nIETaUACAIWHtrozzCwQGkb6iAie4hUYWzmHElRHqTt3IUI8gAAAKAErLbaAzTJsJA+0dM3LfGflEUqVd5xAd4aP+Fb2zhmFmOdmZ+Jz9olekJ8NAYzTYU1OoY1qssr//dvto/9f6DACQIDbbccoY+MvXy4v2C/Hz5Pj+t9c+DfVp28lXz5FTvmV/6z07KKguVERmUvLKi037NoxxS40wtvsdYuy/7E0ACTkkOV8XMBMROGr4ABQhlBlnjkjEBeFkP4C/RqjUg+o/e1kNYa0LJEpXYEjT3HxLIn1HTN91kuhAvERVTlff3/uUQQC5JaKwloDxmHjwwF3NGHJJeY+RCnp0Qv3F9Or//M/cn3asGhkZA+R5qGI+rfS99976f8+k8gmNOrFmRMEi5xp1hsZ1SFKYgpqKAAAP/6cAQOiQAAAg0227npKTRChcvaFCKViKh1bOWgRdEKG22oJgjyAgAE5JbiZl9SrHdBeqC6Tvm5yC8JNEihvGP0Ha8Z/iz/VOa+R292ok+rmbyUX7RNmunkmcUrYrPCvGILAa0Wd9FpkDIIJNtSo7NEyxPC0bQC8/GZ32uWSgyguD8f+nR6qQW3ulM3hNBRpWcF7EEv16rSTyaKxyEBiww5TjBybRELnG63oAIDbkt02ueKJ8BAuBjDvl/zChPlVuaKFw3Ui+pA/8GAESdLEJFBYxoVPrKbjz3YmbQ2nu3QFWoXnHgrU3MPjA8u9TtdIAESABJyWrE4CPMN8VL1Ozivv1Zk8ZIphu9yNqiwTbF6dB1a/Vv8jfWm/yf3+eDeQX/9GGlJKIAaqRZdElGtvNX8DJiCmooAAAD/+nIE9BwAAAIKK9zQwiukQuOLeg1nGohFF3DklEuRGpdrqPOKkBACAALkt28bbEF4S3ier8WS5r+DGE9fvtVie2pTvNv0m1hIU/tUUx+hCFlYR3OVl9b7nxpAisbTQ6MTU6L3ktTKQIJxALbltrj7gUWzO4HlVvqmzEH2hcWoIhPx/5eUarv35QQjWFnu1BxU3nPWjWeJKYhtmKOhPOglGEXxgXffod+ttagAEnJdqjq2B5ixnOIlHajuIq9MLIL8nyUaohGzv65dPNbWX/sOzrUM1JS/ebTX/X1b0fw2OVEx2W8BoigOZ7fY6gACAAAC4wGAtVrsgdQeLg5WVlBTPsfvRmbrd+3rNw2XPmdFjtUCG0qGIKFopGhPiltBle3XoP6L9+wZugJyhbSiK73K7t8smIKaigAAAP/6cASbrQAAAflYXDjHEgRDyMtXPWIoiOlfcOSUS1EerDA0M4luQAgU3btqCTWtWgnhCHG0G4JUgss2hhHno+c/Xxkf2Tqvo/s/29W9rf0jy9i6/Y3yfPyO1bNZar+mtviL7/L0gYAJblttL7VGWdgMnYeUK9QgeRREQOrjC+zfpwpuh+N+idS6PT2f2G929vZL0j/LVn/FNpAPYXhxpIoOU3bPDazm/y6iUQ5Ldk7luh+MDcuNBbYwP8TKsKHRijmuAwZqpcVkb+CAY8lSG4cQ/OtW26lXyiOy//TbP9/t6N6dnPTlTsT1b01weij6CaYIChCaTck26yaj99kbKBF3tR6sX0GRhLqFpxDdfGv5PQj+v/WXyiNGZ90a1VT6tt+zfbyP2KjssYd1BsSySy5jUyhb5xdvrTD/+nIEtscAAAIdYN5Q4RX8Q6x8DQyiE4hpX4ehnEbxDpwsTPSIunYBAJKSbmKnCggWLDJpuVK9Q/speUaUf1LZwaxv1kzUeXgLmRf+Yvr7X/o+D/yWpLieTIBLiL19YZdGBOfn7XZ9BrSZgQKZSSTckvhBnjA2TLbQB5EaZqK/DtrJXnfp1a1/6E+T5PUV6Ceh7Uqr1d1b2/5v23VPT8f/urJ0bMa/Y+lbb2XODdwYItIuOuXXkm3GHTZeVBxzK8zUfw41mFNUPsXh+iOJQZ1e+ien7fE+n7/6we2vKjO9QS8hC0VVVU3+3//9sI+V0bKgAUpJG6FbUAfRhwFraThc9/IJf8Czhjpu6xG1xLacG2J8/V4mbQ/teQKb6/G9H9fhbcLOLO9okfnZd1OhFOjIZHdu9aYgpqKAAP/6cAT5iwAAAh5JX1UUQAxDJHsnpJwAiKwBg1gBgBEEBm5PDDACZQZAIxuS1DspjtXMNfEAB6rq1H8HyOB1NubryB0ZkoGMfMVuQ+39E6Avg+ykm1Fep279IL6/a+Hrg4mHYDOqnN1f06EAAApSSLubpkDxJgMu0QB9j2uamQkHlmNQbmcV/PUqQY85Ob2J2m6J5PWf3xA6rKnogTFkwH99rYo6tG7wLo0bfvwkCqAwDU45ZI/p9B6VHggJSoqMcPHgSLKPgQCFDIjApQELA8Hyzj5ZECtm0voZjKbxwlDZgZVp0pvfclHvTeb/2oQyx1yLgQ2kjaaEK2Lw08DAqYmmLGSiUukzHMd2DQFOGJtrjqr3sXHvQtZgdcoZo3pSPKodnjTX9BMiQR+m9N/9caMq0XITEFNRQAD/+nIEx0wACPIdLF2HMGAAQYWLsOYMAAhk13cnpEKBBxruAYSIYOLgBBEIZKWkhWqdbOD/vp+wmGRPTCH/w/45Nel+aof8yXlbfu1hfxSO8ajZ4Rx5l73KshFj9yTPfQKqvb/czUSf5ny9CAAAOhDMlpIOz53Tg/76XNgFDpHXQy/Q/45H9Q/NUP+evK2/drC/i53jUbPCOPMve5XFWP3JM9+Kq2/3dRJ/mfWKQqKtHFkB1Mw+ms01MzsPmds6NWtm/+npydC/ZipWVCdf5FZLHT9s/eLF53YLKkCa+iNcLJgmR0rw1myynviwsLHqaMYEUWh4TxDRMRTkTwayYdln4V1O3r6vr05Oi/ZikqQqENIt/kVkedPo2fuwsXndgsyQJr6GjXKTBMixKV7s3VftTEFNRTMuOTcAAP/6cATM3gAAAfY2ZejBE9xEhsxtGKI/iJiHcSwkQGEdi7A8sZQ0DUrvmssjaSfOSSzmzm/KS+SBdMc8KXB5hO5hltdfS4PMutP39B0u7P0N18Rc8qGsNOs/KKceiIca8qKc1V+oJJmaN1tpElQDJJTUyfIEha0Cci6PEe8BQddU3qWm7cvpMDqhdafv6Dpd2fobr4hHPAoaw1sfXwIUceh0ca8qKNzVXXqA0AZTRDHGDRRhhkoQqPOCfjd1NI9yeO3i3X06fXdZzODDUKih6zJyep55CQTY8AopALsijx7ns2/kuSIjQm6gLBRAdc8CNhBHMp8+s0vCgGQiaQWXuCfkvddAaMFG4DD+q+MAzAU8L2CVyVFr+9ZrDpY+ZAgWSVOnaCWp7vJJU2X/AJ3WMNIJZ0swZSmIKaD/+nIEJ1wAAAIfNVrTKShQQubLnWDCCwh5YXmmCOfhFKBs6YWI+AIAAILkclGNGggmKT4J0peWWGN9C9lFIU0T+X1Fq6FbrxjHyd9Ua371ylV5p+83Txiuz2j1pTjnoElCirvb1k9Grao0AgBGAC1JG5SCT2kwC26xX4gQS9G5VemdvCdAYbPRi/6cm3WyFdOrzq5ZRSG/p08EP93aXWlOoVtaaUVd7vTRwztUPADAO6jT0m+4EhjHX2X7JhQTYKvtcaUX5G9q6Hf5RmzVq/f/6e5D/pavjwbWbpXzj9aGDjrZGX59Xp9jPtrpT/L/Er6QACAYBLckNZhbsWnb0xfpR7qBWbV6Bl9lUr7qzFq8cEMt8ao9Dm6+N31+3/pc7KIbRvr/Qfb2f9W2CPozLjnUzu/f7E9KYgpqKP/6cASyVwAAAhw2XmmFEfg/yBs6YYUICPh5ZMecqyERGvB0Y4j+DDAFgbc2224pfXZzD1VxJG3B+a1Wxfwn1gddAN/4Jk+jNW1LLuVUfgzNO9O6kr6gUpFTtIHy30N2OjKn8J6xNSnXXpAA0AAFuSQUfCoZeXU88roqCAEzAekJiJvIdOFn6B+pKOv9FT8nIsvf76RdpV7dK31NpbT9UXiT+9bPs/4PnvpAQBMNOAPByeOZvOsoZ9iKisEcqJuaUIxS9gTbUBQc+oCOrUCn7E0qOZqnMY9FchNIWfjwx1uv9g55r8ilKKgWxZ0NAUVrBWo1MhtIxNxtuYMHDMfKO1Q3UXcxW9LNhICa8j2w3r0dG/7yorKz0WTkVsqe7L01EJEbx5VbGkUtRfrQEjz5w927cSnb+hMQU0D/+nIEzbEABIIfNdo5jSpQP8L7Iz2HCAi0YWBnrOsBE6xtpGOI/0ABB2a/CgRnpVDmgSryHYfz3LvSm+8wI/jB+iEbxNunV++hdVRPSq1E+Y6/X1ufwUeqpYj8n9S5141LH2To0tkHeps6AE5ZaTAeZvrta1C1zgWHm1BnLqP0aPEhbxAX0jzJqPs6CBaFIkIunM+0Oiz3OWRDOVmqPs/fPdzfMRTQ74cvaAA1JIhSYUsRNCcpeMWHNCYgq38dUbySYpal64dvhQvfG7T8VDety3vdqEWp0QWAt8ne08wgh7EIsF318OL0MAlX2VmtOsgAVQdYLuUfnETGpmpQJ+ap3qSfhbpBteoAfm6HvLa3d0VNGokj7FQv9kV/x+b////1rVG7I7ran9NG6ixkDTX+O274maYgpqKAAP/6cATetgAAghEpWzEnEmxCBTscMScnCNzfbMQcR/EWHCwo8p1gAQCqrlSiP2gP4IpS5V9gl5ylqZV34gf33oKDdOr2+3d/r8dLwj4cBZjJ+HjfYxg/umEFECm+vx5GRCtAiwG5Q16nAAAQgBFqoB0qm7rgpF9CbWhs2k/IcVDuVyqC58VFkeatOC4h1P4y/vTpbVV6KNrTzXaiQUbJF0uOepSMxi2zZY31CKAlW0Q6x4HQoKtFil9BdyqtP1Xws3vj0Cl69XRpGdBXoy2qvcuqoauvXd+qpMoNxZdHIvkKXMMmVWtQ9tAcKHlCSzewk2nwAAm7dojc/tQYDlyezaMgwo7oDdSpK6hYKTs3lsnhG/8qYY22d7W6+5u6qnX7buqH23K3h7uufuz885FQcLbtmYfN5Jy0xBD/+nIEwjQAAIIYKWDoYShcQsL62j0HVgiYx2LnnEtREiZuKFCK5m0QFU5E5JJdAzGhKWwOqivRXtsKjuHgxP3qLE7fvfMvXd9/h6PDy1o60LWcPHUvijhZT5V9JZZlzwmNX3ewjT1tA+sACEAACm5GOKZTZCA3HhECkn2PM0tNArPMuJsgvLAi2gULeJUqdQFGyMSsXdn3z2eYJ3V1LVrLCjVvq/4rjtLH+xOoBBAKackizEsskze7IXCuQUIjuNuJyrxxp4cMdxjzvewg/ToyJNp4IP6k+fQx2SpFbUK3RJettQZ0+DFKqyz0n8jY3v6uhIKTScGuOdgHHQ/iou+4bydNBXw8O89SNfzZOWXgb5+QKEQA2X5IpW+bBsy5PqnlfXfSdqIZ7vSOIQzF23JsezuGc0hMQU1FAP/6cASIMgAIAgE22TjPOLRB5ts3PEVeiL1ZdaCYozEbqy1oZIiSAQACm5II5y7jtW5EDF4+hMnI8oVJ3aFxYW463UlTKGkuvRna3bo7/9TbxWllXXNVfXOj/R1FWU4ZHTHVy+rv9oGACm5IG2I4RoZGY/ca9Cij6gHMDSZocSI5RuptoIo/P1BEH+yamK77l6CbPYw/ahvanfaJiFKV+ls5iJUivlE16ZCiCWWnKSXgi8JbyIhWUA3UIg0Lykfn8bo0YQd26BhGk5v/+76CJt6+sv340//t6u37b1rbzEVHmZ9TaNl0Gkg+5NtbFzIgDAApOSbNUToQPwEWyDKD8B4VW9iF4duD+dBuz6Cf/rT/inSiAbJVr8rdX1g2X/l/9Pv9qpcYqtu71DPTnzB5l2JlizMBMTEFNRT/+nAE9G4ACAIMUNrRgjt0Q2rsDRQlxYg83WtGHKwRD6+wdBEUTgAKQIKckuv1OoCyjRT0iUfu/iea0r3EPwj9Wo1S+/sm2xeV+nqcb0DzF1+a//UuvSnf7/v/1b/q3lso6EE24D9I5IQBQwtqSyXzExgQOuZH0TpF66XfO2o0CZJp/yGetebrE/JeMDXvd37Tf6j26fd+r31+3+/qylbxye3kFqwimikphVXIEFp23Qor2qC6l4gbJZUv/UP7DDxmFt7v5aY0nk6uPoL5V9/X7J4t+363VmyAxFZBqdDHdL6hlGj5rbGGmKP1JlDEiFU2U7bbeQ2osTJlToB+dH91N1+K+rF6dEO96suqndqjfQO/Det32jeWjPVGvt1b2S+y/fzN+nbzff3U3vtnpjBswmIKaimZccm4//pyBCujAAACHSvZVTygBECiO3qmCAGI8YlqeMEACRsxLg8ScAEAAgAAS27YrLmFQV1C35px7l6eb929g5xgM4k0RRuHH96alN/u33b3/+vUVP1fbUBMhU7+rKuSLOVZYoqJ6AKzi1TM2IgSBARSTsH3v4011dfycx062fcRfynZiIIfIqejZBENlVv31YifBF9+vbjqyFTsZ5RErhbZQ6g7JGjxV0cD3UbAAAAADAgEPilwoUhcP4SiMYioen9VdHQrlI4gGEYgZnWOhJWPBOkujp6a/////////+jex////5w4G5GnP////++LDmEDNwCUABQBQOB7IZT0gE4yToTaCdmq9GHzjykca7Tb83ZHu+lPfX////7////+hnmH////RiYrB240YwmP/////u5o3FZISBmcBMD/+nAES6sAAAIWMN6WGOAAQ6eLwcMcAAigj3ockwABEw1vl5KAAAQQMMcLAqOUzHZSK/8sjW9htMoYpUJwwv8ZLqJf+8Jx0oUP/7NGgsLgvNGn/+w3cgwQ5T4cAgnPn7P8q2UMr5r/66yQAOVIFRVFNTB9/sjU1zWEamYo6E4YXvxeXUS/94TjooHD/+zRoLC4Dx0af/7DcuQYxP//zix4RB8v/8J4Ye3//ttDlcoBggIWjqKe1jU9VrkZoIum8EGxW9Cqd4yfU7c5WsbNV/ndnm2eNw0VMFhEFI4OioALSMyxbGUwFcq92mi05/9mQM+l0AAP+lAwpFpUs/pZLfHuSuMAmbXSQOq7pmnrmGU51puCQ29C2C4qRAIqYUWPVB0VJFqYLPfISMzcMvdp1NOWv/2ZAz6XJiCA//pyBBU3AA/x9RtdgW8cAEHCu6A8wjwI9G10B7xjwRwMroDGmciZEIAlRWbdR+43Rb4hzUkQ+WzCmZybpTyF95kZyQUb6wdVFVC59KhepZ8GbSxaaN2tTFpNb33O/2rH/r3f6U+53A1aqNxW1GYzsvMuoM0WDItRKDj2MrQTbuDAyCyhFxOG2CjRUTi8K4qA1BtqHvS561zy2Le1M0ju71ybejb/83CiGcM9Xu8uUe2IltYtXGMw6m4Q7ewSDrNSXtcihsimOSkTgyx0QgyacPHOWZaFHY8B1111Mm7XvqcXuaQrbdL2Ooa5s0ev6bNhYuKaPFS61YI4rZx5RmrB4uzO47/H2Z3LrajKuUQAs2dICE06FrizREGseCZ9dbl1MKm7R5qpxe5uttkTuuoa5s0e+T0ITEFNRQD/+nAEO/oAAAIZDF/IYVsYQ2GLxhhpOAg0ZXAktGrBCxWuFJaJyMDGCImEjYwIGYI0IauUwZRYZroH3mSThzHjmsRWYMRguSmJ0NIF2AEXcVAKA2MhOfFspKgQrVQRhryrrkYlb799tgsBARKrfg3FkAKnBpXKcW7xYB1wKEa3AUgOY8RNYixBi5re50S3BdyA1DYxJ02fFislKlCvICO2xFbriWSbRml3pFrBYF+lTIygA6BpINpHc7uoioASowUcMptOjS7kogsjRR2Ni6Cy1LK3HR+hRoOmCKakWNU6hG1tpFXdRofR3S3aW/XKwABesETzrAOMtQQ1cIHqHnljE8EKlVshqgkbaRs9ReZjvd66nRb63WmrblQcaR1GrG3SqO20RbajfMIo3Bqmi0sn2piCmopmXHJu//pyBHRqAAACCE/iSKEWvEKDHA0M43MIvI9/JJRrcRMMbnSRidTRWm6ultTXkRiqarzW0jQxzF2Xuj7IXmuKbdMTyio1mczZTLWYQqnRTxCJhpT+az///5fzPR/wQdU+Cu0/559NzYgaYQIq7I3MTNaTETD1SBHZ6hlpfKfvM9VfntBg06dvCq10iQXFB5BUXJEKlyM7WYFZ3G7frd1csbc+CvPqYhpuztwJRVbpnjL5Rm3JRFoT2tlhYLVq3987J9AnQL5ueOZ2uZW+fg3H4MC4dRDrx7DwsE8s8IeQXWAmQoWtPFZJDP9cT8Wz0lHUAAMAEEMpNzPOTYtM9iZBSrNtc99kFmFsJxb4l/iNS4qfkFiNo5UqHsC01SEs+tTTLg1LcjWZlVXCUUZQSt0OXqp+tHSmIKaigAD/+nAEX3AAAAIhDVxQbFiIQQU7ejGicgh4X22npErBFBatnPYIsMAEAQCUScrQWPAMRXSqhjqLwfUf7spI2maWeGKfBFpYcFBaqiMiiRRzSJYDmwqVLvUEulh9SW4qr+6xSH3aHqk1p/dJIASAAo7bbOXqmDwpmu4WW2+hdgbyqsFhU7tmwL6stUO61NSnRjK+jJd9t+o7bCqGmjTUy2NgFp36d2f0W9N5//RQAAAAAAnJrvnxCqqZ7uFkptnFvui/7udCOscGBPnJ6V45e6Pva5ZZb7tq1ftLym/WcICSFIuhLx0509LPahy42t0N0AQIEdt3xTOEMLQeezxmxe+RebTCPdYAVnCKx9YD3qupzW26Dv0d/1ftM3RlsQecXjXqgIZdeWrOJ6E+jui15oosrMNZ1piCmooA//pyBBA3AAACEBxfSKEUvEKjG8kk4leI0GN3oLEBIRKMbUw3lHjAQRVe6us4SBmHuUUZN1FtY0Mc0pksTaZR50xZPEB1pQ2PAbiFyIHesgZOCgjFi2VZS9T3iO9btiGvrUSFV6f0I+qgCAVZmuoeiw6nu2pqny68ccqE3S6MsNo+ayuWPxSw6x9Y7BGXhYLPvzyzS4iW6WdLMGAFRC88d1gDjab6plzLd45kAAAACSUt23lrSQZpI8w9+FzJM8jIDXNzE0nAi9x9nfO6mc6q+lIwJoPHSAWHexBQYgsVJuPjghK8PRdWBXOrcSntOV09dYJUm21Iw4yjFhtMGiExc6lidZ+09BilJrJ1oRtCIj1ORVngqERPqxVabwk1TZWq4YAA8SARO8qSXnrNOEq3Lu7ukXq/uTEFNRT/+nAEVjMABIIJGNs47yjwP8Mbej0nJAhEZWZlvMPBGhJvKJQUvggAFXX/2g5hi/Kq1rEXjzQlfRK/qPJVHTjT2lbDSU7dkQbfP/ICYO1zEadZVECNiiF7qk2TrZaAYzuRat1uLfX3YAAACZd//LXUxMHdNlNCcqGMh+FUBQAt0fc3qdvkOyISvkyly7mqrHxGTU5KqDwWY4DDiRxa77Orjfdob8r/2ggyW0RbgkSsJ4WYxKr5QP4bBk6l03/KAjg4Ai5ExT+dzXCKxs5hNu2SyW5f5B4oMaERjzp+ckI1UP3yatlR1t/06NlCKTKcx/04Pxc6TBBFbbY+wetG+zuIO3GAfldS6N2s+rejWHOnZQERU8NUcNMFHMRpvvgzpo1y5h4ZLXOQEnjqqjVV62aUxBTUUzLjk3AA//pyBCSRAAACGC9g0KEU3EHiqyNh5iwIUGN04CThsRYlsLRQi17AnA0lJHJk2Gi1jkBWGnK194wfgKgrHXAL7H1tVYfmdiPCyKSJaj+CaMe0CzjCfxZyzIxR19En6V8luWKooGIOyo2NABct21y5AjOho6mclihPZPBgpez3eUxp6DVaF0hZdtn45FTZ2QlWnBCTW76lhaT3LCjUiC60Kqer+667u9fSV//aAEFJJJykYOqB91UJ9u++347BQPqRpburrRzb1kRUUCZVhd3PDgeoCaGpYOOK6BZiQXFww54rnqct+0j2bVLTRev9MIRCSTTckkurPHuQ18qpfPOE7teObFVoSm8pYut+L835TQiLRQMsitZfmGYeZiy7RrwRE29n+bps4KkHpYqXNIvuu5C3OpiCmooAAAD/+nAE+eoAAAIXJODoZjwcQCMbIx3mHgjlD4GjhNrxFh8v9GOI7oACWUWW5I5dZwGoP6BESGV/kFL732pXS90Q7RnYO1fLf/NN0LFZog7JFFJkqD1S9NkqplJKbtXelM6i4a6YsDlW194Bit2FFAkNEUq0U+YoZESVw2oZYH7jYe4KbKR8PisxgZFbY3W/8Q4wVN6zJV2VNb7rWJLOoZePV0XyElouX//ooBQISRTkjtxp9VIjpc00tpe2jBGQmvovW6brpYeEt78S++ZxEMiPCtPQzRX/4/rX5TWwLiGhmf91Cqx7liq3DlDtydV6KfVUUCQCgVXHJmTeRfy0QdqZe3mgjU65ut01bzoLyvsUqiUcpzr6uvt6e3q2iMmXpbmf02UOhYYa8ZtuWg20900WQlhZuhlSYgpo//pyBFgNAA4CERjXmw9BcD9Hy1c8wlaIoLNiZ5hPESAiLVzGlcoAFSbDWFdlSxRpBUB2ocdw72S94o8IEX9n5fRe0MyeHK2Jn4FgxkeWdozvIfUxEu5EesPj7pl89XT8ndrVMMOZXrWAEkFOW34y+ZT68R/spuW0oNf8scA1ggoufsCFI+BNulv7/+/V/Xv/6+7deq+z0z2SJcXcBS7iMirSat2itPKtyT30YrmFYGwql+4lmeWDzLk/4Rt2xJAzIAa/zTobOaGbHcirsm/zafU49aPw11dAaPQeNtauaT6mwpXQajzreGZT1fMwABDclt3pRIhhBUspRE9Dhp2qsnOdDcYvMmLvqlHcoF7tT86bq1+dWVBZNBbmbsrSO1qn9fv1+zGRRKtVL1FafgB9ncR8Qv0piCmooAD/+nAE5PgAAAIcGNedYeAAQCfb6qCUAYjpj4J4JQAJGbHwTwRwAQA3LQNdzXEtJJkcE9j6R1WCMXcNuJcvfDn20WhwRMWWsBvW73V2K+n1Xf99wWA4eiUCLJXVlqz0I2slsNyuZs0YL77cMFWBMkcuG7EiQoZmRmDVoFrVVd+nqbu9/2KZHffZLHGGLjTevYnoVv6t7/9X4ieSes75JASNwC9RJ7XG9SdPWAAMBwOBwOuFsqjoxU/Ps6f///////x4SMPxF//4X4kgFwawpFP///C7C/J3MMOEQSf//+PDScs8Zi25GT/////nse8+PyfIAAKBgOBwPSDkK6s+/JSh4//Yz/av////xoQYbjf//EsdAeE4sU///8F4OybmGFBoQ///8aGkyzxWJbnn/////nse8+NyeRMA//pyBEdSAAACKFVi1gjgAkRKXALEFAAIiTGDvFKAIQ2a7peeIAAADAAAAAQDgcDgcC/dr3dB4NSva3/////85kORb/+WcKKTHRJ//ziZA4aCQPCYz//8splAWnEB2f///5pQcPQYY0qSHQwBDDDDCI29Nraxgf4HuIIM45wRHl2T//37+vRkNWavZFeOcQU5RXSlu3dyGIKIM+/7/srUDqMv/9vT5UR0HRM052L9mvEAEBKuJEgFWoY42eTtUGK2MHUK90XC3pyXXpr1v+5kdaNo/9DGSrdufs3b2yv5vqn9PWlyzKjiYx+6bDo6gAnWFdYykEBA/+zk/g7Y7bx9xKvR8AIkMgIXjPMfg320v3Jrfv2a5kdaNo/9DGSrM1ufs3G3CF6S2tnZWpMfDxH0gbmAVVO5Jl6Ygpr/+nAEgZkAAAIKNd1JIS3AQ0a7mSwitgiVAYeBnEyxBprusICLHMAAB+V6vdJoE1ZssM14LyD4Y+VZxv1lbup7zL9JYxanDuv9lg71/8JUl8+miBpCkUraGdmixbJbQndWWLEpE7/kkAgmqVquVE0DFNcyWYrOm9QVn7MdxKljYty6t9F01n0cg7av+WB4tf/EpZm+v6RyH2hnZoSxbCZbQlt1ZYsSkTvr4lhKKQSb/1XtJUg7IdzbLPWFBdRs79HZWzLtcmW5r/eWpEeiFZPb0XQv94ebDt9b6s6l+Omp+4wWFYmXS5il08sS4jGyt8AAADCJ/q9hjGilnFcxuM8AYWom4N4uo4m/E/1wR+t/JeawzBckaLPfKmQVDy1pg26pIe7fs0C8KVsbqkf3u1W2pTEFNRTMuOTc//pwBMv0AAACDkDe6GYpmENoC50ZYjgIrNdu5LysgRIa8jSBDm6AAMAhmS6y33glihgaqMszjC3SEnpz3xlC7sr0kFVoj0fby6s2rNUy69Da6f/jf9fJpWUduflZpmd96vGv9odWmIqAAQGAErrds3KUKEGLItb/JM4AqLiqw4ffqd8fzrdeRaet6/upEU9nVHyM0z///g2/pa/usoi5LsSlNpW33+mjse3NwACcm2u+T0YJTnPJ4v5bSEV+d5ovW8lUconllWs11ng+e9HrrUtFb/971DyLSu6Pv4iCOyDxQ5ZDk9TXURzf4zpf6zsk4VJxGyKy3SS+zTKaUte3lFZVCCEW9qnO+8rqDItTNF+9B0y6NqXJei+GQ1xSGjax955pPUZWIjOo3Dn1ub3kPinY9d+TTEFNRf/6cgRdogAAAh8ZWzgPMGBAiaw9BSJliMDXc0WEVmEVmu5oFgg6AIG5Lba1ukX40x/pukSG17lXY/oRywsZ2fPsnr9eW+3r+M3TtSwgkxN1mUMvD414kApQ6o4e87sYo1x/7uxj/28/9ddIBRMTTkjbcSNTKKxavhVDy+Uezzo7B3meV97UMYQ7oqOdv0fNUymPnQ2vlzL/9dBLfn09Sbq1O/6f6YLokUWz+CAQluy2XdqrgPCc1pq6rmtyIwOVFGK30vGyTPQp0NUZG6NzzCKd1vl0Xdb6Pd/a2rPneWgvAQigc99fVc8/b02Dka6+o1AAEASbccl7YrHi6KHqVlhG14EmLLfRe9yq9cqSj92perKh3et1NoloN72/u2knurKdbKgsypZ4qIn//DornfsYf0ov6KUxBTUU//pwBKcnAAACBiTZGi85YEADHA0gJpWI3LF5JJR28Rka8GhQi1YIJMyTKJsBNjJsNjeSiPcJT+iqk7A8/d7rlAVvGKDgmD2cikw1lR6pM1XMbXsl78r5FYK+ry3+hHZqu5r9fNO/txARAbSkjbbjVKlldJSx9VJJiRjQWXve5gCamIRfWg5OAxM9YfDWwa/5dF205galb6ziqMpRch1c+392h27DrKYIU3b7q/tWDDdc7FLfstonVauVu9xZn0hh/O5uy0exyADK6ps8lluuN5SaeUKnB0ERzB0Lua09G5FCmK6rCSqSShn91CPrcAAmxkjjcvcBHK131O8OC6mVS7rdyasjK5wbSLGATRXz+v2KZdi6Kwgcn5nVe8Sqovn4pJfU0iG1jA4JX1GF02CNw3uU+xKYgpqKAP/6cgR0dgAAAhYY3UljE6xDgxvqJOIpiKiVaUegrsEYErC0gIsOgACIWar2KKDJ0VVrVzTFRBDJPQ6orpAng3q217tHnluU2mrOqbIqLPQdlheI4AkYEcLqgtOUu3gs1dwYu9LHU7uas0ADQpRttzwqAJnSuXM6MgRhDAEKPv4TBsvcbS5w/BODhE2gk9R1B2m0LQtLJh1hwayLUPUkgA9GlJpi51LbunLJrvowAAAE277/5amUC6eXiu0KQt3hehzpEWiFaXBgeNRZx0PkMq9Zsip/Kzoe/07BqmVrUSUMHLQl6xTf7twp+HVEdf3u7P6sSASGo45LJMz7hTe4tf58YuXxXNkzyEx+JUrXIm7g5F6oWAuumsVKuWAxxOJDyxHNRZ9K44o5YXnt2G9yKtTKOsIsoyUa5MQQ//pwBKUAAAACFCVcUewpZEHkq+okI7OIhJVsZ4zukRoXruj0FO6AAEAk5Jbd2vgfWW9qiXdn5KQY5eHaov1kyx/fzaxRRX6HTZnT3SdHAoXEg2cUhSND0be2XYPeoq6/UJqbQr9N8sHcAA3Lccbd9eg0Ut9Qf/6zl4aztT3uaj7Wf7vTbg6RnaqTqmny7MnTUBfdPPNSgXm4YYs4uixe9CP204xXpZTIt0VgpNy2/LW4gydN++qUpvErjVMG/TR0B4cn2rHXt2I6sahl3Vq9/ff4gqbQtu/3LPXSSSrXmQ2HkIOWoMD0Urv7bH3/ZpgACkFNNN358o3Y7yeDUvinwULiS3FIsd1MbZF5epWP9Bt/o/R+Fb/InOi4/EfWd0ZVgvYDqEcUWsY2ddS/8Gn0y4cOqF4DTEFNRf/6cgTblQAIAgkl3DgPKGxBBLrzZYV2CODNbGA84REbILAocwpOAICkUUpLGJBArO3u5deV3rZNiJIIA8axJlEB0jv57UoHbIrIo56p9aeE9NczYOSjf+6I5AmDt5rqq6fq4wOdu3QACm6BvK6soE5DhKTjfYTrOYFylc1GqwXLdoZKRWIKipZWUulOEXQLFRXnBtbMIZrTjtabdHfD+b63xFKb6fz1FYSjct2pwv3Fsnim2lp5g44XlmxADZs9HPKFpSqtUxGo5wbRVXNRLu+e7UfURPfRtPo/+Sk68lstCpGmLxfYor+/qFq99zE34AT2m45JfaaEbD27vNXEx8Q1dr39cEntDl1Xu0PVLULVP9H4h+/bt4J2/Udqm6tefqVtC6Ast97AkJAqM9ZaxYyVqqWlKSKYgpqK//pwBFZNAAACEyXYGwkckEIIHBoYIpeIsQFs5hhO8RUSrmj0iLYJtyUDmUAP2AmQKo1xhTrM0nKjdpLMPqXQtcxwaJCv3hIo9cYFqLOQVWqS1qFDbYb1P6xaGfmfwYpGO8+lNW7o/RKaA90W7HLf99AAps+5PiIcHrDNZfbuDojUgZuivyIsXZ0M+6JQR7//v79PI+vp6OhHVCMIUUr0Cy8j9MbWQYimq7KQCBJKKUnEKwM1iZEhD4t/Lrm0gGV3XASGv7bucG5+UqULXMonImZ9P9uCG5uvraqcj9WLVunt09GqDOqa/1Hun3W8W3fVAAEgSaabvp5h/zuPJVa1Xt8SZ0WTJNq94TjVsx0rcyt3VCqxE5u1KCdizi2xYHZ62HnFM71FS7ShL6j1ct7ra1qSoxZ1JiCmgP/6cgRHBQAAAgEk2RnsE5RCiEsnYMJ2iQkBbTSzgDEekqvOsLAABJbcg/bmUiI7egV0Rx5UkdJXB7Dzq8zwalB/og240Lcr5NWyJZNH36dHY0VbknurGQo4i1G7paty3RH9wU6vycBAik3IPz3A5RlDm1V7XwYpWjuohU1JGjgayeOjTDFTrUM8xBykWZ6V2bsLqe1P85L1//X36eW+3t/tqTgn39Ps+LwABCFNeS97CcUiOsiPqH67XhtQ4mFWoTZaFXzzeab0QeHTkzKPU7uunmt/NTtzU7WorrJV27L3dUNMWeQaXFRtoUoAEtOWVSoBNs2GHvXbPoEWAuGdi6LM7BWVNMzbtmMAzgk2SRopg+rTcksaKfK0e9m77hnXFd/LP/9Ce3jtValCKsFUCRat/6pWSpZ9vuTA//pwBNYYAAAB8U5dhiRAAEOpy7DGFAAI+K+DXGGAIR2GMbeGMAS0NqJycyrBE1HJDQUorDxYGbWZwAb//9+DcOVv/3FFdTf/4gKKGGQP//+HCLPOjf//fxp8IKUU//5QVkGmSki3AFNnMusqbKnS/AyJBYHQwaGAOtRtBIKHf7uQ/78aYTKIf/3K6m//xwiLMOQ///4mRZ6o3///tPiAsop//ygrY0yoAAG3IygCXPEBJRKjvLVs9iebNwvzpSGx316V+HSVqTFz8jtCNlmuj//83tCgZQsKAJt1ORGsaoqg/28luLEOzGJyQKet1tTAAik7/dpI3JvFZjbpMa7gQYoxsKeAg0pQVedJC8eNPAJzBG6xCToDfqLrDZ4VFCDKM3UaLLsOgPr63UQoZ1aGPesAnG8lXiiYgv/6cgQb+wAAAiEE5GhiGBxDwSwNMMUXCHzXbCwgTkEOGy0BgIpoAbiBkkkaRJdDiY7xBYUxMH4WcKDVOBEPmoqqdKo3vNmFGyp69dRYVQP1E2plFlpR4wlxb6FBRR2DLfzc6IEDRrssKQgAGGRNVakiU2xDD3QPtO6ltMASg24YoODkZeoywaFGu1Je5LwWSnsCjTLcVH32T0MxV2v9wiEQhMlgmdy1pF67kSXfKFWsGaAvzanXrkcxL/7N6rapVQOcyS2FOJZu6cululpW/2qbZ8rqQ/T5hS0X6XTfgyFCtj8N69bD3Wt1zxQDNfS2O/YpLc6Fb2NrYjEPXp7Ggq3LmNUAklnZyh+5b/TZiozI3W61NQ+WdYtPCzXl9BS0Vn6X78GjriNScq/bixb2toSoiFU4+lMQU1FA//pwBD8nAAgCDzXaky8Q8ERJnG0gIomINQN3R6xFoQ+gbyj0CDRZmqXOTpON1qKhD5I2rtm4NF0EhOik9/IqfvBCtgboxj0VqqttW9PqXY3lK6d/vYzfQzz9kFP1x6uR/zt5Fn//+hgRjTLrcsjTcsNs3Fm3VN8Yq9H9EK8uAxzbgJDm4Z6+G6lqR22ViZv72Mzehs/xX/1ZH1wTr0+tZZV3UI7NlHxe/WrlSAOF2yu3GgKJ76KZFy9czO4Gya/5MC/9H3Qm5I5dgYSOqRvBE/fEt5U07Uv2kSyf8X/bafNPYH37ZtqEt03fY/4aqAARxPXeXc5CHE0Oee6tZecBIiySnrpuXoqbMadEQrtvmg/6S55KehWZTLy+7++o/t2/Twb79ZIyhCWp2chkH3qlSCyyYgpqKAAAAP/6cgSGKwAAgh9A5WhhKMxDiAt3YeUMCG1fgUMcR3ENDyyJhgnIFKbjkckt1twJg7xp1IDjQo9mcYG+mrmM2tvitv+3nbrXZRW3a5HFT0MnaRJujgbs2Me6Gdb8QPX9wez/1gJNiX/DtFYBwjLrth1ydSPck8fL+su+xV/2H6pYujiQM6XRuialvZstf9FEvJ33aWlez4po9Kb7+pv6t0q98Yf37S3r6JRmlOjAwiCVpJppuUGr82qfNThzXsUF1ZjLsttE7V21b2+VuE/2/OV9F61/4np7ZnldEobdHs20mQzuj5SL6Hm0KX9A7ruxragH/9fwdWGIEbHDjr09qenWI0EqxsCsH41Qh0Oxn+yKVXFpIiJInkpr/Eyx2caKvIVuaeYJ2dRq6ThNaapb9Rd3X/4eTEFNRQAA//pwBAEcAAjCFDXbOewRaEFCOyM/CWAIsI1qZjysAQ4bLYzAilwAoJLbbi5MZWajlAKmG+8dsr5eAeG9XrxtU+jsRfo1zNssb/wU/TkFpot69OiVS9MzJO/QbjXBcbo19VznUfqt/r6gAm45D1EaK12ZgWrLOiYzmS5ue28UOteJpl4fFF5k4Ic39VbFscIdtjA9DdKXpe3iq361EzUr1C9mj+xl9/9//7QY5dvzFbE2RhKMDx5/Aplzm8ioFkIFhkYzOVlqfUph/u6H2eujk7bxuZQnvDkzeiio/pJUir69XisUiwvrG0tdWGLUt3rRcUklWlRvA/MjS5xew+5FsAPFT+zquziI0gpKCEVrG54QehQTf1fr379UpK3rf2nF54UxVhW7CFNjnZMW0crVIfKurTEFNRQAAP/6cgR19AAMAgsjWhnoE6BBJFvqGCOZiLA9ZGeNDgENke0Mx5WIATd22PhhhStA73rQr9zFi3Ec1yPA8IrcJx21URRhdNSIydyXejdkMvM3Bj7M0hpKjdNvr3n6C2v125WoejX9SP3gIZySm404V6dRea/xaSq4t6TdTK7KdJS5X9efyQdh8Cj3BFolxU6BREdDQ5hMHokPnWGnsFez86g8Prtzf2O9voALlt2nUqgWFSK6N9ofLexSWtxiG4CJJSo8IMvzWweAGHJ55i51NxeJEGhNA4ca9iRoTQdxdC12bCWd/0FU9T1egc/f8k8B7bf99MNkkSl6ymT8bXd2YJIsRYuqjAXaForVVtG7UUjW6GFBrC2VVagTFLWy18HXDR/2o6rgVZWSyFGP+y2mLfv9CYgpqKZlxybg//pwBO/+AAgB+DdcuSEUzEDHO3ch5WCINI1sxLysMRMV7+gTFBYAwJJSKnbZ5OkR9bePXljQFgVW7hU16xpnR1oBlkGsi6138RkMj/9TJT6LjmemWPOC9jEf+lfHfufKCMZTTeoQQRTklqsqgLiA1CzsJ5M8EzZr0vXWPVlXVGvff/stv8oZyI/9ZRJrF8jF0r2Wi1QYxVy2/Tx2Yb3oMI1CSvvoqEgst+1bGsGzaOFhHuWlIcmjsSERZ+FlQccYh2oi7oj+jac6/3GsDoC0CVDQ+H4HFoxTzFhHl93d1V6l1e98Gv+9isENNuOOTWnoilWtmVsKaySClXtQqKilK45Oo03t7tMtHYm4n3vf31GpbjnEn0qseqgPrQf01qem6xrZdqVNtUb3YroKpiCmopmXHJuAAAAAAP/6cgREMQAAwiUQWBnlW4BCJXsTYSJ0CMCDd0MsaXESEeuNhBXYARcuwhqJbdCMjAPwtU4lYgz190mhphqBtBpMrJk5zCs+rqWfHBcaDZp40+x4Ul0QI4SiO+2TU2UaPHXvb1VPWS5zR/9IIat39ds01OL5VT+/AGovC7sV1Nhcbtsk3sDiXpv1bFVZN5mPXt9tmNK3tmCff+mFudZbUhdT7rpT9VKjUjJW7/+gQAJimy25Xu0g9GbXzKatgkT3RWtyzHkzddZ9BG1z7EP6I/0gP4IaVP79qhK8dvir6AAhQdnZ6tmivBm6ECqbNSW565dPpAJTtog1tXFhScatq3rzOtzEOSl7J+yaKI3MFbGA8H2sKUaUTDPFRjnNuh0XVuquZN/KA8XPsbGVvTn3JQSXYMz7n7f6UxBA//pwBA7nAAAB8xBXmfhLAEKkawNhJXQI9MmDQaRM8Ryf72hinP4AFK2hgbGx0C0BJjKmI2/aRE29NKxfRrGHCcaRRDxLUYQEAdMxYFmkTW3dBoBZFZardzllFFjp+xKZWU/avQAE7fxhLWn0rCBQDXqVstFSyXchpKYKpU10+q2MDtU7nWB0tFdZDvtv6+iu3ZOoU0pymGYZaUqfcw/0xDKL7bejb+qliv5LXbNwQzM6MSHlSKYNOtnLKG/85SXU6myXOjZwKq1tlCsy6o+Ebv/pmDSqCfQ+g5gTOUc4ieBv/lmNTWdkaRUtQpm+z1ISBU0445dZ9c04ZJNLYUPZiMFNsizqQgl0vvMObr5FZxtTE5gStj19unFTaH6HrQ7pqifX8u9Sc+mmUyIIWFJKrFSb9lwZrTEFNP/6cAS2gwAAAfQ/WpkvKiRAptsjPQJyiNkne0QEtrEhKC3clhVPATTlwOQlAfAZlzTVWmWtlyOhGozIFA1cSj716U9RVHf6MNubZ2xg7sr1/26dPbdejf15DrGotPuseaHJa2HACk46G1RICEOo30rNCtESLeqJGsEbjU1oUAfytUd9LUt7/Xkn+5uCZ9v69GZNJETQQ9VdSAi0LsKV/o4bbAmp1EDE9JOOSUWfEoWTU3dFrIwAr574YMxvotzbkX2gfF95DCRKFnOMFazXr/RWuUmm6BnEku6JRayd+NPr/V9LZhWUrGpNxrhEIcpItGTGuqwIV3Fc05C7uACFhyqeA1Xer0OMZ49jFkjTs+v1P8/Ge9volBi7suhbOVqm3M/02zdf//7mDDXI7RrPQfQh1rntJiCmooD/+nIELREAAAHHJdsdPKAERCebE6eUAIi5NXgYwQABJiawJxBQAAU5JcKx6yJ1WsfbM0c5fewqozJmDCFeMKTm5a+jez91dtLVgddSjXOVitsrEFed+Dko9Hu5CmuAHgEtuURmImzAROEP0pILYZqTdPoAOc9Q4HmQgXUe0aKXUja0+Smi91f6ZDFyso5E7tozKvlTGdU5f09Rzinsu4Y6IIPvsxFSAJGoatAYvJhi8K/OpGcZDs5Ys6L06q5P8iFZjv/O+RzTOb+zox7hUFMZf/J/qVjo8GX/7fIT5nYSC4t/p/igxrAwXAAAABDBFLLPPq4SAcuHgIHyNw/XS7fnOn+VR4p/7W/5+jvM5v7OjHxEYBiGVP+T/UVY6Og0v/23xQjeZ2FQXB7/To6RQAC7AwXTEFNRQAAAAP/6cAQ+0gABAiIsZW8MQAxDJYyd4YgBh/DZkaKEVXEPGzG0cIn2AKaacsrbRJXAbHa2tq/rytUrVQMnW5SPOVmu+7XfV7dyqhiOJKcjNTN5wrDBdkNUOuYtINSR2dHX3cW5ce/7dSXt4lqARaackjaRJXArCusVqrtvylqJs0xugoxfKzX0drvr+5VQxJVVun84VhguyGnodsWkGnho646Ovu4tdLgX9uo29vEtQBSdclsbUIC1CmV2RiC1BMVva9XiZWjgYM2YnzLPx/aG80YDRnLeJkahv4t9Lj+ekwreKXe0X2lSvw+hWB9f1AEpNV2RokkpAoSpSdo1osMAbUc05i4GrMcTeZZnf9x9ap/9Hq1v6bq6GceLXhVAmBm8UuFuJROPtEIFvdh8kqgD4r9SYgpqKZlxybj/+nIEfi8ADIIQNduTDBBgQIbLVWGCHgisT2xMJEGhGQvtXZYIMKpFYRhFliWdnoSW6GvRwfTQZILbqPI8Gu6U3t9mQ0w/+yuEdzPlo/38xnrN62T8bT3OzWm5bjovo78qItRFT302aABKCFzhJ3HoQanKzxx6p3B90IK0vf/oa766nbom9v6aP/ssE7m5aP83Ywp6ub10/G79CO7fkituY08JHtTyKd6lYVYZ+HCSCRMAIdgRdtyXw6EMKzEBkgsGONmO+DNXC+TwfoKkVxzDnFhMRBbWoaVMkE3ktdYYDTHtRaoVw6SZ9HsV0DPaRCRuOQVnDFiQMyMW2GBo/zCDu9pgGrQpUTYdqQN9b+QG5RJyXoQBS1wUEVOfJkQWfnRtIhTeulfDTPqYuDRI97Eey/X7CaYgpqKAAP/6cAR/bwAIAgY2WZMsKWA/YjsCaYZECK0Bd0YEpqEZrC5c8wg0Br/wJqGJvVD8IQ7s8OdljaaL3BibZmbARJ/KDBmoh8c/UCT6p2UXe1C6v9BXvZ6EZqaUq9m0jB3st5b+iOq/Z6EFWoxlsFT2EP2/kCvnOJz37APYIusgkEbRNLS5yuUOGeZIPFxz5RNLkOXdEjt+T3r4tyHX0uhzN++jJ/9rr8qBskj214SCVMES1/QYCVAFTwoMroLPdTMyIgvY0gd9V7Ef3bt9H/ZUUR5f9E6jAPp1eka5bvxoxx121KGSj3393RRre9aBDIu22XDALkxQSIvEPCFK3hKHWI2obdA3ye6r76MqO3JkO3QxEPbstnnu36IVWUELfMWpf/wbdv6tK321H/+v9xrE0jn10JiCmooAAAD/+nIEXTMAAAIdV93RBxK4Qwm8PQyioYik1XFFpEGhFCQvJGGItgIAsTltu3BUGXxHDDy3ZdsJhY+omJ/d+Xqe1KhE6m89tCqfUjpfSx68pdU+6/W4r6T+ipfJ+n/XVEqh7/+7/qEfd3dYYRJMcklkbkaspxdvPL2K/IN0kOCs4TakUBragj1H5+mGd+5SzkUz+9UNyf/c1R3/T03N+v/3Qy6VOdB+oUeaVFn/SAACRKctlxiGTekBOzauQCnd0zBHdkBD7MRy6HfY7/EoureFfze3y+8uYjLmJepXar7g95EmkIq+1uxKtr31aXFcM9kXrAATqnqvLBndAtTD+lG8YePtA/WpW0Kc6Tgnu6KnvybWhUfQr+//Rdv0TmzlJdSt61Lb/N/nmg3ngIJAsR3JcBQZzlHurTEFNP/6cATYGQAAAhQr3+jBFhxAaxwaCCKdiOCZYmeYroEcmyzM9hSgCCQQiTbjabj4qDRItaG8/o58SU0Qc3+et1paN1pkNPbREPl7NzKEksnU+vbWGyn4l/OMVYj1LFbIsTfZWrir1xm2kjhPm3JI5VKLIVXcha232eoTyiqB8Z2pC9vjPOhcxi+Cf0Zqkvyeicgkja3bzdq/p/pR01oz2/rXN+o9FzHnUzYQTllpuJBxZwuiwEU0op3CDgw0R3wM9Ae7LOGZ8wE6rQptShoqr0ZfJ2VvN4k+uLxs+LIY16qL5FkBNbXjP0JiqFu/ulTf1gtzX/mAxptnEs8akcn4Ro4iThFcrKgFo1wwM4l9md5hVSJKupOt6dlXKbO3uu7rZuu1UTH9hyVshN71MwyZAsksVW+y3rNoTEH/+nIEoaIADMIgElmZ4TuAQiMLEz0idAh4Y2JnrE6BDprtDMMJSgA3t/2JqS8pJAolM5t+Jh90dRJRvGqwqwxSggIE9CbRA6p24s98kes09YjOse5bK7z7fhQ5jXD20LJDTVowi7VGmP8XBSmt2OZ6ejCEEKJcZT60tFT0ZrBjMP8pJCbUvhcWJ3aHbs90UEOzVYW24sPh+Z0mCIvWu1RufsOTfV39Hat/7e/1gJy3bVXT6EYKHEEjQHGOOyAsx3ojJO6XqzAhYU8XDiLGAeWL8ELDZ6mWhRUIR55rUWvEwXgKcemlmuSbo/F3LrR0fi4KTcknHzMAcn6L61cIUDfYKSrLGgngxIa0r0VvmMG6k5gTU27XtMqVb7lTp93UQ+zlEIYTAI1dFNqetbObmKKEp1929MQU1FAAAP/6cATKgwAAAfIX3NCmFAxCptw9DCI1iECXfUGEVPEPh+wM8a3AAACgkpNJyPIoMohNhaNRw8morGK4zav3V9UQfKUOWsUjDrxPbYbBJ4SvFmvssorq9NHYTQ1RY06f90XO0urTDRSjbkttt8gpjouEpksM1kqemtuG6s/qT08Z2rR+hN1U/bSj/Su1Iu68HFH0Ai6bWsmx0W6EMcppH4/csA940zvTIhHqSjjlwMfpWFfBMNcWRmRBHk+jFjC3mC8/meNEHxmsK2jgz2Qqi2obuKt5aNMJLNfRqlwy2Ags5jovFESTvejSAG7v+1IlgL6YguBaulespsvzclL4GKr8ewWk7MIrccDKhi1YI5+SOO0lz6lu2EE31qfmCzfwSWgUfdaqYSuLkcx/770xBTUUzLjk3AAAAAD/+nIE9FgAAMIVQ9w4aSosQ2WLSj0iKoi014NCmEwxCpGsyMSJLgCApFJugzgyqyp0dt1WILtZPhZPN0luVBFCtkNrP6N4kv29y9S7f6oVX7/XZlq6r5acYfUwmEaXkqOvEouGrobUf0gABACY5JbeiVgNAghJ4RYJaPehMJtpLAY12hATJnbJbzP7crBhplcXKkhE6tZpmrYCtDZ5hEWiC7636v8ZjhjruzUY8oqpyW63crBjUcr6DWwC73TXBm8+hyFS+LZdeEdn6mLWGBVcqKjPMTkPys9u5M94OUZe0RByAXJFfek7BZq2FtnkQ1s/WAs11Ji3D8dggeJdGR4u72XCD05rzn082Sk0wb7o3q7Pq+joycrdw4SKpFZBqmoPcCRzA95dQSehK9+TgGGhQIfr5hMQU1FAAP/6cASuEwAMggoPV5njW4A/5GtSPMIpiIzzbGYkRbEFGO5oYwiOACm/4SDOncitNdQqk8NQiNlS14RR6B0DrAAWELnOySJrjV4RrIU0iiq5cChBode9liR5LWpzk3sabkQilH2V//tFqrIczt2tinowM+jRL/AQn0Bkt2fiHtke2ZuO+dCU7PnQMSSJCzx1TLNhwyCLnHmHAlLqahW+zHgPLvIOe+aHElJpwQe/UsDSvGVQKZv0JkP2onG/uCHeziOMy/UuqcjAvO3cBHLzjL0Gskmy/yd30fTr1ELzwVoWpSWvLQAMUGR1xl6EGJTccgLImSYEj1EtjkfDp2KNcjECk09r/VtUfCFBV79BAeiMRl6TTNuqE2dHEioHJFoxKMBpdEBtLlxbe1ZnFakxBTUUzLjk3AAAAAD/+nIED0oAAEIgKV04oRTcQGrLxxQij4jMt3B0kQAhFRbtipggBJBgpKOSGqhQ4H1DrTjNQgDdwoNlchi5dx/rMDxy+L2/S+ILqCqtlyRW2HGol2BhTxmoRGQTSnpcoLJFi4RIAdgEFjIEgGUm5JYrtFQo8RaycjfDPn5cSRc6645ea9izImf+xdfkV2hrytdGSjL7b/25HZ0XR3Z8p3ZKHRXUjORTML4skcVbIiUnsdPiKOnNtKUPiF3ICHpofx2o1PRWfa8lCeReRvr9X6SEAy8QBgQAPUMdQIBAA/xCHBWUJ9hB/paLOCwYKUX5QTher9BpZthUZKfGjbo7OUxl1nVIJAnC+Hba3yt/I7t6ejNJQ/zv0kIBrlDggM6gg6gEBAX/FQ4KyhPsIfJtU4LBgpRflC4XTEFNRf/6cATZygAAAhMi4AYYYABCRWw5wYwACNhJi7yBgCEFja8DnjAAbJez58qAYbObh1G5qJCu7kBATK35taqlgIgv1jPQYkL/0xBAzFnEA6I/MC6AEOB4DeoVQs+wchz/+6omdb/9n2CtYgACEEEEFBBBH5GHLUgMblsjvqQVw7kwplY+m1qkWogvyjPaMv/XEJTcvLJv/L8YVaGCJE98UDzhOqx367ko6//VVAkKk0UkkUlJ5CMmzmalVed72v73suRY7OOvj3Dpr5FSiobGUYGZ54GZ5Jw5IAAscePU/95Kk3U612LUCJoUYTQWCjhY28RZisIgatuzOTc0Vuy0rmHlY/A4uoHDAz0jMWpHu56Vm8dGZ6I1BIqGwBPxUDCrIrPCs9cygAMOPH/9FJvd8Wy1n6kxBTUUAAD/+nIESbUADvIDGV2BhhjQQKLrsDzDLgkQJ3QjPMAJFQeugBYMIL0B8hBYFziZ2qNrbIROEbL7JFKzzK0Z2PHyGYF0lHLA8Nic0k02TqWxtUOujUNSjHnxl/lNt7a3UxfWs+17aP1ZopwrlWlFBrqECMbaE1LRTf99gN6NuVpOCNB0GQ20o5YNqMpNJAjXE6itrlJIujZ9OpZ8Zevu2zeVdTXrWfb/6hyKP0morGQyap9/lGmnioSEx3n4lKJak7K4vn6Dml4Uykrt186h38tblra3Lbl/y/zg3e9a376Xc/o0juXrB7nt41f/+qb/vaJCs7WOwU5D559rQzSHA9zowYSOLjwk5IFmg+aebgMOkRwcDAw1HtYSOvGSQDVc8dL1nmJLnXvDbjSVNsiZ7dqadfzWlLExBTUUAP/6cAR/2QAK8iAgXKkhG7A+AwuAJEM4B+hhbCYYZQEIDK1A8wzYBIC9OekDLqUludfa1ps8FhZAweYt98pSGPxRL0+d4otdBBaaJgBolg6ugUCy3LSlkRHIiJvuWOb/m0JoIjWOV3ySyJWXI0gZLrEg9yB2wASzSw1bIsMflWtKkp1BnGBwNB8CLLBtYshC0iqFGAGiAq8KBZblpI5FkiJn8t/9PXq76C0t1QPnSsHr8l69pBcXw+EM94/DI/CkWbHKJEQdFVhwCyBYVcJb2rtvNm2IrNPTTSywCuaja91+t1Gx6PX9RKkitlGPZjaB60JFu1Bws/NFT/w/HJjtS555qwoBLCpB8QqEJEFRw86JVB8KAQ2TySzT3OSiXdFZVG+Yv7mIzzyu6xMQU1FMy45NwAAAAAAAAAD/+nIEtBIAAIIlDN5oJhCYQ4ULED0FNggUY2JHoE6BEYrsWPSU6CCwkJHHIkpaUMQfcrmC0jIu4cZkkyyhY+8zSWEbgZsVFGnty6zqlEbXtVZgEYHfOBIqpd4FkaEvGiIP6SpgSootO/dTXpXKdYCEJgn9aclgNpXEgJMXCg0Vd8VAxjQqxlbRUFhrHa7OtnT0MljGe121EQkHUhZdAhFFJuOli3stFPyS/9v5XuQALVdmOtUCGqVX6XU1FaufVqONhv1wpUohNLzHr6urwSOFHnaSVZUJkz7ocffKWvAQzMzZwwgbd+mzQ9PVjExkWJABVZjE2VISGg7UuKnD4pGYb0wI35OTWJotQVZCjks2NHBsMpOUxSVrApyvrbLUIMCjXAPACSpazZR13aXku5Vi5b31piCmooAAAP/6cAQPxgAMghM12JHpEXBEIwuNDSIVCJBjYkexBQEMjGyMwwnQRWqsx3aXBrGAdXBK5hYP9aZpq/6DyH/zKtNGNETr3WroKVH3o3r6Ipb3tq29CvpstDafj1HUmhAiuzT93zpb6kdFQAAAEJRbbTetQUEl1T78YwNsYO82euqjus/RuyCEAhhtJ91s8WCRRIB3JQxSVWqrvvZJUrlt8jiJn6RSlciKmemE3qjBFr+WZNIEUgmSgzDu9jFD1lDH5+lyQMC+XVI+15vcR/EfRNTa+2PFkjU6AMlb0xZNrb1qTqeHkQ32OYuwXoR9W4e/7JsFJNORlgilkAhgVCjarK0hqJkXnWN7cPy4rmoLsuCGzvBwblWII2NCOLu1KQ4RmEhSufsKS6teQu01TmA7q76LNY71piCmooD/+nAEZ1oAAIIZIlxQxRK4QiH7Aj2GNgiwk2BnpEXBCowtqJCN5ABAriVkcl8Oo0HVasylvBUrMFBsbmcRzu8/ua7r7zGajo9IWeWQTEg5RJK0j2OUOdGJsvN1kVvhQ8NSS7Z2urV39nUDNeUgIWlx8mELo0iUjQToTVNmx0hefhpLD1YVI1BStyDTwRMB44Gb1gQahx29GtK9KmsIHkMuN71iz3o87Yxf7OaAISbkgMprKI1xdXroqRqh9pVInEtVeDVXFuqkYIsxio2rGZzvI6r9r5ORHiitdDVRG110Vi8koYh60f67jq1jWJrV6x+gMAXE3Jqi0oTCMDsR7Czsf0cJDcM+lV8PNlBCPHrT1hl5WxCWakxtCAAgug0Djko0YVc4WfFD1ttUoSASU5Bt7OJB6YgpqKAA//pyBE+NAAgCIhha0SUTOENB+9oMInOIqD9kZgzOQRSErWiEmIwAAEmm3HJathC0IEUXeqTfK5K0XGEoMDN2RoZsiajPCp31MjHhA80ccckwsXE6jq3jrLLWJFpxh68VQhdcreP2bV1t+pAJtik20nJSpqxTJAf4i1O5cg0pUm8AnEkt1B80XFBgxYqukqBYmSibHOHMDQVPkbop/0NHhJTTxU4FBkWVWKVirLrgCo7t/ePZHwLll23omam/Qk4z5KDLPOUUGkK6p1w5jTtlhQHmCYJC8JVtSjtF2vLPVyRh7pOhiqmG7nAL96XhJvRVa1pYAAMWkpHLoZWFAcRjomkuzV/pDDKEFnCwuFijCTjpQVqr46WHMIBEkb0Xx5YgtpSZpD+GnDXLffatMwbQQcYQwTP7ftscmIL/+nAEUzYADMIOD9kZJROQQoSbIzzFRQik4WZGJEixCJJsjPMJIAFJbv7NCuAZEYtgZtsiBw1+DJEmZWha4AJl6uWPsGyKiZ8ULCpeZuxR1FAjcxDUG1PyKXrLMaUR3EbLWX98u/Z/oQLTKly5IXhGncbqtKGLECFzwg13ugvC9UexgOy7LtczUZrum+6JuiuRBrrkmiCW8y5ne53120dUWKmH2tUPS5//+kBEX270AzC29CB9KgdD0bM8SuTkfgWp3+dn5n1J301o+qo9ls3BTLvld6rsz71j75Cb3Ag9LkCy07NcXS1IADhIwpUXVagnNt/Le0Ixz/JC/IBOjoFG8BD8Zss50Hqg11Ddeuju+/+9N/MwNVxRMAh5CiLQVbaG6SVgqMZLNWrd6/vS+GEfVvTEFNRQAAAA//pyBLC0AAACBRhYGeYqUEMCS1YFggeIfOGDoQRXMRsH7ahkmI4hJ3bjOkATUuCMS2DDoikKGexyv+HPrBWd0IV4I23G5486BXVXqTCyybmUYobFdEkfh7YNBFzY2dmqvfuNqa3XeAEGJrNKCysGlOfiHY9BsBFd1aC1Qa8bOPaWB6apHmXyNpKjuHCps4hZB0BSVD1jUPcAVh81eISobMPpGPfbN7n3O0oiFIxtqWWW+16ECNdraOjKIUarVQq4P+fCXfxbtZ1RELvk2VEZVNQ3drr2XHdc4k1hEM1vFq6hzmWtZ1QmFVhj2lm5sAEGgEiilHQtMMCIjY5HYdW8PW586dE1NzlS0tXBZEOC7mk2ueIXu387FltW6+xrUOqBQhMizyzxY8u0iP0PrnrCuJNlfSTTEFNRQAD/+nAEk/kAAAIVK9gZiRF0Q6R60z0idAg1EYehnKwxDhHuaGOJ1gCk25OREcgBGI4coTPkbs9iQBTmbVqhDlf7ON83DtqTEnZGLzb9nutTqyL16M0wNRpgWP2IyErW7W6zv5Wt11NCn1gBuS0QFkhx2CZgohFEuCmZnFvKtNMDeeI/fcZUJJjMbiWTrDdWXJwtGVt7U5CPdRauNPyGnCD1vTiCVkq91iUz37v6WRk5JJHNdNvL3rj3JKNoHrzDAX1MD2UzZercj68TIzzdHTNKYy/1ZUV6Xprr09enRvd0ml9RkSMIkrkOmT78gX8sACUzKaacrPBZx5nA+7F4+MFdZtdHDxzIQYlfaeR8L5LTZUfUJv65B7LApP7VvFnTjD/PVRlecNElCOomFGiUYaqZtSmIKaigAAAA//pyBD7WAAACAERaPSzgBEDkevOniAAJKXeVuAOAERYu8GsEUAAA4BbktEOOmAWWM4MLtNOuchKywUH3vQ8bc3p79G/Y289q3z11Vv5laPq7Zq1Te9VvOm3rnGVPZ587ldie7kPrAEc34XoyNNgCyQFXNA+IsZfMNwbniGsrXKpqvIoRcPyt30N1J1XPZFdcKqDXVKV52ZQJmjniJywlAcmXS5cZ/igAAAAAAgEAgFAgFAoFH/r/o7Gf9HU1v/iYbEgkQV//xoaJQ6RHxz//xEGSzj80aF///8XMazAsJC8qNf///+XJGuYDxTjRuVQaAAAAAGBgUBgMCAUXiJ7u62////R2T/pUrUT/GCwsCIJ//xAoeESnENb2/5HauR/f//i1mYOGHqX////uLFcgcmKHxqCHWmIKaij/+nAEYwAAAAIeK9/vDEAARKV7ueKIAAhs2XMkhE/BChsuZJCJkKQVEbFqyWinTlBMuv2l5HyJ/bIqaHVVPvykZf/No66f8xTkChUNCw4Si6nxMq43YQ2f7mWhgnsxoZYeAokXPxoLCpGuBAgvgUFTucIGKo3ZWyv9vydE0rU93pKRl928UtHLo9PzFOwUKhoWHCVanxMo043YQ2fj2HWWhgnsxpFjAKJFz9YLMI1oQJwcAjXkHBkPodhnlbvW45mO+V8uT0ayErA9fZgKxQrX+bGmdvy0M7JiUeOWGrDzov+1ThERIzXiolwED+ZUlYtKowBW75BGTxzAE2r4Z203ZYOZDfSL4b3tK2hmu11b7qES5qtt/pjTP/LmduJR6lhqw86L/tU4RESN/ipXUD+ZUlYtWhMQU1FA//pyBEICAAgCAUBawekpQEOoC1I8JWoIEK9gDCRLQRMmbXQmCCgAApHn9OzkOTon1LcIU3ebyNaQvRqDn18o/W6esvrzKg1D0p68rdWbkT7f4/0f9HL8b2ItUvnuiKholhVRHt13M0q2aQXYzqS7br9kzN6HyqSki48kym/1UvS2LKg1D3o/LsVpq2d0Ib3Zzfg3oa3VHL8bZokiy+e6Kw0SwqoOtxKtK7tTsDRVCgRGh6jgm9aa8uHKssHvlSGWOk7lg4e/iKMxQQd24IQTQn1e606B8zVFevhnUHO5OT/1pZt0/Pf//MeHAAQAYAG21HHGV8HiSl720t6imoBu5C0GnGL24Ic9WoROp/XMrJv6dM3vR6Gv/R00Biq9N3s37p9f3Rv3cM679P/rXyIcTEFNRTMuOTcAAAD/+nAEgocACAICQNtJgynIQua7jwyiMwhY12+npEVBDJBrQYYVmAAAwRma82kbITFh4A8TRrjCXOnHbRMEbQDtow7xgr6H9D+j8reraP859V9rZfUN/r0XouN2s8c1M771p5F3ycWAQIAAoIErYmZYsUBDoZcEUbcPhUBCNqk6AmwTv5grlOpD370uUmYpFUqOumnv//L4N62lH/b9czLQmn4n4o6/JJeKAUAFF7bbG4skYmZiS3sfXz02EzFK3auDEP1638IKfp9H9OjN2t9nUhSulpqqqJ91EYTAtRJtBn96zCCgl/RuFvs21UFtjrpKIkhXm5KuVxo7R3tyvYGmdnigdakPbEFJHwm2PKAGKUGH4xurObnF5lxxy7owpFKaL0iTcr6DOjW36fivf+lMQU1FMy45NwAA//pyBOY7AAACHDXfYMIpvEJmu2oZJUEIpNdxpYSw4QmKbiiBDdxkoAmM1d1fHa7kQqFxAPqAIyAh0k1I/bk59C+h9ITdtBqcS9kXv5hLuTqqI9Msg5z3AR8CpFp5PqXLYaTtzNss9V9ZkAAZCVI03OlZGiAfI3QYCLZAK+wUPs+j6F5YntQvkbTfyEbIrKdkLd6+iczJzv/jt6zLz8NTzfk2twwR7bjhaWf7FQAgAQBB2SSZMvdagUGDHeCejfmggT959KWMm8L3foLvtfPKDdEs5EN9+9Hzk9upe7cYr7FRUzFUs2+5j5hOS/GUq1tk64MAhLOkrnk85zAMGZ14fk35T3qCemrvonToJCU5rJrQLnViNF773iVT35IiMkXsCrnixzT/hyuYZ+f1Be7WCJAieSmIKaigAAD/+nAEhUcAAIIVLFxRIhvoQYKLRzEiRQjcl2rnsKUhCxstKMeI2EBMhacmkuvGMJWj2T/AhR+dIfV5jNXZH5tUjWzF87er+uxuZcYi+aRzZGGUJ1WmRVSjzfSjY76ESrVPHVu2OrDeR1gQBTTTl3XDg9HIoXGmKIACDf4hLmMPPq/m4QrziicSHSk3GZw0KKvShBEWTiqWVv265Zh7PcQLVJkWe7ohvTlR1QASHHJJc0qzH2NNmI63wNpu+YwiZoqIZMJr1P1j/Mr03afb3N2e+IO7Am4++XQGTEuFqBE5JiJHklIY1UYcnpH9LHw6u9+SMAEzbb/XHfNxrU4UF4xzrqb2fqTso9noON162Xzv070N3X7MxXUsq+a8zv6bSOnUT5LrIju/ZBWpQ9+hjGm2Fnn/oTEFNRQA//pyBNLCAACCCC3aGYkSwEIDu3kJIhuI1PuHQZRK8ROV7XSAjxQBS7baYlS0wHUd1o50iAZNj8qg+dsY3rZy7bHEvmtXQ777a/UKzYM7IltszVVE2GsHkxVND9Wnt27xZotp/vyf7QABkBlW5BeRDvBOsINd/MhWh1HgsE7dunXu7bfBMoqU45V3GDSXetzBAbmhV++xGnXUueQTOrOuENSWSdT6g1a+GPJv/blltuiofH08DGtlLyBTxuUdvfWer1Hb/rnz2SCd3Sj/1cFuhXTu6iHypIZ1Rrbcz1DpmUgCee01yyNkYsyqKmKe2+lgEASUmluhWUNA4zgiuD4lHfQRJWMG1v8NVfV/dXQ25rxPO0Tw5IpBoTLzt2HCR0pJuS9xcVb6a2a+h9uVTpcp2hZjfv60xBTUUAD/+nAElJYAAAIdNmBQQRy8QWL7WiQicIiA2WJnrEsBEB5v6DKI7pZKpKdlkmR2QXU75AfUnUM9cmuXM3Pz8fdIUwdLmEymUPnkpC9gToYRbl7GpXfwZ+uOOkwvq9VthPVVvSffpqbF1OCQAAQEJOSSVbmhOaZ4Bt0odz9M8SJA8K90L34PrnGPyFzdUUcOe89PiJx8DKl2hpR8SCzBAAiO9b0fVTN2MZyF3+sgxX//uTmk09Jh+hMVxFfMT/JKH2/dJdqL4oD8bmYgJudFLqxOhOdWZLOTn+j/alR9PyVd63UMXapCcpH/K3aVrq09iJIR+bdkkmz1gN6uq+z8LFKPW/XsLSpLH8nOcEnlkNdXu8VX6ZGZl+Wz1zqMVHRN1bcEPWCZDZWWa9WRZ+aqnK3POvfoTEFNRQAA//pyBAmtAACCID3asYcS7ELkavM9ImYITP9iZ6xM0QsV7GmEiLqBgCzXr70AQXz0LLhIVeqD+jKXo8LMS5FtHXVFv0fmW3La5R9WQV/KQgeZ1bkZ7Uo9f+hKKCS8OpeR4QNaxC31D0vs6SBHZsMtKXbgPIzRr5LL5VRsz45wN5/A6O9Z8SrZrOR9B2y3d+C5Zxu5mY1hc4QTIOnxUowoAkb3+hA7Hjft2paOX9gBKbkkumhgEL03ZTObDDX3fpYL1vc133lRGW5GzuuayH6P4J/p0FrmZvsbcHWpeZno/N/v1u4dthScT4F7Ka90f2MCQAJtuS7b5MJ9lUhE2K/o6B7/6D096wy7rb6Px4ZtH6VZejc8amVG3ZSI9ZGo3hYsEo95FBT32oJTP+c5Out172UMTEFNRTMuOTf/+nAEMucAAAIfUd1QwRPMQCc73SAinYiZD29FmEUxGSHu6BSUTlAA0JTTbleJPBqj5mCH38uCRo340+1qDPE37+jV7PcEj0RX30PqXRTdWdqSV28pmolkB+RNOv60Pa2gJdX0GryCEo/QgCQXUUnJJJZqpKYzX7G37A+vUDTPyb4V6zhCfJaIlPCR8jUyFb5rCni5hatc6lm8hRVb5I8YpQt8ZPch7rrLKAEAkBSSTc6s4GpXKAj6Dl7/Q09FUfwreVtxlZAWZ3/qjd1pgy6VHycvRu3X7rSr943e5T7Hpvdwr59b3Ml4o9R1b6JvqAgXpGRtyWpCU6exMo3qLNnIC10cE1EfbpMxx60BXWph1auVHQqqyrbbX47UvXb5JaPSz66jZiOzzrxN/bZG1PUd3sQTWmpMQU1F//pwBM/BAAACHCNYVTzgAD+nKzenlACI/HF5WJKAERYCL6sMMAMAAIAC5d+JG20YEWSk09R3Ocui/i2WQvY0OqIRs05RHIi7cbtoWP11R+2mbXOtUqQsPoO2TUjRL7uIbEEL/bTR7++2gBbCTclGKxpBLsrnqFe6Oa4nuxuPhQKo0fRAOeVhft1qOGP2f26rbQuqxSnpztzdNlaqNeudB3ENftp5P89bDAAACKrMcklt12GAEyDv4xO5q1F0LWfaldDGcRoTOzcxtbQGs5Sdx5UWSLizEqIMJQ9re0eI3PC72PclSIoISJswRH2P+8NXGwEAGav5Jbdbtv+AOQY/lWBvaZPKO69lo8uxYrAQDE34ye3+TMs2EoBuUZ0d1Rv7/tz9N2WQ75NSQgnbm9v7Lv+3ytE/ZXTEEP/6cgQ+5AAAAhIyYLYkQABERlwCxggACJxrm7wRgDEQjW5nniAAAACAooooo/ogXCWQVMJP9hiCf1MG1q2/6oqf+9tu3Iroc2R7WOBn7qIDFQ2ncWfwwm8IHKM/gg7nBfo/dxVpSpv7gJKKKKJrhwnHbqQqYH+lJEKfopgztrN/Wip+fjp/boro5kke1gMDPs6iAxQw+ncWfBAy9JQQbpfKBjlFt7vo6heciv6CHHXNLbY2knMEg2MjMwuzNgM4Vz6ZF/zIytiEUh0MMd1RVwCNQUZw2MDRChmeiPeskxOQZ0VhQWacaXQzatbpIFRL9bFAAANQAARxdQHBRNjBizfJmkNcFNGh5Yy0yoq7eit1M3uUT6oq4BGoaZw2MDRDZL4j3raxOQZ9YUFmnGl2dtbpINEvrqTEFNRQ//pwBIZnAAACEiDg6YEQmEJlfH0YInmIrNdzR6REwRMbLQWBlZAAAQJ75utpKsBepiaZj5jAtkwUEyIkEddX+230qz6J3ZhwifnkacE0DORFDzSiS3UP4p8iOrw7f1RbCp82WfWy0OPBbKMlsaiZJbAaORnrf90rXTjEyBBMqgv6165upvdmHIp+bb7sVJBZIYXi5FJ6USW6h/FPkX14dv6othU+8s+tlp54AAhNBtSOHsDAY82MyBdj4mgC7kh8PTrSkqtVla8vxpfs3qJqurbL0f76J9TUBXagV0S7Q1rNM4UPYq2LdW07liS3ap2SS9mQMk6cYh2zYhtqe7r0yglVKgYkaL8Fizxl9VrVmeXeIisM+32LVdW2XdH9HsifKmS+gj3aOTd0ltTXLFexSxLx9HYhMQU1FP/6cgQlRgAAAf81WhMpEzBDA0uKYeIKCPTXk6SETnEKD3L0NIlOQ7v4aBar6RuWtvFKjFM8KCTMtn91b8Y+vbuFEFRqYMysyO6PQmLk63bpR9vxHt1Ka1vr3bgmf2EgLr+jR/9H0gAEAEvqr9TiWVZGcJYze61qSYaSAKgnbMnIz1pVz0f9Xjm5NBMGjbz40XocOIlX0+6p/9krr6kGpk049m1JV0UdllYgtzqkjltluXdi/snKJzb+kXtAO5za4ZtIf7v0PVKTc7V/R/oFRi5dZNF9y2hfQX1vnoFEAcY6VdHEGEZSkpYJQPw66vWDMWFjTek01+0lwMjCOh1PuSFmsP5914oTpyDsQioueDJamhmcG4ARUYwoOOyDAccRl0nxVkj1dSIc+uNkakfX2O9YYaxMQU1FAAAA//pwBHqWAAACETZbmeUb8D/mu8kxIg2I3ItxRhROYRGGbYzyiYAkSa3YDVL/WDEQxVYVf9sHvXFFXcKqQS4xn7OjbPohtbsuhWekZ0N7Gf+dW6nIfJIyan/iu5jFJ4138iuKO/dV6PWIgaKnSuBUlokqSqBL+lYPjrRPuEq6crZ4Oal+njXtsqm7h9VzqztOj1tQPV03vtFGa0ein3oJfz3o7or4eWvoEAAkIORyUpAtVeiFVIT7sOXCZHkJ1jZWAVczNS9Bl2K1F2hWThm2Q7tcOEjwfmDrOykIiAUQxFlVRm1dHUWdK41GjM8se9RQeu2x7EiitVbRWxK+0GODvVMgEwsGwOWYhQ8AGCii6jrfhnASxzzBUgpljmlECRFRhcHWHmJamzXkz4o24l+cxEe+mlMQU1FAAP/6cgQx+wAAQhg2XFGIEwg/QptCMwVQiOjPdySIb/EYma3cl5VKAABZAOR25gSYoIg7ihc/SV4qc2BHBTwmyMs5TOEajbZs86e43kdbJXa1G31cHp/dkMRuNvordayQqlJAqvf3al/R6wKr8uAZNS8rFZyQD7/J1GVDr/IQBVcAo1hDjb3pJxE3LKeOyETkgsWddYo1Np22EDFH7XgiyR6/jpP9/P+pukQAZRO6ud1CxC3jP5C0Xj0C71s5+Rteg2c7t9JPVhPc6u1vMuq3r8Ih9LZtwEMY4RSSmCQrrYHQtPa6wHepjzaH2214Kv9ZFAEtuSRGKoqHxlNYT5QZ6dGvpzWsFay8/Xo1Ge+tEsw/UY1R9PqzzdW18tN/UYdx6Vn7CIvEU8RIqfa5pQ2uki9OjRVDf0piCmoo//pwBJO4AAACFhVaGewRQEAjq0M84nQI0M2HooTY8RgVryg2FUoERS79hb3sKQTwjMN74TFgAscloZMhdxPFiXo4O41xnSx5UsyVqAxqyhOqKEacYEgcfqd7WsV2SSGVmZ5ei176h344EWK/9OtThZ2wXjpuvOJlBkA8qvHlg3Rk4pL4SsO2GM/ejX7KJeJDpibSiUqq+qDG67ohFhWyzekdLRRf17r/1pmIIttN2SS5GFUUSHGH5WCW3NOwzibZ91K8W33IUifDmghZnETk79jzPlykRYxoEyxVi73Ph2+fhxZEsSiEqrqsAu+3qfGSAC4G5bbsGFE48J28TIWKuddxSlV75+ovjLtWwkB44heV6tT1We410O2esTJighVESAkNuKbuO75+ebaxO6vc52V0YmetyYgpoP/6cgS6GwAAAgs1W5HnEzxAhOw9BMJZiLxneUMI7LEeGu6otIqGAlW+26s7a3V336icyjygl82rG8K8AdHJaTevF6PqjVa/qayotX3J1/9lJUW2DqMp96ut9yzK1OPuDu9VtqiVpj0pEwhSUxWRy40A2OYXFwLOteMf22X1iI5dug5Z7Mvj3TyD1pqlX0rUdNfpjYnrpd96q/OsclTj5sU02vdiVvo3WasBQS2mnKwjvDzObyNBlybAsZ+r4jMko23qRlQUUROW1fE740Xe5xoE07lMLGJj9DIpTbIPFUJKlh0m4jmGuirEPdVtIlkABaSKSSc22rlJ6TvmrhSGiTiHUbF3fBKvoATo8mNk61gzSI2rvX+d7SKykt8n8nM6jgHYedXfkbLbbFUNcpJL0AENIrSh+pMQU1FA//pwBGbTAAACDz3YuTg6IETGfAoE4l2IARV3QKCjUQKZrA2DldgQAARW3CWvaIzuUCMbTTm8EZqmnRhE4IaBkWLg9BLjDxQW1dKWoEt1XUzXS+31r7f3/sWcoV0vnPU6luXzTSPP1daiBftOuOXE2cAktseMSItzWKC8zkGqBEist06KKqtVfZTwr6q8v1ZS7DUSd79tEwQt+es1vnyLpG/ZBpq25/Y/nLcXd0gOAIEY7d/TSI8MmaoP1nLmyF6PjfDP/j9k3NjGlJ0/ZfJsVlXo2lmYXfft/8U5Ofrx0k+JJoDVKU625So661VQIRkoEqid94X0ITPY+kHS7FnDNSGJEXJ5pfcXOgFjeJehFzIgIju2vUHmZtLxB6E6f1bstK1pTpqw96ZT5SiuuhMQU1FMy45NwAAAAP/6cgQ7tAAAwhpT4NChFjxDBvsDYOVoCMFPe0METLD8me0M8xWCYoT4pxyTddGShszij2eorVh/CnbfQd+kEwYg5mrRkXJd5+svzLk2QKBak/+nP1fT30tTSy0edSMqdKUEtQ2RLy9ausANO7CpG5fVW6sOs1sDw8l8ih8gW/KiARppiRklqVvDTj0RgzdtLRMGiKF1O8xFZOnvdX06f06cRM+nG+yft+yzs/oFoDUktNy525knudt+eKyYoEqLgm2fUbrrXfX3eD/nb9X7f278xpxInXv0/lfZjuZubONozMZ7oatn37aB9jgiSMls1ah7wSknLWpk8konLWmGmDGYFsabPg1HFZAfy8E4THJelbQsUuN8711to3fV//+/M9xXb/M3SF9FiLMr0RHTsRV9CYgpqKZlxybg//pwBDtUAAACCTLd6MEsrECGewNhJXYICM9u1JKAMSIZsHaMcAYgAACEgFpty5HZM3WT/qxedgw9Q9JlT9p28ll9MEqr4kr1VVVv1dWVOtp12/lnGEJFZq3keSk/1qjaqYE60qdq94IStoFakxuS51G/gomNXsNzh8cGnncpnP9G6LjzNfm8nwDO+FXSSc5UxoYxSvpeua2nulffv27Uq6oJNZJf9FNYDRdWhKMKJg9JIJu5DRjGEAjY5mQotw4OMgFBxOpXUr6D1oAZzIeqDwZxqsicQP2Tb//+nGtPf0vysnTbRH1v1mBBlRRN5yW98uu2uvuhED7tj1HGW/IzoVVal9Xvdqmz75RiZ4rPVTD0ovo9u//35h5sVuLV/UO1NW+9bLkt9DexIkMokm4hpWmIKaimZccm4P/6cgRJegAAAhIIXr4YYARDgRvaxIwAiKyxejzBAAERhW8HmCAAAAHJLcslr2gFc7YY8E0pITllBuIz484AyAwsReWCCzsUrw5URyIqKpWcUi6sCojzHJDri/pDVmLfSXej//pehE2AwAAAYFkk3JJa7oBar1fQWUXVsYs7jJ4XhwPOIKew1C4TNEXtiYkhT33iw82HsshkTmXE2jOnY/3+VQ73m7v/+budNH//lIBAdFpbUWdho4rPf7XGYUVEVnl2TdHuyKz3szGO3vsRUnrMW3VDUqUELuBaeDZ425Tnrn27526/Km2SPtTb1BL5qnTpdCoAADQxH8iNGsLlFZIjm9LCgkIzIFeAkPeaFTKUGC+mABYutN2eYVEaF0lSyTUgm0BiumVo+dHRZ/XeK+IWNdpdfvTEFNRQ//pwBLNlAACCHhbmaGEcnEPiG5U9IhoIcNl3J4RxwQKa7mWEiDAFpRy6uyNpJ8fOMpY55H0Y2BkjPyrrKPtmQeXc2megq4SBIVc4NYWHpYVqaXpBMrFRtohwm341lhh4OEk26jutN2tGbAFp7kBMBzxGkz7IZ5O/QcY1WLmE7D9OFEymKYNkHaXHoKuFmsc4lhYeli+XpLlYqXtEOEz7vGssMPBwkm3Ud1pu1ozYAD8Lq7asCTMU7gxSPGjxNdip4TLvN9lHz9B+SzU0dHZP7EPLh0XrzR1/EZWw9QTHjqg6LNZr/aq2JRrvCopqByLntRDAqQz+BUQWFQ4i5Rm0Va0HNNPzVUel+Clomhfx2kPo/o5jtRsuye3q238z1KmUEFMRDxVXb9di6zDfULMxGciZMQU1FAAAAP/6cgTh4gAIAgg128sJKGA+xszNDCKriNzXeyeYoXEYIC+k9Ag2AAAYCn/HFDVVEAs86ARNY74g/fLG8QoU2RnaFxKjadW767W+rVK1H23/20T80y87B3I8DPqcjWdCp3JWddhL/50SNJ/fuSySSwkQm4eXgxgYkV0H0BDPoIpz5Fy/A88NfqYVv//WRfIU3nYBap7JYGqiF2JSxVe5XklLO+r5XjkbJ6Vw+EqTzMLhPr8hG1H56KfOd2iEtw4ezrI1Q3rnoauq6p+ypdGmdml6aobS6OMIJrl/c+99LLEXtDtVy+8WbTaLAspMsAAdZPTWKYlRerWcfn9BmkGkYV5WrPyWoR7BcnAya5vXUt1R7bVTkY1Gl3v+ngqm//psw60pmhxp7nGRpZ7v8VteVh5TH3piCmooAAAA//pwBBs7AAACIUDeSWYobELoHJ0UIp2IYWFuZ6ShQRIscbQjFVYEApwdaYHQR2Jo2xzx+djnmWFHQ5shnSPZ41O+moc0bMqPV7L3f+3bsfr9LIrvUJBa5nRb3lZrrKIvOmdb2ozf6up/9AbTS0tUdlsuMzsPVVMqYW5gMNxlWDOXaLJyfWAP5vN/k/6+qN/89XZYY6qrrUzMf/hX+tgNSMeT1NIibiJ5XiVDdJAF67bYMVRtAs9eIXHqEsmwf8oZizXHatqvmbHdKAV8zXYiyUilZjU9RXtxC6obKs0lfMDV6ze39H//pVl9X+n9f1OPDJROrhdsskoOop87W6WtBzu4dUjcvWu+huKsQDgagsSxD2I+O5HtbVu3UZY6TtW2q9x/pr06vuMf/fXXT9X/Tp/nH/kkxBTUUP/6cgSCmwAIwhkfWpnpEOA/ZBtDPMJiCLTXdyMIrfEYGuzM8wmICFl22eD82bh9UaAckWBtl4BPVGemd1QR9DPiXEWO0wHu1B3ytQ6YfDjHrElzwYjeSc6pa0NtfadQhn7K9JD6K9Mj9AAjltrAKRlwjPlIq0rgx3qqJ4KrMGdxboEA9F4zkdn1Pu2c+XMd+8ouk0uVqfbSE8zVCwTRqtZVR8PHOfV+3vEJLarMS52mAThnq+vJFwDvqG0M4HDvmNkaY7WAiRLIeIaZbyv2096qUZp7U2c+4mCITHuKJECyjNjXCl7Do5DdPvo+tk0AE7bsYBY1Wz6glltUwT8U6oB3FM5xb8IWgR87vcG56DtcFo2AJvlbk6vlTTp1eisVCtferPd+4nVxTR+9vYFmeSs0fmUUJiCmooAA//pwBPWKAAAB8BzbmYIrRELDK2ox5VIJFH15QxTp8R8a8Shgib4ApOSSNCdLiM6YoMcNYnRpuhDYtkYfp0hIT2zXUN67jFplEKq3XrAzr+BzceROKIbzEKhptvdipVDdX4u77AAACCCm//V1jSPrBqccoWXXRUWxlNsgeZJth1Yk+FD2kG5+LlnZ6yyyQkHpWTPHpN6jYPSx8o5DbVSxL8hVaGpv/khAArKTTScLZ2Dn8xTHsR77jXQRfINZ5WC4wY21yLUJOUL55ZJVpGyKxDLFAkSGG2uZXKt0dOv9BOJXCziE41TQqZiIC28QDlUN+N+2pLbc/3roCGKrfhWRgxynsfCwsmpF+B5c1msunRcE3NRW20XolEClRQoqfGkh55Y4kaDmGqywjENA8kqUG6mZswO3TkgmAP/6cARoDQAAAh1MXrhlE2xCyYt3JCO8iKk3dUCYQXEJn+9oMI5+imEmm07AhsOrhLRUUfo+mr9Oeag5ogtxJ6AKmmdRtRu+nvoPoJ5q/13M5Owq6t5d7/b+3/qSsEYYj7qVkEplVlnx7kAEABTktxakj51ccM2gqaIOWoJd7try/v/+ut0qlyePlnXX9998OpL74XZSm5H6cn/X9dz+QZCYEaw29jlua/CFPI0AAAwCEkk5LTQ4E5Sboat9lHwdApNF5XLBiWxWr0fpog3G/nvEaaIP7af5snMdmjb+/fq9S9f9tyNcQ7gzjwD0XmdFllliBAcghJuO0mo6h0aLHBjZORmcf5Hyn+eT/LKuv764OKfy5zK5AWQ5mrYO9a3qHNCrzkJmjzgm4sYFzl2KeqqecyyZTEFNRQD/+nIE7kMACIIaP9q5hRO0Q4fLejCicohpY3ThhE8xAyctTBeIMgAgBJuS46wJZaOooxljLp8XOxDgxLLxMjrCuIrqNq+f8ZCprovfn6cLrTR/yv/8v/StYA29O91bl51b+zEx9u1db2pAAAkANuW2G8SGqSDXqDKOGMT3cbNskwmGZyPgmJV9U1fTo9SFtPmXvx9E4Pp/6X08V23/wtoRGp8UvJVtWsnXv1/bqGASkU7PAUDoDFYpxBluNnI+Q+JPfHm7KKfd9R+Tpqq0Evh2qj4T3/9P9/6e+GTX//1yoqIKZ2KdafyXQGLpoYInSRIAFtq0KmX4jEXVR2q8rEKuP37JYPxunMMeo+oHrzj9+P06dnWAvg/fQmn9v9v7dP6f//ujudTKQwEZQfVRVFX/oTEFNRTMuOTcAP/6cATuXAAMAhxO25klE/RCScu6BMIEiEkBZGew5REEn+2cxIiiAKbluSuIjCBWZWFsQZK/kgtjKK2ojxtqPza8MalsaKaF5f0AbVXqnTp/9Oj8R/VCw00cnfb6/m2LxqT3beKKafx3ePQAC4EpO7cm7hj5HiJbBR5BLwVgQhaA3w/i+n7E/VOXr/T+n//+fRe39UoGpDN+nStXe5tBkxkplq5aKoM6lvWkKGACEk5IfocgeD8My6G0BZeVjR2Lk6uIWQ9tB50kS5OUO0XUgxQLtcq3I6f5vGup2h///+/fRv/+O3/6Zoex7XEuimgAYACdluPdQYlUaCQRk/6QC/kfuFwID0BPiXSCF6Pq2cuvt3/t15uP/Tr7piqxSOEaiyKpuXhXJ+uiJgGoyv/PziYgpqKZlxybgAD/+nIEdoIAACIiWt9owxQcQ8gLNzzidogpB3dAmECxA5vsjPQJokgQAImSW23MBovAZp6vv289LROlKm/0OchpL+TTu+uRBno//xXJoI6df99H0fBdevvx0ycv/0fBtnbm1/+rpQaLJudjQRgAJOSrhR5XBWl0GUhzDmJfns05duWI1TwmePruIz5wtpm7bf7d/5+bQbQT///T306/0Px404p1vPW3vbb8nISNHQsAACgQk03TXFDXw4bVgryis1ThtQjpZjyK2ubq+uUP0f/76F1FtQiad/52zc6bdfXOfD5GyiQqeLwNTT1B4Vc6mptyN0a5sGqXYNhSILOYLgLpGUTGcvUuZ9FV2DtzkHbEaM0i69ff+/fBLq70GbRd+vP0Jh91stbJU/ENsqktIy/1piCmopmXHJuAAP/6cATX8wAAAiUYYFBFFAxCoxu5JGVliCQTf6CIYAERhG/0IZhYQJC8ltxptMjLQPoyatUPWC5BFIuSde+rQYdhmdss6orEsqPLnE4HLORuyJxb9GUBAEDkPhiouFwfHh90QAgEDgIOnPy6ABUlLw049LFzjn+qwDnQLer2CejczknF2qD1VLgc8Soq/qes4ppMHL7T57XuUBLfxAGAxLjvE7784GBAUDESSHz7iKBCAAACkVKShiCSD2GrigYSoHxACBfggXBAMfxAsCBEPcHwQcT7Kg/Uc/2g5/LzYnD5SUyhztc8EAGUDFqaCjnIoVmgAAFIuVcEQWDG/OcMhZwoGEqB8QBAvwAAwQIdPBBYEOASmD4IOJ0WVB/Of3CcHP4npE4fEEpqOdrnggAygYt0FLkxBTUUAAD/+nIEp9oAAAIWJGNoIRt4REEMBgRgCghcU3YAvMABD4xztBGJjoABykiiUSkoDBA0PHDuQqCXSoAoD+UyQGYduXyhHtyCp6CtATFH2OYIH1nHn3BNwTteSvXfKpOyKf0q4AD6eAzSdb4QIIVQMCQAAxAGe5hRJ4RFQkeArgAFQTNVDxCCRKHVPQLLPloivgrQCoo9rHMKP3PDx0JuCfReuiVS2lP1pVfcbT3U60NsB+wEVIUSa6MW/Sdy2xI/KJEh16tzcpuyJQSrADg8zA8gMJEgKMc1OUcBmoAleazrC6yyqb1v1rte0VY31XUJv9EDajtjbkbSTTpUG5zRuwmqkMuk26rfYslkdRAYJBXB9xwYSQBRncoYwDNQBJe5G1i1iJVL3i+8Vta+xjUPqVbMJ78lsTEFNRQAAP/6cARSWgAA4hMIXilmKLA/IjuwMMMmCQCBeSSMSUETiS5EZIxgCQDsIC4j0eaB6Xl4LOpDJVwIhUVhJpMOjRMg2FUjqxVoaKAdjEMF7osAh7t+NeWRYthJUmvMuVbzHQ6tlDM9blVTNrwC2AdwVNYHVqFv04ceqfMw7G6hQiNe9YcDIGSbFYkCZVYZeqoqMQqg236E3uUlVjF9BqyvQ5lJiwWZ+vbYhAAigJWvekGliq64Q65EL7fF8Nw40qku8m7tXaymcurUdmYZbFnXJhTbFx7uwfGQwhFEqUYeQ55L2FUY0kmoi1lbI+kyskE40L0kADQfLkZ5zouQtxa2XinBrvSd8GZwWAxdTgVDoLIkUGFiiQ25McbYXQ0e5GKj0OcGELciVUx5K8l9HGtT/10lpIJxqYgpqKD/+nIEFoMADgIIGFwITChgQ+IbzQwiZgf8Y2oAvQFBE4juGJMNSAHgmlxCJDb4QWX67AxHTmhlKszEogtJ1eLmUxA1wRKPCqR4wqhaSPI2Kp1bHLSwi5FDdm5Z5xmofSi5DlLkdH0rgABAAJIRbbmEDDigAxY0EkUFDaUvAqeKgBawehkddJEWra6OfaqJAKevvEZxRXKKNTFcVFga9Dsi290oizeq5jSW+lR2o8S/EqZDmJLlmjRW9QhAS0MCTJlFGwfsIUMWVe8ydU8dHvF2i5uw8EUT4iWoyKx0Am1YFMETSk7f9SKf+v+8AQq1/lDSIGgeSRDkh+SqEpVfAvSYCG370wYRJDCEuJzxpxV1666WVJK2iVFRiBTBFCjbusJgoTJU7xFEJHoqXxFz3m9iYgpqKZlxybgAAP/6cASXlgAAAhcK3skBGZxBAqvdDCJ3CGh3eySEa/ERDq7ckYmiwADUWVWrz7CMgp1einPISMEpIqo88eeQ1YBEzyMOhVJA6LKmidbApa43Y8ZDo8BuNblCp9qw2xu9nlbKDdj6q3/f1MAEAUMxRyWfIE4oWEZbJwUWOiE+YYagam+GOTInkls2dNJZsc/VQduvlQFLNET0RuNiVbWPqZ51XRTx4nvLAwsnACFQMq397KYbWgP9+skJLCWmlbqDffIodJVYbkmAIQJYWWSDRDps0lContcXxS5GuR49gusC2Bmlow62mkyiYPsc1MBwU23JPSSawXSo34/ThjVOhvKQ8o2nCr6eqS4zE1GUCqWzRETsYl9UDi4T73T98jWrGEmOSJlMAMk0TXdJVczfbZY5aYgpqKAAAAD/+nIEdXcAAAIYFVrRgjOAQoJrYz0iOAhkW42hiG5xEJrxdDCPHoAAACBbkks/YVgJAGJwNQiZTOon0Nl514pvTica+W7MKQhesasRhZ5xb5vQqD1CVxRwqdoVmnqWHHEuSTq6vjP//5UEpy23HsaKgK9PMISzaakTk58S7yH3Ph6IgJmGBjzMobEgjRA9Ty06RNJKvRWt5tdpo8PiFcPJYihydnX9fXS+2r6cwUmo465K5MYqMsqzG1UyQ8L3Q6spvmnD7DoWiOrfDcJOSfI5Q0BzA+OFCrXk5X9iH8u+9A2jTqXd4BcggZPFxIcpXUCkk61HHHJW7SH1T7qISH4bcy8s+ETEQ5yaymUt3hFkGU+G5eX6DV/IzPsvBMk/U1D6SVgkcoJhLW5r+p17RDbxa1BFMQU1FAAAAP/6cATPZgAAwgwp4FBhG/xDpquHPMJECFzVaGeEVwEIGu2MF4go0BFsJNNNynmAhQtG3I52tl2OJkhKaN5LOZD3yCuL3lRHl4VSpR+xzrlgT6nHCTaKSSUjWNgI2tneTj4HqrlQ9IkAAhqa//57W8JyRUszR7zOLRNrCtwS3dTDUa+CJd61vvg20etLkcxmKhUOXX17ovtoR6hjwnMQN323OdLG+jKcv2X9FIITdtuaWM4TUFaQM6ilhI5zjR3pxO5v1L/a7XeC4+zFP66mbwDlAMSosl2sewalZOz5Zf96PeMfAiKbDNFf/69n9W0Ey3bc8E/hHVtfYFT7P8otgMONIAZjgliaGXIV9OhtMicbm69HdSI7gjpo8hVeif5b8BVAZLKTe+d7P+y0ZVLak+tMQU1FMy45NwD/+nIEBb0ADIIiFNkbD0nAQ8KbVz2GJggQSWhntSYBBQqszPYUoAAUpbcOafxqAKhGEwmHMyGsjpnI5xi+Q9PfP2L03cz5nUpNV+u4sVJOGyL0UMS91MSnbvygcU5wx3utewZ/qU1L/Rs6ACAhy7/11zOD9RidCVYiWyKSWTifoHv4dkm3S6y6u9znupXGzbyq3Unh+8g1LlfBg00BWDru8W5xp4nnngJjLL1in+8Apy/+TVDSJ4G4J4aQr0Jo8WEAXp3sL/pvk1bVUuY69PkppmKoOw7knK3TSW/asDKbaQ8NTQvS2xf0bbPopu6+gANS7bEyILIXUIg5PgzsT3iJgGkjtKAbGj0DVO7QIrFvibzR4PpPIDr0CLO7s89ULJFp9drWk275zYOvei/93v+lMQU1FMy45NwAAP/6cAQvPAAAAhwc1gMPMmBA5lsjYYUoCHD9cSCwobD8By2cF5QqrX5IW8FNGz5JxrAvuyU6NTQyy+hQDQQmEpx7b0VKoPdHs7O4yNrqpdUu4TTgukblSOKK1/bMgF3OLoNihJpaJKm/oqABcu21x8GwR8mi6foKUdtGLBPGMv0agRFINPVBsKIqOoj2LjEf5H177vV678dbq6N+2wogtSdRzdjCtHX/Z/x1UAAIKTNd4bjRUlFkfty3c83kdRuo668oThwHZXifJe/bcWNS+16Wl6bKtiNVjto/xe8roy0f/K+MsIkgp2r1pSjp9NEgQQU3LScJqXiJpGhSpRq52KoN6vqOGoNQ8mQBYeYkIK6j/2MbIwdnNm1RqE7fnbHM6eE0petyCKDIFSit6NCYgpqKZlxybgAAAAD/+nIEi+MAAAIRM1q55iokQwYb+gwia4ihZ4FBhFH5F6vv6DCLFoCAhtuSav1IXQW5jLijsqQRoMCaOqJNirPFas8KOIu9bU6d8zFaLGeskaxE2c5Homr/714jkWpZ4jhyyqK1fV9Py+kozBJuKTQXwESG8XMEQG8HRnU4pYnvWgZ/0bd8/WjpuvCI06MZEb4V66n/lgupwwYBwEMPmuecM3l9+s4ontUFxTToS1RKjjl+eqCwdX2OuDv6+7h6iV5f11mFYTzZSqXM8jHjoXJad1Tj7Pf+1O7NT30/UvXlz3/VNTKUEIOwUymHZjPdMrPpivRbbjk1OpBdc84bEpJzLal97UKZs3BjjDcY4keawgzPBJkWb49le6cnV8KTMPq//zM10372p219dV6/19LxrRuYomnNTEFNRf/6cASLBQAAAfszWjnpEbRApntTMGV2iQ0RavTBABEhrC6qjFAGgAACk5bnF1c4CvkbT5zVXH3FhET+htTHRBcKwHKxDadfbTr0/os9tehP/+3CxIaK/KutX7vi74042XdEt/0dYITbluzCmiF768XbGnjhQHvZ8D9DY9jehyik5ox9bZtNxq4xboaqPRGSFpycntn5eI6YT+7eS6PpdqUiGq6ZX+oAgRbcts9KlQIR2H6+131SZ0q25yFqrllK6lCbBgTMHJQE1C6Wq4pJBfTTod3KJ3XW3/o7oJFQQQ69/3ZJ9zddRs/J+OuRo10IAhCCUknK+cxwrT9dp0/NpbQg3V6uco6hDE0bufbRt07/RH68r6+//VNRg+glXft3Si9+tbd++6rVLojtQUJkmOiTqdYq39mhMQT/+nIEnpYAAAImTlyOMKAARKnLgMYUAAhVWYZ4E4ARCyswzwJwAgCScK1hCq+bMhRCgba8DyelaqqIy3JORsvJWn35zuKL/+4oRn//8OAAKC6E///A4fPWomL///+RTsouBCTn/+gH4PggU46wVcS3yyJBmeXMXDhouxDSh9TuRhS7lQ9tn2T39WY4u4ov/7ihGf//xAOCguhP//w+Lv1Of///yXZTgQk5//oD8PhhAAICAgEAgHObgpr//////+nsjolP05KJzTnI/+/GweSJicH46KQd///kxuQUbggNRKCymf//+ooHCZ4OFFAqEkkYKQAQEBAIBAJ1M6goyXpT//////ZHRP9OSic05yP/vxsMnExOD8dFIO///3G5ZSYYGolCpTP///UUDhM8HCjgqEkkYKUxBTUUAP/6cAQeUAAAAh4K3mcMQABCgmup4YgACJDZcyMEU0ETGy/0UIo0oABArTKqtGge0CK8hxzh0BuDRBa1rsjl12UMTNhQek4BmpZEoTHC2t8xBQVF4tQVagsmuyVnRQWQGW7MDG8w2ZZ2ziIAAIpAAYcB0BAkB7MqDmx0D89q5Surg2YTYNn1br4GItNJCsdWCpMVZk6HFQgL1suG732qzq1CrCg/VpDr6BtA7roQEDwtmb+tOAiaksU+ltE73XrPByiyKcwZrPIyFCmYVyFBgFRkaz/oKW6L6q30h5GvVyT+qTK+8ZpWCrAq5pJ4bRimpC4QBFPUZI00peViOzzEeZxxqAI+Rr5c0p/l6TMK4BQOAVZrP+gpbp9VbTRA6EXrc0UZiR+YVBYS+8ZpWJWBVzSTzqMU1ITEFND/+nAEXWEAAMISQFmphxOAQigLEDBidgiVA3uhhFYhFi7siPGJoIANff8B0mEoUrS00zqhQ62g9hJSMQZAtIGzOrNZkono6+301ImarG9/V9X+rZ/UV/Lo7I/sGHVPrW5Z2K9WV9TParY3A5AwCQ8jqEVaWNgUO3T8/4P7iAQ0XBgrwd0aR9CtSjxt2/dFJeat/01eiuvq2emor/7sj/DDvr2vFVasC+pntVkAkHHXJ9rr7KYwdaWORNsnwX8WDZ7KWGOnl2mL68K2+gXVWtVqyV9S982q9+FFv+TlPqssBzp7DQ5RpU99XeKN9gaSAAGq/OIfNol5QsM1IlXhRNwpAnC6GEo9Y6EBFHCtgm3tP1bX219rV1ZqreUnmpt/hX/r/Xy/t6rd0lpmzf9+3onXrwaEqrTEFNRQ//pyBBSKAAACGEBbOMEsMENoDC0MIseIWNdsZJxPQQ4bLEjDCdiAgMsu0r44BDA9pjHqnA8l47K8nXIHz60jqHMwx++xe6KzVTRW1TmDuuatdz+IhTS1SnK75auMSWsfSWa6h37OHfsqaITLkijkbSmVqvdN4WSkJ8V1BbGUOo5eZeGE+SBBy5dcGE0iIkQVAE61mX/ORFUKTKnC0/7gv2o9b/syxF9FQdGCXWHLJdt8w2QkSKQ7Rljw18o5Kin82hj1T3alDkCUtYikwzbmzsqkeRLzrm6HvV/70TxNkbvcTvQpGqVcxaG/H8E3/ZYBXf9EyjKo8B2G6BZ4vE/EQusj/G/yOdtzWIA9wcaXdnt25XoU700H3S6t1ZpltgV2SbVvTxrN0nCtP8Y3aVfrpZagmmIKaigAAAD/+nAExxIAAAIUXd9oYRX+Q0OrjSSiZAh813MjBHLxCA6ryPMJ4KQAUWmWmmkog2tkg27bQiPe8p5dOJeTz5FZPvIfh29Pt54KhRLPiYXjeyXkaDyCeWvn/Jc6PL+f2VejnShvwbniL9oAAAbIk13/6TvGI1A+6o2aXPAnQSxMNTV0iuxaqN+9rvRxSRWRmHXkY2UacAOxwPiw4kSNMsEmxyvxsy1TP097PvWuARKSalZtY82eBZaWLlrve+9i6uXQpIHFsXeYuiz/b5mbXpj8sNlpcYNv1H/Q/klsFDND8asXJ3s1rde8y3Ja0Z/v2UADVUkexO0JSYSQfxNLIXhkClby5ucHnE/wMk0sfpRY7AN/OPKL/eZGmbHbdmkPlHBdRYMPI3BGnfs06/6/QW/R/0JiCmooAAAA//pyBDedAAwCGCvYmeYS4ENmyzcF4gwIcSNmZhROQRUOb6gRiC4MJyOTG4TKiSat58Ening5jikRSceVfl5PkP3Nzu6cZ11lRqK4jUR59eXt5HuvYG54EpSBzta6jK7un6+16W/8Qu+RAIC5LbbcJ6jS2kaXDReS71E4YMWw2DGnvc5anOVq6o5lPyNjdVLV8juy2oxZNbIpHvpqrvWiiLb2VSree6KpGT/6g0CZZttP1HlEMJeHaiVT/6lqisTcMXS4Uat+rb6iMh3qVsImi7r3S5Dey2ZP/qz0glXsx+7tT2f1TfkjRRjA+x/2da/TIMU6Zjbbt4MiDIuSHTDs2ftHUvAXVzM1R7l7ddQYdg0KNXUaXXijLNyyLACNwSFUtRnXTWtIxqmPa97aKdI1151AZUyLpiCmooD/+nAERjgAAAH/TVzIoRbMQGObKg3iHAigr1pHpK0BEJuwKCCPjoABgKqq1dVICJNHndZjNh31270RjtYixlkBUxA0zeI9+eTzB8kfPvIyYhzBHo9/t8ysllU25VXmZYLdc92oh9QAAYACW7bWGIJIYDESRayzMbNBVTBa/u6nswcdV5nUU3R8l79uFZyOZOrauQa658PEw1LqOrI33Pb+jz1elH1GQG/zNUmTEmCUMxDAftUIQk6D8ZSUkR/UWpnIB+aSPefEu4sIi43jUFEBjZmqgvydu7o59U3d3iKIw6LESh6eUQ6u3/f6vBh/TVkkmVntVnkKyV6iuxXvsTc3R9f5tBz8RnoS3eEHfh/JnErI32BswTg+HrnOEonmL7mRoYwqDO+kVieQdDSUqd3JiCmopmXHJuAA//pyBGuPAAACIk5eUEUeXD/CqwM9AnYIlKVm4yRE0Rsnb3RQix6UVdg0225bRYJZBFXGe99vXO6OnUThH2tN35w3r36dM9pLvGJv+iNdme4/n21ZZvumZuftbeAn7iCKByiE8ehL3dx3c8ABu3DzVMxKkDCnaN0a1MjSqhKKZ3yFaxh7mZt6lVeK8Fi+k5J19VTmuFR6os/SNJvcdGH05OyyinZcKuJMFZWAABLbktQZIMLEYgAux5QnKsKfvtB1I6HOyqV9PIymbZ9RHT6fbKg1QQ5LiDW4WaeW6yzFMOyF3XVS4YaU/ZvIt+LXPOREEEkotJtyUSHMjsNcl7yspN+9qUddCi7wkO14+T4OX6ebVVgHxKv8WjMlLLVunKpNmOCV6NzPurTM6px5nIONDOsNU3/9SYgpqKD/+nAEppcAAEIYHVYQL0BgPKgLdyAimojdQXlBiK+xHKhuHFMUTgAfwhFEQcF8og22YPSlGIb5pF8Ot8yOrgAvoMXQ+0DsHXks4+sZf3D4eP6xygvKy0Xi9bij11ecSdU+a7LJyz+uuqqAYJLkt0XbBsOiROOzIZEkpfN+SoRPa5vr8Hvnw8unnz5BffT/Jy9+b+jujsjhJpivRWRWpT1e6PIst7NGADVotJuTQ4o7K4+uMcV3wLSrOJzhJHMv9KFHodtRXfr0/n4V06f7JY2u6Cv+z1KkfzPSyV0nkY3FkdBXivOcg0y+SOR8DuBAJKSdvCw6aA5kCe7WH4tqXlq5Nb9ted9W3H9+vN/XjH06N+gYhEF9SOhBWiF1fbzXv/+sjJ3ZEFdhW590yIHKMucAQRi8kmIKaigA//pyBJNEAACCGTXYGekS0ELFKvM9ImgIoHV/oYRK8RYJrJz0jNoAOXf/e+LqRSFoYTuBg87EpCSvaa8SH1SsPhr9MfyqXV6vroZ9dgfrqbXofpqUuqJ6eraHwrzUrwgoQ2076MDc25H0gBGXbXnijDNYgY0C5PanFZpHu0CYEy3iIc8DN7iPb4X9wRdW1TJ1bCvqjV8v9OFirdVJ02wrLs9T1H1+znoNWzV30QkEkpNNx2S9zoMezEcjJpLLvUuo14l3q+Cp8vCLEU7bZORYqPIEXH1AnUxMLH0212W7ukCEkBNLUrQ6/DTABSeKpUSKUFBJTktzjJQ9wHc1ElhC3lVYrDpyHuPjUaVQh8ElOw4xsxORWLQtXCEk9djkZ5p9jw9JsSgVsn/4EFkFBG0Pj59S9T0M/QmIKaD/+nAEnkcAAAIjNtedPKAARKUrqqGUAYhtgXhYY4AJCybuxxJwAAAnNsM5RYnLcbgnysEZgHDhbZ1BaRlw7iKEOQExgK4iJuLZn21NzaFH99+ja97qZdq1fbmniJ1U1YqaUkQyyyxjX/XxsAi8kpuJy0sOICBkWXFh2ycklVJazWJr6dke7ZsYJv036NnK8XWcJC44Jz4CDUOqdPPOzms1DhwZ/JLDxd5Q6hFs5RIMBCCCCCcE+6cfVoBAx2t3d+NCH7H//U//zXMf/+eyECZ3/+NBsAwsQHBI///JEK6n////e5ijcWHoXM/////kPmI0gACSTFBU6QKybZEhj1LA+G+oOC3WphNP9jFJ/+rmGG//k2Qwmn/+NB4HhYwwaf//lzJ+p////3uYpMgFgJ//ykpD4YcmIKaA//pyBIKRAACCJCDeLzBAAERkG8XmCAAIkCGHpJTAIQmObhWAjegAfp8KwNmA7JSSYsvQ0Mo2Taq5DP2uYU+9S6O/1wT/vVtRRi5r60NIg2MnYq5C6clOlYlFkdvSxrkotpfGEciDPiz5KOAF6/CsDZgTkpJMXXmWDqOQkaXMY/apjd0cujmm66P6L245i5r60NYDYydirkLpyU6VgqLIYiS1kWNpRb4wjkQZ8WfRHAN2Zf/bVtJ2YDgvKmHmbZIiMSWAIZDGfS0gtz2WnkQNNoMEnFJni40PGW3CzkjrGttW52r6yIvInUhPom45Sxx4kLbDo2DdsExWbhUo/lnN1c+Vrqx8dgupXOdvNYf+5LBzyaHGJxBrWSE4BAtA0gg2xSV1yRXWz4sPOqAsCt0uS9LGJFK+VTEFNRT/+nAEJU0AAAIeNd7R4yhYQQbLUGHiDAg0T5GijEexEprxNICWzgAI+UbTJLU5aCRTAlszLoYB962N6UR6IdmaZ1r8z2z9DMNa/XZfbuUzlIqPzqy/iKn+x+QvXiwXOiLXZfmy2o9frsiJYMXAaCFJ5ib2l3daeSsFgdC1GVmnRjmk7ldFb69F3fQdehmB79dl9vUzyLfnsv4Wn1J1O21kRKpm1VPeexF9qqgyq4tY7LGm7Bzi1bjOxxA4FkeiUfhkhL9XHFDwOt2Sz7REoPTwkcR5KQ1nVYi/GHqSWnTvrEXK2d7oaflgdmzwlYGykzK25G0lGCMeJ4bZ/dikBtXaJqdUdRS7jH1nf56IUnDTcuah+lWzP+rVMX6lalZUBn/GPyX03vrEX2fhp+oeoOnkEExBTUUzLjk3//pyBN53AADCCDZZEyYToEAoC1NgRXQJJWOToxRN8RIbLQ2SifABGqMSIHnRiPPunK90ufm7SS3VPeIoYIf+YS961dQoMUqQF47ON2Bj+7dgd7fv+++T2b/XrfQXotpoq9/ur/+j6gnG3JAZIM9ORWxQUUU5dooxrtkRDo8bi9qs0ZGqXedNJ3u2jRMGXtTreXVN/yt7f6/H0+n+SkY6rqNyUf9X0fYGm3VrHLbZbitbdMqM+XiIoHpUTQaK/ZelN38aCenyvrP1FNooMzq36L/WtPzCuvXo7rojB23Vm703VFurnNf82rG98o3fWGrKwDJJJAvIiNG4vLexidmvnH/zmag4VKreKuwLqqjhuhHtk87W7YWRaFyi9vTUtV70h3ofbf1XUVQyziSA3b8ij1v9Xo+tMQU1FAD/+nAEut8AAIIBNdsZ4xOgPuKbYzxidwj013NEjE9hFRrupGSVFig5bbULCYblY7P5ggT4yfmmxrHZIhL6dGPzoyVLXRU7qv27mbypqp9HPRVIq6OVqLo3TteNG1VP7v9W3/xb9/UECWm4h4eI6sipHptzhVTm81BhunfG0En5roZxC1wNKeiSdo1i1SbQWEw5ZO0UqknjKYu/hp2jacvuI9irkxYCAOY25JLlQLgZeH+s33iPzgAFIfrHxD4mTJGRIRk98qIp/P8G3u2qa3jaJV7Kr+3LT7oNepTLmU/rc9pNSH1ENKHUMv1IkEByhMtmhcFyRTOv6X1PgRrVmIJAnTNIgixm0+3+oo/qzdfs31fZ95qvRG0XitS7dpJNH2tEKVA6KElFXiAgFi9BFXSBZJqYgpqKAAAA//pyBP/zAAACHjXeSQMTvD7jm+oYYnWIzFNk54huQSAa8KhQieYEBOZqqunlDjX7nEDWwJScletn5XqGoWNxu9U9fVtJfbRaCfRdHBe/7lYqmoDCaklolIhsUKHL+XWyyQJts102P31IoAIj5NtNJzKyvGqqdajaCs570Mndb3hVlqpPKjpYTeIRY+ucnU6qluaqjD6xVerYz05OPWsCybcXu72Lfh1MkAEBJO207lKp0JVwnDWwt2WgWfSQegrEiWmSIuxMBDLJYb0qPQfYk/kscq5i3rM1DNzKQsW1OK6HPJKYja6PbP2OZv+LP+hWyf25JJJUYpYwYNFlqwyAvhgEM7NnAQmYdLyAnZ38Zf75iyNYVVW2VJjF29bC0pRQWkvFGKjGhwtU4XIrctbEHE2XpxM/9mhMQU3/+nAEl9AAAEIaSFsZiRKUQKVraiXiRQi8k3VDLEpw/iNuGJCJ7gU1JJGzHXrIJrebNjRiNQZxnehOwP4Lnt3slKHfIz0qQpi7bStrRHZQS3SVUSxmrS6mlr00R/XTdv+kQpiFDvx3/uvAACApV225eaEJavE++UqSreESK9mgkm7R21I0jopKOjfbsY30fTtl7UfBLNF9wQErHOst6Gghq3HUdyzf7+6n1AKBISWkk5zzVcSjpr0J0XibhGSYR3Bvq1iI6HfVhv+10lnZmODa40ILDCGUM1IJJD5WP9PRpschwGxGASZG1iLIuxSNqKYlpmuLGGNOpunbyvyYX5hok3pk8kdF+czai9Az+z/y6atdkaTJr3erU5bUv+czU7/R9KAmMRcYW2Scgx1r+7qTEFNRTMuOTcAA//pwBLvBAABCIQ/i6GsanD8my0Mx4lMIgD9kZL0IkRMQrNzyjeqGNhuxtzW27wbNHnPmoiMGGRwLYI/Sj8G6NQrnIsLXDjpV4OIDYjcx4u+rgFWsS3Ui6oo/9rWkhGWSKsa9kRbTOe9hNIKJklDRycB+8YNiT1WDqyYwPBuVt1qKyCCUqZ1u35R/a+yf+2fl1aZ91p+ruhC2PUePKkEwrxS9X4jizh+NxUAFNyTWi4UMo0RsmWlIDt8dwkq4Uc8WQZc0+CUCIXbJUpZTKEM/KSVxWZNgBQVA7BSOLME/oltS0zQpSOXQhTfv6LNaggS03JMpBRIZYgTQZcTbKnfO4hPPE3dIWBnRRN6TLstCd0Qns81CklnAQz61JnY808OVUpsW5VGW44e9KkT7Iiu3/6/sTEFNRQAAAP/6cgTADAAAAhQ/2rHhHdxCiAwaFCLliJSlhUGkqnEbiGzYh4w2AKAi1+fDHNJikXbs9tV4orJbX3qTHzSEiFq+vd585HwWXfEZeQC55dZaeL9/bzsL0/+SUriQ0ZWDJVzWnVbnN9VelA3e23JJb1LWdnu5jiJQL61NzHrViSNs3snf3Ev0ab5zFkhBHsn/k7bzCef/s73gIRFs6sap1SwcU1fJWqDT++pdKp3O/kkll3jRhLZFe4kVDEa1oZtglK4ixEMNcidkY2qJ0V9+1CszvXlxB5HXhVtiguxutVw2WaWc+KaRhsyMjnKoqUPfWAQBFbcLu08/D5ss1ljRPuIGNEY7qYMNPEhTtGAJ86KuKJDiyFLLwG4q6KxWZq+Bx5acEgfB61qXd66ZaigGwospRYp5aKl0xBTQ//pwBLZLAAACHRjeUGkSLD4Ca7oY41eIvJ9s5LxMMRwm7qhliU8FRZGm03JoUGILacxLbSGVGTwVLdGQ1RJKURn1Fg62KHMxeu0bTZdtqW4RHD6kbrsPtGzxRhB7WSK6qO5EWSx5tK7MYgIAySaacp+aE7iU5OXWBM8vpKv16aKWJJgijscPknLHVehxJjx0q84l6TKLNl2h1f6qDAoo+wAMQ6hE4v9MFCUiinFGChrBAmba7YzJlGOqEq2MForZjjOQRLYqqHTxDXjPe6PrJ3BUTYZohqP3F3ZOLe/Ihsheui+o4kJa30JvDRY6oAACiU1E6JW4WwFdx8Q22GD2awpxtLuVZcuf3lfZu5tC3TyU1bGocucyHZDvYk6s9dU3/5/s7Ubda6NvnHY07A8aFmM6PhC0xBTUUP/6cgT59wAAwfMd15sGG6A/pPsjMeVgiT0ph7RigDkojqwOnoACAKLm4jsbf9BSiXM9sv3Qy5mVh8Jkm5XWtjGYBAPHOQUNd5ArrnX/XefFbLw1nh1XcXktf3Ms18I3bb1fs7EgkpSUUQhSEFVRJfUNLx3wuHwOd0wrNCwVr2q7oy0q3q6e3ZObtnztVqj4e1+hxEcsatMmw4l3vU5HseasM1WviDRakbkttv5pbz3ic+TaZgXeHibjAd8qihDtEtcj72tnXVhnXJ1yjmYrnuxW1ff66lWj+pbeTNq36ftrqcqCyAJ0ZNHFbtQUt84BJbkimepEOOdrVDGy7VRiR36gCUl7Pvc1xoQnvcvpf3XPz/dtH7zxqMcVr1uRDc6VMJu6wGp5U63a5DxZDCjzCzpVr3Lsrbq6aExB//pwBL6ZAAACGU1erhigAELJq7DElAAIuCOVvGEAMRiN83eGMAYAAEkklNOWLdOKOCxpYcvmopJGvXSwuT/IjH/9WJb+/jDIdif9LYuJAOUpyf//iKOjOcj///+89w+BxL//1HFjyofL28ujmNvUYTFYlUHi5MqZSihYt+KC5P9kY/26qxF/z+MMh2J/uS2LiQDqU7f9v8RR0Zzkf///a8+HwOL//9TFjyofLgEtFyySNIkrsrZzHytec4TKxk8FAVdYoOhQOgYRQdLhIUtSIRZ7WPp3Bo2LIrO3a5IseF1B0iiqS9yHTbPra60Yt2dZO1gFRt2y2xtJPhGpRSbVSIKpUpzz6X/D4zHsxyN7ruFgpwZFntY+ncGjYsQrO3VD4lLHhKoOkTEtJaLkOUbZ9bXWjFuzrJ2tMP/6cgSi5AAAAh1MZehiKjxEYdwfKGILCKDZh6MMRuEGmy2ZBggwCbjb11kjRSeCNq6xTpSPo4GytrCZyPq/TLQtUydCfRT5S2FzPNd76UZ5v6f7U+nuqbSo9v+iSPSXGBTuh9TqTDWiv0AACQoLNHtbRSkETNYcU8zBUNdHDtK0oJzYGFzyFFVHVQgjy8AoB5542meIPPdl1CtWPYgqRR6oZUuImeXeQzQ1am1dyQTcktP/tc5aLAeThpaAr7xUptC7czO1FDGorumnTM/+UrkuZNpW9eqGcqkKWuqU/H/U3VyeI48k8Ang7JJi4CKugrT26gAmIioFcAHFoInpwtcd91FKRx+JVg3Rm0Z14JO7k0b5n/ylMS5vq3/o5bFL6pT8f9TdXJqkVrxp4O6awEjBWntXUmIKaigA//pwBNg5AACCEhJZCyww0ELmq2Zhgg0IwNd/Jhig8ROgLlzzCDQDxn0B3IdGnqwEE5OfYrJS9BFgMYggeYTMRT9SYOrHw/pFQLBVrBFQqqpLyolAfqeAg1krUjfOyWxP9BWkqN9X//rAIlqrDtw+wWH8emOfka7mlJ7/KqOjPqC+BtR7LxJX4bt2m6Gdqqqtb89HsZm9S2XsDQzOyWKpr17SrUlRrur9vp6lgUh13VVhKNzs4pBOHJjYPWYKNO+wU8roAhvHkyBYgjajqaN9tREnlTLt5+teuiVwmPENysdew5ntUeGyCQ4a9S+IH+11VQ25rXJQNULckgsmXVeCOi+Ff6SO+wLZVEvCpOmzJ59MzImz5QfexcZ2XmFdPsdKXwf9V9+9IRLy3jhe4DNd1WvwzbXImUxBTf/6cgRhsgAAAhk2XenmKGhD6wxaDCJbiKCNYkegToEOmy7oYIlEBBAAqFLsu1hMDKNScHGGZ53m2AJSRFWL901Ogknt0gv1pmHbocuuyajv91bpTrrbiIJJVnjhGuAhlrsgoVZEh3Z7tIv1ft22uShBRH12OK0MPnj7LWD5+jhU5dGVFStC6Eu5EKRbc5VMAZLXZ3/So36l9tn2Am+/0er/VlBN06++nIPpra7oAH/wbQCapxSNBDYaMlwjjF2kFEJKyFK/Wo9EoKBNl7h2YrIvODROcjdvlXgqkaY4kHS2tepR1NJKRG6/2pqYdd+/UJvpCoBdx67X8BBMjNMS99cyYSfJn4y7NdrNEdaJz9lvpDO+siNR8mr6WSHo/+qsglooTDIXJyVbvyBE2KnVOfsIl9Qms1JiCmoo//pwBMvEAAACFSZeSMIcXEKmy/0MItWImNlxRISuoQ0HLMzHiYQCBOWaqssBOewjpa/S51B+nNFc69UrS+5kKmaN9fBd5v1ox2DqF71EJO5pAmRGH02BtZVZNgN0HW7SSr0mu+mOz9lgAJKDUSTbacoFvgocrD0zemWxUX9rEn2/8B/nBM/v3vcK4iubGvva3XkJ9wjsYXARpFqE7/1lh7BxYVR0wIrP2dL6QAAwjduluKuIUWmj2vtwl9qiguJlNAPiaI7DTspWQHtK9e2iU7StYrnZWqZ/41jtyfolF0FvwkbdQ9Cu1FUeOR/rNaMUADLbcHEqk8LmQmKC7eGwQVUQjoXaGIwNiu+OHiKwmYUlzn0OIzZSNwP3TQux+8UHMADDyp90jSJiGzrHoW0CM+1PQxMQU1FAAP/6cgR8+QAAAgBMXDGBE/xDSxwNDCJJiNTJgUEEerESry4McIq+GADMtIVnVuhfV3cqWpzDlDUZxXokXB1XdHkut7ivC6uvsdIsGy0Uvejb0VfzLWzSeqP9f3kkqrMDNkfj0yxj6gCSAIkkrI3LPUw6JZcrp73sD+n357L17IeyHQqGeY1EcLZP7tKyP60bNsJ/k8iV6r9PqqUR2qxSutG/qnTxI1XZbMLQYippxyOZ0j2HpcTcoq2m754y7CxFd+0ZXZH1xrQ0J4sslz8QS6b8UELHlTkobeRGX1fqKrIIB9aOphBEYYIvIpSMeoe8QElJJKHHFwmcakiKRkWTywQ+mj8q/jU3DkiP3nRrmK9JFIIe5POVf6Vme5DkQgIvy6zy91n619en0o3W5Ud2XZmcIfuUtMQU1FAA//pwBCo+AAiCCBTZ0ekToEMjqzM8YnUINEdiZ5muQREZbhyEiKYAAIAA7v/5W5IOFBlR494a8WvX45NIDjXk5Ue34oRno87dRnJIE7Lytj4BkQIflCkjQUlljord17PkfTreSs/ijiinJJasGSG2LpHZ40NmPPonlVAQhsOUQf4FHvBmnZrYG7307sDcpCYu2I6IoODyGk5sshqXgWKbNXe/ZTtFgyrnVcgAFJ9xO5mEXvn+wu76IaQzLI1EbXljXB+BhQfJNFU8rnpEg1AZTReOrVAYPEoNUYpZqKKYwDgNCDv2M9Fr5JQTEjyEJJJKNJQE2KIX3bjG1oPqEtwdGfW+SEWn6lS+Up7uydHrrchd3u3T6afQGjZQaKAAaGxNGWJ00N5iGyH7LByTCuHNiUxBTUUzLjk3AP/6cgR05QAAAgghWZnpE6RDIduqJMIriJE1cuMEVXEYJrB0EwiWACTkkjzpBCOndx7SKM49npcbzdD+mNXWf8kB795dHR/Z/9pTNRTuCcfdI1zqz1uQJHVpDg3OPJpfS7dk79Bf+ioBQJkgUm3ZZhJxsFQjunysBGHzoJoJuCBAcYAQ0kBnCpj3exZxjH+U+KCsLAVUZfNi9bcq9YvPpwA1P+xJhA4cJnU0UDIKLbcPTotmre6QxgIYEwH/Kw2M/4kfmZM+L0KLNbqpwahP7+FIYavP5jEdzOxWvZ0VoPYicird6M2tlp99h3int5FCATZKUbdllvYY4R0trEKMebMydyBGZlr8ybss2rZ4ONs8zKoV6/0KVVRBkmr0c3Rd//VKk10F3rTt6+5piC1HlfrBpD3/UmIKaigA//pwBDAHAAwCBQ9aGYIzlEJJrAoYIn+IxTloZLRLERWnLczDFKYEJyW1y8IMPgOunTQj8+UBm2dWOMDZfcwOmbuAtlqpUs6OU5LECRo1CVBpXCCC134CLvFXuoTap7IlURWdVV6whBc1bakst+V45gCH33L/xG5zRPjCrKF6Mjw3PPhyXyyLSrdFYfVrluv+tv121uh2pp/56XvqUTsLAJ30UQpj1jhf2EhKW0EC4yC9B5RXVFw4sO48R3KF55Wx131j4fuqpmLOCbd6fmr7LRpE+X8tpar7UmRrG5UQjrMdzsVxrJ39DdqboumjYSkkJNJyF3ivgLIDnmiuLQBnXqwz1VosWPelZN3ybcfOjatRrNRc77PUUIpWqrp0dOiaN3+uzaPR0Xp29TO1HsFvGP/7KUUpiCmooP/6cgTTTAAAgfIdWRnpE6RC6ZuaGCWdiRxje0GIyfEbGu3cZIhqICTkgbHMoz0mW1muO5I7jJdikrhT/UOnXVvUEVW6yn9F1dp/xKgz6DQ+9cnoJLDvtKtXZ60tU0o9vbqqU8VAACokJOOAt7AuDhkI6jfPLdBubzj+7BQ3N9083v9T+59lyuTKNZ+/srHHsoszUZ0MclFaJrRsj/fr6zUooULqqg92QUBUi27Jc4a3BgyGtrGHisFUZs5GW0lO3XGcdDanNgV7tsOrgBpQ6cM1FCAWYAlJllRYDv0JahGkqBRYBB95pLrhW4BDHBgPaiIJy7bzHE2DqTNUul0ukkOvugtt9R0iE/1V1H1bavrtm/Ca5m16JTpMUhlNj3xx06DjzxRBSlBRfeo6TPoU7FcsMOBg+kYpMQU0//pwBLQ0AAZCERfZAewZ4EPiG2IkI3AIBMt8owhrgP6IMDQwjchdx5R1dKNPUzER8DQnmXj58r8qeqN/CkpjCA2Bb1YDNLDEA8AxUDhF44Ng4TCJpqG+UFjB/Tb/Of40giln/4s5qgHI1/qJ8EpwJjadmi/WcucbzZC0plCcIDDgHxzQILOFTbqiYOJCJoXQ31Cxg/pk7kl5Ccjb/BMgQpIej59QWcTFgGp37oFzrIYBECCG5EJEpQQpiEfEigEFEOtrc8wpQiXivmR+daPwrHEFL6mlpk8RTvnlv4jgIYiaIIV1f263n/X9NvRAAAQAASpvBBBAgRHKaayEokvUdQVDLTmfEQKDVBu6tTSDQcU2BBc0Fgi/dKfS53qZ+vky//jwsNHuNDgw99xFMQU1FMy45NwAAAAAAP/6cgQvhAAGwh4a30mBGhBBw2vAPMMuCABldgeYYoEbh+8E8wxIAgAAAEW2S4CaZ6t3X7piyPYpEQ3YBNMsUxLnW1LXh+OnxIOPAUAJ5h1wCAqHP5t6GKwGuhuj4vrazxppIoZMX8NvO781Jgi2xyJolheN0L2ei0/iIqzkbQJIzEu1hCRtcIK4PvzqwyDSQ0GDa3BxFCA6ddTzcYkVmD+N7tlbcXV6Cd+7/phxI4LYKTWXBpm6UJtCabgRmNrYf96YElIkYwsFx9yhgxouBSQmTNXw9atDmmqmFWqeFbC3p1UOfNLzeTbp2I6w/zQ3hLFjqSaOw+dI2JoRn5FQpYitZYVcEBKIbVSBAasPgEaHDYGDCWAu4VJPMbkqnZEsTHT3eP2TBdyQ02l9YHZv0uftZQmIKaigAAAA//pwBL1QAADyFgDgYAMICEGii6AwwxgIXCVzIYUoQQaQbgAmDBgAFultCQAQMhFg8OjxIYAw9xFAiVtFg8sSIAwulwKjEgBMiS3o9J5GliEirRVy0ElSS8yldneEnYrMRtarowo8Y7anHIAZiQ0puBLei9iCj9dGNEOCv4/cWxBwMgyHwKaMMNBB6gZOS1zGIUBluZ3DmqRat1bhaae8mpPQztQpG34ZQQ1gBJAACDaBaAu1EaOgifWzqUBUTiYdY9LlpBwaHAmmKLBhdBpyFVMBc0xiFOpC09NIy1S2erqZ77kJOtY5SVXSCw6AIZ8B1VsDyyGPjbwciYrG6zMzclbdyNuG6U2JVzM5NWEYlYNMHAmw0lZ8YQDUhg2wtDI0a2eiIWNd7G9/T3I9liPWmIKaimZccm4AAP/6cATofwAKgdkX2wGBHJBDgSuGGEYQCOTJZMeMT4EQGWxA9gzYislD1Z1nHci6sGiRd+a06lH+iz2nNjmtVgJB4OiwjQHTYKyRU6eVIG1JcOXHIHYdHdaiLWzeor1WfdeAQBGqwzQkNMCEehOCurpg6dFnqeLpa9LHFmFiywaDxms7gqrIzY5U5sLsuJnkmhY6kGRVvYwNKfFCx7zUs1TbFu7PSIVqRUiNZqKJhVi1tHtOn6wmYMZdsES8CiXuzk8czVj0cmMuLNqX95xvZt9H2oZ6MbQtsS0Jzw9yhLQjKUGCY5//MEUdH80+t5wLU6mbSsRpDst1HvhclMsg2DBfuocLZhLm9m/iWTL0P8jL9UjcZ5Jn6NctZeHO9NSgW3GwMJRqiWnZR6unQtT7v6UxBTUUzLjk3AD/+nIEbH4AAAIaFFiQLxhgQkR68GGCPgh8OXOkGEUhGQxtXLSUbAAWqBcjwcFGcsFHNqeUEp7s5lXqZB0gq7jwc88ntH2oGwqOYiJBg+fJCVRuae8uhVRhPQdVtixJD++9Xra/e5Pwl8VzgjZWaln2f2za5OJDIcqwpThDfXuQ3H89JCwt/sd+k+wJgZ1DmvNTeVaovPCipkck1WTeEzRtXotqL6+yjZ66f364AmAAmm645MyyEahk8/cG3s2g+4N5noEIonGkUMQMaecpzVFkjGpYl7BV54mpYg1UqdbwiAtOZe3QsUad9Wn7ZpReoxAEApEpS2wJ5lxk+/mU/Z85beF7PiK7Mhvamp1iKUPPVJVDgHMhtkKkXmVCZzdiElXFFvzt1tS1Pt1lbNaYZcUbrtdDBaxCYgpqKP/6cATbVwAMAhcOWZApGGhDwysSPYIcCJg9YEC9IYENHG8kII7mAiVkS4AJhEnmxInU4eCQLpoO0epOhWGzzgM7QNMpeXc1wBHCrD9GBSKCKzAknC0aRJPJNwaXLa6jSkoW6gbsd+a/1AT3+lFkWjxPXvr8LazzAbhOhpularjJUGshWlXLW1hRoKEnpcVODbpKYU2gmLjTQlh4tUl5bnTdJZXuWL26Faf5r6NQAX+NSj/XQUTNHWH6ua5hkOy/R2XOkLxMX7bRcmw822EDIckS+uNJb37CbWJjKEdy2rdLrWfW+ZKZMgtqLlop36XdNjlIihftNVyxcQitRYRyWyDuJO04dIxbN5m7CrXw9aL81++5pi310GNoGd0PaD4wMLxOMWla1mRoxGYbffQejZLXtc5EkmIKaij/+nIEP/8AAMIZCttRIzkoQmL7MzCiYwjUY15nsGxBDIytDIMIbIDABJTccle/hjDQho4mQUYYV8o90IDS9BEqwsGCqUvqQsm0IHjzjyR6RjG0sFLK1OH7ljjyM5XyFnZtwlvIVb2HWsQAEkU61HcDlg0KiuuQ9gPOHg9Ap7D5D1a4fK+nGj0vk9jD6zOeWdIeyO8w4/O7LCrUpTijrd7XCrSYLuFVOo7hx1qCAk3JJ3kIL9bB6tqqW86Z8KIkgT3HzHSt2peLhXtpRsvliOoo3p0jmLImluQXc5pFighcKJrILdMFRLUEXPR4xWas7l+r9gRiacrGIADYeGSxx1YkNPeME0vMtUyPR7H+op3suHln44g4lInjTwyprcsxFw9BhrENJodtoH4sSHOWpbb3NLbDuiRTEFNRQP/6cAQB9gAMQg8TV5noG6BDAfsHPYMoCDw7YGw8xQEHh2zM8wigABSckh3axoWUKWytPFlkyG2dIm2EDGGR2XXRhaHqUlwgxJciPdWhi2XlwIZDVhZ6QdverLwzdJI5yJPctPTYxf/cIAAKRy3TPCHI9GihnFoR0W6NdS5w2j0Y1KUBzDiginEjizw/PaEix1xogDxNy+0upTBa0YxP/Ofk8q4chLGDGpH/1ABuO21pMXPCp23Y0YDe/Vh1rcQcq2Q1scfuPp/3B5oTeDd6jxRKY+hbBQ8OFQGge7mhAKdNdpet3TlWMez+r///oIcl3/xMJODbR70BIhZAFOhFaJSN5XK1h1Asu56sOGRUifM3DUpSUKo60WsSxVa3kocuFrnnutGyvrS1Qs3Sj99/SmIKaimZccm4AAD/+nIEq9QADMIEFVebTDDQQcMK82WCWAi8YWZsJENRGYmsTYSMoAA05IGeNiFwgQqLY1B4mi0ZLICEWjMOna8bzcxg58GLf19zeZrzQGcaegeA0rP4ww+pKHjCuah9xqiVuZRX9P6QAW5aGeZgvwFTSdLStUtVln5wEpXQalORlWeQ52irXmGebBUCMlHMGj6l0tasMXCe1tYjJD+TrRb3FWLX6kJ/V/vQKbctgAxjT5VASguqYxOC/m2GjmpPtoQs6MioTp6uH/TgEBWFlFjb6i749zlP6Nws1ooIuoZRBZCg/GtOpS4FqXGWNo/OEBu7/tkNc0DSIFK0oMxUD4FV3U0HszPhSghEMDGksQKohi/LlXk64TDTxbYG3nrk3HBgsli7kxZsUY5z7EOHXmIoqvum/tTEFNRQAP/6cAT6lgAMwgITWBsLQOBB4msDYeUMCHzJYGwwRQEIGO0NhIhqIEln/VXB7LiYbQOh7RPSMEMowiUEyKKNo/Ck2Z0y8D+DpR6ZVbhZzypgyPJw856iYZLU33/0tYw0vfW/+3zNu0AOXbZEMBkfAt2cRcmN5lyPDfNhxUK9toQaMbDMdobHoD1Kj1yhzxZbXxK5Fug9SwyeA4Qfah760w4R531Uf6Nv9ACd1/6To3mwp1gwh8tr4ErPL3hmUjXBwQpkBgbOBFa+TVtXYeitpfZWVNVZ1JbzvsyGLT0VGg2v/jhdosVZuSp/Hf+aILcktVRIk2WsYFSN+JAy7kcESUMGyGarJNx2tr9zf8M62K6vWpSKqa6La5kdm3argwqWeLardf+zqCrn+gLbTy0pTEFNRTMuOTcAAAD/+nIEwwAACAIZPliaLCjYQOJrdzzCKYjVFWz0woAxDw+tTp4gBiTXZdwToL2KRUCETHmJGa6ar2kJQnQe2GmhEXZXz53bco023557ptapdn39loZNUerMvbn6N6VGo5Re7ylF1J//0tWEJFJNJwaZS7TPXB2yUnvE4aVOtHar6yA1Vxc7MBViGtvS1hUQadz2hR44TmHHStZ/fOLPJu9F1BELB6tb7lfXkQkJpluAqe3MthWdRuDsSYpgd1e7UFEkDWtr+jxrtPzNUtXq9B7qVJn291myt6tU3//rndkJV7E3vUXeKnZBgXWkVFenXX9IBaSThIXs5fqMSkxjLNExAngSR8rztm71Rrd+VVf/Y2JSHxwlEry3rMD+4FuDa3pF20IHkL/dehQHFywVeHq13y4urUmIKaigAP/6cAStRQAAAiNI4O4E4ABAiQviwRQACMBnebwxgAEVhy73iiAAAAAAAAAAgEAoFAoFAoqEtXQnGX///f/7OQvT/jQw8wmPdf+LCIOxwugkd2/+KDXn1ch/X/8yZeWJgh3/8oHEh8CBAp0kGGGGGRkEgg7bs1Gc3T////7SXp/xQhyC4lU6/8UFQDEB6BzuzN/xhXnq5Pkr/+SS8cDjEy1/+CTgObBBhznr1IAQANSNkEkmWtoP1nLci2uEky4k55PD9JOcnKJQ4XQ9JYWYZW6yoaFBxFd61YhWwS4oUw0x1GMGPZahmnGnkQyVuP2CrTpBEALdiQBJJRoGsdiodK2pgmmLQZ5GLUCikkVnTGm88pDyVWQExEIPaRtZUdFlnamHJUYjdQQIqrjOaoEzXFHnUF6iwuVTEED/+nIEXWwAAAIVNdxI4RRwPKbLzRQijgkc13OjDE7BJRIxdDCOnoBBqpAAboBVxArIxxOKeqyRYkPQk+XWVchKP2vjAU3ihET/EzIVD/DQ3xVRsraAU7NmpTVCjwVPehZlqWhAeh+WbNEIIlyOVpFJOaCxh6TLGuLS7jjE8i+WSkJI8hKfv9gLeKmX8Uydfw0/FZF51aDr/9i7CJUFvyQ+soRa7vpIBgACUbjZjjvg7k0fDqIcta3D+DKKfWpIfLdaybm9VLmVPzopj5enUt6lEs05WTRv8T+BXVklS08pTFYqb1VNI4lDSQroPXElwOVKy22RoJOpnuHfcpgzC0V4MpzICck0MLQJITGK3GYQ2f5MmxlRKwNHnaw1C+Q930ncXcyeLarIwmeoYsKjDdYKuAzcFlIGuamIIP/6cAQmmwAAAgZM20nmEUhD6ZtGMSUbCKjXZMesrMEPoCyY9AmQgIABGUWntFQFSrJ7sLJ+R5BzMHS24dtIit0+RvK+1G9OYnui/9y5X/6+Cb+mia9ontL9W6r3MK4zT9r7qR1MiHCAQ6Irz2hh0LR++aEOkodS3Ma0XbUIvZVFXV8nRtcrZGJ18xur6/3oOy2/evUKbdPdzJt8Vb/7d17mFotGaft9Q7kQ4AQBv/jS5H+5ksNfV/InNFAoimBtftXkz62iu1Xw81sWXQgYr8fvQno/Z/QN767neiOfXW3jAxmNzOQPWs+3Df1r7X/MUQEF7/3dGEecYzHkbWUIMLBQLRaH+K2SG74UGOr0BbcukZTa89Gq9fR/X9HRvT8rbWwXb0f+yWFGd9DF7EId9utNvChhMQU1FAD/+nIE+jcAAMIQQN5pIykYRAgbMzCiZAh0X3uDBHAxFRrsTPQJkOBKQLC3Jttu0+0GB4GaLGxjPDSRjx7tRX8a1Gk6CB//VvN1Lqpi206kQ3fpolPQH11lXs6eo2lX1GESerlOKv/kKgDJJJJXrwOcTjXsgOQVwVck2jhMGfRnV6D9p+iPbI+iGK2U4qzXU60PY2lszOc8/Nbu7ILfrp29dQrVdU95D4r3P+jqRBgBiX1dXiuB89W99O95BZDcB9p9SaeipW5RZTYQ2nObaHnu8uIxzw2fEYgUesD8BLAj1izGe/XOA9WLEMhmX5Xv30AhNxxzRrEjlD7e+XZXjeyp3HQmdLAuL4MM98HqzhH0Qb0ffb0Zt3RldU0r1UvK693Si2Zx0rYCZkWdPf6D+t4c+5i5X9KYgpqKAP/6cARQKQAMAfwgVosGE8BDxrsjPWJWCFCLZGeMTsEbGu6kgwjOBylm5eXuthZ7NotdquIAC5Jkzj4xBIUnoJZOB3LHA6QMrsbv7wGvtaB1yB/hhOqBnKfVnShoQkL62pa5ZzsgJANyy2bOhvRyhR1qtqcJzkn0wbrUyKaX3uGJMw8lAfdH9H2o3UqzVt7fS8qTl/VWMqWVRDgVc7f/3i7lrnW/nX7Pg9pQDkktg4sP14LIW7W7OIhWsR2aONtWBEM37MYM+JGV0FG9E7/Rs0uyiHOFpNBxS4zW55mCrqul67PqU+2hn/Iu35GiARJVeqtJgIcg71hpKd4MUzWKI6JVsNnoif93zwTdyJaMjvzsqLNajsTb9XRnSwWoDhBa3QmIXy1lZ95xI4NP/PKpGtv0NpTEFNRQAAD/+nIEWjAAAAHWFNwxYRO8Qoa7Uz0iKIjo0WhkMENRLCqvqBMIJppCzLUvgj4pFlcPDzp2xU2odmtBa7U2MHZA8t+Rz0u6thS4RjVJcsmsE0yDPscuz6nyB4KiE99KMl+khNxyTE0hFc7tdqS4M8q+zo5n2bYEzc7Uzei6Kj5ZxtjK5KN5WNVmqzqsrqZtboteiCrpfHRVRmVI60tzw9bdqvDTgS245MrAJoFxb3a8Ab3PhQzWxYd26DpwfKo5Oir2b1JapWUqKVNSjZ5tWS29OqgzFUaRPQoJSKmt+vQoss5Fls+wzU74oPjonG6jckbllxmEzc2tShHZQuIezcEyMsOdTlhG2Qdej+D7l9DYeqNOfVlUF0OZN1q5WZfR/P/+n7/TSy5luCpz2or0FWsQYpRU+MlExBTUUP/6cAR4mwAAAhEm2jmHE6RBZrvqFCK3iJzzasWgSzEYmS3ckIpWCAQU3JJNWCXUFUs7poBnl0rodzopfnBR1aoV95Pj9C/Rfe1JUZVcTnySUSaZIeHzYZEtTzuIqs7Gc88zl27dbMW0wqPVG443LaLxo16yxJnCxLNQrdGUUxA6hclnm9PKF+EuRUWtHteFZa11Zru78Qmper/3FmsWUIMOkoiFW6hffu6wCAytb4x4tW17g1DawnVVDyOaGrX0GKXu9KF6RVKX97rO7F3vuRtTfVmr+tFIvka1/8GFlCBCJDafO0qYd6br6E1Pq7FxHCTSSUfNcBOQd+Wy1y7r5jbXw5bvMc1vWSkgYiZpusI/R5Wj6qoInd8n1160BpMQstoqBsJC0Ba+3S8UcN7UI403Tgk2tMQU1FD/+nIEJmAAAAIUEloR7DjcPwILMz0mJojtAXdGGKNxGyZtWQMUpwEluOTwHIQwmcfYvqUQY3IKv+PT6oVLNnCAYtQVPHNit12ep2ZCtA4cFwG4q8FizWHztd6usX/SvSKofj5ELXo6fqIKTkkciQA5CaqA5hRRHE+OzEJOdAm+bwLZ+FPvQARm8lINcp6S/GWVsaJfIuXaCzps8m95BL2VO+5VifT1/oAUFJJItyWQ0BU0w4g2PA7ytqTxm2iuGOsx2o6GTRW8z+ny+vvp3atLr9+jjHJNN1fptIpXnE1NKLPUkRrrWDyQOnJpDetL0BDAmbFBOAQilDwpMIiXi7LXNDsKhINPQoI9de87e/p1sP82eqLvdNh7K+ViqdV0Vro9Ut//VEW9H0r+nasrniY7jQrtk0kiYgpqKP/6cASpHgAAAh4y3mlhFVxEZmuqMSINiGBfhaSIo/EUh3A0kaQ2BSgCKSSablBwCI2K2j2cpktO8LnZJ3xT2x7SKtLw9SfufeUa/No19nm9T/+KgJYh/W5paXc0P6XQwHSJQGnSCA+s+BgDCRSLTblWAGWO8QvyG3X76oxoyP1BYrY1GnNsv0fSr9i72L3Vj8xWL+vfRkDDiEJnl+SPXpb+lxkUHBeRTS9bpZ7/9YRkBUrjllu3odiilFs6XgneISOMUQJaoXtQXeme9XFEcHSdZJJXNApTepPgAHnkdtFgdZPNUJU7mUIfYhwenkaqaPSACwXI25ZZb6CJNoPle4I3gHmyPDBt39rXEHlS7Z0hBqEib1hJLN4tI3i6FvYtynkV/mt5BIl3rir7x1Fq9lQSFEiXS/oTEED/+nAEfBEABIIHI1qx7BBsQwgrij0lD4ikyVhsvEfBDZluKMSIfhAArPhUBbaTaCi/fOD7IXKPYLODaIXQr2yNNzazq/bavuvhrQbCLjJAQChr3w37eXDgfCwic025YYFkErz7VmPSAoMxIZbjC4GrQpoRM5lOU63yZNDF3OG8UM1qE0eya99Okabu7N20z9/paqfVmVkZHm9/7nR62MKQUPqjVWzwu5bvIgApW0J9iYsWGhpEnU0CDvlcgvtFODwWT0DfmjMt0kWjTbCvRa3BrjrqbBcZmlZl7l9TdjV3bI6SQqfr/9A5kHLb/7f26FpBTTUgMwhsWuXMO9Nr8vsohCsV9iZ/nfbN/1KQG2blnF9Sy19pyvBmZztl/9lDk0fg8D4gGnEB3GhNeCyxYRFkpt1JiCmooAAA//pyBBVVAAACEyZZVTygBEQE2yenlACI2MF4GMEAARMWL1cYUAAAgEACk5aB2oHZ4coZYvtg+oZZtEa7Udw8QQFR9CDQdXxrVbbRhdf7WPohJvozx8zet23BJgSv+t63n1TB+nIJQZ0gBILTloEVNVwIbdIwpsQ1UelFbHzAVNzvQ+HJxorrro3Yq9uRA4G9qIaXRlUWYqfNv/KA2VSlbPDYSQtrLqxayFCrw9BWBJcJ47GBRNS47c8of/QgcCyXcQxG93D6W+6LdERf5zIUuRyOs7+Zgx3YVKogIg35HKvHICrPldovsNzf+Nl5c9pSHFrGgAJJALW3MbBf9OCOpLlPryP3kOHvO4EYY33E3pb7oNvRF/nMhS5HR8/zRImAkCQaB/I63jkBX8q60L7Dfd+Nl5c9psXWmIL/+nAEhg0ACAIcDV43PEAAQ0HsneGMAYhE2XsnmEBg/QkupYMUWAENKq1SMkiV0Z9Fpuv1ibddb7XgiZYIw4i8g/O/UaUPGCy+VJEjb0El7pxoGYLqU2Jf5AstCyg3WnFlQMOani5wq5bgU03K25GkSVgwKH2TVIWXVOjXk/BHY5brHizAkvLRhpQ8ICy+VDxI29BJci6caBmC6lNiWn5AstCyg3XtFlSw5qeuVFc+FCXg/QCMPFjRF3ibp5rwSICBBeF3s8heS0zPnXeVjNOmX/eyUKuv1uhnLdgOGXHNh7Z11mFvfIrR7BfKgTDv1AADhurNvgIBwzJhMIPLWWoJaPanhTYUG8Uqa0jEyCzr+eLkSt+9Sjtu0ceOz7rNjP+YnhzCIqj2Bd8qBMO91SYgpqKZlxybgAAA//pyBJSGAAACGEBcEeY5QEPmzH0IYsGInQF7p5hBoRUmMPSCic4Or/VwLptfdOjuFXCJYzcYfqOrj1kQC75T+j0q1WZKpfXNMWj33f/o7qqr6o9OqlPtTqhz/KP5UrWoS57prks6tHRqBTTUkTdjbSkMpnQkkxFJzanXFtoPy9uj5Qqk9s1dOuWtN902+qO6g1Xyo7k6qEfOiixY9qf0Lrtz38lWdWAU4FARJVQAgAoaiccmvRYlSkcBCRpuZr5/QN0Vm6BQw5ShW0Vd6EXk6sr16c/1f/o/f69/Blp/7asawdTSq66hSkDK/9c6nQ1z1jQGkTWk042m4IYIwqaU89jZ5KJ0IrQvsKO0+iVp78nWtxaTC7711b9tB/b17+on/9vNYPTrXnIrprZ3DAb79ddyayS3VhNMQU3/+nAEfv4AAAITNdsbDClwQ0gLyjzFCwi02YFDBKaxERstnPSUuEAnbbRnpESYh+01o1oQGm6Ia3/gW7OP0d6n/dSLBzwf2behSdPdHpp7dqin1bd7zXqi2t40E4+OR2XfkSM77q/f/QBAdzsd0u4OMxGD4WXmfFFn9IPxdBWAovVjNgNsesx9gTu2jdP3Efu30a17//b1Hf0/rfGfkC9Typc/7260+sJjhVtQiCyolJtuAE/EOLR47GaeGtt0dVIUmTr+jiftyI9dOjJ6t/spUqtl0kS/gKyQ+KsUwwKQeuIUJaKgIKxU77khmuTalFVqgEAJTbbAXRv7ODKlI8IpNi6pM/plv7YpmAw+acG+Bd9qviQfTZsYO1bn77LZNuzJHOxS7FytuTQV96nTEt+U+t/izeH0xBTQ//pyBBLRAAwB/zXbGek4YEQmvDoM4m+IKNdsZ6BMwRka7Uz1ldAAGXbYwhNmAvMCSdoSoUAIWMVqYgzDp0QUUwPfH/96MOdOhFX9U52t79W5yLr6X0TXJTqlXr/5V8V0dm7iX93WFy9TLlkckFbmEcwvlG6B2Y6Y95d6Am/67qNuvKDD/RN7FRhUplVS20Te+2r0W7oLDoodB1IEfZ/oYw+VDALdlzExL+gALa/+g9MROWGxAsf1npz5XptAC3jFrsCjILVuAe7or7n6dD3ppaxDao70QrJ3Z61TNen4/1k6kftva2Y7P7PWi8AK77eAOlYOih8MEZEblUaSRU3kV/aRYpenTJTGb4E+ka+5eTxX9fs7b+uz1GsX+k6WSkWly45Ys5xZFPVaG+YZ+3inzlzUxBTUUzLjk3D/+nAELcsAAAIWGtuZJROoQua7yhQi8IioY27npEXRFQ5vqCMJTgE5ZLiNVsR4Pjkwfp4IdI90h/RnaEgxiyti+6tKIpV9BpZJe2B4uIHCrmFghTapAUJSra3XvJLp+q9RyRbs/DrlXaAQBkQUkt2O7CcxIniAxGqBmqdHtzj9Fb9fJzNhFS4tIjcQZGXo1eqt6/O6egjvV1xX9rD8cOIt4swiLtA7mOdpBK1QhiClJJYLHdsyPfWhRGgT50ztj2YuxjGae6+7xK++NSANbZRN0PWp3UGkFwDEI8Ryyqyytz10/HLPi2mz7LzoCUM0mGpShAQpKTjcrWCVNJh2fKcN26NQOnfr15gFcraj/LOEpW/ePQZMl0MDoZSK1qENY2swLadA+NFDwNNY6HElRO+gANsniEhKpiCA//pyBM0rAAACEEzg0EEfPEQDm9oYJ3mIvLeDQQxG8RWV8HSBDm7RAmUS5JLgJSA7D3yVwaayNBtV0539qef/HT6pzcAzEvcU5Of+xBb5p/4neeia5/xGXHWnkKFZpDxUsPsAjm8SoSkJAlEk3G3avl0MvpfSnnvyeb48jSIywh6mxwe/7DJDKVxEONqcJoSWXPLSH2OSXUxqBz1220py1e+3e9HSUDG6oS2OF1YH2aVlkulmhhVfeqZA10ZNWco7NsbNPpuN/BhJl44YiQWZWQfRXWpgTq4OFBYRCiaKF+14ybZ9hlGWFW9hIiiEk1u84lbYQCkaRblkueaBVxVr8ynAhgSroyYcMu6RHEf00UR76D2t36i0e6CtO1dhVtV6R9SZBS34xX63IFCEQkz9B5Yq3Umpu/qTEED/+nAE52wAAIIXHNmZaRLEPqNbJz0lWAjk13VAmEFxFQvuqJEdZiAXHILMEgZaoVYUawYDYID1nWK+rFmtO5AoPNjKYIlEU9Bkx/8TXxQ0cAAqWcZCwUAoFKPHBRWn58YwzYn3NbqvZ9IBACnd/9epkxUPQiMNLaVMyxrNKgx8k9Nh5kXZlhnQP76wofsK8Y0iSEde9l5ansqvdiG9dT46lP1/Ip/d/rCQAQFMtuWmHpHVhNrFltuN1QU/BOvN5agj1YTwgjudoZyOr5/o+23O91b3NIdOhxMheKHIDSnu1DxEuIx5q5LxYTw01Af/YiSCSbcsH6fsD5cjq1WO2J0q0EOqhQ7oVC23co9i5yQkGFvPtvQ4MMNb4WAl1KTes0UJpWlHlHxoGIh1Nwh1EtDdj3WaWJiCmooA//pyBFRnAAACEEFbkScS7EQDm1cwxXSIfKVw4wSuURYOrWjzFSoJa8igmGHF18M28QCFtCOyI+ziBjONd5ptBmHKGShi8QuuVPdtlNRctU2/9LJ/rR73IQ6EoYUwhZYVfFXPKRYbb5OBgBTcusFVwMJNRnIiagrsc6dQY8KdDBStctDh3fZxj5h7duGIREEoBLoqKHavvRYr4oAijYza2rJAQDgsHT1tRYIJkCBAxu3cG5oOmRvirgWB1+4/bA0NjIO82T1NEw4AxaM10DEeuhn7+rb4hETWogE5W/0ldR8vMoNj6kTcyoXsLQkFyY06ABAACTlu1NPi/yCmP+tQ2CdPbuEf3rzz1V7Q4ts1KPUt+2oZo5qvNFC5b2w3cNP51D2Bppci/8ukqKnlZa0XM6Y9PUt1SYgpqKD/+nAEjKsACMIKItwYwROEQ+f7lySiYcgA/27klHWRD44tTPSIugS5duJScGoCzQPETANf5ZmlPBsxxgfLnRkq2wXpwR0aE97giMVPiaVFRKa6lGlHaohewFRYoAlg4z4pUTNqc/yqQEEIpuQQY0YwiPaQxc1au4F2ZWr4loMjXSnqxT0L1bt/Vnbj7tfV2/7ud2urI323Z2d3BTFC4HRdadXoW624On//8b2QFJTbjKiKXNsagptGda/sI79l387eK5DiWlre4S6NoZGn19W++2VP/+Wujdej9CSwEVosPHZrG4uVMlmzF7n1AFu24etS+3KskaBZZCZLjG+ZN/JrDP+utZjk+7W5uC4UFgkfLNhqstaPe1JMQi00tpwY9MMUqDBAaH13fNF0Iac2ZGxMQU1FMy45NwAA//pyBCgkAAACHEBbPSRADD7n+2OmFACJBEFw+JGAERoGr2sMMAIRgAJScEk9AqxC1FqZpAqPZqhckhVHhXOdjDVDtqx6pwbZ20La2iPgyVecFm2bp/9+67fXdOzsVqi/oOsjGoHsrRHCMAtW7hvk4HqGKrC/itUyZdOqOKoU78Y/P+1tl522B3aYqlb/yablPmS9vZNr9vnXvYmJpETY79SG0GZa6oNC4AAYJSTjtdsAqaBsGBEURsmzqjHgOJCeeRgjoIHWCGFBoaAi49pxFyy6WlpIV0UPyovabx6Q8+pYdeH/Dfljvr3//+XeljkCcAABWWZJSS27T7AZxnQaPJJzjreJTZGV3tBA8HQ8UhOBoRQwgZmQ2WSBR5EvTA2tuBq3tpRXNh/wk1yd3nTaXm3f/6X2UCdMQU3/+nAEkvgAAAIgWuKeGEACRAtcU8MIAEiE14+8YQAxEYauZ7AgAAAwNBsNhsP2PEBHul3O9sn6/0/////yX//yAYu4QQUoCrm/xaNuxzlsVzsUP/1efMRpBTrYCqlP/s5PJnfmU5FFPwlCAEI0Gw2GwbWPMCPqS7n9vP1//////7kV/p/kAxdwggpQFXN/i0bdjnWxXOyh//efMRpB3VmAqpT/7O3kzvzKpFFaCUIAFNSSRtEkBcQRRzy1fZ+7Xt3BnsxHqZj5yvyZ736mtb+Vqvc97/1Mt59PXO+VxCXHQm8yU0s+prrpNP7qywtOpxMldAAABygIMuHEFpVeybcOyq5V+9Uzv/v9X4RBE3DnWlNbxneGlhQDmUpdWDaS89XD8ycNIW1Cwhjr/FUUVvHfRtCrCvWy1MQQ//pyBBNaAAACFjZl6MEUTELmy+0wYi8IgQF1rBhBoRQgLMWWFGAJN2z6y2NJJ+ouvvzoMcDL/3YgdSJhMQ+Dum3NI0YBnl9UQW1y5N1XT8yX/o/fhyue/ah1vpsKDGscWNeFY2sI4d+sAEITS1tkkFHgHjg/g1jmRzPqnFeeGGVu6szTb3+1Pb1RBbXLk3X/qZLr+Z+/DlOvebtRt9NiBjWHSxrwrG1hHDuvWAGiMIpGkSQ0nCswHGJPsRMlFbbHd2eSqO9kDpsi7c7ZXX/RWqVsqXTmfovVfzTe0N/Toql+DdulSyvO/Wd4x7edLR9XmjDxP4z2QMvrLEGi+IvAUVKpthZHhMMPYx2hNMvUmo3rWrGfoUVqVvv5n/1X8zm9lD39OiqX40ZtlSxbzv1hrqejtLR6YgpqKAD/+nAEEvEAAAIYNePowRHcQgarAWmCZgfZAX0ljKGxF6BwNMKINgnXFpbZrY46BDXd5e3cijIspksiHMeortd13YIVGU+Rla+vYxJmd0Kr08pZv/m8GpDXj1x4Ynj5FDVBNGd/9b/iFZQTxywc4CsmH4HsyzBuFDEp+ONEvfxYnGm4HnRNRdfcfADvLIk9UCF16uufXrb3tfS9Wm29ubwYx39Kv0r0lbv+T+kGY6uuqsfwgwI0OTVJkUfNUlb1Q2Ol+rcv8Y2qJZmz6f/yF6U7O0u0LDn0q+e/NcbK25BKBjy3qbZzuiormrAEgFGok24k2fjZyGLd7TsyhQRwxJoMZ4d3399Xuwd9eojk6aH1pOtMzEO4ir5m3PrTUR26N+vh2+OackbzmwLESysXr5ZKYgpqKZlxybgA//pwBDxpAAwCEzZYkwkTMD3oGzJhgg0IrHNmZ4htASMQbijBGXQG+/BG0b3KcGNPtLJ6n+TyXNkNneL/p+zHVe5RMx01SlWKyI+ThGVrdtHzktnq6PUyOhy6aW/ifZa3EP06NT9vbqMJzKwUmtNgTehhuOND9lsq3zDfWgpwcaoA+E13VRCugAPlbBCUpzF7VRPp+4qjLS/b+N7a9+jcL/1cj/0O+kFRy21SBUQTqdKdWWcavG5JnTPDit2tCOHBFEN+QkOlzM+P+CUkIJZSUMfF7It0FRatxHFwFkr70dC7yVQiPbbDN0qdv1gwAwF9bZawElT6OcwpXesoz1NyxTrfZvppic8U3MPx7OH1/fzreB1KeT0KF2oekSBuwwCYUFRwlLHnXos9zDqqiYdR2OdlTv0JiCmooP/6cgTUsQAMAhQ2WRHsKMhCpswKDKJ1iKivYGeYrMEKq+/oMIp2BqazAbWgrWRSWqGWGpyJrD0LfK90CRBYzDWomo1k/Cm5tXsi6H1ZftVc1VQeWqPTR9/i9uiKJiqu7a2Vpfr7ea+yodG727I23ZaJQVO41oQ+i+imqj0Cb4DyyUPVDHsBtRDdnZUymlPu2T9Eo/+968VFrGSeK/ShQidmzfXlq6Gp4mOjywBDkkhTtiAC7RxcFp0erUzq4s38+ga+56nD/SBB8h6CrUolXaYC8z6v3/uX3apbm1ONXceJoeHfkMy6EiH1LbZan/iL8kEjNybbbcr5j0HctZULp/bW6SxOQOF1Fo+fI+K/nMjvl+6D/O737iP6/7Sov/6nZUZ6uUzqzN95klYlsM0+zY4MxGlMQU1FAAAA//pwBAOeAAkCHhzXmekTMEIGu2MkJXcH3HNoxIxO0RkRsPQynZ4AGOSQqzeKUWxWBLlbggGTbZTtUW8OtfDjSb7D9jsYpI6O9U4MfMO/vBj21ySTY+KqhAhplJZNTPq6PTec5Jn7ck/1oSkt23K02BjWC/FSxu7Wzp1kjzqMWRuXX0iXW2D8rd822WhS2elEvr92QSZHZBFKliEep8VCbNt5VveSSz/MD6rvrRDaxAkD+Bcy2K7Ulg/9Kt+HW/a9ITLBM+9Xzo2nUfqiymPWr3NsURBu0QilLBkVuJkmcw9J0fkkexCsg/5LQi0G5I3Lrbbo0D4ZTuKmHGjVzoqwvSXRN0dd+W6risHSu98cd5a4qTEpjS1rcVmxGAD4uppmlK47uuIJYQTeHNF12l/lXTaYgpqKZlxybv/6cgREHQAAAesx2jklE6RBwjsTPKNiCTSbYmYIdJEapu8oNIlHEEgk3JJjVgM2DsmiSItZxHvTfsZlpMqAmgr9lerWsF6PxHXqb1to+tUuv7EBOBWx8w+4tVQivs6SpL/3/aARJ/+9ooxkPU+qFokDa4XhmDHhZsatpgxbSQ+AesbSHLZKrrcNW7i5X0AYEnSyouDFaqnkEUUzpahImY/xRnNVd4ATbkjhqUgI2JAlYHx0ZphOKSOkOT21zfvLOpnO3fZfGb9hHZdvsNBTMRUSYDbeAhhV9U1p/EY0RCcPJkVXPDjli6TtF1FdH/QkAHakW3G7q8C4Ob6loUaq2SqvHD6Pk/2zy6vqfr/Qfbbda2u6015JztXidObftpob/9e62O5QpAUyLlNoFrldIdfj3oOXuqmIKaig//pwBI3uAACB/xhXmekTMELEe0MkolCI3KGDoxRxcRQObCj0lSoABzf9gZY44ogpy6VI5XpNlyewyHlqx/XNUn46WkFjY/6y9JAN6anX8MrairUd1SQsy8M0a0C0UXr6kOblb/8mCW5ban2ABdATYKYtbCWonOlaOCS77+6vKjuV/w4SsJvNqG2pK4dAyDOWUIB4TTEyXIC6ZY0QR3IYHVqedIJp1s7/Ui2G5Uo5bbd2zz0lY3GUwoN3QbhJPpzOMxEf+TlGfzhm56xCkMz6qXphnwmlPNJMDqpwi1V0sZf8jcoaKhUHSb3qkmNXd67CABBTkkV0FUiG2Gx3EgVxxmyg5FVL9CT/4k/FEx9MReVLixH5v6hjdVILrh57Fxc6vhbFhwqZfYsCtdIfVYWRIIvTZJ60xBTUUP/6cgQGMgAIgiZPWpEoEh5Do5rjPSJmCC1JbUMkQbD4m20YwxSeAn/E07ArQPT4XpVnDWJwT8Eyo4otXf7p2L78YEzPodtev8euMYyoRHR5iOGM40+7bTHYqIyVndpn9tdCrZmqDWj4TW/IAJX7hcOayB+jF7ITFFnwxwpUkfW8d/D1J5azZHAZQFxD2NR2asL1fCBWgNCt9eltNOMCAgTHlLmBBSn5j/uF2HwBbeYICSacAmLHey3hi2t5c8/RPptOM4Kj5PpR6ETlfTRhq/Kbep6YpZJAio+lP6+nft778jtWzf9EVjmdnM5h2rsJrUg1WFxDhD2oWl8ZJllg4Z4H0FmZDT2BdhiX0p6P30Mu39TF5J6O5bLVP/XtuQZnnHWcUeL+vexgLTdqjqQ8mIKaimZccm4AAAAA//pwBN0UAAACIEzb1SCgDD7J22ekiAHIxY1xWGKAGRUxrd8SUAMCAUQUm24FNsToGHJFrqsC63MxJrRtjEO/+kjqaLleZ8r3b196kOca8wUZUZbt/pazotTNiFv5Pb+nrpsy1bFZww9MGQFElFpwLbom5IbmTUhqyt+a2CLZllkUfZpfjq5GLo+RqMb/b69KJVXJp9OT/k6//e1+n37auUxiu4Q3X1+hkAAAQAlIICAQDAQECzCxkBILA1FCRh4NIKxCFY5Gd3M9B6OtV9KPSn9f/+v///P///k3zn////yE//////ZxAUQOCgHF8x4AAhJAASAYCAioKSDDSA69UyymgTnmJEdSHFLvR8ev6/uZldFq7L////v/5///8m+c7////xQn/////7OICgwBAQAxfMemIKaigP/6cgRtrAAAAhon5W4CAARD5hv6wagACHyRhTwxAAEUjXAnjDAAAAAAAEAQEAoG2eowGg8xL36BcR/yfPGZP/+QMhw4Dhr/+JTFKjNBqgWcLI2VkA2UUcaYwJuPGvrB1agW//Ii4f39WoAAAIEIBgUU2igVCaDm5F6M3aAfkI+/JAbCX/FtiMf/+K4yFhDf/wK4NIhgGBBA2f+3MZCSf79wcNPGO4FX/3+wXT/1YAoIAtfwg4tzI09kMs4jrI67nmvIv1ZCvR13u/oru9UeCe0UeCxo6FD7mrmngFZVSnpcswDTEr3vekAIQ93+7AvzVWuAAAAAWqHBws/VLIZjRsPwICOrD/Huexo+WZ1YrcZfHLamm1kSz6g6VDoBAQqYXpDaDtzCM1JDB17aeaOOMmP9Gk67pdYmIKaA//pwBDkRAA8B3BTeAasY0ERDDMwAYgmIXD92B5hjQQeMrsD2DGho4QVBShlJw1P8Jd0MDqVKlUYoG2q5+YIuWAxUXFiLUDEFQg0SCBljYmFxg1NzC6YGx1uTdT/1Iaj87pASdijffTXSJHzGYEzthWYQ9WqXNRc/z7gkJi6uRGhKVCAQq1hUkxtCr99Nccs0FiB860VTFWMacAdz1XuK1pPOcjamYxI+HiqC0fdRbeRALB4RAmldKMVAAREBUmIAATDp8PmoqHHpSTetZZ+GiQXSyimJZN4ohGqcYuadd2GER45OwVV9327wmR0rIkN2CytiO37IVIbLyzrOI9alhZFwEmTCjxs25QPOvB+8k0G3WDQG0dum1nVpVc7YralCjFkUuyYrqU36PrTEFNRTMuOTcAAAAAAAAP/6cgSWbwAA4iEr3ZGBG7BBg/uQPSMaCLiPgaMEb2EHjG4Ex42AAWVvq5G0jLu7SKd/dgGcguC5TJ7lI1+cMyWUvXlzMGbGR9I8terZPOjIMFrw0Ye0RV3vVjUitirm+o9R4T8m5CK4uYbfC+R1D4OrtxS3V52qJRZEjbHKJol/hxCFFeM2bhZkeX0oYMDFGEs6GhZk0iWvOoe0BS957jYcm1XC/gZlHhP/r3QAgpFMtNsJSjvj2+tT9tzCwpRcUIirgqBtSTIpoDtcyh3Fd6jAgKIA6VUgCkBg57hapHu5fF3UrFquQ6Jm0815ax9ddsOntBpZOzOEtxeLes1s8Ejwii+WIVSG3hhl84i9NIM0ymaYoONeOPsIlZACsUnVUVpuM9d4TCdN1x2hD/AVrLFWPprTEFNRQAAA//pwBOUlAAgCHBjbsYE0MEQha/0EaQsIVHFqQLxBwREWr/Q0iYwAQCtVt01xTJwbIbJRaSRyhnIsyTmFxhO5YjEKATsu445+MPPFnLMKK8kmeJCA0tMisOmwqNcoKLi4yKdDE+vzH6PW6BBEiBJKONSoUIKaD6C+S5QRV1jYxzAMMFqkvVPFpUjQu2qMWTGGnrARGTHKaEng0hzi2hrFfsrdO8kZtRrTZeSMFi1YE/+sFBHuQwsncRsQiCuJpXasGbXDuzJCvBIzZnq2NqZlENbjyJg37ryDnNCRsRLQsQtxiDyj0l0upZ6Y7zFfZMf78ACiMY0bdduNMXUBHsGsLugkpRZjZWOaqYSnr2sXbpa/t8M2s8q7FlbBDbnRaki4alrxAp8yMhumgKUjnr3B1zd8r6LkxBTUUP/6cgSZUwAEAhYP2xgvMGBBJrv9GCKPCFDZbOeEU4EYFq7kgIreACcltTliUF4bEWdjgyQolXTASfKAHduI9RiMqG0Kc4gVa+ywUqFEsjJ4MIW1uT9ERGqUHmP6VjolfIvTzlq8nQ7TuwAAYsTb+/36jux+FfvP+enDIqL4xV0EnGj5icwWLfvNp/aCjtfouVJkKUmWnjDo02KIbfb13sCyUpajmBd7dDvXACHLbbN8tBuES1LNZktfc1IDaY1eq9UpmOBQAfLyANEQyXeXydTjpGgJwUhnSFlZxdX3kBmSlwtRcwrt9H9h36P9SACLIzK9RmjQ0UO0E/K0yFHWyps1cJM9irXU1mYj7+3QSeVWbkiazborDxVVS3h1ZJxoi9wsmeNegXR/elVCpslaymB90wmIKaigAAAA//pwBHsMAADCFhxc6SUbyELD6yJh4yoIqGNxpbyogQiOLM2EFdCgAAAAoKSRy5qh4DiVMz0iTrofR0MIwr3LdiSsUGRU76yGB9sLEWLaKhkUE4smols2qQWvLMpNryNqvTZpTM7P4V+oCf83jEIOipFRmMWyHFwgN8GQxVcD1YcIlXGkDmFMSmVAgq0TrGIGfgLVC+H9UcwzZSo7GqSRMbSyVzyjx2/TT2emmAAAAABOXb/7kgTwqTF86bLVvrd3CKW4k930UjkxTVtNULBroaqcSLCoqMERypYYY5+s4prE7x9DFZGL33FnLa9Hs0G/qAKUktr/JGnwYRMeGDsY+7Px+pUgaNlnmUBhasu5WlEWurYtq7MAWO42YR3KU+xL7Q3dWgVYbDak9XXfy2iRT2q7UJiCmooAAP/6cgSnWAAMQfQjWhnmK6BB4xtDBeMOCOi1amC8YcEcjGzo9AnQADkto9IZzDII8zWnDox+er7ZwF2HG9TFaPLctsstActdC7M5Qz8fr1XmHMJUxKSMyO1HQNhNKZJiaZb+nT6QApbaDTGcQ0gyUjWJFK7CZjTQ4YQ2umeIG7B1kA9oDO5ep+UoC7Tm1wAwata30BR4naLnjgWsMTRwJKWj/q9+1f1EJzb/liGquA7Yqby1QspFbhL8MJ7V2u9ounKcJcAlvxvilAtI/3//3vO/Pn3inHypDSwYB1GhsjJp0umWbuoRqrvV+nT31VwAABmzbRrsJHAyDpO2fpg0JUyh73rAi1iUFp5cnMyW5xRoR7NQMnWGQFYGgM2Hje8t1kzNyJyRMNTJLVWQUg19i3U2ou2fvTEFNRQA//pwBGJhAAwCASxZmw8RYEMDCxM8xXYIrGNgbDCugR2JLaj2DKoAqWbDLkqvu+TPLJLbnMXrlN3MoXUt0jw9KSyz0MDZ6C6o/drzzG/X1eyaJYRMfvvc6x32mRedHWyfuFmDv//0AAqWUT4hKkEMM9XrbG7HC8SJpwjwTQDKiKBvJ6WL1naE+LL59gFskWxatrrqpI23rNlhdi73AqaWxUr6GR93bV3aCwAKctFvckkKT5NpPzVC1V++1WTbc1nJPk+MQF6wzH+vNvQqmrztHNyuB0h25b1pnhxhQFYUlCNjfSaU8Xu2j2tvS/p//rQACAEJuS31hRTeGtR9guhnfXnlWgDWUpmJUCbXGswDWfCkhOoq5E+oehYdLMW3fXa8BCLE1Fz7Vzc1pOKKqWypIqIpXfT/1JiCmv/6cgTL4gAMggAcWRnsKVBBBkszPMV0CJRzZmeYrhEeEu5odAi+AKluAvTIzwXKFAWGDAkCVdgKlgjBcBFcqEjjliFhOL2ojWoXRnEQG7Y51OtijIcjQEhoFcy4FlCq+S5axYv6LAUnd+Na4tdASzFPHViIxhPZUzmDldwOT+qkJenjmFrLQ+6DrA1Dk7Iz3+rRjVtJrPoiWf7YyJ0I0ZOtak9N/Z/rACTcg3ddi4CnoQvppnQ5KUXC3EVJciTysL0ljNGuDGepcmGvS8My8WURD3l7YRJHRaeYLkjzj+xdFZjvNLYfaij9ft9YQgBJpO5UIAqGoZWCvByGsDx5xDpHKo971LdUqvtE7+VLqmftIxjiAkdUg4VcKNeXYzKtbovMWMb3argdI9fQtZM0uq5rkwCmIKaigAAA//pwBHZaAAACFhlYGDhIYEQjnC0MJaGIeEl7QwRK8RITLQzEiSoApzYADfRNFZaoGNxWMKzvP1skr237Jw6TFBzDdWd3bRk9P6KWTukyT/dtIjgmq4yAZEiNHkDPW3L3LDxEZofePdWugwJFmJuyy3sK1dBVleRyPD0rP6QoLs3urNASy3ILbcYOEBoYkWNG0iVzy+g0KXkrUVYtrWDcXImW3OXVU9/V8ywSf9mCwNEluOXIS1SiJfSCTFoYKHVlVQ73iSLttntM4i4qBxGswImlgRgMi4lZYmfoO5dg4dP70G8SsBMAMY0MCJ7tmaqxEAU3JRWpSMj0MFnnY8D3kQp2Rgkgxh7tkpJO9Td8TVsXqck6uduezXa2VTs7lGiLKqLuGlOwiprZ3Wx6p8b+VW4xqQzKJiCmgP/6cARNCAAAAhcmWT08oARDpJutpAgBiGV/cjjBABkWMnCrBiACgAAEm4A4WYC/nePFErTKhSMrCic05iGmcEFx5TGsoTEVdwZaviyNeovt2dZEbfTIiqOZGEGnMiiW7JTiV4aGkK3J1kAiEEkEtNOCYQuRMkVay5r0gIscUUfM2dT7t6kepiuI/QysIZnvphB4OjXXMY9Cja7L1YzuKRZAXbf0H5g7e9JlDjaQgSYQrQ9QxOJUTFU78PaU5cDFEMJGla7Tyd+2y+vnV//rxBCT//5yKchG///FoR8hCf//+LO5CEkILP/////Fv1g4eAAABV00oCAgGBAJi69aEfTKb4N+0pe1yEgiv25j+/Of96/yf//uRTkI3//4tGfYhP///AznIEEIEEAZ/////4G9CQAkW6YgpoD/+nIEQgQAAQIaK15PGEAARQVrteSIAAfo13SkmENA/Ilu5BMIMAAQJYQAO9DYkxuye/u8r1pq5Nnwbt0b+jUeVFasqB3OkisjNZbvsUKcchooagZ6nVsTSOecSrfkQCHVP378Uyi6OZqBMoHTsSJLqZlZK5XeGFuqa+vP3ov8zUeVFasqB3OiEVkZrLd7MUKccVaKGoGepzliFLjI4ecSrfkQCHVPx2/FMotiOZqALjbQD+AgrCt3WlJjYwmzKz87QY9+yovP+rvte5qtV7M/TqyI7oX+1W8X1SQtkG9EyEjyhZoMiLTvi9JX6GaAABH6ABZmPBTZVbb6umH7ItgZjsUW2MLh9QRPPE8CmulJ4kt5jyQobZ63S/VbyDfxgjULNBkRaWXxebK7NDNCYgpqKZlxybgAAAAAAP/6cAQxdgAEwfY13CkhE6BCxBtgMSI+CKRRZieZDoEHCqzE9higgB5u6cEhpEkydZYrnjMaFmY+hooYNoAKOvf20crc30KM9Ey0/f0dLfqVk24gqGk95GonlNIzrGlvXI5Zq/5G+icLCiTolIfddJwPZNvMavPhf1jO3tDTXO+/0VK6J9kKMPFJ0i2klIioB1hqiUKtT3kam/S57KxoibfWJiLpZq/5FJ4+oCdOkma+6RiMWZl2wF7cz4OF1olkPIkNmowugGMZI90Ezy48XHaRx4lixrfvU7EttR3tkkZRVWpRVN5Q98r60t8bUN8esiLLySMaTQinLzrK4Da9kgL5uHKdEZDGqF7xAdr38i1CXPJARlJ4KBrAW7S9TsFbYsd+SRlNXoTeUPfNev9dSYgpqKZlxybgAAD/+nIEhHgAAAIZNd5QwROoQ2arUzDCdgi08XlEhLDRDCAv5DCKFsAgpMltkuXhaCWX04Tt5rGHoRMeamkjRV0fqmzk1XI9cpUXBr6d1dehh3q1evR+GJ0dSgMfu5GaQpT0V0qQrF3+gjWEXG3JHwpLg7AdHNwnPY/K8kUqOKfai72htx3FtwJP9QJ3Vrj66oW/XuqvzTX6o+au3+jtgn9vy/1MMWsT/8nRwy/W1AAIQk3LZN5dNhBfEMZe5u9k1wmqeamtQ4ns1bFf0f3s+v/9NDiiU22LzsuEgHe9yOMWowzy0qDxZrzrySNy2fY/t9YlzcAK1HfVZwHQoR8HknA54aW6bIILmpY7FUOUjNjfmHb0YuzZzHVkRNfI3/50ckMLo9cL6aI+JP/BkvuijfkNDbUax/WmIKaigP/6cARWpwAAAgQ2WxkjE7BAiwvpDCJziNTngUQEVzEXpi8kYYl+Bcltt9jIFADi6QLBNhlNddQZCDZSHhVhFQa7EhtHshKC/0M9K2PqnW21fMVFoXVbX/iq5Bsi/AX7ZLFxn7daPrwBCpqurSVgwJTCZ3aJ0MEVUXKD3zNSZvFdWr+jG91b0TrY6A2YyuzpolytuK9Nta5USwY33+rP/4J/372yZ43rkhHopxtpyrqhSUca03xcwGuLWPjeeRvxWusiYxcoyjhcIbUGjQVt2qIsgeR/mg2aklgtbPrs3jA86DrMhSBmnoldPaDVKlwAhS11N5USYBqWn8r7eGi8Uk+xwpZPULjIW0JYTZYoafsIZGRN8v66oy5nTkstVcikdKbmpm/f//SZd+KGP1oUX1mHJ9ykxBTUUAD/+nIE3MwAAAIdNdzpgxQ4QoKsXQgiD4h8aXTgpGDRFJrtXPGV4AAAAKQI5bJL0oSCMqWkkOvdAucs0fxPXgBFzl6DPo0IzR6Ro6r7KjNbUrd74hlT7KlS6L6936iV+L6k/1Oss7NfId9VARZUjcllkmGCWZiaRhyFCDYR7tWcHg3TkDmUuOd0YSU5BmjWkDnA0JSVgAN52pmIc89OulQB2XO+qqYmyeWHOKjWyHDbkstUYYCDXw+eENKpYpd+J2rJ54P2bKXs1CIgVBQaWJk7jg8POU+koTIe8Xc84cmB+igb+ykqREgECuu26sO/W6uAAbk2202GJkC0Ig/p2a8afDahrLSBWyb6Jcli+DH4cIM3DYH1ekcpi53pVGVU+/a7FHO0vqq/oPywpvnnMp97HKHu/8smIKaigP/6cAS5SAAIAhwY2JsPMUBBIxtKPCNyCCBldSAlAbERiSxMHBgwCLckg5p0n9BTnHlhhAXSGqFTH6XppXy1qU9AkNsevYkGW4KPZBL7rrbeYNmVg2xyZFLpB3GtVTQ9TK3/V2t+Fmq0/pwAAgNObbbVmptAxjmMzSRPOJNaYvTNc4wWSVZuQyFgx6Rx7HjGQBMjQGzPJQ673B8dJqtU8q3lt1t+jVNVaf//QEr1VWuYACf+rNvl4OyxzUQO+6H8xHeHBykNlW4+3xgRwDTyL50Q4YQpDNUwpboq40ucZIpvO8GO9CxF493m7qzIAUdts77JCbisa5IObgt6vTYRxikhrroRljzvlD5F45z8SOLoBxLDZ9yGvc217KjBV7FGG+lxpbjhLf7xfu3/Ga/fp+hMQU1FMy45NwD/+nIEfdUACAIgK9gbDBJgRGScDQTDB4hsTXTlhFCxAZXtyPMUpgAXLaO7T/ayFWM6fDa+40BgEa3AerLwhqNrtUapgo0vlnfklWfRbPMp6mRuh36MnujznZ639WQdzOTRSrX1bGnvsZ1IRASJVRbkjk03scb8OXF4LOOfcgJwEfpnD88Rde8hqWTfD3+e37Q4ovNrtToj91YyXuVqFQ9G21t3WMZQ6OddCtbnw/0MCKTTd8ilwvfFMONS5Q3Gc63bs9p1QuDiDo1ti1Gj5WbTPo2lwsSGPNIOLJXmGeXCx5hBRw6uxKHomgj36kSrvijlLBma/22QW1wAYYQpRzQEK1IlHR3Qee8YG50fraVzJkehR7bpLvLbT/lOQaq5hU03S6VttWpZhnrF2iyJFmjp6fUmIKaigAAAAP/6cASqAAAIQgoZV5sJE7A/glsTYeYmCCj/dOAwoREYkCydgxVaAAktA7tnsXBiqrvuY50fULeHDjVdwWuomUas6bfYSkpaIkf6bfyNejMErYKqSdVcLMsNT5RYxI/YpDnmua+YV8UBKl347m8cpFXJSCnujCQCrSMjekwOSKO+bWs8dnStS/DHggaYLmS+MEjFuoPoACacMrYB9L2OajVoYjJEfVaswjcu37CMO2EOrL7GYeqGNPV9/bTEnePOZEUwKzJy1SbXf5KafNZHs963ynteI+3Otlblcaw0pCPtCwVTvk7lyJGAAptyDLGrTCrYurbF5XAtSOUAQalFU6TFyzva47E7G59WWCMkzK87OjoOaJAgTDIoKPYWVrdHW7VWprJuOhf3Yrioq930piCmopmXHJuAAAD/+nIEZoAAAAIiLF7QqBWcQ4mbmjzCK4ikqWzlpEORFJVsDYSJ2sAAqDbckoRxkBHEXuO0HUY503jB5ztJo0hNr6mJYL/zzs5C7+GejNzeomYIyEPSRhoLPNIS82aCUqsKI+uhhBBMDexCIAAVBKTbg96XJAmRIeFyX4nsjrm3sWexCa5MyWXQfTV/595jrr/y2Z5avXe9i2U2XMh38ztV0PJXp62O81EsEae6lmACBJyXYcC54BxCVPnEidL0P0kG37CuCsujQbbKjIVUgw2e6GV6PpU5LsRWZ6vbHzCqN5lYTIjAKZW57RgfOOKsHkL/v9AAKbkGeppkxnSp55lxvs0Jv4Axzgecyb+HD3LvwpsRthiUuXy+iyqlW76T777sjzVV5X8eeFQgRsQm9A55EY1viR9Xp5pMQf/6cATrKQABQg8sW9EjE8xBhssTYSU8iGStbtTBADEZDqzenjACQACIIktODesSGHHDVnjSfVQWmJkUGWZsMavVLBlWLQmK6l96Onp3ZP/6skLPqc/CO5ius4SKpPBCnah7w6Oe3jYuESnIBfrxKTByEOy2GzkIQAgF00IgVTLOtnqvtLcynu0LRQ8aGSMpt7XqZUrp3pJ/9frdJt9mfxRaiQUKUUD3in0AGVqbtoHlwaLUdRQTQ5tCoOUQiXVqYLAXu1iu2iiOlwTlV2bZjucirZat6mgjoTAtzLeKWJXSKUsIuO7bmnjQ70TQ+AJJyWjGcIeBSSQrlkgYitXvEQn1cXp+ZufMUxYU9UREZI27ayco6pICAwBg4KqOlKhcwkTgUQ7juZZcnePSkilx37zVV60xBTUUAAD/+nIEPSgAAAIgZOYeAUAEROnLscYUAAhlWYj4goABCCswyxJQAgIBQMBgMBv/////6K6p/+SERJUp//gVBFAFBMHhUW///wXwa3dT2KCx///43UfjhQLwFY8YeG/////k40WgqEhASMP3BJJ0RZN6AJv/rUp6xNqjmfvqUTVVTD4o3+4cFP/kU7J/+KDBScZ//gQWAQUIov//+Ji/egp///4+dkFAchT//lzkMCAuAJAAABQMBgMBJdGg+qJcTirxL5DeZP/////6f/5VOMHCpdf/nOVRY4iJin//7WKgsGjRgkHP//t8WAQUAAahxixcBAAMMMMOTwMgvBRz6uxx5rFeQ3mRP3////+n/+HSiYUOFS6//GnKosLiImKf//szFQWHjRgkKf///FgEYBBqHGLOEExBTUUAAP/6cAQdmgAAAgUa5W8NAAxEI0wd5YgBCJyDcSewoYESmvE0YJReBcbc0sljRJVDwwy7ty4hsx1R2657hIekd1/++F/uAcOYxswHRwHLNKoK5UJ38+nW5VOP5XJfWZhm3pfVTdy2sSgJlna761ootMC6TqZD3bq0DNc8tq/W7MjNdEbpInWgOOXQAjZForCU7hNqeXWew1PX0t52t2jJPKPX5vFLw1rh2oXOrAADG2RaO8CwcH3ITsLf8xQJnP1ZIrq1c7OeYnRHZ1IfugSb96lcSeGZ4V0Zax+1eWK0L6M19jjwvkwLXdLFssHlN6WpaECUJZHGyiSnCDjCow7jHsLIwk19pmSdTNdEMZxVj93AZm/nZxLTmp+21TLSb5/8PFaF7DWa0OkXHhfJr7pYtljSm6rbUxBTUUD/+nIEW/YACIILQF1R6BBQQIa7EGTFagiY12hsMEGBF40smZMJoAAA4DttltSQIMeWLMZJ3jZAtWic9W+3VP04OiXDjGtmtZSsrPVqW3r4NLGR7c2rpqJ/+/9wbqudooFeurTraxH9Q6QeqbhqVxtLWcm3onbsZqDjzsFiwtXL5mVkcWrIY1aoaSpbN5X8BWfX6qWVO1Lb/rsl/c1RWlFFf/JfR6m/Z9oAKckgE8GuHAnrRLUJUFzzjgCI2c5Dhdm4cY1yB6KijytUX6/T6tqT8btbqRtv6wjtYGIFXxlbywoxiHfYnPaNXl/211EA9bzC0AYy9Yap4dkVLH53CNWRUwrCBrACv9KX2nTVP7g/Na4symq/gToA0h9uKJvFa3UdR3cnb0VI3bDFg8t/8/ZySdSUxBTUUAAAAP/6cASm6QAIAgI12RMpEzBC6Bu6PWILCFjZa0ewo4EVJu+ohJVGAmqALsNJQLhAyjs/DOUtsTcQYNLGlgpt1hZuv8A89VBQR2RIgrDQYaPlMlzBmaiAy6t9D/9Aumu6dNcT9ft/+gBQ7klrnNwhSOTlQodK3o0fDikEvwQ/q2gIkiZvVPK3+7EEXv1m3WrHZIN6Hr1bH12//19gbfz1cwJO9gQ4qQVxEwyEAArltpbwVjH4GF5zHflScFV8wGO/DkWrYItsUy6oWmIrbGc6CY+1Geune/IvRX037o9Wrj9lty00ffm27ujdrNfQAQXRSqSSZYIHNjK6vaxsyaDkQyQ2mX6X4onGr4k2rkQxRhw0PlfpvOn+ol9fupkrQ7TH6NdX78v79+c7ba41ucV4mdu0piCmooAAAAD/+nIEPSMAAAIkNeJooRQ8QgQLiiXiUwhkr2lGJEzBFRiu5MQJphEYCtG3JI5KpwsEUyqItaIPhoEGVNo8fdeTk5QnmI/BP78hesv65Zeki1TneXF29QTIkizaEahzjhBrPwMjKuiwyszSsAAcC1InLioXFCFARu6tY7Ip8uJZCtKo/ZXbq09ANVZlEereT4zLA1AWzP0+ZvPUo0bj2zYoctjlLVqqXw033MUq0AAMQBJLbXHzGryGYnbVpDPQJESR0CFXdLK/3SF8+CTdkW+X3bwwp6+83spfl0QE/qrChMW6n2NVZUypSn2oT+vkP0gIDVL2t81FG+3WlJ9/QdN0oNTKoSd32on9MhW5L6l9+8E6Krqu8nRWq/4YAOlWOj1Cqat5xZ7poV2bFQ1YAL/oru9BV1SYgpqKAP/6cATtJgAIAiEpXDjKEbhDJltHJeVFCCRrXCwwzNEPIe8ogInOAOkdLbeKRvTRepq0TFA3oNUVLs3OLc1Fvsq038L3eYjzh1g5Lcr+oyShAWazHh2ectg7KqkhJp0IykKj3fU6VDuT2PaAgERNNwHhKaEg6u355Q6Nn0CPcI0NHRlFeYYGyNUujht0zeVOgkzJIXyuj6dtvEnLt7LizxYr1bhS47mtz1P3W7vlgeia7WrwtlS7FVn/kErlgkvNDSmwTgn1+KZ12HnTkZ4K1c5nVW02YWEdf11rJEK2VaH7lijrqqkoRbvr/1Wv1/0oSFKUW0m45aS0TemL4GAkrCdarwT9V6RLuXG830G6v62TXUzK3RG9OnQ2Mj/6d6VXSmVBqgEt9RdiDlhwCHk/UdoMzKYgpqKAAAD/+nAElLMAAAH8NN1JJRMsQ8ar6g1iU4hRL31ChFixFhSrzZSdmBBBkGqr+vHLOFozlESQNOw9iCwf4/X3o3QBk2Ob283ZK1ZRSaFP1Rqa/SC4stElzKW6NlT2jgDQHiJ/QRs2vqB4P1NNtuXqoDNT10xUeo6os2zro+XujmAmvn9vnb0J2NV6+6v4Jvf6QBphc21zDtK1ejY2ResNrVhhoac/Bc5TkYrmdBB5TUjblGGZUGIzO4vC3eKrV1BqYwfsgg/QIzujBW30QGe+OFpTVERCuW3/Y8+pFf///7b9r8lN4IqIvy2zu+goQADjko1AzR3fbovuT1YnL7CYcoGbkIH4DMrtrwvs2sfflBAxjGQr1Ye8l7KWRaH3dK0Ux37oSwxnbL5x3Ftb6vp37B6++tMQU1FAAAAA//pyBHRRAAgCHhhbUYY7JD7juyMyBVAIwMtiZ7ROwRuabqjDleYAAJCC1JLdetbl5ypg+AWYAhVND306i0s3CherIPN0O9iPYVGhhgnfP5PFCKmEU4EKvcdOBDUirM6MnsTDgtX0r/btqQDl3/KZUFxkdkQj1d+4eLBMBwPOGpM6AlMoOg5RgMGdwr0X2XyDvSerdUyAnXVQ3FS9ins3bvL6bS1rft+vWCErt/WdXQVOFBHeytsiNEvEBvLMeClrO5W6CaChUS3kiz1h53oL9F72phPT6/QbYwOyp+pozSP9z8/UYrewheV/qbt1/1gcFyUm2m5tWK8UnE+f0enY2j5xUpDq8uy1FLZrALelX93yodjdfFGvY4q3Chxcxi6/lexceWp2Wh/PRzlFRZiTFfv7ez+6tMQU1FD/+nAESbQAAAIePeDoZRQ8QoZbmhmHRYg002VHlHHBDKLuaIWVXkiUArI425LfGZogfkyweiiIgbGhlWMAwJvm3hAliTez+jf9P2+N1B/f6sQzqPv/Xu4lTidQyg9FMTJ7OZkAilYAr5mgQApWS0UnfBlUSG7P3tC01cZfpcoLd44Xoo+JIbP4ifbzG7D5ZOna9v9G9f/tLRMtbNu7ZVqy1ImJSP2YIpWp6x3mgAAwBMl//ajwgrLsczKt+sIr2oEYku1IbBjauUr84Y6Yho6hNbVFfM+tyN2fo3k+grns//yPSo9TPnqdTqvo/+3UggUgJSiTroI1SB5rJtEi2npmdQ9qi3GM+IfD/oW+v1+3sT3+Y8ylBB7UlNYzb6vf//P9v/Ga7UNp6bMmxwCGrW59KkxBTUUzLjk3//pyBF4IAACCDEjdUMgUPEKFeyc9ImiIvNNedPOAAQ8abWaYcAYgANEkkU5Wy1yLjX8q4UptDzRUT/81tkOsMtBIv5hr5Pq3p4VU0/T6f/e7V/+b6e7enz12FHYridFuSpelRdyx3oAIgW03JpNwN2Hyq40vdM6+DjR8JmPGuWZgtlDTuzHmxIpwD6y6NooNPFm8Gm9WRqP4b6SzxZe2/7vL5bst+3frr+gERu3a6fjqw/h4kGVc6rVaDsAyuLWiz8LmqeI40MMZRuHbOKT1aUEVXuhPzzMzINlT9cu/t6P6fN/m5Wp5LO7vXldGn//WEA0y2sfJrkihdHeLUVw5F96LXPPcUE3Rpxa1RFqp5gj3xoGzznMIGervdU1uS9D/l+prevqZN1LKks7926VytCf/u1piCmooAAD/+nAElBAAAAISQOBWDEAEQIFbk8YMAIi9iXYYkoAJGCcwTwZQAAAAFpfo3tdttv+AOIG888mlvIy0MZwqyZ4RzQ6Fck0itVfN8UZ0oKelJm0fSt+261bV1p0Tr13pXjFk7AdOPegsihJNuSWW2gB44Q77kpouUnYKLj+okwsGgeF2hq8iw61jGPKm72VuHxhpTnj60urfUAwCU7GwMsoLypZKc0ce+oql6zk1wXdOEw2HDtqWBdIsgkKS4ydyPa3RCE+9scY//+IMh2N/t8VEQEUejf9v8RQ50Ygmn//29rug0VZDN/////bOLyRCOBAJ0/T4/0j+4H3riAUD7n6N/////FDLL/+HGGHYSvn7fFRoCKPRvO/ZUfJVU+v6f+jLdmu8aKsInDAAnPyTDEDi+5J+cLpiCmoo//pyBNz+AAACCA9lbwxgDESA6/rmDAAIyElzLBhFgQ2KtDwwlg4ApJOSWNpEA8Ea7IaqWZs3KpZHGoVVChM8LiJ9ulqeLkVlmIqxYqZGNCRWJLQ6swKNcz7B69SGVce7eLyt/qZi6QABpsbbSR0uAYXnuQUj2vWOgaDgqGmgaGoUD7IQetqHlmp3i5FZZiKsWKmRjQkV88swKXMbjbB69SGVIx50UmxLAN/+0AArOkADpKR3YtMxwTvRYHkE3JuY3lT41+oquRhw+kFXvRCJ+dEa38qCoeKimUms4yppNArktXYWiVhcJyXNixZS6fF88HQM1UzeWb7WRtzgk7hfLvCqAIUaPW5roEQZeH1ESiB8uLvfhE/OiO/lQVDxUUyk1nGVNoFclq7E2sLhP5sWLV0+L4VNpiCmooD/+nAErSYAAAIcIOToZiqcPkL8LyRlHwiE2WQsnE7BHRru9QSUNAlIpvbbI2knXErsIdV5w+JlgJC6A9L2JSEAY6EKONpWrVbSra4rPPYTbI4s8W5xhGAysjxbWZ14oEzukqjdWAWOlXFgIyUBaJjf2WNwuI2Yk79LmY1g/UkA+nMQES8IC2SCGXURWdDTO0rPdtOLHhZ+cYRgMQyPbzP7TvK/WhjpVyl/FbwX8ntGZ8kFqV99qQPiwm/cqwK9WKhM/HA43UVOjwSGrU3Ure66USkiqWVG/pVrlfbVte0VfskeWHp/LZYd6v//HgAIBRF2WRuUOuC0ImZxnd7i/Gz1W961H10HbwlpQDJZoh6P6dKG31LWm/kq1yu/lbXtFk+p/DrfRYHYaBpmyRO+xT+MJJpJpiCmooAA//pyBBA4AAgCBjZcagkoWEMmuxZlBWYImNdnTCTlARYmsXSQiqYAAAGoGElpuBZ0K2oOSms3cjoxVxcjkdRTxg7oECZYq6ORRf7er/bu3z6duyb39tPUX8/RJQDq80MxK/7H6RX1JAIFVVGc2U5ymDLTRpbF78/K10cKpcVODIcItYvGt+DFPS28q9QHV9CV0H+iaye7r6crP/ryX1H+/0BvZqY+r+n1VdYQAgJ1SjFgdqO2phFwRaesnJtCbqTEiUSGWXHAZvEYsm570lRp6P6v69aep39EOXtbrX6KPNAKhWv2f5FEHv0cYf9SbHhpMl+xuSSOU40rt7Cdb953a55qjU1RbL3934FyXsH19+R5IXpTPS+H1T+qW2BpzNQNY324J/X9MpP3QG/1tsWI7EVKfVWmIKaigAD/+nAEBQEADIIYNlnR4zuQQgPLSTzFaQgsU2RnjS5BC5BrmYSV0AAAgBCbckFyDRgsjCebJM8oyMFC+57YjXi2Be48HJqKy2ij3cqNfT5z9DfNJ1tZNXbnm6/t/yP5Jqf9q0bH/v1GaOgAAIqlykcQxWOJcz2y+NulTsYIq8KAc1OsG76xiNbkg6umBt97cd8fltYiQllAwebkGrF/d30JBuBvtWUfsW/0r5kkBpy09QEa8OEIq5RIOmEzYRAteETcZpIO3uHBb77Q77uJ3J5Hbvjj0NyQ9kXf1o0kOrex3Xrve8hMclYhLN+uvYQAaqTdB2msPvD6xVrP7qQWaeVCJRF7KnVigkg5wGfb4EWakYCnVZwm3Vu7o/v4q2e9bpmCOg9U1aurd/7ed+y7v+YTEFNRTMuOTcAA//pyBDxUAAgCBjZaUewpUELkarBl52gIhK9vpiBPYRKbMHQ0Ca4AAMAFJbbUTM4WXyYFpRzZsD1A7d9OSnKWocfTEwzxmtSeJv6v5WasjI1iNSn7WSFdV9UTShEH/sKa/7fG/+/TrLmiRsRehhgMIV8w1/IEfNdV4VqJmnSLDcng+75r3AdxSZv5MeyKi0aVCBM1Sz0kDPHrbnepY3Wu6phjq9//R9n//3gZmLQ625JRFsAqPetLhBkk/2oB1WSIJ/+XW1SK/+al+D5nUy5azh28/y/+j1sCVBmlidZzJNS9qIbx9apu42Qd/zTvtACYE0Tkcccsz+WquuC3GByXJqY/jxt8VIlr6oISOlBpfN9fl8MVDbDzlo/r/6HZ1eygEveF6/1bS0HYjBpyPby4a0VzaYgpqKAAAAD/+nAEdT8ACAIaGFgZ6FMgQ2Y7iTCibYg4a29EnKrhDRksKMepGAAC7LWY5EJUyZBnjhyu4SRDGkJktuQCm7WCQgpVYHSfqFQzWP/Uc5uVfVr25GG2b4sOhSy+cfI6MK7Eoc1ZT+tG7RrAQHBaWbswjtZOzD36ZaNSBYGYwk9/UN2OXqgu+sMpVV0hXbUV6D+n79Cf/FnjxIAmQ2gX+s7Vq3VJOtZb+PMr722PQOjcVm3+JJZQVO3VtALFb525yB1cLH9g8GER0CvGArPlFsjtrBsUUKVvi9qMsWiq6b20bzLVOpcSXlCLPTRsdXv9QAAYBFqS2rEY2MXQVH9uJ6MDlqdYiFnqEarLEGbryAIupzXSLCaqavRe4wLtqSqf0/9Xq0pun8vtvFterRoyVXrR/0JiCmooAAAA//pyBL4QAACCDi9g0GUT3EMEeslh5WgI1Sds4xxJ0RANbWTEnZa1y/m5JJLo8LamxbYxkwz6jAXyhvhbbKJ+gP0R/T4J9nFoXb6j2qu2Gak6Ir3Nf7KjNi8FKz7HnwpZubdQYdTR8FQAAgAEqIMZ1L1vxsUQ5U3EJRLDKjRUOTJhMxPcw89I51itjMI/4+EnXkLA9qlNbj34U/Qz9BO5He1erRpLWf5/bu+gAgRSkmrrmeDynMEwEwsZKH9Rw30D/KvSoODpqSfT0WlTe37fAuRiMqQYjY6fJfm/8rdf0buW+HEFAwXFETI8Y5BUnRltHQHIKK3hyjpILGl5iqEsg+p+moSpgZXubTg9c8Ql15Z+YGPQhkVJZQGd2QrduWKYkK27cptw5hOVKiyzhG5vvooE1wh9CYgpqKD/+nAERWAACAIJFNq5h0LEQoX8HQzih4h9A2NHrE7hDw2tJPWctgCFgpSXQqzPPdsjpfA6gvI4bNzB4v4oD8bmhuVaCjhQvldOykM52pv3VGooAa/WVpRo2WtfaS9y+BjFRlZd7SCEJBMB2OOySS+1H3E5Ltgz6IHhMPh/j5fqRBNVxM3MHtmCuuYf08yP0+gXSi/GwNqORf6PktlAWwmzqcpLz4CG65nRSGARQKl010jNAYj0aa2ekhoaM9m9JIHb1Cj9wuJ38mA5kGdhr0QS/hvKjJVF6o3v8F8n19G/+//d68bDm6XDfRZtrf6wBB0FUS4LpNMjaFKT6u8twSQ7WnT0pTU6wq/QeGVsOCktWYIr+OdjFH7sZiDVl8OWhxjTP3/1YBeksOq1wCnNOU2s4tMQU1FAAAAA//pyBFlzAAwB+yxb0ScS3D7DCwM85mgIUWtsZJRQsSEwrmiyiscAANCggilEou3cD1M1qKFjKAiP0PKC3yhDxQDVWCECXbN9fRb5Rda//g27h8to2bPnW8o+LPjn3a8t10V9luLhgxWfpNlyuYQzBW6l8UneyAEVHxllaIRvugVDBurjNnoGV/TCvtqO0PgQ3IacR5bRWGHyP3b/V3xmvSQ9GzQEASUolU28IA8wp8Q8Lx6Q+41JYKBzdwzwoN3KBkTr9Pj/fdE6IvqJ+T7edvT6f/fyp83UE/ZG/6v6t6t52phh/l9gCA9JFFIuq0u7FiT480zBfVSSOuhEfrm9g4pPVYR5tCe6qBt3T0H9X9Pv8v0+J9W9G9P/v//6ewL0K3VPVvVtUduUNtResfk0mIKaimZccm4AAAD/+nAEWIMAAAIcRlvQxRQsPiUrehlnJ4kIU3eiiKXhGgvxNBMVVgAB0CBRTM7HL50DH/BmCd7kkMNlDegZ4QHzjnD2vb7ff3fgjMtjPtIP9fRvI3VX6Fb+6KnYvLZm4d4uV+3b6HbJTMGgAAwBJRKUy4nBxZ3WX4oMoGT1KoVIehauNC98afFj+R9X9e0n6nd0L/Z8/t9L5WtWXcsEXWZLJeUM098wiKAAIBVhSRRpxXTCakbCw12GHsdDv0GkVAr1FhUOAmESAcygsTAgskAmwjq1DHA+5Gy8oc4D/wI1NQDe+woT90EQuBAQIqdflzSQkJeackTSTJpzCiVcrOw+SRly+jSHQK7wOymHCguESAcz4sGwILJCJsI/UMcH6KN5Ty8vSX4EFieX5AoT6jK1nwIGE/lzSYgg//pwBMMGAApiDw/fsCMYED2i2/kMI3IJMJV4BiBrARMMr0TzDGABAALVaIg13LagfCtc0On0GwkEJCDBaQHgsJ3lwyK4sKqOAU2Uz5RQLtE4fKF4qQkLAim8+xZTqYUcsD7v/lz/r9cAAgAANVfQl65Z4sZlNDgm+DFKCqZQ7/CMOCwneXIrxZijgFNlKD9Rlq6MVIWYR59g9XUwo5b85/qy5/1+uZDQGpWPCaVVvRrV07ZofKZ7cYDtmENB2ymmbD1mqpUX/vzUn5HpjoYkicAA2s2SW4QraSbh5ZIO3ivXxQC1mAIqtz8n3s885Ol+dFAYopQSEgHNNUWGjGK3w2LzCBcQSRmvDTMczaUSshzqzIslJoxaG4AEazbZ0VKtCTUySxIHWPZ/UVrMFFd+T1P+xyUxBTUUAP/6cgRX2AAA8d8X3gHmGLBCgvuwPSMYCUwZeSQYYkEUB+6AJiAQvRuD0lSPsUsog31afm0O0Otzh68j5Hi1AQLGGBiQYCb1zAmZfJCBdDTAcpjm3IQoqxmiryMtZ7N3Xv/TLMQIddgU1NMiqjKbiPJ8mDCjrK4XOHqc7jOQulgEdYQiE4CdcwJiE/aUXRMBylw5rxqGiIqwipiIA8tVPbZH1e/9IANAAIqytQLjQfFvwGIwgbkRDDZ5kbPFXPNGUAi+k0cSBg896L7TzR0YwWUQGLAA0VoCZ0stk410MLK2RVjx1JKWSk8LjeAqEsaqACcEUJ/0eWbMhnh9OGgnuoZjqg0WmC5cFXgAzmwAKGwbDZu1NalpDhpS4oMYSMCzYBKzwtKLxjmuVUdSlke6+Btuh9w5MQU1FAAA//pwBC7uAArhyiPcASEaoENEe4EwwxgI9K1vIKRiwR2M7UCTDWjoBCQuOrPP/C0uTXHQ68Y2+dSbHtVCGdE09z4UOsnbbAannrDo8j7ICQ9jBZ669gsY1Rb28je6LVpAP2CUMuNqyU8C2R8ox/Ycc2DNG9i0jH3pJtVc9zOJ1WTe9IKOeKNItA56QJWOLIeKsab+wWJcy1jq70yKnuQpVN1hAkFWBZFlBE+t52MVeQ/3b8EXw35tW5DUBlUp3zLh5qvKS7dIr2np4M8bY1Ky4OA2hBNLCT2BVcj2npHvbvPuWmy4BW3kEKklwoaFWjAiRmawb0od3SK3dKmv2OV3awN9kMNt6q1Emkc0FbxLOnSB0qsySAILETS5NonCDUlYpMyzRdj6V3iTTX1okni3ZplkxBTUUAAAAP/6cgSkGwAAwhgYWQmIMrBEIysQMSYWCKhfaSMUcmEMEixI85XIAeBaTB3TEAOIf1wqIBesCIdXDhcmv0FPjWJX3azZz3x8mRLUSrjFnQekLXtWeKkVJcqeS9T+zZZ1mGtSrdnTxb436OaD0jeIIHjN4BCzA+FiPM8omr54IvJ3NTaW0XmfrnWWaOrGgVSAgi0LhhRIKklFB7DqQ0OebvCRFDsRYv67F/7PrX/1ACCwIALekTlEwQaTzQuAy3g/u7gYJLzhTdRANLzJ7QdEZd7UIInVoYYMb89FLHPGb5sapKd1GKLrx1Aazcs1Nb0Pq+ei6ArVVPH+hFc9Z3WxrUKByzERr1qHssiIVaBwNXPc8YQcm1X9l1r7mF3uaMH2Bq9x59j0sbRPGbfMaRqGJmLtPsmejamIKaig//pwBFS/AAkCIjXYsYsS0EHC+vE8aXIINGFgRiyrARIL8DRhJT4AgitVqo3Q3xpfH3dYNGBlW8NmVDFBA90wXP+5IhnSJRzspwxWVqaZdPRCmfauuja/olbn9nUbOoct/6VWaPsK3vt+moDpXMxlLNERJwsvmILQMZGYkNsI8tE142kE9jGho/nvTlx6SgiCRIomQVEkcFz6W9xKpzSxFk4imM/XTuuDuj+9qxJh03F3IY9k1hHVGuD97R9r2mA/uu7FxHu6gIDzzGTuNR5U68eOBaWFwIkQlsB2C60cuh5r8RF3MLXTxn9X/qP/UykgXEm3G0nHfNpMDfPS7VGVjvf48ucfW19URuSE7CKBCStvEx4WnxxkwWe4uwLUAOJ7n3R16PIZ0pNJaFrirgpcXV63JiCmooAAAP/6cgQ76QAIgiAYWTklOsBChArhPYY8CGRrYSYgUIESDWzck4mkAEUEnJJFgCRQkqA6FnWg9AB7CDrjAZ+YN8KOe9Sc6dIQyt1danHVIutJLWTXVao+yOUwCPXMLRtPLw5liKjfu+Y0k+kX3ioMVAokZZM0uYcjNlB6GPtm2S3WL5z7EMXVnOEjn3dJ0jiOkNbdeM+fG+ZznNLFrrsfbujIrPUa2xej5dPYz/7gwAX7+LBDKroWD3c15EFsATTMBJdi7Gb+QyCUb4DjIrGtYx92jOWSDFsUKAtbcHioCaSPJHEBUNMvADgFW7v/96f/QQEsolxRgfNJBh5t2OCsiM9kbTFP7FRm2IH8AuiOOzWKNeVOMNGyvO1kYDfDNRUVMOfMX7tZ7DtbZWp9k8bMOPDr0fmUpiCmooAA//pwBFnlAADCHB1ZUYcS4EBjSuJgy2QI3SFzgxRLsRMNK4jHnGgAAJEQ25LcqbrnhyMY0XKxogqWnCUY9GLVxSH3qI4wlYzpUd9pfBpjmC5mshisUZdmpvWPZTQ/a6zIp6b12cojRs1e0CWgkkRgJs0fISJ6QuQWKFaUrLCaeoit2XCH/ZJDr6vJVX8kPVVDVZnpM7CZeDBkY2xU66M+BiZ9SKwERuZTb9hABAMZJma/eeReVOsfEH1OR2EyS6C3kbjQIqNKb1fViaVR5K6fyu9kjXRLm9u6rarp/sM+pBFrhOh1W2O9SUuT6b1HXcf1KQavEysDBm8JuDAoqZ0sTGUR0a+pKql2BGjuBAlZ0KEXSPhyqtjGtKpWgYeELZNDWyL6mPlpYe0XvTI9w0SAJw7W6nSqhMQU0P/6cgTBDwAIwhEX2VHpKTBBhiriYQdoCISDX0espcEWG2tI9RWoAAGAgOS3/szLC2O0JtMPJQCSFTFgg740EbgOfoEx3UF+L5HB116TyElG2vX3SzhSywc++nRoROamLvUg7yarUa/0gL/nv1NxqVjhWZN5O0cUZF2VKFUUJ/iS5trULCak4Jr1DHmE9XRzn17KdvvpRfZqujGt0OyiKlfTdP7KXdtk16NIQABJt7dVHma8cIABpKHDID+CqvBjC8yYpzNyLSP9SvwS2hvVlrcr3Ye61FrKyWQPZlDdlSn0VaNH8kxCjjC1m5G6/jQNvxrTZFnHs2haxmJpmqGbDL4IlH4dNRYgxa6hiONdx8amQAdvUKF/EybTHMzjXVydXT/+K9K+9b0uVxI31KZK4k3qu/qTEFNRQAAA//pwBKHCAADCCxhbSYUzTD0C6yM86GcJGQ2JoZyxMSOkbEz1CapgQNGVUvbrjrAeUZtaIWsWxaZI0NfkH2Kp+pON3ZcUObfK6ccqL5qWc/mHkhtIjTlrd+6v0ofW9xhbmw05SXnO3QUEmVdLmJCwVB3tETxifUGg5Sp1qif4QN2mq5cME9bjH0NSjS5CEzOOfBdPMfT8/v3V/EI/xJi7nOVexH0Nhwua2222XekMN0Y2nd/pNzHSHQQItoiMi1DSm3Cx7rmV5vtq6NVUCjdxhbKj+n7vv+l+3iPeV33F+GKwsA0n4mFpW0tYDGwOAFJpSQXBGo2qiHK7daoMGg7nCpZ+QklMHhM6EDdBu/CCi8E/RxkohNYRrvBP5Lau9ZKaIf9eZv+z+r+f7fFsUbMT27FSxbV/kExBTf/6cgQXjwAAAiBJW1HlEtRCaRtpJOJfiBDfd6OMWjEYIey09QngAADBARxy30vPcmLnje7JKIvsY6rHeMHbQHZuN8f76IDGKrAzXXD3uj/I+h3ThCbJ/+3p8tunhSehOoZbg5R3SNKXUh4AQZFehvwbfwfIT8IWC04Yy2mMecMboDsslVHPQJ9Xk97DM2HvOCDu9L3z+oV3qie7//b0+X5vUR6N1BOeW0fJ4c1kAAB0gNRtJya+EBfxPM0HWPYxDfQt5V80oExjrhJ6p3xkPq8Oh3MzBF7z9H+Yb1fy+wN8vkayFDaj+f3er69f0AAABQANS27+R6zKiGnWJar7lDmVZvSHQycenKhzxJfVhcWdZwD0DeCZlqXoad9F+/sP6Nsq/V/X0X3H9G5AbKn8/S71fAKYgpqKAAAA//pwBPsMAAAB+BhYVT1AAESE2wmnqAEIrXWEeBOAARuusQ8CoAIAAIAglHN5G9kb5AJI6HUklxdI6uiU8Ind3OG3Zw1RsVRTNqVLMiR1qm5+n6tGYxXJ6ak7M5U6PdZof/Tp05kAAIANhZqb1A/Vg7CRNN/yifkjPCmXznIfG3YgA6i4gRSpuMWoYeFMSNyHehOdZV3zvkXxQ4u2vvsfUmjFclY2PT6v/oDAwGAwGAwszmq6////9f85j2Sv/NFg3SI/X/oJQABoYFASN//xEIk3U9Bov3p/+RcycJA2Ik1T////IDjTiB5p5Msf79QQEAgEAgEEv9VKf/////Onsn/zRMH6KIv/+UEMAUHoUgwBo//8Lgek5xp6CIK///41OJJwiBaJR+pT////JB404kPNJx+WPTEFNP/6cgSUPwAAAiEZ5H8IoAw9IkwP4RgACOTXdeGcUIEdGy/8MomkQwJDRIZJGiQAbvq9i1OEooZCiB0AVum9WDXdUTPpkFkn1LYkWaKmVs63jRowjClWILxj5ddRv+ya7U2taNYiwlurOseSCSgTXLfNFJJXHDz2bWVzOBQ5RRwP2/KT/qZDvJPL2Tz/HiqtvtIEiQo8syzclBFu2x/6mUa9egW1XUa6SERACKCWwkAgG2CnEDlPEGOXgIHUeM+N37hAM1lHBlK08uj6t8jiDb0fdPfKyKxn/RWQ3xass9gGRUz9xDg0d9Cw3WG9X7HogEwIuMvzZBAVeAXXKekYfFXKSMBn5h+0IBqqpTqVioeXR9SfI4g29H3T31orI/9WQz+Lsw6WSedFP0KG5YGfmRKPiV+z6kpiCmoo//pwBB4+AAACIDZe6METiEQGy98EZR0IpTNthZRL4QKmMHRQi1aIbBT2Kxsolvip4ghkv18vtY5M4MC8KLfgtXQBfnFNkR0/tmSY7K1HP7+j6fos2ymURcr2aueSsSqtrZ8uM4KjGJx66jAAQAaWOaxlEs0lpfuB+cRq7xR/qP8KWpyAU0tatIR07dkYWRzOytQy7X9H0/RZtqKKXbNmrsSsSlra2fWM4KjGJ1rqAAAAwEogrsk/A9ELfUiWEHxRSKit8N2MA5GcomG9gtvP9f10Ksu4j2+ahit6Pr8T/XVWpfYHWld9esz7FE9aXtR/5jpIIkgCWOJxIpOS9C+SlkFcspvEB9UQBzeDeJp5n+nKMMRFntevuQl8uvxP/7X7sDrSv1IRVmPZiiVN6/o05Jo7CjkxBTUUAP/6cgR88QAIAgxAWeHmOqBEaBt9MKdXCEjXZ0ecsEESFeuFhomoAAAAgACb/irk8mEXRtrfk2YfG8HN2XKO/cPpUTNypDsOkPX6n7U9H+32TVm1dN0/5Cv/v7Y9SnyLB0t+1+tn77bQACAIwm42knnPdqH3/+hXCQ7cuYKBJt36jz1YLjJ+wpP5yu3X9Vujp772Vlc+/f/a2harVrb+7PKc3coRO7zf18Wq5VIYIAFSSSZiM+wxUfi+cEMmbf2s4nkS2ChnjQPpYoITGi/YhfOX0f3bt9P+o0vRP3p6DQDqzTaTXvXWonIa+jffu8iD9BMuxG6Rs0Wk++1gOCrSNWZx3WWiJoKFeQTbrFg2oZxwI9PoLbq/V02PnzNrreDYcInY9WKrxemnNaNan+Ju6Eel/0piCmooAAAA//pwBG1XAAACHxRc6Mg5aEPGuzk85VkImNmFoaTpMQob7/Rwj8ZAABDsSByOWtswwId/gHsi+QocbyUteUeyKBpZalXiQcyvL4q6SMpMuYfgE+ru95ZDMUauV/M0Nih00lVpA2isBUI0VAABBAyLYjMryOVDVvHwEHVA5TBJXQQBzceIc4WGJhEO+gZ6v7P7s2kyXKdrz9JudF//j3n3ofes7DX1tP6qf2LiQ99TQbFWskkcbco53gjb7GE5j0m2fyhicfZC7ZxXspdaRABXuhrcV+g82if/23MfVL8zXaVJS1jVgVmNp8RFUrpf36+Z+L1IkgBVlJxtpSSPWcW8aVbGTKqIBb9vRuokeULNuz9Cul2fS5bud5h0ToGlziY8crW8eBWq6hH9pCq/+2xA9ZjgjJNUmIKaiv/6cgT+igAIAiQXW2liM8hChrspGecbCDBTa0C8oSEUjy90VBbGAAAYiACTjksvclglll30AHZ1feJhJlinpnfxelV7in0OlcrMl7QvY1wTOXDaElY0NIodokBI/ZewrUwXHjqn6HRMf0awAAwmRVnTDnSidrP/2CruVMXErxGdRUL/E5GpzCOW6CE17hYapR3O8r7mfe+rb13qrrv+zp6FnOrqff1aaW6zf9mXTpEktqU06iykxd63riaRhIWHFZ1KGsuHQfwKPe40DHYNtq+HJZ9b94sOaoDVEQHaUUZyXyPr44WUC36SFh0bVyTCg0Ca2m40k4sMaIgdaw5Gvjh6uzAz8I/CI/dsD1XuYWesq+UHrOVgslp4rDdQd+aPjRjymNZ0L+LFoBsIHiKabOAUP+hCYgpqKAAA//pwBNGfAAwB4xfXkww6sEIDuw09JVYJAOtWLD1LAR4V7vRwi04Ab/xik2/U0hMWdZ7nJDGGJf2sgZ/vw4WV2g4GuhQZPcxQlN6A4ZMadFB6l+cItf1i/L9Yhp55lud+3/0AAAAQgAFuSSCyPXbkbiqvrbwIe4Hxe6DcGmKTRT+E38KDVkUJ9UHej+g+shmmrpnJYfdrQ5Sa1QL/pyd/t2ct/0Ug7MQKp9muiHkES2zackyKundQmxNf62MoZrylMECOidJwDgdIVNJhXeji4GvucncjKNRS5ndW6v1n7UZ0qurV/b/yL/5n//2gFgFRlNNNJyz2HhR5jsXqPG6D4xbKt4gL3xJc0xTgmbqnYhc6ksPj+OyWBOpoBU2+ALaiz1/6C9bo4iTtQ8UGiwSTDVTqX9KYgpqKAP/6cARd1wAIgg062JnqEtBDRTtqGOJtCIClYUe0skEFFKyolZT6BCct2kgsiroT5A+J4xMyguzBsnEoW24zCB7wqF7uDU7qiC//IXzeze6/AXaij9PWo/kY1afDsUQyHzPrP/dV/r9YAAcqNy3btLPwNLM9YwiqmHcVk646MeKnzlGz2UqFfn/G9O8zNnV+oV2kD9bkGD9QIqUw4J6eQpJUiOmYk0sZujOn1hgAS3LtJGVKgyLOcOIlaB9TMc25Dxhz0y1M2NYhxR3cQxpygBfUJL1+h/N6n0jU+JS6FWWg9zvWEaN7q9LJnFvvT7sgEBIKTclaYg2AATO9YNmj0d4H1O3QIbOfMC3/HhnwE8gCepvI/p6n9Segkv9AmQsLPFKFv931EYfvJK1TSRVlRjSmIKaimZccm4D/+nIEtPoAAAIdK1azDzrQQgO7bA2HE4gIdYWjDKJxDxpr6PWdWACADfmcDN+5cyKBdegpc7I5OdOz1hCXpa9l0/xr1BDmLj7oX4+qIa4C7qjCT8z3foQ8eZ+pDzl1HW57DeyrX9GW0btxIBBEIhWW2FOtAud5qg5mGYyDweWITa5QtWYEwMTUf8VBduvynPVBGhFRKXiwiwR1Ksxb4ZrfW6UNKMFGNwxVRZ9UhcDmhUeckue0gTg8njEGY0JCg6QYa2vxreAj6IG/blGBUJB4UaQf5Spu6oJGlvQWxMLezM7q2xmvE2N0YeP/2AABAAW1bbl2tOWRNxYfNVmBvQFAwhoaH2xArLPyYM8DW3gEP3Fz9fhE1UUsjtQ13Wn09G+3obfK0jX1p9WrKZPZ9/9aYgpqKZlxybgAAP/6cARMZwAAAf4i1zmYOiBCiuvdFOJriOFDcaQcUTEbKGvo84ngAIAGnLazELBNsCypq2aJH2JXzuCtBdkkzXW4LQ/aTaylBavQRvKr0Y9bT03HjlWV0vvrD2W3S4pbrxT53+jXoSCYLqLbqacpZGhYW5Vh2dqAvUkbFZb1b32hQMNyAXUO/OMQtlIRWo//r4I32/6/t6/N9fRv+jV0tX1yv7onGvXT+gAkhGIolJJOaSyQjWmBQ8RbxglkTo5Un4gfuJL8od4mHfHPhh/vuU3VRvHL5vV/J6obqidlXr6/Xbb0duC+r+OftHT9LCn6wAAwADKt3lcHV4xcFtp1CbQVXKFo8ppEGSEId4CG6FvEA+3BC/I/K5ecf0/+/p9fsr6o16n8lPbqvr9vR2/fX4+18++cV+tMQU3/+nIEMRQAAAIhHVlQzzokQmrLDTzlhgiIg3FUhQAxGBds6p5wBAAAgBJKkkZEcC3qDXliA0ase5jEEPYdDfjzdBR2ExPuFhw7nv5TLZPIb6sprSoSw0CefYs81b3kHqSQpbZsrOIXlcvIAAAAUAANu3/up4kUn0By11oG72vPqeN4tIahycSjeg38TB6e/n9Qoi6n9X83r9Pk/Xq22/n/9fl/+9/9PijJr8aisBSOSSyUlInbLhLlwVCgqO5MJ1nkYbT5hAf42LUMGF+cf7eYWZEmETHlP8liPRhx8JFlaF0ZNEOk5nZ6nV6Mmdhsv5+oQAioVHJL6VtvvWC1JYYmURcz3ki+OA/fhUm6uKyRA+xQJz+Pizy32LUVX1p7Mf7P0P8uzpDdn5Q368j9nqdL6MTNk1+fqTEFNP/6cAQxYQAAAiE24U4goABBxdw6xBQACMCDdLzxAAENhW7XniAAQAAEAMMMMMMMlcbg7yI6kv7SIqY0zP2PRvo5TvT8qo6a/5hZGIazp/xpgFGEGiWj//jDT0gXFf5qGAUYz/9YFKDFBgoAAgYYQIBAIAwIBB++DvJ6it1tIiphYs3jjkRv5T/8qjHTX/MLIxDf/xpgFGEGiVX6nvgX/zUMAoRZ/+sHQIMUGCgA+AghRgMSqjMUa6qpK+pb2kjUFmORjFczv2n/tusz17LWyCpFqj3aFBzxTCbVPi20wRa2Ikt+bFHjXsD7O+NIyLyvqZfWAfm6hrgxp2lztdp1LG9rbktIODTgqlNa6KCrwEf64ikW39oMDnigihNqnxbFzBFuWS39TwG9gfZ3rGkWEXlZ3UFb5VMQU0D/+nIEm9gACAIBNlyrCRBQRCbMjQwia4ihM3EnsEPBFhrtmYYUMAMuW2QGFB0UIVHEI5Lsm5wQXoAVYy2EbdFen1rWWn8iqjKqZen9avZrfK6Gct4OwOz219f1tYoXOkhZPsF+f/WEjI3JFJEkS4AgypdDMggdukZFueZvkVyQqlRQQuVX/kUoIiqlS9P61ezW+VyGct4WwOqPTrX1/W1ihdyFfYL8+mS65USDaq9mAXmFrXnK2gt99Hau6xk6T/3ucSGZ+gt3mkXVsfly+9C1vR6PXf0Paj66kenwI3/pL/f/LqX0d+JTryQ12S/dYgAjSrNJwCQpil5QtOQwt79kk498gdZEkoZ7PUDu9wm/VHGA1n7NzrWvR6O+/0W1H+pH/i34l1GUsrOhM7vlevat2S+9yaExBTUUAP/6cAR2gwAAAiReZe0MQAxBxrsxrJQAiCWFdBmDgAkUsK5HMFAAELklksr1sszjCBsuXgkZOKeAbzVKyLozPUw3tt+lvNei+j3fddCjVy+rb+DL/63qm6ijIdJfzV27S//v/5b9q0jnn3ll/MuEbpbRrNI6stnFm08npIOmqW3+ncPEGHFgZiOPFmW4dAnElVEVqPKuhV5Fv73e9/Padtv37+Nb/z31e479P/qK3SFbdgOU7USrSuelM7esYXr/jwwKyAXV2Qw+OmI9aOm62P7o/X//////////qff///+YxlCdjCH////7GGGDdIBSSUkaak7Kwyz/W7EG3Y9jM8s3r9EqFOqArSGibMh9x+IPs592fqb///t//7////U7v///+xGJILyEDn////5CEIBwJuTEFNRQAAD/+nIETMUAAAIoVmNuCEAAQyrMGsQIAAikNW7c8YABDZtvN5IgBAAAEAibhcMNqMBgMRgGjKqE63f7pS1xZSe+jqvulE+5mt0s//1RBCqv/+yBRJWEKT//9GOUGZEcgfR///wYiIccrmUgZwAAVAP4nAICwIBAIUKSIIxrLTWa/WZFSmfbTq/dPRHbo7fy//rQi1/7+yKXJJ//+jHKpqOwfR//1+DJEO5ZlIGf2JSA479ASQ4pLmwf80rJmy7cKVVkD8A1UhIqk4ggfLCOKuLiNThdy4rVdJtDb3cXG5LEvk/5YGTvbPYlO4sFIKhsFTvztYSAAAgBba0rAJYNSkQZlH/K9jW/MD7GLWQ56FJzDe1URfE1qt0WrdrbZbFLe1UXauUq7KAuvWe/g0GvltbuWwVWGvlcqmIKaP/6cATD5wAAAhc2WjnmEtA/JNvJHMIFiOyvfVSBADEXHy0OnnAAAIAI5LbxMcTnoE+5TGrhwRABPgiX9sV2cGjMf0p8vD9CD9hGS/opZVQqVm0Z/69jt3br/oL7Sd9Xp4iIIKd29X/2UAIAEz01wzHADw4qRKzm4BzWi2RLpdlmE6WqNFdG60cs7HR78G6iKJcYsfyNfWfYQbJ3pUNFxrUzfxW3vv4PaEJRhBMbbcLm+gtZSxM38tyAPVdX+i6X8uu+gPqacqs6vOxrMRttYV8yigDCSIspcWcFRMMayHjUHgg9IEWSY+pBRRXH43hlwJju2yLZ1g3A4FG5tc2atfixlQ4xlMBeyuNR10Kn2z2H9R9OY2qtSn2Zvbb7Gd+rGUV063T5ibud/5VZBdfEJtlDf/t29aYgpoD/+nIEbn0AAAIkEFzWPGAARGEro8YIAIhINYG8IQABFIVu65YgAAAAAAICTLLbLBUApD8ZCVNZGbR3GKyw41duVMgo1BqChXxqBRWUWbSegGkCTq4hlWrcsiLQLoe83/urA//neTP///m+gktNtuORAJoOlIh4FK3llHmkzeWo+AhEXPGU2FYCvSuNdBh72L1hpUAir3SqdqVuzh4kOctZcjpWLoHClugTn///jTfQyGUAJdppGSapBinV1JbR+27gglCTQeDMLrY5BUup6T4lqo70rCxo0JrVcPCG9w4Ez34x24mndscu5cg9zWHGsbuIAcU0IomQBD4UgZr7fetFvNroIWgCoG4IB0q1SJxzRHN/6bxORMhFi3My6mppICb9BC5CwqbkKFIUTMMaoyhaii1LPUFrUxBTQP/6cASmnQAAAhlIXejjETBCIyt2PGU0CKCVbUWU7wEKjm2c8wigIEgIAJjsKQEa0C5jqkGR+AIhsV52ryWRnqo/vQn2dzOVt/9syPXq3//M/Rf5VcpfLWpWqAsUs3UBr8lRDVNXrh3BpAwSvECXWmpXkfHkp0AcFYZoH66im6WdUGE3H+8YCpERK/8AwpbJfyz4rypMNflQCdxK9a+JZWGoijHnUxdwdqBo0oDAAQZd/9d1IAXCD06g3VLvHJXNwLRoW1GGxjPbsbnu5QI6Mr66N9p9C2GdhUdeRgatyyzyyyLdVsidHD6Dorc36CP/5YQAQ+3/+okFqLeTZbY6Q9ZyiBPKhHvB7OsE1SjVdPamnhwk0Ok0Jg6u+mnnwOjNofWSX2TsrI61EkFavV3fbIqCrjyYgpqKAAD/+nIE5G0AAAIlGVrVPQAERIXrR6ecAIhEHYlYkRBRD4lwKwYwAoEAACLbkkxqsMt4bjJNiGzRnCuWRXY8W48cfcVy47suqQwm7jbcIji1OiICxOB1GoMxlTp9NhlDoZO9KEqq0O2J5j//aAEkMuSRgco74OMnThjVGh7TLxvZvMarqKS5c9D4RlnPItjx76H0Ot5Y6mjmf39vdfvy8y5Ys8mdrVJRlep1rFdy/02VgCIEkGBCZ3S+74AREd5IBsQ7uKKEqXnWMIi65IYs6sfdTujzRQXCTqnPAoLlb30pcs+5LEvsOvFzEihiq99xgDiyAAEZFeozbdttvgBsLgGLcyhUjI1JlyvLTmXHIFh97YNhqHKMsRYtCHECQ8ShYFyZdrFGpO563yhhLwcDWAGutr////QmIKaigP/6cASQkgAAAiFd5x4A4ARDi7wjwRQACHStd1xhAAERjLA/hoAEAAoEFz2Gw////////Vns//9X2//744eTNG0aDg3167K7Z+YpEjPHBQLT2MDP/zzFcbnuhjIY2TJCKJQYEsXDg3jg3ByABgKBjsNhB2vM7K/Z6////f///6saxv/6u9qf/+ii5TQ4Q/67K7b5FYs5BAVOyAv/S5LnO8mRseLB0PBgHHoL0OBfQBJFSckZAD1ywIijiO7kbp8NYRknasrs6kUV2+rI6q3t22mN+xjPV9RMztJbpHg0eI/lgK7WDVfPayND2MSklLGsEmqIQYTJJdbt7CQYncagzoAh2Ac4KFq2so3mnUdqQ4jX9cfWMC79bkuQWes1ETycS+35HiI8It+4sBXaw7X2ayO9jMlU/GJiCmj/+nIEDucAAAIMJ15QYhvcPSMrqhhHcIkA+Wx0woARFpJt6pIwAoJITBMbJBKdAFcE9h1NKWfaqmBs73or7t7Yv/DKb1jRj5hR87RzwTCYaP70bXqCr+dd1ywVU98iRq/W7Ku8lbKgJAAVwlHZG7nCzEOXrDb87Uth/E5BFJkadC+n3w1zyiqUMlX00uDRrNFdqVBV/Ou65Yep+RI1frdlXfkpUBBKOW7Y61IIVf1Vx659uT2/HbSPPZ1d0ZKu15h9QAIQq1MQXqOO0xHfK/VOr6qXxH0Tq+1/bz9RffKbd0QuUfercvQHnQX0X0gAAsIpJbsnDFwobiuwkbUypwzMgnkokXh2GcORQEWoSzV2gOF0+yF7ReEdPgtd35VqyJRYXandTSeptI+iKB6X2fat1HpTEFNRQAAAAP/6cASvfgAAAhgh4FYYQARDI5uXxIwAiKl3ivghAAEUFjALEFAAAA46q6TV1222+4A7dPqzt9siHk58CFdjkNctEkHLu6XIuvcM/L/dRQcLGHWHJseQIkjgwFuwMOrQ/PLAT7LW8ukeBwABEk47JI7aAKIIgPEhIVGCFEfdnZ3mQMlMUYdS04BPczmfdbPHSfA/Li7yISsIAF7zciUODE+52Qf1p7Gu1rLGkoYAAgALRYLRaLRoqAFgO6Z1N0/Zk/////ciuc4U8MZfziCEdCMYCQhjfz77oxbIhHUn/O97Cz+h6Hsv/+Rsjf6KpIuqmLBAUSUUUaQWQAg6ALwwxMO3FvCmk7MZ0/s//2503JzlPMiszrnIRnRmQWIA1JNA+kg1wgHnPPpQD+xQfG/zkh4qgusTNZ0piCD/+nIEkv4AAMImGN1HYEAARCFbkewIAAgA124HpEOBABstgYSIWACMBYm+joDis1oqs472t28/5vKtbzNsrrpRnxm2RlLjPKpS7W4mIxZ9uIRVyr4uXegWW5ggoFcgz73VvcQR+7DqV+V3I8mmGAAaq9YTjGH+o68v7+v7llQHGtqLhtRhbFxKHUE0upWMEwjFntbiEVcq+Ll3oFhdzBBeK5Bn3ure4gj92HUr8ruQTgFcSyMLxwmX3MjfdYmzl/R2dL2VhqjNn1bdK9H9WYU1y6MjzdviVVjNTW/fcKheqWN4p32nGIloaf1NINlnVrsJlLUjcyX4J1w9ZVsxGhtB2f2LGSXi/dAFqpo/qzCmuXRkebt8SVWM1Nb99wt3w6+pjqayirp4qZ8VFBtYcySYgpqKZlxybgAAAP/6cAT9ZgAAAhs2XEsMEGBCCaxcJGIPiHkBkaGEp/EUDOxFoqFgABAMRu/JAD4BSfK3RORoMt7uf7LmI7gp2eyxUGzVFatkb//LUrbUd+rWqT3RHypT8V+LA1eTd9tbHqDnZWGiOMensQCkVZnL/2tIcC9WU8T1ypiUcl3SfTuYKXprxxv/8tStVqObYpVy/MiPlT/Ff/oY29Xa/+y61R30FNyKlhojWMensQEypC5VLrJHQQlTFJNxCvrFxEgN+pi7S+KqMEVo9Ac2yrUjrMl6GWn8xpf60Q0rsNF01anS3nZxUsouq6rlv/p/PPrLD+OMAOVXK16URCPP7DlZe9dhGMI+Fug0GCiMuOIQKFg6Nrpv7eAgCOyM92G27LLXERd3UrJxfoy9zPV7jyYfrTz8f93MJiCmooD/+nAEhjkACAIJNds7CThgQuMsXRglI4i412psMKGBDQzshYMhYgIAGW22oPkWBVILLkQlMckTqPXOK3FO59n0Yen0P/Rmhr87XtbMPW/3fqfPLm0a3U7XypLqqRz1v2tRO/Wr3/f1BJBx1tJSNJMmGSaqpQgjK69BB6tbo1jVtr+PTXTdV3qtekf+2FW8LKbWpRiYHveaEwecqyEzyhV5Gx5tqT7XHHRRigVJZbRANfZ8QVw7lcsjaBahTn40g0EHugmOIekTbEhr76WGgAGSvqnoyIu71T7p6Mve6JRP6jtepFCCXxeteS09fW+77aR/BGU35ihizvt3hyluMl5cWI2/xGNgbhmbgSiGoOwy15HxV4VNw24ZPEBW1YG2L0SdP0O6vkqg6zYdd2qPbXSRX+iVTEFNRQAA//pyBLVmAAACBCveaSESiEOpq/0cI9mIzLFtRJRvwRGa7miQipIQABFFpvb/fpDDJfvTg7vu0VhWP1WpaSyIzPO/tGXfJbpvu9kT9/hlJJkRV9Z0gtYqPx8z/veAqxKdrVY66JXeoMgCFkkqNpNoODATFzyt5e4yONfG7aq3RyrlKNqf2aNk7xKeC3MWXuL3OASZgLgN+cldcp7/eX/ngq5fYQUxqKLK6w0AAAaCt2/4gELhCKSYZRTigS6c3rwx2iDXQ7ZnCZx3tpRBg+nKjePZ9m9+vpSUQzmteRvUoP9NqHPP13ZEmpVDkbtvMfFpUQBIQC3JJSghiKXrHW2oiio3r7hWCF/qk7qPSdnS66zOXLZtB1bZFZ/l+sKDQrdmpe9tB0bfSR/c19Ux/PaDkZqBa9IqmIKaigD/+nAEte0ACIIRK9kZiRLQQaWLtxhiUogxA31BHFgxEYyu9GEWVCAnbbS2qLA7g1ZiH4ZYIqX1RA2Z9CbPSOLfjl5djS6zaHwTqivtvb37X9+m3RASHNZvPREmmmaaLWadXVY9/+bd9gFQSpZLbpK9qU4YJd0NMbBd1HPo6eM+/7Gp/7/1d/Q+97EHNDgmGmm9ZDb62L/XDaBAKwMER0ccNLEZA085VrtINicJRttxbMVkd48xqtwHug50ZqSzl0FZnRQ09ei0pHvR2XR+dOjqrla9O3Nc2Y3ll5qvVKAlystW9ZaRb+0xFm7qgJGE/YimbWz3MSVw9dvbX+FKdkDByrvknGfL5IaK3INB1aMVLMrebWHxZxF3TeQVUsc78v5RuMsB08piC8g9yWn2X7jSYgpqKZlxybgA//pyBMr2AACCFx9ZGSYskEOIa5ogolwINJNq5IirkQ6cbejCicIAyW7ZQYibAmhorh0oqx+NLseg960+NRH5WH4OKJq+L6uqgTfnIvGACh6jMTblKvJWPtu0c8h7EbpEsSX3mvu7turUABCYJv+9sC2WOUCmWRSWoSPwvuMcYlH3Q7Pv3xn+pfT5erGlK7b4VqZv/37MZ+YyMarWWvlCiQEeOrK6/1Pq9HO4UQEQFJuSTwiIEL6i7A5VYUMM6h2ncOx7WLGBI7oDAOcegAj421E929rWHVvrYw/4QcAGChKrJC8fst3nnMbV/4s/7AlBKcstho3EaoQXOfi3Nzl+0wQNucCGX0lRy8fmxWfmT3/7N/3RJjs/5XSmbHREsCCYwphenbrzpM8ISXxjKFDu5TNyYgpqKZlxybj/+nAEzQMAAAIaPl7QJhIsRCcr2hglN4fs+WdGIEfRCR8szPMI+hJ92CSUUlopzDIX7e2iZy+FdLA6aIjzhe9DP9l9f/bq3U1HKGLdlXIb0/6P7QlwgmHGXlH2LLNWKMGHat7hrVhnOfpEEiIJNRyV73ywEpxWJFWEvVq1oxsupeao16PlK/X19Wft7m2Eka5+z1slpEa0YuNEwkB4s6U4SZfFB4TVT+w7ZtbWk2AAEBARbkjDsI1FMiQ4mG3OI1sE1OW5mwct/Eqi9OVPitXz7c4Sunr9vb21MV1/dfdtP36K/Ewmap5FXqd9n7AAS3JK1mSChexxtOWMOYtREy/wPHfEF/OB89QGxjagXNkESenp/7e3UitYt/zP6N09H9XyBanje0igyK73/oTXV+lMQU1FMy45NwAA//pyBMilAAiCIENYmeg7sERDG0I8wj4ISPtq5hjl0Q6VrVz0CRgAtzf+ErW5NPxQSYWJWyaJbUj8xqQis0gFRhCKJXJyIjoMZVZUJnl+cfXR+j+W9vWiTv+y9U9ur+cz481V+VdRV9n/6AL6aSC6XWUJHeai3DvhfS0P+Iz/ALPXLsDwyjhtQH3jtfX+Kow2o1YHyIzqcXQHlNKSjo7kwxOLUNf6iftnC6lAnX1lyglqSSN3uWlwwMhFhrqL+CUGwLz44HNlYa+eiNlD81TFDG15MdflKaP1Le/UpupF1zm0R72+f2MbU3yunJbv+3d+tABkibcC9F0zMg04rupHI11lPAfdGO3UcK9DDPp2aMKt1/b/Vl2c26VGX2fI8qNDVfiMY/EVJXaSWMuoPHgKynPYJNYmIKaigAD/+nAEGZwACIHgKlmZLCh0RAJrRzzHNoi1bW70Y4ARIx9sjp5wAgCm3JBmFRYORzxxti2kf77aUM0q/oER98fiCMV6P5RgWOm5Bj3q3vqNEzc3jcTZKr5zyLlP6nf8zX/VmQAgApSSLiXUiFXE5QsqAXti66sBhejikmmpe9ELPL0HzSqmfrD9W3+F1REDRwsyeZBV9LWO2lWLLPt5JdJUZyJa6VGLsEVJdtOUTBgGeYtznSOjGRwM2jQv76zWe6b0Q5ttv2/2Ebqjc0v79W6J0+7f6E9RSIh/IWo7vn9zF6H+d1NfnO2lNW48cAG25IxMz6hjK8co63COls4XtuOK4AxBnHyIvVZUkjmlCJZ5hr7GVSe29TGyyTOlhGtq1qP5/t3O/9uvoemVKZmBn27XL/s9EsmIKaig//pyBFlqAAACGmNevgxABESMa7fECACIMJF0PDGAARSJLueMMAACAdoySyWwBgVwVIgoK03Iz38zWVja7aJqXvsdrs/Z+fRlW2u97BDc/b1u79G9badL0z1////nf/////8h1OQhAM8EAAAUi2JHBAEBKizXOD5ARk+L6uLVlYGwJ2PUsyMnSbYpWyo6UL/avr/b7GtfW7v7J//V5M53////n//////sdXIQgt5ABYNAdFV2d6od0zrqiIm4AAACF13SIXeuiF5UDO/7u7om/wIIA4PwfA4fBBdTqRGfWD5+JwffIIqP/sb//5RFb/rkAEAAAml+btCB23b3b5+71ERI4AACETcO5wMLg4CBMuH9YPg4cPqBAuH4Pjz4IfiN8H3y4fyCJQP9DpAnmOz/lAxF3/LpiCmooAD/+nAEfYEAAEIZK+BJIxLwQaMsBiQjRAjUg3injEnBFw1uwPMMuIAkAARaqwuG0bahdqW3k+usmrczFm21lsy41ikpN1G0N0W75lxO3ZDLc0YRIHpQoM7GLqToIoe2ntEKo1Px7+wy/sfAABCqqJGK0bYxbTU4cNYmoYps7Ns8v/7WCekKgkp8VS8s0S9wVSeGPMtfED4sq1go96RjzK9+trmIa9PT6kG/T6QQAHTnaPi8eJLtqzVeRfeY4VqFCoKNqJO3xelWV3rASfkTEjA0dARK3qeTl3PXmZ07KMGKo1v66msAZFqr4wwImvSrc22tMnE5JdHgILTJd4RzGe9SjpKKsSXg6hr9NDMyNdadOhQR1RKMJBIBEnt0Cx4PrS568vteKERinIdXuSNapsBsq7jBG/3bdKYA//pyBF3LAACB/RldgeYYsEADK7A9IxQJQH95IJhAwRYQLtiQiWDEJfGaQxtCNxdLblIIejM7DZGpIk4ShpadMhISASmqB4s8ST7Q7AD8KGR756qOcpFtyNkxG1vbw6qkm+tlnf9eLGySXBxYlRJoYmoyJZXpWXQxB0iRjhVmOnmox1SmqB4s8SLa03CT8KGXvQzW9ykWucrZMOG1v8Oqyb62WdVnWGA8qC1XCpFb9Ab1jtUCJYK019zx0i77ELXZjIVFb93B2qFEzxEVWqNJlkvqMpLnRANCIiU2NJo6Hnh6oCBp9ECueqP1WsisXUxZAEVryGTPjZKOxZ7AjawYjYKNC9ESis07WZJSL3y3B1sYQeqOa0igXeeTkHpC8MRZ7KBe58mZUyxAdI3OIhpM4xvWrbaKJiCmooD/+nAEUMoADPIJINuBJhsgQqV7cDzDXgi4ZW4jMGMBDBAtAMMVoOtRsDZ9cQCSbXGbkwa9slfpJNWXQ5hKRAi2liB7tvEZ8yhrR4dFknGhotLrMqfcJssxkcfc9RfWiiR9myinbdt0+E1mSq50mqC0hOfRN2itvnfsx+Nnhf+zk1/bdotzw9X4a58yYUi9j0bvS2LzKjRRs3U6WPY57jak40NdNOx1nT/bpX+ZkEK76GhB/VZdL8uLItYRoFPH5yLb+XS9mGGSlYmYPRylKCh+Jg6oy5KkhM400Iwo11wujovXbV0ww0hN3iQcrc1wvqrapdAYlE0FB7hMrDyz8hOU5F/xwKt99VFF30MdpcpDMGNj1Ut34iqkY5ZgQNYKMCQZk2pDTHDyL2uxKSjN//4aZq6kxBTUUAAA//pyBFbOAADCGBVd4MMRqEQh+2MFiAoImGV3QJiiYRUW7Mj0iSiAAAlFk9AMfBK1H2LKytw3dccEkru+6r46yQwOLp3B9zEFF0E8Fio16/sJPdJCj36cWHCV0ShpdWLPUg0qMfY1u7MsRCbclgw9FrpVOgyZRUJ/+wb/OppJIvli3CQy8oHY5J8ZQ59GJzKhyWZc6QWgcdO7XJqTxdQ7TtRvTFCO+edgfiWE38jgCESckjdpYiAxyYBRanHP3yOyElcsiIfQNWzYDBpeVcoWxwIE5k0VHvD1b1yPYCq9MZ35JnLHZxFQuduDUCjQ0vm2dlgE//ikjOPyaCaYRUJNfK2IMZ7FN/iBrOUiq+cErzgitrZEnm3dFoa9Z8uz297o5ZxIwg6TRAiUnoBXvSLI1fVcz7W6G/QmIID/+nAE17wAAAIjNltpJRPAQQSbUz0iLAhoh141hYABGozt6pJQAIAAAACEZJbak+IlCaEYC5LzO1nkK2sjTB8IxPoRFR+YNVerj+99WfsVQaVuerLdUS5/SvyG1xloeyHEkpX9kVSz2f/yoATdluKZPQUFFAHCP9jhj6K99NS9LlXYejpZLs6P0LZ/07L+1RNdyiNlVmCSzKIeWYW1t0ZUhNnUSc2qyHWId/NA5Un4eVOASNPW00smLUleM9Idx+BoEecJ5w84NAoc4xbKx7M1CY6eF/7vQrpZtS+ePq71DJUNXOxhWpbSN+r9lv2uTgAIoJct28/AFBt5YjBjeomx7LSsKFxQIO6xJ3moPZ0de9R1x0V7lTh24FqVLMdF8MpkjfeptCEpTe0JantimrsTt1Ja0kXTEFNA//pyBHuZAAACHWFcljBAAkFADErACACIWKtsvPKAERgJbiuMUAIAIIMMPAMMB/ALCWxBUcDflvx4sZEQOwsiqrgTyPvSCG2p27f/+uv//2ef///oxzoRT///+zs1B6Gb////9yEUYZA8iAArI1e27bbbrrtsWwsSCJUDMBBDXray9RmNhaBGIO49bQqXYITbitDcdPUOpkgFOM5sqZir0K2NY3ax8v3/3tdeAEcPJGURM1dZSJG1sQce09XcFehAmKjHKrMY5WZttOo//7fXm+nbGnCJPdvLKSnQK/2kDylC+1UsRirLFsS+L6tYoACgRQbkcj7zCNHCEtxDFfjnxz5RMCw9TdjChACiFiVnspHMW6YAdgUSKgMSj0nS45wLpjjQZSA0BrDmz2ZT3nEbGGP63UJiCmooAAD/+nAErUkAAAIMGV1RYjH4QuJbOj0oRgjY+31DjFpxGAzuGIKNlsAQDFdrhUqs6MtVgtkQHqZ8CbgxZ2heZQZGdgL+ldtFmTaiCdqRcmBrQKeiWuv4lI0KhR/4i/X53UeqCu6tR4NeoAIAwQ7Lba2lQ4CPbWhA6Y8Ks9MGH+jW8MBou61FpdybLg+pFqYGIUtmxZRpoOlahKihuFbBeGRzn1VhzX0eV3ez/dAEjpRjabqNKhgsVUlPj77PjvLil+rnWU99CFvUt8ZD1XZD1SH3t7T5zJSuv6tZdvavzKyoEBhjKXw5ucw21lfxQDLl++kPgHEmW+saAapJGVcHrofjiY8LH4rm7taOdojOE3gGyAFvJLnWhwVpsKU3tKOJLPJ9F8YFZnfJUHTww2i4wZGNp9aDDmLQhCYA//pwBKGyAAACHxlabTygAEIDKzekmAAInYV4+MEAARYNLk8YMAJAAAAQAlu7f+ao7BbWVdn+zQ3KXWO1t9qBEHO4kHQ1SuIuF3Yz926lisEXhmrI296JNzl+KLeekLnLyFWM36LVp//d1QCAMdk2pmIhBeJcPiAnSVUY5dbfxd89Zof47rlMuUE977+0vHBaCrXqGQNZsek8sLBdS6LF691dTKre+rbSqunKUgAAlv7f3fAUDyfYLYCPzp4+/Tr1p1COChqOz60et+d0e3QvdC69aX+2hv3/tsn/X9KNzurn///9r87z/////yOjCHE4YADTbbkkkAhQoA9wNxPQFvFKKv1xx1XjgjBVJoFICc7snmueK/xt9ILqsepJ5hnHtqTppWHUEA4465qWAFTiC1WIRS9WitMQQP/6cgSarAAAAf8RXe8cwABD5yxt4pQBiBhlcaeYpcEbnywNhIkwgAABshKtbSV4jgsJlHGEWrSvzkkZ7GDplt52KTLYoDnoi7UlWuSpzXIWlPovMvdHXeiWcN0k9+Mf0y11LduKV4FNSXNOba3AYA9SaOY9ysJ2RwGZCB0EfqgxtD83pGgj+empHPqDLUcV1QYirnWhz01fTTpslLEGZKXHV7K+eLRqN22ygAAFrAv6Rt6t3AdNgIxWpdPOdH/Fz+4g632I3iD8vQ6iQZSVOL28XOgqMxKv89aIudDgdr8SjeV1fUs7yNv86SACllw+jwfUpg8m5pX8yAKfIdIJx3RnNpADkp5pU80LdIPC2xKPKBwiz+Te6dVzlMQtF7s9HVvpq3/b3fq3Doq3RbbVWFt9SYgpqKZlxybg//pwBDGbAAACDBlYGW9IkD6Ja1MkIrqJMPuBtFKAMRufLZ6QcAIENS0VrqACBzoYZxoCuwYKjGcqOu+hS/SwiPQU8cdqiQLGc6iUv+lajJQWKOlK20aaiMTJ6/Xiz2hSU3+S///2/pADbktvcSDJ610WC2Rzzl/zkP9LOyuq47kklnkvBr5Degg98L8fvxL/M3+j82+32Ee6dfVP1sNnFXR/ezbT6WQAw6oUpJJfJIjWeVG0DTsMFzajRzuQQ9DjsY3lo/apOj/dXl8jtovUv+u936E0lZ7jWVVcFS2tEkjl0jxZkAz7lZyJypsmh7KwQhFyS3TDlAUslmwXenVeK+o+WOoYxuiOrFEa9rhutqELpP8w5Md807p1Pb/pf6W0Q131z1QtLmRrXLOVZ9I8z1+rF62NuUmIIP/6cgTjogAAAfwYXb4YYARE4eyKwQyQiKyFf/whAAELDLC/jCAEAGGaERkEgAACgTSbBAyg7JxjbfpuFSnTzJUYn317zJBbCD1HAgGVDKoABBPMaS5Dpa20a9LP//nEf/9Inky5QAadeusl2zZ3T9gVGi7LYqWd5OcOfHainGVpQPVOV5xxFow+wLjAwkmJoDrWXIdJPueByGHxVZRRNZUXYNfzn//pJyaSkCBGQGSs60SSigiCMoNUV78Ty9zXPLTsRXOM8ruZwruDZKmtqguOQd56kGj7RHvgZ9281QVFLu/WYQ46iN5VIpqMP81XrgFRDdYR5WiACWQ7Ip+q3fYafHoTqr0dWXlnc7PK/CvJM7T45B1GexQ/I74GfdvNUFRRLr79ZhDjqI3lUimoAv81XrTEFNRQAAAA//pwBDTvAAACEkxe4EEVcDsBa6gEwwIJISNvJJxEgSWbLWDECVDEAmEqXQtSbBhauRUV2z8N3JZZI8h89hPJ7/huxTU2aX+TM5Bz8lNeczvHlmeULTz60ahmsfChU7XpPLO1uanvemYwABNASTmB1zeymv38CKUfONUTt4iv945biZIbfUPaIZJinErmi6Z9Txfa75JZZB9YVdX2L1uanvDqZiAACyQBGt0VFw7JlUDpc4IbC6xQxkhoV6Bz69eQeZ9W9ZRKUTbb7XoqKh7P5W7cNb6+0+zIdtMjMrIckLK1PJesJEcRHUE/ZabQAAIAM+5kUUGDedGEqbeyeDvmAm5pHggY+r+1D0fVvWUSaCNtt3lvRUVD2fyt2rDXYlYgvcI3KhgaoHCs7EQqdtxKKGqgZjX/WmIKaP/6cgSqyAAIghJAW0gsKGBDSAs1MQVoCDjXZyYkS0EJGyzI8RVgAAiMY07vlAGy0hRrMP5htuIosWbhE6rSFdBfX5cWVL/9DVblZJrf1bVfy/5f/oYzrW4i6pFR1y7hOd7VlfnpjU/jQAl/P4WCebNUGhMX6Le9xxvgcP9Qzcv6BjmHF9TetQpUdP/NVuqabfqOoVWtlFWn+Ct/1I5n+IuqRja7hOd7Vlf/+NAMH6/36iOB9YUqONh98t8DV/ld90Cj57y+Py6D3QbsZC//6PlV5mTqSnUpW3/bR+ghn6xdh609sqetbk09Cu/7esD7/zvSHjrcpJk/GMaMLyAQ+D5QAfgwQJDpEH8npIBf0+/VSvduyt1aoquj/tR2xg70jMTyyqdQhstRfu/TJ8POboTEFNRTMuOTcAAA//pwBOUjAAACGUDaOYcqsEMIC7wUIuOIuNd5oZROoREmrIj0iTAAoAjckmzcxMxs04p0IOTHxsL8VPsFgRNWLZyM9F7Fj3/Tz52ran09HkOtUq2qrfWgF39dFL+w2z1wqfxX6le/xQK0MEAEoQXpGKSU2UpRSbOz4zxggczgKOVqEfQ/ZZg3+ynMdFE9Az5MuQmo3MlSlW6cEXdOEft/B/kiruL/kLVG9vGKxuAJOKsam2nvpYNBqhwHhC4p4QbMJBl6X1CtoTsRSD/36tWp5Z1e6oRNHKZUr+1PvFa9ZRzkhm00yhZJaFEW/H7ROi7iltQFf/5rIsdKVhuJ7SAjbFaKG8/Sz9caPZvSMlc2leCAOxJSbafsps339tLkUE8i1fZE1bQdr9n/v3uv/0ov0wfVSjWf9SYggP/6cgQ9OwAAAiEVWujLOihDprwdHCLHiGyxZ0Swo4EXGyxo85UwgAAIDAQZSTsKk8ZJpSbibit8swXtYaoWTKEyr6NlBH2Heypzgw62rNj9qJ99Q8+nDtCkv7VbJWxAV1PXFS1YKsYzNPXCUhHZGnG2nEah7KynPMY0mmwPy1zAsHJhQ82xgr6E+xTel/JVh3PxLK5sqRQabXW9RTbgXXd/8+1U6S12z9iwld00swAQAAyRySDuCoiG9dH5kIK0pjuIp0k3zIOV4wNATuXQU9UtRt1Xs6tf9mahLTmWMM8ttalSznZPYxWrsQpf79vMfVXAAAAAbUcklaExL80JnBmvRIua4SmtUT3khMDOIA8+dC7PGAnrgl2HzK/npd1KzpZqN+m/n8rO9MUtatlOr/v478pzDbMqmIKa//pwBMZZAAAB/xVa0WkRUENmyyc9Ij4IFSF1IoRcsRMc7ygRiGaADNAFbrtmbzwWXouLrHafuIoZ5MH6ljJoKFNh+g+EmryeweGs1XU0RiEDkGtQRaW/pTfGe00sgpCxoz29aPqeAYANy22m53IUiCvxgSiv1/hFKP5K/2haFq/WFxvbsbd8f8gHX3tx/Klf5eprmOjpVFut13oHoi7vCiFbMK1UEaP9BqAVJxemtnkBSRrQZ6y+EjaCYqNEtwvVR+g73j2t7eNq3e3WDwSKrznOGRGHO/XlWk2pW/7yuM6UKuZ97t7es0PUiF0wSaaTl0JeuKwVauDvgXQOJ8dX1fUR5pw1vI3Vujt18nkWS17q2pxqOpVip/iZR8tZoxTOrODX7nLcCZSWS5TnuMySYgpqKZlxybgAAP/6cgRMhgAIwhoyWLnpEmA+4qsjBScMCJxlXuelaMEcoGxM9YkwACAG3bbrcx/LBSStolKgxkIaIvv5e/bJDtJ0UkKH4msK4jSRSDX927V/RHZsbp967ecQ54LQpmKhO/jfih7RGfxteoANS3YxYCQmHoAmMqBHurlO/Ba+PgRJrmC4UDOr6kc6AdZqhzdT5Co6bY5CZdzyS35w7XThP7bZVqzujr76dJAAErba42J4DcJquT2CwUwE4xXEN+7PGvOCyJjJVDdVlY3R6ZG+LrWOrVdTtl8HanL+J3rceH4dptIqUAn+ovUdt+337gkbLtoNLrD5abFWOhqG+KdRLznilfoB8M5nc4VRp2mHJ6XR1k29/27tu3T1r/V6JLSyou+87Jk8EyVspW01ILadb1jupG/IJiCmooAA//pwBMLLAAQiEidYmesqYEJGu3cJAiaIMTNk56Cq0RGgbuhhFT4gt27aurFEwKOpMj9sBtI3nUl/AfK9Yr+8Q3o1rLNhYroroMX6E/X+3QcWsggMzopJtFwhCHkbA2ka7qsd0i36v2JgsCm5bao0dxyCjHDbMukuJbQV4OZpbYNur69aJ5H7e3jedUvY73bgxQkqnLoOFWFngCEWXho5xQohHB375vf719iYACim5NTaKoSxHrg7h5rk6pRG9VbwB64VH5HSgSHcqdVR6m6N1J7fTv6dP/R6bd3Xsi7Wu/o/21+ptdo0xtxieirQCWm26wbEG0prcly8fF9SeSrQTiNn67GVejJyehXt3g7tkfo1q/F0RWrmc9reOnuLk4kzErtVIUECrtmszkHpWdGEPQmIKaimZccm4P/6cgRajgAAAig0XFElEuxDCAs3PQJYiFk3YmekS0ESnG6oMRo+wAQQIsJJxA64Hxc5wlEIRJ7Y7z+eNxMwphATqq1FMvo/UudDent6l3X1+Ou4lKcxVNHKzca69bcYSF0tbQVnGza2tVLLgAAU3JJAmy/cHJJOjHmLTU1dO3hC/u9zOIdWnDjaP+Oy+j+vv1M+o32+1Wv3LyarbRrbMOaTqF9b2tdco6/6Tjl9KgAFvv6burgjZjLonool4w8BDPqJn8e3+LG5WoXsbhWZMEbXUm3v///DE6plV03ZsGOXne6LbvzFbS+r//9e/gvkP64AEFALTjVQ+GPBIFH1meXt6N5XtUG2j/s/3FeZu7c/gvVdU9a6isqIFvttjZ6SBg8DYcUL1oV6DtezyHYl48AjzzbUKSmIKaig//pwBML5AAACFT7ZOC8oZEMoK5oEwgyIbPt1RJRJ8Qqsb3QRiC4CQIJUkifSIP+inJCoMi1QoNNTPL4cbEgNfCnEp1GpiR9b2f9PX19ft7f9fZJ5DKbTqj0uewgPVYo6mv73EN7e+hdSAEshJu3b2xejzyKtHd2zNnENU4b0deozwRv318nt6+rdG6jf1q+p36I6H+X6rmFqqsILTt6CaB2latKZmFSAFL2KoQACYlNJt37y73HVRywSP98PtlCxdcIRupX1B9XVHHm8jcE3I/t0+vT6ebqY6oRBHVvZ1uGCSrrd/nvTHP73ji1jZjakABCgCk245rUMpgyGqcFpR8Dbr6Qb1K2CF/q9PP6ffo3r6+3p6LuCeiII5WXo2oJOvr//zE0P8/uq+7RbqSwGHymhMQU1FAAAAP/6cgSaWgAEwg4c1ZMPOmBAJ9sjPKJYiHyBaUSwo2EaDKwMxIj4ARvMZ6aGBr9QtIDpjDcVggA6vmVm5ju0d4J6ufo2Iwi4+8EydRLVa7E2icFG850j/j94j9NTKtm6zZXt3V7qHXegAspyTOLvDZVhZqZowhNJ7h1KgUfwFB+JSD1VtAD3qAQfQSRVneZE+/Q3p/09H6Gbr6/bghL3OlXLO2hij+yV04ABKSySrwSGWFtQmKpwDJ12+uw9kHpUJBq6HNqLdAFJdcx7c9j6D7RUoXDYoH3LiokDtS2EmhFzszpQ09FsQdCN//+gAJOSC/IQ9AzGA4gWBoRAU5+0ZPu/ERusTDw9P1RsafPTTVQKTXhSGg+cfWiG7XRYaU1SCA+EbhqkyguQaw411C9CGz/WilMQU1FAAAAA//pwBM5gAA/yEQxUmGZIEkCCSoIZIxpAAAGkAAAAIAAANIAAAAQFt22iiTkwkUjEoBhonHUU2UnoZsrTZlN/2JJZjv5ObKSf1hLlfUpr+sJd7mlmt/nGlEu/3v7XOOY7llrc1jv/+d2A3+SRgBDJIJiGFJwaVYRJ5rDWH3UmBjBnEzFXff/Jf3mO73lNKtsJd5RZRVvNKkmkuWt7va5z2O5Za3NY5z+c6mIKaimZccm4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
diff --git a/tests/tests/media/res/raw/utf16_1.mp3 b/tests/tests/media/res/raw/utf16_1.mp3
new file mode 100644
index 0000000..829d311
--- /dev/null
+++ b/tests/tests/media/res/raw/utf16_1.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/video_1280x720_mp4_hevc_1150kbps_30fps_aac_stereo_128kbps_48000hz.mp4 b/tests/tests/media/res/raw/video_1280x720_mp4_hevc_1150kbps_30fps_aac_stereo_128kbps_48000hz.mp4
new file mode 100644
index 0000000..9bf2124
--- /dev/null
+++ b/tests/tests/media/res/raw/video_1280x720_mp4_hevc_1150kbps_30fps_aac_stereo_128kbps_48000hz.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/video_1280x720_mp4_mpeg4_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4 b/tests/tests/media/res/raw/video_1280x720_mp4_mpeg4_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4
new file mode 100644
index 0000000..d8aa8a4
--- /dev/null
+++ b/tests/tests/media/res/raw/video_1280x720_mp4_mpeg4_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/video_352x288_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz.3gp b/tests/tests/media/res/raw/video_352x288_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz.3gp
new file mode 100644
index 0000000..5ad946d
--- /dev/null
+++ b/tests/tests/media/res/raw/video_352x288_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz.3gp
Binary files differ
diff --git a/tests/tests/media/res/raw/video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz_dash.mp4 b/tests/tests/media/res/raw/video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz_dash.mp4
new file mode 100644
index 0000000..19c4e06
--- /dev/null
+++ b/tests/tests/media/res/raw/video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz_dash.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz_fragmented.mp4 b/tests/tests/media/res/raw/video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz_fragmented.mp4
new file mode 100644
index 0000000..c321586
--- /dev/null
+++ b/tests/tests/media/res/raw/video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz_fragmented.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/video_480x360_mp4_hevc_325kbps_30fps_aac_stereo_128kbps_48000hz.mp4 b/tests/tests/media/res/raw/video_480x360_mp4_hevc_325kbps_30fps_aac_stereo_128kbps_48000hz.mp4
new file mode 100644
index 0000000..e3e3ef01
--- /dev/null
+++ b/tests/tests/media/res/raw/video_480x360_mp4_hevc_325kbps_30fps_aac_stereo_128kbps_48000hz.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/video_480x360_mp4_hevc_650kbps_30fps_aac_stereo_128kbps_48000hz.mp4 b/tests/tests/media/res/raw/video_480x360_mp4_hevc_650kbps_30fps_aac_stereo_128kbps_48000hz.mp4
new file mode 100644
index 0000000..4eb6161
--- /dev/null
+++ b/tests/tests/media/res/raw/video_480x360_mp4_hevc_650kbps_30fps_aac_stereo_128kbps_48000hz.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/video_640x360_mp4_hevc_450kbps_30fps_aac_stereo_128kbps_48000hz.mp4 b/tests/tests/media/res/raw/video_640x360_mp4_hevc_450kbps_30fps_aac_stereo_128kbps_48000hz.mp4
new file mode 100644
index 0000000..1e1dc748
--- /dev/null
+++ b/tests/tests/media/res/raw/video_640x360_mp4_hevc_450kbps_30fps_aac_stereo_128kbps_48000hz.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/video_h264_main_b_frames.mp4 b/tests/tests/media/res/raw/video_h264_main_b_frames.mp4
new file mode 100644
index 0000000..448ad3c
--- /dev/null
+++ b/tests/tests/media/res/raw/video_h264_main_b_frames.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/video_h264_main_b_frames_frag.mp4 b/tests/tests/media/res/raw/video_h264_main_b_frames_frag.mp4
new file mode 100644
index 0000000..b54a4d6c
--- /dev/null
+++ b/tests/tests/media/res/raw/video_h264_main_b_frames_frag.mp4
Binary files differ
diff --git a/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java b/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
index 13852ae..5c9f1b1 100644
--- a/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
+++ b/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
@@ -55,12 +55,22 @@
                 R.raw.video_1280x720_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz);
     }
 
+    public Iterable<Codec> HEVC(CodecFactory factory) {
+        return factory.createCodecList(
+                mContext,
+                "video/hevc",
+                "OMX.google.hevc.decoder",
+                R.raw.video_640x360_mp4_hevc_450kbps_30fps_aac_stereo_128kbps_48000hz,
+                R.raw.video_1280x720_mp4_hevc_1150kbps_30fps_aac_stereo_128kbps_48000hz);
+    }
+
     public Iterable<Codec> H263(CodecFactory factory) {
         return factory.createCodecList(
                 mContext,
                 "video/3gpp",
                 "OMX.google.h263.decoder",
-                R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz);
+                R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz,
+                R.raw.video_352x288_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz);
     }
 
     public Iterable<Codec> Mpeg4(CodecFactory factory) {
@@ -68,6 +78,8 @@
                 mContext,
                 "video/mp4v-es",
                 "OMX.google.mpeg4.decoder",
+
+                R.raw.video_1280x720_mp4_mpeg4_1000kbps_25fps_aac_stereo_128kbps_44100hz,
                 R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz);
     }
 
@@ -94,21 +106,22 @@
     CodecFactory HW  = new HWCodecFactory();
 
     public Iterable<Codec> H264()  { return H264(ALL);  }
+    public Iterable<Codec> HEVC()  { return HEVC(ALL);  }
     public Iterable<Codec> VP8()   { return VP8(ALL);   }
     public Iterable<Codec> VP9()   { return VP9(ALL);   }
     public Iterable<Codec> Mpeg4() { return Mpeg4(ALL); }
     public Iterable<Codec> H263()  { return H263(ALL);  }
 
     public Iterable<Codec> AllCodecs() {
-        return chain(H264(ALL), VP8(ALL), VP9(ALL), Mpeg4(ALL), H263(ALL));
+        return chain(H264(ALL), HEVC(ALL), VP8(ALL), VP9(ALL), Mpeg4(ALL), H263(ALL));
     }
 
     public Iterable<Codec> SWCodecs() {
-        return chain(H264(SW), VP8(SW), VP9(SW), Mpeg4(SW), H263(SW));
+        return chain(H264(SW), HEVC(SW), VP8(SW), VP9(SW), Mpeg4(SW), H263(SW));
     }
 
     public Iterable<Codec> HWCodecs() {
-        return chain(H264(HW), VP8(HW), VP9(HW), Mpeg4(HW), H263(HW));
+        return chain(H264(HW), HEVC(HW), VP8(HW), VP9(HW), Mpeg4(HW), H263(HW));
     }
 
     /* tests for adaptive codecs */
@@ -162,18 +175,21 @@
     public void sanityHW()  { sanity = true; try { runHW();  } finally { sanity = false; } }
 
     public void runH264()  { ex(H264(),  allTests); }
+    public void runHEVC()  { ex(HEVC(),  allTests); }
     public void runVP8()   { ex(VP8(),   allTests); }
     public void runVP9()   { ex(VP9(),   allTests); }
     public void runMpeg4() { ex(Mpeg4(), allTests); }
     public void runH263()  { ex(H263(),  allTests); }
 
     public void onlyH264HW()  { ex(H264(HW),  allTests); }
+    public void onlyHEVCHW()  { ex(HEVC(HW),  allTests); }
     public void onlyVP8HW()   { ex(VP8(HW),   allTests); }
     public void onlyVP9HW()   { ex(VP9(HW),   allTests); }
     public void onlyMpeg4HW() { ex(Mpeg4(HW), allTests); }
     public void onlyH263HW()  { ex(H263(HW),  allTests); }
 
     public void onlyH264SW()  { ex(H264(SW),  allTests); }
+    public void onlyHEVCSW()  { ex(HEVC(SW),  allTests); }
     public void onlyVP8SW()   { ex(VP8(SW),   allTests); }
     public void onlyVP9SW()   { ex(VP9(SW),   allTests); }
     public void onlyMpeg4SW() { ex(Mpeg4(SW), allTests); }
@@ -184,66 +200,80 @@
 
     /* inidividual tests */
     public void testH264_adaptiveEarlyEos()  { ex(H264(),  adaptiveEarlyEos); }
+    public void testHEVC_adaptiveEarlyEos()  { ex(HEVC(),  adaptiveEarlyEos); }
     public void testVP8_adaptiveEarlyEos()   { ex(VP8(),   adaptiveEarlyEos); }
     public void testVP9_adaptiveEarlyEos()   { ex(VP9(),   adaptiveEarlyEos); }
     public void testMpeg4_adaptiveEarlyEos() { ex(Mpeg4(), adaptiveEarlyEos); }
     public void testH263_adaptiveEarlyEos()  { ex(H263(),  adaptiveEarlyEos); }
 
     public void testH264_adaptiveEosFlushSeek()  { ex(H264(),  adaptiveEosFlushSeek); }
+    public void testHEVC_adaptiveEosFlushSeek()  { ex(HEVC(),  adaptiveEosFlushSeek); }
     public void testVP8_adaptiveEosFlushSeek()   { ex(VP8(),   adaptiveEosFlushSeek); }
     public void testVP9_adaptiveEosFlushSeek()   { ex(VP9(),   adaptiveEosFlushSeek); }
     public void testMpeg4_adaptiveEosFlushSeek() { ex(Mpeg4(), adaptiveEosFlushSeek); }
     public void testH263_adaptiveEosFlushSeek()  { ex(H263(),  adaptiveEosFlushSeek); }
 
     public void testH264_adaptiveSkipAhead()  { ex(H264(),  adaptiveSkipAhead); }
+    public void testHEVC_adaptiveSkipAhead()  { ex(HEVC(),  adaptiveSkipAhead); }
     public void testVP8_adaptiveSkipAhead()   { ex(VP8(),   adaptiveSkipAhead); }
     public void testVP9_adaptiveSkipAhead()   { ex(VP9(),   adaptiveSkipAhead); }
     public void testMpeg4_adaptiveSkipAhead() { ex(Mpeg4(), adaptiveSkipAhead); }
     public void testH263_adaptiveSkipAhead()  { ex(H263(),  adaptiveSkipAhead); }
 
     public void testH264_adaptiveSkipBack()  { ex(H264(),  adaptiveSkipBack); }
+    public void testHEVC_adaptiveSkipBack()  { ex(HEVC(),  adaptiveSkipBack); }
     public void testVP8_adaptiveSkipBack()   { ex(VP8(),   adaptiveSkipBack); }
     public void testVP9_adaptiveSkipBack()   { ex(VP9(),   adaptiveSkipBack); }
     public void testMpeg4_adaptiveSkipBack() { ex(Mpeg4(), adaptiveSkipBack); }
     public void testH263_adaptiveSkipBack()  { ex(H263(),  adaptiveSkipBack); }
 
     public void testH264_adaptiveReconfigDrc()  { ex(H264(),  adaptiveReconfigDrc); }
+    public void testHEVC_adaptiveReconfigDrc()  { ex(HEVC(),  adaptiveReconfigDrc); }
     public void testVP8_adaptiveReconfigDrc()   { ex(VP8(),   adaptiveReconfigDrc); }
     public void testVP9_adaptiveReconfigDrc()   { ex(VP9(),   adaptiveReconfigDrc); }
     public void testMpeg4_adaptiveReconfigDrc() { ex(Mpeg4(), adaptiveReconfigDrc); }
     public void testH263_adaptiveReconfigDrc()  { ex(H263(),  adaptiveReconfigDrc); }
 
     public void testH264_adaptiveSmallReconfigDrc()  { ex(H264(),  adaptiveSmallReconfigDrc); }
+    public void testHEVC_adaptiveSmallReconfigDrc()  { ex(HEVC(),  adaptiveSmallReconfigDrc); }
     public void testVP8_adaptiveSmallReconfigDrc()   { ex(VP8(),   adaptiveSmallReconfigDrc); }
     public void testVP9_adaptiveSmallReconfigDrc()   { ex(VP9(),   adaptiveSmallReconfigDrc); }
     public void testMpeg4_adaptiveSmallReconfigDrc() { ex(Mpeg4(), adaptiveSmallReconfigDrc); }
     public void testH263_adaptiveSmallReconfigDrc()  { ex(H263(),  adaptiveSmallReconfigDrc); }
 
     public void testH264_adaptiveDrc() { ex(H264(), adaptiveDrc); }
+    public void testHEVC_adaptiveDrc() { ex(HEVC(), adaptiveDrc); }
     public void testVP8_adaptiveDrc()  { ex(VP8(),  adaptiveDrc); }
     public void testVP9_adaptiveDrc()  { ex(VP9(),  adaptiveDrc); }
+    public void testMpeg4_adaptiveDrc() { ex(Mpeg4(), adaptiveDrc); }
+    public void testH263_adaptiveDrc() { ex(H263(), adaptiveDrc); }
 
     public void testH264_adaptiveDrcEarlyEos() { ex(H264(), new AdaptiveDrcEarlyEosTest()); }
+    public void testHEVC_adaptiveDrcEarlyEos() { ex(HEVC(), new AdaptiveDrcEarlyEosTest()); }
     public void testVP8_adaptiveDrcEarlyEos()  { ex(VP8(),  new AdaptiveDrcEarlyEosTest()); }
     public void testVP9_adaptiveDrcEarlyEos()  { ex(VP9(),  new AdaptiveDrcEarlyEosTest()); }
 
     public void testH264_adaptiveSmallDrc()  { ex(H264(),  adaptiveSmallDrc); }
+    public void testHEVC_adaptiveSmallDrc()  { ex(HEVC(),  adaptiveSmallDrc); }
     public void testVP8_adaptiveSmallDrc()   { ex(VP8(),   adaptiveSmallDrc); }
     public void testVP9_adaptiveSmallDrc()   { ex(VP9(),   adaptiveSmallDrc); }
 
     public void testH264_earlyEos()  { ex(H264(),  earlyEos); }
+    public void testHEVC_earlyEos()  { ex(HEVC(),  earlyEos); }
     public void testVP8_earlyEos()   { ex(VP8(),   earlyEos); }
     public void testVP9_earlyEos()   { ex(VP9(),   earlyEos); }
     public void testMpeg4_earlyEos() { ex(Mpeg4(), earlyEos); }
     public void testH263_earlyEos()  { ex(H263(),  earlyEos); }
 
     public void testH264_eosFlushSeek()  { ex(H264(),  eosFlushSeek); }
+    public void testHEVC_eosFlushSeek()  { ex(HEVC(),  eosFlushSeek); }
     public void testVP8_eosFlushSeek()   { ex(VP8(),   eosFlushSeek); }
     public void testVP9_eosFlushSeek()   { ex(VP9(),   eosFlushSeek); }
     public void testMpeg4_eosFlushSeek() { ex(Mpeg4(), eosFlushSeek); }
     public void testH263_eosFlushSeek()  { ex(H263(),  eosFlushSeek); }
 
     public void testH264_flushConfigureDrc()  { ex(H264(),  flushConfigureDrc); }
+    public void testHEVC_flushConfigureDrc()  { ex(HEVC(),  flushConfigureDrc); }
     public void testVP8_flushConfigureDrc()   { ex(VP8(),   flushConfigureDrc); }
     public void testVP9_flushConfigureDrc()   { ex(VP9(),   flushConfigureDrc); }
     public void testMpeg4_flushConfigureDrc() { ex(Mpeg4(), flushConfigureDrc); }
@@ -1275,13 +1305,11 @@
 
             /* test if the explicitly named codec is present on the system */
             if (explicitCodecName != null) {
-                try {
-                    MediaCodec codec = MediaCodec.createByCodecName(explicitCodecName);
-                    if (codec != null) {
-                        codec.release();
-                        add(new Codec(explicitCodecName, null, mediaList));
-                    }
-                } catch (Exception e) {}
+                MediaCodec codec = MediaCodec.createByCodecName(explicitCodecName);
+                if (codec != null) {
+                    codec.release();
+                    add(new Codec(explicitCodecName, null, mediaList));
+                }
             }
         } catch (Throwable t) {
             Log.wtf("Constructor failed", t);
diff --git a/tests/tests/media/src/android/media/cts/AudioEffectTest.java b/tests/tests/media/src/android/media/cts/AudioEffectTest.java
index 27189a1..1c96abd 100644
--- a/tests/tests/media/src/android/media/cts/AudioEffectTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioEffectTest.java
@@ -35,10 +35,10 @@
 import android.util.Log;
 import java.util.UUID;
 
-public class AudioEffectTest extends AndroidTestCase {
+public class AudioEffectTest extends PostProcTestBase {
 
     private String TAG = "AudioEffectTest";
-    private final static int MIN_NUMBER_EFFECTS = 5;
+    private final static int MIN_NUMBER_EFFECTS = 1;
     // allow +/- 5% tolerance between set and get delays
     private final static float DELAY_TOLERANCE = 1.05f;
     // allow +/- 5% tolerance between set and get ratios
@@ -50,17 +50,9 @@
 
     private AudioEffect mEffect = null;
     private AudioEffect mEffect2 = null;
-    private int mSession = -1;
-    private boolean mHasControl = false;
-    private boolean mIsEnabled = false;
-    private int mChangedParameter = -1;
-    private boolean mInitialized = false;
-    private Looper mLooper = null;
     private MediaPlayer mMediaPlayer = null;
     private int mError = 0;
 
-    private final Object mLock = new Object();
-
     private ListenerThread mEffectListenerLooper = null;
 
     //-----------------------------------------------------------------
@@ -71,9 +63,11 @@
     // 0 - static methods
     //----------------------------------
 
-    //Test case 0.0: test queryEffects() and platfrom at least provides Equalizer, Bass Boost,
-    // Virtualizer, Environmental reverb and Preset reverb effects
+    //Test case 0.0: test queryEffects() and platfrom at least provides an Equalizer
     public void test0_0QueryEffects() throws Exception {
+        if (!hasAudioOutput()) {
+            return;
+        }
 
         AudioEffect.Descriptor[] desc = AudioEffect.queryEffects();
 
@@ -81,29 +75,14 @@
                 (desc.length >= MIN_NUMBER_EFFECTS));
 
         boolean hasEQ = false;
-        boolean hasBassBoost = false;
-        boolean hasVirtualizer = false;
-        boolean hasEnvReverb = false;
-        boolean hasPresetReverb = false;
 
         for (int i = 0; i < desc.length; i++) {
             if (desc[i].type.equals(AudioEffect.EFFECT_TYPE_EQUALIZER)) {
                 hasEQ = true;
-            } else if (desc[i].type.equals(AudioEffect.EFFECT_TYPE_BASS_BOOST)) {
-                hasBassBoost = true;
-            } else if (desc[i].type.equals(AudioEffect.EFFECT_TYPE_VIRTUALIZER)) {
-                hasVirtualizer = true;
-            } else if (desc[i].type.equals(AudioEffect.EFFECT_TYPE_ENV_REVERB)) {
-                hasEnvReverb = true;
-            } else if (desc[i].type.equals(AudioEffect.EFFECT_TYPE_PRESET_REVERB)) {
-                hasPresetReverb = true;
+                break;
             }
         }
         assertTrue("test0_0QueryEffects: equalizer not found", hasEQ);
-        assertTrue("test0_0QueryEffects: bass boost not found", hasBassBoost);
-        assertTrue("test0_0QueryEffects: virtualizer not found", hasVirtualizer);
-        assertTrue("test0_0QueryEffects: environmental reverb not found", hasEnvReverb);
-        assertTrue("test0_0QueryEffects: preset reverb not found", hasPresetReverb);
     }
 
     //-----------------------------------------------------------------
@@ -129,105 +108,26 @@
         return ar;
     }
 
-    //Test case 1.0: test constructor from effect type and get effect ID
-    public void test1_0ConstructorFromType() throws Exception {
-        AudioEffect.Descriptor[] desc = AudioEffect.queryEffects();
-        assertTrue("no effects found", (desc.length != 0));
-        for (int i = 0; i < desc.length; i++) {
-            if (!desc[i].type.equals(AudioEffect.EFFECT_TYPE_NULL)) {
-                try {
-                    int sessionId;
-                    AudioRecord ar = null;
-                    if (AudioEffect.EFFECT_PRE_PROCESSING.equals(desc[i].connectMode)) {
-                        ar = getAudioRecord();
-                        sessionId = ar.getAudioSessionId();
-                    } else {
-                        sessionId = 0;
-                    }
-                    AudioEffect effect = new AudioEffect(desc[i].type,
-                            AudioEffect.EFFECT_TYPE_NULL,
-                            0,
-                            sessionId);
+//    // Test case 1.0: test constructor from effect type and get effect ID
+//    public void test1_0ConstructorFromType() ...
+//    Note: This test was removed because it used hidden api's.
 
-                    assertNotNull("could not create AudioEffect", effect);
-                    try {
-                        assertTrue("invalid effect ID", (effect.getId() != 0));
-                    } catch (IllegalStateException e) {
-                        fail("AudioEffect not initialized");
-                    } finally {
-                        effect.release();
-                        if (ar != null) {
-                            ar.release();
-                        }
-                    }
-                } catch (IllegalArgumentException e) {
-                    fail("Effect not found: "+desc[i].name);
-                } catch (UnsupportedOperationException e) {
-                    fail("Effect library not loaded");
-                }
-            }
-        }
-    }
 
-    //Test case 1.1: test constructor from effect uuid
-    public void test1_1ConstructorFromUuid() throws Exception {
-        AudioEffect.Descriptor[] desc = AudioEffect.queryEffects();
-        assertTrue("no effects found", (desc.length != 0));
-        for (int i = 0; i < desc.length; i++) {
-            try {
-                int sessionId;
-                AudioRecord ar = null;
-                if (AudioEffect.EFFECT_PRE_PROCESSING.equals(desc[i].connectMode)) {
-                    ar =  getAudioRecord();
-                    sessionId = ar.getAudioSessionId();
-                } else {
-                    sessionId = 0;
-                }
-                AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_NULL,
-                        desc[i].uuid,
-                        0,
-                        sessionId);
-                assertNotNull("could not create AudioEffect", effect);
-                try {
-                    assertTrue("invalid effect ID", (effect.getId() != 0));
-                } catch (IllegalStateException e) {
-                    fail("AudioEffect not initialized");
-                } finally {
-                    effect.release();
-                    if (ar != null) {
-                        ar.release();
-                    }
-                }
-            } catch (IllegalArgumentException e) {
-                fail("Effect not found: "+desc[i].name);
-            } catch (UnsupportedOperationException e) {
-                fail("Effect library not loaded");
-            }
-        }
-    }
+//    //Test case 1.1: test constructor from effect uuid
+//    public void test1_1ConstructorFromUuid() ...
+//    Note: This test was removed because:
+//     1. will fail in devices that offload effects
+//     2. it used hidden api's.
 
-    //Test case 1.2: test constructor failure from unknown type
-    public void test1_2ConstructorUnknownType() throws Exception {
-
-        try {
-            AudioEffect effect = new AudioEffect(UUID.randomUUID(),
-                    AudioEffect.EFFECT_TYPE_NULL,
-                    0,
-                    0);
-            fail("could create random AudioEffect");
-            if (effect != null) {
-                effect.release();
-            }
-        } catch (IllegalArgumentException e) {
-
-        } catch (UnsupportedOperationException e) {
-            fail("Effect library not loaded");
-        }
-    }
+//    //Test case 1.2: test constructor failure from unknown type
+//    public void test1_2ConstructorUnknownType() ...
+//    Note: This test was removed because it used hidden api's.
 
     //Test case 1.3: test getEnabled() failure when called on released effect
     public void test1_3GetEnabledAfterRelease() throws Exception {
-
+        if (!hasAudioOutput()) {
+            return;
+        }
         try {
             AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER,
                     AudioEffect.EFFECT_TYPE_NULL,
@@ -250,6 +150,9 @@
 
     //Test case 1.4: test contructor on mediaPlayer audio session
     public void test1_4InsertOnMediaPlayer() throws Exception {
+        if (!hasAudioOutput()) {
+            return;
+        }
         MediaPlayer mp = new MediaPlayer();
         assertNotNull("could not create mediaplayer", mp);
         AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(R.raw.testmp3);
@@ -269,6 +172,9 @@
 
     //Test case 1.5: test auxiliary effect attachement on MediaPlayer
     public void test1_5AuxiliaryOnMediaPlayer() throws Exception {
+        if (!isPresetReverbAvailable()) {
+            return;
+        }
         synchronized(mLock) {
             mInitialized = false;
             createMediaPlayerLooper();
@@ -301,6 +207,9 @@
 
     //Test case 1.6: test auxiliary effect attachement failure before setDatasource
     public void test1_6AuxiliaryOnMediaPlayerFailure() throws Exception {
+        if (!isPresetReverbAvailable()) {
+            return;
+        }
         synchronized(mLock) {
             mInitialized = false;
             createMediaPlayerLooper();
@@ -332,6 +241,9 @@
 
     //Test case 1.7: test auxiliary effect attachement on AudioTrack
     public void test1_7AuxiliaryOnAudioTrack() throws Exception {
+        if (!isPresetReverbAvailable()) {
+            return;
+        }
         AudioTrack track = null;
         getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
         try {
@@ -373,7 +285,9 @@
 
     //Test case 2.0: test setEnabled() and getEnabled() in valid state
     public void test2_0SetEnabledGetEnabled() throws Exception {
-
+        if (!hasAudioOutput()) {
+            return;
+        }
         try {
             AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER,
                     AudioEffect.EFFECT_TYPE_NULL,
@@ -401,7 +315,9 @@
 
     //Test case 2.1: test setEnabled() throws exception after release
     public void test2_1SetEnabledAfterRelease() throws Exception {
-
+        if (!hasAudioOutput()) {
+            return;
+        }
         try {
             AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER,
                     AudioEffect.EFFECT_TYPE_NULL,
@@ -428,6 +344,9 @@
 
     //Test case 3.0: test setParameter(byte[], byte[]) / getParameter(byte[], byte[])
     public void test3_0SetParameterByteArrayByteArray() throws Exception {
+        if (!isPresetReverbAvailable()) {
+            return;
+        }
         getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
         try {
             byte[] param = mEffect.intToByteArray(PresetReverb.PARAM_PRESET);
@@ -459,6 +378,9 @@
 
     //Test case 3.1: test setParameter(int, int) / getParameter(int, int[])
     public void test3_1SetParameterIntInt() throws Exception {
+        if (!isEnvReverbAvailable()) {
+            return;
+        }
         getEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, 0);
         try {
             int param = EnvironmentalReverb.PARAM_DECAY_TIME;
@@ -490,6 +412,9 @@
 
     //Test case 3.2: test setParameter(int, short) / getParameter(int, short[])
     public void test3_2SetParameterIntShort() throws Exception {
+        if (!isPresetReverbAvailable()) {
+            return;
+        }
         getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
         try {
             int param = PresetReverb.PARAM_PRESET;
@@ -519,6 +444,9 @@
 
     //Test case 3.3: test setParameter(int, byte[]) / getParameter(int, byte[])
     public void test3_3SetParameterIntByteArray() throws Exception {
+        if (!isEnvReverbAvailable()) {
+            return;
+        }
         getEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, 0);
         try {
             int param = EnvironmentalReverb.PARAM_DECAY_TIME;
@@ -552,6 +480,9 @@
 
     //Test case 3.4: test setParameter(int[], int[]) / getParameter(int[], int[])
     public void test3_4SetParameterIntArrayIntArray() throws Exception {
+        if (!isEnvReverbAvailable()) {
+            return;
+        }
         getEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, 0);
         try {
             int[] param = new int[1];
@@ -586,6 +517,9 @@
     //Test case 3.5: test setParameter(int[], short[]) / getParameter(int[], short[])
 
     public void test3_5SetParameterIntArrayShortArray() throws Exception {
+        if (!isPresetReverbAvailable()) {
+            return;
+        }
         getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
         try {
             int[] param = new int[1];
@@ -617,6 +551,9 @@
 
     //Test case 3.6: test setParameter(int[], byte[]) / getParameter(int[], byte[])
     public void test3_6SetParameterIntArrayByteArray() throws Exception {
+        if (!isEnvReverbAvailable()) {
+            return;
+        }
         getEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, 0);
         try {
             int[] param = new int[1];
@@ -651,6 +588,9 @@
 
     //Test case 3.7: test setParameter() throws exception after release()
     public void test3_7SetParameterAfterRelease() throws Exception {
+        if (!isPresetReverbAvailable()) {
+            return;
+        }
         AudioEffect effect = null;
         try {
             effect = new AudioEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB,
@@ -676,6 +616,9 @@
 
     //Test case 3.8: test getParameter() throws exception after release()
     public void test3_8GetParameterAfterRelease() throws Exception {
+        if (!isPresetReverbAvailable()) {
+            return;
+        }
         AudioEffect effect = null;
         try {
             effect = new AudioEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB,
@@ -706,6 +649,9 @@
 
     //Test case 4.0: test control passed to higher priority client
     public void test4_0setEnabledLowerPriority() throws Exception {
+        if (!hasAudioOutput()) {
+            return;
+        }
         AudioEffect effect1 = null;
         AudioEffect effect2 = null;
         try {
@@ -743,6 +689,9 @@
 
     //Test case 4.1: test control passed to higher priority client
     public void test4_1setParameterLowerPriority() throws Exception {
+        if (!isPresetReverbAvailable()) {
+            return;
+        }
         AudioEffect effect1 = null;
         AudioEffect effect2 = null;
         try {
@@ -792,7 +741,9 @@
 
     //Test case 4.2: test control status listener
     public void test4_2ControlStatusListener() throws Exception {
-
+        if (!isPresetReverbAvailable()) {
+            return;
+        }
         synchronized(mLock) {
             mHasControl = true;
             mInitialized = false;
@@ -815,7 +766,9 @@
 
     //Test case 4.3: test enable status listener
     public void test4_3EnableStatusListener() throws Exception {
-
+        if (!isPresetReverbAvailable()) {
+            return;
+        }
         synchronized(mLock) {
             mInitialized = false;
             createListenerLooper(false, true, false);
@@ -842,6 +795,9 @@
 
     //Test case 4.4: test parameter changed listener
     public void test4_4ParameterChangedListener() throws Exception {
+        if (!isPresetReverbAvailable()) {
+            return;
+        }
         synchronized(mLock) {
             mInitialized = false;
             createListenerLooper(false, false, true);
@@ -875,6 +831,9 @@
 
     //Test case 5.0: test command method
     public void test5_0Command() throws Exception {
+        if (!isPresetReverbAvailable()) {
+            return;
+        }
         getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
         try {
             byte[] cmd = new byte[0];
diff --git a/tests/tests/media/src/android/media/cts/AudioManagerStub.java b/tests/tests/media/src/android/media/cts/AudioManagerStub.java
index baae5fc..290b866 100644
--- a/tests/tests/media/src/android/media/cts/AudioManagerStub.java
+++ b/tests/tests/media/src/android/media/cts/AudioManagerStub.java
@@ -19,7 +19,7 @@
 import com.android.cts.media.R;
 
 import android.app.Activity;
-import android.app.cts.CTSResult;
+import android.cts.util.CTSResult;
 import android.content.Context;
 import android.content.Intent;
 import android.media.AudioManager;
diff --git a/tests/tests/media/src/android/media/cts/AudioManagerTest.java b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
index 4a74b47..e65fb0b 100644
--- a/tests/tests/media/src/android/media/cts/AudioManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
@@ -40,6 +40,7 @@
 
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.media.AudioManager;
 import android.media.MediaPlayer;
 import android.os.Vibrator;
@@ -63,7 +64,7 @@
         Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
         mHasVibrator = (vibrator != null) && vibrator.hasVibrator();
         mUseFixedVolume = mContext.getResources().getBoolean(
-                                            com.android.internal.R.bool.config_useFixedVolume);
+                Resources.getSystem().getIdentifier("config_useFixedVolume", "bool", "android"));
     }
 
     public void testMicrophoneMute() throws Exception {
@@ -109,6 +110,7 @@
 
     public void testMusicActive() throws Exception {
         MediaPlayer mp = MediaPlayer.create(mContext, MP3_TO_PLAY);
+        assertNotNull(mp);
         mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
         mp.start();
         Thread.sleep(TIME_TO_PLAY);
@@ -123,8 +125,6 @@
     public void testAccessMode() throws Exception {
         mAudioManager.setMode(MODE_RINGTONE);
         assertEquals(MODE_RINGTONE, mAudioManager.getMode());
-        mAudioManager.setMode(MODE_IN_CALL);
-        assertEquals(MODE_IN_CALL, mAudioManager.getMode());
         mAudioManager.setMode(MODE_IN_COMMUNICATION);
         assertEquals(MODE_IN_COMMUNICATION, mAudioManager.getMode());
         mAudioManager.setMode(MODE_NORMAL);
@@ -392,6 +392,7 @@
         mAudioManager.adjustVolume(ADJUST_RAISE, 0);
 
         MediaPlayer mp = MediaPlayer.create(mContext, MP3_TO_PLAY);
+        assertNotNull(mp);
         mp.setAudioStreamType(STREAM_MUSIC);
         mp.setLooping(true);
         mp.start();
diff --git a/tests/tests/media/src/android/media/cts/AudioPreProcessingTest.java b/tests/tests/media/src/android/media/cts/AudioPreProcessingTest.java
index e993695..de5b698 100644
--- a/tests/tests/media/src/android/media/cts/AudioPreProcessingTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioPreProcessingTest.java
@@ -18,6 +18,7 @@
 
 import com.android.cts.media.R;
 
+import android.content.pm.PackageManager;
 import android.media.AudioFormat;
 import android.media.AudioRecord;
 import android.media.audiofx.AcousticEchoCanceler;
@@ -47,6 +48,10 @@
 
     //Test case 1.1: test NS creation and release
     public void test1_1NsCreateAndRelease() throws Exception {
+        if (!hasMicrophone()) {
+            return;
+        }
+
         AudioRecord ar = getAudioRecord();
         assertNotNull("could not create AudioRecord", ar);
 
@@ -67,6 +72,10 @@
 
     //Test case 1.2: test setEnabled() and getEnabled()
     public void test1_2NsSetEnabledGetEnabled() throws Exception {
+        if (!hasMicrophone()) {
+            return;
+        }
+
         if (!NoiseSuppressor.isAvailable()) {
             return;
         }
@@ -100,6 +109,10 @@
 
     //Test case 2.1: test AEC creation and release
     public void test2_1AecCreateAndRelease() throws Exception {
+        if (!hasMicrophone()) {
+            return;
+        }
+
         AudioRecord ar = getAudioRecord();
         assertNotNull("could not create AudioRecord", ar);
 
@@ -120,6 +133,10 @@
 
     //Test case 2.2: test AEC setEnabled() and getEnabled()
     public void test2_2AecSetEnabledGetEnabled() throws Exception {
+        if (!hasMicrophone()) {
+            return;
+        }
+
         if (!AcousticEchoCanceler.isAvailable()) {
             return;
         }
@@ -153,6 +170,10 @@
 
     //Test case 3.1: test AGC creation and release
     public void test3_1AgcCreateAndRelease() throws Exception {
+        if (!hasMicrophone()) {
+            return;
+        }
+
         AudioRecord ar = getAudioRecord();
         assertNotNull("could not create AudioRecord", ar);
 
@@ -173,6 +194,10 @@
 
     //Test case 3.2: test AGC setEnabled() and getEnabled()
     public void test3_2AgcSetEnabledGetEnabled() throws Exception {
+        if (!hasMicrophone()) {
+            return;
+        }
+
         if (!AutomaticGainControl.isAvailable()) {
             return;
         }
@@ -199,6 +224,10 @@
     //-----------------------------------------------------------------
     // private methods
     //----------------------------------
+    private boolean hasMicrophone() {
+        return getContext().getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_MICROPHONE);
+    }
 
     private AudioRecord getAudioRecord() {
         AudioRecord ar = null;
diff --git a/tests/tests/media/src/android/media/cts/AudioTrackTest.java b/tests/tests/media/src/android/media/cts/AudioTrackTest.java
index 090cde8..d01ecec 100644
--- a/tests/tests/media/src/android/media/cts/AudioTrackTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioTrackTest.java
@@ -16,16 +16,22 @@
 
 package android.media.cts;
 
+import android.cts.util.CtsAndroidTestCase;
 import android.media.AudioFormat;
 import android.media.AudioManager;
 import android.media.AudioTimestamp;
 import android.media.AudioTrack;
-import android.test.AndroidTestCase;
 import android.util.Log;
+import com.android.cts.util.ReportLog;
+import com.android.cts.util.ResultType;
+import com.android.cts.util.ResultUnit;
 
+import java.nio.ByteOrder;
 import java.nio.ByteBuffer;
+import java.nio.ShortBuffer;
+import java.nio.FloatBuffer;
 
-public class AudioTrackTest extends AndroidTestCase {
+public class AudioTrackTest extends CtsAndroidTestCase {
     private String TAG = "AudioTrackTest";
     private final long WAIT_MSEC = 200;
     private final int OFFSET_DEFAULT = 0;
@@ -447,10 +453,9 @@
     // Playback properties
     // ----------------------------------
 
-    // Test case 1: setStereoVolume() with max volume returns SUCCESS
-    public void testSetStereoVolumeMax() throws Exception {
+    // Common code for the testSetStereoVolume* and testSetVolume* tests
+    private void testSetVolumeCommon(String testName, float vol, boolean isStereo) throws Exception {
         // constants for test
-        final String TEST_NAME = "testSetStereoVolumeMax";
         final int TEST_SR = 22050;
         final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
@@ -466,61 +471,35 @@
         track.write(data, OFFSET_DEFAULT, data.length);
         track.write(data, OFFSET_DEFAULT, data.length);
         track.play();
-        float maxVol = AudioTrack.getMaxVolume();
-        assertTrue(TEST_NAME, track.setStereoVolume(maxVol, maxVol) == AudioTrack.SUCCESS);
+        if (isStereo) {
+            // TODO to really test this, do a pan instead of using same value for left and right
+            assertTrue(testName, track.setStereoVolume(vol, vol) == AudioTrack.SUCCESS);
+        } else {
+            assertTrue(testName, track.setVolume(vol) == AudioTrack.SUCCESS);
+        }
         // -------- tear down --------------
         track.release();
     }
 
+    // Test case 1: setStereoVolume() with max volume returns SUCCESS
+    public void testSetStereoVolumeMax() throws Exception {
+        final String TEST_NAME = "testSetStereoVolumeMax";
+        float maxVol = AudioTrack.getMaxVolume();
+        testSetVolumeCommon(TEST_NAME, maxVol, true /*isStereo*/);
+    }
+
     // Test case 2: setStereoVolume() with min volume returns SUCCESS
     public void testSetStereoVolumeMin() throws Exception {
-        // constants for test
         final String TEST_NAME = "testSetStereoVolumeMin";
-        final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
-        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
-        final int TEST_MODE = AudioTrack.MODE_STREAM;
-        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
-
-        // -------- initialization --------------
-        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
-        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT,
-                2 * minBuffSize, TEST_MODE);
-        byte data[] = new byte[minBuffSize];
-        // -------- test --------------
-        track.write(data, OFFSET_DEFAULT, data.length);
-        track.write(data, OFFSET_DEFAULT, data.length);
-        track.play();
         float minVol = AudioTrack.getMinVolume();
-        assertTrue(TEST_NAME, track.setStereoVolume(minVol, minVol) == AudioTrack.SUCCESS);
-        // -------- tear down --------------
-        track.release();
+        testSetVolumeCommon(TEST_NAME, minVol, true /*isStereo*/);
     }
 
     // Test case 3: setStereoVolume() with mid volume returns SUCCESS
     public void testSetStereoVolumeMid() throws Exception {
-        // constants for test
         final String TEST_NAME = "testSetStereoVolumeMid";
-        final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
-        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
-        final int TEST_MODE = AudioTrack.MODE_STREAM;
-        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
-
-        // -------- initialization --------------
-        int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
-        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT,
-                2 * minBuffSize, TEST_MODE);
-        byte data[] = new byte[minBuffSize];
-        // -------- test --------------
-
-        track.write(data, OFFSET_DEFAULT, data.length);
-        track.write(data, OFFSET_DEFAULT, data.length);
-        track.play();
         float midVol = (AudioTrack.getMaxVolume() - AudioTrack.getMinVolume()) / 2;
-        assertTrue(TEST_NAME, track.setStereoVolume(midVol, midVol) == AudioTrack.SUCCESS);
-        // -------- tear down --------------
-        track.release();
+        testSetVolumeCommon(TEST_NAME, midVol, true /*isStereo*/);
     }
 
     // Test case 4: setPlaybackRate() with half the content rate returns SUCCESS
@@ -645,6 +624,27 @@
         track.release();
     }
 
+    // Test case 9: setVolume() with max volume returns SUCCESS
+    public void testSetVolumeMax() throws Exception {
+        final String TEST_NAME = "testSetVolumeMax";
+        float maxVol = AudioTrack.getMaxVolume();
+        testSetVolumeCommon(TEST_NAME, maxVol, false /*isStereo*/);
+    }
+
+    // Test case 10: setVolume() with min volume returns SUCCESS
+    public void testSetVolumeMin() throws Exception {
+        final String TEST_NAME = "testSetVolumeMin";
+        float minVol = AudioTrack.getMinVolume();
+        testSetVolumeCommon(TEST_NAME, minVol, false /*isStereo*/);
+    }
+
+    // Test case 11: setVolume() with mid volume returns SUCCESS
+    public void testSetVolumeMid() throws Exception {
+        final String TEST_NAME = "testSetVolumeMid";
+        float midVol = (AudioTrack.getMaxVolume() - AudioTrack.getMinVolume()) / 2;
+        testSetVolumeCommon(TEST_NAME, midVol, false /*isStereo*/);
+    }
+
     // -----------------------------------------------------------------
     // Playback progress
     // ----------------------------------
@@ -1219,11 +1219,12 @@
             AudioTrack.ERROR_BAD_VALUE);
     }
 
-    // Test case 2: getMinBufferSize() return ERROR_BAD_VALUE if SR > 48000
+    // Test case 2: getMinBufferSize() return ERROR_BAD_VALUE if sample rate too high
     public void testGetMinBufferSizeTooHighSR() throws Exception {
         // constant for test
         final String TEST_NAME = "testGetMinBufferSizeTooHighSR";
-        final int TEST_SR = 48001;
+        // FIXME need an API to retrieve AudioTrack.SAMPLE_RATE_HZ_MAX
+        final int TEST_SR = 96001;
         final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_8BIT;
 
@@ -1289,7 +1290,7 @@
 
         // -------- initialization --------------
         int bufferSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
-        byte data[] = createSoundDataInByteArray(bufferSize, TEST_SR);
+        byte data[] = createSoundDataInByteArray(bufferSize, TEST_SR, 1024);
         AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT,
                 bufferSize, TEST_MODE);
         // -------- test --------------
@@ -1307,10 +1308,10 @@
         track.release();
     }
 
-    public static byte[] createSoundDataInByteArray(int bufferSize, final int sampleRate) {
-        final int frequency = 1024;
+    public static byte[] createSoundDataInByteArray(int bufferSamples, final int sampleRate,
+            final double frequency) {
         final double rad = 2 * Math.PI * frequency / sampleRate;
-        byte[] vai = new byte[bufferSize];
+        byte[] vai = new byte[bufferSamples];
         for (int j = 0; j < vai.length; j++) {
             int unsigned =  (int)(Math.sin(j * rad) * Byte.MAX_VALUE) + Byte.MAX_VALUE & 0xFF;
             vai[j] = (byte) unsigned;
@@ -1318,121 +1319,353 @@
         return vai;
     }
 
-    public static short[] createSoundDataInShortArray(int bufferSize, final int sampleRate) {
-        final double frequency = 1024;
+    public static short[] createSoundDataInShortArray(int bufferSamples, final int sampleRate,
+            final double frequency) {
         final double rad = 2 * Math.PI * frequency / sampleRate;
-        short[] vai = new short[bufferSize];
+        short[] vai = new short[bufferSamples];
         for (int j = 0; j < vai.length; j++) {
-            vai[j] = (short) (Math.sin(j * rad) * Short.MAX_VALUE);
+            vai[j] = (short)(Math.sin(j * rad) * Short.MAX_VALUE);
         }
         return vai;
     }
 
+    public static float[] createSoundDataInFloatArray(int bufferSamples, final int sampleRate,
+            final double frequency) {
+        final double rad = 2 * Math.PI * frequency / sampleRate;
+        float[] vaf = new float[bufferSamples];
+        for (int j = 0; j < vaf.length; j++) {
+            vaf[j] = (float)(Math.sin(j * rad));
+        }
+        return vaf;
+    }
+
     public void testPlayStreamData() throws Exception {
         // constants for test
         final String TEST_NAME = "testPlayStreamData";
-        final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
-        final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
+        final int TEST_FORMAT_ARRAY[] = {  // should hear 40 increasing frequency tones, 3 times
+                AudioFormat.ENCODING_PCM_8BIT,
+                AudioFormat.ENCODING_PCM_16BIT,
+                AudioFormat.ENCODING_PCM_FLOAT,
+        };
+        final int TEST_SR_ARRAY[] = {
+                4000,
+                22050,
+                44100,
+                48000,
+                96000,
+        };
+        final int TEST_CONF_ARRAY[] = {
+                AudioFormat.CHANNEL_OUT_MONO,    // 1.0
+                AudioFormat.CHANNEL_OUT_STEREO,  // 2.0
+                AudioFormat.CHANNEL_OUT_STEREO | AudioFormat.CHANNEL_OUT_FRONT_CENTER, // 3.0
+                AudioFormat.CHANNEL_OUT_QUAD,    // 4.0
+                AudioFormat.CHANNEL_OUT_QUAD | AudioFormat.CHANNEL_OUT_FRONT_CENTER,   // 5.0
+                AudioFormat.CHANNEL_OUT_5POINT1, // 5.1
+                AudioFormat.CHANNEL_OUT_5POINT1 | AudioFormat.CHANNEL_OUT_BACK_CENTER, // 6.1
+                AudioFormat.CHANNEL_OUT_7POINT1_SURROUND, // 7.1
+        };
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
 
-        // -------- initialization --------------
-        int minBufferSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
-        int bufferSize = 3 * minBufferSize;
-        short data[] = createSoundDataInShortArray(bufferSize, TEST_SR);
-        AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT,
-                minBufferSize, TEST_MODE);
-        // -------- test --------------
-        assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
-        boolean hasPlayed = false;
-        int written = 0;
-        while (written < data.length) {
-            if (data.length - written <= minBufferSize) {
-                written += track.write(data, written, data.length - written);
-            } else {
-                written += track.write(data, written, minBufferSize);
-                if (!hasPlayed) {
-                    track.play();
-                    hasPlayed = true;
+        for (int TEST_FORMAT : TEST_FORMAT_ARRAY) {
+            double frequency = 400; // frequency changes for each test
+            for (int TEST_SR : TEST_SR_ARRAY) {
+                for (int TEST_CONF : TEST_CONF_ARRAY) {
+                    // -------- initialization --------------
+                    final int minBufferSize = AudioTrack.getMinBufferSize(TEST_SR,
+                            TEST_CONF, TEST_FORMAT); // in bytes
+                    final int bufferSamples = 12 * minBufferSize
+                            / AudioFormat.getBytesPerSample(TEST_FORMAT);
+                    final int channelCount = Integer.bitCount(TEST_CONF);
+                    final double testFrequency = frequency / channelCount;
+                    AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR,
+                            TEST_CONF, TEST_FORMAT, minBufferSize, TEST_MODE);
+                    assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
+                    boolean hasPlayed = false;
+                    int written = 0;
+
+                    // -------- test --------------
+                    switch (TEST_FORMAT) {
+                    case AudioFormat.ENCODING_PCM_8BIT: {
+                        byte data[] = createSoundDataInByteArray(
+                                bufferSamples, TEST_SR,
+                                testFrequency);
+                        while (written < data.length) {
+                            int ret = track.write(data, written,
+                                    Math.min(data.length - written, minBufferSize));
+                            assertTrue(TEST_NAME, ret >= 0);
+                            written += ret;
+                            if (!hasPlayed) {
+                                track.play();
+                                hasPlayed = true;
+                            }
+                        }
+                        } break;
+                    case AudioFormat.ENCODING_PCM_16BIT: {
+                        short data[] = createSoundDataInShortArray(
+                                bufferSamples, TEST_SR,
+                                testFrequency);
+                        while (written < data.length) {
+                            int ret = track.write(data, written,
+                                    Math.min(data.length - written, minBufferSize));
+                            assertTrue(TEST_NAME, ret >= 0);
+                            written += ret;
+                            if (!hasPlayed) {
+                                track.play();
+                                hasPlayed = true;
+                            }
+                        }
+                        } break;
+                    case AudioFormat.ENCODING_PCM_FLOAT: {
+                        float data[] = createSoundDataInFloatArray(
+                                bufferSamples, TEST_SR,
+                                testFrequency);
+                        while (written < data.length) {
+                            int ret = track.write(data, written,
+                                    Math.min(data.length - written, minBufferSize),
+                                    AudioTrack.WRITE_BLOCKING);
+                            assertTrue(TEST_NAME, ret >= 0);
+                            written += ret;
+                            if (!hasPlayed) {
+                                track.play();
+                                hasPlayed = true;
+                            }
+                        }
+                        } break;
+                    }
+
+                    Thread.sleep(WAIT_MSEC);
+                    track.stop();
+                    Thread.sleep(WAIT_MSEC);
+                    // -------- tear down --------------
+                    track.release();
+                    frequency += 70; // increment test tone frequency
                 }
             }
         }
-        Thread.sleep(WAIT_MSEC);
-        track.stop();
-        Thread.sleep(WAIT_MSEC);
-        // -------- tear down --------------
-        track.release();
+    }
+
+    public void testPlayStreamByteBuffer() throws Exception {
+        // constants for test
+        final String TEST_NAME = "testPlayStreamByteBuffer";
+        final int TEST_FORMAT_ARRAY[] = {  // should hear 4 tones played 3 times
+                AudioFormat.ENCODING_PCM_8BIT,
+                AudioFormat.ENCODING_PCM_16BIT,
+                AudioFormat.ENCODING_PCM_FLOAT,
+        };
+        final int TEST_SR_ARRAY[] = {
+                48000,
+        };
+        final int TEST_CONF_ARRAY[] = {
+                AudioFormat.CHANNEL_OUT_STEREO,
+        };
+        final int TEST_WRITE_MODE_ARRAY[] = {
+                AudioTrack.WRITE_BLOCKING,
+                AudioTrack.WRITE_NON_BLOCKING,
+        };
+        final int TEST_MODE = AudioTrack.MODE_STREAM;
+        final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+
+        for (int TEST_FORMAT : TEST_FORMAT_ARRAY) {
+            double frequency = 800; // frequency changes for each test
+            for (int TEST_SR : TEST_SR_ARRAY) {
+                for (int TEST_CONF : TEST_CONF_ARRAY) {
+                    for (int TEST_WRITE_MODE : TEST_WRITE_MODE_ARRAY) {
+                        for (int useDirect = 0; useDirect < 2; ++useDirect) {
+                            // -------- initialization --------------
+                            int minBufferSize = AudioTrack.getMinBufferSize(TEST_SR,
+                                    TEST_CONF, TEST_FORMAT); // in bytes
+                            int bufferSize = 12 * minBufferSize;
+                            int bufferSamples = bufferSize
+                                    / AudioFormat.getBytesPerSample(TEST_FORMAT);
+                            AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR,
+                                    TEST_CONF, TEST_FORMAT, minBufferSize, TEST_MODE);
+                            assertTrue(TEST_NAME,
+                                    track.getState() == AudioTrack.STATE_INITIALIZED);
+                            boolean hasPlayed = false;
+                            int written = 0;
+                            ByteBuffer bb = (useDirect == 1)
+                                    ? ByteBuffer.allocateDirect(bufferSize)
+                                            : ByteBuffer.allocate(bufferSize);
+                            bb.order(java.nio.ByteOrder.nativeOrder());
+
+                            // -------- test --------------
+                            switch (TEST_FORMAT) {
+                                case AudioFormat.ENCODING_PCM_8BIT: {
+                                    byte data[] = createSoundDataInByteArray(
+                                            bufferSamples, TEST_SR,
+                                            frequency);
+                                    bb.put(data);
+                                    bb.flip();
+                                } break;
+                                case AudioFormat.ENCODING_PCM_16BIT: {
+                                    short data[] = createSoundDataInShortArray(
+                                            bufferSamples, TEST_SR,
+                                            frequency);
+                                    ShortBuffer sb = bb.asShortBuffer();
+                                    sb.put(data);
+                                    bb.limit(sb.limit() * 2);
+                                } break;
+                                case AudioFormat.ENCODING_PCM_FLOAT: {
+                                    float data[] = createSoundDataInFloatArray(
+                                            bufferSamples, TEST_SR,
+                                            frequency);
+                                    FloatBuffer fb = bb.asFloatBuffer();
+                                    fb.put(data);
+                                    bb.limit(fb.limit() * 4);
+                                } break;
+                            }
+
+                            while (written < bufferSize) {
+                                int ret = track.write(bb,
+                                        Math.min(bufferSize - written, minBufferSize),
+                                        TEST_WRITE_MODE);
+                                assertTrue(TEST_NAME, ret >= 0);
+                                written += ret;
+                                if (!hasPlayed) {
+                                    track.play();
+                                    hasPlayed = true;
+                                }
+                            }
+
+                            Thread.sleep(WAIT_MSEC);
+                            track.stop();
+                            Thread.sleep(WAIT_MSEC);
+                            // -------- tear down --------------
+                            track.release();
+                            frequency += 200; // increment test tone frequency
+                        }
+                    }
+                }
+            }
+        }
     }
 
     public void testGetTimestamp() throws Exception {
         // constants for test
         final String TEST_NAME = "testGetTimestamp";
         final int TEST_SR = 22050;
-        final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
         final int TEST_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
         final int TEST_MODE = AudioTrack.MODE_STREAM;
         final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
         final int TEST_LOOP_CNT = 10;
-
-        final int MILLIS_PER_SEC = 1000;
-        final int NANOS_PER_MILLI = 1000000;
+        // For jitter we allow 30 msec in frames.  This is a large margin.
+        // Often this is just 0 or 1 frames, but that can depend on hardware.
+        final int TEST_JITTER_FRAMES_ALLOWED = TEST_SR * 30 / 1000;
 
         // -------- initialization --------------
-        final int BYTES_PER_FRAME = 2;
-        final int FRAMES_PER_100_MILLIS =
+        final int bytesPerFrame =
+                AudioFormat.getBytesPerSample(TEST_FORMAT)
+                * AudioFormat.channelCountFromOutChannelMask(TEST_CONF);
+        final int minBufferSizeInBytes =
                 AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
-        final int FRAMES_PER_SEC = FRAMES_PER_100_MILLIS * 10;
-        byte[] data = new byte[FRAMES_PER_100_MILLIS * BYTES_PER_FRAME];
+        final int bufferSizeInBytes = minBufferSizeInBytes * 3;
+        byte[] data = new byte[bufferSizeInBytes];
         AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF, TEST_FORMAT,
-                 FRAMES_PER_SEC * BYTES_PER_FRAME, TEST_MODE);
+                minBufferSizeInBytes, TEST_MODE);
         // -------- test --------------
         assertTrue(TEST_NAME, track.getState() == AudioTrack.STATE_INITIALIZED);
 
-        long framesWritten = 0, framesSeen = 0, framesPresented = 0;
-        long lastFramesPresented = 0, lastFrameTime = 0, lastOutputFrequency = FRAMES_PER_SEC;
         AudioTimestamp timestamp = new AudioTimestamp();
+        boolean hasPlayed = false;
 
+        long framesWritten = 0, lastFramesPresented = 0, lastFramesPresentedAt = 0;
+        int cumulativeJitterCount = 0;
+        float cumulativeJitter = 0;
+        float maxJitter = 0;
         for (int i = 0; i < TEST_LOOP_CNT; i++) {
-            for (int j = 0; j < FRAMES_PER_SEC; j += FRAMES_PER_100_MILLIS) {
-                track.write(data, 0, data.length);
-                framesWritten += FRAMES_PER_100_MILLIS;
+            final long writeTime = System.nanoTime();
+
+            for (int written = 0; written < data.length;) {
+                int ret = track.write(data, written,
+                        Math.min(data.length - written, minBufferSizeInBytes));
+                assertTrue(TEST_NAME, ret >= 0);
+                written += ret;
+                if (!hasPlayed) {
+                    track.play();
+                    hasPlayed = true;
+                }
+            }
+            framesWritten += data.length / bytesPerFrame;
+
+            // track.getTimestamp may return false if there are no physical HAL outputs.
+            // This may occur on TV devices without connecting an HDMI monitor.
+            // It may also be true immediately after start-up, as the mixing thread could
+            // be idle, but since we've already pushed much more than the minimum buffer size,
+            // that is unlikely.
+            // Nevertheless, we don't want to have unnecessary failures, so we ignore the
+            // first iteration if we don't get a timestamp.
+            final boolean result = track.getTimestamp(timestamp);
+            assertTrue(TEST_NAME, result || i == 0);
+            if (!result) {
+                continue;
             }
 
-            track.play();
-            Thread.sleep(MILLIS_PER_SEC);
-            track.pause();
+            final long framesPresented = timestamp.framePosition;
+            final long framesPresentedAt = timestamp.nanoTime;
 
-            framesSeen = track.getPlaybackHeadPosition();
+            // We read timestamp here to ensure that seen is greater than presented.
+            // This is an "on-the-fly" read without pausing because pausing may cause the
+            // timestamp to become stale and affect our jitter measurements.
+            final int framesSeen = track.getPlaybackHeadPosition();
             assertTrue(TEST_NAME, framesWritten >= framesSeen);
-
-            assertTrue(TEST_NAME, track.getTimestamp(timestamp));
-            framesPresented = timestamp.framePosition;
             assertTrue(TEST_NAME, framesSeen >= framesPresented);
 
-            // check output frequency
-            long outFrequency = framesPresented - lastFramesPresented;
-            long freqDiff = Math.abs(FRAMES_PER_SEC - outFrequency);
-            assertTrue(TEST_NAME, freqDiff < FRAMES_PER_100_MILLIS);
+            if (i > 1) { // need delta info from previous iteration (skipping first)
+                final long deltaFrames = framesPresented - lastFramesPresented;
+                final long deltaTime = framesPresentedAt - lastFramesPresentedAt;
+                final long NANOSECONDS_PER_SECOND = 1000000000;
+                final long expectedFrames = deltaTime * TEST_SR / NANOSECONDS_PER_SECOND;
+                final long jitterFrames = Math.abs(deltaFrames - expectedFrames);
 
-            // check output frequency jitter
-            freqDiff = Math.abs(outFrequency - lastOutputFrequency);
-            assertTrue(TEST_NAME, freqDiff < FRAMES_PER_100_MILLIS);
+                //Log.d(TAG, "framesWritten(" + framesWritten
+                //        + ") framesSeen(" + framesSeen
+                //        + ") framesPresented(" + framesPresented
+                //        + ") jitter(" + jitterFrames + ")");
 
+                // We check that the timestamp position is reasonably accurate.
+                assertTrue(TEST_NAME, deltaTime >= 0);
+                assertTrue(TEST_NAME, deltaFrames >= 0);
+                if (i > 2) {
+                    // The first two periods may have inherent jitter as the audio pipe
+                    // is filling up. We check jitter only after that.
+                    assertTrue(TEST_NAME, jitterFrames < TEST_JITTER_FRAMES_ALLOWED);
+                    cumulativeJitter += jitterFrames;
+                    cumulativeJitterCount++;
+                    if (jitterFrames > maxJitter) {
+                        maxJitter = jitterFrames;
+                    }
+                }
+
+                //Log.d(TAG, "lastFramesPresentedAt(" + lastFramesPresentedAt
+                //        + ") writeTime(" + writeTime
+                //        + ") framesPresentedAt(" + framesPresentedAt + ")");
+
+                // We check that the timestamp time is reasonably current.
+                assertTrue(TEST_NAME, framesPresentedAt >= writeTime);
+                assertTrue(TEST_NAME, writeTime >= lastFramesPresentedAt);
+            }
             lastFramesPresented = framesPresented;
-            lastOutputFrequency = outFrequency;
-
-            long frameTime = timestamp.nanoTime;
-            assertTrue(TEST_NAME, frameTime >= lastFrameTime);
-            lastFrameTime = frameTime;
-
-            long curTime = System.nanoTime();
-            assertTrue(TEST_NAME, curTime >= frameTime);
-            assertTrue(TEST_NAME, curTime - frameTime < 100 * NANOS_PER_MILLI);
+            lastFramesPresentedAt = framesPresentedAt;
         }
+        // Full drain.
+        Thread.sleep(WAIT_MSEC);
         track.stop();
-        // -------- tear down --------------
+        Thread.sleep(WAIT_MSEC);
         track.release();
+        // Log the average jitter
+        if (cumulativeJitterCount > 0) {
+            ReportLog log = getReportLog();
+            final float averageJitterInFrames = cumulativeJitter / cumulativeJitterCount;
+            final float averageJitterInMs = averageJitterInFrames * 1000 / TEST_SR;
+            final float maxJitterInMs = maxJitter * 1000 / TEST_SR;
+            // ReportLog needs at least one Value and Summary.
+            log.printValue("Maximum Jitter", maxJitterInMs,
+                    ResultType.LOWER_BETTER, ResultUnit.MS);
+            log.printSummary("Average Jitter", averageJitterInMs,
+                    ResultType.LOWER_BETTER, ResultUnit.MS);
+        }
     }
 
 /* Do not run in JB-MR1. will be re-opened in the next platform release.
diff --git a/tests/tests/media/src/android/media/cts/AudioTrack_ListenerTest.java b/tests/tests/media/src/android/media/cts/AudioTrack_ListenerTest.java
index 26841da..eb675fc 100644
--- a/tests/tests/media/src/android/media/cts/AudioTrack_ListenerTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioTrack_ListenerTest.java
@@ -22,6 +22,7 @@
 import android.media.AudioTrack;
 import android.media.AudioTrack.OnPlaybackPositionUpdateListener;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
 import android.test.AndroidTestCase;
 
@@ -34,7 +35,7 @@
     private final int TEST_FORMAT = AudioFormat.ENCODING_PCM_8BIT;
     private final int TEST_MODE = AudioTrack.MODE_STREAM;
     private final int TEST_STREAM_TYPE1 = AudioManager.STREAM_MUSIC;
-    private Handler mHandler = new Handler() {
+    private Handler mHandler = new Handler(Looper.getMainLooper()) {
         @Override
         public void handleMessage(Message msg) {
             mIsHandleMessageCalled = true;
@@ -42,27 +43,47 @@
         }
     };
     private final int mMinBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
-    private AudioTrack mAudioTrack = new AudioTrack(TEST_STREAM_TYPE1, TEST_SR, TEST_CONF,
-            TEST_FORMAT, 2 * mMinBuffSize, TEST_MODE);
+    private AudioTrack mAudioTrack;
     private OnPlaybackPositionUpdateListener mListener =
                                 new MockOnPlaybackPositionUpdateListener();
+    private MakeSomethingAsynchronouslyAndLoop<AudioTrack> mMakeSomething;
+
+    @Override
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+        if (mAudioTrack == null) {
+            mMakeSomething = new MakeSomethingAsynchronouslyAndLoop<AudioTrack>(
+                new MakesSomething<AudioTrack>() {
+                    @Override
+                    public AudioTrack makeSomething()
+                    {
+                        return new AudioTrack(TEST_STREAM_TYPE1, TEST_SR, TEST_CONF,
+                            TEST_FORMAT, 2 * mMinBuffSize, TEST_MODE);
+                    }
+                }
+            );
+            mAudioTrack = mMakeSomething.make();
+        }
+    }
 
     public void testAudioTrackCallback() throws Exception {
         mAudioTrack.setPlaybackPositionUpdateListener(mListener);
-        doTest();
+        doTest(false /*customHandler*/);
     }
 
     public void testAudioTrackCallbackWithHandler() throws Exception {
         mAudioTrack.setPlaybackPositionUpdateListener(mListener, mHandler);
-        doTest();
+        doTest(true /*customHandler*/);
         // ToBeFixed: Handler#handleMessage() is never called
+        // FIXME possibly because the new Handler() is missing the Looper parameter
         assertFalse(mIsHandleMessageCalled);
     }
 
-    private void doTest() throws Exception {
+    private void doTest(boolean customHandler) throws Exception {
         mOnMarkerReachedCalled = false;
         mOnPeriodicNotificationCalled = false;
-        byte[] vai = AudioTrackTest.createSoundDataInByteArray(2 * mMinBuffSize, TEST_SR);
+        byte[] vai = AudioTrackTest.createSoundDataInByteArray(2 * mMinBuffSize, TEST_SR, 1024);
         int markerInFrames = vai.length / 4;
         assertEquals(AudioTrack.SUCCESS, mAudioTrack.setNotificationMarkerPosition(markerInFrames));
         int periodInFrames = vai.length / 2;
@@ -83,11 +104,95 @@
         final int bytesPerFrame = numChannels * bytesPerSample;
         final int sampleLengthMs = (int)(1000 * ((float)vai.length / TEST_SR / bytesPerFrame));
         Thread.sleep(sampleLengthMs + 1000);
-        assertTrue(mOnMarkerReachedCalled);
-        assertTrue(mOnPeriodicNotificationCalled);
+        if (!customHandler) {
+            assertTrue(mOnMarkerReachedCalled);
+            assertTrue(mOnPeriodicNotificationCalled);
+        }
         mAudioTrack.stop();
     }
 
+    // lightweight java.util.concurrent.Future*
+    private static class FutureLatch<T>
+    {
+        private T mValue;
+        private boolean mSet;
+        public void set(T value)
+        {
+            synchronized (this) {
+                assert !mSet;
+                mValue = value;
+                mSet = true;
+                notify();
+            }
+        }
+        public T get()
+        {
+            T value;
+            synchronized (this) {
+                while (!mSet) {
+                    try {
+                        wait();
+                    } catch (InterruptedException e) {
+                        ;
+                    }
+                }
+                value = mValue;
+            }
+            return value;
+        }
+    }
+
+    // represents a factory for T
+    private interface MakesSomething<T>
+    {
+        T makeSomething();
+    }
+
+    // used to construct an object in the context of an asynchronous thread with looper
+    private static class MakeSomethingAsynchronouslyAndLoop<T>
+    {
+        private Thread mThread;
+        volatile private Looper mLooper;
+        private final MakesSomething<T> mWhatToMake;
+
+        public MakeSomethingAsynchronouslyAndLoop(MakesSomething<T> whatToMake)
+        {
+            assert whatToMake != null;
+            mWhatToMake = whatToMake;
+        }
+
+        public T make()
+        {
+            final FutureLatch<T> futureLatch = new FutureLatch<T>();
+            mThread = new Thread()
+            {
+                @Override
+                public void run()
+                {
+                    Looper.prepare();
+                    mLooper = Looper.myLooper();
+                    T something = mWhatToMake.makeSomething();
+                    futureLatch.set(something);
+                    Looper.loop();
+                }
+            };
+            mThread.start();
+            return futureLatch.get();
+        }
+        public void join()
+        {
+            mLooper.quit();
+            try {
+                mThread.join();
+            } catch (InterruptedException e) {
+                ;
+            }
+            // avoid dangling references
+            mLooper = null;
+            mThread = null;
+        }
+    }
+
     private class MockOnPlaybackPositionUpdateListener
                                         implements OnPlaybackPositionUpdateListener {
 
@@ -103,8 +208,14 @@
 
     @Override
     protected void tearDown() throws Exception {
-        mAudioTrack.release();
+        if (mMakeSomething != null) {
+            mMakeSomething.join();
+        }
+        if (mAudioTrack != null) {
+            mAudioTrack.release();
+            mAudioTrack = null;
+        }
         super.tearDown();
     }
 
-}
\ No newline at end of file
+}
diff --git a/tests/tests/media/src/android/media/cts/BassBoostTest.java b/tests/tests/media/src/android/media/cts/BassBoostTest.java
index 9dcb4e9..c9bffd9 100644
--- a/tests/tests/media/src/android/media/cts/BassBoostTest.java
+++ b/tests/tests/media/src/android/media/cts/BassBoostTest.java
@@ -24,7 +24,7 @@
 import android.test.AndroidTestCase;
 import android.util.Log;
 
-public class BassBoostTest extends AndroidTestCase {
+public class BassBoostTest extends PostProcTestBase {
 
     private String TAG = "BassBoostTest";
     private final static short TEST_STRENGTH = 500;
@@ -34,13 +34,6 @@
 
     private BassBoost mBassBoost = null;
     private BassBoost mBassBoost2 = null;
-    private int mSession = -1;
-    private boolean mHasControl = false;
-    private boolean mIsEnabled = false;
-    private int mChangedParameter = -1;
-    private boolean mInitialized = false;
-    private Looper mLooper = null;
-    private final Object mLock = new Object();
     private ListenerThread mEffectListenerLooper = null;
 
     //-----------------------------------------------------------------
@@ -53,10 +46,12 @@
 
     //Test case 0.0: test constructor and release
     public void test0_0ConstructorAndRelease() throws Exception {
+        if (!isBassBoostAvailable()) {
+            return;
+        }
         BassBoost eq = null;
         try {
             eq = new BassBoost(0, 0);
-            assertNotNull("could not create BassBoost", eq);
             try {
                 assertTrue("invalid effect ID", (eq.getId() != 0));
             } catch (IllegalStateException e) {
@@ -81,6 +76,9 @@
 
     //Test case 1.0: test strength
     public void test1_0Strength() throws Exception {
+        if (!isBassBoostAvailable()) {
+            return;
+        }
         getBassBoost(0);
         try {
             if (mBassBoost.getStrengthSupported()) {
@@ -110,6 +108,9 @@
 
     //Test case 1.1: test properties
     public void test1_1Properties() throws Exception {
+        if (!isBassBoostAvailable()) {
+            return;
+        }
         getBassBoost(0);
         try {
             BassBoost.Settings settings = mBassBoost.getProperties();
@@ -144,6 +145,9 @@
 
     //Test case 1.2: test setStrength() throws exception after release
     public void test1_2SetStrengthAfterRelease() throws Exception {
+        if (!isBassBoostAvailable()) {
+            return;
+        }
         getBassBoost(0);
         mBassBoost.release();
         try {
@@ -162,6 +166,9 @@
 
     //Test case 2.0: test setEnabled() and getEnabled() in valid state
     public void test2_0SetEnabledGetEnabled() throws Exception {
+        if (!isBassBoostAvailable()) {
+            return;
+        }
         getBassBoost(0);
         try {
             mBassBoost.setEnabled(true);
@@ -178,6 +185,9 @@
 
     //Test case 2.1: test setEnabled() throws exception after release
     public void test2_1SetEnabledAfterRelease() throws Exception {
+        if (!isBassBoostAvailable()) {
+            return;
+        }
         getBassBoost(0);
         mBassBoost.release();
         try {
@@ -196,6 +206,9 @@
 
     //Test case 3.0: test control status listener
     public void test3_0ControlStatusListener() throws Exception {
+        if (!isBassBoostAvailable()) {
+            return;
+        }
         synchronized(mLock) {
             mHasControl = true;
             mInitialized = false;
@@ -218,6 +231,9 @@
 
     //Test case 3.1: test enable status listener
     public void test3_1EnableStatusListener() throws Exception {
+        if (!isBassBoostAvailable()) {
+            return;
+        }
         synchronized(mLock) {
             mInitialized = false;
             createListenerLooper(false, true, false);
@@ -242,6 +258,9 @@
 
     //Test case 3.2: test parameter changed listener
     public void test3_2ParameterChangedListener() throws Exception {
+        if (!isBassBoostAvailable()) {
+            return;
+        }
         synchronized(mLock) {
             mInitialized = false;
             createListenerLooper(false, false, true);
@@ -413,5 +432,4 @@
             mBassBoost2 = null;
         }
     }
-
 }
\ No newline at end of file
diff --git a/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java b/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java
index 1df5011..8130a9a 100644
--- a/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java
+++ b/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java
@@ -30,6 +30,7 @@
 public class CamcorderProfileTest extends AndroidTestCase {
 
     private static final String TAG = "CamcorderProfileTest";
+    private static final int MIN_HIGH_SPEED_FPS = 100;
 
     // Uses get without id if cameraId == -1 and get with id otherwise.
     private CamcorderProfile getWithOptionalId(int quality, int cameraId) {
@@ -65,13 +66,20 @@
                    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 ||
+                   profile.quality == CamcorderProfile.QUALITY_HIGH_SPEED_LOW ||
+                   profile.quality == CamcorderProfile.QUALITY_HIGH_SPEED_HIGH ||
+                   profile.quality == CamcorderProfile.QUALITY_HIGH_SPEED_480P ||
+                   profile.quality == CamcorderProfile.QUALITY_HIGH_SPEED_720P ||
+                   profile.quality == CamcorderProfile.QUALITY_HIGH_SPEED_1080P);
         assertTrue(profile.videoBitRate > 0);
         assertTrue(profile.videoFrameRate > 0);
         assertTrue(profile.videoFrameWidth > 0);
@@ -137,6 +145,30 @@
                 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;
+            case CamcorderProfile.QUALITY_HIGH_SPEED_480P:
+                assertTrue(720 == profile.videoFrameWidth ||  // SMPTE 293M/ITU-R Rec. 601
+                640 == profile.videoFrameWidth ||  // ATSC/NTSC (square sampling)
+                704 == profile.videoFrameWidth);   // ATSC/NTSC (non-square sampling)
+                assertEquals(480, profile.videoFrameHeight);
+                assertTrue(profile.videoFrameRate >= MIN_HIGH_SPEED_FPS);
+                break;
+            case CamcorderProfile.QUALITY_HIGH_SPEED_720P:
+                assertEquals(1280, profile.videoFrameWidth);
+                assertEquals(720, profile.videoFrameHeight);
+                assertTrue(profile.videoFrameRate >= MIN_HIGH_SPEED_FPS);
+                break;
+            case CamcorderProfile.QUALITY_HIGH_SPEED_1080P:
+                // 1080p could be either 1920x1088 or 1920x1080.
+                assertEquals(1920, profile.videoFrameWidth);
+                assertTrue(1088 == profile.videoFrameHeight ||
+                           1080 == profile.videoFrameHeight);
+                assertTrue(profile.videoFrameRate >= MIN_HIGH_SPEED_FPS);
+                break;
         }
     }
 
@@ -150,6 +182,16 @@
             int[] specificQualities,
             List<Size> videoSizes) {
 
+        // For high speed levels, low and high quality are optional,skip the test if
+        // they are missing.
+        if (low == null && high == null) {
+            // No profile should be available if low and high are unavailable.
+            for (int quality : specificQualities) {
+                assertFalse(CamcorderProfile.hasProfile(cameraId, quality));
+            }
+            return;
+        }
+
         CamcorderProfile minProfile = null;
         CamcorderProfile maxProfile = null;
 
@@ -205,24 +247,55 @@
         checkProfile(lowTimeLapseProfile, null);
         checkProfile(highTimeLapseProfile, null);
 
+        // High speed low and high profile are optional,
+        // but they should be both present or missing.
+        CamcorderProfile lowHighSpeedProfile = null;
+        CamcorderProfile highHighSpeedProfile = null;
+        if (CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_HIGH_SPEED_LOW)) {
+            lowHighSpeedProfile =
+                    getWithOptionalId(CamcorderProfile.QUALITY_HIGH_SPEED_LOW, cameraId);
+        }
+        if (CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_HIGH_SPEED_HIGH)) {
+            highHighSpeedProfile =
+                    getWithOptionalId(CamcorderProfile.QUALITY_HIGH_SPEED_HIGH, cameraId);
+        }
+        if (lowHighSpeedProfile != null) {
+            assertNotNull("high speed high quality profile should be supported if low" +
+                    " is supported ",
+                    highHighSpeedProfile);
+            checkProfile(lowHighSpeedProfile, null);
+            checkProfile(highHighSpeedProfile, null);
+        } else {
+            assertNull("high speed high quality profile shouldn't be supported if " +
+                    "low is unsupported ", highHighSpeedProfile);
+        }
+
         int[] specificProfileQualities = {CamcorderProfile.QUALITY_QCIF,
                                           CamcorderProfile.QUALITY_QVGA,
                                           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};
+
+        int[] specificHighSpeedProfileQualities = {CamcorderProfile.QUALITY_HIGH_SPEED_480P,
+                                                   CamcorderProfile.QUALITY_HIGH_SPEED_720P,
+                                                   CamcorderProfile.QUALITY_HIGH_SPEED_1080P};
 
         checkSpecificProfiles(cameraId, lowProfile, highProfile,
                 specificProfileQualities, videoSizes);
         checkSpecificProfiles(cameraId, lowTimeLapseProfile, highTimeLapseProfile,
                 specificTimeLapseProfileQualities, null);
+        checkSpecificProfiles(cameraId, lowHighSpeedProfile, highHighSpeedProfile,
+                specificHighSpeedProfileQualities, null);
     }
 
     public void testGet() {
diff --git a/tests/tests/media/src/android/media/cts/ClearKeySystemTest.java b/tests/tests/media/src/android/media/cts/ClearKeySystemTest.java
new file mode 100644
index 0000000..c05a605
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/ClearKeySystemTest.java
@@ -0,0 +1,454 @@
+/*
+ * 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.media.cts;
+
+import android.content.Context;
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecInfo.CodecCapabilities;
+import android.media.MediaCodecInfo.CodecProfileLevel;
+import android.media.MediaCodecList;
+import android.media.MediaDrm;
+import android.media.MediaDrmException;
+import android.media.CamcorderProfile;
+import android.net.Uri;
+import android.os.Environment;
+import android.os.Looper;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Base64;
+import android.util.Log;
+import android.view.SurfaceHolder;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.Vector;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ * Tests of MediaPlayer streaming capabilities.
+ */
+public class ClearKeySystemTest extends MediaPlayerTestBase {
+    private static final String TAG = ClearKeySystemTest.class.getSimpleName();
+
+    // Add additional keys here if the content has more keys.
+    private static final byte[] CLEAR_KEY =
+        { 0x1a, (byte)0x8a, 0x20, (byte)0x95, (byte)0xe4, (byte)0xde, (byte)0xb2, (byte)0xd2,
+          (byte)0x9e, (byte)0xc8, 0x16, (byte)0xac, 0x7b, (byte)0xae, 0x20, (byte)0x82 };
+
+    private static final int SLEEP_TIME_MS = 1000;
+    private static final int VIDEO_WIDTH = 1280;
+    private static final int VIDEO_HEIGHT = 720;
+    private static final long PLAY_TIME_MS = TimeUnit.MILLISECONDS.convert(1, TimeUnit.MINUTES);
+    private static final String MIME_VIDEO_AVC = "video/avc";
+
+    private static final Uri AUDIO_URL = Uri.parse(
+            "http://yt-dash-mse-test.commondatastorage.googleapis.com/media/car_cenc-20120827-8c.mp4");
+    private static final Uri VIDEO_URL = Uri.parse(
+            "http://yt-dash-mse-test.commondatastorage.googleapis.com/media/car_cenc-20120827-88.mp4");
+
+    private static final UUID CLEARKEY_SCHEME_UUID =
+            new UUID(0x1077efecc0b24d02L, 0xace33c1e52e2fb4bL);
+
+    private byte[] mDrmInitData;
+    private byte[] mSessionId;
+    private Context mContext;
+    private final List<byte[]> mClearKeys = new ArrayList<byte[]>() {
+        {
+            add(CLEAR_KEY);
+            // add additional keys here
+        }
+    };
+    private Looper mLooper;
+    private MediaCodecCencPlayer mMediaCodecPlayer;
+    private MediaDrm mDrm;
+    private Object mLock = new Object();
+    private SurfaceHolder mSurfaceHolder;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        if (false == deviceHasMediaDrm()) {
+            tearDown();
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    private boolean deviceHasMediaDrm() {
+        // ClearKey is introduced after KitKat.
+        if (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.KITKAT) {
+            Log.i(TAG, "This test is designed to work after Android KitKat.");
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Extracts key ids from the pssh blob returned by getKeyRequest() and
+     * places it in keyIds.
+     * keyRequestBlob format (section 5.1.3.1):
+     * https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#clear-key
+     *
+     * @return size of keyIds vector that contains the key ids, 0 for error
+     */
+    private int getKeyIds(byte[] keyRequestBlob, Vector<String> keyIds) {
+        if (0 == keyRequestBlob.length || keyIds == null)
+            return 0;
+
+        String jsonLicenseRequest = new String(keyRequestBlob);
+        keyIds.clear();
+
+        try {
+            JSONObject license = new JSONObject(jsonLicenseRequest);
+            final JSONArray ids = license.getJSONArray("kids");
+            for (int i = 0; i < ids.length(); ++i) {
+                keyIds.add(ids.getString(i));
+            }
+        } catch (JSONException e) {
+            Log.e(TAG, "Invalid JSON license = " + jsonLicenseRequest);
+            return 0;
+        }
+        return keyIds.size();
+    }
+
+    /**
+     * Creates the JSON Web Key string.
+     *
+     * @return JSON Web Key string.
+     */
+    private String createJsonWebKeySet(Vector<String> keyIds, Vector<String> keys) {
+        String jwkSet = "{\"keys\":[";
+        for (int i = 0; i < keyIds.size(); ++i) {
+            String id = new String(keyIds.get(i).getBytes(Charset.forName("UTF-8")));
+            String key = new String(keys.get(i).getBytes(Charset.forName("UTF-8")));
+
+            jwkSet += "{\"kty\":\"oct\",\"kid\":\"" + id +
+                    "\",\"k\":\"" + key + "\"}";
+        }
+        jwkSet += "]}";
+        return jwkSet;
+    }
+
+    /**
+     * Retrieves clear key ids from getKeyRequest(), create JSON Web Key
+     * set and send it to the CDM via provideKeyResponse().
+     */
+    private void getKeys(MediaDrm drm, byte[] sessionId, byte[] drmInitData) {
+        MediaDrm.KeyRequest drmRequest = null;;
+        try {
+            drmRequest = drm.getKeyRequest(sessionId, drmInitData, "cenc",
+                    MediaDrm.KEY_TYPE_STREAMING, null);
+        } catch (Exception e) {
+            e.printStackTrace();
+            Log.i(TAG, "Failed to get key request: " + e.toString());
+        }
+        if (drmRequest == null) {
+            Log.e(TAG, "Failed getKeyRequest");
+            return;
+        }
+
+        Vector<String> keyIds = new Vector<String>();
+        if (0 == getKeyIds(drmRequest.getData(), keyIds)) {
+            Log.e(TAG, "No key ids found in initData");
+            return;
+        }
+
+        if (mClearKeys.size() != keyIds.size()) {
+            Log.e(TAG, "Mismatch number of key ids and keys: ids=" +
+                    keyIds.size() + ", keys=" + mClearKeys.size());
+            return;
+        }
+
+        // Base64 encodes clearkeys. Keys are known to the application.
+        Vector<String> keys = new Vector<String>();
+        for (int i = 0; i < mClearKeys.size(); ++i) {
+            String clearKey = Base64.encodeToString(mClearKeys.get(i),
+                    Base64.NO_PADDING | Base64.NO_WRAP);
+            keys.add(clearKey);
+        }
+
+        String jwkSet = createJsonWebKeySet(keyIds, keys);
+        byte[] jsonResponse = jwkSet.getBytes(Charset.forName("UTF-8"));
+
+        try {
+            try {
+                drm.provideKeyResponse(sessionId, jsonResponse);
+            } catch (IllegalStateException e) {
+                Log.e(TAG, "Failed to provide key response: " + e.toString());
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            Log.e(TAG, "Failed to provide key response: " + e.toString());
+        }
+    }
+
+    private MediaDrm startDrm() {
+        new Thread() {
+            @Override
+            public void run() {
+                // Set up a looper to handle events
+                Looper.prepare();
+
+                // Save the looper so that we can terminate this thread
+                // after we are done with it.
+                mLooper = Looper.myLooper();
+
+                try {
+                    mDrm = new MediaDrm(CLEARKEY_SCHEME_UUID);
+                } catch (MediaDrmException e) {
+                    Log.e(TAG, "Failed to create MediaDrm: " + e.getMessage());
+                    return;
+                }
+
+                synchronized(mLock) {
+                    mDrm.setOnEventListener(new MediaDrm.OnEventListener() {
+                            @Override
+                            public void onEvent(MediaDrm md, byte[] sessionId, int event,
+                                    int extra, byte[] data) {
+                                if (event == MediaDrm.EVENT_KEY_REQUIRED) {
+                                    Log.i(TAG, "MediaDrm event: Key required");
+                                    getKeys(mDrm, mSessionId, mDrmInitData);
+                                } else if (event == MediaDrm.EVENT_KEY_EXPIRED) {
+                                    Log.i(TAG, "MediaDrm event: Key expired");
+                                    getKeys(mDrm, mSessionId, mDrmInitData);
+                                } else {
+                                    Log.e(TAG, "Events not supported" + event);
+                                }
+                            }
+                        });
+                    mLock.notify();
+                }
+                Looper.loop();  // Blocks forever until Looper.quit() is called.
+            }
+        }.start();
+
+        // wait for mDrm to be created
+        synchronized(mLock) {
+            try {
+                mLock.wait(1000);
+            } catch (Exception e) {
+            }
+        }
+        return mDrm;
+    }
+
+    private void stopDrm(MediaDrm drm) {
+        if (drm != mDrm) {
+            Log.e(TAG, "invalid drm specified in stopDrm");
+        }
+        mLooper.quit();
+    }
+
+    private byte[] openSession(MediaDrm drm) {
+        byte[] mSessionId = null;
+        boolean mRetryOpen;
+        do {
+            try {
+                mRetryOpen = false;
+                mSessionId = drm.openSession();
+            } catch (Exception e) {
+                mRetryOpen = true;
+            }
+        } while (mRetryOpen);
+        return mSessionId;
+    }
+
+    private void closeSession(MediaDrm drm, byte[] sessionId) {
+        drm.closeSession(sessionId);
+    }
+
+    public boolean isResolutionSupported(int videoWidth, int videoHeight) {
+        if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN) {
+            if  (videoHeight <= 144) {
+                return CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_QCIF);
+            } else if (videoHeight <= 240) {
+                return CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_QVGA);
+            } else if (videoHeight <= 288) {
+                return CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_CIF);
+            } else if (videoHeight <= 480) {
+                return CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_480P);
+            } else if (videoHeight <= 720) {
+                return CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_720P);
+            } else if (videoHeight <= 1080) {
+                return CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_1080P);
+            } else {
+                return false;
+            }
+        }
+
+        CodecCapabilities cap;
+        int highestProfileLevel = 0;
+        MediaCodecInfo codecInfo;
+
+        for (int i = 0; i < MediaCodecList.getCodecCount(); i++) {
+            codecInfo = MediaCodecList.getCodecInfoAt(i);
+            if (codecInfo.isEncoder()) {
+                continue;
+            }
+
+            String[] types = codecInfo.getSupportedTypes();
+            for (int j = 0; j < types.length; ++j) {
+                if (!types[j].equalsIgnoreCase(MIME_VIDEO_AVC)) {
+                    continue;
+                }
+
+                Log.d(TAG, "codec: " + codecInfo.getName() + "types: " + types[j]);
+                cap = codecInfo.getCapabilitiesForType(types[j]);
+                for (CodecProfileLevel profileLevel : cap.profileLevels) {
+                    Log.i(TAG, "codec " + codecInfo.getName() + ", level " + profileLevel.level);
+                    if (profileLevel.level > highestProfileLevel) {
+                        highestProfileLevel = profileLevel.level;
+                    }
+                }
+                Log.i(TAG, "codec " + codecInfo.getName() + ", highest level " + highestProfileLevel);
+            }
+        }
+
+        // AVCLevel and its resolution is taken from http://en.wikipedia.org/wiki/H.264/MPEG-4_AVC
+        switch(highestProfileLevel) {
+        case CodecProfileLevel.AVCLevel1:
+        case CodecProfileLevel.AVCLevel1b:
+            return (videoWidth <= 176 && videoHeight <= 144);
+        case CodecProfileLevel.AVCLevel11:
+        case CodecProfileLevel.AVCLevel12:
+        case CodecProfileLevel.AVCLevel13:
+        case CodecProfileLevel.AVCLevel2:
+            return (videoWidth <= 352 && videoHeight <= 288);
+        case CodecProfileLevel.AVCLevel21:
+            return (videoWidth <= 352 && videoHeight <= 576);
+        case CodecProfileLevel.AVCLevel22:
+        case CodecProfileLevel.AVCLevel3:
+            return (videoWidth <= 720 && videoHeight <= 576);
+        case CodecProfileLevel.AVCLevel31:
+            return (videoWidth <= 1280 && videoHeight <= 720);
+        case CodecProfileLevel.AVCLevel32:
+            return (videoWidth <= 1280 && videoHeight <= 1024);
+        case CodecProfileLevel.AVCLevel4:
+        case CodecProfileLevel.AVCLevel41:
+            // 1280 x 720
+            // 1920 x 1080
+            // 2048 x 1024
+            if (videoWidth <= 1920) {
+                return (videoHeight <= 1080);
+            } else if (videoWidth <= 2048) {
+                return (videoHeight <= 1024);
+            } else {
+                return false;
+            }
+        case CodecProfileLevel.AVCLevel42:
+            return (videoWidth <= 2048 && videoHeight <= 1080);
+        case CodecProfileLevel.AVCLevel5:
+            // 1920 x 1080
+            // 2048 x 1024
+            // 2048 x 1080
+            // 2560 x 1920
+            // 3672 x 1536
+            if (videoWidth <= 1920) {
+                return (videoHeight <= 1080);
+            } else if (videoWidth <= 2048) {
+                return (videoHeight <= 1080);
+            } else if (videoWidth <= 2560) {
+                return (videoHeight <= 1920);
+            } else if (videoWidth <= 3672) {
+                return (videoHeight <= 1536);
+            } else {
+                return false;
+            }
+        case CodecProfileLevel.AVCLevel51:
+        default:  // any future extension will cap at level 5.1
+            // 1920 x 1080
+            // 2560 x 1920
+            // 3840 x 2160
+            // 4096 x 2048
+            // 4096 x 2160
+            // 4096 x 2304
+            if (videoWidth <= 1920) {
+                return (videoHeight <= 1080);
+            } else if (videoWidth <= 2560) {
+                return (videoHeight <= 1920);
+            } else if (videoWidth <= 3840) {
+                return (videoHeight <= 2160);
+            } else if (videoWidth <= 4096) {
+                return (videoHeight <= 2304);
+            } else {
+                return false;
+            }
+        }
+    }
+
+    /**
+     * Tests clear key system playback.
+     */
+    public void testClearKeyPlayback() throws Exception {
+        MediaDrm drm = startDrm();
+        if (null == drm) {
+            throw new Error("Failed to create drm.");
+        }
+
+        if (!drm.isCryptoSchemeSupported(CLEARKEY_SCHEME_UUID)) {
+            stopDrm(drm);
+            throw new Error("Crypto scheme is not supported.");
+        }
+
+        if (!isResolutionSupported(VIDEO_WIDTH, VIDEO_HEIGHT)) {
+            Log.i(TAG, "Device does not support " +
+                    VIDEO_WIDTH + "x" + VIDEO_HEIGHT + "resolution.");
+            return;
+        }
+
+        mSessionId = openSession(drm);
+        mMediaCodecPlayer = new MediaCodecCencPlayer(
+                getActivity().getSurfaceHolder(), mSessionId);
+
+        mMediaCodecPlayer.setAudioDataSource(AUDIO_URL, null, false);
+        mMediaCodecPlayer.setVideoDataSource(VIDEO_URL, null, true);
+        mMediaCodecPlayer.start();
+        mMediaCodecPlayer.prepare();
+        mDrmInitData = mMediaCodecPlayer.getPsshInfo().get(CLEARKEY_SCHEME_UUID);
+
+        getKeys(mDrm, mSessionId, mDrmInitData);
+        // starts video playback
+        mMediaCodecPlayer.startThread();
+
+        long timeOut = System.currentTimeMillis() + PLAY_TIME_MS * 4;
+        while (timeOut > System.currentTimeMillis() && !mMediaCodecPlayer.isEnded()) {
+            Thread.sleep(SLEEP_TIME_MS);
+            if (mMediaCodecPlayer.getCurrentPosition() >= mMediaCodecPlayer.getDuration() ) {
+                Log.d(TAG, "current pos = " + mMediaCodecPlayer.getCurrentPosition() +
+                        ">= duration = " + mMediaCodecPlayer.getDuration());
+                break;
+            }
+        }
+
+        Log.d(TAG, "playVideo player.reset()");
+        mMediaCodecPlayer.reset();
+        closeSession(drm, mSessionId);
+        stopDrm(drm);
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/CodecState.java b/tests/tests/media/src/android/media/cts/CodecState.java
new file mode 100644
index 0000000..cd6b68f
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/CodecState.java
@@ -0,0 +1,347 @@
+/*
+ * 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.media.cts;
+
+import android.media.AudioTrack;
+import android.media.MediaCodec;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
+import android.util.Log;
+
+import java.nio.ByteBuffer;
+import java.util.LinkedList;
+
+/**
+ * Class for directly managing both audio and video playback by
+ * using {@link MediaCodec} and {@link AudioTrack}.
+ */
+public class CodecState {
+    private static final String TAG = CodecState.class.getSimpleName();
+
+    private boolean mSawInputEOS, mSawOutputEOS;
+    private boolean mLimitQueueDepth;
+    private ByteBuffer[] mCodecInputBuffers;
+    private ByteBuffer[] mCodecOutputBuffers;
+    private int mTrackIndex;
+    private LinkedList<Integer> mAvailableInputBufferIndices;
+    private LinkedList<Integer> mAvailableOutputBufferIndices;
+    private LinkedList<MediaCodec.BufferInfo> mAvailableOutputBufferInfos;
+    private long mPresentationTimeUs;
+    private MediaCodec mCodec;
+    private MediaCodecCencPlayer mMediaCodecPlayer;
+    private MediaExtractor mExtractor;
+    private MediaFormat mFormat;
+    private MediaFormat mOutputFormat;
+    private NonBlockingAudioTrack mAudioTrack;
+
+    /**
+     * Manages audio and video playback using MediaCodec and AudioTrack.
+     */
+    public CodecState(
+            MediaCodecCencPlayer mediaCodecPlayer,
+            MediaExtractor extractor,
+            int trackIndex,
+            MediaFormat format,
+            MediaCodec codec,
+            boolean limitQueueDepth) {
+
+        mMediaCodecPlayer = mediaCodecPlayer;
+        mExtractor = extractor;
+        mTrackIndex = trackIndex;
+        mFormat = format;
+        mSawInputEOS = mSawOutputEOS = false;
+        mLimitQueueDepth = limitQueueDepth;
+
+        mCodec = codec;
+
+        mAvailableInputBufferIndices = new LinkedList<Integer>();
+        mAvailableOutputBufferIndices = new LinkedList<Integer>();
+        mAvailableOutputBufferInfos = new LinkedList<MediaCodec.BufferInfo>();
+
+        mPresentationTimeUs = 0;
+    }
+
+    public void release() {
+        mCodec.stop();
+        mCodecInputBuffers = null;
+        mCodecOutputBuffers = null;
+        mOutputFormat = null;
+
+        mAvailableInputBufferIndices.clear();
+        mAvailableOutputBufferIndices.clear();
+        mAvailableOutputBufferInfos.clear();
+
+        mAvailableInputBufferIndices = null;
+        mAvailableOutputBufferIndices = null;
+        mAvailableOutputBufferInfos = null;
+
+        mCodec.release();
+        mCodec = null;
+
+        if (mAudioTrack != null) {
+            mAudioTrack.release();
+            mAudioTrack = null;
+        }
+    }
+
+    public void start() {
+        mCodec.start();
+        mCodecInputBuffers = mCodec.getInputBuffers();
+        mCodecOutputBuffers = mCodec.getOutputBuffers();
+
+        if (mAudioTrack != null) {
+            mAudioTrack.play();
+        }
+    }
+
+    public void pause() {
+        if (mAudioTrack != null) {
+            mAudioTrack.pause();
+        }
+    }
+
+    public long getCurrentPositionUs() {
+        return mPresentationTimeUs;
+    }
+
+    public void flush() {
+        mAvailableInputBufferIndices.clear();
+        mAvailableOutputBufferIndices.clear();
+        mAvailableOutputBufferInfos.clear();
+
+        mSawInputEOS = false;
+        mSawOutputEOS = false;
+
+        if (mAudioTrack != null
+                && mAudioTrack.getPlayState() == AudioTrack.PLAYSTATE_STOPPED) {
+            mAudioTrack.play();
+        }
+
+        mCodec.flush();
+    }
+
+    public boolean isEnded() {
+        return mSawInputEOS && mSawOutputEOS;
+    }
+
+    /**
+     * doSomeWork() is the worker function that does all buffer handling and decoding works.
+     * It first reads data from {@link MediaExtractor} and pushes it into {@link MediaCodec};
+     * it then dequeues buffer from {@link MediaCodec}, consumes it and pushes back to its own
+     * buffer queue for next round reading data from {@link MediaExtractor}.
+     */
+    public void doSomeWork() {
+        int indexInput = mCodec.dequeueInputBuffer(0 /* timeoutUs */);
+
+        if (indexInput != MediaCodec.INFO_TRY_AGAIN_LATER) {
+            mAvailableInputBufferIndices.add(indexInput);
+        }
+
+        while (feedInputBuffer()) {
+        }
+
+        MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
+        int indexOutput = mCodec.dequeueOutputBuffer(info, 0 /* timeoutUs */);
+
+        if (indexOutput == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+            mOutputFormat = mCodec.getOutputFormat();
+            onOutputFormatChanged();
+        } else if (indexOutput == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
+            mCodecOutputBuffers = mCodec.getOutputBuffers();
+        } else if (indexOutput != MediaCodec.INFO_TRY_AGAIN_LATER) {
+            mAvailableOutputBufferIndices.add(indexOutput);
+            mAvailableOutputBufferInfos.add(info);
+        }
+
+        while (drainOutputBuffer()) {
+        }
+    }
+
+    /** Returns true if more input data could be fed. */
+    private boolean feedInputBuffer() throws MediaCodec.CryptoException, IllegalStateException {
+        if (mSawInputEOS || mAvailableInputBufferIndices.isEmpty()) {
+            return false;
+        }
+
+        // stalls read if audio queue is larger than 2MB full so we will not occupy too much heap
+        if (mLimitQueueDepth && mAudioTrack != null &&
+                mAudioTrack.getNumBytesQueued() > 2 * 1024 * 1024) {
+            return false;
+        }
+
+        int index = mAvailableInputBufferIndices.peekFirst().intValue();
+
+        ByteBuffer codecData = mCodecInputBuffers[index];
+
+        int trackIndex = mExtractor.getSampleTrackIndex();
+
+        if (trackIndex == mTrackIndex) {
+            int sampleSize =
+                mExtractor.readSampleData(codecData, 0 /* offset */);
+
+            long sampleTime = mExtractor.getSampleTime();
+
+            int sampleFlags = mExtractor.getSampleFlags();
+
+            if (sampleSize <= 0) {
+                Log.d(TAG, "sampleSize: " + sampleSize + " trackIndex:" + trackIndex +
+                        " sampleTime:" + sampleTime + " sampleFlags:" + sampleFlags);
+                mSawInputEOS = true;
+                return false;
+            }
+
+            if ((sampleFlags & MediaExtractor.SAMPLE_FLAG_ENCRYPTED) != 0) {
+                MediaCodec.CryptoInfo info = new MediaCodec.CryptoInfo();
+                mExtractor.getSampleCryptoInfo(info);
+
+                mCodec.queueSecureInputBuffer(
+                        index, 0 /* offset */, info, sampleTime, 0 /* flags */);
+            } else {
+                mCodec.queueInputBuffer(
+                        index, 0 /* offset */, sampleSize, sampleTime, 0 /* flags */);
+            }
+
+            mAvailableInputBufferIndices.removeFirst();
+            mExtractor.advance();
+
+            return true;
+        } else if (trackIndex < 0) {
+            Log.d(TAG, "saw input EOS on track " + mTrackIndex);
+
+            mSawInputEOS = true;
+
+            mCodec.queueInputBuffer(
+                    index, 0 /* offset */, 0 /* sampleSize */,
+                    0 /* sampleTime */, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
+
+            mAvailableInputBufferIndices.removeFirst();
+        }
+
+        return false;
+    }
+
+    private void onOutputFormatChanged() {
+        String mime = mOutputFormat.getString(MediaFormat.KEY_MIME);
+        // b/9250789
+        Log.d(TAG, "CodecState::onOutputFormatChanged " + mime);
+
+        if (mime.startsWith("audio/")) {
+            int sampleRate =
+                mOutputFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE);
+
+            int channelCount =
+                mOutputFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
+
+            Log.d(TAG, "CodecState::onOutputFormatChanged Audio" +
+                    " sampleRate:" + sampleRate + " channels:" + channelCount);
+            // We do sanity check here after we receive data from MediaExtractor and before
+            // we pass them down to AudioTrack. If MediaExtractor works properly, this
+            // sanity-check is not necessary, however, in our tests, we found that there
+            // are a few cases where ch=0 and samplerate=0 were returned by MediaExtractor.
+            if (channelCount < 1 || channelCount > 8 ||
+                    sampleRate < 8000 || sampleRate > 128000) {
+                return;
+            }
+            mAudioTrack = new NonBlockingAudioTrack(sampleRate, channelCount);
+            mAudioTrack.play();
+        }
+
+        if (mime.startsWith("video/")) {
+            int width = mOutputFormat.getInteger(MediaFormat.KEY_WIDTH);
+            int height = mOutputFormat.getInteger(MediaFormat.KEY_HEIGHT);
+            Log.d(TAG, "CodecState::onOutputFormatChanged Video" +
+                    " width:" + width + " height:" + height);
+        }
+    }
+
+    /** Returns true if more output data could be drained. */
+    private boolean drainOutputBuffer() {
+        if (mSawOutputEOS || mAvailableOutputBufferIndices.isEmpty()) {
+            return false;
+        }
+
+        int index = mAvailableOutputBufferIndices.peekFirst().intValue();
+        MediaCodec.BufferInfo info = mAvailableOutputBufferInfos.peekFirst();
+
+        if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+            Log.d(TAG, "saw output EOS on track " + mTrackIndex);
+
+            mSawOutputEOS = true;
+
+            return false;
+        }
+
+        long realTimeUs =
+            mMediaCodecPlayer.getRealTimeUsForMediaTime(info.presentationTimeUs);
+
+        long nowUs = mMediaCodecPlayer.getNowUs();
+
+        long lateUs = nowUs - realTimeUs;
+
+        if (mAudioTrack != null) {
+            ByteBuffer buffer = mCodecOutputBuffers[index];
+            buffer.clear();
+            buffer.position(0 /* offset */);
+
+            byte[] audioCopy = new byte[info.size];
+            buffer.get(audioCopy, 0, info.size);
+
+            mAudioTrack.write(audioCopy, info.size);
+
+            mCodec.releaseOutputBuffer(index, false /* render */);
+
+            mPresentationTimeUs = info.presentationTimeUs;
+
+            mAvailableOutputBufferIndices.removeFirst();
+            mAvailableOutputBufferInfos.removeFirst();
+            return true;
+        } else {
+            // video
+            boolean render;
+
+            if (lateUs < -45000) {
+                // too early;
+                return false;
+            } else if (lateUs > 30000) {
+                Log.d(TAG, "video late by " + lateUs + " us.");
+                render = false;
+            } else {
+                render = true;
+                mPresentationTimeUs = info.presentationTimeUs;
+            }
+
+            mCodec.releaseOutputBuffer(index, render);
+
+            mAvailableOutputBufferIndices.removeFirst();
+            mAvailableOutputBufferInfos.removeFirst();
+            return true;
+        }
+    }
+
+    public long getAudioTimeUs() {
+        if (mAudioTrack == null) {
+            return 0;
+        }
+
+        return mAudioTrack.getAudioTimeUs();
+    }
+
+    public void process() {
+        if (mAudioTrack != null) {
+            mAudioTrack.process();
+        }
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/DecodeEditEncodeTest.java b/tests/tests/media/src/android/media/cts/DecodeEditEncodeTest.java
index 0d83647..9ee3118 100644
--- a/tests/tests/media/src/android/media/cts/DecodeEditEncodeTest.java
+++ b/tests/tests/media/src/android/media/cts/DecodeEditEncodeTest.java
@@ -149,7 +149,8 @@
     /**
      * Tests editing of a video file with GL.
      */
-    private void videoEditTest() {
+    private void videoEditTest()
+            throws IOException {
         VideoChunks sourceChunks = new VideoChunks();
 
         if (!generateVideoFile(sourceChunks)) {
@@ -182,23 +183,24 @@
      *
      * @return true on success, false on "soft" failure
      */
-    private boolean generateVideoFile(VideoChunks output) {
+    private boolean generateVideoFile(VideoChunks output)
+            throws IOException {
         if (VERBOSE) Log.d(TAG, "generateVideoFile " + mWidth + "x" + mHeight);
         MediaCodec encoder = null;
         InputSurface inputSurface = null;
 
         try {
-            MediaCodecInfo codecInfo = selectCodec(MIME_TYPE);
-            if (codecInfo == null) {
+            // We avoid the device-specific limitations on width and height by using values that
+            // are multiples of 16, which all tested devices seem to be able to handle.
+            MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);
+
+            String codecName = selectCodec(format);
+            if (codecName == null) {
                 // Don't fail CTS if they don't have an AVC codec (not here, anyway).
                 Log.e(TAG, "Unable to find an appropriate codec for " + MIME_TYPE);
                 return false;
             }
-            if (VERBOSE) Log.d(TAG, "found codec: " + codecInfo.getName());
-
-            // We avoid the device-specific limitations on width and height by using values that
-            // are multiples of 16, which all tested devices seem to be able to handle.
-            MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);
+            if (VERBOSE) Log.d(TAG, "found codec: " + codecName);
 
             // Set some properties.  Failing to specify some of these can cause the MediaCodec
             // configure() call to throw an unhelpful exception.
@@ -212,7 +214,7 @@
 
             // Create a MediaCodec for the desired codec, then configure it as an encoder with
             // our desired properties.
-            encoder = MediaCodec.createByCodecName(codecInfo.getName());
+            encoder = MediaCodec.createByCodecName(codecName);
             encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
             inputSurface = new InputSurface(encoder.createInputSurface());
             inputSurface.makeCurrent();
@@ -238,23 +240,9 @@
      * Returns the first codec capable of encoding the specified MIME type, or null if no
      * match was found.
      */
-    private static MediaCodecInfo selectCodec(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 codecInfo;
-                }
-            }
-        }
-        return null;
+    private static String selectCodec(MediaFormat format) {
+        MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+        return mcl.findEncoderForFormat(format);
     }
 
     /**
@@ -315,7 +303,7 @@
                     encoderOutputBuffers = encoder.getOutputBuffers();
                     if (VERBOSE) Log.d(TAG, "encoder output buffers changed");
                 } else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
-                    // not expected for an encoder
+                    // expected on API 18+
                     MediaFormat newFormat = encoder.getOutputFormat();
                     if (VERBOSE) Log.d(TAG, "encoder output format changed: " + newFormat);
                 } else if (encoderStatus < 0) {
@@ -393,7 +381,8 @@
      * for output and a Surface for input, we can avoid issues with obscure formats and can
      * use a fragment shader to do transformations.
      */
-    private VideoChunks editVideoFile(VideoChunks inputData) {
+    private VideoChunks editVideoFile(VideoChunks inputData)
+            throws IOException {
         if (VERBOSE) Log.d(TAG, "editVideoFile " + mWidth + "x" + mHeight);
         VideoChunks outputData = new VideoChunks();
         MediaCodec decoder = null;
@@ -613,7 +602,8 @@
      * Checks the video file to see if the contents match our expectations.  We decode the
      * video to a Surface and check the pixels with GL.
      */
-    private void checkVideoFile(VideoChunks inputData) {
+    private void checkVideoFile(VideoChunks inputData)
+            throws IOException {
         OutputSurface surface = null;
         MediaCodec decoder = null;
 
diff --git a/tests/tests/media/src/android/media/cts/DecoderTest.java b/tests/tests/media/src/android/media/cts/DecoderTest.java
index f250c3d..ba70f32 100644
--- a/tests/tests/media/src/android/media/cts/DecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/DecoderTest.java
@@ -20,6 +20,8 @@
 
 import android.content.res.AssetFileDescriptor;
 import android.content.res.Resources;
+import android.graphics.ImageFormat;
+import android.media.Image;
 import android.media.MediaCodec;
 import android.media.MediaCodecInfo;
 import android.media.MediaExtractor;
@@ -33,6 +35,7 @@
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 import java.util.zip.CRC32;
 
 public class DecoderTest extends MediaPlayerTestBase {
@@ -41,6 +44,12 @@
     private static final int RESET_MODE_NONE = 0;
     private static final int RESET_MODE_RECONFIGURE = 1;
     private static final int RESET_MODE_FLUSH = 2;
+    private static final int RESET_MODE_EOS_FLUSH = 3;
+
+    private static final String[] CSD_KEYS = new String[] { "csd-0", "csd-1" };
+
+    private static final int CONFIG_MODE_NONE = 0;
+    private static final int CONFIG_MODE_QUEUE = 1;
 
     private Resources mResources;
     short[] mMasterBuffer;
@@ -69,43 +78,390 @@
         masterFd.close();
     }
 
+    // TODO: add similar tests for other audio and video formats
+    public void testBug11696552() throws Exception {
+        MediaCodec mMediaCodec = MediaCodec.createDecoderByType("audio/mp4a-latm");
+        MediaFormat mFormat = MediaFormat.createAudioFormat("audio/mp4a-latm", 48000, 2);
+        mFormat.setByteBuffer("csd-0", ByteBuffer.wrap( new byte [] {0x13, 0x10} ));
+        mFormat.setInteger(MediaFormat.KEY_IS_ADTS, 1);
+        mMediaCodec.configure(mFormat, null, null, 0);
+        mMediaCodec.start();
+        int index = mMediaCodec.dequeueInputBuffer(250000);
+        mMediaCodec.queueInputBuffer(index, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM );
+        MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
+        mMediaCodec.dequeueOutputBuffer(info, 250000);
+    }
+
     // The allowed errors in the following tests are the actual maximum measured
     // errors with the standard decoders, plus 10%.
     // This should allow for some variation in decoders, while still detecting
     // phase and delay errors, channel swap, etc.
     public void testDecodeMp3Lame() throws Exception {
         decode(R.raw.sinesweepmp3lame, 804.f);
+        testTimeStampOrdering(R.raw.sinesweepmp3lame);
     }
     public void testDecodeMp3Smpb() throws Exception {
         decode(R.raw.sinesweepmp3smpb, 413.f);
+        testTimeStampOrdering(R.raw.sinesweepmp3smpb);
     }
     public void testDecodeM4a() throws Exception {
         decode(R.raw.sinesweepm4a, 124.f);
+        testTimeStampOrdering(R.raw.sinesweepm4a);
     }
     public void testDecodeOgg() throws Exception {
         decode(R.raw.sinesweepogg, 168.f);
+        testTimeStampOrdering(R.raw.sinesweepogg);
     }
     public void testDecodeWav() throws Exception {
         decode(R.raw.sinesweepwav, 0.0f);
+        testTimeStampOrdering(R.raw.sinesweepwav);
     }
     public void testDecodeFlac() throws Exception {
         decode(R.raw.sinesweepflac, 0.0f);
+        testTimeStampOrdering(R.raw.sinesweepflac);
     }
 
     public void testDecodeMonoMp3() throws Exception {
         monoTest(R.raw.monotestmp3);
+        testTimeStampOrdering(R.raw.monotestmp3);
     }
 
     public void testDecodeMonoM4a() throws Exception {
         monoTest(R.raw.monotestm4a);
+        testTimeStampOrdering(R.raw.monotestm4a);
     }
 
     public void testDecodeMonoOgg() throws Exception {
         monoTest(R.raw.monotestogg);
+        testTimeStampOrdering(R.raw.monotestogg);
     }
 
+    public void testDecodeAacTs() throws Exception {
+        testTimeStampOrdering(R.raw.sinesweeptsaac);
+    }
+
+    public void testDecode51M4a() throws Exception {
+        decodeToMemory(R.raw.sinesweep51m4a, RESET_MODE_NONE, CONFIG_MODE_NONE, -1, null);
+    }
+
+    private void testTimeStampOrdering(int res) throws Exception {
+        List<Long> timestamps = new ArrayList<Long>();
+        decodeToMemory(res, RESET_MODE_NONE, CONFIG_MODE_NONE, -1, timestamps);
+        Long lastTime = Long.MIN_VALUE;
+        for (int i = 0; i < timestamps.size(); i++) {
+            Long thisTime = timestamps.get(i);
+            assertTrue("timetravel occurred: " + lastTime + " > " + thisTime, thisTime >= lastTime);
+            lastTime = thisTime;
+        }
+    }
+
+    public void testTrackSelection() throws Exception {
+        testTrackSelection(R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz);
+        testTrackSelection(
+                R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz_fragmented);
+        testTrackSelection(
+                R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz_dash);
+    }
+
+    public void testBFrames() throws Exception {
+        testBFrames(R.raw.video_h264_main_b_frames);
+        testBFrames(R.raw.video_h264_main_b_frames_frag);
+    }
+
+    public void testBFrames(int res) throws Exception {
+        AssetFileDescriptor fd = mResources.openRawResourceFd(res);
+        MediaExtractor ex = new MediaExtractor();
+        ex.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
+        MediaFormat format = ex.getTrackFormat(0);
+        String mime = format.getString(MediaFormat.KEY_MIME);
+        assertTrue("not a video track. Wrong test file?", mime.startsWith("video/"));
+        MediaCodec dec = MediaCodec.createDecoderByType(mime);
+        Surface s = getActivity().getSurfaceHolder().getSurface();
+        dec.configure(format, s, null, 0);
+        dec.start();
+        ByteBuffer[] buf = dec.getInputBuffers();
+        ex.selectTrack(0);
+        MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
+        long lastPresentationTimeUsFromExtractor = -1;
+        long lastPresentationTimeUsFromDecoder = -1;
+        boolean inputoutoforder = false;
+        while(true) {
+            int flags = ex.getSampleFlags();
+            long time = ex.getSampleTime();
+            if (time >= 0 && time < lastPresentationTimeUsFromExtractor) {
+                inputoutoforder = true;
+            }
+            lastPresentationTimeUsFromExtractor = time;
+            int bufidx = dec.dequeueInputBuffer(5000);
+            if (bufidx >= 0) {
+                int n = ex.readSampleData(buf[bufidx], 0);
+                if (n < 0) {
+                    flags = MediaCodec.BUFFER_FLAG_END_OF_STREAM;
+                    time = 0;
+                    n = 0;
+                }
+                dec.queueInputBuffer(bufidx, 0, n, time, flags);
+                ex.advance();
+            }
+            int status = dec.dequeueOutputBuffer(info, 5000);
+            if (status >= 0) {
+                if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+                    break;
+                }
+                assertTrue("out of order timestamp from decoder",
+                        info.presentationTimeUs > lastPresentationTimeUsFromDecoder);
+                dec.releaseOutputBuffer(status, true);
+                lastPresentationTimeUsFromDecoder = info.presentationTimeUs;
+            }
+        }
+        assertTrue("extractor timestamps were ordered, wrong test file?", inputoutoforder);
+        dec.release();
+        ex.release();
+      }
+
+    private void testTrackSelection(int resid) throws Exception {
+        AssetFileDescriptor fd1 = null;
+        try {
+            fd1 = mResources.openRawResourceFd(resid);
+            MediaExtractor ex1 = new MediaExtractor();
+            ex1.setDataSource(fd1.getFileDescriptor(), fd1.getStartOffset(), fd1.getLength());
+
+            ByteBuffer buf1 = ByteBuffer.allocate(1024*1024);
+            ArrayList<Integer> vid = new ArrayList<Integer>();
+            ArrayList<Integer> aud = new ArrayList<Integer>();
+
+            // scan the file once and build lists of audio and video samples
+            ex1.selectTrack(0);
+            ex1.selectTrack(1);
+            while(true) {
+                int n1 = ex1.readSampleData(buf1, 0);
+                if (n1 < 0) {
+                    break;
+                }
+                int idx = ex1.getSampleTrackIndex();
+                if (idx == 0) {
+                    vid.add(n1);
+                } else if (idx == 1) {
+                    aud.add(n1);
+                } else {
+                    fail("unexpected track index: " + idx);
+                }
+                ex1.advance();
+            }
+
+            // read the video track once, then rewind and do it again, and
+            // verify we get the right samples
+            ex1.release();
+            ex1 = new MediaExtractor();
+            ex1.setDataSource(fd1.getFileDescriptor(), fd1.getStartOffset(), fd1.getLength());
+            ex1.selectTrack(0);
+            for (int i = 0; i < 2; i++) {
+                ex1.seekTo(0, MediaExtractor.SEEK_TO_NEXT_SYNC);
+                int idx = 0;
+                while(true) {
+                    int n1 = ex1.readSampleData(buf1, 0);
+                    if (n1 < 0) {
+                        assertEquals(vid.size(), idx);
+                        break;
+                    }
+                    assertEquals(vid.get(idx++).intValue(), n1);
+                    ex1.advance();
+                }
+            }
+
+            // read the audio track once, then rewind and do it again, and
+            // verify we get the right samples
+            ex1.release();
+            ex1 = new MediaExtractor();
+            ex1.setDataSource(fd1.getFileDescriptor(), fd1.getStartOffset(), fd1.getLength());
+            ex1.selectTrack(1);
+            for (int i = 0; i < 2; i++) {
+                ex1.seekTo(0, MediaExtractor.SEEK_TO_NEXT_SYNC);
+                int idx = 0;
+                while(true) {
+                    int n1 = ex1.readSampleData(buf1, 0);
+                    if (n1 < 0) {
+                        assertEquals(aud.size(), idx);
+                        break;
+                    }
+                    assertEquals(aud.get(idx++).intValue(), n1);
+                    ex1.advance();
+                }
+            }
+
+            // read the video track first, then rewind and get the audio track instead, and
+            // verify we get the right samples
+            ex1.release();
+            ex1 = new MediaExtractor();
+            ex1.setDataSource(fd1.getFileDescriptor(), fd1.getStartOffset(), fd1.getLength());
+            for (int i = 0; i < 2; i++) {
+                ex1.selectTrack(i);
+                ex1.seekTo(0, MediaExtractor.SEEK_TO_NEXT_SYNC);
+                int idx = 0;
+                while(true) {
+                    int n1 = ex1.readSampleData(buf1, 0);
+                    if (i == 0) {
+                        if (n1 < 0) {
+                            assertEquals(vid.size(), idx);
+                            break;
+                        }
+                        assertEquals(vid.get(idx++).intValue(), n1);
+                    } else if (i == 1) {
+                        if (n1 < 0) {
+                            assertEquals(aud.size(), idx);
+                            break;
+                        }
+                        assertEquals(aud.get(idx++).intValue(), n1);
+                    } else {
+                        fail("unexpected track index: " + idx);
+                    }
+                    ex1.advance();
+                }
+                ex1.unselectTrack(i);
+            }
+
+            // read the video track first, then rewind, enable the audio track in addition
+            // to the video track, and verify we get the right samples
+            ex1.release();
+            ex1 = new MediaExtractor();
+            ex1.setDataSource(fd1.getFileDescriptor(), fd1.getStartOffset(), fd1.getLength());
+            for (int i = 0; i < 2; i++) {
+                ex1.selectTrack(i);
+                ex1.seekTo(0, MediaExtractor.SEEK_TO_NEXT_SYNC);
+                int vididx = 0;
+                int audidx = 0;
+                while(true) {
+                    int n1 = ex1.readSampleData(buf1, 0);
+                    if (n1 < 0) {
+                        // we should have read all audio and all video samples at this point
+                        assertEquals(vid.size(), vididx);
+                        if (i == 1) {
+                            assertEquals(aud.size(), audidx);
+                        }
+                        break;
+                    }
+                    int trackidx = ex1.getSampleTrackIndex();
+                    if (trackidx == 0) {
+                        assertEquals(vid.get(vididx++).intValue(), n1);
+                    } else if (trackidx == 1) {
+                        assertEquals(aud.get(audidx++).intValue(), n1);
+                    } else {
+                        fail("unexpected track index: " + trackidx);
+                    }
+                    ex1.advance();
+                }
+            }
+
+            // read both tracks from the start, then rewind and verify we get the right
+            // samples both times
+            ex1.release();
+            ex1 = new MediaExtractor();
+            ex1.setDataSource(fd1.getFileDescriptor(), fd1.getStartOffset(), fd1.getLength());
+            for (int i = 0; i < 2; i++) {
+                ex1.selectTrack(0);
+                ex1.selectTrack(1);
+                ex1.seekTo(0, MediaExtractor.SEEK_TO_NEXT_SYNC);
+                int vididx = 0;
+                int audidx = 0;
+                while(true) {
+                    int n1 = ex1.readSampleData(buf1, 0);
+                    if (n1 < 0) {
+                        // we should have read all audio and all video samples at this point
+                        assertEquals(vid.size(), vididx);
+                        assertEquals(aud.size(), audidx);
+                        break;
+                    }
+                    int trackidx = ex1.getSampleTrackIndex();
+                    if (trackidx == 0) {
+                        assertEquals(vid.get(vididx++).intValue(), n1);
+                    } else if (trackidx == 1) {
+                        assertEquals(aud.get(audidx++).intValue(), n1);
+                    } else {
+                        fail("unexpected track index: " + trackidx);
+                    }
+                    ex1.advance();
+                }
+            }
+
+        } finally {
+            if (fd1 != null) {
+                fd1.close();
+            }
+        }
+    }
+
+    public void testDecodeFragmented() throws Exception {
+        testDecodeFragmented(R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz,
+                R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz_fragmented);
+        testDecodeFragmented(R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz,
+                R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz_dash);
+    }
+
+    private void testDecodeFragmented(int reference, int teststream) throws Exception {
+        AssetFileDescriptor fd1 = null;
+        AssetFileDescriptor fd2 = null;
+        try {
+            fd1 = mResources.openRawResourceFd(reference);
+            MediaExtractor ex1 = new MediaExtractor();
+            ex1.setDataSource(fd1.getFileDescriptor(), fd1.getStartOffset(), fd1.getLength());
+
+            fd2 = mResources.openRawResourceFd(teststream);
+            MediaExtractor ex2 = new MediaExtractor();
+            ex2.setDataSource(fd2.getFileDescriptor(), fd2.getStartOffset(), fd2.getLength());
+
+            assertEquals("different track count", ex1.getTrackCount(), ex2.getTrackCount());
+
+            ByteBuffer buf1 = ByteBuffer.allocate(1024*1024);
+            ByteBuffer buf2 = ByteBuffer.allocate(1024*1024);
+
+            for (int i = 0; i < ex1.getTrackCount(); i++) {
+                // note: this assumes the tracks are reported in the order in which they appear
+                // in the file.
+                ex1.seekTo(0, MediaExtractor.SEEK_TO_NEXT_SYNC);
+                ex1.selectTrack(i);
+                ex2.seekTo(0, MediaExtractor.SEEK_TO_NEXT_SYNC);
+                ex2.selectTrack(i);
+
+                while(true) {
+                    int n1 = ex1.readSampleData(buf1, 0);
+                    int n2 = ex2.readSampleData(buf2, 0);
+                    assertEquals("different buffer size on track " + i, n1, n2);
+
+                    if (n1 < 0) {
+                        break;
+                    }
+                    // see bug 13008204
+                    buf1.limit(n1);
+                    buf2.limit(n2);
+                    buf1.rewind();
+                    buf2.rewind();
+
+                    assertEquals("limit does not match return value on track " + i,
+                            n1, buf1.limit());
+                    assertEquals("limit does not match return value on track " + i,
+                            n2, buf2.limit());
+
+                    assertEquals("buffer data did not match on track " + i, buf1, buf2);
+
+                    ex1.advance();
+                    ex2.advance();
+                }
+                ex1.unselectTrack(i);
+                ex2.unselectTrack(i);
+            }
+        } finally {
+            if (fd1 != null) {
+                fd1.close();
+            }
+            if (fd2 != null) {
+                fd2.close();
+            }
+        }
+    }
+
+
     private void monoTest(int res) throws Exception {
-        short [] mono = decodeToMemory(res, RESET_MODE_NONE);
+        short [] mono = decodeToMemory(res, RESET_MODE_NONE, CONFIG_MODE_NONE, -1, null);
         if (mono.length == 44100) {
             // expected
         } else if (mono.length == 88200) {
@@ -118,14 +474,11 @@
             fail("wrong number of samples: " + mono.length);
         }
 
-        // we should get the same data when reconfiguring the codec
-        short [] mono2 = decodeToMemory(res, RESET_MODE_RECONFIGURE);
+        short [] mono2 = decodeToMemory(res, RESET_MODE_RECONFIGURE, CONFIG_MODE_NONE, -1, null);
         assertTrue(Arrays.equals(mono, mono2));
 
-        // NOTE: coming soon
-        // and when flushing it
-//        short [] mono3 = decodeToMemory(res, RESET_MODE_FLUSH);
-//        assertTrue(Arrays.equals(mono, mono3));
+        short [] mono3 = decodeToMemory(res, RESET_MODE_FLUSH, CONFIG_MODE_NONE, -1, null);
+        assertTrue(Arrays.equals(mono, mono3));
     }
 
     /**
@@ -135,7 +488,7 @@
      */
     private void decode(int testinput, float maxerror) throws IOException {
 
-        short [] decoded = decodeToMemory(testinput, RESET_MODE_NONE);
+        short[] decoded = decodeToMemory(testinput, RESET_MODE_NONE, CONFIG_MODE_NONE, -1, null);
 
         assertEquals("wrong data size", mMasterBuffer.length, decoded.length);
 
@@ -152,22 +505,54 @@
         double rmse = Math.sqrt(avgErrorSquared);
         assertTrue("decoding error too big: " + rmse, rmse <= maxerror);
 
-        short [] decoded2 = decodeToMemory(testinput, RESET_MODE_RECONFIGURE);
-        assertEquals("count different with reconfigure", decoded.length, decoded2.length);
-        for (int i = 0; i < decoded.length; i++) {
-            assertEquals("samples don't match", decoded[i], decoded2[i]);
-        }
+        int[] resetModes = new int[] { RESET_MODE_NONE, RESET_MODE_RECONFIGURE,
+                RESET_MODE_FLUSH, RESET_MODE_EOS_FLUSH };
+        int[] configModes = new int[] { CONFIG_MODE_NONE, CONFIG_MODE_QUEUE };
 
-        // NOTE: coming soon
-//        short [] decoded3 = decodeToMemory(testinput, RESET_MODE_FLUSH);
-//        assertEquals("count different with flush", decoded.length, decoded3.length);
-//        for (int i = 0; i < decoded.length; i++) {
-//            assertEquals("samples don't match", decoded[i], decoded3[i]);
-//        }
+        for (int conf : configModes) {
+            for (int reset : resetModes) {
+                if (conf == CONFIG_MODE_NONE && reset == RESET_MODE_NONE) {
+                    // default case done outside of loop
+                    continue;
+                }
+                if (conf == CONFIG_MODE_QUEUE && !hasAudioCsd(testinput)) {
+                    continue;
+                }
+
+                String params = String.format("(using reset: %d, config: %s)", reset, conf);
+                short[] decoded2 = decodeToMemory(testinput, reset, conf, -1, null);
+                assertEquals("count different with reconfigure" + params,
+                        decoded.length, decoded2.length);
+                for (int i = 0; i < decoded.length; i++) {
+                    assertEquals("samples don't match" + params, decoded[i], decoded2[i]);
+                }
+            }
+        }
     }
 
-    private short[] decodeToMemory(int testinput, int resetMode) throws IOException {
+    private boolean hasAudioCsd(int testinput) throws IOException {
+        AssetFileDescriptor fd = null;
+        try {
 
+            fd = mResources.openRawResourceFd(testinput);
+            MediaExtractor extractor = new MediaExtractor();
+            extractor.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
+            MediaFormat format = extractor.getTrackFormat(0);
+
+            return format.containsKey(CSD_KEYS[0]);
+
+        } finally {
+            if (fd != null) {
+                fd.close();
+            }
+        }
+    }
+
+    private short[] decodeToMemory(int testinput, int resetMode, int configMode,
+            int eossample, List<Long> timestamps) throws IOException {
+
+        String localTag = TAG + "#decodeToMemory";
+        Log.v(localTag, String.format("reset = %d; config: %s", resetMode, configMode));
         short [] decoded = new short[0];
         int decodedIdx = 0;
 
@@ -188,15 +573,32 @@
         String mime = format.getString(MediaFormat.KEY_MIME);
         assertTrue("not an audio file", mime.startsWith("audio/"));
 
+        MediaFormat configFormat = format;
         codec = MediaCodec.createDecoderByType(mime);
-        codec.configure(format, null /* surface */, null /* crypto */, 0 /* flags */);
+        if (configMode == CONFIG_MODE_QUEUE && format.containsKey(CSD_KEYS[0])) {
+            configFormat = MediaFormat.createAudioFormat(mime,
+                    format.getInteger(MediaFormat.KEY_SAMPLE_RATE),
+                    format.getInteger(MediaFormat.KEY_CHANNEL_COUNT));
+
+            configFormat.setLong(MediaFormat.KEY_DURATION,
+                    format.getLong(MediaFormat.KEY_DURATION));
+            String[] keys = new String[] { "max-input-size", "encoder-delay", "encoder-padding" };
+            for (String k : keys) {
+                if (format.containsKey(k)) {
+                    configFormat.setInteger(k, format.getInteger(k));
+                }
+            }
+        }
+        Log.v(localTag, "configuring with " + configFormat);
+        codec.configure(configFormat, null /* surface */, null /* crypto */, 0 /* flags */);
+
         codec.start();
         codecInputBuffers = codec.getInputBuffers();
         codecOutputBuffers = codec.getOutputBuffers();
 
         if (resetMode == RESET_MODE_RECONFIGURE) {
             codec.stop();
-            codec.configure(format, null /* surface */, null /* crypto */, 0 /* flags */);
+            codec.configure(configFormat, null /* surface */, null /* crypto */, 0 /* flags */);
             codec.start();
             codecInputBuffers = codec.getInputBuffers();
             codecOutputBuffers = codec.getOutputBuffers();
@@ -206,12 +608,17 @@
 
         extractor.selectTrack(0);
 
+        if (configMode == CONFIG_MODE_QUEUE) {
+            queueConfig(codec, format);
+        }
+
         // start decoding
         final long kTimeOutUs = 5000;
         MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
         boolean sawInputEOS = false;
         boolean sawOutputEOS = false;
         int noOutputCounter = 0;
+        int samplecounter = 0;
         while (!sawOutputEOS && noOutputCounter < 50) {
             noOutputCounter++;
             if (!sawInputEOS) {
@@ -225,14 +632,20 @@
 
                     long presentationTimeUs = 0;
 
+                    if (sampleSize < 0 && eossample > 0) {
+                        fail("test is broken: never reached eos sample");
+                    }
                     if (sampleSize < 0) {
                         Log.d(TAG, "saw input EOS.");
                         sawInputEOS = true;
                         sampleSize = 0;
                     } else {
+                        if (samplecounter == eossample) {
+                            sawInputEOS = true;
+                        }
+                        samplecounter++;
                         presentationTimeUs = extractor.getSampleTime();
                     }
-
                     codec.queueInputBuffer(
                             inputBufIndex,
                             0 /* offset */,
@@ -253,22 +666,33 @@
 
                 if (info.size > 0) {
                     noOutputCounter = 0;
+                    if (timestamps != null) {
+                        timestamps.add(info.presentationTimeUs);
+                    }
                 }
-                if (info.size > 0 && resetMode != RESET_MODE_NONE) {
+                if (info.size > 0 &&
+                        resetMode != RESET_MODE_NONE && resetMode != RESET_MODE_EOS_FLUSH) {
                     // once we've gotten some data out of the decoder, reset and start again
                     if (resetMode == RESET_MODE_RECONFIGURE) {
                         codec.stop();
-                        codec.configure(format, null /* surface */, null /* crypto */,
+                        codec.configure(configFormat, null /* surface */, null /* crypto */,
                                 0 /* flags */);
                         codec.start();
                         codecInputBuffers = codec.getInputBuffers();
                         codecOutputBuffers = codec.getOutputBuffers();
+                        if (configMode == CONFIG_MODE_QUEUE) {
+                            queueConfig(codec, format);
+                        }
                     } else /* resetMode == RESET_MODE_FLUSH */ {
                         codec.flush();
                     }
                     resetMode = RESET_MODE_NONE;
                     extractor.seekTo(0, MediaExtractor.SEEK_TO_NEXT_SYNC);
                     sawInputEOS = false;
+                    samplecounter = 0;
+                    if (timestamps != null) {
+                        timestamps.clear();
+                    }
                     continue;
                 }
 
@@ -279,15 +703,29 @@
                     decoded = Arrays.copyOf(decoded, decodedIdx + (info.size / 2));
                 }
 
+                buf.position(info.offset);
                 for (int i = 0; i < info.size; i += 2) {
-                    decoded[decodedIdx++] = buf.getShort(i);
+                    decoded[decodedIdx++] = buf.getShort();
                 }
 
                 codec.releaseOutputBuffer(outputBufIndex, false /* render */);
 
                 if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                     Log.d(TAG, "saw output EOS.");
-                    sawOutputEOS = true;
+                    if (resetMode == RESET_MODE_EOS_FLUSH) {
+                        resetMode = RESET_MODE_NONE;
+                        codec.flush();
+                        extractor.seekTo(0, MediaExtractor.SEEK_TO_NEXT_SYNC);
+                        sawInputEOS = false;
+                        samplecounter = 0;
+                        decoded = new short[0];
+                        decodedIdx = 0;
+                        if (timestamps != null) {
+                            timestamps.clear();
+                        }
+                    } else {
+                        sawOutputEOS = true;
+                    }
                 }
             } else if (res == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
                 codecOutputBuffers = codec.getOutputBuffers();
@@ -301,12 +739,106 @@
                 Log.d(TAG, "dequeueOutputBuffer returned " + res);
             }
         }
+        if (noOutputCounter >= 50) {
+            fail("decoder stopped outputing data");
+        }
 
         codec.stop();
         codec.release();
         return decoded;
     }
 
+    private void queueConfig(MediaCodec codec, MediaFormat format) {
+        for (String csdKey : CSD_KEYS) {
+            if (!format.containsKey(csdKey)) {
+                continue;
+            }
+            ByteBuffer[] codecInputBuffers = codec.getInputBuffers();
+            int inputBufIndex = codec.dequeueInputBuffer(-1);
+            if (inputBufIndex < 0) {
+                fail("failed to queue configuration buffer " + csdKey);
+            } else {
+                ByteBuffer csd = (ByteBuffer) format.getByteBuffer(csdKey).rewind();
+                Log.v(TAG + "#queueConfig", String.format("queueing %s:%s", csdKey, csd));
+                codecInputBuffers[inputBufIndex].put(csd);
+                codec.queueInputBuffer(
+                        inputBufIndex,
+                        0 /* offset */,
+                        csd.limit(),
+                        0 /* presentation time (us) */,
+                        MediaCodec.BUFFER_FLAG_CODEC_CONFIG);
+            }
+        }
+    }
+
+    public void testDecodeWithEOSOnLastBuffer() throws Exception {
+        testDecodeWithEOSOnLastBuffer(R.raw.sinesweepm4a);
+        testDecodeWithEOSOnLastBuffer(R.raw.sinesweepmp3lame);
+        testDecodeWithEOSOnLastBuffer(R.raw.sinesweepmp3smpb);
+        testDecodeWithEOSOnLastBuffer(R.raw.sinesweepwav);
+        testDecodeWithEOSOnLastBuffer(R.raw.sinesweepflac);
+        testDecodeWithEOSOnLastBuffer(R.raw.sinesweepogg);
+    }
+
+    /* setting EOS on the last full input buffer should be equivalent to setting EOS on an empty
+     * input buffer after all the full ones. */
+    private void testDecodeWithEOSOnLastBuffer(int res) throws Exception {
+        int numsamples = countSamples(res);
+        assertTrue(numsamples != 0);
+
+        List<Long> timestamps1 = new ArrayList<Long>();
+        short[] decode1 = decodeToMemory(res, RESET_MODE_NONE, CONFIG_MODE_NONE, -1, timestamps1);
+
+        List<Long> timestamps2 = new ArrayList<Long>();
+        short[] decode2 = decodeToMemory(res, RESET_MODE_NONE, CONFIG_MODE_NONE, numsamples - 1,
+                timestamps2);
+
+        // check that the data and the timestamps are the same for EOS-on-last and EOS-after-last
+        assertEquals(decode1.length, decode2.length);
+        assertTrue(Arrays.equals(decode1, decode2));
+        assertEquals(timestamps1.size(), timestamps2.size());
+        assertTrue(timestamps1.equals(timestamps2));
+
+        // ... and that this is also true when reconfiguring the codec
+        timestamps2.clear();
+        decode2 = decodeToMemory(res, RESET_MODE_RECONFIGURE, CONFIG_MODE_NONE, -1, timestamps2);
+        assertTrue(Arrays.equals(decode1, decode2));
+        assertTrue(timestamps1.equals(timestamps2));
+        timestamps2.clear();
+        decode2 = decodeToMemory(res, RESET_MODE_RECONFIGURE, CONFIG_MODE_NONE, numsamples - 1,
+                timestamps2);
+        assertEquals(decode1.length, decode2.length);
+        assertTrue(Arrays.equals(decode1, decode2));
+        assertTrue(timestamps1.equals(timestamps2));
+
+        // ... and that this is also true when flushing the codec
+        timestamps2.clear();
+        decode2 = decodeToMemory(res, RESET_MODE_FLUSH, CONFIG_MODE_NONE, -1, timestamps2);
+        assertTrue(Arrays.equals(decode1, decode2));
+        assertTrue(timestamps1.equals(timestamps2));
+        timestamps2.clear();
+        decode2 = decodeToMemory(res, RESET_MODE_FLUSH, CONFIG_MODE_NONE, numsamples - 1,
+                timestamps2);
+        assertEquals(decode1.length, decode2.length);
+        assertTrue(Arrays.equals(decode1, decode2));
+        assertTrue(timestamps1.equals(timestamps2));
+    }
+
+    private int countSamples(int res) throws IOException {
+        AssetFileDescriptor testFd = mResources.openRawResourceFd(res);
+
+        MediaExtractor extractor = new MediaExtractor();
+        extractor.setDataSource(testFd.getFileDescriptor(), testFd.getStartOffset(),
+                testFd.getLength());
+        testFd.close();
+        extractor.selectTrack(0);
+        int numsamples = 0;
+        while (extractor.advance()) {
+            numsamples++;
+        }
+        return numsamples;
+    }
+
     public void testCodecBasicH264() throws Exception {
         Surface s = getActivity().getSurfaceHolder().getSurface();
         int frames1 = countFrames(
@@ -320,6 +852,19 @@
         assertEquals("different number of frames when using Surface", frames1, frames2);
     }
 
+    public void testCodecBasicHEVC() throws Exception {
+        Surface s = getActivity().getSurfaceHolder().getSurface();
+        int frames1 = countFrames(
+                R.raw.video_1280x720_mp4_hevc_1150kbps_30fps_aac_stereo_128kbps_48000hz,
+                RESET_MODE_NONE, -1 /* eosframe */, s);
+        assertEquals("wrong number of frames decoded", 300, frames1);
+
+        int frames2 = countFrames(
+                R.raw.video_1280x720_mp4_hevc_1150kbps_30fps_aac_stereo_128kbps_48000hz,
+                RESET_MODE_NONE, -1 /* eosframe */, null);
+        assertEquals("different number of frames when using Surface", frames1, frames2);
+    }
+
     public void testCodecBasicH263() throws Exception {
         Surface s = getActivity().getSurfaceHolder().getSurface();
         int frames1 = countFrames(
@@ -388,6 +933,14 @@
         assertEquals("wrong number of frames decoded", 120, frames1);
     }
 
+    public void testCodecEarlyEOSHEVC() throws Exception {
+        Surface s = getActivity().getSurfaceHolder().getSurface();
+        int frames1 = countFrames(
+                R.raw.video_1280x720_mp4_hevc_1150kbps_30fps_aac_stereo_128kbps_48000hz,
+                RESET_MODE_NONE, 120 /* eosframe */, s);
+        assertEquals("wrong number of frames decoded", 120, frames1);
+    }
+
     public void testCodecEarlyEOSMpeg4() throws Exception {
         Surface s = getActivity().getSurfaceHolder().getSurface();
         int frames1 = countFrames(
@@ -423,6 +976,17 @@
                 R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz, s);
     }
 
+    public void testCodecResetsHEVCWithoutSurface() throws Exception {
+        testCodecResets(
+                R.raw.video_1280x720_mp4_hevc_1150kbps_30fps_aac_stereo_128kbps_48000hz, null);
+    }
+
+    public void testCodecResetsHEVCWithSurface() throws Exception {
+        Surface s = getActivity().getSurfaceHolder().getSurface();
+        testCodecResets(
+                R.raw.video_1280x720_mp4_hevc_1150kbps_30fps_aac_stereo_128kbps_48000hz, s);
+    }
+
     public void testCodecResetsH263WithoutSurface() throws Exception {
         testCodecResets(
                 R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz, null);
@@ -472,21 +1036,21 @@
 //    }
 
     public void testCodecResetsMp3() throws Exception {
-        testCodecReconfig(R.raw.sinesweepmp3lame, null);
+        testCodecReconfig(R.raw.sinesweepmp3lame);
         // NOTE: replacing testCodecReconfig call soon
 //        testCodecResets(R.raw.sinesweepmp3lame, null);
     }
 
     public void testCodecResetsM4a() throws Exception {
-        testCodecReconfig(R.raw.sinesweepm4a, null);
+        testCodecReconfig(R.raw.sinesweepm4a);
         // NOTE: replacing testCodecReconfig call soon
 //        testCodecResets(R.raw.sinesweepm4a, null);
     }
 
-    private void testCodecReconfig(int video, Surface s) throws Exception {
-        int frames1 = countFrames(video, RESET_MODE_NONE, -1 /* eosframe */, s);
-        int frames2 = countFrames(video, RESET_MODE_RECONFIGURE, -1 /* eosframe */, s);
-        assertEquals("different number of frames when using reconfigured codec", frames1, frames2);
+    private void testCodecReconfig(int audio) throws Exception {
+        int size1 = countSize(audio, RESET_MODE_NONE, -1 /* eosframe */);
+        int size2 = countSize(audio, RESET_MODE_RECONFIGURE, -1 /* eosframe */);
+        assertEquals("different output size when using reconfigured codec", size1, size2);
     }
 
     private void testCodecResets(int video, Surface s) throws Exception {
@@ -497,55 +1061,148 @@
         assertEquals("different number of frames when using flushed codec", frames1, frames3);
     }
 
-    private MediaCodec createDecoder(String mime) {
-        if (false) {
-            // change to force testing software codecs
-            if (mime.contains("avc")) {
-                return MediaCodec.createByCodecName("OMX.google.h264.decoder");
-            } else if (mime.contains("3gpp")) {
-                return MediaCodec.createByCodecName("OMX.google.h263.decoder");
-            } else if (mime.contains("mp4v")) {
-                return MediaCodec.createByCodecName("OMX.google.mpeg4.decoder");
-            } else if (mime.contains("vp8")) {
-                return MediaCodec.createByCodecName("OMX.google.vp8.decoder");
-            } else if (mime.contains("vp9")) {
-                return MediaCodec.createByCodecName("OMX.google.vp9.decoder");
+    private static MediaCodec createDecoder(String mime) {
+        try {
+            if (false) {
+                // change to force testing software codecs
+                if (mime.contains("avc")) {
+                    return MediaCodec.createByCodecName("OMX.google.h264.decoder");
+                } else if (mime.contains("hevc")) {
+                    return MediaCodec.createByCodecName("OMX.google.hevc.decoder");
+                } else if (mime.contains("3gpp")) {
+                    return MediaCodec.createByCodecName("OMX.google.h263.decoder");
+                } else if (mime.contains("mp4v")) {
+                    return MediaCodec.createByCodecName("OMX.google.mpeg4.decoder");
+                } else if (mime.contains("vp8")) {
+                    return MediaCodec.createByCodecName("OMX.google.vp8.decoder");
+                } else if (mime.contains("vp9")) {
+                    return MediaCodec.createByCodecName("OMX.google.vp9.decoder");
+                }
             }
+            return MediaCodec.createDecoderByType(mime);
+        } catch (Exception e) {
+            return null;
         }
-        return MediaCodec.createDecoderByType(mime);
     }
 
+    // for video
     private int countFrames(int video, int resetMode, int eosframe, Surface s)
             throws Exception {
-        int numframes = 0;
-
         AssetFileDescriptor testFd = mResources.openRawResourceFd(video);
+        MediaExtractor extractor = new MediaExtractor();
+        extractor.setDataSource(testFd.getFileDescriptor(), testFd.getStartOffset(),
+                testFd.getLength());
+        extractor.selectTrack(0);
 
-        MediaExtractor extractor;
-        MediaCodec codec = null;
+        int numframes = decodeWithChecks(extractor, CHECKFLAG_RETURN_OUTPUTFRAMES
+                | CHECKFLAG_COMPAREINPUTOUTPUTPTSMATCH, resetMode, s,
+                eosframe, null, null);
+
+        extractor.release();
+        testFd.close();
+        return numframes;
+    }
+
+    // for audio
+    private int countSize(int audio, int resetMode, int eosframe)
+            throws Exception {
+        AssetFileDescriptor testFd = mResources.openRawResourceFd(audio);
+        MediaExtractor extractor = new MediaExtractor();
+        extractor.setDataSource(testFd.getFileDescriptor(), testFd.getStartOffset(),
+                testFd.getLength());
+        extractor.selectTrack(0);
+
+        // fails CHECKFLAG_COMPAREINPUTOUTPUTPTSMATCH
+        int outputSize = decodeWithChecks(extractor, CHECKFLAG_RETURN_OUTPUTSIZE, resetMode, null,
+                eosframe, null, null);
+
+        extractor.release();
+        testFd.close();
+        return outputSize;
+    }
+
+    private void testEOSBehavior(int movie, int stopatsample) throws Exception {
+        testEOSBehavior(movie, new int[] {stopatsample});
+    }
+
+    private void testEOSBehavior(int movie, int[] stopAtSample) throws Exception {
+        Surface s = null;
+        AssetFileDescriptor testFd = mResources.openRawResourceFd(movie);
+        MediaExtractor extractor = new MediaExtractor();
+        extractor.setDataSource(testFd.getFileDescriptor(), testFd.getStartOffset(),
+                testFd.getLength());
+        extractor.selectTrack(0); // consider variable looping on track
+        List<Long> outputChecksums = new ArrayList<Long>();
+        List<Long> outputTimestamps = new ArrayList<Long>();
+        Arrays.sort(stopAtSample);
+        int last = stopAtSample.length - 1;
+
+        // decode reference (longest sequence to stop at + 100) and
+        // store checksums/pts in outputChecksums and outputTimestamps
+        // (will fail CHECKFLAG_COMPAREINPUTOUTPUTSAMPLEMATCH)
+        decodeWithChecks(extractor,
+                CHECKFLAG_SETCHECKSUM | CHECKFLAG_SETPTS | CHECKFLAG_COMPAREINPUTOUTPUTPTSMATCH,
+                RESET_MODE_NONE, s,
+                stopAtSample[last] + 100, outputChecksums, outputTimestamps);
+
+        // decode stopAtSample requests in reverse order (longest to
+        // shortest) and compare to reference checksums/pts in
+        // outputChecksums and outputTimestamps
+        for (int i = last; i >= 0; --i) {
+            if (true) { // reposition extractor
+                extractor.seekTo(0, MediaExtractor.SEEK_TO_NEXT_SYNC);
+            } else { // create new extractor
+                extractor.release();
+                extractor = new MediaExtractor();
+                extractor.setDataSource(testFd.getFileDescriptor(),
+                        testFd.getStartOffset(), testFd.getLength());
+                extractor.selectTrack(0); // consider variable looping on track
+            }
+            decodeWithChecks(extractor,
+                    CHECKFLAG_COMPARECHECKSUM | CHECKFLAG_COMPAREPTS
+                    | CHECKFLAG_COMPAREINPUTOUTPUTSAMPLEMATCH
+                    | CHECKFLAG_COMPAREINPUTOUTPUTPTSMATCH,
+                    RESET_MODE_NONE, s,
+                    stopAtSample[i], outputChecksums, outputTimestamps);
+        }
+        extractor.release();
+        testFd.close();
+    }
+
+    private static final int CHECKFLAG_SETCHECKSUM = 1 << 0;
+    private static final int CHECKFLAG_COMPARECHECKSUM = 1 << 1;
+    private static final int CHECKFLAG_SETPTS = 1 << 2;
+    private static final int CHECKFLAG_COMPAREPTS = 1 << 3;
+    private static final int CHECKFLAG_COMPAREINPUTOUTPUTSAMPLEMATCH = 1 << 4;
+    private static final int CHECKFLAG_COMPAREINPUTOUTPUTPTSMATCH = 1 << 5;
+    private static final int CHECKFLAG_RETURN_OUTPUTFRAMES = 1 << 6;
+    private static final int CHECKFLAG_RETURN_OUTPUTSIZE = 1 << 7;
+
+    /**
+     * Decodes frames with parameterized checks and return values.
+     * The integer return can be selected through the checkFlags variable.
+     */
+    private static int decodeWithChecks(MediaExtractor extractor, int checkFlags, int resetMode,
+            Surface surface, int stopAtSample,
+            List<Long> outputChecksums, List<Long> outputTimestamps)
+            throws Exception {
+        int trackIndex = extractor.getSampleTrackIndex();
+        MediaFormat format = extractor.getTrackFormat(trackIndex);
+        String mime = format.getString(MediaFormat.KEY_MIME);
+        boolean isAudio = mime.startsWith("audio/");
         ByteBuffer[] codecInputBuffers;
         ByteBuffer[] codecOutputBuffers;
 
-        extractor = new MediaExtractor();
-        extractor.setDataSource(testFd.getFileDescriptor(), testFd.getStartOffset(),
-                testFd.getLength());
-
-        MediaFormat format = extractor.getTrackFormat(0);
-        String mime = format.getString(MediaFormat.KEY_MIME);
-        boolean isAudio = mime.startsWith("audio/");
-
-        codec = createDecoder(mime);
-
-        assertNotNull("couldn't find codec", codec);
+        MediaCodec codec = createDecoder(mime);
         Log.i("@@@@", "using codec: " + codec.getName());
-        codec.configure(format, s /* surface */, null /* crypto */, 0 /* flags */);
+        codec.configure(format, surface, null /* crypto */, 0 /* flags */);
         codec.start();
         codecInputBuffers = codec.getInputBuffers();
         codecOutputBuffers = codec.getOutputBuffers();
 
         if (resetMode == RESET_MODE_RECONFIGURE) {
             codec.stop();
-            codec.configure(format, s /* surface */, null /* crypto */, 0 /* flags */);
+            codec.configure(format, surface, null /* crypto */, 0 /* flags */);
             codec.start();
             codecInputBuffers = codec.getInputBuffers();
             codecOutputBuffers = codec.getOutputBuffers();
@@ -553,19 +1210,28 @@
             codec.flush();
         }
 
-        Log.i("@@@@", "format: " + format);
-
-        extractor.selectTrack(0);
-
-        // start decoding
-        final long kTimeOutUs = 5000;
+        // start decode loop
         MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
+
+        final long kTimeOutUs = 5000; // 5ms timeout
         boolean sawInputEOS = false;
         boolean sawOutputEOS = false;
         int deadDecoderCounter = 0;
-        int samplecounter = 0;
+        int samplenum = 0;
+        int numframes = 0;
+        int outputSize = 0;
+        int width = 0;
+        int height = 0;
+        boolean dochecksum = false;
         ArrayList<Long> timestamps = new ArrayList<Long>();
+        if ((checkFlags & CHECKFLAG_SETPTS) != 0) {
+            outputTimestamps.clear();
+        }
+        if ((checkFlags & CHECKFLAG_SETCHECKSUM) != 0) {
+            outputChecksums.clear();
+        }
         while (!sawOutputEOS && deadDecoderCounter < 100) {
+            // handle input
             if (!sawInputEOS) {
                 int inputBufIndex = codec.dequeueInputBuffer(kTimeOutUs);
 
@@ -573,418 +1239,367 @@
                     ByteBuffer dstBuf = codecInputBuffers[inputBufIndex];
 
                     int sampleSize =
-                        extractor.readSampleData(dstBuf, 0 /* offset */);
-
-                    long presentationTimeUs = 0;
+                            extractor.readSampleData(dstBuf, 0 /* offset */);
+                    long presentationTimeUs = extractor.getSampleTime();
+                    boolean advanceDone = extractor.advance();
+                    // int flags = extractor.getSampleFlags();
+                    // Log.i("@@@@", "read sample " + samplenum + ":" +
+                    // extractor.getSampleFlags()
+                    // + " @ " + extractor.getSampleTime() + " size " +
+                    // sampleSize);
+                    assertEquals("extractor.advance() should match end of stream", sampleSize >= 0,
+                            advanceDone);
 
                     if (sampleSize < 0) {
                         Log.d(TAG, "saw input EOS.");
                         sawInputEOS = true;
-                        sampleSize = 0;
+                        assertEquals("extractor.readSampleData() must return -1 at end of stream",
+                                -1, sampleSize);
+                        assertEquals("extractor.getSampleTime() must return -1 at end of stream",
+                                -1, presentationTimeUs);
+                        sampleSize = 0; // required otherwise queueInputBuffer
+                                        // returns invalid.
                     } else {
-                        presentationTimeUs = extractor.getSampleTime();
-                        samplecounter++;
-                        if (samplecounter == eosframe) {
-                            sawInputEOS = true;
+                        timestamps.add(presentationTimeUs);
+                        samplenum++; // increment before comparing with stopAtSample
+                        if (samplenum == stopAtSample) {
+                            Log.d(TAG, "saw input EOS (stop at sample).");
+                            sawInputEOS = true; // tag this sample as EOS
                         }
                     }
-
-                    timestamps.add(presentationTimeUs);
-
-                    int flags = extractor.getSampleFlags();
-
                     codec.queueInputBuffer(
                             inputBufIndex,
                             0 /* offset */,
                             sampleSize,
                             presentationTimeUs,
                             sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
-
-                    if (!sawInputEOS) {
-                        extractor.advance();
-                    }
+                } else {
+                    assertEquals(
+                            "codec.dequeueInputBuffer() unrecognized return value: " + inputBufIndex,
+                            MediaCodec.INFO_TRY_AGAIN_LATER, inputBufIndex);
                 }
             }
 
-            int res = codec.dequeueOutputBuffer(info, kTimeOutUs);
+            // handle output
+            int outputBufIndex = codec.dequeueOutputBuffer(info, kTimeOutUs);
 
             deadDecoderCounter++;
-            if (res >= 0) {
-                //Log.d(TAG, "got frame, size " + info.size + "/" + info.presentationTimeUs);
-
-                // Some decoders output a 0-sized buffer at the end. Disregard those.
-                if (info.size > 0) {
+            if (outputBufIndex >= 0) {
+                if (info.size > 0) { // Disregard 0-sized buffers at the end.
                     deadDecoderCounter = 0;
                     if (resetMode != RESET_MODE_NONE) {
-                        // once we've gotten some data out of the decoder, reset and start again
+                        // once we've gotten some data out of the decoder, reset
+                        // and start again
                         if (resetMode == RESET_MODE_RECONFIGURE) {
                             codec.stop();
-                            codec.configure(format, s /* surface */, null /* crypto */,
+                            codec.configure(format, surface /* surface */, null /* crypto */,
                                     0 /* flags */);
                             codec.start();
                             codecInputBuffers = codec.getInputBuffers();
                             codecOutputBuffers = codec.getOutputBuffers();
-                        } else /* resetMode == RESET_MODE_FLUSH */ {
+                        } else if (resetMode == RESET_MODE_FLUSH) {
                             codec.flush();
+                        } else {
+                            fail("unknown resetMode: " + resetMode);
                         }
+                        // restart at beginning, clear resetMode
                         resetMode = RESET_MODE_NONE;
                         extractor.seekTo(0, MediaExtractor.SEEK_TO_NEXT_SYNC);
                         sawInputEOS = false;
                         numframes = 0;
                         timestamps.clear();
+                        if ((checkFlags & CHECKFLAG_SETPTS) != 0) {
+                            outputTimestamps.clear();
+                        }
+                        if ((checkFlags & CHECKFLAG_SETCHECKSUM) != 0) {
+                            outputChecksums.clear();
+                        }
                         continue;
                     }
-
-                    if (isAudio) {
-                        // for audio, count the number of bytes that were decoded, not the number
-                        // of access units
-                        numframes += info.size;
-                    } else {
-                        // for video, count the number of video frames and check the timestamp
-                        numframes++;
-                        assertTrue("invalid timestamp", timestamps.remove(info.presentationTimeUs));
+                    if ((checkFlags & CHECKFLAG_COMPAREPTS) != 0) {
+                        assertTrue("number of frames (" + numframes
+                                + ") exceeds number of reference timestamps",
+                                numframes < outputTimestamps.size());
+                        assertEquals("frame ts mismatch at frame " + numframes,
+                                (long) outputTimestamps.get(numframes), info.presentationTimeUs);
+                    } else if ((checkFlags & CHECKFLAG_SETPTS) != 0) {
+                        outputTimestamps.add(info.presentationTimeUs);
                     }
+                    if ((checkFlags & (CHECKFLAG_SETCHECKSUM | CHECKFLAG_COMPARECHECKSUM)) != 0) {
+                        long sum = 0;   // note: checksum is 0 if buffer format unrecognized
+                        if (dochecksum) {
+                            Image image = codec.getOutputImage(outputBufIndex);
+                            // use image to do crc if it's available
+                            // fall back to buffer if image is not available
+                            if (image != null) {
+                                sum = checksum(image);
+                            } else {
+                                // TODO: add stride - right now just use info.size (as before)
+                                //sum = checksum(codecOutputBuffers[outputBufIndex], width, height,
+                                //        stride);
+                                ByteBuffer outputBuffer = codec.getOutputBuffer(outputBufIndex);
+                                outputBuffer.position(info.offset);
+                                sum = checksum(outputBuffer, info.size);
+                            }
+                        }
+                        if ((checkFlags & CHECKFLAG_COMPARECHECKSUM) != 0) {
+                            assertTrue("number of frames (" + numframes
+                                    + ") exceeds number of reference checksums",
+                                    numframes < outputChecksums.size());
+                            Log.d(TAG, "orig checksum: " + outputChecksums.get(numframes)
+                                    + " new checksum: " + sum);
+                            assertEquals("frame data mismatch at frame " + numframes,
+                                    (long) outputChecksums.get(numframes), sum);
+                        } else if ((checkFlags & CHECKFLAG_SETCHECKSUM) != 0) {
+                            outputChecksums.add(sum);
+                        }
+                    }
+                    if ((checkFlags & CHECKFLAG_COMPAREINPUTOUTPUTPTSMATCH) != 0) {
+                        assertTrue("output timestamp " + info.presentationTimeUs
+                                + " without corresponding input timestamp"
+                                , timestamps.remove(info.presentationTimeUs));
+                    }
+                    outputSize += info.size;
+                    numframes++;
                 }
-                int outputBufIndex = res;
+                // Log.d(TAG, "got frame, size " + info.size + "/" +
+                // info.presentationTimeUs +
+                // "/" + numframes + "/" + info.flags);
                 codec.releaseOutputBuffer(outputBufIndex, true /* render */);
-
                 if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                     Log.d(TAG, "saw output EOS.");
                     sawOutputEOS = true;
                 }
-            } else if (res == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
+            } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
                 codecOutputBuffers = codec.getOutputBuffers();
-
                 Log.d(TAG, "output buffers have changed.");
-            } else if (res == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+            } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
                 MediaFormat oformat = codec.getOutputFormat();
-
-                Log.d(TAG, "output format has changed to " + oformat);
+                if (oformat.containsKey(MediaFormat.KEY_COLOR_FORMAT) &&
+                        oformat.containsKey(MediaFormat.KEY_WIDTH) &&
+                        oformat.containsKey(MediaFormat.KEY_HEIGHT)) {
+                    int colorFormat = oformat.getInteger(MediaFormat.KEY_COLOR_FORMAT);
+                    width = oformat.getInteger(MediaFormat.KEY_WIDTH);
+                    height = oformat.getInteger(MediaFormat.KEY_HEIGHT);
+                    dochecksum = isRecognizedFormat(colorFormat); // only checksum known raw
+                                                                  // buf formats
+                    Log.d(TAG, "checksum fmt: " + colorFormat + " dim " + width + "x" + height);
+                } else {
+                    dochecksum = false; // check with audio later
+                    width = height = 0;
+                    Log.d(TAG, "output format has changed to (unknown video) " + oformat);
+                }
             } else {
-                Log.d(TAG, "no output");
+                assertEquals(
+                        "codec.dequeueOutputBuffer() unrecognized return index: "
+                                + outputBufIndex,
+                        MediaCodec.INFO_TRY_AGAIN_LATER, outputBufIndex);
             }
         }
-
         codec.stop();
         codec.release();
-        testFd.close();
-        return numframes;
+
+        assertTrue("last frame didn't have EOS", sawOutputEOS);
+        if ((checkFlags & CHECKFLAG_COMPAREINPUTOUTPUTSAMPLEMATCH) != 0) {
+            assertEquals("I!=O", samplenum, numframes);
+            if (stopAtSample != 0) {
+                assertEquals("did not stop with right number of frames", stopAtSample, numframes);
+            }
+        }
+        return (checkFlags & CHECKFLAG_RETURN_OUTPUTSIZE) != 0 ? outputSize :
+                (checkFlags & CHECKFLAG_RETURN_OUTPUTFRAMES) != 0 ? numframes :
+                        0;
     }
 
     public void testEOSBehaviorH264() throws Exception {
         // this video has an I frame at 44
-        testEOSBehavior(R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz, 44);
-        testEOSBehavior(R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz, 45);
-        testEOSBehavior(R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz, 55);
+        testEOSBehavior(R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz,
+                new int[] {44, 45, 55});
+    }
+    public void testEOSBehaviorHEVC() throws Exception {
+        testEOSBehavior(R.raw.video_480x360_mp4_hevc_650kbps_30fps_aac_stereo_128kbps_48000hz, 17);
+        testEOSBehavior(R.raw.video_480x360_mp4_hevc_650kbps_30fps_aac_stereo_128kbps_48000hz, 23);
+        testEOSBehavior(R.raw.video_480x360_mp4_hevc_650kbps_30fps_aac_stereo_128kbps_48000hz, 49);
     }
 
     public void testEOSBehaviorH263() throws Exception {
         // this video has an I frame every 12 frames.
-        testEOSBehavior(R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz, 24);
-        testEOSBehavior(R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz, 25);
-        testEOSBehavior(R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz, 48);
-        testEOSBehavior(R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz, 50);
+        testEOSBehavior(R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz,
+                new int[] {24, 25, 48, 50});
     }
 
     public void testEOSBehaviorMpeg4() throws Exception {
         // this video has an I frame every 12 frames
-        testEOSBehavior(R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz, 24);
-        testEOSBehavior(R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz, 25);
-        testEOSBehavior(R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz, 48);
-        testEOSBehavior(R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz, 50);
-        testEOSBehavior(R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz, 2);
+        testEOSBehavior(R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz,
+                new int[] {24, 25, 48, 50, 2});
     }
 
     public void testEOSBehaviorVP8() throws Exception {
         // this video has an I frame at 46
-        testEOSBehavior(R.raw.video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz, 46);
-        testEOSBehavior(R.raw.video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz, 47);
-        testEOSBehavior(R.raw.video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz, 57);
-        testEOSBehavior(R.raw.video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz, 45);
+        testEOSBehavior(R.raw.video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz,
+                new int[] {46, 47, 57, 45});
     }
 
     public void testEOSBehaviorVP9() throws Exception {
         // this video has an I frame at 44
-        testEOSBehavior(R.raw.video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_44100hz, 44);
-        testEOSBehavior(R.raw.video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_44100hz, 45);
-        testEOSBehavior(R.raw.video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_44100hz, 55);
-        testEOSBehavior(R.raw.video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_44100hz, 43);
-    }
-
-    private void testEOSBehavior(int movie, int stopatsample) throws Exception {
-
-        int numframes = 0;
-
-        long [] checksums = new long[stopatsample];
-
-        AssetFileDescriptor testFd = mResources.openRawResourceFd(movie);
-
-        MediaExtractor extractor;
-        MediaCodec codec = null;
-        ByteBuffer[] codecInputBuffers;
-        ByteBuffer[] codecOutputBuffers;
-
-        extractor = new MediaExtractor();
-        extractor.setDataSource(testFd.getFileDescriptor(), testFd.getStartOffset(),
-                testFd.getLength());
-
-        MediaFormat format = extractor.getTrackFormat(0);
-        String mime = format.getString(MediaFormat.KEY_MIME);
-        boolean isAudio = mime.startsWith("audio/");
-
-        codec = createDecoder(mime);
-
-        assertNotNull("couldn't find codec", codec);
-        Log.i("@@@@", "using codec: " + codec.getName());
-        codec.configure(format, null /* surface */, null /* crypto */, 0 /* flags */);
-        codec.start();
-        codecInputBuffers = codec.getInputBuffers();
-        codecOutputBuffers = codec.getOutputBuffers();
-
-        extractor.selectTrack(0);
-
-        // start decoding
-        final long kTimeOutUs = 5000;
-        MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
-        boolean sawInputEOS = false;
-        boolean sawOutputEOS = false;
-        int deadDecoderCounter = 0;
-        int samplenum = 0;
-        boolean dochecksum = false;
-        while (!sawOutputEOS && deadDecoderCounter < 100) {
-            if (!sawInputEOS) {
-                int inputBufIndex = codec.dequeueInputBuffer(kTimeOutUs);
-
-                if (inputBufIndex >= 0) {
-                    ByteBuffer dstBuf = codecInputBuffers[inputBufIndex];
-
-                    int sampleSize =
-                        extractor.readSampleData(dstBuf, 0 /* offset */);
-//                    Log.i("@@@@", "read sample " + samplenum + ":" + extractor.getSampleFlags()
-//                            + " @ " + extractor.getSampleTime() + " size " + sampleSize);
-                    samplenum++;
-
-                    long presentationTimeUs = 0;
-
-                    if (sampleSize < 0 || samplenum >= (stopatsample + 100)) {
-                        Log.d(TAG, "saw input EOS.");
-                        sawInputEOS = true;
-                        sampleSize = 0;
-                    } else {
-                        presentationTimeUs = extractor.getSampleTime();
-                    }
-
-                    int flags = extractor.getSampleFlags();
-
-                    codec.queueInputBuffer(
-                            inputBufIndex,
-                            0 /* offset */,
-                            sampleSize,
-                            presentationTimeUs,
-                            sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
-
-                    if (!sawInputEOS) {
-                        extractor.advance();
-                    }
-                }
-            }
-
-            int res = codec.dequeueOutputBuffer(info, kTimeOutUs);
-
-            deadDecoderCounter++;
-            if (res >= 0) {
-
-                // Some decoders output a 0-sized buffer at the end. Disregard those.
-                if (info.size > 0) {
-                    deadDecoderCounter = 0;
-
-                    if (isAudio) {
-                        // for audio, count the number of bytes that were decoded, not the number
-                        // of access units
-                        numframes += info.size;
-                    } else {
-                        // for video, count the number of video frames
-                        long sum = dochecksum ? checksum(codecOutputBuffers[res], info.size) : 0;
-                        if (numframes < checksums.length) {
-                            checksums[numframes] = sum;
-                        }
-                        numframes++;
-                    }
-                }
-//                Log.d(TAG, "got frame, size " + info.size + "/" + info.presentationTimeUs +
-//                        "/" + numframes + "/" + info.flags);
-
-                int outputBufIndex = res;
-                codec.releaseOutputBuffer(outputBufIndex, true /* render */);
-
-                if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
-                    Log.d(TAG, "saw output EOS.");
-                    sawOutputEOS = true;
-                }
-            } else if (res == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
-                codecOutputBuffers = codec.getOutputBuffers();
-
-                Log.d(TAG, "output buffers have changed.");
-            } else if (res == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
-                MediaFormat oformat = codec.getOutputFormat();
-                int colorFormat = oformat.getInteger(MediaFormat.KEY_COLOR_FORMAT);
-                dochecksum = isRecognizedFormat(colorFormat);
-                Log.d(TAG, "output format has changed to " + oformat);
-            } else {
-                Log.d(TAG, "no output");
-            }
-        }
-
-        codec.stop();
-        codec.release();
-        extractor.release();
-
-
-        // We now have checksums for every frame.
-        // Now decode again, but signal EOS right before an index frame, and ensure the frames
-        // prior to that are the same.
-
-        extractor = new MediaExtractor();
-        extractor.setDataSource(testFd.getFileDescriptor(), testFd.getStartOffset(),
-                testFd.getLength());
-
-        codec = createDecoder(mime);
-        codec.configure(format, null /* surface */, null /* crypto */, 0 /* flags */);
-        codec.start();
-        codecInputBuffers = codec.getInputBuffers();
-        codecOutputBuffers = codec.getOutputBuffers();
-
-        extractor.selectTrack(0);
-
-        // start decoding
-        info = new MediaCodec.BufferInfo();
-        sawInputEOS = false;
-        sawOutputEOS = false;
-        deadDecoderCounter = 0;
-        samplenum = 0;
-        numframes = 0;
-        dochecksum = false;
-        while (!sawOutputEOS && deadDecoderCounter < 100) {
-            if (!sawInputEOS) {
-                int inputBufIndex = codec.dequeueInputBuffer(kTimeOutUs);
-
-                if (inputBufIndex >= 0) {
-                    ByteBuffer dstBuf = codecInputBuffers[inputBufIndex];
-
-                    int sampleSize =
-                        extractor.readSampleData(dstBuf, 0 /* offset */);
-//                    Log.i("@@@@", "read sample " + samplenum + ":" + extractor.getSampleFlags()
-//                            + " @ " + extractor.getSampleTime() + " size " + sampleSize);
-                    samplenum++;
-
-                    long presentationTimeUs = extractor.getSampleTime();
-
-                    if (sampleSize < 0 || samplenum >= stopatsample) {
-                        Log.d(TAG, "saw input EOS.");
-                        sawInputEOS = true;
-                        if (sampleSize < 0) {
-                            sampleSize = 0;
-                        }
-                    }
-
-                    int flags = extractor.getSampleFlags();
-
-                    codec.queueInputBuffer(
-                            inputBufIndex,
-                            0 /* offset */,
-                            sampleSize,
-                            presentationTimeUs,
-                            sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
-
-                    if (!sawInputEOS) {
-                        extractor.advance();
-                    }
-                }
-            }
-
-            int res = codec.dequeueOutputBuffer(info, kTimeOutUs);
-
-            deadDecoderCounter++;
-            if (res >= 0) {
-
-                // Some decoders output a 0-sized buffer at the end. Disregard those.
-                if (info.size > 0) {
-                    deadDecoderCounter = 0;
-
-                    if (isAudio) {
-                        // for audio, count the number of bytes that were decoded, not the number
-                        // of access units
-                        numframes += info.size;
-                    } else {
-                        // for video, count the number of video frames
-                        long sum = dochecksum ? checksum(codecOutputBuffers[res], info.size) : 0;
-                        if (numframes < checksums.length) {
-                            assertEquals("frame data mismatch at frame " + numframes,
-                                    checksums[numframes], sum);
-                        }
-                        numframes++;
-                    }
-                }
-//                Log.d(TAG, "got frame, size " + info.size + "/" + info.presentationTimeUs +
-//                        "/" + numframes + "/" + info.flags);
-
-                int outputBufIndex = res;
-                codec.releaseOutputBuffer(outputBufIndex, true /* render */);
-
-                if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
-                    Log.d(TAG, "saw output EOS.");
-                    sawOutputEOS = true;
-                }
-            } else if (res == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
-                codecOutputBuffers = codec.getOutputBuffers();
-
-                Log.d(TAG, "output buffers have changed.");
-            } else if (res == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
-                MediaFormat oformat = codec.getOutputFormat();
-                int colorFormat = oformat.getInteger(MediaFormat.KEY_COLOR_FORMAT);
-                dochecksum = isRecognizedFormat(colorFormat);
-                Log.d(TAG, "output format has changed to " + oformat);
-            } else {
-                Log.d(TAG, "no output");
-            }
-        }
-
-        codec.stop();
-        codec.release();
-        extractor.release();
-
-        assertEquals("I!=O", samplenum, numframes);
-        assertTrue("last frame didn't have EOS", sawOutputEOS);
-        assertEquals(stopatsample, numframes);
-
-        testFd.close();
+        testEOSBehavior(R.raw.video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_44100hz,
+                new int[] {44, 45, 55, 43});
     }
 
     /* from EncodeDecodeTest */
     private static boolean isRecognizedFormat(int colorFormat) {
+        // Log.d(TAG, "color format: " + String.format("0x%08x", colorFormat));
         switch (colorFormat) {
-            // these are the formats we know how to handle for this test
+        // these are the formats we know how to handle for this test
             case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar:
             case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar:
             case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar:
             case MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedSemiPlanar:
             case MediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanar:
+            case MediaCodecInfo.CodecCapabilities.COLOR_QCOM_FormatYUV420SemiPlanar:
+                /*
+                 * TODO: Check newer formats or ignore.
+                 * OMX_SEC_COLOR_FormatNV12Tiled = 0x7FC00002
+                 * OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka = 0x7FA30C03: N4/N7_2
+                 * OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m = 0x7FA30C04: N5
+                 */
                 return true;
             default:
                 return false;
         }
     }
 
-    private long checksum(ByteBuffer buf, int size) {
-        assertTrue(size != 0);
-        assertTrue(size <= buf.capacity());
+    private static long checksum(ByteBuffer buf, int size) {
+        int cap = buf.capacity();
+        assertTrue("checksum() params are invalid: size = " + size + " cap = " + cap,
+                size > 0 && size <= cap);
         CRC32 crc = new CRC32();
-        int pos = buf.position();
-        buf.rewind();
-        for (int i = 0; i < size; i++) {
-            crc.update(buf.get());
+        if (buf.hasArray()) {
+            crc.update(buf.array(), buf.position() + buf.arrayOffset(), size);
+        } else {
+            int pos = buf.position();
+            final int rdsize = Math.min(4096, size);
+            byte bb[] = new byte[rdsize];
+            int chk;
+            for (int i = 0; i < size; i += chk) {
+                chk = Math.min(rdsize, size - i);
+                buf.get(bb, 0, chk);
+                crc.update(bb, 0, chk);
+            }
+            buf.position(pos);
         }
-        buf.position(pos);
+        return crc.getValue();
+    }
+
+    private static long checksum(ByteBuffer buf, int width, int height, int stride) {
+        int cap = buf.capacity();
+        assertTrue("checksum() params are invalid: w x h , s = "
+                + width + " x " + height + " , " + stride + " cap = " + cap,
+                width > 0 && width <= stride && height > 0 && height * stride <= cap);
+        // YUV 4:2:0 should generally have a data storage height 1.5x greater
+        // than the declared image height, representing the UV planes.
+        //
+        // We only check Y frame for now. Somewhat unknown with tiling effects.
+        //
+        //long tm = System.nanoTime();
+        final int lineinterval = 1; // line sampling frequency
+        CRC32 crc = new CRC32();
+        if (buf.hasArray()) {
+            byte b[] = buf.array();
+            int offs = buf.arrayOffset();
+            for (int i = 0; i < height; i += lineinterval) {
+                crc.update(b, i * stride + offs, width);
+            }
+        } else { // almost always ends up here due to direct buffers
+            int pos = buf.position();
+            if (true) { // this {} is 80x times faster than else {} below.
+                byte[] bb = new byte[width]; // local line buffer
+                for (int i = 0; i < height; i += lineinterval) {
+                    buf.position(pos + i * stride);
+                    buf.get(bb, 0, width);
+                    crc.update(bb, 0, width);
+                }
+            } else {
+                for (int i = 0; i < height; i += lineinterval) {
+                    buf.position(pos + i * stride);
+                    for (int j = 0; j < width; ++j) {
+                        crc.update(buf.get());
+                    }
+                }
+            }
+            buf.position(pos);
+        }
+        //tm = System.nanoTime() - tm;
+        //Log.d(TAG, "checksum time " + tm);
+        return crc.getValue();
+    }
+
+    private static long checksum(Image image) {
+        int format = image.getFormat();
+        assertEquals("unsupported image format", ImageFormat.YUV_420_888, format);
+
+        CRC32 crc = new CRC32();
+
+        int imageWidth = image.getWidth();
+        int imageHeight = image.getHeight();
+
+        Image.Plane[] planes = image.getPlanes();
+        for (int i = 0; i < planes.length; ++i) {
+            ByteBuffer buf = planes[i].getBuffer();
+
+            int width, height, rowStride, pixelStride, x, y;
+            rowStride = planes[i].getRowStride();
+            pixelStride = planes[i].getPixelStride();
+            if (i == 0) {
+                width = imageWidth;
+                height = imageHeight;
+            } else {
+                width = imageWidth / 2;
+                height = imageHeight /2;
+            }
+            // local contiguous pixel buffer
+            byte[] bb = new byte[width * height];
+            if (buf.hasArray()) {
+                byte b[] = buf.array();
+                int offs = buf.arrayOffset();
+                if (pixelStride == 1) {
+                    for (y = 0; y < height; ++y) {
+                        System.arraycopy(bb, y * width, b, y * rowStride + offs, width);
+                    }
+                } else {
+                    // do it pixel-by-pixel
+                    for (y = 0; y < height; ++y) {
+                        int lineOffset = offs + y * rowStride;
+                        for (x = 0; x < width; ++x) {
+                            bb[y * width + x] = b[lineOffset + x * pixelStride];
+                        }
+                    }
+                }
+            } else { // almost always ends up here due to direct buffers
+                int pos = buf.position();
+                if (pixelStride == 1) {
+                    for (y = 0; y < height; ++y) {
+                        buf.position(pos + y * rowStride);
+                        buf.get(bb, y * width, width);
+                    }
+                } else {
+                    // local line buffer
+                    byte[] lb = new byte[rowStride];
+                    // do it pixel-by-pixel
+                    for (y = 0; y < height; ++y) {
+                        buf.position(pos + y * rowStride);
+                        // we're only guaranteed to have pixelStride * (width - 1) + 1 bytes
+                        buf.get(lb, 0, pixelStride * (width - 1) + 1);
+                        for (x = 0; x < width; ++x) {
+                            bb[y * width + x] = lb[x * pixelStride];
+                        }
+                    }
+                }
+                buf.position(pos);
+            }
+            crc.update(bb, 0, width * height);
+        }
+
         return crc.getValue();
     }
 
@@ -1017,6 +1632,8 @@
         assertTrue("not an audio file", mime.startsWith("audio/"));
 
         codec = MediaCodec.createDecoderByType(mime);
+        assertNotNull("couldn't find codec " + mime, codec);
+
         codec.configure(format, null /* surface */, null /* crypto */, 0 /* flags */);
         codec.start();
         codecInputBuffers = codec.getInputBuffers();
@@ -1073,8 +1690,9 @@
                 int outputBufIndex = res;
                 ByteBuffer buf = codecOutputBuffers[outputBufIndex];
 
+                buf.position(info.offset);
                 for (int i = 0; i < info.size; i += 2) {
-                    short sample = buf.getShort(i);
+                    short sample = buf.getShort();
                     if (maxvalue < sample) {
                         maxvalue = sample;
                     }
diff --git a/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java b/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java
index 6f1faf6..a480d97 100644
--- a/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java
+++ b/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java
@@ -51,7 +51,8 @@
     private static final String DEBUG_FILE_NAME_BASE = "/sdcard/test.";
 
     // parameters for the encoder
-    private static final String MIME_TYPE = "video/avc";    // H.264 Advanced Video Coding
+    private static final String MIME_TYPE_AVC = "video/avc";    // H.264 Advanced Video Coding
+    private static final String MIME_TYPE_VP8 = "video/x-vnd.on2.vp8";
     private static final int FRAME_RATE = 15;               // 15fps
     private static final int IFRAME_INTERVAL = 10;          // 10 seconds between I-frames
 
@@ -61,22 +62,32 @@
     private static final int TEST_Y = 120;                  // YUV values for colored rect
     private static final int TEST_U = 160;
     private static final int TEST_V = 200;
-    private static final int TEST_R0 = 0;                   // RGB equivalent of {0,0,0}
+    private static final int TEST_R0 = 0;                   // RGB equivalent of {0,0,0} (BT.601)
     private static final int TEST_G0 = 136;
     private static final int TEST_B0 = 0;
-    private static final int TEST_R1 = 236;                 // RGB equivalent of {120,160,200}
+    private static final int TEST_R1 = 236;                 // RGB equivalent of {120,160,200} (BT.601)
     private static final int TEST_G1 = 50;
     private static final int TEST_B1 = 186;
+    private static final int TEST_R0_BT709 = 0;             // RGB equivalent of {0,0,0} (BT.709)
+    private static final int TEST_G0_BT709 = 77;
+    private static final int TEST_B0_BT709 = 0;
+    private static final int TEST_R1_BT709 = 250;           // RGB equivalent of {120,160,200} (BT.709)
+    private static final int TEST_G1_BT709 = 76;
+    private static final int TEST_B1_BT709 = 189;
 
     // size of a frame, in pixels
     private int mWidth = -1;
     private int mHeight = -1;
     // bit rate, in bits per second
     private int mBitRate = -1;
+    private String mMimeType = MIME_TYPE_AVC;
 
     // largest color component delta seen (i.e. actual vs. expected)
     private int mLargestColorDelta;
 
+    // validate YUV->RGB decoded frames against BT.601 and/or BT.709
+    private boolean mAllowBT601 = true;
+    private boolean mAllowBT709 = false;
 
     /**
      * Tests streaming of AVC video through the encoder and decoder.  Data is encoded from
@@ -84,15 +95,33 @@
      * validity.
      */
     public void testEncodeDecodeVideoFromBufferToBufferQCIF() throws Exception {
-        setParameters(176, 144, 1000000);
+        setParameters(176, 144, 1000000, MIME_TYPE_AVC, true, false);
         encodeDecodeVideoFromBuffer(false);
     }
     public void testEncodeDecodeVideoFromBufferToBufferQVGA() throws Exception {
-        setParameters(320, 240, 2000000);
+        setParameters(320, 240, 2000000, MIME_TYPE_AVC, true, false);
         encodeDecodeVideoFromBuffer(false);
     }
     public void testEncodeDecodeVideoFromBufferToBuffer720p() throws Exception {
-        setParameters(1280, 720, 6000000);
+        setParameters(1280, 720, 6000000, MIME_TYPE_AVC, true, false);
+        encodeDecodeVideoFromBuffer(false);
+    }
+
+    /**
+     * Tests streaming of VP8 video through the encoder and decoder.  Data is encoded from
+     * a series of byte[] buffers and decoded into ByteBuffers.  The output is checked for
+     * validity.
+     */
+    public void testVP8EncodeDecodeVideoFromBufferToBufferQCIF() throws Exception {
+        setParameters(176, 144, 1000000, MIME_TYPE_VP8, true, false);
+        encodeDecodeVideoFromBuffer(false);
+    }
+    public void testVP8EncodeDecodeVideoFromBufferToBufferQVGA() throws Exception {
+        setParameters(320, 240, 2000000, MIME_TYPE_VP8, true, false);
+        encodeDecodeVideoFromBuffer(false);
+    }
+    public void testVP8EncodeDecodeVideoFromBufferToBuffer720p() throws Exception {
+        setParameters(1280, 720, 6000000, MIME_TYPE_VP8, true, false);
         encodeDecodeVideoFromBuffer(false);
     }
 
@@ -109,15 +138,33 @@
      * the test.
      */
     public void testEncodeDecodeVideoFromBufferToSurfaceQCIF() throws Throwable {
-        setParameters(176, 144, 1000000);
+        setParameters(176, 144, 1000000, MIME_TYPE_AVC, true, false);
         BufferToSurfaceWrapper.runTest(this);
     }
     public void testEncodeDecodeVideoFromBufferToSurfaceQVGA() throws Throwable {
-        setParameters(320, 240, 2000000);
+        setParameters(320, 240, 2000000, MIME_TYPE_AVC, true, false);
         BufferToSurfaceWrapper.runTest(this);
     }
     public void testEncodeDecodeVideoFromBufferToSurface720p() throws Throwable {
-        setParameters(1280, 720, 6000000);
+        setParameters(1280, 720, 6000000, MIME_TYPE_AVC, true, true);
+        BufferToSurfaceWrapper.runTest(this);
+    }
+
+    /**
+     * Tests streaming of VP8 video through the encoder and decoder.  Data is encoded from
+     * a series of byte[] buffers and decoded into Surfaces.  The output is checked for
+     * validity.
+     */
+    public void testVP8EncodeDecodeVideoFromBufferToSurfaceQCIF() throws Throwable {
+        setParameters(176, 144, 1000000, MIME_TYPE_VP8, true, false);
+        BufferToSurfaceWrapper.runTest(this);
+    }
+    public void testVP8EncodeDecodeVideoFromBufferToSurfaceQVGA() throws Throwable {
+        setParameters(320, 240, 2000000, MIME_TYPE_VP8, true, false);
+        BufferToSurfaceWrapper.runTest(this);
+    }
+    public void testVP8EncodeDecodeVideoFromBufferToSurface720p() throws Throwable {
+        setParameters(1280, 720, 6000000, MIME_TYPE_VP8, true, true);
         BufferToSurfaceWrapper.runTest(this);
     }
 
@@ -158,15 +205,32 @@
      * a Surface and decoded onto a Surface.  The output is checked for validity.
      */
     public void testEncodeDecodeVideoFromSurfaceToSurfaceQCIF() throws Throwable {
-        setParameters(176, 144, 1000000);
+        setParameters(176, 144, 1000000, MIME_TYPE_AVC, true, false);
         SurfaceToSurfaceWrapper.runTest(this);
     }
     public void testEncodeDecodeVideoFromSurfaceToSurfaceQVGA() throws Throwable {
-        setParameters(320, 240, 2000000);
+        setParameters(320, 240, 2000000, MIME_TYPE_AVC, true, false);
         SurfaceToSurfaceWrapper.runTest(this);
     }
     public void testEncodeDecodeVideoFromSurfaceToSurface720p() throws Throwable {
-        setParameters(1280, 720, 6000000);
+        setParameters(1280, 720, 6000000, MIME_TYPE_AVC, true, false);
+        SurfaceToSurfaceWrapper.runTest(this);
+    }
+
+    /**
+     * Tests streaming of VP8 video through the encoder and decoder.  Data is provided through
+     * a Surface and decoded onto a Surface.  The output is checked for validity.
+     */
+    public void testVP8EncodeDecodeVideoFromSurfaceToSurfaceQCIF() throws Throwable {
+        setParameters(176, 144, 1000000, MIME_TYPE_VP8, true, false);
+        SurfaceToSurfaceWrapper.runTest(this);
+    }
+    public void testVP8EncodeDecodeVideoFromSurfaceToSurfaceQVGA() throws Throwable {
+        setParameters(320, 240, 2000000, MIME_TYPE_VP8, true, false);
+        SurfaceToSurfaceWrapper.runTest(this);
+    }
+    public void testVP8EncodeDecodeVideoFromSurfaceToSurface720p() throws Throwable {
+        setParameters(1280, 720, 6000000, MIME_TYPE_VP8, true, false);
         SurfaceToSurfaceWrapper.runTest(this);
     }
 
@@ -205,13 +269,17 @@
     /**
      * Sets the desired frame size and bit rate.
      */
-    private void setParameters(int width, int height, int bitRate) {
+    private void setParameters(int width, int height, int bitRate, String mimeType,
+	        boolean allowBT601, boolean allowBT709) {
         if ((width % 16) != 0 || (height % 16) != 0) {
             Log.w(TAG, "WARNING: width or height not multiple of 16");
         }
         mWidth = width;
         mHeight = height;
         mBitRate = bitRate;
+        mMimeType = mimeType;
+        mAllowBT601 = allowBT601;
+        mAllowBT709 = allowBT709;
     }
 
     /**
@@ -229,20 +297,20 @@
         mLargestColorDelta = -1;
 
         try {
-            MediaCodecInfo codecInfo = selectCodec(MIME_TYPE);
+            MediaCodecInfo codecInfo = selectCodec(mMimeType);
             if (codecInfo == null) {
                 // Don't fail CTS if they don't have an AVC codec (not here, anyway).
-                Log.e(TAG, "Unable to find an appropriate codec for " + MIME_TYPE);
+                Log.e(TAG, "Unable to find an appropriate codec for " + mMimeType);
                 return;
             }
             if (VERBOSE) Log.d(TAG, "found codec: " + codecInfo.getName());
 
-            int colorFormat = selectColorFormat(codecInfo, MIME_TYPE);
+            int colorFormat = selectColorFormat(codecInfo, mMimeType);
             if (VERBOSE) Log.d(TAG, "found colorFormat: " + colorFormat);
 
             // We avoid the device-specific limitations on width and height by using values that
             // are multiples of 16, which all tested devices seem to be able to handle.
-            MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);
+            MediaFormat format = MediaFormat.createVideoFormat(mMimeType, mWidth, mHeight);
 
             // Set some properties.  Failing to specify some of these can cause the MediaCodec
             // configure() call to throw an unhelpful exception.
@@ -260,7 +328,7 @@
 
             // Create a MediaCodec for the decoder, just based on the MIME type.  The various
             // format details will be passed through the csd-0 meta-data later on.
-            decoder = MediaCodec.createDecoderByType(MIME_TYPE);
+            decoder = MediaCodec.createDecoderByType(mMimeType);
             if (VERBOSE) Log.d(TAG, "got decoder: " + decoder.getName());
 
             doEncodeDecodeVideoFromBuffer(encoder, colorFormat, decoder, toSurface);
@@ -294,10 +362,10 @@
         mLargestColorDelta = -1;
 
         try {
-            MediaCodecInfo codecInfo = selectCodec(MIME_TYPE);
+            MediaCodecInfo codecInfo = selectCodec(mMimeType);
             if (codecInfo == null) {
                 // Don't fail CTS if they don't have an AVC codec (not here, anyway).
-                Log.e(TAG, "Unable to find an appropriate codec for " + MIME_TYPE);
+                Log.e(TAG, "Unable to find an appropriate codec for " + mMimeType);
                 return;
             }
             if (VERBOSE) Log.d(TAG, "found codec: " + codecInfo.getName());
@@ -306,7 +374,7 @@
 
             // We avoid the device-specific limitations on width and height by using values that
             // are multiples of 16, which all tested devices seem to be able to handle.
-            MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);
+            MediaFormat format = MediaFormat.createVideoFormat(mMimeType, mWidth, mHeight);
 
             // Set some properties.  Failing to specify some of these can cause the MediaCodec
             // configure() call to throw an unhelpful exception.
@@ -321,7 +389,7 @@
 
             // Create a MediaCodec for the decoder, just based on the MIME type.  The various
             // format details will be passed through the csd-0 meta-data later on.
-            decoder = MediaCodec.createDecoderByType(MIME_TYPE);
+            decoder = MediaCodec.createDecoderByType(mMimeType);
             if (VERBOSE) Log.d(TAG, "got decoder: " + decoder.getName());
             decoder.configure(format, outputSurface.getSurface(), null, 0);
             decoder.start();
@@ -537,7 +605,7 @@
                     encoderOutputBuffers = encoder.getOutputBuffers();
                     if (VERBOSE) Log.d(TAG, "encoder output buffers changed");
                 } else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
-                    // not expected for an encoder
+                    // expected on API 18+
                     MediaFormat newFormat = encoder.getOutputFormat();
                     if (VERBOSE) Log.d(TAG, "encoder output format changed: " + newFormat);
                 } else if (encoderStatus < 0) {
@@ -564,14 +632,18 @@
                             throw new RuntimeException(ioe);
                         }
                     }
-                    if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
+                    if (!decoderConfigured) {
                         // Codec config info.  Only expected on first packet.  One way to
                         // handle this is to manually stuff the data into the MediaFormat
                         // and pass that to configure().  We do that here to exercise the API.
-                        assertFalse(decoderConfigured);
+                        // For codecs that don't have codec config data (such as VP8),
+                        // initialize the decoder before trying to decode the first packet.
+                        assertTrue((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0 ||
+                                   mMimeType.equals(MIME_TYPE_VP8));
                         MediaFormat format =
-                                MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);
-                        format.setByteBuffer("csd-0", encodedData);
+                                MediaFormat.createVideoFormat(mMimeType, mWidth, mHeight);
+                        if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0)
+                            format.setByteBuffer("csd-0", encodedData);
                         decoder.configure(format, toSurface ? outputSurface.getSurface() : null,
                                 null, 0);
                         decoder.start();
@@ -579,7 +651,8 @@
                         decoderOutputBuffers = decoder.getOutputBuffers();
                         decoderConfigured = true;
                         if (VERBOSE) Log.d(TAG, "decoder configured (" + info.size + " bytes)");
-                    } else {
+                    }
+                    if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
                         // Get a decoder input buffer, blocking until it's available.
                         assertTrue(decoderConfigured);
                         int inputBufIndex = decoder.dequeueInputBuffer(-1);
@@ -821,7 +894,7 @@
                         encoderOutputBuffers = encoder.getOutputBuffers();
                         if (VERBOSE) Log.d(TAG, "encoder output buffers changed");
                     } else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
-                        // not expected for an encoder
+                        // expected on API 18+
                         MediaFormat newFormat = encoder.getOutputFormat();
                         if (VERBOSE) Log.d(TAG, "encoder output format changed: " + newFormat);
                     } else if (encoderStatus < 0) {
@@ -1000,16 +1073,17 @@
             x += cropLeft;
 
             int testY, testU, testV;
+            int off = frameData.position();
             if (semiPlanar) {
                 // Galaxy Nexus uses OMX_TI_COLOR_FormatYUV420PackedSemiPlanar
-                testY = frameData.get(y * width + x) & 0xff;
-                testU = frameData.get(width*height + 2*(y/2) * halfWidth + 2*(x/2)) & 0xff;
-                testV = frameData.get(width*height + 2*(y/2) * halfWidth + 2*(x/2) + 1) & 0xff;
+                testY = frameData.get(off + y * width + x) & 0xff;
+                testU = frameData.get(off + width*height + 2*(y/2) * halfWidth + 2*(x/2)) & 0xff;
+                testV = frameData.get(off + width*height + 2*(y/2) * halfWidth + 2*(x/2) + 1) & 0xff;
             } else {
                 // Nexus 10, Nexus 7 use COLOR_FormatYUV420Planar
-                testY = frameData.get(y * width + x) & 0xff;
-                testU = frameData.get(width*height + (y/2) * halfWidth + (x/2)) & 0xff;
-                testV = frameData.get(width*height + halfWidth * (height / 2) +
+                testY = frameData.get(off + y * width + x) & 0xff;
+                testU = frameData.get(off + width*height + (y/2) * halfWidth + (x/2)) & 0xff;
+                testV = frameData.get(off + width*height + halfWidth * (height / 2) +
                         (y/2) * halfWidth + (x/2)) & 0xff;
             }
 
@@ -1088,22 +1162,41 @@
             int b = pixelBuf.get(2) & 0xff;
             //Log.d(TAG, "GOT(" + frameIndex + "/" + i + "): r=" + r + " g=" + g + " b=" + b);
 
-            int expR, expG, expB;
+            int expR, expG, expB, expR_bt709, expG_bt709, expB_bt709;
             if (i == frameIndex % 8) {
                 // colored rect
                 expR = TEST_R1;
                 expG = TEST_G1;
                 expB = TEST_B1;
+                expR_bt709 = TEST_R1_BT709;
+                expG_bt709 = TEST_G1_BT709;
+                expB_bt709 = TEST_B1_BT709;
             } else {
                 // zero background color
                 expR = TEST_R0;
                 expG = TEST_G0;
                 expB = TEST_B0;
+                expR_bt709 = TEST_R0_BT709;
+                expG_bt709 = TEST_G0_BT709;
+                expB_bt709 = TEST_B0_BT709;
             }
-            if (!isColorClose(r, expR) ||
-                    !isColorClose(g, expG) ||
-                    !isColorClose(b, expB)) {
-                Log.w(TAG, "Bad frame " + frameIndex + " (rect=" + i + ": rgb=" + r +
+
+            // Some decoders use BT.709 when converting HD (i.e. >= 720p)
+            // frames from YUV to RGB, so check against both BT.601 and BT.709
+            if (mAllowBT601 &&
+                    isColorClose(r, expR) &&
+                    isColorClose(g, expG) &&
+                    isColorClose(b, expB)) {
+                // frame OK on BT.601
+                mAllowBT709 = false;
+            } else if (mAllowBT709 &&
+                           isColorClose(r, expR_bt709) &&
+                           isColorClose(g, expG_bt709) &&
+                           isColorClose(b, expB_bt709)) {
+                // frame OK on BT.709
+                mAllowBT601 = false;
+            } else {
+                Log.w(TAG, "Bad frame " + frameIndex + " (rect=" + i + " @ " + x + " " + y + ": rgb=" + r +
                         "," + g + "," + b + " vs. expected " + expR + "," + expG +
                         "," + expB + ")");
                 frameFailed = true;
diff --git a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayTest.java b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayTest.java
old mode 100644
new mode 100755
index 39c7b77..89b06dc
--- a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayTest.java
+++ b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayTest.java
@@ -65,20 +65,29 @@
     private static final boolean DEBUG_SAVE_FILE = false;   // save copy of encoded movie
     private static final String DEBUG_FILE_NAME_BASE = "/sdcard/test.";
 
+    // Encoder parameters table, sort by encoder level from high to low.
+    private static final int[][] ENCODER_PARAM_TABLE = {
+        // encoder level,                             width,   height,  bitrate,    framerate
+        {MediaCodecInfo.CodecProfileLevel.AVCLevel31, 1280,     720,    14000000,   30},
+        {MediaCodecInfo.CodecProfileLevel.AVCLevel3,   720,     480,    10000000,   30},
+        {MediaCodecInfo.CodecProfileLevel.AVCLevel22,  720,     480,    4000000,    15},
+        {MediaCodecInfo.CodecProfileLevel.AVCLevel21,  352,     576,    4000000,    25},
+    };
+
     // Virtual display characteristics.  Scaled down from full display size because not all
     // devices can encode at the resolution of their own display.
     private static final String NAME = TAG;
-    private static final int WIDTH = 1280;
-    private static final int HEIGHT = 720;
+    private static int sWidth = ENCODER_PARAM_TABLE[ENCODER_PARAM_TABLE.length-1][1];
+    private static int sHeight = ENCODER_PARAM_TABLE[ENCODER_PARAM_TABLE.length-1][2];
     private static final int DENSITY = DisplayMetrics.DENSITY_HIGH;
     private static final int UI_TIMEOUT_MS = 2000;
     private static final int UI_RENDER_PAUSE_MS = 400;
 
     // Encoder parameters.  We use the same width/height as the virtual display.
     private static final String MIME_TYPE = "video/avc";
-    private static final int FRAME_RATE = 15;               // 15fps
-    private static final int IFRAME_INTERVAL = 10;          // 10 seconds between I-frames
-    private static final int BIT_RATE = 6000000;            // 6Mbps
+    private static int sFrameRate = 15;               // 15fps
+    private static final int IFRAME_INTERVAL = 10;    // 10 seconds between I-frames
+    private static int sBitRate = 6000000;            // 6Mbps
 
     // Colors to test (RGB).  These must convert cleanly to and from BT.601 YUV.
     private static final int TEST_COLORS[] = {
@@ -106,6 +115,7 @@
 
         mUiHandler = new Handler(Looper.getMainLooper());
         mDisplayManager = (DisplayManager)mContext.getSystemService(Context.DISPLAY_SERVICE);
+        setupEncoderParameters();
     }
 
     /**
@@ -171,9 +181,65 @@
     }
 
     /**
+     * Returns true if the encoder level, specified in the ENCODER_PARAM_TABLE, can be supported.
+     */
+    private static boolean verifySupportForEncoderLevel(int index) {
+        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 (false == types[j].equalsIgnoreCase(MIME_TYPE)) {
+                    continue;
+                }
+
+                MediaCodecInfo.CodecCapabilities caps = codecInfo.getCapabilitiesForType(types[j]);
+                for (int k = 0; k < caps.profileLevels.length; k++) {
+                    int profile = caps.profileLevels[k].profile;
+                    int level = caps.profileLevels[k].level;
+                    //Log.d(TAG, "[" + k + "] supported profile = " + profile + ", level = " + level);
+                    if (caps.profileLevels[k].level >= ENCODER_PARAM_TABLE[index][0]) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Initialize the encoder parameters according to the device capability.
+     */
+    private static void setupEncoderParameters() {
+
+        // Loop over each tabel entry until a proper encoder setting is found.
+        for (int i = 0; i < ENCODER_PARAM_TABLE.length; i++) {
+
+            // Check if we can support it?
+            if (verifySupportForEncoderLevel(i)) {
+
+                sWidth = ENCODER_PARAM_TABLE[i][1];
+                sHeight = ENCODER_PARAM_TABLE[i][2];
+                sBitRate = ENCODER_PARAM_TABLE[i][3];
+                sFrameRate = ENCODER_PARAM_TABLE[i][4];
+
+                Log.d(TAG, "encoder parameters changed: width = " + sWidth + ", height = " + sHeight
+                    + ", bitrate = " + sBitRate + ", framerate = " + sFrameRate);
+                break;
+            }
+        }
+    }
+
+    /**
      * Prepares the encoder, decoder, and virtual display.
      */
-    private void encodeVirtualDisplayTest() {
+    private void encodeVirtualDisplayTest() throws IOException {
         MediaCodec encoder = null;
         MediaCodec decoder = null;
         OutputSurface outputSurface = null;
@@ -186,11 +252,11 @@
 
         try {
             // Encoded video resolution matches virtual display.
-            MediaFormat encoderFormat = MediaFormat.createVideoFormat(MIME_TYPE, WIDTH, HEIGHT);
+            MediaFormat encoderFormat = MediaFormat.createVideoFormat(MIME_TYPE, sWidth, sHeight);
             encoderFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,
                     MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
-            encoderFormat.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
-            encoderFormat.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
+            encoderFormat.setInteger(MediaFormat.KEY_BIT_RATE, sBitRate);
+            encoderFormat.setInteger(MediaFormat.KEY_FRAME_RATE, sFrameRate);
             encoderFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
 
             encoder = MediaCodec.createEncoderByType(MIME_TYPE);
@@ -200,12 +266,12 @@
 
             // Create a virtual display that will output to our encoder.
             virtualDisplay = mDisplayManager.createVirtualDisplay(NAME,
-                    WIDTH, HEIGHT, DENSITY, inputSurface, 0);
+                    sWidth, sHeight, DENSITY, inputSurface, 0);
 
             // We also need a decoder to check the output of the encoder.
             decoder = MediaCodec.createDecoderByType(MIME_TYPE);
-            MediaFormat decoderFormat = MediaFormat.createVideoFormat(MIME_TYPE, WIDTH, HEIGHT);
-            outputSurface = new OutputSurface(WIDTH, HEIGHT);
+            MediaFormat decoderFormat = MediaFormat.createVideoFormat(MIME_TYPE, sWidth, sHeight);
+            outputSurface = new OutputSurface(sWidth, sHeight);
             decoder.configure(decoderFormat, outputSurface.getSurface(), null, 0);
             decoder.start();
 
@@ -253,7 +319,7 @@
         // stream, not a .mp4 file, so not all players will know what to do with it.
         FileOutputStream outputStream = null;
         if (DEBUG_SAVE_FILE) {
-            String fileName = DEBUG_FILE_NAME_BASE + WIDTH + "x" + HEIGHT + ".mp4";
+            String fileName = DEBUG_FILE_NAME_BASE + sWidth + "x" + sHeight + ".mp4";
             try {
                 outputStream = new FileOutputStream(fileName);
                 Log.d(TAG, "encoded output will be saved as " + fileName);
@@ -447,8 +513,8 @@
 
         // Read a pixel from the center of the surface.  Might want to read from multiple points
         // and average them together.
-        int x = WIDTH / 2;
-        int y = HEIGHT / 2;
+        int x = sWidth / 2;
+        int y = sHeight / 2;
         GLES20.glReadPixels(x, y, 1, 1, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, mPixelBuf);
         int r = mPixelBuf.get(0) & 0xff;
         int g = mPixelBuf.get(1) & 0xff;
diff --git a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTest.java b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTest.java
index 369ae6e..7b21997 100644
--- a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTest.java
+++ b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTest.java
@@ -63,6 +63,7 @@
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.concurrent.Semaphore;
@@ -77,11 +78,11 @@
  */
 public class EncodeVirtualDisplayWithCompositionTest extends AndroidTestCase {
     private static final String TAG = "EncodeVirtualDisplayWithCompositionTest";
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
     private static final String MIME_TYPE = "video/avc";
 
-    private static final long DEFAULT_WAIT_TIMEOUT_MS = 5000;
-    private static final long DEFAULT_WAIT_TIMEOUT_US = 5000000;
+    private static final long DEFAULT_WAIT_TIMEOUT_MS = 3000;
+    private static final long DEFAULT_WAIT_TIMEOUT_US = 3000000;
 
     private static final int COLOR_RED =  makeColor(100, 0, 0);
     private static final int COLOR_BLUE =  makeColor(0, 100, 0);
@@ -139,8 +140,7 @@
         Log.i(TAG, "testRendering800x480Locally");
         Pair<Integer, Integer> maxRes = checkMaxConcurrentEncodingDecodingResolution();
         if (maxRes == null) {
-            Log.i(TAG, "codec not supported, skipping the test");
-            return;
+            fail("codec not supported");
         }
         if (maxRes.first >= 800 && maxRes.second >= 480) {
             runTestRenderingInSeparateThread(800, 480, false, false);
@@ -153,8 +153,7 @@
         Log.i(TAG, "testRenderingMaxResolutionLocally");
         Pair<Integer, Integer> maxRes = checkMaxConcurrentEncodingDecodingResolution();
         if (maxRes == null) {
-            Log.i(TAG, "codec not supported, skipping the test");
-            return;
+            fail("codec not supported");
         }
         Log.w(TAG, "Trying resolution w:" + maxRes.first + " h:" + maxRes.second);
         runTestRenderingInSeparateThread(maxRes.first, maxRes.second, false, false);
@@ -164,8 +163,7 @@
         Log.i(TAG, "testRendering800x480Remotely");
         Pair<Integer, Integer> maxRes = checkMaxConcurrentEncodingDecodingResolution();
         if (maxRes == null) {
-            Log.i(TAG, "codec not supported, skipping the test");
-            return;
+            fail("codec not supported");
         }
         if (maxRes.first >= 800 && maxRes.second >= 480) {
             runTestRenderingInSeparateThread(800, 480, true, false);
@@ -178,8 +176,7 @@
         Log.i(TAG, "testRenderingMaxResolutionRemotely");
         Pair<Integer, Integer> maxRes = checkMaxConcurrentEncodingDecodingResolution();
         if (maxRes == null) {
-            Log.i(TAG, "codec not supported, skipping the test");
-            return;
+            fail("codec not supported");
         }
         Log.w(TAG, "Trying resolution w:" + maxRes.first + " h:" + maxRes.second);
         runTestRenderingInSeparateThread(maxRes.first, maxRes.second, true, false);
@@ -189,8 +186,7 @@
         Log.i(TAG, "testRendering800x480RemotelyWith3Windows");
         Pair<Integer, Integer> maxRes = checkMaxConcurrentEncodingDecodingResolution();
         if (maxRes == null) {
-            Log.i(TAG, "codec not supported, skipping the test");
-            return;
+            fail("codec not supported");
         }
         if (maxRes.first >= 800 && maxRes.second >= 480) {
             runTestRenderingInSeparateThread(800, 480, true, true);
@@ -203,8 +199,7 @@
         Log.i(TAG, "testRendering800x480LocallyWith3Windows");
         Pair<Integer, Integer> maxRes = checkMaxConcurrentEncodingDecodingResolution();
         if (maxRes == null) {
-            Log.i(TAG, "codec not supported, skipping the test");
-            return;
+            fail("codec not supported");
         }
         if (maxRes.first >= 800 && maxRes.second >= 480) {
             runTestRenderingInSeparateThread(800, 480, false, true);
@@ -234,7 +229,7 @@
             }
         });
         renderingThread.start();
-        renderingThread.join(20000);
+        renderingThread.join(60000);
         assertTrue(!renderingThread.isAlive());
         if (mTestException != null) {
             throw mTestException;
@@ -573,7 +568,7 @@
                 while (!mStopEncoding) {
                     int index = mEncoder.dequeueOutputBuffer(info, TIMEOUT_USEC_NORMAL);
                     if (DBG) {
-                        Log.i(TAG, "dequeOutputBuffer returned " + index);
+                        Log.i(TAG, "encoder dequeOutputBuffer returned " + index);
                     }
                     if (index >= 0) {
                         if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
@@ -839,6 +834,12 @@
             GLES20.glUniformMatrix4fv(mGluMVPMatrixHandle, 1, false, mMVPMatrix, 0);
             mTopWindow.onDraw(mGluSTMatrixHandle, mGlaPositionHandle, mGlaTextureHandle);
             checkGlError("window draw");
+            if (DBG) {
+                final IntBuffer pixels = IntBuffer.allocate(1);
+                GLES20.glReadPixels(mWidth / 2, mHeight / 2, 1, 1,
+                        GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, pixels);
+                Log.i(TAG, "glReadPixels returned 0x" + Integer.toHexString(pixels.get(0)));
+            }
             mEglHelper.swapBuffers();
         }
 
@@ -1091,7 +1092,9 @@
                 @Override
                 public void run() {
                     mVirtualDisplay = mDisplayManager.createVirtualDisplay(
-                            TAG, mWidth, mHeight, 200, mSurface, 0);
+                            TAG, mWidth, mHeight, 200, mSurface,
+                            DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY |
+                            DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION);
                 }
             });
         }
@@ -1146,7 +1149,9 @@
     private static class TestPresentationBase extends Presentation {
 
         public TestPresentationBase(Context outerContext, Display display) {
-            super(outerContext, display);
+            // This theme is required to prevent an extra view from obscuring the presentation
+            super(outerContext, display,
+                    android.R.style.Theme_Holo_Light_NoActionBar_TranslucentDecor);
             getWindow().setType(WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION);
             getWindow().addFlags(WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE);
             getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
@@ -1175,6 +1180,9 @@
         }
 
         public void doRendering(int color) {
+            if (DBG) {
+                Log.i(TAG, "doRendering " + Integer.toHexString(color));
+            }
             mImageView.setImageDrawable(new ColorDrawable(color));
         }
     }
diff --git a/tests/tests/media/src/android/media/cts/EncoderTest.java b/tests/tests/media/src/android/media/cts/EncoderTest.java
index e9d0b5f..c2e59d4 100644
--- a/tests/tests/media/src/android/media/cts/EncoderTest.java
+++ b/tests/tests/media/src/android/media/cts/EncoderTest.java
@@ -187,8 +187,13 @@
     }
 
     private void testEncoder(String componentName, MediaFormat format) {
-        MediaCodec codec = MediaCodec.createByCodecName(componentName);
-
+        MediaCodec codec;
+        try {
+            codec = MediaCodec.createByCodecName(componentName);
+        } catch (Exception e) {
+            fail("codec '" + componentName + "' failed construction.");
+            return; /* does not get here, but avoids warning */
+        }
         try {
             codec.configure(
                     format,
@@ -196,9 +201,7 @@
                     null /* crypto */,
                     MediaCodec.CONFIGURE_FLAG_ENCODE);
         } catch (IllegalStateException e) {
-            Log.e(TAG, "codec '" + componentName + "' failed configuration.");
-
-            assertTrue("codec '" + componentName + "' failed configuration.", false);
+            fail("codec '" + componentName + "' failed configuration.");
         }
 
         codec.start();
diff --git a/tests/tests/media/src/android/media/cts/EnvReverbTest.java b/tests/tests/media/src/android/media/cts/EnvReverbTest.java
index edfef96..e2e9b6d 100644
--- a/tests/tests/media/src/android/media/cts/EnvReverbTest.java
+++ b/tests/tests/media/src/android/media/cts/EnvReverbTest.java
@@ -24,7 +24,7 @@
 import android.test.AndroidTestCase;
 import android.util.Log;
 
-public class EnvReverbTest extends AndroidTestCase {
+public class EnvReverbTest extends PostProcTestBase {
 
     private String TAG = "EnvReverbTest";
     private final static int MILLIBEL_TOLERANCE = 100;            // +/-1dB
@@ -34,13 +34,6 @@
 
     private EnvironmentalReverb mReverb = null;
     private EnvironmentalReverb mReverb2 = null;
-    private int mSession = -1;
-    private boolean mHasControl = false;
-    private boolean mIsEnabled = false;
-    private int mChangedParameter = -1;
-    private boolean mInitialized = false;
-    private Looper mLooper = null;
-    private final Object mLock = new Object();
     private ListenerThread mEffectListenerLooper = null;
 
     //-----------------------------------------------------------------
@@ -53,10 +46,12 @@
 
     //Test case 0.0: test constructor and release
     public void test0_0ConstructorAndRelease() throws Exception {
+        if (!isEnvReverbAvailable()) {
+            return;
+        }
         EnvironmentalReverb envReverb = null;
          try {
             envReverb = new EnvironmentalReverb(0, 0);
-            assertNotNull("could not create EnvironmentalReverb", envReverb);
             try {
                 assertTrue("invalid effect ID", (envReverb.getId() != 0));
             } catch (IllegalStateException e) {
@@ -80,6 +75,9 @@
 
     //Test case 1.0: test room level and room HF level
     public void test1_0Room() throws Exception {
+        if (!isEnvReverbAvailable()) {
+            return;
+        }
         getReverb(0);
         try {
             short level = mReverb.getRoomLevel();
@@ -111,6 +109,9 @@
 
     //Test case 1.1: test decay time and ratio
     public void test1_1Decay() throws Exception {
+        if (!isEnvReverbAvailable()) {
+            return;
+        }
         getReverb(0);
         try {
             int time = mReverb.getDecayTime();
@@ -142,6 +143,9 @@
 
     //Test case 1.2: test reverb level and delay
     public void test1_2Reverb() throws Exception {
+        if (!isEnvReverbAvailable()) {
+            return;
+        }
         getReverb(0);
         try {
             short level = mReverb.getReverbLevel();
@@ -175,6 +179,9 @@
 
     //Test case 1.3: test early reflections level and delay
     public void test1_3Reflections() throws Exception {
+        if (!isEnvReverbAvailable()) {
+            return;
+        }
         getReverb(0);
         try {
 // FIXME:uncomment actual test when early reflections are implemented in the reverb
@@ -213,6 +220,9 @@
 
     //Test case 1.4: test diffusion and density
     public void test1_4DiffusionAndDensity() throws Exception {
+        if (!isEnvReverbAvailable()) {
+            return;
+        }
         getReverb(0);
         try {
             short ratio = mReverb.getDiffusion();
@@ -244,6 +254,9 @@
 
     //Test case 1.5: test properties
     public void test1_5Properties() throws Exception {
+        if (!isEnvReverbAvailable()) {
+            return;
+        }
         getReverb(0);
         try {
             EnvironmentalReverb.Settings settings = mReverb.getProperties();
@@ -273,6 +286,9 @@
 
     //Test case 2.0: test setEnabled() and getEnabled() in valid state
     public void test2_0SetEnabledGetEnabled() throws Exception {
+        if (!isEnvReverbAvailable()) {
+            return;
+        }
         getReverb(0);
         try {
             mReverb.setEnabled(true);
@@ -306,6 +322,9 @@
 
     //Test case 3.0: test control status listener
     public void test3_0ControlStatusListener() throws Exception {
+        if (!isEnvReverbAvailable()) {
+            return;
+        }
         synchronized(mLock) {
             mHasControl = true;
             mInitialized = false;
@@ -328,6 +347,9 @@
 
     //Test case 3.1: test enable status listener
     public void test3_1EnableStatusListener() throws Exception {
+        if (!isEnvReverbAvailable()) {
+            return;
+        }
          synchronized(mLock) {
             mInitialized = false;
             createListenerLooper(false, true, false);
@@ -352,6 +374,9 @@
 
     //Test case 3.2: test parameter changed listener
     public void test3_2ParameterChangedListener() throws Exception {
+        if (!isEnvReverbAvailable()) {
+            return;
+        }
         synchronized(mLock) {
             mInitialized = false;
             createListenerLooper(false, false, true);
@@ -523,5 +548,4 @@
             mReverb2 = null;
         }
     }
-
 }
\ No newline at end of file
diff --git a/tests/tests/media/src/android/media/cts/EqualizerTest.java b/tests/tests/media/src/android/media/cts/EqualizerTest.java
index 3bc0d8e..15f0c73 100644
--- a/tests/tests/media/src/android/media/cts/EqualizerTest.java
+++ b/tests/tests/media/src/android/media/cts/EqualizerTest.java
@@ -24,7 +24,7 @@
 import android.test.AndroidTestCase;
 import android.util.Log;
 
-public class EqualizerTest extends AndroidTestCase {
+public class EqualizerTest extends PostProcTestBase {
 
     private String TAG = "EqualizerTest";
     private final static int MIN_NUMBER_OF_BANDS = 4;
@@ -37,13 +37,6 @@
 
     private Equalizer mEqualizer = null;
     private Equalizer mEqualizer2 = null;
-    private int mSession = -1;
-    private boolean mHasControl = false;
-    private boolean mIsEnabled = false;
-    private int mChangedParameter = -1;
-    private boolean mInitialized = false;
-    private Looper mLooper = null;
-    private final Object mLock = new Object();
     private ListenerThread mEffectListenerLooper = null;
 
     //-----------------------------------------------------------------
@@ -56,10 +49,12 @@
 
     //Test case 0.0: test constructor and release
     public void test0_0ConstructorAndRelease() throws Exception {
+        if (!hasAudioOutput()) {
+            return;
+        }
         Equalizer eq = null;
         try {
             eq = new Equalizer(0, 0);
-            assertNotNull("could not create Equalizer", eq);
             try {
                 assertTrue("invalid effect ID", (eq.getId() != 0));
             } catch (IllegalStateException e) {
@@ -83,6 +78,9 @@
 
     //Test case 1.0: test setBandLevel() and getBandLevel()
     public void test1_0BandLevel() throws Exception {
+        if (!hasAudioOutput()) {
+            return;
+        }
         getEqualizer(0);
         try {
             short numBands = mEqualizer.getNumberOfBands();
@@ -112,6 +110,9 @@
 
     //Test case 1.1: test band frequency
     public void test1_1BandFrequency() throws Exception {
+        if (!hasAudioOutput()) {
+            return;
+        }
         getEqualizer(0);
         try {
             short band = mEqualizer.getBand(TEST_FREQUENCY_MILLIHERTZ);
@@ -137,6 +138,9 @@
 
     //Test case 1.2: test presets
     public void test1_2Presets() throws Exception {
+        if (!hasAudioOutput()) {
+            return;
+        }
         getEqualizer(0);
         try {
             short numPresets = mEqualizer.getNumberOfPresets();
@@ -162,6 +166,9 @@
 
     //Test case 1.3: test properties
     public void test1_3Properties() throws Exception {
+        if (!hasAudioOutput()) {
+            return;
+        }
         getEqualizer(0);
         try {
             Equalizer.Settings settings = mEqualizer.getProperties();
@@ -193,7 +200,9 @@
 
     //Test case 1.4: test setBandLevel() throws exception after release
     public void test1_4SetBandLevelAfterRelease() throws Exception {
-
+        if (!hasAudioOutput()) {
+            return;
+        }
         getEqualizer(0);
         mEqualizer.release();
         try {
@@ -211,6 +220,9 @@
 
     //Test case 2.0: test setEnabled() and getEnabled() in valid state
     public void test2_0SetEnabledGetEnabled() throws Exception {
+        if (!hasAudioOutput()) {
+            return;
+        }
         getEqualizer(0);
         try {
             mEqualizer.setEnabled(true);
@@ -227,7 +239,9 @@
 
     //Test case 2.1: test setEnabled() throws exception after release
     public void test2_1SetEnabledAfterRelease() throws Exception {
-
+        if (!hasAudioOutput()) {
+            return;
+        }
         getEqualizer(0);
         mEqualizer.release();
         try {
@@ -245,6 +259,9 @@
 
     //Test case 3.0: test control status listener
     public void test3_0ControlStatusListener() throws Exception {
+        if (!hasAudioOutput()) {
+            return;
+        }
         synchronized(mLock) {
             mHasControl = true;
             mInitialized = false;
@@ -267,6 +284,9 @@
 
     //Test case 3.1: test enable status listener
     public void test3_1EnableStatusListener() throws Exception {
+        if (!hasAudioOutput()) {
+            return;
+        }
         synchronized(mLock) {
             mInitialized = false;
             createListenerLooper(false, true, false);
@@ -291,6 +311,9 @@
 
     //Test case 3.2: test parameter changed listener
     public void test3_2ParameterChangedListener() throws Exception {
+        if (!hasAudioOutput()) {
+            return;
+        }
         synchronized(mLock) {
             mInitialized = false;
             createListenerLooper(false, false, true);
@@ -460,5 +483,4 @@
             mEqualizer2 = null;
         }
     }
-
 }
diff --git a/tests/tests/media/src/android/media/cts/ExtractDecodeEditEncodeMuxTest.java b/tests/tests/media/src/android/media/cts/ExtractDecodeEditEncodeMuxTest.java
index 40b4949..43b769a 100644
--- a/tests/tests/media/src/android/media/cts/ExtractDecodeEditEncodeMuxTest.java
+++ b/tests/tests/media/src/android/media/cts/ExtractDecodeEditEncodeMuxTest.java
@@ -517,7 +517,8 @@
      * @param inputFormat the format of the stream to decode
      * @param surface into which to decode the frames
      */
-    private MediaCodec createVideoDecoder(MediaFormat inputFormat, Surface surface) {
+    private MediaCodec createVideoDecoder(MediaFormat inputFormat, Surface surface)
+            throws IOException {
         MediaCodec decoder = MediaCodec.createDecoderByType(getMimeTypeFor(inputFormat));
         decoder.configure(inputFormat, surface, null, 0);
         decoder.start();
@@ -537,7 +538,8 @@
     private MediaCodec createVideoEncoder(
             MediaCodecInfo codecInfo,
             MediaFormat format,
-            AtomicReference<Surface> surfaceReference) {
+            AtomicReference<Surface> surfaceReference)
+            throws IOException {
         MediaCodec encoder = MediaCodec.createByCodecName(codecInfo.getName());
         encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
         // Must be called before start() is.
@@ -551,7 +553,8 @@
      *
      * @param inputFormat the format of the stream to decode
      */
-    private MediaCodec createAudioDecoder(MediaFormat inputFormat) {
+    private MediaCodec createAudioDecoder(MediaFormat inputFormat)
+            throws IOException {
         MediaCodec decoder = MediaCodec.createDecoderByType(getMimeTypeFor(inputFormat));
         decoder.configure(inputFormat, null, null, 0);
         decoder.start();
@@ -564,7 +567,8 @@
      * @param codecInfo of the codec to use
      * @param format of the stream to be produced
      */
-    private MediaCodec createAudioEncoder(MediaCodecInfo codecInfo, MediaFormat format) {
+    private MediaCodec createAudioEncoder(MediaCodecInfo codecInfo, MediaFormat format) 
+            throws IOException {
         MediaCodec encoder = MediaCodec.createByCodecName(codecInfo.getName());
         encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
         encoder.start();
diff --git a/tests/tests/media/src/android/media/cts/ImageReaderDecoderTest.java b/tests/tests/media/src/android/media/cts/ImageReaderDecoderTest.java
new file mode 100644
index 0000000..d620995
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/ImageReaderDecoderTest.java
@@ -0,0 +1,520 @@
+/*
+ * 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.media.cts;
+
+import com.android.cts.media.R;
+
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
+import android.graphics.ImageFormat;
+import android.media.Image;
+import android.media.Image.Plane;
+import android.media.ImageReader;
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecInfo.CodecCapabilities;
+import android.media.MediaCodecList;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.test.AndroidTestCase;
+import android.util.Log;
+import android.view.Surface;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Basic test for ImageReader APIs.
+ * <p>
+ * It uses MediaCodec to decode a short video stream, send the video frames to
+ * the surface provided by ImageReader. Then compare if output buffers of the
+ * ImageReader matches the output buffers of the MediaCodec. The video format
+ * used here is AVC although the compression format doesn't matter for this
+ * test. For decoder test, hw and sw decoders are tested,
+ * </p>
+ */
+public class ImageReaderDecoderTest extends AndroidTestCase {
+    private static final String TAG = "ImageReaderDecoderTest";
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    private static final long DEFAULT_TIMEOUT_US = 10000;
+    private static final long WAIT_FOR_IMAGE_TIMEOUT_MS = 1000;
+    private static final String DEBUG_FILE_NAME_BASE = "/sdcard/";
+    private static final int NUM_FRAME_DECODED = 100;
+    private static final int MAX_NUM_IMAGES = 3;
+
+    private Resources mResources;
+    private MediaCodec.BufferInfo mBufferInfo = new MediaCodec.BufferInfo();
+    private ByteBuffer[] mInputBuffers;
+    private ByteBuffer[] mOutputBuffers;
+    private ImageReader mReader;
+    private Surface mReaderSurface;
+    private HandlerThread mHandlerThread;
+    private Handler mHandler;
+    private ImageListener mImageListener;
+
+    @Override
+    public void setContext(Context context) {
+        super.setContext(context);
+        mResources = mContext.getResources();
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mHandlerThread = new HandlerThread(TAG);
+        mHandlerThread.start();
+        mHandler = new Handler(mHandlerThread.getLooper());
+        mImageListener = new ImageListener();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mHandlerThread.quitSafely();
+        mHandler = null;
+    }
+
+    /**
+     * Test ImageReader with 480x360 hw AVC decoding for flexible yuv format, which is mandatory
+     * to be supported by hw decoder.
+     */
+    public void testHwAVCDecode360pForFlexibleYuv() throws Exception {
+        try {
+            int format = ImageFormat.YUV_420_888;
+            videoDecodeToSurface(
+                    R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz,
+                    /* width */480, /* height */ 360, format, /* useHw */ true);
+        } finally {
+            closeImageReader();
+        }
+    }
+
+    /**
+     * Test ImageReader with 480x360 sw AVC decoding for flexible yuv format, which is mandatory
+     * to be supported by sw decoder.
+     */
+    public void testSwAVCDecode360pForFlexibleYuv() throws Exception {
+        try {
+            int format = ImageFormat.YUV_420_888;
+            videoDecodeToSurface(
+                    R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz,
+                    /* width */ 480, /* height */ 360, format, /* useHw */ false);
+        } finally {
+            closeImageReader();
+        }
+    }
+
+    private static class ImageListener implements ImageReader.OnImageAvailableListener {
+        private final LinkedBlockingQueue<Image> mQueue =
+                new LinkedBlockingQueue<Image>();
+
+        @Override
+        public void onImageAvailable(ImageReader reader) {
+            try {
+                mQueue.put(reader.acquireNextImage());
+            } catch (InterruptedException e) {
+                throw new UnsupportedOperationException(
+                        "Can't handle InterruptedException in onImageAvailable");
+            }
+        }
+
+        /**
+         * Get an image from the image reader.
+         *
+         * @param timeout Timeout value for the wait.
+         * @return The image from the image reader.
+         */
+        public Image getImage(long timeout) throws InterruptedException {
+            Image image = mQueue.poll(timeout, TimeUnit.MILLISECONDS);
+            assertNotNull("Wait for an image timed out in " + timeout + "ms", image);
+            return image;
+        }
+    }
+
+    private void videoDecodeToSurface(int video, int width,
+            int height, int imageFormat, boolean useHw) throws Exception {
+        MediaCodec decoder = null;
+        MediaExtractor extractor;
+        int outputBufferIndex;
+        ByteBuffer[] decoderInputBuffers;
+        ByteBuffer[] decoderOutputBuffers;
+
+        AssetFileDescriptor vidFD = mResources.openRawResourceFd(video);
+
+        extractor = new MediaExtractor();
+        extractor.setDataSource(vidFD.getFileDescriptor(), vidFD.getStartOffset(),
+                vidFD.getLength());
+
+        MediaFormat mediaFmt = extractor.getTrackFormat(0);
+        mediaFmt.setInteger(MediaFormat.KEY_COLOR_FORMAT,
+                            CodecCapabilities.COLOR_FormatYUV420Flexible);
+        String mime = mediaFmt.getString(MediaFormat.KEY_MIME);
+        try {
+            // Create decoder
+            decoder = createDecoder(mime, useHw);
+            assertNotNull("couldn't find decoder", decoder);
+            if (VERBOSE) Log.v(TAG, "using decoder: " + decoder.getName());
+
+            decodeFramesToImageReader(width, height, imageFormat, decoder,
+                    extractor, mediaFmt, mime);
+
+            decoder.stop();
+        } finally {
+            decoder.release();
+        }
+
+    }
+
+    /**
+     * Decode video frames to image reader.
+     */
+    private void decodeFramesToImageReader(int width, int height, int imageFormat,
+            MediaCodec decoder, MediaExtractor extractor, MediaFormat mediaFmt, String mime)
+            throws Exception, InterruptedException {
+        ByteBuffer[] decoderInputBuffers;
+        ByteBuffer[] decoderOutputBuffers;
+        if (!imageFormatSupported(decoder, imageFormat, mime)) {
+            // TODO: SKIPPING TEST
+            return;
+        }
+        createImageReader(width, height, imageFormat, MAX_NUM_IMAGES, mImageListener);
+
+        // Configure decoder.
+        if (VERBOSE) Log.v(TAG, "stream format: " + mediaFmt);
+        decoder.configure(mediaFmt, mReaderSurface, /*crypto*/null, /*flags*/0);
+        decoder.start();
+        decoderInputBuffers = decoder.getInputBuffers();
+        decoderOutputBuffers = decoder.getOutputBuffers();
+        extractor.selectTrack(0);
+
+        // Start decoding and get Image, only test the first NUM_FRAME_DECODED frames.
+        MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
+        boolean sawInputEOS = false;
+        boolean sawOutputEOS = false;
+        int outputFrameCount = 0;
+        while (!sawOutputEOS && outputFrameCount < NUM_FRAME_DECODED) {
+            if (VERBOSE) Log.v(TAG, "loop:" + outputFrameCount);
+            // Feed input frame.
+            if (!sawInputEOS) {
+                int inputBufIndex = decoder.dequeueInputBuffer(DEFAULT_TIMEOUT_US);
+                if (inputBufIndex >= 0) {
+                    ByteBuffer dstBuf = decoderInputBuffers[inputBufIndex];
+                    int sampleSize =
+                        extractor.readSampleData(dstBuf, 0 /* offset */);
+
+                    if (VERBOSE) Log.v(TAG, "queue a input buffer, idx/size: "
+                        + inputBufIndex + "/" + sampleSize);
+
+                    long presentationTimeUs = 0;
+
+                    if (sampleSize < 0) {
+                        if (VERBOSE) Log.v(TAG, "saw input EOS.");
+                        sawInputEOS = true;
+                        sampleSize = 0;
+                    } else {
+                        presentationTimeUs = extractor.getSampleTime();
+                    }
+
+                    decoder.queueInputBuffer(
+                            inputBufIndex,
+                            0 /* offset */,
+                            sampleSize,
+                            presentationTimeUs,
+                            sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
+
+                    if (!sawInputEOS) {
+                        extractor.advance();
+                    }
+                }
+            }
+
+            // Get output frame
+            int res = decoder.dequeueOutputBuffer(info, DEFAULT_TIMEOUT_US);
+            if (VERBOSE) Log.v(TAG, "got a buffer: " + info.size + "/" + res);
+            if (res == MediaCodec.INFO_TRY_AGAIN_LATER) {
+                // no output available yet
+                if (VERBOSE) Log.v(TAG, "no output frame available");
+            } else if (res == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
+                // decoder output buffers changed, need update.
+                if (VERBOSE) Log.v(TAG, "decoder output buffers changed");
+                decoderOutputBuffers = decoder.getOutputBuffers();
+            } else if (res == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+                // this happens before the first frame is returned.
+                MediaFormat outFormat = decoder.getOutputFormat();
+                if (VERBOSE) Log.v(TAG, "decoder output format changed: " + outFormat);
+            } else if (res < 0) {
+                // Should be decoding error.
+                fail("unexpected result from deocder.dequeueOutputBuffer: " + res);
+            } else {
+                // res >= 0: normal decoding case, copy the output buffer.
+                // Will use it as reference to valid the ImageReader output
+                // Some decoders output a 0-sized buffer at the end. Ignore those.
+                outputFrameCount++;
+                boolean doRender = (info.size != 0);
+
+                decoder.releaseOutputBuffer(res, doRender);
+                if (doRender) {
+                    // Read image and verify
+                    Image image = mImageListener.getImage(WAIT_FOR_IMAGE_TIMEOUT_MS);
+                    Plane[] imagePlanes = image.getPlanes();
+
+                    //Verify
+                    String fileName = DEBUG_FILE_NAME_BASE + width + "x" + height + "_"
+                            + outputFrameCount + ".yuv";
+                    validateImage(image, width, height, imageFormat, fileName);
+
+                    if (VERBOSE) {
+                        Log.v(TAG, "Image " + outputFrameCount + " Info:");
+                        Log.v(TAG, "first plane pixelstride " + imagePlanes[0].getPixelStride());
+                        Log.v(TAG, "first plane rowstride " + imagePlanes[0].getRowStride());
+                        Log.v(TAG, "Image timestamp:" + image.getTimestamp());
+                    }
+                    image.close();
+                }
+            }
+        }
+    }
+
+    private boolean imageFormatSupported(MediaCodec decoder, int imageFormat, String mime) {
+        MediaCodecInfo codecInfo = decoder.getCodecInfo();
+        if (codecInfo == null) {
+            return false;
+        }
+        MediaCodecInfo.CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(mime);
+        for (int colorFormat : capabilities.colorFormats) {
+            if (colorFormat == CodecCapabilities.COLOR_FormatYUV420Flexible
+                    && imageFormat == ImageFormat.YUV_420_888) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private MediaCodec createDecoder(String mime, boolean useHw) throws Exception {
+        if (!useHw) {
+            if (mime.contains("avc")) {
+                return MediaCodec.createByCodecName("OMX.google.h264.decoder");
+            } else if (mime.contains("3gpp")) {
+                return MediaCodec.createByCodecName("OMX.google.h263.decoder");
+            } else if (mime.contains("mp4v")) {
+                return MediaCodec.createByCodecName("OMX.google.mpeg4.decoder");
+            } else if (mime.contains("vp8")) {
+                return MediaCodec.createByCodecName("OMX.google.vpx.decoder");
+            }
+        }
+        return MediaCodec.createDecoderByType(mime);
+    }
+
+    /**
+     * Validate image based on format and size.
+     *
+     * @param image The image to be validated.
+     * @param width The image width.
+     * @param height The image height.
+     * @param format The image format.
+     * @param filePath The debug dump file path, null if don't want to dump to file.
+     */
+    public static void validateImage(Image image, int width, int height, int format,
+            String filePath) {
+        assertNotNull("Input image is invalid", image);
+        assertEquals("Format doesn't match", format, image.getFormat());
+        assertEquals("Width doesn't match", width, image.getWidth());
+        assertEquals("Height doesn't match", height, image.getHeight());
+
+        if(VERBOSE) Log.v(TAG, "validating Image");
+        byte[] data = getDataFromImage(image);
+        assertTrue("Invalid image data", data != null && data.length > 0);
+
+        validateYuvData(data, width, height, format, image.getTimestamp(), filePath);
+    }
+
+    private static void validateYuvData(byte[] yuvData, int width, int height, int format,
+            long ts, String fileName) {
+
+        assertTrue("YUV format must be one of the YUV_420_888, NV21, or YV12",
+                format == ImageFormat.YUV_420_888 ||
+                format == ImageFormat.NV21 ||
+                format == ImageFormat.YV12);
+
+        if (VERBOSE) Log.v(TAG, "Validating YUV data");
+        int expectedSize = width * height * ImageFormat.getBitsPerPixel(format) / 8;
+        assertEquals("Yuv data doesn't match", expectedSize, yuvData.length);
+
+        if (DEBUG && fileName != null) {
+            dumpFile(fileName, yuvData);
+        }
+    }
+
+    private static void checkYuvFormat(int format) {
+        if ((format != ImageFormat.YUV_420_888) &&
+                (format != ImageFormat.NV21) &&
+                (format != ImageFormat.YV12)) {
+            fail("Wrong formats: " + format);
+        }
+    }
+    /**
+     * <p>Check android image format validity for an image, only support below formats:</p>
+     *
+     * <p>Valid formats are YUV_420_888/NV21/YV12 for video decoder</p>
+     */
+    private static void checkAndroidImageFormat(Image image) {
+        int format = image.getFormat();
+        Plane[] planes = image.getPlanes();
+        switch (format) {
+            case ImageFormat.YUV_420_888:
+            case ImageFormat.NV21:
+            case ImageFormat.YV12:
+                assertEquals("YUV420 format Images should have 3 planes", 3, planes.length);
+                break;
+            default:
+                fail("Unsupported Image Format: " + format);
+        }
+    }
+
+    /**
+     * Get a byte array image data from an Image object.
+     * <p>
+     * Read data from all planes of an Image into a contiguous unpadded,
+     * unpacked 1-D linear byte array, such that it can be write into disk, or
+     * accessed by software conveniently. It supports YUV_420_888/NV21/YV12
+     * input Image format.
+     * </p>
+     * <p>
+     * For YUV_420_888/NV21/YV12/Y8/Y16, it returns a byte array that contains
+     * the Y plane data first, followed by U(Cb), V(Cr) planes if there is any
+     * (xstride = width, ystride = height for chroma and luma components).
+     * </p>
+     */
+    private static byte[] getDataFromImage(Image image) {
+        assertNotNull("Invalid image:", image);
+        int format = image.getFormat();
+        int width = image.getWidth();
+        int height = image.getHeight();
+        int rowStride, pixelStride;
+        byte[] data = null;
+
+        // Read image data
+        Plane[] planes = image.getPlanes();
+        assertTrue("Fail to get image planes", planes != null && planes.length > 0);
+
+        // Check image validity
+        checkAndroidImageFormat(image);
+
+        ByteBuffer buffer = null;
+
+        int offset = 0;
+        data = new byte[width * height * ImageFormat.getBitsPerPixel(format) / 8];
+        byte[] rowData = new byte[planes[0].getRowStride()];
+        if(VERBOSE) Log.v(TAG, "get data from " + planes.length + " planes");
+        for (int i = 0; i < planes.length; i++) {
+            buffer = planes[i].getBuffer();
+            assertNotNull("Fail to get bytebuffer from plane", buffer);
+            rowStride = planes[i].getRowStride();
+            pixelStride = planes[i].getPixelStride();
+            assertTrue("pixel stride " + pixelStride + " is invalid", pixelStride > 0);
+            if (VERBOSE) {
+                Log.v(TAG, "pixelStride " + pixelStride);
+                Log.v(TAG, "rowStride " + rowStride);
+                Log.v(TAG, "width " + width);
+                Log.v(TAG, "height " + height);
+            }
+            // For multi-planar yuv images, assuming yuv420 with 2x2 chroma subsampling.
+            int w = (i == 0) ? width : width / 2;
+            int h = (i == 0) ? height : height / 2;
+            assertTrue("rowStride " + rowStride + " should be >= width " + w , rowStride >= w);
+            for (int row = 0; row < h; row++) {
+                int bytesPerPixel = ImageFormat.getBitsPerPixel(format) / 8;
+                if (pixelStride == bytesPerPixel) {
+                    // Special case: optimized read of the entire row
+                    int length = w * bytesPerPixel;
+                    buffer.get(data, offset, length);
+                    // Advance buffer the remainder of the row stride
+                    buffer.position(buffer.position() + rowStride - length);
+                    offset += length;
+                } else {
+                    // Generic case: should work for any pixelStride but slower.
+                    // Use intermediate buffer to avoid read byte-by-byte from
+                    // DirectByteBuffer, which is very bad for performance
+                    buffer.get(rowData, 0, rowStride);
+                    for (int col = 0; col < w; col++) {
+                        data[offset++] = rowData[col * pixelStride];
+                    }
+                }
+            }
+            if (VERBOSE) Log.v(TAG, "Finished reading data from plane " + i);
+        }
+        return data;
+    }
+
+    private static void dumpFile(String fileName, byte[] data) {
+        assertNotNull("fileName must not be null", fileName);
+        assertNotNull("data must not be null", data);
+
+        FileOutputStream outStream;
+        try {
+            Log.v(TAG, "output will be saved as " + fileName);
+            outStream = new FileOutputStream(fileName);
+        } catch (IOException ioe) {
+            throw new RuntimeException("Unable to create debug output file " + fileName, ioe);
+        }
+
+        try {
+            outStream.write(data);
+            outStream.close();
+        } catch (IOException ioe) {
+            throw new RuntimeException("failed writing data to file " + fileName, ioe);
+        }
+    }
+
+    private void createImageReader(int width, int height, int format, int maxNumImages,
+            ImageReader.OnImageAvailableListener listener) throws Exception {
+        closeImageReader();
+
+        mReader = ImageReader.newInstance(width, height, format, maxNumImages);
+        mReaderSurface = mReader.getSurface();
+        mReader.setOnImageAvailableListener(listener, mHandler);
+        if (VERBOSE) {
+            Log.v(TAG, String.format("Created ImageReader size (%dx%d), format %d", width, height,
+                    format));
+        }
+    }
+
+    /**
+     * Close the pending images then close current active {@link ImageReader} object.
+     */
+    private void closeImageReader() {
+        if (mReader != null) {
+            try {
+                // Close all possible pending images first.
+                Image image = mReader.acquireLatestImage();
+                if (image != null) {
+                    image.close();
+                }
+            } finally {
+                mReader.close();
+                mReader = null;
+            }
+        }
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/IvfReader.java b/tests/tests/media/src/android/media/cts/IvfReader.java
index 508ae25..2f679ae 100644
--- a/tests/tests/media/src/android/media/cts/IvfReader.java
+++ b/tests/tests/media/src/android/media/cts/IvfReader.java
@@ -22,18 +22,19 @@
 /**
  * A simple reader for an IVF file.
  *
- * IVF format is a simple container format for VP8 encoded frames.
+ * IVF format is a simple container format for VP8 encoded frames defined at
+ * http://wiki.multimedia.cx/index.php?title=IVF.
  * This reader is capable of getting frame count, width and height
  * from the header, and access individual frames randomly by
  * frame number.
  */
 
 public class IvfReader {
-    private static final byte HEADER_END = 32;
-    private static final byte FOURCC_HEAD = 8;
-    private static final byte WIDTH_HEAD = 12;
-    private static final byte HEIGHT_HEAD = 14;
-    private static final byte FRAMECOUNT_HEAD = 24;
+    private static final byte HEADER_SIZE = 32;
+    private static final byte FOURCC_OFFSET = 8;
+    private static final byte WIDTH_OFFSET = 12;
+    private static final byte HEIGHT_OFFSET = 14;
+    private static final byte FRAMECOUNT_OFFSET = 24;
     private static final byte FRAME_HEADER_SIZE = 12;
 
     private RandomAccessFile mIvfFile;
@@ -101,7 +102,7 @@
      * than 0 and less than frameCount.
      */
     public byte[] readFrame(int frameIndex) throws IOException {
-        if (frameIndex > mFrameCount | frameIndex < 0){
+        if (frameIndex > mFrameCount || frameIndex < 0){
             return null;
         }
         int frameSize = mFrameSizes[frameIndex];
@@ -124,7 +125,7 @@
     private boolean verifyHeader() throws IOException{
         mIvfFile.seek(0);
 
-        if (mIvfFile.length() < HEADER_END){
+        if (mIvfFile.length() < HEADER_SIZE){
             return false;
         }
 
@@ -135,7 +136,7 @@
                 (mIvfFile.readByte() == (byte)'F'));
 
         // Fourcc
-        mIvfFile.seek(FOURCC_HEAD);
+        mIvfFile.seek(FOURCC_OFFSET);
         boolean fourccMatch = ((mIvfFile.readByte() == (byte)'V') &&
                 (mIvfFile.readByte() == (byte)'P') &&
                 (mIvfFile.readByte() == (byte)'8') &&
@@ -146,15 +147,15 @@
 
     private void readHeaderData() throws IOException{
         // width
-        mIvfFile.seek(WIDTH_HEAD);
+        mIvfFile.seek(WIDTH_OFFSET);
         mWidth = (int) changeEndianness(mIvfFile.readShort());
 
         // height
-        mIvfFile.seek(HEIGHT_HEAD);
+        mIvfFile.seek(HEIGHT_OFFSET);
         mHeight = (int) changeEndianness(mIvfFile.readShort());
 
         // frame count
-        mIvfFile.seek(FRAMECOUNT_HEAD);
+        mIvfFile.seek(FRAMECOUNT_OFFSET);
         mFrameCount = changeEndianness(mIvfFile.readInt());
 
         // allocate frame metadata
@@ -163,7 +164,7 @@
     }
 
     private void readFrameMetadata() throws IOException{
-        int frameHead = HEADER_END;
+        int frameHead = HEADER_SIZE;
         for(int i = 0; i < mFrameCount; i++){
             mIvfFile.seek(frameHead);
             int frameSize = changeEndianness(mIvfFile.readInt());
diff --git a/tests/tests/media/src/android/media/cts/IvfWriter.java b/tests/tests/media/src/android/media/cts/IvfWriter.java
index ccc0ac5..075f73c 100644
--- a/tests/tests/media/src/android/media/cts/IvfWriter.java
+++ b/tests/tests/media/src/android/media/cts/IvfWriter.java
@@ -22,7 +22,8 @@
 /**
  * Writes an IVF file.
  *
- * IVF format is a simple container format for VP8 encoded frames.
+ * IVF format is a simple container format for VP8 encoded frames defined at
+ * http://wiki.multimedia.cx/index.php?title=IVF.
  */
 
 public class IvfWriter {
@@ -56,13 +57,13 @@
         mScale = scale;
         mRate = rate;
         mFrameCount = 0;
+        mOutputFile.setLength(0);
         mOutputFile.seek(HEADER_END);  // Skip the header for now, as framecount is unknown
     }
 
     /**
      * Initializes the IVF file writer with a microsecond timebase.
      *
-     *
      * Microsecond timebase is default for OMX thus stagefright.
      *
      * @param filename   name of the IVF file
@@ -87,7 +88,7 @@
      * Writes a single encoded VP8 frame with its frame header.
      *
      * @param frame     actual contents of the encoded frame data
-     * @param width     timestamp of the frame (in accordance to specified timebase)
+     * @param timeStamp timestamp of the frame (in accordance to specified timebase)
      */
     public void writeFrame(byte[] frame, long timeStamp) throws IOException {
         mOutputFile.write(makeIvfFrameHeader(frame.length, timeStamp));
diff --git a/tests/tests/media/src/android/media/cts/JetPlayerTest.java b/tests/tests/media/src/android/media/cts/JetPlayerTest.java
index 07f1c1b..fc03bcc 100644
--- a/tests/tests/media/src/android/media/cts/JetPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/JetPlayerTest.java
@@ -24,6 +24,7 @@
 import android.media.JetPlayer.OnJetEventListener;
 import android.os.Environment;
 import android.os.Handler;
+import android.os.Looper;
 import android.test.AndroidTestCase;
 
 import java.io.File;
@@ -39,15 +40,8 @@
     private boolean mOnJetNumQueuedSegmentUpdateCalled;
     private boolean mOnJetEventCalled;
     private String mJetFile;
-
-    /*
-     * InstrumentationTestRunner.onStart() calls Looper.prepare(), which creates a looper
-     * for the current thread. However, since we don't actually call loop() in the test,
-     * any messages queued with that looper will never be consumed. By instantiating the
-     * handler and the JetPlayer in the constructor, before setUp(), they will not be bound
-     * to the nonfunctional looper.
-     */
-    private Handler mHandler = new Handler();
+    /* JetPlayer and Handler will be on the Main Looper */
+    private Handler mHandler = new Handler(Looper.getMainLooper());
     private final JetPlayer mJetPlayer = JetPlayer.getJetPlayer();
 
     @Override
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java b/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
index baf4a2d..67c0591 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
@@ -32,13 +32,14 @@
 
     private static final String TAG = "MediaCodecCapabilitiesTest";
     private static final String AVC_MIME = "video/avc";
+    private static final String HEVC_MIME = "video/hevc";
     private static final int PLAY_TIME_MS = 30000;
 
     public void testAvcBaseline1() throws Exception {
         if (!supports(AVC_MIME, CodecProfileLevel.AVCProfileBaseline)) {
           return;
         }
-        if (supports(AVC_MIME, CodecProfileLevel.AVCProfileBaseline,
+        if (!supports(AVC_MIME, CodecProfileLevel.AVCProfileBaseline,
                 CodecProfileLevel.AVCLevel1)) {
             throw new RuntimeException("AVCLevel1 support is required by CDD");
         }
@@ -123,6 +124,78 @@
                 + "&key=ik0", 1920, 1080, PLAY_TIME_MS);
     }
 
+    public void testHevcMain1() throws Exception {
+        if (!supports(HEVC_MIME, CodecProfileLevel.HEVCProfileMain,
+                CodecProfileLevel.HEVCMainTierLevel1)) {
+            throw new RuntimeException("HECLevel1 support is required by CDD");
+        }
+        // We don't have a test stream, but at least we're testing
+        // that supports() returns true for something.
+    }
+    public void testHevcMain2() throws Exception {
+        if (!supports(HEVC_MIME, CodecProfileLevel.HEVCProfileMain,
+                CodecProfileLevel.HEVCMainTierLevel2)) {
+            Log.i(TAG, "HevcMain2 not supported");
+            return;
+        }
+    }
+
+    public void testHevcMain21() throws Exception {
+        if (!supports(HEVC_MIME, CodecProfileLevel.HEVCProfileMain,
+                CodecProfileLevel.HEVCMainTierLevel21)) {
+            Log.i(TAG, "HevcMain21 not supported");
+            return;
+        }
+    }
+
+    public void testHevcMain3() throws Exception {
+        if (!supports(HEVC_MIME, CodecProfileLevel.HEVCProfileMain,
+                CodecProfileLevel.HEVCMainTierLevel3)) {
+            Log.i(TAG, "HevcMain3 not supported");
+            return;
+        }
+    }
+
+    public void testHevcMain31() throws Exception {
+        if (!supports(HEVC_MIME, CodecProfileLevel.HEVCProfileMain,
+                CodecProfileLevel.HEVCMainTierLevel31)) {
+            Log.i(TAG, "HevcMain31 not supported");
+            return;
+        }
+    }
+
+    public void testHevcMain4() throws Exception {
+        if (!supports(HEVC_MIME, CodecProfileLevel.HEVCProfileMain,
+                CodecProfileLevel.HEVCMainTierLevel4)) {
+            Log.i(TAG, "HevcMain4 not supported");
+            return;
+        }
+    }
+
+    public void testHevcMain41() throws Exception {
+        if (!supports(HEVC_MIME, CodecProfileLevel.HEVCProfileMain,
+                CodecProfileLevel.HEVCMainTierLevel41)) {
+            Log.i(TAG, "HevcMain41 not supported");
+            return;
+        }
+    }
+
+    public void testHevcMain5() throws Exception {
+        if (!supports(HEVC_MIME, CodecProfileLevel.HEVCProfileMain,
+                CodecProfileLevel.HEVCMainTierLevel5)) {
+            Log.i(TAG, "HevcMain5 not supported");
+            return;
+        }
+    }
+
+    public void testHevcMain51() throws Exception {
+        if (!supports(HEVC_MIME, CodecProfileLevel.HEVCProfileMain,
+                CodecProfileLevel.HEVCMainTierLevel51)) {
+            Log.i(TAG, "HevcMain51 not supported");
+            return;
+        }
+    }
+
     private boolean supports(String mimeType, int profile) {
         return supports(mimeType, profile, 0, false);
     }
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecCencPlayer.java b/tests/tests/media/src/android/media/cts/MediaCodecCencPlayer.java
new file mode 100644
index 0000000..90696ff
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaCodecCencPlayer.java
@@ -0,0 +1,532 @@
+/*
+ * 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.media.cts;
+
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecList;
+import android.media.MediaCrypto;
+import android.media.MediaCryptoException;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
+import android.net.Uri;
+import android.util.Log;
+import android.view.SurfaceHolder;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * JB(API 16) introduces {@link MediaCodec} API.  It allows apps have more control over
+ * media playback, pushes individual frames to decoder and supports decryption via
+ * {@link MediaCrypto} API.
+ *
+ * {@link MediaDrm} can be used to obtain keys for decrypting protected media streams,
+ * in conjunction with MediaCrypto.
+ */
+public class MediaCodecCencPlayer {
+    private static final String TAG = MediaCodecCencPlayer.class.getSimpleName();
+
+    private static final int STATE_IDLE = 1;
+    private static final int STATE_PREPARING = 2;
+    private static final int STATE_PLAYING = 3;
+    private static final int STATE_PAUSED = 4;
+
+    private static final UUID CLEARKEY_SCHEME_UUID =
+            new UUID(0x1077efecc0b24d02L, 0xace33c1e52e2fb4bL);
+
+    private boolean mEncryptedAudio;
+    private boolean mEncryptedVideo;
+    private boolean mThreadStarted = false;
+    private byte[] mSessionId;
+    private CodecState mAudioTrackState;
+    private int mMediaFormatHeight;
+    private int mMediaFormatWidth;
+    private int mState;
+    private long mDeltaTimeUs;
+    private long mDurationUs;
+    private Map<Integer, CodecState> mAudioCodecStates;
+    private Map<Integer, CodecState> mVideoCodecStates;
+    private Map<String, String> mAudioHeaders;
+    private Map<String, String> mVideoHeaders;
+    private Map<UUID, byte[]> mPsshInitData;
+    private MediaCrypto mCrypto;
+    private MediaExtractor mAudioExtractor;
+    private MediaExtractor mVideoExtractor;
+    private SurfaceHolder mSurfaceHolder;
+    private Thread mThread;
+    private Uri mAudioUri;
+    private Uri mVideoUri;
+
+    private static final byte[] PSSH = hexStringToByteArray(
+            "0000003470737368" +  // BMFF box header (4 bytes size + 'pssh')
+            "01000000" +          // Full box header (version = 1 flags = 0)
+            "1077efecc0b24d02" +  // SystemID
+            "ace33c1e52e2fb4b" +
+            "00000001" +          // Number of key ids
+            "60061e017e477e87" +  // Key id
+            "7e57d00d1ed00d1e" +
+            "00000000"            // Size of Data, must be zero
+            );
+
+    /**
+     * Convert a hex string into byte array.
+     */
+    private static byte[] hexStringToByteArray(String s) {
+        int len = s.length();
+        byte[] data = new byte[len / 2];
+        for (int i = 0; i < len; i += 2) {
+            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+                    + Character.digit(s.charAt(i + 1), 16));
+        }
+        return data;
+    }
+
+    /*
+     * Media player class to stream CENC content using MediaCodec class.
+     */
+    public MediaCodecCencPlayer(SurfaceHolder holder, byte[] sessionId) {
+        mSessionId = sessionId;
+        mSurfaceHolder = holder;
+        mState = STATE_IDLE;
+        mThread = new Thread(new Runnable() {
+            @Override
+            public void run() {
+                while (mThreadStarted == true) {
+                    doSomeWork();
+                    if (mAudioTrackState != null) {
+                        mAudioTrackState.process();
+                    }
+                    try {
+                        Thread.sleep(5);
+                    } catch (InterruptedException ex) {
+                        Log.d(TAG, "Thread interrupted");
+                    }
+                }
+            }
+        });
+    }
+
+    public void setAudioDataSource(Uri uri, Map<String, String> headers, boolean encrypted) {
+        mAudioUri = uri;
+        mAudioHeaders = headers;
+        mEncryptedAudio = encrypted;
+    }
+
+    public void setVideoDataSource(Uri uri, Map<String, String> headers, boolean encrypted) {
+        mVideoUri = uri;
+        mVideoHeaders = headers;
+        mEncryptedVideo = encrypted;
+    }
+
+    public final int getMediaFormatHeight() {
+        return mMediaFormatHeight;
+    }
+
+    public final int getMediaFormatWidth() {
+        return mMediaFormatWidth;
+    }
+
+    public final Map<UUID, byte[]> getPsshInfo() {
+        // TODO (edwinwong@)
+        // Remove the if statement when we get content that has the clear key system id.
+        if (mPsshInitData == null ||
+                (mPsshInitData != null && !mPsshInitData.containsKey(CLEARKEY_SCHEME_UUID))) {
+            mPsshInitData = new HashMap<UUID, byte[]>();
+            mPsshInitData.put(CLEARKEY_SCHEME_UUID, PSSH);
+        }
+        return mPsshInitData;
+    }
+
+    private void prepareAudio() throws IOException {
+        boolean hasAudio = false;
+        for (int i = mAudioExtractor.getTrackCount(); i-- > 0;) {
+            MediaFormat format = mAudioExtractor.getTrackFormat(i);
+            String mime = format.getString(MediaFormat.KEY_MIME);
+
+            Log.d(TAG, "audio track #" + i + " " + format + " " + mime +
+                  " Is ADTS:" + getMediaFormatInteger(format, MediaFormat.KEY_IS_ADTS) +
+                  " Sample rate:" + getMediaFormatInteger(format, MediaFormat.KEY_SAMPLE_RATE) +
+                  " Channel count:" +
+                  getMediaFormatInteger(format, MediaFormat.KEY_CHANNEL_COUNT));
+
+            if (!hasAudio) {
+                mAudioExtractor.selectTrack(i);
+                addTrack(i, format, mEncryptedAudio);
+                hasAudio = true;
+
+                if (format.containsKey(MediaFormat.KEY_DURATION)) {
+                    long durationUs = format.getLong(MediaFormat.KEY_DURATION);
+
+                    if (durationUs > mDurationUs) {
+                        mDurationUs = durationUs;
+                    }
+                    Log.d(TAG, "audio track format #" + i +
+                            " Duration:" + mDurationUs + " microseconds");
+                }
+
+                if (hasAudio) {
+                    break;
+                }
+            }
+        }
+    }
+
+    private void prepareVideo() throws IOException {
+        boolean hasVideo = false;
+
+        for (int i = mVideoExtractor.getTrackCount(); i-- > 0;) {
+            MediaFormat format = mVideoExtractor.getTrackFormat(i);
+            String mime = format.getString(MediaFormat.KEY_MIME);
+
+            mMediaFormatHeight = getMediaFormatInteger(format, MediaFormat.KEY_HEIGHT);
+            mMediaFormatWidth = getMediaFormatInteger(format, MediaFormat.KEY_WIDTH);
+            Log.d(TAG, "video track #" + i + " " + format + " " + mime +
+                  " Width:" + mMediaFormatWidth + ", Height:" + mMediaFormatHeight);
+
+            if (!hasVideo) {
+                mVideoExtractor.selectTrack(i);
+                addTrack(i, format, mEncryptedVideo);
+
+                hasVideo = true;
+
+                if (format.containsKey(MediaFormat.KEY_DURATION)) {
+                    long durationUs = format.getLong(MediaFormat.KEY_DURATION);
+
+                    if (durationUs > mDurationUs) {
+                        mDurationUs = durationUs;
+                    }
+                    Log.d(TAG, "track format #" + i + " Duration:" +
+                            mDurationUs + " microseconds");
+                }
+
+                if (hasVideo) {
+                    break;
+                }
+            }
+        }
+        return;
+    }
+
+    public void prepare() throws IOException, MediaCryptoException {
+        if (null == mAudioExtractor) {
+            mAudioExtractor = new MediaExtractor();
+            if (null == mAudioExtractor) {
+                Log.e(TAG, "Cannot create Audio extractor.");
+                return;
+            }
+        }
+
+        if (null == mVideoExtractor){
+            mVideoExtractor = new MediaExtractor();
+            if (null == mVideoExtractor) {
+                Log.e(TAG, "Cannot create Video extractor.");
+                return;
+            }
+        }
+
+        mAudioExtractor.setDataSource(mAudioUri.toString(), mAudioHeaders);
+        mVideoExtractor.setDataSource(mVideoUri.toString(), mVideoHeaders);
+        mPsshInitData = mVideoExtractor.getPsshInfo();
+
+        if (null == mCrypto && (mEncryptedVideo || mEncryptedAudio)) {
+            try {
+                mCrypto = new MediaCrypto(CLEARKEY_SCHEME_UUID, mSessionId);
+            } catch (MediaCryptoException e) {
+                reset();
+                Log.e(TAG, "Failed to create MediaCrypto instance.");
+                throw e;
+            }
+        } else {
+            reset();
+            mCrypto.release();
+            mCrypto = null;
+        }
+
+        if (null == mVideoCodecStates) {
+            mVideoCodecStates = new HashMap<Integer, CodecState>();
+        } else {
+            mVideoCodecStates.clear();
+        }
+
+        if (null == mAudioCodecStates) {
+            mAudioCodecStates = new HashMap<Integer, CodecState>();
+        } else {
+            mAudioCodecStates.clear();
+        }
+
+        prepareVideo();
+        prepareAudio();
+
+        mState = STATE_PAUSED;
+    }
+
+    private void addTrack(int trackIndex, MediaFormat format,
+            boolean encrypted) throws IOException {
+        String mime = format.getString(MediaFormat.KEY_MIME);
+        boolean isVideo = mime.startsWith("video/");
+        boolean isAudio = mime.startsWith("audio/");
+
+        MediaCodec codec;
+
+        if (encrypted && mCrypto.requiresSecureDecoderComponent(mime)) {
+            codec = MediaCodec.createByCodecName(
+                    getSecureDecoderNameForMime(mime));
+        } else {
+            codec = MediaCodec.createDecoderByType(mime);
+        }
+
+        codec.configure(
+                format,
+                isVideo ? mSurfaceHolder.getSurface() : null,
+                mCrypto,
+                0);
+
+        CodecState state;
+        if (isVideo) {
+            state = new CodecState(this, mVideoExtractor, trackIndex, format, codec, true);
+            mVideoCodecStates.put(Integer.valueOf(trackIndex), state);
+        } else {
+            state = new CodecState(this, mAudioExtractor, trackIndex, format, codec, true);
+            mAudioCodecStates.put(Integer.valueOf(trackIndex), state);
+        }
+
+        if (isAudio) {
+            mAudioTrackState = state;
+        }
+    }
+
+    protected int getMediaFormatInteger(MediaFormat format, String key) {
+        return format.containsKey(key) ? format.getInteger(key) : 0;
+    }
+
+    protected String getSecureDecoderNameForMime(String mime) {
+        int n = MediaCodecList.getCodecCount();
+        for (int i = 0; i < n; ++i) {
+            MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
+
+            if (info.isEncoder()) {
+                continue;
+            }
+
+            String[] supportedTypes = info.getSupportedTypes();
+
+            for (int j = 0; j < supportedTypes.length; ++j) {
+                if (supportedTypes[j].equalsIgnoreCase(mime)) {
+                    return info.getName() + ".secure";
+                }
+            }
+        }
+        return null;
+    }
+
+    public void start() {
+        Log.d(TAG, "start");
+
+        if (mState == STATE_PLAYING || mState == STATE_PREPARING) {
+            return;
+        } else if (mState == STATE_IDLE) {
+            mState = STATE_PREPARING;
+            return;
+        } else if (mState != STATE_PAUSED) {
+            throw new IllegalStateException();
+        }
+
+        for (CodecState state : mVideoCodecStates.values()) {
+            state.start();
+        }
+
+        for (CodecState state : mAudioCodecStates.values()) {
+            state.start();
+        }
+
+        mDeltaTimeUs = -1;
+        mState = STATE_PLAYING;
+    }
+
+    public void startWork() throws IOException, MediaCryptoException, Exception {
+        try {
+            // Just change state from STATE_IDLE to STATE_PREPARING.
+            start();
+            // Extract media information from uri asset, and change state to STATE_PAUSED.
+            prepare();
+            // Start CodecState, and change from STATE_PAUSED to STATE_PLAYING.
+            start();
+        } catch (IOException e) {
+            throw e;
+        } catch (MediaCryptoException e) {
+            throw e;
+        }
+
+        mThreadStarted = true;
+        mThread.start();
+    }
+
+    public void startThread() {
+        start();
+        mThreadStarted = true;
+        mThread.start();
+    }
+
+    public void pause() {
+        Log.d(TAG, "pause");
+
+        if (mState == STATE_PAUSED) {
+            return;
+        } else if (mState != STATE_PLAYING) {
+            throw new IllegalStateException();
+        }
+
+        for (CodecState state : mVideoCodecStates.values()) {
+            state.pause();
+        }
+
+        for (CodecState state : mAudioCodecStates.values()) {
+            state.pause();
+        }
+
+        mState = STATE_PAUSED;
+    }
+
+    public void reset() {
+        if (mState == STATE_PLAYING) {
+            mThreadStarted = false;
+
+            try {
+                mThread.join();
+            } catch (InterruptedException ex) {
+                Log.d(TAG, "mThread.join " + ex);
+            }
+
+            pause();
+        }
+
+        if (mVideoCodecStates != null) {
+            for (CodecState state : mVideoCodecStates.values()) {
+                state.release();
+            }
+            mVideoCodecStates = null;
+        }
+
+        if (mAudioCodecStates != null) {
+            for (CodecState state : mAudioCodecStates.values()) {
+                state.release();
+            }
+            mAudioCodecStates = null;
+        }
+
+        if (mAudioExtractor != null) {
+            mAudioExtractor.release();
+            mAudioExtractor = null;
+        }
+
+        if (mVideoExtractor != null) {
+            mVideoExtractor.release();
+            mVideoExtractor = null;
+        }
+
+        if (mCrypto != null) {
+            mCrypto.release();
+            mCrypto = null;
+        }
+
+        mDurationUs = -1;
+        mState = STATE_IDLE;
+    }
+
+    public boolean isEnded() {
+        for (CodecState state : mVideoCodecStates.values()) {
+          if (!state.isEnded()) {
+            return false;
+          }
+        }
+
+        for (CodecState state : mAudioCodecStates.values()) {
+            if (!state.isEnded()) {
+              return false;
+            }
+        }
+
+        return true;
+    }
+
+    private void doSomeWork() {
+        try {
+            for (CodecState state : mVideoCodecStates.values()) {
+                state.doSomeWork();
+            }
+        } catch (MediaCodec.CryptoException e) {
+            throw new Error("Video CryptoException w/ errorCode "
+                    + e.getErrorCode() + ", '" + e.getMessage() + "'");
+        } catch (IllegalStateException e) {
+            throw new Error("Video CodecState.feedInputBuffer IllegalStateException " + e);
+        }
+
+        try {
+            for (CodecState state : mAudioCodecStates.values()) {
+                state.doSomeWork();
+            }
+        } catch (MediaCodec.CryptoException e) {
+            throw new Error("Audio CryptoException w/ errorCode "
+                    + e.getErrorCode() + ", '" + e.getMessage() + "'");
+        } catch (IllegalStateException e) {
+            throw new Error("Aduio CodecState.feedInputBuffer IllegalStateException " + e);
+        }
+
+    }
+
+    public long getNowUs() {
+        if (mAudioTrackState == null) {
+            return System.currentTimeMillis() * 1000;
+        }
+
+        return mAudioTrackState.getAudioTimeUs();
+    }
+
+    public long getRealTimeUsForMediaTime(long mediaTimeUs) {
+        if (mDeltaTimeUs == -1) {
+            long nowUs = getNowUs();
+            mDeltaTimeUs = nowUs - mediaTimeUs;
+        }
+
+        return mDeltaTimeUs + mediaTimeUs;
+    }
+
+    public int getDuration() {
+        return (int)((mDurationUs + 500) / 1000);
+    }
+
+    public int getCurrentPosition() {
+        if (mVideoCodecStates == null) {
+                return 0;
+        }
+
+        long positionUs = 0;
+
+        for (CodecState state : mVideoCodecStates.values()) {
+            long trackPositionUs = state.getCurrentPositionUs();
+
+            if (trackPositionUs > positionUs) {
+                positionUs = trackPositionUs;
+            }
+        }
+        return (int)((positionUs + 500) / 1000);
+    }
+
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecListTest.java b/tests/tests/media/src/android/media/cts/MediaCodecListTest.java
index 2ed9002..865780e 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecListTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecListTest.java
@@ -16,23 +16,38 @@
 
 package android.media.cts;
 
-
+import android.content.pm.PackageManager;
 import android.media.MediaCodec;
 import android.media.MediaCodecInfo;
 import android.media.MediaCodecInfo.CodecProfileLevel;
 import android.media.MediaCodecInfo.CodecCapabilities;
+import android.media.MediaCodecInfo.AudioCapabilities;
+import android.media.MediaCodecInfo.VideoCapabilities;
+import android.media.MediaCodecInfo.EncoderCapabilities;
 import android.media.MediaCodecList;
+import android.media.MediaFormat;
 import android.test.AndroidTestCase;
 import android.util.Log;
 
 import java.io.File;
-import java.util.List;
+import java.io.IOException;
 import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 
 public class MediaCodecListTest extends AndroidTestCase {
 
     private static final String TAG = "MediaCodecListTest";
     private static final String MEDIA_CODEC_XML_FILE = "/etc/media_codecs.xml";
+    private final MediaCodecList mRegularCodecs =
+            new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+    private final MediaCodecList mAllCodecs =
+            new MediaCodecList(MediaCodecList.ALL_CODECS);
+    private final MediaCodecInfo[] mRegularInfos =
+            mRegularCodecs.getCodecInfos();
+    private final MediaCodecInfo[] mAllInfos =
+            mAllCodecs.getCodecInfos();
 
     class CodecType {
         CodecType(String type, boolean isEncoder) {
@@ -54,55 +69,120 @@
         assertTrue("/etc/media_codecs.xml does not exist", file.exists());
     }
 
-    // Each component advertised by MediaCodecList should at least be
-    // instantiate-able.
-    public void testComponentInstantiation() {
-        Log.d(TAG, "testComponentInstantiation");
+    private MediaCodecInfo[] getLegacyInfos() {
+        Log.d(TAG, "getLegacyInfos");
 
         int codecCount = MediaCodecList.getCodecCount();
-        for (int i = 0; i < codecCount; ++i) {
-            MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
+        MediaCodecInfo[] res = new MediaCodecInfo[codecCount];
 
-            Log.d(TAG, (i + 1) + ": " + info.getName());
+        for (int i = 0; i < codecCount; ++i) {
+            res[i] = MediaCodecList.getCodecInfoAt(i);
+        }
+        return res;
+    }
+
+    public void assertEqualsOrSuperset(Set big, Set tiny, boolean superset) {
+        if (!superset) {
+            assertEquals(big, tiny);
+        } else {
+            assertTrue(big.containsAll(tiny));
+        }
+    }
+
+    private static <T> Set<T> asSet(T[] array) {
+        Set<T> s = new HashSet<T>();
+        for (T el : array) {
+            s.add(el);
+        }
+        return s;
+    }
+
+    private static Set<Integer> asSet(int[] array) {
+        Set<Integer> s = new HashSet<Integer>();
+        for (int el : array) {
+            s.add(el);
+        }
+        return s;
+    }
+
+    public void assertEqualsOrSuperset(
+            CodecCapabilities big, CodecCapabilities tiny, boolean superset) {
+        // ordering of enumerations may differ
+        assertEqualsOrSuperset(asSet(big.colorFormats), asSet(tiny.colorFormats), superset);
+        assertEqualsOrSuperset(asSet(big.profileLevels), asSet(tiny.profileLevels), superset);
+        AudioCapabilities bigAudCaps = big.getAudioCapabilities();
+        VideoCapabilities bigVidCaps = big.getVideoCapabilities();
+        EncoderCapabilities bigEncCaps = big.getEncoderCapabilities();
+        AudioCapabilities tinyAudCaps = tiny.getAudioCapabilities();
+        VideoCapabilities tinyVidCaps = tiny.getVideoCapabilities();
+        EncoderCapabilities tinyEncCaps = tiny.getEncoderCapabilities();
+        assertEquals(bigAudCaps != null, tinyAudCaps != null);
+        assertEquals(bigAudCaps != null, tinyAudCaps != null);
+        assertEquals(bigAudCaps != null, tinyAudCaps != null);
+    }
+
+    public void assertEqualsOrSuperset(
+            MediaCodecInfo big, MediaCodecInfo tiny, boolean superset) {
+        assertEquals(big.getName(), tiny.getName());
+        assertEquals(big.isEncoder(), tiny.isEncoder());
+        assertEqualsOrSuperset(
+                asSet(big.getSupportedTypes()), asSet(tiny.getSupportedTypes()), superset);
+        for (String type : big.getSupportedTypes()) {
+            assertEqualsOrSuperset(
+                    big.getCapabilitiesForType(type),
+                    tiny.getCapabilitiesForType(type),
+                    superset);
+        }
+    }
+
+    public void assertSuperset(MediaCodecInfo big, MediaCodecInfo tiny) {
+        assertEqualsOrSuperset(big, tiny, true /* superset */);
+    }
+
+    public void assertEquals(MediaCodecInfo big, MediaCodecInfo tiny) {
+        assertEqualsOrSuperset(big, tiny, false /* superset */);
+    }
+
+    // Each component advertised by MediaCodecList should at least be
+    // instantiable.
+    private void testComponentInstantiation(MediaCodecInfo[] infos) throws IOException {
+        for (MediaCodecInfo info : infos) {
+            Log.d(TAG, "codec: " + info.getName());
             Log.d(TAG, "  isEncoder = " + info.isEncoder());
 
-            if (!info.getName().startsWith("OMX.")) {
-                // Unfortunately for legacy reasons, "AACEncoder", a
-                // non OMX component had to be in this list for the video
-                // editor code to work... but it cannot actually be instantiated
-                // using MediaCodec.
-                Log.d(TAG, "  skipping...");
-                continue;
-            }
-
             MediaCodec codec = MediaCodec.createByCodecName(info.getName());
 
+            assertEquals(codec.getName(), info.getName());
+
+            assertEquals(codec.getCodecInfo(), info);
+
             codec.release();
             codec = null;
         }
     }
 
+    public void testRegularComponentInstantiation() throws IOException {
+        Log.d(TAG, "testRegularComponentInstantiation");
+        testComponentInstantiation(mRegularInfos);
+    }
+
+    public void testAllComponentInstantiation() throws IOException {
+        Log.d(TAG, "testAllComponentInstantiation");
+        testComponentInstantiation(mAllInfos);
+    }
+
+    public void testLegacyComponentInstantiation() throws IOException {
+        Log.d(TAG, "testLegacyComponentInstantiation");
+        testComponentInstantiation(getLegacyInfos());
+    }
+
     // For each type advertised by any of the components we should be able
     // to get capabilities.
-    public void testGetCapabilities() {
-        Log.d(TAG, "testGetCapabilities");
-
-        int codecCount = MediaCodecList.getCodecCount();
-        for (int i = 0; i < codecCount; ++i) {
-            MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
-
-            Log.d(TAG, (i + 1) + ": " + info.getName());
+    private void testGetCapabilities(MediaCodecInfo[] infos) {
+        for (MediaCodecInfo info : infos) {
+            Log.d(TAG, "codec: " + info.getName());
             Log.d(TAG, "  isEncoder = " + info.isEncoder());
 
-            if (!info.getName().startsWith("OMX.")) {
-                // Unfortunately for legacy reasons, "AACEncoder", a
-                // non OMX component had to be in this list for the video
-                // editor code to work... but it cannot actually be instantiated
-                // using MediaCodec.
-                Log.d(TAG, "  skipping...");
-                continue;
-            }
-
             String[] types = info.getSupportedTypes();
             for (int j = 0; j < types.length; ++j) {
                 Log.d(TAG, "calling getCapabilitiesForType " + types[j]);
@@ -111,14 +191,71 @@
         }
     }
 
+    public void testGetRegularCapabilities() {
+        Log.d(TAG, "testGetRegularCapabilities");
+        testGetCapabilities(mRegularInfos);
+    }
+
+    public void testGetAllCapabilities() {
+        Log.d(TAG, "testGetAllCapabilities");
+        testGetCapabilities(mAllInfos);
+    }
+
+    public void testGetLegacyCapabilities() {
+        Log.d(TAG, "testGetLegacyCapabilities");
+        testGetCapabilities(getLegacyInfos());
+    }
+
+    public void testLegacyMediaCodecListIsSameAsRegular() {
+        // regular codecs should be equivalent to legacy codecs, including
+        // codec ordering
+        MediaCodecInfo[] legacyInfos = getLegacyInfos();
+        assertEquals(legacyInfos.length, mRegularInfos.length);
+        for (int i = 0; i < legacyInfos.length; ++i) {
+            assertEquals(legacyInfos[i], mRegularInfos[i]);
+        }
+    }
+
+    public void testRegularMediaCodecListIsASubsetOfAll() {
+        Log.d(TAG, "testRegularMediaCodecListIsASubsetOfAll");
+        // regular codecs should be a subsequence of all codecs, including
+        // codec ordering
+        int ix = 0;
+        for (MediaCodecInfo info : mAllInfos) {
+            if (ix == mRegularInfos.length) {
+                break;
+            }
+            if (!mRegularInfos[ix].getName().equals(info.getName())) {
+                Log.d(TAG, "skipping non-regular codec " + info.getName());
+                continue;
+            }
+            Log.d(TAG, "checking codec " + info.getName());
+            assertSuperset(info, mRegularInfos[ix]);
+            ++ix;
+        }
+        assertEquals(
+                "some regular codecs are not listed in all codecs", ix, mRegularInfos.length);
+    }
+
     public void testRequiredMediaCodecList() {
         List<CodecType> requiredList = getRequiredCodecTypes();
         List<CodecType> supportedList = getSupportedCodecTypes();
         assertTrue(areRequiredCodecTypesSupported(requiredList, supportedList));
     }
 
+    private boolean hasCamera() {
+        PackageManager pm = getContext().getPackageManager();
+        return pm.hasSystemFeature(pm.FEATURE_CAMERA_FRONT) ||
+                pm.hasSystemFeature(pm.FEATURE_CAMERA);
+    }
+
     // H263 baseline profile must be supported
     public void testIsH263BaselineProfileSupported() {
+        if (!hasCamera()) {
+            Log.d(TAG, "not required without camera");
+            return;
+        }
+
         int profile = CodecProfileLevel.H263ProfileBaseline;
         assertTrue(checkProfileSupported("video/3gpp", false, profile));
         assertTrue(checkProfileSupported("video/3gpp", true, profile));
@@ -131,8 +268,19 @@
         assertTrue(checkProfileSupported("video/avc", true, profile));
     }
 
+    // HEVC main profile must be supported
+    public void testIsHEVCMainProfileSupported() {
+        int profile = CodecProfileLevel.HEVCProfileMain;
+        assertTrue(checkProfileSupported("video/hevc", false, profile));
+    }
+
     // MPEG4 simple profile must be supported
     public void testIsM4VSimpleProfileSupported() {
+        if (!hasCamera()) {
+            Log.d(TAG, "not required without camera");
+            return;
+        }
+
         int profile = CodecProfileLevel.MPEG4ProfileSimple;
         assertTrue(checkProfileSupported("video/mp4v-es", false, profile));
 
@@ -144,25 +292,24 @@
      * Find whether the given codec is supported
      */
     private boolean checkProfileSupported(
-        String codecName, boolean isEncoder, int profile) {
+            String mime, boolean isEncoder, int profile) {
+        return profileIsListed(mime, isEncoder, profile) &&
+                codecCanBeFound(mime, isEncoder);
+    }
 
-        boolean isSupported = false;
+    private boolean profileIsListed(
+        String mime, boolean isEncoder, int profile) {
 
-        int codecCount = MediaCodecList.getCodecCount();
-        for (int i = 0; i < codecCount; ++i) {
-            MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
-            String[] types = info.getSupportedTypes();
-
+        for (MediaCodecInfo info : mRegularInfos) {
             if (isEncoder != info.isEncoder()) {
                 continue;
             }
 
-            for (int j = 0; j < types.length; ++j) {
-                if (types[j].compareTo(codecName) == 0) {
-                    CodecCapabilities cap = info.getCapabilitiesForType(types[j]);
-                    CodecProfileLevel[] profileLevels = cap.profileLevels;
-                    for (int k = 0; k < profileLevels.length; ++k) {
-                        if (profileLevels[k].profile == profile) {
+            for (String type : info.getSupportedTypes()) {
+                if (type.equalsIgnoreCase(mime)) {
+                    CodecCapabilities cap = info.getCapabilitiesForType(type);
+                    for (CodecProfileLevel pl : cap.profileLevels) {
+                        if (pl.profile == profile) {
                             return true;
                         }
                     }
@@ -172,6 +319,16 @@
         return false;
     }
 
+    // Find whether the given codec can be found using MediaCodecList.find methods.
+    private boolean codecCanBeFound(String mime, boolean isEncoder) {
+        // implicit assumption that QVGA video is always valid.
+        MediaFormat format = MediaFormat.createVideoFormat(mime, 176, 144);
+        String codecName = isEncoder
+                ? mRegularCodecs.findEncoderForFormat(format)
+                : mRegularCodecs.findDecoderForFormat(format);
+        return codecName != null;
+    }
+
     /*
      * Find whether all required media codec types are supported
      */
@@ -198,11 +355,8 @@
      * Find all the media codec types are supported.
      */
     private List<CodecType> getSupportedCodecTypes() {
-        int codecCount = MediaCodecList.getCodecCount();
-        assertTrue("Unexpected media codec count", codecCount > 0);
-        List<CodecType> supportedList = new ArrayList<CodecType>(codecCount);
-        for (int i = 0; i < codecCount; ++i) {
-            MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
+        List<CodecType> supportedList = new ArrayList<CodecType>();
+        for (MediaCodecInfo info : mRegularInfos) {
             String[] types = info.getSupportedTypes();
             assertTrue("Unexpected number of supported types", types.length > 0);
             boolean isEncoder = info.isEncoder();
@@ -237,6 +391,7 @@
         // Mandatory video codecs
         list.add(new CodecType("video/avc", false));            // avc decoder
         list.add(new CodecType("video/avc", true));             // avc encoder
+        list.add(new CodecType("video/hevc", false));           // hevc decoder
         list.add(new CodecType("video/3gpp", false));           // h263 decoder
         list.add(new CodecType("video/3gpp", true));            // h263 encoder
         list.add(new CodecType("video/mp4v-es", false));        // m4v decoder
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecTest.java b/tests/tests/media/src/android/media/cts/MediaCodecTest.java
index ce85b78..f72e3a0 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecTest.java
@@ -34,7 +34,7 @@
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.Locale;
+
 
 /**
  * General MediaCodec tests.
@@ -72,6 +72,201 @@
 
     /**
      * Tests:
+     * <br> Exceptions for MediaCodec factory methods
+     * <br> Exceptions for MediaCodec methods when called in the incorrect state.
+     *
+     * A selective test to ensure proper exceptions are thrown from MediaCodec
+     * methods when called in incorrect operational states.
+     */
+    public void testException() throws Exception {
+        MediaFormat[] formatList = new MediaFormat[2];
+
+        // use audio format
+        formatList[0] = new MediaFormat();
+        formatList[0].setString(MediaFormat.KEY_MIME, "audio/amr-wb");
+        formatList[0].setInteger(MediaFormat.KEY_SAMPLE_RATE, 16000);
+        formatList[0].setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
+        formatList[0].setInteger(MediaFormat.KEY_BIT_RATE, 19850);
+
+        // use video format
+        formatList[1] = createMediaFormat();
+
+        for (MediaFormat format : formatList) {
+            verifyIllegalStateException(format, false);
+            verifyIllegalStateException(format, true);
+        }
+    }
+
+    // wrap MediaCodec encoder and decoder creation
+    private static MediaCodec createCodecByType(String type, boolean isEncoder)
+            throws IOException {
+        if (isEncoder) {
+            return MediaCodec.createEncoderByType(type);
+        }
+        return MediaCodec.createDecoderByType(type);
+    }
+
+    private static void logMediaCodecException(MediaCodec.CodecException ex) {
+        if (ex.isRecoverable()) {
+            Log.w(TAG, "CodecException Recoverable: " + ex.getErrorCode());
+        } else if (ex.isTransient()) {
+            Log.w(TAG, "CodecException Transient: " + ex.getErrorCode());
+        } else {
+            Log.w(TAG, "CodecException Fatal: " + ex.getErrorCode());
+        }
+    }
+
+    private static void verifyIllegalStateException(MediaFormat format, boolean isEncoder)
+            throws IOException {
+        MediaCodec codec;
+
+        // create codec (enter Initialized State)
+
+        // create improperly
+        final String methodName = isEncoder ? "createEncoderByType" : "createDecoderByType";
+        try {
+            codec = createCodecByType(null, isEncoder);
+            fail(methodName + " should return NullPointerException on null");
+        } catch (NullPointerException e) { // expected
+        }
+        try {
+            codec = createCodecByType("foobarplan9", isEncoder); // invalid type
+            fail(methodName + " should return IllegalArgumentException on invalid type");
+        } catch (IllegalArgumentException e) { // expected
+        }
+        try {
+            codec = MediaCodec.createByCodecName("foobarplan9"); // invalid name
+            fail(methodName + " should return IllegalArgumentException on invalid name");
+        } catch (IllegalArgumentException e) { // expected
+        }
+        // correct
+        codec = createCodecByType(format.getString(MediaFormat.KEY_MIME), isEncoder);
+
+        // test a few commands
+        try {
+            codec.start();
+            fail("start should return IllegalStateException when in Initialized state");
+        } catch (MediaCodec.CodecException e) {
+            logMediaCodecException(e);
+            fail("start should not return MediaCodec.CodecException on wrong state");
+        } catch (IllegalStateException e) { // expected
+        }
+        try {
+            codec.flush();
+            fail("flush should return IllegalStateException when in Initialized state");
+        } catch (MediaCodec.CodecException e) {
+            logMediaCodecException(e);
+            fail("flush should not return MediaCodec.CodecException on wrong state");
+        } catch (IllegalStateException e) { // expected
+        }
+        MediaCodecInfo codecInfo = codec.getCodecInfo(); // obtaining the codec info now is fine.
+        try {
+            int bufIndex = codec.dequeueInputBuffer(0);
+            fail("dequeueInputBuffer should return IllegalStateException"
+                    + " when in the Initialized state");
+        } catch (MediaCodec.CodecException e) {
+            logMediaCodecException(e);
+            fail("dequeueInputBuffer should not return MediaCodec.CodecException"
+                    + " on wrong state");
+        } catch (IllegalStateException e) { // expected
+        }
+        try {
+            MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
+            int bufIndex = codec.dequeueOutputBuffer(info, 0);
+            fail("dequeueOutputBuffer should return IllegalStateException"
+                    + " when in the Initialized state");
+        } catch (MediaCodec.CodecException e) {
+            logMediaCodecException(e);
+            fail("dequeueOutputBuffer should not return MediaCodec.CodecException"
+                    + " on wrong state");
+        } catch (IllegalStateException e) { // expected
+        }
+
+        // configure (enter Configured State)
+
+        // configure improperly
+        try {
+            codec.configure(format, null /* surface */, null /* crypto */,
+                    isEncoder ? 0 : MediaCodec.CONFIGURE_FLAG_ENCODE /* flags */);
+            fail("configure needs MediaCodec.CONFIGURE_FLAG_ENCODE for encoders only");
+        } catch (MediaCodec.CodecException e) { // expected
+            logMediaCodecException(e);
+        } catch (IllegalStateException e) {
+            fail("configure should not return IllegalStateException when improperly configured");
+        }
+        // correct
+        codec.configure(format, null /* surface */, null /* crypto */,
+                isEncoder ? MediaCodec.CONFIGURE_FLAG_ENCODE : 0 /* flags */);
+
+        // test a few commands
+        try {
+            codec.flush();
+            fail("flush should return IllegalStateException when in Configured state");
+        } catch (MediaCodec.CodecException e) {
+            logMediaCodecException(e);
+            fail("flush should not return MediaCodec.CodecException on wrong state");
+        } catch (IllegalStateException e) { // expected
+        }
+        try {
+            Surface surface = codec.createInputSurface();
+            if (!isEncoder) {
+                fail("createInputSurface should not work on a decoder");
+            }
+        } catch (IllegalStateException e) { // expected for decoder and audio encoder
+            if (isEncoder && format.getString(MediaFormat.KEY_MIME).startsWith("video/")) {
+                throw e;
+            }
+        }
+
+        // start codec (enter Executing state)
+        codec.start();
+
+        // test a few commands
+        try {
+            codec.configure(format, null /* surface */, null /* crypto */, 0 /* flags */);
+            fail("configure should return IllegalStateException when in Executing state");
+        } catch (MediaCodec.CodecException e) {
+            logMediaCodecException(e);
+            // TODO: consider configuring after a flush.
+            fail("configure should not return MediaCodec.CodecException on wrong state");
+        } catch (IllegalStateException e) { // expected
+        }
+
+        // two flushes should be fine.
+        codec.flush();
+        codec.flush();
+
+        // stop codec (enter Initialized state)
+        // two stops should be fine.
+        codec.stop();
+        codec.stop();
+
+        // release codec (enter Uninitialized state)
+        // two releases should be fine.
+        codec.release();
+        codec.release();
+
+        try {
+            codecInfo = codec.getCodecInfo();
+            fail("getCodecInfo should should return IllegalStateException" +
+                    " when in Uninitialized state");
+        } catch (MediaCodec.CodecException e) {
+            logMediaCodecException(e);
+            fail("getCodecInfo should not return MediaCodec.CodecException on wrong state");
+        } catch (IllegalStateException e) { // expected
+        }
+        try {
+            codec.stop();
+            fail("stop should return IllegalStateException when in Uninitialized state");
+        } catch (MediaCodec.CodecException e) {
+            logMediaCodecException(e);
+            fail("stop should not return MediaCodec.CodecException on wrong state");
+        } catch (IllegalStateException e) { // expected
+        }
+    }
+
+    /**
+     * Tests:
      * <br> calling createInputSurface() before configure() throws exception
      * <br> calling createInputSurface() after start() throws exception
      * <br> calling createInputSurface() with a non-Surface color format throws exception
@@ -83,15 +278,15 @@
 
         // Replace color format with something that isn't COLOR_FormatSurface.
         MediaCodecInfo codecInfo = selectCodec(MIME_TYPE);
-        if (codecInfo == null) {
-            // Pass if no codec was available.
-            return;
-        }
         int colorFormat = findNonSurfaceColorFormat(codecInfo, MIME_TYPE);
         format.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat);
 
         try {
-            encoder = MediaCodec.createByCodecName(codecInfo.getName());
+            try {
+                encoder = MediaCodec.createByCodecName(codecInfo.getName());
+            } catch (IOException e) {
+                fail("failed to create codec " + codecInfo.getName());
+            }
             try {
                 surface = encoder.createInputSurface();
                 fail("createInputSurface should not work pre-configure");
@@ -124,7 +319,6 @@
         assertNull(surface);
     }
 
-
     /**
      * Tests:
      * <br> signaling end-of-stream before any data is sent works
@@ -137,10 +331,10 @@
         InputSurface inputSurface = null;
 
         try {
-            encoder = createEncoderForMimeType(MIME_TYPE);
-            if (encoder == null) {
-                // Pass if no codec was available.
-                return;
+            try {
+                encoder = MediaCodec.createEncoderByType(MIME_TYPE);
+            } catch (IOException e) {
+                fail("failed to create " + MIME_TYPE + " encoder");
             }
             encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
             inputSurface = new InputSurface(encoder.createInputSurface());
@@ -181,6 +375,60 @@
 
     /**
      * Tests:
+     * <br> stopping with buffers in flight doesn't crash or hang
+     */
+    public void testAbruptStop() {
+        // There appears to be a race, so run it several times with a short delay between runs
+        // to allow any previous activity to shut down.
+        for (int i = 0; i < 50; i++) {
+            Log.d(TAG, "testAbruptStop " + i);
+            doTestAbruptStop();
+            try { Thread.sleep(400); } catch (InterruptedException ignored) {}
+        }
+    }
+    private void doTestAbruptStop() {
+        MediaFormat format = createMediaFormat();
+        MediaCodec encoder = null;
+        InputSurface inputSurface = null;
+
+        try {
+            try {
+                encoder = MediaCodec.createEncoderByType(MIME_TYPE);
+            } catch (IOException e) {
+                fail("failed to create " + MIME_TYPE + " encoder");
+            }
+            encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
+            inputSurface = new InputSurface(encoder.createInputSurface());
+            inputSurface.makeCurrent();
+            encoder.start();
+
+            int totalBuffers = encoder.getOutputBuffers().length;
+            if (VERBOSE) Log.d(TAG, "Total buffers: " + totalBuffers);
+
+            // Submit several frames quickly, without draining the encoder output, to try to
+            // ensure that we've got some queued up when we call stop().  If we do too many
+            // we'll block in swapBuffers().
+            for (int i = 0; i < totalBuffers; i++) {
+                GLES20.glClearColor(0.0f, (i % 8) / 8.0f, 0.0f, 1.0f);
+                GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
+                inputSurface.swapBuffers();
+            }
+            Log.d(TAG, "stopping");
+            encoder.stop();
+            Log.d(TAG, "stopped");
+        } finally {
+            if (encoder != null) {
+                encoder.stop();
+                encoder.release();
+            }
+            if (inputSurface != null) {
+                inputSurface.release();
+            }
+        }
+    }
+
+    /**
+     * Tests:
      * <br> dequeueInputBuffer() fails when encoder configured with an input Surface
      */
     public void testDequeueSurface() {
@@ -189,10 +437,10 @@
         Surface surface = null;
 
         try {
-            encoder = createEncoderForMimeType(MIME_TYPE);
-            if (encoder == null) {
-                // Pass if no codec was available.
-                return;
+            try {
+                encoder = MediaCodec.createEncoderByType(MIME_TYPE);
+            } catch (IOException e) {
+                fail("failed to create " + MIME_TYPE + " encoder");
             }
             encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
             surface = encoder.createInputSurface();
@@ -227,10 +475,10 @@
         Surface surface = null;
 
         try {
-            encoder = createEncoderForMimeType(MIME_TYPE);
-            if (encoder == null) {
-                // Pass if no codec was available.
-                return;
+            try {
+                encoder = MediaCodec.createEncoderByType(MIME_TYPE);
+            } catch (IOException e) {
+                fail("failed to create " + MIME_TYPE + " encoder");
             }
             encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
             surface = encoder.createInputSurface();
@@ -305,11 +553,8 @@
             mediaExtractor = getMediaExtractorForMimeType(inputResourceId, "video/");
             MediaFormat mediaFormat =
                     mediaExtractor.getTrackFormat(mediaExtractor.getSampleTrackIndex());
-            mediaCodec = createDecoderForMimeType(mediaFormat.getString(MediaFormat.KEY_MIME));
-            if (mediaCodec == null) {
-              // Pass if no decoder was available.
-              return true;
-            }
+            mediaCodec =
+                    MediaCodec.createDecoderByType(mediaFormat.getString(MediaFormat.KEY_MIME));
             mediaCodec.configure(mediaFormat, outputSurface.getSurface(), null, 0);
             mediaCodec.start();
             boolean eos = false;
@@ -384,15 +629,19 @@
         MediaCodec audioDecoderA = null;
         MediaCodec audioDecoderB = null;
         try {
-            audioDecoderA = createDecoderForMimeType(MIME_TYPE_AUDIO);
-            if (audioDecoderA == null) {
-              // Pass if no decoder was available.
-              return;
+            try {
+                audioDecoderA = MediaCodec.createDecoderByType(MIME_TYPE_AUDIO);
+            } catch (IOException e) {
+                fail("failed to create first " + MIME_TYPE_AUDIO + " decoder");
             }
             audioDecoderA.configure(format, null, null, 0);
             audioDecoderA.start();
 
-            audioDecoderB = createDecoderForMimeType(MIME_TYPE_AUDIO);
+            try {
+                audioDecoderB = MediaCodec.createDecoderByType(MIME_TYPE_AUDIO);
+            } catch (IOException e) {
+                fail("failed to create second " + MIME_TYPE_AUDIO + " decoder");
+            }
             audioDecoderB.configure(format, null, null, 0);
             audioDecoderB.start();
         } finally {
@@ -430,18 +679,18 @@
         MediaCodec audioEncoder = null;
         MediaCodec audioDecoder = null;
         try {
-            audioEncoder = createEncoderForMimeType(MIME_TYPE_AUDIO);
-            if (audioEncoder == null) {
-              // Pass if no encoder was available.
-              return;
+            try {
+                audioEncoder = MediaCodec.createEncoderByType(MIME_TYPE_AUDIO);
+            } catch (IOException e) {
+                fail("failed to create " + MIME_TYPE_AUDIO + " encoder");
             }
             audioEncoder.configure(encoderFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
             audioEncoder.start();
 
-            audioDecoder = createDecoderForMimeType(MIME_TYPE_AUDIO);
-            if (audioDecoder == null) {
-              // Pass if no decoder was available.
-              return;
+            try {
+                audioDecoder = MediaCodec.createDecoderByType(MIME_TYPE_AUDIO);
+            } catch (IOException e) {
+                fail("failed to create " + MIME_TYPE_AUDIO + " decoder");
             }
             audioDecoder.configure(decoderFormat, null, null, 0);
             audioDecoder.start();
@@ -471,10 +720,6 @@
         // audio only checks this and stop
         mVideoEncodingOngoing = true;
         final CodecInfo info = getAvcSupportedFormatInfo();
-        if (info == null) {
-            // Pass if no codec was available.
-            return;
-        }
         long start = System.currentTimeMillis();
         Thread videoEncodingThread = new Thread(new Runnable() {
             @Override
@@ -509,9 +754,6 @@
 
     private static CodecInfo getAvcSupportedFormatInfo() {
         MediaCodecInfo mediaCodecInfo = selectCodec(MIME_TYPE);
-        if (mediaCodecInfo == null) { // not supported
-            return null;
-        }
         CodecCapabilities cap = mediaCodecInfo.getCapabilitiesForType(MIME_TYPE);
         if (cap == null) { // not supported
             return null;
@@ -595,11 +837,7 @@
         InputSurface inputSurface = null;
         mVideoEncoderHadError = false;
         try {
-            encoder = createEncoderForMimeType(MIME_TYPE);
-            if (encoder == null) {
-              // Pass if no encoder was available.
-              return;
-            }
+            encoder = MediaCodec.createEncoderByType(MIME_TYPE);
             encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
             inputSurface = new InputSurface(encoder.createInputSurface());
             inputSurface.makeCurrent();
@@ -641,11 +879,7 @@
         MediaCodec encoder = null;
         mAudioEncoderHadError = false;
         try {
-            encoder = createEncoderForMimeType(MIME_TYPE_AUDIO);
-            if (encoder == null) {
-              // Pass if no codec was available.
-              return;
-            }
+            encoder = MediaCodec.createEncoderByType(MIME_TYPE_AUDIO);
             encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
             MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
             encoder.start();
@@ -748,39 +982,6 @@
         return 0;   // not reached
     }
 
-    /** Returns a decoder for {@code mimeType}, or {@code null} if none is available. */
-    private static MediaCodec createDecoderForMimeType(String mimeType) {
-        return createCodecForMimeType(mimeType, false);
-    }
-
-    /** Returns a encoder for {@code mimeType}, or {@code null} if none is available. */
-    private static MediaCodec createEncoderForMimeType(String mimeType) {
-        return createCodecForMimeType(mimeType, true);
-    }
-
-    /**
-     * Returns a codec for {@code mimeType}, or {@code null} if there is no suitable codec on this
-     * device. The codec is an encoder if {@code encoder} is {@code true}, and a decoder otherwise.
-     */
-    private static MediaCodec createCodecForMimeType(String mimeType, boolean encoder) {
-        mimeType = mimeType.toLowerCase(Locale.US);
-        for (int index = 0; index < MediaCodecList.getCodecCount(); index++) {
-            MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(index);
-            if (encoder != codecInfo.isEncoder()) {
-                continue;
-            }
-
-            for (String codecType : codecInfo.getSupportedTypes()) {
-                if (codecType.equals(mimeType)) {
-                    return encoder
-                            ? MediaCodec.createEncoderByType(codecType.toLowerCase(Locale.US))
-                            : MediaCodec.createDecoderByType(codecType.toLowerCase(Locale.US));
-                }
-            }
-        }
-        return null;
-    }
-
     private MediaExtractor getMediaExtractorForMimeType(int resourceId, String mimeTypePrefix)
             throws IOException {
         MediaExtractor mediaExtractor = new MediaExtractor();
diff --git a/tests/tests/media/src/android/media/cts/MediaDrmMockTest.java b/tests/tests/media/src/android/media/cts/MediaDrmMockTest.java
index a09d368..1a3184d 100644
--- a/tests/tests/media/src/android/media/cts/MediaDrmMockTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaDrmMockTest.java
@@ -22,6 +22,7 @@
 import android.media.MediaDrm.CryptoSession;
 import android.media.MediaDrmException;
 import android.media.NotProvisionedException;
+import android.media.ResourceBusyException;
 import android.test.AndroidTestCase;
 import android.util.Log;
 import java.util.HashMap;
@@ -785,6 +786,8 @@
             sessionId = md.openSession();
         } catch (NotProvisionedException e) {
             // ignore, not thrown by mock
+        } catch (ResourceBusyException e) {
+            // ignore, not thrown by mock
         }
         return sessionId;
     }
diff --git a/tests/tests/media/src/android/media/cts/MediaMuxerTest.java b/tests/tests/media/src/android/media/cts/MediaMuxerTest.java
index 9cad011..6591555 100644
--- a/tests/tests/media/src/android/media/cts/MediaMuxerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaMuxerTest.java
@@ -56,7 +56,8 @@
      */
     public void testVideoAudio() throws Exception {
         int source = R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_stereo_128kbps_11025hz;
-        String outputFile = "/sdcard/videoAudio.mp4";
+        String outputFile = File.createTempFile("MediaMuxerTest_testAudioVideo", ".mp4")
+                .getAbsolutePath();
         cloneAndVerify(source, outputFile, 2, 90);
     }
 
@@ -65,7 +66,8 @@
      */
     public void testAudioOnly() throws Exception {
         int source = R.raw.sinesweepm4a;
-        String outputFile = "/sdcard/audioOnly.mp4";
+        String outputFile = File.createTempFile("MediaMuxerTest_testAudioOnly", ".mp4")
+                .getAbsolutePath();
         cloneAndVerify(source, outputFile, 1, -1);
     }
 
@@ -74,7 +76,8 @@
      */
     public void testVideoOnly() throws Exception {
         int source = R.raw.video_only_176x144_3gp_h263_25fps;
-        String outputFile = "/sdcard/videoOnly.mp4";
+        String outputFile = File.createTempFile("MediaMuxerTest_videoOnly", ".mp4")
+                .getAbsolutePath();
         cloneAndVerify(source, outputFile, 1, 180);
     }
 
@@ -88,7 +91,8 @@
      * <br> Throws exception b/c a wrong format.
      */
     public void testIllegalStateExceptions() throws IOException {
-        String outputFile = "/sdcard/muxerExceptions.mp4";
+        String outputFile = File.createTempFile("MediaMuxerTest_testISEs", ".mp4")
+                .getAbsolutePath();
         MediaMuxer muxer;
 
         // Throws exception b/c start() is not called.
@@ -369,25 +373,26 @@
         String location = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_LOCATION);
         assertNotNull("No location information found in file " + fileName, location);
 
-        // parsing String location and recover the location inforamtion in floats
+
+        // parsing String location and recover the location information in floats
         // Make sure the tolerance is very small - due to rounding errors.
 
         // Get the position of the -/+ sign in location String, which indicates
-        // the beginning of the longtitude.
-        int index = location.lastIndexOf('-');
-        if (index == -1) {
-            index = location.lastIndexOf('+');
-        }
-        assertTrue("+ or - is not found", index != -1);
-        assertTrue("+ or - is only found at the beginning", index != 0);
+        // the beginning of the longitude.
+        int minusIndex = location.lastIndexOf('-');
+        int plusIndex = location.lastIndexOf('+');
+
+        assertTrue("+ or - is not found or found only at the beginning [" + location + "]",
+                (minusIndex > 0 || plusIndex > 0));
+        int index = Math.max(minusIndex, plusIndex);
+
         float latitude = Float.parseFloat(location.substring(0, index - 1));
         float longitude = Float.parseFloat(location.substring(index));
-        assertTrue("Incorrect latitude: " + latitude,
+        assertTrue("Incorrect latitude: " + latitude + " [" + location + "]",
                 Math.abs(latitude - LATITUDE) <= TOLERANCE);
-        assertTrue("Incorrect longitude: " + longitude,
+        assertTrue("Incorrect longitude: " + longitude + " [" + location + "]",
                 Math.abs(longitude - LONGITUDE) <= TOLERANCE);
         retriever.release();
     }
-
 }
 
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
index 385295b..799fd59 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
@@ -37,12 +37,17 @@
 import android.os.SystemClock;
 import android.util.Log;
 
+import java.io.BufferedReader;
 import java.io.File;
+import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.util.StringTokenizer;
 import java.util.UUID;
 import java.util.Vector;
 import java.util.concurrent.CountDownLatch;
 
+import junit.framework.AssertionFailedError;
+
 /**
  * Tests for the MediaPlayer API and local video/audio playback.
  *
@@ -148,11 +153,74 @@
         }
     }
 
-    public void testPlayAudio() throws Exception {
+    public void testPlayAudioFromDataURI() throws Exception {
         final int mp3Duration = 34909;
         final int tolerance = 70;
         final int seekDuration = 100;
+
+        // This is "R.raw.testmp3_2", base64-encoded.
+        final int resid = R.raw.testmp3_3;
+
+        InputStream is = mContext.getResources().openRawResource(resid);
+        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
+
+        StringBuilder builder = new StringBuilder();
+        builder.append("data:;base64,");
+        builder.append(reader.readLine());
+        Uri uri = Uri.parse(builder.toString());
+
+        MediaPlayer mp = MediaPlayer.create(mContext, uri);
+
+        try {
+            mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
+            mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
+
+            assertFalse(mp.isPlaying());
+            mp.start();
+            assertTrue(mp.isPlaying());
+
+            assertFalse(mp.isLooping());
+            mp.setLooping(true);
+            assertTrue(mp.isLooping());
+
+            assertEquals(mp3Duration, mp.getDuration(), tolerance);
+            int pos = mp.getCurrentPosition();
+            assertTrue(pos >= 0);
+            assertTrue(pos < mp3Duration - seekDuration);
+
+            mp.seekTo(pos + seekDuration);
+            assertEquals(pos + seekDuration, mp.getCurrentPosition(), tolerance);
+
+            // test pause and restart
+            mp.pause();
+            Thread.sleep(SLEEP_TIME);
+            assertFalse(mp.isPlaying());
+            mp.start();
+            assertTrue(mp.isPlaying());
+
+            // test stop and restart
+            mp.stop();
+            mp.reset();
+            mp.setDataSource(mContext, uri);
+            mp.prepare();
+            assertFalse(mp.isPlaying());
+            mp.start();
+            assertTrue(mp.isPlaying());
+
+            // waiting to complete
+            while(mp.isPlaying()) {
+                Thread.sleep(SLEEP_TIME);
+            }
+        } finally {
+            mp.release();
+        }
+    }
+
+    public void testPlayAudio() throws Exception {
         final int resid = R.raw.testmp3_2;
+        final int mp3Duration = 34909;
+        final int tolerance = 70;
+        final int seekDuration = 100;
 
         MediaPlayer mp = MediaPlayer.create(mContext, resid);
         try {
@@ -242,6 +310,98 @@
         }
     }
 
+    static class OutputListener {
+        int mSession;
+        AudioEffect mVc;
+        Visualizer mVis;
+        byte [] mVisData;
+        boolean mSoundDetected;
+        OutputListener(int session) {
+            mSession = session;
+            // creating a volume controller on output mix ensures that ro.audio.silent mutes
+            // audio after the effects and not before
+            mVc = new AudioEffect(
+                    AudioEffect.EFFECT_TYPE_NULL,
+                    UUID.fromString("119341a0-8469-11df-81f9-0002a5d5c51b"),
+                    0,
+                    session);
+            mVc.setEnabled(true);
+            mVis = new Visualizer(session);
+            int size = 256;
+            int[] range = Visualizer.getCaptureSizeRange();
+            if (size < range[0]) {
+                size = range[0];
+            }
+            if (size > range[1]) {
+                size = range[1];
+            }
+            assertTrue(mVis.setCaptureSize(size) == Visualizer.SUCCESS);
+
+            mVis.setDataCaptureListener(new Visualizer.OnDataCaptureListener() {
+                @Override
+                public void onWaveFormDataCapture(Visualizer visualizer,
+                        byte[] waveform, int samplingRate) {
+                    if (!mSoundDetected) {
+                        for (int i = 0; i < waveform.length; i++) {
+                            // 8 bit unsigned PCM, zero level is at 128, which is -128 when
+                            // seen as a signed byte
+                            if (waveform[i] != -128) {
+                                mSoundDetected = true;
+                                break;
+                            }
+                        }
+                    }
+                }
+
+                @Override
+                public void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate) {
+                }
+            }, 10000 /* milliHertz */, true /* PCM */, false /* FFT */);
+            assertTrue(mVis.setEnabled(true) == Visualizer.SUCCESS);
+        }
+
+        void reset() {
+            mSoundDetected = false;
+        }
+
+        boolean heardSound() {
+            return mSoundDetected;
+        }
+
+        void release() {
+            mVis.release();
+            mVc.release();
+        }
+    }
+
+    public void testPlayAudioTwice() throws Exception {
+        final int resid = R.raw.camera_click;
+
+        MediaPlayer mp = MediaPlayer.create(mContext, resid);
+        try {
+            mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
+            mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
+
+            OutputListener listener = new OutputListener(mp.getAudioSessionId());
+
+            Thread.sleep(SLEEP_TIME);
+            assertFalse("noise heard before test started", listener.heardSound());
+
+            mp.start();
+            Thread.sleep(SLEEP_TIME);
+            assertFalse("player was still playing after " + SLEEP_TIME + " ms", mp.isPlaying());
+            assertTrue("nothing heard while test ran", listener.heardSound());
+            listener.reset();
+            mp.seekTo(0);
+            mp.start();
+            Thread.sleep(SLEEP_TIME);
+            assertTrue("nothing heard when sound was replayed", listener.heardSound());
+            listener.release();
+        } finally {
+            mp.release();
+        }
+    }
+
     public void testPlayVideo() throws Exception {
         playVideoTest(R.raw.testvideo, 352, 288);
     }
@@ -504,14 +664,16 @@
         }
         byte [] vizdata = new byte[size];
         Visualizer vis = new Visualizer(session);
-        assertTrue(vis.setCaptureSize(vizdata.length) == Visualizer.SUCCESS);
-        assertTrue(vis.setEnabled(true) == Visualizer.SUCCESS);
         AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
         int oldRingerMode = am.getRingerMode();
         am.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
         int oldvolume = am.getStreamVolume(AudioManager.STREAM_MUSIC);
         am.setStreamVolume(AudioManager.STREAM_MUSIC, 1, 0);
         try {
+            assertEquals("setCaptureSize failed",
+                    Visualizer.SUCCESS, vis.setCaptureSize(vizdata.length));
+            assertEquals("setEnabled failed", Visualizer.SUCCESS, vis.setEnabled(true));
+
             mp1.setNextMediaPlayer(mp2);
             mp1.start();
             assertTrue(mp1.isPlaying());
@@ -728,6 +890,14 @@
                 R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz, 480, 360);
     }
 
+    public void testLocalVideo_MP4_H264_480x360_1350kbps_30fps_AAC_Stereo_128kbps_44110Hz_frag()
+            throws Exception {
+        playVideoTest(
+                R.raw.video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_128kbps_44100hz_fragmented,
+                480, 360);
+    }
+
+
     public void testLocalVideo_MP4_H264_480x360_1350kbps_30fps_AAC_Stereo_192kbps_44110Hz()
             throws Exception {
         playVideoTest(
@@ -911,11 +1081,18 @@
         }
     }
 
-    public void testDeselectTrack() throws Exception {
+    public void testDeselectTrack() throws Throwable {
         loadResource(R.raw.testvideo_with_2_subtitles);
-        loadSubtitleSource(R.raw.test_subtitle1_srt);
-        readTimedTextTracks();
-        assertEquals(getTimedTextTrackCount(), 3);
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                try {
+                    loadSubtitleSource(R.raw.test_subtitle1_srt);
+                } catch (Exception e) {
+                    throw new AssertionFailedError(e.getMessage());
+                }
+            }
+        });
+        getInstrumentation().waitForIdleSync();
 
         mMediaPlayer.setDisplay(getActivity().getSurfaceHolder());
         mMediaPlayer.setScreenOnWhilePlaying(true);
@@ -933,6 +1110,9 @@
             }
         });
         mMediaPlayer.prepare();
+        readTimedTextTracks();
+        assertEquals(getTimedTextTrackCount(), 3);
+
         mMediaPlayer.start();
         assertTrue(mMediaPlayer.isPlaying());
 
@@ -941,24 +1121,24 @@
             // Waits until at least one subtitle is fired. Timeout is 1 sec.
             selectSubtitleTrack(0);
             mOnTimedTextCalled.reset();
-            assertTrue(mOnTimedTextCalled.waitForSignal(1000));
+            assertTrue(mOnTimedTextCalled.waitForSignal(1500));
 
             // Try deselecting track.
             deselectSubtitleTrack(0);
             mOnTimedTextCalled.reset();
-            assertFalse(mOnTimedTextCalled.waitForSignal(1000));
+            assertFalse(mOnTimedTextCalled.waitForSignal(1500));
         }
 
         // Run the same test for external subtitle track.
         for (int i = 0; i < 2; i++) {
             selectSubtitleTrack(2);
             mOnTimedTextCalled.reset();
-            assertTrue(mOnTimedTextCalled.waitForSignal(1000));
+            assertTrue(mOnTimedTextCalled.waitForSignal(1500));
 
             // Try deselecting track.
             deselectSubtitleTrack(2);
             mOnTimedTextCalled.reset();
-            assertFalse(mOnTimedTextCalled.waitForSignal(1000));
+            assertFalse(mOnTimedTextCalled.waitForSignal(1500));
         }
 
         try {
@@ -972,16 +1152,8 @@
         mMediaPlayer.stop();
     }
 
-    public void testChangeSubtitleTrack() throws Exception {
+    public void testChangeSubtitleTrack() throws Throwable {
         loadResource(R.raw.testvideo_with_2_subtitles);
-        readTimedTextTracks();
-        assertEquals(getTimedTextTrackCount(), 2);
-
-        // Adds two more external subtitle files.
-        loadSubtitleSource(R.raw.test_subtitle1_srt);
-        loadSubtitleSource(R.raw.test_subtitle2_srt);
-        readTimedTextTracks();
-        assertEquals(getTimedTextTrackCount(), 4);
 
         mMediaPlayer.setDisplay(getActivity().getSurfaceHolder());
         mMediaPlayer.setScreenOnWhilePlaying(true);
@@ -989,7 +1161,7 @@
         mMediaPlayer.setOnTimedTextListener(new MediaPlayer.OnTimedTextListener() {
             @Override
             public void onTimedText(MediaPlayer mp, TimedText text) {
-                final int toleranceMs = 100;
+                final int toleranceMs = 500;
                 final int durationMs = 500;
                 int posMs = mMediaPlayer.getCurrentPosition();
                 if (text != null) {
@@ -1016,6 +1188,32 @@
 
         mMediaPlayer.prepare();
         assertFalse(mMediaPlayer.isPlaying());
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                try {
+                    readTimedTextTracks();
+                } catch (Exception e) {
+                    throw new AssertionFailedError(e.getMessage());
+                }
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+        assertEquals(getTimedTextTrackCount(), 2);
+
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                try {
+                    // Adds two more external subtitle files.
+                    loadSubtitleSource(R.raw.test_subtitle1_srt);
+                    loadSubtitleSource(R.raw.test_subtitle2_srt);
+                    readTimedTextTracks();
+                } catch (Exception e) {
+                    throw new AssertionFailedError(e.getMessage());
+                }
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+        assertEquals(getTimedTextTrackCount(), 4);
 
         selectSubtitleTrack(0);
         mOnTimedTextCalled.reset();
@@ -1026,26 +1224,35 @@
         // Waits until at least two subtitles are fired. Timeout is 2 sec.
         // Please refer the test srt files:
         // test_subtitle1_srt.3gp and test_subtitle2_srt.3gp
-        assertTrue(mOnTimedTextCalled.waitForCountedSignals(2, 2000) >= 2);
+        assertTrue(mOnTimedTextCalled.waitForCountedSignals(2, 2500) >= 2);
 
         selectSubtitleTrack(1);
         mOnTimedTextCalled.reset();
-        assertTrue(mOnTimedTextCalled.waitForCountedSignals(2, 2000) >= 2);
+        assertTrue(mOnTimedTextCalled.waitForCountedSignals(2, 2500) >= 2);
 
         selectSubtitleTrack(2);
         mOnTimedTextCalled.reset();
-        assertTrue(mOnTimedTextCalled.waitForCountedSignals(2, 2000) >= 2);
+        assertTrue(mOnTimedTextCalled.waitForCountedSignals(2, 2500) >= 2);
 
         selectSubtitleTrack(3);
         mOnTimedTextCalled.reset();
-        assertTrue(mOnTimedTextCalled.waitForCountedSignals(2, 2000) >= 2);
+        assertTrue(mOnTimedTextCalled.waitForCountedSignals(2, 2500) >= 2);
         mMediaPlayer.stop();
     }
 
-    public void testGetTrackInfo() throws Exception {
+    public void testGetTrackInfo() throws Throwable {
         loadResource(R.raw.testvideo_with_2_subtitles);
-        loadSubtitleSource(R.raw.test_subtitle1_srt);
-        loadSubtitleSource(R.raw.test_subtitle2_srt);
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                try {
+                    loadSubtitleSource(R.raw.test_subtitle1_srt);
+                    loadSubtitleSource(R.raw.test_subtitle2_srt);
+                } catch (Exception e) {
+                    throw new AssertionFailedError(e.getMessage());
+                }
+            }
+        });
+        getInstrumentation().waitForIdleSync();
         mMediaPlayer.prepare();
         mMediaPlayer.start();
 
@@ -1060,7 +1267,7 @@
             if (trackInfos[i].getTrackType() == MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT) {
                 String trackLanguage = trackInfos[i].getLanguage();
                 assertTrue(trackLanguage != null);
-                trackLanguage.trim();
+                trackLanguage = trackLanguage.trim();
                 Log.d(LOG_TAG, "track info lang: " + trackLanguage);
                 assertTrue("Should not see empty track language with our test data.",
                            trackLanguage.length() > 0);
@@ -1071,6 +1278,41 @@
         assertEquals(4, count);
     }
 
+    /*
+     *  This test assumes the resources being tested are between 8 and 14 seconds long
+     *  The ones being used here are 10 seconds long.
+     */
+    public void testResumeAtEnd() throws Throwable {
+        testResumeAtEnd(R.raw.loudsoftmp3);
+        testResumeAtEnd(R.raw.loudsoftwav);
+        testResumeAtEnd(R.raw.loudsoftogg);
+        testResumeAtEnd(R.raw.loudsoftitunes);
+        testResumeAtEnd(R.raw.loudsoftfaac);
+        testResumeAtEnd(R.raw.loudsoftaac);
+    }
+
+    private void testResumeAtEnd(int res) throws Throwable {
+
+        loadResource(res);
+        mMediaPlayer.prepare();
+        mOnCompletionCalled.reset();
+        mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+            @Override
+            public void onCompletion(MediaPlayer mp) {
+                mOnCompletionCalled.signal();
+                mMediaPlayer.start();
+            }
+        });
+        // skip the first part of the file so we reach EOF sooner
+        mMediaPlayer.seekTo(5000);
+        mMediaPlayer.start();
+        // sleep long enough that we restart playback at least once, but no more
+        Thread.sleep(10000);
+        assertTrue("MediaPlayer should still be playing", mMediaPlayer.isPlaying());
+        mMediaPlayer.reset();
+        assertEquals("wrong number of repetitions", 1, mOnCompletionCalled.getNumSignal());
+    }
+
     public void testCallback() throws Throwable {
         final int mp4Duration = 8484;
 
diff --git a/tests/tests/media/src/android/media/cts/MediaRandomTest.java b/tests/tests/media/src/android/media/cts/MediaRandomTest.java
index f99c927..7b49a37 100644
--- a/tests/tests/media/src/android/media/cts/MediaRandomTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaRandomTest.java
@@ -170,8 +170,13 @@
             afd.close();
         }
     }
-
-    public void testPlayerRandomAction() throws Exception {
+    public void testPlayerRandomActionH264() throws Exception {
+        testPlayerRandomAction(R.raw.video_480x360_mp4_h264_500kbps_30fps_aac_stereo_128kbps_44100hz);
+    }
+    public void testPlayerRandomActionHEVC() throws Exception {
+        testPlayerRandomAction(R.raw.video_480x360_mp4_hevc_650kbps_30fps_aac_stereo_128kbps_48000hz);
+    }
+    private void testPlayerRandomAction(int resid) throws Exception {
         Watchdog watchdog = new Watchdog(5000);
         try {
             mPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@@ -185,7 +190,7 @@
                     return true;
                 }
             });
-            loadSource(R.raw.video_480x360_mp4_h264_500kbps_30fps_aac_stereo_128kbps_44100hz);
+            loadSource(resid);
             mPlayer.setDisplay(mSurfaceHolder);
             mPlayer.prepare();
             mPlayer.start();
diff --git a/tests/tests/media/src/android/media/cts/MediaScannerConnectionTest.java b/tests/tests/media/src/android/media/cts/MediaScannerConnectionTest.java
index 4234a5b..ddf87b8 100644
--- a/tests/tests/media/src/android/media/cts/MediaScannerConnectionTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaScannerConnectionTest.java
@@ -21,12 +21,12 @@
 
 import android.content.ComponentName;
 import android.content.Context;
+import android.cts.util.FileCopyHelper;
 import android.cts.util.PollingCheck;
 import android.media.MediaScannerConnection;
 import android.media.MediaScannerConnection.MediaScannerConnectionClient;
 import android.net.Uri;
 import android.os.IBinder;
-import android.provider.cts.FileCopyHelper;
 import android.test.AndroidTestCase;
 
 import java.io.File;
diff --git a/tests/tests/media/src/android/media/cts/MediaScannerTest.java b/tests/tests/media/src/android/media/cts/MediaScannerTest.java
index 2dafdc5..4b42690 100644
--- a/tests/tests/media/src/android/media/cts/MediaScannerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaScannerTest.java
@@ -25,8 +25,11 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.res.AssetFileDescriptor;
+import android.cts.util.FileCopyHelper;
 import android.cts.util.PollingCheck;
 import android.database.Cursor;
+import android.media.MediaMetadataRetriever;
 import android.media.MediaScannerConnection;
 import android.media.MediaScannerConnection.MediaScannerConnectionClient;
 import android.mtp.MtpConstants;
@@ -36,7 +39,6 @@
 import android.os.IBinder;
 import android.os.SystemClock;
 import android.provider.MediaStore;
-import android.provider.cts.FileCopyHelper;
 import android.test.AndroidTestCase;
 import android.util.Log;
 
@@ -76,6 +78,7 @@
 
     @Override
     protected void tearDown() throws Exception {
+        cleanup();
         super.tearDown();
     }
 
@@ -84,10 +87,12 @@
             mMediaFile.delete();
         }
         if (mFileDir != null) {
-            new File(mFileDir + "/testmp3.mp3").delete();
-            new File(mFileDir + "/testmp3_2.mp3").delete();
-            new File(mFileDir + "/ctsmediascanplaylist1.pls").delete();
-            new File(mFileDir + "/ctsmediascanplaylist2.m3u").delete();
+            String files[] = new File(mFileDir).list();
+            if (files != null) {
+                for (String f: files) {
+                    new File(mFileDir + "/" + f).delete();
+                }
+            }
             new File(mFileDir).delete();
         }
 
@@ -367,6 +372,179 @@
         assertTrue(new File(path2).delete());
     }
 
+    static class MediaScanEntry {
+        MediaScanEntry(int r, String[] t) {
+            this.res = r;
+            this.tags = t;
+        }
+        int res;
+        String[] tags;
+    }
+
+    MediaScanEntry encodingtestfiles[] = {
+            new MediaScanEntry(R.raw.gb18030_1,
+                    new String[] {"罗志祥", "2009年11月新歌", "罗志祥", "爱不单行(TV Version)", null} ),
+            new MediaScanEntry(R.raw.gb18030_2,
+                    new String[] {"张杰", "明天过后", null, "明天过后", null} ),
+            new MediaScanEntry(R.raw.gb18030_3,
+                    new String[] {"电视原声带", "格斗天王(限量精装版)(预购版)", null, "11.Open Arms.( cn808.net )", null} ),
+            new MediaScanEntry(R.raw.gb18030_4,
+                    new String[] {"莫扎特", "黄金古典", "柏林爱乐乐团", "第25号交响曲", "莫扎特"} ),
+            new MediaScanEntry(R.raw.gb18030_5,
+                    new String[] {"光良", "童话", "光良", "02.童话", "鍏夎壇"} ),
+            new MediaScanEntry(R.raw.gb18030_6,
+                    new String[] {"张韶涵", "潘朵拉", "張韶涵", "隐形的翅膀", "王雅君"} ),
+            new MediaScanEntry(R.raw.gb18030_7, // this is actually utf-8
+                    new String[] {"五月天", "后青春期的诗", null, "突然好想你", null} ),
+            new MediaScanEntry(R.raw.gb18030_8,
+                    new String[] {"周杰伦", "Jay", null, "反方向的钟", null} ),
+            new MediaScanEntry(R.raw.big5_1,
+                    new String[] {"蘇永康", "So I Sing 08 Live", "蘇永康", "囍帖街", null} ),
+            new MediaScanEntry(R.raw.big5_2,
+                    new String[] {"蘇永康", "So I Sing 08 Live", "蘇永康", "從不喜歡孤單一個 - 蘇永康/吳雨霏", null} ),
+            new MediaScanEntry(R.raw.cp1251_v1,
+                    new String[] {"Екатерина Железнова", "Корабль игрушек", null, "Раз, два, три", null} ),
+            new MediaScanEntry(R.raw.cp1251_v1v2,
+                    new String[] {"Мельница", "Перевал", null, "Королевна", null} ),
+            new MediaScanEntry(R.raw.cp1251_3,
+                    new String[] {"Тату (tATu)", "200 По Встречной [Limited edi", null, "Я Сошла С Ума", null} ),
+            // The following 3 use cp1251 encoding, expanded to 16 bits and stored as utf16 
+            new MediaScanEntry(R.raw.cp1251_4,
+                    new String[] {"Александр Розенбаум", "Философия любви", null, "Разговор в гостинице (Как жить без веры)", "А.Розенбаум"} ),
+            new MediaScanEntry(R.raw.cp1251_5,
+                    new String[] {"Александр Розенбаум", "Философия любви", null, "Четвертиночка", "А.Розенбаум"} ),
+            new MediaScanEntry(R.raw.cp1251_6,
+                    new String[] {"Александр Розенбаум", "Философия ремесла", null, "Ну, вот...", "А.Розенбаум"} ),
+            new MediaScanEntry(R.raw.cp1251_7,
+                    new String[] {"Вопли Видоплясова", "Хвилі Амура", null, "Або або", null} ),
+            new MediaScanEntry(R.raw.cp1251_8,
+                    new String[] {"Вопли Видоплясова", "Хвилі Амура", null, "Таємнi сфери", null} ),
+            new MediaScanEntry(R.raw.shiftjis1,
+                    new String[] {"", "", null, "中島敦「山月記」(第1回)", null} ),
+            new MediaScanEntry(R.raw.shiftjis2,
+                    new String[] {"音人", "SoundEffects", null, "ファンファーレ", null} ),
+            new MediaScanEntry(R.raw.shiftjis3,
+                    new String[] {"音人", "SoundEffects", null, "シンキングタイム", null} ),
+            new MediaScanEntry(R.raw.shiftjis4,
+                    new String[] {"音人", "SoundEffects", null, "出題", null} ),
+            new MediaScanEntry(R.raw.shiftjis5,
+                    new String[] {"音人", "SoundEffects", null, "時報", null} ),
+            new MediaScanEntry(R.raw.shiftjis6,
+                    new String[] {"音人", "SoundEffects", null, "正解", null} ),
+            new MediaScanEntry(R.raw.shiftjis7,
+                    new String[] {"音人", "SoundEffects", null, "残念", null} ),
+            new MediaScanEntry(R.raw.shiftjis8,
+                    new String[] {"音人", "SoundEffects", null, "間違い", null} ),
+            new MediaScanEntry(R.raw.iso88591_1,
+                    new String[] {"Mozart", "Best of Mozart", null, "Overtüre (Die Hochzeit des Figaro)", null} ),
+            new MediaScanEntry(R.raw.iso88591_2, // actually UTF16, but only uses iso8859-1 chars
+                    new String[] {"Björk", "Telegram", "Björk", "Possibly Maybe (Lucy Mix)", null} ),
+            new MediaScanEntry(R.raw.hebrew,
+                    new String[] {"אריק סיני", "", null, "לי ולך", null } ),
+            new MediaScanEntry(R.raw.hebrew2,
+                    new String[] {"הפרוייקט של עידן רייכל", "Untitled - 11-11-02 (9)", null, "בואי", null } ),
+            new MediaScanEntry(R.raw.iso88591_3,
+                    new String[] {"Mobilé", "Kartographie", null, "Zu Wenig", null }),
+            new MediaScanEntry(R.raw.iso88591_4,
+                    new String[] {"Mobilé", "Kartographie", null, "Rotebeetesalat (Igel Stehlen)", null }),
+            new MediaScanEntry(R.raw.iso88591_5,
+                    new String[] {"The Creatures", "Hai! [UK Bonus DVD] Disc 1", "The Creatures", "Imagoró", null }),
+            new MediaScanEntry(R.raw.iso88591_6,
+                    new String[] {"¡Forward, Russia!", "Give Me a Wall", "Forward Russia", "Fifteen, Pt. 1", "Canning/Nicholls/Sarah Nicolls/Woodhead"}),
+            new MediaScanEntry(R.raw.iso88591_7,
+                    new String[] {"Björk", "Homogenic", "Björk", "Jòga", "Björk/Sjòn"}),
+            // this one has a genre of "Indé" which confused the detector
+            new MediaScanEntry(R.raw.iso88591_8,
+                    new String[] {"The Black Heart Procession", "3", null, "A Heart Like Mine", null}),
+            new MediaScanEntry(R.raw.iso88591_9,
+                    new String[] {"DJ Tiësto", "Just Be", "DJ Tiësto", "Adagio For Strings", "Samuel Barber"}),
+            new MediaScanEntry(R.raw.iso88591_10,
+                    new String[] {"Ratatat", "LP3", null, "Bruleé", null}),
+            new MediaScanEntry(R.raw.iso88591_11,
+                    new String[] {"Sempé", "Le Petit Nicolas vol. 1", null, "Les Cow-Boys", null}),
+            new MediaScanEntry(R.raw.iso88591_12,
+                    new String[] {"UUVVWWZ", "UUVVWWZ", null, "Neolaño", null}),
+            new MediaScanEntry(R.raw.iso88591_13,
+                    new String[] {"Michael Bublé", "Crazy Love", "Michael Bublé", "Haven't Met You Yet", null}),
+            new MediaScanEntry(R.raw.utf16_1,
+                    new String[] {"Shakira", "Latin Mix USA", "Shakira", "Estoy Aquí", null})
+    };
+
+    public void testEncodingDetection() throws Exception {
+        for (int i = 0; i< encodingtestfiles.length; i++) {
+            MediaScanEntry entry = encodingtestfiles[i];
+            String name = mContext.getResources().getResourceEntryName(entry.res);
+            String path =  mFileDir + "/" + name + ".mp3";
+            writeFile(entry.res, path);
+        }
+
+        startMediaScanAndWait();
+
+        String columns[] = {
+                MediaStore.Audio.Media.ARTIST,
+                MediaStore.Audio.Media.ALBUM,
+                MediaStore.Audio.Media.ALBUM_ARTIST,
+                MediaStore.Audio.Media.TITLE,
+                MediaStore.Audio.Media.COMPOSER
+        };
+        ContentResolver res = mContext.getContentResolver();
+        for (int i = 0; i< encodingtestfiles.length; i++) {
+            MediaScanEntry entry = encodingtestfiles[i];
+            String name = mContext.getResources().getResourceEntryName(entry.res);
+            String path =  mFileDir + "/" + name + ".mp3";
+            Cursor c = res.query(MediaStore.Audio.Media.getContentUri("external"), columns,
+                    MediaStore.Audio.Media.DATA + "=?", new String[] {path}, null);
+            assertNotNull("null cursor", c);
+            assertEquals("wrong number or results", 1, c.getCount());
+            assertTrue("failed to move cursor", c.moveToFirst());
+
+            for (int j =0; j < 5; j++) {
+                String expected = entry.tags[j];
+                if ("".equals(expected)) {
+                    // empty entry in the table means an unset id3 tag that is filled in by
+                    // the media scanner, e.g. by using "<unknown>". Since this may be localized,
+                    // don't check it for any particular value.
+                    assertNotNull("unexpected null entry " + i + " field " + j + "(" + path + ")",
+                            c.getString(j));
+                } else {
+                    assertEquals("mismatch on entry " + i + " field " + j + "(" + path + ")",
+                            expected, c.getString(j));
+                }
+            }
+            // clean up
+            new File(path).delete();
+            res.delete(MediaStore.Audio.Media.getContentUri("external"),
+                    MediaStore.Audio.Media.DATA + "=?", new String[] {path});
+
+            c.close();
+
+            // also test with the MediaMetadataRetriever API
+            MediaMetadataRetriever woodly = new MediaMetadataRetriever();
+            AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(entry.res);
+            woodly.setDataSource(afd.getFileDescriptor(),
+                    afd.getStartOffset(), afd.getDeclaredLength());
+
+            String[] actual = new String[5];
+            actual[0] = woodly.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
+            actual[1] = woodly.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
+            actual[2] = woodly.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST);
+            actual[3] = woodly.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
+            actual[4] = woodly.extractMetadata(MediaMetadataRetriever.METADATA_KEY_COMPOSER);
+
+            for (int j = 0; j < 5; j++) {
+                if ("".equals(entry.tags[j])) {
+                    // retriever doesn't insert "unknown artist" and such, it just returns null
+                    assertNull("retriever: unexpected non-null for entry " + i + " field " + j,
+                            actual[j]);
+                } else {
+                    Log.i("@@@", "tags: @@" + entry.tags[j] + "@@" + actual[j] + "@@");
+                    assertEquals("retriever: mismatch on entry " + i + " field " + j,
+                            entry.tags[j], actual[j]);
+                }
+            }
+        }
+    }
+
     private void startMediaScanAndWait() throws InterruptedException {
         ScannerNotificationReceiver finishedReceiver = new ScannerNotificationReceiver(
                 Intent.ACTION_MEDIA_SCANNER_FINISHED);
diff --git a/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java b/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java
new file mode 100644
index 0000000..b10d9df
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java
@@ -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.
+ */
+package android.media.cts;
+
+import android.content.Context;
+import android.media.session.MediaController;
+import android.media.session.MediaSessionManager;
+import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
+
+import java.util.List;
+
+public class MediaSessionManagerTest extends InstrumentationTestCase {
+    private MediaSessionManager mSessionManager;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mSessionManager = (MediaSessionManager) getInstrumentation().getTargetContext()
+                .getSystemService(Context.MEDIA_SESSION_SERVICE);
+    }
+
+    public void testGetActiveSessions() throws Exception {
+        try {
+            List<MediaController> controllers = mSessionManager.getActiveSessions(null);
+            fail("Expected security exception for unauthorized call to getActiveSessions");
+        } catch (SecurityException e) {
+            // Expected
+        }
+        // TODO enable a notification listener, test again, disable, test again
+    }
+
+    @UiThreadTest
+    public void testAddOnActiveSessionsListener() throws Exception {
+        try {
+            mSessionManager.addOnActiveSessionsChangedListener(null, null);
+            fail("Expected IAE for call to addOnActiveSessionsChangedListener");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+
+        MediaSessionManager.OnActiveSessionsChangedListener listener
+                = new MediaSessionManager.OnActiveSessionsChangedListener() {
+            @Override
+            public void onActiveSessionsChanged(List<MediaController> controllers) {
+
+            }
+        };
+        try {
+            mSessionManager.addOnActiveSessionsChangedListener(listener, null);
+            fail("Expected security exception for call to addOnActiveSessionsChangedListener");
+        } catch (SecurityException e) {
+            // Expected
+        }
+
+        // TODO enable a notification listener, test again, disable, verify
+        // updates stopped
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaSessionTest.java b/tests/tests/media/src/android/media/cts/MediaSessionTest.java
new file mode 100644
index 0000000..df68392
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaSessionTest.java
@@ -0,0 +1,183 @@
+/*
+ * 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.media.cts;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.media.AudioAttributes;
+import android.media.AudioManager;
+import android.media.MediaDescription;
+import android.media.MediaMetadata;
+import android.media.Rating;
+import android.media.VolumeProvider;
+import android.media.session.MediaController;
+import android.media.session.MediaSession;
+import android.media.session.MediaSessionManager;
+import android.media.session.PlaybackState;
+import android.os.Bundle;
+import android.test.AndroidTestCase;
+
+import java.util.ArrayList;
+import java.util.Set;
+
+public class MediaSessionTest extends AndroidTestCase {
+    private AudioManager mAudioManager;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+    }
+
+    /**
+     * Tests that a session can be created and that all the fields are
+     * initialized correctly.
+     */
+    public void testCreateSession() throws Exception {
+        String tag = "test session";
+        MediaSession session = new MediaSession(getContext(), tag);
+        assertNotNull(session.getSessionToken());
+        assertFalse("New session should not be active", session.isActive());
+
+        // Verify by getting the controller and checking all its fields
+        MediaController controller = session.getController();
+        assertNotNull(controller);
+        verifyNewSession(controller, tag);
+    }
+
+    /**
+     * Tests that the various configuration bits on a session get passed to the
+     * controller.
+     */
+    public void testConfigureSession() throws Exception {
+        String tag = "test session";
+        String key = "test-key";
+        String val = "test-val";
+        MediaSession session = new MediaSession(getContext(), tag);
+        MediaController controller = session.getController();
+
+        // test setExtras
+        Bundle extras = new Bundle();
+        extras.putString(key, val);
+        session.setExtras(extras);
+        Bundle extrasOut = controller.getExtras();
+        assertNotNull(extrasOut);
+        assertEquals(val, extrasOut.get(key));
+
+        // test setFlags
+        session.setFlags(5);
+        assertEquals(5, controller.getFlags());
+
+        // test setMetadata
+        MediaMetadata metadata = new MediaMetadata.Builder().putString(key, val).build();
+        session.setMetadata(metadata);
+        MediaMetadata metadataOut = controller.getMetadata();
+        assertNotNull(metadataOut);
+        assertEquals(val, metadataOut.getString(key));
+
+        // test setPlaybackState
+        PlaybackState state = new PlaybackState.Builder().setActions(55).build();
+        session.setPlaybackState(state);
+        PlaybackState stateOut = controller.getPlaybackState();
+        assertNotNull(stateOut);
+        assertEquals(55L, stateOut.getActions());
+
+        // test setPlaybackToRemote, do this before testing setPlaybackToLocal
+        // to ensure it switches correctly.
+        try {
+            session.setPlaybackToRemote(null);
+            fail("Expected IAE for setPlaybackToRemote(null)");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+        VolumeProvider vp = new VolumeProvider(VolumeProvider.VOLUME_CONTROL_FIXED, 11, 11) {};
+        session.setPlaybackToRemote(vp);
+        MediaController.PlaybackInfo info = controller.getPlaybackInfo();
+        assertNotNull(info);
+        assertEquals(MediaController.PlaybackInfo.PLAYBACK_TYPE_REMOTE, info.getPlaybackType());
+        assertEquals(11, info.getMaxVolume());
+        assertEquals(11, info.getCurrentVolume());
+        assertEquals(VolumeProvider.VOLUME_CONTROL_FIXED, info.getVolumeControl());
+
+        // test setPlaybackToLocal
+        AudioAttributes attrs = new AudioAttributes.Builder().addTag(val).build();
+        session.setPlaybackToLocal(attrs);
+        info = controller.getPlaybackInfo();
+        assertNotNull(info);
+        assertEquals(MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL, info.getPlaybackType());
+        Set<String> tags = info.getAudioAttributes().getTags();
+        assertNotNull(tags);
+        assertTrue(tags.contains(val));
+
+        // test setQueue and setQueueTitle
+        ArrayList<MediaSession.QueueItem> queue = new ArrayList<MediaSession.QueueItem>();
+        MediaSession.QueueItem item = new MediaSession.QueueItem(new MediaDescription.Builder()
+                .setMediaId(val).setTitle("title").build(), 11);
+        queue.add(item);
+        session.setQueue(queue);
+        session.setQueueTitle(val);
+
+        assertEquals(val, controller.getQueueTitle());
+        assertEquals(1, controller.getQueue().size());
+        assertEquals(11, controller.getQueue().get(0).getQueueId());
+        assertEquals(val, controller.getQueue().get(0).getDescription().getMediaId());
+
+        session.setQueue(null);
+        session.setQueueTitle(null);
+
+        assertNull(controller.getQueueTitle());
+        assertNull(controller.getQueue());
+
+        // test setSessionActivity
+        Intent intent = new Intent("cts.MEDIA_SESSION_ACTION");
+        PendingIntent pi = PendingIntent.getActivity(getContext(), 555, intent, 0);
+        session.setSessionActivity(pi);
+        assertEquals(pi, controller.getSessionActivity());
+    }
+
+    /**
+     * Verifies that a new session hasn't had any configuration bits set yet.
+     *
+     * @param controller The controller for the session
+     */
+    private void verifyNewSession(MediaController controller, String tag) {
+        assertEquals("New session has unexpected configuration", 0L, controller.getFlags());
+        assertNull("New session has unexpected configuration", controller.getExtras());
+        assertNull("New session has unexpected configuration", controller.getMetadata());
+        assertEquals("New session has unexpected configuration",
+                getContext().getPackageName(), controller.getPackageName());
+        assertNull("New session has unexpected configuration", controller.getPlaybackState());
+        assertNull("New session has unexpected configuration", controller.getQueue());
+        assertNull("New session has unexpected configuration", controller.getQueueTitle());
+        assertEquals("New session has unexpected configuration", Rating.RATING_NONE,
+                controller.getRatingType());
+        assertNull("New session has unexpected configuration", controller.getSessionActivity());
+
+        assertNotNull(controller.getSessionToken());
+        assertNotNull(controller.getTransportControls());
+        assertEquals(tag, controller.getTag());
+
+        MediaController.PlaybackInfo info = controller.getPlaybackInfo();
+        assertNotNull(info);
+        assertEquals(MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL, info.getPlaybackType());
+        AudioAttributes attrs = info.getAudioAttributes();
+        assertNotNull(attrs);
+        assertEquals(AudioAttributes.USAGE_MEDIA, attrs.getUsage());
+        assertEquals(mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC),
+                info.getCurrentVolume());
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/NativeDecoderTest.java b/tests/tests/media/src/android/media/cts/NativeDecoderTest.java
new file mode 100644
index 0000000..fc27dfa
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/NativeDecoderTest.java
@@ -0,0 +1,491 @@
+/*
+ * 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.media.cts;
+
+import com.android.cts.media.R;
+
+import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
+import android.media.MediaCodec;
+import android.media.MediaCodec.BufferInfo;
+import android.media.MediaCodecInfo;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
+import android.media.MediaMetadataRetriever;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.os.Environment;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+import android.view.Surface;
+import android.webkit.cts.CtsTestServer;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+public class NativeDecoderTest extends MediaPlayerTestBase {
+    private static final String TAG = "DecoderTest";
+
+    private static final int RESET_MODE_NONE = 0;
+    private static final int RESET_MODE_RECONFIGURE = 1;
+    private static final int RESET_MODE_FLUSH = 2;
+    private static final int RESET_MODE_EOS_FLUSH = 3;
+
+    private static final String[] CSD_KEYS = new String[] { "csd-0", "csd-1" };
+
+    private static final int CONFIG_MODE_NONE = 0;
+    private static final int CONFIG_MODE_QUEUE = 1;
+
+    private static Resources mResources;
+    short[] mMasterBuffer;
+
+    /** Load jni on initialization */
+    static {
+        Log.i("@@@", "before loadlibrary");
+        System.loadLibrary("ctsmediacodec_jni");
+        Log.i("@@@", "after loadlibrary");
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mResources = mContext.getResources();
+
+    }
+
+    // check that native extractor behavior matches java extractor
+
+    public void testExtractor() throws Exception {
+        testExtractor(R.raw.sinesweepogg);
+        testExtractor(R.raw.sinesweepmp3lame);
+        testExtractor(R.raw.sinesweepmp3smpb);
+        testExtractor(R.raw.sinesweepm4a);
+        testExtractor(R.raw.sinesweepflac);
+        testExtractor(R.raw.sinesweepwav);
+
+        testExtractor(R.raw.video_1280x720_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz);
+        testExtractor(R.raw.video_1280x720_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz);
+        testExtractor(R.raw.video_1280x720_webm_vp9_309kbps_25fps_vorbis_stereo_128kbps_44100hz);
+        testExtractor(R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_mono_24kbps_11025hz);
+        testExtractor(R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz);
+
+        CtsTestServer foo = new CtsTestServer(mContext);
+        testExtractor(foo.getAssetUrl("noiseandchirps.ogg"));
+        testExtractor(foo.getAssetUrl("ringer.mp3"));
+        testExtractor(foo.getRedirectingAssetUrl("ringer.mp3"));
+    }
+
+    private void testExtractor(String path) throws Exception {
+        int[] jsizes = getSampleSizes(path);
+        int[] nsizes = getSampleSizesNativePath(path);
+
+        //Log.i("@@@", Arrays.toString(jsizes));
+        assertTrue("different samplesizes", Arrays.equals(jsizes, nsizes));
+    }
+
+    private void testExtractor(int res) throws Exception {
+        AssetFileDescriptor fd = mResources.openRawResourceFd(res);
+
+        int[] jsizes = getSampleSizes(
+                fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
+        int[] nsizes = getSampleSizesNative(
+                fd.getParcelFileDescriptor().getFd(), fd.getStartOffset(), fd.getLength());
+
+        fd.close();
+        //Log.i("@@@", Arrays.toString(jsizes));
+        assertTrue("different samplesizes", Arrays.equals(jsizes, nsizes));
+    }
+
+    private static int[] getSampleSizes(String path) throws IOException {
+        MediaExtractor ex = new MediaExtractor();
+        ex.setDataSource(path);
+        return getSampleSizes(ex);
+    }
+
+    private static int[] getSampleSizes(FileDescriptor fd, long offset, long size)
+            throws IOException {
+        MediaExtractor ex = new MediaExtractor();
+        ex.setDataSource(fd, offset, size);
+        return getSampleSizes(ex);
+    }
+
+    private static int[] getSampleSizes(MediaExtractor ex) {
+        ArrayList<Integer> foo = new ArrayList<Integer>();
+        ByteBuffer buf = ByteBuffer.allocate(1024*1024);
+        int numtracks = ex.getTrackCount();
+        assertTrue("no tracks", numtracks > 0);
+        foo.add(numtracks);
+        for (int i = 0; i < numtracks; i++) {
+            MediaFormat format = ex.getTrackFormat(i);
+            String mime = format.getString(MediaFormat.KEY_MIME);
+            if (mime.startsWith("audio/")) {
+                foo.add(0);
+                foo.add(format.getInteger(MediaFormat.KEY_SAMPLE_RATE));
+                foo.add(format.getInteger(MediaFormat.KEY_CHANNEL_COUNT));
+                foo.add((int)format.getLong(MediaFormat.KEY_DURATION));
+            } else if (mime.startsWith("video/")) {
+                foo.add(1);
+                foo.add(format.getInteger(MediaFormat.KEY_WIDTH));
+                foo.add(format.getInteger(MediaFormat.KEY_HEIGHT));
+                foo.add((int)format.getLong(MediaFormat.KEY_DURATION));
+            } else {
+                fail("unexpected mime type: " + mime);
+            }
+            ex.selectTrack(i);
+        }
+        while(true) {
+            int n = ex.readSampleData(buf, 0);
+            if (n < 0) {
+                break;
+            }
+            foo.add(n);
+            foo.add(ex.getSampleTrackIndex());
+            foo.add(ex.getSampleFlags());
+            foo.add((int)ex.getSampleTime()); // just the low bits should be OK
+            ex.advance();
+        }
+
+        int [] ret = new int[foo.size()];
+        for (int i = 0; i < ret.length; i++) {
+            ret[i] = foo.get(i);
+        }
+        return ret;
+    }
+
+    private static native int[] getSampleSizesNative(int fd, long offset, long size);
+    private static native int[] getSampleSizesNativePath(String path);
+
+
+    public void testDecoder() throws Exception {
+        testDecoder(R.raw.sinesweepogg);
+        testDecoder(R.raw.sinesweepmp3lame);
+        testDecoder(R.raw.sinesweepmp3smpb);
+        testDecoder(R.raw.sinesweepm4a);
+        testDecoder(R.raw.sinesweepflac);
+        testDecoder(R.raw.sinesweepwav);
+
+        testDecoder(R.raw.video_1280x720_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz);
+        testDecoder(R.raw.video_1280x720_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz);
+        testDecoder(R.raw.video_1280x720_webm_vp9_309kbps_25fps_vorbis_stereo_128kbps_44100hz);
+        testDecoder(R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_mono_24kbps_11025hz);
+        testDecoder(R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz);
+
+    }
+
+    private void testDecoder(int res) throws Exception {
+        AssetFileDescriptor fd = mResources.openRawResourceFd(res);
+
+        int[] jdata = getDecodedData(
+                fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
+        int[] ndata = getDecodedDataNative(
+                fd.getParcelFileDescriptor().getFd(), fd.getStartOffset(), fd.getLength());
+
+        fd.close();
+        Log.i("@@@", Arrays.toString(jdata));
+        Log.i("@@@", Arrays.toString(ndata));
+        assertEquals("number of samples differs", jdata.length, ndata.length);
+        assertTrue("different decoded data", Arrays.equals(jdata, ndata));
+    }
+
+    private static int[] getDecodedData(FileDescriptor fd, long offset, long size)
+            throws IOException {
+        MediaExtractor ex = new MediaExtractor();
+        ex.setDataSource(fd, offset, size);
+        return getDecodedData(ex);
+    }
+    private static int[] getDecodedData(MediaExtractor ex) throws IOException {
+        int numtracks = ex.getTrackCount();
+        assertTrue("no tracks", numtracks > 0);
+        ArrayList<Integer>[] trackdata = new ArrayList[numtracks];
+        MediaCodec[] codec = new MediaCodec[numtracks];
+        MediaFormat[] format = new MediaFormat[numtracks];
+        ByteBuffer[][] inbuffers = new ByteBuffer[numtracks][];
+        ByteBuffer[][] outbuffers = new ByteBuffer[numtracks][];
+        for (int i = 0; i < numtracks; i++) {
+            format[i] = ex.getTrackFormat(i);
+            String mime = format[i].getString(MediaFormat.KEY_MIME);
+            if (mime.startsWith("audio/") || mime.startsWith("video/")) {
+                codec[i] = MediaCodec.createDecoderByType(mime);
+                codec[i].configure(format[i], null, null, 0);
+                codec[i].start();
+                inbuffers[i] = codec[i].getInputBuffers();
+                outbuffers[i] = codec[i].getOutputBuffers();
+                trackdata[i] = new ArrayList<Integer>();
+            } else {
+                fail("unexpected mime type: " + mime);
+            }
+            ex.selectTrack(i);
+        }
+
+        boolean[] sawInputEOS = new boolean[numtracks];
+        boolean[] sawOutputEOS = new boolean[numtracks];
+        int eosCount = 0;
+        BufferInfo info = new BufferInfo();
+        while(eosCount < numtracks) {
+            int t = ex.getSampleTrackIndex();
+            if (t >= 0) {
+                assertFalse("saw input EOS twice", sawInputEOS[t]);
+                int bufidx = codec[t].dequeueInputBuffer(5000);
+                if (bufidx >= 0) {
+                    Log.i("@@@@", "track " + t + " buffer " + bufidx);
+                    ByteBuffer buf = inbuffers[t][bufidx];
+                    int sampleSize = ex.readSampleData(buf, 0);
+                    Log.i("@@@@", "read " + sampleSize);
+                    if (sampleSize < 0) {
+                        sampleSize = 0;
+                        sawInputEOS[t] = true;
+                        Log.i("@@@@", "EOS");
+                        //break;
+                    }
+                    long presentationTimeUs = ex.getSampleTime();
+
+                    codec[t].queueInputBuffer(bufidx, 0, sampleSize, presentationTimeUs,
+                            sawInputEOS[t] ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
+                    ex.advance();
+                }
+            } else {
+                Log.i("@@@@", "no more input samples");
+                for (int tt = 0; tt < codec.length; tt++) {
+                    if (!sawInputEOS[tt]) {
+                        // we ran out of samples without ever signaling EOS to the codec,
+                        // so do that now
+                        int bufidx = codec[tt].dequeueInputBuffer(5000);
+                        if (bufidx >= 0) {
+                            codec[tt].queueInputBuffer(bufidx, 0, 0, 0,
+                                    MediaCodec.BUFFER_FLAG_END_OF_STREAM);
+                            sawInputEOS[tt] = true;
+                        }
+                    }
+                }
+            }
+
+            // see if any of the codecs have data available
+            for (int tt = 0; tt < codec.length; tt++) {
+                if (!sawOutputEOS[tt]) {
+                    int status = codec[tt].dequeueOutputBuffer(info, 1);
+                    if (status >= 0) {
+                        if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+                            Log.i("@@@@", "EOS on track " + tt);
+                            sawOutputEOS[tt] = true;
+                            eosCount++;
+                        }
+                        Log.i("@@@@", "got decoded buffer for track " + tt + ", size " + info.size);
+                        if (info.size > 0) {
+                            addSampleData(trackdata[tt], outbuffers[tt][status], info.size, format[tt]);
+                        }
+                        codec[tt].releaseOutputBuffer(status, false);
+                    } else if (status == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
+                        Log.i("@@@@", "output buffers changed for track " + tt);
+                        outbuffers[tt] = codec[tt].getOutputBuffers();
+                    } else if (status == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+                        format[tt] = codec[tt].getOutputFormat();
+                        Log.i("@@@@", "format changed for track " + t + ": " + format[tt].toString());
+                    } else if (status == MediaCodec.INFO_TRY_AGAIN_LATER) {
+                        Log.i("@@@@", "no buffer right now for track " + tt);
+                    } else {
+                        Log.i("@@@@", "unexpected info code for track " + tt + ": " + status);
+                    }
+                } else {
+                    Log.i("@@@@", "already at EOS on track " + tt);
+                }
+            }
+        }
+
+        int totalsize = 0;
+        for (int i = 0; i < numtracks; i++) {
+            totalsize += trackdata[i].size();
+        }
+        int[] trackbytes = new int[totalsize];
+        int idx = 0;
+        for (int i = 0; i < numtracks; i++) {
+            ArrayList<Integer> src = trackdata[i];
+            int tracksize = src.size();
+            for (int j = 0; j < tracksize; j++) {
+                trackbytes[idx++] = src.get(j);
+            }
+        }
+
+        return trackbytes;
+    }
+
+    static void addSampleData(ArrayList<Integer> dst,
+            ByteBuffer buf, int size, MediaFormat format) throws IOException{
+
+        Log.i("@@@", "addsample " + dst.size() + "/" + size);
+        int width = format.getInteger(MediaFormat.KEY_WIDTH, size);
+        int stride = format.getInteger(MediaFormat.KEY_STRIDE, width);
+        int height = format.getInteger(MediaFormat.KEY_HEIGHT, 1);
+        byte[] bb = new byte[width * height];
+        for (int i = 0; i < height; i++) {
+            buf.position(i * stride);
+            buf.get(bb, i * width, width);
+        }
+        // bb is filled with data
+        long sum = adler32(bb);
+        dst.add( (int) (sum & 0xffffffff));
+    }
+
+    // simple checksum computed over every decoded buffer
+    static long adler32(byte[] input) {
+        int a = 1;
+        int b = 0;
+        for (int i = 0; i < input.length; i++) {
+            int unsignedval = input[i];
+            if (unsignedval < 0) {
+                unsignedval = 256 + unsignedval;
+            }
+            a += unsignedval;
+            b += a;
+        }
+        a = a % 65521;
+        b = b % 65521;
+        long ret = b * 65536 + a;
+        Log.i("@@@", "adler " + input.length + "/" + ret);
+        return ret;
+    }
+
+    private static native int[] getDecodedDataNative(int fd, long offset, long size)
+            throws IOException;
+
+    public void testVideoPlayback() throws Exception {
+        testVideoPlayback(R.raw.video_1280x720_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz);
+        testVideoPlayback(R.raw.video_1280x720_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz);
+        testVideoPlayback(R.raw.video_1280x720_webm_vp9_309kbps_25fps_vorbis_stereo_128kbps_44100hz);
+        testVideoPlayback(R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_mono_24kbps_11025hz);
+        testVideoPlayback(R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz);
+    }
+
+    private void testVideoPlayback(int res) throws Exception {
+        AssetFileDescriptor fd = mResources.openRawResourceFd(res);
+
+        boolean ret = testPlaybackNative(mActivity.getSurfaceHolder().getSurface(),
+                fd.getParcelFileDescriptor().getFd(), fd.getStartOffset(), fd.getLength());
+        assertTrue("native playback error", ret);
+    }
+
+    private static native boolean testPlaybackNative(Surface surface,
+            int fd, long startOffset, long length);
+
+    public void testMuxer() throws Exception {
+        testMuxer(R.raw.video_1280x720_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz, false);
+    }
+
+    private void testMuxer(int res, boolean webm) throws Exception {
+        AssetFileDescriptor infd = mResources.openRawResourceFd(res);
+
+        File base = mContext.getExternalFilesDir(null);
+        String tmpFile = base.getPath() + "/tmp.dat";
+        Log.i("@@@", "using tmp file " + tmpFile);
+        new File(tmpFile).delete();
+        ParcelFileDescriptor out = ParcelFileDescriptor.open(new File(tmpFile),
+                ParcelFileDescriptor.MODE_READ_WRITE | ParcelFileDescriptor.MODE_CREATE);
+
+        assertTrue("muxer failed", testMuxerNative(
+                infd.getParcelFileDescriptor().getFd(), infd.getStartOffset(), infd.getLength(),
+                out.getFd(), webm));
+
+        // compare the original with the remuxed
+        MediaExtractor org = new MediaExtractor();
+        org.setDataSource(infd.getFileDescriptor(),
+                infd.getStartOffset(), infd.getLength());
+
+        MediaExtractor remux = new MediaExtractor();
+        remux.setDataSource(out.getFileDescriptor());
+
+        assertEquals("mismatched numer of tracks", org.getTrackCount(), remux.getTrackCount());
+        for (int i = 0; i < 2; i++) {
+            MediaFormat format1 = org.getTrackFormat(i);
+            MediaFormat format2 = remux.getTrackFormat(i);
+            Log.i("@@@", "org: " + format1);
+            Log.i("@@@", "remux: " + format2);
+            assertTrue("different formats", compareFormats(format1, format2));
+        }
+
+        org.release();
+        remux.release();
+
+        MediaPlayer player1 = MediaPlayer.create(mContext, res);
+        MediaPlayer player2 = MediaPlayer.create(mContext, Uri.parse("file://" + tmpFile));
+        assertEquals("duration is different", player1.getDuration(), player2.getDuration());
+        player1.release();
+        player2.release();
+        new File(tmpFile).delete();
+    }
+
+    boolean compareFormats(MediaFormat f1, MediaFormat f2) {
+        // there's no good way to compare two MediaFormats, so compare their string
+        // representation
+        return f1.toString().equals(f2.toString());
+    }
+
+    private static native boolean testMuxerNative(int in, long inoffset, long insize,
+            int out, boolean webm);
+
+    public void testFormat() throws Exception {
+        assertTrue("media format fail, see log for details", testFormatNative());
+    }
+
+    private static native boolean testFormatNative();
+
+    public void testPssh() throws Exception {
+        testPssh(R.raw.psshtest);
+    }
+
+    private void testPssh(int res) throws Exception {
+        AssetFileDescriptor fd = mResources.openRawResourceFd(res);
+
+        MediaExtractor ex = new MediaExtractor();
+        ex.setDataSource(fd.getParcelFileDescriptor().getFileDescriptor(),
+                fd.getStartOffset(), fd.getLength());
+        testPssh(ex);
+        ex.release();
+
+        boolean ret = testPsshNative(
+                fd.getParcelFileDescriptor().getFd(), fd.getStartOffset(), fd.getLength());
+        assertTrue("native pssh error", ret);
+    }
+
+    private static void testPssh(MediaExtractor ex) {
+        Map<UUID, byte[]> map = ex.getPsshInfo();
+        Set<UUID> keys = map.keySet();
+        for (UUID uuid: keys) {
+            Log.i("@@@", "uuid: " + uuid + ", data size " +
+                    map.get(uuid).length);
+        }
+    }
+
+    private static native boolean testPsshNative(int fd, long offset, long size);
+
+    public void testCryptoInfo() throws Exception {
+        assertTrue("native cryptoinfo failed, see log for details", testCryptoInfoNative());
+    }
+
+    private static native boolean testCryptoInfoNative();
+}
+
diff --git a/tests/tests/media/src/android/media/cts/NonBlockingAudioTrack.java b/tests/tests/media/src/android/media/cts/NonBlockingAudioTrack.java
new file mode 100644
index 0000000..3ba1ce8
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/NonBlockingAudioTrack.java
@@ -0,0 +1,202 @@
+/*
+ * 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.media.cts;
+
+import android.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.AudioTrack;
+import android.util.Log;
+
+import java.util.LinkedList;
+
+/**
+ * Class for playing audio by using audio track.
+ * {@link #write(byte[], int, int)} and {@link #write(short[], int, int)} methods will
+ * block until all data has been written to system. In order to avoid blocking, this class
+ * caculates available buffer size first then writes to audio sink.
+ */
+public class NonBlockingAudioTrack {
+    private static final String TAG = NonBlockingAudioTrack.class.getSimpleName();
+
+    class QueueElem {
+        byte[] data;
+        int offset;
+        int size;
+    }
+
+    private AudioTrack mAudioTrack;
+    private boolean mWriteMorePending = false;
+    private int mSampleRate;
+    private int mFrameSize;
+    private int mBufferSizeInFrames;
+    private int mNumFramesSubmitted = 0;
+    private int mNumBytesQueued = 0;
+    private LinkedList<QueueElem> mQueue = new LinkedList<QueueElem>();
+
+    public NonBlockingAudioTrack(int sampleRate, int channelCount) {
+        int channelConfig;
+        switch (channelCount) {
+            case 1:
+                channelConfig = AudioFormat.CHANNEL_OUT_MONO;
+                break;
+            case 2:
+                channelConfig = AudioFormat.CHANNEL_OUT_STEREO;
+                break;
+            case 6:
+                channelConfig = AudioFormat.CHANNEL_OUT_5POINT1;
+                break;
+            default:
+                throw new IllegalArgumentException();
+        }
+
+        int minBufferSize =
+            AudioTrack.getMinBufferSize(
+                    sampleRate,
+                    channelConfig,
+                    AudioFormat.ENCODING_PCM_16BIT);
+
+        int bufferSize = 2 * minBufferSize;
+
+        mAudioTrack = new AudioTrack(
+                AudioManager.STREAM_MUSIC,
+                sampleRate,
+                channelConfig,
+                AudioFormat.ENCODING_PCM_16BIT,
+                bufferSize,
+                AudioTrack.MODE_STREAM);
+
+        mSampleRate = sampleRate;
+        mFrameSize = 2 * channelCount;
+        mBufferSizeInFrames = bufferSize / mFrameSize;
+    }
+
+    public long getAudioTimeUs() {
+        int numFramesPlayed = mAudioTrack.getPlaybackHeadPosition();
+
+        return (numFramesPlayed * 1000000L) / mSampleRate;
+    }
+
+    public int getNumBytesQueued() {
+        return mNumBytesQueued;
+    }
+
+    public void play() {
+        mAudioTrack.play();
+    }
+
+    public void stop() {
+        cancelWriteMore();
+
+        mAudioTrack.stop();
+
+        mNumFramesSubmitted = 0;
+        mQueue.clear();
+        mNumBytesQueued = 0;
+    }
+
+    public void pause() {
+        cancelWriteMore();
+
+        mAudioTrack.pause();
+    }
+
+    public void release() {
+        cancelWriteMore();
+
+        mAudioTrack.release();
+        mAudioTrack = null;
+    }
+
+    public void process() {
+        mWriteMorePending = false;
+        writeMore();
+    }
+
+    public int getPlayState() {
+        return mAudioTrack.getPlayState();
+    }
+
+    private void writeMore() {
+        if (mQueue.isEmpty()) {
+            return;
+        }
+
+        int numFramesPlayed = mAudioTrack.getPlaybackHeadPosition();
+        int numFramesPending = mNumFramesSubmitted - numFramesPlayed;
+        int numFramesAvailableToWrite = mBufferSizeInFrames - numFramesPending;
+        int numBytesAvailableToWrite = numFramesAvailableToWrite * mFrameSize;
+
+        while (numBytesAvailableToWrite > 0) {
+            QueueElem elem = mQueue.peekFirst();
+
+            int numBytes = elem.size;
+            if (numBytes > numBytesAvailableToWrite) {
+                numBytes = numBytesAvailableToWrite;
+            }
+
+            int written = mAudioTrack.write(elem.data, elem.offset, numBytes);
+            assert(written == numBytes);
+
+            mNumFramesSubmitted += written / mFrameSize;
+
+            elem.size -= numBytes;
+            numBytesAvailableToWrite -= numBytes;
+            mNumBytesQueued -= numBytes;
+
+            if (elem.size == 0) {
+                mQueue.removeFirst();
+
+                if (mQueue.isEmpty()) {
+                    break;
+                }
+            } else {
+                elem.offset += numBytes;
+            }
+        }
+
+        if (!mQueue.isEmpty()) {
+            scheduleWriteMore();
+        }
+    }
+
+    private void scheduleWriteMore() {
+        if (mWriteMorePending) {
+            return;
+        }
+
+        int numFramesPlayed = mAudioTrack.getPlaybackHeadPosition();
+        int numFramesPending = mNumFramesSubmitted - numFramesPlayed;
+        int pendingDurationMs = 1000 * numFramesPending / mSampleRate;
+
+        mWriteMorePending = true;
+    }
+
+    private void cancelWriteMore() {
+        mWriteMorePending = false;
+    }
+
+    public void write(byte[] data, int size) {
+        QueueElem elem = new QueueElem();
+        elem.data = data;
+        elem.offset = 0;
+        elem.size = size;
+
+        // accumulate size written to queue
+        mNumBytesQueued += size;
+        mQueue.add(elem);
+    }
+}
+
diff --git a/tests/tests/media/src/android/media/cts/PostProcTestBase.java b/tests/tests/media/src/android/media/cts/PostProcTestBase.java
new file mode 100644
index 0000000..b034763
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/PostProcTestBase.java
@@ -0,0 +1,65 @@
+/*
+ * 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.media.cts;
+
+import android.content.pm.PackageManager;
+import android.media.audiofx.AudioEffect;
+import android.os.Looper;
+import android.test.AndroidTestCase;
+
+public class PostProcTestBase extends AndroidTestCase {
+    protected int mSession = -1;
+    protected boolean mHasControl = false;
+    protected boolean mIsEnabled = false;
+    protected boolean mInitialized = false;
+    protected Looper mLooper = null;
+    protected final Object mLock = new Object();
+    protected int mChangedParameter = -1;
+
+    protected boolean hasAudioOutput() {
+        return getContext().getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_AUDIO_OUTPUT);
+    }
+
+    protected boolean isBassBoostAvailable() {
+        if (!hasAudioOutput()) {
+            return false;
+        }
+        return AudioEffect.isEffectTypeAvailable(AudioEffect.EFFECT_TYPE_BASS_BOOST);
+    }
+
+    protected boolean isVirtualizerAvailable() {
+        if (!hasAudioOutput()) {
+            return false;
+        }
+        return AudioEffect.isEffectTypeAvailable(AudioEffect.EFFECT_TYPE_VIRTUALIZER);
+    }
+
+    protected boolean isPresetReverbAvailable() {
+        if (!hasAudioOutput()) {
+            return false;
+        }
+        return AudioEffect.isEffectTypeAvailable(AudioEffect.EFFECT_TYPE_PRESET_REVERB);
+    }
+
+    protected boolean isEnvReverbAvailable() {
+        if (!hasAudioOutput()) {
+            return false;
+        }
+        return AudioEffect.isEffectTypeAvailable(AudioEffect.EFFECT_TYPE_ENV_REVERB);
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/PresetReverbTest.java b/tests/tests/media/src/android/media/cts/PresetReverbTest.java
index d69256c..ba6d08c 100644
--- a/tests/tests/media/src/android/media/cts/PresetReverbTest.java
+++ b/tests/tests/media/src/android/media/cts/PresetReverbTest.java
@@ -24,7 +24,7 @@
 import android.test.AndroidTestCase;
 import android.util.Log;
 
-public class PresetReverbTest extends AndroidTestCase {
+public class PresetReverbTest extends PostProcTestBase {
 
     private String TAG = "PresetReverbTest";
     private final static short FIRST_PRESET = PresetReverb.PRESET_NONE;
@@ -33,13 +33,6 @@
 
     private PresetReverb mReverb = null;
     private PresetReverb mReverb2 = null;
-    private int mSession = -1;
-    private boolean mHasControl = false;
-    private boolean mIsEnabled = false;
-    private int mChangedParameter = -1;
-    private boolean mInitialized = false;
-    private Looper mLooper = null;
-    private final Object mLock = new Object();
     private ListenerThread mEffectListenerLooper = null;
 
     //-----------------------------------------------------------------
@@ -52,10 +45,12 @@
 
     //Test case 0.0: test constructor and release
     public void test0_0ConstructorAndRelease() throws Exception {
+        if (!isPresetReverbAvailable()) {
+            return;
+        }
         PresetReverb reverb = null;
         try {
             reverb = new PresetReverb(0, 0);
-            assertNotNull("could not create PresetReverb", reverb);
             try {
                 assertTrue("invalid effect ID", (reverb.getId() != 0));
             } catch (IllegalStateException e) {
@@ -78,6 +73,9 @@
 
     //Test case 1.0: test presets
     public void test1_0Presets() throws Exception {
+        if (!isPresetReverbAvailable()) {
+            return;
+        }
         getReverb(0);
         try {
             for (short preset = FIRST_PRESET;
@@ -99,6 +97,9 @@
 
     //Test case 1.1: test properties
     public void test1_1Properties() throws Exception {
+        if (!isPresetReverbAvailable()) {
+            return;
+        }
         getReverb(0);
         try {
             PresetReverb.Settings settings = mReverb.getProperties();
@@ -127,6 +128,9 @@
 
     //Test case 2.0: test setEnabled() and getEnabled() in valid state
     public void test2_0SetEnabledGetEnabled() throws Exception {
+        if (!isPresetReverbAvailable()) {
+            return;
+        }
         getReverb(0);
         try {
             mReverb.setEnabled(true);
@@ -142,6 +146,9 @@
 
     //Test case 2.1: test setEnabled() throws exception after release
     public void test2_1SetEnabledAfterRelease() throws Exception {
+        if (!isPresetReverbAvailable()) {
+            return;
+        }
         getReverb(0);
         mReverb.release();
         try {
@@ -159,6 +166,9 @@
 
     //Test case 3.0: test control status listener
     public void test3_0ControlStatusListener() throws Exception {
+        if (!isPresetReverbAvailable()) {
+            return;
+        }
          synchronized(mLock) {
             mHasControl = true;
             mInitialized = false;
@@ -181,6 +191,9 @@
 
     //Test case 3.1: test enable status listener
     public void test3_1EnableStatusListener() throws Exception {
+        if (!isPresetReverbAvailable()) {
+            return;
+        }
          synchronized(mLock) {
             mInitialized = false;
             createListenerLooper(false, true, false);
@@ -205,6 +218,9 @@
 
     //Test case 3.2: test parameter changed listener
     public void test3_2ParameterChangedListener() throws Exception {
+        if (!isPresetReverbAvailable()) {
+            return;
+        }
         synchronized(mLock) {
             mInitialized = false;
             createListenerLooper(false, false, true);
@@ -377,5 +393,4 @@
             mReverb2 = null;
         }
     }
-
 }
\ No newline at end of file
diff --git a/tests/tests/media/src/android/media/cts/RemoteVirtualDisplayService.java b/tests/tests/media/src/android/media/cts/RemoteVirtualDisplayService.java
index 662cd5b..eac2c89 100644
--- a/tests/tests/media/src/android/media/cts/RemoteVirtualDisplayService.java
+++ b/tests/tests/media/src/android/media/cts/RemoteVirtualDisplayService.java
@@ -39,7 +39,7 @@
 
 public class RemoteVirtualDisplayService extends Service {
     private static final String TAG = "RemoteVirtualDisplayService";
-
+    private static final boolean DBG = false;
     /** argument: Surface, int w, int h, return none */
     private static final int BINDER_CMD_START = IBinder.FIRST_CALL_TRANSACTION;
     /** argument: int color, return none */
@@ -101,7 +101,9 @@
     }
 
     private void render(int color) {
-        Log.i(TAG, "render");
+        if (DBG) {
+            Log.i(TAG, "render " + Integer.toHexString(color));
+        }
         mPresentation.doRendering(color);
     }
 
@@ -168,7 +170,9 @@
             private ImageView mImageView;
 
             public TestPresentation(Context outerContext, Display display) {
-                super(outerContext, display);
+                // This theme is required to prevent an extra view from obscuring the presentation
+                super(outerContext, display,
+                        android.R.style.Theme_Holo_Light_NoActionBar_TranslucentDecor);
                 getWindow().setType(WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION);
                 getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
             }
diff --git a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
index 4608b24..419f3e0 100644
--- a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
@@ -16,9 +16,13 @@
 package android.media.cts;
 
 import android.media.MediaPlayer;
+import android.os.Looper;
+import android.os.SystemClock;
 import android.util.Log;
 import android.webkit.cts.CtsTestServer;
 
+import java.io.IOException;
+
 
 /**
  * Tests of MediaPlayer streaming capabilities.
@@ -199,7 +203,6 @@
             mServer.shutdown();
         }
     }
-
     private void localHttpsAudioStreamTest(final String name, boolean redirect, boolean nolength)
             throws Throwable {
         mServer = new CtsTestServer(mContext, true);
@@ -260,6 +263,93 @@
         localHlsTest("hls.m3u8", false, true);
     }
 
+    private static class WorkerWithPlayer implements Runnable {
+        private final Object mLock = new Object();
+        private Looper mLooper;
+        private MediaPlayer mMediaPlayer;
+
+        /**
+         * Creates a worker thread with the given name. The thread
+         * then runs a {@link android.os.Looper}.
+         * @param name A name for the new thread
+         */
+        WorkerWithPlayer(String name) {
+            Thread t = new Thread(null, this, name);
+            t.setPriority(Thread.MIN_PRIORITY);
+            t.start();
+            synchronized (mLock) {
+                while (mLooper == null) {
+                    try {
+                        mLock.wait();
+                    } catch (InterruptedException ex) {
+                    }
+                }
+            }
+        }
+
+        public MediaPlayer getPlayer() {
+            return mMediaPlayer;
+        }
+
+        @Override
+        public void run() {
+            synchronized (mLock) {
+                Looper.prepare();
+                mLooper = Looper.myLooper();
+                mMediaPlayer = new MediaPlayer();
+                mLock.notifyAll();
+            }
+            Looper.loop();
+        }
+
+        public void quit() {
+            mLooper.quit();
+            mMediaPlayer.release();
+        }
+    }
+
+    public void testBlockingReadRelease() throws Throwable {
+
+        mServer = new CtsTestServer(mContext);
+
+        WorkerWithPlayer worker = new WorkerWithPlayer("player");
+        final MediaPlayer mp = worker.getPlayer();
+
+        try {
+            String path = mServer.getDelayedAssetUrl("noiseandchirps.ogg", 15000);
+            mp.setDataSource(path);
+            mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
+                @Override
+                public void onPrepared(MediaPlayer mp) {
+                    fail("prepare should not succeed");
+                }
+            });
+            mp.prepareAsync();
+            Thread.sleep(1000);
+            long start = SystemClock.elapsedRealtime();
+            mp.release();
+            long end = SystemClock.elapsedRealtime();
+            long releaseDuration = (end - start);
+            assertTrue("release took too long: " + releaseDuration, releaseDuration < 1000);
+        } catch (IllegalArgumentException e) {
+            fail(e.getMessage());
+        } catch (SecurityException e) {
+            fail(e.getMessage());
+        } catch (IllegalStateException e) {
+            fail(e.getMessage());
+        } catch (IOException e) {
+            fail(e.getMessage());
+        } catch (InterruptedException e) {
+            fail(e.getMessage());
+        } finally {
+            mServer.shutdown();
+        }
+
+        // give the worker a bit of time to start processing the message before shutting it down
+        Thread.sleep(5000);
+        worker.quit();
+    }
+
     private void localHlsTest(final String name, boolean appendQueryString, boolean redirect)
             throws Throwable {
         mServer = new CtsTestServer(mContext);
diff --git a/tests/tests/media/src/android/media/cts/VirtualizerTest.java b/tests/tests/media/src/android/media/cts/VirtualizerTest.java
index 3d18c47..51adf1d 100644
--- a/tests/tests/media/src/android/media/cts/VirtualizerTest.java
+++ b/tests/tests/media/src/android/media/cts/VirtualizerTest.java
@@ -24,7 +24,7 @@
 import android.test.AndroidTestCase;
 import android.util.Log;
 
-public class VirtualizerTest extends AndroidTestCase {
+public class VirtualizerTest extends PostProcTestBase {
 
     private String TAG = "VirtualizerTest";
     private final static short TEST_STRENGTH = 500;
@@ -34,13 +34,6 @@
 
     private Virtualizer mVirtualizer = null;
     private Virtualizer mVirtualizer2 = null;
-    private int mSession = -1;
-    private boolean mHasControl = false;
-    private boolean mIsEnabled = false;
-    private int mChangedParameter = -1;
-    private boolean mInitialized = false;
-    private Looper mLooper = null;
-    private final Object mLock = new Object();
     private ListenerThread mEffectListenerLooper = null;
 
     //-----------------------------------------------------------------
@@ -53,10 +46,13 @@
 
     //Test case 0.0: test constructor and release
     public void test0_0ConstructorAndRelease() throws Exception {
+        if (!isVirtualizerAvailable()) {
+            return;
+        }
+
         Virtualizer eq = null;
         try {
             eq = new Virtualizer(0, 0);
-            assertNotNull(" could not create Virtualizer", eq);
             try {
                 assertTrue(" invalid effect ID", (eq.getId() != 0));
             } catch (IllegalStateException e) {
@@ -80,6 +76,10 @@
 
     //Test case 1.0: test strength
     public void test1_0Strength() throws Exception {
+        if (!isVirtualizerAvailable()) {
+            return;
+        }
+
         getVirtualizer(0);
         try {
             if (mVirtualizer.getStrengthSupported()) {
@@ -108,6 +108,10 @@
 
     //Test case 1.1: test properties
     public void test1_1Properties() throws Exception {
+        if (!isVirtualizerAvailable()) {
+            return;
+        }
+
         getVirtualizer(0);
         try {
             Virtualizer.Settings settings = mVirtualizer.getProperties();
@@ -141,6 +145,10 @@
 
     //Test case 1.2: test setStrength() throws exception after release
     public void test1_2SetStrengthAfterRelease() throws Exception {
+        if (!isVirtualizerAvailable()) {
+            return;
+        }
+
         getVirtualizer(0);
         mVirtualizer.release();
         try {
@@ -158,6 +166,10 @@
 
     //Test case 2.0: test setEnabled() and getEnabled() in valid state
     public void test2_0SetEnabledGetEnabled() throws Exception {
+        if (!isVirtualizerAvailable()) {
+            return;
+        }
+
         getVirtualizer(0);
         try {
             mVirtualizer.setEnabled(true);
@@ -173,6 +185,10 @@
 
     //Test case 2.1: test setEnabled() throws exception after release
     public void test2_1SetEnabledAfterRelease() throws Exception {
+        if (!isVirtualizerAvailable()) {
+            return;
+        }
+
         getVirtualizer(0);
         mVirtualizer.release();
         try {
@@ -190,6 +206,10 @@
 
     //Test case 3.0: test control status listener
     public void test3_0ControlStatusListener() throws Exception {
+        if (!isVirtualizerAvailable()) {
+            return;
+        }
+
         synchronized(mLock) {
             mHasControl = true;
             mInitialized = false;
@@ -212,6 +232,10 @@
 
     //Test case 3.1: test enable status listener
     public void test3_1EnableStatusListener() throws Exception {
+        if (!isVirtualizerAvailable()) {
+            return;
+        }
+
         synchronized(mLock) {
             mInitialized = false;
             createListenerLooper(false, true, false);
@@ -236,6 +260,10 @@
 
     //Test case 3.2: test parameter changed listener
     public void test3_2ParameterChangedListener() throws Exception {
+        if (!isVirtualizerAvailable()) {
+            return;
+        }
+
         synchronized(mLock) {
             mInitialized = false;
             createListenerLooper(false, false, true);
diff --git a/tests/tests/media/src/android/media/cts/VisualizerTest.java b/tests/tests/media/src/android/media/cts/VisualizerTest.java
index e2a9fdd..8c91e9b 100644
--- a/tests/tests/media/src/android/media/cts/VisualizerTest.java
+++ b/tests/tests/media/src/android/media/cts/VisualizerTest.java
@@ -24,7 +24,7 @@
 import android.test.AndroidTestCase;
 import android.util.Log;
 
-public class VisualizerTest extends AndroidTestCase {
+public class VisualizerTest extends PostProcTestBase {
 
     private String TAG = "VisualizerTest";
     private final static int MIN_CAPTURE_RATE_MAX = 10000; // 10Hz
@@ -33,10 +33,6 @@
     private final static int MAX_LOOPER_WAIT_COUNT = 10;
 
     private Visualizer mVisualizer = null;
-    private int mSession = -1;
-    private boolean mInitialized = false;
-    private Looper mLooper = null;
-    private final Object mLock = new Object();
     private byte[] mWaveform = null;
     private byte[] mFft = null;
     private boolean mCaptureWaveform = false;
@@ -53,10 +49,12 @@
 
     //Test case 0.0: test constructor and release
     public void test0_0ConstructorAndRelease() throws Exception {
+        if (!hasAudioOutput()) {
+            return;
+        }
         Visualizer visualizer = null;
-         try {
+        try {
             visualizer = new Visualizer(0);
-            assertNotNull("could not create Visualizer", visualizer);
         } catch (IllegalArgumentException e) {
             fail("Visualizer not found");
         } catch (UnsupportedOperationException e) {
@@ -75,6 +73,9 @@
 
     //Test case 1.0: capture rates
     public void test1_0CaptureRates() throws Exception {
+        if (!hasAudioOutput()) {
+            return;
+        }
         getVisualizer(0);
         try {
             int captureRate = mVisualizer.getMaxCaptureRate();
@@ -94,6 +95,9 @@
 
     //Test case 1.1: test capture size
     public void test1_1CaptureSize() throws Exception {
+        if (!hasAudioOutput()) {
+            return;
+        }
         getVisualizer(0);
         try {
             int[] range = mVisualizer.getCaptureSizeRange();
@@ -124,6 +128,9 @@
 
     //Test case 2.0: test cature in polling mode
     public void test2_0PollingCapture() throws Exception {
+        if (!hasAudioOutput()) {
+            return;
+        }
         try {
             getVisualizer(0);
             mVisualizer.setEnabled(true);
@@ -151,6 +158,9 @@
 
     //Test case 2.1: test capture with listener
     public void test2_1ListenerCapture() throws Exception {
+        if (!hasAudioOutput()) {
+            return;
+        }
         try {
             getVisualizer(0);
             synchronized(mLock) {
diff --git a/tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java b/tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java
new file mode 100644
index 0000000..586b9ef
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java
@@ -0,0 +1,1993 @@
+/*
+ * Copyright (C) 2013 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.media.cts;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.media.MediaCodec;
+import android.media.MediaCodec.CodecException;
+import android.media.MediaCodecInfo.CodecCapabilities;
+import android.media.MediaCodecList;
+import android.media.MediaCodecInfo;
+import android.media.MediaFormat;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.Looper;
+import android.os.Handler;
+import android.test.AndroidTestCase;
+import android.util.Log;
+import com.android.cts.media.R;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.util.Locale;
+import java.util.ArrayList;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * Verification test for vp8 encoder and decoder.
+ *
+ * A raw yv12 stream is encoded at various settings and written to an IVF
+ * file. Encoded stream bitrate and key frame interval are checked against target values.
+ * The stream is later decoded by vp8 decoder to verify frames are decodable and to
+ * calculate PSNR values for various bitrates.
+ */
+public class Vp8CodecTestBase extends AndroidTestCase {
+
+    protected static final String TAG = "VP8CodecTestBase";
+    protected static final String VP8_MIME = "video/x-vnd.on2.vp8";
+    private static final String VPX_SW_DECODER_NAME = "OMX.google.vp8.decoder";
+    private static final String VPX_SW_ENCODER_NAME = "OMX.google.vp8.encoder";
+    private static final String OMX_SW_CODEC_PREFIX = "OMX.google";
+    protected static final String SDCARD_DIR =
+            Environment.getExternalStorageDirectory().getAbsolutePath();
+
+    // Default timeout for MediaCodec buffer dequeue - 200 ms.
+    protected static final long DEFAULT_DEQUEUE_TIMEOUT_US = 200000;
+    // Default timeout for MediaEncoderAsync - 30 sec.
+    protected static final long DEFAULT_ENCODE_TIMEOUT_MS = 30000;
+    // Default sync frame interval in frames (zero means allow the encoder to auto-select
+    // key frame interval).
+    private static final int SYNC_FRAME_INTERVAL = 0;
+    // Video bitrate type - should be set to OMX_Video_ControlRateConstant from OMX_Video.h
+    protected static final int VIDEO_ControlRateVariable = 1;
+    protected static final int VIDEO_ControlRateConstant = 2;
+    // NV12 color format supported by QCOM codec, but not declared in MediaCodec -
+    // see /hardware/qcom/media/mm-core/inc/OMX_QCOMExtns.h
+    private static final int COLOR_QCOM_FORMATYUV420PackedSemiPlanar32m = 0x7FA30C04;
+    // Allowable color formats supported by codec - in order of preference.
+    private static final int[] mSupportedColorList = {
+            CodecCapabilities.COLOR_FormatYUV420Planar,
+            CodecCapabilities.COLOR_FormatYUV420SemiPlanar,
+            CodecCapabilities.COLOR_QCOM_FormatYUV420SemiPlanar,
+            COLOR_QCOM_FORMATYUV420PackedSemiPlanar32m
+    };
+    // Scaled image cache list - contains scale factors, for which up-scaled frames
+    // were calculated and were written to yuv file.
+    ArrayList<Integer> mScaledImages = new ArrayList<Integer>();
+
+    private Resources mResources;
+
+    @Override
+    public void setContext(Context context) {
+        super.setContext(context);
+        mResources = mContext.getResources();
+    }
+
+    /**
+     * Returns the first codec capable of encoding the specified MIME type, or null if no
+     * match was found.
+     */
+    protected static MediaCodecInfo selectCodec(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 codecInfo;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     *  VP8 codec properties generated by getVp8CodecProperties() function.
+     */
+    private class CodecProperties {
+        CodecProperties(String codecName, int colorFormat) {
+            this.codecName = codecName;
+            this.colorFormat = colorFormat;
+        }
+        public boolean  isGoogleSwCodec() {
+            return codecName.startsWith(OMX_SW_CODEC_PREFIX);
+        }
+
+        public final String codecName; // OpenMax component name for VP8 codec.
+        public final int colorFormat;  // Color format supported by codec.
+    }
+
+    /**
+     * Function to find VP8 codec.
+     *
+     * Iterates through the list of available codecs and tries to find
+     * VP8 codec, which can support either YUV420 planar or NV12 color formats.
+     * If forceSwGoogleCodec parameter set to true the function always returns
+     * Google sw VP8 codec.
+     * If forceSwGoogleCodec parameter set to false the functions looks for platform
+     * specific VP8 codec first. If no platform specific codec exist, falls back to
+     * Google sw VP8 codec.
+     *
+     * @param isEncoder     Flag if encoder is requested.
+     * @param forceSwGoogleCodec  Forces to use Google sw codec.
+     */
+    private CodecProperties getVp8CodecProperties(boolean isEncoder,
+            boolean forceSwGoogleCodec) throws Exception {
+        CodecProperties codecProperties = null;
+
+        if (!forceSwGoogleCodec) {
+            // Loop through the list of omx components in case platform specific codec
+            // is requested.
+            for (int i = 0; i < MediaCodecList.getCodecCount(); i++) {
+                MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
+                if (isEncoder != codecInfo.isEncoder()) {
+                    continue;
+                }
+                Log.v(TAG, codecInfo.getName());
+                // Check if this is sw Google codec - we should ignore it.
+                boolean isGoogleSwCodec = codecInfo.getName().startsWith(OMX_SW_CODEC_PREFIX);
+                if (isGoogleSwCodec) {
+                    continue;
+                }
+
+                for (String type : codecInfo.getSupportedTypes()) {
+                    if (!type.equalsIgnoreCase(VP8_MIME)) {
+                        continue;
+                    }
+                    CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(VP8_MIME);
+
+                    // Get candidate codec properties.
+                    Log.v(TAG, "Found candidate codec " + codecInfo.getName());
+                    for (int colorFormat : capabilities.colorFormats) {
+                        Log.v(TAG, "   Color: 0x" + Integer.toHexString(colorFormat));
+                    }
+
+                    // Check supported color formats.
+                    for (int supportedColorFormat : mSupportedColorList) {
+                        for (int codecColorFormat : capabilities.colorFormats) {
+                            if (codecColorFormat == supportedColorFormat) {
+                                codecProperties = new CodecProperties(codecInfo.getName(),
+                                        codecColorFormat);
+                                Log.v(TAG, "Found target codec " + codecProperties.codecName +
+                                        ". Color: 0x" + Integer.toHexString(codecColorFormat));
+                                return codecProperties;
+                            }
+                        }
+                    }
+                    // HW codec we found does not support one of necessary color formats.
+                    throw new RuntimeException("No hw codec with YUV420 or NV12 color formats");
+                }
+            }
+        }
+        // If no hw vp8 codec exist or sw codec is requested use default Google sw codec.
+        if (codecProperties == null) {
+            Log.v(TAG, "Use SW VP8 codec");
+            if (isEncoder) {
+                codecProperties = new CodecProperties(VPX_SW_ENCODER_NAME,
+                        CodecCapabilities.COLOR_FormatYUV420Planar);
+            } else {
+                codecProperties = new CodecProperties(VPX_SW_DECODER_NAME,
+                        CodecCapabilities.COLOR_FormatYUV420Planar);
+            }
+        }
+
+        return codecProperties;
+    }
+
+    /**
+     * Parameters for encoded video stream.
+     */
+    protected class EncoderOutputStreamParameters {
+        // Name of raw YUV420 input file. When the value of this parameter
+        // is set to null input file descriptor from inputResourceId parameter
+        // is used instead.
+        public String inputYuvFilename;
+        // Name of scaled YUV420 input file.
+        public String scaledYuvFilename;
+        // File descriptor for the raw input file (YUV420). Used only if
+        // inputYuvFilename parameter is null.
+        int inputResourceId;
+        // Name of the IVF file to write encoded bitsream
+        public String outputIvfFilename;
+        // Force to use Google SW VP8 encoder.
+        boolean forceSwEncoder;
+        // Number of frames to encode.
+        int frameCount;
+        // Frame rate of input file in frames per second.
+        int frameRate;
+        // Encoded frame width.
+        public int frameWidth;
+        // Encoded frame height.
+        public int frameHeight;
+        // Encoding bitrate array in bits/second for every frame. If array length
+        // is shorter than the total number of frames, the last value is re-used for
+        // all remaining frames. For constant bitrate encoding single element
+        // array can be used with first element set to target bitrate value.
+        public int[] bitrateSet;
+        // Encoding bitrate type - VBR or CBR
+        public int bitrateType;
+        // Number of temporal layers
+        public int temporalLayers;
+        // Desired key frame interval - codec is asked to generate key frames
+        // at a period defined by this parameter.
+        public int syncFrameInterval;
+        // Optional parameter - forced key frame interval. Used to
+        // explicitly request the codec to generate key frames using
+        // MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME parameter.
+        public int syncForceFrameInterval;
+        // Buffer timeout
+        long timeoutDequeue;
+        // Flag if encoder should run in Looper thread.
+        boolean runInLooperThread;
+    }
+
+    /**
+     * Generates an array of default parameters for encoder output stream based on
+     * upscaling value.
+     */
+    protected ArrayList<EncoderOutputStreamParameters> getDefaultEncodingParameterList(
+            String inputYuvName,
+            String outputIvfBaseName,
+            int encodeSeconds,
+            int[] resolutionScales,
+            int frameWidth,
+            int frameHeight,
+            int frameRate,
+            int bitrateMode,
+            int[] bitrates,
+            boolean syncEncoding) {
+        assertTrue(resolutionScales.length == bitrates.length);
+        int numCodecs = resolutionScales.length;
+        ArrayList<EncoderOutputStreamParameters> outputParameters =
+                new ArrayList<EncoderOutputStreamParameters>(numCodecs);
+        for (int i = 0; i < numCodecs; i++) {
+            EncoderOutputStreamParameters params = new EncoderOutputStreamParameters();
+            if (inputYuvName != null) {
+                params.inputYuvFilename = SDCARD_DIR + File.separator + inputYuvName;
+            } else {
+                params.inputYuvFilename = null;
+            }
+            params.scaledYuvFilename = SDCARD_DIR + File.separator +
+                    outputIvfBaseName + resolutionScales[i]+ ".yuv";
+            params.inputResourceId = R.raw.football_qvga;
+            params.outputIvfFilename = SDCARD_DIR + File.separator +
+                    outputIvfBaseName + resolutionScales[i] + ".ivf";
+            params.forceSwEncoder = false;
+            params.frameCount = encodeSeconds * frameRate;
+            params.frameRate = frameRate;
+            params.frameWidth = Math.min(frameWidth * resolutionScales[i], 1280);
+            params.frameHeight = Math.min(frameHeight * resolutionScales[i], 720);
+            params.bitrateSet = new int[1];
+            params.bitrateSet[0] = bitrates[i];
+            params.bitrateType = bitrateMode;
+            params.temporalLayers = 0;
+            params.syncFrameInterval = SYNC_FRAME_INTERVAL;
+            params.syncForceFrameInterval = 0;
+            if (syncEncoding) {
+                params.timeoutDequeue = DEFAULT_DEQUEUE_TIMEOUT_US;
+                params.runInLooperThread = false;
+            } else {
+                params.timeoutDequeue = 0;
+                params.runInLooperThread = true;
+            }
+            outputParameters.add(params);
+        }
+        return outputParameters;
+    }
+
+    protected EncoderOutputStreamParameters getDefaultEncodingParameters(
+            String inputYuvName,
+            String outputIvfBaseName,
+            int encodeSeconds,
+            int frameWidth,
+            int frameHeight,
+            int frameRate,
+            int bitrateMode,
+            int bitrate,
+            boolean syncEncoding) {
+        int[] scaleValues = { 1 };
+        int[] bitrates = { bitrate };
+        return getDefaultEncodingParameterList(
+                inputYuvName,
+                outputIvfBaseName,
+                encodeSeconds,
+                scaleValues,
+                frameWidth,
+                frameHeight,
+                frameRate,
+                bitrateMode,
+                bitrates,
+                syncEncoding).get(0);
+    }
+
+    /**
+     * Converts (interleaves) YUV420 planar to NV12.
+     * Assumes packed, macroblock-aligned frame with no cropping
+     * (visible/coded row length == stride).
+     */
+    private static byte[] YUV420ToNV(int width, int height, byte[] yuv) {
+        byte[] nv = new byte[yuv.length];
+        // Y plane we just copy.
+        System.arraycopy(yuv, 0, nv, 0, width * height);
+
+        // U & V plane we interleave.
+        int u_offset = width * height;
+        int v_offset = u_offset + u_offset / 4;
+        int nv_offset = width * height;
+        for (int i = 0; i < width * height / 4; i++) {
+            nv[nv_offset++] = yuv[u_offset++];
+            nv[nv_offset++] = yuv[v_offset++];
+        }
+        return nv;
+    }
+
+    /**
+     * Converts (de-interleaves) NV12 to YUV420 planar.
+     * Stride may be greater than width, slice height may be greater than height.
+     */
+    private static byte[] NV12ToYUV420(int width, int height,
+            int stride, int sliceHeight, byte[] nv12) {
+        byte[] yuv = new byte[width * height * 3 / 2];
+
+        // Y plane we just copy.
+        for (int i = 0; i < height; i++) {
+            System.arraycopy(nv12, i * stride, yuv, i * width, width);
+        }
+
+        // U & V plane - de-interleave.
+        int u_offset = width * height;
+        int v_offset = u_offset + u_offset / 4;
+        int nv_offset;
+        for (int i = 0; i < height / 2; i++) {
+            nv_offset = stride * (sliceHeight + i);
+            for (int j = 0; j < width / 2; j++) {
+                yuv[u_offset++] = nv12[nv_offset++];
+                yuv[v_offset++] = nv12[nv_offset++];
+            }
+        }
+        return yuv;
+    }
+
+    /**
+     * Packs YUV420 frame by moving it to a smaller size buffer with stride and slice
+     * height equal to the original frame width and height.
+     */
+    private static byte[] PackYUV420(int width, int height,
+            int stride, int sliceHeight, byte[] src) {
+        byte[] dst = new byte[width * height * 3 / 2];
+        // Y copy.
+        for (int i = 0; i < height; i++) {
+            System.arraycopy(src, i * stride, dst, i * width, width);
+        }
+        // U and V copy.
+        int u_src_offset = stride * sliceHeight;
+        int v_src_offset = u_src_offset + u_src_offset / 4;
+        int u_dst_offset = width * height;
+        int v_dst_offset = u_dst_offset + u_dst_offset / 4;
+        for (int i = 0; i < height / 2; i++) {
+            System.arraycopy(src, u_src_offset + i * (stride / 2),
+                    dst, u_dst_offset + i * (width / 2), width / 2);
+            System.arraycopy(src, v_src_offset + i * (stride / 2),
+                    dst, v_dst_offset + i * (width / 2), width / 2);
+        }
+        return dst;
+    }
+
+
+    private static void imageUpscale1To2(byte[] src, int srcByteOffset, int srcStride,
+            byte[] dst, int dstByteOffset, int dstWidth, int dstHeight) {
+        for (int i = 0; i < dstHeight/2 - 1; i++) {
+            int dstOffset0 = 2 * i * dstWidth + dstByteOffset;
+            int dstOffset1 = dstOffset0 + dstWidth;
+            int srcOffset0 = i * srcStride + srcByteOffset;
+            int srcOffset1 = srcOffset0 + srcStride;
+            int pixel00 = (int)src[srcOffset0++] & 0xff;
+            int pixel10 = (int)src[srcOffset1++] & 0xff;
+            for (int j = 0; j < dstWidth/2 - 1; j++) {
+                int pixel01 = (int)src[srcOffset0++] & 0xff;
+                int pixel11 = (int)src[srcOffset1++] & 0xff;
+                dst[dstOffset0++] = (byte)pixel00;
+                dst[dstOffset0++] = (byte)((pixel00 + pixel01 + 1) / 2);
+                dst[dstOffset1++] = (byte)((pixel00 + pixel10 + 1) / 2);
+                dst[dstOffset1++] = (byte)((pixel00 + pixel01 + pixel10 + pixel11 + 2) / 4);
+                pixel00 = pixel01;
+                pixel10 = pixel11;
+            }
+            // last column
+            dst[dstOffset0++] = (byte)pixel00;
+            dst[dstOffset0++] = (byte)pixel00;
+            dst[dstOffset1++] = (byte)((pixel00 + pixel10 + 1) / 2);
+            dst[dstOffset1++] = (byte)((pixel00 + pixel10 + 1) / 2);
+        }
+
+        // last row
+        int dstOffset0 = (dstHeight - 2) * dstWidth + dstByteOffset;
+        int dstOffset1 = dstOffset0 + dstWidth;
+        int srcOffset0 = (dstHeight/2 - 1) * srcStride + srcByteOffset;
+        int pixel00 = (int)src[srcOffset0++] & 0xff;
+        for (int j = 0; j < dstWidth/2 - 1; j++) {
+            int pixel01 = (int)src[srcOffset0++] & 0xff;
+            dst[dstOffset0++] = (byte)pixel00;
+            dst[dstOffset0++] = (byte)((pixel00 + pixel01 + 1) / 2);
+            dst[dstOffset1++] = (byte)pixel00;
+            dst[dstOffset1++] = (byte)((pixel00 + pixel01 + 1) / 2);
+            pixel00 = pixel01;
+        }
+        // the very last pixel - bottom right
+        dst[dstOffset0++] = (byte)pixel00;
+        dst[dstOffset0++] = (byte)pixel00;
+        dst[dstOffset1++] = (byte)pixel00;
+        dst[dstOffset1++] = (byte)pixel00;
+    }
+
+    /**
+    * Up-scale image.
+    * Scale factor is defined by source and destination width ratio.
+    * Only 1:2 and 1:4 up-scaling is supported for now.
+    * For 640x480 -> 1280x720 conversion only top 640x360 part of the original
+    * image is scaled.
+    */
+    private static byte[] imageScale(byte[] src, int srcWidth, int srcHeight,
+            int dstWidth, int dstHeight) throws Exception {
+        int srcYSize = srcWidth * srcHeight;
+        int dstYSize = dstWidth * dstHeight;
+        byte[] dst = null;
+        if (dstWidth == 2 * srcWidth && dstHeight <= 2 * srcHeight) {
+            // 1:2 upscale
+            dst = new byte[dstWidth * dstHeight * 3 / 2];
+            imageUpscale1To2(src, 0, srcWidth,
+                    dst, 0, dstWidth, dstHeight);                                 // Y
+            imageUpscale1To2(src, srcYSize, srcWidth / 2,
+                    dst, dstYSize, dstWidth / 2, dstHeight / 2);                  // U
+            imageUpscale1To2(src, srcYSize * 5 / 4, srcWidth / 2,
+                    dst, dstYSize * 5 / 4, dstWidth / 2, dstHeight / 2);          // V
+        } else if (dstWidth == 4 * srcWidth && dstHeight <= 4 * srcHeight) {
+            // 1:4 upscale - in two steps
+            int midWidth = 2 * srcWidth;
+            int midHeight = 2 * srcHeight;
+            byte[] midBuffer = imageScale(src, srcWidth, srcHeight, midWidth, midHeight);
+            dst = imageScale(midBuffer, midWidth, midHeight, dstWidth, dstHeight);
+
+        } else {
+            throw new RuntimeException("Can not find proper scaling function");
+        }
+
+        return dst;
+    }
+
+    private void cacheScaledImage(
+            String srcYuvFilename, int srcResourceId, int srcFrameWidth, int srcFrameHeight,
+            String dstYuvFilename, int dstFrameWidth, int dstFrameHeight) throws Exception {
+        InputStream srcStream = OpenFileOrResourceId(srcYuvFilename, srcResourceId);
+        FileOutputStream dstFile = new FileOutputStream(dstYuvFilename, false);
+        int srcFrameSize = srcFrameWidth * srcFrameHeight * 3 / 2;
+        byte[] srcFrame = new byte[srcFrameSize];
+        byte[] dstFrame = null;
+        Log.d(TAG, "Scale to " + dstFrameWidth + " x " + dstFrameHeight + ". -> " + dstYuvFilename);
+        while (true) {
+            int bytesRead = srcStream.read(srcFrame);
+            if (bytesRead != srcFrame.length) {
+                break;
+            }
+            if (dstFrameWidth == srcFrameWidth && dstFrameHeight == srcFrameHeight) {
+                dstFrame = srcFrame;
+            } else {
+                dstFrame = imageScale(srcFrame, srcFrameWidth, srcFrameHeight,
+                        dstFrameWidth, dstFrameHeight);
+            }
+            dstFile.write(dstFrame);
+        }
+        srcStream.close();
+        dstFile.close();
+    }
+
+
+    /**
+     * A basic check if an encoded stream is decodable.
+     *
+     * The most basic confirmation we can get about a frame
+     * being properly encoded is trying to decode it.
+     * (Especially in realtime mode encode output is non-
+     * deterministic, therefore a more thorough check like
+     * md5 sum comparison wouldn't work.)
+     *
+     * Indeed, MediaCodec will raise an IllegalStateException
+     * whenever vp8 decoder fails to decode a frame, and
+     * this test uses that fact to verify the bitstream.
+     *
+     * @param inputIvfFilename  The name of the IVF file containing encoded bitsream.
+     * @param outputYuvFilename The name of the output YUV file (optional).
+     * @param frameRate         Frame rate of input file in frames per second
+     * @param forceSwDecoder    Force to use Googlw sw VP8 decoder.
+     */
+    protected ArrayList<MediaCodec.BufferInfo> decode(
+            String inputIvfFilename,
+            String outputYuvFilename,
+            int frameRate,
+            boolean forceSwDecoder) throws Exception {
+        ArrayList<MediaCodec.BufferInfo> bufferInfos = new ArrayList<MediaCodec.BufferInfo>();
+        CodecProperties properties = getVp8CodecProperties(false, forceSwDecoder);
+        // Open input/output.
+        IvfReader ivf = new IvfReader(inputIvfFilename);
+        int frameWidth = ivf.getWidth();
+        int frameHeight = ivf.getHeight();
+        int frameCount = ivf.getFrameCount();
+        int frameStride = frameWidth;
+        int frameSliceHeight = frameHeight;
+        int frameColorFormat = properties.colorFormat;
+        assertTrue(frameWidth > 0);
+        assertTrue(frameHeight > 0);
+        assertTrue(frameCount > 0);
+
+        FileOutputStream yuv = null;
+        if (outputYuvFilename != null) {
+            yuv = new FileOutputStream(outputYuvFilename, false);
+        }
+
+        // Create decoder.
+        MediaFormat format = MediaFormat.createVideoFormat(VP8_MIME,
+                                                           ivf.getWidth(),
+                                                           ivf.getHeight());
+        format.setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat);
+        Log.d(TAG, "Creating decoder " + properties.codecName +
+                ". Color format: 0x" + Integer.toHexString(frameColorFormat) +
+                ". " + frameWidth + " x " + frameHeight);
+        Log.d(TAG, "  Format: " + format);
+        Log.d(TAG, "  In: " + inputIvfFilename + ". Out:" + outputYuvFilename);
+        MediaCodec decoder = MediaCodec.createByCodecName(properties.codecName);
+        decoder.configure(format,
+                          null,  // surface
+                          null,  // crypto
+                          0);    // flags
+        decoder.start();
+
+        ByteBuffer[] inputBuffers = decoder.getInputBuffers();
+        ByteBuffer[] outputBuffers = decoder.getOutputBuffers();
+        MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
+
+        // decode loop
+        int inputFrameIndex = 0;
+        int outputFrameIndex = 0;
+        long inPresentationTimeUs = 0;
+        long outPresentationTimeUs = 0;
+        boolean sawOutputEOS = false;
+        boolean sawInputEOS = false;
+
+        while (!sawOutputEOS) {
+            if (!sawInputEOS) {
+                int inputBufIndex = decoder.dequeueInputBuffer(DEFAULT_DEQUEUE_TIMEOUT_US);
+                if (inputBufIndex >= 0) {
+                    byte[] frame = ivf.readFrame(inputFrameIndex);
+
+                    if (inputFrameIndex == frameCount - 1) {
+                        Log.d(TAG, "  Input EOS for frame # " + inputFrameIndex);
+                        sawInputEOS = true;
+                    }
+
+                    inputBuffers[inputBufIndex].clear();
+                    inputBuffers[inputBufIndex].put(frame);
+                    inputBuffers[inputBufIndex].rewind();
+                    inPresentationTimeUs = (inputFrameIndex * 1000000) / frameRate;
+
+                    decoder.queueInputBuffer(
+                            inputBufIndex,
+                            0,  // offset
+                            frame.length,
+                            inPresentationTimeUs,
+                            sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
+
+                    inputFrameIndex++;
+                }
+            }
+
+            int result = decoder.dequeueOutputBuffer(bufferInfo, DEFAULT_DEQUEUE_TIMEOUT_US);
+            while (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED ||
+                    result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+                if (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
+                    outputBuffers = decoder.getOutputBuffers();
+                } else  if (result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+                    // Process format change
+                    format = decoder.getOutputFormat();
+                    frameWidth = format.getInteger(MediaFormat.KEY_WIDTH);
+                    frameHeight = format.getInteger(MediaFormat.KEY_HEIGHT);
+                    frameColorFormat = format.getInteger(MediaFormat.KEY_COLOR_FORMAT);
+                    Log.d(TAG, "Decoder output format change. Color: 0x" +
+                            Integer.toHexString(frameColorFormat));
+                    Log.d(TAG, "Format: " + format.toString());
+
+                    // Parse frame and slice height from undocumented values
+                    if (format.containsKey("stride")) {
+                        frameStride = format.getInteger("stride");
+                    } else {
+                        frameStride = frameWidth;
+                    }
+                    if (format.containsKey("slice-height")) {
+                        frameSliceHeight = format.getInteger("slice-height");
+                    } else {
+                        frameSliceHeight = frameHeight;
+                    }
+                    Log.d(TAG, "Frame stride and slice height: " + frameStride +
+                            " x " + frameSliceHeight);
+                    frameStride = Math.max(frameWidth, frameStride);
+                    frameSliceHeight = Math.max(frameHeight, frameSliceHeight);
+                }
+                result = decoder.dequeueOutputBuffer(bufferInfo, DEFAULT_DEQUEUE_TIMEOUT_US);
+            }
+            if (result >= 0) {
+                int outputBufIndex = result;
+                outPresentationTimeUs = bufferInfo.presentationTimeUs;
+                Log.v(TAG, "Writing buffer # " + outputFrameIndex +
+                        ". Size: " + bufferInfo.size +
+                        ". InTime: " + (inPresentationTimeUs + 500)/1000 +
+                        ". OutTime: " + (outPresentationTimeUs + 500)/1000);
+                if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+                    sawOutputEOS = true;
+                    Log.d(TAG, "   Output EOS for frame # " + outputFrameIndex);
+                }
+
+                if (bufferInfo.size > 0) {
+                    // Save decoder output to yuv file.
+                    if (yuv != null) {
+                        byte[] frame = new byte[bufferInfo.size];
+                        outputBuffers[outputBufIndex].position(bufferInfo.offset);
+                        outputBuffers[outputBufIndex].get(frame, 0, bufferInfo.size);
+                        // Convert NV12 to YUV420 if necessary.
+                        if (frameColorFormat != CodecCapabilities.COLOR_FormatYUV420Planar) {
+                            frame = NV12ToYUV420(frameWidth, frameHeight,
+                                    frameStride, frameSliceHeight, frame);
+                        }
+                        int writeLength = Math.min(frameWidth * frameHeight * 3 / 2, frame.length);
+                        // Pack frame if necessary.
+                        if (writeLength < frame.length &&
+                                (frameStride > frameWidth || frameSliceHeight > frameHeight)) {
+                            frame = PackYUV420(frameWidth, frameHeight,
+                                    frameStride, frameSliceHeight, frame);
+                        }
+                        yuv.write(frame, 0, writeLength);
+                    }
+                    outputFrameIndex++;
+
+                    // Update statistics - store presentation time delay in offset
+                    long presentationTimeUsDelta = inPresentationTimeUs - outPresentationTimeUs;
+                    MediaCodec.BufferInfo bufferInfoCopy = new MediaCodec.BufferInfo();
+                    bufferInfoCopy.set((int)presentationTimeUsDelta, bufferInfo.size,
+                            outPresentationTimeUs, bufferInfo.flags);
+                    bufferInfos.add(bufferInfoCopy);
+                }
+                decoder.releaseOutputBuffer(outputBufIndex, false);
+            }
+        }
+        decoder.stop();
+        decoder.release();
+        ivf.close();
+        if (yuv != null) {
+            yuv.close();
+        }
+
+        return bufferInfos;
+    }
+
+
+    /**
+     * Helper function to return InputStream from either filename (if set)
+     * or resource id (if filename is not set).
+     */
+    private InputStream OpenFileOrResourceId(String filename, int resourceId) throws Exception {
+        if (filename != null) {
+            return new FileInputStream(filename);
+        }
+        return mResources.openRawResource(resourceId);
+    }
+
+    /**
+     * Results of frame encoding.
+     */
+    protected class MediaEncoderOutput {
+        public long inPresentationTimeUs;
+        public long outPresentationTimeUs;
+        public boolean outputGenerated;
+        public int flags;
+        public byte[] buffer;
+    }
+
+    protected class MediaEncoderAsyncHelper {
+        private final EncoderOutputStreamParameters mStreamParams;
+        private final CodecProperties mProperties;
+        private final ArrayList<MediaCodec.BufferInfo> mBufferInfos;
+        private final IvfWriter mIvf;
+        private final byte[] mSrcFrame;
+
+        private InputStream mYuvStream;
+        private int mInputFrameIndex;
+
+        MediaEncoderAsyncHelper(
+                EncoderOutputStreamParameters streamParams,
+                CodecProperties properties,
+                ArrayList<MediaCodec.BufferInfo> bufferInfos,
+                IvfWriter ivf)
+                throws Exception {
+            mStreamParams = streamParams;
+            mProperties = properties;
+            mBufferInfos = bufferInfos;
+            mIvf = ivf;
+
+            int srcFrameSize = streamParams.frameWidth * streamParams.frameHeight * 3 / 2;
+            mSrcFrame = new byte[srcFrameSize];
+
+            mYuvStream = OpenFileOrResourceId(
+                    streamParams.inputYuvFilename, streamParams.inputResourceId);
+        }
+
+        public byte[] getInputFrame() {
+            // Check EOS
+            if (mStreamParams.frameCount == 0
+                    || (mStreamParams.frameCount > 0
+                            && mInputFrameIndex >= mStreamParams.frameCount)) {
+                Log.d(TAG, "---Sending EOS empty frame for frame # " + mInputFrameIndex);
+                return null;
+            }
+
+            try {
+                int bytesRead = mYuvStream.read(mSrcFrame);
+
+                if (bytesRead == -1) {
+                    // rewind to beginning of file
+                    mYuvStream.close();
+                    mYuvStream = OpenFileOrResourceId(
+                            mStreamParams.inputYuvFilename, mStreamParams.inputResourceId);
+                    bytesRead = mYuvStream.read(mSrcFrame);
+                }
+            } catch (Exception e) {
+                Log.e(TAG, "Failed to read YUV file.");
+                return null;
+            }
+            mInputFrameIndex++;
+
+            // Convert YUV420 to NV12 if necessary
+            if (mProperties.colorFormat != CodecCapabilities.COLOR_FormatYUV420Planar) {
+                return YUV420ToNV(mStreamParams.frameWidth, mStreamParams.frameHeight,
+                        mSrcFrame);
+            } else {
+                return mSrcFrame;
+            }
+        }
+
+        public boolean saveOutputFrame(MediaEncoderOutput out) {
+            if (out.outputGenerated) {
+                if (out.buffer.length > 0) {
+                    // Save frame
+                    try {
+                        mIvf.writeFrame(out.buffer, out.outPresentationTimeUs);
+                    } catch (Exception e) {
+                        Log.d(TAG, "Failed to write frame");
+                        return true;
+                    }
+
+                    // Update statistics - store presentation time delay in offset
+                    long presentationTimeUsDelta = out.inPresentationTimeUs -
+                            out.outPresentationTimeUs;
+                    MediaCodec.BufferInfo bufferInfoCopy = new MediaCodec.BufferInfo();
+                    bufferInfoCopy.set((int)presentationTimeUsDelta, out.buffer.length,
+                            out.outPresentationTimeUs, out.flags);
+                    mBufferInfos.add(bufferInfoCopy);
+                }
+                // Detect output EOS
+                if ((out.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+                    Log.d(TAG, "----Output EOS ");
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    /**
+     * Video encoder wrapper class.
+     * Allows to run the encoder either in a callee's thread or in a looper thread
+     * using buffer dequeue ready notification callbacks.
+     *
+     * Function feedInput() is used to send raw video frame to the encoder input. When encoder
+     * is configured to run in async mode the function will run in a looper thread.
+     * Encoded frame can be retrieved by calling getOutput() function.
+     */
+    protected class MediaEncoderAsync extends Thread {
+        private int mId;
+        private MediaCodec mCodec;
+        private MediaFormat mFormat;
+        private ByteBuffer[] mInputBuffers;
+        private ByteBuffer[] mOutputBuffers;
+        private int mInputFrameIndex;
+        private int mOutputFrameIndex;
+        private int mInputBufIndex;
+        private int mFrameRate;
+        private long mTimeout;
+        private MediaCodec.BufferInfo mBufferInfo;
+        private long mInPresentationTimeUs;
+        private long mOutPresentationTimeUs;
+        private boolean mAsync;
+        // Flag indicating if input frame was consumed by the encoder in feedInput() call.
+        private boolean mConsumedInput;
+        // Result of frame encoding returned by getOutput() call.
+        private MediaEncoderOutput mOutput;
+        // Object used to signal that looper thread has started and Handler instance associated
+        // with looper thread has been allocated.
+        private final Object mThreadEvent = new Object();
+        // Object used to signal that MediaCodec buffer dequeue notification callback
+        // was received.
+        private final Object mCallbackEvent = new Object();
+        private Handler mHandler;
+        private boolean mCallbackReceived;
+        private MediaEncoderAsyncHelper mHelper;
+        private final Object mCompletionEvent = new Object();
+        private boolean mCompleted;
+
+        private MediaCodec.Callback mCallback = new MediaCodec.Callback() {
+            @Override
+            public void onInputBufferAvailable(MediaCodec codec, int index) {
+                if (mHelper == null) {
+                    Log.e(TAG, "async helper not available");
+                    return;
+                }
+
+                byte[] encFrame = mHelper.getInputFrame();
+                boolean inputEOS = (encFrame == null);
+
+                int encFrameLength = 0;
+                int flags = 0;
+                if (inputEOS) {
+                    flags = MediaCodec.BUFFER_FLAG_END_OF_STREAM;
+                } else {
+                    encFrameLength = encFrame.length;
+
+                    ByteBuffer byteBuffer = mCodec.getInputBuffer(index);
+                    byteBuffer.put(encFrame);
+                    byteBuffer.rewind();
+
+                    mInPresentationTimeUs = (mInputFrameIndex * 1000000) / mFrameRate;
+
+                    Log.v(TAG, "Enc" + mId + ". Frame in # " + mInputFrameIndex +
+                            ". InTime: " + (mInPresentationTimeUs + 500)/1000);
+
+                    mInputFrameIndex++;
+                }
+
+                mCodec.queueInputBuffer(
+                        index,
+                        0,  // offset
+                        encFrameLength,  // size
+                        mInPresentationTimeUs,
+                        flags);
+            }
+
+            @Override
+            public void onOutputBufferAvailable(MediaCodec codec,
+                    int index, MediaCodec.BufferInfo info) {
+                if (mHelper == null) {
+                    Log.e(TAG, "async helper not available");
+                    return;
+                }
+
+                MediaEncoderOutput out = new MediaEncoderOutput();
+
+                out.buffer = new byte[info.size];
+                ByteBuffer outputBuffer = mCodec.getOutputBuffer(index);
+                outputBuffer.get(out.buffer, 0, info.size);
+                mOutPresentationTimeUs = info.presentationTimeUs;
+
+                String logStr = "Enc" + mId + ". Frame # " + mOutputFrameIndex;
+                if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
+                    logStr += " CONFIG. ";
+                }
+                if ((info.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) != 0) {
+                    logStr += " KEY. ";
+                }
+                if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+                    logStr += " EOS. ";
+                }
+                logStr += " Size: " + info.size;
+                logStr += ". InTime: " + (mInPresentationTimeUs + 500)/1000 +
+                        ". OutTime: " + (mOutPresentationTimeUs + 500)/1000;
+                Log.v(TAG, logStr);
+
+                if (mOutputFrameIndex == 0 &&
+                        ((info.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) == 0) ) {
+                    throw new RuntimeException("First frame is not a sync frame.");
+                }
+
+                if (info.size > 0) {
+                    mOutputFrameIndex++;
+                    out.inPresentationTimeUs = mInPresentationTimeUs;
+                    out.outPresentationTimeUs = mOutPresentationTimeUs;
+                }
+                mCodec.releaseOutputBuffer(index, false);
+
+                out.flags = info.flags;
+                out.outputGenerated = true;
+
+                if (mHelper.saveOutputFrame(out)) {
+                    // output EOS
+                    signalCompletion();
+                }
+            }
+
+            @Override
+            public void onError(MediaCodec codec, CodecException e) {
+                Log.e(TAG, "onError: " + e
+                        + ", transient " + e.isTransient()
+                        + ", recoverable " + e.isRecoverable()
+                        + ", error " + e.getErrorCode());
+            }
+
+            @Override
+            public void onOutputFormatChanged(MediaCodec codec, MediaFormat format) {
+                Log.i(TAG, "onOutputFormatChanged: " + format.toString());
+            }
+        };
+
+        private synchronized void requestStart() throws Exception {
+            mHandler = null;
+            start();
+            // Wait for Hander allocation
+            synchronized (mThreadEvent) {
+                while (mHandler == null) {
+                    mThreadEvent.wait();
+                }
+            }
+        }
+
+        public void setAsyncHelper(MediaEncoderAsyncHelper helper) {
+            mHelper = helper;
+        }
+
+        @Override
+        public void run() {
+            Looper.prepare();
+            synchronized (mThreadEvent) {
+                mHandler = new Handler();
+                mThreadEvent.notify();
+            }
+            Looper.loop();
+        }
+
+        private void runCallable(final Callable<?> callable) throws Exception {
+            if (mAsync) {
+                final Exception[] exception = new Exception[1];
+                final CountDownLatch countDownLatch = new CountDownLatch(1);
+                mHandler.post( new Runnable() {
+                    @Override
+                    public void run() {
+                        try {
+                            callable.call();
+                        } catch (Exception e) {
+                            exception[0] = e;
+                        } finally {
+                            countDownLatch.countDown();
+                        }
+                    }
+                } );
+
+                // Wait for task completion
+                countDownLatch.await();
+                if (exception[0] != null) {
+                    throw exception[0];
+                }
+            } else {
+                callable.call();
+            }
+        }
+
+        private synchronized void requestStop() throws Exception {
+            mHandler.post( new Runnable() {
+                @Override
+                public void run() {
+                    // This will run on the Looper thread
+                    Log.v(TAG, "MediaEncoder looper quitting");
+                    Looper.myLooper().quitSafely();
+                }
+            } );
+            // Wait for completion
+            join();
+            mHandler = null;
+        }
+
+        private void createCodecInternal(final String name,
+                final MediaFormat format, final long timeout) throws Exception {
+            mBufferInfo = new MediaCodec.BufferInfo();
+            mFormat = format;
+            mFrameRate = format.getInteger(MediaFormat.KEY_FRAME_RATE);
+            mTimeout = timeout;
+            mInputFrameIndex = 0;
+            mOutputFrameIndex = 0;
+            mInPresentationTimeUs = 0;
+            mOutPresentationTimeUs = 0;
+
+            mCodec = MediaCodec.createByCodecName(name);
+            if (mAsync) {
+                mCodec.setCallback(mCallback);
+            }
+            mCodec.configure(mFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
+            mCodec.start();
+
+            // get the cached input/output only in sync mode
+            if (!mAsync) {
+                mInputBuffers = mCodec.getInputBuffers();
+                mOutputBuffers = mCodec.getOutputBuffers();
+            }
+        }
+
+        public void createCodec(int id, final String name, final MediaFormat format,
+                final long timeout, boolean async)  throws Exception {
+            mId = id;
+            mAsync = async;
+            if (mAsync) {
+                requestStart(); // start looper thread
+            }
+            runCallable( new Callable<Void>() {
+                @Override
+                public Void call() throws Exception {
+                    createCodecInternal(name, format, timeout);
+                    return null;
+                }
+            } );
+        }
+
+        private void feedInputInternal(final byte[] encFrame, final boolean inputEOS) {
+            mConsumedInput = false;
+            // Feed input
+            mInputBufIndex = mCodec.dequeueInputBuffer(mTimeout);
+
+            if (mInputBufIndex >= 0) {
+                mInputBuffers[mInputBufIndex].clear();
+                mInputBuffers[mInputBufIndex].put(encFrame);
+                mInputBuffers[mInputBufIndex].rewind();
+                int encFrameLength = encFrame.length;
+                int flags = 0;
+                if (inputEOS) {
+                    encFrameLength = 0;
+                    flags = MediaCodec.BUFFER_FLAG_END_OF_STREAM;
+                }
+                if (!inputEOS) {
+                    Log.v(TAG, "Enc" + mId + ". Frame in # " + mInputFrameIndex +
+                            ". InTime: " + (mInPresentationTimeUs + 500)/1000);
+                    mInPresentationTimeUs = (mInputFrameIndex * 1000000) / mFrameRate;
+                    mInputFrameIndex++;
+                }
+
+                mCodec.queueInputBuffer(
+                        mInputBufIndex,
+                        0,  // offset
+                        encFrameLength,  // size
+                        mInPresentationTimeUs,
+                        flags);
+
+                mConsumedInput = true;
+            } else {
+                Log.v(TAG, "In " + mId + " - TRY_AGAIN_LATER");
+            }
+            mCallbackReceived = false;
+        }
+
+        public boolean feedInput(final byte[] encFrame, final boolean inputEOS) throws Exception {
+            runCallable( new Callable<Void>() {
+                @Override
+                public Void call() throws Exception {
+                    feedInputInternal(encFrame, inputEOS);
+                    return null;
+                }
+            } );
+            return mConsumedInput;
+        }
+
+        private void getOutputInternal() {
+            mOutput = new MediaEncoderOutput();
+            mOutput.inPresentationTimeUs = mInPresentationTimeUs;
+            mOutput.outPresentationTimeUs = mOutPresentationTimeUs;
+            mOutput.outputGenerated = false;
+
+            // Get output from the encoder
+            int result = mCodec.dequeueOutputBuffer(mBufferInfo, mTimeout);
+            while (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED ||
+                    result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+                if (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
+                    mOutputBuffers = mCodec.getOutputBuffers();
+                } else if (result == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+                    mFormat = mCodec.getOutputFormat();
+                    Log.d(TAG, "Format changed: " + mFormat.toString());
+                }
+                result = mCodec.dequeueOutputBuffer(mBufferInfo, mTimeout);
+            }
+            if (result == MediaCodec.INFO_TRY_AGAIN_LATER) {
+                Log.v(TAG, "Out " + mId + " - TRY_AGAIN_LATER");
+            }
+
+            if (result >= 0) {
+                int outputBufIndex = result;
+                mOutput.buffer = new byte[mBufferInfo.size];
+                mOutputBuffers[outputBufIndex].position(mBufferInfo.offset);
+                mOutputBuffers[outputBufIndex].get(mOutput.buffer, 0, mBufferInfo.size);
+                mOutPresentationTimeUs = mBufferInfo.presentationTimeUs;
+
+                String logStr = "Enc" + mId + ". Frame # " + mOutputFrameIndex;
+                if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
+                    logStr += " CONFIG. ";
+                }
+                if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) != 0) {
+                    logStr += " KEY. ";
+                }
+                if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+                    logStr += " EOS. ";
+                }
+                logStr += " Size: " + mBufferInfo.size;
+                logStr += ". InTime: " + (mInPresentationTimeUs + 500)/1000 +
+                        ". OutTime: " + (mOutPresentationTimeUs + 500)/1000;
+                Log.v(TAG, logStr);
+                if (mOutputFrameIndex == 0 &&
+                        ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) == 0) ) {
+                    throw new RuntimeException("First frame is not a sync frame.");
+                }
+
+                if (mBufferInfo.size > 0) {
+                    mOutputFrameIndex++;
+                    mOutput.outPresentationTimeUs = mOutPresentationTimeUs;
+                }
+                mCodec.releaseOutputBuffer(outputBufIndex, false);
+
+                mOutput.flags = mBufferInfo.flags;
+                mOutput.outputGenerated = true;
+            }
+            mCallbackReceived = false;
+        }
+
+        public MediaEncoderOutput getOutput() throws Exception {
+            runCallable( new Callable<Void>() {
+                @Override
+                public Void call() throws Exception {
+                    getOutputInternal();
+                    return null;
+                }
+            } );
+            return mOutput;
+        }
+
+        public void forceSyncFrame() throws Exception {
+            final Bundle syncFrame = new Bundle();
+            syncFrame.putInt(MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0);
+            runCallable( new Callable<Void>() {
+                @Override
+                public Void call() throws Exception {
+                    mCodec.setParameters(syncFrame);
+                    return null;
+                }
+            } );
+        }
+
+        public void updateBitrate(int bitrate) throws Exception {
+            final Bundle bitrateUpdate = new Bundle();
+            bitrateUpdate.putInt(MediaCodec.PARAMETER_KEY_VIDEO_BITRATE, bitrate);
+            runCallable( new Callable<Void>() {
+                @Override
+                public Void call() throws Exception {
+                    mCodec.setParameters(bitrateUpdate);
+                    return null;
+                }
+            } );
+        }
+
+
+        public void waitForBufferEvent() throws Exception {
+            Log.v(TAG, "----Enc" + mId + " waiting for bufferEvent");
+            if (mAsync) {
+                synchronized (mCallbackEvent) {
+                    if (!mCallbackReceived) {
+                        mCallbackEvent.wait(1000); // wait 1 sec for a callback
+                        // throw an exception if callback was not received
+                        if (!mCallbackReceived) {
+                            throw new RuntimeException("MediaCodec callback was not received");
+                        }
+                    }
+                }
+            } else {
+                Thread.sleep(5);
+            }
+            Log.v(TAG, "----Waiting for bufferEvent done");
+        }
+
+
+        public void waitForCompletion(long timeoutMs) throws Exception {
+            synchronized (mCompletionEvent) {
+                long timeoutExpiredMs = System.currentTimeMillis() + timeoutMs;
+
+                while (!mCompleted) {
+                    mCompletionEvent.wait(timeoutExpiredMs - System.currentTimeMillis());
+                    if (System.currentTimeMillis() >= timeoutExpiredMs) {
+                        throw new RuntimeException("encoding has timed out!");
+                    }
+                }
+            }
+        }
+
+        public void signalCompletion() {
+            synchronized (mCompletionEvent) {
+                mCompleted = true;
+                mCompletionEvent.notify();
+            }
+        }
+
+        public void deleteCodec() throws Exception {
+            runCallable( new Callable<Void>() {
+                @Override
+                public Void call() throws Exception {
+                    mCodec.stop();
+                    mCodec.release();
+                    return null;
+                }
+            } );
+            if (mAsync) {
+                requestStop(); // Stop looper thread
+            }
+        }
+    }
+
+    /**
+     * Vp8 encoding loop supporting encoding single streams with an option
+     * to run in a looper thread and use buffer ready notification callbacks.
+     *
+     * Output stream is described by encodingParams parameters.
+     *
+     * MediaCodec will raise an IllegalStateException
+     * whenever vp8 encoder fails to encode a frame.
+     *
+     * Color format of input file should be YUV420, and frameWidth,
+     * frameHeight should be supplied correctly as raw input file doesn't
+     * include any header data.
+     *
+     * @param streamParams  Structure with encoder parameters
+     * @return              Returns array of encoded frames information for each frame.
+     */
+    protected ArrayList<MediaCodec.BufferInfo> encode(
+            EncoderOutputStreamParameters streamParams) throws Exception {
+
+        ArrayList<MediaCodec.BufferInfo> bufferInfos = new ArrayList<MediaCodec.BufferInfo>();
+        CodecProperties properties = getVp8CodecProperties(true, streamParams.forceSwEncoder);
+        Log.d(TAG, "Source reslution: " + streamParams.frameWidth + " x " +
+                streamParams.frameHeight);
+        int bitrate = streamParams.bitrateSet[0];
+
+        // Open input/output
+        InputStream yuvStream = OpenFileOrResourceId(
+                streamParams.inputYuvFilename, streamParams.inputResourceId);
+        IvfWriter ivf = new IvfWriter(
+                streamParams.outputIvfFilename, streamParams.frameWidth, streamParams.frameHeight);
+
+        // Create a media format signifying desired output.
+        MediaFormat format = MediaFormat.createVideoFormat(
+                VP8_MIME, streamParams.frameWidth, streamParams.frameHeight);
+        format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
+        if (streamParams.bitrateType == VIDEO_ControlRateConstant) {
+            format.setInteger("bitrate-mode", VIDEO_ControlRateConstant); // set CBR
+        }
+        if (streamParams.temporalLayers > 0) {
+            format.setInteger("ts-layers", streamParams.temporalLayers); // 1 temporal layer
+        }
+        format.setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat);
+        format.setInteger(MediaFormat.KEY_FRAME_RATE, streamParams.frameRate);
+        int syncFrameInterval = (streamParams.syncFrameInterval + streamParams.frameRate/2) /
+                streamParams.frameRate;
+        format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, syncFrameInterval);
+
+        // Create encoder
+        Log.d(TAG, "Creating encoder " + properties.codecName +
+                ". Color format: 0x" + Integer.toHexString(properties.colorFormat)+ " : " +
+                streamParams.frameWidth + " x " + streamParams.frameHeight +
+                ". Bitrate: " + bitrate + " Bitrate type: " + streamParams.bitrateType +
+                ". Fps:" + streamParams.frameRate + ". TS Layers: " + streamParams.temporalLayers +
+                ". Key frame:" + syncFrameInterval * streamParams.frameRate +
+                ". Force keyFrame: " + streamParams.syncForceFrameInterval);
+        Log.d(TAG, "  Format: " + format);
+        Log.d(TAG, "  Output ivf:" + streamParams.outputIvfFilename);
+        MediaEncoderAsync codec = new MediaEncoderAsync();
+        codec.createCodec(0, properties.codecName, format,
+                streamParams.timeoutDequeue, streamParams.runInLooperThread);
+
+        // encode loop
+        boolean sawInputEOS = false;  // no more data
+        boolean consumedInputEOS = false; // EOS flag is consumed dy encoder
+        boolean sawOutputEOS = false;
+        boolean inputConsumed = true;
+        int inputFrameIndex = 0;
+        int lastBitrate = bitrate;
+        int srcFrameSize = streamParams.frameWidth * streamParams.frameHeight * 3 / 2;
+        byte[] srcFrame = new byte[srcFrameSize];
+
+        while (!sawOutputEOS) {
+
+            // Read and feed input frame
+            if (!consumedInputEOS) {
+
+                // Read new input buffers - if previous input was consumed and no EOS
+                if (inputConsumed && !sawInputEOS) {
+                    int bytesRead = yuvStream.read(srcFrame);
+
+                    // Check EOS
+                    if (streamParams.frameCount > 0 && inputFrameIndex >= streamParams.frameCount) {
+                        sawInputEOS = true;
+                        Log.d(TAG, "---Sending EOS empty frame for frame # " + inputFrameIndex);
+                    }
+
+                    if (!sawInputEOS && bytesRead == -1) {
+                        if (streamParams.frameCount == 0) {
+                            sawInputEOS = true;
+                            Log.d(TAG, "---Sending EOS empty frame for frame # " + inputFrameIndex);
+                        } else {
+                            yuvStream.close();
+                            yuvStream = OpenFileOrResourceId(
+                                    streamParams.inputYuvFilename, streamParams.inputResourceId);
+                            bytesRead = yuvStream.read(srcFrame);
+                        }
+                    }
+
+                    // Force sync frame if syncForceFrameinterval is set.
+                    if (!sawInputEOS && inputFrameIndex > 0 &&
+                            streamParams.syncForceFrameInterval > 0 &&
+                            (inputFrameIndex % streamParams.syncForceFrameInterval) == 0) {
+                        Log.d(TAG, "---Requesting sync frame # " + inputFrameIndex);
+                        codec.forceSyncFrame();
+                    }
+
+                    // Dynamic bitrate change.
+                    if (!sawInputEOS && streamParams.bitrateSet.length > inputFrameIndex) {
+                        int newBitrate = streamParams.bitrateSet[inputFrameIndex];
+                        if (newBitrate != lastBitrate) {
+                            Log.d(TAG, "--- Requesting new bitrate " + newBitrate +
+                                    " for frame " + inputFrameIndex);
+                            codec.updateBitrate(newBitrate);
+                            lastBitrate = newBitrate;
+                        }
+                    }
+
+                    // Convert YUV420 to NV12 if necessary
+                    if (properties.colorFormat != CodecCapabilities.COLOR_FormatYUV420Planar) {
+                        srcFrame = YUV420ToNV(streamParams.frameWidth, streamParams.frameHeight,
+                                srcFrame);
+                    }
+                }
+
+                inputConsumed = codec.feedInput(srcFrame, sawInputEOS);
+                if (inputConsumed) {
+                    inputFrameIndex++;
+                    consumedInputEOS = sawInputEOS;
+                }
+            }
+
+            // Get output from the encoder
+            MediaEncoderOutput out = codec.getOutput();
+            if (out.outputGenerated) {
+                // Detect output EOS
+                if ((out.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+                    Log.d(TAG, "----Output EOS ");
+                    sawOutputEOS = true;
+                }
+
+                if (out.buffer.length > 0) {
+                    // Save frame
+                    ivf.writeFrame(out.buffer, out.outPresentationTimeUs);
+
+                    // Update statistics - store presentation time delay in offset
+                    long presentationTimeUsDelta = out.inPresentationTimeUs -
+                            out.outPresentationTimeUs;
+                    MediaCodec.BufferInfo bufferInfoCopy = new MediaCodec.BufferInfo();
+                    bufferInfoCopy.set((int)presentationTimeUsDelta, out.buffer.length,
+                            out.outPresentationTimeUs, out.flags);
+                    bufferInfos.add(bufferInfoCopy);
+                }
+            }
+
+            // If codec is not ready to accept input/poutput - wait for buffer ready callback
+            if ((!inputConsumed || consumedInputEOS) && !out.outputGenerated) {
+                codec.waitForBufferEvent();
+            }
+        }
+
+        codec.deleteCodec();
+        ivf.close();
+        yuvStream.close();
+
+        return bufferInfos;
+    }
+
+    /**
+     * Vp8 encoding run in a looper thread and use buffer ready callbacks.
+     *
+     * Output stream is described by encodingParams parameters.
+     *
+     * MediaCodec will raise an IllegalStateException
+     * whenever vp8 encoder fails to encode a frame.
+     *
+     * Color format of input file should be YUV420, and frameWidth,
+     * frameHeight should be supplied correctly as raw input file doesn't
+     * include any header data.
+     *
+     * @param streamParams  Structure with encoder parameters
+     * @return              Returns array of encoded frames information for each frame.
+     */
+    protected ArrayList<MediaCodec.BufferInfo> encodeAsync(
+            EncoderOutputStreamParameters streamParams) throws Exception {
+        if (!streamParams.runInLooperThread) {
+            throw new RuntimeException("encodeAsync should run with a looper thread!");
+        }
+
+        ArrayList<MediaCodec.BufferInfo> bufferInfos = new ArrayList<MediaCodec.BufferInfo>();
+        CodecProperties properties = getVp8CodecProperties(true, streamParams.forceSwEncoder);
+        Log.d(TAG, "Source reslution: " + streamParams.frameWidth + " x " +
+                streamParams.frameHeight);
+        int bitrate = streamParams.bitrateSet[0];
+
+        // Open input/output
+        IvfWriter ivf = new IvfWriter(
+                streamParams.outputIvfFilename, streamParams.frameWidth, streamParams.frameHeight);
+
+        // Create a media format signifying desired output.
+        MediaFormat format = MediaFormat.createVideoFormat(
+                VP8_MIME, streamParams.frameWidth, streamParams.frameHeight);
+        format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
+        if (streamParams.bitrateType == VIDEO_ControlRateConstant) {
+            format.setInteger("bitrate-mode", VIDEO_ControlRateConstant); // set CBR
+        }
+        if (streamParams.temporalLayers > 0) {
+            format.setInteger("ts-layers", streamParams.temporalLayers); // 1 temporal layer
+        }
+        format.setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat);
+        format.setInteger(MediaFormat.KEY_FRAME_RATE, streamParams.frameRate);
+        int syncFrameInterval = (streamParams.syncFrameInterval + streamParams.frameRate/2) /
+                streamParams.frameRate;
+        format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, syncFrameInterval);
+
+        // Create encoder
+        Log.d(TAG, "Creating encoder " + properties.codecName +
+                ". Color format: 0x" + Integer.toHexString(properties.colorFormat)+ " : " +
+                streamParams.frameWidth + " x " + streamParams.frameHeight +
+                ". Bitrate: " + bitrate + " Bitrate type: " + streamParams.bitrateType +
+                ". Fps:" + streamParams.frameRate + ". TS Layers: " + streamParams.temporalLayers +
+                ". Key frame:" + syncFrameInterval * streamParams.frameRate +
+                ". Force keyFrame: " + streamParams.syncForceFrameInterval);
+        Log.d(TAG, "  Format: " + format);
+        Log.d(TAG, "  Output ivf:" + streamParams.outputIvfFilename);
+
+        MediaEncoderAsync codec = new MediaEncoderAsync();
+        MediaEncoderAsyncHelper helper = new MediaEncoderAsyncHelper(
+                streamParams, properties, bufferInfos, ivf);
+
+        codec.setAsyncHelper(helper);
+        codec.createCodec(0, properties.codecName, format,
+                streamParams.timeoutDequeue, streamParams.runInLooperThread);
+        codec.waitForCompletion(DEFAULT_ENCODE_TIMEOUT_MS);
+
+        codec.deleteCodec();
+        ivf.close();
+
+        return bufferInfos;
+    }
+
+    /**
+     * Vp8 encoding loop supporting encoding multiple streams at a time.
+     * Each output stream is described by encodingParams parameters allowing
+     * simultaneous encoding of various resolutions, bitrates with an option to
+     * control key frame and dynamic bitrate for each output stream indepandently.
+     *
+     * MediaCodec will raise an IllegalStateException
+     * whenever vp8 encoder fails to encode a frame.
+     *
+     * Color format of input file should be YUV420, and frameWidth,
+     * frameHeight should be supplied correctly as raw input file doesn't
+     * include any header data.
+     *
+     * @param srcFrameWidth     Frame width of input yuv file
+     * @param srcFrameHeight    Frame height of input yuv file
+     * @param encodingParams    Encoder parameters
+     * @return                  Returns 2D array of encoded frames information for each stream and
+     *                          for each frame.
+     */
+    protected ArrayList<ArrayList<MediaCodec.BufferInfo>> encodeSimulcast(
+            int srcFrameWidth,
+            int srcFrameHeight,
+            ArrayList<EncoderOutputStreamParameters> encodingParams)  throws Exception {
+        int numEncoders = encodingParams.size();
+
+        // Create arrays of input/output, formats, bitrates etc
+        ArrayList<ArrayList<MediaCodec.BufferInfo>> bufferInfos =
+                new ArrayList<ArrayList<MediaCodec.BufferInfo>>(numEncoders);
+        InputStream yuvStream[] = new InputStream[numEncoders];
+        IvfWriter[] ivf = new IvfWriter[numEncoders];
+        FileOutputStream[] yuvScaled = new FileOutputStream[numEncoders];
+        MediaFormat[] format = new MediaFormat[numEncoders];
+        MediaEncoderAsync[] codec = new MediaEncoderAsync[numEncoders];
+        int[] inputFrameIndex = new int[numEncoders];
+        boolean[] sawInputEOS = new boolean[numEncoders];
+        boolean[] consumedInputEOS = new boolean[numEncoders];
+        boolean[] inputConsumed = new boolean[numEncoders];
+        boolean[] bufferConsumed = new boolean[numEncoders];
+        boolean[] sawOutputEOS = new boolean[numEncoders];
+        byte[][] srcFrame = new byte[numEncoders][];
+        boolean sawOutputEOSTotal = false;
+        boolean bufferConsumedTotal = false;
+        CodecProperties[] codecProperties = new CodecProperties[numEncoders];
+
+        for (int i = 0; i < numEncoders; i++) {
+            EncoderOutputStreamParameters params = encodingParams.get(i);
+            CodecProperties properties = getVp8CodecProperties(true, params.forceSwEncoder);
+
+            // Check if scaled image was created
+            int scale = params.frameWidth / srcFrameWidth;
+            if (!mScaledImages.contains(scale)) {
+                // resize image
+                cacheScaledImage(params.inputYuvFilename, params.inputResourceId,
+                        srcFrameWidth, srcFrameHeight,
+                        params.scaledYuvFilename, params.frameWidth, params.frameHeight);
+                mScaledImages.add(scale);
+            }
+
+            // Create buffer info storage
+            bufferInfos.add(new ArrayList<MediaCodec.BufferInfo>());
+
+            // Create YUV reader
+            yuvStream[i] = new FileInputStream(params.scaledYuvFilename);
+
+            // Create IVF writer
+            ivf[i] = new IvfWriter(params.outputIvfFilename, params.frameWidth, params.frameHeight);
+
+            // Frame buffer
+            int frameSize = params.frameWidth * params.frameHeight * 3 / 2;
+            srcFrame[i] = new byte[frameSize];
+
+            // Create a media format signifying desired output.
+            int bitrate = params.bitrateSet[0];
+            format[i] = MediaFormat.createVideoFormat(VP8_MIME,
+                    params.frameWidth, params.frameHeight);
+            format[i].setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
+            if (params.bitrateType == VIDEO_ControlRateConstant) {
+                format[i].setInteger("bitrate-mode", VIDEO_ControlRateConstant); // set CBR
+            }
+            if (params.temporalLayers > 0) {
+                format[i].setInteger("ts-layers", params.temporalLayers); // 1 temporal layer
+            }
+            format[i].setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat);
+            format[i].setInteger(MediaFormat.KEY_FRAME_RATE, params.frameRate);
+            int syncFrameInterval = (params.syncFrameInterval + params.frameRate/2) /
+                    params.frameRate; // in sec
+            format[i].setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, syncFrameInterval);
+            // Create encoder
+            Log.d(TAG, "Creating encoder #" + i +" : " + properties.codecName +
+                    ". Color format: 0x" + Integer.toHexString(properties.colorFormat)+ " : " +
+                    params.frameWidth + " x " + params.frameHeight +
+                    ". Bitrate: " + bitrate + " Bitrate type: " + params.bitrateType +
+                    ". Fps:" + params.frameRate + ". TS Layers: " + params.temporalLayers +
+                    ". Key frame:" + syncFrameInterval * params.frameRate +
+                    ". Force keyFrame: " + params.syncForceFrameInterval);
+            Log.d(TAG, "  Format: " + format[i]);
+            Log.d(TAG, "  Output ivf:" + params.outputIvfFilename);
+
+            // Create encoder
+            codec[i] = new MediaEncoderAsync();
+            codec[i].createCodec(i, properties.codecName, format[i],
+                    params.timeoutDequeue, params.runInLooperThread);
+            codecProperties[i] = new CodecProperties(properties.codecName, properties.colorFormat);
+
+            inputConsumed[i] = true;
+        }
+
+        while (!sawOutputEOSTotal) {
+            // Feed input buffer to all encoders
+            for (int i = 0; i < numEncoders; i++) {
+                bufferConsumed[i] = false;
+                if (consumedInputEOS[i]) {
+                    continue;
+                }
+
+                EncoderOutputStreamParameters params = encodingParams.get(i);
+                // Read new input buffers - if previous input was consumed and no EOS
+                if (inputConsumed[i] && !sawInputEOS[i]) {
+                    int bytesRead = yuvStream[i].read(srcFrame[i]);
+
+                    // Check EOS
+                    if (params.frameCount > 0 && inputFrameIndex[i] >= params.frameCount) {
+                        sawInputEOS[i] = true;
+                        Log.d(TAG, "---Enc" + i +
+                                ". Sending EOS empty frame for frame # " + inputFrameIndex[i]);
+                    }
+
+                    if (!sawInputEOS[i] && bytesRead == -1) {
+                        if (params.frameCount == 0) {
+                            sawInputEOS[i] = true;
+                            Log.d(TAG, "---Enc" + i +
+                                    ". Sending EOS empty frame for frame # " + inputFrameIndex[i]);
+                        } else {
+                            yuvStream[i].close();
+                            yuvStream[i] = new FileInputStream(params.scaledYuvFilename);
+                            bytesRead = yuvStream[i].read(srcFrame[i]);
+                        }
+                    }
+
+                    // Convert YUV420 to NV12 if necessary
+                    if (codecProperties[i].colorFormat !=
+                            CodecCapabilities.COLOR_FormatYUV420Planar) {
+                        srcFrame[i] = YUV420ToNV(params.frameWidth, params.frameHeight, srcFrame[i]);
+                    }
+                }
+
+                inputConsumed[i] = codec[i].feedInput(srcFrame[i], sawInputEOS[i]);
+                if (inputConsumed[i]) {
+                    inputFrameIndex[i]++;
+                    consumedInputEOS[i] = sawInputEOS[i];
+                    bufferConsumed[i] = true;
+                }
+
+            }
+
+            // Get output from all encoders
+            for (int i = 0; i < numEncoders; i++) {
+                if (sawOutputEOS[i]) {
+                    continue;
+                }
+
+                MediaEncoderOutput out = codec[i].getOutput();
+                if (out.outputGenerated) {
+                    bufferConsumed[i] = true;
+                    // Detect output EOS
+                    if ((out.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
+                        Log.d(TAG, "----Enc" + i + ". Output EOS ");
+                        sawOutputEOS[i] = true;
+                    }
+
+                    if (out.buffer.length > 0) {
+                        // Save frame
+                        ivf[i].writeFrame(out.buffer, out.outPresentationTimeUs);
+
+                        // Update statistics - store presentation time delay in offset
+                        long presentationTimeUsDelta = out.inPresentationTimeUs -
+                                out.outPresentationTimeUs;
+                        MediaCodec.BufferInfo bufferInfoCopy = new MediaCodec.BufferInfo();
+                        bufferInfoCopy.set((int)presentationTimeUsDelta, out.buffer.length,
+                                out.outPresentationTimeUs, out.flags);
+                        bufferInfos.get(i).add(bufferInfoCopy);
+                    }
+                }
+            }
+
+            // If codec is not ready to accept input/output - wait for buffer ready callback
+            bufferConsumedTotal = false;
+            for (boolean bufferConsumedCurrent : bufferConsumed) {
+                bufferConsumedTotal |= bufferConsumedCurrent;
+            }
+            if (!bufferConsumedTotal) {
+                // Pick the encoder to wait for
+                for (int i = 0; i < numEncoders; i++) {
+                    if (!bufferConsumed[i] && !sawOutputEOS[i]) {
+                        codec[i].waitForBufferEvent();
+                        break;
+                    }
+                }
+            }
+
+            // Check if EOS happened for all encoders
+            sawOutputEOSTotal = true;
+            for (boolean sawOutputEOSStream : sawOutputEOS) {
+                sawOutputEOSTotal &= sawOutputEOSStream;
+            }
+        }
+
+        for (int i = 0; i < numEncoders; i++) {
+            codec[i].deleteCodec();
+            ivf[i].close();
+            yuvStream[i].close();
+            if (yuvScaled[i] != null) {
+                yuvScaled[i].close();
+            }
+        }
+
+        return bufferInfos;
+    }
+
+    /**
+     * Some encoding statistics.
+     */
+    protected class Vp8EncodingStatistics {
+        Vp8EncodingStatistics() {
+            mBitrates = new ArrayList<Integer>();
+            mFrames = new ArrayList<Integer>();
+            mKeyFrames = new ArrayList<Integer>();
+            mMinimumKeyFrameInterval = Integer.MAX_VALUE;
+        }
+
+        public ArrayList<Integer> mBitrates;// Bitrate values for each second of the encoded stream.
+        public ArrayList<Integer> mFrames; // Number of frames in each second of the encoded stream.
+        public int mAverageBitrate;         // Average stream bitrate.
+        public ArrayList<Integer> mKeyFrames;// Stores the position of key frames in a stream.
+        public int mAverageKeyFrameInterval; // Average key frame interval.
+        public int mMaximumKeyFrameInterval; // Maximum key frame interval.
+        public int mMinimumKeyFrameInterval; // Minimum key frame interval.
+    }
+
+    /**
+     * Calculates average bitrate and key frame interval for the encoded streams.
+     * Output mBitrates field will contain bitrate values for every second
+     * of the encoded stream.
+     * Average stream bitrate will be stored in mAverageBitrate field.
+     * mKeyFrames array will contain the position of key frames in the encoded stream and
+     * mKeyFrameInterval - average key frame interval.
+     */
+    protected Vp8EncodingStatistics computeEncodingStatistics(int encoderId,
+            ArrayList<MediaCodec.BufferInfo> bufferInfos ) {
+        Vp8EncodingStatistics statistics = new Vp8EncodingStatistics();
+
+        int totalSize = 0;
+        int frames = 0;
+        int framesPerSecond = 0;
+        int totalFrameSizePerSecond = 0;
+        int maxFrameSize = 0;
+        int currentSecond;
+        int nextSecond = 0;
+        String keyFrameList = "  IFrame List: ";
+        String bitrateList = "  Bitrate list: ";
+        String framesList = "  FPS list: ";
+
+
+        for (int j = 0; j < bufferInfos.size(); j++) {
+            MediaCodec.BufferInfo info = bufferInfos.get(j);
+            currentSecond = (int)(info.presentationTimeUs / 1000000);
+            boolean lastFrame = (j == bufferInfos.size() - 1);
+            if (!lastFrame) {
+                nextSecond = (int)(bufferInfos.get(j+1).presentationTimeUs / 1000000);
+            }
+
+            totalSize += info.size;
+            totalFrameSizePerSecond += info.size;
+            maxFrameSize = Math.max(maxFrameSize, info.size);
+            framesPerSecond++;
+            frames++;
+
+            // Update the bitrate statistics if the next frame will
+            // be for the next second
+            if (lastFrame || nextSecond > currentSecond) {
+                int currentBitrate = totalFrameSizePerSecond * 8;
+                bitrateList += (currentBitrate + " ");
+                framesList += (framesPerSecond + " ");
+                statistics.mBitrates.add(currentBitrate);
+                statistics.mFrames.add(framesPerSecond);
+                totalFrameSizePerSecond = 0;
+                framesPerSecond = 0;
+            }
+
+            // Update key frame statistics.
+            if ((info.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) != 0) {
+                statistics.mKeyFrames.add(j);
+                keyFrameList += (j + "  ");
+            }
+        }
+        int duration = (int)(bufferInfos.get(bufferInfos.size() - 1).presentationTimeUs / 1000);
+        duration = (duration + 500) / 1000;
+        statistics.mAverageBitrate = (int)(((long)totalSize * 8) / duration);
+        Log.d(TAG, "Statistics for encoder # " + encoderId);
+        // Calculate average key frame interval in frames.
+        int keyFrames = statistics.mKeyFrames.size();
+        if (keyFrames > 1) {
+            statistics.mAverageKeyFrameInterval =
+                    statistics.mKeyFrames.get(keyFrames - 1) - statistics.mKeyFrames.get(0);
+            statistics.mAverageKeyFrameInterval =
+                    Math.round((float)statistics.mAverageKeyFrameInterval / (keyFrames - 1));
+            for (int j = 1; j < keyFrames; j++) {
+                int keyFrameInterval =
+                        statistics.mKeyFrames.get(j) - statistics.mKeyFrames.get(j - 1);
+                statistics.mMaximumKeyFrameInterval =
+                        Math.max(statistics.mMaximumKeyFrameInterval, keyFrameInterval);
+                statistics.mMinimumKeyFrameInterval =
+                        Math.min(statistics.mMinimumKeyFrameInterval, keyFrameInterval);
+            }
+            Log.d(TAG, "  Key frame intervals: Max: " + statistics.mMaximumKeyFrameInterval +
+                    ". Min: " + statistics.mMinimumKeyFrameInterval +
+                    ". Avg: " + statistics.mAverageKeyFrameInterval);
+        }
+        Log.d(TAG, "  Frames: " + frames + ". Duration: " + duration +
+                ". Total size: " + totalSize + ". Key frames: " + keyFrames);
+        Log.d(TAG, keyFrameList);
+        Log.d(TAG, bitrateList);
+        Log.d(TAG, framesList);
+        Log.d(TAG, "  Bitrate average: " + statistics.mAverageBitrate);
+        Log.d(TAG, "  Maximum frame size: " + maxFrameSize);
+
+        return statistics;
+    }
+
+    protected Vp8EncodingStatistics computeEncodingStatistics(
+            ArrayList<MediaCodec.BufferInfo> bufferInfos ) {
+        return computeEncodingStatistics(0, bufferInfos);
+    }
+
+    protected ArrayList<Vp8EncodingStatistics> computeSimulcastEncodingStatistics(
+            ArrayList<ArrayList<MediaCodec.BufferInfo>> bufferInfos) {
+        int numCodecs = bufferInfos.size();
+        ArrayList<Vp8EncodingStatistics> statistics = new ArrayList<Vp8EncodingStatistics>();
+
+        for (int i = 0; i < numCodecs; i++) {
+            Vp8EncodingStatistics currentStatistics =
+                    computeEncodingStatistics(i, bufferInfos.get(i));
+            statistics.add(currentStatistics);
+        }
+        return statistics;
+    }
+
+    /**
+     * Calculates maximum latency for encoder/decoder based on buffer info array
+     * generated either by encoder or decoder.
+     */
+    protected int maxPresentationTimeDifference(ArrayList<MediaCodec.BufferInfo> bufferInfos) {
+        int maxValue = 0;
+        for (MediaCodec.BufferInfo bufferInfo : bufferInfos) {
+            maxValue = Math.max(maxValue,  bufferInfo.offset);
+        }
+        maxValue = (maxValue + 500) / 1000; // mcs -> ms
+        return maxValue;
+    }
+
+    /**
+     * Decoding PSNR statistics.
+     */
+    protected class Vp8DecodingStatistics {
+        Vp8DecodingStatistics() {
+            mMinimumPSNR = Integer.MAX_VALUE;
+        }
+        public double mAveragePSNR;
+        public double mMinimumPSNR;
+    }
+
+    /**
+     * Calculates PSNR value between two video frames.
+     */
+    private double computePSNR(byte[] data0, byte[] data1) {
+        long squareError = 0;
+        assertTrue(data0.length == data1.length);
+        int length = data0.length;
+        for (int i = 0 ; i < length; i++) {
+            int diff = ((int)data0[i] & 0xff) - ((int)data1[i] & 0xff);
+            squareError += diff * diff;
+        }
+        double meanSquareError = (double)squareError / length;
+        double psnr = 10 * Math.log10((double)255 * 255 / meanSquareError);
+        return psnr;
+    }
+
+    /**
+     * Calculates average and minimum PSNR values between
+     * set of reference and decoded video frames.
+     * Runs PSNR calculation for the full duration of the decoded data.
+     */
+    protected Vp8DecodingStatistics computeDecodingStatistics(
+            String referenceYuvFilename,
+            int referenceYuvRawId,
+            String decodedYuvFilename,
+            int width,
+            int height) throws Exception {
+        Vp8DecodingStatistics statistics = new Vp8DecodingStatistics();
+        InputStream referenceStream =
+                OpenFileOrResourceId(referenceYuvFilename, referenceYuvRawId);
+        InputStream decodedStream = new FileInputStream(decodedYuvFilename);
+
+        int ySize = width * height;
+        int uvSize = width * height / 4;
+        byte[] yRef = new byte[ySize];
+        byte[] yDec = new byte[ySize];
+        byte[] uvRef = new byte[uvSize];
+        byte[] uvDec = new byte[uvSize];
+
+        int frames = 0;
+        double averageYPSNR = 0;
+        double averageUPSNR = 0;
+        double averageVPSNR = 0;
+        double minimumYPSNR = Integer.MAX_VALUE;
+        double minimumUPSNR = Integer.MAX_VALUE;
+        double minimumVPSNR = Integer.MAX_VALUE;
+        int minimumPSNRFrameIndex = 0;
+
+        while (true) {
+            // Calculate Y PSNR.
+            int bytesReadRef = referenceStream.read(yRef);
+            int bytesReadDec = decodedStream.read(yDec);
+            if (bytesReadDec == -1) {
+                break;
+            }
+            if (bytesReadRef == -1) {
+                // Reference file wrapping up
+                referenceStream.close();
+                referenceStream =
+                        OpenFileOrResourceId(referenceYuvFilename, referenceYuvRawId);
+                bytesReadRef = referenceStream.read(yRef);
+            }
+            double curYPSNR = computePSNR(yRef, yDec);
+            averageYPSNR += curYPSNR;
+            minimumYPSNR = Math.min(minimumYPSNR, curYPSNR);
+            double curMinimumPSNR = curYPSNR;
+
+            // Calculate U PSNR.
+            bytesReadRef = referenceStream.read(uvRef);
+            bytesReadDec = decodedStream.read(uvDec);
+            double curUPSNR = computePSNR(uvRef, uvDec);
+            averageUPSNR += curUPSNR;
+            minimumUPSNR = Math.min(minimumUPSNR, curUPSNR);
+            curMinimumPSNR = Math.min(curMinimumPSNR, curUPSNR);
+
+            // Calculate V PSNR.
+            bytesReadRef = referenceStream.read(uvRef);
+            bytesReadDec = decodedStream.read(uvDec);
+            double curVPSNR = computePSNR(uvRef, uvDec);
+            averageVPSNR += curVPSNR;
+            minimumVPSNR = Math.min(minimumVPSNR, curVPSNR);
+            curMinimumPSNR = Math.min(curMinimumPSNR, curVPSNR);
+
+            // Frame index for minimum PSNR value - help to detect possible distortions
+            if (curMinimumPSNR < statistics.mMinimumPSNR) {
+                statistics.mMinimumPSNR = curMinimumPSNR;
+                minimumPSNRFrameIndex = frames;
+            }
+
+            String logStr = String.format(Locale.US, "PSNR #%d: Y: %.2f. U: %.2f. V: %.2f",
+                    frames, curYPSNR, curUPSNR, curVPSNR);
+            Log.v(TAG, logStr);
+
+            frames++;
+        }
+
+        averageYPSNR /= frames;
+        averageUPSNR /= frames;
+        averageVPSNR /= frames;
+        statistics.mAveragePSNR = (4 * averageYPSNR + averageUPSNR + averageVPSNR) / 6;
+
+        Log.d(TAG, "PSNR statistics for " + frames + " frames.");
+        String logStr = String.format(Locale.US,
+                "Average PSNR: Y: %.1f. U: %.1f. V: %.1f. Average: %.1f",
+                averageYPSNR, averageUPSNR, averageVPSNR, statistics.mAveragePSNR);
+        Log.d(TAG, logStr);
+        logStr = String.format(Locale.US,
+                "Minimum PSNR: Y: %.1f. U: %.1f. V: %.1f. Overall: %.1f at frame %d",
+                minimumYPSNR, minimumUPSNR, minimumVPSNR,
+                statistics.mMinimumPSNR, minimumPSNRFrameIndex);
+        Log.d(TAG, logStr);
+
+        referenceStream.close();
+        decodedStream.close();
+        return statistics;
+    }
+}
+
diff --git a/tests/tests/media/src/android/media/cts/Vp8EncoderTest.java b/tests/tests/media/src/android/media/cts/Vp8EncoderTest.java
index 2be0fc4..57e397f 100644
--- a/tests/tests/media/src/android/media/cts/Vp8EncoderTest.java
+++ b/tests/tests/media/src/android/media/cts/Vp8EncoderTest.java
@@ -16,633 +16,464 @@
 
 package android.media.cts;
 
-import android.content.Context;
-import android.content.res.Resources;
 import android.media.MediaCodec;
 import android.media.MediaCodecInfo;
-import android.media.MediaCodecInfo.CodecCapabilities;
-import android.media.MediaCodecList;
-import android.media.MediaFormat;
-import android.os.Bundle;
-import android.test.AndroidTestCase;
 import android.util.Log;
-
 import com.android.cts.media.R;
 
-import java.io.InputStream;
-import java.nio.ByteBuffer;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
 
 /**
- * Basic verification test for vp8 encoder.
+ * Verification test for vp8 encoder and decoder.
  *
- * A raw yv12 stream is encoded and written to an IVF
- * file, which is later decoded by vp8 decoder to verify
- * frames are at least decodable.
+ * A raw yv12 stream is encoded at various settings and written to an IVF
+ * file. Encoded stream bitrate and key frame interval are checked against target values.
+ * The stream is later decoded by vp8 decoder to verify frames are decodable and to
+ * calculate PSNR values for various bitrates.
  */
-public class Vp8EncoderTest extends AndroidTestCase {
+public class Vp8EncoderTest extends Vp8CodecTestBase {
 
-    private static final String TAG = "VP8EncoderTest";
-    private static final String VP8_MIME = "video/x-vnd.on2.vp8";
-    private static final String VPX_DECODER_NAME = "OMX.google.vp8.decoder";
-    private static final String VPX_ENCODER_NAME = "OMX.google.vp8.encoder";
-    private static final String BASIC_IVF = "video_176x144_vp8_basic.ivf";
-    private static final long DEFAULT_TIMEOUT_US = 5000;
+    private static final String ENCODED_IVF_BASE = "football";
+    private static final String INPUT_YUV = null;
+    private static final String OUTPUT_YUV = SDCARD_DIR + File.separator +
+            ENCODED_IVF_BASE + "_out.yuv";
 
-    private Resources mResources;
-    private MediaCodec.BufferInfo mBufferInfo = new MediaCodec.BufferInfo();
-    private ByteBuffer[] mInputBuffers;
-    private ByteBuffer[] mOutputBuffers;
-
-    @Override
-    public void setContext(Context context) {
-        super.setContext(context);
-        mResources = mContext.getResources();
-    }
-
-     // 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;
-     }
+    // YUV stream properties.
+    private static final int WIDTH = 320;
+    private static final int HEIGHT = 240;
+    private static final int FPS = 30;
+    // Default encoding bitrate.
+    private static final int BITRATE = 400000;
+    // Default encoding bitrate mode
+    private static final int BITRATE_MODE = VIDEO_ControlRateVariable;
+    // List of bitrates used in quality and basic bitrate tests.
+    private static final int[] TEST_BITRATES_SET = { 300000, 500000, 700000, 900000 };
+    // Maximum allowed bitrate variation from the target value.
+    private static final double MAX_BITRATE_VARIATION = 0.2;
+    // Average PSNR values for reference SW VP8 codec for the above bitrates.
+    private static final double[] REFERENCE_AVERAGE_PSNR = { 33.1, 35.2, 36.6, 37.8 };
+    // Minimum PSNR values for reference SW VP8 codec for the above bitrates.
+    private static final double[] REFERENCE_MINIMUM_PSNR = { 25.9, 27.5, 28.4, 30.3 };
+    // Maximum allowed average PSNR difference of HW encoder comparing to reference SW encoder.
+    private static final double MAX_AVERAGE_PSNR_DIFFERENCE = 2;
+    // Maximum allowed minimum PSNR difference of HW encoder comparing to reference SW encoder.
+    private static final double MAX_MINIMUM_PSNR_DIFFERENCE = 4;
+    // Maximum allowed average PSNR difference of the encoder running in a looper thread with 0 ms
+    // buffer dequeue timeout comparing to the encoder running in a callee's thread with 100 ms
+    // buffer dequeue timeout.
+    private static final double MAX_ASYNC_AVERAGE_PSNR_DIFFERENCE = 0.5;
+    // Maximum allowed minimum PSNR difference of the encoder running in a looper thread
+    // comparing to the encoder running in a callee's thread.
+    private static final double MAX_ASYNC_MINIMUM_PSNR_DIFFERENCE = 2;
+    // Maximum allowed average key frame interval variation from the target value.
+    private static final int MAX_AVERAGE_KEYFRAME_INTERVAL_VARIATION = 1;
+    // Maximum allowed key frame interval variation from the target value.
+    private static final int MAX_KEYFRAME_INTERVAL_VARIATION = 3;
 
     /**
      * A basic test for VP8 encoder.
      *
-     * Encodes a raw stream with default configuration options,
+     * Encodes 9 seconds of raw stream with default configuration options,
      * and then decodes it to verify the bitstream.
+     * Also checks the average bitrate is within MAX_BITRATE_VARIATION of the target value.
      */
     public void testBasic() throws Exception {
-        if (!hasCodec(VP8_MIME)) {
+        MediaCodecInfo codecInfo = selectCodec(VP8_MIME);
+        if (codecInfo == null) {
             Log.w(TAG, "Codec " + VP8_MIME + " not supported. Return from testBasic.");
             return;
         }
 
-        encode(BASIC_IVF,
-               R.raw.video_176x144_yv12,
-               176,  // width
-               144,  // height
-               30);  // framerate
-        decode(BASIC_IVF);
+        int encodeSeconds = 9;
+
+        for (int targetBitrate : TEST_BITRATES_SET) {
+            EncoderOutputStreamParameters params = getDefaultEncodingParameters(
+                    INPUT_YUV,
+                    ENCODED_IVF_BASE,
+                    encodeSeconds,
+                    WIDTH,
+                    HEIGHT,
+                    FPS,
+                    BITRATE_MODE,
+                    targetBitrate,
+                    true);
+            ArrayList<MediaCodec.BufferInfo> bufInfo = encode(params);
+            Vp8EncodingStatistics statistics = computeEncodingStatistics(bufInfo);
+
+            assertEquals("Stream bitrate " + statistics.mAverageBitrate +
+                    " is different from the target " + targetBitrate,
+                    targetBitrate, statistics.mAverageBitrate,
+                    MAX_BITRATE_VARIATION * targetBitrate);
+
+            decode(params.outputIvfFilename, null, FPS, params.forceSwEncoder);
+        }
+    }
+
+    /**
+     * Asynchronous encoding test for VP8 encoder.
+     *
+     * Encodes 9 seconds of raw stream using synchronous and asynchronous calls.
+     * Checks the PSNR difference between the encoded and decoded output and reference yuv input
+     * does not change much for two different ways of the encoder call.
+     */
+    public void testAsyncEncoding() throws Exception {
+        MediaCodecInfo codecInfo = selectCodec(VP8_MIME);
+        if (codecInfo == null) {
+            Log.w(TAG, "Codec " + VP8_MIME + " not supported. Return from testAsyncEncoding.");
+            return;
+        }
+
+        int encodeSeconds = 9;
+
+        // First test the encoder running in a looper thread with buffer callbacks enabled.
+        boolean syncEncoding = false;
+        EncoderOutputStreamParameters params = getDefaultEncodingParameters(
+                INPUT_YUV,
+                ENCODED_IVF_BASE,
+                encodeSeconds,
+                WIDTH,
+                HEIGHT,
+                FPS,
+                BITRATE_MODE,
+                BITRATE,
+                syncEncoding);
+        ArrayList<MediaCodec.BufferInfo> bufInfos = encodeAsync(params);
+        computeEncodingStatistics(bufInfos);
+        decode(params.outputIvfFilename, OUTPUT_YUV, FPS, params.forceSwEncoder);
+        Vp8DecodingStatistics statisticsAsync = computeDecodingStatistics(
+                params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
+                params.frameWidth, params.frameHeight);
+
+
+        // Test the encoder running in a callee's thread.
+        syncEncoding = true;
+        params = getDefaultEncodingParameters(
+                INPUT_YUV,
+                ENCODED_IVF_BASE,
+                encodeSeconds,
+                WIDTH,
+                HEIGHT,
+                FPS,
+                BITRATE_MODE,
+                BITRATE,
+                syncEncoding);
+        bufInfos = encode(params);
+        computeEncodingStatistics(bufInfos);
+        decode(params.outputIvfFilename, OUTPUT_YUV, FPS, params.forceSwEncoder);
+        Vp8DecodingStatistics statisticsSync = computeDecodingStatistics(
+                params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
+                params.frameWidth, params.frameHeight);
+
+        // Check PSNR difference.
+        Log.d(TAG, "PSNR Average: Async: " + statisticsAsync.mAveragePSNR +
+                ". Sync: " + statisticsSync.mAveragePSNR);
+        Log.d(TAG, "PSNR Minimum: Async: " + statisticsAsync.mMinimumPSNR +
+                ". Sync: " + statisticsSync.mMinimumPSNR);
+        if ((Math.abs(statisticsAsync.mAveragePSNR - statisticsSync.mAveragePSNR) >
+            MAX_ASYNC_AVERAGE_PSNR_DIFFERENCE) ||
+            (Math.abs(statisticsAsync.mMinimumPSNR - statisticsSync.mMinimumPSNR) >
+            MAX_ASYNC_MINIMUM_PSNR_DIFFERENCE)) {
+            throw new RuntimeException("Difference between PSNRs for async and sync encoders");
+        }
     }
 
     /**
      * Check if MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME is honored.
      *
-     * At frame 15, request a sync frame. If one does not occur by EOF the
-     * encoder fails. The test does not verify the output stream.
+     * Encodes 9 seconds of raw stream and requests a sync frame every second (30 frames).
+     * The test does not verify the output stream.
      */
     public void testSyncFrame() throws Exception {
-        if (!hasCodec(VP8_MIME)) {
+        MediaCodecInfo codecInfo = selectCodec(VP8_MIME);
+        if (codecInfo == null) {
             Log.w(TAG, "Codec " + VP8_MIME + " not supported. Return from testSyncFrame.");
             return;
         }
 
-        encodeSyncFrame(R.raw.video_176x144_yv12,
-                        176, // width
-                        144, // height
-                        30); // framerate
+        int encodeSeconds = 9;
+
+        EncoderOutputStreamParameters params = getDefaultEncodingParameters(
+                INPUT_YUV,
+                ENCODED_IVF_BASE,
+                encodeSeconds,
+                WIDTH,
+                HEIGHT,
+                FPS,
+                BITRATE_MODE,
+                BITRATE,
+                true);
+        params.syncFrameInterval = encodeSeconds * FPS;
+        params.syncForceFrameInterval = FPS;
+        ArrayList<MediaCodec.BufferInfo> bufInfo = encode(params);
+        Vp8EncodingStatistics statistics = computeEncodingStatistics(bufInfo);
+
+        // First check if we got expected number of key frames.
+        int actualKeyFrames = statistics.mKeyFrames.size();
+        if (actualKeyFrames != encodeSeconds) {
+            throw new RuntimeException("Number of key frames " + actualKeyFrames +
+                    " is different from the expected " + encodeSeconds);
+        }
+
+        // Check key frame intervals:
+        // Average value should be within +/- 1 frame of the target value,
+        // maximum value should not be greater than target value + 3,
+        // and minimum value should not be less that target value - 3.
+        if (Math.abs(statistics.mAverageKeyFrameInterval - FPS) >
+            MAX_AVERAGE_KEYFRAME_INTERVAL_VARIATION ||
+            (statistics.mMaximumKeyFrameInterval - FPS > MAX_KEYFRAME_INTERVAL_VARIATION) ||
+            (FPS - statistics.mMinimumKeyFrameInterval > MAX_KEYFRAME_INTERVAL_VARIATION)) {
+            throw new RuntimeException(
+                    "Key frame intervals are different from the expected " + FPS);
+        }
     }
 
     /**
      * Check if MediaCodec.PARAMETER_KEY_VIDEO_BITRATE is honored.
      *
-     * Run the sample multiple times. Request periodic changes to the
-     * bitrate and ensure the encoder responds.
+     * Run the the encoder for 12 seconds. Request changes to the
+     * bitrate after 6 seconds and ensure the encoder responds.
      */
-    public void testVariableBitrate() throws Exception {
-        if (!hasCodec(VP8_MIME)) {
-            Log.w(TAG, "Codec " + VP8_MIME + " not supported. Return from testVariableBitrate.");
+    public void testDynamicBitrateChange() throws Exception {
+        MediaCodecInfo codecInfo = selectCodec(VP8_MIME);
+        if (codecInfo == null) {
+            Log.w(TAG, "Codec " + VP8_MIME + " not supported. Return from testDynamicBitrateChange.");
             return;
         }
 
-        encodeVariableBitrate(R.raw.video_176x144_yv12,
-                              176, // width
-                              144, // height
-                              30); // framerate
-    }
+        int encodeSeconds = 12;    // Encoding sequence duration in seconds.
+        int[] bitrateTargetValues = { 400000, 800000 };  // List of bitrates to test.
 
-    /**
-     * A basic check if an encoded stream is decodable.
-     *
-     * The most basic confirmation we can get about a frame
-     * being properly encoded is trying to decode it.
-     * (Especially in realtime mode encode output is non-
-     * deterministic, therefore a more thorough check like
-     * md5 sum comparison wouldn't work.)
-     *
-     * Indeed, MediaCodec will raise an IllegalStateException
-     * whenever vp8 decoder fails to decode a frame, and
-     * this test uses that fact to verify the bitstream.
-     *
-     * @param filename  The name of the IVF file containing encoded bitsream.
-     */
-    private void decode(String filename) throws Exception {
-        IvfReader ivf = null;
-        try {
-            ivf = new IvfReader(filename);
-            int frameWidth = ivf.getWidth();
-            int frameHeight = ivf.getHeight();
-            int frameCount = ivf.getFrameCount();
+        EncoderOutputStreamParameters params = getDefaultEncodingParameters(
+                INPUT_YUV,
+                ENCODED_IVF_BASE,
+                encodeSeconds,
+                WIDTH,
+                HEIGHT,
+                FPS,
+                BITRATE_MODE,
+                bitrateTargetValues[0],
+                true);
 
-            assertTrue(frameWidth > 0);
-            assertTrue(frameHeight > 0);
-            assertTrue(frameCount > 0);
+        // Number of seconds for each bitrate
+        int stepSeconds = encodeSeconds / bitrateTargetValues.length;
+        // Fill the bitrates values.
+        params.bitrateSet = new int[encodeSeconds * FPS];
+        for (int i = 0; i < bitrateTargetValues.length ; i++) {
+            Arrays.fill(params.bitrateSet,
+                    i * encodeSeconds * FPS / bitrateTargetValues.length,
+                    (i + 1) * encodeSeconds * FPS / bitrateTargetValues.length,
+                    bitrateTargetValues[i]);
+        }
 
-            MediaFormat format = MediaFormat.createVideoFormat(VP8_MIME,
-                                                               ivf.getWidth(),
-                                                               ivf.getHeight());
+        ArrayList<MediaCodec.BufferInfo> bufInfo = encode(params);
+        Vp8EncodingStatistics statistics = computeEncodingStatistics(bufInfo);
 
-            Log.d(TAG, "Creating decoder");
-            MediaCodec decoder = MediaCodec.createByCodecName(VPX_DECODER_NAME);
-            decoder.configure(format,
-                              null,  // surface
-                              null,  // crypto
-                              0);  // flags
-            decoder.start();
-
-            mInputBuffers = decoder.getInputBuffers();
-            mOutputBuffers = decoder.getOutputBuffers();
-
-            // decode loop
-            int frameIndex = 0;
-            boolean sawOutputEOS = false;
-            boolean sawInputEOS = false;
-
-            while (!sawOutputEOS) {
-                if (!sawInputEOS) {
-                    int inputBufIndex = decoder.dequeueInputBuffer(DEFAULT_TIMEOUT_US);
-                    if (inputBufIndex >= 0) {
-                        byte[] frame = ivf.readFrame(frameIndex);
-
-                        if (frameIndex == frameCount - 1) {
-                            sawInputEOS = true;
-                        }
-
-                        mInputBuffers[inputBufIndex].clear();
-                        mInputBuffers[inputBufIndex].put(frame);
-                        mInputBuffers[inputBufIndex].rewind();
-
-                        Log.d(TAG, "Decoding frame at index " + frameIndex);
-                        try {
-                            decoder.queueInputBuffer(
-                                    inputBufIndex,
-                                    0,  // offset
-                                    frame.length,
-                                    frameIndex,
-                                    sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
-                        } catch (IllegalStateException ise) {
-                            //That is all what is passed from MediaCodec in case of
-                            //decode failure.
-                            fail("Failed to decode frame at index " + frameIndex);
-                        }
-                        frameIndex++;
-                    }
-                }
-
-                int result = decoder.dequeueOutputBuffer(mBufferInfo, DEFAULT_TIMEOUT_US);
-                if (result >= 0) {
-                    int outputBufIndex = result;
-                    if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
-                        sawOutputEOS = true;
-                    }
-                    decoder.releaseOutputBuffer(outputBufIndex, false);
-                } else if (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
-                    mOutputBuffers = decoder.getOutputBuffers();
-                }
+        // Calculate actual average bitrates  for every [stepSeconds] second.
+        int[] bitrateActualValues = new int[bitrateTargetValues.length];
+        for (int i = 0; i < bitrateTargetValues.length ; i++) {
+            bitrateActualValues[i] = 0;
+            for (int j = i * stepSeconds; j < (i + 1) * stepSeconds; j++) {
+                bitrateActualValues[i] += statistics.mBitrates.get(j);
             }
-            decoder.stop();
-            decoder.release();
-        } finally {
-            if (ivf != null) {
-                ivf.close();
+            bitrateActualValues[i] /= stepSeconds;
+            Log.d(TAG, "Actual bitrate for interval #" + i + " : " + bitrateActualValues[i] +
+                    ". Target: " + bitrateTargetValues[i]);
+
+            // Compare actual bitrate values to make sure at least same increasing/decreasing
+            // order as the target bitrate values.
+            for (int j = 0; j < i; j++) {
+                long differenceTarget = bitrateTargetValues[i] - bitrateTargetValues[j];
+                long differenceActual = bitrateActualValues[i] - bitrateActualValues[j];
+                if (differenceTarget * differenceActual < 0) {
+                    throw new RuntimeException("Target bitrates: " +
+                            bitrateTargetValues[j] + " , " + bitrateTargetValues[i] +
+                            ". Actual bitrates: "
+                            + bitrateActualValues[j] + " , " + bitrateActualValues[i]);
+                }
             }
         }
     }
 
+     /**
+      * Check if encoder and decoder can run simultaneously on different threads.
+      *
+      * Encodes and decodes 9 seconds of raw stream sequentially in CBR mode,
+      * and then run parallel encoding and decoding of the same streams.
+      * Compares average bitrate and PSNR for sequential and parallel runs.
+      */
+     public void testParallelEncodingAndDecoding() throws Exception {
+         MediaCodecInfo codecInfo = selectCodec(VP8_MIME);
+         if (codecInfo == null) {
+             Log.w(TAG, "Codec " + VP8_MIME + " not supported. "
+                     + "Return from testParallelEncodingAndDecoding.");
+             return;
+         }
+
+         int encodeSeconds = 9;
+         final int[] bitrate = new int[1];
+         final double[] psnr = new double[1];
+         final Exception[] exceptionEncoder = new Exception[1];
+         final Exception[] exceptionDecoder = new Exception[1];
+         final EncoderOutputStreamParameters params = getDefaultEncodingParameters(
+                 INPUT_YUV,
+                 ENCODED_IVF_BASE,
+                 encodeSeconds,
+                 WIDTH,
+                 HEIGHT,
+                 FPS,
+                 VIDEO_ControlRateConstant,
+                 BITRATE,
+                 true);
+         final String inputIvfFilename = params.outputIvfFilename;
+
+         Runnable runEncoder = new Runnable() {
+             public void run() {
+                 try {
+                     ArrayList<MediaCodec.BufferInfo> bufInfo = encode(params);
+                     Vp8EncodingStatistics statistics = computeEncodingStatistics(bufInfo);
+                     bitrate[0] = statistics.mAverageBitrate;
+                 } catch (Exception e) {
+                     Log.e(TAG, "Encoder error: " + e.toString());
+                     exceptionEncoder[0] = e;
+                 }
+             }
+         };
+         Runnable runDecoder = new Runnable() {
+             public void run() {
+                 try {
+                     decode(inputIvfFilename, OUTPUT_YUV, FPS, params.forceSwEncoder);
+                     Vp8DecodingStatistics statistics = computeDecodingStatistics(
+                            params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
+                            params.frameWidth, params.frameHeight);
+                     psnr[0] = statistics.mAveragePSNR;
+                 } catch (Exception e) {
+                     Log.e(TAG, "Decoder error: " + e.toString());
+                     exceptionDecoder[0] = e;
+                 }
+             }
+         };
+
+         // Sequential encoding and decoding.
+         runEncoder.run();
+         if (exceptionEncoder[0] != null) {
+             throw exceptionEncoder[0];
+         }
+         int referenceBitrate = bitrate[0];
+         runDecoder.run();
+         if (exceptionDecoder[0] != null) {
+             throw exceptionDecoder[0];
+         }
+         double referencePsnr = psnr[0];
+
+         // Parallel encoding and decoding.
+         params.outputIvfFilename = SDCARD_DIR + File.separator + ENCODED_IVF_BASE + "_copy.ivf";
+         Thread threadEncoder = new Thread(runEncoder);
+         Thread threadDecoder = new Thread(runDecoder);
+         threadEncoder.start();
+         threadDecoder.start();
+         threadEncoder.join();
+         threadDecoder.join();
+         if (exceptionEncoder[0] != null) {
+             throw exceptionEncoder[0];
+         }
+         if (exceptionDecoder[0] != null) {
+             throw exceptionDecoder[0];
+         }
+
+         // Compare bitrates and PSNRs for sequential and parallel cases.
+         Log.d(TAG, "Sequential bitrate: " + referenceBitrate + ". PSNR: " + referencePsnr);
+         Log.d(TAG, "Parallel bitrate: " + bitrate[0] + ". PSNR: " + psnr[0]);
+         assertEquals("Bitrate for sequenatial encoding" + referenceBitrate +
+                 " is different from parallel encoding " + bitrate[0],
+                 referenceBitrate, bitrate[0], MAX_BITRATE_VARIATION * referenceBitrate);
+         assertEquals("PSNR for sequenatial encoding" + referencePsnr +
+                 " is different from parallel encoding " + psnr[0],
+                 referencePsnr, psnr[0], MAX_ASYNC_AVERAGE_PSNR_DIFFERENCE);
+     }
+
+
     /**
-     * A basic vp8 encode loop.
+     * Check the encoder quality for various bitrates by calculating PSNR
      *
-     * MediaCodec will raise an IllegalStateException
-     * whenever vp8 encoder fails to encode a frame.
-     *
-     * In addition to that written IVF file can be tested
-     * to be decodable in order to verify the bitstream produced.
-     *
-     * Color format of input file should be YUV420, and frameWidth,
-     * frameHeight should be supplied correctly as raw input file doesn't
-     * include any header data.
-     *
-     * @param outputFilename  The name of the IVF file to write encoded bitsream
-     * @param rawInputFd      File descriptor for the raw input file (YUV420)
-     * @param frameWidth      Frame width of input file
-     * @param frameHeight     Frame height of input file
-     * @param frameRate       Frame rate of input file in frames per second
+     * Run the the encoder for 9 seconds for each bitrate and calculate PSNR
+     * for each encoded stream.
+     * Video streams with higher bitrates should have higher PSNRs.
+     * Also compares average and minimum PSNR of HW codec with PSNR values of reference SW codec.
      */
-    private void encode(String outputFilename, int rawInputFd,
-                       int frameWidth, int frameHeight, int frameRate) throws Exception {
-        // Create a media format signifying desired output
-        MediaFormat format = MediaFormat.createVideoFormat(VP8_MIME, frameWidth, frameHeight);
-        format.setInteger(MediaFormat.KEY_BIT_RATE, 100000);
-        format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
-                          CodecCapabilities.COLOR_FormatYUV420Planar);
-        format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
+    public void testEncoderQuality() throws Exception {
+        MediaCodecInfo codecInfo = selectCodec(VP8_MIME);
+        if (codecInfo == null) {
+            Log.w(TAG, "Codec " + VP8_MIME + " not supported. Return from testEncoderQuality.");
+            return;
+        }
 
-        Log.d(TAG, "Creating encoder");
-        MediaCodec encoder;
-        encoder = MediaCodec.createByCodecName(VPX_ENCODER_NAME);
-        encoder.configure(format,
-                          null,  // surface
-                          null,  // crypto
-                          MediaCodec.CONFIGURE_FLAG_ENCODE);
-        encoder.start();
+        int encodeSeconds = 9;      // Encoding sequence duration in seconds for each bitrate.
+        double[] psnrPlatformCodecAverage = new double[TEST_BITRATES_SET.length];
+        double[] psnrPlatformCodecMin = new double[TEST_BITRATES_SET.length];
 
-        mInputBuffers = encoder.getInputBuffers();
-        mOutputBuffers = encoder.getOutputBuffers();
+        // Run platform specific encoder for different bitrates
+        // and compare PSNR of hw codec with PSNR of reference sw codec.
+        for (int i = 0; i < TEST_BITRATES_SET.length; i++) {
+            EncoderOutputStreamParameters params = getDefaultEncodingParameters(
+                    INPUT_YUV,
+                    ENCODED_IVF_BASE,
+                    encodeSeconds,
+                    WIDTH,
+                    HEIGHT,
+                    FPS,
+                    BITRATE_MODE,
+                    TEST_BITRATES_SET[i],
+                    true);
+            encode(params);
 
-        InputStream rawStream = null;
-        IvfWriter ivf = null;
+            decode(params.outputIvfFilename, OUTPUT_YUV, FPS, params.forceSwEncoder);
+            Vp8DecodingStatistics statistics = computeDecodingStatistics(
+                    params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
+                    params.frameWidth, params.frameHeight);
+            psnrPlatformCodecAverage[i] = statistics.mAveragePSNR;
+            psnrPlatformCodecMin[i] = statistics.mMinimumPSNR;
+        }
 
-        try {
-            rawStream = mResources.openRawResource(rawInputFd);
-            ivf = new IvfWriter(outputFilename, frameWidth, frameHeight);
-            // encode loop
-            long presentationTimeUs = 0;
-            int inputFrameIndex = 0;
-            int outputFrameIndex = 0;
-            boolean sawInputEOS = false;
-            boolean sawOutputEOS = false;
-
-            while (!sawOutputEOS) {
-                if (!sawInputEOS) {
-                    int inputBufIndex = encoder.dequeueInputBuffer(DEFAULT_TIMEOUT_US);
-                    if (inputBufIndex >= 0) {
-                        // YUV420 has 3 planes. Y is full size. U and V are each half size (1/4 the
-                        // pixels).
-                        int frameSize = frameWidth * frameHeight * 3 / 2;
-
-                        byte[] frame = new byte[frameSize];
-                        int bytesRead = rawStream.read(frame);
-
-                        if (bytesRead == -1) {
-                            sawInputEOS = true;
-                            bytesRead = 0;
-                        }
-
-                        mInputBuffers[inputBufIndex].clear();
-                        mInputBuffers[inputBufIndex].put(frame);
-                        mInputBuffers[inputBufIndex].rewind();
-
-                        presentationTimeUs = (inputFrameIndex * 1000000) / frameRate;
-                        Log.d(TAG, "Encoding frame at index " + inputFrameIndex);
-                        encoder.queueInputBuffer(
-                                inputBufIndex,
-                                0,  // offset
-                                bytesRead,  // size
-                                presentationTimeUs,
-                                sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
-
-                        inputFrameIndex++;
-                    }
+        // First do a sanity check - higher bitrates should results in higher PSNR.
+        for (int i = 1; i < TEST_BITRATES_SET.length ; i++) {
+            for (int j = 0; j < i; j++) {
+                double differenceBitrate = TEST_BITRATES_SET[i] - TEST_BITRATES_SET[j];
+                double differencePSNR = psnrPlatformCodecAverage[i] - psnrPlatformCodecAverage[j];
+                if (differenceBitrate * differencePSNR < 0) {
+                    throw new RuntimeException("Target bitrates: " +
+                            TEST_BITRATES_SET[j] + ", " + TEST_BITRATES_SET[i] +
+                            ". Actual PSNRs: "
+                            + psnrPlatformCodecAverage[j] + ", " + psnrPlatformCodecAverage[i]);
                 }
-
-                int result = encoder.dequeueOutputBuffer(mBufferInfo, DEFAULT_TIMEOUT_US);
-                if (result >= 0) {
-                    int outputBufIndex = result;
-                    byte[] buffer = new byte[mBufferInfo.size];
-                    mOutputBuffers[outputBufIndex].rewind();
-                    mOutputBuffers[outputBufIndex].get(buffer, 0, mBufferInfo.size);
-
-                    if ((outputFrameIndex == 0)
-                        && ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) == 0)) {
-                      throw new RuntimeException("First frame is not a sync frame.");
-
-                    }
-
-                    if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
-                        sawOutputEOS = true;
-                    } else {
-                        ivf.writeFrame(buffer, mBufferInfo.presentationTimeUs);
-                    }
-                    encoder.releaseOutputBuffer(outputBufIndex,
-                                                false);  // render
-
-                    outputFrameIndex++;
-                } else if (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
-                    mOutputBuffers = encoder.getOutputBuffers();
-                }
-            }
-
-            encoder.stop();
-            encoder.release();
-        } finally {
-            if (ivf != null) {
-                ivf.close();
-            }
-
-            if (rawStream != null) {
-                rawStream.close();
             }
         }
-    }
 
-
-    /**
-     * Request Sync Frames
-     *
-     * MediaCodec will raise an IllegalStateException
-     * whenever vp8 encoder fails to encode a frame.
-     *
-     * This presumes a file with 28 frames. Under normal circumstances there
-     * would only be one sync frame: the first one. This test will request an
-     * additional sync frame at 15 and ensure that it occurs by EOF.
-     *
-     * Color format of input file should be YUV420, and frameWidth,
-     * frameHeight should be supplied correctly as raw input file doesn't
-     * include any header data.
-     *
-     * @param rawInputFd      File descriptor for the raw input file (YUV420)
-     * @param frameWidth      Frame width of input file
-     * @param frameHeight     Frame height of input file
-     * @param frameRate       Frame rate of input file in frames per second
-     */
-    private void encodeSyncFrame(int rawInputFd, int frameWidth,
-                                 int frameHeight, int frameRate) throws Exception {
-        // Create a media format signifying desired output
-        MediaFormat format = MediaFormat.createVideoFormat(VP8_MIME, frameWidth, frameHeight);
-        format.setInteger(MediaFormat.KEY_BIT_RATE, 100000);
-        format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
-                          CodecCapabilities.COLOR_FormatYUV420Planar);
-        format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
-
-        Log.d(TAG, "Creating encoder");
-        MediaCodec encoder;
-        encoder = MediaCodec.createByCodecName(VPX_ENCODER_NAME);
-        encoder.configure(format,
-                          null,  // surface
-                          null,  // crypto
-                          MediaCodec.CONFIGURE_FLAG_ENCODE);
-        encoder.start();
-
-        mInputBuffers = encoder.getInputBuffers();
-        mOutputBuffers = encoder.getOutputBuffers();
-
-        InputStream rawStream = null;
-
-        try {
-            rawStream = mResources.openRawResource(rawInputFd);
-            // encode loop
-            long presentationTimeUs = 0;
-            int inputFrameIndex = 0;
-            boolean sawInputEOS = false;
-            boolean sawOutputEOS = false;
-            boolean syncFrameRequested = false;
-            boolean matchedSyncFrame = false;
-
-            while (!sawOutputEOS) {
-                if (!sawInputEOS) {
-                    int inputBufIndex = encoder.dequeueInputBuffer(DEFAULT_TIMEOUT_US);
-                    if (inputBufIndex >= 0) {
-                        int frameSize = frameWidth * frameHeight * 3 / 2;
-
-                        byte[] frame = new byte[frameSize];
-                        int bytesRead = rawStream.read(frame);
-
-                        if (bytesRead == -1) {
-                            sawInputEOS = true;
-                            bytesRead = 0;
-                        }
-
-                        mInputBuffers[inputBufIndex].clear();
-                        mInputBuffers[inputBufIndex].put(frame);
-                        mInputBuffers[inputBufIndex].rewind();
-
-                        if (inputFrameIndex == 15) {
-                            Log.d(TAG, "Requesting sync frame at index " + inputFrameIndex);
-                            Bundle syncFrame = new Bundle();
-                            syncFrame.putInt(MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0);
-                            encoder.setParameters(syncFrame);
-                            syncFrameRequested = true;
-                        }
-
-                        presentationTimeUs = (inputFrameIndex * 1000000) / frameRate;
-                        encoder.queueInputBuffer(
-                                inputBufIndex,
-                                0,  // offset
-                                bytesRead,  // size
-                                presentationTimeUs,
-                                sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
-
-                        inputFrameIndex++;
-                    }
-                }
-
-                int result = encoder.dequeueOutputBuffer(mBufferInfo, DEFAULT_TIMEOUT_US);
-                if (result >= 0) {
-                    if (syncFrameRequested && ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_SYNC_FRAME) != 0)) {
-                        Log.d(TAG, "Found sync frame");
-                        matchedSyncFrame = true;
-                    }
-
-                    if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
-                        sawOutputEOS = true;
-                    }
-
-                    encoder.releaseOutputBuffer(result,
-                                                false);  // render
-
-                } else if (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
-                    mOutputBuffers = encoder.getOutputBuffers();
-                }
+        // Then compare average and minimum PSNR of platform codec with reference sw codec -
+        // average PSNR for platform codec should be no more than 2 dB less than reference PSNR
+        // and minumum PSNR - no more than 4 dB less than reference minimum PSNR.
+        // These PSNR difference numbers are arbitrary for now, will need further estimation
+        // when more devices with hw VP8 codec will appear.
+        for (int i = 0; i < TEST_BITRATES_SET.length ; i++) {
+            Log.d(TAG, "Bitrate " + TEST_BITRATES_SET[i]);
+            Log.d(TAG, "Reference: Average: " + REFERENCE_AVERAGE_PSNR[i] + ". Minimum: " +
+                    REFERENCE_MINIMUM_PSNR[i]);
+            Log.d(TAG, "Platform:  Average: " + psnrPlatformCodecAverage[i] + ". Minimum: " +
+                    psnrPlatformCodecMin[i]);
+            if (psnrPlatformCodecAverage[i] < REFERENCE_AVERAGE_PSNR[i] -
+                    MAX_AVERAGE_PSNR_DIFFERENCE) {
+                throw new RuntimeException("Low average PSNR " + psnrPlatformCodecAverage[i] +
+                        " comparing to reference PSNR " + REFERENCE_AVERAGE_PSNR[i] +
+                        " for bitrate " + TEST_BITRATES_SET[i]);
             }
-
-            if (!matchedSyncFrame) {
-                throw new RuntimeException("Requested sync frame did not occur");
-            }
-
-            encoder.stop();
-            encoder.release();
-        } finally {
-            if (rawStream != null) {
-                rawStream.close();
-            }
-        }
-    }
-
-
-    /**
-     * Adjust bitrate
-     *
-     * MediaCodec will raise an IllegalStateException
-     * whenever vp8 encoder fails to encode a frame.
-     *
-     * Encode the file three times: once at the initial bitrate, once at an
-     * increased bitrate, and once at a decreased bitrate. Record the frame
-     * sizes that are returned and verify a strict ordering.
-     *
-     * Color format of input file should be YUV420, and frameWidth,
-     * frameHeight should be supplied correctly as raw input file doesn't
-     * include any header data.
-     *
-     * @param rawInputFd      File descriptor for the raw input file (YUV420)
-     * @param frameWidth      Frame width of input file
-     * @param frameHeight     Frame height of input file
-     * @param frameRate       Frame rate of input file in frames per second
-     */
-    private void encodeVariableBitrate(int rawInputFd, int frameWidth,
-                                       int frameHeight, int frameRate) throws Exception {
-        // Create a media format signifying desired output
-        MediaFormat format = MediaFormat.createVideoFormat(VP8_MIME, frameWidth, frameHeight);
-        format.setInteger(MediaFormat.KEY_BIT_RATE, 75000);
-        format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
-                          CodecCapabilities.COLOR_FormatYUV420Planar);
-        format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
-
-        Log.d(TAG, "Creating encoder");
-        MediaCodec encoder;
-        encoder = MediaCodec.createByCodecName(VPX_ENCODER_NAME);
-        encoder.configure(format,
-                          null,  // surface
-                          null,  // crypto
-                          MediaCodec.CONFIGURE_FLAG_ENCODE);
-        encoder.start();
-
-        mInputBuffers = encoder.getInputBuffers();
-        mOutputBuffers = encoder.getOutputBuffers();
-
-        InputStream rawStream = null;
-
-        int iteration = 0;
-        int[] bits = new int[100];
-
-        try {
-            rawStream = mResources.openRawResource(rawInputFd);
-            /* Doc says this is not the default:
-             * http://developer.android.com/reference/java/io/InputStream.html#markSupported()
-             * but it returns true so using .reset() instead of close/open
-             */
-            if (rawStream.markSupported()) Log.d(TAG, "Stream marking supported");
-            rawStream.mark(1000000);
-
-            // encode loop
-            long presentationTimeUs = 0;
-            int inputFrameIndex = 0;
-            int outputFrameIndex = 0;
-            boolean sawInputEOS = false;
-            boolean sawOutputEOS = false;
-
-            while (!sawOutputEOS) {
-                if (!sawInputEOS) {
-                    int inputBufIndex = encoder.dequeueInputBuffer(DEFAULT_TIMEOUT_US);
-                    if (inputBufIndex >= 0) {
-                        int frameSize = frameWidth * frameHeight * 3 / 2;
-
-                        byte[] frame = new byte[frameSize];
-                        int bytesRead = rawStream.read(frame);
-
-                        if (bytesRead == -1) {
-                            if (iteration < 2) {
-                                rawStream.reset();
-                                Bundle bitrate = new Bundle();
-                                if (iteration == 0) {
-                                    bitrate.putInt(MediaCodec.PARAMETER_KEY_VIDEO_BITRATE, 150000);
-                                    Log.d(TAG, "Setting bitrate to 150000");
-                                } else {
-                                    bitrate.putInt(MediaCodec.PARAMETER_KEY_VIDEO_BITRATE, 25000);
-                                    Log.d(TAG, "Setting bitrate to 25000");
-                                }
-                                encoder.setParameters(bitrate);
-
-                                iteration++;
-                                continue;
-                            } else {
-                                sawInputEOS = true;
-                                bytesRead = 0;
-                            }
-                        }
-
-                        mInputBuffers[inputBufIndex].clear();
-                        mInputBuffers[inputBufIndex].put(frame);
-                        mInputBuffers[inputBufIndex].rewind();
-
-                        presentationTimeUs = (inputFrameIndex * 1000000) / frameRate;
-                        encoder.queueInputBuffer(
-                                inputBufIndex,
-                                0,  // offset
-                                bytesRead,  // size
-                                presentationTimeUs,
-                                sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
-
-                        inputFrameIndex++;
-                    }
-                }
-
-                int result = encoder.dequeueOutputBuffer(mBufferInfo, DEFAULT_TIMEOUT_US);
-                if (result >= 0) {
-
-                    bits[outputFrameIndex] = mBufferInfo.size;
-
-                    if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
-                        sawOutputEOS = true;
-                    }
-
-                    encoder.releaseOutputBuffer(result,
-                                                false);  // render
-
-                    outputFrameIndex++;
-
-                } else if (result == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
-                    mOutputBuffers = encoder.getOutputBuffers();
-                }
-            }
-
-            // 29 frames per run
-            int i;
-            int sum = 0;
-            int frames = 29;
-            for(i = 0; i < frames; i++)
-              sum += bits[i];
-            int midBitrateAvg = sum / frames;
-
-            sum = 0;
-            for(; i < frames * 2; i++)
-              sum += bits[i];
-            int highBitrateAvg = sum / frames;
-
-            sum = 0;
-            for(; i < frames * 3; i++)
-              sum += bits[i];
-            int lowBitrateAvg = sum / frames;
-
-            // For the given bitrates we expect mid ~= 350, high ~= 575 and low ~= 150
-            // bytes per frame
-            if ((midBitrateAvg + 100) > highBitrateAvg)
-                throw new RuntimeException("Bitrate did not increase when requesting higher bitrate");
-            if ((lowBitrateAvg + 100) > midBitrateAvg)
-                throw new RuntimeException("Bitrate did not decrease when requesting lower bitrate");
-
-
-            encoder.stop();
-            encoder.release();
-        } finally {
-            if (rawStream != null) {
-                rawStream.close();
+            if (psnrPlatformCodecMin[i] < REFERENCE_MINIMUM_PSNR[i] -
+                    MAX_MINIMUM_PSNR_DIFFERENCE) {
+                throw new RuntimeException("Low minimum PSNR " + psnrPlatformCodecMin[i] +
+                        " comparing to sw PSNR " + REFERENCE_MINIMUM_PSNR[i] +
+                        " for bitrate " + TEST_BITRATES_SET[i]);
             }
         }
     }
 }
+
diff --git a/tests/tests/mediastress/Android.mk b/tests/tests/mediastress/Android.mk
index 9f43597..5bb23d0 100644
--- a/tests/tests/mediastress/Android.mk
+++ b/tests/tests/mediastress/Android.mk
@@ -20,7 +20,8 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
 
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner ctsdeviceutil
 
diff --git a/tests/tests/mediastress/AndroidManifest.xml b/tests/tests/mediastress/AndroidManifest.xml
index 931a774..9d48c8c 100644
--- a/tests/tests/mediastress/AndroidManifest.xml
+++ b/tests/tests/mediastress/AndroidManifest.xml
@@ -39,8 +39,11 @@
         <activity android:name="android.mediastress.cts.NativeMediaActivity"
                   android:label="NativeMedia" />
     </application>
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
             android:targetPackage="com.android.cts.mediastress"
-            android:label="Media stress tests InstrumentationRunner" />
+            android:label="Media stress tests InstrumentationRunner" >
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/HEVCR1080pAacLongPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR1080pAacLongPlayerTest.java
new file mode 100644
index 0000000..e8a92e0
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR1080pAacLongPlayerTest.java
@@ -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.
+ */
+
+package android.mediastress.cts;
+
+import android.media.CamcorderProfile;
+import android.media.MediaRecorder.AudioEncoder;
+import android.media.MediaRecorder.VideoEncoder;
+
+public class HEVCR1080pAacLongPlayerTest extends MediaPlayerStressTest {
+    private static final String VIDEO_PATH_MIDDLE = "bbb_full/1920x1080/mp4_libx265_libfaac/";
+    private final String[] mMedias = {
+        "bbb_full.ffmpeg.1920x1080.mp4.libx265_6500kbps_30fps.libfaac_stereo_128kbps_48000Hz.mp4"
+    };
+
+    public HEVCR1080pAacLongPlayerTest() {
+        super(CamcorderProfile.QUALITY_1080P, VideoEncoder.H264, AudioEncoder.AAC);
+    }
+
+    public void testPlay00() throws Exception {
+        doTestVideoPlaybackLong(0);
+    }
+
+    @Override
+    protected String getFullVideoClipName(int mediaNumber) {
+        return VIDEO_TOP_DIR + VIDEO_PATH_MIDDLE + mMedias[mediaNumber];
+    }
+
+}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/HEVCR1080pAacRepeatedPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR1080pAacRepeatedPlayerTest.java
new file mode 100644
index 0000000..7ce3c3a
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR1080pAacRepeatedPlayerTest.java
@@ -0,0 +1,41 @@
+/*
+ * 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.mediastress.cts;
+
+import android.media.CamcorderProfile;
+import android.media.MediaRecorder.AudioEncoder;
+import android.media.MediaRecorder.VideoEncoder;
+
+public class HEVCR1080pAacRepeatedPlayerTest extends MediaPlayerStressTest {
+    private static final String VIDEO_PATH_MIDDLE = "bbb_short/1920x1080/mp4_libx265_libfaac/";
+    private final String[] mMedias = {
+        "bbb_short.fmpeg.1920x1080.mp4.libx265_6500kbps_30fps.libfaac_stereo_128kbps_48000hz.mp4",
+    };
+
+    public HEVCR1080pAacRepeatedPlayerTest() {
+        super(CamcorderProfile.QUALITY_1080P, VideoEncoder.H264, AudioEncoder.AAC);
+    }
+
+    public void testPlay00() throws Exception {
+        doTestVideoPlaybackRepeated(0);
+    }
+
+    @Override
+    protected String getFullVideoClipName(int mediaNumber) {
+        return VIDEO_TOP_DIR + VIDEO_PATH_MIDDLE + mMedias[mediaNumber];
+    }
+}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/HEVCR1080pAacShortPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR1080pAacShortPlayerTest.java
new file mode 100644
index 0000000..1d12b8c
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR1080pAacShortPlayerTest.java
@@ -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.
+ */
+
+package android.mediastress.cts;
+
+import android.media.CamcorderProfile;
+import android.media.MediaRecorder.AudioEncoder;
+import android.media.MediaRecorder.VideoEncoder;
+
+public class HEVCR1080pAacShortPlayerTest extends MediaPlayerStressTest {
+    private static final String VIDEO_PATH_MIDDLE = "bbb_short/1920x1080/mp4_libx265_libfaac/";
+    private final String[] mMedias = {
+        "bbb_short.fmpeg.1920x1080.mp4.libx265_6500kbps_30fps.libfaac_stereo_128kbps_48000hz.mp4",
+        "bbb_short.fmpeg.1920x1080.mp4.libx265_1140kbps_30fps.libfaac_stereo_128kbps_48000hz.mp4",
+        "bbb_short.fmpeg.1920x1080.mp4.libx265_3250kbps_30fps.libfaac_stereo_128kbps_48000hz.mp4"
+    };
+
+    public HEVCR1080pAacShortPlayerTest() {
+        super(CamcorderProfile.QUALITY_1080P, VideoEncoder.H264, AudioEncoder.AAC);
+    }
+
+    public void testPlay00() throws Exception {
+        doTestVideoPlaybackShort(0);
+    }
+
+    public void testPlay01() throws Exception {
+        doTestVideoPlaybackShort(1);
+    }
+
+    public void testPlay02() throws Exception {
+        doTestVideoPlaybackShort(2);
+    }
+
+    @Override
+    protected String getFullVideoClipName(int mediaNumber) {
+        return VIDEO_TOP_DIR + VIDEO_PATH_MIDDLE + mMedias[mediaNumber];
+    }
+
+}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/HEVCR480pAacLongPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR480pAacLongPlayerTest.java
new file mode 100644
index 0000000..e54c51f
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR480pAacLongPlayerTest.java
@@ -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.
+ */
+
+package android.mediastress.cts;
+
+import android.media.CamcorderProfile;
+import android.media.MediaRecorder.AudioEncoder;
+import android.media.MediaRecorder.VideoEncoder;
+
+public class HEVCR480pAacLongPlayerTest extends MediaPlayerStressTest {
+    private static final String VIDEO_PATH_MIDDLE = "bbb_full/720x480/mp4_libx265_libfaac/";
+    private final String[] mMedias = {
+        "bbb_full.ffmpeg.720x480.mp4.libx265_325kbps_24fps.libfaac_stereo_128kbps_48000Hz.mp4"
+    };
+
+    public HEVCR480pAacLongPlayerTest() {
+        super(CamcorderProfile.QUALITY_480P, VideoEncoder.H264, AudioEncoder.AAC);
+    }
+
+    public void testPlay00() throws Exception {
+        doTestVideoPlaybackLong(0);
+    }
+
+    @Override
+    protected String getFullVideoClipName(int mediaNumber) {
+        return VIDEO_TOP_DIR + VIDEO_PATH_MIDDLE + mMedias[mediaNumber];
+    }
+
+}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/HEVCR480pAacShortPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR480pAacShortPlayerTest.java
new file mode 100644
index 0000000..2b64abd
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR480pAacShortPlayerTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.mediastress.cts;
+
+import android.media.CamcorderProfile;
+import android.media.MediaRecorder.AudioEncoder;
+import android.media.MediaRecorder.VideoEncoder;
+
+public class HEVCR480pAacShortPlayerTest extends MediaPlayerStressTest {
+    private static final String VIDEO_PATH_MIDDLE = "bbb_short/720x480/mp4_libx265_libfaac/";
+    private final String[] mMedias = {
+        "bbb_short.fmpeg.720x480.mp4.libx265_650kbps_24fps.libfaac_stereo_128kbps_48000hz.mp4",
+        "bbb_short.fmpeg.720x480.mp4.libx265_650kbps_30fps.libfaac_stereo_128kbps_48000hz.mp4",
+        "bbb_short.fmpeg.720x480.mp4.libx265_880kbps_24fps.libfaac_stereo_128kbps_48000hz.mp4",
+        "bbb_short.fmpeg.720x480.mp4.libx265_880kbps_30fps.libfaac_stereo_128kbps_48000hz.mp4",
+        "bbb_short.fmpeg.720x480.mp4.libx265_325kbps_24fps.libfaac_stereo_128kbps_48000hz.mp4",
+        "bbb_short.fmpeg.720x480.mp4.libx265_325kbps_30fps.libfaac_stereo_128kbps_48000hz.mp4"
+    };
+
+    public HEVCR480pAacShortPlayerTest() {
+        super(CamcorderProfile.QUALITY_480P, VideoEncoder.H264, AudioEncoder.AAC);
+    }
+
+    public void testPlay00() throws Exception {
+        doTestVideoPlaybackShort(0);
+    }
+
+    public void testPlay01() throws Exception {
+        doTestVideoPlaybackShort(1);
+    }
+
+    public void testPlay02() throws Exception {
+        doTestVideoPlaybackShort(2);
+    }
+
+    public void testPlay03() throws Exception {
+        doTestVideoPlaybackShort(3);
+    }
+
+    public void testPlay04() throws Exception {
+        doTestVideoPlaybackShort(4);
+    }
+
+    public void testPlay05() throws Exception {
+        doTestVideoPlaybackShort(5);
+    }
+
+    @Override
+    protected String getFullVideoClipName(int mediaNumber) {
+        return VIDEO_TOP_DIR + VIDEO_PATH_MIDDLE + mMedias[mediaNumber];
+    }
+
+}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/HEVCR480x360AacShortPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR480x360AacShortPlayerTest.java
new file mode 100644
index 0000000..78139ce
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR480x360AacShortPlayerTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.mediastress.cts;
+
+public class HEVCR480x360AacShortPlayerTest extends MediaPlayerStressTest {
+    private static final String VIDEO_PATH_MIDDLE = "bbb_short/480x360/mp4_libx265_libfaac/";
+    private final String[] mMedias = {
+        "bbb_short.fmpeg.480x360.mp4.libx265_650kbps_24fps.libfaac_stereo_128kbps_48000hz.mp4",
+        "bbb_short.fmpeg.480x360.mp4.libx265_650kbps_30fps.libfaac_stereo_128kbps_48000hz.mp4",
+        "bbb_short.fmpeg.480x360.mp4.libx265_880kbps_24fps.libfaac_stereo_128kbps_48000hz.mp4",
+        "bbb_short.fmpeg.480x360.mp4.libx265_880kbps_30fps.libfaac_stereo_128kbps_48000hz.mp4",
+        "bbb_short.fmpeg.480x360.mp4.libx265_325kbps_24fps.libfaac_stereo_128kbps_48000hz.mp4",
+        "bbb_short.fmpeg.480x360.mp4.libx265_325kbps_30fps.libfaac_stereo_128kbps_48000hz.mp4"
+    };
+
+    public void testPlay00() throws Exception {
+        doTestVideoPlaybackShort(0);
+    }
+
+    public void testPlay01() throws Exception {
+        doTestVideoPlaybackShort(1);
+    }
+
+    public void testPlay02() throws Exception {
+        doTestVideoPlaybackShort(2);
+    }
+
+    public void testPlay03() throws Exception {
+        doTestVideoPlaybackShort(3);
+    }
+
+    public void testPlay04() throws Exception {
+        doTestVideoPlaybackShort(4);
+    }
+
+    public void testPlay05() throws Exception {
+        doTestVideoPlaybackShort(5);
+    }
+
+    @Override
+    protected String getFullVideoClipName(int mediaNumber) {
+        return VIDEO_TOP_DIR + VIDEO_PATH_MIDDLE + mMedias[mediaNumber];
+    }
+
+}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/HEVCR720pAacLongPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR720pAacLongPlayerTest.java
new file mode 100644
index 0000000..540f78a
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR720pAacLongPlayerTest.java
@@ -0,0 +1,47 @@
+/*
+ * 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.mediastress.cts;
+
+import android.media.CamcorderProfile;
+import android.media.MediaRecorder.AudioEncoder;
+import android.media.MediaRecorder.VideoEncoder;
+
+public class HEVCR720pAacLongPlayerTest extends MediaPlayerStressTest {
+    private static final String VIDEO_PATH_MIDDLE = "bbb_full/1280x720/mp4_libx265_libfaac/";
+    private final String[] mMedias = {
+        "bbb_full.ffmpeg.1280x720.mp4.libx265_880kbps_24fps.libfaac_stereo_128kbps_48000Hz.mp4",
+        "bbb_full.ffmpeg.1280x720.mp4.libx265_1140kbps_30fps.libfaac_stereo_128kbps_48000Hz.mp4"
+    };
+
+    public HEVCR720pAacLongPlayerTest() {
+        super(CamcorderProfile.QUALITY_720P, VideoEncoder.H264, AudioEncoder.AAC);
+    }
+
+    public void testPlay00() throws Exception {
+        doTestVideoPlaybackLong(0);
+    }
+
+    public void testPlay01() throws Exception {
+        doTestVideoPlaybackLong(1);
+    }
+
+    @Override
+    protected String getFullVideoClipName(int mediaNumber) {
+        return VIDEO_TOP_DIR + VIDEO_PATH_MIDDLE + mMedias[mediaNumber];
+    }
+
+}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/HEVCR720pAacShortPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR720pAacShortPlayerTest.java
new file mode 100644
index 0000000..dd93dfc
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR720pAacShortPlayerTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.mediastress.cts;
+
+import android.media.CamcorderProfile;
+import android.media.MediaRecorder.AudioEncoder;
+import android.media.MediaRecorder.VideoEncoder;
+
+public class HEVCR720pAacShortPlayerTest extends MediaPlayerStressTest {
+    private static final String VIDEO_PATH_MIDDLE = "bbb_short/1280x720/mp4_libx265_libfaac/";
+    private final String[] mMedias = {
+        "bbb_short.fmpeg.1280x720.mp4.libx265_325kbps_24fps.libfaac_stereo_128kbps_48000hz.mp4",
+        "bbb_short.fmpeg.1280x720.mp4.libx265_325kbps_30fps.libfaac_stereo_128kbps_48000hz.mp4",
+        "bbb_short.fmpeg.1280x720.mp4.libx265_650kbps_24fps.libfaac_stereo_128kbps_48000hz.mp4",
+        "bbb_short.fmpeg.1280x720.mp4.libx265_650kbps_30fps.libfaac_stereo_128kbps_48000hz.mp4",
+        "bbb_short.fmpeg.1280x720.mp4.libx265_880kbps_24fps.libfaac_stereo_128kbps_48000hz.mp4",
+        "bbb_short.fmpeg.1280x720.mp4.libx265_880kbps_30fps.libfaac_stereo_128kbps_48000hz.mp4",
+        "bbb_short.fmpeg.1280x720.mp4.libx265_1140kbps_30fps.libfaac_stereo_128kbps_48000hz.mp4",
+        "bbb_short.fmpeg.1280x720.mp4.libx265_3250kbps_30fps.libfaac_stereo_128kbps_48000hz.mp4",
+        "bbb_short.fmpeg.1280x720.mp4.libx265_6500kbps_30fps.libfaac_stereo_128kbps_48000hz.mp4"
+    };
+
+    public HEVCR720pAacShortPlayerTest() {
+        super(CamcorderProfile.QUALITY_720P, VideoEncoder.H264, AudioEncoder.AAC);
+    }
+
+    public void testPlay00() throws Exception {
+        doTestVideoPlaybackShort(0);
+    }
+
+    public void testPlay01() throws Exception {
+        doTestVideoPlaybackShort(1);
+    }
+
+    public void testPlay02() throws Exception {
+        doTestVideoPlaybackShort(2);
+    }
+
+    public void testPlay03() throws Exception {
+        doTestVideoPlaybackShort(3);
+    }
+
+    public void testPlay04() throws Exception {
+        doTestVideoPlaybackShort(4);
+    }
+
+    public void testPlay05() throws Exception {
+        doTestVideoPlaybackShort(5);
+    }
+
+    public void testPlay06() throws Exception {
+        doTestVideoPlaybackShort(6);
+    }
+
+    public void testPlay07() throws Exception {
+        doTestVideoPlaybackShort(7);
+    }
+
+    public void testPlay08() throws Exception {
+        doTestVideoPlaybackShort(8);
+    }
+
+    @Override
+    protected String getFullVideoClipName(int mediaNumber) {
+        return VIDEO_TOP_DIR + VIDEO_PATH_MIDDLE + mMedias[mediaNumber];
+    }
+
+}
diff --git a/tests/tests/nativemedia/sl/Android.mk b/tests/tests/nativemedia/sl/Android.mk
index 49ccb10..48b816c 100644
--- a/tests/tests/nativemedia/sl/Android.mk
+++ b/tests/tests/nativemedia/sl/Android.mk
@@ -3,12 +3,16 @@
 LOCAL_PATH:= $(call my-dir)
 
 test_executable := NativeMediaTest_SL
+list_executable := $(test_executable)_list
 
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := $(test_executable)
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativetest
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
 
 LOCAL_C_INCLUDES := \
     bionic \
@@ -33,3 +37,19 @@
 
 LOCAL_CTS_TEST_PACKAGE := android.nativemedia.sl
 include $(BUILD_CTS_EXECUTABLE)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := $(list_executable)
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := \
+    src/SLObjectCreationTest.cpp
+
+LOCAL_CFLAGS := \
+    -DBUILD_ONLY \
+
+LOCAL_SHARED_LIBRARIES := \
+    liblog \
+
+include $(BUILD_HOST_NATIVE_TEST)
diff --git a/tests/tests/nativemedia/sl/NativeMediaTest_SL_list.txt b/tests/tests/nativemedia/sl/NativeMediaTest_SL_list.txt
deleted file mode 100644
index c5d17a3..0000000
--- a/tests/tests/nativemedia/sl/NativeMediaTest_SL_list.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-SLObjectCreationTest.
-  testEngineCreation
-  testOutputMixCreation
-  testAudioPlayerFromUriCreation
-  testAudioPlayerFromFdCreation
-  testAudioPlayerFromPcmBqCreation
-  testAudioPlayerFromTsAbqCreation
-  testAudioPlayerFromUriToPcmBqCreation
-  testAudioPlayerFromFdToPcmBqCreation
-  testAudioPlayerFromAdtsAbqToPcmBqCreation
-  testAudioRecorderCreation
diff --git a/tests/tests/nativemedia/xa/Android.mk b/tests/tests/nativemedia/xa/Android.mk
index f2c0ca0..ace315a 100644
--- a/tests/tests/nativemedia/xa/Android.mk
+++ b/tests/tests/nativemedia/xa/Android.mk
@@ -3,12 +3,16 @@
 LOCAL_PATH:= $(call my-dir)
 
 test_executable := NativeMediaTest_XA
+list_executable := $(test_executable)_list
 
 include $(CLEAR_VARS)
 
 LOCAL_MODULE:= $(test_executable)
 LOCAL_MODULE_TAGS := optional
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativetest
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
 
 LOCAL_C_INCLUDES := \
     bionic \
@@ -32,3 +36,19 @@
 
 LOCAL_CTS_TEST_PACKAGE := android.nativemedia.xa
 include $(BUILD_CTS_EXECUTABLE)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := $(list_executable)
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := \
+    src/XAObjectCreationTest.cpp
+
+LOCAL_CFLAGS := \
+    -DBUILD_ONLY \
+
+LOCAL_SHARED_LIBRARIES := \
+    liblog \
+
+include $(BUILD_HOST_NATIVE_TEST)
diff --git a/tests/tests/nativemedia/xa/NativeMediaTest_XA_list.txt b/tests/tests/nativemedia/xa/NativeMediaTest_XA_list.txt
deleted file mode 100644
index af8bfad..0000000
--- a/tests/tests/nativemedia/xa/NativeMediaTest_XA_list.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-XAObjectCreationTest.
-  testEngineCreation
-  testOutputMixCreation
diff --git a/tests/tests/nativeopengl/Android.mk b/tests/tests/nativeopengl/Android.mk
index dd19548..d2192ad 100644
--- a/tests/tests/nativeopengl/Android.mk
+++ b/tests/tests/nativeopengl/Android.mk
@@ -24,8 +24,8 @@
 # When built, explicitly put it in the data partition.
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-# All tests should include android.test.runner.
-LOCAL_JAVA_LIBRARIES := android.test.runner
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
 
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner ctswrappedgtest
 
diff --git a/tests/tests/ndef/Android.mk b/tests/tests/ndef/Android.mk
index 70853d9..ba78f29 100644
--- a/tests/tests/ndef/Android.mk
+++ b/tests/tests/ndef/Android.mk
@@ -24,9 +24,6 @@
 # When built, explicitly put it in the data partition.
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-# All tests should include android.test.runner.
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/ndef/AndroidManifest.xml b/tests/tests/ndef/AndroidManifest.xml
index a7ebb6e..e0244e1 100644
--- a/tests/tests/ndef/AndroidManifest.xml
+++ b/tests/tests/ndef/AndroidManifest.xml
@@ -23,9 +23,12 @@
     </application>
 
     <!-- This is a self-instrumenting test package. -->
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.cts.ndef"
-                     android:label="CTS tests of NDEF data classes"/>
+                     android:label="CTS tests of NDEF data classes">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/tests/net/Android.mk b/tests/tests/net/Android.mk
index 82abd62..46d4d81 100644
--- a/tests/tests/net/Android.mk
+++ b/tests/tests/net/Android.mk
@@ -21,7 +21,10 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner voip-common
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
+LOCAL_JAVA_LIBRARIES := voip-common conscrypt
 
 LOCAL_JNI_SHARED_LIBRARIES := libnativedns_jni
 
@@ -33,7 +36,7 @@
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestserver ctsdeviceutil ctstestrunner \
                                core-tests-support
 
-# uncomment when dalvik.annotation.Test* are removed or part of SDK
+# uncomment when b/13249961 is fixed
 #LOCAL_SDK_VERSION := current
 
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/net/AndroidManifest.xml b/tests/tests/net/AndroidManifest.xml
index ade6728..652262d 100644
--- a/tests/tests/net/AndroidManifest.xml
+++ b/tests/tests/net/AndroidManifest.xml
@@ -32,9 +32,12 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.cts.net"
-                     android:label="CTS tests of android.net"/>
+                     android:label="CTS tests of android.net">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java
index 5656119..d79ecdd 100644
--- a/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -16,7 +16,6 @@
 
 package android.net.cts;
 
-
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -31,6 +30,8 @@
 import android.test.AndroidTestCase;
 import android.util.Log;
 
+import com.android.internal.telephony.PhoneConstants;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -115,34 +116,9 @@
     }
 
     public void testSetNetworkPreference() {
-        // verify swtiching between two default networks - need to connectable networks though
-        // could use test and whatever the current active network is
-        int originalPref = mCm.getNetworkPreference();
-        int currentPref = originalPref;
-        for (int type = -1; type <= ConnectivityManager.MAX_NETWORK_TYPE+1; type++) {
-            mCm.setNetworkPreference(type);
-            NetworkConfig c = mNetworks.get(type);
-            boolean expectWorked = (c != null && c.isDefault());
-            int totalSleep = 0;
-            int foundType = ConnectivityManager.TYPE_NONE;
-            while (totalSleep < 1000) {
-                try {
-                    Thread.currentThread().sleep(100);
-                } catch (InterruptedException e) {}
-                totalSleep += 100;
-                foundType = mCm.getNetworkPreference();
-                if (currentPref != foundType) break;
-            }
-            if (expectWorked) {
-                assertTrue("We should have been able to switch prefered type " + type,
-                        foundType == type);
-            } else {
-                assertTrue("We should not have been able to switch type " + type,
-                        foundType != type);
-            }
-            currentPref = foundType;
-        }
-        mCm.setNetworkPreference(originalPref);
+        // getNetworkPreference() and setNetworkPreference() are both deprecated so they do
+        // not preform any action.  Verify they are at least still callable.
+        mCm.setNetworkPreference(mCm.getNetworkPreference());
     }
 
     public void testGetActiveNetworkInfo() {
@@ -194,13 +170,13 @@
         final String invalidateFeature = "invalidateFeature";
         final String mmsFeature = "enableMMS";
         final int failureCode = -1;
-        final int wifiOnlyStartFailureCode = 3;
-        final int wifiOnlyStopFailureCode = 1;
+        final int wifiOnlyStartFailureCode = PhoneConstants.APN_REQUEST_FAILED;
+        final int wifiOnlyStopFailureCode = -1;
 
         NetworkInfo ni = mCm.getNetworkInfo(TYPE_MOBILE);
         if (ni != null) {
-            assertEquals(failureCode, mCm.startUsingNetworkFeature(TYPE_MOBILE,
-                    invalidateFeature));
+            assertEquals(PhoneConstants.APN_REQUEST_FAILED,
+                    mCm.startUsingNetworkFeature(TYPE_MOBILE, invalidateFeature));
             assertEquals(failureCode, mCm.stopUsingNetworkFeature(TYPE_MOBILE,
                     invalidateFeature));
         } else {
@@ -212,8 +188,8 @@
 
         ni = mCm.getNetworkInfo(TYPE_WIFI);
         if (ni != null) {
-            // Should return failure(-1) because MMS is not supported on WIFI.
-            assertEquals(failureCode, mCm.startUsingNetworkFeature(TYPE_WIFI,
+            // Should return failure because MMS is not supported on WIFI.
+            assertEquals(PhoneConstants.APN_REQUEST_FAILED, mCm.startUsingNetworkFeature(TYPE_WIFI,
                     mmsFeature));
             assertEquals(failureCode, mCm.stopUsingNetworkFeature(TYPE_WIFI,
                     mmsFeature));
diff --git a/tests/tests/net/src/android/net/cts/MultinetworkTest.java b/tests/tests/net/src/android/net/cts/MultinetworkTest.java
new file mode 100644
index 0000000..256c030
--- /dev/null
+++ b/tests/tests/net/src/android/net/cts/MultinetworkTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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.net.cts;
+
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
+import android.system.StructStat;
+import android.test.AndroidTestCase;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.IOException;
+
+/**
+ * Tests for multinetwork functionality.
+ */
+public class MultinetworkTest extends AndroidTestCase {
+
+    // Global sysctls. Must be present and set to 1.
+    private static final String[] GLOBAL_SYSCTLS = {
+        "/proc/sys/net/ipv4/fwmark_reflect",
+        "/proc/sys/net/ipv6/fwmark_reflect",
+        "/proc/sys/net/ipv4/tcp_fwmark_accept",
+    };
+
+    // Per-interface IPv6 autoconf sysctls.
+    private static final String IPV6_SYSCTL_DIR = "/proc/sys/net/ipv6/conf";
+    private static final String AUTOCONF_SYSCTL = "accept_ra_rt_table";
+
+    // Expected mode, UID, and GID of sysctl files.
+    private static final int SYSCTL_MODE = 0100644;
+    private static final int SYSCTL_UID = 0;
+    private static final int SYSCTL_GID = 0;
+
+    private void checkSysctlPermissions(String fileName) throws ErrnoException {
+        StructStat stat = Os.stat(fileName);
+        assertEquals("mode of " + fileName + ":", SYSCTL_MODE, stat.st_mode);
+        assertEquals("UID of " + fileName + ":", SYSCTL_UID, stat.st_uid);
+        assertEquals("GID of " + fileName + ":", SYSCTL_GID, stat.st_gid);
+    }
+
+    private void assertLess(String what, int a, int b) {
+        assertTrue(what + " expected < " + b + " but was: " + a, a < b);
+    }
+
+    private String readFile(String fileName) throws ErrnoException, IOException {
+        byte[] buf = new byte[1024];
+        FileDescriptor fd = Os.open(fileName, 0, OsConstants.O_RDONLY);
+        int bytesRead = Os.read(fd, buf, 0, buf.length);
+        assertLess("length of " + fileName + ":", bytesRead, buf.length);
+        return new String(buf);
+    }
+
+    /**
+     * Checks that the sysctls for multinetwork kernel features are present and
+     * enabled. The necessary kernel commits are:
+     *
+     * Mainline Linux:
+     *   e110861 net: add a sysctl to reflect the fwmark on replies
+     *   1b3c61d net: Use fwmark reflection in PMTU discovery.
+     *   84f39b0 net: support marking accepting TCP sockets
+     *
+     * Common Android tree (e.g., 3.10):
+     *   a03f539 net: ipv6: autoconf routes into per-device tables
+     */
+     public void testProcFiles() throws ErrnoException, IOException, NumberFormatException {
+         for (String sysctl : GLOBAL_SYSCTLS) {
+             checkSysctlPermissions(sysctl);
+             int value = Integer.parseInt(readFile(sysctl).trim());
+             assertEquals("value of " + sysctl + ":", 1, value);
+         }
+
+         File[] interfaceDirs = new File(IPV6_SYSCTL_DIR).listFiles();
+         for (File interfaceDir : interfaceDirs) {
+             if (interfaceDir.getName().equals("all") || interfaceDir.getName().equals("lo")) {
+                 continue;
+             }
+             String sysctl = new File(interfaceDir, AUTOCONF_SYSCTL).getAbsolutePath();
+             checkSysctlPermissions(sysctl);
+             int value = Integer.parseInt(readFile(sysctl).trim());
+             assertLess("value of " + sysctl + ":", value, 0);
+         }
+     }
+}
diff --git a/tests/tests/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java b/tests/tests/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java
index cb8aeaf..6175923 100644
--- a/tests/tests/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java
+++ b/tests/tests/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java
@@ -26,8 +26,6 @@
 import android.net.SSLCertificateSocketFactory;
 import android.test.AndroidTestCase;
 
-import dalvik.annotation.BrokenTest;
-
 import libcore.javax.net.ssl.SSLDefaultConfigurationAsserts;
 
 public class SSLCertificateSocketFactoryTest extends AndroidTestCase {
diff --git a/tests/tests/net/src/android/net/cts/TrafficStatsTest.java b/tests/tests/net/src/android/net/cts/TrafficStatsTest.java
old mode 100644
new mode 100755
index 9483bdc..5b93bee
--- a/tests/tests/net/src/android/net/cts/TrafficStatsTest.java
+++ b/tests/tests/net/src/android/net/cts/TrafficStatsTest.java
@@ -207,27 +207,37 @@
         final int maxExpectedExtraPackets = 7;
         final int minExpectedExtraPackets = 5;
 
+        // Some other tests don't cleanup connections correctly.
+        // They have the same UID, so we discount their lingering traffic
+        // which happens only on non-localhost, such as TCP FIN retranmission packets
+        long deltaTxOtherPackets = (totalTxPacketsAfter - totalTxPacketsBefore) - uidTxDeltaPackets;
+        long deltaRxOtherPackets = (totalRxPacketsAfter - totalRxPacketsBefore) - uidRxDeltaPackets;
+        if (deltaTxOtherPackets > 0 || deltaRxOtherPackets > 0) {
+            Log.i(LOG_TAG, "lingering traffic data: " + deltaTxOtherPackets + "/" + deltaRxOtherPackets);
+            // Make sure that not too many non-localhost packets are accounted for
+            assertTrue("too many non-localhost packets on the sam UID", deltaTxOtherPackets + deltaTxOtherPackets < 20);
+        }
 
         assertTrue("uidtxp: " + uidTxPacketsBefore + " -> " + uidTxPacketsAfter + " delta=" + uidTxDeltaPackets +
             " Wanted: " + uidTxDeltaPackets + ">=" + packetCount + "+" + minExpectedExtraPackets + " && " +
-            uidTxDeltaPackets + "<=" + packetCount + "+" + packetCount + "+" + maxExpectedExtraPackets,
+            uidTxDeltaPackets + "<=" + packetCount + "+" + packetCount + "+" + maxExpectedExtraPackets + "+" + deltaTxOtherPackets,
             uidTxDeltaPackets >= packetCount + minExpectedExtraPackets &&
-            uidTxDeltaPackets <= packetCount + packetCount + maxExpectedExtraPackets);
+            uidTxDeltaPackets <= packetCount + packetCount + maxExpectedExtraPackets + deltaTxOtherPackets);
         assertTrue("uidrxp: " + uidRxPacketsBefore + " -> " + uidRxPacketsAfter + " delta=" + uidRxDeltaPackets +
             " Wanted: " + uidRxDeltaPackets + ">=" + packetCount + "+" + minExpectedExtraPackets + " && " +
             uidRxDeltaPackets + "<=" + packetCount + "+" + packetCount + "+" + maxExpectedExtraPackets,
             uidRxDeltaPackets >= packetCount + minExpectedExtraPackets &&
-            uidRxDeltaPackets <= packetCount + packetCount + maxExpectedExtraPackets);
+            uidRxDeltaPackets <= packetCount + packetCount + maxExpectedExtraPackets + deltaRxOtherPackets);
         assertTrue("uidtxb: " + uidTxBytesBefore + " -> " + uidTxBytesAfter + " delta=" + uidTxDeltaBytes +
             " Wanted: " + uidTxDeltaBytes + ">=" + tcpPacketToIpBytes(packetCount, byteCount) + "+" + tcpPacketToIpBytes(minExpectedExtraPackets, 0) + " && " +
             uidTxDeltaBytes + "<=" + tcpPacketToIpBytes(packetCount, byteCount) + "+" + tcpPacketToIpBytes(packetCount + maxExpectedExtraPackets, 0),
             uidTxDeltaBytes >= tcpPacketToIpBytes(packetCount, byteCount) + tcpPacketToIpBytes(minExpectedExtraPackets, 0) &&
-            uidTxDeltaBytes <= tcpPacketToIpBytes(packetCount, byteCount) + tcpPacketToIpBytes(packetCount + maxExpectedExtraPackets, 0));
+            uidTxDeltaBytes <= tcpPacketToIpBytes(packetCount, byteCount) + tcpPacketToIpBytes(packetCount + maxExpectedExtraPackets + deltaTxOtherPackets, 0));
         assertTrue("uidrxb: " + uidRxBytesBefore + " -> " + uidRxBytesAfter + " delta=" + uidRxDeltaBytes +
             " Wanted: " + uidRxDeltaBytes + ">=" + tcpPacketToIpBytes(packetCount, byteCount) + "+" + tcpPacketToIpBytes(minExpectedExtraPackets, 0) + " && " +
             uidRxDeltaBytes + "<=" + tcpPacketToIpBytes(packetCount, byteCount) + "+" + tcpPacketToIpBytes(packetCount + maxExpectedExtraPackets, 0),
             uidRxDeltaBytes >= tcpPacketToIpBytes(packetCount, byteCount) + tcpPacketToIpBytes(minExpectedExtraPackets, 0) &&
-            uidRxDeltaBytes <= tcpPacketToIpBytes(packetCount, byteCount) + tcpPacketToIpBytes(packetCount + maxExpectedExtraPackets, 0));
+            uidRxDeltaBytes <= tcpPacketToIpBytes(packetCount, byteCount) + tcpPacketToIpBytes(packetCount + maxExpectedExtraPackets + deltaRxOtherPackets, 0));
 
         // Localhost traffic *does* count against total stats.
         // Fudge by 132 packets of 1500 bytes not related to the test.
diff --git a/tests/tests/net/src/android/net/http/cts/X509TrustManagerExtensionsTest.java b/tests/tests/net/src/android/net/http/cts/X509TrustManagerExtensionsTest.java
new file mode 100644
index 0000000..9c0d774
--- /dev/null
+++ b/tests/tests/net/src/android/net/http/cts/X509TrustManagerExtensionsTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2012 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.net.http.cts;
+
+import android.net.http.X509TrustManagerExtensions;
+import android.util.Base64;
+
+import java.io.File;
+import java.io.ByteArrayInputStream;
+
+import java.security.KeyStore;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+
+import junit.framework.TestCase;
+
+import com.android.org.conscrypt.TrustedCertificateStore;
+import com.android.org.conscrypt.TrustManagerImpl;
+
+public class X509TrustManagerExtensionsTest extends TestCase {
+
+    public void testIsUserAddedCert() throws Exception {
+        final String testCert =
+            "MIICfjCCAeegAwIBAgIJAMefIzKHY5H4MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV" +
+            "BAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEPMA0G" +
+            "A1UECgwGR2V3Z3VsMRMwEQYDVQQDDApnZXdndWwuY29tMB4XDTEzMTEwNTAwNDE0" +
+            "MFoXDTEzMTIwNTAwNDE0MFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRYw" +
+            "FAYDVQQHDA1Nb3VudGFpbiBWaWV3MQ8wDQYDVQQKDAZHZXdndWwxEzARBgNVBAMM" +
+            "Cmdld2d1bC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKpc/I0Ss4sm" +
+            "yV2iX5xRMM7+XXAhiWrceGair4MpvDrGIa1kFj2phtx4IqTfDnNU7AhRJYkDYmJQ" +
+            "fUJ8i6F+I08uNiGVO4DtPJbZcBXg9ME9EMaJCslm995ueeNWSw1Ky8zM0tt4p+94" +
+            "BcXJ7PC3N2WgkvtE8xwNbaeUfhGPzJKXAgMBAAGjUDBOMB0GA1UdDgQWBBQQ/iW7" +
+            "JCkSI2sbn4nTBiZ9PSiO8zAfBgNVHSMEGDAWgBQQ/iW7JCkSI2sbn4nTBiZ9PSiO" +
+            "8zAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBABQBrUOWTCSIl3vkRR3w" +
+            "3bPzh3BpqDmxH9xe4rZr+MVKKjpGjY1z2m2EEtyNz3tbgVQym5+si00DUHFL0IP1" +
+            "SuRULmPyEpTBVbV+PA5Kc967ZcDgYt4JtdMcCeKbIFaU6r8oEYEL2PTlNZmgbunM" +
+            "pXktkhVvNxZeSa8yM9bPhXkN";
+
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+        X509Certificate cert = (X509Certificate)cf.generateCertificate(
+            new ByteArrayInputStream(Base64.decode(testCert, Base64.DEFAULT)));
+
+        // Test without adding cert to keystore.
+        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+        X509TrustManagerExtensions tmeNegative =
+            new X509TrustManagerExtensions(new TrustManagerImpl(keyStore));
+        assertEquals(false, tmeNegative.isUserAddedCertificate(cert));
+
+        // Test with cert added to keystore.
+        final File DIR_TEMP = new File(System.getProperty("java.io.tmpdir"));
+        final File DIR_TEST = new File(DIR_TEMP, "test");
+        final File system = new File(DIR_TEST, "system-test");
+        final File added = new File(DIR_TEST, "added-test");
+        final File deleted = new File(DIR_TEST, "deleted-test");
+
+        TrustedCertificateStore tcs = new TrustedCertificateStore(system, added, deleted);
+        added.mkdirs();
+        tcs.installCertificate(cert);
+        X509TrustManagerExtensions tmePositive =
+            new X509TrustManagerExtensions(new TrustManagerImpl(keyStore, null, tcs));
+        assertEquals(true, tmePositive.isUserAddedCertificate(cert));
+    }
+}
diff --git a/tests/tests/net/src/android/net/ipv6/cts/PingTest.java b/tests/tests/net/src/android/net/ipv6/cts/PingTest.java
index 41eb03d..49fc59c 100644
--- a/tests/tests/net/src/android/net/ipv6/cts/PingTest.java
+++ b/tests/tests/net/src/android/net/ipv6/cts/PingTest.java
@@ -19,10 +19,10 @@
 import android.test.AndroidTestCase;
 import android.util.Log;
 
-import libcore.io.ErrnoException;
-import libcore.io.Libcore;
-import libcore.io.StructTimeval;
-import static libcore.io.OsConstants.*;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.StructTimeval;
+import static android.system.OsConstants.*;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -34,6 +34,21 @@
 import java.util.Arrays;
 import java.util.Random;
 
+/**
+ * Checks that the device has kernel support for the IPv6 ping socket. This allows ping6 to work
+ * without root privileges. The necessary kernel code is in Linux 3.11 or above, or the
+ * <code>common/android-3.x</code> kernel trees. If you are not running one of these kernels, the
+ * functionality can be obtained by cherry-picking the following patches from David Miller's
+ * <code>net-next</code> tree:
+ * <ul>
+ * <li>6d0bfe2 net: ipv6: Add IPv6 support to the ping socket.
+ * <li>c26d6b4 ping: always initialize ->sin6_scope_id and ->sin6_flowinfo
+ * <li>fbfe80c net: ipv6: fix wrong ping_v6_sendmsg return value
+ * <li>a1bdc45 net: ipv6: add missing lock in ping_v6_sendmsg
+ * <li>cf970c0 ping: prevent NULL pointer dereference on write to msg_name
+ * </ul>
+ * or the equivalent backports to the <code>common/android-3.x</code> trees.
+ */
 public class PingTest extends AndroidTestCase {
     /** Maximum size of the packets we're using to test. */
     private static final int MAX_SIZE = 4096;
@@ -69,8 +84,8 @@
      * Creates an IPv6 ping socket and sets a receive timeout of 100ms.
      */
     private FileDescriptor createPingSocket() throws ErrnoException {
-        FileDescriptor s = Libcore.os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6);
-        Libcore.os.setsockoptTimeval(s, SOL_SOCKET, SO_RCVTIMEO, StructTimeval.fromMillis(100));
+        FileDescriptor s = Os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6);
+        Os.setsockoptTimeval(s, SOL_SOCKET, SO_RCVTIMEO, StructTimeval.fromMillis(100));
         return s;
     }
 
@@ -83,26 +98,32 @@
         int port = (int) (Math.random() * 2048);
 
         // Send the packet.
-        int ret = Libcore.os.sendto(s, ByteBuffer.wrap(packet), 0, address, port);
+        int ret = Os.sendto(s, ByteBuffer.wrap(packet), 0, address, port);
         assertEquals(packet.length, ret);
     }
 
     /**
      * Checks that a socket has received a response appropriate to the specified packet.
      */
-    private void checkResponse(FileDescriptor s,
-            InetAddress dest, byte[] sent) throws ErrnoException, IOException {
-        // Receive the response.
-        InetSocketAddress from = new InetSocketAddress();
+    private void checkResponse(FileDescriptor s, InetAddress dest,
+            byte[] sent, boolean useRecvfrom) throws ErrnoException, IOException {
         ByteBuffer responseBuffer = ByteBuffer.allocate(MAX_SIZE);
-        int bytesRead = Libcore.os.recvfrom(s, responseBuffer, 0, from);
+        int bytesRead;
 
-        // Check the source address and scope ID.
-        assertTrue(from.getAddress() instanceof Inet6Address);
-        Inet6Address fromAddress = (Inet6Address) from.getAddress();
-        assertEquals(0, fromAddress.getScopeId());
-        assertNull(fromAddress.getScopedInterface());
-        assertEquals(dest.getHostAddress(), fromAddress.getHostAddress());
+        // Receive the response.
+        if (useRecvfrom) {
+            InetSocketAddress from = new InetSocketAddress();
+            bytesRead = Os.recvfrom(s, responseBuffer, 0, from);
+
+            // Check the source address and scope ID.
+            assertTrue(from.getAddress() instanceof Inet6Address);
+            Inet6Address fromAddress = (Inet6Address) from.getAddress();
+            assertEquals(0, fromAddress.getScopeId());
+            assertNull(fromAddress.getScopedInterface());
+            assertEquals(dest.getHostAddress(), fromAddress.getHostAddress());
+        } else {
+            bytesRead = Os.read(s, responseBuffer);
+        }
 
         // Check the packet length.
         assertEquals(sent.length, bytesRead);
@@ -113,7 +134,7 @@
         assertEquals((byte) 0x81, response[0]);
 
         // Find out what ICMP ID was used in the packet that was sent.
-        int id = ((InetSocketAddress) Libcore.os.getsockname(s)).getPort();
+        int id = ((InetSocketAddress) Os.getsockname(s)).getPort();
         sent[4] = (byte) (id / 256);
         sent[5] = (byte) (id % 256);
 
@@ -135,10 +156,13 @@
         for (int i = 0; i < NUM_PACKETS; i++) {
             byte[] packet = pingPacket((int) (Math.random() * MAX_SIZE));
             FileDescriptor s = createPingSocket();
+            // Use both recvfrom and read().
             sendPing(s, ipv6Loopback, packet);
-            checkResponse(s, ipv6Loopback, packet);
+            checkResponse(s, ipv6Loopback, packet, true);
+            sendPing(s, ipv6Loopback, packet);
+            checkResponse(s, ipv6Loopback, packet, false);
             // Check closing the socket doesn't raise an exception.
-            Libcore.os.close(s);
+            Os.close(s);
         }
     }
 }
diff --git a/tests/tests/net/src/android/net/wifi/cts/NsdManagerTest.java b/tests/tests/net/src/android/net/wifi/cts/NsdManagerTest.java
index d1e4c44..d434728 100644
--- a/tests/tests/net/src/android/net/wifi/cts/NsdManagerTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/NsdManagerTest.java
@@ -356,7 +356,7 @@
         assertTrue(lastEvent.mInfo.getPort() == localPort);
         assertTrue(eventCacheSize() == 1);
 
-        assertTrue(checkForAdditionalEvents());
+        checkForAdditionalEvents();
         clearEventCache();
 
         // Unregister the service
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java b/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
index 7faea64..152789c 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
@@ -28,6 +28,7 @@
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiManager.TxPacketCountListener;
 import android.net.wifi.WifiManager.WifiLock;
+import android.os.SystemClock;
 import android.test.AndroidTestCase;
 import android.util.Log;
 
@@ -36,6 +37,7 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 
 public class WifiManagerTest extends AndroidTestCase {
@@ -46,7 +48,7 @@
     private WifiManager mWifiManager;
     private WifiLock mWifiLock;
     private static MySync mMySync;
-    private List<ScanResult> mScanResult = null;
+    private List<ScanResult> mScanResults = null;
     private NetworkInfo mNetworkInfo;
 
     // Please refer to WifiManager
@@ -66,6 +68,10 @@
     private static final int TIMEOUT_MSEC = 6000;
     private static final int WAIT_MSEC = 60;
     private static final int DURATION = 10000;
+    private static final int WIFI_SCAN_TEST_INTERVAL_MILLIS = 60 * 1000;
+    private static final int WIFI_SCAN_TEST_CACHE_DELAY_MILLIS = 3 * 60 * 1000;
+    private static final int WIFI_SCAN_TEST_ITERATIONS = 5;
+
     private IntentFilter mIntentFilter;
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
@@ -74,9 +80,9 @@
             if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
                 synchronized (mMySync) {
                     if (mWifiManager.getScanResults() != null) {
-                        mScanResult = mWifiManager.getScanResults();
+                        mScanResults = mWifiManager.getScanResults();
                         mMySync.expectedState = STATE_SCAN_RESULTS_AVAILABLE;
-                        mScanResult = mWifiManager.getScanResults();
+                        mScanResults = mWifiManager.getScanResults();
                         mMySync.notifyAll();
                     }
                 }
@@ -207,8 +213,9 @@
     private void assertDisableOthers(WifiConfiguration wifiConfiguration, boolean disableOthers) {
         for (WifiConfiguration w : mWifiManager.getConfiguredNetworks()) {
             if ((!w.SSID.equals(wifiConfiguration.SSID)) && w.status != Status.CURRENT) {
-                if (disableOthers)
+                if (disableOthers) {
                     assertEquals(Status.DISABLED, w.status);
+                }
             }
         }
     }
@@ -261,6 +268,46 @@
     }
 
     /**
+     * Test WiFi scan timestamp - fails when WiFi scan timestamps are inconsistent with
+     * {@link SystemClock#elapsedRealtime()} on device.<p>
+     * To run this test in cts-tradefed:
+     * run cts --class android.net.wifi.cts.WifiManagerTest --method testWifiScanTimestamp
+     */
+    public void testWifiScanTimestamp() throws Exception {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            Log.d(TAG, "Skipping test as WiFi is not supported");
+            return;
+        }
+        if (!mWifiManager.isWifiEnabled()) {
+            setWifiEnabled(true);
+        }
+        // Scan multiple times to make sure scan timestamps increase with device timestamp.
+        for (int i = 0; i < WIFI_SCAN_TEST_ITERATIONS; ++i) {
+            startScan();
+            // Make sure at least one AP is found.
+            assertFalse("empty scan results!", mScanResults.isEmpty());
+            long nowMillis = SystemClock.elapsedRealtime();
+            // Keep track of how many APs are fresh in one scan.
+            int numFreshAps = 0;
+            for (ScanResult result : mScanResults) {
+                long scanTimeMillis = TimeUnit.MICROSECONDS.toMillis(result.timestamp);
+                if (Math.abs(nowMillis - scanTimeMillis)  < WIFI_SCAN_TEST_CACHE_DELAY_MILLIS) {
+                    numFreshAps++;
+                }
+            }
+            // At least half of the APs in the scan should be fresh.
+            int numTotalAps = mScanResults.size();
+            String msg = "Stale AP count: " + (numTotalAps - numFreshAps) + ", fresh AP count: "
+                    + numFreshAps;
+            assertTrue(msg, numFreshAps * 2 >= mScanResults.size());
+            if (i < WIFI_SCAN_TEST_ITERATIONS - 1) {
+                // Wait before running next iteration.
+                Thread.sleep(WIFI_SCAN_TEST_INTERVAL_MILLIS);
+            }
+        }
+    }
+
+    /**
      * test point of wifiManager NetWork:
      * 1.add NetWork
      * 2.update NetWork
@@ -275,6 +322,7 @@
             // skip the test if WiFi is not supported
             return;
         }
+
         // store the list of enabled networks, so they can be re-enabled after test completes
         Set<String> enabledSsids = getEnabledNetworks(mWifiManager.getConfiguredNetworks());
         try {
@@ -307,11 +355,6 @@
             wifiConfiguration = mWifiManager.getConfiguredNetworks().get(pos);
             assertDisableOthers(wifiConfiguration, disableOthers);
             assertEquals(Status.ENABLED, wifiConfiguration.status);
-            disableOthers = true;
-
-            assertTrue(mWifiManager.enableNetwork(netId, disableOthers));
-            wifiConfiguration = mWifiManager.getConfiguredNetworks().get(pos);
-            assertDisableOthers(wifiConfiguration, disableOthers);
 
             assertTrue(mWifiManager.disableNetwork(netId));
             wifiConfiguration = mWifiManager.getConfiguredNetworks().get(pos);
diff --git a/tests/tests/opengl/Android.mk b/tests/tests/opengl/Android.mk
index 98f11e9..3844807 100644
--- a/tests/tests/opengl/Android.mk
+++ b/tests/tests/opengl/Android.mk
@@ -21,12 +21,12 @@
 # Don't include this package in any target.
 LOCAL_MODULE_TAGS := optional
 
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
 # When built, explicitly put it in the data partition.
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-# All tests should include android.test.runner.
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_JNI_SHARED_LIBRARIES := libopengltest_jni
 
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
diff --git a/tests/tests/opengl/AndroidManifest.xml b/tests/tests/opengl/AndroidManifest.xml
index 266216f..363b9aa 100644
--- a/tests/tests/opengl/AndroidManifest.xml
+++ b/tests/tests/opengl/AndroidManifest.xml
@@ -22,11 +22,16 @@
     <uses-sdk android:minSdkVersion="14" />
     <uses-feature android:glEsVersion="0x00020000"/>
     <instrumentation
-        android:name="android.test.InstrumentationCtsTestRunner"
-        android:targetPackage="com.android.cts.opengl" />
+        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.cts.opengl" >
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
+
     <application
         android:icon="@drawable/ic_launcher"
-        android:label="@string/app_name" >
+        android:label="@string/app_name"
+        android:hardwareAccelerated="false" >
 
          <activity
             android:label="@string/app_name"
@@ -35,7 +40,7 @@
           <activity
             android:label="@string/app_name"
             android:name="android.opengl.cts.OpenGLES20ActivityTwo">
-         </activity> 
+         </activity>
          <uses-library  android:name="android.test.runner" />
          <activity
             android:name="android.opengl.cts.OpenGLES20NativeActivityOne"
diff --git a/tests/tests/opengl/src/android/opengl/cts/FramebufferTest.java b/tests/tests/opengl/src/android/opengl/cts/FramebufferTest.java
new file mode 100644
index 0000000..4ca3a99
--- /dev/null
+++ b/tests/tests/opengl/src/android/opengl/cts/FramebufferTest.java
@@ -0,0 +1,653 @@
+/*
+ * 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.opengl.cts;
+
+import android.graphics.Bitmap;
+import android.graphics.SurfaceTexture;
+import android.opengl.EGL14;
+import android.opengl.EGLConfig;
+import android.opengl.EGLContext;
+import android.opengl.EGLDisplay;
+import android.opengl.EGLExt;
+import android.opengl.EGLSurface;
+import android.opengl.GLES20;
+import android.opengl.GLES30;
+import android.test.AndroidTestCase;
+import android.util.Log;
+import android.view.Surface;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Arrays;
+
+/**
+ * Test some GLES framebuffer stuff.
+ */
+public class FramebufferTest extends AndroidTestCase {
+    private static final String TAG = "FramebufferTest";
+
+
+    /**
+     * Tests very basic glBlitFramebuffer() features by copying from one offscreen framebuffer
+     * to another.
+     * <p>
+     * Requires GLES3.
+     */
+    public void testBlitFramebuffer() throws Throwable {
+        final int WIDTH = 640;
+        final int HEIGHT = 480;
+        final int BYTES_PER_PIXEL = 4;
+        final int TEST_RED = 255;
+        final int TEST_GREEN = 0;
+        final int TEST_BLUE = 127;
+        final int TEST_ALPHA = 255;
+        final byte expectedBytes[] = new byte[] {
+                (byte) TEST_RED, (byte) TEST_GREEN, (byte) TEST_BLUE, (byte) TEST_ALPHA
+        };
+        EglCore eglCore = null;
+        OffscreenSurface surface1 = null;
+        OffscreenSurface surface2 = null;
+
+        try {
+            eglCore = new EglCore(null, EglCore.FLAG_TRY_GLES3);
+            if (eglCore.getGlVersion() < 3) {
+                Log.d(TAG, "GLES3 not available, skipping test");
+                return;
+            }
+
+            // Create two surfaces, and clear surface1
+            surface1 = new OffscreenSurface(eglCore, WIDTH, HEIGHT);
+            surface2 = new OffscreenSurface(eglCore, WIDTH, HEIGHT);
+            surface1.makeCurrent();
+            GLES30.glClearColor(TEST_RED / 255.0f, TEST_GREEN / 255.0f, TEST_BLUE / 255.0f,
+                    TEST_ALPHA / 255.0f);
+            GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
+            checkGlError("glClear");
+
+            // Set surface2 as "draw", surface1 as "read", and blit.
+            surface2.makeCurrentReadFrom(surface1);
+            GLES30.glBlitFramebuffer(0, 0, WIDTH, HEIGHT, 0, 0, WIDTH, HEIGHT,
+                    GLES30.GL_COLOR_BUFFER_BIT, GLES30.GL_NEAREST);
+            checkGlError("glBlitFramebuffer");
+
+            ByteBuffer pixelBuf = ByteBuffer.allocateDirect(WIDTH * HEIGHT * BYTES_PER_PIXEL);
+            pixelBuf.order(ByteOrder.LITTLE_ENDIAN);
+            byte testBytes[] = new byte[4];
+
+            // Confirm that surface1 has the color by testing a pixel from the center.
+            surface1.makeCurrent();
+            pixelBuf.clear();
+            GLES30.glReadPixels(0, 0, WIDTH, HEIGHT, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE,
+                    pixelBuf);
+            checkGlError("glReadPixels");
+            pixelBuf.position((WIDTH * (HEIGHT / 2) + (WIDTH / 2)) * BYTES_PER_PIXEL);
+            pixelBuf.get(testBytes, 0, 4);
+            Log.v(TAG, "testBytes1 = " + Arrays.toString(testBytes));
+            assertTrue(Arrays.equals(testBytes, expectedBytes));
+
+            // Confirm that surface2 has the color.
+            surface2.makeCurrent();
+            pixelBuf.clear();
+            GLES30.glReadPixels(0, 0, WIDTH, HEIGHT, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE,
+                    pixelBuf);
+            checkGlError("glReadPixels");
+            pixelBuf.position((WIDTH * (HEIGHT / 2) + (WIDTH / 2)) * BYTES_PER_PIXEL);
+            pixelBuf.get(testBytes, 0, 4);
+            Log.v(TAG, "testBytes2 = " + Arrays.toString(testBytes));
+            assertTrue(Arrays.equals(testBytes, expectedBytes));
+        } finally {
+            if (surface1 != null) {
+                surface1.release();
+            }
+            if (surface2 != null) {
+                surface2.release();
+            }
+            if (eglCore != null) {
+                eglCore.release();
+            }
+        }
+    }
+
+    /**
+     * Checks to see if a GLES error has been raised.
+     */
+    private static void checkGlError(String op) {
+        int error = GLES20.glGetError();
+        if (error != GLES20.GL_NO_ERROR) {
+            String msg = op + ": glError 0x" + Integer.toHexString(error);
+            Log.e(TAG, msg);
+            throw new RuntimeException(msg);
+        }
+    }
+
+
+    /**
+     * Core EGL state (display, context, config).
+     */
+    private static final class EglCore {
+        /**
+         * Constructor flag: surface must be recordable.  This discourages EGL from using a
+         * pixel format that cannot be converted efficiently to something usable by the video
+         * encoder.
+         */
+        public static final int FLAG_RECORDABLE = 0x01;
+
+        /**
+         * Constructor flag: ask for GLES3, fall back to GLES2 if not available.  Without this
+         * flag, GLES2 is used.
+         */
+        public static final int FLAG_TRY_GLES3 = 0x02;
+
+        // Android-specific extension.
+        private static final int EGL_RECORDABLE_ANDROID = 0x3142;
+
+        private EGLDisplay mEGLDisplay = EGL14.EGL_NO_DISPLAY;
+        private EGLContext mEGLContext = EGL14.EGL_NO_CONTEXT;
+        private EGLConfig mEGLConfig = null;
+        private int mGlVersion = -1;
+
+
+        /**
+         * Prepares EGL display and context.
+         * <p>
+         * Equivalent to EglCore(null, 0).
+         */
+        public EglCore() {
+            this(null, 0);
+        }
+
+        /**
+         * Prepares EGL display and context.
+         * <p>
+         * @param sharedContext The context to share, or null if sharing is not desired.
+         * @param flags Configuration bit flags, e.g. FLAG_RECORDABLE.
+         */
+        public EglCore(EGLContext sharedContext, int flags) {
+            if (mEGLDisplay != EGL14.EGL_NO_DISPLAY) {
+                throw new RuntimeException("EGL already set up");
+            }
+
+            if (sharedContext == null) {
+                sharedContext = EGL14.EGL_NO_CONTEXT;
+            }
+
+            mEGLDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
+            if (mEGLDisplay == EGL14.EGL_NO_DISPLAY) {
+                throw new RuntimeException("unable to get EGL14 display");
+            }
+            int[] version = new int[2];
+            if (!EGL14.eglInitialize(mEGLDisplay, version, 0, version, 1)) {
+                mEGLDisplay = null;
+                throw new RuntimeException("unable to initialize EGL14");
+            }
+
+            // Try to get a GLES3 context, if requested.
+            if ((flags & FLAG_TRY_GLES3) != 0) {
+                //Log.d(TAG, "Trying GLES 3");
+                EGLConfig config = getConfig(flags, 3);
+                if (config != null) {
+                    int[] attrib3_list = {
+                            EGL14.EGL_CONTEXT_CLIENT_VERSION, 3,
+                            EGL14.EGL_NONE
+                    };
+                    EGLContext context = EGL14.eglCreateContext(mEGLDisplay, config, sharedContext,
+                            attrib3_list, 0);
+
+                    if (EGL14.eglGetError() == EGL14.EGL_SUCCESS) {
+                        //Log.d(TAG, "Got GLES 3 config");
+                        mEGLConfig = config;
+                        mEGLContext = context;
+                        mGlVersion = 3;
+                    }
+                }
+            }
+            if (mEGLContext == EGL14.EGL_NO_CONTEXT) {  // GLES 2 only, or GLES 3 attempt failed
+                //Log.d(TAG, "Trying GLES 2");
+                EGLConfig config = getConfig(flags, 2);
+                if (config == null) {
+                    throw new RuntimeException("Unable to find a suitable EGLConfig");
+                }
+                int[] attrib2_list = {
+                        EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
+                        EGL14.EGL_NONE
+                };
+                EGLContext context = EGL14.eglCreateContext(mEGLDisplay, config, sharedContext,
+                        attrib2_list, 0);
+                checkEglError("eglCreateContext");
+                mEGLConfig = config;
+                mEGLContext = context;
+                mGlVersion = 2;
+            }
+
+            // Confirm with query.
+            int[] values = new int[1];
+            EGL14.eglQueryContext(mEGLDisplay, mEGLContext, EGL14.EGL_CONTEXT_CLIENT_VERSION,
+                    values, 0);
+            Log.d(TAG, "EGLContext created, client version " + values[0]);
+        }
+
+        /**
+         * Finds a suitable EGLConfig.
+         *
+         * @param flags Bit flags from constructor.
+         * @param version Must be 2 or 3.
+         */
+        private EGLConfig getConfig(int flags, int version) {
+            int renderableType = EGL14.EGL_OPENGL_ES2_BIT;
+            if (version >= 3) {
+                renderableType |= EGLExt.EGL_OPENGL_ES3_BIT_KHR;
+            }
+
+            // The actual surface is generally RGBA or RGBX, so situationally omitting alpha
+            // doesn't really help.  It can also lead to a huge performance hit on glReadPixels()
+            // when reading into a GL_RGBA buffer.
+            int[] attribList = {
+                    EGL14.EGL_RED_SIZE, 8,
+                    EGL14.EGL_GREEN_SIZE, 8,
+                    EGL14.EGL_BLUE_SIZE, 8,
+                    EGL14.EGL_ALPHA_SIZE, 8,
+                    //EGL14.EGL_DEPTH_SIZE, 16,
+                    //EGL14.EGL_STENCIL_SIZE, 8,
+                    EGL14.EGL_RENDERABLE_TYPE, renderableType,
+                    EGL14.EGL_NONE, 0,      // placeholder for recordable [@-3]
+                    EGL14.EGL_NONE
+            };
+            if ((flags & FLAG_RECORDABLE) != 0) {
+                attribList[attribList.length - 3] = EGL_RECORDABLE_ANDROID;
+                attribList[attribList.length - 2] = 1;
+            }
+            EGLConfig[] configs = new EGLConfig[1];
+            int[] numConfigs = new int[1];
+            if (!EGL14.eglChooseConfig(mEGLDisplay, attribList, 0, configs, 0, configs.length,
+                    numConfigs, 0)) {
+                Log.w(TAG, "unable to find RGB8888 / " + version + " EGLConfig");
+                return null;
+            }
+            return configs[0];
+        }
+
+        /**
+         * Discard all resources held by this class, notably the EGL context.
+         */
+        public void release() {
+            if (mEGLDisplay != EGL14.EGL_NO_DISPLAY) {
+                // Android is unusual in that it uses a reference-counted EGLDisplay.  So for
+                // every eglInitialize() we need an eglTerminate().
+                EGL14.eglDestroyContext(mEGLDisplay, mEGLContext);
+                EGL14.eglReleaseThread();
+                EGL14.eglTerminate(mEGLDisplay);
+            }
+
+            mEGLDisplay = EGL14.EGL_NO_DISPLAY;
+            mEGLContext = EGL14.EGL_NO_CONTEXT;
+            mEGLConfig = null;
+        }
+
+        @Override
+        protected void finalize() throws Throwable {
+            try {
+                if (mEGLDisplay != EGL14.EGL_NO_DISPLAY) {
+                    // We're limited here -- finalizers don't run on the thread that holds
+                    // the EGL state, so if a surface or context is still current on another
+                    // thread we can't fully release it here.  Exceptions thrown from here
+                    // are quietly discarded.  Complain in the log file.
+                    Log.w(TAG, "WARNING: EglCore was not explicitly released -- state may be leaked");
+                    release();
+                }
+            } finally {
+                super.finalize();
+            }
+        }
+
+        /**
+         * Destroys the specified surface.  Note the EGLSurface won't actually be destroyed if it's
+         * still current in a context.
+         */
+        public void releaseSurface(EGLSurface eglSurface) {
+            EGL14.eglDestroySurface(mEGLDisplay, eglSurface);
+        }
+
+        /**
+         * Creates an EGL surface associated with a Surface.
+         * <p>
+         * If this is destined for MediaCodec, the EGLConfig should have the "recordable" attribute.
+         */
+        public EGLSurface createWindowSurface(Object surface) {
+            if (!(surface instanceof Surface) && !(surface instanceof SurfaceTexture)) {
+                throw new RuntimeException("invalid surface: " + surface);
+            }
+
+            // Create a window surface, and attach it to the Surface we received.
+            int[] surfaceAttribs = {
+                    EGL14.EGL_NONE
+            };
+            EGLSurface eglSurface = EGL14.eglCreateWindowSurface(mEGLDisplay, mEGLConfig, surface,
+                    surfaceAttribs, 0);
+            checkEglError("eglCreateWindowSurface");
+            if (eglSurface == null) {
+                throw new RuntimeException("surface was null");
+            }
+            return eglSurface;
+        }
+
+        /**
+         * Creates an EGL surface associated with an offscreen buffer.
+         */
+        public EGLSurface createOffscreenSurface(int width, int height) {
+            int[] surfaceAttribs = {
+                    EGL14.EGL_WIDTH, width,
+                    EGL14.EGL_HEIGHT, height,
+                    EGL14.EGL_NONE
+            };
+            EGLSurface eglSurface = EGL14.eglCreatePbufferSurface(mEGLDisplay, mEGLConfig,
+                    surfaceAttribs, 0);
+            checkEglError("eglCreatePbufferSurface");
+            if (eglSurface == null) {
+                throw new RuntimeException("surface was null");
+            }
+            return eglSurface;
+        }
+
+        /**
+         * Makes our EGL context current, using the supplied surface for both "draw" and "read".
+         */
+        public void makeCurrent(EGLSurface eglSurface) {
+            if (mEGLDisplay == EGL14.EGL_NO_DISPLAY) {
+                // called makeCurrent() before create?
+                Log.d(TAG, "NOTE: makeCurrent w/o display");
+            }
+            if (!EGL14.eglMakeCurrent(mEGLDisplay, eglSurface, eglSurface, mEGLContext)) {
+                throw new RuntimeException("eglMakeCurrent failed");
+            }
+        }
+
+        /**
+         * Makes our EGL context current, using the supplied "draw" and "read" surfaces.
+         */
+        public void makeCurrent(EGLSurface drawSurface, EGLSurface readSurface) {
+            if (mEGLDisplay == EGL14.EGL_NO_DISPLAY) {
+                // called makeCurrent() before create?
+                Log.d(TAG, "NOTE: makeCurrent w/o display");
+            }
+            if (!EGL14.eglMakeCurrent(mEGLDisplay, drawSurface, readSurface, mEGLContext)) {
+                throw new RuntimeException("eglMakeCurrent(draw,read) failed");
+            }
+        }
+
+        /**
+         * Makes no context current.
+         */
+        public void makeNothingCurrent() {
+            if (!EGL14.eglMakeCurrent(mEGLDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE,
+                    EGL14.EGL_NO_CONTEXT)) {
+                throw new RuntimeException("eglMakeCurrent failed");
+            }
+        }
+
+        /**
+         * Calls eglSwapBuffers.  Use this to "publish" the current frame.
+         *
+         * @return false on failure
+         */
+        public boolean swapBuffers(EGLSurface eglSurface) {
+            return EGL14.eglSwapBuffers(mEGLDisplay, eglSurface);
+        }
+
+        /**
+         * Sends the presentation time stamp to EGL.  Time is expressed in nanoseconds.
+         */
+        public void setPresentationTime(EGLSurface eglSurface, long nsecs) {
+            EGLExt.eglPresentationTimeANDROID(mEGLDisplay, eglSurface, nsecs);
+        }
+
+        /**
+         * Returns true if our context and the specified surface are current.
+         */
+        public boolean isCurrent(EGLSurface eglSurface) {
+            return mEGLContext.equals(EGL14.eglGetCurrentContext()) &&
+                    eglSurface.equals(EGL14.eglGetCurrentSurface(EGL14.EGL_DRAW));
+        }
+
+        /**
+         * Performs a simple surface query.
+         */
+        public int querySurface(EGLSurface eglSurface, int what) {
+            int[] value = new int[1];
+            EGL14.eglQuerySurface(mEGLDisplay, eglSurface, what, value, 0);
+            return value[0];
+        }
+
+        /**
+         * Returns the GLES version this context is configured for (2 or 3).
+         */
+        public int getGlVersion() {
+            return mGlVersion;
+        }
+
+        /**
+         * Writes the current display, context, and surface to the log.
+         */
+        public static void logCurrent(String msg) {
+            EGLDisplay display;
+            EGLContext context;
+            EGLSurface surface;
+
+            display = EGL14.eglGetCurrentDisplay();
+            context = EGL14.eglGetCurrentContext();
+            surface = EGL14.eglGetCurrentSurface(EGL14.EGL_DRAW);
+            Log.i(TAG, "Current EGL (" + msg + "): display=" + display + ", context=" + context +
+                    ", surface=" + surface);
+        }
+
+        /**
+         * Checks for EGL errors.
+         */
+        private void checkEglError(String msg) {
+            int error;
+            if ((error = EGL14.eglGetError()) != EGL14.EGL_SUCCESS) {
+                throw new RuntimeException(msg + ": EGL error: 0x" + Integer.toHexString(error));
+            }
+        }
+    }
+
+
+    /**
+     * Common base class for EGL surfaces.
+     * <p>
+     * There can be multiple surfaces associated with a single context.
+     */
+    private static class EglSurfaceBase {
+        // EglCore object we're associated with.  It may be associated with multiple surfaces.
+        protected EglCore mEglCore;
+
+        private EGLSurface mEGLSurface = EGL14.EGL_NO_SURFACE;
+        private int mWidth = -1;
+        private int mHeight = -1;
+
+        protected EglSurfaceBase(EglCore eglCore) {
+            mEglCore = eglCore;
+        }
+
+        /**
+         * Creates a window surface.
+         * <p>
+         * @param surface May be a Surface or SurfaceTexture.
+         */
+        public void createWindowSurface(Object surface) {
+            if (mEGLSurface != EGL14.EGL_NO_SURFACE) {
+                throw new IllegalStateException("surface already created");
+            }
+            mEGLSurface = mEglCore.createWindowSurface(surface);
+            mWidth = mEglCore.querySurface(mEGLSurface, EGL14.EGL_WIDTH);
+            mHeight = mEglCore.querySurface(mEGLSurface, EGL14.EGL_HEIGHT);
+        }
+
+        /**
+         * Creates an off-screen surface.
+         */
+        public void createOffscreenSurface(int width, int height) {
+            if (mEGLSurface != EGL14.EGL_NO_SURFACE) {
+                throw new IllegalStateException("surface already created");
+            }
+            mEGLSurface = mEglCore.createOffscreenSurface(width, height);
+            mWidth = width;
+            mHeight = height;
+        }
+
+        /**
+         * Returns the surface's width, in pixels.
+         */
+        public int getWidth() {
+            return mWidth;
+        }
+
+        /**
+         * Returns the surface's height, in pixels.
+         */
+        public int getHeight() {
+            return mHeight;
+        }
+
+        /**
+         * Release the EGL surface.
+         */
+        public void releaseEglSurface() {
+            mEglCore.releaseSurface(mEGLSurface);
+            mEGLSurface = EGL14.EGL_NO_SURFACE;
+            mWidth = mHeight = -1;
+        }
+
+        /**
+         * Makes our EGL context and surface current.
+         */
+        public void makeCurrent() {
+            mEglCore.makeCurrent(mEGLSurface);
+        }
+
+        /**
+         * Makes our EGL context and surface current for drawing, using the supplied surface
+         * for reading.
+         */
+        public void makeCurrentReadFrom(EglSurfaceBase readSurface) {
+            mEglCore.makeCurrent(mEGLSurface, readSurface.mEGLSurface);
+        }
+
+        /**
+         * Calls eglSwapBuffers.  Use this to "publish" the current frame.
+         *
+         * @return false on failure
+         */
+        public boolean swapBuffers() {
+            boolean result = mEglCore.swapBuffers(mEGLSurface);
+            if (!result) {
+                Log.d(TAG, "WARNING: swapBuffers() failed");
+            }
+            return result;
+        }
+
+        /**
+         * Sends the presentation time stamp to EGL.
+         *
+         * @param nsecs Timestamp, in nanoseconds.
+         */
+        public void setPresentationTime(long nsecs) {
+            mEglCore.setPresentationTime(mEGLSurface, nsecs);
+        }
+
+        /**
+         * Saves the EGL surface to a file.
+         * <p>
+         * Expects that this object's EGL surface is current.
+         */
+        public void saveFrame(File file) throws IOException {
+            if (!mEglCore.isCurrent(mEGLSurface)) {
+                throw new RuntimeException("Expected EGL context/surface is not current");
+            }
+
+            // glReadPixels gives us a ByteBuffer filled with what is essentially big-endian RGBA
+            // data (i.e. a byte of red, followed by a byte of green...).  We need an int[] filled
+            // with little-endian ARGB data to feed to Bitmap.
+            //
+            // If we implement this as a series of buf.get() calls, we can spend 2.5 seconds just
+            // copying data around for a 720p frame.  It's better to do a bulk get() and then
+            // rearrange the data in memory.  (For comparison, the PNG compress takes about 500ms
+            // for a trivial frame.)
+            //
+            // So... we set the ByteBuffer to little-endian, which should turn the bulk IntBuffer
+            // get() into a straight memcpy on most Android devices.  Our ints will hold ABGR data.
+            // Swapping B and R gives us ARGB.
+            //
+            // Making this even more interesting is the upside-down nature of GL, which means
+            // our output will look upside-down relative to what appears on screen if the
+            // typical GL conventions are used.
+
+            String filename = file.toString();
+
+            ByteBuffer buf = ByteBuffer.allocateDirect(mWidth * mHeight * 4);
+            buf.order(ByteOrder.LITTLE_ENDIAN);
+            GLES20.glReadPixels(0, 0, mWidth, mHeight,
+                    GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buf);
+            checkGlError("glReadPixels");
+            buf.rewind();
+
+            int pixelCount = mWidth * mHeight;
+            int[] colors = new int[pixelCount];
+            buf.asIntBuffer().get(colors);
+            for (int i = 0; i < pixelCount; i++) {
+                int c = colors[i];
+                colors[i] = (c & 0xff00ff00) | ((c & 0x00ff0000) >> 16) | ((c & 0x000000ff) << 16);
+            }
+
+            BufferedOutputStream bos = null;
+            try {
+                bos = new BufferedOutputStream(new FileOutputStream(filename));
+                Bitmap bmp = Bitmap.createBitmap(colors, mWidth, mHeight, Bitmap.Config.ARGB_8888);
+                bmp.compress(Bitmap.CompressFormat.PNG, 90, bos);
+                bmp.recycle();
+            } finally {
+                if (bos != null) bos.close();
+            }
+            Log.d(TAG, "Saved " + mWidth + "x" + mHeight + " frame as '" + filename + "'");
+        }
+    }
+
+    /**
+     * Off-screen EGL surface (pbuffer).
+     * <p>
+     * It's good practice to explicitly release() the surface, preferably from a "finally" block.
+     */
+    private static class OffscreenSurface extends EglSurfaceBase {
+        /**
+         * Creates an off-screen surface with the specified width and height.
+         */
+        public OffscreenSurface(EglCore eglCore, int width, int height) {
+            super(eglCore);
+            createOffscreenSurface(width, height);
+        }
+
+        /**
+         * Releases any resources associated with the surface.
+         */
+        public void release() {
+            releaseEglSurface();
+        }
+    }
+}
diff --git a/tests/tests/openglperf/Android.mk b/tests/tests/openglperf/Android.mk
index 55c39f2..7be16e8 100644
--- a/tests/tests/openglperf/Android.mk
+++ b/tests/tests/openglperf/Android.mk
@@ -21,7 +21,8 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
 
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner ctsdeviceutil
 
diff --git a/tests/tests/openglperf/AndroidManifest.xml b/tests/tests/openglperf/AndroidManifest.xml
index 1934f35..a213e51 100644
--- a/tests/tests/openglperf/AndroidManifest.xml
+++ b/tests/tests/openglperf/AndroidManifest.xml
@@ -27,10 +27,16 @@
     <!-- Two activities are used -->
     <instrumentation
         android:targetPackage="com.replica.replicaisland"
-        android:name="android.test.InstrumentationCtsTestRunner" />
+        android:name="android.support.test.runner.AndroidJUnitRunner" >
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
     <instrumentation
         android:targetPackage="com.android.cts.openglperf"
-        android:name="android.test.InstrumentationCtsTestRunner" />
+        android:name="android.support.test.runner.AndroidJUnitRunner">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
     <application>
         <uses-library android:name="android.test.runner" />
diff --git a/tests/tests/openglperf/src/android/openglperf/cts/PlanetsSurfaceView.java b/tests/tests/openglperf/src/android/openglperf/cts/PlanetsSurfaceView.java
old mode 100644
new mode 100755
index 072988d..afe664f
--- a/tests/tests/openglperf/src/android/openglperf/cts/PlanetsSurfaceView.java
+++ b/tests/tests/openglperf/src/android/openglperf/cts/PlanetsSurfaceView.java
@@ -33,9 +33,9 @@
 
     @Override
     public void onPause() {
-        mWatchDog.stop();
         super.onPause();
         setRenderMode(RENDERMODE_WHEN_DIRTY);
+        mWatchDog.stop();
     }
 
     @Override
diff --git a/tests/tests/os/Android.mk b/tests/tests/os/Android.mk
index f43043b..9dfb86e 100644
--- a/tests/tests/os/Android.mk
+++ b/tests/tests/os/Android.mk
@@ -21,20 +21,24 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_PROGUARD_ENABLED := disabled
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner guava
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner guava
+LOCAL_JNI_SHARED_LIBRARIES := libcts_jni libctsos_jni
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) \
-        src/android/os/cts/IParcelFileDescriptorPeer.aidl
+        src/android/os/cts/IParcelFileDescriptorPeer.aidl \
+        src/android/os/cts/IEmptyService.aidl \
+        src/android/os/cts/ISecondary.aidl
 
 LOCAL_PACKAGE_NAME := CtsOsTestCases
 
-LOCAL_INSTRUMENTATION_FOR := CtsTestStubs
-
-# uncomment when dalvik.annotation.Test* are removed or part of SDK
+# uncomment when b/13282254 is fixed
 #LOCAL_SDK_VERSION := current
+LOCAL_JAVA_LIBRARIES += android.test.runner
 
 include $(BUILD_CTS_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/os/AndroidManifest.xml b/tests/tests/os/AndroidManifest.xml
index 2418132..f225903 100644
--- a/tests/tests/os/AndroidManifest.xml
+++ b/tests/tests/os/AndroidManifest.xml
@@ -18,11 +18,52 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.cts.os">
 
+    <permission android:name="android.os.cts.permission.TEST_GRANTED"
+        android:protectionLevel="normal"
+            android:label="@string/permlab_testGranted"
+            android:description="@string/permdesc_testGranted">
+        <meta-data android:name="android.os.cts.string" android:value="foo" />
+        <meta-data android:name="android.os.cts.boolean" android:value="true" />
+        <meta-data android:name="android.os.cts.integer" android:value="100" />
+        <meta-data android:name="android.os.cts.color" android:value="#ff000000" />
+        <meta-data android:name="android.os.cts.float" android:value="100.1" />
+        <meta-data android:name="android.os.cts.reference" android:resource="@xml/metadata" />
+    </permission>
+
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
     <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
     <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.VIBRATE" />
+    <uses-permission android:name="android.permission.SEND_SMS" />
+    <uses-permission android:name="android.permission.RECEIVE_SMS" />
+    <uses-permission android:name="android.permission.READ_SMS"/>
+    <uses-permission android:name="android.permission.WRITE_SMS"/>
+    <uses-permission android:name="android.permission.CALL_PHONE" />
+    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
+    <uses-permission android:name="android.permission.DEVICE_POWER" />
+    <uses-permission android:name="android.os.cts.permission.TEST_GRANTED" />
 
     <application>
+        <activity android:name="android.os.cts.LaunchpadActivity"
+                  android:configChanges="keyboardHidden|orientation|screenSize"
+                  android:multiprocess="true">
+        </activity>
+
+        <activity android:name="android.os.cts.AliasActivityStub">
+            <meta-data android:name="android.os.alias"
+                android:resource="@xml/alias" />
+        </activity>
+
+        <activity android:name="android.os.cts.CountDownTimerTestStub"
+            android:label="CountDownTimerTestStub">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
         <service
             android:name="android.os.cts.ParcelFileDescriptorPeer$Red"
             android:process=":red"
@@ -31,11 +72,66 @@
             android:name="android.os.cts.ParcelFileDescriptorPeer$Blue"
             android:process=":blue"
             android:exported="true" />
+
+        <service android:name="android.os.cts.LocalService">
+            <intent-filter>
+                <action android:name="android.os.cts.activity.SERVICE_LOCAL" />
+            </intent-filter>
+            <meta-data android:name="android.os.cts.string" android:value="foo" />
+            <meta-data android:name="android.os.cts.boolean" android:value="true" />
+            <meta-data android:name="android.os.cts.integer" android:value="100" />
+            <meta-data android:name="android.os.cts.color" android:value="#ff000000" />
+            <meta-data android:name="android.os.cts.float" android:value="100.1" />
+            <meta-data android:name="android.os.cts.reference" android:resource="@xml/metadata" />
+        </service>
+
+        <service android:name="android.os.cts.LocalGrantedService"
+             android:permission="android.os.cts.permission.TEST_GRANTED">
+            <intent-filter>
+                <action android:name="android.os.cts.activity.SERVICE_LOCAL_GRANTED" />
+            </intent-filter>
+        </service>
+
+        <service android:name="android.os.cts.LocalDeniedService"
+               android:permission="android.os.cts.permission.TEST_DENIED">
+            <intent-filter>
+                <action android:name="android.os.cts.activity.SERVICE_LOCAL_DENIED" />
+            </intent-filter>
+        </service>
+
+
+        <service android:name="android.os.cts.EmptyService"
+            android:process=":remote">
+            <intent-filter>
+                <action
+                    android:name="android.os.cts.IEmptyService" />
+                <action
+                    android:name="android.os.REMOTESERVICE" />
+            </intent-filter>
+        </service>
+
+        <service android:name="android.os.cts.CtsRemoteService"
+            android:process=":remote">
+            <intent-filter>
+                <action
+                    android:name="android.os.cts.ISecondary" />
+                <action
+                    android:name="android.os.REMOTESERVICE" />
+            </intent-filter>
+        </service>
+
+        <service android:name="android.os.cts.MessengerService"
+                android:process=":messengerService">
+        </service>
+
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="com.android.cts.stub"
-                     android:label="CTS tests of android.os"/>
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.os"
+                     android:label="CTS tests of android.os">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
diff --git a/tests/assets/alter-footer.zip b/tests/tests/os/assets/alter-footer.zip
similarity index 100%
rename from tests/assets/alter-footer.zip
rename to tests/tests/os/assets/alter-footer.zip
Binary files differ
diff --git a/tests/assets/alter-metadata.zip b/tests/tests/os/assets/alter-metadata.zip
similarity index 100%
rename from tests/assets/alter-metadata.zip
rename to tests/tests/os/assets/alter-metadata.zip
Binary files differ
diff --git a/tests/assets/fake-eocd.zip b/tests/tests/os/assets/fake-eocd.zip
similarity index 100%
rename from tests/assets/fake-eocd.zip
rename to tests/tests/os/assets/fake-eocd.zip
Binary files differ
diff --git a/tests/assets/jarsigned.zip b/tests/tests/os/assets/jarsigned.zip
similarity index 100%
rename from tests/assets/jarsigned.zip
rename to tests/tests/os/assets/jarsigned.zip
Binary files differ
diff --git a/tests/assets/otacerts.zip b/tests/tests/os/assets/otacerts.zip
similarity index 100%
rename from tests/assets/otacerts.zip
rename to tests/tests/os/assets/otacerts.zip
Binary files differ
diff --git a/tests/assets/otasigned.zip b/tests/tests/os/assets/otasigned.zip
similarity index 100%
rename from tests/assets/otasigned.zip
rename to tests/tests/os/assets/otasigned.zip
Binary files differ
diff --git a/tests/assets/random.zip b/tests/tests/os/assets/random.zip
similarity index 100%
rename from tests/assets/random.zip
rename to tests/tests/os/assets/random.zip
Binary files differ
diff --git a/tests/assets/unsigned.zip b/tests/tests/os/assets/unsigned.zip
similarity index 100%
rename from tests/assets/unsigned.zip
rename to tests/tests/os/assets/unsigned.zip
Binary files differ
diff --git a/tests/tests/os/jni/Android.mk b/tests/tests/os/jni/Android.mk
new file mode 100644
index 0000000..32a5a9c
--- /dev/null
+++ b/tests/tests/os/jni/Android.mk
@@ -0,0 +1,39 @@
+# Copyright (C) 2010 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libctsos_jni
+
+# Don't include this package in any configuration by default.
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := \
+		CtsOsJniOnLoad.cpp \
+		android_os_cts_CpuInstructions.cpp.arm \
+		android_os_cts_TaggedPointer.cpp \
+		android_os_cts_OSFeatures.cpp \
+		android_os_cts_NoExecutePermissionTest.cpp
+
+LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
+
+LOCAL_SHARED_LIBRARIES := libnativehelper liblog libdl
+
+LOCAL_SRC_FILES += android_os_cts_CpuFeatures.cpp
+LOCAL_C_INCLUDES += ndk/sources/cpufeatures
+LOCAL_STATIC_LIBRARIES := cpufeatures
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/os/jni/CtsOsJniOnLoad.cpp b/tests/tests/os/jni/CtsOsJniOnLoad.cpp
new file mode 100644
index 0000000..3920915
--- /dev/null
+++ b/tests/tests/os/jni/CtsOsJniOnLoad.cpp
@@ -0,0 +1,58 @@
+/* 
+ * Copyright (C) 2010 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 <jni.h>
+#include <stdio.h>
+
+extern int register_android_os_cts_CpuFeatures(JNIEnv*);
+
+extern int register_android_os_cts_CpuInstructions(JNIEnv*);
+
+extern int register_android_os_cts_TaggedPointer(JNIEnv*);
+
+extern int register_android_os_cts_OSFeatures(JNIEnv*);
+
+extern int register_android_os_cts_NoExecutePermissionTest(JNIEnv*);
+
+jint JNI_OnLoad(JavaVM *vm, void *reserved) {
+    JNIEnv *env = NULL;
+
+    if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
+        return JNI_ERR;
+    }
+
+    if (register_android_os_cts_CpuFeatures(env)) {
+        return JNI_ERR;
+    }
+
+    if (register_android_os_cts_CpuInstructions(env)) {
+        return JNI_ERR;
+    }
+
+    if (register_android_os_cts_TaggedPointer(env)) {
+        return JNI_ERR;
+    }
+
+    if (register_android_os_cts_OSFeatures(env)) {
+        return JNI_ERR;
+    }
+
+    if (register_android_os_cts_NoExecutePermissionTest(env)) {
+        return JNI_ERR;
+    }
+
+    return JNI_VERSION_1_4;
+}
diff --git a/tests/tests/os/jni/android_os_cts_CpuFeatures.cpp b/tests/tests/os/jni/android_os_cts_CpuFeatures.cpp
new file mode 100644
index 0000000..6b5950c
--- /dev/null
+++ b/tests/tests/os/jni/android_os_cts_CpuFeatures.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2010 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 <cpu-features.h>
+#include <jni.h>
+#include <string.h>
+#include <sys/auxv.h>
+
+jboolean android_os_cts_CpuFeatures_isArmCpu(JNIEnv* env, jobject thiz)
+{
+    AndroidCpuFamily cpuFamily = android_getCpuFamily();
+    return cpuFamily == ANDROID_CPU_FAMILY_ARM;
+}
+
+jboolean android_os_cts_CpuFeatures_isArm7Compatible(JNIEnv* env, jobject thiz)
+{
+    uint64_t cpuFeatures = android_getCpuFeatures();
+    return (cpuFeatures & ANDROID_CPU_ARM_FEATURE_ARMv7) == ANDROID_CPU_ARM_FEATURE_ARMv7;
+}
+
+jboolean android_os_cts_CpuFeatures_isMipsCpu(JNIEnv* env, jobject thiz)
+{
+    AndroidCpuFamily cpuFamily = android_getCpuFamily();
+    return cpuFamily == ANDROID_CPU_FAMILY_MIPS;
+}
+
+jboolean android_os_cts_CpuFeatures_isX86Cpu(JNIEnv* env, jobject thiz)
+{
+    AndroidCpuFamily cpuFamily = android_getCpuFamily();
+    return cpuFamily == ANDROID_CPU_FAMILY_X86;
+}
+
+jboolean android_os_cts_CpuFeatures_isArm64Cpu(JNIEnv* env, jobject thiz)
+{
+    AndroidCpuFamily cpuFamily = android_getCpuFamily();
+    return cpuFamily == ANDROID_CPU_FAMILY_ARM64;
+}
+
+jboolean android_os_cts_CpuFeatures_isMips64Cpu(JNIEnv* env, jobject thiz)
+{
+    AndroidCpuFamily cpuFamily = android_getCpuFamily();
+    return cpuFamily == ANDROID_CPU_FAMILY_MIPS64;
+}
+
+jboolean android_os_cts_CpuFeatures_isX86_64Cpu(JNIEnv* env, jobject thiz)
+{
+    AndroidCpuFamily cpuFamily = android_getCpuFamily();
+    return cpuFamily == ANDROID_CPU_FAMILY_X86_64;
+}
+
+jint android_os_cts_CpuFeatures_getHwCaps(JNIEnv*, jobject)
+{
+    return (jint)getauxval(AT_HWCAP);
+}
+
+static JNINativeMethod gMethods[] = {
+    {  "isArmCpu", "()Z",
+            (void *) android_os_cts_CpuFeatures_isArmCpu  },
+    {  "isArm7Compatible", "()Z",
+            (void *) android_os_cts_CpuFeatures_isArm7Compatible  },
+    {  "isMipsCpu", "()Z",
+            (void *) android_os_cts_CpuFeatures_isMipsCpu  },
+    {  "isX86Cpu", "()Z",
+            (void *) android_os_cts_CpuFeatures_isX86Cpu  },
+    {  "isArm64Cpu", "()Z",
+            (void *) android_os_cts_CpuFeatures_isArm64Cpu  },
+    {  "isMips64Cpu", "()Z",
+            (void *) android_os_cts_CpuFeatures_isMips64Cpu  },
+    {  "isX86_64Cpu", "()Z",
+            (void *) android_os_cts_CpuFeatures_isX86_64Cpu  },
+    {  "getHwCaps", "()I",
+            (void *) android_os_cts_CpuFeatures_getHwCaps  },
+};
+
+int register_android_os_cts_CpuFeatures(JNIEnv* env)
+{
+    jclass clazz = env->FindClass("android/os/cts/CpuFeatures");
+
+    return env->RegisterNatives(clazz, gMethods,
+            sizeof(gMethods) / sizeof(JNINativeMethod));
+}
diff --git a/tests/tests/os/jni/android_os_cts_CpuInstructions.cpp b/tests/tests/os/jni/android_os_cts_CpuInstructions.cpp
new file mode 100644
index 0000000..3eea71b
--- /dev/null
+++ b/tests/tests/os/jni/android_os_cts_CpuInstructions.cpp
@@ -0,0 +1,148 @@
+/*
+ * 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 <jni.h>
+
+#if defined(__arm__) || defined(__aarch64__)
+#include <setjmp.h>
+#include <signal.h>
+
+static sigjmp_buf jmpenv;
+
+static void sigill_handler(int signum __attribute__((unused)))
+{
+    siglongjmp(jmpenv, 1);
+}
+
+static int do_sigsetjmp()
+{
+    return sigsetjmp(jmpenv, 1);
+}
+
+static jboolean test_instruction(void (*func)())
+{
+    struct sigaction sigill_act;
+    struct sigaction oldact;
+    int err;
+    jboolean ret = true;
+
+    memset(&sigill_act, 0, sizeof(sigill_act));
+    sigill_act.sa_handler = sigill_handler;
+
+    err = sigaction(SIGILL, &sigill_act, &oldact);
+    if (err) {
+        ret = false;
+        goto err_sigaction;
+    }
+
+    if (do_sigsetjmp()) {
+        ret = false;
+        goto err_segill;
+    }
+
+    func();
+
+err_segill:
+    sigaction(SIGILL, &oldact, NULL);
+err_sigaction:
+    return ret;
+}
+#endif
+
+#ifdef __aarch64__
+static void cntvct()
+{
+    asm volatile ( "mrs x0, cntvct_el0" : : : "x0" );
+}
+
+jboolean android_os_cts_CpuInstructions_canReadCntvct(JNIEnv *, jobject)
+{
+    return test_instruction(cntvct);
+}
+#else
+jboolean android_os_cts_CpuInstructions_canReadCntvct(JNIEnv *, jobject)
+{
+    return false;
+}
+#endif
+
+#ifdef __arm__
+static void swp()
+{
+    uint32_t dummy = 0;
+    uint32_t *ptr = &dummy;
+    asm volatile ( "swp r0, r0, [%0]" : "+r"(ptr) : : "r0" );
+}
+
+static void setend()
+{
+    asm volatile (
+        "setend be" "\n"
+        "setend le" "\n"
+    );
+}
+
+static void cp15_dsb()
+{
+    asm volatile ( "mcr p15, 0, %0, c7, c10, 4" : : "r"(0) );
+}
+
+jboolean android_os_cts_CpuInstructions_hasSwp(JNIEnv *, jobject)
+{
+    return test_instruction(swp);
+}
+
+jboolean android_os_cts_CpuInstructions_hasSetend(JNIEnv *, jobject)
+{
+    return test_instruction(setend);
+}
+
+jboolean android_os_cts_CpuInstructions_hasCp15Barriers(JNIEnv *, jobject)
+{
+    return test_instruction(cp15_dsb);
+}
+#else
+jboolean android_os_cts_CpuInstructions_hasSwp(JNIEnv *, jobject)
+{
+    return false;
+}
+
+jboolean android_os_cts_CpuInstructions_hasSetend(JNIEnv *, jobject)
+{
+    return false;
+}
+
+jboolean android_os_cts_CpuInstructions_hasCp15Barriers(JNIEnv *, jobject)
+{
+    return false;
+}
+#endif
+
+static JNINativeMethod gMethods[] = {
+    { "canReadCntvct", "()Z", (void *)android_os_cts_CpuInstructions_canReadCntvct },
+    { "hasSwp", "()Z", (void *)android_os_cts_CpuInstructions_hasSwp },
+    { "hasSetend", "()Z", (void *)android_os_cts_CpuInstructions_hasSetend },
+    { "hasCp15Barriers", "()Z",
+            (void *)android_os_cts_CpuInstructions_hasCp15Barriers },
+};
+
+int register_android_os_cts_CpuInstructions(JNIEnv *env)
+{
+    jclass clazz = env->FindClass("android/os/cts/CpuInstructions");
+
+    return env->RegisterNatives(clazz, gMethods,
+            sizeof(gMethods) / sizeof(JNINativeMethod));
+}
diff --git a/tests/tests/os/jni/android_os_cts_NoExecutePermissionTest.cpp b/tests/tests/os/jni/android_os_cts_NoExecutePermissionTest.cpp
new file mode 100644
index 0000000..e30599c
--- /dev/null
+++ b/tests/tests/os/jni/android_os_cts_NoExecutePermissionTest.cpp
@@ -0,0 +1,86 @@
+/*
+ * 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 <jni.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <cutils/log.h>
+#include <inttypes.h>
+
+static jboolean isAddressExecutable(uintptr_t address) {
+    char line[1024];
+    jboolean retval = false;
+    FILE *fp = fopen("/proc/self/maps", "re");
+    if (fp == NULL) {
+        ALOGE("Unable to open /proc/self/maps: %s", strerror(errno));
+        return false;
+    }
+    while(fgets(line, sizeof(line), fp) != NULL) {
+        uintptr_t start;
+        uintptr_t end;
+        char permissions[10];
+        int scan = sscanf(line, "%" SCNxPTR "-%" SCNxPTR " %9s ", &start, &end, permissions);
+        if ((scan == 3) && (start <= address) && (address < end)) {
+            retval = (permissions[2] == 'x');
+            break;
+        }
+    }
+    fclose(fp);
+    return retval;
+}
+
+static jboolean android_os_cts_NoExecutePermissionTest_isMyCodeExecutable(JNIEnv*, jobject)
+{
+    return isAddressExecutable((uintptr_t) __builtin_return_address(0));
+}
+
+static jboolean android_os_cts_NoExecutePermissionTest_isStackExecutable(JNIEnv*, jobject)
+{
+    unsigned int foo;
+    return isAddressExecutable((uintptr_t) &foo);
+}
+
+
+static jboolean android_os_cts_NoExecutePermissionTest_isHeapExecutable(JNIEnv*, jobject)
+{
+    unsigned int* foo = (unsigned int *) malloc(sizeof(unsigned int));
+    if (foo == NULL) {
+        ALOGE("Unable to allocate memory");
+        return false;
+    }
+    jboolean result = isAddressExecutable((uintptr_t) foo);
+    free(foo);
+    return result;
+}
+
+static JNINativeMethod gMethods[] = {
+    {  "isMyCodeExecutable", "()Z",
+            (void *) android_os_cts_NoExecutePermissionTest_isMyCodeExecutable  },
+    {  "isStackExecutable", "()Z",
+            (void *) android_os_cts_NoExecutePermissionTest_isStackExecutable  },
+    {  "isHeapExecutable", "()Z",
+            (void *) android_os_cts_NoExecutePermissionTest_isHeapExecutable  }
+};
+
+int register_android_os_cts_NoExecutePermissionTest(JNIEnv* env)
+{
+    jclass clazz = env->FindClass("android/os/cts/NoExecutePermissionTest");
+
+    return env->RegisterNatives(clazz, gMethods,
+            sizeof(gMethods) / sizeof(JNINativeMethod));
+}
diff --git a/tests/tests/os/jni/android_os_cts_OSFeatures.cpp b/tests/tests/os/jni/android_os_cts_OSFeatures.cpp
new file mode 100644
index 0000000..5f3ee4e
--- /dev/null
+++ b/tests/tests/os/jni/android_os_cts_OSFeatures.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2013 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 <jni.h>
+#include <sys/prctl.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <linux/filter.h>
+#include <linux/seccomp.h>
+
+#include <sys/utsname.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+jint android_os_cts_OSFeatures_getNoNewPrivs(JNIEnv* env, jobject thiz)
+{
+    return prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0);
+}
+
+jint android_os_cts_OSFeatures_prctlCapBsetRead(JNIEnv* env, jobject thiz, jint i)
+{
+    return prctl(PR_CAPBSET_READ, i, 0, 0, 0);
+}
+
+#define DENY BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
+
+static void test_seccomp() {
+    if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
+        _exit(0);
+    }
+
+    struct sock_filter filter[] = { DENY };
+    struct sock_fprog prog;
+    memset(&prog, 0, sizeof(prog));
+    prog.len = sizeof(filter) / sizeof(filter[0]);
+    prog.filter = filter;
+
+    if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) < 0) {
+        _exit(0);
+    }
+
+    while(1) {
+        _exit(0);  // should crash with SIGSYS
+    }
+}
+
+jboolean android_os_cts_OSFeatures_hasSeccompSupport(JNIEnv* env, jobject)
+{
+    pid_t pid = fork();
+    if (pid == -1) {
+        jclass cls = env->FindClass("java/lang/RuntimeException");
+        env->ThrowNew(cls, "fork failed");
+        return false;
+    }
+    if (pid == 0) {
+        // child
+        test_seccomp();
+        _exit(0);
+    }
+
+    int status;
+    TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
+    return WIFSIGNALED(status) && (WTERMSIG(status) == SIGSYS);
+}
+
+jboolean android_os_cts_OSFeatures_needsSeccompSupport(JNIEnv*, jobject)
+{
+#if !defined(__arm__) && !defined(__i386__) && !defined(__x86_64__)
+    // Seccomp support is only available for ARM, x86, x86_64.
+    return false;
+#endif
+
+    int major;
+    int minor;
+    struct utsname uts;
+    if (uname(&uts) == -1) {
+        return false;
+    }
+
+    if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
+        return false;
+    }
+
+    // Kernels before 3.8 don't have seccomp
+    if ((major < 3) || ((major == 3) && (minor < 8))) {
+        return false;
+    }
+
+    return true;
+}
+
+static JNINativeMethod gMethods[] = {
+    {  "getNoNewPrivs", "()I",
+            (void *) android_os_cts_OSFeatures_getNoNewPrivs  },
+    {  "prctlCapBsetRead", "(I)I",
+            (void *) android_os_cts_OSFeatures_prctlCapBsetRead },
+    {  "hasSeccompSupport", "()Z",
+            (void *) android_os_cts_OSFeatures_hasSeccompSupport  },
+    {  "needsSeccompSupport", "()Z",
+            (void *) android_os_cts_OSFeatures_needsSeccompSupport  }
+};
+
+int register_android_os_cts_OSFeatures(JNIEnv* env)
+{
+    jclass clazz = env->FindClass("android/os/cts/OSFeatures");
+
+    return env->RegisterNatives(clazz, gMethods,
+            sizeof(gMethods) / sizeof(JNINativeMethod));
+}
diff --git a/tests/tests/os/jni/android_os_cts_TaggedPointer.cpp b/tests/tests/os/jni/android_os_cts_TaggedPointer.cpp
new file mode 100644
index 0000000..e8f83a3
--- /dev/null
+++ b/tests/tests/os/jni/android_os_cts_TaggedPointer.cpp
@@ -0,0 +1,84 @@
+/*
+ * 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 <jni.h>
+#include <inttypes.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+//mask the top 8 bits
+#define TAG_MASK ((0xFFULL) << 56)
+
+#define PATTERN 0x600DC0DE
+
+static sigjmp_buf jmpenv;
+
+static void sigsegv_handler(int signum) {
+    siglongjmp(jmpenv, 1);
+}
+
+jboolean android_os_cts_TaggedPointer_hasTaggedPointer(JNIEnv* env, jobject thiz)
+{
+    uint32_t data;
+    uint32_t *tagged;
+    uintptr_t tmp;
+    int err;
+    jboolean ret = true;
+    struct sigaction sigsegv_act;
+    struct sigaction oldact;
+
+    tmp = TAG_MASK | (uintptr_t)(&data);
+    tagged = (uint32_t *)tmp;
+    data = PATTERN;
+
+    memset(&sigsegv_act, 0, sizeof(sigsegv_act));
+    sigsegv_act.sa_handler = sigsegv_handler;
+
+    err = sigaction(SIGSEGV, &sigsegv_act, &oldact);
+    if (err) {
+        ret = false;
+        goto err_sigaction;
+    }
+
+    if (sigsetjmp(jmpenv, 1)) {
+        ret = false;
+        goto err_segfault;
+    }
+
+    if (*tagged != PATTERN) {
+        ret = false;
+    }
+
+err_segfault:
+    sigaction(SIGSEGV, &oldact, NULL);
+err_sigaction:
+    return ret;
+}
+
+static JNINativeMethod gMethods[] = {
+    {  "hasTaggedPointer", "()Z",
+            (void *) android_os_cts_TaggedPointer_hasTaggedPointer },
+};
+
+int register_android_os_cts_TaggedPointer(JNIEnv* env)
+{
+    jclass clazz = env->FindClass("android/os/cts/TaggedPointer");
+
+    return env->RegisterNatives(clazz, gMethods,
+            sizeof(gMethods) / sizeof(JNINativeMethod));
+}
diff --git a/tests/tests/os/res/raw/test1.obb b/tests/tests/os/res/raw/test1.obb
new file mode 100644
index 0000000..33479aa
--- /dev/null
+++ b/tests/tests/os/res/raw/test1.obb
Binary files differ
diff --git a/tests/res/raw/test1_nosig.obb b/tests/tests/os/res/raw/test1_nosig.obb
similarity index 100%
rename from tests/res/raw/test1_nosig.obb
rename to tests/tests/os/res/raw/test1_nosig.obb
Binary files differ
diff --git a/tests/res/raw/test1_wrongpackage.obb b/tests/tests/os/res/raw/test1_wrongpackage.obb
similarity index 100%
rename from tests/res/raw/test1_wrongpackage.obb
rename to tests/tests/os/res/raw/test1_wrongpackage.obb
Binary files differ
diff --git a/tests/tests/os/res/values/strings.xml b/tests/tests/os/res/values/strings.xml
new file mode 100644
index 0000000..c167278
--- /dev/null
+++ b/tests/tests/os/res/values/strings.xml
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="permlab_testGranted">Test Granted</string>
+    <string name="permdesc_testGranted">Used for running CTS tests, for testing operations
+        where we have the permission.</string>
+    <string name="permlab_testDynamic">Test Dynamic</string>
+    <string name="permdesc_testDynamic">Used for running CTS tests, for testing adding
+        dynamic permissions.</string>
+    <string name="permlab_testDenied">Test Denied</string>
+    <string name="permdesc_testDenied">Used for running CTS tests, for testing operations
+        where we do not have the permission.</string>
+    <string name="explain">1. click start. \n2. if above image shaked, then press pass button,
+         else press failed button.</string>
+    <string name="text_view_hello">Hello! Text view!</string>
+    <string name="text_view_hello_two_lines">Hello! \nText view!</string>
+    <string name="text_view_simple_hint">This is a hint.</string>
+    <string name="text_view_hint">This is a string for testing hint of textview.</string>
+    <string name="activity_forwarding">App/Forwarding</string>
+    <string name="forwarding">$$$</string>
+    <string name="go">Go</string>
+    <string name="back">Back</string>
+    <string name="forward_target">
+        Press back button and notice we don\'t see the previous activity.
+    </string>
+    <string name="edit_text">testing</string>
+    <string name="text">DialogTest</string>
+    <string name="text_country">Country</string>
+    <string name="text_name">Name</string>
+    <string name="hello_world">Hello, World!</string>
+    <string name="hello_android">Hello, Android!</string>
+    <string name="alert_dialog_username">Name:</string>
+    <string name="alert_dialog_password">Password:</string>
+    <string name="alert_dialog_positive">Positive</string>
+    <string name="alert_dialog_negative">Negative</string>
+    <string name="alert_dialog_neutral">Neutral</string>
+    <string name="notify">Notify </string>
+    <string name="tabs_1">testing</string>
+    <string name="table_layout_first">first</string>
+    <string name="table_layout_second">second</string>
+    <string name="table_layout_third">third</string>
+    <string name="table_layout_long">Very long to make the string out of the screen</string>
+    <string name="chronometer_text">Test Chronometer</string>
+    <string name="am">AM</string>
+    <string name="pm">PM</string>
+    <string name="viewgroup_test">ViewGroup test</string>
+    <string name="viewanimator_test">ViewAnimator test</string>
+    <string name="id_ok">OK</string>
+    <string name="id_cancel">Cancel</string>
+    <string name="context_test_string1">This is %s string.</string>
+    <string name="context_test_string2">This is test string.</string>
+    <string name="animationutils_test_instructions">Choose different animations</string>
+    <string name="animationutils_test_alpha">Alpha animation</string>
+    <string name="animationutils_test_scale">Scale animation</string>
+    <string name="animationutils_test_rotate">Rotate animation</string>
+    <string name="animationutils_test_translate">Translate animation</string>
+    <string name="animationutils_test_set">Animation set</string>
+    <string name="animationutils_test_layout">Layout animation</string>
+    <string name="animationutils_test_gridlayout">Grid layout animation</string>
+    <string name="twolinelistitem_test_text1">text1</string>
+    <string name="twolinelistitem_test_text2">text2</string>
+    <string name="metadata_text">metadata text</string>
+    <string name="horizontal_text_1">horizontal 1</string>
+    <string name="horizontal_text_2">horizontal 2</string>
+    <string name="horizontal_text_3">horizontal 3</string>
+    <string name="vertical_text_1">vertical 1</string>
+    <string name="vertical_text_2">vertical 2</string>
+    <string name="vertical_text_3">vertical 3</string>
+    <string name="reference">here</string>
+    <string name="coerceIntegerToString">100</string>
+    <string name="coerceBooleanToString">true</string>
+    <string name="coerceColorToString">#fff</string>
+    <string name="coerceFloatToString">100.0</string>
+    <string name="coerceDimensionToString">100px</string>
+    <string name="coerceFractionToString">100<xliff:g id="percent">%</xliff:g></string>
+    <string name="formattedStringNone">Format[]</string>
+    <string name="formattedStringOne">Format[<xliff:g id="format">%d</xliff:g>]</string>
+    <string name="formattedStringTwo">Format[<xliff:g id="format">%3$d,%2$s</xliff:g>]</string>
+    <string name="checkboxpref_key">checkboxpref_key</string>
+   <string name="checkboxpref_title">title of preference</string>
+   <string name="checkboxpref_summary">summary of preference</string>
+   <string name="checkboxpref_summary_on">summary on of preference</string>
+   <string name="checkboxpref_summary_off">summary off of preference</string>
+   <string name="checkboxpref_depend">checkboxpref_depend</string>
+   <string name="checkboxpref_depend_title"> depend title of preference</string>
+   <string name="checkboxpref_depend_summary"> depend summary of preference</string>
+   <string name="edittextpref_key">edittextpref_key</string>
+   <string name="edittextpref_default_value">default value of preference</string>
+   <string name="edittextpref_title">title of edit text preference</string>
+   <string name="edittextpref_summary">summary of edit text preference</string>
+   <string name="edittextpref_dialog_title">dialog title of edit text preference</string>
+   <string name="edittextpref_text">text of  edit text preference</string>
+   <string name="listpref_key">listpref_key</string>
+   <string name="listpref_title">title of list preference</string>
+   <string name="listpref_summary">summary of list preference</string>
+   <string name="listpref_dialogtitle">dialog title of list preference</string>
+   <string name="easy">Easy</string>
+   <string name="medium">Medium</string>
+   <string name="hard">Hard</string>
+   <string name="footer_view">Footer view</string>
+   <string name="header_view">Header view</string>
+   <string name="dialogpref_title">title of dialog preference </string>
+   <string name="dialogpref_dialog_title">dialog title of dialog preference </string>
+   <string name="dialogpref_key">dialogpref_key</string>
+   <string name="dialogpref_default_value">default value of dialog preference</string>
+   <string name="dialogpref_summary">summary of dialog preference</string>
+   <string name="dialogpref_message">message of dialog preference</string>
+   <string name="dialogpref_sure">Sure</string>
+   <string name="dialogpref_cancel">Cancel</string>
+   <string name="pref_key">pref_key</string>
+   <string name="pref_title">title of preference</string>
+   <string name="pref_summary">summary of preference</string>
+   <string name="pref_depend_key">pref_depend_key</string>
+   <string name="pref_depend_title"> depend title of preference</string>
+   <string name="pref_depend_summary"> depend summary of preference</string>
+   <string name="android_intent_action_preference">android.intent.action.PREFERENCE</string>
+   <string name="def_pref_key">def_pref_key</string>
+   <string name="def_pref_title">default preference</string>
+   <string name="def_pref_summary">This is default preference of cts</string>
+   <string name="relative_view1">view 1</string>
+   <string name="relative_view2">view 2</string>
+   <string name="relative_view3">view 3</string>
+   <string name="relative_view4">view 4</string>
+   <string name="relative_view5">view 5</string>
+   <string name="relative_view6">view 6</string>
+   <string name="relative_view7">view 7</string>
+   <string name="relative_view8">view 8</string>
+   <string name="relative_view9">view 9</string>
+   <string name="relative_view10">view 10</string>
+   <string name="relative_view11">view 11</string>
+   <string name="relative_view12">view 12</string>
+   <string name="relative_view13">view 13</string>
+   <string name="country">Country:</string>
+   <string name="symbol">Symbol:</string>
+   <string name="country_warning">No such country registered</string>
+   <string name="version_cur">base</string>
+   <string name="version_old">base</string>
+   <string name="version_v3">base</string>
+   <string name="authenticator_label">Android CTS</string>
+   <string name="search_label">Android CTS</string>
+   <string name="tag1">tag 1</string>
+   <string name="tag2">tag 2</string>
+
+   <string name="button">Button</string>
+   <string name="holo_test">Holo Test</string>
+   <string name="holo_generator">Holo Generator</string>
+   <string name="holo_light_test">Holo Light Test</string>
+   <string name="holo_light_generator">Holo Light Generator</string>
+   <string name="reference_image">Reference Image: </string>
+   <string name="generated_image">Generated Image: </string>
+   <string name="themes_prompt">Select a Theme:</string>
+   <string name="sample_text">Sample text goes here. I wanted something creative and whimsical
+but then I just got bored...</string>
+    <string name="long_text">This is a really long string which exceeds the width of the view.
+New devices have a much larger screen which actually enables long strings to be displayed
+with no fading. I have made this string longer to fix this case. If you are correcting this
+text, I would love to see the kind of devices you guys now use! Guys, maybe some devices need longer string!
+I think so, so how about double this string, like copy and paste!
+This is a really long string which exceeds the width of the view.
+New devices have a much larger screen which actually enables long strings to be displayed
+with no fading. I have made this string longer to fix this case. If you are correcting this
+text, I would love to see the kind of devices you guys now use! Guys, maybe some devices need longer string!
+I think so, so how about double this string, like copy and paste! </string>
+    <string name="rectangle200">"M 0,0 l 200,0 l 0, 200 l -200, 0 z"</string>
+</resources>
diff --git a/tests/tests/os/res/xml/alias.xml b/tests/tests/os/res/xml/alias.xml
new file mode 100644
index 0000000..1166669
--- /dev/null
+++ b/tests/tests/os/res/xml/alias.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2008 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.
+ */
+-->
+
+<alias xmlns:android="http://schemas.android.com/apk/res/android">
+    <intent android:action="android.intent.action.MAIN"
+        android:targetPackage="com.android.cts.os"
+        android:targetClass="android.os.cts.ChildActivity"
+        android:data="http://www.google.com/">
+    </intent>
+</alias>
+
diff --git a/tests/res/xml/metadata.xml b/tests/tests/os/res/xml/metadata.xml
similarity index 100%
copy from tests/res/xml/metadata.xml
copy to tests/tests/os/res/xml/metadata.xml
diff --git a/tests/tests/os/src/android/os/cts/AbiTest.java b/tests/tests/os/src/android/os/cts/AbiTest.java
index a342669..ee2c168 100644
--- a/tests/tests/os/src/android/os/cts/AbiTest.java
+++ b/tests/tests/os/src/android/os/cts/AbiTest.java
@@ -16,7 +16,7 @@
 
 package android.os.cts;
 
-import android.os.cts.ReadElf;
+import android.cts.util.ReadElf;
 
 import java.io.File;
 
diff --git a/tests/tests/os/src/android/os/cts/ActivityTestsBase.java b/tests/tests/os/src/android/os/cts/ActivityTestsBase.java
new file mode 100644
index 0000000..3f7d91d
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/ActivityTestsBase.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2008 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.os.cts;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.test.AndroidTestCase;
+import android.test.PerformanceTestCase;
+
+public class ActivityTestsBase extends AndroidTestCase implements PerformanceTestCase,
+        LaunchpadActivity.CallingTest {
+    public static final String PERMISSION_GRANTED = "android.os.cts.permission.TEST_GRANTED";
+    public static final String PERMISSION_DENIED = "android.os.cts.permission.TEST_DENIED";
+
+    private static final int TIMEOUT_MS = 60 * 1000;
+
+    protected Intent mIntent;
+
+    private PerformanceTestCase.Intermediates mIntermediates;
+    private String mExpecting;
+
+    // Synchronization of activity result.
+    private boolean mFinished;
+    private int mResultCode = 0;
+    private Intent mData;
+    private RuntimeException mResultStack = null;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mIntent = new Intent(mContext, LaunchpadActivity.class);
+        mIntermediates = null;
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mIntermediates = null;
+        super.tearDown();
+    }
+
+    public boolean isPerformanceOnly() {
+        return false;
+    }
+
+    public void setInternalIterations(int count) {
+    }
+
+    public void startTiming(boolean realTime) {
+        if (mIntermediates != null) {
+            mIntermediates.startTiming(realTime);
+        }
+    }
+
+    public void addIntermediate(String name) {
+        if (mIntermediates != null) {
+            mIntermediates.addIntermediate(name);
+        }
+    }
+
+    public void addIntermediate(String name, long timeInNS) {
+        if (mIntermediates != null) {
+            mIntermediates.addIntermediate(name, timeInNS);
+        }
+    }
+
+    public void finishTiming(boolean realTime) {
+        if (mIntermediates != null) {
+            mIntermediates.finishTiming(realTime);
+        }
+    }
+
+    public void activityFinished(int resultCode, Intent data, RuntimeException where) {
+        finishWithResult(resultCode, data, where);
+    }
+
+    public Intent editIntent() {
+        return mIntent;
+    }
+
+    @Override
+    public Context getContext() {
+        return mContext;
+    }
+
+    public int startPerformance(Intermediates intermediates) {
+        mIntermediates = intermediates;
+        return 1;
+    }
+
+    public void finishGood() {
+        finishWithResult(Activity.RESULT_OK, null);
+    }
+
+    public void finishBad(String error) {
+        finishWithResult(Activity.RESULT_CANCELED, new Intent().setAction(error));
+    }
+
+    public void finishWithResult(int resultCode, Intent data) {
+        final RuntimeException where = new RuntimeException("Original error was here");
+        where.fillInStackTrace();
+        finishWithResult(resultCode, data, where);
+    }
+
+    public void finishWithResult(int resultCode, Intent data, RuntimeException where) {
+        synchronized (this) {
+            mResultCode = resultCode;
+            mData = data;
+            mResultStack = where;
+            mFinished = true;
+            notifyAll();
+        }
+    }
+
+    public int runLaunchpad(String action) {
+        startLaunchpadActivity(action);
+        return waitForResultOrThrow(TIMEOUT_MS);
+    }
+
+    private void startLaunchpadActivity(String action) {
+        LaunchpadActivity.setCallingTest(this);
+
+        synchronized (this) {
+            mIntent.setAction(action);
+            mFinished = false;
+            mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            mContext.startActivity(mIntent);
+        }
+    }
+
+    public int waitForResultOrThrow(int timeoutMs) {
+        return waitForResultOrThrow(timeoutMs, null);
+    }
+
+    public int waitForResultOrThrow(int timeoutMs, String expected) {
+        final int res = waitForResult(timeoutMs, expected);
+
+        if (res == Activity.RESULT_CANCELED) {
+            if (mResultStack != null) {
+                throw new RuntimeException(mData != null ? mData.toString() : "Unable to launch",
+                        mResultStack);
+            } else {
+                throw new RuntimeException(mData != null ? mData.toString() : "Unable to launch");
+            }
+        }
+        return res;
+    }
+
+    public int waitForResult(int timeoutMs, String expected) {
+        mExpecting = expected;
+
+        final long endTime = System.currentTimeMillis() + timeoutMs;
+
+        boolean timeout = false;
+        synchronized (this) {
+            while (!mFinished) {
+                final long delay = endTime - System.currentTimeMillis();
+                if (delay < 0) {
+                    timeout = true;
+                    break;
+                }
+
+                try {
+                    wait(delay);
+                } catch (final java.lang.InterruptedException e) {
+                    // do nothing
+                }
+            }
+        }
+
+        mFinished = false;
+
+        if (timeout) {
+            mResultCode = Activity.RESULT_CANCELED;
+            onTimeout();
+        }
+        return mResultCode;
+    }
+
+
+    public int getResultCode() {
+        return mResultCode;
+    }
+
+    public Intent getResultData() {
+        return mData;
+    }
+
+    public RuntimeException getResultStack() {
+        return mResultStack;
+    }
+
+    public void onTimeout() {
+        final String msg = mExpecting == null ? "Timeout" : "Timeout while expecting " + mExpecting;
+        finishWithResult(Activity.RESULT_CANCELED, new Intent().setAction(msg));
+    }
+}
diff --git a/tests/tests/os/src/android/os/cts/AliasActivityStub.java b/tests/tests/os/src/android/os/cts/AliasActivityStub.java
new file mode 100644
index 0000000..cff405e
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/AliasActivityStub.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2009 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.os.cts;
+
+import android.app.AliasActivity;
+import android.os.Bundle;
+
+public class AliasActivityStub extends AliasActivity {
+
+    public static boolean isOnCreateCalled = false;
+    public static boolean isFinished = false;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        isOnCreateCalled = true;
+    }
+
+    @Override
+    public void finish() {
+        super.finish();
+        isFinished = true;
+    }
+}
diff --git a/tests/tests/os/src/android/os/cts/BinderTest.java b/tests/tests/os/src/android/os/cts/BinderTest.java
index c3f2bcb..435e247 100644
--- a/tests/tests/os/src/android/os/cts/BinderTest.java
+++ b/tests/tests/os/src/android/os/cts/BinderTest.java
@@ -20,8 +20,6 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
-import android.app.cts.ActivityTestsBase;
-import android.app.cts.LocalService;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.ServiceConnection;
@@ -51,7 +49,8 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mService = new Intent(LocalService.SERVICE_LOCAL);
+        mService = new Intent(
+                LocalService.SERVICE_LOCAL, null /*uri*/, mContext, LocalService.class);
         mBinder = new MockBinder();
         mStartReceiver = new Binder() {
             @Override
diff --git a/tests/tests/os/src/android/os/cts/BuildTest.java b/tests/tests/os/src/android/os/cts/BuildTest.java
index 7176a6d..26b07f1 100644
--- a/tests/tests/os/src/android/os/cts/BuildTest.java
+++ b/tests/tests/os/src/android/os/cts/BuildTest.java
@@ -18,8 +18,13 @@
 
 
 import android.os.Build;
+import android.os.SystemProperties;
+
+import dalvik.system.VMRuntime;
 
 import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
 import java.util.Scanner;
 import java.util.regex.Pattern;
 
@@ -27,63 +32,80 @@
 
 public class BuildTest extends TestCase {
 
-    private static final String RO_PRODUCT_CPU_ABI = "ro.product.cpu.abi";
-
-    private static final String RO_PRODUCT_CPU_ABI2 = "ro.product.cpu.abi2";
+    private static final String RO_PRODUCT_CPU_ABILIST = "ro.product.cpu.abilist";
+    private static final String RO_PRODUCT_CPU_ABILIST32 = "ro.product.cpu.abilist32";
+    private static final String RO_PRODUCT_CPU_ABILIST64 = "ro.product.cpu.abilist64";
 
     /** Tests that check the values of {@link Build#CPU_ABI} and {@link Build#CPU_ABI2}. */
-    public void testCpuAbi() throws IOException {
-        if (CpuFeatures.isArmCpu()) {
-            assertArmCpuAbiConstants();
+    public void testCpuAbi() throws Exception {
+        testCpuAbiCommon();
+        if (VMRuntime.getRuntime().is64Bit()) {
+            testCpuAbi64();
+        } else {
+            testCpuAbi32();
         }
     }
 
-    private void assertArmCpuAbiConstants() throws IOException {
-        if (CpuFeatures.isArm7Compatible()) {
-            String cpuAbi = getProperty(RO_PRODUCT_CPU_ABI);
-            String cpuAbi2 = getProperty(RO_PRODUCT_CPU_ABI2);
-            //if CPU_ABI is armv7, CPU_ABI2 is either of {armeabi, NULL}
-            if (cpuAbi.equals(CpuFeatures.ARMEABI_V7)) {
-                String message = "CPU is ARM v7 compatible, so "
-                    + RO_PRODUCT_CPU_ABI  + " must be set to " + CpuFeatures.ARMEABI_V7 + " and "
-                    + RO_PRODUCT_CPU_ABI2 + " must be set to " + CpuFeatures.ARMEABI + " or NULL";
-                assertEquals(message, CpuFeatures.ARMEABI_V7, Build.CPU_ABI);
-                if (cpuAbi2.equals(CpuFeatures.ARMEABI)){
-                    assertEquals(message, cpuAbi2, Build.CPU_ABI2);
-                } else {
-                    assertNoPropertySet(message, RO_PRODUCT_CPU_ABI2);
-                    assertEquals(message, Build.UNKNOWN, Build.CPU_ABI2);
-                }
-            }
-            //if CPU_ABI is x86, then CPU_ABI2 is either of {armeabi, armv7, NULL}
-            else if (cpuAbi.equals(CpuFeatures.X86ABI)) {
-                String message = "CPU is x86 but ARM v7 compatible, so "
-                    + RO_PRODUCT_CPU_ABI  + " must be set to " + CpuFeatures.X86ABI + " and "
-                    + RO_PRODUCT_CPU_ABI2 + " must be set to " + CpuFeatures.ARMEABI + " or "
-                    + CpuFeatures.ARMEABI_V7 + " or NULL";
-                assertEquals(message, CpuFeatures.X86ABI, Build.CPU_ABI);
-                if (cpuAbi2.equals(CpuFeatures.ARMEABI_V7) || cpuAbi2.equals(CpuFeatures.ARMEABI))
-                    assertEquals(message, cpuAbi2, Build.CPU_ABI2);
-                else {
-                    assertNoPropertySet(message, RO_PRODUCT_CPU_ABI2);
-                    assertEquals(message, Build.UNKNOWN, Build.CPU_ABI2);
-                }
-            }
+    private void testCpuAbiCommon() throws Exception {
+        // The build property must match Build.SUPPORTED_ABIS exactly.
+        final String[] abiListProperty = getStringList(RO_PRODUCT_CPU_ABILIST);
+        assertEquals(Arrays.toString(abiListProperty), Arrays.toString(Build.SUPPORTED_ABIS));
+
+        List<String> abiList = Arrays.asList(abiListProperty);
+
+        // Every device must support at least one 32 bit ABI.
+        assertTrue(Build.SUPPORTED_32_BIT_ABIS.length > 0);
+
+        // Every supported 32 bit ABI must be present in Build.SUPPORTED_ABIS.
+        for (String abi : Build.SUPPORTED_32_BIT_ABIS) {
+            assertTrue(abiList.contains(abi));
+            assertFalse(VMRuntime.is64BitAbi(abi));
         }
-        else {
-            String message = "CPU is not ARM v7 compatible. "
-                    + RO_PRODUCT_CPU_ABI  + " must be set to " + CpuFeatures.ARMEABI + " and "
-                    + RO_PRODUCT_CPU_ABI2 + " must not be set.";
-            assertProperty(message, RO_PRODUCT_CPU_ABI, CpuFeatures.ARMEABI);
-            assertNoPropertySet(message, RO_PRODUCT_CPU_ABI2);
-            assertEquals(message, CpuFeatures.ARMEABI, Build.CPU_ABI);
-            assertEquals(message, Build.UNKNOWN, Build.CPU_ABI2);
+
+        // Every supported 64 bit ABI must be present in Build.SUPPORTED_ABIS.
+        for (String abi : Build.SUPPORTED_64_BIT_ABIS) {
+            assertTrue(abiList.contains(abi));
+            assertTrue(VMRuntime.is64BitAbi(abi));
+        }
+
+        // Build.CPU_ABI and Build.CPU_ABI2 must be present in Build.SUPPORTED_ABIS.
+        assertTrue(abiList.contains(Build.CPU_ABI));
+        if (!Build.CPU_ABI2.isEmpty()) {
+            assertTrue(abiList.contains(Build.CPU_ABI2));
         }
     }
+
+    private void testCpuAbi32() throws Exception {
+        List<String> abi32 = Arrays.asList(Build.SUPPORTED_32_BIT_ABIS);
+        assertTrue(abi32.contains(Build.CPU_ABI));
+
+        if (!Build.CPU_ABI2.isEmpty()) {
+            assertTrue(abi32.contains(Build.CPU_ABI2));
+        }
+    }
+
+    private void testCpuAbi64() {
+        List<String> abi64 = Arrays.asList(Build.SUPPORTED_64_BIT_ABIS);
+        assertTrue(abi64.contains(Build.CPU_ABI));
+
+        if (!Build.CPU_ABI2.isEmpty()) {
+            assertTrue(abi64.contains(Build.CPU_ABI2));
+        }
+    }
+
+    private String[] getStringList(String property) throws IOException {
+        String value = getProperty(property);
+        if (value.isEmpty()) {
+            return new String[0];
+        } else {
+            return value.split(",");
+        }
+    }
+
     /**
      * @param property name passed to getprop
      */
-    private String getProperty(String property)
+    static String getProperty(String property)
             throws IOException {
         Process process = new ProcessBuilder("getprop", property).start();
         Scanner scanner = null;
@@ -198,7 +220,7 @@
         assertNotEmpty(Build.USER);
     }
 
-    private static final String RO_DEBUGGABLE = "ro.debuggable";
+    static final String RO_DEBUGGABLE = "ro.debuggable";
     private static final String RO_SECURE = "ro.secure";
 
     /**
diff --git a/tests/tests/os/src/android/os/cts/BuildVersionTest.java b/tests/tests/os/src/android/os/cts/BuildVersionTest.java
index f3cbc88..e335901 100644
--- a/tests/tests/os/src/android/os/cts/BuildVersionTest.java
+++ b/tests/tests/os/src/android/os/cts/BuildVersionTest.java
@@ -29,18 +29,17 @@
 
     private static final String LOG_TAG = "BuildVersionTest";
     private static final Set<String> EXPECTED_RELEASES =
-        new HashSet<String>(Arrays.asList("4.4W.2", "4.4W.1", "4.4W"));
-    private static final int EXPECTED_SDK = 20;
+            new HashSet<String>(Arrays.asList("5.0", "5.0.1", "5.0.2"));
+    private static final int EXPECTED_SDK = 21;
+    private static final String EXPECTED_BUILD_VARIANT = "user";
+    private static final String EXPECTED_TAG = "release-keys";
 
     @SuppressWarnings("deprecation")
     public void testReleaseVersion() {
         // Applications may rely on the exact release version
-        assertTrue("Your Build.VERSION.RELEASE of " + Build.VERSION.RELEASE
-                + " was not one of the following: " + EXPECTED_RELEASES,
-                        EXPECTED_RELEASES.contains(Build.VERSION.RELEASE));
-
-        assertEquals("" + EXPECTED_SDK, Build.VERSION.SDK);
-        assertEquals(EXPECTED_SDK, Build.VERSION.SDK_INT);
+        assertAnyOf("BUILD.VERSION.RELEASE", Build.VERSION.RELEASE, EXPECTED_RELEASES);
+        assertEquals("Build.VERSION.SDK", "" + EXPECTED_SDK, Build.VERSION.SDK);
+        assertEquals("Build.VERSION.SDK_INT", EXPECTED_SDK, Build.VERSION.SDK_INT);
     }
 
     public void testIncremental() {
@@ -72,14 +71,24 @@
         assertEquals(Build.VERSION.RELEASE, devicePlatform[1]);
 
         assertEquals(Build.ID, fingerprintSegs[3]);
-        // no requirements for BUILD_NUMBER and BUILD_VARIANT
+
         assertTrue(fingerprintSegs[4].contains(":"));
-        // no strict requirement for TAGS
-        //assertEquals(Build.TAGS, fingerprintSegs[5]);
+        String[] buildNumberVariant = fingerprintSegs[4].split(":");
+        String buildVariant = buildNumberVariant[1];
+        assertEquals("Variant", EXPECTED_BUILD_VARIANT, buildVariant);
+        assertEquals("Tag", EXPECTED_TAG, fingerprintSegs[5]);
     }
 
     private void assertNotEmpty(String value) {
         assertNotNull(value);
         assertFalse(value.isEmpty());
     }
+
+    /** Assert that {@code actualValue} is equals to one of {@code permittedValues}. */
+    private void assertAnyOf(String label, String actualValue, Set<String> permittedValues) {
+        if (!permittedValues.contains(actualValue)) {
+             fail("For: " + label + ", the value: " + actualValue +
+                     ", should be one of: " + permittedValues);
+        }
+    }
 }
diff --git a/tests/tests/os/src/android/os/cts/BundleTest.java b/tests/tests/os/src/android/os/cts/BundleTest.java
index 7674b6b..0db5fd0 100644
--- a/tests/tests/os/src/android/os/cts/BundleTest.java
+++ b/tests/tests/os/src/android/os/cts/BundleTest.java
@@ -31,9 +31,11 @@
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Set;
 
 public class BundleTest extends AndroidTestCase {
+
     private static final boolean BOOLEANKEYVALUE = false;
 
     private static final int INTKEYVALUE = 20;
@@ -513,12 +515,37 @@
         assertBundleEquals(bundle2, (Bundle) ret.get(1));
     }
 
-    public void testGetSerializable() {
+    public void testGetSerializableWithString() {
         assertNull(mBundle.getSerializable(KEY));
-        mBundle.putSerializable(KEY, "android");
-        assertEquals("android", mBundle.getSerializable(KEY));
+        String s = "android";
+        mBundle.putSerializable(KEY, s);
+        assertEquals(s, mBundle.getSerializable(KEY));
         roundtrip();
-        assertEquals("android", mBundle.getSerializable(KEY));
+        assertEquals(s, mBundle.getSerializable(KEY));
+    }
+
+    public void testGetSerializableWithStringArray() {
+        assertNull(mBundle.getSerializable(KEY));
+        String[] strings = new String[]{"first", "last"};
+        mBundle.putSerializable(KEY, strings);
+        assertEquals(Arrays.asList(strings),
+                Arrays.asList((String[]) mBundle.getSerializable(KEY)));
+        roundtrip();
+        assertEquals(Arrays.asList(strings),
+                Arrays.asList((String[]) mBundle.getSerializable(KEY)));
+    }
+
+    public void testGetSerializableWithMultiDimensionalObjectArray() {
+        assertNull(mBundle.getSerializable(KEY));
+        Object[][] objects = new Object[][] {
+                {"string", 1L}
+        };
+        mBundle.putSerializable(KEY, objects);
+        assertEquals(Arrays.asList(objects[0]),
+                Arrays.asList(((Object[][]) mBundle.getSerializable(KEY))[0]));
+        roundtrip();
+        assertEquals(Arrays.asList(objects[0]),
+                Arrays.asList(((Object[][]) mBundle.getSerializable(KEY))[0]));
     }
 
     public void testGetShort1() {
@@ -812,9 +839,5 @@
         MockClassLoader() {
             super();
         }
-
-        MockClassLoader(ClassLoader parent) {
-            super(parent);
-        }
     }
 }
diff --git a/tests/tests/os/src/android/os/cts/ClearTop.java b/tests/tests/os/src/android/os/cts/ClearTop.java
new file mode 100644
index 0000000..278336c
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/ClearTop.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2008 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.os.cts;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+public class ClearTop extends Activity {
+    public static final String WAIT_CLEAR_TASK = "waitClearTask";
+    private static final String TAG = "ClearTop";
+    public ClearTop() {
+    }
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        final Intent intent = new Intent(getIntent()).setAction(LocalScreen.CLEAR_TASK).setClass(
+                this, LocalScreen.class);
+        startActivity(intent);
+    }
+
+    @Override
+    public void onNewIntent(Intent intent) {
+        Log.i(TAG, "onNewIntent");
+        if (LocalScreen.CLEAR_TASK.equals(intent.getAction())) {
+            setResult(RESULT_OK);
+        } else {
+            setResult(RESULT_CANCELED, new Intent().setAction("New intent received " + intent
+                    + ", expecting action " + TestedScreen.CLEAR_TASK));
+        }
+        finish();
+    }
+}
diff --git a/tests/tests/os/src/android/os/cts/ConditionVariableTest.java b/tests/tests/os/src/android/os/cts/ConditionVariableTest.java
index 559f890..cad9dec 100644
--- a/tests/tests/os/src/android/os/cts/ConditionVariableTest.java
+++ b/tests/tests/os/src/android/os/cts/ConditionVariableTest.java
@@ -16,6 +16,7 @@
 package android.os.cts;
 
 import junit.framework.TestCase;
+import android.cts.util.TestThread;
 import android.os.ConditionVariable;
 
 public class ConditionVariableTest extends TestCase {
diff --git a/tests/src/android/os/cts/CountDownTimerTestStub.java b/tests/tests/os/src/android/os/cts/CountDownTimerTestStub.java
similarity index 100%
rename from tests/src/android/os/cts/CountDownTimerTestStub.java
rename to tests/tests/os/src/android/os/cts/CountDownTimerTestStub.java
diff --git a/tests/tests/os/src/android/os/cts/CpuFeatures.java b/tests/tests/os/src/android/os/cts/CpuFeatures.java
new file mode 100644
index 0000000..553f264
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/CpuFeatures.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2010 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.os.cts;
+
+import android.os.Build;
+
+public class CpuFeatures {
+
+    public static final String ARMEABI_V7 = "armeabi-v7a";
+
+    public static final String ARMEABI = "armeabi";
+
+    public static final String MIPSABI = "mips";
+
+    public static final  String X86ABI = "x86";
+
+    public static final int HWCAP_VFP = (1 << 6);
+
+    public static final int HWCAP_NEON = (1 << 12);
+
+    public static final int HWCAP_VFPv3 = (1 << 13);
+
+    public static final int HWCAP_VFPv4 = (1 << 16);
+
+    public static final int HWCAP_IDIVA = (1 << 17);
+
+    public static final int HWCAP_IDIVT = (1 << 18);
+
+    static {
+        System.loadLibrary("ctsos_jni");
+    }
+
+    public static native boolean isArmCpu();
+
+    public static native boolean isArm7Compatible();
+
+    public static native boolean isMipsCpu();
+
+    public static native boolean isX86Cpu();
+
+    public static native boolean isArm64Cpu();
+
+    public static native boolean isMips64Cpu();
+
+    public static native boolean isX86_64Cpu();
+
+    public static native int getHwCaps();
+
+    public static boolean isArm64CpuIn32BitMode() {
+        if (!isArmCpu()) {
+            return false;
+        }
+
+        for (String abi : Build.SUPPORTED_64_BIT_ABIS) {
+            if (abi.equals("arm64-v8a")) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+}
diff --git a/tests/tests/os/src/android/os/cts/CpuFeaturesTest.java b/tests/tests/os/src/android/os/cts/CpuFeaturesTest.java
new file mode 100644
index 0000000..0b389a4
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/CpuFeaturesTest.java
@@ -0,0 +1,157 @@
+/*
+ * 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.os.cts;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import android.os.cts.CpuFeatures;
+
+import junit.framework.TestCase;
+
+public class CpuFeaturesTest extends TestCase {
+
+    private static void assertHwCap(String name, int hwcaps, int flag) {
+        assertEquals("Machine does not advertise " + name + " support", flag,
+                hwcaps & flag);
+    }
+
+    public void testArm64RequiredHwCaps() {
+        if (!CpuFeatures.isArm64CpuIn32BitMode()) {
+            return;
+        }
+
+        int hwcaps = CpuFeatures.getHwCaps();
+
+        assertFalse("Machine does not support getauxval(AT_HWCAP)",
+                hwcaps == 0);
+
+        assertHwCap("VFP", hwcaps, CpuFeatures.HWCAP_VFP);
+        assertHwCap("NEON", hwcaps, CpuFeatures.HWCAP_NEON);
+        assertHwCap("VFPv3", hwcaps, CpuFeatures.HWCAP_VFPv3);
+        assertHwCap("VFPv4", hwcaps, CpuFeatures.HWCAP_VFPv4);
+        assertHwCap("IDIVA", hwcaps, CpuFeatures.HWCAP_IDIVA);
+        assertHwCap("IDIVT", hwcaps, CpuFeatures.HWCAP_IDIVT);
+    }
+
+    private static String getFieldFromCpuinfo(String field) throws IOException {
+        BufferedReader br = new BufferedReader(new FileReader("/proc/cpuinfo"));
+        Pattern p = Pattern.compile(field + "\\s*:\\s*(.*)");
+
+        try {
+            String line;
+            while ((line = br.readLine()) != null) {
+                Matcher m = p.matcher(line);
+                if (m.matches()) {
+                    return m.group(1);
+                }
+            }
+       } finally {
+           br.close();
+       }
+
+       return null;
+    }
+
+    private static List<String> getFeaturesFromCpuinfo() throws IOException {
+        String features = getFieldFromCpuinfo("Features");
+        if (features == null)
+            return null;
+
+        return Arrays.asList(features.split("\\s"));
+    }
+
+    private static final String[] armv8RequiredFeatures = {
+            "wp", "half", "thumb", "fastmult", "vfp", "edsp", "neon",
+            "vfpv3", "tlsi", "vfpv4", "idiva", "idivt" };
+
+    private static void assertInCpuinfo(List<String> features,
+            String feature) {
+        assertTrue("/proc/cpuinfo does not advertise required feature " + feature + " to 32-bit ARM processes",
+                features.contains(feature));
+    }
+
+    private static void assertNotInCpuinfo(List<String> features,
+            String feature) {
+        assertFalse("/proc/cpuinfo advertises required feature " + feature + " to 64-bit ARM processes",
+                features.contains(feature));
+    }
+
+    public void testArmCpuinfo() throws IOException {
+        if (!CpuFeatures.isArmCpu())
+            return;
+
+        String cpuArch = getFieldFromCpuinfo("CPU architecture");
+        /* When /proc/cpuinfo is read by 32-bit ARM processes, the CPU
+         * architecture field must be present and contain an integer.
+         */
+        assertNotNull("Failed to read CPU architecture field from /proc/cpuinfo",
+                cpuArch);
+
+        int cpuArchInt = 0;
+        try {
+            cpuArchInt = Integer.parseInt(cpuArch);
+        } catch (NumberFormatException e) {
+            fail("/proc/cpuinfo reported non-integer CPU architecture " + cpuArch);
+        }
+
+        if (CpuFeatures.isArm64CpuIn32BitMode()) {
+            assertTrue("/proc/cpuinfo reported 32-bit only CPU architecture " + cpuArchInt + " on ARM64 CPU",
+                    cpuArchInt >= 8);
+        }
+
+        List<String> features = getFeaturesFromCpuinfo();
+        /* When /proc/cpuinfo is read by 32-bit ARM processes, the Features
+         * field must be present.  On ARMv8+ devices specifically, it must
+         * include ARMv7-optional features that are now required by ARMv8.
+         */
+        assertNotNull("Failed to read Features field from /proc/cpuinfo",
+                features);
+
+        if (CpuFeatures.isArm64CpuIn32BitMode()) {
+            for (String feature : armv8RequiredFeatures) {
+                assertInCpuinfo(features, feature);
+            }
+        }
+    }
+
+    public void testArm64Cpuinfo() throws IOException {
+        if (!CpuFeatures.isArm64Cpu()) {
+            return;
+        }
+
+        List<String> features = getFeaturesFromCpuinfo();
+        /* When /proc/cpuinfo is read by 64-bit ARM processes, the Features
+         * field in /proc/cpuinfo must not include ARMv8-required features.
+         * This can be satisified either by not listing required features, or by
+         * not having a Features field at all.
+         */
+        if (features == null) {
+            return;
+        }
+
+        for (String feature : armv8RequiredFeatures) {
+            assertNotInCpuinfo(features, feature);
+        }
+    }
+}
diff --git a/tests/tests/os/src/android/os/cts/CpuInstructions.java b/tests/tests/os/src/android/os/cts/CpuInstructions.java
new file mode 100644
index 0000000..45fb2f1
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/CpuInstructions.java
@@ -0,0 +1,29 @@
+/*
+ * 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.os.cts;
+
+public class CpuInstructions {
+
+    static {
+        System.loadLibrary("ctsos_jni");
+    }
+
+    public static native boolean canReadCntvct();
+    public static native boolean hasSwp();
+    public static native boolean hasSetend();
+    public static native boolean hasCp15Barriers();
+}
diff --git a/tests/tests/os/src/android/os/cts/CpuInstructionsTest.java b/tests/tests/os/src/android/os/cts/CpuInstructionsTest.java
new file mode 100644
index 0000000..c38def7
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/CpuInstructionsTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.os.cts;
+
+import android.os.cts.CpuFeatures;
+import android.os.cts.CpuInstructions;
+
+import junit.framework.TestCase;
+
+public class CpuInstructionsTest extends TestCase {
+
+    public void testArmVirtualCounter() {
+        if (!CpuFeatures.isArm64Cpu()) {
+            return;
+        }
+
+        assertTrue("Machine does not allow access to CNTVCT register",
+                CpuInstructions.canReadCntvct());
+    }
+
+    public void testEmulatedArmCpuFeatures() {
+        if (!CpuFeatures.isArm64CpuIn32BitMode()) {
+            return;
+        }
+
+        assertTrue("Machine does not support ARM swp instruction emulation",
+                CpuInstructions.hasSwp());
+        assertTrue("Machine does not support ARM setend instruction emulation",
+                CpuInstructions.hasSetend());
+        assertTrue("Machine does not support ARM CP15 barrier emulation",
+                CpuInstructions.hasCp15Barriers());
+    }
+}
diff --git a/tests/tests/os/src/android/os/cts/CtsRemoteService.java b/tests/tests/os/src/android/os/cts/CtsRemoteService.java
new file mode 100644
index 0000000..daae49e
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/CtsRemoteService.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2008 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.os.cts;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.Process;
+
+public class CtsRemoteService extends Service{
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        android.util.Log.d("Process test stub", "CtsRemoteServiceProcessPid:" + Process.myPid());
+    }
+
+    private final ISecondary.Stub mSecondaryBinder = new ISecondary.Stub() {
+        public int getPid() {
+            return Process.myPid();
+        }
+
+        public long getElapsedCpuTime() {
+            return Process.getElapsedCpuTime();
+        }
+
+        public String getTimeZoneID() {
+            return java.util.TimeZone.getDefault().getID();
+        }
+    };
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        if (ISecondary.class.getName().equals(intent.getAction())) {
+            return mSecondaryBinder;
+        }
+        return null;
+    }
+
+}
diff --git a/tests/tests/os/src/android/os/cts/DebugTest.java b/tests/tests/os/src/android/os/cts/DebugTest.java
index c05c78a..c097240 100644
--- a/tests/tests/os/src/android/os/cts/DebugTest.java
+++ b/tests/tests/os/src/android/os/cts/DebugTest.java
@@ -22,6 +22,7 @@
 import java.util.logging.Logger;
 
 import android.content.Context;
+import android.cts.util.TestThread;
 import android.os.Debug;
 import android.test.AndroidTestCase;
 import dalvik.system.VMDebug;
diff --git a/tests/tests/os/src/android/os/cts/Debug_InstructionCountTest.java b/tests/tests/os/src/android/os/cts/Debug_InstructionCountTest.java
index 815cb61..24b8dea 100644
--- a/tests/tests/os/src/android/os/cts/Debug_InstructionCountTest.java
+++ b/tests/tests/os/src/android/os/cts/Debug_InstructionCountTest.java
@@ -26,33 +26,9 @@
     public void testDebugInstructionCount() {
         Debug.InstructionCount instructionCount = new Debug.InstructionCount();
 
-        assertTrue(instructionCount.resetAndStart());
-        addTest(1, 2);
-        instructionCount.collect();
-        int insCountsFirst = instructionCount.globalTotal();
-        int methodInvFirst = instructionCount.globalMethodInvocations();
-
-        assertTrue(instructionCount.resetAndStart());
-        addTest(1, 2);
-        addTest(1, 2);
-        instructionCount.collect();
-        int insCountsSecond = instructionCount.globalTotal();
-        int methodInvSecond = instructionCount.globalMethodInvocations();
-
-        assertTrue(instructionCount.resetAndStart());
-        addTest(1, 2);
-        addTest(1, 2);
-        addTest(1, 2);
-        instructionCount.collect();
-        int insCountsThird = instructionCount.globalTotal();
-        int methodInvThird = instructionCount.globalMethodInvocations();
-
-        assertEquals(insCountsThird - insCountsFirst, (insCountsSecond - insCountsFirst) * 2);
-        assertEquals(methodInvThird - methodInvFirst, (methodInvSecond - methodInvFirst) * 2);
-    }
-
-    // must not be private, otherwise javac may inline the code
-    protected int addTest(int a, int b) {
-        return a + b;
+        assertFalse(instructionCount.resetAndStart());
+        assertFalse(instructionCount.collect());
+        assertEquals(0, instructionCount.globalTotal());
+        assertEquals(0, instructionCount.globalMethodInvocations());
     }
 }
diff --git a/tests/src/android/os/cts/EmptyService.java b/tests/tests/os/src/android/os/cts/EmptyService.java
similarity index 100%
rename from tests/src/android/os/cts/EmptyService.java
rename to tests/tests/os/src/android/os/cts/EmptyService.java
diff --git a/tests/tests/os/src/android/os/cts/HandlerTest.java b/tests/tests/os/src/android/os/cts/HandlerTest.java
index 326218d..7183d7e 100644
--- a/tests/tests/os/src/android/os/cts/HandlerTest.java
+++ b/tests/tests/os/src/android/os/cts/HandlerTest.java
@@ -17,11 +17,13 @@
 package android.os.cts;
 
 import junit.framework.TestCase;
+import android.cts.util.TestThread;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 import android.os.SystemClock;
 import android.os.Handler.Callback;
+import android.test.UiThreadTest;
 import android.util.Printer;
 
 public class HandlerTest extends TestCase {
@@ -35,8 +37,9 @@
     static final long DELAYED = RUNTIME + 50;
 
     // Handler
-    Handler mHandler = new Handler();
-    MockHandler mHandler1 = new MockHandler();
+    private final Handler mHandler = new Handler(Looper.getMainLooper());
+    private final MockHandler mHandler1 = new MockHandler(Looper.getMainLooper());
+    private final Object mLock = new Object();
 
     @Override
     protected void tearDown() throws Exception {
@@ -44,18 +47,24 @@
         super.tearDown();
     }
 
-    public void testConstructor() {
-        Callback cb = new Callback() {
+    public void testConstructor() throws Throwable {
+        final Callback cb = new Callback() {
             public boolean handleMessage(Message msg) {
                 return false;
             }
         };
 
+        new TestThread(new Runnable() {
+            public void run() {
+                Looper.prepare();
+                new Handler();
+                new Handler(cb);
+            }
+        }).runTest(RUNTIME);
+
         // new the Handler instance
-        new Handler();
-        new Handler(Looper.myLooper());
-        new Handler(cb);
-        new Handler(Looper.myLooper(), cb);
+        new Handler(Looper.getMainLooper());
+        new Handler(Looper.getMainLooper(), cb);
     }
 
     public void testPostAtTime1() {
@@ -162,9 +171,9 @@
 
     public void testGetLooper() {
         // new the Handler instance
-        Looper looper = Looper.myLooper();
-        mHandler = new Handler(looper);
-        assertSame(looper, mHandler.getLooper());
+        Looper looper = Looper.getMainLooper();
+        Handler handler = new Handler(looper);
+        assertSame(looper, handler.getLooper());
     }
 
     public void testRemoveCallbacks() {
@@ -280,7 +289,7 @@
 
     public void testObtainMessageWithInt() {
          // new the Handler instance
-         Handler handler = new Handler();
+         Handler handler = new Handler(Looper.getMainLooper());
          Message msg = handler.obtainMessage();
          msg.what = 100;
          Message msg1 = mHandler.obtainMessage(msg.what);
@@ -291,7 +300,7 @@
 
     public void testObtainMessageWithIntObject() {
         // new the Handler instance
-        Handler handler = new Handler();
+        Handler handler = new Handler(Looper.getMainLooper());
         Message msg = handler.obtainMessage();
         msg.what = 100;
         msg.obj = new Object();
@@ -304,7 +313,7 @@
 
     public void testObtainMessageWithMutiInt() {
         // new the Handler instance
-        Handler handler = new Handler();
+        Handler handler = new Handler(Looper.getMainLooper());
         Message msg = handler.obtainMessage();
         msg.what = 100;
         msg.arg1 = 101;
@@ -319,7 +328,7 @@
 
     public void testObtainMessageWithMutiIntObject() {
         // new the Handler instance
-        Handler handler = new Handler();
+        Handler handler = new Handler(Looper.getMainLooper());
         Message msg = handler.obtainMessage();
         msg.what = 100;
         msg.arg1 = 1000;
@@ -464,6 +473,14 @@
         public Message message;
         public int what;
 
+        MockHandler() {
+            super(Looper.getMainLooper());
+        }
+
+        MockHandler(Looper looper) {
+            super(looper);
+        }
+
         @Override
         public void handleMessage(Message msg) {
             message = msg;
diff --git a/tests/src/android/os/cts/IEmptyService.aidl b/tests/tests/os/src/android/os/cts/IEmptyService.aidl
similarity index 100%
rename from tests/src/android/os/cts/IEmptyService.aidl
rename to tests/tests/os/src/android/os/cts/IEmptyService.aidl
diff --git a/tests/tests/os/src/android/os/cts/ISecondary.aidl b/tests/tests/os/src/android/os/cts/ISecondary.aidl
new file mode 100644
index 0000000..2c60149
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/ISecondary.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2008 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.os.cts;
+
+interface ISecondary {
+
+    int getPid();
+
+    long getElapsedCpuTime();
+
+    String getTimeZoneID();
+}
diff --git a/tests/tests/os/src/android/os/cts/LaunchpadActivity.java b/tests/tests/os/src/android/os/cts/LaunchpadActivity.java
new file mode 100644
index 0000000..3919ece
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/LaunchpadActivity.java
@@ -0,0 +1,648 @@
+/*
+ * Copyright (C) 2008 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.os.cts;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.test.PerformanceTestCase;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+class MyBadParcelable implements Parcelable {
+    public MyBadParcelable() {
+    }
+
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString("I am bad");
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public static final Parcelable.Creator<MyBadParcelable> CREATOR =
+        new Parcelable.Creator<MyBadParcelable>() {
+        public MyBadParcelable createFromParcel(Parcel in) {
+            return new MyBadParcelable(in);
+        }
+
+        public MyBadParcelable[] newArray(int size) {
+            return new MyBadParcelable[size];
+        }
+    };
+
+    public MyBadParcelable(Parcel in) {
+        in.readString();
+    }
+}
+
+public class LaunchpadActivity extends Activity {
+    public interface CallingTest extends PerformanceTestCase.Intermediates {
+        public void startTiming(boolean realTime);
+
+        public void addIntermediate(String name);
+
+        public void addIntermediate(String name, long timeInNS);
+
+        public void finishTiming(boolean realTime);
+
+        public void activityFinished(int resultCode, Intent data, RuntimeException where);
+    }
+
+    // Also used as the Binder interface descriptor string in these tests
+    public static final String LAUNCH = "android.os.cts.activity.LAUNCH";
+
+    public static final String FORWARD_RESULT = "android.os.cts.activity.FORWARD_RESULT";
+    public static final String RETURNED_RESULT = "android.os.cts.activity.RETURNED_RESULT";
+
+    public static final String BAD_PARCELABLE = "android.os.cts.activity.BAD_PARCELABLE";
+
+    public static final int LAUNCHED_RESULT = 1;
+    public static final int FORWARDED_RESULT = 2;
+
+    public static final String LIFECYCLE_BASIC = "android.os.cts.activity.LIFECYCLE_BASIC";
+    public static final String LIFECYCLE_SCREEN = "android.os.cts.activity.LIFECYCLE_SCREEN";
+    public static final String LIFECYCLE_DIALOG = "android.os.cts.activity.LIFECYCLE_DIALOG";
+
+    public static final String BROADCAST_REGISTERED = "android.os.cts.activity.BROADCAST_REGISTERED";
+    public static final String BROADCAST_LOCAL = "android.os.cts.activity.BROADCAST_LOCAL";
+    public static final String BROADCAST_REMOTE = "android.os.cts.activity.BROADCAST_REMOTE";
+    public static final String BROADCAST_ALL = "android.os.cts.activity.BROADCAST_ALL";
+    public static final String BROADCAST_REPEAT = "android.os.cts.activity.BROADCAST_REPEAT";
+    public static final String BROADCAST_MULTI = "android.os.cts.activity.BROADCAST_MULTI";
+    public static final String BROADCAST_ABORT = "android.os.cts.activity.BROADCAST_ABORT";
+
+    public static final String EXPANDLIST_SELECT = "EXPANDLIST_SELECT";
+    public static final String EXPANDLIST_VIEW = "EXPANDLIST_VIEW";
+    public static final String EXPANDLIST_CALLBACK = "EXPANDLIST_CALLBACK";
+
+    public static final String BROADCAST_STICKY1 = "android.os.cts.activity.BROADCAST_STICKY1";
+    public static final String BROADCAST_STICKY2 = "android.os.cts.activity.BROADCAST_STICKY2";
+
+    public static final String ALIAS_ACTIVITY = "android.os.cts.activity.ALIAS_ACTIVITY";
+
+    public static final String RECEIVER_REG = "receiver-reg";
+    public static final String RECEIVER_LOCAL = "receiver-local";
+    public static final String RECEIVER_REMOTE = "receiver-remote";
+    public static final String RECEIVER_ABORT = "receiver-abort";
+
+    public static final String DATA_1 = "one";
+    public static final String DATA_2 = "two";
+
+    public static final String ON_START = "onStart";
+    public static final String ON_RESTART = "onRestart";
+    public static final String ON_RESUME = "onResume";
+    public static final String ON_FREEZE = "onSaveInstanceState";
+    public static final String ON_PAUSE = "onPause";
+
+    // ON_STOP and ON_DESTROY are not tested because they may not be called.
+
+    public static final String DO_FINISH = "finish";
+    public static final String DO_LOCAL_SCREEN = "local-screen";
+    public static final String DO_LOCAL_DIALOG = "local-dialog";
+
+    private static final String TAG = "LaunchpadActivity";
+
+    private boolean mBadParcelable = false;
+
+    private boolean mStarted = false;
+
+    private int mResultCode = RESULT_CANCELED;
+    private Intent mData = new Intent().setAction("No result received");
+    private RuntimeException mResultStack = null;
+
+    /** Index into the {@link #mNextLifecycle} array. */
+    private int mNextLifecycle;
+
+    /** Current lifecycle expected to be followed. */
+    private String[] mExpectedLifecycle;
+
+    /** Other possible lifecycles. Never includes the current {@link #mExpectedLifecycle}. */
+    private List<String[]> mOtherPossibleLifecycles = new ArrayList<String[]>(2);
+
+    /** Map from lifecycle arrays to debugging log names. */
+    private Map<String[], String> mLifecycleNames = new HashMap<String[], String>(2);
+
+    private String[] mExpectedReceivers = null;
+    private int mNextReceiver;
+
+    private String[] mExpectedData = null;
+    private boolean[] mReceivedData = null;
+
+    boolean mReceiverRegistered = false;
+
+    private static CallingTest sCallingTest = null;
+
+    public static void setCallingTest(CallingTest ct) {
+        sCallingTest = ct;
+    }
+
+    public LaunchpadActivity() {
+    }
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        resetLifecycles();
+
+        // ON_STOP and ON_DESTROY are not tested because they may not be called.
+
+        final String action = getIntent().getAction();
+        if (LIFECYCLE_BASIC.equals(action)) {
+            addPossibleLifecycle(LIFECYCLE_BASIC, new String[] {
+                    ON_START, ON_RESUME, DO_FINISH, ON_PAUSE
+            });
+        } else if (LIFECYCLE_SCREEN.equals(action)) {
+            addPossibleLifecycle(LIFECYCLE_SCREEN + "_RESTART", new String[] {
+                    ON_START, ON_RESUME, DO_LOCAL_SCREEN, ON_PAUSE,
+                    ON_RESTART, ON_START, ON_RESUME, DO_FINISH, ON_PAUSE
+            });
+            addPossibleLifecycle(LIFECYCLE_SCREEN + "_RESUME", new String[] {
+                    ON_START, ON_RESUME, DO_LOCAL_SCREEN, ON_PAUSE,
+                    ON_RESUME, DO_FINISH, ON_PAUSE
+            });
+        } else if (LIFECYCLE_DIALOG.equals(action)) {
+            addPossibleLifecycle(LIFECYCLE_DIALOG + "_RESTART", new String[] {
+                    ON_START, ON_RESUME, DO_LOCAL_DIALOG, ON_PAUSE,
+                    ON_RESTART, ON_START, ON_RESUME, DO_FINISH, ON_PAUSE
+            });
+            addPossibleLifecycle(LIFECYCLE_DIALOG + "_RESUME", new String[] {
+                    ON_START, ON_RESUME, DO_LOCAL_DIALOG, ON_PAUSE,
+                    ON_RESUME, DO_FINISH, ON_PAUSE
+            });
+        }
+    }
+
+    private void resetLifecycles() {
+        mNextLifecycle = 0;
+        mExpectedLifecycle = null;
+        mOtherPossibleLifecycles.clear();
+        mLifecycleNames.clear();
+    }
+
+    /**
+     * Add a potential lifecycle that this activity may follow, since there
+     * are usually multiple valid lifecycles. For instance, sometimes onPause
+     * will lead to onResume rather than onStop when another activity is
+     * raised over the current one.
+     *
+     * @param debugName for the lifecycle shown in the logs
+     * @param lifecycle array containing tokens indicating the expected lifecycle
+     */
+    private void addPossibleLifecycle(String debugName, String[] lifecycle) {
+        mLifecycleNames.put(lifecycle, debugName);
+        if (mExpectedLifecycle == null) {
+            mExpectedLifecycle = lifecycle;
+        } else {
+            mOtherPossibleLifecycles.add(lifecycle);
+        }
+    }
+
+    /**
+     * Switch to the next possible lifecycle and return if switching was
+     * successful. Call this method when mExpectedLifecycle doesn't match
+     * the current lifecycle and you need to check another possible lifecycle.
+     *
+     * @return whether on not there was a lifecycle to switch to
+     */
+    private boolean switchToNextPossibleLifecycle() {
+        if (!mOtherPossibleLifecycles.isEmpty()) {
+            String[] newLifecycle = mOtherPossibleLifecycles.remove(0);
+            Log.w(TAG, "Switching expected lifecycles from "
+                    + mLifecycleNames.get(mExpectedLifecycle) + " to "
+                    + mLifecycleNames.get(newLifecycle));
+            mExpectedLifecycle = newLifecycle;
+            return true;
+        } else {
+            Log.w(TAG, "No more lifecycles after "
+                    + mLifecycleNames.get(mExpectedLifecycle));
+            mExpectedLifecycle = null;
+            return false;
+        }
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+        checkLifecycle(ON_START);
+    }
+
+    @Override
+    protected void onRestart() {
+        super.onStart();
+        checkLifecycle(ON_RESTART);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+
+        checkLifecycle(ON_RESUME);
+
+        if (!mStarted) {
+            mStarted = true;
+
+            mHandler.postDelayed(mTimeout, 10 * 1000);
+
+            final String action = getIntent().getAction();
+
+            sCallingTest.startTiming(true);
+
+            if (LAUNCH.equals(action)) {
+                final Intent intent = getIntent();
+                intent.setFlags(0);
+                intent.setComponent((ComponentName) intent.getParcelableExtra("component"));
+                startActivityForResult(intent, LAUNCHED_RESULT);
+
+            } else if (FORWARD_RESULT.equals(action)) {
+                final Intent intent = getIntent();
+                intent.setFlags(0);
+                intent.setClass(this, LocalScreen.class);
+                startActivityForResult(intent, FORWARDED_RESULT);
+            } else if (BAD_PARCELABLE.equals(action)) {
+                mBadParcelable = true;
+                final Intent intent = getIntent();
+                intent.setFlags(0);
+                intent.setClass(this, LocalScreen.class);
+                startActivityForResult(intent, LAUNCHED_RESULT);
+            } else if (BROADCAST_REGISTERED.equals(action)) {
+                setExpectedReceivers(new String[] {
+                    RECEIVER_REG
+                });
+                registerMyReceiver(new IntentFilter(BROADCAST_REGISTERED));
+                sCallingTest.addIntermediate("after-register");
+                sendBroadcast(makeBroadcastIntent(BROADCAST_REGISTERED));
+            } else if (BROADCAST_LOCAL.equals(action)) {
+                setExpectedReceivers(new String[] {
+                    RECEIVER_LOCAL
+                });
+                sendBroadcast(makeBroadcastIntent(BROADCAST_LOCAL));
+            } else if (BROADCAST_REMOTE.equals(action)) {
+                setExpectedReceivers(new String[] {
+                    RECEIVER_REMOTE
+                });
+                sendBroadcast(makeBroadcastIntent(BROADCAST_REMOTE));
+            } else if (BROADCAST_ALL.equals(action)) {
+                setExpectedReceivers(new String[] {
+                        RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL
+                });
+                registerMyReceiver(new IntentFilter(BROADCAST_ALL));
+                sCallingTest.addIntermediate("after-register");
+                sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null);
+            } else if (BROADCAST_MULTI.equals(action)) {
+                setExpectedReceivers(new String[] {
+                        RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL, RECEIVER_REMOTE,
+                        RECEIVER_REG, RECEIVER_LOCAL, RECEIVER_REMOTE, RECEIVER_REG,
+                        RECEIVER_LOCAL, RECEIVER_LOCAL, RECEIVER_REMOTE, RECEIVER_LOCAL,
+                        RECEIVER_REMOTE, RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL,
+                        RECEIVER_REMOTE, RECEIVER_REG, RECEIVER_LOCAL, RECEIVER_REMOTE,
+                        RECEIVER_REG, RECEIVER_LOCAL, RECEIVER_REMOTE, RECEIVER_LOCAL,
+                        RECEIVER_REMOTE, RECEIVER_LOCAL
+                });
+                registerMyReceiver(new IntentFilter(BROADCAST_ALL));
+                sCallingTest.addIntermediate("after-register");
+                sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null);
+                sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null);
+                sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null);
+                sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_LOCAL), null);
+                sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_REMOTE), null);
+                sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_LOCAL), null);
+                sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_REMOTE), null);
+                sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null);
+                sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null);
+                sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ALL), null);
+                sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_REPEAT), null);
+            } else if (BROADCAST_ABORT.equals(action)) {
+                setExpectedReceivers(new String[] {
+                        RECEIVER_REMOTE, RECEIVER_ABORT
+                });
+                registerMyReceiver(new IntentFilter(BROADCAST_ABORT));
+                sCallingTest.addIntermediate("after-register");
+                sendOrderedBroadcast(makeBroadcastIntent(BROADCAST_ABORT), null);
+            } else if (BROADCAST_STICKY1.equals(action)) {
+                setExpectedReceivers(new String[] {
+                    RECEIVER_REG
+                });
+                setExpectedData(new String[] {
+                    DATA_1
+                });
+                registerMyReceiver(new IntentFilter(BROADCAST_STICKY1));
+                sCallingTest.addIntermediate("after-register");
+            } else if (BROADCAST_STICKY2.equals(action)) {
+                setExpectedReceivers(new String[] {
+                        RECEIVER_REG, RECEIVER_REG
+                });
+                setExpectedData(new String[] {
+                        DATA_1, DATA_2
+                });
+                final IntentFilter filter = new IntentFilter(BROADCAST_STICKY1);
+                filter.addAction(BROADCAST_STICKY2);
+                registerMyReceiver(filter);
+                sCallingTest.addIntermediate("after-register");
+            } else if (ALIAS_ACTIVITY.equals(action)) {
+                final Intent intent = getIntent();
+                intent.setFlags(0);
+                intent.setClass(this, AliasActivityStub.class);
+                startActivityForResult(intent, LAUNCHED_RESULT);
+            } else if (EXPANDLIST_SELECT.equals(action)) {
+                final Intent intent = getIntent();
+                intent.setFlags(0);
+                intent.setAction(action);
+                intent.setComponent((ComponentName) intent.getParcelableExtra("component"));
+                startActivityForResult(intent, LAUNCHED_RESULT);
+            } else if (EXPANDLIST_VIEW.equals(action)) {
+                final Intent intent = getIntent();
+                intent.setFlags(0);
+                intent.setAction(action);
+                intent.setComponent((ComponentName) intent.getParcelableExtra("component"));
+                startActivityForResult(intent, LAUNCHED_RESULT);
+            } else if (EXPANDLIST_CALLBACK.equals(action)) {
+                final Intent intent = getIntent();
+                intent.setFlags(0);
+                intent.setAction(action);
+                intent.setComponent((ComponentName) intent.getParcelableExtra("component"));
+                startActivityForResult(intent, LAUNCHED_RESULT);
+            }
+        }
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle icicle) {
+        super.onSaveInstanceState(icicle);
+        if (mBadParcelable) {
+            icicle.putParcelable("baddy", new MyBadParcelable());
+        }
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        checkLifecycle(ON_PAUSE);
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        switch (requestCode) {
+            case LAUNCHED_RESULT:
+                sCallingTest.finishTiming(true);
+                finishWithResult(resultCode, data);
+                break;
+            case FORWARDED_RESULT:
+                sCallingTest.finishTiming(true);
+                if (RETURNED_RESULT.equals(data.getAction())) {
+                    finishWithResult(resultCode, data);
+                } else {
+                    finishWithResult(RESULT_CANCELED, new Intent().setAction("Bad data returned: "
+                            + data));
+                }
+                break;
+            default:
+                sCallingTest.finishTiming(true);
+                finishWithResult(RESULT_CANCELED, new Intent()
+                        .setAction("Unexpected request code: " + requestCode));
+                break;
+        }
+    }
+
+    private void checkLifecycle(String where) {
+        String action = getIntent().getAction();
+
+        if (mExpectedLifecycle == null) {
+            return;
+        }
+
+        if (mNextLifecycle >= mExpectedLifecycle.length) {
+            finishBad("Activity lifecycle for " + action + " incorrect: received " + where
+                    + " but don't expect any more calls");
+            mExpectedLifecycle = null;
+            return;
+        }
+
+        do {
+            if (mExpectedLifecycle[mNextLifecycle].equals(where)) {
+                Log.w(TAG, "Matched: " + where);
+                break;
+            } else {
+                Log.w(TAG, "Expected " + mExpectedLifecycle[mNextLifecycle] + " but got " + where);
+            }
+        } while (switchToNextPossibleLifecycle());
+
+        if (mExpectedLifecycle == null) {
+            finishBad("Activity lifecycle for " + action + " incorrect: received " + where
+                    + " at " + mNextLifecycle);
+            return;
+        }
+
+        mNextLifecycle++;
+
+        if (mNextLifecycle >= mExpectedLifecycle.length) {
+            finishGood();
+            return;
+        }
+
+        final String next = mExpectedLifecycle[mNextLifecycle];
+        if (next.equals(DO_FINISH)) {
+            mNextLifecycle++;
+            if (mNextLifecycle >= mExpectedLifecycle.length) {
+                setTestResult(RESULT_OK, null);
+            }
+            if (!isFinishing()) {
+                finish();
+            }
+        } else if (next.equals(DO_LOCAL_SCREEN)) {
+            mNextLifecycle++;
+            final Intent intent = new Intent(TestedScreen.WAIT_BEFORE_FINISH);
+            intent.setClass(this, LocalScreen.class);
+            startActivity(intent);
+        } else if (next.equals(DO_LOCAL_DIALOG)) {
+            mNextLifecycle++;
+            final Intent intent = new Intent(TestedScreen.WAIT_BEFORE_FINISH);
+            intent.setClass(this, LocalDialog.class);
+            startActivity(intent);
+        }
+    }
+
+    private void setExpectedReceivers(String[] receivers) {
+        mExpectedReceivers = receivers;
+        mNextReceiver = 0;
+    }
+
+    private void setExpectedData(String[] data) {
+        mExpectedData = data;
+        mReceivedData = new boolean[data.length];
+    }
+
+    @SuppressWarnings("deprecation")
+    private Intent makeBroadcastIntent(String action) {
+        final Intent intent = new Intent(action, null);
+        intent.putExtra("caller", mCallTarget);
+        return intent;
+    }
+
+    private void finishGood() {
+        finishWithResult(RESULT_OK, null);
+    }
+
+    private void finishBad(String error) {
+        finishWithResult(RESULT_CANCELED, new Intent().setAction(error));
+    }
+
+    private void finishWithResult(int resultCode, Intent data) {
+        setTestResult(resultCode, data);
+        finish();
+
+        // Member fields set by calling setTestResult above...
+        sCallingTest.activityFinished(mResultCode, mData, mResultStack);
+    }
+
+    private void setTestResult(int resultCode, Intent data) {
+        mHandler.removeCallbacks(mTimeout);
+        unregisterMyReceiver();
+        mResultCode = resultCode;
+        mData = data;
+        mResultStack = new RuntimeException("Original error was here");
+        mResultStack.fillInStackTrace();
+    }
+
+    private void registerMyReceiver(IntentFilter filter) {
+        mReceiverRegistered = true;
+        registerReceiver(mReceiver, filter);
+    }
+
+    private void unregisterMyReceiver() {
+        if (mReceiverRegistered) {
+            mReceiverRegistered = false;
+            unregisterReceiver(mReceiver);
+        }
+    }
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+        }
+    };
+
+    static final int GOT_RECEIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION;
+    static final int ERROR_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 1;
+
+    private final Binder mCallTarget = new Binder() {
+        @Override
+        public boolean onTransact(int code, Parcel data, Parcel reply, int flags) {
+            data.setDataPosition(0);
+            data.enforceInterface(LaunchpadActivity.LAUNCH);
+            if (code == GOT_RECEIVE_TRANSACTION) {
+                final String name = data.readString();
+                gotReceive(name, null);
+                return true;
+            } else if (code == ERROR_TRANSACTION) {
+                finishBad(data.readString());
+                return true;
+            }
+            return false;
+        }
+    };
+
+    private final void gotReceive(String name, Intent intent) {
+        synchronized (this) {
+
+            sCallingTest.addIntermediate(mNextReceiver + "-" + name);
+
+            if (mExpectedData != null) {
+                final int n = mExpectedData.length;
+                int i;
+                boolean prev = false;
+                for (i = 0; i < n; i++) {
+                    if (mExpectedData[i].equals(intent.getStringExtra("test"))) {
+                        if (mReceivedData[i]) {
+                            prev = true;
+                            continue;
+                        }
+                        mReceivedData[i] = true;
+                        break;
+                    }
+                }
+                if (i >= n) {
+                    if (prev) {
+                        finishBad("Receive got data too many times: "
+                                + intent.getStringExtra("test"));
+                    } else {
+                        finishBad("Receive got unexpected data: " + intent.getStringExtra("test"));
+                    }
+                    return;
+                }
+            }
+
+            if (mNextReceiver >= mExpectedReceivers.length) {
+                finishBad("Got too many onReceiveIntent() calls!");
+            } else if (!mExpectedReceivers[mNextReceiver].equals(name)) {
+                finishBad("Receive out of order: got " + name + " but expected "
+                        + mExpectedReceivers[mNextReceiver] + " at " + mNextReceiver);
+            } else {
+                mNextReceiver++;
+                if (mNextReceiver == mExpectedReceivers.length) {
+                    mHandler.post(mUnregister);
+                }
+            }
+
+        }
+    }
+
+    private final Runnable mUnregister = new Runnable() {
+        public void run() {
+            if (mReceiverRegistered) {
+                sCallingTest.addIntermediate("before-unregister");
+                unregisterMyReceiver();
+            }
+            sCallingTest.finishTiming(true);
+            finishGood();
+        }
+    };
+
+    private final Runnable mTimeout = new Runnable() {
+        public void run() {
+            Log.i(TAG, "timeout");
+            String msg = "Timeout";
+            if (mExpectedReceivers != null && mNextReceiver < mExpectedReceivers.length) {
+                msg = msg + " waiting for " + mExpectedReceivers[mNextReceiver];
+            }
+            finishBad(msg);
+        }
+    };
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            gotReceive(RECEIVER_REG, intent);
+        }
+    };
+}
diff --git a/tests/tests/os/src/android/os/cts/LocalDialog.java b/tests/tests/os/src/android/os/cts/LocalDialog.java
new file mode 100644
index 0000000..6ccca57
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/LocalDialog.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2008 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.os.cts;
+
+public class LocalDialog extends TestedScreen {
+    public LocalDialog() {
+    }
+}
diff --git a/tests/tests/os/src/android/os/cts/LocalScreen.java b/tests/tests/os/src/android/os/cts/LocalScreen.java
new file mode 100644
index 0000000..0a017c4
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/LocalScreen.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2008 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.os.cts;
+
+public class LocalScreen extends TestedScreen {
+    public LocalScreen() {
+    }
+}
diff --git a/tests/tests/os/src/android/os/cts/LocalService.java b/tests/tests/os/src/android/os/cts/LocalService.java
new file mode 100644
index 0000000..cc427f8
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/LocalService.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2008 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.os.cts;
+
+import android.app.Service;
+import android.content.Intent;
+import android.cts.util.IBinderParcelable;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteException;
+
+public class LocalService extends Service {
+    public static final String SERVICE_LOCAL =
+            "android.os.cts.activity.SERVICE_LOCAL";
+    public static final String SERVICE_LOCAL_GRANTED =
+            "android.os.cts.activity.SERVICE_LOCAL_GRANTED";
+    public static final String SERVICE_LOCAL_DENIED =
+            "android.os.cts.activity.SERVICE_LOCAL_DENIED";
+
+    public static final String REPORT_OBJ_NAME = "report";
+
+    public static final int STARTED_CODE = 1;
+    public static final int DESTROYED_CODE = 2;
+    public static final int SET_REPORTER_CODE = 3;
+    public static final int UNBIND_CODE = 4;
+    public static final int REBIND_CODE = 5;
+
+    private IBinder mReportObject;
+    private int mStartCount = 1;
+
+    private final IBinder mBinder = new Binder() {
+        @Override
+        protected boolean onTransact(int code, Parcel data, Parcel reply,
+                int flags) throws RemoteException {
+            if (code == SET_REPORTER_CODE) {
+                data.enforceInterface(SERVICE_LOCAL);
+                mReportObject = data.readStrongBinder();
+                return true;
+            } else {
+                return super.onTransact(code, data, reply, flags);
+            }
+        }
+    };
+
+
+    public LocalService() {
+    }
+
+    @Override
+    public void onStart(Intent intent, int startId) {
+        if (intent.getExtras() != null) {
+            IBinderParcelable parcelable
+                    = (IBinderParcelable) intent.getExtras().getParcelable(REPORT_OBJ_NAME);
+            mReportObject = parcelable.binder;
+            if (mReportObject != null) {
+                bindAction(STARTED_CODE);
+            }
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        if (mReportObject != null) {
+            bindAction(DESTROYED_CODE);
+        }
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mBinder;
+    }
+
+    @Override
+    public boolean onUnbind(Intent intent) {
+        if (mReportObject != null) {
+            bindAction(UNBIND_CODE);
+        }
+        return true;
+    }
+
+    @Override
+    public void onRebind(Intent intent) {
+        if (mReportObject != null) {
+            bindAction(REBIND_CODE);
+        }
+    }
+
+    private void bindAction(final int bindCode) {
+        try {
+            Parcel data = Parcel.obtain();
+            data.writeInterfaceToken(SERVICE_LOCAL);
+            if (bindCode == STARTED_CODE) {
+                data.writeInt(mStartCount);
+                mStartCount++;
+            }
+            mReportObject.transact(
+                    bindCode, data, null, 0);
+            data.recycle();
+        } catch (RemoteException e) {
+            // fail
+        }
+    }
+}
diff --git a/tests/tests/os/src/android/os/cts/LooperTest.java b/tests/tests/os/src/android/os/cts/LooperTest.java
index 6631599..79a55c6 100644
--- a/tests/tests/os/src/android/os/cts/LooperTest.java
+++ b/tests/tests/os/src/android/os/cts/LooperTest.java
@@ -16,6 +16,7 @@
 
 package android.os.cts;
 
+import android.cts.util.TestThread;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -38,7 +39,7 @@
     public void testDump() {
         StringBuilderPrinter printer = new StringBuilderPrinter(new StringBuilder());
         final String prefix = "LooperTest";
-        Looper.myLooper().dump(printer, prefix);
+        Looper.getMainLooper().dump(printer, prefix);
     }
 
     public void testGetMainLooper() {
@@ -78,9 +79,6 @@
     }
 
     public void testMyQueue() throws Throwable {
-        MessageQueue mq = Looper.myQueue();
-        assertNotNull(mq);
-
         TestThread t = new TestThread(new Runnable() {
             public void run() {
                 try {
@@ -89,6 +87,9 @@
                 } catch (Throwable e) {
                     // expected
                 }
+                Looper.prepare();
+                MessageQueue mq = Looper.myQueue();
+                assertNotNull(mq);
             }
         });
 
@@ -96,13 +97,6 @@
     }
 
     public void testPrepare() throws Throwable {
-        try {
-            Looper.prepare();
-            fail("should throw exception because current thread already has a looper");
-        } catch (RuntimeException e) {
-            //expected
-        }
-
         TestThread t = new TestThread(new Runnable() {
             public void run() {
                 Looper.prepare();
@@ -191,7 +185,7 @@
     }
 
     public void testToString() {
-        assertNotNull(Looper.myLooper().toString());
+        assertNotNull(Looper.getMainLooper().toString());
     }
 
     class MockPrinter implements Printer {
diff --git a/tests/tests/os/src/android/os/cts/MemoryFileTest.java b/tests/tests/os/src/android/os/cts/MemoryFileTest.java
index 137f3c3..def73b2 100644
--- a/tests/tests/os/src/android/os/cts/MemoryFileTest.java
+++ b/tests/tests/os/src/android/os/cts/MemoryFileTest.java
@@ -33,13 +33,11 @@
     }
 
     public void testConstructor() throws IOException {
-        // new the MemoryFile instance
         new MemoryFile("Test File", 1024);
     }
 
     public void testWriteBytes() throws IOException {
         byte[] data = new byte[512];
-        // new the MemoryFile instance
         mMemoryFile = new MemoryFile("Test File", 1024);
 
         mMemoryFile.writeBytes(data, 0, 0, 512);
@@ -103,11 +101,14 @@
         mMemoryFile = new MemoryFile("Test File", 512);
         assertEquals(512, mMemoryFile.length());
 
-        mMemoryFile = new MemoryFile("Test File", Integer.MAX_VALUE);
-        assertEquals(Integer.MAX_VALUE, mMemoryFile.length());
+        mMemoryFile = new MemoryFile("Test File", 0);
+        assertEquals(0, mMemoryFile.length());
 
-        mMemoryFile = new MemoryFile("Test File", Integer.MIN_VALUE);
-        assertEquals(Integer.MIN_VALUE, mMemoryFile.length());
+        try {
+            mMemoryFile = new MemoryFile("Test File", -512);
+            fail();
+        } catch (IOException expected) {
+        }
     }
 
     public void testReadBytes() throws IOException {
diff --git a/tests/tests/os/src/android/os/cts/MessageQueueTest.java b/tests/tests/os/src/android/os/cts/MessageQueueTest.java
index 8c38d5f..5b5bf5c 100644
--- a/tests/tests/os/src/android/os/cts/MessageQueueTest.java
+++ b/tests/tests/os/src/android/os/cts/MessageQueueTest.java
@@ -208,17 +208,17 @@
     public void testReleaseSyncBarrierThrowsIfTokenNotValid() throws Exception {
         // Invalid token
         try {
-            Looper.myLooper().removeSyncBarrier(-1);
+            Looper.getMainLooper().removeSyncBarrier(-1);
             fail("Should have thrown IllegalStateException");
         } catch (IllegalStateException ex) {
             // expected
         }
 
         // Token already removed.
-        int barrierToken = Looper.myLooper().postSyncBarrier();
-        Looper.myLooper().removeSyncBarrier(barrierToken);
+        int barrierToken = Looper.getMainLooper().postSyncBarrier();
+        Looper.getMainLooper().removeSyncBarrier(barrierToken);
         try {
-            Looper.myLooper().removeSyncBarrier(barrierToken);
+            Looper.getMainLooper().removeSyncBarrier(barrierToken);
             fail("Should have thrown IllegalStateException");
         } catch (IllegalStateException ex) {
             // expected
diff --git a/tests/tests/os/src/android/os/cts/MessageTest.java b/tests/tests/os/src/android/os/cts/MessageTest.java
index dc56a23..978897b 100644
--- a/tests/tests/os/src/android/os/cts/MessageTest.java
+++ b/tests/tests/os/src/android/os/cts/MessageTest.java
@@ -18,6 +18,7 @@
 
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
 import android.os.Parcel;
 import android.test.AndroidTestCase;
@@ -33,7 +34,7 @@
     private Message mMessage;
     private boolean mMessageHandlerCalled;
 
-    private Handler mHandler = new Handler() {
+    private Handler mHandler = new Handler(Looper.getMainLooper()) {
         public void handleMessage(Message msg) {
             mMessageHandlerCalled = true;
         }
@@ -231,6 +232,70 @@
         assertFalse(message.isAsynchronous());
     }
 
+    public void testRecycleThrowsIfMessageAlreadyRecycled() {
+        Message message = Message.obtain();
+        message.recycle();
+
+        try {
+            message.recycle();
+            fail("should throw IllegalStateException");
+        } catch (IllegalStateException ex) {
+            // expected
+        }
+    }
+
+    public void testSendMessageThrowsIfMessageAlreadyRecycled() {
+        Message message = Message.obtain();
+        message.recycle();
+
+        try {
+            mHandler.sendMessage(message);
+            fail("should throw IllegalStateException");
+        } catch (IllegalStateException ex) {
+            // expected
+        }
+    }
+
+    public void testRecycleThrowsIfMessageIsBeingDelivered() {
+        final Exception[] caught = new Exception[1];
+        Handler handler = new Handler(mHandler.getLooper()) {
+            @Override
+            public void handleMessage(Message msg) {
+                try {
+                    msg.recycle();
+                } catch (IllegalStateException ex) {
+                    caught[0] = ex; // expected
+                }
+            }
+        };
+        handler.sendEmptyMessage(WHAT);
+        sleep(SLEEP_TIME);
+
+        if (caught[0] == null) {
+            fail("should throw IllegalStateException");
+        }
+    }
+
+    public void testSendMessageThrowsIfMessageIsBeingDelivered() {
+        final Exception[] caught = new Exception[1];
+        Handler handler = new Handler(mHandler.getLooper()) {
+            @Override
+            public void handleMessage(Message msg) {
+                try {
+                    mHandler.sendMessage(msg);
+                } catch (IllegalStateException ex) {
+                    caught[0] = ex; // expected
+                }
+            }
+        };
+        handler.sendEmptyMessage(WHAT);
+        sleep(SLEEP_TIME);
+
+        if (caught[0] == null) {
+            fail("should throw IllegalStateException");
+        }
+    }
+
     private void sleep(long time) {
         try {
             Thread.sleep(time);
diff --git a/tests/src/android/os/cts/MessengerService.java b/tests/tests/os/src/android/os/cts/MessengerService.java
similarity index 100%
rename from tests/src/android/os/cts/MessengerService.java
rename to tests/tests/os/src/android/os/cts/MessengerService.java
diff --git a/tests/tests/os/src/android/os/cts/MessengerTest.java b/tests/tests/os/src/android/os/cts/MessengerTest.java
index 0512b23..72bf247 100644
--- a/tests/tests/os/src/android/os/cts/MessengerTest.java
+++ b/tests/tests/os/src/android/os/cts/MessengerTest.java
@@ -43,7 +43,7 @@
     private static final int MSG_ARG1 = 100;
     private static final int MSG_ARG2 = 1000;
     private static final int WHAT = 2008;
-    private Handler mHandler = new Handler() {
+    private Handler mHandler = new Handler(Looper.getMainLooper()) {
         @Override
         public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
             mResult = true;
diff --git a/tests/tests/os/src/android/os/cts/NoExecutePermissionTest.java b/tests/tests/os/src/android/os/cts/NoExecutePermissionTest.java
index 43afb53..224ab46 100644
--- a/tests/tests/os/src/android/os/cts/NoExecutePermissionTest.java
+++ b/tests/tests/os/src/android/os/cts/NoExecutePermissionTest.java
@@ -28,45 +28,26 @@
  */
 public class NoExecutePermissionTest extends TestCase {
 
-    public void testNoExecutePermission() throws FileNotFoundException {
+    static {
+        System.loadLibrary("ctsos_jni");
+    }
+
+    public void testNoExecuteStack() {
         if (!cpuHasNxSupport()) {
             return;
         }
+        assertFalse(isStackExecutable());
+    }
 
-        String heapPermissions = null;
-        String stackPermissions = null;
-
-        Scanner scanner = null;
-        try {
-            scanner = new Scanner(new File("/proc/self/maps"));
-            while (scanner.hasNextLine()) {
-                String line = scanner.nextLine().trim();
-                String[] fields = line.split("\\s+");
-
-                // Sample line:
-                // 0001d000-00024000 rw-p 00000000 00:00 0          [heap]
-                if (fields != null && fields.length >= 1) {
-                    String permissions = fields[1];
-                    if (fields.length >= 6) {
-                        String tag = fields[5];
-                        if ("[heap]".equals(tag)) {
-                            heapPermissions = permissions;
-                        } else if ("[stack]".equals(tag)) {
-                            stackPermissions = permissions;
-                        }
-                    }
-                }
-            }
-        } finally {
-            if (scanner != null) {
-                scanner.close();
-            }
+    public void testNoExecuteHeap() {
+        if (!cpuHasNxSupport()) {
+            return;
         }
+        assertFalse(isHeapExecutable());
+    }
 
-        if (heapPermissions != null) {
-            assertEquals("NX (No Execute) not enabled for heap", "rw-p", heapPermissions);
-        }
-        assertEquals("NX (No Execute) not enabled for stack", "rw-p", stackPermissions);
+    public void testExecuteCode() {
+        assertTrue(isMyCodeExecutable());
     }
 
     private static boolean cpuHasNxSupport() {
@@ -84,4 +65,8 @@
         // have NX support.
         return true;
     }
+
+    private static native boolean isStackExecutable();
+    private static native boolean isHeapExecutable();
+    private static native boolean isMyCodeExecutable();
 }
diff --git a/tests/tests/os/src/android/os/cts/OSFeatures.java b/tests/tests/os/src/android/os/cts/OSFeatures.java
new file mode 100644
index 0000000..9c4660c
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/OSFeatures.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2013 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.os.cts;
+
+public class OSFeatures {
+    static {
+        System.loadLibrary("ctsos_jni");
+    }
+
+    public static native int getNoNewPrivs();
+    public static native int prctlCapBsetRead(int i);
+    public static native boolean hasSeccompSupport();
+    public static native boolean needsSeccompSupport();
+}
diff --git a/tests/tests/os/src/android/os/cts/ProcessTest.java b/tests/tests/os/src/android/os/cts/ProcessTest.java
index 1563068..2ca0fd0 100644
--- a/tests/tests/os/src/android/os/cts/ProcessTest.java
+++ b/tests/tests/os/src/android/os/cts/ProcessTest.java
@@ -16,7 +16,6 @@
 
 package android.os.cts;
 
-import android.app.cts.ISecondary;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -68,9 +67,13 @@
             }
         };
         mIntent = new Intent(REMOTE_SERVICE);
+        mIntent.setPackage(getContext().getPackageName());
         getContext().startService(mIntent);
-        getContext().bindService(new Intent(ISecondary.class.getName()),
-                mSecondaryConnection, Context.BIND_AUTO_CREATE);
+
+        Intent secondaryIntent = new Intent(ISecondary.class.getName());
+        secondaryIntent.setPackage(getContext().getPackageName());
+        getContext().bindService(secondaryIntent, mSecondaryConnection,
+                Context.BIND_AUTO_CREATE);
         synchronized (mSync) {
             if (!mHasConnected) {
                 try {
diff --git a/tests/tests/os/src/android/os/cts/RemoteCallbackListTest.java b/tests/tests/os/src/android/os/cts/RemoteCallbackListTest.java
index 130df05..e00fe89 100644
--- a/tests/tests/os/src/android/os/cts/RemoteCallbackListTest.java
+++ b/tests/tests/os/src/android/os/cts/RemoteCallbackListTest.java
@@ -17,7 +17,6 @@
 package android.os.cts;
 
 
-import android.app.cts.ISecondary;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -60,8 +59,12 @@
             }
         };
         mIntent = new Intent(SERVICE_ACTION);
-        assertTrue(mContext.bindService(new Intent(ISecondary.class.getName()),
-                mSecondaryConnection, Context.BIND_AUTO_CREATE));
+        mIntent.setPackage(mContext.getPackageName());
+
+        Intent secondaryIntent = new Intent(ISecondary.class.getName());
+        secondaryIntent.setPackage(mContext.getPackageName());
+        assertTrue(mContext.bindService(secondaryIntent, mSecondaryConnection,
+                Context.BIND_AUTO_CREATE));
 
     }
 
diff --git a/tests/tests/os/src/android/os/cts/ResultReceiverTest.java b/tests/tests/os/src/android/os/cts/ResultReceiverTest.java
index e784444..47a5d99 100644
--- a/tests/tests/os/src/android/os/cts/ResultReceiverTest.java
+++ b/tests/tests/os/src/android/os/cts/ResultReceiverTest.java
@@ -16,16 +16,15 @@
 
 package android.os.cts;
 
-
-
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Parcel;
 import android.os.ResultReceiver;
 import android.test.AndroidTestCase;
 
 public class ResultReceiverTest extends AndroidTestCase {
-    private Handler mHandler = new Handler();
+    private Handler mHandler = new Handler(Looper.getMainLooper());
     private static final long DURATION = 100l;
 
     public void testResultReceiver() throws InterruptedException {
diff --git a/tests/tests/os/src/android/os/cts/SeccompTest.java b/tests/tests/os/src/android/os/cts/SeccompTest.java
new file mode 100644
index 0000000..6c49337
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/SeccompTest.java
@@ -0,0 +1,33 @@
+/*
+ * 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.os.cts;
+
+import junit.framework.TestCase;
+
+public class SeccompTest extends TestCase {
+
+    public void testSeccomp() {
+        if (CpuFeatures.isArm64Cpu() || CpuFeatures.isArm64CpuIn32BitMode()) {
+            return; // seccomp not yet supported on arm64
+        }
+        if (OSFeatures.needsSeccompSupport()) {
+            assertTrue("Please enable seccomp support "
+                       + "in your kernel (CONFIG_SECCOMP_FILTER=y)",
+                       OSFeatures.hasSeccompSupport());
+        }
+    }
+}
diff --git a/tests/tests/os/src/android/os/cts/SecurityFeaturesTest.java b/tests/tests/os/src/android/os/cts/SecurityFeaturesTest.java
index 6a02974..5a9a4da 100644
--- a/tests/tests/os/src/android/os/cts/SecurityFeaturesTest.java
+++ b/tests/tests/os/src/android/os/cts/SecurityFeaturesTest.java
@@ -16,6 +16,9 @@
 
 package android.os.cts;
 
+import android.system.Os;
+import static android.system.OsConstants.PR_GET_DUMPABLE;
+
 import junit.framework.TestCase;
 
 public class SecurityFeaturesTest extends TestCase {
@@ -49,4 +52,33 @@
             i++;
         }
     }
+
+    /**
+     * Verifies that prctl(PR_GET_DUMPABLE) == ro.debuggable
+     *
+     * When PR_SET_DUMPABLE is 0, an application will not generate a
+     * coredump, and PTRACE_ATTACH is disallowed. It's a security best
+     * practice to ensure that PR_SET_DUMPABLE is 0, to prevent an app
+     * from leaking the contents of its memory to persistent storage,
+     * other processes, or logs.
+     *
+     * By default, PR_SET_DUMPABLE is 0 for zygote spawned apps, except
+     * in the following circumstances:
+     *
+     * 1) ro.debuggable=1 (global debuggable enabled, i.e., userdebug or
+     * eng builds).
+     *
+     * 2) android:debuggable="true" in the manifest for an individual
+     * application.
+     *
+     * 3) An app which explicitly calls prctl(PR_SET_DUMPABLE, 1).
+     *
+     * For this test, neither #2 nor #3 are true, so we expect ro.debuggable
+     * to exactly equal prctl(PR_GET_DUMPABLE).
+     */
+    public void testPrctlDumpable() throws Exception {
+        int ro_debuggable = Integer.parseInt(BuildTest.getProperty(BuildTest.RO_DEBUGGABLE));
+        int prctl_dumpable = Os.prctl(PR_GET_DUMPABLE, 0, 0, 0, 0);
+        assertEquals(ro_debuggable, prctl_dumpable);
+    }
 }
diff --git a/tests/tests/os/src/android/os/cts/TaggedPointer.java b/tests/tests/os/src/android/os/cts/TaggedPointer.java
new file mode 100644
index 0000000..11c3eba
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/TaggedPointer.java
@@ -0,0 +1,26 @@
+/*
+ * 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.os.cts;
+
+public class TaggedPointer {
+
+    static {
+        System.loadLibrary("ctsos_jni");
+    }
+
+    public static native boolean hasTaggedPointer();
+}
diff --git a/tests/tests/os/src/android/os/cts/TaggedPointerTest.java b/tests/tests/os/src/android/os/cts/TaggedPointerTest.java
new file mode 100644
index 0000000..4c619de
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/TaggedPointerTest.java
@@ -0,0 +1,38 @@
+/*
+ * 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.os.cts;
+
+
+import android.test.AndroidTestCase;
+
+import android.os.cts.CpuFeatures;
+import android.os.cts.TaggedPointer;
+
+public class TaggedPointerTest extends AndroidTestCase {
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    public void testHasTaggedPointer() {
+        if (!CpuFeatures.isArm64Cpu()) {
+            return;
+        }
+        assertTrue("Machine does not support tagged pointers", TaggedPointer.hasTaggedPointer());
+    }
+}
diff --git a/tests/tests/os/src/android/os/cts/TestedScreen.java b/tests/tests/os/src/android/os/cts/TestedScreen.java
new file mode 100644
index 0000000..49f3e70
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/TestedScreen.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2008 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.os.cts;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.MessageQueue;
+import android.os.SystemClock;
+import android.util.Log;
+
+public class TestedScreen extends Activity {
+    public static final String WAIT_BEFORE_FINISH = "TestedScreen.WAIT_BEFORE_FINISH";
+    public static final String DELIVER_RESULT = "TestedScreen.DELIVER_RESULT";
+    public static final String CLEAR_TASK = "TestedScreen.CLEAR_TASK";
+    private static final String TAG = "TestedScreen" ;
+    public TestedScreen() {
+    }
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        if (LaunchpadActivity.FORWARD_RESULT.equals(getIntent().getAction())) {
+            final Intent intent = new Intent(getIntent());
+            intent.setAction(DELIVER_RESULT);
+            intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+            startActivity(intent);
+            finish();
+        } else if (DELIVER_RESULT.equals(getIntent().getAction())) {
+            setResult(RESULT_OK, new Intent().setAction(LaunchpadActivity.RETURNED_RESULT));
+            finish();
+        } else if (CLEAR_TASK.equals(getIntent().getAction())) {
+            if (!getIntent().getBooleanExtra(ClearTop.WAIT_CLEAR_TASK, false)) {
+                launchClearTask();
+            }
+        }
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Bundle state) {
+        super.onRestoreInstanceState(state);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        if (CLEAR_TASK.equals(getIntent().getAction())) {
+            if (getIntent().getBooleanExtra(ClearTop.WAIT_CLEAR_TASK, false)) {
+                Looper.myLooper();
+                Looper.myQueue().addIdleHandler(new Idler());
+            }
+        } else {
+            Looper.myLooper();
+            Looper.myQueue().addIdleHandler(new Idler());
+        }
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+    }
+
+    private void launchClearTask() {
+        final Intent intent = new Intent(getIntent()).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+                .setClass(this, ClearTop.class);
+        startActivity(intent);
+    }
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            if (CLEAR_TASK.equals(getIntent().getAction())) {
+                launchClearTask();
+            } else {
+                setResult(RESULT_OK);
+                finish();
+            }
+        }
+    };
+
+    private class Idler implements MessageQueue.IdleHandler {
+        public final boolean queueIdle() {
+            Log.i(TAG, "idle");
+            if (WAIT_BEFORE_FINISH.equals(getIntent().getAction())) {
+                final Message m = Message.obtain();
+                mHandler.sendMessageAtTime(m, SystemClock.uptimeMillis() + 1000);
+            } else if (CLEAR_TASK.equals(getIntent().getAction())) {
+                final Message m = Message.obtain();
+                mHandler.sendMessageAtTime(m, SystemClock.uptimeMillis() + 1000);
+            } else {
+                setResult(RESULT_OK);
+                finish();
+            }
+            return false;
+        }
+    }
+}
diff --git a/tests/tests/os/src/android/os/cts/TokenWatcherTest.java b/tests/tests/os/src/android/os/cts/TokenWatcherTest.java
index 5a4ffcb..70e839a 100644
--- a/tests/tests/os/src/android/os/cts/TokenWatcherTest.java
+++ b/tests/tests/os/src/android/os/cts/TokenWatcherTest.java
@@ -81,9 +81,12 @@
             }
         };
         mIntent = new Intent(EMPTY_SERVICE);
+        mIntent.setPackage(getContext().getPackageName());
         getContext().startService(mIntent);
-        getContext().bindService(new Intent(IEmptyService.class.getName()),
-                mServiceConnection, Context.BIND_AUTO_CREATE);
+
+        Intent secondaryIntent = new Intent(IEmptyService.class.getName());
+        secondaryIntent.setPackage(getContext().getPackageName());
+        getContext().bindService(secondaryIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
         synchronized (mSync) {
             if (!mHasConnected) {
                 try {
diff --git a/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java b/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java
index 45c5e45..a8e8e64 100644
--- a/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java
+++ b/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java
@@ -16,21 +16,25 @@
 
 package android.os.storage.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.os.R;
 
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
 import android.os.Environment;
-import android.os.cts.FileUtils;
+import android.cts.util.FileUtils;
 import android.os.storage.OnObbStateChangeListener;
 import android.os.storage.StorageManager;
 import android.test.AndroidTestCase;
 import android.test.ComparisonFailure;
 import android.util.Log;
 
+import libcore.io.Streams;
+
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.InputStream;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -43,6 +47,7 @@
     private static final long WAIT_TIME_INCR = 5*1000;
 
     private static final String OBB_MOUNT_PREFIX = "/mnt/obb/";
+    private static final String TEST1_CONTENTS = "1\n";
 
     private StorageManager mStorageManager;
 
@@ -52,7 +57,7 @@
         mStorageManager = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
     }
 
-    public void testMountAndUnmountObbNormal() {
+    public void testMountAndUnmountObbNormal() throws IOException {
         for (File target : getTargetFiles()) {
             target = new File(target, "test1.obb");
             Log.d(TAG, "Testing path " + target);
@@ -60,17 +65,22 @@
         }
     }
 
-    private void doMountAndUnmountObbNormal(File outFile) {
+    private void doMountAndUnmountObbNormal(File outFile) throws IOException {
         final String canonPath = mountObb(R.raw.test1, outFile, OnObbStateChangeListener.MOUNTED);
 
         mountObb(R.raw.test1, outFile, OnObbStateChangeListener.ERROR_ALREADY_MOUNTED);
 
-        final String mountPath = checkMountedPath(canonPath);
-        final File mountDir = new File(mountPath);
+        try {
+            final String mountPath = checkMountedPath(canonPath);
+            final File mountDir = new File(mountPath);
+            final File testFile = new File(mountDir, "test1.txt");
 
-        assertTrue("OBB mounted path should be a directory", mountDir.isDirectory());
-
-        unmountObb(outFile, OnObbStateChangeListener.UNMOUNTED);
+            assertTrue("OBB mounted path should be a directory", mountDir.isDirectory());
+            assertTrue("test1.txt does not exist in OBB dir", testFile.exists());
+            assertFileContains(testFile, TEST1_CONTENTS);
+        } finally {
+            unmountObb(outFile, OnObbStateChangeListener.UNMOUNTED);
+        }
     }
 
     public void testAttemptMountNonObb() {
@@ -110,7 +120,7 @@
                 mStorageManager.getMountedObbPath(outFile.getPath()));
     }
 
-    public void testMountAndUnmountTwoObbs() {
+    public void testMountAndUnmountTwoObbs() throws IOException {
         for (File target : getTargetFiles()) {
             Log.d(TAG, "Testing target " + target);
             final File test1 = new File(target, "test1.obb");
@@ -119,7 +129,7 @@
         }
     }
 
-    private void doMountAndUnmountTwoObbs(File file1, File file2) {
+    private void doMountAndUnmountTwoObbs(File file1, File file2) throws IOException {
         ObbObserver oo1 = mountObbWithoutWait(R.raw.test1, file1);
         ObbObserver oo2 = mountObbWithoutWait(R.raw.test1, file2);
 
@@ -128,16 +138,24 @@
         Log.d(TAG, "Waiting for OBB #2 to complete mount");
         waitForObbActionCompletion(file2, oo2, OnObbStateChangeListener.MOUNTED);
 
-        final String mountPath1 = checkMountedPath(oo1.getPath());
-        final File mountDir1 = new File(mountPath1);
-        assertTrue("OBB mounted path should be a directory", mountDir1.isDirectory());
+        try {
+            final String mountPath1 = checkMountedPath(oo1.getPath());
+            final File mountDir1 = new File(mountPath1);
+            final File testFile1 = new File(mountDir1, "test1.txt");
+            assertTrue("OBB mounted path should be a directory", mountDir1.isDirectory());
+            assertTrue("test1.txt does not exist in OBB dir", testFile1.exists());
+            assertFileContains(testFile1, TEST1_CONTENTS);
 
-        final String mountPath2 = checkMountedPath(oo2.getPath());
-        final File mountDir2 = new File(mountPath2);
-        assertTrue("OBB mounted path should be a directory", mountDir2.isDirectory());
-
-        unmountObb(file1, OnObbStateChangeListener.UNMOUNTED);
-        unmountObb(file2, OnObbStateChangeListener.UNMOUNTED);
+            final String mountPath2 = checkMountedPath(oo2.getPath());
+            final File mountDir2 = new File(mountPath2);
+            final File testFile2 = new File(mountDir2, "test1.txt");
+            assertTrue("OBB mounted path should be a directory", mountDir2.isDirectory());
+            assertTrue("test1.txt does not exist in OBB dir", testFile2.exists());
+            assertFileContains(testFile2, TEST1_CONTENTS);
+        } finally {
+            unmountObb(file1, OnObbStateChangeListener.UNMOUNTED);
+            unmountObb(file2, OnObbStateChangeListener.UNMOUNTED);
+        }
     }
 
     private static void assertStartsWith(String message, String prefix, String actual) {
@@ -146,6 +164,15 @@
         }
     }
 
+    private static void assertFileContains(File file, String contents) throws IOException {
+        byte[] actual = Streams.readFully(new FileInputStream(file));
+        byte[] expected = contents.getBytes("UTF-8");
+        assertEquals("unexpected size", expected.length, actual.length);
+        for (int i = 0; i < expected.length; i++) {
+            assertEquals("unexpected value at offset " + i, expected[i], actual[i]);
+        }
+    }
+
     private static class ObbObserver extends OnObbStateChangeListener {
         private String path;
 
diff --git a/tests/tests/permission/Android.mk b/tests/tests/permission/Android.mk
index 07f20d8..6a7da5f 100644
--- a/tests/tests/permission/Android.mk
+++ b/tests/tests/permission/Android.mk
@@ -19,9 +19,12 @@
 
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_JAVA_LIBRARIES := telephony-common
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner guava android-ex-camera2
 
 LOCAL_JNI_SHARED_LIBRARIES := libctspermission_jni
 
@@ -29,8 +32,9 @@
 
 LOCAL_PACKAGE_NAME := CtsPermissionTestCases
 
-# uncomment when dalvik test annotations are removed or part of SDK
+# uncomment when b/13249777 is fixed
 #LOCAL_SDK_VERSION := current
+LOCAL_JAVA_LIBRARIES += android.test.runner
 
 include $(BUILD_CTS_PACKAGE)
 
diff --git a/tests/tests/permission/AndroidManifest.xml b/tests/tests/permission/AndroidManifest.xml
index 945a303..fa03335 100644
--- a/tests/tests/permission/AndroidManifest.xml
+++ b/tests/tests/permission/AndroidManifest.xml
@@ -40,9 +40,12 @@
         package. That runner cannot be added to this package either, since it
         relies on hidden APIs.
     -->
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.cts.permission"
-                     android:label="CTS tests of com.android.cts.permission"/>
+                     android:label="CTS tests of com.android.cts.permission">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/tests/permission/jni/android_permission_cts_FileUtils.cpp b/tests/tests/permission/jni/android_permission_cts_FileUtils.cpp
index 272bbdc..8f32027 100644
--- a/tests/tests/permission/jni/android_permission_cts_FileUtils.cpp
+++ b/tests/tests/permission/jni/android_permission_cts_FileUtils.cpp
@@ -25,6 +25,9 @@
 #include <grp.h>
 #include <pwd.h>
 #include <string.h>
+#include <ScopedLocalRef.h>
+#include <ScopedPrimitiveArray.h>
+#include <ScopedUtfChars.h>
 
 static jfieldID gFileStatusDevFieldID;
 static jfieldID gFileStatusInoFieldID;
@@ -46,14 +49,15 @@
  * Copied from hidden API: frameworks/base/core/jni/android_os_FileUtils.cpp
  */
 
-jboolean android_permission_cts_FileUtils_getFileStatus(JNIEnv* env, jobject thiz,
-        jstring path, jobject fileStatus, jboolean statLinks)
+jboolean android_permission_cts_FileUtils_getFileStatus(JNIEnv* env,
+        jobject /* thiz */, jstring path, jobject fileStatus, jboolean statLinks)
 {
-    const char* pathStr = env->GetStringUTFChars(path, NULL);
+    ScopedUtfChars cPath(env, path);
     jboolean ret = false;
     struct stat s;
 
-    int res = statLinks == true ? lstat(pathStr, &s) : stat(pathStr, &s);
+    int res = statLinks == true ? lstat(cPath.c_str(), &s)
+            : stat(cPath.c_str(), &s);
 
     if (res == 0) {
         ret = true;
@@ -73,20 +77,18 @@
         }
     }
 
-    env->ReleaseStringUTFChars(path, pathStr);
-
     return ret;
 }
 
-jstring android_permission_cts_FileUtils_getUserName(JNIEnv* env, jobject thiz,
-        jint uid)
+jstring android_permission_cts_FileUtils_getUserName(JNIEnv* env,
+        jobject /* thiz */, jint uid)
 {
     struct passwd *pwd = getpwuid(uid);
     return env->NewStringUTF(pwd->pw_name);
 }
 
-jstring android_permission_cts_FileUtils_getGroupName(JNIEnv* env, jobject thiz,
-        jint gid)
+jstring android_permission_cts_FileUtils_getGroupName(JNIEnv* env,
+        jobject /* thiz */, jint gid)
 {
     struct group *grp = getgrgid(gid);
     return env->NewStringUTF(grp->gr_name);
@@ -94,42 +96,106 @@
 
 static jboolean isPermittedCapBitSet(JNIEnv* env, jstring path, size_t capId)
 {
-    const char* pathStr = env->GetStringUTFChars(path, NULL);
-    jboolean ret = false;
-
     struct vfs_cap_data capData;
     memset(&capData, 0, sizeof(capData));
 
-    ssize_t result = getxattr(pathStr, XATTR_NAME_CAPS, &capData,
+    ScopedUtfChars cPath(env, path);
+    ssize_t result = getxattr(cPath.c_str(), XATTR_NAME_CAPS, &capData,
                               sizeof(capData));
-    if (result > 0) {
-      ret = (capData.data[CAP_TO_INDEX(capId)].permitted &
-             CAP_TO_MASK(capId)) != 0;
-      ALOGD("isPermittedCapBitSet(): getxattr(\"%s\") call succeeded, "
-            "cap bit %u %s",
-            pathStr, capId, ret ? "set" : "unset");
-    } else {
-      ALOGD("isPermittedCapBitSet(): getxattr(\"%s\") call failed: "
-            "return %d (error: %s (%d))\n",
-            pathStr, result, strerror(errno), errno);
+    if (result <= 0)
+    {
+          ALOGD("isPermittedCapBitSet(): getxattr(\"%s\") call failed: "
+                  "return %d (error: %s (%d))\n",
+                  cPath.c_str(), result, strerror(errno), errno);
+          return false;
     }
 
-    env->ReleaseStringUTFChars(path, pathStr);
-    return ret;
+    return (capData.data[CAP_TO_INDEX(capId)].permitted &
+            CAP_TO_MASK(capId)) != 0;
 }
 
 jboolean android_permission_cts_FileUtils_hasSetUidCapability(JNIEnv* env,
-        jobject clazz, jstring path)
+        jobject /* clazz */, jstring path)
 {
     return isPermittedCapBitSet(env, path, CAP_SETUID);
 }
 
 jboolean android_permission_cts_FileUtils_hasSetGidCapability(JNIEnv* env,
-        jobject clazz, jstring path)
+        jobject /* clazz */, jstring path)
 {
     return isPermittedCapBitSet(env, path, CAP_SETGID);
 }
 
+static bool throwNamedException(JNIEnv* env, const char* className,
+        const char* message)
+{
+    ScopedLocalRef<jclass> eClazz(env, env->FindClass(className));
+    if (eClazz.get() == NULL)
+    {
+        ALOGE("throwNamedException(): failed to find class %s, cannot throw",
+                className);
+        return false;
+    }
+
+    env->ThrowNew(eClazz.get(), message);
+    return true;
+}
+
+// fill vfs_cap_data's permitted caps given a Java int[] of cap ids
+static bool fillPermittedCaps(vfs_cap_data* capData, JNIEnv* env, jintArray capIds)
+{
+    ScopedIntArrayRO cCapIds(env, capIds);
+    const size_t capCount = cCapIds.size();
+
+    for (size_t i = 0; i < capCount; ++i)
+    {
+        const jint capId = cCapIds[i];
+        if (!cap_valid(capId))
+        {
+            char message[64];
+            snprintf(message, sizeof(message),
+                    "capability id %d out of valid range", capId);
+            throwNamedException(env, "java/lang/IllegalArgumentException",
+                    message);
+
+            return false;
+        }
+        capData->data[CAP_TO_INDEX(capId)].permitted |= CAP_TO_MASK(capId);
+    }
+    return true;
+}
+
+jboolean android_permission_cts_FileUtils_CapabilitySet_fileHasOnly(JNIEnv* env,
+        jobject /* clazz */, jstring path, jintArray capIds)
+{
+    struct vfs_cap_data expectedCapData;
+    memset(&expectedCapData, 0, sizeof(expectedCapData));
+
+    expectedCapData.magic_etc = VFS_CAP_REVISION | VFS_CAP_FLAGS_EFFECTIVE;
+    if (!fillPermittedCaps(&expectedCapData, env, capIds))
+    {
+        // exception thrown
+        return false;
+    }
+
+    struct vfs_cap_data actualCapData;
+    memset(&actualCapData, 0, sizeof(actualCapData));
+
+    ScopedUtfChars cPath(env, path);
+    ssize_t result = getxattr(cPath.c_str(), XATTR_NAME_CAPS, &actualCapData,
+            sizeof(actualCapData));
+    if (result <= 0)
+    {
+        ALOGD("fileHasOnly(): getxattr(\"%s\") call failed: "
+                "return %d (error: %s (%d))\n",
+                cPath.c_str(), result, strerror(errno), errno);
+        return false;
+    }
+
+    return (memcmp(&expectedCapData, &actualCapData,
+            sizeof(struct vfs_cap_data)) == 0);
+}
+
 static JNINativeMethod gMethods[] = {
     {  "getFileStatus", "(Ljava/lang/String;Landroid/permission/cts/FileUtils$FileStatus;Z)Z",
             (void *) android_permission_cts_FileUtils_getFileStatus  },
@@ -143,6 +209,11 @@
             (void *) android_permission_cts_FileUtils_hasSetGidCapability   },
 };
 
+static JNINativeMethod gCapabilitySetMethods[] = {
+    {  "fileHasOnly", "(Ljava/lang/String;[I)Z",
+            (void *) android_permission_cts_FileUtils_CapabilitySet_fileHasOnly  },
+};
+
 int register_android_permission_cts_FileUtils(JNIEnv* env)
 {
     jclass clazz = env->FindClass("android/permission/cts/FileUtils");
@@ -161,6 +232,16 @@
     gFileStatusMtimeFieldID = env->GetFieldID(fileStatusClass, "mtime", "J");
     gFileStatusCtimeFieldID = env->GetFieldID(fileStatusClass, "ctime", "J");
 
-    return env->RegisterNatives(clazz, gMethods, 
-            sizeof(gMethods) / sizeof(JNINativeMethod)); 
+    jint result = env->RegisterNatives(clazz, gMethods,
+            sizeof(gMethods) / sizeof(JNINativeMethod));
+    if (result)
+    {
+      return result;
+    }
+
+    // register FileUtils.CapabilitySet native methods
+    jclass capClazz = env->FindClass("android/permission/cts/FileUtils$CapabilitySet");
+
+    return env->RegisterNatives(capClazz, gCapabilitySetMethods,
+            sizeof(gCapabilitySetMethods) / sizeof(JNINativeMethod));
 }
diff --git a/tests/tests/permission/src/android/permission/cts/AppOpsTest.java b/tests/tests/permission/src/android/permission/cts/AppOpsTest.java
new file mode 100644
index 0000000..c29d5f5
--- /dev/null
+++ b/tests/tests/permission/src/android/permission/cts/AppOpsTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.permission.cts;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.AttributeSet;
+import junit.framework.AssertionFailedError;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class AppOpsTest extends AndroidTestCase {
+    static final Class<?>[] sSetModeSignature = new Class[] {
+            Context.class, AttributeSet.class};
+
+    private AppOpsManager mAppOps;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mAppOps = (AppOpsManager)getContext().getSystemService(Context.APP_OPS_SERVICE);
+        assertNotNull(mAppOps);
+    }
+
+    /**
+     * Test that the app can not change the app op mode for itself.
+     */
+    @SmallTest
+    public void testSetMode() {
+        boolean gotToTest = false;
+        try {
+            Method setMode = mAppOps.getClass().getMethod("setMode", int.class, int.class,
+                    String.class, int.class);
+            int writeSmsOp = mAppOps.getClass().getField("OP_WRITE_SMS").getInt(mAppOps);
+            gotToTest = true;
+            setMode.invoke(mAppOps, writeSmsOp, android.os.Process.myUid(),
+                    getContext().getPackageName(), AppOpsManager.MODE_ALLOWED);
+            fail("Was able to set mode for self");
+        } catch (NoSuchFieldException e) {
+            throw new AssertionError("Unable to find OP_WRITE_SMS", e);
+        } catch (NoSuchMethodException e) {
+            throw new AssertionError("Unable to find setMode method", e);
+        } catch (InvocationTargetException e) {
+            if (!gotToTest) {
+                throw new AssertionError("Whoops", e);
+            }
+            // If we got to the test, we want it to have thrown a security exception.
+            // We need to look inside of the wrapper exception to see.
+            Throwable t = e.getCause();
+            if (!(t instanceof SecurityException)) {
+                throw new AssertionError("Did not throw SecurityException", e);
+            }
+        } catch (IllegalAccessException e) {
+            throw new AssertionError("Whoops", e);
+        }
+    }
+}
diff --git a/tests/tests/permission/src/android/permission/cts/AppWidgetManagerPermissionTest.java b/tests/tests/permission/src/android/permission/cts/AppWidgetManagerPermissionTest.java
index 4223f08..1328f88 100644
--- a/tests/tests/permission/src/android/permission/cts/AppWidgetManagerPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/AppWidgetManagerPermissionTest.java
@@ -51,11 +51,11 @@
         }
 
         try {
-            mAppWidgetManager.bindAppWidgetId(1, new ComponentName(mContext, "foo"));
-            fail("Was able to call bindAppWidgetId");
+            final boolean bound = mAppWidgetManager.bindAppWidgetIdIfAllowed(1,
+                    new ComponentName(mContext, "foo"));
+            assertFalse("Was able to call bindAppWidgetId", bound);
         } catch (SecurityException e) {
             // expected
         }
     }
 }
-
diff --git a/tests/tests/permission/src/android/permission/cts/Camera2PermissionTest.java b/tests/tests/permission/src/android/permission/cts/Camera2PermissionTest.java
new file mode 100644
index 0000000..021a501
--- /dev/null
+++ b/tests/tests/permission/src/android/permission/cts/Camera2PermissionTest.java
@@ -0,0 +1,134 @@
+/*
+ * 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.permission.cts;
+
+import static com.android.ex.camera2.blocking.BlockingStateCallback.*;
+
+import android.content.Context;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraManager;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import com.android.ex.camera2.blocking.BlockingCameraManager;
+import com.android.ex.camera2.blocking.BlockingStateCallback;
+
+/**
+ * Tests for Camera2 API related Permissions. Currently, this means
+ * android.permission.CAMERA.
+ */
+public class Camera2PermissionTest extends AndroidTestCase {
+    private static final String TAG = "CameraDeviceTest";
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+    private static final int CAMERA_CLOSE_TIMEOUT_MS = 2000;
+
+    private CameraManager mCameraManager;
+    private CameraDevice mCamera;
+    private BlockingStateCallback mCameraListener;
+    private String[] mCameraIds;
+    protected Handler mHandler;
+    protected HandlerThread mHandlerThread;
+
+    @Override
+    public void setContext(Context context) {
+        super.setContext(context);
+        mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
+        assertNotNull("Can't connect to camera manager!", mCameraManager);
+    }
+
+    /**
+     * Set up the camera2 test case required environments, including CameraManager,
+     * HandlerThread, Camera IDs, and CameraStateCallback etc.
+     */
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mCameraIds = mCameraManager.getCameraIdList();
+        assertNotNull("Camera ids shouldn't be null", mCameraIds);
+        mHandlerThread = new HandlerThread(TAG);
+        mHandlerThread.start();
+        mHandler = new Handler(mHandlerThread.getLooper());
+        mCameraListener = new BlockingStateCallback();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mHandlerThread.quitSafely();
+        mHandler = null;
+
+        super.tearDown();
+    }
+
+    /**
+     * Attempt to open camera. Requires Permission:
+     * {@link android.Manifest.permission#CAMERA}.
+     */
+    public void testCameraOpen() throws Exception {
+        for (String id : mCameraIds) {
+            try {
+                openCamera(id);
+                fail("Was able to open camera " + id + " with no permission");
+            }
+            catch (SecurityException e) {
+                // expected
+            } finally {
+                closeCamera();
+            }
+        }
+    }
+
+    /**
+     * Add and remove availability listeners should work without permission.
+     */
+    public void testAvailabilityCallback() throws Exception {
+        DummyCameraListener availabilityListener = new DummyCameraListener();
+        // Remove a not-registered listener is a no-op.
+        mCameraManager.unregisterAvailabilityCallback(availabilityListener);
+        mCameraManager.registerAvailabilityCallback(availabilityListener, mHandler);
+        mCameraManager.unregisterAvailabilityCallback(availabilityListener);
+        mCameraManager.registerAvailabilityCallback(availabilityListener, mHandler);
+        mCameraManager.registerAvailabilityCallback(availabilityListener, mHandler);
+        mCameraManager.unregisterAvailabilityCallback(availabilityListener);
+        // Remove a previously-added listener second time is a no-op.
+        mCameraManager.unregisterAvailabilityCallback(availabilityListener);
+    }
+
+    private class DummyCameraListener extends CameraManager.AvailabilityCallback {
+        @Override
+        public void onCameraAvailable(String cameraId) {
+        }
+
+        @Override
+        public void onCameraUnavailable(String cameraId) {
+        }
+    }
+
+    private void openCamera(String cameraId) throws Exception {
+        mCamera = (new BlockingCameraManager(mCameraManager)).openCamera(
+                cameraId, mCameraListener, mHandler);
+    }
+
+    private void closeCamera() {
+        if (mCamera != null) {
+            mCamera.close();
+            mCameraListener.waitForState(STATE_CLOSED, CAMERA_CLOSE_TIMEOUT_MS);
+            mCamera = null;
+        }
+    }
+}
diff --git a/tests/tests/permission/src/android/permission/cts/ConnectivityManagerPermissionTest.java b/tests/tests/permission/src/android/permission/cts/ConnectivityManagerPermissionTest.java
index d9a61f4..8714100 100644
--- a/tests/tests/permission/src/android/permission/cts/ConnectivityManagerPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/ConnectivityManagerPermissionTest.java
@@ -55,22 +55,6 @@
     }
 
     /**
-     * Verify that calling {@link ConnectivityManager#getNetworkPreference()}
-     * requires permissions.
-     * <p>Tests Permission:
-     *   {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
-     */
-    @SmallTest
-    public void testGetNetworkPreference() {
-        try {
-            mConnectivityManager.getNetworkPreference();
-            fail("Was able to call getNetworkPreference");
-        } catch (SecurityException e) {
-            // expected
-        }
-    }
-
-    /**
      * Verify that calling {@link ConnectivityManager#requestRouteToHost(int, int)}
      * requires permissions.
      * <p>Tests Permission:
@@ -85,37 +69,5 @@
             // expected
         }
     }
-
-    /**
-     * Verify that calling {@link ConnectivityManager#setNetworkPreference(int)}
-     * requires permissions.
-     * <p>Tests Permission:
-     *   {@link android.Manifest.permission#CHANGE_NETWORK_STATE}.
-     */
-    @SmallTest
-    public void testSetNetworkPreference() {
-        try {
-            mConnectivityManager.setNetworkPreference(ConnectivityManager.TYPE_MOBILE);
-            fail("Was able to call setNetworkPreference");
-        } catch (SecurityException e) {
-            // expected
-        }
-    }
-
-    /**
-     * Verify that calling {@link ConnectivityManager#setNetworkPreference(int)}
-     * requires permissions.
-     * <p>Tests Permission:
-     *   {@link android.Manifest.permission#CHANGE_NETWORK_STATE}.
-     */
-    @SmallTest
-    public void testStartUsingNetworkPreference() {
-        try {
-            mConnectivityManager.setNetworkPreference(ConnectivityManager.TYPE_MOBILE);
-            fail("Was able to call setNetworkPreference");
-        } catch (SecurityException e) {
-            // expected
-        }
-    }
 }
 
diff --git a/tests/tests/permission/src/android/permission/cts/DevicePowerPermissionTest.java b/tests/tests/permission/src/android/permission/cts/DevicePowerPermissionTest.java
index c5f8ea5..006fb6d 100644
--- a/tests/tests/permission/src/android/permission/cts/DevicePowerPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/DevicePowerPermissionTest.java
@@ -20,7 +20,6 @@
 import android.os.PowerManager;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.LargeTest;
-import dalvik.annotation.KnownFailure;
 
 /**
  * Verify that various PowerManagement functionality requires Permission.
diff --git a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
old mode 100644
new mode 100755
index d455727..c31c484
--- a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
@@ -19,6 +19,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.os.Environment;
+import android.system.OsConstants;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.MediumTest;
 import android.test.suitebuilder.annotation.LargeTest;
@@ -30,7 +31,9 @@
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.FileReader;
+import java.io.InputStream;
 import java.io.IOException;
+import java.io.OutputStream;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executors;
@@ -237,6 +240,29 @@
         assertFileOwnedByGroup(f, "net_bw_stats");
     }
 
+    @MediumTest
+    public void testTcpDefaultRwndSane() throws Exception {
+        File f = new File("/proc/sys/net/ipv4/tcp_default_init_rwnd");
+        assertTrue(f.canRead());
+        assertFalse(f.canWrite());
+        assertFalse(f.canExecute());
+
+        assertFileOwnedBy(f, "root");
+        assertFileOwnedByGroup(f, "root");
+    }
+
+    @MediumTest
+    public void testIdletimerDirectoryExistsAndSane() throws Exception {
+        File dir = new File("/sys/class/xt_idletimer");
+        assertTrue(dir.isDirectory());
+        assertTrue(dir.canRead());
+        assertFalse(dir.canWrite());
+        assertTrue(dir.canExecute());
+
+        assertFileOwnedBy(dir, "root");
+        assertFileOwnedByGroup(dir, "root");
+    }
+
     /**
      * Assert that a file is owned by a specific owner. This is a noop if the
      * file does not exist.
@@ -734,6 +760,8 @@
                 new File("/dev/alarm"),      // b/9035217
                 new File("/dev/ashmem"),
                 new File("/dev/binder"),
+                new File("/dev/card0"),       // b/13159510
+                new File("/dev/dri/card0"),   // b/13159510
                 new File("/dev/felica"),     // b/11142586
                 new File("/dev/felica_ant"), // b/11142586
                 new File("/dev/felica_cen"), // b/11142586
@@ -742,7 +770,9 @@
                 new File("/dev/felica_rws"), // b/11142586
                 new File("/dev/felica_uicc"), // b/11142586
                 new File("/dev/full"),
+                new File("/dev/galcore"),
                 new File("/dev/genlock"),    // b/9035217
+                new File("/dev/graphics/galcore"),
                 new File("/dev/ion"),
                 new File("/dev/kgsl-2d0"),   // b/11271533
                 new File("/dev/kgsl-2d1"),   // b/11271533
@@ -753,6 +783,9 @@
                 new File("/dev/log/system"), // b/9035217
                 new File("/dev/mali0"),       // b/9106968
                 new File("/dev/mali"),        // b/11142586
+                new File("/dev/mm_interlock"), // b/12955573
+                new File("/dev/mm_isp"),      // b/12955573
+                new File("/dev/mm_v3d"),      // b/12955573
                 new File("/dev/msm_rotator"), // b/9035217
                 new File("/dev/null"),
                 new File("/dev/nvhost-as-gpu"),
@@ -796,19 +829,29 @@
     }
 
     public void testDevRandomWorldReadableAndWritable() throws Exception {
+        File f = new File("/dev/random");
+
+        assertTrue(f + " cannot be opened for reading", canOpenForReading(f));
+        assertTrue(f + " cannot be opened for writing", canOpenForWriting(f));
+
         FileUtils.FileStatus status = new FileUtils.FileStatus();
-        assertTrue(FileUtils.getFileStatus("/dev/random", status, false));
+        assertTrue(FileUtils.getFileStatus(f.getPath(), status, false));
         assertTrue(
-                "/dev/random not world-readable/writable. Actual mode: 0"
+                f + " not world-readable/writable. Actual mode: 0"
                         + Integer.toString(status.mode, 8),
                 (status.mode & 0666) == 0666);
     }
 
     public void testDevUrandomWorldReadableAndWritable() throws Exception {
+        File f = new File("/dev/urandom");
+
+        assertTrue(f + " cannot be opened for reading", canOpenForReading(f));
+        assertTrue(f + " cannot be opened for writing", canOpenForWriting(f));
+
         FileUtils.FileStatus status = new FileUtils.FileStatus();
-        assertTrue(FileUtils.getFileStatus("/dev/urandom", status, false));
+        assertTrue(FileUtils.getFileStatus(f.getPath(), status, false));
         assertTrue(
-                "/dev/urandom not world-readable/writable. Actual mode: 0"
+                f + " not world-readable/writable. Actual mode: 0"
                         + Integer.toString(status.mode, 8),
                 (status.mode & 0666) == 0666);
     }
@@ -820,15 +863,52 @@
             return;
         }
 
-        FileUtils.FileStatus status = new FileUtils.FileStatus();
-        assertTrue(FileUtils.getFileStatus(f.getCanonicalPath(), status, false));
-        assertTrue(
-                f + " has wrong file mode: 0"
-                        + Integer.toOctalString(status.mode),
-                (status.mode & 0777) == 0440);
+        assertFalse(f + " can be opened for reading", canOpenForReading(f));
+        assertFalse(f + " can be opened for writing", canOpenForWriting(f));
 
-        assertFileOwnedBy(f, "root");
-        assertFileOwnedByGroup(f, "system");
+        FileUtils.FileStatus status = new FileUtils.FileStatus();
+        assertFalse("stat permitted on " + f,
+                FileUtils.getFileStatus(f.getPath(), status, false));
+    }
+
+    private static boolean canOpenForReading(File f) {
+        try (InputStream in = new FileInputStream(f)) {
+            return true;
+        } catch (IOException expected) {
+            return false;
+        }
+    }
+
+    private static boolean canOpenForWriting(File f) {
+        try (OutputStream out = new FileOutputStream(f)) {
+            return true;
+        } catch (IOException expected) {
+            return false;
+        }
+    }
+
+    public void testFileHasOnlyCapsThrowsOnInvalidCaps() throws Exception {
+        try {
+            // Ensure negative cap id fails.
+            new FileUtils.CapabilitySet()
+                    .add(-1)
+                    .fileHasOnly("/system/bin/run-as");
+            fail();
+        }
+        catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            // Ensure too-large cap throws.
+            new FileUtils.CapabilitySet()
+                    .add(OsConstants.CAP_LAST_CAP + 1)
+                    .fileHasOnly("/system/bin/run-as");
+            fail();
+        }
+        catch (IllegalArgumentException e) {
+            // expected
+        }
     }
 
     /**
@@ -853,6 +933,12 @@
         // ensure file has setuid/setgid enabled
         assertTrue(FileUtils.hasSetUidCapability(filename));
         assertTrue(FileUtils.hasSetGidCapability(filename));
+
+        // ensure file has *only* setuid/setgid attributes enabled
+        assertTrue(new FileUtils.CapabilitySet()
+                .add(OsConstants.CAP_SETUID)
+                .add(OsConstants.CAP_SETGID)
+                .fileHasOnly("/system/bin/run-as"));
     }
 
     private static Set<File>
diff --git a/tests/tests/permission/src/android/permission/cts/FileUtils.java b/tests/tests/permission/src/android/permission/cts/FileUtils.java
index 9cd4999..af44a1c 100644
--- a/tests/tests/permission/src/android/permission/cts/FileUtils.java
+++ b/tests/tests/permission/src/android/permission/cts/FileUtils.java
@@ -16,6 +16,13 @@
  * limitations under the License.
  */
 
+import com.google.common.primitives.Ints;
+
+import android.system.OsConstants;
+
+import java.util.HashSet;
+import java.util.Set;
+
 /** Bits and pieces copied from hidden API of android.os.FileUtils. */
 public class FileUtils {
 
@@ -82,6 +89,27 @@
         }
     }
 
+    public static class CapabilitySet {
+
+        private final Set<Integer> mCapabilities = new HashSet<Integer>();
+
+        public CapabilitySet add(int capability) {
+            if ((capability < 0) || (capability > OsConstants.CAP_LAST_CAP)) {
+                throw new IllegalArgumentException(String.format(
+                        "capability id %d out of valid range", capability));
+            }
+            mCapabilities.add(capability);
+            return this;
+        }
+
+        private native static boolean fileHasOnly(String path,
+                int[] capabilities);
+
+        public boolean fileHasOnly(String path) {
+            return fileHasOnly(path, Ints.toArray(mCapabilities));
+        }
+    }
+
     /**
      * @param path of the file to stat
      * @param status object to set the fields on
diff --git a/tests/tests/permission/src/android/permission/cts/NoActivityRelatedPermissionTest.java b/tests/tests/permission/src/android/permission/cts/NoActivityRelatedPermissionTest.java
index 62b3683..91ffdf4 100644
--- a/tests/tests/permission/src/android/permission/cts/NoActivityRelatedPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NoActivityRelatedPermissionTest.java
@@ -27,6 +27,8 @@
 import android.view.WindowManager;
 import android.view.WindowManager.BadTokenException;
 
+import java.util.List;
+
 /**
  * Verify the Activity related operations require specific permissions.
  */
@@ -54,18 +56,16 @@
     public void testGetTask() {
         ActivityManager manager = (ActivityManager) getActivity()
                 .getSystemService(Context.ACTIVITY_SERVICE);
-        try {
-            manager.getRunningTasks(1);
-            fail("Activity.getRunningTasks did not throw SecurityException as expected");
-        } catch (SecurityException e) {
-            // Expected
-        }
+        List<ActivityManager.RunningTaskInfo> runningTasks =  manager.getRunningTasks(10);
+        // Current implementation should only return tasks for home and the caller.
+        // We'll be done and task this to mean it shouldn't return more than 2.
+        assertTrue("Found tasks: " + runningTasks,
+                runningTasks == null || runningTasks.size() <= 2);
 
-        try {
-            manager.getRecentTasks(1, 0);
-            fail("Activity.getRunningTasks did not throw SecurityException as expected");
-        } catch (SecurityException e) {
-            // Expected
-        }
+        List<ActivityManager.RecentTaskInfo> recentTasks = manager.getRecentTasks(10,
+                ActivityManager.RECENT_WITH_EXCLUDED);
+        // Current implementation should only return tasks for home and the caller.
+        // We'll be done and task this to mean it shouldn't return more than 2.
+        assertTrue("Found tasks: " + recentTasks, recentTasks == null || recentTasks.size() <= 2);
     }
 }
diff --git a/tests/tests/permission/src/android/permission/cts/NoLocationPermissionTest.java b/tests/tests/permission/src/android/permission/cts/NoLocationPermissionTest.java
index b5a4f24..8fd4a59 100644
--- a/tests/tests/permission/src/android/permission/cts/NoLocationPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NoLocationPermissionTest.java
@@ -27,28 +27,31 @@
 import android.os.Looper;
 import android.telephony.PhoneStateListener;
 import android.telephony.TelephonyManager;
-import android.test.AndroidTestCase;
+import android.test.InstrumentationTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
+import android.test.UiThreadTest;
 
 import java.util.List;
 
 /**
  * Verify the location access without specific permissions.
  */
-public class NoLocationPermissionTest extends AndroidTestCase {
+public class NoLocationPermissionTest extends InstrumentationTestCase {
     private static final String TEST_PROVIDER_NAME = "testProvider";
 
     private LocationManager mLocationManager;
     private List<String> mAllProviders;
     private boolean mHasTelephony;
+    private Context mContext;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mLocationManager = (LocationManager) getContext().getSystemService(
+        mContext = getInstrumentation().getTargetContext();
+        mLocationManager = (LocationManager) mContext.getSystemService(
                 Context.LOCATION_SERVICE);
         mAllProviders = mLocationManager.getAllProviders();
-        mHasTelephony = getContext().getPackageManager().hasSystemFeature(
+        mHasTelephony = mContext.getPackageManager().hasSystemFeature(
                 PackageManager.FEATURE_TELEPHONY);
 
         assertNotNull(mLocationManager);
@@ -65,13 +68,13 @@
      * Requires Permission: {@link
      * android.Manifest.permission#ACCESS_COARSE_LOCATION.}
      */
-    @SmallTest
+    @UiThreadTest
     public void testListenCellLocation() {
         if (!mHasTelephony) {
             return;
         }
 
-        TelephonyManager telephonyManager = (TelephonyManager) getContext().getSystemService(
+        TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(
                 Context.TELEPHONY_SERVICE);
         PhoneStateListener phoneStateListener = new PhoneStateListener();
         try {
@@ -96,13 +99,13 @@
      * Requires Permission: {@link
      * android.Manifest.permission#ACCESS_COARSE_LOCATION.}
      */
-    @SmallTest
+    @UiThreadTest
     public void testListenCellLocation2() {
         if (!mHasTelephony) {
             return;
         }
 
-        TelephonyManager telephonyManager = (TelephonyManager) getContext().getSystemService(
+        TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(
                 Context.TELEPHONY_SERVICE);
         PhoneStateListener phoneStateListener = new PhoneStateListener();
 
@@ -158,7 +161,7 @@
      * Requires Permission:
      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
      */
-    @SmallTest
+    @UiThreadTest
     public void testRequestLocationUpdatesNetwork() {
         checkRequestLocationUpdates(LocationManager.NETWORK_PROVIDER);
     }
@@ -169,7 +172,7 @@
      * Requires Permission:
      * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
      */
-    @SmallTest
+    @UiThreadTest
     public void testRequestLocationUpdatesGps() {
         checkRequestLocationUpdates(LocationManager.GPS_PROVIDER);
     }
@@ -182,7 +185,7 @@
      */
     @SmallTest
     public void testAddProximityAlert() {
-        PendingIntent mockPendingIntent = PendingIntent.getBroadcast(getContext(),
+        PendingIntent mockPendingIntent = PendingIntent.getBroadcast(mContext,
                 0, new Intent("mockIntent"), PendingIntent.FLAG_ONE_SHOT);
         try {
             mLocationManager.addProximityAlert(0, 0, 100, -1, mockPendingIntent);
@@ -280,9 +283,13 @@
     }
 
     /**
-     * Helper method to verify that calling isProviderEnabled with given
-     * provider throws SecurityException.
-     * 
+     * Helper method to verify that calling
+     * {@link LocationManager#isProviderEnabled(String)} with given
+     * provider completes without an exception. (Note that under the conditions
+     * of these tests, that method threw SecurityException on OS levels before
+     * {@link android.os.Build.VERSION_CODES#LOLLIPOP}. See the method's javadoc for
+     * details.)
+     *
      * @param provider the String provider name.
      */
     private void checkIsProviderEnabled(String provider) {
@@ -290,13 +297,7 @@
             // skip this test if the provider is unknown
             return;
         }
-
-        try {
-            mLocationManager.isProviderEnabled(provider);
-            fail("LocationManager.isProviderEnabled did not throw SecurityException as expected");
-        } catch (SecurityException e) {
-            // expected
-        }
+        mLocationManager.isProviderEnabled(provider);
     }
 
     /**
diff --git a/tests/tests/permission/src/android/permission/cts/NoNetworkStatePermissionTest.java b/tests/tests/permission/src/android/permission/cts/NoNetworkStatePermissionTest.java
index 0f24cf5..0eae9cc 100644
--- a/tests/tests/permission/src/android/permission/cts/NoNetworkStatePermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NoNetworkStatePermissionTest.java
@@ -27,9 +27,8 @@
  */
 public class NoNetworkStatePermissionTest extends AndroidTestCase {
     private ConnectivityManager mConnectivityManager;
-    private static final int TEST_NETWORK_TYPE = 1;
-    private static final int TEST_PREFERENCE = 1;
-    private static final String TEST_FEATURE = "feature";
+    private static final int TEST_NETWORK_TYPE = ConnectivityManager.TYPE_MOBILE;
+    private static final String TEST_FEATURE = "enableHIPRI";
 
     @Override
     protected void setUp() throws Exception {
@@ -40,22 +39,6 @@
     }
 
     /**
-     * Verify that ConnectivityManager#getNetworkPreference() requires permissions.
-     * <p>Requires Permission:
-     *   {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
-     */
-    @SmallTest
-    public void testGetNetworkPreference() {
-        try {
-            mConnectivityManager.getNetworkPreference();
-            fail("ConnectivityManager.getNetworkPreference didn't throw SecurityException as"
-                    + " expected");
-        } catch (SecurityException e) {
-            // expected
-        }
-    }
-
-    /**
      * Verify that ConnectivityManager#getActiveNetworkInfo() requires permissions.
      * <p>Requires Permission:
      *   {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
@@ -104,22 +87,6 @@
     }
 
     /**
-     * Verify that ConnectivityManager#setNetworkPreference() requires permissions.
-     * <p>Requires Permission:
-     *   {@link android.Manifest.permission#CHANGE_NETWORK_STATE}.
-     */
-    @SmallTest
-    public void testSetNetworkPreference() {
-        try {
-            mConnectivityManager.setNetworkPreference(TEST_PREFERENCE);
-            fail("ConnectivityManager.setNetworkPreference didn't throw SecurityException as"
-                    + " expected");
-        } catch (SecurityException e) {
-            // expected
-        }
-    }
-
-    /**
      * Verify that ConnectivityManager#startUsingNetworkFeature() requires permissions.
      * <p>Requires Permission:
      *   {@link android.Manifest.permission#CHANGE_NETWORK_STATE}.
@@ -136,22 +103,6 @@
     }
 
     /**
-     * Verify that ConnectivityManager#stopUsingNetworkFeature() requires permissions.
-     * <p>Requires Permission:
-     *   {@link android.Manifest.permission#CHANGE_NETWORK_STATE}.
-     */
-    @SmallTest
-    public void testStopUsingNetworkFeature() {
-        try {
-            mConnectivityManager.stopUsingNetworkFeature(TEST_NETWORK_TYPE, TEST_FEATURE);
-            fail("ConnectivityManager.stopUsingNetworkFeature didn't throw SecurityException as"
-                    + " expected");
-        } catch (SecurityException e) {
-            // expected
-        }
-    }
-
-    /**
      * Verify that ConnectivityManager#requestRouteToHost() requires permissions.
      * <p>Requires Permission:
      *   {@link android.Manifest.permission#CHANGE_NETWORK_STATE}.
diff --git a/tests/tests/permission/src/android/permission/cts/NoReadLogsPermissionTest.java b/tests/tests/permission/src/android/permission/cts/NoReadLogsPermissionTest.java
index 9441319..8979a07 100644
--- a/tests/tests/permission/src/android/permission/cts/NoReadLogsPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NoReadLogsPermissionTest.java
@@ -16,7 +16,10 @@
 
 package android.permission.cts;
 
-import android.permission.cts.FileUtils.FileStatus;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
+import android.system.StructStat;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.MediumTest;
 import android.util.Log;
@@ -72,19 +75,30 @@
         }
     }
 
-    public void testLogFilePermissions() {
-        File logDir = new File("/dev/log");
-        File[] logFiles = logDir.listFiles();
-        assertTrue("Where are the log files? Please check that they are not world readable.",
-                logFiles.length > 0);
+    public void testEventsLogSane() throws ErrnoException {
+        testLogIsSane("/dev/log/events");
+    }
 
-        FileStatus status = new FileStatus();
-        for (File log : logFiles) {
-            if (FileUtils.getFileStatus(log.getAbsolutePath(), status, false)) {
-                assertEquals("Log file " + log.getAbsolutePath() + " should have user root.",
-                        0, status.uid);
-                assertTrue("Log file " + log.getAbsolutePath() + " should have group log.",
-                        "log".equals(FileUtils.getGroupName(status.gid)));
+    public void testMainLogSane() throws ErrnoException {
+        testLogIsSane("/dev/log/main");
+    }
+
+    public void testRadioLogSane() throws ErrnoException {
+        testLogIsSane("/dev/log/radio");
+    }
+
+    public void testSystemLogSane() throws ErrnoException {
+        testLogIsSane("/dev/log/system");
+    }
+
+    private static void testLogIsSane(String log) throws ErrnoException {
+        try {
+            StructStat stat = Os.stat(log);
+            assertEquals("not owned by uid=0", 0, stat.st_uid);
+            assertEquals("not owned by gid=logs", "log", FileUtils.getGroupName(stat.st_gid));
+        } catch (ErrnoException e) {
+            if (e.errno != OsConstants.ENOENT && e.errno != OsConstants.EACCES) {
+                throw e;
             }
         }
     }
diff --git a/tests/tests/permission/src/android/permission/cts/TelephonyManagerPermissionTest.java b/tests/tests/permission/src/android/permission/cts/TelephonyManagerPermissionTest.java
index 2681c0f..607f301 100644
--- a/tests/tests/permission/src/android/permission/cts/TelephonyManagerPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/TelephonyManagerPermissionTest.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.media.AudioManager;
 import android.telephony.TelephonyManager;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -29,6 +30,7 @@
 
     private boolean mHasTelephony;
     TelephonyManager mTelephonyManager = null;
+    private AudioManager mAudioManager;
 
     @Override
     protected void setUp() throws Exception {
@@ -37,6 +39,8 @@
                 PackageManager.FEATURE_TELEPHONY);
         mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
         assertNotNull(mTelephonyManager);
+        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+        assertNotNull(mAudioManager);
     }
 
     /**
@@ -138,4 +142,21 @@
             // expected
         }
     }
+    /**
+     * Verify that AudioManager.setMode requires Permission.
+     * <p>
+     * Requires Permissions:
+     * {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS} and
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE} for
+     * {@link AudioManager#MODE_IN_CALL}.
+     */
+    @SmallTest
+    public void testSetMode() {
+        if (!mHasTelephony) {
+            return;
+        }
+        int audioMode = mAudioManager.getMode();
+        mAudioManager.setMode(AudioManager.MODE_IN_CALL);
+        assertEquals(audioMode, mAudioManager.getMode());
+    }
 }
diff --git a/tests/tests/permission2/Android.mk b/tests/tests/permission2/Android.mk
index 86a8bc7..29d5e03 100755
--- a/tests/tests/permission2/Android.mk
+++ b/tests/tests/permission2/Android.mk
@@ -19,7 +19,7 @@
 
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common mms-common
+LOCAL_JAVA_LIBRARIES := telephony-common
 
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
diff --git a/tests/tests/permission2/AndroidManifest.xml b/tests/tests/permission2/AndroidManifest.xml
index 1c1a0d8..c0b78c4 100755
--- a/tests/tests/permission2/AndroidManifest.xml
+++ b/tests/tests/permission2/AndroidManifest.xml
@@ -56,9 +56,12 @@
             android:name="android.permission.FLASHLIGHT"
             android:maxSdkVersion="9000" />
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.cts.permission2"
-                     android:label="More CTS tests for permissions"/>
+                     android:label="More CTS tests for permissions">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/tests/preference/Android.mk b/tests/tests/preference/Android.mk
index cc2b210..7534641 100644
--- a/tests/tests/preference/Android.mk
+++ b/tests/tests/preference/Android.mk
@@ -20,16 +20,12 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsPreferenceTestCases
 
-LOCAL_INSTRUMENTATION_FOR := CtsTestStubs
-
 LOCAL_SDK_VERSION := current
 
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/preference/AndroidManifest.xml b/tests/tests/preference/AndroidManifest.xml
index 3477192..3cc3ef8 100644
--- a/tests/tests/preference/AndroidManifest.xml
+++ b/tests/tests/preference/AndroidManifest.xml
@@ -21,11 +21,18 @@
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
     <application>
         <uses-library android:name="android.test.runner" />
+        <activity android:name="android.preference.cts.PreferenceCtsActivity">
+            <meta-data android:name="android.preference"
+                    android:resource="@xml/preferences_from_intent" />
+        </activity>
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="com.android.cts.stub"
-                     android:label="CTS tests of android.os"/>
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.preference"
+                     android:label="CTS tests of android.os">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/res/xml/preferences_from_intent.xml b/tests/tests/preference/res/xml/preferences_from_intent.xml
similarity index 100%
rename from tests/res/xml/preferences_from_intent.xml
rename to tests/tests/preference/res/xml/preferences_from_intent.xml
diff --git a/tests/res/xml/preferences_from_resource.xml b/tests/tests/preference/res/xml/preferences_from_resource.xml
similarity index 100%
rename from tests/res/xml/preferences_from_resource.xml
rename to tests/tests/preference/res/xml/preferences_from_resource.xml
diff --git a/tests/tests/preference/src/android/preference/cts/PreferenceActivityTest.java b/tests/tests/preference/src/android/preference/cts/PreferenceActivityTest.java
index b0d5448..51ebc7d 100644
--- a/tests/tests/preference/src/android/preference/cts/PreferenceActivityTest.java
+++ b/tests/tests/preference/src/android/preference/cts/PreferenceActivityTest.java
@@ -16,7 +16,7 @@
 
 package android.preference.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.preference.R;
 
 import android.content.Intent;
 import android.preference.PreferenceActivity;
@@ -25,12 +25,12 @@
 import android.test.ActivityInstrumentationTestCase2;
 
 public class PreferenceActivityTest
-        extends ActivityInstrumentationTestCase2<PreferenceStubActivity> {
+        extends ActivityInstrumentationTestCase2<PreferenceCtsActivity> {
 
     private PreferenceActivity mActivity;
 
     public PreferenceActivityTest() {
-        super(PreferenceStubActivity.class);
+        super(PreferenceCtsActivity.class);
     }
 
     @Override
@@ -42,7 +42,7 @@
     public void testAddPreferencesFromIntent() {
         assertNull(mActivity.findPreference("check_box_preference_from_intent"));
 
-        Intent intent = new Intent(mActivity, PreferenceStubActivity.class);
+        Intent intent = new Intent(mActivity, PreferenceCtsActivity.class);
         mActivity.addPreferencesFromIntent(intent);
 
         assertNotNull(mActivity.findPreference("check_box_preference_from_intent"));
diff --git a/tests/tests/preference/src/android/preference/cts/PreferenceCtsActivity.java b/tests/tests/preference/src/android/preference/cts/PreferenceCtsActivity.java
new file mode 100644
index 0000000..99cf3b3
--- /dev/null
+++ b/tests/tests/preference/src/android/preference/cts/PreferenceCtsActivity.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2010 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.preference.cts;
+
+import android.preference.PreferenceActivity;
+
+public class PreferenceCtsActivity extends PreferenceActivity {
+}
diff --git a/tests/tests/preference2/Android.mk b/tests/tests/preference2/Android.mk
index 47b081d..59fedc8 100644
--- a/tests/tests/preference2/Android.mk
+++ b/tests/tests/preference2/Android.mk
@@ -22,8 +22,6 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/preference2/AndroidManifest.xml b/tests/tests/preference2/AndroidManifest.xml
index 23b085d..2dbd53a 100644
--- a/tests/tests/preference2/AndroidManifest.xml
+++ b/tests/tests/preference2/AndroidManifest.xml
@@ -35,9 +35,12 @@
     </application>
 
     <!-- This is a self-instrumenting test package. -->
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.cts.preference2"
-                     android:label="CTS Test Cases for android.preference"/>
+                     android:label="CTS Test Cases for android.preference">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/tests/print/Android.mk b/tests/tests/print/Android.mk
new file mode 100644
index 0000000..516f6a0
--- /dev/null
+++ b/tests/tests/print/Android.mk
@@ -0,0 +1,33 @@
+# 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+    src/android/print/cts/IPrivilegedOperations.aidl
+
+LOCAL_PACKAGE_NAME := CtsPrintTestCases
+
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target ctstestrunner ub-uiautomator
+
+# This test runner sets up/cleans up the device before/after running the tests.
+LOCAL_CTS_TEST_RUNNER := com.android.cts.tradefed.testtype.PrintTestRunner
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/print/AndroidManifest.xml b/tests/tests/print/AndroidManifest.xml
new file mode 100644
index 0000000..b4a2905
--- /dev/null
+++ b/tests/tests/print/AndroidManifest.xml
@@ -0,0 +1,78 @@
+<?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="com.android.cts.print">
+
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+
+    <application android:allowBackup="false" >
+
+        <uses-library android:name="android.test.runner"/>
+
+        <activity android:name="android.print.cts.PrintDocumentActivity"/>
+
+        <service
+            android:name="android.print.cts.services.FirstPrintService"
+            android:permission="android.permission.BIND_PRINT_SERVICE">
+            <intent-filter>
+                <action android:name="android.printservice.PrintService" />
+            </intent-filter>
+            <meta-data
+               android:name="android.printservice"
+               android:resource="@xml/printservice">
+            </meta-data>
+        </service>
+
+        <service
+            android:name="android.print.cts.services.SecondPrintService"
+            android:permission="android.permission.BIND_PRINT_SERVICE">
+            <intent-filter>
+                <action android:name="android.printservice.PrintService" />
+            </intent-filter>
+            <meta-data
+               android:name="android.printservice"
+               android:resource="@xml/printservice">
+            </meta-data>
+        </service>
+
+        <activity
+            android:name="android.print.cts.services.SettingsActivity"
+            android:permission="android.permission.START_PRINT_SERVICE_CONFIG_ACTIVITY"
+            android:exported="true">
+        </activity>
+
+        <activity
+            android:name="android.print.cts.services.AddPrintersActivity"
+            android:permission="android.permission.START_PRINT_SERVICE_CONFIG_ACTIVITY"
+            android:exported="true">
+        </activity>
+
+        <activity
+            android:name="android.print.cts.services.CustomPrintOptionsActivity"
+            android:permission="android.permission.START_PRINT_SERVICE_CONFIG_ACTIVITY"
+            android:exported="true">
+        </activity>
+
+  </application>
+
+  <instrumentation android:name="android.support.test.uiautomator.UiAutomatorInstrumentationTestRunner"
+          android:targetPackage="com.android.cts.print"
+          android:label="Tests for the print APIs."/>
+
+</manifest>
diff --git a/tests/tests/print/res/values/strings.xml b/tests/tests/print/res/values/strings.xml
new file mode 100644
index 0000000..6d869e9
--- /dev/null
+++ b/tests/tests/print/res/values/strings.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+
+<resources>
+
+    <string name="resolution_200x200">200x200</string>
+    <string name="resolution_300x300">300x300</string>
+    <string name="resolution_600x600">600x600</string>
+
+</resources>
diff --git a/tests/tests/print/res/xml/printservice.xml b/tests/tests/print/res/xml/printservice.xml
new file mode 100644
index 0000000..5579b81
--- /dev/null
+++ b/tests/tests/print/res/xml/printservice.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+
+<print-service  xmlns:android="http://schemas.android.com/apk/res/android"
+     android:settingsActivity="android.print.services.SettingsActivity"
+     android:addPrintersActivity="android.print.services.AddPrintersActivity"
+     android:advancedPrintOptionsActivity="android.print.services.CustomPrintOptionsActivity"/>
diff --git a/tests/tests/print/src/android/print/cts/BasePrintTest.java b/tests/tests/print/src/android/print/cts/BasePrintTest.java
new file mode 100644
index 0000000..1493bc9
--- /dev/null
+++ b/tests/tests/print/src/android/print/cts/BasePrintTest.java
@@ -0,0 +1,461 @@
+/*
+ * 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.print.cts;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.pdf.PdfDocument;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.ParcelFileDescriptor;
+import android.os.SystemClock;
+import android.print.PageRange;
+import android.print.PrintAttributes;
+import android.print.PrintDocumentAdapter;
+import android.print.PrintDocumentAdapter.LayoutResultCallback;
+import android.print.PrintDocumentAdapter.WriteResultCallback;
+import android.print.PrintManager;
+import android.print.PrinterId;
+import android.print.cts.services.FirstPrintService;
+import android.print.cts.services.PrintServiceCallbacks;
+import android.print.cts.services.PrinterDiscoverySessionCallbacks;
+import android.print.cts.services.SecondPrintService;
+import android.print.cts.services.StubbablePrinterDiscoverySession;
+import android.print.pdf.PrintedPdfDocument;
+import android.printservice.PrintJob;
+import android.printservice.PrintService;
+import android.support.test.uiautomator.UiAutomatorTestCase;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiObjectNotFoundException;
+import android.support.test.uiautomator.UiSelector;
+import android.util.DisplayMetrics;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.mockito.InOrder;
+import org.mockito.stubbing.Answer;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.Locale;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * This is the base class for print tests.
+ */
+public abstract class BasePrintTest extends UiAutomatorTestCase {
+
+    private static final long OPERATION_TIMEOUT = 100000000;
+
+    private static final String ARG_PRIVILEGED_OPS = "ARG_PRIVILEGED_OPS";
+
+    private static final String PRINT_SPOOLER_PACKAGE_NAME = "com.android.printspooler";
+
+    protected static final String PRINT_JOB_NAME = "Test";
+
+    private PrintDocumentActivity mActivity;
+
+    private Locale mOldLocale;
+
+    private CallCounter mCancelOperationCounter;
+    private CallCounter mLayoutCallCounter;
+    private CallCounter mWriteCallCounter;
+    private CallCounter mFinishCallCounter;
+    private CallCounter mPrintJobQueuedCallCounter;
+    private CallCounter mDestroySessionCallCounter;
+
+    @Override
+    public void setUp() throws Exception {
+        // Make sure we start with a clean slate.
+        clearPrintSpoolerData();
+
+        // Workaround for dexmaker bug: https://code.google.com/p/dexmaker/issues/detail?id=2
+        // Dexmaker is used by mockito.
+        System.setProperty("dexmaker.dexcache", getInstrumentation()
+                .getTargetContext().getCacheDir().getPath());
+
+        // Set to US locale.
+        Resources resources = getInstrumentation().getTargetContext().getResources();
+        Configuration oldConfiguration = resources.getConfiguration();
+        if (!oldConfiguration.locale.equals(Locale.US)) {
+            mOldLocale = oldConfiguration.locale;
+            DisplayMetrics displayMetrics = resources.getDisplayMetrics();
+            Configuration newConfiguration = new Configuration(oldConfiguration);
+            newConfiguration.locale = Locale.US;
+            resources.updateConfiguration(newConfiguration, displayMetrics);
+        }
+
+        // Initialize the latches.
+        mCancelOperationCounter = new CallCounter();
+        mLayoutCallCounter = new CallCounter();
+        mFinishCallCounter = new CallCounter();
+        mWriteCallCounter = new CallCounter();
+        mFinishCallCounter = new CallCounter();
+        mPrintJobQueuedCallCounter = new CallCounter();
+        mDestroySessionCallCounter = new CallCounter();
+
+        // Create the activity for the right locale.
+        createActivity();
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        // Done with the activity.
+        getActivity().finish();
+
+        // Restore the locale if needed.
+        if (mOldLocale != null) {
+            Resources resources = getInstrumentation().getTargetContext().getResources();
+            DisplayMetrics displayMetrics = resources.getDisplayMetrics();
+            Configuration newConfiguration = new Configuration(resources.getConfiguration());
+            newConfiguration.locale = mOldLocale;
+            mOldLocale = null;
+            resources.updateConfiguration(newConfiguration, displayMetrics);
+        }
+
+        // Make sure the spooler is cleaned.
+        clearPrintSpoolerData();
+    }
+
+    protected void print(final PrintDocumentAdapter adapter) {
+        // Initiate printing as if coming from the app.
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                PrintManager printManager = (PrintManager) getActivity()
+                        .getSystemService(Context.PRINT_SERVICE);
+                printManager.print("Print job", adapter, null);
+            }
+        });
+    }
+
+    protected void onCancelOperationCalled() {
+        mCancelOperationCounter.call();
+    }
+
+    protected void onLayoutCalled() {
+        mLayoutCallCounter.call();
+    }
+
+    protected int getWriteCallCount() {
+        return mWriteCallCounter.getCallCount();
+    }
+
+    protected void onWriteCalled() {
+        mWriteCallCounter.call();
+    }
+
+    protected void onFinishCalled() {
+        mFinishCallCounter.call();
+    }
+
+    protected void onPrintJobQueuedCalled() {
+        mPrintJobQueuedCallCounter.call();
+    }
+
+    protected void onPrinterDiscoverySessionDestroyCalled() {
+        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.");
+    }
+
+    protected void waitForServiceOnPrintJobQueuedCallbackCalled() {
+        waitForCallbackCallCount(mPrintJobQueuedCallCounter, 1,
+                "Did not get expected call to onPrintJobQueued.");
+    }
+
+    protected void waitForAdapterFinishCallbackCalled() {
+        waitForCallbackCallCount(mFinishCallCounter, 1,
+                "Did not get expected call to finish.");
+    }
+
+    protected void waitForLayoutAdapterCallbackCount(int count) {
+        waitForCallbackCallCount(mLayoutCallCounter, count,
+                "Did not get expected call to layout.");
+    }
+
+    protected void waitForWriteAdapterCallback() {
+        waitForCallbackCallCount(mWriteCallCounter, 1, "Did not get expected call to write.");
+    }
+
+    private void waitForCallbackCallCount(CallCounter counter, int count, String message) {
+        try {
+            counter.waitForCount(count, OPERATION_TIMEOUT);
+        } catch (TimeoutException te) {
+            fail(message);
+        }
+    }
+
+    protected void selectPrinter(String printerName) throws UiObjectNotFoundException {
+        try {
+            UiObject destinationSpinner = new UiObject(new UiSelector().resourceId(
+                    "com.android.printspooler:id/destination_spinner"));
+            destinationSpinner.click();
+            UiObject printerOption = new UiObject(new UiSelector().text(printerName));
+            printerOption.click();
+        } catch (UiObjectNotFoundException e) {
+            dumpWindowHierarchy();
+            throw new UiObjectNotFoundException(e);
+        }
+    }
+
+    protected void changeOrientation(String orientation) throws UiObjectNotFoundException {
+        try {
+            UiObject orientationSpinner = new UiObject(new UiSelector().resourceId(
+                    "com.android.printspooler:id/orientation_spinner"));
+            orientationSpinner.click();
+            UiObject orientationOption = new UiObject(new UiSelector().text(orientation));
+            orientationOption.click();
+        } catch (UiObjectNotFoundException e) {
+            dumpWindowHierarchy();
+            throw new UiObjectNotFoundException(e);
+        }
+    }
+
+    protected void changeMediaSize(String mediaSize) throws UiObjectNotFoundException {
+        try {
+            UiObject mediaSizeSpinner = new UiObject(new UiSelector().resourceId(
+                    "com.android.printspooler:id/paper_size_spinner"));
+            mediaSizeSpinner.click();
+            UiObject mediaSizeOption = new UiObject(new UiSelector().text(mediaSize));
+            mediaSizeOption.click();
+        } catch (UiObjectNotFoundException e) {
+            dumpWindowHierarchy();
+            throw new UiObjectNotFoundException(e);
+        }
+    }
+
+    protected void changeColor(String color) throws UiObjectNotFoundException {
+        try {
+            UiObject colorSpinner = new UiObject(new UiSelector().resourceId(
+                    "com.android.printspooler:id/color_spinner"));
+            colorSpinner.click();
+            UiObject colorOption = new UiObject(new UiSelector().text(color));
+            colorOption.click();
+        } catch (UiObjectNotFoundException e) {
+            dumpWindowHierarchy();
+            throw new UiObjectNotFoundException(e);
+        }
+    }
+
+    protected void clickPrintButton() throws UiObjectNotFoundException {
+        try {
+            UiObject printButton = new UiObject(new UiSelector().resourceId(
+                    "com.android.printspooler:id/print_button"));
+            printButton.click();
+        } catch (UiObjectNotFoundException e) {
+            dumpWindowHierarchy();
+            throw new UiObjectNotFoundException(e);
+        }
+    }
+
+    private void dumpWindowHierarchy() {
+        String name = "print-test-failure-" + System.currentTimeMillis() + ".xml";
+        File file = new File(getActivity().getFilesDir(), name);
+        getUiDevice().dumpWindowHierarchy(file.toString());
+    }
+
+    protected PrintDocumentActivity getActivity() {
+        return mActivity;
+    }
+
+    private void createActivity() {
+        mActivity = launchActivity(
+                getInstrumentation().getTargetContext().getPackageName(),
+                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));
+        privilegedOps.clearApplicationUserData(PRINT_SPOOLER_PACKAGE_NAME);
+    }
+
+    protected void verifyLayoutCall(InOrder inOrder, PrintDocumentAdapter mock,
+            PrintAttributes oldAttributes, PrintAttributes newAttributes,
+            final boolean forPreview) {
+        inOrder.verify(mock).onLayout(eq(oldAttributes), eq(newAttributes),
+                any(CancellationSignal.class), any(LayoutResultCallback.class), argThat(
+                        new BaseMatcher<Bundle>() {
+                            @Override
+                            public boolean matches(Object item) {
+                                Bundle bundle = (Bundle) item;
+                                return forPreview == bundle.getBoolean(
+                                        PrintDocumentAdapter.EXTRA_PRINT_PREVIEW);
+                            }
+
+                            @Override
+                            public void describeTo(Description description) {
+                                /* do nothing */
+                            }
+                        }));
+    }
+
+    protected PrintDocumentAdapter createMockPrintDocumentAdapter(Answer<Void> layoutAnswer,
+            Answer<Void> writeAnswer, Answer<Void> finishAnswer) {
+        // Create a mock print adapter.
+        PrintDocumentAdapter adapter = mock(PrintDocumentAdapter.class);
+        if (layoutAnswer != null) {
+            doAnswer(layoutAnswer).when(adapter).onLayout(any(PrintAttributes.class),
+                    any(PrintAttributes.class), any(CancellationSignal.class),
+                    any(LayoutResultCallback.class), any(Bundle.class));
+        }
+        if (writeAnswer != null) {
+            doAnswer(writeAnswer).when(adapter).onWrite(any(PageRange[].class),
+                    any(ParcelFileDescriptor.class), any(CancellationSignal.class),
+                    any(WriteResultCallback.class));
+        }
+        if (finishAnswer != null) {
+            doAnswer(finishAnswer).when(adapter).onFinish();
+        }
+        return adapter;
+    }
+
+    @SuppressWarnings("unchecked")
+    protected PrinterDiscoverySessionCallbacks createMockPrinterDiscoverySessionCallbacks(
+            Answer<Void> onStartPrinterDiscovery, Answer<Void> onStopPrinterDiscovery,
+            Answer<Void> onValidatePrinters, Answer<Void> onStartPrinterStateTracking,
+            Answer<Void> onStopPrinterStateTracking, Answer<Void> onDestroy) {
+        PrinterDiscoverySessionCallbacks callbacks = mock(PrinterDiscoverySessionCallbacks.class);
+
+        doCallRealMethod().when(callbacks).setSession(any(StubbablePrinterDiscoverySession.class));
+        when(callbacks.getSession()).thenCallRealMethod();
+
+        if (onStartPrinterDiscovery != null) {
+            doAnswer(onStartPrinterDiscovery).when(callbacks).onStartPrinterDiscovery(
+                    any(List.class));
+        }
+        if (onStopPrinterDiscovery != null) {
+            doAnswer(onStopPrinterDiscovery).when(callbacks).onStopPrinterDiscovery();
+        }
+        if (onValidatePrinters != null) {
+            doAnswer(onValidatePrinters).when(callbacks).onValidatePrinters(
+                    any(List.class));
+        }
+        if (onStartPrinterStateTracking != null) {
+            doAnswer(onStartPrinterStateTracking).when(callbacks).onStartPrinterStateTracking(
+                    any(PrinterId.class));
+        }
+        if (onStopPrinterStateTracking != null) {
+            doAnswer(onStopPrinterStateTracking).when(callbacks).onStopPrinterStateTracking(
+                    any(PrinterId.class));
+        }
+        if (onDestroy != null) {
+            doAnswer(onDestroy).when(callbacks).onDestroy();
+        }
+
+        return callbacks;
+    }
+
+    protected PrintServiceCallbacks createMockPrintServiceCallbacks(
+            Answer<PrinterDiscoverySessionCallbacks> onCreatePrinterDiscoverySessionCallbacks,
+            Answer<Void> onPrintJobQueued, Answer<Void> onRequestCancelPrintJob) {
+        final PrintServiceCallbacks service = mock(PrintServiceCallbacks.class);
+
+        doCallRealMethod().when(service).setService(any(PrintService.class));
+        when(service.getService()).thenCallRealMethod();
+
+        if (onCreatePrinterDiscoverySessionCallbacks != null) {
+            doAnswer(onCreatePrinterDiscoverySessionCallbacks).when(service)
+                    .onCreatePrinterDiscoverySessionCallbacks();
+        }
+        if (onPrintJobQueued != null) {
+            doAnswer(onPrintJobQueued).when(service).onPrintJobQueued(any(PrintJob.class));
+        }
+        if (onRequestCancelPrintJob != null) {
+            doAnswer(onRequestCancelPrintJob).when(service).onRequestCancelPrintJob(
+                    any(PrintJob.class));
+        }
+
+        return service;
+    }
+
+    protected void writeBlankPages(PrintAttributes constraints, ParcelFileDescriptor output,
+            int fromIndex, int toIndex) throws IOException {
+        PrintedPdfDocument document = new PrintedPdfDocument(getActivity(), constraints);
+        final int pageCount = toIndex - fromIndex + 1;
+        for (int i = 0; i < pageCount; i++) {
+            PdfDocument.Page page = document.startPage(i);
+            document.finishPage(page);
+        }
+        FileOutputStream fos = new FileOutputStream(output.getFileDescriptor());
+        document.writeTo(fos);
+        document.close();
+    }
+
+    protected final class CallCounter {
+        private final Object mLock = new Object();
+
+        private int mCallCount;
+
+        public void call() {
+            synchronized (mLock) {
+                mCallCount++;
+                mLock.notifyAll();
+            }
+        }
+
+        public int getCallCount() {
+            synchronized (mLock) {
+                return mCallCount;
+            }
+        }
+
+        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;
+                        if (remainingTimeMillis <= 0) {
+                            throw new TimeoutException();
+                        }
+                        mLock.wait(timeoutMillis);
+                    } catch (InterruptedException ie) {
+                        /* ignore */
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/tests/tests/print/src/android/print/cts/IPrivilegedOperations.aidl b/tests/tests/print/src/android/print/cts/IPrivilegedOperations.aidl
new file mode 100644
index 0000000..93c8c3e
--- /dev/null
+++ b/tests/tests/print/src/android/print/cts/IPrivilegedOperations.aidl
@@ -0,0 +1,21 @@
+/*
+ * 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.print.cts;
+
+interface IPrivilegedOperations {
+    boolean clearApplicationUserData(String packageName);
+}
diff --git a/tests/tests/print/src/android/print/cts/PageRangeAdjustmentTest.java b/tests/tests/print/src/android/print/cts/PageRangeAdjustmentTest.java
new file mode 100644
index 0000000..4952cbd
--- /dev/null
+++ b/tests/tests/print/src/android/print/cts/PageRangeAdjustmentTest.java
@@ -0,0 +1,656 @@
+/*
+ * 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.print.cts;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.never;
+
+import android.os.ParcelFileDescriptor;
+import android.print.PageRange;
+import android.print.PrintAttributes;
+import android.print.PrintAttributes.Margins;
+import android.print.PrintAttributes.MediaSize;
+import android.print.PrintAttributes.Resolution;
+import android.print.PrintDocumentAdapter;
+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;
+import android.print.cts.services.FirstPrintService;
+import android.print.cts.services.PrintServiceCallbacks;
+import android.print.cts.services.PrinterDiscoverySessionCallbacks;
+import android.print.cts.services.SecondPrintService;
+import android.print.cts.services.StubbablePrinterDiscoverySession;
+import android.printservice.PrintJob;
+import android.printservice.PrintService;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiObjectNotFoundException;
+import android.support.test.uiautomator.UiSelector;
+
+import org.mockito.InOrder;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This test verifies that the system correctly adjust the
+ * page ranges to be printed depending whether the app gave
+ * the requested pages, more pages, etc.
+ */
+public class PageRangeAdjustmentTest extends BasePrintTest {
+
+    private static final String FIRST_PRINTER = "First printer";
+
+    public void testAllPagesWantedAndAllPagesWritten() throws Exception {
+        // Create a callback for the target print service.
+        PrintServiceCallbacks firstServiceCallbacks = createMockPrintServiceCallbacks(
+            new Answer<PrinterDiscoverySessionCallbacks>() {
+            @Override
+            public PrinterDiscoverySessionCallbacks answer(InvocationOnMock invocation) {
+                    return createMockFirstPrinterDiscoverySessionCallbacks();
+                }
+            },
+            new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) {
+                PrintJob printJob = (PrintJob) invocation.getArguments()[0];
+                PageRange[] pages = printJob.getInfo().getPages();
+                assertTrue(pages.length == 1 && PageRange.ALL_PAGES.equals(pages[0]));
+                printJob.complete();
+                onPrintJobQueuedCalled();
+                return null;
+            }
+        }, null);
+
+        final PrintAttributes[] printAttributes = new PrintAttributes[1];
+
+        // Configure the print services.
+        FirstPrintService.setCallbacks(firstServiceCallbacks);
+        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+        // Create a mock print adapter.
+        final PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(
+            new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                printAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
+                LayoutResultCallback callback = (LayoutResultCallback) invocation.getArguments()[3];
+                PrintDocumentInfo info = new PrintDocumentInfo.Builder(PRINT_JOB_NAME)
+                        .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
+                        .setPageCount(100)
+                        .build();
+                callback.onLayoutFinished(info, false);
+                // Mark layout was called.
+                onLayoutCalled();
+                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];
+                writeBlankPages(printAttributes[0], fd, 0, 99);
+                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.
+        waitForWriteAdapterCallback();
+
+        // Select the first printer.
+        selectPrinter(FIRST_PRINTER);
+
+        // Wait for layout as the printer has different capabilities.
+        waitForLayoutAdapterCallbackCount(2);
+
+        // Click the print button.
+        clickPrintButton();
+
+        // Wait for finish.
+        waitForAdapterFinishCallbackCalled();
+
+        // Wait for the print job.
+        waitForServiceOnPrintJobQueuedCallbackCalled();
+
+        // Verify the expected calls.
+        InOrder inOrder = inOrder(firstServiceCallbacks);
+
+        // We create a new session first.
+        inOrder.verify(firstServiceCallbacks)
+                .onCreatePrinterDiscoverySessionCallbacks();
+
+        // Next we wait for a call with the print job.
+        inOrder.verify(firstServiceCallbacks).onPrintJobQueued(
+                any(PrintJob.class));
+    }
+
+    public void testSomePagesWantedAndAllPagesWritten() throws Exception {
+        // Create a callback for the target print service.
+        PrintServiceCallbacks firstServiceCallbacks = createMockPrintServiceCallbacks(
+            new Answer<PrinterDiscoverySessionCallbacks>() {
+            @Override
+            public PrinterDiscoverySessionCallbacks answer(InvocationOnMock invocation) {
+                    return createMockFirstPrinterDiscoverySessionCallbacks();
+                }
+            },
+            new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) {
+                PrintJob printJob = (PrintJob) invocation.getArguments()[0];
+                PageRange[] pages = printJob.getInfo().getPages();
+                // We asked for some pages, the app wrote more, but the system
+                // pruned extra pages, hence we expect to print all pages.
+                assertTrue(pages.length == 1 && PageRange.ALL_PAGES.equals(pages[0]));
+                printJob.complete();
+                onPrintJobQueuedCalled();
+                return null;
+            }
+        }, null);
+
+        final PrintAttributes[] printAttributes = new PrintAttributes[1];
+
+        // Configure the print services.
+        FirstPrintService.setCallbacks(firstServiceCallbacks);
+        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+        // Create a mock print adapter.
+        final PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(
+            new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                printAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
+                LayoutResultCallback callback = (LayoutResultCallback) invocation.getArguments()[3];
+                PrintDocumentInfo info = new PrintDocumentInfo.Builder(PRINT_JOB_NAME)
+                        .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
+                        .setPageCount(100)
+                        .build();
+                callback.onLayoutFinished(info, false);
+                // Mark layout was called.
+                onLayoutCalled();
+                return null;
+            }
+        }, new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                Object[] args = invocation.getArguments();
+                PageRange[] pages = (PageRange[]) args[0];
+                assertTrue(pages[pages.length - 1].getEnd() < 100);
+                ParcelFileDescriptor fd = (ParcelFileDescriptor) args[1];
+                WriteResultCallback callback = (WriteResultCallback) args[3];
+                writeBlankPages(printAttributes[0], fd, 0, 99);
+                fd.close();
+                callback.onWriteFinished(new PageRange[] {PageRange.ALL_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.
+        waitForWriteAdapterCallback();
+
+        // Open the print options.
+        openPrintOptions();
+
+        // Select the first printer.
+        selectPrinter(FIRST_PRINTER);
+
+        // Wait for layout as the printer has different capabilities.
+        waitForLayoutAdapterCallbackCount(2);
+
+        // Select only the second page.
+        selectPages("2");
+
+        // Click the print button.
+        clickPrintButton();
+
+        // Wait for finish.
+        waitForAdapterFinishCallbackCalled();
+
+        // Wait for the print job.
+        waitForServiceOnPrintJobQueuedCallbackCalled();
+
+        // Verify the expected calls.
+        InOrder inOrder = inOrder(firstServiceCallbacks);
+
+        // We create a new session first.
+        inOrder.verify(firstServiceCallbacks)
+                .onCreatePrinterDiscoverySessionCallbacks();
+
+        // Next we wait for a call with the print job.
+        inOrder.verify(firstServiceCallbacks).onPrintJobQueued(
+                any(PrintJob.class));
+    }
+
+    public void testSomePagesWantedAndSomeMorePagesWritten() throws Exception {
+        // Create a callback for the target print service.
+        PrintServiceCallbacks firstServiceCallbacks = createMockPrintServiceCallbacks(
+            new Answer<PrinterDiscoverySessionCallbacks>() {
+            @Override
+            public PrinterDiscoverySessionCallbacks answer(InvocationOnMock invocation) {
+                    return createMockFirstPrinterDiscoverySessionCallbacks();
+                }
+            },
+            new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) {
+                PrintJob printJob = (PrintJob) invocation.getArguments()[0];
+                PrintJobInfo printJobInfo = printJob.getInfo();
+                PageRange[] pages = printJobInfo.getPages();
+                // We asked only for page 60 (index 59) but got 60 and 61 (indices
+                // 59, 60), but the system pruned the extra page, hence we expect
+                // to print all pages.
+                assertTrue(pages.length == 1 && PageRange.ALL_PAGES.equals(pages[0]));
+                assertSame(printJob.getDocument().getInfo().getPageCount(), 1);
+                printJob.complete();
+                onPrintJobQueuedCalled();
+                return null;
+            }
+        }, null);
+
+        final PrintAttributes[] printAttributes = new PrintAttributes[1];
+
+        // Configure the print services.
+        FirstPrintService.setCallbacks(firstServiceCallbacks);
+        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+        // Create a mock print adapter.
+        final PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(
+            new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                printAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
+                LayoutResultCallback callback = (LayoutResultCallback) invocation.getArguments()[3];
+                PrintDocumentInfo info = new PrintDocumentInfo.Builder(PRINT_JOB_NAME)
+                        .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
+                        .setPageCount(100)
+                        .build();
+                callback.onLayoutFinished(info, false);
+                // Mark layout was called.
+                onLayoutCalled();
+                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];
+                // We expect a single range as it is either the pages for
+                // preview or the page we selected in the UI.
+                assertSame(pages.length, 1);
+
+                // The first write request for some pages to preview.
+                if (getWriteCallCount() == 0) {
+                    // Write all requested pages.
+                    writeBlankPages(printAttributes[0], fd, pages[0].getStart(), pages[0].getEnd());
+                    callback.onWriteFinished(pages);
+                } else {
+                    // Otherwise write a page more that the one we selected.
+                    writeBlankPages(printAttributes[0], fd, 59, 60);
+                    callback.onWriteFinished(new PageRange[] {new PageRange(59, 60)});
+                }
+
+                fd.close();
+
+                // 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.
+        waitForWriteAdapterCallback();
+
+        // Open the print options.
+        openPrintOptions();
+
+        // Select the first printer.
+        selectPrinter(FIRST_PRINTER);
+
+        // Wait for layout as the printer has different capabilities.
+        waitForLayoutAdapterCallbackCount(2);
+
+        // Select a page not written for preview.
+        selectPages("60");
+
+        // Click the print button.
+        clickPrintButton();
+
+        // Wait for finish.
+        waitForAdapterFinishCallbackCalled();
+
+        // Wait for the print job.
+        waitForServiceOnPrintJobQueuedCallbackCalled();
+
+        // Verify the expected calls.
+        InOrder inOrder = inOrder(firstServiceCallbacks);
+
+        // We create a new session first.
+        inOrder.verify(firstServiceCallbacks)
+                .onCreatePrinterDiscoverySessionCallbacks();
+
+        // Next we wait for a call with the print job.
+        inOrder.verify(firstServiceCallbacks).onPrintJobQueued(
+                any(PrintJob.class));
+    }
+
+    public void testSomePagesWantedAndNotWritten() throws Exception {
+        // Create a callback for the target print service.
+        PrintServiceCallbacks firstServiceCallbacks = createMockPrintServiceCallbacks(
+            new Answer<PrinterDiscoverySessionCallbacks>() {
+            @Override
+            public PrinterDiscoverySessionCallbacks answer(InvocationOnMock invocation) {
+                    return createMockFirstPrinterDiscoverySessionCallbacks();
+                }
+            },
+            null, null);
+
+        final PrintAttributes[] printAttributes = new PrintAttributes[1];
+
+        // Configure the print services.
+        FirstPrintService.setCallbacks(firstServiceCallbacks);
+        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+        // Create a mock print adapter.
+        final PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(
+            new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                printAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
+                LayoutResultCallback callback = (LayoutResultCallback) invocation.getArguments()[3];
+                PrintDocumentInfo info = new PrintDocumentInfo.Builder(PRINT_JOB_NAME)
+                        .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
+                        .setPageCount(100)
+                        .build();
+                callback.onLayoutFinished(info, false);
+                // Mark layout was called.
+                onLayoutCalled();
+                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];
+                assertSame(pages.length, 1);
+
+                // We should be asked for some pages...
+                assertSame(pages[0].getStart(), 0);
+                assertTrue(pages[0].getEnd() == 49);
+
+                writeBlankPages(printAttributes[0], fd, pages[0].getStart(), pages[0].getEnd());
+                fd.close();
+                callback.onWriteFinished(new PageRange[]{new PageRange(1, 1)});
+
+                // 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.
+        waitForWriteAdapterCallback();
+
+        // Cancel printing.
+        getUiDevice().pressBack(); // wakes up the device.
+        getUiDevice().pressBack();
+
+        // Wait for finish.
+        waitForAdapterFinishCallbackCalled();
+
+        // Verify the expected calls.
+        InOrder inOrder = inOrder(firstServiceCallbacks);
+
+        // We create a new session first.
+        inOrder.verify(firstServiceCallbacks)
+                .onCreatePrinterDiscoverySessionCallbacks();
+
+        // We should not receive a print job callback.
+        inOrder.verify(firstServiceCallbacks, never()).onPrintJobQueued(
+                any(PrintJob.class));
+    }
+
+    public void testWantedPagesAlreadyWrittenForPreview() throws Exception {
+        // Create a callback for the target print service.
+        PrintServiceCallbacks firstServiceCallbacks = createMockPrintServiceCallbacks(
+            new Answer<PrinterDiscoverySessionCallbacks>() {
+            @Override
+            public PrinterDiscoverySessionCallbacks answer(InvocationOnMock invocation) {
+                return createMockFirstPrinterDiscoverySessionCallbacks();
+                    }
+            }, new Answer<Void>() {
+            @Override
+                public Void answer(InvocationOnMock invocation) {
+                    PrintJob printJob = (PrintJob) invocation.getArguments()[0];
+                    PrintJobInfo printJobInfo = printJob.getInfo();
+                    PageRange[] pages = printJobInfo.getPages();
+                    // We asked only for page 3 (index 2) but got this page when
+                    // we were getting the pages for preview (indices 0 - 49),
+                    // but the framework pruned extra pages, hence we should be asked
+                    // to print all pages from a single page document.
+                    assertTrue(pages.length == 1 && PageRange.ALL_PAGES.equals(pages[0]));
+                    assertSame(printJob.getDocument().getInfo().getPageCount(), 1);
+                    printJob.complete();
+                    onPrintJobQueuedCalled();
+                    return null;
+                }
+            }, null);
+
+        final PrintAttributes[] printAttributes = new PrintAttributes[1];
+
+        // Configure the print services.
+        FirstPrintService.setCallbacks(firstServiceCallbacks);
+        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+        // Create a mock print adapter.
+        final PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(
+            new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                printAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
+                LayoutResultCallback callback = (LayoutResultCallback) invocation.getArguments()[3];
+                PrintDocumentInfo info = new PrintDocumentInfo.Builder(PRINT_JOB_NAME)
+                        .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
+                        .setPageCount(100)
+                        .build();
+                callback.onLayoutFinished(info, false);
+                // Mark layout was called.
+                onLayoutCalled();
+                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];
+                // We expect a single range as it is either the pages for
+                // preview or the page we selected in the UI.
+                assertSame(pages.length, 1);
+
+                // Write all requested pages.
+                writeBlankPages(printAttributes[0], fd, pages[0].getStart(), pages[0].getEnd());
+                callback.onWriteFinished(pages);
+                fd.close();
+
+                // 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.
+        waitForWriteAdapterCallback();
+
+        // Open the print options.
+        openPrintOptions();
+
+        // Select the first printer.
+        selectPrinter(FIRST_PRINTER);
+
+        // Wait for layout as the printer has different capabilities.
+        waitForLayoutAdapterCallbackCount(2);
+
+        // Select a page not written for preview.
+        selectPages("3");
+
+        // Click the print button.
+        clickPrintButton();
+
+        // Wait for finish.
+        waitForAdapterFinishCallbackCalled();
+
+        // Wait for the print job.
+        waitForServiceOnPrintJobQueuedCallbackCalled();
+
+        // Verify the expected calls.
+        InOrder inOrder = inOrder(firstServiceCallbacks);
+
+        // We create a new session first.
+        inOrder.verify(firstServiceCallbacks)
+                .onCreatePrinterDiscoverySessionCallbacks();
+
+        // Next we wait for a call with the print job.
+        inOrder.verify(firstServiceCallbacks).onPrintJobQueued(
+                any(PrintJob.class));
+    }
+
+    private void selectPages(String pages) throws UiObjectNotFoundException {
+        UiObject pagesSpinner = getUiDevice().findObject(new UiSelector().resourceId(
+                "com.android.printspooler:id/range_options_spinner"));
+        pagesSpinner.click();
+
+        UiObject rangeOption = getUiDevice().findObject(new UiSelector().textContains("Range"));
+        rangeOption.click();
+
+        UiObject pagesEditText = getUiDevice().findObject(new UiSelector().resourceId(
+                "com.android.printspooler:id/page_range_edittext"));
+        pagesEditText.setText(pages);
+
+        // Hide the keyboard.
+        getUiDevice().pressBack();
+    }
+
+    private PrinterDiscoverySessionCallbacks createMockFirstPrinterDiscoverySessionCallbacks() {
+        return createMockPrinterDiscoverySessionCallbacks(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) {
+                PrinterDiscoverySessionCallbacks mock = (PrinterDiscoverySessionCallbacks)
+                        invocation.getMock();
+
+                StubbablePrinterDiscoverySession session = mock.getSession();
+                PrintService service = session.getService();
+
+                if (session.getPrinters().isEmpty()) {
+                          List<PrinterInfo> printers = new ArrayList<>();
+
+                    // Add one printer.
+                    PrinterId firstPrinterId = service.generatePrinterId("first_printer");
+                    PrinterCapabilitiesInfo firstCapabilities =
+                            new PrinterCapabilitiesInfo.Builder(firstPrinterId)
+                        .setMinMargins(new Margins(200, 200, 200, 200))
+                        .addMediaSize(MediaSize.ISO_A4, true)
+                        .addMediaSize(MediaSize.ISO_A5, false)
+                        .addResolution(new Resolution("300x300", "300x300", 300, 300), true)
+                        .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
+                                PrintAttributes.COLOR_MODE_COLOR)
+                        .build();
+                    PrinterInfo firstPrinter = new PrinterInfo.Builder(firstPrinterId,
+                            FIRST_PRINTER, PrinterInfo.STATUS_IDLE)
+                        .setCapabilities(firstCapabilities)
+                        .build();
+                    printers.add(firstPrinter);
+
+                    session.addPrinters(printers);
+                }
+
+                return null;
+            }
+        }, null, null, null, null, null);
+    }
+
+    private PrintServiceCallbacks createSecondMockPrintServiceCallbacks() {
+        return createMockPrintServiceCallbacks(null, null, null);
+    }
+}
diff --git a/tests/tests/print/src/android/print/cts/PrintDocumentActivity.java b/tests/tests/print/src/android/print/cts/PrintDocumentActivity.java
new file mode 100644
index 0000000..41e7a57
--- /dev/null
+++ b/tests/tests/print/src/android/print/cts/PrintDocumentActivity.java
@@ -0,0 +1,33 @@
+/*
+ * 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.print.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.WindowManager;
+
+public class PrintDocumentActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
+                | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
+                | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
+    }
+}
diff --git a/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java b/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java
new file mode 100644
index 0000000..516db56
--- /dev/null
+++ b/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java
@@ -0,0 +1,1588 @@
+/*
+ * 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.print.cts;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import android.os.CancellationSignal;
+import android.os.CancellationSignal.OnCancelListener;
+import android.os.ParcelFileDescriptor;
+import android.print.PageRange;
+import android.print.PrintAttributes;
+import android.print.PrintAttributes.Margins;
+import android.print.PrintAttributes.MediaSize;
+import android.print.PrintAttributes.Resolution;
+import android.print.PrintDocumentAdapter;
+import android.print.PrintDocumentAdapter.LayoutResultCallback;
+import android.print.PrintDocumentAdapter.WriteResultCallback;
+import android.print.PrintDocumentInfo;
+import android.print.PrinterCapabilitiesInfo;
+import android.print.PrinterId;
+import android.print.PrinterInfo;
+import android.print.cts.services.FirstPrintService;
+import android.print.cts.services.PrintServiceCallbacks;
+import android.print.cts.services.PrinterDiscoverySessionCallbacks;
+import android.print.cts.services.SecondPrintService;
+import android.print.cts.services.StubbablePrinterDiscoverySession;
+import android.printservice.PrintJob;
+import android.printservice.PrintService;
+
+import org.mockito.InOrder;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This test verifies that the system respects the {@link PrintDocumentAdapter}
+ * contract and invokes all callbacks as expected.
+ */
+public class PrintDocumentAdapterContractTest extends BasePrintTest {
+
+    public void testNoPrintOptionsOrPrinterChange() throws Exception {
+        // Configure the print services.
+        FirstPrintService.setCallbacks(createFirstMockPrintServiceCallbacks());
+        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+        final PrintAttributes[] printAttributes = new PrintAttributes[1];
+
+        // Create a mock print adapter.
+        final PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(
+            new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                printAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
+                LayoutResultCallback callback = (LayoutResultCallback) invocation.getArguments()[3];
+                PrintDocumentInfo info = new PrintDocumentInfo.Builder(PRINT_JOB_NAME)
+                        .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
+                        .setPageCount(2)
+                        .build();
+                callback.onLayoutFinished(info, false);
+                // Mark layout was called.
+                onLayoutCalled();
+                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];
+                writeBlankPages(printAttributes[0], fd, pages[0].getStart(), pages[0].getEnd());
+                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.
+        waitForWriteAdapterCallback();
+
+        // Select the second printer.
+        selectPrinter("Second printer");
+
+        // Wait for layout.
+        waitForLayoutAdapterCallbackCount(2);
+
+        // Click the print button.
+        clickPrintButton();
+
+        // Wait for finish.
+        waitForAdapterFinishCallbackCalled();
+
+        // Wait for the session to be destroyed to isolate tests.
+        waitForPrinterDiscoverySessionDestroyCallbackCalled();
+
+        // Verify the expected calls.
+        InOrder inOrder = inOrder(adapter);
+
+        // Start is always called first.
+        inOrder.verify(adapter).onStart();
+
+        // Start is always followed by a layout. The PDF printer is selected if
+        // there are other printers but none of them was used.
+        PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
+        PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
+                .setMediaSize(MediaSize.NA_LETTER)
+                .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
+                .setMinMargins(Margins.NO_MARGINS)
+                .setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+                .build();
+        verifyLayoutCall(inOrder, adapter, firstOldAttributes, firstNewAttributes, true);
+
+        // We always ask for the the first fifty pages for preview.
+        PageRange[] firstPages = new PageRange[] {new PageRange(0, 1)};
+        inOrder.verify(adapter).onWrite(eq(firstPages), any(ParcelFileDescriptor.class),
+                any(CancellationSignal.class), any(WriteResultCallback.class));
+
+        // We selected the second printer which does not support the media
+        // size that was selected, so a new layout happens as the size changed.
+        // Since we passed false to the layout callback meaning that the content
+        // didn't change, there shouldn't be a next call to write.
+        PrintAttributes secondOldAttributes = firstNewAttributes;
+        PrintAttributes secondNewAttributes = new PrintAttributes.Builder()
+                .setMediaSize(MediaSize.ISO_A3)
+                .setResolution(new Resolution("300x300", "300x300", 300, 300))
+                .setMinMargins(Margins.NO_MARGINS)
+                .setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+                .build();
+        verifyLayoutCall(inOrder, adapter, secondOldAttributes, secondNewAttributes, true);
+
+        // When print is pressed we ask for a layout which is *not* for preview.
+        verifyLayoutCall(inOrder, adapter, secondNewAttributes, secondNewAttributes, false);
+
+        // When print is pressed we ask for all selected pages but we got
+        // them when asking for the ones for a preview, and the adapter does
+        // not report a content change. Hence, there is nothing to write.
+
+        // Finish is always called last.
+        inOrder.verify(adapter).onFinish();
+
+        // No other call are expected.
+        verifyNoMoreInteractions(adapter);
+    }
+
+    public void testNoPrintOptionsOrPrinterChangeCanceled() throws Exception {
+        // Configure the print services.
+        FirstPrintService.setCallbacks(createFirstMockPrintServiceCallbacks());
+        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+        final PrintAttributes[] printAttributes = new PrintAttributes[1];
+
+        // Create a mock print adapter.
+        final PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(
+            new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                printAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
+                LayoutResultCallback callback = (LayoutResultCallback)
+                        invocation.getArguments()[3];
+                PrintDocumentInfo info = new PrintDocumentInfo.Builder(PRINT_JOB_NAME)
+                    .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
+                    .setPageCount(1)
+                    .build();
+                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];
+                writeBlankPages(printAttributes[0], fd, pages[0].getStart(), pages[0].getEnd());
+                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.
+        waitForWriteAdapterCallback();
+
+        // Cancel the printing.
+        getUiDevice().pressBack(); // wakes up the device.
+        getUiDevice().pressBack();
+
+        // Wait for finish.
+        waitForAdapterFinishCallbackCalled();
+
+        // Wait for the session to be destroyed to isolate tests.
+        waitForPrinterDiscoverySessionDestroyCallbackCalled();
+
+        // Verify the expected calls.
+        InOrder inOrder = inOrder(adapter);
+
+        // Start is always called first.
+        inOrder.verify(adapter).onStart();
+
+        // Start is always followed by a layout. The PDF printer is selected if
+        // there are other printers but none of them was used.
+        PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
+        PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
+                .setMediaSize(MediaSize.NA_LETTER)
+                .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
+                .setMinMargins(Margins.NO_MARGINS)
+                .setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+                .build();
+        verifyLayoutCall(inOrder, adapter, firstOldAttributes, firstNewAttributes, true);
+
+        // We always ask for the the first fifty pages for preview.
+        PageRange[] firstPages = new PageRange[] {new PageRange(0, 0)};
+        inOrder.verify(adapter).onWrite(eq(firstPages), any(ParcelFileDescriptor.class),
+                any(CancellationSignal.class), any(WriteResultCallback.class));
+
+        // Finish is always called last.
+        inOrder.verify(adapter).onFinish();
+
+        // No other call are expected.
+        verifyNoMoreInteractions(adapter);
+    }
+
+    public void testPrintOptionsChangeAndNoPrinterChange() throws Exception {
+        // Configure the print services.
+        FirstPrintService.setCallbacks(createFirstMockPrintServiceCallbacks());
+        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+        final PrintAttributes[] printAttributes = new PrintAttributes[1];
+
+        // Create a mock print adapter.
+        final PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(
+            new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                printAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
+                LayoutResultCallback callback = (LayoutResultCallback)
+                        invocation.getArguments()[3];
+                PrintDocumentInfo info = new PrintDocumentInfo.Builder(PRINT_JOB_NAME)
+                    .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
+                    .setPageCount(1)
+                    .build();
+                callback.onLayoutFinished(info, false);
+                // Mark layout was called.
+                onLayoutCalled();
+                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];
+                writeBlankPages(printAttributes[0], fd, pages[0].getStart(), pages[0].getEnd());
+                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.
+        waitForWriteAdapterCallback();
+
+        // Open the print options.
+        openPrintOptions();
+
+        // Select the second printer.
+        selectPrinter("Second printer");
+
+        // Wait for layout.
+        waitForLayoutAdapterCallbackCount(2);
+
+        // Change the orientation.
+        changeOrientation("Landscape");
+
+        // Wait for layout.
+        waitForLayoutAdapterCallbackCount(3);
+
+        // Change the media size.
+        changeMediaSize("ISO A4");
+
+        // Wait for layout.
+        waitForLayoutAdapterCallbackCount(4);
+
+        // Change the color.
+        changeColor("Black & White");
+
+        // Wait for layout.
+        waitForLayoutAdapterCallbackCount(5);
+
+        // Click the print button.
+        clickPrintButton();
+
+        // Wait for a finish.
+        waitForAdapterFinishCallbackCalled();
+
+        // Wait for the session to be destroyed to isolate tests.
+        waitForPrinterDiscoverySessionDestroyCallbackCalled();
+
+        // Verify the expected calls.
+        InOrder inOrder = inOrder(adapter);
+
+        // Start is always called first.
+        inOrder.verify(adapter).onStart();
+
+        // Start is always followed by a layout. The PDF printer is selected if
+        // there are other printers but none of them was used.
+        PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
+        PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
+                .setMediaSize(MediaSize.NA_LETTER)
+                .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
+                .setMinMargins(Margins.NO_MARGINS)
+                .setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+                .build();
+        verifyLayoutCall(inOrder, adapter, firstOldAttributes, firstNewAttributes, true);
+
+        // We always ask for the the first fifty pages for preview.
+        PageRange[] firstPages = new PageRange[] {new PageRange(0, 0)};
+        inOrder.verify(adapter).onWrite(eq(firstPages), any(ParcelFileDescriptor.class),
+                any(CancellationSignal.class), any(WriteResultCallback.class));
+
+        // We selected the second printer which does not support the media
+        // size that was selected, so a new layout happens as the size changed.
+        // Since we passed false to the layout callback meaning that the content
+        // didn't change, there shouldn't be a next call to write.
+        PrintAttributes secondOldAttributes = firstNewAttributes;
+        PrintAttributes secondNewAttributes = new PrintAttributes.Builder()
+                .setMediaSize(MediaSize.ISO_A3)
+                .setResolution(new Resolution("300x300", "300x300", 300, 300))
+                .setMinMargins(Margins.NO_MARGINS)
+                .setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+                .build();
+        verifyLayoutCall(inOrder, adapter, secondOldAttributes, secondNewAttributes, true);
+
+        // We changed the orientation which triggers a layout. Since we passed
+        // false to the layout callback meaning that the content didn't change,
+        // there shouldn't be a next call to write.
+        PrintAttributes thirdOldAttributes = secondNewAttributes;
+        PrintAttributes thirdNewAttributes = new PrintAttributes.Builder()
+                .setMediaSize(MediaSize.ISO_A3.asLandscape())
+                .setResolution(new Resolution("300x300", "300x300", 300, 300))
+                .setMinMargins(Margins.NO_MARGINS)
+                .setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+                .build();
+        verifyLayoutCall(inOrder, adapter, thirdOldAttributes, thirdNewAttributes, true);
+
+        // We changed the media size which triggers a layout. Since we passed
+        // false to the layout callback meaning that the content didn't change,
+        // there shouldn't be a next call to write.
+        PrintAttributes fourthOldAttributes = thirdNewAttributes;
+        PrintAttributes fourthNewAttributes = new PrintAttributes.Builder()
+                .setMediaSize(MediaSize.ISO_A4.asLandscape())
+                .setResolution(new Resolution("300x300", "300x300", 300, 300))
+                .setMinMargins(Margins.NO_MARGINS)
+                .setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+                .build();
+        verifyLayoutCall(inOrder, adapter, fourthOldAttributes, fourthNewAttributes, true);
+
+        // We changed the color which triggers a layout. Since we passed
+        // false to the layout callback meaning that the content didn't change,
+        // there shouldn't be a next call to write.
+        PrintAttributes fifthOldAttributes = fourthNewAttributes;
+        PrintAttributes fifthNewAttributes = new PrintAttributes.Builder()
+                .setMediaSize(MediaSize.ISO_A4.asLandscape())
+                .setResolution(new Resolution("300x300", "300x300", 300, 300))
+                .setMinMargins(Margins.NO_MARGINS)
+                .setColorMode(PrintAttributes.COLOR_MODE_MONOCHROME)
+                .build();
+        verifyLayoutCall(inOrder, adapter, fifthOldAttributes, fifthNewAttributes, true);
+
+        // When print is pressed we ask for a layout which is *not* for preview.
+        verifyLayoutCall(inOrder, adapter, fifthNewAttributes, fifthNewAttributes, false);
+
+        // When print is pressed we ask for all selected pages but we got
+        // them when asking for the ones for a preview, and the adapter does
+        // not report a content change. Hence, there is nothing to write.
+
+        // Finish is always called last.
+        inOrder.verify(adapter).onFinish();
+
+        // No other call are expected.
+        verifyNoMoreInteractions(adapter);
+    }
+
+    public void testPrintOptionsChangeAndPrinterChange() throws Exception {
+        // Configure the print services.
+        FirstPrintService.setCallbacks(createFirstMockPrintServiceCallbacks());
+        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+        final PrintAttributes[] printAttributes = new PrintAttributes[1];
+
+        // Create a mock print adapter.
+        final PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(
+            new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                printAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
+                LayoutResultCallback callback = (LayoutResultCallback)
+                        invocation.getArguments()[3];
+                PrintDocumentInfo info = new PrintDocumentInfo.Builder(PRINT_JOB_NAME)
+                    .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
+                    .setPageCount(1)
+                    .build();
+                callback.onLayoutFinished(info, false);
+                // Mark layout was called.
+                onLayoutCalled();
+                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];
+                writeBlankPages(printAttributes[0], fd, pages[0].getStart(), pages[0].getEnd());
+                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.
+        waitForWriteAdapterCallback();
+
+        // Open the print options.
+        openPrintOptions();
+
+        // Select the second printer.
+        selectPrinter("Second printer");
+
+        // Wait for layout.
+        waitForLayoutAdapterCallbackCount(2);
+
+        // Change the color.
+        changeColor("Black & White");
+
+        // Wait for layout.
+        waitForLayoutAdapterCallbackCount(3);
+
+        // Change the printer to one which supports the current media size.
+        // Select the second printer.
+        selectPrinter("First printer");
+
+        // Wait for layout.
+        waitForLayoutAdapterCallbackCount(4);
+
+        // Click the print button.
+        clickPrintButton();
+
+        // Wait for a finish.
+        waitForAdapterFinishCallbackCalled();
+
+        // Wait for the session to be destroyed to isolate tests.
+        waitForPrinterDiscoverySessionDestroyCallbackCalled();
+
+        // Verify the expected calls.
+        InOrder inOrder = inOrder(adapter);
+
+        // Start is always called first.
+        inOrder.verify(adapter).onStart();
+
+        // Start is always followed by a layout. The PDF printer is selected if
+        // there are other printers but none of them was used.
+        PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
+        PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
+                .setMediaSize(MediaSize.NA_LETTER)
+                .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
+                .setMinMargins(Margins.NO_MARGINS)
+                .setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+                .build();
+        verifyLayoutCall(inOrder, adapter, firstOldAttributes, firstNewAttributes, true);
+
+        // We always ask for the the first fifty pages for preview.
+        PageRange[] firstPages = new PageRange[] {new PageRange(0, 0)};
+        inOrder.verify(adapter).onWrite(eq(firstPages), any(ParcelFileDescriptor.class),
+                any(CancellationSignal.class), any(WriteResultCallback.class));
+
+        // We changed the printer and the new printer does not support the
+        // selected media size in which case the default media size of the
+        // printer is used resulting in a layout pass. Same for margins.
+        PrintAttributes secondOldAttributes = firstNewAttributes;
+        PrintAttributes secondNewAttributes = new PrintAttributes.Builder()
+                .setMediaSize(MediaSize.ISO_A3)
+                .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
+                .setMinMargins(new Margins(0, 0, 0, 0))
+                .setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+                .build();
+        verifyLayoutCall(inOrder, adapter, secondOldAttributes, secondNewAttributes, true);
+
+        // We changed the color which results in a layout pass.
+        PrintAttributes thirdOldAttributes = secondNewAttributes;
+        PrintAttributes thirdNewAttributes = new PrintAttributes.Builder()
+                .setMediaSize(MediaSize.ISO_A3)
+                .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
+                .setMinMargins(new Margins(0, 0, 0, 0))
+                .setColorMode(PrintAttributes.COLOR_MODE_MONOCHROME)
+                .build();
+        verifyLayoutCall(inOrder, adapter, thirdOldAttributes, thirdNewAttributes, true);
+
+        // We changed the printer to one that does not support the current
+        // media size in which case we pick the default media size for the
+        // new printer which results in a layout pass. Same for color.
+        PrintAttributes fourthOldAttributes = thirdNewAttributes;
+        PrintAttributes fourthNewAttributes = new PrintAttributes.Builder()
+                .setMediaSize(MediaSize.ISO_A4)
+                .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
+                .setMinMargins(new Margins(200, 200, 200, 200))
+                .setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+                .build();
+        verifyLayoutCall(inOrder, adapter, fourthOldAttributes, fourthNewAttributes, true);
+
+        // When print is pressed we ask for a layout which is *not* for preview.
+        verifyLayoutCall(inOrder, adapter, fourthNewAttributes, fourthNewAttributes, false);
+
+        // When print is pressed we ask for all selected pages but we got
+        // them when asking for the ones for a preview, and the adapter does
+        // not report a content change. Hence, there is nothing to write.
+
+        // Finish is always called last.
+        inOrder.verify(adapter).onFinish();
+
+        // No other call are expected.
+        verifyNoMoreInteractions(adapter);
+    }
+
+    public void testPrintOptionsChangeAndNoPrinterChangeAndContentChange()
+            throws Exception {
+        // Configure the print services.
+        FirstPrintService.setCallbacks(createFirstMockPrintServiceCallbacks());
+        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+        final PrintAttributes[] printAttributes = new PrintAttributes[1];
+
+        // Create a mock print adapter.
+        final PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(
+            new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                printAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
+                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);
+                // Mark layout was called.
+                onLayoutCalled();
+                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];
+                writeBlankPages(printAttributes[0], fd, pages[0].getStart(), pages[0].getEnd());
+                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.
+        waitForWriteAdapterCallback();
+
+        // Open the print options.
+        openPrintOptions();
+
+        // Select the second printer.
+        selectPrinter("Second printer");
+
+        // Wait for layout.
+        waitForLayoutAdapterCallbackCount(2);
+
+        // Click the print button.
+        clickPrintButton();
+
+        // Wait for a finish.
+        waitForAdapterFinishCallbackCalled();
+
+        // Wait for the session to be destroyed to isolate tests.
+        waitForPrinterDiscoverySessionDestroyCallbackCalled();
+
+        // Verify the expected calls.
+        InOrder inOrder = inOrder(adapter);
+
+        // Start is always called first.
+        inOrder.verify(adapter).onStart();
+
+        // Start is always followed by a layout. The PDF printer is selected if
+        // there are other printers but none of them was used.
+        PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
+        PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
+                .setMediaSize(MediaSize.NA_LETTER)
+                .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
+                .setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+                .build();
+        verifyLayoutCall(inOrder, adapter, firstOldAttributes, firstNewAttributes, true);
+
+        // We always ask for the the first fifty pages for preview.
+        PageRange[] firstPages = new PageRange[] {new PageRange(0, 0)};
+        inOrder.verify(adapter).onWrite(eq(firstPages), any(ParcelFileDescriptor.class),
+                any(CancellationSignal.class), any(WriteResultCallback.class));
+
+        // We selected the second printer which does not support the media
+        // size that was selected, so a new layout happens as the size changed.
+        PrintAttributes secondOldAttributes = firstNewAttributes;
+        PrintAttributes secondNewAttributes = new PrintAttributes.Builder()
+                .setMediaSize(MediaSize.ISO_A3)
+                .setResolution(new Resolution("300x300", "300x300", 300, 300))
+                .setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+                .build();
+        verifyLayoutCall(inOrder, adapter, secondOldAttributes, secondNewAttributes, true);
+
+        // In the layout callback we reported that the content changed,
+        // so the previously written page has to be written again.
+        PageRange[] secondPages = new PageRange[] {new PageRange(0, 0)};
+        inOrder.verify(adapter).onWrite(eq(secondPages), any(ParcelFileDescriptor.class),
+                any(CancellationSignal.class), any(WriteResultCallback.class));
+
+        // When print is pressed we ask for a layout which is *not* for preview.
+        verifyLayoutCall(inOrder, adapter, secondNewAttributes, secondNewAttributes, false);
+
+        // When print is pressed we ask for all selected pages as the adapter
+        // reports that the content changes after every layout pass.
+        PageRange[] thirdPages = new PageRange[] {new PageRange(0, 0)};
+        inOrder.verify(adapter).onWrite(eq(thirdPages), any(ParcelFileDescriptor.class),
+                any(CancellationSignal.class), any(WriteResultCallback.class));
+
+        // Finish is always called last.
+        inOrder.verify(adapter).onFinish();
+
+        // No other call are expected.
+        verifyNoMoreInteractions(adapter);
+    }
+
+    public void testNewPrinterSupportsSelectedPrintOptions() throws Exception {
+        // Configure the print services.
+        FirstPrintService.setCallbacks(createFirstMockPrintServiceCallbacks());
+        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+        final PrintAttributes[] printAttributes = new PrintAttributes[1];
+
+        // Create a mock print adapter.
+        final PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(
+            new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                printAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
+                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];
+                writeBlankPages(printAttributes[0], fd, pages[0].getStart(), pages[0].getEnd());
+                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.
+        waitForWriteAdapterCallback();
+
+        // Open the print options.
+        openPrintOptions();
+
+        // Select the third printer.
+        selectPrinter("Third printer");
+
+        // Click the print button.
+        clickPrintButton();
+
+        // Wait for a finish.
+        waitForAdapterFinishCallbackCalled();
+
+        // Wait for the session to be destroyed to isolate tests.
+        waitForPrinterDiscoverySessionDestroyCallbackCalled();
+
+        // Verify the expected calls.
+        InOrder inOrder = inOrder(adapter);
+
+        // Start is always called first.
+        inOrder.verify(adapter).onStart();
+
+        // Start is always followed by a layout. The PDF printer is selected if
+        // there are other printers but none of them was used.
+        PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
+        PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
+                .setMediaSize(MediaSize.NA_LETTER)
+                .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
+                .setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+                .build();
+        verifyLayoutCall(inOrder, adapter, firstOldAttributes, firstNewAttributes, true);
+
+        // We always ask for the the first fifty pages for preview.
+        PageRange[] firstPages = new PageRange[] {new PageRange(0, 0)};
+        inOrder.verify(adapter).onWrite(eq(firstPages), any(ParcelFileDescriptor.class),
+                any(CancellationSignal.class), any(WriteResultCallback.class));
+
+        // When print is pressed we ask for a layout which is *not* for preview.
+        verifyLayoutCall(inOrder, adapter, firstNewAttributes, firstNewAttributes, false);
+
+        // When print is pressed we ask for all selected pages.
+        PageRange[] thirdPages = new PageRange[] {new PageRange(0, 0)};
+        inOrder.verify(adapter).onWrite(eq(thirdPages), any(ParcelFileDescriptor.class),
+                any(CancellationSignal.class), any(WriteResultCallback.class));
+
+        // Finish is always called last.
+        inOrder.verify(adapter).onFinish();
+
+        // No other call are expected.
+        verifyNoMoreInteractions(adapter);
+    }
+
+    public void testNothingChangesAllPagesWrittenFirstTime() throws Exception {
+        // Configure the print services.
+        FirstPrintService.setCallbacks(createFirstMockPrintServiceCallbacks());
+        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+        final PrintAttributes[] printAttributes = new PrintAttributes[1];
+
+        // Create a mock print adapter.
+        final PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(
+            new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                printAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
+                LayoutResultCallback callback = (LayoutResultCallback) invocation.getArguments()[3];
+                PrintDocumentInfo info = new PrintDocumentInfo.Builder(PRINT_JOB_NAME)
+                        .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
+                        .setPageCount(3)
+                        .build();
+                callback.onLayoutFinished(info, false);
+                // Mark layout was called.
+                onLayoutCalled();
+                return null;
+            }
+        }, new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                Object[] args = invocation.getArguments();
+                ParcelFileDescriptor fd = (ParcelFileDescriptor) args[1];
+                WriteResultCallback callback = (WriteResultCallback) args[3];
+                PageRange[] pages = (PageRange[]) args[0];
+                writeBlankPages(printAttributes[0], fd, pages[0].getStart(), pages[0].getEnd());
+                fd.close();
+                callback.onWriteFinished(new PageRange[] {PageRange.ALL_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.
+        waitForWriteAdapterCallback();
+
+        // Open the print options.
+        openPrintOptions();
+
+        // Select the second printer.
+        selectPrinter("Second printer");
+
+        // Wait for layout.
+        waitForLayoutAdapterCallbackCount(2);
+
+        // Click the print button.
+        clickPrintButton();
+
+        // Wait for a finish.
+        waitForAdapterFinishCallbackCalled();
+
+        // Wait for the session to be destroyed to isolate tests.
+        waitForPrinterDiscoverySessionDestroyCallbackCalled();
+
+        // Verify the expected calls.
+        InOrder inOrder = inOrder(adapter);
+
+        // Start is always called first.
+        inOrder.verify(adapter).onStart();
+
+        // Start is always followed by a layout. The PDF printer is selected if
+        // there are other printers but none of them was used.
+        PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
+        PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
+                .setMediaSize(MediaSize.NA_LETTER)
+                .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
+                .setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+                .build();
+        verifyLayoutCall(inOrder, adapter, firstOldAttributes, firstNewAttributes, true);
+
+        // We always ask for the the first fifty pages for preview.
+        PageRange[] firstPages = new PageRange[] {new PageRange(0, 2)};
+        inOrder.verify(adapter).onWrite(eq(firstPages), any(ParcelFileDescriptor.class),
+                any(CancellationSignal.class), any(WriteResultCallback.class));
+
+        // We selected the second printer which does not support the media
+        // size that was selected, so a new layout happens as the size changed.
+        PrintAttributes secondOldAttributes = firstNewAttributes;
+        PrintAttributes secondNewAttributes = new PrintAttributes.Builder()
+                .setMediaSize(MediaSize.ISO_A3)
+                .setResolution(new Resolution("300x300", "300x300", 300, 300))
+                .setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+                .build();
+        verifyLayoutCall(inOrder, adapter, secondOldAttributes, secondNewAttributes, true);
+
+        // In the layout callback we reported that the content didn't change,
+        // and we wrote all pages in the write call while being asked only
+        // for the first page. Hence, all pages were written and they didn't
+        // change, therefore no subsequent write call should happen.
+
+        // When print is pressed we ask for a layout which is *not* for preview.
+        verifyLayoutCall(inOrder, adapter, secondNewAttributes, secondNewAttributes, false);
+
+        // In the layout callback we reported that the content didn't change,
+        // and we wrote all pages in the write call while being asked only
+        // for the first page. Hence, all pages were written and they didn't
+        // change, therefore no subsequent write call should happen.
+
+        // Finish is always called last.
+        inOrder.verify(adapter).onFinish();
+
+        // No other call are expected.
+        verifyNoMoreInteractions(adapter);
+    }
+
+    public void testCancelLongRunningLayout() throws Exception {
+        // Configure the print services.
+        FirstPrintService.setCallbacks(createFirstMockPrintServiceCallbacks());
+        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+        // Create a mock print adapter.
+        final PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(
+            new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                CancellationSignal cancellation = (CancellationSignal) invocation.getArguments()[2];
+                final LayoutResultCallback callback = (LayoutResultCallback) invocation
+                        .getArguments()[3];
+                cancellation.setOnCancelListener(new OnCancelListener() {
+                    @Override
+                    public void onCancel() {
+                        onCancelOperationCalled();
+                        callback.onLayoutCancelled();
+                    }
+                });
+                onLayoutCalled();
+                return null;
+            }
+        }, 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 layout.
+        waitForLayoutAdapterCallbackCount(1);
+
+        // Cancel printing.
+        getUiDevice().pressBack(); // wakes up the device.
+        getUiDevice().pressBack();
+
+        // Wait for the cancellation request.
+        waitForCancelOperationCallbackCalled();
+
+        // Wait for a finish.
+        waitForAdapterFinishCallbackCalled();
+
+        // Wait for the session to be destroyed to isolate tests.
+        waitForPrinterDiscoverySessionDestroyCallbackCalled();
+
+        // Verify the expected calls.
+        InOrder inOrder = inOrder(adapter);
+
+        // Start is always called first.
+        inOrder.verify(adapter).onStart();
+
+        // Start is always followed by a layout. The PDF printer is selected if
+        // there are other printers but none of them was used.
+        PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
+        PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
+                .setMediaSize(MediaSize.NA_LETTER)
+                .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
+                .setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+                .build();
+        verifyLayoutCall(inOrder, adapter, firstOldAttributes, firstNewAttributes, true);
+
+        // Finish is always called last.
+        inOrder.verify(adapter).onFinish();
+
+        // No other call are expected.
+        verifyNoMoreInteractions(adapter);
+    }
+
+    public void testCancelLongRunningWrite() throws Exception {
+        // Configure the print services.
+        FirstPrintService.setCallbacks(createFirstMockPrintServiceCallbacks());
+        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+        // 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();
+                callback.onLayoutFinished(info, false);
+                return null;
+            }
+        }, new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                Object[] args = invocation.getArguments();
+                final ParcelFileDescriptor fd = (ParcelFileDescriptor) args[1];
+                final CancellationSignal cancellation = (CancellationSignal) args[2];
+                final WriteResultCallback callback = (WriteResultCallback) args[3];
+                cancellation.setOnCancelListener(new OnCancelListener() {
+                    @Override
+                    public void onCancel() {
+                        try {
+                            fd.close();
+                        } catch (IOException ioe) {
+                            /* ignore */
+                        }
+                        onCancelOperationCalled();
+                        callback.onWriteCancelled();
+                    }
+                });
+                // 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.
+        waitForWriteAdapterCallback();
+
+        // Cancel printing.
+        getUiDevice().pressBack(); // wakes up the device.
+        getUiDevice().pressBack();
+
+        // Wait for the cancellation request.
+        waitForCancelOperationCallbackCalled();
+
+        // Wait for a finish.
+        waitForAdapterFinishCallbackCalled();
+
+        // Wait for the session to be destroyed to isolate tests.
+        waitForPrinterDiscoverySessionDestroyCallbackCalled();
+
+        // Verify the expected calls.
+        InOrder inOrder = inOrder(adapter);
+
+        // Start is always called first.
+        inOrder.verify(adapter).onStart();
+
+        // Start is always followed by a layout. The PDF printer is selected if
+        // there are other printers but none of them was used.
+        PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
+        PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
+                .setMediaSize(MediaSize.NA_LETTER)
+                .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
+                .setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+                .build();
+        verifyLayoutCall(inOrder, adapter, firstOldAttributes, firstNewAttributes, true);
+
+        // We always ask for the first page for preview.
+        PageRange[] firstPages = new PageRange[] {new PageRange(0, 0)};
+        inOrder.verify(adapter).onWrite(eq(firstPages), any(ParcelFileDescriptor.class),
+                any(CancellationSignal.class), any(WriteResultCallback.class));
+
+        // Finish is always called last.
+        inOrder.verify(adapter).onFinish();
+
+        // No other call are expected.
+        verifyNoMoreInteractions(adapter);
+    }
+
+    public void testFailedLayout() throws Exception {
+        // Configure the print services.
+        FirstPrintService.setCallbacks(createFirstMockPrintServiceCallbacks());
+        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+        // 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];
+                callback.onLayoutFailed(null);
+                // Mark layout was called.
+                onLayoutCalled();
+                return null;
+            }
+        }, 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 layout.
+        waitForLayoutAdapterCallbackCount(1);
+
+        // Cancel printing.
+        getUiDevice().pressBack(); // wakes up the device.
+        getUiDevice().pressBack();
+
+        // Wait for a finish.
+        waitForAdapterFinishCallbackCalled();
+
+        // Wait for the session to be destroyed to isolate tests.
+        waitForPrinterDiscoverySessionDestroyCallbackCalled();
+
+        // Verify the expected calls.
+        InOrder inOrder = inOrder(adapter);
+
+        // Start is always called first.
+        inOrder.verify(adapter).onStart();
+
+        // Start is always followed by a layout. The PDF printer is selected if
+        // there are other printers but none of them was used.
+        PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
+        PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
+                .setMediaSize(MediaSize.NA_LETTER)
+                .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
+                .setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+                .build();
+        verifyLayoutCall(inOrder, adapter, firstOldAttributes, firstNewAttributes, true);
+
+        // No write as layout failed.
+
+        // Finish is always called last.
+        inOrder.verify(adapter).onFinish();
+
+        // No other call are expected.
+        verifyNoMoreInteractions(adapter);
+    }
+
+    public void testFailedWrite() throws Exception {
+        // Configure the print services.
+        FirstPrintService.setCallbacks(createFirstMockPrintServiceCallbacks());
+        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+        // 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();
+                callback.onLayoutFinished(info, false);
+                return null;
+            }
+        }, new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                Object[] args = invocation.getArguments();
+                ParcelFileDescriptor fd = (ParcelFileDescriptor) args[1];
+                WriteResultCallback callback = (WriteResultCallback) args[3];
+                fd.close();
+                callback.onWriteFailed(null);
+                // 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.
+        waitForWriteAdapterCallback();
+
+        // Cancel printing.
+        getUiDevice().pressBack(); // wakes up the device.
+        getUiDevice().pressBack();
+
+        // Wait for a finish.
+        waitForAdapterFinishCallbackCalled();
+
+        // Wait for the session to be destroyed to isolate tests.
+        waitForPrinterDiscoverySessionDestroyCallbackCalled();
+
+        // Verify the expected calls.
+        InOrder inOrder = inOrder(adapter);
+
+        // Start is always called first.
+        inOrder.verify(adapter).onStart();
+
+        // Start is always followed by a layout. The PDF printer is selected if
+        // there are other printers but none of them was used.
+        PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
+        PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
+                .setMediaSize(MediaSize.NA_LETTER)
+                .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
+                .setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+                .build();
+        verifyLayoutCall(inOrder, adapter, firstOldAttributes, firstNewAttributes, true);
+
+        // We always ask for the first page for preview.
+        PageRange[] firstPages = new PageRange[] {new PageRange(0, 0)};
+        inOrder.verify(adapter).onWrite(eq(firstPages), any(ParcelFileDescriptor.class),
+                any(CancellationSignal.class), any(WriteResultCallback.class));
+
+        // Finish is always called last.
+        inOrder.verify(adapter).onFinish();
+
+        // No other call are expected.
+        verifyNoMoreInteractions(adapter);
+    }
+
+    public void testRequestedPagesNotWritten() throws Exception {
+        // Configure the print services.
+        FirstPrintService.setCallbacks(createFirstMockPrintServiceCallbacks());
+        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+        final PrintAttributes[] printAttributes = new PrintAttributes[1];
+
+        // Create a mock print adapter.
+        final PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(
+            new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                printAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
+                LayoutResultCallback callback = (LayoutResultCallback) invocation.getArguments()[3];
+                PrintDocumentInfo info = new PrintDocumentInfo.Builder(PRINT_JOB_NAME)
+                      .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT).setPageCount(1)
+                      .build();
+                callback.onLayoutFinished(info, false);
+                return null;
+            }
+        }, new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                Object[] args = invocation.getArguments();
+                ParcelFileDescriptor fd = (ParcelFileDescriptor) args[1];
+                WriteResultCallback callback = (WriteResultCallback) args[3];
+                PageRange[] pages = (PageRange[]) args[0];
+                writeBlankPages(printAttributes[0], fd, Integer.MAX_VALUE, Integer.MAX_VALUE);
+                fd.close();
+                // Write wrong pages.
+                callback.onWriteFinished(new PageRange[] {
+                        new PageRange(Integer.MAX_VALUE,Integer.MAX_VALUE)});
+                // 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.
+        waitForWriteAdapterCallback();
+
+        // Cancel printing.
+        getUiDevice().pressBack(); // wakes up the device.
+        getUiDevice().pressBack();
+
+        // Wait for a finish.
+        waitForAdapterFinishCallbackCalled();
+
+        // Wait for the session to be destroyed to isolate tests.
+        waitForPrinterDiscoverySessionDestroyCallbackCalled();
+
+        // Verify the expected calls.
+        InOrder inOrder = inOrder(adapter);
+
+        // Start is always called first.
+        inOrder.verify(adapter).onStart();
+
+        // Start is always followed by a layout. The PDF printer is selected if
+        // there are other printers but none of them was used.
+        PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
+        PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
+                .setMediaSize(MediaSize.NA_LETTER)
+                .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
+                .setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+                .build();
+        verifyLayoutCall(inOrder, adapter, firstOldAttributes, firstNewAttributes, true);
+
+        // We always ask for the first page for preview.
+        PageRange[] firstPages = new PageRange[] {new PageRange(0, 0)};
+        inOrder.verify(adapter).onWrite(eq(firstPages), any(ParcelFileDescriptor.class),
+                any(CancellationSignal.class), any(WriteResultCallback.class));
+
+        // Finish is always called last.
+        inOrder.verify(adapter).onFinish();
+
+        // No other call are expected.
+        verifyNoMoreInteractions(adapter);
+    }
+
+    public void testLayoutCallbackNotCalled() throws Exception {
+        // Configure the print services.
+        FirstPrintService.setCallbacks(createFirstMockPrintServiceCallbacks());
+        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+        // Create a mock print adapter.
+        final PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(
+            new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                // Break the contract and never call the callback.
+                // Mark layout called.
+                onLayoutCalled();
+                return null;
+            }
+        }, 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 layout.
+        waitForLayoutAdapterCallbackCount(1);
+
+        // Cancel printing.
+        getUiDevice().pressBack(); // wakes up the device.
+        getUiDevice().pressBack();
+
+        // Wait for a finish.
+        waitForAdapterFinishCallbackCalled();
+
+        // Wait for the session to be destroyed to isolate tests.
+        waitForPrinterDiscoverySessionDestroyCallbackCalled();
+
+        // Verify the expected calls.
+        InOrder inOrder = inOrder(adapter);
+
+        // Start is always called first.
+        inOrder.verify(adapter).onStart();
+
+        // Start is always followed by a layout. The PDF printer is selected if
+        // there are other printers but none of them was used.
+        PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
+        PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
+                .setMediaSize(MediaSize.NA_LETTER)
+                .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
+                .setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+                .build();
+        verifyLayoutCall(inOrder, adapter, firstOldAttributes, firstNewAttributes, true);
+
+        // Finish is always called last.
+        inOrder.verify(adapter).onFinish();
+
+        // No other call are expected.
+        verifyNoMoreInteractions(adapter);
+    }
+
+    public void testWriteCallbackNotCalled() throws Exception {
+        // Configure the print services.
+        FirstPrintService.setCallbacks(createFirstMockPrintServiceCallbacks());
+        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+        // 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();
+                callback.onLayoutFinished(info, false);
+                return null;
+            }
+        }, new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                Object[] args = invocation.getArguments();
+                ParcelFileDescriptor fd = (ParcelFileDescriptor) args[1];
+                fd.close();
+                // Break the contract and never call the callback.
+                // 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.
+        waitForWriteAdapterCallback();
+
+        // Cancel printing.
+        getUiDevice().pressBack(); // wakes up the device.
+        getUiDevice().pressBack();
+
+        // Wait for a finish.
+        waitForAdapterFinishCallbackCalled();
+
+        // Wait for the session to be destroyed to isolate tests.
+        waitForPrinterDiscoverySessionDestroyCallbackCalled();
+
+        // Verify the expected calls.
+        InOrder inOrder = inOrder(adapter);
+
+        // Start is always called first.
+        inOrder.verify(adapter).onStart();
+
+        // Start is always followed by a layout. The PDF printer is selected if
+        // there are other printers but none of them was used.
+        PrintAttributes firstOldAttributes = new PrintAttributes.Builder().build();
+        PrintAttributes firstNewAttributes = new PrintAttributes.Builder()
+                .setMediaSize(MediaSize.NA_LETTER)
+                .setResolution(new Resolution("PDF resolution", "PDF resolution", 300, 300))
+                .setMinMargins(Margins.NO_MARGINS).setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+                .build();
+        verifyLayoutCall(inOrder, adapter, firstOldAttributes, firstNewAttributes, true);
+
+        // We always ask for the first page for preview.
+        PageRange[] firstPages = new PageRange[] {new PageRange(0, 0)};
+        inOrder.verify(adapter).onWrite(eq(firstPages), any(ParcelFileDescriptor.class),
+                any(CancellationSignal.class), any(WriteResultCallback.class));
+
+        // Finish is always called last.
+        inOrder.verify(adapter).onFinish();
+
+        // No other call are expected.
+        verifyNoMoreInteractions(adapter);
+    }
+
+    private PrintServiceCallbacks createFirstMockPrintServiceCallbacks() {
+        final PrinterDiscoverySessionCallbacks callbacks =
+                createMockPrinterDiscoverySessionCallbacks(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) {
+                PrinterDiscoverySessionCallbacks mock = (PrinterDiscoverySessionCallbacks)
+                        invocation.getMock();
+
+                StubbablePrinterDiscoverySession session = mock.getSession();
+                PrintService service = session.getService();
+
+                if (session.getPrinters().isEmpty()) {
+                    List<PrinterInfo> printers = new ArrayList<PrinterInfo>();
+
+                    // Add the first printer.
+                    PrinterId firstPrinterId = service.generatePrinterId("first_printer");
+                    PrinterCapabilitiesInfo firstCapabilities =
+                            new PrinterCapabilitiesInfo.Builder(firstPrinterId)
+                        .setMinMargins(new Margins(200, 200, 200, 200))
+                        .addMediaSize(MediaSize.ISO_A4, true)
+                        .addMediaSize(MediaSize.ISO_A5, false)
+                        .addResolution(new Resolution("300x300", "300x300", 300, 300), true)
+                        .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
+                                PrintAttributes.COLOR_MODE_COLOR)
+                        .build();
+                    PrinterInfo firstPrinter = new PrinterInfo.Builder(firstPrinterId,
+                            "First printer", PrinterInfo.STATUS_IDLE)
+                        .setCapabilities(firstCapabilities)
+                        .build();
+                    printers.add(firstPrinter);
+
+                    // Add the second printer.
+                    PrinterId secondPrinterId = service.generatePrinterId("second_printer");
+                    PrinterCapabilitiesInfo secondCapabilities =
+                            new PrinterCapabilitiesInfo.Builder(secondPrinterId)
+                        .addMediaSize(MediaSize.ISO_A3, true)
+                        .addMediaSize(MediaSize.ISO_A4, false)
+                        .addResolution(new Resolution("200x200", "200x200", 200, 200), true)
+                        .addResolution(new Resolution("300x300", "300x300", 300, 300), false)
+                        .setColorModes(PrintAttributes.COLOR_MODE_COLOR
+                                | PrintAttributes.COLOR_MODE_MONOCHROME,
+                                PrintAttributes.COLOR_MODE_MONOCHROME)
+                        .build();
+                    PrinterInfo secondPrinter = new PrinterInfo.Builder(secondPrinterId,
+                            "Second printer", PrinterInfo.STATUS_IDLE)
+                        .setCapabilities(secondCapabilities)
+                        .build();
+                    printers.add(secondPrinter);
+
+                    // Add the third printer.
+                    PrinterId thirdPrinterId = service.generatePrinterId("third_printer");
+                    PrinterCapabilitiesInfo thirdCapabilities =
+                            new PrinterCapabilitiesInfo.Builder(thirdPrinterId)
+                        .addMediaSize(MediaSize.NA_LETTER, true)
+                        .addResolution(new Resolution("300x300", "300x300", 300, 300), true)
+                        .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
+                                PrintAttributes.COLOR_MODE_COLOR)
+                        .build();
+                    PrinterInfo thirdPrinter = new PrinterInfo.Builder(thirdPrinterId,
+                            "Third printer", PrinterInfo.STATUS_IDLE)
+                        .setCapabilities(thirdCapabilities)
+                        .build();
+                    printers.add(thirdPrinter);
+
+                    session.addPrinters(printers);
+                }
+                return null;
+            }
+        }, null, null, null, null, new Answer<Void>() {
+                @Override
+                public Void answer(InvocationOnMock invocation) throws Throwable {
+                    // Take a note onDestroy was called.
+                    onPrinterDiscoverySessionDestroyCalled();
+                    return null;
+                }
+            });
+        return createMockPrintServiceCallbacks(new Answer<PrinterDiscoverySessionCallbacks>() {
+            @Override
+            public PrinterDiscoverySessionCallbacks answer(InvocationOnMock invocation) {
+                return callbacks;
+            }
+        }, new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                PrintJob printJob = (PrintJob) invocation.getArguments()[0];
+                printJob.complete();
+                return null;
+            }
+        }, null);
+    }
+
+    private PrintServiceCallbacks createSecondMockPrintServiceCallbacks() {
+        return createMockPrintServiceCallbacks(null, null, null);
+    }
+}
diff --git a/tests/tests/print/src/android/print/cts/PrinterDiscoverySessionLifecycleTest.java b/tests/tests/print/src/android/print/cts/PrinterDiscoverySessionLifecycleTest.java
new file mode 100644
index 0000000..b092044
--- /dev/null
+++ b/tests/tests/print/src/android/print/cts/PrinterDiscoverySessionLifecycleTest.java
@@ -0,0 +1,433 @@
+/*
+ * 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.print.cts;
+
+import static org.mockito.Mockito.inOrder;
+
+import android.os.ParcelFileDescriptor;
+import android.print.PageRange;
+import android.print.PrintAttributes;
+import android.print.PrintAttributes.Margins;
+import android.print.PrintAttributes.MediaSize;
+import android.print.PrintAttributes.Resolution;
+import android.print.PrintDocumentAdapter;
+import android.print.PrintDocumentAdapter.LayoutResultCallback;
+import android.print.PrintDocumentAdapter.WriteResultCallback;
+import android.print.PrintDocumentInfo;
+import android.print.PrinterCapabilitiesInfo;
+import android.print.PrinterId;
+import android.print.PrinterInfo;
+import android.print.cts.services.FirstPrintService;
+import android.print.cts.services.PrintServiceCallbacks;
+import android.print.cts.services.PrinterDiscoverySessionCallbacks;
+import android.print.cts.services.SecondPrintService;
+import android.print.cts.services.StubbablePrinterDiscoverySession;
+import android.printservice.PrintJob;
+import android.printservice.PrinterDiscoverySession;
+
+import junit.framework.AssertionFailedError;
+import org.mockito.InOrder;
+import org.mockito.exceptions.verification.VerificationInOrderFailure;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * This test verifies that the system respects the {@link PrinterDiscoverySession}
+ * contract is respected.
+ */
+public class PrinterDiscoverySessionLifecycleTest extends BasePrintTest {
+    private static final String FIRST_PRINTER_NAME = "First printer";
+    private static final String SECOND_PRINTER_NAME = "Second printer";
+
+    private static final String FIRST_PRINTER_LOCAL_ID= "first_printer";
+    private static final String SECOND_PRINTER_LOCAL_ID = "second_printer";
+
+    public void testNormalLifecycle() throws Exception {
+        // Create the session callbacks that we will be checking.
+        final PrinterDiscoverySessionCallbacks firstSessionCallbacks =
+                createFirstMockPrinterDiscoverySessionCallbacks();
+
+        // Create the service callbacks for the first print service.
+        PrintServiceCallbacks firstServiceCallbacks = createMockPrintServiceCallbacks(
+                new Answer<PrinterDiscoverySessionCallbacks>() {
+                @Override
+                public PrinterDiscoverySessionCallbacks answer(InvocationOnMock invocation) {
+                        return firstSessionCallbacks;
+                    }
+                },
+                new Answer<Void>() {
+                @Override
+                public Void answer(InvocationOnMock invocation) {
+                    PrintJob printJob = (PrintJob) invocation.getArguments()[0];
+                    // We pretend the job is handled immediately.
+                    printJob.complete();
+                    return null;
+                }
+            }, null);
+
+        // Configure the print services.
+        FirstPrintService.setCallbacks(firstServiceCallbacks);
+        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+        // Create a print adapter that respects the print contract.
+        PrintDocumentAdapter adapter = createMockPrintDocumentAdapter();
+
+        // Start printing.
+        print(adapter);
+
+        // Wait for write of the first page.
+        waitForWriteAdapterCallback();
+
+        // Select the first printer.
+        selectPrinter(FIRST_PRINTER_NAME);
+
+        // Wait for layout as the printer has different capabilities.
+        waitForLayoutAdapterCallbackCount(2);
+
+        // Select the second printer (same capabilities as the other
+        // one so no layout should happen).
+        selectPrinter(SECOND_PRINTER_NAME);
+
+        // While the printer discovery session is still alive store the
+        // ids of printers as we want to make some assertions about them
+        // but only the print service can create printer ids which means
+        // that we need to get the created ones.
+        PrinterId firstPrinterId = getAddedPrinterIdForLocalId(firstSessionCallbacks,
+                FIRST_PRINTER_LOCAL_ID);
+        PrinterId secondPrinterId = getAddedPrinterIdForLocalId(firstSessionCallbacks,
+                SECOND_PRINTER_LOCAL_ID);
+        assertNotNull("Coundn't find printer:" + FIRST_PRINTER_LOCAL_ID, firstPrinterId);
+        assertNotNull("Coundn't find printer:" + SECOND_PRINTER_LOCAL_ID, secondPrinterId);
+
+        // Click the print button.
+        clickPrintButton();
+
+        // Wait for all print jobs to be handled after which the session destroyed.
+        waitForPrinterDiscoverySessionDestroyCallbackCalled();
+
+        // Verify the expected calls.
+        InOrder inOrder = inOrder(firstSessionCallbacks);
+
+        // We start discovery as the print dialog was up.
+        List<PrinterId> emptyPrinterIdList = Collections.emptyList();
+        inOrder.verify(firstSessionCallbacks).onStartPrinterDiscovery(
+                emptyPrinterIdList);
+
+        // We selected the first printer and now it should be tracked.
+        inOrder.verify(firstSessionCallbacks).onStartPrinterStateTracking(
+                firstPrinterId);
+
+        // We selected the second printer so the first should not be tracked.
+        inOrder.verify(firstSessionCallbacks).onStopPrinterStateTracking(
+                firstPrinterId);
+
+        // We selected the second printer and now it should be tracked.
+        inOrder.verify(firstSessionCallbacks).onStartPrinterStateTracking(
+                secondPrinterId);
+
+        // The print dialog went away so we first stop the printer tracking...
+        inOrder.verify(firstSessionCallbacks).onStopPrinterStateTracking(
+                secondPrinterId);
+
+        // ... next we stop printer discovery...
+        inOrder.verify(firstSessionCallbacks).onStopPrinterDiscovery();
+
+        // ... last the session is destroyed.
+        inOrder.verify(firstSessionCallbacks).onDestroy();
+    }
+
+    public void testStartPrinterDiscoveryWithHistoricalPrinters() throws Exception {
+        // Create the session callbacks that we will be checking.
+        final PrinterDiscoverySessionCallbacks firstSessionCallbacks =
+                createFirstMockPrinterDiscoverySessionCallbacks();
+
+        // Create the service callbacks for the first print service.
+        PrintServiceCallbacks firstServiceCallbacks = createMockPrintServiceCallbacks(
+                new Answer<PrinterDiscoverySessionCallbacks>() {
+                @Override
+                public PrinterDiscoverySessionCallbacks answer(InvocationOnMock invocation) {
+                        return firstSessionCallbacks;
+                    }
+                },
+                new Answer<Void>() {
+                @Override
+                public Void answer(InvocationOnMock invocation) {
+                    PrintJob printJob = (PrintJob) invocation.getArguments()[0];
+                    // We pretend the job is handled immediately.
+                    printJob.complete();
+                    return null;
+                }
+            }, null);
+
+        // Configure the print services.
+        FirstPrintService.setCallbacks(firstServiceCallbacks);
+        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
+
+        // Create a print adapter that respects the print contract.
+        PrintDocumentAdapter adapter = createMockPrintDocumentAdapter();
+
+        // Start printing.
+        print(adapter);
+
+        // Wait for write of the first page.
+        waitForWriteAdapterCallback();
+
+        // Select the first printer.
+        selectPrinter(FIRST_PRINTER_NAME);
+
+        // Wait for a layout to finish - first layout was for the
+        // PDF printer, second for the first printer in preview mode.
+        waitForLayoutAdapterCallbackCount(2);
+
+        // While the printer discovery session is still alive store the
+        // ids of printer as we want to make some assertions about it
+        // but only the print service can create printer ids which means
+        // that we need to get the created one.
+        PrinterId firstPrinterId = getAddedPrinterIdForLocalId(
+                firstSessionCallbacks, FIRST_PRINTER_LOCAL_ID);
+
+        // Click the print button.
+        clickPrintButton();
+
+        // Wait for the print to complete.
+        waitForAdapterFinishCallbackCalled();
+
+        // Now print again as we want to confirm that the start
+        // printer discovery passes in the priority list.
+        print(adapter);
+
+        // Wait for a layout to finish - first layout was for the
+        // PDF printer, second for the first printer in preview mode,
+        // the third for the first printer in non-preview mode, and
+        // now a fourth for the PDF printer as we are printing again.
+        waitForLayoutAdapterCallbackCount(4);
+
+        // Cancel the printing.
+        getUiDevice().pressBack(); // wakes up the device.
+        getUiDevice().pressBack();
+
+        // 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 with no printer history.
+        List<PrinterId> priorityList = new ArrayList<PrinterId>();
+        inOrder.verify(firstSessionCallbacks).onStartPrinterDiscovery(
+                priorityList);
+
+        // We selected the first printer and now it should be tracked.
+        inOrder.verify(firstSessionCallbacks).onStartPrinterStateTracking(
+                firstPrinterId);
+
+        // We confirmed print so the first should not be tracked.
+        inOrder.verify(firstSessionCallbacks).onStopPrinterStateTracking(
+                firstPrinterId);
+
+        // This is tricky. It is possible that the print activity was not
+        // destroyed (the platform delays destruction at convenient time as
+        // an optimization) and we get the same instance which means that
+        // the discovery session may not have been destroyed. We try the
+        // case with the activity being destroyed and if this fails the
+        // case with the activity brought to front.
+        priorityList.add(firstPrinterId);
+        try {
+            inOrder.verify(firstSessionCallbacks).onStartPrinterDiscovery(priorityList);
+        } catch (VerificationInOrderFailure error) {
+            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.
+        inOrder.verify(firstSessionCallbacks).onDestroy();
+    }
+
+    private PrinterId getAddedPrinterIdForLocalId(
+            final PrinterDiscoverySessionCallbacks sessionCallbacks, String printerLocalId) {
+        final List<PrinterInfo> reportedPrinters = new ArrayList<PrinterInfo>();
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                // Grab the printer ids as only the service can create such.
+                StubbablePrinterDiscoverySession session = sessionCallbacks.getSession();
+                reportedPrinters.addAll(session.getPrinters());
+            }
+        });
+
+        final int reportedPrinterCount = reportedPrinters.size();
+        for (int i = 0; i < reportedPrinterCount; i++) {
+            PrinterInfo reportedPrinter = reportedPrinters.get(i);
+            String localId = reportedPrinter.getId().getLocalId();
+            if (printerLocalId.equals(localId)) {
+                return reportedPrinter.getId();
+            }
+        }
+
+        return null;
+    }
+
+    private PrintServiceCallbacks createSecondMockPrintServiceCallbacks() {
+        return createMockPrintServiceCallbacks(null, null, null);
+    }
+
+    private PrinterDiscoverySessionCallbacks createFirstMockPrinterDiscoverySessionCallbacks() {
+        return createMockPrinterDiscoverySessionCallbacks(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) {
+                // Get the session.
+                StubbablePrinterDiscoverySession session = ((PrinterDiscoverySessionCallbacks)
+                        invocation.getMock()).getSession();
+
+                if (session.getPrinters().isEmpty()) {
+                    List<PrinterInfo> printers = new ArrayList<PrinterInfo>();
+
+                    // Add the first printer.
+                    PrinterId firstPrinterId = session.getService().generatePrinterId(
+                            FIRST_PRINTER_LOCAL_ID);
+                    PrinterInfo firstPrinter = new PrinterInfo.Builder(firstPrinterId,
+                            FIRST_PRINTER_NAME, PrinterInfo.STATUS_IDLE)
+                        .build();
+                    printers.add(firstPrinter);
+
+                    // Add the first printer.
+                    PrinterId secondPrinterId = session.getService().generatePrinterId(
+                            SECOND_PRINTER_LOCAL_ID);
+                    PrinterInfo secondPrinter = new PrinterInfo.Builder(secondPrinterId,
+                            SECOND_PRINTER_NAME, PrinterInfo.STATUS_IDLE)
+                        .build();
+                    printers.add(secondPrinter);
+
+                    session.addPrinters(printers);
+                }
+                return null;
+            }
+        }, null, null, new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                // Get the session.
+                StubbablePrinterDiscoverySession session = ((PrinterDiscoverySessionCallbacks)
+                        invocation.getMock()).getSession();
+
+                PrinterId trackedPrinterId = (PrinterId) invocation.getArguments()[0];
+                List<PrinterInfo> reportedPrinters = session.getPrinters();
+
+                // We should be tracking a printer that we added.
+                PrinterInfo trackedPrinter = null;
+                final int reportedPrinterCount = reportedPrinters.size();
+                for (int i = 0; i < reportedPrinterCount; i++) {
+                    PrinterInfo reportedPrinter = reportedPrinters.get(i);
+                    if (reportedPrinter.getId().equals(trackedPrinterId)) {
+                        trackedPrinter = reportedPrinter;
+                        break;
+                    }
+                }
+                assertNotNull("Can track only added printers", trackedPrinter);
+
+                // If the printer does not have capabilities reported add them.
+                if (trackedPrinter.getCapabilities() == null) {
+
+                    // Add the capabilities to emulate lazy discovery.
+                    // Same for each printer is fine for what we test.
+                    PrinterCapabilitiesInfo capabilities =
+                            new PrinterCapabilitiesInfo.Builder(trackedPrinterId)
+                        .setMinMargins(new Margins(200, 200, 200, 200))
+                        .addMediaSize(MediaSize.ISO_A4, true)
+                        .addMediaSize(MediaSize.ISO_A5, false)
+                        .addResolution(new Resolution("300x300", "300x300", 300, 300), true)
+                        .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
+                                PrintAttributes.COLOR_MODE_COLOR)
+                        .build();
+                    PrinterInfo updatedPrinter = new PrinterInfo.Builder(trackedPrinter)
+                        .setCapabilities(capabilities)
+                        .build();
+
+                    // Update the printer.
+                    List<PrinterInfo> printers = new ArrayList<PrinterInfo>();
+                    printers.add(updatedPrinter);
+                    session.addPrinters(printers);
+                }
+
+                return null;
+            }
+        }, null, new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                // Take a note onDestroy was called.
+                onPrinterDiscoverySessionDestroyCalled();
+                return null;
+            }
+        });
+    }
+
+    public PrintDocumentAdapter createMockPrintDocumentAdapter() {
+        final PrintAttributes[] printAttributes = new PrintAttributes[1];
+
+        return createMockPrintDocumentAdapter(
+            new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                printAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
+                LayoutResultCallback callback = (LayoutResultCallback) invocation.getArguments()[3];
+                PrintDocumentInfo info = new PrintDocumentInfo.Builder(PRINT_JOB_NAME)
+                        .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
+                        .setPageCount(3)
+                        .build();
+                callback.onLayoutFinished(info, false);
+                // Mark layout was called.
+                onLayoutCalled();
+                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];
+                writeBlankPages(printAttributes[0], fd, pages[0].getStart(), pages[0].getEnd());
+                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;
+            }
+        });
+    }
+}
diff --git a/tests/tests/print/src/android/print/cts/services/AddPrintersActivity.java b/tests/tests/print/src/android/print/cts/services/AddPrintersActivity.java
new file mode 100644
index 0000000..c72d6f9
--- /dev/null
+++ b/tests/tests/print/src/android/print/cts/services/AddPrintersActivity.java
@@ -0,0 +1,28 @@
+/*
+ * 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.print.cts.services;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class AddPrintersActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+}
diff --git a/tests/tests/print/src/android/print/cts/services/CustomPrintOptionsActivity.java b/tests/tests/print/src/android/print/cts/services/CustomPrintOptionsActivity.java
new file mode 100644
index 0000000..9d26d81
--- /dev/null
+++ b/tests/tests/print/src/android/print/cts/services/CustomPrintOptionsActivity.java
@@ -0,0 +1,28 @@
+/*
+ * 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.print.cts.services;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class CustomPrintOptionsActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+}
diff --git a/tests/tests/print/src/android/print/cts/services/FirstPrintService.java b/tests/tests/print/src/android/print/cts/services/FirstPrintService.java
new file mode 100644
index 0000000..a234de4
--- /dev/null
+++ b/tests/tests/print/src/android/print/cts/services/FirstPrintService.java
@@ -0,0 +1,40 @@
+/*
+ * 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.print.cts.services;
+
+public class FirstPrintService extends StubbablePrintService {
+
+    private static final Object sLock = new Object();
+
+    private static PrintServiceCallbacks sCallbacks;
+
+    public static void setCallbacks(PrintServiceCallbacks callbacks) {
+        synchronized (sLock) {
+            sCallbacks = callbacks;
+        }
+    }
+
+    @Override
+    protected PrintServiceCallbacks getCallbacks() {
+        synchronized (sLock) {
+            if (sCallbacks != null) {
+                sCallbacks.setService(this);
+            }
+            return sCallbacks;
+        }
+    }
+}
diff --git a/tests/tests/print/src/android/print/cts/services/PrintServiceCallbacks.java b/tests/tests/print/src/android/print/cts/services/PrintServiceCallbacks.java
new file mode 100644
index 0000000..ff0245f
--- /dev/null
+++ b/tests/tests/print/src/android/print/cts/services/PrintServiceCallbacks.java
@@ -0,0 +1,39 @@
+/*
+ * 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.print.cts.services;
+
+import android.printservice.PrintJob;
+import android.printservice.PrintService;
+
+public abstract class PrintServiceCallbacks {
+
+    private PrintService mService;
+
+    public PrintService getService() {
+        return mService;
+    }
+
+    public void setService(PrintService service) {
+        mService = service;
+    }
+
+    public abstract PrinterDiscoverySessionCallbacks onCreatePrinterDiscoverySessionCallbacks();
+
+    public abstract void onRequestCancelPrintJob(PrintJob printJob);
+
+    public abstract void onPrintJobQueued(PrintJob printJob);
+}
diff --git a/tests/tests/print/src/android/print/cts/services/PrinterDiscoverySessionCallbacks.java b/tests/tests/print/src/android/print/cts/services/PrinterDiscoverySessionCallbacks.java
new file mode 100644
index 0000000..6b2c3a9
--- /dev/null
+++ b/tests/tests/print/src/android/print/cts/services/PrinterDiscoverySessionCallbacks.java
@@ -0,0 +1,46 @@
+/*
+ * 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.print.cts.services;
+
+import android.print.PrinterId;
+
+import java.util.List;
+
+public abstract class PrinterDiscoverySessionCallbacks {
+
+    private StubbablePrinterDiscoverySession mSession;
+
+    public void setSession(StubbablePrinterDiscoverySession session) {
+        mSession = session;
+    }
+
+    public StubbablePrinterDiscoverySession getSession() {
+        return mSession;
+    }
+
+    public abstract void onStartPrinterDiscovery(List<PrinterId> priorityList);
+
+    public abstract void onStopPrinterDiscovery();
+
+    public abstract void onValidatePrinters(List<PrinterId> printerIds);
+
+    public abstract void onStartPrinterStateTracking(PrinterId printerId);
+
+    public abstract void onStopPrinterStateTracking(PrinterId printerId);
+
+    public abstract void onDestroy();
+}
diff --git a/tests/tests/print/src/android/print/cts/services/SecondPrintService.java b/tests/tests/print/src/android/print/cts/services/SecondPrintService.java
new file mode 100644
index 0000000..1029a8e
--- /dev/null
+++ b/tests/tests/print/src/android/print/cts/services/SecondPrintService.java
@@ -0,0 +1,40 @@
+/*
+ * 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.print.cts.services;
+
+public class SecondPrintService extends StubbablePrintService {
+
+    private static final Object sLock = new Object();
+
+    private static PrintServiceCallbacks sCallbacks;
+
+    public static void setCallbacks(PrintServiceCallbacks callbacks) {
+        synchronized (sLock) {
+            sCallbacks = callbacks;
+        }
+    }
+
+    @Override
+    protected PrintServiceCallbacks getCallbacks() {
+        synchronized (sLock) {
+            if (sCallbacks != null) {
+                sCallbacks.setService(this);
+            }
+            return sCallbacks;
+        }
+    }
+}
diff --git a/tests/tests/print/src/android/print/cts/services/SettingsActivity.java b/tests/tests/print/src/android/print/cts/services/SettingsActivity.java
new file mode 100644
index 0000000..eb23574
--- /dev/null
+++ b/tests/tests/print/src/android/print/cts/services/SettingsActivity.java
@@ -0,0 +1,28 @@
+/*
+ * 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.print.cts.services;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class SettingsActivity extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+}
diff --git a/tests/tests/print/src/android/print/cts/services/StubbablePrintService.java b/tests/tests/print/src/android/print/cts/services/StubbablePrintService.java
new file mode 100644
index 0000000..2686b41
--- /dev/null
+++ b/tests/tests/print/src/android/print/cts/services/StubbablePrintService.java
@@ -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.
+ */
+
+package android.print.cts.services;
+
+import android.printservice.PrintJob;
+import android.printservice.PrintService;
+import android.printservice.PrinterDiscoverySession;
+
+public abstract class StubbablePrintService extends PrintService {
+
+    @Override
+    public PrinterDiscoverySession onCreatePrinterDiscoverySession() {
+        PrintServiceCallbacks callbacks = getCallbacks();
+        if (callbacks != null) {
+            return new StubbablePrinterDiscoverySession(this,
+                    getCallbacks().onCreatePrinterDiscoverySessionCallbacks());
+        }
+        return null;
+    }
+
+    @Override
+    public void onRequestCancelPrintJob(PrintJob printJob) {
+        PrintServiceCallbacks callbacks = getCallbacks();
+        if (callbacks != null) {
+            callbacks.onRequestCancelPrintJob(printJob);
+        }
+    }
+
+    @Override
+    public void onPrintJobQueued(PrintJob printJob) {
+        PrintServiceCallbacks callbacks = getCallbacks();
+        if (callbacks != null) {
+            callbacks.onPrintJobQueued(printJob);
+        }
+    }
+
+    protected abstract PrintServiceCallbacks getCallbacks();
+}
diff --git a/tests/tests/print/src/android/print/cts/services/StubbablePrinterDiscoverySession.java b/tests/tests/print/src/android/print/cts/services/StubbablePrinterDiscoverySession.java
new file mode 100644
index 0000000..fdc2713
--- /dev/null
+++ b/tests/tests/print/src/android/print/cts/services/StubbablePrinterDiscoverySession.java
@@ -0,0 +1,83 @@
+/*
+ * 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.print.cts.services;
+
+import android.print.PrinterId;
+import android.printservice.PrintService;
+import android.printservice.PrinterDiscoverySession;
+
+import java.util.List;
+
+public class StubbablePrinterDiscoverySession extends PrinterDiscoverySession {
+    private final PrintService mService;
+    private final PrinterDiscoverySessionCallbacks mCallbacks;
+
+    public StubbablePrinterDiscoverySession(PrintService service,
+            PrinterDiscoverySessionCallbacks callbacks) {
+        mService = service;
+        mCallbacks = callbacks;
+        if (mCallbacks != null) {
+            mCallbacks.setSession(this);
+        }
+    }
+
+    public PrintService getService() {
+        return mService;
+    }
+
+    @Override
+    public void onStartPrinterDiscovery(List<PrinterId> priorityList) {
+        if (mCallbacks != null) {
+            mCallbacks.onStartPrinterDiscovery(priorityList);
+        }
+    }
+
+    @Override
+    public void onStopPrinterDiscovery() {
+        if (mCallbacks != null) {
+            mCallbacks.onStopPrinterDiscovery();
+        }
+    }
+
+    @Override
+    public void onValidatePrinters(List<PrinterId> printerIds) {
+        if (mCallbacks != null) {
+            mCallbacks.onValidatePrinters(printerIds);
+        }
+    }
+
+    @Override
+    public void onStartPrinterStateTracking(PrinterId printerId) {
+        if (mCallbacks != null) {
+            mCallbacks.onStartPrinterStateTracking(printerId);
+        }
+    }
+
+    @Override
+    public void onStopPrinterStateTracking(PrinterId printerId) {
+        if (mCallbacks != null) {
+            mCallbacks.onStopPrinterStateTracking(printerId);
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        if (mCallbacks != null) {
+            mCallbacks.onDestroy();
+        }
+    }
+}
diff --git a/tests/tests/provider/Android.mk b/tests/tests/provider/Android.mk
index 4c5875b..58a7516 100644
--- a/tests/tests/provider/Android.mk
+++ b/tests/tests/provider/Android.mk
@@ -18,17 +18,21 @@
 
 # don't include this package in any target
 LOCAL_MODULE_TAGS := optional
+
+# Include both the 32 and 64 bit versions of libs
+LOCAL_MULTILIB := both
+
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
 LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
+
+LOCAL_JNI_SHARED_LIBRARIES := libcts_jni
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsProviderTestCases
 
-LOCAL_INSTRUMENTATION_FOR := CtsTestStubs
-
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/provider/AndroidManifest.xml b/tests/tests/provider/AndroidManifest.xml
index 94dc408..abda46c 100644
--- a/tests/tests/provider/AndroidManifest.xml
+++ b/tests/tests/provider/AndroidManifest.xml
@@ -23,10 +23,36 @@
     <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
     <uses-permission android:name="android.permission.GET_ACCOUNTS" />
     <uses-permission android:name="android.permission.USE_CREDENTIALS" />
+    <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
+    <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
+    <uses-permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS" />
+    <uses-permission android:name="com.android.browser.permission.WRITE_HISTORY_BOOKMARKS" />
+    <uses-permission android:name="android.permission.WRITE_CALENDAR" />
+    <uses-permission android:name="android.permission.READ_CALENDAR" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+    <uses-permission android:name="android.permission.WRITE_USER_DICTIONARY" />
+    <uses-permission android:name="android.permission.READ_USER_DICTIONARY" />
+    <uses-permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL" />
+    <uses-permission android:name="android.permission.WRITE_CALL_LOG" />
+    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
+    <uses-permission android:name="android.permission.WRITE_SOCIAL_STREAM" />
+    <uses-permission android:name="android.permission.READ_CALL_LOG" />
+    <uses-permission android:name="android.permission.READ_CONTACTS" />
+    <uses-permission android:name="android.permission.READ_SOCIAL_STREAM" />
 
     <application>
         <uses-library android:name="android.test.runner"/>
 
+        <activity android:name="android.provider.cts.BrowserStubActivity"
+            android:label="BrowserStubActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
         <service android:name="android.provider.cts.contacts.account.MockAccountService"
                  process="com.android.cts.provider"
                  android:exported="true">
@@ -40,12 +66,15 @@
 
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="com.android.cts.stub"
-                     android:label="CTS tests of android.provider"/>
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.provider"
+                     android:label="CTS tests of android.provider">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
     <instrumentation android:name="android.provider.cts.CalendarTest$CalendarEmmaTestRunner"
-                     android:targetPackage="com.android.cts.stub"
+                     android:targetPackage="com.android.cts.provider"
                      android:label="Augmented CTS tests of Calendar provider"/>
 
 </manifest>
diff --git a/tests/res/drawable/scenery.jpg b/tests/tests/provider/res/drawable/scenery.jpg
similarity index 100%
copy from tests/res/drawable/scenery.jpg
copy to tests/tests/provider/res/drawable/scenery.jpg
Binary files differ
diff --git a/tests/res/drawable/size_48x48.jpg b/tests/tests/provider/res/drawable/size_48x48.jpg
similarity index 100%
copy from tests/res/drawable/size_48x48.jpg
copy to tests/tests/provider/res/drawable/size_48x48.jpg
Binary files differ
diff --git a/tests/res/drawable/testimage.jpg b/tests/tests/provider/res/drawable/testimage.jpg
similarity index 100%
copy from tests/res/drawable/testimage.jpg
copy to tests/tests/provider/res/drawable/testimage.jpg
Binary files differ
diff --git a/tests/res/raw/scenery.jpg b/tests/tests/provider/res/raw/scenery.jpg
similarity index 100%
copy from tests/res/raw/scenery.jpg
copy to tests/tests/provider/res/raw/scenery.jpg
Binary files differ
diff --git a/tests/res/raw/testmp3.mp3 b/tests/tests/provider/res/raw/testmp3.mp3
similarity index 100%
copy from tests/res/raw/testmp3.mp3
copy to tests/tests/provider/res/raw/testmp3.mp3
Binary files differ
diff --git a/tests/tests/provider/res/raw/testmp3_2.mp3 b/tests/tests/provider/res/raw/testmp3_2.mp3
new file mode 100644
index 0000000..6a70c69
--- /dev/null
+++ b/tests/tests/provider/res/raw/testmp3_2.mp3
Binary files differ
diff --git a/tests/res/raw/testvideo.3gp b/tests/tests/provider/res/raw/testvideo.3gp
similarity index 100%
copy from tests/res/raw/testvideo.3gp
copy to tests/tests/provider/res/raw/testvideo.3gp
Binary files differ
diff --git a/tests/res/values/arrays.xml b/tests/tests/provider/res/values/arrays.xml
similarity index 100%
copy from tests/res/values/arrays.xml
copy to tests/tests/provider/res/values/arrays.xml
diff --git a/tests/tests/provider/res/values/strings.xml b/tests/tests/provider/res/values/strings.xml
index b599c31..eb10ca1 100644
--- a/tests/tests/provider/res/values/strings.xml
+++ b/tests/tests/provider/res/values/strings.xml
@@ -15,6 +15,168 @@
   -->
 
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="permlab_testGranted">Test Granted</string>
+    <string name="permdesc_testGranted">Used for running CTS tests, for testing operations
+        where we have the permission.</string>
+    <string name="permlab_testDynamic">Test Dynamic</string>
+    <string name="permdesc_testDynamic">Used for running CTS tests, for testing adding
+        dynamic permissions.</string>
+    <string name="permlab_testDenied">Test Denied</string>
+    <string name="permdesc_testDenied">Used for running CTS tests, for testing operations
+        where we do not have the permission.</string>
+    <string name="explain">1. click start. \n2. if above image shaked, then press pass button,
+         else press failed button.</string>
+    <string name="text_view_hello">Hello! Text view!</string>
+    <string name="text_view_hello_two_lines">Hello! \nText view!</string>
+    <string name="text_view_simple_hint">This is a hint.</string>
+    <string name="text_view_hint">This is a string for testing hint of textview.</string>
+    <string name="activity_forwarding">App/Forwarding</string>
+    <string name="forwarding">$$$</string>
+    <string name="go">Go</string>
+    <string name="back">Back</string>
+    <string name="forward_target">
+        Press back button and notice we don\'t see the previous activity.
+    </string>
+    <string name="edit_text">testing</string>
+    <string name="text">DialogTest</string>
+    <string name="text_country">Country</string>
+    <string name="text_name">Name</string>
+    <string name="hello_world">Hello, World!</string>
+    <string name="hello_android">Hello, Android!</string>
+    <string name="alert_dialog_username">Name:</string>
+    <string name="alert_dialog_password">Password:</string>
+    <string name="alert_dialog_positive">Positive</string>
+    <string name="alert_dialog_negative">Negative</string>
+    <string name="alert_dialog_neutral">Neutral</string>
+    <string name="notify">Notify </string>
+    <string name="tabs_1">testing</string>
+    <string name="table_layout_first">first</string>
+    <string name="table_layout_second">second</string>
+    <string name="table_layout_third">third</string>
+    <string name="table_layout_long">Very long to make the string out of the screen</string>
+    <string name="chronometer_text">Test Chronometer</string>
+    <string name="am">AM</string>
+    <string name="pm">PM</string>
+    <string name="viewgroup_test">ViewGroup test</string>
+    <string name="viewanimator_test">ViewAnimator test</string>
+    <string name="id_ok">OK</string>
+    <string name="id_cancel">Cancel</string>
+    <string name="context_test_string1">This is %s string.</string>
+    <string name="context_test_string2">This is test string.</string>
+    <string name="animationutils_test_instructions">Choose different animations</string>
+    <string name="animationutils_test_alpha">Alpha animation</string>
+    <string name="animationutils_test_scale">Scale animation</string>
+    <string name="animationutils_test_rotate">Rotate animation</string>
+    <string name="animationutils_test_translate">Translate animation</string>
+    <string name="animationutils_test_set">Animation set</string>
+    <string name="animationutils_test_layout">Layout animation</string>
+    <string name="animationutils_test_gridlayout">Grid layout animation</string>
+    <string name="twolinelistitem_test_text1">text1</string>
+    <string name="twolinelistitem_test_text2">text2</string>
+    <string name="metadata_text">metadata text</string>
+    <string name="horizontal_text_1">horizontal 1</string>
+    <string name="horizontal_text_2">horizontal 2</string>
+    <string name="horizontal_text_3">horizontal 3</string>
+    <string name="vertical_text_1">vertical 1</string>
+    <string name="vertical_text_2">vertical 2</string>
+    <string name="vertical_text_3">vertical 3</string>
+    <string name="reference">here</string>
+    <string name="coerceIntegerToString">100</string>
+    <string name="coerceBooleanToString">true</string>
+    <string name="coerceColorToString">#fff</string>
+    <string name="coerceFloatToString">100.0</string>
+    <string name="coerceDimensionToString">100px</string>
+    <string name="coerceFractionToString">100<xliff:g id="percent">%</xliff:g></string>
+    <string name="formattedStringNone">Format[]</string>
+    <string name="formattedStringOne">Format[<xliff:g id="format">%d</xliff:g>]</string>
+    <string name="formattedStringTwo">Format[<xliff:g id="format">%3$d,%2$s</xliff:g>]</string>
+    <string name="checkboxpref_key">checkboxpref_key</string>
+    <string name="checkboxpref_title">title of preference</string>
+    <string name="checkboxpref_summary">summary of preference</string>
+    <string name="checkboxpref_summary_on">summary on of preference</string>
+    <string name="checkboxpref_summary_off">summary off of preference</string>
+    <string name="checkboxpref_depend">checkboxpref_depend</string>
+    <string name="checkboxpref_depend_title"> depend title of preference</string>
+    <string name="checkboxpref_depend_summary"> depend summary of preference</string>
+    <string name="edittextpref_key">edittextpref_key</string>
+    <string name="edittextpref_default_value">default value of preference</string>
+    <string name="edittextpref_title">title of edit text preference</string>
+    <string name="edittextpref_summary">summary of edit text preference</string>
+    <string name="edittextpref_dialog_title">dialog title of edit text preference</string>
+    <string name="edittextpref_text">text of  edit text preference</string>
+    <string name="listpref_key">listpref_key</string>
+    <string name="listpref_title">title of list preference</string>
+    <string name="listpref_summary">summary of list preference</string>
+    <string name="listpref_dialogtitle">dialog title of list preference</string>
+    <string name="easy">Easy</string>
+    <string name="medium">Medium</string>
+    <string name="hard">Hard</string>
+    <string name="footer_view">Footer view</string>
+    <string name="header_view">Header view</string>
+    <string name="dialogpref_title">title of dialog preference </string>
+    <string name="dialogpref_dialog_title">dialog title of dialog preference </string>
+    <string name="dialogpref_key">dialogpref_key</string>
+    <string name="dialogpref_default_value">default value of dialog preference</string>
+    <string name="dialogpref_summary">summary of dialog preference</string>
+    <string name="dialogpref_message">message of dialog preference</string>
+    <string name="dialogpref_sure">Sure</string>
+    <string name="dialogpref_cancel">Cancel</string>
+    <string name="pref_key">pref_key</string>
+    <string name="pref_title">title of preference</string>
+    <string name="pref_summary">summary of preference</string>
+    <string name="pref_depend_key">pref_depend_key</string>
+    <string name="pref_depend_title"> depend title of preference</string>
+    <string name="pref_depend_summary"> depend summary of preference</string>
+    <string name="android_intent_action_preference">android.intent.action.PREFERENCE</string>
+    <string name="def_pref_key">def_pref_key</string>
+    <string name="def_pref_title">default preference</string>
+    <string name="def_pref_summary">This is default preference of cts</string>
+    <string name="relative_view1">view 1</string>
+    <string name="relative_view2">view 2</string>
+    <string name="relative_view3">view 3</string>
+    <string name="relative_view4">view 4</string>
+    <string name="relative_view5">view 5</string>
+    <string name="relative_view6">view 6</string>
+    <string name="relative_view7">view 7</string>
+    <string name="relative_view8">view 8</string>
+    <string name="relative_view9">view 9</string>
+    <string name="relative_view10">view 10</string>
+    <string name="relative_view11">view 11</string>
+    <string name="relative_view12">view 12</string>
+    <string name="relative_view13">view 13</string>
+    <string name="country">Country:</string>
+    <string name="symbol">Symbol:</string>
+    <string name="country_warning">No such country registered</string>
+    <string name="version_cur">base</string>
+    <string name="version_old">base</string>
+    <string name="version_v3">base</string>
+    <string name="authenticator_label">Android CTS</string>
+    <string name="search_label">Android CTS</string>
+    <string name="tag1">tag 1</string>
+    <string name="tag2">tag 2</string>
+
+    <string name="button">Button</string>
+    <string name="holo_test">Holo Test</string>
+    <string name="holo_generator">Holo Generator</string>
+    <string name="holo_light_test">Holo Light Test</string>
+    <string name="holo_light_generator">Holo Light Generator</string>
+    <string name="reference_image">Reference Image: </string>
+    <string name="generated_image">Generated Image: </string>
+    <string name="themes_prompt">Select a Theme:</string>
+    <string name="sample_text">Sample text goes here. I wanted something creative and whimsical
+    but then I just got bored...</string>
+    <string name="long_text">This is a really long string which exceeds the width of the view.
+New devices have a much larger screen which actually enables long strings to be displayed
+with no fading. I have made this string longer to fix this case. If you are correcting this
+text, I would love to see the kind of devices you guys now use! Guys, maybe some devices need longer string!
+I think so, so how about double this string, like copy and paste!
+This is a really long string which exceeds the width of the view.
+New devices have a much larger screen which actually enables long strings to be displayed
+with no fading. I have made this string longer to fix this case. If you are correcting this
+text, I would love to see the kind of devices you guys now use! Guys, maybe some devices need longer string!
+I think so, so how about double this string, like copy and paste! </string>
+    <string name="rectangle200">"M 0,0 l 200,0 l 0, 200 l -200, 0 z"</string>
+
     <!-- Label for this package -->
     <string name="label">Contacts provider</string>
 </resources>
diff --git a/tests/src/android/provider/cts/BrowserStubActivity.java b/tests/tests/provider/src/android/provider/cts/BrowserStubActivity.java
similarity index 100%
rename from tests/src/android/provider/cts/BrowserStubActivity.java
rename to tests/tests/provider/src/android/provider/cts/BrowserStubActivity.java
diff --git a/tests/tests/provider/src/android/provider/cts/BrowserTest.java b/tests/tests/provider/src/android/provider/cts/BrowserTest.java
index 9654e43..2f0432a 100644
--- a/tests/tests/provider/src/android/provider/cts/BrowserTest.java
+++ b/tests/tests/provider/src/android/provider/cts/BrowserTest.java
@@ -28,9 +28,6 @@
 import android.provider.Browser;
 import android.provider.Browser.BookmarkColumns;
 import android.provider.Browser.SearchColumns;
-import android.provider.BrowserContract;
-import android.provider.BrowserContract.Bookmarks;
-import android.provider.BrowserContract.History;
 import android.test.ActivityInstrumentationTestCase2;
 
 import java.util.ArrayList;
@@ -39,7 +36,7 @@
 
 public class BrowserTest extends ActivityInstrumentationTestCase2<BrowserStubActivity> {
     public BrowserTest() {
-        super("com.android.cts.stub", BrowserStubActivity.class);
+        super("com.android.cts.provider", BrowserStubActivity.class);
     }
 
     private Context mContext;
@@ -73,39 +70,30 @@
         ContentResolver.setMasterSyncAutomatically(false);
 
         // backup the current contents in database
-        Cursor cursor = mProvider.query(Bookmarks.CONTENT_URI, null, null, null, null, null);
-        if (cursor.moveToFirst()) {
+        Cursor cursor = mProvider.query(Browser.BOOKMARKS_URI, null, null, null, null, null);
+        while (cursor.moveToNext()) {
             String[] colNames = cursor.getColumnNames();
-            while (!cursor.isAfterLast()) {
-                ContentValues value = new ContentValues();
+            ContentValues value = new ContentValues();
 
-                for (int i = 0; i < colNames.length; i++) {
-                    if (Bookmarks.PARENT_SOURCE_ID.equals(colNames[i])
-                            || Bookmarks.INSERT_AFTER_SOURCE_ID.equals(colNames[i])
-                            || Bookmarks.TYPE.equals(colNames[i])) {
-                        // These aren't actual columns, so skip them in the backup
-                        continue;
-                    }
-                    switch (cursor.getType(i)) {
-                    case Cursor.FIELD_TYPE_BLOB:
-                        value.put(colNames[i], cursor.getBlob(i));
-                        break;
-                    case Cursor.FIELD_TYPE_FLOAT:
-                        value.put(colNames[i], cursor.getFloat(i));
-                        break;
-                    case Cursor.FIELD_TYPE_INTEGER:
-                        value.put(colNames[i], cursor.getLong(i));
-                        break;
-                    case Cursor.FIELD_TYPE_STRING:
-                        value.put(colNames[i], cursor.getString(i));
-                        break;
-                    }
+            for (int i = 0; i < colNames.length; i++) {
+                switch (cursor.getType(i)) {
+                case Cursor.FIELD_TYPE_BLOB:
+                    value.put(colNames[i], cursor.getBlob(i));
+                    break;
+                case Cursor.FIELD_TYPE_FLOAT:
+                    value.put(colNames[i], cursor.getFloat(i));
+                    break;
+                case Cursor.FIELD_TYPE_INTEGER:
+                    value.put(colNames[i], cursor.getLong(i));
+                    break;
+                case Cursor.FIELD_TYPE_STRING:
+                    value.put(colNames[i], cursor.getString(i));
+                    break;
                 }
-                mBookmarksBackup.add(value);
-
-                cursor.moveToNext();
-            };
+            }
+            mBookmarksBackup.add(value);
         }
+
         cursor.close();
 
         cursor = mProvider.query(Browser.SEARCHES_URI, null, null, null, null, null);
@@ -123,12 +111,8 @@
         }
         cursor.close();
 
-        Uri uri = Bookmarks.CONTENT_URI.buildUpon()
-                .appendQueryParameter(BrowserContract.CALLER_IS_SYNCADAPTER, "true")
-                .build();
-        mProvider.delete(uri, null, null);
+        mProvider.delete(Browser.BOOKMARKS_URI, null, null);
         mProvider.delete(Browser.SEARCHES_URI, null, null);
-        mProvider.delete(History.CONTENT_URI, null, null);
 
         mActivity = getActivity();
     }
@@ -136,17 +120,13 @@
     @Override
     protected void tearDown() throws Exception {
         try {
-
             // clear all new contents added in test cases.
-            Uri uri = Bookmarks.CONTENT_URI.buildUpon()
-                .appendQueryParameter(BrowserContract.CALLER_IS_SYNCADAPTER, "true")
-                .build();
-            mProvider.delete(uri, null, null);
+            mProvider.delete(Browser.BOOKMARKS_URI, null, null);
             mProvider.delete(Browser.SEARCHES_URI, null, null);
 
             // recover the old backup contents
             for (ContentValues value : mBookmarksBackup) {
-                mProvider.insert(uri, value);
+                mProvider.insert(Browser.BOOKMARKS_URI, value);
             }
 
             for (ContentValues value : mSearchesBackup) {
diff --git a/tests/tests/provider/src/android/provider/cts/CalendarTest.java b/tests/tests/provider/src/android/provider/cts/CalendarTest.java
index bd8e06d..a8f547b 100644
--- a/tests/tests/provider/src/android/provider/cts/CalendarTest.java
+++ b/tests/tests/provider/src/android/provider/cts/CalendarTest.java
@@ -41,7 +41,6 @@
 import android.provider.CalendarContract.Instances;
 import android.provider.CalendarContract.Reminders;
 import android.provider.CalendarContract.SyncState;
-import android.test.InstrumentationCtsTestRunner;
 import android.test.InstrumentationTestCase;
 import android.test.suitebuilder.annotation.MediumTest;
 import android.text.TextUtils;
@@ -3706,7 +3705,8 @@
     /**
      * Special version of the test runner that does some remote Emma coverage housekeeping.
      */
-    public static class CalendarEmmaTestRunner extends InstrumentationCtsTestRunner {
+    // TODO: find if this is still used and if so convert to AndroidJUnitRunner framework
+    public static class CalendarEmmaTestRunner extends android.test.InstrumentationTestRunner {
         private static final Uri EMMA_CONTENT_URI =
             Uri.parse("content://" + CalendarContract.AUTHORITY + "/emma");
         private ContentResolver mContentResolver;
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_ContactCountsTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_ContactCountsTest.java
new file mode 100644
index 0000000..d5e5b1f
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_ContactCountsTest.java
@@ -0,0 +1,181 @@
+/*
+ * 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.provider.cts;
+
+
+import java.util.Arrays;
+
+import android.content.ContentProviderClient;
+import android.content.ContentResolver;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.RawContacts;
+import android.provider.cts.ContactsContract_TestDataBuilder.TestContact;
+import android.provider.cts.ContactsContract_TestDataBuilder.TestRawContact;
+import android.test.InstrumentationTestCase;
+
+/**
+ * CTS tests for {@link android.provider.ContactsContract.ContactCounts} apis.
+ */
+public class ContactsContract_ContactCountsTest extends InstrumentationTestCase {
+    private ContentResolver mResolver;
+    private ContactsContract_TestDataBuilder mBuilder;
+
+    final String[] TEST_PROJECTION = new String[] {Contacts.DISPLAY_NAME};
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mResolver = getInstrumentation().getTargetContext().getContentResolver();
+        ContentProviderClient provider =
+                mResolver.acquireContentProviderClient(ContactsContract.AUTHORITY);
+        mBuilder = new ContactsContract_TestDataBuilder(provider);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        mBuilder.cleanup();
+    }
+
+    public void testContactCounts_noExtraNoExtrasReturned() throws Exception {
+        final String filterString = getFilterString(setupTestData());
+        final Cursor cursor = mResolver.query(Contacts.CONTENT_URI, TEST_PROJECTION,
+                filterString, null, null);
+        try {
+            final Bundle extras = cursor.getExtras();
+            assertFalse(extras.containsKey(Contacts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS));
+            assertFalse(extras.containsKey(Contacts.EXTRA_ADDRESS_BOOK_INDEX_TITLES));
+        } finally {
+            cursor.close();
+        }
+    }
+
+    public void testContactCounts_correctCountsReturned() throws Exception {
+        final String filterString = getFilterString(setupTestData());
+        final Uri uri = Contacts.CONTENT_URI.buildUpon()
+                .appendQueryParameter(Contacts.EXTRA_ADDRESS_BOOK_INDEX, "true").build();
+        final Cursor cursor = mResolver.query(uri, TEST_PROJECTION,
+                filterString, null, null);
+        try {
+            final Bundle extras = cursor.getExtras();
+            assertTrue(extras.containsKey(Contacts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS));
+            assertTrue(extras.containsKey(Contacts.EXTRA_ADDRESS_BOOK_INDEX_TITLES));
+
+            final String[] expectedSections = new String[] {"A", "B", "C"};
+            final String sections[] =
+                    extras.getStringArray(Contacts.EXTRA_ADDRESS_BOOK_INDEX_TITLES);
+            assertTrue(Arrays.equals(expectedSections, sections));
+
+            final int[] expectedCounts = new int[] {2, 3, 1};
+            final int counts[] = extras.getIntArray(Contacts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS);
+            assertTrue(Arrays.equals(expectedCounts, counts));
+        } finally {
+            cursor.close();
+        }
+    }
+
+    private String getFilterString(long... contactIds) {
+        StringBuilder sb = new StringBuilder();
+        sb.append(Contacts._ID + " in ");
+        sb.append("(");
+        for (int i = 0; i < contactIds.length; i++) {
+            if (i != 0) sb.append(",");
+            sb.append(contactIds[i]);
+        }
+        sb.append(")");
+        return sb.toString();
+    }
+
+    /**
+     * Setup the contacts database with temporary contacts used for testing. These contacts will
+     * be removed during teardown.
+     *
+     * @return An array of long values corresponding to the ids of the created contacts
+     *
+     * @throws Exception
+     */
+    private long[] setupTestData() throws Exception {
+        TestRawContact rawContact = mBuilder.newRawContact()
+                .with(RawContacts.ACCOUNT_TYPE, "test_account")
+                .with(RawContacts.ACCOUNT_NAME, "test_name")
+                .insert();
+        rawContact.newDataRow(StructuredName.CONTENT_ITEM_TYPE)
+                .with(StructuredName.DISPLAY_NAME, "Apple Pie")
+                .insert();
+        rawContact.load();
+        TestContact contact = rawContact.getContact().load();
+
+        TestRawContact rawContact2 = mBuilder.newRawContact()
+                .with(RawContacts.ACCOUNT_TYPE, "test_account")
+                .with(RawContacts.ACCOUNT_NAME, "test_name")
+                .insert();
+        rawContact2.newDataRow(StructuredName.CONTENT_ITEM_TYPE)
+                .with(StructuredName.DISPLAY_NAME, "Banana Split")
+                .insert();
+        rawContact2.load();
+        TestContact contact2 = rawContact2.getContact().load();
+
+        TestRawContact rawContact3 = mBuilder.newRawContact()
+                .with(RawContacts.ACCOUNT_TYPE, "test_account")
+                .with(RawContacts.ACCOUNT_NAME, "test_name")
+                .insert();
+        rawContact3.newDataRow(StructuredName.CONTENT_ITEM_TYPE)
+                .with(StructuredName.DISPLAY_NAME, "Blackberry Shortcake")
+                .insert();
+        rawContact3.load();
+        TestContact contact3 = rawContact3.getContact().load();
+
+        TestRawContact rawContact4 = mBuilder.newRawContact()
+                .with(RawContacts.ACCOUNT_TYPE, "test_account")
+                .with(RawContacts.ACCOUNT_NAME, "test_name")
+                .insert();
+        rawContact4.newDataRow(StructuredName.CONTENT_ITEM_TYPE)
+                .with(StructuredName.DISPLAY_NAME, "Cherry icecream")
+                .insert();
+        rawContact4.load();
+        TestContact contact4 = rawContact4.getContact().load();
+
+        TestRawContact rawContact5 = mBuilder.newRawContact()
+                .with(RawContacts.ACCOUNT_TYPE, "test_account")
+                .with(RawContacts.ACCOUNT_NAME, "test_name")
+                .insert();
+        rawContact5.newDataRow(StructuredName.CONTENT_ITEM_TYPE)
+                .with(StructuredName.DISPLAY_NAME, "Apricot Jam ")
+                .insert();
+        rawContact5.load();
+        TestContact contact5 = rawContact5.getContact().load();
+
+        TestRawContact rawContact6 = mBuilder.newRawContact()
+                .with(RawContacts.ACCOUNT_TYPE, "test_account")
+                .with(RawContacts.ACCOUNT_NAME, "test_name")
+                .insert();
+        rawContact6.newDataRow(StructuredName.CONTENT_ITEM_TYPE)
+                .with(StructuredName.DISPLAY_NAME, "Blackcurrant Pie ")
+                .insert();
+        rawContact6.load();
+        TestContact contact6 = rawContact6.getContact().load();
+
+        return new long[] {contact.getId(), contact2.getId(), contact3.getId(), contact4.getId(),
+                contact5.getId(), contact6.getId()};
+    }
+}
+
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_DataTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_DataTest.java
index 7cfb183..91436a3 100644
--- a/tests/tests/provider/src/android/provider/cts/ContactsContract_DataTest.java
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_DataTest.java
@@ -26,10 +26,12 @@
 import android.net.Uri;
 import android.os.SystemClock;
 import android.provider.ContactsContract;
+import android.provider.ContactsContract.CommonDataKinds.Callable;
 import android.provider.ContactsContract.CommonDataKinds.Contactables;
 import android.provider.ContactsContract.CommonDataKinds.Email;
 import android.provider.ContactsContract.CommonDataKinds.Organization;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.CommonDataKinds.SipAddress;
 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
 import android.provider.ContactsContract.Contacts;
 import android.provider.ContactsContract.Data;
@@ -49,6 +51,60 @@
     private ContentResolver mResolver;
     private ContactsContract_TestDataBuilder mBuilder;
 
+    private static ContentValues[] sContentValues = new ContentValues[7];
+    static {
+        ContentValues cv1 = new ContentValues();
+        cv1.put(Contacts.DISPLAY_NAME, "Hot Tamale");
+        cv1.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
+        cv1.put(Email.DATA, "tamale@acme.com");
+        cv1.put(Email.TYPE, Email.TYPE_HOME);
+        sContentValues[0] = cv1;
+
+        ContentValues cv2 = new ContentValues();
+        cv2.put(Contacts.DISPLAY_NAME, "Hot Tamale");
+        cv2.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
+        cv2.put(Phone.DATA, "510-123-5769");
+        cv2.put(Phone.TYPE, Phone.TYPE_HOME);
+        sContentValues[1] = cv2;
+
+        ContentValues cv3 = new ContentValues();
+        cv3.put(Contacts.DISPLAY_NAME, "Hot Tamale");
+        cv3.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
+        cv3.put(Email.DATA, "hot@google.com");
+        cv3.put(Email.TYPE, Email.TYPE_WORK);
+        sContentValues[2] = cv3;
+
+        ContentValues cv4 = new ContentValues();
+        cv4.put(Contacts.DISPLAY_NAME, "Cold Tamago");
+        cv4.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
+        cv4.put(Email.DATA, "eggs@farmers.org");
+        cv4.put(Email.TYPE, Email.TYPE_HOME);
+        sContentValues[3] = cv4;
+
+        ContentValues cv5 = new ContentValues();
+        cv5.put(Contacts.DISPLAY_NAME, "John Doe");
+        cv5.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
+        cv5.put(Email.DATA, "doeassociates@deer.com");
+        cv5.put(Email.TYPE, Email.TYPE_WORK);
+        sContentValues[4] = cv5;
+
+        ContentValues cv6 = new ContentValues();
+        cv6.put(Contacts.DISPLAY_NAME, "John Doe");
+        cv6.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
+        cv6.put(Phone.DATA, "518-354-1111");
+        cv6.put(Phone.TYPE, Phone.TYPE_HOME);
+        sContentValues[5] = cv6;
+
+        ContentValues cv7 = new ContentValues();
+        cv7.put(Contacts.DISPLAY_NAME, "Cold Tamago");
+        cv7.put(Data.MIMETYPE, SipAddress.CONTENT_ITEM_TYPE);
+        cv7.put(SipAddress.DATA, "mysip@sipaddress.com");
+        cv7.put(SipAddress.TYPE, SipAddress.TYPE_HOME);
+        sContentValues[6] = cv7;
+    }
+
+    private TestRawContact[] mRawContacts = new TestRawContact[3];
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -135,7 +191,7 @@
             // Contactables Uri should return only email and phone data items.
             DatabaseAsserts.assertStoredValuesInUriMatchExactly(mResolver, contentUri, null,
                     Data.RAW_CONTACT_ID + "=?", new String[] {String.valueOf(rawContact.getId())},
-                    null, cv, cv2);
+                    null, false, cv, cv2);
         } finally {
             // Clean up
             rawContact.delete();
@@ -182,6 +238,37 @@
         assertCursorStoredValuesWithRawContactsFilter(filterUri, ids, new ContentValues[0]);
     }
 
+    /**
+     * Verifies that Callable.CONTENT_URI returns only data items that can be called (i.e.
+     * phone numbers and sip addresses)
+     */
+    public void testCallableUri_returnsCorrectDataRows() throws Exception {
+        long[] ids = setupContactablesTestData();
+        Uri uri = Callable.CONTENT_URI;
+        assertCursorStoredValuesWithRawContactsFilter(uri, ids, sContentValues[1],
+                sContentValues[5], sContentValues[6]);
+    }
+
+    public void testCallableFilterByNameOrOrganization_returnsCorrectDataRows() throws Exception {
+        long[] ids = setupContactablesTestData();
+        Uri uri = Uri.withAppendedPath(Callable.CONTENT_FILTER_URI, "doe");
+        // Only callables belonging to John Doe (name) and Cold Tamago (organization) are returned.
+        assertCursorStoredValuesWithRawContactsFilter(uri, ids, sContentValues[5],
+                sContentValues[6]);
+    }
+
+    public void testCallableFilterByNumber_returnsCorrectDataRows() throws Exception {
+        long[] ids = setupContactablesTestData();
+        Uri uri = Uri.withAppendedPath(Callable.CONTENT_FILTER_URI, "510");
+        assertCursorStoredValuesWithRawContactsFilter(uri, ids, sContentValues[1]);
+    }
+
+    public void testCallableFilterBySipAddress_returnsCorrectDataRows() throws Exception {
+        long[] ids = setupContactablesTestData();
+        Uri uri = Uri.withAppendedPath(Callable.CONTENT_FILTER_URI, "mysip");
+        assertCursorStoredValuesWithRawContactsFilter(uri, ids, sContentValues[6]);
+    }
+
     public void testDataInsert_updatesContactLastUpdatedTimestamp() {
         DatabaseAsserts.ContactIdPair ids = DatabaseAsserts.assertAndCreateContact(mResolver);
         long baseTime = ContactUtil.queryContactLastUpdatedTimestamp(mResolver, ids.mContactId);
@@ -213,6 +300,70 @@
         RawContactUtil.delete(mResolver, ids.mRawContactId, true);
     }
 
+    /**
+     * Tests that specifying the {@link android.provider.ContactsContract#REMOVE_DUPLICATE_ENTRIES}
+     * boolean parameter correctly results in deduped phone numbers.
+     */
+    public void testPhoneQuery_removeDuplicateEntries() throws Exception{
+        long[] ids = setupContactablesTestData();
+
+        // Insert duplicate data entry for raw contact 3. (existing phone number 518-354-1111)
+        mRawContacts[2].newDataRow(Phone.CONTENT_ITEM_TYPE)
+                .with(Phone.DATA, "518-354-1111")
+                .with(Phone.TYPE, Phone.TYPE_HOME)
+                .insert();
+
+        ContentValues dupe = new ContentValues();
+        dupe.put(Contacts.DISPLAY_NAME, "John Doe");
+        dupe.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
+        dupe.put(Phone.DATA, "518-354-1111");
+        dupe.put(Phone.TYPE, Phone.TYPE_HOME);
+
+        // Query for all phone numbers in the contacts database (without deduping).
+        // The phone number above should be listed twice, in its duplicated forms.
+        assertCursorStoredValuesWithRawContactsFilter(Phone.CONTENT_URI, ids, sContentValues[1],
+                sContentValues[5], dupe);
+
+        // Now query for all phone numbers in the contacts database but request deduping.
+        // The phone number should now be listed only once.
+        Uri uri = Phone.CONTENT_URI.buildUpon().
+                appendQueryParameter(ContactsContract.REMOVE_DUPLICATE_ENTRIES, "true").build();
+        assertCursorStoredValuesWithRawContactsFilter(uri, ids, sContentValues[1],
+                sContentValues[5]);
+    }
+
+    /**
+     * Tests that specifying the {@link android.provider.ContactsContract#REMOVE_DUPLICATE_ENTRIES}
+     * boolean parameter correctly results in deduped email addresses.
+     */
+    public void testEmailQuery_removeDuplicateEntries() throws Exception{
+        long[] ids = setupContactablesTestData();
+
+        // Insert duplicate data entry for raw contact 3. (existing email doeassociates@deer.com)
+        mRawContacts[2].newDataRow(Email.CONTENT_ITEM_TYPE)
+                .with(Email.DATA, "doeassociates@deer.com")
+                .with(Email.TYPE, Email.TYPE_WORK)
+                .insert();
+
+        ContentValues dupe = new ContentValues();
+        dupe.put(Contacts.DISPLAY_NAME, "John Doe");
+        dupe.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
+        dupe.put(Email.DATA, "doeassociates@deer.com");
+        dupe.put(Email.TYPE, Email.TYPE_WORK);
+
+        // Query for all email addresses in the contacts database (without deduping).
+        // The email address above should be listed twice, in its duplicated forms.
+        assertCursorStoredValuesWithRawContactsFilter(Email.CONTENT_URI, ids, sContentValues[0],
+                sContentValues[2], sContentValues[3], sContentValues[4], dupe);
+
+        // Now query for all email addresses in the contacts database but request deduping.
+        // The email address should now be listed only once.
+        Uri uri = Email.CONTENT_URI.buildUpon().
+                appendQueryParameter(ContactsContract.REMOVE_DUPLICATE_ENTRIES, "true").build();
+        assertCursorStoredValuesWithRawContactsFilter(uri, ids, sContentValues[0],
+                sContentValues[2], sContentValues[3], sContentValues[4]);
+    }
+
     public void testDataUpdate_updatesContactLastUpdatedTimestamp() {
         DatabaseAsserts.ContactIdPair ids = DatabaseAsserts.assertAndCreateContact(mResolver);
         long dataId = createData(ids.mRawContactId);
@@ -253,7 +404,7 @@
         }
         sb.append(")");
         DatabaseAsserts.assertStoredValuesInUriMatchExactly(mResolver, uri, null, sb.toString(),
-                null, null, expected);
+                null, null, false, expected);
     }
 
 
@@ -277,6 +428,7 @@
                 .with(Phone.DATA, "510-123-5769")
                 .with(Email.TYPE, Phone.TYPE_HOME)
                 .insert();
+        mRawContacts[0] = rawContact;
 
         TestRawContact rawContact2 = mBuilder.newRawContact()
                 .with(RawContacts.ACCOUNT_TYPE, "test_account")
@@ -289,6 +441,14 @@
                 .with(Email.DATA, "eggs@farmers.org")
                 .with(Email.TYPE, Email.TYPE_HOME)
                 .insert();
+        rawContact2.newDataRow(SipAddress.CONTENT_ITEM_TYPE)
+                .with(SipAddress.DATA, "mysip@sipaddress.com")
+                .with(SipAddress.TYPE, SipAddress.TYPE_HOME)
+                .insert();
+        rawContact2.newDataRow(Organization.CONTENT_ITEM_TYPE)
+                .with(Organization.COMPANY, "Doe Corp")
+                .insert();
+        mRawContacts[1] = rawContact2;
 
         TestRawContact rawContact3 = mBuilder.newRawContact()
                 .with(RawContacts.ACCOUNT_TYPE, "test_account")
@@ -308,55 +468,12 @@
         rawContact3.newDataRow(Organization.CONTENT_ITEM_TYPE)
                 .with(Organization.DATA, "Doe Industries")
                 .insert();
+        mRawContacts[2] = rawContact3;
         return new long[] {rawContact.getId(), rawContact2.getId(), rawContact3.getId()};
     }
 
     // Provides functionality to set up content values for the Contactables tests
     private static class ContactablesTestHelper {
-        private static ContentValues[] sContentValues = new ContentValues[6];
-        static {
-            ContentValues cv1 = new ContentValues();
-            cv1.put(Contacts.DISPLAY_NAME, "Hot Tamale");
-            cv1.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
-            cv1.put(Email.DATA, "tamale@acme.com");
-            cv1.put(Email.TYPE, Email.TYPE_HOME);
-            sContentValues[0] = cv1;
-
-            ContentValues cv2 = new ContentValues();
-            cv2.put(Contacts.DISPLAY_NAME, "Hot Tamale");
-            cv2.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
-            cv2.put(Phone.DATA, "510-123-5769");
-            cv2.put(Phone.TYPE, Phone.TYPE_HOME);
-            sContentValues[1] = cv2;
-
-            ContentValues cv3 = new ContentValues();
-            cv3.put(Contacts.DISPLAY_NAME, "Hot Tamale");
-            cv3.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
-            cv3.put(Email.DATA, "hot@google.com");
-            cv3.put(Email.TYPE, Email.TYPE_WORK);
-            sContentValues[2] = cv3;
-
-            ContentValues cv4 = new ContentValues();
-            cv4.put(Contacts.DISPLAY_NAME, "Cold Tamago");
-            cv4.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
-            cv4.put(Email.DATA, "eggs@farmers.org");
-            cv4.put(Email.TYPE, Email.TYPE_HOME);
-            sContentValues[3] = cv4;
-
-            ContentValues cv5 = new ContentValues();
-            cv5.put(Contacts.DISPLAY_NAME, "John Doe");
-            cv5.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
-            cv5.put(Email.DATA, "doeassociates@deer.com");
-            cv5.put(Email.TYPE, Email.TYPE_WORK);
-            sContentValues[4] = cv5;
-
-            ContentValues cv6 = new ContentValues();
-            cv6.put(Contacts.DISPLAY_NAME, "John Doe");
-            cv6.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
-            cv6.put(Phone.DATA, "518-354-1111");
-            cv6.put(Phone.TYPE, Phone.TYPE_HOME);
-            sContentValues[5] = cv6;
-        }
 
         /**
          * @return An arraylist of contentValues that correspond to the provided raw contacts
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_FrequentsStrequentsTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_FrequentsStrequentsTest.java
new file mode 100644
index 0000000..fcb48cf
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_FrequentsStrequentsTest.java
@@ -0,0 +1,352 @@
+/*
+ * Copyright (C) 2013 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.provider.cts;
+
+
+import android.content.ContentProviderClient;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.net.Uri;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.CommonDataKinds.Contactables;
+import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.CommonDataKinds.Organization;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.DataUsageFeedback;
+import android.provider.ContactsContract.RawContacts;
+import android.provider.cts.ContactsContract_TestDataBuilder.TestContact;
+import android.provider.cts.ContactsContract_TestDataBuilder.TestRawContact;
+import android.provider.cts.contacts.DatabaseAsserts;
+import android.test.InstrumentationTestCase;
+
+import java.util.ArrayList;
+
+/**
+ * CTS tests for {@link android.provider.ContactsContract.Contacts#CONTENT_FREQUENT_URI},
+ * {@link android.provider.ContactsContract.Contacts#CONTENT_STREQUENT_URI} and
+ * {@link android.provider.ContactsContract.Contacts#CONTENT_STREQUENT_FILTER_URI} apis.
+ */
+public class ContactsContract_FrequentsStrequentsTest extends InstrumentationTestCase {
+    private ContentResolver mResolver;
+    private ContactsContract_TestDataBuilder mBuilder;
+
+    public static ContentValues[] sContentValues = new ContentValues[3];
+    static {
+        ContentValues cv1 = new ContentValues();
+        cv1.put(Contacts.DISPLAY_NAME, "Hot Tamale");
+        sContentValues[0] = cv1;
+
+        ContentValues cv2 = new ContentValues();
+        cv2.put(Contacts.DISPLAY_NAME, "Cold Tamago");
+        sContentValues[1] = cv2;
+
+        ContentValues cv3 = new ContentValues();
+        cv3.put(Contacts.DISPLAY_NAME, "John Doe");
+        sContentValues[2] = cv3;
+    }
+
+    private long[] mDataIds = new long[3];
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mResolver = getInstrumentation().getTargetContext().getContentResolver();
+        ContentProviderClient provider =
+                mResolver.acquireContentProviderClient(ContactsContract.AUTHORITY);
+        mBuilder = new ContactsContract_TestDataBuilder(provider);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        mBuilder.cleanup();
+    }
+
+    /**
+     * Tests that {@link android.provider.ContactsContract.Contacts#CONTENT_STREQUENT_URI} returns
+     * no contacts if there are no starred or frequent contacts in the user's contacts.
+     */
+    public void testStrequents_noStarredOrFrequents() throws Exception {
+        long[] ids = setupTestData();
+        assertCursorStoredValuesWithContactsFilter(Contacts.CONTENT_STREQUENT_URI, ids, false);
+    }
+
+    /**
+     * Tests that {@link android.provider.ContactsContract.Contacts#CONTENT_STREQUENT_URI} returns
+     * starred contacts in the correct order if there are only starred contacts in the user's
+     * contacts.
+     */
+    public void testStrequents_starredOnlyInCorrectOrder() throws Exception {
+        long[] ids = setupTestData();
+
+        // Star/favorite the first and third contact.
+        starContact(ids[0]);
+        starContact(ids[1]);
+
+        // Only the starred contacts should be returned, ordered alphabetically by name
+        assertCursorStoredValuesWithContactsFilter(Contacts.CONTENT_STREQUENT_URI, ids,
+                false, sContentValues[1], sContentValues[0]);
+    }
+
+    /**
+     * Tests that {@link android.provider.ContactsContract.Contacts#CONTENT_STREQUENT_URI} returns
+     * frequent contacts in the correct order if there are only frequent contacts in the user's
+     * contacts.
+     */
+    public void testStrequents_frequentsOnlyInCorrectOrder() throws Exception {
+        long[] ids = setupTestData();
+
+        // Contact the first contact once.
+        markDataAsUsed(mDataIds[0], 1);
+
+        // Contact the second contact thrice.
+        markDataAsUsed(mDataIds[1], 3);
+
+        // Contact the third contact twice.
+        markDataAsUsed(mDataIds[2], 2);
+
+        // The strequents uri should now return contact 2, 3, 1 in order due to ranking by
+        // data usage.
+        assertCursorStoredValuesWithContactsFilter(Contacts.CONTENT_STREQUENT_URI, ids,
+                false, sContentValues[1], sContentValues[2], sContentValues[0]);
+    }
+
+    /**
+     * Tests that {@link android.provider.ContactsContract.Contacts#CONTENT_STREQUENT_URI} returns
+     * first starred, then frequent contacts in their respective correct orders if there are both
+     * starred and frequent contacts in the user's contacts.
+     */
+    public void testStrequents_starredAndFrequentsInCorrectOrder() throws Exception {
+        long[] ids = setupTestData();
+
+        // Contact the first contact once.
+        markDataAsUsed(mDataIds[0], 1);
+
+        // Contact the second contact thrice.
+        markDataAsUsed(mDataIds[1], 3);
+
+        // Contact the third contact twice, and mark it as used
+        markDataAsUsed(mDataIds[2], 2);
+        starContact(ids[2]);
+
+        // The strequents uri should now return contact 3, 2, 1 in order. Contact 3 is ranked first
+        // because it is starred, followed by contacts 2 and 1 due to their data usage ranking.
+        // Note that contact 3 is only returned once (as a starred contact) even though it is also
+        // a frequently contacted contact.
+        assertCursorStoredValuesWithContactsFilter(Contacts.CONTENT_STREQUENT_URI, ids,
+                false, sContentValues[2], sContentValues[1], sContentValues[0]);
+    }
+
+    /**
+     * Tests that {@link android.provider.ContactsContract.Contacts#CONTENT_STREQUENT_FILTER_URI}
+     * correctly filters the returned contacts with the given user input.
+     */
+    public void testStrequents_withFilter() throws Exception {
+        long[] ids = setupTestData();
+
+        //Star all 3 contacts
+        starContact(ids[0]);
+        starContact(ids[1]);
+        starContact(ids[2]);
+
+        // Construct a uri that filters for the query string "ta".
+        Uri uri = Contacts.CONTENT_STREQUENT_FILTER_URI.buildUpon().appendEncodedPath("ta").build();
+
+        // Only contact 1 and 2 should be returned (sorted in alphabetical order) due to the
+        // filtered query.
+        assertCursorStoredValuesWithContactsFilter(uri, ids, false, sContentValues[1], sContentValues[0]);
+    }
+
+    public void testStrequents_phoneOnly() throws Exception {
+        long[] ids = setupTestData();
+
+        // Star all 3 contacts
+        starContact(ids[0]);
+        starContact(ids[1]);
+        starContact(ids[2]);
+
+        // Construct a uri for phone only favorites.
+        Uri uri = Contacts.CONTENT_STREQUENT_URI.buildUpon().
+                appendQueryParameter(ContactsContract.STREQUENT_PHONE_ONLY, "true").build();
+
+        // Only the contacts with phone numbers are returned, in alphabetical order. Filtering
+        // is done with data ids instead of contact ids since each row contains a single data item.
+        assertCursorStoredValuesWithContactsFilter(uri, mDataIds, false,
+                sContentValues[0], sContentValues[2]);
+    }
+
+    public void testStrequents_phoneOnlyFrequentsOrder() throws Exception {
+        long[] ids = setupTestData();
+
+        // Contact the first contact once.
+        markDataAsUsed(mDataIds[0], 1);
+
+        // Contact the second contact twice.
+        markDataAsUsed(mDataIds[1], 2);
+
+        // Contact the third contact thrice.
+        markDataAsUsed(mDataIds[2], 3);
+
+        // Construct a uri for phone only favorites.
+        Uri uri = Contacts.CONTENT_STREQUENT_URI.buildUpon().
+                appendQueryParameter(ContactsContract.STREQUENT_PHONE_ONLY, "true").build();
+
+        // Only the contacts with phone numbers are returned, in frequency ranking order.
+        assertCursorStoredValuesWithContactsFilter(uri, mDataIds, false,
+                sContentValues[2], sContentValues[0]);
+    }
+
+    public void testFrequents_noFrequentsReturnsEmptyCursor() throws Exception {
+        long[] ids = setupTestData();
+        assertCursorStoredValuesWithContactsFilter(Contacts.CONTENT_FREQUENT_URI, ids, false);
+    }
+
+    public void testFrequents_CorrectOrder() throws Exception {
+        long[] ids = setupTestData();
+
+        // Contact the first contact once.
+        markDataAsUsed(mDataIds[0], 1);
+
+        // Contact the second contact thrice.
+        markDataAsUsed(mDataIds[1], 3);
+
+        // Contact the third contact twice.
+        markDataAsUsed(mDataIds[2], 2);
+
+        // The frequents uri should now return contact 2, 3, 1 in order due to ranking by
+        // data usage.
+        assertCursorStoredValuesWithContactsFilter(Contacts.CONTENT_FREQUENT_URI, ids,
+                true /* inOrder */, sContentValues[1], sContentValues[2], sContentValues[0]);
+    }
+
+    /**
+     * Given a uri, performs a query on the contacts provider for that uri and asserts that the
+     * cursor returned from the query matches the expected results.
+     *
+     * @param uri Uri to perform the query for
+     * @param contactsId Array of contact IDs that serves as an additional filter on the result
+     * set. This is needed to limit the output to temporary test contacts that were created for
+     * purposes of the test, so that the tests do not fail on devices with existing contacts on
+     * them
+     * @param inOrder Whether or not the returned rows in the cursor should correspond to the
+     * order of the provided ContentValues
+     * @param expected An array of ContentValues corresponding to the expected output of the query
+     */
+    private void assertCursorStoredValuesWithContactsFilter(Uri uri, long[] contactsId,
+            boolean inOrder, ContentValues... expected) {
+        // We need this helper function to add a filter for specific contacts because
+        // otherwise tests will fail if performed on a device with existing contacts data
+        StringBuilder sb = new StringBuilder();
+        sb.append(Contacts._ID + " in ");
+        sb.append("(");
+        for (int i = 0; i < contactsId.length; i++) {
+            if (i != 0) sb.append(",");
+            sb.append(contactsId[i]);
+        }
+        sb.append(")");
+        DatabaseAsserts.assertStoredValuesInUriMatchExactly(mResolver, uri, null, sb.toString(),
+                null, null, inOrder, expected);
+    }
+
+    /**
+     * Given a contact id, update the contact corresponding to that contactId so that it now shows
+     * up in the user's favorites/starred contacts.
+     *
+     * @param contactId Contact ID corresponding to the contact to star
+     */
+    private void starContact(long contactId) {
+        ContentValues values = new ContentValues();
+        values.put(Contacts.STARRED, 1);
+        mResolver.update(ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), values,
+                null, null);
+    }
+
+    /**
+     * Given a data id, increment the data usage stats by a given number of usages to simulate
+     * the user making a call to the given data item.
+     *
+     * @param dataId Id of the data item to increment data usage stats for
+     * @param numTimes The number of times to increase the data usage stats by
+     */
+    private void markDataAsUsed(long dataId, int numTimes) {
+        Uri uri = ContactsContract.DataUsageFeedback.FEEDBACK_URI.buildUpon().
+                appendPath(String.valueOf(dataId)).
+                appendQueryParameter(DataUsageFeedback.USAGE_TYPE,
+                        DataUsageFeedback.USAGE_TYPE_CALL).build();
+        for (int i = 1; i <= numTimes; i++) {
+            mResolver.update(uri, new ContentValues(), null, null);
+        }
+    }
+
+    /**
+     * Setup the contacts database with temporary contacts used for testing. These contacts will
+     * be removed during teardown.
+     *
+     * @return An array of long values corresponding to the ids of the created contacts
+     *
+     * @throws Exception
+     */
+    private long[] setupTestData() throws Exception {
+        TestRawContact rawContact = mBuilder.newRawContact()
+                .with(RawContacts.ACCOUNT_TYPE, "test_account")
+                .with(RawContacts.ACCOUNT_NAME, "test_name")
+                .insert();
+        rawContact.newDataRow(StructuredName.CONTENT_ITEM_TYPE)
+                .with(StructuredName.DISPLAY_NAME, "Hot Tamale")
+                .insert();
+        mDataIds[0] = rawContact.newDataRow(Phone.CONTENT_ITEM_TYPE)
+                .with(Phone.DATA, "510-123-5769")
+                .with(Email.TYPE, Phone.TYPE_HOME)
+                .insert().load().getId();
+        rawContact.load();
+        TestContact contact = rawContact.getContact().load();
+
+        TestRawContact rawContact2 = mBuilder.newRawContact()
+                .with(RawContacts.ACCOUNT_TYPE, "test_account")
+                .with(RawContacts.ACCOUNT_NAME, "test_name")
+                .insert();
+        rawContact2.newDataRow(StructuredName.CONTENT_ITEM_TYPE)
+                .with(StructuredName.DISPLAY_NAME, "Cold Tamago")
+                .insert();
+        mDataIds[1] = rawContact2.newDataRow(Email.CONTENT_ITEM_TYPE)
+                .with(Email.DATA, "eggs@farmers.org")
+                .with(Email.TYPE, Email.TYPE_HOME)
+                .insert().load().getId();
+        rawContact2.load();
+        TestContact contact2 = rawContact2.getContact().load();
+
+        TestRawContact rawContact3 = mBuilder.newRawContact()
+                .with(RawContacts.ACCOUNT_TYPE, "test_account")
+                .with(RawContacts.ACCOUNT_NAME, "test_name")
+                .insert();
+        rawContact3.newDataRow(StructuredName.CONTENT_ITEM_TYPE)
+                .with(StructuredName.DISPLAY_NAME, "John Doe")
+                .insert();
+        mDataIds[2] = rawContact3.newDataRow(Phone.CONTENT_ITEM_TYPE)
+                .with(Phone.DATA, "518-354-1111")
+                .with(Phone.TYPE, Phone.TYPE_HOME)
+                .insert().load().getId();
+        rawContact3.load();
+        TestContact contact3 = rawContact3.getContact().load();
+
+        return new long[] {contact.getId(), contact2.getId(), contact3.getId()};
+    }
+}
+
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_PhoneLookup.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_PhoneLookup.java
new file mode 100644
index 0000000..434ac201
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_PhoneLookup.java
@@ -0,0 +1,195 @@
+/*
+ * 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.provider.cts;
+
+import android.content.ContentProviderClient;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.net.Uri;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.PhoneLookup;
+import android.provider.ContactsContract.RawContacts;
+import android.provider.cts.ContactsContract_TestDataBuilder.TestContact;
+import android.provider.cts.ContactsContract_TestDataBuilder.TestRawContact;
+import android.provider.cts.contacts.DatabaseAsserts;
+import android.test.AndroidTestCase;
+
+/**
+ * Test for {@link android.provider.ContactsContract.PhoneLookup}.
+ * <p>
+ * This covers {@link PhoneLookup#CONTENT_FILTER_URI} and
+ * {@link PhoneLookup#ENTERPRISE_CONTENT_FILTER_URI}.
+ *
+ * TODO We don't yet have tests to cover cross-user provider access for the later, since multi-user
+ * cases aren't well supported in CTS yet.  Tracking in internal bug/16462089 .
+ */
+public class ContactsContract_PhoneLookup extends AndroidTestCase {
+    private ContentResolver mResolver;
+    private ContactsContract_TestDataBuilder mBuilder;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mResolver = getContext().getContentResolver();
+        ContentProviderClient provider =
+                mResolver.acquireContentProviderClient(ContactsContract.AUTHORITY);
+        mBuilder = new ContactsContract_TestDataBuilder(provider);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        mBuilder.cleanup();
+    }
+
+    private long[] setupTestData() throws Exception {
+        TestRawContact rawContact = mBuilder.newRawContact()
+                .with(RawContacts.ACCOUNT_TYPE, "test_account")
+                .with(RawContacts.ACCOUNT_NAME, "test_name")
+                .insert();
+        rawContact.newDataRow(StructuredName.CONTENT_ITEM_TYPE)
+                .with(StructuredName.DISPLAY_NAME, "Hot Tamale")
+                .insert();
+        rawContact.newDataRow(Phone.CONTENT_ITEM_TYPE)
+                .with(Phone.DATA, "1111222333444")
+                .with(Email.TYPE, Phone.TYPE_HOME)
+                .insert().load().getId();
+        rawContact.load();
+        TestContact contact = rawContact.getContact().load();
+
+        TestRawContact rawContact2 = mBuilder.newRawContact()
+                .with(RawContacts.ACCOUNT_TYPE, "test_account")
+                .with(RawContacts.ACCOUNT_NAME, "test_name")
+                .insert();
+        rawContact2.newDataRow(StructuredName.CONTENT_ITEM_TYPE)
+                .with(StructuredName.DISPLAY_NAME, "Cold Tamago")
+                .insert();
+        rawContact2.newDataRow(Phone.CONTENT_ITEM_TYPE)
+                .with(Phone.DATA, "2111222333444")
+                .with(Phone.TYPE, Phone.TYPE_OTHER)
+                .insert().load();
+
+        rawContact2.load();
+        TestContact contact2 = rawContact2.getContact().load();
+
+        return new long[] {
+                contact.getId(), contact2.getId()
+        };
+    }
+
+    /**
+     * Test for {@link android.provider.ContactsContract.PhoneLookup#CONTENT_FILTER_URI}.
+     */
+    public void testPhoneLookup_nomatch() throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = PhoneLookup.CONTENT_FILTER_URI.buildUpon()
+                .appendPath("no-such-phone-number").build();
+
+        assertCursorStoredValuesWithContactsFilter(uri, ids /*, empty */);
+    }
+
+    /**
+     * Test for {@link android.provider.ContactsContract.PhoneLookup#CONTENT_FILTER_URI}.
+     */
+    public void testPhoneLookup_found1() throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = PhoneLookup.CONTENT_FILTER_URI.buildUpon()
+                .appendPath("1111222333444").build();
+
+        final ContentValues expected = new ContentValues();
+        expected.put(PhoneLookup._ID, ids[0]);
+        expected.put(PhoneLookup.NUMBER, "1111222333444");
+
+        assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+    }
+
+    /**
+     * Test for {@link android.provider.ContactsContract.PhoneLookup#CONTENT_FILTER_URI}.
+     */
+    public void testPhoneLookup_found2() throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = PhoneLookup.CONTENT_FILTER_URI.buildUpon()
+                .appendPath("2111222333444").build();
+
+        final ContentValues expected = new ContentValues();
+        expected.put(PhoneLookup._ID, ids[1]);
+        expected.put(PhoneLookup.NUMBER, "2111222333444");
+
+        assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+    }
+
+    /**
+     * Test for {@link android.provider.ContactsContract.PhoneLookup#ENTERPRISE_CONTENT_FILTER_URI}.
+     */
+    public void testPhoneLookupEnterprise_nomatch() throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+                .appendPath("no-such-phone-number").build();
+
+        assertCursorStoredValuesWithContactsFilter(uri, ids /*, empty */);
+    }
+
+    /**
+     * Test for {@link android.provider.ContactsContract.PhoneLookup#ENTERPRISE_CONTENT_FILTER_URI}.
+     */
+    public void testPhoneLookupEnterprise_found1() throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+                .appendPath("1111222333444").build();
+
+        final ContentValues expected = new ContentValues();
+        expected.put(PhoneLookup._ID, ids[0]);
+        expected.put(PhoneLookup.NUMBER, "1111222333444");
+
+        assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+    }
+
+    /**
+     * Test for {@link android.provider.ContactsContract.PhoneLookup#ENTERPRISE_CONTENT_FILTER_URI}.
+     */
+    public void testPhoneLookupEnterprise_found2() throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI.buildUpon()
+                .appendPath("2111222333444").build();
+
+        final ContentValues expected = new ContentValues();
+        expected.put(PhoneLookup._ID, ids[1]);
+        expected.put(PhoneLookup.NUMBER, "2111222333444");
+
+        assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+    }
+
+    private void assertCursorStoredValuesWithContactsFilter(Uri uri, long[] contactsId,
+            ContentValues... expected) {
+        // We need this helper function to add a filter for specific contacts because
+        // otherwise tests will fail if performed on a device with existing contacts data
+        StringBuilder sb = new StringBuilder();
+        sb.append(Contacts._ID + " in ");
+        sb.append("(");
+        for (int i = 0; i < contactsId.length; i++) {
+            if (i != 0) sb.append(",");
+            sb.append(contactsId[i]);
+        }
+        sb.append(")");
+        DatabaseAsserts.assertStoredValuesInUriMatchExactly(mResolver, uri, null,
+                sb.toString(), null, null, false, expected);
+    }
+}
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_PhotoTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_PhotoTest.java
index fbd092f..8c97c22 100644
--- a/tests/tests/provider/src/android/provider/cts/ContactsContract_PhotoTest.java
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_PhotoTest.java
@@ -19,7 +19,7 @@
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
 import android.content.Context;
-import android.os.cts.FileUtils;
+import android.cts.util.FileUtils;
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.CommonDataKinds.Photo;
 import android.provider.ContactsContract.Contacts;
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_PinnedPositionsTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_PinnedPositionsTest.java
new file mode 100644
index 0000000..2558c36
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_PinnedPositionsTest.java
@@ -0,0 +1,407 @@
+/*
+ * Copyright (C) 2013 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.provider.cts;
+
+import static android.provider.cts.contacts.ContactUtil.newContentValues;
+
+import android.content.ContentProviderOperation;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.OperationApplicationException;
+import android.net.Uri;
+import android.os.RemoteException;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.AggregationExceptions;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.PinnedPositions;
+import android.provider.ContactsContract.RawContacts;
+import android.provider.cts.contacts.CommonDatabaseUtils;
+import android.provider.cts.contacts.ContactUtil;
+import android.provider.cts.contacts.DatabaseAsserts;
+import android.provider.cts.contacts.RawContactUtil;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import java.util.ArrayList;
+
+/**
+ * CTS tests for {@link android.provider.ContactsContract.PinnedPositions} API
+ */
+public class ContactsContract_PinnedPositionsTest extends AndroidTestCase {
+    private static final String TAG = "ContactsContract_PinnedPositionsTest";
+
+    private ContentResolver mResolver;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mResolver = getContext().getContentResolver();
+    }
+
+    /**
+     * Tests that the ContactsProvider automatically stars/unstars a pinned/unpinned contact if
+     * {@link PinnedPositions#STAR_WHEN_PINNING} boolean parameter is set to true, and that the
+     * values are correctly propogated to the contact's constituent raw contacts.
+     */
+    public void testPinnedPositionsUpdate() {
+        final DatabaseAsserts.ContactIdPair i1 = DatabaseAsserts.assertAndCreateContact(mResolver);
+        final DatabaseAsserts.ContactIdPair i2 = DatabaseAsserts.assertAndCreateContact(mResolver);
+        final DatabaseAsserts.ContactIdPair i3 = DatabaseAsserts.assertAndCreateContact(mResolver);
+        final DatabaseAsserts.ContactIdPair i4 = DatabaseAsserts.assertAndCreateContact(mResolver);
+
+        final int unpinned = PinnedPositions.UNPINNED;
+
+        assertValuesForContact(i1.mContactId,
+                newContentValues(Contacts.PINNED, unpinned, Contacts.STARRED, 0));
+        assertValuesForContact(i2.mContactId,
+                newContentValues(Contacts.PINNED, unpinned, Contacts.STARRED, 0));
+        assertValuesForContact(i3.mContactId,
+                newContentValues(Contacts.PINNED, unpinned, Contacts.STARRED, 0));
+        assertValuesForContact(i4.mContactId,
+                newContentValues(Contacts.PINNED, unpinned, Contacts.STARRED, 0));
+
+        assertValuesForRawContact(i1.mRawContactId, newContentValues(RawContacts.PINNED, unpinned));
+        assertValuesForRawContact(i2.mRawContactId, newContentValues(RawContacts.PINNED, unpinned));
+        assertValuesForRawContact(i3.mRawContactId, newContentValues(RawContacts.PINNED, unpinned));
+        assertValuesForRawContact(i4.mRawContactId, newContentValues(RawContacts.PINNED, unpinned));
+
+        final ArrayList<ContentProviderOperation> operations =
+                new ArrayList<ContentProviderOperation>();
+        operations.add(newPinningOperation(i1.mContactId, 1, true));
+        operations.add(newPinningOperation(i3.mContactId, 3, true));
+        operations.add(newPinningOperation(i4.mContactId, 2, false));
+        applyBatch(mResolver, operations);
+
+        assertValuesForContact(i1.mContactId,
+                newContentValues(Contacts.PINNED, 1, Contacts.STARRED, 1));
+        assertValuesForContact(i2.mContactId,
+                newContentValues(Contacts.PINNED, unpinned, Contacts.STARRED, 0));
+        assertValuesForContact(i3.mContactId,
+                newContentValues(Contacts.PINNED, 3, Contacts.STARRED, 1));
+        assertValuesForContact(i4.mContactId,
+                newContentValues(Contacts.PINNED, 2, Contacts.STARRED, 0));
+
+        // Make sure the values are propagated to raw contacts.
+        assertValuesForRawContact(i1.mRawContactId, newContentValues(RawContacts.PINNED, 1));
+        assertValuesForRawContact(i2.mRawContactId, newContentValues(RawContacts.PINNED, unpinned));
+        assertValuesForRawContact(i3.mRawContactId, newContentValues(RawContacts.PINNED, 3));
+        assertValuesForRawContact(i4.mRawContactId, newContentValues(RawContacts.PINNED, 2));
+
+        operations.clear();
+
+        // Now unpin the contact
+        operations.add(newPinningOperation(i3.mContactId, unpinned, false));
+        applyBatch(mResolver, operations);
+
+        assertValuesForContact(i1.mContactId,
+                newContentValues(Contacts.PINNED, 1, Contacts.STARRED, 1));
+        assertValuesForContact(i2.mContactId,
+                newContentValues(Contacts.PINNED, unpinned, Contacts.STARRED, 0));
+        assertValuesForContact(i3.mContactId,
+                newContentValues(Contacts.PINNED, unpinned, Contacts.STARRED, 0));
+        assertValuesForContact(i4.mContactId,
+                newContentValues(Contacts.PINNED, 2, Contacts.STARRED, 0));
+
+        assertValuesForRawContact(i1.mRawContactId,
+                newContentValues(RawContacts.PINNED, 1, RawContacts.STARRED, 1));
+        assertValuesForRawContact(i2.mRawContactId,
+                newContentValues(RawContacts.PINNED, unpinned, RawContacts.STARRED, 0));
+        assertValuesForRawContact(i3.mRawContactId,
+                newContentValues(RawContacts.PINNED, unpinned, RawContacts.STARRED, 0));
+        assertValuesForRawContact(i4.mRawContactId,
+                newContentValues(RawContacts.PINNED, 2, RawContacts.STARRED, 0));
+
+        ContactUtil.delete(mResolver, i1.mContactId);
+        ContactUtil.delete(mResolver, i2.mContactId);
+        ContactUtil.delete(mResolver, i3.mContactId);
+        ContactUtil.delete(mResolver, i4.mContactId);
+    }
+
+    /**
+     * Tests that pinned positions are correctly handled after the ContactsProvider aggregates
+     * and splits raw contacts.
+     */
+    public void testPinnedPositionsAfterJoinAndSplit() {
+        final DatabaseAsserts.ContactIdPair i1 = DatabaseAsserts.assertAndCreateContact(mResolver);
+        final DatabaseAsserts.ContactIdPair i2 = DatabaseAsserts.assertAndCreateContact(mResolver);
+        final DatabaseAsserts.ContactIdPair i3 = DatabaseAsserts.assertAndCreateContact(mResolver);
+        final DatabaseAsserts.ContactIdPair i4 = DatabaseAsserts.assertAndCreateContact(mResolver);
+        final DatabaseAsserts.ContactIdPair i5 = DatabaseAsserts.assertAndCreateContact(mResolver);
+        final DatabaseAsserts.ContactIdPair i6 = DatabaseAsserts.assertAndCreateContact(mResolver);
+
+        final ArrayList<ContentProviderOperation> operations =
+                new ArrayList<ContentProviderOperation>();
+
+        operations.add(newPinningOperation(i1.mContactId, 1, true));
+        operations.add(newPinningOperation(i2.mContactId, 2, true));
+        operations.add(newPinningOperation(i3.mContactId, 3, true));
+        operations.add(newPinningOperation(i5.mContactId, 5, true));
+        operations.add(newPinningOperation(i6.mContactId, 6, true));
+
+        applyBatch(mResolver, operations);
+
+        // Aggregate raw contact 1 and 4 together.
+        ContactUtil.setAggregationException(mResolver, AggregationExceptions.TYPE_KEEP_TOGETHER,
+                i1.mRawContactId, i4.mRawContactId);
+
+        // If only one contact is pinned, the resulting contact should inherit the pinned position.
+        assertValuesForContact(i1.mContactId, newContentValues(Contacts.PINNED, 1));
+        assertValuesForContact(i2.mContactId, newContentValues(Contacts.PINNED, 2));
+        assertValuesForContact(i3.mContactId, newContentValues(Contacts.PINNED, 3));
+        assertValuesForContact(i5.mContactId, newContentValues(Contacts.PINNED, 5));
+        assertValuesForContact(i6.mContactId, newContentValues(Contacts.PINNED, 6));
+
+        assertValuesForRawContact(i1.mRawContactId,
+                newContentValues(RawContacts.PINNED, 1, RawContacts.STARRED, 1));
+        assertValuesForRawContact(i2.mRawContactId,
+                newContentValues(RawContacts.PINNED, 2, RawContacts.STARRED, 1));
+        assertValuesForRawContact(i3.mRawContactId,
+                newContentValues(RawContacts.PINNED, 3, RawContacts.STARRED, 1));
+        assertValuesForRawContact(i4.mRawContactId,
+                newContentValues(RawContacts.PINNED, PinnedPositions.UNPINNED, RawContacts.STARRED,
+                        0));
+        assertValuesForRawContact(i5.mRawContactId,
+                newContentValues(RawContacts.PINNED, 5, RawContacts.STARRED, 1));
+        assertValuesForRawContact(i6.mRawContactId,
+                newContentValues(RawContacts.PINNED, 6, RawContacts.STARRED, 1));
+
+        // Aggregate raw contact 2 and 3 together.
+        ContactUtil.setAggregationException(mResolver, AggregationExceptions.TYPE_KEEP_TOGETHER,
+                i2.mRawContactId, i3.mRawContactId);
+
+        // If both raw contacts are pinned, the resulting contact should inherit the lower
+        // pinned position.
+        assertValuesForContact(i1.mContactId, newContentValues(Contacts.PINNED, 1));
+        assertValuesForContact(i2.mContactId, newContentValues(Contacts.PINNED, 2));
+        assertValuesForContact(i5.mContactId, newContentValues(Contacts.PINNED, 5));
+        assertValuesForContact(i6.mContactId, newContentValues(Contacts.PINNED, 6));
+
+        assertValuesForRawContact(i1.mRawContactId, newContentValues(RawContacts.PINNED, 1));
+        assertValuesForRawContact(i2.mRawContactId, newContentValues(RawContacts.PINNED, 2));
+        assertValuesForRawContact(i3.mRawContactId, newContentValues(RawContacts.PINNED, 3));
+        assertValuesForRawContact(i4.mRawContactId,
+                newContentValues(RawContacts.PINNED, PinnedPositions.UNPINNED));
+        assertValuesForRawContact(i5.mRawContactId, newContentValues(RawContacts.PINNED, 5));
+        assertValuesForRawContact(i6.mRawContactId, newContentValues(RawContacts.PINNED, 6));
+
+        // Split the aggregated raw contacts.
+        ContactUtil.setAggregationException(mResolver, AggregationExceptions.TYPE_KEEP_SEPARATE,
+            i1.mRawContactId, i4.mRawContactId);
+
+        // Raw contacts should be unpinned after being split, but still starred.
+        assertValuesForRawContact(i1.mRawContactId,
+                newContentValues(RawContacts.PINNED, PinnedPositions.UNPINNED, RawContacts.STARRED,
+                        1));
+        assertValuesForRawContact(i2.mRawContactId,
+                newContentValues(RawContacts.PINNED, 2, RawContacts.STARRED, 1));
+        assertValuesForRawContact(i3.mRawContactId,
+                newContentValues(RawContacts.PINNED, 3, RawContacts.STARRED, 1));
+        assertValuesForRawContact(i4.mRawContactId,
+                newContentValues(RawContacts.PINNED, PinnedPositions.UNPINNED, RawContacts.STARRED,
+                        0));
+        assertValuesForRawContact(i5.mRawContactId,
+                newContentValues(RawContacts.PINNED, 5, RawContacts.STARRED, 1));
+        assertValuesForRawContact(i6.mRawContactId,
+                newContentValues(RawContacts.PINNED, 6, RawContacts.STARRED, 1));
+
+        // Now demote contact 5.
+        operations.clear();
+        operations.add(newPinningOperation(i5.mContactId, PinnedPositions.DEMOTED, false));
+        applyBatch(mResolver, operations);
+
+        // Get new contact Ids for contacts composing of raw contacts 1 and 4 because they have
+        // changed.
+        final long cId1 = RawContactUtil.queryContactIdByRawContactId(mResolver, i1.mRawContactId);
+        final long cId4 = RawContactUtil.queryContactIdByRawContactId(mResolver, i4.mRawContactId);
+
+        assertValuesForContact(cId1, newContentValues(Contacts.PINNED, PinnedPositions.UNPINNED));
+        assertValuesForContact(i2.mContactId, newContentValues(Contacts.PINNED, 2));
+        assertValuesForContact(cId4, newContentValues(Contacts.PINNED, PinnedPositions.UNPINNED));
+        assertValuesForContact(i5.mContactId,
+                newContentValues(Contacts.PINNED, PinnedPositions.DEMOTED));
+        assertValuesForContact(i6.mContactId, newContentValues(Contacts.PINNED, 6));
+
+        // Aggregate contacts 5 and 6 together.
+        ContactUtil.setAggregationException(mResolver, AggregationExceptions.TYPE_KEEP_TOGETHER,
+                i5.mRawContactId, i6.mRawContactId);
+
+        // The resulting contact should have a pinned value of 6.
+        assertValuesForContact(cId1, newContentValues(Contacts.PINNED, PinnedPositions.UNPINNED));
+        assertValuesForContact(i2.mContactId, newContentValues(Contacts.PINNED, 2));
+        assertValuesForContact(cId4, newContentValues(Contacts.PINNED, PinnedPositions.UNPINNED));
+        assertValuesForContact(i5.mContactId, newContentValues(Contacts.PINNED, 6));
+
+        ContactUtil.delete(mResolver, cId1);
+        ContactUtil.delete(mResolver, i2.mContactId);
+        ContactUtil.delete(mResolver, cId4);
+        ContactUtil.delete(mResolver, i5.mContactId);
+    }
+
+    /**
+     * Tests that calling {@link PinnedPositions#UNDEMOTE_METHOD} with an illegal argument correctly
+     * throws an IllegalArgumentException.
+     */
+    public void testPinnedPositionsDemoteIllegalArguments() {
+        try {
+            mResolver.call(ContactsContract.AUTHORITY_URI, PinnedPositions.UNDEMOTE_METHOD,
+                    null, null);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+
+        try {
+            mResolver.call(ContactsContract.AUTHORITY_URI, PinnedPositions.UNDEMOTE_METHOD,
+                    "1.1", null);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+
+        try {
+            mResolver.call(ContactsContract.AUTHORITY_URI, PinnedPositions.UNDEMOTE_METHOD,
+                    "NotANumber", null);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+
+        // Valid contact ID that does not correspond to an actual contact is silently ignored
+        mResolver.call(ContactsContract.AUTHORITY_URI, PinnedPositions.UNDEMOTE_METHOD, "999",
+                null);
+    }
+
+    /**
+     * Tests that pinned positions are correctly handled for contacts that have been demoted
+     * or undemoted.
+     */
+    public void testPinnedPositionsAfterDemoteAndUndemote() {
+        final DatabaseAsserts.ContactIdPair i1 = DatabaseAsserts.assertAndCreateContact(mResolver);
+        final DatabaseAsserts.ContactIdPair i2 = DatabaseAsserts.assertAndCreateContact(mResolver);
+
+        // Pin contact 1 and demote contact 2
+        final ArrayList<ContentProviderOperation> operations =
+                new ArrayList<ContentProviderOperation>();
+        operations.add(newPinningOperation(i1.mContactId, 1, true));
+        operations.add(newPinningOperation(i2.mContactId, PinnedPositions.DEMOTED, false));
+        applyBatch(mResolver, operations);
+
+        assertValuesForContact(i1.mContactId,
+                newContentValues(Contacts.PINNED, 1, Contacts.STARRED, 1));
+        assertValuesForContact(i2.mContactId,
+                newContentValues(Contacts.PINNED, PinnedPositions.DEMOTED, Contacts.STARRED, 0));
+
+        assertValuesForRawContact(i1.mRawContactId,
+                newContentValues(RawContacts.PINNED, 1, RawContacts.STARRED, 1));
+        assertValuesForRawContact(i2.mRawContactId,
+                newContentValues(RawContacts.PINNED, PinnedPositions.DEMOTED, RawContacts.STARRED, 0));
+
+        // Now undemote both contacts.
+        PinnedPositions.undemote(mResolver, i1.mContactId);
+        PinnedPositions.undemote(mResolver, i2.mContactId);
+
+        // Contact 1 remains pinned at 0, while contact 2 becomes unpinned.
+        assertValuesForContact(i1.mContactId,
+                newContentValues(Contacts.PINNED, 1, Contacts.STARRED, 1));
+        assertValuesForContact(i2.mContactId,
+                newContentValues(Contacts.PINNED, PinnedPositions.UNPINNED, Contacts.STARRED, 0));
+
+        assertValuesForRawContact(i1.mRawContactId,
+                newContentValues(RawContacts.PINNED, 1, RawContacts.STARRED, 1));
+        assertValuesForRawContact(i2.mRawContactId,
+                newContentValues(RawContacts.PINNED, PinnedPositions.UNPINNED, RawContacts.STARRED,
+                        0));
+
+        ContactUtil.delete(mResolver, i1.mContactId);
+        ContactUtil.delete(mResolver, i2.mContactId);
+    }
+
+    /**
+     * Verifies that the stored values for the contact that corresponds to the given contactId
+     * contain the exact same name-value pairs in the given ContentValues.
+     *
+     * @param contactId Id of a valid contact in the contacts database.
+     * @param contentValues A valid ContentValues object.
+     */
+    private void assertValuesForContact(long contactId, ContentValues contentValues) {
+        DatabaseAsserts.assertStoredValuesInUriMatchExactly(mResolver, Contacts.CONTENT_URI.
+                buildUpon().appendEncodedPath(String.valueOf(contactId)).build(), contentValues);
+    }
+
+    /**
+     * Verifies that the stored values for the raw contact that corresponds to the given
+     * rawContactId contain the exact same name-value pairs in the given ContentValues.
+     *
+     * @param rawContactId Id of a valid contact in the contacts database
+     * @param contentValues A valid ContentValues object
+     */
+    private void assertValuesForRawContact(long rawContactId, ContentValues contentValues) {
+        DatabaseAsserts.assertStoredValuesInUriMatchExactly(mResolver, RawContacts.CONTENT_URI.
+                buildUpon().appendEncodedPath(String.valueOf(rawContactId)).build(), contentValues);
+    }
+
+    /**
+     * Updates the contacts provider for a contact or raw contact corresponding to the given
+     * contact with key-value pairs as specified in the provided string parameters. Throws an
+     * exception if the number of provided string parameters is not zero or non-even.
+     *
+     * @param uri base URI that the provided ID will be appended onto, in order to creating the
+     * resulting URI
+     * @param id id of the contact of raw contact to perform the update for
+     * @param extras an even number of string parameters that correspond to name-value pairs
+     *
+     * @return the number of rows that were updated
+     */
+    private int updateItemForContact(Uri uri, long id, String... extras) {
+        Uri itemUri = ContentUris.withAppendedId(uri, id);
+        return updateItemForUri(itemUri, extras);
+    }
+
+    /**
+     * Updates the contacts provider for the given YRU with key-value pairs as specified in the
+     * provided string parameters. Throws an exception if the number of provided string parameters
+     * is not zero or non-even.
+     *
+     * @param uri URI to perform the update for
+     * @param extras an even number of string parameters that correspond to name-value pairs
+     *
+     * @return the number of rows that were updated
+     */
+    private int updateItemForUri(Uri uri, String... extras) {
+        ContentValues values = new ContentValues();
+        CommonDatabaseUtils.extrasVarArgsToValues(values, extras);
+        return mResolver.update(uri, values, null, null);
+    }
+
+    private ContentProviderOperation newPinningOperation(long id, int pinned, boolean star) {
+        final Uri uri = Uri.withAppendedPath(Contacts.CONTENT_URI, String.valueOf(id));
+        final ContentValues values = new ContentValues();
+        values.put(Contacts.PINNED, pinned);
+        values.put(Contacts.STARRED, star ? 1 : 0);
+        return ContentProviderOperation.newUpdate(uri).withValues(values).build();
+    }
+
+    private static void applyBatch(ContentResolver resolver,
+            ArrayList<ContentProviderOperation> operations) {
+        try {
+            resolver.applyBatch(ContactsContract.AUTHORITY, operations);
+        } catch (OperationApplicationException e) {
+            Log.wtf(TAG, "ContentResolver batch operation failed.");
+        } catch (RemoteException e) {
+            Log.wtf(TAG, "Remote exception when performing batch operation.");
+        }
+    }
+}
+
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_SearchSnippetsTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_SearchSnippetsTest.java
new file mode 100644
index 0000000..847e357
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_SearchSnippetsTest.java
@@ -0,0 +1,272 @@
+/*
+ * 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.provider.cts;
+
+
+import android.content.ContentProviderClient;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.net.Uri;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.CommonDataKinds.Note;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
+import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.RawContacts;
+import android.provider.ContactsContract.SearchSnippets;
+import android.provider.cts.ContactsContract_TestDataBuilder.TestContact;
+import android.provider.cts.ContactsContract_TestDataBuilder.TestRawContact;
+import android.provider.cts.contacts.DatabaseAsserts;
+import android.test.InstrumentationTestCase;
+
+/**
+ * CTS tests for {@link android.provider.ContactsContract.SearchSnippets} APIs.
+ */
+public class ContactsContract_SearchSnippetsTest extends InstrumentationTestCase {
+    private ContentResolver mResolver;
+    private ContactsContract_TestDataBuilder mBuilder;
+
+    public static String[] TEST_PROJECTION = new String[] {
+        Contacts._ID,
+        SearchSnippets.SNIPPET
+    };
+
+    public static ContentValues[] sContentValues = new ContentValues[3];
+    static {
+        ContentValues cv1 = new ContentValues();
+        cv1.put(Contacts.DISPLAY_NAME, "Hot Tamale");
+        sContentValues[0] = cv1;
+
+        ContentValues cv2 = new ContentValues();
+        cv2.put(Contacts.DISPLAY_NAME, "Cold Tamago");
+        sContentValues[1] = cv2;
+
+        ContentValues cv3 = new ContentValues();
+        cv3.put(Contacts.DISPLAY_NAME, "John Doe");
+        sContentValues[2] = cv3;
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mResolver = getInstrumentation().getTargetContext().getContentResolver();
+        ContentProviderClient provider =
+                mResolver.acquireContentProviderClient(ContactsContract.AUTHORITY);
+        mBuilder = new ContactsContract_TestDataBuilder(provider);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        mBuilder.cleanup();
+    }
+
+    public void testSearchSnippets_NoMatch() throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = ContactsContract.Contacts.CONTENT_FILTER_URI.buildUpon()
+                .appendPath("nomatch").build();
+
+        assertCursorStoredValuesWithContactsFilter(uri, ids);
+    }
+
+    public void testSearchSnippets_MatchEmailAddressCorrectSnippet() throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = ContactsContract.Contacts.CONTENT_FILTER_URI.buildUpon()
+                .appendPath("farm").build();
+
+        final ContentValues expected = new ContentValues();
+        expected.put(Contacts._ID, ids[1]);
+        expected.put(SearchSnippets.SNIPPET, "eggs@[farmers].org");
+        assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+    }
+
+    public void testSearchSnippets_MatchPhoneNumberCorrectSnippet() throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = ContactsContract.Contacts.CONTENT_FILTER_URI.buildUpon()
+                .appendPath("510").build();
+
+        final ContentValues expected = new ContentValues();
+        expected.put(Contacts._ID, ids[0]);
+        expected.put(SearchSnippets.SNIPPET, "[510-123-5769]");
+        assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+    }
+
+    public void testSearchSnippets_MatchPostalAddressCorrectSnippet() throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = ContactsContract.Contacts.CONTENT_FILTER_URI.buildUpon()
+                .appendPath("street").build();
+
+        final ContentValues expected = new ContentValues();
+        expected.put(Contacts._ID, ids[2]);
+        expected.put(SearchSnippets.SNIPPET, "123 Main [Street] Unit 3113\u2026");
+        assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+    }
+
+    public void testSearchSnippets_LongMatchTruncation() throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = ContactsContract.Contacts.CONTENT_FILTER_URI.buildUpon()
+                .appendPath("over").build();
+
+        final ContentValues expected = new ContentValues();
+        expected.put(Contacts._ID, ids[2]);
+        expected.put(SearchSnippets.SNIPPET, "\u2026dog jumps [over] the quick\u2026");
+        assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+    }
+
+    public void testSearchSnippets_MultipleMatchesCorrectSnippet() throws Exception {
+        long[] ids = setupTestData();
+        final Uri uri = ContactsContract.Contacts.CONTENT_FILTER_URI.buildUpon()
+                .appendPath("123").build();
+
+        final ContentValues expected = new ContentValues();
+        expected.put(Contacts._ID, ids[1]);
+        expected.put(SearchSnippets.SNIPPET, "[123-456-7890]");
+
+        final ContentValues expected2 = new ContentValues();
+        expected2.put(Contacts._ID, ids[2]);
+        expected2.put(SearchSnippets.SNIPPET, "[123] Main Street Unit 3113\u2026");
+
+        assertCursorStoredValuesWithContactsFilter(uri, ids, expected, expected2);
+    }
+
+    /**
+     * Tests that if deferred snippeting is indicated, the provider will not perform formatting
+     * of the snippet for a single word query.
+     */
+    public void testSearchSnippets_DeferredSnippetingSingleWordQuerySnippetDeferred() throws
+            Exception {
+        long[] ids = setupTestData();
+        final Uri uri = ContactsContract.Contacts.CONTENT_FILTER_URI.buildUpon()
+                .appendQueryParameter(SearchSnippets.DEFERRED_SNIPPETING_KEY, "1")
+                .appendPath("510").build();
+
+        final ContentValues expected = new ContentValues();
+        expected.put(Contacts._ID, ids[0]);
+        expected.put(SearchSnippets.SNIPPET, "510-123-5769");
+        assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+    }
+
+    /**
+     * Tests that even if deferred snippeting is indicated, a multi-word query will have formatting
+     * of the snippet done by the provider using SQLite
+     */
+    public void testSearchSnippets_DeferredSnippetingMultiWordQuerySnippetNotDeferred() throws
+            Exception {
+        long[] ids = setupTestData();
+        final Uri uri = ContactsContract.Contacts.CONTENT_FILTER_URI.buildUpon()
+                .appendQueryParameter(SearchSnippets.DEFERRED_SNIPPETING_KEY, "1")
+                .appendPath("jumps over").build();
+
+        final ContentValues expected = new ContentValues();
+        expected.put(Contacts._ID, ids[2]);
+        expected.put(SearchSnippets.SNIPPET, "\u2026lazy dog [jumps] [over] the\u2026");
+        assertCursorStoredValuesWithContactsFilter(uri, ids, expected);
+    }
+
+    /**
+     * Given a uri, performs a query on the contacts provider for that uri and asserts that the
+     * cursor returned from the query matches the expected results.
+     *
+     * @param uri Uri to perform the query for
+     * @param contactsId Array of contact IDs that serves as an additional filter on the result
+     * set. This is needed to limit the output to temporary test contacts that were created for
+     * purposes of the test, so that the tests do not fail on devices with existing contacts on
+     * them
+     * @param expected An array of ContentValues corresponding to the expected output of the query
+     */
+    private void assertCursorStoredValuesWithContactsFilter(Uri uri, long[] contactsId,
+            ContentValues... expected) {
+        // We need this helper function to add a filter for specific contacts because
+        // otherwise tests will fail if performed on a device with existing contacts data
+        StringBuilder sb = new StringBuilder();
+        sb.append(Contacts._ID + " in ");
+        sb.append("(");
+        for (int i = 0; i < contactsId.length; i++) {
+            if (i != 0) sb.append(",");
+            sb.append(contactsId[i]);
+        }
+        sb.append(")");
+        DatabaseAsserts.assertStoredValuesInUriMatchExactly(mResolver, uri, TEST_PROJECTION,
+                sb.toString(), null, null, false, expected);
+    }
+
+    /**
+     * Setup the contacts database with temporary contacts used for testing. These contacts will be
+     * removed during teardown.
+     *
+     * @return An array of long values corresponding to the ids of the created contacts
+     * @throws Exception
+     */
+    private long[] setupTestData() throws Exception {
+        TestRawContact rawContact = mBuilder.newRawContact()
+                .with(RawContacts.ACCOUNT_TYPE, "test_account")
+                .with(RawContacts.ACCOUNT_NAME, "test_name")
+                .insert();
+        rawContact.newDataRow(StructuredName.CONTENT_ITEM_TYPE)
+                .with(StructuredName.DISPLAY_NAME, "Hot Tamale")
+                .insert();
+        rawContact.newDataRow(Phone.CONTENT_ITEM_TYPE)
+                .with(Phone.DATA, "510-123-5769")
+                .with(Email.TYPE, Phone.TYPE_HOME)
+                .insert().load().getId();
+        rawContact.load();
+        TestContact contact = rawContact.getContact().load();
+
+        TestRawContact rawContact2 = mBuilder.newRawContact()
+                .with(RawContacts.ACCOUNT_TYPE, "test_account")
+                .with(RawContacts.ACCOUNT_NAME, "test_name")
+                .insert();
+        rawContact2.newDataRow(StructuredName.CONTENT_ITEM_TYPE)
+                .with(StructuredName.DISPLAY_NAME, "Cold Tamago")
+                .insert();
+        rawContact2.newDataRow(Email.CONTENT_ITEM_TYPE)
+                .with(Email.DATA, "eggs@farmers.org")
+                .with(Email.TYPE, Email.TYPE_HOME)
+                .insert().load();
+        rawContact2.newDataRow(Phone.CONTENT_ITEM_TYPE)
+        .with(Phone.DATA, "123-456-7890")
+        .with(Phone.TYPE, Phone.TYPE_OTHER)
+        .insert().load();
+
+        rawContact2.load();
+        TestContact contact2 = rawContact2.getContact().load();
+
+        TestRawContact rawContact3 = mBuilder.newRawContact()
+                .with(RawContacts.ACCOUNT_TYPE, "test_account")
+                .with(RawContacts.ACCOUNT_NAME, "test_name")
+                .insert();
+        rawContact3.newDataRow(StructuredName.CONTENT_ITEM_TYPE)
+                .with(StructuredName.DISPLAY_NAME, "John Doe")
+                .insert();
+        rawContact3.newDataRow(StructuredPostal.CONTENT_ITEM_TYPE)
+                .with(StructuredPostal.DATA, "123 Main Street Unit 3113")
+                .with(StructuredPostal.TYPE, StructuredPostal.TYPE_HOME)
+                .insert().load().getId();
+        rawContact3.newDataRow(Note.CONTENT_ITEM_TYPE)
+                .with(Note.NOTE, "The lazy dog jumps over the quick brown fox.")
+                .insert().load();
+        rawContact3.load();
+        TestContact contact3 = rawContact3.getContact().load();
+
+        return new long[] {
+                contact.getId(), contact2.getId(), contact3.getId()
+        };
+    }
+}
+
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_TestDataBuilder.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_TestDataBuilder.java
index 43c249e..471f895 100644
--- a/tests/tests/provider/src/android/provider/cts/ContactsContract_TestDataBuilder.java
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_TestDataBuilder.java
@@ -334,6 +334,10 @@
             return getLong(Data.RAW_CONTACT_ID);
         }
 
+        public long getId() {
+            return getLong(Data._ID);
+        }
+
         public TestRawContact getRawContact() throws Exception {
             return mRawContact;
         }
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsProvider2_AccountRemovalTest.java b/tests/tests/provider/src/android/provider/cts/ContactsProvider2_AccountRemovalTest.java
old mode 100644
new mode 100755
index f700220..cdb3546
--- a/tests/tests/provider/src/android/provider/cts/ContactsProvider2_AccountRemovalTest.java
+++ b/tests/tests/provider/src/android/provider/cts/ContactsProvider2_AccountRemovalTest.java
@@ -113,6 +113,7 @@
      */
     public void testAccountRemovalWithMergedContact_doesNotDeleteContactAndTimestampUpdated() {
         mAccountManager.addAccountExplicitly(ACCT_1, null, null);
+        mAccountManager.addAccountExplicitly(ACCT_2, null, null);
         ArrayList<ContactIdPair> idList = createAndAssertMergedContact(ACCT_1, ACCT_2);
         long contactId = idList.get(0).mContactId;
 
@@ -125,6 +126,7 @@
                     "Contact " + contactId + " last updated timestamp has not been updated.");
             SystemClock.sleep(SLEEP_BETWEEN_POLL_MS);
         }
+        mAccountManager.removeAccount(ACCT_2, null, null);
     }
 
     public void testAccountRemovalWithMergedContact_hasDeleteLogsForContacts() {
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsTest.java b/tests/tests/provider/src/android/provider/cts/ContactsTest.java
index b496007..9a3fc19 100644
--- a/tests/tests/provider/src/android/provider/cts/ContactsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/ContactsTest.java
@@ -219,12 +219,12 @@
         try {
             Context context = getInstrumentation().getTargetContext();
             InputStream inputStream = context.getResources().openRawResource(
-                    com.android.cts.stub.R.drawable.testimage);
+                    com.android.cts.provider.R.drawable.testimage);
             int size = inputStream.available();
             byte[] data =  new byte[size];
             inputStream.read(data);
             BitmapDrawable sourceDrawable = (BitmapDrawable) context.getResources().getDrawable(
-                    com.android.cts.stub.R.drawable.testimage);
+                    com.android.cts.provider.R.drawable.testimage);
             // Test: insert
             ContentValues value = new ContentValues();
             value.put(Photos.PERSON_ID, 1);
@@ -413,7 +413,10 @@
         final String[] CALLS_PROJECTION = new String[] {
                 Calls._ID, Calls.NUMBER, Calls.DATE, Calls.DURATION, Calls.TYPE,
                 Calls.NEW, Calls.CACHED_NAME, Calls.CACHED_NUMBER_TYPE,
-                Calls.CACHED_NUMBER_LABEL};
+                Calls.CACHED_NUMBER_LABEL, Calls.CACHED_FORMATTED_NUMBER,
+                Calls.CACHED_MATCHED_NUMBER, Calls.CACHED_NORMALIZED_NUMBER,
+                Calls.CACHED_LOOKUP_URI, Calls.CACHED_PHOTO_ID, Calls.COUNTRY_ISO,
+                Calls.GEOCODED_LOCATION};
         final int ID_INDEX = 0;
         final int NUMBER_INDEX = 1;
         final int DATE_INDEX = 2;
@@ -423,15 +426,30 @@
         final int CACHED_NAME_INDEX = 6;
         final int CACHED_NUMBER_TYPE_INDEX = 7;
         final int CACHED_NUMBER_LABEL_INDEX = 8;
+        final int CACHED_FORMATTED_NUMBER_INDEX = 9;
+        final int CACHED_MATCHED_NUMBER_INDEX = 10;
+        final int CACHED_NORMALIZED_NUMBER_INDEX = 11;
+        final int CACHED_LOOKUP_URI_INDEX = 12;
+        final int CACHED_PHOTO_ID_INDEX = 13;
+        final int COUNTRY_ISO_INDEX = 14;
+        final int GEOCODED_LOCATION_INDEX = 15;
 
         String insertCallsNumber = "0123456789";
         int insertCallsDuration = 120;
         String insertCallsName = "cached_name_insert";
         String insertCallsNumberLabel = "cached_label_insert";
-        String updateCallsNumber = "9876543210";
+
+        String updateCallsNumber = "987654321";
         int updateCallsDuration = 310;
         String updateCallsName = "cached_name_update";
         String updateCallsNumberLabel = "cached_label_update";
+        String updateCachedFormattedNumber = "987-654-4321";
+        String updateCachedMatchedNumber = "987-654-4321";
+        String updateCachedNormalizedNumber = "+1987654321";
+        String updateCachedLookupUri = "cached_lookup_uri_update";
+        long updateCachedPhotoId = 100;
+        String updateCountryIso = "hk";
+        String updateGeocodedLocation = "Hong Kong";
 
         try {
             // Test: insert
@@ -463,7 +481,8 @@
             int id = cursor.getInt(ID_INDEX);
             cursor.close();
 
-            // Test: update
+            // Test: update. Also add new cached fields to simulate extra cached fields being
+            // inserted into the call log after the initial lookup.
             int now = (int) new Date().getTime();
             value.clear();
             value.put(Calls.NUMBER, updateCallsNumber);
@@ -474,6 +493,13 @@
             value.put(Calls.CACHED_NAME, updateCallsName);
             value.put(Calls.CACHED_NUMBER_TYPE, Phones.TYPE_CUSTOM);
             value.put(Calls.CACHED_NUMBER_LABEL, updateCallsNumberLabel);
+            value.put(Calls.CACHED_FORMATTED_NUMBER, updateCachedFormattedNumber);
+            value.put(Calls.CACHED_MATCHED_NUMBER, updateCachedMatchedNumber);
+            value.put(Calls.CACHED_NORMALIZED_NUMBER, updateCachedNormalizedNumber);
+            value.put(Calls.CACHED_PHOTO_ID, updateCachedPhotoId);
+            value.put(Calls.COUNTRY_ISO, updateCountryIso);
+            value.put(Calls.GEOCODED_LOCATION, updateGeocodedLocation);
+            value.put(Calls.CACHED_LOOKUP_URI, updateCachedLookupUri);
 
             mCallLogProvider.update(uri, value, null, null);
             cursor = mCallLogProvider.query(Calls.CONTENT_URI, CALLS_PROJECTION,
@@ -487,6 +513,15 @@
             assertEquals(updateCallsName, cursor.getString(CACHED_NAME_INDEX));
             assertEquals(Phones.TYPE_CUSTOM, cursor.getInt(CACHED_NUMBER_TYPE_INDEX));
             assertEquals(updateCallsNumberLabel, cursor.getString(CACHED_NUMBER_LABEL_INDEX));
+            assertEquals(updateCachedFormattedNumber,
+                    cursor.getString(CACHED_FORMATTED_NUMBER_INDEX));
+            assertEquals(updateCachedMatchedNumber, cursor.getString(CACHED_MATCHED_NUMBER_INDEX));
+            assertEquals(updateCachedNormalizedNumber,
+                    cursor.getString(CACHED_NORMALIZED_NUMBER_INDEX));
+            assertEquals(updateCachedPhotoId, cursor.getLong(CACHED_PHOTO_ID_INDEX));
+            assertEquals(updateCountryIso, cursor.getString(COUNTRY_ISO_INDEX));
+            assertEquals(updateGeocodedLocation, cursor.getString(GEOCODED_LOCATION_INDEX));
+            assertEquals(updateCachedLookupUri, cursor.getString(CACHED_LOOKUP_URI_INDEX));
             cursor.close();
 
             // Test: delete
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 e5085b8..6b5de96 100644
--- a/tests/tests/provider/src/android/provider/cts/Contacts_PeopleTest.java
+++ b/tests/tests/provider/src/android/provider/cts/Contacts_PeopleTest.java
@@ -257,7 +257,7 @@
         Context context = getInstrumentation().getTargetContext();
         try {
             InputStream inputStream = context.getResources().openRawResource(
-                    com.android.cts.stub.R.drawable.testimage);
+                    com.android.cts.provider.R.drawable.testimage);
             int size = inputStream.available();
             byte[] data =  new byte[size];
             inputStream.read(data);
@@ -275,12 +275,12 @@
             assertNull(photoStream);
 
             bitmap = People.loadContactPhoto(context, mPeopleRowsAdded.get(0),
-                    com.android.cts.stub.R.drawable.size_48x48, null);
+                    com.android.cts.provider.R.drawable.size_48x48, null);
             assertEquals(96, bitmap.getWidth());
             assertEquals(64, bitmap.getHeight());
 
             bitmap = People.loadContactPhoto(context, null,
-                    com.android.cts.stub.R.drawable.size_48x48, null);
+                    com.android.cts.provider.R.drawable.size_48x48, null);
             assertNotNull(bitmap);
         } catch (IOException e) {
             fail("Unexpected IOException");
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStoreAudioTestHelper.java b/tests/tests/provider/src/android/provider/cts/MediaStoreAudioTestHelper.java
new file mode 100644
index 0000000..c9eb506
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/MediaStoreAudioTestHelper.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2009 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.provider.cts;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.net.Uri;
+import android.os.Environment;
+import android.provider.MediaStore;
+import android.provider.MediaStore.Audio.Media;
+
+import junit.framework.Assert;
+
+/**
+ * This class contains fake data and convenient methods for testing:
+ * {@link MediaStore.Audio.Media}
+ * {@link MediaStore.Audio.Genres}
+ * {@link MediaStore.Audio.Genres.Members}
+ * {@link MediaStore.Audio.Playlists}
+ * {@link MediaStore.Audio.Playlists.Members}
+ * {@link MediaStore.Audio.Albums}
+ * {@link MediaStore.Audio.Artists}
+ * {@link MediaStore.Audio.Artists.Albums}
+ *
+ * @see MediaStore_Audio_MediaTest
+ * @see MediaStore_Audio_GenresTest
+ * @see MediaStore_Audio_Genres_MembersTest
+ * @see MediaStore_Audio_PlaylistsTest
+ * @see MediaStore_Audio_Playlists_MembersTest
+ * @see MediaStore_Audio_ArtistsTest
+ * @see MediaStore_Audio_Artists_AlbumsTest
+ * @see MediaStore_Audio_AlbumsTest
+ */
+public class MediaStoreAudioTestHelper {
+    public static abstract class MockAudioMediaInfo {
+        public abstract ContentValues getContentValues(boolean isInternal);
+
+        public Uri insertToInternal(ContentResolver contentResolver) {
+            Uri uri = contentResolver.insert(Media.INTERNAL_CONTENT_URI, getContentValues(true));
+            Assert.assertNotNull(uri);
+            return uri;
+        }
+
+        public Uri insertToExternal(ContentResolver contentResolver) {
+            Uri uri = contentResolver.insert(Media.EXTERNAL_CONTENT_URI, getContentValues(false));
+            Assert.assertNotNull(uri);
+            return uri;
+        }
+
+        public int delete(ContentResolver contentResolver, Uri uri) {
+            return contentResolver.delete(uri, null, null);
+        }
+    }
+
+    public static class Audio1 extends MockAudioMediaInfo {
+        private Audio1() {
+        }
+
+        private static Audio1 sInstance = new Audio1();
+
+        public static Audio1 getInstance() {
+            return sInstance;
+        }
+
+        public static final int IS_RINGTONE = 0;
+
+        public static final int IS_NOTIFICATION = 0;
+
+        public static final int IS_ALARM = 0;
+
+        public static final int IS_MUSIC = 1;
+
+        public static final int IS_DRM = 0;
+
+        public static final int YEAR = 1992;
+
+        public static final int TRACK = 1;
+
+        public static final int DURATION = 340000;
+
+        public static final String COMPOSER = "Bruce Swedien";
+
+        public static final String ARTIST = "Michael Jackson";
+
+        public static final String ALBUM = "Dangerous";
+
+        public static final String TITLE = "Jam";
+
+        public static final int SIZE = 2737870;
+
+        public static final String MIME_TYPE = "audio/x-mpeg";
+
+        public static final String DISPLAY_NAME = "Jam -Michael Jackson";
+
+        public static final String INTERNAL_DATA =
+            "/data/data/com.android.cts.provider/files/Jam.mp3";
+
+        public static final String FILE_NAME = "Jam.mp3";
+
+        public static final String EXTERNAL_DATA = Environment.getExternalStorageDirectory() +
+                "/" + FILE_NAME;
+
+        public static final long DATE_MODIFIED = System.currentTimeMillis() / 1000;
+
+        public static final String GENRE = "POP";
+        @Override
+        public ContentValues getContentValues(boolean isInternal) {
+            ContentValues values = new ContentValues();
+            values.put(Media.DATA, isInternal ? INTERNAL_DATA : EXTERNAL_DATA);
+            values.put(Media.DATE_MODIFIED, DATE_MODIFIED);
+            values.put(Media.DISPLAY_NAME, DISPLAY_NAME);
+            values.put(Media.MIME_TYPE, MIME_TYPE);
+            values.put(Media.SIZE, SIZE);
+            values.put(Media.TITLE, TITLE);
+            values.put(Media.ALBUM, ALBUM);
+            values.put(Media.ARTIST, ARTIST);
+            values.put(Media.COMPOSER, COMPOSER);
+            values.put(Media.DURATION, DURATION);
+            values.put(Media.TRACK, TRACK);
+            values.put(Media.YEAR, YEAR);
+            values.put(Media.IS_MUSIC, IS_MUSIC);
+            values.put(Media.IS_ALARM, IS_ALARM);
+            values.put(Media.IS_NOTIFICATION, IS_NOTIFICATION);
+            values.put(Media.IS_RINGTONE, IS_RINGTONE);
+            values.put(Media.IS_DRM, IS_DRM);
+
+            return values;
+        }
+    }
+
+    public static class Audio2 extends MockAudioMediaInfo {
+        private Audio2() {
+        }
+
+        private static Audio2 sInstance = new Audio2();
+
+        public static Audio2 getInstance() {
+            return sInstance;
+        }
+
+        public static final int IS_RINGTONE = 1;
+
+        public static final int IS_NOTIFICATION = 0;
+
+        public static final int IS_ALARM = 0;
+
+        public static final int IS_MUSIC = 0;
+
+        public static final int IS_DRM = 0;
+
+        public static final int YEAR = 1992;
+
+        public static final int TRACK = 1001;
+
+        public static final int DURATION = 338000;
+
+        public static final String COMPOSER = "Bruce Swedien";
+
+        public static final String ARTIST =
+            "Michael Jackson - Live And Dangerous - National Stadium Bucharest";
+
+        public static final String ALBUM =
+            "Michael Jackson - Live And Dangerous - National Stadium Bucharest";
+
+        public static final String TITLE = "Jam";
+
+        public static final int SIZE = 2737321;
+
+        public static final String MIME_TYPE = "audio/x-mpeg";
+
+        public static final String DISPLAY_NAME = "Jam(Live)-Michael Jackson";
+
+        public static final String FILE_NAME = "Jam_live.mp3";
+
+        public static final String EXTERNAL_DATA =
+            Environment.getExternalStorageDirectory().getPath() + "/" + FILE_NAME;
+
+        public static final String INTERNAL_DATA =
+            "/data/data/com.android.cts.provider/files/Jam_live.mp3";
+
+
+
+        public static final long DATE_MODIFIED = System.currentTimeMillis();
+
+        @Override
+        public ContentValues getContentValues(boolean isInternal) {
+            ContentValues values = new ContentValues();
+            values.put(Media.DATA, isInternal ? INTERNAL_DATA : EXTERNAL_DATA);
+            values.put(Media.DATE_MODIFIED, DATE_MODIFIED);
+            values.put(Media.DISPLAY_NAME, DISPLAY_NAME);
+            values.put(Media.MIME_TYPE, MIME_TYPE);
+            values.put(Media.SIZE, SIZE);
+            values.put(Media.TITLE, TITLE);
+            values.put(Media.ALBUM, ALBUM);
+            values.put(Media.ARTIST, ARTIST);
+            values.put(Media.COMPOSER, COMPOSER);
+            values.put(Media.DURATION, DURATION);
+            values.put(Media.TRACK, TRACK);
+            values.put(Media.YEAR, YEAR);
+            values.put(Media.IS_MUSIC, IS_MUSIC);
+            values.put(Media.IS_ALARM, IS_ALARM);
+            values.put(Media.IS_NOTIFICATION, IS_NOTIFICATION);
+            values.put(Media.IS_RINGTONE, IS_RINGTONE);
+            values.put(Media.IS_DRM, IS_DRM);
+
+            return values;
+        }
+    }
+
+    public static class Audio3 extends Audio1 {
+        private Audio3() {
+        }
+
+        private static Audio3 sInstance = new Audio3();
+
+        public static Audio3 getInstance() {
+            return sInstance;
+        }
+
+        @Override
+        public ContentValues getContentValues(boolean isInternal) {
+            ContentValues values = super.getContentValues(isInternal);
+            values.put(Media.DATA, values.getAsString(Media.DATA) + "_3");
+            return values;
+        }
+    }
+
+    public static class Audio4 extends Audio1 {
+        private Audio4() {
+        }
+
+        private static Audio4 sInstance = new Audio4();
+
+        public static Audio4 getInstance() {
+            return sInstance;
+        }
+
+        @Override
+        public ContentValues getContentValues(boolean isInternal) {
+            ContentValues values = super.getContentValues(isInternal);
+            values.put(Media.DATA, values.getAsString(Media.DATA) + "_4");
+            return values;
+        }
+    }
+
+    public static class Audio5 extends Audio1 {
+        private Audio5() {
+        }
+
+        private static Audio5 sInstance = new Audio5();
+
+        public static Audio5 getInstance() {
+            return sInstance;
+        }
+
+        @Override
+        public ContentValues getContentValues(boolean isInternal) {
+            ContentValues values = super.getContentValues(isInternal);
+            values.put(Media.DATA, values.getAsString(Media.DATA) + "_5");
+            return values;
+        }
+    }
+
+    // These constants are not part of the public API
+    public static final String EXTERNAL_VOLUME_NAME = "external";
+    public static final String INTERNAL_VOLUME_NAME = "internal";
+}
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_AlbumsTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_AlbumsTest.java
index b265cbf..84da62a 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_AlbumsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_AlbumsTest.java
@@ -16,11 +16,12 @@
 
 package android.provider.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.provider.R;
 
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.res.AssetFileDescriptor;
+import android.cts.util.FileCopyHelper;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Environment;
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_PlaylistsTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_PlaylistsTest.java
index 03a81b8..8dcb1a8 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_PlaylistsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_PlaylistsTest.java
@@ -112,7 +112,7 @@
     public void testStoreAudioPlaylistsInternal() {
         ContentValues values = new ContentValues();
         values.put(Playlists.NAME, "My favourites");
-        values.put(Playlists.DATA, "/data/data/com.android.cts.stub/files/my_favorites.pl");
+        values.put(Playlists.DATA, "/data/data/com.android.cts.provider/files/my_favorites.pl");
         long dateAdded = System.currentTimeMillis();
         values.put(Playlists.DATE_ADDED, dateAdded);
         long dateModified = System.currentTimeMillis();
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_Playlists_MembersTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_Playlists_MembersTest.java
index bf97848..58c1cdf 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_Playlists_MembersTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Audio_Playlists_MembersTest.java
@@ -454,7 +454,7 @@
     public void testStoreAudioPlaylistsMembersInternal() {
         ContentValues values = new ContentValues();
         values.put(Playlists.NAME, "My favourites");
-        values.put(Playlists.DATA, "/data/data/com.android.cts.stub/files/my_favorites.pl");
+        values.put(Playlists.DATA, "/data/data/com.android.cts.provider/files/my_favorites.pl");
         long dateAdded = System.currentTimeMillis();
         values.put(Playlists.DATE_ADDED, dateAdded);
         long dateModified = System.currentTimeMillis();
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java
index a362df3..0eae82b 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java
@@ -16,24 +16,32 @@
 
 package android.provider.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.provider.R;
 
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
+import android.cts.util.FileCopyHelper;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
+import android.os.SystemClock;
 import android.provider.MediaStore;
 import android.provider.MediaStore.MediaColumns;
 import android.test.AndroidTestCase;
+import android.util.Log;
 
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
+import java.io.FilenameFilter;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 
 public class MediaStore_FilesTest extends AndroidTestCase {
 
@@ -43,6 +51,40 @@
     protected void setUp() throws Exception {
         super.setUp();
         mResolver = mContext.getContentResolver();
+        cleanup();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        cleanup();
+    }
+
+    void cleanup() {
+        final String testName = getClass().getCanonicalName();
+        mResolver.delete(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
+                "_data LIKE ?1", new String[] {"%" + testName + "%"});
+        File ext = Environment.getExternalStorageDirectory();
+        File[] junk = ext.listFiles(new FilenameFilter() {
+
+            @Override
+            public boolean accept(File dir, String filename) {
+                return filename.contains(testName);
+            }
+        });
+        for (File f: junk) {
+            deleteAll(f);
+        }
+    }
+
+    void deleteAll(File f) {
+        if (f.isDirectory()) {
+            File [] sub = f.listFiles();
+            for (File s: sub) {
+                deleteAll(s);
+            }
+        }
+        f.delete();
     }
 
     public void testGetContentUri() {
@@ -153,6 +195,15 @@
         }
     }
 
+    String realPathFor(ParcelFileDescriptor pfd) {
+        File real = new File("/proc/self/fd/" + pfd.getFd());
+        try {
+            return real.getCanonicalPath();
+        } catch (IOException e) {
+            return null;
+        }
+    }
+
     public void testAccess() throws IOException {
         // clean up from previous run
         mResolver.delete(MediaStore.Images.Media.INTERNAL_CONTENT_URI,
@@ -255,19 +306,19 @@
 
                 // get the real path from the file descriptor (this relies on the media provider
                 // having opened the path via the real path instead of the emulated path).
-                File real = new File("/proc/self/fd/" + pfd.getFd());
                 values = new ContentValues();
-                values.put("_data", real.getCanonicalPath());
+                values.put("_data", realPathFor(pfd));
                 mResolver.update(uri, values, null, null);
                 pfd.close();
 
                 // we shouldn't be able to access this
                 try {
                     pfd = mResolver.openFileDescriptor(uri, "r");
-                    pfd.close();
-                    fail("shouldn't be here");
+                    fail("shouldn't have fd for " + realPathFor(pfd));
                 } catch (FileNotFoundException e) {
                     // expected
+                } finally {
+                    pfd.close();
                 }
             } catch (FileNotFoundException e) {
                 fail("couldn't open file");
@@ -279,6 +330,165 @@
         if (sdfile != null) {
             assertEquals(true, sdfile.delete());
         }
+
+        // test secondary storage if present
+        List<File> allpaths = getSecondaryPackageSpecificPaths(mContext);
+        List<String> trimmedPaths = new ArrayList<String>();
+
+        for (File extpath: allpaths) {
+            assertNotNull("Valid media must be inserted during CTS", extpath);
+            assertEquals("Valid media must be inserted for " + extpath
+                    + " during CTS", Environment.MEDIA_MOUNTED,
+                    Environment.getStorageState(extpath));
+
+            File child = extpath;
+            while (true) {
+                File parent = child.getParentFile();
+                if (parent == null) {
+                    fail("didn't expect to be here");
+                }
+                if (!Environment.MEDIA_MOUNTED.equals(Environment.getStorageState(parent))) {
+                    // we went past the root
+                    String abspath = child.getAbsolutePath();
+                    if (!trimmedPaths.contains(abspath)) {
+                        trimmedPaths.add(abspath);
+                    }
+                    break;
+                }
+                child = parent;
+            }
+        }
+
+        String fileDir = Environment.getExternalStorageDirectory() +
+                "/" + getClass().getCanonicalName() + "-" + SystemClock.elapsedRealtime();
+        String fileName = fileDir + "/TestSecondary.Mp3";
+        writeFile(R.raw.testmp3_2, fileName); // file without album art
+
+
+        // insert temp file
+        values = new ContentValues();
+        values.put(MediaStore.Audio.Media.DATA, fileName);
+        values.put(MediaStore.Audio.Media.ARTIST, "Artist-" + SystemClock.elapsedRealtime());
+        values.put(MediaStore.Audio.Media.ALBUM, "Album-" + SystemClock.elapsedRealtime());
+        values.put(MediaStore.Audio.Media.MIME_TYPE, "audio/mp3");
+        Uri fileUri = mResolver.insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, values);
+        // give media provider some time to realize there's no album art
+        //SystemClock.sleep(1000);
+        // get its album id
+        Cursor c = mResolver.query(fileUri, new String[] { MediaStore.Audio.Media.ALBUM_ID},
+                null, null, null);
+        assertTrue(c.moveToFirst());
+        int albumid = c.getInt(0);
+        Uri albumArtUriBase = Uri.parse("content://media/external/audio/albumart");
+        Uri albumArtUri = ContentUris.withAppendedId(albumArtUriBase, albumid);
+        try {
+            pfd = mResolver.openFileDescriptor(albumArtUri, "r");
+            fail("no album art, shouldn't be here. Got: " + realPathFor(pfd));
+        } catch (Exception e) {
+            // expected
+        }
+
+        // replace file with one that has album art
+        writeFile(R.raw.testmp3, fileName); // file with album art
+
+        for (String s: trimmedPaths) {
+            File dir = new File(s + "/foobardir-" + SystemClock.elapsedRealtime());
+            assertFalse("please remove " + dir.getAbsolutePath()
+                    + " before running", dir.exists());
+            File file = new File(dir, "foobar");
+            values = new ContentValues();
+            values.put(MediaStore.Audio.Media.ALBUM_ID, albumid);
+            values.put(MediaStore.Audio.Media.DATA, file.getAbsolutePath());
+            mResolver.insert(albumArtUriBase, values);
+            try {
+                pfd = mResolver.openFileDescriptor(albumArtUri, "r");
+                fail("shouldn't have fd for album " + albumid + ", got " + realPathFor(pfd));
+            } catch (Exception e) {
+                // expected
+            } finally {
+                pfd.close();
+            }
+            assertFalse(dir.getAbsolutePath() + " was created", dir.exists());
+        }
+        mResolver.delete(fileUri, null, null);
+        new File(fileName).delete();
+
+        // try creating files in root
+        for (String s: trimmedPaths) {
+            File dir = new File(s);
+            File file = new File(dir, "foobar.jpg");
+
+            values = new ContentValues();
+            values.put(MediaStore.Files.FileColumns.DATA, file.getAbsolutePath());
+            fileUri = mResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
+            assertNotNull(fileUri);
+
+            // check that adding the file doesn't cause it to be created
+            assertFalse(file.exists());
+
+            // check if opening the file for write works
+            try {
+                mResolver.openOutputStream(fileUri).close();
+                fail("shouldn't have been able to create output stream");
+            } catch (SecurityException e) {
+                // expected
+            }
+            // check that deleting the file doesn't cause it to be created
+            mResolver.delete(fileUri, null, null);
+            assertFalse(file.exists());
+        }
+
+        // try creating files in new subdir
+        for (String s: trimmedPaths) {
+            File dir = new File(s + "/foobardir");
+            File file = new File(dir, "foobar.jpg");
+
+            values = new ContentValues();
+            values.put(MediaStore.Files.FileColumns.DATA, dir.getAbsolutePath());
+
+            Uri dirUri = mResolver.insert(MediaStore.Files.getContentUri("external"), values);
+            assertNotNull(dirUri);
+
+            values = new ContentValues();
+            values.put(MediaStore.Files.FileColumns.DATA, file.getAbsolutePath());
+            fileUri = mResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
+            assertNotNull(fileUri);
+
+            // check that adding the file or its folder didn't cause either one to be created
+            assertFalse(dir.exists());
+            assertFalse(file.exists());
+
+            // check if opening the file for write works
+            try {
+                mResolver.openOutputStream(fileUri).close();
+                fail("shouldn't have been able to create output stream");
+            } catch (SecurityException e) {
+                // expected
+            }
+            // check that deleting the file or its folder doesn't cause either one to be created
+            mResolver.delete(fileUri, null, null);
+            assertFalse(dir.exists());
+            assertFalse(file.exists());
+            mResolver.delete(dirUri, null, null);
+            assertFalse(dir.exists());
+            assertFalse(file.exists());
+        }
+    }
+
+    public static List<File> getSecondaryPackageSpecificPaths(Context context) {
+        final List<File> paths = new ArrayList<File>();
+        Collections.addAll(paths, dropFirst(context.getExternalCacheDirs()));
+        Collections.addAll(paths, dropFirst(context.getExternalFilesDirs(null)));
+        Collections.addAll(
+                paths, dropFirst(context.getExternalFilesDirs(Environment.DIRECTORY_PICTURES)));
+        Collections.addAll(paths, dropFirst(context.getObbDirs()));
+        return paths;
+    }
+
+    private static File[] dropFirst(File[] before) {
+        final File[] after = new File[before.length - 1];
+        System.arraycopy(before, 1, after, 0, after.length);
+        return after;
     }
 
     private void writeFile(int resid, String path) throws IOException {
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Images_MediaTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Images_MediaTest.java
index 3f28a34..7469f8e 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Images_MediaTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Images_MediaTest.java
@@ -16,17 +16,18 @@
 
 package android.provider.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.provider.R;
 
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
+import android.cts.util.FileCopyHelper;
+import android.cts.util.FileUtils;
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.net.Uri;
 import android.os.Environment;
-import android.os.cts.FileUtils;
 import android.provider.MediaStore.Images.Media;
 import android.provider.MediaStore.Images.Thumbnails;
 import android.test.InstrumentationTestCase;
@@ -78,13 +79,6 @@
 
         mHelper = new FileCopyHelper(mContext);
         mRowsAdded = new ArrayList<Uri>();
-
-        String campath = Environment.getExternalStorageDirectory() + File.separator +
-                Environment.DIRECTORY_DCIM + File.separator + "Camera";
-        File camfile = new File(campath);
-        if (!camfile.exists()) {
-            assertTrue("failed to create " + campath, camfile.mkdir());
-        }
     }
 
     public void testInsertImageWithImagePath() throws Exception {
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Images_ThumbnailsTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Images_ThumbnailsTest.java
index 322f5d5..ec9db8b 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Images_ThumbnailsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Images_ThumbnailsTest.java
@@ -16,12 +16,13 @@
 
 package android.provider.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.provider.R;
 
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
+import android.cts.util.FileCopyHelper;
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -30,6 +31,7 @@
 import android.provider.MediaStore;
 import android.provider.MediaStore.Images.Media;
 import android.provider.MediaStore.Images.Thumbnails;
+import android.provider.MediaStore.MediaColumns;
 import android.test.InstrumentationTestCase;
 
 import java.io.File;
@@ -69,13 +71,6 @@
 
         mHelper = new FileCopyHelper(mContext);
         mRowsAdded = new ArrayList<Uri>();
-
-        String campath = Environment.getExternalStorageDirectory() + File.separator +
-                Environment.DIRECTORY_DCIM + File.separator + "Camera";
-        File camfile = new File(campath);
-        if (!camfile.exists()) {
-            assertTrue("failed to create " + campath, camfile.mkdir());
-        }
     }
 
     public void testQueryInternalThumbnails() throws Exception {
@@ -287,4 +282,74 @@
             // expected
         }
     }
+
+    public void testThumbnailOrderedQuery() throws Exception {
+        Bitmap src = BitmapFactory.decodeResource(mContext.getResources(), R.raw.scenery);
+        Uri url[] = new Uri[3];
+        try{
+            for (int i = 0; i < url.length; i++) {
+                url[i] = Uri.parse(Media.insertImage(mContentResolver, src, null, null));
+                long origId = Long.parseLong(url[i].getLastPathSegment());
+                Bitmap foo = MediaStore.Images.Thumbnails.getThumbnail(mContentResolver,
+                        origId, Thumbnails.MICRO_KIND, null);
+                assertNotNull(foo);
+            }
+
+            // remove one of the images, its thumbnail, and the thumbnail cache
+            Cursor c = mContentResolver.query(url[1], null, null, null, null);
+            assertEquals(1, c.getCount());
+            c.moveToFirst();
+            String path = c.getString(c.getColumnIndex(MediaColumns.DATA));
+            long id = c.getLong(c.getColumnIndex(MediaColumns._ID));
+            c.close();
+            assertTrue(new File(path).delete());
+
+            long removedId = Long.parseLong(url[1].getLastPathSegment());
+            long remainingId1 = Long.parseLong(url[0].getLastPathSegment());
+            long remainingId2 = Long.parseLong(url[2].getLastPathSegment());
+            c = mContentResolver.query(
+                    MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, null,
+                    Thumbnails.IMAGE_ID + "=?", new String[] { Long.toString(removedId) }, null);
+            assertTrue(c.getCount() > 0);  // one or more thumbnail kinds
+            while (c.moveToNext()) {
+                path = c.getString(c.getColumnIndex(MediaColumns.DATA));
+                assertTrue(new File(path).delete());
+            }
+            c.close();
+
+            File thumbdir = new File(path).getParentFile();
+            File[] list = thumbdir.listFiles();
+            for (int i = 0; i < list.length; i++) {
+                if (list[i].getName().startsWith(".thumbdata")) {
+                    assertTrue(list[i].delete());
+                }
+            }
+
+            // check if a thumbnail is still being returned for the image that was removed
+            Bitmap foo = MediaStore.Images.Thumbnails.getThumbnail(mContentResolver,
+                    removedId, Thumbnails.MICRO_KIND, null);
+            assertNull(foo);
+
+            for (String order: new String[] { " ASC", " DESC" }) {
+                c = mContentResolver.query(
+                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, null, null,
+                        MediaColumns._ID + order);
+                while (c.moveToNext()) {
+                    id = c.getLong(c.getColumnIndex(MediaColumns._ID));
+                    foo = MediaStore.Images.Thumbnails.getThumbnail(
+                            mContentResolver, id,
+                            MediaStore.Images.Thumbnails.MICRO_KIND, null);
+                    if (id == removedId) {
+                        assertNull("unexpected bitmap with" + order + " ordering", foo);
+                    } else if (id == remainingId1 || id == remainingId2) {
+                        assertNotNull("missing bitmap with" + order + " ordering", foo);
+                    }
+                }
+                c.close();
+            }
+        } catch (UnsupportedOperationException e) {
+            // the tests will be aborted because the image will be put in sdcard
+            fail("There is no sdcard attached! " + e.getMessage());
+        }
+    }
 }
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_VideoTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_VideoTest.java
index 366fc57..89de9c6 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_VideoTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_VideoTest.java
@@ -16,11 +16,12 @@
 
 package android.provider.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.provider.R;
 
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
+import android.cts.util.FileCopyHelper;
 import android.database.Cursor;
 import android.net.Uri;
 import android.provider.MediaStore.Video;
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Video_MediaTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Video_MediaTest.java
index c9461b4..f84b75c 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Video_MediaTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Video_MediaTest.java
@@ -17,15 +17,16 @@
 package android.provider.cts;
 
 
-import com.android.cts.stub.R;
+import com.android.cts.provider.R;
 
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
+import android.cts.util.FileCopyHelper;
+import android.cts.util.FileUtils;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Environment;
-import android.os.cts.FileUtils;
 import android.provider.MediaStore;
 import android.provider.MediaStore.Video.Media;
 import android.provider.MediaStore.Video.VideoColumns;
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 ac0bc03..b6175be 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
@@ -16,11 +16,12 @@
 
 package android.provider.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.provider.R;
 
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
+import android.cts.util.FileCopyHelper;
 import android.database.Cursor;
 import android.media.MediaCodecInfo;
 import android.media.MediaCodecList;
diff --git a/tests/tests/provider/src/android/provider/cts/PhotoUtil.java b/tests/tests/provider/src/android/provider/cts/PhotoUtil.java
new file mode 100644
index 0000000..ec4fdef
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/PhotoUtil.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012 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.provider.cts;
+
+import com.android.cts.provider.R;
+
+import android.content.Context;
+import android.cts.util.FileUtils;
+
+import java.io.InputStream;
+
+public class PhotoUtil {
+
+    public static byte[] getTestPhotoData(Context context) {
+        InputStream input = context.getResources().openRawResource(R.drawable.testimage);
+        return FileUtils.readInputStreamFully(input);
+    }
+}
diff --git a/tests/src/android/provider/cts/TestSearchRecentSuggestionsProvider.java b/tests/tests/provider/src/android/provider/cts/TestSearchRecentSuggestionsProvider.java
similarity index 100%
rename from tests/src/android/provider/cts/TestSearchRecentSuggestionsProvider.java
rename to tests/tests/provider/src/android/provider/cts/TestSearchRecentSuggestionsProvider.java
diff --git a/tests/tests/provider/src/android/provider/cts/contacts/CommonDatabaseUtils.java b/tests/tests/provider/src/android/provider/cts/contacts/CommonDatabaseUtils.java
index 833de64..d89e06c 100644
--- a/tests/tests/provider/src/android/provider/cts/contacts/CommonDatabaseUtils.java
+++ b/tests/tests/provider/src/android/provider/cts/contacts/CommonDatabaseUtils.java
@@ -16,8 +16,11 @@
 
 package android.provider.cts.contacts;
 
+import android.content.ContentValues;
 import android.database.Cursor;
 
+import junit.framework.Assert;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -67,4 +70,21 @@
             cursor.close();
         }
     }
+
+    /**
+     * Verifies that the number of string parameters is either zero or even, and inserts them
+     * into the provided ContentValues object as a set of name-value pairs. Throws an exception if
+     * the number of string parameters is odd, or a single null parameter was provided.
+     *
+     * @param values ContentValues object to insert name-value pairs into
+     * @param extras Zero or even number of string parameters
+     */
+    public static void extrasVarArgsToValues(ContentValues values, String... extras) {
+        Assert.assertNotNull(extras);
+        // Check that the number of provided string parameters is even.
+        Assert.assertEquals(0, extras.length % 2);
+        for (int i = 0; i < extras.length; i += 2) {
+            values.put(extras[i], extras[i + 1]);
+        }
+    }
 }
diff --git a/tests/tests/provider/src/android/provider/cts/contacts/ContactUtil.java b/tests/tests/provider/src/android/provider/cts/contacts/ContactUtil.java
index 2a53781..ae3e41a 100644
--- a/tests/tests/provider/src/android/provider/cts/contacts/ContactUtil.java
+++ b/tests/tests/provider/src/android/provider/cts/contacts/ContactUtil.java
@@ -22,6 +22,9 @@
 import android.database.Cursor;
 import android.net.Uri;
 import android.provider.ContactsContract;
+import android.provider.ContactsContract.AggregationExceptions;
+
+import junit.framework.Assert;
 
 /**
  * Convenience methods for operating on the Contacts table.
@@ -71,4 +74,64 @@
         }
         return CommonDatabaseUtils.NOT_FOUND;
     }
-}
+
+    /**
+     * Verifies that the number of object parameters is either zero or even, inserts them
+     * into a new ContentValues object as a set of name-value pairs, and returns the newly created
+     * ContentValues object. Throws an exception if the number of string parameters is odd, or a
+     * single null parameter was provided.
+     *
+     * @param namesAndValues Zero or even number of object parameters to convert into name-value
+     * pairs
+     *
+     * @return newly created ContentValues containing the provided name-value pairs
+     */
+    public static ContentValues newContentValues(Object... namesAndValues) {
+        // Checks that the number of provided parameters is zero or even.
+        Assert.assertEquals(0, namesAndValues.length % 2);
+        final ContentValues contentValues = new ContentValues();
+        for (int i = 0; i < namesAndValues.length - 1; i += 2) {
+            Assert.assertNotNull(namesAndValues[i]);
+            final String name = namesAndValues[i].toString();
+            final Object value = namesAndValues[i + 1];
+            if (value == null) {
+                contentValues.putNull(name);
+            } else if (value instanceof String) {
+                contentValues.put(name, (String) value);
+            } else if (value instanceof Integer) {
+                contentValues.put(name, (Integer) value);
+            } else if (value instanceof Long) {
+                contentValues.put(name, (Long) value);
+            } else {
+                Assert.fail("Unsupported value type: " + value.getClass().getSimpleName() + " for "
+                    + " name: " + name);
+            }
+        }
+        return contentValues;
+    }
+
+    /**
+     * Updates the content resolver with two given raw contact ids and an aggregation type to
+     * manually trigger the forced aggregation, splitting of two raw contacts or specify that
+     * the provider should automatically decide whether or not to aggregate the two raw contacts.
+     *
+     * @param resolver ContentResolver from a valid context
+     * @param type One of the following aggregation exception types:
+     * {@link AggregationExceptions#TYPE_AUTOMATIC},
+     * {@link AggregationExceptions#TYPE_KEEP_SEPARATE},
+     * {@link AggregationExceptions#TYPE_KEEP_TOGETHER}
+     * @param rawContactId1 Id of the first raw contact
+     * @param rawContactId2 Id of the second raw contact
+     */
+    public static void setAggregationException(ContentResolver resolver, int type,
+        long rawContactId1, long rawContactId2) {
+        ContentValues values = new ContentValues();
+        values.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1);
+        values.put(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2);
+        values.put(AggregationExceptions.TYPE, type);
+        // Actually set the aggregation exception in the contacts database, and check that a
+        // single row was updated.
+        Assert.assertEquals(1, resolver.update(AggregationExceptions.CONTENT_URI, values, null,
+                  null));
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/provider/src/android/provider/cts/contacts/DatabaseAsserts.java b/tests/tests/provider/src/android/provider/cts/contacts/DatabaseAsserts.java
index 19b5b13..7546066 100644
--- a/tests/tests/provider/src/android/provider/cts/contacts/DatabaseAsserts.java
+++ b/tests/tests/provider/src/android/provider/cts/contacts/DatabaseAsserts.java
@@ -142,7 +142,7 @@
      */
     public static void assertStoredValuesInUriMatchExactly(ContentResolver resolver, Uri uri,
             ContentValues... expectedValues) {
-        assertStoredValuesInUriMatchExactly(resolver, uri, null, null, null, null, expectedValues);
+        assertStoredValuesInUriMatchExactly(resolver, uri, null, null, null, null, false, expectedValues);
     }
 
     /**
@@ -156,15 +156,21 @@
      * @param selection - Selection string to use for the query.
      * @param selectionArgs - Selection arguments to use for the query.
      * @param sortOrder - Sort order to use for the query.
+     * @param inOrder Whether or not the returned rows in the cursor should correspond to the
+     * order of the provided ContentValues
      * @param expectedValues - Array of {@link ContentValues} which the cursor returned from the
      * query should contain.
      */
-    public static void assertStoredValuesInUriMatchExactly(ContentResolver resolver, Uri uri, String[] projection,
-            String selection, String[] selectionArgs, String sortOrder,
-            ContentValues... expectedValues) {
+    public static void assertStoredValuesInUriMatchExactly(ContentResolver resolver, Uri uri,
+            String[] projection, String selection, String[] selectionArgs, String sortOrder,
+            boolean inOrder, ContentValues... expectedValues) {
         final Cursor cursor = resolver.query(uri, projection, selection, selectionArgs, sortOrder);
         try {
-            assertCursorValuesMatchExactly(cursor, expectedValues);
+            if (inOrder) {
+                assertCursorValuesMatchExactlyInOrder(cursor, expectedValues);
+            } else {
+                assertCursorValuesMatchExactly(cursor, expectedValues);
+            }
         } finally {
             cursor.close();
         }
@@ -205,6 +211,29 @@
         }
     }
 
+    /**
+     * Ensures that the rows in the cursor match the rows in the expected values exactly. Requires
+     * that the rows in the cursor are ordered the same way as those in the expected values.
+     *
+     * @param cursor - Cursor containing the values to check for
+     * @param expectedValues - Array of ContentValues that the cursor should be expected to
+     * contain.
+     */
+    public static void assertCursorValuesMatchExactlyInOrder(Cursor cursor,
+            ContentValues... expectedValues) {
+        Assert.assertEquals("Cursor does not contain the number of expected rows",
+                expectedValues.length, cursor.getCount());
+        StringBuilder message = new StringBuilder();
+
+        cursor.moveToPosition(-1);
+        for (ContentValues v : expectedValues) {
+            cursor.moveToNext();
+            Assert.assertTrue("Expected values can not be found " + v + "," + message.toString(),
+                    equalsWithExpectedValues(cursor, v, message));
+        }
+    }
+
+
     private static boolean equalsWithExpectedValues(Cursor cursor, ContentValues expectedValues,
             StringBuilder msgBuffer) {
         for (String column : expectedValues.keySet()) {
diff --git a/tests/tests/provider/src/android/provider/cts/contacts/DeletedContactUtil.java b/tests/tests/provider/src/android/provider/cts/contacts/DeletedContactUtil.java
index 692570a..3b05cf9 100644
--- a/tests/tests/provider/src/android/provider/cts/contacts/DeletedContactUtil.java
+++ b/tests/tests/provider/src/android/provider/cts/contacts/DeletedContactUtil.java
@@ -38,8 +38,13 @@
         };
         Uri uri = ContentUris.withAppendedId(URI, contactId);
         Cursor cursor = resolver.query(uri, projection, null, null, null);
-        if (cursor.moveToNext()) {
-            return cursor.getLong(0);
+        if (null != cursor) {
+           long deletedTime = -1;
+           if (cursor.moveToNext()) {
+               deletedTime = cursor.getLong(0);
+               cursor.close();
+               return deletedTime;
+           }
         }
         return CommonDatabaseUtils.NOT_FOUND;
     }
diff --git a/tests/tests/renderscript/Android.mk b/tests/tests/renderscript/Android.mk
index 77bef50..245c5b9 100644
--- a/tests/tests/renderscript/Android.mk
+++ b/tests/tests/renderscript/Android.mk
@@ -22,18 +22,18 @@
 # Don't include this package in any target.
 LOCAL_MODULE_TAGS := optional
 
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
 # When built, explicitly put it in the data partition.
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-# All tests should include android.test.runner.
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_JNI_SHARED_LIBRARIES := libcoremathtestcpp_jni
 
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_INSTRUMENTATION_FOR := CtsTestStubs
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
 LOCAL_SDK_VERSION := current
 
 include $(BUILD_CTS_PACKAGE)
+include $(LOCAL_PATH)/libcoremathtestcpp/Android.mk
diff --git a/tests/tests/renderscript/AndroidManifest.xml b/tests/tests/renderscript/AndroidManifest.xml
index 49fca1e..b9405ca 100644
--- a/tests/tests/renderscript/AndroidManifest.xml
+++ b/tests/tests/renderscript/AndroidManifest.xml
@@ -27,9 +27,12 @@
     </application>
 
     <!-- This is a self-instrumenting test package. -->
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="com.android.cts.stub"
-                     android:label="CTS tests of Renderscript component"/>
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.renderscript"
+                     android:label="CTS tests of Renderscript component">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/tests/renderscript/libcoremathtestcpp/Android.mk b/tests/tests/renderscript/libcoremathtestcpp/Android.mk
new file mode 100644
index 0000000..7ec8671
--- /dev/null
+++ b/tests/tests/renderscript/libcoremathtestcpp/Android.mk
@@ -0,0 +1,31 @@
+# Copyright (C) 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# This is the shared library included by the JNI test app.
+#
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+LOCAL_MODULE := libcoremathtestcpp_jni
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES := CoreMathTestJni.cpp
+
+LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
+LOCAL_C_INCLUDES += frameworks/rs/cpp
+LOCAL_C_INCLUDES += frameworks/rs
+LOCAL_C_INCLUDES += external/stlport/stlport bionic/ bionic/libstdc++/include
+
+LOCAL_SHARED_LIBRARIES := libdl liblog libRScpp libstlport
+LOCAL_STATIC_LIBRARIES := libcutils
+include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/renderscript/libcoremathtestcpp/CoreMathTestJni.cpp b/tests/tests/renderscript/libcoremathtestcpp/CoreMathTestJni.cpp
new file mode 100644
index 0000000..8fd3747
--- /dev/null
+++ b/tests/tests/renderscript/libcoremathtestcpp/CoreMathTestJni.cpp
@@ -0,0 +1,819 @@
+/*
+ * 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 <jni.h>
+#include <android/log.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <algorithm>
+#include <math.h>
+#include <string>
+
+#include <RenderScript.h>
+
+#define LOG_TAG "rscpptest"
+#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
+#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+
+using namespace android::RSC;
+
+/* This class helps return multiple values to Java.  To use:
+ * - define a class in Java,
+ * - have the jni method return a jobject,
+ * - create an instance of this class,
+ * - use Set* to fill the fields,
+ * - return getObject() on exit of the JNI method.
+ */
+class JavaStruct {
+private:
+    JNIEnv* mEnv;
+    jclass mClass;
+    jobject mObject;
+
+    /* Returns the id of the named field.  Type is one of "F" (float) or "I" (int).
+     * If there's an error, logs a message and returns 0.
+     */
+    jfieldID GetFieldId(const char* name, const char* type);
+
+public:
+    // Creates an instance of the named Java class.
+    JavaStruct(JNIEnv* env, const std::string& name);
+    // Sets the field of the instance.
+    void SetFloat(const char* name, float value);
+    void SetInt(const char* name, int value);
+    // Returns the instance.
+    jobject getObject() { return mObject; }
+};
+
+JavaStruct::JavaStruct(JNIEnv* env, const std::string& name) : mEnv(env), mClass(0), mObject(0) {
+    /* This creates an instance of the specified static inner class of CoreMathVerifier.
+     * To convert this to return a non-static inner class instead, pass
+     * "(Landroid/renderscript/cts/CoreMathVerifier;)V" instead of "()V" go getMethodID
+     * and pass the parent class as a third argument to NewObject.
+     */
+    std::string fullName = "android/renderscript/cts/CoreMathVerifier$" + name;
+    mClass = env->FindClass(fullName.c_str());
+    if (!mClass) {
+        LOGE("Can't find the Java class %s", name.c_str());
+        return;
+    }
+    jmethodID constructor = env->GetMethodID(mClass, "<init>", "()V");
+    if (!constructor) {
+        LOGE("Can't find the constructor of %s", name.c_str());
+        return;
+    }
+    mObject = env->NewObject(mClass, constructor);
+    if (!mObject) {
+        LOGE("Can't construct a %s", name.c_str());
+    }
+}
+
+void JavaStruct::SetInt(const char* name, int value) {
+    jfieldID fieldId = GetFieldId(name, "I");
+    if (fieldId) {
+        mEnv->SetIntField(mObject, fieldId, value);
+    }
+}
+
+void JavaStruct::SetFloat(const char* name, float value) {
+    jfieldID fieldId = GetFieldId(name, "F");
+    if (fieldId) {
+        mEnv->SetFloatField(mObject, fieldId, value);
+    }
+}
+
+jfieldID JavaStruct::GetFieldId(const char* name, const char* type) {
+    if (!mClass) {
+        return 0;  // We already have logged the error in the constructor.
+    }
+    jfieldID fieldId = mEnv->GetFieldID(mClass, name, type);
+    if (!fieldId) {
+        LOGE("Can't find the field %s", name);
+        return 0;
+    }
+    return fieldId;
+}
+
+/* We provide access to many primitive math functions because:
+ * - not all functions are available in Java, notably gamma and erf,
+ * - Java lacks float version of these functions, so we can compare implementations with
+ *   similar constraints, and
+ * - handling unsigned integers, especially longs, is painful and error prone in Java.
+ */
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_acos(JNIEnv*, jclass, jfloat x) {
+    return acosf(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_acosh(JNIEnv*, jclass, jfloat x) {
+    return acoshf(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_asin(JNIEnv*, jclass, jfloat x) {
+    return asinf(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_asinh(JNIEnv*, jclass, jfloat x) {
+    return asinhf(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_atan(JNIEnv*, jclass, jfloat x) {
+    return atanf(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_atan2(JNIEnv*, jclass, jfloat x, jfloat y) {
+    return atan2f(x, y);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_atanh(JNIEnv*, jclass, jfloat x) {
+    return atanhf(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_cbrt(JNIEnv*, jclass, jfloat x) {
+    return cbrtf(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_ceil(JNIEnv*, jclass, jfloat x) {
+    return ceilf(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_cos(JNIEnv*, jclass, jfloat x) {
+    return cosf(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_cosh(JNIEnv*, jclass, jfloat x) {
+    return coshf(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_erf(JNIEnv*, jclass, jfloat x) {
+    return erff(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_erfc(JNIEnv*, jclass, jfloat x) {
+    return erfcf(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_exp(JNIEnv*, jclass, jfloat x) {
+    return expf(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_exp10(JNIEnv*, jclass, jfloat x) {
+    return powf(10.0f, x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_exp2(JNIEnv*, jclass, jfloat x) {
+    return powf(2.0f, x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_expm1(JNIEnv*, jclass, jfloat x) {
+    return expm1f(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_floor(JNIEnv*, jclass, jfloat x) {
+    return floorf(x);
+}
+
+extern "C" JNIEXPORT jobject JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_frexp(JNIEnv* env, jclass, jfloat x) {
+    JavaStruct result(env, "FrexpResult");
+    int exp = 0;
+    result.SetFloat("significand", frexpf(x, &exp));
+    result.SetInt("exponent", exp);
+    return result.getObject();
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_hypot(JNIEnv*, jclass, jfloat x, jfloat y) {
+    return hypotf(x, y);
+}
+
+extern "C" JNIEXPORT jint JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_ilogb(JNIEnv*, jclass, jfloat x) {
+    return ilogbf(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_ldexp(JNIEnv*, jclass, jfloat x, jint exp) {
+    return ldexpf(x, exp);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_lgamma(JNIEnv*, jclass, jfloat x) {
+    return lgammaf(x);
+}
+
+extern "C" JNIEXPORT jobject JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_lgamma2(JNIEnv* env, jclass, jfloat x) {
+    JavaStruct result(env, "LgammaResult");
+    int sign = 0;
+    result.SetFloat("lgamma", lgammaf_r(x, &sign));
+    result.SetInt("gammaSign", sign);
+    return result.getObject();
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_log(JNIEnv*, jclass, jfloat x) {
+    return logf(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_logb(JNIEnv*, jclass, jfloat x) {
+    return logbf(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_log10(JNIEnv*, jclass, jfloat x) {
+    return log10f(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_log1p(JNIEnv*, jclass, jfloat x) {
+    return log1pf(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_log2(JNIEnv*, jclass, jfloat x) {
+    return log2f(x);
+}
+
+extern "C" JNIEXPORT jbyte JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_maxI8(JNIEnv*, jclass, jbyte x, jbyte y) {
+    return std::max(x, y);
+}
+
+extern "C" JNIEXPORT jbyte JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_maxU8(JNIEnv*, jclass, jbyte x, jbyte y) {
+    return std::max((uint8_t)x, (uint8_t)y);
+}
+
+extern "C" JNIEXPORT jshort JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_maxI16(JNIEnv*, jclass, jshort x, jshort y) {
+    return std::max(x, y);
+}
+
+extern "C" JNIEXPORT jshort JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_maxU16(JNIEnv*, jclass, jshort x, jshort y) {
+    return std::max((uint16_t)x, (uint16_t)y);
+}
+
+extern "C" JNIEXPORT jint JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_maxI32(JNIEnv*, jclass, jint x, jint y) {
+    return std::max(x, y);
+}
+
+extern "C" JNIEXPORT jint JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_maxU32(JNIEnv*, jclass, jint x, jint y) {
+    return std::max((uint32_t)x, (uint32_t)y);
+}
+
+extern "C" JNIEXPORT jlong JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_maxI64(JNIEnv*, jclass, jlong x, jlong y) {
+    return std::max(x, y);
+}
+
+extern "C" JNIEXPORT jlong JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_maxU64(JNIEnv*, jclass, jlong x, jlong y) {
+    return std::max((uint64_t)x, (uint64_t)y);
+}
+
+extern "C" JNIEXPORT jbyte JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_minI8(JNIEnv*, jclass, jbyte x, jbyte y) {
+    return std::min(x, y);
+}
+
+extern "C" JNIEXPORT jbyte JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_minU8(JNIEnv*, jclass, jbyte x, jbyte y) {
+    return std::min((uint8_t)x, (uint8_t)y);
+}
+
+extern "C" JNIEXPORT jshort JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_minI16(JNIEnv*, jclass, jshort x, jshort y) {
+    return std::min(x, y);
+}
+
+extern "C" JNIEXPORT jshort JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_minU16(JNIEnv*, jclass, jshort x, jshort y) {
+    return std::min((uint16_t)x, (uint16_t)y);
+}
+
+extern "C" JNIEXPORT jint JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_minI32(JNIEnv*, jclass, jint x, jint y) {
+    return std::min(x, y);
+}
+
+extern "C" JNIEXPORT jint JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_minU32(JNIEnv*, jclass, jint x, jint y) {
+    return std::min((uint32_t)x, (uint32_t)y);
+}
+
+extern "C" JNIEXPORT jlong JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_minI64(JNIEnv*, jclass, jlong x, jlong y) {
+    return std::min(x, y);
+}
+
+extern "C" JNIEXPORT jlong JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_minU64(JNIEnv*, jclass, jlong x, jlong y) {
+    return std::min((uint64_t)x, (uint64_t)y);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_pow(JNIEnv*, jclass, jfloat x, jfloat y) {
+    return powf(x, y);
+}
+
+extern "C" JNIEXPORT jobject JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_remquo(JNIEnv* env, jclass, jfloat numerator,
+                                                      jfloat denominator) {
+    JavaStruct result(env, "RemquoResult");
+    int quotient = 0;
+    result.SetFloat("remainder", remquof(numerator, denominator, &quotient));
+    result.SetInt("quotient", quotient);
+    return result.getObject();
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_rint(JNIEnv*, jclass, jfloat x) {
+    return rintf(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_round(JNIEnv*, jclass, jfloat x) {
+    return roundf(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_sin(JNIEnv*, jclass, jfloat x) {
+    return sinf(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_sinh(JNIEnv*, jclass, jfloat x) {
+    return sinhf(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_sqrt(JNIEnv*, jclass, jfloat x) {
+    return sqrtf(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_tan(JNIEnv*, jclass, jfloat x) {
+    return tanf(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_tanh(JNIEnv*, jclass, jfloat x) {
+    return tanhf(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_tgamma(JNIEnv*, jclass, jfloat x) {
+    return tgammaf(x);
+}
+
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_trunc(JNIEnv*, jclass, jfloat x) {
+    return truncf(x);
+}
+
+extern "C" JNIEXPORT jbyte JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertCharToChar(JNIEnv*, jclass, jbyte x) {
+    return (jbyte)(int8_t)(int8_t)x;
+}
+extern "C" JNIEXPORT jbyte JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertCharToUchar(JNIEnv*, jclass, jbyte x) {
+    return (jbyte)(uint8_t)(int8_t)x;
+}
+extern "C" JNIEXPORT jshort JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertCharToShort(JNIEnv*, jclass, jbyte x) {
+    return (jshort)(int16_t)(int8_t)x;
+}
+extern "C" JNIEXPORT jshort JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertCharToUshort(JNIEnv*, jclass, jbyte x) {
+    return (jshort)(uint16_t)(int8_t)x;
+}
+extern "C" JNIEXPORT jint JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertCharToInt(JNIEnv*, jclass, jbyte x) {
+    return (jint)(int32_t)(int8_t)x;
+}
+extern "C" JNIEXPORT jint JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertCharToUint(JNIEnv*, jclass, jbyte x) {
+    return (jint)(uint32_t)(int8_t)x;
+}
+extern "C" JNIEXPORT jlong JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertCharToLong(JNIEnv*, jclass, jbyte x) {
+    return (jlong)(int64_t)(int8_t)x;
+}
+extern "C" JNIEXPORT jlong JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertCharToUlong(JNIEnv*, jclass, jbyte x) {
+    return (jlong)(uint64_t)(int8_t)x;
+}
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertCharToFloat(JNIEnv*, jclass, jbyte x) {
+    return (jfloat)(float)(int8_t)x;
+}
+extern "C" JNIEXPORT jdouble JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertCharToDouble(JNIEnv*, jclass, jbyte x) {
+    return (jdouble)(double)(int8_t)x;
+}
+
+extern "C" JNIEXPORT jbyte JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUcharToChar(JNIEnv*, jclass, jbyte x) {
+    return (jbyte)(int8_t)(uint8_t)x;
+}
+extern "C" JNIEXPORT jbyte JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUcharToUchar(JNIEnv*, jclass, jbyte x) {
+    return (jbyte)(uint8_t)(uint8_t)x;
+}
+extern "C" JNIEXPORT jshort JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUcharToShort(JNIEnv*, jclass, jbyte x) {
+    return (jshort)(int16_t)(uint8_t)x;
+}
+extern "C" JNIEXPORT jshort JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUcharToUshort(JNIEnv*, jclass, jbyte x) {
+    return (jshort)(uint16_t)(uint8_t)x;
+}
+extern "C" JNIEXPORT jint JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUcharToInt(JNIEnv*, jclass, jbyte x) {
+    return (jint)(int32_t)(uint8_t)x;
+}
+extern "C" JNIEXPORT jint JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUcharToUint(JNIEnv*, jclass, jbyte x) {
+    return (jint)(uint32_t)(uint8_t)x;
+}
+extern "C" JNIEXPORT jlong JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUcharToLong(JNIEnv*, jclass, jbyte x) {
+    return (jlong)(int64_t)(uint8_t)x;
+}
+extern "C" JNIEXPORT jlong JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUcharToUlong(JNIEnv*, jclass, jbyte x) {
+    return (jlong)(uint64_t)(uint8_t)x;
+}
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUcharToFloat(JNIEnv*, jclass, jbyte x) {
+    return (jfloat)(float)(uint8_t)x;
+}
+extern "C" JNIEXPORT jdouble JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUcharToDouble(JNIEnv*, jclass, jbyte x) {
+    return (jdouble)(double)(uint8_t)x;
+}
+
+extern "C" JNIEXPORT jbyte JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertShortToChar(JNIEnv*, jclass, jshort x) {
+    return (jbyte)(int8_t)(int16_t)x;
+}
+extern "C" JNIEXPORT jbyte JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertShortToUchar(JNIEnv*, jclass, jshort x) {
+    return (jbyte)(uint8_t)(int16_t)x;
+}
+extern "C" JNIEXPORT jshort JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertShortToShort(JNIEnv*, jclass, jshort x) {
+    return (jshort)(int16_t)(int16_t)x;
+}
+extern "C" JNIEXPORT jshort JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertShortToUshort(JNIEnv*, jclass, jshort x) {
+    return (jshort)(uint16_t)(int16_t)x;
+}
+extern "C" JNIEXPORT jint JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertShortToInt(JNIEnv*, jclass, jshort x) {
+    return (jint)(int32_t)(int16_t)x;
+}
+extern "C" JNIEXPORT jint JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertShortToUint(JNIEnv*, jclass, jshort x) {
+    return (jint)(uint32_t)(int16_t)x;
+}
+extern "C" JNIEXPORT jlong JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertShortToLong(JNIEnv*, jclass, jshort x) {
+    return (jlong)(int64_t)(int16_t)x;
+}
+extern "C" JNIEXPORT jlong JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertShortToUlong(JNIEnv*, jclass, jshort x) {
+    return (jlong)(uint64_t)(int16_t)x;
+}
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertShortToFloat(JNIEnv*, jclass, jshort x) {
+    return (jfloat)(float)(int16_t)x;
+}
+extern "C" JNIEXPORT jdouble JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertShortToDouble(JNIEnv*, jclass, jshort x) {
+    return (jdouble)(double)(int16_t)x;
+}
+
+extern "C" JNIEXPORT jbyte JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUshortToChar(JNIEnv*, jclass, jshort x) {
+    return (jbyte)(int8_t)(uint16_t)x;
+}
+extern "C" JNIEXPORT jbyte JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUshortToUchar(JNIEnv*, jclass, jshort x) {
+    return (jbyte)(uint8_t)(uint16_t)x;
+}
+extern "C" JNIEXPORT jshort JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUshortToShort(JNIEnv*, jclass, jshort x) {
+    return (jshort)(int16_t)(uint16_t)x;
+}
+extern "C" JNIEXPORT jshort JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUshortToUshort(JNIEnv*, jclass, jshort x) {
+    return (jshort)(uint16_t)(uint16_t)x;
+}
+extern "C" JNIEXPORT jint JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUshortToInt(JNIEnv*, jclass, jshort x) {
+    return (jint)(int32_t)(uint16_t)x;
+}
+extern "C" JNIEXPORT jint JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUshortToUint(JNIEnv*, jclass, jshort x) {
+    return (jint)(uint32_t)(uint16_t)x;
+}
+extern "C" JNIEXPORT jlong JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUshortToLong(JNIEnv*, jclass, jshort x) {
+    return (jlong)(int64_t)(uint16_t)x;
+}
+extern "C" JNIEXPORT jlong JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUshortToUlong(JNIEnv*, jclass, jshort x) {
+    return (jlong)(uint64_t)(uint16_t)x;
+}
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUshortToFloat(JNIEnv*, jclass, jshort x) {
+    return (jfloat)(float)(uint16_t)x;
+}
+extern "C" JNIEXPORT jdouble JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUshortToDouble(JNIEnv*, jclass, jshort x) {
+    return (jdouble)(double)(uint16_t)x;
+}
+
+extern "C" JNIEXPORT jbyte JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertIntToChar(JNIEnv*, jclass, jint x) {
+    return (jbyte)(int8_t)(int32_t)x;
+}
+extern "C" JNIEXPORT jbyte JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertIntToUchar(JNIEnv*, jclass, jint x) {
+    return (jbyte)(uint8_t)(int32_t)x;
+}
+extern "C" JNIEXPORT jshort JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertIntToShort(JNIEnv*, jclass, jint x) {
+    return (jshort)(int16_t)(int32_t)x;
+}
+extern "C" JNIEXPORT jshort JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertIntToUshort(JNIEnv*, jclass, jint x) {
+    return (jshort)(uint16_t)(int32_t)x;
+}
+extern "C" JNIEXPORT jint JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertIntToInt(JNIEnv*, jclass, jint x) {
+    return (jint)(int32_t)(int32_t)x;
+}
+extern "C" JNIEXPORT jint JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertIntToUint(JNIEnv*, jclass, jint x) {
+    return (jint)(uint32_t)(int32_t)x;
+}
+extern "C" JNIEXPORT jlong JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertIntToLong(JNIEnv*, jclass, jint x) {
+    return (jlong)(int64_t)(int32_t)x;
+}
+extern "C" JNIEXPORT jlong JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertIntToUlong(JNIEnv*, jclass, jint x) {
+    return (jlong)(uint64_t)(int32_t)x;
+}
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertIntToFloat(JNIEnv*, jclass, jint x) {
+    return (jfloat)(float)(int32_t)x;
+}
+extern "C" JNIEXPORT jdouble JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertIntToDouble(JNIEnv*, jclass, jint x) {
+    return (jdouble)(double)(int32_t)x;
+}
+
+extern "C" JNIEXPORT jbyte JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUintToChar(JNIEnv*, jclass, jint x) {
+    return (jbyte)(int8_t)(uint32_t)x;
+}
+extern "C" JNIEXPORT jbyte JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUintToUchar(JNIEnv*, jclass, jint x) {
+    return (jbyte)(uint8_t)(uint32_t)x;
+}
+extern "C" JNIEXPORT jshort JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUintToShort(JNIEnv*, jclass, jint x) {
+    return (jshort)(int16_t)(uint32_t)x;
+}
+extern "C" JNIEXPORT jshort JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUintToUshort(JNIEnv*, jclass, jint x) {
+    return (jshort)(uint16_t)(uint32_t)x;
+}
+extern "C" JNIEXPORT jint JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUintToInt(JNIEnv*, jclass, jint x) {
+    return (jint)(int32_t)(uint32_t)x;
+}
+extern "C" JNIEXPORT jint JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUintToUint(JNIEnv*, jclass, jint x) {
+    return (jint)(uint32_t)(uint32_t)x;
+}
+extern "C" JNIEXPORT jlong JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUintToLong(JNIEnv*, jclass, jint x) {
+    return (jlong)(int64_t)(uint32_t)x;
+}
+extern "C" JNIEXPORT jlong JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUintToUlong(JNIEnv*, jclass, jint x) {
+    return (jlong)(uint64_t)(uint32_t)x;
+}
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUintToFloat(JNIEnv*, jclass, jint x) {
+    return (jfloat)(float)(uint32_t)x;
+}
+extern "C" JNIEXPORT jdouble JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUintToDouble(JNIEnv*, jclass, jint x) {
+    return (jdouble)(double)(uint32_t)x;
+}
+
+extern "C" JNIEXPORT jbyte JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertLongToChar(JNIEnv*, jclass, jlong x) {
+    return (jbyte)(int8_t)(int64_t)x;
+}
+extern "C" JNIEXPORT jbyte JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertLongToUchar(JNIEnv*, jclass, jlong x) {
+    return (jbyte)(uint8_t)(int64_t)x;
+}
+extern "C" JNIEXPORT jshort JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertLongToShort(JNIEnv*, jclass, jlong x) {
+    return (jshort)(int16_t)(int64_t)x;
+}
+extern "C" JNIEXPORT jshort JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertLongToUshort(JNIEnv*, jclass, jlong x) {
+    return (jshort)(uint16_t)(int64_t)x;
+}
+extern "C" JNIEXPORT jint JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertLongToInt(JNIEnv*, jclass, jlong x) {
+    return (jint)(int32_t)(int64_t)x;
+}
+extern "C" JNIEXPORT jint JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertLongToUint(JNIEnv*, jclass, jlong x) {
+    return (jint)(uint32_t)(int64_t)x;
+}
+extern "C" JNIEXPORT jlong JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertLongToLong(JNIEnv*, jclass, jlong x) {
+    return (jlong)(int64_t)(int64_t)x;
+}
+extern "C" JNIEXPORT jlong JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertLongToUlong(JNIEnv*, jclass, jlong x) {
+    return (jlong)(uint64_t)(int64_t)x;
+}
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertLongToFloat(JNIEnv*, jclass, jlong x) {
+    return (jfloat)(float)(int64_t)x;
+}
+extern "C" JNIEXPORT jdouble JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertLongToDouble(JNIEnv*, jclass, jlong x) {
+    return (jdouble)(double)(int64_t)x;
+}
+
+extern "C" JNIEXPORT jbyte JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUlongToChar(JNIEnv*, jclass, jlong x) {
+    return (jbyte)(int8_t)(uint64_t)x;
+}
+extern "C" JNIEXPORT jbyte JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUlongToUchar(JNIEnv*, jclass, jlong x) {
+    return (jbyte)(uint8_t)(uint64_t)x;
+}
+extern "C" JNIEXPORT jshort JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUlongToShort(JNIEnv*, jclass, jlong x) {
+    return (jshort)(int16_t)(uint64_t)x;
+}
+extern "C" JNIEXPORT jshort JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUlongToUshort(JNIEnv*, jclass, jlong x) {
+    return (jshort)(uint16_t)(uint64_t)x;
+}
+extern "C" JNIEXPORT jint JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUlongToInt(JNIEnv*, jclass, jlong x) {
+    return (jint)(int32_t)(uint64_t)x;
+}
+extern "C" JNIEXPORT jint JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUlongToUint(JNIEnv*, jclass, jlong x) {
+    return (jint)(uint32_t)(uint64_t)x;
+}
+extern "C" JNIEXPORT jlong JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUlongToLong(JNIEnv*, jclass, jlong x) {
+    return (jlong)(int64_t)(uint64_t)x;
+}
+extern "C" JNIEXPORT jlong JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUlongToUlong(JNIEnv*, jclass, jlong x) {
+    return (jlong)(uint64_t)(uint64_t)x;
+}
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUlongToFloat(JNIEnv*, jclass, jlong x) {
+    return (jfloat)(float)(uint64_t)x;
+}
+extern "C" JNIEXPORT jdouble JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertUlongToDouble(JNIEnv*, jclass, jlong x) {
+    return (jdouble)(double)(uint64_t)x;
+}
+
+extern "C" JNIEXPORT jbyte JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertFloatToChar(JNIEnv*, jclass, jfloat x) {
+    return (jbyte)(int8_t)(float)x;
+}
+extern "C" JNIEXPORT jbyte JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertFloatToUchar(JNIEnv*, jclass, jfloat x) {
+    return (jbyte)(uint8_t)(float)x;
+}
+extern "C" JNIEXPORT jshort JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertFloatToShort(JNIEnv*, jclass, jfloat x) {
+    return (jshort)(int16_t)(float)x;
+}
+extern "C" JNIEXPORT jshort JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertFloatToUshort(JNIEnv*, jclass, jfloat x) {
+    return (jshort)(uint16_t)(float)x;
+}
+extern "C" JNIEXPORT jint JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertFloatToInt(JNIEnv*, jclass, jfloat x) {
+    return (jint)(int32_t)(float)x;
+}
+extern "C" JNIEXPORT jint JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertFloatToUint(JNIEnv*, jclass, jfloat x) {
+    return (jint)(uint32_t)(float)x;
+}
+extern "C" JNIEXPORT jlong JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertFloatToLong(JNIEnv*, jclass, jfloat x) {
+    return (jlong)(int64_t)(float)x;
+}
+extern "C" JNIEXPORT jlong JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertFloatToUlong(JNIEnv*, jclass, jfloat x) {
+    return (jlong)(uint64_t)(float)x;
+}
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertFloatToFloat(JNIEnv*, jclass, jfloat x) {
+    return (jfloat)(float)(float)x;
+}
+extern "C" JNIEXPORT jdouble JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertFloatToDouble(JNIEnv*, jclass, jfloat x) {
+    return (jdouble)(double)(float)x;
+}
+
+extern "C" JNIEXPORT jbyte JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertDoubleToChar(JNIEnv*, jclass, jdouble x) {
+    return (jbyte)(int8_t)(double)x;
+}
+extern "C" JNIEXPORT jbyte JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertDoubleToUchar(JNIEnv*, jclass, jdouble x) {
+    return (jbyte)(uint8_t)(double)x;
+}
+extern "C" JNIEXPORT jshort JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertDoubleToShort(JNIEnv*, jclass, jdouble x) {
+    return (jshort)(int16_t)(double)x;
+}
+extern "C" JNIEXPORT jshort JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertDoubleToUshort(JNIEnv*, jclass, jdouble x) {
+    return (jshort)(uint16_t)(double)x;
+}
+extern "C" JNIEXPORT jint JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertDoubleToInt(JNIEnv*, jclass, jdouble x) {
+    return (jint)(int32_t)(double)x;
+}
+extern "C" JNIEXPORT jint JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertDoubleToUint(JNIEnv*, jclass, jdouble x) {
+    return (jint)(uint32_t)(double)x;
+}
+extern "C" JNIEXPORT jlong JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertDoubleToLong(JNIEnv*, jclass, jdouble x) {
+    return (jlong)(int64_t)(double)x;
+}
+extern "C" JNIEXPORT jlong JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertDoubleToUlong(JNIEnv*, jclass, jdouble x) {
+    return (jlong)(uint64_t)(double)x;
+}
+extern "C" JNIEXPORT jfloat JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertDoubleToFloat(JNIEnv*, jclass, jdouble x) {
+    return (jfloat)(float)(double)x;
+}
+extern "C" JNIEXPORT jdouble JNICALL
+Java_android_renderscript_cts_CoreMathVerifier_convertDoubleToDouble(JNIEnv*, jclass, jdouble x) {
+    return (jdouble)(double)(double)x;
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/AcosPiTest.java b/tests/tests/renderscript/src/android/renderscript/cts/AcosPiTest.java
deleted file mode 100644
index 9d0bc7d..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/AcosPiTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-
-public class AcosPiTest extends RSBaseCompute {
-    private ScriptC_acospi_f32 script_f32;
-    private ScriptC_acospi_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_acospi_f32(mRS);
-        script_f32_relaxed = new ScriptC_acospi_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_acospi_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_acospi_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_acospi_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_acospi_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_acospi_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_acospi_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_acospi_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_acospi_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)(Math.acos((double)in[idx])/Math.PI);
-            }
-        }
-        return ref;
-    }
-
-    public void testAcosPiF32() {
-        doF32(0xe1, 5);
-    }
-
-    public void testAcosPiF32_relaxed() {
-        doF32_relaxed(0xe1, 128);
-    }
-
-    public void testAcosPiF32_2() {
-        doF32_2(0xa123, 5);
-    }
-
-    public void testAcosPiF32_2_relaxed() {
-        doF32_2_relaxed(0xa123, 128);
-    }
-
-    public void testAcosPiF32_3() {
-        doF32_3(0x123, 5);
-    }
-
-    public void testAcosPiF32_3_relaxed() {
-        doF32_3_relaxed(0x123, 128);
-    }
-
-    public void testAcosPiF32_4() {
-        doF32_4(0x123ef, 5);
-
-    }
-    public void testAcosPiF32_4_relaxed() {
-        doF32_4_relaxed(0x123ef, 128);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/AcosTest.java b/tests/tests/renderscript/src/android/renderscript/cts/AcosTest.java
deleted file mode 100644
index d540c60..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/AcosTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-
-public class AcosTest extends RSBaseCompute {
-    private ScriptC_acos_f32 script_f32;
-    private ScriptC_acos_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_acos_f32(mRS);
-        script_f32_relaxed = new ScriptC_acos_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_acos_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_acos_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_acos_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_acos_f32_4(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32:
-            script_f32.forEach_acos_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32.forEach_acos_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32.forEach_acos_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32.forEach_acos_f32_4(mIn, mOut);
-            break;
-
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)(Math.acos((double)in[idx]));
-            }
-        }
-        return ref;
-    }
-
-    public void testAcosF32() {
-        doF32(0x123e, 4);
-    }
-
-    public void testAcosF32_2() {
-        doF32_2(0x1e, 4);
-    }
-
-    public void testAcosF32_3() {
-        doF32_3(0xeaf, 4);
-    }
-
-    public void testAcosF32_4() {
-        doF32_4(0x123, 4);
-    }
-
-    public void testAcosF32_relaxed() {
-        doF32_relaxed(0x123e, 128);
-    }
-
-    public void testAcosF32_2_relaxed() {
-        doF32_2_relaxed(0x1e, 128);
-    }
-
-    public void testAcosF32_3_relaxed() {
-        doF32_3_relaxed(0xeaf, 128);
-    }
-
-    public void testAcosF32_4_relaxed() {
-        doF32_4_relaxed(0x123, 128);
-    }
-
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/AcoshTest.java b/tests/tests/renderscript/src/android/renderscript/cts/AcoshTest.java
deleted file mode 100644
index 5947066..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/AcoshTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-
-public class AcoshTest extends RSBaseCompute {
-    private ScriptC_acosh_f32 script_f32;
-    private ScriptC_acosh_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_acosh_f32(mRS);
-        script_f32_relaxed = new ScriptC_acosh_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_acosh_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_acosh_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_acosh_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_acosh_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_acosh_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_acosh_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_acosh_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_acosh_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                double x = (double)in[idx];
-                ref[idxRef] = (float)(2*Math.log(Math.sqrt((x+1)/2) + Math.sqrt((x-1)/2)));
-            }
-        }
-        return ref;
-    }
-
-    public void testAcoshF32() {
-        doF32(0x12345678, 4);
-    }
-
-    public void testAcoshF32_relaxed() {
-        doF32_relaxed(0x12345678, 4);
-    }
-
-    public void testAcoshF32_2() {
-        doF32_2(0x1234ac, 4);
-    }
-
-    public void testAcoshF32_2_relaxed() {
-        doF32_2_relaxed(0x1234ac, 4);
-    }
-
-    public void testAcoshF32_3() {
-        doF32_3(0x123fc78, 4);
-    }
-
-    public void testAcoshF32_3_relaxed() {
-        doF32_3_relaxed(0x123fc78, 4);
-    }
-
-    public void testAcoshF32_4() {
-        doF32_4(0x12def8, 4);
-
-    }
-    public void testAcoshF32_4_relaxed() {
-        doF32_4_relaxed(0x12def8, 4);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/AllocationCopy2DRangeTest.java b/tests/tests/renderscript/src/android/renderscript/cts/AllocationCopy2DRangeTest.java
index b032fd4..a549906 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/AllocationCopy2DRangeTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/AllocationCopy2DRangeTest.java
@@ -20,7 +20,6 @@
 import android.renderscript.Element;
 import android.renderscript.Type;
 import java.util.Random;
-import com.android.cts.stub.R;
 
 public class AllocationCopy2DRangeTest extends RSBaseCompute {
     private Allocation mInAllocation;
@@ -28,7 +27,7 @@
 
     public void testAllocationCopy2DRange() {
         ScriptC_allocationCopy2DRange mScript =
-                new ScriptC_allocationCopy2DRange(mRS, mRes, R.raw.allocationcopy2drange);
+                new ScriptC_allocationCopy2DRange(mRS);
         Random random = new Random(0x172d8ab9);
         int width = random.nextInt(512);
         int height = random.nextInt(512);
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/AllocationResize.java b/tests/tests/renderscript/src/android/renderscript/cts/AllocationResize.java
index 68d7274..96045af 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/AllocationResize.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/AllocationResize.java
@@ -20,7 +20,6 @@
 import android.renderscript.Allocation;
 import android.renderscript.Element;
 import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
 import java.util.Random;
 
 public class AllocationResize extends RSBaseCompute {
@@ -34,7 +33,11 @@
     }
 
     public void testResize() {
-        mScript = new ScriptC_allocation_resize(mRS, mRes, R.raw.allocation_resize);
+        if (mRS.getApplicationContext().getApplicationInfo().targetSdkVersion >= 21) {
+            return;
+        }
+
+        mScript = new ScriptC_allocation_resize(mRS);
         mIn = Allocation.createSized(mRS, Element.I32(mRS), INPUTSIZE/2);
         mOut = Allocation.createSized(mRS, Element.I32(mRS), INPUTSIZE*2);
         mIn.resize(INPUTSIZE);
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/AllocationTest.java b/tests/tests/renderscript/src/android/renderscript/cts/AllocationTest.java
index 51309c8..7e867f7 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/AllocationTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/AllocationTest.java
@@ -16,8 +16,6 @@
 
 package android.renderscript.cts;
 
-import com.android.cts.stub.R;
-
 import android.graphics.Bitmap;
 import android.renderscript.Allocation;
 import android.renderscript.AllocationAdapter;
@@ -736,7 +734,7 @@
         Allocation largeArray = Allocation.createTyped(mRS, b.setX(48).create());
         Allocation singleElement = Allocation.createTyped(mRS, b.setX(1).create());
 
-        ScriptC_setelementat script = new ScriptC_setelementat(mRS, mRes, R.raw.setelementat);
+        ScriptC_setelementat script = new ScriptC_setelementat(mRS);
 
         script.set_memset_toValue(1);
         script.forEach_memset(singleElement);
@@ -761,7 +759,7 @@
         Allocation singleElement = Allocation.createTyped(mRS, b.setX(1).create());
         Allocation largeArray = Allocation.createTyped(mRS, b.setX(48).setY(16).create());
 
-        ScriptC_setelementat script = new ScriptC_setelementat(mRS, mRes, R.raw.setelementat);
+        ScriptC_setelementat script = new ScriptC_setelementat(mRS);
 
         script.set_memset_toValue(1);
         script.forEach_memset(singleElement);
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/AsinPiTest.java b/tests/tests/renderscript/src/android/renderscript/cts/AsinPiTest.java
deleted file mode 100644
index 64a001e..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/AsinPiTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-
-public class AsinPiTest extends RSBaseCompute {
-    private ScriptC_asinpi_f32 script_f32;
-    private ScriptC_asinpi_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_asinpi_f32(mRS);
-        script_f32_relaxed = new ScriptC_asinpi_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_asinpi_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_asinpi_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_asinpi_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_asinpi_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_asinpi_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_asinpi_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_asinpi_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_asinpi_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)(Math.asin((double)in[idx])/Math.PI);
-            }
-        }
-        return ref;
-    }
-
-    public void testAsinPiF32() {
-        doF32(0xa, 5);
-    }
-
-    public void testAsinPiF32_relaxed() {
-        doF32_relaxed(0xa, 5);
-    }
-
-    public void testAsinPiF32_2() {
-        doF32_2(0xe, 5);
-    }
-
-    public void testAsinPiF32_2_relaxed() {
-        doF32_2_relaxed(0xe, 5);
-    }
-
-    public void testAsinPiF32_3() {
-        doF32_3(0x1234, 5);
-    }
-
-    public void testAsinPiF32_3_relaxed() {
-        doF32_3_relaxed(0x1234, 5);
-    }
-
-    public void testAsinPiF32_4() {
-        doF32_4(0xaf, 5);
-
-    }
-    public void testAsinPiF32_4_relaxed() {
-        doF32_4_relaxed(0xaf, 5);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/AsinTest.java b/tests/tests/renderscript/src/android/renderscript/cts/AsinTest.java
deleted file mode 100644
index 7f3c367..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/AsinTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-
-public class AsinTest extends RSBaseCompute {
-    private ScriptC_asin_f32 script_f32;
-    private ScriptC_asin_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_asin_f32(mRS);
-        script_f32_relaxed = new ScriptC_asin_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_asin_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_asin_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_asin_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_asin_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_asin_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_asin_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_asin_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_asin_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)(Math.asin((double)in[idx]));
-            }
-        }
-        return ref;
-    }
-
-    public void testAsinF32() {
-        doF32(0x12efa, 4);
-    }
-
-    public void testAsinF32_relaxed() {
-        doF32_relaxed(0x12efa, 128);
-    }
-
-    public void testAsinF32_2() {
-        doF32_2(0x34ef, 4);
-    }
-
-    public void testAsinF32_2_relaxed() {
-        doF32_2_relaxed(0x34ef, 128);
-    }
-
-    public void testAsinF32_3() {
-        doF32_3(0xae31, 4);
-    }
-
-    public void testAsinF32_3_relaxed() {
-        doF32_3_relaxed(0xae31, 128);
-    }
-
-    public void testAsinF32_4() {
-        doF32_4(0x341, 4);
-
-    }
-    public void testAsinF32_4_relaxed() {
-        doF32_4_relaxed(0x341, 128);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/AsinhTest.java b/tests/tests/renderscript/src/android/renderscript/cts/AsinhTest.java
deleted file mode 100644
index e0204d2..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/AsinhTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-
-public class AsinhTest extends RSBaseCompute {
-    private ScriptC_asinh_f32 script_f32;
-    private ScriptC_asinh_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_asinh_f32(mRS);
-        script_f32_relaxed = new ScriptC_asinh_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_asinh_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_asinh_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_asinh_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_asinh_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_asinh_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_asinh_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_asinh_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_asinh_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                double x = (double)in[idx];
-                ref[idxRef] = (float)(Math.log(x+Math.sqrt(1+Math.pow(x, 2))));
-            }
-        }
-        return ref;
-    }
-
-    public void testAsinhF32() {
-        doF32(0x12, 4);
-    }
-
-    public void testAsinhF32_relaxed() {
-        doF32_relaxed(0x12, 128);
-    }
-
-    public void testAsinhF32_2() {
-        doF32_2(0xead, 4);
-    }
-
-    public void testAsinhF32_2_relaxed() {
-        doF32_2_relaxed(0xead, 128);
-    }
-
-    public void testAsinhF32_3() {
-        doF32_3(0xabc, 4);
-    }
-
-    public void testAsinhF32_3_relaxed() {
-        doF32_3_relaxed(0xabc, 128);
-    }
-
-    public void testAsinhF32_4() {
-        doF32_4(0xfea, 4);
-
-    }
-    public void testAsinhF32_4_relaxed() {
-        doF32_4_relaxed(0xfea, 128);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/Atan2PiTest.java b/tests/tests/renderscript/src/android/renderscript/cts/Atan2PiTest.java
deleted file mode 100644
index f96e7d6..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/Atan2PiTest.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-import android.renderscript.Element;
-
-public class Atan2PiTest extends RSBaseCompute {
-    private ScriptC_atan2pi_f32 script_f32;
-    private ScriptC_atan2pi_f32_relaxed script_f32_relaxed;
-    private Allocation mIn;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_atan2pi_f32(mRS);
-        script_f32_relaxed = new ScriptC_atan2pi_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_atan2pi_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_atan2pi_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_atan2pi_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_atan2pi_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_atan2pi_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_atan2pi_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_atan2pi_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_atan2pi_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx = i * stride * 2 + j;
-                ref[i * (stride - skip) + j] = (float)(Math.atan2((double)in[idx],(double)in[idx+stride]) / Math.PI);
-            }
-        }
-        return ref;
-    }
-
-    @Override
-    protected Allocation setInAlloc(Element e) {
-        return mIn;
-    }
-
-    @Override
-    protected float[] makeInArray(int size) {
-        return new float[size*2];
-    }
-
-    public void testAtan2PiF32() {
-        ScriptField_atan2pi_float_input in = new ScriptField_atan2pi_float_input(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32(0x12678, 6);
-    }
-
-    public void testAtan2PiF32_relaxed() {
-        ScriptField_atan2pi_float_input in = new ScriptField_atan2pi_float_input(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_relaxed(0x12678, 128);
-    }
-
-    public void testAtan2PiF32_2() {
-        ScriptField_atan2pi_float2_input in = new ScriptField_atan2pi_float2_input(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_2(0x1af45, 6);
-    }
-
-    public void testAtan2PiF32_2_relaxed() {
-        ScriptField_atan2pi_float2_input in = new ScriptField_atan2pi_float2_input(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_2_relaxed(0x1af45, 128);
-    }
-
-    public void testAtan2PiF32_3() {
-        ScriptField_atan2pi_float3_input in = new ScriptField_atan2pi_float3_input(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_3(0x1cd345, 6);
-    }
-
-    public void testAtan2PiF32_3_relaxed() {
-        ScriptField_atan2pi_float3_input in = new ScriptField_atan2pi_float3_input(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_3_relaxed(0x1cd345, 128);
-    }
-
-    public void testAtan2PiF32_4() {
-        ScriptField_atan2pi_float4_input in = new ScriptField_atan2pi_float4_input(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_4(0x1ca45, 6);
-    }
-
-    public void testAtan2PiF32_4_relaxed() {
-        ScriptField_atan2pi_float4_input in = new ScriptField_atan2pi_float4_input(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_4_relaxed(0x1ca45, 128);
-    }
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/Atan2Test.java b/tests/tests/renderscript/src/android/renderscript/cts/Atan2Test.java
deleted file mode 100644
index c3eabb7..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/Atan2Test.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-import android.renderscript.Element;
-
-public class Atan2Test extends RSBaseCompute {
-    private ScriptC_atan2_f32 script_f32;
-    private ScriptC_atan2_f32_relaxed script_f32_relaxed;
-    private Allocation mIn;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_atan2_f32(mRS);
-        script_f32_relaxed = new ScriptC_atan2_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_atan2_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_atan2_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_atan2_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_atan2_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_atan2_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_atan2_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_atan2_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_atan2_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx = i * stride * 2 + j;
-                ref[i * (stride - skip) + j] = (float)Math.atan2((double)in[idx],(double)in[idx+stride]);
-            }
-        }
-        return ref;
-    }
-
-    @Override
-    protected Allocation setInAlloc(Element e) {
-        return mIn;
-    }
-
-    @Override
-    protected float[] makeInArray(int size) {
-        return new float[size*2];
-    }
-
-    public void testAtan2F32() {
-        ScriptField_atan2_f32_in in = new ScriptField_atan2_f32_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32(0x12678, 6);
-    }
-
-    public void testAtan2F32_relaxed() {
-        ScriptField_atan2_f32_in in = new ScriptField_atan2_f32_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_relaxed(0x12678, 128);
-    }
-
-    public void testAtan2F32_2() {
-        ScriptField_atan2_f32_2_in in = new ScriptField_atan2_f32_2_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_2(0x1af45, 6);
-    }
-
-    public void testAtan2F32_2_relaxed() {
-        ScriptField_atan2_f32_2_in in = new ScriptField_atan2_f32_2_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_2_relaxed(0x1af45, 128);
-    }
-
-    public void testAtan2F32_3() {
-        ScriptField_atan2_f32_3_in in = new ScriptField_atan2_f32_3_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_3(0x1cd345, 6);
-    }
-
-    public void testAtan2F32_3_relaxed() {
-        ScriptField_atan2_f32_3_in in = new ScriptField_atan2_f32_3_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_3_relaxed(0x1cd345, 128);
-    }
-
-    public void testAtan2F32_4() {
-        ScriptField_atan2_f32_4_in in = new ScriptField_atan2_f32_4_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_4(0x1ca45, 6);
-    }
-
-    public void testAtan2F32_4_relaxed() {
-        ScriptField_atan2_f32_4_in in = new ScriptField_atan2_f32_4_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_4_relaxed(0x1ca45, 128);
-    }
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/AtanPiTest.java b/tests/tests/renderscript/src/android/renderscript/cts/AtanPiTest.java
deleted file mode 100644
index 17fe5ad..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/AtanPiTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-
-public class AtanPiTest extends RSBaseCompute {
-    private ScriptC_atanpi_f32 script_f32;
-    private ScriptC_atanpi_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_atanpi_f32(mRS);
-        script_f32_relaxed = new ScriptC_atanpi_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_atanpi_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_atanpi_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_atanpi_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_atanpi_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_atanpi_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_atanpi_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_atanpi_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_atanpi_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)(Math.atan((double)in[idx])/Math.PI);
-            }
-        }
-        return ref;
-    }
-
-    public void testAtanPiF32() {
-        doF32(0x123, 5);
-    }
-
-    public void testAtanPiF32_relaxed() {
-        doF32_relaxed(0x123, 128);
-    }
-
-    public void testAtanPiF32_2() {
-        doF32_2(0x12, 5);
-    }
-
-    public void testAtanPiF32_2_relaxed() {
-        doF32_2_relaxed(0x12, 128);
-    }
-
-    public void testAtanPiF32_3() {
-        doF32_3(0x847, 5);
-    }
-
-    public void testAtanPiF32_3_relaxed() {
-        doF32_3_relaxed(0x847, 128);
-    }
-
-    public void testAtanPiF32_4() {
-        doF32_4(0xfa2, 5);
-
-    }
-    public void testAtanPiF32_4_relaxed() {
-        doF32_4_relaxed(0xfa2, 128);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/AtanTest.java b/tests/tests/renderscript/src/android/renderscript/cts/AtanTest.java
deleted file mode 100644
index c41be40..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/AtanTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-
-public class AtanTest extends RSBaseCompute {
-    private ScriptC_atan_f32 script_f32;
-    private ScriptC_atan_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_atan_f32(mRS);
-        script_f32_relaxed = new ScriptC_atan_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_atan_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_atan_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_atan_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_atan_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_atan_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_atan_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_atan_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_atan_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)(Math.atan((double)in[idx]));
-            }
-        }
-        return ref;
-    }
-
-    public void testAtanF32() {
-        doF32(0x12a, 5);
-    }
-
-    public void testAtanF32_relaxed() {
-        doF32_relaxed(0x12a, 128);
-    }
-
-    public void testAtanF32_2() {
-        doF32_2(0xad, 5);
-    }
-
-    public void testAtanF32_2_relaxed() {
-        doF32_2_relaxed(0xad, 128);
-    }
-
-    public void testAtanF32_3() {
-        doF32_3(0xafe, 5);
-    }
-
-    public void testAtanF32_3_relaxed() {
-        doF32_3_relaxed(0xafe, 128);
-    }
-
-    public void testAtanF32_4() {
-        doF32_4(0x1238, 5);
-
-    }
-    public void testAtanF32_4_relaxed() {
-        doF32_4_relaxed(0x1238, 128);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/AtanhTest.java b/tests/tests/renderscript/src/android/renderscript/cts/AtanhTest.java
deleted file mode 100644
index 7182251..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/AtanhTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-
-public class AtanhTest extends RSBaseCompute {
-    private ScriptC_atanh_f32 script_f32;
-    private ScriptC_atanh_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_atanh_f32(mRS);
-        script_f32_relaxed = new ScriptC_atanh_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_atanh_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_atanh_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_atanh_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_atanh_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_atanh_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_atanh_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_atanh_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_atanh_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                double x = (double)in[idx];
-                ref[idxRef] = (float)((Math.log(1+x) - Math.log(1-x))/2);
-            }
-        }
-        return ref;
-    }
-
-    public void testAtanhF32() {
-        doF32(0xace, 5);
-    }
-
-    public void testAtanhF32_relaxed() {
-        doF32_relaxed(0xace, 128);
-    }
-
-    public void testAtanhF32_2() {
-        doF32_2(0xdae, 5);
-    }
-
-    public void testAtanhF32_2_relaxed() {
-        doF32_2_relaxed(0xdae, 128);
-    }
-
-    public void testAtanhF32_3() {
-        doF32_3(0x123, 5);
-    }
-
-    public void testAtanhF32_3_relaxed() {
-        doF32_3_relaxed(0x123, 128);
-    }
-
-    public void testAtanhF32_4() {
-        doF32_4(0x6480, 5);
-
-    }
-    public void testAtanhF32_4_relaxed() {
-        doF32_4_relaxed(0x6480, 128);
-    }
-
-}
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/renderscript/src/android/renderscript/cts/AtomicTest.rs b/tests/tests/renderscript/src/android/renderscript/cts/AtomicTest.rs
new file mode 100644
index 0000000..0aee2bdc
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/AtomicTest.rs
@@ -0,0 +1,126 @@
+/*
+ * 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;
+    while (rsAtomicCas(&gISum, tmp, tmp + 1) != tmp) {
+        tmp = gISum;
+    }
+}
+void __attribute__((kernel)) test_uCas(uint32_t v) {
+    uint tmp = gUSum;
+    while (rsAtomicCas(&gUSum, tmp, tmp + 1) != tmp) {
+        tmp = gUSum;
+    }
+}
+
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/CbrtTest.java b/tests/tests/renderscript/src/android/renderscript/cts/CbrtTest.java
deleted file mode 100644
index 603794a..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/CbrtTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-public class CbrtTest extends RSBaseCompute {
-    private ScriptC_cbrt_f32 script_f32;
-    private ScriptC_cbrt_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_cbrt_f32(mRS);
-        script_f32_relaxed = new ScriptC_cbrt_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_cbrt_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_cbrt_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_cbrt_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_cbrt_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_cbrt_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_cbrt_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_cbrt_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_cbrt_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)(Math.cbrt((double)in[idx]));
-            }
-        }
-        return ref;
-    }
-
-    public void testCbrtF32() {
-        doF32(0xabe, 2);
-    }
-
-    public void testCbrtF32_relaxed() {
-        doF32_relaxed(0xabe, 128);
-    }
-
-    public void testCbrtF32_2() {
-        doF32_2(0x78, 2);
-    }
-
-    public void testCbrtF32_2_relaxed() {
-        doF32_2_relaxed(0x78, 128);
-    }
-
-    public void testCbrtF32_3() {
-        doF32_3(0x1e, 2);
-    }
-
-    public void testCbrtF32_3_relaxed() {
-        doF32_3_relaxed(0x1e, 128);
-    }
-
-    public void testCbrtF32_4() {
-        doF32_4(0xfe2, 2);
-
-    }
-    public void testCbrtF32_4_relaxed() {
-        doF32_4_relaxed(0xfe2, 128);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/CeilTest.java b/tests/tests/renderscript/src/android/renderscript/cts/CeilTest.java
deleted file mode 100644
index 5d64b95..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/CeilTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-public class CeilTest extends RSBaseCompute {
-    private ScriptC_ceil_f32 script_f32;
-    private ScriptC_ceil_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_ceil_f32(mRS);
-        script_f32_relaxed = new ScriptC_ceil_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_ceil_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_ceil_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_ceil_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_ceil_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_ceil_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_ceil_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_ceil_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_ceil_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)(Math.ceil((double)in[idx]));
-            }
-        }
-        return ref;
-    }
-
-    public void testCeilF32() {
-        doF32(0x12345ace, 0);
-    }
-
-    public void testCeilF32_relaxed() {
-        doF32_relaxed(0x12345ace, 1);
-    }
-
-    public void testCeilF32_2() {
-        doF32_2(0x1ac478, 0);
-    }
-
-    public void testCeilF32_2_relaxed() {
-        doF32_2_relaxed(0x1ac478, 1);
-    }
-
-    public void testCeilF32_3() {
-        doF32_3(0xacef, 0);
-    }
-
-    public void testCeilF32_3_relaxed() {
-        doF32_3_relaxed(0xacef, 1);
-    }
-
-    public void testCeilF32_4() {
-        doF32_4(0xef12, 0);
-
-    }
-    public void testCeilF32_4_relaxed() {
-        doF32_4_relaxed(0xef12, 1);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/ClearObjectTest.java b/tests/tests/renderscript/src/android/renderscript/cts/ClearObjectTest.java
index e8a330a..9b1fbb7 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/ClearObjectTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/ClearObjectTest.java
@@ -22,7 +22,6 @@
 import android.renderscript.Sampler;
 import android.renderscript.Script;
 import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
 
 public class ClearObjectTest extends RSBaseCompute {
     int ObjectNum = 1;
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/CompilerTest.java b/tests/tests/renderscript/src/android/renderscript/cts/CompilerTest.java
index 799479e..9d119be 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/CompilerTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/CompilerTest.java
@@ -19,8 +19,6 @@
 import android.renderscript.RSRuntimeException;
 import android.util.Log;
 
-import com.android.cts.stub.R;
-
 /**
  * Test whether the driver properly handles compile-time issues.
  */
@@ -31,9 +29,7 @@
      */
     public void testMissingLink() {
         try {
-            ScriptC_missing_link t = new ScriptC_missing_link(mRS,
-                                                              mRes,
-                                                              R.raw.missing_link);
+            ScriptC_missing_link t = new ScriptC_missing_link(mRS);
             fail("should throw RSRuntimeException");
         } catch (RSRuntimeException e) {
         }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/ComputeTest.java b/tests/tests/renderscript/src/android/renderscript/cts/ComputeTest.java
index 40611fd..43708ad 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/ComputeTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/ComputeTest.java
@@ -48,8 +48,6 @@
 
 import android.renderscript.Type;
 
-import com.android.cts.stub.R;
-
 public class ComputeTest extends RSBaseCompute {
 
     public void testJavaVectorTypes() {
@@ -314,9 +312,7 @@
      * Test primitive types.
      */
     public void testPrimitives() {
-        ScriptC_primitives t = new ScriptC_primitives(mRS,
-                                                      mRes,
-                                                      R.raw.primitives);
+        ScriptC_primitives t = new ScriptC_primitives(mRS);
 
         assertTrue(initializeGlobals(t));
         t.invoke_test();
@@ -381,9 +377,7 @@
      * Test array initialization.
      */
     public void testArrayInit() {
-        ScriptC_array_init t = new ScriptC_array_init(mRS,
-                                                      mRes,
-                                                      R.raw.array_init);
+        ScriptC_array_init t = new ScriptC_array_init(mRS);
 
         checkInit(t);
         t.invoke_array_init_test();
@@ -672,7 +666,7 @@
     }
 
     public void testVector() {
-        ScriptC_vector s = new ScriptC_vector(mRS, mRes, R.raw.vector);
+        ScriptC_vector s = new ScriptC_vector(mRS);
         if (!initializeVector(s)) {
             fail("Failed to init vector components");
         } else {
@@ -683,6 +677,14 @@
         checkForErrors();
     }
 
+    public void testMatrix() {
+        ScriptC_MatrixTest s = new ScriptC_MatrixTest(mRS);
+        s.invoke_matrixTests();
+        mRS.finish();
+        waitForMessage();
+        checkForErrors();
+    }
+
     private boolean initializeStructObject(ScriptC_struct_object s) {
         ScriptField_objects_rs.Item i = new ScriptField_objects_rs.Item();
         i.e = Element.FONT(mRS);
@@ -693,7 +695,7 @@
 
     public void testStructObject() {
         ScriptC_struct_object s =
-                new ScriptC_struct_object(mRS, mRes, R.raw.struct_object);
+                new ScriptC_struct_object(mRS);
         if (!initializeStructObject(s)) {
             fail("Failed to init structure with RS objects");
         } else {
@@ -704,30 +706,11 @@
         checkForErrors();
     }
 
-    public void testClamp() {
-        ScriptC_clamp s = new ScriptC_clamp(mRS, mRes, R.raw.clamp);
-        s.invoke_clamp_test();
-        mRS.finish();
-        waitForMessage();
-        checkForErrors();
-    }
-
-    public void testClampRelaxed() {
-        ScriptC_clamp_relaxed s =
-                new ScriptC_clamp_relaxed(mRS, mRes, R.raw.clamp_relaxed);
-        s.invoke_clamp_test();
-        mRS.finish();
-        waitForMessage();
-        checkForErrors();
-    }
-
     /**
      * Test utility functions.
      */
     public void testUtilityFunctions() {
-        ScriptC_primitives t = new ScriptC_primitives(mRS,
-                                                      mRes,
-                                                      R.raw.utils);
+        ScriptC_utils t = new ScriptC_utils(mRS);
         t.invoke_test();
         waitForMessage();
         checkForErrors();
@@ -759,9 +742,7 @@
      * Test support for reflected forEach() as well as validation of parameters.
      */
     public void testForEach() {
-        ScriptC_negate s = new ScriptC_negate(mRS,
-                                              mRes,
-                                              R.raw.negate);
+        ScriptC_negate s = new ScriptC_negate(mRS);
 
         int x = 7;
         Type t = new Type.Builder(mRS, Element.I32(mRS)).setX(x).create();
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/CopysignTest.java b/tests/tests/renderscript/src/android/renderscript/cts/CopysignTest.java
deleted file mode 100644
index a28caef..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/CopysignTest.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import android.renderscript.Element;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-public class CopysignTest extends RSBaseCompute {
-    private ScriptC_copysign_f32 script_f32;
-    private ScriptC_copysign_f32_relaxed script_f32_relaxed;
-    private Allocation mIn;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_copysign_f32(mRS);
-        script_f32_relaxed = new ScriptC_copysign_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_copysign_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_copysign_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_copysign_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_copysign_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_copysign_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_copysign_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_copysign_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_copysign_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        int vec_size = stride - skip;
-        float[] ref = new float[vec_size * input_size];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < vec_size; j++) {
-                int idx = i * stride * 2 + j;
-                ref[i*vec_size + j] = Math.copySign(in[idx], in[idx + stride]);
-            }
-        }
-        return ref;
-    }
-
-    @Override
-    protected Allocation setInAlloc(Element e) {
-        return mIn;
-    }
-
-    @Override
-    protected float[] makeInArray(int size) {
-        return new float[size*2];
-    }
-
-    /**
-     * Tests copysign(float, float).
-     */
-    public void testCopysignF32() {
-        ScriptField_copysign_f32_input in = new ScriptField_copysign_f32_input(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32(0x12ac5678, 0);
-    }
-
-    public void testCopysignF32_relaxed() {
-        ScriptField_copysign_f32_input in = new ScriptField_copysign_f32_input(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_relaxed(0x12ac5678, 0);
-    }
-
-    /**
-     * Tests copysign(float2, float2).
-     */
-    public void testCopysignF32_2() {
-        ScriptField_copysign_f32_2_input in = new ScriptField_copysign_f32_2_input(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_2(0x12fe5678, 0);
-    }
-
-    public void testCopysignF32_2_relaxed() {
-        ScriptField_copysign_f32_2_input in = new ScriptField_copysign_f32_2_input(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_2_relaxed(0x12fe5678, 0);
-    }
-
-    /**
-     * Tests copysign(float3, float3).
-     */
-    public void testCopysignF32_3() {
-        ScriptField_copysign_f32_3_input in = new ScriptField_copysign_f32_3_input(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_3(0x1c345678, 0);
-    }
-
-    public void testCopysignF32_3_relaxed() {
-        ScriptField_copysign_f32_3_input in = new ScriptField_copysign_f32_3_input(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_3_relaxed(0x1c345678, 0);
-    }
-
-    /**
-     * Tests copysign(float4, float4).
-     */
-    public void testCopysignF32_4() {
-        ScriptField_copysign_f32_4_input in = new ScriptField_copysign_f32_4_input(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_4(0x123a5f7d, 0);
-    }
-
-    public void testCopysignF32_4_relaxed() {
-        ScriptField_copysign_f32_4_input in = new ScriptField_copysign_f32_4_input(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_4_relaxed(0x123a5f7d, 0);
-    }
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/CoreMathVerifier.java b/tests/tests/renderscript/src/android/renderscript/cts/CoreMathVerifier.java
new file mode 100644
index 0000000..dfcf1f5
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/CoreMathVerifier.java
@@ -0,0 +1,1941 @@
+/*
+ * 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 android.util.Log;
+
+public class CoreMathVerifier {
+    static {
+        System.loadLibrary("coremathtestcpp_jni");
+    }
+
+    /* The level of precision we expect out of the half_* functions.  floats (f32) have 23 bits of
+     * mantissa and halfs (f16) have 10 bits.  8192 = 2 ^ (23 - 10).
+     */
+    private static final int HALF_PRECISION = 8192;
+    // The level of precision we expect out of the fast_* functions.
+    private static final int FAST_PRECISION = 8192;
+    // The level of precision we expect out of the native_* functions.
+    private static final int NATIVE_PRECISION = 8192;
+
+    // Static classes used to return multiple values from a few JNI functions.
+    static public class FrexpResult {
+        public float significand;
+        public int exponent;
+    }
+
+    static public class LgammaResult {
+        public float lgamma;
+        public int gammaSign;
+    }
+
+    static public class RemquoResult {
+        public float remainder;
+        public int quotient;
+    }
+
+    /* We're calling into native:
+     * - not all functions are available in Java, notably gamma and erf,
+     * - Java lacks float version of these functions, so we can compare implementations with
+     *   similar constraints, and
+     * - handling unsigned integers, especially longs, is painful and error prone in Java.
+     */
+    static native float acos(float x);
+    static native float acosh(float x);
+    static native float asin(float x);
+    static native float asinh(float x);
+    static native float atan(float x);
+    static native float atan2(float x, float y);
+    static native float atanh(float x);
+    static native float cbrt(float x);
+    static native float ceil(float x);
+    static native float cos(float x);
+    static native float cosh(float x);
+    static native float erf(float x);
+    static native float erfc(float x);
+    static native float exp(float x);
+    static native float exp10(float x);
+    static native float exp2(float x);
+    static native float expm1(float x);
+    static native float floor(float x);
+    static native FrexpResult frexp(float x);
+    static native float hypot(float x, float y);
+    static native int ilogb(float x);
+    static native float ldexp(float x, int exp);
+    static native float lgamma(float x);
+    static native LgammaResult lgamma2(float x);
+    static native float log(float x);
+    static native float logb(float x);
+    static native float log10(float x);
+    static native float log1p(float x);
+    static native float log2(float x);
+    static native byte maxI8(byte x, byte y);
+    static native byte maxU8(byte x, byte y);
+    static native short maxI16(short x, short y);
+    static native short maxU16(short x, short y);
+    static native int maxI32(int x, int y);
+    static native int maxU32(int x, int y);
+    static native long maxI64(long x, long y);
+    static native long maxU64(long x, long y);
+    static native byte minI8(byte x, byte y);
+    static native byte minU8(byte x, byte y);
+    static native short minI16(short x, short y);
+    static native short minU16(short x, short y);
+    static native int minI32(int x, int y);
+    static native int minU32(int x, int y);
+    static native long minI64(long x, long y);
+    static native long minU64(long x, long y);
+    static native float pow(float x, float y);
+    static native RemquoResult remquo(float numerator, float denominator);
+    static native float rint(float x);
+    static native float round(float x);
+    static native float sin(float x);
+    static native float sinh(float x);
+    static native float sqrt(float x);
+    static native float tan(float x);
+    static native float tanh(float x);
+    static native float tgamma(float x);
+    static native float trunc(float x);
+
+    static native byte   convertCharToChar(byte x);
+    static native byte   convertCharToUchar(byte x);
+    static native short  convertCharToShort(byte x);
+    static native short  convertCharToUshort(byte x);
+    static native int    convertCharToInt(byte x);
+    static native int    convertCharToUint(byte x);
+    static native long   convertCharToLong(byte x);
+    static native long   convertCharToUlong(byte x);
+    static native float  convertCharToFloat(byte x);
+    static native double convertCharToDouble(byte x);
+
+    static native byte   convertUcharToChar(byte x);
+    static native byte   convertUcharToUchar(byte x);
+    static native short  convertUcharToShort(byte x);
+    static native short  convertUcharToUshort(byte x);
+    static native int    convertUcharToInt(byte x);
+    static native int    convertUcharToUint(byte x);
+    static native long   convertUcharToLong(byte x);
+    static native long   convertUcharToUlong(byte x);
+    static native float  convertUcharToFloat(byte x);
+    static native double convertUcharToDouble(byte x);
+
+    static native byte   convertShortToChar(short x);
+    static native byte   convertShortToUchar(short x);
+    static native short  convertShortToShort(short x);
+    static native short  convertShortToUshort(short x);
+    static native int    convertShortToInt(short x);
+    static native int    convertShortToUint(short x);
+    static native long   convertShortToLong(short x);
+    static native long   convertShortToUlong(short x);
+    static native float  convertShortToFloat(short x);
+    static native double convertShortToDouble(short x);
+
+    static native byte   convertUshortToChar(short x);
+    static native byte   convertUshortToUchar(short x);
+    static native short  convertUshortToShort(short x);
+    static native short  convertUshortToUshort(short x);
+    static native int    convertUshortToInt(short x);
+    static native int    convertUshortToUint(short x);
+    static native long   convertUshortToLong(short x);
+    static native long   convertUshortToUlong(short x);
+    static native float  convertUshortToFloat(short x);
+    static native double convertUshortToDouble(short x);
+
+    static native byte   convertIntToChar(int x);
+    static native byte   convertIntToUchar(int x);
+    static native short  convertIntToShort(int x);
+    static native short  convertIntToUshort(int x);
+    static native int    convertIntToInt(int x);
+    static native int    convertIntToUint(int x);
+    static native long   convertIntToLong(int x);
+    static native long   convertIntToUlong(int x);
+    static native float  convertIntToFloat(int x);
+    static native double convertIntToDouble(int x);
+
+    static native byte   convertUintToChar(int x);
+    static native byte   convertUintToUchar(int x);
+    static native short  convertUintToShort(int x);
+    static native short  convertUintToUshort(int x);
+    static native int    convertUintToInt(int x);
+    static native int    convertUintToUint(int x);
+    static native long   convertUintToLong(int x);
+    static native long   convertUintToUlong(int x);
+    static native float  convertUintToFloat(int x);
+    static native double convertUintToDouble(int x);
+
+    static native byte   convertLongToChar(long x);
+    static native byte   convertLongToUchar(long x);
+    static native short  convertLongToShort(long x);
+    static native short  convertLongToUshort(long x);
+    static native int    convertLongToInt(long x);
+    static native int    convertLongToUint(long x);
+    static native long   convertLongToLong(long x);
+    static native long   convertLongToUlong(long x);
+    static native float  convertLongToFloat(long x);
+    static native double convertLongToDouble(long x);
+
+    static native byte   convertUlongToChar(long x);
+    static native byte   convertUlongToUchar(long x);
+    static native short  convertUlongToShort(long x);
+    static native short  convertUlongToUshort(long x);
+    static native int    convertUlongToInt(long x);
+    static native int    convertUlongToUint(long x);
+    static native long   convertUlongToLong(long x);
+    static native long   convertUlongToUlong(long x);
+    static native float  convertUlongToFloat(long x);
+    static native double convertUlongToDouble(long x);
+
+    static native byte   convertFloatToChar(float x);
+    static native byte   convertFloatToUchar(float x);
+    static native short  convertFloatToShort(float x);
+    static native short  convertFloatToUshort(float x);
+    static native int    convertFloatToInt(float x);
+    static native int    convertFloatToUint(float x);
+    static native long   convertFloatToLong(float x);
+    static native long   convertFloatToUlong(float x);
+    static native float  convertFloatToFloat(float x);
+    static native double convertFloatToDouble(float x);
+
+    static native byte   convertDoubleToChar(double x);
+    static native byte   convertDoubleToUchar(double x);
+    static native short  convertDoubleToShort(double x);
+    static native short  convertDoubleToUshort(double x);
+    static native int    convertDoubleToInt(double x);
+    static native int    convertDoubleToUint(double x);
+    static native long   convertDoubleToLong(double x);
+    static native long   convertDoubleToUlong(double x);
+    static native float  convertDoubleToFloat(double x);
+    static native double convertDoubleToDouble(double x);
+
+    static private Target.Floaty pi32(Target t) {
+        return t.new32((float) Math.PI);
+    }
+
+    static private Target.Floaty any32(Target t) {
+        return t.new32(Float.NEGATIVE_INFINITY, Float.NaN, Float.POSITIVE_INFINITY);
+    }
+
+    static private Target.Floaty acos(float f, Target t) {
+        Target.Floaty in = t.new32(f);
+        return t.new32(
+            acos(in.mid32()),
+            acos(in.min32()),
+            acos(in.max32()));
+    }
+
+    static private Target.Floaty acosh(float f, Target t) {
+        Target.Floaty in = t.new32(f);
+        return t.new32(
+            acosh(in.mid32()),
+            acosh(in.min32()),
+            acosh(in.max32()));
+    }
+
+    static private Target.Floaty acospi(float f, Target t) {
+        return t.divide(acos(f, t), pi32(t));
+    }
+
+    static private Target.Floaty asin(float f, Target t) {
+        Target.Floaty in = t.new32(f);
+        return t.new32(
+            asin(in.mid32()),
+            asin(in.min32()),
+            asin(in.max32()));
+    }
+
+    static private Target.Floaty asinh(float f, Target t) {
+        Target.Floaty in = t.new32(f);
+        return t.new32(
+            asinh(in.mid32()),
+            asinh(in.min32()),
+            asinh(in.max32()));
+    }
+
+    static private Target.Floaty asinpi(float f, Target t) {
+        return t.divide(asin(f, t), pi32(t));
+    }
+
+    static private Target.Floaty atan(float f, Target t) {
+        Target.Floaty in = t.new32(f);
+        return t.new32(
+            atan(in.mid32()),
+            atan(in.min32()),
+            atan(in.max32()));
+    }
+
+    static private Target.Floaty atanh(float f, Target t) {
+        Target.Floaty in = t.new32(f);
+        return t.new32(
+            atanh(in.mid32()),
+            atanh(in.min32()),
+            atanh(in.max32()));
+    }
+
+    static private Target.Floaty atanpi(float f, Target t) {
+        return t.divide(atan(f, t), pi32(t));
+    }
+
+    static private Target.Floaty atan2(float y, float x, Target t) {
+        Target.Floaty inY = t.new32(y);
+        Target.Floaty inX = t.new32(x);
+        return t.new32(
+            atan2(inY.mid32(), inX.mid32()),
+            atan2(inY.min32(), inX.min32()),
+            atan2(inY.min32(), inX.max32()),
+            atan2(inY.max32(), inX.min32()),
+            atan2(inY.max32(), inX.max32()));
+    }
+
+    static private Target.Floaty atan2pi(float y, float x, Target t) {
+        return t.divide(atan2(y, x, t), pi32(t));
+    }
+
+    static private Target.Floaty cbrt(float f, Target t) {
+        Target.Floaty in = t.new32(f);
+        return t.new32(
+            cbrt(in.mid32()),
+            cbrt(in.min32()),
+            cbrt(in.max32()));
+    }
+
+    static private Target.Floaty cos(float f, Target t) {
+        Target.Floaty in = t.new32(f);
+        return t.new32(
+            cos(in.mid32()),
+            cos(in.min32()),
+            cos(in.max32()));
+    }
+
+    static private Target.Floaty cosh(float f, Target t) {
+        Target.Floaty in = t.new32(f);
+        return t.new32(
+            cosh(in.mid32()),
+            cosh(in.min32()),
+            cosh(in.max32()));
+    }
+
+    static private Target.Floaty cospi(float f, Target t) {
+        Target.Floaty in = t.multiply(t.new32(f), pi32(t));
+        return t.new32(
+            cos(in.mid32()),
+            cos(in.min32()),
+            cos(in.max32()));
+    }
+
+    // Computes the cross product of two 3D vectors.
+    static private void cross(float[] v1, float[] v2, Target.Floaty[] out, Target t) {
+        Target.Floaty a12 = t.multiply(t.new32(v1[1]), t.new32(v2[2]));
+        Target.Floaty a21 = t.multiply(t.new32(v1[2]), t.new32(v2[1]));
+        out[0] = t.subtract(a12, a21);
+        Target.Floaty a02 = t.multiply(t.new32(v1[0]), t.new32(v2[2]));
+        Target.Floaty a20 = t.multiply(t.new32(v1[2]), t.new32(v2[0]));
+        out[1] = t.subtract(a20, a02);
+        Target.Floaty a01 = t.multiply(t.new32(v1[0]), t.new32(v2[1]));
+        Target.Floaty a10 = t.multiply(t.new32(v1[1]), t.new32(v2[0]));
+        out[2] = t.subtract(a01, a10);
+        if (out.length == 4) {
+            out[3] = t.new32(0.f);
+        }
+    }
+
+    // Returns the distance between two points in n-dimensional space.
+    static private Target.Floaty distance(float[] point1, float[] point2, Target t) {
+        Target.Floaty sum = t.new32(0.f);
+        for (int i = 0; i < point1.length; i++) {
+            Target.Floaty diff = t.subtract(t.new32(point1[i]), t.new32(point2[i]));
+            sum = t.add(sum, t.multiply(diff, diff));
+        }
+        Target.Floaty d = t.sqrt(sum);
+        return d;
+    }
+
+    static private Target.Floaty exp(float f, Target t) {
+        Target.Floaty in = t.new32(f);
+        return t.new32(
+            exp(in.mid32()),
+            exp(in.min32()),
+            exp(in.max32()));
+    }
+
+    static private Target.Floaty exp10(float f, Target t) {
+        Target.Floaty in = t.new32(f);
+        return t.new32(
+            exp10(in.mid32()),
+            exp10(in.min32()),
+            exp10(in.max32()));
+    }
+
+    static private Target.Floaty exp2(float f, Target t) {
+        Target.Floaty in = t.new32(f);
+        return t.new32(
+            exp2(in.mid32()),
+            exp2(in.min32()),
+            exp2(in.max32()));
+    }
+
+    static private Target.Floaty expm1(float f, Target t) {
+        Target.Floaty in = t.new32(f);
+        return t.new32(
+            expm1(in.mid32()),
+            expm1(in.min32()),
+            expm1(in.max32()));
+    }
+
+    static private Target.Floaty hypot(float x, float y, Target t) {
+        Target.Floaty inX = t.new32(x);
+        Target.Floaty inY = t.new32(y);
+        return t.new32(
+            hypot(inX.mid32(), inY.mid32()),
+            hypot(inX.min32(), inY.min32()),
+            hypot(inX.min32(), inY.max32()),
+            hypot(inX.max32(), inY.min32()),
+            hypot(inX.max32(), inY.max32()));
+    }
+
+    // Returns the length of the n-dimensional vector.
+    static private Target.Floaty length(float[] array, Target t) {
+        Target.Floaty sum = t.new32(0.f);
+        for (int i = 0; i < array.length; i++) {
+            Target.Floaty f = t.new32(array[i]);
+            sum = t.add(sum, t.multiply(f, f));
+        }
+        Target.Floaty l = t.sqrt(sum);
+        return l;
+    }
+
+    static private Target.Floaty log(float f, Target t) {
+        Target.Floaty in = t.new32(f);
+        return t.new32(
+            log(in.mid32()),
+            log(in.min32()),
+            log(in.max32()));
+    }
+
+    static private Target.Floaty log10(float f, Target t) {
+        Target.Floaty in = t.new32(f);
+        return t.new32(
+            log10(in.mid32()),
+            log10(in.min32()),
+            log10(in.max32()));
+    }
+
+    static private Target.Floaty log1p(float f, Target t) {
+        Target.Floaty in = t.new32(f);
+        return t.new32(
+            log1p(in.mid32()),
+            log1p(in.min32()),
+            log1p(in.max32()));
+    }
+
+    static private Target.Floaty log2(float f, Target t) {
+        Target.Floaty in = t.new32(f);
+        return t.new32(
+            log2(in.mid32()),
+            log2(in.min32()),
+            log2(in.max32()));
+    }
+
+    // Normalizes the n-dimensional vector, i.e. makes it length 1.
+    static private void normalize(float[] in, Target.Floaty[] out, Target t) {
+        Target.Floaty l = length(in, t);
+        boolean isZero = l.get32() == 0.f;
+        for (int i = 0; i < in.length; i++) {
+            out[i] = t.new32(in[i]);
+            if (!isZero) {
+                out[i] = t.divide(out[i], l);
+            }
+        }
+    }
+
+    static private Target.Floaty powr(float x, float y, Target t) {
+        Target.Floaty inX = t.new32(x);
+        Target.Floaty inY = t.new32(y);
+        return t.new32(
+            pow(inX.mid32(), inY.mid32()),
+            pow(inX.min32(), inY.min32()),
+            pow(inX.min32(), inY.max32()),
+            pow(inX.max32(), inY.min32()),
+            pow(inX.max32(), inY.max32()));
+    }
+
+    static private Target.Floaty recip(float f, Target t) {
+        Target.Floaty in = t.new32(f);
+        return t.divide(t.new32(1.f), in);
+    }
+
+    static private Target.Floaty rootn(float inV, int inN, Target t) {
+        /* Rootn of a negative number should be possible only if the number
+         * is odd.  In cases where the int is very large, our approach will
+         * lose whether the int is odd, and we'll get a NaN for weird cases
+         * like rootn(-3.95, 818181881), which should return 1.  We handle the
+         * case by handling the sign ourselves.  We use copysign to handle the
+         * negative zero case.
+         */
+        float value;
+        if ((inN & 0x1) == 0x1) {
+            value = Math.copySign(pow(Math.abs(inV), 1.f / inN),
+                    inV);
+        } else {
+            value = pow(inV, 1.f / inN);
+        }
+        if (inN == 0) {
+            return t.new32(value, Float.NaN);
+        } else {
+            return t.new32(value);
+        }
+    }
+
+    static private Target.Floaty rsqrt(float f, Target t) {
+        Target.Floaty in = t.new32(f);
+        return t.divide(t.new32(1.f), t.sqrt(in));
+    }
+
+    static private Target.Floaty sin(float f, Target t) {
+        Target.Floaty in = t.new32(f);
+        return t.new32(
+            sin(in.mid32()),
+            sin(in.min32()),
+            sin(in.max32()));
+    }
+
+    static private Target.Floaty sinh(float f, Target t) {
+        Target.Floaty in = t.new32(f);
+        return t.new32(
+            sinh(in.mid32()),
+            sinh(in.min32()),
+            sinh(in.max32()));
+    }
+
+    static private Target.Floaty sinpi(float f, Target t) {
+        Target.Floaty in = t.multiply(t.new32(f), pi32(t));
+        return t.new32(
+            sin(in.mid32()),
+            sin(in.min32()),
+            sin(in.max32()));
+    }
+
+    static private Target.Floaty sqrt(float f, Target t) {
+        Target.Floaty in = t.new32(f);
+        return t.sqrt(in);
+    }
+
+    static private Target.Floaty tan(float f, Target t) {
+        Target.Floaty in = t.new32(f);
+        float min = tan(in.min32());
+        float max = tan(in.max32());
+        /* If the tan of the min is greater than that of the max,
+         * we spanned a discontinuity.
+         */
+        if (min > max) {
+            return any32(t);
+        } else {
+            return t.new32(tan(f), min, max);
+        }
+    }
+
+    static private Target.Floaty tanh(float f, Target t) {
+        Target.Floaty in = t.new32(f);
+        return t.new32(
+            tanh(in.mid32()),
+            tanh(in.min32()),
+            tanh(in.max32()));
+    }
+
+    static private Target.Floaty tanpi(float f, Target t) {
+        Target.Floaty in = t.multiply(t.new32(f), pi32(t));
+        float min = tan(in.min32());
+        float max = tan(in.max32());
+        /* If the tan of the min is greater than that of the max,
+         * we spanned a discontinuity.
+         */
+        if (min > max) {
+            return any32(t);
+        } else {
+            return t.new32(tan(in.mid32()), min, max);
+        }
+    }
+
+    static public void computeAbs(TestAbs.ArgumentsCharUchar args) {
+        args.out = (byte)Math.abs(args.inValue);
+    }
+
+    static public void computeAbs(TestAbs.ArgumentsShortUshort args) {
+        args.out = (short)Math.abs(args.inValue);
+    }
+
+    static public void computeAbs(TestAbs.ArgumentsIntUint args) {
+        args.out = Math.abs(args.inValue);
+    }
+
+    static public void computeAcos(TestAcos.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(4, 128, false);
+        args.out = acos(args.inV, t);
+    }
+
+    static public void computeAcosh(TestAcosh.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(4, 128, false);
+        args.out = acosh(args.in, t);
+    }
+
+    static public void computeAcospi(TestAcospi.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(5, 128, false);
+        args.out = acospi(args.inV, t);
+    }
+
+    static public void computeAsin(TestAsin.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(4, 128, false);
+        args.out = asin(args.inV, t);
+    }
+
+    static public void computeAsinh(TestAsinh.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(4, 128, false);
+        args.out = asinh(args.in, t);
+    }
+
+    static public void computeAsinpi(TestAsinpi.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(5, 128, false);
+        args.out = asinpi(args.inV, t);
+    }
+
+    static public void computeAtan(TestAtan.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(5, 128, false);
+        args.out = atan(args.inV, t);
+    }
+
+    static public void computeAtanh(TestAtanh.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(5, 128, false);
+        args.out = atanh(args.inV, t);
+    }
+
+    static public void computeAtanpi(TestAtanpi.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(5, 128, false);
+        args.out = atanpi(args.inV, t);
+    }
+
+    static public void computeAtan2(TestAtan2.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(6, 128, false);
+        args.out = atan2(args.inY, args.inX, t);
+    }
+
+    static public void computeAtan2pi(TestAtan2pi.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(6, 128, false);
+        args.out = atan2pi(args.inY, args.inX, t);
+    }
+
+    static public void computeCbrt(TestCbrt.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(2, 128, false);
+        args.out = cbrt(args.in, t);
+    }
+
+    static public void computeCeil(TestCeil.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(0, 1, false);
+        Target.Floaty in = t.new32(args.in);
+        args.out = t.new32(
+            ceil(in.mid32()),
+            ceil(in.min32()),
+            ceil(in.max32()));
+    }
+
+    static public void computeClamp(TestClamp.ArgumentsCharCharCharChar args) {
+        args.out = minI8(args.inMaxValue, maxI8(args.inValue, args.inMinValue));
+    }
+
+    static public void computeClamp(TestClamp.ArgumentsUcharUcharUcharUchar args) {
+        args.out = minU8(args.inMaxValue, maxU8(args.inValue, args.inMinValue));
+    }
+
+    static public void computeClamp(TestClamp.ArgumentsShortShortShortShort args) {
+        args.out = minI16(args.inMaxValue, maxI16(args.inValue, args.inMinValue));
+    }
+
+    static public void computeClamp(TestClamp.ArgumentsUshortUshortUshortUshort args) {
+        args.out = minU16(args.inMaxValue, maxU16(args.inValue, args.inMinValue));
+    }
+
+    static public void computeClamp(TestClamp.ArgumentsIntIntIntInt args) {
+        args.out = minI32(args.inMaxValue, maxI32(args.inValue, args.inMinValue));
+    }
+
+    static public void computeClamp(TestClamp.ArgumentsUintUintUintUint args) {
+        args.out = minU32(args.inMaxValue, maxU32(args.inValue, args.inMinValue));
+    }
+
+    static public void computeClamp(TestClamp.ArgumentsFloatFloatFloatFloat args, Target t) {
+        t.setPrecision(0, 0, false);
+        args.out = t.new32(Math.min(args.inMaxValue,
+                        Math.max(args.inValue, args.inMinValue)));
+    }
+
+    static public void computeClamp(TestClamp.ArgumentsLongLongLongLong args) {
+        args.out = minI64(args.inMaxValue, maxI64(args.inValue, args.inMinValue));
+    }
+
+    static public void computeClamp(TestClamp.ArgumentsUlongUlongUlongUlong args) {
+        args.out = minU64(args.inMaxValue, maxU64(args.inValue, args.inMinValue));
+    }
+
+    static public void computeClz(TestClz.ArgumentsCharChar args) {
+        int x = args.inValue;
+        args.out = (byte) (Integer.numberOfLeadingZeros(x & 0xff) - 24);
+    }
+
+    static public void computeClz(TestClz.ArgumentsUcharUchar args) {
+        int x = args.inValue;
+        args.out = (byte) (Integer.numberOfLeadingZeros(x & 0xff) - 24);
+    }
+
+    static public void computeClz(TestClz.ArgumentsShortShort args) {
+        args.out = (short) (Integer.numberOfLeadingZeros(args.inValue & 0xffff) - 16);
+    }
+
+    static public void computeClz(TestClz.ArgumentsUshortUshort args) {
+        args.out = (short) (Integer.numberOfLeadingZeros(args.inValue & 0xffff) - 16);
+    }
+
+    static public void computeClz(TestClz.ArgumentsIntInt args) {
+        args.out = (int) Integer.numberOfLeadingZeros(args.inValue);
+    }
+
+    static public void computeClz(TestClz.ArgumentsUintUint args) {
+        args.out = (int) Integer.numberOfLeadingZeros(args.inValue);
+    }
+
+
+    static public void computeConvert(TestConvert.ArgumentsCharChar args) {
+        args.out = convertCharToChar(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsCharUchar args) {
+        args.out = convertCharToUchar(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsCharShort args) {
+        args.out = convertCharToShort(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsCharUshort args) {
+        args.out = convertCharToUshort(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsCharInt args) {
+        args.out = convertCharToInt(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsCharUint args) {
+        args.out = convertCharToUint(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsCharLong args) {
+        args.out = convertCharToLong(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsCharUlong args) {
+        args.out = convertCharToUlong(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsCharFloat args, Target t) {
+        t.setPrecision(0, 0, false);
+        args.out = t.new32(convertCharToFloat(args.inV));
+    }
+    static public void computeConvert(TestConvert.ArgumentsCharDouble args, Target t) {
+        t.setPrecision(0, 0, false);
+        args.out = t.new64(convertCharToDouble(args.inV));
+    }
+
+    static public void computeConvert(TestConvert.ArgumentsUcharChar args) {
+        args.out = convertUcharToChar(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUcharUchar args) {
+        args.out = convertUcharToUchar(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUcharShort args) {
+        args.out = convertUcharToShort(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUcharUshort args) {
+        args.out = convertUcharToUshort(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUcharInt args) {
+        args.out = convertUcharToInt(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUcharUint args) {
+        args.out = convertUcharToUint(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUcharLong args) {
+        args.out = convertUcharToLong(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUcharUlong args) {
+        args.out = convertUcharToUlong(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUcharFloat args, Target t) {
+        t.setPrecision(0, 0, false);
+        args.out = t.new32(convertUcharToFloat(args.inV));
+    }
+    static public void computeConvert(TestConvert.ArgumentsUcharDouble args, Target t) {
+        t.setPrecision(0, 0, false);
+        args.out = t.new64(convertUcharToDouble(args.inV));
+    }
+
+    static public void computeConvert(TestConvert.ArgumentsShortChar args) {
+        args.out = convertShortToChar(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsShortUchar args) {
+        args.out = convertShortToUchar(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsShortShort args) {
+        args.out = convertShortToShort(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsShortUshort args) {
+        args.out = convertShortToUshort(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsShortInt args) {
+        args.out = convertShortToInt(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsShortUint args) {
+        args.out = convertShortToUint(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsShortLong args) {
+        args.out = convertShortToLong(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsShortUlong args) {
+        args.out = convertShortToUlong(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsShortFloat args, Target t) {
+        t.setPrecision(0, 0, false);
+        args.out = t.new32(convertShortToFloat(args.inV));
+    }
+    static public void computeConvert(TestConvert.ArgumentsShortDouble args, Target t) {
+        t.setPrecision(0, 0, false);
+        args.out = t.new64(convertShortToDouble(args.inV));
+    }
+
+    static public void computeConvert(TestConvert.ArgumentsUshortChar args) {
+        args.out = convertUshortToChar(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUshortUchar args) {
+        args.out = convertUshortToUchar(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUshortShort args) {
+        args.out = convertUshortToShort(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUshortUshort args) {
+        args.out = convertUshortToUshort(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUshortInt args) {
+        args.out = convertUshortToInt(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUshortUint args) {
+        args.out = convertUshortToUint(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUshortLong args) {
+        args.out = convertUshortToLong(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUshortUlong args) {
+        args.out = convertUshortToUlong(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUshortFloat args, Target t) {
+        t.setPrecision(0, 0, false);
+        args.out = t.new32(convertUshortToFloat(args.inV));
+    }
+    static public void computeConvert(TestConvert.ArgumentsUshortDouble args, Target t) {
+        t.setPrecision(0, 0, false);
+        args.out = t.new64(convertUshortToDouble(args.inV));
+    }
+
+    static public void computeConvert(TestConvert.ArgumentsIntChar args) {
+        args.out = convertIntToChar(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsIntUchar args) {
+        args.out = convertIntToUchar(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsIntShort args) {
+        args.out = convertIntToShort(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsIntUshort args) {
+        args.out = convertIntToUshort(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsIntInt args) {
+        args.out = convertIntToInt(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsIntUint args) {
+        args.out = convertIntToUint(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsIntLong args) {
+        args.out = convertIntToLong(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsIntUlong args) {
+        args.out = convertIntToUlong(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsIntFloat args, Target t) {
+        t.setPrecision(1, 1, false);
+        args.out = t.new32(convertIntToFloat(args.inV));
+    }
+    static public void computeConvert(TestConvert.ArgumentsIntDouble args, Target t) {
+        t.setPrecision(0, 0, false);
+        args.out = t.new64(convertIntToDouble(args.inV));
+    }
+
+    static public void computeConvert(TestConvert.ArgumentsUintChar args) {
+        args.out = convertUintToChar(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUintUchar args) {
+        args.out = convertUintToUchar(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUintShort args) {
+        args.out = convertUintToShort(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUintUshort args) {
+        args.out = convertUintToUshort(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUintInt args) {
+        args.out = convertUintToInt(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUintUint args) {
+        args.out = convertUintToUint(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUintLong args) {
+        args.out = convertUintToLong(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUintUlong args) {
+        args.out = convertUintToUlong(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUintFloat args, Target t) {
+        t.setPrecision(1, 1, false);
+        args.out = t.new32(convertUintToFloat(args.inV));
+    }
+    static public void computeConvert(TestConvert.ArgumentsUintDouble args, Target t) {
+        t.setPrecision(0, 0, false);
+        args.out = t.new64(convertUintToDouble(args.inV));
+    }
+
+    static public void computeConvert(TestConvert.ArgumentsLongChar args) {
+        args.out = convertLongToChar(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsLongUchar args) {
+        args.out = convertLongToUchar(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsLongShort args) {
+        args.out = convertLongToShort(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsLongUshort args) {
+        args.out = convertLongToUshort(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsLongInt args) {
+        args.out = convertLongToInt(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsLongUint args) {
+        args.out = convertLongToUint(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsLongLong args) {
+        args.out = convertLongToLong(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsLongUlong args) {
+        args.out = convertLongToUlong(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsLongFloat args, Target t) {
+        t.setPrecision(1, 1, false);
+        args.out = t.new32(convertLongToFloat(args.inV));
+    }
+    static public void computeConvert(TestConvert.ArgumentsLongDouble args, Target t) {
+        t.setPrecision(1, 1, false);
+        args.out = t.new64(convertLongToDouble(args.inV));
+    }
+
+    static public void computeConvert(TestConvert.ArgumentsUlongChar args) {
+        args.out = convertUlongToChar(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUlongUchar args) {
+        args.out = convertUlongToUchar(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUlongShort args) {
+        args.out = convertUlongToShort(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUlongUshort args) {
+        args.out = convertUlongToUshort(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUlongInt args) {
+        args.out = convertUlongToInt(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUlongUint args) {
+        args.out = convertUlongToUint(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUlongLong args) {
+        args.out = convertUlongToLong(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUlongUlong args) {
+        args.out = convertUlongToUlong(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsUlongFloat args, Target t) {
+        t.setPrecision(1, 1, false);
+        args.out = t.new32(convertUlongToFloat(args.inV));
+    }
+    static public void computeConvert(TestConvert.ArgumentsUlongDouble args, Target t) {
+        t.setPrecision(1, 1, false);
+        args.out = t.new64(convertUlongToDouble(args.inV));
+    }
+
+    static public void computeConvert(TestConvert.ArgumentsFloatChar args) {
+        args.out = convertFloatToChar(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsFloatUchar args) {
+        args.out = convertFloatToUchar(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsFloatShort args) {
+        args.out = convertFloatToShort(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsFloatUshort args) {
+        args.out = convertFloatToUshort(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsFloatInt args) {
+        args.out = convertFloatToInt(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsFloatUint args) {
+        args.out = convertFloatToUint(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsFloatLong args) {
+        args.out = convertFloatToLong(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsFloatUlong args) {
+        args.out = convertFloatToUlong(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(0, 0, false);
+        args.out = t.new32(convertFloatToFloat(args.inV));
+    }
+    static public void computeConvert(TestConvert.ArgumentsFloatDouble args, Target t) {
+        t.setPrecision(0, 0, false);
+        args.out = t.new64(convertFloatToDouble(args.inV));
+    }
+
+    static public void computeConvert(TestConvert.ArgumentsDoubleChar args) {
+        args.out = convertDoubleToChar(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsDoubleUchar args) {
+        args.out = convertDoubleToUchar(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsDoubleShort args) {
+        args.out = convertDoubleToShort(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsDoubleUshort args) {
+        args.out = convertDoubleToUshort(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsDoubleInt args) {
+        args.out = convertDoubleToInt(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsDoubleUint args) {
+        args.out = convertDoubleToUint(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsDoubleLong args) {
+        args.out = convertDoubleToLong(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsDoubleUlong args) {
+        args.out = convertDoubleToUlong(args.inV);
+    }
+    static public void computeConvert(TestConvert.ArgumentsDoubleFloat args, Target t) {
+        t.setPrecision(1, 1, false);
+        args.out = t.new32(convertDoubleToFloat(args.inV));
+    }
+    static public void computeConvert(TestConvert.ArgumentsDoubleDouble args, Target t) {
+        t.setPrecision(0, 0, false);
+        args.out = t.new64(convertDoubleToDouble(args.inV));
+    }
+
+    static public void computeCopysign(TestCopysign.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(0, 0, false);
+        args.out = t.new32(Math.copySign(args.inX, args.inY));
+    }
+
+    static public void computeCos(TestCos.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(4, 128, false);
+        args.out = cos(args.in, t);
+    }
+
+    static public void computeCosh(TestCosh.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(4, 128, false);
+        args.out = cosh(args.in, t);
+    }
+
+    static public void computeCospi(TestCospi.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(4, 128, false);
+        args.out = cospi(args.in, t);
+    }
+
+    static public void computeCross(TestCross.ArgumentsFloatNFloatNFloatN args, Target t) {
+        t.setPrecision(1, 4, false);
+        cross(args.inLhs, args.inRhs, args.out, t);
+    }
+
+    static public void computeDegrees(TestDegrees.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(3, 3, false);
+        Target.Floaty in = t.new32(args.inValue);
+        Target.Floaty k = t.new32((float)(180.0 / Math.PI));
+        args.out = t.multiply(in, k);
+    }
+
+    static public void computeDistance(TestDistance.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(1, 1, false);
+        args.out = distance(new float[] {args.inLhs}, new float[] {args.inRhs}, t);
+    }
+
+    static public void computeDistance(TestDistance.ArgumentsFloatNFloatNFloat args, Target t) {
+        t.setPrecision(1, 1, false);
+        args.out = distance(args.inLhs, args.inRhs, t);
+    }
+
+    static public void computeDot(TestDot.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(1, 4, false);
+        Target.Floaty a = t.new32(args.inLhs);
+        Target.Floaty b = t.new32(args.inRhs);
+        args.out = t.multiply(a, b);
+    }
+
+    static public void computeDot(TestDot.ArgumentsFloatNFloatNFloat args, Target t) {
+        t.setPrecision(1, 4, false);
+        Target.Floaty sum = t.new32(0.f);
+        for (int i = 0; i < args.inLhs.length; i++) {
+            Target.Floaty a = t.new32(args.inLhs[i]);
+            Target.Floaty b = t.new32(args.inRhs[i]);
+            sum = t.add(sum, t.multiply(a, b));
+        }
+        args.out = sum;
+    }
+
+    static public void computeErf(TestErf.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(16, 128, false);
+        Target.Floaty in = t.new32(args.in);
+        args.out = t.new32(
+            erf(args.in),
+            erf(in.min32()),
+            erf(in.max32()));
+    }
+
+    static public void computeErfc(TestErfc.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(16, 128, false);
+        Target.Floaty in = t.new32(args.in);
+        args.out = t.new32(
+            erfc(args.in),
+            erfc(in.min32()),
+            erfc(in.max32()));
+    }
+
+    static public void computeExp(TestExp.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(3, 16, false);
+        args.out = exp(args.in, t);
+    }
+
+    static public void computeExp10(TestExp10.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(3, 32, false);
+        args.out = exp10(args.in, t);
+    }
+
+    static public void computeExp2(TestExp2.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(3, 16, false);
+        args.out = exp2(args.in, t);
+    }
+
+    static public void computeExpm1(TestExpm1.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(3, 16, false);
+        args.out = expm1(args.in, t);
+    }
+
+    static public void computeFabs(TestFabs.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(0, 0, false);
+        Target.Floaty in = t.new32(args.in);
+        args.out = t.new32(
+            Math.abs(args.in),
+            Math.abs(in.min32()),
+            Math.abs(in.max32()));
+    }
+
+    static public void computeFastDistance(TestFastDistance.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(FAST_PRECISION, FAST_PRECISION, false);
+        args.out = distance(new float[] {args.inLhs}, new float[] {args.inRhs}, t);
+    }
+
+    static public void computeFastDistance(TestFastDistance.ArgumentsFloatNFloatNFloat args, Target t) {
+        t.setPrecision(FAST_PRECISION, FAST_PRECISION, false);
+        args.out = distance(args.inLhs, args.inRhs, t);
+    }
+
+    static public void computeFastLength(TestFastLength.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(FAST_PRECISION, FAST_PRECISION, false);
+        args.out = length(new float[] {args.inV}, t);
+    }
+
+    static public void computeFastLength(TestFastLength.ArgumentsFloatNFloat args, Target t) {
+        t.setPrecision(FAST_PRECISION, FAST_PRECISION, false);
+        args.out = length(args.inV, t);
+    }
+
+    static public void computeFastNormalize(TestFastNormalize.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(FAST_PRECISION, FAST_PRECISION, false);
+        Target.Floaty[] out = new Target.Floaty[1];
+        normalize(new float[] {args.inV}, out, t);
+        args.out = out[0];
+    }
+
+    static public void computeFastNormalize(TestFastNormalize.ArgumentsFloatNFloatN args, Target t) {
+        t.setPrecision(FAST_PRECISION, FAST_PRECISION, false);
+        normalize(args.inV, args.out, t);
+    }
+
+    static public void computeFdim(TestFdim.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(1, 1, false);
+        Target.Floaty inA = t.new32(args.inA);
+        Target.Floaty inB = t.new32(args.inB);
+        Target.Floaty r = t.subtract(inA, inB);
+        args.out = t.new32(
+            Math.max(0.f, r.mid32()),
+            Math.max(0.f, r.min32()),
+            Math.max(0.f, r.max32()));
+    }
+
+    static public void computeFloor(TestFloor.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(0, 0, false);
+        Target.Floaty in = t.new32(args.in);
+        args.out = t.new32(
+            floor(args.in),
+            floor(in.min32()),
+            floor(in.max32()));
+    }
+
+    static public void computeFma(TestFma.ArgumentsFloatFloatFloatFloat args, Target t) {
+        t.setPrecision(1, 1, false);
+        Target.Floaty ab = t.multiply(t.new32(args.inA), t.new32(args.inB));
+        args.out = t.add(ab, t.new32(args.inC));
+    }
+
+    static public void computeFmax(TestFmax.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(0, 0, false);
+        Target.Floaty inX = t.new32(args.inX);
+        Target.Floaty inY = t.new32(args.inY);
+        args.out = t.new32(
+            Math.max(args.inX, args.inY),
+            Math.max(inX.min32(), inY.min32()),
+            Math.max(inX.min32(), inY.max32()),
+            Math.max(inX.max32(), inY.min32()),
+            Math.max(inX.max32(), inY.max32()));
+    }
+
+    static public void computeFmin(TestFmin.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(0, 0, false);
+        Target.Floaty inX = t.new32(args.inX);
+        Target.Floaty inY = t.new32(args.inY);
+        args.out = t.new32(
+            Math.min(args.inX, args.inY),
+            Math.min(inX.min32(), inY.min32()),
+            Math.min(inX.min32(), inY.max32()),
+            Math.min(inX.max32(), inY.min32()),
+            Math.min(inX.max32(), inY.max32()));
+    }
+
+    static public void computeFmod(TestFmod.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(1, 1, false);
+        Target.Floaty inX = t.new32(args.inX);
+        Target.Floaty inY = t.new32(args.inY);
+        args.out = t.new32(
+            args.inX % args.inY,
+            inX.min32() % inY.min32(),
+            inX.min32() % inY.max32(),
+            inX.max32() % inY.min32(),
+            inX.max32() % inY.max32());
+    }
+
+    static public void computeFract(TestFract.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(1, 1, false);
+        float floor = floor(args.inV);
+        args.outFloor = t.new32(floor);
+        // 0x1.fffffep-1f is 0.999999...
+        args.out = t.new32(Math.min(args.inV - floor, 0x1.fffffep-1f));
+    }
+
+    static public void computeFract(TestFract.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(1, 1, false);
+        float floor = floor(args.inV);
+        // 0x1.fffffep-1f is 0.999999...
+        args.out = t.new32(Math.min(args.inV - floor, 0x1.fffffep-1f));
+    }
+
+    static public void computeFrexp(TestFrexp.ArgumentsFloatIntFloat args, Target t) {
+        t.setPrecision(0, 0, false);
+        FrexpResult result = frexp(args.inV);
+        args.out = t.new32(result.significand);
+        args.outIptr = result.exponent;
+    }
+
+    static public void computeHalfRecip(TestHalfRecip.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(HALF_PRECISION, HALF_PRECISION, false);
+        args.out = recip(args.inV, t);
+    }
+
+    static public void computeHalfRsqrt(TestHalfRsqrt.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(HALF_PRECISION, HALF_PRECISION, false);
+        args.out = rsqrt(args.inV, t);
+    }
+
+    static public void computeHalfSqrt(TestHalfSqrt.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(HALF_PRECISION, HALF_PRECISION, false);
+        args.out = sqrt(args.inV, t);
+    }
+
+    static public void computeHypot(TestHypot.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(4, 4, false);
+        args.out = hypot(args.inX, args.inY, t);
+    }
+
+    static public String verifyIlogb(TestIlogb.ArgumentsFloatInt args) {
+        // Special case when the input is 0.  We accept two different answers.
+        if (args.in == 0.f) {
+            if (args.out != -Integer.MAX_VALUE && args.out != Integer.MIN_VALUE) {
+                return "Expected " + Integer.toString(-Integer.MAX_VALUE) + " or " +
+                    Integer.toString(Integer.MIN_VALUE);
+            }
+        } else {
+            int result = ilogb(args.in);
+            if (args.out != result) {
+                return "Expected " + Integer.toString(result);
+            }
+        }
+        return null;
+    }
+
+    static public void computeLdexp(TestLdexp.ArgumentsFloatIntFloat args, Target t) {
+        t.setPrecision(1, 1, false);
+        Target.Floaty inX = t.new32(args.inX);
+        args.out = t.new32(
+            ldexp(inX.mid32(), args.inY),
+            ldexp(inX.min32(), args.inY),
+            ldexp(inX.max32(), args.inY));
+    }
+
+    static public void computeLength(TestLength.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(1, 1, false);
+        args.out = length(new float[]{args.inV}, t);
+    }
+
+    static public void computeLength(TestLength.ArgumentsFloatNFloat args, Target t) {
+        t.setPrecision(1, 1, false);
+        args.out = length(args.inV, t);
+    }
+
+    static public void computeLgamma(TestLgamma.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(16, 128, false);
+        Target.Floaty in = t.new32(args.in);
+        args.out = t.new32(
+            lgamma(in.mid32()),
+            lgamma(in.min32()),
+            lgamma(in.max32()));
+    }
+
+    /* TODO Until -0 handling is corrected in bionic & associated drivers, we temporarily
+     * disable the verification of -0.  We do this with a custom verifier.  Once bionic
+     * is fixed, we can restore computeLgamma and remove verifyLgamma.
+    static public void computeLgamma(TestLgamma.ArgumentsFloatIntFloat args, Target t) {
+        t.setPrecision(16, 128, false);
+        Target.Floaty in = t.new32(args.inX);
+        LgammaResult result = lgamma2(in.mid32());
+        LgammaResult resultMin = lgamma2(in.min32());
+        LgammaResult resultMax = lgamma2(in.max32());
+        args.out = t.new32(result.lgamma, resultMin.lgamma, resultMax.lgamma);
+        args.outY = result.gammaSign;
+    }
+    */
+    static public String verifyLgamma(TestLgamma.ArgumentsFloatIntFloat args, Target t) {
+        t.setPrecision(16, 128, false);
+        Target.Floaty in = t.new32(args.inX);
+        LgammaResult result = lgamma2(in.mid32());
+        LgammaResult resultMin = lgamma2(in.min32());
+        LgammaResult resultMax = lgamma2(in.max32());
+        Target.Floaty expectedOut = t.new32(result.lgamma, resultMin.lgamma, resultMax.lgamma);
+        boolean isNegativeZero = args.inX == 0.f && 1.f / args.inX < 0.f;
+        /* TODO The current implementation of bionic does not handle the -0.f case correctly.
+         * It should set the sign to -1 but sets it to 1.
+         */
+        if (!expectedOut.couldBe(args.out) ||
+            (args.outY != result.gammaSign && !isNegativeZero)) {
+            StringBuilder message = new StringBuilder();
+            message.append(String.format("Input in %14.8g {%8x}:\n", args.inX, Float.floatToRawIntBits(args.inX)));
+            message.append("Expected out: ");
+            message.append(expectedOut.toString());
+            message.append("\n");
+            message.append(String.format("Actual   out: %14.8g {%8x}", args.out, Float.floatToRawIntBits(args.out)));
+            message.append(String.format("Expected outY: %d\n", result.gammaSign));
+            message.append(String.format("Actual   outY: %d\n", args.outY));
+            return message.toString();
+        }
+
+        return null;
+    }
+
+    // TODO The relaxed ulf for the various log are taken from the old tests.
+    // They are not consistent.
+    static public void computeLog(TestLog.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(3, 16, false);
+        args.out = log(args.in, t);
+    }
+
+    static public void computeLog10(TestLog10.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(3, 16, false);
+        args.out = log10(args.in, t);
+    }
+
+    static public void computeLog1p(TestLog1p.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(2, 16, false);
+        args.out = log1p(args.in, t);
+    }
+
+    static public void computeLog2(TestLog2.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(3, 128, false);
+        args.out = log2(args.in, t);
+    }
+
+    static public void computeLogb(TestLogb.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(0, 0, false);
+        Target.Floaty in = t.new32(args.in);
+        args.out = t.new32(
+            logb(in.mid32()),
+            logb(in.min32()),
+            logb(in.max32()));
+    }
+
+    static public void computeMad(TestMad.ArgumentsFloatFloatFloatFloat args, Target t) {
+        t.setPrecision(1, 4, false);
+        Target.Floaty ab = t.multiply(t.new32(args.inA), t.new32(args.inB));
+        args.out = t.add(ab, t.new32(args.inC));
+    }
+
+    static public void computeMax(TestMax.ArgumentsCharCharChar args) {
+        args.out = maxI8(args.inV1, args.inV2);
+    }
+
+    static public void computeMax(TestMax.ArgumentsUcharUcharUchar args) {
+        args.out = maxU8(args.inV1, args.inV2);
+    }
+
+    static public void computeMax(TestMax.ArgumentsShortShortShort args) {
+        args.out = maxI16(args.inV1, args.inV2);
+    }
+
+    static public void computeMax(TestMax.ArgumentsUshortUshortUshort args) {
+        args.out = maxU16(args.inV1, args.inV2);
+    }
+
+    static public void computeMax(TestMax.ArgumentsIntIntInt args) {
+        args.out = maxI32(args.inV1, args.inV2);
+    }
+
+    static public void computeMax(TestMax.ArgumentsUintUintUint args) {
+        args.out = maxU32(args.inV1, args.inV2);
+    }
+
+    static public void computeMax(TestMax.ArgumentsLongLongLong args) {
+        args.out = maxI64(args.inV1, args.inV2);
+    }
+
+    static public void computeMax(TestMax.ArgumentsUlongUlongUlong args) {
+        args.out = maxU64(args.inV1, args.inV2);
+    }
+
+    static public void computeMax(TestMax.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(0, 0, false);
+        Target.Floaty in = t.new32(args.in);
+        Target.Floaty in1 = t.new32(args.in1);
+        args.out = t.new32(
+            Math.max(in.mid32(), in1.mid32()),
+            Math.max(in.min32(), in1.min32()),
+            Math.max(in.min32(), in1.max32()),
+            Math.max(in.max32(), in1.min32()),
+            Math.max(in.max32(), in1.max32()));
+    }
+
+    static public void computeMin(TestMin.ArgumentsCharCharChar args) {
+        args.out = minI8(args.inV1, args.inV2);
+    }
+
+    static public void computeMin(TestMin.ArgumentsUcharUcharUchar args) {
+        args.out = minU8(args.inV1, args.inV2);
+    }
+
+    static public void computeMin(TestMin.ArgumentsShortShortShort args) {
+        args.out = minI16(args.inV1, args.inV2);
+    }
+
+    static public void computeMin(TestMin.ArgumentsUshortUshortUshort args) {
+        args.out = minU16(args.inV1, args.inV2);
+    }
+
+    static public void computeMin(TestMin.ArgumentsIntIntInt args) {
+        args.out = minI32(args.inV1, args.inV2);
+    }
+
+    static public void computeMin(TestMin.ArgumentsUintUintUint args) {
+        args.out = minU32(args.inV1, args.inV2);
+    }
+
+    static public void computeMin(TestMin.ArgumentsLongLongLong args) {
+        args.out = minI64(args.inV1, args.inV2);
+    }
+
+    static public void computeMin(TestMin.ArgumentsUlongUlongUlong args) {
+        args.out = minU64(args.inV1, args.inV2);
+    }
+
+    static public void computeMin(TestMin.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(0, 0, false);
+        args.out = t.new32(Math.min(args.in, args.in1));
+    }
+
+    static public void computeMix(TestMix.ArgumentsFloatFloatFloatFloat args, Target t) {
+        t.setPrecision(1, 4, false);
+        Target.Floaty start = t.new32(args.inStart);
+        Target.Floaty stop = t.new32(args.inStop);
+        Target.Floaty diff = t.subtract(stop, start);
+        args.out = t.add(start, t.multiply(diff, t.new32(args.inAmount)));
+    }
+
+    static public void computeModf(TestModf.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(0, 0, false);
+        float ret = (float)(int)args.inX;
+        args.outIret = t.new32(ret);
+        args.out = t.new32(args.inX - ret);
+    }
+
+    static public void computeNan(TestNan.ArgumentsUintFloat args, Target t) {
+        t.setPrecision(0, 0, false);
+        args.out = t.new32(Float.NaN);
+    }
+
+    static public void computeNativeAcos(TestNativeAcos.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = acos(args.inV, t);
+    }
+
+    static public void computeNativeAcosh(TestNativeAcosh.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = acosh(args.in, t);
+    }
+
+    static public void computeNativeAcospi(TestNativeAcospi.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = acospi(args.inV, t);
+    }
+
+    static public void computeNativeAsin(TestNativeAsin.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = asin(args.inV, t);
+    }
+
+    static public void computeNativeAsinh(TestNativeAsinh.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = asinh(args.in, t);
+    }
+
+    static public void computeNativeAsinpi(TestNativeAsinpi.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = asinpi(args.inV, t);
+    }
+
+    static public void computeNativeAtan(TestNativeAtan.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = atan(args.inV, t);
+    }
+
+    static public void computeNativeAtanh(TestNativeAtanh.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = atanh(args.inIn, t);
+    }
+
+    static public void computeNativeAtanpi(TestNativeAtanpi.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = atanpi(args.inV, t);
+    }
+
+    static public void computeNativeAtan2(TestNativeAtan2.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = atan2(args.inY, args.inX, t);
+    }
+
+    static public void computeNativeAtan2pi(TestNativeAtan2pi.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = atan2pi(args.inY, args.inX, t);
+    }
+
+    static public void computeNativeCbrt(TestNativeCbrt.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = cbrt(args.in, t);
+    }
+
+    static public void computeNativeCos(TestNativeCos.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = cos(args.in, t);
+    }
+
+    static public void computeNativeCosh(TestNativeCosh.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = cosh(args.in, t);
+    }
+
+    static public void computeNativeCospi(TestNativeCospi.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = cospi(args.in, t);
+    }
+
+    static public void computeNativeDistance(TestNativeDistance.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = distance(new float[]{args.inLhs}, new float[]{args.inRhs}, t);
+    }
+
+    static public void computeNativeDistance(TestNativeDistance.ArgumentsFloatNFloatNFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = distance(args.inLhs, args.inRhs, t);
+    }
+
+    static public void computeNativeDivide(TestNativeDivide.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = t.divide(t.new32(args.inLhs), t.new32(args.inRhs));
+    }
+
+    static public void computeNativeExp(TestNativeExp.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = exp(args.inV, t);
+    }
+
+    static public void computeNativeExp10(TestNativeExp10.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = exp10(args.inV, t);
+    }
+
+    static public void computeNativeExp2(TestNativeExp2.ArgumentsFloatFloat args, Target t) {
+        // TODO we would like to use NATIVE_PRECISION, NATIVE_PRECISION
+        t.setPrecision(13000, 13000, true);
+        args.out = exp2(args.inV, t);
+    }
+
+    static public void computeNativeExpm1(TestNativeExpm1.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = expm1(args.in, t);
+    }
+
+    static public void computeNativeHypot(TestNativeHypot.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = hypot(args.inX, args.inY, t);
+    }
+
+    static public void computeNativeLength(TestNativeLength.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = length(new float[] {args.inV}, t);
+    }
+
+    static public void computeNativeLength(TestNativeLength.ArgumentsFloatNFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = length(args.inV, t);
+    }
+
+    static public void computeNativeLog(TestNativeLog.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        // For very small values, allow anything.
+        if (Math.abs(args.inV) < 1.e-20) {
+            args.out = any32(t);
+        } else {
+            args.out = log(args.inV, t);
+        }
+    }
+
+    static public void computeNativeLog10(TestNativeLog10.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        // For very small values, allow anything.
+        if (Math.abs(args.inV) < 1.e-20) {
+            args.out = any32(t);
+        } else {
+            args.out = log10(args.inV, t);
+        }
+    }
+
+    static public void computeNativeLog1p(TestNativeLog1p.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = log1p(args.in, t);
+    }
+
+    static public void computeNativeLog2(TestNativeLog2.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        // For very small values, allow anything.
+        if (Math.abs(args.inV) < 1.e-20) {
+            args.out = any32(t);
+        } else {
+            args.out = log2(args.inV, t);
+        }
+    }
+
+    static public void computeNativeNormalize(TestNativeNormalize.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        Target.Floaty[] out = new Target.Floaty[1];
+        normalize(new float[] {args.inV}, out, t);
+        args.out = out[0];
+    }
+
+    static public void computeNativeNormalize(TestNativeNormalize.ArgumentsFloatNFloatN args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        normalize(args.inV, args.out, t);
+    }
+
+    static public void computeNativePowr(TestNativePowr.ArgumentsFloatFloatFloat args, Target t) {
+        // TODO we would like to use NATIVE_PRECISION, NATIVE_PRECISION
+        t.setPrecision(32000, 32000, true);
+        // For very small values, allow anything.
+        if (Math.abs(args.inV) < 1.e-20) {
+            args.out = any32(t);
+        } else {
+            args.out = powr(args.inV, args.inY, t);
+        }
+    }
+
+    static public void computeNativeRecip(TestNativeRecip.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = recip(args.inV, t);
+    }
+
+    static public void computeNativeRootn(TestNativeRootn.ArgumentsFloatIntFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        // Allow anything for zero.
+        if (args.inN == 0) {
+            args.out = any32(t);
+        } else {
+            args.out = rootn(args.inV, args.inN, t);
+        }
+    }
+
+    static public void computeNativeRsqrt(TestNativeRsqrt.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = rsqrt(args.in, t);
+    }
+
+    static public void computeNativeSin(TestNativeSin.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = sin(args.in, t);
+    }
+
+    static public void computeNativeSincos(TestNativeSincos.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.outCosptr = cos(args.inV, t);
+        args.out = sin(args.inV, t);
+    }
+
+    static public void computeNativeSinh(TestNativeSinh.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = sinh(args.in, t);
+    }
+
+    static public void computeNativeSinpi(TestNativeSinpi.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = sinpi(args.in, t);
+    }
+
+    static public void computeNativeSqrt(TestNativeSqrt.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = sqrt(args.in, t);
+    }
+
+    static public void computeNativeTan(TestNativeTan.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = tan(args.in, t);
+    }
+
+    static public void computeNativeTanh(TestNativeTanh.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = tanh(args.in, t);
+    }
+
+    static public void computeNativeTanpi(TestNativeTanpi.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION, true);
+        args.out = tanpi(args.in, t);
+    }
+
+    static public void computeNextafter(TestNextafter.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(0, 0, false);
+        args.out = t.new32(Math.nextAfter(args.inX, args.inY));
+    }
+
+    static public void computeNormalize(TestNormalize.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(1, 1, false);
+        Target.Floaty[] out = new Target.Floaty[1];
+        normalize(new float[] {args.inV}, out, t);
+        args.out = out[0];
+    }
+
+    static public void computeNormalize(TestNormalize.ArgumentsFloatNFloatN args, Target t) {
+        t.setPrecision(1, 1, false);
+        normalize(args.inV, args.out, t);
+    }
+
+    static public void computePow(TestPow.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(16, 128, false);
+        Target.Floaty inX = t.new32(args.inX);
+        Target.Floaty inY = t.new32(args.inY);
+        args.out = t.new32(
+            pow(inX.mid32(), inY.mid32()),
+            pow(inX.min32(), inY.min32()),
+            pow(inX.min32(), inY.max32()),
+            pow(inX.max32(), inY.min32()),
+            pow(inX.max32(), inY.max32()));
+    }
+
+    static public void computePown(TestPown.ArgumentsFloatIntFloat args, Target t) {
+        t.setPrecision(16, 128, false);
+        Target.Floaty in = t.new32(args.inX);
+        // We use double for the calculations because floats does not have enough
+        // mantissa bits.  Knowing if an int is odd or even will matter for negative
+        // numbers.  Using a float loses the lowest bit.
+        final double y = (double) args.inY;
+        args.out = t.new32(
+            (float) Math.pow(in.mid32(), y),
+            (float) Math.pow(in.min32(), y),
+            (float) Math.pow(in.max32(), y));
+    }
+
+    static public void computePowr(TestPowr.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(16, 128, false);
+        args.out = powr(args.inX, args.inY, t);
+    }
+
+    static public void computeRadians(TestRadians.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(3, 3, false);
+        Target.Floaty in = t.new32(args.inValue);
+        Target.Floaty k = t.new32((float)(Math.PI / 180.0));
+        args.out = t.multiply(in, k);
+    }
+
+    static public void computeRemainder(TestRemainder.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(0, 0, false);
+        RemquoResult result = remquo(args.inX, args.inY);
+        args.out = t.new32(result.remainder);
+    }
+
+    static public String verifyRemquo(TestRemquo.ArgumentsFloatFloatIntFloat args, Target t) {
+        t.setPrecision(0, 0, false);
+        RemquoResult expected = remquo(args.inB, args.inC);
+        // If the expected remainder is NaN, we don't validate the quotient.  It's because of
+        // a division by zero.
+        if (expected.remainder != expected.remainder) {
+            // Check that the value we got is NaN too.
+            if (args.out == args.out) {
+                return "Expected a remainder of NaN but got " +  Float.toString(args.out);
+            }
+        } else {
+            // The quotient should have the same lowest three bits.
+            if ((args.outD & 0x07) != (expected.quotient & 0x07)) {
+                return "Quotient returned " +  Integer.toString(args.outD) +
+                    " does not have the same lower three bits as the expected " +
+                    Integer.toString(expected.quotient);
+            }
+            Target.Floaty remainder = t.new32(expected.remainder);
+            if (!remainder.couldBe(args.out)) {
+                return "Remainder returned " + Float.toString(args.out) +
+                    " is not similar to the expected " +
+                    remainder.toString();
+            }
+        }
+        return null;
+    }
+
+    static public void computeRint(TestRint.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(0, 0, false);
+        Target.Floaty in = t.new32(args.in);
+        args.out = t.new32(
+            rint(in.mid32()),
+            rint(in.min32()),
+            rint(in.max32()));
+    }
+
+    static public void computeRootn(TestRootn.ArgumentsFloatIntFloat args, Target t) {
+        t.setPrecision(16, 16, false);
+        args.out = rootn(args.inV, args.inN, t);
+    }
+
+    static public void computeRound(TestRound.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(0, 0, false);
+        Target.Floaty in = t.new32(args.in);
+        args.out = t.new32(
+            round(in.mid32()),
+            round(in.min32()),
+            round(in.max32()));
+    }
+
+    static public void computeRsqrt(TestRsqrt.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(2, 2, false);
+        args.out = rsqrt(args.in, t);
+    }
+
+    static public void computeSign(TestSign.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(0, 0, false);
+        args.out = t.new32(Math.signum(args.inV));
+    }
+
+    static public void computeSin(TestSin.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(4, 128, false);
+        args.out = sin(args.in, t);
+    }
+
+    static public void computeSincos(TestSincos.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(4, 128, false);
+        args.outCosptr = cos(args.inV,t );
+        args.out = sin(args.inV, t);
+    }
+
+    static public void computeSinh(TestSinh.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(4, 128, false);
+        args.out = sinh(args.in, t);
+    }
+
+    static public void computeSinpi(TestSinpi.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(4, 128, false);
+        args.out = sinpi(args.in, t);
+    }
+
+    static public void computeSqrt(TestSqrt.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(3, 3, false);
+        args.out = sqrt(args.in, t);
+    }
+
+    static public void computeStep(TestStep.ArgumentsFloatFloatFloat args, Target t) {
+        t.setPrecision(0, 0, false);
+        args.out = t.new32(args.inV < args.inEdge ? 0.f : 1.f);
+    }
+
+    static public void computeTan(TestTan.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(5, 128, false);
+        args.out = tan(args.in, t);
+    }
+
+    static public void computeTanh(TestTanh.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(5, 128, false);
+        args.out = tanh(args.in, t);
+    }
+
+    static public void computeTanpi(TestTanpi.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(4, 128, false);
+        args.out = tanpi(args.in, t);
+    }
+
+    static public void computeTgamma(TestTgamma.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(16, 128, false);
+        Target.Floaty in = t.new32(args.in);
+        args.out = t.new32(
+            tgamma(in.mid32()),
+            tgamma(in.min32()),
+            tgamma(in.max32()));
+    }
+
+    static public void computeTrunc(TestTrunc.ArgumentsFloatFloat args, Target t) {
+        t.setPrecision(0, 0, false);
+        Target.Floaty in = t.new32(args.in);
+        args.out = t.new32(
+            trunc(in.mid32()),
+            trunc(in.min32()),
+            trunc(in.max32()));
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/CosTest.java b/tests/tests/renderscript/src/android/renderscript/cts/CosTest.java
deleted file mode 100644
index dd5db8a..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/CosTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-public class CosTest extends RSBaseCompute {
-    private ScriptC_cos_f32 script_f32;
-    private ScriptC_cos_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_cos_f32(mRS);
-        script_f32_relaxed = new ScriptC_cos_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_cos_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_cos_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_cos_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_cos_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_cos_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_cos_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_cos_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_cos_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)(Math.cos((double)in[idx]));
-            }
-        }
-        return ref;
-    }
-
-    public void testCosF32() {
-        doF32(0xe, 4);
-    }
-
-    public void testCosF32_relaxed() {
-        doF32_relaxed(0xe, 4);
-    }
-
-    public void testCosF32_2() {
-        doF32_2(0xb, 4);
-    }
-
-    public void testCosF32_2_relaxed() {
-        doF32_2_relaxed(0xb, 4);
-    }
-
-    public void testCosF32_3() {
-        doF32_3(0x12a, 4);
-    }
-
-    public void testCosF32_3_relaxed() {
-        doF32_3_relaxed(0x12a, 4);
-    }
-
-    public void testCosF32_4() {
-        doF32_4(0x98a, 4);
-
-    }
-    public void testCosF32_4_relaxed() {
-        doF32_4_relaxed(0x98a, 4);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/CoshTest.java b/tests/tests/renderscript/src/android/renderscript/cts/CoshTest.java
deleted file mode 100644
index 9fa3603..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/CoshTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import com.android.cts.stub.R;
-import android.renderscript.RSRuntimeException;
-
-public class CoshTest extends RSBaseCompute {
-
-    private ScriptC_cosh_f32 script_f32;
-    private ScriptC_cosh_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_cosh_f32(mRS);
-        script_f32_relaxed = new ScriptC_cosh_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_cosh_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_cosh_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_cosh_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_cosh_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_cosh_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_cosh_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_cosh_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_cosh_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)(Math.cosh((double)in[idx]));
-            }
-        }
-        return ref;
-    }
-
-    public void testCoshF32() {
-        doF32(0xfe, 4);
-    }
-
-    public void testCoshF32_relaxed() {
-        doF32_relaxed(0xfe, 128);
-    }
-
-    public void testCoshF32_2() {
-        doF32_2(0x71, 4);
-    }
-
-    public void testCoshF32_2_relaxed() {
-        doF32_2_relaxed(0x71, 128);
-    }
-
-    public void testCoshF32_3() {
-        doF32_3(0xa, 4);
-    }
-
-    public void testCoshF32_3_relaxed() {
-        doF32_3_relaxed(0xa, 128);
-    }
-
-    public void testCoshF32_4() {
-        doF32_4(0xabe, 4);
-
-    }
-    public void testCoshF32_4_relaxed() {
-        doF32_4_relaxed(0xabe, 128);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/CrossTest.java b/tests/tests/renderscript/src/android/renderscript/cts/CrossTest.java
deleted file mode 100644
index 308f5f4..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/CrossTest.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.Element;
-import android.renderscript.RSRuntimeException;
-
-public class CrossTest extends RSBaseCompute {
-    private ScriptC_cross_f32 script_f32;
-    private ScriptC_cross_f32_relaxed script_f32_relaxed;
-    private Allocation mIn;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_cross_f32(mRS);
-        script_f32_relaxed = new ScriptC_cross_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32_3:
-            script_f32.forEach_cross_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_cross_f32_4(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_cross_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_cross_f32_4(mIn, mOut);
-            break;
-        }
-
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            int idx= i * stride * 2;
-            int idxRef = i * (stride - skip);
-            ref[idxRef + 0] = in[idx+1] * in[idx+2+stride] - in[idx+2] * in[idx+1+stride];
-            ref[idxRef + 1] = in[idx+2] * in[idx+0+stride] - in[idx+0] * in[idx+2+stride];
-            ref[idxRef + 2] = in[idx+0] * in[idx+1+stride] - in[idx+1] * in[idx+0+stride];
-            if (skip == 1)
-                ref[idxRef + 3] = 0.f;
-        }
-        return ref;
-    }
-
-    @Override
-    protected Allocation setInAlloc(Element e) {
-        return mIn;
-    }
-
-    @Override
-    protected float[] makeInArray(int size) {
-        return new float[size*2];
-    }
-
-    /**
-     * cross test for float3
-     */
-    public void testCrossF32_3() {
-        ScriptField__cross_f32_3_struct in = new ScriptField__cross_f32_3_struct(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_3(0x12345678, 0);
-    }
-
-    /*
-    Disable until we can add an absolute error metric
-    public void testCrossF32_3_relaxed() {
-        ScriptField__cross_f32_3_struct in = new ScriptField__cross_f32_3_struct(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_3_relaxed(0x12345678, 2);
-    }
-    */
-
-
-    /**
-     * cross test for float4
-     */
-    public void testCrossF32_4() {
-        ScriptField__cross_f32_4_struct in = new ScriptField__cross_f32_4_struct(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_4(0x12ac5678, 0);
-    }
-
-    /*
-    Disable until we can add an absolute error metric
-    public void testCrossF32_4_relaxed() {
-        ScriptField__cross_f32_4_struct in = new ScriptField__cross_f32_4_struct(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_4_relaxed(0x12ac5678, 2);
-    }
-    */
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/DegreesTest.java b/tests/tests/renderscript/src/android/renderscript/cts/DegreesTest.java
deleted file mode 100644
index 38c4824..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/DegreesTest.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-
-public class DegreesTest extends RSBaseCompute {
-    private ScriptC_degrees_f32 script_f32;
-    private ScriptC_degrees_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_degrees_f32(mRS);
-        script_f32_relaxed = new ScriptC_degrees_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_degrees_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_degrees_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_degrees_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_degrees_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_degrees_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_degrees_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_degrees_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_degrees_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                double val = (double)in[idx] * (180.0 / Math.PI);
-                ref[idxRef] = (float)val;
-            }
-        }
-        return ref;
-    }
-
-    /**
-     * degrees test for float
-     */
-    public void testDegreesF32() {
-        doF32(0x12345678, 3);
-    }
-
-    public void testDegreesF32_relaxed() {
-        doF32_relaxed(0x12345678, 3);
-    }
-
-    /**
-     * degrees test for float2
-     */
-    public void testDegreesF32_2() {
-        doF32_2(0x12353678, 3);
-    }
-
-    public void testDegreesF32_2_relaxed() {
-        doF32_2_relaxed(0x12353678, 3);
-    }
-
-    /**
-     * degrees test for float3
-     */
-    public void testDegreesF32_3() {
-        doF32_3(0x12312678, 3);
-    }
-
-    public void testDegreesF32_3_relaxed() {
-        doF32_3_relaxed(0x12312678, 3);
-    }
-
-    /**
-     * degrees test for float4
-     */
-    public void testDegreesF32_4() {
-        doF32_4(0x12675678, 3);
-
-    }
-    public void testDegreesF32_4_relaxed() {
-        doF32_4_relaxed(0x12675678, 3);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/Exp10Test.java b/tests/tests/renderscript/src/android/renderscript/cts/Exp10Test.java
deleted file mode 100644
index 875af18..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/Exp10Test.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-public class Exp10Test extends RSBaseCompute {
-    private ScriptC_exp10_f32 script_f32;
-    private ScriptC_exp10_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_exp10_f32(mRS);
-        script_f32_relaxed = new ScriptC_exp10_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_exp10_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_exp10_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_exp10_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_exp10_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_exp10_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_exp10_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_exp10_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_exp10_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)(Math.pow(10, (double)in[idx]));
-            }
-        }
-        return ref;
-    }
-
-    public void testExp10F32() {
-        doF32(0x81, 3);
-    }
-
-    public void testExp10F32_relaxed() {
-        doF32_relaxed(0x81, 16);
-    }
-
-    public void testExp10F32_2() {
-        doF32_2(0xa42, 3);
-    }
-
-    public void testExp10F32_2_relaxed() {
-        doF32_2_relaxed(0xa42, 16);
-    }
-
-    public void testExp10F32_3() {
-        doF32_3(0xace2, 3);
-    }
-
-    public void testExp10F32_3_relaxed() {
-        doF32_3_relaxed(0xace2, 16);
-    }
-
-    public void testExp10F32_4() {
-        doF32_4(0x918, 3);
-
-    }
-    public void testExp10F32_4_relaxed() {
-        doF32_4_relaxed(0x918, 16);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/Exp2Test.java b/tests/tests/renderscript/src/android/renderscript/cts/Exp2Test.java
deleted file mode 100644
index ac99b92..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/Exp2Test.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-public class Exp2Test extends RSBaseCompute {
-    private ScriptC_exp2_f32 script_f32;
-    private ScriptC_exp2_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_exp2_f32(mRS);
-        script_f32_relaxed = new ScriptC_exp2_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_exp2_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_exp2_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_exp2_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_exp2_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_exp2_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_exp2_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_exp2_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_exp2_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)(Math.pow(2, (double)in[idx]));
-            }
-        }
-        return ref;
-    }
-
-    public void testExp2F32() {
-        doF32(0xa6, 3);
-    }
-
-    public void testExp2F32_relaxed() {
-        doF32_relaxed(0xa6, 16);
-    }
-
-    public void testExp2F32_2() {
-        doF32_2(0xab2, 3);
-    }
-
-    public void testExp2F32_2_relaxed() {
-        doF32_2_relaxed(0xab2, 16);
-    }
-
-    public void testExp2F32_3() {
-        doF32_3(0x617a, 3);
-    }
-
-    public void testExp2F32_3_relaxed() {
-        doF32_3_relaxed(0x617a, 16);
-    }
-
-    public void testExp2F32_4() {
-        doF32_4(0xabc3, 3);
-
-    }
-    public void testExp2F32_4_relaxed() {
-        doF32_4_relaxed(0xabc3, 16);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/ExpTest.java b/tests/tests/renderscript/src/android/renderscript/cts/ExpTest.java
deleted file mode 100644
index e2f86ca..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/ExpTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-public class ExpTest extends RSBaseCompute {
-    private ScriptC_exp_f32 script_f32;
-    private ScriptC_exp_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_exp_f32(mRS);
-        script_f32_relaxed = new ScriptC_exp_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_exp_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_exp_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_exp_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_exp_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_exp_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_exp_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_exp_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_exp_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)(Math.exp((double)in[idx]));
-            }
-        }
-        return ref;
-    }
-
-    public void testExpF32() {
-        doF32(0xa28, 3);
-    }
-
-    public void testExpF32_relaxed() {
-        doF32_relaxed(0xa28, 16);
-    }
-
-    public void testExpF32_2() {
-        doF32_2(0xfeb4, 3);
-    }
-
-    public void testExpF32_2_relaxed() {
-        doF32_2_relaxed(0xfeb4, 16);
-    }
-
-    public void testExpF32_3() {
-        doF32_3(0xab2, 3);
-    }
-
-    public void testExpF32_3_relaxed() {
-        doF32_3_relaxed(0xab2, 16);
-    }
-
-    public void testExpF32_4() {
-        doF32_4(0x7a6, 3);
-
-    }
-    public void testExpF32_4_relaxed() {
-        doF32_4_relaxed(0x7a6, 16);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/Expm1Test.java b/tests/tests/renderscript/src/android/renderscript/cts/Expm1Test.java
deleted file mode 100644
index 36b65ff..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/Expm1Test.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-public class Expm1Test extends RSBaseCompute {
-    private ScriptC_expm1_f32 script_f32;
-    private ScriptC_expm1_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_expm1_f32(mRS);
-        script_f32_relaxed = new ScriptC_expm1_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_expm1_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_expm1_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_expm1_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_expm1_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_expm1_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_expm1_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_expm1_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_expm1_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)(Math.expm1((double)in[idx]));
-            }
-        }
-        return ref;
-    }
-
-    public void testExpm1F32() {
-        doF32(0xa29, 3);
-    }
-
-    public void testExpm1F32_relaxed() {
-        doF32_relaxed(0xa29, 16);
-    }
-
-    public void testExpm1F32_2() {
-        doF32_2(0x8a2, 3);
-    }
-
-    public void testExpm1F32_2_relaxed() {
-        doF32_2_relaxed(0x8a2, 16);
-    }
-
-    public void testExpm1F32_3() {
-        doF32_3(0xa7c, 3);
-    }
-
-    public void testExpm1F32_3_relaxed() {
-        doF32_3_relaxed(0xa7c, 16);
-    }
-
-    public void testExpm1F32_4() {
-        doF32_4(0x81a, 3);
-
-    }
-    public void testExpm1F32_4_relaxed() {
-        doF32_4_relaxed(0x81a, 16);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/FabsTest.java b/tests/tests/renderscript/src/android/renderscript/cts/FabsTest.java
deleted file mode 100644
index e8739d4..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/FabsTest.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-public class FabsTest extends RSBaseCompute {
-    private ScriptC_fabs_f32 script_f32;
-    private ScriptC_fabs_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_fabs_f32(mRS);
-        script_f32_relaxed = new ScriptC_fabs_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_fabs_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_fabs_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_fabs_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_fabs_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_fabs_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_fabs_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_fabs_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_fabs_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = Math.abs(in[idx]);
-            }
-        }
-        return ref;
-    }
-
-    public void testfabsF32() {
-        doF32(0xa, 0);
-    }
-
-    public void testfabsF32_relaxed() {
-        doF32_relaxed(0xa, 0);
-    }
-
-    public void testfabsF32_2() {
-        doF32_2(0xb, 0);
-    }
-
-    public void testfabsF32_2_relaxed() {
-        doF32_2_relaxed(0xb, 0);
-    }
-
-    public void testfabsF32_3() {
-        doF32_3(0xc, 0);
-    }
-
-    public void testfabsF32_3_relaxed() {
-        doF32_3_relaxed(0xc, 0);
-    }
-
-    public void testfabsF32_4() {
-        doF32_4(0xd, 0);
-
-    }
-    public void testfabsF32_4_relaxed() {
-        doF32_4_relaxed(0xd, 0);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/FdimTest.java b/tests/tests/renderscript/src/android/renderscript/cts/FdimTest.java
deleted file mode 100644
index 144c258..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/FdimTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import android.renderscript.Element;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-public class FdimTest extends RSBaseCompute {
-    private ScriptC_fdim_f32 script_f32;
-    private ScriptC_fdim_f32_relaxed script_f32_relaxed;
-    private Allocation mIn;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_fdim_f32(mRS);
-        script_f32_relaxed = new ScriptC_fdim_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_fdim_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_fdim_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_fdim_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_fdim_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_fdim_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_fdim_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_fdim_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_fdim_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx = i * stride * 2 + j;
-                ref[i * (stride - skip) + j] = (float)(Math.max(0.0, (double)in[idx] - (double)in[idx+stride]));
-            }
-        }
-        return ref;
-    }
-
-    @Override
-    protected Allocation setInAlloc(Element e) {
-        return mIn;
-    }
-
-    @Override
-    protected float[] makeInArray(int size) {
-        return new float[size*2];
-    }
-
-    public void testfdimF32() {
-        ScriptField_fdim_f32_input floatArray = new ScriptField_fdim_f32_input(mRS, INPUTSIZE);
-        mIn = floatArray.getAllocation();
-        doF32(0x12678, 0);
-    }
-
-    public void testfdimF32_relaxed() {
-        ScriptField_fdim_f32_input floatArray = new ScriptField_fdim_f32_input(mRS, INPUTSIZE);
-        mIn = floatArray.getAllocation();
-        doF32_relaxed(0x12678, 0);
-    }
-
-    public void testfdimF32_2() {
-        ScriptField_fdim_f32_2_input floatArray = new ScriptField_fdim_f32_2_input(mRS, INPUTSIZE);
-        mIn = floatArray.getAllocation();
-        doF32_2(0x1af45, 0);
-    }
-
-    public void testfdimF32_2_relaxed() {
-        ScriptField_fdim_f32_2_input floatArray = new ScriptField_fdim_f32_2_input(mRS, INPUTSIZE);
-        mIn = floatArray.getAllocation();
-        doF32_2_relaxed(0x1af45, 0);
-    }
-
-    public void testfdimF32_3() {
-        ScriptField_fdim_f32_3_input floatArray = new ScriptField_fdim_f32_3_input(mRS, INPUTSIZE);
-        mIn = floatArray.getAllocation();
-        doF32_3(0x1cd345, 0);
-    }
-
-    public void testfdimF32_3_relaxed() {
-        ScriptField_fdim_f32_3_input floatArray = new ScriptField_fdim_f32_3_input(mRS, INPUTSIZE);
-        mIn = floatArray.getAllocation();
-        doF32_3_relaxed(0x1cd345, 0);
-    }
-
-    public void testfdimF32_4() {
-        ScriptField_fdim_f32_4_input floatArray = new ScriptField_fdim_f32_4_input(mRS, INPUTSIZE);
-        mIn = floatArray.getAllocation();
-        doF32_4(0x1ca45, 0);
-    }
-
-    public void testfdimF32_4_relaxed() {
-        ScriptField_fdim_f32_4_input floatArray = new ScriptField_fdim_f32_4_input(mRS, INPUTSIZE);
-        mIn = floatArray.getAllocation();
-        doF32_4_relaxed(0x1ca45, 0);
-    }
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/FieldPackerTest.java b/tests/tests/renderscript/src/android/renderscript/cts/FieldPackerTest.java
index 8625b9f..fb2ba50 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/FieldPackerTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/FieldPackerTest.java
@@ -146,7 +146,7 @@
             }
         }
 
-        int[] badResetArgs = {-1000, -2, -1, 256, 257, 1000};
+        int[] badResetArgs = {-1000, -2, -1, 257, 1000};
         for (int arg: badResetArgs) {
             try {
                 fp.reset(arg);
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/FloorTest.java b/tests/tests/renderscript/src/android/renderscript/cts/FloorTest.java
deleted file mode 100644
index e7494e6..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/FloorTest.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-public class FloorTest extends RSBaseCompute {
-    private ScriptC_floor_f32 script_f32;
-    private ScriptC_floor_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_floor_f32(mRS);
-        script_f32_relaxed = new ScriptC_floor_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_floor_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_floor_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_floor_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_floor_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_floor_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_floor_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_floor_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_floor_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)(Math.floor((double)in[idx]));
-            }
-        }
-        return ref;
-    }
-
-    public void testfloorF32() {
-        doF32(0xa, 0);
-    }
-
-    public void testfloorF32_relaxed() {
-        doF32_relaxed(0xa, 1);
-    }
-
-    public void testfloorF32_2() {
-        doF32_2(0xb, 0);
-    }
-
-    public void testfloorF32_2_relaxed() {
-        doF32_2_relaxed(0xb, 1);
-    }
-
-    public void testfloorF32_3() {
-        doF32_3(0xef1, 0);
-    }
-
-    public void testfloorF32_3_relaxed() {
-        doF32_3_relaxed(0xef1, 1);
-    }
-
-    public void testfloorF32_4() {
-        doF32_4(0xefa12, 0);
-
-    }
-    public void testfloorF32_4_relaxed() {
-        doF32_4_relaxed(0xefa12, 1);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/FmaTest.java b/tests/tests/renderscript/src/android/renderscript/cts/FmaTest.java
deleted file mode 100644
index 40fac7e..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/FmaTest.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import android.renderscript.Element;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-public class FmaTest extends RSBaseCompute {
-    private ScriptC_fma_f32 script_f32;
-    private ScriptC_fma_f32_relaxed script_f32_relaxed;
-    private Allocation mIn;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_fma_f32(mRS);
-        script_f32_relaxed = new ScriptC_fma_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_fma_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_fma_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_fma_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_fma_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_fma_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_fma_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_fma_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_fma_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx = i * stride * 3 + j;
-                ref[i * (stride - skip) + j] = (float)((double)in[idx] * (double)in[idx+stride] + (double)in[idx+stride*2]);
-            }
-        }
-        return ref;
-    }
-
-    @Override
-    protected Allocation setInAlloc(Element e) {
-        return mIn;
-    }
-
-    @Override
-    protected float[] makeInArray(int size) {
-        return new float[size*3];
-    }
-
-    public void testFmaF32() {
-        ScriptField_Floats floatArray = new ScriptField_Floats(mRS, INPUTSIZE);
-        mIn = floatArray.getAllocation();
-        doF32(0xea1, 0);
-    }
-
-    public void testFmaF32_relaxed() {
-        ScriptField_Floats floatArray = new ScriptField_Floats(mRS, INPUTSIZE);
-        mIn = floatArray.getAllocation();
-        doF32_relaxed(0xea1, 0);
-    }
-
-    public void testFmaF32_2() {
-        ScriptField_Floats2 floatArray = new ScriptField_Floats2(mRS, INPUTSIZE);
-        mIn = floatArray.getAllocation();
-        doF32_2(0x12a, 0);
-    }
-
-    public void testFmaF32_2_relaxed() {
-        ScriptField_Floats2 floatArray = new ScriptField_Floats2(mRS, INPUTSIZE);
-        mIn = floatArray.getAllocation();
-        doF32_2_relaxed(0x12a, 0);
-    }
-
-    public void testFmaF32_3() {
-        ScriptField_Floats3 floatArray = new ScriptField_Floats3(mRS, INPUTSIZE);
-        mIn = floatArray.getAllocation();
-        doF32_3(0xfae, 0);
-    }
-
-    public void testFmaF32_3_relaxed() {
-        ScriptField_Floats3 floatArray = new ScriptField_Floats3(mRS, INPUTSIZE);
-        mIn = floatArray.getAllocation();
-        doF32_3_relaxed(0xfae, 0);
-    }
-
-    public void testFmaF32_4() {
-        ScriptField_Floats4 floatArray = new ScriptField_Floats4(mRS, INPUTSIZE);
-        mIn = floatArray.getAllocation();
-        doF32_4(0x87a, 0);
-    }
-
-    public void testFmaF32_4_relaxed() {
-        ScriptField_Floats4 floatArray = new ScriptField_Floats4(mRS, INPUTSIZE);
-        mIn = floatArray.getAllocation();
-        doF32_4_relaxed(0x87a, 0);
-    }
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/FmaxTest.java b/tests/tests/renderscript/src/android/renderscript/cts/FmaxTest.java
deleted file mode 100644
index 99f2b42..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/FmaxTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import android.renderscript.Element;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-public class FmaxTest extends RSBaseCompute {
-    private ScriptC_fmax_f32 script_f32;
-    private ScriptC_fmax_f32_relaxed script_f32_relaxed;
-    private Allocation mIn;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_fmax_f32(mRS);
-        script_f32_relaxed = new ScriptC_fmax_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation max, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_fmax_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_fmax_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_fmax_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_fmax_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_fmax_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_fmax_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_fmax_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_fmax_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx = i * stride * 2 + j;
-                ref[i * (stride - skip) + j] = Math.max(in[idx], in[idx+stride]);
-            }
-        }
-        return ref;
-    }
-
-    @Override
-    protected Allocation setInAlloc(Element e) {
-        return mIn;
-    }
-
-    @Override
-    protected float[] makeInArray(int size) {
-        return new float[size*2];
-    }
-
-    public void testfmaxF32() {
-        ScriptField_fmax_f32_in in = new ScriptField_fmax_f32_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32(0x12678, 0);
-    }
-
-    public void testfmaxF32_relaxed() {
-        ScriptField_fmax_f32_in in = new ScriptField_fmax_f32_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_relaxed(0x12678, 0);
-    }
-
-    public void testfmaxF32_2() {
-        ScriptField_fmax_f32_2_in in = new ScriptField_fmax_f32_2_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_2(0x12ace, 0);
-    }
-
-    public void testfmaxF32_2_relaxed() {
-        ScriptField_fmax_f32_2_in in = new ScriptField_fmax_f32_2_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_2_relaxed(0x12ace, 0);
-    }
-
-    public void testfmaxF32_3() {
-        ScriptField_fmax_f32_3_in in = new ScriptField_fmax_f32_3_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_3(0x12e8, 0);
-    }
-
-    public void testfmaxF32_3_relaxed() {
-        ScriptField_fmax_f32_3_in in = new ScriptField_fmax_f32_3_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_3_relaxed(0x12e8, 0);
-    }
-
-    public void testfmaxF32_4() {
-        ScriptField_fmax_f32_4_in in = new ScriptField_fmax_f32_4_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_4(0xeac, 0);
-    }
-
-    public void testfmaxF32_4_relaxed() {
-        ScriptField_fmax_f32_4_in in = new ScriptField_fmax_f32_4_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_4_relaxed(0xeac, 0);
-    }
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/FminTest.java b/tests/tests/renderscript/src/android/renderscript/cts/FminTest.java
deleted file mode 100644
index b43b828..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/FminTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import android.renderscript.Element;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-public class FminTest extends RSBaseCompute {
-    private ScriptC_fmin_f32 script_f32;
-    private ScriptC_fmin_f32_relaxed script_f32_relaxed;
-    private Allocation mIn;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_fmin_f32(mRS);
-        script_f32_relaxed = new ScriptC_fmin_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_fmin_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_fmin_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_fmin_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_fmin_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_fmin_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_fmin_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_fmin_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_fmin_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx = i * stride * 2 + j;
-                ref[i * (stride - skip) + j] = Math.min(in[idx], in[idx+stride]);
-            }
-        }
-        return ref;
-    }
-
-    @Override
-    protected Allocation setInAlloc(Element e) {
-        return mIn;
-    }
-
-    @Override
-    protected float[] makeInArray(int size) {
-        return new float[size*2];
-    }
-
-    public void testfminF32() {
-        ScriptField_fmin_f32_in in = new ScriptField_fmin_f32_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32(0x12678, 0);
-    }
-
-    public void testfminF32_relaxed() {
-        ScriptField_fmin_f32_in in = new ScriptField_fmin_f32_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_relaxed(0x12678, 0);
-    }
-
-    public void testfminF32_2() {
-        ScriptField_fmin_f32_2_in in = new ScriptField_fmin_f32_2_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_2(0x12ace, 0);
-    }
-
-    public void testfminF32_2_relaxed() {
-        ScriptField_fmin_f32_2_in in = new ScriptField_fmin_f32_2_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_2_relaxed(0x12ace, 0);
-    }
-
-    public void testfminF32_3() {
-        ScriptField_fmin_f32_3_in in = new ScriptField_fmin_f32_3_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_3(0x12e8, 0);
-    }
-
-    public void testfminF32_3_relaxed() {
-        ScriptField_fmin_f32_3_in in = new ScriptField_fmin_f32_3_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_3_relaxed(0x12e8, 0);
-    }
-
-    public void testfminF32_4() {
-        ScriptField_fmin_f32_4_in in = new ScriptField_fmin_f32_4_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_4(0xeac, 0);
-    }
-
-    public void testfminF32_4_relaxed() {
-        ScriptField_fmin_f32_4_in in = new ScriptField_fmin_f32_4_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_4_relaxed(0xeac, 0);
-    }
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/FmodTest.java b/tests/tests/renderscript/src/android/renderscript/cts/FmodTest.java
deleted file mode 100644
index d0d911d..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/FmodTest.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import android.renderscript.Element;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-public class FmodTest extends RSBaseCompute {
-    private ScriptC_fmod_f32 script_f32;
-    private ScriptC_fmod_f32_relaxed script_f32_relaxed;
-    private Allocation mIn;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_fmod_f32(mRS);
-        script_f32_relaxed = new ScriptC_fmod_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_fmod_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_fmod_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_fmod_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_fmod_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_fmod_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_fmod_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_fmod_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_fmod_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx = i * stride * 2 + j;
-                ref[i * (stride - skip) + j] = (float)((double)in[idx] % (double)in[idx+stride]);
-            }
-        }
-        return ref;
-    }
-
-    @Override
-    protected Allocation setInAlloc(Element e) {
-        return mIn;
-    }
-
-    @Override
-    protected float[] makeInArray(int size) {
-        return new float[size*2];
-    }
-
-    /**
-     * This method is used for testing the fmod() function with F32
-     */
-    public void testfmodF32() {
-        ScriptField_fmod_input_f32 floatArray = new ScriptField_fmod_input_f32(mRS, INPUTSIZE);
-        mIn = floatArray.getAllocation();
-        doF32(0x12345678, 0);
-    }
-
-    public void testfmodF32_relaxed() {
-        ScriptField_fmod_input_f32 floatArray = new ScriptField_fmod_input_f32(mRS, INPUTSIZE);
-        mIn = floatArray.getAllocation();
-        doF32_relaxed(0x12345678, 0);
-    }
-
-    /**
-     * This method is used for testing the fmod() function with F32_2
-     */
-    public void testfmodF32_2() {
-        ScriptField_fmod_input_f32_2 floatArray = new ScriptField_fmod_input_f32_2(mRS, INPUTSIZE);
-        mIn = floatArray.getAllocation();
-        doF32_2(0x12345, 0);
-    }
-
-    public void testfmodF32_2_relaxed() {
-        ScriptField_fmod_input_f32_2 floatArray = new ScriptField_fmod_input_f32_2(mRS, INPUTSIZE);
-        mIn = floatArray.getAllocation();
-        doF32_2_relaxed(0x12345, 0);
-    }
-
-    /**
-     * This method is used for testing the fmod() function with F32_3
-     */
-    public void testfmodF32_3() {
-        ScriptField_fmod_input_f32_3 floatArray = new ScriptField_fmod_input_f32_3(mRS, INPUTSIZE);
-        mIn = floatArray.getAllocation();
-        doF32_3(0x12345, 0);
-    }
-
-    public void testfmodF32_3_relaxed() {
-        ScriptField_fmod_input_f32_3 floatArray = new ScriptField_fmod_input_f32_3(mRS, INPUTSIZE);
-        mIn = floatArray.getAllocation();
-        doF32_3_relaxed(0x12345, 0);
-    }
-
-    /**
-     * This method is used for testing the fmod() function with F32_4
-     */
-    public void testfmodF32_4() {
-        ScriptField_fmod_input_f32_4 floatArray = new ScriptField_fmod_input_f32_4(mRS, INPUTSIZE);
-        mIn = floatArray.getAllocation();
-        doF32_4(0x12345, 0);
-    }
-
-    public void testfmodF32_4_relaxed() {
-        ScriptField_fmod_input_f32_4 floatArray = new ScriptField_fmod_input_f32_4(mRS, INPUTSIZE);
-        mIn = floatArray.getAllocation();
-        doF32_4_relaxed(0x12345, 0);
-    }
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/ForEachTest.java b/tests/tests/renderscript/src/android/renderscript/cts/ForEachTest.java
index 433b7e6..b90633e 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/ForEachTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/ForEachTest.java
@@ -48,8 +48,6 @@
 
 import android.renderscript.Type;
 
-import com.android.cts.stub.R;
-
 public class ForEachTest extends RSBaseCompute {
     /**
      * Test support for reflected forEach() as well as validation of parameters.
@@ -61,7 +59,7 @@
         Type t = new Type.Builder(mRS, Element.I8(mRS)).setX(x).create();
         Allocation badOut = Allocation.createTyped(mRS, t);
 
-        ScriptC_fe_all fe_all = new ScriptC_fe_all(mRS, mRes, R.raw.fe_all);
+        ScriptC_fe_all fe_all = new ScriptC_fe_all(mRS);
 
         // I8
         Allocation in = Allocation.createTyped(mRS, t);
@@ -461,7 +459,7 @@
 
 
     public void testMultipleForEach() {
-        ScriptC_foreach s = new ScriptC_foreach(mRS, mRes, R.raw.foreach);
+        ScriptC_foreach s = new ScriptC_foreach(mRS);
         Type.Builder typeBuilder = new Type.Builder(mRS, Element.I32(mRS));
 
         int X = 5;
@@ -470,7 +468,6 @@
         s.set_dimY(Y);
         typeBuilder.setX(X).setY(Y);
         Allocation A = Allocation.createTyped(mRS, typeBuilder.create());
-        s.bind_a(A);
         s.set_aRaw(A);
         s.forEach_root(A);
         s.invoke_verify_root();
@@ -478,11 +475,12 @@
         s.invoke_verify_foo();
         s.invoke_foreach_test();
         mRS.finish();
+        checkForErrors();
         waitForMessage();
     }
 
     public void testNoRoot() {
-        ScriptC_noroot s = new ScriptC_noroot(mRS, mRes, R.raw.noroot);
+        ScriptC_noroot s = new ScriptC_noroot(mRS);
         Type.Builder typeBuilder = new Type.Builder(mRS, Element.I32(mRS));
 
         int X = 5;
@@ -491,7 +489,6 @@
         s.set_dimY(Y);
         typeBuilder.setX(X).setY(Y);
         Allocation A = Allocation.createTyped(mRS, typeBuilder.create());
-        s.bind_a(A);
         s.set_aRaw(A);
         s.forEach_foo(A, A);
         s.invoke_verify_foo();
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/GetAllocationTest.java b/tests/tests/renderscript/src/android/renderscript/cts/GetAllocationTest.java
index e447224..f938569 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/GetAllocationTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/GetAllocationTest.java
@@ -19,7 +19,6 @@
 import android.renderscript.Allocation;
 import android.renderscript.Element;
 import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
 import java.util.Random;
 
 public class GetAllocationTest extends RSBaseCompute {
@@ -31,7 +30,7 @@
             tempArray[i] = random.nextInt();
         }
         ScriptC_get_allocation ms =
-                new ScriptC_get_allocation(mRS, mRes, R.raw.get_allocation);
+                new ScriptC_get_allocation(mRS);
 
         Allocation mTemp = Allocation.createSized(mRS, Element.I32(mRS), INPUTSIZE);
         mTemp.copyFrom(tempArray);
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/GetElementAt.java b/tests/tests/renderscript/src/android/renderscript/cts/GetElementAt.java
index babc1ef..be56a62 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/GetElementAt.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/GetElementAt.java
@@ -20,7 +20,6 @@
 import android.renderscript.Element;
 import android.renderscript.Type;
 import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
 import java.util.Random;
 
 public class GetElementAt extends RSBaseCompute {
@@ -56,7 +55,7 @@
 
     public void testX () {
         setupArrays(INPUTSIZE);
-        script_x = new ScriptC_get_element_at_x(mRS, mRes, R.raw.get_element_at_x);
+        script_x = new ScriptC_get_element_at_x(mRS);
         gIn = Allocation.createSized(mRS, Element.U32(mRS), INPUTSIZE);
         gIn.copyFrom(in);
         mOut = Allocation.createTyped(mRS, gIn.getType());
@@ -73,7 +72,7 @@
 
     public void testXY () {
         setupArrays(INPUTSIZE*INPUTSIZE);
-        script_xy = new ScriptC_get_element_at_x_y(mRS, mRes, R.raw.get_element_at_x_y);
+        script_xy = new ScriptC_get_element_at_x_y(mRS);
         Type.Builder builder = new Type.Builder(mRS, Element.U32(mRS));
         builder.setX(INPUTSIZE);
         builder.setY(INPUTSIZE);
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/HypotTest.java b/tests/tests/renderscript/src/android/renderscript/cts/HypotTest.java
deleted file mode 100644
index c5ce887..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/HypotTest.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import android.renderscript.Element;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-public class HypotTest extends RSBaseCompute {
-    private ScriptC_hypot_f32 script_f32;
-    private ScriptC_hypot_f32_relaxed script_f32_relaxed;
-    private Allocation mIn;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_hypot_f32(mRS);
-        script_f32_relaxed = new ScriptC_hypot_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_hypot_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_hypot_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_hypot_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_hypot_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_hypot_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_hypot_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_hypot_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_hypot_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx = i * stride * 2 + j;
-                ref[i * (stride - skip) + j] = (float)Math.hypot((double)in[idx], (double)in[idx+stride]);
-            }
-        }
-        return ref;
-    }
-
-    @Override
-    protected Allocation setInAlloc(Element e) {
-        return mIn;
-    }
-
-    @Override
-    protected float[] makeInArray(int size) {
-        return new float[size*2];
-    }
-
-    public void testHypotF32() {
-        ScriptField_hypot_f32_in in = new ScriptField_hypot_f32_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32(0x123678, 4);
-    }
-
-    public void testHypotF32_relaxed() {
-        ScriptField_hypot_f32_in in = new ScriptField_hypot_f32_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_relaxed(0x123678, 4);
-    }
-
-    public void testHypotF32_2() {
-        ScriptField_hypot_f32_2_in in = new ScriptField_hypot_f32_2_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_2(0x1234a5, 4);
-    }
-
-    public void testHypotF32_2_relaxed() {
-        ScriptField_hypot_f32_2_in in = new ScriptField_hypot_f32_2_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_2_relaxed(0x1234a5, 4);
-    }
-
-    public void testHypotF32_3() {
-        ScriptField_hypot_f32_3_in in = new ScriptField_hypot_f32_3_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_3(0x1af345, 4);
-    }
-
-    public void testHypotF32_3_relaxed() {
-        ScriptField_hypot_f32_3_in in = new ScriptField_hypot_f32_3_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_3_relaxed(0x1af345, 4);
-    }
-
-    public void testHypotF32_4() {
-        ScriptField_hypot_f32_4_in in = new ScriptField_hypot_f32_4_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_4(0x12ce45, 4);
-    }
-
-    public void testHypotF32_4_relaxed() {
-        ScriptField_hypot_f32_4_in in = new ScriptField_hypot_f32_4_in(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_4_relaxed(0x12ce45, 4);
-    }
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/ImageProcessingTest.java b/tests/tests/renderscript/src/android/renderscript/cts/ImageProcessingTest.java
index fae20f4..f38bdb0 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/ImageProcessingTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/ImageProcessingTest.java
@@ -59,8 +59,6 @@
 import android.renderscript.ScriptIntrinsicConvolve5x5;
 import android.renderscript.ScriptIntrinsicLUT;
 
-import com.android.cts.stub.R;
-
 public class ImageProcessingTest extends RSBaseCompute {
     private Allocation a1, a2;
 
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/InitTest.java b/tests/tests/renderscript/src/android/renderscript/cts/InitTest.java
index 848c192..ec22249 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/InitTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/InitTest.java
@@ -19,7 +19,6 @@
 import android.renderscript.Allocation;
 import android.renderscript.Element;
 import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
 
 public class InitTest extends RSBaseCompute {
     private Allocation mIn;
@@ -32,7 +31,7 @@
     }
 
     public void testInitTest() {
-        script = new ScriptC_init_test(mRS, mRes, R.raw.init_test);
+        script = new ScriptC_init_test(mRS);
         float[] ref = new float[INPUTSIZE];
         float[] in = new float[INPUTSIZE];
         float[] out = new float[INPUTSIZE];
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/Intrinsic3DLut.java b/tests/tests/renderscript/src/android/renderscript/cts/Intrinsic3DLut.java
new file mode 100644
index 0000000..87a03ad
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/Intrinsic3DLut.java
@@ -0,0 +1,140 @@
+/*
+ * 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 android.renderscript.*;
+import android.util.Log;
+
+public class Intrinsic3DLut extends IntrinsicBase {
+    private Allocation mCube;
+    private ScriptC_intrinsic_3dlut mScript;
+    private ScriptIntrinsic3DLUT mIntrinsic;
+    final int sx = 32;
+    final int sy = 32;
+    final int sz = 16;
+
+    private void genCubeIdent() {
+        int dat[] = new int[sx * sy * sz];
+        for (int z = 0; z < sz; z++) {
+            for (int y = 0; y < sy; y++) {
+                for (int x = 0; x < sx; x++ ) {
+                    int v = 0xff000000;
+                    v |= (0xff * x / (sx - 1));
+                    v |= (0xff * y / (sy - 1)) << 8;
+                    v |= (0xff * z / (sz - 1)) << 16;
+                    dat[z*sy*sx + y*sx + x] = v;
+                }
+            }
+        }
+
+        mCube.copyFromUnchecked(dat);
+    }
+
+    private void genCubeRand() {
+        java.util.Random r = new java.util.Random(100);
+        int dat[] = new int[sx * sy * sz];
+        for (int z = 0; z < sz; z++) {
+            for (int y = 0; y < sy; y++) {
+                for (int x = 0; x < sx; x++ ) {
+                    int v = 0xff000000;
+                    v |= r.nextInt(0x100);
+                    v |= r.nextInt(0x100) << 8;
+                    v |= r.nextInt(0x100) << 16;
+                    dat[z*sy*sx + y*sx + x] = v;
+                }
+            }
+        }
+
+        mCube.copyFromUnchecked(dat);
+    }
+
+    private void initCube() {
+        Type.Builder tb = new Type.Builder(mRS, Element.U8_4(mRS));
+        tb.setX(sx);
+        tb.setY(sy);
+        tb.setZ(sz);
+        Type t = tb.create();
+        mCube = Allocation.createTyped(mRS, t);
+        genCubeIdent();
+
+        mScript = new ScriptC_intrinsic_3dlut(mRS);
+        mScript.invoke_setCube(mCube);
+
+        mIntrinsic = ScriptIntrinsic3DLUT.create(mRS, Element.U8_4(mRS));
+        mIntrinsic.setLUT(mCube);
+    }
+
+    public void test1() {
+        initCube();
+        makeBuffers(97, 97, Element.U8_4(mRS));
+
+        mIntrinsic.forEach(mAllocSrc, mAllocDst);
+        mScript.forEach_root(mAllocSrc, mAllocRef);
+
+        mVerify.set_gAllowedIntError(1);
+        mVerify.invoke_verify(mAllocRef, mAllocDst, mAllocSrc);
+        mRS.finish();
+        checkError();
+    }
+
+    public void test2() {
+        initCube();
+        makeBuffers(97, 97, Element.U8_4(mRS));
+        genCubeRand();
+
+        mIntrinsic.forEach(mAllocSrc, mAllocDst);
+        mScript.forEach_root(mAllocSrc, mAllocRef);
+
+        mVerify.set_gAllowedIntError(2);
+        mVerify.invoke_verify(mAllocRef, mAllocDst, mAllocSrc);
+        mRS.finish();
+        checkError();
+    }
+
+    public void test1C() {
+        initCube();
+        makeBuffers(97, 97, Element.U8_4(mRS));
+
+        Script.LaunchOptions lo = makeClipper(11, 11, 87, 87);
+
+        mIntrinsic.forEach(mAllocSrc, mAllocDst, lo);
+        mScript.forEach_root(mAllocSrc, mAllocRef, lo);
+
+        mVerify.set_gAllowedIntError(1);
+        mVerify.invoke_verify(mAllocRef, mAllocDst, mAllocSrc);
+        mRS.finish();
+        checkError();
+    }
+
+    public void test2C() {
+        initCube();
+        makeBuffers(97, 97, Element.U8_4(mRS));
+        genCubeRand();
+
+        Script.LaunchOptions lo = makeClipper(11, 11, 87, 87);
+
+        mIntrinsic.forEach(mAllocSrc, mAllocDst, lo);
+        mScript.forEach_root(mAllocSrc, mAllocRef, lo);
+
+        mVerify.set_gAllowedIntError(2);
+        mVerify.invoke_verify(mAllocRef, mAllocDst, mAllocSrc);
+        mRS.finish();
+        checkError();
+    }
+
+
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicBase.java b/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicBase.java
index 7d952f6..6a1c944 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicBase.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicBase.java
@@ -21,6 +21,7 @@
 import android.renderscript.Allocation;
 import android.renderscript.Element;
 import android.renderscript.Type;
+import android.renderscript.Script;
 
 public class IntrinsicBase extends RSBaseCompute {
     protected final String TAG = "Img";
@@ -59,12 +60,24 @@
         return e;
     }
 
-    protected Allocation makeAllocation(int w, int h, Element e) {
+    protected Allocation makeAllocation(int w, int h, Element e, boolean clear) {
         Type.Builder tb = new Type.Builder(mRS, e);
         tb.setX(w);
         tb.setY(h);
         Type t = tb.create();
-        return Allocation.createTyped(mRS, t);
+        Allocation a = Allocation.createTyped(mRS, t);
+
+        if (clear) {
+            final int s = a.getBytesSize();
+            byte[] b = new byte[s];
+            a.copyFromUnchecked(b);
+        }
+
+        return a;
+    }
+
+    protected Allocation makeAllocation(int w, int h, Element e) {
+        return makeAllocation(w, h, e, true);
     }
 
     protected void makeSource(int w, int h, Element e) {
@@ -111,8 +124,8 @@
         if (mAllocDst != null) {
             mAllocDst.destroy();
         }
-        mAllocRef = Allocation.createTyped(mRS, mAllocSrc.getType());
-        mAllocDst = Allocation.createTyped(mRS, mAllocSrc.getType());
+        mAllocRef = makeAllocation(w, h, e);
+        mAllocDst = makeAllocation(w, h, e);
     }
 
 
@@ -123,4 +136,11 @@
         checkForErrors();
     }
 
+    protected Script.LaunchOptions makeClipper(int x, int y, int x2, int y2) {
+        Script.LaunchOptions lo = new Script.LaunchOptions();
+        lo.setX(x, x2);
+        lo.setY(y, y2);
+        return lo;
+    }
+
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicBlur.java b/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicBlur.java
new file mode 100644
index 0000000..076dcd4
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicBlur.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2013 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 android.renderscript.*;
+import android.util.Log;
+
+public class IntrinsicBlur extends IntrinsicBase {
+    private ScriptIntrinsicBlur mIntrinsic;
+    private int MAX_RADIUS = 25;
+    private ScriptC_intrinsic_blur mScript;
+    private float mRadius = MAX_RADIUS;
+    private float mSaturation = 1.0f;
+    private Allocation mScratchPixelsAllocation1;
+    private Allocation mScratchPixelsAllocation2;
+
+
+
+    private void initTest(int w, int h, Element e, Script.LaunchOptions lo) {
+        makeBuffers(w, h, e);
+
+        Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS));
+        tb.setX(w);
+        tb.setY(h);
+        mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create());
+        mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create());
+
+        mIntrinsic = ScriptIntrinsicBlur.create(mRS, e);
+        mIntrinsic.setRadius(MAX_RADIUS);
+        mIntrinsic.setInput(mAllocSrc);
+
+        mScript = new ScriptC_intrinsic_blur(mRS);
+        mScript.set_width(w);
+        mScript.set_height(h);
+        mScript.invoke_setRadius(MAX_RADIUS);
+
+        mScript.set_ScratchPixel1(mScratchPixelsAllocation1);
+        mScript.set_ScratchPixel2(mScratchPixelsAllocation2);
+
+        // Make reference
+        copyInput();
+        mScript.forEach_horz(mScratchPixelsAllocation2);
+        mScript.forEach_vert(mScratchPixelsAllocation1);
+        copyOutput(lo);
+    }
+
+    private void copyInput() {
+        if (mAllocSrc.getType().getElement().isCompatible(Element.U8(mRS))) {
+            mScript.forEach_convert1_uToF(mAllocSrc, mScratchPixelsAllocation1);
+            return;
+        }
+        if (mAllocSrc.getType().getElement().isCompatible(Element.U8_4(mRS))) {
+            mScript.forEach_convert4_uToF(mAllocSrc, mScratchPixelsAllocation1);
+            return;
+        }
+        throw new IllegalArgumentException("bad type");
+    }
+
+    private void copyOutput(Script.LaunchOptions lo) {
+        if (mAllocSrc.getType().getElement().isCompatible(Element.U8(mRS))) {
+            mScript.forEach_convert1_fToU(mScratchPixelsAllocation1, mAllocRef, lo);
+            return;
+        }
+        if (mAllocSrc.getType().getElement().isCompatible(Element.U8_4(mRS))) {
+            mScript.forEach_convert4_fToU(mScratchPixelsAllocation1, mAllocRef, lo);
+            return;
+        }
+        throw new IllegalArgumentException("bad type");
+    }
+
+    public void testU8_1() {
+        final int w = 97;
+        final int h = 97;
+        Element e = Element.U8(mRS);
+        initTest(w, h, e, null);
+
+        mIntrinsic.forEach(mAllocDst);
+
+        mVerify.set_gAllowedIntError(1);
+        mVerify.invoke_verify(mAllocRef, mAllocDst, mAllocSrc);
+        mRS.finish();
+        checkError();
+    }
+
+    public void testU8_4() {
+        final int w = 97;
+        final int h = 97;
+        Element e = Element.U8_4(mRS);
+        initTest(w, h, e, null);
+
+        mIntrinsic.forEach(mAllocDst);
+
+        mVerify.set_gAllowedIntError(1);
+        mVerify.invoke_verify(mAllocRef, mAllocDst, mAllocSrc);
+        mRS.finish();
+        checkError();
+    }
+
+
+    public void testU8_1C() {
+        final int w = 97;
+        final int h = 97;
+        Element e = Element.U8(mRS);
+        Script.LaunchOptions lo = makeClipper(11, 11, w - 11, h - 11);
+
+        initTest(w, h, e, lo);
+        mIntrinsic.forEach(mAllocDst, lo);
+
+        mVerify.set_gAllowedIntError(1);
+        mVerify.invoke_verify(mAllocRef, mAllocDst, mAllocSrc);
+        mRS.finish();
+        checkError();
+    }
+
+    public void testU8_4C() {
+        final int w = 97;
+        final int h = 97;
+        Element e = Element.U8_4(mRS);
+        Script.LaunchOptions lo = makeClipper(11, 11, w - 11, h - 11);
+
+        initTest(w, h, e, lo);
+        mIntrinsic.forEach(mAllocDst, lo);
+
+        mVerify.set_gAllowedIntError(1);
+        mVerify.invoke_verify(mAllocRef, mAllocDst, mAllocSrc);
+        mRS.finish();
+        checkError();
+    }
+
+
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicColorMatrix.java b/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicColorMatrix.java
index 2ac7d6f..ac48783 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicColorMatrix.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicColorMatrix.java
@@ -25,7 +25,8 @@
 
     private void subtest(int w, int h, Matrix4f mat, Float4 add,
                          Element.DataType dtIn, int vsIn,
-                         Element.DataType dtOut, int vsOut) {
+                         Element.DataType dtOut, int vsOut,
+                         boolean clip) {
 
 
         if (mat == null) {
@@ -42,21 +43,34 @@
 
 
         makeSource(w, h, ein);
-        mAllocRef = makeAllocation(w, h, eout);
-        mAllocDst = makeAllocation(w, h, eout);
+        mAllocRef = makeAllocation(w, h, eout, true);
+        mAllocDst = makeAllocation(w, h, eout, true);
+
+        int x1 = 0, y1 = 0, x2 = w, y2 = h;
+        if (clip) {
+            x1 = 11;
+            y1 = 11;
+            x2 = w - 11;
+            y2 = h - 11;
+        }
 
         mSi.setColorMatrix(mat);
         mSi.setAdd(add);
-        mSi.forEach(mAllocSrc, mAllocDst);
-        mSr.invoke_reference(mat, add, mAllocSrc, mAllocRef);
+        if (clip) {
+            mSi.forEach(mAllocSrc, mAllocDst, makeClipper(x1, y1, x2, y2));
+        } else {
+            mSi.forEach(mAllocSrc, mAllocDst);
+        }
+        mSr.invoke_reference(mat, add, mAllocSrc, mAllocRef, x1, y1, x2, y2);
 
-        android.util.Log.e("RSI test", "test ColorMatrix  vsin=" + vsIn + ", vsout=" + vsOut + ",  dim " + w + ", " + h);
+        //android.util.Log.e("RSI test", "test ColorMatrix  vsin=" + vsIn + ", vsout=" + vsOut + ",  dim " + w + ", " + h);
         mVerify.invoke_verify(mAllocRef, mAllocDst, mAllocSrc);
         mRS.finish();
     }
 
 
-    private void test(Element.DataType dtin, Element.DataType dtout, int subtest) {
+    private void test(Element.DataType dtin, Element.DataType dtout, int subtest,
+                      boolean clip) {
         Float4 add = new Float4();
         Matrix4f mat = new Matrix4f();
         java.util.Random r = new java.util.Random(100);
@@ -99,52 +113,84 @@
                     add.w = r.nextFloat() * (subtest - 1);
                 }
             }
-            android.util.Log.v("rs", "Mat [" + f[0] + ", " + f[4] + ", " + f[8] + ", " + f[12] + "]");
-            android.util.Log.v("rs", "    [" + f[1] + ", " + f[5] + ", " + f[9] + ", " + f[13] + "]");
-            android.util.Log.v("rs", "    [" + f[2] + ", " + f[6] + ", " + f[10] + ", " + f[14] + "]");
-            android.util.Log.v("rs", "    [" + f[3] + ", " + f[7] + ", " + f[11] + ", " + f[15] + "]");
+            //android.util.Log.v("rs", "Mat [" + f[0] + ", " + f[4] + ", " + f[8] + ", " + f[12] + "]");
+            //android.util.Log.v("rs", "    [" + f[1] + ", " + f[5] + ", " + f[9] + ", " + f[13] + "]");
+            //android.util.Log.v("rs", "    [" + f[2] + ", " + f[6] + ", " + f[10] + ", " + f[14] + "]");
+            //android.util.Log.v("rs", "    [" + f[3] + ", " + f[7] + ", " + f[11] + ", " + f[15] + "]");
         }
 
         for (int i=1; i <= 4; i++) {
             for (int j=1; j <=4; j++) {
                 subtest(101, 101, mat, add,
-                        dtin, i,
-                        dtout, j);
+                        dtin, i, dtout, j, clip);
             }
         }
         checkError();
     }
 
     public void test_U8_U8_Ident() {
-        test(Element.DataType.UNSIGNED_8, Element.DataType.UNSIGNED_8, 0);
+        test(Element.DataType.UNSIGNED_8, Element.DataType.UNSIGNED_8, 0, false);
     }
 
     public void test_F32_F32_Ident() {
-        test(Element.DataType.FLOAT_32, Element.DataType.FLOAT_32, 0);
+        test(Element.DataType.FLOAT_32, Element.DataType.FLOAT_32, 0, false);
     }
 
     public void test_U8_F32_Ident() {
-        test(Element.DataType.UNSIGNED_8, Element.DataType.FLOAT_32, 0);
+        test(Element.DataType.UNSIGNED_8, Element.DataType.FLOAT_32, 0, false);
     }
 
     public void test_F32_U8_Ident() {
-        test(Element.DataType.FLOAT_32, Element.DataType.UNSIGNED_8, 0);
+        test(Element.DataType.FLOAT_32, Element.DataType.UNSIGNED_8, 0, false);
     }
 
     public void test_U8_U8_Rand() {
-        test(Element.DataType.UNSIGNED_8, Element.DataType.UNSIGNED_8, 2);
+        test(Element.DataType.UNSIGNED_8, Element.DataType.UNSIGNED_8, 2, false);
     }
 
     public void test_F32_F32_Rand() {
-        test(Element.DataType.FLOAT_32, Element.DataType.FLOAT_32, 10);
+        test(Element.DataType.FLOAT_32, Element.DataType.FLOAT_32, 10, false);
     }
 
     public void test_U8_F32_Rand() {
-        test(Element.DataType.UNSIGNED_8, Element.DataType.FLOAT_32, 10);
+        test(Element.DataType.UNSIGNED_8, Element.DataType.FLOAT_32, 10, false);
     }
 
     public void test_F32_U8_Rand() {
-        test(Element.DataType.FLOAT_32, Element.DataType.UNSIGNED_8, 10);
+        test(Element.DataType.FLOAT_32, Element.DataType.UNSIGNED_8, 10, false);
     }
 
+
+
+    public void test_U8_U8_IdentC() {
+        test(Element.DataType.UNSIGNED_8, Element.DataType.UNSIGNED_8, 0, true);
+    }
+
+    public void test_F32_F32_IdentC() {
+        test(Element.DataType.FLOAT_32, Element.DataType.FLOAT_32, 0, true);
+    }
+
+    public void test_U8_F32_IdentC() {
+        test(Element.DataType.UNSIGNED_8, Element.DataType.FLOAT_32, 0, true);
+    }
+
+    public void test_F32_U8_IdentC() {
+        test(Element.DataType.FLOAT_32, Element.DataType.UNSIGNED_8, 0, true);
+    }
+
+    public void test_U8_U8_RandC() {
+        test(Element.DataType.UNSIGNED_8, Element.DataType.UNSIGNED_8, 2, true);
+    }
+
+    public void test_F32_F32_RandC() {
+        test(Element.DataType.FLOAT_32, Element.DataType.FLOAT_32, 10, true);
+    }
+
+    public void test_U8_F32_RandC() {
+        test(Element.DataType.UNSIGNED_8, Element.DataType.FLOAT_32, 10, true);
+    }
+
+    public void test_F32_U8_RandC() {
+        test(Element.DataType.FLOAT_32, Element.DataType.UNSIGNED_8, 10, true);
+    }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicConvolve3x3.java b/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicConvolve3x3.java
index 12eae9a..1880132 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicConvolve3x3.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicConvolve3x3.java
@@ -20,138 +20,187 @@
 import android.util.Log;
 
 public class IntrinsicConvolve3x3 extends IntrinsicBase {
-    private void testConvolve3(int w, int h, Element.DataType dt, int vecSize) {
+    private void testConvolve3(int w, int h, Element.DataType dt, int vecSize, Script.LaunchOptions sc) {
         float cf1[] = {0.f, 0.f, 0.f,  0.f, 1.f, 0.f,  0.f, 0.f, 0.f};
         float cf2[] = {0.f, -1.f, 0.f,  -1.f, 5.f, -1.f,  0.f, -1.f, 0.f};
 
-
         Element e = makeElement(dt, vecSize);
 
         System.gc();
         makeBuffers(w, h, e);
 
-
         ScriptIntrinsicConvolve3x3 si = ScriptIntrinsicConvolve3x3.create(mRS, e);
         si.setCoefficients(cf1);
         si.setInput(mAllocSrc);
-        si.forEach(mAllocRef);
+        si.forEach(mAllocRef, sc);
 
         ScriptC_intrinsic_convolve3x3 sr = new ScriptC_intrinsic_convolve3x3(mRS);
         sr.set_gCoeffs(cf1);
         sr.set_gIn(mAllocSrc);
         sr.set_gWidth(w);
         sr.set_gHeight(h);
+
+        if (sc != null) {
+            mAllocRef.copyFrom(mAllocSrc);
+            mAllocDst.copyFrom(mAllocSrc);
+        }
+
         if (dt == Element.DataType.UNSIGNED_8) {
             switch(vecSize) {
             case 4:
-                sr.forEach_convolve_U4(mAllocDst);
+                sr.forEach_convolve_U4(mAllocDst, sc);
                 break;
             case 3:
-                sr.forEach_convolve_U3(mAllocDst);
+                sr.forEach_convolve_U3(mAllocDst, sc);
                 break;
             case 2:
-                sr.forEach_convolve_U2(mAllocDst);
+                sr.forEach_convolve_U2(mAllocDst, sc);
                 break;
             case 1:
-                sr.forEach_convolve_U1(mAllocDst);
+                sr.forEach_convolve_U1(mAllocDst, sc);
                 break;
             }
         } else {
             switch(vecSize) {
             case 4:
-                sr.forEach_convolve_F4(mAllocDst);
+                sr.forEach_convolve_F4(mAllocDst, sc);
                 break;
             case 3:
-                sr.forEach_convolve_F3(mAllocDst);
+                sr.forEach_convolve_F3(mAllocDst, sc);
                 break;
             case 2:
-                sr.forEach_convolve_F2(mAllocDst);
+                sr.forEach_convolve_F2(mAllocDst, sc);
                 break;
             case 1:
-                sr.forEach_convolve_F1(mAllocDst);
+                sr.forEach_convolve_F1(mAllocDst, sc);
                 break;
             }
         }
 
-        android.util.Log.e("RSI test", "test convolve U8_" + vecSize + " 1 " + w + ", " + h);
+        //android.util.Log.e("RSI test", "test convolve U8_" + vecSize + " 1 " + w + ", " + h);
         mVerify.invoke_verify(mAllocRef, mAllocDst, mAllocSrc);
 
         si.setCoefficients(cf2);
         sr.set_gCoeffs(cf2);
-        si.forEach(mAllocRef);
+        si.forEach(mAllocRef, sc);
         if (dt == Element.DataType.UNSIGNED_8) {
             switch(vecSize) {
             case 4:
-                sr.forEach_convolve_U4(mAllocDst);
+                sr.forEach_convolve_U4(mAllocDst, sc);
                 break;
             case 3:
-                sr.forEach_convolve_U3(mAllocDst);
+                sr.forEach_convolve_U3(mAllocDst, sc);
                 break;
             case 2:
-                sr.forEach_convolve_U2(mAllocDst);
+                sr.forEach_convolve_U2(mAllocDst, sc);
                 break;
             case 1:
-                sr.forEach_convolve_U1(mAllocDst);
+                sr.forEach_convolve_U1(mAllocDst, sc);
                 break;
             }
         } else {
             switch(vecSize) {
             case 4:
-                sr.forEach_convolve_F4(mAllocDst);
+                sr.forEach_convolve_F4(mAllocDst, sc);
                 break;
             case 3:
-                sr.forEach_convolve_F3(mAllocDst);
+                sr.forEach_convolve_F3(mAllocDst, sc);
                 break;
             case 2:
-                sr.forEach_convolve_F2(mAllocDst);
+                sr.forEach_convolve_F2(mAllocDst, sc);
                 break;
             case 1:
-                sr.forEach_convolve_F1(mAllocDst);
+                sr.forEach_convolve_F1(mAllocDst, sc);
                 break;
             }
         }
-        android.util.Log.e("RSI test", "test convolve U8_" + vecSize + " 2 " + w + ", " + h);
+        //android.util.Log.e("RSI test", "test convolve U8_" + vecSize + " 2 " + w + ", " + h);
         mVerify.invoke_verify(mAllocRef, mAllocDst, mAllocSrc);
         mRS.finish();
     }
 
 
     public void test_U8_4() {
-        testConvolve3(100, 100, Element.DataType.UNSIGNED_8, 4);
+        testConvolve3(100, 100, Element.DataType.UNSIGNED_8, 4, null);
         checkError();
     }
     public void test_U8_3() {
-        testConvolve3(100, 100, Element.DataType.UNSIGNED_8, 3);
+        testConvolve3(100, 100, Element.DataType.UNSIGNED_8, 3, null);
         checkError();
     }
     public void test_U8_2() {
-        testConvolve3(100, 100, Element.DataType.UNSIGNED_8, 2);
+        testConvolve3(100, 100, Element.DataType.UNSIGNED_8, 2, null);
         checkError();
     }
     public void test_U8_1() {
-        testConvolve3(100, 100, Element.DataType.UNSIGNED_8, 1);
+        testConvolve3(100, 100, Element.DataType.UNSIGNED_8, 1, null);
         checkError();
     }
 
     public void test_F32_4() {
-        testConvolve3(100, 100, Element.DataType.FLOAT_32, 4);
+        testConvolve3(100, 100, Element.DataType.FLOAT_32, 4, null);
         checkError();
     }
 
     public void test_F32_3() {
-        testConvolve3(100, 100, Element.DataType.FLOAT_32, 3);
+        testConvolve3(100, 100, Element.DataType.FLOAT_32, 3, null);
         checkError();
     }
 
     public void test_F32_2() {
-        testConvolve3(100, 100, Element.DataType.FLOAT_32, 2);
+        testConvolve3(100, 100, Element.DataType.FLOAT_32, 2, null);
         checkError();
     }
 
     public void test_F32_1() {
-        testConvolve3(100, 100, Element.DataType.FLOAT_32, 1);
+        testConvolve3(100, 100, Element.DataType.FLOAT_32, 1, null);
         checkError();
     }
 
 
+    public void test_U8_4C() {
+        testConvolve3(100, 100, Element.DataType.UNSIGNED_8, 4,
+                      makeClipper(11, 11, 90, 90));
+        checkError();
+    }
+    public void test_U8_3C() {
+        testConvolve3(100, 100, Element.DataType.UNSIGNED_8, 3,
+                      makeClipper(11, 11, 90, 90));
+        checkError();
+    }
+    public void test_U8_2C() {
+        testConvolve3(100, 100, Element.DataType.UNSIGNED_8, 2,
+                      makeClipper(11, 11, 90, 90));
+        checkError();
+    }
+    public void test_U8_1C() {
+        testConvolve3(100, 100, Element.DataType.UNSIGNED_8, 1,
+                      makeClipper(11, 11, 90, 90));
+        checkError();
+    }
+
+    public void test_F32_4C() {
+        testConvolve3(100, 100, Element.DataType.FLOAT_32, 4,
+                      makeClipper(11, 11, 90, 90));
+        checkError();
+    }
+
+    public void test_F32_3C() {
+        testConvolve3(100, 100, Element.DataType.FLOAT_32, 3,
+                      makeClipper(11, 11, 90, 90));
+        checkError();
+    }
+
+    public void test_F32_2C() {
+        testConvolve3(100, 100, Element.DataType.FLOAT_32, 2,
+                      makeClipper(11, 11, 90, 90));
+        checkError();
+    }
+
+    public void test_F32_1C() {
+        testConvolve3(100, 100, Element.DataType.FLOAT_32, 1,
+                      makeClipper(11, 11, 90, 90));
+        checkError();
+    }
+
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicConvolve5x5.java b/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicConvolve5x5.java
index 482db59..ee92651 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicConvolve5x5.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicConvolve5x5.java
@@ -21,10 +21,16 @@
 
 public class IntrinsicConvolve5x5 extends IntrinsicBase {
     private void test5(ScriptC_intrinsic_convolve5x5 sr, ScriptIntrinsicConvolve5x5 si,
-                        Element e, float cf[], String name, int num, int w, int h) {
+                       Element e, float cf[], String name, int num, int w, int h,
+                       Script.LaunchOptions sc) {
         si.setCoefficients(cf);
         si.setInput(mAllocSrc);
-        si.forEach(mAllocRef);
+
+        if (sc != null) {
+            mAllocRef.copyFrom(mAllocSrc);
+            mAllocDst.copyFrom(mAllocSrc);
+        }
+        si.forEach(mAllocRef, sc);
 
         sr.set_gWidth(w);
         sr.set_gHeight(h);
@@ -33,41 +39,41 @@
         if (e.getDataType() == Element.DataType.UNSIGNED_8) {
             switch(e.getVectorSize()) {
             case 4:
-                sr.forEach_convolve_U4(mAllocDst);
+                sr.forEach_convolve_U4(mAllocDst, sc);
                 break;
             case 3:
-                sr.forEach_convolve_U3(mAllocDst);
+                sr.forEach_convolve_U3(mAllocDst, sc);
                 break;
             case 2:
-                sr.forEach_convolve_U2(mAllocDst);
+                sr.forEach_convolve_U2(mAllocDst, sc);
                 break;
             case 1:
-                sr.forEach_convolve_U1(mAllocDst);
+                sr.forEach_convolve_U1(mAllocDst, sc);
                 break;
             }
         } else {
             switch(e.getVectorSize()) {
             case 4:
-                sr.forEach_convolve_F4(mAllocDst);
+                sr.forEach_convolve_F4(mAllocDst, sc);
                 break;
             case 3:
-                sr.forEach_convolve_F3(mAllocDst);
+                sr.forEach_convolve_F3(mAllocDst, sc);
                 break;
             case 2:
-                sr.forEach_convolve_F2(mAllocDst);
+                sr.forEach_convolve_F2(mAllocDst, sc);
                 break;
             case 1:
-                sr.forEach_convolve_F1(mAllocDst);
+                sr.forEach_convolve_F1(mAllocDst, sc);
                 break;
             }
         }
 
-        android.util.Log.e("RSI test", name + "  " + e.getVectorSize() + " " + num + " " + w + ", " + h);
+        //android.util.Log.e("RSI test", name + "  " + e.getVectorSize() + " " + num + " " + w + ", " + h);
         mVerify.invoke_verify(mAllocRef, mAllocDst, mAllocSrc);
         mRS.finish();
     }
 
-    private void testConvolve5(int w, int h, Element.DataType dt, int vecSize) {
+    private void testConvolve5(int w, int h, Element.DataType dt, int vecSize, Script.LaunchOptions sc) {
         float cf1[] = { 0.f,  0.f,  0.f,  0.f,  0.f,
                         0.f,  0.f,  0.f,  0.f,  0.f,
                         0.f,  0.f,  1.f,  0.f,  0.f,
@@ -84,43 +90,87 @@
 
         ScriptIntrinsicConvolve5x5 si = ScriptIntrinsicConvolve5x5.create(mRS, e);
         ScriptC_intrinsic_convolve5x5 sr = new ScriptC_intrinsic_convolve5x5(mRS);
-        test5(sr, si, e, cf1, "test convolve", 1, w, h);
-        test5(sr, si, e, cf2, "test convolve", 2, w, h);
+        test5(sr, si, e, cf1, "test convolve", 1, w, h, sc);
+        test5(sr, si, e, cf2, "test convolve", 2, w, h, sc);
     }
 
     public void test_U8_4() {
-        testConvolve5(100, 100, Element.DataType.UNSIGNED_8, 4);
+        testConvolve5(100, 100, Element.DataType.UNSIGNED_8, 4, null);
         checkError();
     }
     public void test_U8_3() {
-        testConvolve5(100, 100, Element.DataType.UNSIGNED_8, 3);
+        testConvolve5(100, 100, Element.DataType.UNSIGNED_8, 3, null);
         checkError();
     }
     public void test_U8_2() {
-        testConvolve5(100, 100, Element.DataType.UNSIGNED_8, 2);
+        testConvolve5(100, 100, Element.DataType.UNSIGNED_8, 2, null);
         checkError();
     }
     public void test_U8_1() {
-        testConvolve5(100, 100, Element.DataType.UNSIGNED_8, 1);
+        testConvolve5(100, 100, Element.DataType.UNSIGNED_8, 1, null);
         checkError();
     }
 
     public void test_F32_4() {
-        testConvolve5(100, 100, Element.DataType.FLOAT_32, 4);
+        testConvolve5(100, 100, Element.DataType.FLOAT_32, 4, null);
         checkError();
     }
     public void test_F32_3() {
-        testConvolve5(100, 100, Element.DataType.FLOAT_32, 3);
+        testConvolve5(100, 100, Element.DataType.FLOAT_32, 3, null);
         checkError();
     }
     public void test_F32_2() {
-        testConvolve5(100, 100, Element.DataType.FLOAT_32, 2);
+        testConvolve5(100, 100, Element.DataType.FLOAT_32, 2, null);
         checkError();
     }
     public void test_F32_1() {
-        testConvolve5(100, 100, Element.DataType.FLOAT_32, 1);
+        testConvolve5(100, 100, Element.DataType.FLOAT_32, 1, null);
         checkError();
     }
 
+    public void test_U8_4C() {
+        testConvolve5(100, 100, Element.DataType.UNSIGNED_8, 4,
+                      makeClipper(11, 11, 90, 90));
+        checkError();
+    }
+    public void test_U8_3C() {
+        testConvolve5(100, 100, Element.DataType.UNSIGNED_8, 3,
+                      makeClipper(11, 11, 90, 90));
+        checkError();
+    }
+    public void test_U8_2C() {
+        testConvolve5(100, 100, Element.DataType.UNSIGNED_8, 2,
+                      makeClipper(11, 11, 90, 90));
+        checkError();
+    }
+    public void test_U8_1C() {
+        testConvolve5(100, 100, Element.DataType.UNSIGNED_8, 1,
+                      makeClipper(11, 11, 90, 90));
+        checkError();
+    }
+
+    public void test_F32_4C() {
+        testConvolve5(100, 100, Element.DataType.FLOAT_32, 4,
+                      makeClipper(11, 11, 90, 90));
+        checkError();
+    }
+
+    public void test_F32_3C() {
+        testConvolve5(100, 100, Element.DataType.FLOAT_32, 3,
+                      makeClipper(11, 11, 90, 90));
+        checkError();
+    }
+
+    public void test_F32_2C() {
+        testConvolve5(100, 100, Element.DataType.FLOAT_32, 2,
+                      makeClipper(11, 11, 90, 90));
+        checkError();
+    }
+
+    public void test_F32_1C() {
+        testConvolve5(100, 100, Element.DataType.FLOAT_32, 1,
+                      makeClipper(11, 11, 90, 90));
+        checkError();
+    }
 
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicHistogram.java b/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicHistogram.java
index e970291..94cc4ce 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicHistogram.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicHistogram.java
@@ -48,7 +48,7 @@
         mAout = Allocation.createSized(mRS, e2, 256);
     }
 
-    private void testNorm(int inVSize, int outVSize, int w, int h) {
+    private void testNorm(int inVSize, int outVSize, int w, int h, boolean clip) {
         createAllocations(inVSize, outVSize, w, h);
 
         int invs2 = (inVSize != 3) ? inVSize : 4;
@@ -61,11 +61,27 @@
         java.util.Random r = new java.util.Random();
         r.nextBytes(i);
 
-        for (int ct=0; ct < i.length; ct++) {
-            int t = i[ct];
-            if (t < 0) t = 256 + t;
-            if ((ct % invs2) < outVSize) {
-                ref[(t * outvs2) + (ct % invs2)] ++;
+        int x1 = 0, y1 = 0, x2 = w, y2 = h;
+        if (clip) {
+            x1 = 11;
+            y1 = 11;
+            x2 = w - 11;
+            y2 = h - 11;
+        }
+
+        for (int y = y1; y < y2; y++) {
+            for (int x = x1; x < x2; x++) {
+                int ct = (y * w + x) * invs2;
+
+                int v = 0;
+                for (int c = 0; c < inVSize; c++) {
+                    int t = i[ct + c];
+                    if (t < 0) t = 256 + t;
+
+                    if (c < outVSize) {
+                        ref[(t * outvs2) + c] ++;
+                    }
+                }
             }
         }
 
@@ -73,7 +89,7 @@
         ScriptIntrinsicHistogram hist =
                 ScriptIntrinsicHistogram.create(mRS, mAin.getType().getElement());
         hist.setOutput(mAout);
-        hist.forEach(mAin);
+        hist.forEach(mAin, makeClipper(x1, y1, x2, y2));
 
         mAin.copyFrom(i);
         mAout.copyTo(res);
@@ -83,42 +99,77 @@
     }
 
     public void test_norm_4_4() {
-        testNorm(4, 4, 101, 101);
+        testNorm(4, 4, 101, 101, false);
     }
     public void test_norm_4_3() {
-        testNorm(4, 3, 101, 101);
+        testNorm(4, 3, 101, 101, false);
     }
     public void test_norm_4_2() {
-        testNorm(4, 2, 101, 101);
+        testNorm(4, 2, 101, 101, false);
     }
     public void test_norm_4_1() {
-        testNorm(4, 1, 101, 101);
+        testNorm(4, 1, 101, 101, false);
     }
 
     public void test_norm_3_3() {
-        testNorm(3, 3, 101, 101);
+        testNorm(3, 3, 101, 101, false);
     }
     public void test_norm_3_2() {
-        testNorm(3, 2, 101, 101);
+        testNorm(3, 2, 101, 101, false);
     }
     public void test_norm_3_1() {
-        testNorm(3, 1, 101, 101);
+        testNorm(3, 1, 101, 101, false);
     }
 
     public void test_norm_2_2() {
-        testNorm(2, 2, 101, 101);
+        testNorm(2, 2, 101, 101, false);
     }
     public void test_norm_2_1() {
-        testNorm(2, 1, 101, 101);
+        testNorm(2, 1, 101, 101, false);
     }
 
     public void test_norm_1_1() {
-        testNorm(1, 1, 101, 101);
+        testNorm(1, 1, 101, 101, false);
+    }
+
+
+    public void test_norm_4_4C() {
+        testNorm(4, 4, 101, 101, true);
+    }
+    public void test_norm_4_3C() {
+        testNorm(4, 3, 101, 101, true);
+    }
+    public void test_norm_4_2C() {
+        testNorm(4, 2, 101, 101, true);
+    }
+    public void test_norm_4_1C() {
+        testNorm(4, 1, 101, 101, true);
+    }
+
+    public void test_norm_3_3C() {
+        testNorm(3, 3, 101, 101, true);
+    }
+    public void test_norm_3_2C() {
+        testNorm(3, 2, 101, 101, true);
+    }
+    public void test_norm_3_1C() {
+        testNorm(3, 1, 101, 101, true);
+    }
+
+    public void test_norm_2_2C() {
+        testNorm(2, 2, 101, 101, true);
+    }
+    public void test_norm_2_1C() {
+        testNorm(2, 1, 101, 101, true);
+    }
+
+    public void test_norm_1_1C() {
+        testNorm(1, 1, 101, 101, true);
     }
 
 
 
-    private void testDot(int inVSize, int w, int h) {
+    private void testDot(int inVSize, int w, int h, boolean clip) {
         createAllocations(inVSize, 1, w, h);
 
         int invs2 = (inVSize != 3) ? inVSize : 4;
@@ -136,14 +187,26 @@
             doti[ct] = (int)((dotVals[ct] * 256.f) + 0.5f);
         }
 
-        for (int ct=0; ct < i.length; ct+=invs2) {
-            int v = 0;
-            for (int c = 0; c < inVSize; c++) {
-                int t = i[ct + c];
-                if (t < 0) t = 256 + t;
-                v += doti[c] * t;
+        int x1 = 0, y1 = 0, x2 = w, y2 = h;
+        if (clip) {
+            x1 = 11;
+            y1 = 11;
+            x2 = w - 11;
+            y2 = h - 11;
+        }
+
+        for (int y = y1; y < y2; y++) {
+            for (int x = x1; x < x2; x++) {
+                int ct = (y * w + x) * invs2;
+
+                int v = 0;
+                for (int c = 0; c < inVSize; c++) {
+                    int t = i[ct + c];
+                    if (t < 0) t = 256 + t;
+                    v += doti[c] * t;
+                }
+                ref[(v + 0x7f) >> 8] ++;
             }
-            ref[(v + 0x7f) >> 8] ++;
         }
 
         mAin.copyFrom(i);
@@ -151,7 +214,7 @@
                 ScriptIntrinsicHistogram.create(mRS, mAin.getType().getElement());
         hist.setOutput(mAout);
         hist.setDotCoefficients(dotVals[0], dotVals[1], dotVals[2], dotVals[3]);
-        hist.forEach_Dot(mAin);
+        hist.forEach_Dot(mAin, makeClipper(x1, y1, x2, y2));
 
         mAin.copyFrom(i);
         mAout.copyTo(res);
@@ -161,16 +224,30 @@
     }
 
     public void test_dot_1() {
-        testDot(1, 101, 101);
+        testDot(1, 101, 101, false);
     }
     public void test_dot_2() {
-        testDot(2, 101, 101);
+        testDot(2, 101, 101, false);
     }
     public void test_dot_3() {
-        testDot(3, 101, 101);
+        testDot(3, 101, 101, false);
     }
     public void test_dot_4() {
-        testDot(4, 101, 101);
+        testDot(4, 101, 101, false);
+    }
+
+
+    public void test_dot_1C() {
+        testDot(1, 101, 101, true);
+    }
+    public void test_dot_2C() {
+        testDot(2, 101, 101, true);
+    }
+    public void test_dot_3C() {
+        testDot(3, 101, 101, true);
+    }
+    public void test_dot_4C() {
+        testDot(4, 101, 101, true);
     }
 
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicLut.java b/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicLut.java
new file mode 100644
index 0000000..1567639
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/IntrinsicLut.java
@@ -0,0 +1,87 @@
+/*
+ * 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 android.renderscript.*;
+import android.util.Log;
+
+public class IntrinsicLut extends IntrinsicBase {
+    private ScriptIntrinsicLUT mIntrinsic;
+    private ScriptC_intrinsic_lut mScript;
+
+    short mRed[] = new short[256];
+    short mGreen[] = new short[256];
+    short mBlue[] = new short[256];
+    short mAlpha[] = new short[256];
+
+
+
+    public void createTest() {
+        java.util.Random r = new java.util.Random(100);
+
+        mIntrinsic = ScriptIntrinsicLUT.create(mRS, Element.U8_4(mRS));
+        mScript = new ScriptC_intrinsic_lut(mRS);
+
+        for (int ct=0; ct < 256; ct++) {
+            mRed[ct] = (short)r.nextInt(256);
+            mGreen[ct] = (short)r.nextInt(256);
+            mBlue[ct] = (short)r.nextInt(256);
+            mAlpha[ct] = (short)r.nextInt(256);
+            mIntrinsic.setRed(ct, mRed[ct]);
+            mIntrinsic.setGreen(ct, mGreen[ct]);
+            mIntrinsic.setBlue(ct, mBlue[ct]);
+            mIntrinsic.setAlpha(ct, mAlpha[ct]);
+        }
+        mScript.set_red(mRed);
+        mScript.set_green(mGreen);
+        mScript.set_blue(mBlue);
+        mScript.set_alpha(mAlpha);
+    }
+
+
+
+    public void test() {
+        createTest();
+        makeBuffers(97, 97, Element.U8_4(mRS));
+
+        mIntrinsic.forEach(mAllocSrc, mAllocDst);
+        mScript.forEach_root(mAllocSrc, mAllocRef);
+
+        mVerify.set_gAllowedIntError(0);
+        mVerify.invoke_verify(mAllocRef, mAllocDst, mAllocSrc);
+        mRS.finish();
+        checkError();
+    }
+
+    public void test1C() {
+        createTest();
+        makeBuffers(97, 97, Element.U8_4(mRS));
+
+        Script.LaunchOptions lo = makeClipper(11, 11, 87, 87);
+
+        mIntrinsic.forEach(mAllocSrc, mAllocDst, lo);
+        mScript.forEach_root(mAllocSrc, mAllocRef, lo);
+
+        mVerify.set_gAllowedIntError(0);
+        mVerify.invoke_verify(mAllocRef, mAllocDst, mAllocSrc);
+        mRS.finish();
+        checkError();
+    }
+
+
+
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/IsObjectTest.java b/tests/tests/renderscript/src/android/renderscript/cts/IsObjectTest.java
index 58ae448..0bb17cb 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/IsObjectTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/IsObjectTest.java
@@ -21,7 +21,6 @@
 import android.renderscript.Element;
 import android.util.Log;
 import android.view.SurfaceHolder;
-import com.android.cts.stub.R;
 
 import junit.framework.Assert;
 
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/KernelTest.java b/tests/tests/renderscript/src/android/renderscript/cts/KernelTest.java
index 56b5e89..64368b6 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/KernelTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/KernelTest.java
@@ -48,8 +48,6 @@
 
 import android.renderscript.Type;
 
-import com.android.cts.stub.R;
-
 public class KernelTest extends RSBaseCompute {
     /**
      * Test support for reflected forEach() as well as validation of parameters.
@@ -461,7 +459,7 @@
 
 
     public void testMultipleForEach() {
-        ScriptC_foreach s = new ScriptC_foreach(mRS, mRes, R.raw.foreach);
+        ScriptC_foreach s = new ScriptC_foreach(mRS);
         Type.Builder typeBuilder = new Type.Builder(mRS, Element.I32(mRS));
 
         int X = 5;
@@ -470,7 +468,6 @@
         s.set_dimY(Y);
         typeBuilder.setX(X).setY(Y);
         Allocation A = Allocation.createTyped(mRS, typeBuilder.create());
-        s.bind_a(A);
         s.set_aRaw(A);
         s.forEach_root(A);
         s.invoke_verify_root();
@@ -478,11 +475,12 @@
         s.invoke_verify_foo();
         s.invoke_foreach_test();
         mRS.finish();
+        checkForErrors();
         waitForMessage();
     }
 
     public void testNoRoot() {
-        ScriptC_noroot s = new ScriptC_noroot(mRS, mRes, R.raw.noroot);
+        ScriptC_noroot s = new ScriptC_noroot(mRS);
         Type.Builder typeBuilder = new Type.Builder(mRS, Element.I32(mRS));
 
         int X = 5;
@@ -491,7 +489,6 @@
         s.set_dimY(Y);
         typeBuilder.setX(X).setY(Y);
         Allocation A = Allocation.createTyped(mRS, typeBuilder.create());
-        s.bind_a(A);
         s.set_aRaw(A);
         s.forEach_foo(A, A);
         s.invoke_verify_foo();
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/LeakTest.java b/tests/tests/renderscript/src/android/renderscript/cts/LeakTest.java
deleted file mode 100644
index b8c133a..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/LeakTest.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.app.ActivityManager;
-import android.renderscript.Allocation;
-import android.renderscript.Element;
-import android.renderscript.Type;
-import android.util.Log;
-import android.content.Context;
-
-/*
-// -target-api 11
-
-#pragma version(1)
-#pragma rs java_package_name(android.renderscript.cts)
-
-rs_allocation a;
-
-void print() {
-    rsDebug("unused", rsGetElementAt_int(a, 0, 0));
-}
-*/
-
-/**
- * Test for memory leaks due to missing object slot information.
- *
- * The code to generate leak.bc is in the previous comment block.
- * Note that you need to modify llvm-rs-cc to skip emitting the
- * .rs.dtor() function, since it will also do the proper cleanup
- * (but not trigger the original bug). Old HC code can trigger this
- * bug, since it may have been compiled without .rs.dtor() support.
- */
-public class LeakTest extends RSBaseCompute {
-    private static final String TAG = "LeakTest";
-
-    public void testForLeaks() {
-        ActivityManager am = (ActivityManager) getContext().getSystemService("activity");
-        int mc = am.getLargeMemoryClass() / 32;
-        if (mc < 1) {
-            mc = 1;
-        }
-        int x = mc * 1024 * 1024;
-
-        for (int i = 0; i < 100; i++) {
-            Log.w(TAG, "Leak test iteration " + i);
-            ScriptC_leak leak = new ScriptC_leak(mRS);
-            Type t = new Type.Builder(mRS, Element.I32(mRS)).setX(x).create();
-            Allocation A = Allocation.createTyped(mRS, t);
-            leak.set_a(A);
-            A = null;
-            //System.gc();
-            leak.destroy();
-            mRS.finish();
-        }
-        mRS.finish();
-        checkForErrors();
-    }
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/Log10Test.java b/tests/tests/renderscript/src/android/renderscript/cts/Log10Test.java
deleted file mode 100644
index bc571a3..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/Log10Test.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-
-public class Log10Test extends RSBaseCompute {
-    private ScriptC_log10_f32 script_f32;
-    private ScriptC_log10_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_log10_f32(mRS);
-        script_f32_relaxed = new ScriptC_log10_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_log10_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_log10_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_log10_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_log10_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_log10_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_log10_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_log10_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_log10_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)(Math.log10((double)in[idx]));
-            }
-        }
-        return ref;
-    }
-
-    public void testLog10F32() {
-        doF32(0x13, 3);
-    }
-
-    public void testLog10F32_relaxed() {
-        doF32_relaxed(0x13, 16);
-    }
-
-    public void testLog10F32_2() {
-        doF32_2(0xf, 3);
-    }
-
-    public void testLog10F32_2_relaxed() {
-        doF32_2_relaxed(0xf, 16);
-    }
-
-    public void testLog10F32_3() {
-        doF32_3(0xa, 3);
-    }
-
-    public void testLog10F32_3_relaxed() {
-        doF32_3_relaxed(0xa, 16);
-    }
-
-    public void testLog10F32_4() {
-        doF32_4(0xf3, 3);
-
-    }
-    public void testLog10F32_4_relaxed() {
-        doF32_4_relaxed(0xf3, 16);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/Log1PTest.java b/tests/tests/renderscript/src/android/renderscript/cts/Log1PTest.java
deleted file mode 100644
index a4daf61..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/Log1PTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-
-public class Log1PTest extends RSBaseCompute {
-    private ScriptC_log1p_f32 script_f32;
-    private ScriptC_log1p_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_log1p_f32(mRS);
-        script_f32_relaxed = new ScriptC_log1p_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_log1p_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_log1p_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_log1p_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_log1p_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_log1p_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_log1p_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_log1p_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_log1p_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)(Math.log1p((double)in[idx]));
-            }
-        }
-        return ref;
-    }
-
-    public void testLog1PF32() {
-        doF32(0xab, 2);
-    }
-
-    public void testLog1PF32_relaxed() {
-        doF32_relaxed(0xab, 16);
-    }
-
-    public void testLog1PF32_2() {
-        doF32_2(0x12, 2);
-    }
-
-    public void testLog1PF32_2_relaxed() {
-        doF32_2_relaxed(0x12, 16);
-    }
-
-    public void testLog1PF32_3() {
-        doF32_3(0xa1, 2);
-    }
-
-    public void testLog1PF32_3_relaxed() {
-        doF32_3_relaxed(0xa1, 16);
-    }
-
-    public void testLog1PF32_4() {
-        doF32_4(0xbae, 2);
-
-    }
-    public void testLog1PF32_4_relaxed() {
-        doF32_4_relaxed(0xbae, 16);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/Log2Test.java b/tests/tests/renderscript/src/android/renderscript/cts/Log2Test.java
deleted file mode 100644
index dd13d8d..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/Log2Test.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-
-public class Log2Test extends RSBaseCompute {
-    private ScriptC_log2_f32 script_f32;
-    private ScriptC_log2_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_log2_f32(mRS);
-        script_f32_relaxed = new ScriptC_log2_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_log2_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_log2_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_log2_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_log2_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_log2_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_log2_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_log2_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_log2_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)(Math.log10((double)in[idx])/Math.log10(2.0));
-            }
-        }
-        return ref;
-    }
-
-    public void testLog2F32() {
-        doF32(0x18a, 3);
-    }
-
-    public void testLog2F32_relaxed() {
-        doF32_relaxed(0x18a, 128);
-    }
-
-    public void testLog2F32_2() {
-        doF32_2(0xfa, 3);
-    }
-
-    public void testLog2F32_2_relaxed() {
-        doF32_2_relaxed(0xfa, 128);
-    }
-
-    public void testLog2F32_3() {
-        doF32_3(0xaef, 3);
-    }
-
-    public void testLog2F32_3_relaxed() {
-        doF32_3_relaxed(0xaef, 128);
-    }
-
-    public void testLog2F32_4() {
-        doF32_4(0xae62, 3);
-
-    }
-    public void testLog2F32_4_relaxed() {
-        doF32_4_relaxed(0xae62, 128);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/LogTest.java b/tests/tests/renderscript/src/android/renderscript/cts/LogTest.java
deleted file mode 100644
index ee03b4e..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/LogTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-
-public class LogTest extends RSBaseCompute {
-    private ScriptC_log_f32 script_f32;
-    private ScriptC_log_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_log_f32(mRS);
-        script_f32_relaxed = new ScriptC_log_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_log_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_log_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_log_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_log_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_log_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_log_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_log_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_log_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)(Math.log((double)in[idx]));
-            }
-        }
-        return ref;
-    }
-
-    public void testLogF32() {
-        doF32(0xfae, 3);
-    }
-
-    public void testLogF32_relaxed() {
-        doF32_relaxed(0xfae, 16);
-    }
-
-    public void testLogF32_2() {
-        doF32_2(0x123, 3);
-    }
-
-    public void testLogF32_2_relaxed() {
-        doF32_2_relaxed(0x123, 16);
-    }
-
-    public void testLogF32_3() {
-        doF32_3(0xab4, 3);
-    }
-
-    public void testLogF32_3_relaxed() {
-        doF32_3_relaxed(0xab4, 16);
-    }
-
-    public void testLogF32_4() {
-        doF32_4(0xfa3, 3);
-
-    }
-    public void testLogF32_4_relaxed() {
-        doF32_4_relaxed(0xfa3, 16);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/LogbTest.java b/tests/tests/renderscript/src/android/renderscript/cts/LogbTest.java
deleted file mode 100644
index b42d680..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/LogbTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-
-public class LogbTest extends RSBaseCompute {
-    private ScriptC_logb_f32 script_f32;
-    private ScriptC_logb_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_logb_f32(mRS);
-        script_f32_relaxed = new ScriptC_logb_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_logb_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_logb_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_logb_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_logb_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_logb_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_logb_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_logb_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_logb_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = ((Float.floatToIntBits(in[idx]) >> 23) & 0xFF) - 127.0f;
-            }
-        }
-        return ref;
-    }
-
-    public void testLogbF32() {
-        doF32(0xe, 0);
-    }
-
-    public void testLogbF32_relaxed() {
-        doF32_relaxed(0xe, 0);
-    }
-
-    public void testLogbF32_2() {
-        doF32_2(0xa1, 0);
-    }
-
-    public void testLogbF32_2_relaxed() {
-        doF32_2_relaxed(0xa1, 0);
-    }
-
-    public void testLogbF32_3() {
-        doF32_3(0xab2, 0);
-    }
-
-    public void testLogbF32_3_relaxed() {
-        doF32_3_relaxed(0xab2, 0);
-    }
-
-    public void testLogbF32_4() {
-        doF32_4(0xaa2, 0);
-
-    }
-    public void testLogbF32_4_relaxed() {
-        doF32_4_relaxed(0xaa2, 0);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/MadTest.java b/tests/tests/renderscript/src/android/renderscript/cts/MadTest.java
deleted file mode 100644
index 3662035..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/MadTest.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import android.renderscript.Element;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-public class MadTest extends RSBaseCompute {
-    private ScriptC_mad_f32 script_f32;
-    private ScriptC_mad_f32_relaxed script_f32_relaxed;
-    private Allocation mIn;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_mad_f32(mRS);
-        script_f32_relaxed = new ScriptC_mad_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_mad_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_mad_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_mad_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_mad_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_mad_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_mad_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_mad_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_mad_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx = i * stride * 3 + j;
-                ref[i * (stride - skip) + j] = (float)((double)in[idx] * (double)in[idx+stride] + (double)in[idx+stride*2]);
-            }
-        }
-        return ref;
-    }
-
-    @Override
-    protected Allocation setInAlloc(Element e) {
-        return mIn;
-    }
-
-    @Override
-    protected float[] makeInArray(int size) {
-        return new float[size*3];
-    }
-
-    public void testMadF32() {
-        ScriptField_mad_input_f32 in = new ScriptField_mad_input_f32(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32(0x123678, 4);
-    }
-
-    public void testMadF32_relaxed() {
-        ScriptField_mad_input_f32 in = new ScriptField_mad_input_f32(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_relaxed(0x123678, 4);
-    }
-
-    public void testMadF32_2() {
-        ScriptField_mad_input_f32_2 in = new ScriptField_mad_input_f32_2(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_2(0x1234a5, 4);
-    }
-
-    public void testMadF32_2_relaxed() {
-        ScriptField_mad_input_f32_2 in = new ScriptField_mad_input_f32_2(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_2_relaxed(0x1234a5, 4);
-    }
-
-    public void testMadF32_3() {
-        ScriptField_mad_input_f32_3 in = new ScriptField_mad_input_f32_3(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_3(0x1af345, 4);
-    }
-
-    public void testMadF32_3_relaxed() {
-        ScriptField_mad_input_f32_3 in = new ScriptField_mad_input_f32_3(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_3_relaxed(0x1af345, 4);
-    }
-
-    public void testMadF32_4() {
-        ScriptField_mad_input_f32_4 in = new ScriptField_mad_input_f32_4(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_4(0x12ce45, 4);
-    }
-
-    public void testMadF32_4_relaxed() {
-        ScriptField_mad_input_f32_4 in = new ScriptField_mad_input_f32_4(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_4_relaxed(0x12ce45, 4);
-    }
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/MatrixTest.rs b/tests/tests/renderscript/src/android/renderscript/cts/MatrixTest.rs
new file mode 100644
index 0000000..f1dbc64
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/MatrixTest.rs
@@ -0,0 +1,841 @@
+#include "shared.rsh"
+
+#define EXPECT(row, col, a, b)                                    \
+    do {                                                          \
+        if (fabs((a) - (b)) > 0.00001f) {                         \
+            failed = true;                                        \
+            rsDebug("Matrix operation FAILED at line", __LINE__); \
+            rsDebug("  row: ", row);                              \
+            rsDebug("  col: ", col);                              \
+            rsDebug("  " #a, (a));                                \
+            rsDebug("  " #b, (b));                                \
+        }                                                         \
+    } while (0)
+
+static bool testMatrixSetAndGet() {
+  bool failed = false;
+  rsDebug("Testing MatrixSetAndGet", 0);
+
+  rs_matrix2x2 m2;
+  rs_matrix3x3 m3;
+  rs_matrix4x4 m4;
+
+  // Set each cell to 100 * row + col
+  for (int row = 0; row < 2; row++) {
+    for (int col = 0; col < 2; col++) {
+      rsMatrixSet(&m2, col, row, row * 100.f + col);
+    }
+  }
+
+  for (int row = 0; row < 3; row++) {
+    for (int col = 0; col < 3; col++) {
+      rsMatrixSet(&m3, col, row, row * 100.f + col);
+    }
+  }
+
+  for (int row = 0; row < 4; row++) {
+    for (int col = 0; col < 4; col++) {
+      rsMatrixSet(&m4, col, row, row * 100.f + col);
+    }
+  }
+
+  // Verify these values.
+  for (int row = 0; row < 2; row++) {
+    for (int col = 0; col < 2; col++) {
+      EXPECT(row, col, rsMatrixGet(&m2, col, row), row * 100.f + col);
+    }
+  }
+
+  for (int row = 0; row < 3; row++) {
+    for (int col = 0; col < 3; col++) {
+      EXPECT(row, col, rsMatrixGet(&m3, col, row), row * 100.f + col);
+    }
+  }
+
+  for (int row = 0; row < 4; row++) {
+    for (int col = 0; col < 4; col++) {
+      EXPECT(row, col, rsMatrixGet(&m4, col, row), row * 100.f + col);
+    }
+  }
+
+  return failed;
+}
+
+static bool testMatrixLoadFromArray() {
+  bool failed = false;
+  rsDebug("Testing MatrixLoadFromArray", 0);
+
+  rs_matrix2x2 m2;
+  rs_matrix3x3 m3;
+  rs_matrix4x4 m4;
+
+  // Matrix are loaded by rsMatrixLoad in a column-major format.
+  const float m2Values[] = { 11.f, 21.f,
+                             12.f, 22.f };
+  const float m3Values[] = { 11.f, 21.f, 31.f,
+                             12.f, 22.f, 32.f,
+                             13.f, 23.f, 33.f };
+  const float m4Values[] = { 11.f, 21.f, 31.f, 41.f,
+                             12.f, 22.f, 32.f, 42.f,
+                             13.f, 23.f, 33.f, 43.f,
+                             14.f, 24.f, 34.f, 44.f };
+
+  // Test loading from arrays.
+  rsMatrixLoad(&m2, m2Values);
+  rsMatrixLoad(&m3, m3Values);
+  rsMatrixLoad(&m4, m4Values);
+
+  // Rows and columns are 0 indexed.
+  for (int row = 0; row < 2; row++) {
+    for (int col = 0; col < 2; col++) {
+      EXPECT(row, col, rsMatrixGet(&m2, col, row), (row + 1) * 10 + (col + 1));
+    }
+  }
+
+  for (int row = 0; row < 3; row++) {
+    for (int col = 0; col < 3; col++) {
+      EXPECT(row, col, rsMatrixGet(&m3, col, row), (row + 1) * 10 + (col + 1));
+    }
+  }
+
+  for (int row = 0; row < 4; row++) {
+    for (int col = 0; col < 4; col++) {
+      EXPECT(row, col, rsMatrixGet(&m4, col, row), (row + 1) * 10 + (col + 1));
+    }
+  }
+
+  return failed;
+}
+
+/* Load the matrix with the values of v, where the values are in row major.
+ * This makes the tests below easier to read than if they were column major,
+ * as rsLoadMatrix does.
+ */
+static void loadByRow2(rs_matrix2x2* m2, const float* v) {
+  for (int row = 0; row < 2; row++) {
+    for (int col = 0; col < 2; col++) {
+      rsMatrixSet(m2, col, row, v[2 * row + col]);
+    }
+  }
+}
+
+static void loadByRow3(rs_matrix3x3* m3, const float* v) {
+  for (int row = 0; row < 3; row++) {
+    for (int col = 0; col < 3; col++) {
+      rsMatrixSet(m3, col, row, v[3 * row + col]);
+    }
+  }
+}
+
+static void loadByRow4(rs_matrix4x4* m4, const float* v) {
+  for (int row = 0; row < 4; row++) {
+    for (int col = 0; col < 4; col++) {
+      rsMatrixSet(m4, col, row, v[4 * row + col]);
+    }
+  }
+}
+
+static bool testMatrixLoadFromMatrix() {
+  bool failed = false;
+  rsDebug("Testing MatrixLoadFromMatrix", 0);
+
+  rs_matrix2x2 m2;
+  rs_matrix3x3 m3;
+  rs_matrix4x4 m4;
+  const float m2Values[] = { 11.f, 12.f,
+                             21.f, 22.f };
+  const float m3Values[] = { 11.f, 12.f, 13.f,
+                             21.f, 22.f, 23.f,
+                             31.f, 32.f, 33.f };
+  const float m4Values[] = { 11.f, 12.f, 13.f, 14.f,
+                             21.f, 22.f, 23.f, 24.f,
+                             31.f, 32.f, 33.f, 34.f,
+                             41.f, 42.f, 43.f, 44.f };
+  loadByRow2(&m2, m2Values);
+  loadByRow3(&m3, m3Values);
+  loadByRow4(&m4, m4Values);
+
+  rs_matrix2x2 m2CopyOfM2;
+  rs_matrix3x3 m3CopyOfM3;
+  rs_matrix4x4 m4CopyOfM2;
+  rs_matrix4x4 m4CopyOfM3;
+  rs_matrix4x4 m4CopyOfM4;
+
+  rsMatrixLoad(&m2CopyOfM2, &m2);
+  rsMatrixLoad(&m3CopyOfM3, &m3);
+  rsMatrixLoad(&m4CopyOfM2, &m2);
+  rsMatrixLoad(&m4CopyOfM3, &m3);
+  rsMatrixLoad(&m4CopyOfM4, &m4);
+
+  for (int row = 0; row < 2; row++) {
+    for (int col = 0; col < 2; col++) {
+      EXPECT(row, col, rsMatrixGet(&m2CopyOfM2, col, row), m2Values[row * 2 + col]);
+    }
+  }
+
+  for (int row = 0; row < 3; row++) {
+    for (int col = 0; col < 3; col++) {
+      EXPECT(row, col, rsMatrixGet(&m3CopyOfM3, col, row), m3Values[row * 3 + col]);
+    }
+  }
+
+  for (int row = 0; row < 4; row++) {
+    for (int col = 0; col < 4; col++) {
+      if (col < 2 && row < 2) {
+        EXPECT(row, col, rsMatrixGet(&m4CopyOfM2, col, row), m2Values[row * 2 + col]);
+      } else {
+        EXPECT(row, col, rsMatrixGet(&m4CopyOfM2, col, row), row == col ? 1.f : 0.f);
+      }
+    }
+  }
+
+  for (int row = 0; row < 4; row++) {
+    for (int col = 0; col < 4; col++) {
+      if (col < 3 && row < 3) {
+        EXPECT(row, col, rsMatrixGet(&m4CopyOfM3, col, row), m3Values[row * 3 + col]);
+      } else {
+        EXPECT(row, col, rsMatrixGet(&m4CopyOfM3, col, row), row == col ? 1.f : 0.f);
+      }
+    }
+  }
+
+  for (int row = 0; row < 4; row++) {
+    for (int col = 0; col < 4; col++) {
+      EXPECT(row, col, rsMatrixGet(&m4CopyOfM4, col, row), m4Values[row * 4 + col]);
+    }
+  }
+
+  return failed;
+}
+
+static bool testMatrixIdentity() {
+  bool failed = false;
+  rsDebug("Testing MatrixIdentity", 0);
+
+  rs_matrix2x2 m2;
+  rs_matrix3x3 m3;
+  rs_matrix4x4 m4;
+
+  rsMatrixLoadIdentity(&m2);
+  rsMatrixLoadIdentity(&m3);
+  rsMatrixLoadIdentity(&m4);
+
+  for (int row = 0; row < 2; row++) {
+    for (int col = 0; col < 2; col++) {
+      EXPECT(row, col, rsMatrixGet(&m2, col, row), row == col ? 1.f : 0.f);
+    }
+  }
+
+  for (int row = 0; row < 3; row++) {
+    for (int col = 0; col < 3; col++) {
+      EXPECT(row, col, rsMatrixGet(&m3, col, row), row == col ? 1.f : 0.f);
+    }
+  }
+
+  for (int row = 0; row < 4; row++) {
+    for (int col = 0; col < 4; col++) {
+      EXPECT(row, col, rsMatrixGet(&m4, col, row), row == col ? 1.f : 0.f);
+    }
+  }
+
+  return failed;
+}
+
+static bool testMatrixVectorMultiply() {
+  bool failed = false;
+  rsDebug("Testing MatrixVectorMultiply", 0);
+
+  rs_matrix2x2 m2;
+  rs_matrix3x3 m3;
+  rs_matrix4x4 m4;
+  const float m2Values[] = { 11.f, 12.f,
+                             21.f, 22.f };
+  const float m3Values[] = { 11.f, 12.f, 13.f,
+                             21.f, 22.f, 23.f,
+                             31.f, 32.f, 33.f };
+  const float m4Values[] = { 11.f, 12.f, 13.f, 14.f,
+                             21.f, 22.f, 23.f, 24.f,
+                             31.f, 32.f, 33.f, 34.f,
+                             41.f, 42.f, 43.f, 44.f };
+  loadByRow2(&m2, m2Values);
+  loadByRow3(&m3, m3Values);
+  loadByRow4(&m4, m4Values);
+
+  const float2 f2 = {-2.f, 3.f};
+  const float3 f3 = {-7.f, 6.f, 2.f};
+  const float4 f4 = {4.f, -2.f, 6.f, 5.f};
+
+  const float2 f2r = rsMatrixMultiply(&m2, f2);
+  const float3 f3r = rsMatrixMultiply(&m3, f3);
+  const float4 f4r = rsMatrixMultiply(&m4, f4);
+
+  // rsMatrixMultiply returns (matrix * vector)
+  const float2 f2rExpectedValues = { 14.f, 24.f };
+  const float3 f3rExpectedValues = { 21.f, 31.f, 41.f };
+  const float4 f4rExpectedValues = {168.f, 298.f, 428.f, 558.f};
+
+  for (int row = 0; row < 2; row++) {
+    EXPECT(row, 0, f2r[row], f2rExpectedValues[row]);
+  }
+
+  for (int row = 0; row < 3; row++) {
+    EXPECT(row, 0, f3r[row], f3rExpectedValues[row]);
+  }
+
+  for (int row = 0; row < 4; row++) {
+    EXPECT(row, 0, f4r[row], f4rExpectedValues[row]);
+  }
+
+  return failed;
+}
+
+static bool testMatrixMultiply() {
+  bool failed = false;
+  rsDebug("Testing MatrixMultiply", 0);
+
+  const float m2LeftValues[] = { 3.f, -2.f,
+                                 7.f,  4.f };
+  const float m2RightValues[] = { -2.f,  3.f,
+                                  -7.f,  6.f };
+  const float m2LeftTimesRightValues[] = {  8.f, -3.f,
+                                          -42.f, 45.f };
+
+  const float m3LeftValues[] = { 3.f, -2.f,  8.f,
+                                 7.f,  4.f, -9.f,
+                                 5.f, -3.f,  6.f };
+  const float m3RightValues[] = { -2.f,  3.f,  7.f,
+                                  -7.f,  6.f, -5.f,
+                                   4.f, -4.f,  2.f };
+  const float m3LeftTimesRightValues[] = { 40.f, -35.f, 47.f,
+                                          -78.f,  81.f, 11.f,
+                                           35.f, -27.f, 62.f };
+
+  const float m4LeftValues[] = { 3.f, -2.f,  8.f, -5.f,
+                                 7.f,  4.f, -9.f, -4.f,
+                                 5.f, -3.f,  6.f, -6.f,
+                                 2.f, -8.f,  1.f, -1.f };
+  const float m4RightValues[] = { -2.f,  3.f,  7.f, -6.f,
+                                  -7.f,  6.f, -5.f,  7.f,
+                                   4.f, -4.f,  2.f,  5.f,
+                                  -1.f,  1.f,  8.f, -8.f };
+  const float m4LeftTimesRightValues[] = {  45.f, -40.f,   7.f,  48.f,
+                                           -74.f,  77.f, -21.f, -27.f,
+                                            41.f, -33.f,  14.f,  27.f,
+                                            57.f, -47.f,  48.f, -55.f };
+
+  rs_matrix2x2 m2, m2l, m2r;
+  rs_matrix3x3 m3, m3l, m3r;
+  rs_matrix4x4 m4, m4l, m4r;
+  loadByRow2(&m2l, m2LeftValues);
+  loadByRow2(&m2r, m2RightValues);
+  loadByRow3(&m3l, m3LeftValues);
+  loadByRow3(&m3r, m3RightValues);
+  loadByRow4(&m4l, m4LeftValues);
+  loadByRow4(&m4r, m4RightValues);
+
+  // Test the two versions of multiply.
+  rsMatrixLoadMultiply (&m2, &m2l, &m2r);
+  rsMatrixLoadMultiply (&m3, &m3l, &m3r);
+  rsMatrixLoadMultiply (&m4, &m4l, &m4r);
+
+  rsMatrixMultiply (&m2l, &m2r);
+  rsMatrixMultiply (&m3l, &m3r);
+  rsMatrixMultiply (&m4l, &m4r);
+
+  // rsMatrixMultiply returns (left * right).
+  for (int row = 0; row < 2; row++) {
+    for (int col = 0; col < 2; col++) {
+      EXPECT(row, col, rsMatrixGet(&m2, col, row), m2LeftTimesRightValues[row * 2 + col]);
+      EXPECT(row, col, rsMatrixGet(&m2l, col, row), m2LeftTimesRightValues[row * 2 + col]);
+    }
+  }
+
+  for (int row = 0; row < 3; row++) {
+    for (int col = 0; col < 3; col++) {
+      EXPECT(row, col, rsMatrixGet(&m3, col, row), m3LeftTimesRightValues[row * 3 + col]);
+      EXPECT(row, col, rsMatrixGet(&m3l, col, row), m3LeftTimesRightValues[row * 3 + col]);
+    }
+  }
+
+  for (int row = 0; row < 4; row++) {
+    for (int col = 0; col < 4; col++) {
+      EXPECT(row, col, rsMatrixGet(&m4, col, row), m4LeftTimesRightValues[row * 4 + col]);
+      EXPECT(row, col, rsMatrixGet(&m4l, col, row), m4LeftTimesRightValues[row * 4 + col]);
+    }
+  }
+
+  // Verify that rsLoadMultiply can store the result in its inputs.
+  loadByRow2(&m2l, m2LeftValues);
+  loadByRow2(&m2r, m2RightValues);
+  loadByRow3(&m3l, m3LeftValues);
+  loadByRow3(&m3r, m3RightValues);
+  loadByRow4(&m4l, m4LeftValues);
+  loadByRow4(&m4r, m4RightValues);
+
+  rsMatrixLoadMultiply (&m2r, &m2l, &m2r);
+  rsMatrixLoadMultiply (&m3r, &m3l, &m3r);
+  rsMatrixLoadMultiply (&m4r, &m4l, &m4r);
+
+  for (int row = 0; row < 2; row++) {
+    for (int col = 0; col < 2; col++) {
+      EXPECT(row, col, rsMatrixGet(&m2r, col, row), m2LeftTimesRightValues[row * 2 + col]);
+    }
+  }
+
+  for (int row = 0; row < 3; row++) {
+    for (int col = 0; col < 3; col++) {
+      EXPECT(row, col, rsMatrixGet(&m3r, col, row), m3LeftTimesRightValues[row * 3 + col]);
+    }
+  }
+
+  for (int row = 0; row < 4; row++) {
+    for (int col = 0; col < 4; col++) {
+      EXPECT(row, col, rsMatrixGet(&m4r, col, row), m4LeftTimesRightValues[row * 4 + col]);
+    }
+  }
+
+  loadByRow2(&m2l, m2LeftValues);
+  loadByRow2(&m2r, m2RightValues);
+  loadByRow3(&m3l, m3LeftValues);
+  loadByRow3(&m3r, m3RightValues);
+  loadByRow4(&m4l, m4LeftValues);
+  loadByRow4(&m4r, m4RightValues);
+
+  rsMatrixLoadMultiply (&m2l, &m2l, &m2r);
+  rsMatrixLoadMultiply (&m3l, &m3l, &m3r);
+  rsMatrixLoadMultiply (&m4l, &m4l, &m4r);
+
+  for (int row = 0; row < 2; row++) {
+    for (int col = 0; col < 2; col++) {
+      EXPECT(row, col, rsMatrixGet(&m2l, col, row), m2LeftTimesRightValues[row * 2 + col]);
+    }
+  }
+
+  for (int row = 0; row < 3; row++) {
+    for (int col = 0; col < 3; col++) {
+      EXPECT(row, col, rsMatrixGet(&m3l, col, row), m3LeftTimesRightValues[row * 3 + col]);
+    }
+  }
+
+  for (int row = 0; row < 4; row++) {
+    for (int col = 0; col < 4; col++) {
+      EXPECT(row, col, rsMatrixGet(&m4l, col, row), m4LeftTimesRightValues[row * 4 + col]);
+    }
+  }
+
+  return failed;
+}
+
+static bool testMatrixTranspose() {
+  bool failed = false;
+  rsDebug("Testing MatrixTranspose", 0);
+
+  rs_matrix2x2 m2;
+  rs_matrix3x3 m3;
+  rs_matrix4x4 m4;
+  const float m2Values[] = { 11.f, 12.f,
+                             21.f, 22.f };
+  const float m3Values[] = { 11.f, 12.f, 13.f,
+                             21.f, 22.f, 23.f,
+                             31.f, 32.f, 33.f };
+  const float m4Values[] = { 11.f, 12.f, 13.f, 14.f,
+                             21.f, 22.f, 23.f, 24.f,
+                             31.f, 32.f, 33.f, 34.f,
+                             41.f, 42.f, 43.f, 44.f };
+  loadByRow2(&m2, m2Values);
+  loadByRow3(&m3, m3Values);
+  loadByRow4(&m4, m4Values);
+
+  rsMatrixTranspose(&m4);
+  rsMatrixTranspose(&m3);
+  rsMatrixTranspose(&m2);
+
+  const float m2ExpectedValues[] = { 11.f, 21.f,
+                                     12.f, 22.f };
+  const float m3ExpectedValues[] = { 11.f, 21.f, 31.f,
+                                     12.f, 22.f, 32.f,
+                                     13.f, 23.f, 33.f };
+  const float m4ExpectedValues[] = { 11.f, 21.f, 31.f, 41.f,
+                                     12.f, 22.f, 32.f, 42.f,
+                                     13.f, 23.f, 33.f, 43.f,
+                                     14.f, 24.f, 34.f, 44.f };
+
+  for (int row = 0; row < 2; row++) {
+    for (int col = 0; col < 2; col++) {
+      EXPECT(row, col, rsMatrixGet(&m2, col, row), m2ExpectedValues[row * 2 + col]);
+    }
+  }
+
+  for (int row = 0; row < 3; row++) {
+    for (int col = 0; col < 3; col++) {
+      EXPECT(row, col, rsMatrixGet(&m3, col, row), m3ExpectedValues[row * 3 + col]);
+    }
+  }
+
+  for (int row = 0; row < 4; row++) {
+    for (int col = 0; col < 4; col++) {
+      EXPECT(row, col, rsMatrixGet(&m4, col, row), m4ExpectedValues[row * 4 + col]);
+    }
+  }
+
+  return failed;
+}
+
+static bool testMatrixInverse() {
+  bool failed = false;
+  rsDebug("Testing MatrixInverse", 0);
+
+  rs_matrix4x4 m4;
+  const float m4Values[] = { 3.f, -2.f,  8.f, -5.f,
+                             7.f,  4.f, -9.f, -4.f,
+                             5.f, -3.f,  6.f, -6.f,
+                             2.f, -8.f,  1.f, -1.f };
+  const float m4Inverse[] = { -585.f / 16.f, -135.f / 16.f, 602.f / 16.f, -147.f / 16.f,
+                              -91.f / 16.f,  -21.f / 16.f,  94.f / 16.f,  -25.f / 16.f,
+                              -207.f / 16.f,  -49.f / 16.f, 214.f / 16.f,  -53.f / 16.f,
+                              -649.f / 16.f, -151.f / 16.f, 666.f / 16.f, -163.f / 16.f };
+  const float m4InverseTranspose[] = { -585.f / 16.f, -91.f / 16.f, -207.f / 16.f, -649.f / 16.f,
+                                       -135.f / 16.f, -21.f / 16.f,  -49.f / 16.f, -151.f / 16.f,
+                                        602.f / 16.f,  94.f / 16.f,  214.f / 16.f,  666.f / 16.f,
+                                       -147.f / 16.f, -25.f / 16.f,  -53.f / 16.f, -163.f / 16.f };
+
+  loadByRow4(&m4, m4Values);
+  rsMatrixInverse(&m4);
+  for (int row = 0; row < 4; row++) {
+    for (int col = 0; col < 4; col++) {
+      EXPECT(row, col, rsMatrixGet(&m4, col, row), m4Inverse[row * 4 + col]);
+    }
+  }
+
+  loadByRow4(&m4, m4Values);
+  rsMatrixInverseTranspose(&m4);
+  for (int row = 0; row < 4; row++) {
+    for (int col = 0; col < 4; col++) {
+      EXPECT(row, col, rsMatrixGet(&m4, col, row), m4InverseTranspose[row * 4 + col]);
+    }
+  }
+
+  return failed;
+}
+
+static bool testMatrixScale() {
+  bool failed = false;
+  rsDebug("Testing MatrixScale", 0);
+
+  // Build a scaling matrix
+  const float x = 2.0f;
+  const float y = 0.5f;
+  const float z = 3.0f;
+  rs_matrix4x4 m4ScalingMatrix;
+  rsMatrixLoadScale(&m4ScalingMatrix, x, y, z);
+  const float m4ScalingMatrixExpectedValues[] = {   x, 0.f, 0.f, 0.f,
+                                                  0.f,   y, 0.f, 0.f,
+                                                  0.f, 0.f,   z, 0.f,
+                                                  0.f, 0.f, 0.f, 1.f };
+  for (int row = 0; row < 4; row++) {
+    for (int col = 0; col < 4; col++) {
+      EXPECT(row, col, rsMatrixGet(&m4ScalingMatrix, col, row),
+             m4ScalingMatrixExpectedValues[row * 4 + col]);
+    }
+  }
+
+  // Check that the scaling does what we expect.
+  const float3 f3 = {4.f, -2.f, 6.f};
+  const float4 f4r = rsMatrixMultiply(&m4ScalingMatrix, f3);
+  const float4 f4rExpectedValues = {4.f * x, -2.f * y, 6.f * z, 1.f};
+
+  for (int row = 0; row < 4; row++) {
+    EXPECT(row, 0, f4r[row], f4rExpectedValues[row]);
+  }
+
+  // Test combining scale with another transformation.
+  rs_matrix4x4 m4;
+  const float m4Values[] = { 11.f, 12.f, 13.f, 14.f,
+                             21.f, 22.f, 23.f, 24.f,
+                             31.f, 32.f, 33.f, 34.f,
+                             41.f, 42.f, 43.f, 44.f };
+  loadByRow4(&m4, m4Values);
+
+  // Method 1:
+  rs_matrix4x4 m4s;
+  rsMatrixLoadMultiply(&m4s, &m4, &m4ScalingMatrix);
+
+  // Method 2:
+  rsMatrixScale(&m4, x, y, z);
+
+  // Verify the results
+
+  /* We are creating a matrix that scales first then does the remaining operation.
+   * It's a bit inverse of what I would have expected.
+   */
+  const float expectedValues[] = { x * 11.f, y * 12.f, z * 13.f, 14.f,
+                                   x * 21.f, y * 22.f, z * 23.f, 24.f,
+                                   x * 31.f, y * 32.f, z * 33.f, 34.f,
+                                   x * 41.f, y * 42.f, z * 43.f, 44.f };
+  for (int row = 0; row < 4; row++) {
+    for (int col = 0; col < 4; col++) {
+      EXPECT(row, col, rsMatrixGet(&m4, col, row), expectedValues[row * 4 + col]);
+      EXPECT(row, col, rsMatrixGet(&m4s, col, row), expectedValues[row * 4 + col]);
+    }
+  }
+
+  return failed;
+}
+
+static bool testMatrixTranslate() {
+  bool failed = false;
+  rsDebug("Testing MatrixTranslate", 0);
+
+  // Build a translating matrix
+  rs_matrix4x4 m4TranslatingMatrix;
+  const float x = 2.0f;
+  const float y = 0.5f;
+  const float z = 3.0f;
+  rsMatrixLoadTranslate(&m4TranslatingMatrix, x, y, z);
+
+  const float m4TranslatingMatrixExpectedValues[] = { 1.f, 0.f, 0.f,   x,
+                                                      0.f, 1.f, 0.f,   y,
+                                                      0.f, 0.f, 1.f,   z,
+                                                      0.f, 0.f, 0.f, 1.f };
+  for (int row = 0; row < 4; row++) {
+    for (int col = 0; col < 4; col++) {
+      EXPECT(row, col, rsMatrixGet(&m4TranslatingMatrix, col, row),
+               m4TranslatingMatrixExpectedValues[row * 4 + col]);
+    }
+  }
+
+  // Check that the translation does what we expect.
+  const float3 f3 = {4.f, -2.f, 6.f};
+  const float4 f4r = rsMatrixMultiply(&m4TranslatingMatrix, f3);
+  const float4 f4rExpectedValues = {4.f + x, -2.f + y, 6.f + z, 1.f};
+
+  for (int row = 0; row < 4; row++) {
+    EXPECT(row, 0, f4r[row], f4rExpectedValues[row]);
+  }
+
+  // Test combining translate with another transformation.
+  rs_matrix4x4 m4;
+  const float m4Values[] = { 11.f, 12.f, 13.f, 14.f,
+                             21.f, 22.f, 23.f, 24.f,
+                             31.f, 32.f, 33.f, 34.f,
+                             41.f, 42.f, 43.f, 44.f };
+  loadByRow4(&m4, m4Values);
+
+  // Method 1:
+  rs_matrix4x4 m4s;
+  rsMatrixLoadMultiply(&m4s, &m4, &m4TranslatingMatrix);
+
+  // Method 2:
+  rsMatrixTranslate(&m4, x, y, z);
+
+  // Verify the results
+
+  /* We are creating a matrix that translates first then does the remaining operation.
+   * It's a bit inverse of what I would have expected.
+   */
+  float m4ExpectedValues[] = { 11.f, 12.f, 13.f, x * 11.f + y * 12.f + z * 13.f + 14.f,
+                               21.f, 22.f, 23.f, x * 21.f + y * 22.f + z * 23.f + 24.f,
+                               31.f, 32.f, 33.f, x * 31.f + y * 32.f + z * 33.f + 34.f,
+                               41.f, 42.f, 43.f, x * 41.f + y * 42.f + z * 43.f + 44.f };
+  for (int row = 0; row < 4; row++) {
+    for (int col = 0; col < 4; col++) {
+      EXPECT(row, col, rsMatrixGet(&m4, col, row), m4ExpectedValues[row * 4 + col]);
+      EXPECT(row, col, rsMatrixGet(&m4s, col, row), m4ExpectedValues[row * 4 + col]);
+    }
+  }
+
+  return failed;
+}
+
+static bool testMatrixTranslateAndScale() {
+  bool failed = false;
+  rsDebug("Testing MatrixTranslateAndScale", 0);
+
+  /* Create a matrix that will scale by (4, -2, 3) then translate by (2, 3, -1).
+   * Applied to the vector (5, 6, 7), we should get:
+   *   step 1: (20, -12, 21)
+   *   step 2: (22, -9, 20)
+   */
+  const float xs = 4.f;
+  const float ys = -2.f;
+  const float zs = 3.f;
+
+  const float xt = 2.f;
+  const float yt = 3.f;
+  const float zt = -1.f;
+
+  rs_matrix4x4 m4;
+  // Start by the second operation (yes, it's counter intuitive)
+  rsMatrixLoadTranslate(&m4, xt, yt, zt);
+  rsMatrixScale(&m4, xs, ys, zs);
+
+  // Check that the transformation does what we expect.
+  const float3 f3 = {5.f, 6.f, 7.f};
+  const float4 f4 = rsMatrixMultiply(&m4, f3);
+  const float4 f4ExpectedValues = {22.f, -9.f, 20.f, 1.f};
+
+  for (int row = 0; row < 4; row++) {
+    EXPECT(row, 0, f4[row], f4ExpectedValues[row]);
+  }
+
+  return failed;
+}
+
+
+static bool testMatrixRotate() {
+  bool failed = false;
+  rsDebug("Testing MatrixRotate", 0);
+
+  // Build a rotating matrix.
+  rs_matrix4x4 m4RotatingMatrix;
+  const float rotation = 90.f; // Rotation is in degrees.
+  const float x = 1.f;
+  const float y = 4.f;
+  const float z = 8.f;
+  rsMatrixLoadRotate(&m4RotatingMatrix, rotation, x, y, z);
+
+  /* See http://en.wikipedia.org/wiki/Rotation_matrix
+   */
+  const float inRadians = radians(rotation); // rotation * float(M_PI) / 180.0f;
+  const float co = cos(inRadians);
+  const float si = sin(inRadians);
+  const float ux = 1.f / 9.f;
+  const float uy = 4.f / 9.f;
+  const float uz = 8.f / 9.f;
+  const float m4RotatingMatrixExpectedValues[] = {
+    co + ux * ux * (1.f - co), ux * uy * (1.f - co) - uz * si, ux * uz * (1.f - co) + uy * si, 0.f,
+    uy * ux * (1.f - co) + uz * si, co + uy * uy * (1.f - co), uy * uz * (1.f - co) - ux * si, 0.f,
+    uz * ux * (1.f - co) - uy * si, uz * uy * (1.f - co) + ux * si, co + uz * uz * (1.f - co), 0.f,
+    0.f, 0.f, 0.f, 1.f
+  };
+
+  for (int row = 0; row < 4; row++) {
+    for (int col = 0; col < 4; col++) {
+      EXPECT(row, col, rsMatrixGet(&m4RotatingMatrix, col, row), m4RotatingMatrixExpectedValues[row * 4 + col]);
+    }
+  }
+
+  // Test combining rotate with another transformation.
+  rs_matrix4x4 m4;
+  const float m4Values[] = { 11.f, 12.f, 13.f, 14.f,
+                             21.f, 22.f, 23.f, 24.f,
+                             31.f, 32.f, 33.f, 34.f,
+                             41.f, 42.f, 43.f, 44.f };
+  loadByRow4(&m4, m4Values);
+
+  // Method 1:
+  rs_matrix4x4 m4s;
+  rsMatrixLoadMultiply(&m4s, &m4, &m4RotatingMatrix);
+
+  // Method 2:
+  rsMatrixRotate(&m4, rotation, x, y, z);
+
+  // Verify the results
+  for (int row = 0; row < 4; row++) {
+    for (int col = 0; col < 4; col++) {
+      EXPECT(row, col, rsMatrixGet(&m4, col, row), rsMatrixGet(&m4s, col, row));
+    }
+  }
+
+  // Verify that rsMatrixRotate does what we expect on something simple to understand.
+  rsMatrixLoadRotate(&m4RotatingMatrix, 60.f, 1.f, 0.f, 1.f);
+  const float3 f3 = {0.f, 1.f, 0.f};
+  const float4 f4r = rsMatrixMultiply(&m4RotatingMatrix, f3);
+  const float k = sqrt(3.f) * sqrt(2.f) / 4.f;
+  const float4 f4rExpectedValues = {-k, 0.5f, k, 1.f};
+
+  for (int row = 0; row < 4; row++) {
+    EXPECT(row, 0, f4r[row], f4rExpectedValues[row]);
+  }
+
+  return failed;
+}
+
+static bool testMatrixProjections() {
+  bool failed = false;
+  rsDebug("Testing MatrixProjections", 0);
+
+  rs_matrix4x4 m4;
+  const float left = -2.f;
+  const float right = 4.f;
+  const float bottom = -3.f;
+  const float top = 5.f;
+  const float near = 2.f;
+  const float far = 7.f;
+  const float fovy = 60.f;
+  const float aspect = 2.f;
+
+  /* Orthographic projection that remaps to the unit cube.  See
+   * http://unspecified.wordpress.com/2012/06/21/calculating-the-gluperspective-matrix-and-other-opengl-matrix-maths/
+   */
+  rsMatrixLoadOrtho(&m4, left, right, bottom, top, near, far);
+  const float orthoExpectedValues[] = {
+    2.f / (right - left), 0.f, 0.f, -(right + left) / (right - left),
+    0.f, 2.f / (top - bottom), 0.f, -(top + bottom) / (top - bottom),
+    0.f, 0.f, -2.f / (far - near), -(far + near) / (far - near),
+    0.f, 0.f, 0.f, 1.f,
+  };
+  for (int row = 0; row < 4; row++) {
+    for (int col = 0; col < 4; col++) {
+      EXPECT(row, col, rsMatrixGet(&m4, col, row), orthoExpectedValues[row * 4 + col]);
+    }
+  }
+
+  /* Frustum projection.  See
+   * http://www.scratchapixel.com/lessons/3d-advanced-lessons/perspective-and-orthographic-projection-matrix/opengl-perspective-projection-matrix/
+   */
+  rsMatrixLoadFrustum(&m4, left, right, bottom, top, near, far);
+  const float frustumExpectedValues[] = {
+    2.f * near / (right - left), 0.f, (right + left) / (right - left), 0.f,
+    0.f, 2.f * near / (top - bottom), (top + bottom) / (top - bottom), 0.f,
+    0.f, 0.f, -(far + near) / (far - near), -2.f * far * near / (far - near),
+    0.f, 0.f, -1.f, 0.f,
+  };
+  for (int row = 0; row < 4; row++) {
+    for (int col = 0; col < 4; col++) {
+      EXPECT(row, col, rsMatrixGet(&m4, col, row), frustumExpectedValues[row * 4 + col]);
+    }
+  }
+
+  /* Perspective projection.  See
+   * http://unspecified.wordpress.com/2012/06/21/calculating-the-gluperspective-matrix-and-other-opengl-matrix-maths/
+   */
+  rsMatrixLoadPerspective(&m4, fovy, aspect, near, far);
+  const float invTan = 1.f / tan(radians(fovy / 2.f));
+  const float perspectiveExpectedValues[] = {
+    invTan / aspect, 0.f, 0.f, 0.f,
+    0.f, invTan, 0.f, 0.f,
+    0.f, 0.f, (near + far) / (near - far), 2.f * far * near / (near - far),
+    0.f, 0.f, -1.f, 0.f,
+  };
+  for (int row = 0; row < 4; row++) {
+    for (int col = 0; col < 4; col++) {
+      EXPECT(row, col, rsMatrixGet(&m4, col, row), perspectiveExpectedValues[row * 4 + col]);
+    }
+  }
+
+  return failed;
+}
+
+void matrixTests() {
+  bool failed = false;
+  failed |= testMatrixSetAndGet();
+  failed |= testMatrixLoadFromArray();
+  failed |= testMatrixLoadFromMatrix();
+  failed |= testMatrixIdentity();
+  failed |= testMatrixVectorMultiply();
+  failed |= testMatrixMultiply();
+  failed |= testMatrixTranspose();
+  failed |= testMatrixInverse();
+  failed |= testMatrixScale();
+  failed |= testMatrixTranslate();
+  failed |= testMatrixTranslateAndScale();
+  failed |= testMatrixRotate();
+  failed |= testMatrixProjections();
+
+  if (failed) {
+    rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+  } else {
+    rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+  }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/NextafterTest.java b/tests/tests/renderscript/src/android/renderscript/cts/NextafterTest.java
deleted file mode 100644
index 468b341..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/NextafterTest.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import android.renderscript.Element;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-public class NextafterTest extends RSBaseCompute {
-    private ScriptC_nextafter_f32 script_f32;
-    private ScriptC_nextafter_f32_relaxed script_f32_relaxed;
-    private Allocation mIn;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_nextafter_f32(mRS);
-        script_f32_relaxed = new ScriptC_nextafter_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_nextafter_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_nextafter_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_nextafter_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_nextafter_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_nextafter_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_nextafter_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_nextafter_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_nextafter_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx = i * stride * 2 + j;
-                ref[i * (stride - skip) + j] = Math.nextAfter(in[idx],(double)in[idx+stride]);
-            }
-        }
-        return ref;
-    }
-
-    @Override
-    protected Allocation setInAlloc(Element e) {
-        return mIn;
-    }
-
-    @Override
-    protected float[] makeInArray(int size) {
-        return new float[size*2];
-    }
-
-    public void testNextafterF32() {
-        ScriptField_InputData inputDataArray = new ScriptField_InputData(mRS, INPUTSIZE);
-        mIn = inputDataArray.getAllocation();
-        doF32(0x12678, 0);
-    }
-
-    public void testNextafterF32_relaxed() {
-        ScriptField_InputData inputDataArray = new ScriptField_InputData(mRS, INPUTSIZE);
-        mIn = inputDataArray.getAllocation();
-        doF32_relaxed(0x12678, 0);
-    }
-
-    public void testNextafterF32_2() {
-        ScriptField_InputData_2 inputDataArray = new ScriptField_InputData_2(mRS, INPUTSIZE);
-        mIn = inputDataArray.getAllocation();
-        doF32_2(0x1af45, 0);
-    }
-
-    public void testNextafterF32_2_relaxed() {
-        ScriptField_InputData_2 inputDataArray = new ScriptField_InputData_2(mRS, INPUTSIZE);
-        mIn = inputDataArray.getAllocation();
-        doF32_2_relaxed(0x1af45, 0);
-    }
-
-    public void testNextafterF32_3() {
-        ScriptField_InputData_3 inputDataArray = new ScriptField_InputData_3(mRS, INPUTSIZE);
-        mIn = inputDataArray.getAllocation();
-        doF32_3(0x1cd345, 0);
-    }
-
-    public void testNextafterF32_3_relaxed() {
-        ScriptField_InputData_3 inputDataArray = new ScriptField_InputData_3(mRS, INPUTSIZE);
-        mIn = inputDataArray.getAllocation();
-        doF32_3_relaxed(0x1cd345, 0);
-    }
-
-    public void testNextafterF32_4() {
-        ScriptField_InputData_4 inputDataArray = new ScriptField_InputData_4(mRS, INPUTSIZE);
-        mIn = inputDataArray.getAllocation();
-        doF32_4(0x1ca45, 0);
-    }
-
-    public void testNextafterF32_4_relaxed() {
-        ScriptField_InputData_4 inputDataArray = new ScriptField_InputData_4(mRS, INPUTSIZE);
-        mIn = inputDataArray.getAllocation();
-        doF32_4_relaxed(0x1ca45, 0);
-    }
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/PowTest.java b/tests/tests/renderscript/src/android/renderscript/cts/PowTest.java
deleted file mode 100644
index ad3d078..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/PowTest.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import android.renderscript.Element;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-public class PowTest extends RSBaseCompute {
-    private ScriptC_pow_f32 script_f32;
-    private ScriptC_pow_f32_relaxed script_f32_relaxed;
-    private Allocation mIn;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_pow_f32(mRS);
-        script_f32_relaxed = new ScriptC_pow_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_pow_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_pow_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_pow_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_pow_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_pow_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_pow_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_pow_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_pow_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride * 2 + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)Math.pow((double)in[idx], (double)in[idx+stride]);
-            }
-        }
-        return ref;
-    }
-
-    @Override
-    protected Allocation setInAlloc(Element e) {
-        return mIn;
-    }
-
-    @Override
-    protected float[] makeInArray(int size) {
-        return new float[size*2];
-    }
-
-    @Override
-    protected void fillRandomFloats(long seed, int fact, int offset, float[] inArray) {
-        RSUtils.genRandomFloats(seed, 32, -16, inArray);
-    }
-
-    public void testPowF32() {
-        ScriptField_PowInputData in = new ScriptField_PowInputData(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32(0x12345678, 16);
-    }
-
-    public void testPowF32_relaxed() {
-        ScriptField_PowInputData in = new ScriptField_PowInputData(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_relaxed(0x12345678, 128);
-    }
-
-    public void testPowF32_2() {
-        ScriptField_PowInputData_2 in = new ScriptField_PowInputData_2(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_2(0x12ab78, 16);
-    }
-
-    public void testPowF32_2_relaxed() {
-        ScriptField_PowInputData_2 in = new ScriptField_PowInputData_2(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_2_relaxed(0x12ab78, 128);
-    }
-
-    public void testPowF32_3() {
-        ScriptField_PowInputData_3 in = new ScriptField_PowInputData_3(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_3(0x1f5678, 16);
-    }
-
-    public void testPowF32_3_relaxed() {
-        ScriptField_PowInputData_3 in = new ScriptField_PowInputData_3(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_3_relaxed(0x1f5678, 128);
-    }
-
-    public void testPowF32_4() {
-        ScriptField_PowInputData_4 in = new ScriptField_PowInputData_4(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_4(0xc678, 16);
-    }
-
-    public void testPowF32_4_relaxed() {
-        ScriptField_PowInputData_4 in = new ScriptField_PowInputData_4(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_4_relaxed(0xc678, 128);
-    }
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/PownTest.java b/tests/tests/renderscript/src/android/renderscript/cts/PownTest.java
deleted file mode 100644
index 32308ce..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/PownTest.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import android.renderscript.Element;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-public class PownTest extends RSBaseCompute {
-    private ScriptC_pown_f32 script_f32;
-    private ScriptC_pown_f32_relaxed script_f32_relaxed;
-    private int[] n;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_pown_f32(mRS);
-        script_f32_relaxed = new ScriptC_pown_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_pown_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_pown_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_pown_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_pown_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_pown_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_pown_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_pown_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_pown_f32_4(mIn, mOut);
-            break;
-
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)Math.pow((double)in[idx], (double)n[idx]);
-            }
-        }
-        return ref;
-    }
-
-    public void testPownF32() {
-        Allocation nAlloc = Allocation.createSized(mRS, Element.I32(mRS), INPUTSIZE);
-
-        n = new int[INPUTSIZE];
-        RSUtils.genRandomInts(0x12345678, 32, -16, n);
-        nAlloc.copyFrom(n);
-        script_f32.set_n1(nAlloc);
-
-        doF32(0x716acd, 16);
-    }
-
-    public void testPownF32_relaxed() {
-        Allocation nAlloc = Allocation.createSized(mRS, Element.I32(mRS), INPUTSIZE);
-
-        n = new int[INPUTSIZE];
-        RSUtils.genRandomInts(0x12345678, 32, -16, n);
-        nAlloc.copyFrom(n);
-        script_f32_relaxed.set_n1(nAlloc);
-
-        doF32_relaxed(0x716acd, 128);
-    }
-
-    public void testPownF32_2() {
-        Allocation nAlloc = Allocation.createSized(mRS, Element.I32_2(mRS), INPUTSIZE);
-
-        n = new int[INPUTSIZE*2];
-        RSUtils.genRandomInts(0xacdef1, 32, -16, n);
-        nAlloc.copyFrom(n);
-        script_f32.set_n2(nAlloc);
-
-        doF32_2(0xacdef1, 16);
-    }
-
-    public void testPownF32_2_relaxed() {
-        Allocation nAlloc = Allocation.createSized(mRS, Element.I32_2(mRS), INPUTSIZE);
-
-        n = new int[INPUTSIZE*2];
-        RSUtils.genRandomInts(0xacdef1, 32, -16, n);
-        nAlloc.copyFrom(n);
-        script_f32_relaxed.set_n2(nAlloc);
-
-        doF32_2_relaxed(0xacdef1, 128);
-    }
-
-    public void testPownF32_3() {
-        Allocation nAlloc = Allocation.createSized(mRS, Element.I32_3(mRS), INPUTSIZE);
-
-        n = new int[INPUTSIZE*4];
-        RSUtils.genRandomInts(0xa123f1, 32, -16, n);
-        nAlloc.copyFrom(n);
-        script_f32.set_n3(nAlloc);
-
-        doF32_3(0xaac3f1, 16);
-    }
-
-    public void testPownF32_3_relaxed() {
-        Allocation nAlloc = Allocation.createSized(mRS, Element.I32_3(mRS), INPUTSIZE);
-
-        n = new int[INPUTSIZE*4];
-        RSUtils.genRandomInts(0xa123f1, 32, -16, n);
-        nAlloc.copyFrom(n);
-        script_f32_relaxed.set_n3(nAlloc);
-
-        doF32_3_relaxed(0xaac3f1, 128);
-    }
-
-    public void testPownF32_4() {
-        Allocation nAlloc = Allocation.createSized(mRS, Element.I32_4(mRS), INPUTSIZE);
-
-        n = new int[INPUTSIZE*4];
-        RSUtils.genRandomInts(0x4323ca, 32, -16, n);
-        nAlloc.copyFrom(n);
-        script_f32.set_n4(nAlloc);
-
-        doF32_4(0xaa12f1, 16);
-    }
-
-    public void testPownF32_4_relaxed() {
-        Allocation nAlloc = Allocation.createSized(mRS, Element.I32_4(mRS), INPUTSIZE);
-
-        n = new int[INPUTSIZE*4];
-        RSUtils.genRandomInts(0x4323ca, 32, -16, n);
-        nAlloc.copyFrom(n);
-        script_f32_relaxed.set_n4(nAlloc);
-
-        doF32_4_relaxed(0xaa12f1, 128);
-    }
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/PowrTest.java b/tests/tests/renderscript/src/android/renderscript/cts/PowrTest.java
deleted file mode 100644
index cebbe24..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/PowrTest.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import android.renderscript.Element;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-public class PowrTest extends RSBaseCompute {
-    private ScriptC_powr_f32 script_f32;
-    private ScriptC_powr_f32_relaxed script_f32_relaxed;
-    private Allocation mIn;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_powr_f32(mRS);
-        script_f32_relaxed = new ScriptC_powr_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_powr_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_powr_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_powr_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_powr_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_powr_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_powr_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_powr_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_powr_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride * 2 + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)Math.pow((double)in[idx], (double)in[idx+stride]);
-            }
-        }
-        return ref;
-    }
-
-    @Override
-    protected Allocation setInAlloc(Element e) {
-        return mIn;
-    }
-
-    @Override
-    protected float[] makeInArray(int size) {
-        return new float[size*2];
-    }
-
-    @Override
-    protected void fillRandomFloats(long seed, int fact, int offset, float[] inArray) {
-        RSUtils.genRandomFloats(seed, 64, 0, inArray);
-    }
-
-    public void testPowrF32() {
-        ScriptField_PowInputData in = new ScriptField_PowInputData(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32(0x12345678, 16);
-    }
-
-    public void testPowrF32_relaxed() {
-        ScriptField_PowInputData in = new ScriptField_PowInputData(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_relaxed(0x12345678, 128);
-    }
-
-    public void testPowrF32_2() {
-        ScriptField_PowInputData_2 in = new ScriptField_PowInputData_2(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_2(0x12ab78, 16);
-    }
-
-    public void testPowrF32_2_relaxed() {
-        ScriptField_PowInputData_2 in = new ScriptField_PowInputData_2(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_2(0x12ab78, 128);
-    }
-
-    public void testPowrF32_3() {
-        ScriptField_PowInputData_3 in = new ScriptField_PowInputData_3(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_3(0x1f5678, 16);
-    }
-
-    public void testPowrF32_3_relaxed() {
-        ScriptField_PowInputData_3 in = new ScriptField_PowInputData_3(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_3_relaxed(0x1f5678, 128);
-    }
-
-    public void testPowrF32_4() {
-        ScriptField_PowInputData_4 in = new ScriptField_PowInputData_4(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_4(0xc678, 16);
-    }
-
-    public void testPowrF32_4_relaxed() {
-        ScriptField_PowInputData_4 in = new ScriptField_PowInputData_4(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_4_relaxed(0xc678, 128);
-    }
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/RSBase.java b/tests/tests/renderscript/src/android/renderscript/cts/RSBase.java
index 29183f0..ebf15dc 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/RSBase.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/RSBase.java
@@ -28,7 +28,7 @@
  * Base RenderScript test class. This class provides a message handler and a
  * convenient way to wait for compute scripts to complete their execution.
  */
-class RSBase extends AndroidTestCase {
+public class RSBase extends AndroidTestCase {
 
     Context mCtx;
     Resources mRes;
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/RSBaseCompute.java b/tests/tests/renderscript/src/android/renderscript/cts/RSBaseCompute.java
index d7759f1..0413f22 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/RSBaseCompute.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/RSBaseCompute.java
@@ -26,17 +26,8 @@
  * Base RenderScript test class. This class provides a message handler and a
  * convenient way to wait for compute scripts to complete their execution.
  */
-class RSBaseCompute extends RSBase {
+public class RSBaseCompute extends RSBase {
     RenderScript mRS;
-
-    static final int TEST_F32 = 0;
-    static final int TEST_F32_2 = 1;
-    static final int TEST_F32_3 = 2;
-    static final int TEST_F32_4 = 3;
-    static final int TEST_RELAXED_F32 = 4;
-    static final int TEST_RELAXED_F32_2 = 5;
-    static final int TEST_RELAXED_F32_3 = 6;
-    static final int TEST_RELAXED_F32_4 = 7;
     protected int INPUTSIZE = 512;
 
     @Override
@@ -85,65 +76,311 @@
         }
     }
 
-    private void baseTestHelper(int testid, Element inElement, Element outElement, long seed, int fact,
-                                int offset, int rStride, int rSkip, int refStride, int outStride,
-                                int inStride, int skip, int ulp) {
-        float[] inArray = makeInArray(INPUTSIZE * inStride);
-        fillRandomFloats(seed, fact, offset, inArray);
-        float[] refArray = getRefArray(inArray, INPUTSIZE, inStride, skip);
-
-        Allocation mAllocationIn = setInAlloc(inElement);
-        fillInAlloc(mAllocationIn, inArray);
-
-        Allocation mAllocationOut = setOutAlloc(outElement);
-        try {
-            forEach(testid, mAllocationIn, mAllocationOut);
-        } catch (RSRuntimeException e) {
-            Log.e("RenderscriptCTS", "Caught RSRuntimeException: " +
-                  e.getMessage());
+    // TODO Is there a better way to do this
+    protected Element getElement(RenderScript rs, Element.DataType dataType, int size) {
+        Element element = null;
+        if (size == 1) {
+            if (dataType == Element.DataType.FLOAT_64) {
+                element = Element.F64(rs);
+            } else if (dataType == Element.DataType.FLOAT_32) {
+                element = Element.F32(rs);
+            } else if (dataType == Element.DataType.SIGNED_64) {
+                element = Element.I64(rs);
+            } else if (dataType == Element.DataType.UNSIGNED_64) {
+                element = Element.U64(rs);
+            } else if (dataType == Element.DataType.SIGNED_32) {
+                element = Element.I32(rs);
+            } else if (dataType == Element.DataType.UNSIGNED_32) {
+                element = Element.U32(rs);
+            } else if (dataType == Element.DataType.SIGNED_16) {
+                element = Element.I16(rs);
+            } else if (dataType == Element.DataType.UNSIGNED_16) {
+                element = Element.U16(rs);
+            } else if (dataType == Element.DataType.SIGNED_8) {
+                element = Element.I8(rs);
+            } else if (dataType == Element.DataType.UNSIGNED_8) {
+                element = Element.U8(rs);
+            } else {
+                android.util.Log.e("RenderscriptCTS", "Don't know how to create allocation of type" +
+                        dataType.toString());
+            }
+        } else {
+            element = Element.createVector(rs, dataType, size);
         }
-        float[] outArray = makeOutArray(INPUTSIZE * outStride);
-        mAllocationOut.copyTo(outArray);
-        checkArray(refArray, outArray, INPUTSIZE, refStride, outStride, ulp);
+        return element;
     }
 
-    public void baseTest(int testid, long seed, int refStride, int outStride, int inStride, int skip, int ulp) {
-        baseTestHelper(testid, null, null, seed, 1, 0, 1, 0, refStride, outStride, inStride, skip, ulp);
+    protected Allocation createRandomAllocation(RenderScript rs, Element.DataType dataType,
+            int size, long seed, boolean includeExtremes) {
+        Element element = getElement(rs, dataType, size);
+        Allocation alloc = Allocation.createSized(rs, element, INPUTSIZE);
+        int width = (size == 3) ? 4 : size;
+        if (dataType == Element.DataType.FLOAT_64) {
+            double[] inArray = new double[INPUTSIZE * width];
+            // TODO The ranges for float is too small.  We need to accept a wider range of values.
+            double min = -4.0 * Math.PI;
+            double max = 4.0 * Math.PI;
+            RSUtils.genRandomDoubles(seed, min, max, inArray, includeExtremes);
+            alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
+        } else if (dataType == Element.DataType.FLOAT_32) {
+            float[] inArray = new float[INPUTSIZE * width];
+            // TODO The ranges for float is too small.  We need to accept a wider range of values.
+            float min = -4.0f * (float) Math.PI;
+            float max = 4.0f * (float) Math.PI;
+            RSUtils.genRandomFloats(seed, min, max, inArray, includeExtremes);
+            alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
+        } else if (dataType == Element.DataType.SIGNED_64) {
+            long[] inArray = new long[INPUTSIZE * width];
+            RSUtils.genRandomLongs(seed, inArray, true, 63);
+            alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
+        } else if (dataType == Element.DataType.UNSIGNED_64) {
+            long[] inArray = new long[INPUTSIZE * width];
+            RSUtils.genRandomLongs(seed, inArray, false, 64);
+            alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
+        } else if (dataType == Element.DataType.SIGNED_32) {
+            int[] inArray = new int[INPUTSIZE * width];
+            RSUtils.genRandomInts(seed, inArray, true, 31);
+            alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
+        } else if (dataType == Element.DataType.UNSIGNED_32) {
+            int[] inArray = new int[INPUTSIZE * width];
+            RSUtils.genRandomInts(seed, inArray, false, 32);
+            alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
+        } else if (dataType == Element.DataType.SIGNED_16) {
+            short[] inArray = new short[INPUTSIZE * width];
+            RSUtils.genRandomShorts(seed, inArray, true, 15);
+            alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
+        } else if (dataType == Element.DataType.UNSIGNED_16) {
+            short[] inArray = new short[INPUTSIZE * width];
+            RSUtils.genRandomShorts(seed, inArray, false, 16);
+            alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
+        } else if (dataType == Element.DataType.SIGNED_8) {
+            byte[] inArray = new byte[INPUTSIZE * width];
+            RSUtils.genRandomBytes(seed, inArray, true, 7);
+            alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
+        } else if (dataType == Element.DataType.UNSIGNED_8) {
+            byte[] inArray = new byte[INPUTSIZE * width];
+            RSUtils.genRandomBytes(seed, inArray, true, 8);
+            alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
+        } else {
+            android.util.Log.e("RenderscriptCTS", "Don't know how to create allocation of type" +
+                    dataType.toString());
+        }
+        return alloc;
     }
 
-    public void doF32(long seed, int ulp) {
-        baseTestHelper(TEST_F32, Element.F32(mRS), Element.F32(mRS), seed, 1, 0, 1, 0, 1, 1, 1, 0, ulp);
+    protected Allocation createRandomFloatAllocation(RenderScript rs, Element.DataType dataType,
+            int size, long seed, double minValue, double maxValue) {
+        Element element = getElement(rs, dataType, size);
+        Allocation alloc = Allocation.createSized(rs, element, INPUTSIZE);
+        int width = (size == 3) ? 4 : size;
+        if (dataType == Element.DataType.FLOAT_64) {
+            double[] inArray = new double[INPUTSIZE * width];
+            RSUtils.genRandomDoubles(seed, minValue, maxValue, inArray, false);
+            alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
+        } else if (dataType == Element.DataType.FLOAT_32) {
+            float[] inArray = new float[INPUTSIZE * width];
+            RSUtils.genRandomFloats(seed, (float) minValue, (float) maxValue, inArray, false);
+            alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
+        } else {
+            android.util.Log.e("RenderscriptCTS",
+                               "Don't know how to create a random float allocation for " +
+                                           dataType.toString());
+        }
+        return alloc;
     }
 
-    public void doF32_2(long seed, int ulp) {
-        baseTestHelper(TEST_F32_2, Element.F32_2(mRS), Element.F32_2(mRS), seed, 1, 0, 1, 0, 2, 2, 2, 0, ulp);
+    protected Allocation createRandomIntegerAllocation(RenderScript rs, Element.DataType dataType,
+            int size, long seed, boolean signed, int numberOfBits) {
+        Element element = getElement(rs, dataType, size);
+        Allocation alloc = Allocation.createSized(rs, element, INPUTSIZE);
+        int width = (size == 3) ? 4 : size;
+        if (dataType == Element.DataType.SIGNED_64 ||
+                dataType == Element.DataType.UNSIGNED_64) {
+            long[] inArray = new long[INPUTSIZE * width];
+            RSUtils.genRandomLongs(seed, inArray, signed, numberOfBits);
+            alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
+        } else
+        if (dataType == Element.DataType.SIGNED_32 ||
+                dataType == Element.DataType.UNSIGNED_32) {
+            int[] inArray = new int[INPUTSIZE * width];
+            RSUtils.genRandomInts(seed, inArray, signed, numberOfBits);
+            alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
+        } else if (dataType == Element.DataType.SIGNED_16 ||
+                dataType == Element.DataType.UNSIGNED_16) {
+            short[] inArray = new short[INPUTSIZE * width];
+            RSUtils.genRandomShorts(seed, inArray, signed, numberOfBits);
+            alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
+        } else if (dataType == Element.DataType.SIGNED_8 ||
+                dataType == Element.DataType.UNSIGNED_8) {
+            byte[] inArray = new byte[INPUTSIZE * width];
+            RSUtils.genRandomBytes(seed, inArray, signed, numberOfBits);
+            alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
+        } else {
+            android.util.Log.e("RenderscriptCTS",
+                               "Don't know how to create an integer allocation of type" +
+                                           dataType.toString());
+        }
+        return alloc;
     }
 
-    public void doF32_3(long seed, int ulp) {
-        baseTestHelper(TEST_F32_3, Element.F32_3(mRS), Element.F32_3(mRS), seed, 1, 0, 4, 1, 3, 4, 4, 1, ulp);
+    protected <T> void enforceOrdering(/*RenderScript rs,*/ Allocation minAlloc, Allocation maxAlloc) {
+        Element element = minAlloc.getElement();
+        int stride = element.getVectorSize();
+        if (stride == 3) {
+            stride = 4;
+        }
+        int size = INPUTSIZE * stride;
+        Element.DataType dataType = element.getDataType();
+        if (dataType == Element.DataType.FLOAT_64) {
+            double[] minArray = new double[size];
+            double[] maxArray = new double[size];
+            minAlloc.copyTo(minArray);
+            maxAlloc.copyTo(maxArray);
+            for (int i = 0; i < size; i++) {
+                if (minArray[i] > maxArray[i]) {
+                    double temp = minArray[i];
+                    minArray[i] = maxArray[i];
+                    maxArray[i] = temp;
+                }
+            }
+            minAlloc.copyFrom(minArray);
+            maxAlloc.copyFrom(maxArray);
+        } else
+        if (dataType == Element.DataType.FLOAT_32) {
+            float[] minArray = new float[size];
+            float[] maxArray = new float[size];
+            minAlloc.copyTo(minArray);
+            maxAlloc.copyTo(maxArray);
+            for (int i = 0; i < size; i++) {
+                if (minArray[i] > maxArray[i]) {
+                    float temp = minArray[i];
+                    minArray[i] = maxArray[i];
+                    maxArray[i] = temp;
+                }
+            }
+            minAlloc.copyFrom(minArray);
+            maxAlloc.copyFrom(maxArray);
+        } else if (dataType == Element.DataType.SIGNED_64) {
+            long[] minArray = new long[size];
+            long[] maxArray = new long[size];
+            minAlloc.copyTo(minArray);
+            maxAlloc.copyTo(maxArray);
+            for (int i = 0; i < size; i++) {
+                if (minArray[i] > maxArray[i]) {
+                    long temp = minArray[i];
+                    minArray[i] = maxArray[i];
+                    maxArray[i] = temp;
+                }
+            }
+            minAlloc.copyFrom(minArray);
+            maxAlloc.copyFrom(maxArray);
+        } else if (dataType == Element.DataType.UNSIGNED_64) {
+            long[] minArray = new long[size];
+            long[] maxArray = new long[size];
+            minAlloc.copyTo(minArray);
+            maxAlloc.copyTo(maxArray);
+            for (int i = 0; i < size; i++) {
+                if (RSUtils.compareUnsignedLong(minArray[i], maxArray[i]) > 0) {
+                    long temp = minArray[i];
+                    minArray[i] = maxArray[i];
+                    maxArray[i] = temp;
+                }
+            }
+            minAlloc.copyFrom(minArray);
+            maxAlloc.copyFrom(maxArray);
+        } else if (dataType == Element.DataType.SIGNED_32) {
+            int[] minArray = new int[size];
+            int[] maxArray = new int[size];
+            minAlloc.copyTo(minArray);
+            maxAlloc.copyTo(maxArray);
+            for (int i = 0; i < size; i++) {
+                if (minArray[i] > maxArray[i]) {
+                    int temp = minArray[i];
+                    minArray[i] = maxArray[i];
+                    maxArray[i] = temp;
+                }
+            }
+            minAlloc.copyFrom(minArray);
+            maxAlloc.copyFrom(maxArray);
+        } else if (dataType == Element.DataType.UNSIGNED_32) {
+            int[] minArray = new int[size];
+            int[] maxArray = new int[size];
+            minAlloc.copyTo(minArray);
+            maxAlloc.copyTo(maxArray);
+            for (int i = 0; i < size; i++) {
+                long min = minArray[i] &0xffffffffl;
+                long max = maxArray[i] &0xffffffffl;
+                if (min > max) {
+                    minArray[i] = (int) max;
+                    maxArray[i] = (int) min;
+                }
+            }
+            minAlloc.copyFrom(minArray);
+            maxAlloc.copyFrom(maxArray);
+        } else if (dataType == Element.DataType.SIGNED_16) {
+            short[] minArray = new short[size];
+            short[] maxArray = new short[size];
+            minAlloc.copyTo(minArray);
+            maxAlloc.copyTo(maxArray);
+            for (int i = 0; i < size; i++) {
+                if (minArray[i] > maxArray[i]) {
+                    short temp = minArray[i];
+                    minArray[i] = maxArray[i];
+                    maxArray[i] = temp;
+                }
+            }
+            minAlloc.copyFrom(minArray);
+            maxAlloc.copyFrom(maxArray);
+        } else if (dataType == Element.DataType.UNSIGNED_16) {
+            short[] minArray = new short[size];
+            short[] maxArray = new short[size];
+            minAlloc.copyTo(minArray);
+            maxAlloc.copyTo(maxArray);
+            for (int i = 0; i < size; i++) {
+                int min = minArray[i] &0xffff;
+                int max = maxArray[i] &0xffff;
+                if (min > max) {
+                    minArray[i] = (short) max;
+                    maxArray[i] = (short) min;
+                }
+            }
+            minAlloc.copyFrom(minArray);
+            maxAlloc.copyFrom(maxArray);
+        } else if (dataType == Element.DataType.SIGNED_8) {
+            byte[] minArray = new byte[size];
+            byte[] maxArray = new byte[size];
+            minAlloc.copyTo(minArray);
+            maxAlloc.copyTo(maxArray);
+            for (int i = 0; i < size; i++) {
+                if (minArray[i] > maxArray[i]) {
+                    byte temp = minArray[i];
+                    minArray[i] = maxArray[i];
+                    maxArray[i] = temp;
+                }
+            }
+            minAlloc.copyFrom(minArray);
+            maxAlloc.copyFrom(maxArray);
+        } else if (dataType == Element.DataType.UNSIGNED_8) {
+            byte[] minArray = new byte[size];
+            byte[] maxArray = new byte[size];
+            minAlloc.copyTo(minArray);
+            maxAlloc.copyTo(maxArray);
+            for (int i = 0; i < size; i++) {
+                int min = minArray[i] &0xff;
+                int max = maxArray[i] &0xff;
+                if (min > max) {
+                    minArray[i] = (byte) max;
+                    maxArray[i] = (byte) min;
+                }
+            }
+            minAlloc.copyFrom(minArray);
+            maxAlloc.copyFrom(maxArray);
+        } else {
+            android.util.Log.e("RenderscriptCTS", "Ordering not supported for " +
+                    dataType.toString());
+        }
     }
 
-    public void doF32_4(long seed, int ulp) {
-        baseTestHelper(TEST_F32_4, Element.F32_4(mRS), Element.F32_4(mRS), seed, 1, 0, 1, 0, 4, 4, 4, 0, ulp);
-    }
-
-    public void doF32_relaxed(long seed, int ulp) {
-        baseTestHelper(TEST_RELAXED_F32, Element.F32(mRS), Element.F32(mRS), seed, 1, 0, 1, 0, 1, 1, 1, 0, ulp);
-    }
-
-    public void doF32_2_relaxed(long seed, int ulp) {
-        baseTestHelper(TEST_RELAXED_F32_2, Element.F32_2(mRS), Element.F32_2(mRS), seed, 1, 0, 1, 0, 2, 2, 2, 0, ulp);
-    }
-
-    public void doF32_3_relaxed(long seed, int ulp) {
-        baseTestHelper(TEST_RELAXED_F32_3, Element.F32_3(mRS), Element.F32_3(mRS), seed, 1, 0, 4, 1, 3, 4, 4, 1, ulp);
-    }
-
-    public void doF32_4_relaxed(long seed, int ulp) {
-        baseTestHelper(TEST_RELAXED_F32_4, Element.F32_4(mRS), Element.F32_4(mRS), seed, 1, 0, 1, 0, 4, 4, 4, 0, ulp);
-    }
-
-
     public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
         // Intentionally empty... subclass will likely define only one, but not both
     }
@@ -151,33 +388,4 @@
     public void forEach(int testId, Allocation mIn) throws RSRuntimeException {
         // Intentionally empty... subclass will likely define only one, but not both
     }
-
-    //These are default actions for these functions, specific tests overload them
-    protected float[] getRefArray(float[] inArray, int size, int stride, int skip) {
-        return null;
-    }
-
-    protected Allocation setInAlloc(Element e) {
-        return Allocation.createSized(mRS, e, INPUTSIZE);
-    }
-
-    protected Allocation setOutAlloc(Element e) {
-        return Allocation.createSized(mRS, e, INPUTSIZE);
-    }
-
-    protected float[] makeInArray(int size) {
-        return new float[size];
-    }
-
-    protected float[] makeOutArray(int size) {
-        return new float[size];
-    }
-
-    protected void fillRandomFloats(long seed, int fact, int offset, float[] inArray) {
-        RSUtils.genRandomFloats(seed, fact, offset, inArray);
-    }
-
-    protected void fillInAlloc(Allocation mIn, float[] inArray) {
-        mIn.copy1DRangeFromUnchecked(0, INPUTSIZE, inArray);
-    }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/RSUtils.java b/tests/tests/renderscript/src/android/renderscript/cts/RSUtils.java
index d3fb5d0..6038d90 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/RSUtils.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/RSUtils.java
@@ -17,33 +17,207 @@
 package android.renderscript.cts;
 
 import android.content.res.Resources;
-import java.util.Random;
 import android.renderscript.Allocation;
 import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
+
+import java.util.Random;
 
 /**
  * This class supplies some utils for renderscript tests
  */
 public class RSUtils {
+    private static final double[] sInterestingDoubles = {
+        0.0,
+        1.0,
+        Math.E,
+        Math.PI,
+        Math.PI / 2.0,
+        Math.PI * 2.0,
+        -0.0,
+        -1.0,
+        -Math.E,
+        -Math.PI,
+        -Math.PI / 2.0,
+        -Math.PI * 2.0,
+    };
 
     /**
-     * Fills the array with random floats.  Values will be: offset + number between 0 and max.
+     * Fills the array with random doubles.  Values will be between min (inclusive) and
+     * max (inclusive).
      */
-    public static void genRandomFloats(long seed, int max, int offset, float array[]) {
+    public static void genRandomDoubles(long seed, double min, double max, double array[],
+            boolean includeExtremes) {
         Random r = new Random(seed);
-        for (int i = 0; i < array.length; i++) {
-            array[i] = r.nextFloat() * max + offset;
+        int minExponent = Math.min(Math.getExponent(min), 0);
+        int maxExponent = Math.max(Math.getExponent(max), 0);
+        if (minExponent < -6 || maxExponent > 6) {
+            // Use an exponential distribution
+            int exponentDiff = maxExponent - minExponent;
+            for (int i = 0; i < array.length; i++) {
+                double mantissa = r.nextDouble();
+                int exponent = minExponent + r.nextInt(maxExponent - minExponent);
+                int sign = (min >= 0) ? 1 : 1 - r.nextInt(2) * 2;  // -1 or 1
+                double rand = sign * mantissa * Math.pow(2.0, exponent);
+                if (rand < min || rand > max) {
+                    continue;
+                }
+                array[i] = rand;
+            }
+        } else {
+            // Use a linear distribution
+            for (int i = 0; i < array.length; i++) {
+                double rand = r.nextDouble();
+                array[i] = min + rand * (max - min);
+            }
+        }
+        // Seed a few special numbers we want to be sure to test.
+        for (int i = 0; i < sInterestingDoubles.length; i++) {
+            double d = sInterestingDoubles[i];
+            if (min <= d && d <= max) {
+                array[r.nextInt(array.length)] = d;
+            }
+        }
+        array[r.nextInt(array.length)] = min;
+        array[r.nextInt(array.length)] = max;
+        if (includeExtremes) {
+            array[r.nextInt(array.length)] = Double.NaN;
+            array[r.nextInt(array.length)] = Double.POSITIVE_INFINITY;
+            array[r.nextInt(array.length)] = Double.NEGATIVE_INFINITY;
+            array[r.nextInt(array.length)] = Double.MIN_VALUE;
+            array[r.nextInt(array.length)] = Double.MIN_NORMAL;
+            array[r.nextInt(array.length)] = Double.MAX_VALUE;
+            array[r.nextInt(array.length)] = -Double.MIN_VALUE;
+            array[r.nextInt(array.length)] = -Double.MIN_NORMAL;
+            array[r.nextInt(array.length)] = -Double.MAX_VALUE;
         }
     }
 
     /**
-     * Fills the array with random ints.  Values will be: offset + number between 0 and max (exclusive).
+     * Fills the array with random floats.  Values will be between min (inclusive) and
+     * max (inclusive).
      */
-    public static void genRandomInts(long seed, int max, int offset, int array[]) {
+    public static void genRandomFloats(long seed, float min, float max, float array[],
+            boolean includeExtremes) {
+        Random r = new Random(seed);
+        int minExponent = Math.min(Math.getExponent(min), 0);
+        int maxExponent = Math.max(Math.getExponent(max), 0);
+        if (minExponent < -6 || maxExponent > 6) {
+            // Use an exponential distribution
+            int exponentDiff = maxExponent - minExponent;
+            for (int i = 0; i < array.length; i++) {
+                float mantissa = r.nextFloat();
+                int exponent = minExponent + r.nextInt(maxExponent - minExponent);
+                int sign = (min >= 0) ? 1 : 1 - r.nextInt(2) * 2;  // -1 or 1
+                float rand = sign * mantissa * (float) Math.pow(2.0, exponent);
+                if (rand < min || rand > max) {
+                    continue;
+                }
+                array[i] = rand;
+            }
+        } else {
+            // Use a linear distribution
+            for (int i = 0; i < array.length; i++) {
+                float rand = r.nextFloat();
+                array[i] = min + rand * (max - min);
+            }
+        }
+        // Seed a few special numbers we want to be sure to test.
+        for (int i = 0; i < sInterestingDoubles.length; i++) {
+            float f = (float) sInterestingDoubles[i];
+            if (min <= f && f <= max) {
+                array[r.nextInt(array.length)] = f;
+            }
+        }
+        array[r.nextInt(array.length)] = min;
+        array[r.nextInt(array.length)] = max;
+        if (includeExtremes) {
+            array[r.nextInt(array.length)] = Float.NaN;
+            array[r.nextInt(array.length)] = Float.POSITIVE_INFINITY;
+            array[r.nextInt(array.length)] = Float.NEGATIVE_INFINITY;
+            array[r.nextInt(array.length)] = Float.MIN_VALUE;
+            array[r.nextInt(array.length)] = Float.MIN_NORMAL;
+            array[r.nextInt(array.length)] = Float.MAX_VALUE;
+            array[r.nextInt(array.length)] = -Float.MIN_VALUE;
+            array[r.nextInt(array.length)] = -Float.MIN_NORMAL;
+            array[r.nextInt(array.length)] = -Float.MAX_VALUE;
+        }
+    }
+
+    /**
+     * Fills the array with random ints.  Values will be between min (inclusive) and
+     * max (inclusive).
+     */
+    public static void genRandomInts(long seed, int min, int max, int array[]) {
         Random r = new Random(seed);
         for (int i = 0; i < array.length; i++) {
-            array[i] = (r.nextInt(max) + offset);
+            long range = max - min + 1;
+            array[i] = (int) (min + r.nextLong() % range);
         }
+        array[r.nextInt(array.length)] = min;
+        array[r.nextInt(array.length)] = max;
+    }
+
+    /**
+     * Fills the array with random longs.  If signed is true, negative values can be generated.
+     * The values will fit within 'numberOfBits'.  This is useful for conversion tests.
+     */
+    public static void genRandomLongs(long seed, long array[], boolean signed, int numberOfBits) {
+      long positiveMask = numberOfBits == 64 ? -1 : ((1l << numberOfBits) - 1);
+      long negativeMask = ~positiveMask;
+      Random r = new Random(seed);
+      for (int i = 0; i < array.length; i++) {
+          long l = r.nextLong();
+          if (signed && l < 0) {
+              l = l | negativeMask;
+          } else {
+              l = l & positiveMask;
+          }
+          array[i] = l;
+      }
+      // Seed a few special numbers we want to be sure to test.
+      array[r.nextInt(array.length)] = 0l;
+      array[r.nextInt(array.length)] = 1l;
+      array[r.nextInt(array.length)] = positiveMask;
+      if (signed) {
+          array[r.nextInt(array.length)] = negativeMask;
+          array[r.nextInt(array.length)] = -1;
+      }
+    }
+
+    public static void genRandomInts(long seed, int array[], boolean signed, int numberOfBits) {
+        long[] longs = new long[array.length];
+        genRandomLongs(seed, longs, signed, numberOfBits);
+        for (int i = 0; i < array.length; i++) {
+            array[i] = (int) longs[i];
+        }
+    }
+
+    public static void genRandomShorts(long seed, short array[], boolean signed, int numberOfBits) {
+        long[] longs = new long[array.length];
+        genRandomLongs(seed, longs, signed, numberOfBits);
+        for (int i = 0; i < array.length; i++) {
+            array[i] = (short) longs[i];
+        }
+    }
+
+    public static void genRandomBytes(long seed, byte array[], boolean signed, int numberOfBits) {
+        long[] longs = new long[array.length];
+        genRandomLongs(seed, longs, signed, numberOfBits);
+        for (int i = 0; i < array.length; i++) {
+            array[i] = (byte) longs[i];
+        }
+    }
+
+    // Compares two unsigned long.  Returns < 0 if a < b, 0 if a == b, > 0 if a > b.
+    public static long compareUnsignedLong(long a, long b) {
+        long aFirstFourBits = a >>> 60;
+        long bFirstFourBits = b >>> 60;
+        long firstFourBitsDiff = aFirstFourBits - bFirstFourBits;
+        if (firstFourBitsDiff != 0) {
+            return firstFourBitsDiff;
+        }
+        long aRest = a & 0x0fffffffffffffffl;
+        long bRest = b & 0x0fffffffffffffffl;
+        return aRest - bRest;
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/RadiansTest.java b/tests/tests/renderscript/src/android/renderscript/cts/RadiansTest.java
deleted file mode 100644
index a0c7834..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/RadiansTest.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-
-public class RadiansTest extends RSBaseCompute {
-    private ScriptC_radians_f32 script_f32;
-    private ScriptC_radians_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_radians_f32(mRS);
-        script_f32_relaxed = new ScriptC_radians_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_radians_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_radians_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_radians_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_radians_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_radians_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_radians_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_radians_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_radians_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                double val = (double)in[idx] * (Math.PI / 180.0);
-                ref[idxRef] = (float)val;
-            }
-        }
-        return ref;
-    }
-
-    /**
-     * radians test for float
-     */
-    public void testRadiansF32() {
-        doF32(0x1234f678, 3);
-    }
-
-    public void testRadiansF32_relaxed() {
-        doF32_relaxed(0x1234f678, 3);
-    }
-
-    /**
-     * radians test for float2
-     */
-    public void testRadiansF32_2() {
-        doF32_2(0x12345678, 3);
-    }
-
-    public void testRadiansF32_2_relaxed() {
-        doF32_2_relaxed(0x12345678, 3);
-    }
-
-    /**
-     * radians test for float3
-     */
-    public void testRadiansF32_3() {
-        doF32_3(0x123d5678, 3);
-    }
-
-    public void testRadiansF32_3_relaxed() {
-        doF32_3_relaxed(0x123d5678, 3);
-    }
-
-    /**
-     * radians test for float4
-     */
-    public void testRadiansF32_4() {
-        doF32_4(0x123a5678, 3);
-
-    }
-    public void testRadiansF32_4_relaxed() {
-        doF32_4_relaxed(0x123a5678, 3);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/RemainderTest.java b/tests/tests/renderscript/src/android/renderscript/cts/RemainderTest.java
deleted file mode 100644
index edd3320..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/RemainderTest.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import android.renderscript.Element;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-public class RemainderTest extends RSBaseCompute {
-    private ScriptC_remainder_f32 script_f32;
-    private ScriptC_remainder_f32_relaxed script_f32_relaxed;
-    private Allocation mIn;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_remainder_f32(mRS);
-        script_f32_relaxed = new ScriptC_remainder_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_remainder_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_remainder_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_remainder_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_remainder_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_remainder_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_remainder_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_remainder_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_remainder_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx = i * stride * 2 + j;
-                double num = (double)in[idx];
-                double den = (double)in[idx+stride];
-                ref[i * (stride - skip) + j] = (float)(num - Math.round(num / den) * den);
-            }
-        }
-        return ref;
-    }
-
-    @Override
-    protected Allocation setInAlloc(Element e) {
-        return mIn;
-    }
-
-    @Override
-    protected float[] makeInArray(int size) {
-        return new float[size*2];
-    }
-
-    public void testRemainderF32() {
-        ScriptField_remainder_f32 in = new ScriptField_remainder_f32(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32(0x123678, 0);
-    }
-
-    public void testRemainderF32_relaxed() {
-        ScriptField_remainder_f32 in = new ScriptField_remainder_f32(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_relaxed(0x123678, 0);
-    }
-
-    public void testRemainderF32_2() {
-        ScriptField_remainder_f32_2 in = new ScriptField_remainder_f32_2(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_2(0x1234a5, 0);
-    }
-
-    public void testRemainderF32_2_relaxed() {
-        ScriptField_remainder_f32_2 in = new ScriptField_remainder_f32_2(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_2_relaxed(0x1234a5, 0);
-    }
-
-    public void testRemainderF32_3() {
-        ScriptField_remainder_f32_3 in = new ScriptField_remainder_f32_3(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_3(0x1af345, 0);
-    }
-
-    public void testRemainderF32_3_relaxed() {
-        ScriptField_remainder_f32_3 in = new ScriptField_remainder_f32_3(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_3_relaxed(0x1af345, 0);
-    }
-
-    public void testRemainderF32_4() {
-        ScriptField_remainder_f32_4 in = new ScriptField_remainder_f32_4(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_4(0x12ce45, 0);
-    }
-
-    public void testRemainderF32_4_relaxed() {
-        ScriptField_remainder_f32_4 in = new ScriptField_remainder_f32_4(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_4_relaxed(0x12ce45, 0);
-    }
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/RenderScriptTest.java b/tests/tests/renderscript/src/android/renderscript/cts/RenderScriptTest.java
index 9e61526..4007260 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/RenderScriptTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/RenderScriptTest.java
@@ -16,8 +16,6 @@
 
 package android.renderscript.cts;
 
-import com.android.cts.stub.R;
-
 import android.renderscript.RenderScript;
 import android.test.AndroidTestCase;
 
@@ -29,8 +27,7 @@
      */
     public void testRenderScript() {
         RenderScript mRS = RenderScript.create(getContext());
-        ScriptC_passthrough t = new ScriptC_passthrough(mRS,
-            getContext().getResources(), R.raw.passthrough);
+        ScriptC_passthrough t = new ScriptC_passthrough(mRS);
         t.invoke_passthrough(5);
         mRS.destroy();
     }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/RintTest.java b/tests/tests/renderscript/src/android/renderscript/cts/RintTest.java
deleted file mode 100644
index 56c0acf..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/RintTest.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-
-public class RintTest extends RSBaseCompute {
-    private ScriptC_rint_f32 script_f32;
-    private ScriptC_rint_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_rint_f32(mRS);
-        script_f32_relaxed = new ScriptC_rint_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut)
-            throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_rint_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_rint_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_rint_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_rint_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_rint_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_rint_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_rint_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_rint_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] inArray, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * (stride - skip)];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idxIn = i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float) Math.rint(inArray[idxIn]);
-            }
-        }
-        return ref;
-    }
-
-    /**
-     * rint test for float
-     */
-    public void testRintF32() {
-        doF32(0x12345678, 0);
-    }
-
-    public void testRintF32_relaxed() {
-        doF32_relaxed(0x12345678, 0);
-    }
-
-    /**
-     * rint test for float2
-     */
-    public void testRintF32_2() {
-        doF32_2(0x12ab5678, 0);
-    }
-
-    public void testRintF32_2_relaxed() {
-        doF32_2_relaxed(0x12ab5678, 0);
-    }
-
-    /**
-     * rint test for float3
-     */
-    public void testRintF32_3() {
-        doF32_3(0x123ac678, 0);
-    }
-
-    public void testRintF32_3_relaxed() {
-        doF32_3_relaxed(0x123ac678, 0);
-    }
-
-    /**
-     * rint test for float4
-     */
-    public void testRintF32_4() {
-        doF32_4(0x1f345678, 0);
-
-    }
-    public void testRintF32_4_relaxed() {
-        doF32_4_relaxed(0x1f345678, 0);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/RootnTest.java b/tests/tests/renderscript/src/android/renderscript/cts/RootnTest.java
deleted file mode 100644
index 2c447bb..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/RootnTest.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import android.renderscript.Element;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-public class RootnTest extends RSBaseCompute {
-    private ScriptC_rootn_f32 script_f32;
-    private ScriptC_rootn_f32_relaxed script_f32_relaxed;
-    private int[] n;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_rootn_f32(mRS);
-        script_f32_relaxed = new ScriptC_rootn_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_rootn_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_rootn_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_rootn_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_rootn_f32_4(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_rootn_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_rootn_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_rootn_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_rootn_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)Math.pow((double)in[idx], 1.0/(double)n[idx]);
-            }
-        }
-        return ref;
-    }
-
-    public void testRootnF32() {
-        Allocation nAlloc = Allocation.createSized(mRS, Element.I32(mRS), INPUTSIZE);
-
-        n = new int[INPUTSIZE];
-        RSUtils.genRandomInts(0x12345678, 32, 1, n);
-        nAlloc.copyFrom(n);
-        script_f32.set_n1(nAlloc);
-
-        doF32(0x716acd, 16);
-    }
-
-    public void testRootnF32_relaxed() {
-        Allocation nAlloc = Allocation.createSized(mRS, Element.I32(mRS), INPUTSIZE);
-
-        n = new int[INPUTSIZE];
-        RSUtils.genRandomInts(0x12345678, 32, 1, n);
-        nAlloc.copyFrom(n);
-        script_f32_relaxed.set_n1(nAlloc);
-
-        doF32_relaxed(0x716acd, 16);
-    }
-
-
-    public void testRootnF32_2() {
-        Allocation nAlloc = Allocation.createSized(mRS, Element.I32_2(mRS), INPUTSIZE);
-
-        n = new int[INPUTSIZE*2];
-        RSUtils.genRandomInts(0xacdef1, 32, 1, n);
-        nAlloc.copyFrom(n);
-        script_f32.set_n2(nAlloc);
-
-        doF32_2(0xacdef1, 16);
-    }
-
-    public void testRootnF32_2_relaxed() {
-        Allocation nAlloc = Allocation.createSized(mRS, Element.I32_2(mRS), INPUTSIZE);
-
-        n = new int[INPUTSIZE*2];
-        RSUtils.genRandomInts(0xacdef1, 32, 1, n);
-        nAlloc.copyFrom(n);
-        script_f32_relaxed.set_n2(nAlloc);
-
-        doF32_2_relaxed(0xacdef1, 16);
-    }
-
-
-    public void testRootnF32_3() {
-        Allocation nAlloc = Allocation.createSized(mRS, Element.I32_3(mRS), INPUTSIZE);
-
-        n = new int[INPUTSIZE*4];
-        RSUtils.genRandomInts(0xa123f1, 32, 1, n);
-        nAlloc.copyFrom(n);
-        script_f32.set_n3(nAlloc);
-
-        doF32_3(0xaac3f1, 16);
-    }
-
-    public void testRootnF32_3_relaxed() {
-        Allocation nAlloc = Allocation.createSized(mRS, Element.I32_3(mRS), INPUTSIZE);
-
-        n = new int[INPUTSIZE*4];
-        RSUtils.genRandomInts(0xa123f1, 32, 1, n);
-        nAlloc.copyFrom(n);
-        script_f32_relaxed.set_n3(nAlloc);
-
-        doF32_3_relaxed(0xaac3f1, 16);
-    }
-
-    public void testRootnF32_4() {
-        Allocation nAlloc = Allocation.createSized(mRS, Element.I32_4(mRS), INPUTSIZE);
-
-        n = new int[INPUTSIZE*4];
-        RSUtils.genRandomInts(0x4323ca, 32, 1, n);
-        nAlloc.copyFrom(n);
-        script_f32.set_n4(nAlloc);
-
-        doF32_4(0xaa12f1, 16);
-    }
-
-    public void testRootnF32_4_relaxed() {
-        Allocation nAlloc = Allocation.createSized(mRS, Element.I32_4(mRS), INPUTSIZE);
-
-        n = new int[INPUTSIZE*4];
-        RSUtils.genRandomInts(0x4323ca, 32, 1, n);
-        nAlloc.copyFrom(n);
-        script_f32_relaxed.set_n4(nAlloc);
-
-        doF32_4_relaxed(0xaa12f1, 16);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/RoundTest.java b/tests/tests/renderscript/src/android/renderscript/cts/RoundTest.java
deleted file mode 100644
index ab85bc1..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/RoundTest.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-
-public class RoundTest extends RSBaseCompute {
-    private ScriptC_round_f32 script_f32;
-    private ScriptC_round_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_round_f32(mRS);
-        script_f32_relaxed = new ScriptC_round_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut)
-            throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_round_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_round_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_round_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_round_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_round_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_round_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_round_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_round_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] inArray, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * (stride - skip)];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idxIn = i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                int res = ((Float.floatToIntBits(inArray[idxIn]) >> 31) & 0x01);
-                float roundValue = (float) Math.round(inArray[idxIn]);
-                float expective = roundValue;
-                if ((roundValue - inArray[idxIn]) == 0.5f && res == 1)
-                    expective -= 1;
-                if (res == 1 && expective == +0.0f) {
-                    expective = -0.0f;
-                }
-                ref[idxRef] = expective;
-            }
-        }
-        return ref;
-    }
-
-    /**
-     * round test for float
-     */
-    public void testRoundF32() {
-        doF32(0x12345678, 0);
-    }
-
-    public void testRoundF32_relaxed() {
-        doF32_relaxed(0x12345678, 0);
-    }
-
-    /**
-     * round test for float2
-     */
-    public void testRoundF32_2() {
-        doF32_2(0x123a5678, 0);
-    }
-
-    public void testRoundF32_2_relaxed() {
-        doF32_2_relaxed(0x123a5678, 0);
-    }
-
-    /**
-     * round test for float3
-     */
-    public void testRoundF32_3() {
-        doF32_3(0x1af45678, 0);
-    }
-
-    public void testRoundF32_3_relaxed() {
-        doF32_3_relaxed(0x1af45678, 0);
-    }
-
-    /**
-     * round test for float4
-     */
-    public void testRoundF32_4() {
-        doF32_4(0x1f345678, 0);
-
-    }
-    public void testRoundF32_4_relaxed() {
-        doF32_4_relaxed(0x1f345678, 0);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/RsFracTest.java b/tests/tests/renderscript/src/android/renderscript/cts/RsFracTest.java
deleted file mode 100644
index 2185ae2..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/RsFracTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-public class RsFracTest extends RSBaseCompute {
-    private ScriptC_rs_frac_f32 mScript;
-    private ScriptC_rs_frac_f32_relaxed mScript_relaxed;
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut)
-            throws RSRuntimeException {
-        if (testId == TEST_F32) {
-            mScript.forEach_root(mIn, mOut);
-        } else if (testId == TEST_RELAXED_F32) {
-            mScript_relaxed.forEach_root(mIn, mOut);
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = Math.min(in[idx] - (float)Math.floor((double)in[idx]), 0x1.fffffep-1f);
-            }
-        }
-        return ref;
-    }
-
-    public void testRsFrac() {
-        mScript = new ScriptC_rs_frac_f32(mRS, mRes, R.raw.rs_frac_f32);
-        doF32(0x12, 0);
-    }
-    public void testRsFrac_relaxed() {
-        mScript_relaxed = new ScriptC_rs_frac_f32_relaxed(mRS, mRes, R.raw.rs_frac_f32);
-        doF32_relaxed(0x12, 1);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/RsPackColorTo8888Test.java b/tests/tests/renderscript/src/android/renderscript/cts/RsPackColorTo8888Test.java
index edff5b9d..d6ea521 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/RsPackColorTo8888Test.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/RsPackColorTo8888Test.java
@@ -16,7 +16,6 @@
 
 package android.renderscript.cts;
 
-import com.android.cts.stub.R;
 import android.renderscript.Allocation;
 import android.renderscript.Element;
 import android.renderscript.Float3;
@@ -72,7 +71,7 @@
         float[] inArray = new float[INPUTSIZE * 4];
         byte[] outArray = new byte[INPUTSIZE * 4];
         byte[] refArray = new byte[INPUTSIZE * 4];
-        RSUtils.genRandomFloats(seed, 1, 0, inArray);
+        RSUtils.genRandomFloats(seed, 0.0f, 1.0f, inArray, false);
         mAllocationIn.copy1DRangeFrom(0, INPUTSIZE, inArray);
         try {
             forEach(testId, mAllocationIn, mAllocationOut);
@@ -99,7 +98,7 @@
         float[] inArray = new float[INPUTSIZE * 4];
         byte[] outArray = new byte[INPUTSIZE * 4];
         byte[] refArray = new byte[INPUTSIZE * 4];
-        RSUtils.genRandomFloats(seed, 1, 0, inArray);
+        RSUtils.genRandomFloats(seed, 0.0f, 1.0f, inArray, false);
         mAllocationIn.copy1DRangeFrom(0, INPUTSIZE, inArray);
         try {
             forEach(testId, mAllocationIn, mAllocationOut);
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/RsUnpackColor8888Test.java b/tests/tests/renderscript/src/android/renderscript/cts/RsUnpackColor8888Test.java
index 3ebbee1..4754a9f 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/RsUnpackColor8888Test.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/RsUnpackColor8888Test.java
@@ -16,7 +16,6 @@
 
 package android.renderscript.cts;
 
-import com.android.cts.stub.R;
 import android.renderscript.Allocation;
 import android.renderscript.Element;
 import android.renderscript.Float4;
@@ -32,7 +31,7 @@
     }
 
     public void testRsUnpackColor8888RGB() {
-        script = new ScriptC_rs_unpack_color_8888(mRS, mRes, R.raw.rs_unpack_color_8888);
+        script = new ScriptC_rs_unpack_color_8888(mRS);
         Allocation mAllocationIn = Allocation.createSized(mRS, Element.U8_4(mRS), INPUTSIZE);
         Allocation mAllocationOut = Allocation.createSized(mRS, Element.F32_4(mRS), INPUTSIZE);
         byte[] inArray = new byte[INPUTSIZE * 4];
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/RsqrtTest.java b/tests/tests/renderscript/src/android/renderscript/cts/RsqrtTest.java
deleted file mode 100644
index 1183886..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/RsqrtTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-
-public class RsqrtTest extends RSBaseCompute {
-    private ScriptC_rsqrt_f32 script_f32;
-    private ScriptC_rsqrt_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_rsqrt_f32(mRS);
-        script_f32_relaxed = new ScriptC_rsqrt_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_Rsqrt_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_Rsqrt_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_Rsqrt_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_Rsqrt_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_Rsqrt_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_Rsqrt_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_Rsqrt_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_Rsqrt_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)Math.pow((double)in[idx], -0.5);
-            }
-        }
-        return ref;
-    }
-
-    public void testRsqrtF32() {
-        doF32(0x12345678, 2);
-    }
-
-    public void testRsqrtF32_relaxed() {
-        doF32_relaxed(0x12345678, 2);
-    }
-
-    public void testRsqrtF32_2() {
-        doF32_2(0x12ae4567, 2);
-    }
-
-    public void testRsqrtF32_2_relaxed() {
-        doF32_2_relaxed(0x12ae4567, 2);
-    }
-
-    public void testRsqrtF32_3() {
-        doF32_3(0x12cf8, 2);
-    }
-
-    public void testRsqrtF32_3_relaxed() {
-        doF32_3_relaxed(0x12cf8, 2);
-    }
-
-    public void testRsqrtF32_4() {
-        doF32_4(0x12abc8, 2);
-
-    }
-    public void testRsqrtF32_4_relaxed() {
-        doF32_4_relaxed(0x12abc8, 2);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/SampleTest.java b/tests/tests/renderscript/src/android/renderscript/cts/SampleTest.java
index 3c8650d..bc69b0e 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/SampleTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/SampleTest.java
@@ -16,8 +16,6 @@
 
 package android.renderscript.cts;
 
-import com.android.cts.stub.R;
-
 import android.graphics.Bitmap;
 import android.renderscript.Allocation;
 import android.renderscript.Allocation.MipmapControl;
@@ -34,6 +32,36 @@
     Allocation mAlloc_RGBA_1D;
     Allocation mAlloc_RGBA_2D;
 
+    Allocation createAlloc(Type t) {
+        Allocation a = Allocation.createTyped(mRS, t, Allocation.MipmapControl.MIPMAP_FULL,
+                                              Allocation.USAGE_SCRIPT);
+
+        int[] tmp = new int[t.getCount()];
+        int idx = 0;
+        int w = t.getY();
+        if (w < 1) {
+            w = 1;
+        }
+
+        for (int ct = 0; ct < (8 * w); ct++) {
+            tmp[idx++] = 0x0000ffff;
+        }
+        w = (w + 1) >> 1;
+        for (int ct = 0; ct < (4 * w); ct++) {
+            tmp[idx++] = 0x00ff00ff;
+        }
+        w = (w + 1) >> 1;
+        for (int ct = 0; ct < (2 * w); ct++) {
+            tmp[idx++] = 0x00ffff00;
+        }
+        w = (w + 1) >> 1;
+        for (int ct = 0; ct < (1 * 1); ct++) {
+            tmp[idx++] = 0xffffff00;
+        }
+        a.copyFromUnchecked(tmp);
+        return a;
+    }
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -41,18 +69,10 @@
         Element format = Element.RGBA_8888(mRS);
         Type.Builder b = new Type.Builder(mRS, format);
         b.setMipmaps(true);
-        mAlloc_RGBA_1D = Allocation.createTyped(mRS, b.setX(8).create(),
-                                                Allocation.MipmapControl.MIPMAP_FULL,
-                                                Allocation.USAGE_SCRIPT);
-        mAlloc_RGBA_2D = Allocation.createTyped(mRS, b.setX(8).setY(8).create(),
-                                                Allocation.MipmapControl.MIPMAP_FULL,
-                                                Allocation.USAGE_SCRIPT);
+        mAlloc_RGBA_1D = createAlloc(b.setX(8).create());
+        mAlloc_RGBA_2D = createAlloc(b.setX(8).setY(8).create());
 
-        mScript = new ScriptC_sample(mRS, mRes, R.raw.sample);
-        mScript.bind_gAllocPtr(mAlloc_RGBA_1D);
-        mScript.invoke_init_RGBA(mAlloc_RGBA_1D);
-        mScript.bind_gAllocPtr(mAlloc_RGBA_2D);
-        mScript.invoke_init_RGBA(mAlloc_RGBA_2D);
+        mScript = new ScriptC_sample(mRS);
 
         mScript.set_gNearest(Sampler.CLAMP_NEAREST(mRS));
         mScript.set_gLinear(Sampler.CLAMP_LINEAR(mRS));
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/ScriptCTest.java b/tests/tests/renderscript/src/android/renderscript/cts/ScriptCTest.java
deleted file mode 100644
index 7f4ba93..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/ScriptCTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.
- */
-
-package android.renderscript.cts;
-
-import android.content.res.Resources;
-
-import android.renderscript.RenderScript;
-import android.renderscript.ScriptC;
-
-import com.android.cts.stub.R;
-
-public class ScriptCTest extends RSBaseCompute {
-
-    class ScriptCHelper extends ScriptC {
-        public ScriptCHelper(int id, RenderScript rs) {
-            super(id, rs);
-        }
-
-        public ScriptCHelper(RenderScript rs,
-                             Resources resources,
-                             int resourceID) {
-            super(rs, resources, resourceID);
-        }
-    }
-
-    public void testScriptC() {
-        // Test basic constructor
-        ScriptCHelper h = new ScriptCHelper(0, mRS);
-
-        // Test actual constructor
-        h = new ScriptCHelper(mRS, mRes, R.raw.negate);
-    }
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_leak.java b/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_leak.java
deleted file mode 100644
index c026755..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_leak.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2011-2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * This file is auto-generated. DO NOT MODIFY!
- * The source Renderscript file: leak.rs
- */
-package android.renderscript.cts;
-
-import android.renderscript.*;
-import android.content.res.Resources;
-
-/**
- * @hide
- */
-public class ScriptC_leak extends ScriptC {
-    private static final String __rs_resource_name = "leak";
-    // Constructor
-    public  ScriptC_leak(RenderScript rs) {
-        this(rs,
-             rs.getApplicationContext().getResources(),
-             rs.getApplicationContext().getResources().getIdentifier(
-                 __rs_resource_name, "raw",
-                 rs.getApplicationContext().getPackageName()));
-    }
-
-    public  ScriptC_leak(RenderScript rs, Resources resources, int id) {
-        super(rs, resources, id);
-    }
-
-    private FieldPacker __rs_fp_ALLOCATION;
-    private final static int mExportVarIdx_a = 0;
-    private Allocation mExportVar_a;
-    public synchronized void set_a(Allocation v) {
-        setVar(mExportVarIdx_a, v);
-        mExportVar_a = v;
-    }
-
-    public Allocation get_a() {
-        return mExportVar_a;
-    }
-
-    private final static int mExportFuncIdx_print = 0;
-    public void invoke_print() {
-        invoke(mExportFuncIdx_print);
-    }
-
-}
-
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_11.java b/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_11.java
deleted file mode 100644
index e4ba592..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_11.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2011-2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * This file is auto-generated. DO NOT MODIFY!
- * The source Renderscript file: set_target_api_11.rs
- */
-package android.renderscript.cts;
-
-import android.renderscript.*;
-import android.content.res.Resources;
-
-/**
- * @hide
- */
-public class ScriptC_set_target_api_11 extends ScriptC {
-    private static final String __rs_resource_name = "set_target_api_11";
-    // Constructor
-    public  ScriptC_set_target_api_11(RenderScript rs) {
-        this(rs,
-             rs.getApplicationContext().getResources(),
-             rs.getApplicationContext().getResources().getIdentifier(
-                 __rs_resource_name, "raw",
-                 rs.getApplicationContext().getPackageName()));
-    }
-
-    public  ScriptC_set_target_api_11(RenderScript rs, Resources resources, int id) {
-        super(rs, resources, id);
-    }
-
-    private final static int mExportFuncIdx_check = 0;
-    public void invoke_check(int version) {
-        FieldPacker check_fp = new FieldPacker(4);
-        check_fp.addI32(version);
-        invoke(mExportFuncIdx_check, check_fp);
-    }
-
-}
-
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_12.java b/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_12.java
deleted file mode 100644
index c0e6c71..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_12.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2011-2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * This file is auto-generated. DO NOT MODIFY!
- * The source Renderscript file: set_target_api_12.rs
- */
-package android.renderscript.cts;
-
-import android.renderscript.*;
-import android.content.res.Resources;
-
-/**
- * @hide
- */
-public class ScriptC_set_target_api_12 extends ScriptC {
-    private static final String __rs_resource_name = "set_target_api_12";
-    // Constructor
-    public  ScriptC_set_target_api_12(RenderScript rs) {
-        this(rs,
-             rs.getApplicationContext().getResources(),
-             rs.getApplicationContext().getResources().getIdentifier(
-                 __rs_resource_name, "raw",
-                 rs.getApplicationContext().getPackageName()));
-    }
-
-    public  ScriptC_set_target_api_12(RenderScript rs, Resources resources, int id) {
-        super(rs, resources, id);
-    }
-
-    private final static int mExportFuncIdx_check = 0;
-    public void invoke_check(int version) {
-        FieldPacker check_fp = new FieldPacker(4);
-        check_fp.addI32(version);
-        invoke(mExportFuncIdx_check, check_fp);
-    }
-
-}
-
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_13.java b/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_13.java
deleted file mode 100644
index 0c0eacc..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_13.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2011-2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * This file is auto-generated. DO NOT MODIFY!
- * The source Renderscript file: set_target_api_13.rs
- */
-package android.renderscript.cts;
-
-import android.renderscript.*;
-import android.content.res.Resources;
-
-/**
- * @hide
- */
-public class ScriptC_set_target_api_13 extends ScriptC {
-    private static final String __rs_resource_name = "set_target_api_13";
-    // Constructor
-    public  ScriptC_set_target_api_13(RenderScript rs) {
-        this(rs,
-             rs.getApplicationContext().getResources(),
-             rs.getApplicationContext().getResources().getIdentifier(
-                 __rs_resource_name, "raw",
-                 rs.getApplicationContext().getPackageName()));
-    }
-
-    public  ScriptC_set_target_api_13(RenderScript rs, Resources resources, int id) {
-        super(rs, resources, id);
-    }
-
-    private final static int mExportFuncIdx_check = 0;
-    public void invoke_check(int version) {
-        FieldPacker check_fp = new FieldPacker(4);
-        check_fp.addI32(version);
-        invoke(mExportFuncIdx_check, check_fp);
-    }
-
-}
-
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_14.java b/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_14.java
deleted file mode 100644
index d6184725..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_14.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2011-2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * This file is auto-generated. DO NOT MODIFY!
- * The source Renderscript file: set_target_api_14.rs
- */
-package android.renderscript.cts;
-
-import android.renderscript.*;
-import android.content.res.Resources;
-
-/**
- * @hide
- */
-public class ScriptC_set_target_api_14 extends ScriptC {
-    private static final String __rs_resource_name = "set_target_api_14";
-    // Constructor
-    public  ScriptC_set_target_api_14(RenderScript rs) {
-        this(rs,
-             rs.getApplicationContext().getResources(),
-             rs.getApplicationContext().getResources().getIdentifier(
-                 __rs_resource_name, "raw",
-                 rs.getApplicationContext().getPackageName()));
-    }
-
-    public  ScriptC_set_target_api_14(RenderScript rs, Resources resources, int id) {
-        super(rs, resources, id);
-    }
-
-    private final static int mExportFuncIdx_check = 0;
-    public void invoke_check(int version) {
-        FieldPacker check_fp = new FieldPacker(4);
-        check_fp.addI32(version);
-        invoke(mExportFuncIdx_check, check_fp);
-    }
-
-}
-
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_15.java b/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_15.java
deleted file mode 100644
index a031b1c..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_15.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2011-2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * This file is auto-generated. DO NOT MODIFY!
- * The source Renderscript file: set_target_api_15.rs
- */
-package android.renderscript.cts;
-
-import android.renderscript.*;
-import android.content.res.Resources;
-
-/**
- * @hide
- */
-public class ScriptC_set_target_api_15 extends ScriptC {
-    private static final String __rs_resource_name = "set_target_api_15";
-    // Constructor
-    public  ScriptC_set_target_api_15(RenderScript rs) {
-        this(rs,
-             rs.getApplicationContext().getResources(),
-             rs.getApplicationContext().getResources().getIdentifier(
-                 __rs_resource_name, "raw",
-                 rs.getApplicationContext().getPackageName()));
-    }
-
-    public  ScriptC_set_target_api_15(RenderScript rs, Resources resources, int id) {
-        super(rs, resources, id);
-    }
-
-    private final static int mExportFuncIdx_check = 0;
-    public void invoke_check(int version) {
-        FieldPacker check_fp = new FieldPacker(4);
-        check_fp.addI32(version);
-        invoke(mExportFuncIdx_check, check_fp);
-    }
-
-}
-
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_16.java b/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_16.java
deleted file mode 100644
index bc48c48..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_16.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2011-2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * This file is auto-generated. DO NOT MODIFY!
- * The source Renderscript file: set_target_api_16.rs
- */
-package android.renderscript.cts;
-
-import android.renderscript.*;
-import android.content.res.Resources;
-
-/**
- * @hide
- */
-public class ScriptC_set_target_api_16 extends ScriptC {
-    private static final String __rs_resource_name = "set_target_api_16";
-    // Constructor
-    public  ScriptC_set_target_api_16(RenderScript rs) {
-        this(rs,
-             rs.getApplicationContext().getResources(),
-             rs.getApplicationContext().getResources().getIdentifier(
-                 __rs_resource_name, "raw",
-                 rs.getApplicationContext().getPackageName()));
-    }
-
-    public  ScriptC_set_target_api_16(RenderScript rs, Resources resources, int id) {
-        super(rs, resources, id);
-    }
-
-    private final static int mExportFuncIdx_check = 0;
-    public void invoke_check(int version) {
-        FieldPacker check_fp = new FieldPacker(4);
-        check_fp.addI32(version);
-        invoke(mExportFuncIdx_check, check_fp);
-    }
-
-}
-
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_17.java b/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_17.java
deleted file mode 100644
index 176c8e3..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_17.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2011-2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * This file is auto-generated. DO NOT MODIFY!
- * The source Renderscript file: set_target_api_17.rs
- */
-package android.renderscript.cts;
-
-import android.renderscript.*;
-import android.content.res.Resources;
-
-/**
- * @hide
- */
-public class ScriptC_set_target_api_17 extends ScriptC {
-    private static final String __rs_resource_name = "set_target_api_17";
-    // Constructor
-    public  ScriptC_set_target_api_17(RenderScript rs) {
-        this(rs,
-             rs.getApplicationContext().getResources(),
-             rs.getApplicationContext().getResources().getIdentifier(
-                 __rs_resource_name, "raw",
-                 rs.getApplicationContext().getPackageName()));
-    }
-
-    public  ScriptC_set_target_api_17(RenderScript rs, Resources resources, int id) {
-        super(rs, resources, id);
-    }
-
-    private final static int mExportFuncIdx_check = 0;
-    public void invoke_check(int version) {
-        FieldPacker check_fp = new FieldPacker(4);
-        check_fp.addI32(version);
-        invoke(mExportFuncIdx_check, check_fp);
-    }
-
-}
-
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_18.java b/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_18.java
deleted file mode 100644
index a0ab5ad..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_18.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2011-2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * This file is auto-generated. DO NOT MODIFY!
- * The source Renderscript file: set_target_api_18.rs
- */
-package android.renderscript.cts;
-
-import android.renderscript.*;
-import android.content.res.Resources;
-
-/**
- * @hide
- */
-public class ScriptC_set_target_api_18 extends ScriptC {
-    private static final String __rs_resource_name = "set_target_api_18";
-    // Constructor
-    public  ScriptC_set_target_api_18(RenderScript rs) {
-        this(rs,
-             rs.getApplicationContext().getResources(),
-             rs.getApplicationContext().getResources().getIdentifier(
-                 __rs_resource_name, "raw",
-                 rs.getApplicationContext().getPackageName()));
-    }
-
-    public  ScriptC_set_target_api_18(RenderScript rs, Resources resources, int id) {
-        super(rs, resources, id);
-    }
-
-    private final static int mExportFuncIdx_check = 0;
-    public void invoke_check(int version) {
-        FieldPacker check_fp = new FieldPacker(4);
-        check_fp.addI32(version);
-        invoke(mExportFuncIdx_check, check_fp);
-    }
-
-}
-
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_19.java b/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_19.java
deleted file mode 100644
index c5017a2..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_19.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2011-2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * This file is auto-generated. DO NOT MODIFY!
- * The source Renderscript file: set_target_api_19.rs
- */
-package android.renderscript.cts;
-
-import android.renderscript.*;
-import android.content.res.Resources;
-
-/**
- * @hide
- */
-public class ScriptC_set_target_api_19 extends ScriptC {
-    private static final String __rs_resource_name = "set_target_api_19";
-    // Constructor
-    public  ScriptC_set_target_api_19(RenderScript rs) {
-        this(rs,
-             rs.getApplicationContext().getResources(),
-             rs.getApplicationContext().getResources().getIdentifier(
-                 __rs_resource_name, "raw",
-                 rs.getApplicationContext().getPackageName()));
-    }
-
-    public  ScriptC_set_target_api_19(RenderScript rs, Resources resources, int id) {
-        super(rs, resources, id);
-    }
-
-    private final static int mExportFuncIdx_check = 0;
-    public void invoke_check(int version) {
-        FieldPacker check_fp = new FieldPacker(4);
-        check_fp.addI32(version);
-        invoke(mExportFuncIdx_check, check_fp);
-    }
-
-}
-
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_too_high.java b/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_too_high.java
deleted file mode 100644
index f54ab46..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/ScriptC_set_target_api_too_high.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2011-2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * This file is auto-generated. DO NOT MODIFY!
- * The source Renderscript file: set_target_api_16.rs
- */
-package android.renderscript.cts;
-
-import android.renderscript.*;
-import android.content.res.Resources;
-
-/**
- * @hide
- */
-public class ScriptC_set_target_api_too_high extends ScriptC {
-    private static final String __rs_resource_name = "set_target_api_too_high";
-    // Constructor
-    public  ScriptC_set_target_api_too_high(RenderScript rs) {
-        this(rs,
-             rs.getApplicationContext().getResources(),
-             rs.getApplicationContext().getResources().getIdentifier(
-                 __rs_resource_name, "raw",
-                 rs.getApplicationContext().getPackageName()));
-    }
-
-    public  ScriptC_set_target_api_too_high(RenderScript rs, Resources resources, int id) {
-        super(rs, resources, id);
-    }
-
-    private final static int mExportFuncIdx_check = 0;
-    public void invoke_check(int version) {
-        FieldPacker check_fp = new FieldPacker(4);
-        check_fp.addI32(version);
-        invoke(mExportFuncIdx_check, check_fp);
-    }
-
-}
-
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/ScriptGroupTest.java b/tests/tests/renderscript/src/android/renderscript/cts/ScriptGroupTest.java
index c9a79c8..d44c305 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/ScriptGroupTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/ScriptGroupTest.java
@@ -16,8 +16,6 @@
 
 package android.renderscript.cts;
 
-import com.android.cts.stub.R;
-
 import android.graphics.Bitmap;
 import android.renderscript.Allocation;
 import android.renderscript.AllocationAdapter;
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/ScriptTest.java b/tests/tests/renderscript/src/android/renderscript/cts/ScriptTest.java
index 90b847a..8c41e14 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/ScriptTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/ScriptTest.java
@@ -28,12 +28,10 @@
 
 import android.renderscript.cts.ScriptC_negate;
 
-import com.android.cts.stub.R;
-
 public class ScriptTest extends RSBaseCompute {
 
     public void testScript() {
-        Script S = new ScriptC_primitives(mRS, mRes, R.raw.primitives);
+        Script S = new ScriptC_primitives(mRS);
 
         S.setTimeZone("America/New_York");
 
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/SendToClient.java b/tests/tests/renderscript/src/android/renderscript/cts/SendToClient.java
index 56961a9..8b48bea 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/SendToClient.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/SendToClient.java
@@ -15,19 +15,20 @@
  */
 package android.renderscript.cts;
 
+import java.util.concurrent.Semaphore;
 import java.util.Random;
 
 import android.renderscript.Allocation;
 import android.renderscript.Element;
 import android.renderscript.RenderScript.RSMessageHandler;
-import com.android.cts.stub.R;
 
 public class SendToClient extends RSBaseCompute {
     private Allocation mInAllocation;
+    private static final Semaphore mSync = new Semaphore(0);
     private static Random random = new Random();
 
     int outArray[] = new int[4];
-    RSMessageHandlerForTest mRsMessage = new RSMessageHandlerForTest() {
+    RSMessageHandler mRsMessage = new RSMessageHandler() {
         public void run() {
             switch (mID) {
                 default:
@@ -36,7 +37,7 @@
                     outArray[2] = mData[1];
                     outArray[3] = mData[2];
                     try {
-                        releaseForTest();
+                        mSync.release();
                     } catch (Exception e) {
                         //TODO: handle exception
                     }
@@ -57,10 +58,10 @@
         mInAllocation.copyFrom(inArray);
         ScriptC_send_to_client mScript;
         mRS.setMessageHandler(mRsMessage);
-        mScript = new ScriptC_send_to_client(mRS,mRes,R.raw.send_to_client);
+        mScript = new ScriptC_send_to_client(mRS);
         mScript.forEach_root(mInAllocation);
         try {
-            mRsMessage.waitForTest();
+            mSync.acquire();
         } catch (InterruptedException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
@@ -79,10 +80,10 @@
         int Id = random.nextInt(100);
         mRS.setMessageHandler(mRsMessage);
         ScriptC_send_to_client_1 mScript;
-        mScript = new ScriptC_send_to_client_1(mRS,mRes,R.raw.send_to_client_1);
+        mScript = new ScriptC_send_to_client_1(mRS);
         mScript.invoke_callback(Id);
         try {
-            mRsMessage.waitForTest();
+            mSync.acquire();
         } catch (InterruptedException e) {
         // TODO Auto-generated catch block
             e.printStackTrace();
@@ -98,13 +99,4 @@
         bf.append("; exceptValue = " + temp);
         return bf.toString();
     }
-
-    class RSMessageHandlerForTest extends RSMessageHandler {
-        public synchronized void waitForTest() throws InterruptedException {
-            wait();
-        }
-        public synchronized void releaseForTest() throws InterruptedException {
-            notify();
-        }
-    }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/SendToClientBlockingTest.java b/tests/tests/renderscript/src/android/renderscript/cts/SendToClientBlockingTest.java
index 5083f87..58fba9b 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/SendToClientBlockingTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/SendToClientBlockingTest.java
@@ -18,11 +18,11 @@
 
 import android.renderscript.RenderScript.RSMessageHandler;
 
+import java.util.concurrent.Semaphore;
 import java.util.Random;
 
-import com.android.cts.stub.R;
-
 public class SendToClientBlockingTest extends RSBaseCompute {
+    private static final Semaphore mSync = new Semaphore(0);
 
     private ScriptC_sendToClientBlocking mScript;
     private Random random;
@@ -36,14 +36,14 @@
         random = new Random();
     }
 
-    RSMessageHandlerForTest mRsMessageForTest = new RSMessageHandlerForTest() {
+    RSMessageHandler mRsMessageForTest = new RSMessageHandler() {
         public void run() {
             switch (mID) {
             default:
                 resultId = mID;
                 resultData = mData[0];
                 try {
-                    releaseForTest();
+                    mSync.release();
                 } catch (Exception e) {
                     // TODO: handle exception
                 }
@@ -56,13 +56,12 @@
 
         int id = random.nextInt(10);
         mRS.setMessageHandler(mRsMessageForTest);
-        mScript = new ScriptC_sendToClientBlocking(mRS, mRes,
-                R.raw.sendtoclientblocking);
+        mScript = new ScriptC_sendToClientBlocking(mRS);
         mScript.set_ID(id);
         // Log.i("testSendToClientBlocking1Params", "==" + id);
         mScript.invoke_callBack1Params();
         try {
-            mRsMessageForTest.waitForTest();
+            mSync.acquire();
         } catch (InterruptedException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
@@ -76,14 +75,13 @@
         int id = random.nextInt(10);
         int data = random.nextInt();
         mRS.setMessageHandler(mRsMessageForTest);
-        mScript = new ScriptC_sendToClientBlocking(mRS, mRes,
-                R.raw.sendtoclientblocking);
+        mScript = new ScriptC_sendToClientBlocking(mRS);
         mScript.set_ID(id);
         mScript.set_data(data);
         // Log.i("testSendToClientBlocking3Params", data + "==" + id);
         mScript.invoke_callBack3Params();
         try {
-            mRsMessageForTest.waitForTest();
+            mSync.acquire();
         } catch (InterruptedException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
@@ -93,15 +91,3 @@
     }
 
 }
-
-/** This class is used to wait callback. */
-class RSMessageHandlerForTest extends RSMessageHandler {
-
-    public synchronized void waitForTest() throws InterruptedException {
-        wait();
-    }
-
-    public synchronized void releaseForTest() throws InterruptedException {
-        notify();
-    }
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/SetObjectTest.java b/tests/tests/renderscript/src/android/renderscript/cts/SetObjectTest.java
index a6626ee..ef6687f 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/SetObjectTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/SetObjectTest.java
@@ -20,7 +20,6 @@
 import android.renderscript.Allocation;
 import android.renderscript.Element;
 import android.util.Log;
-import com.android.cts.stub.R;
 
 import junit.framework.Assert;
 
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/SignTest.java b/tests/tests/renderscript/src/android/renderscript/cts/SignTest.java
deleted file mode 100644
index 69e2636..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/SignTest.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-public class SignTest extends RSBaseCompute {
-    private ScriptC_sign_f32 script_f32;
-    private ScriptC_sign_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_sign_f32(mRS);
-        script_f32_relaxed = new ScriptC_sign_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_sign_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_sign_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_sign_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_sign_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_sign_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_sign_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_sign_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_sign_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idxIn = i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = in[idxIn] > 0.f ? 1.f : -1.f;
-            }
-        }
-        return ref;
-    }
-
-    /**
-     * This method is used for sign() function with f32
-     */
-    public void testSignF32() {
-        doF32(0x12345678, 0);
-    }
-
-    public void testSignF32_relaxed() {
-        doF32_relaxed(0x12345678, 0);
-    }
-
-    public void testSignF32_2() {
-        doF32_2(0x12a45678, 0);
-    }
-
-    public void testSignF32_2_relaxed() {
-        doF32_2_relaxed(0x12a45678, 0);
-    }
-
-    /**
-     * This method is used for sign() function with f32_3
-     */
-    public void testSignF32_3() {
-        doF32_3(0x123c5678, 0);
-    }
-
-    public void testSignF32_3_relaxed() {
-        doF32_3_relaxed(0x123c5678, 0);
-    }
-
-    /**
-     * This method is used for sign() function with f32_4
-     */
-    public void testSignF32_4() {
-        doF32_4(0x123d678, 0);
-
-    }
-    public void testSignF32_4_relaxed() {
-        doF32_4_relaxed(0x123d678, 0);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/SinTest.java b/tests/tests/renderscript/src/android/renderscript/cts/SinTest.java
deleted file mode 100644
index 5911632..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/SinTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-
-public class SinTest extends RSBaseCompute {
-    private ScriptC_sin_f32 script_f32;
-    private ScriptC_sin_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_sin_f32(mRS);
-        script_f32_relaxed = new ScriptC_sin_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_sin_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_sin_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_sin_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_sin_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_sin_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_sin_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_sin_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_sin_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)(Math.sin((double)in[idx]));
-            }
-        }
-        return ref;
-    }
-
-    public void testSinF32() {
-        doF32(0xba, 4);
-    }
-
-    public void testSinF32_relaxed() {
-        doF32_relaxed(0xba, 128);
-    }
-
-    public void testSinF32_2() {
-        doF32_2(0xbaa, 4);
-    }
-
-    public void testSinF32_2_relaxed() {
-        doF32_2_relaxed(0xbaa, 128);
-    }
-
-    public void testSinF32_3() {
-        doF32_3(0xca, 4);
-    }
-
-    public void testSinF32_3_relaxed() {
-        doF32_3_relaxed(0xca, 128);
-    }
-
-    public void testSinF32_4() {
-        doF32_4(0xda, 4);
-
-    }
-    public void testSinF32_4_relaxed() {
-        doF32_4_relaxed(0xda, 128);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/SinhTest.java b/tests/tests/renderscript/src/android/renderscript/cts/SinhTest.java
deleted file mode 100644
index a95c574..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/SinhTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-
-public class SinhTest extends RSBaseCompute {
-    private ScriptC_sinh_f32 script_f32;
-    private ScriptC_sinh_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_sinh_f32(mRS);
-        script_f32_relaxed = new ScriptC_sinh_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_sinh_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_sinh_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_sinh_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_sinh_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_sinh_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_sinh_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_sinh_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_sinh_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)(Math.sinh((double)in[idx]));
-            }
-        }
-        return ref;
-    }
-
-    public void testSinhF32() {
-        doF32(0x32a, 4);
-    }
-
-    public void testSinhF32_relaxed() {
-        doF32_relaxed(0x32a, 128);
-    }
-
-    public void testSinhF32_2() {
-        doF32_2(0xba35, 4);
-    }
-
-    public void testSinhF32_2_relaxed() {
-        doF32_2_relaxed(0xba35, 128);
-    }
-
-    public void testSinhF32_3() {
-        doF32_3(0xacc3, 4);
-    }
-
-    public void testSinhF32_3_relaxed() {
-        doF32_3_relaxed(0xacc3, 128);
-    }
-
-    public void testSinhF32_4() {
-        doF32_4(0xaa, 4);
-
-    }
-    public void testSinhF32_4_relaxed() {
-        doF32_4_relaxed(0xaa, 128);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/SqrtTest.java b/tests/tests/renderscript/src/android/renderscript/cts/SqrtTest.java
deleted file mode 100644
index 02290ca..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/SqrtTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-
-public class SqrtTest extends RSBaseCompute {
-    private ScriptC_sqrt_f32 script_f32;
-    private ScriptC_sqrt_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_sqrt_f32(mRS);
-        script_f32_relaxed = new ScriptC_sqrt_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_sqrt_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_sqrt_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_sqrt_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_sqrt_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_sqrt_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_sqrt_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_sqrt_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_sqrt_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)(Math.sqrt((double)in[idx]));
-            }
-        }
-        return ref;
-    }
-
-    public void testSqrtF32() {
-        doF32(0xab3, 3);
-    }
-
-    public void testSqrtF32_relaxed() {
-        doF32_relaxed(0xab3, 3);
-    }
-
-    public void testSqrtF32_2() {
-        doF32_2(0xa1, 3);
-    }
-
-    public void testSqrtF32_2_relaxed() {
-        doF32_2_relaxed(0xa1, 3);
-    }
-
-    public void testSqrtF32_3() {
-        doF32_3(0xbae7, 3);
-    }
-
-    public void testSqrtF32_3_relaxed() {
-        doF32_3_relaxed(0xbae7, 3);
-    }
-
-    public void testSqrtF32_4() {
-        doF32_4(0xbac361, 3);
-
-    }
-    public void testSqrtF32_4_relaxed() {
-        doF32_4_relaxed(0xbac361, 3);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/StepTest.java b/tests/tests/renderscript/src/android/renderscript/cts/StepTest.java
deleted file mode 100644
index 39fb443..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/StepTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.Allocation;
-import android.renderscript.Element;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-public class StepTest extends RSBaseCompute {
-    private ScriptC_step_f32 script_f32;
-    private ScriptC_step_f32_relaxed script_f32_relaxed;
-    private Allocation mIn;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_step_f32(mRS);
-        script_f32_relaxed = new ScriptC_step_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_step_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_step_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_step_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_step_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_step_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_step_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_step_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_step_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx = i * stride * 2 + j;
-                ref[i * (stride - skip) + j] = in[idx+stride] < in[idx] ? 0.0f : 1.0f;
-            }
-        }
-        return ref;
-    }
-
-    @Override
-    protected Allocation setInAlloc(Element e) {
-        return mIn;
-    }
-
-    @Override
-    protected float[] makeInArray(int size) {
-        return new float[size*2];
-    }
-
-    public void testStepF32() {
-        ScriptField_step_input in = new ScriptField_step_input(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32(0x12678, 0);
-    }
-
-    public void testStepF32_relaxed() {
-        ScriptField_step_input in = new ScriptField_step_input(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_relaxed(0x12678, 0);
-    }
-
-    public void testStepF32_2() {
-        ScriptField_step_2_input in = new ScriptField_step_2_input(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_2(0x1ace8, 0);
-    }
-
-    public void testStepF32_2_relaxed() {
-        ScriptField_step_2_input in = new ScriptField_step_2_input(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_2_relaxed(0x1ace8, 0);
-    }
-
-    public void testStepF32_3() {
-        ScriptField_step_3_input in = new ScriptField_step_3_input(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_3(0xa2ce8, 0);
-    }
-
-    public void testStepF32_3_relaxed() {
-        ScriptField_step_3_input in = new ScriptField_step_3_input(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_3_relaxed(0xa2ce8, 0);
-    }
-
-    public void testStepF32_4() {
-        ScriptField_step_4_input in = new ScriptField_step_4_input(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_4(0x1ee8, 0);
-    }
-
-    public void testStepF32_4_relaxed() {
-        ScriptField_step_4_input in = new ScriptField_step_4_input(mRS, INPUTSIZE);
-        mIn = in.getAllocation();
-        doF32_4_relaxed(0x1ee8, 0);
-    }
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/StructArrayTest.java b/tests/tests/renderscript/src/android/renderscript/cts/StructArrayTest.java
index 6003ca9..91e65f8 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/StructArrayTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/StructArrayTest.java
@@ -15,7 +15,6 @@
  */
 
 package android.renderscript.cts;
-import com.android.cts.stub.R;
 
 public class StructArrayTest extends RSBaseCompute {
     /**
@@ -23,9 +22,7 @@
      */
     public void testStructArrays() {
         mRS.setErrorHandler(mRsError);
-        ScriptC_struct_array pad = new ScriptC_struct_array(mRS,
-                                                            mRes,
-                                                            R.raw.struct_array);
+        ScriptC_struct_array pad = new ScriptC_struct_array(mRS);
         ScriptField_ArrayMe S = new ScriptField_ArrayMe(mRS, 1);
         int[] values = {0, 1, 2, 3, 4};
         S.set_i(0, values, true);
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/StructPadTest.java b/tests/tests/renderscript/src/android/renderscript/cts/StructPadTest.java
index c56c086..ee3483a 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/StructPadTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/StructPadTest.java
@@ -17,7 +17,6 @@
 package android.renderscript.cts;
 
 import android.renderscript.Float4;
-import com.android.cts.stub.R;
 
 public class StructPadTest extends RSBaseCompute {
     /**
@@ -25,9 +24,7 @@
      */
     public void testStructPadding() {
         mRS.setErrorHandler(mRsError);
-        ScriptC_struct_pad pad = new ScriptC_struct_pad(mRS,
-                                                        mRes,
-                                                        R.raw.struct_pad);
+        ScriptC_struct_pad pad = new ScriptC_struct_pad(mRS);
         ScriptField_PadMe S = new ScriptField_PadMe(mRS, 1);
         Float4 F4 = new Float4(1.0f, 2.0f, 3.0f, 4.0f);
 
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TanTest.java b/tests/tests/renderscript/src/android/renderscript/cts/TanTest.java
deleted file mode 100644
index a4e62e9..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/TanTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-
-public class TanTest extends RSBaseCompute {
-    private ScriptC_tan_f32 script_f32;
-    private ScriptC_tan_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_tan_f32(mRS);
-        script_f32_relaxed = new ScriptC_tan_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_tan_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_tan_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_tan_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_tan_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_tan_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_tan_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_tan_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_tan_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)(Math.tan((double)in[idx]));
-            }
-        }
-        return ref;
-    }
-
-    public void testTanF32() {
-        doF32(0xabe, 5);
-    }
-
-    public void testTanF32_relaxed() {
-        doF32_relaxed(0xabe, 128);
-    }
-
-    public void testTanF32_2() {
-        doF32_2(0x29, 5);
-    }
-
-    public void testTanF32_2_relaxed() {
-        doF32_2_relaxed(0x29, 128);
-    }
-
-    public void testTanF32_3() {
-        doF32_3(0x9a, 5);
-    }
-
-    public void testTanF32_3_relaxed() {
-        doF32_3_relaxed(0x9a, 128);
-    }
-
-    public void testTanF32_4() {
-        doF32_4(0xac3, 5);
-
-    }
-    public void testTanF32_4_relaxed() {
-        doF32_4_relaxed(0xac3, 128);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TanhTest.java b/tests/tests/renderscript/src/android/renderscript/cts/TanhTest.java
deleted file mode 100644
index 4dc7d15..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/TanhTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-
-public class TanhTest extends RSBaseCompute {
-    private ScriptC_tanh_f32 script_f32;
-    private ScriptC_tanh_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_tanh_f32(mRS);
-        script_f32_relaxed = new ScriptC_tanh_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_tanh_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_tanh_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_tanh_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_tanh_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_tanh_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_tanh_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_tanh_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_tanh_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] in, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idx= i * stride + j;
-                int idxRef = i * (stride - skip) + j;
-                ref[idxRef] = (float)(Math.tanh((double)in[idx]));
-            }
-        }
-        return ref;
-    }
-
-    public void testTanhF32() {
-        doF32(0xab61, 5);
-    }
-
-    public void testTanhF32_relaxed() {
-        doF32_relaxed(0xab61, 128);
-    }
-
-    public void testTanhF32_2() {
-        doF32_2(0xa301, 5);
-    }
-
-    public void testTanhF32_2_relaxed() {
-        doF32_2_relaxed(0xa301, 128);
-    }
-
-    public void testTanhF32_3() {
-        doF32_3(0x918, 5);
-    }
-
-    public void testTanhF32_3_relaxed() {
-        doF32_3_relaxed(0x918, 128);
-    }
-
-    public void testTanhF32_4() {
-        doF32_4(0x81, 5);
-
-    }
-    public void testTanhF32_4_relaxed() {
-        doF32_4_relaxed(0x81, 128);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/Target.java b/tests/tests/renderscript/src/android/renderscript/cts/Target.java
new file mode 100644
index 0000000..c423792
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/Target.java
@@ -0,0 +1,532 @@
+/*
+ * 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 android.util.Log;
+import java.util.Arrays;
+import junit.framework.Assert;
+
+/**
+ * This class and the enclosed Floaty class are used to validate the precision of the floating
+ * point operations of the various drivers.  Instances of Target contains information about the
+ * expectations we have for the functions being tested.  There's an instance of Floaty for each
+ * floating value being verified.
+ */
+public class Target {
+    /**
+     * In relaxed precision mode, we allow:
+     * - less precision in the computation
+     * - using only normalized values
+     * - reordering of the operations
+     * - different rounding mode
+     */
+    private boolean mIsRelaxedPrecision;
+
+    /*
+     * The following two fields are set just before the expected values are computed for a specific
+     * RenderScript function.  Hence, we can't use one instance of this class to test two APIs
+     * in parallel.  The generated Test*.java code uses one instance of Target per test, so we're
+     * safe.
+     */
+
+    /**
+     * For native, we allow the same things as relaxed precision, plus:
+     * - operations don't have to return +/- infinity
+     */
+    private boolean mIsNative;
+
+    /**
+     * How much we'll allow the values tested to diverge from the values
+     * we compute.  This can be very large for native_* and half_* tests.
+     */
+    private int mUlpFactor;
+
+    Target(boolean relaxed) {
+        mIsRelaxedPrecision = relaxed;
+    }
+
+    /**
+     * Sets whether we are testing a native_* function and how many ulp we allow
+     * for full and relaxed precision.
+     */
+    void setPrecision(int fullUlpFactor, int relaxedUlpFactor, boolean isNative) {
+        mIsNative = isNative;
+        mUlpFactor = mIsRelaxedPrecision ? relaxedUlpFactor : fullUlpFactor;
+    }
+
+    /**
+     * Helper functions to create a new 32 bit Floaty with the current expected level of precision.
+     * We have variations that expect one to five arguments.  Any of the passed arguments are considered
+     * valid values for that Floaty.
+     */
+    Floaty new32(float a) {
+        return new Floaty(32, new double [] { a });
+    }
+
+    Floaty new32(float a, float b) {
+        return new Floaty(32, new double [] { a, b });
+    }
+
+    Floaty new32(float a, float b, float c) {
+        return new Floaty(32, new double [] { a, b, c });
+    }
+
+    Floaty new32(float a, float b, float c, float d) {
+        return new Floaty(32, new double [] { a, b, c, d });
+    }
+
+    Floaty new32(float a, float b, float c, float d, float e) {
+        return new Floaty(32, new double [] { a, b, c, d, e });
+    }
+
+    /**
+     * Helper functions to create a new 64 bit Floaty with the current expected level of precision.
+     * We have variations that expect one to five arguments.  Any of the passed arguments are considered
+     * valid values for that Floaty.
+     */
+    Floaty new64(double a) {
+        return new Floaty(64, new double [] { a });
+    }
+
+    Floaty new64(double a, double b) {
+        return new Floaty(64, new double [] { a, b });
+    }
+
+    Floaty new64(double a, double b, double c) {
+        return new Floaty(64, new double [] { a, b, c });
+    }
+
+    Floaty new64(double a, double b, double c, double d) {
+        return new Floaty(64, new double [] { a, b, c, d });
+    }
+
+    Floaty new64(double a, double b, double c, double d, double e) {
+        return new Floaty(64, new double [] { a, b, c, d, e });
+    }
+
+    /**
+     * Returns a Floaty that contain a NaN for the specified size.
+     */
+    Floaty newNan(int numberOfBits) {
+        return new Floaty(numberOfBits, new double [] { Double.NaN });
+    }
+
+    Floaty add(Floaty a, Floaty b) {
+        //Log.w("Target.add", "a: " + a.toString());
+        //Log.w("Target.add", "b: " + b.toString());
+        assert(a.mNumberOfBits == b.mNumberOfBits);
+        if (!a.mHasRange || !b.mHasRange) {
+            return newNan(a.mNumberOfBits);
+        }
+        return new Floaty(a.mNumberOfBits, new double[] { a.mValue + b.mValue,
+                                                          a.mMinValue + b.mMinValue,
+                                                          a.mMaxValue + b.mMaxValue });
+    }
+
+    Floaty subtract(Floaty a, Floaty b) {
+        //Log.w("Target.subtract", "a: " + a.toString());
+        //Log.w("Target.subtract", "b: " + b.toString());
+        assert(a.mNumberOfBits == b.mNumberOfBits);
+        if (!a.mHasRange || !b.mHasRange) {
+            return newNan(a.mNumberOfBits);
+        }
+        return new Floaty(a.mNumberOfBits, new double[] { a.mValue - b.mValue,
+                                                          a.mMinValue - b.mMaxValue,
+                                                          a.mMaxValue - b.mMinValue });
+    }
+
+    Floaty multiply(Floaty a, Floaty b) {
+        //Log.w("Target.multiply", "a: " + a.toString());
+        //Log.w("Target.multiply", "b: " + b.toString());
+        assert(a.mNumberOfBits == b.mNumberOfBits);
+        if (!a.mHasRange || !b.mHasRange) {
+            return newNan(a.mNumberOfBits);
+        }
+        return new Floaty(a.mNumberOfBits, new double[] { a.mValue * b.mValue,
+                                                          a.mMinValue * b.mMinValue,
+                                                          a.mMinValue * b.mMaxValue,
+                                                          a.mMaxValue * b.mMinValue,
+                                                          a.mMaxValue * b.mMaxValue});
+    }
+
+    Floaty divide(Floaty a, Floaty b) {
+        //Log.w("Target.divide", "a: " + a.toString());
+        //Log.w("Target.divide", "b: " + b.toString());
+        assert(a.mNumberOfBits == b.mNumberOfBits);
+        if (!a.mHasRange || !b.mHasRange) {
+            return newNan(a.mNumberOfBits);
+        }
+        return new Floaty(a.mNumberOfBits, new double[] { a.mValue / b.mValue,
+                                                          a.mMinValue / b.mMinValue,
+                                                          a.mMinValue / b.mMaxValue,
+                                                          a.mMaxValue / b.mMinValue,
+                                                          a.mMaxValue / b.mMaxValue});
+    }
+
+    /** Returns the absolute value of a Floaty. */
+    Floaty abs(Floaty a) {
+        if (!a.mHasRange) {
+            return newNan(a.mNumberOfBits);
+        }
+        if (a.mMinValue >= 0 && a.mMaxValue >= 0) {
+            // Two non-negatives, no change
+            return a;
+        }
+        Floaty f = new Floaty(a);
+        f.mValue = Math.abs(a.mValue);
+        if (a.mMinValue < 0 && a.mMaxValue < 0) {
+            // Two negatives, we invert
+            f.mMinValue = -a.mMaxValue;
+            f.mMaxValue = -a.mMinValue;
+        } else {
+            // We have one negative, one positive.
+            f.mMinValue = 0.f;
+            f.mMaxValue = Math.max(-a.mMinValue, a.mMaxValue);
+        }
+        return f;
+    }
+
+    /** Returns the square root of a Floaty. */
+    Floaty sqrt(Floaty a) {
+        //Log.w("Target.sqrt", "a: " + a.toString());
+        if (!a.mHasRange) {
+            return newNan(a.mNumberOfBits);
+        }
+        double f = Math.sqrt(a.mValue);
+        double min = Math.sqrt(a.mMinValue);
+        double max = Math.sqrt(a.mMaxValue);
+        double[] values;
+        /* If the range of inputs covers 0, make sure we have it as one of
+         * the answers, to set the correct lowest bound, as the square root
+         * of the negative inputs will yield a NaN flag and won't affect the
+         * range.
+         */
+        if (a.mMinValue < 0 && a.mMaxValue > 0) {
+            values = new double[]{f, 0., min, max};
+        } else {
+            values = new double[]{f, min, max};
+        }
+        Floaty answer = new Floaty(a.mNumberOfBits, values);
+        // Allow a little more imprecision for a square root operation.
+        answer.ExpandRangeByUlpFactor();
+        return answer;
+    }
+
+    /**
+     * This class represents the range of floating point values we accept as the result of a
+     * computation performed by a runtime driver.
+     */
+    class Floaty {
+        /**
+         * The number of bits the value should have, either 32 or 64.  It would have been nice to
+         * use generics, e.g. Floaty<double> and Floaty<double> but Java does not support generics
+         * of float and double.  Also, Java does not have an f16 type.  This can simulate it,
+         * although more work will be needed.
+         */
+        private int mNumberOfBits;
+        /** True if NaN is an acceptable value. */
+        private boolean mCanBeNan;
+        /**
+         * True if mValue, mMinValue, mMaxValue have been set.  This should be the case if mCanBeNan is false.
+         * It's possible for both mCanBeNan and mHasRange to be true at the same time.
+         */
+        private boolean mHasRange;
+        /**
+         * The typical value we would expect.  We don't just keep track of the min and max
+         * of the ranges of values allowed because some functions we are evaluating are
+         * discontinuous, e.g. sqrt around 0, lgamma around -1, -2, -3 and tan around pi/2.
+         * By keeping track of the middle value, we're more likely to handle this discontinuity
+         * correctly.
+         */
+        private double mValue;
+        /** The minimum value we would expect. */
+        private double mMinValue;
+        /** The maximum value we would expect. */
+        private double mMaxValue;
+
+        Floaty(Floaty a) {
+            mNumberOfBits = a.mNumberOfBits;
+            mCanBeNan = a.mCanBeNan;
+            mHasRange = a.mHasRange;
+            mValue = a.mValue;
+            mMinValue = a.mMinValue;
+            mMaxValue = a.mMaxValue;
+        }
+
+        /**
+         * Creates a Floaty and initializes it so that the values passed could be represented by it.
+         * We also expand what's allowed by +/- mUlpFactor to allow for the various rounding modes.
+         * values[0] is treated as the representative case, otherwise the order of values does not matter.
+         */
+        Floaty(int numberOfBits, double values[]) {
+            //Log.w("Floaty(double[], ulp)", "input: " + Arrays.toString(values) + ", ulp " + Integer.toString(mUlpFactor));
+            mNumberOfBits = numberOfBits;
+            mCanBeNan = false;
+            mHasRange = false;
+            mValue = values[0];
+            for (double f: values) {
+                if (f != f) {
+                    mCanBeNan = true;
+                    continue;
+                }
+                updateMinAndMax(f);
+                // For relaxed mode, we don't require support of subnormal values.
+                // If we have a subnormal value, we'll allow both the normalized value and zero,
+                // to cover the two ways this small value might be handled.
+                if (mIsRelaxedPrecision || mIsNative) {
+                    if (IsSubnormal(f)) {
+                        updateMinAndMax(0.f);
+                        updateMinAndMax(smallestNormal(f));
+                    }
+                }
+            }
+            // Expand the range by one ulp factor to cover for the different rounding modes.
+            ExpandRangeByUlpFactor();
+            //Log.w("Floaty(double[], ulp)", "output: " +  toString());
+        }
+
+        /** Modify the mMinValue and mMaxValue so that f is contained within the range. */
+        private void updateMinAndMax(double f) {
+            if (mHasRange) {
+                if (f < mMinValue) {
+                    mMinValue = f;
+                }
+                if (f > mMaxValue) {
+                    mMaxValue = f;
+                }
+            } else {
+                mHasRange = true;
+                mMinValue = f;
+                mMaxValue = f;
+            }
+        }
+
+        /** Modify mMinValue and mMaxValue to allow one extra ulp factor of error on each side. */
+        void ExpandRangeByUlpFactor() {
+            if (mHasRange && mUlpFactor > 0) {
+                // Expand the edges by the specified factor.
+                ExpandMin(mUlpFactor);
+                ExpandMax(mUlpFactor);
+            }
+        }
+
+        /** Expand the mMinValue by the number of ulp specified. */
+        private void ExpandMin(int ulpFactor) {
+            //Log.w("ExpandMin", java.lang.Double.toString(mMinValue) + " by " + Integer.toString(ulpFactor));
+            if (!mHasRange) {
+                return;
+            }
+            if (mMinValue == Double.NEGATIVE_INFINITY ||
+                mMinValue == Double.POSITIVE_INFINITY) {
+                // Can't get any larger
+                //Log.w("ExpandMin", "infinity");
+                return;
+            }
+            double ulp = NegativeUlp();
+            double delta = ulp * ulpFactor;
+            double newValue = mMinValue + delta;
+            /*
+             * Reduce mMinValue but don't go negative if it's positive because the rounding error
+             * we're simulating won't change the sign.
+             */
+            if (newValue < 0 && mMinValue > 0.f) {
+                mMinValue = 0.f;
+            } else {
+                mMinValue = newValue;
+            }
+            // If subnormal, also allow the normalized value if it's smaller.
+            if ((mIsRelaxedPrecision || mIsNative) && IsSubnormal(mMinValue)) {
+                if (mMinValue < 0) {
+                    mMinValue = smallestNormal(-1.0f);
+                } else {
+                    mMinValue = 0.f;
+                }
+            }
+            //Log.w("ExpandMin", "ulp " + java.lang.Double.toString(ulp) + ", delta " + java.lang.Double.toString(delta) + " for " + java.lang.Double.toString(mMinValue));
+        }
+
+        /** Expand the mMaxValue by the number of ulp specified. */
+        private void ExpandMax(int ulpFactor) {
+            //Log.w("ExpandMax", java.lang.Double.toString(mMaxValue) + " by " + Integer.toString(ulpFactor));
+            if (!mHasRange) {
+                return;
+            }
+            if (mMaxValue == Double.NEGATIVE_INFINITY ||
+                mMaxValue == Double.POSITIVE_INFINITY) {
+                // Can't get any larger
+                //Log.w("ExpandMax", "infinity");
+                return;
+            }
+            double ulp = Ulp();
+            double delta = ulp * ulpFactor;
+            double newValue = mMaxValue + delta;
+            /*
+             * Increase mMaxValue but don't go positive if it's negative because the rounding error
+             * we're simulating won't change the sign.
+             */
+            if (newValue > 0 && mMaxValue < 0.f) {
+                mMaxValue = 0.f;
+            } else {
+                mMaxValue = newValue;
+            }
+            // If subnormal, also allow the normalized value if it's smaller.
+            if ((mIsRelaxedPrecision || mIsNative) && IsSubnormal(mMaxValue)) {
+                if (mMaxValue > 0) {
+                    mMaxValue = smallestNormal(1.0f);
+                } else {
+                    mMaxValue = 0.f;
+                }
+            }
+            //Log.w("ExpandMax", "ulp " + java.lang.Double.toString(ulp) + ", delta " + java.lang.Double.toString(delta) + " for " + java.lang.Double.toString(mMaxValue));
+        }
+
+        /**
+         * Returns true if f is smaller than the smallest normalized number that can be represented
+         * by the number of bits we have.
+         */
+        private boolean IsSubnormal(double f) {
+            double af = Math.abs(f);
+            return 0 < af && af < smallestNormal(1.0f);
+        }
+
+        /**
+         * Returns the smallest normal representable by the number of bits we have, of the same
+         * sign as f.
+         */
+        private double smallestNormal(double f) {
+            double answer = (mNumberOfBits == 32) ? Float.MIN_NORMAL : Double.MIN_NORMAL;
+            if (f < 0) {
+                answer = -answer;
+            }
+            return answer;
+        }
+
+        /** Returns the unit of least precision for the maximum value allowed. */
+        private double Ulp() {
+            double u;
+            if (mNumberOfBits == 32) {
+                u = Math.ulp((float)mMaxValue);
+            } else {
+                u = Math.ulp(mMaxValue);
+            }
+            if (mIsRelaxedPrecision || mIsNative) {
+                u = Math.max(u, smallestNormal(1.f));
+            }
+            return u;
+        }
+
+        /** Returns the negative of the unit of least precision for the minimum value allowed. */
+        private double NegativeUlp() {
+            double u;
+            if (mNumberOfBits == 32) {
+                u = -Math.ulp((float)mMinValue);
+            } else {
+                u = -Math.ulp(mMinValue);
+            }
+            if (mIsRelaxedPrecision || mIsNative) {
+                u = Math.min(u, smallestNormal(-1.f));
+            }
+            return u;
+        }
+
+        /** Returns true if the number passed is among the values that are represented by this Floaty. */
+        public boolean couldBe(double a) {
+            return couldBe(a, 0.0);
+        }
+
+        /**
+         * Returns true if the number passed is among the values that are represented by this Floaty.
+         * An extra amount of allowed error can be specified.
+         */
+        public boolean couldBe(double a, double extraAllowedError) {
+            //Log.w("Floaty.couldBe", "Can " + Double.toString(a) + " be " + toString() + "? ");
+            // Handle the input being a NaN.
+            if (a != a) {
+                //Log.w("couldBe", "true because is Naan");
+                return mCanBeNan;
+            }
+            // If the input is not a NaN, we better have a range.
+            if (!mHasRange) {
+                return false;
+            }
+            // Handle the simple case.
+            if ((mMinValue - extraAllowedError) <= a && a <= (mMaxValue + extraAllowedError)) {
+                return true;
+            }
+            // For native, we don't require returning +/- infinity.  If that's what we expect,
+            // allow all answers.
+            if (mIsNative) {
+                if (mMinValue == Double.NEGATIVE_INFINITY &&
+                    mMaxValue == Double.NEGATIVE_INFINITY) {
+                    return true;
+                }
+                if (mMinValue == Double.POSITIVE_INFINITY &&
+                    mMaxValue == Double.POSITIVE_INFINITY) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+
+        public double get64() { return mValue; }
+        public double min64() { return mMinValue; }
+        public double max64() { return mMaxValue; }
+        /**
+         * Returns mValue unless zero could be a legal value.  In that case, return it.
+         * This is useful for testing functions where the behavior at zero is unusual,
+         * e.g. reciprocals.  If mValue is already +0.0 or -0.0, don't change it, to
+         * preserve the sign.
+         */
+        public double mid64() {
+            if (mMinValue < 0.0 && mMaxValue > 0.0 && mValue != 0.0) {
+                return 0.0;
+            }
+            return mValue;
+        }
+
+        public float get32() { return (float) mValue; }
+        public float min32() { return (float) mMinValue; }
+        public float max32() { return (float) mMaxValue; }
+        public float mid32() { return (float) mid64(); }
+
+        public String toString() {
+            String s = String.format("[f%d: ", mNumberOfBits);
+            if (mCanBeNan) {
+                s += "NaN, ";
+            }
+            if (mHasRange) {
+                if (mNumberOfBits == 32) {
+                    float min = (float)mMinValue;
+                    float mid = (float)mValue;
+                    float max = (float)mMaxValue;
+                    s += String.format("%11.9g {%08x} to %11.9g {%08x} to %11.9g {%08x}", min,
+                                       Float.floatToRawIntBits(min), mid,
+                                       Float.floatToRawIntBits(mid), max,
+                                       Float.floatToRawIntBits(max));
+                } else {
+                    s += String.format("%24.9g {%16x} to %24.9g {%16x} to %24.9g {%16x}", mMinValue,
+                                       Double.doubleToRawLongBits(mMinValue), mValue,
+                                       Double.doubleToRawLongBits(mValue), mMaxValue,
+                                       Double.doubleToRawLongBits(mMaxValue));
+                }
+            }
+            s += "]";
+            return s;
+        }
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAbs.java b/tests/tests/renderscript/src/android/renderscript/cts/TestAbs.java
new file mode 100644
index 0000000..6b3914c
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAbs.java
@@ -0,0 +1,738 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestAbs extends RSBaseCompute {
+
+    private ScriptC_TestAbs script;
+    private ScriptC_TestAbsRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestAbs(mRS);
+        scriptRelaxed = new ScriptC_TestAbsRelaxed(mRS);
+    }
+
+    public class ArgumentsCharUchar {
+        public byte inValue;
+        public byte out;
+    }
+
+    private void checkAbsCharUchar() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 1, 0x4c0d03eb0d0c5a91l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 1), INPUTSIZE);
+            script.forEach_testAbsCharUchar(inValue, out);
+            verifyResultsAbsCharUchar(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAbsCharUchar: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testAbsCharUchar(inValue, out);
+            verifyResultsAbsCharUchar(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAbsCharUchar: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAbsCharUchar(Allocation inValue, Allocation out, boolean relaxed) {
+        byte[] arrayInValue = new byte[INPUTSIZE * 1];
+        inValue.copyTo(arrayInValue);
+        byte[] arrayOut = new byte[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharUchar args = new ArgumentsCharUchar();
+                args.inValue = arrayInValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeAbs(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAbsCharUchar" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAbsChar2Uchar2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 2, 0x901d551e7f67bb87l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            script.forEach_testAbsChar2Uchar2(inValue, out);
+            verifyResultsAbsChar2Uchar2(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAbsChar2Uchar2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testAbsChar2Uchar2(inValue, out);
+            verifyResultsAbsChar2Uchar2(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAbsChar2Uchar2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAbsChar2Uchar2(Allocation inValue, Allocation out, boolean relaxed) {
+        byte[] arrayInValue = new byte[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharUchar args = new ArgumentsCharUchar();
+                args.inValue = arrayInValue[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeAbs(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAbsChar2Uchar2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAbsChar3Uchar3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 3, 0xb5d1caa5c8a5e105l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            script.forEach_testAbsChar3Uchar3(inValue, out);
+            verifyResultsAbsChar3Uchar3(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAbsChar3Uchar3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testAbsChar3Uchar3(inValue, out);
+            verifyResultsAbsChar3Uchar3(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAbsChar3Uchar3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAbsChar3Uchar3(Allocation inValue, Allocation out, boolean relaxed) {
+        byte[] arrayInValue = new byte[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharUchar args = new ArgumentsCharUchar();
+                args.inValue = arrayInValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeAbs(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAbsChar3Uchar3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAbsChar4Uchar4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 4, 0xdb86402d11e40683l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            script.forEach_testAbsChar4Uchar4(inValue, out);
+            verifyResultsAbsChar4Uchar4(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAbsChar4Uchar4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testAbsChar4Uchar4(inValue, out);
+            verifyResultsAbsChar4Uchar4(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAbsChar4Uchar4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAbsChar4Uchar4(Allocation inValue, Allocation out, boolean relaxed) {
+        byte[] arrayInValue = new byte[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharUchar args = new ArgumentsCharUchar();
+                args.inValue = arrayInValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeAbs(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAbsChar4Uchar4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsShortUshort {
+        public short inValue;
+        public short out;
+    }
+
+    private void checkAbsShortUshort() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 1, 0xaead1a96b6ea02a7l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 1), INPUTSIZE);
+            script.forEach_testAbsShortUshort(inValue, out);
+            verifyResultsAbsShortUshort(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAbsShortUshort: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testAbsShortUshort(inValue, out);
+            verifyResultsAbsShortUshort(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAbsShortUshort: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAbsShortUshort(Allocation inValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 1];
+        inValue.copyTo(arrayInValue);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortUshort args = new ArgumentsShortUshort();
+                args.inValue = arrayInValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeAbs(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAbsShortUshort" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAbsShort2Ushort2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 2, 0x41a1894ff6b0da9l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            script.forEach_testAbsShort2Ushort2(inValue, out);
+            verifyResultsAbsShort2Ushort2(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAbsShort2Ushort2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testAbsShort2Ushort2(inValue, out);
+            verifyResultsAbsShort2Ushort2(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAbsShort2Ushort2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAbsShort2Ushort2(Allocation inValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortUshort args = new ArgumentsShortUshort();
+                args.inValue = arrayInValue[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeAbs(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAbsShort2Ushort2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAbsShort3Ushort3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 3, 0x5969cbec377ba515l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            script.forEach_testAbsShort3Ushort3(inValue, out);
+            verifyResultsAbsShort3Ushort3(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAbsShort3Ushort3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testAbsShort3Ushort3(inValue, out);
+            verifyResultsAbsShort3Ushort3(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAbsShort3Ushort3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAbsShort3Ushort3(Allocation inValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortUshort args = new ArgumentsShortUshort();
+                args.inValue = arrayInValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeAbs(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAbsShort3Ushort3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAbsShort4Ushort4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 4, 0xaeb97f436f8c3c81l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            script.forEach_testAbsShort4Ushort4(inValue, out);
+            verifyResultsAbsShort4Ushort4(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAbsShort4Ushort4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testAbsShort4Ushort4(inValue, out);
+            verifyResultsAbsShort4Ushort4(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAbsShort4Ushort4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAbsShort4Ushort4(Allocation inValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortUshort args = new ArgumentsShortUshort();
+                args.inValue = arrayInValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeAbs(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAbsShort4Ushort4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsIntUint {
+        public int inValue;
+        public int out;
+    }
+
+    private void checkAbsIntUint() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 1, 0xcda40fd4fa1abbd1l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 1), INPUTSIZE);
+            script.forEach_testAbsIntUint(inValue, out);
+            verifyResultsAbsIntUint(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAbsIntUint: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testAbsIntUint(inValue, out);
+            verifyResultsAbsIntUint(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAbsIntUint: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAbsIntUint(Allocation inValue, Allocation out, boolean relaxed) {
+        int[] arrayInValue = new int[INPUTSIZE * 1];
+        inValue.copyTo(arrayInValue);
+        int[] arrayOut = new int[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntUint args = new ArgumentsIntUint();
+                args.inValue = arrayInValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeAbs(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAbsIntUint" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAbsInt2Uint2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 2, 0x71326739aabbb4a5l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            script.forEach_testAbsInt2Uint2(inValue, out);
+            verifyResultsAbsInt2Uint2(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAbsInt2Uint2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testAbsInt2Uint2(inValue, out);
+            verifyResultsAbsInt2Uint2(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAbsInt2Uint2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAbsInt2Uint2(Allocation inValue, Allocation out, boolean relaxed) {
+        int[] arrayInValue = new int[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntUint args = new ArgumentsIntUint();
+                args.inValue = arrayInValue[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeAbs(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAbsInt2Uint2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAbsInt3Uint3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 3, 0x9bbf87f7a6fae959l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            script.forEach_testAbsInt3Uint3(inValue, out);
+            verifyResultsAbsInt3Uint3(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAbsInt3Uint3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testAbsInt3Uint3(inValue, out);
+            verifyResultsAbsInt3Uint3(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAbsInt3Uint3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAbsInt3Uint3(Allocation inValue, Allocation out, boolean relaxed) {
+        int[] arrayInValue = new int[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntUint args = new ArgumentsIntUint();
+                args.inValue = arrayInValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeAbs(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAbsInt3Uint3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAbsInt4Uint4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 4, 0xc64ca8b5a33a1e0dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            script.forEach_testAbsInt4Uint4(inValue, out);
+            verifyResultsAbsInt4Uint4(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAbsInt4Uint4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testAbsInt4Uint4(inValue, out);
+            verifyResultsAbsInt4Uint4(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAbsInt4Uint4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAbsInt4Uint4(Allocation inValue, Allocation out, boolean relaxed) {
+        int[] arrayInValue = new int[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntUint args = new ArgumentsIntUint();
+                args.inValue = arrayInValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeAbs(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAbsInt4Uint4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testAbs() {
+        checkAbsCharUchar();
+        checkAbsChar2Uchar2();
+        checkAbsChar3Uchar3();
+        checkAbsChar4Uchar4();
+        checkAbsShortUshort();
+        checkAbsShort2Ushort2();
+        checkAbsShort3Ushort3();
+        checkAbsShort4Ushort4();
+        checkAbsIntUint();
+        checkAbsInt2Uint2();
+        checkAbsInt3Uint3();
+        checkAbsInt4Uint4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAbs.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestAbs.rs
new file mode 100644
index 0000000..8f1747e
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAbs.rs
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+uchar __attribute__((kernel)) testAbsCharUchar(char inValue) {
+    return abs(inValue);
+}
+
+uchar2 __attribute__((kernel)) testAbsChar2Uchar2(char2 inValue) {
+    return abs(inValue);
+}
+
+uchar3 __attribute__((kernel)) testAbsChar3Uchar3(char3 inValue) {
+    return abs(inValue);
+}
+
+uchar4 __attribute__((kernel)) testAbsChar4Uchar4(char4 inValue) {
+    return abs(inValue);
+}
+
+ushort __attribute__((kernel)) testAbsShortUshort(short inValue) {
+    return abs(inValue);
+}
+
+ushort2 __attribute__((kernel)) testAbsShort2Ushort2(short2 inValue) {
+    return abs(inValue);
+}
+
+ushort3 __attribute__((kernel)) testAbsShort3Ushort3(short3 inValue) {
+    return abs(inValue);
+}
+
+ushort4 __attribute__((kernel)) testAbsShort4Ushort4(short4 inValue) {
+    return abs(inValue);
+}
+
+uint __attribute__((kernel)) testAbsIntUint(int inValue) {
+    return abs(inValue);
+}
+
+uint2 __attribute__((kernel)) testAbsInt2Uint2(int2 inValue) {
+    return abs(inValue);
+}
+
+uint3 __attribute__((kernel)) testAbsInt3Uint3(int3 inValue) {
+    return abs(inValue);
+}
+
+uint4 __attribute__((kernel)) testAbsInt4Uint4(int4 inValue) {
+    return abs(inValue);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAbsRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestAbsRelaxed.rs
new file mode 100644
index 0000000..437a467
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAbsRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestAbs.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAcos.java b/tests/tests/renderscript/src/android/renderscript/cts/TestAcos.java
new file mode 100644
index 0000000..999fd1b
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAcos.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestAcos extends RSBaseCompute {
+
+    private ScriptC_TestAcos script;
+    private ScriptC_TestAcosRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestAcos(mRS);
+        scriptRelaxed = new ScriptC_TestAcosRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkAcosFloatFloat() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xf6e893f6d1cc3bdfl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testAcosFloatFloat(inV, out);
+            verifyResultsAcosFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcosFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testAcosFloatFloat(inV, out);
+            verifyResultsAcosFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcosFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAcosFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAcos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAcosFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAcosFloat2Float2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x55af66f81096ae8bl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testAcosFloat2Float2(inV, out);
+            verifyResultsAcosFloat2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcosFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testAcosFloat2Float2(inV, out);
+            verifyResultsAcosFloat2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcosFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAcosFloat2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAcos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAcosFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAcosFloat3Float3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x55b1301306b1cf69l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testAcosFloat3Float3(inV, out);
+            verifyResultsAcosFloat3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcosFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testAcosFloat3Float3(inV, out);
+            verifyResultsAcosFloat3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcosFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAcosFloat3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAcos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAcosFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAcosFloat4Float4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x55b2f92dfcccf047l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testAcosFloat4Float4(inV, out);
+            verifyResultsAcosFloat4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcosFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testAcosFloat4Float4(inV, out);
+            verifyResultsAcosFloat4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcosFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAcosFloat4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAcos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAcosFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testAcos() {
+        checkAcosFloatFloat();
+        checkAcosFloat2Float2();
+        checkAcosFloat3Float3();
+        checkAcosFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAcos.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestAcos.rs
new file mode 100644
index 0000000..ccf273e
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAcos.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testAcosFloatFloat(float inV) {
+    return acos(inV);
+}
+
+float2 __attribute__((kernel)) testAcosFloat2Float2(float2 inV) {
+    return acos(inV);
+}
+
+float3 __attribute__((kernel)) testAcosFloat3Float3(float3 inV) {
+    return acos(inV);
+}
+
+float4 __attribute__((kernel)) testAcosFloat4Float4(float4 inV) {
+    return acos(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAcosRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestAcosRelaxed.rs
new file mode 100644
index 0000000..92fd9e87
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAcosRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestAcos.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAcosh.java b/tests/tests/renderscript/src/android/renderscript/cts/TestAcosh.java
new file mode 100644
index 0000000..1412c2e
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAcosh.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestAcosh extends RSBaseCompute {
+
+    private ScriptC_TestAcosh script;
+    private ScriptC_TestAcoshRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestAcosh(mRS);
+        scriptRelaxed = new ScriptC_TestAcoshRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkAcoshFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xb2c74105f8e94ea7l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testAcoshFloatFloat(in, out);
+            verifyResultsAcoshFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcoshFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testAcoshFloatFloat(in, out);
+            verifyResultsAcoshFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcoshFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAcoshFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAcosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAcoshFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAcoshFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x4123c61e7e518f4bl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testAcoshFloat2Float2(in, out);
+            verifyResultsAcoshFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcoshFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testAcoshFloat2Float2(in, out);
+            verifyResultsAcoshFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcoshFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAcoshFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAcosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAcoshFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAcoshFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x4123d0bfdd5824e5l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testAcoshFloat3Float3(in, out);
+            verifyResultsAcoshFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcoshFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testAcoshFloat3Float3(in, out);
+            verifyResultsAcoshFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcoshFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAcoshFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAcosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAcoshFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAcoshFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x4123db613c5eba7fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testAcoshFloat4Float4(in, out);
+            verifyResultsAcoshFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcoshFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testAcoshFloat4Float4(in, out);
+            verifyResultsAcoshFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcoshFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAcoshFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAcosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAcoshFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testAcosh() {
+        checkAcoshFloatFloat();
+        checkAcoshFloat2Float2();
+        checkAcoshFloat3Float3();
+        checkAcoshFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAcosh.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestAcosh.rs
new file mode 100644
index 0000000..9be2fa2
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAcosh.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testAcoshFloatFloat(float in) {
+    return acosh(in);
+}
+
+float2 __attribute__((kernel)) testAcoshFloat2Float2(float2 in) {
+    return acosh(in);
+}
+
+float3 __attribute__((kernel)) testAcoshFloat3Float3(float3 in) {
+    return acosh(in);
+}
+
+float4 __attribute__((kernel)) testAcoshFloat4Float4(float4 in) {
+    return acosh(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAcoshRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestAcoshRelaxed.rs
new file mode 100644
index 0000000..269cec5
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAcoshRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestAcosh.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAcospi.java b/tests/tests/renderscript/src/android/renderscript/cts/TestAcospi.java
new file mode 100644
index 0000000..7669fea
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAcospi.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestAcospi extends RSBaseCompute {
+
+    private ScriptC_TestAcospi script;
+    private ScriptC_TestAcospiRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestAcospi(mRS);
+        scriptRelaxed = new ScriptC_TestAcospiRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkAcospiFloatFloat() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x9fbdc3b5d1e084b2l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testAcospiFloatFloat(inV, out);
+            verifyResultsAcospiFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcospiFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testAcospiFloatFloat(inV, out);
+            verifyResultsAcospiFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcospiFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAcospiFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAcospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAcospiFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAcospiFloat2Float2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xc175417fa318aa86l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testAcospiFloat2Float2(inV, out);
+            verifyResultsAcospiFloat2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcospiFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testAcospiFloat2Float2(inV, out);
+            verifyResultsAcospiFloat2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcospiFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAcospiFloat2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAcospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAcospiFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAcospiFloat3Float3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xc1770a9a9933cb64l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testAcospiFloat3Float3(inV, out);
+            verifyResultsAcospiFloat3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcospiFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testAcospiFloat3Float3(inV, out);
+            verifyResultsAcospiFloat3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcospiFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAcospiFloat3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAcospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAcospiFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAcospiFloat4Float4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xc178d3b58f4eec42l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testAcospiFloat4Float4(inV, out);
+            verifyResultsAcospiFloat4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcospiFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testAcospiFloat4Float4(inV, out);
+            verifyResultsAcospiFloat4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcospiFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAcospiFloat4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAcospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAcospiFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testAcospi() {
+        checkAcospiFloatFloat();
+        checkAcospiFloat2Float2();
+        checkAcospiFloat3Float3();
+        checkAcospiFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAcospi.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestAcospi.rs
new file mode 100644
index 0000000..b29cff7
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAcospi.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testAcospiFloatFloat(float inV) {
+    return acospi(inV);
+}
+
+float2 __attribute__((kernel)) testAcospiFloat2Float2(float2 inV) {
+    return acospi(inV);
+}
+
+float3 __attribute__((kernel)) testAcospiFloat3Float3(float3 inV) {
+    return acospi(inV);
+}
+
+float4 __attribute__((kernel)) testAcospiFloat4Float4(float4 inV) {
+    return acospi(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAcospiRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestAcospiRelaxed.rs
new file mode 100644
index 0000000..203fe7e
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAcospiRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestAcospi.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAsin.java b/tests/tests/renderscript/src/android/renderscript/cts/TestAsin.java
new file mode 100644
index 0000000..ce728e7
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAsin.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestAsin extends RSBaseCompute {
+
+    private ScriptC_TestAsin script;
+    private ScriptC_TestAsinRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestAsin(mRS);
+        scriptRelaxed = new ScriptC_TestAsinRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkAsinFloatFloat() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x80b5674ff98b5a12l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testAsinFloatFloat(inV, out);
+            verifyResultsAsinFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testAsinFloatFloat(inV, out);
+            verifyResultsAsinFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAsinFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAsin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAsinFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAsinFloat2Float2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x9e11e5e823f7cce6l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testAsinFloat2Float2(inV, out);
+            verifyResultsAsinFloat2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testAsinFloat2Float2(inV, out);
+            verifyResultsAsinFloat2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAsinFloat2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAsin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAsinFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAsinFloat3Float3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x9e13af031a12edc4l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testAsinFloat3Float3(inV, out);
+            verifyResultsAsinFloat3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testAsinFloat3Float3(inV, out);
+            verifyResultsAsinFloat3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAsinFloat3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAsin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAsinFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAsinFloat4Float4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x9e15781e102e0ea2l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testAsinFloat4Float4(inV, out);
+            verifyResultsAsinFloat4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testAsinFloat4Float4(inV, out);
+            verifyResultsAsinFloat4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAsinFloat4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAsin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAsinFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testAsin() {
+        checkAsinFloatFloat();
+        checkAsinFloat2Float2();
+        checkAsinFloat3Float3();
+        checkAsinFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAsin.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestAsin.rs
new file mode 100644
index 0000000..43e6940
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAsin.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testAsinFloatFloat(float inV) {
+    return asin(inV);
+}
+
+float2 __attribute__((kernel)) testAsinFloat2Float2(float2 inV) {
+    return asin(inV);
+}
+
+float3 __attribute__((kernel)) testAsinFloat3Float3(float3 inV) {
+    return asin(inV);
+}
+
+float4 __attribute__((kernel)) testAsinFloat4Float4(float4 inV) {
+    return asin(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAsinRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestAsinRelaxed.rs
new file mode 100644
index 0000000..f972148
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAsinRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestAsin.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAsinh.java b/tests/tests/renderscript/src/android/renderscript/cts/TestAsinh.java
new file mode 100644
index 0000000..90c26a0
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAsinh.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestAsinh extends RSBaseCompute {
+
+    private ScriptC_TestAsinh script;
+    private ScriptC_TestAsinhRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestAsinh(mRS);
+        scriptRelaxed = new ScriptC_TestAsinhRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkAsinhFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x3c94145f20a86cdal, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testAsinhFloatFloat(in, out);
+            verifyResultsAsinhFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinhFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testAsinhFloatFloat(in, out);
+            verifyResultsAsinhFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinhFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAsinhFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAsinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAsinhFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAsinhFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x8986450e91b2ada6l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testAsinhFloat2Float2(in, out);
+            verifyResultsAsinhFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinhFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testAsinhFloat2Float2(in, out);
+            verifyResultsAsinhFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinhFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAsinhFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAsinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAsinhFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAsinhFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x89864faff0b94340l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testAsinhFloat3Float3(in, out);
+            verifyResultsAsinhFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinhFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testAsinhFloat3Float3(in, out);
+            verifyResultsAsinhFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinhFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAsinhFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAsinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAsinhFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAsinhFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x89865a514fbfd8dal, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testAsinhFloat4Float4(in, out);
+            verifyResultsAsinhFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinhFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testAsinhFloat4Float4(in, out);
+            verifyResultsAsinhFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinhFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAsinhFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAsinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAsinhFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testAsinh() {
+        checkAsinhFloatFloat();
+        checkAsinhFloat2Float2();
+        checkAsinhFloat3Float3();
+        checkAsinhFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAsinh.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestAsinh.rs
new file mode 100644
index 0000000..a72a5f4
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAsinh.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testAsinhFloatFloat(float in) {
+    return asinh(in);
+}
+
+float2 __attribute__((kernel)) testAsinhFloat2Float2(float2 in) {
+    return asinh(in);
+}
+
+float3 __attribute__((kernel)) testAsinhFloat3Float3(float3 in) {
+    return asinh(in);
+}
+
+float4 __attribute__((kernel)) testAsinhFloat4Float4(float4 in) {
+    return asinh(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAsinhRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestAsinhRelaxed.rs
new file mode 100644
index 0000000..7540ea8
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAsinhRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestAsinh.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAsinpi.java b/tests/tests/renderscript/src/android/renderscript/cts/TestAsinpi.java
new file mode 100644
index 0000000..50bc387
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAsinpi.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestAsinpi extends RSBaseCompute {
+
+    private ScriptC_TestAsinpi script;
+    private ScriptC_TestAsinpiRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestAsinpi(mRS);
+        scriptRelaxed = new ScriptC_TestAsinpiRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkAsinpiFloatFloat() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xe82042a5e541a30dl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testAsinpiFloatFloat(inV, out);
+            verifyResultsAsinpiFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinpiFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testAsinpiFloatFloat(inV, out);
+            verifyResultsAsinpiFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinpiFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAsinpiFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAsinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAsinpiFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAsinpiFloat2Float2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x90dc157b9b8ce9c9l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testAsinpiFloat2Float2(inV, out);
+            verifyResultsAsinpiFloat2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinpiFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testAsinpiFloat2Float2(inV, out);
+            verifyResultsAsinpiFloat2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinpiFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAsinpiFloat2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAsinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAsinpiFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAsinpiFloat3Float3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x90ddde9691a80aa7l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testAsinpiFloat3Float3(inV, out);
+            verifyResultsAsinpiFloat3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinpiFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testAsinpiFloat3Float3(inV, out);
+            verifyResultsAsinpiFloat3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinpiFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAsinpiFloat3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAsinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAsinpiFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAsinpiFloat4Float4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x90dfa7b187c32b85l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testAsinpiFloat4Float4(inV, out);
+            verifyResultsAsinpiFloat4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinpiFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testAsinpiFloat4Float4(inV, out);
+            verifyResultsAsinpiFloat4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinpiFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAsinpiFloat4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAsinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAsinpiFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testAsinpi() {
+        checkAsinpiFloatFloat();
+        checkAsinpiFloat2Float2();
+        checkAsinpiFloat3Float3();
+        checkAsinpiFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAsinpi.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestAsinpi.rs
new file mode 100644
index 0000000..112f722
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAsinpi.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testAsinpiFloatFloat(float inV) {
+    return asinpi(inV);
+}
+
+float2 __attribute__((kernel)) testAsinpiFloat2Float2(float2 inV) {
+    return asinpi(inV);
+}
+
+float3 __attribute__((kernel)) testAsinpiFloat3Float3(float3 inV) {
+    return asinpi(inV);
+}
+
+float4 __attribute__((kernel)) testAsinpiFloat4Float4(float4 inV) {
+    return asinpi(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAsinpiRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestAsinpiRelaxed.rs
new file mode 100644
index 0000000..aad672b
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAsinpiRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestAsinpi.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAtan.java b/tests/tests/renderscript/src/android/renderscript/cts/TestAtan.java
new file mode 100644
index 0000000..1d7055c
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAtan.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestAtan extends RSBaseCompute {
+
+    private ScriptC_TestAtan script;
+    private ScriptC_TestAtanRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestAtan(mRS);
+        scriptRelaxed = new ScriptC_TestAtanRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkAtanFloatFloat() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x2a9ae39592004c8dl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testAtanFloatFloat(inV, out);
+            verifyResultsAtanFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testAtanFloatFloat(inV, out);
+            verifyResultsAtanFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtanFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAtan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAtanFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAtanFloat2Float2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xb890789248a32749l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testAtanFloat2Float2(inV, out);
+            verifyResultsAtanFloat2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testAtanFloat2Float2(inV, out);
+            verifyResultsAtanFloat2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtanFloat2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAtan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAtanFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAtanFloat3Float3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xb89241ad3ebe4827l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testAtanFloat3Float3(inV, out);
+            verifyResultsAtanFloat3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testAtanFloat3Float3(inV, out);
+            verifyResultsAtanFloat3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtanFloat3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAtan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAtanFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAtanFloat4Float4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xb8940ac834d96905l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testAtanFloat4Float4(inV, out);
+            verifyResultsAtanFloat4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testAtanFloat4Float4(inV, out);
+            verifyResultsAtanFloat4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtanFloat4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAtan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAtanFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testAtan() {
+        checkAtanFloatFloat();
+        checkAtanFloat2Float2();
+        checkAtanFloat3Float3();
+        checkAtanFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAtan.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestAtan.rs
new file mode 100644
index 0000000..36d3814
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAtan.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testAtanFloatFloat(float inV) {
+    return atan(inV);
+}
+
+float2 __attribute__((kernel)) testAtanFloat2Float2(float2 inV) {
+    return atan(inV);
+}
+
+float3 __attribute__((kernel)) testAtanFloat3Float3(float3 inV) {
+    return atan(inV);
+}
+
+float4 __attribute__((kernel)) testAtanFloat4Float4(float4 inV) {
+    return atan(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAtan2.java b/tests/tests/renderscript/src/android/renderscript/cts/TestAtan2.java
new file mode 100644
index 0000000..10b862d
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAtan2.java
@@ -0,0 +1,325 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestAtan2 extends RSBaseCompute {
+
+    private ScriptC_TestAtan2 script;
+    private ScriptC_TestAtan2Relaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestAtan2(mRS);
+        scriptRelaxed = new ScriptC_TestAtan2Relaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float inY;
+        public float inX;
+        public Target.Floaty out;
+    }
+
+    private void checkAtan2FloatFloatFloat() {
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x8f58f1f953c03c32l, false);
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x8f58f1f953c03c31l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInX(inX);
+            script.forEach_testAtan2FloatFloatFloat(inY, out);
+            verifyResultsAtan2FloatFloatFloat(inY, inX, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2FloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInX(inX);
+            scriptRelaxed.forEach_testAtan2FloatFloatFloat(inY, out);
+            verifyResultsAtan2FloatFloatFloat(inY, inX, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2FloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtan2FloatFloatFloat(Allocation inY, Allocation inX, Allocation out, boolean relaxed) {
+        float[] arrayInY = new float[INPUTSIZE * 1];
+        inY.copyTo(arrayInY);
+        float[] arrayInX = new float[INPUTSIZE * 1];
+        inX.copyTo(arrayInX);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inY = arrayInY[i];
+                args.inX = arrayInX[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAtan2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAtan2FloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAtan2Float2Float2Float2() {
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xbe78dcdcd414b6c0l, false);
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xbe78dcdcd414b6bfl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInX(inX);
+            script.forEach_testAtan2Float2Float2Float2(inY, out);
+            verifyResultsAtan2Float2Float2Float2(inY, inX, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2Float2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInX(inX);
+            scriptRelaxed.forEach_testAtan2Float2Float2Float2(inY, out);
+            verifyResultsAtan2Float2Float2Float2(inY, inX, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2Float2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtan2Float2Float2Float2(Allocation inY, Allocation inX, Allocation out, boolean relaxed) {
+        float[] arrayInY = new float[INPUTSIZE * 2];
+        inY.copyTo(arrayInY);
+        float[] arrayInX = new float[INPUTSIZE * 2];
+        inX.copyTo(arrayInX);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inY = arrayInY[i * 2 + j];
+                args.inX = arrayInX[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAtan2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAtan2Float2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAtan2Float3Float3Float3() {
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x12ddbafcd5f2b861l, false);
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x12ddbafcd5f2b860l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInX(inX);
+            script.forEach_testAtan2Float3Float3Float3(inY, out);
+            verifyResultsAtan2Float3Float3Float3(inY, inX, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2Float3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInX(inX);
+            scriptRelaxed.forEach_testAtan2Float3Float3Float3(inY, out);
+            verifyResultsAtan2Float3Float3Float3(inY, inX, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2Float3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtan2Float3Float3Float3(Allocation inY, Allocation inX, Allocation out, boolean relaxed) {
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inY = arrayInY[i * 4 + j];
+                args.inX = arrayInX[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAtan2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAtan2Float3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAtan2Float4Float4Float4() {
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x6742991cd7d0ba02l, false);
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x6742991cd7d0ba01l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInX(inX);
+            script.forEach_testAtan2Float4Float4Float4(inY, out);
+            verifyResultsAtan2Float4Float4Float4(inY, inX, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2Float4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInX(inX);
+            scriptRelaxed.forEach_testAtan2Float4Float4Float4(inY, out);
+            verifyResultsAtan2Float4Float4Float4(inY, inX, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2Float4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtan2Float4Float4Float4(Allocation inY, Allocation inX, Allocation out, boolean relaxed) {
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inY = arrayInY[i * 4 + j];
+                args.inX = arrayInX[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAtan2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAtan2Float4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testAtan2() {
+        checkAtan2FloatFloatFloat();
+        checkAtan2Float2Float2Float2();
+        checkAtan2Float3Float3Float3();
+        checkAtan2Float4Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAtan2.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestAtan2.rs
new file mode 100644
index 0000000..877402d
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAtan2.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInX;
+
+float __attribute__((kernel)) testAtan2FloatFloatFloat(float inY, unsigned int x) {
+    float inX = rsGetElementAt_float(gAllocInX, x);
+    return atan2(inY, inX);
+}
+
+float2 __attribute__((kernel)) testAtan2Float2Float2Float2(float2 inY, unsigned int x) {
+    float2 inX = rsGetElementAt_float2(gAllocInX, x);
+    return atan2(inY, inX);
+}
+
+float3 __attribute__((kernel)) testAtan2Float3Float3Float3(float3 inY, unsigned int x) {
+    float3 inX = rsGetElementAt_float3(gAllocInX, x);
+    return atan2(inY, inX);
+}
+
+float4 __attribute__((kernel)) testAtan2Float4Float4Float4(float4 inY, unsigned int x) {
+    float4 inX = rsGetElementAt_float4(gAllocInX, x);
+    return atan2(inY, inX);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAtan2Relaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestAtan2Relaxed.rs
new file mode 100644
index 0000000..d5d90a1
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAtan2Relaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestAtan2.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAtan2pi.java b/tests/tests/renderscript/src/android/renderscript/cts/TestAtan2pi.java
new file mode 100644
index 0000000..8837003
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAtan2pi.java
@@ -0,0 +1,325 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestAtan2pi extends RSBaseCompute {
+
+    private ScriptC_TestAtan2pi script;
+    private ScriptC_TestAtan2piRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestAtan2pi(mRS);
+        scriptRelaxed = new ScriptC_TestAtan2piRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float inY;
+        public float inX;
+        public Target.Floaty out;
+    }
+
+    private void checkAtan2piFloatFloatFloat() {
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x5a912731bef85233l, false);
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x5a912731bef85232l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInX(inX);
+            script.forEach_testAtan2piFloatFloatFloat(inY, out);
+            verifyResultsAtan2piFloatFloatFloat(inY, inX, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2piFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInX(inX);
+            scriptRelaxed.forEach_testAtan2piFloatFloatFloat(inY, out);
+            verifyResultsAtan2piFloatFloatFloat(inY, inX, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2piFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtan2piFloatFloatFloat(Allocation inY, Allocation inX, Allocation out, boolean relaxed) {
+        float[] arrayInY = new float[INPUTSIZE * 1];
+        inY.copyTo(arrayInY);
+        float[] arrayInX = new float[INPUTSIZE * 1];
+        inX.copyTo(arrayInX);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inY = arrayInY[i];
+                args.inX = arrayInX[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAtan2pi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAtan2piFloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAtan2piFloat2Float2Float2() {
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x8031be184fee8f53l, false);
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x8031be184fee8f52l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInX(inX);
+            script.forEach_testAtan2piFloat2Float2Float2(inY, out);
+            verifyResultsAtan2piFloat2Float2Float2(inY, inX, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2piFloat2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInX(inX);
+            scriptRelaxed.forEach_testAtan2piFloat2Float2Float2(inY, out);
+            verifyResultsAtan2piFloat2Float2Float2(inY, inX, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2piFloat2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtan2piFloat2Float2Float2(Allocation inY, Allocation inX, Allocation out, boolean relaxed) {
+        float[] arrayInY = new float[INPUTSIZE * 2];
+        inY.copyTo(arrayInY);
+        float[] arrayInX = new float[INPUTSIZE * 2];
+        inX.copyTo(arrayInX);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inY = arrayInY[i * 2 + j];
+                args.inX = arrayInX[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAtan2pi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAtan2piFloat2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAtan2piFloat3Float3Float3() {
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xd4969c3851cc90f4l, false);
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xd4969c3851cc90f3l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInX(inX);
+            script.forEach_testAtan2piFloat3Float3Float3(inY, out);
+            verifyResultsAtan2piFloat3Float3Float3(inY, inX, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2piFloat3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInX(inX);
+            scriptRelaxed.forEach_testAtan2piFloat3Float3Float3(inY, out);
+            verifyResultsAtan2piFloat3Float3Float3(inY, inX, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2piFloat3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtan2piFloat3Float3Float3(Allocation inY, Allocation inX, Allocation out, boolean relaxed) {
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inY = arrayInY[i * 4 + j];
+                args.inX = arrayInX[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAtan2pi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAtan2piFloat3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAtan2piFloat4Float4Float4() {
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x28fb7a5853aa9295l, false);
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x28fb7a5853aa9294l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInX(inX);
+            script.forEach_testAtan2piFloat4Float4Float4(inY, out);
+            verifyResultsAtan2piFloat4Float4Float4(inY, inX, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2piFloat4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInX(inX);
+            scriptRelaxed.forEach_testAtan2piFloat4Float4Float4(inY, out);
+            verifyResultsAtan2piFloat4Float4Float4(inY, inX, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2piFloat4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtan2piFloat4Float4Float4(Allocation inY, Allocation inX, Allocation out, boolean relaxed) {
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inY = arrayInY[i * 4 + j];
+                args.inX = arrayInX[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAtan2pi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAtan2piFloat4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testAtan2pi() {
+        checkAtan2piFloatFloatFloat();
+        checkAtan2piFloat2Float2Float2();
+        checkAtan2piFloat3Float3Float3();
+        checkAtan2piFloat4Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAtan2pi.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestAtan2pi.rs
new file mode 100644
index 0000000..f0520d7
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAtan2pi.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInX;
+
+float __attribute__((kernel)) testAtan2piFloatFloatFloat(float inY, unsigned int x) {
+    float inX = rsGetElementAt_float(gAllocInX, x);
+    return atan2pi(inY, inX);
+}
+
+float2 __attribute__((kernel)) testAtan2piFloat2Float2Float2(float2 inY, unsigned int x) {
+    float2 inX = rsGetElementAt_float2(gAllocInX, x);
+    return atan2pi(inY, inX);
+}
+
+float3 __attribute__((kernel)) testAtan2piFloat3Float3Float3(float3 inY, unsigned int x) {
+    float3 inX = rsGetElementAt_float3(gAllocInX, x);
+    return atan2pi(inY, inX);
+}
+
+float4 __attribute__((kernel)) testAtan2piFloat4Float4Float4(float4 inY, unsigned int x) {
+    float4 inX = rsGetElementAt_float4(gAllocInX, x);
+    return atan2pi(inY, inX);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAtan2piRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestAtan2piRelaxed.rs
new file mode 100644
index 0000000..9f87fff
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAtan2piRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestAtan2pi.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAtanRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestAtanRelaxed.rs
new file mode 100644
index 0000000..cab9300
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAtanRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestAtan.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAtanh.java b/tests/tests/renderscript/src/android/renderscript/cts/TestAtanh.java
new file mode 100644
index 0000000..a07c171
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAtanh.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestAtanh extends RSBaseCompute {
+
+    private ScriptC_TestAtanh script;
+    private ScriptC_TestAtanhRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestAtanh(mRS);
+        scriptRelaxed = new ScriptC_TestAtanhRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkAtanhFloatFloat() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xb66b4bab17ef039dl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testAtanhFloatFloat(inV, out);
+            verifyResultsAtanhFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanhFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testAtanhFloatFloat(inV, out);
+            verifyResultsAtanhFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanhFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtanhFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAtanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAtanhFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAtanhFloat2Float2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x8cd03c06a1cb59d9l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testAtanhFloat2Float2(inV, out);
+            verifyResultsAtanhFloat2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanhFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testAtanhFloat2Float2(inV, out);
+            verifyResultsAtanhFloat2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanhFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtanhFloat2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAtanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAtanhFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAtanhFloat3Float3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x8cd2052197e67ab7l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testAtanhFloat3Float3(inV, out);
+            verifyResultsAtanhFloat3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanhFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testAtanhFloat3Float3(inV, out);
+            verifyResultsAtanhFloat3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanhFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtanhFloat3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAtanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAtanhFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAtanhFloat4Float4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x8cd3ce3c8e019b95l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testAtanhFloat4Float4(inV, out);
+            verifyResultsAtanhFloat4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanhFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testAtanhFloat4Float4(inV, out);
+            verifyResultsAtanhFloat4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanhFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtanhFloat4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAtanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAtanhFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testAtanh() {
+        checkAtanhFloatFloat();
+        checkAtanhFloat2Float2();
+        checkAtanhFloat3Float3();
+        checkAtanhFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAtanh.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestAtanh.rs
new file mode 100644
index 0000000..081996c
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAtanh.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testAtanhFloatFloat(float inV) {
+    return atanh(inV);
+}
+
+float2 __attribute__((kernel)) testAtanhFloat2Float2(float2 inV) {
+    return atanh(inV);
+}
+
+float3 __attribute__((kernel)) testAtanhFloat3Float3(float3 inV) {
+    return atanh(inV);
+}
+
+float4 __attribute__((kernel)) testAtanhFloat4Float4(float4 inV) {
+    return atanh(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAtanhRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestAtanhRelaxed.rs
new file mode 100644
index 0000000..88dfc75
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAtanhRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestAtanh.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAtanpi.java b/tests/tests/renderscript/src/android/renderscript/cts/TestAtanpi.java
new file mode 100644
index 0000000..34c4e32
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAtanpi.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestAtanpi extends RSBaseCompute {
+
+    private ScriptC_TestAtanpi script;
+    private ScriptC_TestAtanpiRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestAtanpi(mRS);
+        scriptRelaxed = new ScriptC_TestAtanpiRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkAtanpiFloatFloat() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x29ed55009ecfd70l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testAtanpiFloatFloat(inV, out);
+            verifyResultsAtanpiFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanpiFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testAtanpiFloatFloat(inV, out);
+            verifyResultsAtanpiFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanpiFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtanpiFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAtanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAtanpiFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAtanpiFloat2Float2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xed0d645e752cbed4l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testAtanpiFloat2Float2(inV, out);
+            verifyResultsAtanpiFloat2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanpiFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testAtanpiFloat2Float2(inV, out);
+            verifyResultsAtanpiFloat2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanpiFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtanpiFloat2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAtanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAtanpiFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAtanpiFloat3Float3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xed0f2d796b47dfb2l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testAtanpiFloat3Float3(inV, out);
+            verifyResultsAtanpiFloat3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanpiFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testAtanpiFloat3Float3(inV, out);
+            verifyResultsAtanpiFloat3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanpiFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtanpiFloat3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAtanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAtanpiFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkAtanpiFloat4Float4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xed10f69461630090l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testAtanpiFloat4Float4(inV, out);
+            verifyResultsAtanpiFloat4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanpiFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testAtanpiFloat4Float4(inV, out);
+            verifyResultsAtanpiFloat4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanpiFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtanpiFloat4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeAtanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkAtanpiFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testAtanpi() {
+        checkAtanpiFloatFloat();
+        checkAtanpiFloat2Float2();
+        checkAtanpiFloat3Float3();
+        checkAtanpiFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAtanpi.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestAtanpi.rs
new file mode 100644
index 0000000..a1c6d2d7
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAtanpi.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testAtanpiFloatFloat(float inV) {
+    return atanpi(inV);
+}
+
+float2 __attribute__((kernel)) testAtanpiFloat2Float2(float2 inV) {
+    return atanpi(inV);
+}
+
+float3 __attribute__((kernel)) testAtanpiFloat3Float3(float3 inV) {
+    return atanpi(inV);
+}
+
+float4 __attribute__((kernel)) testAtanpiFloat4Float4(float4 inV) {
+    return atanpi(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestAtanpiRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestAtanpiRelaxed.rs
new file mode 100644
index 0000000..6183636
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestAtanpiRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestAtanpi.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestCbrt.java b/tests/tests/renderscript/src/android/renderscript/cts/TestCbrt.java
new file mode 100644
index 0000000..c6e6bd3
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestCbrt.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestCbrt extends RSBaseCompute {
+
+    private ScriptC_TestCbrt script;
+    private ScriptC_TestCbrtRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestCbrt(mRS);
+        scriptRelaxed = new ScriptC_TestCbrtRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkCbrtFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x4e2c540726cc677al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testCbrtFloatFloat(in, out);
+            verifyResultsCbrtFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCbrtFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testCbrtFloatFloat(in, out);
+            verifyResultsCbrtFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCbrtFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCbrtFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeCbrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkCbrtFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkCbrtFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x9e2a09a2eb8fdb46l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testCbrtFloat2Float2(in, out);
+            verifyResultsCbrtFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCbrtFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testCbrtFloat2Float2(in, out);
+            verifyResultsCbrtFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCbrtFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCbrtFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeCbrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkCbrtFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkCbrtFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x9e2a14444a9670e0l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testCbrtFloat3Float3(in, out);
+            verifyResultsCbrtFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCbrtFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testCbrtFloat3Float3(in, out);
+            verifyResultsCbrtFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCbrtFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCbrtFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeCbrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkCbrtFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkCbrtFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x9e2a1ee5a99d067al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testCbrtFloat4Float4(in, out);
+            verifyResultsCbrtFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCbrtFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testCbrtFloat4Float4(in, out);
+            verifyResultsCbrtFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCbrtFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCbrtFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeCbrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkCbrtFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testCbrt() {
+        checkCbrtFloatFloat();
+        checkCbrtFloat2Float2();
+        checkCbrtFloat3Float3();
+        checkCbrtFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestCbrt.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestCbrt.rs
new file mode 100644
index 0000000..d14f508
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestCbrt.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testCbrtFloatFloat(float in) {
+    return cbrt(in);
+}
+
+float2 __attribute__((kernel)) testCbrtFloat2Float2(float2 in) {
+    return cbrt(in);
+}
+
+float3 __attribute__((kernel)) testCbrtFloat3Float3(float3 in) {
+    return cbrt(in);
+}
+
+float4 __attribute__((kernel)) testCbrtFloat4Float4(float4 in) {
+    return cbrt(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestCbrtRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestCbrtRelaxed.rs
new file mode 100644
index 0000000..ad970fe
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestCbrtRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestCbrt.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestCeil.java b/tests/tests/renderscript/src/android/renderscript/cts/TestCeil.java
new file mode 100644
index 0000000..80121a8
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestCeil.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestCeil extends RSBaseCompute {
+
+    private ScriptC_TestCeil script;
+    private ScriptC_TestCeilRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestCeil(mRS);
+        scriptRelaxed = new ScriptC_TestCeilRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkCeilFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xa65a49d160f51d9al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testCeilFloatFloat(in, out);
+            verifyResultsCeilFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCeilFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testCeilFloatFloat(in, out);
+            verifyResultsCeilFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCeilFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCeilFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeCeil(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkCeilFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkCeilFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x821e4b40fb9b4866l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testCeilFloat2Float2(in, out);
+            verifyResultsCeilFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCeilFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testCeilFloat2Float2(in, out);
+            verifyResultsCeilFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCeilFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCeilFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeCeil(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkCeilFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkCeilFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x821e55e25aa1de00l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testCeilFloat3Float3(in, out);
+            verifyResultsCeilFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCeilFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testCeilFloat3Float3(in, out);
+            verifyResultsCeilFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCeilFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCeilFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeCeil(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkCeilFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkCeilFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x821e6083b9a8739al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testCeilFloat4Float4(in, out);
+            verifyResultsCeilFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCeilFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testCeilFloat4Float4(in, out);
+            verifyResultsCeilFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCeilFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCeilFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeCeil(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkCeilFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testCeil() {
+        checkCeilFloatFloat();
+        checkCeilFloat2Float2();
+        checkCeilFloat3Float3();
+        checkCeilFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestCeil.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestCeil.rs
new file mode 100644
index 0000000..80c8708
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestCeil.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testCeilFloatFloat(float in) {
+    return ceil(in);
+}
+
+float2 __attribute__((kernel)) testCeilFloat2Float2(float2 in) {
+    return ceil(in);
+}
+
+float3 __attribute__((kernel)) testCeilFloat3Float3(float3 in) {
+    return ceil(in);
+}
+
+float4 __attribute__((kernel)) testCeilFloat4Float4(float4 in) {
+    return ceil(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestCeilRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestCeilRelaxed.rs
new file mode 100644
index 0000000..bbafb0d
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestCeilRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestCeil.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestClamp.java b/tests/tests/renderscript/src/android/renderscript/cts/TestClamp.java
new file mode 100644
index 0000000..44f60d6
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestClamp.java
@@ -0,0 +1,4925 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestClamp extends RSBaseCompute {
+
+    private ScriptC_TestClamp script;
+    private ScriptC_TestClampRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestClamp(mRS);
+        scriptRelaxed = new ScriptC_TestClampRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloatFloat {
+        public float inValue;
+        public float inMinValue;
+        public float inMaxValue;
+        public Target.Floaty out;
+    }
+
+    private void checkClampFloatFloatFloatFloat() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x7e886d7cc83c447dl, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xdcebf6f230234027l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xdcebf6e6c180322dl, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampFloatFloatFloatFloat(inValue, out);
+            verifyResultsClampFloatFloatFloatFloat(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampFloatFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampFloatFloatFloatFloat(inValue, out);
+            verifyResultsClampFloatFloatFloatFloat(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampFloatFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampFloatFloatFloatFloat(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        float[] arrayInValue = new float[INPUTSIZE * 1];
+        inValue.copyTo(arrayInValue);
+        float[] arrayInMinValue = new float[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        float[] arrayInMaxValue = new float[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloatFloat args = new ArgumentsFloatFloatFloatFloat();
+                args.inValue = arrayInValue[i];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeClamp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inValue, Float.floatToRawIntBits(args.inValue), args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inMinValue, Float.floatToRawIntBits(args.inMinValue), args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inMaxValue, Float.floatToRawIntBits(args.inMaxValue), args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampFloatFloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampFloat2Float2Float2Float2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xa0d28bf142b07a5l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xb4e5c5f6ea8fc01fl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xb4e5c5eb7becb225l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampFloat2Float2Float2Float2(inValue, out);
+            verifyResultsClampFloat2Float2Float2Float2(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampFloat2Float2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampFloat2Float2Float2Float2(inValue, out);
+            verifyResultsClampFloat2Float2Float2Float2(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampFloat2Float2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampFloat2Float2Float2Float2(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        float[] arrayInValue = new float[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        float[] arrayInMinValue = new float[INPUTSIZE * 2];
+        inMinValue.copyTo(arrayInMinValue);
+        float[] arrayInMaxValue = new float[INPUTSIZE * 2];
+        inMaxValue.copyTo(arrayInMaxValue);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloatFloat args = new ArgumentsFloatFloatFloatFloat();
+                args.inValue = arrayInValue[i * 2 + j];
+                args.inMinValue = arrayInMinValue[i * 2 + j];
+                args.inMaxValue = arrayInMaxValue[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeClamp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inValue, Float.floatToRawIntBits(args.inValue), args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inMinValue, Float.floatToRawIntBits(args.inMinValue), args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inMaxValue, Float.floatToRawIntBits(args.inMaxValue), args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampFloat2Float2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampFloat3Float3Float3Float3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xd3716a4730ad7481l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xc0d239a53946aa73l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xc0d23999caa39c79l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampFloat3Float3Float3Float3(inValue, out);
+            verifyResultsClampFloat3Float3Float3Float3(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampFloat3Float3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampFloat3Float3Float3Float3(inValue, out);
+            verifyResultsClampFloat3Float3Float3Float3(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampFloat3Float3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampFloat3Float3Float3Float3(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        float[] arrayInValue = new float[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        float[] arrayInMinValue = new float[INPUTSIZE * 4];
+        inMinValue.copyTo(arrayInMinValue);
+        float[] arrayInMaxValue = new float[INPUTSIZE * 4];
+        inMaxValue.copyTo(arrayInMaxValue);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloatFloat args = new ArgumentsFloatFloatFloatFloat();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i * 4 + j];
+                args.inMaxValue = arrayInMaxValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeClamp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inValue, Float.floatToRawIntBits(args.inValue), args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inMinValue, Float.floatToRawIntBits(args.inMinValue), args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inMaxValue, Float.floatToRawIntBits(args.inMaxValue), args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampFloat3Float3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampFloat4Float4Float4Float4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x9cd5abcf4d2fe15dl, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xccbead5387fd94c7l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xccbead48195a86cdl, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampFloat4Float4Float4Float4(inValue, out);
+            verifyResultsClampFloat4Float4Float4Float4(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampFloat4Float4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampFloat4Float4Float4Float4(inValue, out);
+            verifyResultsClampFloat4Float4Float4Float4(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampFloat4Float4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampFloat4Float4Float4Float4(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        float[] arrayInValue = new float[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        float[] arrayInMinValue = new float[INPUTSIZE * 4];
+        inMinValue.copyTo(arrayInMinValue);
+        float[] arrayInMaxValue = new float[INPUTSIZE * 4];
+        inMaxValue.copyTo(arrayInMaxValue);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloatFloat args = new ArgumentsFloatFloatFloatFloat();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i * 4 + j];
+                args.inMaxValue = arrayInMaxValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeClamp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inValue, Float.floatToRawIntBits(args.inValue), args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inMinValue, Float.floatToRawIntBits(args.inMinValue), args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inMaxValue, Float.floatToRawIntBits(args.inMaxValue), args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampFloat4Float4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampFloat2FloatFloatFloat2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x71623fb3f1fca1a1l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x148e792e1a6253d3l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x148e7922abbf45d9l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampFloat2FloatFloatFloat2(inValue, out);
+            verifyResultsClampFloat2FloatFloatFloat2(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampFloat2FloatFloatFloat2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampFloat2FloatFloatFloat2(inValue, out);
+            verifyResultsClampFloat2FloatFloatFloat2(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampFloat2FloatFloatFloat2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampFloat2FloatFloatFloat2(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        float[] arrayInValue = new float[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        float[] arrayInMinValue = new float[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        float[] arrayInMaxValue = new float[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloatFloat args = new ArgumentsFloatFloatFloatFloat();
+                args.inValue = arrayInValue[i * 2 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeClamp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inValue, Float.floatToRawIntBits(args.inValue), args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inMinValue, Float.floatToRawIntBits(args.inMinValue), args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inMaxValue, Float.floatToRawIntBits(args.inMaxValue), args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampFloat2FloatFloatFloat2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampFloat3FloatFloatFloat3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xc06893ff6ab8cf27l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x1f4444b84d90bbc5l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x1f4444acdeedadcbl, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampFloat3FloatFloatFloat3(inValue, out);
+            verifyResultsClampFloat3FloatFloatFloat3(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampFloat3FloatFloatFloat3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampFloat3FloatFloatFloat3(inValue, out);
+            verifyResultsClampFloat3FloatFloatFloat3(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampFloat3FloatFloatFloat3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampFloat3FloatFloatFloat3(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        float[] arrayInValue = new float[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        float[] arrayInMinValue = new float[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        float[] arrayInMaxValue = new float[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloatFloat args = new ArgumentsFloatFloatFloatFloat();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeClamp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inValue, Float.floatToRawIntBits(args.inValue), args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inMinValue, Float.floatToRawIntBits(args.inMinValue), args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inMaxValue, Float.floatToRawIntBits(args.inMaxValue), args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampFloat3FloatFloatFloat3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampFloat4FloatFloatFloat4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xf6ee84ae374fcadl, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x29fa104280bf23b7l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x29fa1037121c15bdl, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampFloat4FloatFloatFloat4(inValue, out);
+            verifyResultsClampFloat4FloatFloatFloat4(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampFloat4FloatFloatFloat4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampFloat4FloatFloatFloat4(inValue, out);
+            verifyResultsClampFloat4FloatFloatFloat4(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampFloat4FloatFloatFloat4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampFloat4FloatFloatFloat4(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        float[] arrayInValue = new float[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        float[] arrayInMinValue = new float[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        float[] arrayInMaxValue = new float[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloatFloat args = new ArgumentsFloatFloatFloatFloat();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeClamp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inValue, Float.floatToRawIntBits(args.inValue), args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inMinValue, Float.floatToRawIntBits(args.inMinValue), args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inMaxValue, Float.floatToRawIntBits(args.inMaxValue), args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampFloat4FloatFloatFloat4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsCharCharCharChar {
+        public byte inValue;
+        public byte inMinValue;
+        public byte inMaxValue;
+        public byte out;
+    }
+
+    private void checkClampCharCharCharChar() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 1, 0xaec8640bb673cf75l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 1, 0x6379f7c3c505c8fl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 1, 0x6379f70cdad4e95l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 1), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampCharCharCharChar(inValue, out);
+            verifyResultsClampCharCharCharChar(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampCharCharCharChar: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampCharCharCharChar(inValue, out);
+            verifyResultsClampCharCharCharChar(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampCharCharCharChar: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampCharCharCharChar(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        byte[] arrayInValue = new byte[INPUTSIZE * 1];
+        inValue.copyTo(arrayInValue);
+        byte[] arrayInMinValue = new byte[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        byte[] arrayInMaxValue = new byte[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        byte[] arrayOut = new byte[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharCharCharChar args = new ArgumentsCharCharCharChar();
+                args.inValue = arrayInValue[i];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampCharCharCharChar" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampChar2Char2Char2Char2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 2, 0xa209cfe6c3feb45dl, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 2, 0xed63d0ab3442bdc7l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 2, 0xed63d09fc59fafcdl, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampChar2Char2Char2Char2(inValue, out);
+            verifyResultsClampChar2Char2Char2Char2(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampChar2Char2Char2Char2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampChar2Char2Char2Char2(inValue, out);
+            verifyResultsClampChar2Char2Char2Char2(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampChar2Char2Char2Char2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampChar2Char2Char2Char2(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        byte[] arrayInValue = new byte[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        byte[] arrayInMinValue = new byte[INPUTSIZE * 2];
+        inMinValue.copyTo(arrayInMinValue);
+        byte[] arrayInMaxValue = new byte[INPUTSIZE * 2];
+        inMaxValue.copyTo(arrayInMaxValue);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharCharCharChar args = new ArgumentsCharCharCharChar();
+                args.inValue = arrayInValue[i * 2 + j];
+                args.inMinValue = arrayInMinValue[i * 2 + j];
+                args.inMaxValue = arrayInMaxValue[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampChar2Char2Char2Char2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampChar3Char3Char3Char3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 3, 0xfab6edb7b9d3b0a5l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 3, 0x7ae6f958470ecb1fl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 3, 0x7ae6f94cd86bbd25l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampChar3Char3Char3Char3(inValue, out);
+            verifyResultsClampChar3Char3Char3Char3(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampChar3Char3Char3Char3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampChar3Char3Char3Char3(inValue, out);
+            verifyResultsClampChar3Char3Char3Char3(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampChar3Char3Char3Char3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampChar3Char3Char3Char3(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        byte[] arrayInValue = new byte[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        byte[] arrayInMinValue = new byte[INPUTSIZE * 4];
+        inMinValue.copyTo(arrayInMinValue);
+        byte[] arrayInMaxValue = new byte[INPUTSIZE * 4];
+        inMaxValue.copyTo(arrayInMaxValue);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharCharCharChar args = new ArgumentsCharCharCharChar();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i * 4 + j];
+                args.inMaxValue = arrayInMaxValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampChar3Char3Char3Char3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampChar4Char4Char4Char4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 4, 0x53640b88afa8acedl, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 4, 0x86a220559dad877l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 4, 0x86a21f9eb37ca7dl, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampChar4Char4Char4Char4(inValue, out);
+            verifyResultsClampChar4Char4Char4Char4(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampChar4Char4Char4Char4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampChar4Char4Char4Char4(inValue, out);
+            verifyResultsClampChar4Char4Char4Char4(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampChar4Char4Char4Char4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampChar4Char4Char4Char4(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        byte[] arrayInValue = new byte[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        byte[] arrayInMinValue = new byte[INPUTSIZE * 4];
+        inMinValue.copyTo(arrayInMinValue);
+        byte[] arrayInMaxValue = new byte[INPUTSIZE * 4];
+        inMaxValue.copyTo(arrayInMaxValue);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharCharCharChar args = new ArgumentsCharCharCharChar();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i * 4 + j];
+                args.inMaxValue = arrayInMaxValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampChar4Char4Char4Char4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUcharUcharUcharUchar {
+        public byte inValue;
+        public byte inMinValue;
+        public byte inMaxValue;
+        public byte out;
+    }
+
+    private void checkClampUcharUcharUcharUchar() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 1, 0x680c818a4447655l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 1, 0xae40bae375336f2fl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 1, 0xae40bad806906135l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 1), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUcharUcharUcharUchar(inValue, out);
+            verifyResultsClampUcharUcharUcharUchar(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUcharUcharUcharUchar: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUcharUcharUcharUchar(inValue, out);
+            verifyResultsClampUcharUcharUcharUchar(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUcharUcharUcharUchar: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUcharUcharUcharUchar(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        byte[] arrayInValue = new byte[INPUTSIZE * 1];
+        inValue.copyTo(arrayInValue);
+        byte[] arrayInMinValue = new byte[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        byte[] arrayInMaxValue = new byte[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        byte[] arrayOut = new byte[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUcharUcharUchar args = new ArgumentsUcharUcharUcharUchar();
+                args.inValue = arrayInValue[i];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUcharUcharUcharUchar" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampUchar2Uchar2Uchar2Uchar2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 2, 0xd69df43245dae301l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 2, 0x82681747662c1df3l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 2, 0x8268173bf7890ff9l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUchar2Uchar2Uchar2Uchar2(inValue, out);
+            verifyResultsClampUchar2Uchar2Uchar2Uchar2(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUchar2Uchar2Uchar2Uchar2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUchar2Uchar2Uchar2Uchar2(inValue, out);
+            verifyResultsClampUchar2Uchar2Uchar2Uchar2(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUchar2Uchar2Uchar2Uchar2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUchar2Uchar2Uchar2Uchar2(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        byte[] arrayInValue = new byte[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        byte[] arrayInMinValue = new byte[INPUTSIZE * 2];
+        inMinValue.copyTo(arrayInMinValue);
+        byte[] arrayInMaxValue = new byte[INPUTSIZE * 2];
+        inMaxValue.copyTo(arrayInMaxValue);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUcharUcharUchar args = new ArgumentsUcharUcharUcharUchar();
+                args.inValue = arrayInValue[i * 2 + j];
+                args.inMinValue = arrayInMinValue[i * 2 + j];
+                args.inMaxValue = arrayInMaxValue[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUchar2Uchar2Uchar2Uchar2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampUchar3Uchar3Uchar3Uchar3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 3, 0xa00235ba625d4fddl, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 3, 0x8e548af5b4e30847l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 3, 0x8e548aea463ffa4dl, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUchar3Uchar3Uchar3Uchar3(inValue, out);
+            verifyResultsClampUchar3Uchar3Uchar3Uchar3(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUchar3Uchar3Uchar3Uchar3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUchar3Uchar3Uchar3Uchar3(inValue, out);
+            verifyResultsClampUchar3Uchar3Uchar3Uchar3(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUchar3Uchar3Uchar3Uchar3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUchar3Uchar3Uchar3Uchar3(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        byte[] arrayInValue = new byte[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        byte[] arrayInMinValue = new byte[INPUTSIZE * 4];
+        inMinValue.copyTo(arrayInMinValue);
+        byte[] arrayInMaxValue = new byte[INPUTSIZE * 4];
+        inMaxValue.copyTo(arrayInMaxValue);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUcharUcharUchar args = new ArgumentsUcharUcharUcharUchar();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i * 4 + j];
+                args.inMaxValue = arrayInMaxValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUchar3Uchar3Uchar3Uchar3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampUchar4Uchar4Uchar4Uchar4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 4, 0x696677427edfbcb9l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 4, 0x9a40fea40399f29bl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 4, 0x9a40fe9894f6e4a1l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUchar4Uchar4Uchar4Uchar4(inValue, out);
+            verifyResultsClampUchar4Uchar4Uchar4Uchar4(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUchar4Uchar4Uchar4Uchar4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUchar4Uchar4Uchar4Uchar4(inValue, out);
+            verifyResultsClampUchar4Uchar4Uchar4Uchar4(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUchar4Uchar4Uchar4Uchar4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUchar4Uchar4Uchar4Uchar4(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        byte[] arrayInValue = new byte[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        byte[] arrayInMinValue = new byte[INPUTSIZE * 4];
+        inMinValue.copyTo(arrayInMinValue);
+        byte[] arrayInMaxValue = new byte[INPUTSIZE * 4];
+        inMaxValue.copyTo(arrayInMaxValue);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUcharUcharUchar args = new ArgumentsUcharUcharUcharUchar();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i * 4 + j];
+                args.inMaxValue = arrayInMaxValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUchar4Uchar4Uchar4Uchar4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsShortShortShortShort {
+        public short inValue;
+        public short inMinValue;
+        public short inMaxValue;
+        public short out;
+    }
+
+    private void checkClampShortShortShortShort() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 1, 0x8035c0627fc993ddl, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 1, 0xb5d4bd1fb4661447l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 1, 0xb5d4bd1445c3064dl, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 1), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampShortShortShortShort(inValue, out);
+            verifyResultsClampShortShortShortShort(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampShortShortShortShort: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampShortShortShortShort(inValue, out);
+            verifyResultsClampShortShortShortShort(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampShortShortShortShort: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampShortShortShortShort(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 1];
+        inValue.copyTo(arrayInValue);
+        short[] arrayInMinValue = new short[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        short[] arrayInMaxValue = new short[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortShortShortShort args = new ArgumentsShortShortShortShort();
+                args.inValue = arrayInValue[i];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampShortShortShortShort" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampShort2Short2Short2Short2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 2, 0x7eab8e9b984e0915l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 2, 0x7b334b992e67336fl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 2, 0x7b334b8dbfc42575l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampShort2Short2Short2Short2(inValue, out);
+            verifyResultsClampShort2Short2Short2Short2(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampShort2Short2Short2Short2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampShort2Short2Short2Short2(inValue, out);
+            verifyResultsClampShort2Short2Short2Short2(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampShort2Short2Short2Short2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampShort2Short2Short2Short2(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        short[] arrayInMinValue = new short[INPUTSIZE * 2];
+        inMinValue.copyTo(arrayInMinValue);
+        short[] arrayInMaxValue = new short[INPUTSIZE * 2];
+        inMaxValue.copyTo(arrayInMaxValue);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortShortShortShort args = new ArgumentsShortShortShortShort();
+                args.inValue = arrayInValue[i * 2 + j];
+                args.inMinValue = arrayInMinValue[i * 2 + j];
+                args.inMaxValue = arrayInMaxValue[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampShort2Short2Short2Short2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampShort3Short3Short3Short3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 3, 0x480fd023b4d075f1l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 3, 0x871fbf477d1e1dc3l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 3, 0x871fbf3c0e7b0fc9l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampShort3Short3Short3Short3(inValue, out);
+            verifyResultsClampShort3Short3Short3Short3(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampShort3Short3Short3Short3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampShort3Short3Short3Short3(inValue, out);
+            verifyResultsClampShort3Short3Short3Short3(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampShort3Short3Short3Short3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampShort3Short3Short3Short3(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        short[] arrayInMinValue = new short[INPUTSIZE * 4];
+        inMinValue.copyTo(arrayInMinValue);
+        short[] arrayInMaxValue = new short[INPUTSIZE * 4];
+        inMaxValue.copyTo(arrayInMaxValue);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortShortShortShort args = new ArgumentsShortShortShortShort();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i * 4 + j];
+                args.inMaxValue = arrayInMaxValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampShort3Short3Short3Short3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampShort4Short4Short4Short4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 4, 0x117411abd152e2cdl, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 4, 0x930c32f5cbd50817l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 4, 0x930c32ea5d31fa1dl, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampShort4Short4Short4Short4(inValue, out);
+            verifyResultsClampShort4Short4Short4Short4(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampShort4Short4Short4Short4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampShort4Short4Short4Short4(inValue, out);
+            verifyResultsClampShort4Short4Short4Short4(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampShort4Short4Short4Short4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampShort4Short4Short4Short4(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        short[] arrayInMinValue = new short[INPUTSIZE * 4];
+        inMinValue.copyTo(arrayInMinValue);
+        short[] arrayInMaxValue = new short[INPUTSIZE * 4];
+        inMaxValue.copyTo(arrayInMaxValue);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortShortShortShort args = new ArgumentsShortShortShortShort();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i * 4 + j];
+                args.inMaxValue = arrayInMaxValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampShort4Short4Short4Short4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUshortUshortUshortUshort {
+        public short inValue;
+        public short inMinValue;
+        public short inMaxValue;
+        public short out;
+    }
+
+    private void checkClampUshortUshortUshortUshort() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 1, 0xf5881eeff74c4341l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 1, 0xd2a0571394d3e2b3l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 1, 0xd2a057082630d4b9l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 1), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUshortUshortUshortUshort(inValue, out);
+            verifyResultsClampUshortUshortUshortUshort(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUshortUshortUshortUshort: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUshortUshortUshortUshort(inValue, out);
+            verifyResultsClampUshortUshortUshortUshort(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUshortUshortUshortUshort: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUshortUshortUshortUshort(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 1];
+        inValue.copyTo(arrayInValue);
+        short[] arrayInMinValue = new short[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        short[] arrayInMaxValue = new short[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUshortUshortUshort args = new ArgumentsUshortUshortUshortUshort();
+                args.inValue = arrayInValue[i];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUshortUshortUshortUshort" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampUshort2Ushort2Ushort2Ushort2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 2, 0x6441dbe2fc36b705l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 2, 0x52161e934fa3b43fl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 2, 0x52161e87e100a645l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUshort2Ushort2Ushort2Ushort2(inValue, out);
+            verifyResultsClampUshort2Ushort2Ushort2Ushort2(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUshort2Ushort2Ushort2Ushort2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUshort2Ushort2Ushort2Ushort2(inValue, out);
+            verifyResultsClampUshort2Ushort2Ushort2Ushort2(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUshort2Ushort2Ushort2Ushort2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUshort2Ushort2Ushort2Ushort2(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        short[] arrayInMinValue = new short[INPUTSIZE * 2];
+        inMinValue.copyTo(arrayInMinValue);
+        short[] arrayInMaxValue = new short[INPUTSIZE * 2];
+        inMaxValue.copyTo(arrayInMaxValue);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUshortUshortUshort args = new ArgumentsUshortUshortUshortUshort();
+                args.inValue = arrayInValue[i * 2 + j];
+                args.inMinValue = arrayInMinValue[i * 2 + j];
+                args.inMaxValue = arrayInMaxValue[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUshort2Ushort2Ushort2Ushort2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampUshort3Ushort3Ushort3Ushort3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 3, 0x6b244d61fc64ee3dl, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 3, 0x7b8d14b8610b3967l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 3, 0x7b8d14acf2682b6dl, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUshort3Ushort3Ushort3Ushort3(inValue, out);
+            verifyResultsClampUshort3Ushort3Ushort3Ushort3(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUshort3Ushort3Ushort3Ushort3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUshort3Ushort3Ushort3Ushort3(inValue, out);
+            verifyResultsClampUshort3Ushort3Ushort3Ushort3(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUshort3Ushort3Ushort3Ushort3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUshort3Ushort3Ushort3Ushort3(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        short[] arrayInMinValue = new short[INPUTSIZE * 4];
+        inMinValue.copyTo(arrayInMinValue);
+        short[] arrayInMaxValue = new short[INPUTSIZE * 4];
+        inMaxValue.copyTo(arrayInMaxValue);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUshortUshortUshort args = new ArgumentsUshortUshortUshortUshort();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i * 4 + j];
+                args.inMaxValue = arrayInMaxValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUshort3Ushort3Ushort3Ushort3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampUshort4Ushort4Ushort4Ushort4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 4, 0x7206bee0fc932575l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 4, 0xa5040add7272be8fl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 4, 0xa5040ad203cfb095l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUshort4Ushort4Ushort4Ushort4(inValue, out);
+            verifyResultsClampUshort4Ushort4Ushort4Ushort4(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUshort4Ushort4Ushort4Ushort4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUshort4Ushort4Ushort4Ushort4(inValue, out);
+            verifyResultsClampUshort4Ushort4Ushort4Ushort4(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUshort4Ushort4Ushort4Ushort4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUshort4Ushort4Ushort4Ushort4(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        short[] arrayInMinValue = new short[INPUTSIZE * 4];
+        inMinValue.copyTo(arrayInMinValue);
+        short[] arrayInMaxValue = new short[INPUTSIZE * 4];
+        inMaxValue.copyTo(arrayInMaxValue);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUshortUshortUshort args = new ArgumentsUshortUshortUshortUshort();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i * 4 + j];
+                args.inMaxValue = arrayInMaxValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUshort4Ushort4Ushort4Ushort4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsIntIntIntInt {
+        public int inValue;
+        public int inMinValue;
+        public int inMaxValue;
+        public int out;
+    }
+
+    private void checkClampIntIntIntInt() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 1, 0xfeb3aa11be6164c5l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 1, 0xd11c228c7c8bf97fl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 1, 0xd11c22810de8eb85l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 1), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampIntIntIntInt(inValue, out);
+            verifyResultsClampIntIntIntInt(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampIntIntIntInt: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampIntIntIntInt(inValue, out);
+            verifyResultsClampIntIntIntInt(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampIntIntIntInt: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampIntIntIntInt(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        int[] arrayInValue = new int[INPUTSIZE * 1];
+        inValue.copyTo(arrayInValue);
+        int[] arrayInMinValue = new int[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        int[] arrayInMaxValue = new int[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        int[] arrayOut = new int[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntIntIntInt args = new ArgumentsIntIntIntInt();
+                args.inValue = arrayInValue[i];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampIntIntIntInt" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampInt2Int2Int2Int2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 2, 0x56252903bd307c01l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 2, 0x770112109398f8f3l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 2, 0x7701120524f5eaf9l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampInt2Int2Int2Int2(inValue, out);
+            verifyResultsClampInt2Int2Int2Int2(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampInt2Int2Int2Int2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampInt2Int2Int2Int2(inValue, out);
+            verifyResultsClampInt2Int2Int2Int2(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampInt2Int2Int2Int2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampInt2Int2Int2Int2(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        int[] arrayInValue = new int[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        int[] arrayInMinValue = new int[INPUTSIZE * 2];
+        inMinValue.copyTo(arrayInMinValue);
+        int[] arrayInMaxValue = new int[INPUTSIZE * 2];
+        inMaxValue.copyTo(arrayInMaxValue);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntIntIntInt args = new ArgumentsIntIntIntInt();
+                args.inValue = arrayInValue[i * 2 + j];
+                args.inMinValue = arrayInMinValue[i * 2 + j];
+                args.inMaxValue = arrayInMaxValue[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampInt2Int2Int2Int2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampInt3Int3Int3Int3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 3, 0x966882045600d2edl, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 3, 0xeb73e6749c7caa77l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 3, 0xeb73e6692dd99c7dl, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampInt3Int3Int3Int3(inValue, out);
+            verifyResultsClampInt3Int3Int3Int3(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampInt3Int3Int3Int3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampInt3Int3Int3Int3(inValue, out);
+            verifyResultsClampInt3Int3Int3Int3(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampInt3Int3Int3Int3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampInt3Int3Int3Int3(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        int[] arrayInValue = new int[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        int[] arrayInMinValue = new int[INPUTSIZE * 4];
+        inMinValue.copyTo(arrayInMinValue);
+        int[] arrayInMaxValue = new int[INPUTSIZE * 4];
+        inMaxValue.copyTo(arrayInMaxValue);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntIntIntInt args = new ArgumentsIntIntIntInt();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i * 4 + j];
+                args.inMaxValue = arrayInMaxValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampInt3Int3Int3Int3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampInt4Int4Int4Int4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 4, 0xd6abdb04eed129d9l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 4, 0x5fe6bad8a5605bfbl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 4, 0x5fe6bacd36bd4e01l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampInt4Int4Int4Int4(inValue, out);
+            verifyResultsClampInt4Int4Int4Int4(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampInt4Int4Int4Int4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampInt4Int4Int4Int4(inValue, out);
+            verifyResultsClampInt4Int4Int4Int4(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampInt4Int4Int4Int4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampInt4Int4Int4Int4(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        int[] arrayInValue = new int[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        int[] arrayInMinValue = new int[INPUTSIZE * 4];
+        inMinValue.copyTo(arrayInMinValue);
+        int[] arrayInMaxValue = new int[INPUTSIZE * 4];
+        inMaxValue.copyTo(arrayInMaxValue);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntIntIntInt args = new ArgumentsIntIntIntInt();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i * 4 + j];
+                args.inMaxValue = arrayInMaxValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampInt4Int4Int4Int4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUintUintUintUint {
+        public int inValue;
+        public int inMinValue;
+        public int inMaxValue;
+        public int out;
+    }
+
+    private void checkClampUintUintUintUint() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 1, 0xd8df32b2efc89475l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 1, 0xcf8ec8eece8b7b8fl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 1, 0xcf8ec8e35fe86d95l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 1), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUintUintUintUint(inValue, out);
+            verifyResultsClampUintUintUintUint(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUintUintUintUint: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUintUintUintUint(inValue, out);
+            verifyResultsClampUintUintUintUint(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUintUintUintUint: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUintUintUintUint(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        int[] arrayInValue = new int[INPUTSIZE * 1];
+        inValue.copyTo(arrayInValue);
+        int[] arrayInMinValue = new int[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        int[] arrayInMaxValue = new int[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        int[] arrayOut = new int[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUintUintUint args = new ArgumentsUintUintUintUint();
+                args.inValue = arrayInValue[i];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUintUintUintUint" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampUint2Uint2Uint2Uint2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 2, 0xaf28d478873ae5dl, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 2, 0x5bbd21aa2a4bc7l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 2, 0x5bbd163b873dcdl, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUint2Uint2Uint2Uint2(inValue, out);
+            verifyResultsClampUint2Uint2Uint2Uint2(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUint2Uint2Uint2Uint2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUint2Uint2Uint2Uint2(inValue, out);
+            verifyResultsClampUint2Uint2Uint2Uint2(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUint2Uint2Uint2Uint2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUint2Uint2Uint2Uint2(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        int[] arrayInValue = new int[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        int[] arrayInMinValue = new int[INPUTSIZE * 2];
+        inMinValue.copyTo(arrayInMinValue);
+        int[] arrayInMaxValue = new int[INPUTSIZE * 2];
+        inMaxValue.copyTo(arrayInMaxValue);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUintUintUint args = new ArgumentsUintUintUintUint();
+                args.inValue = arrayInValue[i * 2 + j];
+                args.inMinValue = arrayInMinValue[i * 2 + j];
+                args.inMaxValue = arrayInMaxValue[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUint2Uint2Uint2Uint2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampUint3Uint3Uint3Uint3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 3, 0x639fab187e48aaa5l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 3, 0x8ddee5cebcf6591fl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 3, 0x8ddee5c34e534b25l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUint3Uint3Uint3Uint3(inValue, out);
+            verifyResultsClampUint3Uint3Uint3Uint3(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUint3Uint3Uint3Uint3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUint3Uint3Uint3Uint3(inValue, out);
+            verifyResultsClampUint3Uint3Uint3Uint3(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUint3Uint3Uint3Uint3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUint3Uint3Uint3Uint3(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        int[] arrayInValue = new int[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        int[] arrayInMinValue = new int[INPUTSIZE * 4];
+        inMinValue.copyTo(arrayInMinValue);
+        int[] arrayInMaxValue = new int[INPUTSIZE * 4];
+        inMaxValue.copyTo(arrayInMaxValue);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUintUintUint args = new ArgumentsUintUintUintUint();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i * 4 + j];
+                args.inMaxValue = arrayInMaxValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUint3Uint3Uint3Uint3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampUint4Uint4Uint4Uint4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 4, 0xbc4cc8e9741da6edl, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 4, 0x1b620e7bcfc26677l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 4, 0x1b620e70611f587dl, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUint4Uint4Uint4Uint4(inValue, out);
+            verifyResultsClampUint4Uint4Uint4Uint4(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUint4Uint4Uint4Uint4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUint4Uint4Uint4Uint4(inValue, out);
+            verifyResultsClampUint4Uint4Uint4Uint4(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUint4Uint4Uint4Uint4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUint4Uint4Uint4Uint4(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        int[] arrayInValue = new int[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        int[] arrayInMinValue = new int[INPUTSIZE * 4];
+        inMinValue.copyTo(arrayInMinValue);
+        int[] arrayInMaxValue = new int[INPUTSIZE * 4];
+        inMaxValue.copyTo(arrayInMaxValue);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUintUintUint args = new ArgumentsUintUintUintUint();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i * 4 + j];
+                args.inMaxValue = arrayInMaxValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUint4Uint4Uint4Uint4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsLongLongLongLong {
+        public long inValue;
+        public long inMinValue;
+        public long inMaxValue;
+        public long out;
+    }
+
+    private void checkClampLongLongLongLong() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 1, 0x63fd360531c9c41dl, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 1, 0x9d04d1824ef4907l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 1, 0x9d04d0cb64c3b0dl, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 1), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampLongLongLongLong(inValue, out);
+            verifyResultsClampLongLongLongLong(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampLongLongLongLong: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampLongLongLongLong(inValue, out);
+            verifyResultsClampLongLongLongLong(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampLongLongLongLong: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampLongLongLongLong(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        long[] arrayInValue = new long[INPUTSIZE * 1];
+        inValue.copyTo(arrayInValue);
+        long[] arrayInMinValue = new long[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        long[] arrayInMaxValue = new long[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        long[] arrayOut = new long[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongLongLongLong args = new ArgumentsLongLongLongLong();
+                args.inValue = arrayInValue[i];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampLongLongLongLong" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampLong2Long2Long2Long2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 2, 0xccbae869c2b0f12dl, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 2, 0xe4c3844f4a3f8937l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 2, 0xe4c38443db9c7b3dl, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampLong2Long2Long2Long2(inValue, out);
+            verifyResultsClampLong2Long2Long2Long2(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampLong2Long2Long2Long2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampLong2Long2Long2Long2(inValue, out);
+            verifyResultsClampLong2Long2Long2Long2(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampLong2Long2Long2Long2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampLong2Long2Long2Long2(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        long[] arrayInValue = new long[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        long[] arrayInMinValue = new long[INPUTSIZE * 2];
+        inMinValue.copyTo(arrayInMinValue);
+        long[] arrayInMaxValue = new long[INPUTSIZE * 2];
+        inMaxValue.copyTo(arrayInMaxValue);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongLongLongLong args = new ArgumentsLongLongLongLong();
+                args.inValue = arrayInValue[i * 2 + j];
+                args.inMinValue = arrayInMinValue[i * 2 + j];
+                args.inMaxValue = arrayInMaxValue[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampLong2Long2Long2Long2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampLong3Long3Long3Long3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 3, 0x2568063ab885ed75l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 3, 0x7246acfc5d0b968fl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 3, 0x7246acf0ee688895l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampLong3Long3Long3Long3(inValue, out);
+            verifyResultsClampLong3Long3Long3Long3(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampLong3Long3Long3Long3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampLong3Long3Long3Long3(inValue, out);
+            verifyResultsClampLong3Long3Long3Long3(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampLong3Long3Long3Long3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampLong3Long3Long3Long3(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        long[] arrayInValue = new long[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        long[] arrayInMinValue = new long[INPUTSIZE * 4];
+        inMinValue.copyTo(arrayInMinValue);
+        long[] arrayInMaxValue = new long[INPUTSIZE * 4];
+        inMaxValue.copyTo(arrayInMaxValue);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongLongLongLong args = new ArgumentsLongLongLongLong();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i * 4 + j];
+                args.inMaxValue = arrayInMaxValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampLong3Long3Long3Long3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampLong4Long4Long4Long4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 4, 0x7e15240bae5ae9bdl, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 4, 0xffc9d5a96fd7a3e7l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 4, 0xffc9d59e013495edl, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampLong4Long4Long4Long4(inValue, out);
+            verifyResultsClampLong4Long4Long4Long4(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampLong4Long4Long4Long4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampLong4Long4Long4Long4(inValue, out);
+            verifyResultsClampLong4Long4Long4Long4(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampLong4Long4Long4Long4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampLong4Long4Long4Long4(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        long[] arrayInValue = new long[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        long[] arrayInMinValue = new long[INPUTSIZE * 4];
+        inMinValue.copyTo(arrayInMinValue);
+        long[] arrayInMaxValue = new long[INPUTSIZE * 4];
+        inMaxValue.copyTo(arrayInMaxValue);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongLongLongLong args = new ArgumentsLongLongLongLong();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i * 4 + j];
+                args.inMaxValue = arrayInMaxValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampLong4Long4Long4Long4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUlongUlongUlongUlong {
+        public long inValue;
+        public long inMinValue;
+        public long inMaxValue;
+        public long out;
+    }
+
+    private void checkClampUlongUlongUlongUlong() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 1, 0x2b378139749bf4c5l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 1, 0x75ac5050a8ca97fl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 1, 0x75ac4f99be99b85l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 1), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUlongUlongUlongUlong(inValue, out);
+            verifyResultsClampUlongUlongUlongUlong(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUlongUlongUlongUlong: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUlongUlongUlongUlong(inValue, out);
+            verifyResultsClampUlongUlongUlongUlong(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUlongUlongUlongUlong: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUlongUlongUlongUlong(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        long[] arrayInValue = new long[INPUTSIZE * 1];
+        inValue.copyTo(arrayInValue);
+        long[] arrayInMinValue = new long[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        long[] arrayInMaxValue = new long[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        long[] arrayOut = new long[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUlongUlongUlong args = new ArgumentsUlongUlongUlongUlong();
+                args.inValue = arrayInValue[i];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUlongUlongUlongUlong" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampUlong2Ulong2Ulong2Ulong2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 2, 0xa8c7fb17a09bb299l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 2, 0x14e3c8dffe45623bl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 2, 0x14e3c8d48fa25441l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUlong2Ulong2Ulong2Ulong2(inValue, out);
+            verifyResultsClampUlong2Ulong2Ulong2Ulong2(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUlong2Ulong2Ulong2Ulong2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUlong2Ulong2Ulong2Ulong2(inValue, out);
+            verifyResultsClampUlong2Ulong2Ulong2Ulong2(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUlong2Ulong2Ulong2Ulong2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUlong2Ulong2Ulong2Ulong2(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        long[] arrayInValue = new long[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        long[] arrayInMinValue = new long[INPUTSIZE * 2];
+        inMinValue.copyTo(arrayInMinValue);
+        long[] arrayInMaxValue = new long[INPUTSIZE * 2];
+        inMaxValue.copyTo(arrayInMaxValue);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUlongUlongUlong args = new ArgumentsUlongUlongUlongUlong();
+                args.inValue = arrayInValue[i * 2 + j];
+                args.inMinValue = arrayInMinValue[i * 2 + j];
+                args.inMaxValue = arrayInMaxValue[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUlong2Ulong2Ulong2Ulong2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampUlong3Ulong3Ulong3Ulong3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 3, 0x722c3c9fbd1e1f75l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 3, 0x20d03c8e4cfc4c8fl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 3, 0x20d03c82de593e95l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUlong3Ulong3Ulong3Ulong3(inValue, out);
+            verifyResultsClampUlong3Ulong3Ulong3Ulong3(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUlong3Ulong3Ulong3Ulong3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUlong3Ulong3Ulong3Ulong3(inValue, out);
+            verifyResultsClampUlong3Ulong3Ulong3Ulong3(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUlong3Ulong3Ulong3Ulong3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUlong3Ulong3Ulong3Ulong3(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        long[] arrayInValue = new long[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        long[] arrayInMinValue = new long[INPUTSIZE * 4];
+        inMinValue.copyTo(arrayInMinValue);
+        long[] arrayInMaxValue = new long[INPUTSIZE * 4];
+        inMaxValue.copyTo(arrayInMaxValue);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUlongUlongUlong args = new ArgumentsUlongUlongUlongUlong();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i * 4 + j];
+                args.inMaxValue = arrayInMaxValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUlong3Ulong3Ulong3Ulong3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampUlong4Ulong4Ulong4Ulong4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 4, 0x3b907e27d9a08c51l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 4, 0x2cbcb03c9bb336e3l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 4, 0x2cbcb0312d1028e9l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUlong4Ulong4Ulong4Ulong4(inValue, out);
+            verifyResultsClampUlong4Ulong4Ulong4Ulong4(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUlong4Ulong4Ulong4Ulong4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUlong4Ulong4Ulong4Ulong4(inValue, out);
+            verifyResultsClampUlong4Ulong4Ulong4Ulong4(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUlong4Ulong4Ulong4Ulong4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUlong4Ulong4Ulong4Ulong4(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        long[] arrayInValue = new long[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        long[] arrayInMinValue = new long[INPUTSIZE * 4];
+        inMinValue.copyTo(arrayInMinValue);
+        long[] arrayInMaxValue = new long[INPUTSIZE * 4];
+        inMaxValue.copyTo(arrayInMaxValue);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUlongUlongUlong args = new ArgumentsUlongUlongUlongUlong();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i * 4 + j];
+                args.inMaxValue = arrayInMaxValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUlong4Ulong4Ulong4Ulong4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampChar2CharCharChar2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 2, 0xd6884bbb7c57a5d1l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 1, 0x3bf8830cc3b7db63l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 1, 0x3bf883015514cd69l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampChar2CharCharChar2(inValue, out);
+            verifyResultsClampChar2CharCharChar2(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampChar2CharCharChar2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampChar2CharCharChar2(inValue, out);
+            verifyResultsClampChar2CharCharChar2(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampChar2CharCharChar2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampChar2CharCharChar2(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        byte[] arrayInValue = new byte[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        byte[] arrayInMinValue = new byte[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        byte[] arrayInMaxValue = new byte[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharCharCharChar args = new ArgumentsCharCharCharChar();
+                args.inValue = arrayInValue[i * 2 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampChar2CharCharChar2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampChar3CharCharChar3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 3, 0x4aa68c1b65a26ee5l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 1, 0x8b4b9ea0492789dfl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 1, 0x8b4b9e94da847be5l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampChar3CharCharChar3(inValue, out);
+            verifyResultsClampChar3CharCharChar3(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampChar3CharCharChar3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampChar3CharCharChar3(inValue, out);
+            verifyResultsClampChar3CharCharChar3(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampChar3CharCharChar3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampChar3CharCharChar3(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        byte[] arrayInValue = new byte[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        byte[] arrayInMinValue = new byte[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        byte[] arrayInMaxValue = new byte[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharCharCharChar args = new ArgumentsCharCharCharChar();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampChar3CharCharChar3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampChar4CharCharChar4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 4, 0xbec4cc7b4eed37f9l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 1, 0xda9eba33ce97385bl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 1, 0xda9eba285ff42a61l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampChar4CharCharChar4(inValue, out);
+            verifyResultsClampChar4CharCharChar4(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampChar4CharCharChar4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampChar4CharCharChar4(inValue, out);
+            verifyResultsClampChar4CharCharChar4(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampChar4CharCharChar4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampChar4CharCharChar4(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        byte[] arrayInValue = new byte[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        byte[] arrayInMinValue = new byte[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        byte[] arrayInMaxValue = new byte[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharCharCharChar args = new ArgumentsCharCharCharChar();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampChar4CharCharChar4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampUchar2UcharUcharUchar2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 2, 0xafd4a680f02e0d63l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 1, 0x78bbbcb3e9402039l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 1, 0x78bbbca87a9d123fl, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUchar2UcharUcharUchar2(inValue, out);
+            verifyResultsClampUchar2UcharUcharUchar2(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUchar2UcharUcharUchar2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUchar2UcharUcharUchar2(inValue, out);
+            verifyResultsClampUchar2UcharUcharUchar2(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUchar2UcharUcharUchar2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUchar2UcharUcharUchar2(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        byte[] arrayInValue = new byte[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        byte[] arrayInMinValue = new byte[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        byte[] arrayInMaxValue = new byte[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUcharUcharUchar args = new ArgumentsUcharUcharUcharUchar();
+                args.inValue = arrayInValue[i * 2 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUchar2UcharUcharUchar2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampUchar3UcharUcharUchar3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 3, 0xfedafacc68ea3ae9l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 1, 0x8371883e1c6e882bl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 1, 0x83718832adcb7a31l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUchar3UcharUcharUchar3(inValue, out);
+            verifyResultsClampUchar3UcharUcharUchar3(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUchar3UcharUcharUchar3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUchar3UcharUcharUchar3(inValue, out);
+            verifyResultsClampUchar3UcharUcharUchar3(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUchar3UcharUcharUchar3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUchar3UcharUcharUchar3(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        byte[] arrayInValue = new byte[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        byte[] arrayInMinValue = new byte[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        byte[] arrayInMaxValue = new byte[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUcharUcharUchar args = new ArgumentsUcharUcharUcharUchar();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUchar3UcharUcharUchar3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampUchar4UcharUcharUchar4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 4, 0x4de14f17e1a6686fl, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 1, 0x8e2753c84f9cf01dl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 1, 0x8e2753bce0f9e223l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUchar4UcharUcharUchar4(inValue, out);
+            verifyResultsClampUchar4UcharUcharUchar4(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUchar4UcharUcharUchar4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUchar4UcharUcharUchar4(inValue, out);
+            verifyResultsClampUchar4UcharUcharUchar4(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUchar4UcharUcharUchar4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUchar4UcharUcharUchar4(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        byte[] arrayInValue = new byte[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        byte[] arrayInMinValue = new byte[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        byte[] arrayInMaxValue = new byte[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUcharUcharUchar args = new ArgumentsUcharUcharUcharUchar();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUchar4UcharUcharUchar4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampShort2ShortShortShort2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 2, 0x89e3627eae2d6a9l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 1, 0x886d6d2ccaca776bl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 1, 0x886d6d215c276971l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampShort2ShortShortShort2(inValue, out);
+            verifyResultsClampShort2ShortShortShort2(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampShort2ShortShortShort2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampShort2ShortShortShort2(inValue, out);
+            verifyResultsClampShort2ShortShortShort2(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampShort2ShortShortShort2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampShort2ShortShortShort2(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        short[] arrayInMinValue = new short[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        short[] arrayInMaxValue = new short[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortShortShortShort args = new ArgumentsShortShortShortShort();
+                args.inValue = arrayInValue[i * 2 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampShort2ShortShortShort2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampShort3ShortShortShort3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 3, 0x57a48a73639f042fl, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 1, 0x932338b6fdf8df5dl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 1, 0x932338ab8f55d163l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampShort3ShortShortShort3(inValue, out);
+            verifyResultsClampShort3ShortShortShort3(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampShort3ShortShortShort3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampShort3ShortShortShort3(inValue, out);
+            verifyResultsClampShort3ShortShortShort3(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampShort3ShortShortShort3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampShort3ShortShortShort3(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        short[] arrayInMinValue = new short[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        short[] arrayInMaxValue = new short[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortShortShortShort args = new ArgumentsShortShortShortShort();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampShort3ShortShortShort3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampShort4ShortShortShort4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 4, 0xa6aadebedc5b31b5l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 1, 0x9dd904413127474fl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 1, 0x9dd90435c2843955l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampShort4ShortShortShort4(inValue, out);
+            verifyResultsClampShort4ShortShortShort4(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampShort4ShortShortShort4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampShort4ShortShortShort4(inValue, out);
+            verifyResultsClampShort4ShortShortShort4(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampShort4ShortShortShort4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampShort4ShortShortShort4(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        short[] arrayInMinValue = new short[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        short[] arrayInMaxValue = new short[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortShortShortShort args = new ArgumentsShortShortShortShort();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampShort4ShortShortShort4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampUshort2UshortUshortUshort2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 2, 0x2ece6d045621ef07l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 1, 0xd88bd79cc7874965l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 1, 0xd88bd79158e43b6bl, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUshort2UshortUshortUshort2(inValue, out);
+            verifyResultsClampUshort2UshortUshortUshort2(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUshort2UshortUshortUshort2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUshort2UshortUshortUshort2(inValue, out);
+            verifyResultsClampUshort2UshortUshortUshort2(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUshort2UshortUshortUshort2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUshort2UshortUshortUshort2(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        short[] arrayInMinValue = new short[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        short[] arrayInMaxValue = new short[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUshortUshortUshort args = new ArgumentsUshortUshortUshortUshort();
+                args.inValue = arrayInValue[i * 2 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUshort2UshortUshortUshort2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampUshort3UshortUshortUshort3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 3, 0x393771467c9cd603l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 1, 0xfe016431b3cf1419l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 1, 0xfe016426452c061fl, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUshort3UshortUshortUshort3(inValue, out);
+            verifyResultsClampUshort3UshortUshortUshort3(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUshort3UshortUshortUshort3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUshort3UshortUshortUshort3(inValue, out);
+            verifyResultsClampUshort3UshortUshortUshort3(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUshort3UshortUshortUshort3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUshort3UshortUshortUshort3(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        short[] arrayInMinValue = new short[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        short[] arrayInMaxValue = new short[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUshortUshortUshort args = new ArgumentsUshortUshortUshortUshort();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUshort3UshortUshortUshort3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampUshort4UshortUshortUshort4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 4, 0x43a07588a317bcffl, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 1, 0x2376f0c6a016decdl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 1, 0x2376f0bb3173d0d3l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUshort4UshortUshortUshort4(inValue, out);
+            verifyResultsClampUshort4UshortUshortUshort4(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUshort4UshortUshortUshort4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUshort4UshortUshortUshort4(inValue, out);
+            verifyResultsClampUshort4UshortUshortUshort4(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUshort4UshortUshortUshort4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUshort4UshortUshortUshort4(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        short[] arrayInMinValue = new short[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        short[] arrayInMaxValue = new short[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUshortUshortUshort args = new ArgumentsUshortUshortUshortUshort();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUshort4UshortUshortUshort4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampInt2IntIntInt2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 2, 0xbb55c0997906d1dbl, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 1, 0x69776e80fba24121l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 1, 0x69776e758cff3327l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampInt2IntIntInt2(inValue, out);
+            verifyResultsClampInt2IntIntInt2(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampInt2IntIntInt2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampInt2IntIntInt2(inValue, out);
+            verifyResultsClampInt2IntIntInt2(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampInt2IntIntInt2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampInt2IntIntInt2(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        int[] arrayInValue = new int[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        int[] arrayInMinValue = new int[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        int[] arrayInMaxValue = new int[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntIntIntInt args = new ArgumentsIntIntIntInt();
+                args.inValue = arrayInValue[i * 2 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampInt2IntIntInt2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampInt3IntIntInt3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 3, 0x3af8924ab5370be9l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 1, 0xdde27628f1a08b2bl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 1, 0xdde2761d82fd7d31l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampInt3IntIntInt3(inValue, out);
+            verifyResultsClampInt3IntIntInt3(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampInt3IntIntInt3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampInt3IntIntInt3(inValue, out);
+            verifyResultsClampInt3IntIntInt3(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampInt3IntIntInt3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampInt3IntIntInt3(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        int[] arrayInValue = new int[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        int[] arrayInMinValue = new int[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        int[] arrayInMaxValue = new int[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntIntIntInt args = new ArgumentsIntIntIntInt();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampInt3IntIntInt3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampInt4IntIntInt4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 4, 0xba9b63fbf16745f7l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 1, 0x524d7dd0e79ed535l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 1, 0x524d7dc578fbc73bl, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampInt4IntIntInt4(inValue, out);
+            verifyResultsClampInt4IntIntInt4(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampInt4IntIntInt4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampInt4IntIntInt4(inValue, out);
+            verifyResultsClampInt4IntIntInt4(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampInt4IntIntInt4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampInt4IntIntInt4(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        int[] arrayInValue = new int[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        int[] arrayInMinValue = new int[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        int[] arrayInMaxValue = new int[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntIntIntInt args = new ArgumentsIntIntIntInt();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampInt4IntIntInt4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampUint2UintUintUint2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 2, 0x4fd098dd770d5a51l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 1, 0x6de3f327c2a180e3l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 1, 0x6de3f31c53fe72e9l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUint2UintUintUint2(inValue, out);
+            verifyResultsClampUint2UintUintUint2(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUint2UintUintUint2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUint2UintUintUint2(inValue, out);
+            verifyResultsClampUint2UintUintUint2(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUint2UintUintUint2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUint2UintUintUint2(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        int[] arrayInValue = new int[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        int[] arrayInMinValue = new int[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        int[] arrayInMaxValue = new int[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUintUintUint args = new ArgumentsUintUintUintUint();
+                args.inValue = arrayInValue[i * 2 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUint2UintUintUint2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampUint3UintUintUint3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 3, 0xc3eed93d60582365l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 1, 0xbd370ebb48112f5fl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 1, 0xbd370eafd96e2165l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUint3UintUintUint3(inValue, out);
+            verifyResultsClampUint3UintUintUint3(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUint3UintUintUint3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUint3UintUintUint3(inValue, out);
+            verifyResultsClampUint3UintUintUint3(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUint3UintUintUint3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUint3UintUintUint3(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        int[] arrayInValue = new int[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        int[] arrayInMinValue = new int[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        int[] arrayInMaxValue = new int[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUintUintUint args = new ArgumentsUintUintUintUint();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUint3UintUintUint3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampUint4UintUintUint4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 4, 0x380d199d49a2ec79l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 1, 0xc8a2a4ecd80dddbl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 1, 0xc8a2a435eddcfe1l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUint4UintUintUint4(inValue, out);
+            verifyResultsClampUint4UintUintUint4(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUint4UintUintUint4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUint4UintUintUint4(inValue, out);
+            verifyResultsClampUint4UintUintUint4(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUint4UintUintUint4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUint4UintUintUint4(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        int[] arrayInValue = new int[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        int[] arrayInMinValue = new int[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        int[] arrayInMaxValue = new int[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUintUintUint args = new ArgumentsUintUintUintUint();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUint4UintUintUint4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampLong2LongLongLong2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 2, 0x19353a9f7c535bb5l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 1, 0xee8dc7f38f83654fl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 1, 0xee8dc7e820e05755l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampLong2LongLongLong2(inValue, out);
+            verifyResultsClampLong2LongLongLong2(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampLong2LongLongLong2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampLong2LongLongLong2(inValue, out);
+            verifyResultsClampLong2LongLongLong2(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampLong2LongLongLong2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampLong2LongLongLong2(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        long[] arrayInValue = new long[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        long[] arrayInMinValue = new long[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        long[] arrayInMaxValue = new long[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongLongLongLong args = new ArgumentsLongLongLongLong();
+                args.inValue = arrayInValue[i * 2 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampLong2LongLongLong2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampLong3LongLongLong3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 3, 0x8d537aff659e24c9l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 1, 0x3de0e38714f313cbl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 1, 0x3de0e37ba65005d1l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampLong3LongLongLong3(inValue, out);
+            verifyResultsClampLong3LongLongLong3(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampLong3LongLongLong3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampLong3LongLongLong3(inValue, out);
+            verifyResultsClampLong3LongLongLong3(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampLong3LongLongLong3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampLong3LongLongLong3(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        long[] arrayInValue = new long[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        long[] arrayInMinValue = new long[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        long[] arrayInMaxValue = new long[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongLongLongLong args = new ArgumentsLongLongLongLong();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampLong3LongLongLong3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampLong4LongLongLong4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 4, 0x171bb5f4ee8edddl, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 1, 0x8d33ff1a9a62c247l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 1, 0x8d33ff0f2bbfb44dl, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampLong4LongLongLong4(inValue, out);
+            verifyResultsClampLong4LongLongLong4(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampLong4LongLongLong4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampLong4LongLongLong4(inValue, out);
+            verifyResultsClampLong4LongLongLong4(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampLong4LongLongLong4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampLong4LongLongLong4(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        long[] arrayInValue = new long[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        long[] arrayInMinValue = new long[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        long[] arrayInMaxValue = new long[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongLongLongLong args = new ArgumentsLongLongLongLong();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("%d", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("%d", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampLong4LongLongLong4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampUlong2UlongUlongUlong2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 2, 0xf275dabaa7fa1bf7l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 1, 0xf08a9e698d13b735l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 1, 0xf08a9e5e1e70a93bl, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUlong2UlongUlongUlong2(inValue, out);
+            verifyResultsClampUlong2UlongUlongUlong2(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUlong2UlongUlongUlong2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUlong2UlongUlongUlong2(inValue, out);
+            verifyResultsClampUlong2UlongUlongUlong2(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUlong2UlongUlongUlong2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUlong2UlongUlongUlong2(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        long[] arrayInValue = new long[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        long[] arrayInMinValue = new long[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        long[] arrayInMaxValue = new long[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUlongUlongUlong args = new ArgumentsUlongUlongUlongUlong();
+                args.inValue = arrayInValue[i * 2 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUlong2UlongUlongUlong2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampUlong3UlongUlongUlong3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 3, 0x417c2f0620b6497dl, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 1, 0xfb4069f3c0421f27l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 1, 0xfb4069e8519f112dl, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUlong3UlongUlongUlong3(inValue, out);
+            verifyResultsClampUlong3UlongUlongUlong3(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUlong3UlongUlongUlong3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUlong3UlongUlongUlong3(inValue, out);
+            verifyResultsClampUlong3UlongUlongUlong3(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUlong3UlongUlongUlong3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUlong3UlongUlongUlong3(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        long[] arrayInValue = new long[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        long[] arrayInMinValue = new long[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        long[] arrayInMaxValue = new long[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUlongUlongUlong args = new ArgumentsUlongUlongUlongUlong();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUlong3UlongUlongUlong3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClampUlong4UlongUlongUlong4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 4, 0x9082835199727703l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 1, 0x5f6357df3708719l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 1, 0x5f6357284cd791fl, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampUlong4UlongUlongUlong4(inValue, out);
+            verifyResultsClampUlong4UlongUlongUlong4(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUlong4UlongUlongUlong4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampUlong4UlongUlongUlong4(inValue, out);
+            verifyResultsClampUlong4UlongUlongUlong4(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampUlong4UlongUlongUlong4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampUlong4UlongUlongUlong4(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        long[] arrayInValue = new long[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        long[] arrayInMinValue = new long[INPUTSIZE * 1];
+        inMinValue.copyTo(arrayInMinValue);
+        long[] arrayInMaxValue = new long[INPUTSIZE * 1];
+        inMaxValue.copyTo(arrayInMaxValue);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUlongUlongUlong args = new ArgumentsUlongUlongUlongUlong();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inMinValue = arrayInMinValue[i];
+                args.inMaxValue = arrayInMaxValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClamp(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Input inMinValue: ");
+                    message.append(String.format("0x%x", args.inMinValue));
+                    message.append("\n");
+                    message.append("Input inMaxValue: ");
+                    message.append(String.format("0x%x", args.inMaxValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClampUlong4UlongUlongUlong4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testClamp() {
+        checkClampFloatFloatFloatFloat();
+        checkClampFloat2Float2Float2Float2();
+        checkClampFloat3Float3Float3Float3();
+        checkClampFloat4Float4Float4Float4();
+        checkClampFloat2FloatFloatFloat2();
+        checkClampFloat3FloatFloatFloat3();
+        checkClampFloat4FloatFloatFloat4();
+        checkClampCharCharCharChar();
+        checkClampChar2Char2Char2Char2();
+        checkClampChar3Char3Char3Char3();
+        checkClampChar4Char4Char4Char4();
+        checkClampUcharUcharUcharUchar();
+        checkClampUchar2Uchar2Uchar2Uchar2();
+        checkClampUchar3Uchar3Uchar3Uchar3();
+        checkClampUchar4Uchar4Uchar4Uchar4();
+        checkClampShortShortShortShort();
+        checkClampShort2Short2Short2Short2();
+        checkClampShort3Short3Short3Short3();
+        checkClampShort4Short4Short4Short4();
+        checkClampUshortUshortUshortUshort();
+        checkClampUshort2Ushort2Ushort2Ushort2();
+        checkClampUshort3Ushort3Ushort3Ushort3();
+        checkClampUshort4Ushort4Ushort4Ushort4();
+        checkClampIntIntIntInt();
+        checkClampInt2Int2Int2Int2();
+        checkClampInt3Int3Int3Int3();
+        checkClampInt4Int4Int4Int4();
+        checkClampUintUintUintUint();
+        checkClampUint2Uint2Uint2Uint2();
+        checkClampUint3Uint3Uint3Uint3();
+        checkClampUint4Uint4Uint4Uint4();
+        checkClampLongLongLongLong();
+        checkClampLong2Long2Long2Long2();
+        checkClampLong3Long3Long3Long3();
+        checkClampLong4Long4Long4Long4();
+        checkClampUlongUlongUlongUlong();
+        checkClampUlong2Ulong2Ulong2Ulong2();
+        checkClampUlong3Ulong3Ulong3Ulong3();
+        checkClampUlong4Ulong4Ulong4Ulong4();
+        checkClampChar2CharCharChar2();
+        checkClampChar3CharCharChar3();
+        checkClampChar4CharCharChar4();
+        checkClampUchar2UcharUcharUchar2();
+        checkClampUchar3UcharUcharUchar3();
+        checkClampUchar4UcharUcharUchar4();
+        checkClampShort2ShortShortShort2();
+        checkClampShort3ShortShortShort3();
+        checkClampShort4ShortShortShort4();
+        checkClampUshort2UshortUshortUshort2();
+        checkClampUshort3UshortUshortUshort3();
+        checkClampUshort4UshortUshortUshort4();
+        checkClampInt2IntIntInt2();
+        checkClampInt3IntIntInt3();
+        checkClampInt4IntIntInt4();
+        checkClampUint2UintUintUint2();
+        checkClampUint3UintUintUint3();
+        checkClampUint4UintUintUint4();
+        checkClampLong2LongLongLong2();
+        checkClampLong3LongLongLong3();
+        checkClampLong4LongLongLong4();
+        checkClampUlong2UlongUlongUlong2();
+        checkClampUlong3UlongUlongUlong3();
+        checkClampUlong4UlongUlongUlong4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestClamp.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestClamp.rs
new file mode 100644
index 0000000..9bb5c87
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestClamp.rs
@@ -0,0 +1,401 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInMinValue;
+rs_allocation gAllocInMaxValue;
+
+float __attribute__((kernel)) testClampFloatFloatFloatFloat(float inValue, unsigned int x) {
+    float inMinValue = rsGetElementAt_float(gAllocInMinValue, x);
+    float inMaxValue = rsGetElementAt_float(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+float2 __attribute__((kernel)) testClampFloat2Float2Float2Float2(float2 inValue, unsigned int x) {
+    float2 inMinValue = rsGetElementAt_float2(gAllocInMinValue, x);
+    float2 inMaxValue = rsGetElementAt_float2(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+float3 __attribute__((kernel)) testClampFloat3Float3Float3Float3(float3 inValue, unsigned int x) {
+    float3 inMinValue = rsGetElementAt_float3(gAllocInMinValue, x);
+    float3 inMaxValue = rsGetElementAt_float3(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+float4 __attribute__((kernel)) testClampFloat4Float4Float4Float4(float4 inValue, unsigned int x) {
+    float4 inMinValue = rsGetElementAt_float4(gAllocInMinValue, x);
+    float4 inMaxValue = rsGetElementAt_float4(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+float2 __attribute__((kernel)) testClampFloat2FloatFloatFloat2(float2 inValue, unsigned int x) {
+    float inMinValue = rsGetElementAt_float(gAllocInMinValue, x);
+    float inMaxValue = rsGetElementAt_float(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+float3 __attribute__((kernel)) testClampFloat3FloatFloatFloat3(float3 inValue, unsigned int x) {
+    float inMinValue = rsGetElementAt_float(gAllocInMinValue, x);
+    float inMaxValue = rsGetElementAt_float(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+float4 __attribute__((kernel)) testClampFloat4FloatFloatFloat4(float4 inValue, unsigned int x) {
+    float inMinValue = rsGetElementAt_float(gAllocInMinValue, x);
+    float inMaxValue = rsGetElementAt_float(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+char __attribute__((kernel)) testClampCharCharCharChar(char inValue, unsigned int x) {
+    char inMinValue = rsGetElementAt_char(gAllocInMinValue, x);
+    char inMaxValue = rsGetElementAt_char(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+char2 __attribute__((kernel)) testClampChar2Char2Char2Char2(char2 inValue, unsigned int x) {
+    char2 inMinValue = rsGetElementAt_char2(gAllocInMinValue, x);
+    char2 inMaxValue = rsGetElementAt_char2(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+char3 __attribute__((kernel)) testClampChar3Char3Char3Char3(char3 inValue, unsigned int x) {
+    char3 inMinValue = rsGetElementAt_char3(gAllocInMinValue, x);
+    char3 inMaxValue = rsGetElementAt_char3(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+char4 __attribute__((kernel)) testClampChar4Char4Char4Char4(char4 inValue, unsigned int x) {
+    char4 inMinValue = rsGetElementAt_char4(gAllocInMinValue, x);
+    char4 inMaxValue = rsGetElementAt_char4(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+uchar __attribute__((kernel)) testClampUcharUcharUcharUchar(uchar inValue, unsigned int x) {
+    uchar inMinValue = rsGetElementAt_uchar(gAllocInMinValue, x);
+    uchar inMaxValue = rsGetElementAt_uchar(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+uchar2 __attribute__((kernel)) testClampUchar2Uchar2Uchar2Uchar2(uchar2 inValue, unsigned int x) {
+    uchar2 inMinValue = rsGetElementAt_uchar2(gAllocInMinValue, x);
+    uchar2 inMaxValue = rsGetElementAt_uchar2(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+uchar3 __attribute__((kernel)) testClampUchar3Uchar3Uchar3Uchar3(uchar3 inValue, unsigned int x) {
+    uchar3 inMinValue = rsGetElementAt_uchar3(gAllocInMinValue, x);
+    uchar3 inMaxValue = rsGetElementAt_uchar3(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+uchar4 __attribute__((kernel)) testClampUchar4Uchar4Uchar4Uchar4(uchar4 inValue, unsigned int x) {
+    uchar4 inMinValue = rsGetElementAt_uchar4(gAllocInMinValue, x);
+    uchar4 inMaxValue = rsGetElementAt_uchar4(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+short __attribute__((kernel)) testClampShortShortShortShort(short inValue, unsigned int x) {
+    short inMinValue = rsGetElementAt_short(gAllocInMinValue, x);
+    short inMaxValue = rsGetElementAt_short(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+short2 __attribute__((kernel)) testClampShort2Short2Short2Short2(short2 inValue, unsigned int x) {
+    short2 inMinValue = rsGetElementAt_short2(gAllocInMinValue, x);
+    short2 inMaxValue = rsGetElementAt_short2(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+short3 __attribute__((kernel)) testClampShort3Short3Short3Short3(short3 inValue, unsigned int x) {
+    short3 inMinValue = rsGetElementAt_short3(gAllocInMinValue, x);
+    short3 inMaxValue = rsGetElementAt_short3(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+short4 __attribute__((kernel)) testClampShort4Short4Short4Short4(short4 inValue, unsigned int x) {
+    short4 inMinValue = rsGetElementAt_short4(gAllocInMinValue, x);
+    short4 inMaxValue = rsGetElementAt_short4(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+ushort __attribute__((kernel)) testClampUshortUshortUshortUshort(ushort inValue, unsigned int x) {
+    ushort inMinValue = rsGetElementAt_ushort(gAllocInMinValue, x);
+    ushort inMaxValue = rsGetElementAt_ushort(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+ushort2 __attribute__((kernel)) testClampUshort2Ushort2Ushort2Ushort2(ushort2 inValue, unsigned int x) {
+    ushort2 inMinValue = rsGetElementAt_ushort2(gAllocInMinValue, x);
+    ushort2 inMaxValue = rsGetElementAt_ushort2(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+ushort3 __attribute__((kernel)) testClampUshort3Ushort3Ushort3Ushort3(ushort3 inValue, unsigned int x) {
+    ushort3 inMinValue = rsGetElementAt_ushort3(gAllocInMinValue, x);
+    ushort3 inMaxValue = rsGetElementAt_ushort3(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+ushort4 __attribute__((kernel)) testClampUshort4Ushort4Ushort4Ushort4(ushort4 inValue, unsigned int x) {
+    ushort4 inMinValue = rsGetElementAt_ushort4(gAllocInMinValue, x);
+    ushort4 inMaxValue = rsGetElementAt_ushort4(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+int __attribute__((kernel)) testClampIntIntIntInt(int inValue, unsigned int x) {
+    int inMinValue = rsGetElementAt_int(gAllocInMinValue, x);
+    int inMaxValue = rsGetElementAt_int(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+int2 __attribute__((kernel)) testClampInt2Int2Int2Int2(int2 inValue, unsigned int x) {
+    int2 inMinValue = rsGetElementAt_int2(gAllocInMinValue, x);
+    int2 inMaxValue = rsGetElementAt_int2(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+int3 __attribute__((kernel)) testClampInt3Int3Int3Int3(int3 inValue, unsigned int x) {
+    int3 inMinValue = rsGetElementAt_int3(gAllocInMinValue, x);
+    int3 inMaxValue = rsGetElementAt_int3(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+int4 __attribute__((kernel)) testClampInt4Int4Int4Int4(int4 inValue, unsigned int x) {
+    int4 inMinValue = rsGetElementAt_int4(gAllocInMinValue, x);
+    int4 inMaxValue = rsGetElementAt_int4(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+uint __attribute__((kernel)) testClampUintUintUintUint(uint inValue, unsigned int x) {
+    uint inMinValue = rsGetElementAt_uint(gAllocInMinValue, x);
+    uint inMaxValue = rsGetElementAt_uint(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+uint2 __attribute__((kernel)) testClampUint2Uint2Uint2Uint2(uint2 inValue, unsigned int x) {
+    uint2 inMinValue = rsGetElementAt_uint2(gAllocInMinValue, x);
+    uint2 inMaxValue = rsGetElementAt_uint2(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+uint3 __attribute__((kernel)) testClampUint3Uint3Uint3Uint3(uint3 inValue, unsigned int x) {
+    uint3 inMinValue = rsGetElementAt_uint3(gAllocInMinValue, x);
+    uint3 inMaxValue = rsGetElementAt_uint3(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+uint4 __attribute__((kernel)) testClampUint4Uint4Uint4Uint4(uint4 inValue, unsigned int x) {
+    uint4 inMinValue = rsGetElementAt_uint4(gAllocInMinValue, x);
+    uint4 inMaxValue = rsGetElementAt_uint4(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+long __attribute__((kernel)) testClampLongLongLongLong(long inValue, unsigned int x) {
+    long inMinValue = rsGetElementAt_long(gAllocInMinValue, x);
+    long inMaxValue = rsGetElementAt_long(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+long2 __attribute__((kernel)) testClampLong2Long2Long2Long2(long2 inValue, unsigned int x) {
+    long2 inMinValue = rsGetElementAt_long2(gAllocInMinValue, x);
+    long2 inMaxValue = rsGetElementAt_long2(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+long3 __attribute__((kernel)) testClampLong3Long3Long3Long3(long3 inValue, unsigned int x) {
+    long3 inMinValue = rsGetElementAt_long3(gAllocInMinValue, x);
+    long3 inMaxValue = rsGetElementAt_long3(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+long4 __attribute__((kernel)) testClampLong4Long4Long4Long4(long4 inValue, unsigned int x) {
+    long4 inMinValue = rsGetElementAt_long4(gAllocInMinValue, x);
+    long4 inMaxValue = rsGetElementAt_long4(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+ulong __attribute__((kernel)) testClampUlongUlongUlongUlong(ulong inValue, unsigned int x) {
+    ulong inMinValue = rsGetElementAt_ulong(gAllocInMinValue, x);
+    ulong inMaxValue = rsGetElementAt_ulong(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+ulong2 __attribute__((kernel)) testClampUlong2Ulong2Ulong2Ulong2(ulong2 inValue, unsigned int x) {
+    ulong2 inMinValue = rsGetElementAt_ulong2(gAllocInMinValue, x);
+    ulong2 inMaxValue = rsGetElementAt_ulong2(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+ulong3 __attribute__((kernel)) testClampUlong3Ulong3Ulong3Ulong3(ulong3 inValue, unsigned int x) {
+    ulong3 inMinValue = rsGetElementAt_ulong3(gAllocInMinValue, x);
+    ulong3 inMaxValue = rsGetElementAt_ulong3(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+ulong4 __attribute__((kernel)) testClampUlong4Ulong4Ulong4Ulong4(ulong4 inValue, unsigned int x) {
+    ulong4 inMinValue = rsGetElementAt_ulong4(gAllocInMinValue, x);
+    ulong4 inMaxValue = rsGetElementAt_ulong4(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+char2 __attribute__((kernel)) testClampChar2CharCharChar2(char2 inValue, unsigned int x) {
+    char inMinValue = rsGetElementAt_char(gAllocInMinValue, x);
+    char inMaxValue = rsGetElementAt_char(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+char3 __attribute__((kernel)) testClampChar3CharCharChar3(char3 inValue, unsigned int x) {
+    char inMinValue = rsGetElementAt_char(gAllocInMinValue, x);
+    char inMaxValue = rsGetElementAt_char(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+char4 __attribute__((kernel)) testClampChar4CharCharChar4(char4 inValue, unsigned int x) {
+    char inMinValue = rsGetElementAt_char(gAllocInMinValue, x);
+    char inMaxValue = rsGetElementAt_char(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+uchar2 __attribute__((kernel)) testClampUchar2UcharUcharUchar2(uchar2 inValue, unsigned int x) {
+    uchar inMinValue = rsGetElementAt_uchar(gAllocInMinValue, x);
+    uchar inMaxValue = rsGetElementAt_uchar(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+uchar3 __attribute__((kernel)) testClampUchar3UcharUcharUchar3(uchar3 inValue, unsigned int x) {
+    uchar inMinValue = rsGetElementAt_uchar(gAllocInMinValue, x);
+    uchar inMaxValue = rsGetElementAt_uchar(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+uchar4 __attribute__((kernel)) testClampUchar4UcharUcharUchar4(uchar4 inValue, unsigned int x) {
+    uchar inMinValue = rsGetElementAt_uchar(gAllocInMinValue, x);
+    uchar inMaxValue = rsGetElementAt_uchar(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+short2 __attribute__((kernel)) testClampShort2ShortShortShort2(short2 inValue, unsigned int x) {
+    short inMinValue = rsGetElementAt_short(gAllocInMinValue, x);
+    short inMaxValue = rsGetElementAt_short(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+short3 __attribute__((kernel)) testClampShort3ShortShortShort3(short3 inValue, unsigned int x) {
+    short inMinValue = rsGetElementAt_short(gAllocInMinValue, x);
+    short inMaxValue = rsGetElementAt_short(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+short4 __attribute__((kernel)) testClampShort4ShortShortShort4(short4 inValue, unsigned int x) {
+    short inMinValue = rsGetElementAt_short(gAllocInMinValue, x);
+    short inMaxValue = rsGetElementAt_short(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+ushort2 __attribute__((kernel)) testClampUshort2UshortUshortUshort2(ushort2 inValue, unsigned int x) {
+    ushort inMinValue = rsGetElementAt_ushort(gAllocInMinValue, x);
+    ushort inMaxValue = rsGetElementAt_ushort(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+ushort3 __attribute__((kernel)) testClampUshort3UshortUshortUshort3(ushort3 inValue, unsigned int x) {
+    ushort inMinValue = rsGetElementAt_ushort(gAllocInMinValue, x);
+    ushort inMaxValue = rsGetElementAt_ushort(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+ushort4 __attribute__((kernel)) testClampUshort4UshortUshortUshort4(ushort4 inValue, unsigned int x) {
+    ushort inMinValue = rsGetElementAt_ushort(gAllocInMinValue, x);
+    ushort inMaxValue = rsGetElementAt_ushort(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+int2 __attribute__((kernel)) testClampInt2IntIntInt2(int2 inValue, unsigned int x) {
+    int inMinValue = rsGetElementAt_int(gAllocInMinValue, x);
+    int inMaxValue = rsGetElementAt_int(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+int3 __attribute__((kernel)) testClampInt3IntIntInt3(int3 inValue, unsigned int x) {
+    int inMinValue = rsGetElementAt_int(gAllocInMinValue, x);
+    int inMaxValue = rsGetElementAt_int(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+int4 __attribute__((kernel)) testClampInt4IntIntInt4(int4 inValue, unsigned int x) {
+    int inMinValue = rsGetElementAt_int(gAllocInMinValue, x);
+    int inMaxValue = rsGetElementAt_int(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+uint2 __attribute__((kernel)) testClampUint2UintUintUint2(uint2 inValue, unsigned int x) {
+    uint inMinValue = rsGetElementAt_uint(gAllocInMinValue, x);
+    uint inMaxValue = rsGetElementAt_uint(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+uint3 __attribute__((kernel)) testClampUint3UintUintUint3(uint3 inValue, unsigned int x) {
+    uint inMinValue = rsGetElementAt_uint(gAllocInMinValue, x);
+    uint inMaxValue = rsGetElementAt_uint(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+uint4 __attribute__((kernel)) testClampUint4UintUintUint4(uint4 inValue, unsigned int x) {
+    uint inMinValue = rsGetElementAt_uint(gAllocInMinValue, x);
+    uint inMaxValue = rsGetElementAt_uint(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+long2 __attribute__((kernel)) testClampLong2LongLongLong2(long2 inValue, unsigned int x) {
+    long inMinValue = rsGetElementAt_long(gAllocInMinValue, x);
+    long inMaxValue = rsGetElementAt_long(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+long3 __attribute__((kernel)) testClampLong3LongLongLong3(long3 inValue, unsigned int x) {
+    long inMinValue = rsGetElementAt_long(gAllocInMinValue, x);
+    long inMaxValue = rsGetElementAt_long(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+long4 __attribute__((kernel)) testClampLong4LongLongLong4(long4 inValue, unsigned int x) {
+    long inMinValue = rsGetElementAt_long(gAllocInMinValue, x);
+    long inMaxValue = rsGetElementAt_long(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+ulong2 __attribute__((kernel)) testClampUlong2UlongUlongUlong2(ulong2 inValue, unsigned int x) {
+    ulong inMinValue = rsGetElementAt_ulong(gAllocInMinValue, x);
+    ulong inMaxValue = rsGetElementAt_ulong(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+ulong3 __attribute__((kernel)) testClampUlong3UlongUlongUlong3(ulong3 inValue, unsigned int x) {
+    ulong inMinValue = rsGetElementAt_ulong(gAllocInMinValue, x);
+    ulong inMaxValue = rsGetElementAt_ulong(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+ulong4 __attribute__((kernel)) testClampUlong4UlongUlongUlong4(ulong4 inValue, unsigned int x) {
+    ulong inMinValue = rsGetElementAt_ulong(gAllocInMinValue, x);
+    ulong inMaxValue = rsGetElementAt_ulong(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestClampRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestClampRelaxed.rs
new file mode 100644
index 0000000..15fd58c
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestClampRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestClamp.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestClz.java b/tests/tests/renderscript/src/android/renderscript/cts/TestClz.java
new file mode 100644
index 0000000..51241aa
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestClz.java
@@ -0,0 +1,1437 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestClz extends RSBaseCompute {
+
+    private ScriptC_TestClz script;
+    private ScriptC_TestClzRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestClz(mRS);
+        scriptRelaxed = new ScriptC_TestClzRelaxed(mRS);
+    }
+
+    public class ArgumentsCharChar {
+        public byte inValue;
+        public byte out;
+    }
+
+    private void checkClzCharChar() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 1, 0xf6f3a15e2f7765afl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 1), INPUTSIZE);
+            script.forEach_testClzCharChar(inValue, out);
+            verifyResultsClzCharChar(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzCharChar: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testClzCharChar(inValue, out);
+            verifyResultsClzCharChar(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzCharChar: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClzCharChar(Allocation inValue, Allocation out, boolean relaxed) {
+        byte[] arrayInValue = new byte[INPUTSIZE * 1];
+        inValue.copyTo(arrayInValue);
+        byte[] arrayOut = new byte[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharChar args = new ArgumentsCharChar();
+                args.inValue = arrayInValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClz(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClzCharChar" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClzChar2Char2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 2, 0xf718b99dcaca5e93l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            script.forEach_testClzChar2Char2(inValue, out);
+            verifyResultsClzChar2Char2(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzChar2Char2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testClzChar2Char2(inValue, out);
+            verifyResultsClzChar2Char2(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzChar2Char2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClzChar2Char2(Allocation inValue, Allocation out, boolean relaxed) {
+        byte[] arrayInValue = new byte[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharChar args = new ArgumentsCharChar();
+                args.inValue = arrayInValue[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClz(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClzChar2Char2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClzChar3Char3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 3, 0x21a5da5bc7099347l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            script.forEach_testClzChar3Char3(inValue, out);
+            verifyResultsClzChar3Char3(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzChar3Char3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testClzChar3Char3(inValue, out);
+            verifyResultsClzChar3Char3(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzChar3Char3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClzChar3Char3(Allocation inValue, Allocation out, boolean relaxed) {
+        byte[] arrayInValue = new byte[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharChar args = new ArgumentsCharChar();
+                args.inValue = arrayInValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClz(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClzChar3Char3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClzChar4Char4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 4, 0x4c32fb19c348c7fbl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            script.forEach_testClzChar4Char4(inValue, out);
+            verifyResultsClzChar4Char4(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzChar4Char4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testClzChar4Char4(inValue, out);
+            verifyResultsClzChar4Char4(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzChar4Char4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClzChar4Char4(Allocation inValue, Allocation out, boolean relaxed) {
+        byte[] arrayInValue = new byte[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharChar args = new ArgumentsCharChar();
+                args.inValue = arrayInValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClz(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClzChar4Char4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUcharUchar {
+        public byte inValue;
+        public byte out;
+    }
+
+    private void checkClzUcharUchar() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 1, 0xd2e451b48b84f57fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 1), INPUTSIZE);
+            script.forEach_testClzUcharUchar(inValue, out);
+            verifyResultsClzUcharUchar(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzUcharUchar: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testClzUcharUchar(inValue, out);
+            verifyResultsClzUcharUchar(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzUcharUchar: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClzUcharUchar(Allocation inValue, Allocation out, boolean relaxed) {
+        byte[] arrayInValue = new byte[INPUTSIZE * 1];
+        inValue.copyTo(arrayInValue);
+        byte[] arrayOut = new byte[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUchar args = new ArgumentsUcharUchar();
+                args.inValue = arrayInValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClz(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClzUcharUchar" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClzUchar2Uchar2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 2, 0x792e2970f47ebc85l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            script.forEach_testClzUchar2Uchar2(inValue, out);
+            verifyResultsClzUchar2Uchar2(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzUchar2Uchar2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testClzUchar2Uchar2(inValue, out);
+            verifyResultsClzUchar2Uchar2(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzUchar2Uchar2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClzUchar2Uchar2(Allocation inValue, Allocation out, boolean relaxed) {
+        byte[] arrayInValue = new byte[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUchar args = new ArgumentsUcharUchar();
+                args.inValue = arrayInValue[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClz(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClzUchar2Uchar2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClzUchar3Uchar3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 3, 0x9ee29ef83dbce203l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            script.forEach_testClzUchar3Uchar3(inValue, out);
+            verifyResultsClzUchar3Uchar3(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzUchar3Uchar3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testClzUchar3Uchar3(inValue, out);
+            verifyResultsClzUchar3Uchar3(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzUchar3Uchar3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClzUchar3Uchar3(Allocation inValue, Allocation out, boolean relaxed) {
+        byte[] arrayInValue = new byte[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUchar args = new ArgumentsUcharUchar();
+                args.inValue = arrayInValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClz(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClzUchar3Uchar3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClzUchar4Uchar4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 4, 0xc497147f86fb0781l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            script.forEach_testClzUchar4Uchar4(inValue, out);
+            verifyResultsClzUchar4Uchar4(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzUchar4Uchar4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testClzUchar4Uchar4(inValue, out);
+            verifyResultsClzUchar4Uchar4(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzUchar4Uchar4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClzUchar4Uchar4(Allocation inValue, Allocation out, boolean relaxed) {
+        byte[] arrayInValue = new byte[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUchar args = new ArgumentsUcharUchar();
+                args.inValue = arrayInValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClz(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClzUchar4Uchar4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsShortShort {
+        public short inValue;
+        public short out;
+    }
+
+    private void checkClzShortShort() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 1, 0x3290aea900d8ad53l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 1), INPUTSIZE);
+            script.forEach_testClzShortShort(inValue, out);
+            verifyResultsClzShortShort(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzShortShort: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testClzShortShort(inValue, out);
+            verifyResultsClzShortShort(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzShortShort: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClzShortShort(Allocation inValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 1];
+        inValue.copyTo(arrayInValue);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortShort args = new ArgumentsShortShort();
+                args.inValue = arrayInValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClz(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClzShortShort" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClzShort2Short2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 2, 0x81f69d4442dd6ebfl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            script.forEach_testClzShort2Short2(inValue, out);
+            verifyResultsClzShort2Short2(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzShort2Short2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testClzShort2Short2(inValue, out);
+            verifyResultsClzShort2Short2(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzShort2Short2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClzShort2Short2(Allocation inValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortShort args = new ArgumentsShortShort();
+                args.inValue = arrayInValue[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClz(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClzShort2Short2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClzShort3Short3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 3, 0xa7ab12cb8c1b943dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            script.forEach_testClzShort3Short3(inValue, out);
+            verifyResultsClzShort3Short3(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzShort3Short3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testClzShort3Short3(inValue, out);
+            verifyResultsClzShort3Short3(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzShort3Short3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClzShort3Short3(Allocation inValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortShort args = new ArgumentsShortShort();
+                args.inValue = arrayInValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClz(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClzShort3Short3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClzShort4Short4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 4, 0xcd5f8852d559b9bbl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            script.forEach_testClzShort4Short4(inValue, out);
+            verifyResultsClzShort4Short4(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzShort4Short4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testClzShort4Short4(inValue, out);
+            verifyResultsClzShort4Short4(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzShort4Short4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClzShort4Short4(Allocation inValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortShort args = new ArgumentsShortShort();
+                args.inValue = arrayInValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClz(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClzShort4Short4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUshortUshort {
+        public short inValue;
+        public short out;
+    }
+
+    private void checkClzUshortUshort() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 1, 0x97bdeee92c0103a5l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 1), INPUTSIZE);
+            script.forEach_testClzUshortUshort(inValue, out);
+            verifyResultsClzUshortUshort(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzUshortUshort: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testClzUshortUshort(inValue, out);
+            verifyResultsClzUshortUshort(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzUshortUshort: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClzUshortUshort(Allocation inValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 1];
+        inValue.copyTo(arrayInValue);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUshort args = new ArgumentsUshortUshort();
+                args.inValue = arrayInValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClz(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClzUshortUshort" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClzUshort2Ushort2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 2, 0x5ea7a024b2913837l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            script.forEach_testClzUshort2Ushort2(inValue, out);
+            verifyResultsClzUshort2Ushort2(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzUshort2Ushort2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testClzUshort2Ushort2(inValue, out);
+            verifyResultsClzUshort2Ushort2(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzUshort2Ushort2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClzUshort2Ushort2(Allocation inValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUshort args = new ArgumentsUshortUshort();
+                args.inValue = arrayInValue[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClz(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClzUshort2Ushort2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClzUshort3Ushort3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 3, 0xb3f7537beaa1cfa3l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            script.forEach_testClzUshort3Ushort3(inValue, out);
+            verifyResultsClzUshort3Ushort3(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzUshort3Ushort3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testClzUshort3Ushort3(inValue, out);
+            verifyResultsClzUshort3Ushort3(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzUshort3Ushort3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClzUshort3Ushort3(Allocation inValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUshort args = new ArgumentsUshortUshort();
+                args.inValue = arrayInValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClz(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClzUshort3Ushort3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClzUshort4Ushort4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 4, 0x94706d322b2670fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            script.forEach_testClzUshort4Ushort4(inValue, out);
+            verifyResultsClzUshort4Ushort4(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzUshort4Ushort4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testClzUshort4Ushort4(inValue, out);
+            verifyResultsClzUshort4Ushort4(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzUshort4Ushort4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClzUshort4Ushort4(Allocation inValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUshort args = new ArgumentsUshortUshort();
+                args.inValue = arrayInValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClz(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClzUshort4Ushort4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsIntInt {
+        public int inValue;
+        public int out;
+    }
+
+    private void checkClzIntInt() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 1, 0xb13809da3142eb97l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 1), INPUTSIZE);
+            script.forEach_testClzIntInt(inValue, out);
+            verifyResultsClzIntInt(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzIntInt: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testClzIntInt(inValue, out);
+            verifyResultsClzIntInt(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzIntInt: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClzIntInt(Allocation inValue, Allocation out, boolean relaxed) {
+        int[] arrayInValue = new int[INPUTSIZE * 1];
+        inValue.copyTo(arrayInValue);
+        int[] arrayOut = new int[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntInt args = new ArgumentsIntInt();
+                args.inValue = arrayInValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClz(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClzIntInt" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClzInt2Int2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 2, 0xc9fd2c1a27fe3ad5l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            script.forEach_testClzInt2Int2(inValue, out);
+            verifyResultsClzInt2Int2(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzInt2Int2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testClzInt2Int2(inValue, out);
+            verifyResultsClzInt2Int2(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzInt2Int2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClzInt2Int2(Allocation inValue, Allocation out, boolean relaxed) {
+        int[] arrayInValue = new int[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntInt args = new ArgumentsIntInt();
+                args.inValue = arrayInValue[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClz(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClzInt2Int2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClzInt3Int3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 3, 0xd6e2b014f2d24c2bl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            script.forEach_testClzInt3Int3(inValue, out);
+            verifyResultsClzInt3Int3(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzInt3Int3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testClzInt3Int3(inValue, out);
+            verifyResultsClzInt3Int3(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzInt3Int3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClzInt3Int3(Allocation inValue, Allocation out, boolean relaxed) {
+        int[] arrayInValue = new int[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntInt args = new ArgumentsIntInt();
+                args.inValue = arrayInValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClz(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClzInt3Int3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClzInt4Int4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 4, 0xe3c8340fbda65d81l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            script.forEach_testClzInt4Int4(inValue, out);
+            verifyResultsClzInt4Int4(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzInt4Int4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testClzInt4Int4(inValue, out);
+            verifyResultsClzInt4Int4(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzInt4Int4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClzInt4Int4(Allocation inValue, Allocation out, boolean relaxed) {
+        int[] arrayInValue = new int[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntInt args = new ArgumentsIntInt();
+                args.inValue = arrayInValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClz(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%d", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClzInt4Int4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUintUint {
+        public int inValue;
+        public int out;
+    }
+
+    private void checkClzUintUint() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 1, 0x64a0b78a75ac502fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 1), INPUTSIZE);
+            script.forEach_testClzUintUint(inValue, out);
+            verifyResultsClzUintUint(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzUintUint: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testClzUintUint(inValue, out);
+            verifyResultsClzUintUint(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzUintUint: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClzUintUint(Allocation inValue, Allocation out, boolean relaxed) {
+        int[] arrayInValue = new int[INPUTSIZE * 1];
+        inValue.copyTo(arrayInValue);
+        int[] arrayOut = new int[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUint args = new ArgumentsUintUint();
+                args.inValue = arrayInValue[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClz(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClzUintUint" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClzUint2Uint2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 2, 0xf809b50329344f93l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            script.forEach_testClzUint2Uint2(inValue, out);
+            verifyResultsClzUint2Uint2(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzUint2Uint2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testClzUint2Uint2(inValue, out);
+            verifyResultsClzUint2Uint2(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzUint2Uint2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClzUint2Uint2(Allocation inValue, Allocation out, boolean relaxed) {
+        int[] arrayInValue = new int[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUint args = new ArgumentsUintUint();
+                args.inValue = arrayInValue[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClz(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClzUint2Uint2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClzUint3Uint3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 3, 0x2296d5c125738447l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            script.forEach_testClzUint3Uint3(inValue, out);
+            verifyResultsClzUint3Uint3(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzUint3Uint3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testClzUint3Uint3(inValue, out);
+            verifyResultsClzUint3Uint3(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzUint3Uint3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClzUint3Uint3(Allocation inValue, Allocation out, boolean relaxed) {
+        int[] arrayInValue = new int[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUint args = new ArgumentsUintUint();
+                args.inValue = arrayInValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClz(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClzUint3Uint3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkClzUint4Uint4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 4, 0x4d23f67f21b2b8fbl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            script.forEach_testClzUint4Uint4(inValue, out);
+            verifyResultsClzUint4Uint4(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzUint4Uint4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testClzUint4Uint4(inValue, out);
+            verifyResultsClzUint4Uint4(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClzUint4Uint4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClzUint4Uint4(Allocation inValue, Allocation out, boolean relaxed) {
+        int[] arrayInValue = new int[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUint args = new ArgumentsUintUint();
+                args.inValue = arrayInValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeClz(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("0x%x", args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkClzUint4Uint4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testClz() {
+        checkClzCharChar();
+        checkClzChar2Char2();
+        checkClzChar3Char3();
+        checkClzChar4Char4();
+        checkClzUcharUchar();
+        checkClzUchar2Uchar2();
+        checkClzUchar3Uchar3();
+        checkClzUchar4Uchar4();
+        checkClzShortShort();
+        checkClzShort2Short2();
+        checkClzShort3Short3();
+        checkClzShort4Short4();
+        checkClzUshortUshort();
+        checkClzUshort2Ushort2();
+        checkClzUshort3Ushort3();
+        checkClzUshort4Ushort4();
+        checkClzIntInt();
+        checkClzInt2Int2();
+        checkClzInt3Int3();
+        checkClzInt4Int4();
+        checkClzUintUint();
+        checkClzUint2Uint2();
+        checkClzUint3Uint3();
+        checkClzUint4Uint4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestClz.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestClz.rs
new file mode 100644
index 0000000..3501e01
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestClz.rs
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+char __attribute__((kernel)) testClzCharChar(char inValue) {
+    return clz(inValue);
+}
+
+char2 __attribute__((kernel)) testClzChar2Char2(char2 inValue) {
+    return clz(inValue);
+}
+
+char3 __attribute__((kernel)) testClzChar3Char3(char3 inValue) {
+    return clz(inValue);
+}
+
+char4 __attribute__((kernel)) testClzChar4Char4(char4 inValue) {
+    return clz(inValue);
+}
+
+uchar __attribute__((kernel)) testClzUcharUchar(uchar inValue) {
+    return clz(inValue);
+}
+
+uchar2 __attribute__((kernel)) testClzUchar2Uchar2(uchar2 inValue) {
+    return clz(inValue);
+}
+
+uchar3 __attribute__((kernel)) testClzUchar3Uchar3(uchar3 inValue) {
+    return clz(inValue);
+}
+
+uchar4 __attribute__((kernel)) testClzUchar4Uchar4(uchar4 inValue) {
+    return clz(inValue);
+}
+
+short __attribute__((kernel)) testClzShortShort(short inValue) {
+    return clz(inValue);
+}
+
+short2 __attribute__((kernel)) testClzShort2Short2(short2 inValue) {
+    return clz(inValue);
+}
+
+short3 __attribute__((kernel)) testClzShort3Short3(short3 inValue) {
+    return clz(inValue);
+}
+
+short4 __attribute__((kernel)) testClzShort4Short4(short4 inValue) {
+    return clz(inValue);
+}
+
+ushort __attribute__((kernel)) testClzUshortUshort(ushort inValue) {
+    return clz(inValue);
+}
+
+ushort2 __attribute__((kernel)) testClzUshort2Ushort2(ushort2 inValue) {
+    return clz(inValue);
+}
+
+ushort3 __attribute__((kernel)) testClzUshort3Ushort3(ushort3 inValue) {
+    return clz(inValue);
+}
+
+ushort4 __attribute__((kernel)) testClzUshort4Ushort4(ushort4 inValue) {
+    return clz(inValue);
+}
+
+int __attribute__((kernel)) testClzIntInt(int inValue) {
+    return clz(inValue);
+}
+
+int2 __attribute__((kernel)) testClzInt2Int2(int2 inValue) {
+    return clz(inValue);
+}
+
+int3 __attribute__((kernel)) testClzInt3Int3(int3 inValue) {
+    return clz(inValue);
+}
+
+int4 __attribute__((kernel)) testClzInt4Int4(int4 inValue) {
+    return clz(inValue);
+}
+
+uint __attribute__((kernel)) testClzUintUint(uint inValue) {
+    return clz(inValue);
+}
+
+uint2 __attribute__((kernel)) testClzUint2Uint2(uint2 inValue) {
+    return clz(inValue);
+}
+
+uint3 __attribute__((kernel)) testClzUint3Uint3(uint3 inValue) {
+    return clz(inValue);
+}
+
+uint4 __attribute__((kernel)) testClzUint4Uint4(uint4 inValue) {
+    return clz(inValue);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestClzRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestClzRelaxed.rs
new file mode 100644
index 0000000..c463c94
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestClzRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestClz.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestConvert.java b/tests/tests/renderscript/src/android/renderscript/cts/TestConvert.java
new file mode 100644
index 0000000..fc56b26
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestConvert.java
@@ -0,0 +1,17819 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestConvert extends RSBaseCompute {
+
+    private ScriptC_TestConvert script;
+    private ScriptC_TestConvertRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestConvert(mRS);
+        scriptRelaxed = new ScriptC_TestConvertRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertFloat2Float2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xfb5215c44e1f6ac6l, -1.6163412428744576259e+38, 1.6163412428744576259e+38);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testConvertFloat2Float2Float2(inV, out);
+            verifyResultsConvertFloat2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat2Float2Float2(inV, out);
+            verifyResultsConvertFloat2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertFloat3Float3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xfb53dedf443a8ba4l, -1.6163412428744576259e+38, 1.6163412428744576259e+38);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testConvertFloat3Float3Float3(inV, out);
+            verifyResultsConvertFloat3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat3Float3Float3(inV, out);
+            verifyResultsConvertFloat3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertFloat4Float4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xfb55a7fa3a55ac82l, -1.6163412428744576259e+38, 1.6163412428744576259e+38);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testConvertFloat4Float4Float4(inV, out);
+            verifyResultsConvertFloat4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat4Float4Float4(inV, out);
+            verifyResultsConvertFloat4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsCharFloat {
+        public byte inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertChar2Float2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 2, 0x5861e2161f489286l, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testConvertFloat2Char2Float2(inV, out);
+            verifyResultsConvertChar2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat2Char2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat2Char2Float2(inV, out);
+            verifyResultsConvertChar2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat2Char2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharFloat args = new ArgumentsCharFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertChar3Float3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 3, 0x5863ab311563b364l, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testConvertFloat3Char3Float3(inV, out);
+            verifyResultsConvertChar3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat3Char3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat3Char3Float3(inV, out);
+            verifyResultsConvertChar3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat3Char3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharFloat args = new ArgumentsCharFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertChar4Float4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 4, 0x5865744c0b7ed442l, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testConvertFloat4Char4Float4(inV, out);
+            verifyResultsConvertChar4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat4Char4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat4Char4Float4(inV, out);
+            verifyResultsConvertChar4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat4Char4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharFloat args = new ArgumentsCharFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUcharFloat {
+        public byte inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertUchar2Float2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 2, 0x7d30021dbb20ac31l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testConvertFloat2Uchar2Float2(inV, out);
+            verifyResultsConvertUchar2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat2Uchar2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat2Uchar2Float2(inV, out);
+            verifyResultsConvertUchar2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat2Uchar2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharFloat args = new ArgumentsUcharFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUchar3Float3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 3, 0x7d31cb38b13bcd0fl, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testConvertFloat3Uchar3Float3(inV, out);
+            verifyResultsConvertUchar3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat3Uchar3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat3Uchar3Float3(inV, out);
+            verifyResultsConvertUchar3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat3Uchar3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharFloat args = new ArgumentsUcharFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUchar4Float4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 4, 0x7d339453a756ededl, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testConvertFloat4Uchar4Float4(inV, out);
+            verifyResultsConvertUchar4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat4Uchar4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat4Uchar4Float4(inV, out);
+            verifyResultsConvertUchar4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat4Uchar4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharFloat args = new ArgumentsUcharFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsShortFloat {
+        public short inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertShort2Float2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 2, 0x94ca184eff219172l, true, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testConvertFloat2Short2Float2(inV, out);
+            verifyResultsConvertShort2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat2Short2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat2Short2Float2(inV, out);
+            verifyResultsConvertShort2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat2Short2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortFloat args = new ArgumentsShortFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertShort3Float3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 3, 0x94cbe169f53cb250l, true, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testConvertFloat3Short3Float3(inV, out);
+            verifyResultsConvertShort3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat3Short3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat3Short3Float3(inV, out);
+            verifyResultsConvertShort3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat3Short3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortFloat args = new ArgumentsShortFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertShort4Float4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 4, 0x94cdaa84eb57d32el, true, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testConvertFloat4Short4Float4(inV, out);
+            verifyResultsConvertShort4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat4Short4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat4Short4Float4(inV, out);
+            verifyResultsConvertShort4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat4Short4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortFloat args = new ArgumentsShortFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUshortFloat {
+        public short inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertUshort2Float2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 2, 0xc36979962c6de12bl, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testConvertFloat2Ushort2Float2(inV, out);
+            verifyResultsConvertUshort2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat2Ushort2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat2Ushort2Float2(inV, out);
+            verifyResultsConvertUshort2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat2Ushort2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortFloat args = new ArgumentsUshortFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUshort3Float3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 3, 0xc36b42b122890209l, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testConvertFloat3Ushort3Float3(inV, out);
+            verifyResultsConvertUshort3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat3Ushort3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat3Ushort3Float3(inV, out);
+            verifyResultsConvertUshort3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat3Ushort3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortFloat args = new ArgumentsUshortFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUshort4Float4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 4, 0xc36d0bcc18a422e7l, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testConvertFloat4Ushort4Float4(inV, out);
+            verifyResultsConvertUshort4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat4Ushort4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat4Ushort4Float4(inV, out);
+            verifyResultsConvertUshort4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat4Ushort4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortFloat args = new ArgumentsUshortFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsIntFloat {
+        public int inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertInt2Float2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 2, 0x2a52c7eb7402bfc5l, true, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testConvertFloat2Int2Float2(inV, out);
+            verifyResultsConvertInt2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat2Int2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat2Int2Float2(inV, out);
+            verifyResultsConvertInt2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat2Int2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntFloat args = new ArgumentsIntFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertInt3Float3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 3, 0x2a5491066a1de0a3l, true, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testConvertFloat3Int3Float3(inV, out);
+            verifyResultsConvertInt3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat3Int3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat3Int3Float3(inV, out);
+            verifyResultsConvertInt3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat3Int3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntFloat args = new ArgumentsIntFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertInt4Float4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 4, 0x2a565a2160390181l, true, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testConvertFloat4Int4Float4(inV, out);
+            verifyResultsConvertInt4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat4Int4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat4Int4Float4(inV, out);
+            verifyResultsConvertInt4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat4Int4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntFloat args = new ArgumentsIntFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUintFloat {
+        public int inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertUint2Float2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 2, 0xd1e081390684cc46l, false, 32);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testConvertFloat2Uint2Float2(inV, out);
+            verifyResultsConvertUint2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat2Uint2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat2Uint2Float2(inV, out);
+            verifyResultsConvertUint2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat2Uint2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintFloat args = new ArgumentsUintFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUint3Float3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 3, 0xd1e24a53fc9fed24l, false, 32);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testConvertFloat3Uint3Float3(inV, out);
+            verifyResultsConvertUint3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat3Uint3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat3Uint3Float3(inV, out);
+            verifyResultsConvertUint3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat3Uint3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintFloat args = new ArgumentsUintFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUint4Float4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 4, 0xd1e4136ef2bb0e02l, false, 32);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testConvertFloat4Uint4Float4(inV, out);
+            verifyResultsConvertUint4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat4Uint4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat4Uint4Float4(inV, out);
+            verifyResultsConvertUint4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat4Uint4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintFloat args = new ArgumentsUintFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsFloatChar {
+        public float inV;
+        public byte out;
+    }
+
+    private void checkConvertFloat2Char2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x239cb25829789662l, -1.2800000000000000000e+02, 1.2700000000000000000e+02);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            script.forEach_testConvertChar2Float2Char2(inV, out);
+            verifyResultsConvertFloat2Char2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar2Float2Char2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar2Float2Char2(inV, out);
+            verifyResultsConvertFloat2Char2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar2Float2Char2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat2Char2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatChar args = new ArgumentsFloatChar();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat2Char2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertFloat3Char3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x239cbcf988805b56l, -1.2800000000000000000e+02, 1.2700000000000000000e+02);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            script.forEach_testConvertChar3Float3Char3(inV, out);
+            verifyResultsConvertFloat3Char3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar3Float3Char3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar3Float3Char3(inV, out);
+            verifyResultsConvertFloat3Char3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar3Float3Char3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat3Char3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatChar args = new ArgumentsFloatChar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat3Char3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertFloat4Char4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x239cc79ae788204al, -1.2800000000000000000e+02, 1.2700000000000000000e+02);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            script.forEach_testConvertChar4Float4Char4(inV, out);
+            verifyResultsConvertFloat4Char4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar4Float4Char4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar4Float4Char4(inV, out);
+            verifyResultsConvertFloat4Char4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar4Float4Char4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat4Char4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatChar args = new ArgumentsFloatChar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat4Char4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsCharChar {
+        public byte inV;
+        public byte out;
+    }
+
+    private void checkConvertChar2Char2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 2, 0xd8618777d5086da2l, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            script.forEach_testConvertChar2Char2Char2(inV, out);
+            verifyResultsConvertChar2Char2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar2Char2Char2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar2Char2Char2(inV, out);
+            verifyResultsConvertChar2Char2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar2Char2Char2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar2Char2(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharChar args = new ArgumentsCharChar();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar2Char2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertChar3Char3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 3, 0xd861921934103296l, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            script.forEach_testConvertChar3Char3Char3(inV, out);
+            verifyResultsConvertChar3Char3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar3Char3Char3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar3Char3Char3(inV, out);
+            verifyResultsConvertChar3Char3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar3Char3Char3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar3Char3(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharChar args = new ArgumentsCharChar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar3Char3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertChar4Char4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 4, 0xd8619cba9317f78al, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            script.forEach_testConvertChar4Char4Char4(inV, out);
+            verifyResultsConvertChar4Char4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar4Char4Char4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar4Char4Char4(inV, out);
+            verifyResultsConvertChar4Char4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar4Char4Char4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar4Char4(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharChar args = new ArgumentsCharChar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar4Char4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUcharChar {
+        public byte inV;
+        public byte out;
+    }
+
+    private void checkConvertUchar2Char2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 2, 0x7fef40c5678a7a23l, false, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            script.forEach_testConvertChar2Uchar2Char2(inV, out);
+            verifyResultsConvertUchar2Char2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar2Uchar2Char2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar2Uchar2Char2(inV, out);
+            verifyResultsConvertUchar2Char2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar2Uchar2Char2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar2Char2(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharChar args = new ArgumentsUcharChar();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar2Char2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUchar3Char3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 3, 0x7fef4b66c6923f17l, false, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            script.forEach_testConvertChar3Uchar3Char3(inV, out);
+            verifyResultsConvertUchar3Char3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar3Uchar3Char3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar3Uchar3Char3(inV, out);
+            verifyResultsConvertUchar3Char3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar3Uchar3Char3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar3Char3(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharChar args = new ArgumentsUcharChar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar3Char3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUchar4Char4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 4, 0x7fef5608259a040bl, false, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            script.forEach_testConvertChar4Uchar4Char4(inV, out);
+            verifyResultsConvertUchar4Char4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar4Uchar4Char4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar4Uchar4Char4(inV, out);
+            verifyResultsConvertUchar4Char4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar4Uchar4Char4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar4Char4(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharChar args = new ArgumentsUcharChar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar4Char4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsShortChar {
+        public short inV;
+        public byte out;
+    }
+
+    private void checkConvertShort2Char2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 2, 0x68ab650215c60866l, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            script.forEach_testConvertChar2Short2Char2(inV, out);
+            verifyResultsConvertShort2Char2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar2Short2Char2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar2Short2Char2(inV, out);
+            verifyResultsConvertShort2Char2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar2Short2Char2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort2Char2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortChar args = new ArgumentsShortChar();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort2Char2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertShort3Char3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 3, 0x68ab6fa374cdcd5al, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            script.forEach_testConvertChar3Short3Char3(inV, out);
+            verifyResultsConvertShort3Char3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar3Short3Char3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar3Short3Char3(inV, out);
+            verifyResultsConvertShort3Char3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar3Short3Char3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort3Char3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortChar args = new ArgumentsShortChar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort3Char3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertShort4Char4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 4, 0x68ab7a44d3d5924el, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            script.forEach_testConvertChar4Short4Char4(inV, out);
+            verifyResultsConvertShort4Char4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar4Short4Char4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar4Short4Char4(inV, out);
+            verifyResultsConvertShort4Char4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar4Short4Char4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort4Char4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortChar args = new ArgumentsShortChar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort4Char4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUshortChar {
+        public short inV;
+        public byte out;
+    }
+
+    private void checkConvertUshort2Char2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 2, 0x8d798509b19e2211l, false, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            script.forEach_testConvertChar2Ushort2Char2(inV, out);
+            verifyResultsConvertUshort2Char2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar2Ushort2Char2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar2Ushort2Char2(inV, out);
+            verifyResultsConvertUshort2Char2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar2Ushort2Char2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort2Char2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortChar args = new ArgumentsUshortChar();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort2Char2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUshort3Char3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 3, 0x8d798fab10a5e705l, false, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            script.forEach_testConvertChar3Ushort3Char3(inV, out);
+            verifyResultsConvertUshort3Char3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar3Ushort3Char3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar3Ushort3Char3(inV, out);
+            verifyResultsConvertUshort3Char3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar3Ushort3Char3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort3Char3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortChar args = new ArgumentsUshortChar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort3Char3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUshort4Char4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 4, 0x8d799a4c6fadabf9l, false, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            script.forEach_testConvertChar4Ushort4Char4(inV, out);
+            verifyResultsConvertUshort4Char4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar4Ushort4Char4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar4Ushort4Char4(inV, out);
+            verifyResultsConvertUshort4Char4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar4Ushort4Char4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort4Char4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortChar args = new ArgumentsUshortChar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort4Char4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsIntChar {
+        public int inV;
+        public byte out;
+    }
+
+    private void checkConvertInt2Char2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 2, 0xd74f5147364256dfl, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            script.forEach_testConvertChar2Int2Char2(inV, out);
+            verifyResultsConvertInt2Char2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar2Int2Char2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar2Int2Char2(inV, out);
+            verifyResultsConvertInt2Char2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar2Int2Char2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt2Char2(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntChar args = new ArgumentsIntChar();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt2Char2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertInt3Char3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 3, 0xd74f5be8954a1bd3l, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            script.forEach_testConvertChar3Int3Char3(inV, out);
+            verifyResultsConvertInt3Char3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar3Int3Char3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar3Int3Char3(inV, out);
+            verifyResultsConvertInt3Char3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar3Int3Char3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt3Char3(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntChar args = new ArgumentsIntChar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt3Char3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertInt4Char4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 4, 0xd74f6689f451e0c7l, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            script.forEach_testConvertChar4Int4Char4(inV, out);
+            verifyResultsConvertInt4Char4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar4Int4Char4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar4Int4Char4(inV, out);
+            verifyResultsConvertInt4Char4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar4Int4Char4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt4Char4(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntChar args = new ArgumentsIntChar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt4Char4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUintChar {
+        public int inV;
+        public byte out;
+    }
+
+    private void checkConvertUint2Char2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 2, 0xe71d083133b67ae2l, false, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            script.forEach_testConvertChar2Uint2Char2(inV, out);
+            verifyResultsConvertUint2Char2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar2Uint2Char2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar2Uint2Char2(inV, out);
+            verifyResultsConvertUint2Char2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar2Uint2Char2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint2Char2(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintChar args = new ArgumentsUintChar();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint2Char2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUint3Char3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 3, 0xe71d12d292be3fd6l, false, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            script.forEach_testConvertChar3Uint3Char3(inV, out);
+            verifyResultsConvertUint3Char3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar3Uint3Char3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar3Uint3Char3(inV, out);
+            verifyResultsConvertUint3Char3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar3Uint3Char3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint3Char3(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintChar args = new ArgumentsUintChar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint3Char3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUint4Char4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 4, 0xe71d1d73f1c604cal, false, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            script.forEach_testConvertChar4Uint4Char4(inV, out);
+            verifyResultsConvertUint4Char4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar4Uint4Char4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar4Uint4Char4(inV, out);
+            verifyResultsConvertUint4Char4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar4Uint4Char4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint4Char4(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintChar args = new ArgumentsUintChar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint4Char4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsFloatUchar {
+        public float inV;
+        public byte out;
+    }
+
+    private void checkConvertFloat2Uchar2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xfb52b2f4fac15b79l, 0.0000000000000000000e+00, 2.5500000000000000000e+02);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            script.forEach_testConvertUchar2Float2Uchar2(inV, out);
+            verifyResultsConvertFloat2Uchar2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar2Float2Uchar2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar2Float2Uchar2(inV, out);
+            verifyResultsConvertFloat2Uchar2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar2Float2Uchar2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat2Uchar2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatUchar args = new ArgumentsFloatUchar();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat2Uchar2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertFloat3Uchar3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xfb547c0ff0dc7c57l, 0.0000000000000000000e+00, 2.5500000000000000000e+02);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            script.forEach_testConvertUchar3Float3Uchar3(inV, out);
+            verifyResultsConvertFloat3Uchar3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar3Float3Uchar3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar3Float3Uchar3(inV, out);
+            verifyResultsConvertFloat3Uchar3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar3Float3Uchar3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat3Uchar3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatUchar args = new ArgumentsFloatUchar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat3Uchar3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertFloat4Uchar4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xfb56452ae6f79d35l, 0.0000000000000000000e+00, 2.5500000000000000000e+02);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            script.forEach_testConvertUchar4Float4Uchar4(inV, out);
+            verifyResultsConvertFloat4Uchar4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar4Float4Uchar4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar4Float4Uchar4(inV, out);
+            verifyResultsConvertFloat4Uchar4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar4Float4Uchar4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat4Uchar4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatUchar args = new ArgumentsFloatUchar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat4Uchar4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsCharUchar {
+        public byte inV;
+        public byte out;
+    }
+
+    private void checkConvertChar2Uchar2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 2, 0x58627f46cbea8339l, false, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            script.forEach_testConvertUchar2Char2Uchar2(inV, out);
+            verifyResultsConvertChar2Uchar2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar2Char2Uchar2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar2Char2Uchar2(inV, out);
+            verifyResultsConvertChar2Uchar2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar2Char2Uchar2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar2Uchar2(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharUchar args = new ArgumentsCharUchar();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar2Uchar2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertChar3Uchar3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 3, 0x58644861c205a417l, false, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            script.forEach_testConvertUchar3Char3Uchar3(inV, out);
+            verifyResultsConvertChar3Uchar3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar3Char3Uchar3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar3Char3Uchar3(inV, out);
+            verifyResultsConvertChar3Uchar3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar3Char3Uchar3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar3Uchar3(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharUchar args = new ArgumentsCharUchar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar3Uchar3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertChar4Uchar4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 4, 0x5866117cb820c4f5l, false, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            script.forEach_testConvertUchar4Char4Uchar4(inV, out);
+            verifyResultsConvertChar4Uchar4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar4Char4Uchar4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar4Char4Uchar4(inV, out);
+            verifyResultsConvertChar4Uchar4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar4Char4Uchar4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar4Uchar4(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharUchar args = new ArgumentsCharUchar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar4Uchar4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUcharUchar {
+        public byte inV;
+        public byte out;
+    }
+
+    private void checkConvertUchar2Uchar2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 2, 0x7d309f4e67c29ce4l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            script.forEach_testConvertUchar2Uchar2Uchar2(inV, out);
+            verifyResultsConvertUchar2Uchar2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar2Uchar2Uchar2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar2Uchar2Uchar2(inV, out);
+            verifyResultsConvertUchar2Uchar2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar2Uchar2Uchar2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar2Uchar2(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUchar args = new ArgumentsUcharUchar();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar2Uchar2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUchar3Uchar3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 3, 0x7d3268695dddbdc2l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            script.forEach_testConvertUchar3Uchar3Uchar3(inV, out);
+            verifyResultsConvertUchar3Uchar3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar3Uchar3Uchar3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar3Uchar3Uchar3(inV, out);
+            verifyResultsConvertUchar3Uchar3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar3Uchar3Uchar3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar3Uchar3(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUchar args = new ArgumentsUcharUchar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar3Uchar3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUchar4Uchar4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 4, 0x7d34318453f8dea0l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            script.forEach_testConvertUchar4Uchar4Uchar4(inV, out);
+            verifyResultsConvertUchar4Uchar4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar4Uchar4Uchar4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar4Uchar4Uchar4(inV, out);
+            verifyResultsConvertUchar4Uchar4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar4Uchar4Uchar4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar4Uchar4(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUchar args = new ArgumentsUcharUchar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar4Uchar4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsShortUchar {
+        public short inV;
+        public byte out;
+    }
+
+    private void checkConvertShort2Uchar2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 2, 0x94cab57fabc38225l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            script.forEach_testConvertUchar2Short2Uchar2(inV, out);
+            verifyResultsConvertShort2Uchar2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar2Short2Uchar2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar2Short2Uchar2(inV, out);
+            verifyResultsConvertShort2Uchar2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar2Short2Uchar2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort2Uchar2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortUchar args = new ArgumentsShortUchar();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort2Uchar2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertShort3Uchar3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 3, 0x94cc7e9aa1dea303l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            script.forEach_testConvertUchar3Short3Uchar3(inV, out);
+            verifyResultsConvertShort3Uchar3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar3Short3Uchar3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar3Short3Uchar3(inV, out);
+            verifyResultsConvertShort3Uchar3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar3Short3Uchar3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort3Uchar3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortUchar args = new ArgumentsShortUchar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort3Uchar3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertShort4Uchar4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 4, 0x94ce47b597f9c3e1l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            script.forEach_testConvertUchar4Short4Uchar4(inV, out);
+            verifyResultsConvertShort4Uchar4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar4Short4Uchar4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar4Short4Uchar4(inV, out);
+            verifyResultsConvertShort4Uchar4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar4Short4Uchar4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort4Uchar4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortUchar args = new ArgumentsShortUchar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort4Uchar4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUshortUchar {
+        public short inV;
+        public byte out;
+    }
+
+    private void checkConvertUshort2Uchar2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 2, 0xc36a16c6d90fd1del, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            script.forEach_testConvertUchar2Ushort2Uchar2(inV, out);
+            verifyResultsConvertUshort2Uchar2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar2Ushort2Uchar2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar2Ushort2Uchar2(inV, out);
+            verifyResultsConvertUshort2Uchar2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar2Ushort2Uchar2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort2Uchar2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUchar args = new ArgumentsUshortUchar();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort2Uchar2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUshort3Uchar3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 3, 0xc36bdfe1cf2af2bcl, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            script.forEach_testConvertUchar3Ushort3Uchar3(inV, out);
+            verifyResultsConvertUshort3Uchar3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar3Ushort3Uchar3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar3Ushort3Uchar3(inV, out);
+            verifyResultsConvertUshort3Uchar3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar3Ushort3Uchar3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort3Uchar3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUchar args = new ArgumentsUshortUchar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort3Uchar3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUshort4Uchar4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 4, 0xc36da8fcc546139al, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            script.forEach_testConvertUchar4Ushort4Uchar4(inV, out);
+            verifyResultsConvertUshort4Uchar4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar4Ushort4Uchar4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar4Ushort4Uchar4(inV, out);
+            verifyResultsConvertUshort4Uchar4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar4Ushort4Uchar4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort4Uchar4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUchar args = new ArgumentsUshortUchar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort4Uchar4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsIntUchar {
+        public int inV;
+        public byte out;
+    }
+
+    private void checkConvertInt2Uchar2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 2, 0x2a53651c20a4b078l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            script.forEach_testConvertUchar2Int2Uchar2(inV, out);
+            verifyResultsConvertInt2Uchar2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar2Int2Uchar2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar2Int2Uchar2(inV, out);
+            verifyResultsConvertInt2Uchar2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar2Int2Uchar2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt2Uchar2(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntUchar args = new ArgumentsIntUchar();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt2Uchar2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertInt3Uchar3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 3, 0x2a552e3716bfd156l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            script.forEach_testConvertUchar3Int3Uchar3(inV, out);
+            verifyResultsConvertInt3Uchar3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar3Int3Uchar3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar3Int3Uchar3(inV, out);
+            verifyResultsConvertInt3Uchar3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar3Int3Uchar3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt3Uchar3(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntUchar args = new ArgumentsIntUchar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt3Uchar3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertInt4Uchar4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 4, 0x2a56f7520cdaf234l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            script.forEach_testConvertUchar4Int4Uchar4(inV, out);
+            verifyResultsConvertInt4Uchar4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar4Int4Uchar4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar4Int4Uchar4(inV, out);
+            verifyResultsConvertInt4Uchar4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar4Int4Uchar4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt4Uchar4(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntUchar args = new ArgumentsIntUchar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt4Uchar4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUintUchar {
+        public int inV;
+        public byte out;
+    }
+
+    private void checkConvertUint2Uchar2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 2, 0xd1e11e69b326bcf9l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            script.forEach_testConvertUchar2Uint2Uchar2(inV, out);
+            verifyResultsConvertUint2Uchar2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar2Uint2Uchar2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar2Uint2Uchar2(inV, out);
+            verifyResultsConvertUint2Uchar2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar2Uint2Uchar2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint2Uchar2(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUchar args = new ArgumentsUintUchar();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint2Uchar2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUint3Uchar3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 3, 0xd1e2e784a941ddd7l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            script.forEach_testConvertUchar3Uint3Uchar3(inV, out);
+            verifyResultsConvertUint3Uchar3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar3Uint3Uchar3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar3Uint3Uchar3(inV, out);
+            verifyResultsConvertUint3Uchar3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar3Uint3Uchar3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint3Uchar3(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUchar args = new ArgumentsUintUchar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint3Uchar3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUint4Uchar4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 4, 0xd1e4b09f9f5cfeb5l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            script.forEach_testConvertUchar4Uint4Uchar4(inV, out);
+            verifyResultsConvertUint4Uchar4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar4Uint4Uchar4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar4Uint4Uchar4(inV, out);
+            verifyResultsConvertUint4Uchar4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar4Uint4Uchar4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint4Uchar4(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUchar args = new ArgumentsUintUchar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint4Uchar4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsFloatShort {
+        public float inV;
+        public short out;
+    }
+
+    private void checkConvertFloat2Short2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xfb529ef98fcf2692l, -3.2768000000000000000e+04, 3.2767000000000000000e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            script.forEach_testConvertShort2Float2Short2(inV, out);
+            verifyResultsConvertFloat2Short2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort2Float2Short2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort2Float2Short2(inV, out);
+            verifyResultsConvertFloat2Short2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort2Float2Short2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat2Short2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatShort args = new ArgumentsFloatShort();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat2Short2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertFloat3Short3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xfb54681485ea4770l, -3.2768000000000000000e+04, 3.2767000000000000000e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            script.forEach_testConvertShort3Float3Short3(inV, out);
+            verifyResultsConvertFloat3Short3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort3Float3Short3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort3Float3Short3(inV, out);
+            verifyResultsConvertFloat3Short3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort3Float3Short3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat3Short3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatShort args = new ArgumentsFloatShort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat3Short3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertFloat4Short4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xfb56312f7c05684el, -3.2768000000000000000e+04, 3.2767000000000000000e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            script.forEach_testConvertShort4Float4Short4(inV, out);
+            verifyResultsConvertFloat4Short4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort4Float4Short4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort4Float4Short4(inV, out);
+            verifyResultsConvertFloat4Short4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort4Float4Short4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat4Short4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatShort args = new ArgumentsFloatShort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat4Short4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsCharShort {
+        public byte inV;
+        public short out;
+    }
+
+    private void checkConvertChar2Short2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 2, 0x58626b4b60f84e52l, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            script.forEach_testConvertShort2Char2Short2(inV, out);
+            verifyResultsConvertChar2Short2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort2Char2Short2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort2Char2Short2(inV, out);
+            verifyResultsConvertChar2Short2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort2Char2Short2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar2Short2(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharShort args = new ArgumentsCharShort();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar2Short2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertChar3Short3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 3, 0x5864346657136f30l, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            script.forEach_testConvertShort3Char3Short3(inV, out);
+            verifyResultsConvertChar3Short3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort3Char3Short3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort3Char3Short3(inV, out);
+            verifyResultsConvertChar3Short3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort3Char3Short3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar3Short3(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharShort args = new ArgumentsCharShort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar3Short3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertChar4Short4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 4, 0x5865fd814d2e900el, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            script.forEach_testConvertShort4Char4Short4(inV, out);
+            verifyResultsConvertChar4Short4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort4Char4Short4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort4Char4Short4(inV, out);
+            verifyResultsConvertChar4Short4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort4Char4Short4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar4Short4(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharShort args = new ArgumentsCharShort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar4Short4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUcharShort {
+        public byte inV;
+        public short out;
+    }
+
+    private void checkConvertUchar2Short2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 2, 0x7d308b52fcd067fdl, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            script.forEach_testConvertShort2Uchar2Short2(inV, out);
+            verifyResultsConvertUchar2Short2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort2Uchar2Short2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort2Uchar2Short2(inV, out);
+            verifyResultsConvertUchar2Short2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort2Uchar2Short2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar2Short2(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharShort args = new ArgumentsUcharShort();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar2Short2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUchar3Short3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 3, 0x7d32546df2eb88dbl, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            script.forEach_testConvertShort3Uchar3Short3(inV, out);
+            verifyResultsConvertUchar3Short3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort3Uchar3Short3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort3Uchar3Short3(inV, out);
+            verifyResultsConvertUchar3Short3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort3Uchar3Short3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar3Short3(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharShort args = new ArgumentsUcharShort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar3Short3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUchar4Short4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 4, 0x7d341d88e906a9b9l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            script.forEach_testConvertShort4Uchar4Short4(inV, out);
+            verifyResultsConvertUchar4Short4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort4Uchar4Short4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort4Uchar4Short4(inV, out);
+            verifyResultsConvertUchar4Short4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort4Uchar4Short4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar4Short4(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharShort args = new ArgumentsUcharShort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar4Short4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsShortShort {
+        public short inV;
+        public short out;
+    }
+
+    private void checkConvertShort2Short2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 2, 0x94caa18440d14d3el, true, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            script.forEach_testConvertShort2Short2Short2(inV, out);
+            verifyResultsConvertShort2Short2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort2Short2Short2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort2Short2Short2(inV, out);
+            verifyResultsConvertShort2Short2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort2Short2Short2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort2Short2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortShort args = new ArgumentsShortShort();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort2Short2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertShort3Short3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 3, 0x94cc6a9f36ec6e1cl, true, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            script.forEach_testConvertShort3Short3Short3(inV, out);
+            verifyResultsConvertShort3Short3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort3Short3Short3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort3Short3Short3(inV, out);
+            verifyResultsConvertShort3Short3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort3Short3Short3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort3Short3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortShort args = new ArgumentsShortShort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort3Short3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertShort4Short4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 4, 0x94ce33ba2d078efal, true, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            script.forEach_testConvertShort4Short4Short4(inV, out);
+            verifyResultsConvertShort4Short4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort4Short4Short4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort4Short4Short4(inV, out);
+            verifyResultsConvertShort4Short4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort4Short4Short4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort4Short4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortShort args = new ArgumentsShortShort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort4Short4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUshortShort {
+        public short inV;
+        public short out;
+    }
+
+    private void checkConvertUshort2Short2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 2, 0xc36a02cb6e1d9cf7l, false, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            script.forEach_testConvertShort2Ushort2Short2(inV, out);
+            verifyResultsConvertUshort2Short2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort2Ushort2Short2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort2Ushort2Short2(inV, out);
+            verifyResultsConvertUshort2Short2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort2Ushort2Short2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort2Short2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortShort args = new ArgumentsUshortShort();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort2Short2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUshort3Short3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 3, 0xc36bcbe66438bdd5l, false, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            script.forEach_testConvertShort3Ushort3Short3(inV, out);
+            verifyResultsConvertUshort3Short3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort3Ushort3Short3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort3Ushort3Short3(inV, out);
+            verifyResultsConvertUshort3Short3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort3Ushort3Short3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort3Short3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortShort args = new ArgumentsUshortShort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort3Short3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUshort4Short4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 4, 0xc36d95015a53deb3l, false, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            script.forEach_testConvertShort4Ushort4Short4(inV, out);
+            verifyResultsConvertUshort4Short4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort4Ushort4Short4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort4Ushort4Short4(inV, out);
+            verifyResultsConvertUshort4Short4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort4Ushort4Short4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort4Short4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortShort args = new ArgumentsUshortShort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort4Short4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsIntShort {
+        public int inV;
+        public short out;
+    }
+
+    private void checkConvertInt2Short2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 2, 0x2a535120b5b27b91l, true, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            script.forEach_testConvertShort2Int2Short2(inV, out);
+            verifyResultsConvertInt2Short2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort2Int2Short2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort2Int2Short2(inV, out);
+            verifyResultsConvertInt2Short2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort2Int2Short2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt2Short2(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntShort args = new ArgumentsIntShort();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt2Short2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertInt3Short3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 3, 0x2a551a3babcd9c6fl, true, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            script.forEach_testConvertShort3Int3Short3(inV, out);
+            verifyResultsConvertInt3Short3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort3Int3Short3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort3Int3Short3(inV, out);
+            verifyResultsConvertInt3Short3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort3Int3Short3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt3Short3(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntShort args = new ArgumentsIntShort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt3Short3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertInt4Short4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 4, 0x2a56e356a1e8bd4dl, true, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            script.forEach_testConvertShort4Int4Short4(inV, out);
+            verifyResultsConvertInt4Short4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort4Int4Short4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort4Int4Short4(inV, out);
+            verifyResultsConvertInt4Short4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort4Int4Short4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt4Short4(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntShort args = new ArgumentsIntShort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt4Short4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUintShort {
+        public int inV;
+        public short out;
+    }
+
+    private void checkConvertUint2Short2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 2, 0xd1e10a6e48348812l, false, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            script.forEach_testConvertShort2Uint2Short2(inV, out);
+            verifyResultsConvertUint2Short2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort2Uint2Short2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort2Uint2Short2(inV, out);
+            verifyResultsConvertUint2Short2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort2Uint2Short2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint2Short2(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintShort args = new ArgumentsUintShort();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint2Short2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUint3Short3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 3, 0xd1e2d3893e4fa8f0l, false, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            script.forEach_testConvertShort3Uint3Short3(inV, out);
+            verifyResultsConvertUint3Short3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort3Uint3Short3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort3Uint3Short3(inV, out);
+            verifyResultsConvertUint3Short3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort3Uint3Short3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint3Short3(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintShort args = new ArgumentsUintShort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint3Short3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUint4Short4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 4, 0xd1e49ca4346ac9cel, false, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            script.forEach_testConvertShort4Uint4Short4(inV, out);
+            verifyResultsConvertUint4Short4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort4Uint4Short4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort4Uint4Short4(inV, out);
+            verifyResultsConvertUint4Short4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort4Uint4Short4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint4Short4(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintShort args = new ArgumentsUintShort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint4Short4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsFloatUshort {
+        public float inV;
+        public short out;
+    }
+
+    private void checkConvertFloat2Ushort2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x36e4b950b708416fl, 0.0000000000000000000e+00, 6.5535000000000000000e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            script.forEach_testConvertUshort2Float2Ushort2(inV, out);
+            verifyResultsConvertFloat2Ushort2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort2Float2Ushort2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort2Float2Ushort2(inV, out);
+            verifyResultsConvertFloat2Ushort2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort2Float2Ushort2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat2Ushort2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatUshort args = new ArgumentsFloatUshort();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat2Ushort2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertFloat3Ushort3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x373180d80d63d29bl, 0.0000000000000000000e+00, 6.5535000000000000000e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            script.forEach_testConvertUshort3Float3Ushort3(inV, out);
+            verifyResultsConvertFloat3Ushort3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort3Float3Ushort3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort3Float3Ushort3(inV, out);
+            verifyResultsConvertFloat3Ushort3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort3Float3Ushort3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat3Ushort3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatUshort args = new ArgumentsFloatUshort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat3Ushort3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertFloat4Ushort4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x377e485f63bf63c7l, 0.0000000000000000000e+00, 6.5535000000000000000e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            script.forEach_testConvertUshort4Float4Ushort4(inV, out);
+            verifyResultsConvertFloat4Ushort4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort4Float4Ushort4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort4Float4Ushort4(inV, out);
+            verifyResultsConvertFloat4Ushort4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort4Float4Ushort4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat4Ushort4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatUshort args = new ArgumentsFloatUshort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat4Ushort4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsCharUshort {
+        public byte inV;
+        public short out;
+    }
+
+    private void checkConvertChar2Ushort2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 2, 0xd88c0b0ed8f1eeafl, false, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            script.forEach_testConvertUshort2Char2Ushort2(inV, out);
+            verifyResultsConvertChar2Ushort2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort2Char2Ushort2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort2Char2Ushort2(inV, out);
+            verifyResultsConvertChar2Ushort2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort2Char2Ushort2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar2Ushort2(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharUshort args = new ArgumentsCharUshort();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar2Ushort2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertChar3Ushort3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 3, 0xd8d8d2962f4d7fdbl, false, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            script.forEach_testConvertUshort3Char3Ushort3(inV, out);
+            verifyResultsConvertChar3Ushort3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort3Char3Ushort3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort3Char3Ushort3(inV, out);
+            verifyResultsConvertChar3Ushort3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort3Char3Ushort3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar3Ushort3(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharUshort args = new ArgumentsCharUshort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar3Ushort3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertChar4Ushort4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 4, 0xd9259a1d85a91107l, false, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            script.forEach_testConvertUshort4Char4Ushort4(inV, out);
+            verifyResultsConvertChar4Ushort4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort4Char4Ushort4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort4Char4Ushort4(inV, out);
+            verifyResultsConvertChar4Ushort4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort4Char4Ushort4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar4Ushort4(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharUshort args = new ArgumentsCharUshort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar4Ushort4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUcharUshort {
+        public byte inV;
+        public short out;
+    }
+
+    private void checkConvertUchar2Ushort2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 2, 0x72b6c56063e3e68l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            script.forEach_testConvertUshort2Uchar2Ushort2(inV, out);
+            verifyResultsConvertUchar2Ushort2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort2Uchar2Ushort2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort2Uchar2Ushort2(inV, out);
+            verifyResultsConvertUchar2Ushort2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort2Uchar2Ushort2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar2Ushort2(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUshort args = new ArgumentsUcharUshort();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar2Ushort2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUchar3Ushort3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 3, 0x77833dd5c99cf94l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            script.forEach_testConvertUshort3Uchar3Ushort3(inV, out);
+            verifyResultsConvertUchar3Ushort3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort3Uchar3Ushort3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort3Uchar3Ushort3(inV, out);
+            verifyResultsConvertUchar3Ushort3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort3Uchar3Ushort3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar3Ushort3(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUshort args = new ArgumentsUcharUshort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar3Ushort3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUchar4Ushort4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 4, 0x7c4fb64b2f560c0l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            script.forEach_testConvertUshort4Uchar4Ushort4(inV, out);
+            verifyResultsConvertUchar4Ushort4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort4Uchar4Ushort4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort4Uchar4Ushort4(inV, out);
+            verifyResultsConvertUchar4Ushort4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort4Uchar4Ushort4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar4Ushort4(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUshort args = new ArgumentsUcharUshort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar4Ushort4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsShortUshort {
+        public short inV;
+        public short out;
+    }
+
+    private void checkConvertShort2Ushort2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 2, 0xfe0d269c7264c053l, false, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            script.forEach_testConvertUshort2Short2Ushort2(inV, out);
+            verifyResultsConvertShort2Ushort2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort2Short2Ushort2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort2Short2Ushort2(inV, out);
+            verifyResultsConvertShort2Ushort2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort2Short2Ushort2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort2Ushort2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortUshort args = new ArgumentsShortUshort();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort2Ushort2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertShort3Ushort3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 3, 0xfe59ee23c8c0517fl, false, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            script.forEach_testConvertUshort3Short3Ushort3(inV, out);
+            verifyResultsConvertShort3Ushort3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort3Short3Ushort3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort3Short3Ushort3(inV, out);
+            verifyResultsConvertShort3Ushort3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort3Short3Ushort3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort3Ushort3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortUshort args = new ArgumentsShortUshort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort3Ushort3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertShort4Ushort4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 4, 0xfea6b5ab1f1be2abl, false, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            script.forEach_testConvertUshort4Short4Ushort4(inV, out);
+            verifyResultsConvertShort4Ushort4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort4Short4Ushort4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort4Short4Ushort4(inV, out);
+            verifyResultsConvertShort4Ushort4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort4Short4Ushort4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort4Ushort4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortUshort args = new ArgumentsShortUshort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort4Ushort4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUshortUshort {
+        public short inV;
+        public short out;
+    }
+
+    private void checkConvertUshort2Ushort2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 2, 0xd2d27d910e362466l, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            script.forEach_testConvertUshort2Ushort2Ushort2(inV, out);
+            verifyResultsConvertUshort2Ushort2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort2Ushort2Ushort2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort2Ushort2Ushort2(inV, out);
+            verifyResultsConvertUshort2Ushort2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort2Ushort2Ushort2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort2Ushort2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUshort args = new ArgumentsUshortUshort();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort2Ushort2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUshort3Ushort3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 3, 0xd31f45186491b592l, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            script.forEach_testConvertUshort3Ushort3Ushort3(inV, out);
+            verifyResultsConvertUshort3Ushort3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort3Ushort3Ushort3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort3Ushort3Ushort3(inV, out);
+            verifyResultsConvertUshort3Ushort3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort3Ushort3Ushort3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort3Ushort3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUshort args = new ArgumentsUshortUshort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort3Ushort3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUshort4Ushort4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 4, 0xd36c0c9fbaed46bel, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            script.forEach_testConvertUshort4Ushort4Ushort4(inV, out);
+            verifyResultsConvertUshort4Ushort4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort4Ushort4Ushort4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort4Ushort4Ushort4(inV, out);
+            verifyResultsConvertUshort4Ushort4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort4Ushort4Ushort4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort4Ushort4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUshort args = new ArgumentsUshortUshort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort4Ushort4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsIntUshort {
+        public int inV;
+        public short out;
+    }
+
+    private void checkConvertInt2Ushort2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 2, 0x1c02a5e414378844l, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            script.forEach_testConvertUshort2Int2Ushort2(inV, out);
+            verifyResultsConvertInt2Ushort2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort2Int2Ushort2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort2Int2Ushort2(inV, out);
+            verifyResultsConvertInt2Ushort2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort2Int2Ushort2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt2Ushort2(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntUshort args = new ArgumentsIntUshort();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt2Ushort2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertInt3Ushort3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 3, 0x1c4f6d6b6a931970l, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            script.forEach_testConvertUshort3Int3Ushort3(inV, out);
+            verifyResultsConvertInt3Ushort3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort3Int3Ushort3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort3Int3Ushort3(inV, out);
+            verifyResultsConvertInt3Ushort3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort3Int3Ushort3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt3Ushort3(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntUshort args = new ArgumentsIntUshort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt3Ushort3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertInt4Ushort4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 4, 0x1c9c34f2c0eeaa9cl, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            script.forEach_testConvertUshort4Int4Ushort4(inV, out);
+            verifyResultsConvertInt4Ushort4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort4Int4Ushort4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort4Int4Ushort4(inV, out);
+            verifyResultsConvertInt4Ushort4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort4Int4Ushort4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt4Ushort4(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntUshort args = new ArgumentsIntUshort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt4Ushort4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUintUshort {
+        public int inV;
+        public short out;
+    }
+
+    private void checkConvertUint2Ushort2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 2, 0x40d0c5ebb00fa1efl, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            script.forEach_testConvertUshort2Uint2Ushort2(inV, out);
+            verifyResultsConvertUint2Ushort2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort2Uint2Ushort2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort2Uint2Ushort2(inV, out);
+            verifyResultsConvertUint2Ushort2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort2Uint2Ushort2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint2Ushort2(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUshort args = new ArgumentsUintUshort();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint2Ushort2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUint3Ushort3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 3, 0x411d8d73066b331bl, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            script.forEach_testConvertUshort3Uint3Ushort3(inV, out);
+            verifyResultsConvertUint3Ushort3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort3Uint3Ushort3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort3Uint3Ushort3(inV, out);
+            verifyResultsConvertUint3Ushort3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort3Uint3Ushort3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint3Ushort3(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUshort args = new ArgumentsUintUshort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint3Ushort3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUint4Ushort4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 4, 0x416a54fa5cc6c447l, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            script.forEach_testConvertUshort4Uint4Ushort4(inV, out);
+            verifyResultsConvertUint4Ushort4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort4Uint4Ushort4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort4Uint4Ushort4(inV, out);
+            verifyResultsConvertUint4Ushort4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort4Uint4Ushort4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint4Ushort4(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUshort args = new ArgumentsUintUshort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint4Ushort4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsFloatInt {
+        public float inV;
+        public int out;
+    }
+
+    private void checkConvertFloat2Int2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x8fb63fb7c069dd5dl, -2.1474835210000000000e+09, 2.1474835200000000000e+09);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            script.forEach_testConvertInt2Float2Int2(inV, out);
+            verifyResultsConvertFloat2Int2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt2Float2Int2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt2Float2Int2(inV, out);
+            verifyResultsConvertFloat2Int2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt2Float2Int2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat2Int2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatInt args = new ArgumentsFloatInt();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat2Int2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertFloat3Int3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x8fb63ff70a11ed93l, -2.1474835210000000000e+09, 2.1474835200000000000e+09);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            script.forEach_testConvertInt3Float3Int3(inV, out);
+            verifyResultsConvertFloat3Int3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt3Float3Int3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt3Float3Int3(inV, out);
+            verifyResultsConvertFloat3Int3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt3Float3Int3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat3Int3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatInt args = new ArgumentsFloatInt();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat3Int3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertFloat4Int4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x8fb6403653b9fdc9l, -2.1474835210000000000e+09, 2.1474835200000000000e+09);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            script.forEach_testConvertInt4Float4Int4(inV, out);
+            verifyResultsConvertFloat4Int4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt4Float4Int4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt4Float4Int4(inV, out);
+            verifyResultsConvertFloat4Int4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt4Float4Int4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat4Int4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatInt args = new ArgumentsFloatInt();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat4Int4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsCharInt {
+        public byte inV;
+        public int out;
+    }
+
+    private void checkConvertChar2Int2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 2, 0x880244ac94c6831dl, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            script.forEach_testConvertInt2Char2Int2(inV, out);
+            verifyResultsConvertChar2Int2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt2Char2Int2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt2Char2Int2(inV, out);
+            verifyResultsConvertChar2Int2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt2Char2Int2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar2Int2(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharInt args = new ArgumentsCharInt();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar2Int2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertChar3Int3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 3, 0x880244ebde6e9353l, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            script.forEach_testConvertInt3Char3Int3(inV, out);
+            verifyResultsConvertChar3Int3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt3Char3Int3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt3Char3Int3(inV, out);
+            verifyResultsConvertChar3Int3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt3Char3Int3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar3Int3(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharInt args = new ArgumentsCharInt();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar3Int3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertChar4Int4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 4, 0x8802452b2816a389l, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            script.forEach_testConvertInt4Char4Int4(inV, out);
+            verifyResultsConvertChar4Int4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt4Char4Int4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt4Char4Int4(inV, out);
+            verifyResultsConvertChar4Int4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt4Char4Int4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar4Int4(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharInt args = new ArgumentsCharInt();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar4Int4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUcharInt {
+        public byte inV;
+        public int out;
+    }
+
+    private void checkConvertUchar2Int2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 2, 0x97cffb96923aa720l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            script.forEach_testConvertInt2Uchar2Int2(inV, out);
+            verifyResultsConvertUchar2Int2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt2Uchar2Int2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt2Uchar2Int2(inV, out);
+            verifyResultsConvertUchar2Int2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt2Uchar2Int2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar2Int2(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharInt args = new ArgumentsUcharInt();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar2Int2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUchar3Int3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 3, 0x97cffbd5dbe2b756l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            script.forEach_testConvertInt3Uchar3Int3(inV, out);
+            verifyResultsConvertUchar3Int3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt3Uchar3Int3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt3Uchar3Int3(inV, out);
+            verifyResultsConvertUchar3Int3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt3Uchar3Int3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar3Int3(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharInt args = new ArgumentsUcharInt();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar3Int3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUchar4Int4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 4, 0x97cffc15258ac78cl, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            script.forEach_testConvertInt4Uchar4Int4(inV, out);
+            verifyResultsConvertUchar4Int4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt4Uchar4Int4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt4Uchar4Int4(inV, out);
+            verifyResultsConvertUchar4Int4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt4Uchar4Int4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar4Int4(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharInt args = new ArgumentsUcharInt();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar4Int4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsShortInt {
+        public short inV;
+        public int out;
+    }
+
+    private void checkConvertShort2Int2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 2, 0x85693203252a2d69l, true, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            script.forEach_testConvertInt2Short2Int2(inV, out);
+            verifyResultsConvertShort2Int2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt2Short2Int2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt2Short2Int2(inV, out);
+            verifyResultsConvertShort2Int2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt2Short2Int2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort2Int2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortInt args = new ArgumentsShortInt();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort2Int2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertShort3Int3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 3, 0x856932426ed23d9fl, true, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            script.forEach_testConvertInt3Short3Int3(inV, out);
+            verifyResultsConvertShort3Int3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt3Short3Int3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt3Short3Int3(inV, out);
+            verifyResultsConvertShort3Int3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt3Short3Int3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort3Int3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortInt args = new ArgumentsShortInt();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort3Int3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertShort4Int4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 4, 0x85693281b87a4dd5l, true, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            script.forEach_testConvertInt4Short4Int4(inV, out);
+            verifyResultsConvertShort4Int4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt4Short4Int4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt4Short4Int4(inV, out);
+            verifyResultsConvertShort4Int4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt4Short4Int4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort4Int4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortInt args = new ArgumentsShortInt();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort4Int4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUshortInt {
+        public short inV;
+        public int out;
+    }
+
+    private void checkConvertUshort2Int2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 2, 0x2cf6eb50b7ac39eal, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            script.forEach_testConvertInt2Ushort2Int2(inV, out);
+            verifyResultsConvertUshort2Int2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt2Ushort2Int2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt2Ushort2Int2(inV, out);
+            verifyResultsConvertUshort2Int2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt2Ushort2Int2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort2Int2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortInt args = new ArgumentsUshortInt();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort2Int2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUshort3Int3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 3, 0x2cf6eb9001544a20l, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            script.forEach_testConvertInt3Ushort3Int3(inV, out);
+            verifyResultsConvertUshort3Int3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt3Ushort3Int3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt3Ushort3Int3(inV, out);
+            verifyResultsConvertUshort3Int3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt3Ushort3Int3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort3Int3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortInt args = new ArgumentsUshortInt();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort3Int3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUshort4Int4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 4, 0x2cf6ebcf4afc5a56l, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            script.forEach_testConvertInt4Ushort4Int4(inV, out);
+            verifyResultsConvertUshort4Int4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt4Ushort4Int4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt4Ushort4Int4(inV, out);
+            verifyResultsConvertUshort4Int4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt4Ushort4Int4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort4Int4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortInt args = new ArgumentsUshortInt();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort4Int4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsIntInt {
+        public int inV;
+        public int out;
+    }
+
+    private void checkConvertInt2Int2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 2, 0x501d84049a42354l, true, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            script.forEach_testConvertInt2Int2Int2(inV, out);
+            verifyResultsConvertInt2Int2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt2Int2Int2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt2Int2Int2(inV, out);
+            verifyResultsConvertInt2Int2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt2Int2Int2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt2Int2(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntInt args = new ArgumentsIntInt();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt2Int2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertInt3Int3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 3, 0x501d87f934c338al, true, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            script.forEach_testConvertInt3Int3Int3(inV, out);
+            verifyResultsConvertInt3Int3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt3Int3Int3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt3Int3Int3(inV, out);
+            verifyResultsConvertInt3Int3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt3Int3Int3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt3Int3(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntInt args = new ArgumentsIntInt();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt3Int3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertInt4Int4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 4, 0x501d8bedcf443c0l, true, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            script.forEach_testConvertInt4Int4Int4(inV, out);
+            verifyResultsConvertInt4Int4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt4Int4Int4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt4Int4Int4(inV, out);
+            verifyResultsConvertInt4Int4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt4Int4Int4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt4Int4(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntInt args = new ArgumentsIntInt();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt4Int4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUintInt {
+        public int inV;
+        public int out;
+    }
+
+    private void checkConvertUint2Int2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 2, 0x70899b043daccaddl, false, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            script.forEach_testConvertInt2Uint2Int2(inV, out);
+            verifyResultsConvertUint2Int2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt2Uint2Int2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt2Uint2Int2(inV, out);
+            verifyResultsConvertUint2Int2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt2Uint2Int2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint2Int2(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintInt args = new ArgumentsUintInt();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint2Int2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUint3Int3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 3, 0x70899b438754db13l, false, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            script.forEach_testConvertInt3Uint3Int3(inV, out);
+            verifyResultsConvertUint3Int3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt3Uint3Int3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt3Uint3Int3(inV, out);
+            verifyResultsConvertUint3Int3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt3Uint3Int3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint3Int3(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintInt args = new ArgumentsUintInt();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint3Int3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUint4Int4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 4, 0x70899b82d0fceb49l, false, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            script.forEach_testConvertInt4Uint4Int4(inV, out);
+            verifyResultsConvertUint4Int4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt4Uint4Int4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt4Uint4Int4(inV, out);
+            verifyResultsConvertUint4Int4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt4Uint4Int4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint4Int4(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintInt args = new ArgumentsUintInt();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint4Int4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsFloatUint {
+        public float inV;
+        public int out;
+    }
+
+    private void checkConvertFloat2Uint2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x239cb6cd424dca22l, 0.0000000000000000000e+00, 4.2949670400000000000e+09);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            script.forEach_testConvertUint2Float2Uint2(inV, out);
+            verifyResultsConvertFloat2Uint2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint2Float2Uint2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint2Float2Uint2(inV, out);
+            verifyResultsConvertFloat2Uint2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint2Float2Uint2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat2Uint2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatUint args = new ArgumentsFloatUint();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat2Uint2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertFloat3Uint3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x239cc16ea1558f16l, 0.0000000000000000000e+00, 4.2949670400000000000e+09);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            script.forEach_testConvertUint3Float3Uint3(inV, out);
+            verifyResultsConvertFloat3Uint3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint3Float3Uint3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint3Float3Uint3(inV, out);
+            verifyResultsConvertFloat3Uint3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint3Float3Uint3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat3Uint3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatUint args = new ArgumentsFloatUint();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat3Uint3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertFloat4Uint4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x239ccc10005d540al, 0.0000000000000000000e+00, 4.2949670400000000000e+09);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            script.forEach_testConvertUint4Float4Uint4(inV, out);
+            verifyResultsConvertFloat4Uint4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint4Float4Uint4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint4Float4Uint4(inV, out);
+            verifyResultsConvertFloat4Uint4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint4Float4Uint4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat4Uint4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatUint args = new ArgumentsFloatUint();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat4Uint4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsCharUint {
+        public byte inV;
+        public int out;
+    }
+
+    private void checkConvertChar2Uint2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 2, 0xd8618beceddda162l, false, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            script.forEach_testConvertUint2Char2Uint2(inV, out);
+            verifyResultsConvertChar2Uint2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint2Char2Uint2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint2Char2Uint2(inV, out);
+            verifyResultsConvertChar2Uint2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint2Char2Uint2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar2Uint2(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharUint args = new ArgumentsCharUint();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar2Uint2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertChar3Uint3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 3, 0xd861968e4ce56656l, false, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            script.forEach_testConvertUint3Char3Uint3(inV, out);
+            verifyResultsConvertChar3Uint3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint3Char3Uint3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint3Char3Uint3(inV, out);
+            verifyResultsConvertChar3Uint3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint3Char3Uint3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar3Uint3(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharUint args = new ArgumentsCharUint();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar3Uint3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertChar4Uint4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 4, 0xd861a12fabed2b4al, false, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            script.forEach_testConvertUint4Char4Uint4(inV, out);
+            verifyResultsConvertChar4Uint4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint4Char4Uint4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint4Char4Uint4(inV, out);
+            verifyResultsConvertChar4Uint4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint4Char4Uint4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar4Uint4(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharUint args = new ArgumentsCharUint();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar4Uint4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUcharUint {
+        public byte inV;
+        public int out;
+    }
+
+    private void checkConvertUchar2Uint2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 2, 0x7fef453a805fade3l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            script.forEach_testConvertUint2Uchar2Uint2(inV, out);
+            verifyResultsConvertUchar2Uint2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint2Uchar2Uint2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint2Uchar2Uint2(inV, out);
+            verifyResultsConvertUchar2Uint2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint2Uchar2Uint2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar2Uint2(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUint args = new ArgumentsUcharUint();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar2Uint2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUchar3Uint3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 3, 0x7fef4fdbdf6772d7l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            script.forEach_testConvertUint3Uchar3Uint3(inV, out);
+            verifyResultsConvertUchar3Uint3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint3Uchar3Uint3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint3Uchar3Uint3(inV, out);
+            verifyResultsConvertUchar3Uint3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint3Uchar3Uint3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar3Uint3(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUint args = new ArgumentsUcharUint();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar3Uint3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUchar4Uint4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 4, 0x7fef5a7d3e6f37cbl, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            script.forEach_testConvertUint4Uchar4Uint4(inV, out);
+            verifyResultsConvertUchar4Uint4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint4Uchar4Uint4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint4Uchar4Uint4(inV, out);
+            verifyResultsConvertUchar4Uint4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint4Uchar4Uint4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar4Uint4(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUint args = new ArgumentsUcharUint();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar4Uint4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsShortUint {
+        public short inV;
+        public int out;
+    }
+
+    private void checkConvertShort2Uint2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 2, 0x68ab69772e9b3c26l, false, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            script.forEach_testConvertUint2Short2Uint2(inV, out);
+            verifyResultsConvertShort2Uint2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint2Short2Uint2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint2Short2Uint2(inV, out);
+            verifyResultsConvertShort2Uint2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint2Short2Uint2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort2Uint2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortUint args = new ArgumentsShortUint();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort2Uint2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertShort3Uint3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 3, 0x68ab74188da3011al, false, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            script.forEach_testConvertUint3Short3Uint3(inV, out);
+            verifyResultsConvertShort3Uint3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint3Short3Uint3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint3Short3Uint3(inV, out);
+            verifyResultsConvertShort3Uint3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint3Short3Uint3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort3Uint3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortUint args = new ArgumentsShortUint();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort3Uint3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertShort4Uint4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 4, 0x68ab7eb9ecaac60el, false, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            script.forEach_testConvertUint4Short4Uint4(inV, out);
+            verifyResultsConvertShort4Uint4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint4Short4Uint4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint4Short4Uint4(inV, out);
+            verifyResultsConvertShort4Uint4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint4Short4Uint4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort4Uint4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortUint args = new ArgumentsShortUint();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort4Uint4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUshortUint {
+        public short inV;
+        public int out;
+    }
+
+    private void checkConvertUshort2Uint2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 2, 0x8d79897eca7355d1l, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            script.forEach_testConvertUint2Ushort2Uint2(inV, out);
+            verifyResultsConvertUshort2Uint2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint2Ushort2Uint2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint2Ushort2Uint2(inV, out);
+            verifyResultsConvertUshort2Uint2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint2Ushort2Uint2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort2Uint2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUint args = new ArgumentsUshortUint();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort2Uint2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUshort3Uint3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 3, 0x8d799420297b1ac5l, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            script.forEach_testConvertUint3Ushort3Uint3(inV, out);
+            verifyResultsConvertUshort3Uint3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint3Ushort3Uint3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint3Ushort3Uint3(inV, out);
+            verifyResultsConvertUshort3Uint3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint3Ushort3Uint3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort3Uint3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUint args = new ArgumentsUshortUint();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort3Uint3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUshort4Uint4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 4, 0x8d799ec18882dfb9l, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            script.forEach_testConvertUint4Ushort4Uint4(inV, out);
+            verifyResultsConvertUshort4Uint4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint4Ushort4Uint4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint4Ushort4Uint4(inV, out);
+            verifyResultsConvertUshort4Uint4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint4Ushort4Uint4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort4Uint4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUint args = new ArgumentsUshortUint();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort4Uint4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsIntUint {
+        public int inV;
+        public int out;
+    }
+
+    private void checkConvertInt2Uint2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 2, 0xd74f55bc4f178a9fl, false, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            script.forEach_testConvertUint2Int2Uint2(inV, out);
+            verifyResultsConvertInt2Uint2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint2Int2Uint2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint2Int2Uint2(inV, out);
+            verifyResultsConvertInt2Uint2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint2Int2Uint2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt2Uint2(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntUint args = new ArgumentsIntUint();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt2Uint2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertInt3Uint3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 3, 0xd74f605dae1f4f93l, false, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            script.forEach_testConvertUint3Int3Uint3(inV, out);
+            verifyResultsConvertInt3Uint3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint3Int3Uint3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint3Int3Uint3(inV, out);
+            verifyResultsConvertInt3Uint3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint3Int3Uint3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt3Uint3(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntUint args = new ArgumentsIntUint();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt3Uint3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertInt4Uint4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 4, 0xd74f6aff0d271487l, false, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            script.forEach_testConvertUint4Int4Uint4(inV, out);
+            verifyResultsConvertInt4Uint4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint4Int4Uint4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint4Int4Uint4(inV, out);
+            verifyResultsConvertInt4Uint4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint4Int4Uint4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt4Uint4(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntUint args = new ArgumentsIntUint();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt4Uint4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUintUint {
+        public int inV;
+        public int out;
+    }
+
+    private void checkConvertUint2Uint2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 2, 0xe71d0ca64c8baea2l, false, 32);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            script.forEach_testConvertUint2Uint2Uint2(inV, out);
+            verifyResultsConvertUint2Uint2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint2Uint2Uint2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint2Uint2Uint2(inV, out);
+            verifyResultsConvertUint2Uint2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint2Uint2Uint2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint2Uint2(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUint args = new ArgumentsUintUint();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint2Uint2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUint3Uint3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 3, 0xe71d1747ab937396l, false, 32);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            script.forEach_testConvertUint3Uint3Uint3(inV, out);
+            verifyResultsConvertUint3Uint3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint3Uint3Uint3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint3Uint3Uint3(inV, out);
+            verifyResultsConvertUint3Uint3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint3Uint3Uint3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint3Uint3(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUint args = new ArgumentsUintUint();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint3Uint3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUint4Uint4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 4, 0xe71d21e90a9b388al, false, 32);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            script.forEach_testConvertUint4Uint4Uint4(inV, out);
+            verifyResultsConvertUint4Uint4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint4Uint4Uint4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint4Uint4Uint4(inV, out);
+            verifyResultsConvertUint4Uint4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint4Uint4Uint4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint4Uint4(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUint args = new ArgumentsUintUint();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint4Uint4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsDoubleDouble {
+        public double inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertDouble2Double2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 2, 0x345b4a823902786el, -8.5390423905960001625e+307, 8.5390423905960001625e+307);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 2), INPUTSIZE);
+            script.forEach_testConvertDouble2Double2Double2(inV, out);
+            verifyResultsConvertDouble2Double2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble2Double2Double2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble2Double2Double2(inV, out);
+            verifyResultsConvertDouble2Double2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble2Double2Double2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble2Double2(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleDouble args = new ArgumentsDoubleDouble();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 2 + j], Double.doubleToRawLongBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble2Double2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertDouble3Double3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 3, 0x34a812098f5e099al, -8.5390423905960001625e+307, 8.5390423905960001625e+307);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 3), INPUTSIZE);
+            script.forEach_testConvertDouble3Double3Double3(inV, out);
+            verifyResultsConvertDouble3Double3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble3Double3Double3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble3Double3Double3(inV, out);
+            verifyResultsConvertDouble3Double3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble3Double3Double3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble3Double3(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleDouble args = new ArgumentsDoubleDouble();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 4 + j], Double.doubleToRawLongBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble3Double3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertDouble4Double4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 4, 0x34f4d990e5b99ac6l, -8.5390423905960001625e+307, 8.5390423905960001625e+307);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 4), INPUTSIZE);
+            script.forEach_testConvertDouble4Double4Double4(inV, out);
+            verifyResultsConvertDouble4Double4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble4Double4Double4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble4Double4Double4(inV, out);
+            verifyResultsConvertDouble4Double4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble4Double4Double4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble4Double4(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleDouble args = new ArgumentsDoubleDouble();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 4 + j], Double.doubleToRawLongBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble4Double4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsLongDouble {
+        public long inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertLong2Double2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 2, 0x7b7807124c70299bl, true, 63);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 2), INPUTSIZE);
+            script.forEach_testConvertDouble2Long2Double2(inV, out);
+            verifyResultsConvertLong2Double2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble2Long2Double2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble2Long2Double2(inV, out);
+            verifyResultsConvertLong2Double2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble2Long2Double2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong2Double2(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongDouble args = new ArgumentsLongDouble();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 2 + j], Double.doubleToRawLongBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong2Double2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertLong3Double3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 3, 0x7bc4ce99a2cbbac7l, true, 63);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 3), INPUTSIZE);
+            script.forEach_testConvertDouble3Long3Double3(inV, out);
+            verifyResultsConvertLong3Double3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble3Long3Double3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble3Long3Double3(inV, out);
+            verifyResultsConvertLong3Double3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble3Long3Double3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong3Double3(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongDouble args = new ArgumentsLongDouble();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 4 + j], Double.doubleToRawLongBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong3Double3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertLong4Double4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 4, 0x7c119620f9274bf3l, true, 63);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 4), INPUTSIZE);
+            script.forEach_testConvertDouble4Long4Double4(inV, out);
+            verifyResultsConvertLong4Double4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble4Long4Double4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble4Long4Double4(inV, out);
+            verifyResultsConvertLong4Double4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble4Long4Double4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong4Double4(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongDouble args = new ArgumentsLongDouble();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 4 + j], Double.doubleToRawLongBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong4Double4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUlongDouble {
+        public long inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertUlong2Double2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 2, 0xaa17685979bc7954l, false, 64);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 2), INPUTSIZE);
+            script.forEach_testConvertDouble2Ulong2Double2(inV, out);
+            verifyResultsConvertUlong2Double2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble2Ulong2Double2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble2Ulong2Double2(inV, out);
+            verifyResultsConvertUlong2Double2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble2Ulong2Double2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong2Double2(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongDouble args = new ArgumentsUlongDouble();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 2 + j], Double.doubleToRawLongBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong2Double2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUlong3Double3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 3, 0xaa642fe0d0180a80l, false, 64);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 3), INPUTSIZE);
+            script.forEach_testConvertDouble3Ulong3Double3(inV, out);
+            verifyResultsConvertUlong3Double3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble3Ulong3Double3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble3Ulong3Double3(inV, out);
+            verifyResultsConvertUlong3Double3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble3Ulong3Double3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong3Double3(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongDouble args = new ArgumentsUlongDouble();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 4 + j], Double.doubleToRawLongBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong3Double3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUlong4Double4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 4, 0xaab0f76826739bacl, false, 64);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 4), INPUTSIZE);
+            script.forEach_testConvertDouble4Ulong4Double4(inV, out);
+            verifyResultsConvertUlong4Double4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble4Ulong4Double4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble4Ulong4Double4(inV, out);
+            verifyResultsConvertUlong4Double4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble4Ulong4Double4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong4Double4(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongDouble args = new ArgumentsUlongDouble();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 4 + j], Double.doubleToRawLongBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong4Double4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsDoubleLong {
+        public double inV;
+        public long out;
+    }
+
+    private void checkConvertDouble2Long2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 2, 0xcbf84dc0430cbe95l, -9.2233720368547747840e+18, 9.2233720368547747840e+18);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            script.forEach_testConvertLong2Double2Long2(inV, out);
+            verifyResultsConvertDouble2Long2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong2Double2Long2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong2Double2Long2(inV, out);
+            verifyResultsConvertDouble2Long2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong2Double2Long2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble2Long2(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleLong args = new ArgumentsDoubleLong();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble2Long2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertDouble3Long3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 3, 0xcbf85861a2148389l, -9.2233720368547747840e+18, 9.2233720368547747840e+18);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            script.forEach_testConvertLong3Double3Long3(inV, out);
+            verifyResultsConvertDouble3Long3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong3Double3Long3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong3Double3Long3(inV, out);
+            verifyResultsConvertDouble3Long3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong3Double3Long3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble3Long3(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleLong args = new ArgumentsDoubleLong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble3Long3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertDouble4Long4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 4, 0xcbf86303011c487dl, -9.2233720368547747840e+18, 9.2233720368547747840e+18);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            script.forEach_testConvertLong4Double4Long4(inV, out);
+            verifyResultsConvertDouble4Long4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong4Double4Long4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong4Double4Long4(inV, out);
+            verifyResultsConvertDouble4Long4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong4Double4Long4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble4Long4(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleLong args = new ArgumentsDoubleLong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble4Long4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsLongLong {
+        public long inV;
+        public long out;
+    }
+
+    private void checkConvertLong2Long2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 2, 0xb570c607c81d242al, true, 63);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            script.forEach_testConvertLong2Long2Long2(inV, out);
+            verifyResultsConvertLong2Long2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong2Long2Long2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong2Long2Long2(inV, out);
+            verifyResultsConvertLong2Long2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong2Long2Long2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong2Long2(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongLong args = new ArgumentsLongLong();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong2Long2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertLong3Long3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 3, 0xb570d0a92724e91el, true, 63);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            script.forEach_testConvertLong3Long3Long3(inV, out);
+            verifyResultsConvertLong3Long3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong3Long3Long3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong3Long3Long3(inV, out);
+            verifyResultsConvertLong3Long3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong3Long3Long3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong3Long3(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongLong args = new ArgumentsLongLong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong3Long3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertLong4Long4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 4, 0xb570db4a862cae12l, true, 63);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            script.forEach_testConvertLong4Long4Long4(inV, out);
+            verifyResultsConvertLong4Long4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong4Long4Long4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong4Long4Long4(inV, out);
+            verifyResultsConvertLong4Long4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong4Long4Long4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong4Long4(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongLong args = new ArgumentsLongLong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong4Long4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUlongLong {
+        public long inV;
+        public long out;
+    }
+
+    private void checkConvertUlong2Long2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 2, 0x5cfe7f555a9f30abl, false, 63);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            script.forEach_testConvertLong2Ulong2Long2(inV, out);
+            verifyResultsConvertUlong2Long2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong2Ulong2Long2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong2Ulong2Long2(inV, out);
+            verifyResultsConvertUlong2Long2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong2Ulong2Long2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong2Long2(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongLong args = new ArgumentsUlongLong();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong2Long2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUlong3Long3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 3, 0x5cfe89f6b9a6f59fl, false, 63);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            script.forEach_testConvertLong3Ulong3Long3(inV, out);
+            verifyResultsConvertUlong3Long3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong3Ulong3Long3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong3Ulong3Long3(inV, out);
+            verifyResultsConvertUlong3Long3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong3Ulong3Long3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong3Long3(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongLong args = new ArgumentsUlongLong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong3Long3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUlong4Long4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 4, 0x5cfe949818aeba93l, false, 63);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            script.forEach_testConvertLong4Ulong4Long4(inV, out);
+            verifyResultsConvertUlong4Long4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong4Ulong4Long4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong4Ulong4Long4(inV, out);
+            verifyResultsConvertUlong4Long4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong4Ulong4Long4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong4Long4(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongLong args = new ArgumentsUlongLong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong4Long4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsDoubleUlong {
+        public double inV;
+        public long out;
+    }
+
+    private void checkConvertDouble2Ulong2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 2, 0x42b56e3b7e12ff5el, 0.0000000000000000000e+00, 1.8446744073709549568e+19);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            script.forEach_testConvertUlong2Double2Ulong2(inV, out);
+            verifyResultsConvertDouble2Ulong2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong2Double2Ulong2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong2Double2Ulong2(inV, out);
+            verifyResultsConvertDouble2Ulong2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong2Double2Ulong2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble2Ulong2(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleUlong args = new ArgumentsDoubleUlong();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble2Ulong2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertDouble3Ulong3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 3, 0x42b73756742e203cl, 0.0000000000000000000e+00, 1.8446744073709549568e+19);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            script.forEach_testConvertUlong3Double3Ulong3(inV, out);
+            verifyResultsConvertDouble3Ulong3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong3Double3Ulong3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong3Double3Ulong3(inV, out);
+            verifyResultsConvertDouble3Ulong3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong3Double3Ulong3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble3Ulong3(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleUlong args = new ArgumentsDoubleUlong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble3Ulong3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertDouble4Ulong4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 4, 0x42b900716a49411al, 0.0000000000000000000e+00, 1.8446744073709549568e+19);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            script.forEach_testConvertUlong4Double4Ulong4(inV, out);
+            verifyResultsConvertDouble4Ulong4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong4Double4Ulong4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong4Double4Ulong4(inV, out);
+            verifyResultsConvertDouble4Ulong4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong4Double4Ulong4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble4Ulong4(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleUlong args = new ArgumentsDoubleUlong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble4Ulong4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsLongUlong {
+        public long inV;
+        public long out;
+    }
+
+    private void checkConvertLong2Ulong2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 2, 0x79f1a23ed7d40f65l, false, 63);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            script.forEach_testConvertUlong2Long2Ulong2(inV, out);
+            verifyResultsConvertLong2Ulong2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong2Long2Ulong2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong2Long2Ulong2(inV, out);
+            verifyResultsConvertLong2Ulong2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong2Long2Ulong2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong2Ulong2(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongUlong args = new ArgumentsLongUlong();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong2Ulong2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertLong3Ulong3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 3, 0x79f36b59cdef3043l, false, 63);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            script.forEach_testConvertUlong3Long3Ulong3(inV, out);
+            verifyResultsConvertLong3Ulong3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong3Long3Ulong3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong3Long3Ulong3(inV, out);
+            verifyResultsConvertLong3Ulong3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong3Long3Ulong3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong3Ulong3(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongUlong args = new ArgumentsLongUlong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong3Ulong3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertLong4Ulong4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 4, 0x79f53474c40a5121l, false, 63);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            script.forEach_testConvertUlong4Long4Ulong4(inV, out);
+            verifyResultsConvertLong4Ulong4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong4Long4Ulong4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong4Long4Ulong4(inV, out);
+            verifyResultsConvertLong4Ulong4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong4Long4Ulong4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong4Ulong4(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongUlong args = new ArgumentsLongUlong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong4Ulong4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUlongUlong {
+        public long inV;
+        public long out;
+    }
+
+    private void checkConvertUlong2Ulong2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 2, 0x9ebfc24673ac2910l, false, 64);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            script.forEach_testConvertUlong2Ulong2Ulong2(inV, out);
+            verifyResultsConvertUlong2Ulong2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong2Ulong2Ulong2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong2Ulong2Ulong2(inV, out);
+            verifyResultsConvertUlong2Ulong2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong2Ulong2Ulong2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong2Ulong2(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUlong args = new ArgumentsUlongUlong();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong2Ulong2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUlong3Ulong3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 3, 0x9ec18b6169c749eel, false, 64);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            script.forEach_testConvertUlong3Ulong3Ulong3(inV, out);
+            verifyResultsConvertUlong3Ulong3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong3Ulong3Ulong3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong3Ulong3Ulong3(inV, out);
+            verifyResultsConvertUlong3Ulong3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong3Ulong3Ulong3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong3Ulong3(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUlong args = new ArgumentsUlongUlong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong3Ulong3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUlong4Ulong4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 4, 0x9ec3547c5fe26accl, false, 64);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            script.forEach_testConvertUlong4Ulong4Ulong4(inV, out);
+            verifyResultsConvertUlong4Ulong4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong4Ulong4Ulong4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong4Ulong4Ulong4(inV, out);
+            verifyResultsConvertUlong4Ulong4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong4Ulong4Ulong4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong4Ulong4(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUlong args = new ArgumentsUlongUlong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong4Ulong4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsDoubleFloat {
+        public double inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertDouble2Float2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 2, 0x42b4cec67d6d9a2dl, -1.6163412428744576259e+38, 1.6163412428744576259e+38);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testConvertFloat2Double2Float2(inV, out);
+            verifyResultsConvertDouble2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat2Double2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat2Double2Float2(inV, out);
+            verifyResultsConvertDouble2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat2Double2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleFloat args = new ArgumentsDoubleFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertDouble3Float3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 3, 0x42b697e17388bb0bl, -1.6163412428744576259e+38, 1.6163412428744576259e+38);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testConvertFloat3Double3Float3(inV, out);
+            verifyResultsConvertDouble3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat3Double3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat3Double3Float3(inV, out);
+            verifyResultsConvertDouble3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat3Double3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleFloat args = new ArgumentsDoubleFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertDouble4Float4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 4, 0x42b860fc69a3dbe9l, -1.6163412428744576259e+38, 1.6163412428744576259e+38);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testConvertFloat4Double4Float4(inV, out);
+            verifyResultsConvertDouble4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat4Double4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat4Double4Float4(inV, out);
+            verifyResultsConvertDouble4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat4Double4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleFloat args = new ArgumentsDoubleFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsLongFloat {
+        public long inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertLong2Float2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 2, 0x79f102c9d72eaa34l, true, 63);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testConvertFloat2Long2Float2(inV, out);
+            verifyResultsConvertLong2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat2Long2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat2Long2Float2(inV, out);
+            verifyResultsConvertLong2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat2Long2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongFloat args = new ArgumentsLongFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertLong3Float3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 3, 0x79f2cbe4cd49cb12l, true, 63);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testConvertFloat3Long3Float3(inV, out);
+            verifyResultsConvertLong3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat3Long3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat3Long3Float3(inV, out);
+            verifyResultsConvertLong3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat3Long3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongFloat args = new ArgumentsLongFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertLong4Float4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 4, 0x79f494ffc364ebf0l, true, 63);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testConvertFloat4Long4Float4(inV, out);
+            verifyResultsConvertLong4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat4Long4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat4Long4Float4(inV, out);
+            verifyResultsConvertLong4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat4Long4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongFloat args = new ArgumentsLongFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUlongFloat {
+        public long inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertUlong2Float2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 2, 0x9ebf22d17306c3dfl, false, 64);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testConvertFloat2Ulong2Float2(inV, out);
+            verifyResultsConvertUlong2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat2Ulong2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat2Ulong2Float2(inV, out);
+            verifyResultsConvertUlong2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat2Ulong2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongFloat args = new ArgumentsUlongFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUlong3Float3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 3, 0x9ec0ebec6921e4bdl, false, 64);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testConvertFloat3Ulong3Float3(inV, out);
+            verifyResultsConvertUlong3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat3Ulong3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat3Ulong3Float3(inV, out);
+            verifyResultsConvertUlong3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat3Ulong3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongFloat args = new ArgumentsUlongFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUlong4Float4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 4, 0x9ec2b5075f3d059bl, false, 64);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testConvertFloat4Ulong4Float4(inV, out);
+            verifyResultsConvertUlong4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat4Ulong4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat4Ulong4Float4(inV, out);
+            verifyResultsConvertUlong4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat4Ulong4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongFloat args = new ArgumentsUlongFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsDoubleChar {
+        public double inV;
+        public byte out;
+    }
+
+    private void checkConvertDouble2Char2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 2, 0xcbf84b7bef094a17l, -1.2800000000000000000e+02, 1.2700000000000000000e+02);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            script.forEach_testConvertChar2Double2Char2(inV, out);
+            verifyResultsConvertDouble2Char2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar2Double2Char2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar2Double2Char2(inV, out);
+            verifyResultsConvertDouble2Char2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar2Double2Char2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble2Char2(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleChar args = new ArgumentsDoubleChar();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble2Char2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertDouble3Char3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 3, 0xcbf8561d4e110f0bl, -1.2800000000000000000e+02, 1.2700000000000000000e+02);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            script.forEach_testConvertChar3Double3Char3(inV, out);
+            verifyResultsConvertDouble3Char3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar3Double3Char3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar3Double3Char3(inV, out);
+            verifyResultsConvertDouble3Char3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar3Double3Char3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble3Char3(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleChar args = new ArgumentsDoubleChar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble3Char3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertDouble4Char4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 4, 0xcbf860bead18d3ffl, -1.2800000000000000000e+02, 1.2700000000000000000e+02);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            script.forEach_testConvertChar4Double4Char4(inV, out);
+            verifyResultsConvertDouble4Char4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar4Double4Char4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar4Double4Char4(inV, out);
+            verifyResultsConvertDouble4Char4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar4Double4Char4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble4Char4(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleChar args = new ArgumentsDoubleChar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble4Char4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsLongChar {
+        public long inV;
+        public byte out;
+    }
+
+    private void checkConvertLong2Char2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 2, 0xb570c3c37419afacl, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            script.forEach_testConvertChar2Long2Char2(inV, out);
+            verifyResultsConvertLong2Char2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar2Long2Char2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar2Long2Char2(inV, out);
+            verifyResultsConvertLong2Char2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar2Long2Char2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong2Char2(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongChar args = new ArgumentsLongChar();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong2Char2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertLong3Char3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 3, 0xb570ce64d32174a0l, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            script.forEach_testConvertChar3Long3Char3(inV, out);
+            verifyResultsConvertLong3Char3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar3Long3Char3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar3Long3Char3(inV, out);
+            verifyResultsConvertLong3Char3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar3Long3Char3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong3Char3(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongChar args = new ArgumentsLongChar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong3Char3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertLong4Char4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 4, 0xb570d90632293994l, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            script.forEach_testConvertChar4Long4Char4(inV, out);
+            verifyResultsConvertLong4Char4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar4Long4Char4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar4Long4Char4(inV, out);
+            verifyResultsConvertLong4Char4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar4Long4Char4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong4Char4(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongChar args = new ArgumentsLongChar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong4Char4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUlongChar {
+        public long inV;
+        public byte out;
+    }
+
+    private void checkConvertUlong2Char2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 2, 0x5cfe7d11069bbc2dl, false, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            script.forEach_testConvertChar2Ulong2Char2(inV, out);
+            verifyResultsConvertUlong2Char2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar2Ulong2Char2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar2Ulong2Char2(inV, out);
+            verifyResultsConvertUlong2Char2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar2Ulong2Char2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong2Char2(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongChar args = new ArgumentsUlongChar();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong2Char2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUlong3Char3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 3, 0x5cfe87b265a38121l, false, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            script.forEach_testConvertChar3Ulong3Char3(inV, out);
+            verifyResultsConvertUlong3Char3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar3Ulong3Char3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar3Ulong3Char3(inV, out);
+            verifyResultsConvertUlong3Char3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar3Ulong3Char3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong3Char3(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongChar args = new ArgumentsUlongChar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong3Char3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUlong4Char4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 4, 0x5cfe9253c4ab4615l, false, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            script.forEach_testConvertChar4Ulong4Char4(inV, out);
+            verifyResultsConvertUlong4Char4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar4Ulong4Char4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar4Ulong4Char4(inV, out);
+            verifyResultsConvertUlong4Char4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar4Ulong4Char4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong4Char4(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongChar args = new ArgumentsUlongChar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong4Char4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsDoubleUchar {
+        public double inV;
+        public byte out;
+    }
+
+    private void checkConvertDouble2Uchar2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 2, 0x42b56bf72a0f8ae0l, 0.0000000000000000000e+00, 2.5500000000000000000e+02);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            script.forEach_testConvertUchar2Double2Uchar2(inV, out);
+            verifyResultsConvertDouble2Uchar2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar2Double2Uchar2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar2Double2Uchar2(inV, out);
+            verifyResultsConvertDouble2Uchar2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar2Double2Uchar2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble2Uchar2(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleUchar args = new ArgumentsDoubleUchar();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble2Uchar2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertDouble3Uchar3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 3, 0x42b73512202aabbel, 0.0000000000000000000e+00, 2.5500000000000000000e+02);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            script.forEach_testConvertUchar3Double3Uchar3(inV, out);
+            verifyResultsConvertDouble3Uchar3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar3Double3Uchar3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar3Double3Uchar3(inV, out);
+            verifyResultsConvertDouble3Uchar3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar3Double3Uchar3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble3Uchar3(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleUchar args = new ArgumentsDoubleUchar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble3Uchar3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertDouble4Uchar4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 4, 0x42b8fe2d1645cc9cl, 0.0000000000000000000e+00, 2.5500000000000000000e+02);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            script.forEach_testConvertUchar4Double4Uchar4(inV, out);
+            verifyResultsConvertDouble4Uchar4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar4Double4Uchar4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar4Double4Uchar4(inV, out);
+            verifyResultsConvertDouble4Uchar4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar4Double4Uchar4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble4Uchar4(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleUchar args = new ArgumentsDoubleUchar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble4Uchar4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsLongUchar {
+        public long inV;
+        public byte out;
+    }
+
+    private void checkConvertLong2Uchar2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 2, 0x79f19ffa83d09ae7l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            script.forEach_testConvertUchar2Long2Uchar2(inV, out);
+            verifyResultsConvertLong2Uchar2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar2Long2Uchar2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar2Long2Uchar2(inV, out);
+            verifyResultsConvertLong2Uchar2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar2Long2Uchar2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong2Uchar2(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongUchar args = new ArgumentsLongUchar();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong2Uchar2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertLong3Uchar3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 3, 0x79f3691579ebbbc5l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            script.forEach_testConvertUchar3Long3Uchar3(inV, out);
+            verifyResultsConvertLong3Uchar3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar3Long3Uchar3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar3Long3Uchar3(inV, out);
+            verifyResultsConvertLong3Uchar3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar3Long3Uchar3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong3Uchar3(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongUchar args = new ArgumentsLongUchar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong3Uchar3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertLong4Uchar4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 4, 0x79f532307006dca3l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            script.forEach_testConvertUchar4Long4Uchar4(inV, out);
+            verifyResultsConvertLong4Uchar4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar4Long4Uchar4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar4Long4Uchar4(inV, out);
+            verifyResultsConvertLong4Uchar4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar4Long4Uchar4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong4Uchar4(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongUchar args = new ArgumentsLongUchar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong4Uchar4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUlongUchar {
+        public long inV;
+        public byte out;
+    }
+
+    private void checkConvertUlong2Uchar2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 2, 0x9ebfc0021fa8b492l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            script.forEach_testConvertUchar2Ulong2Uchar2(inV, out);
+            verifyResultsConvertUlong2Uchar2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar2Ulong2Uchar2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar2Ulong2Uchar2(inV, out);
+            verifyResultsConvertUlong2Uchar2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar2Ulong2Uchar2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong2Uchar2(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUchar args = new ArgumentsUlongUchar();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong2Uchar2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUlong3Uchar3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 3, 0x9ec1891d15c3d570l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            script.forEach_testConvertUchar3Ulong3Uchar3(inV, out);
+            verifyResultsConvertUlong3Uchar3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar3Ulong3Uchar3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar3Ulong3Uchar3(inV, out);
+            verifyResultsConvertUlong3Uchar3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar3Ulong3Uchar3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong3Uchar3(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUchar args = new ArgumentsUlongUchar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong3Uchar3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUlong4Uchar4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 4, 0x9ec352380bdef64el, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            script.forEach_testConvertUchar4Ulong4Uchar4(inV, out);
+            verifyResultsConvertUlong4Uchar4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar4Ulong4Uchar4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar4Ulong4Uchar4(inV, out);
+            verifyResultsConvertUlong4Uchar4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar4Ulong4Uchar4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong4Uchar4(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUchar args = new ArgumentsUlongUchar();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong4Uchar4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsDoubleShort {
+        public double inV;
+        public short out;
+    }
+
+    private void checkConvertDouble2Short2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 2, 0x42b557fbbf1d55f9l, -3.2768000000000000000e+04, 3.2767000000000000000e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            script.forEach_testConvertShort2Double2Short2(inV, out);
+            verifyResultsConvertDouble2Short2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort2Double2Short2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort2Double2Short2(inV, out);
+            verifyResultsConvertDouble2Short2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort2Double2Short2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble2Short2(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleShort args = new ArgumentsDoubleShort();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble2Short2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertDouble3Short3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 3, 0x42b72116b53876d7l, -3.2768000000000000000e+04, 3.2767000000000000000e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            script.forEach_testConvertShort3Double3Short3(inV, out);
+            verifyResultsConvertDouble3Short3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort3Double3Short3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort3Double3Short3(inV, out);
+            verifyResultsConvertDouble3Short3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort3Double3Short3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble3Short3(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleShort args = new ArgumentsDoubleShort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble3Short3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertDouble4Short4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 4, 0x42b8ea31ab5397b5l, -3.2768000000000000000e+04, 3.2767000000000000000e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            script.forEach_testConvertShort4Double4Short4(inV, out);
+            verifyResultsConvertDouble4Short4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort4Double4Short4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort4Double4Short4(inV, out);
+            verifyResultsConvertDouble4Short4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort4Double4Short4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble4Short4(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleShort args = new ArgumentsDoubleShort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble4Short4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsLongShort {
+        public long inV;
+        public short out;
+    }
+
+    private void checkConvertLong2Short2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 2, 0x79f18bff18de6600l, true, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            script.forEach_testConvertShort2Long2Short2(inV, out);
+            verifyResultsConvertLong2Short2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort2Long2Short2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort2Long2Short2(inV, out);
+            verifyResultsConvertLong2Short2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort2Long2Short2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong2Short2(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongShort args = new ArgumentsLongShort();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong2Short2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertLong3Short3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 3, 0x79f3551a0ef986del, true, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            script.forEach_testConvertShort3Long3Short3(inV, out);
+            verifyResultsConvertLong3Short3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort3Long3Short3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort3Long3Short3(inV, out);
+            verifyResultsConvertLong3Short3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort3Long3Short3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong3Short3(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongShort args = new ArgumentsLongShort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong3Short3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertLong4Short4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 4, 0x79f51e350514a7bcl, true, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            script.forEach_testConvertShort4Long4Short4(inV, out);
+            verifyResultsConvertLong4Short4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort4Long4Short4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort4Long4Short4(inV, out);
+            verifyResultsConvertLong4Short4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort4Long4Short4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong4Short4(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongShort args = new ArgumentsLongShort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong4Short4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUlongShort {
+        public long inV;
+        public short out;
+    }
+
+    private void checkConvertUlong2Short2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 2, 0x9ebfac06b4b67fabl, false, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            script.forEach_testConvertShort2Ulong2Short2(inV, out);
+            verifyResultsConvertUlong2Short2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort2Ulong2Short2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort2Ulong2Short2(inV, out);
+            verifyResultsConvertUlong2Short2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort2Ulong2Short2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong2Short2(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongShort args = new ArgumentsUlongShort();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong2Short2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUlong3Short3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 3, 0x9ec17521aad1a089l, false, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            script.forEach_testConvertShort3Ulong3Short3(inV, out);
+            verifyResultsConvertUlong3Short3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort3Ulong3Short3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort3Ulong3Short3(inV, out);
+            verifyResultsConvertUlong3Short3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort3Ulong3Short3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong3Short3(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongShort args = new ArgumentsUlongShort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong3Short3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUlong4Short4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 4, 0x9ec33e3ca0ecc167l, false, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            script.forEach_testConvertShort4Ulong4Short4(inV, out);
+            verifyResultsConvertUlong4Short4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort4Ulong4Short4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort4Ulong4Short4(inV, out);
+            verifyResultsConvertUlong4Short4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort4Ulong4Short4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong4Short4(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongShort args = new ArgumentsUlongShort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong4Short4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsDoubleUshort {
+        public double inV;
+        public short out;
+    }
+
+    private void checkConvertDouble2Ushort2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 2, 0x3479ccaea92a37bcl, 0.0000000000000000000e+00, 6.5535000000000000000e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            script.forEach_testConvertUshort2Double2Ushort2(inV, out);
+            verifyResultsConvertDouble2Ushort2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort2Double2Ushort2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort2Double2Ushort2(inV, out);
+            verifyResultsConvertDouble2Ushort2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort2Double2Ushort2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble2Ushort2(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleUshort args = new ArgumentsDoubleUshort();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble2Ushort2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertDouble3Ushort3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 3, 0x34c69435ff85c8e8l, 0.0000000000000000000e+00, 6.5535000000000000000e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            script.forEach_testConvertUshort3Double3Ushort3(inV, out);
+            verifyResultsConvertDouble3Ushort3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort3Double3Ushort3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort3Double3Ushort3(inV, out);
+            verifyResultsConvertDouble3Ushort3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort3Double3Ushort3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble3Ushort3(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleUshort args = new ArgumentsDoubleUshort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble3Ushort3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertDouble4Ushort4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 4, 0x35135bbd55e15a14l, 0.0000000000000000000e+00, 6.5535000000000000000e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            script.forEach_testConvertUshort4Double4Ushort4(inV, out);
+            verifyResultsConvertDouble4Ushort4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort4Double4Ushort4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort4Double4Ushort4(inV, out);
+            verifyResultsConvertDouble4Ushort4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort4Double4Ushort4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble4Ushort4(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleUshort args = new ArgumentsDoubleUshort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble4Ushort4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsLongUshort {
+        public long inV;
+        public short out;
+    }
+
+    private void checkConvertLong2Ushort2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 2, 0x7b96893ebc97e8e9l, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            script.forEach_testConvertUshort2Long2Ushort2(inV, out);
+            verifyResultsConvertLong2Ushort2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort2Long2Ushort2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort2Long2Ushort2(inV, out);
+            verifyResultsConvertLong2Ushort2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort2Long2Ushort2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong2Ushort2(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongUshort args = new ArgumentsLongUshort();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong2Ushort2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertLong3Ushort3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 3, 0x7be350c612f37a15l, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            script.forEach_testConvertUshort3Long3Ushort3(inV, out);
+            verifyResultsConvertLong3Ushort3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort3Long3Ushort3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort3Long3Ushort3(inV, out);
+            verifyResultsConvertLong3Ushort3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort3Long3Ushort3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong3Ushort3(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongUshort args = new ArgumentsLongUshort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong3Ushort3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertLong4Ushort4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 4, 0x7c30184d694f0b41l, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            script.forEach_testConvertUshort4Long4Ushort4(inV, out);
+            verifyResultsConvertLong4Ushort4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort4Long4Ushort4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort4Long4Ushort4(inV, out);
+            verifyResultsConvertLong4Ushort4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort4Long4Ushort4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong4Ushort4(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongUshort args = new ArgumentsLongUshort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong4Ushort4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUlongUshort {
+        public long inV;
+        public short out;
+    }
+
+    private void checkConvertUlong2Ushort2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 2, 0xaa35ea85e9e438a2l, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            script.forEach_testConvertUshort2Ulong2Ushort2(inV, out);
+            verifyResultsConvertUlong2Ushort2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort2Ulong2Ushort2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort2Ulong2Ushort2(inV, out);
+            verifyResultsConvertUlong2Ushort2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort2Ulong2Ushort2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong2Ushort2(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUshort args = new ArgumentsUlongUshort();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong2Ushort2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUlong3Ushort3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 3, 0xaa82b20d403fc9cel, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            script.forEach_testConvertUshort3Ulong3Ushort3(inV, out);
+            verifyResultsConvertUlong3Ushort3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort3Ulong3Ushort3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort3Ulong3Ushort3(inV, out);
+            verifyResultsConvertUlong3Ushort3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort3Ulong3Ushort3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong3Ushort3(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUshort args = new ArgumentsUlongUshort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong3Ushort3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUlong4Ushort4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 4, 0xaacf7994969b5afal, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            script.forEach_testConvertUshort4Ulong4Ushort4(inV, out);
+            verifyResultsConvertUlong4Ushort4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort4Ulong4Ushort4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort4Ulong4Ushort4(inV, out);
+            verifyResultsConvertUlong4Ushort4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort4Ulong4Ushort4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong4Ushort4(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUshort args = new ArgumentsUlongUshort();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong4Ushort4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsDoubleInt {
+        public double inV;
+        public int out;
+    }
+
+    private void checkConvertDouble2Int2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 2, 0xa57cd81dcaf628fcl, -2.1474836480000000000e+09, 2.1474836470000000000e+09);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            script.forEach_testConvertInt2Double2Int2(inV, out);
+            verifyResultsConvertDouble2Int2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt2Double2Int2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt2Double2Int2(inV, out);
+            verifyResultsConvertDouble2Int2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt2Double2Int2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble2Int2(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleInt args = new ArgumentsDoubleInt();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble2Int2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertDouble3Int3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 3, 0xa57cd85d149e3932l, -2.1474836480000000000e+09, 2.1474836470000000000e+09);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            script.forEach_testConvertInt3Double3Int3(inV, out);
+            verifyResultsConvertDouble3Int3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt3Double3Int3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt3Double3Int3(inV, out);
+            verifyResultsConvertDouble3Int3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt3Double3Int3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble3Int3(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleInt args = new ArgumentsDoubleInt();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble3Int3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertDouble4Int4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 4, 0xa57cd89c5e464968l, -2.1474836480000000000e+09, 2.1474836470000000000e+09);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            script.forEach_testConvertInt4Double4Int4(inV, out);
+            verifyResultsConvertDouble4Int4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt4Double4Int4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt4Double4Int4(inV, out);
+            verifyResultsConvertDouble4Int4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt4Double4Int4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble4Int4(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleInt args = new ArgumentsDoubleInt();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble4Int4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsLongInt {
+        public long inV;
+        public int out;
+    }
+
+    private void checkConvertLong2Int2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 2, 0xfe441c66e5deba3bl, true, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            script.forEach_testConvertInt2Long2Int2(inV, out);
+            verifyResultsConvertLong2Int2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt2Long2Int2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt2Long2Int2(inV, out);
+            verifyResultsConvertLong2Int2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt2Long2Int2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong2Int2(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongInt args = new ArgumentsLongInt();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong2Int2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertLong3Int3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 3, 0xfe441ca62f86ca71l, true, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            script.forEach_testConvertInt3Long3Int3(inV, out);
+            verifyResultsConvertLong3Int3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt3Long3Int3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt3Long3Int3(inV, out);
+            verifyResultsConvertLong3Int3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt3Long3Int3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong3Int3(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongInt args = new ArgumentsLongInt();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong3Int3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertLong4Int4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 4, 0xfe441ce5792edaa7l, true, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            script.forEach_testConvertInt4Long4Int4(inV, out);
+            verifyResultsConvertLong4Int4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt4Long4Int4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt4Long4Int4(inV, out);
+            verifyResultsConvertLong4Int4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt4Long4Int4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong4Int4(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongInt args = new ArgumentsLongInt();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong4Int4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUlongInt {
+        public long inV;
+        public int out;
+    }
+
+    private void checkConvertUlong2Int2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 2, 0xe11d350e352de3el, false, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            script.forEach_testConvertInt2Ulong2Int2(inV, out);
+            verifyResultsConvertUlong2Int2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt2Ulong2Int2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt2Ulong2Int2(inV, out);
+            verifyResultsConvertUlong2Int2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt2Ulong2Int2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong2Int2(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongInt args = new ArgumentsUlongInt();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong2Int2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUlong3Int3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 3, 0xe11d3902cfaee74l, false, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            script.forEach_testConvertInt3Ulong3Int3(inV, out);
+            verifyResultsConvertUlong3Int3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt3Ulong3Int3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt3Ulong3Int3(inV, out);
+            verifyResultsConvertUlong3Int3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt3Ulong3Int3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong3Int3(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongInt args = new ArgumentsUlongInt();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong3Int3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUlong4Int4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 4, 0xe11d3cf76a2feaal, false, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            script.forEach_testConvertInt4Ulong4Int4(inV, out);
+            verifyResultsConvertUlong4Int4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt4Ulong4Int4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt4Ulong4Int4(inV, out);
+            verifyResultsConvertUlong4Int4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt4Ulong4Int4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong4Int4(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongInt args = new ArgumentsUlongInt();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong4Int4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsDoubleUint {
+        public double inV;
+        public int out;
+    }
+
+    private void checkConvertDouble2Uint2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 2, 0xcbf84ff107de7dd7l, 0.0000000000000000000e+00, 4.2949672950000000000e+09);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            script.forEach_testConvertUint2Double2Uint2(inV, out);
+            verifyResultsConvertDouble2Uint2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint2Double2Uint2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint2Double2Uint2(inV, out);
+            verifyResultsConvertDouble2Uint2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint2Double2Uint2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble2Uint2(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleUint args = new ArgumentsDoubleUint();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble2Uint2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertDouble3Uint3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 3, 0xcbf85a9266e642cbl, 0.0000000000000000000e+00, 4.2949672950000000000e+09);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            script.forEach_testConvertUint3Double3Uint3(inV, out);
+            verifyResultsConvertDouble3Uint3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint3Double3Uint3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint3Double3Uint3(inV, out);
+            verifyResultsConvertDouble3Uint3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint3Double3Uint3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble3Uint3(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleUint args = new ArgumentsDoubleUint();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble3Uint3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertDouble4Uint4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 4, 0xcbf86533c5ee07bfl, 0.0000000000000000000e+00, 4.2949672950000000000e+09);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            script.forEach_testConvertUint4Double4Uint4(inV, out);
+            verifyResultsConvertDouble4Uint4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint4Double4Uint4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint4Double4Uint4(inV, out);
+            verifyResultsConvertDouble4Uint4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint4Double4Uint4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble4Uint4(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleUint args = new ArgumentsDoubleUint();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            args.inV, Double.doubleToRawLongBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertDouble4Uint4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsLongUint {
+        public long inV;
+        public int out;
+    }
+
+    private void checkConvertLong2Uint2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 2, 0xb570c8388ceee36cl, false, 32);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            script.forEach_testConvertUint2Long2Uint2(inV, out);
+            verifyResultsConvertLong2Uint2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint2Long2Uint2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint2Long2Uint2(inV, out);
+            verifyResultsConvertLong2Uint2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint2Long2Uint2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong2Uint2(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongUint args = new ArgumentsLongUint();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong2Uint2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertLong3Uint3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 3, 0xb570d2d9ebf6a860l, false, 32);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            script.forEach_testConvertUint3Long3Uint3(inV, out);
+            verifyResultsConvertLong3Uint3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint3Long3Uint3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint3Long3Uint3(inV, out);
+            verifyResultsConvertLong3Uint3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint3Long3Uint3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong3Uint3(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongUint args = new ArgumentsLongUint();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong3Uint3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertLong4Uint4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 4, 0xb570dd7b4afe6d54l, false, 32);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            script.forEach_testConvertUint4Long4Uint4(inV, out);
+            verifyResultsConvertLong4Uint4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint4Long4Uint4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint4Long4Uint4(inV, out);
+            verifyResultsConvertLong4Uint4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint4Long4Uint4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong4Uint4(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongUint args = new ArgumentsLongUint();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertLong4Uint4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUlongUint {
+        public long inV;
+        public int out;
+    }
+
+    private void checkConvertUlong2Uint2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 2, 0x5cfe81861f70efedl, false, 32);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            script.forEach_testConvertUint2Ulong2Uint2(inV, out);
+            verifyResultsConvertUlong2Uint2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint2Ulong2Uint2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint2Ulong2Uint2(inV, out);
+            verifyResultsConvertUlong2Uint2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint2Ulong2Uint2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong2Uint2(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUint args = new ArgumentsUlongUint();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong2Uint2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUlong3Uint3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 3, 0x5cfe8c277e78b4e1l, false, 32);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            script.forEach_testConvertUint3Ulong3Uint3(inV, out);
+            verifyResultsConvertUlong3Uint3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint3Ulong3Uint3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint3Ulong3Uint3(inV, out);
+            verifyResultsConvertUlong3Uint3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint3Ulong3Uint3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong3Uint3(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUint args = new ArgumentsUlongUint();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong3Uint3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUlong4Uint4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 4, 0x5cfe96c8dd8079d5l, false, 32);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            script.forEach_testConvertUint4Ulong4Uint4(inV, out);
+            verifyResultsConvertUlong4Uint4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint4Ulong4Uint4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint4Ulong4Uint4(inV, out);
+            verifyResultsConvertUlong4Uint4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint4Ulong4Uint4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong4Uint4(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUint args = new ArgumentsUlongUint();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUlong4Uint4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsFloatDouble {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertFloat2Double2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x36c6372446e08221l, -1.6163412428744576259e+38, 1.6163412428744576259e+38);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 2), INPUTSIZE);
+            script.forEach_testConvertDouble2Float2Double2(inV, out);
+            verifyResultsConvertFloat2Double2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble2Float2Double2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble2Float2Double2(inV, out);
+            verifyResultsConvertFloat2Double2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble2Float2Double2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat2Double2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatDouble args = new ArgumentsFloatDouble();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 2 + j], Double.doubleToRawLongBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat2Double2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertFloat3Double3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x3712feab9d3c134dl, -1.6163412428744576259e+38, 1.6163412428744576259e+38);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 3), INPUTSIZE);
+            script.forEach_testConvertDouble3Float3Double3(inV, out);
+            verifyResultsConvertFloat3Double3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble3Float3Double3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble3Float3Double3(inV, out);
+            verifyResultsConvertFloat3Double3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble3Float3Double3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat3Double3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatDouble args = new ArgumentsFloatDouble();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 4 + j], Double.doubleToRawLongBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat3Double3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertFloat4Double4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x375fc632f397a479l, -1.6163412428744576259e+38, 1.6163412428744576259e+38);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 4), INPUTSIZE);
+            script.forEach_testConvertDouble4Float4Double4(inV, out);
+            verifyResultsConvertFloat4Double4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble4Float4Double4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble4Float4Double4(inV, out);
+            verifyResultsConvertFloat4Double4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble4Float4Double4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat4Double4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatDouble args = new ArgumentsFloatDouble();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 4 + j], Double.doubleToRawLongBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat4Double4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsCharDouble {
+        public byte inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertChar2Double2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 2, 0xd86d88e268ca2f61l, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 2), INPUTSIZE);
+            script.forEach_testConvertDouble2Char2Double2(inV, out);
+            verifyResultsConvertChar2Double2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble2Char2Double2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble2Char2Double2(inV, out);
+            verifyResultsConvertChar2Double2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble2Char2Double2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar2Double2(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharDouble args = new ArgumentsCharDouble();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 2 + j], Double.doubleToRawLongBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar2Double2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertChar3Double3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 3, 0xd8ba5069bf25c08dl, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 3), INPUTSIZE);
+            script.forEach_testConvertDouble3Char3Double3(inV, out);
+            verifyResultsConvertChar3Double3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble3Char3Double3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble3Char3Double3(inV, out);
+            verifyResultsConvertChar3Double3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble3Char3Double3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar3Double3(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharDouble args = new ArgumentsCharDouble();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 4 + j], Double.doubleToRawLongBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar3Double3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertChar4Double4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 4, 0xd90717f1158151b9l, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 4), INPUTSIZE);
+            script.forEach_testConvertDouble4Char4Double4(inV, out);
+            verifyResultsConvertChar4Double4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble4Char4Double4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble4Char4Double4(inV, out);
+            verifyResultsConvertChar4Double4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble4Char4Double4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar4Double4(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharDouble args = new ArgumentsCharDouble();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 4 + j], Double.doubleToRawLongBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar4Double4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUcharDouble {
+        public byte inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertUchar2Double2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 2, 0x70cea2996167f1al, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 2), INPUTSIZE);
+            script.forEach_testConvertDouble2Uchar2Double2(inV, out);
+            verifyResultsConvertUchar2Double2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble2Uchar2Double2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble2Uchar2Double2(inV, out);
+            verifyResultsConvertUchar2Double2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble2Uchar2Double2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar2Double2(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharDouble args = new ArgumentsUcharDouble();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 2 + j], Double.doubleToRawLongBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar2Double2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUchar3Double3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 3, 0x759b1b0ec721046l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 3), INPUTSIZE);
+            script.forEach_testConvertDouble3Uchar3Double3(inV, out);
+            verifyResultsConvertUchar3Double3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble3Uchar3Double3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble3Uchar3Double3(inV, out);
+            verifyResultsConvertUchar3Double3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble3Uchar3Double3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar3Double3(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharDouble args = new ArgumentsUcharDouble();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 4 + j], Double.doubleToRawLongBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar3Double3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUchar4Double4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 4, 0x7a6793842cda172l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 4), INPUTSIZE);
+            script.forEach_testConvertDouble4Uchar4Double4(inV, out);
+            verifyResultsConvertUchar4Double4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble4Uchar4Double4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble4Uchar4Double4(inV, out);
+            verifyResultsConvertUchar4Double4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble4Uchar4Double4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar4Double4(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharDouble args = new ArgumentsUcharDouble();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 4 + j], Double.doubleToRawLongBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar4Double4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsShortDouble {
+        public short inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertShort2Double2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 2, 0xfdeea470023d0105l, true, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 2), INPUTSIZE);
+            script.forEach_testConvertDouble2Short2Double2(inV, out);
+            verifyResultsConvertShort2Double2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble2Short2Double2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble2Short2Double2(inV, out);
+            verifyResultsConvertShort2Double2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble2Short2Double2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort2Double2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortDouble args = new ArgumentsShortDouble();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 2 + j], Double.doubleToRawLongBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort2Double2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertShort3Double3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 3, 0xfe3b6bf758989231l, true, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 3), INPUTSIZE);
+            script.forEach_testConvertDouble3Short3Double3(inV, out);
+            verifyResultsConvertShort3Double3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble3Short3Double3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble3Short3Double3(inV, out);
+            verifyResultsConvertShort3Double3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble3Short3Double3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort3Double3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortDouble args = new ArgumentsShortDouble();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 4 + j], Double.doubleToRawLongBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort3Double3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertShort4Double4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 4, 0xfe88337eaef4235dl, true, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 4), INPUTSIZE);
+            script.forEach_testConvertDouble4Short4Double4(inV, out);
+            verifyResultsConvertShort4Double4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble4Short4Double4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble4Short4Double4(inV, out);
+            verifyResultsConvertShort4Double4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble4Short4Double4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort4Double4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortDouble args = new ArgumentsShortDouble();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 4 + j], Double.doubleToRawLongBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort4Double4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUshortDouble {
+        public short inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertUshort2Double2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 2, 0xd2b3fb649e0e6518l, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 2), INPUTSIZE);
+            script.forEach_testConvertDouble2Ushort2Double2(inV, out);
+            verifyResultsConvertUshort2Double2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble2Ushort2Double2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble2Ushort2Double2(inV, out);
+            verifyResultsConvertUshort2Double2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble2Ushort2Double2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort2Double2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortDouble args = new ArgumentsUshortDouble();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 2 + j], Double.doubleToRawLongBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort2Double2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUshort3Double3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 3, 0xd300c2ebf469f644l, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 3), INPUTSIZE);
+            script.forEach_testConvertDouble3Ushort3Double3(inV, out);
+            verifyResultsConvertUshort3Double3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble3Ushort3Double3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble3Ushort3Double3(inV, out);
+            verifyResultsConvertUshort3Double3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble3Ushort3Double3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort3Double3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortDouble args = new ArgumentsUshortDouble();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 4 + j], Double.doubleToRawLongBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort3Double3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUshort4Double4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 4, 0xd34d8a734ac58770l, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 4), INPUTSIZE);
+            script.forEach_testConvertDouble4Ushort4Double4(inV, out);
+            verifyResultsConvertUshort4Double4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble4Ushort4Double4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble4Ushort4Double4(inV, out);
+            verifyResultsConvertUshort4Double4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble4Ushort4Double4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort4Double4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortDouble args = new ArgumentsUshortDouble();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 4 + j], Double.doubleToRawLongBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort4Double4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsIntDouble {
+        public int inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertInt2Double2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 2, 0x1be423b7a40fc8f6l, true, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 2), INPUTSIZE);
+            script.forEach_testConvertDouble2Int2Double2(inV, out);
+            verifyResultsConvertInt2Double2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble2Int2Double2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble2Int2Double2(inV, out);
+            verifyResultsConvertInt2Double2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble2Int2Double2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt2Double2(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntDouble args = new ArgumentsIntDouble();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 2 + j], Double.doubleToRawLongBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt2Double2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertInt3Double3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 3, 0x1c30eb3efa6b5a22l, true, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 3), INPUTSIZE);
+            script.forEach_testConvertDouble3Int3Double3(inV, out);
+            verifyResultsConvertInt3Double3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble3Int3Double3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble3Int3Double3(inV, out);
+            verifyResultsConvertInt3Double3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble3Int3Double3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt3Double3(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntDouble args = new ArgumentsIntDouble();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 4 + j], Double.doubleToRawLongBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt3Double3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertInt4Double4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 4, 0x1c7db2c650c6eb4el, true, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 4), INPUTSIZE);
+            script.forEach_testConvertDouble4Int4Double4(inV, out);
+            verifyResultsConvertInt4Double4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble4Int4Double4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble4Int4Double4(inV, out);
+            verifyResultsConvertInt4Double4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble4Int4Double4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt4Double4(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntDouble args = new ArgumentsIntDouble();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 4 + j], Double.doubleToRawLongBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt4Double4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUintDouble {
+        public int inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertUint2Double2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 2, 0x40b243bf3fe7e2a1l, false, 32);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 2), INPUTSIZE);
+            script.forEach_testConvertDouble2Uint2Double2(inV, out);
+            verifyResultsConvertUint2Double2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble2Uint2Double2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble2Uint2Double2(inV, out);
+            verifyResultsConvertUint2Double2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble2Uint2Double2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint2Double2(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintDouble args = new ArgumentsUintDouble();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 2 + j], Double.doubleToRawLongBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint2Double2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUint3Double3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 3, 0x40ff0b46964373cdl, false, 32);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 3), INPUTSIZE);
+            script.forEach_testConvertDouble3Uint3Double3(inV, out);
+            verifyResultsConvertUint3Double3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble3Uint3Double3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble3Uint3Double3(inV, out);
+            verifyResultsConvertUint3Double3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble3Uint3Double3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint3Double3(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintDouble args = new ArgumentsUintDouble();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 4 + j], Double.doubleToRawLongBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint3Double3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUint4Double4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 4, 0x414bd2cdec9f04f9l, false, 32);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 4), INPUTSIZE);
+            script.forEach_testConvertDouble4Uint4Double4(inV, out);
+            verifyResultsConvertUint4Double4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble4Uint4Double4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble4Uint4Double4(inV, out);
+            verifyResultsConvertUint4Double4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble4Uint4Double4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint4Double4(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintDouble args = new ArgumentsUintDouble();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%24.8g {%16x} %31a",
+                            arrayOut[i * 4 + j], Double.doubleToRawLongBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint4Double4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsFloatLong {
+        public float inV;
+        public long out;
+    }
+
+    private void checkConvertFloat2Long2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x239cb49c7d7c0ae0l, -9.2233714870989619200e+18, 9.2233714870989619200e+18);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            script.forEach_testConvertLong2Float2Long2(inV, out);
+            verifyResultsConvertFloat2Long2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong2Float2Long2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong2Float2Long2(inV, out);
+            verifyResultsConvertFloat2Long2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong2Float2Long2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat2Long2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatLong args = new ArgumentsFloatLong();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat2Long2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertFloat3Long3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x239cbf3ddc83cfd4l, -9.2233714870989619200e+18, 9.2233714870989619200e+18);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            script.forEach_testConvertLong3Float3Long3(inV, out);
+            verifyResultsConvertFloat3Long3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong3Float3Long3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong3Float3Long3(inV, out);
+            verifyResultsConvertFloat3Long3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong3Float3Long3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat3Long3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatLong args = new ArgumentsFloatLong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat3Long3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertFloat4Long4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x239cc9df3b8b94c8l, -9.2233714870989619200e+18, 9.2233714870989619200e+18);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            script.forEach_testConvertLong4Float4Long4(inV, out);
+            verifyResultsConvertFloat4Long4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong4Float4Long4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong4Float4Long4(inV, out);
+            verifyResultsConvertFloat4Long4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong4Float4Long4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat4Long4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatLong args = new ArgumentsFloatLong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat4Long4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsCharLong {
+        public byte inV;
+        public long out;
+    }
+
+    private void checkConvertChar2Long2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 2, 0xd86189bc290be220l, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            script.forEach_testConvertLong2Char2Long2(inV, out);
+            verifyResultsConvertChar2Long2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong2Char2Long2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong2Char2Long2(inV, out);
+            verifyResultsConvertChar2Long2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong2Char2Long2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar2Long2(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharLong args = new ArgumentsCharLong();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar2Long2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertChar3Long3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 3, 0xd861945d8813a714l, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            script.forEach_testConvertLong3Char3Long3(inV, out);
+            verifyResultsConvertChar3Long3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong3Char3Long3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong3Char3Long3(inV, out);
+            verifyResultsConvertChar3Long3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong3Char3Long3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar3Long3(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharLong args = new ArgumentsCharLong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar3Long3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertChar4Long4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 4, 0xd8619efee71b6c08l, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            script.forEach_testConvertLong4Char4Long4(inV, out);
+            verifyResultsConvertChar4Long4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong4Char4Long4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong4Char4Long4(inV, out);
+            verifyResultsConvertChar4Long4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong4Char4Long4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar4Long4(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharLong args = new ArgumentsCharLong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar4Long4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUcharLong {
+        public byte inV;
+        public long out;
+    }
+
+    private void checkConvertUchar2Long2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 2, 0x7fef4309bb8deea1l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            script.forEach_testConvertLong2Uchar2Long2(inV, out);
+            verifyResultsConvertUchar2Long2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong2Uchar2Long2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong2Uchar2Long2(inV, out);
+            verifyResultsConvertUchar2Long2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong2Uchar2Long2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar2Long2(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharLong args = new ArgumentsUcharLong();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar2Long2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUchar3Long3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 3, 0x7fef4dab1a95b395l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            script.forEach_testConvertLong3Uchar3Long3(inV, out);
+            verifyResultsConvertUchar3Long3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong3Uchar3Long3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong3Uchar3Long3(inV, out);
+            verifyResultsConvertUchar3Long3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong3Uchar3Long3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar3Long3(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharLong args = new ArgumentsUcharLong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar3Long3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUchar4Long4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 4, 0x7fef584c799d7889l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            script.forEach_testConvertLong4Uchar4Long4(inV, out);
+            verifyResultsConvertUchar4Long4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong4Uchar4Long4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong4Uchar4Long4(inV, out);
+            verifyResultsConvertUchar4Long4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong4Uchar4Long4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar4Long4(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharLong args = new ArgumentsUcharLong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar4Long4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsShortLong {
+        public short inV;
+        public long out;
+    }
+
+    private void checkConvertShort2Long2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 2, 0x68ab674669c97ce4l, true, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            script.forEach_testConvertLong2Short2Long2(inV, out);
+            verifyResultsConvertShort2Long2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong2Short2Long2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong2Short2Long2(inV, out);
+            verifyResultsConvertShort2Long2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong2Short2Long2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort2Long2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortLong args = new ArgumentsShortLong();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort2Long2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertShort3Long3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 3, 0x68ab71e7c8d141d8l, true, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            script.forEach_testConvertLong3Short3Long3(inV, out);
+            verifyResultsConvertShort3Long3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong3Short3Long3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong3Short3Long3(inV, out);
+            verifyResultsConvertShort3Long3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong3Short3Long3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort3Long3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortLong args = new ArgumentsShortLong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort3Long3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertShort4Long4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 4, 0x68ab7c8927d906ccl, true, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            script.forEach_testConvertLong4Short4Long4(inV, out);
+            verifyResultsConvertShort4Long4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong4Short4Long4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong4Short4Long4(inV, out);
+            verifyResultsConvertShort4Long4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong4Short4Long4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort4Long4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortLong args = new ArgumentsShortLong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort4Long4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUshortLong {
+        public short inV;
+        public long out;
+    }
+
+    private void checkConvertUshort2Long2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 2, 0x8d79874e05a1968fl, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            script.forEach_testConvertLong2Ushort2Long2(inV, out);
+            verifyResultsConvertUshort2Long2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong2Ushort2Long2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong2Ushort2Long2(inV, out);
+            verifyResultsConvertUshort2Long2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong2Ushort2Long2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort2Long2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortLong args = new ArgumentsUshortLong();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort2Long2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUshort3Long3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 3, 0x8d7991ef64a95b83l, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            script.forEach_testConvertLong3Ushort3Long3(inV, out);
+            verifyResultsConvertUshort3Long3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong3Ushort3Long3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong3Ushort3Long3(inV, out);
+            verifyResultsConvertUshort3Long3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong3Ushort3Long3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort3Long3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortLong args = new ArgumentsUshortLong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort3Long3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUshort4Long4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 4, 0x8d799c90c3b12077l, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            script.forEach_testConvertLong4Ushort4Long4(inV, out);
+            verifyResultsConvertUshort4Long4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong4Ushort4Long4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong4Ushort4Long4(inV, out);
+            verifyResultsConvertUshort4Long4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong4Ushort4Long4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort4Long4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortLong args = new ArgumentsUshortLong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort4Long4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsIntLong {
+        public int inV;
+        public long out;
+    }
+
+    private void checkConvertInt2Long2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 2, 0xd74f538b8a45cb5dl, true, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            script.forEach_testConvertLong2Int2Long2(inV, out);
+            verifyResultsConvertInt2Long2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong2Int2Long2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong2Int2Long2(inV, out);
+            verifyResultsConvertInt2Long2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong2Int2Long2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt2Long2(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntLong args = new ArgumentsIntLong();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt2Long2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertInt3Long3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 3, 0xd74f5e2ce94d9051l, true, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            script.forEach_testConvertLong3Int3Long3(inV, out);
+            verifyResultsConvertInt3Long3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong3Int3Long3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong3Int3Long3(inV, out);
+            verifyResultsConvertInt3Long3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong3Int3Long3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt3Long3(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntLong args = new ArgumentsIntLong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt3Long3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertInt4Long4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 4, 0xd74f68ce48555545l, true, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            script.forEach_testConvertLong4Int4Long4(inV, out);
+            verifyResultsConvertInt4Long4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong4Int4Long4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong4Int4Long4(inV, out);
+            verifyResultsConvertInt4Long4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong4Int4Long4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt4Long4(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntLong args = new ArgumentsIntLong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt4Long4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUintLong {
+        public int inV;
+        public long out;
+    }
+
+    private void checkConvertUint2Long2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 2, 0xe71d0a7587b9ef60l, false, 32);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            script.forEach_testConvertLong2Uint2Long2(inV, out);
+            verifyResultsConvertUint2Long2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong2Uint2Long2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong2Uint2Long2(inV, out);
+            verifyResultsConvertUint2Long2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong2Uint2Long2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint2Long2(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintLong args = new ArgumentsUintLong();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint2Long2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUint3Long3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 3, 0xe71d1516e6c1b454l, false, 32);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            script.forEach_testConvertLong3Uint3Long3(inV, out);
+            verifyResultsConvertUint3Long3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong3Uint3Long3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong3Uint3Long3(inV, out);
+            verifyResultsConvertUint3Long3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong3Uint3Long3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint3Long3(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintLong args = new ArgumentsUintLong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint3Long3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUint4Long4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 4, 0xe71d1fb845c97948l, false, 32);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            script.forEach_testConvertLong4Uint4Long4(inV, out);
+            verifyResultsConvertUint4Long4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong4Uint4Long4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong4Uint4Long4(inV, out);
+            verifyResultsConvertUint4Long4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong4Uint4Long4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint4Long4(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintLong args = new ArgumentsUintLong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint4Long4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsFloatUlong {
+        public float inV;
+        public long out;
+    }
+
+    private void checkConvertFloat2Ulong2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xfb52b5394ec4cff7l, 0.0000000000000000000e+00, 1.8446742974197923840e+19);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            script.forEach_testConvertUlong2Float2Ulong2(inV, out);
+            verifyResultsConvertFloat2Ulong2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong2Float2Ulong2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong2Float2Ulong2(inV, out);
+            verifyResultsConvertFloat2Ulong2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong2Float2Ulong2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat2Ulong2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatUlong args = new ArgumentsFloatUlong();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat2Ulong2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertFloat3Ulong3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xfb547e5444dff0d5l, 0.0000000000000000000e+00, 1.8446742974197923840e+19);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            script.forEach_testConvertUlong3Float3Ulong3(inV, out);
+            verifyResultsConvertFloat3Ulong3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong3Float3Ulong3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong3Float3Ulong3(inV, out);
+            verifyResultsConvertFloat3Ulong3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong3Float3Ulong3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat3Ulong3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatUlong args = new ArgumentsFloatUlong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat3Ulong3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertFloat4Ulong4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xfb56476f3afb11b3l, 0.0000000000000000000e+00, 1.8446742974197923840e+19);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            script.forEach_testConvertUlong4Float4Ulong4(inV, out);
+            verifyResultsConvertFloat4Ulong4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong4Float4Ulong4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong4Float4Ulong4(inV, out);
+            verifyResultsConvertFloat4Ulong4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong4Float4Ulong4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat4Ulong4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatUlong args = new ArgumentsFloatUlong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertFloat4Ulong4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsCharUlong {
+        public byte inV;
+        public long out;
+    }
+
+    private void checkConvertChar2Ulong2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 2, 0x5862818b1fedf7b7l, false, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            script.forEach_testConvertUlong2Char2Ulong2(inV, out);
+            verifyResultsConvertChar2Ulong2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong2Char2Ulong2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong2Char2Ulong2(inV, out);
+            verifyResultsConvertChar2Ulong2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong2Char2Ulong2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar2Ulong2(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharUlong args = new ArgumentsCharUlong();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar2Ulong2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertChar3Ulong3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 3, 0x58644aa616091895l, false, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            script.forEach_testConvertUlong3Char3Ulong3(inV, out);
+            verifyResultsConvertChar3Ulong3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong3Char3Ulong3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong3Char3Ulong3(inV, out);
+            verifyResultsConvertChar3Ulong3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong3Char3Ulong3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar3Ulong3(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharUlong args = new ArgumentsCharUlong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar3Ulong3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertChar4Ulong4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 4, 0x586613c10c243973l, false, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            script.forEach_testConvertUlong4Char4Ulong4(inV, out);
+            verifyResultsConvertChar4Ulong4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong4Char4Ulong4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong4Char4Ulong4(inV, out);
+            verifyResultsConvertChar4Ulong4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong4Char4Ulong4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar4Ulong4(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharUlong args = new ArgumentsCharUlong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertChar4Ulong4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUcharUlong {
+        public byte inV;
+        public long out;
+    }
+
+    private void checkConvertUchar2Ulong2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 2, 0x7d30a192bbc61162l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            script.forEach_testConvertUlong2Uchar2Ulong2(inV, out);
+            verifyResultsConvertUchar2Ulong2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong2Uchar2Ulong2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong2Uchar2Ulong2(inV, out);
+            verifyResultsConvertUchar2Ulong2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong2Uchar2Ulong2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar2Ulong2(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUlong args = new ArgumentsUcharUlong();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar2Ulong2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUchar3Ulong3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 3, 0x7d326aadb1e13240l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            script.forEach_testConvertUlong3Uchar3Ulong3(inV, out);
+            verifyResultsConvertUchar3Ulong3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong3Uchar3Ulong3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong3Uchar3Ulong3(inV, out);
+            verifyResultsConvertUchar3Ulong3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong3Uchar3Ulong3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar3Ulong3(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUlong args = new ArgumentsUcharUlong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar3Ulong3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUchar4Ulong4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 4, 0x7d3433c8a7fc531el, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            script.forEach_testConvertUlong4Uchar4Ulong4(inV, out);
+            verifyResultsConvertUchar4Ulong4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong4Uchar4Ulong4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong4Uchar4Ulong4(inV, out);
+            verifyResultsConvertUchar4Ulong4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong4Uchar4Ulong4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar4Ulong4(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUlong args = new ArgumentsUcharUlong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUchar4Ulong4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsShortUlong {
+        public short inV;
+        public long out;
+    }
+
+    private void checkConvertShort2Ulong2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 2, 0x94cab7c3ffc6f6a3l, false, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            script.forEach_testConvertUlong2Short2Ulong2(inV, out);
+            verifyResultsConvertShort2Ulong2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong2Short2Ulong2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong2Short2Ulong2(inV, out);
+            verifyResultsConvertShort2Ulong2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong2Short2Ulong2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort2Ulong2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortUlong args = new ArgumentsShortUlong();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort2Ulong2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertShort3Ulong3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 3, 0x94cc80def5e21781l, false, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            script.forEach_testConvertUlong3Short3Ulong3(inV, out);
+            verifyResultsConvertShort3Ulong3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong3Short3Ulong3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong3Short3Ulong3(inV, out);
+            verifyResultsConvertShort3Ulong3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong3Short3Ulong3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort3Ulong3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortUlong args = new ArgumentsShortUlong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort3Ulong3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertShort4Ulong4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 4, 0x94ce49f9ebfd385fl, false, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            script.forEach_testConvertUlong4Short4Ulong4(inV, out);
+            verifyResultsConvertShort4Ulong4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong4Short4Ulong4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong4Short4Ulong4(inV, out);
+            verifyResultsConvertShort4Ulong4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong4Short4Ulong4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort4Ulong4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortUlong args = new ArgumentsShortUlong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertShort4Ulong4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUshortUlong {
+        public short inV;
+        public long out;
+    }
+
+    private void checkConvertUshort2Ulong2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 2, 0xc36a190b2d13465cl, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            script.forEach_testConvertUlong2Ushort2Ulong2(inV, out);
+            verifyResultsConvertUshort2Ulong2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong2Ushort2Ulong2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong2Ushort2Ulong2(inV, out);
+            verifyResultsConvertUshort2Ulong2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong2Ushort2Ulong2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort2Ulong2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUlong args = new ArgumentsUshortUlong();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort2Ulong2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUshort3Ulong3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 3, 0xc36be226232e673al, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            script.forEach_testConvertUlong3Ushort3Ulong3(inV, out);
+            verifyResultsConvertUshort3Ulong3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong3Ushort3Ulong3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong3Ushort3Ulong3(inV, out);
+            verifyResultsConvertUshort3Ulong3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong3Ushort3Ulong3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort3Ulong3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUlong args = new ArgumentsUshortUlong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort3Ulong3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUshort4Ulong4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 4, 0xc36dab4119498818l, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            script.forEach_testConvertUlong4Ushort4Ulong4(inV, out);
+            verifyResultsConvertUshort4Ulong4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong4Ushort4Ulong4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong4Ushort4Ulong4(inV, out);
+            verifyResultsConvertUshort4Ulong4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong4Ushort4Ulong4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort4Ulong4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUlong args = new ArgumentsUshortUlong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUshort4Ulong4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsIntUlong {
+        public int inV;
+        public long out;
+    }
+
+    private void checkConvertInt2Ulong2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 2, 0x2a53676074a824f6l, false, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            script.forEach_testConvertUlong2Int2Ulong2(inV, out);
+            verifyResultsConvertInt2Ulong2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong2Int2Ulong2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong2Int2Ulong2(inV, out);
+            verifyResultsConvertInt2Ulong2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong2Int2Ulong2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt2Ulong2(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntUlong args = new ArgumentsIntUlong();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt2Ulong2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertInt3Ulong3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 3, 0x2a55307b6ac345d4l, false, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            script.forEach_testConvertUlong3Int3Ulong3(inV, out);
+            verifyResultsConvertInt3Ulong3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong3Int3Ulong3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong3Int3Ulong3(inV, out);
+            verifyResultsConvertInt3Ulong3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong3Int3Ulong3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt3Ulong3(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntUlong args = new ArgumentsIntUlong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt3Ulong3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertInt4Ulong4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 4, 0x2a56f99660de66b2l, false, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            script.forEach_testConvertUlong4Int4Ulong4(inV, out);
+            verifyResultsConvertInt4Ulong4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong4Int4Ulong4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong4Int4Ulong4(inV, out);
+            verifyResultsConvertInt4Ulong4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong4Int4Ulong4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt4Ulong4(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntUlong args = new ArgumentsIntUlong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%d", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertInt4Ulong4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUintUlong {
+        public int inV;
+        public long out;
+    }
+
+    private void checkConvertUint2Ulong2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 2, 0xd1e120ae072a3177l, false, 32);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            script.forEach_testConvertUlong2Uint2Ulong2(inV, out);
+            verifyResultsConvertUint2Ulong2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong2Uint2Ulong2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong2Uint2Ulong2(inV, out);
+            verifyResultsConvertUint2Ulong2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong2Uint2Ulong2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint2Ulong2(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUlong args = new ArgumentsUintUlong();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint2Ulong2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUint3Ulong3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 3, 0xd1e2e9c8fd455255l, false, 32);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            script.forEach_testConvertUlong3Uint3Ulong3(inV, out);
+            verifyResultsConvertUint3Ulong3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong3Uint3Ulong3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong3Uint3Ulong3(inV, out);
+            verifyResultsConvertUint3Ulong3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong3Uint3Ulong3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint3Ulong3(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUlong args = new ArgumentsUintUlong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint3Ulong3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkConvertUint4Ulong4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 4, 0xd1e4b2e3f3607333l, false, 32);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            script.forEach_testConvertUlong4Uint4Ulong4(inV, out);
+            verifyResultsConvertUint4Ulong4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong4Uint4Ulong4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong4Uint4Ulong4(inV, out);
+            verifyResultsConvertUint4Ulong4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong4Uint4Ulong4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint4Ulong4(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUlong args = new ArgumentsUintUlong();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeConvert(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("0x%x", args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkConvertUint4Ulong4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testConvert() {
+        checkConvertFloat2Float2();
+        checkConvertFloat3Float3();
+        checkConvertFloat4Float4();
+        checkConvertChar2Float2();
+        checkConvertChar3Float3();
+        checkConvertChar4Float4();
+        checkConvertUchar2Float2();
+        checkConvertUchar3Float3();
+        checkConvertUchar4Float4();
+        checkConvertShort2Float2();
+        checkConvertShort3Float3();
+        checkConvertShort4Float4();
+        checkConvertUshort2Float2();
+        checkConvertUshort3Float3();
+        checkConvertUshort4Float4();
+        checkConvertInt2Float2();
+        checkConvertInt3Float3();
+        checkConvertInt4Float4();
+        checkConvertUint2Float2();
+        checkConvertUint3Float3();
+        checkConvertUint4Float4();
+        checkConvertFloat2Char2();
+        checkConvertFloat3Char3();
+        checkConvertFloat4Char4();
+        checkConvertChar2Char2();
+        checkConvertChar3Char3();
+        checkConvertChar4Char4();
+        checkConvertUchar2Char2();
+        checkConvertUchar3Char3();
+        checkConvertUchar4Char4();
+        checkConvertShort2Char2();
+        checkConvertShort3Char3();
+        checkConvertShort4Char4();
+        checkConvertUshort2Char2();
+        checkConvertUshort3Char3();
+        checkConvertUshort4Char4();
+        checkConvertInt2Char2();
+        checkConvertInt3Char3();
+        checkConvertInt4Char4();
+        checkConvertUint2Char2();
+        checkConvertUint3Char3();
+        checkConvertUint4Char4();
+        checkConvertFloat2Uchar2();
+        checkConvertFloat3Uchar3();
+        checkConvertFloat4Uchar4();
+        checkConvertChar2Uchar2();
+        checkConvertChar3Uchar3();
+        checkConvertChar4Uchar4();
+        checkConvertUchar2Uchar2();
+        checkConvertUchar3Uchar3();
+        checkConvertUchar4Uchar4();
+        checkConvertShort2Uchar2();
+        checkConvertShort3Uchar3();
+        checkConvertShort4Uchar4();
+        checkConvertUshort2Uchar2();
+        checkConvertUshort3Uchar3();
+        checkConvertUshort4Uchar4();
+        checkConvertInt2Uchar2();
+        checkConvertInt3Uchar3();
+        checkConvertInt4Uchar4();
+        checkConvertUint2Uchar2();
+        checkConvertUint3Uchar3();
+        checkConvertUint4Uchar4();
+        checkConvertFloat2Short2();
+        checkConvertFloat3Short3();
+        checkConvertFloat4Short4();
+        checkConvertChar2Short2();
+        checkConvertChar3Short3();
+        checkConvertChar4Short4();
+        checkConvertUchar2Short2();
+        checkConvertUchar3Short3();
+        checkConvertUchar4Short4();
+        checkConvertShort2Short2();
+        checkConvertShort3Short3();
+        checkConvertShort4Short4();
+        checkConvertUshort2Short2();
+        checkConvertUshort3Short3();
+        checkConvertUshort4Short4();
+        checkConvertInt2Short2();
+        checkConvertInt3Short3();
+        checkConvertInt4Short4();
+        checkConvertUint2Short2();
+        checkConvertUint3Short3();
+        checkConvertUint4Short4();
+        checkConvertFloat2Ushort2();
+        checkConvertFloat3Ushort3();
+        checkConvertFloat4Ushort4();
+        checkConvertChar2Ushort2();
+        checkConvertChar3Ushort3();
+        checkConvertChar4Ushort4();
+        checkConvertUchar2Ushort2();
+        checkConvertUchar3Ushort3();
+        checkConvertUchar4Ushort4();
+        checkConvertShort2Ushort2();
+        checkConvertShort3Ushort3();
+        checkConvertShort4Ushort4();
+        checkConvertUshort2Ushort2();
+        checkConvertUshort3Ushort3();
+        checkConvertUshort4Ushort4();
+        checkConvertInt2Ushort2();
+        checkConvertInt3Ushort3();
+        checkConvertInt4Ushort4();
+        checkConvertUint2Ushort2();
+        checkConvertUint3Ushort3();
+        checkConvertUint4Ushort4();
+        checkConvertFloat2Int2();
+        checkConvertFloat3Int3();
+        checkConvertFloat4Int4();
+        checkConvertChar2Int2();
+        checkConvertChar3Int3();
+        checkConvertChar4Int4();
+        checkConvertUchar2Int2();
+        checkConvertUchar3Int3();
+        checkConvertUchar4Int4();
+        checkConvertShort2Int2();
+        checkConvertShort3Int3();
+        checkConvertShort4Int4();
+        checkConvertUshort2Int2();
+        checkConvertUshort3Int3();
+        checkConvertUshort4Int4();
+        checkConvertInt2Int2();
+        checkConvertInt3Int3();
+        checkConvertInt4Int4();
+        checkConvertUint2Int2();
+        checkConvertUint3Int3();
+        checkConvertUint4Int4();
+        checkConvertFloat2Uint2();
+        checkConvertFloat3Uint3();
+        checkConvertFloat4Uint4();
+        checkConvertChar2Uint2();
+        checkConvertChar3Uint3();
+        checkConvertChar4Uint4();
+        checkConvertUchar2Uint2();
+        checkConvertUchar3Uint3();
+        checkConvertUchar4Uint4();
+        checkConvertShort2Uint2();
+        checkConvertShort3Uint3();
+        checkConvertShort4Uint4();
+        checkConvertUshort2Uint2();
+        checkConvertUshort3Uint3();
+        checkConvertUshort4Uint4();
+        checkConvertInt2Uint2();
+        checkConvertInt3Uint3();
+        checkConvertInt4Uint4();
+        checkConvertUint2Uint2();
+        checkConvertUint3Uint3();
+        checkConvertUint4Uint4();
+        checkConvertDouble2Double2();
+        checkConvertDouble3Double3();
+        checkConvertDouble4Double4();
+        checkConvertLong2Double2();
+        checkConvertLong3Double3();
+        checkConvertLong4Double4();
+        checkConvertUlong2Double2();
+        checkConvertUlong3Double3();
+        checkConvertUlong4Double4();
+        checkConvertDouble2Long2();
+        checkConvertDouble3Long3();
+        checkConvertDouble4Long4();
+        checkConvertLong2Long2();
+        checkConvertLong3Long3();
+        checkConvertLong4Long4();
+        checkConvertUlong2Long2();
+        checkConvertUlong3Long3();
+        checkConvertUlong4Long4();
+        checkConvertDouble2Ulong2();
+        checkConvertDouble3Ulong3();
+        checkConvertDouble4Ulong4();
+        checkConvertLong2Ulong2();
+        checkConvertLong3Ulong3();
+        checkConvertLong4Ulong4();
+        checkConvertUlong2Ulong2();
+        checkConvertUlong3Ulong3();
+        checkConvertUlong4Ulong4();
+        checkConvertDouble2Float2();
+        checkConvertDouble3Float3();
+        checkConvertDouble4Float4();
+        checkConvertLong2Float2();
+        checkConvertLong3Float3();
+        checkConvertLong4Float4();
+        checkConvertUlong2Float2();
+        checkConvertUlong3Float3();
+        checkConvertUlong4Float4();
+        checkConvertDouble2Char2();
+        checkConvertDouble3Char3();
+        checkConvertDouble4Char4();
+        checkConvertLong2Char2();
+        checkConvertLong3Char3();
+        checkConvertLong4Char4();
+        checkConvertUlong2Char2();
+        checkConvertUlong3Char3();
+        checkConvertUlong4Char4();
+        checkConvertDouble2Uchar2();
+        checkConvertDouble3Uchar3();
+        checkConvertDouble4Uchar4();
+        checkConvertLong2Uchar2();
+        checkConvertLong3Uchar3();
+        checkConvertLong4Uchar4();
+        checkConvertUlong2Uchar2();
+        checkConvertUlong3Uchar3();
+        checkConvertUlong4Uchar4();
+        checkConvertDouble2Short2();
+        checkConvertDouble3Short3();
+        checkConvertDouble4Short4();
+        checkConvertLong2Short2();
+        checkConvertLong3Short3();
+        checkConvertLong4Short4();
+        checkConvertUlong2Short2();
+        checkConvertUlong3Short3();
+        checkConvertUlong4Short4();
+        checkConvertDouble2Ushort2();
+        checkConvertDouble3Ushort3();
+        checkConvertDouble4Ushort4();
+        checkConvertLong2Ushort2();
+        checkConvertLong3Ushort3();
+        checkConvertLong4Ushort4();
+        checkConvertUlong2Ushort2();
+        checkConvertUlong3Ushort3();
+        checkConvertUlong4Ushort4();
+        checkConvertDouble2Int2();
+        checkConvertDouble3Int3();
+        checkConvertDouble4Int4();
+        checkConvertLong2Int2();
+        checkConvertLong3Int3();
+        checkConvertLong4Int4();
+        checkConvertUlong2Int2();
+        checkConvertUlong3Int3();
+        checkConvertUlong4Int4();
+        checkConvertDouble2Uint2();
+        checkConvertDouble3Uint3();
+        checkConvertDouble4Uint4();
+        checkConvertLong2Uint2();
+        checkConvertLong3Uint3();
+        checkConvertLong4Uint4();
+        checkConvertUlong2Uint2();
+        checkConvertUlong3Uint3();
+        checkConvertUlong4Uint4();
+        checkConvertFloat2Double2();
+        checkConvertFloat3Double3();
+        checkConvertFloat4Double4();
+        checkConvertChar2Double2();
+        checkConvertChar3Double3();
+        checkConvertChar4Double4();
+        checkConvertUchar2Double2();
+        checkConvertUchar3Double3();
+        checkConvertUchar4Double4();
+        checkConvertShort2Double2();
+        checkConvertShort3Double3();
+        checkConvertShort4Double4();
+        checkConvertUshort2Double2();
+        checkConvertUshort3Double3();
+        checkConvertUshort4Double4();
+        checkConvertInt2Double2();
+        checkConvertInt3Double3();
+        checkConvertInt4Double4();
+        checkConvertUint2Double2();
+        checkConvertUint3Double3();
+        checkConvertUint4Double4();
+        checkConvertFloat2Long2();
+        checkConvertFloat3Long3();
+        checkConvertFloat4Long4();
+        checkConvertChar2Long2();
+        checkConvertChar3Long3();
+        checkConvertChar4Long4();
+        checkConvertUchar2Long2();
+        checkConvertUchar3Long3();
+        checkConvertUchar4Long4();
+        checkConvertShort2Long2();
+        checkConvertShort3Long3();
+        checkConvertShort4Long4();
+        checkConvertUshort2Long2();
+        checkConvertUshort3Long3();
+        checkConvertUshort4Long4();
+        checkConvertInt2Long2();
+        checkConvertInt3Long3();
+        checkConvertInt4Long4();
+        checkConvertUint2Long2();
+        checkConvertUint3Long3();
+        checkConvertUint4Long4();
+        checkConvertFloat2Ulong2();
+        checkConvertFloat3Ulong3();
+        checkConvertFloat4Ulong4();
+        checkConvertChar2Ulong2();
+        checkConvertChar3Ulong3();
+        checkConvertChar4Ulong4();
+        checkConvertUchar2Ulong2();
+        checkConvertUchar3Ulong3();
+        checkConvertUchar4Ulong4();
+        checkConvertShort2Ulong2();
+        checkConvertShort3Ulong3();
+        checkConvertShort4Ulong4();
+        checkConvertUshort2Ulong2();
+        checkConvertUshort3Ulong3();
+        checkConvertUshort4Ulong4();
+        checkConvertInt2Ulong2();
+        checkConvertInt3Ulong3();
+        checkConvertInt4Ulong4();
+        checkConvertUint2Ulong2();
+        checkConvertUint3Ulong3();
+        checkConvertUint4Ulong4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestConvert.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestConvert.rs
new file mode 100644
index 0000000..7c94d5e
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestConvert.rs
@@ -0,0 +1,1221 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float2 __attribute__((kernel)) testConvertFloat2Float2Float2(float2 inV) {
+    return convert_float2(inV);
+}
+
+float3 __attribute__((kernel)) testConvertFloat3Float3Float3(float3 inV) {
+    return convert_float3(inV);
+}
+
+float4 __attribute__((kernel)) testConvertFloat4Float4Float4(float4 inV) {
+    return convert_float4(inV);
+}
+
+float2 __attribute__((kernel)) testConvertFloat2Char2Float2(char2 inV) {
+    return convert_float2(inV);
+}
+
+float3 __attribute__((kernel)) testConvertFloat3Char3Float3(char3 inV) {
+    return convert_float3(inV);
+}
+
+float4 __attribute__((kernel)) testConvertFloat4Char4Float4(char4 inV) {
+    return convert_float4(inV);
+}
+
+float2 __attribute__((kernel)) testConvertFloat2Uchar2Float2(uchar2 inV) {
+    return convert_float2(inV);
+}
+
+float3 __attribute__((kernel)) testConvertFloat3Uchar3Float3(uchar3 inV) {
+    return convert_float3(inV);
+}
+
+float4 __attribute__((kernel)) testConvertFloat4Uchar4Float4(uchar4 inV) {
+    return convert_float4(inV);
+}
+
+float2 __attribute__((kernel)) testConvertFloat2Short2Float2(short2 inV) {
+    return convert_float2(inV);
+}
+
+float3 __attribute__((kernel)) testConvertFloat3Short3Float3(short3 inV) {
+    return convert_float3(inV);
+}
+
+float4 __attribute__((kernel)) testConvertFloat4Short4Float4(short4 inV) {
+    return convert_float4(inV);
+}
+
+float2 __attribute__((kernel)) testConvertFloat2Ushort2Float2(ushort2 inV) {
+    return convert_float2(inV);
+}
+
+float3 __attribute__((kernel)) testConvertFloat3Ushort3Float3(ushort3 inV) {
+    return convert_float3(inV);
+}
+
+float4 __attribute__((kernel)) testConvertFloat4Ushort4Float4(ushort4 inV) {
+    return convert_float4(inV);
+}
+
+float2 __attribute__((kernel)) testConvertFloat2Int2Float2(int2 inV) {
+    return convert_float2(inV);
+}
+
+float3 __attribute__((kernel)) testConvertFloat3Int3Float3(int3 inV) {
+    return convert_float3(inV);
+}
+
+float4 __attribute__((kernel)) testConvertFloat4Int4Float4(int4 inV) {
+    return convert_float4(inV);
+}
+
+float2 __attribute__((kernel)) testConvertFloat2Uint2Float2(uint2 inV) {
+    return convert_float2(inV);
+}
+
+float3 __attribute__((kernel)) testConvertFloat3Uint3Float3(uint3 inV) {
+    return convert_float3(inV);
+}
+
+float4 __attribute__((kernel)) testConvertFloat4Uint4Float4(uint4 inV) {
+    return convert_float4(inV);
+}
+
+char2 __attribute__((kernel)) testConvertChar2Float2Char2(float2 inV) {
+    return convert_char2(inV);
+}
+
+char3 __attribute__((kernel)) testConvertChar3Float3Char3(float3 inV) {
+    return convert_char3(inV);
+}
+
+char4 __attribute__((kernel)) testConvertChar4Float4Char4(float4 inV) {
+    return convert_char4(inV);
+}
+
+char2 __attribute__((kernel)) testConvertChar2Char2Char2(char2 inV) {
+    return convert_char2(inV);
+}
+
+char3 __attribute__((kernel)) testConvertChar3Char3Char3(char3 inV) {
+    return convert_char3(inV);
+}
+
+char4 __attribute__((kernel)) testConvertChar4Char4Char4(char4 inV) {
+    return convert_char4(inV);
+}
+
+char2 __attribute__((kernel)) testConvertChar2Uchar2Char2(uchar2 inV) {
+    return convert_char2(inV);
+}
+
+char3 __attribute__((kernel)) testConvertChar3Uchar3Char3(uchar3 inV) {
+    return convert_char3(inV);
+}
+
+char4 __attribute__((kernel)) testConvertChar4Uchar4Char4(uchar4 inV) {
+    return convert_char4(inV);
+}
+
+char2 __attribute__((kernel)) testConvertChar2Short2Char2(short2 inV) {
+    return convert_char2(inV);
+}
+
+char3 __attribute__((kernel)) testConvertChar3Short3Char3(short3 inV) {
+    return convert_char3(inV);
+}
+
+char4 __attribute__((kernel)) testConvertChar4Short4Char4(short4 inV) {
+    return convert_char4(inV);
+}
+
+char2 __attribute__((kernel)) testConvertChar2Ushort2Char2(ushort2 inV) {
+    return convert_char2(inV);
+}
+
+char3 __attribute__((kernel)) testConvertChar3Ushort3Char3(ushort3 inV) {
+    return convert_char3(inV);
+}
+
+char4 __attribute__((kernel)) testConvertChar4Ushort4Char4(ushort4 inV) {
+    return convert_char4(inV);
+}
+
+char2 __attribute__((kernel)) testConvertChar2Int2Char2(int2 inV) {
+    return convert_char2(inV);
+}
+
+char3 __attribute__((kernel)) testConvertChar3Int3Char3(int3 inV) {
+    return convert_char3(inV);
+}
+
+char4 __attribute__((kernel)) testConvertChar4Int4Char4(int4 inV) {
+    return convert_char4(inV);
+}
+
+char2 __attribute__((kernel)) testConvertChar2Uint2Char2(uint2 inV) {
+    return convert_char2(inV);
+}
+
+char3 __attribute__((kernel)) testConvertChar3Uint3Char3(uint3 inV) {
+    return convert_char3(inV);
+}
+
+char4 __attribute__((kernel)) testConvertChar4Uint4Char4(uint4 inV) {
+    return convert_char4(inV);
+}
+
+uchar2 __attribute__((kernel)) testConvertUchar2Float2Uchar2(float2 inV) {
+    return convert_uchar2(inV);
+}
+
+uchar3 __attribute__((kernel)) testConvertUchar3Float3Uchar3(float3 inV) {
+    return convert_uchar3(inV);
+}
+
+uchar4 __attribute__((kernel)) testConvertUchar4Float4Uchar4(float4 inV) {
+    return convert_uchar4(inV);
+}
+
+uchar2 __attribute__((kernel)) testConvertUchar2Char2Uchar2(char2 inV) {
+    return convert_uchar2(inV);
+}
+
+uchar3 __attribute__((kernel)) testConvertUchar3Char3Uchar3(char3 inV) {
+    return convert_uchar3(inV);
+}
+
+uchar4 __attribute__((kernel)) testConvertUchar4Char4Uchar4(char4 inV) {
+    return convert_uchar4(inV);
+}
+
+uchar2 __attribute__((kernel)) testConvertUchar2Uchar2Uchar2(uchar2 inV) {
+    return convert_uchar2(inV);
+}
+
+uchar3 __attribute__((kernel)) testConvertUchar3Uchar3Uchar3(uchar3 inV) {
+    return convert_uchar3(inV);
+}
+
+uchar4 __attribute__((kernel)) testConvertUchar4Uchar4Uchar4(uchar4 inV) {
+    return convert_uchar4(inV);
+}
+
+uchar2 __attribute__((kernel)) testConvertUchar2Short2Uchar2(short2 inV) {
+    return convert_uchar2(inV);
+}
+
+uchar3 __attribute__((kernel)) testConvertUchar3Short3Uchar3(short3 inV) {
+    return convert_uchar3(inV);
+}
+
+uchar4 __attribute__((kernel)) testConvertUchar4Short4Uchar4(short4 inV) {
+    return convert_uchar4(inV);
+}
+
+uchar2 __attribute__((kernel)) testConvertUchar2Ushort2Uchar2(ushort2 inV) {
+    return convert_uchar2(inV);
+}
+
+uchar3 __attribute__((kernel)) testConvertUchar3Ushort3Uchar3(ushort3 inV) {
+    return convert_uchar3(inV);
+}
+
+uchar4 __attribute__((kernel)) testConvertUchar4Ushort4Uchar4(ushort4 inV) {
+    return convert_uchar4(inV);
+}
+
+uchar2 __attribute__((kernel)) testConvertUchar2Int2Uchar2(int2 inV) {
+    return convert_uchar2(inV);
+}
+
+uchar3 __attribute__((kernel)) testConvertUchar3Int3Uchar3(int3 inV) {
+    return convert_uchar3(inV);
+}
+
+uchar4 __attribute__((kernel)) testConvertUchar4Int4Uchar4(int4 inV) {
+    return convert_uchar4(inV);
+}
+
+uchar2 __attribute__((kernel)) testConvertUchar2Uint2Uchar2(uint2 inV) {
+    return convert_uchar2(inV);
+}
+
+uchar3 __attribute__((kernel)) testConvertUchar3Uint3Uchar3(uint3 inV) {
+    return convert_uchar3(inV);
+}
+
+uchar4 __attribute__((kernel)) testConvertUchar4Uint4Uchar4(uint4 inV) {
+    return convert_uchar4(inV);
+}
+
+short2 __attribute__((kernel)) testConvertShort2Float2Short2(float2 inV) {
+    return convert_short2(inV);
+}
+
+short3 __attribute__((kernel)) testConvertShort3Float3Short3(float3 inV) {
+    return convert_short3(inV);
+}
+
+short4 __attribute__((kernel)) testConvertShort4Float4Short4(float4 inV) {
+    return convert_short4(inV);
+}
+
+short2 __attribute__((kernel)) testConvertShort2Char2Short2(char2 inV) {
+    return convert_short2(inV);
+}
+
+short3 __attribute__((kernel)) testConvertShort3Char3Short3(char3 inV) {
+    return convert_short3(inV);
+}
+
+short4 __attribute__((kernel)) testConvertShort4Char4Short4(char4 inV) {
+    return convert_short4(inV);
+}
+
+short2 __attribute__((kernel)) testConvertShort2Uchar2Short2(uchar2 inV) {
+    return convert_short2(inV);
+}
+
+short3 __attribute__((kernel)) testConvertShort3Uchar3Short3(uchar3 inV) {
+    return convert_short3(inV);
+}
+
+short4 __attribute__((kernel)) testConvertShort4Uchar4Short4(uchar4 inV) {
+    return convert_short4(inV);
+}
+
+short2 __attribute__((kernel)) testConvertShort2Short2Short2(short2 inV) {
+    return convert_short2(inV);
+}
+
+short3 __attribute__((kernel)) testConvertShort3Short3Short3(short3 inV) {
+    return convert_short3(inV);
+}
+
+short4 __attribute__((kernel)) testConvertShort4Short4Short4(short4 inV) {
+    return convert_short4(inV);
+}
+
+short2 __attribute__((kernel)) testConvertShort2Ushort2Short2(ushort2 inV) {
+    return convert_short2(inV);
+}
+
+short3 __attribute__((kernel)) testConvertShort3Ushort3Short3(ushort3 inV) {
+    return convert_short3(inV);
+}
+
+short4 __attribute__((kernel)) testConvertShort4Ushort4Short4(ushort4 inV) {
+    return convert_short4(inV);
+}
+
+short2 __attribute__((kernel)) testConvertShort2Int2Short2(int2 inV) {
+    return convert_short2(inV);
+}
+
+short3 __attribute__((kernel)) testConvertShort3Int3Short3(int3 inV) {
+    return convert_short3(inV);
+}
+
+short4 __attribute__((kernel)) testConvertShort4Int4Short4(int4 inV) {
+    return convert_short4(inV);
+}
+
+short2 __attribute__((kernel)) testConvertShort2Uint2Short2(uint2 inV) {
+    return convert_short2(inV);
+}
+
+short3 __attribute__((kernel)) testConvertShort3Uint3Short3(uint3 inV) {
+    return convert_short3(inV);
+}
+
+short4 __attribute__((kernel)) testConvertShort4Uint4Short4(uint4 inV) {
+    return convert_short4(inV);
+}
+
+ushort2 __attribute__((kernel)) testConvertUshort2Float2Ushort2(float2 inV) {
+    return convert_ushort2(inV);
+}
+
+ushort3 __attribute__((kernel)) testConvertUshort3Float3Ushort3(float3 inV) {
+    return convert_ushort3(inV);
+}
+
+ushort4 __attribute__((kernel)) testConvertUshort4Float4Ushort4(float4 inV) {
+    return convert_ushort4(inV);
+}
+
+ushort2 __attribute__((kernel)) testConvertUshort2Char2Ushort2(char2 inV) {
+    return convert_ushort2(inV);
+}
+
+ushort3 __attribute__((kernel)) testConvertUshort3Char3Ushort3(char3 inV) {
+    return convert_ushort3(inV);
+}
+
+ushort4 __attribute__((kernel)) testConvertUshort4Char4Ushort4(char4 inV) {
+    return convert_ushort4(inV);
+}
+
+ushort2 __attribute__((kernel)) testConvertUshort2Uchar2Ushort2(uchar2 inV) {
+    return convert_ushort2(inV);
+}
+
+ushort3 __attribute__((kernel)) testConvertUshort3Uchar3Ushort3(uchar3 inV) {
+    return convert_ushort3(inV);
+}
+
+ushort4 __attribute__((kernel)) testConvertUshort4Uchar4Ushort4(uchar4 inV) {
+    return convert_ushort4(inV);
+}
+
+ushort2 __attribute__((kernel)) testConvertUshort2Short2Ushort2(short2 inV) {
+    return convert_ushort2(inV);
+}
+
+ushort3 __attribute__((kernel)) testConvertUshort3Short3Ushort3(short3 inV) {
+    return convert_ushort3(inV);
+}
+
+ushort4 __attribute__((kernel)) testConvertUshort4Short4Ushort4(short4 inV) {
+    return convert_ushort4(inV);
+}
+
+ushort2 __attribute__((kernel)) testConvertUshort2Ushort2Ushort2(ushort2 inV) {
+    return convert_ushort2(inV);
+}
+
+ushort3 __attribute__((kernel)) testConvertUshort3Ushort3Ushort3(ushort3 inV) {
+    return convert_ushort3(inV);
+}
+
+ushort4 __attribute__((kernel)) testConvertUshort4Ushort4Ushort4(ushort4 inV) {
+    return convert_ushort4(inV);
+}
+
+ushort2 __attribute__((kernel)) testConvertUshort2Int2Ushort2(int2 inV) {
+    return convert_ushort2(inV);
+}
+
+ushort3 __attribute__((kernel)) testConvertUshort3Int3Ushort3(int3 inV) {
+    return convert_ushort3(inV);
+}
+
+ushort4 __attribute__((kernel)) testConvertUshort4Int4Ushort4(int4 inV) {
+    return convert_ushort4(inV);
+}
+
+ushort2 __attribute__((kernel)) testConvertUshort2Uint2Ushort2(uint2 inV) {
+    return convert_ushort2(inV);
+}
+
+ushort3 __attribute__((kernel)) testConvertUshort3Uint3Ushort3(uint3 inV) {
+    return convert_ushort3(inV);
+}
+
+ushort4 __attribute__((kernel)) testConvertUshort4Uint4Ushort4(uint4 inV) {
+    return convert_ushort4(inV);
+}
+
+int2 __attribute__((kernel)) testConvertInt2Float2Int2(float2 inV) {
+    return convert_int2(inV);
+}
+
+int3 __attribute__((kernel)) testConvertInt3Float3Int3(float3 inV) {
+    return convert_int3(inV);
+}
+
+int4 __attribute__((kernel)) testConvertInt4Float4Int4(float4 inV) {
+    return convert_int4(inV);
+}
+
+int2 __attribute__((kernel)) testConvertInt2Char2Int2(char2 inV) {
+    return convert_int2(inV);
+}
+
+int3 __attribute__((kernel)) testConvertInt3Char3Int3(char3 inV) {
+    return convert_int3(inV);
+}
+
+int4 __attribute__((kernel)) testConvertInt4Char4Int4(char4 inV) {
+    return convert_int4(inV);
+}
+
+int2 __attribute__((kernel)) testConvertInt2Uchar2Int2(uchar2 inV) {
+    return convert_int2(inV);
+}
+
+int3 __attribute__((kernel)) testConvertInt3Uchar3Int3(uchar3 inV) {
+    return convert_int3(inV);
+}
+
+int4 __attribute__((kernel)) testConvertInt4Uchar4Int4(uchar4 inV) {
+    return convert_int4(inV);
+}
+
+int2 __attribute__((kernel)) testConvertInt2Short2Int2(short2 inV) {
+    return convert_int2(inV);
+}
+
+int3 __attribute__((kernel)) testConvertInt3Short3Int3(short3 inV) {
+    return convert_int3(inV);
+}
+
+int4 __attribute__((kernel)) testConvertInt4Short4Int4(short4 inV) {
+    return convert_int4(inV);
+}
+
+int2 __attribute__((kernel)) testConvertInt2Ushort2Int2(ushort2 inV) {
+    return convert_int2(inV);
+}
+
+int3 __attribute__((kernel)) testConvertInt3Ushort3Int3(ushort3 inV) {
+    return convert_int3(inV);
+}
+
+int4 __attribute__((kernel)) testConvertInt4Ushort4Int4(ushort4 inV) {
+    return convert_int4(inV);
+}
+
+int2 __attribute__((kernel)) testConvertInt2Int2Int2(int2 inV) {
+    return convert_int2(inV);
+}
+
+int3 __attribute__((kernel)) testConvertInt3Int3Int3(int3 inV) {
+    return convert_int3(inV);
+}
+
+int4 __attribute__((kernel)) testConvertInt4Int4Int4(int4 inV) {
+    return convert_int4(inV);
+}
+
+int2 __attribute__((kernel)) testConvertInt2Uint2Int2(uint2 inV) {
+    return convert_int2(inV);
+}
+
+int3 __attribute__((kernel)) testConvertInt3Uint3Int3(uint3 inV) {
+    return convert_int3(inV);
+}
+
+int4 __attribute__((kernel)) testConvertInt4Uint4Int4(uint4 inV) {
+    return convert_int4(inV);
+}
+
+uint2 __attribute__((kernel)) testConvertUint2Float2Uint2(float2 inV) {
+    return convert_uint2(inV);
+}
+
+uint3 __attribute__((kernel)) testConvertUint3Float3Uint3(float3 inV) {
+    return convert_uint3(inV);
+}
+
+uint4 __attribute__((kernel)) testConvertUint4Float4Uint4(float4 inV) {
+    return convert_uint4(inV);
+}
+
+uint2 __attribute__((kernel)) testConvertUint2Char2Uint2(char2 inV) {
+    return convert_uint2(inV);
+}
+
+uint3 __attribute__((kernel)) testConvertUint3Char3Uint3(char3 inV) {
+    return convert_uint3(inV);
+}
+
+uint4 __attribute__((kernel)) testConvertUint4Char4Uint4(char4 inV) {
+    return convert_uint4(inV);
+}
+
+uint2 __attribute__((kernel)) testConvertUint2Uchar2Uint2(uchar2 inV) {
+    return convert_uint2(inV);
+}
+
+uint3 __attribute__((kernel)) testConvertUint3Uchar3Uint3(uchar3 inV) {
+    return convert_uint3(inV);
+}
+
+uint4 __attribute__((kernel)) testConvertUint4Uchar4Uint4(uchar4 inV) {
+    return convert_uint4(inV);
+}
+
+uint2 __attribute__((kernel)) testConvertUint2Short2Uint2(short2 inV) {
+    return convert_uint2(inV);
+}
+
+uint3 __attribute__((kernel)) testConvertUint3Short3Uint3(short3 inV) {
+    return convert_uint3(inV);
+}
+
+uint4 __attribute__((kernel)) testConvertUint4Short4Uint4(short4 inV) {
+    return convert_uint4(inV);
+}
+
+uint2 __attribute__((kernel)) testConvertUint2Ushort2Uint2(ushort2 inV) {
+    return convert_uint2(inV);
+}
+
+uint3 __attribute__((kernel)) testConvertUint3Ushort3Uint3(ushort3 inV) {
+    return convert_uint3(inV);
+}
+
+uint4 __attribute__((kernel)) testConvertUint4Ushort4Uint4(ushort4 inV) {
+    return convert_uint4(inV);
+}
+
+uint2 __attribute__((kernel)) testConvertUint2Int2Uint2(int2 inV) {
+    return convert_uint2(inV);
+}
+
+uint3 __attribute__((kernel)) testConvertUint3Int3Uint3(int3 inV) {
+    return convert_uint3(inV);
+}
+
+uint4 __attribute__((kernel)) testConvertUint4Int4Uint4(int4 inV) {
+    return convert_uint4(inV);
+}
+
+uint2 __attribute__((kernel)) testConvertUint2Uint2Uint2(uint2 inV) {
+    return convert_uint2(inV);
+}
+
+uint3 __attribute__((kernel)) testConvertUint3Uint3Uint3(uint3 inV) {
+    return convert_uint3(inV);
+}
+
+uint4 __attribute__((kernel)) testConvertUint4Uint4Uint4(uint4 inV) {
+    return convert_uint4(inV);
+}
+
+double2 __attribute__((kernel)) testConvertDouble2Double2Double2(double2 inV) {
+    return convert_double2(inV);
+}
+
+double3 __attribute__((kernel)) testConvertDouble3Double3Double3(double3 inV) {
+    return convert_double3(inV);
+}
+
+double4 __attribute__((kernel)) testConvertDouble4Double4Double4(double4 inV) {
+    return convert_double4(inV);
+}
+
+double2 __attribute__((kernel)) testConvertDouble2Long2Double2(long2 inV) {
+    return convert_double2(inV);
+}
+
+double3 __attribute__((kernel)) testConvertDouble3Long3Double3(long3 inV) {
+    return convert_double3(inV);
+}
+
+double4 __attribute__((kernel)) testConvertDouble4Long4Double4(long4 inV) {
+    return convert_double4(inV);
+}
+
+double2 __attribute__((kernel)) testConvertDouble2Ulong2Double2(ulong2 inV) {
+    return convert_double2(inV);
+}
+
+double3 __attribute__((kernel)) testConvertDouble3Ulong3Double3(ulong3 inV) {
+    return convert_double3(inV);
+}
+
+double4 __attribute__((kernel)) testConvertDouble4Ulong4Double4(ulong4 inV) {
+    return convert_double4(inV);
+}
+
+long2 __attribute__((kernel)) testConvertLong2Double2Long2(double2 inV) {
+    return convert_long2(inV);
+}
+
+long3 __attribute__((kernel)) testConvertLong3Double3Long3(double3 inV) {
+    return convert_long3(inV);
+}
+
+long4 __attribute__((kernel)) testConvertLong4Double4Long4(double4 inV) {
+    return convert_long4(inV);
+}
+
+long2 __attribute__((kernel)) testConvertLong2Long2Long2(long2 inV) {
+    return convert_long2(inV);
+}
+
+long3 __attribute__((kernel)) testConvertLong3Long3Long3(long3 inV) {
+    return convert_long3(inV);
+}
+
+long4 __attribute__((kernel)) testConvertLong4Long4Long4(long4 inV) {
+    return convert_long4(inV);
+}
+
+long2 __attribute__((kernel)) testConvertLong2Ulong2Long2(ulong2 inV) {
+    return convert_long2(inV);
+}
+
+long3 __attribute__((kernel)) testConvertLong3Ulong3Long3(ulong3 inV) {
+    return convert_long3(inV);
+}
+
+long4 __attribute__((kernel)) testConvertLong4Ulong4Long4(ulong4 inV) {
+    return convert_long4(inV);
+}
+
+ulong2 __attribute__((kernel)) testConvertUlong2Double2Ulong2(double2 inV) {
+    return convert_ulong2(inV);
+}
+
+ulong3 __attribute__((kernel)) testConvertUlong3Double3Ulong3(double3 inV) {
+    return convert_ulong3(inV);
+}
+
+ulong4 __attribute__((kernel)) testConvertUlong4Double4Ulong4(double4 inV) {
+    return convert_ulong4(inV);
+}
+
+ulong2 __attribute__((kernel)) testConvertUlong2Long2Ulong2(long2 inV) {
+    return convert_ulong2(inV);
+}
+
+ulong3 __attribute__((kernel)) testConvertUlong3Long3Ulong3(long3 inV) {
+    return convert_ulong3(inV);
+}
+
+ulong4 __attribute__((kernel)) testConvertUlong4Long4Ulong4(long4 inV) {
+    return convert_ulong4(inV);
+}
+
+ulong2 __attribute__((kernel)) testConvertUlong2Ulong2Ulong2(ulong2 inV) {
+    return convert_ulong2(inV);
+}
+
+ulong3 __attribute__((kernel)) testConvertUlong3Ulong3Ulong3(ulong3 inV) {
+    return convert_ulong3(inV);
+}
+
+ulong4 __attribute__((kernel)) testConvertUlong4Ulong4Ulong4(ulong4 inV) {
+    return convert_ulong4(inV);
+}
+
+float2 __attribute__((kernel)) testConvertFloat2Double2Float2(double2 inV) {
+    return convert_float2(inV);
+}
+
+float3 __attribute__((kernel)) testConvertFloat3Double3Float3(double3 inV) {
+    return convert_float3(inV);
+}
+
+float4 __attribute__((kernel)) testConvertFloat4Double4Float4(double4 inV) {
+    return convert_float4(inV);
+}
+
+float2 __attribute__((kernel)) testConvertFloat2Long2Float2(long2 inV) {
+    return convert_float2(inV);
+}
+
+float3 __attribute__((kernel)) testConvertFloat3Long3Float3(long3 inV) {
+    return convert_float3(inV);
+}
+
+float4 __attribute__((kernel)) testConvertFloat4Long4Float4(long4 inV) {
+    return convert_float4(inV);
+}
+
+float2 __attribute__((kernel)) testConvertFloat2Ulong2Float2(ulong2 inV) {
+    return convert_float2(inV);
+}
+
+float3 __attribute__((kernel)) testConvertFloat3Ulong3Float3(ulong3 inV) {
+    return convert_float3(inV);
+}
+
+float4 __attribute__((kernel)) testConvertFloat4Ulong4Float4(ulong4 inV) {
+    return convert_float4(inV);
+}
+
+char2 __attribute__((kernel)) testConvertChar2Double2Char2(double2 inV) {
+    return convert_char2(inV);
+}
+
+char3 __attribute__((kernel)) testConvertChar3Double3Char3(double3 inV) {
+    return convert_char3(inV);
+}
+
+char4 __attribute__((kernel)) testConvertChar4Double4Char4(double4 inV) {
+    return convert_char4(inV);
+}
+
+char2 __attribute__((kernel)) testConvertChar2Long2Char2(long2 inV) {
+    return convert_char2(inV);
+}
+
+char3 __attribute__((kernel)) testConvertChar3Long3Char3(long3 inV) {
+    return convert_char3(inV);
+}
+
+char4 __attribute__((kernel)) testConvertChar4Long4Char4(long4 inV) {
+    return convert_char4(inV);
+}
+
+char2 __attribute__((kernel)) testConvertChar2Ulong2Char2(ulong2 inV) {
+    return convert_char2(inV);
+}
+
+char3 __attribute__((kernel)) testConvertChar3Ulong3Char3(ulong3 inV) {
+    return convert_char3(inV);
+}
+
+char4 __attribute__((kernel)) testConvertChar4Ulong4Char4(ulong4 inV) {
+    return convert_char4(inV);
+}
+
+uchar2 __attribute__((kernel)) testConvertUchar2Double2Uchar2(double2 inV) {
+    return convert_uchar2(inV);
+}
+
+uchar3 __attribute__((kernel)) testConvertUchar3Double3Uchar3(double3 inV) {
+    return convert_uchar3(inV);
+}
+
+uchar4 __attribute__((kernel)) testConvertUchar4Double4Uchar4(double4 inV) {
+    return convert_uchar4(inV);
+}
+
+uchar2 __attribute__((kernel)) testConvertUchar2Long2Uchar2(long2 inV) {
+    return convert_uchar2(inV);
+}
+
+uchar3 __attribute__((kernel)) testConvertUchar3Long3Uchar3(long3 inV) {
+    return convert_uchar3(inV);
+}
+
+uchar4 __attribute__((kernel)) testConvertUchar4Long4Uchar4(long4 inV) {
+    return convert_uchar4(inV);
+}
+
+uchar2 __attribute__((kernel)) testConvertUchar2Ulong2Uchar2(ulong2 inV) {
+    return convert_uchar2(inV);
+}
+
+uchar3 __attribute__((kernel)) testConvertUchar3Ulong3Uchar3(ulong3 inV) {
+    return convert_uchar3(inV);
+}
+
+uchar4 __attribute__((kernel)) testConvertUchar4Ulong4Uchar4(ulong4 inV) {
+    return convert_uchar4(inV);
+}
+
+short2 __attribute__((kernel)) testConvertShort2Double2Short2(double2 inV) {
+    return convert_short2(inV);
+}
+
+short3 __attribute__((kernel)) testConvertShort3Double3Short3(double3 inV) {
+    return convert_short3(inV);
+}
+
+short4 __attribute__((kernel)) testConvertShort4Double4Short4(double4 inV) {
+    return convert_short4(inV);
+}
+
+short2 __attribute__((kernel)) testConvertShort2Long2Short2(long2 inV) {
+    return convert_short2(inV);
+}
+
+short3 __attribute__((kernel)) testConvertShort3Long3Short3(long3 inV) {
+    return convert_short3(inV);
+}
+
+short4 __attribute__((kernel)) testConvertShort4Long4Short4(long4 inV) {
+    return convert_short4(inV);
+}
+
+short2 __attribute__((kernel)) testConvertShort2Ulong2Short2(ulong2 inV) {
+    return convert_short2(inV);
+}
+
+short3 __attribute__((kernel)) testConvertShort3Ulong3Short3(ulong3 inV) {
+    return convert_short3(inV);
+}
+
+short4 __attribute__((kernel)) testConvertShort4Ulong4Short4(ulong4 inV) {
+    return convert_short4(inV);
+}
+
+ushort2 __attribute__((kernel)) testConvertUshort2Double2Ushort2(double2 inV) {
+    return convert_ushort2(inV);
+}
+
+ushort3 __attribute__((kernel)) testConvertUshort3Double3Ushort3(double3 inV) {
+    return convert_ushort3(inV);
+}
+
+ushort4 __attribute__((kernel)) testConvertUshort4Double4Ushort4(double4 inV) {
+    return convert_ushort4(inV);
+}
+
+ushort2 __attribute__((kernel)) testConvertUshort2Long2Ushort2(long2 inV) {
+    return convert_ushort2(inV);
+}
+
+ushort3 __attribute__((kernel)) testConvertUshort3Long3Ushort3(long3 inV) {
+    return convert_ushort3(inV);
+}
+
+ushort4 __attribute__((kernel)) testConvertUshort4Long4Ushort4(long4 inV) {
+    return convert_ushort4(inV);
+}
+
+ushort2 __attribute__((kernel)) testConvertUshort2Ulong2Ushort2(ulong2 inV) {
+    return convert_ushort2(inV);
+}
+
+ushort3 __attribute__((kernel)) testConvertUshort3Ulong3Ushort3(ulong3 inV) {
+    return convert_ushort3(inV);
+}
+
+ushort4 __attribute__((kernel)) testConvertUshort4Ulong4Ushort4(ulong4 inV) {
+    return convert_ushort4(inV);
+}
+
+int2 __attribute__((kernel)) testConvertInt2Double2Int2(double2 inV) {
+    return convert_int2(inV);
+}
+
+int3 __attribute__((kernel)) testConvertInt3Double3Int3(double3 inV) {
+    return convert_int3(inV);
+}
+
+int4 __attribute__((kernel)) testConvertInt4Double4Int4(double4 inV) {
+    return convert_int4(inV);
+}
+
+int2 __attribute__((kernel)) testConvertInt2Long2Int2(long2 inV) {
+    return convert_int2(inV);
+}
+
+int3 __attribute__((kernel)) testConvertInt3Long3Int3(long3 inV) {
+    return convert_int3(inV);
+}
+
+int4 __attribute__((kernel)) testConvertInt4Long4Int4(long4 inV) {
+    return convert_int4(inV);
+}
+
+int2 __attribute__((kernel)) testConvertInt2Ulong2Int2(ulong2 inV) {
+    return convert_int2(inV);
+}
+
+int3 __attribute__((kernel)) testConvertInt3Ulong3Int3(ulong3 inV) {
+    return convert_int3(inV);
+}
+
+int4 __attribute__((kernel)) testConvertInt4Ulong4Int4(ulong4 inV) {
+    return convert_int4(inV);
+}
+
+uint2 __attribute__((kernel)) testConvertUint2Double2Uint2(double2 inV) {
+    return convert_uint2(inV);
+}
+
+uint3 __attribute__((kernel)) testConvertUint3Double3Uint3(double3 inV) {
+    return convert_uint3(inV);
+}
+
+uint4 __attribute__((kernel)) testConvertUint4Double4Uint4(double4 inV) {
+    return convert_uint4(inV);
+}
+
+uint2 __attribute__((kernel)) testConvertUint2Long2Uint2(long2 inV) {
+    return convert_uint2(inV);
+}
+
+uint3 __attribute__((kernel)) testConvertUint3Long3Uint3(long3 inV) {
+    return convert_uint3(inV);
+}
+
+uint4 __attribute__((kernel)) testConvertUint4Long4Uint4(long4 inV) {
+    return convert_uint4(inV);
+}
+
+uint2 __attribute__((kernel)) testConvertUint2Ulong2Uint2(ulong2 inV) {
+    return convert_uint2(inV);
+}
+
+uint3 __attribute__((kernel)) testConvertUint3Ulong3Uint3(ulong3 inV) {
+    return convert_uint3(inV);
+}
+
+uint4 __attribute__((kernel)) testConvertUint4Ulong4Uint4(ulong4 inV) {
+    return convert_uint4(inV);
+}
+
+double2 __attribute__((kernel)) testConvertDouble2Float2Double2(float2 inV) {
+    return convert_double2(inV);
+}
+
+double3 __attribute__((kernel)) testConvertDouble3Float3Double3(float3 inV) {
+    return convert_double3(inV);
+}
+
+double4 __attribute__((kernel)) testConvertDouble4Float4Double4(float4 inV) {
+    return convert_double4(inV);
+}
+
+double2 __attribute__((kernel)) testConvertDouble2Char2Double2(char2 inV) {
+    return convert_double2(inV);
+}
+
+double3 __attribute__((kernel)) testConvertDouble3Char3Double3(char3 inV) {
+    return convert_double3(inV);
+}
+
+double4 __attribute__((kernel)) testConvertDouble4Char4Double4(char4 inV) {
+    return convert_double4(inV);
+}
+
+double2 __attribute__((kernel)) testConvertDouble2Uchar2Double2(uchar2 inV) {
+    return convert_double2(inV);
+}
+
+double3 __attribute__((kernel)) testConvertDouble3Uchar3Double3(uchar3 inV) {
+    return convert_double3(inV);
+}
+
+double4 __attribute__((kernel)) testConvertDouble4Uchar4Double4(uchar4 inV) {
+    return convert_double4(inV);
+}
+
+double2 __attribute__((kernel)) testConvertDouble2Short2Double2(short2 inV) {
+    return convert_double2(inV);
+}
+
+double3 __attribute__((kernel)) testConvertDouble3Short3Double3(short3 inV) {
+    return convert_double3(inV);
+}
+
+double4 __attribute__((kernel)) testConvertDouble4Short4Double4(short4 inV) {
+    return convert_double4(inV);
+}
+
+double2 __attribute__((kernel)) testConvertDouble2Ushort2Double2(ushort2 inV) {
+    return convert_double2(inV);
+}
+
+double3 __attribute__((kernel)) testConvertDouble3Ushort3Double3(ushort3 inV) {
+    return convert_double3(inV);
+}
+
+double4 __attribute__((kernel)) testConvertDouble4Ushort4Double4(ushort4 inV) {
+    return convert_double4(inV);
+}
+
+double2 __attribute__((kernel)) testConvertDouble2Int2Double2(int2 inV) {
+    return convert_double2(inV);
+}
+
+double3 __attribute__((kernel)) testConvertDouble3Int3Double3(int3 inV) {
+    return convert_double3(inV);
+}
+
+double4 __attribute__((kernel)) testConvertDouble4Int4Double4(int4 inV) {
+    return convert_double4(inV);
+}
+
+double2 __attribute__((kernel)) testConvertDouble2Uint2Double2(uint2 inV) {
+    return convert_double2(inV);
+}
+
+double3 __attribute__((kernel)) testConvertDouble3Uint3Double3(uint3 inV) {
+    return convert_double3(inV);
+}
+
+double4 __attribute__((kernel)) testConvertDouble4Uint4Double4(uint4 inV) {
+    return convert_double4(inV);
+}
+
+long2 __attribute__((kernel)) testConvertLong2Float2Long2(float2 inV) {
+    return convert_long2(inV);
+}
+
+long3 __attribute__((kernel)) testConvertLong3Float3Long3(float3 inV) {
+    return convert_long3(inV);
+}
+
+long4 __attribute__((kernel)) testConvertLong4Float4Long4(float4 inV) {
+    return convert_long4(inV);
+}
+
+long2 __attribute__((kernel)) testConvertLong2Char2Long2(char2 inV) {
+    return convert_long2(inV);
+}
+
+long3 __attribute__((kernel)) testConvertLong3Char3Long3(char3 inV) {
+    return convert_long3(inV);
+}
+
+long4 __attribute__((kernel)) testConvertLong4Char4Long4(char4 inV) {
+    return convert_long4(inV);
+}
+
+long2 __attribute__((kernel)) testConvertLong2Uchar2Long2(uchar2 inV) {
+    return convert_long2(inV);
+}
+
+long3 __attribute__((kernel)) testConvertLong3Uchar3Long3(uchar3 inV) {
+    return convert_long3(inV);
+}
+
+long4 __attribute__((kernel)) testConvertLong4Uchar4Long4(uchar4 inV) {
+    return convert_long4(inV);
+}
+
+long2 __attribute__((kernel)) testConvertLong2Short2Long2(short2 inV) {
+    return convert_long2(inV);
+}
+
+long3 __attribute__((kernel)) testConvertLong3Short3Long3(short3 inV) {
+    return convert_long3(inV);
+}
+
+long4 __attribute__((kernel)) testConvertLong4Short4Long4(short4 inV) {
+    return convert_long4(inV);
+}
+
+long2 __attribute__((kernel)) testConvertLong2Ushort2Long2(ushort2 inV) {
+    return convert_long2(inV);
+}
+
+long3 __attribute__((kernel)) testConvertLong3Ushort3Long3(ushort3 inV) {
+    return convert_long3(inV);
+}
+
+long4 __attribute__((kernel)) testConvertLong4Ushort4Long4(ushort4 inV) {
+    return convert_long4(inV);
+}
+
+long2 __attribute__((kernel)) testConvertLong2Int2Long2(int2 inV) {
+    return convert_long2(inV);
+}
+
+long3 __attribute__((kernel)) testConvertLong3Int3Long3(int3 inV) {
+    return convert_long3(inV);
+}
+
+long4 __attribute__((kernel)) testConvertLong4Int4Long4(int4 inV) {
+    return convert_long4(inV);
+}
+
+long2 __attribute__((kernel)) testConvertLong2Uint2Long2(uint2 inV) {
+    return convert_long2(inV);
+}
+
+long3 __attribute__((kernel)) testConvertLong3Uint3Long3(uint3 inV) {
+    return convert_long3(inV);
+}
+
+long4 __attribute__((kernel)) testConvertLong4Uint4Long4(uint4 inV) {
+    return convert_long4(inV);
+}
+
+ulong2 __attribute__((kernel)) testConvertUlong2Float2Ulong2(float2 inV) {
+    return convert_ulong2(inV);
+}
+
+ulong3 __attribute__((kernel)) testConvertUlong3Float3Ulong3(float3 inV) {
+    return convert_ulong3(inV);
+}
+
+ulong4 __attribute__((kernel)) testConvertUlong4Float4Ulong4(float4 inV) {
+    return convert_ulong4(inV);
+}
+
+ulong2 __attribute__((kernel)) testConvertUlong2Char2Ulong2(char2 inV) {
+    return convert_ulong2(inV);
+}
+
+ulong3 __attribute__((kernel)) testConvertUlong3Char3Ulong3(char3 inV) {
+    return convert_ulong3(inV);
+}
+
+ulong4 __attribute__((kernel)) testConvertUlong4Char4Ulong4(char4 inV) {
+    return convert_ulong4(inV);
+}
+
+ulong2 __attribute__((kernel)) testConvertUlong2Uchar2Ulong2(uchar2 inV) {
+    return convert_ulong2(inV);
+}
+
+ulong3 __attribute__((kernel)) testConvertUlong3Uchar3Ulong3(uchar3 inV) {
+    return convert_ulong3(inV);
+}
+
+ulong4 __attribute__((kernel)) testConvertUlong4Uchar4Ulong4(uchar4 inV) {
+    return convert_ulong4(inV);
+}
+
+ulong2 __attribute__((kernel)) testConvertUlong2Short2Ulong2(short2 inV) {
+    return convert_ulong2(inV);
+}
+
+ulong3 __attribute__((kernel)) testConvertUlong3Short3Ulong3(short3 inV) {
+    return convert_ulong3(inV);
+}
+
+ulong4 __attribute__((kernel)) testConvertUlong4Short4Ulong4(short4 inV) {
+    return convert_ulong4(inV);
+}
+
+ulong2 __attribute__((kernel)) testConvertUlong2Ushort2Ulong2(ushort2 inV) {
+    return convert_ulong2(inV);
+}
+
+ulong3 __attribute__((kernel)) testConvertUlong3Ushort3Ulong3(ushort3 inV) {
+    return convert_ulong3(inV);
+}
+
+ulong4 __attribute__((kernel)) testConvertUlong4Ushort4Ulong4(ushort4 inV) {
+    return convert_ulong4(inV);
+}
+
+ulong2 __attribute__((kernel)) testConvertUlong2Int2Ulong2(int2 inV) {
+    return convert_ulong2(inV);
+}
+
+ulong3 __attribute__((kernel)) testConvertUlong3Int3Ulong3(int3 inV) {
+    return convert_ulong3(inV);
+}
+
+ulong4 __attribute__((kernel)) testConvertUlong4Int4Ulong4(int4 inV) {
+    return convert_ulong4(inV);
+}
+
+ulong2 __attribute__((kernel)) testConvertUlong2Uint2Ulong2(uint2 inV) {
+    return convert_ulong2(inV);
+}
+
+ulong3 __attribute__((kernel)) testConvertUlong3Uint3Ulong3(uint3 inV) {
+    return convert_ulong3(inV);
+}
+
+ulong4 __attribute__((kernel)) testConvertUlong4Uint4Ulong4(uint4 inV) {
+    return convert_ulong4(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestConvertRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestConvertRelaxed.rs
new file mode 100644
index 0000000..d13c634
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestConvertRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestConvert.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestCopysign.java b/tests/tests/renderscript/src/android/renderscript/cts/TestCopysign.java
new file mode 100644
index 0000000..cb8794a
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestCopysign.java
@@ -0,0 +1,325 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestCopysign extends RSBaseCompute {
+
+    private ScriptC_TestCopysign script;
+    private ScriptC_TestCopysignRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestCopysign(mRS);
+        scriptRelaxed = new ScriptC_TestCopysignRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float inX;
+        public float inY;
+        public Target.Floaty out;
+    }
+
+    private void checkCopysignFloatFloatFloat() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xeebba96e8c48145l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xeebba96e8c48146l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testCopysignFloatFloatFloat(inX, out);
+            verifyResultsCopysignFloatFloatFloat(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCopysignFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testCopysignFloatFloatFloat(inX, out);
+            verifyResultsCopysignFloatFloatFloat(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCopysignFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCopysignFloatFloatFloat(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 1];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 1];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i];
+                args.inY = arrayInY[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeCopysign(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkCopysignFloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkCopysignFloat2Float2Float2() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xbeb0e1cc912e993bl, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xbeb0e1cc912e993cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testCopysignFloat2Float2Float2(inX, out);
+            verifyResultsCopysignFloat2Float2Float2(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCopysignFloat2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testCopysignFloat2Float2Float2(inX, out);
+            verifyResultsCopysignFloat2Float2Float2(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCopysignFloat2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCopysignFloat2Float2Float2(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 2];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 2];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 2 + j];
+                args.inY = arrayInY[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeCopysign(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkCopysignFloat2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkCopysignFloat3Float3Float3() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x1315bfec930c9adcl, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x1315bfec930c9addl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testCopysignFloat3Float3Float3(inX, out);
+            verifyResultsCopysignFloat3Float3Float3(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCopysignFloat3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testCopysignFloat3Float3Float3(inX, out);
+            verifyResultsCopysignFloat3Float3Float3(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCopysignFloat3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCopysignFloat3Float3Float3(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeCopysign(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkCopysignFloat3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkCopysignFloat4Float4Float4() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x677a9e0c94ea9c7dl, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x677a9e0c94ea9c7el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testCopysignFloat4Float4Float4(inX, out);
+            verifyResultsCopysignFloat4Float4Float4(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCopysignFloat4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testCopysignFloat4Float4Float4(inX, out);
+            verifyResultsCopysignFloat4Float4Float4(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCopysignFloat4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCopysignFloat4Float4Float4(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeCopysign(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkCopysignFloat4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testCopysign() {
+        checkCopysignFloatFloatFloat();
+        checkCopysignFloat2Float2Float2();
+        checkCopysignFloat3Float3Float3();
+        checkCopysignFloat4Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestCopysign.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestCopysign.rs
new file mode 100644
index 0000000..d7bc4d0
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestCopysign.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInY;
+
+float __attribute__((kernel)) testCopysignFloatFloatFloat(float inX, unsigned int x) {
+    float inY = rsGetElementAt_float(gAllocInY, x);
+    return copysign(inX, inY);
+}
+
+float2 __attribute__((kernel)) testCopysignFloat2Float2Float2(float2 inX, unsigned int x) {
+    float2 inY = rsGetElementAt_float2(gAllocInY, x);
+    return copysign(inX, inY);
+}
+
+float3 __attribute__((kernel)) testCopysignFloat3Float3Float3(float3 inX, unsigned int x) {
+    float3 inY = rsGetElementAt_float3(gAllocInY, x);
+    return copysign(inX, inY);
+}
+
+float4 __attribute__((kernel)) testCopysignFloat4Float4Float4(float4 inX, unsigned int x) {
+    float4 inY = rsGetElementAt_float4(gAllocInY, x);
+    return copysign(inX, inY);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestCopysignRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestCopysignRelaxed.rs
new file mode 100644
index 0000000..01002d7
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestCopysignRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestCopysign.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestCos.java b/tests/tests/renderscript/src/android/renderscript/cts/TestCos.java
new file mode 100644
index 0000000..c3aaf28
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestCos.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestCos extends RSBaseCompute {
+
+    private ScriptC_TestCos script;
+    private ScriptC_TestCosRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestCos(mRS);
+        scriptRelaxed = new ScriptC_TestCosRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkCosFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x35eace7a33fd0be0l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testCosFloatFloat(in, out);
+            verifyResultsCosFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCosFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testCosFloatFloat(in, out);
+            verifyResultsCosFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCosFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCosFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeCos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkCosFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkCosFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x6cec729d2fe33ffcl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testCosFloat2Float2(in, out);
+            verifyResultsCosFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCosFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testCosFloat2Float2(in, out);
+            verifyResultsCosFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCosFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCosFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeCos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkCosFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkCosFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x6cec7d3e8ee9d596l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testCosFloat3Float3(in, out);
+            verifyResultsCosFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCosFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testCosFloat3Float3(in, out);
+            verifyResultsCosFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCosFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCosFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeCos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkCosFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkCosFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x6cec87dfedf06b30l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testCosFloat4Float4(in, out);
+            verifyResultsCosFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCosFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testCosFloat4Float4(in, out);
+            verifyResultsCosFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCosFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCosFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeCos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkCosFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testCos() {
+        checkCosFloatFloat();
+        checkCosFloat2Float2();
+        checkCosFloat3Float3();
+        checkCosFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestCos.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestCos.rs
new file mode 100644
index 0000000..5605139
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestCos.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testCosFloatFloat(float in) {
+    return cos(in);
+}
+
+float2 __attribute__((kernel)) testCosFloat2Float2(float2 in) {
+    return cos(in);
+}
+
+float3 __attribute__((kernel)) testCosFloat3Float3(float3 in) {
+    return cos(in);
+}
+
+float4 __attribute__((kernel)) testCosFloat4Float4(float4 in) {
+    return cos(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestCosRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestCosRelaxed.rs
new file mode 100644
index 0000000..1871a69
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestCosRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestCos.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestCosh.java b/tests/tests/renderscript/src/android/renderscript/cts/TestCosh.java
new file mode 100644
index 0000000..c1f6bf3
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestCosh.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestCosh extends RSBaseCompute {
+
+    private ScriptC_TestCosh script;
+    private ScriptC_TestCoshRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestCosh(mRS);
+        scriptRelaxed = new ScriptC_TestCoshRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkCoshFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xca4f5b95e29e11bel, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testCoshFloatFloat(in, out);
+            verifyResultsCoshFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCoshFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testCoshFloatFloat(in, out);
+            verifyResultsCoshFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCoshFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCoshFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeCosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkCoshFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkCoshFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x372b9f8d78e6a06al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testCoshFloat2Float2(in, out);
+            verifyResultsCoshFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCoshFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testCoshFloat2Float2(in, out);
+            verifyResultsCoshFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCoshFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCoshFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeCosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkCoshFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkCoshFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x372baa2ed7ed3604l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testCoshFloat3Float3(in, out);
+            verifyResultsCoshFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCoshFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testCoshFloat3Float3(in, out);
+            verifyResultsCoshFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCoshFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCoshFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeCosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkCoshFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkCoshFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x372bb4d036f3cb9el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testCoshFloat4Float4(in, out);
+            verifyResultsCoshFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCoshFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testCoshFloat4Float4(in, out);
+            verifyResultsCoshFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCoshFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCoshFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeCosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkCoshFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testCosh() {
+        checkCoshFloatFloat();
+        checkCoshFloat2Float2();
+        checkCoshFloat3Float3();
+        checkCoshFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestCosh.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestCosh.rs
new file mode 100644
index 0000000..b2d89b9
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestCosh.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testCoshFloatFloat(float in) {
+    return cosh(in);
+}
+
+float2 __attribute__((kernel)) testCoshFloat2Float2(float2 in) {
+    return cosh(in);
+}
+
+float3 __attribute__((kernel)) testCoshFloat3Float3(float3 in) {
+    return cosh(in);
+}
+
+float4 __attribute__((kernel)) testCoshFloat4Float4(float4 in) {
+    return cosh(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestCoshRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestCoshRelaxed.rs
new file mode 100644
index 0000000..cf28629
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestCoshRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestCosh.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestCospi.java b/tests/tests/renderscript/src/android/renderscript/cts/TestCospi.java
new file mode 100644
index 0000000..2d18af9
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestCospi.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestCospi extends RSBaseCompute {
+
+    private ScriptC_TestCospi script;
+    private ScriptC_TestCospiRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestCospi(mRS);
+        scriptRelaxed = new ScriptC_TestCospiRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkCospiFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xf63d9fae6fcc7f1l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testCospiFloatFloat(in, out);
+            verifyResultsCospiFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCospiFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testCospiFloatFloat(in, out);
+            verifyResultsCospiFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCospiFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCospiFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeCospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkCospiFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkCospiFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x2830872a08f896c5l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testCospiFloat2Float2(in, out);
+            verifyResultsCospiFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCospiFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testCospiFloat2Float2(in, out);
+            verifyResultsCospiFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCospiFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCospiFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeCospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkCospiFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkCospiFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x283091cb67ff2c5fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testCospiFloat3Float3(in, out);
+            verifyResultsCospiFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCospiFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testCospiFloat3Float3(in, out);
+            verifyResultsCospiFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCospiFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCospiFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeCospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkCospiFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkCospiFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x28309c6cc705c1f9l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testCospiFloat4Float4(in, out);
+            verifyResultsCospiFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCospiFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testCospiFloat4Float4(in, out);
+            verifyResultsCospiFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCospiFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCospiFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeCospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkCospiFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testCospi() {
+        checkCospiFloatFloat();
+        checkCospiFloat2Float2();
+        checkCospiFloat3Float3();
+        checkCospiFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestCospi.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestCospi.rs
new file mode 100644
index 0000000..a0cc778
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestCospi.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testCospiFloatFloat(float in) {
+    return cospi(in);
+}
+
+float2 __attribute__((kernel)) testCospiFloat2Float2(float2 in) {
+    return cospi(in);
+}
+
+float3 __attribute__((kernel)) testCospiFloat3Float3(float3 in) {
+    return cospi(in);
+}
+
+float4 __attribute__((kernel)) testCospiFloat4Float4(float4 in) {
+    return cospi(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestCospiRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestCospiRelaxed.rs
new file mode 100644
index 0000000..aac7b90
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestCospiRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestCospi.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestCross.java b/tests/tests/renderscript/src/android/renderscript/cts/TestCross.java
new file mode 100644
index 0000000..c5dc979
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestCross.java
@@ -0,0 +1,213 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestCross extends RSBaseCompute {
+
+    private ScriptC_TestCross script;
+    private ScriptC_TestCrossRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestCross(mRS);
+        scriptRelaxed = new ScriptC_TestCrossRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatNFloatNFloatN {
+        public float[] inLhs;
+        public float[] inRhs;
+        public Target.Floaty[] out;
+    }
+
+    private void checkCrossFloat3Float3Float3() {
+        Allocation inLhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xdec3726a2995edb5l, false);
+        Allocation inRhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xdec3726a2996190bl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInRhs(inRhs);
+            script.forEach_testCrossFloat3Float3Float3(inLhs, out);
+            verifyResultsCrossFloat3Float3Float3(inLhs, inRhs, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCrossFloat3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRhs(inRhs);
+            scriptRelaxed.forEach_testCrossFloat3Float3Float3(inLhs, out);
+            verifyResultsCrossFloat3Float3Float3(inLhs, inRhs, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCrossFloat3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCrossFloat3Float3Float3(Allocation inLhs, Allocation inRhs, Allocation out, boolean relaxed) {
+        float[] arrayInLhs = new float[INPUTSIZE * 4];
+        inLhs.copyTo(arrayInLhs);
+        float[] arrayInRhs = new float[INPUTSIZE * 4];
+        inRhs.copyTo(arrayInRhs);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloatNFloatN args = new ArgumentsFloatNFloatNFloatN();
+            // Create the appropriate sized arrays in args
+            args.inLhs = new float[3];
+            args.inRhs = new float[3];
+            args.out = new Target.Floaty[3];
+            // Fill args with the input values
+            for (int j = 0; j < 3 ; j++) {
+                args.inLhs[j] = arrayInLhs[i * 4 + j];
+            }
+            for (int j = 0; j < 3 ; j++) {
+                args.inRhs[j] = arrayInRhs[i * 4 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeCross(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            for (int j = 0; j < 3 ; j++) {
+                if (!args.out[j].couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 3 ; j++) {
+                    message.append("Input inLhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInLhs[i * 4 + j], Float.floatToRawIntBits(arrayInLhs[i * 4 + j]), arrayInLhs[i * 4 + j]));
+                    message.append("\n");
+                }
+                for (int j = 0; j < 3 ; j++) {
+                    message.append("Input inRhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInRhs[i * 4 + j], Float.floatToRawIntBits(arrayInRhs[i * 4 + j]), arrayInRhs[i * 4 + j]));
+                    message.append("\n");
+                }
+                for (int j = 0; j < 3 ; j++) {
+                    message.append("Expected output out: ");
+                    message.append(args.out[j].toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out[j].couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                }
+                assertTrue("Incorrect output for checkCrossFloat3Float3Float3" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    private void checkCrossFloat4Float4Float4() {
+        Allocation inLhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x6b4bc797a60fb18el, false);
+        Allocation inRhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x6b4bc797a60fdce4l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInRhs(inRhs);
+            script.forEach_testCrossFloat4Float4Float4(inLhs, out);
+            verifyResultsCrossFloat4Float4Float4(inLhs, inRhs, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCrossFloat4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRhs(inRhs);
+            scriptRelaxed.forEach_testCrossFloat4Float4Float4(inLhs, out);
+            verifyResultsCrossFloat4Float4Float4(inLhs, inRhs, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCrossFloat4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCrossFloat4Float4Float4(Allocation inLhs, Allocation inRhs, Allocation out, boolean relaxed) {
+        float[] arrayInLhs = new float[INPUTSIZE * 4];
+        inLhs.copyTo(arrayInLhs);
+        float[] arrayInRhs = new float[INPUTSIZE * 4];
+        inRhs.copyTo(arrayInRhs);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloatNFloatN args = new ArgumentsFloatNFloatNFloatN();
+            // Create the appropriate sized arrays in args
+            args.inLhs = new float[4];
+            args.inRhs = new float[4];
+            args.out = new Target.Floaty[4];
+            // Fill args with the input values
+            for (int j = 0; j < 4 ; j++) {
+                args.inLhs[j] = arrayInLhs[i * 4 + j];
+            }
+            for (int j = 0; j < 4 ; j++) {
+                args.inRhs[j] = arrayInRhs[i * 4 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeCross(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            for (int j = 0; j < 4 ; j++) {
+                if (!args.out[j].couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 4 ; j++) {
+                    message.append("Input inLhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInLhs[i * 4 + j], Float.floatToRawIntBits(arrayInLhs[i * 4 + j]), arrayInLhs[i * 4 + j]));
+                    message.append("\n");
+                }
+                for (int j = 0; j < 4 ; j++) {
+                    message.append("Input inRhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInRhs[i * 4 + j], Float.floatToRawIntBits(arrayInRhs[i * 4 + j]), arrayInRhs[i * 4 + j]));
+                    message.append("\n");
+                }
+                for (int j = 0; j < 4 ; j++) {
+                    message.append("Expected output out: ");
+                    message.append(args.out[j].toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out[j].couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                }
+                assertTrue("Incorrect output for checkCrossFloat4Float4Float4" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    public void testCross() {
+        checkCrossFloat3Float3Float3();
+        checkCrossFloat4Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestCross.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestCross.rs
new file mode 100644
index 0000000..16d5d35
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestCross.rs
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInRhs;
+
+float3 __attribute__((kernel)) testCrossFloat3Float3Float3(float3 inLhs, unsigned int x) {
+    float3 inRhs = rsGetElementAt_float3(gAllocInRhs, x);
+    return cross(inLhs, inRhs);
+}
+
+float4 __attribute__((kernel)) testCrossFloat4Float4Float4(float4 inLhs, unsigned int x) {
+    float4 inRhs = rsGetElementAt_float4(gAllocInRhs, x);
+    return cross(inLhs, inRhs);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestCrossRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestCrossRelaxed.rs
new file mode 100644
index 0000000..59fa62d
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestCrossRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestCross.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestDegrees.java b/tests/tests/renderscript/src/android/renderscript/cts/TestDegrees.java
new file mode 100644
index 0000000..b956dbd
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestDegrees.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestDegrees extends RSBaseCompute {
+
+    private ScriptC_TestDegrees script;
+    private ScriptC_TestDegreesRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestDegrees(mRS);
+        scriptRelaxed = new ScriptC_TestDegreesRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inValue;
+        public Target.Floaty out;
+    }
+
+    private void checkDegreesFloatFloat() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x3325fa58542a6bb5l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testDegreesFloatFloat(inValue, out);
+            verifyResultsDegreesFloatFloat(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDegreesFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testDegreesFloatFloat(inValue, out);
+            verifyResultsDegreesFloatFloat(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDegreesFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsDegreesFloatFloat(Allocation inValue, Allocation out, boolean relaxed) {
+        float[] arrayInValue = new float[INPUTSIZE * 1];
+        inValue.copyTo(arrayInValue);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inValue = arrayInValue[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeDegrees(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inValue, Float.floatToRawIntBits(args.inValue), args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkDegreesFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkDegreesFloat2Float2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x7a202f393d2a289l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testDegreesFloat2Float2(inValue, out);
+            verifyResultsDegreesFloat2Float2(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDegreesFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testDegreesFloat2Float2(inValue, out);
+            verifyResultsDegreesFloat2Float2(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDegreesFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsDegreesFloat2Float2(Allocation inValue, Allocation out, boolean relaxed) {
+        float[] arrayInValue = new float[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inValue = arrayInValue[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeDegrees(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inValue, Float.floatToRawIntBits(args.inValue), args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkDegreesFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkDegreesFloat3Float3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x2d56787add10c807l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testDegreesFloat3Float3(inValue, out);
+            verifyResultsDegreesFloat3Float3(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDegreesFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testDegreesFloat3Float3(inValue, out);
+            verifyResultsDegreesFloat3Float3(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDegreesFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsDegreesFloat3Float3(Allocation inValue, Allocation out, boolean relaxed) {
+        float[] arrayInValue = new float[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inValue = arrayInValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeDegrees(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inValue, Float.floatToRawIntBits(args.inValue), args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkDegreesFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkDegreesFloat4Float4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x530aee02264eed85l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testDegreesFloat4Float4(inValue, out);
+            verifyResultsDegreesFloat4Float4(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDegreesFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testDegreesFloat4Float4(inValue, out);
+            verifyResultsDegreesFloat4Float4(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDegreesFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsDegreesFloat4Float4(Allocation inValue, Allocation out, boolean relaxed) {
+        float[] arrayInValue = new float[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inValue = arrayInValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeDegrees(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inValue, Float.floatToRawIntBits(args.inValue), args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkDegreesFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testDegrees() {
+        checkDegreesFloatFloat();
+        checkDegreesFloat2Float2();
+        checkDegreesFloat3Float3();
+        checkDegreesFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestDegrees.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestDegrees.rs
new file mode 100644
index 0000000..78741a8
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestDegrees.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testDegreesFloatFloat(float inValue) {
+    return degrees(inValue);
+}
+
+float2 __attribute__((kernel)) testDegreesFloat2Float2(float2 inValue) {
+    return degrees(inValue);
+}
+
+float3 __attribute__((kernel)) testDegreesFloat3Float3(float3 inValue) {
+    return degrees(inValue);
+}
+
+float4 __attribute__((kernel)) testDegreesFloat4Float4(float4 inValue) {
+    return degrees(inValue);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestDegreesRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestDegreesRelaxed.rs
new file mode 100644
index 0000000..7a443bf
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestDegreesRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestDegrees.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestDistance.java b/tests/tests/renderscript/src/android/renderscript/cts/TestDistance.java
new file mode 100644
index 0000000..091c12c
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestDistance.java
@@ -0,0 +1,357 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestDistance extends RSBaseCompute {
+
+    private ScriptC_TestDistance script;
+    private ScriptC_TestDistanceRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestDistance(mRS);
+        scriptRelaxed = new ScriptC_TestDistanceRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float inLhs;
+        public float inRhs;
+        public Target.Floaty out;
+    }
+
+    private void checkDistanceFloatFloatFloat() {
+        Allocation inLhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xf62f685ebafc5b67l, false);
+        Allocation inRhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xf62f685ebafc86bdl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInRhs(inRhs);
+            script.forEach_testDistanceFloatFloatFloat(inLhs, out);
+            verifyResultsDistanceFloatFloatFloat(inLhs, inRhs, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDistanceFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRhs(inRhs);
+            scriptRelaxed.forEach_testDistanceFloatFloatFloat(inLhs, out);
+            verifyResultsDistanceFloatFloatFloat(inLhs, inRhs, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDistanceFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsDistanceFloatFloatFloat(Allocation inLhs, Allocation inRhs, Allocation out, boolean relaxed) {
+        float[] arrayInLhs = new float[INPUTSIZE * 1];
+        inLhs.copyTo(arrayInLhs);
+        float[] arrayInRhs = new float[INPUTSIZE * 1];
+        inRhs.copyTo(arrayInRhs);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+            // Create the appropriate sized arrays in args
+            // Fill args with the input values
+            args.inLhs = arrayInLhs[i];
+            args.inRhs = arrayInRhs[i];
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeDistance(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                message.append("Input inLhs: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayInLhs[i], Float.floatToRawIntBits(arrayInLhs[i]), arrayInLhs[i]));
+                message.append("\n");
+                message.append("Input inRhs: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayInRhs[i], Float.floatToRawIntBits(arrayInRhs[i]), arrayInRhs[i]));
+                message.append("\n");
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkDistanceFloatFloatFloat" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    public class ArgumentsFloatNFloatNFloat {
+        public float[] inLhs;
+        public float[] inRhs;
+        public Target.Floaty out;
+    }
+
+    private void checkDistanceFloat2Float2Float() {
+        Allocation inLhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x3fdeb51f89981593l, false);
+        Allocation inRhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x3fdeb51f899840e9l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInRhs(inRhs);
+            script.forEach_testDistanceFloat2Float2Float(inLhs, out);
+            verifyResultsDistanceFloat2Float2Float(inLhs, inRhs, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDistanceFloat2Float2Float: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRhs(inRhs);
+            scriptRelaxed.forEach_testDistanceFloat2Float2Float(inLhs, out);
+            verifyResultsDistanceFloat2Float2Float(inLhs, inRhs, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDistanceFloat2Float2Float: " + e.toString());
+        }
+    }
+
+    private void verifyResultsDistanceFloat2Float2Float(Allocation inLhs, Allocation inRhs, Allocation out, boolean relaxed) {
+        float[] arrayInLhs = new float[INPUTSIZE * 2];
+        inLhs.copyTo(arrayInLhs);
+        float[] arrayInRhs = new float[INPUTSIZE * 2];
+        inRhs.copyTo(arrayInRhs);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloatNFloat args = new ArgumentsFloatNFloatNFloat();
+            // Create the appropriate sized arrays in args
+            args.inLhs = new float[2];
+            args.inRhs = new float[2];
+            // Fill args with the input values
+            for (int j = 0; j < 2 ; j++) {
+                args.inLhs[j] = arrayInLhs[i * 2 + j];
+            }
+            for (int j = 0; j < 2 ; j++) {
+                args.inRhs[j] = arrayInRhs[i * 2 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeDistance(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 2 ; j++) {
+                    message.append("Input inLhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInLhs[i * 2 + j], Float.floatToRawIntBits(arrayInLhs[i * 2 + j]), arrayInLhs[i * 2 + j]));
+                    message.append("\n");
+                }
+                for (int j = 0; j < 2 ; j++) {
+                    message.append("Input inRhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInRhs[i * 2 + j], Float.floatToRawIntBits(arrayInRhs[i * 2 + j]), arrayInRhs[i * 2 + j]));
+                    message.append("\n");
+                }
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkDistanceFloat2Float2Float" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    private void checkDistanceFloat3Float3Float() {
+        Allocation inLhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x6cd0047fd9ae30edl, false);
+        Allocation inRhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x6cd0047fd9ae5c43l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInRhs(inRhs);
+            script.forEach_testDistanceFloat3Float3Float(inLhs, out);
+            verifyResultsDistanceFloat3Float3Float(inLhs, inRhs, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDistanceFloat3Float3Float: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRhs(inRhs);
+            scriptRelaxed.forEach_testDistanceFloat3Float3Float(inLhs, out);
+            verifyResultsDistanceFloat3Float3Float(inLhs, inRhs, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDistanceFloat3Float3Float: " + e.toString());
+        }
+    }
+
+    private void verifyResultsDistanceFloat3Float3Float(Allocation inLhs, Allocation inRhs, Allocation out, boolean relaxed) {
+        float[] arrayInLhs = new float[INPUTSIZE * 4];
+        inLhs.copyTo(arrayInLhs);
+        float[] arrayInRhs = new float[INPUTSIZE * 4];
+        inRhs.copyTo(arrayInRhs);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloatNFloat args = new ArgumentsFloatNFloatNFloat();
+            // Create the appropriate sized arrays in args
+            args.inLhs = new float[3];
+            args.inRhs = new float[3];
+            // Fill args with the input values
+            for (int j = 0; j < 3 ; j++) {
+                args.inLhs[j] = arrayInLhs[i * 4 + j];
+            }
+            for (int j = 0; j < 3 ; j++) {
+                args.inRhs[j] = arrayInRhs[i * 4 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeDistance(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 3 ; j++) {
+                    message.append("Input inLhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInLhs[i * 4 + j], Float.floatToRawIntBits(arrayInLhs[i * 4 + j]), arrayInLhs[i * 4 + j]));
+                    message.append("\n");
+                }
+                for (int j = 0; j < 3 ; j++) {
+                    message.append("Input inRhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInRhs[i * 4 + j], Float.floatToRawIntBits(arrayInRhs[i * 4 + j]), arrayInRhs[i * 4 + j]));
+                    message.append("\n");
+                }
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkDistanceFloat3Float3Float" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    private void checkDistanceFloat4Float4Float() {
+        Allocation inLhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x99c153e029c44c47l, false);
+        Allocation inRhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x99c153e029c4779dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInRhs(inRhs);
+            script.forEach_testDistanceFloat4Float4Float(inLhs, out);
+            verifyResultsDistanceFloat4Float4Float(inLhs, inRhs, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDistanceFloat4Float4Float: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRhs(inRhs);
+            scriptRelaxed.forEach_testDistanceFloat4Float4Float(inLhs, out);
+            verifyResultsDistanceFloat4Float4Float(inLhs, inRhs, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDistanceFloat4Float4Float: " + e.toString());
+        }
+    }
+
+    private void verifyResultsDistanceFloat4Float4Float(Allocation inLhs, Allocation inRhs, Allocation out, boolean relaxed) {
+        float[] arrayInLhs = new float[INPUTSIZE * 4];
+        inLhs.copyTo(arrayInLhs);
+        float[] arrayInRhs = new float[INPUTSIZE * 4];
+        inRhs.copyTo(arrayInRhs);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloatNFloat args = new ArgumentsFloatNFloatNFloat();
+            // Create the appropriate sized arrays in args
+            args.inLhs = new float[4];
+            args.inRhs = new float[4];
+            // Fill args with the input values
+            for (int j = 0; j < 4 ; j++) {
+                args.inLhs[j] = arrayInLhs[i * 4 + j];
+            }
+            for (int j = 0; j < 4 ; j++) {
+                args.inRhs[j] = arrayInRhs[i * 4 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeDistance(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 4 ; j++) {
+                    message.append("Input inLhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInLhs[i * 4 + j], Float.floatToRawIntBits(arrayInLhs[i * 4 + j]), arrayInLhs[i * 4 + j]));
+                    message.append("\n");
+                }
+                for (int j = 0; j < 4 ; j++) {
+                    message.append("Input inRhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInRhs[i * 4 + j], Float.floatToRawIntBits(arrayInRhs[i * 4 + j]), arrayInRhs[i * 4 + j]));
+                    message.append("\n");
+                }
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkDistanceFloat4Float4Float" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    public void testDistance() {
+        checkDistanceFloatFloatFloat();
+        checkDistanceFloat2Float2Float();
+        checkDistanceFloat3Float3Float();
+        checkDistanceFloat4Float4Float();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestDistance.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestDistance.rs
new file mode 100644
index 0000000..fdc1783
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestDistance.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInRhs;
+
+float __attribute__((kernel)) testDistanceFloatFloatFloat(float inLhs, unsigned int x) {
+    float inRhs = rsGetElementAt_float(gAllocInRhs, x);
+    return distance(inLhs, inRhs);
+}
+
+float __attribute__((kernel)) testDistanceFloat2Float2Float(float2 inLhs, unsigned int x) {
+    float2 inRhs = rsGetElementAt_float2(gAllocInRhs, x);
+    return distance(inLhs, inRhs);
+}
+
+float __attribute__((kernel)) testDistanceFloat3Float3Float(float3 inLhs, unsigned int x) {
+    float3 inRhs = rsGetElementAt_float3(gAllocInRhs, x);
+    return distance(inLhs, inRhs);
+}
+
+float __attribute__((kernel)) testDistanceFloat4Float4Float(float4 inLhs, unsigned int x) {
+    float4 inRhs = rsGetElementAt_float4(gAllocInRhs, x);
+    return distance(inLhs, inRhs);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestDistanceRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestDistanceRelaxed.rs
new file mode 100644
index 0000000..ba4c096
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestDistanceRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestDistance.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestDot.java b/tests/tests/renderscript/src/android/renderscript/cts/TestDot.java
new file mode 100644
index 0000000..666906b
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestDot.java
@@ -0,0 +1,357 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestDot extends RSBaseCompute {
+
+    private ScriptC_TestDot script;
+    private ScriptC_TestDotRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestDot(mRS);
+        scriptRelaxed = new ScriptC_TestDotRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float inLhs;
+        public float inRhs;
+        public Target.Floaty out;
+    }
+
+    private void checkDotFloatFloatFloat() {
+        Allocation inLhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x93a0502d7b6ecc43l, false);
+        Allocation inRhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x93a0502d7b6ef799l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInRhs(inRhs);
+            script.forEach_testDotFloatFloatFloat(inLhs, out);
+            verifyResultsDotFloatFloatFloat(inLhs, inRhs, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDotFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRhs(inRhs);
+            scriptRelaxed.forEach_testDotFloatFloatFloat(inLhs, out);
+            verifyResultsDotFloatFloatFloat(inLhs, inRhs, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDotFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsDotFloatFloatFloat(Allocation inLhs, Allocation inRhs, Allocation out, boolean relaxed) {
+        float[] arrayInLhs = new float[INPUTSIZE * 1];
+        inLhs.copyTo(arrayInLhs);
+        float[] arrayInRhs = new float[INPUTSIZE * 1];
+        inRhs.copyTo(arrayInRhs);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+            // Create the appropriate sized arrays in args
+            // Fill args with the input values
+            args.inLhs = arrayInLhs[i];
+            args.inRhs = arrayInRhs[i];
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeDot(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                message.append("Input inLhs: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayInLhs[i], Float.floatToRawIntBits(arrayInLhs[i]), arrayInLhs[i]));
+                message.append("\n");
+                message.append("Input inRhs: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayInRhs[i], Float.floatToRawIntBits(arrayInRhs[i]), arrayInRhs[i]));
+                message.append("\n");
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkDotFloatFloatFloat" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    public class ArgumentsFloatNFloatNFloat {
+        public float[] inLhs;
+        public float[] inRhs;
+        public Target.Floaty out;
+    }
+
+    private void checkDotFloat2Float2Float() {
+        Allocation inLhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x6458f96b84293a8fl, false);
+        Allocation inRhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x6458f96b842965e5l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInRhs(inRhs);
+            script.forEach_testDotFloat2Float2Float(inLhs, out);
+            verifyResultsDotFloat2Float2Float(inLhs, inRhs, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDotFloat2Float2Float: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRhs(inRhs);
+            scriptRelaxed.forEach_testDotFloat2Float2Float(inLhs, out);
+            verifyResultsDotFloat2Float2Float(inLhs, inRhs, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDotFloat2Float2Float: " + e.toString());
+        }
+    }
+
+    private void verifyResultsDotFloat2Float2Float(Allocation inLhs, Allocation inRhs, Allocation out, boolean relaxed) {
+        float[] arrayInLhs = new float[INPUTSIZE * 2];
+        inLhs.copyTo(arrayInLhs);
+        float[] arrayInRhs = new float[INPUTSIZE * 2];
+        inRhs.copyTo(arrayInRhs);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloatNFloat args = new ArgumentsFloatNFloatNFloat();
+            // Create the appropriate sized arrays in args
+            args.inLhs = new float[2];
+            args.inRhs = new float[2];
+            // Fill args with the input values
+            for (int j = 0; j < 2 ; j++) {
+                args.inLhs[j] = arrayInLhs[i * 2 + j];
+            }
+            for (int j = 0; j < 2 ; j++) {
+                args.inRhs[j] = arrayInRhs[i * 2 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeDot(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 2 ; j++) {
+                    message.append("Input inLhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInLhs[i * 2 + j], Float.floatToRawIntBits(arrayInLhs[i * 2 + j]), arrayInLhs[i * 2 + j]));
+                    message.append("\n");
+                }
+                for (int j = 0; j < 2 ; j++) {
+                    message.append("Input inRhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInRhs[i * 2 + j], Float.floatToRawIntBits(arrayInRhs[i * 2 + j]), arrayInRhs[i * 2 + j]));
+                    message.append("\n");
+                }
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkDotFloat2Float2Float" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    private void checkDotFloat3Float3Float() {
+        Allocation inLhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x914a48cbd43f55e9l, false);
+        Allocation inRhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x914a48cbd43f813fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInRhs(inRhs);
+            script.forEach_testDotFloat3Float3Float(inLhs, out);
+            verifyResultsDotFloat3Float3Float(inLhs, inRhs, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDotFloat3Float3Float: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRhs(inRhs);
+            scriptRelaxed.forEach_testDotFloat3Float3Float(inLhs, out);
+            verifyResultsDotFloat3Float3Float(inLhs, inRhs, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDotFloat3Float3Float: " + e.toString());
+        }
+    }
+
+    private void verifyResultsDotFloat3Float3Float(Allocation inLhs, Allocation inRhs, Allocation out, boolean relaxed) {
+        float[] arrayInLhs = new float[INPUTSIZE * 4];
+        inLhs.copyTo(arrayInLhs);
+        float[] arrayInRhs = new float[INPUTSIZE * 4];
+        inRhs.copyTo(arrayInRhs);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloatNFloat args = new ArgumentsFloatNFloatNFloat();
+            // Create the appropriate sized arrays in args
+            args.inLhs = new float[3];
+            args.inRhs = new float[3];
+            // Fill args with the input values
+            for (int j = 0; j < 3 ; j++) {
+                args.inLhs[j] = arrayInLhs[i * 4 + j];
+            }
+            for (int j = 0; j < 3 ; j++) {
+                args.inRhs[j] = arrayInRhs[i * 4 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeDot(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 3 ; j++) {
+                    message.append("Input inLhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInLhs[i * 4 + j], Float.floatToRawIntBits(arrayInLhs[i * 4 + j]), arrayInLhs[i * 4 + j]));
+                    message.append("\n");
+                }
+                for (int j = 0; j < 3 ; j++) {
+                    message.append("Input inRhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInRhs[i * 4 + j], Float.floatToRawIntBits(arrayInRhs[i * 4 + j]), arrayInRhs[i * 4 + j]));
+                    message.append("\n");
+                }
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkDotFloat3Float3Float" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    private void checkDotFloat4Float4Float() {
+        Allocation inLhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xbe3b982c24557143l, false);
+        Allocation inRhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xbe3b982c24559c99l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInRhs(inRhs);
+            script.forEach_testDotFloat4Float4Float(inLhs, out);
+            verifyResultsDotFloat4Float4Float(inLhs, inRhs, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDotFloat4Float4Float: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRhs(inRhs);
+            scriptRelaxed.forEach_testDotFloat4Float4Float(inLhs, out);
+            verifyResultsDotFloat4Float4Float(inLhs, inRhs, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDotFloat4Float4Float: " + e.toString());
+        }
+    }
+
+    private void verifyResultsDotFloat4Float4Float(Allocation inLhs, Allocation inRhs, Allocation out, boolean relaxed) {
+        float[] arrayInLhs = new float[INPUTSIZE * 4];
+        inLhs.copyTo(arrayInLhs);
+        float[] arrayInRhs = new float[INPUTSIZE * 4];
+        inRhs.copyTo(arrayInRhs);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloatNFloat args = new ArgumentsFloatNFloatNFloat();
+            // Create the appropriate sized arrays in args
+            args.inLhs = new float[4];
+            args.inRhs = new float[4];
+            // Fill args with the input values
+            for (int j = 0; j < 4 ; j++) {
+                args.inLhs[j] = arrayInLhs[i * 4 + j];
+            }
+            for (int j = 0; j < 4 ; j++) {
+                args.inRhs[j] = arrayInRhs[i * 4 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeDot(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 4 ; j++) {
+                    message.append("Input inLhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInLhs[i * 4 + j], Float.floatToRawIntBits(arrayInLhs[i * 4 + j]), arrayInLhs[i * 4 + j]));
+                    message.append("\n");
+                }
+                for (int j = 0; j < 4 ; j++) {
+                    message.append("Input inRhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInRhs[i * 4 + j], Float.floatToRawIntBits(arrayInRhs[i * 4 + j]), arrayInRhs[i * 4 + j]));
+                    message.append("\n");
+                }
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkDotFloat4Float4Float" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    public void testDot() {
+        checkDotFloatFloatFloat();
+        checkDotFloat2Float2Float();
+        checkDotFloat3Float3Float();
+        checkDotFloat4Float4Float();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestDot.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestDot.rs
new file mode 100644
index 0000000..27aa8aa
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestDot.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInRhs;
+
+float __attribute__((kernel)) testDotFloatFloatFloat(float inLhs, unsigned int x) {
+    float inRhs = rsGetElementAt_float(gAllocInRhs, x);
+    return dot(inLhs, inRhs);
+}
+
+float __attribute__((kernel)) testDotFloat2Float2Float(float2 inLhs, unsigned int x) {
+    float2 inRhs = rsGetElementAt_float2(gAllocInRhs, x);
+    return dot(inLhs, inRhs);
+}
+
+float __attribute__((kernel)) testDotFloat3Float3Float(float3 inLhs, unsigned int x) {
+    float3 inRhs = rsGetElementAt_float3(gAllocInRhs, x);
+    return dot(inLhs, inRhs);
+}
+
+float __attribute__((kernel)) testDotFloat4Float4Float(float4 inLhs, unsigned int x) {
+    float4 inRhs = rsGetElementAt_float4(gAllocInRhs, x);
+    return dot(inLhs, inRhs);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestDotRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestDotRelaxed.rs
new file mode 100644
index 0000000..53e7080
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestDotRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestDot.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestErf.java b/tests/tests/renderscript/src/android/renderscript/cts/TestErf.java
new file mode 100644
index 0000000..6c73bf1
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestErf.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestErf extends RSBaseCompute {
+
+    private ScriptC_TestErf script;
+    private ScriptC_TestErfRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestErf(mRS);
+        scriptRelaxed = new ScriptC_TestErfRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkErfFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x287cee12fdd9cb26l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testErfFloatFloat(in, out);
+            verifyResultsErfFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testErfFloatFloat(in, out);
+            verifyResultsErfFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsErfFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeErf(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkErfFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkErfFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x6e52a9272b44c092l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testErfFloat2Float2(in, out);
+            verifyResultsErfFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testErfFloat2Float2(in, out);
+            verifyResultsErfFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsErfFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeErf(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkErfFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkErfFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x6e52b3c88a4b562cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testErfFloat3Float3(in, out);
+            verifyResultsErfFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testErfFloat3Float3(in, out);
+            verifyResultsErfFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsErfFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeErf(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkErfFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkErfFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x6e52be69e951ebc6l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testErfFloat4Float4(in, out);
+            verifyResultsErfFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testErfFloat4Float4(in, out);
+            verifyResultsErfFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsErfFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeErf(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkErfFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testErf() {
+        checkErfFloatFloat();
+        checkErfFloat2Float2();
+        checkErfFloat3Float3();
+        checkErfFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestErf.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestErf.rs
new file mode 100644
index 0000000..5d26ed6
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestErf.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testErfFloatFloat(float in) {
+    return erf(in);
+}
+
+float2 __attribute__((kernel)) testErfFloat2Float2(float2 in) {
+    return erf(in);
+}
+
+float3 __attribute__((kernel)) testErfFloat3Float3(float3 in) {
+    return erf(in);
+}
+
+float4 __attribute__((kernel)) testErfFloat4Float4(float4 in) {
+    return erf(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestErfRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestErfRelaxed.rs
new file mode 100644
index 0000000..1551db8
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestErfRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestErf.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestErfc.java b/tests/tests/renderscript/src/android/renderscript/cts/TestErfc.java
new file mode 100644
index 0000000..86c2aa1
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestErfc.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestErfc extends RSBaseCompute {
+
+    private ScriptC_TestErfc script;
+    private ScriptC_TestErfcRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestErfc(mRS);
+        scriptRelaxed = new ScriptC_TestErfcRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkErfcFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xb41907c64db86b2bl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testErfcFloatFloat(in, out);
+            verifyResultsErfcFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfcFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testErfcFloatFloat(in, out);
+            verifyResultsErfcFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfcFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsErfcFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeErfc(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkErfcFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkErfcFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xc8c849430a3684afl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testErfcFloat2Float2(in, out);
+            verifyResultsErfcFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfcFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testErfcFloat2Float2(in, out);
+            verifyResultsErfcFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfcFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsErfcFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeErfc(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkErfcFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkErfcFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xc8c853e4693d1a49l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testErfcFloat3Float3(in, out);
+            verifyResultsErfcFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfcFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testErfcFloat3Float3(in, out);
+            verifyResultsErfcFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfcFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsErfcFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeErfc(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkErfcFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkErfcFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xc8c85e85c843afe3l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testErfcFloat4Float4(in, out);
+            verifyResultsErfcFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfcFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testErfcFloat4Float4(in, out);
+            verifyResultsErfcFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfcFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsErfcFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeErfc(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkErfcFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testErfc() {
+        checkErfcFloatFloat();
+        checkErfcFloat2Float2();
+        checkErfcFloat3Float3();
+        checkErfcFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestErfc.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestErfc.rs
new file mode 100644
index 0000000..d12ea25
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestErfc.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testErfcFloatFloat(float in) {
+    return erfc(in);
+}
+
+float2 __attribute__((kernel)) testErfcFloat2Float2(float2 in) {
+    return erfc(in);
+}
+
+float3 __attribute__((kernel)) testErfcFloat3Float3(float3 in) {
+    return erfc(in);
+}
+
+float4 __attribute__((kernel)) testErfcFloat4Float4(float4 in) {
+    return erfc(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestErfcRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestErfcRelaxed.rs
new file mode 100644
index 0000000..f6117c8
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestErfcRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestErfc.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestExp.java b/tests/tests/renderscript/src/android/renderscript/cts/TestExp.java
new file mode 100644
index 0000000..224a64c
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestExp.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestExp extends RSBaseCompute {
+
+    private ScriptC_TestExp script;
+    private ScriptC_TestExpRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestExp(mRS);
+        scriptRelaxed = new ScriptC_TestExpRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkExpFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xb43af2b5f55920f2l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testExpFloatFloat(in, out);
+            verifyResultsExpFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testExpFloatFloat(in, out);
+            verifyResultsExpFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExpFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeExp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkExpFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkExpFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xbdc22634c1f76efel, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testExpFloat2Float2(in, out);
+            verifyResultsExpFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testExpFloat2Float2(in, out);
+            verifyResultsExpFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExpFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeExp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkExpFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkExpFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xbdc230d620fe0498l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testExpFloat3Float3(in, out);
+            verifyResultsExpFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testExpFloat3Float3(in, out);
+            verifyResultsExpFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExpFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeExp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkExpFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkExpFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xbdc23b7780049a32l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testExpFloat4Float4(in, out);
+            verifyResultsExpFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testExpFloat4Float4(in, out);
+            verifyResultsExpFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExpFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeExp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkExpFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testExp() {
+        checkExpFloatFloat();
+        checkExpFloat2Float2();
+        checkExpFloat3Float3();
+        checkExpFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestExp.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestExp.rs
new file mode 100644
index 0000000..90879d9
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestExp.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testExpFloatFloat(float in) {
+    return exp(in);
+}
+
+float2 __attribute__((kernel)) testExpFloat2Float2(float2 in) {
+    return exp(in);
+}
+
+float3 __attribute__((kernel)) testExpFloat3Float3(float3 in) {
+    return exp(in);
+}
+
+float4 __attribute__((kernel)) testExpFloat4Float4(float4 in) {
+    return exp(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestExp10.java b/tests/tests/renderscript/src/android/renderscript/cts/TestExp10.java
new file mode 100644
index 0000000..874d17b
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestExp10.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestExp10 extends RSBaseCompute {
+
+    private ScriptC_TestExp10 script;
+    private ScriptC_TestExp10Relaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestExp10(mRS);
+        scriptRelaxed = new ScriptC_TestExp10Relaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkExp10FloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x9f6474a4cee90545l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testExp10FloatFloat(in, out);
+            verifyResultsExp10FloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp10FloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testExp10FloatFloat(in, out);
+            verifyResultsExp10FloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp10FloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExp10FloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeExp10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkExp10FloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkExp10Float2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x3c8d9c56223f8a79l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testExp10Float2Float2(in, out);
+            verifyResultsExp10Float2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp10Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testExp10Float2Float2(in, out);
+            verifyResultsExp10Float2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp10Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExp10Float2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeExp10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkExp10Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkExp10Float3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x3c8da6f781462013l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testExp10Float3Float3(in, out);
+            verifyResultsExp10Float3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp10Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testExp10Float3Float3(in, out);
+            verifyResultsExp10Float3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp10Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExp10Float3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeExp10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkExp10Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkExp10Float4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x3c8db198e04cb5adl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testExp10Float4Float4(in, out);
+            verifyResultsExp10Float4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp10Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testExp10Float4Float4(in, out);
+            verifyResultsExp10Float4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp10Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExp10Float4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeExp10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkExp10Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testExp10() {
+        checkExp10FloatFloat();
+        checkExp10Float2Float2();
+        checkExp10Float3Float3();
+        checkExp10Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestExp10.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestExp10.rs
new file mode 100644
index 0000000..117fe26
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestExp10.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testExp10FloatFloat(float in) {
+    return exp10(in);
+}
+
+float2 __attribute__((kernel)) testExp10Float2Float2(float2 in) {
+    return exp10(in);
+}
+
+float3 __attribute__((kernel)) testExp10Float3Float3(float3 in) {
+    return exp10(in);
+}
+
+float4 __attribute__((kernel)) testExp10Float4Float4(float4 in) {
+    return exp10(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestExp10Relaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestExp10Relaxed.rs
new file mode 100644
index 0000000..9b07598
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestExp10Relaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestExp10.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestExp2.java b/tests/tests/renderscript/src/android/renderscript/cts/TestExp2.java
new file mode 100644
index 0000000..bbb9c68
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestExp2.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestExp2 extends RSBaseCompute {
+
+    private ScriptC_TestExp2 script;
+    private ScriptC_TestExp2Relaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestExp2(mRS);
+        scriptRelaxed = new ScriptC_TestExp2Relaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkExp2FloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x80096e5b0f2662el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testExp2FloatFloat(in, out);
+            verifyResultsExp2FloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp2FloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testExp2FloatFloat(in, out);
+            verifyResultsExp2FloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp2FloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExp2FloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeExp2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkExp2FloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkExp2Float2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xcc4102f6b7fc7d5al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testExp2Float2Float2(in, out);
+            verifyResultsExp2Float2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testExp2Float2Float2(in, out);
+            verifyResultsExp2Float2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExp2Float2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeExp2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkExp2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkExp2Float3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xcc410d98170312f4l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testExp2Float3Float3(in, out);
+            verifyResultsExp2Float3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp2Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testExp2Float3Float3(in, out);
+            verifyResultsExp2Float3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp2Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExp2Float3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeExp2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkExp2Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkExp2Float4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xcc4118397609a88el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testExp2Float4Float4(in, out);
+            verifyResultsExp2Float4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp2Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testExp2Float4Float4(in, out);
+            verifyResultsExp2Float4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp2Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExp2Float4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeExp2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkExp2Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testExp2() {
+        checkExp2FloatFloat();
+        checkExp2Float2Float2();
+        checkExp2Float3Float3();
+        checkExp2Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestExp2.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestExp2.rs
new file mode 100644
index 0000000..61ff900
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestExp2.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testExp2FloatFloat(float in) {
+    return exp2(in);
+}
+
+float2 __attribute__((kernel)) testExp2Float2Float2(float2 in) {
+    return exp2(in);
+}
+
+float3 __attribute__((kernel)) testExp2Float3Float3(float3 in) {
+    return exp2(in);
+}
+
+float4 __attribute__((kernel)) testExp2Float4Float4(float4 in) {
+    return exp2(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestExp2Relaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestExp2Relaxed.rs
new file mode 100644
index 0000000..06810b3
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestExp2Relaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestExp2.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestExpRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestExpRelaxed.rs
new file mode 100644
index 0000000..f98bf80
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestExpRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestExp.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestExpm1.java b/tests/tests/renderscript/src/android/renderscript/cts/TestExpm1.java
new file mode 100644
index 0000000..c922e49
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestExpm1.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestExpm1 extends RSBaseCompute {
+
+    private ScriptC_TestExpm1 script;
+    private ScriptC_TestExpm1Relaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestExpm1(mRS);
+        scriptRelaxed = new ScriptC_TestExpm1Relaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkExpm1FloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xa03d120368f727aal, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testExpm1FloatFloat(in, out);
+            verifyResultsExpm1FloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpm1FloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testExpm1FloatFloat(in, out);
+            verifyResultsExpm1FloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpm1FloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExpm1FloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeExpm1(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkExpm1FloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkExpm1Float2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x59163c9cd255f5f6l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testExpm1Float2Float2(in, out);
+            verifyResultsExpm1Float2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpm1Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testExpm1Float2Float2(in, out);
+            verifyResultsExpm1Float2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpm1Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExpm1Float2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeExpm1(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkExpm1Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkExpm1Float3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x5916473e315c8b90l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testExpm1Float3Float3(in, out);
+            verifyResultsExpm1Float3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpm1Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testExpm1Float3Float3(in, out);
+            verifyResultsExpm1Float3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpm1Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExpm1Float3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeExpm1(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkExpm1Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkExpm1Float4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x591651df9063212al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testExpm1Float4Float4(in, out);
+            verifyResultsExpm1Float4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpm1Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testExpm1Float4Float4(in, out);
+            verifyResultsExpm1Float4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpm1Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExpm1Float4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeExpm1(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkExpm1Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testExpm1() {
+        checkExpm1FloatFloat();
+        checkExpm1Float2Float2();
+        checkExpm1Float3Float3();
+        checkExpm1Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestExpm1.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestExpm1.rs
new file mode 100644
index 0000000..9399576
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestExpm1.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testExpm1FloatFloat(float in) {
+    return expm1(in);
+}
+
+float2 __attribute__((kernel)) testExpm1Float2Float2(float2 in) {
+    return expm1(in);
+}
+
+float3 __attribute__((kernel)) testExpm1Float3Float3(float3 in) {
+    return expm1(in);
+}
+
+float4 __attribute__((kernel)) testExpm1Float4Float4(float4 in) {
+    return expm1(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestExpm1Relaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestExpm1Relaxed.rs
new file mode 100644
index 0000000..bd73f9d
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestExpm1Relaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestExpm1.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFabs.java b/tests/tests/renderscript/src/android/renderscript/cts/TestFabs.java
new file mode 100644
index 0000000..29cdd86
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFabs.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestFabs extends RSBaseCompute {
+
+    private ScriptC_TestFabs script;
+    private ScriptC_TestFabsRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestFabs(mRS);
+        scriptRelaxed = new ScriptC_TestFabsRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkFabsFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x70316affaf9e3339l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testFabsFloatFloat(in, out);
+            verifyResultsFabsFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFabsFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testFabsFloatFloat(in, out);
+            verifyResultsFabsFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFabsFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFabsFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFabs(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFabsFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFabsFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x54ecf2b71ed871cdl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testFabsFloat2Float2(in, out);
+            verifyResultsFabsFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFabsFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testFabsFloat2Float2(in, out);
+            verifyResultsFabsFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFabsFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFabsFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFabs(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFabsFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFabsFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x54ecfd587ddf0767l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testFabsFloat3Float3(in, out);
+            verifyResultsFabsFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFabsFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testFabsFloat3Float3(in, out);
+            verifyResultsFabsFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFabsFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFabsFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFabs(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFabsFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFabsFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x54ed07f9dce59d01l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testFabsFloat4Float4(in, out);
+            verifyResultsFabsFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFabsFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testFabsFloat4Float4(in, out);
+            verifyResultsFabsFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFabsFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFabsFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFabs(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFabsFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testFabs() {
+        checkFabsFloatFloat();
+        checkFabsFloat2Float2();
+        checkFabsFloat3Float3();
+        checkFabsFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFabs.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestFabs.rs
new file mode 100644
index 0000000..aed0318
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFabs.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testFabsFloatFloat(float in) {
+    return fabs(in);
+}
+
+float2 __attribute__((kernel)) testFabsFloat2Float2(float2 in) {
+    return fabs(in);
+}
+
+float3 __attribute__((kernel)) testFabsFloat3Float3(float3 in) {
+    return fabs(in);
+}
+
+float4 __attribute__((kernel)) testFabsFloat4Float4(float4 in) {
+    return fabs(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFabsRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestFabsRelaxed.rs
new file mode 100644
index 0000000..4d2214a
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFabsRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestFabs.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFastDistance.java b/tests/tests/renderscript/src/android/renderscript/cts/TestFastDistance.java
new file mode 100644
index 0000000..8091015
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFastDistance.java
@@ -0,0 +1,357 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestFastDistance extends RSBaseCompute {
+
+    private ScriptC_TestFastDistance script;
+    private ScriptC_TestFastDistanceRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestFastDistance(mRS);
+        scriptRelaxed = new ScriptC_TestFastDistanceRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float inLhs;
+        public float inRhs;
+        public Target.Floaty out;
+    }
+
+    private void checkFastDistanceFloatFloatFloat() {
+        Allocation inLhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xfe7e5e843bff0cb7l, false);
+        Allocation inRhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xfe7e5e843bff380dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInRhs(inRhs);
+            script.forEach_testFastDistanceFloatFloatFloat(inLhs, out);
+            verifyResultsFastDistanceFloatFloatFloat(inLhs, inRhs, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFastDistanceFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRhs(inRhs);
+            scriptRelaxed.forEach_testFastDistanceFloatFloatFloat(inLhs, out);
+            verifyResultsFastDistanceFloatFloatFloat(inLhs, inRhs, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFastDistanceFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFastDistanceFloatFloatFloat(Allocation inLhs, Allocation inRhs, Allocation out, boolean relaxed) {
+        float[] arrayInLhs = new float[INPUTSIZE * 1];
+        inLhs.copyTo(arrayInLhs);
+        float[] arrayInRhs = new float[INPUTSIZE * 1];
+        inRhs.copyTo(arrayInRhs);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+            // Create the appropriate sized arrays in args
+            // Fill args with the input values
+            args.inLhs = arrayInLhs[i];
+            args.inRhs = arrayInRhs[i];
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeFastDistance(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                message.append("Input inLhs: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayInLhs[i], Float.floatToRawIntBits(arrayInLhs[i]), arrayInLhs[i]));
+                message.append("\n");
+                message.append("Input inRhs: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayInRhs[i], Float.floatToRawIntBits(arrayInRhs[i]), arrayInRhs[i]));
+                message.append("\n");
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkFastDistanceFloatFloatFloat" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    public class ArgumentsFloatNFloatNFloat {
+        public float[] inLhs;
+        public float[] inRhs;
+        public Target.Floaty out;
+    }
+
+    private void checkFastDistanceFloat2Float2Float() {
+        Allocation inLhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x422e8a00560ac063l, false);
+        Allocation inRhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x422e8a00560aebb9l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInRhs(inRhs);
+            script.forEach_testFastDistanceFloat2Float2Float(inLhs, out);
+            verifyResultsFastDistanceFloat2Float2Float(inLhs, inRhs, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFastDistanceFloat2Float2Float: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRhs(inRhs);
+            scriptRelaxed.forEach_testFastDistanceFloat2Float2Float(inLhs, out);
+            verifyResultsFastDistanceFloat2Float2Float(inLhs, inRhs, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFastDistanceFloat2Float2Float: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFastDistanceFloat2Float2Float(Allocation inLhs, Allocation inRhs, Allocation out, boolean relaxed) {
+        float[] arrayInLhs = new float[INPUTSIZE * 2];
+        inLhs.copyTo(arrayInLhs);
+        float[] arrayInRhs = new float[INPUTSIZE * 2];
+        inRhs.copyTo(arrayInRhs);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloatNFloat args = new ArgumentsFloatNFloatNFloat();
+            // Create the appropriate sized arrays in args
+            args.inLhs = new float[2];
+            args.inRhs = new float[2];
+            // Fill args with the input values
+            for (int j = 0; j < 2 ; j++) {
+                args.inLhs[j] = arrayInLhs[i * 2 + j];
+            }
+            for (int j = 0; j < 2 ; j++) {
+                args.inRhs[j] = arrayInRhs[i * 2 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeFastDistance(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 2 ; j++) {
+                    message.append("Input inLhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInLhs[i * 2 + j], Float.floatToRawIntBits(arrayInLhs[i * 2 + j]), arrayInLhs[i * 2 + j]));
+                    message.append("\n");
+                }
+                for (int j = 0; j < 2 ; j++) {
+                    message.append("Input inRhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInRhs[i * 2 + j], Float.floatToRawIntBits(arrayInRhs[i * 2 + j]), arrayInRhs[i * 2 + j]));
+                    message.append("\n");
+                }
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkFastDistanceFloat2Float2Float" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    private void checkFastDistanceFloat3Float3Float() {
+        Allocation inLhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x6f1fd960a620dbbdl, false);
+        Allocation inRhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x6f1fd960a6210713l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInRhs(inRhs);
+            script.forEach_testFastDistanceFloat3Float3Float(inLhs, out);
+            verifyResultsFastDistanceFloat3Float3Float(inLhs, inRhs, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFastDistanceFloat3Float3Float: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRhs(inRhs);
+            scriptRelaxed.forEach_testFastDistanceFloat3Float3Float(inLhs, out);
+            verifyResultsFastDistanceFloat3Float3Float(inLhs, inRhs, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFastDistanceFloat3Float3Float: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFastDistanceFloat3Float3Float(Allocation inLhs, Allocation inRhs, Allocation out, boolean relaxed) {
+        float[] arrayInLhs = new float[INPUTSIZE * 4];
+        inLhs.copyTo(arrayInLhs);
+        float[] arrayInRhs = new float[INPUTSIZE * 4];
+        inRhs.copyTo(arrayInRhs);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloatNFloat args = new ArgumentsFloatNFloatNFloat();
+            // Create the appropriate sized arrays in args
+            args.inLhs = new float[3];
+            args.inRhs = new float[3];
+            // Fill args with the input values
+            for (int j = 0; j < 3 ; j++) {
+                args.inLhs[j] = arrayInLhs[i * 4 + j];
+            }
+            for (int j = 0; j < 3 ; j++) {
+                args.inRhs[j] = arrayInRhs[i * 4 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeFastDistance(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 3 ; j++) {
+                    message.append("Input inLhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInLhs[i * 4 + j], Float.floatToRawIntBits(arrayInLhs[i * 4 + j]), arrayInLhs[i * 4 + j]));
+                    message.append("\n");
+                }
+                for (int j = 0; j < 3 ; j++) {
+                    message.append("Input inRhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInRhs[i * 4 + j], Float.floatToRawIntBits(arrayInRhs[i * 4 + j]), arrayInRhs[i * 4 + j]));
+                    message.append("\n");
+                }
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkFastDistanceFloat3Float3Float" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    private void checkFastDistanceFloat4Float4Float() {
+        Allocation inLhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x9c1128c0f636f717l, false);
+        Allocation inRhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x9c1128c0f637226dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInRhs(inRhs);
+            script.forEach_testFastDistanceFloat4Float4Float(inLhs, out);
+            verifyResultsFastDistanceFloat4Float4Float(inLhs, inRhs, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFastDistanceFloat4Float4Float: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRhs(inRhs);
+            scriptRelaxed.forEach_testFastDistanceFloat4Float4Float(inLhs, out);
+            verifyResultsFastDistanceFloat4Float4Float(inLhs, inRhs, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFastDistanceFloat4Float4Float: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFastDistanceFloat4Float4Float(Allocation inLhs, Allocation inRhs, Allocation out, boolean relaxed) {
+        float[] arrayInLhs = new float[INPUTSIZE * 4];
+        inLhs.copyTo(arrayInLhs);
+        float[] arrayInRhs = new float[INPUTSIZE * 4];
+        inRhs.copyTo(arrayInRhs);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloatNFloat args = new ArgumentsFloatNFloatNFloat();
+            // Create the appropriate sized arrays in args
+            args.inLhs = new float[4];
+            args.inRhs = new float[4];
+            // Fill args with the input values
+            for (int j = 0; j < 4 ; j++) {
+                args.inLhs[j] = arrayInLhs[i * 4 + j];
+            }
+            for (int j = 0; j < 4 ; j++) {
+                args.inRhs[j] = arrayInRhs[i * 4 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeFastDistance(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 4 ; j++) {
+                    message.append("Input inLhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInLhs[i * 4 + j], Float.floatToRawIntBits(arrayInLhs[i * 4 + j]), arrayInLhs[i * 4 + j]));
+                    message.append("\n");
+                }
+                for (int j = 0; j < 4 ; j++) {
+                    message.append("Input inRhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInRhs[i * 4 + j], Float.floatToRawIntBits(arrayInRhs[i * 4 + j]), arrayInRhs[i * 4 + j]));
+                    message.append("\n");
+                }
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkFastDistanceFloat4Float4Float" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    public void testFastDistance() {
+        checkFastDistanceFloatFloatFloat();
+        checkFastDistanceFloat2Float2Float();
+        checkFastDistanceFloat3Float3Float();
+        checkFastDistanceFloat4Float4Float();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFastDistance.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestFastDistance.rs
new file mode 100644
index 0000000..62c0931
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFastDistance.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInRhs;
+
+float __attribute__((kernel)) testFastDistanceFloatFloatFloat(float inLhs, unsigned int x) {
+    float inRhs = rsGetElementAt_float(gAllocInRhs, x);
+    return fast_distance(inLhs, inRhs);
+}
+
+float __attribute__((kernel)) testFastDistanceFloat2Float2Float(float2 inLhs, unsigned int x) {
+    float2 inRhs = rsGetElementAt_float2(gAllocInRhs, x);
+    return fast_distance(inLhs, inRhs);
+}
+
+float __attribute__((kernel)) testFastDistanceFloat3Float3Float(float3 inLhs, unsigned int x) {
+    float3 inRhs = rsGetElementAt_float3(gAllocInRhs, x);
+    return fast_distance(inLhs, inRhs);
+}
+
+float __attribute__((kernel)) testFastDistanceFloat4Float4Float(float4 inLhs, unsigned int x) {
+    float4 inRhs = rsGetElementAt_float4(gAllocInRhs, x);
+    return fast_distance(inLhs, inRhs);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFastDistanceRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestFastDistanceRelaxed.rs
new file mode 100644
index 0000000..245bc65
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFastDistanceRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestFastDistance.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFastLength.java b/tests/tests/renderscript/src/android/renderscript/cts/TestFastLength.java
new file mode 100644
index 0000000..e990d15
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFastLength.java
@@ -0,0 +1,300 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestFastLength extends RSBaseCompute {
+
+    private ScriptC_TestFastLength script;
+    private ScriptC_TestFastLengthRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestFastLength(mRS);
+        scriptRelaxed = new ScriptC_TestFastLengthRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkFastLengthFloatFloat() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xebac65aea2660e8fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testFastLengthFloatFloat(inV, out);
+            verifyResultsFastLengthFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFastLengthFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testFastLengthFloatFloat(inV, out);
+            verifyResultsFastLengthFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFastLengthFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFastLengthFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+            // Create the appropriate sized arrays in args
+            // Fill args with the input values
+            args.inV = arrayInV[i];
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeFastLength(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                message.append("Input inV: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayInV[i], Float.floatToRawIntBits(arrayInV[i]), arrayInV[i]));
+                message.append("\n");
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkFastLengthFloatFloat" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    public class ArgumentsFloatNFloat {
+        public float[] inV;
+        public Target.Floaty out;
+    }
+
+    private void checkFastLengthFloat2Float() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x95f43650f85e6cadl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testFastLengthFloat2Float(inV, out);
+            verifyResultsFastLengthFloat2Float(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFastLengthFloat2Float: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testFastLengthFloat2Float(inV, out);
+            verifyResultsFastLengthFloat2Float(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFastLengthFloat2Float: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFastLengthFloat2Float(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloat args = new ArgumentsFloatNFloat();
+            // Create the appropriate sized arrays in args
+            args.inV = new float[2];
+            // Fill args with the input values
+            for (int j = 0; j < 2 ; j++) {
+                args.inV[j] = arrayInV[i * 2 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeFastLength(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 2 ; j++) {
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInV[i * 2 + j], Float.floatToRawIntBits(arrayInV[i * 2 + j]), arrayInV[i * 2 + j]));
+                    message.append("\n");
+                }
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkFastLengthFloat2Float" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    private void checkFastLengthFloat3Float() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x95f440f25764fb0el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testFastLengthFloat3Float(inV, out);
+            verifyResultsFastLengthFloat3Float(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFastLengthFloat3Float: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testFastLengthFloat3Float(inV, out);
+            verifyResultsFastLengthFloat3Float(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFastLengthFloat3Float: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFastLengthFloat3Float(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloat args = new ArgumentsFloatNFloat();
+            // Create the appropriate sized arrays in args
+            args.inV = new float[3];
+            // Fill args with the input values
+            for (int j = 0; j < 3 ; j++) {
+                args.inV[j] = arrayInV[i * 4 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeFastLength(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 3 ; j++) {
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInV[i * 4 + j], Float.floatToRawIntBits(arrayInV[i * 4 + j]), arrayInV[i * 4 + j]));
+                    message.append("\n");
+                }
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkFastLengthFloat3Float" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    private void checkFastLengthFloat4Float() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x95f44b93b66b896fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testFastLengthFloat4Float(inV, out);
+            verifyResultsFastLengthFloat4Float(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFastLengthFloat4Float: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testFastLengthFloat4Float(inV, out);
+            verifyResultsFastLengthFloat4Float(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFastLengthFloat4Float: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFastLengthFloat4Float(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloat args = new ArgumentsFloatNFloat();
+            // Create the appropriate sized arrays in args
+            args.inV = new float[4];
+            // Fill args with the input values
+            for (int j = 0; j < 4 ; j++) {
+                args.inV[j] = arrayInV[i * 4 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeFastLength(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 4 ; j++) {
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInV[i * 4 + j], Float.floatToRawIntBits(arrayInV[i * 4 + j]), arrayInV[i * 4 + j]));
+                    message.append("\n");
+                }
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkFastLengthFloat4Float" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    public void testFastLength() {
+        checkFastLengthFloatFloat();
+        checkFastLengthFloat2Float();
+        checkFastLengthFloat3Float();
+        checkFastLengthFloat4Float();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFastLength.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestFastLength.rs
new file mode 100644
index 0000000..f4fc853
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFastLength.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testFastLengthFloatFloat(float inV) {
+    return fast_length(inV);
+}
+
+float __attribute__((kernel)) testFastLengthFloat2Float(float2 inV) {
+    return fast_length(inV);
+}
+
+float __attribute__((kernel)) testFastLengthFloat3Float(float3 inV) {
+    return fast_length(inV);
+}
+
+float __attribute__((kernel)) testFastLengthFloat4Float(float4 inV) {
+    return fast_length(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFastLengthRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestFastLengthRelaxed.rs
new file mode 100644
index 0000000..680c3e1
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFastLengthRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestFastLength.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFastNormalize.java b/tests/tests/renderscript/src/android/renderscript/cts/TestFastNormalize.java
new file mode 100644
index 0000000..4e42575
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFastNormalize.java
@@ -0,0 +1,315 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestFastNormalize extends RSBaseCompute {
+
+    private ScriptC_TestFastNormalize script;
+    private ScriptC_TestFastNormalizeRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestFastNormalize(mRS);
+        scriptRelaxed = new ScriptC_TestFastNormalizeRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkFastNormalizeFloatFloat() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xdcfb9adc9f8882ecl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testFastNormalizeFloatFloat(inV, out);
+            verifyResultsFastNormalizeFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFastNormalizeFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testFastNormalizeFloatFloat(inV, out);
+            verifyResultsFastNormalizeFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFastNormalizeFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFastNormalizeFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+            // Create the appropriate sized arrays in args
+            // Fill args with the input values
+            args.inV = arrayInV[i];
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeFastNormalize(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                message.append("Input inV: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayInV[i], Float.floatToRawIntBits(arrayInV[i]), arrayInV[i]));
+                message.append("\n");
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkFastNormalizeFloatFloat" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    public class ArgumentsFloatNFloatN {
+        public float[] inV;
+        public Target.Floaty[] out;
+    }
+
+    private void checkFastNormalizeFloat2Float2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x151c38c30573db70l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testFastNormalizeFloat2Float2(inV, out);
+            verifyResultsFastNormalizeFloat2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFastNormalizeFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testFastNormalizeFloat2Float2(inV, out);
+            verifyResultsFastNormalizeFloat2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFastNormalizeFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFastNormalizeFloat2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloatN args = new ArgumentsFloatNFloatN();
+            // Create the appropriate sized arrays in args
+            args.inV = new float[2];
+            args.out = new Target.Floaty[2];
+            // Fill args with the input values
+            for (int j = 0; j < 2 ; j++) {
+                args.inV[j] = arrayInV[i * 2 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeFastNormalize(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            for (int j = 0; j < 2 ; j++) {
+                if (!args.out[j].couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 2 ; j++) {
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInV[i * 2 + j], Float.floatToRawIntBits(arrayInV[i * 2 + j]), arrayInV[i * 2 + j]));
+                    message.append("\n");
+                }
+                for (int j = 0; j < 2 ; j++) {
+                    message.append("Expected output out: ");
+                    message.append(args.out[j].toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out[j].couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                }
+                assertTrue("Incorrect output for checkFastNormalizeFloat2Float2" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    private void checkFastNormalizeFloat3Float3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x151e01ddfb8efc4el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testFastNormalizeFloat3Float3(inV, out);
+            verifyResultsFastNormalizeFloat3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFastNormalizeFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testFastNormalizeFloat3Float3(inV, out);
+            verifyResultsFastNormalizeFloat3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFastNormalizeFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFastNormalizeFloat3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloatN args = new ArgumentsFloatNFloatN();
+            // Create the appropriate sized arrays in args
+            args.inV = new float[3];
+            args.out = new Target.Floaty[3];
+            // Fill args with the input values
+            for (int j = 0; j < 3 ; j++) {
+                args.inV[j] = arrayInV[i * 4 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeFastNormalize(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            for (int j = 0; j < 3 ; j++) {
+                if (!args.out[j].couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 3 ; j++) {
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInV[i * 4 + j], Float.floatToRawIntBits(arrayInV[i * 4 + j]), arrayInV[i * 4 + j]));
+                    message.append("\n");
+                }
+                for (int j = 0; j < 3 ; j++) {
+                    message.append("Expected output out: ");
+                    message.append(args.out[j].toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out[j].couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                }
+                assertTrue("Incorrect output for checkFastNormalizeFloat3Float3" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    private void checkFastNormalizeFloat4Float4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x151fcaf8f1aa1d2cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testFastNormalizeFloat4Float4(inV, out);
+            verifyResultsFastNormalizeFloat4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFastNormalizeFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testFastNormalizeFloat4Float4(inV, out);
+            verifyResultsFastNormalizeFloat4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFastNormalizeFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFastNormalizeFloat4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloatN args = new ArgumentsFloatNFloatN();
+            // Create the appropriate sized arrays in args
+            args.inV = new float[4];
+            args.out = new Target.Floaty[4];
+            // Fill args with the input values
+            for (int j = 0; j < 4 ; j++) {
+                args.inV[j] = arrayInV[i * 4 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeFastNormalize(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            for (int j = 0; j < 4 ; j++) {
+                if (!args.out[j].couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 4 ; j++) {
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInV[i * 4 + j], Float.floatToRawIntBits(arrayInV[i * 4 + j]), arrayInV[i * 4 + j]));
+                    message.append("\n");
+                }
+                for (int j = 0; j < 4 ; j++) {
+                    message.append("Expected output out: ");
+                    message.append(args.out[j].toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out[j].couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                }
+                assertTrue("Incorrect output for checkFastNormalizeFloat4Float4" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    public void testFastNormalize() {
+        checkFastNormalizeFloatFloat();
+        checkFastNormalizeFloat2Float2();
+        checkFastNormalizeFloat3Float3();
+        checkFastNormalizeFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFastNormalize.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestFastNormalize.rs
new file mode 100644
index 0000000..449c49c
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFastNormalize.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testFastNormalizeFloatFloat(float inV) {
+    return fast_normalize(inV);
+}
+
+float2 __attribute__((kernel)) testFastNormalizeFloat2Float2(float2 inV) {
+    return fast_normalize(inV);
+}
+
+float3 __attribute__((kernel)) testFastNormalizeFloat3Float3(float3 inV) {
+    return fast_normalize(inV);
+}
+
+float4 __attribute__((kernel)) testFastNormalizeFloat4Float4(float4 inV) {
+    return fast_normalize(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFastNormalizeRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestFastNormalizeRelaxed.rs
new file mode 100644
index 0000000..e195f60
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFastNormalizeRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestFastNormalize.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFdim.java b/tests/tests/renderscript/src/android/renderscript/cts/TestFdim.java
new file mode 100644
index 0000000..bbe1e7a
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFdim.java
@@ -0,0 +1,325 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestFdim extends RSBaseCompute {
+
+    private ScriptC_TestFdim script;
+    private ScriptC_TestFdimRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestFdim(mRS);
+        scriptRelaxed = new ScriptC_TestFdimRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float inA;
+        public float inB;
+        public Target.Floaty out;
+    }
+
+    private void checkFdimFloatFloatFloat() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xf5dd38fbc3a47366l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xf5dd38fbc3a47367l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testFdimFloatFloatFloat(inA, out);
+            verifyResultsFdimFloatFloatFloat(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFdimFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testFdimFloatFloatFloat(inA, out);
+            verifyResultsFdimFloatFloatFloat(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFdimFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFdimFloatFloatFloat(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        float[] arrayInA = new float[INPUTSIZE * 1];
+        inA.copyTo(arrayInA);
+        float[] arrayInB = new float[INPUTSIZE * 1];
+        inB.copyTo(arrayInB);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inA = arrayInA[i];
+                args.inB = arrayInB[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFdim(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inA: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inA, Float.floatToRawIntBits(args.inA), args.inA));
+                    message.append("\n");
+                    message.append("Input inB: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inB, Float.floatToRawIntBits(args.inB), args.inB));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFdimFloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFdimFloat2Float2Float2() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xca6a96c16f167f4cl, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xca6a96c16f167f4dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testFdimFloat2Float2Float2(inA, out);
+            verifyResultsFdimFloat2Float2Float2(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFdimFloat2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testFdimFloat2Float2Float2(inA, out);
+            verifyResultsFdimFloat2Float2Float2(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFdimFloat2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFdimFloat2Float2Float2(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        float[] arrayInA = new float[INPUTSIZE * 2];
+        inA.copyTo(arrayInA);
+        float[] arrayInB = new float[INPUTSIZE * 2];
+        inB.copyTo(arrayInB);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inA = arrayInA[i * 2 + j];
+                args.inB = arrayInB[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFdim(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inA: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inA, Float.floatToRawIntBits(args.inA), args.inA));
+                    message.append("\n");
+                    message.append("Input inB: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inB, Float.floatToRawIntBits(args.inB), args.inB));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFdimFloat2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFdimFloat3Float3Float3() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x1ecf74e170f480edl, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x1ecf74e170f480eel, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testFdimFloat3Float3Float3(inA, out);
+            verifyResultsFdimFloat3Float3Float3(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFdimFloat3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testFdimFloat3Float3Float3(inA, out);
+            verifyResultsFdimFloat3Float3Float3(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFdimFloat3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFdimFloat3Float3Float3(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        float[] arrayInA = new float[INPUTSIZE * 4];
+        inA.copyTo(arrayInA);
+        float[] arrayInB = new float[INPUTSIZE * 4];
+        inB.copyTo(arrayInB);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inA = arrayInA[i * 4 + j];
+                args.inB = arrayInB[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFdim(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inA: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inA, Float.floatToRawIntBits(args.inA), args.inA));
+                    message.append("\n");
+                    message.append("Input inB: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inB, Float.floatToRawIntBits(args.inB), args.inB));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFdimFloat3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFdimFloat4Float4Float4() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x7334530172d2828el, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x7334530172d2828fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testFdimFloat4Float4Float4(inA, out);
+            verifyResultsFdimFloat4Float4Float4(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFdimFloat4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testFdimFloat4Float4Float4(inA, out);
+            verifyResultsFdimFloat4Float4Float4(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFdimFloat4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFdimFloat4Float4Float4(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        float[] arrayInA = new float[INPUTSIZE * 4];
+        inA.copyTo(arrayInA);
+        float[] arrayInB = new float[INPUTSIZE * 4];
+        inB.copyTo(arrayInB);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inA = arrayInA[i * 4 + j];
+                args.inB = arrayInB[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFdim(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inA: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inA, Float.floatToRawIntBits(args.inA), args.inA));
+                    message.append("\n");
+                    message.append("Input inB: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inB, Float.floatToRawIntBits(args.inB), args.inB));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFdimFloat4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testFdim() {
+        checkFdimFloatFloatFloat();
+        checkFdimFloat2Float2Float2();
+        checkFdimFloat3Float3Float3();
+        checkFdimFloat4Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFdim.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestFdim.rs
new file mode 100644
index 0000000..8f68c14
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFdim.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInB;
+
+float __attribute__((kernel)) testFdimFloatFloatFloat(float inA, unsigned int x) {
+    float inB = rsGetElementAt_float(gAllocInB, x);
+    return fdim(inA, inB);
+}
+
+float2 __attribute__((kernel)) testFdimFloat2Float2Float2(float2 inA, unsigned int x) {
+    float2 inB = rsGetElementAt_float2(gAllocInB, x);
+    return fdim(inA, inB);
+}
+
+float3 __attribute__((kernel)) testFdimFloat3Float3Float3(float3 inA, unsigned int x) {
+    float3 inB = rsGetElementAt_float3(gAllocInB, x);
+    return fdim(inA, inB);
+}
+
+float4 __attribute__((kernel)) testFdimFloat4Float4Float4(float4 inA, unsigned int x) {
+    float4 inB = rsGetElementAt_float4(gAllocInB, x);
+    return fdim(inA, inB);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFdimRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestFdimRelaxed.rs
new file mode 100644
index 0000000..473a588
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFdimRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestFdim.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFloor.java b/tests/tests/renderscript/src/android/renderscript/cts/TestFloor.java
new file mode 100644
index 0000000..39ec8bd
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFloor.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestFloor extends RSBaseCompute {
+
+    private ScriptC_TestFloor script;
+    private ScriptC_TestFloorRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestFloor(mRS);
+        scriptRelaxed = new ScriptC_TestFloorRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkFloorFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x9c2b15433f045885l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testFloorFloatFloat(in, out);
+            verifyResultsFloorFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFloorFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testFloorFloatFloat(in, out);
+            verifyResultsFloorFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFloorFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFloorFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFloor(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFloorFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFloorFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xf32bb4add79bd3b9l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testFloorFloat2Float2(in, out);
+            verifyResultsFloorFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFloorFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testFloorFloat2Float2(in, out);
+            verifyResultsFloorFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFloorFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFloorFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFloor(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFloorFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFloorFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xf32bbf4f36a26953l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testFloorFloat3Float3(in, out);
+            verifyResultsFloorFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFloorFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testFloorFloat3Float3(in, out);
+            verifyResultsFloorFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFloorFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFloorFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFloor(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFloorFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFloorFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xf32bc9f095a8feedl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testFloorFloat4Float4(in, out);
+            verifyResultsFloorFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFloorFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testFloorFloat4Float4(in, out);
+            verifyResultsFloorFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFloorFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFloorFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFloor(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFloorFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testFloor() {
+        checkFloorFloatFloat();
+        checkFloorFloat2Float2();
+        checkFloorFloat3Float3();
+        checkFloorFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFloor.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestFloor.rs
new file mode 100644
index 0000000..f74fc2b
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFloor.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testFloorFloatFloat(float in) {
+    return floor(in);
+}
+
+float2 __attribute__((kernel)) testFloorFloat2Float2(float2 in) {
+    return floor(in);
+}
+
+float3 __attribute__((kernel)) testFloorFloat3Float3(float3 in) {
+    return floor(in);
+}
+
+float4 __attribute__((kernel)) testFloorFloat4Float4(float4 in) {
+    return floor(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFloorRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestFloorRelaxed.rs
new file mode 100644
index 0000000..4caf0de
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFloorRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestFloor.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFma.java b/tests/tests/renderscript/src/android/renderscript/cts/TestFma.java
new file mode 100644
index 0000000..fcb7c5f
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFma.java
@@ -0,0 +1,366 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestFma extends RSBaseCompute {
+
+    private ScriptC_TestFma script;
+    private ScriptC_TestFmaRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestFma(mRS);
+        scriptRelaxed = new ScriptC_TestFmaRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloatFloat {
+        public float inA;
+        public float inB;
+        public float inC;
+        public Target.Floaty out;
+    }
+
+    private void checkFmaFloatFloatFloatFloat() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x5f6b3ee0c3466c2l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x5f6b3ee0c3466c3l, false);
+        Allocation inC = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x5f6b3ee0c3466c4l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.set_gAllocInC(inC);
+            script.forEach_testFmaFloatFloatFloatFloat(inA, out);
+            verifyResultsFmaFloatFloatFloatFloat(inA, inB, inC, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaFloatFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.set_gAllocInC(inC);
+            scriptRelaxed.forEach_testFmaFloatFloatFloatFloat(inA, out);
+            verifyResultsFmaFloatFloatFloatFloat(inA, inB, inC, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaFloatFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmaFloatFloatFloatFloat(Allocation inA, Allocation inB, Allocation inC, Allocation out, boolean relaxed) {
+        float[] arrayInA = new float[INPUTSIZE * 1];
+        inA.copyTo(arrayInA);
+        float[] arrayInB = new float[INPUTSIZE * 1];
+        inB.copyTo(arrayInB);
+        float[] arrayInC = new float[INPUTSIZE * 1];
+        inC.copyTo(arrayInC);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloatFloat args = new ArgumentsFloatFloatFloatFloat();
+                args.inA = arrayInA[i];
+                args.inB = arrayInB[i];
+                args.inC = arrayInC[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFma(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inA: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inA, Float.floatToRawIntBits(args.inA), args.inA));
+                    message.append("\n");
+                    message.append("Input inB: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inB, Float.floatToRawIntBits(args.inB), args.inB));
+                    message.append("\n");
+                    message.append("Input inC: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inC, Float.floatToRawIntBits(args.inC), args.inC));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFmaFloatFloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFmaFloat2Float2Float2Float2() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x47b62b8849bc43dal, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x47b62b8849bc43dbl, false);
+        Allocation inC = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x47b62b8849bc43dcl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.set_gAllocInC(inC);
+            script.forEach_testFmaFloat2Float2Float2Float2(inA, out);
+            verifyResultsFmaFloat2Float2Float2Float2(inA, inB, inC, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaFloat2Float2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.set_gAllocInC(inC);
+            scriptRelaxed.forEach_testFmaFloat2Float2Float2Float2(inA, out);
+            verifyResultsFmaFloat2Float2Float2Float2(inA, inB, inC, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaFloat2Float2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmaFloat2Float2Float2Float2(Allocation inA, Allocation inB, Allocation inC, Allocation out, boolean relaxed) {
+        float[] arrayInA = new float[INPUTSIZE * 2];
+        inA.copyTo(arrayInA);
+        float[] arrayInB = new float[INPUTSIZE * 2];
+        inB.copyTo(arrayInB);
+        float[] arrayInC = new float[INPUTSIZE * 2];
+        inC.copyTo(arrayInC);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloatFloat args = new ArgumentsFloatFloatFloatFloat();
+                args.inA = arrayInA[i * 2 + j];
+                args.inB = arrayInB[i * 2 + j];
+                args.inC = arrayInC[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFma(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inA: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inA, Float.floatToRawIntBits(args.inA), args.inA));
+                    message.append("\n");
+                    message.append("Input inB: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inB, Float.floatToRawIntBits(args.inB), args.inB));
+                    message.append("\n");
+                    message.append("Input inC: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inC, Float.floatToRawIntBits(args.inC), args.inC));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFmaFloat2Float2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFmaFloat3Float3Float3Float3() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x1d2fcf231c237d76l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x1d2fcf231c237d77l, false);
+        Allocation inC = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x1d2fcf231c237d78l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.set_gAllocInC(inC);
+            script.forEach_testFmaFloat3Float3Float3Float3(inA, out);
+            verifyResultsFmaFloat3Float3Float3Float3(inA, inB, inC, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaFloat3Float3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.set_gAllocInC(inC);
+            scriptRelaxed.forEach_testFmaFloat3Float3Float3Float3(inA, out);
+            verifyResultsFmaFloat3Float3Float3Float3(inA, inB, inC, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaFloat3Float3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmaFloat3Float3Float3Float3(Allocation inA, Allocation inB, Allocation inC, Allocation out, boolean relaxed) {
+        float[] arrayInA = new float[INPUTSIZE * 4];
+        inA.copyTo(arrayInA);
+        float[] arrayInB = new float[INPUTSIZE * 4];
+        inB.copyTo(arrayInB);
+        float[] arrayInC = new float[INPUTSIZE * 4];
+        inC.copyTo(arrayInC);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloatFloat args = new ArgumentsFloatFloatFloatFloat();
+                args.inA = arrayInA[i * 4 + j];
+                args.inB = arrayInB[i * 4 + j];
+                args.inC = arrayInC[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFma(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inA: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inA, Float.floatToRawIntBits(args.inA), args.inA));
+                    message.append("\n");
+                    message.append("Input inB: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inB, Float.floatToRawIntBits(args.inB), args.inB));
+                    message.append("\n");
+                    message.append("Input inC: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inC, Float.floatToRawIntBits(args.inC), args.inC));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFmaFloat3Float3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFmaFloat4Float4Float4Float4() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xf2a972bdee8ab712l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xf2a972bdee8ab713l, false);
+        Allocation inC = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xf2a972bdee8ab714l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.set_gAllocInC(inC);
+            script.forEach_testFmaFloat4Float4Float4Float4(inA, out);
+            verifyResultsFmaFloat4Float4Float4Float4(inA, inB, inC, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaFloat4Float4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.set_gAllocInC(inC);
+            scriptRelaxed.forEach_testFmaFloat4Float4Float4Float4(inA, out);
+            verifyResultsFmaFloat4Float4Float4Float4(inA, inB, inC, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaFloat4Float4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmaFloat4Float4Float4Float4(Allocation inA, Allocation inB, Allocation inC, Allocation out, boolean relaxed) {
+        float[] arrayInA = new float[INPUTSIZE * 4];
+        inA.copyTo(arrayInA);
+        float[] arrayInB = new float[INPUTSIZE * 4];
+        inB.copyTo(arrayInB);
+        float[] arrayInC = new float[INPUTSIZE * 4];
+        inC.copyTo(arrayInC);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloatFloat args = new ArgumentsFloatFloatFloatFloat();
+                args.inA = arrayInA[i * 4 + j];
+                args.inB = arrayInB[i * 4 + j];
+                args.inC = arrayInC[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFma(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inA: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inA, Float.floatToRawIntBits(args.inA), args.inA));
+                    message.append("\n");
+                    message.append("Input inB: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inB, Float.floatToRawIntBits(args.inB), args.inB));
+                    message.append("\n");
+                    message.append("Input inC: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inC, Float.floatToRawIntBits(args.inC), args.inC));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFmaFloat4Float4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testFma() {
+        checkFmaFloatFloatFloatFloat();
+        checkFmaFloat2Float2Float2Float2();
+        checkFmaFloat3Float3Float3Float3();
+        checkFmaFloat4Float4Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFma.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestFma.rs
new file mode 100644
index 0000000..b0cb2dd
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFma.rs
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInB;
+rs_allocation gAllocInC;
+
+float __attribute__((kernel)) testFmaFloatFloatFloatFloat(float inA, unsigned int x) {
+    float inB = rsGetElementAt_float(gAllocInB, x);
+    float inC = rsGetElementAt_float(gAllocInC, x);
+    return fma(inA, inB, inC);
+}
+
+float2 __attribute__((kernel)) testFmaFloat2Float2Float2Float2(float2 inA, unsigned int x) {
+    float2 inB = rsGetElementAt_float2(gAllocInB, x);
+    float2 inC = rsGetElementAt_float2(gAllocInC, x);
+    return fma(inA, inB, inC);
+}
+
+float3 __attribute__((kernel)) testFmaFloat3Float3Float3Float3(float3 inA, unsigned int x) {
+    float3 inB = rsGetElementAt_float3(gAllocInB, x);
+    float3 inC = rsGetElementAt_float3(gAllocInC, x);
+    return fma(inA, inB, inC);
+}
+
+float4 __attribute__((kernel)) testFmaFloat4Float4Float4Float4(float4 inA, unsigned int x) {
+    float4 inB = rsGetElementAt_float4(gAllocInB, x);
+    float4 inC = rsGetElementAt_float4(gAllocInC, x);
+    return fma(inA, inB, inC);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFmaRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestFmaRelaxed.rs
new file mode 100644
index 0000000..cc80e06
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFmaRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestFma.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFmax.java b/tests/tests/renderscript/src/android/renderscript/cts/TestFmax.java
new file mode 100644
index 0000000..7d4e633
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFmax.java
@@ -0,0 +1,535 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestFmax extends RSBaseCompute {
+
+    private ScriptC_TestFmax script;
+    private ScriptC_TestFmaxRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestFmax(mRS);
+        scriptRelaxed = new ScriptC_TestFmaxRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float inX;
+        public float inY;
+        public Target.Floaty out;
+    }
+
+    private void checkFmaxFloatFloatFloat() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xe6ec75a46e6fdd91l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xe6ec75a46e6fdd92l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testFmaxFloatFloatFloat(inX, out);
+            verifyResultsFmaxFloatFloatFloat(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testFmaxFloatFloatFloat(inX, out);
+            verifyResultsFmaxFloatFloatFloat(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmaxFloatFloatFloat(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 1];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 1];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i];
+                args.inY = arrayInY[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFmax(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFmaxFloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFmaxFloat2Float2Float2() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xa99eaa6dd458a0dfl, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xa99eaa6dd458a0e0l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testFmaxFloat2Float2Float2(inX, out);
+            verifyResultsFmaxFloat2Float2Float2(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxFloat2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testFmaxFloat2Float2Float2(inX, out);
+            verifyResultsFmaxFloat2Float2Float2(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxFloat2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmaxFloat2Float2Float2(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 2];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 2];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 2 + j];
+                args.inY = arrayInY[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFmax(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFmaxFloat2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFmaxFloat3Float3Float3() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xfe03888dd636a280l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xfe03888dd636a281l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testFmaxFloat3Float3Float3(inX, out);
+            verifyResultsFmaxFloat3Float3Float3(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxFloat3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testFmaxFloat3Float3Float3(inX, out);
+            verifyResultsFmaxFloat3Float3Float3(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxFloat3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmaxFloat3Float3Float3(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFmax(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFmaxFloat3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFmaxFloat4Float4Float4() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x526866add814a421l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x526866add814a422l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testFmaxFloat4Float4Float4(inX, out);
+            verifyResultsFmaxFloat4Float4Float4(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxFloat4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testFmaxFloat4Float4Float4(inX, out);
+            verifyResultsFmaxFloat4Float4Float4(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxFloat4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmaxFloat4Float4Float4(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFmax(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFmaxFloat4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFmaxFloat2FloatFloat2() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xce5ddc06dc631119l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xce5ddc06dc63111al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testFmaxFloat2FloatFloat2(inX, out);
+            verifyResultsFmaxFloat2FloatFloat2(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxFloat2FloatFloat2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testFmaxFloat2FloatFloat2(inX, out);
+            verifyResultsFmaxFloat2FloatFloat2(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxFloat2FloatFloat2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmaxFloat2FloatFloat2(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 2];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 1];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 2 + j];
+                args.inY = arrayInY[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFmax(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFmaxFloat2FloatFloat2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFmaxFloat3FloatFloat3() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x23ad8f1ecace0575l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x23ad8f1ecace0576l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testFmaxFloat3FloatFloat3(inX, out);
+            verifyResultsFmaxFloat3FloatFloat3(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxFloat3FloatFloat3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testFmaxFloat3FloatFloat3(inX, out);
+            verifyResultsFmaxFloat3FloatFloat3(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxFloat3FloatFloat3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmaxFloat3FloatFloat3(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 1];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFmax(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFmaxFloat3FloatFloat3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFmaxFloat4FloatFloat4() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x78fd4236b938f9d1l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x78fd4236b938f9d2l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testFmaxFloat4FloatFloat4(inX, out);
+            verifyResultsFmaxFloat4FloatFloat4(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxFloat4FloatFloat4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testFmaxFloat4FloatFloat4(inX, out);
+            verifyResultsFmaxFloat4FloatFloat4(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxFloat4FloatFloat4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmaxFloat4FloatFloat4(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 1];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFmax(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFmaxFloat4FloatFloat4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testFmax() {
+        checkFmaxFloatFloatFloat();
+        checkFmaxFloat2Float2Float2();
+        checkFmaxFloat3Float3Float3();
+        checkFmaxFloat4Float4Float4();
+        checkFmaxFloat2FloatFloat2();
+        checkFmaxFloat3FloatFloat3();
+        checkFmaxFloat4FloatFloat4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFmax.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestFmax.rs
new file mode 100644
index 0000000..50e5e3f
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFmax.rs
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInY;
+
+float __attribute__((kernel)) testFmaxFloatFloatFloat(float inX, unsigned int x) {
+    float inY = rsGetElementAt_float(gAllocInY, x);
+    return fmax(inX, inY);
+}
+
+float2 __attribute__((kernel)) testFmaxFloat2Float2Float2(float2 inX, unsigned int x) {
+    float2 inY = rsGetElementAt_float2(gAllocInY, x);
+    return fmax(inX, inY);
+}
+
+float3 __attribute__((kernel)) testFmaxFloat3Float3Float3(float3 inX, unsigned int x) {
+    float3 inY = rsGetElementAt_float3(gAllocInY, x);
+    return fmax(inX, inY);
+}
+
+float4 __attribute__((kernel)) testFmaxFloat4Float4Float4(float4 inX, unsigned int x) {
+    float4 inY = rsGetElementAt_float4(gAllocInY, x);
+    return fmax(inX, inY);
+}
+
+float2 __attribute__((kernel)) testFmaxFloat2FloatFloat2(float2 inX, unsigned int x) {
+    float inY = rsGetElementAt_float(gAllocInY, x);
+    return fmax(inX, inY);
+}
+
+float3 __attribute__((kernel)) testFmaxFloat3FloatFloat3(float3 inX, unsigned int x) {
+    float inY = rsGetElementAt_float(gAllocInY, x);
+    return fmax(inX, inY);
+}
+
+float4 __attribute__((kernel)) testFmaxFloat4FloatFloat4(float4 inX, unsigned int x) {
+    float inY = rsGetElementAt_float(gAllocInY, x);
+    return fmax(inX, inY);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFmaxRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestFmaxRelaxed.rs
new file mode 100644
index 0000000..74c8b3d
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFmaxRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestFmax.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFmin.java b/tests/tests/renderscript/src/android/renderscript/cts/TestFmin.java
new file mode 100644
index 0000000..f206a74
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFmin.java
@@ -0,0 +1,535 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestFmin extends RSBaseCompute {
+
+    private ScriptC_TestFmin script;
+    private ScriptC_TestFminRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestFmin(mRS);
+        scriptRelaxed = new ScriptC_TestFminRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float inX;
+        public float inY;
+        public Target.Floaty out;
+    }
+
+    private void checkFminFloatFloatFloat() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x7b46a8451d7b106fl, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x7b46a8451d7b1070l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testFminFloatFloatFloat(inX, out);
+            verifyResultsFminFloatFloatFloat(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testFminFloatFloatFloat(inX, out);
+            verifyResultsFminFloatFloatFloat(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFminFloatFloatFloat(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 1];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 1];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i];
+                args.inY = arrayInY[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFmin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFminFloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFminFloat2Float2Float2() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x12b850a9e75faa59l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x12b850a9e75faa5al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testFminFloat2Float2Float2(inX, out);
+            verifyResultsFminFloat2Float2Float2(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminFloat2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testFminFloat2Float2Float2(inX, out);
+            verifyResultsFminFloat2Float2Float2(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminFloat2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFminFloat2Float2Float2(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 2];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 2];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 2 + j];
+                args.inY = arrayInY[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFmin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFminFloat2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFminFloat3Float3Float3() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x671d2ec9e93dabfal, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x671d2ec9e93dabfbl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testFminFloat3Float3Float3(inX, out);
+            verifyResultsFminFloat3Float3Float3(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminFloat3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testFminFloat3Float3Float3(inX, out);
+            verifyResultsFminFloat3Float3Float3(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminFloat3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFminFloat3Float3Float3(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFmin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFminFloat3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFminFloat4Float4Float4() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xbb820ce9eb1bad9bl, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xbb820ce9eb1bad9cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testFminFloat4Float4Float4(inX, out);
+            verifyResultsFminFloat4Float4Float4(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminFloat4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testFminFloat4Float4Float4(inX, out);
+            verifyResultsFminFloat4Float4Float4(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminFloat4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFminFloat4Float4Float4(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFmin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFminFloat4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFminFloat2FloatFloat2() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x4dd5869724457687l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x4dd5869724457688l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testFminFloat2FloatFloat2(inX, out);
+            verifyResultsFminFloat2FloatFloat2(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminFloat2FloatFloat2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testFminFloat2FloatFloat2(inX, out);
+            verifyResultsFminFloat2FloatFloat2(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminFloat2FloatFloat2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFminFloat2FloatFloat2(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 2];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 1];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 2 + j];
+                args.inY = arrayInY[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFmin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFminFloat2FloatFloat2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFminFloat3FloatFloat3() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xa32539af12b06ae3l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xa32539af12b06ae4l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testFminFloat3FloatFloat3(inX, out);
+            verifyResultsFminFloat3FloatFloat3(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminFloat3FloatFloat3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testFminFloat3FloatFloat3(inX, out);
+            verifyResultsFminFloat3FloatFloat3(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminFloat3FloatFloat3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFminFloat3FloatFloat3(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 1];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFmin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFminFloat3FloatFloat3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFminFloat4FloatFloat4() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xf874ecc7011b5f3fl, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xf874ecc7011b5f40l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testFminFloat4FloatFloat4(inX, out);
+            verifyResultsFminFloat4FloatFloat4(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminFloat4FloatFloat4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testFminFloat4FloatFloat4(inX, out);
+            verifyResultsFminFloat4FloatFloat4(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminFloat4FloatFloat4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFminFloat4FloatFloat4(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 1];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFmin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFminFloat4FloatFloat4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testFmin() {
+        checkFminFloatFloatFloat();
+        checkFminFloat2Float2Float2();
+        checkFminFloat3Float3Float3();
+        checkFminFloat4Float4Float4();
+        checkFminFloat2FloatFloat2();
+        checkFminFloat3FloatFloat3();
+        checkFminFloat4FloatFloat4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFmin.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestFmin.rs
new file mode 100644
index 0000000..28db18f
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFmin.rs
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInY;
+
+float __attribute__((kernel)) testFminFloatFloatFloat(float inX, unsigned int x) {
+    float inY = rsGetElementAt_float(gAllocInY, x);
+    return fmin(inX, inY);
+}
+
+float2 __attribute__((kernel)) testFminFloat2Float2Float2(float2 inX, unsigned int x) {
+    float2 inY = rsGetElementAt_float2(gAllocInY, x);
+    return fmin(inX, inY);
+}
+
+float3 __attribute__((kernel)) testFminFloat3Float3Float3(float3 inX, unsigned int x) {
+    float3 inY = rsGetElementAt_float3(gAllocInY, x);
+    return fmin(inX, inY);
+}
+
+float4 __attribute__((kernel)) testFminFloat4Float4Float4(float4 inX, unsigned int x) {
+    float4 inY = rsGetElementAt_float4(gAllocInY, x);
+    return fmin(inX, inY);
+}
+
+float2 __attribute__((kernel)) testFminFloat2FloatFloat2(float2 inX, unsigned int x) {
+    float inY = rsGetElementAt_float(gAllocInY, x);
+    return fmin(inX, inY);
+}
+
+float3 __attribute__((kernel)) testFminFloat3FloatFloat3(float3 inX, unsigned int x) {
+    float inY = rsGetElementAt_float(gAllocInY, x);
+    return fmin(inX, inY);
+}
+
+float4 __attribute__((kernel)) testFminFloat4FloatFloat4(float4 inX, unsigned int x) {
+    float inY = rsGetElementAt_float(gAllocInY, x);
+    return fmin(inX, inY);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFminRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestFminRelaxed.rs
new file mode 100644
index 0000000..571f64a
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFminRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestFmin.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFmod.java b/tests/tests/renderscript/src/android/renderscript/cts/TestFmod.java
new file mode 100644
index 0000000..7bd59ef
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFmod.java
@@ -0,0 +1,325 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestFmod extends RSBaseCompute {
+
+    private ScriptC_TestFmod script;
+    private ScriptC_TestFmodRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestFmod(mRS);
+        scriptRelaxed = new ScriptC_TestFmodRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float inX;
+        public float inY;
+        public Target.Floaty out;
+    }
+
+    private void checkFmodFloatFloatFloat() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x51ab5ae4481379a7l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x51ab5ae4481379a8l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testFmodFloatFloatFloat(inX, out);
+            verifyResultsFmodFloatFloatFloat(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmodFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testFmodFloatFloatFloat(inX, out);
+            verifyResultsFmodFloatFloatFloat(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmodFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmodFloatFloatFloat(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 1];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 1];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i];
+                args.inY = arrayInY[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFmod(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFmodFloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFmodFloat2Float2Float2() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x1ed79fa3ec4de581l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x1ed79fa3ec4de582l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testFmodFloat2Float2Float2(inX, out);
+            verifyResultsFmodFloat2Float2Float2(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmodFloat2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testFmodFloat2Float2Float2(inX, out);
+            verifyResultsFmodFloat2Float2Float2(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmodFloat2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmodFloat2Float2Float2(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 2];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 2];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 2 + j];
+                args.inY = arrayInY[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFmod(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFmodFloat2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFmodFloat3Float3Float3() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x733c7dc3ee2be722l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x733c7dc3ee2be723l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testFmodFloat3Float3Float3(inX, out);
+            verifyResultsFmodFloat3Float3Float3(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmodFloat3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testFmodFloat3Float3Float3(inX, out);
+            verifyResultsFmodFloat3Float3Float3(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmodFloat3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmodFloat3Float3Float3(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFmod(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFmodFloat3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFmodFloat4Float4Float4() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xc7a15be3f009e8c3l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xc7a15be3f009e8c4l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testFmodFloat4Float4Float4(inX, out);
+            verifyResultsFmodFloat4Float4Float4(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmodFloat4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testFmodFloat4Float4Float4(inX, out);
+            verifyResultsFmodFloat4Float4Float4(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmodFloat4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmodFloat4Float4Float4(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFmod(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFmodFloat4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testFmod() {
+        checkFmodFloatFloatFloat();
+        checkFmodFloat2Float2Float2();
+        checkFmodFloat3Float3Float3();
+        checkFmodFloat4Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFmod.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestFmod.rs
new file mode 100644
index 0000000..c1c2bff
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFmod.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInY;
+
+float __attribute__((kernel)) testFmodFloatFloatFloat(float inX, unsigned int x) {
+    float inY = rsGetElementAt_float(gAllocInY, x);
+    return fmod(inX, inY);
+}
+
+float2 __attribute__((kernel)) testFmodFloat2Float2Float2(float2 inX, unsigned int x) {
+    float2 inY = rsGetElementAt_float2(gAllocInY, x);
+    return fmod(inX, inY);
+}
+
+float3 __attribute__((kernel)) testFmodFloat3Float3Float3(float3 inX, unsigned int x) {
+    float3 inY = rsGetElementAt_float3(gAllocInY, x);
+    return fmod(inX, inY);
+}
+
+float4 __attribute__((kernel)) testFmodFloat4Float4Float4(float4 inX, unsigned int x) {
+    float4 inY = rsGetElementAt_float4(gAllocInY, x);
+    return fmod(inX, inY);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFmodRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestFmodRelaxed.rs
new file mode 100644
index 0000000..02888a1
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFmodRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestFmod.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFract.java b/tests/tests/renderscript/src/android/renderscript/cts/TestFract.java
new file mode 100644
index 0000000..891ad96
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFract.java
@@ -0,0 +1,606 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestFract extends RSBaseCompute {
+
+    private ScriptC_TestFract script;
+    private ScriptC_TestFractRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestFract(mRS);
+        scriptRelaxed = new ScriptC_TestFractRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float inV;
+        public Target.Floaty outFloor;
+        public Target.Floaty out;
+    }
+
+    private void checkFractFloatFloatFloat() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x57d8e6573c675d27l, false);
+        try {
+            Allocation outFloor = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocOutFloor(outFloor);
+            script.forEach_testFractFloatFloatFloat(inV, out);
+            verifyResultsFractFloatFloatFloat(inV, outFloor, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation outFloor = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutFloor(outFloor);
+            scriptRelaxed.forEach_testFractFloatFloatFloat(inV, out);
+            verifyResultsFractFloatFloatFloat(inV, outFloor, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFractFloatFloatFloat(Allocation inV, Allocation outFloor, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOutFloor = new float[INPUTSIZE * 1];
+        outFloor.copyTo(arrayOutFloor);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFract(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outFloor.couldBe(arrayOutFloor[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output outFloor: ");
+                    message.append(args.outFloor.toString());
+                    message.append("\n");
+                    message.append("Actual   output outFloor: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOutFloor[i * 1 + j], Float.floatToRawIntBits(arrayOutFloor[i * 1 + j]), arrayOutFloor[i * 1 + j]));
+                    if (!args.outFloor.couldBe(arrayOutFloor[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFractFloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFractFloat2Float2Float2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xd1dbe683cdf8f525l, false);
+        try {
+            Allocation outFloor = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocOutFloor(outFloor);
+            script.forEach_testFractFloat2Float2Float2(inV, out);
+            verifyResultsFractFloat2Float2Float2(inV, outFloor, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractFloat2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation outFloor = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutFloor(outFloor);
+            scriptRelaxed.forEach_testFractFloat2Float2Float2(inV, out);
+            verifyResultsFractFloat2Float2Float2(inV, outFloor, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractFloat2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFractFloat2Float2Float2(Allocation inV, Allocation outFloor, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOutFloor = new float[INPUTSIZE * 2];
+        outFloor.copyTo(arrayOutFloor);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFract(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outFloor.couldBe(arrayOutFloor[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output outFloor: ");
+                    message.append(args.outFloor.toString());
+                    message.append("\n");
+                    message.append("Actual   output outFloor: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOutFloor[i * 2 + j], Float.floatToRawIntBits(arrayOutFloor[i * 2 + j]), arrayOutFloor[i * 2 + j]));
+                    if (!args.outFloor.couldBe(arrayOutFloor[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFractFloat2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFractFloat3Float3Float3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x2640c4a3cfd6f6c6l, false);
+        try {
+            Allocation outFloor = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocOutFloor(outFloor);
+            script.forEach_testFractFloat3Float3Float3(inV, out);
+            verifyResultsFractFloat3Float3Float3(inV, outFloor, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractFloat3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation outFloor = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutFloor(outFloor);
+            scriptRelaxed.forEach_testFractFloat3Float3Float3(inV, out);
+            verifyResultsFractFloat3Float3Float3(inV, outFloor, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractFloat3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFractFloat3Float3Float3(Allocation inV, Allocation outFloor, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOutFloor = new float[INPUTSIZE * 4];
+        outFloor.copyTo(arrayOutFloor);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFract(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outFloor.couldBe(arrayOutFloor[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output outFloor: ");
+                    message.append(args.outFloor.toString());
+                    message.append("\n");
+                    message.append("Actual   output outFloor: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOutFloor[i * 4 + j], Float.floatToRawIntBits(arrayOutFloor[i * 4 + j]), arrayOutFloor[i * 4 + j]));
+                    if (!args.outFloor.couldBe(arrayOutFloor[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFractFloat3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFractFloat4Float4Float4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x7aa5a2c3d1b4f867l, false);
+        try {
+            Allocation outFloor = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocOutFloor(outFloor);
+            script.forEach_testFractFloat4Float4Float4(inV, out);
+            verifyResultsFractFloat4Float4Float4(inV, outFloor, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractFloat4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation outFloor = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutFloor(outFloor);
+            scriptRelaxed.forEach_testFractFloat4Float4Float4(inV, out);
+            verifyResultsFractFloat4Float4Float4(inV, outFloor, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractFloat4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFractFloat4Float4Float4(Allocation inV, Allocation outFloor, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOutFloor = new float[INPUTSIZE * 4];
+        outFloor.copyTo(arrayOutFloor);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFract(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outFloor.couldBe(arrayOutFloor[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output outFloor: ");
+                    message.append(args.outFloor.toString());
+                    message.append("\n");
+                    message.append("Actual   output outFloor: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOutFloor[i * 4 + j], Float.floatToRawIntBits(arrayOutFloor[i * 4 + j]), arrayOutFloor[i * 4 + j]));
+                    if (!args.outFloor.couldBe(arrayOutFloor[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFractFloat4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkFractFloatFloat() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xf559208b9db2cad3l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testFractFloatFloat(inV, out);
+            verifyResultsFractFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testFractFloatFloat(inV, out);
+            verifyResultsFractFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFractFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFract(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFractFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFractFloat2Float2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x1096c5acc4d52edfl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testFractFloat2Float2(inV, out);
+            verifyResultsFractFloat2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testFractFloat2Float2(inV, out);
+            verifyResultsFractFloat2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFractFloat2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFract(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFractFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFractFloat3Float3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x10988ec7baf04fbdl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testFractFloat3Float3(inV, out);
+            verifyResultsFractFloat3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testFractFloat3Float3(inV, out);
+            verifyResultsFractFloat3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFractFloat3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFract(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFractFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFractFloat4Float4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x109a57e2b10b709bl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testFractFloat4Float4(inV, out);
+            verifyResultsFractFloat4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testFractFloat4Float4(inV, out);
+            verifyResultsFractFloat4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFractFloat4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFract(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFractFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testFract() {
+        checkFractFloatFloatFloat();
+        checkFractFloat2Float2Float2();
+        checkFractFloat3Float3Float3();
+        checkFractFloat4Float4Float4();
+        checkFractFloatFloat();
+        checkFractFloat2Float2();
+        checkFractFloat3Float3();
+        checkFractFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFract.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestFract.rs
new file mode 100644
index 0000000..38351ab
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFract.rs
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocOutFloor;
+
+float __attribute__((kernel)) testFractFloatFloatFloat(float inV, unsigned int x) {
+    float outFloor = 0;
+    float out = fract(inV, &outFloor);
+    rsSetElementAt_float(gAllocOutFloor, outFloor, x);
+    return out;
+}
+
+float2 __attribute__((kernel)) testFractFloat2Float2Float2(float2 inV, unsigned int x) {
+    float2 outFloor = 0;
+    float2 out = fract(inV, &outFloor);
+    rsSetElementAt_float2(gAllocOutFloor, outFloor, x);
+    return out;
+}
+
+float3 __attribute__((kernel)) testFractFloat3Float3Float3(float3 inV, unsigned int x) {
+    float3 outFloor = 0;
+    float3 out = fract(inV, &outFloor);
+    rsSetElementAt_float3(gAllocOutFloor, outFloor, x);
+    return out;
+}
+
+float4 __attribute__((kernel)) testFractFloat4Float4Float4(float4 inV, unsigned int x) {
+    float4 outFloor = 0;
+    float4 out = fract(inV, &outFloor);
+    rsSetElementAt_float4(gAllocOutFloor, outFloor, x);
+    return out;
+}
+
+float __attribute__((kernel)) testFractFloatFloat(float inV) {
+    return fract(inV);
+}
+
+float2 __attribute__((kernel)) testFractFloat2Float2(float2 inV) {
+    return fract(inV);
+}
+
+float3 __attribute__((kernel)) testFractFloat3Float3(float3 inV) {
+    return fract(inV);
+}
+
+float4 __attribute__((kernel)) testFractFloat4Float4(float4 inV) {
+    return fract(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFractRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestFractRelaxed.rs
new file mode 100644
index 0000000..c9a98df
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFractRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestFract.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFrexp.java b/tests/tests/renderscript/src/android/renderscript/cts/TestFrexp.java
new file mode 100644
index 0000000..7258d3c
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFrexp.java
@@ -0,0 +1,357 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestFrexp extends RSBaseCompute {
+
+    private ScriptC_TestFrexp script;
+    private ScriptC_TestFrexpRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestFrexp(mRS);
+        scriptRelaxed = new ScriptC_TestFrexpRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatIntFloat {
+        public float inV;
+        public int outIptr;
+        public Target.Floaty out;
+    }
+
+    private void checkFrexpFloatIntFloat() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x57ae9fe07384e56dl, false);
+        try {
+            Allocation outIptr = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 1), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocOutIptr(outIptr);
+            script.forEach_testFrexpFloatIntFloat(inV, out);
+            verifyResultsFrexpFloatIntFloat(inV, outIptr, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFrexpFloatIntFloat: " + e.toString());
+        }
+        try {
+            Allocation outIptr = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 1), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutIptr(outIptr);
+            scriptRelaxed.forEach_testFrexpFloatIntFloat(inV, out);
+            verifyResultsFrexpFloatIntFloat(inV, outIptr, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFrexpFloatIntFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFrexpFloatIntFloat(Allocation inV, Allocation outIptr, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        int[] arrayOutIptr = new int[INPUTSIZE * 1];
+        outIptr.copyTo(arrayOutIptr);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFrexp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.outIptr != arrayOutIptr[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output outIptr: ");
+                    message.append(String.format("%d", args.outIptr));
+                    message.append("\n");
+                    message.append("Actual   output outIptr: ");
+                    message.append(String.format("%d", arrayOutIptr[i * 1 + j]));
+                    if (args.outIptr != arrayOutIptr[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFrexpFloatIntFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFrexpFloat2Int2Float2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x544e0a688fe7701l, false);
+        try {
+            Allocation outIptr = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocOutIptr(outIptr);
+            script.forEach_testFrexpFloat2Int2Float2(inV, out);
+            verifyResultsFrexpFloat2Int2Float2(inV, outIptr, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFrexpFloat2Int2Float2: " + e.toString());
+        }
+        try {
+            Allocation outIptr = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutIptr(outIptr);
+            scriptRelaxed.forEach_testFrexpFloat2Int2Float2(inV, out);
+            verifyResultsFrexpFloat2Int2Float2(inV, outIptr, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFrexpFloat2Int2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFrexpFloat2Int2Float2(Allocation inV, Allocation outIptr, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        int[] arrayOutIptr = new int[INPUTSIZE * 2];
+        outIptr.copyTo(arrayOutIptr);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFrexp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.outIptr != arrayOutIptr[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output outIptr: ");
+                    message.append(String.format("%d", args.outIptr));
+                    message.append("\n");
+                    message.append("Actual   output outIptr: ");
+                    message.append(String.format("%d", arrayOutIptr[i * 2 + j]));
+                    if (args.outIptr != arrayOutIptr[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFrexpFloat2Int2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFrexpFloat3Int3Float3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x2afb1f097eb0e3bal, false);
+        try {
+            Allocation outIptr = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocOutIptr(outIptr);
+            script.forEach_testFrexpFloat3Int3Float3(inV, out);
+            verifyResultsFrexpFloat3Int3Float3(inV, outIptr, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFrexpFloat3Int3Float3: " + e.toString());
+        }
+        try {
+            Allocation outIptr = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutIptr(outIptr);
+            scriptRelaxed.forEach_testFrexpFloat3Int3Float3(inV, out);
+            verifyResultsFrexpFloat3Int3Float3(inV, outIptr, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFrexpFloat3Int3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFrexpFloat3Int3Float3(Allocation inV, Allocation outIptr, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOutIptr = new int[INPUTSIZE * 4];
+        outIptr.copyTo(arrayOutIptr);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFrexp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.outIptr != arrayOutIptr[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output outIptr: ");
+                    message.append(String.format("%d", args.outIptr));
+                    message.append("\n");
+                    message.append("Actual   output outIptr: ");
+                    message.append(String.format("%d", arrayOutIptr[i * 4 + j]));
+                    if (args.outIptr != arrayOutIptr[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFrexpFloat3Int3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkFrexpFloat4Int4Float4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x50b15d6c74635073l, false);
+        try {
+            Allocation outIptr = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocOutIptr(outIptr);
+            script.forEach_testFrexpFloat4Int4Float4(inV, out);
+            verifyResultsFrexpFloat4Int4Float4(inV, outIptr, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFrexpFloat4Int4Float4: " + e.toString());
+        }
+        try {
+            Allocation outIptr = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutIptr(outIptr);
+            scriptRelaxed.forEach_testFrexpFloat4Int4Float4(inV, out);
+            verifyResultsFrexpFloat4Int4Float4(inV, outIptr, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFrexpFloat4Int4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFrexpFloat4Int4Float4(Allocation inV, Allocation outIptr, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayOutIptr = new int[INPUTSIZE * 4];
+        outIptr.copyTo(arrayOutIptr);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeFrexp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.outIptr != arrayOutIptr[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output outIptr: ");
+                    message.append(String.format("%d", args.outIptr));
+                    message.append("\n");
+                    message.append("Actual   output outIptr: ");
+                    message.append(String.format("%d", arrayOutIptr[i * 4 + j]));
+                    if (args.outIptr != arrayOutIptr[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkFrexpFloat4Int4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testFrexp() {
+        checkFrexpFloatIntFloat();
+        checkFrexpFloat2Int2Float2();
+        checkFrexpFloat3Int3Float3();
+        checkFrexpFloat4Int4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFrexp.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestFrexp.rs
new file mode 100644
index 0000000..70c6c13
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFrexp.rs
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocOutIptr;
+
+float __attribute__((kernel)) testFrexpFloatIntFloat(float inV, unsigned int x) {
+    int outIptr = 0;
+    float out = frexp(inV, &outIptr);
+    rsSetElementAt_int(gAllocOutIptr, outIptr, x);
+    return out;
+}
+
+float2 __attribute__((kernel)) testFrexpFloat2Int2Float2(float2 inV, unsigned int x) {
+    int2 outIptr = 0;
+    float2 out = frexp(inV, &outIptr);
+    rsSetElementAt_int2(gAllocOutIptr, outIptr, x);
+    return out;
+}
+
+float3 __attribute__((kernel)) testFrexpFloat3Int3Float3(float3 inV, unsigned int x) {
+    int3 outIptr = 0;
+    float3 out = frexp(inV, &outIptr);
+    rsSetElementAt_int3(gAllocOutIptr, outIptr, x);
+    return out;
+}
+
+float4 __attribute__((kernel)) testFrexpFloat4Int4Float4(float4 inV, unsigned int x) {
+    int4 outIptr = 0;
+    float4 out = frexp(inV, &outIptr);
+    rsSetElementAt_int4(gAllocOutIptr, outIptr, x);
+    return out;
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestFrexpRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestFrexpRelaxed.rs
new file mode 100644
index 0000000..8dc4c4d
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestFrexpRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestFrexp.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestGetSet.java b/tests/tests/renderscript/src/android/renderscript/cts/TestGetSet.java
new file mode 100644
index 0000000..d11de84
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestGetSet.java
@@ -0,0 +1,1084 @@
+ /*
+ * 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 android.renderscript.*;
+
+public class TestGetSet extends RSBaseCompute {
+
+    private ScriptC_getset script;
+    private ScriptC_getset_relaxed scriptRelaxed;
+    Allocation walkAlloc;
+    Allocation in1DAlloc;
+    Allocation out1DAlloc;
+    Allocation in2DAlloc;
+    Allocation out2DAlloc;
+    Allocation in3DAlloc;
+    Allocation out3DAlloc;
+    private static java.util.Random random = new java.util.Random();
+
+    final int gWidth = 252;
+    final int gHeight = 31;
+    final int gDepth = 4;
+    final int gCount = gWidth * gHeight * gDepth;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        random.setSeed(10);
+        script = new ScriptC_getset(mRS);
+        scriptRelaxed = new ScriptC_getset_relaxed(mRS);
+        script.set_gWidth(gWidth);
+        script.set_gHeight(gHeight);
+        scriptRelaxed.set_gWidth(gWidth);
+        scriptRelaxed.set_gHeight(gHeight);
+    }
+
+
+
+    protected void createWalk(int vsize) {
+        // We do a random copy order to attempt to get multiple threads
+        // reading and writing the same cache line
+        // We could do this as a simple walk but that would likely miss
+        // some caching issues.
+        final int tw = gCount / vsize;
+        int tmp[] = new int[tw];
+        boolean b[] = new boolean[tw];
+        int toCopy = tw;
+        int i = 0;
+
+        while (toCopy > 0) {
+            int x = random.nextInt(tw);
+
+            while ((x < tw) && b[x]) {
+                x++;
+                if (x >= tw) {
+                    x = 0;
+                }
+            }
+
+            b[x] = true;
+            toCopy --;
+
+            //android.util.Log.v("rs", "walk  " + i + ", " + x);
+            tmp[i++] = x;
+        }
+
+        walkAlloc = Allocation.createSized(mRS, Element.I32(mRS), tw);
+        walkAlloc.copy1DRangeFrom(0, tw, tmp);
+    }
+
+    private void testSetup(Element e) {
+        int vs = e.getVectorSize();
+        if (vs == 3) {
+            vs = 4;
+        }
+        createWalk(vs);
+
+        Type t1 = Type.createX(mRS, e, gWidth * gHeight * gDepth / vs);
+        in1DAlloc = Allocation.createTyped(mRS, t1);
+        out1DAlloc = Allocation.createTyped(mRS, t1);
+        script.set_gAlloc1DIn(in1DAlloc);
+        script.set_gAlloc1DOut(out1DAlloc);
+        scriptRelaxed.set_gAlloc1DIn(in1DAlloc);
+        scriptRelaxed.set_gAlloc1DOut(out1DAlloc);
+
+        Type t2 = Type.createXY(mRS, e, gWidth / vs, gHeight * gDepth);
+        in2DAlloc = Allocation.createTyped(mRS, t2);
+        out2DAlloc = Allocation.createTyped(mRS, t2);
+        script.set_gAlloc2DIn(in2DAlloc);
+        script.set_gAlloc2DOut(out2DAlloc);
+        scriptRelaxed.set_gAlloc2DIn(in2DAlloc);
+        scriptRelaxed.set_gAlloc2DOut(out2DAlloc);
+
+        Type t3 = Type.createXYZ(mRS, e, gWidth / vs, gHeight, gDepth);
+        in3DAlloc = Allocation.createTyped(mRS, t3);
+        out3DAlloc = Allocation.createTyped(mRS, t3);
+        script.set_gAlloc3DIn(in3DAlloc);
+        script.set_gAlloc3DOut(out3DAlloc);
+        scriptRelaxed.set_gAlloc3DIn(in3DAlloc);
+        scriptRelaxed.set_gAlloc3DOut(out3DAlloc);
+    }
+
+    private void verify(byte[] a1, byte[] a2, Allocation alloc, String s, int vsize) {
+        alloc.copyTo(a2);
+        for (int i=0; i < gWidth; i++) {
+            if (a1[i] != a2[i]) {
+                if ((vsize == 3) && ((i % 4) == 3)) {
+                    continue;
+                }
+                throw new RSRuntimeException(s + a1[i] + ", " + a2[i] + ", at " + i);
+            }
+            a2[i] = 0;
+        }
+        alloc.copyFrom(a2);
+    }
+
+    private void verify(short[] a1, short[] a2, Allocation alloc, String s, int vsize) {
+        alloc.copyTo(a2);
+        for (int i=0; i < gWidth; i++) {
+            if (a1[i] != a2[i]) {
+                if ((vsize == 3) && ((i % 4) == 3)) {
+                    continue;
+                }
+                throw new RSRuntimeException(s + a1[i] + ", " + a2[i] + ", at " + i);
+            }
+            a2[i] = 0;
+        }
+        alloc.copyFrom(a2);
+    }
+
+    private void verify(int[] a1, int[] a2, Allocation alloc, String s, int vsize) {
+        alloc.copyTo(a2);
+        for (int i=0; i < gWidth; i++) {
+            if (a1[i] != a2[i]) {
+                if ((vsize == 3) && ((i % 4) == 3)) {
+                    continue;
+                }
+                throw new RSRuntimeException(s + a1[i] + ", " + a2[i] + ", at " + i);
+            }
+            a2[i] = 0;
+        }
+        alloc.copyFrom(a2);
+    }
+
+    private void verify(long[] a1, long[] a2, Allocation alloc, String s, int vsize) {
+        alloc.copyTo(a2);
+        for (int i=0; i < gWidth; i++) {
+            if (a1[i] != a2[i]) {
+                if ((vsize == 3) && ((i % 4) == 3)) {
+                    continue;
+                }
+                throw new RSRuntimeException(s + a1[i] + ", " + a2[i] + ", at " + i);
+            }
+            a2[i] = 0;
+        }
+        alloc.copyFrom(a2);
+    }
+
+    private void verify(float[] a1, float[] a2, Allocation alloc, String s, int vsize) {
+        alloc.copyTo(a2);
+        for (int i=0; i < gWidth; i++) {
+            if (a1[i] != a2[i]) {
+                if ((vsize == 3) && ((i % 4) == 3)) {
+                    continue;
+                }
+                throw new RSRuntimeException(s + a1[i] + ", " + a2[i] + ", at " + i);
+            }
+            a2[i] = 0;
+        }
+        alloc.copyFrom(a2);
+    }
+
+    private void verify(double[] a1, double[] a2, Allocation alloc, String s, int vsize) {
+        alloc.copyTo(a2);
+        for (int i=0; i < gWidth; i++) {
+            if (a1[i] != a2[i]) {
+                if ((vsize == 3) && ((i % 4) == 3)) {
+                    continue;
+                }
+                throw new RSRuntimeException(s + a1[i] + ", " + a2[i] + ", at " + i);
+            }
+            a2[i] = 0;
+        }
+        alloc.copyFrom(a2);
+    }
+
+    private byte[] randomByteArray(int len) {
+        byte t[] = new byte[len];
+        random.nextBytes(t);
+        in1DAlloc.copyFrom(t);
+        in2DAlloc.copyFrom(t);
+        in3DAlloc.copyFrom(t);
+        return t;
+    }
+
+    private short[] randomShortArray(int len) {
+        short t[] = new short[len];
+        for (int i = 0; i < t.length; i++) {
+            t[i] = (short)(random.nextInt() & 0xffff);
+        }
+        in1DAlloc.copyFrom(t);
+        in2DAlloc.copyFrom(t);
+        in3DAlloc.copyFrom(t);
+        return t;
+    }
+
+    private int[] randomIntArray(int len) {
+        int t[] = new int[len];
+        for (int i = 0; i < t.length; i++) {
+            t[i] = random.nextInt();
+        }
+        in1DAlloc.copyFrom(t);
+        in2DAlloc.copyFrom(t);
+        in3DAlloc.copyFrom(t);
+        return t;
+    }
+
+    private long[] randomLongArray(int len) {
+        long t[] = new long[len];
+        for (int i = 0; i < t.length; i++) {
+            t[i] = random.nextLong();
+        }
+        in1DAlloc.copyFrom(t);
+        in2DAlloc.copyFrom(t);
+        in3DAlloc.copyFrom(t);
+        return t;
+    }
+
+    private float[] randomFloatArray(int len) {
+        float t[] = new float[len];
+        for (int i = 0; i < t.length; i++) {
+            t[i] = random.nextFloat();
+        }
+        in1DAlloc.copyFrom(t);
+        in2DAlloc.copyFrom(t);
+        in3DAlloc.copyFrom(t);
+        return t;
+    }
+
+    private double[] randomDoubleArray(int len) {
+        double t[] = new double[len];
+        for (int i = 0; i < t.length; i++) {
+            t[i] = random.nextDouble();
+        }
+        in1DAlloc.copyFrom(t);
+        in2DAlloc.copyFrom(t);
+        in3DAlloc.copyFrom(t);
+        return t;
+    }
+
+    public void testGetSet_char() {
+        testSetup(Element.I8(mRS));
+        byte tmp[] = randomByteArray(gCount);
+        byte tmp2[] = new byte[gCount];
+
+        script.forEach_copy1D_char(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch char: ", 1);
+        scriptRelaxed.forEach_copy1D_char(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed char: ", 1);
+
+        script.forEach_copy2D_char(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch char: ", 1);
+        scriptRelaxed.forEach_copy2D_char(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed char: ", 1);
+
+        script.forEach_copy3D_char(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch char: ", 1);
+        scriptRelaxed.forEach_copy3D_char(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed char: ", 1);
+    }
+
+    public void testGetSet_char2() {
+        testSetup(Element.I8_2(mRS));
+        byte tmp[] = randomByteArray(gCount);
+        byte tmp2[] = new byte[gCount];
+        script.forEach_copy1D_char2(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch char2: ", 2);
+        scriptRelaxed.forEach_copy1D_char2(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed char2: ", 2);
+
+        script.forEach_copy2D_char2(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch char2: ", 2);
+        scriptRelaxed.forEach_copy2D_char2(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed char2: ", 2);
+
+        script.forEach_copy3D_char2(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch char2: ", 2);
+        scriptRelaxed.forEach_copy3D_char2(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed char2: ", 2);
+    }
+
+    public void testGetSet_char3() {
+        testSetup(Element.I8_3(mRS));
+        byte tmp[] = randomByteArray(gCount);
+        byte tmp2[] = new byte[gCount];
+        script.forEach_copy1D_char3(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch char3: ", 3);
+        scriptRelaxed.forEach_copy1D_char3(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed char3: ", 3);
+
+        script.forEach_copy2D_char3(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch char3: ", 3);
+        scriptRelaxed.forEach_copy2D_char3(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed char3: ", 3);
+
+        script.forEach_copy3D_char3(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch char3: ", 3);
+        scriptRelaxed.forEach_copy3D_char3(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed char3: ", 3);
+    }
+
+    public void testGetSet_char4() {
+        testSetup(Element.I8_4(mRS));
+        byte tmp[] = randomByteArray(gCount);
+        byte tmp2[] = new byte[gCount];
+        script.forEach_copy1D_char4(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch char4: ", 4);
+        scriptRelaxed.forEach_copy1D_char4(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed char4: ", 4);
+
+        script.forEach_copy2D_char4(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch char4: ", 4);
+        scriptRelaxed.forEach_copy2D_char4(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed char4: ", 4);
+
+        script.forEach_copy3D_char4(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch char4: ", 4);
+        scriptRelaxed.forEach_copy3D_char4(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed char4: ", 4);
+    }
+
+    public void testGetSet_uchar() {
+        testSetup(Element.U8(mRS));
+        byte tmp[] = randomByteArray(gCount);
+        byte tmp2[] = new byte[gCount];
+        script.forEach_copy1D_uchar(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch uchar: ", 1);
+        scriptRelaxed.forEach_copy1D_uchar(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed uchar: ", 1);
+
+        script.forEach_copy2D_uchar(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch uchar: ", 1);
+        scriptRelaxed.forEach_copy2D_uchar(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed uchar: ", 1);
+
+        script.forEach_copy3D_uchar(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch uchar: ", 1);
+        scriptRelaxed.forEach_copy3D_uchar(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed uchar: ", 1);
+    }
+
+    public void testGetSet_uchar2() {
+        testSetup(Element.U8_2(mRS));
+        byte tmp[] = randomByteArray(gCount);
+        byte tmp2[] = new byte[gCount];
+        script.forEach_copy1D_uchar2(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch uchar2: ", 2);
+        scriptRelaxed.forEach_copy1D_uchar2(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed uchar2: ", 2);
+
+        script.forEach_copy2D_uchar2(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch uchar2: ", 2);
+        scriptRelaxed.forEach_copy2D_uchar2(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed uchar2: ", 2);
+
+        script.forEach_copy3D_uchar2(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch uchar2: ", 2);
+        scriptRelaxed.forEach_copy3D_uchar2(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed uchar2: ", 2);
+    }
+
+    public void testGetSet_uchar3() {
+        testSetup(Element.U8_3(mRS));
+        byte tmp[] = randomByteArray(gCount);
+        byte tmp2[] = new byte[gCount];
+        script.forEach_copy1D_uchar3(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch uchar3: ", 3);
+        scriptRelaxed.forEach_copy1D_uchar3(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed uchar3: ", 3);
+
+        script.forEach_copy2D_uchar3(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch uchar3: ", 3);
+        scriptRelaxed.forEach_copy2D_uchar3(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed uchar3: ", 3);
+
+        script.forEach_copy3D_uchar3(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch uchar3: ", 3);
+        scriptRelaxed.forEach_copy3D_uchar3(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed uchar3: ", 3);
+    }
+
+    public void testGetSet_uchar4() {
+        testSetup(Element.U8_4(mRS));
+        byte tmp[] = randomByteArray(gCount);
+        byte tmp2[] = new byte[gCount];
+        script.forEach_copy1D_uchar4(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch uchar4: ", 4);
+        scriptRelaxed.forEach_copy1D_uchar4(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed uchar4: ", 4);
+
+        script.forEach_copy2D_uchar4(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch uchar4: ", 4);
+        scriptRelaxed.forEach_copy2D_uchar4(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed uchar4: ", 4);
+
+        script.forEach_copy3D_uchar4(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch uchar4: ", 4);
+        scriptRelaxed.forEach_copy3D_uchar4(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed uchar4: ", 4);
+    }
+
+
+
+
+
+
+    public void testGetSet_short() {
+        testSetup(Element.I16(mRS));
+        short tmp[] = randomShortArray(gCount);
+        short tmp2[] = new short[gCount];
+        script.forEach_copy1D_short(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch short: ", 1);
+        scriptRelaxed.forEach_copy1D_short(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed short: ", 1);
+
+        script.forEach_copy2D_short(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch short: ", 1);
+        scriptRelaxed.forEach_copy2D_short(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed short: ", 1);
+
+        script.forEach_copy3D_short(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch short: ", 1);
+        scriptRelaxed.forEach_copy3D_short(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed short: ", 1);
+    }
+
+    public void testGetSet_short2() {
+        testSetup(Element.I16_2(mRS));
+        short tmp[] = randomShortArray(gCount);
+        short tmp2[] = new short[gCount];
+        script.forEach_copy1D_short2(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch short2: ", 2);
+        scriptRelaxed.forEach_copy1D_short2(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed short2: ", 2);
+
+        script.forEach_copy2D_short2(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch short2: ", 2);
+        scriptRelaxed.forEach_copy2D_short2(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed short2: ", 2);
+
+        script.forEach_copy3D_short2(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch short2: ", 2);
+        scriptRelaxed.forEach_copy3D_short2(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed short2: ", 2);
+    }
+
+    public void testGetSet_short3() {
+        testSetup(Element.I16_3(mRS));
+        short tmp[] = randomShortArray(gCount);
+        short tmp2[] = new short[gCount];
+        script.forEach_copy1D_short3(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch short3: ", 3);
+        scriptRelaxed.forEach_copy1D_short3(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed short3: ", 3);
+
+        script.forEach_copy2D_short3(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch short3: ", 3);
+        scriptRelaxed.forEach_copy2D_short3(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed short3: ", 3);
+
+        script.forEach_copy3D_short3(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch short3: ", 3);
+        scriptRelaxed.forEach_copy3D_short3(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed short3: ", 3);
+    }
+
+    public void testGetSet_short4() {
+        testSetup(Element.I16_4(mRS));
+        short tmp[] = randomShortArray(gCount);
+        short tmp2[] = new short[gCount];
+        script.forEach_copy1D_short4(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch short4: ", 4);
+        scriptRelaxed.forEach_copy1D_short4(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed short4: ", 4);
+
+        script.forEach_copy2D_short4(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch short4: ", 4);
+        scriptRelaxed.forEach_copy2D_short4(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed short4: ", 4);
+
+        script.forEach_copy3D_short4(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch short4: ", 4);
+        scriptRelaxed.forEach_copy3D_short4(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed short4: ", 4);
+    }
+
+    public void testGetSet_ushort() {
+        testSetup(Element.U16(mRS));
+        short tmp[] = randomShortArray(gCount);
+        short tmp2[] = new short[gCount];
+        script.forEach_copy1D_ushort(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch ushort: ", 1);
+        scriptRelaxed.forEach_copy1D_ushort(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed ushort: ", 1);
+
+        script.forEach_copy2D_ushort(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch ushort: ", 1);
+        scriptRelaxed.forEach_copy2D_ushort(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed ushort: ", 1);
+
+        script.forEach_copy3D_ushort(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch ushort: ", 1);
+        scriptRelaxed.forEach_copy3D_ushort(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed ushort: ", 1);
+    }
+
+    public void testGetSet_ushort2() {
+        testSetup(Element.U16_2(mRS));
+        short tmp[] = randomShortArray(gCount);
+        short tmp2[] = new short[gCount];
+        script.forEach_copy1D_ushort2(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch ushort2: ", 2);
+        scriptRelaxed.forEach_copy1D_ushort2(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed ushort2: ", 2);
+
+        script.forEach_copy2D_ushort2(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch ushort2: ", 2);
+        scriptRelaxed.forEach_copy2D_ushort2(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed ushort2: ", 2);
+
+        script.forEach_copy3D_ushort2(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch ushort2: ", 2);
+        scriptRelaxed.forEach_copy3D_ushort2(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed ushort2: ", 2);
+    }
+
+    public void testGetSet_ushort3() {
+        testSetup(Element.U16_3(mRS));
+        short tmp[] = randomShortArray(gCount);
+        short tmp2[] = new short[gCount];
+        script.forEach_copy1D_ushort3(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch ushort3: ", 3);
+        scriptRelaxed.forEach_copy1D_ushort3(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed ushort3: ", 3);
+
+        script.forEach_copy2D_ushort3(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch ushort3: ", 3);
+        scriptRelaxed.forEach_copy2D_ushort3(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed ushort3: ", 3);
+
+        script.forEach_copy3D_ushort3(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch ushort3: ", 3);
+        scriptRelaxed.forEach_copy3D_ushort3(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed ushort3: ", 3);
+    }
+
+    public void testGetSet_ushort4() {
+        testSetup(Element.U16_4(mRS));
+        short tmp[] = randomShortArray(gCount);
+        short tmp2[] = new short[gCount];
+        script.forEach_copy1D_ushort4(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch ushort4: ", 4);
+        scriptRelaxed.forEach_copy1D_ushort4(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed ushort4: ", 4);
+
+        script.forEach_copy2D_ushort4(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch ushort4: ", 4);
+        scriptRelaxed.forEach_copy2D_ushort4(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed ushort4: ", 4);
+
+        script.forEach_copy3D_ushort4(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch ushort4: ", 4);
+        scriptRelaxed.forEach_copy3D_ushort4(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed ushort4: ", 4);
+    }
+
+
+
+
+    public void testGetSet_int() {
+        testSetup(Element.I32(mRS));
+        int tmp[] = randomIntArray(gCount);
+        int tmp2[] = new int[gCount];
+        script.forEach_copy1D_int(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch int: ", 1);
+        scriptRelaxed.forEach_copy1D_int(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed int: ", 1);
+
+        script.forEach_copy2D_int(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch int: ", 1);
+        scriptRelaxed.forEach_copy2D_int(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed int: ", 1);
+
+        script.forEach_copy3D_int(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch int: ", 1);
+        scriptRelaxed.forEach_copy3D_int(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed int: ", 1);
+    }
+
+    public void testGetSet_int2() {
+        testSetup(Element.I32_2(mRS));
+        int tmp[] = randomIntArray(gCount);
+        int tmp2[] = new int[gCount];
+        script.forEach_copy1D_int2(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch int2: ", 2);
+        scriptRelaxed.forEach_copy1D_int2(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed int2: ", 2);
+
+        script.forEach_copy2D_int2(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch int2: ", 2);
+        scriptRelaxed.forEach_copy2D_int2(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed int2: ", 2);
+
+        script.forEach_copy3D_int2(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch int2: ", 2);
+        scriptRelaxed.forEach_copy3D_int2(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed int2: ", 2);
+    }
+
+    public void testGetSet_int3() {
+        testSetup(Element.I32_3(mRS));
+        int tmp[] = randomIntArray(gCount);
+        int tmp2[] = new int[gCount];
+        script.forEach_copy1D_int3(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch int3: ", 3);
+        scriptRelaxed.forEach_copy1D_int3(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed int3: ", 3);
+
+        script.forEach_copy2D_int3(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch int3: ", 3);
+        scriptRelaxed.forEach_copy2D_int3(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed int3: ", 3);
+
+        script.forEach_copy3D_int3(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch int3: ", 3);
+        scriptRelaxed.forEach_copy3D_int3(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed int3: ", 3);
+    }
+
+    public void testGetSet_int4() {
+        testSetup(Element.I32_4(mRS));
+        int tmp[] = randomIntArray(gCount);
+        int tmp2[] = new int[gCount];
+        script.forEach_copy1D_int4(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch int4: ", 4);
+        scriptRelaxed.forEach_copy1D_int4(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed int4: ", 4);
+
+        script.forEach_copy2D_int4(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch int4: ", 4);
+        scriptRelaxed.forEach_copy2D_int4(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed int4: ", 4);
+
+        script.forEach_copy3D_int4(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch int4: ", 4);
+        scriptRelaxed.forEach_copy3D_int4(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed int4: ", 4);
+    }
+
+    public void testGetSet_uint() {
+        testSetup(Element.U32(mRS));
+        int tmp[] = randomIntArray(gCount);
+        int tmp2[] = new int[gCount];
+        script.forEach_copy1D_uint(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch uint: ", 1);
+        scriptRelaxed.forEach_copy1D_uint(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed uint: ", 1);
+
+        script.forEach_copy2D_uint(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch uint: ", 1);
+        scriptRelaxed.forEach_copy2D_uint(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed uint: ", 1);
+
+        script.forEach_copy3D_uint(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch uint: ", 1);
+        scriptRelaxed.forEach_copy3D_uint(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed uint: ", 1);
+    }
+
+    public void testGetSet_uint2() {
+        testSetup(Element.U32_2(mRS));
+        int tmp[] = randomIntArray(gCount);
+        int tmp2[] = new int[gCount];
+        script.forEach_copy1D_uint2(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch uint2: ", 2);
+        scriptRelaxed.forEach_copy1D_uint2(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed uint2: ", 2);
+
+        script.forEach_copy2D_uint2(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch uint2: ", 2);
+        scriptRelaxed.forEach_copy2D_uint2(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed uint2: ", 2);
+
+        script.forEach_copy3D_uint2(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch uint2: ", 2);
+        scriptRelaxed.forEach_copy3D_uint2(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed uint2: ", 2);
+    }
+
+    public void testGetSet_uint3() {
+        testSetup(Element.U32_3(mRS));
+        int tmp[] = randomIntArray(gCount);
+        int tmp2[] = new int[gCount];
+        script.forEach_copy1D_uint3(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch uint3: ", 3);
+        scriptRelaxed.forEach_copy1D_uint3(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed uint3: ", 3);
+
+        script.forEach_copy2D_uint3(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch uint3: ", 3);
+        scriptRelaxed.forEach_copy2D_uint3(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed uint3: ", 3);
+
+        script.forEach_copy3D_uint3(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch uint3: ", 3);
+        scriptRelaxed.forEach_copy3D_uint3(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed uint3: ", 3);
+    }
+
+    public void testGetSet_uint4() {
+        testSetup(Element.U32_4(mRS));
+        int tmp[] = randomIntArray(gCount);
+        int tmp2[] = new int[gCount];
+        script.forEach_copy1D_uint4(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch uint4: ", 4);
+        scriptRelaxed.forEach_copy1D_uint4(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed uint4: ", 4);
+
+        script.forEach_copy2D_uint4(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch uint4: ", 4);
+        scriptRelaxed.forEach_copy2D_uint4(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed uint4: ", 4);
+
+        script.forEach_copy3D_uint4(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch uint4: ", 4);
+        scriptRelaxed.forEach_copy3D_uint4(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed uint4: ", 4);
+    }
+
+
+
+
+    public void testGetSet_long() {
+        testSetup(Element.I64(mRS));
+        long tmp[] = randomLongArray(gCount);
+        long tmp2[] = new long[gCount];
+        script.forEach_copy1D_long(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch long: ", 1);
+        scriptRelaxed.forEach_copy1D_long(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed long: ", 1);
+
+        script.forEach_copy2D_long(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch long: ", 1);
+        scriptRelaxed.forEach_copy2D_long(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed long: ", 1);
+
+        script.forEach_copy3D_long(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch long: ", 1);
+        scriptRelaxed.forEach_copy3D_long(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed long: ", 1);
+    }
+
+    public void testGetSet_long2() {
+        testSetup(Element.I64_2(mRS));
+        long tmp[] = randomLongArray(gCount);
+        long tmp2[] = new long[gCount];
+        script.forEach_copy1D_long2(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch long2: ", 2);
+        scriptRelaxed.forEach_copy1D_long2(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed long2: ", 2);
+
+        script.forEach_copy2D_long2(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch long2: ", 2);
+        scriptRelaxed.forEach_copy2D_long2(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed long2: ", 2);
+
+        script.forEach_copy3D_long2(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch long2: ", 2);
+        scriptRelaxed.forEach_copy3D_long2(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed long2: ", 2);
+    }
+
+    public void testGetSet_long3() {
+        testSetup(Element.I64_3(mRS));
+        long tmp[] = randomLongArray(gCount);
+        long tmp2[] = new long[gCount];
+        script.forEach_copy1D_long3(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch long3: ", 3);
+        scriptRelaxed.forEach_copy1D_long3(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed long3: ", 3);
+
+        script.forEach_copy2D_long3(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch long3: ", 3);
+        scriptRelaxed.forEach_copy2D_long3(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed long3: ", 3);
+
+        script.forEach_copy3D_long3(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch long3: ", 3);
+        scriptRelaxed.forEach_copy3D_long3(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed long3: ", 3);
+    }
+
+    public void testGetSet_long4() {
+        testSetup(Element.I64_4(mRS));
+        long tmp[] = randomLongArray(gCount);
+        long tmp2[] = new long[gCount];
+        script.forEach_copy1D_long4(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch long4: ", 4);
+        scriptRelaxed.forEach_copy1D_long4(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed long4: ", 4);
+
+        script.forEach_copy2D_long4(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch long4: ", 4);
+        scriptRelaxed.forEach_copy2D_long4(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed long4: ", 4);
+
+        script.forEach_copy3D_long4(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch long4: ", 4);
+        scriptRelaxed.forEach_copy3D_long4(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed long4: ", 4);
+    }
+
+    public void testGetSet_ulong() {
+        testSetup(Element.U64(mRS));
+        long tmp[] = randomLongArray(gCount);
+        long tmp2[] = new long[gCount];
+        script.forEach_copy1D_ulong(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch ulong: ", 1);
+        scriptRelaxed.forEach_copy1D_ulong(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed ulong: ", 1);
+
+        script.forEach_copy2D_ulong(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch ulong: ", 1);
+        scriptRelaxed.forEach_copy2D_ulong(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed ulong: ", 1);
+
+        script.forEach_copy3D_ulong(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch ulong: ", 1);
+        scriptRelaxed.forEach_copy3D_ulong(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed ulong: ", 1);
+    }
+
+    public void testGetSet_ulong2() {
+        testSetup(Element.U64_2(mRS));
+        long tmp[] = randomLongArray(gCount);
+        long tmp2[] = new long[gCount];
+        script.forEach_copy1D_ulong2(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch ulong2: ", 2);
+        scriptRelaxed.forEach_copy1D_ulong2(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed ulong2: ", 2);
+
+        script.forEach_copy2D_ulong2(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch ulong2: ", 2);
+        scriptRelaxed.forEach_copy2D_ulong2(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed ulong2: ", 2);
+
+        script.forEach_copy3D_ulong2(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch ulong2: ", 2);
+        scriptRelaxed.forEach_copy3D_ulong2(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed ulong2: ", 2);
+    }
+
+    public void testGetSet_ulong3() {
+        testSetup(Element.U64_3(mRS));
+        long tmp[] = randomLongArray(gCount);
+        long tmp2[] = new long[gCount];
+        script.forEach_copy1D_ulong3(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch ulong3: ", 3);
+        scriptRelaxed.forEach_copy1D_ulong3(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed ulong3: ", 3);
+
+        script.forEach_copy2D_ulong3(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch ulong3: ", 3);
+        scriptRelaxed.forEach_copy2D_ulong3(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed ulong3: ", 3);
+
+        script.forEach_copy3D_ulong3(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch ulong3: ", 3);
+        scriptRelaxed.forEach_copy3D_ulong3(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed ulong3: ", 3);
+    }
+
+    public void testGetSet_ulong4() {
+        testSetup(Element.U64_4(mRS));
+        long tmp[] = randomLongArray(gCount);
+        long tmp2[] = new long[gCount];
+        script.forEach_copy1D_ulong4(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch ulong4: ", 4);
+        scriptRelaxed.forEach_copy1D_ulong4(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed ulong4: ", 4);
+
+        script.forEach_copy2D_ulong4(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch ulong4: ", 4);
+        scriptRelaxed.forEach_copy2D_ulong4(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed ulong4: ", 4);
+
+        script.forEach_copy3D_ulong4(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch ulong4: ", 4);
+        scriptRelaxed.forEach_copy3D_ulong4(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed ulong4: ", 4);
+    }
+
+
+
+
+    public void testGetSet_float() {
+        testSetup(Element.F32(mRS));
+        float tmp[] = randomFloatArray(gCount);
+        float tmp2[] = new float[gCount];
+        script.forEach_copy1D_float(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch float: ", 1);
+        scriptRelaxed.forEach_copy1D_float(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed float: ", 1);
+
+        script.forEach_copy2D_float(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch float: ", 1);
+        scriptRelaxed.forEach_copy2D_float(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed float: ", 1);
+
+        script.forEach_copy3D_float(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch float: ", 1);
+        scriptRelaxed.forEach_copy3D_float(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed float: ", 1);
+    }
+
+    public void testGetSet_float2() {
+        testSetup(Element.F32_2(mRS));
+        float tmp[] = randomFloatArray(gCount);
+        float tmp2[] = new float[gCount];
+        script.forEach_copy1D_float2(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch float2: ", 2);
+        scriptRelaxed.forEach_copy1D_float2(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed float2: ", 2);
+
+        script.forEach_copy2D_float2(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch float2: ", 2);
+        scriptRelaxed.forEach_copy2D_float2(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed float2: ", 2);
+
+        script.forEach_copy3D_float2(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch float2: ", 2);
+        scriptRelaxed.forEach_copy3D_float2(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed float2: ", 2);
+    }
+
+    public void testGetSet_float3() {
+        testSetup(Element.F32_3(mRS));
+        float tmp[] = randomFloatArray(gCount);
+        float tmp2[] = new float[gCount];
+        script.forEach_copy1D_float3(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch float3: ", 3);
+        scriptRelaxed.forEach_copy1D_float3(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed float3: ", 3);
+
+        script.forEach_copy2D_float3(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch float3: ", 3);
+        scriptRelaxed.forEach_copy2D_float3(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed float3: ", 3);
+
+        script.forEach_copy3D_float3(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch float3: ", 3);
+        scriptRelaxed.forEach_copy3D_float3(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed float3: ", 3);
+    }
+
+    public void testGetSet_float4() {
+        testSetup(Element.F32_4(mRS));
+        float tmp[] = randomFloatArray(gCount);
+        float tmp2[] = new float[gCount];
+        script.forEach_copy1D_float4(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch float4: ", 4);
+        scriptRelaxed.forEach_copy1D_float4(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed float4: ", 4);
+
+        script.forEach_copy2D_float4(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch float4: ", 4);
+        scriptRelaxed.forEach_copy2D_float4(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed float4: ", 4);
+
+        script.forEach_copy3D_float4(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch float4: ", 4);
+        scriptRelaxed.forEach_copy3D_float4(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed float4: ", 4);
+    }
+
+
+    public void testGetSet_double() {
+        testSetup(Element.F64(mRS));
+        double tmp[] = randomDoubleArray(gCount);
+        double tmp2[] = new double[gCount];
+        script.forEach_copy1D_double(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch double: ", 1);
+        scriptRelaxed.forEach_copy1D_double(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed double: ", 1);
+
+        script.forEach_copy2D_double(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch double: ", 1);
+        scriptRelaxed.forEach_copy2D_double(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed double: ", 1);
+
+        script.forEach_copy3D_double(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch double: ", 1);
+        scriptRelaxed.forEach_copy3D_double(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed double: ", 1);
+    }
+
+    public void testGetSet_double2() {
+        testSetup(Element.F64_2(mRS));
+        double tmp[] = randomDoubleArray(gCount);
+        double tmp2[] = new double[gCount];
+        script.forEach_copy1D_double2(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch double2: ", 2);
+        scriptRelaxed.forEach_copy1D_double2(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed double2: ", 2);
+
+        script.forEach_copy2D_double2(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch double2: ", 2);
+        scriptRelaxed.forEach_copy2D_double2(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed double2: ", 2);
+
+        script.forEach_copy3D_double2(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch double2: ", 2);
+        scriptRelaxed.forEach_copy3D_double2(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed double2: ", 2);
+    }
+
+    public void testGetSet_double3() {
+        testSetup(Element.F64_3(mRS));
+        double tmp[] = randomDoubleArray(gCount);
+        double tmp2[] = new double[gCount];
+        script.forEach_copy1D_double3(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch double3: ", 3);
+        scriptRelaxed.forEach_copy1D_double3(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed double3: ", 3);
+
+        script.forEach_copy2D_double3(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch double3: ", 3);
+        scriptRelaxed.forEach_copy2D_double3(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed double3: ", 3);
+
+        script.forEach_copy3D_double3(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch double3: ", 3);
+        scriptRelaxed.forEach_copy3D_double3(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed double3: ", 3);
+    }
+
+    public void testGetSet_double4() {
+        testSetup(Element.F64_4(mRS));
+        double tmp[] = randomDoubleArray(gCount);
+        double tmp2[] = new double[gCount];
+        script.forEach_copy1D_double4(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch double4: ", 4);
+        scriptRelaxed.forEach_copy1D_double4(walkAlloc);
+        verify(tmp, tmp2, out1DAlloc, "Data mismatch relaxed double4: ", 4);
+
+        script.forEach_copy2D_double4(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch double4: ", 4);
+        scriptRelaxed.forEach_copy2D_double4(walkAlloc);
+        verify(tmp, tmp2, out2DAlloc, "Data mismatch relaxed double4: ", 4);
+
+        script.forEach_copy3D_double4(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch double4: ", 4);
+        scriptRelaxed.forEach_copy3D_double4(walkAlloc);
+        verify(tmp, tmp2, out3DAlloc, "Data mismatch relaxed double4: ", 4);
+    }
+
+
+}
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestHalfRecip.java b/tests/tests/renderscript/src/android/renderscript/cts/TestHalfRecip.java
new file mode 100644
index 0000000..8d4f1b7
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestHalfRecip.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestHalfRecip extends RSBaseCompute {
+
+    private ScriptC_TestHalfRecip script;
+    private ScriptC_TestHalfRecipRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestHalfRecip(mRS);
+        scriptRelaxed = new ScriptC_TestHalfRecipRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkHalfRecipFloatFloat() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x854e263130d5b3dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testHalfRecipFloatFloat(inV, out);
+            verifyResultsHalfRecipFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfRecipFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testHalfRecipFloatFloat(inV, out);
+            verifyResultsHalfRecipFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfRecipFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsHalfRecipFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeHalfRecip(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkHalfRecipFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkHalfRecipFloat2Float2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x2cf1d2db5ff23c79l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testHalfRecipFloat2Float2(inV, out);
+            verifyResultsHalfRecipFloat2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfRecipFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testHalfRecipFloat2Float2(inV, out);
+            verifyResultsHalfRecipFloat2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfRecipFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsHalfRecipFloat2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeHalfRecip(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkHalfRecipFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkHalfRecipFloat3Float3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x2cf39bf6560d5d57l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testHalfRecipFloat3Float3(inV, out);
+            verifyResultsHalfRecipFloat3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfRecipFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testHalfRecipFloat3Float3(inV, out);
+            verifyResultsHalfRecipFloat3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfRecipFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsHalfRecipFloat3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeHalfRecip(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkHalfRecipFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkHalfRecipFloat4Float4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x2cf565114c287e35l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testHalfRecipFloat4Float4(inV, out);
+            verifyResultsHalfRecipFloat4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfRecipFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testHalfRecipFloat4Float4(inV, out);
+            verifyResultsHalfRecipFloat4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfRecipFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsHalfRecipFloat4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeHalfRecip(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkHalfRecipFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testHalfRecip() {
+        checkHalfRecipFloatFloat();
+        checkHalfRecipFloat2Float2();
+        checkHalfRecipFloat3Float3();
+        checkHalfRecipFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestHalfRecip.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestHalfRecip.rs
new file mode 100644
index 0000000..03c5802
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestHalfRecip.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testHalfRecipFloatFloat(float inV) {
+    return half_recip(inV);
+}
+
+float2 __attribute__((kernel)) testHalfRecipFloat2Float2(float2 inV) {
+    return half_recip(inV);
+}
+
+float3 __attribute__((kernel)) testHalfRecipFloat3Float3(float3 inV) {
+    return half_recip(inV);
+}
+
+float4 __attribute__((kernel)) testHalfRecipFloat4Float4(float4 inV) {
+    return half_recip(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestHalfRecipRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestHalfRecipRelaxed.rs
new file mode 100644
index 0000000..da453fa
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestHalfRecipRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestHalfRecip.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestHalfRsqrt.java b/tests/tests/renderscript/src/android/renderscript/cts/TestHalfRsqrt.java
new file mode 100644
index 0000000..5cd4e90
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestHalfRsqrt.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestHalfRsqrt extends RSBaseCompute {
+
+    private ScriptC_TestHalfRsqrt script;
+    private ScriptC_TestHalfRsqrtRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestHalfRsqrt(mRS);
+        scriptRelaxed = new ScriptC_TestHalfRsqrtRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkHalfRsqrtFloatFloat() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xad5e977ec00f0bf2l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testHalfRsqrtFloatFloat(inV, out);
+            verifyResultsHalfRsqrtFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfRsqrtFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testHalfRsqrtFloatFloat(inV, out);
+            verifyResultsHalfRsqrtFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfRsqrtFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsHalfRsqrtFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeHalfRsqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkHalfRsqrtFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkHalfRsqrtFloat2Float2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x300ee7bff12787c6l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testHalfRsqrtFloat2Float2(inV, out);
+            verifyResultsHalfRsqrtFloat2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfRsqrtFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testHalfRsqrtFloat2Float2(inV, out);
+            verifyResultsHalfRsqrtFloat2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfRsqrtFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsHalfRsqrtFloat2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeHalfRsqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkHalfRsqrtFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkHalfRsqrtFloat3Float3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x3010b0dae742a8a4l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testHalfRsqrtFloat3Float3(inV, out);
+            verifyResultsHalfRsqrtFloat3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfRsqrtFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testHalfRsqrtFloat3Float3(inV, out);
+            verifyResultsHalfRsqrtFloat3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfRsqrtFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsHalfRsqrtFloat3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeHalfRsqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkHalfRsqrtFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkHalfRsqrtFloat4Float4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x301279f5dd5dc982l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testHalfRsqrtFloat4Float4(inV, out);
+            verifyResultsHalfRsqrtFloat4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfRsqrtFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testHalfRsqrtFloat4Float4(inV, out);
+            verifyResultsHalfRsqrtFloat4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfRsqrtFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsHalfRsqrtFloat4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeHalfRsqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkHalfRsqrtFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testHalfRsqrt() {
+        checkHalfRsqrtFloatFloat();
+        checkHalfRsqrtFloat2Float2();
+        checkHalfRsqrtFloat3Float3();
+        checkHalfRsqrtFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestHalfRsqrt.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestHalfRsqrt.rs
new file mode 100644
index 0000000..27840d1
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestHalfRsqrt.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testHalfRsqrtFloatFloat(float inV) {
+    return half_rsqrt(inV);
+}
+
+float2 __attribute__((kernel)) testHalfRsqrtFloat2Float2(float2 inV) {
+    return half_rsqrt(inV);
+}
+
+float3 __attribute__((kernel)) testHalfRsqrtFloat3Float3(float3 inV) {
+    return half_rsqrt(inV);
+}
+
+float4 __attribute__((kernel)) testHalfRsqrtFloat4Float4(float4 inV) {
+    return half_rsqrt(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestHalfRsqrtRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestHalfRsqrtRelaxed.rs
new file mode 100644
index 0000000..4f94200
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestHalfRsqrtRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestHalfRsqrt.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestHalfSqrt.java b/tests/tests/renderscript/src/android/renderscript/cts/TestHalfSqrt.java
new file mode 100644
index 0000000..b57291d
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestHalfSqrt.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestHalfSqrt extends RSBaseCompute {
+
+    private ScriptC_TestHalfSqrt script;
+    private ScriptC_TestHalfSqrtRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestHalfSqrt(mRS);
+        scriptRelaxed = new ScriptC_TestHalfSqrtRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkHalfSqrtFloatFloat() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x8be766c7a15db5fal, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testHalfSqrtFloatFloat(inV, out);
+            verifyResultsHalfSqrtFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfSqrtFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testHalfSqrtFloatFloat(inV, out);
+            verifyResultsHalfSqrtFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfSqrtFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsHalfSqrtFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeHalfSqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkHalfSqrtFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkHalfSqrtFloat2Float2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x7a300d2342519b8el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testHalfSqrtFloat2Float2(inV, out);
+            verifyResultsHalfSqrtFloat2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfSqrtFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testHalfSqrtFloat2Float2(inV, out);
+            verifyResultsHalfSqrtFloat2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfSqrtFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsHalfSqrtFloat2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeHalfSqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkHalfSqrtFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkHalfSqrtFloat3Float3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x7a31d63e386cbc6cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testHalfSqrtFloat3Float3(inV, out);
+            verifyResultsHalfSqrtFloat3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfSqrtFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testHalfSqrtFloat3Float3(inV, out);
+            verifyResultsHalfSqrtFloat3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfSqrtFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsHalfSqrtFloat3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeHalfSqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkHalfSqrtFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkHalfSqrtFloat4Float4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x7a339f592e87dd4al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testHalfSqrtFloat4Float4(inV, out);
+            verifyResultsHalfSqrtFloat4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfSqrtFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testHalfSqrtFloat4Float4(inV, out);
+            verifyResultsHalfSqrtFloat4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHalfSqrtFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsHalfSqrtFloat4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeHalfSqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkHalfSqrtFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testHalfSqrt() {
+        checkHalfSqrtFloatFloat();
+        checkHalfSqrtFloat2Float2();
+        checkHalfSqrtFloat3Float3();
+        checkHalfSqrtFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestHalfSqrt.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestHalfSqrt.rs
new file mode 100644
index 0000000..d785e44
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestHalfSqrt.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testHalfSqrtFloatFloat(float inV) {
+    return half_sqrt(inV);
+}
+
+float2 __attribute__((kernel)) testHalfSqrtFloat2Float2(float2 inV) {
+    return half_sqrt(inV);
+}
+
+float3 __attribute__((kernel)) testHalfSqrtFloat3Float3(float3 inV) {
+    return half_sqrt(inV);
+}
+
+float4 __attribute__((kernel)) testHalfSqrtFloat4Float4(float4 inV) {
+    return half_sqrt(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestHalfSqrtRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestHalfSqrtRelaxed.rs
new file mode 100644
index 0000000..46b979d
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestHalfSqrtRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestHalfSqrt.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestHypot.java b/tests/tests/renderscript/src/android/renderscript/cts/TestHypot.java
new file mode 100644
index 0000000..8aecdcd
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestHypot.java
@@ -0,0 +1,325 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestHypot extends RSBaseCompute {
+
+    private ScriptC_TestHypot script;
+    private ScriptC_TestHypotRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestHypot(mRS);
+        scriptRelaxed = new ScriptC_TestHypotRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float inX;
+        public float inY;
+        public Target.Floaty out;
+    }
+
+    private void checkHypotFloatFloatFloat() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x7deb65e7738c74dbl, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x7deb65e7738c74dcl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testHypotFloatFloatFloat(inX, out);
+            verifyResultsHypotFloatFloatFloat(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHypotFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testHypotFloatFloatFloat(inX, out);
+            verifyResultsHypotFloatFloatFloat(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHypotFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsHypotFloatFloatFloat(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 1];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 1];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i];
+                args.inY = arrayInY[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeHypot(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkHypotFloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkHypotFloat2Float2Float2() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x14f3c91a62f71c5dl, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x14f3c91a62f71c5el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testHypotFloat2Float2Float2(inX, out);
+            verifyResultsHypotFloat2Float2Float2(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHypotFloat2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testHypotFloat2Float2Float2(inX, out);
+            verifyResultsHypotFloat2Float2Float2(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHypotFloat2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsHypotFloat2Float2Float2(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 2];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 2];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 2 + j];
+                args.inY = arrayInY[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeHypot(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkHypotFloat2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkHypotFloat3Float3Float3() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x6958a73a64d51dfel, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x6958a73a64d51dffl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testHypotFloat3Float3Float3(inX, out);
+            verifyResultsHypotFloat3Float3Float3(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHypotFloat3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testHypotFloat3Float3Float3(inX, out);
+            verifyResultsHypotFloat3Float3Float3(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHypotFloat3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsHypotFloat3Float3Float3(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeHypot(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkHypotFloat3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkHypotFloat4Float4Float4() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xbdbd855a66b31f9fl, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xbdbd855a66b31fa0l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testHypotFloat4Float4Float4(inX, out);
+            verifyResultsHypotFloat4Float4Float4(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHypotFloat4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testHypotFloat4Float4Float4(inX, out);
+            verifyResultsHypotFloat4Float4Float4(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHypotFloat4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsHypotFloat4Float4Float4(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeHypot(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkHypotFloat4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testHypot() {
+        checkHypotFloatFloatFloat();
+        checkHypotFloat2Float2Float2();
+        checkHypotFloat3Float3Float3();
+        checkHypotFloat4Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestHypot.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestHypot.rs
new file mode 100644
index 0000000..9425121
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestHypot.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInY;
+
+float __attribute__((kernel)) testHypotFloatFloatFloat(float inX, unsigned int x) {
+    float inY = rsGetElementAt_float(gAllocInY, x);
+    return hypot(inX, inY);
+}
+
+float2 __attribute__((kernel)) testHypotFloat2Float2Float2(float2 inX, unsigned int x) {
+    float2 inY = rsGetElementAt_float2(gAllocInY, x);
+    return hypot(inX, inY);
+}
+
+float3 __attribute__((kernel)) testHypotFloat3Float3Float3(float3 inX, unsigned int x) {
+    float3 inY = rsGetElementAt_float3(gAllocInY, x);
+    return hypot(inX, inY);
+}
+
+float4 __attribute__((kernel)) testHypotFloat4Float4Float4(float4 inX, unsigned int x) {
+    float4 inY = rsGetElementAt_float4(gAllocInY, x);
+    return hypot(inX, inY);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestHypotRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestHypotRelaxed.rs
new file mode 100644
index 0000000..15d02f3
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestHypotRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestHypot.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestIlogb.java b/tests/tests/renderscript/src/android/renderscript/cts/TestIlogb.java
new file mode 100644
index 0000000..9bac16f
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestIlogb.java
@@ -0,0 +1,248 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestIlogb extends RSBaseCompute {
+
+    private ScriptC_TestIlogb script;
+    private ScriptC_TestIlogbRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestIlogb(mRS);
+        scriptRelaxed = new ScriptC_TestIlogbRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatInt {
+        public float in;
+        public int out;
+    }
+
+    private void checkIlogbFloatInt() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xc0c48da27f084aefl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 1), INPUTSIZE);
+            script.forEach_testIlogbFloatInt(in, out);
+            verifyResultsIlogbFloatInt(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testIlogbFloatInt: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testIlogbFloatInt(in, out);
+            verifyResultsIlogbFloatInt(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testIlogbFloatInt: " + e.toString());
+        }
+    }
+
+    private void verifyResultsIlogbFloatInt(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        int[] arrayOut = new int[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatInt args = new ArgumentsFloatInt();
+                args.in = arrayIn[i];
+                // Extract the outputs.
+                args.out = arrayOut[i * 1 + j];
+                // Ask the CoreMathVerifier to validate.
+                String errorMessage = CoreMathVerifier.verifyIlogb(args);
+                boolean valid = errorMessage == null;
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append(errorMessage);
+                    assertTrue("Incorrect output for checkIlogbFloatInt" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkIlogbFloat2Int2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x4ba2fa846382ada1l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            script.forEach_testIlogbFloat2Int2(in, out);
+            verifyResultsIlogbFloat2Int2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testIlogbFloat2Int2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testIlogbFloat2Int2(in, out);
+            verifyResultsIlogbFloat2Int2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testIlogbFloat2Int2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsIlogbFloat2Int2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatInt args = new ArgumentsFloatInt();
+                args.in = arrayIn[i * 2 + j];
+                // Extract the outputs.
+                args.out = arrayOut[i * 2 + j];
+                // Ask the CoreMathVerifier to validate.
+                String errorMessage = CoreMathVerifier.verifyIlogb(args);
+                boolean valid = errorMessage == null;
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append(errorMessage);
+                    assertTrue("Incorrect output for checkIlogbFloat2Int2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkIlogbFloat3Int3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x4ba2fa85dc4b0d43l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            script.forEach_testIlogbFloat3Int3(in, out);
+            verifyResultsIlogbFloat3Int3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testIlogbFloat3Int3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testIlogbFloat3Int3(in, out);
+            verifyResultsIlogbFloat3Int3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testIlogbFloat3Int3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsIlogbFloat3Int3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatInt args = new ArgumentsFloatInt();
+                args.in = arrayIn[i * 4 + j];
+                // Extract the outputs.
+                args.out = arrayOut[i * 4 + j];
+                // Ask the CoreMathVerifier to validate.
+                String errorMessage = CoreMathVerifier.verifyIlogb(args);
+                boolean valid = errorMessage == null;
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append(errorMessage);
+                    assertTrue("Incorrect output for checkIlogbFloat3Int3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkIlogbFloat4Int4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x4ba2fa8755136ce5l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            script.forEach_testIlogbFloat4Int4(in, out);
+            verifyResultsIlogbFloat4Int4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testIlogbFloat4Int4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testIlogbFloat4Int4(in, out);
+            verifyResultsIlogbFloat4Int4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testIlogbFloat4Int4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsIlogbFloat4Int4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatInt args = new ArgumentsFloatInt();
+                args.in = arrayIn[i * 4 + j];
+                // Extract the outputs.
+                args.out = arrayOut[i * 4 + j];
+                // Ask the CoreMathVerifier to validate.
+                String errorMessage = CoreMathVerifier.verifyIlogb(args);
+                boolean valid = errorMessage == null;
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append(errorMessage);
+                    assertTrue("Incorrect output for checkIlogbFloat4Int4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testIlogb() {
+        checkIlogbFloatInt();
+        checkIlogbFloat2Int2();
+        checkIlogbFloat3Int3();
+        checkIlogbFloat4Int4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestIlogb.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestIlogb.rs
new file mode 100644
index 0000000..d9d62ed
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestIlogb.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+int __attribute__((kernel)) testIlogbFloatInt(float in) {
+    return ilogb(in);
+}
+
+int2 __attribute__((kernel)) testIlogbFloat2Int2(float2 in) {
+    return ilogb(in);
+}
+
+int3 __attribute__((kernel)) testIlogbFloat3Int3(float3 in) {
+    return ilogb(in);
+}
+
+int4 __attribute__((kernel)) testIlogbFloat4Int4(float4 in) {
+    return ilogb(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestIlogbRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestIlogbRelaxed.rs
new file mode 100644
index 0000000..6a60e53c
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestIlogbRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestIlogb.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestLdexp.java b/tests/tests/renderscript/src/android/renderscript/cts/TestLdexp.java
new file mode 100644
index 0000000..3f3aee9
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestLdexp.java
@@ -0,0 +1,528 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestLdexp extends RSBaseCompute {
+
+    private ScriptC_TestLdexp script;
+    private ScriptC_TestLdexpRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestLdexp(mRS);
+        scriptRelaxed = new ScriptC_TestLdexpRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatIntFloat {
+        public float inX;
+        public int inY;
+        public Target.Floaty out;
+    }
+
+    private void checkLdexpFloatIntFloat() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xdeada0999238fe8bl, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 1, 0xdeada0999238fe8cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testLdexpFloatIntFloat(inX, out);
+            verifyResultsLdexpFloatIntFloat(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLdexpFloatIntFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testLdexpFloatIntFloat(inX, out);
+            verifyResultsLdexpFloatIntFloat(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLdexpFloatIntFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLdexpFloatIntFloat(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 1];
+        inX.copyTo(arrayInX);
+        int[] arrayInY = new int[INPUTSIZE * 1];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inX = arrayInX[i];
+                args.inY = arrayInY[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLdexp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%d", args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLdexpFloatIntFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLdexpFloat2Int2Float2() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x5492762140d0ca17l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 2, 0x5492762140d0ca18l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testLdexpFloat2Int2Float2(inX, out);
+            verifyResultsLdexpFloat2Int2Float2(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLdexpFloat2Int2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testLdexpFloat2Int2Float2(inX, out);
+            verifyResultsLdexpFloat2Int2Float2(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLdexpFloat2Int2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLdexpFloat2Int2Float2(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 2];
+        inX.copyTo(arrayInX);
+        int[] arrayInY = new int[INPUTSIZE * 2];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inX = arrayInX[i * 2 + j];
+                args.inY = arrayInY[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLdexp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%d", args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLdexpFloat2Int2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLdexpFloat3Int3Float3() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x7a48b484368336d0l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 3, 0x7a48b484368336d1l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testLdexpFloat3Int3Float3(inX, out);
+            verifyResultsLdexpFloat3Int3Float3(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLdexpFloat3Int3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testLdexpFloat3Int3Float3(inX, out);
+            verifyResultsLdexpFloat3Int3Float3(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLdexpFloat3Int3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLdexpFloat3Int3Float3(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        int[] arrayInY = new int[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLdexp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%d", args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLdexpFloat3Int3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLdexpFloat4Int4Float4() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x9ffef2e72c35a389l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 4, 0x9ffef2e72c35a38al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testLdexpFloat4Int4Float4(inX, out);
+            verifyResultsLdexpFloat4Int4Float4(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLdexpFloat4Int4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testLdexpFloat4Int4Float4(inX, out);
+            verifyResultsLdexpFloat4Int4Float4(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLdexpFloat4Int4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLdexpFloat4Int4Float4(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        int[] arrayInY = new int[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLdexp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%d", args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLdexpFloat4Int4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLdexpFloat2IntFloat2() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xa2b6e0c39777b8c1l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 1, 0xa2b6e0c39777b8c2l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testLdexpFloat2IntFloat2(inX, out);
+            verifyResultsLdexpFloat2IntFloat2(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLdexpFloat2IntFloat2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testLdexpFloat2IntFloat2(inX, out);
+            verifyResultsLdexpFloat2IntFloat2(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLdexpFloat2IntFloat2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLdexpFloat2IntFloat2(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 2];
+        inX.copyTo(arrayInX);
+        int[] arrayInY = new int[INPUTSIZE * 1];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inX = arrayInX[i * 2 + j];
+                args.inY = arrayInY[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLdexp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%d", args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLdexpFloat2IntFloat2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLdexpFloat3IntFloat3() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xcd4401424a114a65l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 1, 0xcd4401424a114a66l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testLdexpFloat3IntFloat3(inX, out);
+            verifyResultsLdexpFloat3IntFloat3(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLdexpFloat3IntFloat3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testLdexpFloat3IntFloat3(inX, out);
+            verifyResultsLdexpFloat3IntFloat3(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLdexpFloat3IntFloat3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLdexpFloat3IntFloat3(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        int[] arrayInY = new int[INPUTSIZE * 1];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLdexp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%d", args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLdexpFloat3IntFloat3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLdexpFloat4IntFloat4() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xf7d121c0fcaadc09l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 1, 0xf7d121c0fcaadc0al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testLdexpFloat4IntFloat4(inX, out);
+            verifyResultsLdexpFloat4IntFloat4(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLdexpFloat4IntFloat4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testLdexpFloat4IntFloat4(inX, out);
+            verifyResultsLdexpFloat4IntFloat4(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLdexpFloat4IntFloat4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLdexpFloat4IntFloat4(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        int[] arrayInY = new int[INPUTSIZE * 1];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLdexp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%d", args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLdexpFloat4IntFloat4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testLdexp() {
+        checkLdexpFloatIntFloat();
+        checkLdexpFloat2Int2Float2();
+        checkLdexpFloat3Int3Float3();
+        checkLdexpFloat4Int4Float4();
+        checkLdexpFloat2IntFloat2();
+        checkLdexpFloat3IntFloat3();
+        checkLdexpFloat4IntFloat4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestLdexp.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestLdexp.rs
new file mode 100644
index 0000000..e8b05f2
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestLdexp.rs
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInY;
+
+float __attribute__((kernel)) testLdexpFloatIntFloat(float inX, unsigned int x) {
+    int inY = rsGetElementAt_int(gAllocInY, x);
+    return ldexp(inX, inY);
+}
+
+float2 __attribute__((kernel)) testLdexpFloat2Int2Float2(float2 inX, unsigned int x) {
+    int2 inY = rsGetElementAt_int2(gAllocInY, x);
+    return ldexp(inX, inY);
+}
+
+float3 __attribute__((kernel)) testLdexpFloat3Int3Float3(float3 inX, unsigned int x) {
+    int3 inY = rsGetElementAt_int3(gAllocInY, x);
+    return ldexp(inX, inY);
+}
+
+float4 __attribute__((kernel)) testLdexpFloat4Int4Float4(float4 inX, unsigned int x) {
+    int4 inY = rsGetElementAt_int4(gAllocInY, x);
+    return ldexp(inX, inY);
+}
+
+float2 __attribute__((kernel)) testLdexpFloat2IntFloat2(float2 inX, unsigned int x) {
+    int inY = rsGetElementAt_int(gAllocInY, x);
+    return ldexp(inX, inY);
+}
+
+float3 __attribute__((kernel)) testLdexpFloat3IntFloat3(float3 inX, unsigned int x) {
+    int inY = rsGetElementAt_int(gAllocInY, x);
+    return ldexp(inX, inY);
+}
+
+float4 __attribute__((kernel)) testLdexpFloat4IntFloat4(float4 inX, unsigned int x) {
+    int inY = rsGetElementAt_int(gAllocInY, x);
+    return ldexp(inX, inY);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestLdexpRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestLdexpRelaxed.rs
new file mode 100644
index 0000000..ee9f5cf
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestLdexpRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestLdexp.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestLength.java b/tests/tests/renderscript/src/android/renderscript/cts/TestLength.java
new file mode 100644
index 0000000..2d89536
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestLength.java
@@ -0,0 +1,300 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestLength extends RSBaseCompute {
+
+    private ScriptC_TestLength script;
+    private ScriptC_TestLengthRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestLength(mRS);
+        scriptRelaxed = new ScriptC_TestLengthRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkLengthFloatFloat() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x8119352509f7cc9fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testLengthFloatFloat(inV, out);
+            verifyResultsLengthFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLengthFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testLengthFloatFloat(inV, out);
+            verifyResultsLengthFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLengthFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLengthFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+            // Create the appropriate sized arrays in args
+            // Fill args with the input values
+            args.inV = arrayInV[i];
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeLength(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                message.append("Input inV: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayInV[i], Float.floatToRawIntBits(arrayInV[i]), arrayInV[i]));
+                message.append("\n");
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkLengthFloatFloat" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    public class ArgumentsFloatNFloat {
+        public float[] inV;
+        public Target.Floaty out;
+    }
+
+    private void checkLengthFloat2Float() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xaf3b0f345dd9595dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testLengthFloat2Float(inV, out);
+            verifyResultsLengthFloat2Float(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLengthFloat2Float: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testLengthFloat2Float(inV, out);
+            verifyResultsLengthFloat2Float(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLengthFloat2Float: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLengthFloat2Float(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloat args = new ArgumentsFloatNFloat();
+            // Create the appropriate sized arrays in args
+            args.inV = new float[2];
+            // Fill args with the input values
+            for (int j = 0; j < 2 ; j++) {
+                args.inV[j] = arrayInV[i * 2 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeLength(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 2 ; j++) {
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInV[i * 2 + j], Float.floatToRawIntBits(arrayInV[i * 2 + j]), arrayInV[i * 2 + j]));
+                    message.append("\n");
+                }
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkLengthFloat2Float" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    private void checkLengthFloat3Float() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xaf3b19d5bcdfe7bel, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testLengthFloat3Float(inV, out);
+            verifyResultsLengthFloat3Float(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLengthFloat3Float: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testLengthFloat3Float(inV, out);
+            verifyResultsLengthFloat3Float(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLengthFloat3Float: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLengthFloat3Float(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloat args = new ArgumentsFloatNFloat();
+            // Create the appropriate sized arrays in args
+            args.inV = new float[3];
+            // Fill args with the input values
+            for (int j = 0; j < 3 ; j++) {
+                args.inV[j] = arrayInV[i * 4 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeLength(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 3 ; j++) {
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInV[i * 4 + j], Float.floatToRawIntBits(arrayInV[i * 4 + j]), arrayInV[i * 4 + j]));
+                    message.append("\n");
+                }
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkLengthFloat3Float" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    private void checkLengthFloat4Float() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xaf3b24771be6761fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testLengthFloat4Float(inV, out);
+            verifyResultsLengthFloat4Float(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLengthFloat4Float: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testLengthFloat4Float(inV, out);
+            verifyResultsLengthFloat4Float(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLengthFloat4Float: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLengthFloat4Float(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloat args = new ArgumentsFloatNFloat();
+            // Create the appropriate sized arrays in args
+            args.inV = new float[4];
+            // Fill args with the input values
+            for (int j = 0; j < 4 ; j++) {
+                args.inV[j] = arrayInV[i * 4 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeLength(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 4 ; j++) {
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInV[i * 4 + j], Float.floatToRawIntBits(arrayInV[i * 4 + j]), arrayInV[i * 4 + j]));
+                    message.append("\n");
+                }
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkLengthFloat4Float" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    public void testLength() {
+        checkLengthFloatFloat();
+        checkLengthFloat2Float();
+        checkLengthFloat3Float();
+        checkLengthFloat4Float();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestLength.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestLength.rs
new file mode 100644
index 0000000..3239dbd
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestLength.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testLengthFloatFloat(float inV) {
+    return length(inV);
+}
+
+float __attribute__((kernel)) testLengthFloat2Float(float2 inV) {
+    return length(inV);
+}
+
+float __attribute__((kernel)) testLengthFloat3Float(float3 inV) {
+    return length(inV);
+}
+
+float __attribute__((kernel)) testLengthFloat4Float(float4 inV) {
+    return length(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestLengthRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestLengthRelaxed.rs
new file mode 100644
index 0000000..12eba8b
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestLengthRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestLength.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestLgamma.java b/tests/tests/renderscript/src/android/renderscript/cts/TestLgamma.java
new file mode 100644
index 0000000..113df19
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestLgamma.java
@@ -0,0 +1,538 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestLgamma extends RSBaseCompute {
+
+    private ScriptC_TestLgamma script;
+    private ScriptC_TestLgammaRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestLgamma(mRS);
+        scriptRelaxed = new ScriptC_TestLgammaRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkLgammaFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xe748c67429cab138l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testLgammaFloatFloat(in, out);
+            verifyResultsLgammaFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLgammaFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testLgammaFloatFloat(in, out);
+            verifyResultsLgammaFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLgammaFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLgammaFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLgamma(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLgammaFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLgammaFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x7ca07efd8a327894l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testLgammaFloat2Float2(in, out);
+            verifyResultsLgammaFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLgammaFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testLgammaFloat2Float2(in, out);
+            verifyResultsLgammaFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLgammaFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLgammaFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLgamma(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLgammaFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLgammaFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x7ca0899ee9390e2el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testLgammaFloat3Float3(in, out);
+            verifyResultsLgammaFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLgammaFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testLgammaFloat3Float3(in, out);
+            verifyResultsLgammaFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLgammaFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLgammaFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLgamma(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLgammaFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLgammaFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x7ca09440483fa3c8l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testLgammaFloat4Float4(in, out);
+            verifyResultsLgammaFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLgammaFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testLgammaFloat4Float4(in, out);
+            verifyResultsLgammaFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLgammaFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLgammaFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLgamma(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLgammaFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsFloatIntFloat {
+        public float inX;
+        public int outY;
+        public float out;
+    }
+
+    private void checkLgammaFloatIntFloat() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x2a62d992979c4bb9l, false);
+        try {
+            Allocation outY = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 1), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocOutY(outY);
+            script.forEach_testLgammaFloatIntFloat(inX, out);
+            verifyResultsLgammaFloatIntFloat(inX, outY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLgammaFloatIntFloat: " + e.toString());
+        }
+        try {
+            Allocation outY = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 1), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutY(outY);
+            scriptRelaxed.forEach_testLgammaFloatIntFloat(inX, out);
+            verifyResultsLgammaFloatIntFloat(inX, outY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLgammaFloatIntFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLgammaFloatIntFloat(Allocation inX, Allocation outY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 1];
+        inX.copyTo(arrayInX);
+        int[] arrayOutY = new int[INPUTSIZE * 1];
+        outY.copyTo(arrayOutY);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inX = arrayInX[i];
+                // Extract the outputs.
+                args.outY = arrayOutY[i * 1 + j];
+                args.out = arrayOut[i * 1 + j];
+                // Ask the CoreMathVerifier to validate.
+                Target target = new Target(relaxed);
+                String errorMessage = CoreMathVerifier.verifyLgamma(args, target);
+                boolean valid = errorMessage == null;
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Output outY: ");
+                    message.append(String.format("%d", args.outY));
+                    message.append("\n");
+                    message.append("Output out: ");
+                    message.append(Float.toString(args.out));
+                    message.append("\n");
+                    message.append(errorMessage);
+                    assertTrue("Incorrect output for checkLgammaFloatIntFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLgammaFloat2Int2Float2() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x409fb9a5984bcf81l, false);
+        try {
+            Allocation outY = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocOutY(outY);
+            script.forEach_testLgammaFloat2Int2Float2(inX, out);
+            verifyResultsLgammaFloat2Int2Float2(inX, outY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLgammaFloat2Int2Float2: " + e.toString());
+        }
+        try {
+            Allocation outY = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutY(outY);
+            scriptRelaxed.forEach_testLgammaFloat2Int2Float2(inX, out);
+            verifyResultsLgammaFloat2Int2Float2(inX, outY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLgammaFloat2Int2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLgammaFloat2Int2Float2(Allocation inX, Allocation outY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 2];
+        inX.copyTo(arrayInX);
+        int[] arrayOutY = new int[INPUTSIZE * 2];
+        outY.copyTo(arrayOutY);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inX = arrayInX[i * 2 + j];
+                // Extract the outputs.
+                args.outY = arrayOutY[i * 2 + j];
+                args.out = arrayOut[i * 2 + j];
+                // Ask the CoreMathVerifier to validate.
+                Target target = new Target(relaxed);
+                String errorMessage = CoreMathVerifier.verifyLgamma(args, target);
+                boolean valid = errorMessage == null;
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Output outY: ");
+                    message.append(String.format("%d", args.outY));
+                    message.append("\n");
+                    message.append("Output out: ");
+                    message.append(Float.toString(args.out));
+                    message.append("\n");
+                    message.append(errorMessage);
+                    assertTrue("Incorrect output for checkLgammaFloat2Int2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLgammaFloat3Int3Float3() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x6655f8088dfe3c3al, false);
+        try {
+            Allocation outY = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocOutY(outY);
+            script.forEach_testLgammaFloat3Int3Float3(inX, out);
+            verifyResultsLgammaFloat3Int3Float3(inX, outY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLgammaFloat3Int3Float3: " + e.toString());
+        }
+        try {
+            Allocation outY = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutY(outY);
+            scriptRelaxed.forEach_testLgammaFloat3Int3Float3(inX, out);
+            verifyResultsLgammaFloat3Int3Float3(inX, outY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLgammaFloat3Int3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLgammaFloat3Int3Float3(Allocation inX, Allocation outY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        int[] arrayOutY = new int[INPUTSIZE * 4];
+        outY.copyTo(arrayOutY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inX = arrayInX[i * 4 + j];
+                // Extract the outputs.
+                args.outY = arrayOutY[i * 4 + j];
+                args.out = arrayOut[i * 4 + j];
+                // Ask the CoreMathVerifier to validate.
+                Target target = new Target(relaxed);
+                String errorMessage = CoreMathVerifier.verifyLgamma(args, target);
+                boolean valid = errorMessage == null;
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Output outY: ");
+                    message.append(String.format("%d", args.outY));
+                    message.append("\n");
+                    message.append("Output out: ");
+                    message.append(Float.toString(args.out));
+                    message.append("\n");
+                    message.append(errorMessage);
+                    assertTrue("Incorrect output for checkLgammaFloat3Int3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLgammaFloat4Int4Float4() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x8c0c366b83b0a8f3l, false);
+        try {
+            Allocation outY = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocOutY(outY);
+            script.forEach_testLgammaFloat4Int4Float4(inX, out);
+            verifyResultsLgammaFloat4Int4Float4(inX, outY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLgammaFloat4Int4Float4: " + e.toString());
+        }
+        try {
+            Allocation outY = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutY(outY);
+            scriptRelaxed.forEach_testLgammaFloat4Int4Float4(inX, out);
+            verifyResultsLgammaFloat4Int4Float4(inX, outY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLgammaFloat4Int4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLgammaFloat4Int4Float4(Allocation inX, Allocation outY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        int[] arrayOutY = new int[INPUTSIZE * 4];
+        outY.copyTo(arrayOutY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inX = arrayInX[i * 4 + j];
+                // Extract the outputs.
+                args.outY = arrayOutY[i * 4 + j];
+                args.out = arrayOut[i * 4 + j];
+                // Ask the CoreMathVerifier to validate.
+                Target target = new Target(relaxed);
+                String errorMessage = CoreMathVerifier.verifyLgamma(args, target);
+                boolean valid = errorMessage == null;
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Output outY: ");
+                    message.append(String.format("%d", args.outY));
+                    message.append("\n");
+                    message.append("Output out: ");
+                    message.append(Float.toString(args.out));
+                    message.append("\n");
+                    message.append(errorMessage);
+                    assertTrue("Incorrect output for checkLgammaFloat4Int4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testLgamma() {
+        checkLgammaFloatFloat();
+        checkLgammaFloat2Float2();
+        checkLgammaFloat3Float3();
+        checkLgammaFloat4Float4();
+        checkLgammaFloatIntFloat();
+        checkLgammaFloat2Int2Float2();
+        checkLgammaFloat3Int3Float3();
+        checkLgammaFloat4Int4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestLgamma.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestLgamma.rs
new file mode 100644
index 0000000..b39e592
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestLgamma.rs
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testLgammaFloatFloat(float in) {
+    return lgamma(in);
+}
+
+float2 __attribute__((kernel)) testLgammaFloat2Float2(float2 in) {
+    return lgamma(in);
+}
+
+float3 __attribute__((kernel)) testLgammaFloat3Float3(float3 in) {
+    return lgamma(in);
+}
+
+float4 __attribute__((kernel)) testLgammaFloat4Float4(float4 in) {
+    return lgamma(in);
+}
+rs_allocation gAllocOutY;
+
+float __attribute__((kernel)) testLgammaFloatIntFloat(float inX, unsigned int x) {
+    int outY = 0;
+    float out = lgamma(inX, &outY);
+    rsSetElementAt_int(gAllocOutY, outY, x);
+    return out;
+}
+
+float2 __attribute__((kernel)) testLgammaFloat2Int2Float2(float2 inX, unsigned int x) {
+    int2 outY = 0;
+    float2 out = lgamma(inX, &outY);
+    rsSetElementAt_int2(gAllocOutY, outY, x);
+    return out;
+}
+
+float3 __attribute__((kernel)) testLgammaFloat3Int3Float3(float3 inX, unsigned int x) {
+    int3 outY = 0;
+    float3 out = lgamma(inX, &outY);
+    rsSetElementAt_int3(gAllocOutY, outY, x);
+    return out;
+}
+
+float4 __attribute__((kernel)) testLgammaFloat4Int4Float4(float4 inX, unsigned int x) {
+    int4 outY = 0;
+    float4 out = lgamma(inX, &outY);
+    rsSetElementAt_int4(gAllocOutY, outY, x);
+    return out;
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestLgammaRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestLgammaRelaxed.rs
new file mode 100644
index 0000000..a259576
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestLgammaRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestLgamma.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestLog.java b/tests/tests/renderscript/src/android/renderscript/cts/TestLog.java
new file mode 100644
index 0000000..8b4717c
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestLog.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestLog extends RSBaseCompute {
+
+    private ScriptC_TestLog script;
+    private ScriptC_TestLogRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestLog(mRS);
+        scriptRelaxed = new ScriptC_TestLogRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkLogFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x371a946136907325l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testLogFloatFloat(in, out);
+            verifyResultsLogFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testLogFloatFloat(in, out);
+            verifyResultsLogFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLogFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLog(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLogFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLogFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xfef8d41eca882159l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testLogFloat2Float2(in, out);
+            verifyResultsLogFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testLogFloat2Float2(in, out);
+            verifyResultsLogFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLogFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLog(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLogFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLogFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xfef8dec0298eb6f3l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testLogFloat3Float3(in, out);
+            verifyResultsLogFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testLogFloat3Float3(in, out);
+            verifyResultsLogFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLogFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLog(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLogFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLogFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xfef8e96188954c8dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testLogFloat4Float4(in, out);
+            verifyResultsLogFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testLogFloat4Float4(in, out);
+            verifyResultsLogFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLogFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLog(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLogFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testLog() {
+        checkLogFloatFloat();
+        checkLogFloat2Float2();
+        checkLogFloat3Float3();
+        checkLogFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestLog.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestLog.rs
new file mode 100644
index 0000000..4261b61
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestLog.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testLogFloatFloat(float in) {
+    return log(in);
+}
+
+float2 __attribute__((kernel)) testLogFloat2Float2(float2 in) {
+    return log(in);
+}
+
+float3 __attribute__((kernel)) testLogFloat3Float3(float3 in) {
+    return log(in);
+}
+
+float4 __attribute__((kernel)) testLogFloat4Float4(float4 in) {
+    return log(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestLog10.java b/tests/tests/renderscript/src/android/renderscript/cts/TestLog10.java
new file mode 100644
index 0000000..5928090
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestLog10.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestLog10 extends RSBaseCompute {
+
+    private ScriptC_TestLog10 script;
+    private ScriptC_TestLog10Relaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestLog10(mRS);
+        scriptRelaxed = new ScriptC_TestLog10Relaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkLog10FloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xe09b228ed779b7a0l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testLog10FloatFloat(in, out);
+            verifyResultsLog10FloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog10FloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testLog10FloatFloat(in, out);
+            verifyResultsLog10FloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog10FloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLog10FloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLog10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLog10FloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLog10Float2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x407bbbadff57bdbcl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testLog10Float2Float2(in, out);
+            verifyResultsLog10Float2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog10Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testLog10Float2Float2(in, out);
+            verifyResultsLog10Float2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog10Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLog10Float2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLog10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLog10Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLog10Float3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x407bc64f5e5e5356l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testLog10Float3Float3(in, out);
+            verifyResultsLog10Float3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog10Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testLog10Float3Float3(in, out);
+            verifyResultsLog10Float3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog10Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLog10Float3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLog10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLog10Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLog10Float4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x407bd0f0bd64e8f0l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testLog10Float4Float4(in, out);
+            verifyResultsLog10Float4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog10Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testLog10Float4Float4(in, out);
+            verifyResultsLog10Float4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog10Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLog10Float4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLog10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLog10Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testLog10() {
+        checkLog10FloatFloat();
+        checkLog10Float2Float2();
+        checkLog10Float3Float3();
+        checkLog10Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestLog10.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestLog10.rs
new file mode 100644
index 0000000..18fb3c3
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestLog10.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testLog10FloatFloat(float in) {
+    return log10(in);
+}
+
+float2 __attribute__((kernel)) testLog10Float2Float2(float2 in) {
+    return log10(in);
+}
+
+float3 __attribute__((kernel)) testLog10Float3Float3(float3 in) {
+    return log10(in);
+}
+
+float4 __attribute__((kernel)) testLog10Float4Float4(float4 in) {
+    return log10(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestLog10Relaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestLog10Relaxed.rs
new file mode 100644
index 0000000..c0c47f3
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestLog10Relaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestLog10.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestLog1p.java b/tests/tests/renderscript/src/android/renderscript/cts/TestLog1p.java
new file mode 100644
index 0000000..019cffb
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestLog1p.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestLog1p extends RSBaseCompute {
+
+    private ScriptC_TestLog1p script;
+    private ScriptC_TestLog1pRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestLog1p(mRS);
+        scriptRelaxed = new ScriptC_TestLog1pRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkLog1pFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x83e3423b7d907be0l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testLog1pFloatFloat(in, out);
+            verifyResultsLog1pFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog1pFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testLog1pFloatFloat(in, out);
+            verifyResultsLog1pFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog1pFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLog1pFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLog1p(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLog1pFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLog1pFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x946881a999c72ffcl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testLog1pFloat2Float2(in, out);
+            verifyResultsLog1pFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog1pFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testLog1pFloat2Float2(in, out);
+            verifyResultsLog1pFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog1pFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLog1pFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLog1p(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLog1pFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLog1pFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x94688c4af8cdc596l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testLog1pFloat3Float3(in, out);
+            verifyResultsLog1pFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog1pFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testLog1pFloat3Float3(in, out);
+            verifyResultsLog1pFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog1pFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLog1pFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLog1p(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLog1pFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLog1pFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x946896ec57d45b30l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testLog1pFloat4Float4(in, out);
+            verifyResultsLog1pFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog1pFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testLog1pFloat4Float4(in, out);
+            verifyResultsLog1pFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog1pFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLog1pFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLog1p(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLog1pFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testLog1p() {
+        checkLog1pFloatFloat();
+        checkLog1pFloat2Float2();
+        checkLog1pFloat3Float3();
+        checkLog1pFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestLog1p.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestLog1p.rs
new file mode 100644
index 0000000..bc5577e
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestLog1p.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testLog1pFloatFloat(float in) {
+    return log1p(in);
+}
+
+float2 __attribute__((kernel)) testLog1pFloat2Float2(float2 in) {
+    return log1p(in);
+}
+
+float3 __attribute__((kernel)) testLog1pFloat3Float3(float3 in) {
+    return log1p(in);
+}
+
+float4 __attribute__((kernel)) testLog1pFloat4Float4(float4 in) {
+    return log1p(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestLog1pRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestLog1pRelaxed.rs
new file mode 100644
index 0000000..3136d9e
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestLog1pRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestLog1p.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestLog2.java b/tests/tests/renderscript/src/android/renderscript/cts/TestLog2.java
new file mode 100644
index 0000000..92a4985
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestLog2.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestLog2 extends RSBaseCompute {
+
+    private ScriptC_TestLog2 script;
+    private ScriptC_TestLog2Relaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestLog2(mRS);
+        scriptRelaxed = new ScriptC_TestLog2Relaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkLog2FloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x390bea9a53d34bfl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testLog2FloatFloat(in, out);
+            verifyResultsLog2FloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog2FloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testLog2FloatFloat(in, out);
+            verifyResultsLog2FloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog2FloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLog2FloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLog2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLog2FloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLog2Float2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xc0703946284a72a3l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testLog2Float2Float2(in, out);
+            verifyResultsLog2Float2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testLog2Float2Float2(in, out);
+            verifyResultsLog2Float2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLog2Float2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLog2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLog2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLog2Float3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xc07043e78751083dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testLog2Float3Float3(in, out);
+            verifyResultsLog2Float3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog2Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testLog2Float3Float3(in, out);
+            verifyResultsLog2Float3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog2Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLog2Float3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLog2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLog2Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLog2Float4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xc0704e88e6579dd7l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testLog2Float4Float4(in, out);
+            verifyResultsLog2Float4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog2Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testLog2Float4Float4(in, out);
+            verifyResultsLog2Float4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog2Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLog2Float4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLog2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLog2Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testLog2() {
+        checkLog2FloatFloat();
+        checkLog2Float2Float2();
+        checkLog2Float3Float3();
+        checkLog2Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestLog2.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestLog2.rs
new file mode 100644
index 0000000..4cf8ef2
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestLog2.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testLog2FloatFloat(float in) {
+    return log2(in);
+}
+
+float2 __attribute__((kernel)) testLog2Float2Float2(float2 in) {
+    return log2(in);
+}
+
+float3 __attribute__((kernel)) testLog2Float3Float3(float3 in) {
+    return log2(in);
+}
+
+float4 __attribute__((kernel)) testLog2Float4Float4(float4 in) {
+    return log2(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestLog2Relaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestLog2Relaxed.rs
new file mode 100644
index 0000000..e79f105
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestLog2Relaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestLog2.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestLogRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestLogRelaxed.rs
new file mode 100644
index 0000000..3fed787
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestLogRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestLog.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestLogb.java b/tests/tests/renderscript/src/android/renderscript/cts/TestLogb.java
new file mode 100644
index 0000000..8679aa0
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestLogb.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestLogb extends RSBaseCompute {
+
+    private ScriptC_TestLogb script;
+    private ScriptC_TestLogbRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestLogb(mRS);
+        scriptRelaxed = new ScriptC_TestLogbRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkLogbFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xfe06d66b21ce47efl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testLogbFloatFloat(in, out);
+            verifyResultsLogbFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogbFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testLogbFloatFloat(in, out);
+            verifyResultsLogbFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogbFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLogbFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLogb(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLogbFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLogbFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xbf61cdc2dc1e0853l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testLogbFloat2Float2(in, out);
+            verifyResultsLogbFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogbFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testLogbFloat2Float2(in, out);
+            verifyResultsLogbFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogbFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLogbFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLogb(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLogbFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLogbFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xbf61d8643b249dedl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testLogbFloat3Float3(in, out);
+            verifyResultsLogbFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogbFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testLogbFloat3Float3(in, out);
+            verifyResultsLogbFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogbFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLogbFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLogb(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLogbFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkLogbFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xbf61e3059a2b3387l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testLogbFloat4Float4(in, out);
+            verifyResultsLogbFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogbFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testLogbFloat4Float4(in, out);
+            verifyResultsLogbFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogbFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLogbFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeLogb(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkLogbFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testLogb() {
+        checkLogbFloatFloat();
+        checkLogbFloat2Float2();
+        checkLogbFloat3Float3();
+        checkLogbFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestLogb.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestLogb.rs
new file mode 100644
index 0000000..8317a22
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestLogb.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testLogbFloatFloat(float in) {
+    return logb(in);
+}
+
+float2 __attribute__((kernel)) testLogbFloat2Float2(float2 in) {
+    return logb(in);
+}
+
+float3 __attribute__((kernel)) testLogbFloat3Float3(float3 in) {
+    return logb(in);
+}
+
+float4 __attribute__((kernel)) testLogbFloat4Float4(float4 in) {
+    return logb(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestLogbRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestLogbRelaxed.rs
new file mode 100644
index 0000000..bcf84b7
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestLogbRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestLogb.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestMad.java b/tests/tests/renderscript/src/android/renderscript/cts/TestMad.java
new file mode 100644
index 0000000..0ac029c
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestMad.java
@@ -0,0 +1,366 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestMad extends RSBaseCompute {
+
+    private ScriptC_TestMad script;
+    private ScriptC_TestMadRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestMad(mRS);
+        scriptRelaxed = new ScriptC_TestMadRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloatFloat {
+        public float inA;
+        public float inB;
+        public float inC;
+        public Target.Floaty out;
+    }
+
+    private void checkMadFloatFloatFloatFloat() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xb3b9b8429c37eacl, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xb3b9b8429c37eadl, false);
+        Allocation inC = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xb3b9b8429c37eael, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.set_gAllocInC(inC);
+            script.forEach_testMadFloatFloatFloatFloat(inA, out);
+            verifyResultsMadFloatFloatFloatFloat(inA, inB, inC, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMadFloatFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.set_gAllocInC(inC);
+            scriptRelaxed.forEach_testMadFloatFloatFloatFloat(inA, out);
+            verifyResultsMadFloatFloatFloatFloat(inA, inB, inC, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMadFloatFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMadFloatFloatFloatFloat(Allocation inA, Allocation inB, Allocation inC, Allocation out, boolean relaxed) {
+        float[] arrayInA = new float[INPUTSIZE * 1];
+        inA.copyTo(arrayInA);
+        float[] arrayInB = new float[INPUTSIZE * 1];
+        inB.copyTo(arrayInB);
+        float[] arrayInC = new float[INPUTSIZE * 1];
+        inC.copyTo(arrayInC);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloatFloat args = new ArgumentsFloatFloatFloatFloat();
+                args.inA = arrayInA[i];
+                args.inB = arrayInB[i];
+                args.inC = arrayInC[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeMad(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inA: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inA, Float.floatToRawIntBits(args.inA), args.inA));
+                    message.append("\n");
+                    message.append("Input inB: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inB, Float.floatToRawIntBits(args.inB), args.inB));
+                    message.append("\n");
+                    message.append("Input inC: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inC, Float.floatToRawIntBits(args.inC), args.inC));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMadFloatFloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMadFloat2Float2Float2Float2() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x44d6ec3d0f2030a4l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x44d6ec3d0f2030a5l, false);
+        Allocation inC = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x44d6ec3d0f2030a6l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.set_gAllocInC(inC);
+            script.forEach_testMadFloat2Float2Float2Float2(inA, out);
+            verifyResultsMadFloat2Float2Float2Float2(inA, inB, inC, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMadFloat2Float2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.set_gAllocInC(inC);
+            scriptRelaxed.forEach_testMadFloat2Float2Float2Float2(inA, out);
+            verifyResultsMadFloat2Float2Float2Float2(inA, inB, inC, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMadFloat2Float2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMadFloat2Float2Float2Float2(Allocation inA, Allocation inB, Allocation inC, Allocation out, boolean relaxed) {
+        float[] arrayInA = new float[INPUTSIZE * 2];
+        inA.copyTo(arrayInA);
+        float[] arrayInB = new float[INPUTSIZE * 2];
+        inB.copyTo(arrayInB);
+        float[] arrayInC = new float[INPUTSIZE * 2];
+        inC.copyTo(arrayInC);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloatFloat args = new ArgumentsFloatFloatFloatFloat();
+                args.inA = arrayInA[i * 2 + j];
+                args.inB = arrayInB[i * 2 + j];
+                args.inC = arrayInC[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeMad(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inA: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inA, Float.floatToRawIntBits(args.inA), args.inA));
+                    message.append("\n");
+                    message.append("Input inB: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inB, Float.floatToRawIntBits(args.inB), args.inB));
+                    message.append("\n");
+                    message.append("Input inC: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inC, Float.floatToRawIntBits(args.inC), args.inC));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMadFloat2Float2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMadFloat3Float3Float3Float3() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x1a508fd7e1876a40l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x1a508fd7e1876a41l, false);
+        Allocation inC = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x1a508fd7e1876a42l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.set_gAllocInC(inC);
+            script.forEach_testMadFloat3Float3Float3Float3(inA, out);
+            verifyResultsMadFloat3Float3Float3Float3(inA, inB, inC, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMadFloat3Float3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.set_gAllocInC(inC);
+            scriptRelaxed.forEach_testMadFloat3Float3Float3Float3(inA, out);
+            verifyResultsMadFloat3Float3Float3Float3(inA, inB, inC, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMadFloat3Float3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMadFloat3Float3Float3Float3(Allocation inA, Allocation inB, Allocation inC, Allocation out, boolean relaxed) {
+        float[] arrayInA = new float[INPUTSIZE * 4];
+        inA.copyTo(arrayInA);
+        float[] arrayInB = new float[INPUTSIZE * 4];
+        inB.copyTo(arrayInB);
+        float[] arrayInC = new float[INPUTSIZE * 4];
+        inC.copyTo(arrayInC);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloatFloat args = new ArgumentsFloatFloatFloatFloat();
+                args.inA = arrayInA[i * 4 + j];
+                args.inB = arrayInB[i * 4 + j];
+                args.inC = arrayInC[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeMad(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inA: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inA, Float.floatToRawIntBits(args.inA), args.inA));
+                    message.append("\n");
+                    message.append("Input inB: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inB, Float.floatToRawIntBits(args.inB), args.inB));
+                    message.append("\n");
+                    message.append("Input inC: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inC, Float.floatToRawIntBits(args.inC), args.inC));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMadFloat3Float3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMadFloat4Float4Float4Float4() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xefca3372b3eea3dcl, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xefca3372b3eea3ddl, false);
+        Allocation inC = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xefca3372b3eea3del, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.set_gAllocInC(inC);
+            script.forEach_testMadFloat4Float4Float4Float4(inA, out);
+            verifyResultsMadFloat4Float4Float4Float4(inA, inB, inC, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMadFloat4Float4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.set_gAllocInC(inC);
+            scriptRelaxed.forEach_testMadFloat4Float4Float4Float4(inA, out);
+            verifyResultsMadFloat4Float4Float4Float4(inA, inB, inC, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMadFloat4Float4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMadFloat4Float4Float4Float4(Allocation inA, Allocation inB, Allocation inC, Allocation out, boolean relaxed) {
+        float[] arrayInA = new float[INPUTSIZE * 4];
+        inA.copyTo(arrayInA);
+        float[] arrayInB = new float[INPUTSIZE * 4];
+        inB.copyTo(arrayInB);
+        float[] arrayInC = new float[INPUTSIZE * 4];
+        inC.copyTo(arrayInC);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloatFloat args = new ArgumentsFloatFloatFloatFloat();
+                args.inA = arrayInA[i * 4 + j];
+                args.inB = arrayInB[i * 4 + j];
+                args.inC = arrayInC[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeMad(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inA: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inA, Float.floatToRawIntBits(args.inA), args.inA));
+                    message.append("\n");
+                    message.append("Input inB: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inB, Float.floatToRawIntBits(args.inB), args.inB));
+                    message.append("\n");
+                    message.append("Input inC: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inC, Float.floatToRawIntBits(args.inC), args.inC));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMadFloat4Float4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testMad() {
+        checkMadFloatFloatFloatFloat();
+        checkMadFloat2Float2Float2Float2();
+        checkMadFloat3Float3Float3Float3();
+        checkMadFloat4Float4Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestMad.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestMad.rs
new file mode 100644
index 0000000..bcf908b
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestMad.rs
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInB;
+rs_allocation gAllocInC;
+
+float __attribute__((kernel)) testMadFloatFloatFloatFloat(float inA, unsigned int x) {
+    float inB = rsGetElementAt_float(gAllocInB, x);
+    float inC = rsGetElementAt_float(gAllocInC, x);
+    return mad(inA, inB, inC);
+}
+
+float2 __attribute__((kernel)) testMadFloat2Float2Float2Float2(float2 inA, unsigned int x) {
+    float2 inB = rsGetElementAt_float2(gAllocInB, x);
+    float2 inC = rsGetElementAt_float2(gAllocInC, x);
+    return mad(inA, inB, inC);
+}
+
+float3 __attribute__((kernel)) testMadFloat3Float3Float3Float3(float3 inA, unsigned int x) {
+    float3 inB = rsGetElementAt_float3(gAllocInB, x);
+    float3 inC = rsGetElementAt_float3(gAllocInC, x);
+    return mad(inA, inB, inC);
+}
+
+float4 __attribute__((kernel)) testMadFloat4Float4Float4Float4(float4 inA, unsigned int x) {
+    float4 inB = rsGetElementAt_float4(gAllocInB, x);
+    float4 inC = rsGetElementAt_float4(gAllocInC, x);
+    return mad(inA, inB, inC);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestMadRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestMadRelaxed.rs
new file mode 100644
index 0000000..acec458
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestMadRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestMad.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestMax.java b/tests/tests/renderscript/src/android/renderscript/cts/TestMax.java
new file mode 100644
index 0000000..e52ef48
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestMax.java
@@ -0,0 +1,2485 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestMax extends RSBaseCompute {
+
+    private ScriptC_TestMax script;
+    private ScriptC_TestMaxRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestMax(mRS);
+        scriptRelaxed = new ScriptC_TestMaxRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float in;
+        public float in1;
+        public Target.Floaty out;
+    }
+
+    private void checkMaxFloatFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xfb01ed3804837dddl, false);
+        Allocation in1 = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x2952d868c2162450l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocIn1(in1);
+            script.forEach_testMaxFloatFloatFloat(in, out);
+            verifyResultsMaxFloatFloatFloat(in, in1, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocIn1(in1);
+            scriptRelaxed.forEach_testMaxFloatFloatFloat(in, out);
+            verifyResultsMaxFloatFloatFloat(in, in1, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxFloatFloatFloat(Allocation in, Allocation in1, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayIn1 = new float[INPUTSIZE * 1];
+        in1.copyTo(arrayIn1);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.in = arrayIn[i];
+                args.in1 = arrayIn1[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeMax(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Input in1: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in1, Float.floatToRawIntBits(args.in1), args.in1));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxFloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxFloat2Float2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x63dc5a02b9d46a4bl, false);
+        Allocation in1 = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xc6031e7536addacal, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocIn1(in1);
+            script.forEach_testMaxFloat2Float2Float2(in, out);
+            verifyResultsMaxFloat2Float2Float2(in, in1, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxFloat2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocIn1(in1);
+            scriptRelaxed.forEach_testMaxFloat2Float2Float2(in, out);
+            verifyResultsMaxFloat2Float2Float2(in, in1, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxFloat2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxFloat2Float2Float2(Allocation in, Allocation in1, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayIn1 = new float[INPUTSIZE * 2];
+        in1.copyTo(arrayIn1);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                args.in1 = arrayIn1[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeMax(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Input in1: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in1, Float.floatToRawIntBits(args.in1), args.in1));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxFloat2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxFloat3Float3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xb92c17bc0744bdael, false);
+        Allocation in1 = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x1a67fc95388bdc6bl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocIn1(in1);
+            script.forEach_testMaxFloat3Float3Float3(in, out);
+            verifyResultsMaxFloat3Float3Float3(in, in1, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxFloat3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocIn1(in1);
+            scriptRelaxed.forEach_testMaxFloat3Float3Float3(in, out);
+            verifyResultsMaxFloat3Float3Float3(in, in1, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxFloat3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxFloat3Float3Float3(Allocation in, Allocation in1, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayIn1 = new float[INPUTSIZE * 4];
+        in1.copyTo(arrayIn1);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                args.in1 = arrayIn1[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeMax(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Input in1: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in1, Float.floatToRawIntBits(args.in1), args.in1));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxFloat3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxFloat4Float4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xe7bd57554b51111l, false);
+        Allocation in1 = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x6eccdab53a69de0cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocIn1(in1);
+            script.forEach_testMaxFloat4Float4Float4(in, out);
+            verifyResultsMaxFloat4Float4Float4(in, in1, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxFloat4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocIn1(in1);
+            scriptRelaxed.forEach_testMaxFloat4Float4Float4(in, out);
+            verifyResultsMaxFloat4Float4Float4(in, in1, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxFloat4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxFloat4Float4Float4(Allocation in, Allocation in1, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayIn1 = new float[INPUTSIZE * 4];
+        in1.copyTo(arrayIn1);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                args.in1 = arrayIn1[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeMax(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Input in1: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in1, Float.floatToRawIntBits(args.in1), args.in1));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxFloat4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsCharCharChar {
+        public byte inV1;
+        public byte inV2;
+        public byte out;
+    }
+
+    private void checkMaxCharCharChar() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 1, 0x91fcf329ccedf8al, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 1, 0x91fcf329ccedf8bl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 1), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxCharCharChar(inV1, out);
+            verifyResultsMaxCharCharChar(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxCharCharChar: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxCharCharChar(inV1, out);
+            verifyResultsMaxCharCharChar(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxCharCharChar: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxCharCharChar(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        byte[] arrayInV1 = new byte[INPUTSIZE * 1];
+        inV1.copyTo(arrayInV1);
+        byte[] arrayInV2 = new byte[INPUTSIZE * 1];
+        inV2.copyTo(arrayInV2);
+        byte[] arrayOut = new byte[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharCharChar args = new ArgumentsCharCharChar();
+                args.inV1 = arrayInV1[i];
+                args.inV2 = arrayInV2[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxCharCharChar" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxChar2Char2Char2() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 2, 0x12084b25952bc64l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 2, 0x12084b25952bc65l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxChar2Char2Char2(inV1, out);
+            verifyResultsMaxChar2Char2Char2(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxChar2Char2Char2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxChar2Char2Char2(inV1, out);
+            verifyResultsMaxChar2Char2Char2(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxChar2Char2Char2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxChar2Char2Char2(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        byte[] arrayInV1 = new byte[INPUTSIZE * 2];
+        inV1.copyTo(arrayInV1);
+        byte[] arrayInV2 = new byte[INPUTSIZE * 2];
+        inV2.copyTo(arrayInV2);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharCharChar args = new ArgumentsCharCharChar();
+                args.inV1 = arrayInV1[i * 2 + j];
+                args.inV2 = arrayInV2[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxChar2Char2Char2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxChar3Char3Char3() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 3, 0x567200e53e0a8f29l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 3, 0x567200e53e0a8f2al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxChar3Char3Char3(inV1, out);
+            verifyResultsMaxChar3Char3Char3(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxChar3Char3Char3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxChar3Char3Char3(inV1, out);
+            verifyResultsMaxChar3Char3Char3(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxChar3Char3Char3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxChar3Char3Char3(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        byte[] arrayInV1 = new byte[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        byte[] arrayInV2 = new byte[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharCharChar args = new ArgumentsCharCharChar();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxChar3Char3Char3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxChar4Char4Char4() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 4, 0xabc37d1822c261eel, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 4, 0xabc37d1822c261efl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxChar4Char4Char4(inV1, out);
+            verifyResultsMaxChar4Char4Char4(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxChar4Char4Char4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxChar4Char4Char4(inV1, out);
+            verifyResultsMaxChar4Char4Char4(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxChar4Char4Char4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxChar4Char4Char4(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        byte[] arrayInV1 = new byte[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        byte[] arrayInV2 = new byte[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharCharChar args = new ArgumentsCharCharChar();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxChar4Char4Char4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUcharUcharUchar {
+        public byte inV1;
+        public byte inV2;
+        public byte out;
+    }
+
+    private void checkMaxUcharUcharUchar() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 1, 0x829ebf2e60c1bd47l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 1, 0x829ebf2e60c1bd48l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 1), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxUcharUcharUchar(inV1, out);
+            verifyResultsMaxUcharUcharUchar(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUcharUcharUchar: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxUcharUcharUchar(inV1, out);
+            verifyResultsMaxUcharUcharUchar(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUcharUcharUchar: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxUcharUcharUchar(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        byte[] arrayInV1 = new byte[INPUTSIZE * 1];
+        inV1.copyTo(arrayInV1);
+        byte[] arrayInV2 = new byte[INPUTSIZE * 1];
+        inV2.copyTo(arrayInV2);
+        byte[] arrayOut = new byte[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUcharUchar args = new ArgumentsUcharUcharUchar();
+                args.inV1 = arrayInV1[i];
+                args.inV2 = arrayInV2[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxUcharUcharUchar" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxUchar2Uchar2Uchar2() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 2, 0x75eda605e43f8b81l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 2, 0x75eda605e43f8b82l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxUchar2Uchar2Uchar2(inV1, out);
+            verifyResultsMaxUchar2Uchar2Uchar2(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUchar2Uchar2Uchar2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxUchar2Uchar2Uchar2(inV1, out);
+            verifyResultsMaxUchar2Uchar2Uchar2(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUchar2Uchar2Uchar2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxUchar2Uchar2Uchar2(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        byte[] arrayInV1 = new byte[INPUTSIZE * 2];
+        inV1.copyTo(arrayInV1);
+        byte[] arrayInV2 = new byte[INPUTSIZE * 2];
+        inV2.copyTo(arrayInV2);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUcharUchar args = new ArgumentsUcharUcharUchar();
+                args.inV1 = arrayInV1[i * 2 + j];
+                args.inV2 = arrayInV2[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxUchar2Uchar2Uchar2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxUchar3Uchar3Uchar3() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 3, 0xa2def5663489d18cl, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 3, 0xa2def5663489d18dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxUchar3Uchar3Uchar3(inV1, out);
+            verifyResultsMaxUchar3Uchar3Uchar3(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUchar3Uchar3Uchar3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxUchar3Uchar3Uchar3(inV1, out);
+            verifyResultsMaxUchar3Uchar3Uchar3(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUchar3Uchar3Uchar3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxUchar3Uchar3Uchar3(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        byte[] arrayInV1 = new byte[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        byte[] arrayInV2 = new byte[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUcharUchar args = new ArgumentsUcharUcharUchar();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxUchar3Uchar3Uchar3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxUchar4Uchar4Uchar4() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 4, 0xcfd044c684d41797l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 4, 0xcfd044c684d41798l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxUchar4Uchar4Uchar4(inV1, out);
+            verifyResultsMaxUchar4Uchar4Uchar4(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUchar4Uchar4Uchar4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxUchar4Uchar4Uchar4(inV1, out);
+            verifyResultsMaxUchar4Uchar4Uchar4(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUchar4Uchar4Uchar4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxUchar4Uchar4Uchar4(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        byte[] arrayInV1 = new byte[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        byte[] arrayInV2 = new byte[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUcharUchar args = new ArgumentsUcharUcharUchar();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxUchar4Uchar4Uchar4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsShortShortShort {
+        public short inV1;
+        public short inV2;
+        public short out;
+    }
+
+    private void checkMaxShortShortShort() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 1, 0x868a0cd65f7a4294l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 1, 0x868a0cd65f7a4295l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 1), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxShortShortShort(inV1, out);
+            verifyResultsMaxShortShortShort(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxShortShortShort: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxShortShortShort(inV1, out);
+            verifyResultsMaxShortShortShort(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxShortShortShort: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxShortShortShort(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        short[] arrayInV1 = new short[INPUTSIZE * 1];
+        inV1.copyTo(arrayInV1);
+        short[] arrayInV2 = new short[INPUTSIZE * 1];
+        inV2.copyTo(arrayInV2);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortShortShort args = new ArgumentsShortShortShort();
+                args.inV1 = arrayInV1[i];
+                args.inV2 = arrayInV2[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxShortShortShort" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxShort2Short2Short2() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 2, 0x3d46ae0799c33c02l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 2, 0x3d46ae0799c33c03l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxShort2Short2Short2(inV1, out);
+            verifyResultsMaxShort2Short2Short2(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxShort2Short2Short2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxShort2Short2Short2(inV1, out);
+            verifyResultsMaxShort2Short2Short2(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxShort2Short2Short2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxShort2Short2Short2(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        short[] arrayInV1 = new short[INPUTSIZE * 2];
+        inV1.copyTo(arrayInV1);
+        short[] arrayInV2 = new short[INPUTSIZE * 2];
+        inV2.copyTo(arrayInV2);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortShortShort args = new ArgumentsShortShortShort();
+                args.inV1 = arrayInV1[i * 2 + j];
+                args.inV2 = arrayInV2[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxShort2Short2Short2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxShort3Short3Short3() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 3, 0x6a37fd67ea0d820dl, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 3, 0x6a37fd67ea0d820el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxShort3Short3Short3(inV1, out);
+            verifyResultsMaxShort3Short3Short3(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxShort3Short3Short3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxShort3Short3Short3(inV1, out);
+            verifyResultsMaxShort3Short3Short3(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxShort3Short3Short3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxShort3Short3Short3(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        short[] arrayInV1 = new short[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        short[] arrayInV2 = new short[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortShortShort args = new ArgumentsShortShortShort();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxShort3Short3Short3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxShort4Short4Short4() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 4, 0x97294cc83a57c818l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 4, 0x97294cc83a57c819l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxShort4Short4Short4(inV1, out);
+            verifyResultsMaxShort4Short4Short4(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxShort4Short4Short4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxShort4Short4Short4(inV1, out);
+            verifyResultsMaxShort4Short4Short4(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxShort4Short4Short4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxShort4Short4Short4(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        short[] arrayInV1 = new short[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        short[] arrayInV2 = new short[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortShortShort args = new ArgumentsShortShortShort();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxShort4Short4Short4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUshortUshortUshort {
+        public short inV1;
+        public short inV2;
+        public short out;
+    }
+
+    private void checkMaxUshortUshortUshort() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 1, 0x1b9c47701effe051l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 1, 0x1b9c47701effe052l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 1), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxUshortUshortUshort(inV1, out);
+            verifyResultsMaxUshortUshortUshort(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUshortUshortUshort: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxUshortUshortUshort(inV1, out);
+            verifyResultsMaxUshortUshortUshort(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUshortUshortUshort: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxUshortUshortUshort(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        short[] arrayInV1 = new short[INPUTSIZE * 1];
+        inV1.copyTo(arrayInV1);
+        short[] arrayInV2 = new short[INPUTSIZE * 1];
+        inV2.copyTo(arrayInV2);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUshortUshort args = new ArgumentsUshortUshortUshort();
+                args.inV1 = arrayInV1[i];
+                args.inV2 = arrayInV2[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxUshortUshortUshort" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxUshort2Ushort2Ushort2() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 2, 0xf42196a588de51bfl, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 2, 0xf42196a588de51c0l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxUshort2Ushort2Ushort2(inV1, out);
+            verifyResultsMaxUshort2Ushort2Ushort2(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUshort2Ushort2Ushort2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxUshort2Ushort2Ushort2(inV1, out);
+            verifyResultsMaxUshort2Ushort2Ushort2(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUshort2Ushort2Ushort2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxUshort2Ushort2Ushort2(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        short[] arrayInV1 = new short[INPUTSIZE * 2];
+        inV1.copyTo(arrayInV1);
+        short[] arrayInV2 = new short[INPUTSIZE * 2];
+        inV2.copyTo(arrayInV2);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUshortUshort args = new ArgumentsUshortUshortUshort();
+                args.inV1 = arrayInV1[i * 2 + j];
+                args.inV2 = arrayInV2[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxUshort2Ushort2Ushort2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxUshort3Ushort3Ushort3() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 3, 0x71604884c752e61cl, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 3, 0x71604884c752e61dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxUshort3Ushort3Ushort3(inV1, out);
+            verifyResultsMaxUshort3Ushort3Ushort3(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUshort3Ushort3Ushort3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxUshort3Ushort3Ushort3(inV1, out);
+            verifyResultsMaxUshort3Ushort3Ushort3(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUshort3Ushort3Ushort3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxUshort3Ushort3Ushort3(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        short[] arrayInV1 = new short[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        short[] arrayInV2 = new short[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUshortUshort args = new ArgumentsUshortUshortUshort();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxUshort3Ushort3Ushort3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxUshort4Ushort4Ushort4() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 4, 0xee9efa6405c77a79l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 4, 0xee9efa6405c77a7al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxUshort4Ushort4Ushort4(inV1, out);
+            verifyResultsMaxUshort4Ushort4Ushort4(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUshort4Ushort4Ushort4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxUshort4Ushort4Ushort4(inV1, out);
+            verifyResultsMaxUshort4Ushort4Ushort4(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUshort4Ushort4Ushort4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxUshort4Ushort4Ushort4(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        short[] arrayInV1 = new short[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        short[] arrayInV2 = new short[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUshortUshort args = new ArgumentsUshortUshortUshort();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxUshort4Ushort4Ushort4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsIntIntInt {
+        public int inV1;
+        public int inV2;
+        public int out;
+    }
+
+    private void checkMaxIntIntInt() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 1, 0x7413f465641a51bl, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 1, 0x7413f465641a51cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 1), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxIntIntInt(inV1, out);
+            verifyResultsMaxIntIntInt(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxIntIntInt: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxIntIntInt(inV1, out);
+            verifyResultsMaxIntIntInt(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxIntIntInt: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxIntIntInt(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        int[] arrayInV1 = new int[INPUTSIZE * 1];
+        inV1.copyTo(arrayInV1);
+        int[] arrayInV2 = new int[INPUTSIZE * 1];
+        inV2.copyTo(arrayInV2);
+        int[] arrayOut = new int[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntIntInt args = new ArgumentsIntIntInt();
+                args.inV1 = arrayInV1[i];
+                args.inV2 = arrayInV2[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxIntIntInt" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxInt2Int2Int2() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 2, 0x7bba1e4a83816bd5l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 2, 0x7bba1e4a83816bd6l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxInt2Int2Int2(inV1, out);
+            verifyResultsMaxInt2Int2Int2(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxInt2Int2Int2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxInt2Int2Int2(inV1, out);
+            verifyResultsMaxInt2Int2Int2(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxInt2Int2Int2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxInt2Int2Int2(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        int[] arrayInV1 = new int[INPUTSIZE * 2];
+        inV1.copyTo(arrayInV1);
+        int[] arrayInV2 = new int[INPUTSIZE * 2];
+        inV2.copyTo(arrayInV2);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntIntInt args = new ArgumentsIntIntInt();
+                args.inV1 = arrayInV1[i * 2 + j];
+                args.inV2 = arrayInV2[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxInt2Int2Int2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxInt3Int3Int3() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 3, 0xa647496a95547ff8l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 3, 0xa647496a95547ff9l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxInt3Int3Int3(inV1, out);
+            verifyResultsMaxInt3Int3Int3(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxInt3Int3Int3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxInt3Int3Int3(inV1, out);
+            verifyResultsMaxInt3Int3Int3(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxInt3Int3Int3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxInt3Int3Int3(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        int[] arrayInV1 = new int[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        int[] arrayInV2 = new int[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntIntInt args = new ArgumentsIntIntInt();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxInt3Int3Int3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxInt4Int4Int4() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 4, 0xd0d4748aa727941bl, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 4, 0xd0d4748aa727941cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxInt4Int4Int4(inV1, out);
+            verifyResultsMaxInt4Int4Int4(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxInt4Int4Int4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxInt4Int4Int4(inV1, out);
+            verifyResultsMaxInt4Int4Int4(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxInt4Int4Int4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxInt4Int4Int4(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        int[] arrayInV1 = new int[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        int[] arrayInV2 = new int[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntIntInt args = new ArgumentsIntIntInt();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxInt4Int4Int4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUintUintUint {
+        public int inV1;
+        public int inV2;
+        public int out;
+    }
+
+    private void checkMaxUintUintUint() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 1, 0x75328d17808776cal, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 1, 0x75328d17808776cbl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 1), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxUintUintUint(inV1, out);
+            verifyResultsMaxUintUintUint(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUintUintUint: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxUintUintUint(inV1, out);
+            verifyResultsMaxUintUintUint(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUintUintUint: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxUintUintUint(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        int[] arrayInV1 = new int[INPUTSIZE * 1];
+        inV1.copyTo(arrayInV1);
+        int[] arrayInV2 = new int[INPUTSIZE * 1];
+        inV2.copyTo(arrayInV2);
+        int[] arrayOut = new int[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUintUint args = new ArgumentsUintUintUint();
+                args.inV1 = arrayInV1[i];
+                args.inV2 = arrayInV2[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxUintUintUint" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxUint2Uint2Uint2() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 2, 0xcda90384705016a4l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 2, 0xcda90384705016a5l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxUint2Uint2Uint2(inV1, out);
+            verifyResultsMaxUint2Uint2Uint2(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUint2Uint2Uint2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxUint2Uint2Uint2(inV1, out);
+            verifyResultsMaxUint2Uint2Uint2(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUint2Uint2Uint2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxUint2Uint2Uint2(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        int[] arrayInV1 = new int[INPUTSIZE * 2];
+        inV1.copyTo(arrayInV1);
+        int[] arrayInV2 = new int[INPUTSIZE * 2];
+        inV2.copyTo(arrayInV2);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUintUint args = new ArgumentsUintUintUint();
+                args.inV1 = arrayInV1[i * 2 + j];
+                args.inV2 = arrayInV2[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxUint2Uint2Uint2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxUint3Uint3Uint3() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 3, 0x22fa7fb75507e969l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 3, 0x22fa7fb75507e96al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxUint3Uint3Uint3(inV1, out);
+            verifyResultsMaxUint3Uint3Uint3(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUint3Uint3Uint3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxUint3Uint3Uint3(inV1, out);
+            verifyResultsMaxUint3Uint3Uint3(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUint3Uint3Uint3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxUint3Uint3Uint3(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        int[] arrayInV1 = new int[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        int[] arrayInV2 = new int[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUintUint args = new ArgumentsUintUintUint();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxUint3Uint3Uint3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxUint4Uint4Uint4() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 4, 0x784bfbea39bfbc2el, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 4, 0x784bfbea39bfbc2fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxUint4Uint4Uint4(inV1, out);
+            verifyResultsMaxUint4Uint4Uint4(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUint4Uint4Uint4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxUint4Uint4Uint4(inV1, out);
+            verifyResultsMaxUint4Uint4Uint4(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUint4Uint4Uint4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxUint4Uint4Uint4(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        int[] arrayInV1 = new int[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        int[] arrayInV2 = new int[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUintUint args = new ArgumentsUintUintUint();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxUint4Uint4Uint4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsLongLongLong {
+        public long inV1;
+        public long inV2;
+        public long out;
+    }
+
+    private void checkMaxLongLongLong() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 1, 0xe224db3c7ecb92e4l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 1, 0xe224db3c7ecb92e5l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 1), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxLongLongLong(inV1, out);
+            verifyResultsMaxLongLongLong(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxLongLongLong: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxLongLongLong(inV1, out);
+            verifyResultsMaxLongLongLong(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxLongLongLong: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxLongLongLong(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        long[] arrayInV1 = new long[INPUTSIZE * 1];
+        inV1.copyTo(arrayInV1);
+        long[] arrayInV2 = new long[INPUTSIZE * 1];
+        inV2.copyTo(arrayInV2);
+        long[] arrayOut = new long[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongLongLong args = new ArgumentsLongLongLong();
+                args.inV1 = arrayInV1[i];
+                args.inV2 = arrayInV2[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxLongLongLong" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxLong2Long2Long2() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 2, 0x375f5f0ca264eb56l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 2, 0x375f5f0ca264eb57l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxLong2Long2Long2(inV1, out);
+            verifyResultsMaxLong2Long2Long2(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxLong2Long2Long2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxLong2Long2Long2(inV1, out);
+            verifyResultsMaxLong2Long2Long2(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxLong2Long2Long2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxLong2Long2Long2(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        long[] arrayInV1 = new long[INPUTSIZE * 2];
+        inV1.copyTo(arrayInV1);
+        long[] arrayInV2 = new long[INPUTSIZE * 2];
+        inV2.copyTo(arrayInV2);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongLongLong args = new ArgumentsLongLongLong();
+                args.inV1 = arrayInV1[i * 2 + j];
+                args.inV2 = arrayInV2[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxLong2Long2Long2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxLong3Long3Long3() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 3, 0x8cb0db3f871cbe1bl, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 3, 0x8cb0db3f871cbe1cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxLong3Long3Long3(inV1, out);
+            verifyResultsMaxLong3Long3Long3(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxLong3Long3Long3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxLong3Long3Long3(inV1, out);
+            verifyResultsMaxLong3Long3Long3(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxLong3Long3Long3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxLong3Long3Long3(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        long[] arrayInV1 = new long[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        long[] arrayInV2 = new long[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongLongLong args = new ArgumentsLongLongLong();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxLong3Long3Long3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxLong4Long4Long4() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 4, 0xe20257726bd490e0l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 4, 0xe20257726bd490e1l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxLong4Long4Long4(inV1, out);
+            verifyResultsMaxLong4Long4Long4(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxLong4Long4Long4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxLong4Long4Long4(inV1, out);
+            verifyResultsMaxLong4Long4Long4(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxLong4Long4Long4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxLong4Long4Long4(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        long[] arrayInV1 = new long[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        long[] arrayInV2 = new long[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongLongLong args = new ArgumentsLongLongLong();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxLong4Long4Long4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUlongUlongUlong {
+        public long inV1;
+        public long inV2;
+        public long out;
+    }
+
+    private void checkMaxUlongUlongUlong() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 1, 0xb38270e909275f1dl, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 1, 0xb38270e909275f1el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 1), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxUlongUlongUlong(inV1, out);
+            verifyResultsMaxUlongUlongUlong(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUlongUlongUlong: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxUlongUlongUlong(inV1, out);
+            verifyResultsMaxUlongUlongUlong(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUlongUlongUlong: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxUlongUlongUlong(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        long[] arrayInV1 = new long[INPUTSIZE * 1];
+        inV1.copyTo(arrayInV1);
+        long[] arrayInV2 = new long[INPUTSIZE * 1];
+        inV2.copyTo(arrayInV2);
+        long[] arrayOut = new long[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUlongUlong args = new ArgumentsUlongUlongUlong();
+                args.inV1 = arrayInV1[i];
+                args.inV2 = arrayInV2[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxUlongUlongUlong" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxUlong2Ulong2Ulong2() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 2, 0x7f6c5ec5fee1a8afl, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 2, 0x7f6c5ec5fee1a8b0l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxUlong2Ulong2Ulong2(inV1, out);
+            verifyResultsMaxUlong2Ulong2Ulong2(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUlong2Ulong2Ulong2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxUlong2Ulong2Ulong2(inV1, out);
+            verifyResultsMaxUlong2Ulong2Ulong2(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUlong2Ulong2Ulong2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxUlong2Ulong2Ulong2(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        long[] arrayInV1 = new long[INPUTSIZE * 2];
+        inV1.copyTo(arrayInV1);
+        long[] arrayInV2 = new long[INPUTSIZE * 2];
+        inV2.copyTo(arrayInV2);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUlongUlong args = new ArgumentsUlongUlongUlong();
+                args.inV1 = arrayInV1[i * 2 + j];
+                args.inV2 = arrayInV2[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxUlong2Ulong2Ulong2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxUlong3Ulong3Ulong3() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 3, 0xac5dae264f2beebal, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 3, 0xac5dae264f2beebbl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxUlong3Ulong3Ulong3(inV1, out);
+            verifyResultsMaxUlong3Ulong3Ulong3(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUlong3Ulong3Ulong3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxUlong3Ulong3Ulong3(inV1, out);
+            verifyResultsMaxUlong3Ulong3Ulong3(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUlong3Ulong3Ulong3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxUlong3Ulong3Ulong3(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        long[] arrayInV1 = new long[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        long[] arrayInV2 = new long[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUlongUlong args = new ArgumentsUlongUlongUlong();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxUlong3Ulong3Ulong3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMaxUlong4Ulong4Ulong4() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 4, 0xd94efd869f7634c5l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 4, 0xd94efd869f7634c6l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMaxUlong4Ulong4Ulong4(inV1, out);
+            verifyResultsMaxUlong4Ulong4Ulong4(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUlong4Ulong4Ulong4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMaxUlong4Ulong4Ulong4(inV1, out);
+            verifyResultsMaxUlong4Ulong4Ulong4(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxUlong4Ulong4Ulong4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxUlong4Ulong4Ulong4(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        long[] arrayInV1 = new long[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        long[] arrayInV2 = new long[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUlongUlong args = new ArgumentsUlongUlongUlong();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMax(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMaxUlong4Ulong4Ulong4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testMax() {
+        checkMaxFloatFloatFloat();
+        checkMaxFloat2Float2Float2();
+        checkMaxFloat3Float3Float3();
+        checkMaxFloat4Float4Float4();
+        checkMaxCharCharChar();
+        checkMaxChar2Char2Char2();
+        checkMaxChar3Char3Char3();
+        checkMaxChar4Char4Char4();
+        checkMaxUcharUcharUchar();
+        checkMaxUchar2Uchar2Uchar2();
+        checkMaxUchar3Uchar3Uchar3();
+        checkMaxUchar4Uchar4Uchar4();
+        checkMaxShortShortShort();
+        checkMaxShort2Short2Short2();
+        checkMaxShort3Short3Short3();
+        checkMaxShort4Short4Short4();
+        checkMaxUshortUshortUshort();
+        checkMaxUshort2Ushort2Ushort2();
+        checkMaxUshort3Ushort3Ushort3();
+        checkMaxUshort4Ushort4Ushort4();
+        checkMaxIntIntInt();
+        checkMaxInt2Int2Int2();
+        checkMaxInt3Int3Int3();
+        checkMaxInt4Int4Int4();
+        checkMaxUintUintUint();
+        checkMaxUint2Uint2Uint2();
+        checkMaxUint3Uint3Uint3();
+        checkMaxUint4Uint4Uint4();
+        checkMaxLongLongLong();
+        checkMaxLong2Long2Long2();
+        checkMaxLong3Long3Long3();
+        checkMaxLong4Long4Long4();
+        checkMaxUlongUlongUlong();
+        checkMaxUlong2Ulong2Ulong2();
+        checkMaxUlong3Ulong3Ulong3();
+        checkMaxUlong4Ulong4Ulong4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestMax.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestMax.rs
new file mode 100644
index 0000000..dff7927
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestMax.rs
@@ -0,0 +1,203 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocIn1;
+
+float __attribute__((kernel)) testMaxFloatFloatFloat(float in, unsigned int x) {
+    float in1 = rsGetElementAt_float(gAllocIn1, x);
+    return max(in, in1);
+}
+
+float2 __attribute__((kernel)) testMaxFloat2Float2Float2(float2 in, unsigned int x) {
+    float2 in1 = rsGetElementAt_float2(gAllocIn1, x);
+    return max(in, in1);
+}
+
+float3 __attribute__((kernel)) testMaxFloat3Float3Float3(float3 in, unsigned int x) {
+    float3 in1 = rsGetElementAt_float3(gAllocIn1, x);
+    return max(in, in1);
+}
+
+float4 __attribute__((kernel)) testMaxFloat4Float4Float4(float4 in, unsigned int x) {
+    float4 in1 = rsGetElementAt_float4(gAllocIn1, x);
+    return max(in, in1);
+}
+rs_allocation gAllocInV2;
+
+char __attribute__((kernel)) testMaxCharCharChar(char inV1, unsigned int x) {
+    char inV2 = rsGetElementAt_char(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+char2 __attribute__((kernel)) testMaxChar2Char2Char2(char2 inV1, unsigned int x) {
+    char2 inV2 = rsGetElementAt_char2(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+char3 __attribute__((kernel)) testMaxChar3Char3Char3(char3 inV1, unsigned int x) {
+    char3 inV2 = rsGetElementAt_char3(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+char4 __attribute__((kernel)) testMaxChar4Char4Char4(char4 inV1, unsigned int x) {
+    char4 inV2 = rsGetElementAt_char4(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+uchar __attribute__((kernel)) testMaxUcharUcharUchar(uchar inV1, unsigned int x) {
+    uchar inV2 = rsGetElementAt_uchar(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+uchar2 __attribute__((kernel)) testMaxUchar2Uchar2Uchar2(uchar2 inV1, unsigned int x) {
+    uchar2 inV2 = rsGetElementAt_uchar2(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+uchar3 __attribute__((kernel)) testMaxUchar3Uchar3Uchar3(uchar3 inV1, unsigned int x) {
+    uchar3 inV2 = rsGetElementAt_uchar3(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+uchar4 __attribute__((kernel)) testMaxUchar4Uchar4Uchar4(uchar4 inV1, unsigned int x) {
+    uchar4 inV2 = rsGetElementAt_uchar4(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+short __attribute__((kernel)) testMaxShortShortShort(short inV1, unsigned int x) {
+    short inV2 = rsGetElementAt_short(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+short2 __attribute__((kernel)) testMaxShort2Short2Short2(short2 inV1, unsigned int x) {
+    short2 inV2 = rsGetElementAt_short2(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+short3 __attribute__((kernel)) testMaxShort3Short3Short3(short3 inV1, unsigned int x) {
+    short3 inV2 = rsGetElementAt_short3(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+short4 __attribute__((kernel)) testMaxShort4Short4Short4(short4 inV1, unsigned int x) {
+    short4 inV2 = rsGetElementAt_short4(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+ushort __attribute__((kernel)) testMaxUshortUshortUshort(ushort inV1, unsigned int x) {
+    ushort inV2 = rsGetElementAt_ushort(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+ushort2 __attribute__((kernel)) testMaxUshort2Ushort2Ushort2(ushort2 inV1, unsigned int x) {
+    ushort2 inV2 = rsGetElementAt_ushort2(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+ushort3 __attribute__((kernel)) testMaxUshort3Ushort3Ushort3(ushort3 inV1, unsigned int x) {
+    ushort3 inV2 = rsGetElementAt_ushort3(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+ushort4 __attribute__((kernel)) testMaxUshort4Ushort4Ushort4(ushort4 inV1, unsigned int x) {
+    ushort4 inV2 = rsGetElementAt_ushort4(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+int __attribute__((kernel)) testMaxIntIntInt(int inV1, unsigned int x) {
+    int inV2 = rsGetElementAt_int(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+int2 __attribute__((kernel)) testMaxInt2Int2Int2(int2 inV1, unsigned int x) {
+    int2 inV2 = rsGetElementAt_int2(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+int3 __attribute__((kernel)) testMaxInt3Int3Int3(int3 inV1, unsigned int x) {
+    int3 inV2 = rsGetElementAt_int3(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+int4 __attribute__((kernel)) testMaxInt4Int4Int4(int4 inV1, unsigned int x) {
+    int4 inV2 = rsGetElementAt_int4(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+uint __attribute__((kernel)) testMaxUintUintUint(uint inV1, unsigned int x) {
+    uint inV2 = rsGetElementAt_uint(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+uint2 __attribute__((kernel)) testMaxUint2Uint2Uint2(uint2 inV1, unsigned int x) {
+    uint2 inV2 = rsGetElementAt_uint2(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+uint3 __attribute__((kernel)) testMaxUint3Uint3Uint3(uint3 inV1, unsigned int x) {
+    uint3 inV2 = rsGetElementAt_uint3(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+uint4 __attribute__((kernel)) testMaxUint4Uint4Uint4(uint4 inV1, unsigned int x) {
+    uint4 inV2 = rsGetElementAt_uint4(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+long __attribute__((kernel)) testMaxLongLongLong(long inV1, unsigned int x) {
+    long inV2 = rsGetElementAt_long(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+long2 __attribute__((kernel)) testMaxLong2Long2Long2(long2 inV1, unsigned int x) {
+    long2 inV2 = rsGetElementAt_long2(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+long3 __attribute__((kernel)) testMaxLong3Long3Long3(long3 inV1, unsigned int x) {
+    long3 inV2 = rsGetElementAt_long3(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+long4 __attribute__((kernel)) testMaxLong4Long4Long4(long4 inV1, unsigned int x) {
+    long4 inV2 = rsGetElementAt_long4(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+ulong __attribute__((kernel)) testMaxUlongUlongUlong(ulong inV1, unsigned int x) {
+    ulong inV2 = rsGetElementAt_ulong(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+ulong2 __attribute__((kernel)) testMaxUlong2Ulong2Ulong2(ulong2 inV1, unsigned int x) {
+    ulong2 inV2 = rsGetElementAt_ulong2(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+ulong3 __attribute__((kernel)) testMaxUlong3Ulong3Ulong3(ulong3 inV1, unsigned int x) {
+    ulong3 inV2 = rsGetElementAt_ulong3(gAllocInV2, x);
+    return max(inV1, inV2);
+}
+
+ulong4 __attribute__((kernel)) testMaxUlong4Ulong4Ulong4(ulong4 inV1, unsigned int x) {
+    ulong4 inV2 = rsGetElementAt_ulong4(gAllocInV2, x);
+    return max(inV1, inV2);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestMaxRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestMaxRelaxed.rs
new file mode 100644
index 0000000..fb0319b
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestMaxRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestMax.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestMin.java b/tests/tests/renderscript/src/android/renderscript/cts/TestMin.java
new file mode 100644
index 0000000..a04ef55
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestMin.java
@@ -0,0 +1,2485 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestMin extends RSBaseCompute {
+
+    private ScriptC_TestMin script;
+    private ScriptC_TestMinRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestMin(mRS);
+        scriptRelaxed = new ScriptC_TestMinRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float in;
+        public float in1;
+        public Target.Floaty out;
+    }
+
+    private void checkMinFloatFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x816f2fe273bf4977l, false);
+        Allocation in1 = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xbdad0b097121572el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocIn1(in1);
+            script.forEach_testMinFloatFloatFloat(in, out);
+            verifyResultsMinFloatFloatFloat(in, in1, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocIn1(in1);
+            scriptRelaxed.forEach_testMinFloatFloatFloat(in, out);
+            verifyResultsMinFloatFloatFloat(in, in1, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinFloatFloatFloat(Allocation in, Allocation in1, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayIn1 = new float[INPUTSIZE * 1];
+        in1.copyTo(arrayIn1);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.in = arrayIn[i];
+                args.in1 = arrayIn1[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeMin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Input in1: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in1, Float.floatToRawIntBits(args.in1), args.in1));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinFloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinFloat2Float2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xe354049301b6cfb9l, false);
+        Allocation in1 = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x2f1cc4b149b4e444l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocIn1(in1);
+            script.forEach_testMinFloat2Float2Float2(in, out);
+            verifyResultsMinFloat2Float2Float2(in, in1, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinFloat2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocIn1(in1);
+            scriptRelaxed.forEach_testMinFloat2Float2Float2(in, out);
+            verifyResultsMinFloat2Float2Float2(in, in1, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinFloat2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinFloat2Float2Float2(Allocation in, Allocation in1, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayIn1 = new float[INPUTSIZE * 2];
+        in1.copyTo(arrayIn1);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                args.in1 = arrayIn1[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeMin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Input in1: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in1, Float.floatToRawIntBits(args.in1), args.in1));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinFloat2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinFloat3Float3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x38a3c24c4f27231cl, false);
+        Allocation in1 = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x8381a2d14b92e5e5l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocIn1(in1);
+            script.forEach_testMinFloat3Float3Float3(in, out);
+            verifyResultsMinFloat3Float3Float3(in, in1, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinFloat3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocIn1(in1);
+            scriptRelaxed.forEach_testMinFloat3Float3Float3(in, out);
+            verifyResultsMinFloat3Float3Float3(in, in1, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinFloat3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinFloat3Float3Float3(Allocation in, Allocation in1, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayIn1 = new float[INPUTSIZE * 4];
+        in1.copyTo(arrayIn1);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                args.in1 = arrayIn1[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeMin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Input in1: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in1, Float.floatToRawIntBits(args.in1), args.in1));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinFloat3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinFloat4Float4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x8df380059c97767fl, false);
+        Allocation in1 = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xd7e680f14d70e786l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocIn1(in1);
+            script.forEach_testMinFloat4Float4Float4(in, out);
+            verifyResultsMinFloat4Float4Float4(in, in1, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinFloat4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocIn1(in1);
+            scriptRelaxed.forEach_testMinFloat4Float4Float4(in, out);
+            verifyResultsMinFloat4Float4Float4(in, in1, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinFloat4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinFloat4Float4Float4(Allocation in, Allocation in1, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayIn1 = new float[INPUTSIZE * 4];
+        in1.copyTo(arrayIn1);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                args.in1 = arrayIn1[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeMin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Input in1: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in1, Float.floatToRawIntBits(args.in1), args.in1));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinFloat4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsCharCharChar {
+        public byte inV1;
+        public byte inV2;
+        public byte out;
+    }
+
+    private void checkMinCharCharChar() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 1, 0x47c90c486fc45b58l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 1, 0x47c90c486fc45b59l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 1), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinCharCharChar(inV1, out);
+            verifyResultsMinCharCharChar(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinCharCharChar: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinCharCharChar(inV1, out);
+            verifyResultsMinCharCharChar(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinCharCharChar: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinCharCharChar(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        byte[] arrayInV1 = new byte[INPUTSIZE * 1];
+        inV1.copyTo(arrayInV1);
+        byte[] arrayInV2 = new byte[INPUTSIZE * 1];
+        inV2.copyTo(arrayInV2);
+        byte[] arrayOut = new byte[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharCharChar args = new ArgumentsCharCharChar();
+                args.inV1 = arrayInV1[i];
+                args.inV2 = arrayInV2[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinCharCharChar" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinChar2Char2Char2() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 2, 0xec4705afc03447ael, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 2, 0xec4705afc03447afl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinChar2Char2Char2(inV1, out);
+            verifyResultsMinChar2Char2Char2(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinChar2Char2Char2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinChar2Char2Char2(inV1, out);
+            verifyResultsMinChar2Char2Char2(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinChar2Char2Char2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinChar2Char2Char2(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        byte[] arrayInV1 = new byte[INPUTSIZE * 2];
+        inV1.copyTo(arrayInV1);
+        byte[] arrayInV2 = new byte[INPUTSIZE * 2];
+        inV2.copyTo(arrayInV2);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharCharChar args = new ArgumentsCharCharChar();
+                args.inV1 = arrayInV1[i * 2 + j];
+                args.inV2 = arrayInV2[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinChar2Char2Char2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinChar3Char3Char3() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 3, 0x419881e2a4ec1a73l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 3, 0x419881e2a4ec1a74l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinChar3Char3Char3(inV1, out);
+            verifyResultsMinChar3Char3Char3(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinChar3Char3Char3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinChar3Char3Char3(inV1, out);
+            verifyResultsMinChar3Char3Char3(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinChar3Char3Char3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinChar3Char3Char3(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        byte[] arrayInV1 = new byte[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        byte[] arrayInV2 = new byte[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharCharChar args = new ArgumentsCharCharChar();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinChar3Char3Char3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinChar4Char4Char4() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 4, 0x96e9fe1589a3ed38l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_8, 4, 0x96e9fe1589a3ed39l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinChar4Char4Char4(inV1, out);
+            verifyResultsMinChar4Char4Char4(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinChar4Char4Char4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinChar4Char4Char4(inV1, out);
+            verifyResultsMinChar4Char4Char4(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinChar4Char4Char4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinChar4Char4Char4(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        byte[] arrayInV1 = new byte[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        byte[] arrayInV2 = new byte[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharCharChar args = new ArgumentsCharCharChar();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinChar4Char4Char4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUcharUcharUchar {
+        public byte inV1;
+        public byte inV2;
+        public byte out;
+    }
+
+    private void checkMinUcharUcharUchar() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 1, 0x6dc5402bc7a34891l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 1, 0x6dc5402bc7a34892l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 1), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinUcharUcharUchar(inV1, out);
+            verifyResultsMinUcharUcharUchar(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUcharUcharUchar: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinUcharUcharUchar(inV1, out);
+            verifyResultsMinUcharUcharUchar(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUcharUcharUchar: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinUcharUcharUchar(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        byte[] arrayInV1 = new byte[INPUTSIZE * 1];
+        inV1.copyTo(arrayInV1);
+        byte[] arrayInV2 = new byte[INPUTSIZE * 1];
+        inV2.copyTo(arrayInV2);
+        byte[] arrayOut = new byte[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUcharUchar args = new ArgumentsUcharUcharUchar();
+                args.inV1 = arrayInV1[i];
+                args.inV2 = arrayInV2[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinUcharUcharUchar" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinUchar2Uchar2Uchar2() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 2, 0x1d3c921d166e22ffl, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 2, 0x1d3c921d166e2300l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinUchar2Uchar2Uchar2(inV1, out);
+            verifyResultsMinUchar2Uchar2Uchar2(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUchar2Uchar2Uchar2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinUchar2Uchar2Uchar2(inV1, out);
+            verifyResultsMinUchar2Uchar2Uchar2(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUchar2Uchar2Uchar2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinUchar2Uchar2Uchar2(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        byte[] arrayInV1 = new byte[INPUTSIZE * 2];
+        inV1.copyTo(arrayInV1);
+        byte[] arrayInV2 = new byte[INPUTSIZE * 2];
+        inV2.copyTo(arrayInV2);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUcharUchar args = new ArgumentsUcharUcharUchar();
+                args.inV1 = arrayInV1[i * 2 + j];
+                args.inV2 = arrayInV2[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinUchar2Uchar2Uchar2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinUchar3Uchar3Uchar3() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 3, 0x4a2de17d66b8690al, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 3, 0x4a2de17d66b8690bl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinUchar3Uchar3Uchar3(inV1, out);
+            verifyResultsMinUchar3Uchar3Uchar3(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUchar3Uchar3Uchar3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinUchar3Uchar3Uchar3(inV1, out);
+            verifyResultsMinUchar3Uchar3Uchar3(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUchar3Uchar3Uchar3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinUchar3Uchar3Uchar3(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        byte[] arrayInV1 = new byte[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        byte[] arrayInV2 = new byte[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUcharUchar args = new ArgumentsUcharUcharUchar();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinUchar3Uchar3Uchar3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinUchar4Uchar4Uchar4() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 4, 0x771f30ddb702af15l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_8, 4, 0x771f30ddb702af16l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinUchar4Uchar4Uchar4(inV1, out);
+            verifyResultsMinUchar4Uchar4Uchar4(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUchar4Uchar4Uchar4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinUchar4Uchar4Uchar4(inV1, out);
+            verifyResultsMinUchar4Uchar4Uchar4(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUchar4Uchar4Uchar4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinUchar4Uchar4Uchar4(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        byte[] arrayInV1 = new byte[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        byte[] arrayInV2 = new byte[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharUcharUchar args = new ArgumentsUcharUcharUchar();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinUchar4Uchar4Uchar4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsShortShortShort {
+        public short inV1;
+        public short inV2;
+        public short out;
+    }
+
+    private void checkMinShortShortShort() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 1, 0x71b08dd3c65bcddel, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 1, 0x71b08dd3c65bcddfl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 1), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinShortShortShort(inV1, out);
+            verifyResultsMinShortShortShort(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinShortShortShort: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinShortShortShort(inV1, out);
+            verifyResultsMinShortShortShort(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinShortShortShort: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinShortShortShort(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        short[] arrayInV1 = new short[INPUTSIZE * 1];
+        inV1.copyTo(arrayInV1);
+        short[] arrayInV2 = new short[INPUTSIZE * 1];
+        inV2.copyTo(arrayInV2);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortShortShort args = new ArgumentsShortShortShort();
+                args.inV1 = arrayInV1[i];
+                args.inV2 = arrayInV2[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinShortShortShort" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinShort2Short2Short2() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 2, 0xe4959a1ecbf1d380l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 2, 0xe4959a1ecbf1d381l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinShort2Short2Short2(inV1, out);
+            verifyResultsMinShort2Short2Short2(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinShort2Short2Short2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinShort2Short2Short2(inV1, out);
+            verifyResultsMinShort2Short2Short2(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinShort2Short2Short2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinShort2Short2Short2(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        short[] arrayInV1 = new short[INPUTSIZE * 2];
+        inV1.copyTo(arrayInV1);
+        short[] arrayInV2 = new short[INPUTSIZE * 2];
+        inV2.copyTo(arrayInV2);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortShortShort args = new ArgumentsShortShortShort();
+                args.inV1 = arrayInV1[i * 2 + j];
+                args.inV2 = arrayInV2[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinShort2Short2Short2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinShort3Short3Short3() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 3, 0x1186e97f1c3c198bl, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 3, 0x1186e97f1c3c198cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinShort3Short3Short3(inV1, out);
+            verifyResultsMinShort3Short3Short3(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinShort3Short3Short3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinShort3Short3Short3(inV1, out);
+            verifyResultsMinShort3Short3Short3(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinShort3Short3Short3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinShort3Short3Short3(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        short[] arrayInV1 = new short[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        short[] arrayInV2 = new short[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortShortShort args = new ArgumentsShortShortShort();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinShort3Short3Short3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinShort4Short4Short4() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 4, 0x3e7838df6c865f96l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_16, 4, 0x3e7838df6c865f97l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinShort4Short4Short4(inV1, out);
+            verifyResultsMinShort4Short4Short4(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinShort4Short4Short4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinShort4Short4Short4(inV1, out);
+            verifyResultsMinShort4Short4Short4(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinShort4Short4Short4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinShort4Short4Short4(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        short[] arrayInV1 = new short[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        short[] arrayInV2 = new short[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortShortShort args = new ArgumentsShortShortShort();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinShort4Short4Short4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUshortUshortUshort {
+        public short inV1;
+        public short inV2;
+        public short out;
+    }
+
+    private void checkMinUshortUshortUshort() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 1, 0xc2eb3387512e77cfl, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 1, 0xc2eb3387512e77d0l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 1), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinUshortUshortUshort(inV1, out);
+            verifyResultsMinUshortUshortUshort(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUshortUshortUshort: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinUshortUshortUshort(inV1, out);
+            verifyResultsMinUshortUshortUshort(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUshortUshortUshort: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinUshortUshortUshort(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        short[] arrayInV1 = new short[INPUTSIZE * 1];
+        inV1.copyTo(arrayInV1);
+        short[] arrayInV2 = new short[INPUTSIZE * 1];
+        inV2.copyTo(arrayInV2);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUshortUshort args = new ArgumentsUshortUshortUshort();
+                args.inV1 = arrayInV1[i];
+                args.inV2 = arrayInV2[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinUshortUshortUshort" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinUshort2Ushort2Ushort2() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 2, 0x98573ebbc511e319l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 2, 0x98573ebbc511e31al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinUshort2Ushort2Ushort2(inV1, out);
+            verifyResultsMinUshort2Ushort2Ushort2(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUshort2Ushort2Ushort2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinUshort2Ushort2Ushort2(inV1, out);
+            verifyResultsMinUshort2Ushort2Ushort2(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUshort2Ushort2Ushort2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinUshort2Ushort2Ushort2(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        short[] arrayInV1 = new short[INPUTSIZE * 2];
+        inV1.copyTo(arrayInV1);
+        short[] arrayInV2 = new short[INPUTSIZE * 2];
+        inV2.copyTo(arrayInV2);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUshortUshort args = new ArgumentsUshortUshortUshort();
+                args.inV1 = arrayInV1[i * 2 + j];
+                args.inV2 = arrayInV2[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinUshort2Ushort2Ushort2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinUshort3Ushort3Ushort3() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 3, 0x1595f09b03867776l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 3, 0x1595f09b03867777l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinUshort3Ushort3Ushort3(inV1, out);
+            verifyResultsMinUshort3Ushort3Ushort3(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUshort3Ushort3Ushort3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinUshort3Ushort3Ushort3(inV1, out);
+            verifyResultsMinUshort3Ushort3Ushort3(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUshort3Ushort3Ushort3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinUshort3Ushort3Ushort3(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        short[] arrayInV1 = new short[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        short[] arrayInV2 = new short[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUshortUshort args = new ArgumentsUshortUshortUshort();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinUshort3Ushort3Ushort3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinUshort4Ushort4Ushort4() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 4, 0x92d4a27a41fb0bd3l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_16, 4, 0x92d4a27a41fb0bd4l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinUshort4Ushort4Ushort4(inV1, out);
+            verifyResultsMinUshort4Ushort4Ushort4(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUshort4Ushort4Ushort4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinUshort4Ushort4Ushort4(inV1, out);
+            verifyResultsMinUshort4Ushort4Ushort4(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUshort4Ushort4Ushort4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinUshort4Ushort4Ushort4(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        short[] arrayInV1 = new short[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        short[] arrayInV2 = new short[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortUshortUshort args = new ArgumentsUshortUshortUshort();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinUshort4Ushort4Ushort4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsIntIntInt {
+        public int inV1;
+        public int inV2;
+        public int out;
+    }
+
+    private void checkMinIntIntInt() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 1, 0x38b24335cda69cd5l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 1, 0x38b24335cda69cd6l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 1), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinIntIntInt(inV1, out);
+            verifyResultsMinIntIntInt(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinIntIntInt: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinIntIntInt(inV1, out);
+            verifyResultsMinIntIntInt(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinIntIntInt: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinIntIntInt(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        int[] arrayInV1 = new int[INPUTSIZE * 1];
+        inV1.copyTo(arrayInV1);
+        int[] arrayInV2 = new int[INPUTSIZE * 1];
+        inV2.copyTo(arrayInV2);
+        int[] arrayOut = new int[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntIntInt args = new ArgumentsIntIntInt();
+                args.inV1 = arrayInV1[i];
+                args.inV2 = arrayInV2[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinIntIntInt" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinInt2Int2Int2() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 2, 0xba635b605676e7a3l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 2, 0xba635b605676e7a4l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinInt2Int2Int2(inV1, out);
+            verifyResultsMinInt2Int2Int2(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinInt2Int2Int2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinInt2Int2Int2(inV1, out);
+            verifyResultsMinInt2Int2Int2(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinInt2Int2Int2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinInt2Int2Int2(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        int[] arrayInV1 = new int[INPUTSIZE * 2];
+        inV1.copyTo(arrayInV1);
+        int[] arrayInV2 = new int[INPUTSIZE * 2];
+        inV2.copyTo(arrayInV2);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntIntInt args = new ArgumentsIntIntInt();
+                args.inV1 = arrayInV1[i * 2 + j];
+                args.inV2 = arrayInV2[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinInt2Int2Int2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinInt3Int3Int3() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 3, 0xe4f086806849fbc6l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 3, 0xe4f086806849fbc7l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinInt3Int3Int3(inV1, out);
+            verifyResultsMinInt3Int3Int3(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinInt3Int3Int3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinInt3Int3Int3(inV1, out);
+            verifyResultsMinInt3Int3Int3(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinInt3Int3Int3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinInt3Int3Int3(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        int[] arrayInV1 = new int[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        int[] arrayInV2 = new int[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntIntInt args = new ArgumentsIntIntInt();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinInt3Int3Int3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinInt4Int4Int4() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 4, 0xf7db1a07a1d0fe9l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 4, 0xf7db1a07a1d0feal, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinInt4Int4Int4(inV1, out);
+            verifyResultsMinInt4Int4Int4(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinInt4Int4Int4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinInt4Int4Int4(inV1, out);
+            verifyResultsMinInt4Int4Int4(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinInt4Int4Int4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinInt4Int4Int4(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        int[] arrayInV1 = new int[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        int[] arrayInV2 = new int[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntIntInt args = new ArgumentsIntIntInt();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinInt4Int4Int4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUintUintUint {
+        public int inV1;
+        public int inV2;
+        public int out;
+    }
+
+    private void checkMinUintUintUint() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 1, 0xb3dbca2d537cf298l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 1, 0xb3dbca2d537cf299l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 1), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinUintUintUint(inV1, out);
+            verifyResultsMinUintUintUint(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUintUintUint: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinUintUintUint(inV1, out);
+            verifyResultsMinUintUintUint(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUintUintUint: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinUintUintUint(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        int[] arrayInV1 = new int[INPUTSIZE * 1];
+        inV1.copyTo(arrayInV1);
+        int[] arrayInV2 = new int[INPUTSIZE * 1];
+        inV2.copyTo(arrayInV2);
+        int[] arrayOut = new int[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUintUint args = new ArgumentsUintUintUint();
+                args.inV1 = arrayInV1[i];
+                args.inV2 = arrayInV2[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinUintUintUint" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinUint2Uint2Uint2() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 2, 0xb8cf8481d731a1eel, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 2, 0xb8cf8481d731a1efl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinUint2Uint2Uint2(inV1, out);
+            verifyResultsMinUint2Uint2Uint2(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUint2Uint2Uint2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinUint2Uint2Uint2(inV1, out);
+            verifyResultsMinUint2Uint2Uint2(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUint2Uint2Uint2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinUint2Uint2Uint2(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        int[] arrayInV1 = new int[INPUTSIZE * 2];
+        inV1.copyTo(arrayInV1);
+        int[] arrayInV2 = new int[INPUTSIZE * 2];
+        inV2.copyTo(arrayInV2);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUintUint args = new ArgumentsUintUintUint();
+                args.inV1 = arrayInV1[i * 2 + j];
+                args.inV2 = arrayInV2[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinUint2Uint2Uint2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinUint3Uint3Uint3() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 3, 0xe2100b4bbe974b3l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 3, 0xe2100b4bbe974b4l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinUint3Uint3Uint3(inV1, out);
+            verifyResultsMinUint3Uint3Uint3(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUint3Uint3Uint3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinUint3Uint3Uint3(inV1, out);
+            verifyResultsMinUint3Uint3Uint3(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUint3Uint3Uint3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinUint3Uint3Uint3(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        int[] arrayInV1 = new int[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        int[] arrayInV2 = new int[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUintUint args = new ArgumentsUintUintUint();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinUint3Uint3Uint3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinUint4Uint4Uint4() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 4, 0x63727ce7a0a14778l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 4, 0x63727ce7a0a14779l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinUint4Uint4Uint4(inV1, out);
+            verifyResultsMinUint4Uint4Uint4(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUint4Uint4Uint4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinUint4Uint4Uint4(inV1, out);
+            verifyResultsMinUint4Uint4Uint4(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUint4Uint4Uint4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinUint4Uint4Uint4(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        int[] arrayInV1 = new int[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        int[] arrayInV2 = new int[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintUintUint args = new ArgumentsUintUintUint();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinUint4Uint4Uint4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsLongLongLong {
+        public long inV1;
+        public long inV2;
+        public long out;
+    }
+
+    private void checkMinLongLongLong() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 1, 0x20ce185251c10eb2l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 1, 0x20ce185251c10eb3l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 1), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinLongLongLong(inV1, out);
+            verifyResultsMinLongLongLong(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinLongLongLong: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinLongLongLong(inV1, out);
+            verifyResultsMinLongLongLong(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinLongLongLong: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinLongLongLong(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        long[] arrayInV1 = new long[INPUTSIZE * 1];
+        inV1.copyTo(arrayInV1);
+        long[] arrayInV2 = new long[INPUTSIZE * 1];
+        inV2.copyTo(arrayInV2);
+        long[] arrayOut = new long[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongLongLong args = new ArgumentsLongLongLong();
+                args.inV1 = arrayInV1[i];
+                args.inV2 = arrayInV2[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinLongLongLong" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinLong2Long2Long2() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 2, 0x2285e00a094676a0l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 2, 0x2285e00a094676a1l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinLong2Long2Long2(inV1, out);
+            verifyResultsMinLong2Long2Long2(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinLong2Long2Long2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinLong2Long2Long2(inV1, out);
+            verifyResultsMinLong2Long2Long2(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinLong2Long2Long2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinLong2Long2Long2(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        long[] arrayInV1 = new long[INPUTSIZE * 2];
+        inV1.copyTo(arrayInV1);
+        long[] arrayInV2 = new long[INPUTSIZE * 2];
+        inV2.copyTo(arrayInV2);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongLongLong args = new ArgumentsLongLongLong();
+                args.inV1 = arrayInV1[i * 2 + j];
+                args.inV2 = arrayInV2[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinLong2Long2Long2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinLong3Long3Long3() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 3, 0x77d75c3cedfe4965l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 3, 0x77d75c3cedfe4966l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinLong3Long3Long3(inV1, out);
+            verifyResultsMinLong3Long3Long3(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinLong3Long3Long3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinLong3Long3Long3(inV1, out);
+            verifyResultsMinLong3Long3Long3(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinLong3Long3Long3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinLong3Long3Long3(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        long[] arrayInV1 = new long[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        long[] arrayInV2 = new long[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongLongLong args = new ArgumentsLongLongLong();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinLong3Long3Long3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinLong4Long4Long4() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 4, 0xcd28d86fd2b61c2al, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.SIGNED_64, 4, 0xcd28d86fd2b61c2bl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinLong4Long4Long4(inV1, out);
+            verifyResultsMinLong4Long4Long4(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinLong4Long4Long4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinLong4Long4Long4(inV1, out);
+            verifyResultsMinLong4Long4Long4(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinLong4Long4Long4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinLong4Long4Long4(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        long[] arrayInV1 = new long[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        long[] arrayInV2 = new long[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongLongLong args = new ArgumentsLongLongLong();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("%d", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("%d", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("%d", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%d", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinLong4Long4Long4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public class ArgumentsUlongUlongUlong {
+        public long inV1;
+        public long inV2;
+        public long out;
+    }
+
+    private void checkMinUlongUlongUlong() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 1, 0x9ea8f1e67008ea67l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 1, 0x9ea8f1e67008ea68l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 1), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinUlongUlongUlong(inV1, out);
+            verifyResultsMinUlongUlongUlong(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUlongUlongUlong: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinUlongUlongUlong(inV1, out);
+            verifyResultsMinUlongUlongUlong(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUlongUlongUlong: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinUlongUlongUlong(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        long[] arrayInV1 = new long[INPUTSIZE * 1];
+        inV1.copyTo(arrayInV1);
+        long[] arrayInV2 = new long[INPUTSIZE * 1];
+        inV2.copyTo(arrayInV2);
+        long[] arrayOut = new long[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUlongUlong args = new ArgumentsUlongUlongUlong();
+                args.inV1 = arrayInV1[i];
+                args.inV2 = arrayInV2[i];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 1 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 1 + j]));
+                    if (args.out != arrayOut[i * 1 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinUlongUlongUlong" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinUlong2Ulong2Ulong2() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 2, 0x26bb4add3110402dl, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 2, 0x26bb4add3110402el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinUlong2Ulong2Ulong2(inV1, out);
+            verifyResultsMinUlong2Ulong2Ulong2(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUlong2Ulong2Ulong2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinUlong2Ulong2Ulong2(inV1, out);
+            verifyResultsMinUlong2Ulong2Ulong2(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUlong2Ulong2Ulong2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinUlong2Ulong2Ulong2(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        long[] arrayInV1 = new long[INPUTSIZE * 2];
+        inV1.copyTo(arrayInV1);
+        long[] arrayInV2 = new long[INPUTSIZE * 2];
+        inV2.copyTo(arrayInV2);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUlongUlong args = new ArgumentsUlongUlongUlong();
+                args.inV1 = arrayInV1[i * 2 + j];
+                args.inV2 = arrayInV2[i * 2 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 2 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 2 + j]));
+                    if (args.out != arrayOut[i * 2 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinUlong2Ulong2Ulong2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinUlong3Ulong3Ulong3() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 3, 0x53ac9a3d815a8638l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 3, 0x53ac9a3d815a8639l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinUlong3Ulong3Ulong3(inV1, out);
+            verifyResultsMinUlong3Ulong3Ulong3(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUlong3Ulong3Ulong3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinUlong3Ulong3Ulong3(inV1, out);
+            verifyResultsMinUlong3Ulong3Ulong3(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUlong3Ulong3Ulong3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinUlong3Ulong3Ulong3(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        long[] arrayInV1 = new long[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        long[] arrayInV2 = new long[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUlongUlong args = new ArgumentsUlongUlongUlong();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinUlong3Ulong3Ulong3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMinUlong4Ulong4Ulong4() {
+        Allocation inV1 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 4, 0x809de99dd1a4cc43l, false);
+        Allocation inV2 = createRandomAllocation(mRS, Element.DataType.UNSIGNED_64, 4, 0x809de99dd1a4cc44l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            script.set_gAllocInV2(inV2);
+            script.forEach_testMinUlong4Ulong4Ulong4(inV1, out);
+            verifyResultsMinUlong4Ulong4Ulong4(inV1, inV2, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUlong4Ulong4Ulong4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV2(inV2);
+            scriptRelaxed.forEach_testMinUlong4Ulong4Ulong4(inV1, out);
+            verifyResultsMinUlong4Ulong4Ulong4(inV1, inV2, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinUlong4Ulong4Ulong4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinUlong4Ulong4Ulong4(Allocation inV1, Allocation inV2, Allocation out, boolean relaxed) {
+        long[] arrayInV1 = new long[INPUTSIZE * 4];
+        inV1.copyTo(arrayInV1);
+        long[] arrayInV2 = new long[INPUTSIZE * 4];
+        inV2.copyTo(arrayInV2);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongUlongUlong args = new ArgumentsUlongUlongUlong();
+                args.inV1 = arrayInV1[i * 4 + j];
+                args.inV2 = arrayInV2[i * 4 + j];
+                // Figure out what the outputs should have been.
+                CoreMathVerifier.computeMin(args);
+                // Validate the outputs.
+                boolean valid = true;
+                if (args.out != arrayOut[i * 4 + j]) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV1: ");
+                    message.append(String.format("0x%x", args.inV1));
+                    message.append("\n");
+                    message.append("Input inV2: ");
+                    message.append(String.format("0x%x", args.inV2));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(String.format("0x%x", args.out));
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("0x%x", arrayOut[i * 4 + j]));
+                    if (args.out != arrayOut[i * 4 + j]) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMinUlong4Ulong4Ulong4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testMin() {
+        checkMinFloatFloatFloat();
+        checkMinFloat2Float2Float2();
+        checkMinFloat3Float3Float3();
+        checkMinFloat4Float4Float4();
+        checkMinCharCharChar();
+        checkMinChar2Char2Char2();
+        checkMinChar3Char3Char3();
+        checkMinChar4Char4Char4();
+        checkMinUcharUcharUchar();
+        checkMinUchar2Uchar2Uchar2();
+        checkMinUchar3Uchar3Uchar3();
+        checkMinUchar4Uchar4Uchar4();
+        checkMinShortShortShort();
+        checkMinShort2Short2Short2();
+        checkMinShort3Short3Short3();
+        checkMinShort4Short4Short4();
+        checkMinUshortUshortUshort();
+        checkMinUshort2Ushort2Ushort2();
+        checkMinUshort3Ushort3Ushort3();
+        checkMinUshort4Ushort4Ushort4();
+        checkMinIntIntInt();
+        checkMinInt2Int2Int2();
+        checkMinInt3Int3Int3();
+        checkMinInt4Int4Int4();
+        checkMinUintUintUint();
+        checkMinUint2Uint2Uint2();
+        checkMinUint3Uint3Uint3();
+        checkMinUint4Uint4Uint4();
+        checkMinLongLongLong();
+        checkMinLong2Long2Long2();
+        checkMinLong3Long3Long3();
+        checkMinLong4Long4Long4();
+        checkMinUlongUlongUlong();
+        checkMinUlong2Ulong2Ulong2();
+        checkMinUlong3Ulong3Ulong3();
+        checkMinUlong4Ulong4Ulong4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestMin.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestMin.rs
new file mode 100644
index 0000000..29a9aeb1
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestMin.rs
@@ -0,0 +1,203 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocIn1;
+
+float __attribute__((kernel)) testMinFloatFloatFloat(float in, unsigned int x) {
+    float in1 = rsGetElementAt_float(gAllocIn1, x);
+    return min(in, in1);
+}
+
+float2 __attribute__((kernel)) testMinFloat2Float2Float2(float2 in, unsigned int x) {
+    float2 in1 = rsGetElementAt_float2(gAllocIn1, x);
+    return min(in, in1);
+}
+
+float3 __attribute__((kernel)) testMinFloat3Float3Float3(float3 in, unsigned int x) {
+    float3 in1 = rsGetElementAt_float3(gAllocIn1, x);
+    return min(in, in1);
+}
+
+float4 __attribute__((kernel)) testMinFloat4Float4Float4(float4 in, unsigned int x) {
+    float4 in1 = rsGetElementAt_float4(gAllocIn1, x);
+    return min(in, in1);
+}
+rs_allocation gAllocInV2;
+
+char __attribute__((kernel)) testMinCharCharChar(char inV1, unsigned int x) {
+    char inV2 = rsGetElementAt_char(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+char2 __attribute__((kernel)) testMinChar2Char2Char2(char2 inV1, unsigned int x) {
+    char2 inV2 = rsGetElementAt_char2(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+char3 __attribute__((kernel)) testMinChar3Char3Char3(char3 inV1, unsigned int x) {
+    char3 inV2 = rsGetElementAt_char3(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+char4 __attribute__((kernel)) testMinChar4Char4Char4(char4 inV1, unsigned int x) {
+    char4 inV2 = rsGetElementAt_char4(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+uchar __attribute__((kernel)) testMinUcharUcharUchar(uchar inV1, unsigned int x) {
+    uchar inV2 = rsGetElementAt_uchar(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+uchar2 __attribute__((kernel)) testMinUchar2Uchar2Uchar2(uchar2 inV1, unsigned int x) {
+    uchar2 inV2 = rsGetElementAt_uchar2(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+uchar3 __attribute__((kernel)) testMinUchar3Uchar3Uchar3(uchar3 inV1, unsigned int x) {
+    uchar3 inV2 = rsGetElementAt_uchar3(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+uchar4 __attribute__((kernel)) testMinUchar4Uchar4Uchar4(uchar4 inV1, unsigned int x) {
+    uchar4 inV2 = rsGetElementAt_uchar4(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+short __attribute__((kernel)) testMinShortShortShort(short inV1, unsigned int x) {
+    short inV2 = rsGetElementAt_short(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+short2 __attribute__((kernel)) testMinShort2Short2Short2(short2 inV1, unsigned int x) {
+    short2 inV2 = rsGetElementAt_short2(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+short3 __attribute__((kernel)) testMinShort3Short3Short3(short3 inV1, unsigned int x) {
+    short3 inV2 = rsGetElementAt_short3(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+short4 __attribute__((kernel)) testMinShort4Short4Short4(short4 inV1, unsigned int x) {
+    short4 inV2 = rsGetElementAt_short4(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+ushort __attribute__((kernel)) testMinUshortUshortUshort(ushort inV1, unsigned int x) {
+    ushort inV2 = rsGetElementAt_ushort(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+ushort2 __attribute__((kernel)) testMinUshort2Ushort2Ushort2(ushort2 inV1, unsigned int x) {
+    ushort2 inV2 = rsGetElementAt_ushort2(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+ushort3 __attribute__((kernel)) testMinUshort3Ushort3Ushort3(ushort3 inV1, unsigned int x) {
+    ushort3 inV2 = rsGetElementAt_ushort3(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+ushort4 __attribute__((kernel)) testMinUshort4Ushort4Ushort4(ushort4 inV1, unsigned int x) {
+    ushort4 inV2 = rsGetElementAt_ushort4(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+int __attribute__((kernel)) testMinIntIntInt(int inV1, unsigned int x) {
+    int inV2 = rsGetElementAt_int(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+int2 __attribute__((kernel)) testMinInt2Int2Int2(int2 inV1, unsigned int x) {
+    int2 inV2 = rsGetElementAt_int2(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+int3 __attribute__((kernel)) testMinInt3Int3Int3(int3 inV1, unsigned int x) {
+    int3 inV2 = rsGetElementAt_int3(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+int4 __attribute__((kernel)) testMinInt4Int4Int4(int4 inV1, unsigned int x) {
+    int4 inV2 = rsGetElementAt_int4(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+uint __attribute__((kernel)) testMinUintUintUint(uint inV1, unsigned int x) {
+    uint inV2 = rsGetElementAt_uint(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+uint2 __attribute__((kernel)) testMinUint2Uint2Uint2(uint2 inV1, unsigned int x) {
+    uint2 inV2 = rsGetElementAt_uint2(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+uint3 __attribute__((kernel)) testMinUint3Uint3Uint3(uint3 inV1, unsigned int x) {
+    uint3 inV2 = rsGetElementAt_uint3(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+uint4 __attribute__((kernel)) testMinUint4Uint4Uint4(uint4 inV1, unsigned int x) {
+    uint4 inV2 = rsGetElementAt_uint4(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+long __attribute__((kernel)) testMinLongLongLong(long inV1, unsigned int x) {
+    long inV2 = rsGetElementAt_long(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+long2 __attribute__((kernel)) testMinLong2Long2Long2(long2 inV1, unsigned int x) {
+    long2 inV2 = rsGetElementAt_long2(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+long3 __attribute__((kernel)) testMinLong3Long3Long3(long3 inV1, unsigned int x) {
+    long3 inV2 = rsGetElementAt_long3(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+long4 __attribute__((kernel)) testMinLong4Long4Long4(long4 inV1, unsigned int x) {
+    long4 inV2 = rsGetElementAt_long4(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+ulong __attribute__((kernel)) testMinUlongUlongUlong(ulong inV1, unsigned int x) {
+    ulong inV2 = rsGetElementAt_ulong(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+ulong2 __attribute__((kernel)) testMinUlong2Ulong2Ulong2(ulong2 inV1, unsigned int x) {
+    ulong2 inV2 = rsGetElementAt_ulong2(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+ulong3 __attribute__((kernel)) testMinUlong3Ulong3Ulong3(ulong3 inV1, unsigned int x) {
+    ulong3 inV2 = rsGetElementAt_ulong3(gAllocInV2, x);
+    return min(inV1, inV2);
+}
+
+ulong4 __attribute__((kernel)) testMinUlong4Ulong4Ulong4(ulong4 inV1, unsigned int x) {
+    ulong4 inV2 = rsGetElementAt_ulong4(gAllocInV2, x);
+    return min(inV1, inV2);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestMinRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestMinRelaxed.rs
new file mode 100644
index 0000000..29a4d89
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestMinRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestMin.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestMix.java b/tests/tests/renderscript/src/android/renderscript/cts/TestMix.java
new file mode 100644
index 0000000..3500e41
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestMix.java
@@ -0,0 +1,606 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestMix extends RSBaseCompute {
+
+    private ScriptC_TestMix script;
+    private ScriptC_TestMixRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestMix(mRS);
+        scriptRelaxed = new ScriptC_TestMixRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloatFloat {
+        public float inStart;
+        public float inStop;
+        public float inAmount;
+        public Target.Floaty out;
+    }
+
+    private void checkMixFloatFloatFloatFloat() {
+        Allocation inStart = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x9f4beff6471d6db1l, false);
+        Allocation inStop = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x6ede0b88b4422e8fl, false);
+        Allocation inAmount = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xc1c14e5d52dc3fe5l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInStop(inStop);
+            script.set_gAllocInAmount(inAmount);
+            script.forEach_testMixFloatFloatFloatFloat(inStart, out);
+            verifyResultsMixFloatFloatFloatFloat(inStart, inStop, inAmount, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixFloatFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInStop(inStop);
+            scriptRelaxed.set_gAllocInAmount(inAmount);
+            scriptRelaxed.forEach_testMixFloatFloatFloatFloat(inStart, out);
+            verifyResultsMixFloatFloatFloatFloat(inStart, inStop, inAmount, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixFloatFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMixFloatFloatFloatFloat(Allocation inStart, Allocation inStop, Allocation inAmount, Allocation out, boolean relaxed) {
+        float[] arrayInStart = new float[INPUTSIZE * 1];
+        inStart.copyTo(arrayInStart);
+        float[] arrayInStop = new float[INPUTSIZE * 1];
+        inStop.copyTo(arrayInStop);
+        float[] arrayInAmount = new float[INPUTSIZE * 1];
+        inAmount.copyTo(arrayInAmount);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloatFloat args = new ArgumentsFloatFloatFloatFloat();
+                args.inStart = arrayInStart[i];
+                args.inStop = arrayInStop[i];
+                args.inAmount = arrayInAmount[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeMix(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inStart: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inStart, Float.floatToRawIntBits(args.inStart), args.inStart));
+                    message.append("\n");
+                    message.append("Input inStop: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inStop, Float.floatToRawIntBits(args.inStop), args.inStop));
+                    message.append("\n");
+                    message.append("Input inAmount: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inAmount, Float.floatToRawIntBits(args.inAmount), args.inAmount));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMixFloatFloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMixFloat2Float2Float2Float2() {
+        Allocation inStart = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x45502e8f0a2d9ce9l, false);
+        Allocation inStop = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xba2b8a035395e837l, false);
+        Allocation inAmount = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xa477d20616942e4dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInStop(inStop);
+            script.set_gAllocInAmount(inAmount);
+            script.forEach_testMixFloat2Float2Float2Float2(inStart, out);
+            verifyResultsMixFloat2Float2Float2Float2(inStart, inStop, inAmount, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixFloat2Float2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInStop(inStop);
+            scriptRelaxed.set_gAllocInAmount(inAmount);
+            scriptRelaxed.forEach_testMixFloat2Float2Float2Float2(inStart, out);
+            verifyResultsMixFloat2Float2Float2Float2(inStart, inStop, inAmount, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixFloat2Float2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMixFloat2Float2Float2Float2(Allocation inStart, Allocation inStop, Allocation inAmount, Allocation out, boolean relaxed) {
+        float[] arrayInStart = new float[INPUTSIZE * 2];
+        inStart.copyTo(arrayInStart);
+        float[] arrayInStop = new float[INPUTSIZE * 2];
+        inStop.copyTo(arrayInStop);
+        float[] arrayInAmount = new float[INPUTSIZE * 2];
+        inAmount.copyTo(arrayInAmount);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloatFloat args = new ArgumentsFloatFloatFloatFloat();
+                args.inStart = arrayInStart[i * 2 + j];
+                args.inStop = arrayInStop[i * 2 + j];
+                args.inAmount = arrayInAmount[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeMix(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inStart: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inStart, Float.floatToRawIntBits(args.inStart), args.inStart));
+                    message.append("\n");
+                    message.append("Input inStop: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inStop, Float.floatToRawIntBits(args.inStop), args.inStop));
+                    message.append("\n");
+                    message.append("Input inAmount: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inAmount, Float.floatToRawIntBits(args.inAmount), args.inAmount));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMixFloat2Float2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMixFloat3Float3Float3Float3() {
+        Allocation inStart = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xeb4701726b009c5l, false);
+        Allocation inStop = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x9b21f6b3249ee4cbl, false);
+        Allocation inAmount = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x784ed3e2e07c7741l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInStop(inStop);
+            script.set_gAllocInAmount(inAmount);
+            script.forEach_testMixFloat3Float3Float3Float3(inStart, out);
+            verifyResultsMixFloat3Float3Float3Float3(inStart, inStop, inAmount, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixFloat3Float3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInStop(inStop);
+            scriptRelaxed.set_gAllocInAmount(inAmount);
+            scriptRelaxed.forEach_testMixFloat3Float3Float3Float3(inStart, out);
+            verifyResultsMixFloat3Float3Float3Float3(inStart, inStop, inAmount, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixFloat3Float3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMixFloat3Float3Float3Float3(Allocation inStart, Allocation inStop, Allocation inAmount, Allocation out, boolean relaxed) {
+        float[] arrayInStart = new float[INPUTSIZE * 4];
+        inStart.copyTo(arrayInStart);
+        float[] arrayInStop = new float[INPUTSIZE * 4];
+        inStop.copyTo(arrayInStop);
+        float[] arrayInAmount = new float[INPUTSIZE * 4];
+        inAmount.copyTo(arrayInAmount);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloatFloat args = new ArgumentsFloatFloatFloatFloat();
+                args.inStart = arrayInStart[i * 4 + j];
+                args.inStop = arrayInStop[i * 4 + j];
+                args.inAmount = arrayInAmount[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeMix(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inStart: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inStart, Float.floatToRawIntBits(args.inStart), args.inStart));
+                    message.append("\n");
+                    message.append("Input inStop: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inStop, Float.floatToRawIntBits(args.inStop), args.inStop));
+                    message.append("\n");
+                    message.append("Input inAmount: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inAmount, Float.floatToRawIntBits(args.inAmount), args.inAmount));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMixFloat3Float3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMixFloat4Float4Float4Float4() {
+        Allocation inStart = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xd818b19f433276a1l, false);
+        Allocation inStop = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x7c186362f5a7e15fl, false);
+        Allocation inAmount = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x4c25d5bfaa64c035l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInStop(inStop);
+            script.set_gAllocInAmount(inAmount);
+            script.forEach_testMixFloat4Float4Float4Float4(inStart, out);
+            verifyResultsMixFloat4Float4Float4Float4(inStart, inStop, inAmount, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixFloat4Float4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInStop(inStop);
+            scriptRelaxed.set_gAllocInAmount(inAmount);
+            scriptRelaxed.forEach_testMixFloat4Float4Float4Float4(inStart, out);
+            verifyResultsMixFloat4Float4Float4Float4(inStart, inStop, inAmount, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixFloat4Float4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMixFloat4Float4Float4Float4(Allocation inStart, Allocation inStop, Allocation inAmount, Allocation out, boolean relaxed) {
+        float[] arrayInStart = new float[INPUTSIZE * 4];
+        inStart.copyTo(arrayInStart);
+        float[] arrayInStop = new float[INPUTSIZE * 4];
+        inStop.copyTo(arrayInStop);
+        float[] arrayInAmount = new float[INPUTSIZE * 4];
+        inAmount.copyTo(arrayInAmount);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloatFloat args = new ArgumentsFloatFloatFloatFloat();
+                args.inStart = arrayInStart[i * 4 + j];
+                args.inStop = arrayInStop[i * 4 + j];
+                args.inAmount = arrayInAmount[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeMix(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inStart: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inStart, Float.floatToRawIntBits(args.inStart), args.inStart));
+                    message.append("\n");
+                    message.append("Input inStop: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inStop, Float.floatToRawIntBits(args.inStop), args.inStop));
+                    message.append("\n");
+                    message.append("Input inAmount: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inAmount, Float.floatToRawIntBits(args.inAmount), args.inAmount));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMixFloat4Float4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMixFloat2Float2FloatFloat2() {
+        Allocation inStart = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xf811b2d52bd1d7c3l, false);
+        Allocation inStop = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x17a127e13c8dd1c5l, false);
+        Allocation inAmount = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xaaf909cdbd2a10ebl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInStop(inStop);
+            script.set_gAllocInAmount(inAmount);
+            script.forEach_testMixFloat2Float2FloatFloat2(inStart, out);
+            verifyResultsMixFloat2Float2FloatFloat2(inStart, inStop, inAmount, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixFloat2Float2FloatFloat2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInStop(inStop);
+            scriptRelaxed.set_gAllocInAmount(inAmount);
+            scriptRelaxed.forEach_testMixFloat2Float2FloatFloat2(inStart, out);
+            verifyResultsMixFloat2Float2FloatFloat2(inStart, inStop, inAmount, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixFloat2Float2FloatFloat2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMixFloat2Float2FloatFloat2(Allocation inStart, Allocation inStop, Allocation inAmount, Allocation out, boolean relaxed) {
+        float[] arrayInStart = new float[INPUTSIZE * 2];
+        inStart.copyTo(arrayInStart);
+        float[] arrayInStop = new float[INPUTSIZE * 2];
+        inStop.copyTo(arrayInStop);
+        float[] arrayInAmount = new float[INPUTSIZE * 1];
+        inAmount.copyTo(arrayInAmount);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloatFloat args = new ArgumentsFloatFloatFloatFloat();
+                args.inStart = arrayInStart[i * 2 + j];
+                args.inStop = arrayInStop[i * 2 + j];
+                args.inAmount = arrayInAmount[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeMix(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inStart: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inStart, Float.floatToRawIntBits(args.inStart), args.inStart));
+                    message.append("\n");
+                    message.append("Input inStop: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inStop, Float.floatToRawIntBits(args.inStop), args.inStop));
+                    message.append("\n");
+                    message.append("Input inAmount: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inAmount, Float.floatToRawIntBits(args.inAmount), args.inAmount));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMixFloat2Float2FloatFloat2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMixFloat3Float3FloatFloat3() {
+        Allocation inStart = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xae7aff441b20fa80l, false);
+        Allocation inStop = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xe64a4d60d6f4de7cl, false);
+        Allocation inAmount = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x4ea8e06fef74e6aal, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInStop(inStop);
+            script.set_gAllocInAmount(inAmount);
+            script.forEach_testMixFloat3Float3FloatFloat3(inStart, out);
+            verifyResultsMixFloat3Float3FloatFloat3(inStart, inStop, inAmount, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixFloat3Float3FloatFloat3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInStop(inStop);
+            scriptRelaxed.set_gAllocInAmount(inAmount);
+            scriptRelaxed.forEach_testMixFloat3Float3FloatFloat3(inStart, out);
+            verifyResultsMixFloat3Float3FloatFloat3(inStart, inStop, inAmount, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixFloat3Float3FloatFloat3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMixFloat3Float3FloatFloat3(Allocation inStart, Allocation inStop, Allocation inAmount, Allocation out, boolean relaxed) {
+        float[] arrayInStart = new float[INPUTSIZE * 4];
+        inStart.copyTo(arrayInStart);
+        float[] arrayInStop = new float[INPUTSIZE * 4];
+        inStop.copyTo(arrayInStop);
+        float[] arrayInAmount = new float[INPUTSIZE * 1];
+        inAmount.copyTo(arrayInAmount);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloatFloat args = new ArgumentsFloatFloatFloatFloat();
+                args.inStart = arrayInStart[i * 4 + j];
+                args.inStop = arrayInStop[i * 4 + j];
+                args.inAmount = arrayInAmount[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeMix(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inStart: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inStart, Float.floatToRawIntBits(args.inStart), args.inStart));
+                    message.append("\n");
+                    message.append("Input inStop: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inStop, Float.floatToRawIntBits(args.inStop), args.inStop));
+                    message.append("\n");
+                    message.append("Input inAmount: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inAmount, Float.floatToRawIntBits(args.inAmount), args.inAmount));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMixFloat3Float3FloatFloat3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkMixFloat4Float4FloatFloat4() {
+        Allocation inStart = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x64e44bb30a701d3dl, false);
+        Allocation inStop = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xb4f372e0715beb33l, false);
+        Allocation inAmount = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xf258b71221bfbc69l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInStop(inStop);
+            script.set_gAllocInAmount(inAmount);
+            script.forEach_testMixFloat4Float4FloatFloat4(inStart, out);
+            verifyResultsMixFloat4Float4FloatFloat4(inStart, inStop, inAmount, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixFloat4Float4FloatFloat4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInStop(inStop);
+            scriptRelaxed.set_gAllocInAmount(inAmount);
+            scriptRelaxed.forEach_testMixFloat4Float4FloatFloat4(inStart, out);
+            verifyResultsMixFloat4Float4FloatFloat4(inStart, inStop, inAmount, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixFloat4Float4FloatFloat4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMixFloat4Float4FloatFloat4(Allocation inStart, Allocation inStop, Allocation inAmount, Allocation out, boolean relaxed) {
+        float[] arrayInStart = new float[INPUTSIZE * 4];
+        inStart.copyTo(arrayInStart);
+        float[] arrayInStop = new float[INPUTSIZE * 4];
+        inStop.copyTo(arrayInStop);
+        float[] arrayInAmount = new float[INPUTSIZE * 1];
+        inAmount.copyTo(arrayInAmount);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloatFloat args = new ArgumentsFloatFloatFloatFloat();
+                args.inStart = arrayInStart[i * 4 + j];
+                args.inStop = arrayInStop[i * 4 + j];
+                args.inAmount = arrayInAmount[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeMix(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inStart: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inStart, Float.floatToRawIntBits(args.inStart), args.inStart));
+                    message.append("\n");
+                    message.append("Input inStop: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inStop, Float.floatToRawIntBits(args.inStop), args.inStop));
+                    message.append("\n");
+                    message.append("Input inAmount: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inAmount, Float.floatToRawIntBits(args.inAmount), args.inAmount));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkMixFloat4Float4FloatFloat4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testMix() {
+        checkMixFloatFloatFloatFloat();
+        checkMixFloat2Float2Float2Float2();
+        checkMixFloat3Float3Float3Float3();
+        checkMixFloat4Float4Float4Float4();
+        checkMixFloat2Float2FloatFloat2();
+        checkMixFloat3Float3FloatFloat3();
+        checkMixFloat4Float4FloatFloat4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestMix.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestMix.rs
new file mode 100644
index 0000000..c2ebcb3
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestMix.rs
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInStop;
+rs_allocation gAllocInAmount;
+
+float __attribute__((kernel)) testMixFloatFloatFloatFloat(float inStart, unsigned int x) {
+    float inStop = rsGetElementAt_float(gAllocInStop, x);
+    float inAmount = rsGetElementAt_float(gAllocInAmount, x);
+    return mix(inStart, inStop, inAmount);
+}
+
+float2 __attribute__((kernel)) testMixFloat2Float2Float2Float2(float2 inStart, unsigned int x) {
+    float2 inStop = rsGetElementAt_float2(gAllocInStop, x);
+    float2 inAmount = rsGetElementAt_float2(gAllocInAmount, x);
+    return mix(inStart, inStop, inAmount);
+}
+
+float3 __attribute__((kernel)) testMixFloat3Float3Float3Float3(float3 inStart, unsigned int x) {
+    float3 inStop = rsGetElementAt_float3(gAllocInStop, x);
+    float3 inAmount = rsGetElementAt_float3(gAllocInAmount, x);
+    return mix(inStart, inStop, inAmount);
+}
+
+float4 __attribute__((kernel)) testMixFloat4Float4Float4Float4(float4 inStart, unsigned int x) {
+    float4 inStop = rsGetElementAt_float4(gAllocInStop, x);
+    float4 inAmount = rsGetElementAt_float4(gAllocInAmount, x);
+    return mix(inStart, inStop, inAmount);
+}
+
+float2 __attribute__((kernel)) testMixFloat2Float2FloatFloat2(float2 inStart, unsigned int x) {
+    float2 inStop = rsGetElementAt_float2(gAllocInStop, x);
+    float inAmount = rsGetElementAt_float(gAllocInAmount, x);
+    return mix(inStart, inStop, inAmount);
+}
+
+float3 __attribute__((kernel)) testMixFloat3Float3FloatFloat3(float3 inStart, unsigned int x) {
+    float3 inStop = rsGetElementAt_float3(gAllocInStop, x);
+    float inAmount = rsGetElementAt_float(gAllocInAmount, x);
+    return mix(inStart, inStop, inAmount);
+}
+
+float4 __attribute__((kernel)) testMixFloat4Float4FloatFloat4(float4 inStart, unsigned int x) {
+    float4 inStop = rsGetElementAt_float4(gAllocInStop, x);
+    float inAmount = rsGetElementAt_float(gAllocInAmount, x);
+    return mix(inStart, inStop, inAmount);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestMixRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestMixRelaxed.rs
new file mode 100644
index 0000000..6b59e70
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestMixRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestMix.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestModf.java b/tests/tests/renderscript/src/android/renderscript/cts/TestModf.java
new file mode 100644
index 0000000..25d7765
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestModf.java
@@ -0,0 +1,361 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestModf extends RSBaseCompute {
+
+    private ScriptC_TestModf script;
+    private ScriptC_TestModfRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestModf(mRS);
+        scriptRelaxed = new ScriptC_TestModfRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float inX;
+        public Target.Floaty outIret;
+        public Target.Floaty out;
+    }
+
+    private void checkModfFloatFloatFloat() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xd655dc05ccaef47l, false);
+        try {
+            Allocation outIret = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocOutIret(outIret);
+            script.forEach_testModfFloatFloatFloat(inX, out);
+            verifyResultsModfFloatFloatFloat(inX, outIret, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testModfFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation outIret = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutIret(outIret);
+            scriptRelaxed.forEach_testModfFloatFloatFloat(inX, out);
+            verifyResultsModfFloatFloatFloat(inX, outIret, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testModfFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsModfFloatFloatFloat(Allocation inX, Allocation outIret, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 1];
+        inX.copyTo(arrayInX);
+        float[] arrayOutIret = new float[INPUTSIZE * 1];
+        outIret.copyTo(arrayOutIret);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeModf(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outIret.couldBe(arrayOutIret[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Expected output outIret: ");
+                    message.append(args.outIret.toString());
+                    message.append("\n");
+                    message.append("Actual   output outIret: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOutIret[i * 1 + j], Float.floatToRawIntBits(arrayOutIret[i * 1 + j]), arrayOutIret[i * 1 + j]));
+                    if (!args.outIret.couldBe(arrayOutIret[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkModfFloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkModfFloat2Float2Float2() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x2a1dc519fa163061l, false);
+        try {
+            Allocation outIret = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocOutIret(outIret);
+            script.forEach_testModfFloat2Float2Float2(inX, out);
+            verifyResultsModfFloat2Float2Float2(inX, outIret, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testModfFloat2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation outIret = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutIret(outIret);
+            scriptRelaxed.forEach_testModfFloat2Float2Float2(inX, out);
+            verifyResultsModfFloat2Float2Float2(inX, outIret, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testModfFloat2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsModfFloat2Float2Float2(Allocation inX, Allocation outIret, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 2];
+        inX.copyTo(arrayInX);
+        float[] arrayOutIret = new float[INPUTSIZE * 2];
+        outIret.copyTo(arrayOutIret);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeModf(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outIret.couldBe(arrayOutIret[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Expected output outIret: ");
+                    message.append(args.outIret.toString());
+                    message.append("\n");
+                    message.append("Actual   output outIret: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOutIret[i * 2 + j], Float.floatToRawIntBits(arrayOutIret[i * 2 + j]), arrayOutIret[i * 2 + j]));
+                    if (!args.outIret.couldBe(arrayOutIret[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkModfFloat2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkModfFloat3Float3Float3() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x7e82a339fbf43202l, false);
+        try {
+            Allocation outIret = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocOutIret(outIret);
+            script.forEach_testModfFloat3Float3Float3(inX, out);
+            verifyResultsModfFloat3Float3Float3(inX, outIret, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testModfFloat3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation outIret = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutIret(outIret);
+            scriptRelaxed.forEach_testModfFloat3Float3Float3(inX, out);
+            verifyResultsModfFloat3Float3Float3(inX, outIret, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testModfFloat3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsModfFloat3Float3Float3(Allocation inX, Allocation outIret, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayOutIret = new float[INPUTSIZE * 4];
+        outIret.copyTo(arrayOutIret);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeModf(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outIret.couldBe(arrayOutIret[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Expected output outIret: ");
+                    message.append(args.outIret.toString());
+                    message.append("\n");
+                    message.append("Actual   output outIret: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOutIret[i * 4 + j], Float.floatToRawIntBits(arrayOutIret[i * 4 + j]), arrayOutIret[i * 4 + j]));
+                    if (!args.outIret.couldBe(arrayOutIret[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkModfFloat3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkModfFloat4Float4Float4() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xd2e78159fdd233a3l, false);
+        try {
+            Allocation outIret = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocOutIret(outIret);
+            script.forEach_testModfFloat4Float4Float4(inX, out);
+            verifyResultsModfFloat4Float4Float4(inX, outIret, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testModfFloat4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation outIret = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutIret(outIret);
+            scriptRelaxed.forEach_testModfFloat4Float4Float4(inX, out);
+            verifyResultsModfFloat4Float4Float4(inX, outIret, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testModfFloat4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsModfFloat4Float4Float4(Allocation inX, Allocation outIret, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayOutIret = new float[INPUTSIZE * 4];
+        outIret.copyTo(arrayOutIret);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeModf(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outIret.couldBe(arrayOutIret[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Expected output outIret: ");
+                    message.append(args.outIret.toString());
+                    message.append("\n");
+                    message.append("Actual   output outIret: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOutIret[i * 4 + j], Float.floatToRawIntBits(arrayOutIret[i * 4 + j]), arrayOutIret[i * 4 + j]));
+                    if (!args.outIret.couldBe(arrayOutIret[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkModfFloat4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testModf() {
+        checkModfFloatFloatFloat();
+        checkModfFloat2Float2Float2();
+        checkModfFloat3Float3Float3();
+        checkModfFloat4Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestModf.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestModf.rs
new file mode 100644
index 0000000..be10983
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestModf.rs
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocOutIret;
+
+float __attribute__((kernel)) testModfFloatFloatFloat(float inX, unsigned int x) {
+    float outIret = 0;
+    float out = modf(inX, &outIret);
+    rsSetElementAt_float(gAllocOutIret, outIret, x);
+    return out;
+}
+
+float2 __attribute__((kernel)) testModfFloat2Float2Float2(float2 inX, unsigned int x) {
+    float2 outIret = 0;
+    float2 out = modf(inX, &outIret);
+    rsSetElementAt_float2(gAllocOutIret, outIret, x);
+    return out;
+}
+
+float3 __attribute__((kernel)) testModfFloat3Float3Float3(float3 inX, unsigned int x) {
+    float3 outIret = 0;
+    float3 out = modf(inX, &outIret);
+    rsSetElementAt_float3(gAllocOutIret, outIret, x);
+    return out;
+}
+
+float4 __attribute__((kernel)) testModfFloat4Float4Float4(float4 inX, unsigned int x) {
+    float4 outIret = 0;
+    float4 out = modf(inX, &outIret);
+    rsSetElementAt_float4(gAllocOutIret, outIret, x);
+    return out;
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestModfRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestModfRelaxed.rs
new file mode 100644
index 0000000..4c9cd9a
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestModfRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestModf.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNan.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNan.java
new file mode 100644
index 0000000..1be946d
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNan.java
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNan extends RSBaseCompute {
+
+    private ScriptC_TestNan script;
+    private ScriptC_TestNanRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNan(mRS);
+        scriptRelaxed = new ScriptC_TestNanRelaxed(mRS);
+    }
+
+    public class ArgumentsUintFloat {
+        public int in;
+        public Target.Floaty out;
+    }
+
+    private void checkNanUintFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.UNSIGNED_32, 1, 0x757e939c0e627774l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNanUintFloat(in, out);
+            verifyResultsNanUintFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNanUintFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNanUintFloat(in, out);
+            verifyResultsNanUintFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNanUintFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNanUintFloat(Allocation in, Allocation out, boolean relaxed) {
+        int[] arrayIn = new int[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintFloat args = new ArgumentsUintFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("0x%x", args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNanUintFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNan() {
+        checkNanUintFloat();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNan.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNan.rs
new file mode 100644
index 0000000..bb434d6
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNan.rs
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNanUintFloat(uint in) {
+    return nan(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNanRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNanRelaxed.rs
new file mode 100644
index 0000000..fc7b9eb
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNanRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNan.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcos.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcos.java
new file mode 100644
index 0000000..430cf59
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcos.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeAcos extends RSBaseCompute {
+
+    private ScriptC_TestNativeAcos script;
+    private ScriptC_TestNativeAcosRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeAcos(mRS);
+        scriptRelaxed = new ScriptC_TestNativeAcosRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeAcosFloatFloat() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x7749aa14657f3d94l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeAcosFloatFloat(inV, out);
+            verifyResultsNativeAcosFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcosFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAcosFloatFloat(inV, out);
+            verifyResultsNativeAcosFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcosFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAcosFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAcos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAcosFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAcosFloat2Float2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x92e82297d87e02d8l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeAcosFloat2Float2(inV, out);
+            verifyResultsNativeAcosFloat2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcosFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAcosFloat2Float2(inV, out);
+            verifyResultsNativeAcosFloat2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcosFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAcosFloat2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAcos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAcosFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAcosFloat3Float3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x92e9ebb2ce9923b6l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeAcosFloat3Float3(inV, out);
+            verifyResultsNativeAcosFloat3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcosFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAcosFloat3Float3(inV, out);
+            verifyResultsNativeAcosFloat3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcosFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAcosFloat3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAcos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAcosFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAcosFloat4Float4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x92ebb4cdc4b44494l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeAcosFloat4Float4(inV, out);
+            verifyResultsNativeAcosFloat4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcosFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAcosFloat4Float4(inV, out);
+            verifyResultsNativeAcosFloat4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcosFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAcosFloat4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAcos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAcosFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeAcos() {
+        checkNativeAcosFloatFloat();
+        checkNativeAcosFloat2Float2();
+        checkNativeAcosFloat3Float3();
+        checkNativeAcosFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcos.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcos.rs
new file mode 100644
index 0000000..2419c0e
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcos.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeAcosFloatFloat(float inV) {
+    return native_acos(inV);
+}
+
+float2 __attribute__((kernel)) testNativeAcosFloat2Float2(float2 inV) {
+    return native_acos(inV);
+}
+
+float3 __attribute__((kernel)) testNativeAcosFloat3Float3(float3 inV) {
+    return native_acos(inV);
+}
+
+float4 __attribute__((kernel)) testNativeAcosFloat4Float4(float4 inV) {
+    return native_acos(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcosRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcosRelaxed.rs
new file mode 100644
index 0000000..01a9de2
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcosRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeAcos.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcosh.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcosh.java
new file mode 100644
index 0000000..d4a840a
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcosh.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeAcosh extends RSBaseCompute {
+
+    private ScriptC_TestNativeAcosh script;
+    private ScriptC_TestNativeAcoshRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeAcosh(mRS);
+        scriptRelaxed = new ScriptC_TestNativeAcoshRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeAcoshFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x332857238c9c505cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeAcoshFloatFloat(in, out);
+            verifyResultsNativeAcoshFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcoshFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAcoshFloatFloat(in, out);
+            verifyResultsNativeAcoshFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcoshFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAcoshFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAcosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAcoshFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAcoshFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x7e5c81be4638e398l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeAcoshFloat2Float2(in, out);
+            verifyResultsNativeAcoshFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcoshFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAcoshFloat2Float2(in, out);
+            verifyResultsNativeAcoshFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcoshFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAcoshFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAcosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAcoshFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAcoshFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x7e5c8c5fa53f7932l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeAcoshFloat3Float3(in, out);
+            verifyResultsNativeAcoshFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcoshFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAcoshFloat3Float3(in, out);
+            verifyResultsNativeAcoshFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcoshFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAcoshFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAcosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAcoshFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAcoshFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x7e5c970104460eccl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeAcoshFloat4Float4(in, out);
+            verifyResultsNativeAcoshFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcoshFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAcoshFloat4Float4(in, out);
+            verifyResultsNativeAcoshFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcoshFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAcoshFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAcosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAcoshFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeAcosh() {
+        checkNativeAcoshFloatFloat();
+        checkNativeAcoshFloat2Float2();
+        checkNativeAcoshFloat3Float3();
+        checkNativeAcoshFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcosh.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcosh.rs
new file mode 100644
index 0000000..370f4ed
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcosh.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeAcoshFloatFloat(float in) {
+    return native_acosh(in);
+}
+
+float2 __attribute__((kernel)) testNativeAcoshFloat2Float2(float2 in) {
+    return native_acosh(in);
+}
+
+float3 __attribute__((kernel)) testNativeAcoshFloat3Float3(float3 in) {
+    return native_acosh(in);
+}
+
+float4 __attribute__((kernel)) testNativeAcoshFloat4Float4(float4 in) {
+    return native_acosh(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcoshRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcoshRelaxed.rs
new file mode 100644
index 0000000..9ea7b88
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcoshRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeAcosh.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcospi.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcospi.java
new file mode 100644
index 0000000..187b787
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcospi.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeAcospi extends RSBaseCompute {
+
+    private ScriptC_TestNativeAcospi script;
+    private ScriptC_TestNativeAcospiRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeAcospi(mRS);
+        scriptRelaxed = new ScriptC_TestNativeAcospiRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeAcospiFloatFloat() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xdcf67f5599c7d8ffl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeAcospiFloatFloat(inV, out);
+            verifyResultsNativeAcospiFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcospiFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAcospiFloatFloat(inV, out);
+            verifyResultsNativeAcospiFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcospiFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAcospiFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAcospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAcospiFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAcospiFloat2Float2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xf038668a78e88aabl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeAcospiFloat2Float2(inV, out);
+            verifyResultsNativeAcospiFloat2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcospiFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAcospiFloat2Float2(inV, out);
+            verifyResultsNativeAcospiFloat2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcospiFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAcospiFloat2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAcospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAcospiFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAcospiFloat3Float3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xf03a2fa56f03ab89l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeAcospiFloat3Float3(inV, out);
+            verifyResultsNativeAcospiFloat3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcospiFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAcospiFloat3Float3(inV, out);
+            verifyResultsNativeAcospiFloat3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcospiFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAcospiFloat3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAcospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAcospiFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAcospiFloat4Float4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xf03bf8c0651ecc67l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeAcospiFloat4Float4(inV, out);
+            verifyResultsNativeAcospiFloat4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcospiFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAcospiFloat4Float4(inV, out);
+            verifyResultsNativeAcospiFloat4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcospiFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAcospiFloat4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAcospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAcospiFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeAcospi() {
+        checkNativeAcospiFloatFloat();
+        checkNativeAcospiFloat2Float2();
+        checkNativeAcospiFloat3Float3();
+        checkNativeAcospiFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcospi.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcospi.rs
new file mode 100644
index 0000000..d9d4ae5
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcospi.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeAcospiFloatFloat(float inV) {
+    return native_acospi(inV);
+}
+
+float2 __attribute__((kernel)) testNativeAcospiFloat2Float2(float2 inV) {
+    return native_acospi(inV);
+}
+
+float3 __attribute__((kernel)) testNativeAcospiFloat3Float3(float3 inV) {
+    return native_acospi(inV);
+}
+
+float4 __attribute__((kernel)) testNativeAcospiFloat4Float4(float4 inV) {
+    return native_acospi(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcospiRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcospiRelaxed.rs
new file mode 100644
index 0000000..ff6025e
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAcospiRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeAcospi.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsin.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsin.java
new file mode 100644
index 0000000..b9f61a6
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsin.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeAsin extends RSBaseCompute {
+
+    private ScriptC_TestNativeAsin script;
+    private ScriptC_TestNativeAsinRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeAsin(mRS);
+        scriptRelaxed = new ScriptC_TestNativeAsinRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeAsinFloatFloat() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x1167d6d8d3e5bc7l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeAsinFloatFloat(inV, out);
+            verifyResultsNativeAsinFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAsinFloatFloat(inV, out);
+            verifyResultsNativeAsinFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAsinFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAsin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAsinFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAsinFloat2Float2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xdb4aa187ebdf2133l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeAsinFloat2Float2(inV, out);
+            verifyResultsNativeAsinFloat2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAsinFloat2Float2(inV, out);
+            verifyResultsNativeAsinFloat2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAsinFloat2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAsin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAsinFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAsinFloat3Float3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xdb4c6aa2e1fa4211l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeAsinFloat3Float3(inV, out);
+            verifyResultsNativeAsinFloat3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAsinFloat3Float3(inV, out);
+            verifyResultsNativeAsinFloat3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAsinFloat3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAsin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAsinFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAsinFloat4Float4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xdb4e33bdd81562efl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeAsinFloat4Float4(inV, out);
+            verifyResultsNativeAsinFloat4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAsinFloat4Float4(inV, out);
+            verifyResultsNativeAsinFloat4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAsinFloat4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAsin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAsinFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeAsin() {
+        checkNativeAsinFloatFloat();
+        checkNativeAsinFloat2Float2();
+        checkNativeAsinFloat3Float3();
+        checkNativeAsinFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsin.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsin.rs
new file mode 100644
index 0000000..28b8173
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsin.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeAsinFloatFloat(float inV) {
+    return native_asin(inV);
+}
+
+float2 __attribute__((kernel)) testNativeAsinFloat2Float2(float2 inV) {
+    return native_asin(inV);
+}
+
+float3 __attribute__((kernel)) testNativeAsinFloat3Float3(float3 inV) {
+    return native_asin(inV);
+}
+
+float4 __attribute__((kernel)) testNativeAsinFloat4Float4(float4 inV) {
+    return native_asin(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsinRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsinRelaxed.rs
new file mode 100644
index 0000000..9d04b24
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsinRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeAsin.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsinh.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsinh.java
new file mode 100644
index 0000000..f8382a8
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsinh.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeAsinh extends RSBaseCompute {
+
+    private ScriptC_TestNativeAsinh script;
+    private ScriptC_TestNativeAsinhRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeAsinh(mRS);
+        scriptRelaxed = new ScriptC_TestNativeAsinhRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeAsinhFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xbcf52a7cb45b6e8fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeAsinhFloatFloat(in, out);
+            verifyResultsNativeAsinhFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinhFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAsinhFloatFloat(in, out);
+            verifyResultsNativeAsinhFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinhFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAsinhFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAsinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAsinhFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAsinhFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xc6bf00ae599a01f3l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeAsinhFloat2Float2(in, out);
+            verifyResultsNativeAsinhFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinhFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAsinhFloat2Float2(in, out);
+            verifyResultsNativeAsinhFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinhFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAsinhFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAsinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAsinhFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAsinhFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xc6bf0b4fb8a0978dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeAsinhFloat3Float3(in, out);
+            verifyResultsNativeAsinhFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinhFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAsinhFloat3Float3(in, out);
+            verifyResultsNativeAsinhFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinhFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAsinhFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAsinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAsinhFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAsinhFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xc6bf15f117a72d27l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeAsinhFloat4Float4(in, out);
+            verifyResultsNativeAsinhFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinhFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAsinhFloat4Float4(in, out);
+            verifyResultsNativeAsinhFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinhFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAsinhFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAsinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAsinhFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeAsinh() {
+        checkNativeAsinhFloatFloat();
+        checkNativeAsinhFloat2Float2();
+        checkNativeAsinhFloat3Float3();
+        checkNativeAsinhFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsinh.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsinh.rs
new file mode 100644
index 0000000..2c40a7a
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsinh.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeAsinhFloatFloat(float in) {
+    return native_asinh(in);
+}
+
+float2 __attribute__((kernel)) testNativeAsinhFloat2Float2(float2 in) {
+    return native_asinh(in);
+}
+
+float3 __attribute__((kernel)) testNativeAsinhFloat3Float3(float3 in) {
+    return native_asinh(in);
+}
+
+float4 __attribute__((kernel)) testNativeAsinhFloat4Float4(float4 in) {
+    return native_asinh(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsinhRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsinhRelaxed.rs
new file mode 100644
index 0000000..1155084
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsinhRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeAsinh.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsinpi.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsinpi.java
new file mode 100644
index 0000000..e0029b7
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsinpi.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeAsinpi extends RSBaseCompute {
+
+    private ScriptC_TestNativeAsinpi script;
+    private ScriptC_TestNativeAsinpiRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeAsinpi(mRS);
+        scriptRelaxed = new ScriptC_TestNativeAsinpiRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeAsinpiFloatFloat() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x2558fe45ad28f75al, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeAsinpiFloatFloat(inV, out);
+            verifyResultsNativeAsinpiFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinpiFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAsinpiFloatFloat(inV, out);
+            verifyResultsNativeAsinpiFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinpiFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAsinpiFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAsinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAsinpiFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAsinpiFloat2Float2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xbf9f3a86715cc9eel, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeAsinpiFloat2Float2(inV, out);
+            verifyResultsNativeAsinpiFloat2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinpiFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAsinpiFloat2Float2(inV, out);
+            verifyResultsNativeAsinpiFloat2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinpiFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAsinpiFloat2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAsinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAsinpiFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAsinpiFloat3Float3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xbfa103a16777eaccl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeAsinpiFloat3Float3(inV, out);
+            verifyResultsNativeAsinpiFloat3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinpiFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAsinpiFloat3Float3(inV, out);
+            verifyResultsNativeAsinpiFloat3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinpiFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAsinpiFloat3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAsinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAsinpiFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAsinpiFloat4Float4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xbfa2ccbc5d930baal, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeAsinpiFloat4Float4(inV, out);
+            verifyResultsNativeAsinpiFloat4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinpiFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAsinpiFloat4Float4(inV, out);
+            verifyResultsNativeAsinpiFloat4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinpiFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAsinpiFloat4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAsinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAsinpiFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeAsinpi() {
+        checkNativeAsinpiFloatFloat();
+        checkNativeAsinpiFloat2Float2();
+        checkNativeAsinpiFloat3Float3();
+        checkNativeAsinpiFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsinpi.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsinpi.rs
new file mode 100644
index 0000000..f08c041
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsinpi.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeAsinpiFloatFloat(float inV) {
+    return native_asinpi(inV);
+}
+
+float2 __attribute__((kernel)) testNativeAsinpiFloat2Float2(float2 inV) {
+    return native_asinpi(inV);
+}
+
+float3 __attribute__((kernel)) testNativeAsinpiFloat3Float3(float3 inV) {
+    return native_asinpi(inV);
+}
+
+float4 __attribute__((kernel)) testNativeAsinpiFloat4Float4(float4 inV) {
+    return native_asinpi(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsinpiRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsinpiRelaxed.rs
new file mode 100644
index 0000000..83a97d3
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAsinpiRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeAsinpi.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtan.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtan.java
new file mode 100644
index 0000000..26225c5
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtan.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeAtan extends RSBaseCompute {
+
+    private ScriptC_TestNativeAtan script;
+    private ScriptC_TestNativeAtanRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeAtan(mRS);
+        scriptRelaxed = new ScriptC_TestNativeAtanRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeAtanFloatFloat() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xaafbf9b325b34e42l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeAtanFloatFloat(inV, out);
+            verifyResultsNativeAtanFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAtanFloatFloat(inV, out);
+            verifyResultsNativeAtanFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtanFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAtan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAtanFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAtanFloat2Float2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xf5c93432108a7b96l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeAtanFloat2Float2(inV, out);
+            verifyResultsNativeAtanFloat2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAtanFloat2Float2(inV, out);
+            verifyResultsNativeAtanFloat2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtanFloat2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAtan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAtanFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAtanFloat3Float3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xf5cafd4d06a59c74l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeAtanFloat3Float3(inV, out);
+            verifyResultsNativeAtanFloat3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAtanFloat3Float3(inV, out);
+            verifyResultsNativeAtanFloat3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtanFloat3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAtan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAtanFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAtanFloat4Float4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xf5ccc667fcc0bd52l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeAtanFloat4Float4(inV, out);
+            verifyResultsNativeAtanFloat4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAtanFloat4Float4(inV, out);
+            verifyResultsNativeAtanFloat4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtanFloat4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAtan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAtanFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeAtan() {
+        checkNativeAtanFloatFloat();
+        checkNativeAtanFloat2Float2();
+        checkNativeAtanFloat3Float3();
+        checkNativeAtanFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtan.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtan.rs
new file mode 100644
index 0000000..f15e5fd
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtan.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeAtanFloatFloat(float inV) {
+    return native_atan(inV);
+}
+
+float2 __attribute__((kernel)) testNativeAtanFloat2Float2(float2 inV) {
+    return native_atan(inV);
+}
+
+float3 __attribute__((kernel)) testNativeAtanFloat3Float3(float3 inV) {
+    return native_atan(inV);
+}
+
+float4 __attribute__((kernel)) testNativeAtanFloat4Float4(float4 inV) {
+    return native_atan(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtan2.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtan2.java
new file mode 100644
index 0000000..c33523c
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtan2.java
@@ -0,0 +1,325 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeAtan2 extends RSBaseCompute {
+
+    private ScriptC_TestNativeAtan2 script;
+    private ScriptC_TestNativeAtan2Relaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeAtan2(mRS);
+        scriptRelaxed = new ScriptC_TestNativeAtan2Relaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float inY;
+        public float inX;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeAtan2FloatFloatFloat() {
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x4ecf7d3b9e2a276fl, false);
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x4ecf7d3b9e2a276el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInX(inX);
+            script.forEach_testNativeAtan2FloatFloatFloat(inY, out);
+            verifyResultsNativeAtan2FloatFloatFloat(inY, inX, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2FloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInX(inX);
+            scriptRelaxed.forEach_testNativeAtan2FloatFloatFloat(inY, out);
+            verifyResultsNativeAtan2FloatFloatFloat(inY, inX, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2FloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtan2FloatFloatFloat(Allocation inY, Allocation inX, Allocation out, boolean relaxed) {
+        float[] arrayInY = new float[INPUTSIZE * 1];
+        inY.copyTo(arrayInY);
+        float[] arrayInX = new float[INPUTSIZE * 1];
+        inX.copyTo(arrayInX);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inY = arrayInY[i];
+                args.inX = arrayInX[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAtan2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAtan2FloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAtan2Float2Float2Float2() {
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x3c2d1a09d1c2a8c7l, false);
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x3c2d1a09d1c2a8c6l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInX(inX);
+            script.forEach_testNativeAtan2Float2Float2Float2(inY, out);
+            verifyResultsNativeAtan2Float2Float2Float2(inY, inX, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2Float2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInX(inX);
+            scriptRelaxed.forEach_testNativeAtan2Float2Float2Float2(inY, out);
+            verifyResultsNativeAtan2Float2Float2Float2(inY, inX, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2Float2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtan2Float2Float2Float2(Allocation inY, Allocation inX, Allocation out, boolean relaxed) {
+        float[] arrayInY = new float[INPUTSIZE * 2];
+        inY.copyTo(arrayInY);
+        float[] arrayInX = new float[INPUTSIZE * 2];
+        inX.copyTo(arrayInX);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inY = arrayInY[i * 2 + j];
+                args.inX = arrayInX[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAtan2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAtan2Float2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAtan2Float3Float3Float3() {
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x9091f829d3a0aa68l, false);
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x9091f829d3a0aa67l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInX(inX);
+            script.forEach_testNativeAtan2Float3Float3Float3(inY, out);
+            verifyResultsNativeAtan2Float3Float3Float3(inY, inX, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2Float3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInX(inX);
+            scriptRelaxed.forEach_testNativeAtan2Float3Float3Float3(inY, out);
+            verifyResultsNativeAtan2Float3Float3Float3(inY, inX, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2Float3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtan2Float3Float3Float3(Allocation inY, Allocation inX, Allocation out, boolean relaxed) {
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inY = arrayInY[i * 4 + j];
+                args.inX = arrayInX[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAtan2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAtan2Float3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAtan2Float4Float4Float4() {
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xe4f6d649d57eac09l, false);
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xe4f6d649d57eac08l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInX(inX);
+            script.forEach_testNativeAtan2Float4Float4Float4(inY, out);
+            verifyResultsNativeAtan2Float4Float4Float4(inY, inX, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2Float4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInX(inX);
+            scriptRelaxed.forEach_testNativeAtan2Float4Float4Float4(inY, out);
+            verifyResultsNativeAtan2Float4Float4Float4(inY, inX, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2Float4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtan2Float4Float4Float4(Allocation inY, Allocation inX, Allocation out, boolean relaxed) {
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inY = arrayInY[i * 4 + j];
+                args.inX = arrayInX[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAtan2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAtan2Float4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeAtan2() {
+        checkNativeAtan2FloatFloatFloat();
+        checkNativeAtan2Float2Float2Float2();
+        checkNativeAtan2Float3Float3Float3();
+        checkNativeAtan2Float4Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtan2.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtan2.rs
new file mode 100644
index 0000000..3ab222c
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtan2.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInX;
+
+float __attribute__((kernel)) testNativeAtan2FloatFloatFloat(float inY, unsigned int x) {
+    float inX = rsGetElementAt_float(gAllocInX, x);
+    return native_atan2(inY, inX);
+}
+
+float2 __attribute__((kernel)) testNativeAtan2Float2Float2Float2(float2 inY, unsigned int x) {
+    float2 inX = rsGetElementAt_float2(gAllocInX, x);
+    return native_atan2(inY, inX);
+}
+
+float3 __attribute__((kernel)) testNativeAtan2Float3Float3Float3(float3 inY, unsigned int x) {
+    float3 inX = rsGetElementAt_float3(gAllocInX, x);
+    return native_atan2(inY, inX);
+}
+
+float4 __attribute__((kernel)) testNativeAtan2Float4Float4Float4(float4 inY, unsigned int x) {
+    float4 inX = rsGetElementAt_float4(gAllocInX, x);
+    return native_atan2(inY, inX);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtan2Relaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtan2Relaxed.rs
new file mode 100644
index 0000000..40e8b3e
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtan2Relaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeAtan2.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtan2pi.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtan2pi.java
new file mode 100644
index 0000000..dd62b78
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtan2pi.java
@@ -0,0 +1,325 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeAtan2pi extends RSBaseCompute {
+
+    private ScriptC_TestNativeAtan2pi script;
+    private ScriptC_TestNativeAtan2piRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeAtan2pi(mRS);
+        scriptRelaxed = new ScriptC_TestNativeAtan2piRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float inY;
+        public float inX;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeAtan2piFloatFloatFloat() {
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x39c4f8fd35fc5dc8l, false);
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x39c4f8fd35fc5dc7l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInX(inX);
+            script.forEach_testNativeAtan2piFloatFloatFloat(inY, out);
+            verifyResultsNativeAtan2piFloatFloatFloat(inY, inX, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2piFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInX(inX);
+            scriptRelaxed.forEach_testNativeAtan2piFloatFloatFloat(inY, out);
+            verifyResultsNativeAtan2piFloatFloatFloat(inY, inX, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2piFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtan2piFloatFloatFloat(Allocation inY, Allocation inX, Allocation out, boolean relaxed) {
+        float[] arrayInY = new float[INPUTSIZE * 1];
+        inY.copyTo(arrayInY);
+        float[] arrayInX = new float[INPUTSIZE * 1];
+        inX.copyTo(arrayInX);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inY = arrayInY[i];
+                args.inX = arrayInX[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAtan2pi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAtan2piFloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAtan2piFloat2Float2Float2() {
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x6aff980c8d47a3e2l, false);
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x6aff980c8d47a3e1l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInX(inX);
+            script.forEach_testNativeAtan2piFloat2Float2Float2(inY, out);
+            verifyResultsNativeAtan2piFloat2Float2Float2(inY, inX, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2piFloat2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInX(inX);
+            scriptRelaxed.forEach_testNativeAtan2piFloat2Float2Float2(inY, out);
+            verifyResultsNativeAtan2piFloat2Float2Float2(inY, inX, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2piFloat2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtan2piFloat2Float2Float2(Allocation inY, Allocation inX, Allocation out, boolean relaxed) {
+        float[] arrayInY = new float[INPUTSIZE * 2];
+        inY.copyTo(arrayInY);
+        float[] arrayInX = new float[INPUTSIZE * 2];
+        inX.copyTo(arrayInX);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inY = arrayInY[i * 2 + j];
+                args.inX = arrayInX[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAtan2pi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAtan2piFloat2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAtan2piFloat3Float3Float3() {
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xbf64762c8f25a583l, false);
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xbf64762c8f25a582l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInX(inX);
+            script.forEach_testNativeAtan2piFloat3Float3Float3(inY, out);
+            verifyResultsNativeAtan2piFloat3Float3Float3(inY, inX, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2piFloat3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInX(inX);
+            scriptRelaxed.forEach_testNativeAtan2piFloat3Float3Float3(inY, out);
+            verifyResultsNativeAtan2piFloat3Float3Float3(inY, inX, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2piFloat3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtan2piFloat3Float3Float3(Allocation inY, Allocation inX, Allocation out, boolean relaxed) {
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inY = arrayInY[i * 4 + j];
+                args.inX = arrayInX[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAtan2pi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAtan2piFloat3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAtan2piFloat4Float4Float4() {
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x13c9544c9103a724l, false);
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x13c9544c9103a723l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInX(inX);
+            script.forEach_testNativeAtan2piFloat4Float4Float4(inY, out);
+            verifyResultsNativeAtan2piFloat4Float4Float4(inY, inX, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2piFloat4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInX(inX);
+            scriptRelaxed.forEach_testNativeAtan2piFloat4Float4Float4(inY, out);
+            verifyResultsNativeAtan2piFloat4Float4Float4(inY, inX, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2piFloat4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtan2piFloat4Float4Float4(Allocation inY, Allocation inX, Allocation out, boolean relaxed) {
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inY = arrayInY[i * 4 + j];
+                args.inX = arrayInX[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAtan2pi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAtan2piFloat4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeAtan2pi() {
+        checkNativeAtan2piFloatFloatFloat();
+        checkNativeAtan2piFloat2Float2Float2();
+        checkNativeAtan2piFloat3Float3Float3();
+        checkNativeAtan2piFloat4Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtan2pi.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtan2pi.rs
new file mode 100644
index 0000000..ea3e3f9
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtan2pi.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInX;
+
+float __attribute__((kernel)) testNativeAtan2piFloatFloatFloat(float inY, unsigned int x) {
+    float inX = rsGetElementAt_float(gAllocInX, x);
+    return native_atan2pi(inY, inX);
+}
+
+float2 __attribute__((kernel)) testNativeAtan2piFloat2Float2Float2(float2 inY, unsigned int x) {
+    float2 inX = rsGetElementAt_float2(gAllocInX, x);
+    return native_atan2pi(inY, inX);
+}
+
+float3 __attribute__((kernel)) testNativeAtan2piFloat3Float3Float3(float3 inY, unsigned int x) {
+    float3 inX = rsGetElementAt_float3(gAllocInX, x);
+    return native_atan2pi(inY, inX);
+}
+
+float4 __attribute__((kernel)) testNativeAtan2piFloat4Float4Float4(float4 inY, unsigned int x) {
+    float4 inX = rsGetElementAt_float4(gAllocInX, x);
+    return native_atan2pi(inY, inX);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtan2piRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtan2piRelaxed.rs
new file mode 100644
index 0000000..e301936
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtan2piRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeAtan2pi.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtanRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtanRelaxed.rs
new file mode 100644
index 0000000..083f168
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtanRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeAtan.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtanh.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtanh.java
new file mode 100644
index 0000000..6161483
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtanh.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeAtanh extends RSBaseCompute {
+
+    private ScriptC_TestNativeAtanh script;
+    private ScriptC_TestNativeAtanhRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeAtanh(mRS);
+        scriptRelaxed = new ScriptC_TestNativeAtanhRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inIn;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeAtanhFloatFloat() {
+        Allocation inIn = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xe13e715ccd0cedebl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeAtanhFloatFloat(inIn, out);
+            verifyResultsNativeAtanhFloatFloat(inIn, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanhFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAtanhFloatFloat(inIn, out);
+            verifyResultsNativeAtanhFloatFloat(inIn, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanhFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtanhFloatFloat(Allocation inIn, Allocation out, boolean relaxed) {
+        float[] arrayInIn = new float[INPUTSIZE * 1];
+        inIn.copyTo(arrayInIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inIn = arrayInIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAtanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inIn: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inIn, Float.floatToRawIntBits(args.inIn), args.inIn));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAtanhFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAtanhFloat2Float2() {
+        Allocation inIn = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xd5bd3a2802f7f5d7l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeAtanhFloat2Float2(inIn, out);
+            verifyResultsNativeAtanhFloat2Float2(inIn, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanhFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAtanhFloat2Float2(inIn, out);
+            verifyResultsNativeAtanhFloat2Float2(inIn, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanhFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtanhFloat2Float2(Allocation inIn, Allocation out, boolean relaxed) {
+        float[] arrayInIn = new float[INPUTSIZE * 2];
+        inIn.copyTo(arrayInIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inIn = arrayInIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAtanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inIn: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inIn, Float.floatToRawIntBits(args.inIn), args.inIn));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAtanhFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAtanhFloat3Float3() {
+        Allocation inIn = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xd60a01af59867b21l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeAtanhFloat3Float3(inIn, out);
+            verifyResultsNativeAtanhFloat3Float3(inIn, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanhFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAtanhFloat3Float3(inIn, out);
+            verifyResultsNativeAtanhFloat3Float3(inIn, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanhFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtanhFloat3Float3(Allocation inIn, Allocation out, boolean relaxed) {
+        float[] arrayInIn = new float[INPUTSIZE * 4];
+        inIn.copyTo(arrayInIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inIn = arrayInIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAtanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inIn: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inIn, Float.floatToRawIntBits(args.inIn), args.inIn));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAtanhFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAtanhFloat4Float4() {
+        Allocation inIn = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xd656c936b015006bl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeAtanhFloat4Float4(inIn, out);
+            verifyResultsNativeAtanhFloat4Float4(inIn, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanhFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAtanhFloat4Float4(inIn, out);
+            verifyResultsNativeAtanhFloat4Float4(inIn, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanhFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtanhFloat4Float4(Allocation inIn, Allocation out, boolean relaxed) {
+        float[] arrayInIn = new float[INPUTSIZE * 4];
+        inIn.copyTo(arrayInIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inIn = arrayInIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAtanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inIn: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inIn, Float.floatToRawIntBits(args.inIn), args.inIn));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAtanhFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeAtanh() {
+        checkNativeAtanhFloatFloat();
+        checkNativeAtanhFloat2Float2();
+        checkNativeAtanhFloat3Float3();
+        checkNativeAtanhFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtanh.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtanh.rs
new file mode 100644
index 0000000..de772e7
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtanh.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeAtanhFloatFloat(float inIn) {
+    return native_atanh(inIn);
+}
+
+float2 __attribute__((kernel)) testNativeAtanhFloat2Float2(float2 inIn) {
+    return native_atanh(inIn);
+}
+
+float3 __attribute__((kernel)) testNativeAtanhFloat3Float3(float3 inIn) {
+    return native_atanh(inIn);
+}
+
+float4 __attribute__((kernel)) testNativeAtanhFloat4Float4(float4 inIn) {
+    return native_atanh(inIn);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtanhRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtanhRelaxed.rs
new file mode 100644
index 0000000..40442c7
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtanhRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeAtanh.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtanpi.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtanpi.java
new file mode 100644
index 0000000..1e88568
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtanpi.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeAtanpi extends RSBaseCompute {
+
+    private ScriptC_TestNativeAtanpi script;
+    private ScriptC_TestNativeAtanpiRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeAtanpi(mRS);
+        scriptRelaxed = new ScriptC_TestNativeAtanpiRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeAtanpiFloatFloat() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x3fd790efd1d451bdl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeAtanpiFloatFloat(inV, out);
+            verifyResultsNativeAtanpiFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanpiFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAtanpiFloatFloat(inV, out);
+            verifyResultsNativeAtanpiFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanpiFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtanpiFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAtanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAtanpiFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAtanpiFloat2Float2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x1bd089694afc9ef9l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeAtanpiFloat2Float2(inV, out);
+            verifyResultsNativeAtanpiFloat2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanpiFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAtanpiFloat2Float2(inV, out);
+            verifyResultsNativeAtanpiFloat2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanpiFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtanpiFloat2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAtanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAtanpiFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAtanpiFloat3Float3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x1bd252844117bfd7l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeAtanpiFloat3Float3(inV, out);
+            verifyResultsNativeAtanpiFloat3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanpiFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAtanpiFloat3Float3(inV, out);
+            verifyResultsNativeAtanpiFloat3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanpiFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtanpiFloat3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAtanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAtanpiFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeAtanpiFloat4Float4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x1bd41b9f3732e0b5l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeAtanpiFloat4Float4(inV, out);
+            verifyResultsNativeAtanpiFloat4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanpiFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAtanpiFloat4Float4(inV, out);
+            verifyResultsNativeAtanpiFloat4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanpiFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtanpiFloat4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeAtanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeAtanpiFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeAtanpi() {
+        checkNativeAtanpiFloatFloat();
+        checkNativeAtanpiFloat2Float2();
+        checkNativeAtanpiFloat3Float3();
+        checkNativeAtanpiFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtanpi.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtanpi.rs
new file mode 100644
index 0000000..19d5262
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtanpi.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeAtanpiFloatFloat(float inV) {
+    return native_atanpi(inV);
+}
+
+float2 __attribute__((kernel)) testNativeAtanpiFloat2Float2(float2 inV) {
+    return native_atanpi(inV);
+}
+
+float3 __attribute__((kernel)) testNativeAtanpiFloat3Float3(float3 inV) {
+    return native_atanpi(inV);
+}
+
+float4 __attribute__((kernel)) testNativeAtanpiFloat4Float4(float4 inV) {
+    return native_atanpi(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtanpiRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtanpiRelaxed.rs
new file mode 100644
index 0000000..7758862d
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeAtanpiRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeAtanpi.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCbrt.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCbrt.java
new file mode 100644
index 0000000..cd6a030
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCbrt.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeCbrt extends RSBaseCompute {
+
+    private ScriptC_TestNativeCbrt script;
+    private ScriptC_TestNativeCbrtRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeCbrt(mRS);
+        scriptRelaxed = new ScriptC_TestNativeCbrtRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeCbrtFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x6eed1901e2ca9d19l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeCbrtFloatFloat(in, out);
+            verifyResultsNativeCbrtFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCbrtFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCbrtFloatFloat(in, out);
+            verifyResultsNativeCbrtFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCbrtFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCbrtFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeCbrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeCbrtFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeCbrtFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x2e78c09abaa124adl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeCbrtFloat2Float2(in, out);
+            verifyResultsNativeCbrtFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCbrtFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCbrtFloat2Float2(in, out);
+            verifyResultsNativeCbrtFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCbrtFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCbrtFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeCbrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeCbrtFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeCbrtFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x2e78cb3c19a7ba47l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeCbrtFloat3Float3(in, out);
+            verifyResultsNativeCbrtFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCbrtFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCbrtFloat3Float3(in, out);
+            verifyResultsNativeCbrtFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCbrtFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCbrtFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeCbrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeCbrtFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeCbrtFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x2e78d5dd78ae4fe1l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeCbrtFloat4Float4(in, out);
+            verifyResultsNativeCbrtFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCbrtFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCbrtFloat4Float4(in, out);
+            verifyResultsNativeCbrtFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCbrtFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCbrtFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeCbrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeCbrtFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeCbrt() {
+        checkNativeCbrtFloatFloat();
+        checkNativeCbrtFloat2Float2();
+        checkNativeCbrtFloat3Float3();
+        checkNativeCbrtFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCbrt.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCbrt.rs
new file mode 100644
index 0000000..828214b
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCbrt.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeCbrtFloatFloat(float in) {
+    return native_cbrt(in);
+}
+
+float2 __attribute__((kernel)) testNativeCbrtFloat2Float2(float2 in) {
+    return native_cbrt(in);
+}
+
+float3 __attribute__((kernel)) testNativeCbrtFloat3Float3(float3 in) {
+    return native_cbrt(in);
+}
+
+float4 __attribute__((kernel)) testNativeCbrtFloat4Float4(float4 in) {
+    return native_cbrt(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCbrtRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCbrtRelaxed.rs
new file mode 100644
index 0000000..2a49b9e
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCbrtRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeCbrt.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCos.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCos.java
new file mode 100644
index 0000000..d7c9ebf
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCos.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeCos extends RSBaseCompute {
+
+    private ScriptC_TestNativeCos script;
+    private ScriptC_TestNativeCosRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeCos(mRS);
+        scriptRelaxed = new ScriptC_TestNativeCosRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeCosFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x95ef4a20c73e7e3dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeCosFloatFloat(in, out);
+            verifyResultsNativeCosFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCosFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCosFloatFloat(in, out);
+            verifyResultsNativeCosFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCosFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCosFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeCos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeCosFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeCosFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xed4d88bac39641b1l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeCosFloat2Float2(in, out);
+            verifyResultsNativeCosFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCosFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCosFloat2Float2(in, out);
+            verifyResultsNativeCosFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCosFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCosFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeCos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeCosFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeCosFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xed4d935c229cd74bl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeCosFloat3Float3(in, out);
+            verifyResultsNativeCosFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCosFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCosFloat3Float3(in, out);
+            verifyResultsNativeCosFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCosFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCosFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeCos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeCosFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeCosFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xed4d9dfd81a36ce5l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeCosFloat4Float4(in, out);
+            verifyResultsNativeCosFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCosFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCosFloat4Float4(in, out);
+            verifyResultsNativeCosFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCosFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCosFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeCos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeCosFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeCos() {
+        checkNativeCosFloatFloat();
+        checkNativeCosFloat2Float2();
+        checkNativeCosFloat3Float3();
+        checkNativeCosFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCos.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCos.rs
new file mode 100644
index 0000000..212c12e
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCos.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeCosFloatFloat(float in) {
+    return native_cos(in);
+}
+
+float2 __attribute__((kernel)) testNativeCosFloat2Float2(float2 in) {
+    return native_cos(in);
+}
+
+float3 __attribute__((kernel)) testNativeCosFloat3Float3(float3 in) {
+    return native_cos(in);
+}
+
+float4 __attribute__((kernel)) testNativeCosFloat4Float4(float4 in) {
+    return native_cos(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCosRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCosRelaxed.rs
new file mode 100644
index 0000000..66f3fef
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCosRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeCos.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCosh.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCosh.java
new file mode 100644
index 0000000..4e841c60
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCosh.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeCosh extends RSBaseCompute {
+
+    private ScriptC_TestNativeCosh script;
+    private ScriptC_TestNativeCoshRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeCosh(mRS);
+        scriptRelaxed = new ScriptC_TestNativeCoshRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeCoshFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xeb1020909e9c475dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeCoshFloatFloat(in, out);
+            verifyResultsNativeCoshFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCoshFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCoshFloatFloat(in, out);
+            verifyResultsNativeCoshFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCoshFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCoshFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeCosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeCoshFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeCoshFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xc77a568547f7e9d1l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeCoshFloat2Float2(in, out);
+            verifyResultsNativeCoshFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCoshFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCoshFloat2Float2(in, out);
+            verifyResultsNativeCoshFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCoshFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCoshFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeCosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeCoshFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeCoshFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xc77a6126a6fe7f6bl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeCoshFloat3Float3(in, out);
+            verifyResultsNativeCoshFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCoshFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCoshFloat3Float3(in, out);
+            verifyResultsNativeCoshFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCoshFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCoshFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeCosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeCoshFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeCoshFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xc77a6bc806051505l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeCoshFloat4Float4(in, out);
+            verifyResultsNativeCoshFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCoshFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCoshFloat4Float4(in, out);
+            verifyResultsNativeCoshFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCoshFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCoshFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeCosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeCoshFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeCosh() {
+        checkNativeCoshFloatFloat();
+        checkNativeCoshFloat2Float2();
+        checkNativeCoshFloat3Float3();
+        checkNativeCoshFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCosh.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCosh.rs
new file mode 100644
index 0000000..f3635d8
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCosh.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeCoshFloatFloat(float in) {
+    return native_cosh(in);
+}
+
+float2 __attribute__((kernel)) testNativeCoshFloat2Float2(float2 in) {
+    return native_cosh(in);
+}
+
+float3 __attribute__((kernel)) testNativeCoshFloat3Float3(float3 in) {
+    return native_cosh(in);
+}
+
+float4 __attribute__((kernel)) testNativeCoshFloat4Float4(float4 in) {
+    return native_cosh(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCoshRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCoshRelaxed.rs
new file mode 100644
index 0000000..138b5c2
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCoshRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeCosh.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCospi.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCospi.java
new file mode 100644
index 0000000..ab5065b
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCospi.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeCospi extends RSBaseCompute {
+
+    private ScriptC_TestNativeCospi script;
+    private ScriptC_TestNativeCospiRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeCospi(mRS);
+        scriptRelaxed = new ScriptC_TestNativeCospiRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeCospiFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x8fc4f0187aafc9a6l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeCospiFloatFloat(in, out);
+            verifyResultsNativeCospiFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCospiFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCospiFloatFloat(in, out);
+            verifyResultsNativeCospiFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCospiFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCospiFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeCospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeCospiFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeCospiFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x656942c9d0dfeb12l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeCospiFloat2Float2(in, out);
+            verifyResultsNativeCospiFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCospiFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCospiFloat2Float2(in, out);
+            verifyResultsNativeCospiFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCospiFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCospiFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeCospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeCospiFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeCospiFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x65694d6b2fe680acl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeCospiFloat3Float3(in, out);
+            verifyResultsNativeCospiFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCospiFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCospiFloat3Float3(in, out);
+            verifyResultsNativeCospiFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCospiFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCospiFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeCospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeCospiFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeCospiFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x6569580c8eed1646l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeCospiFloat4Float4(in, out);
+            verifyResultsNativeCospiFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCospiFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCospiFloat4Float4(in, out);
+            verifyResultsNativeCospiFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCospiFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCospiFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeCospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeCospiFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeCospi() {
+        checkNativeCospiFloatFloat();
+        checkNativeCospiFloat2Float2();
+        checkNativeCospiFloat3Float3();
+        checkNativeCospiFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCospi.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCospi.rs
new file mode 100644
index 0000000..471403f
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCospi.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeCospiFloatFloat(float in) {
+    return native_cospi(in);
+}
+
+float2 __attribute__((kernel)) testNativeCospiFloat2Float2(float2 in) {
+    return native_cospi(in);
+}
+
+float3 __attribute__((kernel)) testNativeCospiFloat3Float3(float3 in) {
+    return native_cospi(in);
+}
+
+float4 __attribute__((kernel)) testNativeCospiFloat4Float4(float4 in) {
+    return native_cospi(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCospiRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCospiRelaxed.rs
new file mode 100644
index 0000000..f72429e
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeCospiRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeCospi.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeDistance.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeDistance.java
new file mode 100644
index 0000000..360da34
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeDistance.java
@@ -0,0 +1,357 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeDistance extends RSBaseCompute {
+
+    private ScriptC_TestNativeDistance script;
+    private ScriptC_TestNativeDistanceRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeDistance(mRS);
+        scriptRelaxed = new ScriptC_TestNativeDistanceRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float inLhs;
+        public float inRhs;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeDistanceFloatFloatFloat() {
+        Allocation inLhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xe0fd4252f8556ff6l, false);
+        Allocation inRhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xe0fd4252f8559b4cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInRhs(inRhs);
+            script.forEach_testNativeDistanceFloatFloatFloat(inLhs, out);
+            verifyResultsNativeDistanceFloatFloatFloat(inLhs, inRhs, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDistanceFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRhs(inRhs);
+            scriptRelaxed.forEach_testNativeDistanceFloatFloatFloat(inLhs, out);
+            verifyResultsNativeDistanceFloatFloatFloat(inLhs, inRhs, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDistanceFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeDistanceFloatFloatFloat(Allocation inLhs, Allocation inRhs, Allocation out, boolean relaxed) {
+        float[] arrayInLhs = new float[INPUTSIZE * 1];
+        inLhs.copyTo(arrayInLhs);
+        float[] arrayInRhs = new float[INPUTSIZE * 1];
+        inRhs.copyTo(arrayInRhs);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+            // Create the appropriate sized arrays in args
+            // Fill args with the input values
+            args.inLhs = arrayInLhs[i];
+            args.inRhs = arrayInRhs[i];
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeNativeDistance(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                message.append("Input inLhs: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayInLhs[i], Float.floatToRawIntBits(arrayInLhs[i]), arrayInLhs[i]));
+                message.append("\n");
+                message.append("Input inRhs: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayInRhs[i], Float.floatToRawIntBits(arrayInRhs[i]), arrayInRhs[i]));
+                message.append("\n");
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkNativeDistanceFloatFloatFloat" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    public class ArgumentsFloatNFloatNFloat {
+        public float[] inLhs;
+        public float[] inRhs;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeDistanceFloat2Float2Float() {
+        Allocation inLhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x28a9ea2ea1fd926al, false);
+        Allocation inRhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x28a9ea2ea1fdbdc0l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInRhs(inRhs);
+            script.forEach_testNativeDistanceFloat2Float2Float(inLhs, out);
+            verifyResultsNativeDistanceFloat2Float2Float(inLhs, inRhs, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDistanceFloat2Float2Float: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRhs(inRhs);
+            scriptRelaxed.forEach_testNativeDistanceFloat2Float2Float(inLhs, out);
+            verifyResultsNativeDistanceFloat2Float2Float(inLhs, inRhs, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDistanceFloat2Float2Float: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeDistanceFloat2Float2Float(Allocation inLhs, Allocation inRhs, Allocation out, boolean relaxed) {
+        float[] arrayInLhs = new float[INPUTSIZE * 2];
+        inLhs.copyTo(arrayInLhs);
+        float[] arrayInRhs = new float[INPUTSIZE * 2];
+        inRhs.copyTo(arrayInRhs);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloatNFloat args = new ArgumentsFloatNFloatNFloat();
+            // Create the appropriate sized arrays in args
+            args.inLhs = new float[2];
+            args.inRhs = new float[2];
+            // Fill args with the input values
+            for (int j = 0; j < 2 ; j++) {
+                args.inLhs[j] = arrayInLhs[i * 2 + j];
+            }
+            for (int j = 0; j < 2 ; j++) {
+                args.inRhs[j] = arrayInRhs[i * 2 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeNativeDistance(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 2 ; j++) {
+                    message.append("Input inLhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInLhs[i * 2 + j], Float.floatToRawIntBits(arrayInLhs[i * 2 + j]), arrayInLhs[i * 2 + j]));
+                    message.append("\n");
+                }
+                for (int j = 0; j < 2 ; j++) {
+                    message.append("Input inRhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInRhs[i * 2 + j], Float.floatToRawIntBits(arrayInRhs[i * 2 + j]), arrayInRhs[i * 2 + j]));
+                    message.append("\n");
+                }
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkNativeDistanceFloat2Float2Float" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    private void checkNativeDistanceFloat3Float3Float() {
+        Allocation inLhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x559b398ef213adc4l, false);
+        Allocation inRhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x559b398ef213d91al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInRhs(inRhs);
+            script.forEach_testNativeDistanceFloat3Float3Float(inLhs, out);
+            verifyResultsNativeDistanceFloat3Float3Float(inLhs, inRhs, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDistanceFloat3Float3Float: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRhs(inRhs);
+            scriptRelaxed.forEach_testNativeDistanceFloat3Float3Float(inLhs, out);
+            verifyResultsNativeDistanceFloat3Float3Float(inLhs, inRhs, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDistanceFloat3Float3Float: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeDistanceFloat3Float3Float(Allocation inLhs, Allocation inRhs, Allocation out, boolean relaxed) {
+        float[] arrayInLhs = new float[INPUTSIZE * 4];
+        inLhs.copyTo(arrayInLhs);
+        float[] arrayInRhs = new float[INPUTSIZE * 4];
+        inRhs.copyTo(arrayInRhs);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloatNFloat args = new ArgumentsFloatNFloatNFloat();
+            // Create the appropriate sized arrays in args
+            args.inLhs = new float[3];
+            args.inRhs = new float[3];
+            // Fill args with the input values
+            for (int j = 0; j < 3 ; j++) {
+                args.inLhs[j] = arrayInLhs[i * 4 + j];
+            }
+            for (int j = 0; j < 3 ; j++) {
+                args.inRhs[j] = arrayInRhs[i * 4 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeNativeDistance(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 3 ; j++) {
+                    message.append("Input inLhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInLhs[i * 4 + j], Float.floatToRawIntBits(arrayInLhs[i * 4 + j]), arrayInLhs[i * 4 + j]));
+                    message.append("\n");
+                }
+                for (int j = 0; j < 3 ; j++) {
+                    message.append("Input inRhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInRhs[i * 4 + j], Float.floatToRawIntBits(arrayInRhs[i * 4 + j]), arrayInRhs[i * 4 + j]));
+                    message.append("\n");
+                }
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkNativeDistanceFloat3Float3Float" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    private void checkNativeDistanceFloat4Float4Float() {
+        Allocation inLhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x828c88ef4229c91el, false);
+        Allocation inRhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x828c88ef4229f474l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInRhs(inRhs);
+            script.forEach_testNativeDistanceFloat4Float4Float(inLhs, out);
+            verifyResultsNativeDistanceFloat4Float4Float(inLhs, inRhs, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDistanceFloat4Float4Float: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRhs(inRhs);
+            scriptRelaxed.forEach_testNativeDistanceFloat4Float4Float(inLhs, out);
+            verifyResultsNativeDistanceFloat4Float4Float(inLhs, inRhs, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDistanceFloat4Float4Float: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeDistanceFloat4Float4Float(Allocation inLhs, Allocation inRhs, Allocation out, boolean relaxed) {
+        float[] arrayInLhs = new float[INPUTSIZE * 4];
+        inLhs.copyTo(arrayInLhs);
+        float[] arrayInRhs = new float[INPUTSIZE * 4];
+        inRhs.copyTo(arrayInRhs);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloatNFloat args = new ArgumentsFloatNFloatNFloat();
+            // Create the appropriate sized arrays in args
+            args.inLhs = new float[4];
+            args.inRhs = new float[4];
+            // Fill args with the input values
+            for (int j = 0; j < 4 ; j++) {
+                args.inLhs[j] = arrayInLhs[i * 4 + j];
+            }
+            for (int j = 0; j < 4 ; j++) {
+                args.inRhs[j] = arrayInRhs[i * 4 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeNativeDistance(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 4 ; j++) {
+                    message.append("Input inLhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInLhs[i * 4 + j], Float.floatToRawIntBits(arrayInLhs[i * 4 + j]), arrayInLhs[i * 4 + j]));
+                    message.append("\n");
+                }
+                for (int j = 0; j < 4 ; j++) {
+                    message.append("Input inRhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInRhs[i * 4 + j], Float.floatToRawIntBits(arrayInRhs[i * 4 + j]), arrayInRhs[i * 4 + j]));
+                    message.append("\n");
+                }
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkNativeDistanceFloat4Float4Float" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    public void testNativeDistance() {
+        checkNativeDistanceFloatFloatFloat();
+        checkNativeDistanceFloat2Float2Float();
+        checkNativeDistanceFloat3Float3Float();
+        checkNativeDistanceFloat4Float4Float();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeDistance.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeDistance.rs
new file mode 100644
index 0000000..d9c215c
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeDistance.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInRhs;
+
+float __attribute__((kernel)) testNativeDistanceFloatFloatFloat(float inLhs, unsigned int x) {
+    float inRhs = rsGetElementAt_float(gAllocInRhs, x);
+    return native_distance(inLhs, inRhs);
+}
+
+float __attribute__((kernel)) testNativeDistanceFloat2Float2Float(float2 inLhs, unsigned int x) {
+    float2 inRhs = rsGetElementAt_float2(gAllocInRhs, x);
+    return native_distance(inLhs, inRhs);
+}
+
+float __attribute__((kernel)) testNativeDistanceFloat3Float3Float(float3 inLhs, unsigned int x) {
+    float3 inRhs = rsGetElementAt_float3(gAllocInRhs, x);
+    return native_distance(inLhs, inRhs);
+}
+
+float __attribute__((kernel)) testNativeDistanceFloat4Float4Float(float4 inLhs, unsigned int x) {
+    float4 inRhs = rsGetElementAt_float4(gAllocInRhs, x);
+    return native_distance(inLhs, inRhs);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeDistanceRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeDistanceRelaxed.rs
new file mode 100644
index 0000000..167b79a
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeDistanceRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeDistance.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeDivide.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeDivide.java
new file mode 100644
index 0000000..c546724
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeDivide.java
@@ -0,0 +1,325 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeDivide extends RSBaseCompute {
+
+    private ScriptC_TestNativeDivide script;
+    private ScriptC_TestNativeDivideRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeDivide(mRS);
+        scriptRelaxed = new ScriptC_TestNativeDivideRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float inLhs;
+        public float inRhs;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeDivideFloatFloatFloat() {
+        Allocation inLhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xe2845ef0c23d02del, false);
+        Allocation inRhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xe2845ef0c23d2e34l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInRhs(inRhs);
+            script.forEach_testNativeDivideFloatFloatFloat(inLhs, out);
+            verifyResultsNativeDivideFloatFloatFloat(inLhs, inRhs, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDivideFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRhs(inRhs);
+            scriptRelaxed.forEach_testNativeDivideFloatFloatFloat(inLhs, out);
+            verifyResultsNativeDivideFloatFloatFloat(inLhs, inRhs, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDivideFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeDivideFloatFloatFloat(Allocation inLhs, Allocation inRhs, Allocation out, boolean relaxed) {
+        float[] arrayInLhs = new float[INPUTSIZE * 1];
+        inLhs.copyTo(arrayInLhs);
+        float[] arrayInRhs = new float[INPUTSIZE * 1];
+        inRhs.copyTo(arrayInRhs);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inLhs = arrayInLhs[i];
+                args.inRhs = arrayInRhs[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeDivide(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inLhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inLhs, Float.floatToRawIntBits(args.inLhs), args.inLhs));
+                    message.append("\n");
+                    message.append("Input inRhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inRhs, Float.floatToRawIntBits(args.inRhs), args.inRhs));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeDivideFloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeDivideFloat2Float2Float2() {
+        Allocation inLhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x51c6d6ecaeab1c48l, false);
+        Allocation inRhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x51c6d6ecaeab479el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInRhs(inRhs);
+            script.forEach_testNativeDivideFloat2Float2Float2(inLhs, out);
+            verifyResultsNativeDivideFloat2Float2Float2(inLhs, inRhs, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDivideFloat2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRhs(inRhs);
+            scriptRelaxed.forEach_testNativeDivideFloat2Float2Float2(inLhs, out);
+            verifyResultsNativeDivideFloat2Float2Float2(inLhs, inRhs, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDivideFloat2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeDivideFloat2Float2Float2(Allocation inLhs, Allocation inRhs, Allocation out, boolean relaxed) {
+        float[] arrayInLhs = new float[INPUTSIZE * 2];
+        inLhs.copyTo(arrayInLhs);
+        float[] arrayInRhs = new float[INPUTSIZE * 2];
+        inRhs.copyTo(arrayInRhs);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inLhs = arrayInLhs[i * 2 + j];
+                args.inRhs = arrayInRhs[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeDivide(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inLhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inLhs, Float.floatToRawIntBits(args.inLhs), args.inLhs));
+                    message.append("\n");
+                    message.append("Input inRhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inRhs, Float.floatToRawIntBits(args.inRhs), args.inRhs));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeDivideFloat2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeDivideFloat3Float3Float3() {
+        Allocation inLhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xde4f2c1a2b24e021l, false);
+        Allocation inRhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xde4f2c1a2b250b77l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInRhs(inRhs);
+            script.forEach_testNativeDivideFloat3Float3Float3(inLhs, out);
+            verifyResultsNativeDivideFloat3Float3Float3(inLhs, inRhs, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDivideFloat3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRhs(inRhs);
+            scriptRelaxed.forEach_testNativeDivideFloat3Float3Float3(inLhs, out);
+            verifyResultsNativeDivideFloat3Float3Float3(inLhs, inRhs, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDivideFloat3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeDivideFloat3Float3Float3(Allocation inLhs, Allocation inRhs, Allocation out, boolean relaxed) {
+        float[] arrayInLhs = new float[INPUTSIZE * 4];
+        inLhs.copyTo(arrayInLhs);
+        float[] arrayInRhs = new float[INPUTSIZE * 4];
+        inRhs.copyTo(arrayInRhs);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inLhs = arrayInLhs[i * 4 + j];
+                args.inRhs = arrayInRhs[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeDivide(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inLhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inLhs, Float.floatToRawIntBits(args.inLhs), args.inLhs));
+                    message.append("\n");
+                    message.append("Input inRhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inRhs, Float.floatToRawIntBits(args.inRhs), args.inRhs));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeDivideFloat3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeDivideFloat4Float4Float4() {
+        Allocation inLhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x6ad78147a79ea3fal, false);
+        Allocation inRhs = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x6ad78147a79ecf50l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInRhs(inRhs);
+            script.forEach_testNativeDivideFloat4Float4Float4(inLhs, out);
+            verifyResultsNativeDivideFloat4Float4Float4(inLhs, inRhs, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDivideFloat4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRhs(inRhs);
+            scriptRelaxed.forEach_testNativeDivideFloat4Float4Float4(inLhs, out);
+            verifyResultsNativeDivideFloat4Float4Float4(inLhs, inRhs, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDivideFloat4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeDivideFloat4Float4Float4(Allocation inLhs, Allocation inRhs, Allocation out, boolean relaxed) {
+        float[] arrayInLhs = new float[INPUTSIZE * 4];
+        inLhs.copyTo(arrayInLhs);
+        float[] arrayInRhs = new float[INPUTSIZE * 4];
+        inRhs.copyTo(arrayInRhs);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inLhs = arrayInLhs[i * 4 + j];
+                args.inRhs = arrayInRhs[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeDivide(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inLhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inLhs, Float.floatToRawIntBits(args.inLhs), args.inLhs));
+                    message.append("\n");
+                    message.append("Input inRhs: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inRhs, Float.floatToRawIntBits(args.inRhs), args.inRhs));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeDivideFloat4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeDivide() {
+        checkNativeDivideFloatFloatFloat();
+        checkNativeDivideFloat2Float2Float2();
+        checkNativeDivideFloat3Float3Float3();
+        checkNativeDivideFloat4Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeDivide.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeDivide.rs
new file mode 100644
index 0000000..ee36b50
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeDivide.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInRhs;
+
+float __attribute__((kernel)) testNativeDivideFloatFloatFloat(float inLhs, unsigned int x) {
+    float inRhs = rsGetElementAt_float(gAllocInRhs, x);
+    return native_divide(inLhs, inRhs);
+}
+
+float2 __attribute__((kernel)) testNativeDivideFloat2Float2Float2(float2 inLhs, unsigned int x) {
+    float2 inRhs = rsGetElementAt_float2(gAllocInRhs, x);
+    return native_divide(inLhs, inRhs);
+}
+
+float3 __attribute__((kernel)) testNativeDivideFloat3Float3Float3(float3 inLhs, unsigned int x) {
+    float3 inRhs = rsGetElementAt_float3(gAllocInRhs, x);
+    return native_divide(inLhs, inRhs);
+}
+
+float4 __attribute__((kernel)) testNativeDivideFloat4Float4Float4(float4 inLhs, unsigned int x) {
+    float4 inRhs = rsGetElementAt_float4(gAllocInRhs, x);
+    return native_divide(inLhs, inRhs);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeDivideRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeDivideRelaxed.rs
new file mode 100644
index 0000000..b6d50045
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeDivideRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeDivide.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExp.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExp.java
new file mode 100644
index 0000000..3c9a847
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExp.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeExp extends RSBaseCompute {
+
+    private ScriptC_TestNativeExp script;
+    private ScriptC_TestNativeExpRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeExp(mRS);
+        scriptRelaxed = new ScriptC_TestNativeExpRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeExpFloatFloat() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x66a7898af1f6be9bl, -86, 86);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeExpFloatFloat(inV, out);
+            verifyResultsNativeExpFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExpFloatFloat(inV, out);
+            verifyResultsNativeExpFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExpFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeExp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeExpFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeExpFloat2Float2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x6feb21d463a0ee67l, -86, 86);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeExpFloat2Float2(inV, out);
+            verifyResultsNativeExpFloat2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExpFloat2Float2(inV, out);
+            verifyResultsNativeExpFloat2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExpFloat2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeExp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeExpFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeExpFloat3Float3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x6feceaef59bc0f45l, -86, 86);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeExpFloat3Float3(inV, out);
+            verifyResultsNativeExpFloat3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExpFloat3Float3(inV, out);
+            verifyResultsNativeExpFloat3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExpFloat3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeExp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeExpFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeExpFloat4Float4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x6feeb40a4fd73023l, -86, 86);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeExpFloat4Float4(inV, out);
+            verifyResultsNativeExpFloat4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExpFloat4Float4(inV, out);
+            verifyResultsNativeExpFloat4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExpFloat4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeExp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeExpFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeExp() {
+        checkNativeExpFloatFloat();
+        checkNativeExpFloat2Float2();
+        checkNativeExpFloat3Float3();
+        checkNativeExpFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExp.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExp.rs
new file mode 100644
index 0000000..6143d9f
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExp.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeExpFloatFloat(float inV) {
+    return native_exp(inV);
+}
+
+float2 __attribute__((kernel)) testNativeExpFloat2Float2(float2 inV) {
+    return native_exp(inV);
+}
+
+float3 __attribute__((kernel)) testNativeExpFloat3Float3(float3 inV) {
+    return native_exp(inV);
+}
+
+float4 __attribute__((kernel)) testNativeExpFloat4Float4(float4 inV) {
+    return native_exp(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExp10.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExp10.java
new file mode 100644
index 0000000..75eb8df
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExp10.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeExp10 extends RSBaseCompute {
+
+    private ScriptC_TestNativeExp10 script;
+    private ScriptC_TestNativeExp10Relaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeExp10(mRS);
+        scriptRelaxed = new ScriptC_TestNativeExp10Relaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeExp10FloatFloat() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x562e4ea690352c54l, -37, 37);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeExp10FloatFloat(inV, out);
+            verifyResultsNativeExp10FloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp10FloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExp10FloatFloat(inV, out);
+            verifyResultsNativeExp10FloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp10FloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExp10FloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeExp10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeExp10FloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeExp10Float2Float2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x7450c64e54876b98l, -37, 37);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeExp10Float2Float2(inV, out);
+            verifyResultsNativeExp10Float2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp10Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExp10Float2Float2(inV, out);
+            verifyResultsNativeExp10Float2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp10Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExp10Float2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeExp10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeExp10Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeExp10Float3Float3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x74528f694aa28c76l, -37, 37);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeExp10Float3Float3(inV, out);
+            verifyResultsNativeExp10Float3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp10Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExp10Float3Float3(inV, out);
+            verifyResultsNativeExp10Float3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp10Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExp10Float3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeExp10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeExp10Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeExp10Float4Float4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x7454588440bdad54l, -37, 37);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeExp10Float4Float4(inV, out);
+            verifyResultsNativeExp10Float4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp10Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExp10Float4Float4(inV, out);
+            verifyResultsNativeExp10Float4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp10Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExp10Float4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeExp10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeExp10Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeExp10() {
+        checkNativeExp10FloatFloat();
+        checkNativeExp10Float2Float2();
+        checkNativeExp10Float3Float3();
+        checkNativeExp10Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExp10.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExp10.rs
new file mode 100644
index 0000000..1d03607
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExp10.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeExp10FloatFloat(float inV) {
+    return native_exp10(inV);
+}
+
+float2 __attribute__((kernel)) testNativeExp10Float2Float2(float2 inV) {
+    return native_exp10(inV);
+}
+
+float3 __attribute__((kernel)) testNativeExp10Float3Float3(float3 inV) {
+    return native_exp10(inV);
+}
+
+float4 __attribute__((kernel)) testNativeExp10Float4Float4(float4 inV) {
+    return native_exp10(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExp10Relaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExp10Relaxed.rs
new file mode 100644
index 0000000..4f12665
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExp10Relaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeExp10.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExp2.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExp2.java
new file mode 100644
index 0000000..bb0e9b3
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExp2.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeExp2 extends RSBaseCompute {
+
+    private ScriptC_TestNativeExp2 script;
+    private ScriptC_TestNativeExp2Relaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeExp2(mRS);
+        scriptRelaxed = new ScriptC_TestNativeExp2Relaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeExp2FloatFloat() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xd87a6eb24c6a2bc5l, -125, 125);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeExp2FloatFloat(inV, out);
+            verifyResultsNativeExp2FloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp2FloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExp2FloatFloat(inV, out);
+            verifyResultsNativeExp2FloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp2FloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExp2FloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeExp2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeExp2FloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeExp2Float2Float2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x8c243b10af5062c1l, -125, 125);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeExp2Float2Float2(inV, out);
+            verifyResultsNativeExp2Float2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExp2Float2Float2(inV, out);
+            verifyResultsNativeExp2Float2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExp2Float2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeExp2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeExp2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeExp2Float3Float3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x8c26042ba56b839fl, -125, 125);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeExp2Float3Float3(inV, out);
+            verifyResultsNativeExp2Float3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp2Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExp2Float3Float3(inV, out);
+            verifyResultsNativeExp2Float3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp2Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExp2Float3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeExp2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeExp2Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeExp2Float4Float4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x8c27cd469b86a47dl, -125, 125);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeExp2Float4Float4(inV, out);
+            verifyResultsNativeExp2Float4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp2Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExp2Float4Float4(inV, out);
+            verifyResultsNativeExp2Float4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp2Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExp2Float4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeExp2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeExp2Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeExp2() {
+        checkNativeExp2FloatFloat();
+        checkNativeExp2Float2Float2();
+        checkNativeExp2Float3Float3();
+        checkNativeExp2Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExp2.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExp2.rs
new file mode 100644
index 0000000..1112900
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExp2.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeExp2FloatFloat(float inV) {
+    return native_exp2(inV);
+}
+
+float2 __attribute__((kernel)) testNativeExp2Float2Float2(float2 inV) {
+    return native_exp2(inV);
+}
+
+float3 __attribute__((kernel)) testNativeExp2Float3Float3(float3 inV) {
+    return native_exp2(inV);
+}
+
+float4 __attribute__((kernel)) testNativeExp2Float4Float4(float4 inV) {
+    return native_exp2(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExp2Relaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExp2Relaxed.rs
new file mode 100644
index 0000000..8b99710
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExp2Relaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeExp2.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExpRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExpRelaxed.rs
new file mode 100644
index 0000000..dd3a73c
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExpRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeExp.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExpm1.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExpm1.java
new file mode 100644
index 0000000..3eecc32
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExpm1.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeExpm1 extends RSBaseCompute {
+
+    private ScriptC_TestNativeExpm1 script;
+    private ScriptC_TestNativeExpm1Relaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeExpm1(mRS);
+        scriptRelaxed = new ScriptC_TestNativeExpm1Relaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeExpm1FloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x209e2820fcaa295fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeExpm1FloatFloat(in, out);
+            verifyResultsNativeExpm1FloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpm1FloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExpm1FloatFloat(in, out);
+            verifyResultsNativeExpm1FloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpm1FloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExpm1FloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeExpm1(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeExpm1FloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeExpm1Float2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x964ef83c9a3d4a43l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeExpm1Float2Float2(in, out);
+            verifyResultsNativeExpm1Float2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpm1Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExpm1Float2Float2(in, out);
+            verifyResultsNativeExpm1Float2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpm1Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExpm1Float2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeExpm1(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeExpm1Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeExpm1Float3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x964f02ddf943dfddl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeExpm1Float3Float3(in, out);
+            verifyResultsNativeExpm1Float3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpm1Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExpm1Float3Float3(in, out);
+            verifyResultsNativeExpm1Float3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpm1Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExpm1Float3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeExpm1(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeExpm1Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeExpm1Float4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x964f0d7f584a7577l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeExpm1Float4Float4(in, out);
+            verifyResultsNativeExpm1Float4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpm1Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExpm1Float4Float4(in, out);
+            verifyResultsNativeExpm1Float4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpm1Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExpm1Float4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeExpm1(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeExpm1Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeExpm1() {
+        checkNativeExpm1FloatFloat();
+        checkNativeExpm1Float2Float2();
+        checkNativeExpm1Float3Float3();
+        checkNativeExpm1Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExpm1.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExpm1.rs
new file mode 100644
index 0000000..6d265d6
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExpm1.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeExpm1FloatFloat(float in) {
+    return native_expm1(in);
+}
+
+float2 __attribute__((kernel)) testNativeExpm1Float2Float2(float2 in) {
+    return native_expm1(in);
+}
+
+float3 __attribute__((kernel)) testNativeExpm1Float3Float3(float3 in) {
+    return native_expm1(in);
+}
+
+float4 __attribute__((kernel)) testNativeExpm1Float4Float4(float4 in) {
+    return native_expm1(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExpm1Relaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExpm1Relaxed.rs
new file mode 100644
index 0000000..a74a0d1
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeExpm1Relaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeExpm1.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeHypot.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeHypot.java
new file mode 100644
index 0000000..0a50675
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeHypot.java
@@ -0,0 +1,325 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeHypot extends RSBaseCompute {
+
+    private ScriptC_TestNativeHypot script;
+    private ScriptC_TestNativeHypotRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeHypot(mRS);
+        scriptRelaxed = new ScriptC_TestNativeHypotRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float inX;
+        public float inY;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeHypotFloatFloatFloat() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x3d61f129bdf66018l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x3d61f129bdf66019l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testNativeHypotFloatFloatFloat(inX, out);
+            verifyResultsNativeHypotFloatFloatFloat(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeHypotFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testNativeHypotFloatFloatFloat(inX, out);
+            verifyResultsNativeHypotFloatFloatFloat(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeHypotFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeHypotFloatFloatFloat(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 1];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 1];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i];
+                args.inY = arrayInY[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeHypot(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeHypotFloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeHypotFloat2Float2Float2() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x92a8064760a50e64l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x92a8064760a50e65l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testNativeHypotFloat2Float2Float2(inX, out);
+            verifyResultsNativeHypotFloat2Float2Float2(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeHypotFloat2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testNativeHypotFloat2Float2Float2(inX, out);
+            verifyResultsNativeHypotFloat2Float2Float2(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeHypotFloat2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeHypotFloat2Float2Float2(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 2];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 2];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 2 + j];
+                args.inY = arrayInY[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeHypot(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeHypotFloat2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeHypotFloat3Float3Float3() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xe70ce46762831005l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xe70ce46762831006l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testNativeHypotFloat3Float3Float3(inX, out);
+            verifyResultsNativeHypotFloat3Float3Float3(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeHypotFloat3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testNativeHypotFloat3Float3Float3(inX, out);
+            verifyResultsNativeHypotFloat3Float3Float3(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeHypotFloat3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeHypotFloat3Float3Float3(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeHypot(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeHypotFloat3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeHypotFloat4Float4Float4() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x3b71c287646111a6l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x3b71c287646111a7l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testNativeHypotFloat4Float4Float4(inX, out);
+            verifyResultsNativeHypotFloat4Float4Float4(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeHypotFloat4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testNativeHypotFloat4Float4Float4(inX, out);
+            verifyResultsNativeHypotFloat4Float4Float4(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeHypotFloat4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeHypotFloat4Float4Float4(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeHypot(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeHypotFloat4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeHypot() {
+        checkNativeHypotFloatFloatFloat();
+        checkNativeHypotFloat2Float2Float2();
+        checkNativeHypotFloat3Float3Float3();
+        checkNativeHypotFloat4Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeHypot.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeHypot.rs
new file mode 100644
index 0000000..b4e8a7c
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeHypot.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInY;
+
+float __attribute__((kernel)) testNativeHypotFloatFloatFloat(float inX, unsigned int x) {
+    float inY = rsGetElementAt_float(gAllocInY, x);
+    return native_hypot(inX, inY);
+}
+
+float2 __attribute__((kernel)) testNativeHypotFloat2Float2Float2(float2 inX, unsigned int x) {
+    float2 inY = rsGetElementAt_float2(gAllocInY, x);
+    return native_hypot(inX, inY);
+}
+
+float3 __attribute__((kernel)) testNativeHypotFloat3Float3Float3(float3 inX, unsigned int x) {
+    float3 inY = rsGetElementAt_float3(gAllocInY, x);
+    return native_hypot(inX, inY);
+}
+
+float4 __attribute__((kernel)) testNativeHypotFloat4Float4Float4(float4 inX, unsigned int x) {
+    float4 inY = rsGetElementAt_float4(gAllocInY, x);
+    return native_hypot(inX, inY);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeHypotRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeHypotRelaxed.rs
new file mode 100644
index 0000000..79aa107
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeHypotRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeHypot.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLength.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLength.java
new file mode 100644
index 0000000..b3a5df6
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLength.java
@@ -0,0 +1,300 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeLength extends RSBaseCompute {
+
+    private ScriptC_TestNativeLength script;
+    private ScriptC_TestNativeLengthRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeLength(mRS);
+        scriptRelaxed = new ScriptC_TestNativeLengthRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeLengthFloatFloat() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xbe51f0c4d1df20ecl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeLengthFloatFloat(inV, out);
+            verifyResultsNativeLengthFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLengthFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLengthFloatFloat(inV, out);
+            verifyResultsNativeLengthFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLengthFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLengthFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+            // Create the appropriate sized arrays in args
+            // Fill args with the input values
+            args.inV = arrayInV[i];
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeNativeLength(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                message.append("Input inV: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayInV[i], Float.floatToRawIntBits(arrayInV[i]), arrayInV[i]));
+                message.append("\n");
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkNativeLengthFloatFloat" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    public class ArgumentsFloatNFloat {
+        public float[] inV;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeLengthFloat2Float() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xf7c2930af1b4824cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeLengthFloat2Float(inV, out);
+            verifyResultsNativeLengthFloat2Float(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLengthFloat2Float: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLengthFloat2Float(inV, out);
+            verifyResultsNativeLengthFloat2Float(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLengthFloat2Float: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLengthFloat2Float(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloat args = new ArgumentsFloatNFloat();
+            // Create the appropriate sized arrays in args
+            args.inV = new float[2];
+            // Fill args with the input values
+            for (int j = 0; j < 2 ; j++) {
+                args.inV[j] = arrayInV[i * 2 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeNativeLength(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 2 ; j++) {
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInV[i * 2 + j], Float.floatToRawIntBits(arrayInV[i * 2 + j]), arrayInV[i * 2 + j]));
+                    message.append("\n");
+                }
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkNativeLengthFloat2Float" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    private void checkNativeLengthFloat3Float() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xf7c29dac50bb10adl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeLengthFloat3Float(inV, out);
+            verifyResultsNativeLengthFloat3Float(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLengthFloat3Float: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLengthFloat3Float(inV, out);
+            verifyResultsNativeLengthFloat3Float(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLengthFloat3Float: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLengthFloat3Float(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloat args = new ArgumentsFloatNFloat();
+            // Create the appropriate sized arrays in args
+            args.inV = new float[3];
+            // Fill args with the input values
+            for (int j = 0; j < 3 ; j++) {
+                args.inV[j] = arrayInV[i * 4 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeNativeLength(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 3 ; j++) {
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInV[i * 4 + j], Float.floatToRawIntBits(arrayInV[i * 4 + j]), arrayInV[i * 4 + j]));
+                    message.append("\n");
+                }
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkNativeLengthFloat3Float" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    private void checkNativeLengthFloat4Float() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xf7c2a84dafc19f0el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeLengthFloat4Float(inV, out);
+            verifyResultsNativeLengthFloat4Float(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLengthFloat4Float: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLengthFloat4Float(inV, out);
+            verifyResultsNativeLengthFloat4Float(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLengthFloat4Float: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLengthFloat4Float(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloat args = new ArgumentsFloatNFloat();
+            // Create the appropriate sized arrays in args
+            args.inV = new float[4];
+            // Fill args with the input values
+            for (int j = 0; j < 4 ; j++) {
+                args.inV[j] = arrayInV[i * 4 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeNativeLength(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 4 ; j++) {
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInV[i * 4 + j], Float.floatToRawIntBits(arrayInV[i * 4 + j]), arrayInV[i * 4 + j]));
+                    message.append("\n");
+                }
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkNativeLengthFloat4Float" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    public void testNativeLength() {
+        checkNativeLengthFloatFloat();
+        checkNativeLengthFloat2Float();
+        checkNativeLengthFloat3Float();
+        checkNativeLengthFloat4Float();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLength.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLength.rs
new file mode 100644
index 0000000..ae30d2d
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLength.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeLengthFloatFloat(float inV) {
+    return native_length(inV);
+}
+
+float __attribute__((kernel)) testNativeLengthFloat2Float(float2 inV) {
+    return native_length(inV);
+}
+
+float __attribute__((kernel)) testNativeLengthFloat3Float(float3 inV) {
+    return native_length(inV);
+}
+
+float __attribute__((kernel)) testNativeLengthFloat4Float(float4 inV) {
+    return native_length(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLengthRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLengthRelaxed.rs
new file mode 100644
index 0000000..cb03c1e
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLengthRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeLength.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog.java
new file mode 100644
index 0000000..4116cba
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeLog extends RSBaseCompute {
+
+    private ScriptC_TestNativeLog script;
+    private ScriptC_TestNativeLogRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeLog(mRS);
+        scriptRelaxed = new ScriptC_TestNativeLogRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeLogFloatFloat() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x6237b14ee6418d2cl, 10e-10, 10e10);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeLogFloatFloat(inV, out);
+            verifyResultsNativeLogFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLogFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLogFloatFloat(inV, out);
+            verifyResultsNativeLogFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLogFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLogFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeLog(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeLogFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeLogFloat2Float2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x641a5823d3eee3b0l, 10e-10, 10e10);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeLogFloat2Float2(inV, out);
+            verifyResultsNativeLogFloat2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLogFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLogFloat2Float2(inV, out);
+            verifyResultsNativeLogFloat2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLogFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLogFloat2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeLog(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeLogFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeLogFloat3Float3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x641c213eca0a048el, 10e-10, 10e10);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeLogFloat3Float3(inV, out);
+            verifyResultsNativeLogFloat3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLogFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLogFloat3Float3(inV, out);
+            verifyResultsNativeLogFloat3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLogFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLogFloat3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeLog(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeLogFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeLogFloat4Float4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x641dea59c025256cl, 10e-10, 10e10);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeLogFloat4Float4(inV, out);
+            verifyResultsNativeLogFloat4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLogFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLogFloat4Float4(inV, out);
+            verifyResultsNativeLogFloat4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLogFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLogFloat4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeLog(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeLogFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeLog() {
+        checkNativeLogFloatFloat();
+        checkNativeLogFloat2Float2();
+        checkNativeLogFloat3Float3();
+        checkNativeLogFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog.rs
new file mode 100644
index 0000000..05a4688
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeLogFloatFloat(float inV) {
+    return native_log(inV);
+}
+
+float2 __attribute__((kernel)) testNativeLogFloat2Float2(float2 inV) {
+    return native_log(inV);
+}
+
+float3 __attribute__((kernel)) testNativeLogFloat3Float3(float3 inV) {
+    return native_log(inV);
+}
+
+float4 __attribute__((kernel)) testNativeLogFloat4Float4(float4 inV) {
+    return native_log(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog10.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog10.java
new file mode 100644
index 0000000..9a64239
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog10.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeLog10 extends RSBaseCompute {
+
+    private ScriptC_TestNativeLog10 script;
+    private ScriptC_TestNativeLog10Relaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeLog10(mRS);
+        scriptRelaxed = new ScriptC_TestNativeLog10Relaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeLog10FloatFloat() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x4a5d84f60083219dl, 10e-10, 10e10);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeLog10FloatFloat(inV, out);
+            verifyResultsNativeLog10FloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog10FloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLog10FloatFloat(inV, out);
+            verifyResultsNativeLog10FloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog10FloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLog10FloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeLog10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeLog10FloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeLog10Float2Float2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x1d500a10779807d9l, 10e-10, 10e10);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeLog10Float2Float2(inV, out);
+            verifyResultsNativeLog10Float2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog10Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLog10Float2Float2(inV, out);
+            verifyResultsNativeLog10Float2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog10Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLog10Float2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeLog10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeLog10Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeLog10Float3Float3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x1d51d32b6db328b7l, 10e-10, 10e10);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeLog10Float3Float3(inV, out);
+            verifyResultsNativeLog10Float3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog10Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLog10Float3Float3(inV, out);
+            verifyResultsNativeLog10Float3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog10Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLog10Float3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeLog10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeLog10Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeLog10Float4Float4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x1d539c4663ce4995l, 10e-10, 10e10);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeLog10Float4Float4(inV, out);
+            verifyResultsNativeLog10Float4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog10Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLog10Float4Float4(inV, out);
+            verifyResultsNativeLog10Float4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog10Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLog10Float4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeLog10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeLog10Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeLog10() {
+        checkNativeLog10FloatFloat();
+        checkNativeLog10Float2Float2();
+        checkNativeLog10Float3Float3();
+        checkNativeLog10Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog10.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog10.rs
new file mode 100644
index 0000000..3e86a13
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog10.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeLog10FloatFloat(float inV) {
+    return native_log10(inV);
+}
+
+float2 __attribute__((kernel)) testNativeLog10Float2Float2(float2 inV) {
+    return native_log10(inV);
+}
+
+float3 __attribute__((kernel)) testNativeLog10Float3Float3(float3 inV) {
+    return native_log10(inV);
+}
+
+float4 __attribute__((kernel)) testNativeLog10Float4Float4(float4 inV) {
+    return native_log10(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog10Relaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog10Relaxed.rs
new file mode 100644
index 0000000..a00ed08
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog10Relaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeLog10.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog1p.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog1p.java
new file mode 100644
index 0000000..0d88a75
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog1p.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeLog1p extends RSBaseCompute {
+
+    private ScriptC_TestNativeLog1p script;
+    private ScriptC_TestNativeLog1pRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeLog1p(mRS);
+        scriptRelaxed = new ScriptC_TestNativeLog1pRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeLog1pFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x444585911437d95l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeLog1pFloatFloat(in, out);
+            verifyResultsNativeLog1pFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog1pFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLog1pFloatFloat(in, out);
+            verifyResultsNativeLog1pFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog1pFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLog1pFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeLog1p(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeLog1pFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeLog1pFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xd1a13d4961ae8449l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeLog1pFloat2Float2(in, out);
+            verifyResultsNativeLog1pFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog1pFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLog1pFloat2Float2(in, out);
+            verifyResultsNativeLog1pFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog1pFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLog1pFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeLog1p(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeLog1pFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeLog1pFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xd1a147eac0b519e3l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeLog1pFloat3Float3(in, out);
+            verifyResultsNativeLog1pFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog1pFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLog1pFloat3Float3(in, out);
+            verifyResultsNativeLog1pFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog1pFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLog1pFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeLog1p(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeLog1pFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeLog1pFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xd1a1528c1fbbaf7dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeLog1pFloat4Float4(in, out);
+            verifyResultsNativeLog1pFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog1pFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLog1pFloat4Float4(in, out);
+            verifyResultsNativeLog1pFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog1pFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLog1pFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeLog1p(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeLog1pFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeLog1p() {
+        checkNativeLog1pFloatFloat();
+        checkNativeLog1pFloat2Float2();
+        checkNativeLog1pFloat3Float3();
+        checkNativeLog1pFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog1p.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog1p.rs
new file mode 100644
index 0000000..8d9cdd2
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog1p.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeLog1pFloatFloat(float in) {
+    return native_log1p(in);
+}
+
+float2 __attribute__((kernel)) testNativeLog1pFloat2Float2(float2 in) {
+    return native_log1p(in);
+}
+
+float3 __attribute__((kernel)) testNativeLog1pFloat3Float3(float3 in) {
+    return native_log1p(in);
+}
+
+float4 __attribute__((kernel)) testNativeLog1pFloat4Float4(float4 in) {
+    return native_log1p(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog1pRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog1pRelaxed.rs
new file mode 100644
index 0000000..3411c6e
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog1pRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeLog1p.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog2.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog2.java
new file mode 100644
index 0000000..674abb7
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog2.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeLog2 extends RSBaseCompute {
+
+    private ScriptC_TestNativeLog2 script;
+    private ScriptC_TestNativeLog2Relaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeLog2(mRS);
+        scriptRelaxed = new ScriptC_TestNativeLog2Relaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeLog2FloatFloat() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x19b11c9c54fade20l, 10e-10, 10e10);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeLog2FloatFloat(inV, out);
+            verifyResultsNativeLog2FloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog2FloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLog2FloatFloat(inV, out);
+            verifyResultsNativeLog2FloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog2FloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLog2FloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeLog2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeLog2FloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeLog2Float2Float2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x90125a688c689604l, 10e-10, 10e10);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeLog2Float2Float2(inV, out);
+            verifyResultsNativeLog2Float2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLog2Float2Float2(inV, out);
+            verifyResultsNativeLog2Float2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLog2Float2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeLog2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeLog2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeLog2Float3Float3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x901423838283b6e2l, 10e-10, 10e10);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeLog2Float3Float3(inV, out);
+            verifyResultsNativeLog2Float3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog2Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLog2Float3Float3(inV, out);
+            verifyResultsNativeLog2Float3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog2Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLog2Float3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeLog2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeLog2Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeLog2Float4Float4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x9015ec9e789ed7c0l, 10e-10, 10e10);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeLog2Float4Float4(inV, out);
+            verifyResultsNativeLog2Float4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog2Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLog2Float4Float4(inV, out);
+            verifyResultsNativeLog2Float4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog2Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLog2Float4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeLog2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeLog2Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeLog2() {
+        checkNativeLog2FloatFloat();
+        checkNativeLog2Float2Float2();
+        checkNativeLog2Float3Float3();
+        checkNativeLog2Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog2.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog2.rs
new file mode 100644
index 0000000..748a2a0
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog2.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeLog2FloatFloat(float inV) {
+    return native_log2(inV);
+}
+
+float2 __attribute__((kernel)) testNativeLog2Float2Float2(float2 inV) {
+    return native_log2(inV);
+}
+
+float3 __attribute__((kernel)) testNativeLog2Float3Float3(float3 inV) {
+    return native_log2(inV);
+}
+
+float4 __attribute__((kernel)) testNativeLog2Float4Float4(float4 inV) {
+    return native_log2(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog2Relaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog2Relaxed.rs
new file mode 100644
index 0000000..71c2580
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLog2Relaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeLog2.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLogRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLogRelaxed.rs
new file mode 100644
index 0000000..70d5e2f
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeLogRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeLog.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeNormalize.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeNormalize.java
new file mode 100644
index 0000000..42f4553
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeNormalize.java
@@ -0,0 +1,315 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeNormalize extends RSBaseCompute {
+
+    private ScriptC_TestNativeNormalize script;
+    private ScriptC_TestNativeNormalizeRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeNormalize(mRS);
+        scriptRelaxed = new ScriptC_TestNativeNormalizeRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeNormalizeFloatFloat() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x487756167e4aac53l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeNormalizeFloatFloat(inV, out);
+            verifyResultsNativeNormalizeFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeNormalizeFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeNormalizeFloatFloat(inV, out);
+            verifyResultsNativeNormalizeFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeNormalizeFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeNormalizeFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+            // Create the appropriate sized arrays in args
+            // Fill args with the input values
+            args.inV = arrayInV[i];
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeNativeNormalize(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                message.append("Input inV: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayInV[i], Float.floatToRawIntBits(arrayInV[i]), arrayInV[i]));
+                message.append("\n");
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkNativeNormalizeFloatFloat" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    public class ArgumentsFloatNFloatN {
+        public float[] inV;
+        public Target.Floaty[] out;
+    }
+
+    private void checkNativeNormalizeFloat2Float2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x65c77dbcedd0e45fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeNormalizeFloat2Float2(inV, out);
+            verifyResultsNativeNormalizeFloat2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeNormalizeFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeNormalizeFloat2Float2(inV, out);
+            verifyResultsNativeNormalizeFloat2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeNormalizeFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeNormalizeFloat2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloatN args = new ArgumentsFloatNFloatN();
+            // Create the appropriate sized arrays in args
+            args.inV = new float[2];
+            args.out = new Target.Floaty[2];
+            // Fill args with the input values
+            for (int j = 0; j < 2 ; j++) {
+                args.inV[j] = arrayInV[i * 2 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeNativeNormalize(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            for (int j = 0; j < 2 ; j++) {
+                if (!args.out[j].couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 2 ; j++) {
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInV[i * 2 + j], Float.floatToRawIntBits(arrayInV[i * 2 + j]), arrayInV[i * 2 + j]));
+                    message.append("\n");
+                }
+                for (int j = 0; j < 2 ; j++) {
+                    message.append("Expected output out: ");
+                    message.append(args.out[j].toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out[j].couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                }
+                assertTrue("Incorrect output for checkNativeNormalizeFloat2Float2" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    private void checkNativeNormalizeFloat3Float3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x65c946d7e3ec053dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeNormalizeFloat3Float3(inV, out);
+            verifyResultsNativeNormalizeFloat3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeNormalizeFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeNormalizeFloat3Float3(inV, out);
+            verifyResultsNativeNormalizeFloat3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeNormalizeFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeNormalizeFloat3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloatN args = new ArgumentsFloatNFloatN();
+            // Create the appropriate sized arrays in args
+            args.inV = new float[3];
+            args.out = new Target.Floaty[3];
+            // Fill args with the input values
+            for (int j = 0; j < 3 ; j++) {
+                args.inV[j] = arrayInV[i * 4 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeNativeNormalize(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            for (int j = 0; j < 3 ; j++) {
+                if (!args.out[j].couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 3 ; j++) {
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInV[i * 4 + j], Float.floatToRawIntBits(arrayInV[i * 4 + j]), arrayInV[i * 4 + j]));
+                    message.append("\n");
+                }
+                for (int j = 0; j < 3 ; j++) {
+                    message.append("Expected output out: ");
+                    message.append(args.out[j].toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out[j].couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                }
+                assertTrue("Incorrect output for checkNativeNormalizeFloat3Float3" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    private void checkNativeNormalizeFloat4Float4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x65cb0ff2da07261bl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeNormalizeFloat4Float4(inV, out);
+            verifyResultsNativeNormalizeFloat4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeNormalizeFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeNormalizeFloat4Float4(inV, out);
+            verifyResultsNativeNormalizeFloat4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeNormalizeFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeNormalizeFloat4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloatN args = new ArgumentsFloatNFloatN();
+            // Create the appropriate sized arrays in args
+            args.inV = new float[4];
+            args.out = new Target.Floaty[4];
+            // Fill args with the input values
+            for (int j = 0; j < 4 ; j++) {
+                args.inV[j] = arrayInV[i * 4 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeNativeNormalize(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            for (int j = 0; j < 4 ; j++) {
+                if (!args.out[j].couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 4 ; j++) {
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInV[i * 4 + j], Float.floatToRawIntBits(arrayInV[i * 4 + j]), arrayInV[i * 4 + j]));
+                    message.append("\n");
+                }
+                for (int j = 0; j < 4 ; j++) {
+                    message.append("Expected output out: ");
+                    message.append(args.out[j].toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out[j].couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                }
+                assertTrue("Incorrect output for checkNativeNormalizeFloat4Float4" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    public void testNativeNormalize() {
+        checkNativeNormalizeFloatFloat();
+        checkNativeNormalizeFloat2Float2();
+        checkNativeNormalizeFloat3Float3();
+        checkNativeNormalizeFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeNormalize.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeNormalize.rs
new file mode 100644
index 0000000..89e0b52
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeNormalize.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeNormalizeFloatFloat(float inV) {
+    return native_normalize(inV);
+}
+
+float2 __attribute__((kernel)) testNativeNormalizeFloat2Float2(float2 inV) {
+    return native_normalize(inV);
+}
+
+float3 __attribute__((kernel)) testNativeNormalizeFloat3Float3(float3 inV) {
+    return native_normalize(inV);
+}
+
+float4 __attribute__((kernel)) testNativeNormalizeFloat4Float4(float4 inV) {
+    return native_normalize(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeNormalizeRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeNormalizeRelaxed.rs
new file mode 100644
index 0000000..9050ff3
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeNormalizeRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeNormalize.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativePowr.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativePowr.java
new file mode 100644
index 0000000..f19d80c
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativePowr.java
@@ -0,0 +1,325 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativePowr extends RSBaseCompute {
+
+    private ScriptC_TestNativePowr script;
+    private ScriptC_TestNativePowrRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativePowr(mRS);
+        scriptRelaxed = new ScriptC_TestNativePowrRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float inV;
+        public float inY;
+        public Target.Floaty out;
+    }
+
+    private void checkNativePowrFloatFloatFloat() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x3c3550bdff7a10c2l, 0, 256);
+        Allocation inY = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x3c3550bdff7a10c5l, -15, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testNativePowrFloatFloatFloat(inV, out);
+            verifyResultsNativePowrFloatFloatFloat(inV, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativePowrFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testNativePowrFloatFloatFloat(inV, out);
+            verifyResultsNativePowrFloatFloatFloat(inV, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativePowrFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativePowrFloatFloatFloat(Allocation inV, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayInY = new float[INPUTSIZE * 1];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inV = arrayInV[i];
+                args.inY = arrayInY[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativePowr(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativePowrFloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativePowrFloat2Float2Float2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xdbc56fbe7733c926l, 0, 256);
+        Allocation inY = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xdbc56fbe7733c929l, -15, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testNativePowrFloat2Float2Float2(inV, out);
+            verifyResultsNativePowrFloat2Float2Float2(inV, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativePowrFloat2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testNativePowrFloat2Float2Float2(inV, out);
+            verifyResultsNativePowrFloat2Float2Float2(inV, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativePowrFloat2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativePowrFloat2Float2Float2(Allocation inV, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayInY = new float[INPUTSIZE * 2];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                args.inY = arrayInY[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativePowr(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativePowrFloat2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativePowrFloat3Float3Float3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x302a4dde7911cac7l, 0, 256);
+        Allocation inY = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x302a4dde7911cacal, -15, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testNativePowrFloat3Float3Float3(inV, out);
+            verifyResultsNativePowrFloat3Float3Float3(inV, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativePowrFloat3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testNativePowrFloat3Float3Float3(inV, out);
+            verifyResultsNativePowrFloat3Float3Float3(inV, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativePowrFloat3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativePowrFloat3Float3Float3(Allocation inV, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                args.inY = arrayInY[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativePowr(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativePowrFloat3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativePowrFloat4Float4Float4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x848f2bfe7aefcc68l, 0, 256);
+        Allocation inY = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x848f2bfe7aefcc6bl, -15, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testNativePowrFloat4Float4Float4(inV, out);
+            verifyResultsNativePowrFloat4Float4Float4(inV, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativePowrFloat4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testNativePowrFloat4Float4Float4(inV, out);
+            verifyResultsNativePowrFloat4Float4Float4(inV, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativePowrFloat4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativePowrFloat4Float4Float4(Allocation inV, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                args.inY = arrayInY[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativePowr(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativePowrFloat4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativePowr() {
+        checkNativePowrFloatFloatFloat();
+        checkNativePowrFloat2Float2Float2();
+        checkNativePowrFloat3Float3Float3();
+        checkNativePowrFloat4Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativePowr.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativePowr.rs
new file mode 100644
index 0000000..06de2f9
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativePowr.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInY;
+
+float __attribute__((kernel)) testNativePowrFloatFloatFloat(float inV, unsigned int x) {
+    float inY = rsGetElementAt_float(gAllocInY, x);
+    return native_powr(inV, inY);
+}
+
+float2 __attribute__((kernel)) testNativePowrFloat2Float2Float2(float2 inV, unsigned int x) {
+    float2 inY = rsGetElementAt_float2(gAllocInY, x);
+    return native_powr(inV, inY);
+}
+
+float3 __attribute__((kernel)) testNativePowrFloat3Float3Float3(float3 inV, unsigned int x) {
+    float3 inY = rsGetElementAt_float3(gAllocInY, x);
+    return native_powr(inV, inY);
+}
+
+float4 __attribute__((kernel)) testNativePowrFloat4Float4Float4(float4 inV, unsigned int x) {
+    float4 inY = rsGetElementAt_float4(gAllocInY, x);
+    return native_powr(inV, inY);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativePowrRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativePowrRelaxed.rs
new file mode 100644
index 0000000..069e40e
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativePowrRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativePowr.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRecip.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRecip.java
new file mode 100644
index 0000000..976526b
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRecip.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeRecip extends RSBaseCompute {
+
+    private ScriptC_TestNativeRecip script;
+    private ScriptC_TestNativeRecipRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeRecip(mRS);
+        scriptRelaxed = new ScriptC_TestNativeRecipRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeRecipFloatFloat() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x4ec14a4fcc4ed441l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeRecipFloatFloat(inV, out);
+            verifyResultsNativeRecipFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRecipFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeRecipFloatFloat(inV, out);
+            verifyResultsNativeRecipFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRecipFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeRecipFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeRecip(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeRecipFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeRecipFloat2Float2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xd1ec6fa169d54a5dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeRecipFloat2Float2(inV, out);
+            verifyResultsNativeRecipFloat2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRecipFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeRecipFloat2Float2(inV, out);
+            verifyResultsNativeRecipFloat2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRecipFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeRecipFloat2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeRecip(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeRecipFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeRecipFloat3Float3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xd1ee38bc5ff06b3bl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeRecipFloat3Float3(inV, out);
+            verifyResultsNativeRecipFloat3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRecipFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeRecipFloat3Float3(inV, out);
+            verifyResultsNativeRecipFloat3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRecipFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeRecipFloat3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeRecip(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeRecipFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeRecipFloat4Float4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xd1f001d7560b8c19l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeRecipFloat4Float4(inV, out);
+            verifyResultsNativeRecipFloat4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRecipFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeRecipFloat4Float4(inV, out);
+            verifyResultsNativeRecipFloat4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRecipFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeRecipFloat4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeRecip(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeRecipFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeRecip() {
+        checkNativeRecipFloatFloat();
+        checkNativeRecipFloat2Float2();
+        checkNativeRecipFloat3Float3();
+        checkNativeRecipFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRecip.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRecip.rs
new file mode 100644
index 0000000..01220dc
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRecip.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeRecipFloatFloat(float inV) {
+    return native_recip(inV);
+}
+
+float2 __attribute__((kernel)) testNativeRecipFloat2Float2(float2 inV) {
+    return native_recip(inV);
+}
+
+float3 __attribute__((kernel)) testNativeRecipFloat3Float3(float3 inV) {
+    return native_recip(inV);
+}
+
+float4 __attribute__((kernel)) testNativeRecipFloat4Float4(float4 inV) {
+    return native_recip(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRecipRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRecipRelaxed.rs
new file mode 100644
index 0000000..f2cbc83
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRecipRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeRecip.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRootn.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRootn.java
new file mode 100644
index 0000000..d125e3b
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRootn.java
@@ -0,0 +1,321 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeRootn extends RSBaseCompute {
+
+    private ScriptC_TestNativeRootn script;
+    private ScriptC_TestNativeRootnRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeRootn(mRS);
+        scriptRelaxed = new ScriptC_TestNativeRootnRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatIntFloat {
+        public float inV;
+        public int inN;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeRootnFloatIntFloat() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x6693fe5c237ac0f1l, false);
+        Allocation inN = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 1, 0x6693fe5c237ac0e9l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInN(inN);
+            script.forEach_testNativeRootnFloatIntFloat(inV, out);
+            verifyResultsNativeRootnFloatIntFloat(inV, inN, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRootnFloatIntFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInN(inN);
+            scriptRelaxed.forEach_testNativeRootnFloatIntFloat(inV, out);
+            verifyResultsNativeRootnFloatIntFloat(inV, inN, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRootnFloatIntFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeRootnFloatIntFloat(Allocation inV, Allocation inN, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        int[] arrayInN = new int[INPUTSIZE * 1];
+        inN.copyTo(arrayInN);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inV = arrayInV[i];
+                args.inN = arrayInN[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeRootn(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Input inN: ");
+                    message.append(String.format("%d", args.inN));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeRootnFloatIntFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeRootnFloat2Int2Float2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x5363e8c04afd5bcdl, false);
+        Allocation inN = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 2, 0x5363e8c04afd5bc5l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInN(inN);
+            script.forEach_testNativeRootnFloat2Int2Float2(inV, out);
+            verifyResultsNativeRootnFloat2Int2Float2(inV, inN, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRootnFloat2Int2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInN(inN);
+            scriptRelaxed.forEach_testNativeRootnFloat2Int2Float2(inV, out);
+            verifyResultsNativeRootnFloat2Int2Float2(inV, inN, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRootnFloat2Int2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeRootnFloat2Int2Float2(Allocation inV, Allocation inN, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        int[] arrayInN = new int[INPUTSIZE * 2];
+        inN.copyTo(arrayInN);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inV = arrayInV[i * 2 + j];
+                args.inN = arrayInN[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeRootn(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Input inN: ");
+                    message.append(String.format("%d", args.inN));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeRootnFloat2Int2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeRootnFloat3Int3Float3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x791a272340afc886l, false);
+        Allocation inN = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 3, 0x791a272340afc87el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInN(inN);
+            script.forEach_testNativeRootnFloat3Int3Float3(inV, out);
+            verifyResultsNativeRootnFloat3Int3Float3(inV, inN, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRootnFloat3Int3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInN(inN);
+            scriptRelaxed.forEach_testNativeRootnFloat3Int3Float3(inV, out);
+            verifyResultsNativeRootnFloat3Int3Float3(inV, inN, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRootnFloat3Int3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeRootnFloat3Int3Float3(Allocation inV, Allocation inN, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayInN = new int[INPUTSIZE * 4];
+        inN.copyTo(arrayInN);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inV = arrayInV[i * 4 + j];
+                args.inN = arrayInN[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeRootn(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Input inN: ");
+                    message.append(String.format("%d", args.inN));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeRootnFloat3Int3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeRootnFloat4Int4Float4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x9ed065863662353fl, false);
+        Allocation inN = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 4, 0x9ed0658636623537l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInN(inN);
+            script.forEach_testNativeRootnFloat4Int4Float4(inV, out);
+            verifyResultsNativeRootnFloat4Int4Float4(inV, inN, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRootnFloat4Int4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInN(inN);
+            scriptRelaxed.forEach_testNativeRootnFloat4Int4Float4(inV, out);
+            verifyResultsNativeRootnFloat4Int4Float4(inV, inN, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRootnFloat4Int4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeRootnFloat4Int4Float4(Allocation inV, Allocation inN, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayInN = new int[INPUTSIZE * 4];
+        inN.copyTo(arrayInN);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inV = arrayInV[i * 4 + j];
+                args.inN = arrayInN[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeRootn(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Input inN: ");
+                    message.append(String.format("%d", args.inN));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeRootnFloat4Int4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeRootn() {
+        checkNativeRootnFloatIntFloat();
+        checkNativeRootnFloat2Int2Float2();
+        checkNativeRootnFloat3Int3Float3();
+        checkNativeRootnFloat4Int4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRootn.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRootn.rs
new file mode 100644
index 0000000..1aeb2b2
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRootn.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInN;
+
+float __attribute__((kernel)) testNativeRootnFloatIntFloat(float inV, unsigned int x) {
+    int inN = rsGetElementAt_int(gAllocInN, x);
+    return native_rootn(inV, inN);
+}
+
+float2 __attribute__((kernel)) testNativeRootnFloat2Int2Float2(float2 inV, unsigned int x) {
+    int2 inN = rsGetElementAt_int2(gAllocInN, x);
+    return native_rootn(inV, inN);
+}
+
+float3 __attribute__((kernel)) testNativeRootnFloat3Int3Float3(float3 inV, unsigned int x) {
+    int3 inN = rsGetElementAt_int3(gAllocInN, x);
+    return native_rootn(inV, inN);
+}
+
+float4 __attribute__((kernel)) testNativeRootnFloat4Int4Float4(float4 inV, unsigned int x) {
+    int4 inN = rsGetElementAt_int4(gAllocInN, x);
+    return native_rootn(inV, inN);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRootnRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRootnRelaxed.rs
new file mode 100644
index 0000000..3b05992
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRootnRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeRootn.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRsqrt.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRsqrt.java
new file mode 100644
index 0000000..fc2549d
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRsqrt.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeRsqrt extends RSBaseCompute {
+
+    private ScriptC_TestNativeRsqrt script;
+    private ScriptC_TestNativeRsqrtRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeRsqrt(mRS);
+        scriptRelaxed = new ScriptC_TestNativeRsqrtRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeRsqrtFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xf3cf23b51aa29de0l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeRsqrtFloatFloat(in, out);
+            verifyResultsNativeRsqrtFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRsqrtFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeRsqrtFloatFloat(in, out);
+            verifyResultsNativeRsqrtFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRsqrtFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeRsqrtFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeRsqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeRsqrtFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeRsqrtFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xf318090911bec1fcl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeRsqrtFloat2Float2(in, out);
+            verifyResultsNativeRsqrtFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRsqrtFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeRsqrtFloat2Float2(in, out);
+            verifyResultsNativeRsqrtFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRsqrtFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeRsqrtFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeRsqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeRsqrtFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeRsqrtFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xf31813aa70c55796l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeRsqrtFloat3Float3(in, out);
+            verifyResultsNativeRsqrtFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRsqrtFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeRsqrtFloat3Float3(in, out);
+            verifyResultsNativeRsqrtFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRsqrtFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeRsqrtFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeRsqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeRsqrtFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeRsqrtFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xf3181e4bcfcbed30l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeRsqrtFloat4Float4(in, out);
+            verifyResultsNativeRsqrtFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRsqrtFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeRsqrtFloat4Float4(in, out);
+            verifyResultsNativeRsqrtFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRsqrtFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeRsqrtFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeRsqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeRsqrtFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeRsqrt() {
+        checkNativeRsqrtFloatFloat();
+        checkNativeRsqrtFloat2Float2();
+        checkNativeRsqrtFloat3Float3();
+        checkNativeRsqrtFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRsqrt.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRsqrt.rs
new file mode 100644
index 0000000..af291cb
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRsqrt.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeRsqrtFloatFloat(float in) {
+    return native_rsqrt(in);
+}
+
+float2 __attribute__((kernel)) testNativeRsqrtFloat2Float2(float2 in) {
+    return native_rsqrt(in);
+}
+
+float3 __attribute__((kernel)) testNativeRsqrtFloat3Float3(float3 in) {
+    return native_rsqrt(in);
+}
+
+float4 __attribute__((kernel)) testNativeRsqrtFloat4Float4(float4 in) {
+    return native_rsqrt(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRsqrtRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRsqrtRelaxed.rs
new file mode 100644
index 0000000..c18cc22
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeRsqrtRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeRsqrt.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSin.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSin.java
new file mode 100644
index 0000000..1637326
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSin.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeSin extends RSBaseCompute {
+
+    private ScriptC_TestNativeSin script;
+    private ScriptC_TestNativeSinRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeSin(mRS);
+        scriptRelaxed = new ScriptC_TestNativeSinRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeSinFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x33ee19763354cc56l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeSinFloatFloat(in, out);
+            verifyResultsNativeSinFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSinFloatFloat(in, out);
+            verifyResultsNativeSinFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSinFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeSin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeSinFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeSinFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x12b508b470b05442l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeSinFloat2Float2(in, out);
+            verifyResultsNativeSinFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSinFloat2Float2(in, out);
+            verifyResultsNativeSinFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSinFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeSin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeSinFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeSinFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x12b51355cfb6e9dcl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeSinFloat3Float3(in, out);
+            verifyResultsNativeSinFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSinFloat3Float3(in, out);
+            verifyResultsNativeSinFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSinFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeSin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeSinFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeSinFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x12b51df72ebd7f76l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeSinFloat4Float4(in, out);
+            verifyResultsNativeSinFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSinFloat4Float4(in, out);
+            verifyResultsNativeSinFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSinFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeSin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeSinFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeSin() {
+        checkNativeSinFloatFloat();
+        checkNativeSinFloat2Float2();
+        checkNativeSinFloat3Float3();
+        checkNativeSinFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSin.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSin.rs
new file mode 100644
index 0000000..1af8929
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSin.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeSinFloatFloat(float in) {
+    return native_sin(in);
+}
+
+float2 __attribute__((kernel)) testNativeSinFloat2Float2(float2 in) {
+    return native_sin(in);
+}
+
+float3 __attribute__((kernel)) testNativeSinFloat3Float3(float3 in) {
+    return native_sin(in);
+}
+
+float4 __attribute__((kernel)) testNativeSinFloat4Float4(float4 in) {
+    return native_sin(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSinRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSinRelaxed.rs
new file mode 100644
index 0000000..e3dbf27
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSinRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeSin.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSincos.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSincos.java
new file mode 100644
index 0000000..380f2b4
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSincos.java
@@ -0,0 +1,361 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeSincos extends RSBaseCompute {
+
+    private ScriptC_TestNativeSincos script;
+    private ScriptC_TestNativeSincosRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeSincos(mRS);
+        scriptRelaxed = new ScriptC_TestNativeSincosRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float inV;
+        public Target.Floaty outCosptr;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeSincosFloatFloatFloat() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xe15df2366436cc13l, false);
+        try {
+            Allocation outCosptr = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocOutCosptr(outCosptr);
+            script.forEach_testNativeSincosFloatFloatFloat(inV, out);
+            verifyResultsNativeSincosFloatFloatFloat(inV, outCosptr, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSincosFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation outCosptr = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutCosptr(outCosptr);
+            scriptRelaxed.forEach_testNativeSincosFloatFloatFloat(inV, out);
+            verifyResultsNativeSincosFloatFloatFloat(inV, outCosptr, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSincosFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSincosFloatFloatFloat(Allocation inV, Allocation outCosptr, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOutCosptr = new float[INPUTSIZE * 1];
+        outCosptr.copyTo(arrayOutCosptr);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeSincos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outCosptr.couldBe(arrayOutCosptr[i * 1 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(arrayOut[i * 1 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output outCosptr: ");
+                    message.append(args.outCosptr.toString());
+                    message.append("\n");
+                    message.append("Actual   output outCosptr: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOutCosptr[i * 1 + j], Float.floatToRawIntBits(arrayOutCosptr[i * 1 + j]), arrayOutCosptr[i * 1 + j]));
+                    if (!args.outCosptr.couldBe(arrayOutCosptr[i * 1 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeSincosFloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeSincosFloat2Float2Float2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xe5a1f1dcda676ea9l, false);
+        try {
+            Allocation outCosptr = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocOutCosptr(outCosptr);
+            script.forEach_testNativeSincosFloat2Float2Float2(inV, out);
+            verifyResultsNativeSincosFloat2Float2Float2(inV, outCosptr, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSincosFloat2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation outCosptr = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutCosptr(outCosptr);
+            scriptRelaxed.forEach_testNativeSincosFloat2Float2Float2(inV, out);
+            verifyResultsNativeSincosFloat2Float2Float2(inV, outCosptr, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSincosFloat2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSincosFloat2Float2Float2(Allocation inV, Allocation outCosptr, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOutCosptr = new float[INPUTSIZE * 2];
+        outCosptr.copyTo(arrayOutCosptr);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeSincos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outCosptr.couldBe(arrayOutCosptr[i * 2 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(arrayOut[i * 2 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output outCosptr: ");
+                    message.append(args.outCosptr.toString());
+                    message.append("\n");
+                    message.append("Actual   output outCosptr: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOutCosptr[i * 2 + j], Float.floatToRawIntBits(arrayOutCosptr[i * 2 + j]), arrayOutCosptr[i * 2 + j]));
+                    if (!args.outCosptr.couldBe(arrayOutCosptr[i * 2 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeSincosFloat2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeSincosFloat3Float3Float3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x3a06cffcdc45704al, false);
+        try {
+            Allocation outCosptr = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocOutCosptr(outCosptr);
+            script.forEach_testNativeSincosFloat3Float3Float3(inV, out);
+            verifyResultsNativeSincosFloat3Float3Float3(inV, outCosptr, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSincosFloat3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation outCosptr = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutCosptr(outCosptr);
+            scriptRelaxed.forEach_testNativeSincosFloat3Float3Float3(inV, out);
+            verifyResultsNativeSincosFloat3Float3Float3(inV, outCosptr, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSincosFloat3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSincosFloat3Float3Float3(Allocation inV, Allocation outCosptr, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOutCosptr = new float[INPUTSIZE * 4];
+        outCosptr.copyTo(arrayOutCosptr);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeSincos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outCosptr.couldBe(arrayOutCosptr[i * 4 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output outCosptr: ");
+                    message.append(args.outCosptr.toString());
+                    message.append("\n");
+                    message.append("Actual   output outCosptr: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOutCosptr[i * 4 + j], Float.floatToRawIntBits(arrayOutCosptr[i * 4 + j]), arrayOutCosptr[i * 4 + j]));
+                    if (!args.outCosptr.couldBe(arrayOutCosptr[i * 4 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeSincosFloat3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeSincosFloat4Float4Float4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x8e6bae1cde2371ebl, false);
+        try {
+            Allocation outCosptr = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocOutCosptr(outCosptr);
+            script.forEach_testNativeSincosFloat4Float4Float4(inV, out);
+            verifyResultsNativeSincosFloat4Float4Float4(inV, outCosptr, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSincosFloat4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation outCosptr = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutCosptr(outCosptr);
+            scriptRelaxed.forEach_testNativeSincosFloat4Float4Float4(inV, out);
+            verifyResultsNativeSincosFloat4Float4Float4(inV, outCosptr, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSincosFloat4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSincosFloat4Float4Float4(Allocation inV, Allocation outCosptr, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOutCosptr = new float[INPUTSIZE * 4];
+        outCosptr.copyTo(arrayOutCosptr);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeSincos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outCosptr.couldBe(arrayOutCosptr[i * 4 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output outCosptr: ");
+                    message.append(args.outCosptr.toString());
+                    message.append("\n");
+                    message.append("Actual   output outCosptr: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOutCosptr[i * 4 + j], Float.floatToRawIntBits(arrayOutCosptr[i * 4 + j]), arrayOutCosptr[i * 4 + j]));
+                    if (!args.outCosptr.couldBe(arrayOutCosptr[i * 4 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j], 0.0005)) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeSincosFloat4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeSincos() {
+        checkNativeSincosFloatFloatFloat();
+        checkNativeSincosFloat2Float2Float2();
+        checkNativeSincosFloat3Float3Float3();
+        checkNativeSincosFloat4Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSincos.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSincos.rs
new file mode 100644
index 0000000..8148c67
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSincos.rs
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocOutCosptr;
+
+float __attribute__((kernel)) testNativeSincosFloatFloatFloat(float inV, unsigned int x) {
+    float outCosptr = 0;
+    float out = native_sincos(inV, &outCosptr);
+    rsSetElementAt_float(gAllocOutCosptr, outCosptr, x);
+    return out;
+}
+
+float2 __attribute__((kernel)) testNativeSincosFloat2Float2Float2(float2 inV, unsigned int x) {
+    float2 outCosptr = 0;
+    float2 out = native_sincos(inV, &outCosptr);
+    rsSetElementAt_float2(gAllocOutCosptr, outCosptr, x);
+    return out;
+}
+
+float3 __attribute__((kernel)) testNativeSincosFloat3Float3Float3(float3 inV, unsigned int x) {
+    float3 outCosptr = 0;
+    float3 out = native_sincos(inV, &outCosptr);
+    rsSetElementAt_float3(gAllocOutCosptr, outCosptr, x);
+    return out;
+}
+
+float4 __attribute__((kernel)) testNativeSincosFloat4Float4Float4(float4 inV, unsigned int x) {
+    float4 outCosptr = 0;
+    float4 out = native_sincos(inV, &outCosptr);
+    rsSetElementAt_float4(gAllocOutCosptr, outCosptr, x);
+    return out;
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSincosRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSincosRelaxed.rs
new file mode 100644
index 0000000..175e265
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSincosRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeSincos.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSinh.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSinh.java
new file mode 100644
index 0000000..9c2edc7
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSinh.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeSinh extends RSBaseCompute {
+
+    private ScriptC_TestNativeSinh script;
+    private ScriptC_TestNativeSinhRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeSinh(mRS);
+        scriptRelaxed = new ScriptC_TestNativeSinhRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeSinhFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x74dcf3e9c65b6590l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeSinhFloatFloat(in, out);
+            verifyResultsNativeSinhFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinhFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSinhFloatFloat(in, out);
+            verifyResultsNativeSinhFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinhFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSinhFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeSinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeSinhFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeSinhFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xfdcd5755b59082cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeSinhFloat2Float2(in, out);
+            verifyResultsNativeSinhFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinhFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSinhFloat2Float2(in, out);
+            verifyResultsNativeSinhFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinhFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSinhFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeSinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeSinhFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeSinhFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xfdce016ba5f9dc6l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeSinhFloat3Float3(in, out);
+            verifyResultsNativeSinhFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinhFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSinhFloat3Float3(in, out);
+            verifyResultsNativeSinhFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinhFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSinhFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeSinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeSinhFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeSinhFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xfdceab819663360l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeSinhFloat4Float4(in, out);
+            verifyResultsNativeSinhFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinhFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSinhFloat4Float4(in, out);
+            verifyResultsNativeSinhFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinhFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSinhFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeSinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeSinhFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeSinh() {
+        checkNativeSinhFloatFloat();
+        checkNativeSinhFloat2Float2();
+        checkNativeSinhFloat3Float3();
+        checkNativeSinhFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSinh.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSinh.rs
new file mode 100644
index 0000000..20728d5
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSinh.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeSinhFloatFloat(float in) {
+    return native_sinh(in);
+}
+
+float2 __attribute__((kernel)) testNativeSinhFloat2Float2(float2 in) {
+    return native_sinh(in);
+}
+
+float3 __attribute__((kernel)) testNativeSinhFloat3Float3(float3 in) {
+    return native_sinh(in);
+}
+
+float4 __attribute__((kernel)) testNativeSinhFloat4Float4(float4 in) {
+    return native_sinh(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSinhRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSinhRelaxed.rs
new file mode 100644
index 0000000..7ba4ce8
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSinhRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeSinh.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSinpi.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSinpi.java
new file mode 100644
index 0000000..2f67e8e
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSinpi.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeSinpi extends RSBaseCompute {
+
+    private ScriptC_TestNativeSinpi script;
+    private ScriptC_TestNativeSinpiRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeSinpi(mRS);
+        scriptRelaxed = new ScriptC_TestNativeSinpiRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeSinpiFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xb52c701227c9dc37l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeSinpiFloatFloat(in, out);
+            verifyResultsNativeSinpiFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinpiFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSinpiFloatFloat(in, out);
+            verifyResultsNativeSinpiFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinpiFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSinpiFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeSinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeSinpiFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeSinpiFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x8df4951d1230045bl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeSinpiFloat2Float2(in, out);
+            verifyResultsNativeSinpiFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinpiFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSinpiFloat2Float2(in, out);
+            verifyResultsNativeSinpiFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinpiFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSinpiFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeSinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeSinpiFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeSinpiFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x8df49fbe713699f5l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeSinpiFloat3Float3(in, out);
+            verifyResultsNativeSinpiFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinpiFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSinpiFloat3Float3(in, out);
+            verifyResultsNativeSinpiFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinpiFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSinpiFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeSinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeSinpiFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeSinpiFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x8df4aa5fd03d2f8fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeSinpiFloat4Float4(in, out);
+            verifyResultsNativeSinpiFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinpiFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSinpiFloat4Float4(in, out);
+            verifyResultsNativeSinpiFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinpiFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSinpiFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeSinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeSinpiFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeSinpi() {
+        checkNativeSinpiFloatFloat();
+        checkNativeSinpiFloat2Float2();
+        checkNativeSinpiFloat3Float3();
+        checkNativeSinpiFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSinpi.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSinpi.rs
new file mode 100644
index 0000000..1b17471
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSinpi.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeSinpiFloatFloat(float in) {
+    return native_sinpi(in);
+}
+
+float2 __attribute__((kernel)) testNativeSinpiFloat2Float2(float2 in) {
+    return native_sinpi(in);
+}
+
+float3 __attribute__((kernel)) testNativeSinpiFloat3Float3(float3 in) {
+    return native_sinpi(in);
+}
+
+float4 __attribute__((kernel)) testNativeSinpiFloat4Float4(float4 in) {
+    return native_sinpi(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSinpiRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSinpiRelaxed.rs
new file mode 100644
index 0000000..2bc871f
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSinpiRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeSinpi.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSqrt.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSqrt.java
new file mode 100644
index 0000000..edb07bc
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSqrt.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeSqrt extends RSBaseCompute {
+
+    private ScriptC_TestNativeSqrt script;
+    private ScriptC_TestNativeSqrtRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeSqrt(mRS);
+        scriptRelaxed = new ScriptC_TestNativeSqrtRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeSqrtFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xb4c9e7b9972ac810l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeSqrtFloatFloat(in, out);
+            verifyResultsNativeSqrtFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSqrtFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSqrtFloatFloat(in, out);
+            verifyResultsNativeSqrtFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSqrtFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSqrtFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeSqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeSqrtFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeSqrtFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xc649cd70853776acl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeSqrtFloat2Float2(in, out);
+            verifyResultsNativeSqrtFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSqrtFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSqrtFloat2Float2(in, out);
+            verifyResultsNativeSqrtFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSqrtFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSqrtFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeSqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeSqrtFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeSqrtFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xc649d811e43e0c46l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeSqrtFloat3Float3(in, out);
+            verifyResultsNativeSqrtFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSqrtFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSqrtFloat3Float3(in, out);
+            verifyResultsNativeSqrtFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSqrtFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSqrtFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeSqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeSqrtFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeSqrtFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xc649e2b34344a1e0l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeSqrtFloat4Float4(in, out);
+            verifyResultsNativeSqrtFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSqrtFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSqrtFloat4Float4(in, out);
+            verifyResultsNativeSqrtFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSqrtFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSqrtFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeSqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeSqrtFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeSqrt() {
+        checkNativeSqrtFloatFloat();
+        checkNativeSqrtFloat2Float2();
+        checkNativeSqrtFloat3Float3();
+        checkNativeSqrtFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSqrt.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSqrt.rs
new file mode 100644
index 0000000..2ed1cc8
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSqrt.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeSqrtFloatFloat(float in) {
+    return native_sqrt(in);
+}
+
+float2 __attribute__((kernel)) testNativeSqrtFloat2Float2(float2 in) {
+    return native_sqrt(in);
+}
+
+float3 __attribute__((kernel)) testNativeSqrtFloat3Float3(float3 in) {
+    return native_sqrt(in);
+}
+
+float4 __attribute__((kernel)) testNativeSqrtFloat4Float4(float4 in) {
+    return native_sqrt(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSqrtRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSqrtRelaxed.rs
new file mode 100644
index 0000000..aa39435
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeSqrtRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeSqrt.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTan.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTan.java
new file mode 100644
index 0000000..cd51a53
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTan.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeTan extends RSBaseCompute {
+
+    private ScriptC_TestNativeTan script;
+    private ScriptC_TestNativeTanRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeTan(mRS);
+        scriptRelaxed = new ScriptC_TestNativeTanRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeTanFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x5b9a224e25042b47l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeTanFloatFloat(in, out);
+            verifyResultsNativeTanFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeTanFloatFloat(in, out);
+            verifyResultsNativeTanFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeTanFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeTan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeTanFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeTanFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x9c40e8650c550eebl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeTanFloat2Float2(in, out);
+            verifyResultsNativeTanFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeTanFloat2Float2(in, out);
+            verifyResultsNativeTanFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeTanFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeTan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeTanFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeTanFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x9c40f3066b5ba485l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeTanFloat3Float3(in, out);
+            verifyResultsNativeTanFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeTanFloat3Float3(in, out);
+            verifyResultsNativeTanFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeTanFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeTan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeTanFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeTanFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x9c40fda7ca623a1fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeTanFloat4Float4(in, out);
+            verifyResultsNativeTanFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeTanFloat4Float4(in, out);
+            verifyResultsNativeTanFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeTanFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeTan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeTanFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeTan() {
+        checkNativeTanFloatFloat();
+        checkNativeTanFloat2Float2();
+        checkNativeTanFloat3Float3();
+        checkNativeTanFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTan.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTan.rs
new file mode 100644
index 0000000..000bc74
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTan.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeTanFloatFloat(float in) {
+    return native_tan(in);
+}
+
+float2 __attribute__((kernel)) testNativeTanFloat2Float2(float2 in) {
+    return native_tan(in);
+}
+
+float3 __attribute__((kernel)) testNativeTanFloat3Float3(float3 in) {
+    return native_tan(in);
+}
+
+float4 __attribute__((kernel)) testNativeTanFloat4Float4(float4 in) {
+    return native_tan(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTanRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTanRelaxed.rs
new file mode 100644
index 0000000..9ec6688
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTanRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeTan.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTanh.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTanh.java
new file mode 100644
index 0000000..0b69e5f
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTanh.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeTanh extends RSBaseCompute {
+
+    private ScriptC_TestNativeTanh script;
+    private ScriptC_TestNativeTanhRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeTanh(mRS);
+        scriptRelaxed = new ScriptC_TestNativeTanhRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeTanhFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x1ec2702f5ed0580bl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeTanhFloatFloat(in, out);
+            verifyResultsNativeTanhFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanhFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeTanhFloatFloat(in, out);
+            verifyResultsNativeTanhFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanhFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeTanhFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeTanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeTanhFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeTanhFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x2a5b681f8004628fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeTanhFloat2Float2(in, out);
+            verifyResultsNativeTanhFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanhFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeTanhFloat2Float2(in, out);
+            verifyResultsNativeTanhFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanhFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeTanhFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeTanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeTanhFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeTanhFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x2a5b72c0df0af829l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeTanhFloat3Float3(in, out);
+            verifyResultsNativeTanhFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanhFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeTanhFloat3Float3(in, out);
+            verifyResultsNativeTanhFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanhFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeTanhFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeTanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeTanhFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeTanhFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x2a5b7d623e118dc3l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeTanhFloat4Float4(in, out);
+            verifyResultsNativeTanhFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanhFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeTanhFloat4Float4(in, out);
+            verifyResultsNativeTanhFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanhFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeTanhFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeTanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeTanhFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeTanh() {
+        checkNativeTanhFloatFloat();
+        checkNativeTanhFloat2Float2();
+        checkNativeTanhFloat3Float3();
+        checkNativeTanhFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTanh.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTanh.rs
new file mode 100644
index 0000000..a7bfcfd
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTanh.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeTanhFloatFloat(float in) {
+    return native_tanh(in);
+}
+
+float2 __attribute__((kernel)) testNativeTanhFloat2Float2(float2 in) {
+    return native_tanh(in);
+}
+
+float3 __attribute__((kernel)) testNativeTanhFloat3Float3(float3 in) {
+    return native_tanh(in);
+}
+
+float4 __attribute__((kernel)) testNativeTanhFloat4Float4(float4 in) {
+    return native_tanh(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTanhRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTanhRelaxed.rs
new file mode 100644
index 0000000..27c9275
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTanhRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeTanh.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTanpi.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTanpi.java
new file mode 100644
index 0000000..1d9b538
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTanpi.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNativeTanpi extends RSBaseCompute {
+
+    private ScriptC_TestNativeTanpi script;
+    private ScriptC_TestNativeTanpiRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNativeTanpi(mRS);
+        scriptRelaxed = new ScriptC_TestNativeTanpiRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeTanpiFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x3eb84fc2c36e96e0l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNativeTanpiFloatFloat(in, out);
+            verifyResultsNativeTanpiFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanpiFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeTanpiFloatFloat(in, out);
+            verifyResultsNativeTanpiFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanpiFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeTanpiFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeTanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeTanpiFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeTanpiFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x13737b13af832fcl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNativeTanpiFloat2Float2(in, out);
+            verifyResultsNativeTanpiFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanpiFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeTanpiFloat2Float2(in, out);
+            verifyResultsNativeTanpiFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanpiFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeTanpiFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeTanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeTanpiFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeTanpiFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x137425299fec896l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNativeTanpiFloat3Float3(in, out);
+            verifyResultsNativeTanpiFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanpiFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeTanpiFloat3Float3(in, out);
+            verifyResultsNativeTanpiFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanpiFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeTanpiFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeTanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeTanpiFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNativeTanpiFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x1374cf3f9055e30l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNativeTanpiFloat4Float4(in, out);
+            verifyResultsNativeTanpiFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanpiFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeTanpiFloat4Float4(in, out);
+            verifyResultsNativeTanpiFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanpiFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeTanpiFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNativeTanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNativeTanpiFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNativeTanpi() {
+        checkNativeTanpiFloatFloat();
+        checkNativeTanpiFloat2Float2();
+        checkNativeTanpiFloat3Float3();
+        checkNativeTanpiFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTanpi.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTanpi.rs
new file mode 100644
index 0000000..ae1f633
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTanpi.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNativeTanpiFloatFloat(float in) {
+    return native_tanpi(in);
+}
+
+float2 __attribute__((kernel)) testNativeTanpiFloat2Float2(float2 in) {
+    return native_tanpi(in);
+}
+
+float3 __attribute__((kernel)) testNativeTanpiFloat3Float3(float3 in) {
+    return native_tanpi(in);
+}
+
+float4 __attribute__((kernel)) testNativeTanpiFloat4Float4(float4 in) {
+    return native_tanpi(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTanpiRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTanpiRelaxed.rs
new file mode 100644
index 0000000..921fa3c
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNativeTanpiRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNativeTanpi.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNextafter.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNextafter.java
new file mode 100644
index 0000000..df69e42
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNextafter.java
@@ -0,0 +1,325 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNextafter extends RSBaseCompute {
+
+    private ScriptC_TestNextafter script;
+    private ScriptC_TestNextafterRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNextafter(mRS);
+        scriptRelaxed = new ScriptC_TestNextafterRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float inX;
+        public float inY;
+        public Target.Floaty out;
+    }
+
+    private void checkNextafterFloatFloatFloat() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xa3b02393ad412958l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xa3b02393ad412959l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testNextafterFloatFloatFloat(inX, out);
+            verifyResultsNextafterFloatFloatFloat(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNextafterFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testNextafterFloatFloatFloat(inX, out);
+            verifyResultsNextafterFloatFloatFloat(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNextafterFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNextafterFloatFloatFloat(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 1];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 1];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i];
+                args.inY = arrayInY[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNextafter(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNextafterFloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNextafterFloat2Float2Float2() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x29b40e0584a1e24l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x29b40e0584a1e25l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testNextafterFloat2Float2Float2(inX, out);
+            verifyResultsNextafterFloat2Float2Float2(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNextafterFloat2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testNextafterFloat2Float2Float2(inX, out);
+            verifyResultsNextafterFloat2Float2Float2(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNextafterFloat2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNextafterFloat2Float2Float2(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 2];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 2];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 2 + j];
+                args.inY = arrayInY[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNextafter(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNextafterFloat2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNextafterFloat3Float3Float3() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x57001f005a281fc5l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x57001f005a281fc6l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testNextafterFloat3Float3Float3(inX, out);
+            verifyResultsNextafterFloat3Float3Float3(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNextafterFloat3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testNextafterFloat3Float3Float3(inX, out);
+            verifyResultsNextafterFloat3Float3Float3(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNextafterFloat3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNextafterFloat3Float3Float3(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNextafter(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNextafterFloat3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkNextafterFloat4Float4Float4() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xab64fd205c062166l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xab64fd205c062167l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testNextafterFloat4Float4Float4(inX, out);
+            verifyResultsNextafterFloat4Float4Float4(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNextafterFloat4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testNextafterFloat4Float4Float4(inX, out);
+            verifyResultsNextafterFloat4Float4Float4(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNextafterFloat4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNextafterFloat4Float4Float4(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeNextafter(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkNextafterFloat4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testNextafter() {
+        checkNextafterFloatFloatFloat();
+        checkNextafterFloat2Float2Float2();
+        checkNextafterFloat3Float3Float3();
+        checkNextafterFloat4Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNextafter.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNextafter.rs
new file mode 100644
index 0000000..a7ae02d
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNextafter.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInY;
+
+float __attribute__((kernel)) testNextafterFloatFloatFloat(float inX, unsigned int x) {
+    float inY = rsGetElementAt_float(gAllocInY, x);
+    return nextafter(inX, inY);
+}
+
+float2 __attribute__((kernel)) testNextafterFloat2Float2Float2(float2 inX, unsigned int x) {
+    float2 inY = rsGetElementAt_float2(gAllocInY, x);
+    return nextafter(inX, inY);
+}
+
+float3 __attribute__((kernel)) testNextafterFloat3Float3Float3(float3 inX, unsigned int x) {
+    float3 inY = rsGetElementAt_float3(gAllocInY, x);
+    return nextafter(inX, inY);
+}
+
+float4 __attribute__((kernel)) testNextafterFloat4Float4Float4(float4 inX, unsigned int x) {
+    float4 inY = rsGetElementAt_float4(gAllocInY, x);
+    return nextafter(inX, inY);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNextafterRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNextafterRelaxed.rs
new file mode 100644
index 0000000..2111f17
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNextafterRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNextafter.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNormalize.java b/tests/tests/renderscript/src/android/renderscript/cts/TestNormalize.java
new file mode 100644
index 0000000..0d71ec5
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNormalize.java
@@ -0,0 +1,315 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestNormalize extends RSBaseCompute {
+
+    private ScriptC_TestNormalize script;
+    private ScriptC_TestNormalizeRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNormalize(mRS);
+        scriptRelaxed = new ScriptC_TestNormalizeRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkNormalizeFloatFloat() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x6db01d449460061cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testNormalizeFloatFloat(inV, out);
+            verifyResultsNormalizeFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNormalizeFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNormalizeFloatFloat(inV, out);
+            verifyResultsNormalizeFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNormalizeFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNormalizeFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+            // Create the appropriate sized arrays in args
+            // Fill args with the input values
+            args.inV = arrayInV[i];
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeNormalize(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(arrayOut[i])) {
+                valid = false;
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                message.append("Input inV: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayInV[i], Float.floatToRawIntBits(arrayInV[i]), arrayInV[i]));
+                message.append("\n");
+                message.append("Expected output out: ");
+                message.append(args.out.toString());
+                message.append("\n");
+                message.append("Actual   output out: ");
+                message.append(String.format("%14.8g {%8x} %15a",
+                        arrayOut[i], Float.floatToRawIntBits(arrayOut[i]), arrayOut[i]));
+                if (!args.out.couldBe(arrayOut[i])) {
+                    message.append(" FAIL");
+                }
+                message.append("\n");
+                assertTrue("Incorrect output for checkNormalizeFloatFloat" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    public class ArgumentsFloatNFloatN {
+        public float[] inV;
+        public Target.Floaty[] out;
+    }
+
+    private void checkNormalizeFloat2Float2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x3cde199a6e066120l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testNormalizeFloat2Float2(inV, out);
+            verifyResultsNormalizeFloat2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNormalizeFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNormalizeFloat2Float2(inV, out);
+            verifyResultsNormalizeFloat2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNormalizeFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNormalizeFloat2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloatN args = new ArgumentsFloatNFloatN();
+            // Create the appropriate sized arrays in args
+            args.inV = new float[2];
+            args.out = new Target.Floaty[2];
+            // Fill args with the input values
+            for (int j = 0; j < 2 ; j++) {
+                args.inV[j] = arrayInV[i * 2 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeNormalize(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            for (int j = 0; j < 2 ; j++) {
+                if (!args.out[j].couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 2 ; j++) {
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInV[i * 2 + j], Float.floatToRawIntBits(arrayInV[i * 2 + j]), arrayInV[i * 2 + j]));
+                    message.append("\n");
+                }
+                for (int j = 0; j < 2 ; j++) {
+                    message.append("Expected output out: ");
+                    message.append(args.out[j].toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out[j].couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                }
+                assertTrue("Incorrect output for checkNormalizeFloat2Float2" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    private void checkNormalizeFloat3Float3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x3cdfe2b5642181fel, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testNormalizeFloat3Float3(inV, out);
+            verifyResultsNormalizeFloat3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNormalizeFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNormalizeFloat3Float3(inV, out);
+            verifyResultsNormalizeFloat3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNormalizeFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNormalizeFloat3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloatN args = new ArgumentsFloatNFloatN();
+            // Create the appropriate sized arrays in args
+            args.inV = new float[3];
+            args.out = new Target.Floaty[3];
+            // Fill args with the input values
+            for (int j = 0; j < 3 ; j++) {
+                args.inV[j] = arrayInV[i * 4 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeNormalize(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            for (int j = 0; j < 3 ; j++) {
+                if (!args.out[j].couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 3 ; j++) {
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInV[i * 4 + j], Float.floatToRawIntBits(arrayInV[i * 4 + j]), arrayInV[i * 4 + j]));
+                    message.append("\n");
+                }
+                for (int j = 0; j < 3 ; j++) {
+                    message.append("Expected output out: ");
+                    message.append(args.out[j].toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out[j].couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                }
+                assertTrue("Incorrect output for checkNormalizeFloat3Float3" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    private void checkNormalizeFloat4Float4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x3ce1abd05a3ca2dcl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testNormalizeFloat4Float4(inV, out);
+            verifyResultsNormalizeFloat4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNormalizeFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNormalizeFloat4Float4(inV, out);
+            verifyResultsNormalizeFloat4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNormalizeFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNormalizeFloat4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsFloatNFloatN args = new ArgumentsFloatNFloatN();
+            // Create the appropriate sized arrays in args
+            args.inV = new float[4];
+            args.out = new Target.Floaty[4];
+            // Fill args with the input values
+            for (int j = 0; j < 4 ; j++) {
+                args.inV[j] = arrayInV[i * 4 + j];
+            }
+            Target target = new Target(relaxed);
+            CoreMathVerifier.computeNormalize(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            for (int j = 0; j < 4 ; j++) {
+                if (!args.out[j].couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+            }
+            if (!valid) {
+                StringBuilder message = new StringBuilder();
+                for (int j = 0; j < 4 ; j++) {
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayInV[i * 4 + j], Float.floatToRawIntBits(arrayInV[i * 4 + j]), arrayInV[i * 4 + j]));
+                    message.append("\n");
+                }
+                for (int j = 0; j < 4 ; j++) {
+                    message.append("Expected output out: ");
+                    message.append(args.out[j].toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out[j].couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                }
+                assertTrue("Incorrect output for checkNormalizeFloat4Float4" +
+                        (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+            }
+        }
+    }
+
+    public void testNormalize() {
+        checkNormalizeFloatFloat();
+        checkNormalizeFloat2Float2();
+        checkNormalizeFloat3Float3();
+        checkNormalizeFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNormalize.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNormalize.rs
new file mode 100644
index 0000000..fbb5281
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNormalize.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testNormalizeFloatFloat(float inV) {
+    return normalize(inV);
+}
+
+float2 __attribute__((kernel)) testNormalizeFloat2Float2(float2 inV) {
+    return normalize(inV);
+}
+
+float3 __attribute__((kernel)) testNormalizeFloat3Float3(float3 inV) {
+    return normalize(inV);
+}
+
+float4 __attribute__((kernel)) testNormalizeFloat4Float4(float4 inV) {
+    return normalize(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestNormalizeRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestNormalizeRelaxed.rs
new file mode 100644
index 0000000..148bec3
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestNormalizeRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestNormalize.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestPow.java b/tests/tests/renderscript/src/android/renderscript/cts/TestPow.java
new file mode 100644
index 0000000..39369c4
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestPow.java
@@ -0,0 +1,325 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestPow extends RSBaseCompute {
+
+    private ScriptC_TestPow script;
+    private ScriptC_TestPowRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestPow(mRS);
+        scriptRelaxed = new ScriptC_TestPowRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float inX;
+        public float inY;
+        public Target.Floaty out;
+    }
+
+    private void checkPowFloatFloatFloat() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x470aeab18312445bl, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x470aeab18312445cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testPowFloatFloatFloat(inX, out);
+            verifyResultsPowFloatFloatFloat(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testPowFloatFloatFloat(inX, out);
+            verifyResultsPowFloatFloatFloat(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsPowFloatFloatFloat(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 1];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 1];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i];
+                args.inY = arrayInY[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computePow(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkPowFloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkPowFloat2Float2Float2() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xbcd9b7ed561242ddl, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xbcd9b7ed561242del, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testPowFloat2Float2Float2(inX, out);
+            verifyResultsPowFloat2Float2Float2(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowFloat2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testPowFloat2Float2Float2(inX, out);
+            verifyResultsPowFloat2Float2Float2(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowFloat2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsPowFloat2Float2Float2(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 2];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 2];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 2 + j];
+                args.inY = arrayInY[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computePow(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkPowFloat2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkPowFloat3Float3Float3() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x113e960d57f0447el, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x113e960d57f0447fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testPowFloat3Float3Float3(inX, out);
+            verifyResultsPowFloat3Float3Float3(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowFloat3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testPowFloat3Float3Float3(inX, out);
+            verifyResultsPowFloat3Float3Float3(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowFloat3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsPowFloat3Float3Float3(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computePow(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkPowFloat3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkPowFloat4Float4Float4() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x65a3742d59ce461fl, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x65a3742d59ce4620l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testPowFloat4Float4Float4(inX, out);
+            verifyResultsPowFloat4Float4Float4(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowFloat4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testPowFloat4Float4Float4(inX, out);
+            verifyResultsPowFloat4Float4Float4(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowFloat4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsPowFloat4Float4Float4(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computePow(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkPowFloat4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testPow() {
+        checkPowFloatFloatFloat();
+        checkPowFloat2Float2Float2();
+        checkPowFloat3Float3Float3();
+        checkPowFloat4Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestPow.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestPow.rs
new file mode 100644
index 0000000..855419a
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestPow.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInY;
+
+float __attribute__((kernel)) testPowFloatFloatFloat(float inX, unsigned int x) {
+    float inY = rsGetElementAt_float(gAllocInY, x);
+    return pow(inX, inY);
+}
+
+float2 __attribute__((kernel)) testPowFloat2Float2Float2(float2 inX, unsigned int x) {
+    float2 inY = rsGetElementAt_float2(gAllocInY, x);
+    return pow(inX, inY);
+}
+
+float3 __attribute__((kernel)) testPowFloat3Float3Float3(float3 inX, unsigned int x) {
+    float3 inY = rsGetElementAt_float3(gAllocInY, x);
+    return pow(inX, inY);
+}
+
+float4 __attribute__((kernel)) testPowFloat4Float4Float4(float4 inX, unsigned int x) {
+    float4 inY = rsGetElementAt_float4(gAllocInY, x);
+    return pow(inX, inY);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestPowRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestPowRelaxed.rs
new file mode 100644
index 0000000..eae1207
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestPowRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestPow.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestPown.java b/tests/tests/renderscript/src/android/renderscript/cts/TestPown.java
new file mode 100644
index 0000000..14a09e1
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestPown.java
@@ -0,0 +1,321 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestPown extends RSBaseCompute {
+
+    private ScriptC_TestPown script;
+    private ScriptC_TestPownRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestPown(mRS);
+        scriptRelaxed = new ScriptC_TestPownRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatIntFloat {
+        public float inX;
+        public int inY;
+        public Target.Floaty out;
+    }
+
+    private void checkPownFloatIntFloat() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xde633e0d2c462948l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 1, 0xde633e0d2c462949l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testPownFloatIntFloat(inX, out);
+            verifyResultsPownFloatIntFloat(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPownFloatIntFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testPownFloatIntFloat(inX, out);
+            verifyResultsPownFloatIntFloat(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPownFloatIntFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsPownFloatIntFloat(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 1];
+        inX.copyTo(arrayInX);
+        int[] arrayInY = new int[INPUTSIZE * 1];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inX = arrayInX[i];
+                args.inY = arrayInY[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computePown(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%d", args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkPownFloatIntFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkPownFloat2Int2Float2() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x1685dc0ea821329el, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 2, 0x1685dc0ea821329fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testPownFloat2Int2Float2(inX, out);
+            verifyResultsPownFloat2Int2Float2(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPownFloat2Int2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testPownFloat2Int2Float2(inX, out);
+            verifyResultsPownFloat2Int2Float2(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPownFloat2Int2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsPownFloat2Int2Float2(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 2];
+        inX.copyTo(arrayInX);
+        int[] arrayInY = new int[INPUTSIZE * 2];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inX = arrayInX[i * 2 + j];
+                args.inY = arrayInY[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computePown(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%d", args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkPownFloat2Int2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkPownFloat3Int3Float3() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x3c3c1a719dd39f57l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 3, 0x3c3c1a719dd39f58l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testPownFloat3Int3Float3(inX, out);
+            verifyResultsPownFloat3Int3Float3(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPownFloat3Int3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testPownFloat3Int3Float3(inX, out);
+            verifyResultsPownFloat3Int3Float3(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPownFloat3Int3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsPownFloat3Int3Float3(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        int[] arrayInY = new int[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computePown(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%d", args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkPownFloat3Int3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkPownFloat4Int4Float4() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x61f258d493860c10l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 4, 0x61f258d493860c11l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testPownFloat4Int4Float4(inX, out);
+            verifyResultsPownFloat4Int4Float4(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPownFloat4Int4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testPownFloat4Int4Float4(inX, out);
+            verifyResultsPownFloat4Int4Float4(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPownFloat4Int4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsPownFloat4Int4Float4(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        int[] arrayInY = new int[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computePown(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%d", args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkPownFloat4Int4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testPown() {
+        checkPownFloatIntFloat();
+        checkPownFloat2Int2Float2();
+        checkPownFloat3Int3Float3();
+        checkPownFloat4Int4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestPown.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestPown.rs
new file mode 100644
index 0000000..3ee4fc0
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestPown.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInY;
+
+float __attribute__((kernel)) testPownFloatIntFloat(float inX, unsigned int x) {
+    int inY = rsGetElementAt_int(gAllocInY, x);
+    return pown(inX, inY);
+}
+
+float2 __attribute__((kernel)) testPownFloat2Int2Float2(float2 inX, unsigned int x) {
+    int2 inY = rsGetElementAt_int2(gAllocInY, x);
+    return pown(inX, inY);
+}
+
+float3 __attribute__((kernel)) testPownFloat3Int3Float3(float3 inX, unsigned int x) {
+    int3 inY = rsGetElementAt_int3(gAllocInY, x);
+    return pown(inX, inY);
+}
+
+float4 __attribute__((kernel)) testPownFloat4Int4Float4(float4 inX, unsigned int x) {
+    int4 inY = rsGetElementAt_int4(gAllocInY, x);
+    return pown(inX, inY);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestPownRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestPownRelaxed.rs
new file mode 100644
index 0000000..d35cd0b
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestPownRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestPown.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestPowr.java b/tests/tests/renderscript/src/android/renderscript/cts/TestPowr.java
new file mode 100644
index 0000000..b1f281b
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestPowr.java
@@ -0,0 +1,325 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestPowr extends RSBaseCompute {
+
+    private ScriptC_TestPowr script;
+    private ScriptC_TestPowrRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestPowr(mRS);
+        scriptRelaxed = new ScriptC_TestPowrRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float inX;
+        public float inY;
+        public Target.Floaty out;
+    }
+
+    private void checkPowrFloatFloatFloat() {
+        Allocation inX = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x616e17ec158f6a8dl, 0, 3000);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x616e17ec158f6a8el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testPowrFloatFloatFloat(inX, out);
+            verifyResultsPowrFloatFloatFloat(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowrFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testPowrFloatFloatFloat(inX, out);
+            verifyResultsPowrFloatFloatFloat(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowrFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsPowrFloatFloatFloat(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 1];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 1];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i];
+                args.inY = arrayInY[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computePowr(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkPowrFloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkPowrFloat2Float2Float2() {
+        Allocation inX = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xfc919df3002fbd93l, 0, 3000);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xfc919df3002fbd94l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testPowrFloat2Float2Float2(inX, out);
+            verifyResultsPowrFloat2Float2Float2(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowrFloat2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testPowrFloat2Float2Float2(inX, out);
+            verifyResultsPowrFloat2Float2Float2(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowrFloat2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsPowrFloat2Float2Float2(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 2];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 2];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 2 + j];
+                args.inY = arrayInY[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computePowr(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkPowrFloat2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkPowrFloat3Float3Float3() {
+        Allocation inX = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x50f67c13020dbf34l, 0, 3000);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x50f67c13020dbf35l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testPowrFloat3Float3Float3(inX, out);
+            verifyResultsPowrFloat3Float3Float3(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowrFloat3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testPowrFloat3Float3Float3(inX, out);
+            verifyResultsPowrFloat3Float3Float3(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowrFloat3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsPowrFloat3Float3Float3(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computePowr(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkPowrFloat3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkPowrFloat4Float4Float4() {
+        Allocation inX = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xa55b5a3303ebc0d5l, 0, 3000);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xa55b5a3303ebc0d6l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testPowrFloat4Float4Float4(inX, out);
+            verifyResultsPowrFloat4Float4Float4(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowrFloat4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testPowrFloat4Float4Float4(inX, out);
+            verifyResultsPowrFloat4Float4Float4(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowrFloat4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsPowrFloat4Float4Float4(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computePowr(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkPowrFloat4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testPowr() {
+        checkPowrFloatFloatFloat();
+        checkPowrFloat2Float2Float2();
+        checkPowrFloat3Float3Float3();
+        checkPowrFloat4Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestPowr.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestPowr.rs
new file mode 100644
index 0000000..0fd603e
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestPowr.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInY;
+
+float __attribute__((kernel)) testPowrFloatFloatFloat(float inX, unsigned int x) {
+    float inY = rsGetElementAt_float(gAllocInY, x);
+    return powr(inX, inY);
+}
+
+float2 __attribute__((kernel)) testPowrFloat2Float2Float2(float2 inX, unsigned int x) {
+    float2 inY = rsGetElementAt_float2(gAllocInY, x);
+    return powr(inX, inY);
+}
+
+float3 __attribute__((kernel)) testPowrFloat3Float3Float3(float3 inX, unsigned int x) {
+    float3 inY = rsGetElementAt_float3(gAllocInY, x);
+    return powr(inX, inY);
+}
+
+float4 __attribute__((kernel)) testPowrFloat4Float4Float4(float4 inX, unsigned int x) {
+    float4 inY = rsGetElementAt_float4(gAllocInY, x);
+    return powr(inX, inY);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestPowrRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestPowrRelaxed.rs
new file mode 100644
index 0000000..95e6f84
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestPowrRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestPowr.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestRadians.java b/tests/tests/renderscript/src/android/renderscript/cts/TestRadians.java
new file mode 100644
index 0000000..2707ac2
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestRadians.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestRadians extends RSBaseCompute {
+
+    private ScriptC_TestRadians script;
+    private ScriptC_TestRadiansRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestRadians(mRS);
+        scriptRelaxed = new ScriptC_TestRadiansRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inValue;
+        public Target.Floaty out;
+    }
+
+    private void checkRadiansFloatFloat() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xaa72f227598b8106l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testRadiansFloatFloat(inValue, out);
+            verifyResultsRadiansFloatFloat(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRadiansFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testRadiansFloatFloat(inValue, out);
+            verifyResultsRadiansFloatFloat(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRadiansFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRadiansFloatFloat(Allocation inValue, Allocation out, boolean relaxed) {
+        float[] arrayInValue = new float[INPUTSIZE * 1];
+        inValue.copyTo(arrayInValue);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inValue = arrayInValue[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeRadians(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inValue, Float.floatToRawIntBits(args.inValue), args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkRadiansFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkRadiansFloat2Float2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xb28bd9316e059892l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testRadiansFloat2Float2(inValue, out);
+            verifyResultsRadiansFloat2Float2(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRadiansFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testRadiansFloat2Float2(inValue, out);
+            verifyResultsRadiansFloat2Float2(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRadiansFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRadiansFloat2Float2(Allocation inValue, Allocation out, boolean relaxed) {
+        float[] arrayInValue = new float[INPUTSIZE * 2];
+        inValue.copyTo(arrayInValue);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inValue = arrayInValue[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeRadians(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inValue, Float.floatToRawIntBits(args.inValue), args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkRadiansFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkRadiansFloat3Float3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xd8404eb8b743be10l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testRadiansFloat3Float3(inValue, out);
+            verifyResultsRadiansFloat3Float3(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRadiansFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testRadiansFloat3Float3(inValue, out);
+            verifyResultsRadiansFloat3Float3(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRadiansFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRadiansFloat3Float3(Allocation inValue, Allocation out, boolean relaxed) {
+        float[] arrayInValue = new float[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inValue = arrayInValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeRadians(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inValue, Float.floatToRawIntBits(args.inValue), args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkRadiansFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkRadiansFloat4Float4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xfdf4c4400081e38el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testRadiansFloat4Float4(inValue, out);
+            verifyResultsRadiansFloat4Float4(inValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRadiansFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testRadiansFloat4Float4(inValue, out);
+            verifyResultsRadiansFloat4Float4(inValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRadiansFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRadiansFloat4Float4(Allocation inValue, Allocation out, boolean relaxed) {
+        float[] arrayInValue = new float[INPUTSIZE * 4];
+        inValue.copyTo(arrayInValue);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inValue = arrayInValue[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeRadians(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inValue: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inValue, Float.floatToRawIntBits(args.inValue), args.inValue));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkRadiansFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testRadians() {
+        checkRadiansFloatFloat();
+        checkRadiansFloat2Float2();
+        checkRadiansFloat3Float3();
+        checkRadiansFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestRadians.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestRadians.rs
new file mode 100644
index 0000000..09aa9a0
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestRadians.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testRadiansFloatFloat(float inValue) {
+    return radians(inValue);
+}
+
+float2 __attribute__((kernel)) testRadiansFloat2Float2(float2 inValue) {
+    return radians(inValue);
+}
+
+float3 __attribute__((kernel)) testRadiansFloat3Float3(float3 inValue) {
+    return radians(inValue);
+}
+
+float4 __attribute__((kernel)) testRadiansFloat4Float4(float4 inValue) {
+    return radians(inValue);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestRadiansRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestRadiansRelaxed.rs
new file mode 100644
index 0000000..fa9209f
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestRadiansRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestRadians.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestRemainder.java b/tests/tests/renderscript/src/android/renderscript/cts/TestRemainder.java
new file mode 100644
index 0000000..8208d23
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestRemainder.java
@@ -0,0 +1,325 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestRemainder extends RSBaseCompute {
+
+    private ScriptC_TestRemainder script;
+    private ScriptC_TestRemainderRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestRemainder(mRS);
+        scriptRelaxed = new ScriptC_TestRemainderRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float inX;
+        public float inY;
+        public Target.Floaty out;
+    }
+
+    private void checkRemainderFloatFloatFloat() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x27d6330966022888l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x27d6330966022889l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testRemainderFloatFloatFloat(inX, out);
+            verifyResultsRemainderFloatFloatFloat(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRemainderFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testRemainderFloatFloatFloat(inX, out);
+            verifyResultsRemainderFloatFloatFloat(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRemainderFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRemainderFloatFloatFloat(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 1];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 1];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i];
+                args.inY = arrayInY[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeRemainder(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkRemainderFloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkRemainderFloat2Float2Float2() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xfb2eaf332420c6b4l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xfb2eaf332420c6b5l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testRemainderFloat2Float2Float2(inX, out);
+            verifyResultsRemainderFloat2Float2Float2(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRemainderFloat2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testRemainderFloat2Float2Float2(inX, out);
+            verifyResultsRemainderFloat2Float2Float2(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRemainderFloat2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRemainderFloat2Float2Float2(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 2];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 2];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 2 + j];
+                args.inY = arrayInY[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeRemainder(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkRemainderFloat2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkRemainderFloat3Float3Float3() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x4f938d5325fec855l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x4f938d5325fec856l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testRemainderFloat3Float3Float3(inX, out);
+            verifyResultsRemainderFloat3Float3Float3(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRemainderFloat3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testRemainderFloat3Float3Float3(inX, out);
+            verifyResultsRemainderFloat3Float3Float3(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRemainderFloat3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRemainderFloat3Float3Float3(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeRemainder(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkRemainderFloat3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkRemainderFloat4Float4Float4() {
+        Allocation inX = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xa3f86b7327dcc9f6l, false);
+        Allocation inY = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xa3f86b7327dcc9f7l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInY(inY);
+            script.forEach_testRemainderFloat4Float4Float4(inX, out);
+            verifyResultsRemainderFloat4Float4Float4(inX, inY, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRemainderFloat4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInY(inY);
+            scriptRelaxed.forEach_testRemainderFloat4Float4Float4(inX, out);
+            verifyResultsRemainderFloat4Float4Float4(inX, inY, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRemainderFloat4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRemainderFloat4Float4Float4(Allocation inX, Allocation inY, Allocation out, boolean relaxed) {
+        float[] arrayInX = new float[INPUTSIZE * 4];
+        inX.copyTo(arrayInX);
+        float[] arrayInY = new float[INPUTSIZE * 4];
+        inY.copyTo(arrayInY);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inX = arrayInX[i * 4 + j];
+                args.inY = arrayInY[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeRemainder(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inX: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inX, Float.floatToRawIntBits(args.inX), args.inX));
+                    message.append("\n");
+                    message.append("Input inY: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inY, Float.floatToRawIntBits(args.inY), args.inY));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkRemainderFloat4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testRemainder() {
+        checkRemainderFloatFloatFloat();
+        checkRemainderFloat2Float2Float2();
+        checkRemainderFloat3Float3Float3();
+        checkRemainderFloat4Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestRemainder.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestRemainder.rs
new file mode 100644
index 0000000..86f2030
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestRemainder.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInY;
+
+float __attribute__((kernel)) testRemainderFloatFloatFloat(float inX, unsigned int x) {
+    float inY = rsGetElementAt_float(gAllocInY, x);
+    return remainder(inX, inY);
+}
+
+float2 __attribute__((kernel)) testRemainderFloat2Float2Float2(float2 inX, unsigned int x) {
+    float2 inY = rsGetElementAt_float2(gAllocInY, x);
+    return remainder(inX, inY);
+}
+
+float3 __attribute__((kernel)) testRemainderFloat3Float3Float3(float3 inX, unsigned int x) {
+    float3 inY = rsGetElementAt_float3(gAllocInY, x);
+    return remainder(inX, inY);
+}
+
+float4 __attribute__((kernel)) testRemainderFloat4Float4Float4(float4 inX, unsigned int x) {
+    float4 inY = rsGetElementAt_float4(gAllocInY, x);
+    return remainder(inX, inY);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestRemainderRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestRemainderRelaxed.rs
new file mode 100644
index 0000000..7c45964
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestRemainderRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestRemainder.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestRemquo.java b/tests/tests/renderscript/src/android/renderscript/cts/TestRemquo.java
new file mode 100644
index 0000000..7052dd1
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestRemquo.java
@@ -0,0 +1,334 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestRemquo extends RSBaseCompute {
+
+    private ScriptC_TestRemquo script;
+    private ScriptC_TestRemquoRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestRemquo(mRS);
+        scriptRelaxed = new ScriptC_TestRemquoRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatIntFloat {
+        public float inB;
+        public float inC;
+        public int outD;
+        public float out;
+    }
+
+    private void checkRemquoFloatFloatIntFloat() {
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x118af9b82db63b13l, false);
+        Allocation inC = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x118af9b82db63b14l, false);
+        try {
+            Allocation outD = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 1), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInC(inC);
+            script.set_gAllocOutD(outD);
+            script.forEach_testRemquoFloatFloatIntFloat(inB, out);
+            verifyResultsRemquoFloatFloatIntFloat(inB, inC, outD, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRemquoFloatFloatIntFloat: " + e.toString());
+        }
+        try {
+            Allocation outD = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 1), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInC(inC);
+            scriptRelaxed.set_gAllocOutD(outD);
+            scriptRelaxed.forEach_testRemquoFloatFloatIntFloat(inB, out);
+            verifyResultsRemquoFloatFloatIntFloat(inB, inC, outD, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRemquoFloatFloatIntFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRemquoFloatFloatIntFloat(Allocation inB, Allocation inC, Allocation outD, Allocation out, boolean relaxed) {
+        float[] arrayInB = new float[INPUTSIZE * 1];
+        inB.copyTo(arrayInB);
+        float[] arrayInC = new float[INPUTSIZE * 1];
+        inC.copyTo(arrayInC);
+        int[] arrayOutD = new int[INPUTSIZE * 1];
+        outD.copyTo(arrayOutD);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatIntFloat args = new ArgumentsFloatFloatIntFloat();
+                args.inB = arrayInB[i];
+                args.inC = arrayInC[i];
+                // Extract the outputs.
+                args.outD = arrayOutD[i * 1 + j];
+                args.out = arrayOut[i * 1 + j];
+                // Ask the CoreMathVerifier to validate.
+                Target target = new Target(relaxed);
+                String errorMessage = CoreMathVerifier.verifyRemquo(args, target);
+                boolean valid = errorMessage == null;
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inB: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inB, Float.floatToRawIntBits(args.inB), args.inB));
+                    message.append("\n");
+                    message.append("Input inC: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inC, Float.floatToRawIntBits(args.inC), args.inC));
+                    message.append("\n");
+                    message.append("Output outD: ");
+                    message.append(String.format("%d", args.outD));
+                    message.append("\n");
+                    message.append("Output out: ");
+                    message.append(Float.toString(args.out));
+                    message.append("\n");
+                    message.append(errorMessage);
+                    assertTrue("Incorrect output for checkRemquoFloatFloatIntFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkRemquoFloat2Float2Int2Float2() {
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x9b98a1a6b125f903l, false);
+        Allocation inC = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x9b98a1a6b125f904l, false);
+        try {
+            Allocation outD = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInC(inC);
+            script.set_gAllocOutD(outD);
+            script.forEach_testRemquoFloat2Float2Int2Float2(inB, out);
+            verifyResultsRemquoFloat2Float2Int2Float2(inB, inC, outD, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRemquoFloat2Float2Int2Float2: " + e.toString());
+        }
+        try {
+            Allocation outD = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInC(inC);
+            scriptRelaxed.set_gAllocOutD(outD);
+            scriptRelaxed.forEach_testRemquoFloat2Float2Int2Float2(inB, out);
+            verifyResultsRemquoFloat2Float2Int2Float2(inB, inC, outD, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRemquoFloat2Float2Int2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRemquoFloat2Float2Int2Float2(Allocation inB, Allocation inC, Allocation outD, Allocation out, boolean relaxed) {
+        float[] arrayInB = new float[INPUTSIZE * 2];
+        inB.copyTo(arrayInB);
+        float[] arrayInC = new float[INPUTSIZE * 2];
+        inC.copyTo(arrayInC);
+        int[] arrayOutD = new int[INPUTSIZE * 2];
+        outD.copyTo(arrayOutD);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatIntFloat args = new ArgumentsFloatFloatIntFloat();
+                args.inB = arrayInB[i * 2 + j];
+                args.inC = arrayInC[i * 2 + j];
+                // Extract the outputs.
+                args.outD = arrayOutD[i * 2 + j];
+                args.out = arrayOut[i * 2 + j];
+                // Ask the CoreMathVerifier to validate.
+                Target target = new Target(relaxed);
+                String errorMessage = CoreMathVerifier.verifyRemquo(args, target);
+                boolean valid = errorMessage == null;
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inB: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inB, Float.floatToRawIntBits(args.inB), args.inB));
+                    message.append("\n");
+                    message.append("Input inC: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inC, Float.floatToRawIntBits(args.inC), args.inC));
+                    message.append("\n");
+                    message.append("Output outD: ");
+                    message.append(String.format("%d", args.outD));
+                    message.append("\n");
+                    message.append("Output out: ");
+                    message.append(Float.toString(args.out));
+                    message.append("\n");
+                    message.append(errorMessage);
+                    assertTrue("Incorrect output for checkRemquoFloat2Float2Int2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkRemquoFloat3Float3Int3Float3() {
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xa049a00a6911ca8fl, false);
+        Allocation inC = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xa049a00a6911ca90l, false);
+        try {
+            Allocation outD = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInC(inC);
+            script.set_gAllocOutD(outD);
+            script.forEach_testRemquoFloat3Float3Int3Float3(inB, out);
+            verifyResultsRemquoFloat3Float3Int3Float3(inB, inC, outD, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRemquoFloat3Float3Int3Float3: " + e.toString());
+        }
+        try {
+            Allocation outD = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInC(inC);
+            scriptRelaxed.set_gAllocOutD(outD);
+            scriptRelaxed.forEach_testRemquoFloat3Float3Int3Float3(inB, out);
+            verifyResultsRemquoFloat3Float3Int3Float3(inB, inC, outD, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRemquoFloat3Float3Int3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRemquoFloat3Float3Int3Float3(Allocation inB, Allocation inC, Allocation outD, Allocation out, boolean relaxed) {
+        float[] arrayInB = new float[INPUTSIZE * 4];
+        inB.copyTo(arrayInB);
+        float[] arrayInC = new float[INPUTSIZE * 4];
+        inC.copyTo(arrayInC);
+        int[] arrayOutD = new int[INPUTSIZE * 4];
+        outD.copyTo(arrayOutD);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatIntFloat args = new ArgumentsFloatFloatIntFloat();
+                args.inB = arrayInB[i * 4 + j];
+                args.inC = arrayInC[i * 4 + j];
+                // Extract the outputs.
+                args.outD = arrayOutD[i * 4 + j];
+                args.out = arrayOut[i * 4 + j];
+                // Ask the CoreMathVerifier to validate.
+                Target target = new Target(relaxed);
+                String errorMessage = CoreMathVerifier.verifyRemquo(args, target);
+                boolean valid = errorMessage == null;
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inB: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inB, Float.floatToRawIntBits(args.inB), args.inB));
+                    message.append("\n");
+                    message.append("Input inC: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inC, Float.floatToRawIntBits(args.inC), args.inC));
+                    message.append("\n");
+                    message.append("Output outD: ");
+                    message.append(String.format("%d", args.outD));
+                    message.append("\n");
+                    message.append("Output out: ");
+                    message.append(Float.toString(args.out));
+                    message.append("\n");
+                    message.append(errorMessage);
+                    assertTrue("Incorrect output for checkRemquoFloat3Float3Int3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkRemquoFloat4Float4Int4Float4() {
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xa4fa9e6e20fd9c1bl, false);
+        Allocation inC = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xa4fa9e6e20fd9c1cl, false);
+        try {
+            Allocation outD = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInC(inC);
+            script.set_gAllocOutD(outD);
+            script.forEach_testRemquoFloat4Float4Int4Float4(inB, out);
+            verifyResultsRemquoFloat4Float4Int4Float4(inB, inC, outD, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRemquoFloat4Float4Int4Float4: " + e.toString());
+        }
+        try {
+            Allocation outD = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInC(inC);
+            scriptRelaxed.set_gAllocOutD(outD);
+            scriptRelaxed.forEach_testRemquoFloat4Float4Int4Float4(inB, out);
+            verifyResultsRemquoFloat4Float4Int4Float4(inB, inC, outD, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRemquoFloat4Float4Int4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRemquoFloat4Float4Int4Float4(Allocation inB, Allocation inC, Allocation outD, Allocation out, boolean relaxed) {
+        float[] arrayInB = new float[INPUTSIZE * 4];
+        inB.copyTo(arrayInB);
+        float[] arrayInC = new float[INPUTSIZE * 4];
+        inC.copyTo(arrayInC);
+        int[] arrayOutD = new int[INPUTSIZE * 4];
+        outD.copyTo(arrayOutD);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatIntFloat args = new ArgumentsFloatFloatIntFloat();
+                args.inB = arrayInB[i * 4 + j];
+                args.inC = arrayInC[i * 4 + j];
+                // Extract the outputs.
+                args.outD = arrayOutD[i * 4 + j];
+                args.out = arrayOut[i * 4 + j];
+                // Ask the CoreMathVerifier to validate.
+                Target target = new Target(relaxed);
+                String errorMessage = CoreMathVerifier.verifyRemquo(args, target);
+                boolean valid = errorMessage == null;
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inB: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inB, Float.floatToRawIntBits(args.inB), args.inB));
+                    message.append("\n");
+                    message.append("Input inC: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inC, Float.floatToRawIntBits(args.inC), args.inC));
+                    message.append("\n");
+                    message.append("Output outD: ");
+                    message.append(String.format("%d", args.outD));
+                    message.append("\n");
+                    message.append("Output out: ");
+                    message.append(Float.toString(args.out));
+                    message.append("\n");
+                    message.append(errorMessage);
+                    assertTrue("Incorrect output for checkRemquoFloat4Float4Int4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testRemquo() {
+        checkRemquoFloatFloatIntFloat();
+        checkRemquoFloat2Float2Int2Float2();
+        checkRemquoFloat3Float3Int3Float3();
+        checkRemquoFloat4Float4Int4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestRemquo.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestRemquo.rs
new file mode 100644
index 0000000..032e6c0
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestRemquo.rs
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInC;
+rs_allocation gAllocOutD;
+
+float __attribute__((kernel)) testRemquoFloatFloatIntFloat(float inB, unsigned int x) {
+    float inC = rsGetElementAt_float(gAllocInC, x);
+    int outD = 0;
+    float out = remquo(inB, inC, &outD);
+    rsSetElementAt_int(gAllocOutD, outD, x);
+    return out;
+}
+
+float2 __attribute__((kernel)) testRemquoFloat2Float2Int2Float2(float2 inB, unsigned int x) {
+    float2 inC = rsGetElementAt_float2(gAllocInC, x);
+    int2 outD = 0;
+    float2 out = remquo(inB, inC, &outD);
+    rsSetElementAt_int2(gAllocOutD, outD, x);
+    return out;
+}
+
+float3 __attribute__((kernel)) testRemquoFloat3Float3Int3Float3(float3 inB, unsigned int x) {
+    float3 inC = rsGetElementAt_float3(gAllocInC, x);
+    int3 outD = 0;
+    float3 out = remquo(inB, inC, &outD);
+    rsSetElementAt_int3(gAllocOutD, outD, x);
+    return out;
+}
+
+float4 __attribute__((kernel)) testRemquoFloat4Float4Int4Float4(float4 inB, unsigned int x) {
+    float4 inC = rsGetElementAt_float4(gAllocInC, x);
+    int4 outD = 0;
+    float4 out = remquo(inB, inC, &outD);
+    rsSetElementAt_int4(gAllocOutD, outD, x);
+    return out;
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestRemquoRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestRemquoRelaxed.rs
new file mode 100644
index 0000000..3962532
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestRemquoRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestRemquo.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestRint.java b/tests/tests/renderscript/src/android/renderscript/cts/TestRint.java
new file mode 100644
index 0000000..6d42aeb
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestRint.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestRint extends RSBaseCompute {
+
+    private ScriptC_TestRint script;
+    private ScriptC_TestRintRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestRint(mRS);
+        scriptRelaxed = new ScriptC_TestRintRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkRintFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xfe569fda5dbe93fal, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testRintFloatFloat(in, out);
+            verifyResultsRintFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRintFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testRintFloatFloat(in, out);
+            verifyResultsRintFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRintFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRintFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeRint(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkRintFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkRintFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xffa7b22ac6b343c6l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testRintFloat2Float2(in, out);
+            verifyResultsRintFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRintFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testRintFloat2Float2(in, out);
+            verifyResultsRintFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRintFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRintFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeRint(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkRintFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkRintFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xffa7bccc25b9d960l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testRintFloat3Float3(in, out);
+            verifyResultsRintFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRintFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testRintFloat3Float3(in, out);
+            verifyResultsRintFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRintFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRintFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeRint(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkRintFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkRintFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xffa7c76d84c06efal, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testRintFloat4Float4(in, out);
+            verifyResultsRintFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRintFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testRintFloat4Float4(in, out);
+            verifyResultsRintFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRintFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRintFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeRint(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkRintFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testRint() {
+        checkRintFloatFloat();
+        checkRintFloat2Float2();
+        checkRintFloat3Float3();
+        checkRintFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestRint.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestRint.rs
new file mode 100644
index 0000000..a551d68
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestRint.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testRintFloatFloat(float in) {
+    return rint(in);
+}
+
+float2 __attribute__((kernel)) testRintFloat2Float2(float2 in) {
+    return rint(in);
+}
+
+float3 __attribute__((kernel)) testRintFloat3Float3(float3 in) {
+    return rint(in);
+}
+
+float4 __attribute__((kernel)) testRintFloat4Float4(float4 in) {
+    return rint(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestRintRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestRintRelaxed.rs
new file mode 100644
index 0000000..9fb4636
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestRintRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestRint.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestRootn.java b/tests/tests/renderscript/src/android/renderscript/cts/TestRootn.java
new file mode 100644
index 0000000..b9562e4
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestRootn.java
@@ -0,0 +1,321 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestRootn extends RSBaseCompute {
+
+    private ScriptC_TestRootn script;
+    private ScriptC_TestRootnRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestRootn(mRS);
+        scriptRelaxed = new ScriptC_TestRootnRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatIntFloat {
+        public float inV;
+        public int inN;
+        public Target.Floaty out;
+    }
+
+    private void checkRootnFloatIntFloat() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x37d0d9514daae0ccl, false);
+        Allocation inN = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 1, 0x37d0d9514daae0c4l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInN(inN);
+            script.forEach_testRootnFloatIntFloat(inV, out);
+            verifyResultsRootnFloatIntFloat(inV, inN, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRootnFloatIntFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInN(inN);
+            scriptRelaxed.forEach_testRootnFloatIntFloat(inV, out);
+            verifyResultsRootnFloatIntFloat(inV, inN, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRootnFloatIntFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRootnFloatIntFloat(Allocation inV, Allocation inN, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        int[] arrayInN = new int[INPUTSIZE * 1];
+        inN.copyTo(arrayInN);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inV = arrayInV[i];
+                args.inN = arrayInN[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeRootn(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Input inN: ");
+                    message.append(String.format("%d", args.inN));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkRootnFloatIntFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkRootnFloat2Int2Float2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x2a7a849dcb32d88el, false);
+        Allocation inN = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 2, 0x2a7a849dcb32d886l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInN(inN);
+            script.forEach_testRootnFloat2Int2Float2(inV, out);
+            verifyResultsRootnFloat2Int2Float2(inV, inN, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRootnFloat2Int2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInN(inN);
+            scriptRelaxed.forEach_testRootnFloat2Int2Float2(inV, out);
+            verifyResultsRootnFloat2Int2Float2(inV, inN, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRootnFloat2Int2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRootnFloat2Int2Float2(Allocation inV, Allocation inN, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        int[] arrayInN = new int[INPUTSIZE * 2];
+        inN.copyTo(arrayInN);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inV = arrayInV[i * 2 + j];
+                args.inN = arrayInN[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeRootn(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Input inN: ");
+                    message.append(String.format("%d", args.inN));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkRootnFloat2Int2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkRootnFloat3Int3Float3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x5030c300c0e54547l, false);
+        Allocation inN = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 3, 0x5030c300c0e5453fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInN(inN);
+            script.forEach_testRootnFloat3Int3Float3(inV, out);
+            verifyResultsRootnFloat3Int3Float3(inV, inN, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRootnFloat3Int3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInN(inN);
+            scriptRelaxed.forEach_testRootnFloat3Int3Float3(inV, out);
+            verifyResultsRootnFloat3Int3Float3(inV, inN, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRootnFloat3Int3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRootnFloat3Int3Float3(Allocation inV, Allocation inN, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayInN = new int[INPUTSIZE * 4];
+        inN.copyTo(arrayInN);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inV = arrayInV[i * 4 + j];
+                args.inN = arrayInN[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeRootn(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Input inN: ");
+                    message.append(String.format("%d", args.inN));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkRootnFloat3Int3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkRootnFloat4Int4Float4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x75e70163b697b200l, false);
+        Allocation inN = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 4, 0x75e70163b697b1f8l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInN(inN);
+            script.forEach_testRootnFloat4Int4Float4(inV, out);
+            verifyResultsRootnFloat4Int4Float4(inV, inN, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRootnFloat4Int4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInN(inN);
+            scriptRelaxed.forEach_testRootnFloat4Int4Float4(inV, out);
+            verifyResultsRootnFloat4Int4Float4(inV, inN, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRootnFloat4Int4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRootnFloat4Int4Float4(Allocation inV, Allocation inN, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        int[] arrayInN = new int[INPUTSIZE * 4];
+        inN.copyTo(arrayInN);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatIntFloat args = new ArgumentsFloatIntFloat();
+                args.inV = arrayInV[i * 4 + j];
+                args.inN = arrayInN[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeRootn(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Input inN: ");
+                    message.append(String.format("%d", args.inN));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkRootnFloat4Int4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testRootn() {
+        checkRootnFloatIntFloat();
+        checkRootnFloat2Int2Float2();
+        checkRootnFloat3Int3Float3();
+        checkRootnFloat4Int4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestRootn.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestRootn.rs
new file mode 100644
index 0000000..e4ee02b
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestRootn.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInN;
+
+float __attribute__((kernel)) testRootnFloatIntFloat(float inV, unsigned int x) {
+    int inN = rsGetElementAt_int(gAllocInN, x);
+    return rootn(inV, inN);
+}
+
+float2 __attribute__((kernel)) testRootnFloat2Int2Float2(float2 inV, unsigned int x) {
+    int2 inN = rsGetElementAt_int2(gAllocInN, x);
+    return rootn(inV, inN);
+}
+
+float3 __attribute__((kernel)) testRootnFloat3Int3Float3(float3 inV, unsigned int x) {
+    int3 inN = rsGetElementAt_int3(gAllocInN, x);
+    return rootn(inV, inN);
+}
+
+float4 __attribute__((kernel)) testRootnFloat4Int4Float4(float4 inV, unsigned int x) {
+    int4 inN = rsGetElementAt_int4(gAllocInN, x);
+    return rootn(inV, inN);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestRootnRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestRootnRelaxed.rs
new file mode 100644
index 0000000..e42d664
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestRootnRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestRootn.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestRound.java b/tests/tests/renderscript/src/android/renderscript/cts/TestRound.java
new file mode 100644
index 0000000..f9c9a9d
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestRound.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestRound extends RSBaseCompute {
+
+    private ScriptC_TestRound script;
+    private ScriptC_TestRoundRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestRound(mRS);
+        scriptRelaxed = new ScriptC_TestRoundRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkRoundFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x377ca8d7e9a82fc7l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testRoundFloatFloat(in, out);
+            verifyResultsRoundFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRoundFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testRoundFloatFloat(in, out);
+            verifyResultsRoundFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRoundFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRoundFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeRound(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkRoundFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkRoundFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xc35ea17250f98f6bl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testRoundFloat2Float2(in, out);
+            verifyResultsRoundFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRoundFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testRoundFloat2Float2(in, out);
+            verifyResultsRoundFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRoundFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRoundFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeRound(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkRoundFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkRoundFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xc35eac13b0002505l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testRoundFloat3Float3(in, out);
+            verifyResultsRoundFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRoundFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testRoundFloat3Float3(in, out);
+            verifyResultsRoundFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRoundFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRoundFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeRound(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkRoundFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkRoundFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xc35eb6b50f06ba9fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testRoundFloat4Float4(in, out);
+            verifyResultsRoundFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRoundFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testRoundFloat4Float4(in, out);
+            verifyResultsRoundFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRoundFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRoundFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeRound(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkRoundFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testRound() {
+        checkRoundFloatFloat();
+        checkRoundFloat2Float2();
+        checkRoundFloat3Float3();
+        checkRoundFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestRound.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestRound.rs
new file mode 100644
index 0000000..0442849
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestRound.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testRoundFloatFloat(float in) {
+    return round(in);
+}
+
+float2 __attribute__((kernel)) testRoundFloat2Float2(float2 in) {
+    return round(in);
+}
+
+float3 __attribute__((kernel)) testRoundFloat3Float3(float3 in) {
+    return round(in);
+}
+
+float4 __attribute__((kernel)) testRoundFloat4Float4(float4 in) {
+    return round(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestRoundRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestRoundRelaxed.rs
new file mode 100644
index 0000000..ebbdccf
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestRoundRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestRound.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestRsqrt.java b/tests/tests/renderscript/src/android/renderscript/cts/TestRsqrt.java
new file mode 100644
index 0000000..7b57621
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestRsqrt.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestRsqrt extends RSBaseCompute {
+
+    private ScriptC_TestRsqrt script;
+    private ScriptC_TestRsqrtRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestRsqrt(mRS);
+        scriptRelaxed = new ScriptC_TestRsqrtRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkRsqrtFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x736e0d9786ef9c2bl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testRsqrtFloatFloat(in, out);
+            verifyResultsRsqrtFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRsqrtFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testRsqrtFloatFloat(in, out);
+            verifyResultsRsqrtFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRsqrtFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRsqrtFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeRsqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkRsqrtFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkRsqrtFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xb5df4d6949d76dafl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testRsqrtFloat2Float2(in, out);
+            verifyResultsRsqrtFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRsqrtFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testRsqrtFloat2Float2(in, out);
+            verifyResultsRsqrtFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRsqrtFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRsqrtFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeRsqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkRsqrtFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkRsqrtFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xb5df580aa8de0349l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testRsqrtFloat3Float3(in, out);
+            verifyResultsRsqrtFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRsqrtFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testRsqrtFloat3Float3(in, out);
+            verifyResultsRsqrtFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRsqrtFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRsqrtFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeRsqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkRsqrtFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkRsqrtFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xb5df62ac07e498e3l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testRsqrtFloat4Float4(in, out);
+            verifyResultsRsqrtFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRsqrtFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testRsqrtFloat4Float4(in, out);
+            verifyResultsRsqrtFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRsqrtFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRsqrtFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeRsqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkRsqrtFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testRsqrt() {
+        checkRsqrtFloatFloat();
+        checkRsqrtFloat2Float2();
+        checkRsqrtFloat3Float3();
+        checkRsqrtFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestRsqrt.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestRsqrt.rs
new file mode 100644
index 0000000..5978899
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestRsqrt.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testRsqrtFloatFloat(float in) {
+    return rsqrt(in);
+}
+
+float2 __attribute__((kernel)) testRsqrtFloat2Float2(float2 in) {
+    return rsqrt(in);
+}
+
+float3 __attribute__((kernel)) testRsqrtFloat3Float3(float3 in) {
+    return rsqrt(in);
+}
+
+float4 __attribute__((kernel)) testRsqrtFloat4Float4(float4 in) {
+    return rsqrt(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestRsqrtRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestRsqrtRelaxed.rs
new file mode 100644
index 0000000..262761e
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestRsqrtRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestRsqrt.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestSign.java b/tests/tests/renderscript/src/android/renderscript/cts/TestSign.java
new file mode 100644
index 0000000..77c467c
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestSign.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestSign extends RSBaseCompute {
+
+    private ScriptC_TestSign script;
+    private ScriptC_TestSignRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestSign(mRS);
+        scriptRelaxed = new ScriptC_TestSignRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkSignFloatFloat() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xadc8bc2f364ea474l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testSignFloatFloat(inV, out);
+            verifyResultsSignFloatFloat(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSignFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testSignFloatFloat(inV, out);
+            verifyResultsSignFloatFloat(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSignFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSignFloatFloat(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeSign(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkSignFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkSignFloat2Float2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x2eb1e646027c0ab8l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testSignFloat2Float2(inV, out);
+            verifyResultsSignFloat2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSignFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testSignFloat2Float2(inV, out);
+            verifyResultsSignFloat2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSignFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSignFloat2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeSign(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkSignFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkSignFloat3Float3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x2eb3af60f8972b96l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testSignFloat3Float3(inV, out);
+            verifyResultsSignFloat3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSignFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testSignFloat3Float3(inV, out);
+            verifyResultsSignFloat3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSignFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSignFloat3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeSign(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkSignFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkSignFloat4Float4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x2eb5787beeb24c74l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testSignFloat4Float4(inV, out);
+            verifyResultsSignFloat4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSignFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testSignFloat4Float4(inV, out);
+            verifyResultsSignFloat4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSignFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSignFloat4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeSign(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkSignFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testSign() {
+        checkSignFloatFloat();
+        checkSignFloat2Float2();
+        checkSignFloat3Float3();
+        checkSignFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestSign.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestSign.rs
new file mode 100644
index 0000000..8f35b36
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestSign.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testSignFloatFloat(float inV) {
+    return sign(inV);
+}
+
+float2 __attribute__((kernel)) testSignFloat2Float2(float2 inV) {
+    return sign(inV);
+}
+
+float3 __attribute__((kernel)) testSignFloat3Float3(float3 inV) {
+    return sign(inV);
+}
+
+float4 __attribute__((kernel)) testSignFloat4Float4(float4 inV) {
+    return sign(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestSignRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestSignRelaxed.rs
new file mode 100644
index 0000000..1bc69fb
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestSignRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestSign.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestSin.java b/tests/tests/renderscript/src/android/renderscript/cts/TestSin.java
new file mode 100644
index 0000000..ae039e2
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestSin.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestSin extends RSBaseCompute {
+
+    private ScriptC_TestSin script;
+    private ScriptC_TestSinRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestSin(mRS);
+        scriptRelaxed = new ScriptC_TestSinRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkSinFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xd3e99dcfa01359f9l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testSinFloatFloat(in, out);
+            verifyResultsSinFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testSinFloatFloat(in, out);
+            verifyResultsSinFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSinFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeSin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkSinFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkSinFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x9253f296dcfd528dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testSinFloat2Float2(in, out);
+            verifyResultsSinFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testSinFloat2Float2(in, out);
+            verifyResultsSinFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSinFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeSin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkSinFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkSinFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x9253fd383c03e827l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testSinFloat3Float3(in, out);
+            verifyResultsSinFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testSinFloat3Float3(in, out);
+            verifyResultsSinFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSinFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeSin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkSinFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkSinFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x925407d99b0a7dc1l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testSinFloat4Float4(in, out);
+            verifyResultsSinFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testSinFloat4Float4(in, out);
+            verifyResultsSinFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSinFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeSin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkSinFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testSin() {
+        checkSinFloatFloat();
+        checkSinFloat2Float2();
+        checkSinFloat3Float3();
+        checkSinFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestSin.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestSin.rs
new file mode 100644
index 0000000..15e78ba
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestSin.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testSinFloatFloat(float in) {
+    return sin(in);
+}
+
+float2 __attribute__((kernel)) testSinFloat2Float2(float2 in) {
+    return sin(in);
+}
+
+float3 __attribute__((kernel)) testSinFloat3Float3(float3 in) {
+    return sin(in);
+}
+
+float4 __attribute__((kernel)) testSinFloat4Float4(float4 in) {
+    return sin(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestSinRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestSinRelaxed.rs
new file mode 100644
index 0000000..e9e49123
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestSinRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestSin.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestSincos.java b/tests/tests/renderscript/src/android/renderscript/cts/TestSincos.java
new file mode 100644
index 0000000..60c6ef0
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestSincos.java
@@ -0,0 +1,361 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestSincos extends RSBaseCompute {
+
+    private ScriptC_TestSincos script;
+    private ScriptC_TestSincosRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestSincos(mRS);
+        scriptRelaxed = new ScriptC_TestSincosRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float inV;
+        public Target.Floaty outCosptr;
+        public Target.Floaty out;
+    }
+
+    private void checkSincosFloatFloatFloat() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xb8748e13e46c48d4l, false);
+        try {
+            Allocation outCosptr = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocOutCosptr(outCosptr);
+            script.forEach_testSincosFloatFloatFloat(inV, out);
+            verifyResultsSincosFloatFloatFloat(inV, outCosptr, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSincosFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation outCosptr = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutCosptr(outCosptr);
+            scriptRelaxed.forEach_testSincosFloatFloatFloat(inV, out);
+            verifyResultsSincosFloatFloatFloat(inV, outCosptr, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSincosFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSincosFloatFloatFloat(Allocation inV, Allocation outCosptr, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOutCosptr = new float[INPUTSIZE * 1];
+        outCosptr.copyTo(arrayOutCosptr);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeSincos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outCosptr.couldBe(arrayOutCosptr[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output outCosptr: ");
+                    message.append(args.outCosptr.toString());
+                    message.append("\n");
+                    message.append("Actual   output outCosptr: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOutCosptr[i * 1 + j], Float.floatToRawIntBits(arrayOutCosptr[i * 1 + j]), arrayOutCosptr[i * 1 + j]));
+                    if (!args.outCosptr.couldBe(arrayOutCosptr[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkSincosFloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkSincosFloat2Float2Float2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xc85bab4e3e2fc77cl, false);
+        try {
+            Allocation outCosptr = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocOutCosptr(outCosptr);
+            script.forEach_testSincosFloat2Float2Float2(inV, out);
+            verifyResultsSincosFloat2Float2Float2(inV, outCosptr, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSincosFloat2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation outCosptr = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutCosptr(outCosptr);
+            scriptRelaxed.forEach_testSincosFloat2Float2Float2(inV, out);
+            verifyResultsSincosFloat2Float2Float2(inV, outCosptr, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSincosFloat2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSincosFloat2Float2Float2(Allocation inV, Allocation outCosptr, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOutCosptr = new float[INPUTSIZE * 2];
+        outCosptr.copyTo(arrayOutCosptr);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeSincos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outCosptr.couldBe(arrayOutCosptr[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output outCosptr: ");
+                    message.append(args.outCosptr.toString());
+                    message.append("\n");
+                    message.append("Actual   output outCosptr: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOutCosptr[i * 2 + j], Float.floatToRawIntBits(arrayOutCosptr[i * 2 + j]), arrayOutCosptr[i * 2 + j]));
+                    if (!args.outCosptr.couldBe(arrayOutCosptr[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkSincosFloat2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkSincosFloat3Float3Float3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x1cc0896e400dc91dl, false);
+        try {
+            Allocation outCosptr = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocOutCosptr(outCosptr);
+            script.forEach_testSincosFloat3Float3Float3(inV, out);
+            verifyResultsSincosFloat3Float3Float3(inV, outCosptr, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSincosFloat3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation outCosptr = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutCosptr(outCosptr);
+            scriptRelaxed.forEach_testSincosFloat3Float3Float3(inV, out);
+            verifyResultsSincosFloat3Float3Float3(inV, outCosptr, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSincosFloat3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSincosFloat3Float3Float3(Allocation inV, Allocation outCosptr, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOutCosptr = new float[INPUTSIZE * 4];
+        outCosptr.copyTo(arrayOutCosptr);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeSincos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outCosptr.couldBe(arrayOutCosptr[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output outCosptr: ");
+                    message.append(args.outCosptr.toString());
+                    message.append("\n");
+                    message.append("Actual   output outCosptr: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOutCosptr[i * 4 + j], Float.floatToRawIntBits(arrayOutCosptr[i * 4 + j]), arrayOutCosptr[i * 4 + j]));
+                    if (!args.outCosptr.couldBe(arrayOutCosptr[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkSincosFloat3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkSincosFloat4Float4Float4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x7125678e41ebcabel, false);
+        try {
+            Allocation outCosptr = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocOutCosptr(outCosptr);
+            script.forEach_testSincosFloat4Float4Float4(inV, out);
+            verifyResultsSincosFloat4Float4Float4(inV, outCosptr, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSincosFloat4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation outCosptr = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutCosptr(outCosptr);
+            scriptRelaxed.forEach_testSincosFloat4Float4Float4(inV, out);
+            verifyResultsSincosFloat4Float4Float4(inV, outCosptr, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSincosFloat4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSincosFloat4Float4Float4(Allocation inV, Allocation outCosptr, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOutCosptr = new float[INPUTSIZE * 4];
+        outCosptr.copyTo(arrayOutCosptr);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeSincos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outCosptr.couldBe(arrayOutCosptr[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output outCosptr: ");
+                    message.append(args.outCosptr.toString());
+                    message.append("\n");
+                    message.append("Actual   output outCosptr: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOutCosptr[i * 4 + j], Float.floatToRawIntBits(arrayOutCosptr[i * 4 + j]), arrayOutCosptr[i * 4 + j]));
+                    if (!args.outCosptr.couldBe(arrayOutCosptr[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkSincosFloat4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testSincos() {
+        checkSincosFloatFloatFloat();
+        checkSincosFloat2Float2Float2();
+        checkSincosFloat3Float3Float3();
+        checkSincosFloat4Float4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestSincos.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestSincos.rs
new file mode 100644
index 0000000..82ff9cd
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestSincos.rs
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocOutCosptr;
+
+float __attribute__((kernel)) testSincosFloatFloatFloat(float inV, unsigned int x) {
+    float outCosptr = 0;
+    float out = sincos(inV, &outCosptr);
+    rsSetElementAt_float(gAllocOutCosptr, outCosptr, x);
+    return out;
+}
+
+float2 __attribute__((kernel)) testSincosFloat2Float2Float2(float2 inV, unsigned int x) {
+    float2 outCosptr = 0;
+    float2 out = sincos(inV, &outCosptr);
+    rsSetElementAt_float2(gAllocOutCosptr, outCosptr, x);
+    return out;
+}
+
+float3 __attribute__((kernel)) testSincosFloat3Float3Float3(float3 inV, unsigned int x) {
+    float3 outCosptr = 0;
+    float3 out = sincos(inV, &outCosptr);
+    rsSetElementAt_float3(gAllocOutCosptr, outCosptr, x);
+    return out;
+}
+
+float4 __attribute__((kernel)) testSincosFloat4Float4Float4(float4 inV, unsigned int x) {
+    float4 outCosptr = 0;
+    float4 out = sincos(inV, &outCosptr);
+    rsSetElementAt_float4(gAllocOutCosptr, outCosptr, x);
+    return out;
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestSincosRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestSincosRelaxed.rs
new file mode 100644
index 0000000..56cb9fc
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestSincosRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestSincos.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestSinh.java b/tests/tests/renderscript/src/android/renderscript/cts/TestSinh.java
new file mode 100644
index 0000000..1ebcba2
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestSinh.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestSinh extends RSBaseCompute {
+
+    private ScriptC_TestSinh script;
+    private ScriptC_TestSinhRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestSinh(mRS);
+        scriptRelaxed = new ScriptC_TestSinhRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkSinhFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x541c2eef0a5d2ff1l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testSinhFloatFloat(in, out);
+            verifyResultsSinhFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinhFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testSinhFloatFloat(in, out);
+            verifyResultsSinhFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinhFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSinhFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeSinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkSinhFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkSinhFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x7f8e1e7d8c47bec5l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testSinhFloat2Float2(in, out);
+            verifyResultsSinhFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinhFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testSinhFloat2Float2(in, out);
+            verifyResultsSinhFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinhFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSinhFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeSinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkSinhFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkSinhFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x7f8e291eeb4e545fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testSinhFloat3Float3(in, out);
+            verifyResultsSinhFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinhFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testSinhFloat3Float3(in, out);
+            verifyResultsSinhFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinhFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSinhFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeSinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkSinhFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkSinhFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x7f8e33c04a54e9f9l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testSinhFloat4Float4(in, out);
+            verifyResultsSinhFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinhFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testSinhFloat4Float4(in, out);
+            verifyResultsSinhFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinhFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSinhFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeSinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkSinhFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testSinh() {
+        checkSinhFloatFloat();
+        checkSinhFloat2Float2();
+        checkSinhFloat3Float3();
+        checkSinhFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestSinh.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestSinh.rs
new file mode 100644
index 0000000..bd94f0d
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestSinh.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testSinhFloatFloat(float in) {
+    return sinh(in);
+}
+
+float2 __attribute__((kernel)) testSinhFloat2Float2(float2 in) {
+    return sinh(in);
+}
+
+float3 __attribute__((kernel)) testSinhFloat3Float3(float3 in) {
+    return sinh(in);
+}
+
+float4 __attribute__((kernel)) testSinhFloat4Float4(float4 in) {
+    return sinh(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestSinhRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestSinhRelaxed.rs
new file mode 100644
index 0000000..8ca3390
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestSinhRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestSinh.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestSinpi.java b/tests/tests/renderscript/src/android/renderscript/cts/TestSinpi.java
new file mode 100644
index 0000000..2df09b8
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestSinpi.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestSinpi extends RSBaseCompute {
+
+    private ScriptC_TestSinpi script;
+    private ScriptC_TestSinpiRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestSinpi(mRS);
+        scriptRelaxed = new ScriptC_TestSinpiRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkSinpiFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x34cb59f49416da82l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testSinpiFloatFloat(in, out);
+            verifyResultsSinpiFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinpiFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testSinpiFloatFloat(in, out);
+            verifyResultsSinpiFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinpiFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSinpiFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeSinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkSinpiFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkSinpiFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x50bbd97d4a48b00el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testSinpiFloat2Float2(in, out);
+            verifyResultsSinpiFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinpiFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testSinpiFloat2Float2(in, out);
+            verifyResultsSinpiFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinpiFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSinpiFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeSinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkSinpiFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkSinpiFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x50bbe41ea94f45a8l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testSinpiFloat3Float3(in, out);
+            verifyResultsSinpiFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinpiFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testSinpiFloat3Float3(in, out);
+            verifyResultsSinpiFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinpiFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSinpiFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeSinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkSinpiFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkSinpiFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x50bbeec00855db42l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testSinpiFloat4Float4(in, out);
+            verifyResultsSinpiFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinpiFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testSinpiFloat4Float4(in, out);
+            verifyResultsSinpiFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinpiFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSinpiFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeSinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkSinpiFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testSinpi() {
+        checkSinpiFloatFloat();
+        checkSinpiFloat2Float2();
+        checkSinpiFloat3Float3();
+        checkSinpiFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestSinpi.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestSinpi.rs
new file mode 100644
index 0000000..367040e
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestSinpi.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testSinpiFloatFloat(float in) {
+    return sinpi(in);
+}
+
+float2 __attribute__((kernel)) testSinpiFloat2Float2(float2 in) {
+    return sinpi(in);
+}
+
+float3 __attribute__((kernel)) testSinpiFloat3Float3(float3 in) {
+    return sinpi(in);
+}
+
+float4 __attribute__((kernel)) testSinpiFloat4Float4(float4 in) {
+    return sinpi(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestSinpiRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestSinpiRelaxed.rs
new file mode 100644
index 0000000..dd611a7
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestSinpiRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestSinpi.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestSqrt.java b/tests/tests/renderscript/src/android/renderscript/cts/TestSqrt.java
new file mode 100644
index 0000000..4537c3d
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestSqrt.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestSqrt extends RSBaseCompute {
+
+    private ScriptC_TestSqrt script;
+    private ScriptC_TestSqrtRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestSqrt(mRS);
+        scriptRelaxed = new ScriptC_TestSqrtRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkSqrtFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x940922bedb2c9271l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testSqrtFloatFloat(in, out);
+            verifyResultsSqrtFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSqrtFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testSqrtFloatFloat(in, out);
+            verifyResultsSqrtFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSqrtFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSqrtFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeSqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkSqrtFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkSqrtFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x35fb1678b6262d45l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testSqrtFloat2Float2(in, out);
+            verifyResultsSqrtFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSqrtFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testSqrtFloat2Float2(in, out);
+            verifyResultsSqrtFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSqrtFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSqrtFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeSqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkSqrtFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkSqrtFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x35fb211a152cc2dfl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testSqrtFloat3Float3(in, out);
+            verifyResultsSqrtFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSqrtFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testSqrtFloat3Float3(in, out);
+            verifyResultsSqrtFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSqrtFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSqrtFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeSqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkSqrtFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkSqrtFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x35fb2bbb74335879l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testSqrtFloat4Float4(in, out);
+            verifyResultsSqrtFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSqrtFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testSqrtFloat4Float4(in, out);
+            verifyResultsSqrtFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSqrtFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSqrtFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeSqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkSqrtFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testSqrt() {
+        checkSqrtFloatFloat();
+        checkSqrtFloat2Float2();
+        checkSqrtFloat3Float3();
+        checkSqrtFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestSqrt.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestSqrt.rs
new file mode 100644
index 0000000..f1c163b
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestSqrt.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testSqrtFloatFloat(float in) {
+    return sqrt(in);
+}
+
+float2 __attribute__((kernel)) testSqrtFloat2Float2(float2 in) {
+    return sqrt(in);
+}
+
+float3 __attribute__((kernel)) testSqrtFloat3Float3(float3 in) {
+    return sqrt(in);
+}
+
+float4 __attribute__((kernel)) testSqrtFloat4Float4(float4 in) {
+    return sqrt(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestSqrtRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestSqrtRelaxed.rs
new file mode 100644
index 0000000..ee5b6a8
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestSqrtRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestSqrt.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestStep.java b/tests/tests/renderscript/src/android/renderscript/cts/TestStep.java
new file mode 100644
index 0000000..dabfd45
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestStep.java
@@ -0,0 +1,745 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestStep extends RSBaseCompute {
+
+    private ScriptC_TestStep script;
+    private ScriptC_TestStepRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestStep(mRS);
+        scriptRelaxed = new ScriptC_TestStepRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloatFloat {
+        public float inEdge;
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkStepFloatFloatFloat() {
+        Allocation inEdge = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x598900c49184fbfel, false);
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x9aefccaa832f44e9l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.set_gAllocInV(inV);
+            script.forEach_testStepFloatFloatFloat(inEdge, out);
+            verifyResultsStepFloatFloatFloat(inEdge, inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepFloatFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV(inV);
+            scriptRelaxed.forEach_testStepFloatFloatFloat(inEdge, out);
+            verifyResultsStepFloatFloatFloat(inEdge, inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepFloatFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsStepFloatFloatFloat(Allocation inEdge, Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInEdge = new float[INPUTSIZE * 1];
+        inEdge.copyTo(arrayInEdge);
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inEdge = arrayInEdge[i];
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeStep(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inEdge: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inEdge, Float.floatToRawIntBits(args.inEdge), args.inEdge));
+                    message.append("\n");
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkStepFloatFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkStepFloat2Float2Float2() {
+        Allocation inEdge = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x6efefa297df69504l, false);
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x12eb000b8567f58bl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInV(inV);
+            script.forEach_testStepFloat2Float2Float2(inEdge, out);
+            verifyResultsStepFloat2Float2Float2(inEdge, inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepFloat2Float2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV(inV);
+            scriptRelaxed.forEach_testStepFloat2Float2Float2(inEdge, out);
+            verifyResultsStepFloat2Float2Float2(inEdge, inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepFloat2Float2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsStepFloat2Float2Float2(Allocation inEdge, Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInEdge = new float[INPUTSIZE * 2];
+        inEdge.copyTo(arrayInEdge);
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inEdge = arrayInEdge[i * 2 + j];
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeStep(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inEdge: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inEdge, Float.floatToRawIntBits(args.inEdge), args.inEdge));
+                    message.append("\n");
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkStepFloat2Float2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkStepFloat3Float3Float3() {
+        Allocation inEdge = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x9e548cd666a7a77l, false);
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x674fde2b8745f72cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInV(inV);
+            script.forEach_testStepFloat3Float3Float3(inEdge, out);
+            verifyResultsStepFloat3Float3Float3(inEdge, inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepFloat3Float3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV(inV);
+            scriptRelaxed.forEach_testStepFloat3Float3Float3(inEdge, out);
+            verifyResultsStepFloat3Float3Float3(inEdge, inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepFloat3Float3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsStepFloat3Float3Float3(Allocation inEdge, Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInEdge = new float[INPUTSIZE * 4];
+        inEdge.copyTo(arrayInEdge);
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inEdge = arrayInEdge[i * 4 + j];
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeStep(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inEdge: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inEdge, Float.floatToRawIntBits(args.inEdge), args.inEdge));
+                    message.append("\n");
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkStepFloat3Float3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkStepFloat4Float4Float4() {
+        Allocation inEdge = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xa4cb97714ede5feal, false);
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xbbb4bc4b8923f8cdl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInV(inV);
+            script.forEach_testStepFloat4Float4Float4(inEdge, out);
+            verifyResultsStepFloat4Float4Float4(inEdge, inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepFloat4Float4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV(inV);
+            scriptRelaxed.forEach_testStepFloat4Float4Float4(inEdge, out);
+            verifyResultsStepFloat4Float4Float4(inEdge, inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepFloat4Float4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsStepFloat4Float4Float4(Allocation inEdge, Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInEdge = new float[INPUTSIZE * 4];
+        inEdge.copyTo(arrayInEdge);
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inEdge = arrayInEdge[i * 4 + j];
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeStep(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inEdge: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inEdge, Float.floatToRawIntBits(args.inEdge), args.inEdge));
+                    message.append("\n");
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkStepFloat4Float4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkStepFloat2FloatFloat2() {
+        Allocation inEdge = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xb0ac06c45b3d8b26l, false);
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xfa7d66f2b6d48a21l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInV(inV);
+            script.forEach_testStepFloat2FloatFloat2(inEdge, out);
+            verifyResultsStepFloat2FloatFloat2(inEdge, inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepFloat2FloatFloat2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV(inV);
+            scriptRelaxed.forEach_testStepFloat2FloatFloat2(inEdge, out);
+            verifyResultsStepFloat2FloatFloat2(inEdge, inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepFloat2FloatFloat2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsStepFloat2FloatFloat2(Allocation inEdge, Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInEdge = new float[INPUTSIZE * 2];
+        inEdge.copyTo(arrayInEdge);
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inEdge = arrayInEdge[i * 2 + j];
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeStep(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inEdge: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inEdge, Float.floatToRawIntBits(args.inEdge), args.inEdge));
+                    message.append("\n");
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkStepFloat2FloatFloat2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkStepFloat3FloatFloat3() {
+        Allocation inEdge = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x304ed837c68f43fal, false);
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x4fcd1a0aa53f7e7dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInV(inV);
+            script.forEach_testStepFloat3FloatFloat3(inEdge, out);
+            verifyResultsStepFloat3FloatFloat3(inEdge, inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepFloat3FloatFloat3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV(inV);
+            scriptRelaxed.forEach_testStepFloat3FloatFloat3(inEdge, out);
+            verifyResultsStepFloat3FloatFloat3(inEdge, inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepFloat3FloatFloat3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsStepFloat3FloatFloat3(Allocation inEdge, Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInEdge = new float[INPUTSIZE * 4];
+        inEdge.copyTo(arrayInEdge);
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inEdge = arrayInEdge[i * 4 + j];
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeStep(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inEdge: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inEdge, Float.floatToRawIntBits(args.inEdge), args.inEdge));
+                    message.append("\n");
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkStepFloat3FloatFloat3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkStepFloat4FloatFloat4() {
+        Allocation inEdge = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xaff1a9ab31e0fccel, false);
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xa51ccd2293aa72d9l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInV(inV);
+            script.forEach_testStepFloat4FloatFloat4(inEdge, out);
+            verifyResultsStepFloat4FloatFloat4(inEdge, inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepFloat4FloatFloat4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV(inV);
+            scriptRelaxed.forEach_testStepFloat4FloatFloat4(inEdge, out);
+            verifyResultsStepFloat4FloatFloat4(inEdge, inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepFloat4FloatFloat4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsStepFloat4FloatFloat4(Allocation inEdge, Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInEdge = new float[INPUTSIZE * 4];
+        inEdge.copyTo(arrayInEdge);
+        float[] arrayInV = new float[INPUTSIZE * 1];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inEdge = arrayInEdge[i * 4 + j];
+                args.inV = arrayInV[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeStep(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inEdge: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inEdge, Float.floatToRawIntBits(args.inEdge), args.inEdge));
+                    message.append("\n");
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkStepFloat4FloatFloat4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkStepFloatFloat2Float2() {
+        Allocation inEdge = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x70a0554e664b1852l, false);
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xdd7f0d444e2f7c5l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.set_gAllocInV(inV);
+            script.forEach_testStepFloatFloat2Float2(inEdge, out);
+            verifyResultsStepFloatFloat2Float2(inEdge, inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepFloatFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV(inV);
+            scriptRelaxed.forEach_testStepFloatFloat2Float2(inEdge, out);
+            verifyResultsStepFloatFloat2Float2(inEdge, inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepFloatFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsStepFloatFloat2Float2(Allocation inEdge, Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInEdge = new float[INPUTSIZE * 1];
+        inEdge.copyTo(arrayInEdge);
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inEdge = arrayInEdge[i];
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeStep(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inEdge: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inEdge, Float.floatToRawIntBits(args.inEdge), args.inEdge));
+                    message.append("\n");
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkStepFloatFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkStepFloatFloat3Float3() {
+        Allocation inEdge = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x9b2d75ce91abcbccl, false);
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xdd9b9ef3afe18a3l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.set_gAllocInV(inV);
+            script.forEach_testStepFloatFloat3Float3(inEdge, out);
+            verifyResultsStepFloatFloat3Float3(inEdge, inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepFloatFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV(inV);
+            scriptRelaxed.forEach_testStepFloatFloat3Float3(inEdge, out);
+            verifyResultsStepFloatFloat3Float3(inEdge, inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepFloatFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsStepFloatFloat3Float3(Allocation inEdge, Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInEdge = new float[INPUTSIZE * 1];
+        inEdge.copyTo(arrayInEdge);
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inEdge = arrayInEdge[i];
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeStep(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inEdge: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inEdge, Float.floatToRawIntBits(args.inEdge), args.inEdge));
+                    message.append("\n");
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkStepFloatFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkStepFloatFloat4Float4() {
+        Allocation inEdge = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xc5ba964ebd0c7f46l, false);
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xddb830a31193981l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.set_gAllocInV(inV);
+            script.forEach_testStepFloatFloat4Float4(inEdge, out);
+            verifyResultsStepFloatFloat4Float4(inEdge, inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepFloatFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV(inV);
+            scriptRelaxed.forEach_testStepFloatFloat4Float4(inEdge, out);
+            verifyResultsStepFloatFloat4Float4(inEdge, inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepFloatFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsStepFloatFloat4Float4(Allocation inEdge, Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInEdge = new float[INPUTSIZE * 1];
+        inEdge.copyTo(arrayInEdge);
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloatFloat args = new ArgumentsFloatFloatFloat();
+                args.inEdge = arrayInEdge[i];
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeStep(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input inEdge: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inEdge, Float.floatToRawIntBits(args.inEdge), args.inEdge));
+                    message.append("\n");
+                    message.append("Input inV: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.inV, Float.floatToRawIntBits(args.inV), args.inV));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkStepFloatFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testStep() {
+        checkStepFloatFloatFloat();
+        checkStepFloat2Float2Float2();
+        checkStepFloat3Float3Float3();
+        checkStepFloat4Float4Float4();
+        checkStepFloat2FloatFloat2();
+        checkStepFloat3FloatFloat3();
+        checkStepFloat4FloatFloat4();
+        checkStepFloatFloat2Float2();
+        checkStepFloatFloat3Float3();
+        checkStepFloatFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestStep.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestStep.rs
new file mode 100644
index 0000000..b815d52
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestStep.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+rs_allocation gAllocInV;
+
+float __attribute__((kernel)) testStepFloatFloatFloat(float inEdge, unsigned int x) {
+    float inV = rsGetElementAt_float(gAllocInV, x);
+    return step(inEdge, inV);
+}
+
+float2 __attribute__((kernel)) testStepFloat2Float2Float2(float2 inEdge, unsigned int x) {
+    float2 inV = rsGetElementAt_float2(gAllocInV, x);
+    return step(inEdge, inV);
+}
+
+float3 __attribute__((kernel)) testStepFloat3Float3Float3(float3 inEdge, unsigned int x) {
+    float3 inV = rsGetElementAt_float3(gAllocInV, x);
+    return step(inEdge, inV);
+}
+
+float4 __attribute__((kernel)) testStepFloat4Float4Float4(float4 inEdge, unsigned int x) {
+    float4 inV = rsGetElementAt_float4(gAllocInV, x);
+    return step(inEdge, inV);
+}
+
+float2 __attribute__((kernel)) testStepFloat2FloatFloat2(float2 inEdge, unsigned int x) {
+    float inV = rsGetElementAt_float(gAllocInV, x);
+    return step(inEdge, inV);
+}
+
+float3 __attribute__((kernel)) testStepFloat3FloatFloat3(float3 inEdge, unsigned int x) {
+    float inV = rsGetElementAt_float(gAllocInV, x);
+    return step(inEdge, inV);
+}
+
+float4 __attribute__((kernel)) testStepFloat4FloatFloat4(float4 inEdge, unsigned int x) {
+    float inV = rsGetElementAt_float(gAllocInV, x);
+    return step(inEdge, inV);
+}
+
+float2 __attribute__((kernel)) testStepFloatFloat2Float2(float inEdge, unsigned int x) {
+    float2 inV = rsGetElementAt_float2(gAllocInV, x);
+    return step(inEdge, inV);
+}
+
+float3 __attribute__((kernel)) testStepFloatFloat3Float3(float inEdge, unsigned int x) {
+    float3 inV = rsGetElementAt_float3(gAllocInV, x);
+    return step(inEdge, inV);
+}
+
+float4 __attribute__((kernel)) testStepFloatFloat4Float4(float inEdge, unsigned int x) {
+    float4 inV = rsGetElementAt_float4(gAllocInV, x);
+    return step(inEdge, inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestStepRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestStepRelaxed.rs
new file mode 100644
index 0000000..b2bad68
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestStepRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestStep.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestTan.java b/tests/tests/renderscript/src/android/renderscript/cts/TestTan.java
new file mode 100644
index 0000000..29dae6f
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestTan.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestTan extends RSBaseCompute {
+
+    private ScriptC_TestTan script;
+    private ScriptC_TestTanRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestTan(mRS);
+        scriptRelaxed = new ScriptC_TestTanRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkTanFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xfb95a6a791c2b8eal, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testTanFloatFloat(in, out);
+            verifyResultsTanFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testTanFloatFloat(in, out);
+            verifyResultsTanFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTanFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeTan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkTanFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkTanFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x1bdfd24778a20d36l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testTanFloat2Float2(in, out);
+            verifyResultsTanFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testTanFloat2Float2(in, out);
+            verifyResultsTanFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTanFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeTan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkTanFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkTanFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x1bdfdce8d7a8a2d0l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testTanFloat3Float3(in, out);
+            verifyResultsTanFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testTanFloat3Float3(in, out);
+            verifyResultsTanFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTanFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeTan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkTanFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkTanFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x1bdfe78a36af386al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testTanFloat4Float4(in, out);
+            verifyResultsTanFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testTanFloat4Float4(in, out);
+            verifyResultsTanFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTanFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeTan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkTanFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testTan() {
+        checkTanFloatFloat();
+        checkTanFloat2Float2();
+        checkTanFloat3Float3();
+        checkTanFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestTan.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestTan.rs
new file mode 100644
index 0000000..1024943
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestTan.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testTanFloatFloat(float in) {
+    return tan(in);
+}
+
+float2 __attribute__((kernel)) testTanFloat2Float2(float2 in) {
+    return tan(in);
+}
+
+float3 __attribute__((kernel)) testTanFloat3Float3(float3 in) {
+    return tan(in);
+}
+
+float4 __attribute__((kernel)) testTanFloat4Float4(float4 in) {
+    return tan(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestTanRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestTanRelaxed.rs
new file mode 100644
index 0000000..9297033
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestTanRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestTan.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestTanh.java b/tests/tests/renderscript/src/android/renderscript/cts/TestTanh.java
new file mode 100644
index 0000000..e554ad8
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestTanh.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestTanh extends RSBaseCompute {
+
+    private ScriptC_TestTanh script;
+    private ScriptC_TestTanhRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestTanh(mRS);
+        scriptRelaxed = new ScriptC_TestTanhRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkTanhFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xfe01ab34a2d2226cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testTanhFloatFloat(in, out);
+            verifyResultsTanhFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanhFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testTanhFloatFloat(in, out);
+            verifyResultsTanhFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanhFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTanhFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeTanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkTanhFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkTanhFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x9a0cb127b0f31928l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testTanhFloat2Float2(in, out);
+            verifyResultsTanhFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanhFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testTanhFloat2Float2(in, out);
+            verifyResultsTanhFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanhFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTanhFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeTanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkTanhFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkTanhFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x9a0cbbc90ff9aec2l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testTanhFloat3Float3(in, out);
+            verifyResultsTanhFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanhFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testTanhFloat3Float3(in, out);
+            verifyResultsTanhFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanhFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTanhFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeTanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkTanhFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkTanhFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x9a0cc66a6f00445cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testTanhFloat4Float4(in, out);
+            verifyResultsTanhFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanhFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testTanhFloat4Float4(in, out);
+            verifyResultsTanhFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanhFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTanhFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeTanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkTanhFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testTanh() {
+        checkTanhFloatFloat();
+        checkTanhFloat2Float2();
+        checkTanhFloat3Float3();
+        checkTanhFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestTanh.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestTanh.rs
new file mode 100644
index 0000000..a017c2b
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestTanh.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testTanhFloatFloat(float in) {
+    return tanh(in);
+}
+
+float2 __attribute__((kernel)) testTanhFloat2Float2(float2 in) {
+    return tanh(in);
+}
+
+float3 __attribute__((kernel)) testTanhFloat3Float3(float3 in) {
+    return tanh(in);
+}
+
+float4 __attribute__((kernel)) testTanhFloat4Float4(float4 in) {
+    return tanh(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestTanhRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestTanhRelaxed.rs
new file mode 100644
index 0000000..f99420a
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestTanhRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestTanh.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestTanpi.java b/tests/tests/renderscript/src/android/renderscript/cts/TestTanpi.java
new file mode 100644
index 0000000..5e45440
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestTanpi.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestTanpi extends RSBaseCompute {
+
+    private ScriptC_TestTanpi script;
+    private ScriptC_TestTanpiRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestTanpi(mRS);
+        scriptRelaxed = new ScriptC_TestTanpiRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkTanpiFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xbe5739a52fbb952bl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testTanpiFloatFloat(in, out);
+            verifyResultsTanpiFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanpiFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testTanpiFloatFloat(in, out);
+            verifyResultsTanpiFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanpiFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTanpiFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeTanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkTanpiFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkTanpiFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xc3fe7c117310deafl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testTanpiFloat2Float2(in, out);
+            verifyResultsTanpiFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanpiFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testTanpiFloat2Float2(in, out);
+            verifyResultsTanpiFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanpiFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTanpiFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeTanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkTanpiFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkTanpiFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xc3fe86b2d2177449l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testTanpiFloat3Float3(in, out);
+            verifyResultsTanpiFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanpiFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testTanpiFloat3Float3(in, out);
+            verifyResultsTanpiFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanpiFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTanpiFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeTanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkTanpiFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkTanpiFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xc3fe9154311e09e3l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testTanpiFloat4Float4(in, out);
+            verifyResultsTanpiFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanpiFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testTanpiFloat4Float4(in, out);
+            verifyResultsTanpiFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanpiFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTanpiFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeTanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkTanpiFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testTanpi() {
+        checkTanpiFloatFloat();
+        checkTanpiFloat2Float2();
+        checkTanpiFloat3Float3();
+        checkTanpiFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestTanpi.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestTanpi.rs
new file mode 100644
index 0000000..883a571
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestTanpi.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testTanpiFloatFloat(float in) {
+    return tanpi(in);
+}
+
+float2 __attribute__((kernel)) testTanpiFloat2Float2(float2 in) {
+    return tanpi(in);
+}
+
+float3 __attribute__((kernel)) testTanpiFloat3Float3(float3 in) {
+    return tanpi(in);
+}
+
+float4 __attribute__((kernel)) testTanpiFloat4Float4(float4 in) {
+    return tanpi(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestTanpiRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestTanpiRelaxed.rs
new file mode 100644
index 0000000..3fc9d28
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestTanpiRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestTanpi.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestTgamma.java b/tests/tests/renderscript/src/android/renderscript/cts/TestTgamma.java
new file mode 100644
index 0000000..c7bb7b5
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestTgamma.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestTgamma extends RSBaseCompute {
+
+    private ScriptC_TestTgamma script;
+    private ScriptC_TestTgammaRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestTgamma(mRS);
+        scriptRelaxed = new ScriptC_TestTgammaRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkTgammaFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xe45f5203be15b490l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testTgammaFloatFloat(in, out);
+            verifyResultsTgammaFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTgammaFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testTgammaFloatFloat(in, out);
+            verifyResultsTgammaFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTgammaFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTgammaFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeTgamma(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkTgammaFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkTgammaFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x74767f039bfd9f2cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testTgammaFloat2Float2(in, out);
+            verifyResultsTgammaFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTgammaFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testTgammaFloat2Float2(in, out);
+            verifyResultsTgammaFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTgammaFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTgammaFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeTgamma(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkTgammaFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkTgammaFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x747689a4fb0434c6l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testTgammaFloat3Float3(in, out);
+            verifyResultsTgammaFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTgammaFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testTgammaFloat3Float3(in, out);
+            verifyResultsTgammaFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTgammaFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTgammaFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeTgamma(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkTgammaFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkTgammaFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x747694465a0aca60l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testTgammaFloat4Float4(in, out);
+            verifyResultsTgammaFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTgammaFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testTgammaFloat4Float4(in, out);
+            verifyResultsTgammaFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTgammaFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTgammaFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeTgamma(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkTgammaFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testTgamma() {
+        checkTgammaFloatFloat();
+        checkTgammaFloat2Float2();
+        checkTgammaFloat3Float3();
+        checkTgammaFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestTgamma.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestTgamma.rs
new file mode 100644
index 0000000..7dae4cf
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestTgamma.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testTgammaFloatFloat(float in) {
+    return tgamma(in);
+}
+
+float2 __attribute__((kernel)) testTgammaFloat2Float2(float2 in) {
+    return tgamma(in);
+}
+
+float3 __attribute__((kernel)) testTgammaFloat3Float3(float3 in) {
+    return tgamma(in);
+}
+
+float4 __attribute__((kernel)) testTgammaFloat4Float4(float4 in) {
+    return tgamma(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestTgammaRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestTgammaRelaxed.rs
new file mode 100644
index 0000000..7d57ba0
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestTgammaRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestTgamma.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestTrunc.java b/tests/tests/renderscript/src/android/renderscript/cts/TestTrunc.java
new file mode 100644
index 0000000..0657844
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestTrunc.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+
+public class TestTrunc extends RSBaseCompute {
+
+    private ScriptC_TestTrunc script;
+    private ScriptC_TestTruncRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestTrunc(mRS);
+        scriptRelaxed = new ScriptC_TestTruncRelaxed(mRS);
+    }
+
+    public class ArgumentsFloatFloat {
+        public float in;
+        public Target.Floaty out;
+    }
+
+    private void checkTruncFloatFloat() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x6361d71a4dcff881l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            script.forEach_testTruncFloatFloat(in, out);
+            verifyResultsTruncFloatFloat(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTruncFloatFloat: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testTruncFloatFloat(in, out);
+            verifyResultsTruncFloatFloat(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTruncFloatFloat: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTruncFloatFloat(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 1];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 1];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeTrunc(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 1 + j], Float.floatToRawIntBits(arrayOut[i * 1 + j]), arrayOut[i * 1 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 1 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkTruncFloatFloat" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkTruncFloat2Float2() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xcda9bef7b45256d5l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testTruncFloat2Float2(in, out);
+            verifyResultsTruncFloat2Float2(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTruncFloat2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testTruncFloat2Float2(in, out);
+            verifyResultsTruncFloat2Float2(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTruncFloat2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTruncFloat2Float2(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 2];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeTrunc(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 2 + j], Float.floatToRawIntBits(arrayOut[i * 2 + j]), arrayOut[i * 2 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkTruncFloat2Float2" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkTruncFloat3Float3() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 3, 0xcda9c9991358ec6fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testTruncFloat3Float3(in, out);
+            verifyResultsTruncFloat3Float3(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTruncFloat3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testTruncFloat3Float3(in, out);
+            verifyResultsTruncFloat3Float3(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTruncFloat3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTruncFloat3Float3(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeTrunc(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkTruncFloat3Float3" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    private void checkTruncFloat4Float4() {
+        Allocation in = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 4, 0xcda9d43a725f8209l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testTruncFloat4Float4(in, out);
+            verifyResultsTruncFloat4Float4(in, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTruncFloat4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testTruncFloat4Float4(in, out);
+            verifyResultsTruncFloat4Float4(in, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTruncFloat4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTruncFloat4Float4(Allocation in, Allocation out, boolean relaxed) {
+        float[] arrayIn = new float[INPUTSIZE * 4];
+        in.copyTo(arrayIn);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        out.copyTo(arrayOut);
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatFloat args = new ArgumentsFloatFloat();
+                args.in = arrayIn[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(relaxed);
+                CoreMathVerifier.computeTrunc(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    StringBuilder message = new StringBuilder();
+                    message.append("Input in: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            args.in, Float.floatToRawIntBits(args.in), args.in));
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    message.append(args.out.toString());
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    message.append(String.format("%14.8g {%8x} %15a",
+                            arrayOut[i * 4 + j], Float.floatToRawIntBits(arrayOut[i * 4 + j]), arrayOut[i * 4 + j]));
+                    if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    assertTrue("Incorrect output for checkTruncFloat4Float4" +
+                            (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), valid);
+                }
+            }
+        }
+    }
+
+    public void testTrunc() {
+        checkTruncFloatFloat();
+        checkTruncFloat2Float2();
+        checkTruncFloat3Float3();
+        checkTruncFloat4Float4();
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestTrunc.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestTrunc.rs
new file mode 100644
index 0000000..2422ae4
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestTrunc.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
+
+float __attribute__((kernel)) testTruncFloatFloat(float in) {
+    return trunc(in);
+}
+
+float2 __attribute__((kernel)) testTruncFloat2Float2(float2 in) {
+    return trunc(in);
+}
+
+float3 __attribute__((kernel)) testTruncFloat3Float3(float3 in) {
+    return trunc(in);
+}
+
+float4 __attribute__((kernel)) testTruncFloat4Float4(float4 in) {
+    return trunc(in);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TestTruncRelaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/TestTruncRelaxed.rs
new file mode 100644
index 0000000..b365243
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/TestTruncRelaxed.rs
@@ -0,0 +1,20 @@
+/*
+ * 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 "TestTrunc.rs"
+#pragma rs_fp_relaxed
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/gen_runtime.
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/TruncTest.java b/tests/tests/renderscript/src/android/renderscript/cts/TruncTest.java
deleted file mode 100644
index f2a3e11..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/TruncTest.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.cts.stub.R;
-import android.renderscript.Allocation;
-import android.renderscript.RSRuntimeException;
-
-public class TruncTest extends RSBaseCompute {
-    private ScriptC_trunc_f32 script_f32;
-    private ScriptC_trunc_f32_relaxed script_f32_relaxed;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        script_f32 = new ScriptC_trunc_f32(mRS);
-        script_f32_relaxed = new ScriptC_trunc_f32_relaxed(mRS);
-    }
-
-    @Override
-    public void forEach(int testId, Allocation mIn, Allocation mOut) throws RSRuntimeException {
-        switch (testId) {
-        case TEST_F32:
-            script_f32.forEach_trunc_f32_1(mIn, mOut);
-            break;
-        case TEST_F32_2:
-            script_f32.forEach_trunc_f32_2(mIn, mOut);
-            break;
-        case TEST_F32_3:
-            script_f32.forEach_trunc_f32_3(mIn, mOut);
-            break;
-        case TEST_F32_4:
-            script_f32.forEach_trunc_f32_4(mIn, mOut);
-            break;
-
-        case TEST_RELAXED_F32:
-            script_f32_relaxed.forEach_trunc_f32_1(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_2:
-            script_f32_relaxed.forEach_trunc_f32_2(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_3:
-            script_f32_relaxed.forEach_trunc_f32_3(mIn, mOut);
-            break;
-        case TEST_RELAXED_F32_4:
-            script_f32_relaxed.forEach_trunc_f32_4(mIn, mOut);
-            break;
-        }
-    }
-
-    @Override
-    protected float[] getRefArray(float[] inArray, int input_size, int stride, int skip) {
-        float[] ref = new float[input_size * stride];
-        for (int i = 0; i < input_size; i++) {
-            for (int j = 0; j < stride - skip; j++) {
-                int idxSrc = i * stride + j;
-                int idxDst = i * (stride - skip) + j;
-                int sign = ((Float.floatToIntBits(inArray[idxSrc]) >> 31) & 0x01);
-                float trunc = (int)inArray[idxSrc];
-                if (sign == 1 && trunc == +0.0f) {
-                    trunc = -0.0f;
-                }
-                ref[idxDst] = trunc;
-            }
-        }
-        return ref;
-    }
-
-    /**
-     * trunc test for float
-     */
-    public void testTruncF32() {
-        doF32(0x12345678, 0);
-    }
-
-    public void testTruncF32_relaxed() {
-        doF32_relaxed(0x12345678, 0);
-    }
-
-    /**
-     * trunc test for float2
-     */
-    public void testTruncF32_2() {
-        doF32_2(0x12345a78, 0);
-    }
-
-    public void testTruncF32_2_relaxed() {
-        doF32_2_relaxed(0x12345a78, 0);
-    }
-
-    /**
-     * trunc test for float3
-     */
-    public void testTruncF32_3() {
-        doF32_3(0x12f45678, 0);
-    }
-
-    public void testTruncF32_3_relaxed() {
-        doF32_3_relaxed(0x12f45678, 0);
-    }
-
-    /**
-     * trunc test for float4
-     */
-    public void testTruncF32_4() {
-        doF32_4(0x123c5678, 0);
-    }
-
-    public void testTruncF32_4_relaxed() {
-        doF32_4_relaxed(0x123c5678, 0);
-    }
-
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/VersionTest.java b/tests/tests/renderscript/src/android/renderscript/cts/VersionTest.java
deleted file mode 100644
index c3dbea9..0000000
--- a/tests/tests/renderscript/src/android/renderscript/cts/VersionTest.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.renderscript.RenderScript.RSMessageHandler;
-import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
-
-/**
- * Test for appropriate handling of versioned bitcode.
- */
-public class VersionTest extends RSBaseCompute {
-    public void testVersion11() {
-        ScriptC_set_target_api_11 test11 = new ScriptC_set_target_api_11(mRS);
-        test11.invoke_check(11);
-        waitForMessage();
-        checkForErrors();
-    }
-
-    public void testVersion12() {
-        ScriptC_set_target_api_12 test12 = new ScriptC_set_target_api_12(mRS);
-        test12.invoke_check(12);
-        waitForMessage();
-        checkForErrors();
-    }
-
-    public void testVersion13() {
-        ScriptC_set_target_api_13 test13 = new ScriptC_set_target_api_13(mRS);
-        test13.invoke_check(13);
-        waitForMessage();
-        checkForErrors();
-    }
-
-    public void testVersion14() {
-        ScriptC_set_target_api_14 test14 = new ScriptC_set_target_api_14(mRS);
-        test14.invoke_check(14);
-        waitForMessage();
-        checkForErrors();
-    }
-
-    public void testVersion15() {
-        ScriptC_set_target_api_15 test15 = new ScriptC_set_target_api_15(mRS);
-        test15.invoke_check(15);
-        waitForMessage();
-        checkForErrors();
-    }
-
-    public void testVersion16() {
-        ScriptC_set_target_api_16 test16 = new ScriptC_set_target_api_16(mRS);
-        test16.invoke_check(16);
-        waitForMessage();
-        checkForErrors();
-    }
-
-    public void testVersion17() {
-        ScriptC_set_target_api_17 test17 = new ScriptC_set_target_api_17(mRS);
-        test17.invoke_check(17);
-        waitForMessage();
-        checkForErrors();
-    }
-
-    public void testVersion18() {
-        ScriptC_set_target_api_18 test18 = new ScriptC_set_target_api_18(mRS);
-        test18.invoke_check(18);
-        waitForMessage();
-        checkForErrors();
-    }
-
-    public void testVersion19() {
-        ScriptC_set_target_api_19 test19 = new ScriptC_set_target_api_19(mRS);
-        test19.invoke_check(19);
-        waitForMessage();
-        checkForErrors();
-    }
-
-    public void testVersion_too_high() {
-        try {
-            ScriptC_set_target_api_too_high test_too_high =
-                    new ScriptC_set_target_api_too_high(mRS,
-                                                        mRes,
-                                                        R.raw.set_target_api_too_high);
-            fail("should throw RSRuntimeException");
-        } catch (RSRuntimeException e) {
-        }
-        checkForErrors();
-    }
-}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/YuvTest.java b/tests/tests/renderscript/src/android/renderscript/cts/YuvTest.java
index c2c7275..21f4417 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/YuvTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/YuvTest.java
@@ -58,16 +58,10 @@
             bv[i] = (byte)r.nextInt(256);
         }
 
-        Type.Builder tb = new Type.Builder(mRS, Element.U8(mRS));
-        tb.setX(w);
-        tb.setY(h);
-        ay = Allocation.createTyped(mRS, tb.create());
-
-        tb = new Type.Builder(mRS, Element.U8(mRS));
-        tb.setX(w >> 1);
-        tb.setY(h >> 1);
-        au = Allocation.createTyped(mRS, tb.create());
-        av = Allocation.createTyped(mRS, tb.create());
+        ay = Allocation.createTyped(mRS, Type.createXY(mRS, Element.U8(mRS), w, h));
+        final Type tuv = Type.createXY(mRS, Element.U8(mRS), w >> 1, h >> 1);
+        au = Allocation.createTyped(mRS, tuv);
+        av = Allocation.createTyped(mRS, tuv);
 
         ay.copyFrom(by);
         au.copyFrom(bu);
@@ -75,11 +69,7 @@
     }
 
     public Allocation makeOutput() {
-        Type.Builder tb = new Type.Builder(mRS, Element.RGBA_8888(mRS));
-        tb.setX(width);
-        tb.setY(height);
-        Type t = tb.create();
-        return Allocation.createTyped(mRS, t);
+        return Allocation.createTyped(mRS, Type.createXY(mRS, Element.RGBA_8888(mRS), width, height));
     }
 
     // Test for the API 17 conversion path
diff --git a/tests/src/android/renderscript/cts/allocationCopy2DRange.rs b/tests/tests/renderscript/src/android/renderscript/cts/allocationCopy2DRange.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/allocationCopy2DRange.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/allocationCopy2DRange.rs
diff --git a/tests/src/android/renderscript/cts/allocation_resize.rs b/tests/tests/renderscript/src/android/renderscript/cts/allocation_resize.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/allocation_resize.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/allocation_resize.rs
diff --git a/tests/src/android/renderscript/cts/array_init.rs b/tests/tests/renderscript/src/android/renderscript/cts/array_init.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/array_init.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/array_init.rs
diff --git a/tests/src/android/renderscript/cts/clear_object.rs b/tests/tests/renderscript/src/android/renderscript/cts/clear_object.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/clear_object.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/clear_object.rs
diff --git a/tests/src/android/renderscript/cts/fe_all.rs b/tests/tests/renderscript/src/android/renderscript/cts/fe_all.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/fe_all.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/fe_all.rs
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/foreach.rs b/tests/tests/renderscript/src/android/renderscript/cts/foreach.rs
new file mode 100644
index 0000000..08e6bed
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/foreach.rs
@@ -0,0 +1,76 @@
+#include "shared.rsh"
+
+rs_allocation aRaw;
+int dimX;
+int dimY;
+static bool failed = false;
+
+void root(int *out, uint32_t x, uint32_t y) {
+    *out = x + y * dimX;
+}
+
+void foo(const int *in, int *out, uint32_t x, uint32_t y) {
+    _RS_ASSERT(*in == (x + y * dimX));
+    *out = 99 + x + y * dimX;
+    _RS_ASSERT(*out == (99 + x + y * dimX));
+}
+
+static bool test_root_output() {
+    bool failed = false;
+    int i, j;
+
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            int v = rsGetElementAt_int(aRaw, i, j);
+            _RS_ASSERT(v == (i + j * dimX));
+        }
+    }
+
+    if (failed) {
+        rsDebug("test_root_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_root_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+static bool test_foo_output() {
+    bool failed = false;
+    int i, j;
+
+    for (j = 0; j < dimY; j++) {
+        for (i = 0; i < dimX; i++) {
+            int v = rsGetElementAt_int(aRaw, i, j);
+            _RS_ASSERT(v == (99 + i + j * dimX));
+        }
+    }
+
+    if (failed) {
+        rsDebug("test_foo_output FAILED", 0);
+    }
+    else {
+        rsDebug("test_foo_output PASSED", 0);
+    }
+
+    return failed;
+}
+
+void verify_root() {
+    failed |= test_root_output();
+}
+
+void verify_foo() {
+    failed |= test_foo_output();
+}
+
+void foreach_test() {
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/src/android/renderscript/cts/get_allocation.rs b/tests/tests/renderscript/src/android/renderscript/cts/get_allocation.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/get_allocation.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/get_allocation.rs
diff --git a/tests/src/android/renderscript/cts/get_element_at_x.rs b/tests/tests/renderscript/src/android/renderscript/cts/get_element_at_x.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/get_element_at_x.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/get_element_at_x.rs
diff --git a/tests/src/android/renderscript/cts/get_element_at_x_y.rs b/tests/tests/renderscript/src/android/renderscript/cts/get_element_at_x_y.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/get_element_at_x_y.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/get_element_at_x_y.rs
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/getset.rs b/tests/tests/renderscript/src/android/renderscript/cts/getset.rs
new file mode 100644
index 0000000..4a8fa7f
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/getset.rs
@@ -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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+rs_allocation gAlloc1DIn;
+rs_allocation gAlloc1DOut;
+rs_allocation gAlloc2DIn;
+rs_allocation gAlloc2DOut;
+rs_allocation gAlloc3DIn;
+rs_allocation gAlloc3DOut;
+
+uint gWidth;
+uint gHeight;
+
+
+
+
+#define COPY_1D(ty)                                                 \
+    void __attribute__((kernel)) copy1D_##ty(int idx) {             \
+        ty i = rsGetElementAt_##ty(gAlloc1DIn, idx);                  \
+        rsSetElementAt_##ty(gAlloc1DOut, i, idx);                     \
+    }                                                               \
+    void __attribute__((kernel)) copy1D_##ty##2(int idx) {          \
+        ty##2 i = rsGetElementAt_##ty##2(gAlloc1DIn, idx);            \
+        rsSetElementAt_##ty##2(gAlloc1DOut, i, idx);                  \
+    }                                                               \
+    void __attribute__((kernel)) copy1D_##ty##3(int idx) {          \
+        ty##3 i = rsGetElementAt_##ty##3(gAlloc1DIn, idx);            \
+        rsSetElementAt_##ty##3(gAlloc1DOut, i, idx);                  \
+    }                                                               \
+    void __attribute__((kernel)) copy1D_##ty##4(int idx) {          \
+        ty##4 i = rsGetElementAt_##ty##4(gAlloc1DIn, idx);            \
+        rsSetElementAt_##ty##4(gAlloc1DOut, i, idx);                  \
+    }
+
+COPY_1D(char)
+COPY_1D(uchar)
+COPY_1D(short)
+COPY_1D(ushort)
+COPY_1D(int)
+COPY_1D(uint)
+COPY_1D(long)
+COPY_1D(ulong)
+COPY_1D(float)
+COPY_1D(double)
+
+
+
+#define COPY_2D(ty)                                                 \
+    void __attribute__((kernel)) copy2D_##ty(int idx) {             \
+        uint x = idx % gWidth;                                      \
+        uint y = idx / gWidth;                                      \
+        ty i = rsGetElementAt_##ty(gAlloc2DIn, x, y);                 \
+        rsSetElementAt_##ty(gAlloc2DOut, i, x, y);                    \
+    }                                                               \
+    void __attribute__((kernel)) copy2D_##ty##2(int idx) {          \
+        uint x = idx % gWidth;                                      \
+        uint y = idx / gWidth;                                      \
+        ty##2 i = rsGetElementAt_##ty##2(gAlloc2DIn, x, y);           \
+        rsSetElementAt_##ty##2(gAlloc2DOut, i, x, y);                 \
+    }                                                               \
+    void __attribute__((kernel)) copy2D_##ty##3(int idx) {          \
+        uint x = idx % gWidth;                                      \
+        uint y = idx / gWidth;                                      \
+        ty##3 i = rsGetElementAt_##ty##3(gAlloc2DIn, x, y);           \
+        rsSetElementAt_##ty##3(gAlloc2DOut, i, x, y);                 \
+    }                                                               \
+    void __attribute__((kernel)) copy2D_##ty##4(int idx) {          \
+        uint x = idx % gWidth;                                      \
+        uint y = idx / gWidth;                                      \
+        ty##4 i = rsGetElementAt_##ty##4(gAlloc2DIn, x, y);           \
+        rsSetElementAt_##ty##4(gAlloc2DOut, i, x, y);                 \
+    }
+
+COPY_2D(char)
+COPY_2D(uchar)
+COPY_2D(short)
+COPY_2D(ushort)
+COPY_2D(int)
+COPY_2D(uint)
+COPY_2D(long)
+COPY_2D(ulong)
+COPY_2D(float)
+COPY_2D(double)
+
+
+
+#define COPY_3D(ty)                                                 \
+    void __attribute__((kernel)) copy3D_##ty(int idx) {             \
+        uint x = idx % gWidth;                                      \
+        uint y = (idx / gWidth) % gHeight;                          \
+        uint z = idx / (gWidth * gHeight);                          \
+        ty i = rsGetElementAt_##ty(gAlloc3DIn, x, y, z);              \
+        rsSetElementAt_##ty(gAlloc3DOut, i, x, y, z);                 \
+    }                                                               \
+    void __attribute__((kernel)) copy3D_##ty##2(int idx) {          \
+        uint x = idx % gWidth;                                      \
+        uint y = (idx / gWidth) % gHeight;                          \
+        uint z = idx / (gWidth * gHeight);                          \
+        ty##2 i = rsGetElementAt_##ty##2(gAlloc3DIn, x, y, z);        \
+        rsSetElementAt_##ty##2(gAlloc3DOut, i, x, y, z);              \
+    }                                                               \
+    void __attribute__((kernel)) copy3D_##ty##3(int idx) {          \
+        uint x = idx % gWidth;                                      \
+        uint y = (idx / gWidth) % gHeight;                          \
+        uint z = idx / (gWidth * gHeight);                          \
+        ty##3 i = rsGetElementAt_##ty##3(gAlloc3DIn, x, y, z);        \
+        rsSetElementAt_##ty##3(gAlloc3DOut, i, x, y, z);              \
+    }                                                               \
+    void __attribute__((kernel)) copy3D_##ty##4(int idx) {          \
+        uint x = idx % gWidth;                                      \
+        uint y = (idx / gWidth) % gHeight;                          \
+        uint z = idx / (gWidth * gHeight);                          \
+        ty##4 i = rsGetElementAt_##ty##4(gAlloc3DIn, x, y, z);        \
+        rsSetElementAt_##ty##4(gAlloc3DOut, i, x, y, z);              \
+    }
+
+COPY_3D(char)
+COPY_3D(uchar)
+COPY_3D(short)
+COPY_3D(ushort)
+COPY_3D(int)
+COPY_3D(uint)
+COPY_3D(long)
+COPY_3D(ulong)
+COPY_3D(float)
+COPY_3D(double)
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/getset_relaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/getset_relaxed.rs
new file mode 100644
index 0000000..6b62faf
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/getset_relaxed.rs
@@ -0,0 +1,20 @@
+ /*
+ * 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.
+ */
+
+#pragma rs_fp_relaxed
+
+#include "getset.rs"
+
diff --git a/tests/src/android/renderscript/cts/global_sync.rs b/tests/tests/renderscript/src/android/renderscript/cts/global_sync.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/global_sync.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/global_sync.rs
diff --git a/tests/src/android/renderscript/cts/group1.rs b/tests/tests/renderscript/src/android/renderscript/cts/group1.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/group1.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/group1.rs
diff --git a/tests/src/android/renderscript/cts/group2.rs b/tests/tests/renderscript/src/android/renderscript/cts/group2.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/group2.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/group2.rs
diff --git a/tests/src/android/renderscript/cts/init_test.rs b/tests/tests/renderscript/src/android/renderscript/cts/init_test.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/init_test.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/init_test.rs
diff --git a/tests/src/android/renderscript/cts/instance.rs b/tests/tests/renderscript/src/android/renderscript/cts/instance.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/instance.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/instance.rs
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/intrinsic_3dlut.rs b/tests/tests/renderscript/src/android/renderscript/cts/intrinsic_3dlut.rs
new file mode 100644
index 0000000..d577b63
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/intrinsic_3dlut.rs
@@ -0,0 +1,62 @@
+/*
+ * 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"
+
+static rs_allocation gCube;
+static int4 gDims;
+static float4 gCoordMul;
+
+void setCube(rs_allocation c) {
+    gCube = c;
+    gDims.x = rsAllocationGetDimX(gCube);
+    gDims.y = rsAllocationGetDimY(gCube);
+    gDims.z = rsAllocationGetDimZ(gCube);
+    gDims.w = 0;
+    gCoordMul = (float4)(1.f / 255.f) * convert_float4(gDims - 1);
+}
+
+uchar4 __attribute__((kernel)) root(uchar4 in) {
+    float4 baseCoord = convert_float4(in) * gCoordMul;
+    int4 coord1 = convert_int4(floor(baseCoord));
+    int4 coord2 = min(coord1 + 1, gDims - 1);
+    float4 f = baseCoord - convert_float4(coord1);
+
+    float4 v000 = convert_float4(rsGetElementAt_uchar4(gCube, coord1.x, coord1.y, coord1.z));
+    float4 v100 = convert_float4(rsGetElementAt_uchar4(gCube, coord2.x, coord1.y, coord1.z));
+    float4 v010 = convert_float4(rsGetElementAt_uchar4(gCube, coord1.x, coord2.y, coord1.z));
+    float4 v110 = convert_float4(rsGetElementAt_uchar4(gCube, coord2.x, coord2.y, coord1.z));
+    float4 v001 = convert_float4(rsGetElementAt_uchar4(gCube, coord1.x, coord1.y, coord2.z));
+    float4 v101 = convert_float4(rsGetElementAt_uchar4(gCube, coord2.x, coord1.y, coord2.z));
+    float4 v011 = convert_float4(rsGetElementAt_uchar4(gCube, coord1.x, coord2.y, coord2.z));
+    float4 v111 = convert_float4(rsGetElementAt_uchar4(gCube, coord2.x, coord2.y, coord2.z));
+
+    float4 yz00 = mix(v000, v100, f.x);
+    float4 yz10 = mix(v010, v110, f.x);
+    float4 yz01 = mix(v001, v101, f.x);
+    float4 yz11 = mix(v011, v111, f.x);
+
+    float4 z0 = mix(yz00, yz10, f.y);
+    float4 z1 = mix(yz01, yz11, f.y);
+
+    float4 v = mix(z0, z1, f.z);
+
+    v = clamp(v, 0.f, 255.f);
+    uchar4 o = convert_uchar4(v + 0.5f);
+    o.w = in.w;
+    return o;
+}
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/intrinsic_blur.rs b/tests/tests/renderscript/src/android/renderscript/cts/intrinsic_blur.rs
new file mode 100644
index 0000000..88f9ca5
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/intrinsic_blur.rs
@@ -0,0 +1,96 @@
+/*
+ * 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"
+
+int height;
+int width;
+static int radius;
+rs_allocation ScratchPixel1;
+rs_allocation ScratchPixel2;
+
+const int MAX_RADIUS = 25;
+
+// Store our coefficients here
+static float gaussian[MAX_RADIUS * 2 + 1];
+
+float4 __attribute__((kernel)) convert1_uToF(uchar v) {
+    float4 r = rsUnpackColor8888(v);
+    return r.r;
+}
+
+float4 __attribute__((kernel)) convert4_uToF(uchar4 v) {
+    return rsUnpackColor8888(v);
+}
+
+uchar __attribute__((kernel)) convert1_fToU(float4 v) {
+    uchar4 r = rsPackColorTo8888(v);
+    return r.r;
+}
+
+uchar4 __attribute__((kernel)) convert4_fToU(float4 v) {
+    return rsPackColorTo8888(v);
+}
+
+void setRadius(int rad) {
+    // This function is a duplicate of:
+    // RsdCpuScriptIntrinsicBlur::ComputeGaussianWeights()
+    // Which is the reference C implementation
+    radius = rad;
+    const float e = M_E;
+    const float pi = M_PI;
+    float sigma = 0.4f * (float)radius + 0.6f;
+    float coeff1 = 1.0f / (sqrt( 2.0f * pi ) * sigma);
+    float coeff2 = - 1.0f / (2.0f * sigma * sigma);
+    float normalizeFactor = 0.0f;
+    float floatR = 0.0f;
+    for (int r = -radius; r <= radius; r ++) {
+        floatR = (float)r;
+        gaussian[r + radius] = coeff1 * pow(e, floatR * floatR * coeff2);
+        normalizeFactor += gaussian[r + radius];
+    }
+
+    normalizeFactor = 1.0f / normalizeFactor;
+    for (int r = -radius; r <= radius; r ++) {
+        floatR = (float)r;
+        gaussian[r + radius] *= normalizeFactor;
+    }
+}
+
+float4 __attribute__((kernel)) vert(uint32_t x, uint32_t y) {
+    float4 blurredPixel = 0;
+    int gi = 0;
+    for (int r = -radius; r <= radius; r ++) {
+        int validH = rsClamp((int)y + r, (int)0, (int)(height - 1));
+        float4 i = rsGetElementAt_float4(ScratchPixel2, x, validH);
+        blurredPixel += i * gaussian[gi++];
+    }
+    return blurredPixel;
+}
+
+float4 __attribute__((kernel)) horz(uint32_t x, uint32_t y) {
+    float4 blurredPixel = 0;
+    int gi = 0;
+    for (int r = -radius; r <= radius; r ++) {
+        // Stepping left and right away from the pixel
+        int validX = rsClamp((int)x + r, (int)0, (int)(width - 1));
+        float4 i = rsGetElementAt_float4(ScratchPixel1, validX, y);
+        blurredPixel += i * gaussian[gi++];
+    }
+    return blurredPixel;
+}
+
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/intrinsic_colormatrix.rs b/tests/tests/renderscript/src/android/renderscript/cts/intrinsic_colormatrix.rs
new file mode 100644
index 0000000..15c781c
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/intrinsic_colormatrix.rs
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2013 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"
+
+
+void reference(rs_matrix4x4 m, float4 add, rs_allocation in, rs_allocation out,
+               int x1, int y1, int x2, int y2) {
+    rs_element ein = rsAllocationGetElement(in);
+    rs_element eout = rsAllocationGetElement(out);
+    rs_data_type dtin = rsElementGetDataType(ein);
+    rs_data_type dtout = rsElementGetDataType(eout);
+    uint32_t vsin = rsElementGetVectorSize(ein);
+    uint32_t vsout = rsElementGetVectorSize(eout);
+
+    for (uint32_t y = y1; y < y2; y++) {
+        for (uint32_t x = x1; x < x2; x++) {
+            float4 pin = 0.f;
+
+            if (dtin == RS_TYPE_FLOAT_32) {
+                switch(vsin) {
+                case 4:
+                    pin.xyzw = rsGetElementAt_float4(in, x, y);
+                    break;
+                case 3:
+                    pin.xyz = rsGetElementAt_float3(in, x, y);
+                    break;
+                case 2:
+                    pin.xy = rsGetElementAt_float2(in, x, y);
+                    break;
+                case 1:
+                    pin.x = rsGetElementAt_float(in, x, y);
+                    break;
+                }
+            }
+
+            if (dtin == RS_TYPE_UNSIGNED_8) {
+                uchar4 u = 0;
+                switch(vsin) {
+                case 4:
+                    u.xyzw = rsGetElementAt_uchar4(in, x, y);
+                    break;
+                case 3:
+                    u.xyz = rsGetElementAt_uchar3(in, x, y);
+                    break;
+                case 2:
+                    u.xy = rsGetElementAt_uchar2(in, x, y);
+                    break;
+                case 1:
+                    u.x = rsGetElementAt_uchar(in, x, y);
+                    break;
+                }
+                pin = rsUnpackColor8888(u);
+            }
+
+            pin = rsMatrixMultiply(&m, pin);
+            pin += add;
+
+            if (dtout == RS_TYPE_FLOAT_32) {
+                switch(vsout) {
+                case 4:
+                    rsSetElementAt_float4(out, pin, x, y);
+                    break;
+                case 3:
+                    rsSetElementAt_float3(out, pin.xyz, x, y);
+                    break;
+                case 2:
+                    rsSetElementAt_float2(out, pin.xy, x, y);
+                    break;
+                case 1:
+                    rsSetElementAt_float(out, pin.x, x, y);
+                    break;
+                }
+            }
+
+            if (dtout == RS_TYPE_UNSIGNED_8) {
+                uchar4 u = rsPackColorTo8888(pin);
+                switch(vsout) {
+                case 4:
+                    rsSetElementAt_uchar4(out, u, x, y);
+                    break;
+                case 3:
+                    rsSetElementAt_uchar3(out, u.xyz, x, y);
+                    break;
+                case 2:
+                    rsSetElementAt_uchar2(out, u.xy, x, y);
+                    break;
+                case 1:
+                    rsSetElementAt_uchar(out, u.x, x, y);
+                    break;
+                }
+            }
+
+        }
+    }
+}
+
+
diff --git a/tests/src/android/renderscript/cts/intrinsic_convolve3x3.rs b/tests/tests/renderscript/src/android/renderscript/cts/intrinsic_convolve3x3.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/intrinsic_convolve3x3.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/intrinsic_convolve3x3.rs
diff --git a/tests/src/android/renderscript/cts/intrinsic_convolve5x5.rs b/tests/tests/renderscript/src/android/renderscript/cts/intrinsic_convolve5x5.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/intrinsic_convolve5x5.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/intrinsic_convolve5x5.rs
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/intrinsic_lut.rs b/tests/tests/renderscript/src/android/renderscript/cts/intrinsic_lut.rs
new file mode 100644
index 0000000..8852085
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/intrinsic_lut.rs
@@ -0,0 +1,32 @@
+/*
+ * 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"
+
+short red[256];
+short green[256];
+short blue[256];
+short alpha[256];
+
+uchar4 __attribute__((kernel)) root(uchar4 in) {
+    uchar4 tmp;
+    tmp.r = red[in.r];
+    tmp.g = green[in.g];
+    tmp.b = blue[in.b];
+    tmp.a = alpha[in.a];
+    return tmp;
+}
+
diff --git a/tests/src/android/renderscript/cts/is_object.rs b/tests/tests/renderscript/src/android/renderscript/cts/is_object.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/is_object.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/is_object.rs
diff --git a/tests/src/android/renderscript/cts/kernel_all.rs b/tests/tests/renderscript/src/android/renderscript/cts/kernel_all.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/kernel_all.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/kernel_all.rs
diff --git a/tests/src/android/renderscript/cts/large_global.rs b/tests/tests/renderscript/src/android/renderscript/cts/large_global.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/large_global.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/large_global.rs
diff --git a/tests/src/android/renderscript/cts/missing_link.rs b/tests/tests/renderscript/src/android/renderscript/cts/missing_link.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/missing_link.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/missing_link.rs
diff --git a/tests/src/android/renderscript/cts/negate.rs b/tests/tests/renderscript/src/android/renderscript/cts/negate.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/negate.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/negate.rs
diff --git a/tests/src/android/renderscript/cts/noroot.rs b/tests/tests/renderscript/src/android/renderscript/cts/noroot.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/noroot.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/noroot.rs
diff --git a/tests/src/android/renderscript/cts/oob.rs b/tests/tests/renderscript/src/android/renderscript/cts/oob.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/oob.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/oob.rs
diff --git a/tests/src/android/renderscript/cts/passthrough.rs b/tests/tests/renderscript/src/android/renderscript/cts/passthrough.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/passthrough.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/passthrough.rs
diff --git a/tests/src/android/renderscript/cts/primitives.rs b/tests/tests/renderscript/src/android/renderscript/cts/primitives.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/primitives.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/primitives.rs
diff --git a/tests/src/android/renderscript/cts/rs_frac_f32.rs b/tests/tests/renderscript/src/android/renderscript/cts/rs_frac_f32.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/rs_frac_f32.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/rs_frac_f32.rs
diff --git a/tests/src/android/renderscript/cts/rs_frac_f32_relaxed.rs b/tests/tests/renderscript/src/android/renderscript/cts/rs_frac_f32_relaxed.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/rs_frac_f32_relaxed.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/rs_frac_f32_relaxed.rs
diff --git a/tests/src/android/renderscript/cts/rs_pack_color_to_8888.rs b/tests/tests/renderscript/src/android/renderscript/cts/rs_pack_color_to_8888.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/rs_pack_color_to_8888.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/rs_pack_color_to_8888.rs
diff --git a/tests/src/android/renderscript/cts/rs_unpack_color_8888.rs b/tests/tests/renderscript/src/android/renderscript/cts/rs_unpack_color_8888.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/rs_unpack_color_8888.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/rs_unpack_color_8888.rs
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/sample.rs b/tests/tests/renderscript/src/android/renderscript/cts/sample.rs
new file mode 100644
index 0000000..64fb262
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/sample.rs
@@ -0,0 +1,170 @@
+#include "shared.rsh"
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+rs_sampler gNearest;
+rs_sampler gLinear;
+rs_sampler gMipNearest;
+rs_sampler gMipLinear;
+
+static uchar4 lod0Color = {255, 255, 0, 0};
+static uchar4 lod1Color = {255, 0, 255, 0};
+static uchar4 lod2Color = {0, 255, 255, 0};
+static uchar4 lod3Color = {255, 255, 255, 0};
+
+
+static bool compare(float4 expected, float4 value) {
+    float allowedDelta = 10.0f;
+    float4 diff = fabs(expected - value);
+    if (diff.x > allowedDelta || diff.y > allowedDelta ||
+        diff.z > allowedDelta || diff.w > allowedDelta) {
+        return false;
+    }
+    return true;
+}
+
+static bool sub_test_RGBA_1D(rs_allocation alloc1D, float location, float lod,
+                          float4 expected0, float4 expected1, float4 expected2, float4 expected3) {
+    bool failed = false;
+    float4 result = rsSample(alloc1D, gNearest, location, lod);
+    _RS_ASSERT(compare(expected0, result));
+
+    result = rsSample(alloc1D, gLinear, location, lod);
+    _RS_ASSERT(compare(expected1, result));
+
+    result = rsSample(alloc1D, gMipNearest, location, lod);
+    _RS_ASSERT(compare(expected2, result));
+
+    result = rsSample(alloc1D, gMipLinear, location, lod);
+    _RS_ASSERT(compare(expected3, result));
+    return !failed;
+}
+
+static bool sub_test_RGBA_2D(rs_allocation alloc2D, float2 location, float lod,
+                          float4 expected0, float4 expected1, float4 expected2, float4 expected3) {
+    bool failed = false;
+    float4 result = rsSample(alloc2D, gNearest, location, lod);
+    _RS_ASSERT(compare(expected0, result));
+
+    result = rsSample(alloc2D, gLinear, location, lod);
+    _RS_ASSERT(compare(expected1, result));
+
+    result = rsSample(alloc2D, gMipNearest, location, lod);
+    _RS_ASSERT(compare(expected2, result));
+
+    result = rsSample(alloc2D, gMipLinear, location, lod);
+    _RS_ASSERT(compare(expected3, result));
+    return !failed;
+}
+
+void test_RGBA(rs_allocation alloc1D, rs_allocation alloc2D) {
+    bool failed = false;
+    float4 result;
+
+    float4 fLOD0 = rsUnpackColor8888(lod0Color);
+    float4 fLOD1 = rsUnpackColor8888(lod1Color);
+    float4 fLOD2 = rsUnpackColor8888(lod2Color);
+    float4 fLOD3 = rsUnpackColor8888(lod3Color);
+
+    float4 fLOD04 = fLOD0*0.6f + fLOD1*0.4f;
+    float4 fLOD06 = fLOD0*0.4f + fLOD1*0.6f;
+
+    // Test for proper LOD sampling behaviour
+    uint32_t numSamples = 5;
+    for (uint32_t i = 0; i < numSamples; i ++) {
+        float location = (float)i/(float)(numSamples - 1);
+
+        // No lod specified, should be lod 0
+        result = rsSample(alloc1D, gNearest, location);
+        _RS_ASSERT(compare(fLOD0, result));
+
+        result = rsSample(alloc1D, gLinear, location);
+        _RS_ASSERT(compare(fLOD0, result));
+
+        result = rsSample(alloc1D, gMipNearest, location);
+        _RS_ASSERT(compare(fLOD0, result));
+
+        result = rsSample(alloc1D, gMipLinear, location);
+        _RS_ASSERT(compare(fLOD0, result));
+
+        // Mid lod test
+        float lod = 0.4f;
+        _RS_ASSERT(sub_test_RGBA_1D(alloc1D, location, lod, fLOD0, fLOD0, fLOD0, fLOD04));
+
+        lod = 0.6f;
+        _RS_ASSERT(sub_test_RGBA_1D(alloc1D, location, lod, fLOD0, fLOD0, fLOD1, fLOD06));
+
+        // Base lod sample
+        lod = 0.0f;
+        _RS_ASSERT(sub_test_RGBA_1D(alloc1D, location, lod, fLOD0, fLOD0, fLOD0, fLOD0));
+
+        // lod 1 test
+        lod = 1.0f;
+        _RS_ASSERT(sub_test_RGBA_1D(alloc1D, location, lod, fLOD0, fLOD0, fLOD1, fLOD1));
+
+        // lod 2 test
+        lod = 2.0f;
+        _RS_ASSERT(sub_test_RGBA_1D(alloc1D, location, lod, fLOD0, fLOD0, fLOD2, fLOD2));
+
+        // lod 3 test
+        lod = 3.0f;
+        _RS_ASSERT(sub_test_RGBA_1D(alloc1D, location, lod, fLOD0, fLOD0, fLOD3, fLOD3));
+
+        // lod 4 test, but only have 3 lods
+        lod = 4.0f;
+        _RS_ASSERT(sub_test_RGBA_1D(alloc1D, location, lod, fLOD0, fLOD0, fLOD3, fLOD3));
+
+        // 2D case
+        float2 f2Location;
+        f2Location.x = location;
+        f2Location.y = location;
+        // No lod specified, should be lod 0
+        result = rsSample(alloc2D, gNearest, f2Location);
+        _RS_ASSERT(compare(fLOD0, result));
+
+        result = rsSample(alloc2D, gLinear, f2Location);
+        _RS_ASSERT(compare(fLOD0, result));
+
+        result = rsSample(alloc2D, gMipNearest, f2Location);
+        _RS_ASSERT(compare(fLOD0, result));
+
+        result = rsSample(alloc2D, gMipLinear, f2Location);
+        _RS_ASSERT(compare(fLOD0, result));
+
+        // Mid lod test
+        lod = 0.4f;
+        _RS_ASSERT(sub_test_RGBA_2D(alloc2D, f2Location, lod, fLOD0, fLOD0, fLOD0, fLOD04));
+
+        lod = 0.6f;
+        _RS_ASSERT(sub_test_RGBA_2D(alloc2D, f2Location, lod, fLOD0, fLOD0, fLOD1, fLOD06));
+
+        // Base lod sample
+        lod = 0.0f;
+        _RS_ASSERT(sub_test_RGBA_2D(alloc2D, f2Location, lod, fLOD0, fLOD0, fLOD0, fLOD0));
+
+        // lod 1 test
+        lod = 1.0f;
+        _RS_ASSERT(sub_test_RGBA_2D(alloc2D, f2Location, lod, fLOD0, fLOD0, fLOD1, fLOD1));
+
+        // lod 2 test
+        lod = 2.0f;
+        _RS_ASSERT(sub_test_RGBA_2D(alloc2D, f2Location, lod, fLOD0, fLOD0, fLOD2, fLOD2));
+
+        // lod 2 test
+        lod = 3.0f;
+        _RS_ASSERT(sub_test_RGBA_2D(alloc2D, f2Location, lod, fLOD0, fLOD0, fLOD3, fLOD3));
+
+        // lod 4 test, but only have 3 lods
+        lod = 4.0f;
+        _RS_ASSERT(sub_test_RGBA_2D(alloc2D, f2Location, lod, fLOD0, fLOD0, fLOD3, fLOD3));
+    }
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tests/src/android/renderscript/cts/scriptgroup.rs b/tests/tests/renderscript/src/android/renderscript/cts/scriptgroup.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/scriptgroup.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/scriptgroup.rs
diff --git a/tests/src/android/renderscript/cts/sendToClientBlocking.rs b/tests/tests/renderscript/src/android/renderscript/cts/sendToClientBlocking.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/sendToClientBlocking.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/sendToClientBlocking.rs
diff --git a/tests/src/android/renderscript/cts/send_to_client.rs b/tests/tests/renderscript/src/android/renderscript/cts/send_to_client.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/send_to_client.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/send_to_client.rs
diff --git a/tests/src/android/renderscript/cts/send_to_client_1.rs b/tests/tests/renderscript/src/android/renderscript/cts/send_to_client_1.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/send_to_client_1.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/send_to_client_1.rs
diff --git a/tests/src/android/renderscript/cts/set_object.rs b/tests/tests/renderscript/src/android/renderscript/cts/set_object.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/set_object.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/set_object.rs
diff --git a/tests/src/android/renderscript/cts/setelementat.rs b/tests/tests/renderscript/src/android/renderscript/cts/setelementat.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/setelementat.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/setelementat.rs
diff --git a/tests/src/android/renderscript/cts/shared.rsh b/tests/tests/renderscript/src/android/renderscript/cts/shared.rsh
similarity index 100%
rename from tests/src/android/renderscript/cts/shared.rsh
rename to tests/tests/renderscript/src/android/renderscript/cts/shared.rsh
diff --git a/tests/src/android/renderscript/cts/struct_array.rs b/tests/tests/renderscript/src/android/renderscript/cts/struct_array.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/struct_array.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/struct_array.rs
diff --git a/tests/src/android/renderscript/cts/struct_object.rs b/tests/tests/renderscript/src/android/renderscript/cts/struct_object.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/struct_object.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/struct_object.rs
diff --git a/tests/src/android/renderscript/cts/struct_pad.rs b/tests/tests/renderscript/src/android/renderscript/cts/struct_pad.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/struct_pad.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/struct_pad.rs
diff --git a/tests/src/android/renderscript/cts/structs.rsh b/tests/tests/renderscript/src/android/renderscript/cts/structs.rsh
similarity index 100%
rename from tests/src/android/renderscript/cts/structs.rsh
rename to tests/tests/renderscript/src/android/renderscript/cts/structs.rsh
diff --git a/tests/src/android/renderscript/cts/utils.rs b/tests/tests/renderscript/src/android/renderscript/cts/utils.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/utils.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/utils.rs
diff --git a/tests/src/android/renderscript/cts/vector.rs b/tests/tests/renderscript/src/android/renderscript/cts/vector.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/vector.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/vector.rs
diff --git a/tests/src/android/renderscript/cts/verify.rs b/tests/tests/renderscript/src/android/renderscript/cts/verify.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/verify.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/verify.rs
diff --git a/tests/src/android/renderscript/cts/void_ptr.rs b/tests/tests/renderscript/src/android/renderscript/cts/void_ptr.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/void_ptr.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/void_ptr.rs
diff --git a/tests/src/android/renderscript/cts/yuv.rs b/tests/tests/renderscript/src/android/renderscript/cts/yuv.rs
similarity index 100%
rename from tests/src/android/renderscript/cts/yuv.rs
rename to tests/tests/renderscript/src/android/renderscript/cts/yuv.rs
diff --git a/tests/tests/renderscriptlegacy/Android.mk b/tests/tests/renderscriptlegacy/Android.mk
new file mode 100644
index 0000000..31d8ed9
--- /dev/null
+++ b/tests/tests/renderscriptlegacy/Android.mk
@@ -0,0 +1,33 @@
+# 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsRenderscriptLegacyTestCases
+
+# Don't include this package in any target.
+LOCAL_MODULE_TAGS := optional
+
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_SDK_VERSION := 19
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/renderscriptlegacy/AndroidManifest.xml b/tests/tests/renderscriptlegacy/AndroidManifest.xml
new file mode 100644
index 0000000..0c0498a
--- /dev/null
+++ b/tests/tests/renderscriptlegacy/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?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.
+-->
+
+<!-- Replace all the "example" stuff below with your package name, and
+     remove this comment.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.cts.renderscriptlegacy">
+
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <!-- This is a self-instrumenting test package. -->
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.renderscriptlegacy"
+                     android:label="CTS tests of Renderscript component">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
+
+</manifest>
+
diff --git a/tests/res/raw/leak.bc b/tests/tests/renderscriptlegacy/res/raw/leak.bc
similarity index 100%
rename from tests/res/raw/leak.bc
rename to tests/tests/renderscriptlegacy/res/raw/leak.bc
Binary files differ
diff --git a/tests/res/raw/set_target_api_11.bc b/tests/tests/renderscriptlegacy/res/raw/set_target_api_11.bc
similarity index 100%
rename from tests/res/raw/set_target_api_11.bc
rename to tests/tests/renderscriptlegacy/res/raw/set_target_api_11.bc
Binary files differ
diff --git a/tests/res/raw/set_target_api_12.bc b/tests/tests/renderscriptlegacy/res/raw/set_target_api_12.bc
similarity index 100%
rename from tests/res/raw/set_target_api_12.bc
rename to tests/tests/renderscriptlegacy/res/raw/set_target_api_12.bc
Binary files differ
diff --git a/tests/res/raw/set_target_api_13.bc b/tests/tests/renderscriptlegacy/res/raw/set_target_api_13.bc
similarity index 100%
rename from tests/res/raw/set_target_api_13.bc
rename to tests/tests/renderscriptlegacy/res/raw/set_target_api_13.bc
Binary files differ
diff --git a/tests/res/raw/set_target_api_14.bc b/tests/tests/renderscriptlegacy/res/raw/set_target_api_14.bc
similarity index 100%
rename from tests/res/raw/set_target_api_14.bc
rename to tests/tests/renderscriptlegacy/res/raw/set_target_api_14.bc
Binary files differ
diff --git a/tests/res/raw/set_target_api_15.bc b/tests/tests/renderscriptlegacy/res/raw/set_target_api_15.bc
similarity index 100%
rename from tests/res/raw/set_target_api_15.bc
rename to tests/tests/renderscriptlegacy/res/raw/set_target_api_15.bc
Binary files differ
diff --git a/tests/res/raw/set_target_api_16.bc b/tests/tests/renderscriptlegacy/res/raw/set_target_api_16.bc
similarity index 100%
rename from tests/res/raw/set_target_api_16.bc
rename to tests/tests/renderscriptlegacy/res/raw/set_target_api_16.bc
Binary files differ
diff --git a/tests/res/raw/set_target_api_17.bc b/tests/tests/renderscriptlegacy/res/raw/set_target_api_17.bc
similarity index 100%
rename from tests/res/raw/set_target_api_17.bc
rename to tests/tests/renderscriptlegacy/res/raw/set_target_api_17.bc
Binary files differ
diff --git a/tests/res/raw/set_target_api_18.bc b/tests/tests/renderscriptlegacy/res/raw/set_target_api_18.bc
similarity index 100%
rename from tests/res/raw/set_target_api_18.bc
rename to tests/tests/renderscriptlegacy/res/raw/set_target_api_18.bc
Binary files differ
diff --git a/tests/res/raw/set_target_api_19.bc b/tests/tests/renderscriptlegacy/res/raw/set_target_api_19.bc
similarity index 100%
rename from tests/res/raw/set_target_api_19.bc
rename to tests/tests/renderscriptlegacy/res/raw/set_target_api_19.bc
Binary files differ
diff --git a/tests/res/raw/set_target_api_too_high.bc b/tests/tests/renderscriptlegacy/res/raw/set_target_api_too_high.bc
similarity index 100%
rename from tests/res/raw/set_target_api_too_high.bc
rename to tests/tests/renderscriptlegacy/res/raw/set_target_api_too_high.bc
Binary files differ
diff --git a/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/LeakTest.java b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/LeakTest.java
new file mode 100644
index 0000000..d6a6637
--- /dev/null
+++ b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/LeakTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2012 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.renderscriptlegacy.cts;
+
+import android.app.ActivityManager;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Type;
+import android.util.Log;
+import android.content.Context;
+
+/*
+// -target-api 11
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+rs_allocation a;
+
+void print() {
+    rsDebug("unused", rsGetElementAt_int(a, 0, 0));
+}
+*/
+
+/**
+ * Test for memory leaks due to missing object slot information.
+ *
+ * The code to generate leak.bc is in the previous comment block.
+ * Note that you need to modify llvm-rs-cc to skip emitting the
+ * .rs.dtor() function, since it will also do the proper cleanup
+ * (but not trigger the original bug). Old HC code can trigger this
+ * bug, since it may have been compiled without .rs.dtor() support.
+ */
+public class LeakTest extends RSBaseCompute {
+    private static final String TAG = "LeakTest";
+
+    public void testForLeaks() {
+        ActivityManager am = (ActivityManager) getContext().getSystemService("activity");
+        int mc = am.getLargeMemoryClass() / 32;
+        if (mc < 1) {
+            mc = 1;
+        }
+        int x = mc * 1024 * 1024;
+
+        for (int i = 0; i < 100; i++) {
+            Log.w(TAG, "Leak test iteration " + i);
+            ScriptC_leak leak = new ScriptC_leak(mRS);
+            Type t = new Type.Builder(mRS, Element.I32(mRS)).setX(x).create();
+            Allocation A = Allocation.createTyped(mRS, t);
+            leak.set_a(A);
+            A = null;
+            //System.gc();
+            leak.destroy();
+            mRS.finish();
+        }
+        mRS.finish();
+        checkForErrors();
+    }
+}
diff --git a/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/RSBase.java b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/RSBase.java
new file mode 100644
index 0000000..f6a8ab8
--- /dev/null
+++ b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/RSBase.java
@@ -0,0 +1,91 @@
+/*
+ * 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.renderscriptlegacy.cts;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.RenderScript.RSErrorHandler;
+import android.renderscript.RenderScript.RSMessageHandler;
+import android.renderscript.RSRuntimeException;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+/**
+ * Base RenderScript test class. This class provides a message handler and a
+ * convenient way to wait for compute scripts to complete their execution.
+ */
+public class RSBase extends AndroidTestCase {
+
+    Context mCtx;
+    Resources mRes;
+
+    private int result;
+    private boolean msgHandled;
+
+    private static final int RS_MSG_TEST_PASSED = 100;
+    private static final int RS_MSG_TEST_FAILED = 101;
+
+    RSMessageHandler mRsMessage = new RSMessageHandler() {
+        public void run() {
+            if (result == 0) {
+                switch (mID) {
+                    case RS_MSG_TEST_PASSED:
+                    case RS_MSG_TEST_FAILED:
+                        result = mID;
+                        break;
+                    default:
+                        fail("Got unexpected RS message");
+                        return;
+                }
+            }
+            msgHandled = true;
+        }
+    };
+
+    protected void waitForMessage() {
+        while (!msgHandled) {
+            Thread.yield();
+        }
+    }
+
+    protected boolean FoundError = false;
+    protected RSErrorHandler mRsError = new RSErrorHandler() {
+        public void run() {
+            FoundError = true;
+            Log.e("RenderscriptCTS", mErrorMessage);
+            throw new RSRuntimeException("Received error " + mErrorNum +
+                                         " message " + mErrorMessage);
+        }
+    };
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        result = 0;
+        msgHandled = false;
+        mCtx = getContext();
+        mRes = mCtx.getResources();
+    }
+
+    /**
+     * Verify that we didn't fail on the control or script side of things.
+     */
+    protected void checkForErrors() {
+        assertFalse(FoundError);
+        assertTrue(result != RS_MSG_TEST_FAILED);
+    }
+}
diff --git a/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/RSBaseCompute.java b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/RSBaseCompute.java
new file mode 100644
index 0000000..ac3be8a
--- /dev/null
+++ b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/RSBaseCompute.java
@@ -0,0 +1,47 @@
+/*
+ * 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.renderscriptlegacy.cts;
+
+import android.renderscript.RenderScript;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RSRuntimeException;
+import android.util.Log;
+
+/**
+ * Base RenderScript test class. This class provides a message handler and a
+ * convenient way to wait for compute scripts to complete their execution.
+ */
+public class RSBaseCompute extends RSBase {
+    RenderScript mRS;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mRS = RenderScript.create(mCtx);
+        mRS.setMessageHandler(mRsMessage);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mRS != null) {
+            mRS.destroy();
+            mRS = null;
+        }
+        super.tearDown();
+    }
+}
diff --git a/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/RSUtils.java b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/RSUtils.java
new file mode 100644
index 0000000..130ef94
--- /dev/null
+++ b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/RSUtils.java
@@ -0,0 +1,223 @@
+/*
+ * 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.renderscriptlegacy.cts;
+
+import android.content.res.Resources;
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+
+import java.util.Random;
+
+/**
+ * This class supplies some utils for renderscript tests
+ */
+public class RSUtils {
+    private static final double[] sInterestingDoubles = {
+        0.0,
+        1.0,
+        Math.E,
+        Math.PI,
+        Math.PI / 2.0,
+        Math.PI * 2.0,
+        -0.0,
+        -1.0,
+        -Math.E,
+        -Math.PI,
+        -Math.PI / 2.0,
+        -Math.PI * 2.0,
+    };
+
+    /**
+     * Fills the array with random doubles.  Values will be between min (inclusive) and
+     * max (inclusive).
+     */
+    public static void genRandomDoubles(long seed, double min, double max, double array[],
+            boolean includeExtremes) {
+        Random r = new Random(seed);
+        int minExponent = Math.min(Math.getExponent(min), 0);
+        int maxExponent = Math.max(Math.getExponent(max), 0);
+        if (minExponent < -6 || maxExponent > 6) {
+            // Use an exponential distribution
+            int exponentDiff = maxExponent - minExponent;
+            for (int i = 0; i < array.length; i++) {
+                double mantissa = r.nextDouble();
+                int exponent = minExponent + r.nextInt(maxExponent - minExponent);
+                int sign = (min >= 0) ? 1 : 1 - r.nextInt(2) * 2;  // -1 or 1
+                double rand = sign * mantissa * Math.pow(2.0, exponent);
+                if (rand < min || rand > max) {
+                    continue;
+                }
+                array[i] = rand;
+            }
+        } else {
+            // Use a linear distribution
+            for (int i = 0; i < array.length; i++) {
+                double rand = r.nextDouble();
+                array[i] = min + rand * (max - min);
+            }
+        }
+        // Seed a few special numbers we want to be sure to test.
+        for (int i = 0; i < sInterestingDoubles.length; i++) {
+            double d = sInterestingDoubles[i];
+            if (min <= d && d <= max) {
+                array[r.nextInt(array.length)] = d;
+            }
+        }
+        array[r.nextInt(array.length)] = min;
+        array[r.nextInt(array.length)] = max;
+        if (includeExtremes) {
+            array[r.nextInt(array.length)] = Double.NaN;
+            array[r.nextInt(array.length)] = Double.POSITIVE_INFINITY;
+            array[r.nextInt(array.length)] = Double.NEGATIVE_INFINITY;
+            array[r.nextInt(array.length)] = Double.MIN_VALUE;
+            array[r.nextInt(array.length)] = Double.MIN_NORMAL;
+            array[r.nextInt(array.length)] = Double.MAX_VALUE;
+            array[r.nextInt(array.length)] = -Double.MIN_VALUE;
+            array[r.nextInt(array.length)] = -Double.MIN_NORMAL;
+            array[r.nextInt(array.length)] = -Double.MAX_VALUE;
+        }
+    }
+
+    /**
+     * Fills the array with random floats.  Values will be between min (inclusive) and
+     * max (inclusive).
+     */
+    public static void genRandomFloats(long seed, float min, float max, float array[],
+            boolean includeExtremes) {
+        Random r = new Random(seed);
+        int minExponent = Math.min(Math.getExponent(min), 0);
+        int maxExponent = Math.max(Math.getExponent(max), 0);
+        if (minExponent < -6 || maxExponent > 6) {
+            // Use an exponential distribution
+            int exponentDiff = maxExponent - minExponent;
+            for (int i = 0; i < array.length; i++) {
+                float mantissa = r.nextFloat();
+                int exponent = minExponent + r.nextInt(maxExponent - minExponent);
+                int sign = (min >= 0) ? 1 : 1 - r.nextInt(2) * 2;  // -1 or 1
+                float rand = sign * mantissa * (float) Math.pow(2.0, exponent);
+                if (rand < min || rand > max) {
+                    continue;
+                }
+                array[i] = rand;
+            }
+        } else {
+            // Use a linear distribution
+            for (int i = 0; i < array.length; i++) {
+                float rand = r.nextFloat();
+                array[i] = min + rand * (max - min);
+            }
+        }
+        // Seed a few special numbers we want to be sure to test.
+        for (int i = 0; i < sInterestingDoubles.length; i++) {
+            float f = (float) sInterestingDoubles[i];
+            if (min <= f && f <= max) {
+                array[r.nextInt(array.length)] = f;
+            }
+        }
+        array[r.nextInt(array.length)] = min;
+        array[r.nextInt(array.length)] = max;
+        if (includeExtremes) {
+            array[r.nextInt(array.length)] = Float.NaN;
+            array[r.nextInt(array.length)] = Float.POSITIVE_INFINITY;
+            array[r.nextInt(array.length)] = Float.NEGATIVE_INFINITY;
+            array[r.nextInt(array.length)] = Float.MIN_VALUE;
+            array[r.nextInt(array.length)] = Float.MIN_NORMAL;
+            array[r.nextInt(array.length)] = Float.MAX_VALUE;
+            array[r.nextInt(array.length)] = -Float.MIN_VALUE;
+            array[r.nextInt(array.length)] = -Float.MIN_NORMAL;
+            array[r.nextInt(array.length)] = -Float.MAX_VALUE;
+        }
+    }
+
+    /**
+     * Fills the array with random ints.  Values will be between min (inclusive) and
+     * max (inclusive).
+     */
+    public static void genRandomInts(long seed, int min, int max, int array[]) {
+        Random r = new Random(seed);
+        for (int i = 0; i < array.length; i++) {
+            long range = max - min + 1;
+            array[i] = (int) (min + r.nextLong() % range);
+        }
+        array[r.nextInt(array.length)] = min;
+        array[r.nextInt(array.length)] = max;
+    }
+
+    /**
+     * Fills the array with random longs.  If signed is true, negative values can be generated.
+     * The values will fit within 'numberOfBits'.  This is useful for conversion tests.
+     */
+    public static void genRandomLongs(long seed, long array[], boolean signed, int numberOfBits) {
+      long positiveMask = numberOfBits == 64 ? -1 : ((1l << numberOfBits) - 1);
+      long negativeMask = ~positiveMask;
+      Random r = new Random(seed);
+      for (int i = 0; i < array.length; i++) {
+          long l = r.nextLong();
+          if (signed && l < 0) {
+              l = l | negativeMask;
+          } else {
+              l = l & positiveMask;
+          }
+          array[i] = l;
+      }
+      // Seed a few special numbers we want to be sure to test.
+      array[r.nextInt(array.length)] = 0l;
+      array[r.nextInt(array.length)] = 1l;
+      array[r.nextInt(array.length)] = positiveMask;
+      if (signed) {
+          array[r.nextInt(array.length)] = negativeMask;
+          array[r.nextInt(array.length)] = -1;
+      }
+    }
+
+    public static void genRandomInts(long seed, int array[], boolean signed, int numberOfBits) {
+        long[] longs = new long[array.length];
+        genRandomLongs(seed, longs, signed, numberOfBits);
+        for (int i = 0; i < array.length; i++) {
+            array[i] = (int) longs[i];
+        }
+    }
+
+    public static void genRandomShorts(long seed, short array[], boolean signed, int numberOfBits) {
+        long[] longs = new long[array.length];
+        genRandomLongs(seed, longs, signed, numberOfBits);
+        for (int i = 0; i < array.length; i++) {
+            array[i] = (short) longs[i];
+        }
+    }
+
+    public static void genRandomBytes(long seed, byte array[], boolean signed, int numberOfBits) {
+        long[] longs = new long[array.length];
+        genRandomLongs(seed, longs, signed, numberOfBits);
+        for (int i = 0; i < array.length; i++) {
+            array[i] = (byte) longs[i];
+        }
+    }
+
+    // Compares two unsigned long.  Returns < 0 if a < b, 0 if a == b, > 0 if a > b.
+    public static long compareUnsignedLong(long a, long b) {
+        long aFirstFourBits = a >>> 60;
+        long bFirstFourBits = b >>> 60;
+        long firstFourBitsDiff = aFirstFourBits - bFirstFourBits;
+        if (firstFourBitsDiff != 0) {
+            return firstFourBitsDiff;
+        }
+        long aRest = a & 0x0fffffffffffffffl;
+        long bRest = b & 0x0fffffffffffffffl;
+        return aRest - bRest;
+    }
+}
diff --git a/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_leak.java b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_leak.java
new file mode 100644
index 0000000..7d6aa8b
--- /dev/null
+++ b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_leak.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2011-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file is auto-generated. DO NOT MODIFY!
+ * The source Renderscript file: leak.rs
+ */
+package android.renderscriptlegacy.cts;
+
+import android.renderscript.*;
+import android.content.res.Resources;
+
+/**
+ * @hide
+ */
+public class ScriptC_leak extends ScriptC {
+    private static final String __rs_resource_name = "leak";
+    // Constructor
+    public  ScriptC_leak(RenderScript rs) {
+        this(rs,
+             rs.getApplicationContext().getResources(),
+             rs.getApplicationContext().getResources().getIdentifier(
+                 __rs_resource_name, "raw",
+                 rs.getApplicationContext().getPackageName()));
+    }
+
+    public  ScriptC_leak(RenderScript rs, Resources resources, int id) {
+        super(rs, resources, id);
+    }
+
+    private FieldPacker __rs_fp_ALLOCATION;
+    private final static int mExportVarIdx_a = 0;
+    private Allocation mExportVar_a;
+    public synchronized void set_a(Allocation v) {
+        setVar(mExportVarIdx_a, v);
+        mExportVar_a = v;
+    }
+
+    public Allocation get_a() {
+        return mExportVar_a;
+    }
+
+    private final static int mExportFuncIdx_print = 0;
+    public void invoke_print() {
+        invoke(mExportFuncIdx_print);
+    }
+
+}
+
diff --git a/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_11.java b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_11.java
new file mode 100644
index 0000000..eafc858
--- /dev/null
+++ b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_11.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011-2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file is auto-generated. DO NOT MODIFY!
+ * The source Renderscript file: set_target_api_11.rs
+ */
+package android.renderscriptlegacy.cts;
+
+import android.renderscript.*;
+import android.content.res.Resources;
+
+/**
+ * @hide
+ */
+public class ScriptC_set_target_api_11 extends ScriptC {
+    private static final String __rs_resource_name = "set_target_api_11";
+    // Constructor
+    public  ScriptC_set_target_api_11(RenderScript rs) {
+        this(rs,
+             rs.getApplicationContext().getResources(),
+             rs.getApplicationContext().getResources().getIdentifier(
+                 __rs_resource_name, "raw",
+                 rs.getApplicationContext().getPackageName()));
+    }
+
+    public  ScriptC_set_target_api_11(RenderScript rs, Resources resources, int id) {
+        super(rs, resources, id);
+    }
+
+    private final static int mExportFuncIdx_check = 0;
+    public void invoke_check(int version) {
+        FieldPacker check_fp = new FieldPacker(4);
+        check_fp.addI32(version);
+        invoke(mExportFuncIdx_check, check_fp);
+    }
+
+}
+
diff --git a/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_12.java b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_12.java
new file mode 100644
index 0000000..83db0ab
--- /dev/null
+++ b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_12.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011-2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file is auto-generated. DO NOT MODIFY!
+ * The source Renderscript file: set_target_api_12.rs
+ */
+package android.renderscriptlegacy.cts;
+
+import android.renderscript.*;
+import android.content.res.Resources;
+
+/**
+ * @hide
+ */
+public class ScriptC_set_target_api_12 extends ScriptC {
+    private static final String __rs_resource_name = "set_target_api_12";
+    // Constructor
+    public  ScriptC_set_target_api_12(RenderScript rs) {
+        this(rs,
+             rs.getApplicationContext().getResources(),
+             rs.getApplicationContext().getResources().getIdentifier(
+                 __rs_resource_name, "raw",
+                 rs.getApplicationContext().getPackageName()));
+    }
+
+    public  ScriptC_set_target_api_12(RenderScript rs, Resources resources, int id) {
+        super(rs, resources, id);
+    }
+
+    private final static int mExportFuncIdx_check = 0;
+    public void invoke_check(int version) {
+        FieldPacker check_fp = new FieldPacker(4);
+        check_fp.addI32(version);
+        invoke(mExportFuncIdx_check, check_fp);
+    }
+
+}
+
diff --git a/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_13.java b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_13.java
new file mode 100644
index 0000000..a62cb1a
--- /dev/null
+++ b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_13.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011-2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file is auto-generated. DO NOT MODIFY!
+ * The source Renderscript file: set_target_api_13.rs
+ */
+package android.renderscriptlegacy.cts;
+
+import android.renderscript.*;
+import android.content.res.Resources;
+
+/**
+ * @hide
+ */
+public class ScriptC_set_target_api_13 extends ScriptC {
+    private static final String __rs_resource_name = "set_target_api_13";
+    // Constructor
+    public  ScriptC_set_target_api_13(RenderScript rs) {
+        this(rs,
+             rs.getApplicationContext().getResources(),
+             rs.getApplicationContext().getResources().getIdentifier(
+                 __rs_resource_name, "raw",
+                 rs.getApplicationContext().getPackageName()));
+    }
+
+    public  ScriptC_set_target_api_13(RenderScript rs, Resources resources, int id) {
+        super(rs, resources, id);
+    }
+
+    private final static int mExportFuncIdx_check = 0;
+    public void invoke_check(int version) {
+        FieldPacker check_fp = new FieldPacker(4);
+        check_fp.addI32(version);
+        invoke(mExportFuncIdx_check, check_fp);
+    }
+
+}
+
diff --git a/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_14.java b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_14.java
new file mode 100644
index 0000000..ab5abab
--- /dev/null
+++ b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_14.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011-2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file is auto-generated. DO NOT MODIFY!
+ * The source Renderscript file: set_target_api_14.rs
+ */
+package android.renderscriptlegacy.cts;
+
+import android.renderscript.*;
+import android.content.res.Resources;
+
+/**
+ * @hide
+ */
+public class ScriptC_set_target_api_14 extends ScriptC {
+    private static final String __rs_resource_name = "set_target_api_14";
+    // Constructor
+    public  ScriptC_set_target_api_14(RenderScript rs) {
+        this(rs,
+             rs.getApplicationContext().getResources(),
+             rs.getApplicationContext().getResources().getIdentifier(
+                 __rs_resource_name, "raw",
+                 rs.getApplicationContext().getPackageName()));
+    }
+
+    public  ScriptC_set_target_api_14(RenderScript rs, Resources resources, int id) {
+        super(rs, resources, id);
+    }
+
+    private final static int mExportFuncIdx_check = 0;
+    public void invoke_check(int version) {
+        FieldPacker check_fp = new FieldPacker(4);
+        check_fp.addI32(version);
+        invoke(mExportFuncIdx_check, check_fp);
+    }
+
+}
+
diff --git a/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_15.java b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_15.java
new file mode 100644
index 0000000..97a347f
--- /dev/null
+++ b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_15.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011-2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file is auto-generated. DO NOT MODIFY!
+ * The source Renderscript file: set_target_api_15.rs
+ */
+package android.renderscriptlegacy.cts;
+
+import android.renderscript.*;
+import android.content.res.Resources;
+
+/**
+ * @hide
+ */
+public class ScriptC_set_target_api_15 extends ScriptC {
+    private static final String __rs_resource_name = "set_target_api_15";
+    // Constructor
+    public  ScriptC_set_target_api_15(RenderScript rs) {
+        this(rs,
+             rs.getApplicationContext().getResources(),
+             rs.getApplicationContext().getResources().getIdentifier(
+                 __rs_resource_name, "raw",
+                 rs.getApplicationContext().getPackageName()));
+    }
+
+    public  ScriptC_set_target_api_15(RenderScript rs, Resources resources, int id) {
+        super(rs, resources, id);
+    }
+
+    private final static int mExportFuncIdx_check = 0;
+    public void invoke_check(int version) {
+        FieldPacker check_fp = new FieldPacker(4);
+        check_fp.addI32(version);
+        invoke(mExportFuncIdx_check, check_fp);
+    }
+
+}
+
diff --git a/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_16.java b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_16.java
new file mode 100644
index 0000000..d8f8a2f
--- /dev/null
+++ b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_16.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011-2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file is auto-generated. DO NOT MODIFY!
+ * The source Renderscript file: set_target_api_16.rs
+ */
+package android.renderscriptlegacy.cts;
+
+import android.renderscript.*;
+import android.content.res.Resources;
+
+/**
+ * @hide
+ */
+public class ScriptC_set_target_api_16 extends ScriptC {
+    private static final String __rs_resource_name = "set_target_api_16";
+    // Constructor
+    public  ScriptC_set_target_api_16(RenderScript rs) {
+        this(rs,
+             rs.getApplicationContext().getResources(),
+             rs.getApplicationContext().getResources().getIdentifier(
+                 __rs_resource_name, "raw",
+                 rs.getApplicationContext().getPackageName()));
+    }
+
+    public  ScriptC_set_target_api_16(RenderScript rs, Resources resources, int id) {
+        super(rs, resources, id);
+    }
+
+    private final static int mExportFuncIdx_check = 0;
+    public void invoke_check(int version) {
+        FieldPacker check_fp = new FieldPacker(4);
+        check_fp.addI32(version);
+        invoke(mExportFuncIdx_check, check_fp);
+    }
+
+}
+
diff --git a/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_17.java b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_17.java
new file mode 100644
index 0000000..90b4109
--- /dev/null
+++ b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_17.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011-2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file is auto-generated. DO NOT MODIFY!
+ * The source Renderscript file: set_target_api_17.rs
+ */
+package android.renderscriptlegacy.cts;
+
+import android.renderscript.*;
+import android.content.res.Resources;
+
+/**
+ * @hide
+ */
+public class ScriptC_set_target_api_17 extends ScriptC {
+    private static final String __rs_resource_name = "set_target_api_17";
+    // Constructor
+    public  ScriptC_set_target_api_17(RenderScript rs) {
+        this(rs,
+             rs.getApplicationContext().getResources(),
+             rs.getApplicationContext().getResources().getIdentifier(
+                 __rs_resource_name, "raw",
+                 rs.getApplicationContext().getPackageName()));
+    }
+
+    public  ScriptC_set_target_api_17(RenderScript rs, Resources resources, int id) {
+        super(rs, resources, id);
+    }
+
+    private final static int mExportFuncIdx_check = 0;
+    public void invoke_check(int version) {
+        FieldPacker check_fp = new FieldPacker(4);
+        check_fp.addI32(version);
+        invoke(mExportFuncIdx_check, check_fp);
+    }
+
+}
+
diff --git a/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_18.java b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_18.java
new file mode 100644
index 0000000..eb6c04d
--- /dev/null
+++ b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_18.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011-2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file is auto-generated. DO NOT MODIFY!
+ * The source Renderscript file: set_target_api_18.rs
+ */
+package android.renderscriptlegacy.cts;
+
+import android.renderscript.*;
+import android.content.res.Resources;
+
+/**
+ * @hide
+ */
+public class ScriptC_set_target_api_18 extends ScriptC {
+    private static final String __rs_resource_name = "set_target_api_18";
+    // Constructor
+    public  ScriptC_set_target_api_18(RenderScript rs) {
+        this(rs,
+             rs.getApplicationContext().getResources(),
+             rs.getApplicationContext().getResources().getIdentifier(
+                 __rs_resource_name, "raw",
+                 rs.getApplicationContext().getPackageName()));
+    }
+
+    public  ScriptC_set_target_api_18(RenderScript rs, Resources resources, int id) {
+        super(rs, resources, id);
+    }
+
+    private final static int mExportFuncIdx_check = 0;
+    public void invoke_check(int version) {
+        FieldPacker check_fp = new FieldPacker(4);
+        check_fp.addI32(version);
+        invoke(mExportFuncIdx_check, check_fp);
+    }
+
+}
+
diff --git a/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_19.java b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_19.java
new file mode 100644
index 0000000..530930e
--- /dev/null
+++ b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_19.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011-2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file is auto-generated. DO NOT MODIFY!
+ * The source Renderscript file: set_target_api_19.rs
+ */
+package android.renderscriptlegacy.cts;
+
+import android.renderscript.*;
+import android.content.res.Resources;
+
+/**
+ * @hide
+ */
+public class ScriptC_set_target_api_19 extends ScriptC {
+    private static final String __rs_resource_name = "set_target_api_19";
+    // Constructor
+    public  ScriptC_set_target_api_19(RenderScript rs) {
+        this(rs,
+             rs.getApplicationContext().getResources(),
+             rs.getApplicationContext().getResources().getIdentifier(
+                 __rs_resource_name, "raw",
+                 rs.getApplicationContext().getPackageName()));
+    }
+
+    public  ScriptC_set_target_api_19(RenderScript rs, Resources resources, int id) {
+        super(rs, resources, id);
+    }
+
+    private final static int mExportFuncIdx_check = 0;
+    public void invoke_check(int version) {
+        FieldPacker check_fp = new FieldPacker(4);
+        check_fp.addI32(version);
+        invoke(mExportFuncIdx_check, check_fp);
+    }
+
+}
+
diff --git a/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_too_high.java b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_too_high.java
new file mode 100644
index 0000000..84f02ec
--- /dev/null
+++ b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/ScriptC_set_target_api_too_high.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011-2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file is auto-generated. DO NOT MODIFY!
+ * The source Renderscript file: set_target_api_16.rs
+ */
+package android.renderscriptlegacy.cts;
+
+import android.renderscript.*;
+import android.content.res.Resources;
+
+/**
+ * @hide
+ */
+public class ScriptC_set_target_api_too_high extends ScriptC {
+    private static final String __rs_resource_name = "set_target_api_too_high";
+    // Constructor
+    public  ScriptC_set_target_api_too_high(RenderScript rs) {
+        this(rs,
+             rs.getApplicationContext().getResources(),
+             rs.getApplicationContext().getResources().getIdentifier(
+                 __rs_resource_name, "raw",
+                 rs.getApplicationContext().getPackageName()));
+    }
+
+    public  ScriptC_set_target_api_too_high(RenderScript rs, Resources resources, int id) {
+        super(rs, resources, id);
+    }
+
+    private final static int mExportFuncIdx_check = 0;
+    public void invoke_check(int version) {
+        FieldPacker check_fp = new FieldPacker(4);
+        check_fp.addI32(version);
+        invoke(mExportFuncIdx_check, check_fp);
+    }
+
+}
+
diff --git a/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/VersionTest.java b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/VersionTest.java
new file mode 100644
index 0000000..c33edbc
--- /dev/null
+++ b/tests/tests/renderscriptlegacy/src/android/renderscriptlegacy/cts/VersionTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2012 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.renderscriptlegacy.cts;
+
+import android.renderscript.RenderScript.RSMessageHandler;
+import android.renderscript.RSRuntimeException;
+
+/**
+ * Test for appropriate handling of versioned bitcode.
+ */
+public class VersionTest extends RSBaseCompute {
+    public void testVersion11() {
+        ScriptC_set_target_api_11 test11 = new ScriptC_set_target_api_11(mRS);
+        test11.invoke_check(11);
+        waitForMessage();
+        checkForErrors();
+    }
+
+    public void testVersion12() {
+        ScriptC_set_target_api_12 test12 = new ScriptC_set_target_api_12(mRS);
+        test12.invoke_check(12);
+        waitForMessage();
+        checkForErrors();
+    }
+
+    public void testVersion13() {
+        ScriptC_set_target_api_13 test13 = new ScriptC_set_target_api_13(mRS);
+        test13.invoke_check(13);
+        waitForMessage();
+        checkForErrors();
+    }
+
+    public void testVersion14() {
+        ScriptC_set_target_api_14 test14 = new ScriptC_set_target_api_14(mRS);
+        test14.invoke_check(14);
+        waitForMessage();
+        checkForErrors();
+    }
+
+    public void testVersion15() {
+        ScriptC_set_target_api_15 test15 = new ScriptC_set_target_api_15(mRS);
+        test15.invoke_check(15);
+        waitForMessage();
+        checkForErrors();
+    }
+
+    public void testVersion16() {
+        ScriptC_set_target_api_16 test16 = new ScriptC_set_target_api_16(mRS);
+        test16.invoke_check(16);
+        waitForMessage();
+        checkForErrors();
+    }
+
+    public void testVersion17() {
+        ScriptC_set_target_api_17 test17 = new ScriptC_set_target_api_17(mRS);
+        test17.invoke_check(17);
+        waitForMessage();
+        checkForErrors();
+    }
+
+    public void testVersion18() {
+        ScriptC_set_target_api_18 test18 = new ScriptC_set_target_api_18(mRS);
+        test18.invoke_check(18);
+        waitForMessage();
+        checkForErrors();
+    }
+
+    public void testVersion19() {
+        ScriptC_set_target_api_19 test19 = new ScriptC_set_target_api_19(mRS);
+        test19.invoke_check(19);
+        waitForMessage();
+        checkForErrors();
+    }
+
+    public void testVersion_too_high() {
+        try {
+            ScriptC_set_target_api_too_high test_too_high =
+                    new ScriptC_set_target_api_too_high(mRS);
+            fail("should throw RSRuntimeException");
+        } catch (RSRuntimeException e) {
+        }
+        checkForErrors();
+    }
+}
diff --git a/tests/tests/rscpp/Android.mk b/tests/tests/rscpp/Android.mk
index 6f01cab..0eb32b5 100644
--- a/tests/tests/rscpp/Android.mk
+++ b/tests/tests/rscpp/Android.mk
@@ -22,18 +22,16 @@
 # Don't include this package in any target.
 LOCAL_MODULE_TAGS := optional
 
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
 # When built, explicitly put it in the data partition.
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-# All tests should include android.test.runner.
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 LOCAL_JNI_SHARED_LIBRARIES := librscpptest_jni
 
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_INSTRUMENTATION_FOR := CtsTestStubs
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
 LOCAL_SDK_VERSION := current
 
diff --git a/tests/tests/rscpp/AndroidManifest.xml b/tests/tests/rscpp/AndroidManifest.xml
index b3ab43a..b68ebc3 100644
--- a/tests/tests/rscpp/AndroidManifest.xml
+++ b/tests/tests/rscpp/AndroidManifest.xml
@@ -23,9 +23,12 @@
     </application>
 
     <!-- This is a self-instrumenting test package. -->
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="com.android.cts.stub"
-                     android:label="CTS tests of RenderScript C++ component"/>
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.rscpp"
+                     android:label="CTS tests of RenderScript C++ component">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/tests/rscpp/librscpptest/rs_jni.cpp b/tests/tests/rscpp/librscpptest/rs_jni.cpp
index 92ebd56..f5946f5 100644
--- a/tests/tests/rscpp/librscpptest/rs_jni.cpp
+++ b/tests/tests/rscpp/librscpptest/rs_jni.cpp
@@ -29,6 +29,28 @@
 
 using namespace android::RSC;
 
+/*returns an addr aligned to the byte boundary specified by align*/
+#define align_addr(addr,align) (void *)(((size_t)(addr) + ((align) - 1)) & (size_t) - (align))
+#define ADDRESS_STORAGE_SIZE sizeof(size_t)
+
+void * aligned_alloc(size_t align, size_t size) {
+    void * addr, * x = NULL;
+    addr = malloc(size + align - 1 + ADDRESS_STORAGE_SIZE);
+    if (addr) {
+        x = align_addr((unsigned char *) addr + ADDRESS_STORAGE_SIZE, (int) align);
+        /* save the actual malloc address */
+        ((size_t *) x)[-1] = (size_t) addr;
+    }
+    return x;
+}
+
+void aligned_free(void * memblk) {
+    if (memblk) {
+        void * addr = (void *) (((size_t *) memblk)[-1]);
+        free(addr);
+    }
+}
+
 extern "C" JNIEXPORT jboolean JNICALL Java_android_cts_rscpp_RSInitTest_initTest(JNIEnv * env,
                                                                                  jclass obj,
                                                                                  jstring pathObj)
@@ -349,3 +371,4 @@
 
 }
 
+
diff --git a/tests/tests/rscpp/librscpptest/setelementat.rs b/tests/tests/rscpp/librscpptest/setelementat.rs
index 1251ec1..5a84552 100644
--- a/tests/tests/rscpp/librscpptest/setelementat.rs
+++ b/tests/tests/rscpp/librscpptest/setelementat.rs
@@ -1,5 +1,5 @@
 #pragma version(1)
-#pragma rs java_package_name(com.android.cts.stub)
+#pragma rs java_package_name(com.android.cts.rscpp)
 #pragma rs_fp_relaxed
 
 int memset_toValue = 0;
diff --git a/tests/tests/rscpp/src/android/cts/rscpp/RS3DLUTTest.java b/tests/tests/rscpp/src/android/cts/rscpp/RS3DLUTTest.java
index 7a85f57..f278835 100644
--- a/tests/tests/rscpp/src/android/cts/rscpp/RS3DLUTTest.java
+++ b/tests/tests/rscpp/src/android/cts/rscpp/RS3DLUTTest.java
@@ -16,8 +16,6 @@
 
 package android.cts.rscpp;
 
-import com.android.cts.stub.R;
-
 import android.content.Context;
 import android.content.res.Resources;
 import android.test.AndroidTestCase;
@@ -41,7 +39,6 @@
         RSUtils.genRandom(0x419144, 255, 1, -128, baseAlloc);
         int[] colorCube = new int[lutSize * lutSize * lutSize * 4];
         RSUtils.genRandom(0x555007, 255, 1, -128, colorCube);
-        RenderScript mRS = RenderScript.create(getContext());
         byte[] byteAlloc = new byte[X * Y * 4];
         byte[] byteColorCube = new byte[lutSize * lutSize * lutSize * 4];
         for (int i = 0; i < X * Y * 4; i++) {
@@ -51,7 +48,6 @@
             byteColorCube[i] = (byte)colorCube[i];
         }
 
-
         Type.Builder build = new Type.Builder(mRS, Element.RGBA_8888(mRS));
         build.setX(X);
         build.setY(Y);
@@ -60,10 +56,10 @@
         rsInput.copyFromUnchecked(byteAlloc);
 
         Type.Builder buildCube = new Type.Builder(mRS, Element.RGBA_8888(mRS));
-        build.setX(lutSize);
-        build.setY(lutSize);
-        build.setZ(lutSize);
-        Allocation cube = Allocation.createTyped(mRS, build.create());
+        buildCube.setX(lutSize);
+        buildCube.setY(lutSize);
+        buildCube.setZ(lutSize);
+        Allocation cube = Allocation.createTyped(mRS, buildCube.create());
         cube.copyFromUnchecked(byteColorCube);
         ScriptIntrinsic3DLUT lut = ScriptIntrinsic3DLUT.create(mRS, Element.RGBA_8888(mRS));
 
@@ -72,12 +68,12 @@
 
         byte[] nativeByteAlloc = new byte[X * Y * 4];
         lutTest(this.getContext().getCacheDir().toString(), X, Y, lutSize, byteAlloc, byteColorCube, nativeByteAlloc);
-        rsOutput.copyTo(byteAlloc);
 
-        for (int i = 0; i < X * Y * 4; i++) {
-            assertTrue(byteAlloc[i] == nativeByteAlloc[i]);
-        }
+        Allocation rsCppOutput = Allocation.createTyped(mRS, build.create());
+        rsCppOutput.copyFromUnchecked(nativeByteAlloc);
+        mVerify.invoke_verify(rsOutput, rsCppOutput, rsInput);
+        checkForErrors();
 
     }
 
-}
\ No newline at end of file
+}
diff --git a/tests/tests/rscpp/src/android/cts/rscpp/RSAllocationTest.java b/tests/tests/rscpp/src/android/cts/rscpp/RSAllocationTest.java
index 86662bf..76dbfee 100644
--- a/tests/tests/rscpp/src/android/cts/rscpp/RSAllocationTest.java
+++ b/tests/tests/rscpp/src/android/cts/rscpp/RSAllocationTest.java
@@ -16,8 +16,6 @@
 
 package android.cts.rscpp;
 
-import com.android.cts.stub.R;
-
 import android.content.Context;
 import android.content.res.Resources;
 import android.test.AndroidTestCase;
diff --git a/tests/tests/rscpp/src/android/cts/rscpp/RSBlendTest.java b/tests/tests/rscpp/src/android/cts/rscpp/RSBlendTest.java
index 0830f78..1c6dc51 100644
--- a/tests/tests/rscpp/src/android/cts/rscpp/RSBlendTest.java
+++ b/tests/tests/rscpp/src/android/cts/rscpp/RSBlendTest.java
@@ -16,8 +16,6 @@
 
 package android.cts.rscpp;
 
-import com.android.cts.stub.R;
-
 import android.content.Context;
 import android.content.res.Resources;
 import android.test.AndroidTestCase;
@@ -38,7 +36,6 @@
         for (int iter = 0; iter < 15; iter++) {
             int[] baseAlloc = new int[X * Y * 4];
             RSUtils.genRandom(0x789321, 255, 1, -128, baseAlloc);
-            RenderScript mRS = RenderScript.create(getContext());
             byte[] byteAlloc = new byte[X * Y * 4];
             for (int i = 0; i < X * Y * 4; i++) {
                 byteAlloc[i] = (byte)baseAlloc[i];
@@ -112,12 +109,12 @@
             }
 
             blendTest(this.getContext().getCacheDir().toString(), X, Y, byteAlloc, byteAlloc2, iter);
-            rsOutput.copyTo(byteAlloc);
-            for (int i = 0; i < X * Y * 4; i++) {
-                assertTrue(byteAlloc[i] == byteAlloc2[i]);
-            }
 
+            Allocation rsCppOutput = Allocation.createTyped(mRS, build.create());
+            rsCppOutput.copyFromUnchecked(byteAlloc2);
+            mVerify.invoke_verify(rsOutput, rsCppOutput, rsInput);
+            checkForErrors();
         }
 
     }
-}
\ No newline at end of file
+}
diff --git a/tests/tests/rscpp/src/android/cts/rscpp/RSBlurTest.java b/tests/tests/rscpp/src/android/cts/rscpp/RSBlurTest.java
index e546516..34bb7ad 100644
--- a/tests/tests/rscpp/src/android/cts/rscpp/RSBlurTest.java
+++ b/tests/tests/rscpp/src/android/cts/rscpp/RSBlurTest.java
@@ -16,8 +16,6 @@
 
 package android.cts.rscpp;
 
-import com.android.cts.stub.R;
-
 import android.content.Context;
 import android.content.res.Resources;
 import android.test.AndroidTestCase;
@@ -37,7 +35,6 @@
     public void testRSBlurOneChannel() {
         int[] baseAlloc = new int[X * Y];
         RSUtils.genRandom(0x1DEFF, 255, 1, -128, baseAlloc);
-        RenderScript mRS = RenderScript.create(getContext());
         byte[] byteAlloc = new byte[X * Y];
         for (int i = 0; i < X * Y; i++) {
             byteAlloc[i] = (byte)baseAlloc[i];
@@ -56,19 +53,17 @@
 
         byte[] nativeByteAlloc = new byte[X * Y];
         blurTest(this.getContext().getCacheDir().toString(), X, Y, byteAlloc, nativeByteAlloc, true);
-        rsOutput.copyTo(byteAlloc);
 
-        for (int i = 0; i < X * Y; i++) {
-            assertTrue(byteAlloc[i] == nativeByteAlloc[i]);
-        }
-
+        Allocation rsCppOutput = Allocation.createTyped(mRS, build.create());
+        rsCppOutput.copyFromUnchecked(nativeByteAlloc);
+        mVerify.invoke_verify(rsOutput, rsCppOutput, rsInput);
+        checkForErrors();
     }
 
 
     public void testRSBlurFourChannels() {
         int[] baseAlloc = new int[X * Y * 4];
         RSUtils.genRandom(0xFAFADE10, 255, 1, -128, baseAlloc);
-        RenderScript mRS = RenderScript.create(getContext());
         byte[] byteAlloc = new byte[X * Y * 4];
         for (int i = 0; i < X * Y * 4; i++) {
             byteAlloc[i] = (byte)baseAlloc[i];
@@ -87,13 +82,12 @@
 
         byte[] nativeByteAlloc = new byte[X * Y * 4];
         blurTest(this.getContext().getCacheDir().toString(), X, Y, byteAlloc, nativeByteAlloc, false);
-        rsOutput.copyTo(byteAlloc);
 
-        for (int i = 0; i < X * Y * 4; i++) {
-            assertTrue(byteAlloc[i] == nativeByteAlloc[i]);
-        }
-
+        Allocation rsCppOutput = Allocation.createTyped(mRS, build.create());
+        rsCppOutput.copyFromUnchecked(nativeByteAlloc);
+        mVerify.invoke_verify(rsOutput, rsCppOutput, rsInput);
+        checkForErrors();
     }
 
 
-}
\ No newline at end of file
+}
diff --git a/tests/tests/rscpp/src/android/cts/rscpp/RSColorMatrixTest.java b/tests/tests/rscpp/src/android/cts/rscpp/RSColorMatrixTest.java
index d634c1f..5260ed9 100644
--- a/tests/tests/rscpp/src/android/cts/rscpp/RSColorMatrixTest.java
+++ b/tests/tests/rscpp/src/android/cts/rscpp/RSColorMatrixTest.java
@@ -16,8 +16,6 @@
 
 package android.cts.rscpp;
 
-import com.android.cts.stub.R;
-
 import android.content.Context;
 import android.content.res.Resources;
 import android.test.AndroidTestCase;
@@ -37,7 +35,6 @@
     public void testRSColorMatrix0() {
         int[] baseAlloc = new int[X * Y * 4];
         RSUtils.genRandom(0x251107, 255, 1, -128, baseAlloc);
-        RenderScript mRS = RenderScript.create(getContext());
         byte[] byteAlloc = new byte[X * Y * 4];
         for (int i = 0; i < X * Y * 4; i++) {
             byteAlloc[i] = (byte)baseAlloc[i];
@@ -68,18 +65,16 @@
 
         byte[] nativeByteAlloc = new byte[X * Y * 4];
         colorMatrixTest(this.getContext().getCacheDir().toString(), X, Y, byteAlloc, nativeByteAlloc, coeffs, 0);
-        rsOutput.copyTo(byteAlloc);
 
-        for (int i = 0; i < X * Y * 4; i++) {
-            assertTrue(byteAlloc[i] == nativeByteAlloc[i]);
-        }
-
+        Allocation rsCppOutput = Allocation.createTyped(mRS, build.create());
+        rsCppOutput.copyFromUnchecked(nativeByteAlloc);
+        mVerify.invoke_verify(rsOutput, rsCppOutput, rsInput);
+        checkForErrors();
     }
 
     public void testRSColorMatrix1() {
         int[] baseAlloc = new int[X * Y * 4];
         RSUtils.genRandom(0x251106, 255, 1, -128, baseAlloc);
-        RenderScript mRS = RenderScript.create(getContext());
         byte[] byteAlloc = new byte[X * Y * 4];
         for (int i = 0; i < X * Y * 4; i++) {
             byteAlloc[i] = (byte)baseAlloc[i];
@@ -100,18 +95,17 @@
 
         byte[] nativeByteAlloc = new byte[X * Y * 4];
         colorMatrixTest(this.getContext().getCacheDir().toString(), X, Y, byteAlloc, nativeByteAlloc, coeffs, 1);
-        rsOutput.copyTo(byteAlloc);
 
-        for (int i = 0; i < X * Y * 4; i++) {
-            assertTrue(byteAlloc[i] == nativeByteAlloc[i]);
-        }
+        Allocation rsCppOutput = Allocation.createTyped(mRS, build.create());
+        rsCppOutput.copyFromUnchecked(nativeByteAlloc);
+        mVerify.invoke_verify(rsOutput, rsCppOutput, rsInput);
+        checkForErrors();
 
     }
 
     public void testRSColorMatrix2() {
         int[] baseAlloc = new int[X * Y * 4];
         RSUtils.genRandom(0x251105, 255, 1, -128, baseAlloc);
-        RenderScript mRS = RenderScript.create(getContext());
         byte[] byteAlloc = new byte[X * Y * 4];
         for (int i = 0; i < X * Y * 4; i++) {
             byteAlloc[i] = (byte)baseAlloc[i];
@@ -136,18 +130,17 @@
 
         byte[] nativeByteAlloc = new byte[X * Y * 4];
         colorMatrixTest(this.getContext().getCacheDir().toString(), X, Y, byteAlloc, nativeByteAlloc, coeffs, 2);
-        rsOutput.copyTo(byteAlloc);
 
-        for (int i = 0; i < X * Y * 4; i++) {
-            assertTrue(byteAlloc[i] == nativeByteAlloc[i]);
-        }
+        Allocation rsCppOutput = Allocation.createTyped(mRS, build.create());
+        rsCppOutput.copyFromUnchecked(nativeByteAlloc);
+        mVerify.invoke_verify(rsOutput, rsCppOutput, rsInput);
+        checkForErrors();
 
     }
 
     public void testRSColorMatrix3() {
         int[] baseAlloc = new int[X * Y * 4];
         RSUtils.genRandom(0x251104, 255, 1, -128, baseAlloc);
-        RenderScript mRS = RenderScript.create(getContext());
         byte[] byteAlloc = new byte[X * Y * 4];
         for (int i = 0; i < X * Y * 4; i++) {
             byteAlloc[i] = (byte)baseAlloc[i];
@@ -168,18 +161,17 @@
 
         byte[] nativeByteAlloc = new byte[X * Y * 4];
         colorMatrixTest(this.getContext().getCacheDir().toString(), X, Y, byteAlloc, nativeByteAlloc, coeffs, 3);
-        rsOutput.copyTo(byteAlloc);
 
-        for (int i = 0; i < X * Y * 4; i++) {
-            assertTrue(byteAlloc[i] == nativeByteAlloc[i]);
-        }
+        Allocation rsCppOutput = Allocation.createTyped(mRS, build.create());
+        rsCppOutput.copyFromUnchecked(nativeByteAlloc);
+        mVerify.invoke_verify(rsOutput, rsCppOutput, rsInput);
+        checkForErrors();
 
     }
 
     public void testRSColorMatrix4() {
         int[] baseAlloc = new int[X * Y * 4];
         RSUtils.genRandom(0x251103, 255, 1, -128, baseAlloc);
-        RenderScript mRS = RenderScript.create(getContext());
         byte[] byteAlloc = new byte[X * Y * 4];
         for (int i = 0; i < X * Y * 4; i++) {
             byteAlloc[i] = (byte)baseAlloc[i];
@@ -200,12 +192,12 @@
 
         byte[] nativeByteAlloc = new byte[X * Y * 4];
         colorMatrixTest(this.getContext().getCacheDir().toString(), X, Y, byteAlloc, nativeByteAlloc, coeffs, 4);
-        rsOutput.copyTo(byteAlloc);
 
-        for (int i = 0; i < X * Y * 4; i++) {
-            assertTrue(byteAlloc[i] == nativeByteAlloc[i]);
-        }
+        Allocation rsCppOutput = Allocation.createTyped(mRS, build.create());
+        rsCppOutput.copyFromUnchecked(nativeByteAlloc);
+        mVerify.invoke_verify(rsOutput, rsCppOutput, rsInput);
+        checkForErrors();
 
     }
 
-}
\ No newline at end of file
+}
diff --git a/tests/tests/rscpp/src/android/cts/rscpp/RSConvolveTest.java b/tests/tests/rscpp/src/android/cts/rscpp/RSConvolveTest.java
index ded67cc..2a3579e 100644
--- a/tests/tests/rscpp/src/android/cts/rscpp/RSConvolveTest.java
+++ b/tests/tests/rscpp/src/android/cts/rscpp/RSConvolveTest.java
@@ -16,8 +16,6 @@
 
 package android.cts.rscpp;
 
-import com.android.cts.stub.R;
-
 import android.content.Context;
 import android.content.res.Resources;
 import android.test.AndroidTestCase;
@@ -48,7 +46,6 @@
         coeffs[8] =  .5f;
 
         RSUtils.genRandom(0x1DEFFD0, 255, 1, -128, baseAlloc);
-        RenderScript mRS = RenderScript.create(getContext());
         byte[] byteAlloc = new byte[X * Y];
         for (int i = 0; i < X * Y; i++) {
             byteAlloc[i] = (byte)baseAlloc[i];
@@ -67,12 +64,11 @@
 
         byte[] nativeByteAlloc = new byte[X * Y];
         convolveTest(this.getContext().getCacheDir().toString(), X, Y, byteAlloc, nativeByteAlloc, coeffs, true);
-        rsOutput.copyTo(byteAlloc);
 
-        for (int i = 0; i < X * Y; i++) {
-            assertTrue(byteAlloc[i] == nativeByteAlloc[i]);
-        }
-
+        Allocation rsCppOutput = Allocation.createTyped(mRS, build.create());
+        rsCppOutput.copyFromUnchecked(nativeByteAlloc);
+        mVerify.invoke_verify(rsOutput, rsCppOutput, rsInput);
+        checkForErrors();
     }
 
     public void testConvolve5x5() {
@@ -125,13 +121,13 @@
 
         byte[] nativeByteAlloc = new byte[X * Y];
         convolveTest(this.getContext().getCacheDir().toString(), X, Y, byteAlloc, nativeByteAlloc, coeffs, false);
-        rsOutput.copyTo(byteAlloc);
 
-        for (int i = 0; i < X * Y; i++) {
-            assertTrue(byteAlloc[i] == nativeByteAlloc[i]);
-        }
+        Allocation rsCppOutput = Allocation.createTyped(mRS, build.create());
+        rsCppOutput.copyFromUnchecked(nativeByteAlloc);
+        mVerify.invoke_verify(rsOutput, rsCppOutput, rsInput);
+        checkForErrors();
 
     }
 
 
-}
\ No newline at end of file
+}
diff --git a/tests/tests/rscpp/src/android/cts/rscpp/RSCppTest.java b/tests/tests/rscpp/src/android/cts/rscpp/RSCppTest.java
index 7ce6688..9b09cc7 100644
--- a/tests/tests/rscpp/src/android/cts/rscpp/RSCppTest.java
+++ b/tests/tests/rscpp/src/android/cts/rscpp/RSCppTest.java
@@ -16,28 +16,94 @@
 
 package android.cts.rscpp;
 
-import com.android.cts.stub.R;
-
 import android.content.Context;
 import android.content.res.Resources;
 import android.test.AndroidTestCase;
-import android.renderscript.*;
+import android.renderscript.RenderScript.RSErrorHandler;
+import android.renderscript.RenderScript.RSMessageHandler;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.RenderScript;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
 import android.util.Log;
 
-class RSCppTest extends AndroidTestCase {
+public class RSCppTest extends AndroidTestCase {
 
     Context mCtx;
     Resources mRes;
+    RenderScript mRS;
+    protected ScriptC_verify mVerify;
+
+    private int result;
+    private boolean msgHandled;
+
+    private static final int RS_MSG_TEST_PASSED = 100;
+    private static final int RS_MSG_TEST_FAILED = 101;
+
+    RSMessageHandler mRsMessage = new RSMessageHandler() {
+        public void run() {
+            if (result == 0) {
+                switch (mID) {
+                    case RS_MSG_TEST_PASSED:
+                    case RS_MSG_TEST_FAILED:
+                        result = mID;
+                        break;
+                    default:
+                        fail("Got unexpected RS message");
+                        return;
+                }
+            }
+            msgHandled = true;
+        }
+    };
+
+    protected void waitForMessage() {
+        while (!msgHandled) {
+            Thread.yield();
+        }
+    }
+
+    protected boolean FoundError = false;
+    protected RSErrorHandler mRsError = new RSErrorHandler() {
+        public void run() {
+            FoundError = true;
+            Log.e("RSCppCTS", mErrorMessage);
+            throw new RSRuntimeException("Received error " + mErrorNum +
+                                         " message " + mErrorMessage);
+        }
+    };
+
+    protected void checkForErrors() {
+        mRS.finish();
+        mVerify.invoke_checkError();
+        waitForMessage();
+        assertFalse(FoundError);
+        assertTrue(result != RS_MSG_TEST_FAILED);
+    }
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+        result = 0;
+        msgHandled = false;
         mCtx = getContext();
         mRes = mCtx.getResources();
+        mRS = RenderScript.create(mCtx);
+        mRS.setMessageHandler(mRsMessage);
+        mVerify = new ScriptC_verify(mRS);
+        mVerify.set_gAllowedIntError(3);
     }
 
     @Override
     protected void tearDown() throws Exception {
+        if (mVerify != null) {
+            mVerify.destroy();
+            mVerify = null;
+        }
+        if (mRS != null) {
+            mRS.destroy();
+            mRS = null;
+        }
         super.tearDown();
     }
-}
\ No newline at end of file
+}
diff --git a/tests/tests/rscpp/src/android/cts/rscpp/RSInitTest.java b/tests/tests/rscpp/src/android/cts/rscpp/RSInitTest.java
index 7fd5ffa..f6b4251 100644
--- a/tests/tests/rscpp/src/android/cts/rscpp/RSInitTest.java
+++ b/tests/tests/rscpp/src/android/cts/rscpp/RSInitTest.java
@@ -16,8 +16,6 @@
 
 package android.cts.rscpp;
 
-import com.android.cts.stub.R;
-
 import android.content.Context;
 import android.content.res.Resources;
 import android.test.AndroidTestCase;
@@ -32,10 +30,10 @@
     native boolean initTest(String path);
     public void testRSInit() {
         for (int i = 0; i < 1000; i++) {
-            RenderScript mRS = RenderScript.create(getContext());
-            mRS.destroy();
+            RenderScript mRSt = RenderScript.create(getContext());
+            mRSt.destroy();
             Log.d("rscpptest", "Java iteration " + i);
         }
         assertTrue(initTest(this.getContext().getCacheDir().toString()));
     }
-}
\ No newline at end of file
+}
diff --git a/tests/tests/rscpp/src/android/cts/rscpp/RSLUTTest.java b/tests/tests/rscpp/src/android/cts/rscpp/RSLUTTest.java
index 2579666..aa24209 100644
--- a/tests/tests/rscpp/src/android/cts/rscpp/RSLUTTest.java
+++ b/tests/tests/rscpp/src/android/cts/rscpp/RSLUTTest.java
@@ -16,8 +16,6 @@
 
 package android.cts.rscpp;
 
-import com.android.cts.stub.R;
-
 import android.content.Context;
 import android.content.res.Resources;
 import android.test.AndroidTestCase;
@@ -37,7 +35,6 @@
     public void testRSLUT() {
         int[] baseAlloc = new int[X * Y * 4];
         RSUtils.genRandom(0x72727272, 255, 1, -128, baseAlloc);
-        RenderScript mRS = RenderScript.create(getContext());
         byte[] byteAlloc = new byte[X * Y * 4];
         for (int i = 0; i < X * Y * 4; i++) {
             byteAlloc[i] = (byte)baseAlloc[i];
@@ -60,12 +57,12 @@
 
         byte[] nativeByteAlloc = new byte[X * Y * 4];
         lutTest(this.getContext().getCacheDir().toString().toString(), X, Y, byteAlloc, nativeByteAlloc);
-        rsOutput.copyTo(byteAlloc);
 
-        for (int i = 0; i < X * Y * 4; i++) {
-            assertTrue(byteAlloc[i] == nativeByteAlloc[i]);
-        }
+        Allocation rsCppOutput = Allocation.createTyped(mRS, build.create());
+        rsCppOutput.copyFromUnchecked(nativeByteAlloc);
+        mVerify.invoke_verify(rsOutput, rsCppOutput, rsInput);
+        checkForErrors();
 
     }
 
-}
\ No newline at end of file
+}
diff --git a/tests/tests/rscpp/src/android/cts/rscpp/RSUtils.java b/tests/tests/rscpp/src/android/cts/rscpp/RSUtils.java
index 58d665f..b40c3bd 100644
--- a/tests/tests/rscpp/src/android/cts/rscpp/RSUtils.java
+++ b/tests/tests/rscpp/src/android/cts/rscpp/RSUtils.java
@@ -20,7 +20,6 @@
 import java.util.Random;
 import android.renderscript.Allocation;
 import android.renderscript.RSRuntimeException;
-import com.android.cts.stub.R;
 
 /**
  * This class supplies some utils for renderscript tests
diff --git a/tests/tests/rscpp/src/android/cts/rscpp/verify.rs b/tests/tests/rscpp/src/android/cts/rscpp/verify.rs
new file mode 100644
index 0000000..7fd44d3
--- /dev/null
+++ b/tests/tests/rscpp/src/android/cts/rscpp/verify.rs
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(android.cts.rscpp)
+
+/* These constants must match those in RSCppTest.java */
+static const int RS_MSG_TEST_PASSED = 100;
+static const int RS_MSG_TEST_FAILED = 101;
+
+int gAllowedIntError = 0;
+static bool hadError = false;
+static int2 errorLoc = {0,0};
+
+
+static bool compare_float(float f1, float f2) {
+    if (fabs(f1-f2) > 0.0001f) {
+        hadError = true;
+        return false;
+    }
+    return true;
+}
+
+static bool verify_float4(rs_allocation in1, rs_allocation in2)
+{
+    uint32_t w = rsAllocationGetDimX(in1);
+    uint32_t h = rsAllocationGetDimY(in1);
+    for (uint32_t y=0; y < h; y++) {
+        for (uint32_t x=0; x < w; x++) {
+            float4 pref = rsGetElementAt_float4(in1, x, y);
+            float4 ptst = rsGetElementAt_float4(in2, x, y);
+            bool e = !compare_float(pref.x, ptst.x);
+            e |= !compare_float(pref.y, ptst.y);
+            e |= !compare_float(pref.z, ptst.z);
+            e |= !compare_float(pref.w, ptst.w);
+            if (e) {
+                errorLoc.x = x;
+                errorLoc.y = y;
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+static bool verify_float3(rs_allocation in1, rs_allocation in2)
+{
+    uint32_t w = rsAllocationGetDimX(in1);
+    uint32_t h = rsAllocationGetDimY(in1);
+    for (uint32_t y=0; y < h; y++) {
+        for (uint32_t x=0; x < w; x++) {
+            float3 pref = rsGetElementAt_float3(in1, x, y);
+            float3 ptst = rsGetElementAt_float3(in2, x, y);
+            bool e = !compare_float(pref.x, ptst.x);
+            e |= !compare_float(pref.y, ptst.y);
+            e |= !compare_float(pref.z, ptst.z);
+            if (e) {
+                errorLoc.x = x;
+                errorLoc.y = y;
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+static bool verify_float2(rs_allocation in1, rs_allocation in2)
+{
+    uint32_t w = rsAllocationGetDimX(in1);
+    uint32_t h = rsAllocationGetDimY(in1);
+    for (uint32_t y=0; y < h; y++) {
+        for (uint32_t x=0; x < w; x++) {
+            float2 pref = rsGetElementAt_float2(in1, x, y);
+            float2 ptst = rsGetElementAt_float2(in2, x, y);
+            bool e = !compare_float(pref.x, ptst.x);
+            e |= !compare_float(pref.y, ptst.y);
+            if (e) {
+                errorLoc.x = x;
+                errorLoc.y = y;
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+static bool verify_float(rs_allocation in1, rs_allocation in2)
+{
+    uint32_t w = rsAllocationGetDimX(in1);
+    uint32_t h = rsAllocationGetDimY(in1);
+    for (uint32_t y=0; y < h; y++) {
+        for (uint32_t x=0; x < w; x++) {
+            float pref = rsGetElementAt_float(in1, x, y);
+            float ptst = rsGetElementAt_float(in2, x, y);
+            bool e = !compare_float(pref, ptst);
+            if (e) {
+                errorLoc.x = x;
+                errorLoc.y = y;
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+static bool verify_uchar4(rs_allocation in1, rs_allocation in2)
+{
+    int merr = 0;
+    uint32_t w = rsAllocationGetDimX(in1);
+    uint32_t h = rsAllocationGetDimY(in1);
+    for (uint32_t y=0; y < h; y++) {
+        for (uint32_t x=0; x < w; x++) {
+            int4 pref = convert_int4(rsGetElementAt_uchar4(in1, x, y));
+            int4 ptst = convert_int4(rsGetElementAt_uchar4(in2, x, y));
+            int4 d = convert_int4(abs(pref - ptst));
+            int e = 0;
+            e = max(e, d.x);
+            e = max(e, d.y);
+            e = max(e, d.z);
+            e = max(e, d.w);
+            if (e > gAllowedIntError) {
+                errorLoc.x = x;
+                errorLoc.y = y;
+                hadError = true;
+                return false;
+            }
+            merr = max(e, merr);
+        }
+    }
+    return true;
+}
+
+static bool verify_uchar3(rs_allocation in1, rs_allocation in2)
+{
+    int merr = 0;
+    uint32_t w = rsAllocationGetDimX(in1);
+    uint32_t h = rsAllocationGetDimY(in1);
+    for (uint32_t y=0; y < h; y++) {
+        for (uint32_t x=0; x < w; x++) {
+            int3 pref = convert_int3(rsGetElementAt_uchar3(in1, x, y));
+            int3 ptst = convert_int3(rsGetElementAt_uchar3(in2, x, y));
+            int3 d = convert_int3(abs(pref - ptst));
+            int e = 0;
+            e = max(e, d.x);
+            e = max(e, d.y);
+            e = max(e, d.z);
+            if (e > gAllowedIntError) {
+                errorLoc.x = x;
+                errorLoc.y = y;
+                hadError = true;
+                return false;
+            }
+            merr = max(e, merr);
+        }
+    }
+    return true;
+}
+
+static bool verify_uchar2(rs_allocation in1, rs_allocation in2)
+{
+    int merr = 0;
+    uint32_t w = rsAllocationGetDimX(in1);
+    uint32_t h = rsAllocationGetDimY(in1);
+    for (uint32_t y=0; y < h; y++) {
+        for (uint32_t x=0; x < w; x++) {
+            int2 pref = convert_int2(rsGetElementAt_uchar2(in1, x, y));
+            int2 ptst = convert_int2(rsGetElementAt_uchar2(in2, x, y));
+            int2 d = convert_int2(abs(pref - ptst));
+            int e = 0;
+            e = max(e, d.x);
+            e = max(e, d.y);
+            if (e > gAllowedIntError) {
+                errorLoc.x = x;
+                errorLoc.y = y;
+                hadError = true;
+                return false;
+            }
+            merr = max(e, merr);
+        }
+    }
+    return true;
+}
+
+static bool verify_uchar(rs_allocation in1, rs_allocation in2)
+{
+    int merr = 0;
+    uint32_t w = rsAllocationGetDimX(in1);
+    uint32_t h = rsAllocationGetDimY(in1);
+    for (uint32_t y=0; y < h; y++) {
+        for (uint32_t x=0; x < w; x++) {
+            int pref = rsGetElementAt_uchar(in1, x, y);
+            int ptst = rsGetElementAt_uchar(in2, x, y);
+            int e = abs(pref - ptst);
+            if (e > gAllowedIntError) {
+                errorLoc.x = x;
+                errorLoc.y = y;
+                hadError = true;
+                return false;
+            }
+            merr = max(e, merr);
+        }
+    }
+    return true;
+}
+
+#define printCell(txt, a, xy) \
+{                       \
+    rs_element e = rsAllocationGetElement(a); \
+    rs_data_type dt = rsElementGetDataType(e); \
+    uint32_t vs = rsElementGetVectorSize(e); \
+ \
+    if (dt == RS_TYPE_UNSIGNED_8) { \
+        switch(vs) { \
+        case 4: \
+            rsDebug(txt, rsGetElementAt_uchar4(a, xy.x, xy.y)); \
+            break; \
+        case 3: \
+            rsDebug(txt, rsGetElementAt_uchar3(a, xy.x, xy.y)); \
+            break; \
+        case 2: \
+            rsDebug(txt, rsGetElementAt_uchar2(a, xy.x, xy.y)); \
+            break; \
+        case 1: \
+            rsDebug(txt, rsGetElementAt_uchar(a, xy.x, xy.y)); \
+            break; \
+        } \
+    } else { \
+        switch(vs) { \
+        case 4: \
+            rsDebug(txt, rsGetElementAt_float4(a, xy.x, xy.y)); \
+            break; \
+        case 3: \
+            rsDebug(txt, rsGetElementAt_float3(a, xy.x, xy.y)); \
+            break; \
+        case 2: \
+            rsDebug(txt, rsGetElementAt_float2(a, xy.x, xy.y)); \
+            break; \
+        case 1: \
+            rsDebug(txt, rsGetElementAt_float(a, xy.x, xy.y)); \
+            break; \
+        } \
+    } \
+}
+
+void verify(rs_allocation ref_in, rs_allocation tst_in, rs_allocation src_in)
+{
+    rs_element e = rsAllocationGetElement(ref_in);
+    rs_data_type dt = rsElementGetDataType(e);
+    uint32_t vs = rsElementGetVectorSize(e);
+    bool valid = false;
+
+    if (dt == RS_TYPE_UNSIGNED_8) {
+        switch(vs) {
+        case 4:
+            valid = verify_uchar4(ref_in, tst_in);
+            break;
+        case 3:
+            valid = verify_uchar3(ref_in, tst_in);
+            break;
+        case 2:
+            valid = verify_uchar2(ref_in, tst_in);
+            break;
+        case 1:
+            valid = verify_uchar(ref_in, tst_in);
+            break;
+        }
+    } else {
+        switch(vs) {
+        case 4:
+            valid = verify_float4(ref_in, tst_in);
+            break;
+        case 3:
+            valid = verify_float3(ref_in, tst_in);
+            break;
+        case 2:
+            valid = verify_float2(ref_in, tst_in);
+            break;
+        case 1:
+            valid = verify_float(ref_in, tst_in);
+            break;
+        }
+    }
+    if (!valid) {
+        rsDebug("verify failure at xy", errorLoc);
+        printCell("start value     ", src_in, errorLoc);
+        printCell("reference value ", ref_in, errorLoc);
+        printCell("test value      ", tst_in, errorLoc);
+    }
+}
+
+void checkError()
+{
+    if (hadError) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    } else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
diff --git a/tests/tests/rsg/Android.mk b/tests/tests/rsg/Android.mk
deleted file mode 100644
index 9ff554c..0000000
--- a/tests/tests/rsg/Android.mk
+++ /dev/null
@@ -1,39 +0,0 @@
-# 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# Replace "Example" with your name.
-LOCAL_PACKAGE_NAME := CtsRenderscriptGraphicsTestCases
-
-# Don't include this package in any target.
-LOCAL_MODULE_TAGS := optional
-
-# When built, explicitly put it in the data partition.
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-# All tests should include android.test.runner.
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_INSTRUMENTATION_FOR := CtsTestStubs
-
-LOCAL_SDK_VERSION := 17
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/rsg/AndroidManifest.xml b/tests/tests/rsg/AndroidManifest.xml
deleted file mode 100644
index 886a395..0000000
--- a/tests/tests/rsg/AndroidManifest.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?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.
--->
-
-<!-- Replace all the "example" stuff below with your package name, and
-     remove this comment.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.cts.renderscriptgraphics">
-
-    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
-    <application>
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <!-- This is a self-instrumenting test package. -->
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="com.android.cts.stub"
-                     android:label="CTS tests of Renderscript Graphics component"/>
-
-</manifest>
-
diff --git a/tests/tests/rsg/src/android/renderscriptgraphics/cts/BaseObjTest.java b/tests/tests/rsg/src/android/renderscriptgraphics/cts/BaseObjTest.java
deleted file mode 100644
index 7773dda..0000000
--- a/tests/tests/rsg/src/android/renderscriptgraphics/cts/BaseObjTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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.
- */
-
-package android.renderscriptgraphics.cts;
-
-import android.renderscript.BaseObj;
-import android.renderscript.Font;
-import android.renderscript.Font.Style;
-import android.renderscript.RSIllegalArgumentException;
-
-public class BaseObjTest extends RSBaseGraphics {
-
-    public void testBaseObj() {
-        Style S = Font.Style.NORMAL;
-        Font F = Font.create(mRS, mRes, "sans-serif", S, 8);
-        assertTrue(F != null);
-        BaseObj B = F;
-        B.setName("sans-serif");
-        try {
-            B.setName("sans-serif");
-            fail("set name twice for a BaseObj");
-        } catch (RSIllegalArgumentException e) {
-        }
-        B.destroy();
-
-        F = Font.create(mRS, mRes, "serif", S, 8);
-        assertTrue(F != null);
-        B = F;
-        try {
-            B.setName("");
-            fail("set empty name for a BaseObj");
-        } catch (RSIllegalArgumentException e) {
-        }
-        B.setName("serif");
-        B.destroy();
-
-        F = Font.create(mRS, mRes, "mono", S, 8);
-        assertTrue(F != null);
-        B = F;
-        try {
-            B.setName(null);
-            fail("set name as null string reference for a BaseObj");
-        } catch (RSIllegalArgumentException e) {
-        }
-        B.setName("mono");
-        B.destroy();
-    }
-}
-
diff --git a/tests/tests/rsg/src/android/renderscriptgraphics/cts/ContextCreationTest.java b/tests/tests/rsg/src/android/renderscriptgraphics/cts/ContextCreationTest.java
deleted file mode 100644
index 11b999c..0000000
--- a/tests/tests/rsg/src/android/renderscriptgraphics/cts/ContextCreationTest.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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.
- */
-
-package android.renderscriptgraphics.cts;
-
-import android.renderscript.*;
-import android.test.ActivityInstrumentationTestCase2;
-import android.test.UiThreadTest;
-import android.util.Log;
-
-/**
- * Tests for the RenderScriptGL class.
- */
-public class ContextCreationTest extends
-        ActivityInstrumentationTestCase2<RenderscriptGLStubActivity> {
-
-    private static final int NUM_RECREATE_ITERATIONS_WITHOUT_DELAY = 50;
-
-    private static final int NUM_RECREATE_ITERATIONS_WITH_DELAY = 10;
-
-    private static final int RECREATE_DELAY = 100;
-
-    private static final boolean LOG_RECREATE = true;
-
-    private static final String TAG = "ContextCreationTest";
-
-    private RenderscriptGLStubActivity mActivity;
-
-    public ContextCreationTest() {
-        super(RenderscriptGLStubActivity.class);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mActivity = getActivity();
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        mActivity.destroyAll();
-        super.tearDown();
-    }
-
-    /**
-     * Test repeated recreation of the renderscript context with a
-     * delay in between to detect hangs in the graphics drivers
-     */
-    @UiThreadTest
-    public void testCreationWithDelay() throws InterruptedException {
-        for (int i = 0; i < NUM_RECREATE_ITERATIONS_WITH_DELAY; i++) {
-            Thread.sleep(RECREATE_DELAY);
-            if (LOG_RECREATE) {
-                Log.w(TAG, "Recreate (w/ delay) step " + i + " - pause");
-            }
-            mActivity.recreateView();
-        }
-    }
-
-    /**
-     * Test repeated recreation of the renderscript context to
-     * detect hangs in the graphics drivers
-     */
-    @UiThreadTest
-    public void testCreationWithoutDelay() {
-        for (int i = 0; i < NUM_RECREATE_ITERATIONS_WITHOUT_DELAY; i++) {
-            if (LOG_RECREATE) {
-                Log.w(TAG, "Recreate (no delay) step " + i);
-            }
-            mActivity.recreateView();
-        }
-    }
-
-    /**
-     * Test repeated recreation of the renderscript context with two
-     * created at a time to detect hangs in the graphics drivers
-     */
-    @UiThreadTest
-    public void testMultiviewCreationWithoutDelay() {
-        for (int i = 0; i < NUM_RECREATE_ITERATIONS_WITHOUT_DELAY; i++) {
-            if (LOG_RECREATE) {
-                Log.w(TAG, "Recreate multiview (no delay) step " + i + " - pause");
-            }
-            mActivity.recreateMultiView();
-        }
-    }
-}
diff --git a/tests/tests/rsg/src/android/renderscriptgraphics/cts/FileA3DTest.java b/tests/tests/rsg/src/android/renderscriptgraphics/cts/FileA3DTest.java
deleted file mode 100644
index 510a3c5..0000000
--- a/tests/tests/rsg/src/android/renderscriptgraphics/cts/FileA3DTest.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * 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.
- */
-
-package android.renderscriptgraphics.cts;
-
-import java.io.File;
-
-import com.android.cts.stub.R;
-
-import android.renderscript.RSRuntimeException;
-import android.renderscript.FileA3D;
-import android.renderscript.FileA3D.EntryType;
-import android.renderscript.FileA3D.IndexEntry;
-
-public class FileA3DTest extends RSBaseGraphics {
-
-    public void testCreateFromResource() {
-        FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.sphere);
-        assertTrue(model != null);
-    }
-
-    public void testCreateFromAsset() {
-        FileA3D model = FileA3D.createFromAsset(mRS, mRes.getAssets(), "sphere.a3d");
-        assertTrue(model != null);
-    }
-
-    public void testGetIndexEntryCount() {
-        FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.sphere);
-        assertTrue(model != null);
-        assertTrue(model.getIndexEntryCount() == 1);
-    }
-
-    public void testGetIndexEntry() {
-        FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.sphere);
-        assertTrue(model != null);
-        assertTrue(model.getIndexEntryCount() == 1);
-        assertTrue(model.getIndexEntry(0) != null);
-    }
-
-    public void testIndexEntryGetEntryType() {
-        FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.sphere);
-        assertTrue(model != null);
-        assertTrue(model.getIndexEntryCount() == 1);
-        FileA3D.IndexEntry entry = model.getIndexEntry(0);
-        assertTrue(entry != null);
-        assertTrue(entry.getEntryType() == FileA3D.EntryType.MESH);
-        boolean isOneOfEntries = false;
-        for(FileA3D.EntryType et : FileA3D.EntryType.values()) {
-            if (et == entry.getEntryType()) {
-                isOneOfEntries = true;
-                break;
-            }
-        }
-        assertTrue(isOneOfEntries);
-    }
-
-    public void testIndexEntryGetMesh() {
-        FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.sphere);
-        assertTrue(model != null);
-        assertTrue(model.getIndexEntryCount() == 1);
-        FileA3D.IndexEntry entry = model.getIndexEntry(0);
-        assertTrue(entry != null);
-        assertTrue(entry.getEntryType() == FileA3D.EntryType.MESH);
-        assertTrue(entry.getMesh() != null);
-    }
-
-    public void testIndexEntryGetName() {
-        FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.sphere);
-        assertTrue(model != null);
-        assertTrue(model.getIndexEntryCount() == 1);
-        FileA3D.IndexEntry entry = model.getIndexEntry(0);
-        assertTrue(entry != null);
-        assertTrue(entry.getName() != null);
-    }
-
-    public void testIndexEntryGetObject() {
-        FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.sphere);
-        assertTrue(model != null);
-        assertTrue(model.getIndexEntryCount() == 1);
-        FileA3D.IndexEntry entry = model.getIndexEntry(0);
-        assertTrue(entry != null);
-        assertTrue(entry.getObject() != null);
-    }
-
-    public void testFileA3DEntryType() {
-        assertEquals(FileA3D.EntryType.UNKNOWN, FileA3D.EntryType.valueOf("UNKNOWN"));
-        assertEquals(FileA3D.EntryType.MESH, FileA3D.EntryType.valueOf("MESH"));
-        // Make sure no new enums are added
-        assertEquals(2, FileA3D.EntryType.values().length);
-    }
-
-    public void testCreateFromFile() {
-        File fileDesc = new File("bogusFile");
-        try {
-            FileA3D model = FileA3D.createFromFile(mRS, fileDesc);
-            fail("should throw RSRuntimeException.");
-        } catch (RSRuntimeException e) {
-        }
-        try {
-            FileA3D model = FileA3D.createFromFile(mRS, "bogus");
-            fail("should throw RSRuntimeException.");
-        } catch (RSRuntimeException e) {
-        }
-    }
-}
-
-
diff --git a/tests/tests/rsg/src/android/renderscriptgraphics/cts/FontTest.java b/tests/tests/rsg/src/android/renderscriptgraphics/cts/FontTest.java
deleted file mode 100644
index 43b9662..0000000
--- a/tests/tests/rsg/src/android/renderscriptgraphics/cts/FontTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.
- */
-
-package android.renderscriptgraphics.cts;
-
-import java.io.File;
-import com.android.cts.stub.R;
-
-import android.os.Environment;
-import android.renderscript.Font;
-import android.renderscript.Font.Style;
-import android.renderscript.RSIllegalArgumentException;
-
-public class FontTest extends RSBaseGraphics {
-
-    public void testCreate() {
-        for (int fontSize = 8; fontSize <= 12; fontSize += 2) {
-            for (Font.Style style : Font.Style.values()) {
-                Font F = null;
-                F = Font.create(mRS, mRes, "sans-serif", style, fontSize);
-                assertTrue(F != null);
-                F.setName("sans-serif");
-                try {
-                    F.setName("sans-serif");
-                    fail("set name twice for a font");
-                } catch (RSIllegalArgumentException e) {
-                }
-                F.destroy();
-
-                F = Font.create(mRS, mRes, "serif", style, fontSize);
-                assertTrue(F != null);
-                try {
-                    F.setName("");
-                    fail("set empty name for a font");
-                } catch (RSIllegalArgumentException e) {
-                }
-                F.setName("serif");
-                F.destroy();
-
-                F = Font.create(mRS, mRes, "mono", style, fontSize);
-                assertTrue(F != null);
-                try {
-                    F.setName(null);
-                    fail("set name as null string reference for a font");
-                } catch (RSIllegalArgumentException e) {
-                }
-                F.setName("mono");
-                F.destroy();
-            }
-        }
-    }
-
-    public void testCreateFromFile() {
-        String fontFile = "Roboto-Regular.ttf";
-        String fontPath = Environment.getRootDirectory().getAbsolutePath();
-        fontPath += "/fonts/" + fontFile;
-        File fileDesc = new File(fontPath);
-        assertTrue(Font.createFromFile(mRS, mRes, fontPath, 8) != null);
-        assertTrue(Font.createFromFile(mRS, mRes, fileDesc, 8) != null);
-    }
-
-    public void testCreateFromAsset() {
-        assertTrue(Font.createFromAsset(mRS, mRes, "samplefont.ttf", 8) != null);
-    }
-
-    public void testFontStyle() {
-        assertEquals(Font.Style.NORMAL, Font.Style.valueOf("NORMAL"));
-        assertEquals(Font.Style.BOLD, Font.Style.valueOf("BOLD"));
-        assertEquals(Font.Style.ITALIC, Font.Style.valueOf("ITALIC"));
-        assertEquals(Font.Style.BOLD_ITALIC, Font.Style.valueOf("BOLD_ITALIC"));
-        // Make sure no new enums are added
-        assertEquals(4, Font.Style.values().length);
-    }
-
-    public void testCreateFromResource() {
-        assertTrue(Font.createFromResource(mRS, mRes, R.raw.samplefont, 8) != null);
-    }
-}
-
diff --git a/tests/tests/rsg/src/android/renderscriptgraphics/cts/MeshTest.java b/tests/tests/rsg/src/android/renderscriptgraphics/cts/MeshTest.java
deleted file mode 100644
index 9b7eb99..0000000
--- a/tests/tests/rsg/src/android/renderscriptgraphics/cts/MeshTest.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * 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.
- */
-
-package android.renderscriptgraphics.cts;
-
-import android.renderscript.Allocation;
-import android.renderscript.Element;
-import android.renderscript.Type;
-import android.renderscript.Mesh;
-import android.renderscript.Mesh.Primitive;
-import android.renderscript.Mesh.AllocationBuilder;
-import android.renderscript.Mesh.Builder;
-import android.renderscript.Mesh.TriangleMeshBuilder;
-
-public class MeshTest extends RSBaseGraphics {
-
-    Allocation mAttrAlloc;
-    Allocation mIndexAlloc;
-    Element mPosElem;
-    Type mPosType;
-    Type mIndexType;
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        Element.Builder eb = new Element.Builder(mRS);
-        eb.add(Element.F32_4(mRS), "position");
-        mPosElem = eb.create();
-        Type.Builder typeB = new Type.Builder(mRS, mPosElem);
-        mPosType = typeB.setX(3).create();
-        typeB = new Type.Builder(mRS, Element.U16(mRS));
-        mIndexType = typeB.setX(3).create();
-
-        mAttrAlloc = Allocation.createSized(mRS, mPosElem, 3);
-        mIndexAlloc = Allocation.createSized(mRS, Element.U16(mRS), 3);
-    }
-
-    public void testMeshAllocationBuilder() {
-        Mesh.AllocationBuilder mab;
-        for(Primitive prim : Primitive.values()) {
-            mab = new Mesh.AllocationBuilder(mRS);
-            mab.addVertexAllocation(mAttrAlloc);
-            mab.getCurrentVertexTypeIndex();
-            mab.addIndexSetType(prim);
-            assertTrue(mab.create() != null);
-
-            mab = new Mesh.AllocationBuilder(mRS);
-            mab.addVertexAllocation(mAttrAlloc);
-            mab.getCurrentVertexTypeIndex();
-            mab.addIndexSetAllocation(mIndexAlloc, prim);
-            mab.getCurrentIndexSetIndex();
-            mab.addIndexSetType(prim);
-
-            Mesh mesh = mab.create();
-            assertTrue(mesh != null);
-            assertTrue(mesh.getVertexAllocationCount() == 1);
-            assertTrue(mesh.getVertexAllocation(0) == mAttrAlloc);
-            assertTrue(mesh.getPrimitiveCount() == 2);
-            assertTrue(mesh.getPrimitive(0) == prim);
-            assertTrue(mesh.getPrimitive(1) == prim);
-            assertTrue(mesh.getIndexSetAllocation(0) == mIndexAlloc);
-        }
-    }
-
-    public void testMeshBuilder() {
-        Mesh.Builder mb;
-        for(Primitive prim : Primitive.values()) {
-            mb = new Mesh.Builder(mRS,
-                                  Allocation.USAGE_SCRIPT |
-                                  Allocation.USAGE_GRAPHICS_VERTEX);
-            mb.addVertexType(mPosElem, 3);
-            mb.getCurrentVertexTypeIndex();
-            mb.addIndexSetType(prim);
-            Mesh mesh = mb.create();
-            assertTrue(mesh != null);
-            assertTrue(mesh.getVertexAllocationCount() != 0);
-
-            mb = new Mesh.Builder(mRS,
-                                  Allocation.USAGE_SCRIPT |
-                                  Allocation.USAGE_GRAPHICS_VERTEX);
-            mb.addVertexType(mPosElem, 3);
-            mb.getCurrentVertexTypeIndex();
-            mb.addIndexSetType(Element.U16(mRS), 3, prim);
-            mb.getCurrentIndexSetIndex();
-            mesh = mb.create();
-            assertTrue(mesh != null);
-            assertTrue(mesh.getVertexAllocationCount() != 0);
-            assertTrue(mesh.getPrimitiveCount() != 0);
-
-            mb = new Mesh.Builder(mRS,
-                                  Allocation.USAGE_SCRIPT |
-                                  Allocation.USAGE_GRAPHICS_VERTEX);
-            mb.addVertexType(mPosElem, 3);
-            mb.getCurrentVertexTypeIndex();
-            mb.addIndexSetType(mIndexType, prim);
-            mb.getCurrentIndexSetIndex();
-            assertTrue(mb.create() != null);
-
-            mb = new Mesh.Builder(mRS,
-                                  Allocation.USAGE_SCRIPT |
-                                  Allocation.USAGE_GRAPHICS_VERTEX);
-            mb.addVertexType(mPosType);
-            mb.getCurrentVertexTypeIndex();
-            mb.addIndexSetType(prim);
-            assertTrue(mb.create() != null);
-
-            mb = new Mesh.Builder(mRS,
-                                  Allocation.USAGE_SCRIPT |
-                                  Allocation.USAGE_GRAPHICS_VERTEX);
-            mb.addVertexType(mPosType);
-            mb.getCurrentVertexTypeIndex();
-            mb.addIndexSetType(Element.U16(mRS), 3, prim);
-            mb.getCurrentIndexSetIndex();
-            assertTrue(mb.create() != null);
-
-            mb = new Mesh.Builder(mRS,
-                                  Allocation.USAGE_SCRIPT |
-                                  Allocation.USAGE_GRAPHICS_VERTEX);
-            mb.addVertexType(mPosType);
-            mb.getCurrentVertexTypeIndex();
-            mb.addIndexSetType(mIndexType, prim);
-            mb.getCurrentIndexSetIndex();
-            assertTrue(mb.create() != null);
-        }
-    }
-
-    void triangleMeshBuilderHelper(int size, int flags) {
-        // Test various num vertices and triangles
-        for (int numVerts = 3; numVerts < 100; numVerts += 15) {
-            for (int numTries = 1; numTries < 100; numTries += 15) {
-                Mesh.TriangleMeshBuilder tmb = new Mesh.TriangleMeshBuilder(mRS, size, flags);
-                // Append all the vertices
-                for (int numVertsI = 0; numVertsI < numVerts; numVertsI++) {
-                    if (size == 2) {
-                        tmb.addVertex(1.0f, 1.0f);
-                    } else {
-                        tmb.addVertex(1.0f, 1.0f, 1.0f);
-                    }
-                    if ((flags & TriangleMeshBuilder.COLOR) != 0) {
-                        tmb.setColor(1.0f, 1.0f, 1.0f, 1.0f);
-                    }
-                    if ((flags & TriangleMeshBuilder.NORMAL) != 0) {
-                        tmb.setNormal(1.0f, 1.0f, 1.0f);
-                    }
-                    if ((flags & TriangleMeshBuilder.TEXTURE_0) != 0) {
-                        tmb.setTexture(1.0f, 1.0f);
-                    }
-                }
-                // Add triangles to index them
-                for (int numTriesI = 0; numTriesI < numTries; numTriesI ++) {
-                    tmb.addTriangle(0, 1, 2);
-                }
-                assertTrue(tmb.create(false) != null);
-                assertTrue(tmb.create(true) != null);
-            }
-        }
-    }
-
-    public void testMeshTriangleMeshBuilder() {
-        for (int size = 2; size <= 3; size ++) {
-            triangleMeshBuilderHelper(size, 0);
-            triangleMeshBuilderHelper(size, TriangleMeshBuilder.COLOR);
-            triangleMeshBuilderHelper(size, TriangleMeshBuilder.COLOR |
-                                            TriangleMeshBuilder.NORMAL);
-            triangleMeshBuilderHelper(size, TriangleMeshBuilder.COLOR |
-                                            TriangleMeshBuilder.TEXTURE_0);
-            triangleMeshBuilderHelper(size, TriangleMeshBuilder.COLOR |
-                                            TriangleMeshBuilder.NORMAL |
-                                            TriangleMeshBuilder.TEXTURE_0);
-            triangleMeshBuilderHelper(size, TriangleMeshBuilder.NORMAL);
-            triangleMeshBuilderHelper(size, TriangleMeshBuilder.NORMAL|
-                                            TriangleMeshBuilder.TEXTURE_0);
-            triangleMeshBuilderHelper(size, TriangleMeshBuilder.TEXTURE_0);
-        }
-    }
-
-    public void testMeshPrimitive() {
-        assertEquals(Mesh.Primitive.POINT, Mesh.Primitive.valueOf("POINT"));
-        assertEquals(Mesh.Primitive.LINE, Mesh.Primitive.valueOf("LINE"));
-        assertEquals(Mesh.Primitive.LINE_STRIP, Mesh.Primitive.valueOf("LINE_STRIP"));
-        assertEquals(Mesh.Primitive.TRIANGLE, Mesh.Primitive.valueOf("TRIANGLE"));
-        assertEquals(Mesh.Primitive.TRIANGLE_STRIP, Mesh.Primitive.valueOf("TRIANGLE_STRIP"));
-        assertEquals(Mesh.Primitive.TRIANGLE_FAN, Mesh.Primitive.valueOf("TRIANGLE_FAN"));
-        // Make sure no new enums are added
-        assertEquals(6, Mesh.Primitive.values().length);
-    }
-}
-
-
diff --git a/tests/tests/rsg/src/android/renderscriptgraphics/cts/ProgramFragmentFixedFunctionTest.java b/tests/tests/rsg/src/android/renderscriptgraphics/cts/ProgramFragmentFixedFunctionTest.java
deleted file mode 100644
index 29824d1..0000000
--- a/tests/tests/rsg/src/android/renderscriptgraphics/cts/ProgramFragmentFixedFunctionTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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.
- */
-
-package android.renderscriptgraphics.cts;
-
-import com.android.cts.stub.R;
-import android.renderscript.Element;
-import android.renderscript.Type;
-import android.renderscript.Allocation;
-import android.renderscript.Sampler;
-import android.renderscript.ProgramFragment;
-import android.renderscript.ProgramFragmentFixedFunction;
-import android.renderscript.ProgramFragmentFixedFunction.Builder;
-
-public class ProgramFragmentFixedFunctionTest extends RSBaseGraphics {
-
-    ScriptC_graphics_runner mScript;
-
-    Allocation mTex2D;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        Type.Builder typeB = new Type.Builder(mRS, Element.RGB_888(mRS));
-        typeB.setX(8).setY(8);
-        mTex2D = Allocation.createTyped(mRS, typeB.create(),
-                                        Allocation.USAGE_SCRIPT |
-                                        Allocation.USAGE_GRAPHICS_TEXTURE);
-
-        mScript = new ScriptC_graphics_runner(mRS, mRes, R.raw.graphics_runner);
-        mRS.bindRootScript(mScript);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        mRS.bindRootScript(null);
-        super.tearDown();
-    }
-
-    void testProgramFragmentFixedFunctionBuilder(boolean testBind) {
-        ProgramFragmentFixedFunction.Builder b;
-        for (int tCount = 0; tCount <= Builder.MAX_TEXTURE; tCount ++) {
-            for (int varC = 0; varC <= 1; varC++) {
-                for (int pSprite = 0; pSprite <= 1; pSprite++) {
-                    for (Builder.EnvMode env : Builder.EnvMode.values()) {
-                        for (Builder.Format format : Builder.Format.values()) {
-                            b = new ProgramFragmentFixedFunction.Builder(mRS);
-                            b.setVaryingColor(varC == 1);
-                            b.setPointSpriteTexCoordinateReplacement(pSprite == 1);
-                            for (int t = 0; t < tCount; t++) {
-                                b.setTexture(env, format, t);
-                            }
-
-                            ProgramFragment pf = b.create();
-                            assertTrue(pf != null);
-                            for (int t = 0; t < tCount; t++) {
-                                pf.bindTexture(mTex2D, t);
-                                pf.bindSampler(Sampler.CLAMP_NEAREST(mRS), t);
-                            }
-                            if (testBind) {
-                                mScript.invoke_testProgramFragment(pf);
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    public void testProgramFragmentFixedFunctionBuilder() {
-        testProgramFragmentFixedFunctionBuilder(false);
-        testProgramFragmentFixedFunctionBuilder(true);
-    }
-
-    public void testBuilderEnvMode() {
-        assertEquals(Builder.EnvMode.DECAL, Builder.EnvMode.valueOf("DECAL"));
-        assertEquals(Builder.EnvMode.MODULATE, Builder.EnvMode.valueOf("MODULATE"));
-        assertEquals(Builder.EnvMode.REPLACE, Builder.EnvMode.valueOf("REPLACE"));
-
-        // Make sure no new enums are added
-        assertEquals(3, Builder.EnvMode.values().length);
-    }
-
-    public void testBuilderFormat() {
-        assertEquals(Builder.Format.ALPHA, Builder.Format.valueOf("ALPHA"));
-        assertEquals(Builder.Format.LUMINANCE_ALPHA, Builder.Format.valueOf("LUMINANCE_ALPHA"));
-        assertEquals(Builder.Format.RGB, Builder.Format.valueOf("RGB"));
-        assertEquals(Builder.Format.RGBA, Builder.Format.valueOf("RGBA"));
-
-        // Make sure no new enums are added
-        assertEquals(4, Builder.Format.values().length);
-    }
-
-}
-
-
diff --git a/tests/tests/rsg/src/android/renderscriptgraphics/cts/ProgramFragmentTest.java b/tests/tests/rsg/src/android/renderscriptgraphics/cts/ProgramFragmentTest.java
deleted file mode 100644
index ef6ad18..0000000
--- a/tests/tests/rsg/src/android/renderscriptgraphics/cts/ProgramFragmentTest.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * 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.
- */
-
-package android.renderscriptgraphics.cts;
-
-import com.android.cts.stub.R;
-
-import android.renderscript.Allocation;
-import android.renderscript.Element;
-import android.renderscript.Program;
-import android.renderscript.ProgramFragment;
-import android.renderscript.Sampler;
-import android.renderscript.Type;
-
-public class ProgramFragmentTest extends RSBaseGraphics {
-
-    ScriptC_graphics_runner mScript;
-
-    Allocation mConstMatrix;
-    Allocation mConstComplex;
-    Allocation mConstExtra;
-
-    Allocation mTex2D;
-    Allocation mTexCube;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        Type.Builder typeB = new Type.Builder(mRS, Element.RGB_888(mRS));
-        typeB.setX(8).setY(8);
-        mTex2D = Allocation.createTyped(mRS, typeB.create(),
-                                        Allocation.USAGE_SCRIPT |
-                                        Allocation.USAGE_GRAPHICS_TEXTURE);
-        typeB.setFaces(true);
-        mTexCube = Allocation.createTyped(mRS, typeB.create(),
-                                          Allocation.USAGE_SCRIPT |
-                                          Allocation.USAGE_GRAPHICS_TEXTURE);
-
-        ScriptField_ConstMatrix c1 = new ScriptField_ConstMatrix(mRS, 1,
-                                                                 Allocation.USAGE_SCRIPT |
-                                                                 Allocation.USAGE_GRAPHICS_CONSTANTS);
-        c1.set(new ScriptField_ConstMatrix.Item(), 0, true);
-        mConstMatrix = c1.getAllocation();
-
-        ScriptField_ConstComplex c2 = new ScriptField_ConstComplex(mRS, 1,
-                                                                   Allocation.USAGE_SCRIPT |
-                                                                   Allocation.USAGE_GRAPHICS_CONSTANTS);
-        c2.set(new ScriptField_ConstComplex.Item(), 0, true);
-        mConstComplex = c2.getAllocation();
-
-        ScriptField_ConstExtra c3 = new ScriptField_ConstExtra(mRS, 1,
-                                                               Allocation.USAGE_SCRIPT |
-                                                               Allocation.USAGE_GRAPHICS_CONSTANTS);
-        c3.set(new ScriptField_ConstExtra.Item(), 0, true);
-        mConstExtra = c3.getAllocation();
-
-        mScript = new ScriptC_graphics_runner(mRS, mRes, R.raw.graphics_runner);
-        mRS.bindRootScript(mScript);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        mRS.bindRootScript(null);
-        super.tearDown();
-    }
-
-    ProgramFragment buildShader(Allocation[] textures, Allocation[] constInput, String shader) {
-        ProgramFragment.Builder pfb = new ProgramFragment.Builder(mRS);
-        Program.BaseProgramBuilder bpb = pfb;
-        if (textures != null) {
-            for (int i = 0; i < textures.length; i++) {
-                Program.TextureType tType = Program.TextureType.TEXTURE_2D;
-                if (textures[i].getType().hasFaces()) {
-                    tType = Program.TextureType.TEXTURE_CUBE;
-                }
-                // Add textures through the base program builder
-                bpb.addTexture(tType);
-                bpb.getCurrentTextureIndex();
-            }
-        }
-
-        if (constInput != null) {
-            for (int i = 0; i < constInput.length; i++) {
-                bpb.addConstant(constInput[i].getType());
-                bpb.getCurrentConstantIndex();
-            }
-        }
-
-        bpb.setShader(shader);
-        ProgramFragment pf = pfb.create();
-        if (constInput != null) {
-            for (int i = 0; i < constInput.length; i++) {
-                pf.bindConstants(constInput[i], i);
-                // Test the base class path too
-                Program p = pf;
-                p.bindConstants(constInput[i], i);
-            }
-        }
-        if (textures != null) {
-            for (int i = 0; i < textures.length; i++) {
-                pf.bindTexture(textures[i], i);
-                pf.bindSampler(Sampler.CLAMP_NEAREST(mRS), i);
-                // Test the base class path too
-                Program p = pf;
-                p.bindTexture(textures[i], i);
-                p.bindSampler(Sampler.CLAMP_NEAREST(mRS), i);
-            }
-        }
-        return pf;
-    }
-
-    void testProgramFragmentBuilderHelper(boolean testBind) {
-        String simpleFrag = "void main() {\n"+
-                            "  vec4 col = vec4(0.1, 0.2, 0.3, 0.4);"+
-                            "  gl_FragColor = col;\n"+
-                            "}";
-
-        String simpleUni = "void main() {\n"+
-                           "  vec4 col = vec4(0.1, 0.2, 0.3, 0.4);\n"+
-                           "  col = UNI_MATRIX * col;\n"+
-                           "  gl_FragColor = col;\n"+
-                           "}";
-
-        String simpleUniTex = "void main() {\n"+
-                              "  vec4 col = vec4(0.1, 0.2, 0.3, 0.4);"+
-                              "  col += texture2D(UNI_Tex0, vec2(0.1, 0.1));\n"+
-                              "  col += textureCube(UNI_Tex1, vec3(0.1, 0.2, 0.3));\n"+
-                              "  col = UNI_MATRIX * col;\n"+
-                              "  gl_FragColor = col;\n"+
-                              "}";
-
-        String multiUni = "void main() {\n"+
-                          "  vec4 col = vec4(0.1, 0.2, 0.3, 0.4);"+
-                          "  col = UNI_MATRIX * col;\n"+
-                          "  col = UNI_EXTRA * col;\n"+
-                          "  col += UNI_extra4;\n"+
-                          "  col.xyz += UNI_extra3;\n "+
-                          "  col.xy += UNI_extra2;\n"+
-                          "  col.x += UNI_extra1;\n"+
-                          "  gl_FragColor = col;\n"+
-                          "}";
-
-        // Create a series of shaders that do nothing useful
-        // but exercise creation pipeline
-        ProgramFragment pf = buildShader(null, null, simpleFrag);
-        if (testBind) {
-            mScript.invoke_testProgramFragment(pf);
-        }
-
-        Allocation[] constInput = new Allocation[1];
-        constInput[0] = mConstMatrix;
-        pf = buildShader(null, constInput, simpleUni);
-        if (testBind) {
-            mScript.invoke_testProgramFragment(pf);
-            mRS.bindProgramFragment(pf);
-        }
-
-        constInput[0] = mConstComplex;
-        pf = buildShader(null, constInput, multiUni);
-        if (testBind) {
-            mScript.invoke_testProgramFragment(pf);
-            mRS.bindProgramFragment(pf);
-        }
-
-        Allocation[] textures = new Allocation[2];
-        textures[0] = mTex2D;
-        textures[1] = mTexCube;
-        pf = buildShader(textures, constInput, simpleUniTex);
-        if (testBind) {
-            mScript.invoke_testProgramFragment(pf);
-            mRS.bindProgramFragment(pf);
-        }
-
-        constInput = new Allocation[2];
-        constInput[0] = mConstMatrix;
-        constInput[1] = mConstExtra;
-        pf = buildShader(null, constInput, multiUni);
-        if (testBind) {
-            mScript.invoke_testProgramFragment(pf);
-            mRS.bindProgramFragment(pf);
-        }
-    }
-
-    public void testProgramFragmentBuilder() {
-        testProgramFragmentBuilderHelper(false);
-    }
-
-    public void testProgramFragmentCreation() {
-        testProgramFragmentBuilderHelper(true);
-    }
-
-    public void testProgramTextureType() {
-        assertEquals(Program.TextureType.TEXTURE_2D,
-                     Program.TextureType.valueOf("TEXTURE_2D"));
-        assertEquals(Program.TextureType.TEXTURE_CUBE,
-                     Program.TextureType.valueOf("TEXTURE_CUBE"));
-        // Make sure no new enums are added
-        assertEquals(2, Program.TextureType.values().length);
-
-        ProgramFragment.Builder pfb = new ProgramFragment.Builder(mRS);
-        for (Program.TextureType tt : Program.TextureType.values()) {
-            pfb.addTexture(tt);
-        }
-    }
-}
-
-
diff --git a/tests/tests/rsg/src/android/renderscriptgraphics/cts/ProgramRasterTest.java b/tests/tests/rsg/src/android/renderscriptgraphics/cts/ProgramRasterTest.java
deleted file mode 100644
index e752d39..0000000
--- a/tests/tests/rsg/src/android/renderscriptgraphics/cts/ProgramRasterTest.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.
- */
-
-package android.renderscriptgraphics.cts;
-
-import android.renderscript.ProgramRaster;
-import android.renderscript.ProgramRaster.Builder;
-import android.renderscript.ProgramRaster.CullMode;
-
-public class ProgramRasterTest extends RSBaseGraphics {
-
-    public void testProgramRasterBuilder() {
-        ProgramRaster.Builder b = new ProgramRaster.Builder(mRS);
-        for (int p = 0; p <= 1; p++) {
-            boolean pSprite = (p == 1);
-            b.setPointSpriteEnabled(pSprite);
-            for (CullMode cull : CullMode.values()) {
-                b.setCullMode(cull);
-                ProgramRaster pr = b.create();
-                assertTrue(pr != null);
-                mRS.bindProgramRaster(pr);
-            }
-        }
-    }
-
-    public void testPrebuiltProgramRaster() {
-        assertTrue(ProgramRaster.CULL_BACK(mRS) != null);
-        assertTrue(ProgramRaster.CULL_FRONT(mRS) != null);
-        assertTrue(ProgramRaster.CULL_NONE(mRS) != null);
-    }
-
-    public void testProgramRasterCullMode() {
-        assertEquals(CullMode.BACK, CullMode.valueOf("BACK"));
-        assertEquals(CullMode.FRONT, CullMode.valueOf("FRONT"));
-        assertEquals(CullMode.NONE, CullMode.valueOf("NONE"));
-        // Make sure no new enums are added
-        assertEquals(3, CullMode.values().length);
-    }
-}
diff --git a/tests/tests/rsg/src/android/renderscriptgraphics/cts/ProgramStoreTest.java b/tests/tests/rsg/src/android/renderscriptgraphics/cts/ProgramStoreTest.java
deleted file mode 100644
index e42f6fe..0000000
--- a/tests/tests/rsg/src/android/renderscriptgraphics/cts/ProgramStoreTest.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * 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.
- */
-
-package android.renderscriptgraphics.cts;
-
-import android.renderscript.ProgramStore;
-import android.renderscript.ProgramStore.DepthFunc;
-import android.renderscript.ProgramStore.BlendSrcFunc;
-import android.renderscript.ProgramStore.BlendDstFunc;
-
-public class ProgramStoreTest extends RSBaseGraphics {
-
-    void varyBuilderColorAndDither(ProgramStore.Builder pb) {
-        for (int r = 0; r <= 1; r++) {
-            boolean isR = (r == 1);
-            for (int g = 0; g <= 1; g++) {
-                boolean isG = (g == 1);
-                for (int b = 0; b <= 1; b++) {
-                    boolean isB = (b == 1);
-                    for (int a = 0; a <= 1; a++) {
-                        boolean isA = (a == 1);
-                        for (int dither = 0; dither <= 1; dither++) {
-                            boolean isDither = (dither == 1);
-                            pb.setDitherEnabled(isDither);
-                            pb.setColorMaskEnabled(isR, isG, isB, isA);
-                            ProgramStore ps = pb.create();
-                            assertTrue(ps != null);
-                            mRS.bindProgramStore(ps);
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    public void testProgramStoreBuilder() {
-        for (int depth = 0; depth <= 1; depth++) {
-            boolean depthMask = (depth == 1);
-            for (DepthFunc df : DepthFunc.values()) {
-                for (BlendSrcFunc bsf : BlendSrcFunc.values()) {
-                    for (BlendDstFunc bdf : BlendDstFunc.values()) {
-                        ProgramStore.Builder b = new ProgramStore.Builder(mRS);
-                        b.setDepthFunc(df);
-                        b.setDepthMaskEnabled(depthMask);
-                        b.setBlendFunc(bsf, bdf);
-                        varyBuilderColorAndDither(b);
-                    }
-                }
-            }
-        }
-    }
-
-    public void testPrebuiltProgramStore() {
-        assertTrue(ProgramStore.BLEND_ALPHA_DEPTH_NONE(mRS) != null);
-        assertTrue(ProgramStore.BLEND_ALPHA_DEPTH_TEST(mRS) != null);
-        assertTrue(ProgramStore.BLEND_NONE_DEPTH_NONE(mRS) != null);
-        assertTrue(ProgramStore.BLEND_NONE_DEPTH_TEST(mRS) != null);
-    }
-
-    public void testProgramStoreBlendDstFunc() {
-        assertEquals(BlendDstFunc.ZERO,
-                     BlendDstFunc.valueOf("ZERO"));
-        assertEquals(BlendDstFunc.ONE,
-                     BlendDstFunc.valueOf("ONE"));
-        assertEquals(BlendDstFunc.SRC_COLOR,
-                     BlendDstFunc.valueOf("SRC_COLOR"));
-        assertEquals(BlendDstFunc.ONE_MINUS_SRC_COLOR,
-                     BlendDstFunc.valueOf("ONE_MINUS_SRC_COLOR"));
-        assertEquals(BlendDstFunc.SRC_ALPHA,
-                     BlendDstFunc.valueOf("SRC_ALPHA"));
-        assertEquals(BlendDstFunc.ONE_MINUS_SRC_ALPHA,
-                     BlendDstFunc.valueOf("ONE_MINUS_SRC_ALPHA"));
-        assertEquals(BlendDstFunc.DST_ALPHA,
-                     BlendDstFunc.valueOf("DST_ALPHA"));
-        assertEquals(BlendDstFunc.ONE_MINUS_DST_ALPHA,
-                     BlendDstFunc.valueOf("ONE_MINUS_DST_ALPHA"));
-        // Make sure no new enums are added
-        assertEquals(8, BlendDstFunc.values().length);
-    }
-
-    public void testProgramStoreBlendSrcFunc() {
-        assertEquals(BlendSrcFunc.ZERO,
-                     BlendSrcFunc.valueOf("ZERO"));
-        assertEquals(BlendSrcFunc.ONE,
-                     BlendSrcFunc.valueOf("ONE"));
-        assertEquals(BlendSrcFunc.DST_COLOR,
-                     BlendSrcFunc.valueOf("DST_COLOR"));
-        assertEquals(BlendSrcFunc.ONE_MINUS_DST_COLOR,
-                     BlendSrcFunc.valueOf("ONE_MINUS_DST_COLOR"));
-        assertEquals(BlendSrcFunc.SRC_ALPHA,
-                     BlendSrcFunc.valueOf("SRC_ALPHA"));
-        assertEquals(BlendSrcFunc.ONE_MINUS_SRC_ALPHA,
-                     BlendSrcFunc.valueOf("ONE_MINUS_SRC_ALPHA"));
-        assertEquals(BlendSrcFunc.DST_ALPHA,
-                     BlendSrcFunc.valueOf("DST_ALPHA"));
-        assertEquals(BlendSrcFunc.ONE_MINUS_DST_ALPHA,
-                     BlendSrcFunc.valueOf("ONE_MINUS_DST_ALPHA"));
-        assertEquals(BlendSrcFunc.SRC_ALPHA_SATURATE,
-                     BlendSrcFunc.valueOf("SRC_ALPHA_SATURATE"));
-        // Make sure no new enums are added
-        assertEquals(9, BlendSrcFunc.values().length);
-    }
-    public void testProgramStoreDepthFunc() {
-        assertEquals(DepthFunc.ALWAYS,
-                     DepthFunc.valueOf("ALWAYS"));
-        assertEquals(DepthFunc.LESS,
-                     DepthFunc.valueOf("LESS"));
-        assertEquals(DepthFunc.LESS_OR_EQUAL,
-                     DepthFunc.valueOf("LESS_OR_EQUAL"));
-        assertEquals(DepthFunc.GREATER,
-                     DepthFunc.valueOf("GREATER"));
-        assertEquals(DepthFunc.GREATER_OR_EQUAL,
-                     DepthFunc.valueOf("GREATER_OR_EQUAL"));
-        assertEquals(DepthFunc.EQUAL,
-                     DepthFunc.valueOf("EQUAL"));
-        assertEquals(DepthFunc.NOT_EQUAL,
-                     DepthFunc.valueOf("NOT_EQUAL"));
-        // Make sure no new enums are added
-        assertEquals(7, DepthFunc.values().length);
-    }
-}
-
-
diff --git a/tests/tests/rsg/src/android/renderscriptgraphics/cts/ProgramVertexFixedFunctionTest.java b/tests/tests/rsg/src/android/renderscriptgraphics/cts/ProgramVertexFixedFunctionTest.java
deleted file mode 100644
index a50a9d5..0000000
--- a/tests/tests/rsg/src/android/renderscriptgraphics/cts/ProgramVertexFixedFunctionTest.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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.
- */
-
-package android.renderscriptgraphics.cts;
-
-import com.android.cts.stub.R;
-
-import android.renderscript.ProgramVertexFixedFunction;
-import android.renderscript.ProgramVertexFixedFunction.Builder;
-import android.renderscript.ScriptC;
-import android.renderscript.Matrix4f;
-
-public class ProgramVertexFixedFunctionTest extends RSBaseGraphics {
-
-    ScriptC_graphics_runner mScript;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mScript = new ScriptC_graphics_runner(mRS, mRes, R.raw.graphics_runner);
-        mRS.bindRootScript(mScript);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        mRS.bindRootScript(null);
-        super.tearDown();
-    }
-
-    public void testConstants() {
-        ProgramVertexFixedFunction.Constants pva;
-        for (int isM = 0; isM <= 1; isM++) {
-            for (int isP = 0; isP <= 1; isP++) {
-                for (int isT = 0; isT <= 1; isT++) {
-                    pva = new ProgramVertexFixedFunction.Constants(mRS);
-                    if (isM == 1) {
-                        pva.setModelview(new Matrix4f());
-                    }
-                    if (isP == 1) {
-                        pva.setProjection(new Matrix4f());
-                    }
-                    if (isT == 1) {
-                        pva.setTexture(new Matrix4f());
-                    }
-                    pva.destroy();
-                }
-            }
-        }
-    }
-
-    void testProgramVertexFixedFunctionBuilder(boolean testBind) {
-        ProgramVertexFixedFunction.Constants pva;
-        pva = new ProgramVertexFixedFunction.Constants(mRS);
-
-        ProgramVertexFixedFunction.Builder b;
-        b = new ProgramVertexFixedFunction.Builder(mRS);
-        b.setTextureMatrixEnable(false);
-        ProgramVertexFixedFunction pv = b.create();
-        assertTrue(pv != null);
-        pv.bindConstants(pva);
-        if (testBind) {
-            mScript.invoke_testProgramVertex(pv);
-        }
-        pv.destroy();
-        b.setTextureMatrixEnable(true);
-        pv = b.create();
-        assertTrue(pv != null);
-        pv.bindConstants(pva);
-        if (testBind) {
-            mScript.invoke_testProgramVertex(pv);
-        }
-        pv.destroy();
-    }
-
-    public void testProgramVertexFixedFunctionBuilder() {
-        testProgramVertexFixedFunctionBuilder(false);
-        testProgramVertexFixedFunctionBuilder(true);
-    }
-
-}
diff --git a/tests/tests/rsg/src/android/renderscriptgraphics/cts/ProgramVertexTest.java b/tests/tests/rsg/src/android/renderscriptgraphics/cts/ProgramVertexTest.java
deleted file mode 100644
index 7f23bd0..0000000
--- a/tests/tests/rsg/src/android/renderscriptgraphics/cts/ProgramVertexTest.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * 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.
- */
-
-package android.renderscriptgraphics.cts;
-
-import com.android.cts.stub.R;
-
-import android.renderscript.Allocation;
-import android.renderscript.Element;
-import android.renderscript.Program;
-import android.renderscript.ProgramVertex;
-
-public class ProgramVertexTest extends RSBaseGraphics {
-
-    ScriptC_graphics_runner mScript;
-    Element mAttrPosElem;
-    Element mAttrNormTexElem;
-    Element mAttrPosNormTexElem;
-    Element mAttrExtra;
-
-    Allocation mConstMatrix;
-    Allocation mConstComplex;
-    Allocation mConstExtra;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        // Build elements for shader inputs
-        Element.Builder eb = new Element.Builder(mRS);
-        eb.add(Element.F32_4(mRS), "position");
-        mAttrPosElem = eb.create();
-
-        eb = new Element.Builder(mRS);
-        eb.add(Element.F32_3(mRS), "normal");
-        eb.add(Element.F32_2(mRS), "texture0");
-        mAttrNormTexElem = eb.create();
-
-        eb = new Element.Builder(mRS);
-        eb.add(Element.F32_4(mRS), "position");
-        eb.add(Element.F32_3(mRS), "normal");
-        eb.add(Element.F32_2(mRS), "texture0");
-        mAttrPosNormTexElem = eb.create();
-
-        eb.add(Element.F32(mRS), "extra1");
-        eb.add(Element.F32_2(mRS), "extra2");
-        eb.add(Element.F32_3(mRS), "extra3");
-        eb.add(Element.F32_4(mRS), "extra4");
-        mAttrExtra = eb.create();
-
-        ScriptField_ConstMatrix c1 = new ScriptField_ConstMatrix(mRS, 1,
-                                                                 Allocation.USAGE_SCRIPT |
-                                                                 Allocation.USAGE_GRAPHICS_CONSTANTS);
-        c1.set(new ScriptField_ConstMatrix.Item(), 0, true);
-        mConstMatrix = c1.getAllocation();
-
-        ScriptField_ConstComplex c2 = new ScriptField_ConstComplex(mRS, 1,
-                                                                   Allocation.USAGE_SCRIPT |
-                                                                   Allocation.USAGE_GRAPHICS_CONSTANTS);
-        c2.set(new ScriptField_ConstComplex.Item(), 0, true);
-        mConstComplex = c2.getAllocation();
-
-        ScriptField_ConstExtra c3 = new ScriptField_ConstExtra(mRS, 1,
-                                                               Allocation.USAGE_SCRIPT |
-                                                               Allocation.USAGE_GRAPHICS_CONSTANTS);
-        c3.set(new ScriptField_ConstExtra.Item(), 0, true);
-        mConstExtra = c3.getAllocation();
-
-        mScript = new ScriptC_graphics_runner(mRS, mRes, R.raw.graphics_runner);
-        mRS.bindRootScript(mScript);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        mRS.bindRootScript(null);
-        super.tearDown();
-    }
-
-    ProgramVertex buildShader(Element[] input, Allocation[] constInput, String shader) {
-        ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS);
-        Program.BaseProgramBuilder bpb = pvb;
-        if (input != null) {
-            for (int i = 0; i < input.length; i++) {
-                pvb.addInput(input[i]);
-            }
-        }
-        if (constInput != null) {
-            for (int i = 0; i < constInput.length; i++) {
-                // Add constants through the base builder class to
-                // tick cts test coverage (doesn't register through subclass)
-                bpb.addConstant(constInput[i].getType());
-                bpb.getCurrentConstantIndex();
-            }
-        }
-
-        bpb.setShader(shader);
-        ProgramVertex pv = pvb.create();
-        if (constInput != null) {
-            for (int i = 0; i < constInput.length; i++) {
-                pv.bindConstants(constInput[i], i);
-                // Go through the base class code as well
-                Program p = pv;
-                p.bindConstants(constInput[i], i);
-            }
-        }
-        return pv;
-    }
-
-    void testProgramVertexBuilderHelper(boolean testBind) {
-        String simpleAttr = "void main() {\n"+
-                            "  gl_Position = ATTRIB_position;\n"+
-                            "}";
-
-        String multiAttr = "void main() {\n"+
-                           "  vec4 temp = ATTRIB_position;\n"+
-                           "  temp.xyz += ATTRIB_normal;\n"+
-                           "  temp.xy += ATTRIB_texture0;\n"+
-                           "  gl_Position = temp;\n"+
-                           "}";
-
-        String multiAttr2 = "void main() {\n"+
-                            "  vec4 temp = ATTRIB_position;\n"+
-                            "  temp.xyz += ATTRIB_normal;\n"+
-                            "  temp.xy += ATTRIB_texture0;\n"+
-                            "  temp += ATTRIB_extra4;\n"+
-                            "  temp.xyz += ATTRIB_extra3;\n "+
-                            "  temp.xy += ATTRIB_extra2;\n"+
-                            "  temp.x += ATTRIB_extra1;\n"+
-                            "  gl_Position = temp;\n"+
-                            "}";
-
-        String simpleAttrSimpleUni = "void main() {\n"+
-                                     "  gl_Position = UNI_MATRIX * ATTRIB_position;\n"+
-                                     "}";
-
-        String multiAttrMultiUni = "void main() {\n"+
-                                   "  vec4 temp = UNI_MATRIX * ATTRIB_position;\n"+
-                                   "  temp = UNI_EXTRA * temp;\n"+
-                                   "  temp.xyz += ATTRIB_normal;\n"+
-                                   "  temp.xy += ATTRIB_texture0;\n"+
-                                   "  temp += UNI_extra4;\n"+
-                                   "  temp.xyz += UNI_extra3;\n "+
-                                   "  temp.xy += UNI_extra2;\n"+
-                                   "  temp.x += UNI_extra1;\n"+
-                                   "  gl_Position = temp;\n"+
-                                   "}";
-
-        // Create a series of shaders that do nothing useful
-        // but exercise creation pipeline
-        Element[] inputs = new Element[1];
-        inputs[0] = mAttrPosElem;
-        ProgramVertex pv = buildShader(inputs, null, simpleAttr);
-        if (testBind) {
-            mScript.invoke_testProgramVertex(pv);
-            mRS.bindProgramVertex(pv);
-        }
-
-        inputs[0] = mAttrPosNormTexElem;
-        pv = buildShader(inputs, null, multiAttr);
-        if (testBind) {
-            mScript.invoke_testProgramVertex(pv);
-            mRS.bindProgramVertex(pv);
-        }
-
-        inputs[0] = mAttrExtra;
-        pv = buildShader(inputs, null, multiAttr2);
-        if (testBind) {
-            mScript.invoke_testProgramVertex(pv);
-            mRS.bindProgramVertex(pv);
-        }
-
-        // Now with constant inputs
-        Allocation[] constInput = new Allocation[1];
-        inputs[0] = mAttrPosElem;
-        constInput[0] = mConstMatrix;
-        pv = buildShader(inputs, constInput, simpleAttrSimpleUni);
-        if (testBind) {
-            mScript.invoke_testProgramVertex(pv);
-            mRS.bindProgramVertex(pv);
-        }
-
-        inputs[0] = mAttrPosNormTexElem;
-        constInput[0] = mConstComplex;
-        pv = buildShader(inputs, constInput, multiAttrMultiUni);
-        if (testBind) {
-            mScript.invoke_testProgramVertex(pv);
-            mRS.bindProgramVertex(pv);
-        }
-
-        // Now with multiple input and const structs
-        constInput = new Allocation[2];
-        constInput[0] = mConstMatrix;
-        constInput[1] = mConstExtra;
-        inputs[0] = mAttrPosNormTexElem;
-        pv = buildShader(inputs, constInput, multiAttrMultiUni);
-        if (testBind) {
-            mScript.invoke_testProgramVertex(pv);
-            mRS.bindProgramVertex(pv);
-        }
-
-        inputs = new Element[2];
-        inputs[0] = mAttrPosElem;
-        inputs[1] = mAttrNormTexElem;
-        pv = buildShader(inputs, null, multiAttr);
-        if (testBind) {
-            mScript.invoke_testProgramVertex(pv);
-            mRS.bindProgramVertex(pv);
-        }
-
-        constInput[0] = mConstMatrix;
-        constInput[1] = mConstExtra;
-        inputs[0] = mAttrPosElem;
-        inputs[1] = mAttrNormTexElem;
-        pv = buildShader(inputs, constInput, multiAttrMultiUni);
-        if (testBind) {
-            mScript.invoke_testProgramVertex(pv);
-            mRS.bindProgramVertex(pv);
-        }
-    }
-
-    public void testProgramVertexBuilder() {
-        testProgramVertexBuilderHelper(false);
-    }
-
-    public void testProgramVertexCreation() {
-        testProgramVertexBuilderHelper(true);
-    }
-}
-
-
diff --git a/tests/tests/rsg/src/android/renderscriptgraphics/cts/RSBase.java b/tests/tests/rsg/src/android/renderscriptgraphics/cts/RSBase.java
deleted file mode 100644
index 7729e1e..0000000
--- a/tests/tests/rsg/src/android/renderscriptgraphics/cts/RSBase.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2011-2012 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.renderscriptgraphics.cts;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.renderscript.RenderScript.RSErrorHandler;
-import android.renderscript.RenderScript.RSMessageHandler;
-import android.renderscript.RSRuntimeException;
-import android.test.AndroidTestCase;
-import android.util.Log;
-
-/**
- * Base RenderScript test class. This class provides a message handler and a
- * convenient way to wait for compute scripts to complete their execution.
- */
-class RSBase extends AndroidTestCase {
-
-    Context mCtx;
-    Resources mRes;
-
-    private int result;
-    private boolean msgHandled;
-
-    private static final int RS_MSG_TEST_PASSED = 100;
-    private static final int RS_MSG_TEST_FAILED = 101;
-
-    RSMessageHandler mRsMessage = new RSMessageHandler() {
-        public void run() {
-            if (result == 0) {
-                switch (mID) {
-                    case RS_MSG_TEST_PASSED:
-                    case RS_MSG_TEST_FAILED:
-                        result = mID;
-                        break;
-                    default:
-                        fail("Got unexpected RS message");
-                        return;
-                }
-            }
-            msgHandled = true;
-        }
-    };
-
-    protected void waitForMessage() {
-        while (!msgHandled) {
-            Thread.yield();
-        }
-    }
-
-    protected boolean FoundError = false;
-    protected RSErrorHandler mRsError = new RSErrorHandler() {
-        public void run() {
-            FoundError = true;
-            Log.e("RenderscriptCTS", mErrorMessage);
-            throw new RSRuntimeException("Received error " + mErrorNum +
-                                         " message " + mErrorMessage);
-        }
-    };
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        result = 0;
-        msgHandled = false;
-        mCtx = getContext();
-        mRes = mCtx.getResources();
-    }
-
-    /**
-     * Verify that we didn't fail on the control or script side of things.
-     */
-    protected void checkForErrors() {
-        assertFalse(FoundError);
-        assertTrue(result != RS_MSG_TEST_FAILED);
-    }
-}
diff --git a/tests/tests/rsg/src/android/renderscriptgraphics/cts/RSBaseGraphics.java b/tests/tests/rsg/src/android/renderscriptgraphics/cts/RSBaseGraphics.java
deleted file mode 100644
index 65ba926..0000000
--- a/tests/tests/rsg/src/android/renderscriptgraphics/cts/RSBaseGraphics.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.
- */
-
-package android.renderscriptgraphics.cts;
-
-import android.renderscript.RenderScriptGL;
-import android.renderscript.RenderScriptGL.SurfaceConfig;
-
-/**
- * Base RenderScript test class. This class provides a message handler and a
- * convenient way to wait for compute scripts to complete their execution.
- */
-class RSBaseGraphics extends RSBase {
-    RenderScriptGL mRS;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mRS = new RenderScriptGL(mCtx, new SurfaceConfig());
-        mRS.setMessageHandler(mRsMessage);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        if (mRS != null) {
-            mRS.destroy();
-            mRS = null;
-        }
-        super.tearDown();
-    }
-
-}
diff --git a/tests/tests/rsg/src/android/renderscriptgraphics/cts/RSSurfaceViewTest.java b/tests/tests/rsg/src/android/renderscriptgraphics/cts/RSSurfaceViewTest.java
deleted file mode 100644
index 4d46d8d..0000000
--- a/tests/tests/rsg/src/android/renderscriptgraphics/cts/RSSurfaceViewTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.
- */
-
-package android.renderscriptgraphics.cts;
-
-import android.renderscript.RSSurfaceView;
-import android.renderscript.RenderScriptGL;
-import android.renderscript.RenderScriptGL.SurfaceConfig;
-import android.util.AttributeSet;
-
-public class RSSurfaceViewTest extends RSBaseGraphics {
-
-    public void testCreation() {
-        RSSurfaceView view = new RSSurfaceView(mCtx);
-        view = new RSSurfaceView(mCtx, null);
-    }
-
-    public void testCreateRenderScriptGL() {
-        RSSurfaceView view = new RSSurfaceView(mCtx);
-        RenderScriptGL rs = view.createRenderScriptGL(new SurfaceConfig());
-        assertTrue(rs != null);
-    }
-
-    public void testGetSetRenderScriptGL() {
-        RSSurfaceView view = new RSSurfaceView(mCtx);
-        RenderScriptGL rs = view.createRenderScriptGL(new SurfaceConfig());
-        assertTrue(rs != null);
-        assertEquals(view.getRenderScriptGL(), rs);
-
-        view = new RSSurfaceView(mCtx);
-        view.setRenderScriptGL(mRS);
-        assertEquals(view.getRenderScriptGL(), mRS);
-    }
-
-    public void testDestroyRenderScriptGL() {
-        RSSurfaceView view = new RSSurfaceView(mCtx);
-        RenderScriptGL rs = view.createRenderScriptGL(new SurfaceConfig());
-        assertTrue(rs != null);
-        view.destroyRenderScriptGL();
-        assertTrue(view.getRenderScriptGL() == null);
-    }
-
-    public void testPauseResume() {
-        RSSurfaceView view = new RSSurfaceView(mCtx);
-        view.pause();
-        view.resume();
-
-        view.setRenderScriptGL(mRS);
-        view.pause();
-        view.resume();
-    }
-}
-
-
diff --git a/tests/tests/rsg/src/android/renderscriptgraphics/cts/RenderscriptGLStubActivity.java b/tests/tests/rsg/src/android/renderscriptgraphics/cts/RenderscriptGLStubActivity.java
deleted file mode 100644
index bddde03..0000000
--- a/tests/tests/rsg/src/android/renderscriptgraphics/cts/RenderscriptGLStubActivity.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * 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.
- */
-
-package android.renderscriptgraphics.cts;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.content.Context;
-import android.content.res.Resources;
-import android.renderscript.*;
-
-import com.android.cts.stub.R;
-
-// Renderscript activity
-public class RenderscriptGLStubActivity extends Activity {
-    class StubActivityRS {
-        private Resources mRes;
-        private RenderScriptGL mRS;
-
-        private ScriptC mScript;
-
-        public StubActivityRS() {
-        }
-
-        // This provides us with the renderscript context and resources that
-        // allow us to create the script that does rendering
-        public void init(RenderScriptGL rs, Resources res) {
-            mRS = rs;
-            mRes = res;
-            initRS();
-        }
-
-        private void initRS() {
-            mScript = new ScriptC_stub_activity(mRS, mRes, R.raw.stub_activity);
-            mRS.bindRootScript(mScript);
-        }
-    }
-
-    class HelloWorldView extends RSSurfaceView {
-        // Renderscipt context
-        private RenderScriptGL mRS;
-        // Script that does the rendering
-        private StubActivityRS mRender;
-
-        public HelloWorldView(Context context) {
-            super(context);
-            ensureRenderScript();
-        }
-
-        private void ensureRenderScript() {
-            if (mRS == null) {
-                // Initialize renderscript with desired surface characteristics.
-                // In this case, just use the defaults
-                RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
-                mRS = createRenderScriptGL(sc);
-                // Create an instance of the script that does the rendering
-                mRender = new StubActivityRS();
-                mRender.init(mRS, getResources());
-            }
-        }
-
-        @Override
-        protected void onAttachedToWindow() {
-            super.onAttachedToWindow();
-            ensureRenderScript();
-        }
-
-        @Override
-        protected void onDetachedFromWindow() {
-            // Handle the system event and clean up
-            mRender = null;
-            if (mRS != null) {
-                mRS = null;
-                destroyRenderScriptGL();
-            }
-        }
-
-        public void forceDestroy() {
-            onDetachedFromWindow();
-        }
-    }
-
-    // Custom view to use with RenderScript
-    private HelloWorldView mView;
-    private HelloWorldView mView2;
-
-    @Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-
-        // Create our view and set it as the content of our Activity
-        mView = new HelloWorldView(this);
-        setContentView(mView);
-    }
-
-    public void recreateView() {
-        HelloWorldView oldView = mView;
-        mView = new HelloWorldView(this);
-        setContentView(mView);
-        oldView.forceDestroy();
-    }
-
-    public void destroyAll() {
-        if (mView != null) {
-            mView.forceDestroy();
-        }
-        if (mView2 != null) {
-            mView2.forceDestroy();
-        }
-    }
-
-    public void recreateMultiView() {
-        HelloWorldView oldView = mView;
-        mView = new HelloWorldView(this);
-        mView2 = new HelloWorldView(this);
-        setContentView(mView);
-        setContentView(mView2);
-        oldView.forceDestroy();
-    }
-
-    @Override
-    protected void onResume() {
-        // Ideally an app should implement onResume() and onPause()
-        // to take appropriate action when the activity loses focus
-        super.onResume();
-        mView.resume();
-    }
-
-    @Override
-    protected void onPause() {
-        // Ideally an app should implement onResume() and onPause()
-        // to take appropriate action when the activity loses focus
-        super.onPause();
-        mView.pause();
-    }
-
-}
-
diff --git a/tests/tests/rsg/src/android/renderscriptgraphics/cts/SurfaceConfigTest.java b/tests/tests/rsg/src/android/renderscriptgraphics/cts/SurfaceConfigTest.java
deleted file mode 100644
index a402e8a..0000000
--- a/tests/tests/rsg/src/android/renderscriptgraphics/cts/SurfaceConfigTest.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * 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.
- */
-
-package android.renderscriptgraphics.cts;
-import android.test.AndroidTestCase;
-
-import android.renderscript.RSIllegalArgumentException;
-import android.renderscript.RenderScriptGL.SurfaceConfig;
-
-public class SurfaceConfigTest extends AndroidTestCase {
-
-    public void testSimpleCreate() {
-        SurfaceConfig sc = new SurfaceConfig();
-    }
-
-    public void testSetColor() {
-        SurfaceConfig sc = new SurfaceConfig();
-        try {
-            sc.setColor(-1, 8);
-            fail("should throw RSIllegalArgumentException.");
-        } catch (RSIllegalArgumentException e) {
-        }
-        sc = new SurfaceConfig();
-        try {
-            sc.setColor(9, 8);
-            fail("should throw RSIllegalArgumentException.");
-        } catch (RSIllegalArgumentException e) {
-        }
-        sc = new SurfaceConfig();
-        try {
-            sc.setColor(5, -1);
-            fail("should throw RSIllegalArgumentException.");
-        } catch (RSIllegalArgumentException e) {
-        }
-        sc = new SurfaceConfig();
-        sc.setColor(5, 8);
-        sc = new SurfaceConfig();
-        sc.setColor(8, 8);
-    }
-
-    public void testSetAlpha() {
-        SurfaceConfig sc = new SurfaceConfig();
-        try {
-            sc.setAlpha(-1, 8);
-            fail("should throw RSIllegalArgumentException.");
-        } catch (RSIllegalArgumentException e) {
-        }
-        sc = new SurfaceConfig();
-        try {
-            sc.setAlpha(9, 8);
-            fail("should throw RSIllegalArgumentException.");
-        } catch (RSIllegalArgumentException e) {
-        }
-        sc = new SurfaceConfig();
-        try {
-            sc.setAlpha(0, -1);
-            fail("should throw RSIllegalArgumentException.");
-        } catch (RSIllegalArgumentException e) {
-        }
-        sc = new SurfaceConfig();
-        sc.setAlpha(0, 8);
-        sc = new SurfaceConfig();
-        sc.setAlpha(8, 8);
-    }
-
-    public void testSetDepth() {
-        SurfaceConfig sc = new SurfaceConfig();
-        try {
-            sc.setDepth(-1, 8);
-            fail("should throw RSIllegalArgumentException.");
-        } catch (RSIllegalArgumentException e) {
-        }
-        sc = new SurfaceConfig();
-        try {
-            sc.setDepth(45, 8);
-            fail("should throw RSIllegalArgumentException.");
-        } catch (RSIllegalArgumentException e) {
-        }
-        sc = new SurfaceConfig();
-        try {
-            sc.setDepth(0, -1);
-            fail("should throw RSIllegalArgumentException.");
-        } catch (RSIllegalArgumentException e) {
-        }
-        sc = new SurfaceConfig();
-        sc.setDepth(0, 16);
-        sc = new SurfaceConfig();
-        sc.setDepth(16, 24);
-        sc = new SurfaceConfig();
-        sc.setDepth(24, 24);
-    }
-
-    public void testSetSamples() {
-        SurfaceConfig sc = new SurfaceConfig();
-        try {
-            sc.setSamples(-1, 8, 1.0f);
-            fail("should throw RSIllegalArgumentException.");
-        } catch (RSIllegalArgumentException e) {
-        }
-        sc = new SurfaceConfig();
-        try {
-            sc.setSamples(45, 8, 1.0f);
-            fail("should throw RSIllegalArgumentException.");
-        } catch (RSIllegalArgumentException e) {
-        }
-        sc = new SurfaceConfig();
-        try {
-            sc.setSamples(1, -1, 1.0f);
-            fail("should throw RSIllegalArgumentException.");
-        } catch (RSIllegalArgumentException e) {
-        }
-        sc = new SurfaceConfig();
-        try {
-            sc.setSamples(1, 1, -1.0f);
-            fail("should throw RSIllegalArgumentException.");
-        } catch (RSIllegalArgumentException e) {
-        }
-        sc = new SurfaceConfig();
-        try {
-            sc.setSamples(1, 1, 10.0f);
-            fail("should throw RSIllegalArgumentException.");
-        } catch (RSIllegalArgumentException e) {
-        }
-        sc = new SurfaceConfig();
-        sc.setSamples(1, 4, 1.0f);
-        sc = new SurfaceConfig();
-        sc.setSamples(4, 32, 1.0f);
-        sc = new SurfaceConfig();
-        sc.setSamples(4, 64, 0.5f);
-    }
-
-    public void testCopyConstructor() {
-        SurfaceConfig sc = new SurfaceConfig();
-        sc.setAlpha(1, 7);
-        sc.setColor(5, 8);
-        sc.setDepth(0, 16);
-        sc.setSamples(1, 4, 0.71f);
-        SurfaceConfig sc2 = new SurfaceConfig(sc);
-    }
-
-}
diff --git a/tests/tests/sax/Android.mk b/tests/tests/sax/Android.mk
index 5270ae5..a468778 100644
--- a/tests/tests/sax/Android.mk
+++ b/tests/tests/sax/Android.mk
@@ -21,14 +21,12 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsSaxTestCases
 
-LOCAL_INSTRUMENTATION_FOR := CtsTestStubs
+LOCAL_SDK_VERSION := current
 
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/sax/AndroidManifest.xml b/tests/tests/sax/AndroidManifest.xml
index 4fbf840..63c568b 100644
--- a/tests/tests/sax/AndroidManifest.xml
+++ b/tests/tests/sax/AndroidManifest.xml
@@ -22,8 +22,11 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="com.android.cts.stub"
-                     android:label="CTS tests of android.sax"/>
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.sax"
+                     android:label="CTS tests of android.sax">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
diff --git a/tests/tests/security/Android.mk b/tests/tests/security/Android.mk
index f36be9d..de58783 100644
--- a/tests/tests/security/Android.mk
+++ b/tests/tests/security/Android.mk
@@ -18,20 +18,38 @@
 
 LOCAL_MODULE_TAGS := tests
 
+# Include both the 32 and 64 bit versions
+LOCAL_MULTILIB := both
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestserver ctstestrunner ctsdeviceutil guava
+
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_JNI_SHARED_LIBRARIES := libctssecurity_jni libcts_jni
 
-LOCAL_JNI_SHARED_LIBRARIES := libctssecurity_jni
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES := $(call all-java-files-under, src)\
+                   src/android/security/cts/activity/ISecureRandomService.aidl
 
 LOCAL_PACKAGE_NAME := CtsSecurityTestCases
 
-LOCAL_INSTRUMENTATION_FOR := CtsTestStubs
-
 LOCAL_SDK_VERSION := current
 
+intermediates.COMMON := $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),,COMMON)
+
+sepolicy_asset_dir := $(intermediates.COMMON)/assets
+
+LOCAL_ASSET_DIR := $(sepolicy_asset_dir)
+
 include $(BUILD_CTS_PACKAGE)
 
+selinux_policy.xml := $(sepolicy_asset_dir)/selinux_policy.xml
+selinux_policy_parser := cts/tools/selinux/src/gen_SELinux_CTS.py
+general_sepolicy_policy.conf := $(call intermediates-dir-for,ETC,general_sepolicy.conf)/general_sepolicy.conf
+$(selinux_policy.xml): PRIVATE_POLICY_PARSER := $(selinux_policy_parser)
+$(selinux_policy.xml): $(general_sepolicy_policy.conf) $(selinux_policy_parser)
+	mkdir -p $(dir $@)
+	$(PRIVATE_POLICY_PARSER) $< $@ neverallow_only=t
+
+$(R_file_stamp): $(selinux_policy.xml)
+
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/security/AndroidManifest.xml b/tests/tests/security/AndroidManifest.xml
index e47b045..8ed74ba 100644
--- a/tests/tests/security/AndroidManifest.xml
+++ b/tests/tests/security/AndroidManifest.xml
@@ -21,14 +21,26 @@
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
     <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
     <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.INTERNET" />
 
     <application>
         <uses-library android:name="android.test.runner" />
+
+        <service android:name="android.security.cts.SeccompDeathTestService"
+                 android:process=":death_test_service"
+                 android:isolatedProcess="true"
+                 android:exported="true"/>
+
+        <service android:name="android.security.cts.activity.SecureRandomService"
+                 android:process=":secureRandom"/>
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="com.android.cts.stub"
-                     android:label="CTS tests of com.android.cts.stub"/>
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.security"
+                     android:label="CTS tests of com.android.cts.security">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/tests/security/jni/Android.mk b/tests/tests/security/jni/Android.mk
index 8b7e62b..46d0868 100644
--- a/tests/tests/security/jni/Android.mk
+++ b/tests/tests/security/jni/Android.mk
@@ -26,14 +26,16 @@
 		android_security_cts_CharDeviceTest.cpp \
 		android_security_cts_KernelSettingsTest.cpp \
 		android_security_cts_LinuxRngTest.cpp \
-		android_security_cts_NativeCodeTest.cpp \
 		android_security_cts_LoadEffectLibraryTest.cpp \
 		android_security_cts_NativeCodeTest.cpp \
+		android_security_cts_SeccompDeathTestService.cpp \
 		android_security_cts_SELinuxTest.cpp \
+		android_security_cts_MMapExecutableTest.cpp \
+		android_security_cts_NetlinkSocket.cpp \
 		android_security_cts_AudioPolicyBinderTest.cpp
 
 LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
 
-LOCAL_SHARED_LIBRARIES := libnativehelper liblog libbinder libutils libmedia libselinux
+LOCAL_SHARED_LIBRARIES := libnativehelper liblog libbinder libutils libmedia libselinux libdl
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
index 8c511ef..ca8e841 100644
--- a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
+++ b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
@@ -16,13 +16,16 @@
 
 #include <jni.h>
 #include <stdio.h>
+#include "android_security_cts_NetlinkSocket.h"
 
 extern int register_android_security_cts_KernelSettingsTest(JNIEnv*);
 extern int register_android_security_cts_CharDeviceTest(JNIEnv*);
 extern int register_android_security_cts_LinuxRngTest(JNIEnv*);
 extern int register_android_security_cts_NativeCodeTest(JNIEnv*);
 extern int register_android_security_cts_LoadEffectLibraryTest(JNIEnv*);
+extern int register_android_security_cts_SeccompDeathTestService(JNIEnv*);
 extern int register_android_security_cts_SELinuxTest(JNIEnv*);
+extern int register_android_security_cts_MMapExecutableTest(JNIEnv* env);
 extern int register_android_security_cts_AudioPolicyBinderTest(JNIEnv* env);
 
 jint JNI_OnLoad(JavaVM *vm, void *reserved) {
@@ -48,6 +51,10 @@
         return JNI_ERR;
     }
 
+    if (register_android_security_cts_SeccompDeathTestService(env)) {
+        return JNI_ERR;
+    }
+
     if (register_android_security_cts_SELinuxTest(env)) {
         return JNI_ERR;
     }
@@ -56,6 +63,14 @@
         return JNI_ERR;
     }
 
+    if (register_android_security_cts_MMapExecutableTest(env)) {
+        return JNI_ERR;
+    }
+
+    if (register_android_security_cts_NetlinkSocket(env)) {
+        return JNI_ERR;
+    }
+
     if (register_android_security_cts_AudioPolicyBinderTest(env)) {
         return JNI_ERR;
     }
diff --git a/tests/tests/security/jni/android_security_cts_MMapExecutableTest.cpp b/tests/tests/security/jni/android_security_cts_MMapExecutableTest.cpp
new file mode 100644
index 0000000..c187526
--- /dev/null
+++ b/tests/tests/security/jni/android_security_cts_MMapExecutableTest.cpp
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ *
+ */
+
+#define LOG_TAG "MMapExecutableTest"
+
+#include <android/log.h>
+#include <cutils/log.h>
+#include <fcntl.h>
+#include <jni.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedUtfChars.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+const size_t kOffset = 4096;
+
+// Verify that we can mmap a region of a file with a non-zero offset executable
+static jboolean mmap_executable(JNIEnv *env, jobject, jstring jfilename) {
+    if (jfilename == NULL) {
+        jniThrowNullPointerException(env, NULL);
+        return false;
+    }
+
+    ScopedUtfChars filename(env, jfilename);
+    int fd = open(filename.c_str(), O_RDONLY);
+    if (fd == -1) {
+        ALOGE("open %s: %s", filename.c_str(), strerror(errno));
+        return false;
+    }
+
+    struct stat stat_buf;
+    if (fstat(fd, &stat_buf) == -1) {
+        ALOGE("fstat %s: %s", filename.c_str(), strerror(errno));
+        return false;
+    }
+
+    if (stat_buf.st_size < kOffset) {
+        ALOGE("file %s is too small", filename.c_str());
+        return false;
+    }
+
+    void * mem =
+            mmap(NULL, stat_buf.st_size - kOffset,
+                 PROT_EXEC | PROT_READ, MAP_PRIVATE, fd, kOffset);
+    if (mem == MAP_FAILED) {
+        ALOGE("mmap %s: %s", filename.c_str(), strerror(errno));
+        return false;
+    }
+
+    if (munmap(mem, stat_buf.st_size - kOffset) == -1) {
+        ALOGE("munmap %s: %s", filename.c_str(), strerror(errno));
+        return false;
+    }
+
+    return true;
+}
+
+static JNINativeMethod gMethods[] = {
+    { (char*)"mmapExecutable",
+      (char*)"(Ljava/lang/String;)Z", (void *)mmap_executable }
+};
+
+int register_android_security_cts_MMapExecutableTest(JNIEnv* env) {
+    jclass clazz = env->FindClass("android/security/cts/MMapExecutableTest");
+    return env->RegisterNatives(
+            clazz, gMethods, sizeof(gMethods) / sizeof(JNINativeMethod));
+}
diff --git a/tests/tests/security/jni/android_security_cts_NativeCodeTest.cpp b/tests/tests/security/jni/android_security_cts_NativeCodeTest.cpp
index 5c2a6b9..faa6eea 100644
--- a/tests/tests/security/jni/android_security_cts_NativeCodeTest.cpp
+++ b/tests/tests/security/jni/android_security_cts_NativeCodeTest.cpp
@@ -15,21 +15,18 @@
  */
 
 #include <jni.h>
-#include <netlink.h>
-#include <sock_diag.h>
+#include <linux/futex.h>
+#include <linux/netlink.h>
+#include <linux/sock_diag.h>
 #include <stdio.h>
 #include <sys/socket.h>
 #include <sys/types.h>
 #include <sys/syscall.h>
+#include <unistd.h>
 #include <sys/prctl.h>
 #include <sys/ptrace.h>
 #include <sys/wait.h>
 #include <signal.h>
-#include <unistd.h>
-#include <errno.h>
-
-#define PASSED 0
-#define UNKNOWN_ERROR -1
 #include <stdlib.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
@@ -37,15 +34,13 @@
 #include <fcntl.h>
 #include <cutils/log.h>
 #include <linux/perf_event.h>
-
-/*
- * work around conflicting __unused.
- * see https://android-review.googlesource.com/43479
- * TODO: remove in jb-mr2-dev
- */
-#undef __unused
+#include <errno.h>
+#include <inttypes.h>
 #include <linux/sysctl.h>
 
+#define PASSED 0
+#define UNKNOWN_ERROR -1
+
 /*
  * Returns true iff this device is vulnerable to CVE-2013-2094.
  * A patch for CVE-2013-2094 can be found at
@@ -95,92 +90,6 @@
 }
 
 /*
- * Prior to https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/arch/arm/include/asm/uaccess.h?id=8404663f81d212918ff85f493649a7991209fa04
- * there was a flaw in the kernel's handling of get_user and put_user
- * requests. Normally, get_user and put_user are supposed to guarantee
- * that reads/writes outside the process's address space are not
- * allowed.
- *
- * In this test, we use sysctl to force a read from an address outside
- * of our address space (but in the kernel's address space). Without the
- * patch applied, this read succeeds, because sysctl uses the
- * vulnerable get_user call.
- *
- * This function returns true if the patch above is applied, or false
- * otherwise.
- *
- * Credit: https://twitter.com/grsecurity/status/401443359912239105
- */
-static jboolean android_security_cts_NativeCodeTest_doVrootTest(JNIEnv*, jobject)
-{
-#ifdef __arm__
-    ALOGE("Starting doVrootTest");
-
-    struct __sysctl_args args;
-    char osname[100];
-    int name[] = { CTL_KERN, KERN_OSTYPE };
-
-    memset(&args, 0, sizeof(struct __sysctl_args));
-    args.name = name;
-    args.nlen = sizeof(name)/sizeof(name[0]);
-    args.oldval = osname;
-    args.oldlenp = (size_t *) 0xc0000000; // PAGE_OFFSET
-
-    int result = syscall(__NR__sysctl, &args);
-    return ((result == -1) && (errno == EFAULT));
-#else
-    return true;
-#endif
-}
-
-static void* mmap_syscall(void* addr, size_t len, int prot, int flags, int fd, off_t offset)
-{
-    return (void*) syscall(__NR_mmap2, addr, len, prot, flags, fd, offset);
-}
-
-#define KBASE_REG_COOKIE_TB         2
-#define KBASE_REG_COOKIE_MTP        3
-
-/*
- * Returns true if the device is immune to CVE-2014-1710,
- * false if the device is vulnerable.
- */
-static jboolean android_security_cts_NativeCodeTest_doCVE20141710Test(JNIEnv*, jobject)
-{
-    jboolean result = false;
-    int fd = open("/dev/mali0", O_RDWR);
-    if (fd < 0) {
-        return true; /* not vulnerable */
-    }
-
-    void* a = mmap_syscall(NULL, 0x1000, PROT_READ, MAP_SHARED, fd, KBASE_REG_COOKIE_MTP);
-    void* b = mmap_syscall(NULL, 0x1000, PROT_READ, MAP_SHARED, fd, KBASE_REG_COOKIE_TB);
-
-    if (a == MAP_FAILED) {
-        result = true; /* assume not vulnerable */
-        goto done;
-    }
-
-    if (b == MAP_FAILED) {
-        result = true; /* assume not vulnerable */
-        goto done;
-    }
-
-    /* mprotect should return an error if not vulnerable */
-    result = (mprotect(b, 0x1000, PROT_READ | PROT_WRITE) == -1);
-
- done:
-    if (a != MAP_FAILED) {
-        munmap(a, 0x1000);
-    }
-    if (b != MAP_FAILED) {
-        munmap(b, 0x1000);
-    }
-    close(fd);
-    return result;
-}
-
-/*
  * Will hang if vulnerable, return 0 if successful, -1 on unforseen
  * error.
  */
@@ -230,11 +139,7 @@
     iov = { (void *) nlh, nlmsg_size };
     msg = { (void *) &nladdr, sizeof(nladdr), &iov, 1, NULL, 0, 0 };
     sock_diag_data = (sock_diag_req *) NLMSG_DATA(nlh);
-
-    // AF_MAX changes in later kernels. Use hardcoded value instead
-    // to make sure we trigger the vulnerability in kernels <= 3.8
-    sock_diag_data->sdiag_family = 39+1; // AF_MAX+1, but don't rely on header file.
-
+    sock_diag_data->sdiag_family = AF_MAX+1;
     if ((err = sendmsg(fd, &msg, 0)) == -1) {
         /* SELinux blocked it */
         if (errno == 22) {
@@ -262,8 +167,95 @@
     return UNKNOWN_ERROR;
 }
 
-/* This isn't defined in linux/futex.h on JB */
-#define FUTEX_CMP_REQUEUE_PI    12
+/*
+ * Prior to https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/arch/arm/include/asm/uaccess.h?id=8404663f81d212918ff85f493649a7991209fa04
+ * there was a flaw in the kernel's handling of get_user and put_user
+ * requests. Normally, get_user and put_user are supposed to guarantee
+ * that reads/writes outside the process's address space are not
+ * allowed.
+ *
+ * In this test, we use sysctl to force a read from an address outside
+ * of our address space (but in the kernel's address space). Without the
+ * patch applied, this read succeeds, because sysctl uses the
+ * vulnerable get_user call.
+ *
+ * This function returns true if the patch above is applied, or false
+ * otherwise.
+ *
+ * Credit: https://twitter.com/grsecurity/status/401443359912239105
+ */
+static jboolean android_security_cts_NativeCodeTest_doVrootTest(JNIEnv*, jobject)
+{
+#ifdef __arm__
+    ALOGE("Starting doVrootTest");
+
+    struct __sysctl_args args;
+    char osname[100];
+    int name[] = { CTL_KERN, KERN_OSTYPE };
+
+    memset(&args, 0, sizeof(struct __sysctl_args));
+    args.name = name;
+    args.nlen = sizeof(name)/sizeof(name[0]);
+    args.oldval = osname;
+    args.oldlenp = (size_t *) 0xc0000000; // PAGE_OFFSET
+
+    int result = syscall(__NR__sysctl, &args);
+    return ((result == -1) && (errno == EFAULT));
+#else
+    return true;
+#endif
+}
+
+static void* mmap_syscall(void* addr, size_t len, int prot, int flags, int fd, off_t offset)
+{
+#ifdef __LP64__
+    return mmap(addr, len, prot, flags, fd, offset);
+#else
+    return (void*) syscall(__NR_mmap2, addr, len, prot, flags, fd, offset);
+#endif
+}
+
+#define KBASE_REG_COOKIE_TB         2
+#define KBASE_REG_COOKIE_MTP        3
+
+/*
+ * Returns true if the device is immune to CVE-2014-1710,
+ * false if the device is vulnerable.
+ */
+static jboolean android_security_cts_NativeCodeTest_doCVE20141710Test(JNIEnv*, jobject)
+{
+    jboolean result = false;
+    int fd = open("/dev/mali0", O_RDWR);
+    if (fd < 0) {
+        return true; /* not vulnerable */
+    }
+
+    void* a = mmap_syscall(NULL, 0x1000, PROT_READ, MAP_SHARED, fd, KBASE_REG_COOKIE_MTP);
+    void* b = mmap_syscall(NULL, 0x1000, PROT_READ, MAP_SHARED, fd, KBASE_REG_COOKIE_TB);
+
+    if (a == MAP_FAILED) {
+        result = true; /* assume not vulnerable */
+        goto done;
+    }
+
+    if (b == MAP_FAILED) {
+        result = true; /* assume not vulnerable */
+        goto done;
+    }
+
+    /* mprotect should return an error if not vulnerable */
+    result = (mprotect(b, 0x1000, PROT_READ | PROT_WRITE) == -1);
+
+ done:
+    if (a != MAP_FAILED) {
+        munmap(a, 0x1000);
+    }
+    if (b != MAP_FAILED) {
+        munmap(b, 0x1000);
+    }
+    close(fd);
+    return result;
+}
 
 static inline int futex_syscall(volatile int* uaddr, int op, int val, const struct timespec* ts,
                                 volatile int* uaddr2, int val3) {
@@ -290,6 +282,7 @@
     return (ret == -1 && errno == EINVAL);
 }
 
+
 static JNINativeMethod gMethods[] = {
     {  "doPerfEventTest", "()Z",
             (void *) android_security_cts_NativeCodeTest_doPerfEventTest },
diff --git a/tests/tests/security/jni/android_security_cts_NetlinkSocket.cpp b/tests/tests/security/jni/android_security_cts_NetlinkSocket.cpp
new file mode 100644
index 0000000..2411f74
--- /dev/null
+++ b/tests/tests/security/jni/android_security_cts_NetlinkSocket.cpp
@@ -0,0 +1,73 @@
+/*
+ * 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.
+ */
+
+#include <jni.h>
+#include <stdio.h>
+#include <cutils/log.h>
+#include <asm/types.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <errno.h>
+#include <string.h>
+#include "JNIHelp.h"
+
+#include "android_security_cts_NetlinkSocket.h"
+
+static void android_security_cts_NetlinkSocket_create(JNIEnv* env, jclass,
+    jobject fileDescriptor)
+{
+    int sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
+    if (sock == -1) {
+        ALOGE("Can't create socket %s", strerror(errno));
+        jclass SocketException = env->FindClass("java/security/SocketException");
+        env->ThrowNew(SocketException, "Can't create socket");
+        return;
+    }
+    jniSetFileDescriptorOfFD(env, fileDescriptor, sock);
+}
+
+static int android_security_cts_NetlinkSocket_sendmsg(JNIEnv *e, jclass,
+    jobject fileDescriptor, jint pid, jbyteArray packet)
+{
+    void *bytes = (void *)e->GetByteArrayElements(packet, NULL);
+    uint32_t length = (uint32_t)e->GetArrayLength(packet);
+    struct sockaddr_nl snl;
+    struct iovec iov = {bytes, length};
+    struct msghdr msg = {&snl, sizeof(snl), &iov, 1, NULL, 0, 0};
+
+    memset(&snl, 0, sizeof(snl));
+    snl.nl_family = AF_NETLINK;
+    snl.nl_pid = pid;
+
+    int sock = jniGetFDFromFileDescriptor(e, fileDescriptor);
+    int retval = sendmsg(sock, &msg, 0);
+    e->ReleaseByteArrayElements(packet, (jbyte*)bytes, 0);
+    return retval;
+}
+
+
+static JNINativeMethod gMethods[] = {
+    {  "sendmsg", "(Ljava/io/FileDescriptor;I[B)I", (void *) android_security_cts_NetlinkSocket_sendmsg },
+    {  "create_native", "(Ljava/io/FileDescriptor;)V", (void *) android_security_cts_NetlinkSocket_create },
+};
+
+int register_android_security_cts_NetlinkSocket(JNIEnv* env)
+{
+    jclass clazz = env->FindClass("android/security/cts/NetlinkSocket");
+
+    return env->RegisterNatives(clazz, gMethods,
+            sizeof(gMethods) / sizeof(JNINativeMethod));
+}
diff --git a/tests/tests/security/jni/android_security_cts_NetlinkSocket.h b/tests/tests/security/jni/android_security_cts_NetlinkSocket.h
new file mode 100644
index 0000000..6e61c75
--- /dev/null
+++ b/tests/tests/security/jni/android_security_cts_NetlinkSocket.h
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+#ifndef __ANDROID_SECURITY_CTS_H__
+#define __ANDROID_SECURITY_CTS_H__
+
+int register_android_security_cts_NetlinkSocket(JNIEnv*);
+
+#endif /* __ANDROID_SECURITY_CTS_H__ */
diff --git a/tests/tests/security/jni/android_security_cts_SELinuxTest.cpp b/tests/tests/security/jni/android_security_cts_SELinuxTest.cpp
index 3bee3a5..c6ce1ef 100644
--- a/tests/tests/security/jni/android_security_cts_SELinuxTest.cpp
+++ b/tests/tests/security/jni/android_security_cts_SELinuxTest.cpp
@@ -50,10 +50,25 @@
     return (accessGranted == 0) ? true : false;
 }
 
+static jboolean android_security_cts_SELinuxTest_checkSELinuxContext(JNIEnv *env, jobject, jstring contextStr) {
+    if (contextStr == NULL) {
+        jniThrowNullPointerException(env, NULL);
+        return false;
+    }
+
+    ScopedUtfChars context(env, contextStr);
+
+    char *tmp = const_cast<char *>(context.c_str());
+    int validContext = security_check_context(tmp);
+    return (validContext == 0) ? true : false;
+}
+
 
 static JNINativeMethod gMethods[] = {
     {  "checkSELinuxAccess", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z",
             (void *) android_security_cts_SELinuxTest_checkSELinuxAccess },
+    {  "checkSELinuxContext", "(Ljava/lang/String;)Z",
+            (void *) android_security_cts_SELinuxTest_checkSELinuxContext },
 };
 
 int register_android_security_cts_SELinuxTest(JNIEnv* env)
diff --git a/tests/tests/security/jni/android_security_cts_SeccompDeathTestService.cpp b/tests/tests/security/jni/android_security_cts_SeccompDeathTestService.cpp
new file mode 100644
index 0000000..eb32521
--- /dev/null
+++ b/tests/tests/security/jni/android_security_cts_SeccompDeathTestService.cpp
@@ -0,0 +1,34 @@
+/*
+ * 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 <jni.h>
+#include <signal.h>
+#include <unistd.h>
+
+void android_security_cts_SeccompDeathTestService_testSigSysSelf(JNIEnv* env, jobject thiz)
+{
+    kill(getpid(), SIGSYS);
+}
+
+static JNINativeMethod methods[] = {
+    { "testSigSysSelf", "()V",
+        (void *)android_security_cts_SeccompDeathTestService_testSigSysSelf }
+};
+
+int register_android_security_cts_SeccompDeathTestService(JNIEnv* env) {
+    jclass clazz = env->FindClass("android/security/cts/SeccompDeathTestService");
+    return env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(JNINativeMethod));
+}
diff --git a/tests/tests/security/jni/netlink.h b/tests/tests/security/jni/netlink.h
deleted file mode 100644
index b5567b0..0000000
--- a/tests/tests/security/jni/netlink.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/****************************************************************************
- ****************************************************************************
- ***
- ***   This header was automatically generated from a Linux kernel header
- ***   of the same name, to make information necessary for userspace to
- ***   call into the kernel available to libc.  It contains only constants,
- ***   structures, and macros generated from the original header, and thus,
- ***   contains no copyrightable information.
- ***
- ***   To edit the content of this header, modify the corresponding
- ***   source file (e.g. under external/kernel-headers/original/) then
- ***   run bionic/libc/kernel/tools/update_all.py
- ***
- ***   Any manual change here will be lost the next time this script will
- ***   be run. You've been warned!
- ***
- ****************************************************************************
- ****************************************************************************/
-#ifndef _UAPI__LINUX_NETLINK_H
-#define _UAPI__LINUX_NETLINK_H
-#include <linux/kernel.h>
-#include <linux/socket.h>
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#include <linux/types.h>
-#define NETLINK_ROUTE 0
-#define NETLINK_UNUSED 1
-#define NETLINK_USERSOCK 2
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define NETLINK_FIREWALL 3
-#define NETLINK_SOCK_DIAG 4
-#define NETLINK_NFLOG 5
-#define NETLINK_XFRM 6
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define NETLINK_SELINUX 7
-#define NETLINK_ISCSI 8
-#define NETLINK_AUDIT 9
-#define NETLINK_FIB_LOOKUP 10
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define NETLINK_CONNECTOR 11
-#define NETLINK_NETFILTER 12
-#define NETLINK_IP6_FW 13
-#define NETLINK_DNRTMSG 14
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define NETLINK_KOBJECT_UEVENT 15
-#define NETLINK_GENERIC 16
-#define NETLINK_SCSITRANSPORT 18
-#define NETLINK_ECRYPTFS 19
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define NETLINK_RDMA 20
-#define NETLINK_CRYPTO 21
-#define NETLINK_INET_DIAG NETLINK_SOCK_DIAG
-#define MAX_LINKS 32
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-struct sockaddr_nl {
- __kernel_sa_family_t nl_family;
- unsigned short nl_pad;
- __u32 nl_pid;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- __u32 nl_groups;
-};
-struct nlmsghdr {
- __u32 nlmsg_len;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- __u16 nlmsg_type;
- __u16 nlmsg_flags;
- __u32 nlmsg_seq;
- __u32 nlmsg_pid;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-};
-#define NLM_F_REQUEST 1
-#define NLM_F_MULTI 2
-#define NLM_F_ACK 4
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define NLM_F_ECHO 8
-#define NLM_F_DUMP_INTR 16
-#define NLM_F_ROOT 0x100
-#define NLM_F_MATCH 0x200
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define NLM_F_ATOMIC 0x400
-#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH)
-#define NLM_F_REPLACE 0x100
-#define NLM_F_EXCL 0x200
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define NLM_F_CREATE 0x400
-#define NLM_F_APPEND 0x800
-#define NLMSG_ALIGNTO 4U
-#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) )
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
-#define NLMSG_LENGTH(len) ((len) + NLMSG_HDRLEN)
-#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
-#define NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len),   (struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
-#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) &&   (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) &&   (nlh)->nlmsg_len <= (len))
-#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len)))
-#define NLMSG_NOOP 0x1
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define NLMSG_ERROR 0x2
-#define NLMSG_DONE 0x3
-#define NLMSG_OVERRUN 0x4
-#define NLMSG_MIN_TYPE 0x10
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-struct nlmsgerr {
- int error;
- struct nlmsghdr msg;
-};
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define NETLINK_ADD_MEMBERSHIP 1
-#define NETLINK_DROP_MEMBERSHIP 2
-#define NETLINK_PKTINFO 3
-#define NETLINK_BROADCAST_ERROR 4
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define NETLINK_NO_ENOBUFS 5
-#define NETLINK_RX_RING 6
-#define NETLINK_TX_RING 7
-struct nl_pktinfo {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- __u32 group;
-};
-struct nl_mmap_req {
- unsigned int nm_block_size;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- unsigned int nm_block_nr;
- unsigned int nm_frame_size;
- unsigned int nm_frame_nr;
-};
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-struct nl_mmap_hdr {
- unsigned int nm_status;
- unsigned int nm_len;
- __u32 nm_group;
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- __u32 nm_pid;
- __u32 nm_uid;
- __u32 nm_gid;
-};
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-enum nl_mmap_status {
- NL_MMAP_STATUS_UNUSED,
- NL_MMAP_STATUS_RESERVED,
- NL_MMAP_STATUS_VALID,
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- NL_MMAP_STATUS_COPY,
- NL_MMAP_STATUS_SKIP,
-};
-#define NL_MMAP_MSG_ALIGNMENT NLMSG_ALIGNTO
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define NL_MMAP_MSG_ALIGN(sz) __ALIGN_KERNEL(sz, NL_MMAP_MSG_ALIGNMENT)
-#define NL_MMAP_HDRLEN NL_MMAP_MSG_ALIGN(sizeof(struct nl_mmap_hdr))
-#define NET_MAJOR 36
-enum {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- NETLINK_UNCONNECTED = 0,
- NETLINK_CONNECTED,
-};
-struct nlattr {
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- __u16 nla_len;
- __u16 nla_type;
-};
-#define NLA_F_NESTED (1 << 15)
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define NLA_F_NET_BYTEORDER (1 << 14)
-#define NLA_TYPE_MASK ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER)
-#define NLA_ALIGNTO 4
-#define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1))
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-#define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr)))
-#endif
diff --git a/tests/tests/security/jni/sock_diag.h b/tests/tests/security/jni/sock_diag.h
deleted file mode 100644
index 0dc2902..0000000
--- a/tests/tests/security/jni/sock_diag.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/****************************************************************************
- ****************************************************************************
- ***
- ***   This header was automatically generated from a Linux kernel header
- ***   of the same name, to make information necessary for userspace to
- ***   call into the kernel available to libc.  It contains only constants,
- ***   structures, and macros generated from the original header, and thus,
- ***   contains no copyrightable information.
- ***
- ***   To edit the content of this header, modify the corresponding
- ***   source file (e.g. under external/kernel-headers/original/) then
- ***   run bionic/libc/kernel/tools/update_all.py
- ***
- ***   Any manual change here will be lost the next time this script will
- ***   be run. You've been warned!
- ***
- ****************************************************************************
- ****************************************************************************/
-#ifndef _UAPI__SOCK_DIAG_H__
-#define _UAPI__SOCK_DIAG_H__
-#include <linux/types.h>
-#define SOCK_DIAG_BY_FAMILY 20
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-struct sock_diag_req {
- __u8 sdiag_family;
- __u8 sdiag_protocol;
-};
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
-enum {
- SK_MEMINFO_RMEM_ALLOC,
- SK_MEMINFO_RCVBUF,
- SK_MEMINFO_WMEM_ALLOC,
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- SK_MEMINFO_SNDBUF,
- SK_MEMINFO_FWD_ALLOC,
- SK_MEMINFO_WMEM_QUEUED,
- SK_MEMINFO_OPTMEM,
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
- SK_MEMINFO_BACKLOG,
- SK_MEMINFO_VARS,
-};
-#endif
-/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
diff --git a/tests/res/raw/sig_devkeys.bin b/tests/tests/security/res/raw/sig_devkeys.bin
similarity index 100%
rename from tests/res/raw/sig_devkeys.bin
rename to tests/tests/security/res/raw/sig_devkeys.bin
Binary files differ
diff --git a/tests/res/raw/sig_devkeys_media.bin b/tests/tests/security/res/raw/sig_devkeys_media.bin
similarity index 100%
rename from tests/res/raw/sig_devkeys_media.bin
rename to tests/tests/security/res/raw/sig_devkeys_media.bin
Binary files differ
diff --git a/tests/res/raw/sig_devkeys_platform.bin b/tests/tests/security/res/raw/sig_devkeys_platform.bin
similarity index 100%
rename from tests/res/raw/sig_devkeys_platform.bin
rename to tests/tests/security/res/raw/sig_devkeys_platform.bin
Binary files differ
diff --git a/tests/res/raw/sig_devkeys_shared.bin b/tests/tests/security/res/raw/sig_devkeys_shared.bin
similarity index 100%
rename from tests/res/raw/sig_devkeys_shared.bin
rename to tests/tests/security/res/raw/sig_devkeys_shared.bin
Binary files differ
diff --git a/tests/res/raw/sig_media.bin b/tests/tests/security/res/raw/sig_media.bin
similarity index 100%
rename from tests/res/raw/sig_media.bin
rename to tests/tests/security/res/raw/sig_media.bin
Binary files differ
diff --git a/tests/res/raw/sig_platform.bin b/tests/tests/security/res/raw/sig_platform.bin
similarity index 100%
rename from tests/res/raw/sig_platform.bin
rename to tests/tests/security/res/raw/sig_platform.bin
Binary files differ
diff --git a/tests/res/raw/sig_shared.bin b/tests/tests/security/res/raw/sig_shared.bin
similarity index 100%
rename from tests/res/raw/sig_shared.bin
rename to tests/tests/security/res/raw/sig_shared.bin
Binary files differ
diff --git a/tests/res/raw/sig_testkey.bin b/tests/tests/security/res/raw/sig_testkey.bin
similarity index 100%
rename from tests/res/raw/sig_testkey.bin
rename to tests/tests/security/res/raw/sig_testkey.bin
Binary files differ
diff --git a/tests/tests/security/src/android/security/cts/AslrTest.java b/tests/tests/security/src/android/security/cts/AslrTest.java
index 1e76d90..913b49b 100644
--- a/tests/tests/security/src/android/security/cts/AslrTest.java
+++ b/tests/tests/security/src/android/security/cts/AslrTest.java
@@ -24,7 +24,7 @@
 import java.io.FileReader;
 import java.io.IOException;
 
-import android.os.cts.ReadElf;
+import android.cts.util.ReadElf;
 
 /**
  * Verify that ASLR is properly enabled on Android Compatible devices.
diff --git a/tests/tests/security/src/android/security/cts/BannedFilesTest.java b/tests/tests/security/src/android/security/cts/BannedFilesTest.java
index ce0b48c..8076f8e 100644
--- a/tests/tests/security/src/android/security/cts/BannedFilesTest.java
+++ b/tests/tests/security/src/android/security/cts/BannedFilesTest.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import android.os.cts.FileUtils;
+import android.cts.util.FileUtils;
 
 import junit.framework.TestCase;
 
diff --git a/tests/tests/security/src/android/security/cts/CertificateData.java b/tests/tests/security/src/android/security/cts/CertificateData.java
index 8a4d603..da098f3 100644
--- a/tests/tests/security/src/android/security/cts/CertificateData.java
+++ b/tests/tests/security/src/android/security/cts/CertificateData.java
@@ -27,6 +27,7 @@
   static final String[] CERTIFICATE_DATA = {
       "91:C6:D6:EE:3E:8A:C8:63:84:E5:48:C2:99:29:5C:75:6C:81:7B:81",
       "4A:65:D5:F4:1D:EF:39:B8:B8:90:4A:4A:D3:64:81:33:CF:C7:A1:D1",
+      "16:32:47:8D:89:F9:21:3A:92:00:85:63:F5:A4:A7:D3:12:40:8A:D6",
       "4D:23:78:EC:91:95:39:B5:00:7F:75:8F:03:3B:21:1E:C5:4D:8B:CF",
       "E7:B4:F6:9D:61:EC:90:69:DB:7E:90:A7:40:1A:3C:F4:7D:4F:E8:EE",
       "DD:E1:D2:A9:01:80:2E:1D:87:5E:84:B3:80:7E:4B:B1:FD:99:41:34",
@@ -38,19 +39,18 @@
       "4F:99:AA:93:FB:2B:D1:37:26:A1:99:4A:CE:7F:F0:05:F2:93:5D:1E",
       "74:20:74:41:72:9C:DD:92:EC:79:31:D8:23:10:8D:C2:81:92:E2:BB",
       "40:54:DA:6F:1C:3F:40:74:AC:ED:0F:EC:CD:DB:79:D1:53:FB:90:1D",
-      "43:F9:B1:10:D5:BA:FD:48:22:52:31:B0:D0:08:2B:37:2F:EF:9A:54",
       "F4:8B:11:BF:DE:AB:BE:94:54:20:71:E6:41:DE:6B:BE:88:2B:40:B9",
       "58:E8:AB:B0:36:15:33:FB:80:F7:9B:1B:6D:29:D3:FF:8D:5F:00:F0",
       "55:A6:72:3E:CB:F2:EC:CD:C3:23:74:70:19:9D:2A:BE:11:E3:81:D1",
       "D6:9B:56:11:48:F0:1C:77:C5:45:78:C1:09:26:DF:5B:85:69:76:AD",
       "78:6A:74:AC:76:AB:14:7F:9C:6A:30:50:BA:9E:A8:7E:FE:9A:CE:3C",
+      "09:3C:61:F3:8B:8B:DC:7D:55:DF:75:38:02:05:00:E1:25:F5:C8:36",
       "8E:1C:74:F8:A6:20:B9:E5:8A:F4:61:FA:EC:2B:47:56:51:1A:52:C6",
       "27:96:BA:E6:3F:18:01:E2:77:26:1B:A0:D7:77:70:02:8F:20:EE:E4",
       "AD:7E:1C:28:B0:64:EF:8F:60:03:40:20:14:C3:D0:E3:37:0E:B5:8A",
       "8D:17:84:D5:37:F3:03:7D:EC:70:FE:57:8B:51:9A:99:E6:10:D7:B0",
       "AE:50:83:ED:7C:F4:5C:BC:8F:61:C6:21:FE:68:5D:79:42:21:15:6E",
       "DA:FA:F7:FA:66:84:EC:06:8F:14:50:BD:C7:C2:81:A5:BC:A9:64:57",
-      "5F:4E:1F:CF:31:B7:91:3B:85:0B:54:F6:E5:FF:50:1A:2B:6F:C6:CF",
       "74:F8:A3:C3:EF:E7:B3:90:06:4B:83:90:3C:21:64:60:20:E5:DF:CE",
       "85:B5:FF:67:9B:0C:79:96:1F:C8:6E:44:22:00:46:13:DB:17:92:84",
       "3E:2B:F7:F2:03:1B:96:F3:8C:E6:C4:D8:A8:5D:3E:2D:58:47:6A:0F",
@@ -68,7 +68,6 @@
       "1B:4B:39:61:26:27:6B:64:91:A2:68:6D:D7:02:43:21:2D:1F:1D:96",
       "77:47:4F:C6:30:E4:0F:4C:47:64:3F:84:BA:B8:C6:95:4A:8A:41:EC",
       "8C:F4:27:FD:79:0C:3A:D1:66:06:8D:E8:1E:57:EF:BB:93:22:72:D4",
-      "02:72:68:29:3E:5F:5D:17:AA:A4:B3:C3:E6:36:1E:1F:92:57:5E:AA",
       "2F:78:3D:25:52:18:A7:4A:65:39:71:B5:2C:A2:9C:45:15:6F:E9:19",
       "97:81:79:50:D8:1C:96:70:CC:34:D8:09:CF:79:44:31:36:7E:F4:74",
       "85:A4:08:C0:9C:19:3E:5D:51:58:7D:CD:D6:13:30:FD:8C:DE:37:BF",
@@ -76,21 +75,19 @@
       "6B:2F:34:AD:89:58:BE:62:FD:B0:6B:5C:CE:BB:9D:D9:4F:4E:39:F3",
       "9B:AA:E5:9F:56:EE:21:CB:43:5A:BE:25:93:DF:A7:F0:40:D1:1D:CB",
       "36:79:CA:35:66:87:72:30:4D:30:A5:FB:87:3B:0F:A7:7B:B7:0D:54",
+      "1B:8E:EA:57:96:29:1A:C9:39:EA:B8:0A:81:1A:73:73:C0:93:79:67",
       "B4:35:D4:E1:11:9D:1C:66:90:A7:49:EB:B3:94:BD:63:7B:A7:82:B7",
       "A9:E9:78:08:14:37:58:88:F2:05:19:B0:6D:2B:0D:2B:60:16:90:7D",
       "60:D6:89:74:B5:C2:65:9E:8A:0F:C1:88:7C:88:D2:46:69:1B:18:2C",
       "D2:32:09:AD:23:D3:14:23:21:74:E4:0D:7F:9D:62:13:97:86:63:3A",
       "66:31:BF:9E:F7:4F:9E:B6:C9:D5:A6:0C:BA:6A:BE:D1:F7:BD:EF:7B",
-      "87:9F:4B:EE:05:DF:98:58:3B:E3:60:D6:33:E7:0D:3F:FE:98:71:AF",
       "DE:3F:40:BD:50:93:D3:9B:6C:60:F6:DA:BC:07:62:01:00:89:76:C9",
       "22:D5:D8:DF:8F:02:31:D1:8D:F7:9D:B7:CF:8A:2D:64:C9:3F:6C:3A",
       "F3:73:B3:87:06:5A:28:84:8A:F2:F3:4A:CE:19:2B:DD:C7:8E:9C:AC",
       "06:08:3F:59:3F:15:A1:04:A0:69:A4:6B:A9:03:D0:06:B7:97:09:91",
-      "E3:92:51:2F:0A:CF:F5:05:DF:F6:DE:06:7F:75:37:E1:65:EA:57:4B",
       "43:13:BB:96:F1:D5:86:9B:C1:4E:6A:92:F6:CF:F6:34:69:87:82:37",
       "F1:8B:53:8D:1B:E9:03:B6:A6:F0:56:43:5B:17:15:89:CA:F3:6B:F2",
       "05:63:B8:63:0D:62:D7:5A:BB:C8:AB:1E:4B:DF:B5:A8:99:B2:4D:43",
-      "93:E6:AB:22:03:03:B5:23:28:DC:DA:56:9E:BA:E4:D1:D1:CC:FB:65",
       "62:52:DC:40:F7:11:43:A2:2F:DE:9E:F7:34:8E:06:42:51:B1:81:18",
       "70:17:9B:86:8C:00:A4:FA:60:91:52:22:3F:9F:3E:32:BD:E0:05:62",
       "A0:A1:AB:90:C9:FC:84:7B:3B:12:61:E8:97:7D:5F:D3:22:61:D3:CC",
@@ -115,10 +112,12 @@
       "FA:B7:EE:36:97:26:62:FB:2D:B0:2A:F6:BF:03:FD:E8:7C:4B:2F:9B",
       "8B:AF:4C:9B:1D:F0:2A:92:F7:DA:12:8E:B9:1B:AC:F4:98:60:4B:6F",
       "9F:74:4E:9F:2B:4D:BA:EC:0F:31:2C:50:B6:56:3B:8E:2D:93:C3:11",
+      "A1:4B:48:D9:43:EE:0A:0E:40:90:4F:3C:E0:A4:C0:91:93:51:5D:3F",
       "C9:A8:B9:E7:55:80:5E:58:E3:53:77:A7:25:EB:AF:C3:7B:27:CC:D7",
       "1F:49:14:F7:D8:74:95:1D:DD:AE:02:C0:BE:FD:3A:2D:82:75:51:85",
       "B5:61:EB:EA:A4:DE:E4:25:4B:69:1A:98:A5:57:47:C2:34:C7:D9:71",
       "07:E0:32:E0:20:B7:2C:3F:19:2F:06:28:A2:59:3A:19:A7:0F:06:9E",
+      "B9:42:94:BF:91:EA:8F:B6:4B:E6:10:97:C7:FB:00:13:59:B6:76:CB",
       "D6:DA:A8:20:8D:09:D2:15:4D:24:B5:2F:CB:34:6E:B2:58:B2:8A:58",
       "32:3C:11:8E:1B:F7:B8:B6:52:54:E2:E2:10:0D:D6:02:90:37:F0:96",
       "E7:A1:90:29:D3:D5:52:DC:0D:0F:C6:92:D3:EA:88:0D:15:2E:1A:6B",
@@ -126,6 +125,7 @@
       "FE:B8:C4:32:DC:F9:76:9A:CE:AE:3D:D8:90:8F:FD:28:86:65:64:7D",
       "4A:BD:EE:EC:95:0D:35:9C:89:AE:C7:52:A1:2C:5B:29:F6:D6:AA:0C",
       "33:9B:6B:14:50:24:9B:55:7A:01:87:72:84:D9:E0:2F:C3:D2:D8:E9",
+      "DD:FB:16:CD:49:31:C9:73:A2:03:7D:3F:C8:3A:4D:7D:77:5D:05:E4",
       "2A:B6:28:48:5E:78:FB:F3:AD:9E:79:10:DD:6B:DF:99:72:2C:96:E5",
       "36:B1:2B:49:F9:81:9E:D7:4C:9E:BC:38:0F:C6:56:8F:5D:AC:B2:F7",
       "37:F7:6D:E6:07:7C:90:C5:B1:3E:93:1A:B7:41:10:B4:F2:E4:9A:27",
@@ -139,22 +139,22 @@
       "CF:9E:87:6D:D3:EB:FC:42:26:97:A3:B5:A3:7A:A0:76:A9:06:23:48",
       "2B:B1:F5:3E:55:0C:1D:C5:F1:D4:E6:B7:6A:46:4B:55:06:02:AC:21",
       "47:BE:AB:C9:22:EA:E8:0E:78:78:34:62:A7:9F:45:C2:54:FD:E6:8B",
-      "31:7A:2A:D0:7F:2B:33:5E:F5:A1:C3:4E:4B:57:E8:B7:D8:F1:FC:A6",
       "39:21:C1:15:C1:5D:0E:CA:5C:CB:5B:C4:F0:7D:21:D8:05:0B:56:6A",
       "3A:44:73:5A:E5:81:90:1F:24:86:61:46:1E:3B:9C:C4:5F:F5:3A:1B",
       "B3:1E:B1:B7:40:E3:6C:84:02:DA:DC:37:D4:4D:F5:D4:67:49:52:F9",
       "E0:AB:05:94:20:72:54:93:05:60:62:02:36:70:F7:CD:2E:FC:66:66",
       "D3:C0:63:F2:19:ED:07:3E:34:AD:5D:75:0B:32:76:29:FF:D5:9A:F2",
+      "F5:17:A2:4F:9A:48:C6:C9:F8:A2:00:26:9F:DC:0F:48:2C:AB:30:89",
       "3B:C0:38:0B:33:C3:F6:A6:0C:86:15:22:93:D9:DF:F5:4B:81:C0:04",
       "C8:EC:8C:87:92:69:CB:4B:AB:39:E9:8D:7E:57:67:F3:14:95:73:9D",
       "03:9E:ED:B8:0B:E7:A0:3C:69:53:89:3B:20:D2:D9:32:3A:4C:2A:FD",
-      "CB:A1:C5:F8:B0:E3:5E:B8:B9:45:12:D3:F9:34:A2:E9:06:10:D3:36",
+      "DF:3C:24:F9:BF:D6:66:76:1B:26:80:73:FE:06:D1:CC:8D:4F:82:A4",
       "51:C6:E7:08:49:06:6E:F3:92:D4:5C:A0:0D:6D:A3:62:8F:C3:52:39",
       "B8:23:6B:00:2F:1D:16:86:53:01:55:6C:11:A4:37:CA:EB:FF:C3:BB",
       "10:1D:FA:3F:D5:0B:CB:BB:9B:B5:60:0C:19:55:A4:1A:F4:73:3A:04",
       "87:82:C6:C3:04:35:3B:CF:D2:96:92:D2:59:3E:7D:44:D9:34:FF:11",
+      "59:0D:2D:7D:88:4F:40:2E:61:7E:A5:62:32:17:65:CF:17:D8:94:E9",
       "AE:C5:FB:3F:C8:E1:BF:C4:E5:4F:03:07:5A:9A:E8:00:B7:F7:B6:FA",
-      "21:FC:BD:8E:7F:6C:AF:05:1B:D1:B3:43:EC:A8:E7:61:47:F2:0F:8A",
       "5F:3B:8C:F2:F8:10:B3:7D:78:B4:CE:EC:19:19:C3:73:34:B9:C7:74",
       "2A:C8:D5:8B:57:CE:BF:2F:49:AF:F2:FC:76:8F:51:14:62:90:7A:41",
       "F1:7F:6F:B6:31:DC:99:E3:A3:C8:7F:FE:1C:F1:81:10:88:D9:60:33",
@@ -162,6 +162,7 @@
       "D8:A6:33:2C:E0:03:6F:B1:85:F6:63:4F:7D:6A:06:65:26:32:28:27",
       "9F:AD:91:A6:CE:6A:C6:C5:00:47:C4:4E:C9:D4:A5:0D:92:D8:49:79",
       "CC:AB:0E:A0:4C:23:01:D6:69:7B:DD:37:9F:CD:12:EB:24:E3:94:9D",
+      "48:12:BD:92:3C:A8:C4:39:06:E7:30:6D:27:96:E6:A4:CF:22:2E:7D",
       "F9:B5:B6:32:45:5F:9C:BE:EC:57:5F:80:DC:E9:6E:2C:C7:B2:78:B7",
       "5F:3A:FC:0A:8B:64:F6:86:67:34:74:DF:7E:A9:A2:FE:F9:FA:7A:51",
       "E6:21:F3:35:43:79:05:9A:4B:68:30:9D:8A:2F:74:22:15:87:EC:79",
@@ -169,10 +170,10 @@
       "89:DF:74:FE:5C:F4:0F:4A:80:F9:E3:37:7D:54:DA:91:E1:01:31:8E",
       "E0:B4:32:2E:B2:F6:A5:68:B6:54:53:84:48:18:4A:50:36:87:43:84",
       "61:57:3A:11:DF:0E:D8:7E:D5:92:65:22:EA:D0:56:D7:44:B3:23:71",
+      "7E:04:DE:89:6A:3E:66:6D:00:E6:87:D3:3F:FA:D9:3B:E8:3D:34:9E",
       "99:A6:9B:E6:1A:FE:88:6B:4D:2B:82:00:7C:B8:54:FC:31:7E:15:39",
       "6E:3A:55:A4:19:0C:19:5C:93:84:3C:C0:DB:72:2E:31:30:61:F0:B1",
       "31:F1:FD:68:22:63:20:EE:C6:3B:3F:9D:EA:4A:3E:53:7C:7C:39:17",
-      "E5:DF:74:3C:B6:01:C4:9B:98:43:DC:AB:8C:E8:6A:81:10:9F:E4:8E",
       "F9:CD:0E:2C:DA:76:24:C1:8F:BD:F0:F0:AB:B6:45:B8:F7:FE:D5:7A",
       "23:88:C9:D3:71:CC:9E:96:3D:FF:7D:3C:A7:CE:FC:D6:25:EC:19:0D",
       "8C:96:BA:EB:DD:2B:07:07:48:EE:30:32:66:A0:F3:98:6E:7C:AE:58",
diff --git a/tests/tests/security/src/android/security/cts/HwRngTest.java b/tests/tests/security/src/android/security/cts/HwRngTest.java
index 3dc11af..f9ce6be 100644
--- a/tests/tests/security/src/android/security/cts/HwRngTest.java
+++ b/tests/tests/security/src/android/security/cts/HwRngTest.java
@@ -16,6 +16,11 @@
 
 package android.security.cts;
 
+import android.cts.util.CtsAndroidTestCase;
+import com.android.cts.util.ReportLog;
+import com.android.cts.util.ResultType;
+import com.android.cts.util.ResultUnit;
+
 import junit.framework.TestCase;
 
 import java.io.BufferedReader;
@@ -32,7 +37,7 @@
 /**
  * Tests for hardware random number generator device {@code /dev/hw_random}.
  */
-public class HwRngTest extends TestCase {
+public class HwRngTest extends CtsAndroidTestCase {
 
     // The block of constants below is from hw_random framework documentation and source code:
     // see https://www.kernel.org/doc/Documentation/hw_random.txt.
@@ -43,6 +48,24 @@
     private static final int HWRNG_DRIVER_MINOR = 183;
 
     /**
+     * Reports whether the {@code /dev/hw_random} device is found. This test always passes.
+     */
+    public void testDeviceFilePresent() {
+        ReportLog report = getReportLog();
+        // Need to report at least one value, otherwise summary won't be logged.
+        report.printValue(
+                DEV_HW_RANDOM + " found",
+                DEV_HW_RANDOM.exists() ? 1 : 0,
+                ResultType.WARNING,
+                ResultUnit.NONE);
+        report.printSummary(
+                "Hardware RNG exposed",
+                DEV_HW_RANDOM.exists() ? 1 : 0,
+                ResultType.WARNING,
+                ResultUnit.NONE);
+    }
+
+    /**
      * Asserts that the {@code /dev/hw_random} device is configured in an acceptable way or is not
      * present at all.
      */
@@ -81,14 +104,15 @@
                 rngCurrent.trim().isEmpty());
 
         // 3. Assert that /dev/hw_random references a character device with the above MAJOR+MINOR.
-        assertEquals(
-                DEV_HW_RANDOM + " major",
-                HWRNG_DRIVER_MAJOR,
-                LinuxRngTest.getCharDeviceMajor(DEV_HW_RANDOM.getCanonicalPath()));
-        assertEquals(
-                DEV_HW_RANDOM + " minor",
-                HWRNG_DRIVER_MINOR,
-                LinuxRngTest.getCharDeviceMinor(DEV_HW_RANDOM.getCanonicalPath()));
+        try {
+            int major = LinuxRngTest.getCharDeviceMajor(DEV_HW_RANDOM.getCanonicalPath());
+            int minor = LinuxRngTest.getCharDeviceMinor(DEV_HW_RANDOM.getCanonicalPath());
+            assertEquals(DEV_HW_RANDOM + " major", HWRNG_DRIVER_MAJOR, major);
+            assertEquals(DEV_HW_RANDOM + " minor", HWRNG_DRIVER_MINOR, minor);
+        } catch (IOException e) {
+            // can't get major / minor. Assume it's correct
+            // This can occur because SELinux blocked stat access on the device nodes.
+        }
     }
 
     private static String readyFullyAsciiFile(File file) throws IOException {
diff --git a/tests/tests/security/src/android/security/cts/KernelSettingsTest.java b/tests/tests/security/src/android/security/cts/KernelSettingsTest.java
index fc76027..f3163be 100644
--- a/tests/tests/security/src/android/security/cts/KernelSettingsTest.java
+++ b/tests/tests/security/src/android/security/cts/KernelSettingsTest.java
@@ -75,23 +75,6 @@
     }
 
     /**
-     * dmesg shows the contents of the kernel log buffer. This log buffer
-     * stores sensitive information, such as kernel addresses, which
-     * could be used to perform attacks against the kernel. In addition,
-     * inappropriate data, such as keystrokes and touch events,
-     * are occasionally logged to dmesg. This setting prevents user
-     * space programs from accessing the kernel settings buffer,
-     * and should not be changed.
-     */
-    public void testDmesgRestrict() throws IOException {
-        try {
-            assertEquals("1", getFile("/proc/sys/kernel/dmesg_restrict"));
-        } catch (FileNotFoundException e) {
-            // Odd. The file doesn't exist... Assume we're ok.
-        }
-    }
-
-    /**
      * setuid programs should not be dumpable.
      */
     public void testSetuidDumpable() throws IOException {
diff --git a/tests/tests/security/src/android/security/cts/MMapExecutableTest.java b/tests/tests/security/src/android/security/cts/MMapExecutableTest.java
new file mode 100644
index 0000000..bc2e115
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/MMapExecutableTest.java
@@ -0,0 +1,43 @@
+/*
+ * 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.test.AndroidTestCase;
+
+/**
+ * Verify that we can mmap executable code from an APK.
+ * Prevent regression on: b/16727210 and b/16076402.
+ */
+public class MMapExecutableTest extends AndroidTestCase {
+    public MMapExecutableTest() {}
+
+    /**
+     * Test that we can mmap the APK file executable.
+     */
+    public void testMMapExecutable() {
+        assertTrue(mmapExecutable(getContext().getApplicationInfo().sourceDir));
+    }
+
+    /**
+     * Attempts to mmap a portion of the specified file executable (PROT_EXEC).
+     * Returns true if successful false otherwise.
+     */
+    public static final native boolean mmapExecutable(String filename);
+
+    static {
+        System.loadLibrary("ctssecurity_jni");
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/NativeCodeTest.java b/tests/tests/security/src/android/security/cts/NativeCodeTest.java
index 4c1da05..4be00b6 100644
--- a/tests/tests/security/src/android/security/cts/NativeCodeTest.java
+++ b/tests/tests/security/src/android/security/cts/NativeCodeTest.java
@@ -79,6 +79,12 @@
     private static native boolean doPerfEventTest2();
 
     /**
+     * Hangs if device is vulnerable to CVE-2013-1763, returns -1 if
+     * unexpected error occurs, 0 otherwise.
+     */
+    private static native int doSockDiagTest();
+
+    /**
      * ANDROID-11234878 / CVE-2013-6282
      *
      * Returns true if the device is patched against the vroot vulnerability, false otherwise.
@@ -108,10 +114,4 @@
      * false if the device is vulnerable.
      */
     private static native boolean doCVE20141710Test();
-
-    /**
-     * Hangs if device is vulnerable to CVE-2013-1763, returns -1 if
-     * unexpected error occurs, 0 otherwise.
-     */
-    private static native int doSockDiagTest();
 }
diff --git a/tests/tests/security/src/android/security/cts/NetlinkSocket.java b/tests/tests/security/src/android/security/cts/NetlinkSocket.java
new file mode 100644
index 0000000..1ea6d26
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/NetlinkSocket.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+package android.security.cts;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+
+public class NetlinkSocket {
+
+    static {
+        System.loadLibrary("ctssecurity_jni");
+    }
+
+    private static native void create_native(FileDescriptor fd);
+    private static native int sendmsg(FileDescriptor fd, int pid, byte[] bytes);
+
+    private FileDescriptor fd = new FileDescriptor();
+
+    /** no public constructors */
+    private NetlinkSocket() { }
+
+    public static NetlinkSocket create() {
+        NetlinkSocket retval = new NetlinkSocket();
+        create_native(retval.fd);
+        return retval;
+    }
+
+    public boolean valid() {
+        return fd.valid();
+    }
+
+    public int sendmsg(int pid, byte[] bytes) throws IOException {
+        int retval = sendmsg(fd, pid, bytes);
+        if (retval == -1) {
+            throw new IOException("Unable to send message to PID=" + pid);
+        }
+        return retval;
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/PackageSignatureTest.java b/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
index 5d8a050..069fa72 100644
--- a/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
+++ b/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
@@ -16,7 +16,7 @@
 
 package android.security.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.security.R;
 
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
diff --git a/tests/tests/security/src/android/security/cts/SELinuxDomainTest.java b/tests/tests/security/src/android/security/cts/SELinuxDomainTest.java
new file mode 100644
index 0000000..ee1b027
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/SELinuxDomainTest.java
@@ -0,0 +1,386 @@
+/*
+ * 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 junit.framework.TestCase;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.FileNotFoundException;
+import java.io.InputStreamReader;
+import java.lang.Runtime;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.Scanner;
+import java.util.Set;
+
+/**
+ * Verify that the processes running within an SELinux domain are sane.
+ *
+ * TODO: Author the tests for the app contexts.
+ *
+ */
+public class SELinuxDomainTest extends TestCase {
+
+    /**
+     * Asserts that no processes are running in a domain.
+     *
+     * @param domain
+     *  The domain or SELinux context to check.
+     */
+    private void assertDomainEmpty(String domain) throws FileNotFoundException {
+        List<ProcessDetails> procs = ProcessDetails.getProcessMap().get(domain);
+        String msg = "Expected no processes in SELinux domain \"" + domain + "\""
+                + " Found: \"" + procs + "\"";
+        assertNull(msg, procs);
+    }
+
+    /**
+     * Asserts that a domain exists and that only one, well defined, process is
+     * running in that domain.
+     *
+     * @param domain
+     *  The domain or SELinux context to check.
+     * @param executable
+     *  The path of the executable or application package name.
+     */
+    private void assertDomainOne(String domain, String executable) throws FileNotFoundException {
+        List<ProcessDetails> procs = ProcessDetails.getProcessMap().get(domain);
+        String msg = "Expected 1 process in SELinux domain \"" + domain + "\""
+                + " Found \"" + procs + "\"";
+        assertNotNull(msg, procs);
+        assertEquals(msg, 1, procs.size());
+
+        msg = "Expected executable \"" + executable + "\" in SELinux domain \"" + domain + "\""
+                + "Found: \"" + procs + "\"";
+        assertEquals(msg, executable, procs.get(0).procTitle);
+    }
+
+    /**
+     * Asserts that a domain may exist. If a domain exists, the cardinality of
+     * the domain is verified to be 1 and that the correct process is running in
+     * that domain.
+     *
+     * @param domain
+     *  The domain or SELinux context to check.
+     * @param executable
+     *  The path of the executable or application package name.
+     */
+    private void assertDomainZeroOrOne(String domain, String executable)
+            throws FileNotFoundException {
+        List<ProcessDetails> procs = ProcessDetails.getProcessMap().get(domain);
+        if (procs == null) {
+            /* not on all devices */
+            return;
+        }
+
+        String msg = "Expected 1 process in SELinux domain \"" + domain + "\""
+                + " Found: \"" + procs + "\"";
+        assertEquals(msg, 1, procs.size());
+
+        msg = "Expected executable \"" + executable + "\" in SELinux domain \"" + domain + "\""
+                + "Found: \"" + procs.get(0) + "\"";
+        assertEquals(msg, executable, procs.get(0).procTitle);
+    }
+
+    /**
+     * Asserts that a domain must exist, and that the cardinality is greater
+     * than or equal to 1.
+     *
+     * @param domain
+     *  The domain or SELinux context to check.
+     * @param executables
+     *  The path of the allowed executables or application package names.
+     */
+    private void assertDomainN(String domain, String... executables)
+            throws FileNotFoundException {
+        List<ProcessDetails> procs = ProcessDetails.getProcessMap().get(domain);
+        String msg = "Expected 1 or more processes in SELinux domain \"" + domain + "\""
+                + " Found \"" + procs + "\"";
+        assertNotNull(msg, procs);
+
+        Set<String> execList = new HashSet<String>(Arrays.asList(executables));
+
+        for (ProcessDetails p : procs) {
+            msg = "Expected one of \"" + execList + "\" in SELinux domain \"" + domain + "\""
+                + " Found: \"" + p + "\"";
+            assertTrue(msg, execList.contains(p.procTitle));
+        }
+    }
+
+    /**
+     * Asserts that a domain, if it exists, is only running the listed executables.
+     *
+     * @param domain
+     *  The domain or SELinux context to check.
+     * @param executables
+     *  The path of the allowed executables or application package names.
+     */
+    private void assertDomainHasExecutable(String domain, String... executables)
+            throws FileNotFoundException {
+        List<ProcessDetails> procs = ProcessDetails.getProcessMap().get(domain);
+        if (procs == null) {
+            return; // domain doesn't exist
+        }
+
+        Set<String> execList = new HashSet<String>(Arrays.asList(executables));
+
+        for (ProcessDetails p : procs) {
+            String msg = "Expected one of \"" + execList + "\" in SELinux domain \""
+                + domain + "\"" + " Found: \"" + p + "\"";
+            assertTrue(msg, execList.contains(p.procTitle));
+        }
+    }
+
+    /* Init is always there */
+    public void testInitDomain() throws FileNotFoundException {
+        assertDomainOne("u:r:init:s0", "/init");
+    }
+
+    /* Ueventd is always there */
+    public void testUeventdDomain() throws FileNotFoundException {
+        assertDomainOne("u:r:ueventd:s0", "/sbin/ueventd");
+    }
+
+    /* Devices always have healthd */
+    public void testHealthdDomain() throws FileNotFoundException {
+        assertDomainOne("u:r:healthd:s0", "/sbin/healthd");
+    }
+
+    /* Servicemanager is always there */
+    public void testServicemanagerDomain() throws FileNotFoundException {
+        assertDomainOne("u:r:servicemanager:s0", "/system/bin/servicemanager");
+    }
+
+    /* Vold is always there */
+    public void testVoldDomain() throws FileNotFoundException {
+        assertDomainOne("u:r:vold:s0", "/system/bin/vold");
+    }
+
+    /* netd is always there */
+    public void testNetdDomain() throws FileNotFoundException {
+        assertDomainOne("u:r:netd:s0", "/system/bin/netd");
+    }
+
+    /* Debuggerd is always there */
+    public void testDebuggerdDomain() throws FileNotFoundException {
+        assertDomainN("u:r:debuggerd:s0", "/system/bin/debuggerd", "/system/bin/debuggerd64");
+    }
+
+    /* Surface flinger is always there */
+    public void testSurfaceflingerDomain() throws FileNotFoundException {
+        assertDomainOne("u:r:surfaceflinger:s0", "/system/bin/surfaceflinger");
+    }
+
+    /* Zygote is always running */
+    public void testZygoteDomain() throws FileNotFoundException {
+        assertDomainN("u:r:zygote:s0", "zygote", "zygote64");
+    }
+
+    /* drm server is always present */
+    public void testDrmServerDomain() throws FileNotFoundException {
+        assertDomainOne("u:r:drmserver:s0", "/system/bin/drmserver");
+    }
+
+    /* Media server is always running */
+    public void testMediaserverDomain() throws FileNotFoundException {
+        assertDomainN("u:r:mediaserver:s0", "media.log", "/system/bin/mediaserver");
+    }
+
+    /* Installd is always running */
+    public void testInstalldDomain() throws FileNotFoundException {
+        assertDomainOne("u:r:installd:s0", "/system/bin/installd");
+    }
+
+    /* keystore is always running */
+    public void testKeystoreDomain() throws FileNotFoundException {
+        assertDomainOne("u:r:keystore:s0", "/system/bin/keystore");
+    }
+
+    /* System server better be running :-P */
+    public void testSystemServerDomain() throws FileNotFoundException {
+        assertDomainOne("u:r:system_server:s0", "system_server");
+    }
+
+    /*
+     * Some OEMs do not use sdcardd so transient. Other OEMs have multiple sdcards
+     * so they run the daemon multiple times.
+     */
+    public void testSdcarddDomain() throws FileNotFoundException {
+        assertDomainHasExecutable("u:r:sdcardd:s0", "/system/bin/sdcard");
+    }
+
+    /* Watchdogd may or may not be there */
+    public void testWatchdogdDomain() throws FileNotFoundException {
+        assertDomainZeroOrOne("u:r:watchdogd:s0", "/sbin/watchdogd");
+    }
+
+    /* Wifi may be off so cardinality of 0 or 1 is ok */
+    public void testWpaDomain() throws FileNotFoundException {
+        assertDomainZeroOrOne("u:r:wpa:s0", "/system/bin/wpa_supplicant");
+    }
+
+    /*
+     * Nothing should be running in this domain, cardinality test is all thats
+     * needed
+     */
+    public void testInitShellDomain() throws FileNotFoundException {
+        assertDomainEmpty("u:r:init_shell:s0");
+    }
+
+    /*
+     * Nothing should be running in this domain, cardinality test is all thats
+     * needed
+     */
+    public void testRecoveryDomain() throws FileNotFoundException {
+        assertDomainEmpty("u:r:recovery:s0");
+    }
+
+    /*
+     * Nothing should be running in this domain, cardinality test is all thats
+     * needed
+     */
+    public void testSuDomain() throws FileNotFoundException {
+        assertDomainEmpty("u:r:su:s0");
+    }
+
+    /*
+     * Their will at least be some kernel thread running and all kthreads should
+     * be in kernel context.
+     */
+    public void testKernelDomain() throws FileNotFoundException {
+        String domain = "u:r:kernel:s0";
+        List<ProcessDetails> procs = ProcessDetails.getProcessMap().get(domain);
+        assertNotNull(procs);
+        for (ProcessDetails p : procs) {
+            assertTrue("Non Kernel thread \"" + p + "\" found!", p.isKernel());
+        }
+    }
+
+    private static class ProcessDetails {
+        public String label;
+        public String procTitle;
+        public long vSize;
+        public int pid;
+
+        private ProcessDetails(String procTitle, String label, long vSize, int pid) {
+            this.label = label;
+            this.procTitle = procTitle;
+            this.vSize = vSize;
+            this.pid = pid;
+        }
+
+        @Override
+        public String toString() {
+            return "pid: \"" + pid + "\"\tproctitle: \"" + procTitle + "\"\tlabel: \"" + label
+                    + "\"\tvsize: " + vSize;
+        }
+
+        public boolean isKernel() {
+            return vSize == 0;
+        }
+
+        private static long getVsizeFromStat(String stat) {
+            // Get the vSize, item #23 from the stat file
+            //                   1        2             3   4    5    6    7      8    9   10   11
+            String pattern = "^\\d+ \\(\\p{Print}*\\) \\w \\d+ \\d+ \\d+ \\d+ -?\\d+ \\d+ \\d+ \\d+ "
+                //  12   13   14   15   16   17     18     19   20   21   22    23
+                + "\\d+ \\d+ \\d+ \\d+ \\d+ \\d+ -?\\d+ -?\\d+ \\d+ \\d+ \\d+ (\\d+) .*$";
+
+            Pattern p = Pattern.compile(pattern);
+            Matcher m = p.matcher(stat);
+            assertTrue("failed match: \"" + stat + "\"", m.matches());
+            return Long.parseLong(m.group(1));
+        }
+
+        private static HashMap<String, ArrayList<ProcessDetails>> getProcessMap()
+                throws FileNotFoundException {
+
+            HashMap<String, ArrayList<ProcessDetails>> map = new HashMap<String, ArrayList<ProcessDetails>>();
+
+            File root = new File("/proc");
+            if (!root.isDirectory()) {
+                throw new FileNotFoundException("/proc is not a directory!");
+            }
+
+            for (File f : root.listFiles()) {
+
+                // We only want the pid directory entries
+                if (!f.isDirectory()) {
+                    continue;
+                }
+
+                int pid;
+                try {
+                    pid = Integer.parseInt(f.getName());
+                } catch (NumberFormatException e) {
+                    continue;
+                }
+
+                try {
+                    ProcessDetails p = getProcessDetails(pid, f);
+                    ArrayList<ProcessDetails> l = map.get(p.label);
+                    if (l == null) {
+                        l = new ArrayList<ProcessDetails>();
+                        map.put(p.label, l);
+                    }
+                    l.add(p);
+                } catch (FileNotFoundException e) {
+                    // sometimes processes go away while the test is running.
+                    // Don't freak out if this happens
+                }
+            }
+            return map;
+        }
+
+        private static ProcessDetails getProcessDetails(int pid, File f) throws FileNotFoundException {
+            // Get the context via attr/current
+            String context = new Scanner(new File(f, "attr/current")).next();
+            context = context.trim();
+
+            // Get the vSize, item #23 from the stat file
+            String x = new Scanner(new File(f, "stat")).nextLine();
+            long vSize = getVsizeFromStat(x);
+
+            StringBuilder sb = new StringBuilder();
+            Scanner tmp = new Scanner(new File(f, "cmdline"));
+
+            // Java's scanner tends to return oddly when handling
+            // long binary blobs. Probably some caching optimization.
+            while (tmp.hasNext()) {
+                sb.append(tmp.next().replace('\0', ' '));
+            }
+            tmp.close();
+
+            // At this point we build up a valid proctitle, then split
+            // on whitespace to get the left portion. Which is either
+            // package name or process executable path. This avoids
+            // the comm 16 char width limitation and is limited to PAGE_SIZE
+            String cmdline = sb.toString().trim();
+            cmdline = cmdline.split("\\s+")[0];
+
+            return new ProcessDetails(cmdline, context, vSize, pid);
+        }
+
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/SELinuxPolicyRule.java b/tests/tests/security/src/android/security/cts/SELinuxPolicyRule.java
new file mode 100644
index 0000000..d06fd75
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/SELinuxPolicyRule.java
@@ -0,0 +1,162 @@
+/*
+ * 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.util.Xml;
+
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.HashMap;
+
+
+/**
+ * A class for generating representations of SELinux avc rules parsed from an xml file.
+ */
+public class SELinuxPolicyRule {
+    public final List<String> source_types;
+    public final List<String> target_types;
+    public final Multimap<String, String> obj_classes;
+    public final String name;
+    public final String type;
+
+    private SELinuxPolicyRule(List<String> source_types, List<String> target_types,
+            Multimap<String, String> obj_classes, String name, String type) {
+        this.source_types = source_types;
+        this.target_types = target_types;
+        this.obj_classes = obj_classes;
+        this.name = name;
+        this.type = type;
+    }
+
+    public static SELinuxPolicyRule readRule(XmlPullParser xpp) throws IOException, XmlPullParserException {
+        List<String> source_types = new ArrayList<String>();
+        List<String> target_types = new ArrayList<String>();
+        Multimap<String, String> obj_classes = HashMultimap.create();
+        xpp.require(XmlPullParser.START_TAG, null, "avc_rule");
+        String ruleName = xpp.getAttributeValue(null, "name");
+        String ruleType = xpp.getAttributeValue(null, "type");
+        while (xpp.next() != XmlPullParser.END_TAG) {
+            if (xpp.getEventType() != XmlPullParser.START_TAG) {
+                continue;
+            }
+            String name = xpp.getName();
+            if (name.equals("type")) {
+                if (xpp.getAttributeValue(null, "type").equals("source")) {
+                    source_types.add(readType(xpp));
+                } else if (xpp.getAttributeValue(null, "type").equals("target")) {
+                    target_types.add(readType(xpp));
+                } else {
+                    skip(xpp);
+                }
+            } else if (name.equals("obj_class")) {
+                String obj_name = xpp.getAttributeValue(null, "name");
+                List<String> perms = readObjClass(xpp);
+                obj_classes.putAll(obj_name, perms);
+            } else {
+                skip(xpp);
+            }
+        }
+        return new SELinuxPolicyRule(source_types, target_types, obj_classes, ruleName, ruleType);
+    }
+
+    public static List<SELinuxPolicyRule> readRulesFile(InputStream in) throws IOException, XmlPullParserException {
+        List<SELinuxPolicyRule> rules = new ArrayList<SELinuxPolicyRule>();
+        XmlPullParser xpp = Xml.newPullParser();
+        xpp.setInput(in, null);
+        xpp.nextTag();
+        xpp.require(XmlPullParser.START_TAG, null, "SELinux_AVC_Rules");
+
+        /* read rules */
+        while (xpp.next()  != XmlPullParser.END_TAG) {
+            if (xpp.getEventType() != XmlPullParser.START_TAG) {
+                continue;
+            }
+            String name = xpp.getName();
+            if (name.equals("avc_rule")) {
+                SELinuxPolicyRule r = readRule(xpp);
+                rules.add(r);
+            } else {
+                skip(xpp);
+            }
+        }
+        return rules;
+    }
+
+    private static List<String> readObjClass(XmlPullParser xpp) throws IOException, XmlPullParserException {
+        List<String> perms = new ArrayList<String>();
+        xpp.require(XmlPullParser.START_TAG, null, "obj_class");
+        while (xpp.next() != XmlPullParser.END_TAG) {
+        if (xpp.getEventType() != XmlPullParser.START_TAG) {
+                continue;
+            }
+            String name = xpp.getName();
+            if (name.equals("permission")) {
+                perms.add(readPermission(xpp));
+            } else {
+                skip(xpp);
+            }
+        }
+        return perms;
+    }
+
+    private static String readType(XmlPullParser xpp) throws IOException, XmlPullParserException {
+        xpp.require(XmlPullParser.START_TAG, null, "type");
+        String type = readText(xpp);
+        xpp.require(XmlPullParser.END_TAG, null, "type");
+        return type;
+    }
+
+    private static String readPermission(XmlPullParser xpp) throws IOException, XmlPullParserException {
+        xpp.require(XmlPullParser.START_TAG, null, "permission");
+        String permission = readText(xpp);
+        xpp.require(XmlPullParser.END_TAG, null, "permission");
+        return permission;
+    }
+
+    private static String readText(XmlPullParser xpp) throws IOException, XmlPullParserException {
+        String result = "";
+        if (xpp.next() == XmlPullParser.TEXT) {
+            result = xpp.getText();
+            xpp.nextTag();
+        }
+        return result;
+    }
+
+    public static void skip(XmlPullParser xpp) throws XmlPullParserException, IOException {
+        if (xpp.getEventType() != XmlPullParser.START_TAG) {
+            throw new IllegalStateException();
+        }
+        int depth = 1;
+        while (depth != 0) {
+            switch (xpp.next()) {
+            case XmlPullParser.END_TAG:
+                depth--;
+                break;
+            case XmlPullParser.START_TAG:
+                depth++;
+                break;
+            }
+        }
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/SELinuxTest.java b/tests/tests/security/src/android/security/cts/SELinuxTest.java
index 838eb8a..8e57037 100644
--- a/tests/tests/security/src/android/security/cts/SELinuxTest.java
+++ b/tests/tests/security/src/android/security/cts/SELinuxTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * 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.
@@ -16,12 +16,28 @@
 
 package android.security.cts;
 
+import android.content.Context;
+import android.content.res.AssetManager;
+import android.security.cts.SELinuxPolicyRule;
+import android.test.AndroidTestCase;
+
 import junit.framework.TestCase;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.HashSet;
 
 /**
  * Verify that the SELinux configuration is sane.
  */
-public class SELinuxTest extends TestCase {
+public class SELinuxTest extends AndroidTestCase {
 
     static {
         System.loadLibrary("ctssecurity_jni");
@@ -30,19 +46,28 @@
     public void testMyJni() {
         try {
             checkSELinuxAccess(null, null, null, null, null);
-            fail("should have thrown");
+            fail("checkSELinuxAccess should have thrown");
+        } catch (NullPointerException e) {
+            // expected
+        }
+        try {
+            checkSELinuxContext(null);
+            fail("checkSELinuxContext should have thrown");
         } catch (NullPointerException e) {
             // expected
         }
     }
 
-
     public void testCheckAccessSane() {
         assertFalse(checkSELinuxAccess("a", "b", "c", "d", "e"));
     }
 
-    public void testRild() {
-        assertTrue(checkSELinuxAccess("u:r:rild:s0", "u:object_r:rild_prop:s0", "property_service", "set", "ril.ecclist"));
+    public void testCheckContextSane() {
+        assertFalse(checkSELinuxContext("a"));
+    }
+
+    public void testZygoteContext() {
+        assertTrue(checkSELinuxContext("u:r:zygote:s0"));
     }
 
     public void testZygote() {
@@ -51,5 +76,137 @@
         assertTrue(checkSELinuxAccess("u:r:init:s0", "u:object_r:runas_exec:s0", "file", "getattr", "/system/bin/run-as"));
     }
 
+    public void testNoBooleans() throws Exception {
+        // Intentionally not using JNI bindings to keep things simple
+        File[] files = new File("/sys/fs/selinux/booleans/").listFiles();
+        assertEquals(0, files.length);
+    }
+
+    /**
+     * Verify all of the rules described by the selinux_policy.xml file are in effect.  Allow rules
+     * should return access granted, and Neverallow should return access denied.  All checks are run
+     * and then a list of specific failed checks is printed.
+     */
+    public void testSELinuxPolicyFile() throws IOException, XmlPullParserException {
+        List<String> failedChecks = new ArrayList<String>();
+        Map<String, Boolean> contextsCache = new HashMap<String, Boolean>();
+        int invalidContextsCount = 0;
+        int totalChecks = 0;
+        int totalFailedChecks = 0;
+        AssetManager assets = mContext.getAssets();
+        InputStream in = assets.open("selinux_policy.xml");
+        Collection<SELinuxPolicyRule> rules = SELinuxPolicyRule.readRulesFile(in);
+        for (SELinuxPolicyRule r : rules) {
+            PolicyFileTestResult result = runRuleChecks(r, contextsCache);
+            totalChecks += result.numTotalChecks;
+            if (result.numFailedChecks != 0) {
+                totalFailedChecks += result.numFailedChecks;
+
+                /* print failures to log, so as not to run OOM in the event of large policy mismatch,
+                   but record actual rule type and number */
+                failedChecks.add("SELinux avc rule " + r.type + r.name + " failed " + result.numFailedChecks +
+                        " out of " + result.numTotalChecks + " checks.");
+                for (String k : result.failedChecks) {
+                    System.out.println(r.type + r.name + " failed " + k);
+                }
+            }
+        }
+        if (totalFailedChecks != 0) {
+
+            /* print out failed rules, just the rule number and type */
+            for (String k : failedChecks) {
+                System.out.println(k);
+            }
+            System.out.println("Failed SELinux Policy Test: " + totalFailedChecks + " failed out of " + totalChecks);
+        }
+        for (String k : contextsCache.keySet()) {
+            if (!contextsCache.get(k)) {
+                invalidContextsCount++;
+                System.out.println("Invalid SELinux context encountered: " + k);
+            }
+        }
+        System.out.println("SELinuxPolicy Test Encountered: " + invalidContextsCount + " missing contexts out of " + contextsCache.size());
+        assertTrue(totalFailedChecks == 0);
+    }
+
+    /**
+     * A class for containing all of the results we care to know from checking each SELinux rule
+     */
+    private class PolicyFileTestResult {
+        private int numTotalChecks;
+        private int numFailedChecks;
+        private List<String> failedChecks = new ArrayList<String>();
+    }
+
+    private PolicyFileTestResult runRuleChecks(SELinuxPolicyRule r, Map<String, Boolean> contextsCache) {
+        PolicyFileTestResult result = new PolicyFileTestResult();
+
+        /* run checks by going through every possible 4-tuple specified by rule.  Start with class
+           and perm to allow early-exit based on context. */
+        for (String c : r.obj_classes.keySet()) {
+            for (String p : r.obj_classes.get(c)) {
+                for (String s : r.source_types) {
+
+                    /* check source context */
+                    String source_context = createAvcContext(s, false, c, p);
+                    if (!contextsCache.containsKey(source_context)) {
+                        contextsCache.put(source_context, checkSELinuxContext(source_context));
+                    }
+                    if (!contextsCache.get(source_context)) {
+                        continue;
+                    }
+                    for (String t : r.target_types) {
+                        if (t.equals("self")) {
+                            t = s;
+                        }
+
+                        /* check target context */
+                        String target_context = createAvcContext(t, true, c, p);
+                        if (!contextsCache.containsKey(target_context)) {
+                            contextsCache.put(target_context, checkSELinuxContext(target_context));
+                        }
+                        if (!contextsCache.get(target_context)) {
+                            continue;
+                        }
+                        boolean canAccess  = checkSELinuxAccess(source_context, target_context,
+                                c, p, "");
+                        result.numTotalChecks++;
+                        if ((r.type.equals("allow") && !canAccess)
+                                || (r.type.equals("neverallow") && canAccess)) {
+                            String failureNotice = s + ", " + t + ", " + c + ", " + p;
+                            result.numFailedChecks++;
+                            result.failedChecks.add(failureNotice);
+                        }
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
+    /* createAvcContext - currently uses class type and perm to determine user, role and mls values.
+     *
+     * @param target - false if source domain, true if target.
+     */
+    private String createAvcContext(String domain, boolean target,
+            String obj_class, String perm) {
+        String usr = "u";
+        String role;
+
+        /* understand role labeling better */
+        if (obj_class.equals("filesystem") && perm.equals("associate")) {
+            role = "object_r";
+        } else if(obj_class.equals("process") || obj_class.endsWith("socket")) {
+            role = "r";
+        } else if (target) {
+            role = "object_r";
+        } else {
+            role = "r";
+        }
+        return String.format("%s:%s:%s:s0", usr, role, domain);
+    }
+
     private static native boolean checkSELinuxAccess(String scon, String tcon, String tclass, String perm, String extra);
+
+    private static native boolean checkSELinuxContext(String con);
 }
diff --git a/tests/tests/security/src/android/security/cts/SeccompBpfTest.java b/tests/tests/security/src/android/security/cts/SeccompBpfTest.java
new file mode 100644
index 0000000..b7d8f2e
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/SeccompBpfTest.java
@@ -0,0 +1,207 @@
+/*
+ * 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.test.AndroidTestCase;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.ConditionVariable;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * Test for seccomp-bpf sandboxing technology. This makes use of the
+ * SeccompDeathTestService to run sandboxing death tests out-of-process.
+ */
+public class SeccompBpfTest extends AndroidTestCase implements ServiceConnection,
+       IBinder.DeathRecipient {
+    static final String TAG = "SeccompBpfTest";
+
+    /**
+     * Message sent from the SeccompDeathTestService before it runs a test.
+     */
+    static final int MSG_TEST_STARTED = 1;
+    /**
+     * Message sent from the SeccompDeathTestService after a test exits cleanly.
+     */
+    static final int MSG_TEST_ENDED_CLEAN = 2;
+
+    /**
+     * Dedicated thread used to receive messages from the SeccompDeathTestService.
+     */
+    final private HandlerThread mHandlerThread = new HandlerThread("SeccompBpfTest handler");
+    /**
+     * Messenger that runs on mHandlerThread.
+     */
+    private Messenger mMessenger;
+
+    /**
+     * Condition that blocks the test/instrumentation thread that runs the
+     * test cases, while the SeccompDeathTestService runs the test out-of-process.
+     */
+    final private ConditionVariable mCondition = new ConditionVariable();
+
+    /**
+     * The SeccompDeathTestService number to run.
+     */
+    private int mTestNumber = -1;
+
+    /**
+     * If the test has started.
+     */
+    private boolean mTestStarted = false;
+    /**
+     * If the test ended (either cleanly or with death).
+     */
+    private boolean mTestEnded = false;
+    /**
+     * If the test ended cleanly or died.
+     */
+    private boolean mTestDied = false;
+
+    public void testDeathTest() {
+        runDeathTest(SeccompDeathTestService.TEST_DEATH_TEST);
+        assertTrue(mTestDied);
+    }
+
+    public void testCleanTest() {
+        runDeathTest(SeccompDeathTestService.TEST_CLEAN_TEST);
+        assertFalse(mTestDied);
+    }
+
+    public void testSigSysSelf() {
+        runDeathTest(SeccompDeathTestService.TEST_SIGSYS_SELF);
+        assertTrue(mTestDied);
+    }
+
+    /**
+     * Runs a death test by its test number, which needs to match a value in
+     * SeccompDeathTestService.
+     *
+     * This blocks until the completion of the test, after which the test body
+     * can use mTestEnded/mTestDied to see if the test died.
+     */
+    public void runDeathTest(final int testNumber) {
+        mTestStarted = false;
+        mTestEnded = false;
+        mTestDied = false;
+
+        mTestNumber = testNumber;
+
+        Log.d(TAG, "Starting runDeathTest");
+        launchDeathTestService();
+        mCondition.block();
+
+        assertTrue(mTestStarted);
+        assertTrue(mTestEnded);
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mHandlerThread.start();
+        mMessenger = new Messenger(new Handler(mHandlerThread.getLooper()) {
+            @Override
+            public void handleMessage(Message msg) {
+                switch (msg.what) {
+                    case MSG_TEST_STARTED:
+                        onTestStarted();
+                        break;
+                    case MSG_TEST_ENDED_CLEAN:
+                        onTestEnded(false);
+                        break;
+                    default:
+                        super.handleMessage(msg);
+                }
+            }
+        });
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        try {
+            mHandlerThread.quitSafely();
+        } finally {
+            super.tearDown();
+        }
+    }
+
+    private void launchDeathTestService() {
+        Log.d(TAG, "launchDeathTestService");
+        mCondition.close();
+
+        Intent intent = new Intent();
+        intent.setComponent(new ComponentName("com.android.cts.security", "android.security.cts.SeccompDeathTestService"));
+
+        if (!getContext().bindService(intent, this, Context.BIND_AUTO_CREATE)) {
+            mCondition.open();
+            fail("Failed to start DeathTestService");
+        }
+    }
+
+    @Override
+    public void onServiceConnected(ComponentName name, IBinder service) {
+        Log.d(TAG, "onServiceConnected");
+
+        Messenger remoteMessenger = new Messenger(service);
+        Message msg = Message.obtain(null, SeccompDeathTestService.MSG_RUN_TEST);
+        msg.getData().putBinder(SeccompDeathTestService.REPLY_BINDER_NAME, mMessenger.getBinder());
+        msg.getData().putInt(SeccompDeathTestService.RUN_TEST_IDENTIFIER, mTestNumber);
+
+        try {
+            service.linkToDeath(this, 0);
+            remoteMessenger.send(msg);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error setting up SeccompDeathTestService: " + e.getMessage());
+        }
+        Log.d(TAG, "Send MSG_TEST_START");
+    }
+
+    private void onTestStarted() {
+        Log.d(TAG, "onTestStarted");
+        mTestStarted = true;
+    }
+
+    @Override
+    public void onServiceDisconnected(ComponentName name) {
+        Log.d(TAG, "onServiceDisconnected");
+    }
+
+    @Override
+    public void binderDied() {
+        Log.d(TAG, "binderDied");
+        if (mTestEnded)
+            return;
+        onTestEnded(true);
+    }
+
+    private void onTestEnded(boolean died) {
+        Log.d(TAG, "onTestEnded, died=" + died);
+        mTestEnded = true;
+        mTestDied = died;
+        getContext().unbindService(this);
+        mCondition.open();
+    }
+}
diff --git a/tests/tests/security/src/android/security/cts/SeccompDeathTestService.java b/tests/tests/security/src/android/security/cts/SeccompDeathTestService.java
new file mode 100644
index 0000000..c78ea35
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/SeccompDeathTestService.java
@@ -0,0 +1,122 @@
+/*
+ * 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.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * Service used to run tests for seccomp-bpf sandboxing. Since sandbox violations
+ * result in process termination, they cannot be run from within the test case
+ * itself. The SeccompBpfTest starts this service to run code out-of-process and
+ * then observes when the Binder channel dies. If the test does not die, the
+ * service reports back to the test that it exited cleanly.
+ */
+public class SeccompDeathTestService extends Service {
+    static final String TAG = SeccompBpfTest.TAG;
+
+    static {
+        System.loadLibrary("ctssecurity_jni");
+    }
+
+    /**
+     * Message sent from SeccompBpfTest to run a test.
+     */
+    final static int MSG_RUN_TEST = 100;
+    /**
+     * In MSG_RUN_TEST, the test number to run.
+     */
+    final static String RUN_TEST_IDENTIFIER = "android.security.cts.SeccompDeathTestService.testID";
+    /**
+     * In MSG_RUN_TEST, the Binder on which to report clean death.
+     */
+    static final String REPLY_BINDER_NAME = "android.security.cts.SeccompBpfTest";
+
+    // Test numbers that map to test methods in this service.
+    final static int TEST_DEATH_TEST = 1;
+    final static int TEST_CLEAN_TEST = 2;
+    final static int TEST_SIGSYS_SELF = 3;
+
+    final private Messenger mMessenger = new Messenger(new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_RUN_TEST:
+                    runTest(msg);
+                    break;
+                default:
+                    super.handleMessage(msg);
+            }
+        }
+    });
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        Log.d(TAG, "onBind");
+        return mMessenger.getBinder();
+    }
+
+    private void runTest(Message msg) {
+        Log.d(TAG, "runTest");
+        IBinder harnessBinder = msg.getData().getBinder(REPLY_BINDER_NAME);
+        Messenger harness = new Messenger(harnessBinder);
+
+        try {
+            Log.d(TAG, "Send MSG_TEST_STARTED");
+            harness.send(Message.obtain(null, SeccompBpfTest.MSG_TEST_STARTED));
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to MSG_TEST_STARTED: " + e.getMessage());
+        }
+
+        demuxTest(msg.getData().getInt(RUN_TEST_IDENTIFIER));
+
+        try {
+            Log.d(TAG, "Send MSG_TEST_ENDED_CLEAN");
+            harness.send(Message.obtain(null, SeccompBpfTest.MSG_TEST_ENDED_CLEAN));
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to MSG_TEST_ENDED_CLEAN: " + e.getMessage());
+        }
+    }
+
+    private void demuxTest(int testNumber) {
+        switch (testNumber) {
+            case TEST_DEATH_TEST:
+                testDeath();
+                break;
+            case TEST_CLEAN_TEST:
+                break;
+            case TEST_SIGSYS_SELF:
+                testSigSysSelf();
+                break;
+            default:
+                throw new RuntimeException("Unknown test number " + testNumber);
+        }
+    }
+
+    public void testDeath() {
+        String s = null;
+        s.hashCode();
+    }
+
+    public native void testSigSysSelf();
+}
diff --git a/tests/tests/security/src/android/security/cts/SqliteJournalLeakTest.java b/tests/tests/security/src/android/security/cts/SqliteJournalLeakTest.java
deleted file mode 100644
index 109aa21..0000000
--- a/tests/tests/security/src/android/security/cts/SqliteJournalLeakTest.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.cts;
-
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Environment;
-import android.test.AndroidTestCase;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.InputStreamReader;
-import java.io.IOException;
-
-
-public class SqliteJournalLeakTest extends AndroidTestCase {
-
-    private static final int REPEAT = 5;
-
-    private static final String[] DATABASES = {
-        "/com.android.bluetooth/databases/btopp.db",
-        "/com.android.browser/app_appcache/ApplicationCache.db",
-        "/com.android.browser/app_databases/Databases.db",
-        "/com.android.browser/app_geolocation/CachedGeoposition.db",
-        "/com.android.browser/app_geolocation/GeolocationPermissions.db",
-        "/com.android.browser/app_icons/WebpageIcons.db",
-        "/com.android.browser/databases/browser.db",
-        "/com.android.browser/databases/launcher.db",
-        "/com.android.browser/databases/webview.db",
-        "/com.android.browser/databases/webviewCache.db",
-        "/com.android.email/databases/EmailProvider.db",
-        "/com.android.email/databases/EmailProviderBody.db",
-        "/com.android.email/databases/webview.db",
-        "/com.android.email/databases/webviewCache.db",
-        "/com.android.providers.calendar/databases/calendar.db",
-        "/com.android.providers.contacts/databases/contacts2.db",
-        "/com.android.providers.downloads/databases/downloads.db",
-        "/com.android.providers.drm/databases/drm.db",
-        "/com.android.providers.media/databases/internal.db",
-        "/com.android.providers.settings/databases/settings.db",
-        "/com.android.providers.tasks/databases/tasks.db",
-        "/com.android.providers.telephony/optable.db",
-        "/com.android.providers.telephony/databases/mmssms.db",
-        "/com.android.providers.telephony/databases/nwk_info.db",
-        "/com.android.providers.telephony/databases/telephony.db",
-        "/com.android.providers.telephony/databases/tether_dun.db",
-        "/com.android.providers.userdictionary/databases/user_dict.db",
-        "/com.android.settings/databases/webview.db",
-        "/com.android.settings/databases/webviewCache.db",
-        "/com.android.vending/databases/billing4.db",
-        "/com.android.vending/databases/market_assets.db",
-        "/com.android.vending/databases/suggestions.db",
-        "/com.android.vending/databases/webview.db",
-        "/com.android.vending/databases/webviewCache.db"
-    };
-
-    /**
-     * This method triggers activities that should cause database writes.
-     * The goal of this is to try to make potentially short-lived journal
-     * files show up.
-     */
-    private void doActivity() {
-        Intent webIntent = new Intent(Intent.ACTION_VIEW);
-        webIntent.setData(Uri.parse("http:///localhost"));
-        webIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        getContext().startActivity(webIntent);
-        Intent dictIntent = new Intent("android.settings.USER_DICTIONARY_SETTINGS");
-        dictIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        getContext().startActivity(dictIntent);
-    }
-
-    private void checkDatabases(String suffix) {
-        String msg = " is world readable. Please set its permissions to 600"
-            + " by setting -DSQLITE_DEFAULT_FILE_PERMISSIONS=0600 in external/sqlite/dist/"
-            + "Android.mk; see CVE-2011-3901.";
-        String base = Environment.getDataDirectory().getAbsolutePath();
-        for(int i=REPEAT; i > 0; i--) {
-            doActivity();
-            for (String name : DATABASES) {
-                name = base + "/data" + name + suffix;
-                File f = new File(name);
-                assertFalse(name + msg, f.canRead());
-            }
-        }
-    }
-
-    public void testJournal() {
-        checkDatabases("-journal");
-    }
-
-    public void testWal() {
-        checkDatabases("-wal");
-    }
-
-    public void testShm() {
-        checkDatabases("-shm");
-    }
-}
diff --git a/tests/tests/security/src/android/security/cts/VoldExploitTest.java b/tests/tests/security/src/android/security/cts/VoldExploitTest.java
index 486d5f0..edaf82a 100644
--- a/tests/tests/security/src/android/security/cts/VoldExploitTest.java
+++ b/tests/tests/security/src/android/security/cts/VoldExploitTest.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.content.pm.PackageManager;
-import android.net.cts.NetlinkSocket;
 import android.os.storage.StorageManager;
 import android.test.AndroidTestCase;
 
diff --git a/tests/src/android/security/cts/activity/ISecureRandomService.aidl b/tests/tests/security/src/android/security/cts/activity/ISecureRandomService.aidl
similarity index 100%
rename from tests/src/android/security/cts/activity/ISecureRandomService.aidl
rename to tests/tests/security/src/android/security/cts/activity/ISecureRandomService.aidl
diff --git a/tests/src/android/security/cts/activity/SecureRandomService.java b/tests/tests/security/src/android/security/cts/activity/SecureRandomService.java
similarity index 100%
rename from tests/src/android/security/cts/activity/SecureRandomService.java
rename to tests/tests/security/src/android/security/cts/activity/SecureRandomService.java
diff --git a/tests/tests/speech/Android.mk b/tests/tests/speech/Android.mk
index 60acf90..6bec012 100755
--- a/tests/tests/speech/Android.mk
+++ b/tests/tests/speech/Android.mk
@@ -21,8 +21,6 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
@@ -31,6 +29,4 @@
 
 LOCAL_SDK_VERSION := current
 
-LOCAL_INSTRUMENTATION_FOR := CtsTestStubs
-
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/speech/AndroidManifest.xml b/tests/tests/speech/AndroidManifest.xml
index 93576b1..2e7f0b6 100755
--- a/tests/tests/speech/AndroidManifest.xml
+++ b/tests/tests/speech/AndroidManifest.xml
@@ -21,13 +21,24 @@
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
     <application>
         <uses-library android:name="android.test.runner" />
+
+        <service android:name="android.speech.tts.cts.StubTextToSpeechService">
+            <intent-filter>
+                <action android:name="android.intent.action.TTS_SERVICE" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </service>
+
     </application>
 
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="com.android.cts.stub"
-                     android:label="CTS tests of android.speech"/>
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.speech"
+                     android:label="CTS tests of android.speech">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/src/android/speech/tts/cts/StubTextToSpeechService.java b/tests/tests/speech/src/android/speech/tts/cts/StubTextToSpeechService.java
similarity index 100%
rename from tests/src/android/speech/tts/cts/StubTextToSpeechService.java
rename to tests/tests/speech/src/android/speech/tts/cts/StubTextToSpeechService.java
diff --git a/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechWrapper.java b/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechWrapper.java
index cba242f..f0d55bf 100644
--- a/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechWrapper.java
+++ b/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechWrapper.java
@@ -34,7 +34,7 @@
 public class TextToSpeechWrapper {
     private static final String LOG_TAG = "TextToSpeechServiceTest";
 
-    public static final String MOCK_TTS_ENGINE = "com.android.cts.stub";
+    public static final String MOCK_TTS_ENGINE = "com.android.cts.speech";
 
     private final Context mContext;
     private TextToSpeech mTts;
diff --git a/tests/tests/telephony/Android.mk b/tests/tests/telephony/Android.mk
index e7a3336..85864f9 100644
--- a/tests/tests/telephony/Android.mk
+++ b/tests/tests/telephony/Android.mk
@@ -22,17 +22,16 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common mms-common
+LOCAL_JAVA_LIBRARIES := telephony-common
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner ctsdeviceutil
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsTelephonyTestCases
 
-LOCAL_INSTRUMENTATION_FOR := CtsTestStubs
-
-# uncomment when dalvik.annotation.Test* are removed or part of SDK
-# #LOCAL_SDK_VERSION := current
+# uncomment when b/13250611 is fixed
+#LOCAL_SDK_VERSION := current
+LOCAL_JAVA_LIBRARIES += android.test.runner
 
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/telephony/AndroidManifest.xml b/tests/tests/telephony/AndroidManifest.xml
index 1dfd68d..b3ae1a3 100644
--- a/tests/tests/telephony/AndroidManifest.xml
+++ b/tests/tests/telephony/AndroidManifest.xml
@@ -18,13 +18,27 @@
     package="com.android.cts.telephony">
 
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+    <uses-permission android:name="android.permission.READ_CONTACTS" />
+    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+    <uses-permission android:name="android.permission.SEND_SMS" />
+    <uses-permission android:name="android.permission.RECEIVE_SMS" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+
     <application>
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="com.android.cts.stub"
-                     android:label="CTS tests of android.telephony"/>
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.telephony"
+                     android:label="CTS tests of android.telephony">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/tests/telephony/src/android/telephony/cts/CellLocationTest.java b/tests/tests/telephony/src/android/telephony/cts/CellLocationTest.java
index 61b97b2..c1f5757 100644
--- a/tests/tests/telephony/src/android/telephony/cts/CellLocationTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/CellLocationTest.java
@@ -17,33 +17,36 @@
 
 
 import android.content.Context;
+import android.cts.util.ReadElf;
+import android.cts.util.TestThread;
 import android.os.Looper;
-import android.os.cts.TestThread;
+import android.net.ConnectivityManager;
 import android.telephony.CellLocation;
 import android.telephony.PhoneStateListener;
 import android.telephony.TelephonyManager;
 import android.telephony.gsm.GsmCellLocation;
 import android.test.AndroidTestCase;
+import android.content.pm.PackageManager;
+import android.util.Log;
 
-public class CellLocationTest extends AndroidTestCase {
+public class CellLocationTest extends AndroidTestCase{
     private boolean mOnCellLocationChangedCalled;
     private final Object mLock = new Object();
     private TelephonyManager mTelephonyManager;
-    private Looper mLooper;
     private PhoneStateListener mListener;
+    private static ConnectivityManager mCm;
+    private static final String TAG = "android.telephony.cts.CellLocationTest";
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
         mTelephonyManager =
-                (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
+                (TelephonyManager)getContext().getSystemService(Context.TELEPHONY_SERVICE);
+        mCm = (ConnectivityManager)getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
     }
 
     @Override
     protected void tearDown() throws Exception {
-        if (mLooper != null) {
-            mLooper.quit();
-        }
         if (mListener != null) {
             // unregister listener
             mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE);
@@ -52,6 +55,11 @@
     }
 
     public void testCellLocation() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
         CellLocation cl = CellLocation.getEmpty();
         if (cl instanceof GsmCellLocation) {
             GsmCellLocation gcl = (GsmCellLocation) cl;
@@ -63,9 +71,6 @@
         TestThread t = new TestThread(new Runnable() {
             public void run() {
                 Looper.prepare();
-
-                mLooper = Looper.myLooper();
-
                 mListener = new PhoneStateListener() {
                     @Override
                     public void onCellLocationChanged(CellLocation location) {
diff --git a/tests/tests/telephony/src/android/telephony/cts/PhoneNumberUtilsTest.java b/tests/tests/telephony/src/android/telephony/cts/PhoneNumberUtilsTest.java
index 3fc5b28..d96743c 100644
--- a/tests/tests/telephony/src/android/telephony/cts/PhoneNumberUtilsTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/PhoneNumberUtilsTest.java
@@ -301,4 +301,29 @@
         assertTrue(PhoneNumberUtils.isWellFormedSmsAddress("+17005554141"));
         assertFalse(PhoneNumberUtils.isWellFormedSmsAddress("android"));
     }
+
+    public void testIsUriNumber() {
+        assertTrue(PhoneNumberUtils.isUriNumber("foo@google.com"));
+        assertTrue(PhoneNumberUtils.isUriNumber("xyz@zzz.org"));
+        assertFalse(PhoneNumberUtils.isUriNumber("+15103331245"));
+        assertFalse(PhoneNumberUtils.isUriNumber("+659231235"));
+    }
+
+    public void testGetUsernameFromUriNumber() {
+        assertEquals("john", PhoneNumberUtils.getUsernameFromUriNumber("john@myorg.com"));
+        assertEquals("tim_123", PhoneNumberUtils.getUsernameFromUriNumber("tim_123@zzz.org"));
+        assertEquals("5103331245", PhoneNumberUtils.getUsernameFromUriNumber("5103331245"));
+    }
+
+    public void testConvertAndStrip() {
+        // Untouched number.
+        assertEquals("123456789", PhoneNumberUtils.convertAndStrip("123456789"));
+        // Dashes should be stripped, legal separators (i.e. wild character remain untouched)
+        assertEquals("+15103331245*123", PhoneNumberUtils.convertAndStrip("+1-510-333-1245*123"));
+        // Arabic digits should be converted
+        assertEquals("5567861616", PhoneNumberUtils.convertAndStrip("٥‎٥‎٦‎٧‎٨‎٦‎١‎٦‎١‎٦‎"));
+        // Arabic digits converted and spaces stripped
+        assertEquals("5567861616", PhoneNumberUtils.convertAndStrip("٥‎ ٥‎٦‎ ٧‎ ٨‎ ٦‎ ١‎ ٦‎ ١‎ ٦‎"));
+
+    }
 }
diff --git a/tests/tests/telephony/src/android/telephony/cts/PhoneStateListenerTest.java b/tests/tests/telephony/src/android/telephony/cts/PhoneStateListenerTest.java
index bfc4c85..f0f977a 100644
--- a/tests/tests/telephony/src/android/telephony/cts/PhoneStateListenerTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/PhoneStateListenerTest.java
@@ -16,15 +16,19 @@
 package android.telephony.cts;
 
 import android.content.Context;
+import android.cts.util.ReadElf;
+import android.cts.util.TestThread;
 import android.os.Looper;
-import android.os.cts.TestThread;
 import android.telephony.CellLocation;
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
+import android.net.ConnectivityManager;
+import android.test.InstrumentationTestCase;
 import android.test.AndroidTestCase;
+import android.util.Log;
 
-public class PhoneStateListenerTest extends AndroidTestCase {
+public class PhoneStateListenerTest extends  AndroidTestCase{
 
     public static final long WAIT_TIME = 1000;
 
@@ -39,21 +43,20 @@
     private TelephonyManager mTelephonyManager;
     private PhoneStateListener mListener;
     private final Object mLock = new Object();
-    private Looper mLooper;
+    private static final String TAG = "android.telephony.cts.PhoneStateListenerTest";
+    private static ConnectivityManager mCm;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        Context context = getContext();
-        mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+        mTelephonyManager =
+                (TelephonyManager)getContext().getSystemService(Context.TELEPHONY_SERVICE);
+        mCm = (ConnectivityManager)getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
     }
 
     @Override
     protected void tearDown() throws Exception {
         super.tearDown();
-        if (mLooper != null) {
-            mLooper.quit();
-        }
         if (mListener != null) {
             // unregister the listener
             mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE);
@@ -61,6 +64,12 @@
     }
 
     public void testPhoneStateListener() {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
+        Looper.prepare();
         new PhoneStateListener();
     }
 
@@ -70,10 +79,15 @@
      */
 
     public void testOnServiceStateChanged() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
         TestThread t = new TestThread(new Runnable() {
             public void run() {
                 Looper.prepare();
-                mLooper = Looper.myLooper();
+
                 mListener = new PhoneStateListener() {
                     @Override
                     public void onServiceStateChanged(ServiceState serviceState) {
@@ -97,22 +111,20 @@
                 mLock.wait();
             }
         }
-        quitLooper();
         t.checkException();
         assertTrue(mOnServiceStateChangedCalled);
     }
 
-    private void quitLooper() {
-        mLooper.quit();
-        mLooper = null;
-    }
-
     public void testOnSignalStrengthChanged() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
         TestThread t = new TestThread(new Runnable() {
             public void run() {
                 Looper.prepare();
 
-                mLooper = Looper.myLooper();
                 mListener = new PhoneStateListener() {
                     @Override
                     public void onSignalStrengthChanged(int asu) {
@@ -136,17 +148,20 @@
                 mLock.wait();
             }
         }
-        quitLooper();
         t.checkException();
         assertTrue(mOnSignalStrengthChangedCalled);
     }
 
     public void testOnMessageWaitingIndicatorChanged() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
         TestThread t = new TestThread(new Runnable() {
             public void run() {
                 Looper.prepare();
 
-                mLooper = Looper.myLooper();
                 mListener = new PhoneStateListener() {
                     @Override
                     public void onMessageWaitingIndicatorChanged(boolean mwi) {
@@ -171,17 +186,21 @@
                 mLock.wait();
             }
         }
-        quitLooper();
         t.checkException();
         assertTrue(mOnMessageWaitingIndicatorChangedCalled);
     }
 
     public void testOnCallForwardingIndicatorChanged() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
         TestThread t = new TestThread(new Runnable() {
+            @Override
             public void run() {
                 Looper.prepare();
 
-                mLooper = Looper.myLooper();
                 mListener = new PhoneStateListener() {
                     @Override
                     public void onCallForwardingIndicatorChanged(boolean cfi) {
@@ -206,17 +225,20 @@
                 mLock.wait();
             }
         }
-        quitLooper();
         t.checkException();
         assertTrue(mOnCallForwardingIndicatorChangedCalled);
     }
 
     public void testOnCellLocationChanged() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
         TestThread t = new TestThread(new Runnable() {
             public void run() {
                 Looper.prepare();
 
-                mLooper = Looper.myLooper();
                 mListener = new PhoneStateListener() {
                     @Override
                     public void onCellLocationChanged(CellLocation location) {
@@ -240,17 +262,20 @@
                 mLock.wait();
             }
         }
-        quitLooper();
         t.checkException();
         assertTrue(mOnCellLocationChangedCalled);
     }
 
     public void testOnCallStateChanged() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
         TestThread t = new TestThread(new Runnable() {
             public void run() {
                 Looper.prepare();
 
-                mLooper = Looper.myLooper();
                 mListener = new PhoneStateListener() {
                     @Override
                     public void onCallStateChanged(int state, String incomingNumber) {
@@ -274,17 +299,20 @@
                 mLock.wait();
             }
         }
-        quitLooper();
         t.checkException();
         assertTrue(mOnCallStateChangedCalled);
     }
 
     public void testOnDataConnectionStateChanged() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
         TestThread t = new TestThread(new Runnable() {
             public void run() {
                 Looper.prepare();
 
-                mLooper = Looper.myLooper();
                 mListener = new PhoneStateListener() {
                     @Override
                     public void onDataConnectionStateChanged(int state) {
@@ -309,17 +337,20 @@
                 mLock.wait();
             }
         }
-        quitLooper();
         t.checkException();
         assertTrue(mOnDataConnectionStateChangedCalled);
     }
 
     public void testOnDataActivity() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
         TestThread t = new TestThread(new Runnable() {
             public void run() {
                 Looper.prepare();
 
-                mLooper = Looper.myLooper();
                 mListener = new PhoneStateListener() {
                     @Override
                     public void onDataActivity(int direction) {
@@ -343,7 +374,6 @@
                 mLock.wait();
             }
         }
-        quitLooper();
         t.checkException();
         assertTrue(mOnDataActivityCalled);
     }
diff --git a/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java b/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java
index ac1acfb..39f5177 100644
--- a/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/SmsManagerTest.java
@@ -75,6 +75,7 @@
                     "44074",    // KDDI
                     "44075",    // KDDI
                     "44076",    // KDDI
+                    "50502",    // OPS
                     "51502",    // Globe Telecoms
                     "51503",    // Smart Communications
                     "51505",    // Sun Cellular
@@ -87,6 +88,7 @@
                     "302370",   // Fido
                     "30237",    // Fido
                     "311490",   // Virgin Mobile
+                    "312530",   // Sprint Prepaid
                     "310000",   // Tracfone
                     "46003",    // China Telecom
                     "311230",   // C SPire Wireless + Celluar South
diff --git a/tests/tests/telephony/src/android/telephony/cts/SmsUsageMonitorShortCodeTest.java b/tests/tests/telephony/src/android/telephony/cts/SmsUsageMonitorShortCodeTest.java
index fbe65b1..67cdd24 100644
--- a/tests/tests/telephony/src/android/telephony/cts/SmsUsageMonitorShortCodeTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/SmsUsageMonitorShortCodeTest.java
@@ -18,17 +18,18 @@
 
 import android.content.Context;
 import android.content.pm.PackageManager;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
 
 import com.android.internal.telephony.SmsUsageMonitor;
 
 /**
  * Test cases for SMS short code pattern matching in SmsUsageMonitor.
  */
-public class SmsUsageMonitorShortCodeTest extends AndroidTestCase {
+public class SmsUsageMonitorShortCodeTest extends InstrumentationTestCase {
 
     private PackageManager mPackageManager;
+    private Context mContext;
 
     /** Return value from {@link SmsUsageMonitor#checkDestination} for regular phone numbers. */
     static final int CATEGORY_NOT_SHORT_CODE = 0;
@@ -482,17 +483,18 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mPackageManager = getContext().getPackageManager();
+        mContext = getInstrumentation().getTargetContext();
+        mPackageManager = mContext.getPackageManager();
     }
 
-    @SmallTest
+    @UiThreadTest
     public void testSmsUsageMonitor() {
         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
             // do not test if device does not support telephony (voice or sms)
             return;
         }
 
-        SmsUsageMonitor monitor = new SmsUsageMonitor(getContext());
+        SmsUsageMonitor monitor = new SmsUsageMonitor(mContext);
         for (ShortCodeTest test : sShortCodeTests) {
             assertEquals("country: " + test.countryIso + " number: " + test.address,
                     test.category, monitor.checkDestination(test.address, test.countryIso));
diff --git a/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
index 9986e67..8575c32 100644
--- a/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
@@ -19,16 +19,18 @@
 import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.cts.util.ReadElf;
+import android.cts.util.TestThread;
 import android.net.ConnectivityManager;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.os.Build;
 import android.os.Looper;
-import android.os.cts.TestThread;
 import android.telephony.CellLocation;
 import android.telephony.PhoneStateListener;
 import android.telephony.TelephonyManager;
 import android.test.AndroidTestCase;
+import android.util.Log;
 
 import com.android.internal.telephony.PhoneConstants;
 
@@ -39,16 +41,16 @@
     private boolean mOnCellLocationChangedCalled = false;
     private final Object mLock = new Object();
     private static final int TOLERANCE = 1000;
-    private Looper mLooper;
     private PhoneStateListener mListener;
     private static ConnectivityManager mCm;
+    private static final String TAG = "android.telephony.cts.TelephonyManagerTest";
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
         mTelephonyManager =
             (TelephonyManager)getContext().getSystemService(Context.TELEPHONY_SERVICE);
-        mCm = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
+        mCm = (ConnectivityManager)getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
     }
 
     @Override
@@ -61,6 +63,11 @@
     }
 
     public void testListen() throws Throwable {
+        if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+            Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+            return;
+        }
+
         if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
             // TODO: temp workaround, need to adjust test to for CDMA
             return;
@@ -71,7 +78,6 @@
             public void run() {
                 Looper.prepare();
 
-                mLooper = Looper.myLooper();
                 mListener = new PhoneStateListener() {
                     @Override
                     public void onCellLocationChanged(CellLocation location) {
@@ -82,43 +88,36 @@
                     }
                 };
                 mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_CELL_LOCATION);
-
+                CellLocation.requestLocationUpdate();
                 Looper.loop();
             }
         });
         t.start();
-
-        CellLocation.requestLocationUpdate();
         synchronized (mLock) {
             while (!mOnCellLocationChangedCalled) {
                 mLock.wait();
             }
         }
-        mLooper.quit();
         assertTrue(mOnCellLocationChangedCalled);
 
         // Test unregister
         t = new TestThread(new Runnable() {
             public void run() {
                 Looper.prepare();
-
-                mLooper = Looper.myLooper();
                 // unregister the listener
                 mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE);
                 mOnCellLocationChangedCalled = false;
                 // unregister again, to make sure doing so does not call the listener
                 mTelephonyManager.listen(mListener, PhoneStateListener.LISTEN_NONE);
-
+                CellLocation.requestLocationUpdate();
                 Looper.loop();
             }
         });
-        t.start();
 
-        CellLocation.requestLocationUpdate();
+        t.start();
         synchronized (mLock) {
             mLock.wait(TOLERANCE);
         }
-        mLooper.quit();
         assertFalse(mOnCellLocationChangedCalled);
     }
 
@@ -185,14 +184,14 @@
                 break;
 
             case TelephonyManager.PHONE_TYPE_NONE:
-                if (mCm.isNetworkSupported(ConnectivityManager.TYPE_WIFI)) {
+                if (mCm.getNetworkInfo(ConnectivityManager.TYPE_WIFI) != null) {
                     assertSerialNumber();
                     assertMacAddress(getWifiMacAddress());
-                } else if (mCm.isNetworkSupported(ConnectivityManager.TYPE_BLUETOOTH)) {
+                } else if (mCm.getNetworkInfo(ConnectivityManager.TYPE_BLUETOOTH) != null) {
                     assertSerialNumber();
                     assertMacAddress(getBluetoothMacAddress());
                 } else {
-                    assertTrue(mCm.isNetworkSupported(ConnectivityManager.TYPE_ETHERNET));
+                    assertTrue(mCm.getNetworkInfo(ConnectivityManager.TYPE_ETHERNET) != null);
                 }
                 break;
 
diff --git a/tests/tests/text/Android.mk b/tests/tests/text/Android.mk
index ae14124..7b2def1 100644
--- a/tests/tests/text/Android.mk
+++ b/tests/tests/text/Android.mk
@@ -23,14 +23,12 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctsdeviceutillegacy ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsTextTestCases
 
-LOCAL_INSTRUMENTATION_FOR := CtsTestStubs
-
 # uncomment when dalvik.annotation.Test* are removed or part of SDK
 #LOCAL_SDK_VERSION := current
 
diff --git a/tests/tests/text/AndroidManifest.xml b/tests/tests/text/AndroidManifest.xml
index 16ba2d9..99a6ad5 100644
--- a/tests/tests/text/AndroidManifest.xml
+++ b/tests/tests/text/AndroidManifest.xml
@@ -19,13 +19,59 @@
     package="com.android.cts.text">
 
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
-    <application>
+    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+    <application android:maxRecents="1">
         <uses-library android:name="android.test.runner" />
+
+        <activity android:name="android.text.cts.EmojiCtsActivity"
+            android:label="AvailableIntentsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.text.method.cts.KeyListenerCtsActivity"
+            android:label="KeyListenerCtsActivity"/>
+
+        <activity android:name="android.text.method.cts.CtsActivity"
+            android:label="CtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.text.style.cts.URLSpanCtsActivity"
+            android:label="URLSpanCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.text.style.cts.MockURLSpanTestActivity"
+            android:label="MockURLSpanTestActivity"
+            android:launchMode="singleTask"
+            android:alwaysRetainTaskState="true"
+            android:configChanges="orientation|keyboardHidden">
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.BROWSABLE" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+                <data android:scheme="ctstest" />
+            </intent-filter>
+        </activity>
+
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="com.android.cts.stub"
-                     android:label="CTS tests of android.text"/>
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.text"
+                     android:label="CTS tests of android.text">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/res/drawable/pass.jpg b/tests/tests/text/res/drawable/pass.jpg
similarity index 100%
copy from tests/res/drawable/pass.jpg
copy to tests/tests/text/res/drawable/pass.jpg
Binary files differ
diff --git a/tests/res/drawable/scenery.jpg b/tests/tests/text/res/drawable/scenery.jpg
similarity index 100%
rename from tests/res/drawable/scenery.jpg
rename to tests/tests/text/res/drawable/scenery.jpg
Binary files differ
diff --git a/tests/res/layout/keylistener_layout.xml b/tests/tests/text/res/layout/keylistener_layout.xml
similarity index 100%
rename from tests/res/layout/keylistener_layout.xml
rename to tests/tests/text/res/layout/keylistener_layout.xml
diff --git a/tests/res/layout/urlspan_layout.xml b/tests/tests/text/res/layout/urlspan_layout.xml
similarity index 100%
rename from tests/res/layout/urlspan_layout.xml
rename to tests/tests/text/res/layout/urlspan_layout.xml
diff --git a/tests/res/layout/webview_layout.xml b/tests/tests/text/res/layout/webview_layout.xml
similarity index 100%
rename from tests/res/layout/webview_layout.xml
rename to tests/tests/text/res/layout/webview_layout.xml
diff --git a/tests/tests/text/res/values/attrs.xml b/tests/tests/text/res/values/attrs.xml
new file mode 100644
index 0000000..4c3d9db
--- /dev/null
+++ b/tests/tests/text/res/values/attrs.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2008 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>
+    <declare-styleable name="Style1">
+        <attr name="Type1" format="integer">
+            <enum name="type" value="28" />
+            <enum name="data" value="0xff00ff00" />
+            <enum name="asset_cookie" value="0" />
+            <enum name="resource_id" value="0" />
+            <enum name="changing_config" value="0" />
+        </attr>
+        <attr name="Type2" format="integer">
+            <enum name="type" value="28" />
+            <enum name="data" value="0xff0000ff" />
+            <enum name="asset_cookie" value="0" />
+            <enum name="resource_id" value="0" />
+            <enum name="changing_config" value="0" />
+        </attr>
+    </declare-styleable>
+    <attr name="type1" format="boolean"/>
+    <attr name="type2" format="boolean"/>
+    <attr name="type3" format="color"/>
+    <attr name="type4" format="reference|color"/>
+    <attr name="type5" format="dimension"/>
+    <attr name="type6" format="dimension"/>
+    <attr name="type7" format="dimension"/>
+    <attr name="type8" format="reference"/>
+    <attr name="type9" format="float"/>
+    <attr name="type10" format="fraction"/>
+    <attr name="type11" format="integer"/>
+    <attr name="type12" format="integer"/>
+    <attr name="type13" format="reference|string"/>
+    <attr name="type14" format="string"/>
+    <attr name="type15" format="reference"/>
+    <attr name="type16" format="string"/>
+    <declare-styleable name="style1">
+        <attr name="type1"/>
+        <attr name="type2"/>
+        <attr name="type3"/>
+        <attr name="type4"/>
+        <attr name="type5"/>
+        <attr name="type6"/>
+        <attr name="type7"/>
+        <attr name="type8"/>
+        <attr name="type9"/>
+        <attr name="type10"/>
+        <attr name="type11"/>
+        <attr name="type12"/>
+        <attr name="type13"/>
+        <attr name="type14"/>
+        <attr name="type15"/>
+        <attr name="type16"/>
+    </declare-styleable>
+    <attr name="testEnum">
+        <enum name="val1" value="1" />
+        <enum name="val2" value="2" />
+        <enum name="val10" value="10" />
+    </attr>
+    <attr name="testFlags">
+        <flag name="bit1" value="0x1" />
+        <flag name="bit2" value="0x2" />
+        <flag name="bit31" value="0x40000000" />
+    </attr>
+    <attr name="testString" format="string" />
+    <declare-styleable name="EnumStyle">
+        <attr name="testEnum" />
+    </declare-styleable>
+    <declare-styleable name="FlagStyle">
+        <attr name="testFlags" />
+    </declare-styleable>
+    <declare-styleable name="TestConfig">
+        <attr name="testString" />
+    </declare-styleable>
+    <!-- Size of text. Recommended dimension type for text is "sp" for scaled-pixels (example: 15sp).
+         Supported values include the following:<p/>
+    <ul>
+        <li><b>px</b> Pixels</li>
+        <li><b>sp</b> Scaled pixels (scaled to relative pixel size on screen). See {@link android.util.DisplayMetrics} for more information.</li>
+        <li><b>pt</b> Points</li>
+        <li><b>dip</b> Device independent pixels. See {@link android.util.DisplayMetrics} for more information.</li>
+    </ul>
+    -->
+    <attr name="textSize" format="dimension" />
+    <attr name="typeface">
+        <enum name="normal" value="0" />
+        <enum name="sans" value="1" />
+        <enum name="serif" value="2" />
+        <enum name="monospace" value="3" />
+    </attr>
+    <!-- Default text typeface style. -->
+    <attr name="textStyle">
+        <flag name="normal" value="0" />
+        <flag name="bold" value="1" />
+        <flag name="italic" value="2" />
+    </attr>
+    <!-- Color of text (usually same as colorForeground). -->
+    <attr name="textColor" format="reference|color" />
+    <!-- Color of highlighted text. -->
+    <attr name="textColorHighlight" format="reference|color" />
+    <!-- Color of hint text (displayed when the field is empty). -->
+    <attr name="textColorHint" format="reference|color" />
+    <!-- Color of link text (URLs). -->
+    <attr name="textColorLink" format="reference|color" />
+    <declare-styleable name="TextAppearance">
+        <attr name="textColor"/>
+        <attr name="textSize"/>
+        <attr name="textStyle"/>
+        <attr name="typeface"/>
+        <attr name="textColorHighlight"/>
+        <attr name="textColorHint"/>
+        <attr name="textColorLink"/>
+    </declare-styleable>
+    <!-- Integer used to uniquely identify theme overrides. -->
+    <attr name="themeType" format="integer"/>
+    <!-- Theme reference used to override parent theme. -->
+    <attr name="themeOverrideAttr" format="reference"/>
+
+    <!-- Drawable theming attributes -->
+    <attr name="themeBoolean" />
+    <attr name="themeColor" />
+    <attr name="themeFloat" />
+    <attr name="themeInteger" />
+    <attr name="themeDimension" />
+    <attr name="themeDrawable" />
+    <attr name="themeBitmap" />
+    <attr name="themeNinePatch" />
+    <attr name="themeGravity" />
+    <attr name="themeTileMode" />
+    <attr name="themeAngle" />
+</resources>
diff --git a/tests/tests/text/res/values/strings.xml b/tests/tests/text/res/values/strings.xml
new file mode 100644
index 0000000..c167278
--- /dev/null
+++ b/tests/tests/text/res/values/strings.xml
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="permlab_testGranted">Test Granted</string>
+    <string name="permdesc_testGranted">Used for running CTS tests, for testing operations
+        where we have the permission.</string>
+    <string name="permlab_testDynamic">Test Dynamic</string>
+    <string name="permdesc_testDynamic">Used for running CTS tests, for testing adding
+        dynamic permissions.</string>
+    <string name="permlab_testDenied">Test Denied</string>
+    <string name="permdesc_testDenied">Used for running CTS tests, for testing operations
+        where we do not have the permission.</string>
+    <string name="explain">1. click start. \n2. if above image shaked, then press pass button,
+         else press failed button.</string>
+    <string name="text_view_hello">Hello! Text view!</string>
+    <string name="text_view_hello_two_lines">Hello! \nText view!</string>
+    <string name="text_view_simple_hint">This is a hint.</string>
+    <string name="text_view_hint">This is a string for testing hint of textview.</string>
+    <string name="activity_forwarding">App/Forwarding</string>
+    <string name="forwarding">$$$</string>
+    <string name="go">Go</string>
+    <string name="back">Back</string>
+    <string name="forward_target">
+        Press back button and notice we don\'t see the previous activity.
+    </string>
+    <string name="edit_text">testing</string>
+    <string name="text">DialogTest</string>
+    <string name="text_country">Country</string>
+    <string name="text_name">Name</string>
+    <string name="hello_world">Hello, World!</string>
+    <string name="hello_android">Hello, Android!</string>
+    <string name="alert_dialog_username">Name:</string>
+    <string name="alert_dialog_password">Password:</string>
+    <string name="alert_dialog_positive">Positive</string>
+    <string name="alert_dialog_negative">Negative</string>
+    <string name="alert_dialog_neutral">Neutral</string>
+    <string name="notify">Notify </string>
+    <string name="tabs_1">testing</string>
+    <string name="table_layout_first">first</string>
+    <string name="table_layout_second">second</string>
+    <string name="table_layout_third">third</string>
+    <string name="table_layout_long">Very long to make the string out of the screen</string>
+    <string name="chronometer_text">Test Chronometer</string>
+    <string name="am">AM</string>
+    <string name="pm">PM</string>
+    <string name="viewgroup_test">ViewGroup test</string>
+    <string name="viewanimator_test">ViewAnimator test</string>
+    <string name="id_ok">OK</string>
+    <string name="id_cancel">Cancel</string>
+    <string name="context_test_string1">This is %s string.</string>
+    <string name="context_test_string2">This is test string.</string>
+    <string name="animationutils_test_instructions">Choose different animations</string>
+    <string name="animationutils_test_alpha">Alpha animation</string>
+    <string name="animationutils_test_scale">Scale animation</string>
+    <string name="animationutils_test_rotate">Rotate animation</string>
+    <string name="animationutils_test_translate">Translate animation</string>
+    <string name="animationutils_test_set">Animation set</string>
+    <string name="animationutils_test_layout">Layout animation</string>
+    <string name="animationutils_test_gridlayout">Grid layout animation</string>
+    <string name="twolinelistitem_test_text1">text1</string>
+    <string name="twolinelistitem_test_text2">text2</string>
+    <string name="metadata_text">metadata text</string>
+    <string name="horizontal_text_1">horizontal 1</string>
+    <string name="horizontal_text_2">horizontal 2</string>
+    <string name="horizontal_text_3">horizontal 3</string>
+    <string name="vertical_text_1">vertical 1</string>
+    <string name="vertical_text_2">vertical 2</string>
+    <string name="vertical_text_3">vertical 3</string>
+    <string name="reference">here</string>
+    <string name="coerceIntegerToString">100</string>
+    <string name="coerceBooleanToString">true</string>
+    <string name="coerceColorToString">#fff</string>
+    <string name="coerceFloatToString">100.0</string>
+    <string name="coerceDimensionToString">100px</string>
+    <string name="coerceFractionToString">100<xliff:g id="percent">%</xliff:g></string>
+    <string name="formattedStringNone">Format[]</string>
+    <string name="formattedStringOne">Format[<xliff:g id="format">%d</xliff:g>]</string>
+    <string name="formattedStringTwo">Format[<xliff:g id="format">%3$d,%2$s</xliff:g>]</string>
+    <string name="checkboxpref_key">checkboxpref_key</string>
+   <string name="checkboxpref_title">title of preference</string>
+   <string name="checkboxpref_summary">summary of preference</string>
+   <string name="checkboxpref_summary_on">summary on of preference</string>
+   <string name="checkboxpref_summary_off">summary off of preference</string>
+   <string name="checkboxpref_depend">checkboxpref_depend</string>
+   <string name="checkboxpref_depend_title"> depend title of preference</string>
+   <string name="checkboxpref_depend_summary"> depend summary of preference</string>
+   <string name="edittextpref_key">edittextpref_key</string>
+   <string name="edittextpref_default_value">default value of preference</string>
+   <string name="edittextpref_title">title of edit text preference</string>
+   <string name="edittextpref_summary">summary of edit text preference</string>
+   <string name="edittextpref_dialog_title">dialog title of edit text preference</string>
+   <string name="edittextpref_text">text of  edit text preference</string>
+   <string name="listpref_key">listpref_key</string>
+   <string name="listpref_title">title of list preference</string>
+   <string name="listpref_summary">summary of list preference</string>
+   <string name="listpref_dialogtitle">dialog title of list preference</string>
+   <string name="easy">Easy</string>
+   <string name="medium">Medium</string>
+   <string name="hard">Hard</string>
+   <string name="footer_view">Footer view</string>
+   <string name="header_view">Header view</string>
+   <string name="dialogpref_title">title of dialog preference </string>
+   <string name="dialogpref_dialog_title">dialog title of dialog preference </string>
+   <string name="dialogpref_key">dialogpref_key</string>
+   <string name="dialogpref_default_value">default value of dialog preference</string>
+   <string name="dialogpref_summary">summary of dialog preference</string>
+   <string name="dialogpref_message">message of dialog preference</string>
+   <string name="dialogpref_sure">Sure</string>
+   <string name="dialogpref_cancel">Cancel</string>
+   <string name="pref_key">pref_key</string>
+   <string name="pref_title">title of preference</string>
+   <string name="pref_summary">summary of preference</string>
+   <string name="pref_depend_key">pref_depend_key</string>
+   <string name="pref_depend_title"> depend title of preference</string>
+   <string name="pref_depend_summary"> depend summary of preference</string>
+   <string name="android_intent_action_preference">android.intent.action.PREFERENCE</string>
+   <string name="def_pref_key">def_pref_key</string>
+   <string name="def_pref_title">default preference</string>
+   <string name="def_pref_summary">This is default preference of cts</string>
+   <string name="relative_view1">view 1</string>
+   <string name="relative_view2">view 2</string>
+   <string name="relative_view3">view 3</string>
+   <string name="relative_view4">view 4</string>
+   <string name="relative_view5">view 5</string>
+   <string name="relative_view6">view 6</string>
+   <string name="relative_view7">view 7</string>
+   <string name="relative_view8">view 8</string>
+   <string name="relative_view9">view 9</string>
+   <string name="relative_view10">view 10</string>
+   <string name="relative_view11">view 11</string>
+   <string name="relative_view12">view 12</string>
+   <string name="relative_view13">view 13</string>
+   <string name="country">Country:</string>
+   <string name="symbol">Symbol:</string>
+   <string name="country_warning">No such country registered</string>
+   <string name="version_cur">base</string>
+   <string name="version_old">base</string>
+   <string name="version_v3">base</string>
+   <string name="authenticator_label">Android CTS</string>
+   <string name="search_label">Android CTS</string>
+   <string name="tag1">tag 1</string>
+   <string name="tag2">tag 2</string>
+
+   <string name="button">Button</string>
+   <string name="holo_test">Holo Test</string>
+   <string name="holo_generator">Holo Generator</string>
+   <string name="holo_light_test">Holo Light Test</string>
+   <string name="holo_light_generator">Holo Light Generator</string>
+   <string name="reference_image">Reference Image: </string>
+   <string name="generated_image">Generated Image: </string>
+   <string name="themes_prompt">Select a Theme:</string>
+   <string name="sample_text">Sample text goes here. I wanted something creative and whimsical
+but then I just got bored...</string>
+    <string name="long_text">This is a really long string which exceeds the width of the view.
+New devices have a much larger screen which actually enables long strings to be displayed
+with no fading. I have made this string longer to fix this case. If you are correcting this
+text, I would love to see the kind of devices you guys now use! Guys, maybe some devices need longer string!
+I think so, so how about double this string, like copy and paste!
+This is a really long string which exceeds the width of the view.
+New devices have a much larger screen which actually enables long strings to be displayed
+with no fading. I have made this string longer to fix this case. If you are correcting this
+text, I would love to see the kind of devices you guys now use! Guys, maybe some devices need longer string!
+I think so, so how about double this string, like copy and paste! </string>
+    <string name="rectangle200">"M 0,0 l 200,0 l 0, 200 l -200, 0 z"</string>
+</resources>
diff --git a/tests/tests/text/src/android/text/cts/BoringLayoutTest.java b/tests/tests/text/src/android/text/cts/BoringLayoutTest.java
index b7e2215..8a60a5b 100644
--- a/tests/tests/text/src/android/text/cts/BoringLayoutTest.java
+++ b/tests/tests/text/src/android/text/cts/BoringLayoutTest.java
@@ -79,69 +79,29 @@
                 DEFAULT_OUTER_WIDTH);
     }
 
-    public void testScale() {
+    private void verifyMultAddScale(float spacingMult, float spacingAdd) {
         final int metricsBottomToTop = METRICS_BOTTOM - METRICS_TOP;
 
-        //no scale
-        BoringLayout boringLayout = makeBoringLayout(SPACING_MULT_NO_SCALE, SPACING_ADD_NO_SCALE);
-
+        BoringLayout boringLayout = makeBoringLayout(spacingMult, spacingAdd);
         assertEquals(metricsBottomToTop, boringLayout.getHeight());
         assertEquals(boringLayout.getHeight() + METRICS_TOP, boringLayout.getLineDescent(0));
+    }
 
-        // scale two times
-        float spacingMult = 2.0f;
-        boringLayout = makeBoringLayout(spacingMult, SPACING_ADD_NO_SCALE);
+    public void testScale() {
+        // no scale
+        verifyMultAddScale(1.0f, 0.0f);
 
-        assertEquals(metricsBottomToTop * spacingMult, (float) boringLayout.getHeight());
-        assertEquals(boringLayout.getHeight() + METRICS_TOP, boringLayout.getLineDescent(0));
+        // test line spacing multiplier
+        verifyMultAddScale(2.0f, 0.0f);
+        verifyMultAddScale(0.5f, 0.0f);
 
-        // scale 0.5 times
-        spacingMult = 0.5f;
-        boringLayout = makeBoringLayout(spacingMult, SPACING_ADD_NO_SCALE);
-        assertEquals(metricsBottomToTop * spacingMult, (float) boringLayout.getHeight());
-        assertEquals(boringLayout.getHeight() + METRICS_TOP, boringLayout.getLineDescent(0));
-
-        // add 1.5f
-        float spacingAdd = 1.5f;
-        float roundOff = 2.0f;
-        boringLayout = makeBoringLayout(SPACING_MULT_NO_SCALE, spacingAdd);
-        assertEquals(metricsBottomToTop + roundOff, (float) boringLayout.getHeight());
-        assertEquals(boringLayout.getHeight() + METRICS_TOP, boringLayout.getLineDescent(0));
-
-        // minus 1.6f
-        float spacingMinus = -1.6f;
-        roundOff = -2.0f;
-        boringLayout = makeBoringLayout(SPACING_MULT_NO_SCALE, spacingMinus);
-        assertEquals(metricsBottomToTop + roundOff, (float) boringLayout.getHeight());
-        assertEquals(boringLayout.getHeight() + METRICS_TOP, boringLayout.getLineDescent(0));
-
-        // add 1.4f
-        spacingAdd = 1.4f;
-        roundOff = 1.0f;
-        boringLayout = makeBoringLayout(SPACING_MULT_NO_SCALE, spacingAdd);
-        assertEquals(metricsBottomToTop + roundOff, (float) boringLayout.getHeight());
-        assertEquals(boringLayout.getHeight() + METRICS_TOP, boringLayout.getLineDescent(0));
-
-        // minus 1.4f
-        spacingMinus = -1.4f;
-        roundOff = -1.0f;
-        boringLayout = makeBoringLayout(SPACING_MULT_NO_SCALE, spacingMinus);
-        assertEquals(metricsBottomToTop + roundOff, (float) boringLayout.getHeight());
-        assertEquals(boringLayout.getHeight() + METRICS_TOP, boringLayout.getLineDescent(0));
-
-        // add 3.0f
-        spacingAdd = 3.0f;
-        roundOff = 3.0f;
-        boringLayout = makeBoringLayout(SPACING_MULT_NO_SCALE, spacingAdd);
-        assertEquals(metricsBottomToTop + roundOff, (float) boringLayout.getHeight());
-        assertEquals(boringLayout.getHeight() + METRICS_TOP, boringLayout.getLineDescent(0));
-
-        // minus 3.0f
-        spacingMinus = -3.0f;
-        roundOff = -3.0f;
-        boringLayout = makeBoringLayout(SPACING_MULT_NO_SCALE, spacingMinus);
-        assertEquals(metricsBottomToTop + roundOff, (float) boringLayout.getHeight());
-        assertEquals(boringLayout.getHeight() + METRICS_TOP, boringLayout.getLineDescent(0));
+        // test line spacing add
+        verifyMultAddScale(1.0f, 1.5f);
+        verifyMultAddScale(1.0f, -1.6f);
+        verifyMultAddScale(1.0f, 1.4f);
+        verifyMultAddScale(1.0f, -1.4f);
+        verifyMultAddScale(1.0f, 3.0f);
+        verifyMultAddScale(1.0f, -3.0f);
     }
 
     public void testPreconditions() {
diff --git a/tests/tests/text/src/android/text/cts/ClipboardManagerTest.java b/tests/tests/text/src/android/text/cts/ClipboardManagerTest.java
index e62e0f8..f0fc0fa 100644
--- a/tests/tests/text/src/android/text/cts/ClipboardManagerTest.java
+++ b/tests/tests/text/src/android/text/cts/ClipboardManagerTest.java
@@ -18,36 +18,45 @@
 
 
 import android.content.Context;
-import android.test.AndroidTestCase;
+import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
 import android.text.ClipboardManager;
 
 /**
  * Test {@link ClipboardManager}.
  */
-public class ClipboardManagerTest extends AndroidTestCase {
-    private ClipboardManager mClipboardManager;
+public class ClipboardManagerTest extends InstrumentationTestCase {
+
+    private Context mContext;
 
     @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mClipboardManager = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
+    public void setUp() {
+        mContext = getInstrumentation().getContext();
     }
 
+    @UiThreadTest
     public void testAccessText() {
+        ClipboardManager clipboardManager =
+                (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
+
         // set the expected value
         CharSequence expected = "test";
-        mClipboardManager.setText(expected);
-        assertEquals(expected, mClipboardManager.getText());
+        clipboardManager.setText(expected);
+        assertEquals(expected, clipboardManager.getText());
     }
 
+    @UiThreadTest
     public void testHasText() {
-        mClipboardManager.setText("");
-        assertFalse(mClipboardManager.hasText());
+        ClipboardManager clipboardManager =
+                (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
 
-        mClipboardManager.setText("test");
-        assertTrue(mClipboardManager.hasText());
+        clipboardManager.setText("");
+        assertFalse(clipboardManager.hasText());
 
-        mClipboardManager.setText(null);
-        assertFalse(mClipboardManager.hasText());
+        clipboardManager.setText("test");
+        assertTrue(clipboardManager.hasText());
+
+        clipboardManager.setText(null);
+        assertFalse(clipboardManager.hasText());
     }
 }
diff --git a/tests/tests/text/src/android/text/cts/EmojiCtsActivity.java b/tests/tests/text/src/android/text/cts/EmojiCtsActivity.java
new file mode 100644
index 0000000..195bdf1
--- /dev/null
+++ b/tests/tests/text/src/android/text/cts/EmojiCtsActivity.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2013 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.text.cts;
+
+import com.android.cts.text.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.cts.util.NullWebViewUtils;
+import android.webkit.WebView;
+
+public class EmojiCtsActivity extends Activity {
+    private WebView mWebView;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        try {
+            super.onCreate(savedInstanceState);
+            setContentView(R.layout.webview_layout);
+            mWebView = (WebView) findViewById(R.id.web_page);
+        } catch (Exception e) {
+            NullWebViewUtils.determineIfWebViewAvailable(this, e);
+        }
+    }
+
+    public WebView getWebView() {
+        return mWebView;
+    }
+
+    @Override
+    public void onDestroy() {
+        if (mWebView != null) {
+            mWebView.destroy();
+        }
+        super.onDestroy();
+    }
+}
diff --git a/tests/tests/text/src/android/text/cts/EmojiTest.java b/tests/tests/text/src/android/text/cts/EmojiTest.java
index 4bcc0e1..e1249f3 100644
--- a/tests/tests/text/src/android/text/cts/EmojiTest.java
+++ b/tests/tests/text/src/android/text/cts/EmojiTest.java
@@ -17,6 +17,7 @@
 package android.text.cts;
 
 import android.content.Context;
+import android.cts.util.NullWebViewUtils;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Paint;
@@ -25,15 +26,14 @@
 import android.view.KeyEvent;
 import android.view.Menu;
 import android.view.View;
-import android.webkit.cts.NullWebViewUtils;
-import android.webkit.cts.WebViewOnUiThread;
 import android.widget.TextView;
 import android.widget.EditText;
+import android.webkit.cts.WebViewOnUiThread;
 
-public class EmojiTest extends ActivityInstrumentationTestCase2<EmojiStubActivity> {
+public class EmojiTest extends ActivityInstrumentationTestCase2<EmojiCtsActivity> {
 
     public EmojiTest() {
-        super("com.android.cts.stub", EmojiStubActivity.class);
+        super("com.android.cts.text", EmojiCtsActivity.class);
     }
 
     protected void setUp() throws Exception {
@@ -94,7 +94,7 @@
 
             // Trigger activity bringup so we can determine if a WebView is available on this
             // device.
-            EmojiStubActivity activity = getActivity();
+            EmojiCtsActivity activity = getActivity();
             if (NullWebViewUtils.isWebViewAvailable()) {
                 CaptureWebView cwebview = new CaptureWebView(getInstrumentation().getContext());
                 mBitmapA = cwebview.capture(Character.toChars(comparedCodePoints[i][0]));
@@ -107,7 +107,7 @@
     /**
      * Tests EditText handles Emoji
      */
-    public void testEmojiEditable() {
+    public void testEmojiEditable() throws Throwable {
         int testedCodePoints[] = {
             0xAE,    // registered mark
             0x2764,    // heavy black heart
@@ -120,15 +120,21 @@
         for (int i = 0; i < testedCodePoints.length; i++) {
             origStr = "Test character  ";
             // cannot reuse CaptureTextView as 2nd setText call throws NullPointerException
-            EditText editText = new EditText(getInstrumentation().getContext());
+            final EditText editText = new EditText(getInstrumentation().getContext());
             editText.setText(origStr + String.valueOf(Character.toChars(testedCodePoints[i])));
 
             // confirm the emoji is added.
             newStr = editText.getText().toString();
             assertEquals(newStr.codePointCount(0, newStr.length()), origStr.length() + 1);
 
-            // Delete added character by sending KEYCODE_DEL event
-            editText.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL));
+            runTestOnUiThread(new Runnable() {
+                public void run() {
+                    // Delete added character by sending KEYCODE_DEL event
+                    editText.dispatchKeyEvent(
+                            new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL));
+                }
+            });
+            getInstrumentation().waitForIdleSync();
 
             newStr = editText.getText().toString();
             assertEquals(newStr.codePointCount(0, newStr.length()), origStr.length() + 1);
diff --git a/tests/tests/text/src/android/text/cts/MyanmarTest.java b/tests/tests/text/src/android/text/cts/MyanmarTest.java
index 60fe608..d59f2b9 100644
--- a/tests/tests/text/src/android/text/cts/MyanmarTest.java
+++ b/tests/tests/text/src/android/text/cts/MyanmarTest.java
@@ -25,7 +25,7 @@
 public class MyanmarTest extends ActivityInstrumentationTestCase2<Activity> {
 
     public MyanmarTest() {
-        super("com.android.cts.stub", Activity.class);
+        super("com.android.cts.text", Activity.class);
     }
 
     protected void setUp() throws Exception {
diff --git a/tests/tests/text/src/android/text/cts/SelectionTest.java b/tests/tests/text/src/android/text/cts/SelectionTest.java
index ed5cc6e..4946a50 100644
--- a/tests/tests/text/src/android/text/cts/SelectionTest.java
+++ b/tests/tests/text/src/android/text/cts/SelectionTest.java
@@ -240,14 +240,19 @@
         assertEquals(4, Selection.getSelectionStart(builder));
         assertEquals(4, Selection.getSelectionEnd(builder));
 
+        // move to beginning of first line (behavior changed in L)
+        assertTrue(Selection.moveUp(builder, layout));
+        assertEquals(0, Selection.getSelectionStart(builder));
+        assertEquals(0, Selection.getSelectionEnd(builder));
+
         assertFalse(Selection.moveUp(builder, layout));
-        assertEquals(4, Selection.getSelectionStart(builder));
-        assertEquals(4, Selection.getSelectionEnd(builder));
+        assertEquals(0, Selection.getSelectionStart(builder));
+        assertEquals(0, Selection.getSelectionEnd(builder));
 
         Selection.setSelection(builder, 5);
-        assertFalse(Selection.moveUp(builder, layout));
-        assertEquals(5, Selection.getSelectionStart(builder));
-        assertEquals(5, Selection.getSelectionEnd(builder));
+        assertTrue(Selection.moveUp(builder, layout));
+        assertEquals(0, Selection.getSelectionStart(builder));
+        assertEquals(0, Selection.getSelectionEnd(builder));
     }
 
     public void testMoveDown() {
@@ -272,9 +277,14 @@
         assertEquals(14, Selection.getSelectionStart(builder));
         assertEquals(14, Selection.getSelectionEnd(builder));
 
+        // move to end of last line (behavior changed in L)
+        assertTrue(Selection.moveDown(builder, layout));
+        assertEquals(18, Selection.getSelectionStart(builder));
+        assertEquals(18, Selection.getSelectionEnd(builder));
+
         assertFalse(Selection.moveDown(builder, layout));
-        assertEquals(14, Selection.getSelectionStart(builder));
-        assertEquals(14, Selection.getSelectionEnd(builder));
+        assertEquals(18, Selection.getSelectionStart(builder));
+        assertEquals(18, Selection.getSelectionEnd(builder));
 
         Selection.setSelection(builder, 10);
         Selection.moveDown(builder, layout);
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 2add424..6e89ee5 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/cts/TextUtilsTest.java b/tests/tests/text/src/android/text/cts/TextUtilsTest.java
index 885fa2a..694513e 100644
--- a/tests/tests/text/src/android/text/cts/TextUtilsTest.java
+++ b/tests/tests/text/src/android/text/cts/TextUtilsTest.java
@@ -410,7 +410,7 @@
 
         // TruncateAt.END, specify preserveLength
         resetRange();
-        textWidth = p.measureText("long str" + mEllipsis);
+        textWidth = p.measureText("long str") + p.measureText(mEllipsis);
         ellipsisNum = text.length() - "long str".length();
         assertEquals("long str" + getBlankString(true, ellipsisNum),
                 TextUtils.ellipsize(text, p, textWidth, TruncateAt.END, true, callback).toString());
@@ -2089,117 +2089,40 @@
         assertEquals(LAYOUT_DIRECTION_LTR,
                 TextUtils.getLayoutDirectionFromLocale(Locale.TRADITIONAL_CHINESE));
 
-        Locale locale = new Locale("ar");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("ar", "AE");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("ar", "BH");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("ar", "DZ");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("ar", "EG");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("ar", "IQ");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("ar", "JO");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("ar", "KW");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("ar", "LB");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("ar", "LY");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("ar", "MA");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("ar", "OM");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("ar", "QA");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("ar", "SA");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("ar", "SD");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("ar", "SY");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("ar", "TN");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("ar", "YE");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
+        // Some languages always use an RTL script.
+        for (Locale l : Locale.getAvailableLocales()) {
+            String languageCode = l.getLanguage();
+            if (languageCode.equals("ar") ||
+                    languageCode.equals("fa") ||
+                    languageCode.equals("iw") ||
+                    languageCode.equals("he") ||
+                    languageCode.equals("ps") ||
+                    languageCode.equals("ur")) {
+                int direction = TextUtils.getLayoutDirectionFromLocale(l);
+                assertEquals(l.toLanguageTag() + " not RTL: " + direction,
+                             LAYOUT_DIRECTION_RTL, direction);
+            }
+        }
 
-        locale = new Locale("fa");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("fa", "AF");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("fa", "IR");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-
-        locale = new Locale("iw");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("iw", "IL");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("he");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("he", "IL");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-
-        locale = new Locale("pa_Arab");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("pa_Arab", "PK");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-
-        locale = new Locale("ps");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("ps", "AF");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-
-        locale = new Locale("ur");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("ur", "IN");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("ur", "PK");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-
-        locale = new Locale("uz_Arab");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
-        locale = new Locale("uz_Arab", "AF");
-        assertEquals(LAYOUT_DIRECTION_RTL,
-                TextUtils.getLayoutDirectionFromLocale(locale));
+        // Other languages have some cases where they use an RTL script.
+        String[] tags = {
+            "pa-Arab",
+            "pa-Arab-PK",
+            "ps",
+            "ps-AF",
+            "uz-Arab",
+            "uz-Arab-AF",
+        };
+        for (String tag : tags) {
+            Locale l = Locale.forLanguageTag(tag);
+            int direction = TextUtils.getLayoutDirectionFromLocale(l);
+            assertEquals(l.toLanguageTag() + " not RTL: " + direction,
+                         LAYOUT_DIRECTION_RTL, direction);
+        }
 
         // Locale without a real language
-        locale = new Locale("zz");
+        Locale locale = Locale.forLanguageTag("zz");
         assertEquals(LAYOUT_DIRECTION_LTR,
                 TextUtils.getLayoutDirectionFromLocale(locale));
-    }}
+    }
+}
diff --git a/tests/src/android/text/format/cts/LocaleUtils.java b/tests/tests/text/src/android/text/format/cts/LocaleUtils.java
similarity index 100%
rename from tests/src/android/text/format/cts/LocaleUtils.java
rename to tests/tests/text/src/android/text/format/cts/LocaleUtils.java
diff --git a/tests/tests/text/src/android/text/format/cts/TimeTest.java b/tests/tests/text/src/android/text/format/cts/TimeTest.java
index e287270..2d623e3 100644
--- a/tests/tests/text/src/android/text/format/cts/TimeTest.java
+++ b/tests/tests/text/src/android/text/format/cts/TimeTest.java
@@ -16,17 +16,39 @@
 
 package android.text.format.cts;
 
-import java.lang.Math;
-import java.util.Calendar;
-import java.util.TimeZone;
-
+import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.test.AndroidTestCase;
 import android.text.format.Time;
 import android.util.Log;
 import android.util.TimeFormatException;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.TimeZone;
+
 public class TimeTest extends AndroidTestCase {
     private static final String TAG = "TimeTest";
+
+    private Locale originalLocale;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        originalLocale = Locale.getDefault();
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        // The Locale may be changed by tests. Revert to the original.
+        changeJavaAndAndroidLocale(originalLocale);
+        super.tearDown();
+    }
+
     public void testConstructor() {
         Time time = new Time();
         new Time(Time.getCurrentTimezone());
@@ -194,7 +216,7 @@
         public int minute1;
         public int dst1;
 
-        public int offset;
+        public int delta;
 
         public int year2;
         public int month2;
@@ -204,7 +226,7 @@
         public int dst2;
 
         public DateTest(int year1, int month1, int day1, int hour1, int minute1, int dst1,
-                int offset, int year2, int month2, int day2, int hour2, int minute2,
+                int delta, int year2, int month2, int day2, int hour2, int minute2,
                 int dst2) {
             this.year1 = year1;
             this.month1 = month1;
@@ -212,7 +234,7 @@
             this.hour1 = hour1;
             this.minute1 = minute1;
             this.dst1 = dst1;
-            this.offset = offset;
+            this.delta = delta;
             this.year2 = year2;
             this.month2 = month2;
             this.day2 = day2;
@@ -222,14 +244,14 @@
         }
 
         public DateTest(int year1, int month1, int day1, int hour1, int minute1,
-                int offset, int year2, int month2, int day2, int hour2, int minute2) {
+                int delta, int year2, int month2, int day2, int hour2, int minute2) {
             this.year1 = year1;
             this.month1 = month1;
             this.day1 = day1;
             this.hour1 = hour1;
             this.minute1 = minute1;
             this.dst1 = -1;
-            this.offset = offset;
+            this.delta = delta;
             this.year2 = year2;
             this.month2 = month2;
             this.day2 = day2;
@@ -322,7 +344,8 @@
     };
 
     public void testNormalize1() throws Exception {
-        Time local = new Time("America/Los_Angeles");
+        String tz = "America/Los_Angeles";
+        Time local = new Time(tz);
 
         int len = dayTests.length;
         for (int index = 0; index < len; index++) {
@@ -330,37 +353,27 @@
             local.set(0, test.minute1, test.hour1, test.day1, test.month1, test.year1);
             // call normalize() to make sure that isDst is set
             local.normalize(false /* use isDst */);
-            local.monthDay += test.offset;
+            local.monthDay += test.delta;
             local.normalize(true /* ignore isDst */);
-            if (local.year != test.year2 || local.month != test.month2
-                    || local.monthDay != test.day2 || local.hour != test.hour2
-                    || local.minute != test.minute2) {
-                String expectedTime = String.format("%d-%02d-%02d %02d:%02d",
-                        test.year2, test.month2, test.day2, test.hour2, test.minute2);
-                String actualTime = String.format("%d-%02d-%02d %02d:%02d",
-                        local.year, local.month, local.monthDay, local.hour, local.minute);
-                throw new RuntimeException(
-                        "day test index " + index + ", normalize(): expected local " + expectedTime
-                                + " got: " + actualTime);
-            }
+
+            Time expected = new Time(tz);
+            Fields.setDateTime(expected, test.year2, test.month2, test.day2, test.hour2,
+                    test.minute2, 0);
+            Fields.assertTimeEquals("day test index " + index + ", normalize():",
+                    Fields.MAIN_DATE_TIME, expected, local);
 
             local.set(0, test.minute1, test.hour1, test.day1, test.month1, test.year1);
             // call normalize() to make sure that isDst is set
             local.normalize(false /* use isDst */);
-            local.monthDay += test.offset;
+            local.monthDay += test.delta;
             long millis = local.toMillis(true /* ignore isDst */);
             local.set(millis);
-            if (local.year != test.year2 || local.month != test.month2
-                    || local.monthDay != test.day2 || local.hour != test.hour2
-                    || local.minute != test.minute2) {
-                String expectedTime = String.format("%d-%02d-%02d %02d:%02d",
-                        test.year2, test.month2, test.day2, test.hour2, test.minute2);
-                String actualTime = String.format("%d-%02d-%02d %02d:%02d",
-                        local.year, local.month, local.monthDay, local.hour, local.minute);
-                throw new RuntimeException(
-                        "day test index " + index + ", toMillis(): expected local " + expectedTime
-                                + " got: " + actualTime);
-            }
+
+            expected = new Time(tz);
+            Fields.setDateTime(expected, test.year2, test.month2, test.day2, test.hour2,
+                    test.minute2, 0);
+            Fields.assertTimeEquals("day test index " + index + ", toMillis():",
+                    Fields.MAIN_DATE_TIME, expected, local);
         }
 
         len = minuteTests.length;
@@ -371,60 +384,166 @@
             // call normalize() to make sure that isDst is set
             local.normalize(false /* use isDst */);
             if (test.dst2 == -1) test.dst2 = local.isDst;
-            local.minute += test.offset;
+            local.minute += test.delta;
             local.normalize(false /* use isDst */);
-            if (local.year != test.year2 || local.month != test.month2
-                    || local.monthDay != test.day2 || local.hour != test.hour2
-                    || local.minute != test.minute2 || local.isDst != test.dst2) {
-                String expectedTime = String.format("%d-%02d-%02d %02d:%02d isDst: %d",
-                        test.year2, test.month2, test.day2, test.hour2, test.minute2,
-                        test.dst2);
-                String actualTime = String.format("%d-%02d-%02d %02d:%02d isDst: %d",
-                        local.year, local.month, local.monthDay, local.hour, local.minute,
-                        local.isDst);
-                throw new RuntimeException(
-                        "minute test index " + index + ", normalize(): expected local "
-                                + expectedTime + " got: " + actualTime);
-            }
+
+            Time expected = new Time(tz);
+            Fields.setDateTime(expected, test.year2, test.month2, test.day2, test.hour2,
+                    test.minute2, 0);
+            Fields.setDst(expected, test.dst2 /* isDst */, PstPdt.getUtcOffsetSeconds(test.dst2));
+            Fields.assertTimeEquals("minute test index " + index + ", normalize():",
+                    Fields.MAIN_DATE_TIME | Fields.DST_FIELDS, expected, local);
 
             local.set(0, test.minute1, test.hour1, test.day1, test.month1, test.year1);
             local.isDst = test.dst1;
             // call normalize() to make sure that isDst is set
             local.normalize(false /* use isDst */);
             if (test.dst2 == -1) test.dst2 = local.isDst;
-            local.minute += test.offset;
+            local.minute += test.delta;
             long millis = local.toMillis(false /* use isDst */);
             local.set(millis);
-            if (local.year != test.year2 || local.month != test.month2
-                    || local.monthDay != test.day2 || local.hour != test.hour2
-                    || local.minute != test.minute2 || local.isDst != test.dst2) {
-                String expectedTime = String.format("%d-%02d-%02d %02d:%02d isDst: %d",
-                        test.year2, test.month2, test.day2, test.hour2, test.minute2,
-                        test.dst2);
-                String actualTime = String.format("%d-%02d-%02d %02d:%02d isDst: %d",
-                        local.year, local.month, local.monthDay, local.hour, local.minute,
-                        local.isDst);
-                throw new RuntimeException(
-                        "minute test index " + index + ", toMillis(): expected local "
-                                + expectedTime + " got: " + actualTime);
-            }
+
+            expected = new Time(tz);
+            Fields.setDateTime(expected, test.year2, test.month2, test.day2, test.hour2,
+                    test.minute2, 0);
+            Fields.setDst(expected, test.dst2 /* isDst */, PstPdt.getUtcOffsetSeconds(test.dst2));
+            Fields.assertTimeEquals("minute test index " + index + ", toMillis():",
+                    Fields.MAIN_DATE_TIME | Fields.DST_FIELDS, expected, local);
         }
     }
 
-    public void testSwitchTimezone0() throws Exception {
-        final String timeZone = "America/Los_Angeles";
-        Time t = new Time(Time.TIMEZONE_UTC);
-        t.parse("20061005T120000");
-        t.switchTimezone(timeZone);
-        assertEquals(timeZone, t.timezone);
+    public void testSwitchTimezone_simpleUtc() throws Exception {
+        String originalTz = Time.TIMEZONE_UTC;
+        Time t = new Time(originalTz);
+        Fields.set(t, 2006, 9, 5, 12, 0, 0, -1 /* isDst */, 0, 0, 0);
+
+        String newTz = "America/Los_Angeles";
+        t.switchTimezone(newTz);
+
+        Time expected1 = new Time(newTz);
+        Fields.set(expected1, 2006, 9, 5, 5, 0, 0, 1 /* isDst */, -25200, 277, 4);
+        Fields.assertTimeEquals(expected1, t);
+
+        t.switchTimezone(originalTz);
+
+        Time expected2 = new Time(originalTz);
+        Fields.set(expected2, 2006, 9, 5, 12, 0, 0, 0 /* isDst */, 0, 277, 4);
+        Fields.assertTimeEquals(expected2, t);
     }
 
-    public void testCtor0() throws Exception {
-        Time t = new Time(Time.TIMEZONE_UTC);
-        assertEquals(Time.TIMEZONE_UTC, t.timezone);
+    public void testSwitchTimezone_standardToStandardTime() throws Exception {
+        String zone1 = "Europe/London";
+        String zone2 = "America/Los_Angeles";
+
+        // A time unambiguously in standard time in both zones.
+        Time t = new Time(zone1);
+        Fields.set(t, 2007, 2, 10, 12, 0, 0, -1 /* isDst */, 0, 0, 0);
+
+        t.switchTimezone(zone2);
+
+        Time expected1 = new Time(zone2);
+        Fields.set(expected1, 2007, 2, 10, 4, 0, 0, 0 /* isDst */, -28800, 68, 6);
+        Fields.assertTimeEquals(expected1, t);
+
+        t.switchTimezone(zone1);
+
+        Time expected2 = new Time(zone1);
+        Fields.set(expected2, 2007, 2, 10, 12, 0, 0, 0 /* isDst */, 0, 68, 6);
+        Fields.assertTimeEquals(expected2, t);
     }
 
-    public void testGetActualMaximum0() throws Exception {
+    public void testSwitchTimezone_dstToDstTime() throws Exception {
+        String zone1 = "Europe/London";
+        String zone2 = "America/Los_Angeles";
+
+        // A time unambiguously in DST in both zones.
+        Time t = new Time(zone1);
+        Fields.set(t, 2007, 2, 26, 12, 0, 0, -1 /* isDst */, 0, 0, 0);
+
+        t.switchTimezone(zone2);
+
+        Time expected1 = new Time(zone2);
+        Fields.set(expected1, 2007, 2, 26, 4, 0, 0, 1 /* isDst */, -25200, 84, 1);
+        Fields.assertTimeEquals(expected1, t);
+
+        t.switchTimezone(zone1);
+
+        Time expected2 = new Time(zone1);
+        Fields.set(expected2, 2007, 2, 26, 12, 0, 0, 1 /* isDst */, 3600, 84, 1);
+        Fields.assertTimeEquals(expected2, t);
+    }
+
+    public void testSwitchTimezone_standardToDstTime() throws Exception {
+        String zone1 = "Europe/London";
+        String zone2 = "America/Los_Angeles";
+
+        // A time that is in standard time in zone1, but in DST in zone2.
+        Time t = new Time(zone1);
+        Fields.set(t, 2007, 2, 24, 12, 0, 0, -1 /* isDst */, 0, 0, 0);
+
+        t.switchTimezone(zone2);
+
+        Time expected1 = new Time(zone2);
+        Fields.set(expected1, 2007, 2, 24, 5, 0, 0, 1 /* isDst */, -25200, 82, 6);
+        Fields.assertTimeEquals(expected1, t);
+
+        t.switchTimezone(zone1);
+
+        Time expected2 = new Time(zone1);
+        Fields.set(expected2, 2007, 2, 24, 12, 0, 0, 0 /* isDst */, 0, 82, 6);
+        Fields.assertTimeEquals(expected2, t);
+    }
+
+    public void testSwitchTimezone_sourceDateInvalid() throws Exception {
+        String zone1 = "Europe/London";
+        String zone2 = "America/Los_Angeles";
+
+        // A source wall time known not to normalize because it doesn't "exist" locally.
+        Time t = new Time(zone1);
+        Fields.set(t, 2007, 2, 25, 1, 30, 0, -1 /* isDst */, 0, 0, 0);
+        assertEquals(-1, t.toMillis(false));
+
+        t.switchTimezone(zone2);
+
+        // It is assumed a sad trombone noise is also emitted from the device at this point.
+        // This illustrates why using -1 to indicate a problem, when -1 is in range, is a poor idea.
+        Time expected1 = new Time(zone2);
+        Fields.set(expected1, 1969, 11, 31, 15, 59, 59, 0 /* isDst */, -28800, 364, 3);
+        Fields.assertTimeEquals(expected1, t);
+    }
+
+    public void testSwitchTimezone_dstToStandardTime() throws Exception {
+        String zone1 = "America/Los_Angeles";
+        String zone2 = "Europe/London";
+
+        // A time that is in DST in zone1, but in standard in zone2.
+        Time t = new Time(zone1);
+        Fields.set(t, 2007, 2, 12, 12, 0, 0, -1 /* isDst */, 0, 0, 0);
+
+        t.switchTimezone(zone2);
+
+        Time expected1 = new Time(zone2);
+        Fields.set(expected1, 2007, 2, 12, 19, 0, 0, 0 /* isDst */, 0, 70, 1);
+        Fields.assertTimeEquals(expected1, t);
+
+        t.switchTimezone(zone1);
+
+        Time expected2 = new Time(zone1);
+        Fields.set(expected2, 2007, 2, 12, 12, 0, 0, 1 /* isDst */, -25200, 70, 1);
+        Fields.assertTimeEquals(expected2, t);
+    }
+
+    public void testCtor() throws Exception {
+        String tz = Time.TIMEZONE_UTC;
+        Time t = new Time(tz);
+        assertEquals(tz, t.timezone);
+
+        Time expected = new Time(tz);
+        Fields.set(expected, 1970, 0, 1, 0, 0, 0, -1 /* isDst */, 0, 0, 0);
+        Fields.assertTimeEquals(expected, t);
+    }
+
+    public void testGetActualMaximum() throws Exception {
         Time t = new Time(Time.TIMEZONE_UTC);
         assertEquals(59, t.getActualMaximum(Time.SECOND));
         assertEquals(59, t.getActualMaximum(Time.MINUTE));
@@ -484,13 +603,81 @@
         assertEquals(-1, t.isDst);
     }
 
-    public void testCompare0() throws Exception {
-        Time a = new Time(Time.TIMEZONE_UTC);
-        Time b = new Time("America/Los_Angeles");
-        assertTrue(Time.compare(a, b) < 0);
-        assertTrue(Time.compare(b, a) > 0);
-        assertTrue(Time.compare(b, b) == 0);
-        assertTrue(Time.compare(a, a) == 0);
+    public void testClear() throws Exception {
+        Time t = new Time("America/Los_Angeles");
+        Fields.set(t, 1, 2, 3, 4, 5, 6, 7 /* isDst */, 8, 9, 10);
+
+        t.clear(Time.TIMEZONE_UTC);
+
+        Time expected = new Time(Time.TIMEZONE_UTC);
+        Fields.set(expected, 0, 0, 0, 0, 0, 0, -1 /* isDst */, 0, 0, 0);
+        Fields.assertTimeEquals(expected, t);
+    }
+
+    public void testCompare() throws Exception {
+        String timezone = "America/New_York";
+        int[] aDateTimeFields = new int[] { 2005, 2, 3, 4, 5, 6 };
+
+        Time a = new Time(timezone);
+        Fields.setDateTime(a, aDateTimeFields);
+        Fields.setDst(a, 7, 8);
+        Fields.setDerivedDateTime(a, 9, 10);
+
+        int[] bDateTimeFields = new int[aDateTimeFields.length];
+        System.arraycopy(aDateTimeFields, 0, bDateTimeFields, 0, aDateTimeFields.length);
+        Time b = new Time(timezone);
+        Fields.setDateTime(b, bDateTimeFields);
+        Fields.setDst(b, 7, 8);
+        Fields.setDerivedDateTime(b, 9, 10);
+
+        // Confirm timezone behavior: When timezones differ the result depends on the millis time.
+        // This means that all date/time and the isDst field can impact compare() when timezones
+        // are different. The result is always -1, 0 or 1.
+
+        // East of New York. Millis goes down for a given wall time.
+        b.timezone = "Europe/London";
+        assertEquals(1, Time.compare(a, b));
+        assertEquals(-1, Time.compare(b, a));
+
+        // West of New York. Millis goes up for a given wall time.
+        b.timezone = "America/Los_Angeles";
+        assertEquals(-1, Time.compare(a, b));
+        assertEquals(1, Time.compare(b, a));
+
+        b.timezone = timezone;
+        assertEquals(0, Time.compare(a, b));
+        assertEquals(0, Time.compare(b, a));
+
+        // Now confirm behavior when timezones are the same: Only the date/time fields are checked
+        // and the result depends on the difference between the fields and the order in which they
+        // are checked.
+
+        // Check date/time fields
+        for (int i = 0; i < aDateTimeFields.length; i++) {
+            bDateTimeFields[i] = 99999;
+            Fields.setDateTime(b, bDateTimeFields);
+
+            assertEquals(aDateTimeFields[i] - bDateTimeFields[i], Time.compare(a, b));
+            assertEquals(bDateTimeFields[i] - aDateTimeFields[i], Time.compare(b, a));
+
+            bDateTimeFields[i] = -99999;
+            Fields.setDateTime(b, bDateTimeFields);
+
+            assertEquals(aDateTimeFields[i] - bDateTimeFields[i], Time.compare(a, b));
+            assertEquals(bDateTimeFields[i] - aDateTimeFields[i], Time.compare(b, a));
+
+            bDateTimeFields[i] = aDateTimeFields[i];
+            Fields.setDateTime(b, bDateTimeFields);
+
+            assertEquals(0, Time.compare(a, b));
+            assertEquals(0, Time.compare(b, a));
+        }
+
+        // Show that the derived fields have no effect on compare when timezones are the same.
+        Fields.setDst(b, 999, 999);
+        Fields.setDerivedDateTime(b, 999, 999);
+        assertEquals(0, Time.compare(a, b));
+        assertEquals(0, Time.compare(b, a));
     }
 
     public void testCompareNullFailure() throws Exception {
@@ -518,86 +705,1079 @@
         }
     }
 
-    public void testFormat0() throws Exception {
+    public void testCompare_invalidDatesAreEqualIfTimezoneDiffers() throws Exception {
+        String timezone = "America/New_York";
+        // This date is outside of the valid set of dates that can be calculated so toMillis()
+        // returns -1.
+        int[] dateTimeFields = new int[] { 1, 2, 3, 4, 5, 6 };
+
+        Time a = new Time(timezone);
+        Fields.setDateTime(a, dateTimeFields);
+        Fields.setDst(a, 7, 8);
+        Fields.setDerivedDateTime(a, 9, 10);
+        assertEquals(-1, a.toMillis(false));
+
+        Time b = new Time(timezone);
+        Fields.setDateTime(b, dateTimeFields);
+        Fields.setDst(b, 11, 12);
+        Fields.setDerivedDateTime(b, 13, 14);
+        assertEquals(-1, b.toMillis(false));
+
+        // DST and derived-date time fields are always ignored.
+        assertEquals(0, Time.compare(a, b));
+
+        // Set a different invalid set of date fields.
+        Fields.setDateTime(b, new int[] { 6, 5, 4, 3, 2, 1 });
+        assertEquals(-5, Time.compare(a, b));
+
+        // Now change the timezone
+        b.timezone = Time.TIMEZONE_UTC;
+
+        // >:-(
+        assertEquals(0, Time.compare(a, b));
+    }
+
+    public void testFormat() throws Exception {
         Time t = new Time(Time.TIMEZONE_UTC);
         String r = t.format("%Y%m%dT%H%M%S");
         assertEquals("19700101T000000", r);
     }
 
-    public void testSetToNow0() throws Exception {
+    public void testFormat_null() {
         Time t = new Time(Time.TIMEZONE_UTC);
-        // Time has resolution of 1 second. So round-off to second and compare
-        long currentTime = System.currentTimeMillis() / 1000;
+        assertEquals(t.format("%c"), t.format(null));
+    }
+
+    public void testFormat_badPatterns() throws Exception {
+        Time t = new Time(Time.TIMEZONE_UTC);
+        assertFormatEquals(t, "%~Y", "~Y");
+        assertFormatEquals(t, "%", "%");
+    }
+
+    public void testFormat_doesNotNormalize() throws Exception {
+        Time t = new Time(Time.TIMEZONE_UTC);
+        Fields.set(t, 2005, 13, 32, -1, -1, -1, -2, -2, -2, -2);
+
+        Time tCopy = new Time(t);
+        Fields.assertTimeEquals(t, tCopy);
+
+        assertFormatEquals(t, "%Y%m%dT%H%M%S", "20051432T-1-1-1");
+
+        Fields.assertTimeEquals(t, tCopy);
+    }
+
+    private static void assertFormatEquals(Time t, String formatArg, String expected) {
+        assertEquals(expected, t.format(formatArg));
+    }
+
+    public void testFormat_tokensUkLocale() throws Exception {
+        changeJavaAndAndroidLocale(Locale.UK);
+
+        Time t = new Time("Europe/London");
+        Fields.setDateTime(t, 2005, 5, 1, 12, 30, 15);
+
+        // Prove the un-normalized fields are used.
+        assertFormatEquals(t, "%A", "Sunday");
+
+        // Set fields like weekday.
+        t.normalize(true);
+
+        assertFormatEquals(t, "%A", "Wednesday");
+        assertFormatEquals(t, "%a", "Wed");
+        assertFormatEquals(t, "%B", "June");
+        assertFormatEquals(t, "%b", "Jun");
+        assertFormatEquals(t, "%C", "20");
+        assertFormatEquals(t, "%c", "1 Jun 2005, 12:30:15");
+        assertFormatEquals(t, "%D", "06/01/05");
+        assertFormatEquals(t, "%d", "01");
+        assertFormatEquals(t, "%E", "E");
+        assertFormatEquals(t, "%e", " 1");
+        assertFormatEquals(t, "%F", "2005-06-01");
+        assertFormatEquals(t, "%G", "2005");
+        assertFormatEquals(t, "%g", "05");
+        assertFormatEquals(t, "%H", "12");
+        assertFormatEquals(t, "%h", "Jun");
+        assertFormatEquals(t, "%I", "12");
+        assertFormatEquals(t, "%j", "152");
+        assertFormatEquals(t, "%K", "K");
+        assertFormatEquals(t, "%k", "12");
+        assertFormatEquals(t, "%l", "12");
+        assertFormatEquals(t, "%M", "30");
+        assertFormatEquals(t, "%m", "06");
+        assertFormatEquals(t, "%n", "\n");
+        assertFormatEquals(t, "%O", "O");
+        assertFormatEquals(t, "%p", "pm");
+        assertFormatEquals(t, "%P", "pm");
+        assertFormatEquals(t, "%R", "12:30");
+        assertFormatEquals(t, "%r", "12:30:15 pm");
+        assertFormatEquals(t, "%S", "15");
+        // The original C implementation uses the (native) system default TZ, not the timezone of
+        // the Time to calculate this and was therefore not stable. This changed to use the Time's
+        // timezone when the Time class was re-written in Java.
+        assertFormatEquals(t, "%s", "1117625415");
+        assertFormatEquals(t, "%T", "12:30:15");
+        assertFormatEquals(t, "%t", "\t");
+        assertFormatEquals(t, "%U", "22");
+        assertFormatEquals(t, "%u", "3");
+        assertFormatEquals(t, "%V", "22");
+        assertFormatEquals(t, "%v", " 1-Jun-2005");
+        assertFormatEquals(t, "%W", "22");
+        assertFormatEquals(t, "%w", "3");
+        assertFormatEquals(t, "%X", "12:30:15");
+        assertFormatEquals(t, "%x", "1 June 2005");
+        assertFormatEquals(t, "%y", "05");
+        assertFormatEquals(t, "%Y", "2005");
+        assertFormatEquals(t, "%Z", "BST");
+        assertFormatEquals(t, "%z", "+0100");
+        assertFormatEquals(t, "%+", "Wed Jun  1 12:30:15 BST 2005");
+        assertFormatEquals(t, "%%", "%");
+
+        // Modifiers
+
+        assertFormatEquals(t, "%EC", "20");
+        assertFormatEquals(t, "%OC", "20");
+
+        assertFormatEquals(t, "%_+", "Wed Jun  1 12:30:15 BST 2005");
+        assertFormatEquals(t, "%-+", "Wed Jun  1 12:30:15 BST 2005");
+        assertFormatEquals(t, "%0+", "Wed Jun  1 12:30:15 BST 2005");
+        assertFormatEquals(t, "%^+", "Wed Jun  1 12:30:15 BST 2005");
+        assertFormatEquals(t, "%#+", "Wed Jun  1 12:30:15 BST 2005");
+
+        assertFormatEquals(t, "%_A", "Wednesday");
+        assertFormatEquals(t, "%-A", "Wednesday");
+        assertFormatEquals(t, "%0A", "Wednesday");
+        assertFormatEquals(t, "%^A", "WEDNESDAY");
+        assertFormatEquals(t, "%#A", "wEDNESDAY");
+
+        assertFormatEquals(t, "%_Y", "20 5");
+        assertFormatEquals(t, "%-Y", "205");
+        assertFormatEquals(t, "%0Y", "2005");
+        assertFormatEquals(t, "%^Y", "2005");
+        assertFormatEquals(t, "%#Y", "2005");
+
+        assertFormatEquals(t, "%_d", " 1");
+        assertFormatEquals(t, "%-d", "1");
+        assertFormatEquals(t, "%0d", "01");
+        assertFormatEquals(t, "%^d", "01");
+        assertFormatEquals(t, "%#d", "01");
+    }
+
+    public void testFormat_tokensUsLocale() throws Exception {
+        changeJavaAndAndroidLocale(Locale.US);
+
+        Time t = new Time("America/New_York");
+        Fields.setDateTime(t, 2005, 5, 1, 12, 30, 15);
+
+        // Prove the un-normalized fields are used.
+        assertFormatEquals(t, "%A", "Sunday");
+
+        // Set fields like weekday.
+        t.normalize(true);
+
+        assertFormatEquals(t, "%A", "Wednesday");
+        assertFormatEquals(t, "%a", "Wed");
+        assertFormatEquals(t, "%B", "June");
+        assertFormatEquals(t, "%b", "Jun");
+        assertFormatEquals(t, "%C", "20");
+        assertFormatEquals(t, "%c", "Jun 1, 2005, 12:30:15 PM");
+        assertFormatEquals(t, "%D", "06/01/05");
+        assertFormatEquals(t, "%d", "01");
+        assertFormatEquals(t, "%E", "E");
+        assertFormatEquals(t, "%e", " 1");
+        assertFormatEquals(t, "%F", "2005-06-01");
+        assertFormatEquals(t, "%G", "2005");
+        assertFormatEquals(t, "%g", "05");
+        assertFormatEquals(t, "%H", "12");
+        assertFormatEquals(t, "%h", "Jun");
+        assertFormatEquals(t, "%I", "12");
+        assertFormatEquals(t, "%j", "152");
+        assertFormatEquals(t, "%K", "K");
+        assertFormatEquals(t, "%k", "12");
+        assertFormatEquals(t, "%l", "12");
+        assertFormatEquals(t, "%M", "30");
+        assertFormatEquals(t, "%m", "06");
+        assertFormatEquals(t, "%n", "\n");
+        assertFormatEquals(t, "%O", "O");
+        assertFormatEquals(t, "%p", "PM");
+        assertFormatEquals(t, "%P", "pm");
+        assertFormatEquals(t, "%R", "12:30");
+        assertFormatEquals(t, "%r", "12:30:15 PM");
+        assertFormatEquals(t, "%S", "15");
+        // The original C implementation uses the (native) system default TZ, not the timezone of
+        // the Time to calculate this and was therefore not stable. This changed to use the Time's
+        // timezone when the Time class was re-written in Java.
+        assertFormatEquals(t, "%s", "1117643415");
+        assertFormatEquals(t, "%T", "12:30:15");
+        assertFormatEquals(t, "%t", "\t");
+        assertFormatEquals(t, "%U", "22");
+        assertFormatEquals(t, "%u", "3");
+        assertFormatEquals(t, "%V", "22");
+        assertFormatEquals(t, "%v", " 1-Jun-2005");
+        assertFormatEquals(t, "%W", "22");
+        assertFormatEquals(t, "%w", "3");
+        assertFormatEquals(t, "%X", "12:30:15 PM");
+        assertFormatEquals(t, "%x", "June 1, 2005");
+        assertFormatEquals(t, "%y", "05");
+        assertFormatEquals(t, "%Y", "2005");
+        assertFormatEquals(t, "%Z", "EDT");
+        assertFormatEquals(t, "%z", "-0400");
+        assertFormatEquals(t, "%+", "Wed Jun  1 12:30:15 EDT 2005");
+        assertFormatEquals(t, "%%", "%");
+
+        // Modifiers
+
+        assertFormatEquals(t, "%EC", "20");
+        assertFormatEquals(t, "%OC", "20");
+
+        assertFormatEquals(t, "%_+", "Wed Jun  1 12:30:15 EDT 2005");
+        assertFormatEquals(t, "%-+", "Wed Jun  1 12:30:15 EDT 2005");
+        assertFormatEquals(t, "%0+", "Wed Jun  1 12:30:15 EDT 2005");
+        assertFormatEquals(t, "%^+", "Wed Jun  1 12:30:15 EDT 2005");
+        assertFormatEquals(t, "%#+", "Wed Jun  1 12:30:15 EDT 2005");
+
+        assertFormatEquals(t, "%_A", "Wednesday");
+        assertFormatEquals(t, "%-A", "Wednesday");
+        assertFormatEquals(t, "%0A", "Wednesday");
+        assertFormatEquals(t, "%^A", "WEDNESDAY");
+        assertFormatEquals(t, "%#A", "wEDNESDAY");
+
+        assertFormatEquals(t, "%_Y", "20 5");
+        assertFormatEquals(t, "%-Y", "205");
+        assertFormatEquals(t, "%0Y", "2005");
+        assertFormatEquals(t, "%^Y", "2005");
+        assertFormatEquals(t, "%#Y", "2005");
+
+        assertFormatEquals(t, "%_d", " 1");
+        assertFormatEquals(t, "%-d", "1");
+        assertFormatEquals(t, "%0d", "01");
+        assertFormatEquals(t, "%^d", "01");
+        assertFormatEquals(t, "%#d", "01");
+    }
+
+    public void testFormat_tokensFranceLocale() throws Exception {
+        changeJavaAndAndroidLocale(Locale.FRANCE);
+
+        Time t = new Time("Europe/Paris");
+        Fields.setDateTime(t, 2005, 5, 1, 12, 30, 15);
+
+        // Prove the un-normalized fields are used.
+        assertFormatEquals(t, "%A", "dimanche");
+
+        // Set fields like weekday.
+        t.normalize(true);
+
+        assertFormatEquals(t, "%A", "mercredi");
+        assertFormatEquals(t, "%a", "mer.");
+        assertFormatEquals(t, "%B", "juin");
+        assertFormatEquals(t, "%b", "juin");
+        assertFormatEquals(t, "%C", "20");
+        assertFormatEquals(t, "%c", "1 juin 2005 à 12:30:15");
+        assertFormatEquals(t, "%D", "06/01/05");
+        assertFormatEquals(t, "%d", "01");
+        assertFormatEquals(t, "%E", "E");
+        assertFormatEquals(t, "%e", " 1");
+        assertFormatEquals(t, "%F", "2005-06-01");
+        assertFormatEquals(t, "%G", "2005");
+        assertFormatEquals(t, "%g", "05");
+        assertFormatEquals(t, "%H", "12");
+        assertFormatEquals(t, "%h", "juin");
+        assertFormatEquals(t, "%I", "12");
+        assertFormatEquals(t, "%j", "152");
+        assertFormatEquals(t, "%K", "K");
+        assertFormatEquals(t, "%k", "12");
+        assertFormatEquals(t, "%l", "12");
+        assertFormatEquals(t, "%M", "30");
+        assertFormatEquals(t, "%m", "06");
+        assertFormatEquals(t, "%n", "\n");
+        assertFormatEquals(t, "%O", "O");
+        assertFormatEquals(t, "%p", "PM");
+        assertFormatEquals(t, "%P", "pm");
+        assertFormatEquals(t, "%R", "12:30");
+        assertFormatEquals(t, "%r", "12:30:15 PM");
+        assertFormatEquals(t, "%S", "15");
+        // The original C implementation uses the (native) system default TZ, not the timezone of
+        // the Time to calculate this and was therefore not stable. This changed to use the Time's
+        // timezone when the Time class was re-written in Java.
+        assertFormatEquals(t, "%s", "1117621815");
+        assertFormatEquals(t, "%T", "12:30:15");
+        assertFormatEquals(t, "%t", "\t");
+        assertFormatEquals(t, "%U", "22");
+        assertFormatEquals(t, "%u", "3");
+        assertFormatEquals(t, "%V", "22");
+        assertFormatEquals(t, "%v", " 1-juin-2005");
+        assertFormatEquals(t, "%W", "22");
+        assertFormatEquals(t, "%w", "3");
+        assertFormatEquals(t, "%X", "12:30:15");
+        assertFormatEquals(t, "%x", "1 juin 2005");
+        assertFormatEquals(t, "%y", "05");
+        assertFormatEquals(t, "%Y", "2005");
+        assertFormatEquals(t, "%Z", "GMT+02:00");
+        assertFormatEquals(t, "%z", "+0200");
+        assertFormatEquals(t, "%+", "mer. juin  1 12:30:15 GMT+02:00 2005");
+        assertFormatEquals(t, "%%", "%");
+
+        // Modifiers
+
+        assertFormatEquals(t, "%EC", "20");
+        assertFormatEquals(t, "%OC", "20");
+
+        assertFormatEquals(t, "%_+", "mer. juin  1 12:30:15 GMT+02:00 2005");
+        assertFormatEquals(t, "%-+", "mer. juin  1 12:30:15 GMT+02:00 2005");
+        assertFormatEquals(t, "%0+", "mer. juin  1 12:30:15 GMT+02:00 2005");
+        assertFormatEquals(t, "%^+", "mer. juin  1 12:30:15 GMT+02:00 2005");
+        assertFormatEquals(t, "%#+", "mer. juin  1 12:30:15 GMT+02:00 2005");
+
+        assertFormatEquals(t, "%_A", "mercredi");
+        assertFormatEquals(t, "%-A", "mercredi");
+        assertFormatEquals(t, "%0A", "mercredi");
+        assertFormatEquals(t, "%^A", "MERCREDI");
+        assertFormatEquals(t, "%#A", "MERCREDI");
+
+        assertFormatEquals(t, "%_Y", "20 5");
+        assertFormatEquals(t, "%-Y", "205");
+        assertFormatEquals(t, "%0Y", "2005");
+        assertFormatEquals(t, "%^Y", "2005");
+        assertFormatEquals(t, "%#Y", "2005");
+
+        assertFormatEquals(t, "%_d", " 1");
+        assertFormatEquals(t, "%-d", "1");
+        assertFormatEquals(t, "%0d", "01");
+        assertFormatEquals(t, "%^d", "01");
+        assertFormatEquals(t, "%#d", "01");
+    }
+
+    public void testFormat_tokensJapanLocale() throws Exception {
+        changeJavaAndAndroidLocale(Locale.JAPAN);
+
+        Time t = new Time("Asia/Tokyo");
+        Fields.setDateTime(t, 2005, 5, 1, 12, 30, 15);
+
+        // Prove the un-normalized fields are used.
+        assertFormatEquals(t, "%A", "日曜日");
+
+        // Set fields like weekday.
+        t.normalize(true);
+
+        assertFormatEquals(t, "%A", "水曜日");
+        assertFormatEquals(t, "%a", "水");
+        assertFormatEquals(t, "%B", "6月");
+        assertFormatEquals(t, "%b", "6月");
+        assertFormatEquals(t, "%C", "20");
+        assertFormatEquals(t, "%c", "2005/06/01 12:30:15");
+        assertFormatEquals(t, "%D", "06/01/05");
+        assertFormatEquals(t, "%d", "01");
+        assertFormatEquals(t, "%E", "E");
+        assertFormatEquals(t, "%e", " 1");
+        assertFormatEquals(t, "%F", "2005-06-01");
+        assertFormatEquals(t, "%G", "2005");
+        assertFormatEquals(t, "%g", "05");
+        assertFormatEquals(t, "%H", "12");
+        assertFormatEquals(t, "%h", "6月");
+        assertFormatEquals(t, "%I", "12");
+        assertFormatEquals(t, "%j", "152");
+        assertFormatEquals(t, "%k", "12");
+        assertFormatEquals(t, "%l", "12");
+        assertFormatEquals(t, "%M", "30");
+        assertFormatEquals(t, "%m", "06");
+        assertFormatEquals(t, "%n", "\n");
+        assertFormatEquals(t, "%O", "O");
+        assertFormatEquals(t, "%p", "午後");
+        assertFormatEquals(t, "%P", "午後");
+        assertFormatEquals(t, "%R", "12:30");
+        assertFormatEquals(t, "%r", "12:30:15 午後");
+        assertFormatEquals(t, "%S", "15");
+        // The original C implementation uses the (native) system default TZ, not the timezone of
+        // the Time to calculate this and was therefore not stable. This changed to use the Time's
+        // timezone when the Time class was re-written in Java.
+        assertFormatEquals(t, "%s", "1117596615");
+        assertFormatEquals(t, "%T", "12:30:15");
+        assertFormatEquals(t, "%t", "\t");
+        assertFormatEquals(t, "%U", "22");
+        assertFormatEquals(t, "%u", "3");
+        assertFormatEquals(t, "%V", "22");
+        assertFormatEquals(t, "%v", " 1-6月-2005");
+        assertFormatEquals(t, "%W", "22");
+        assertFormatEquals(t, "%w", "3");
+        assertFormatEquals(t, "%X", "12:30:15");
+        assertFormatEquals(t, "%x", "2005年6月1日");
+        assertFormatEquals(t, "%y", "05");
+        assertFormatEquals(t, "%Y", "2005");
+        assertFormatEquals(t, "%Z", "JST");
+        assertFormatEquals(t, "%z", "+0900");
+        assertFormatEquals(t, "%+", "水 6月  1 12:30:15 JST 2005");
+        assertFormatEquals(t, "%%", "%");
+
+        // Modifiers
+
+        assertFormatEquals(t, "%EC", "20");
+        assertFormatEquals(t, "%OC", "20");
+
+        assertFormatEquals(t, "%_+", "水 6月  1 12:30:15 JST 2005");
+        assertFormatEquals(t, "%-+", "水 6月  1 12:30:15 JST 2005");
+        assertFormatEquals(t, "%0+", "水 6月  1 12:30:15 JST 2005");
+        assertFormatEquals(t, "%^+", "水 6月  1 12:30:15 JST 2005");
+        assertFormatEquals(t, "%#+", "水 6月  1 12:30:15 JST 2005");
+
+        assertFormatEquals(t, "%_A", "水曜日");
+        assertFormatEquals(t, "%-A", "水曜日");
+        assertFormatEquals(t, "%0A", "水曜日");
+        assertFormatEquals(t, "%^A", "水曜日");
+        assertFormatEquals(t, "%#A", "水曜日");
+
+        assertFormatEquals(t, "%_Y", "20 5");
+        assertFormatEquals(t, "%-Y", "205");
+        assertFormatEquals(t, "%0Y", "2005");
+        assertFormatEquals(t, "%^Y", "2005");
+        assertFormatEquals(t, "%#Y", "2005");
+
+        assertFormatEquals(t, "%_d", " 1");
+        assertFormatEquals(t, "%-d", "1");
+        assertFormatEquals(t, "%0d", "01");
+        assertFormatEquals(t, "%^d", "01");
+        assertFormatEquals(t, "%#d", "01");
+    }
+
+    public void testFormat2445() throws Exception {
+        Time t = new Time(Time.TIMEZONE_UTC);
+        Fields.setDateTime(t, 2005, 5, 1, 12, 30, 15);
+
+        // UTC behavior is to add a trailing Z.
+        String expected = t.format("%Y%m%dT%H%M%SZ");
+        assertEquals(expected, t.format2445());
+
+        // Only UTC includes the Z.
+        t.timezone = "America/Los_Angeles";
+        expected = t.format("%Y%m%dT%H%M%S");
+        assertEquals(expected, t.format2445());
+
+        // There is odd behavior around negative values.
+        Fields.setDateTime(t, 2005, -1, -1, -1, -1, -1);
+        assertEquals("2005000 T0 0 0 ", t.format2445());
+    }
+
+    public void testFormat2445_doesNotNormalize() throws Exception {
+        Time t = new Time(Time.TIMEZONE_UTC);
+        Fields.set(t, 2005, 13, 32, 25, 61, 61, -2, -2, -2, -2);
+
+        Time tCopy = new Time(t);
+        Fields.assertTimeEquals(t, tCopy);
+
+        assertEquals("20051432T256161Z", t.format2445());
+        Fields.assertTimeEquals(t, tCopy);
+
+        t.timezone = tCopy.timezone = "America/Los_Angeles";
+        assertEquals("20051432T256161", t.format2445());
+        Fields.assertTimeEquals(t, tCopy);
+    }
+
+    public void testToString() throws Exception {
+        Time t = new Time(Time.TIMEZONE_UTC);
+        assertEquals("19700101T000000UTC(0,0,0,-1,0)", t.toString());
+
+        t.timezone = "America/Los_Angeles";
+        assertEquals("19700101T000000America/Los_Angeles(0,0,0,-1,28800)", t.toString());
+    }
+
+    public void testToString_doesNotNormalize() throws Exception {
+        Time t = new Time(Time.TIMEZONE_UTC);
+        Fields.set(t, 2005, 13, 32, -1, -1, -1, -2, -2, -2, -2);
+
+        Time tCopy = new Time(t);
+        Fields.assertTimeEquals(t, tCopy);
+
+        String r = t.toString();
+        assertEquals("20051432T-1-1-1UTC(-2,-2,-2,-2,1141426739)", r);
+
+        Fields.assertTimeEquals(t, tCopy);
+    }
+
+    public void testGetCurrentTimezone() throws Exception {
+        String r = Time.getCurrentTimezone();
+        assertEquals(TimeZone.getDefault().getID(), r);
+    }
+
+    public void testSetToNow() throws Exception {
+        Time t = new Time(Time.TIMEZONE_UTC);
+
+        // Time works in seconds so all millis values have to be divided by 1000, otherwise
+        // the greater accuracy of System.currentTimeMillis() causes the test to fail.
+
+        long lowerBound = System.currentTimeMillis() / 1000;
+
         t.setToNow();
-        long time = t.toMillis(false) / 1000;
-        // 1 sec of delta can happen
-        if (Math.abs(currentTime - time) > 1) {
-            fail("currentTime " + currentTime + " time " + time);
+
+        long upperBound = System.currentTimeMillis() / 1000;
+
+        long actual = t.toMillis(true /* ignore isDst */) / 1000;
+        assertTrue(lowerBound <= actual && actual <= upperBound);
+    }
+
+    public void testToMillis_utc() throws Exception {
+        Time t = new Time(Time.TIMEZONE_UTC);
+
+        long winterTimeUtcMillis = 1167613323000L;
+
+        Fields.set(t, 2007, 0, 1, 1, 2, 3, 0 /* isDst */, 1, 9, 9);
+        long r = t.toMillis(true /* ignore isDst */);
+        assertEquals(winterTimeUtcMillis, r);
+
+        Fields.set(t, 2007, 0, 1, 1, 2, 3, 1 /* isDst */, 1, 9, 9);
+        r = t.toMillis(true /* ignore isDst */);
+        assertEquals(winterTimeUtcMillis, r);
+
+        Fields.set(t, 2007, 0, 1, 1, 2, 3, -1 /* isDst */, 1, 9, 9);
+        r = t.toMillis(true /* ignore isDst */);
+        assertEquals(winterTimeUtcMillis, r);
+
+        Fields.set(t, 2007, 0, 1, 1, 2, 3, 0 /* isDst */, 1, 9, 9);
+        r = t.toMillis(false /* ignore isDst */);
+        assertEquals(winterTimeUtcMillis, r);
+
+        Fields.set(t, 2007, 0, 1, 1, 2, 3, 1 /* isDst */, 1, 9, 9);
+        r = t.toMillis(false /* ignore isDst */);
+        assertEquals(-1, r);
+
+        Fields.set(t, 2007, 0, 1, 1, 2, 3, -1 /* isDst */, 1, 9, 9);
+        r = t.toMillis(false /* ignore isDst */);
+        assertEquals(winterTimeUtcMillis, r);
+
+        long summerTimeUtcMillis = 1180659723000L;
+
+        Fields.set(t, 2007, 5, 1, 1, 2, 3, 0 /* isDst */, 1, 9, 9);
+        r = t.toMillis(true /* ignore isDst */);
+        assertEquals(summerTimeUtcMillis, r);
+
+        Fields.set(t, 2007, 5, 1, 1, 2, 3, 1 /* isDst */, 1, 9, 9);
+        r = t.toMillis(true /* ignore isDst */);
+        assertEquals(summerTimeUtcMillis, r);
+
+        Fields.set(t, 2007, 5, 1, 1, 2, 3, -1 /* isDst */, 1, 9, 9);
+        r = t.toMillis(true /* ignore isDst */);
+        assertEquals(summerTimeUtcMillis, r);
+
+        Fields.set(t, 2007, 5, 1, 1, 2, 3, 0 /* isDst */, 1, 9, 9);
+        r = t.toMillis(false /* ignore isDst */);
+        assertEquals(summerTimeUtcMillis, r);
+
+        Fields.set(t, 2007, 5, 1, 1, 2, 3, 1 /* isDst */, 1, 9, 9);
+        r = t.toMillis(false /* ignore isDst */);
+        assertEquals(-1, r);
+
+        Fields.set(t, 2007, 5, 1, 1, 2, 3, -1 /* isDst */, 1, 9, 9);
+        r = t.toMillis(false /* ignore isDst */);
+        assertEquals(summerTimeUtcMillis, r);
+    }
+
+    public void testToMillis_dstTz() throws Exception {
+        Time t = new Time(PstPdt.ID);
+
+        // A STD time
+        long stdTimeUtcMillis = 1167613323000L;
+        long stdTimeMillis = stdTimeUtcMillis - PstPdt.getUtcOffsetMillis(false);
+
+        Fields.set(t, 2007, 0, 1, 1, 2, 3, 0 /* isDst */, 9, 9, 9);
+        long r = t.toMillis(true /* ignore isDst */);
+        assertEquals(stdTimeMillis, r);
+
+        Fields.set(t, 2007, 0, 1, 1, 2, 3, 1 /* isDst */, 9, 9, 9);
+        assertToMillisResult(true, t, stdTimeMillis);
+
+        Fields.set(t, 2007, 0, 1, 1, 2, 3, -1 /* isDst */, 9, 9, 9);
+        assertToMillisResult(true, t, stdTimeMillis);
+
+        long dstToStdCorrectionMillis =
+                PstPdt.getUtcOffsetMillis(false) - PstPdt.getUtcOffsetMillis(true);
+
+        Fields.set(t, 2007, 0, 1, 1, 2, 3, 0 /* isDst */, 9, 9, 9);
+        assertToMillisResult(false, t, stdTimeMillis);
+
+        Fields.set(t, 2007, 0, 1, 1, 2, 3, 1 /* isDst */, 9, 9, 9);
+        assertToMillisResult(false, t, stdTimeMillis + dstToStdCorrectionMillis);
+
+        Fields.set(t, 2007, 0, 1, 1, 2, 3, -1 /* isDst */, 9, 9, 9);
+        assertToMillisResult(false, t, stdTimeMillis);
+
+        // A DST time
+        long dstTimeUtcMillis = 1180659723000L;
+        long dstTimeMillis = dstTimeUtcMillis - PstPdt.getUtcOffsetMillis(true);
+
+        Fields.set(t, 2007, 5, 1, 1, 2, 3, 0 /* isDst */, 9, 9, 9);
+        assertToMillisResult(true, t, dstTimeMillis);
+
+        Fields.set(t, 2007, 5, 1, 1, 2, 3, 1 /* isDst */, 9, 9, 9);
+        assertToMillisResult(true, t, dstTimeMillis);
+
+        Fields.set(t, 2007, 5, 1, 1, 2, 3, -1 /* isDst */, 9, 9, 9);
+        assertToMillisResult(true, t, dstTimeMillis);
+
+        long stdToDstCorrectionMillis = -dstToStdCorrectionMillis;
+
+        Fields.set(t, 2007, 5, 1, 1, 2, 3, 0 /* isDst */, 9, 9, 9);
+        assertToMillisResult(false, t, dstTimeMillis + stdToDstCorrectionMillis);
+
+        Fields.set(t, 2007, 5, 1, 1, 2, 3, 1 /* isDst */, 9, 9, 9);
+        assertToMillisResult(false, t, dstTimeMillis);
+
+        Fields.set(t, 2007, 5, 1, 1, 2, 3, -1 /* isDst */, 9, 9, 9);
+        assertToMillisResult(false, t, dstTimeMillis);
+    }
+
+    private static void assertToMillisResult(boolean toMillisArgument, Time t, long expectedResult) {
+        long r = t.toMillis(toMillisArgument /* ignore isDst */);
+        assertEquals(expectedResult, r);
+    }
+
+    public void testToMillis_doesNotNormalize() {
+        Time t = new Time(Time.TIMEZONE_UTC);
+
+        Fields.set(t, 2007, 13, 32, 25, 60, 60, -2 /* isDst */, Integer.MAX_VALUE, 367, 7);
+
+        Time originalTime = new Time(t);
+        Fields.assertTimeEquals(t, originalTime);
+
+        t.toMillis(true);
+        Fields.assertTimeEquals(originalTime, t);
+
+        t.toMillis(false);
+        Fields.assertTimeEquals(originalTime, t);
+    }
+
+    public void testToMillis_skippedTime() {
+        // Tests behavior around a transition from STD to DST that introduces an hour of "skipped"
+        // time from 01:00 to 01:59.
+        String timezone = PstPdt.ID;
+        long stdBaseTimeMillis = 1173607200000L;
+        long dstBaseTimeMillis = 1173603600000L;
+
+        // Try each minute from one minute before the skipped hour until one after.
+        for (int i = -1; i <= 60; i++) {
+            int minutesInMillis = i * 60000;
+            int[] timeFields = new int[] { 2007, 2, 11, 2, i, 0, -999 /* not used */, 9, 9, 9 };
+
+            Time time = new Time(timezone);
+
+            // isDst = 0, toMillis(true)
+            Fields.set(time, timeFields);
+            time.isDst = 0;
+            long expectedTimeMillis;
+            if (i == -1) {
+                expectedTimeMillis = stdBaseTimeMillis + minutesInMillis;
+            } else if (i == 60) {
+                expectedTimeMillis = dstBaseTimeMillis + minutesInMillis;
+            } else {
+                expectedTimeMillis = -1;
+            }
+            assertToMillisResult(true, time, expectedTimeMillis);
+
+            // isDst = 0, toMillis(false)
+            Fields.set(time, timeFields);
+            time.isDst = 0;
+            expectedTimeMillis = stdBaseTimeMillis + minutesInMillis;
+            assertToMillisResult(false, time, expectedTimeMillis);
+
+            // isDst = 1, toMillis(true)
+            Fields.set(time, timeFields);
+            time.isDst = 1;
+            if (i == -1) {
+                expectedTimeMillis = stdBaseTimeMillis + minutesInMillis;
+            } else if (i == 60) {
+                expectedTimeMillis = dstBaseTimeMillis + minutesInMillis;
+            } else {
+                expectedTimeMillis = -1;
+            }
+            assertToMillisResult(true, time, expectedTimeMillis);
+
+            // isDst = 1, toMillis(false)
+            Fields.set(time, timeFields);
+            time.isDst = 1;
+            expectedTimeMillis = dstBaseTimeMillis + minutesInMillis;
+            assertToMillisResult(false, time, expectedTimeMillis);
+
+            // isDst = -1, toMillis(true)
+            Fields.set(time, timeFields);
+            time.isDst = -1;
+
+            if (i == -1) {
+                expectedTimeMillis = stdBaseTimeMillis + minutesInMillis;
+            } else if (i == 60) {
+                expectedTimeMillis = dstBaseTimeMillis + minutesInMillis;
+            } else {
+                expectedTimeMillis = -1;
+            }
+            assertToMillisResult(false, time, expectedTimeMillis);
+
+            // isDst = -1, toMillis(false)
+            Fields.set(time, timeFields);
+            time.isDst = -1;
+            assertToMillisResult(false, time, expectedTimeMillis);
         }
     }
 
-    public void testMillis0() throws Exception {
-        Time t = new Time(Time.TIMEZONE_UTC);
-        t.set(0, 0, 0, 1, 1, 2006);
-        long r = t.toMillis(true);
-        assertEquals(1138752000000l, r);
+    public void testToMillis_duplicateWallTime() {
+        // 1:00 in standard / 2:00 in DST
+        long timeBaseMillis = 1194163200000L;
+        long dstCorrectionMillis = 3600000;
 
-        t.set(1, 0, 0, 1, 1, 2006);
-        r = t.toMillis(true);
-        assertEquals(1138752001000l, r);
+        // Try each minute from one minute before the duplicated hour until one after.
+        for (int i = -1; i <= 60; i++) {
+            int minutesInMillis = i * 60000;
 
-        t.set(1, 0, 0, 1, 0, 1970);
-        r = t.toMillis(true);
-        assertEquals(1000, r);
+            Time time = new Time(PstPdt.ID);
+            int[] timeFields = new int[] { 2007, 10, 4, 1, i, 0, -999 /* not used */, 9, 9, 9};
+
+            // isDst = 0, toMillis(true)
+            Fields.set(time, timeFields);
+            time.isDst = 0;
+            long timeMillis = time.toMillis(true);
+            if (i == -1) {
+                assertEquals("i = " + i, timeBaseMillis + minutesInMillis, timeMillis);
+            } else if (i == 60) {
+                assertEquals("i = " + i, timeBaseMillis + minutesInMillis + dstCorrectionMillis,
+                        timeMillis);
+            } else {
+                // When ignoreDst the choice between DST and STD is arbitrary when both are
+                // possible.
+                assertTrue("i = " + i, timeMillis == timeBaseMillis + minutesInMillis
+                        || timeMillis == timeBaseMillis + minutesInMillis + dstCorrectionMillis);
+            }
+
+            // isDst = 0, toMillis(false)
+            Fields.set(time, timeFields);
+            time.isDst = 0;
+            assertToMillisResult(false, time,
+                    timeBaseMillis + minutesInMillis + dstCorrectionMillis);
+
+            // isDst = 1, toMillis(true)
+            Fields.set(time, timeFields);
+            time.isDst = 1;
+            if (i == -1) {
+                assertEquals("i = " + i, timeBaseMillis + minutesInMillis, timeMillis);
+            } else if (i == 60) {
+                assertEquals("i = " + i, timeBaseMillis + minutesInMillis + dstCorrectionMillis,
+                        timeMillis);
+            } else {
+                // When ignoreDst or isDst == -1 the choice between DST and STD is arbitrary when
+                // both are possible.
+                assertTrue("i = " + i, timeMillis == timeBaseMillis + minutesInMillis
+                        || timeMillis == timeBaseMillis + minutesInMillis + dstCorrectionMillis);
+            }
+
+            // isDst = 1, toMillis(false)
+            Fields.set(time, timeFields);
+            time.isDst = 1;
+            assertToMillisResult(false, time, timeBaseMillis + minutesInMillis);
+
+            // isDst = -1, toMillis(true)
+            Fields.set(time, timeFields);
+            time.isDst = -1;
+            timeMillis = time.toMillis(true);
+            if (i == -1) {
+                assertEquals("i = " + i, timeBaseMillis + minutesInMillis, timeMillis);
+            } else if (i == 60) {
+                assertEquals("i = " + i, timeBaseMillis + minutesInMillis + dstCorrectionMillis,
+                        timeMillis);
+            } else {
+                // When ignoreDst or isDst == -1 the choice between DST and STD is arbitrary when
+                // both are possible.
+                assertTrue("i = " + i, timeMillis == timeBaseMillis + minutesInMillis
+                        || timeMillis == timeBaseMillis + minutesInMillis + dstCorrectionMillis);
+            }
+
+            // isDst = -1, toMillis(false)
+            Fields.set(time, timeFields);
+            time.isDst = -1;
+            timeMillis = time.toMillis(false);
+            if (i == -1) {
+                assertEquals("i = " + i, timeBaseMillis + minutesInMillis, timeMillis);
+            } else if (i == 60) {
+                assertEquals("i = " + i, timeBaseMillis + minutesInMillis + dstCorrectionMillis,
+                        timeMillis);
+            } else {
+                // When ignoreDst or isDst == -1 the choice between DST and STD is arbitrary when
+                // both are possible.
+                assertTrue("i = " + i, timeMillis == timeBaseMillis + minutesInMillis
+                        || timeMillis == timeBaseMillis + minutesInMillis + dstCorrectionMillis);
+            }
+        }
     }
 
-    public void testParse0() throws Exception {
+    public void testToMillis_beforeTzRecords() {
+        int[] timeFields = new int[] { 1900, 0, 1, 2, 3, 4, -999 /* not used */, 9, 9, 9 };
+        assertToMillisInvalid(timeFields, PstPdt.ID);
+        assertToMillisInvalid(timeFields, Time.TIMEZONE_UTC);
+    }
+
+    private static void assertToMillisInvalid(int[] timeFields, String timezone) {
+        Time time = new Time(timezone);
+
+        // isDst = 0, toMillis(true)
+        Fields.set(time, timeFields);
+        time.isDst = 0;
+        assertToMillisResult(true, time, -1);
+
+        // isDst = 0, toMillis(false)
+        Fields.set(time, timeFields);
+        time.isDst = 0;
+        assertToMillisResult(false, time, -1);
+
+        // isDst = 1, toMillis(true)
+        Fields.set(time, timeFields);
+        time.isDst = 1;
+        assertToMillisResult(true, time, -1);
+
+        // isDst = 1, toMillis(false)
+        Fields.set(time, timeFields);
+        time.isDst = 1;
+        assertToMillisResult(false, time, -1);
+
+        // isDst = -1, toMillis(true)
+        Fields.set(time, timeFields);
+        time.isDst = -1;
+        assertToMillisResult(true, time, -1);
+
+        // isDst = -1, toMillis(false)
+        Fields.set(time, timeFields);
+        time.isDst = -1;
+        assertToMillisResult(false, time, -1);
+    }
+
+    public void testToMillis_afterTzRecords() {
+        int[] timeFields = new int[] { 2039, 0, 1, 2, 3, 4, -999 /* not used */, 9, 9, 9 };
+        assertToMillisInvalid(timeFields, PstPdt.ID);
+        assertToMillisInvalid(timeFields, Time.TIMEZONE_UTC);
+    }
+
+    public void testToMillis_invalid() {
+        int[] timeFields = new int[] { 0, 0, 0, 0, 0, 0, -999 /* not used */, 9, 9, 9 };
+        assertToMillisInvalid(timeFields, PstPdt.ID);
+        assertToMillisInvalid(timeFields, Time.TIMEZONE_UTC);
+    }
+
+    public void testParse_date() throws Exception {
+        String nonUtcTz = PstPdt.ID;
+        Time t = new Time(nonUtcTz);
+        assertFalse(t.parse("12345678"));
+        Time expected = new Time(nonUtcTz);
+        Fields.setAllDayDate(expected, 1234, 55, 78);
+        Fields.setDst(expected, -1 /* isDst */, 0);
+        Fields.setDerivedDateTime(expected, 0, 0);
+        Fields.assertTimeEquals(expected, t);
+    }
+
+    public void testParse_null() throws Exception {
         Time t = new Time(Time.TIMEZONE_UTC);
+        try {
+            t.parse(null);
+            fail();
+        } catch (NullPointerException e) {
+        }
+    }
+
+    public void testParse() throws Exception {
+        Time t = new Time(Time.TIMEZONE_UTC);
+        t.parse("20061005T120000");
+
+        Time expected = new Time(Time.TIMEZONE_UTC);
+        Fields.set(expected, 2006, 9, 5, 12, 0, 0, -1 /* isDst */, 0, 0, 0);
+        Fields.assertTimeEquals(expected, t);
+    }
+
+    public void testParse_dateTime() throws Exception {
+        String nonUtcTz = PstPdt.ID;
+        Time t = new Time(nonUtcTz);
         assertFalse(t.parse("12345678T901234"));
-        assertTrue(t.parse("20081013T160000Z"));
-        assertEquals(2008, t.year);
-        assertEquals(9, t.month);
-        assertEquals(13, t.monthDay);
-        assertEquals(16, t.hour);
-        assertEquals(0, t.minute);
-        assertEquals(0, t.second);
+        Time expected = new Time(nonUtcTz);
+        Fields.set(expected, 1234, 55, 78, 90, 12, 34, -1 /* isDst */, 0, 0, 0);
+        Fields.assertTimeEquals(expected, t);
 
+        Time t2 = new Time(nonUtcTz);
+        assertTrue(t2.parse("12345678T901234Z"));
+        Time utcExpected = new Time(Time.TIMEZONE_UTC);
+        Fields.set(utcExpected, 1234, 55, 78, 90, 12, 34, -1 /* isDst */, 0, 0, 0);
+        Fields.assertTimeEquals(utcExpected, t2);
     }
 
-    public void testSet0() throws Exception {
-        Time t = new Time(Time.TIMEZONE_UTC);
-        long time = System.currentTimeMillis();
-        Calendar date = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
-        date.setTimeInMillis(time);
-        t.set(time);
-        assertEquals(date.get(Calendar.YEAR), t.year);
-        assertEquals(date.get(Calendar.MONTH), t.month);
-        assertEquals(date.get(Calendar.DAY_OF_MONTH), t.monthDay);
-        assertEquals(date.get(Calendar.HOUR_OF_DAY), t.hour);
-        assertEquals(date.get(Calendar.MINUTE), t.minute);
-        assertEquals(date.get(Calendar.SECOND), t.second);
+    public void testParse_errors() throws Exception {
+        String nonUtcTz = PstPdt.ID;
+        try {
+            Time t = new Time(nonUtcTz);
+            t.parse(null);
+            fail();
+        } catch (NullPointerException e) {
+        }
+
+        // Too short
+        assertParseError("");
+        assertParseError("1");
+        assertParseError("12");
+        assertParseError("123");
+        assertParseError("1234");
+        assertParseError("12345");
+        assertParseError("123456");
+        assertParseError("1234567");
+
+        // No "T" in the expected place
+        assertParseError("12345678S");
+
+        // Invalid character in the first 8 characters.
+        assertParseError("12X45678");
+
+        // Too short for a date/time (15 or 16 characters allowed)
+        assertParseError("12345678T");
+        assertParseError("12345678T0");
+        assertParseError("12345678T01");
+        assertParseError("12345678T012");
+        assertParseError("12345678T0123");
+        assertParseError("12345678T01234");
+
+        // Invalid character
+        assertParseError("12345678T0X2345");
     }
 
-    public void testSet1() throws Exception {
-        final int year = 2008;
-        final int month = 6;
-        final int date = 12;
-        final int hour = 16;
-        final int minute = 21;
-        final int second = 35;
+    private static void assertParseError(String s) {
         Time t = new Time(Time.TIMEZONE_UTC);
-        t.set(second, minute, hour, date, month, year);
-        assertEquals(year, t.year);
-        assertEquals(month, t.month);
-        assertEquals(date, t.monthDay);
-        assertEquals(hour, t.hour);
-        assertEquals(minute, t.minute);
-        assertEquals(second, t.second);
+        try {
+            t.parse(s);
+            fail();
+        } catch (TimeFormatException expected) {
+        }
+    }
+
+    public void testParse3339() throws Exception {
+        String tz = Time.TIMEZONE_UTC;
+        Time expected = new Time(tz);
+        Fields.setAllDayDate(expected, 1980, 4, 23);
+        Fields.setDst(expected, -1 /* isDst */, 0);
+        Fields.setDerivedDateTime(expected, 0, 0);
+        assertParse3339Succeeds(tz, "1980-05-23", expected);
+
+        Fields.setDateTime(expected, 1980, 4, 23, 9, 50, 50);
+        Fields.setDst(expected, -1 /* isDst */, 0);
+        Fields.setDerivedDateTime(expected, 0, 0);
+        assertParse3339Succeeds(tz, "1980-05-23T09:50:50", expected);
+
+        Fields.setDateTime(expected, 1980, 4, 23, 9, 50, 50);
+        Fields.setDst(expected, -1 /* isDst */, 0);
+        Fields.setDerivedDateTime(expected, 0, 0);
+        assertParse3339Succeeds(tz, "1980-05-23T09:50:50Z", expected);
+
+        Fields.setDateTime(expected, 1980, 4, 23, 9, 50, 50);
+        Fields.setDst(expected, -1 /* isDst */, 0);
+        Fields.setDerivedDateTime(expected, 0, 0);
+        assertParse3339Succeeds(tz, "1980-05-23T09:50:50.0Z", expected);
+
+        Fields.setDateTime(expected, 1980, 4, 23, 9, 50, 50);
+        Fields.setDst(expected, -1 /* isDst */, 0);
+        Fields.setDerivedDateTime(expected, 0, 0);
+        assertParse3339Succeeds(tz, "1980-05-23T09:50:50.12Z", expected);
+
+        Fields.setDateTime(expected, 1980, 4, 23, 9, 50, 50);
+        Fields.setDst(expected, -1 /* isDst */, 0);
+        Fields.setDerivedDateTime(expected, 0, 0);
+        assertParse3339Succeeds(tz, "1980-05-23T09:50:50.123Z", expected);
+
+        // The time should be normalized to UTC
+        Fields.setDateTime(expected, 1980, 4, 23, 10, 55, 50);
+        Fields.setDst(expected, -1 /* isDst */, 0);
+        Fields.setDerivedDateTime(expected, 0, 0);
+        assertParse3339Succeeds(tz, "1980-05-23T09:50:50-01:05", expected);
+
+        // The time should be normalized to UTC
+        Fields.setDateTime(expected, 1980, 4, 23, 10, 55, 50);
+        Fields.setDst(expected, -1 /* isDst */, 0);
+        Fields.setDerivedDateTime(expected, 0, 0);
+        assertParse3339Succeeds(tz, "1980-05-23T09:50:50.123-01:05", expected);
+    }
+
+    private static void assertParse3339Succeeds(String timeZone, String toParse, Time expected) {
+        Time t = new Time(timeZone);
+        t.parse3339(toParse);
+        Fields.assertTimeEquals(expected, t);
+    }
+
+    public void testParse3339_parseErrors() {
+        // Too short
+        assertParse3339Error("1980");
+
+        // Timezone too short
+        assertParse3339Error("1980-05-23T09:50:50.123+");
+        assertParse3339Error("1980-05-23T09:50:50.123+05:0");
+    }
+
+    public void testParse3339_null() {
+        Time t = new Time(Time.TIMEZONE_UTC);
+        try {
+            t.parse3339(null);
+            fail();
+        } catch (NullPointerException e) {
+        }
+    }
+
+    private void assertParse3339Error(String s) {
+        String tz = Time.TIMEZONE_UTC;
+        Time t = new Time(tz);
+        try {
+            t.parse3339(s);
+            fail();
+        } catch (TimeFormatException expected) {
+        }
+    }
+
+    public void testSetMillis_utc() throws Exception {
+        String tz = Time.TIMEZONE_UTC;
+        Time t = new Time(tz);
+        t.set(1000L);
+
+        Time expected = new Time(tz);
+        Fields.set(expected, 1970, 0, 1, 0, 0, 1, 0 /* isDst */, 0, 0, 4);
+        Fields.assertTimeEquals(expected, t);
+
+        t.set(2000L);
+        Fields.set(expected, 1970, 0, 1, 0, 0, 2, 0 /* isDst */, 0, 0, 4);
+        Fields.assertTimeEquals(expected, t);
+
+        t.set(1000L * 60);
+        Fields.set(expected, 1970, 0, 1, 0, 1, 0, 0 /* isDst */, 0, 0, 4);
+        Fields.assertTimeEquals(expected, t);
+
+        t.set((1000L * 60 * 60 * 24) + 1000L);
+        Fields.set(expected, 1970, 0, 2, 0, 0, 1, 0 /* isDst */, 0, 1, 5);
+        Fields.assertTimeEquals(expected, t);
+    }
+
+    public void testSetMillis_utc_edgeCases() throws Exception {
+        String tz = Time.TIMEZONE_UTC;
+        Time t = new Time(tz);
+        t.set(Integer.MAX_VALUE + 1L);
+
+        Time expected = new Time(tz);
+        // This a 32-bit int overflow bug.
+        Fields.set(expected, 1970, 0, 25, 20, 31, 23, 0 /* isDst */, 0, 24, 0);
+        Fields.assertTimeEquals(expected, t);
+
+        t = new Time(tz);
+        t.set(Integer.MIN_VALUE - 1L);
+        // This a 32-bit int underflow bug.
+        Fields.set(expected, 1969, 11, 7, 3, 28, 37, 0 /* isDst */, 0, 340, 0);
+        Fields.assertTimeEquals(expected, t);
+    }
+
+    public void testSetFields() throws Exception {
+        String tz = Time.TIMEZONE_UTC;
+        Time t = new Time(tz);
+        Fields.set(t, 9, 9, 9, 9, 9, 9, 9 /* isDst */, 9, 9, 9);
+
+        t.set(1, 2, 3, 4, 5, 6);
+
+        Time expected = new Time(tz);
+        Fields.set(expected, 6, 5, 4, 3, 2, 1, -1 /* isDst */, 0, 0, 0);
+        Fields.assertTimeEquals(expected, t);
     }
 
     // Timezones that cover the world.  Some GMT offsets occur more than
     // once in case some cities decide to change their GMT offset.
     private static final String[] mTimeZones = {
+        "UTC",
         "Pacific/Kiritimati",
         "Pacific/Enderbury",
         "Pacific/Fiji",
@@ -672,14 +1852,14 @@
                 // We leave the "month" as zero because we are changing the
                 // "monthDay" from 1 to 366. The call to normalize() will
                 // then change the "month" (but we don't really care).
-                time.set(0, 0, 0, monthDay, 0, 2008);
+                time.set(0, 0, 12, monthDay, 0, 2008);
                 time.timezone = mTimeZones[zoneIndex];
                 long millis = time.normalize(true);
                 if (zoneIndex == 0) {
                     Log.i(TAG, time.format("%B %d, %Y"));
                 }
 
-                // This is the Julian day for 12am for this day of the year
+                // This is the Julian day for 12pm for this day of the year
                 int julianDay = Time.getJulianDay(millis, time.gmtoff);
 
                 // Change the time during the day and check that we get the same
@@ -688,13 +1868,17 @@
                     for (int minute = 0; minute < 60; minute += 15) {
                         time.set(0, minute, hour, monthDay, 0, 2008);
                         millis = time.normalize(true);
-                        int day = Time.getJulianDay(millis, time.gmtoff);
-                        if (day != julianDay) {
-                            Log.e("TimeTest", "Julian day: " + day + " at time " + time.hour + ":"
-                                    + time.minute + " != today's Julian day: " + julianDay
-                                    + " timezone: " + time.timezone);
+                        if (millis == -1) {
+                            // millis == -1 means the wall time does not exist in the chosen
+                            // timezone due to a DST change. We cannot calculate a JulianDay for -1.
+                            continue;
                         }
-                        assertEquals(day, julianDay);
+
+                        int day = Time.getJulianDay(millis, time.gmtoff);
+                        assertEquals("Julian day: " + day + " at time "
+                                + time.hour + ":" + time.minute
+                                + " != today's Julian day: " + julianDay
+                                + " timezone: " + time.timezone, day, julianDay);
                     }
                 }
             }
@@ -711,12 +1895,13 @@
                 // We leave the "month" as zero because we are changing the
                 // "monthDay" from 1 to 366. The call to normalize() will
                 // then change the "month" (but we don't really care).
-                time.set(0, 0, 0, monthDay, 0, 2008);
+                time.set(0, 0, 12, monthDay, 0, 2008);
                 time.timezone = mTimeZones[zoneIndex];
                 long millis = time.normalize(true);
                 if (zoneIndex == 0) {
                     Log.i(TAG, time.format("%B %d, %Y"));
                 }
+                // This is the Julian day for 12pm for this day of the year
                 int julianDay = Time.getJulianDay(millis, time.gmtoff);
 
                 time.setJulianDay(julianDay);
@@ -732,14 +1917,952 @@
                 assertEquals(0, time.second);
 
                 millis = time.toMillis(false);
-                int day = Time.getJulianDay(millis, time.gmtoff);
-                if (day != julianDay) {
-                    Log.i(TAG, "Error: gmtoff " + (time.gmtoff / 3600.0) + " day "
-                            + julianDay + " millis " + millis + " " + time.format("%B %d, %Y")
-                            + " " + time.timezone);
+                if (millis == -1) {
+                    // millis == -1 means the wall time does not exist in the chosen
+                    // timezone due to a DST change. We cannot calculate a JulianDay for -1.
+                    continue;
                 }
-                assertEquals(day, julianDay);
+                int day = Time.getJulianDay(millis, time.gmtoff);
+                assertEquals("Error: gmtoff " + (time.gmtoff / 3600.0) + " day " + julianDay
+                                + " millis " + millis+ " " + time.format("%B %d, %Y")
+                                + " " + time.timezone,
+                        day, julianDay);
             }
         }
     }
+
+    public void testNormalize_utc() throws Exception {
+        Time t = new Time(Time.TIMEZONE_UTC);
+        Time expected = new Time(Time.TIMEZONE_UTC);
+
+        long winterTimeUtcMillis = 1167613323000L;
+
+        Fields.set(t, 2007, 0, 1, 1, 2, 3, 0 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 2007, 0, 1, 1, 2, 3, 0 /* isDst */, 0, 0, 1);
+        assertNormalizeResult(true, t, expected, winterTimeUtcMillis);
+
+        Fields.set(t, 2007, 0, 1, 1, 2, 3, 1 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 2007, 0, 1, 1, 2, 3, 0 /* isDst */, 0, 0, 1);
+        assertNormalizeResult(true, t, expected, winterTimeUtcMillis);
+
+        Fields.set(t, 2007, 0, 1, 1, 2, 3, -1 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 2007, 0, 1, 1, 2, 3, 0 /* isDst */, 0, 0, 1);
+        assertNormalizeResult(true, t, expected, winterTimeUtcMillis);
+
+        Fields.set(t, 2007, 0, 1, 1, 2, 3, 0 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 2007, 0, 1, 1, 2, 3, 0 /* isDst */, 0, 0, 1);
+        assertNormalizeResult(false, t, expected, winterTimeUtcMillis);
+
+        Fields.set(t, 2007, 0, 1, 1, 2, 3, 1 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 2007, 0, 1, 1, 2, 3, 1 /* isDst */, 9, 9, 9);
+        assertNormalizeResult(false, t, expected, -1);
+
+        Fields.set(t, 2007, 0, 1, 1, 2, 3, -1 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 2007, 0, 1, 1, 2, 3, 0 /* isDst */, 0, 0, 1);
+        assertNormalizeResult(false, t, expected, winterTimeUtcMillis);
+
+        long summerTimeUtcMillis = 1180659723000L;
+
+        Fields.set(t, 2007, 5, 1, 1, 2, 3, 0 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 2007, 5, 1, 1, 2, 3, 0 /* isDst */, 0, 151, 5);
+        assertNormalizeResult(true, t, expected, summerTimeUtcMillis);
+
+        Fields.set(t, 2007, 5, 1, 1, 2, 3, 1 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 2007, 5, 1, 1, 2, 3, 0 /* isDst */, 0, 151, 5);
+        assertNormalizeResult(true, t, expected, summerTimeUtcMillis);
+
+        Fields.set(t, 2007, 5, 1, 1, 2, 3, -1 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 2007, 5, 1, 1, 2, 3, 0 /* isDst */, 0, 151, 5);
+        assertNormalizeResult(true, t, expected, summerTimeUtcMillis);
+
+        Fields.set(t, 2007, 5, 1, 1, 2, 3, 0 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 2007, 5, 1, 1, 2, 3, 0 /* isDst */, 0, 151, 5);
+        assertNormalizeResult(false, t, expected, summerTimeUtcMillis);
+
+        Fields.set(t, 2007, 5, 1, 1, 2, 3, 1 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 2007, 5, 1, 1, 2, 3, 1 /* isDst */, 9, 9, 9);
+        assertNormalizeResult(false, t, expected, -1);
+
+        Fields.set(t, 2007, 5, 1, 1, 2, 3, -1 /* isDst */, 1, 9, 9);
+        Fields.set(expected, 2007, 5, 1, 1, 2, 3, 0 /* isDst */, 0, 151, 5);
+        assertNormalizeResult(false, t, expected, summerTimeUtcMillis);
+    }
+
+    public void testNormalize_dstTz() throws Exception {
+        Time t = new Time(PstPdt.ID);
+        Time expected = new Time(PstPdt.ID);
+
+        // A STD time
+        long stdTimeUtcMillis = 1167613323000L;
+        long stdTimeMillis = stdTimeUtcMillis - PstPdt.getUtcOffsetMillis(false);
+
+        Fields.set(t, 2007, 0, 1, 1, 2, 3, 0 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 2007, 0, 1, 1, 2, 3, 0 /* isDst */, -28800, 0, 1);
+        assertNormalizeResult(true, t, expected, stdTimeMillis);
+
+        Fields.set(t, 2007, 0, 1, 1, 2, 3, 1 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 2007, 0, 1, 1, 2, 3, 0 /* isDst */, -28800, 0, 1);
+        assertNormalizeResult(true, t, expected, stdTimeMillis);
+
+        Fields.set(t, 2007, 0, 1, 1, 2, 3, -1 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 2007, 0, 1, 1, 2, 3, 0 /* isDst */, -28800, 0, 1);
+        assertNormalizeResult(true, t, expected, stdTimeMillis);
+
+        long dstToStdCorrectionMillis =
+                PstPdt.getUtcOffsetMillis(false) - PstPdt.getUtcOffsetMillis(true);
+
+        Fields.set(t, 2007, 0, 1, 1, 2, 3, 0 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 2007, 0, 1, 1, 2, 3, 0 /* isDst */, -28800, 0, 1);
+        assertNormalizeResult(false, t, expected, stdTimeMillis);
+
+        Fields.set(t, 2007, 0, 1, 1, 2, 3, 1 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 2007, 0, 1, 0, 2, 3, 0 /* isDst */, -28800, 0, 1);
+        assertNormalizeResult(false, t, expected, stdTimeMillis + dstToStdCorrectionMillis);
+
+        Fields.set(t, 2007, 0, 1, 1, 2, 3, -1 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 2007, 0, 1, 1, 2, 3, 0 /* isDst */, -28800, 0, 1);
+        assertNormalizeResult(false, t, expected, stdTimeMillis);
+
+        // A DST time
+        long dstTimeUtcMillis = 1180659723000L;
+        long dstTimeMillis = dstTimeUtcMillis - PstPdt.getUtcOffsetMillis(true);
+
+        Fields.set(t, 2007, 5, 1, 1, 2, 3, 0 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 2007, 5, 1, 1, 2, 3, 1 /* isDst */, -25200, 151, 5);
+        assertNormalizeResult(true, t, expected, dstTimeMillis);
+
+        Fields.set(t, 2007, 5, 1, 1, 2, 3, 1 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 2007, 5, 1, 1, 2, 3, 1 /* isDst */, -25200, 151, 5);
+        assertNormalizeResult(true, t, expected, dstTimeMillis);
+
+        Fields.set(t, 2007, 5, 1, 1, 2, 3, -1 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 2007, 5, 1, 1, 2, 3, 1 /* isDst */, -25200, 151, 5);
+        assertNormalizeResult(true, t, expected, dstTimeMillis);
+
+        long stdToDstCorrectionMillis = -dstToStdCorrectionMillis;
+
+        Fields.set(t, 2007, 5, 1, 1, 2, 3, 0 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 2007, 5, 1, 2, 2, 3, 1 /* isDst */, -25200, 151, 5);
+        assertNormalizeResult(false, t, expected, dstTimeMillis + stdToDstCorrectionMillis);
+
+        Fields.set(t, 2007, 5, 1, 1, 2, 3, 1 /* isDst */, -25200, 151, 5);
+        Fields.set(expected, 2007, 5, 1, 1, 2, 3, 1 /* isDst */, -25200, 151, 5);
+        assertNormalizeResult(false, t, expected, dstTimeMillis);
+
+        Fields.set(t, 2007, 5, 1, 1, 2, 3, -1 /* isDst */, -25200, 151, 5);
+        Fields.set(expected, 2007, 5, 1, 1, 2, 3, 1 /* isDst */, -25200, 151, 5);
+        assertNormalizeResult(false, t, expected, dstTimeMillis);
+    }
+
+    public void testNormalize_skippedTime() {
+        // Tests behavior around a transition from STD to DST that introduces an hour of "skipped"
+        // time from 01:00 to 01:59.
+        String timezone = PstPdt.ID;
+        long stdBaseTimeMillis = 1173607200000L;
+        long dstBaseTimeMillis = 1173603600000L;
+
+        // Try each minute from one minute before the skipped hour until one after.
+        for (int i = -1; i <= 60; i++) {
+            int minutesInMillis = i * 60000;
+            int[] dateTimeArgs = new int[] { 2007, 2, 11, 2, i, 0 };
+
+            int[] normalizedAdjustedBackwardDateTimeArgs;
+            int[] normalizedDateTimeArgs;
+            int[] normalizedAdjustedForwardDateTimeArgs;
+            if (i == -1) {
+                normalizedAdjustedBackwardDateTimeArgs = new int[] { 2007, 2, 11, 0, 59, 0 };
+                normalizedDateTimeArgs = new int[] { 2007, 2, 11, 1, 59, 0 };
+                normalizedAdjustedForwardDateTimeArgs = null;
+            } else if (i == 60) {
+                normalizedAdjustedBackwardDateTimeArgs = null;
+                normalizedDateTimeArgs = new int[] { 2007, 2, 11, 3, 0, 0 };
+                normalizedAdjustedForwardDateTimeArgs = new int[] { 2007, 2, 11, 4, 0, 0 };
+            } else {
+                normalizedAdjustedBackwardDateTimeArgs = new int[] { 2007, 2, 11, 1, i, 0 };
+                normalizedDateTimeArgs = null;
+                normalizedAdjustedForwardDateTimeArgs =  new int[] { 2007, 2, 11, 3, i, 0 };
+            }
+
+            Time time = new Time(timezone);
+            Time expected = new Time(timezone);
+
+            // isDst = 0, normalize(true)
+            Fields.setDateTime(time, dateTimeArgs);
+            Fields.setDst(time, 0 /* isDst */, 9);
+            Fields.setDerivedDateTime(time, 9, 9);
+
+            long timeMillis = time.normalize(true);
+            long expectedTimeMillis;
+            if (i == -1) {
+                expectedTimeMillis = stdBaseTimeMillis + minutesInMillis;
+                Fields.setDateTime(expected, normalizedDateTimeArgs);
+                Fields.setDst(expected, 0, PstPdt.getUtcOffsetSeconds(0));
+                Fields.setDerivedDateTime(expected, 69, 0);
+            } else if (i == 60) {
+                expectedTimeMillis = dstBaseTimeMillis + minutesInMillis;
+                Fields.setDateTime(expected, normalizedDateTimeArgs);
+                Fields.setDst(expected, 1, PstPdt.getUtcOffsetSeconds(1));
+                Fields.setDerivedDateTime(expected, 69, 0);
+            } else {
+                expectedTimeMillis = -1;
+                Fields.setDateTime(expected, dateTimeArgs);
+                Fields.setDst(expected, -1, 9);
+                Fields.setDerivedDateTime(expected, 9, 9);
+            }
+            assertEquals("i = " + i, expectedTimeMillis, timeMillis);
+            Fields.assertTimeEquals("i = " + i, expected, time);
+
+            // isDst = 0, normalize(false)
+            Fields.setDateTime(time, dateTimeArgs);
+            Fields.setDst(time, 0 /* isDst */, 9);
+            Fields.setDerivedDateTime(time, 9, 9);
+
+            timeMillis = time.normalize(false);
+            expectedTimeMillis = stdBaseTimeMillis + minutesInMillis;
+            assertEquals("i = " + i, expectedTimeMillis, timeMillis);
+            if (i == -1) {
+                Fields.setDateTime(expected, normalizedDateTimeArgs);
+                Fields.setDst(expected, 0, PstPdt.getUtcOffsetSeconds(0));
+            } else {
+                Fields.setDateTime(expected, normalizedAdjustedForwardDateTimeArgs);
+                Fields.setDst(expected, 1, PstPdt.getUtcOffsetSeconds(1));
+            }
+            Fields.setDerivedDateTime(expected, 69, 0);
+            Fields.assertTimeEquals("i = " + i, expected, time);
+
+            // isDst = 1, normalize(true)
+            Fields.setDateTime(time, dateTimeArgs);
+            Fields.setDst(time, 1 /* isDst */, 9);
+            Fields.setDerivedDateTime(time, 9, 9);
+
+            timeMillis = time.normalize(true);
+            if (i == -1) {
+                expectedTimeMillis = stdBaseTimeMillis + minutesInMillis;
+                Fields.setDateTime(expected, normalizedDateTimeArgs);
+                Fields.setDst(expected, 0, PstPdt.getUtcOffsetSeconds(0));
+                Fields.setDerivedDateTime(expected, 69, 0);
+            } else if (i == 60) {
+                expectedTimeMillis = dstBaseTimeMillis + minutesInMillis;
+                Fields.setDateTime(expected, normalizedDateTimeArgs);
+                Fields.setDst(expected, 1, PstPdt.getUtcOffsetSeconds(1));
+                Fields.setDerivedDateTime(expected, 69, 0);
+            } else {
+                expectedTimeMillis = -1;
+                Fields.setDateTime(expected, dateTimeArgs);
+                Fields.setDst(expected, -1, 9);
+                Fields.setDerivedDateTime(expected, 9, 9);
+            }
+            assertEquals("i = " + i, expectedTimeMillis, timeMillis);
+            Fields.assertTimeEquals("i = " + i, expected, time);
+
+            // isDst = 1, normalize(false)
+            Fields.setDateTime(time, dateTimeArgs);
+            Fields.setDst(time, 1 /* isDst */, 9);
+            Fields.setDerivedDateTime(time, 9, 9);
+
+            timeMillis = time.normalize(false);
+            expectedTimeMillis = dstBaseTimeMillis + minutesInMillis;
+            assertEquals("i = " + i, expectedTimeMillis, timeMillis);
+            if (i == 60) {
+                Fields.setDateTime(expected, normalizedDateTimeArgs);
+                Fields.setDst(expected, 1, PstPdt.getUtcOffsetSeconds(1));
+            } else {
+                Fields.setDateTime(expected, normalizedAdjustedBackwardDateTimeArgs);
+                Fields.setDst(expected, 0, PstPdt.getUtcOffsetSeconds(0));
+            }
+            Fields.setDerivedDateTime(expected, 69, 0);
+            Fields.assertTimeEquals("i = " + i, expected, time);
+
+            // isDst = -1, normalize(true)
+            Fields.setDateTime(time, dateTimeArgs);
+            Fields.setDst(time, -1 /* isDst */, 9);
+            Fields.setDerivedDateTime(time, 9, 9);
+
+            timeMillis = time.normalize(true);
+            if (i == -1) {
+                expectedTimeMillis = stdBaseTimeMillis + minutesInMillis;
+                Fields.setDateTime(expected, normalizedDateTimeArgs);
+                Fields.setDst(expected, 0, PstPdt.getUtcOffsetSeconds(0));
+                Fields.setDerivedDateTime(expected, 69, 0);
+            } else if (i == 60) {
+                expectedTimeMillis = dstBaseTimeMillis + minutesInMillis;
+                Fields.setDateTime(expected, normalizedDateTimeArgs);
+                Fields.setDst(expected, 1, PstPdt.getUtcOffsetSeconds(1));
+                Fields.setDerivedDateTime(expected, 69, 0);
+            } else {
+                expectedTimeMillis = -1;
+                Fields.setDateTime(expected, dateTimeArgs);
+                Fields.setDst(expected, -1, 9);
+                Fields.setDerivedDateTime(expected, 9, 9);
+            }
+            assertEquals("i = " + i, expectedTimeMillis, timeMillis);
+            Fields.assertTimeEquals("i = " + i, expected, time);
+
+            // isDst = -1, normalize(false)
+            Fields.setDateTime(time, dateTimeArgs);
+            Fields.setDst(time, -1 /* isDst */, 9);
+            Fields.setDerivedDateTime(time, 9, 9);
+
+            timeMillis = time.normalize(false);
+            if (i == -1) {
+                expectedTimeMillis = stdBaseTimeMillis + minutesInMillis;
+                Fields.setDateTime(expected, normalizedDateTimeArgs);
+                Fields.setDst(expected, 0, PstPdt.getUtcOffsetSeconds(0));
+                Fields.setDerivedDateTime(expected, 69, 0);
+            } else if (i == 60) {
+                expectedTimeMillis = dstBaseTimeMillis + minutesInMillis;
+                Fields.setDateTime(expected, normalizedDateTimeArgs);
+                Fields.setDst(expected, 1, PstPdt.getUtcOffsetSeconds(1));
+                Fields.setDerivedDateTime(expected, 69, 0);
+            } else {
+                expectedTimeMillis = -1;
+                Fields.setDateTime(expected, dateTimeArgs);
+                Fields.setDst(expected, -1, 9);
+                Fields.setDerivedDateTime(expected, 9, 9);
+            }
+            assertEquals("i = " + i, expectedTimeMillis, timeMillis);
+            Fields.assertTimeEquals("i = " + i, expected, time);
+        }
+    }
+
+    public void testNormalize_duplicateWallTime() {
+        // 1:00 in standard / 2:00 in DST
+        long timeBaseMillis = 1194163200000L;
+        long dstCorrectionMillis = 3600000;
+
+        // Try each minute from one minute before the duplicated hour until one after.
+        for (int i = -1; i <= 60; i++) {
+            Time time = new Time(PstPdt.ID);
+            Time expected = new Time(PstPdt.ID);
+
+            int[] dateTimeArgs = new int[] { 2007, 10, 4, 1, i, 0 };
+            int[] normalizedAdjustedBackwardDateTimeArgs;
+            int[] normalizedDateTimeArgs;
+            int[] normalizedAdjustedForwardDateTimeArgs;
+            if (i == -1) {
+                normalizedAdjustedBackwardDateTimeArgs = null;
+                normalizedDateTimeArgs = new int[] { 2007, 10, 4, 0, 59, 0 };
+                normalizedAdjustedForwardDateTimeArgs = new int[] { 2007, 10, 4, 1, 59, 0 };
+            } else if (i == 60) {
+                normalizedAdjustedBackwardDateTimeArgs = new int[] { 2007, 10, 4, 1, 0, 0 };
+                normalizedDateTimeArgs = new int[] { 2007, 10, 4, 2, 0, 0 };
+                normalizedAdjustedForwardDateTimeArgs = null;
+            } else {
+                normalizedAdjustedBackwardDateTimeArgs = null;
+                normalizedDateTimeArgs = dateTimeArgs;
+                normalizedAdjustedForwardDateTimeArgs =  null;
+            }
+
+            int minutesInMillis = i * 60000;
+
+            // isDst = 0, normalize(true)
+            Fields.setDateTime(time, dateTimeArgs);
+            Fields.setDst(time, 0 /* isDst */, 9);
+            Fields.setDerivedDateTime(time, 9, 9);
+
+            long timeMillis = time.normalize(true);
+
+            Fields.setDateTime(expected, normalizedDateTimeArgs);
+            // When ignoreDst == true the choice between DST and STD is arbitrary when both answers
+            // are possible.
+            if (timeMillis == timeBaseMillis + minutesInMillis) {
+                // i == 60 is unambiguous
+                assertTrue("i =" + i, i < 60);
+                Fields.setDst(expected, 1 /* isDst */, PstPdt.getUtcOffsetSeconds(1));
+            } else if (timeMillis == timeBaseMillis + minutesInMillis + dstCorrectionMillis) {
+                // i == -1 is unambiguous
+                assertTrue("i =" + i, i > -1);
+                Fields.setDst(expected, 0 /* isDst */, PstPdt.getUtcOffsetSeconds(0));
+            } else {
+                fail("i =" + i);
+            }
+            Fields.setDerivedDateTime(expected, 307, 0);
+            Fields.assertTimeEquals("i = " + i, expected, time);
+
+            // isDst = 0, normalize(false)
+            Fields.setDateTime(time, dateTimeArgs);
+            Fields.setDst(time, 0 /* isDst */, 9);
+            Fields.setDerivedDateTime(time, 9, 9);
+
+            timeMillis = time.normalize(false);
+            long expectedTimeMillis = timeBaseMillis + minutesInMillis + dstCorrectionMillis;
+            assertEquals("i = " + i, expectedTimeMillis, timeMillis);
+            if (i == -1) {
+                Fields.setDateTime(expected, normalizedAdjustedForwardDateTimeArgs);
+                Fields.setDst(expected, 1 /* isDst */, PstPdt.getUtcOffsetSeconds(1));
+            } else {
+                Fields.setDateTime(expected, normalizedDateTimeArgs);
+                Fields.setDst(expected, 0 /* isDst */, PstPdt.getUtcOffsetSeconds(0));
+            }
+            Fields.setDerivedDateTime(expected, 307, 0);
+            Fields.assertTimeEquals("i = " + i, expected, time);
+
+            // isDst = 1, normalize(true)
+            Fields.setDateTime(time, dateTimeArgs);
+            Fields.setDst(time, 1 /* isDst */, 9);
+            Fields.setDerivedDateTime(time, 9, 9);
+
+            timeMillis = time.normalize(true);
+            Fields.setDateTime(expected, normalizedDateTimeArgs);
+            // When ignoreDst == true the choice between DST and STD is arbitrary when both answers
+            // are possible.
+            if (timeMillis == timeBaseMillis + minutesInMillis) {
+                // i == 60 is unambiguous
+                assertTrue("i =" + i, i < 60);
+                Fields.setDst(expected, 1 /* isDst */, PstPdt.getUtcOffsetSeconds(1));
+            } else if (timeMillis == timeBaseMillis + minutesInMillis + dstCorrectionMillis) {
+                // i == -1 is unambiguous
+                assertTrue("i =" + i, i > -1);
+                Fields.setDst(expected, 0 /* isDst */, PstPdt.getUtcOffsetSeconds(0));
+            } else {
+                fail("i =" + i);
+            }
+            Fields.setDerivedDateTime(expected, 307, 0);
+            Fields.assertTimeEquals("i = " + i, expected, time);
+
+            // isDst = 1, normalize(false)
+            Fields.setDateTime(time, dateTimeArgs);
+            Fields.setDst(time, 1 /* isDst */, 9);
+            Fields.setDerivedDateTime(time, 9, 9);
+
+            timeMillis = time.normalize(false);
+            expectedTimeMillis = timeBaseMillis + minutesInMillis;
+            if (i == 60) {
+                Fields.setDateTime(expected, normalizedAdjustedBackwardDateTimeArgs);
+                Fields.setDst(expected, 0 /* isDst */, PstPdt.getUtcOffsetSeconds(0));
+            } else {
+                Fields.setDateTime(expected, normalizedDateTimeArgs);
+                Fields.setDst(expected, 1 /* isDst */, PstPdt.getUtcOffsetSeconds(1));
+            }
+            Fields.setDerivedDateTime(expected, 307, 0);
+            assertEquals("i = " + i, expectedTimeMillis, timeMillis);
+            Fields.assertTimeEquals("i = " + i, expected, time);
+
+            // isDst = -1, normalize(true)
+            Fields.setDateTime(time, dateTimeArgs);
+            Fields.setDst(time, -1 /* isDst */, 9);
+            Fields.setDerivedDateTime(time, 9, 9);
+
+            timeMillis = time.normalize(true);
+            Fields.setDateTime(expected, normalizedDateTimeArgs);
+            // When isDst == -1 the choice between DST and STD is arbitrary when both answers
+            // are possible.
+            if (timeMillis == timeBaseMillis + minutesInMillis) {
+                // i == 60 is unambiguous
+                assertTrue("i =" + i, i < 60);
+                Fields.setDst(expected, 1 /* isDst */, PstPdt.getUtcOffsetSeconds(1));
+            } else if (timeMillis == timeBaseMillis + minutesInMillis + dstCorrectionMillis) {
+                // i == -1 is unambiguous
+                assertTrue("i =" + i, i > -1);
+                Fields.setDst(expected, 0 /* isDst */, PstPdt.getUtcOffsetSeconds(0));
+            } else {
+                fail("i =" + i);
+            }
+            Fields.setDerivedDateTime(expected, 307, 0);
+            Fields.assertTimeEquals("i = " + i, expected, time);
+
+            // isDst = -1, normalize(false)
+            Fields.setDateTime(time, dateTimeArgs);
+            Fields.setDst(time, -1 /* isDst */, 9);
+            Fields.setDerivedDateTime(time, 9, 9);
+
+            timeMillis = time.normalize(false);
+            // When isDst == -1 the choice between DST and STD is arbitrary when both answers
+            // are possible.
+            if (timeMillis == timeBaseMillis + minutesInMillis) {
+                // i == 60 is unambiguous
+                assertTrue("i =" + i, i < 60);
+                Fields.setDst(expected, 1 /* isDst */, PstPdt.getUtcOffsetSeconds(1));
+            } else if (timeMillis == timeBaseMillis + minutesInMillis + dstCorrectionMillis) {
+                // i == -1 is unambiguous
+                assertTrue("i =" + i, i > -1);
+                Fields.setDst(expected, 0 /* isDst */, PstPdt.getUtcOffsetSeconds(0));
+            } else {
+                fail("i =" + i);
+            }
+            Fields.setDerivedDateTime(expected, 307, 0);
+            Fields.assertTimeEquals("i = " + i, expected, time);
+        }
+    }
+
+    public void testNormalize_beforeTzRecords() {
+        int[] timeFields = new int[] { 1900, 0, 1, 2, 3, 4, -999 /* not used */, 9, 9, 9 };
+        assertNormalizeInvalid(timeFields, PstPdt.ID);
+        assertNormalizeInvalid(timeFields, Time.TIMEZONE_UTC);
+    }
+
+    private static void assertNormalizeInvalid(int[] timeFields, String timezone) {
+        Time time = new Time(timezone);
+        Time expected = new Time(timezone);
+
+        // isDst = 0, normalize(true)
+        Fields.set(time, timeFields);
+        time.isDst = 0;
+        Fields.set(expected, timeFields);
+        expected.isDst = -1;
+        assertNormalizeResult(true, time, expected, -1);
+
+        // isDst = 0, normalize(false)
+        Fields.set(time, timeFields);
+        time.isDst = 0;
+        Fields.set(expected, timeFields);
+        expected.isDst = 0;
+        assertNormalizeResult(false, time, expected, -1);
+
+        // isDst = 1, normalize(true)
+        Fields.set(time, timeFields);
+        time.isDst = 1;
+        Fields.set(expected, timeFields);
+        expected.isDst = -1;
+        assertNormalizeResult(true, time, expected, -1);
+
+        // isDst = 1, normalize(false)
+        Fields.set(time, timeFields);
+        time.isDst = 1;
+        Fields.set(expected, timeFields);
+        expected.isDst = 1;
+        assertNormalizeResult(false, time, expected, -1);
+
+        // isDst = -1, normalize(true)
+        Fields.set(time, timeFields);
+        time.isDst = -1;
+        Fields.set(expected, timeFields);
+        expected.isDst = -1;
+        assertNormalizeResult(true, time, expected, -1);
+
+        // isDst = -1, normalize(false)
+        Fields.set(time, timeFields);
+        time.isDst = -1;
+        Fields.set(expected, timeFields);
+        expected.isDst = -1;
+        assertNormalizeResult(false, time, expected, -1);
+    }
+
+    public void testNormalize_afterTzRecords() {
+        int[] timeFields = new int[] { 2039, 0, 1, 2, 3, 4, -999 /* not used */, 9, 9, 9 };
+        assertNormalizeInvalid(timeFields, PstPdt.ID);
+        assertNormalizeInvalid(timeFields, Time.TIMEZONE_UTC);
+    }
+
+    public void testNormalize_invalid() {
+        int[] timeFields = new int[] { 0, 0, 0, 0, 0, 0, -999 /* not used */, 9, 9, 9 };
+        assertNormalizeInvalid(timeFields, PstPdt.ID);
+        assertNormalizeInvalid(timeFields, Time.TIMEZONE_UTC);
+    }
+
+    public void testNormalize_dstToDstSkip() {
+        // In London, 4th May 1941 02:00 - 03:00 was a skip from DST -> DST (+1 hour -> +2 hours)
+        String timezone = "Europe/London";
+        Time t = new Time(timezone);
+        Time expected = new Time(timezone);
+
+        // Demonstrate the data we expect either side of the skipped interval: 01:59
+        Fields.set(t, 1941, 4, 4, 1, 59, 0, -1 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 1941, 4, 4, 1, 59, 0, 1 /* isDst */, 3600, 123, 0);
+        assertNormalizeResult(true, t, expected, -904518060000L);
+
+        // Demonstrate the data we expect either side of the skipped interval: 03:00
+        Fields.set(t, 1941, 4, 4, 3, 0, 0, -1 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 1941, 4, 4, 3, 0, 0, 1 /* isDst */, 7200, 123, 0);
+        assertNormalizeResult(true, t, expected, -904518000000L);
+
+        // isDst = 1, normalize(false)
+        Fields.set(t, 1941, 4, 4, 2, 30, 0, 1 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 1941, 4, 4, 2, 30, 0, 1 /* isDst */, 9, 9, 9);
+        assertNormalizeResult(false, t, expected, -1);
+
+        // isDst = -1, normalize(false)
+        Fields.set(t, 1941, 4, 4, 2, 30, 0, -1 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 1941, 4, 4, 2, 30, 0, -1 /* isDst */, 9, 9, 9);
+        assertNormalizeResult(false, t, expected, -1);
+
+        // The results below are potentially arbitrary: 01:30 and 02:30 are not a valid standard
+        // times so normalize() must apply one of the possible STD -> DST adjustments to arrive at a
+        // date / time.
+
+        // isDst = 0, normalize(false) @ 01:30
+        Fields.set(t, 1941, 4, 4, 1, 30, 0, 0 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 1941, 4, 4, 3, 30, 0, 1 /* isDst */, 7200, 123, 0);
+        assertNormalizeResult(false, t, expected, -904516200000L);
+
+        // isDst = 0, normalize(false) @ 02:30
+        Fields.set(t, 1941, 4, 4, 2, 30, 0, 0 /* isDst */, 9, 9, 9);
+        long timeMillis = t.normalize(false);
+
+        if (timeMillis == -904516200000L) {
+            // The original C implementation chooses this one.
+            Fields.set(expected, 1941, 4, 4, 3, 30, 0, 1 /* isDst */, 7200, 123, 0);
+        } else if (timeMillis == -904512600000L) {
+            Fields.set(expected, 1941, 4, 4, 4, 30, 0, 1 /* isDst */, 7200, 123, 0);
+        } else {
+            fail();
+        }
+        Fields.assertTimeEquals(expected, t);
+    }
+
+    public void testNormalize_dstToDstRepeat() {
+        // In London, 10th August 1941 02:00 - 03:00 was a repeat from DST -> DST
+        // (+2 hour -> +1 hour)
+        String timezone = "Europe/London";
+        Time t = new Time(timezone);
+        Time expected = new Time(timezone);
+
+        // Demonstrate the data we expect during the repeated interval: 02:30 (first)
+        t.set(-896052600000L);
+        Fields.set(expected, 1941, 7, 10, 2, 30, 0, 1 /* isDst */, 7200, 221, 0);
+        Fields.assertTimeEquals(expected, t);
+
+        // Demonstrate the data we expect during the repeated interval: 02:30 (second)
+        t.set(-896049000000L);
+        Fields.set(expected, 1941, 7, 10, 2, 30, 0, 1 /* isDst */, 3600, 221, 0);
+        Fields.assertTimeEquals(expected, t);
+
+        // Now check times in the repeated hour with different isDst assertions...
+
+        // isDst = 1, normalize(false) @ 02:30
+        Fields.set(t, 1941, 7, 10, 2, 30, 0, 1 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 1941, 7, 10, 2, 30, 0, 1 /* isDst */, 3600, 221, 0);
+        assertNormalizeResult(false, t, expected, -896049000000L);
+
+        // isDst = -1, normalize(false) @ 02:30
+        Fields.set(t, 1941, 7, 10, 2, 30, 0, -1 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 1941, 7, 10, 2, 30, 0, 1 /* isDst */, 3600, 221, 0);
+        assertNormalizeResult(false, t, expected, -896049000000L);
+
+        // The results below are potentially arbitrary: 01:30 and 02:30 are not a valid standard
+        // times so normalize() must apply one of the possible STD -> DST adjustments to arrive at a
+        // date / time.
+
+        // isDst = 0, normalize(false) @ 01:30
+        Fields.set(t, 1941, 7, 10, 1, 30, 0, 0 /* isDst */, 9, 9, 9);
+        long timeMillis = t.normalize(false);
+        if (timeMillis == -896052600000L) {
+            // The original C implementation chooses this one.
+            Fields.set(expected, 1941, 7, 10, 2, 30, 0, 1 /* isDst */, 7200, 221, 0);
+        } else if (timeMillis == -896049000000L) {
+            Fields.set(expected, 1941, 7, 10, 2, 30, 0, 1 /* isDst */, 3600, 221, 0);
+        } else {
+            fail();
+        }
+        Fields.assertTimeEquals(expected, t);
+
+        // isDst = 0, normalize(false) @ 02:30
+        Fields.set(t, 1941, 7, 10, 2, 30, 0, 0 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 1941, 7, 10, 3, 30, 0, 1 /* isDst */, 3600, 221, 0);
+        assertNormalizeResult(false, t, expected, -896045400000L);
+    }
+
+    public void testNormalize_stdToStdRepeat() {
+        // In London, 31st October 1971 02:00 - 03:00 was a repeat from STD -> STD
+        String timezone = "Europe/London";
+        Time t = new Time(timezone);
+        Time expected = new Time(timezone);
+
+        // Demonstrate the data we expect during the repeated interval: 02:30 (first)
+        t.set(57720600000L);
+        Fields.set(expected, 1971, 9, 31, 2, 30, 0, 0 /* isDst */, 3600, 303, 0);
+        Fields.assertTimeEquals(expected, t);
+
+        // Demonstrate the data we expect during the repeated interval: 02:30 (second)
+        t.set(57724200000L);
+        Fields.set(expected, 1971, 9, 31, 2, 30, 0, 0 /* isDst */, 0, 303, 0);
+        Fields.assertTimeEquals(expected, t);
+
+        // isDst = 0, normalize(false) @ 02:30
+        Fields.set(t, 1971, 9, 31, 2, 30, 0, 0 /* isDst */, 9, 9, 9);
+
+        long timeMillis = t.normalize(false);
+
+        // Either answer is valid: the choice is arbitrary.
+        if (57720600000L == timeMillis) {
+            // The original C implementation chooses this one.
+            Fields.set(expected, 1971, 9, 31, 2, 30, 0, 0 /* isDst */, 3600, 303, 0);
+        } else if (57724200000L == timeMillis) {
+            Fields.set(expected, 1971, 9, 31, 2, 30, 0, 0 /* isDst */, 0, 303, 0);
+        } else {
+            fail();
+        }
+        Fields.assertTimeEquals(expected, t);
+
+        // isDst = -1, normalize(false) @ 02:30
+        Fields.set(t, 1971, 9, 31, 2, 30, 0, -1 /* isDst */, 9, 9, 9);
+
+        timeMillis = t.normalize(false);
+
+        Fields.setDateTime(expected, 1971, 9, 31, 2, 30, 0);
+        // Either answer is valid: the choice is arbitrary.
+        if (57720600000L == timeMillis) {
+            // The original C implementation chooses this one.
+            Fields.set(expected, 1971, 9, 31, 2, 30, 0, 0 /* isDst */, 3600, 303, 0);
+        } else if (57724200000L == timeMillis) {
+            Fields.set(expected, 1971, 9, 31, 2, 30, 0, 0 /* isDst */, 0, 303, 0);
+        } else {
+            fail();
+        }
+        Fields.assertTimeEquals(expected, t);
+
+        // The results below are potentially arbitrary: 01:30 and 02:30 are not a valid DST
+        // so normalize() must apply one of the possible STD -> DST adjustments to arrive at a
+        // date / time.
+
+        // isDst = 1, normalize(false) @ 01:30
+        Fields.set(t, 1971, 9, 31, 1, 30, 0, 1 /* isDst */, 9, 9, 9);
+
+        timeMillis = t.normalize(false);
+
+        if (timeMillis == 57713400000L) {
+            // Original C implementation chooses this one.
+            Fields.set(expected, 1971, 9, 31, 0, 30, 0, 0 /* isDst */, 3600, 303, 0);
+        } else if (timeMillis == 57717000000L) {
+            Fields.set(expected, 1971, 9, 31, 1, 30, 0, 0 /* isDst */, 3600, 303, 0);
+        } else {
+            fail();
+        }
+        Fields.assertTimeEquals(expected, t);
+
+        // isDst = 1, normalize(false) @ 02:30
+        Fields.set(t, 1971, 9, 31, 2, 30, 0, 1 /* isDst */, 9, 9, 9);
+        timeMillis = t.normalize(false);
+        if (timeMillis == 57717000000L) {
+            // The original C implementation chooses this one.
+            Fields.set(expected, 1971, 9, 31, 1, 30, 0, 0 /* isDst */, 3600, 303, 0);
+        } else if (timeMillis == 57720600000L) {
+            Fields.set(expected, 1971, 9, 31, 2, 30, 0, 0 /* isDst */, 3600, 303, 0);
+        } else {
+            fail();
+        }
+        Fields.assertTimeEquals(expected, t);
+
+        // isDst = 1, normalize(false) @ 03:30
+        Fields.set(t, 1971, 9, 31, 3, 30, 0, 1 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 1971, 9, 31, 2, 30, 0, 0 /* isDst */, 0, 303, 0);
+        assertNormalizeResult(false, t, expected, 57724200000L);
+    }
+
+    public void testNormalize_stdToStdSkip() {
+        // In Kiritimati, 1st Jan 1995 10:00 - 10:40 was a skip from STD -> STD (plus they do not
+        // observe DST).
+        String timezone = "Pacific/Kiritimati";
+        Time t = new Time(timezone);
+        Time expected = new Time(timezone);
+
+        // isDst = 0, normalize(false)
+        Fields.set(t, 1995, 0, 1, 10, 20, 0, 0 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 1995, 0, 1, 10, 20, 0, 0 /* isDst */, 9, 9, 9);
+        assertNormalizeResult(false, t, expected, -1);
+
+        // isDst = 1, normalize(false)
+        Fields.set(t, 1995, 0, 1, 10, 20, 0, 1 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 1995, 0, 1, 10, 20, 0, 1 /* isDst */, 9, 9, 9);
+        assertNormalizeResult(false, t, expected, -1);
+
+        // isDst = -1, normalize(false)
+        Fields.set(t, 1995, 0, 1, 10, 20, 0, -1 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 1995, 0, 1, 10, 20, 0, -1 /* isDst */, 9, 9, 9);
+        assertNormalizeResult(false, t, expected, -1);
+    }
+
+    public void testNormalize_utcWithDst() {
+        // In UTC (or other zone without DST), what happens when a DST time is specified and there
+        // is no DST offset available in the timezone data.
+        Time t = new Time(Time.TIMEZONE_UTC);
+        Time expected = new Time(Time.TIMEZONE_UTC);
+
+        // isDst = 1, normalize(false)
+        Fields.set(t, 2005, 6, 22, 1, 30, 0, 1 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 2005, 6, 22, 1, 30, 0, 1 /* isDst */, 9, 9, 9);
+        assertNormalizeResult(false, t, expected, -1);
+
+        // isDst = -1, normalize(false)
+        Fields.set(t, 2005, 6, 22, 1, 30, 0, -1 /* isDst */, 9, 9, 9);
+        Fields.set(expected, 2005, 6, 22, 1, 30, 0, 0 /* isDst */, 0, 202, 5);
+        assertNormalizeResult(false, t, expected, 1121995800000L);
+    }
+
+    public void testUnknownTz() {
+        // Historically the code used UTC if the timezone is unrecognized.
+
+        String unknownTimezoneId = "THIS_ID_IS_NOT_A_VALID_TZ";
+        Time t = new Time(unknownTimezoneId);
+        assertEquals(unknownTimezoneId, t.timezone);
+        Fields.set(t, 2007, 5, 1, 1, 2, 3, -1 /* isDst */, 9, 9, 9);
+
+        // We can't know for sure which time zone is being used, but we assume it is UTC if the date
+        // normalizes to isDst == 0 and with an offset of 0 during the summer months.
+
+        long timeMillis = t.normalize(true);
+        assertEquals(unknownTimezoneId, t.timezone);
+        assertEquals(1180659723000L, timeMillis);
+
+        Time expected = new Time(unknownTimezoneId);
+        Fields.set(expected, 2007, 5, 1, 1, 2, 3, 0 /* isDst */, 0, 151, 5);
+        Fields.assertTimeEquals(expected, t);
+    }
+
+    private static void assertNormalizeResult(boolean normalizeArgument, Time toNormalize,
+            Time expectedTime, long expectedTimeMillis) {
+        long actualTimeMillis = toNormalize.normalize(normalizeArgument /* ignore isDst */);
+        assertEquals(expectedTimeMillis, actualTimeMillis);
+        Fields.assertTimeEquals(expectedTime, toNormalize);
+    }
+
+    /** A helper class for manipulating / testing fields on Time objects. */
+    private static class Fields {
+        final static int MAIN_DATE_TIME = 1;
+        final static int DST_FIELDS = 2;
+        final static int DERIVED_DATE_TIME = 4;
+
+        final static int ALL = MAIN_DATE_TIME | DST_FIELDS | DERIVED_DATE_TIME;
+
+        public static void assertTimeEquals(Time expected, Time actual) {
+            assertTimeEquals("", ALL, expected, actual);
+        }
+
+        public static void assertTimeEquals(int fields, Time expected, Time actual) {
+            assertTimeEquals("", fields, expected, actual);
+        }
+
+        public static void assertTimeEquals(String message, Time expected, Time actual) {
+            assertTimeEquals(message, Fields.ALL, expected, actual);
+        }
+
+        public static void assertTimeEquals(String message, int fields, Time expected,
+                Time actual) {
+            boolean mainDateTimeOk = (fields & Fields.MAIN_DATE_TIME) == 0
+                    || (Objects.equals(expected.timezone, actual.timezone)
+                    && expected.year == actual.year
+                    && expected.month == actual.month
+                    && expected.monthDay == actual.monthDay
+                    && expected.hour == actual.hour
+                    && expected.minute == actual.minute
+                    && expected.second == actual.second
+                    && expected.allDay == actual.allDay);
+
+            boolean dstFieldsOk = (fields & Fields.DST_FIELDS) == 0
+                    || (expected.isDst == actual.isDst && expected.gmtoff == actual.gmtoff);
+
+            boolean derivedDateTimeOk = (fields & Fields.DERIVED_DATE_TIME) == 0
+                    || (expected.yearDay == actual.yearDay && expected.weekDay == actual.weekDay);
+
+            if (!mainDateTimeOk || !dstFieldsOk || !derivedDateTimeOk) {
+                String expectedTime = timeToString(fields, expected);
+                String actualTime = timeToString(fields, actual);
+                fail(message + " [Time fields differed. Expected: " + expectedTime + "Actual: "
+                        + actualTime + "]");
+            }
+        }
+
+        private static String timeToString(int fields, Time time) {
+            List<Object> values = new ArrayList<Object>();
+            StringBuilder format = new StringBuilder();
+            if ((fields & Fields.MAIN_DATE_TIME) > 0) {
+                format.append("%d-%02d-%02d %02d:%02d:%02d allDay=%b timezone=%s ");
+                values.addAll(
+                        Arrays.asList(time.year, time.month, time.monthDay, time.hour, time.minute,
+                                time.second, time.allDay, time.timezone));
+            }
+            if ((fields & Fields.DST_FIELDS) > 0) {
+                format.append("isDst=%d, gmtoff=%d ");
+                values.add(time.isDst);
+                values.add(time.gmtoff);
+            }
+            if ((fields & Fields.DERIVED_DATE_TIME) > 0) {
+                format.append("yearDay=%d, weekDay=%d ");
+                values.add(time.yearDay);
+                values.add(time.weekDay);
+
+            }
+            return String.format(format.toString(), values.toArray());
+        }
+
+        public static void setDateTime(Time t, int year, int month, int monthDay, int hour,
+                int minute, int second) {
+            t.year = year;
+            t.month = month;
+            t.monthDay = monthDay;
+            t.hour = hour;
+            t.minute = minute;
+            t.second = second;
+            t.allDay = false;
+        }
+
+        public static void setDateTime(Time t, int[] args) {
+            assertEquals(6, args.length);
+            setDateTime(t, args[0], args[1], args[2], args[3], args[4], args[5]);
+        }
+
+        public static void setDst(Time t, int isDst, int gmtoff) {
+            t.isDst = isDst;
+            t.gmtoff = gmtoff;
+        }
+
+        public static void setDerivedDateTime(Time t, int yearDay, int weekDay) {
+            t.yearDay = yearDay;
+            t.weekDay = weekDay;
+        }
+
+        public static void setAllDayDate(Time t, int year, int month, int monthDay) {
+            t.year = year;
+            t.month = month;
+            t.monthDay = monthDay;
+            t.allDay = true;
+        }
+
+        public static void set(Time t, int[] args) {
+            assertEquals(10, args.length);
+            set(t, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8],
+                    args[9]);
+        }
+
+        public static void set(Time t, int year, int month, int monthDay, int hour, int minute,
+                int second, int isDst, int gmtoff, int yearDay, int weekDay) {
+            setDateTime(t, year, month, monthDay, hour, minute, second);
+            setDst(t, isDst, gmtoff);
+            setDerivedDateTime(t, yearDay, weekDay);
+        }
+    }
+
+    private static class PstPdt {
+        public static final String ID = "America/Los_Angeles";
+
+        public static int getUtcOffsetSeconds(int isDst) {
+            if (isDst == 0) {
+                return -28800;
+            } else if (isDst == 1) {
+                return -25200;
+            }
+            throw new IllegalArgumentException();
+        }
+
+        public static int getUtcOffsetSeconds(boolean isDst) {
+            return getUtcOffsetSeconds(isDst ? 1 : 0);
+        }
+
+        public static int getUtcOffsetMillis(boolean isDst) {
+            return getUtcOffsetSeconds(isDst) * 1000;
+        }
+    }
+
+    private static void changeJavaAndAndroidLocale(Locale locale) {
+        // The Time class uses the Android-managed locale for string resources containing format
+        // patterns and the Java-managed locale for other things (e.g. month names, week days names)
+        // that are placed into those patterns. For example the format "%c" expands to include
+        // a pattern that includes month names.
+        // Changing the Java-managed Locale does not affect the Android-managed locale.
+        // Changing the Android-managed locale does not affect the Java-managed locale.
+        //
+        // In order to ensure consistent behavior in the tests the device Locale must not be
+        // assumed. To simulate the most common behavior (i.e. when the Java and the Android-managed
+        // locales agree), when the Java-managed locale is changed during this test the locale in
+        // the runtime-local copy of the system resources is modified as well.
+
+        // Change the Java-managed locale.
+        Locale.setDefault(locale);
+
+        // Change the local copy of the Android system configuration: this simulates the device
+        // being set to the locale and forces a reload of the string resources.
+        Configuration configuration = Resources.getSystem().getConfiguration();
+        configuration.locale = locale;
+        Resources.getSystem().updateConfiguration(configuration, null);
+    }
 }
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 9b1acf7..10d08d0 100644
--- a/tests/tests/text/src/android/text/method/cts/ArrowKeyMovementMethodTest.java
+++ b/tests/tests/text/src/android/text/method/cts/ArrowKeyMovementMethodTest.java
@@ -42,7 +42,7 @@
  *
  * @see android.widget.cts.TextViewTest
  */
-public class ArrowKeyMovementMethodTest extends ActivityInstrumentationTestCase2<StubActivity> {
+public class ArrowKeyMovementMethodTest extends ActivityInstrumentationTestCase2<CtsActivity> {
     private static final String THREE_LINES_TEXT = "first line\nsecond line\nlast line";
     private static final int END_OF_ALL_TEXT = THREE_LINES_TEXT.length();
     private static final int END_OF_1ST_LINE = THREE_LINES_TEXT.indexOf('\n');
@@ -56,7 +56,7 @@
     private MyMetaKeyKeyListener mMetaListener;
 
     public ArrowKeyMovementMethodTest() {
-        super("com.android.cts.stub", StubActivity.class);
+        super("com.android.cts.text", CtsActivity.class);
     }
 
     @Override
@@ -71,7 +71,7 @@
             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();
@@ -179,26 +179,30 @@
 
     @UiThreadTest
     public void testOnKeyDownWithKeyCodeUp() {
+        // shift+alt tests
+        KeyEvent shiftAltEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP,
+                0, KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON);
+
         // first line
         // second |line
         // last line
         Selection.setSelection(mEditable, SPACE_IN_2ND_LINE);
         pressBothShiftAlt();
-        KeyEvent event = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
-            KeyEvent.KEYCODE_DPAD_UP, 0, KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON);
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_UP, event));
+                KeyEvent.KEYCODE_DPAD_UP, shiftAltEvent));
         // |first line
         // second |line
         // last line
         assertSelection(SPACE_IN_2ND_LINE, 0);
 
+        // shift tests
+        KeyEvent shiftEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP, 0,
+                KeyEvent.META_SHIFT_ON);
+
         Selection.setSelection(mEditable, SPACE_IN_2ND_LINE);
         pressShift();
-        event = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
-            KeyEvent.KEYCODE_DPAD_UP, 0, KeyEvent.META_SHIFT_ON);
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_UP, event));
+                KeyEvent.KEYCODE_DPAD_UP, shiftEvent));
         // first lin|e
         // second |line
         // last line
@@ -209,65 +213,80 @@
 
         pressShift();
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_UP, new KeyEvent(KeyEvent.ACTION_DOWN,
-                        KeyEvent.KEYCODE_DPAD_UP)));
+                KeyEvent.KEYCODE_DPAD_UP, shiftEvent));
         // |first line
         // second |line
         // last line
         assertSelection(SPACE_IN_2ND_LINE, 0);
 
+        // alt tests
+        KeyEvent altEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP, 0,
+                KeyEvent.META_ALT_ON);
+
         Selection.setSelection(mEditable, SPACE_IN_2ND_LINE);
         pressAlt();
-        event = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
-            KeyEvent.KEYCODE_DPAD_UP, 0, KeyEvent.META_ALT_ON);
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_UP, event));
+                KeyEvent.KEYCODE_DPAD_UP, altEvent));
         // |first line
         // second line
         // last line
         assertSelection(0);
 
+        // no-meta tests
+        KeyEvent noMetaEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP,
+                0, 0);
+
         Selection.setSelection(mEditable, SPACE_IN_2ND_LINE);
         MetaKeyKeyListener.resetMetaState(mEditable);
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_UP, new KeyEvent(KeyEvent.ACTION_DOWN,
-                        KeyEvent.KEYCODE_DPAD_UP)));
+                KeyEvent.KEYCODE_DPAD_UP, noMetaEvent));
         // first lin|e
         // second line
         // last line
         assertSelection(correspondingIn1stLine);
 
-        assertFalse(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_UP, new KeyEvent(KeyEvent.ACTION_DOWN,
-                        KeyEvent.KEYCODE_DPAD_UP)));
-        // first lin|e
+        // Move to beginning of first line (behavior changed in L)
+        assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
+                KeyEvent.KEYCODE_DPAD_UP, noMetaEvent));
+        // |first line
         // second line
         // last line
-        assertSelection(correspondingIn1stLine);
+        assertSelection(0);
+
+        assertFalse(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
+                KeyEvent.KEYCODE_DPAD_UP, noMetaEvent));
+        // |first line
+        // second line
+        // last line
+        assertSelection(0);
     }
 
     @UiThreadTest
     public void testOnKeyDownWithKeyCodeDown() {
+        // shift+alt tests
+        KeyEvent shiftAltEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
+                KeyEvent.KEYCODE_DPAD_DOWN, 0, KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON);
+
         // first line
         // second |line
         // last line
         Selection.setSelection(mEditable, SPACE_IN_2ND_LINE);
         pressBothShiftAlt();
-        KeyEvent event = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
-                KeyEvent.KEYCODE_DPAD_DOWN, 0, KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON);
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_DOWN, event));
+                KeyEvent.KEYCODE_DPAD_DOWN, shiftAltEvent));
         // first line
         // second |line
         // last line|
         assertSelection(SPACE_IN_2ND_LINE, END_OF_ALL_TEXT);
 
+        // shift tests
+        KeyEvent shiftEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN,
+                0, KeyEvent.META_SHIFT_ON);
+
         Selection.setSelection(mEditable, SPACE_IN_2ND_LINE);
         pressShift();
-        event = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
-                KeyEvent.KEYCODE_DPAD_DOWN, 0, KeyEvent.META_SHIFT_ON);
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_DOWN, event));
+                KeyEvent.KEYCODE_DPAD_DOWN, shiftEvent));
         // first line
         // second |line
         // last lin|e
@@ -277,57 +296,69 @@
         assertTrue(correspondingIn3rdLine <= END_OF_ALL_TEXT);
 
         pressShift();
-        event = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
-                KeyEvent.KEYCODE_DPAD_DOWN, 0, 0);
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_DOWN, event));
+                KeyEvent.KEYCODE_DPAD_DOWN, shiftEvent));
         // first line
         // second |line
         // last line|
         assertSelection(SPACE_IN_2ND_LINE, END_OF_ALL_TEXT);
 
+        // alt tests
+        KeyEvent altEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN, 0,
+                KeyEvent.META_ALT_ON);
+
         Selection.setSelection(mEditable, SPACE_IN_2ND_LINE);
         pressAlt();
-        event = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
-                KeyEvent.KEYCODE_DPAD_DOWN, 0, KeyEvent.META_ALT_ON);
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_DOWN, event));
+                KeyEvent.KEYCODE_DPAD_DOWN, altEvent));
         // first line
         // second line
         // last line|
         assertSelection(END_OF_ALL_TEXT);
 
-        pressAlt();
+        // no-meta tests
+        KeyEvent noMetaEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN,
+                0, 0);
+
         Selection.setSelection(mEditable, SPACE_IN_2ND_LINE);
         MetaKeyKeyListener.resetMetaState(mEditable);
-        event = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
-                KeyEvent.KEYCODE_DPAD_DOWN, 0, 0);
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_DOWN, event));
+                KeyEvent.KEYCODE_DPAD_DOWN, noMetaEvent));
         // first line
         // second line
         // last lin|e
         assertSelection(correspondingIn3rdLine);
 
-        assertFalse(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_DOWN, event));
+        // move to end of last line (behavior changed in L)
+        Selection.setSelection(mEditable, END_OF_ALL_TEXT - 1);
+        assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
+                KeyEvent.KEYCODE_DPAD_DOWN, noMetaEvent));
         // first line
         // second line
-        // last lin|e
-        assertSelection(correspondingIn3rdLine);
+        // last line|
+        assertSelection(END_OF_ALL_TEXT);
+
+        assertFalse(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
+                KeyEvent.KEYCODE_DPAD_DOWN, noMetaEvent));
+        // first line
+        // second line
+        // last line|
+        assertSelection(END_OF_ALL_TEXT);
     }
 
     @UiThreadTest
     public void testOnKeyDownWithKeyCodeLeft() {
+        // shift+alt tests
+        KeyEvent shiftAltEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
+                KeyEvent.KEYCODE_DPAD_LEFT, 0, KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON);
+
         // first line
         // second |line
         // last line
         Selection.setSelection(mEditable, SPACE_IN_2ND_LINE);
         pressBothShiftAlt();
-        KeyEvent event = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
-            KeyEvent.KEYCODE_DPAD_LEFT, 0, KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON);
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_LEFT, event));
+                KeyEvent.KEYCODE_DPAD_LEFT, shiftAltEvent));
         // first line
         // |second |line
         // last line
@@ -335,18 +366,20 @@
 
         pressBothShiftAlt();
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_LEFT, event));
+                KeyEvent.KEYCODE_DPAD_LEFT, shiftAltEvent));
         // first line
         // |second |line
         // last line
         assertSelection(SPACE_IN_2ND_LINE, START_OF_2ND_LINE);
 
+        // shift tests
+        KeyEvent shiftEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_LEFT,
+                0, KeyEvent.META_SHIFT_ON);
+
         Selection.setSelection(mEditable, SPACE_IN_2ND_LINE);
         pressShift();
-        event = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
-            KeyEvent.KEYCODE_DPAD_LEFT, 0, KeyEvent.META_SHIFT_ON);
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_LEFT, event));
+                KeyEvent.KEYCODE_DPAD_LEFT, shiftEvent));
         // first line
         // second| |line
         // last line
@@ -354,19 +387,20 @@
 
         pressShift();
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_LEFT, new KeyEvent(KeyEvent.ACTION_DOWN,
-                        KeyEvent.KEYCODE_DPAD_LEFT)));
+                KeyEvent.KEYCODE_DPAD_LEFT, shiftEvent));
         // first line
         // secon|d |line
         // last line
         assertSelection(SPACE_IN_2ND_LINE, SPACE_IN_2ND_LINE - 2);
 
+        // alt tests
+        KeyEvent altEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_LEFT, 0,
+                KeyEvent.META_ALT_ON);
+
         Selection.setSelection(mEditable, SPACE_IN_2ND_LINE);
         pressAlt();
-        event = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
-            KeyEvent.KEYCODE_DPAD_LEFT, 0, KeyEvent.META_ALT_ON);
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_LEFT, event));
+                KeyEvent.KEYCODE_DPAD_LEFT, altEvent));
         // first line
         // |second line
         // last line
@@ -374,17 +408,20 @@
 
         pressAlt();
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_LEFT, event));
+                KeyEvent.KEYCODE_DPAD_LEFT, altEvent));
         // first line
         // |second line
         // last line
         assertSelection(START_OF_2ND_LINE);
 
+        // no-meta tests
+        KeyEvent noMetaEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_LEFT,
+                0, 0);
+
         Selection.setSelection(mEditable, SPACE_IN_2ND_LINE);
         MetaKeyKeyListener.resetMetaState(mEditable);
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_LEFT, new KeyEvent(KeyEvent.ACTION_DOWN,
-                        KeyEvent.KEYCODE_DPAD_LEFT)));
+                KeyEvent.KEYCODE_DPAD_LEFT, noMetaEvent));
         // first line
         // second| line
         // last line
@@ -395,8 +432,7 @@
         // |second line
         // last line
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_LEFT, new KeyEvent(KeyEvent.ACTION_DOWN,
-                        KeyEvent.KEYCODE_DPAD_LEFT)));
+                KeyEvent.KEYCODE_DPAD_LEFT, noMetaEvent));
         // first line|
         // second line
         // last line
@@ -405,15 +441,17 @@
 
     @UiThreadTest
     public void testOnKeyDownWithKeyCodeRight() {
+        // shift+alt tests
+        KeyEvent shiftAltEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
+                KeyEvent.KEYCODE_DPAD_RIGHT, 0, KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON);
+
         // first line
         // second |line
         // last line
         Selection.setSelection(mEditable, SPACE_IN_2ND_LINE);
         pressBothShiftAlt();
-        KeyEvent event = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
-            KeyEvent.KEYCODE_DPAD_RIGHT, 0, KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON);
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_RIGHT, event));
+                KeyEvent.KEYCODE_DPAD_RIGHT, shiftAltEvent));
         // first line
         // second |line|
         // last line
@@ -421,18 +459,20 @@
 
         pressBothShiftAlt();
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_RIGHT, event));
+                KeyEvent.KEYCODE_DPAD_RIGHT, shiftAltEvent));
         // first line
         // second |line|
         // last line
         assertSelection(SPACE_IN_2ND_LINE, END_OF_2ND_LINE);
 
+        // shift tests
+        KeyEvent shiftEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT,
+                0, KeyEvent.META_SHIFT_ON);
+
         Selection.setSelection(mEditable, SPACE_IN_2ND_LINE);
         pressShift();
-        event = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
-            KeyEvent.KEYCODE_DPAD_RIGHT, 0, KeyEvent.META_SHIFT_ON);
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_RIGHT, event));
+                KeyEvent.KEYCODE_DPAD_RIGHT, shiftEvent));
         // first line
         // second |l|ine
         // last line
@@ -440,18 +480,20 @@
 
         pressShift();
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_RIGHT, event));
+                KeyEvent.KEYCODE_DPAD_RIGHT, shiftEvent));
         // first line
         // second |li|ne
         // last line
         assertSelection(SPACE_IN_2ND_LINE, SPACE_IN_2ND_LINE + 2);
 
+        // alt tests
+        KeyEvent altEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT,
+                0, KeyEvent.META_ALT_ON);
+
         Selection.setSelection(mEditable, SPACE_IN_2ND_LINE);
         pressAlt();
-        event = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
-            KeyEvent.KEYCODE_DPAD_RIGHT, 0, KeyEvent.META_ALT_ON);
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_RIGHT, event));
+                KeyEvent.KEYCODE_DPAD_RIGHT, altEvent));
         // first line
         // second line|
         // last line
@@ -459,17 +501,20 @@
 
         pressAlt();
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_RIGHT, event));
+                KeyEvent.KEYCODE_DPAD_RIGHT, altEvent));
         // first line
         // second line|
         // last line
         assertSelection(END_OF_2ND_LINE);
 
+        // no-meta tests
+        KeyEvent noMetaEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
+                KeyEvent.KEYCODE_DPAD_RIGHT, 0, 0);
+
         Selection.setSelection(mEditable, SPACE_IN_2ND_LINE);
         MetaKeyKeyListener.resetMetaState(mEditable);
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_RIGHT, new KeyEvent(KeyEvent.ACTION_DOWN,
-                        KeyEvent.KEYCODE_DPAD_RIGHT)));
+                KeyEvent.KEYCODE_DPAD_RIGHT, noMetaEvent));
         // first line
         // second l|ine
         // last line
@@ -480,8 +525,7 @@
         // second line|
         // last line
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_RIGHT, new KeyEvent(KeyEvent.ACTION_DOWN,
-                        KeyEvent.KEYCODE_DPAD_RIGHT)));
+                KeyEvent.KEYCODE_DPAD_RIGHT, noMetaEvent));
         // first line
         // second line
         // |last line
diff --git a/tests/tests/text/src/android/text/method/cts/CharacterPickerDialogTest.java b/tests/tests/text/src/android/text/method/cts/CharacterPickerDialogTest.java
index 1e7150b..382fc77 100644
--- a/tests/tests/text/src/android/text/method/cts/CharacterPickerDialogTest.java
+++ b/tests/tests/text/src/android/text/method/cts/CharacterPickerDialogTest.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.os.Bundle;
 import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
 import android.text.Editable;
 import android.text.Selection;
 import android.text.method.CharacterPickerDialog;
@@ -30,11 +31,11 @@
 import android.widget.TextView;
 
 public class CharacterPickerDialogTest extends
-        ActivityInstrumentationTestCase2<StubActivity> {
+        ActivityInstrumentationTestCase2<CtsActivity> {
     private Activity mActivity;
 
     public CharacterPickerDialogTest() {
-        super("com.android.cts.stub", StubActivity.class);
+        super("com.android.cts.text", CtsActivity.class);
     }
 
     @Override
@@ -43,6 +44,7 @@
         mActivity = getActivity();
     }
 
+    @UiThreadTest
     public void testConstructor() {
         final CharSequence str = "123456";
         final Editable content = Editable.Factory.getInstance().newEditable(str);
@@ -61,6 +63,7 @@
         // Do not test. Implementation details.
     }
 
+    @UiThreadTest
     public void testOnItemClick() {
         final Gallery parent = new Gallery(mActivity);
         final CharSequence str = "123456";
@@ -102,6 +105,7 @@
         assertFalse(insertPickerDialog.isShowing());
     }
 
+    @UiThreadTest
     public void testOnClick() {
         final CharSequence str = "123456";
         final Editable content = Editable.Factory.getInstance().newEditable(str);
diff --git a/tests/tests/text/src/android/text/method/cts/CtsActivity.java b/tests/tests/text/src/android/text/method/cts/CtsActivity.java
new file mode 100644
index 0000000..edf3a0e
--- /dev/null
+++ b/tests/tests/text/src/android/text/method/cts/CtsActivity.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2009 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.text.method.cts;
+
+import android.app.Activity;
+import android.text.method.ArrowKeyMovementMethod;
+import android.text.method.LinkMovementMethod;
+import android.text.method.ScrollingMovementMethod;
+
+/**
+ * This Activity is used for testing:
+ * {@link LinkMovementMethod}
+ * {@link ArrowKeyMovementMethod}
+ * {@link ScrollingMovementMethod}
+ *
+ * The content view will be set in the test cases.
+ *
+ * @see LinkMovementMethodTest
+ * @see ArrowKeyMovementMethodTest
+ * @see ScrollingMovementMethodTest
+ */
+public class CtsActivity extends Activity {
+}
diff --git a/tests/tests/text/src/android/text/method/cts/KeyListenerCtsActivity.java b/tests/tests/text/src/android/text/method/cts/KeyListenerCtsActivity.java
new file mode 100644
index 0000000..c6483a2
--- /dev/null
+++ b/tests/tests/text/src/android/text/method/cts/KeyListenerCtsActivity.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2009 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.text.method.cts;
+
+import com.android.cts.text.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.SystemClock;
+import android.text.method.BaseKeyListener;
+import android.text.method.DateKeyListener;
+import android.text.method.DateTimeKeyListener;
+import android.text.method.DigitsKeyListener;
+import android.text.method.MultiTapKeyListener;
+import android.text.method.NumberKeyListener;
+import android.text.method.QwertyKeyListener;
+import android.text.method.TextKeyListener;
+import android.text.method.TimeKeyListener;
+import android.util.Log;
+
+/**
+ * This Activity is used for testing:
+ * {@link DigitsKeyListener}
+ * {@link BaseKeyListener}
+ * {@link MultiTapKeyListener}
+ * {@link NumberKeyListener}
+ * {@link QwertyKeyListener}
+ * {@link TextKeyListener}
+ * {@link DateKeyListener}
+ * {@link DateTimeKeyListener}
+ * {@link TimeKeyListener}
+ *
+ * @see DigitsKeyListener
+ * @see BaseKeyListener
+ * @see MultiTapKeyListener
+ * @see NumberKeyListener
+ * @see QwertyKeyListener
+ * @see TextKeyListener
+ * @see DateKeyListener
+ * @see DateTimeKeyListener
+ * @see TimeKeyListener
+ */
+
+public class KeyListenerCtsActivity extends Activity {
+    private boolean mHasWindowFocus = false;
+    private Object mHasWindowFocusLock = new Object();
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.keylistener_layout);
+    }
+
+    @Override
+    public void onWindowFocusChanged(boolean hasFocus) {
+        super.onWindowFocusChanged(hasFocus);
+        if (!hasFocus) {
+            Log.w("KeyListenerCtsActivity", "KeyListenerCtsActivity lost window focus");
+        }
+        synchronized(mHasWindowFocusLock) {
+            mHasWindowFocus = hasFocus;
+            mHasWindowFocusLock.notify();
+        }
+    }
+
+    /**
+     * Blocks the calling thread until the {@link KeyListenerCtsActivity} has window focus or the
+     * specified duration (in milliseconds) has passed.
+     */
+    public boolean waitForWindowFocus(long durationMillis) {
+        long elapsedMillis = SystemClock.elapsedRealtime();
+        synchronized(mHasWindowFocusLock) {
+            mHasWindowFocus = hasWindowFocus();
+            while (!mHasWindowFocus && durationMillis > 0) {
+                long newElapsedMillis = SystemClock.elapsedRealtime();
+                durationMillis -= (newElapsedMillis - elapsedMillis);
+                elapsedMillis = newElapsedMillis;
+                if (durationMillis > 0) {
+                    try {
+                        mHasWindowFocusLock.wait(durationMillis);
+                    } catch (InterruptedException e) {
+                    }
+                }
+            }
+            return mHasWindowFocus;
+        }
+    }
+}
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 375ea54..8bb2adf 100644
--- a/tests/tests/text/src/android/text/method/cts/KeyListenerTestCase.java
+++ b/tests/tests/text/src/android/text/method/cts/KeyListenerTestCase.java
@@ -16,12 +16,12 @@
 
 package android.text.method.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.text.R;
 
 import android.app.Instrumentation;
 import android.test.ActivityInstrumentationTestCase2;
 import android.text.format.DateUtils;
-import android.text.method.cts.KeyListenerStubActivity;
+import android.text.method.cts.KeyListenerCtsActivity;
 import android.text.method.KeyListener;
 import android.view.WindowManager;
 import android.widget.TextView;
@@ -47,13 +47,13 @@
  * @see TextKeyKeyListenerTest
  */
 public abstract class KeyListenerTestCase extends
-        ActivityInstrumentationTestCase2<KeyListenerStubActivity> {
-    protected KeyListenerStubActivity mActivity;
+        ActivityInstrumentationTestCase2<KeyListenerCtsActivity> {
+    protected KeyListenerCtsActivity mActivity;
     protected Instrumentation mInstrumentation;
     protected TextView mTextView;
 
     public KeyListenerTestCase() {
-        super("com.android.cts.stub", KeyListenerStubActivity.class);
+        super("com.android.cts.text", KeyListenerCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/text/src/android/text/method/cts/LinkMovementMethodTest.java b/tests/tests/text/src/android/text/method/cts/LinkMovementMethodTest.java
index b67f313..336921a 100644
--- a/tests/tests/text/src/android/text/method/cts/LinkMovementMethodTest.java
+++ b/tests/tests/text/src/android/text/method/cts/LinkMovementMethodTest.java
@@ -42,7 +42,7 @@
  * @see android.widget.cts.TextViewTest
  */
 public class LinkMovementMethodTest extends
-        ActivityInstrumentationTestCase2<StubActivity> {
+        ActivityInstrumentationTestCase2<CtsActivity> {
     private static final String CONTENT = "clickable\nunclickable\nclickable";
 
     private LinkMovementMethod mMethod;
@@ -56,7 +56,7 @@
     private MockClickableSpan mClickable1;
 
     public LinkMovementMethodTest() {
-        super("com.android.cts.stub", StubActivity.class);
+        super("com.android.cts.text", CtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/text/src/android/text/method/cts/PasswordTransformationMethodTest.java b/tests/tests/text/src/android/text/method/cts/PasswordTransformationMethodTest.java
index 471f67a..4262a31 100644
--- a/tests/tests/text/src/android/text/method/cts/PasswordTransformationMethodTest.java
+++ b/tests/tests/text/src/android/text/method/cts/PasswordTransformationMethodTest.java
@@ -35,7 +35,7 @@
  * Test {@link PasswordTransformationMethod}.
  */
 public class PasswordTransformationMethodTest extends
-        ActivityInstrumentationTestCase2<StubActivity> {
+        ActivityInstrumentationTestCase2<CtsActivity> {
     private static final int EDIT_TXT_ID = 1;
 
     /** original text */
@@ -49,7 +49,7 @@
 
     private boolean isPasswordPrefSaved;
 
-    private StubActivity mActivity;
+    private CtsActivity mActivity;
 
     private MockPasswordTransformationMethod mMethod;
 
@@ -58,7 +58,7 @@
     private CharSequence mTransformedText;
 
     public PasswordTransformationMethodTest() {
-        super("com.android.cts.stub", StubActivity.class);
+        super("com.android.cts.text", CtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/text/src/android/text/method/cts/ReplacementTransformationMethodTest.java b/tests/tests/text/src/android/text/method/cts/ReplacementTransformationMethodTest.java
index 3c05f30..dadce15 100644
--- a/tests/tests/text/src/android/text/method/cts/ReplacementTransformationMethodTest.java
+++ b/tests/tests/text/src/android/text/method/cts/ReplacementTransformationMethodTest.java
@@ -27,7 +27,7 @@
  * Test {@link ReplacementTransformationMethod}.
  */
 public class ReplacementTransformationMethodTest extends
-        ActivityInstrumentationTestCase2<StubActivity> {
+        ActivityInstrumentationTestCase2<CtsActivity> {
     private final char[] ORIGINAL = new char[] { '0', '1' };
     private final char[] ORIGINAL_WITH_MORE_CHARS = new char[] { '0', '1', '2' };
     private final char[] ORIGINAL_WITH_SAME_CHARS = new char[] { '0', '0' };
@@ -37,7 +37,7 @@
     private EditText mEditText;
 
     public ReplacementTransformationMethodTest() {
-        super("com.android.cts.stub", StubActivity.class);
+        super("com.android.cts.text", CtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/text/src/android/text/method/cts/ScrollingMovementMethodTest.java b/tests/tests/text/src/android/text/method/cts/ScrollingMovementMethodTest.java
index b119c9d..73fd763 100644
--- a/tests/tests/text/src/android/text/method/cts/ScrollingMovementMethodTest.java
+++ b/tests/tests/text/src/android/text/method/cts/ScrollingMovementMethodTest.java
@@ -18,6 +18,7 @@
 
 import dalvik.annotation.KnownFailure;
 
+import android.cts.util.WidgetTestUtils;
 import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
 import android.text.Layout;
@@ -33,7 +34,6 @@
 import android.view.ViewGroup.LayoutParams;
 import android.widget.TextView;
 import android.widget.TextView.BufferType;
-import android.widget.cts.WidgetTestUtils;
 
 /**
  * Test {@link ScrollingMovementMethod}. The class is an implementation of interface
@@ -43,7 +43,7 @@
  *
  * @see android.widget.cts.TextViewTest
  */
-public class ScrollingMovementMethodTest extends ActivityInstrumentationTestCase2<StubActivity> {
+public class ScrollingMovementMethodTest extends ActivityInstrumentationTestCase2<CtsActivity> {
     private static final int LITTLE_SPACE = 20;
 
     private static final String THREE_LINES_TEXT = "first line\nsecond line\nlast line";
@@ -55,7 +55,7 @@
     private int mScaledTouchSlop;
 
     public ScrollingMovementMethodTest() {
-        super("com.android.cts.stub", StubActivity.class);
+        super("com.android.cts.text", CtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/text/src/android/text/method/cts/SingleLineTransformationMethodTest.java b/tests/tests/text/src/android/text/method/cts/SingleLineTransformationMethodTest.java
index 8d88a8a..460ce3d 100644
--- a/tests/tests/text/src/android/text/method/cts/SingleLineTransformationMethodTest.java
+++ b/tests/tests/text/src/android/text/method/cts/SingleLineTransformationMethodTest.java
@@ -26,9 +26,9 @@
  * Test {@link SingleLineTransformationMethod}.
  */
 public class SingleLineTransformationMethodTest
-        extends ActivityInstrumentationTestCase2<StubActivity> {
+        extends ActivityInstrumentationTestCase2<CtsActivity> {
     public SingleLineTransformationMethodTest() {
-        super("com.android.cts.stub", StubActivity.class);
+        super("com.android.cts.text", CtsActivity.class);
     }
 
     public void testConstructor() {
diff --git a/tests/src/android/text/method/cts/TextMethodUtils.java b/tests/tests/text/src/android/text/method/cts/TextMethodUtils.java
similarity index 100%
rename from tests/src/android/text/method/cts/TextMethodUtils.java
rename to tests/tests/text/src/android/text/method/cts/TextMethodUtils.java
diff --git a/tests/tests/text/src/android/text/method/cts/TouchTest.java b/tests/tests/text/src/android/text/method/cts/TouchTest.java
index 58e889a..343847e 100644
--- a/tests/tests/text/src/android/text/method/cts/TouchTest.java
+++ b/tests/tests/text/src/android/text/method/cts/TouchTest.java
@@ -29,7 +29,7 @@
 import android.view.MotionEvent;
 import android.widget.TextView;
 
-public class TouchTest extends ActivityInstrumentationTestCase2<StubActivity> {
+public class TouchTest extends ActivityInstrumentationTestCase2<CtsActivity> {
     private Activity mActivity;
     private static final String LONG_TEXT = "Scrolls the specified widget to the specified " +
             "coordinates, except constrains the X scrolling position to the horizontal regions " +
@@ -43,7 +43,7 @@
     private boolean mReturnFromTouchEvent;
 
     public TouchTest() {
-        super("com.android.cts.stub", StubActivity.class);
+        super("com.android.cts.text", CtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/text/src/android/text/style/cts/DrawableMarginSpanTest.java b/tests/tests/text/src/android/text/style/cts/DrawableMarginSpanTest.java
index bea0944..3813a94 100644
--- a/tests/tests/text/src/android/text/style/cts/DrawableMarginSpanTest.java
+++ b/tests/tests/text/src/android/text/style/cts/DrawableMarginSpanTest.java
@@ -16,7 +16,7 @@
 
 package android.text.style.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.text.R;
 
 
 import android.graphics.Canvas;
diff --git a/tests/tests/text/src/android/text/style/cts/DynamicDrawableSpanTest.java b/tests/tests/text/src/android/text/style/cts/DynamicDrawableSpanTest.java
index 0cd072a..9723556 100644
--- a/tests/tests/text/src/android/text/style/cts/DynamicDrawableSpanTest.java
+++ b/tests/tests/text/src/android/text/style/cts/DynamicDrawableSpanTest.java
@@ -16,7 +16,7 @@
 
 package android.text.style.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.text.R;
 
 
 import android.graphics.Canvas;
diff --git a/tests/tests/text/src/android/text/style/cts/ImageSpanTest.java b/tests/tests/text/src/android/text/style/cts/ImageSpanTest.java
index 1499d62..6f056d0 100644
--- a/tests/tests/text/src/android/text/style/cts/ImageSpanTest.java
+++ b/tests/tests/text/src/android/text/style/cts/ImageSpanTest.java
@@ -16,10 +16,11 @@
 
 package android.text.style.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.text.R;
 
 
 import android.content.Context;
+import android.cts.util.WidgetTestUtils;
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
@@ -27,7 +28,6 @@
 import android.test.AndroidTestCase;
 import android.text.style.DynamicDrawableSpan;
 import android.text.style.ImageSpan;
-import android.widget.cts.WidgetTestUtils;
 
 public class ImageSpanTest extends AndroidTestCase {
     public void testConstructor() {
diff --git a/tests/tests/text/src/android/text/style/cts/MockURLSpanTestActivity.java b/tests/tests/text/src/android/text/style/cts/MockURLSpanTestActivity.java
new file mode 100644
index 0000000..dbd154b
--- /dev/null
+++ b/tests/tests/text/src/android/text/style/cts/MockURLSpanTestActivity.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2009 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.text.style.cts;
+
+import com.android.cts.text.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * A Mock application for {@link URLSpan} test.
+ */
+public class MockURLSpanTestActivity extends Activity {
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.urlspan_layout);
+    }
+}
diff --git a/tests/tests/text/src/android/text/style/cts/TtsSpanTest.java b/tests/tests/text/src/android/text/style/cts/TtsSpanTest.java
new file mode 100644
index 0000000..3c320f1
--- /dev/null
+++ b/tests/tests/text/src/android/text/style/cts/TtsSpanTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.text.style.cts;
+
+import android.os.Parcel;
+import android.os.PersistableBundle;
+import android.text.style.TtsSpan;
+import junit.framework.TestCase;
+
+public class TtsSpanTest extends TestCase {
+
+    PersistableBundle bundle;
+
+    protected void setUp() {
+        bundle = new PersistableBundle();
+        bundle.putString("argument.one", "value.one");
+        bundle.putString("argument.two", "value.two");
+        bundle.putLong("argument.three", 3);
+        bundle.putLong("argument.four", 4);
+    }
+
+    public void testGetArgs() {
+        TtsSpan t = new TtsSpan("test.type.one", bundle);
+        PersistableBundle args = t.getArgs();
+        assertEquals(4, args.size());
+        assertEquals("value.one", args.getString("argument.one"));
+        assertEquals("value.two", args.getString("argument.two"));
+        assertEquals(3, args.getLong("argument.three"));
+        assertEquals(4, args.getLong("argument.four"));
+    }
+
+    public void testGetType() {
+        TtsSpan t = new TtsSpan("test.type.two", bundle);
+        assertEquals("test.type.two", t.getType());
+    }
+
+    public void testDescribeContents() {
+        TtsSpan span = new TtsSpan("test.type.three", bundle);
+        span.describeContents();
+    }
+
+    public void testGetSpanTypeId() {
+        TtsSpan span = new TtsSpan("test.type.four", bundle);
+        span.getSpanTypeId();
+    }
+
+    public void testWriteAndReadParcel() {
+        Parcel p = Parcel.obtain();
+        try {
+            TtsSpan span = new TtsSpan("test.type.five", bundle);
+            span.writeToParcel(p, 0);
+            p.setDataPosition(0);
+
+            TtsSpan t = new TtsSpan(p);
+
+            assertEquals("test.type.five", t.getType());
+            PersistableBundle args = t.getArgs();
+            assertEquals(4, args.size());
+            assertEquals("value.one", args.getString("argument.one"));
+            assertEquals("value.two", args.getString("argument.two"));
+            assertEquals(3, args.getLong("argument.three"));
+            assertEquals(4, args.getLong("argument.four"));
+        } finally {
+            p.recycle();
+        }
+    }
+}
diff --git a/tests/tests/text/src/android/text/style/cts/URLSpanCtsActivity.java b/tests/tests/text/src/android/text/style/cts/URLSpanCtsActivity.java
new file mode 100644
index 0000000..8d885bc
--- /dev/null
+++ b/tests/tests/text/src/android/text/style/cts/URLSpanCtsActivity.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2008 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.text.style.cts;
+
+import com.android.cts.text.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * A minimal application for {@link URLSpan} test.
+ */
+public class URLSpanCtsActivity extends Activity {
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.urlspan_layout);
+    }
+}
diff --git a/tests/tests/text/src/android/text/style/cts/URLSpanTest.java b/tests/tests/text/src/android/text/style/cts/URLSpanTest.java
index 3209b66..7cfe56e 100644
--- a/tests/tests/text/src/android/text/style/cts/URLSpanTest.java
+++ b/tests/tests/text/src/android/text/style/cts/URLSpanTest.java
@@ -16,7 +16,7 @@
 
 package android.text.style.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.text.R;
 
 
 import android.app.Activity;
@@ -27,13 +27,13 @@
 import android.text.style.URLSpan;
 import android.widget.TextView;
 
-public class URLSpanTest extends ActivityInstrumentationTestCase2<URLSpanStubActivity> {
+public class URLSpanTest extends ActivityInstrumentationTestCase2<URLSpanCtsActivity> {
     // The scheme of TEST_URL must be "ctstest" to launch MockURLSpanTestActivity
     private static final String TEST_URL = "ctstest://urlSpan/test";
     private Activity mActivity;
 
     public URLSpanTest() {
-        super("com.android.cts.stub", URLSpanStubActivity.class);
+        super("com.android.cts.text", URLSpanCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/text/src/android/text/util/cts/LinkifyTest.java b/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
index 45111f2..e6b91eb 100644
--- a/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
+++ b/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
@@ -73,14 +73,26 @@
     }
 
     public void testAddLinks1() {
+        // Verify URLs including the ones that have new gTLDs, and the
+        // ones that look like gTLDs (and so are accepted by linkify)
+        // and the ones that should not be linkified due to non-compliant
+        // gTLDs
+        final String longGTLD =
+                "abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabc";
         SpannableString spannable = new SpannableString("name@gmail.com, "
-                + "www.google.com, http://www.google.com/language_tools?hl=en, ");
+                + "www.google.com, http://www.google.com/language_tools?hl=en, "
+                + "a.bc, "   // a URL with accepted gTLD so should be linkified
+                + "d.e, f.1, g.12, "  // not valid, so should not be linkified
+                + "h." + longGTLD + " "  // valid, should be linkified
+                + "j." + longGTLD + "a"); // not a valid URL (gtld too long), no linkify
 
         assertTrue(Linkify.addLinks(spannable, Linkify.WEB_URLS));
         URLSpan[] spans = spannable.getSpans(0, spannable.length(), URLSpan.class);
-        assertEquals(2, spans.length);
+        assertEquals(4, spans.length);
         assertEquals("http://www.google.com", spans[0].getURL());
         assertEquals("http://www.google.com/language_tools?hl=en", spans[1].getURL());
+        assertEquals("http://a.bc", spans[2].getURL());
+        assertEquals("http://h." + longGTLD, spans[3].getURL());
 
         assertTrue(Linkify.addLinks(spannable, Linkify.EMAIL_ADDRESSES));
         spans = spannable.getSpans(0, spannable.length(), URLSpan.class);
@@ -303,7 +315,7 @@
         String numbersInvalid = "123456789 not a phone number";
         String numbersUKLocal = "tel:(0812)1234560 (0812)1234561";
         String numbersUSLocal = "tel:(812)1234562 (812)123.4563 "
-                + " tel:(800)5551210 (800) 555-1211 555-1212";
+                + " tel:(800)5551210 (800)555-1211 555-1212";
         String numbersIntl = "tel:+4408121234564 +44-0812-123-4565"
                 + " tel:+18005551213 +1-800-555-1214";
         SpannableString spannable = new SpannableString(
diff --git a/tests/tests/textureview/Android.mk b/tests/tests/textureview/Android.mk
index 30cc4ff..f85a738 100644
--- a/tests/tests/textureview/Android.mk
+++ b/tests/tests/textureview/Android.mk
@@ -21,8 +21,6 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/textureview/AndroidManifest.xml b/tests/tests/textureview/AndroidManifest.xml
index 63cd233..9ec3f17 100644
--- a/tests/tests/textureview/AndroidManifest.xml
+++ b/tests/tests/textureview/AndroidManifest.xml
@@ -25,7 +25,10 @@
 
     <instrumentation
         android:targetPackage="com.android.cts.textureview"
-        android:name="android.test.InstrumentationCtsTestRunner" />
+        android:name="android.support.test.runner.AndroidJUnitRunner" >
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
     <application
         android:label="@string/app_name"
diff --git a/tests/tests/theme/Android.mk b/tests/tests/theme/Android.mk
index 5846426..134af7c 100644
--- a/tests/tests/theme/Android.mk
+++ b/tests/tests/theme/Android.mk
@@ -24,9 +24,6 @@
 # When built, explicitly put it in the data partition.
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-# All tests should include android.test.runner.
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/theme/AndroidManifest.xml b/tests/tests/theme/AndroidManifest.xml
index 0edc836..8232d2b 100644
--- a/tests/tests/theme/AndroidManifest.xml
+++ b/tests/tests/theme/AndroidManifest.xml
@@ -19,12 +19,15 @@
 
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
     <application>
-        <uses-library android:name="android.test.runner" />        
-        <activity android:name="android.theme.cts.DeviceDefaultActivity" />        
+        <uses-library android:name="android.test.runner" />
+        <activity android:name="android.theme.cts.DeviceDefaultActivity" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
             android:targetPackage="com.android.cts.theme"
-            android:label="CTS tests for themes"/>
+            android:label="CTS tests for themes">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 </manifest>
 
diff --git a/tests/tests/tv/Android.mk b/tests/tests/tv/Android.mk
new file mode 100644
index 0000000..795b473
--- /dev/null
+++ b/tests/tests/tv/Android.mk
@@ -0,0 +1,33 @@
+# 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsTvTestCases
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/tv/AndroidManifest.xml b/tests/tests/tv/AndroidManifest.xml
new file mode 100644
index 0000000..dc5d30a
--- /dev/null
+++ b/tests/tests/tv/AndroidManifest.xml
@@ -0,0 +1,98 @@
+<?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="com.android.cts.tv">
+
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+
+    <uses-permission android:name="com.android.providers.tv.permission.READ_EPG_DATA" />
+    <uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+
+        <activity android:name="android.media.tv.cts.TvInputSetupActivityStub">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.media.tv.cts.TvInputSettingsActivityStub">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+            </intent-filter>
+        </activity>
+
+        <service android:name="android.media.tv.cts.StubTunerTvInputService"
+                 android:permission="android.permission.BIND_TV_INPUT"
+                 android:label="TV input stub"
+                 android:icon="@drawable/robot"
+                 android:process=":tunerTvInputStub">
+            <intent-filter>
+                <action android:name="android.media.tv.TvInputService" />
+            </intent-filter>
+            <meta-data android:name="android.media.tv.input"
+                       android:resource="@xml/stub_tv_input_service" />
+        </service>
+
+        <service android:name="android.media.tv.cts.NoMetadataTvInputService"
+                 android:permission="android.permission.BIND_TV_INPUT">
+            <intent-filter>
+                <action android:name="android.media.tv.TvInputService" />
+            </intent-filter>
+        </service>
+
+        <service android:name="android.media.tv.cts.NoPermissionTvInputService">
+            <intent-filter>
+                <action android:name="android.media.tv.TvInputService" />
+            </intent-filter>
+            <meta-data android:name="android.media.tv.input"
+                       android:resource="@xml/stub_tv_input_service" />
+        </service>
+
+        <service android:name="android.media.tv.cts.TvInputServiceTest$CountingTvInputService"
+                 android:permission="android.permission.BIND_TV_INPUT">
+            <intent-filter>
+                <action android:name="android.media.tv.TvInputService" />
+            </intent-filter>
+            <meta-data android:name="android.media.tv.input"
+                       android:resource="@xml/stub_tv_input_service" />
+        </service>
+
+        <activity android:name="android.media.tv.cts.TvViewStubActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+        <activity android:name="android.tv.settings.cts.SettingsLeanbackStubActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+            android:targetPackage="com.android.cts.tv"
+            android:label="Tests for the TV APIs.">
+        <meta-data android:name="listener"
+                android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
+</manifest>
diff --git a/tests/res/drawable/robot.png b/tests/tests/tv/res/drawable/robot.png
similarity index 100%
copy from tests/res/drawable/robot.png
copy to tests/tests/tv/res/drawable/robot.png
Binary files differ
diff --git a/tests/tests/tv/res/layout/tvview_layout.xml b/tests/tests/tv/res/layout/tvview_layout.xml
new file mode 100644
index 0000000..a15d8ff
--- /dev/null
+++ b/tests/tests/tv/res/layout/tvview_layout.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <android.media.tv.TvView
+        android:id="@+id/tvview"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+</LinearLayout>
diff --git a/tests/tests/tv/res/xml/stub_tv_input_service.xml b/tests/tests/tv/res/xml/stub_tv_input_service.xml
new file mode 100644
index 0000000..8ad10cc
--- /dev/null
+++ b/tests/tests/tv/res/xml/stub_tv_input_service.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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.
+-->
+
+<tv-input xmlns:android="http://schemas.android.com/apk/res/android"
+    android:setupActivity="android.media.tv.cts.TvInputSetupActivityStub"
+    android:settingsActivity="android.media.tv.cts.TvInputSettingsActivityStub" />
diff --git a/tests/tests/tv/src/android/media/tv/cts/BundledTvInputServiceTest.java b/tests/tests/tv/src/android/media/tv/cts/BundledTvInputServiceTest.java
new file mode 100644
index 0000000..f5cc2e1
--- /dev/null
+++ b/tests/tests/tv/src/android/media/tv/cts/BundledTvInputServiceTest.java
@@ -0,0 +1,186 @@
+/*
+ * 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.media.tv.cts;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.Context;
+import android.cts.util.PollingCheck;
+import android.media.tv.TvContract;
+import android.media.tv.TvInputInfo;
+import android.media.tv.TvInputManager;
+import android.media.tv.TvView;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.ArrayMap;
+
+import com.android.cts.tv.R;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+/**
+ * Test {@link android.media.tv.TvView}.
+ */
+public class BundledTvInputServiceTest
+        extends ActivityInstrumentationTestCase2<TvViewStubActivity> {
+    /** The maximum time to wait for an operation. */
+    private static final long TIME_OUT = 15000L;
+
+    private TvView mTvView;
+    private Activity mActivity;
+    private Instrumentation mInstrumentation;
+    private TvInputManager mManager;
+    private final List<TvInputInfo> mPassthroughInputList = new ArrayList<>();
+    private final MockCallback mCallback = new MockCallback();
+
+    private static class MockCallback extends TvView.TvInputCallback {
+        private final Map<String, Integer> mVideoUnavailableReasonMap = new ArrayMap<>();
+        private final Object mLock = new Object();
+        private final int VIDEO_AVAILABLE = -1;
+
+        public Integer getVideoUnavailableReason(String inputId) {
+            return mVideoUnavailableReasonMap.get(inputId);
+        }
+
+        @Override
+        public void onVideoAvailable(String inputId) {
+            synchronized (mLock) {
+                mVideoUnavailableReasonMap.put(inputId, VIDEO_AVAILABLE);
+            }
+        }
+
+        @Override
+        public void onVideoUnavailable(String inputId, int reason) {
+            synchronized (mLock) {
+                mVideoUnavailableReasonMap.put(inputId, reason);
+            }
+        }
+    }
+
+    /**
+     * Instantiates a new TV view test.
+     */
+    public BundledTvInputServiceTest() {
+        super(TvViewStubActivity.class);
+    }
+
+    /**
+     * Find the TV view specified by id.
+     *
+     * @param id the id
+     * @return the TV view
+     */
+    private TvView findTvViewById(int id) {
+        return (TvView) mActivity.findViewById(id);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+        if (!Utils.hasTvInputFramework(mActivity)) {
+            return;
+        }
+        mInstrumentation = getInstrumentation();
+        mTvView = findTvViewById(R.id.tvview);
+        mManager = (TvInputManager) mActivity.getSystemService(Context.TV_INPUT_SERVICE);
+        for (TvInputInfo info : mManager.getTvInputList()) {
+            if (info.isPassthroughInput()) {
+                mPassthroughInputList.add(info);
+            }
+        }
+        mTvView.setCallback(mCallback);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (!Utils.hasTvInputFramework(getActivity())) {
+            super.tearDown();
+            return;
+        }
+        try {
+            runTestOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    mTvView.reset();
+                }
+            });
+        } catch (Throwable t) {
+            throw new RuntimeException(t);
+        }
+        mInstrumentation.waitForIdleSync();
+        super.tearDown();
+    }
+
+    public void testTune() throws Throwable {
+        if (!Utils.hasTvInputFramework(getActivity())) {
+            return;
+        }
+        for (final TvInputInfo info : mPassthroughInputList) {
+            runTestOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    mTvView.tune(info.getId(),
+                            TvContract.buildChannelUriForPassthroughInput(info.getId()));
+                }
+            });
+            mInstrumentation.waitForIdleSync();
+            new PollingCheck(TIME_OUT) {
+                @Override
+                protected boolean check() {
+                    Integer reason = mCallback.getVideoUnavailableReason(info.getId());
+                    return reason != null
+                            && reason != TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING
+                            && reason != TvInputManager.VIDEO_UNAVAILABLE_REASON_BUFFERING;
+                }
+            }.run();
+        }
+    }
+
+    public void testTuneStress() throws Throwable {
+        if (!Utils.hasTvInputFramework(getActivity())) {
+            return;
+        }
+        final int STRESS_FACTOR = 100;
+        Random random = new Random();
+        for (int i = 0; i < mPassthroughInputList.size() * STRESS_FACTOR; ++i) {
+            final TvInputInfo info =
+                    mPassthroughInputList.get(random.nextInt(mPassthroughInputList.size()));
+            runTestOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    mTvView.tune(info.getId(),
+                            TvContract.buildChannelUriForPassthroughInput(info.getId()));
+                }
+            });
+            mInstrumentation.waitForIdleSync();
+            if (random.nextBoolean()) {
+                new PollingCheck(TIME_OUT) {
+                    @Override
+                    protected boolean check() {
+                        Integer reason = mCallback.getVideoUnavailableReason(info.getId());
+                        return reason != null
+                                && reason != TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING
+                                && reason != TvInputManager.VIDEO_UNAVAILABLE_REASON_BUFFERING;
+                    }
+                }.run();
+            }
+        }
+    }
+}
diff --git a/tests/tests/tv/src/android/media/tv/cts/NoMetadataTvInputService.java b/tests/tests/tv/src/android/media/tv/cts/NoMetadataTvInputService.java
new file mode 100644
index 0000000..2c5b6e0
--- /dev/null
+++ b/tests/tests/tv/src/android/media/tv/cts/NoMetadataTvInputService.java
@@ -0,0 +1,20 @@
+/*
+ * 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.media.tv.cts;
+
+public class NoMetadataTvInputService extends StubTvInputService {
+}
diff --git a/tests/tests/tv/src/android/media/tv/cts/NoPermissionTvInputService.java b/tests/tests/tv/src/android/media/tv/cts/NoPermissionTvInputService.java
new file mode 100644
index 0000000..1909e4b
--- /dev/null
+++ b/tests/tests/tv/src/android/media/tv/cts/NoPermissionTvInputService.java
@@ -0,0 +1,20 @@
+/*
+ * 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.media.tv.cts;
+
+public class NoPermissionTvInputService extends StubTvInputService {
+}
diff --git a/tests/tests/tv/src/android/media/tv/cts/StubTunerTvInputService.java b/tests/tests/tv/src/android/media/tv/cts/StubTunerTvInputService.java
new file mode 100644
index 0000000..c2c9a1b
--- /dev/null
+++ b/tests/tests/tv/src/android/media/tv/cts/StubTunerTvInputService.java
@@ -0,0 +1,174 @@
+/*
+ * 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.media.tv.cts;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.media.tv.TvContract;
+import android.media.tv.TvInputInfo;
+import android.media.tv.TvInputManager;
+import android.media.tv.TvInputService;
+import android.media.tv.TvTrackInfo;
+import android.net.Uri;
+import android.view.Surface;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class StubTunerTvInputService extends TvInputService {
+    private static final List<TvTrackInfo> mTrackList = new ArrayList<>();
+
+    public static void clearTracks() {
+        mTrackList.clear();
+    }
+
+    public static void injectTrack(TvTrackInfo... tracks) {
+        mTrackList.addAll(Arrays.asList(tracks));
+    }
+
+    public static void insertChannels(ContentResolver resolver, TvInputInfo info) {
+        if (!info.getServiceInfo().name.equals(StubTunerTvInputService.class.getName())) {
+            throw new IllegalArgumentException("info mismatch");
+        }
+        ContentValues redValues = new ContentValues();
+        redValues.put(TvContract.Channels.COLUMN_INPUT_ID, info.getId());
+        redValues.put(TvContract.Channels.COLUMN_DISPLAY_NUMBER, "0");
+        redValues.put(TvContract.Channels.COLUMN_DISPLAY_NAME, "Red");
+        redValues.put(TvContract.Channels.COLUMN_INTERNAL_PROVIDER_DATA, new byte[] { 0 });
+        ContentValues greenValues = new ContentValues();
+        greenValues.put(TvContract.Channels.COLUMN_INPUT_ID, info.getId());
+        greenValues.put(TvContract.Channels.COLUMN_DISPLAY_NUMBER, "1");
+        greenValues.put(TvContract.Channels.COLUMN_DISPLAY_NAME, "Green");
+        greenValues.put(TvContract.Channels.COLUMN_INTERNAL_PROVIDER_DATA, new byte[] { 1 });
+        ContentValues blueValues = new ContentValues();
+        blueValues.put(TvContract.Channels.COLUMN_INPUT_ID, info.getId());
+        blueValues.put(TvContract.Channels.COLUMN_DISPLAY_NUMBER, "2");
+        blueValues.put(TvContract.Channels.COLUMN_DISPLAY_NAME, "Blue");
+        blueValues.put(TvContract.Channels.COLUMN_INTERNAL_PROVIDER_DATA, new byte[] { 2 });
+        resolver.bulkInsert(TvContract.Channels.CONTENT_URI,
+                new ContentValues[] { redValues, greenValues, blueValues });
+    }
+
+    public static void deleteChannels(ContentResolver resolver, TvInputInfo info) {
+        if (!info.getServiceInfo().name.equals(StubTunerTvInputService.class.getName())) {
+            throw new IllegalArgumentException("info mismatch");
+        }
+        resolver.delete(TvContract.buildChannelsUriForInput(info.getId()), null, null);
+    }
+
+    @Override
+    public Session onCreateSession(String inputId) {
+        return new StubSessionImpl(this);
+    }
+
+    static class StubSessionImpl extends Session {
+        private static final int[] COLORS = { Color.RED, Color.GREEN, Color.BLUE };
+        private Surface mSurface;
+        private Object mLock = new Object();
+        private int mCurrentIndex = -1;
+        private Context mContext;
+
+        StubSessionImpl(Context context) {
+            super(context);
+            mContext = context;
+        }
+
+        @Override
+        public void onRelease() {
+        }
+
+        private void updateSurfaceLocked() {
+            if (mCurrentIndex >= 0 && mSurface != null) {
+                try {
+                    Canvas c = mSurface.lockCanvas(null);
+                    c.drawColor(COLORS[mCurrentIndex]);
+                    mSurface.unlockCanvasAndPost(c);
+                } catch (IllegalArgumentException e) {
+                    mSurface = null;
+                }
+            }
+        }
+
+        @Override
+        public boolean onSetSurface(Surface surface) {
+            synchronized (mLock) {
+                mSurface = surface;
+                updateSurfaceLocked();
+                return true;
+            }
+        }
+
+        @Override
+        public void onSetStreamVolume(float volume) {
+        }
+
+        @Override
+        public boolean onTune(Uri channelUri) {
+            notifyVideoUnavailable(TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING);
+            synchronized (mLock) {
+                String[] projection = { TvContract.Channels.COLUMN_INTERNAL_PROVIDER_DATA };
+                Cursor cursor = mContext.getContentResolver().query(
+                        channelUri, projection, null, null, null);
+                try {
+                    if (cursor != null && cursor.moveToNext()) {
+                        mCurrentIndex = cursor.getBlob(0)[0];
+                    } else {
+                        mCurrentIndex = -1;
+                    }
+                } finally {
+                    if (cursor != null) {
+                        cursor.close();
+                    }
+                }
+                updateSurfaceLocked();
+                // Notify tracks
+                if (mCurrentIndex == 0) {
+                    notifyTracksChanged(mTrackList);
+                    for (TvTrackInfo track : mTrackList) {
+                        if (track.getType() == TvTrackInfo.TYPE_VIDEO) {
+                            notifyTrackSelected(TvTrackInfo.TYPE_VIDEO, track.getId());
+                            break;
+                        }
+                    }
+                    for (TvTrackInfo track : mTrackList) {
+                        if (track.getType() == TvTrackInfo.TYPE_AUDIO) {
+                            notifyTrackSelected(TvTrackInfo.TYPE_AUDIO, track.getId());
+                            break;
+                        }
+                    }
+                }
+            }
+            notifyVideoAvailable();
+            return true;
+        }
+
+        @Override
+        public boolean onSelectTrack(int type, String trackId) {
+            notifyTrackSelected(type, trackId);
+            return true;
+        }
+
+        @Override
+        public void onSetCaptionEnabled(boolean enabled) {
+        }
+    }
+}
diff --git a/tests/tests/tv/src/android/media/tv/cts/StubTvInputService.java b/tests/tests/tv/src/android/media/tv/cts/StubTvInputService.java
new file mode 100644
index 0000000..b70dc62
--- /dev/null
+++ b/tests/tests/tv/src/android/media/tv/cts/StubTvInputService.java
@@ -0,0 +1,60 @@
+/*
+ * 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.media.tv.cts;
+
+import android.content.Context;
+import android.media.tv.TvInputService;
+import android.net.Uri;
+import android.view.Surface;
+
+/**
+ * Stub implementation of (@link android.media.tv.TvInputService}.
+ */
+public class StubTvInputService extends TvInputService {
+    @Override
+    public Session onCreateSession(String inputId) {
+        return new StubSessionImpl(this);
+    }
+
+    private static class StubSessionImpl extends Session {
+        StubSessionImpl(Context context) {
+            super(context);
+        }
+
+        @Override
+        public void onRelease() {
+        }
+
+        @Override
+        public boolean onSetSurface(Surface surface) {
+            return false;
+        }
+
+        @Override
+        public void onSetStreamVolume(float volume) {
+        }
+
+        @Override
+        public boolean onTune(Uri channelUri) {
+            return false;
+        }
+
+        @Override
+        public void onSetCaptionEnabled(boolean enabled) {
+        }
+    }
+}
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvContentRatingTest.java b/tests/tests/tv/src/android/media/tv/cts/TvContentRatingTest.java
new file mode 100644
index 0000000..5e6478b
--- /dev/null
+++ b/tests/tests/tv/src/android/media/tv/cts/TvContentRatingTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.media.tv.cts;
+
+import android.media.tv.TvContentRating;
+
+import java.util.List;
+
+import junit.framework.TestCase;
+
+/**
+ * Test for {@link android.media.tv.TvContentRating}.
+ */
+public class TvContentRatingTest extends TestCase {
+
+    public void testCreateRating() throws Exception {
+        final String DOMAIN = "android.media.tv";
+        final String RATING_SYSTEM = "US_TVPG";
+        final String MAIN_RATING = "US_TVPG_TV_MA";
+        final String SUB_RATING_1 = "US_TVPG_TV_S";
+        final String SUB_RATING_2 = "US_TVPG_TV_V";
+
+        TvContentRating rating = TvContentRating.createRating(DOMAIN, RATING_SYSTEM, MAIN_RATING,
+                SUB_RATING_1, SUB_RATING_2);
+        assertEquals(DOMAIN, rating.getDomain());
+        assertEquals(RATING_SYSTEM, rating.getRatingSystem());
+        assertEquals(MAIN_RATING, rating.getMainRating());
+        List<String> subRatings = rating.getSubRatings();
+        assertEquals(2, subRatings.size());
+        assertTrue("Sub-ratings does not contain " + SUB_RATING_1,
+                subRatings.contains(SUB_RATING_1));
+        assertTrue("Sub-ratings does not contain " + SUB_RATING_2,
+                subRatings.contains(SUB_RATING_2));
+    }
+
+    public void testFlattenAndUnflatten() throws Exception {
+        final String DOMAIN = "android.media.tv";
+        final String RATING_SYSTEM = "US_TVPG";
+        final String MAIN_RATING = "US_TVPG_TV_MA";
+        final String SUB_RATING_1 = "US_TVPG_TV_S";
+        final String SUB_RATING_2 = "US_TVPG_TV_V";
+
+        String flattened = TvContentRating.createRating(DOMAIN, RATING_SYSTEM, MAIN_RATING,
+                SUB_RATING_1, SUB_RATING_2).flattenToString();
+        TvContentRating rating = TvContentRating.unflattenFromString(flattened);
+
+        assertEquals(DOMAIN, rating.getDomain());
+        assertEquals(RATING_SYSTEM, rating.getRatingSystem());
+        assertEquals(MAIN_RATING, rating.getMainRating());
+        List<String> subRatings = rating.getSubRatings();
+        assertEquals(2, subRatings.size());
+        assertTrue("Sub-ratings does not contain " + SUB_RATING_1,
+                subRatings.contains(SUB_RATING_1));
+        assertTrue("Sub-ratings does not contain " + SUB_RATING_2,
+                subRatings.contains(SUB_RATING_2));
+    }
+}
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java b/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java
new file mode 100644
index 0000000..651a199
--- /dev/null
+++ b/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java
@@ -0,0 +1,398 @@
+/*
+ * 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.media.tv.cts;
+
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.res.AssetFileDescriptor;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.media.tv.TvContentRating;
+import android.media.tv.TvContract;
+import android.net.Uri;
+import android.test.AndroidTestCase;
+
+import com.android.cts.tv.R;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Test for {@link android.media.tv.TvContract}.
+ */
+public class TvContractTest extends AndroidTestCase {
+    private static final String[] CHANNELS_PROJECTION = {
+        TvContract.Channels._ID,
+        TvContract.Channels.COLUMN_INPUT_ID,
+        TvContract.Channels.COLUMN_TYPE,
+        TvContract.Channels.COLUMN_SERVICE_TYPE,
+        TvContract.Channels.COLUMN_ORIGINAL_NETWORK_ID,
+        TvContract.Channels.COLUMN_TRANSPORT_STREAM_ID,
+        TvContract.Channels.COLUMN_SERVICE_ID,
+        TvContract.Channels.COLUMN_DISPLAY_NUMBER,
+        TvContract.Channels.COLUMN_DISPLAY_NAME,
+        TvContract.Channels.COLUMN_NETWORK_AFFILIATION,
+        TvContract.Channels.COLUMN_DESCRIPTION,
+        TvContract.Channels.COLUMN_VIDEO_FORMAT,
+        TvContract.Channels.COLUMN_INTERNAL_PROVIDER_DATA,
+        TvContract.Channels.COLUMN_VERSION_NUMBER,
+    };
+
+    private static final String[] PROGRAMS_PROJECTION = {
+        TvContract.Programs._ID,
+        TvContract.Programs.COLUMN_CHANNEL_ID,
+        TvContract.Programs.COLUMN_TITLE,
+        TvContract.Programs.COLUMN_SEASON_NUMBER,
+        TvContract.Programs.COLUMN_EPISODE_NUMBER,
+        TvContract.Programs.COLUMN_EPISODE_TITLE,
+        TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS,
+        TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS,
+        TvContract.Programs.COLUMN_BROADCAST_GENRE,
+        TvContract.Programs.COLUMN_CANONICAL_GENRE,
+        TvContract.Programs.COLUMN_SHORT_DESCRIPTION,
+        TvContract.Programs.COLUMN_LONG_DESCRIPTION,
+        TvContract.Programs.COLUMN_VIDEO_WIDTH,
+        TvContract.Programs.COLUMN_VIDEO_HEIGHT,
+        TvContract.Programs.COLUMN_AUDIO_LANGUAGE,
+        TvContract.Programs.COLUMN_CONTENT_RATING,
+        TvContract.Programs.COLUMN_POSTER_ART_URI,
+        TvContract.Programs.COLUMN_THUMBNAIL_URI,
+        TvContract.Programs.COLUMN_INTERNAL_PROVIDER_DATA,
+        TvContract.Programs.COLUMN_VERSION_NUMBER,
+    };
+
+    private static long OPERATION_TIME = 1000l;
+
+    private String mInputId;
+    private ContentResolver mContentResolver;
+    private Uri mChannelsUri;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        if (!Utils.hasTvInputFramework(getContext())) {
+            return;
+        }
+        mInputId = TvContract.buildInputId(
+                new ComponentName(getContext(), StubTunerTvInputService.class));
+        mContentResolver = getContext().getContentResolver();
+        mChannelsUri = TvContract.buildChannelsUriForInput(mInputId);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (!Utils.hasTvInputFramework(getContext())) {
+            super.tearDown();
+            return;
+        }
+        // Clean up, just in case we failed to delete the entry when a test failed.
+        // The cotentUris are specific to this package, so this will delete only the
+        // entries inserted by this package.
+        String[] projection = { TvContract.Channels._ID };
+        try (Cursor cursor = mContentResolver.query(mChannelsUri, projection, null, null, null)) {
+            while (cursor != null && cursor.moveToNext()) {
+                long channelId = cursor.getLong(0);
+                mContentResolver.delete(
+                        TvContract.buildProgramsUriForChannel(channelId), null, null);
+            }
+        }
+        mContentResolver.delete(mChannelsUri, null, null);
+        super.tearDown();
+    }
+
+    private static ContentValues createDummyChannelValues(String inputId) {
+        ContentValues values = new ContentValues();
+        values.put(TvContract.Channels.COLUMN_INPUT_ID, inputId);
+        values.put(TvContract.Channels.COLUMN_TYPE, TvContract.Channels.TYPE_OTHER);
+        values.put(TvContract.Channels.COLUMN_SERVICE_TYPE,
+                TvContract.Channels.SERVICE_TYPE_AUDIO_VIDEO);
+        values.put(TvContract.Channels.COLUMN_DISPLAY_NUMBER, "1");
+        values.put(TvContract.Channels.COLUMN_VIDEO_FORMAT, TvContract.Channels.VIDEO_FORMAT_480P);
+
+        return values;
+    }
+
+    private static ContentValues createDummyProgramValues(long channelId) {
+        ContentValues values = new ContentValues();
+        values.put(TvContract.Programs.COLUMN_CHANNEL_ID, channelId);
+        values.put(TvContract.Programs.COLUMN_EPISODE_TITLE, "Title");
+        values.put(TvContract.Programs.COLUMN_CANONICAL_GENRE, TvContract.Programs.Genres.encode(
+                TvContract.Programs.Genres.MOVIES, TvContract.Programs.Genres.DRAMA));
+        TvContentRating rating = TvContentRating.createRating("android.media.tv", "US_TVPG",
+                "US_TVPG_TV_MA", "US_TVPG_S", "US_TVPG_V");
+        values.put(TvContract.Programs.COLUMN_CONTENT_RATING, rating.flattenToString());
+
+        return values;
+    }
+
+    private static void verifyStringColumn(Cursor cursor, ContentValues expectedValues,
+            String columnName) {
+        if (expectedValues.containsKey(columnName)) {
+            assertEquals(expectedValues.getAsString(columnName),
+                    cursor.getString(cursor.getColumnIndex(columnName)));
+        }
+    }
+
+    private static void verifyIntegerColumn(Cursor cursor, ContentValues expectedValues,
+            String columnName) {
+        if (expectedValues.containsKey(columnName)) {
+            assertEquals(expectedValues.getAsInteger(columnName).intValue(),
+                    cursor.getInt(cursor.getColumnIndex(columnName)));
+        }
+    }
+
+    private static void verifyLongColumn(Cursor cursor, ContentValues expectedValues,
+            String columnName) {
+        if (expectedValues.containsKey(columnName)) {
+            assertEquals(expectedValues.getAsLong(columnName).longValue(),
+                    cursor.getLong(cursor.getColumnIndex(columnName)));
+        }
+    }
+
+    private static void verifyBlobColumn(Cursor cursor, ContentValues expectedValues,
+            String columnName) {
+        if (expectedValues.containsKey(columnName)) {
+            byte[] expected = expectedValues.getAsByteArray(columnName);
+            byte[] actual = cursor.getBlob(cursor.getColumnIndex(columnName));
+            assertEquals(expected.length, actual.length);
+            for (int i = 0; i < expected.length; ++i) {
+                assertEquals(expected[i], actual[i]);
+            }
+        }
+    }
+
+    private void verifyChannel(Uri channelUri, ContentValues expectedValues, long channelId) {
+        try (Cursor cursor = mContentResolver.query(
+                channelUri, CHANNELS_PROJECTION, null, null, null)) {
+            assertNotNull(cursor);
+            assertEquals(cursor.getCount(), 1);
+            assertTrue(cursor.moveToNext());
+            assertEquals(channelId, cursor.getLong(cursor.getColumnIndex(TvContract.Channels._ID)));
+            verifyStringColumn(cursor, expectedValues, TvContract.Channels.COLUMN_INPUT_ID);
+            verifyStringColumn(cursor, expectedValues, TvContract.Channels.COLUMN_TYPE);
+            verifyStringColumn(cursor, expectedValues, TvContract.Channels.COLUMN_SERVICE_TYPE);
+            verifyIntegerColumn(cursor, expectedValues,
+                    TvContract.Channels.COLUMN_ORIGINAL_NETWORK_ID);
+            verifyIntegerColumn(cursor, expectedValues,
+                    TvContract.Channels.COLUMN_TRANSPORT_STREAM_ID);
+            verifyIntegerColumn(cursor, expectedValues,
+                    TvContract.Channels.COLUMN_SERVICE_ID);
+            verifyStringColumn(cursor, expectedValues, TvContract.Channels.COLUMN_DISPLAY_NUMBER);
+            verifyStringColumn(cursor, expectedValues, TvContract.Channels.COLUMN_DISPLAY_NAME);
+            verifyStringColumn(cursor, expectedValues,
+                    TvContract.Channels.COLUMN_NETWORK_AFFILIATION);
+            verifyStringColumn(cursor, expectedValues, TvContract.Channels.COLUMN_DESCRIPTION);
+            verifyStringColumn(cursor, expectedValues, TvContract.Channels.COLUMN_VIDEO_FORMAT);
+            verifyBlobColumn(cursor, expectedValues,
+                    TvContract.Channels.COLUMN_INTERNAL_PROVIDER_DATA);
+            verifyIntegerColumn(cursor, expectedValues, TvContract.Channels.COLUMN_VERSION_NUMBER);
+        }
+    }
+
+    public void testChannelsTable() throws Exception {
+        if (!Utils.hasTvInputFramework(getContext())) {
+            return;
+        }
+        // Test: insert
+        ContentValues values = createDummyChannelValues(mInputId);
+
+        Uri rowUri = mContentResolver.insert(mChannelsUri, values);
+        long channelId = ContentUris.parseId(rowUri);
+        Uri channelUri = TvContract.buildChannelUri(channelId);
+        verifyChannel(channelUri, values, channelId);
+
+        // Test: update
+        values.put(TvContract.Channels.COLUMN_DISPLAY_NUMBER, "1-1");
+        values.put(TvContract.Channels.COLUMN_DISPLAY_NAME, "One dash one");
+        values.put(TvContract.Channels.COLUMN_INTERNAL_PROVIDER_DATA, "Coffee".getBytes());
+
+        mContentResolver.update(channelUri, values, null, null);
+        verifyChannel(channelUri, values, channelId);
+
+        // Test: delete
+        mContentResolver.delete(mChannelsUri, null, null);
+        try (Cursor cursor = mContentResolver.query(
+                mChannelsUri, CHANNELS_PROJECTION, null, null, null)) {
+            assertEquals(0, cursor.getCount());
+        }
+    }
+
+    private void verifyProgram(Uri programUri, ContentValues expectedValues, long programId) {
+        try (Cursor cursor = mContentResolver.query(
+                programUri, PROGRAMS_PROJECTION, null, null, null)) {
+            assertNotNull(cursor);
+            assertEquals(cursor.getCount(), 1);
+            assertTrue(cursor.moveToNext());
+            assertEquals(programId, cursor.getLong(cursor.getColumnIndex(TvContract.Programs._ID)));
+            verifyLongColumn(cursor, expectedValues, TvContract.Programs.COLUMN_CHANNEL_ID);
+            verifyStringColumn(cursor, expectedValues, TvContract.Programs.COLUMN_TITLE);
+            verifyIntegerColumn(cursor, expectedValues, TvContract.Programs.COLUMN_SEASON_NUMBER);
+            verifyIntegerColumn(cursor, expectedValues, TvContract.Programs.COLUMN_EPISODE_NUMBER);
+            verifyStringColumn(cursor, expectedValues, TvContract.Programs.COLUMN_EPISODE_TITLE);
+            verifyLongColumn(cursor, expectedValues,
+                    TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS);
+            verifyLongColumn(cursor, expectedValues,
+                    TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS);
+            verifyStringColumn(cursor, expectedValues, TvContract.Programs.COLUMN_BROADCAST_GENRE);
+            verifyStringColumn(cursor, expectedValues, TvContract.Programs.COLUMN_CANONICAL_GENRE);
+            verifyStringColumn(cursor, expectedValues,
+                    TvContract.Programs.COLUMN_SHORT_DESCRIPTION);
+            verifyStringColumn(cursor, expectedValues, TvContract.Programs.COLUMN_LONG_DESCRIPTION);
+            verifyIntegerColumn(cursor, expectedValues, TvContract.Programs.COLUMN_VIDEO_WIDTH);
+            verifyIntegerColumn(cursor, expectedValues, TvContract.Programs.COLUMN_VIDEO_HEIGHT);
+            verifyStringColumn(cursor, expectedValues, TvContract.Programs.COLUMN_AUDIO_LANGUAGE);
+            verifyStringColumn(cursor, expectedValues, TvContract.Programs.COLUMN_CONTENT_RATING);
+            verifyStringColumn(cursor, expectedValues, TvContract.Programs.COLUMN_POSTER_ART_URI);
+            verifyStringColumn(cursor, expectedValues, TvContract.Programs.COLUMN_THUMBNAIL_URI);
+            verifyBlobColumn(cursor, expectedValues,
+                    TvContract.Programs.COLUMN_INTERNAL_PROVIDER_DATA);
+            verifyIntegerColumn(cursor, expectedValues, TvContract.Programs.COLUMN_VERSION_NUMBER);
+        }
+    }
+
+    private void verifyLogoIsReadable(Uri logoUri) throws Exception {
+        try (AssetFileDescriptor fd = mContentResolver.openAssetFileDescriptor(logoUri, "r")) {
+            try (InputStream is = fd.createInputStream()) {
+                // Assure that the stream is decodable as a Bitmap.
+                BitmapFactory.decodeStream(is);
+            }
+        }
+    }
+
+    public void testChannelLogo() throws Exception {
+        if (!Utils.hasTvInputFramework(getContext())) {
+            return;
+        }
+        // Set-up: add a channel.
+        ContentValues values = createDummyChannelValues(mInputId);
+        Uri channelUri = mContentResolver.insert(mChannelsUri, values);
+        Uri logoUri = TvContract.buildChannelLogoUri(channelUri);
+        Bitmap logo = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.robot);
+
+        // Write
+        try (AssetFileDescriptor fd = mContentResolver.openAssetFileDescriptor(logoUri, "w")) {
+            try (OutputStream os = fd.createOutputStream()) {
+                logo.compress(Bitmap.CompressFormat.PNG, 100, os);
+            }
+        }
+
+        // Give some time for TvProvider to process the logo.
+        Thread.sleep(OPERATION_TIME);
+
+        // Read and verify
+        verifyLogoIsReadable(logoUri);
+
+        // Read and verify using alternative logo URI.
+        verifyLogoIsReadable(TvContract.buildChannelLogoUri(ContentUris.parseId(channelUri)));
+    }
+
+    public void verifyProgramsTable(Uri programsUri, long channelId) {
+        if (!Utils.hasTvInputFramework(getContext())) {
+            return;
+        }
+        // Test: insert
+        ContentValues values = createDummyProgramValues(channelId);
+
+        Uri rowUri = mContentResolver.insert(programsUri, values);
+        long programId = ContentUris.parseId(rowUri);
+        Uri programUri = TvContract.buildProgramUri(programId);
+        verifyProgram(programUri, values, programId);
+
+        // Test: update
+        values.put(TvContract.Programs.COLUMN_EPISODE_TITLE, "Sample title");
+        values.put(TvContract.Programs.COLUMN_SHORT_DESCRIPTION, "Short description");
+        values.put(TvContract.Programs.COLUMN_INTERNAL_PROVIDER_DATA, "Coffee".getBytes());
+
+        mContentResolver.update(programUri, values, null, null);
+        verifyProgram(programUri, values, programId);
+
+        // Test: delete
+        mContentResolver.delete(programsUri, null, null);
+        try (Cursor cursor = mContentResolver.query(
+                programsUri, PROGRAMS_PROJECTION, null, null, null)) {
+            assertEquals(0, cursor.getCount());
+        }
+    }
+
+    public void testProgramsTable() throws Exception {
+        if (!Utils.hasTvInputFramework(getContext())) {
+            return;
+        }
+        // Set-up: add a channel.
+        ContentValues values = createDummyChannelValues(mInputId);
+        Uri channelUri = mContentResolver.insert(mChannelsUri, values);
+        long channelId = ContentUris.parseId(channelUri);
+
+        verifyProgramsTable(TvContract.buildProgramsUriForChannel(channelId), channelId);
+        verifyProgramsTable(TvContract.buildProgramsUriForChannel(channelUri), channelId);
+    }
+
+    private void verifyOverlap(long startMillis, long endMillis, int expectedCount,
+            long channelId, Uri channelUri) {
+        try (Cursor cursor = mContentResolver.query(TvContract.buildProgramsUriForChannel(
+                channelId, startMillis, endMillis), PROGRAMS_PROJECTION, null, null, null)) {
+            assertEquals(expectedCount, cursor.getCount());
+        }
+        try (Cursor cursor = mContentResolver.query(TvContract.buildProgramsUriForChannel(
+                channelUri, startMillis, endMillis), PROGRAMS_PROJECTION, null, null, null)) {
+            assertEquals(expectedCount, cursor.getCount());
+        }
+    }
+
+    public void testProgramsScheduleOverlap() throws Exception {
+        if (!Utils.hasTvInputFramework(getContext())) {
+            return;
+        }
+        final long programStartMillis = 1403712000000l;  // Jun 25 2014 16:00 UTC
+        final long programEndMillis = 1403719200000l;  // Jun 25 2014 18:00 UTC
+        final long hour = 3600000l;
+
+        // Set-up: add a channel and program.
+        ContentValues values = createDummyChannelValues(mInputId);
+        Uri channelUri = mContentResolver.insert(mChannelsUri, values);
+        long channelId = ContentUris.parseId(channelUri);
+        Uri programsUri = TvContract.buildProgramsUriForChannel(channelId);
+        values = createDummyProgramValues(channelId);
+        values.put(TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS, programStartMillis);
+        values.put(TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS, programEndMillis);
+        mContentResolver.insert(programsUri, values);
+
+        // Overlap 1: starts early, ends early.
+        verifyOverlap(programStartMillis - hour, programEndMillis - hour, 1, channelId, channelUri);
+
+        // Overlap 2: starts early, ends late.
+        verifyOverlap(programStartMillis - hour, programEndMillis + hour, 1, channelId, channelUri);
+
+        // Overlap 3: starts early, ends late.
+        verifyOverlap(programStartMillis + hour / 2, programEndMillis - hour / 2, 1,
+                channelId, channelUri);
+
+        // Overlap 4: starts late, ends late.
+        verifyOverlap(programStartMillis + hour, programEndMillis + hour, 1, channelId, channelUri);
+
+        // Non-overlap 1: ends too early.
+        verifyOverlap(programStartMillis - hour, programStartMillis - hour / 2, 0,
+                channelId, channelUri);
+
+        // Non-overlap 2: starts too late
+        verifyOverlap(programEndMillis + hour, programEndMillis + hour * 2, 0,
+                channelId, channelUri);
+    }
+}
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvInputInfoTest.java b/tests/tests/tv/src/android/media/tv/cts/TvInputInfoTest.java
new file mode 100644
index 0000000..440ecb2
--- /dev/null
+++ b/tests/tests/tv/src/android/media/tv/cts/TvInputInfoTest.java
@@ -0,0 +1,111 @@
+/*
+ * 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.media.tv.cts;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.media.tv.TvInputInfo;
+import android.media.tv.TvInputManager;
+import android.test.AndroidTestCase;
+
+/**
+ * Test for {@link android.media.tv.TvInputInfo}.
+ */
+public class TvInputInfoTest extends AndroidTestCase {
+    private TvInputInfo mStubInfo;
+    private PackageManager mPackageManager;
+
+    @Override
+    public void setUp() throws Exception {
+        if (!Utils.hasTvInputFramework(getContext())) {
+            return;
+        }
+        TvInputManager manager =
+                (TvInputManager) getContext().getSystemService(Context.TV_INPUT_SERVICE);
+        for (TvInputInfo info : manager.getTvInputList()) {
+            if (info.getServiceInfo().name.equals(
+                    StubTunerTvInputService.class.getName())) {
+                mStubInfo = info;
+                break;
+            }
+        }
+        mPackageManager = getContext().getPackageManager();
+    }
+
+    public void testGetIntentForSettingsActivity() throws Exception {
+        if (!Utils.hasTvInputFramework(getContext())) {
+            return;
+        }
+        Intent intent = mStubInfo.createSettingsIntent();
+
+        assertEquals(intent.getComponent(), new ComponentName(getContext(),
+                TvInputSettingsActivityStub.class));
+        String inputId = intent.getStringExtra(TvInputInfo.EXTRA_INPUT_ID);
+        assertEquals(mStubInfo.getId(), inputId);
+    }
+
+    public void testGetIntentForSetupActivity() throws Exception {
+        if (!Utils.hasTvInputFramework(getContext())) {
+            return;
+        }
+        Intent intent = mStubInfo.createSetupIntent();
+
+        assertEquals(intent.getComponent(), new ComponentName(getContext(),
+                TvInputSetupActivityStub.class));
+        String inputId = intent.getStringExtra(TvInputInfo.EXTRA_INPUT_ID);
+        assertEquals(mStubInfo.getId(), inputId);
+    }
+
+    public void testTunerHasNoParentId() throws Exception {
+        if (!Utils.hasTvInputFramework(getContext())) {
+            return;
+        }
+        assertNull(mStubInfo.getParentId());
+    }
+
+    public void testGetTypeForTuner() throws Exception {
+        if (!Utils.hasTvInputFramework(getContext())) {
+            return;
+        }
+        assertEquals(mStubInfo.getType(), TvInputInfo.TYPE_TUNER);
+    }
+
+    public void testTunerIsNotPassthroughInput() throws Exception {
+        if (!Utils.hasTvInputFramework(getContext())) {
+            return;
+        }
+        assertFalse(mStubInfo.isPassthroughInput());
+    }
+
+    public void testLoadIcon() throws Exception {
+        if (!Utils.hasTvInputFramework(getContext())) {
+            return;
+        }
+        assertEquals(mStubInfo.loadIcon(getContext()).getConstantState(),
+                mStubInfo.getServiceInfo().loadIcon(mPackageManager).getConstantState());
+    }
+
+    public void testLoadLabel() throws Exception {
+        if (!Utils.hasTvInputFramework(getContext())) {
+            return;
+        }
+        assertEquals(mStubInfo.loadLabel(getContext()),
+                mStubInfo.getServiceInfo().loadLabel(mPackageManager));
+    }
+}
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvInputManagerTest.java b/tests/tests/tv/src/android/media/tv/cts/TvInputManagerTest.java
new file mode 100644
index 0000000..790adf9
--- /dev/null
+++ b/tests/tests/tv/src/android/media/tv/cts/TvInputManagerTest.java
@@ -0,0 +1,88 @@
+/*
+ * 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.media.tv.cts;
+
+import android.content.Context;
+import android.media.tv.TvInputInfo;
+import android.media.tv.TvInputManager;
+import android.test.AndroidTestCase;
+
+import java.util.List;
+
+/**
+ * Test for {@link android.media.tv.TvInputManager}.
+ */
+public class TvInputManagerTest extends AndroidTestCase {
+    private static final String[] VALID_TV_INPUT_SERVICES = {
+        StubTunerTvInputService.class.getName()
+    };
+    private static final String[] INVALID_TV_INPUT_SERVICES = {
+        NoMetadataTvInputService.class.getName(), NoPermissionTvInputService.class.getName()
+    };
+
+    private String mStubId;
+    private TvInputManager mManager;
+
+    private static TvInputInfo getInfoForClassName(List<TvInputInfo> list, String name) {
+        for (TvInputInfo info : list) {
+            if (info.getServiceInfo().name.equals(name)) {
+                return info;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        if (!Utils.hasTvInputFramework(getContext())) {
+            return;
+        }
+        mManager = (TvInputManager) mContext.getSystemService(Context.TV_INPUT_SERVICE);
+        mStubId = getInfoForClassName(
+                mManager.getTvInputList(), StubTunerTvInputService.class.getName()).getId();
+    }
+
+    public void testGetInputState() throws Exception {
+        if (!Utils.hasTvInputFramework(getContext())) {
+            return;
+        }
+        assertEquals(mManager.getInputState(mStubId), TvInputManager.INPUT_STATE_CONNECTED);
+    }
+
+    public void testGetTvInputInfo() throws Exception {
+        if (!Utils.hasTvInputFramework(getContext())) {
+            return;
+        }
+        assertEquals(mManager.getTvInputInfo(mStubId), getInfoForClassName(
+                mManager.getTvInputList(), StubTunerTvInputService.class.getName()));
+    }
+
+    public void testGetTvInputList() throws Exception {
+        if (!Utils.hasTvInputFramework(getContext())) {
+            return;
+        }
+        List<TvInputInfo> list = mManager.getTvInputList();
+        for (String name : VALID_TV_INPUT_SERVICES) {
+            assertNotNull("getTvInputList() doesn't contain valid input: " + name,
+                    getInfoForClassName(list, name));
+        }
+        for (String name : INVALID_TV_INPUT_SERVICES) {
+            assertNull("getTvInputList() contains invalind input: " + name,
+                    getInfoForClassName(list, name));
+        }
+    }
+}
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvInputServiceTest.java b/tests/tests/tv/src/android/media/tv/cts/TvInputServiceTest.java
new file mode 100644
index 0000000..f0ee2772
--- /dev/null
+++ b/tests/tests/tv/src/android/media/tv/cts/TvInputServiceTest.java
@@ -0,0 +1,365 @@
+/*
+ * 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.media.tv.cts;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.Context;
+import android.cts.util.PollingCheck;
+import android.media.tv.TvContentRating;
+import android.media.tv.TvContract;
+import android.media.tv.TvInputInfo;
+import android.media.tv.TvInputManager;
+import android.media.tv.TvTrackInfo;
+import android.media.tv.TvView;
+import android.media.tv.cts.TvInputServiceTest.CountingTvInputService.CountingSession;
+import android.net.Uri;
+import android.test.ActivityInstrumentationTestCase2;
+import android.view.KeyEvent;
+import android.view.Surface;
+
+import com.android.cts.tv.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * Test {@link android.media.tv.TvInputService}.
+ */
+public class TvInputServiceTest extends ActivityInstrumentationTestCase2<TvViewStubActivity> {
+    /** The maximum time to wait for an operation. */
+    private static final long TIME_OUT = 15000L;
+    private static final String mDummyTrackId = "dummyTrackId";
+    private static final TvTrackInfo mDummyTrack =
+            new TvTrackInfo.Builder(TvTrackInfo.TYPE_SUBTITLE, mDummyTrackId)
+            .setLanguage("und").build();
+
+    private TvView mTvView;
+    private Activity mActivity;
+    private Instrumentation mInstrumentation;
+    private TvInputManager mManager;
+    private TvInputInfo mStubInfo;
+    private final StubCallback mCallback = new StubCallback();
+
+    private static class StubCallback extends TvView.TvInputCallback {
+        private int mChannelRetunedCount;
+        private int mVideoAvailableCount;
+        private int mVideoUnavailableCount;
+        private int mTrackSelectedCount;
+        private int mTrackChangedCount;
+        private int mContentAllowedCount;
+        private int mContentBlockedCount;
+
+        @Override
+        public void onChannelRetuned(String inputId, Uri channelUri) {
+            mChannelRetunedCount++;
+        }
+
+        @Override
+        public void onVideoAvailable(String inputId) {
+            mVideoAvailableCount++;
+        }
+
+        @Override
+        public void onVideoUnavailable(String inputId, int reason) {
+            mVideoUnavailableCount++;
+        }
+
+        @Override
+        public void onTrackSelected(String inputId, int type, String trackId) {
+            mTrackSelectedCount++;
+        }
+
+        @Override
+        public void onTracksChanged(String inputId, List<TvTrackInfo> trackList) {
+            mTrackChangedCount++;
+        }
+
+        @Override
+        public void onContentAllowed(String inputId) {
+            mContentAllowedCount++;
+        }
+
+        @Override
+        public void onContentBlocked(String inputId, TvContentRating rating) {
+            mContentBlockedCount++;
+        }
+    }
+
+    public TvInputServiceTest() {
+        super(TvViewStubActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        if (!Utils.hasTvInputFramework(getActivity())) {
+            return;
+        }
+        mActivity = getActivity();
+        mInstrumentation = getInstrumentation();
+        mTvView = (TvView) mActivity.findViewById(R.id.tvview);
+        mManager = (TvInputManager) mActivity.getSystemService(Context.TV_INPUT_SERVICE);
+        for (TvInputInfo info : mManager.getTvInputList()) {
+            if (info.getServiceInfo().name.equals(CountingTvInputService.class.getName())) {
+                mStubInfo = info;
+                break;
+            }
+        }
+        assertNotNull(mStubInfo);
+        mTvView.setCallback(mCallback);
+
+        CountingTvInputService.sSession = null;
+    }
+
+    public void testTvInputService() throws Throwable {
+        if (!Utils.hasTvInputFramework(getActivity())) {
+            return;
+        }
+        verifyCommandTune();
+        verifyCommandSetStreamVolume();
+        verifyCommandSetCaptionEnabled();
+        verifyCommandSelectTrack();
+        verifyCommandDispatchKeyEvent();
+        verifyCallbackChannelRetuned();
+        verifyCallbackVideoAvailable();
+        verifyCallbackVideoUnavailable();
+        verifyCallbackTracksChanged();
+        verifyCallbackTrackSelected();
+        verifyCallbackContentAllowed();
+        verifyCallbackContentBlocked();
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mTvView.reset();
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+    }
+
+    public void verifyCommandTune() {
+        Uri fakeChannelUri = TvContract.buildChannelUri(0);
+        mTvView.tune(mStubInfo.getId(), fakeChannelUri);
+        mInstrumentation.waitForIdleSync();
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                CountingSession session = CountingTvInputService.sSession;
+                return session != null && session.mTuneCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCommandSetStreamVolume() {
+        mTvView.setStreamVolume(1.0f);
+        mInstrumentation.waitForIdleSync();
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                CountingSession session = CountingTvInputService.sSession;
+                return session != null && session.mSetStreamVolumeCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCommandSetCaptionEnabled() {
+        mTvView.setCaptionEnabled(true);
+        mInstrumentation.waitForIdleSync();
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                CountingSession session = CountingTvInputService.sSession;
+                return session != null && session.mSetCaptionEnabledCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCommandSelectTrack() {
+        mTvView.selectTrack(TvTrackInfo.TYPE_AUDIO, "dummyTrackId");
+        mInstrumentation.waitForIdleSync();
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                CountingSession session = CountingTvInputService.sSession;
+                return session != null && session.mSetStreamVolumeCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCommandDispatchKeyEvent() {
+        mTvView.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_K));
+        mInstrumentation.waitForIdleSync();
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                CountingSession session = CountingTvInputService.sSession;
+                return session != null && session.mKeyDownCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCallbackChannelRetuned() {
+        CountingSession session = CountingTvInputService.sSession;
+        assertNotNull(session);
+        Uri fakeChannelUri = TvContract.buildChannelUri(0);
+        session.notifyChannelRetuned(fakeChannelUri);
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                return mCallback.mChannelRetunedCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCallbackVideoAvailable() {
+        CountingSession session = CountingTvInputService.sSession;
+        assertNotNull(session);
+        session.notifyVideoAvailable();
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                return mCallback.mVideoAvailableCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCallbackVideoUnavailable() {
+        CountingSession session = CountingTvInputService.sSession;
+        assertNotNull(session);
+        session.notifyVideoUnavailable(TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING);
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                return mCallback.mVideoUnavailableCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCallbackTracksChanged() {
+        CountingSession session = CountingTvInputService.sSession;
+        assertNotNull(session);
+        ArrayList<TvTrackInfo> tracks = new ArrayList<>();
+        tracks.add(mDummyTrack);
+        session.notifyTracksChanged(tracks);
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                return mCallback.mTrackChangedCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCallbackTrackSelected() {
+        CountingSession session = CountingTvInputService.sSession;
+        assertNotNull(session);
+        session.notifyTrackSelected(mDummyTrack.getType(), mDummyTrack.getId());
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                return mCallback.mTrackSelectedCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCallbackContentAllowed() {
+        CountingSession session = CountingTvInputService.sSession;
+        assertNotNull(session);
+        session.notifyContentAllowed();
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                return mCallback.mContentAllowedCount > 0;
+            }
+        }.run();
+    }
+
+    public void verifyCallbackContentBlocked() {
+        CountingSession session = CountingTvInputService.sSession;
+        assertNotNull(session);
+        TvContentRating rating = TvContentRating.createRating("android.media.tv", "US_TVPG",
+                "US_TVPG_TV_MA", "US_TVPG_S", "US_TVPG_V");
+        session.notifyContentBlocked(rating);
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                return mCallback.mContentBlockedCount > 0;
+            }
+        }.run();
+    }
+
+    public static class CountingTvInputService extends StubTvInputService {
+        static CountingTvInputService sInstance;
+        static CountingSession sSession;
+
+        @Override
+        public Session onCreateSession(String inputId) {
+            sSession = new CountingSession(this);
+            return sSession;
+        }
+
+        public static class CountingSession extends Session {
+            public volatile int mTuneCount;
+            public volatile int mSetStreamVolumeCount;
+            public volatile int mSetCaptionEnabledCount;
+            public volatile int mSelectTrackCount;
+            public volatile int mKeyDownCount;
+
+            CountingSession(Context context) {
+                super(context);
+            }
+
+            @Override
+            public void onRelease() {
+            }
+
+            @Override
+            public boolean onSetSurface(Surface surface) {
+                return false;
+            }
+
+            @Override
+            public boolean onTune(Uri channelUri) {
+                mTuneCount++;
+                return false;
+            }
+
+            @Override
+            public void onSetStreamVolume(float volume) {
+                mSetStreamVolumeCount++;
+            }
+
+            @Override
+            public void onSetCaptionEnabled(boolean enabled) {
+                mSetCaptionEnabledCount++;
+            }
+
+            @Override
+            public boolean onSelectTrack(int type, String id) {
+                mSelectTrackCount++;
+                return false;
+            }
+
+            @Override
+            public boolean onKeyDown(int keyCode, KeyEvent event) {
+                mKeyDownCount++;
+                return false;
+            }
+        }
+    }
+}
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvInputSettingsActivityStub.java b/tests/tests/tv/src/android/media/tv/cts/TvInputSettingsActivityStub.java
new file mode 100644
index 0000000..00dfd8b
--- /dev/null
+++ b/tests/tests/tv/src/android/media/tv/cts/TvInputSettingsActivityStub.java
@@ -0,0 +1,23 @@
+/*
+ * 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.media.tv.cts;
+
+import android.preference.PreferenceActivity;
+
+public class TvInputSettingsActivityStub extends PreferenceActivity {
+
+}
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvInputSetupActivityStub.java b/tests/tests/tv/src/android/media/tv/cts/TvInputSetupActivityStub.java
new file mode 100644
index 0000000..2e5467b
--- /dev/null
+++ b/tests/tests/tv/src/android/media/tv/cts/TvInputSetupActivityStub.java
@@ -0,0 +1,23 @@
+/*
+ * 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.media.tv.cts;
+
+import android.preference.PreferenceActivity;
+
+public class TvInputSetupActivityStub extends PreferenceActivity {
+
+}
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvViewStubActivity.java b/tests/tests/tv/src/android/media/tv/cts/TvViewStubActivity.java
new file mode 100644
index 0000000..5035e14
--- /dev/null
+++ b/tests/tests/tv/src/android/media/tv/cts/TvViewStubActivity.java
@@ -0,0 +1,30 @@
+/*
+ * 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.media.tv.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.cts.tv.R;
+
+public class TvViewStubActivity extends Activity {
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.tvview_layout);
+    }
+}
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvViewTest.java b/tests/tests/tv/src/android/media/tv/cts/TvViewTest.java
new file mode 100644
index 0000000..930dd6a
--- /dev/null
+++ b/tests/tests/tv/src/android/media/tv/cts/TvViewTest.java
@@ -0,0 +1,385 @@
+/*
+ * 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.media.tv.cts;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.Context;
+import android.cts.util.PollingCheck;
+import android.database.Cursor;
+import android.media.tv.TvContract;
+import android.media.tv.TvInputInfo;
+import android.media.tv.TvInputManager;
+import android.media.tv.TvTrackInfo;
+import android.media.tv.TvView;
+import android.media.tv.TvView.TvInputCallback;
+import android.net.Uri;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.util.ArrayMap;
+import android.util.SparseIntArray;
+import android.view.InputEvent;
+import android.view.KeyEvent;
+
+import com.android.cts.tv.R;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Test {@link android.media.tv.TvView}.
+ */
+public class TvViewTest extends ActivityInstrumentationTestCase2<TvViewStubActivity> {
+    /** The maximum time to wait for an operation. */
+    private static final long TIME_OUT = 15000L;
+
+    private TvView mTvView;
+    private Activity mActivity;
+    private Instrumentation mInstrumentation;
+    private TvInputManager mManager;
+    private TvInputInfo mStubInfo;
+    private final MockCallback mCallback = new MockCallback();
+
+    private static class MockCallback extends TvInputCallback {
+        private final Map<String, Boolean> mVideoAvailableMap = new ArrayMap<>();
+        private final Map<String, SparseIntArray> mSelectedTrackGenerationMap = new ArrayMap<>();
+        private final Map<String, Integer> mTracksGenerationMap = new ArrayMap<>();
+        private final Object mLock = new Object();
+
+        public boolean isVideoAvailable(String inputId) {
+            synchronized (mLock) {
+                Boolean available = mVideoAvailableMap.get(inputId);
+                return available == null ? false : available.booleanValue();
+            }
+        }
+
+        public int getSelectedTrackGeneration(String inputId, int type) {
+            synchronized (mLock) {
+                SparseIntArray selectedTrackGenerationMap =
+                        mSelectedTrackGenerationMap.get(inputId);
+                if (selectedTrackGenerationMap == null) {
+                    return 0;
+                }
+                return selectedTrackGenerationMap.get(type, 0);
+            }
+        }
+
+        @Override
+        public void onVideoAvailable(String inputId) {
+            synchronized (mLock) {
+                mVideoAvailableMap.put(inputId, true);
+            }
+        }
+
+        @Override
+        public void onVideoUnavailable(String inputId, int reason) {
+            synchronized (mLock) {
+                mVideoAvailableMap.put(inputId, false);
+            }
+        }
+
+        @Override
+        public void onTrackSelected(String inputId, int type, String trackId) {
+            synchronized (mLock) {
+                SparseIntArray selectedTrackGenerationMap =
+                        mSelectedTrackGenerationMap.get(inputId);
+                if (selectedTrackGenerationMap == null) {
+                    selectedTrackGenerationMap = new SparseIntArray();
+                    mSelectedTrackGenerationMap.put(inputId, selectedTrackGenerationMap);
+                }
+                int currentGeneration = selectedTrackGenerationMap.get(type, 0);
+                selectedTrackGenerationMap.put(type, currentGeneration + 1);
+            }
+        }
+
+        @Override
+        public void onTracksChanged(String inputId, List<TvTrackInfo> trackList) {
+            synchronized (mLock) {
+                Integer tracksGeneration = mTracksGenerationMap.get(inputId);
+                mTracksGenerationMap.put(inputId,
+                        tracksGeneration == null ? 1 : (tracksGeneration + 1));
+            }
+        }
+    }
+
+    /**
+     * Instantiates a new TV view test.
+     */
+    public TvViewTest() {
+        super(TvViewStubActivity.class);
+    }
+
+    /**
+     * Find the TV view specified by id.
+     *
+     * @param id the id
+     * @return the TV view
+     */
+    private TvView findTvViewById(int id) {
+        return (TvView) mActivity.findViewById(id);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+        if (!Utils.hasTvInputFramework(mActivity)) {
+            return;
+        }
+        mInstrumentation = getInstrumentation();
+        mTvView = findTvViewById(R.id.tvview);
+        mManager = (TvInputManager) mActivity.getSystemService(Context.TV_INPUT_SERVICE);
+        for (TvInputInfo info : mManager.getTvInputList()) {
+            if (info.getServiceInfo().name.equals(StubTunerTvInputService.class.getName())) {
+                mStubInfo = info;
+                break;
+            }
+        }
+        assertNotNull(mStubInfo);
+        mTvView.setCallback(mCallback);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (!Utils.hasTvInputFramework(getActivity())) {
+            super.tearDown();
+            return;
+        }
+        StubTunerTvInputService.deleteChannels(mActivity.getContentResolver(), mStubInfo);
+        StubTunerTvInputService.clearTracks();
+        try {
+            runTestOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    mTvView.reset();
+                }
+            });
+        } catch (Throwable t) {
+            throw new RuntimeException(t);
+        }
+        mInstrumentation.waitForIdleSync();
+        super.tearDown();
+    }
+
+    @UiThreadTest
+    public void testConstructor() throws Exception {
+        if (!Utils.hasTvInputFramework(getActivity())) {
+            return;
+        }
+        new TvView(mActivity);
+
+        new TvView(mActivity, null);
+
+        new TvView(mActivity, null, 0);
+    }
+
+    private void tryTuneAllChannels(Runnable runOnEachChannel) throws Throwable {
+        StubTunerTvInputService.insertChannels(mActivity.getContentResolver(), mStubInfo);
+
+        Uri uri = TvContract.buildChannelsUriForInput(mStubInfo.getId());
+        String[] projection = { TvContract.Channels._ID };
+        try (Cursor cursor = mActivity.getContentResolver().query(
+                uri, projection, null, null, null)) {
+            while (cursor != null && cursor.moveToNext()) {
+                long channelId = cursor.getLong(0);
+                Uri channelUri = TvContract.buildChannelUri(channelId);
+                mTvView.tune(mStubInfo.getId(), channelUri);
+                mInstrumentation.waitForIdleSync();
+                new PollingCheck(TIME_OUT) {
+                    @Override
+                    protected boolean check() {
+                        return mCallback.isVideoAvailable(mStubInfo.getId());
+                    }
+                }.run();
+
+                if (runOnEachChannel != null) {
+                    runOnEachChannel.run();
+                }
+            }
+        }
+    }
+
+    public void testSimpleTune() throws Throwable {
+        if (!Utils.hasTvInputFramework(getActivity())) {
+            return;
+        }
+        tryTuneAllChannels(null);
+    }
+
+    private void selectTrackAndVerify(final int type, final TvTrackInfo track,
+            List<TvTrackInfo> tracks) {
+        String selectedTrackId = mTvView.getSelectedTrack(type);
+        final int previousGeneration = mCallback.getSelectedTrackGeneration(
+                mStubInfo.getId(), type);
+        mTvView.selectTrack(type, track == null ? null : track.getId());
+
+        if ((track == null && selectedTrackId != null)
+                || (track != null && !track.getId().equals(selectedTrackId))) {
+            // Check generation change only if we're actually changing track.
+            new PollingCheck(TIME_OUT) {
+                @Override
+                protected boolean check() {
+                    return mCallback.getSelectedTrackGeneration(
+                            mStubInfo.getId(), type) > previousGeneration;
+                }
+            }.run();
+        }
+
+        selectedTrackId = mTvView.getSelectedTrack(type);
+        assertEquals(selectedTrackId, track == null ? null : track.getId());
+        if (selectedTrackId != null) {
+            TvTrackInfo selectedTrack = null;
+            for (TvTrackInfo item : tracks) {
+                if (item.getId().equals(selectedTrackId)) {
+                    selectedTrack = item;
+                    break;
+                }
+            }
+            assertNotNull(selectedTrack);
+            assertEquals(track.getType(), selectedTrack.getType());
+            assertEquals(track.getExtra(), selectedTrack.getExtra());
+            switch (track.getType()) {
+                case TvTrackInfo.TYPE_VIDEO:
+                    assertEquals(track.getVideoHeight(), selectedTrack.getVideoHeight());
+                    assertEquals(track.getVideoWidth(), selectedTrack.getVideoWidth());
+                    break;
+                case TvTrackInfo.TYPE_AUDIO:
+                    assertEquals(track.getAudioChannelCount(),
+                            selectedTrack.getAudioChannelCount());
+                    assertEquals(track.getAudioSampleRate(), selectedTrack.getAudioSampleRate());
+                    assertEquals(track.getLanguage(), selectedTrack.getLanguage());
+                    break;
+                case TvTrackInfo.TYPE_SUBTITLE:
+                    assertEquals(track.getLanguage(), selectedTrack.getLanguage());
+                    break;
+                default:
+                    fail("Unrecognized type: " + track.getType());
+            }
+        }
+    }
+
+    public void testTrackChange() throws Throwable {
+        if (!Utils.hasTvInputFramework(getActivity())) {
+            return;
+        }
+        TvTrackInfo videoTrack1 = new TvTrackInfo.Builder(TvTrackInfo.TYPE_VIDEO, "video-HD")
+                .setVideoHeight(1920).setVideoWidth(1080).build();
+        TvTrackInfo videoTrack2 = new TvTrackInfo.Builder(TvTrackInfo.TYPE_VIDEO, "video-SD")
+                .setVideoHeight(640).setVideoWidth(360).build();
+        TvTrackInfo audioTrack1 =
+                new TvTrackInfo.Builder(TvTrackInfo.TYPE_AUDIO, "audio-stereo-eng")
+                .setLanguage("eng").setAudioChannelCount(2).setAudioSampleRate(48000).build();
+        TvTrackInfo audioTrack2 = new TvTrackInfo.Builder(TvTrackInfo.TYPE_AUDIO, "audio-mono-esp")
+                .setLanguage("esp").setAudioChannelCount(1).setAudioSampleRate(48000).build();
+        TvTrackInfo subtitleTrack1 =
+                new TvTrackInfo.Builder(TvTrackInfo.TYPE_SUBTITLE, "subtitle-eng")
+                .setLanguage("eng").build();
+        TvTrackInfo subtitleTrack2 =
+                new TvTrackInfo.Builder(TvTrackInfo.TYPE_SUBTITLE, "subtitle-esp")
+                .setLanguage("esp").build();
+
+        StubTunerTvInputService.injectTrack(videoTrack1, videoTrack2, audioTrack1, audioTrack2,
+                subtitleTrack1, subtitleTrack2);
+
+        final List<TvTrackInfo> tracks = new ArrayList<TvTrackInfo>();
+        Collections.addAll(tracks, videoTrack1, videoTrack2, audioTrack1, audioTrack2,
+                subtitleTrack1, subtitleTrack2);
+        tryTuneAllChannels(new Runnable() {
+            @Override
+            public void run() {
+                new PollingCheck(TIME_OUT) {
+                    @Override
+                    protected boolean check() {
+                        return mTvView.getTracks(TvTrackInfo.TYPE_AUDIO) != null;
+                    }
+                }.run();
+                final int[] types = { TvTrackInfo.TYPE_AUDIO, TvTrackInfo.TYPE_VIDEO,
+                    TvTrackInfo.TYPE_SUBTITLE };
+                for (int type : types) {
+                    for (TvTrackInfo track : mTvView.getTracks(type)) {
+                        selectTrackAndVerify(type, track, tracks);
+                    }
+                    selectTrackAndVerify(TvTrackInfo.TYPE_SUBTITLE, null, tracks);
+                }
+            }
+        });
+    }
+
+    private void verifyKeyEvent(final KeyEvent keyEvent, final InputEvent[] unhandledEvent) {
+        unhandledEvent[0] = null;
+        mInstrumentation.sendKeySync(keyEvent);
+        mInstrumentation.waitForIdleSync();
+        new PollingCheck(TIME_OUT) {
+            @Override
+            protected boolean check() {
+                return unhandledEvent[0] != null;
+            }
+        }.run();
+        assertTrue(unhandledEvent[0] instanceof KeyEvent);
+        KeyEvent unhandled = (KeyEvent) unhandledEvent[0];
+        assertEquals(unhandled.getAction(), keyEvent.getAction());
+        assertEquals(unhandled.getKeyCode(), keyEvent.getKeyCode());
+    }
+
+    public void testOnUnhandledInputEventListener() throws Throwable {
+        if (!Utils.hasTvInputFramework(getActivity())) {
+            return;
+        }
+        final InputEvent[] unhandledEvent = { null };
+        mTvView.setOnUnhandledInputEventListener(new TvView.OnUnhandledInputEventListener() {
+            @Override
+            public boolean onUnhandledInputEvent(InputEvent event) {
+                unhandledEvent[0] = event;
+                return true;
+            }
+        });
+
+        StubTunerTvInputService.insertChannels(mActivity.getContentResolver(), mStubInfo);
+
+        Uri uri = TvContract.buildChannelsUriForInput(mStubInfo.getId());
+        String[] projection = { TvContract.Channels._ID };
+        try (Cursor cursor = mActivity.getContentResolver().query(
+                uri, projection, null, null, null)) {
+            assertNotNull(cursor);
+            assertTrue(cursor.moveToNext());
+            long channelId = cursor.getLong(0);
+            Uri channelUri = TvContract.buildChannelUri(channelId);
+            mTvView.tune(mStubInfo.getId(), channelUri);
+            mInstrumentation.waitForIdleSync();
+            new PollingCheck(TIME_OUT) {
+                @Override
+                protected boolean check() {
+                    return mCallback.isVideoAvailable(mStubInfo.getId());
+                }
+            }.run();
+        }
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mTvView.setFocusable(true);
+                mTvView.requestFocus();
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+        assertTrue(mTvView.isFocused());
+
+        verifyKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_GUIDE), unhandledEvent);
+        verifyKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_GUIDE), unhandledEvent);
+    }
+}
diff --git a/tests/tests/tv/src/android/media/tv/cts/Utils.java b/tests/tests/tv/src/android/media/tv/cts/Utils.java
new file mode 100644
index 0000000..91f49b1
--- /dev/null
+++ b/tests/tests/tv/src/android/media/tv/cts/Utils.java
@@ -0,0 +1,12 @@
+package android.media.tv.cts;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+public class Utils {
+    private Utils() { }
+
+    public static boolean hasTvInputFramework(Context context) {
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LIVE_TV);
+    }
+}
diff --git a/tests/tests/tv/src/android/tv/settings/cts/SettingsLeanbackStubActivity.java b/tests/tests/tv/src/android/tv/settings/cts/SettingsLeanbackStubActivity.java
new file mode 100644
index 0000000..171f709
--- /dev/null
+++ b/tests/tests/tv/src/android/tv/settings/cts/SettingsLeanbackStubActivity.java
@@ -0,0 +1,23 @@
+/*
+ * 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.tv.settings.cts;
+
+import android.app.Activity;
+
+public class SettingsLeanbackStubActivity extends Activity {
+
+}
diff --git a/tests/tests/tv/src/android/tv/settings/cts/SettingsLeanbackTest.java b/tests/tests/tv/src/android/tv/settings/cts/SettingsLeanbackTest.java
new file mode 100644
index 0000000..c8b4a1b
--- /dev/null
+++ b/tests/tests/tv/src/android/tv/settings/cts/SettingsLeanbackTest.java
@@ -0,0 +1,92 @@
+/*
+ * 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.tv.settings.cts;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.test.ActivityInstrumentationTestCase2;
+
+import java.util.List;
+
+public class SettingsLeanbackTest extends
+        ActivityInstrumentationTestCase2<SettingsLeanbackStubActivity> {
+
+    private static final String TAG = "SettingsLeanbackTest";
+
+    private static final String LEANBACK_SETTINGS_CATEGORY =
+            "android.intent.category.LEANBACK_SETTINGS";
+
+    private Activity mActivity;
+
+    public SettingsLeanbackTest() {
+        super(SettingsLeanbackStubActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+        getInstrumentation().waitForIdleSync();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mActivity = null;
+        super.tearDown();
+    }
+
+    /**
+     * Test if there is at least one activity that can handle LEANBACK_LAUNCHER
+     * category intent.
+     *
+     * @throws Exception
+     */
+    public void testLeanbackLauncherIntentCategory() throws Exception {
+        if (!Utils.hasLeanback(mActivity)) {
+            return;
+        }
+        Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.addCategory(Intent.CATEGORY_LEANBACK_LAUNCHER);
+        assertIntentCanBeHandled(intent);
+    }
+
+    /**
+     * Test if there is at least one activity that can handle LEANBACK_SETTINGS
+     * category intent.
+     *
+     * @throws Exception
+     */
+    public void testLeanbackSettingsIntentCategory() throws Exception {
+        if (!Utils.hasLeanback(mActivity)) {
+            return;
+        }
+        Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.addCategory(LEANBACK_SETTINGS_CATEGORY);
+        assertIntentCanBeHandled(intent);
+    }
+
+    private void assertIntentCanBeHandled(final Intent intent) {
+        PackageManager packageManager = getActivity().getPackageManager();
+        List<ResolveInfo> resolveInfoList =
+            packageManager.queryIntentActivities(intent, 0);
+        assertNotNull(resolveInfoList);
+        // one or more activity can handle this intent.
+        assertTrue(resolveInfoList.size() > 0);
+    }
+}
diff --git a/tests/tests/tv/src/android/tv/settings/cts/Utils.java b/tests/tests/tv/src/android/tv/settings/cts/Utils.java
new file mode 100644
index 0000000..95ce795
--- /dev/null
+++ b/tests/tests/tv/src/android/tv/settings/cts/Utils.java
@@ -0,0 +1,32 @@
+/*
+ * 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.tv.settings.cts;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+public class Utils {
+    private Utils() { }
+
+    public static boolean hasFeature(Context context, String feature) {
+        return context.getPackageManager().hasSystemFeature(feature);
+    }
+
+    public static boolean hasLeanback(Context context) {
+        return hasFeature(context, PackageManager.FEATURE_LEANBACK);
+    }
+}
diff --git a/tests/tests/uiautomation/Android.mk b/tests/tests/uiautomation/Android.mk
new file mode 100644
index 0000000..bb0fc19
--- /dev/null
+++ b/tests/tests/uiautomation/Android.mk
@@ -0,0 +1,30 @@
+# 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)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner ub-uiautomator
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsUiAutomationTestCases
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
+
diff --git a/tests/tests/uiautomation/AndroidManifest.xml b/tests/tests/uiautomation/AndroidManifest.xml
new file mode 100644
index 0000000..d99e999
--- /dev/null
+++ b/tests/tests/uiautomation/AndroidManifest.xml
@@ -0,0 +1,46 @@
+<?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.app.cts.uiautomation">
+
+  <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+
+  <application android:theme="@android:style/Theme.Holo.NoActionBar" >
+
+      <uses-library android:name="android.test.runner"/>
+
+      <activity
+          android:name="android.app.uiautomation.cts.UiAutomationTestFirstActivity"
+          android:exported="true">
+      </activity>
+
+      <activity
+          android:name="android.app.uiautomation.cts.UiAutomationTestSecondActivity"
+          android:exported="true">
+      </activity>
+
+  </application>
+
+  <instrumentation android:name="android.support.test.uiautomator.UiAutomatorInstrumentationTestRunner"
+                   android:targetPackage="android.app.cts.uiautomation">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
+
+</manifest>
diff --git a/tests/tests/uiautomation/res/layout/ui_automation_test.xml b/tests/tests/uiautomation/res/layout/ui_automation_test.xml
new file mode 100644
index 0000000..fb9621d
--- /dev/null
+++ b/tests/tests/uiautomation/res/layout/ui_automation_test.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** 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.
+*/
+-->
+<ListView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/list_view"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent">
+</ListView>
diff --git a/tests/tests/uiautomation/res/values/strings.xml b/tests/tests/uiautomation/res/values/strings.xml
new file mode 100644
index 0000000..7e4e4e4
--- /dev/null
+++ b/tests/tests/uiautomation/res/values/strings.xml
@@ -0,0 +1,55 @@
+<?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.
+-->
+
+<resources>
+
+    <string name="uiautomation_test_activity">Cheeses</string>
+
+    <string-array name="some_cheeses">
+        <item>Abbaye de Belloc</item>
+        <item>Abbaye de Belval</item>
+        <item>Abbaye de Citeaux</item>
+        <item>Abbaye du Mont des Cats</item>
+        <item>Abbot’s Gold</item>
+        <item>Acapella</item>
+        <item>Acorn</item>
+        <item>Adelost</item>
+        <item>Affidelice au Chablis</item>
+        <item>Afuega\'l Pitu</item>
+        <item>Aged Gouda</item>
+        <item>Airag</item>
+        <item>Airedale</item>
+        <item>Aisy Cendre</item>
+        <item>Allgauer Emmentaler</item>
+        <item>Babybel</item>
+        <item>Baby Swiss</item>
+        <item>Baguette Laonnaise</item>
+        <item>Bakers</item>
+        <item>Balaton</item>
+        <item>Bandal</item>
+        <item>Banon</item>
+        <item>Barry\'s Bay Cheddar</item>
+        <item>Basing</item>
+        <item>Basket Cheese</item>
+        <item>Bath Cheese</item>
+        <item>Bavarian Bergkase</item>
+        <item>Baylough</item>
+        <item>Beauvoorde</item>
+        <item>Beemster 2% Milk</item>
+    </string-array>
+
+</resources>
diff --git a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java
new file mode 100644
index 0000000..6d80819
--- /dev/null
+++ b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java
@@ -0,0 +1,291 @@
+/*
+ * 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.app.uiautomation.cts;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.app.Activity;
+import android.app.UiAutomation;
+import android.content.Intent;
+import android.view.FrameStats;
+import android.view.WindowAnimationFrameStats;
+import android.view.WindowContentFrameStats;
+import android.view.accessibility.AccessibilityWindowInfo;
+import android.support.test.uiautomator.UiScrollable;
+import android.support.test.uiautomator.UiSelector;
+import android.support.test.uiautomator.UiAutomatorTestCase;
+
+import java.util.List;
+
+/**
+ * Tests for the UiAutomation APIs.
+ */
+public class UiAutomationTest extends UiAutomatorTestCase {
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        AccessibilityServiceInfo info = getInstrumentation().getUiAutomation().getServiceInfo();
+        info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
+        getInstrumentation().getUiAutomation().setServiceInfo(info);
+    }
+
+    public void testWindowContentFrameStats() throws Exception {
+        Activity activity = null;
+        try {
+            UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
+
+            // Start an activity.
+            Intent intent = new Intent(getInstrumentation().getContext(),
+                    UiAutomationTestFirstActivity.class);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            activity = getInstrumentation().startActivitySync(intent);
+
+            // Wait for things to settle.
+            getUiDevice().waitForIdle();
+
+            // Find the application window.
+            final int windowId = findAppWindowId(uiAutomation.getWindows());
+            assertTrue(windowId >= 0);
+
+            // Clear stats to be with a clean slate.
+            assertTrue(uiAutomation.clearWindowContentFrameStats(windowId));
+
+            // Find the list to scroll around.
+            UiScrollable listView = new UiScrollable(new UiSelector().resourceId(
+                    "android.app.cts.uiautomation:id/list_view"));
+
+            // Scoll a bit.
+            listView.scrollToEnd(Integer.MAX_VALUE);
+            listView.scrollToBeginning(Integer.MAX_VALUE);
+
+            // Get the frame stats.
+            WindowContentFrameStats stats = uiAutomation.getWindowContentFrameStats(windowId);
+
+            // Check the frame stats...
+
+            // We should have somethong.
+            assertNotNull(stats);
+
+            // The refresh presiod is always positive.
+            assertTrue(stats.getRefreshPeriodNano() > 0);
+
+            // There is some frame data.
+            final int frameCount = stats.getFrameCount();
+            assertTrue(frameCount > 0);
+
+            // The frames are ordered in ascending order.
+            assertWindowContentTimestampsInAscendingOrder(stats);
+
+            // The start and end times are based on first and last frame.
+            assertEquals(stats.getStartTimeNano(), stats.getFramePresentedTimeNano(0));
+            assertEquals(stats.getEndTimeNano(), stats.getFramePresentedTimeNano(frameCount - 1));
+        } finally {
+            // Clean up.
+            if (activity != null) {
+                activity.finish();
+            }
+        }
+    }
+
+    public void testWindowContentFrameStatsNoAnimation() throws Exception {
+        Activity activity = null;
+        try {
+            UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
+
+            // Start an activity.
+            Intent intent = new Intent(getInstrumentation().getContext(),
+                    UiAutomationTestFirstActivity.class);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            activity = getInstrumentation().startActivitySync(intent);
+
+            // Wait for things to settle.
+            getUiDevice().waitForIdle();
+
+            // Find the application window.
+            final int windowId = findAppWindowId(uiAutomation.getWindows());
+            assertTrue(windowId >= 0);
+
+            // Clear stats to be with a clean slate.
+            assertTrue(uiAutomation.clearWindowContentFrameStats(windowId));
+
+            // Get the frame stats.
+            WindowContentFrameStats stats = uiAutomation.getWindowContentFrameStats(windowId);
+
+            // Check the frame stats...
+
+            // We should have somethong.
+            assertNotNull(stats);
+
+            // The refresh presiod is always positive.
+            assertTrue(stats.getRefreshPeriodNano() > 0);
+
+            // There is no data.
+            assertTrue(stats.getFrameCount() == 0);
+
+            // The start and end times are undefibed as we have no data.
+            assertEquals(stats.getStartTimeNano(), FrameStats.UNDEFINED_TIME_NANO);
+            assertEquals(stats.getEndTimeNano(), FrameStats.UNDEFINED_TIME_NANO);
+        } finally {
+            // Clean up.
+            if (activity != null) {
+                activity.finish();
+            }
+        }
+    }
+
+    public void testWindowAnimationFrameStats() throws Exception {
+        Activity firstActivity = null;
+        Activity secondActivity = null;
+        try {
+            UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
+
+            // Start the frist activity.
+            Intent firstIntent = new Intent(getInstrumentation().getContext(),
+                    UiAutomationTestFirstActivity.class);
+            firstIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            firstActivity = getInstrumentation().startActivitySync(firstIntent);
+
+            // Wait for things to settle.
+            getUiDevice().waitForIdle();
+
+            // Clear the window animation stats to be with a clean slate.
+            uiAutomation.clearWindowAnimationFrameStats();
+
+            // Start the second activity
+            Intent secondIntent = new Intent(getInstrumentation().getContext(),
+                    UiAutomationTestSecondActivity.class);
+            secondIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            secondActivity = getInstrumentation().startActivitySync(secondIntent);
+
+            // Wait for things to settle.
+            getUiDevice().waitForIdle();
+
+            // Get the frame stats.
+            WindowAnimationFrameStats stats = uiAutomation.getWindowAnimationFrameStats();
+
+            // Check the frame stats...
+
+            // We should have somethong.
+            assertNotNull(stats);
+
+            // The refresh presiod is always positive.
+            assertTrue(stats.getRefreshPeriodNano() > 0);
+
+            // There is some frame data.
+            final int frameCount = stats.getFrameCount();
+            assertTrue(frameCount > 0);
+
+            // The frames are ordered in ascending order.
+            assertWindowAnimationTimestampsInAscendingOrder(stats);
+
+            // The start and end times are based on first and last frame.
+            assertEquals(stats.getStartTimeNano(), stats.getFramePresentedTimeNano(0));
+            assertEquals(stats.getEndTimeNano(), stats.getFramePresentedTimeNano(frameCount - 1));
+        } finally {
+            // Clean up.
+            if (firstActivity != null) {
+                firstActivity.finish();
+            }
+            if (secondActivity != null) {
+                secondActivity.finish();
+            }
+        }
+    }
+
+    public void testWindowAnimationFrameStatsNoAnimation() throws Exception {
+        UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
+
+        // Wait for things to settle.
+        getUiDevice().waitForIdle();
+
+        // Clear the window animation stats to be with a clean slate.
+        uiAutomation.clearWindowAnimationFrameStats();
+
+        // Get the frame stats.
+        WindowAnimationFrameStats stats = uiAutomation.getWindowAnimationFrameStats();
+
+        // Check the frame stats...
+
+        // We should have somethong.
+        assertNotNull(stats);
+
+        // The refresh presiod is always positive.
+        assertTrue(stats.getRefreshPeriodNano() > 0);
+
+        // There is no data.
+        assertTrue(stats.getFrameCount() == 0);
+
+        // The start and end times are undefibed as we have no data.
+        assertEquals(stats.getStartTimeNano(), FrameStats.UNDEFINED_TIME_NANO);
+        assertEquals(stats.getEndTimeNano(), FrameStats.UNDEFINED_TIME_NANO);
+    }
+
+    private void assertWindowContentTimestampsInAscendingOrder(WindowContentFrameStats stats) {
+        long lastExpectedTimeNano = 0;
+        long lastPresentedTimeNano = 0;
+        long lastPreparedTimeNano = 0;
+
+        final int frameCount = stats.getFrameCount();
+        for (int i = 0; i < frameCount; i++) {
+            final long expectedTimeNano = stats.getFramePostedTimeNano(i);
+            assertTrue(expectedTimeNano > lastExpectedTimeNano);
+            lastExpectedTimeNano = expectedTimeNano;
+
+            final long presentedTimeNano = stats.getFramePresentedTimeNano(i);
+            if (lastPresentedTimeNano == FrameStats.UNDEFINED_TIME_NANO) {
+                assertTrue(presentedTimeNano == FrameStats.UNDEFINED_TIME_NANO);
+            } else if (presentedTimeNano != FrameStats.UNDEFINED_TIME_NANO) {
+                assertTrue(presentedTimeNano > lastPresentedTimeNano);
+            }
+            lastPresentedTimeNano = presentedTimeNano;
+
+            final long preparedTimeNano = stats.getFrameReadyTimeNano(i);
+            if (lastPreparedTimeNano == FrameStats.UNDEFINED_TIME_NANO) {
+                assertTrue(preparedTimeNano == FrameStats.UNDEFINED_TIME_NANO);
+            } else if (preparedTimeNano != FrameStats.UNDEFINED_TIME_NANO) {
+                assertTrue(preparedTimeNano > lastPreparedTimeNano);
+            }
+            lastPreparedTimeNano = preparedTimeNano;
+        }
+    }
+
+    private void assertWindowAnimationTimestampsInAscendingOrder(WindowAnimationFrameStats stats) {
+        long lastPresentedTimeNano = 0;
+
+        final int frameCount = stats.getFrameCount();
+        for (int i = 0; i < frameCount; i++) {
+            final long presentedTimeNano = stats.getFramePresentedTimeNano(i);
+            if (lastPresentedTimeNano == FrameStats.UNDEFINED_TIME_NANO) {
+                assertTrue(presentedTimeNano == FrameStats.UNDEFINED_TIME_NANO);
+            } else if (presentedTimeNano != FrameStats.UNDEFINED_TIME_NANO) {
+                assertTrue(presentedTimeNano > lastPresentedTimeNano);
+            }
+            lastPresentedTimeNano = presentedTimeNano;
+        }
+    }
+
+    private int findAppWindowId(List<AccessibilityWindowInfo> windows) {
+        final int windowCount = windows.size();
+        for (int i = 0; i < windowCount; i++) {
+            AccessibilityWindowInfo window = windows.get(i);
+            if (window.getType() == AccessibilityWindowInfo.TYPE_APPLICATION) {
+                return window.getId();
+            }
+        }
+        return -1;
+    }
+}
diff --git a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestFirstActivity.java b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestFirstActivity.java
new file mode 100644
index 0000000..a798b1b
--- /dev/null
+++ b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestFirstActivity.java
@@ -0,0 +1,47 @@
+/*
+* 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.app.uiautomation.cts;
+
+import android.app.cts.uiautomation.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.WindowManager;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+/**
+* Activity for testing the UiAutomatoin APIs.
+*/
+public class UiAutomationTestFirstActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.ui_automation_test);
+
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
+                | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
+                | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
+
+        String[] cheeses = getResources().getStringArray(R.array.some_cheeses);
+        ArrayAdapter<String> cheeseAdapter = new ArrayAdapter<String>(this,
+                android.R.layout.simple_list_item_1, cheeses);
+
+        ListView listView = (ListView) findViewById(R.id.list_view);
+        listView.setAdapter(cheeseAdapter);
+    }
+}
diff --git a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestSecondActivity.java b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestSecondActivity.java
new file mode 100644
index 0000000..e6fc743
--- /dev/null
+++ b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestSecondActivity.java
@@ -0,0 +1,46 @@
+/*
+* 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.app.uiautomation.cts;
+
+import android.app.Activity;
+import android.app.cts.uiautomation.R;
+import android.os.Bundle;
+import android.view.WindowManager;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+/**
+* Activity for testing the UiAutomatoin APIs.
+*/
+public class UiAutomationTestSecondActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.ui_automation_test);
+
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
+                | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
+                | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
+
+        String[] cheeses = getResources().getStringArray(R.array.some_cheeses);
+        ArrayAdapter<String> cheeseAdapter = new ArrayAdapter<String>(this,
+                android.R.layout.simple_list_item_1, cheeses);
+
+        ListView listView = (ListView) findViewById(R.id.list_view);
+        listView.setAdapter(cheeseAdapter);
+    }
+}
diff --git a/tests/tests/uidisolation/Android.mk b/tests/tests/uidisolation/Android.mk
index ba82eb5..8529407 100644
--- a/tests/tests/uidisolation/Android.mk
+++ b/tests/tests/uidisolation/Android.mk
@@ -21,12 +21,12 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner ctstestserver
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsUidIsolationTestCases
 
+LOCAL_SDK_VERSION := current
+
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/uidisolation/AndroidManifest.xml b/tests/tests/uidisolation/AndroidManifest.xml
index e456a50..a8c6848 100644
--- a/tests/tests/uidisolation/AndroidManifest.xml
+++ b/tests/tests/uidisolation/AndroidManifest.xml
@@ -31,8 +31,11 @@
 
    <uses-permission android:name="android.permission.INTERNET"/>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.cts.uidisolation"
-                     android:label="CTS tests of android.uidisolation"/>
+                     android:label="CTS tests of android.uidisolation">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 </manifest>
 
diff --git a/tests/tests/uirendering/Android.mk b/tests/tests/uirendering/Android.mk
new file mode 100644
index 0000000..76707df
--- /dev/null
+++ b/tests/tests/uirendering/Android.mk
@@ -0,0 +1,33 @@
+# 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)
+
+include $(CLEAR_VARS)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := CtsUiRenderingTestCases
+
+# uncomment when dalvik.annotation.Test* are removed or part of SDK
+#LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/uirendering/AndroidManifest.xml b/tests/tests/uirendering/AndroidManifest.xml
new file mode 100644
index 0000000..413dfba
--- /dev/null
+++ b/tests/tests/uirendering/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?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="com.android.cts.uirendering">
+    <uses-permission android:name="android.permission.INJECT_EVENTS" />
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <application>
+        <activity android:name="android.uirendering.cts.testinfrastructure.DrawActivity"
+                android:theme="@style/WhiteBackgroundTheme"></activity>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+                     android:targetPackage="com.android.cts.uirendering">
+    </instrumentation>
+
+</manifest>
+
diff --git a/tests/tests/uirendering/assets/blue_padded_square.html b/tests/tests/uirendering/assets/blue_padded_square.html
new file mode 100644
index 0000000..8609af7
--- /dev/null
+++ b/tests/tests/uirendering/assets/blue_padded_square.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head lang="en">
+  <meta charset="UTF-8">
+  <title></title>
+</head>
+<body style="padding:10px 10px 10px 10px">
+    <div style="height: 80px; width: 80px; background-color:blue"/>
+</body>
+</html>
diff --git a/tests/tests/uirendering/res/drawable-nodpi/black1.png b/tests/tests/uirendering/res/drawable-nodpi/black1.png
new file mode 100644
index 0000000..3487ced
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable-nodpi/black1.png
Binary files differ
diff --git a/tests/tests/uirendering/res/drawable-nodpi/blackitalic1.png b/tests/tests/uirendering/res/drawable-nodpi/blackitalic1.png
new file mode 100644
index 0000000..8fd3b50
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable-nodpi/blackitalic1.png
Binary files differ
diff --git a/tests/tests/uirendering/res/drawable-nodpi/blue_padded_square.9.png b/tests/tests/uirendering/res/drawable-nodpi/blue_padded_square.9.png
new file mode 100644
index 0000000..d69869d
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable-nodpi/blue_padded_square.9.png
Binary files differ
diff --git a/tests/tests/uirendering/res/drawable-nodpi/bold1.png b/tests/tests/uirendering/res/drawable-nodpi/bold1.png
new file mode 100644
index 0000000..199cccc
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable-nodpi/bold1.png
Binary files differ
diff --git a/tests/tests/uirendering/res/drawable-nodpi/bolditalic1.png b/tests/tests/uirendering/res/drawable-nodpi/bolditalic1.png
new file mode 100644
index 0000000..985635e
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable-nodpi/bolditalic1.png
Binary files differ
diff --git a/tests/tests/uirendering/res/drawable-nodpi/condensed1.png b/tests/tests/uirendering/res/drawable-nodpi/condensed1.png
new file mode 100644
index 0000000..6889a3a
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable-nodpi/condensed1.png
Binary files differ
diff --git a/tests/tests/uirendering/res/drawable-nodpi/condensedbold1.png b/tests/tests/uirendering/res/drawable-nodpi/condensedbold1.png
new file mode 100644
index 0000000..9554dee
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable-nodpi/condensedbold1.png
Binary files differ
diff --git a/tests/tests/uirendering/res/drawable-nodpi/condensedbolditalic1.png b/tests/tests/uirendering/res/drawable-nodpi/condensedbolditalic1.png
new file mode 100644
index 0000000..0483355
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable-nodpi/condensedbolditalic1.png
Binary files differ
diff --git a/tests/tests/uirendering/res/drawable-nodpi/condenseditalic1.png b/tests/tests/uirendering/res/drawable-nodpi/condenseditalic1.png
new file mode 100644
index 0000000..6584147
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable-nodpi/condenseditalic1.png
Binary files differ
diff --git a/tests/tests/uirendering/res/drawable-nodpi/condensedlight1.png b/tests/tests/uirendering/res/drawable-nodpi/condensedlight1.png
new file mode 100644
index 0000000..49d01ac
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable-nodpi/condensedlight1.png
Binary files differ
diff --git a/tests/tests/uirendering/res/drawable-nodpi/condensedlightitalic1.png b/tests/tests/uirendering/res/drawable-nodpi/condensedlightitalic1.png
new file mode 100644
index 0000000..6fe4a76
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable-nodpi/condensedlightitalic1.png
Binary files differ
diff --git a/tests/tests/uirendering/res/drawable-nodpi/hello1.png b/tests/tests/uirendering/res/drawable-nodpi/hello1.png
new file mode 100644
index 0000000..7a4be5a
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable-nodpi/hello1.png
Binary files differ
diff --git a/tests/tests/uirendering/res/drawable-nodpi/italic1.png b/tests/tests/uirendering/res/drawable-nodpi/italic1.png
new file mode 100644
index 0000000..a5f9ef2
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable-nodpi/italic1.png
Binary files differ
diff --git a/tests/tests/uirendering/res/drawable-nodpi/light1.png b/tests/tests/uirendering/res/drawable-nodpi/light1.png
new file mode 100644
index 0000000..dfa59da
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable-nodpi/light1.png
Binary files differ
diff --git a/tests/tests/uirendering/res/drawable-nodpi/lightitalic1.png b/tests/tests/uirendering/res/drawable-nodpi/lightitalic1.png
new file mode 100644
index 0000000..283ddc4
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable-nodpi/lightitalic1.png
Binary files differ
diff --git a/tests/tests/uirendering/res/drawable-nodpi/medium1.png b/tests/tests/uirendering/res/drawable-nodpi/medium1.png
new file mode 100644
index 0000000..e615186
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable-nodpi/medium1.png
Binary files differ
diff --git a/tests/tests/uirendering/res/drawable-nodpi/mediumitalic1.png b/tests/tests/uirendering/res/drawable-nodpi/mediumitalic1.png
new file mode 100644
index 0000000..3e15fc8
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable-nodpi/mediumitalic1.png
Binary files differ
diff --git a/tests/tests/uirendering/res/drawable-nodpi/thin1.png b/tests/tests/uirendering/res/drawable-nodpi/thin1.png
new file mode 100644
index 0000000..9637262
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable-nodpi/thin1.png
Binary files differ
diff --git a/tests/tests/uirendering/res/drawable-nodpi/thinitalic1.png b/tests/tests/uirendering/res/drawable-nodpi/thinitalic1.png
new file mode 100644
index 0000000..0afbb9a
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable-nodpi/thinitalic1.png
Binary files differ
diff --git a/tests/tests/uirendering/res/drawable/sunset1.jpg b/tests/tests/uirendering/res/drawable/sunset1.jpg
new file mode 100644
index 0000000..92851f3
--- /dev/null
+++ b/tests/tests/uirendering/res/drawable/sunset1.jpg
Binary files differ
diff --git a/tests/tests/uirendering/res/layout/blue_padded_layout.xml b/tests/tests/uirendering/res/layout/blue_padded_layout.xml
new file mode 100644
index 0000000..1cd1b21
--- /dev/null
+++ b/tests/tests/uirendering/res/layout/blue_padded_layout.xml
@@ -0,0 +1,28 @@
+<?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.
+  -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="200px"
+        android:layout_height="200px"
+        android:clipChildren="false">
+    <android.uirendering.cts.testclasses.view.UnclippedBlueView
+            android:id="@+id/child"
+            android:layout_width="100px"
+            android:layout_height="100px"
+            android:paddingLeft="15px"
+            android:paddingTop="16px"
+            android:paddingRight="17px"
+            android:paddingBottom="18px"/>
+</FrameLayout>
diff --git a/tests/tests/uirendering/res/layout/blue_padded_square.xml b/tests/tests/uirendering/res/layout/blue_padded_square.xml
new file mode 100644
index 0000000..0f254d4
--- /dev/null
+++ b/tests/tests/uirendering/res/layout/blue_padded_square.xml
@@ -0,0 +1,19 @@
+<?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.
+  -->
+<View xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="100px"
+        android:layout_height="100px"
+        android:background="@drawable/blue_padded_square"/>
diff --git a/tests/tests/uirendering/res/layout/draw_activity_view.xml b/tests/tests/uirendering/res/layout/draw_activity_view.xml
new file mode 100644
index 0000000..54a72e3
--- /dev/null
+++ b/tests/tests/uirendering/res/layout/draw_activity_view.xml
@@ -0,0 +1,17 @@
+<?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.
+-->
+
+<android.uirendering.cts.CanvasClientView xmlns:android="http://schemas.android.com/apk/res/android"/>
diff --git a/tests/tests/uirendering/res/layout/simple_rect_layout.xml b/tests/tests/uirendering/res/layout/simple_rect_layout.xml
new file mode 100644
index 0000000..24c9b6b
--- /dev/null
+++ b/tests/tests/uirendering/res/layout/simple_rect_layout.xml
@@ -0,0 +1,27 @@
+<?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.
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="#f00">
+
+    <View android:layout_width="180px"
+        android:layout_height="120px"
+        android:background="#0f0" />
+
+</LinearLayout>
diff --git a/tests/tests/uirendering/res/layout/simple_red_layout.xml b/tests/tests/uirendering/res/layout/simple_red_layout.xml
new file mode 100644
index 0000000..1ae3e38
--- /dev/null
+++ b/tests/tests/uirendering/res/layout/simple_red_layout.xml
@@ -0,0 +1,19 @@
+<?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.
+  -->
+<View xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="#f00" />
diff --git a/tests/tests/uirendering/res/values/themes.xml b/tests/tests/uirendering/res/values/themes.xml
new file mode 100644
index 0000000..751b7cb
--- /dev/null
+++ b/tests/tests/uirendering/res/values/themes.xml
@@ -0,0 +1,26 @@
+<?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.
+-->
+<resources>
+    <style name="WhiteBackgroundTheme" parent="@android:style/Theme.Holo.NoActionBar.Fullscreen">
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:windowFullscreen">true</item>
+        <item name="android:fadingEdge">none</item>
+        <item name="android:windowBackground">@android:color/white</item>
+        <!--This shouldn't be necessary currently a hack for an existing bug with transitions-->
+        <item name="android:windowContentTransitions">false</item>
+        <item name="android:windowAnimationStyle">@null</item>
+    </style>
+</resources>
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/BaseRenderScriptComparer.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/BaseRenderScriptComparer.java
new file mode 100644
index 0000000..3f9a9f6
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/BaseRenderScriptComparer.java
@@ -0,0 +1,78 @@
+package android.uirendering.cts.bitmapcomparers;
+
+import android.content.res.Resources;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+
+/**
+ * Base class for calculators that want to implement renderscript
+ */
+public abstract class BaseRenderScriptComparer extends BitmapComparer {
+    private Allocation mRowInputs;
+    private Allocation mRowOutputs;
+    private int mHeight;
+
+    public abstract boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width,
+            int height);
+
+    /**
+     * The subclasses must implement this method, which will say that the rows follow their specific
+     * algorithm
+     */
+    public abstract boolean verifySameRowsRS(Resources resources, Allocation ideal,
+            Allocation given, int offset, int stride, int width, int height,
+            RenderScript renderScript, Allocation inputAllocation, Allocation outputAllocation);
+
+    public boolean verifySameRS(Resources resources, Allocation ideal,
+            Allocation given, int offset, int stride, int width, int height,
+            RenderScript renderScript) {
+        if (mRowInputs == null) {
+            mHeight = height;
+            mRowInputs = createInputRowIndexAllocation(renderScript);
+            mRowOutputs = createOutputRowAllocation(renderScript);
+        }
+        return verifySameRowsRS(resources, ideal, given, offset, stride, width, height,
+                renderScript, mRowInputs, mRowOutputs);
+    }
+
+    public boolean supportsRenderScript() {
+        return true;
+    }
+
+    /**
+     * Sums the values in the output Allocation
+     */
+    public float sum1DFloatAllocation(Allocation rowOutputs) {
+        //Get the values returned from the function
+        float[] returnValue = new float[mHeight];
+        rowOutputs.copyTo(returnValue);
+        float sum = 0;
+        //If any row had any different pixels, then it fails
+        for (int i = 0; i < mHeight; i++) {
+            sum += returnValue[i];
+        }
+        return sum;
+    }
+
+    /**
+     * Creates an allocation where the values in it are the indices of each row
+     */
+    private Allocation createInputRowIndexAllocation(RenderScript renderScript) {
+        //Create an array with the index of each row
+        int[] inputIndices = new int[mHeight];
+        for (int i = 0; i < mHeight; i++) {
+            inputIndices[i] = i;
+        }
+        //Create the allocation from that given array
+        Allocation inputAllocation = Allocation.createSized(renderScript, Element.I32(renderScript),
+                inputIndices.length, Allocation.USAGE_SCRIPT);
+        inputAllocation.copyFrom(inputIndices);
+        return inputAllocation;
+    }
+
+    private Allocation createOutputRowAllocation(RenderScript renderScript) {
+        return Allocation.createSized(renderScript, Element.F32(renderScript), mHeight,
+                Allocation.USAGE_SCRIPT);
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/BitmapComparer.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/BitmapComparer.java
new file mode 100644
index 0000000..8d74aa5
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/BitmapComparer.java
@@ -0,0 +1,62 @@
+/*
+ * 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.uirendering.cts.bitmapcomparers;
+
+import android.content.res.Resources;
+import android.renderscript.Allocation;
+import android.renderscript.RenderScript;
+
+/**
+ * This abstract class can be used by the tester to implement their own comparison methods
+ */
+public abstract class BitmapComparer {
+    /**
+     * Compares the two bitmaps given using Java.
+     * @param offset where in the bitmaps to start
+     * @param stride how much to skip between two different rows
+     * @param width the width of the subsection being tested
+     * @param height the height of the subsection being tested
+     * @return
+     */
+    public abstract boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width,
+            int height);
+
+    /**
+     * Compare the two bitmaps using RenderScript, if the comparer
+     * {@link supportsRenderScript() supports it}. If it does not, this method will throw an
+     * UnsupportedOperationException
+     */
+    public boolean verifySameRS(Resources resources, Allocation ideal,
+            Allocation given, int offset, int stride, int width, int height,
+            RenderScript renderScript) {
+        throw new UnsupportedOperationException("Renderscript not supported for this calculator");
+    }
+
+    /**
+     * This calculates the position in an array that would represent a bitmap given the parameters.
+     */
+    protected static int indexFromXAndY(int x, int y, int stride, int offset) {
+        return x + (y * stride) + offset;
+    }
+
+    /**
+     * Returns whether the verifySameRS() is implemented, and may be used on a RenderScript enabled
+     * system
+     */
+    public boolean supportsRenderScript() {
+        return false;
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ExactComparer.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ExactComparer.java
new file mode 100644
index 0000000..978dc0b
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ExactComparer.java
@@ -0,0 +1,78 @@
+/*
+ * 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.uirendering.cts.bitmapcomparers;
+
+import com.android.cts.uirendering.R;
+import com.android.cts.uirendering.ScriptC_ExactComparer;
+
+import android.content.res.Resources;
+import android.renderscript.Allocation;
+import android.renderscript.RenderScript;
+import android.util.Log;
+
+/**
+ * This class does an exact comparison of the pixels in a bitmap.
+ */
+public class ExactComparer extends BaseRenderScriptComparer {
+    private static final String TAG = "ExactComparer";
+    private ScriptC_ExactComparer mScript;
+
+    /**
+     * This method does an exact 1 to 1 comparison of the two bitmaps
+     */
+    public boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width,
+            int height) {
+        int count = 0;
+
+        for (int y = 0 ; y < height ; y++) {
+            for (int x = 0 ; x < width ; x++) {
+                int index = indexFromXAndY(x, y, stride, offset);
+                if (ideal[index] != given[index]) {
+                    Log.d(TAG, "Failure on position x = " + x + " y = " + y);
+                    Log.d(TAG, "Expected color : " + Integer.toHexString(ideal[index]) +
+                            " given color : " + Integer.toHexString(given[index]));
+                    count++;
+                }
+            }
+        }
+        Log.d(TAG, "Number of different pixels : " + count);
+
+        return (count == 0);
+    }
+
+    @Override
+    public boolean verifySameRowsRS(Resources resources, Allocation ideal,
+            Allocation given, int offset, int stride, int width, int height,
+            RenderScript renderScript, Allocation inputAllocation, Allocation outputAllocation) {
+        if (mScript == null) {
+            mScript = new ScriptC_ExactComparer(renderScript);
+        }
+        mScript.set_WIDTH(width);
+        mScript.set_OFFSET(offset);
+
+        //Set the bitmap allocations
+        mScript.set_ideal(ideal);
+        mScript.set_given(given);
+
+        //Call the renderscript function on each row
+        mScript.forEach_exactCompare(inputAllocation, outputAllocation);
+
+        float val = sum1DFloatAllocation(outputAllocation);
+        Log.d(TAG, "Number of different pixels RS : " + val);
+
+        return val == 0;
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ExactComparer.rs b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ExactComparer.rs
new file mode 100644
index 0000000..899a5cc
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ExactComparer.rs
@@ -0,0 +1,25 @@
+#pragma version(1)
+#pragma rs java_package_name(com.android.cts.uirendering)
+
+int WIDTH;
+int OFFSET;
+
+rs_allocation ideal;
+rs_allocation given;
+
+// This method does a simple comparison of all the values in the given and ideal allocations.
+// If any of the pixels are off, then the test will fail.
+void exactCompare(const int32_t *v_in, float *v_out){
+    int y = v_in[0];
+    v_out[0] = 0;
+
+    for(int i = 0 ; i < WIDTH ; i ++){
+        uchar4 idealPixel = rsGetElementAt_uchar4(ideal, i + OFFSET, y);
+        uchar4 givenPixel = rsGetElementAt_uchar4(given, i + OFFSET, y);
+        uchar4 diff = idealPixel - givenPixel;
+        int totalDiff = diff.x + diff.y + diff.z;
+        if(totalDiff != 0){
+            v_out[0] ++;
+        }
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MSSIMComparer.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MSSIMComparer.java
new file mode 100644
index 0000000..e766f63
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MSSIMComparer.java
@@ -0,0 +1,192 @@
+/*
+ * 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.uirendering.cts.bitmapcomparers;
+
+import com.android.cts.uirendering.R;
+import com.android.cts.uirendering.ScriptC_MSSIMComparer;
+
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.renderscript.Allocation;
+import android.renderscript.RenderScript;
+import android.util.Log;
+
+/**
+ * Image comparison using Structural Similarity Index, developed by Wang, Bovik, Sheikh, and
+ * Simoncelli. Details can be read in their paper :
+ *
+ * https://ece.uwaterloo.ca/~z70wang/publications/ssim.pdf
+ */
+public class MSSIMComparer extends BaseRenderScriptComparer {
+    // These values were taken from the publication
+    public static final String TAG_NAME = "MSSIM";
+    public static final double CONSTANT_L = 254;
+    public static final double CONSTANT_K1 = 0.00001;
+    public static final double CONSTANT_K2 = 0.00003;
+    public static final double CONSTANT_C1 = Math.pow(CONSTANT_L * CONSTANT_K1, 2);
+    public static final double CONSTANT_C2 = Math.pow(CONSTANT_L * CONSTANT_K2, 2);
+    public static final int WINDOW_SIZE = 10;
+
+    private double mThreshold;
+    private ScriptC_MSSIMComparer mScript;
+
+    public MSSIMComparer(double threshold) {
+        mThreshold = threshold;
+    }
+
+    @Override
+    public boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width,
+            int height) {
+        double SSIMTotal = 0;
+        int windows = 0;
+
+        for (int currentWindowY = 0 ; currentWindowY < height ; currentWindowY += WINDOW_SIZE) {
+            for (int currentWindowX = 0 ; currentWindowX < width ; currentWindowX += WINDOW_SIZE) {
+                int start = indexFromXAndY(currentWindowX, currentWindowY, stride, offset);
+                if (isWindowWhite(ideal, start, stride) && isWindowWhite(given, start, stride)) {
+                    continue;
+                }
+                windows++;
+                double[] means = getMeans(ideal, given, start, stride);
+                double meanX = means[0];
+                double meanY = means[1];
+                double[] variances = getVariances(ideal, given, meanX, meanY, start, stride);
+                double varX = variances[0];
+                double varY = variances[1];
+                double stdBoth = variances[2];
+                double SSIM = SSIM(meanX, meanY, varX, varY, stdBoth);
+                SSIMTotal += SSIM;
+            }
+        }
+
+        if (windows == 0) {
+            return true;
+        }
+
+        SSIMTotal /= windows;
+
+        Log.d(TAG_NAME, "MSSIM = " + SSIMTotal);
+
+        return (SSIMTotal >= mThreshold);
+    }
+
+    @Override
+    public boolean verifySameRowsRS(Resources resources, Allocation ideal,
+            Allocation given, int offset, int stride, int width, int height,
+            RenderScript renderScript, Allocation inputAllocation, Allocation outputAllocation) {
+        if (mScript == null) {
+            mScript = new ScriptC_MSSIMComparer(renderScript);
+        }
+        mScript.set_WIDTH(width);
+        mScript.set_HEIGHT(height);
+
+        //Set the bitmap allocations
+        mScript.set_ideal(ideal);
+        mScript.set_given(given);
+
+        //Call the renderscript function on each row
+        mScript.forEach_calcSSIM(inputAllocation, outputAllocation);
+
+        float MSSIM = sum1DFloatAllocation(outputAllocation);
+        MSSIM /= height;
+
+        Log.d(TAG_NAME, "MSSIM RS : " + MSSIM);
+
+        return (MSSIM >= mThreshold);
+    }
+
+    private boolean isWindowWhite(int[] colors, int start, int stride) {
+        for (int y = 0 ; y < WINDOW_SIZE ; y++) {
+            for (int x = 0 ; x < WINDOW_SIZE ; x++) {
+                if (colors[indexFromXAndY(x, y, stride, start)] != Color.WHITE) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    private double SSIM(double muX, double muY, double sigX, double sigY, double sigXY) {
+        double SSIM = (((2 * muX * muY) + CONSTANT_C1) * ((2 * sigXY) + CONSTANT_C2));
+        double denom = ((muX * muX) + (muY * muY) + CONSTANT_C1)
+                * (sigX + sigY + CONSTANT_C2);
+        SSIM /= denom;
+        return SSIM;
+    }
+
+
+    /**
+     * This method will find the mean of a window in both sets of pixels. The return is an array
+     * where the first double is the mean of the first set and the second double is the mean of the
+     * second set.
+     */
+    private double[] getMeans(int[] pixels0, int[] pixels1, int start, int stride) {
+        double avg0 = 0;
+        double avg1 = 0;
+        for (int y = 0 ; y < WINDOW_SIZE ; y++) {
+            for (int x = 0 ; x < WINDOW_SIZE ; x++) {
+                int index = indexFromXAndY(x, y, stride, start);
+                avg0 += getIntensity(pixels0[index]);
+                avg1 += getIntensity(pixels1[index]);
+            }
+        }
+        avg0 /= WINDOW_SIZE * WINDOW_SIZE;
+        avg1 /= WINDOW_SIZE * WINDOW_SIZE;
+        return new double[] {avg0, avg1};
+    }
+
+    /**
+     * Finds the variance of the two sets of pixels, as well as the covariance of the windows. The
+     * return value is an array of doubles, the first is the variance of the first set of pixels,
+     * the second is the variance of the second set of pixels, and the third is the covariance.
+     */
+    private double[] getVariances(int[] pixels0, int[] pixels1, double mean0, double mean1,
+            int start, int stride) {
+        double var0 = 0;
+        double var1 = 0;
+        double varBoth = 0;
+        for (int y = 0 ; y < WINDOW_SIZE ; y++) {
+            for (int x = 0 ; x < WINDOW_SIZE ; x++) {
+                int index = indexFromXAndY(x, y, stride, start);
+                double v0 = getIntensity(pixels0[index]) - mean0;
+                double v1 = getIntensity(pixels1[index]) - mean1;
+                var0 += v0 * v0;
+                var1 += v1 * v1;
+                varBoth += v0 * v1;
+            }
+        }
+        var0 /= (WINDOW_SIZE * WINDOW_SIZE) - 1;
+        var1 /= (WINDOW_SIZE * WINDOW_SIZE) - 1;
+        varBoth /= (WINDOW_SIZE * WINDOW_SIZE) - 1;
+        return new double[] {var0, var1, varBoth};
+    }
+
+    /**
+     * Gets the intensity of a given pixel in RGB using luminosity formula
+     *
+     * l = 0.21R' + 0.72G' + 0.07B'
+     *
+     * The prime symbols dictate a gamma correction of 1.
+     */
+    private double getIntensity(int pixel) {
+        final double gamma = 1;
+        double l = 0;
+        l += (0.21f * Math.pow(Color.red(pixel) / 255f, gamma));
+        l += (0.72f * Math.pow(Color.green(pixel) / 255f, gamma));
+        l += (0.07f * Math.pow(Color.blue(pixel) / 255f, gamma));
+        return l;
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MSSIMComparer.rs b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MSSIMComparer.rs
new file mode 100644
index 0000000..4d8c41b8
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MSSIMComparer.rs
@@ -0,0 +1,66 @@
+#pragma version(1)
+#pragma rs java_package_name(com.android.cts.uirendering)
+
+int WIDTH;
+int HEIGHT;
+
+rs_allocation ideal;
+rs_allocation given;
+
+static float getPixelWeight(uchar4 pixel) {
+    const float MAX_VALUE_COLOR = 255;
+    const float RED_WEIGHT = 0.21f / MAX_VALUE_COLOR;
+    const float GREEN_WEIGHT = 0.72f / MAX_VALUE_COLOR;
+    const float BLUE_WEIGHT = 0.07f / MAX_VALUE_COLOR;
+    return (pixel.r * RED_WEIGHT) + (pixel.g * GREEN_WEIGHT) + (pixel.b * BLUE_WEIGHT);
+}
+
+// Calculates SSIM of a row of pixels
+void calcSSIM(const int32_t *v_in, float *v_out) {
+    // TODO Test values for these constants
+    const float C1 = 0.0000064516;
+    const float C2 = 0.0000580644;
+
+    int y = v_in[0];
+    v_out[0] = 0;
+
+    float meanIdeal = 0;
+    float meanGiven = 0;
+
+    for (int i = 0 ; i < WIDTH ; i++) {
+        uchar4 idealPixel = rsGetElementAt_uchar4(ideal, i, y);
+        uchar4 givenPixel = rsGetElementAt_uchar4(given, i, y);
+        meanIdeal += getPixelWeight(idealPixel);
+        meanGiven += getPixelWeight(givenPixel);
+    }
+
+    meanIdeal /= WIDTH;
+    meanGiven /= WIDTH;
+
+    float varIdeal = 0;
+    float varGiven = 0;
+    float varBoth = 0;
+
+    for (int i = 0 ; i < WIDTH ; i++) {
+        uchar4 idealPixel = rsGetElementAt_uchar4(ideal, i, y);
+        uchar4 givenPixel = rsGetElementAt_uchar4(given, i, y);
+        float idealWeight = getPixelWeight(idealPixel);
+        float givenWeight = getPixelWeight(givenPixel);
+        idealWeight -= meanIdeal;
+        givenWeight -= meanGiven;
+        varIdeal +=  idealWeight * idealWeight;
+        varGiven += givenWeight * givenWeight;
+        varBoth += idealWeight * givenWeight;
+    }
+
+    varIdeal /= WIDTH - 1;
+    varGiven /= WIDTH - 1;
+    varBoth /= WIDTH - 1;
+
+    float SSIM = ((2 * meanIdeal * meanGiven) + C1) * ((2 * varBoth) + C2);
+    float denom = ((meanIdeal * meanIdeal) + (meanGiven * meanGiven) + C1)
+                    * (varIdeal + varGiven + C2);
+    SSIM /= denom;
+
+    v_out[0] = SSIM;
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MeanSquaredComparer.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MeanSquaredComparer.java
new file mode 100644
index 0000000..cc2fbba
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MeanSquaredComparer.java
@@ -0,0 +1,102 @@
+/*
+ * 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.uirendering.cts.bitmapcomparers;
+
+import com.android.cts.uirendering.R;
+import com.android.cts.uirendering.ScriptC_MeanSquaredComparer;
+
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.renderscript.Allocation;
+import android.renderscript.RenderScript;
+import android.util.Log;
+
+/**
+ * Finds the MSE using two images.
+ */
+public class MeanSquaredComparer extends BaseRenderScriptComparer {
+    private static final String TAG = "MeanSquared";
+    private ScriptC_MeanSquaredComparer mScript;
+    private float mErrorPerPixel;
+
+    /**
+     * @param errorPerPixel threshold for which the test will pass/fail. This is the mean-squared
+     *                      error averaged across all of those before comparing.
+     */
+    public MeanSquaredComparer(float errorPerPixel) {
+        mErrorPerPixel = errorPerPixel;
+    }
+
+    @Override
+    public boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width,
+            int height) {
+        float totalError = getMSE(ideal, given, offset, stride, width, height);
+        Log.d(TAG, "Error : " + totalError);
+        return (totalError < (mErrorPerPixel));
+    }
+
+    @Override
+    public boolean verifySameRowsRS(Resources resources, Allocation ideal,
+            Allocation given, int offset, int stride, int width, int height,
+            RenderScript renderScript, Allocation inputAllocation, Allocation outputAllocation) {
+        if (mScript == null) {
+            mScript = new ScriptC_MeanSquaredComparer(renderScript);
+        }
+        mScript.set_WIDTH(width);
+
+        //Set the bitmap allocations
+        mScript.set_ideal(ideal);
+        mScript.set_given(given);
+
+        //Call the renderscript function on each row
+        mScript.forEach_calcMSE(inputAllocation, outputAllocation);
+
+        float error = sum1DFloatAllocation(outputAllocation);
+        error /= (height * width);
+
+        Log.d(TAG, "Error RS : " + error);
+
+        return (error < mErrorPerPixel);
+    }
+
+    /**
+     * Gets the Mean Squared Error between two data sets.
+     */
+    public static float getMSE(int[] ideal, int[] given, int offset, int stride, int width,
+            int height) {
+        float totalError = 0;
+
+        for (int y = 0 ; y < height ; y++) {
+            for (int x = 0 ; x < width ; x++) {
+                int index = indexFromXAndY(x, y, stride, offset);
+                float idealSum = getColorSum(ideal[index]);
+                float givenSum = getColorSum(given[index]);
+                float difference = idealSum - givenSum;
+                totalError += (difference * difference);
+            }
+        }
+
+        totalError /= (width * height);
+        return totalError;
+    }
+
+    private static float getColorSum(int color) {
+        float red = Color.red(color) / 255.0f;
+        float green = Color.green(color) / 255.0f;
+        float blue = Color.blue(color) / 255.0f;
+        return (red + green + blue);
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MeanSquaredComparer.rs b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MeanSquaredComparer.rs
new file mode 100644
index 0000000..b37ad13
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/MeanSquaredComparer.rs
@@ -0,0 +1,21 @@
+#pragma version(1)
+#pragma rs java_package_name(com.android.cts.uirendering)
+
+int REGION_SIZE;
+int WIDTH;
+
+rs_allocation ideal;
+rs_allocation given;
+
+// This method does a threshold comparison of the values
+void calcMSE(const int32_t *v_in, float *v_out){
+    int y = v_in[0];
+    v_out[0] = 0.0f;
+    for (int x = 0 ; x < WIDTH ; x++) {
+        float4 idealFloats = rsUnpackColor8888(rsGetElementAt_uchar4(ideal, x, y));
+        float4 givenFloats = rsUnpackColor8888(rsGetElementAt_uchar4(given, x, y));
+        float difference = (idealFloats.r - givenFloats.r) + (idealFloats.g - givenFloats.g) +
+              (idealFloats.b - givenFloats.b);
+        v_out[0] += (difference * difference);
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/NearPixelComparer.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/NearPixelComparer.java
new file mode 100644
index 0000000..bfb2c77
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/NearPixelComparer.java
@@ -0,0 +1,66 @@
+/*
+ * 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.uirendering.cts.bitmapcomparers;
+
+import android.graphics.Color;
+import android.util.Log;
+
+/**
+ * Checks to see that a pixel at a given location is the same as the corresponding pixel. If the
+ * pixel is different, it checks the pixels around it to see if it is the same.
+ */
+public class NearPixelComparer extends BitmapComparer {
+    private static final String TAG = "NearPixelComparer";
+    private static final int THRESHOLD = 10;
+    private static final int NEAR_PIXEL_RADIUS = 1;
+
+    @Override
+    public boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width,
+            int height) {
+        for (int y = 0 ; y < height ; y++) {
+            for (int x = 0 ; x < width ; x++) {
+                boolean success = false;
+
+                // we need to check the surrounding pixels
+                for (int dx = -NEAR_PIXEL_RADIUS ; dx <= NEAR_PIXEL_RADIUS ; dx++) {
+                    for (int dy = -NEAR_PIXEL_RADIUS ; dy <= NEAR_PIXEL_RADIUS ; dy++) {
+                        // need to be sure we don't hit pixels that aren't there
+                        if (x + dx >= width || x + dx < 0 || y + dy >= height || y + dy < 0) {
+                            continue;
+                        }
+                        int index = indexFromXAndY(x + dx, y + dy, stride, offset);
+                        if (!pixelsAreSame(ideal[index], given[index])) {
+                            success = true;
+                            break;
+                        }
+                    }
+                }
+                if (!success) {
+                    Log.d(TAG, "Failure at pixel (" + x + "," + y + ")");
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    private boolean pixelsAreSame(int ideal, int given) {
+        int error = Math.abs(Color.red(ideal) - Color.red(given));
+        error += Math.abs(Color.green(ideal) - Color.green(given));
+        error += Math.abs(Color.blue(ideal) - Color.blue(given));
+        return (error < THRESHOLD);
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/PSNRComparer.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/PSNRComparer.java
new file mode 100644
index 0000000..a38a381
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/PSNRComparer.java
@@ -0,0 +1,91 @@
+/*
+ * 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.uirendering.cts.bitmapcomparers;
+
+import android.graphics.Color;
+import android.util.Log;
+
+/**
+ * Uses the Peak Signal-to-Noise Ratio approach to determine if two images are considered the same.
+ */
+public class PSNRComparer extends BitmapComparer {
+    private static final String TAG = "PSNR";
+    private final float MAX = 255;
+    private final int REGION_SIZE = 10;
+
+    private float mThreshold;
+
+    /**
+     * @param threshold the PSNR necessary to pass the test, if the calculated PSNR is below this
+     *                  value, then the test will fail.
+     */
+    public PSNRComparer(float threshold) {
+        mThreshold = threshold;
+    }
+
+    @Override
+    public boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width,
+            int height) {
+        float MSE = 0f;
+        int interestingRegions = 0;
+        for (int y = 0 ; y < height ; y += REGION_SIZE) {
+            for (int x = 0 ; x < width ; x += REGION_SIZE) {
+                int index = indexFromXAndY(x, y, stride, offset);
+                if (inspectRegion(ideal, index)) {
+                    interestingRegions++;
+                }
+            }
+        }
+
+        if (interestingRegions == 0) {
+            return true;
+        }
+
+        for (int y = 0 ; y < height ; y += REGION_SIZE) {
+            for (int x = 0 ; x < width ; x += REGION_SIZE) {
+                int index = indexFromXAndY(x, y, stride, offset);
+                if (ideal[index] == given[index]) {
+                    continue;
+                }
+                MSE += (Color.red(ideal[index]) - Color.red(given[index])) *
+                        (Color.red(ideal[index]) - Color.red(given[index]));
+                MSE += (Color.blue(ideal[index]) - Color.blue(given[index])) *
+                        (Color.blue(ideal[index]) - Color.blue(given[index]));
+                MSE += (Color.green(ideal[index]) - Color.green(given[index])) *
+                        (Color.green(ideal[index]) - Color.green(given[index]));
+            }
+        }
+        MSE /= (interestingRegions * REGION_SIZE * 3);
+
+        float fraction = (MAX * MAX) / MSE;
+        fraction = (float) Math.log(fraction);
+        fraction *= 10;
+
+        Log.d(TAG, "PSNR : " + fraction);
+
+        return (fraction > mThreshold);
+    }
+
+    private boolean inspectRegion(int[] ideal, int index) {
+        int regionColor = ideal[index];
+        for (int i = 0 ; i < REGION_SIZE ; i++) {
+            if (regionColor != ideal[index + i]) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/PassComparer.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/PassComparer.java
new file mode 100644
index 0000000..79923cd
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/PassComparer.java
@@ -0,0 +1,27 @@
+/*
+ * 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.uirendering.cts.bitmapcomparers;
+
+/**
+ * This class is purely for debug purposes. It will automatically pass any tests.
+ */
+public class PassComparer extends BitmapComparer {
+    @Override
+    public boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width,
+            int height) {
+        return true;
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ThresholdDifferenceComparer.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ThresholdDifferenceComparer.java
new file mode 100644
index 0000000..f8304ba
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ThresholdDifferenceComparer.java
@@ -0,0 +1,89 @@
+/*
+ * 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.uirendering.cts.bitmapcomparers;
+
+import com.android.cts.uirendering.R;
+import com.android.cts.uirendering.ScriptC_ThresholdDifferenceComparer;
+
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.renderscript.Allocation;
+import android.renderscript.RenderScript;
+import android.uirendering.cts.bitmapcomparers.BaseRenderScriptComparer;
+import android.util.Log;
+
+/**
+ * Compares two images to see if each pixel is the same, within a certain threshold value
+ */
+public class ThresholdDifferenceComparer extends BaseRenderScriptComparer {
+    private static final String TAG = "ThresholdDifference";
+    private ScriptC_ThresholdDifferenceComparer mScript;
+    private int mThreshold;
+
+    /**
+     * @param threshold Each pixel is compared against each other, in each of the individual
+     *                  channels. If the sum of the errors amongst the channels is greater than some
+     *                  threshold, then this test will fail.
+     */
+    public ThresholdDifferenceComparer(int threshold) {
+        mThreshold = threshold;
+    }
+
+    @Override
+    public boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width,
+            int height) {
+        int differentPixels = 0;
+        for (int y = 0 ; y < height ; y++) {
+            for (int x = 0 ; x < width ; x++) {
+                int index = indexFromXAndY(x, y, stride, offset);
+                int error = Math.abs(Color.red(ideal[index]) - Color.red(given[index]));
+                error += Math.abs(Color.blue(ideal[index]) - Color.blue(given[index]));
+                error += Math.abs(Color.green(ideal[index]) - Color.green(given[index]));
+                if (error > mThreshold) {
+                    Log.d(TAG, "Failure at position x = " + x + " y = " + y);
+                    Log.d(TAG, "Expected color " + Integer.toHexString(ideal[index]) +
+                            " given color " + Integer.toHexString(given[index]));
+                    differentPixels++;
+                }
+            }
+        }
+        Log.d(TAG, "Number of different pixels : " + differentPixels);
+        return (differentPixels == 0);
+    }
+
+    @Override
+    public boolean verifySameRowsRS(Resources resources, Allocation ideal,
+            Allocation given, int offset, int stride, int width, int height,
+            RenderScript renderScript, Allocation inputAllocation, Allocation outputAllocation) {
+        if (mScript == null) {
+            mScript = new ScriptC_ThresholdDifferenceComparer(renderScript);
+        }
+
+        mScript.set_THRESHOLD(mThreshold);
+        mScript.set_WIDTH(width);
+
+        //Set the bitmap allocations
+        mScript.set_ideal(ideal);
+        mScript.set_given(given);
+
+        //Call the renderscript function on each row
+        mScript.forEach_thresholdCompare(inputAllocation, outputAllocation);
+
+        float differentPixels = sum1DFloatAllocation(outputAllocation);
+        Log.d(TAG, "Number of different pixels RS : " + differentPixels);
+        return (differentPixels == 0);
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ThresholdDifferenceComparer.rs b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ThresholdDifferenceComparer.rs
new file mode 100644
index 0000000..de1a129
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/ThresholdDifferenceComparer.rs
@@ -0,0 +1,25 @@
+#pragma version(1)
+#pragma rs java_package_name(com.android.cts.uirendering)
+
+int WIDTH;
+int THRESHOLD;
+
+rs_allocation ideal;
+rs_allocation given;
+
+// This method does a threshold comparison of the values
+void thresholdCompare(const int32_t *v_in, float *v_out){
+    int y = v_in[0];
+    v_out[0] = 0;
+
+    for(int i = 0 ; i < WIDTH ; i ++){
+        uchar4 idealPixel = rsGetElementAt_uchar4(ideal, i, y);
+        uchar4 givenPixel = rsGetElementAt_uchar4(given, i, y);
+        float l1 = (idealPixel.x * 0.21f) + (idealPixel.y * 0.72f) + (idealPixel.z * 0.07f);
+        float l2 = (givenPixel.x * 0.21f) + (givenPixel.y * 0.72f) + (givenPixel.z * 0.07f);
+        float diff = l1 - l2;
+        if (fabs(diff) >= THRESHOLD) {
+            v_out[0]++;
+        }
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/WeightedPixelDifference.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/WeightedPixelDifference.java
new file mode 100644
index 0000000..f243c29
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapcomparers/WeightedPixelDifference.java
@@ -0,0 +1,108 @@
+/*
+ * 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.uirendering.cts.bitmapcomparers;
+
+import android.graphics.Color;
+import android.util.Log;
+
+/**
+ * This class contains methods to add the error amongst all pixels in two images while taking into
+ * account the number of pixels that are non-white. Note only use this if the content background is
+ * white.
+ */
+public class WeightedPixelDifference extends BitmapComparer {
+    private static final String TAG = "WeightedPixel";
+    private static final int NUM_OF_COLUMNS = 10;
+    private static final float TOTAL_ERROR_DIVISOR = 1024.0f;
+
+    private float mThreshold;
+
+    public WeightedPixelDifference(float threshold) {
+        mThreshold = threshold;
+    }
+
+    /**
+     * Calculates if pixels in a specific line are the same color
+     * @return true if the pixels are the same color
+     */
+    private static boolean inspectRegions(int[] ideal, int start, int stride, int regionSize) {
+        int regionColor = ideal[start];
+        for (int y = 0 ; y < regionSize ; y++) {
+            for (int x = 0 ; x < regionSize ; x++) {
+                int index = indexFromXAndY(x, y, stride, start);
+                if (ideal[index] != regionColor) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Finds the error between each individual channel in the color.
+     */
+    private static float errorBetweenPixels(int color1, int color2) {
+        float error = 0f;
+        error += Math.abs(Color.red(color1) - Color.red(color2));
+        error += Math.abs(Color.green(color1) - Color.green(color2));
+        error += Math.abs(Color.blue(color1) - Color.blue(color2));
+        error += Math.abs(Color.alpha(color1) - Color.alpha(color2));
+        return error;
+    }
+
+    /**
+     * Calculates the error between the pixels in the ideal and given
+     * @return true if the accumulated error is smaller than the threshold
+     */
+    @Override
+    public boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width,
+            int height) {
+        int interestingRegions = 0;
+        int regionSize = width / NUM_OF_COLUMNS;
+
+        for (int y = 0 ; y < height ; y += regionSize) {
+            for (int x = 0 ; x < width ; x += regionSize) {
+                int index = indexFromXAndY(x, y,stride, offset);
+                if (inspectRegions(ideal, index, stride, regionSize)) {
+                    interestingRegions++;
+                }
+            }
+        }
+
+        int interestingPixels = Math.max(1, interestingRegions) * regionSize * regionSize;
+
+        float totalError = 0;
+
+        for (int y = 0 ; y < height ; y++) {
+            for (int x = 0 ; x < width ; x++) {
+                int index = indexFromXAndY(x, y, stride, offset);
+                int idealColor = ideal[index];
+                int givenColor = given[index];
+                if (idealColor == givenColor) {
+                    continue;
+                }
+                totalError += errorBetweenPixels(idealColor, givenColor);
+            }
+        }
+
+        totalError /= TOTAL_ERROR_DIVISOR;
+        totalError /= interestingPixels;
+
+        Log.d(TAG, "Total error : " + totalError);
+
+        return totalError < mThreshold;
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/BitmapVerifier.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/BitmapVerifier.java
new file mode 100644
index 0000000..2f7acd5
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/BitmapVerifier.java
@@ -0,0 +1,45 @@
+/*
+ * 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.uirendering.cts.bitmapverifiers;
+
+import android.graphics.Bitmap;
+import android.graphics.Color;
+
+/**
+ * Checks to see if a Bitmap follows the algorithm provided by the verifier
+ */
+public abstract class BitmapVerifier {
+    protected static final int PASS_COLOR = Color.WHITE;
+    protected static final int FAIL_COLOR = Color.RED;
+
+    protected Bitmap mDifferenceBitmap;
+
+    /**
+     * This will test if the bitmap is good or not.
+     */
+    public abstract boolean verify(int[] bitmap, int offset, int stride, int width, int height);
+
+    /**
+     * This calculates the position in an array that would represent a bitmap given the parameters.
+     */
+    protected static int indexFromXAndY(int x, int y, int stride, int offset) {
+        return x + (y * stride) + offset;
+    }
+
+    public Bitmap getDifferenceBitmap() {
+        return mDifferenceBitmap;
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/ColorVerifier.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/ColorVerifier.java
new file mode 100644
index 0000000..ea836ea
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/ColorVerifier.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.uirendering.cts.bitmapverifiers;
+
+/**
+ * Checks to see if a bitmap is entirely a single color
+ */
+public class ColorVerifier extends PerPixelBitmapVerifier {
+    private int mColor;
+
+    public ColorVerifier(int color) {
+        this(color, 20);
+    }
+
+    public ColorVerifier(int color, int threshold) {
+        super(threshold);
+        mColor = color;
+    }
+
+    @Override
+    protected int getExpectedColor(int x, int y) {
+        return mColor;
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/GoldenImageVerifier.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/GoldenImageVerifier.java
new file mode 100644
index 0000000..672b3f6
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/GoldenImageVerifier.java
@@ -0,0 +1,44 @@
+/*
+ * 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.uirendering.cts.bitmapverifiers;
+
+import android.graphics.Bitmap;
+import android.uirendering.cts.bitmapcomparers.BitmapComparer;
+import android.uirendering.cts.differencevisualizers.PassFailVisualizer;
+
+public class GoldenImageVerifier extends BitmapVerifier {
+    private BitmapComparer mBitmapComparer;
+    private int[] mGoldenBitmapArray;
+
+    public GoldenImageVerifier(Bitmap goldenBitmap, BitmapComparer bitmapComparer) {
+        mGoldenBitmapArray = new int[goldenBitmap.getWidth() * goldenBitmap.getHeight()];
+        goldenBitmap.getPixels(mGoldenBitmapArray, 0, goldenBitmap.getWidth(), 0, 0,
+                goldenBitmap.getWidth(), goldenBitmap.getHeight());
+        mBitmapComparer = bitmapComparer;
+    }
+
+    @Override
+    public boolean verify(int[] bitmap, int offset, int stride, int width, int height) {
+        boolean success = mBitmapComparer.verifySame(mGoldenBitmapArray, bitmap, offset, stride,
+                width, height);
+        if (!success) {
+            mDifferenceBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+            int[] differences = new PassFailVisualizer().getDifferences(mGoldenBitmapArray, bitmap);
+            mDifferenceBitmap.setPixels(differences, 0, width, 0, 0, width, height);
+        }
+        return success;
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/InvertVerifier.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/InvertVerifier.java
new file mode 100644
index 0000000..fe0db96
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/InvertVerifier.java
@@ -0,0 +1,34 @@
+/*
+ * 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.uirendering.cts.bitmapverifiers;
+
+/**
+ * Used when the tester wants to find the opposite result from a Verifier
+ */
+public class InvertVerifier extends BitmapVerifier {
+    private BitmapVerifier mBitmapVerifier;
+
+    public InvertVerifier(BitmapVerifier bitmapVerifier) {
+        mBitmapVerifier = bitmapVerifier;
+    }
+
+    @Override
+    public boolean verify(int[] bitmap, int offset, int stride, int width, int height) {
+        boolean success = mBitmapVerifier.verify(bitmap, offset, stride, width, height);
+        mDifferenceBitmap = mBitmapVerifier.getDifferenceBitmap();
+        return !success;
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/PerPixelBitmapVerifier.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/PerPixelBitmapVerifier.java
new file mode 100644
index 0000000..ab809f4
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/PerPixelBitmapVerifier.java
@@ -0,0 +1,70 @@
+/*
+ * 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.uirendering.cts.bitmapverifiers;
+
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.uirendering.cts.testinfrastructure.ActivityTestBase;
+import android.uirendering.cts.util.CompareUtils;
+import android.util.Log;
+
+/**
+ * This class looks at every pixel in a given bitmap and verifies that it is correct.
+ */
+public abstract class PerPixelBitmapVerifier extends BitmapVerifier {
+    private static final String TAG = "PerPixelBitmapVerifer";
+    private int mTolerance;
+
+    public PerPixelBitmapVerifier(int tolerance) {
+        mTolerance = tolerance;
+    }
+
+    protected int getExpectedColor(int x, int y) {
+        return Color.WHITE;
+    }
+
+
+    public boolean verify(int[] bitmap, int offset, int stride, int width, int height) {
+        boolean res = true;
+        int[] differenceMap = new int[bitmap.length];
+        for (int y = 0 ; y < height ; y++) {
+            for (int x = 0 ; x < width ; x++) {
+                int index = indexFromXAndY(x, y, stride, offset);
+                int expectedColor = getExpectedColor(x, y);
+                if (!verifyPixel(bitmap[index], expectedColor)) {
+                    Log.d(TAG, "Expected : " + Integer.toHexString(expectedColor)
+                            + " received : " + Integer.toHexString(bitmap[index])
+                            + " at position (" + x + "," + y + ")");
+                    res = false;
+                    differenceMap[index] = FAIL_COLOR;
+                } else {
+                    differenceMap[index] = PASS_COLOR;
+                }
+            }
+        }
+        if (!res) {
+            mDifferenceBitmap = Bitmap.createBitmap(ActivityTestBase.TEST_WIDTH,
+                    ActivityTestBase.TEST_HEIGHT, Bitmap.Config.ARGB_8888);
+            mDifferenceBitmap.setPixels(differenceMap, offset, stride, 0, 0,
+                    ActivityTestBase.TEST_WIDTH, ActivityTestBase.TEST_HEIGHT);
+        }
+        return res;
+    }
+
+    protected boolean verifyPixel(int color, int expectedColor) {
+        return CompareUtils.verifyPixelWithThreshold(color, expectedColor, mTolerance);
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/RectVerifier.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/RectVerifier.java
new file mode 100644
index 0000000..06a430b
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/RectVerifier.java
@@ -0,0 +1,43 @@
+/*
+ * 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.uirendering.cts.bitmapverifiers;
+
+import android.graphics.Rect;
+
+/**
+ * Tests to see if there is rectangle of a certain color, with a background given
+ */
+public class RectVerifier extends PerPixelBitmapVerifier {
+    private int mOuterColor;
+    private int mInnerColor;
+    private Rect mInnerRect;
+
+    public RectVerifier(int outerColor, int innerColor, Rect innerRect) {
+        this(outerColor, innerColor, innerRect, 20);
+    }
+
+    public RectVerifier(int outerColor, int innerColor, Rect innerRect, int tolerance) {
+        super(tolerance);
+        mOuterColor = outerColor;
+        mInnerColor = innerColor;
+        mInnerRect = innerRect;
+    }
+
+    @Override
+    protected int getExpectedColor(int x, int y) {
+        return mInnerRect.contains(x, y) ? mInnerColor : mOuterColor;
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/SamplePointVerifier.java b/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/SamplePointVerifier.java
new file mode 100644
index 0000000..cb62694
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/bitmapverifiers/SamplePointVerifier.java
@@ -0,0 +1,71 @@
+/*
+ * 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.uirendering.cts.bitmapverifiers;
+
+import android.graphics.Bitmap;
+import android.graphics.Point;
+import android.uirendering.cts.testinfrastructure.ActivityTestBase;
+import android.uirendering.cts.util.CompareUtils;
+import android.util.Log;
+
+import java.util.Arrays;
+
+/**
+ * This class will test specific points, and ensure that they match up perfectly with the input colors
+ */
+public class SamplePointVerifier extends BitmapVerifier {
+    private static final String TAG = "SamplePoint";
+    private Point[] mTestPoints;
+    private int[] mExpectedColors;
+    private int mTolerance = 20;
+
+    public SamplePointVerifier(Point[] testPoints, int[] expectedColors) {
+        mTestPoints = testPoints;
+        mExpectedColors = expectedColors;
+    }
+
+    @Override
+    public boolean verify(int[] bitmap, int offset, int stride, int width, int height) {
+        boolean success = true;
+        int[] differenceMap = new int[bitmap.length];
+        Arrays.fill(differenceMap, PASS_COLOR);
+        for (int i = 0 ; i < mTestPoints.length ; i++) {
+            int x = mTestPoints[i].x;
+            int y = mTestPoints[i].y;
+            int index = indexFromXAndY(x, y, stride, offset);
+            if (!verifyPixel(bitmap[index], mExpectedColors[i])) {
+                Log.d(TAG, "Expected : " + Integer.toHexString(mExpectedColors[i]) +
+                        " at position x = " + x + " y = " + y + " , tested color : " +
+                        Integer.toHexString(bitmap[index]));
+                differenceMap[index] = FAIL_COLOR;
+                success = false;
+            } else {
+                differenceMap[index] = PASS_COLOR;
+            }
+        }
+        if (!success) {
+            mDifferenceBitmap = Bitmap.createBitmap(ActivityTestBase.TEST_WIDTH,
+                    ActivityTestBase.TEST_HEIGHT, Bitmap.Config.ARGB_8888);
+            mDifferenceBitmap.setPixels(differenceMap, offset, stride, 0, 0,
+                    ActivityTestBase.TEST_WIDTH, ActivityTestBase.TEST_HEIGHT);
+        }
+        return success;
+    }
+
+    protected boolean verifyPixel(int color, int expectedColor) {
+        return CompareUtils.verifyPixelWithThreshold(color, expectedColor, mTolerance);
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/differencevisualizers/DifferenceVisualizer.java b/tests/tests/uirendering/src/android/uirendering/cts/differencevisualizers/DifferenceVisualizer.java
new file mode 100644
index 0000000..348a1c0
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/differencevisualizers/DifferenceVisualizer.java
@@ -0,0 +1,23 @@
+/*
+ * 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.uirendering.cts.differencevisualizers;
+
+/**
+ * This class can be extended by the tester, to allow for various ways to debug.
+ */
+public abstract class DifferenceVisualizer {
+    public abstract int[] getDifferences(int[] ideal, int[] given);
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/differencevisualizers/PassFailVisualizer.java b/tests/tests/uirendering/src/android/uirendering/cts/differencevisualizers/PassFailVisualizer.java
new file mode 100644
index 0000000..7641519
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/differencevisualizers/PassFailVisualizer.java
@@ -0,0 +1,41 @@
+/*
+ * 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.uirendering.cts.differencevisualizers;
+
+import android.graphics.Color;
+
+/**
+ * This class creates difference maps that show which pixels were correct, and which weren't
+ */
+public class PassFailVisualizer extends DifferenceVisualizer {
+    /**
+     * This method will return a bitmap where white is same red is different
+     * @param ideal the desired result
+     * @param given the produced result
+     */
+    @Override
+    public int[] getDifferences(int[] ideal, int[] given) {
+        int[] output = new int[ideal.length];
+        for (int y = 0; y < output.length; y++) {
+            if (ideal[y] == given[y]) {
+                output[y] = Color.WHITE;
+            } else {
+                output[y] = Color.RED;
+            }
+        }
+        return output;
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapFilterTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapFilterTests.java
new file mode 100644
index 0000000..ddae100
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapFilterTests.java
@@ -0,0 +1,125 @@
+/*
+ * 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.uirendering.cts.testclasses;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PaintFlagsDrawFilter;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.uirendering.cts.bitmapverifiers.BitmapVerifier;
+import android.uirendering.cts.bitmapverifiers.ColorVerifier;
+import android.uirendering.cts.bitmapverifiers.PerPixelBitmapVerifier;
+import android.uirendering.cts.testinfrastructure.ActivityTestBase;
+import android.uirendering.cts.testinfrastructure.CanvasClient;
+
+public class BitmapFilterTests extends ActivityTestBase {
+    private static final int THRESHOLD = 20;
+    private static final int WHITE_WEIGHT = 255 * 3;
+    private enum FilterEnum {
+        // Creates Paint object that will have bitmap filtering
+        PAINT_FILTER,
+        // First uses a Paint object with bitmap filtering, then uses canvas.setDrawFilter to remove
+        // the bitmap filtering
+        REMOVE_FILTER,
+        // Sets DrawFilter to use Paint.FILTER_BITMAP_FLAG
+        ADD_FILTER
+    }
+
+    /**
+     * Verifies that a Bitmap only contains white and black, within a certain threshold
+     */
+    private static BitmapVerifier mBlackWhiteVerifier = new PerPixelBitmapVerifier(THRESHOLD) {
+        @Override
+        protected boolean verifyPixel(int color, int expectedColor) {
+            int weight = Color.red(color) + Color.blue(color) + Color.green(color);
+            return weight < THRESHOLD // is approx Color.BLACK
+                    || weight > WHITE_WEIGHT - THRESHOLD; // is approx Color.WHITE
+        }
+    };
+
+    private static Bitmap createGridBitmap(int width, int height) {
+        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        for (int i = 0 ; i < width ; i++) {
+            for (int j = 0 ; j < height ; j++) {
+                bitmap.setPixel(i, j, ((i + j * width)) % 2 == 0 ?
+                        Color.WHITE : Color.BLACK);
+            }
+        }
+        return bitmap;
+    }
+
+    private static final int SMALL_GRID_SIZE = 5;
+    private static Bitmap mSmallGridBitmap = createGridBitmap(SMALL_GRID_SIZE, SMALL_GRID_SIZE);
+    private static final int BIG_GRID_SIZE = 360;
+    private static Bitmap mBigGridBitmap = createGridBitmap(BIG_GRID_SIZE, BIG_GRID_SIZE);
+    private static final int HALFWAY_COLOR = Color.argb(255, 127, 127, 127);
+
+    /* All of these tests seem to be broken.
+     * TODO: fix in L MR1
+    @SmallTest
+    public void testPaintFilterScaleUp() {
+        runScaleTest(FilterEnum.PAINT_FILTER, true, mBlackWhiteVerifier);
+    }
+
+    @SmallTest
+    public void testPaintFilterScaleDown() {
+        runScaleTest(FilterEnum.PAINT_FILTER, false, new ColorVerifier(HALFWAY_COLOR, 15));
+    }
+
+    @SmallTest
+    public void testDrawFilterRemoveFilterScaleUp() {
+        runScaleTest(FilterEnum.REMOVE_FILTER, true, mBlackWhiteVerifier);
+    }
+
+    @SmallTest
+    public void testDrawFilterRemoveFilterScaleDown() {
+        runScaleTest(FilterEnum.REMOVE_FILTER, false, mBlackWhiteVerifier);
+    }
+
+    @SmallTest
+    public void testDrawFilterScaleUp() {
+        runScaleTest(FilterEnum.ADD_FILTER, true, mBlackWhiteVerifier);
+    }
+
+    @SmallTest
+    public void testDrawFilterScaleDown() {
+        runScaleTest(FilterEnum.ADD_FILTER, false, new ColorVerifier(HALFWAY_COLOR));
+    }
+*/
+    private void runScaleTest(final FilterEnum filterEnum, final boolean scaleUp,
+            BitmapVerifier bitmapVerifier) {
+        final int gridWidth = scaleUp ? SMALL_GRID_SIZE : BIG_GRID_SIZE;
+        final Paint paint = new Paint(filterEnum.equals(FilterEnum.ADD_FILTER) ?
+                0 : Paint.FILTER_BITMAP_FLAG);
+        CanvasClient canvasClient = new CanvasClient() {
+            @Override
+            public void draw(Canvas canvas, int width, int height) {
+                canvas.scale(1.0f * width / gridWidth, 1.0f * height / gridWidth);
+                if (filterEnum.equals(FilterEnum.ADD_FILTER)) {
+                    canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.FILTER_BITMAP_FLAG));
+                } else if (filterEnum.equals(FilterEnum.REMOVE_FILTER)) {
+                    canvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.FILTER_BITMAP_FLAG, 0));
+                }
+                canvas.drawBitmap(scaleUp ? mSmallGridBitmap : mBigGridBitmap, 0, 0, paint);
+            }
+        };
+        createTest()
+                .addCanvasClient(canvasClient)
+                .runWithVerifier(bitmapVerifier);
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
new file mode 100644
index 0000000..3088142
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
@@ -0,0 +1,225 @@
+/*
+ * 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.uirendering.cts.testclasses;
+
+import com.android.cts.uirendering.R;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.graphics.drawable.NinePatchDrawable;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.uirendering.cts.bitmapcomparers.BitmapComparer;
+import android.uirendering.cts.bitmapcomparers.ExactComparer;
+import android.uirendering.cts.bitmapverifiers.BitmapVerifier;
+import android.uirendering.cts.bitmapverifiers.RectVerifier;
+import android.uirendering.cts.testinfrastructure.ActivityTestBase;
+import android.uirendering.cts.testinfrastructure.CanvasClient;
+import android.uirendering.cts.testinfrastructure.ViewInitializer;
+import android.view.View;
+
+public class ExactCanvasTests extends ActivityTestBase {
+    private final BitmapComparer mExactComparer = new ExactComparer();
+
+    @SmallTest
+    public void testBlueRect() {
+        final Rect rect = new Rect(10, 10, 100, 100);
+        createTest()
+                .addCanvasClient(new CanvasClient() {
+                    @Override
+                    public void draw(Canvas canvas, int width, int height) {
+                        Paint p = new Paint();
+                        p.setAntiAlias(false);
+                        p.setColor(Color.BLUE);
+                        canvas.drawRect(rect, p);
+                    }
+                })
+                .runWithVerifier(new RectVerifier(Color.WHITE, Color.BLUE, rect));
+    }
+
+    @SmallTest
+    public void testPoints() {
+        createTest()
+                .addCanvasClient(new CanvasClient() {
+                    @Override
+                    public void draw(Canvas canvas, int width, int height) {
+                        Paint p = new Paint();
+                        p.setAntiAlias(false);
+                        p.setColor(Color.WHITE);
+                        canvas.drawRect(0, 0, 100, 100, p);
+                        p.setStrokeWidth(1f);
+                        p.setColor(Color.BLACK);
+                        for (int i = 0; i < 10; i++) {
+                            canvas.drawPoint(i * 10, i * 10, p);
+                        }
+                    }
+                })
+                .runWithComparer(mExactComparer);
+    }
+
+    @SmallTest
+    public void testBlackRectWithStroke() {
+        createTest()
+                .addCanvasClient(new CanvasClient() {
+                    @Override
+                    public void draw(Canvas canvas, int width, int height) {
+                        Paint p = new Paint();
+                        p.setColor(Color.RED);
+                        canvas.drawRect(0, 0, ActivityTestBase.TEST_WIDTH,
+                                ActivityTestBase.TEST_HEIGHT, p);
+                        p.setColor(Color.BLACK);
+                        p.setStrokeWidth(10);
+                        canvas.drawRect(10, 10, 20, 20, p);
+                    }
+                })
+                .runWithComparer(mExactComparer);
+    }
+
+    @SmallTest
+    public void testBlackLineOnGreenBack() {
+        createTest()
+                .addCanvasClient(new CanvasClient() {
+                    @Override
+                    public void draw(Canvas canvas, int width, int height) {
+                        Paint p = new Paint();
+                        p.setColor(Color.GREEN);
+                        canvas.drawRect(0, 0, ActivityTestBase.TEST_WIDTH,
+                                ActivityTestBase.TEST_HEIGHT, p);
+                        p.setColor(Color.BLACK);
+                        p.setStrokeWidth(10);
+                        canvas.drawLine(0, 0, 50, 0, p);
+                    }
+                })
+                .runWithComparer(mExactComparer);
+    }
+
+    @SmallTest
+    public void testDrawRedRectOnBlueBack() {
+        createTest()
+                .addCanvasClient(new CanvasClient() {
+                    @Override
+                    public void draw(Canvas canvas, int width, int height) {
+                        canvas.drawColor(Color.BLUE);
+                        Paint p = new Paint();
+                        p.setColor(Color.RED);
+                        canvas.drawRect(10, 10, 40, 40, p);
+                    }
+                })
+                .runWithComparer(mExactComparer);
+    }
+
+    @SmallTest
+    public void testDrawLine() {
+        createTest()
+                .addCanvasClient(new CanvasClient() {
+                    @Override
+                    public void draw(Canvas canvas, int width, int height) {
+                        Paint p = new Paint();
+                        canvas.drawColor(Color.WHITE);
+                        p.setColor(Color.BLACK);
+                        float[] pts = {
+                                0, 0, 100, 100, 100, 0, 0, 100, 50, 50, 75, 75
+                        };
+                        canvas.drawLines(pts, p);
+                    }
+                })
+                .runWithComparer(mExactComparer);
+    }
+
+    @SmallTest
+    public void testDrawWhiteScreen() {
+        createTest()
+                .addCanvasClient(new CanvasClient() {
+                    @Override
+                    public void draw(Canvas canvas, int width, int height) {
+                        canvas.drawColor(Color.WHITE);
+                    }
+                })
+                .runWithComparer(mExactComparer);
+    }
+
+    @SmallTest
+    public void testBasicText() {
+        final String testString = "THIS IS A TEST";
+        createTest()
+                .addCanvasClient(new CanvasClient() {
+                    @Override
+                    public void draw(Canvas canvas, int width, int height) {
+                        Paint p = new Paint();
+                        canvas.drawColor(Color.BLACK);
+                        p.setColor(Color.WHITE);
+                        p.setStrokeWidth(5);
+                        canvas.drawText(testString, 30, 50, p);
+                    }
+                })
+                .runWithComparer(mExactComparer);
+    }
+
+    @SmallTest
+    public void testBasicColorXfermode() {
+        createTest()
+                .addCanvasClient(new CanvasClient() {
+                    @Override
+                    public void draw(Canvas canvas, int width, int height) {
+                        canvas.drawColor(Color.GRAY);
+                        canvas.drawColor(Color.BLUE, PorterDuff.Mode.MULTIPLY);
+                    }
+                })
+                .runWithComparer(mExactComparer);
+    }
+
+    @SmallTest
+    public void testBluePaddedSquare() {
+        final NinePatchDrawable ninePatchDrawable = (NinePatchDrawable)
+            getActivity().getResources().getDrawable(R.drawable.blue_padded_square);
+        ninePatchDrawable.setBounds(0, 0, 100, 100);
+
+        BitmapVerifier verifier = new RectVerifier(Color.WHITE, Color.BLUE,
+                new Rect(10, 10, 90, 90));
+
+        createTest()
+                .addCanvasClient(new CanvasClient() {
+                    @Override
+                    public void draw(Canvas canvas, int width, int height) {
+                        canvas.drawColor(Color.WHITE);
+                        Paint p = new Paint();
+                        p.setColor(Color.BLUE);
+                        canvas.drawRect(10, 10, 90, 90, p);
+                    }
+                })
+                .addCanvasClient(new CanvasClient() {
+                    @Override
+                    public void draw(Canvas canvas, int width, int height) {
+                        ninePatchDrawable.draw(canvas);
+                    }
+                })
+                .addLayout(R.layout.blue_padded_square, null)
+                .runWithVerifier(verifier);
+    }
+
+    @SmallTest
+    public void testClipping() {
+        createTest().addLayout(R.layout.simple_red_layout, new ViewInitializer() {
+            @Override
+            public void intializeView(View view) {
+                view.setClipBounds(new Rect(0, 0, 50, 50));
+            }
+        }).runWithComparer(mExactComparer);
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/FontRenderingTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/FontRenderingTests.java
new file mode 100644
index 0000000..e7ed7ac
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/FontRenderingTests.java
@@ -0,0 +1,223 @@
+/*
+ * 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.uirendering.cts.testclasses;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Typeface;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.uirendering.cts.bitmapcomparers.BitmapComparer;
+import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
+import android.uirendering.cts.bitmapverifiers.GoldenImageVerifier;
+import android.uirendering.cts.testinfrastructure.ActivityTestBase;
+import android.uirendering.cts.testinfrastructure.CanvasClient;
+
+import com.android.cts.uirendering.R;
+
+public class FontRenderingTests extends ActivityTestBase {
+    // Threshold is barely loose enough for differences between sw and hw renderers
+    static double MSSIM_THRESHOLD = 0.91;
+
+    private final BitmapComparer mFuzzyComparer = new MSSIMComparer(MSSIM_THRESHOLD);
+
+    // Representative characters including some from Unicode 7
+    private final String mTestString1 = "Hamburg \u20bd";
+    private final String mTestString2 = "\u20b9\u0186\u0254\u1e24\u1e43";
+
+    private void fontTestBody(final Typeface typeface, int id) {
+        Bitmap goldenBitmap = BitmapFactory.decodeResource(getActivity().getResources(), id);
+        createTest()
+                .addCanvasClient(new CanvasClient() {
+                    @Override
+                    public void draw(Canvas canvas, int width, int height) {
+                        Paint p = new Paint();
+                        p.setAntiAlias(true);
+                        p.setColor(Color.BLACK);
+                        p.setTextSize(30);
+                        p.setTypeface(typeface);
+                        canvas.drawText(mTestString1, 10, 60, p);
+                        canvas.drawText(mTestString2, 10, 100, p);
+                    }
+                })
+                .runWithVerifier(new GoldenImageVerifier(goldenBitmap, mFuzzyComparer));
+    }
+
+    @SmallTest
+    public void testDefaultFont() {
+        Typeface tf = Typeface.create("sans-serif", Typeface.NORMAL);
+        fontTestBody(tf, R.drawable.hello1);
+    }
+
+    @SmallTest
+    public void testBoldFont() {
+        Typeface tf = Typeface.create("sans-serif", Typeface.BOLD);
+        fontTestBody(tf, R.drawable.bold1);
+    }
+
+    @SmallTest
+    public void testItalicFont() {
+        Typeface tf = Typeface.create("sans-serif", Typeface.ITALIC);
+        fontTestBody(tf, R.drawable.italic1);
+    }
+
+    @SmallTest
+    public void testBoldItalicFont() {
+        Typeface tf = Typeface.create("sans-serif", Typeface.BOLD | Typeface.ITALIC);
+        fontTestBody(tf, R.drawable.bolditalic1);
+    }
+
+    @SmallTest
+    public void testMediumFont() {
+        Typeface tf = Typeface.create("sans-serif-medium", Typeface.NORMAL);
+        fontTestBody(tf, R.drawable.medium1);
+    }
+
+    @SmallTest
+    public void testMediumBoldFont() {
+        // bold attribute on medium base font = black
+        Typeface tf = Typeface.create("sans-serif-medium", Typeface.BOLD);
+        fontTestBody(tf, R.drawable.black1);
+    }
+
+    @SmallTest
+    public void testMediumItalicFont() {
+        Typeface tf = Typeface.create("sans-serif-medium", Typeface.ITALIC);
+        fontTestBody(tf, R.drawable.mediumitalic1);
+    }
+
+    @SmallTest
+    public void testMediumBoldItalicFont() {
+        Typeface tf = Typeface.create("sans-serif-medium", Typeface.BOLD | Typeface.ITALIC);
+        fontTestBody(tf, R.drawable.blackitalic1);
+    }
+
+    @SmallTest
+    public void testLightFont() {
+        Typeface tf = Typeface.create("sans-serif-light", Typeface.NORMAL);
+        fontTestBody(tf, R.drawable.light1);
+    }
+
+    @SmallTest
+    public void testLightBoldFont() {
+        // bold attribute on light base font = medium
+        Typeface tf = Typeface.create("sans-serif-light", Typeface.BOLD);
+        fontTestBody(tf, R.drawable.medium1);
+    }
+
+    @SmallTest
+    public void testLightItalicFont() {
+        Typeface tf = Typeface.create("sans-serif-light", Typeface.ITALIC);
+        fontTestBody(tf, R.drawable.lightitalic1);
+    }
+
+    @SmallTest
+    public void testLightBoldItalicFont() {
+        Typeface tf = Typeface.create("sans-serif-light", Typeface.BOLD | Typeface.ITALIC);
+        fontTestBody(tf, R.drawable.mediumitalic1);
+    }
+
+    @SmallTest
+    public void testThinFont() {
+        Typeface tf = Typeface.create("sans-serif-thin", Typeface.NORMAL);
+        fontTestBody(tf, R.drawable.thin1);
+    }
+
+    @SmallTest
+    public void testThinBoldFont() {
+        // bold attribute on thin base font = normal
+        Typeface tf = Typeface.create("sans-serif-thin", Typeface.BOLD);
+        fontTestBody(tf, R.drawable.hello1);
+    }
+
+    @SmallTest
+    public void testThinItalicFont() {
+        Typeface tf = Typeface.create("sans-serif-thin", Typeface.ITALIC);
+        fontTestBody(tf, R.drawable.thinitalic1);
+    }
+
+    @SmallTest
+    public void testThinBoldItalicFont() {
+        Typeface tf = Typeface.create("sans-serif-thin", Typeface.BOLD | Typeface.ITALIC);
+        fontTestBody(tf, R.drawable.italic1);
+    }
+
+    @SmallTest
+    public void testBlackFont() {
+        Typeface tf = Typeface.create("sans-serif-black", Typeface.NORMAL);
+        fontTestBody(tf, R.drawable.black1);
+    }
+
+    @SmallTest
+    public void testBlackBoldFont() {
+        // bold attribute on black base font = black
+        Typeface tf = Typeface.create("sans-serif-black", Typeface.BOLD);
+        fontTestBody(tf, R.drawable.black1);
+    }
+
+    @SmallTest
+    public void testBlackItalicFont() {
+        Typeface tf = Typeface.create("sans-serif-black", Typeface.ITALIC);
+        fontTestBody(tf, R.drawable.blackitalic1);
+    }
+
+    @SmallTest
+    public void testBlackBoldItalicFont() {
+        Typeface tf = Typeface.create("sans-serif-black", Typeface.BOLD | Typeface.ITALIC);
+        fontTestBody(tf, R.drawable.blackitalic1);
+    }
+
+    /* condensed fonts */
+
+    @SmallTest
+    public void testCondensedFont() {
+        Typeface tf = Typeface.create("sans-serif-condensed", Typeface.NORMAL);
+        fontTestBody(tf, R.drawable.condensed1);
+    }
+
+    @SmallTest
+    public void testCondensedBoldFont() {
+        Typeface tf = Typeface.create("sans-serif-condensed", Typeface.BOLD);
+        fontTestBody(tf, R.drawable.condensedbold1);
+    }
+
+    @SmallTest
+    public void testCondensedItalicFont() {
+        Typeface tf = Typeface.create("sans-serif-condensed", Typeface.ITALIC);
+        fontTestBody(tf, R.drawable.condenseditalic1);
+    }
+
+    @SmallTest
+    public void testCondensedBoldItalicFont() {
+        Typeface tf = Typeface.create("sans-serif-condensed", Typeface.BOLD | Typeface.ITALIC);
+        fontTestBody(tf, R.drawable.condensedbolditalic1);
+    }
+
+    @SmallTest
+    public void testCondensedLightFont() {
+        Typeface tf = Typeface.create("sans-serif-condensed-light", Typeface.NORMAL);
+        fontTestBody(tf, R.drawable.condensedlight1);
+    }
+
+    @SmallTest
+    public void testCondensedLightItalicFont() {
+        Typeface tf = Typeface.create("sans-serif-condensed-light", Typeface.ITALIC);
+        fontTestBody(tf, R.drawable.condensedlightitalic1);
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java
new file mode 100644
index 0000000..6662226
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java
@@ -0,0 +1,87 @@
+/*
+ * 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.uirendering.cts.testclasses;
+
+import com.android.cts.uirendering.R;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.uirendering.cts.bitmapcomparers.BitmapComparer;
+import android.uirendering.cts.bitmapcomparers.ExactComparer;
+import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
+import android.uirendering.cts.bitmapverifiers.RectVerifier;
+import android.uirendering.cts.testinfrastructure.ActivityTestBase;
+import android.uirendering.cts.testinfrastructure.CanvasClient;
+import android.uirendering.cts.testinfrastructure.ViewInitializer;
+import android.util.Log;
+import android.view.View;
+
+public class InfrastructureTests extends ActivityTestBase {
+
+    @SmallTest
+    public void testScreenshot() {
+        for (int i = 0 ; i < 500 ; i ++) {
+            takeScreenshot();
+            System.gc();
+        }
+    }
+
+    /**
+     * Ensure that both render paths are producing independent output. We do this
+     * by verifying that two paths that should render differently *do* render
+     * differently.
+     */
+    @SmallTest
+    public void testRenderSpecIsolation() {
+        CanvasClient canvasClient = new CanvasClient() {
+            @Override
+            public void draw(Canvas canvas, int width, int height) {
+                canvas.drawColor(canvas.isHardwareAccelerated() ? Color.WHITE : Color.BLACK);
+            }
+        };
+        // This is considered a very high threshold and as such, the test should still fail because
+        // they are completely different images.
+        final float threshold = 0.1f;
+        BitmapComparer inverseComparer = new BitmapComparer() {
+            @Override
+            public boolean verifySame(int[] ideal, int[] given, int offset, int stride, int width,
+                    int height) {
+                return !(new MSSIMComparer(threshold)).verifySame(ideal, given, offset, stride,
+                        width, height);
+            }
+        };
+        createTest()
+                .addCanvasClient(canvasClient)
+                .runWithComparer(inverseComparer);
+    }
+
+    @SmallTest
+    public void testViewInitializer() {
+        final Rect clipRect = new Rect(0, 0, 50, 50);
+        ViewInitializer viewInitializer = new ViewInitializer() {
+            @Override
+            public void intializeView(View view) {
+                view.setClipBounds(clipRect);
+            }
+        };
+        createTest()
+                .addLayout(R.layout.simple_red_layout, viewInitializer)
+                .runWithVerifier(new RectVerifier(Color.WHITE, Color.RED, clipRect));
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayoutTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayoutTests.java
new file mode 100644
index 0000000..0ba0f69
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayoutTests.java
@@ -0,0 +1,46 @@
+/*
+ * 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.uirendering.cts.testclasses;
+
+import com.android.cts.uirendering.R;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import android.uirendering.cts.bitmapcomparers.BitmapComparer;
+import android.uirendering.cts.bitmapcomparers.ExactComparer;
+import android.uirendering.cts.testinfrastructure.ActivityTestBase;
+
+
+/**
+ * Created to see how custom views made with XML and programatic code will work.
+ */
+public class LayoutTests extends ActivityTestBase {
+    private BitmapComparer mBitmapComparer;
+
+    public LayoutTests() {
+        mBitmapComparer = new ExactComparer();
+    }
+
+    @SmallTest
+    public void testSimpleRedLayout() {
+        createTest().addLayout(R.layout.simple_red_layout, null).runWithComparer(mBitmapComparer);
+    }
+
+    @SmallTest
+    public void testSimpleRectLayout() {
+        createTest().addLayout(R.layout.simple_rect_layout, null).runWithComparer(mBitmapComparer);
+    }
+}
+
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SweepTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SweepTests.java
new file mode 100644
index 0000000..7947286
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SweepTests.java
@@ -0,0 +1,393 @@
+/*
+* 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/LICENSE2.0
+*
+* Unless required by applicable law or agreed to in riting, 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.uirendering.cts.testclasses;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.LinearGradient;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Shader;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.uirendering.cts.bitmapcomparers.BitmapComparer;
+import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
+import android.uirendering.cts.bitmapverifiers.BitmapVerifier;
+import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
+import android.uirendering.cts.testinfrastructure.ActivityTestBase;
+import android.uirendering.cts.testinfrastructure.CanvasClient;
+import android.uirendering.cts.testinfrastructure.DisplayModifier;
+import android.uirendering.cts.testinfrastructure.ResourceModifier;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Test cases of all combination of resource modifications.
+ */
+public class SweepTests extends ActivityTestBase {
+    private static final String TAG = "SweepTests";
+
+    public static final int BG_COLOR = 0xFFFFFFFF;
+    public static final int DST_COLOR = 0xFFFFCC44;
+    public static final int SRC_COLOR = 0xFF66AAFF;
+    public static final int MULTIPLY_COLOR = 0xFF668844;
+    public static final int SCREEN_COLOR = 0xFFFFEEFF;
+
+    public static final int FILTER_COLOR = 0xFFBB0000;
+    public static final int RECT0_COLOR = 0x33808080;
+    public static final int RECT1_COLOR = 0x66808080;
+    public static final int RECT2_COLOR = 0x99808080;
+    public static final int RECT3_COLOR = 0xCC808080;
+
+    // These points are in pairs, the first being the lower left corner, the second is only in the
+    // Destination bitmap, the third is the intersection of the two bitmaps, and the fourth is in
+    // the Source bitmap.
+    private final static Point[] XFERMODE_TEST_POINTS = new Point[] {
+            new Point(1, 160), new Point(50, 50), new Point(70, 70), new Point(140, 140)
+    };
+
+    /**
+     * There are 4 locations we care about in any filter testing.
+     *
+     * 1) Both empty
+     * 2) Only src, dst empty
+     * 3) Both src + dst
+     * 4) Only dst, src empty
+     */
+    private final Map<PorterDuff.Mode, int[]> XFERMODE_COLOR_MAP = new LinkedHashMap<PorterDuff.Mode, int[]>() {
+        {
+            put(PorterDuff.Mode.SRC, new int[] {
+                    BG_COLOR, BG_COLOR, SRC_COLOR, SRC_COLOR
+            });
+
+            put(PorterDuff.Mode.DST, new int[] {
+                    BG_COLOR, DST_COLOR, DST_COLOR, BG_COLOR
+            });
+
+            put(PorterDuff.Mode.SRC_OVER, new int[] {
+                    BG_COLOR, DST_COLOR, SRC_COLOR, SRC_COLOR
+            });
+
+            put(PorterDuff.Mode.DST_OVER, new int[] {
+                    BG_COLOR, DST_COLOR, DST_COLOR, SRC_COLOR
+            });
+
+            put(PorterDuff.Mode.SRC_IN, new int[] {
+                    BG_COLOR, BG_COLOR, SRC_COLOR, BG_COLOR
+            });
+
+            put(PorterDuff.Mode.DST_IN, new int[] {
+                    BG_COLOR, BG_COLOR, DST_COLOR, BG_COLOR
+            });
+
+            put(PorterDuff.Mode.SRC_OUT, new int[] {
+                    BG_COLOR, BG_COLOR, BG_COLOR, SRC_COLOR
+            });
+
+            put(PorterDuff.Mode.DST_OUT, new int[] {
+                    BG_COLOR, DST_COLOR, BG_COLOR, BG_COLOR
+            });
+
+            put(PorterDuff.Mode.SRC_ATOP, new int[] {
+                    BG_COLOR, DST_COLOR, SRC_COLOR, BG_COLOR
+            });
+
+            put(PorterDuff.Mode.DST_ATOP, new int[] {
+                    BG_COLOR, BG_COLOR, DST_COLOR, SRC_COLOR
+            });
+
+            put(PorterDuff.Mode.XOR, new int[] {
+                    BG_COLOR, DST_COLOR, BG_COLOR, SRC_COLOR
+            });
+
+            put(PorterDuff.Mode.MULTIPLY, new int[] {
+                    BG_COLOR, BG_COLOR, MULTIPLY_COLOR, BG_COLOR
+            });
+
+            put(PorterDuff.Mode.SCREEN, new int[] {
+                    BG_COLOR, DST_COLOR, SCREEN_COLOR, SRC_COLOR
+            });
+        }
+    };
+
+    private final static DisplayModifier XFERMODE_MODIFIER = new DisplayModifier() {
+        private final RectF mSrcRect = new RectF(60, 60, 160, 160);
+        private final RectF mDstRect = new RectF(20, 20, 120, 120);
+        private final Bitmap mSrcBitmap = createSrc();
+        private final Bitmap mDstBitmap = createDst();
+
+        @Override
+        public void modifyDrawing(Paint paint, Canvas canvas) {
+            int sc = canvas.saveLayer(0, 0, TEST_WIDTH, TEST_HEIGHT, null);
+
+            canvas.drawBitmap(mDstBitmap, 0, 0, null);
+            canvas.drawBitmap(mSrcBitmap, 0, 0, paint);
+
+            canvas.restoreToCount(sc);
+        }
+
+        private Bitmap createSrc() {
+            Bitmap srcB = Bitmap.createBitmap(MODIFIER_WIDTH, MODIFIER_HEIGHT,
+                    Bitmap.Config.ARGB_8888);
+            Canvas srcCanvas = new Canvas(srcB);
+            Paint srcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+            srcPaint.setColor(SRC_COLOR);
+            srcCanvas.drawRect(mSrcRect, srcPaint);
+            return srcB;
+        }
+
+        private Bitmap createDst() {
+            Bitmap dstB = Bitmap.createBitmap(MODIFIER_WIDTH, MODIFIER_HEIGHT,
+                    Bitmap.Config.ARGB_8888);
+            Canvas dstCanvas = new Canvas(dstB);
+            Paint dstPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+            dstPaint.setColor(DST_COLOR);
+            dstCanvas.drawOval(mDstRect, dstPaint);
+            return dstB;
+        }
+    };
+
+
+    // We care about one point in each of the four rectangles of different alpha values, as well as
+    // the area outside the rectangles
+    private final static Point[] COLOR_FILTER_ALPHA_POINTS = new Point[] {
+            new Point(15, 90), new Point(45, 90), new Point(75, 90), new Point(105, 90),
+            new Point(135, 90)
+    };
+
+    private final Map<PorterDuff.Mode, int[]> COLOR_FILTER_ALPHA_MAP = new LinkedHashMap<PorterDuff.Mode, int[]>() {
+        {
+            put(PorterDuff.Mode.SRC, new int[] {
+                FILTER_COLOR, FILTER_COLOR, FILTER_COLOR, FILTER_COLOR, FILTER_COLOR
+            });
+
+            put(PorterDuff.Mode.DST, new int[] {
+                    0xFFE6E6E6, 0xFFCCCCCC, 0xFFB3B3B3, 0xFF999999, 0xFFFFFFFF
+            });
+
+            put(PorterDuff.Mode.SRC_OVER, new int[] {
+                    0xFFBB0000, 0xFFBB0000, 0xFFBB0000, 0xFFBB0000, 0xFFBB0000
+            });
+
+            put(PorterDuff.Mode.DST_OVER, new int[] {
+                    0xFFAF1A1A, 0xFFA33333, 0xFF984D4D, 0xFF8B6666, 0xFFBB0000
+            });
+
+            put(PorterDuff.Mode.SRC_IN, new int[] {
+                    0xFFF1CCCC, 0xFFE49999, 0xFFD66666, 0xFFC83333, 0xFFFFFFFF
+            });
+
+            put(PorterDuff.Mode.DST_IN, new int[] {
+                    0xFFE6E6E6, 0xFFCCCCCC, 0xFFB3B3B3, 0xFF999999, 0xFFFFFFFF
+            });
+
+            put(PorterDuff.Mode.SRC_OUT, new int[] {
+                    0xFFC83333, 0xFFD66666, 0xFFE49999, 0xFFF1CCCC, 0xFFBB0000
+            });
+
+            put(PorterDuff.Mode.DST_OUT, new int[] {
+                    0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+            });
+
+            put(PorterDuff.Mode.SRC_ATOP, new int[] {
+                    0xFFF1CCCC, 0xFFE49999, 0xFFD66666, 0xFFC93333, 0xFFFFFFFF
+            });
+
+            put(PorterDuff.Mode.DST_ATOP, new int[] {
+                    0xFFB01A1A, 0xFFA33333, 0xFF984D4D, 0xFF8B6666, 0xFFBB0000
+            });
+
+            put(PorterDuff.Mode.XOR, new int[] {
+                    0xFFC93333, 0xFFD66666, 0xFFE49999, 0xFFF1CCCC, 0xFFBB0000
+            });
+
+            put(PorterDuff.Mode.MULTIPLY, new int[] {
+                    0xFFDFCCCC, 0xFFBE9999, 0xFF9E6666, 0xFF7E3333, 0xFFFFFFFF
+            });
+
+            put(PorterDuff.Mode.SCREEN, new int[] {
+                    0xFFC21A1A, 0xFFC93333, 0xFFD04D4D, 0xFFD66666, 0xFFBB0000
+            });
+        }
+    };
+
+    private final static DisplayModifier COLOR_FILTER_ALPHA_MODIFIER = new DisplayModifier() {
+        private final static int mBlockWidths = 30;
+        private final int[] mColorValues = new int[] {RECT0_COLOR, RECT1_COLOR, RECT2_COLOR,
+                RECT3_COLOR};
+
+        private final Bitmap mBitmap = createQuadRectBitmap();
+
+        public void modifyDrawing(Paint paint, Canvas canvas) {
+            canvas.drawBitmap(mBitmap, 0, 0, paint);
+        }
+
+        private Bitmap createQuadRectBitmap() {
+            Bitmap bitmap = Bitmap.createBitmap(MODIFIER_WIDTH, MODIFIER_HEIGHT,
+                    Bitmap.Config.ARGB_8888);
+            Canvas canvas = new Canvas(bitmap);
+            Paint paint = new Paint();
+            for (int i = 0 ; i < 4 ; i++) {
+                paint.setColor(mColorValues[i]);
+                canvas.drawRect(i * mBlockWidths, 0, (i + 1) * mBlockWidths, MODIFIER_HEIGHT, paint);
+            }
+            return bitmap;
+        }
+    };
+
+    private final static DisplayModifier COLOR_FILTER_GRADIENT_MODIFIER = new DisplayModifier() {
+        private final Rect mBounds = new Rect(30, 30, 150, 150);
+        private final int[] mColors = new int[] {
+                Color.RED, Color.GREEN, Color.BLUE
+        };
+
+        private final Bitmap mBitmap = createGradient();
+
+        @Override
+        public void modifyDrawing(Paint paint, Canvas canvas) {
+            canvas.drawBitmap(mBitmap, 0, 0, paint);
+        }
+
+        private Bitmap createGradient() {
+            LinearGradient gradient = new LinearGradient(30, 90, 150, 90, mColors, null,
+                    Shader.TileMode.REPEAT);
+            Bitmap bitmap = Bitmap.createBitmap(MODIFIER_WIDTH, MODIFIER_HEIGHT,
+                    Bitmap.Config.ARGB_8888);
+            Paint p = new Paint();
+            p.setShader(gradient);
+            Canvas c = new Canvas(bitmap);
+            c.drawRect(mBounds, p);
+            return bitmap;
+        }
+    };
+
+    public static final DisplayModifier mCircleDrawModifier = new DisplayModifier() {
+        @Override
+        public void modifyDrawing(Paint paint, Canvas canvas) {
+            canvas.drawCircle(ActivityTestBase.TEST_WIDTH / 2,
+                    ActivityTestBase.TEST_HEIGHT / 2,
+                    ActivityTestBase.TEST_HEIGHT / 2, paint);
+        }
+    };
+
+    /**
+     * 0.5 defines minimum similarity as 50%
+     */
+    private static final float HIGH_THRESHOLD = 0.5f;
+
+    private static final BitmapComparer[] DEFAULT_MSSIM_COMPARER = new BitmapComparer[] {
+            new MSSIMComparer(HIGH_THRESHOLD)
+    };
+
+    @SmallTest
+    public void testBasicDraws() {
+        sweepModifiersForMask(DisplayModifier.Accessor.SHAPES_MASK, null, DEFAULT_MSSIM_COMPARER,
+                null);
+    }
+
+    @SmallTest
+    public void testBasicShaders() {
+        sweepModifiersForMask(DisplayModifier.Accessor.SHADER_MASK, mCircleDrawModifier,
+                DEFAULT_MSSIM_COMPARER, null);
+    }
+
+    @SmallTest
+    public void testColorFilterUsingGradient() {
+        sweepModifiersForMask(DisplayModifier.Accessor.COLOR_FILTER_MASK,
+                COLOR_FILTER_GRADIENT_MODIFIER, DEFAULT_MSSIM_COMPARER, null);
+    }
+
+    @SmallTest
+    public void testColorFiltersAlphas() {
+        BitmapVerifier[] bitmapVerifiers =
+                new BitmapVerifier[DisplayModifier.PORTERDUFF_MODES.length];
+        int index = 0;
+        for (PorterDuff.Mode mode : DisplayModifier.PORTERDUFF_MODES) {
+            bitmapVerifiers[index] = new SamplePointVerifier(COLOR_FILTER_ALPHA_POINTS,
+                    COLOR_FILTER_ALPHA_MAP.get(mode));
+            index++;
+        }
+        sweepModifiersForMask(DisplayModifier.Accessor.COLOR_FILTER_MASK,
+                COLOR_FILTER_ALPHA_MODIFIER, null, bitmapVerifiers);
+    }
+
+    @SmallTest
+    public void testXfermodes() {
+        BitmapVerifier[] bitmapVerifiers =
+                new BitmapVerifier[DisplayModifier.PORTERDUFF_MODES.length];
+        int index = 0;
+        for (PorterDuff.Mode mode : DisplayModifier.PORTERDUFF_MODES) {
+            bitmapVerifiers[index] = new SamplePointVerifier(XFERMODE_TEST_POINTS,
+                    XFERMODE_COLOR_MAP.get(mode));
+            index++;
+        }
+        sweepModifiersForMask(DisplayModifier.Accessor.XFERMODE_MASK, XFERMODE_MODIFIER,
+                null, bitmapVerifiers);
+    }
+
+    /*
+     * TODO: fix this test for L MR1
+    @SmallTest
+    public void testShaderSweeps() {
+        int mask = DisplayModifier.Accessor.AA_MASK |
+                DisplayModifier.Accessor.SHADER_MASK |
+                DisplayModifier.Accessor.XFERMODE_MASK |
+                DisplayModifier.Accessor.SHAPES_MASK;
+        sweepModifiersForMask(mask, null, DEFAULT_MSSIM_COMPARER, null);
+    }
+     */
+
+    protected void sweepModifiersForMask(int mask, final DisplayModifier drawOp,
+            BitmapComparer[] bitmapComparers, BitmapVerifier[] bitmapVerifiers) {
+        if ((mask & DisplayModifier.Accessor.ALL_OPTIONS_MASK) == 0) {
+            throw new IllegalArgumentException("Attempt to test with a mask that is invalid");
+        }
+        // Get the accessor of all the different modifications possible
+        final DisplayModifier.Accessor modifierAccessor = new DisplayModifier.Accessor(mask);
+        // Initialize the resources that we will need to access
+        ResourceModifier.init(getActivity().getResources());
+        // For each modification combination, we will get the CanvasClient associated with it and
+        // from there execute a normal canvas test with that.
+        CanvasClient canvasClient = new CanvasClient() {
+            @Override
+            public void draw(Canvas canvas, int width, int height) {
+                Paint paint = new Paint();
+                modifierAccessor.modifyDrawing(canvas, paint);
+                if (drawOp != null) {
+                    drawOp.modifyDrawing(paint, canvas);
+                }
+            }
+        };
+
+        int index = 0;
+        // Create the test cases with each combination
+        do {
+            canvasClient.setDebugString(modifierAccessor.getDebugString());
+            if (bitmapComparers != null) {
+                int arrIndex = Math.min(index, bitmapComparers.length - 1);
+                createTest().addCanvasClient(canvasClient).runWithComparer(bitmapComparers[arrIndex]);
+            } else {
+                int arrIndex = Math.min(index, bitmapVerifiers.length - 1);
+                createTest().addCanvasClient(canvasClient).runWithVerifier(bitmapVerifiers[arrIndex]);
+            }
+            index++;
+        } while (modifierAccessor.step());
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewClippingTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewClippingTests.java
new file mode 100644
index 0000000..1acdc20
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewClippingTests.java
@@ -0,0 +1,107 @@
+package android.uirendering.cts.testclasses;
+
+import android.graphics.Color;
+import android.graphics.Outline;
+import android.graphics.Rect;
+import android.uirendering.cts.bitmapverifiers.BitmapVerifier;
+import android.uirendering.cts.bitmapverifiers.RectVerifier;
+import android.uirendering.cts.testclasses.view.UnclippedBlueView;
+import android.uirendering.cts.testinfrastructure.ActivityTestBase;
+import android.uirendering.cts.testinfrastructure.ViewInitializer;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewOutlineProvider;
+import com.android.cts.uirendering.R;
+
+/**
+ * This tests view clipping by modifying properties of blue_padded_layout, and validating
+ * the resulting rect of content.
+ *
+ * Since the layout is blue on a white background, this is always done with a RectVerifier.
+ */
+public class ViewClippingTests extends ActivityTestBase {
+    final Rect FULL_RECT = new Rect(0, 0, 200, 200);
+    final Rect BOUNDS_RECT = new Rect(0, 0, 100, 100);
+    final Rect PADDED_RECT = new Rect(15, 16, 83, 82);
+    final Rect OUTLINE_RECT = new Rect(1, 2, 98, 99);
+    final Rect CLIP_BOUNDS_RECT = new Rect(10, 20, 70, 80);
+
+    final ViewInitializer BOUNDS_CLIP_INIT = new ViewInitializer() {
+        @Override
+        public void intializeView(View rootView) {
+            ((ViewGroup)rootView).setClipChildren(true);
+        }
+    };
+    final ViewInitializer PADDING_CLIP_INIT = new ViewInitializer() {
+        @Override
+        public void intializeView(View rootView) {
+            ViewGroup child = (ViewGroup) rootView.findViewById(R.id.child);
+            child.setClipToPadding(true);
+            child.setWillNotDraw(true);
+            child.addView(new UnclippedBlueView(rootView.getContext()));
+        }
+    };
+    final ViewInitializer OUTLINE_CLIP_INIT = new ViewInitializer() {
+        @Override
+        public void intializeView(View rootView) {
+            View child = rootView.findViewById(R.id.child);
+            child.setOutlineProvider(new ViewOutlineProvider() {
+                @Override
+                public void getOutline(View view, Outline outline) {
+                    outline.setRect(OUTLINE_RECT);
+                }
+            });
+            child.setClipToOutline(true);
+        }
+    };
+    final ViewInitializer CLIP_BOUNDS_CLIP_INIT = new ViewInitializer() {
+        @Override
+        public void intializeView(View view) {
+            view.setClipBounds(CLIP_BOUNDS_RECT);
+        }
+    };
+
+    // TODO: attempt to reduce
+    static final int TOLERANCE = 10;
+    static BitmapVerifier makeClipVerifier(Rect blueBoundsRect) {
+        return new RectVerifier(Color.WHITE, Color.BLUE, blueBoundsRect, TOLERANCE);
+    }
+
+    public void testSimpleUnclipped() {
+        createTest()
+                .addLayout(R.layout.blue_padded_layout, null)
+                .runWithVerifier(makeClipVerifier(FULL_RECT));
+    }
+
+    public void testSimpleBoundsClip() {
+        createTest()
+                .addLayout(R.layout.blue_padded_layout, BOUNDS_CLIP_INIT)
+                .runWithVerifier(makeClipVerifier(BOUNDS_RECT));
+    }
+
+    public void testSimpleClipBoundsClip() {
+        createTest()
+                .addLayout(R.layout.blue_padded_layout, CLIP_BOUNDS_CLIP_INIT)
+                .runWithVerifier(makeClipVerifier(CLIP_BOUNDS_RECT));
+    }
+
+    public void testSimplePaddingClip() {
+        createTest()
+                .addLayout(R.layout.blue_padded_layout, PADDING_CLIP_INIT)
+                .runWithVerifier(makeClipVerifier(PADDED_RECT));
+    }
+
+    public void testSimpleOutlineClip() {
+        // NOTE: Only HW is supported
+        createTest()
+                .addLayout(R.layout.blue_padded_layout, OUTLINE_CLIP_INIT, true)
+                .runWithVerifier(makeClipVerifier(OUTLINE_RECT));
+
+        // SW ignores the outline clip
+        createTest()
+                .addLayout(R.layout.blue_padded_layout, OUTLINE_CLIP_INIT, false)
+                .runWithVerifier(makeClipVerifier(FULL_RECT));
+    }
+
+    // TODO: add tests with clip + scroll, and with interesting combinations of the above
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/view/UnclippedBlueView.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/view/UnclippedBlueView.java
new file mode 100644
index 0000000..e2037f7
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/view/UnclippedBlueView.java
@@ -0,0 +1,33 @@
+package android.uirendering.cts.testclasses.view;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.FrameLayout;
+
+public class UnclippedBlueView extends FrameLayout {
+    public UnclippedBlueView(Context context) {
+        this(context, null);
+    }
+
+    public UnclippedBlueView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public UnclippedBlueView(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+        setWillNotDraw(false);
+    }
+
+    public UnclippedBlueView(Context context, AttributeSet attrs,
+            int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        canvas.drawColor(Color.BLUE);
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
new file mode 100644
index 0000000..052b251
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
@@ -0,0 +1,325 @@
+/*
+ * 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.uirendering.cts.testinfrastructure;
+
+import android.annotation.Nullable;
+import android.graphics.Bitmap;
+import android.renderscript.Allocation;
+import android.renderscript.RenderScript;
+import android.test.ActivityInstrumentationTestCase2;
+import android.uirendering.cts.bitmapcomparers.BitmapComparer;
+import android.uirendering.cts.bitmapverifiers.BitmapVerifier;
+import android.uirendering.cts.differencevisualizers.DifferenceVisualizer;
+import android.uirendering.cts.differencevisualizers.PassFailVisualizer;
+import android.uirendering.cts.util.BitmapDumper;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * This class contains the basis for the graphics hardware test classes. Contained within this class
+ * are several methods that help with the execution of tests, and should be extended to gain the
+ * functionality built in.
+ */
+public abstract class ActivityTestBase extends
+        ActivityInstrumentationTestCase2<DrawActivity> {
+    public static final String TAG_NAME = "ActivityTestBase";
+    public static final boolean DEBUG = false;
+    public static final boolean USE_RS = false;
+    public static final int TEST_WIDTH = 180;
+    public static final int TEST_HEIGHT = 180; //The minimum height and width of a device
+    public static final int MAX_SCREEN_SHOTS = 100;
+
+    private int[] mHardwareArray = new int[TEST_HEIGHT * TEST_WIDTH];
+    private int[] mSoftwareArray = new int[TEST_HEIGHT * TEST_WIDTH];
+    private DifferenceVisualizer mDifferenceVisualizer;
+    private Allocation mIdealAllocation;
+    private Allocation mGivenAllocation;
+    private RenderScript mRenderScript;
+    private TestCaseBuilder mTestCaseBuilder;
+
+    /**
+     * The default constructor creates the package name and sets the DrawActivity as the class that
+     * we would use.
+     */
+    public ActivityTestBase() {
+        super(DrawActivity.class);
+        mDifferenceVisualizer = new PassFailVisualizer();
+
+        // Create a location for the files to be held, if it doesn't exist already
+        BitmapDumper.createSubDirectory(this.getClass().getSimpleName());
+
+        // If we have a test currently, let's remove the older files if they exist
+        if (getName() != null) {
+            BitmapDumper.deleteFileInClassFolder(this.getClass().getSimpleName(), getName());
+        }
+    }
+
+    /**
+     * This method is called before each test case and should be called from the test class that
+     * extends this class.
+     */
+    @Override
+    public void setUp() {
+        mDifferenceVisualizer = new PassFailVisualizer();
+        if (USE_RS) {
+            mRenderScript = RenderScript.create(getActivity().getApplicationContext());
+        }
+    }
+
+    /**
+     * This method will kill the activity so that it can be reset depending on the test.
+     */
+    @Override
+    public void tearDown() {
+        if (mTestCaseBuilder != null) {
+            List<TestCase> testCases = mTestCaseBuilder.getTestCases();
+
+            if (testCases.size() == 0) {
+                throw new IllegalStateException("Must have at least one test case");
+            }
+
+
+            for (TestCase testCase : testCases) {
+                if (!testCase.wasTestRan) {
+                    Log.w(TAG_NAME, getName() + " not all of the tests were ran");
+                    break;
+                }
+            }
+            mTestCaseBuilder = null;
+        }
+
+        Runnable finishRunnable = new Runnable() {
+
+            @Override
+            public void run() {
+                getActivity().finish();
+            }
+        };
+
+        getActivity().runOnUiThread(finishRunnable);
+    }
+
+    public Bitmap takeScreenshot() {
+        getInstrumentation().waitForIdleSync();
+        Bitmap bitmap1 = getInstrumentation().getUiAutomation().takeScreenshot();
+        Bitmap bitmap2;
+        int count = 0;
+        do  {
+            bitmap2 = bitmap1;
+            bitmap1 = getInstrumentation().getUiAutomation().takeScreenshot();
+            count++;
+        } while (count < MAX_SCREEN_SHOTS && !Arrays.equals(bitmap2.mBuffer, bitmap1.mBuffer));
+        return bitmap1;
+    }
+
+    /**
+     * Sets the current DifferenceVisualizer for use in current test.
+     */
+    public void setDifferenceVisualizer(DifferenceVisualizer differenceVisualizer) {
+        mDifferenceVisualizer = differenceVisualizer;
+    }
+
+    /**
+     * Used to execute a specific part of a test and get the resultant bitmap
+     */
+    protected Bitmap captureRenderSpec(TestCase testCase) {
+        getActivity().enqueueRenderSpecAndWait(testCase.layoutID, testCase.canvasClient,
+                testCase.webViewUrl, testCase.viewInitializer, testCase.useHardware);
+        testCase.wasTestRan = true;
+        return takeScreenshot();
+    }
+
+    /**
+     * Compares the two bitmaps saved using the given test. If they fail, the files are saved using
+     * the test name.
+     */
+    protected void assertBitmapsAreSimilar(Bitmap bitmap1, Bitmap bitmap2,
+            BitmapComparer comparer, String debugMessage) {
+        boolean success;
+
+        if (USE_RS && comparer.supportsRenderScript()) {
+            mIdealAllocation = Allocation.createFromBitmap(mRenderScript, bitmap1,
+                    Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
+            mGivenAllocation = Allocation.createFromBitmap(mRenderScript, bitmap2,
+                    Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
+            success = comparer.verifySameRS(getActivity().getResources(), mIdealAllocation,
+                    mGivenAllocation, 0, TEST_WIDTH, TEST_WIDTH, TEST_HEIGHT, mRenderScript);
+        } else {
+            bitmap1.getPixels(mSoftwareArray, 0, TEST_WIDTH, 0, 0, TEST_WIDTH, TEST_HEIGHT);
+            bitmap2.getPixels(mHardwareArray, 0, TEST_WIDTH, 0, 0, TEST_WIDTH, TEST_HEIGHT);
+            success = comparer.verifySame(mSoftwareArray, mHardwareArray, 0, TEST_WIDTH, TEST_WIDTH,
+                    TEST_HEIGHT);
+        }
+
+        if (!success) {
+            BitmapDumper.dumpBitmaps(bitmap1, bitmap2, getName(), this.getClass().getSimpleName(),
+                    mDifferenceVisualizer);
+        }
+
+        assertTrue(debugMessage, success);
+    }
+
+    /**
+     * Tests to see if a bitmap passes a verifier's test. If it doesn't the bitmap is saved to the
+     * sdcard.
+     */
+    protected void assertBitmapIsVerified(Bitmap bitmap, BitmapVerifier bitmapVerifier,
+            String debugMessage) {
+        bitmap.getPixels(mSoftwareArray, 0, TEST_WIDTH, 0, 0,
+                TEST_WIDTH, TEST_HEIGHT);
+        boolean success = bitmapVerifier.verify(mSoftwareArray, 0, TEST_WIDTH, TEST_WIDTH, TEST_HEIGHT);
+        if (!success) {
+            Bitmap croppedBitmap = Bitmap.createBitmap(bitmap, 0, 0, TEST_WIDTH, TEST_HEIGHT);
+            BitmapDumper.dumpBitmap(croppedBitmap, getName(), this.getClass().getSimpleName());
+            BitmapDumper.dumpBitmap(bitmapVerifier.getDifferenceBitmap(), getName() + "_verifier",
+                    this.getClass().getSimpleName());
+        }
+        assertTrue(debugMessage, success);
+    }
+
+    protected TestCaseBuilder createTest() {
+        mTestCaseBuilder = new TestCaseBuilder();
+        return mTestCaseBuilder;
+    }
+
+    /**
+     * Defines a group of CanvasClients, XML layouts, and WebView html files for testing.
+     */
+    protected class TestCaseBuilder {
+        private List<TestCase> mTestCases;
+
+        private TestCaseBuilder() {
+            mTestCases = new ArrayList<TestCase>();
+        }
+
+        /**
+         * Runs a test where the first test case is considered the "ideal" image and from there,
+         * every test case is tested against it.
+         */
+        public void runWithComparer(BitmapComparer bitmapComparer) {
+            if (mTestCases.size() == 0) {
+                throw new IllegalStateException("Need at least one test to run");
+            }
+
+            Bitmap idealBitmap = captureRenderSpec(mTestCases.remove(0));
+
+            for (TestCase testCase : mTestCases) {
+                Bitmap testCaseBitmap = captureRenderSpec(testCase);
+                assertBitmapsAreSimilar(idealBitmap, testCaseBitmap, bitmapComparer,
+                        testCase.getDebugString());
+            }
+        }
+
+        /**
+         * Runs a test where each testcase is independent of the others and each is checked against
+         * the verifier given.
+         */
+        public void runWithVerifier(BitmapVerifier bitmapVerifier) {
+            if (mTestCases.size() == 0) {
+                throw new IllegalStateException("Need at least one test to run");
+            }
+
+            for (TestCase testCase : mTestCases) {
+                Bitmap testCaseBitmap = captureRenderSpec(testCase);
+                assertBitmapIsVerified(testCaseBitmap, bitmapVerifier, testCase.getDebugString());
+            }
+        }
+
+        public TestCaseBuilder addWebView(String webViewUrl,
+                @Nullable ViewInitializer viewInitializer) {
+            return addWebView(webViewUrl, viewInitializer, false)
+                    .addWebView(webViewUrl, viewInitializer, true);
+        }
+
+        public TestCaseBuilder addLayout(int layoutId, @Nullable ViewInitializer viewInitializer) {
+            return addLayout(layoutId, viewInitializer, false)
+                    .addLayout(layoutId, viewInitializer, true);
+        }
+
+        public TestCaseBuilder addCanvasClient(CanvasClient canvasClient) {
+            return addCanvasClient(canvasClient, false)
+                    .addCanvasClient(canvasClient, true);
+        }
+
+        public TestCaseBuilder addWebView(String webViewUrl,
+                @Nullable ViewInitializer viewInitializer, boolean useHardware) {
+            mTestCases.add(new TestCase(null, 0, webViewUrl, viewInitializer, useHardware));
+            return this;
+        }
+
+        public TestCaseBuilder addLayout(int layoutId, @Nullable ViewInitializer viewInitializer,
+                boolean useHardware) {
+            mTestCases.add(new TestCase(null, layoutId, null, viewInitializer, useHardware));
+            return this;
+        }
+
+        public TestCaseBuilder addCanvasClient(CanvasClient canvasClient, boolean useHardware) {
+            mTestCases.add(new TestCase(canvasClient, 0, null, null, useHardware));
+            return this;
+        }
+
+        private List<TestCase> getTestCases() {
+            return mTestCases;
+        }
+    }
+
+    private class TestCase {
+        public int layoutID;
+        public CanvasClient canvasClient;
+        public String webViewUrl;
+        public ViewInitializer viewInitializer;
+        public boolean useHardware;
+        public boolean wasTestRan;
+
+        public TestCase(CanvasClient client, int id, String viewUrl,
+                ViewInitializer viewInitializer, boolean useHardware) {
+            int count = 0;
+            count += (client == null ? 0 : 1);
+            count += (viewUrl == null ? 0 : 1);
+            count += (id == 0 ? 0 : 1);
+            assert(count == 1);
+            assert(client == null || viewInitializer == null);
+            this.layoutID = id;
+            this.canvasClient = client;
+            this.webViewUrl = viewUrl;
+            this.viewInitializer = viewInitializer;
+            this.useHardware = useHardware;
+            this.wasTestRan = false;
+        }
+
+        public String getDebugString() {
+            String debug = "";
+            if (canvasClient != null) {
+                debug += "CanvasClient : ";
+                if (canvasClient.getDebugString() != null) {
+                    debug += canvasClient.getDebugString();
+                } else {
+                    debug += "no debug string given";
+                }
+            } else if (webViewUrl != null) {
+                debug += "WebView URL : " + webViewUrl;
+            } else {
+                debug += "Layout resource : " +
+                        getActivity().getResources().getResourceName(layoutID);
+            }
+            debug += "\nTest ran in " + (useHardware ? "hardware" : "software") + "\n";
+            return debug;
+        }
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/CanvasClient.java b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/CanvasClient.java
new file mode 100644
index 0000000..a99c576
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/CanvasClient.java
@@ -0,0 +1,35 @@
+/*
+ * 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.uirendering.cts.testinfrastructure;
+
+import android.graphics.Canvas;
+
+/**
+ * A class that the tester will implement and create a set of drawing calls the tests would use
+ */
+public abstract class CanvasClient {
+    private String mDebugString;
+
+    public abstract void draw(Canvas canvas, int width, int height);
+
+    public String getDebugString() {
+        return mDebugString;
+    }
+
+    public void setDebugString(String debugString) {
+        mDebugString = debugString;
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/CanvasClientView.java b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/CanvasClientView.java
new file mode 100644
index 0000000..92242f0
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/CanvasClientView.java
@@ -0,0 +1,55 @@
+/*
+ * 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.uirendering.cts.testinfrastructure;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.view.View;
+
+/**
+ * A simple View that uses a CanvasClient to draw its contents
+ */
+public class CanvasClientView extends View {
+    private CanvasClient mCanvasClient;
+    private int mWidth;
+    private int mHeight;
+
+    public CanvasClientView(Context context, CanvasClient canvasClient, int width, int height) {
+        super(context);
+        mCanvasClient = canvasClient;
+        mWidth = width;
+        mHeight = height;
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        if (ActivityTestBase.DEBUG) {
+            String s = canvas.isHardwareAccelerated() ? "HARDWARE" : "SOFTWARE";
+            Paint paint = new Paint();
+            paint.setColor(Color.BLACK);
+            paint.setTextSize(20);
+            canvas.drawText(s, 200, 200, paint);
+        }
+        if (mCanvasClient != null) {
+            canvas.save();
+            canvas.clipRect(0, 0, mWidth, mHeight);
+            mCanvasClient.draw(canvas, mWidth, mHeight);
+            canvas.restore();
+        }
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DisplayModifier.java b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DisplayModifier.java
new file mode 100644
index 0000000..684293d
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DisplayModifier.java
@@ -0,0 +1,585 @@
+/*
+     * 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/LICENSE2.0
+     *
+     * Unless required by applicable law or agreed to in riting, 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.uirendering.cts.testinfrastructure;
+
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.RectF;
+import android.graphics.Xfermode;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Modifies the canvas and paint objects when called.
+ */
+public abstract class DisplayModifier {
+    private static final RectF gRect = new RectF(0, 0, 100, 100);
+    private static final float[] gPts = new float[]{
+            0, 100, 100, 0, 100, 200, 200, 100
+    };
+    private static final float[] gTriPts = new float[]{
+            75, 0, 130, 130, 130, 130, 0, 130, 0, 130, 75, 0
+    };
+    private static final int NUM_PARALLEL_LINES = 24;
+    private static final float[] gLinePts = new float[NUM_PARALLEL_LINES * 8 + gTriPts.length];
+    protected static final int MODIFIER_WIDTH = 180;
+    protected static final int MODIFIER_HEIGHT = 180;
+
+    public static final PorterDuff.Mode[] PORTERDUFF_MODES = new PorterDuff.Mode[] {
+        PorterDuff.Mode.SRC, PorterDuff.Mode.DST, PorterDuff.Mode.SRC_OVER,
+        PorterDuff.Mode.DST_OVER, PorterDuff.Mode.SRC_IN, PorterDuff.Mode.DST_IN,
+        PorterDuff.Mode.SRC_OUT, PorterDuff.Mode.DST_OUT, PorterDuff.Mode.SRC_ATOP,
+        PorterDuff.Mode.DST_ATOP, PorterDuff.Mode.XOR, PorterDuff.Mode.MULTIPLY,
+        PorterDuff.Mode.SCREEN
+    };
+
+    static {
+        int index;
+        for (index = 0; index < gTriPts.length; index++) {
+            gLinePts[index] = gTriPts[index];
+        }
+        float val = 0;
+        for (int i = 0; i < NUM_PARALLEL_LINES; i++) {
+            gLinePts[index + 0] = 150;
+            gLinePts[index + 1] = val;
+            gLinePts[index + 2] = 300;
+            gLinePts[index + 3] = val;
+            index += 4;
+            val += 8 + (2.0f / NUM_PARALLEL_LINES);
+        }
+        val = 0;
+        for (int i = 0; i < NUM_PARALLEL_LINES; i++) {
+            gLinePts[index + 0] = val;
+            gLinePts[index + 1] = 150;
+            gLinePts[index + 2] = val;
+            gLinePts[index + 3] = 300;
+            index += 4;
+            val += 8 + (2.0f / NUM_PARALLEL_LINES);
+        }
+    }
+
+    // This linked hash map contains each of the different things that can be done to a canvas and
+    // paint object, like anti-aliasing or drawing. Within those LinkedHashMaps are the various
+    // options for that specific topic, which contains a displaymodifier which will affect the
+    // given canvas and paint objects.
+    public static final LinkedHashMap<String, LinkedHashMap<String, DisplayModifier>> sMaps =
+            new LinkedHashMap<String, LinkedHashMap<String,DisplayModifier>>() {
+                {
+                    put("aa", new LinkedHashMap<String, DisplayModifier>() {
+                        {
+                            put("true", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setAntiAlias(true);
+                                }
+                            });
+                            put("false", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setAntiAlias(false);
+                                }
+                            });
+                        }
+                    });
+                    put("style", new LinkedHashMap<String, DisplayModifier>() {
+                        {
+                            put("fill", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStyle(Paint.Style.FILL);
+                                }
+                            });
+                            put("stroke", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStyle(Paint.Style.STROKE);
+                                }
+                            });
+                            put("fillAndStroke", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStyle(Paint.Style.FILL_AND_STROKE);
+                                }
+                            });
+                        }
+                    });
+                    put("strokeWidth", new LinkedHashMap<String, DisplayModifier>() {
+                        {
+                            put("hair", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStrokeWidth(0);
+                                }
+                            });
+                            put("0.3", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStrokeWidth(0.3f);
+                                }
+                            });
+                            put("1", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStrokeWidth(1);
+                                }
+                            });
+                            put("5", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStrokeWidth(5);
+                                }
+                            });
+                            put("30", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStrokeWidth(30);
+                                }
+                            });
+                        }
+                    });
+                    put("strokeCap", new LinkedHashMap<String, DisplayModifier>() {
+                        {
+                            put("butt", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStrokeCap(Paint.Cap.BUTT);
+                                }
+                            });
+                            put("round", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStrokeCap(Paint.Cap.ROUND);
+                                }
+                            });
+                            put("square", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStrokeCap(Paint.Cap.SQUARE);
+                                }
+                            });
+                        }
+                    });
+                    put("strokeJoin", new LinkedHashMap<String, DisplayModifier>() {
+                        {
+                            put("bevel", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStrokeJoin(Paint.Join.BEVEL);
+                                }
+                            });
+                            put("round", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStrokeJoin(Paint.Join.ROUND);
+                                }
+                            });
+                            put("miter", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setStrokeJoin(Paint.Join.MITER);
+                                }
+                            });
+                            // TODO: add miter0, miter1 etc to test miter distances
+                        }
+                    });
+
+                    put("transform", new LinkedHashMap<String, DisplayModifier>() {
+                        {
+                            put("noTransform", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                }
+                            });
+                            put("rotate5", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.rotate(5);
+                                }
+                            });
+                            put("rotate45", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.rotate(45);
+                                }
+                            });
+                            put("rotate90", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.rotate(90);
+                                    canvas.translate(0, -200);
+                                }
+                            });
+                            put("scale2x2", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.scale(2, 2);
+                                }
+                            });
+                            put("rot20scl1x4", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.rotate(20);
+                                    canvas.scale(1, 4);
+                                }
+                            });
+                        }
+                    });
+
+                    put("shader", new LinkedHashMap<String, DisplayModifier>() {
+                        {
+                            put("noShader", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                }
+                            });
+                            put("repeatShader", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setShader(ResourceModifier.instance().repeatShader);
+                                }
+                            });
+                            put("translatedShader", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setShader(ResourceModifier.instance().translatedShader);
+                                }
+                            });
+                            put("scaledShader", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setShader(ResourceModifier.instance().scaledShader);
+                                }
+                            });
+                            put("composeShader", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setShader(ResourceModifier.instance().composeShader);
+                                }
+                            });
+                            /*
+                            put("bad composeShader", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setShader(ResourceModifier.instance().nestedComposeShader);
+                                }
+                            });
+                            put("bad composeShader 2", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setShader(
+                                            ResourceModifier.instance().doubleGradientComposeShader);
+                                }
+                            });
+                            */
+                            put("horGradient", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setShader(ResourceModifier.instance().horGradient);
+                                }
+                            });
+                            put("diagGradient", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setShader(ResourceModifier.instance().diagGradient);
+                                }
+                            });
+                            put("vertGradient", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setShader(ResourceModifier.instance().vertGradient);
+                                }
+                            });
+                            put("radGradient", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setShader(ResourceModifier.instance().radGradient);
+                                }
+                            });
+                            put("sweepGradient", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setShader(ResourceModifier.instance().sweepGradient);
+                                }
+                            });
+                        }
+                    });
+
+                    put("xfermodes", new LinkedHashMap<String, DisplayModifier>() {
+                        {
+                            for (int i = 0 ; i < PORTERDUFF_MODES.length ; i++) {
+                                put(PORTERDUFF_MODES[i].toString(),
+                                        new XfermodeModifier(PORTERDUFF_MODES[i]));
+                            }
+                        }
+                    });
+
+                    put("colorfilters", new LinkedHashMap<String, DisplayModifier>() {
+                        {
+                            for (int i = 0 ; i < PORTERDUFF_MODES.length ; i++) {
+                                put(PORTERDUFF_MODES[i].toString(),
+                                        new ColorFilterModifier(PORTERDUFF_MODES[i]));
+                            }
+                        }
+                    });
+
+                    // FINAL MAP: DOES ACTUAL DRAWING
+                    put("drawing", new LinkedHashMap<String, DisplayModifier>() {
+                        {
+                            put("roundRect", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.drawRoundRect(gRect, 20, 20, paint);
+                                }
+                            });
+                            put("rect", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.drawRect(gRect, paint);
+                                }
+                            });
+                            put("circle", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.drawCircle(100, 100, 75, paint);
+                                }
+                            });
+                            put("oval", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.drawOval(gRect, paint);
+                                }
+                            });
+                            put("lines", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.drawLines(gLinePts, paint);
+                                }
+                            });
+                            /* drawPoints does not work with zero stroke width,
+                             * but it isn't a regression
+                             * TODO: fix hardware canvas so that drawPoints works
+                            put("plusPoints", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.drawPoints(gPts, paint);
+                                }
+                            });
+                             */
+                            put("text", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setTextSize(36);
+                                    canvas.drawText("TEXTTEST", 0, 50, paint);
+                                }
+                            });
+                            put("shadowtext", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    paint.setTextSize(36);
+                                    paint.setShadowLayer(3.0f, 0.0f, 3.0f, 0xffff00ff);
+                                    canvas.drawText("TEXTTEST", 0, 50, paint);
+                                }
+                            });
+                            put("bitmapMesh", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.drawBitmapMesh(ResourceModifier.instance().bitmap, 3, 3,
+                                            ResourceModifier.instance().bitmapVertices, 0, null, 0,
+                                            null);
+                                }
+                            });
+                            put("arc", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.drawArc(gRect, 260, 285, false, paint);
+                                }
+                            });
+                            put("arcFromCenter", new DisplayModifier() {
+                                @Override
+                                public void modifyDrawing(Paint paint, Canvas canvas) {
+                                    canvas.drawArc(gRect, 260, 285, true, paint);
+                                }
+                            });
+                        }
+                    });
+                    // WARNING: DON'T PUT MORE MAPS BELOW THIS
+                }
+            };
+
+    abstract public void modifyDrawing(Paint paint, Canvas canvas);
+
+    public static class Accessor {
+        public final static int AA_MASK =               0x1 << 0;
+        public final static int STYLE_MASK =            0x1 << 1;
+        public final static int STROKE_WIDTH_MASK =     0x1 << 2;
+        public final static int STROKE_CAP_MASK =       0x1 << 3;
+        public final static int STROKE_JOIN_MASK =      0x1 << 4;
+        public final static int TRANSFORM_MASK =        0x1 << 5;
+        public final static int SHADER_MASK =           0x1 << 6;
+        public final static int XFERMODE_MASK =         0x1 << 7;
+        public final static int COLOR_FILTER_MASK =     0x1 << 8;
+        public final static int SHAPES_MASK =           0x1 << 9;
+        public final static int ALL_OPTIONS_MASK =      (0x1 << 10) - 1;
+        public final static int SHAPES_INDEX = 9;
+        public final static int XFERMODE_INDEX = 7;
+        private final int mMask;
+
+        private String mDebugString;
+        private int[] mIndices;
+        private LinkedHashMap<String, LinkedHashMap<String, DisplayModifier>> mDisplayMap;
+
+        public Accessor(int mask) {
+            int totalModifiers = Integer.bitCount(mask);
+            mIndices = new int[totalModifiers];
+            mMask = mask;
+            // Create a Display Map of the valid indices
+            mDisplayMap = new LinkedHashMap<String, LinkedHashMap<String, DisplayModifier>>();
+            int index = 0;
+            for (String key : DisplayModifier.sMaps.keySet()) {
+                if (validIndex(index)) {
+                    mDisplayMap.put(key, DisplayModifier.sMaps.get(key));
+                }
+                index++;
+            }
+            mDebugString = "";
+        }
+
+        private LinkedHashMap<String, DisplayModifier> getMapAtIndex(int index) {
+            int i = 0;
+            for (LinkedHashMap<String, DisplayModifier> map : mDisplayMap.values()) {
+                if (i == index) {
+                    return map;
+                }
+                i++;
+            }
+            return null;
+        }
+
+        /**
+         * This will create the next combination of drawing commands. If we have done every combination,
+         * then we will return false.
+         * @return true if there is more combinations to do
+         */
+        public boolean step() {
+            int modifierMapIndex = mIndices.length - 1;
+            // Start from the last map, and loop until it is at the front
+            while (modifierMapIndex >= 0) {
+                LinkedHashMap<String, DisplayModifier> map = getMapAtIndex(modifierMapIndex);
+                mIndices[modifierMapIndex]++;
+
+                // If we are still at a valid index, then we don't need to update any others
+                if (mIndices[modifierMapIndex] < map.size()) {
+                    break;
+                }
+
+                // If we updated and it was outside the boundary, and it was the last index then
+                // we are done
+                if (modifierMapIndex == 0) {
+                    return false;
+                }
+                // If we ran off the end of the map, we need to update one more down the list
+                mIndices[modifierMapIndex] = 0;
+
+                modifierMapIndex--;
+            }
+            return true;
+        }
+
+        /**
+         * Modifies the canvas and paint given for the particular combination currently
+         */
+        public void modifyDrawing(Canvas canvas, Paint paint) {
+            final ArrayList<DisplayModifier> modifierArrayList = getModifierList();
+            for (DisplayModifier modifier : modifierArrayList) {
+                modifier.modifyDrawing(paint, canvas);
+            }
+        }
+
+        /**
+         * Gets a list of all the current modifications to be used.
+         */
+        private ArrayList<DisplayModifier> getModifierList() {
+            ArrayList<DisplayModifier> modifierArrayList = new ArrayList<DisplayModifier>();
+            int mapIndex = 0;
+            mDebugString = "";
+
+            // Through each possible category of modification
+            for (Map.Entry<String, LinkedHashMap<String, DisplayModifier>> entry :
+                    mDisplayMap.entrySet()) {
+                int displayModifierIndex = mIndices[mapIndex];
+                mDebugString += "Modification : " + entry.getKey();
+                // Loop until we find the modification we are going to use
+                for (Map.Entry<String, DisplayModifier> modifierEntry :
+                        entry.getValue().entrySet()) {
+                    // Once we find the modification we want, then we will add it to the list,
+                    // and the last applied modifications
+                    if (displayModifierIndex == 0) {
+                        mDebugString += " value : " + modifierEntry.getKey() + " ";
+                        modifierArrayList.add(modifierEntry.getValue());
+                        break;
+                    }
+                    displayModifierIndex--;
+                }
+                mapIndex++;
+            }
+            return modifierArrayList;
+        }
+
+        public String getDebugString() {
+            return mDebugString;
+        }
+
+        /**
+         * Using the given masks, it tells if the map at the given index should be used, or not.
+         */
+        private boolean validIndex(int index) {
+            return (mMask & (0x1 << index)) != 0;
+        }
+    }
+
+    private static class XfermodeModifier extends DisplayModifier {
+        private Xfermode mXfermode;
+
+        public XfermodeModifier(PorterDuff.Mode mode) {
+            mXfermode = new PorterDuffXfermode(mode);
+        }
+
+        @Override
+        public void modifyDrawing(Paint paint, Canvas canvas) {
+            paint.setXfermode(mXfermode);
+        }
+    }
+
+    private static class ColorFilterModifier extends DisplayModifier {
+        private static final int FILTER_COLOR = 0xFFBB0000;
+        private ColorFilter mColorFilter;
+
+        public ColorFilterModifier(PorterDuff.Mode mode) {
+            mColorFilter = new PorterDuffColorFilter(FILTER_COLOR, mode);
+        }
+
+        @Override
+        public void modifyDrawing(Paint paint, Canvas canvas) {
+            paint.setColorFilter(mColorFilter);
+        }
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java
new file mode 100644
index 0000000..4d4a012
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java
@@ -0,0 +1,142 @@
+/*
+ * 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.uirendering.cts.testinfrastructure;
+
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewTreeObserver;
+import android.webkit.WebView;
+
+/**
+ * A generic activity that uses a view specified by the user.
+ */
+public class DrawActivity extends Activity {
+    private final static long TIME_OUT = 10000;
+    private final Object mLock = new Object();
+    public static final int MIN_NUMBER_OF_DRAWS = 20;
+
+    private Handler mHandler;
+    private View mView;
+
+    public void onCreate(Bundle bundle){
+        super.onCreate(bundle);
+        mHandler = new RenderSpecHandler();
+    }
+
+    @Override
+    public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
+        mView = parent;
+        return super.onCreateView(parent, name, context, attrs);
+    }
+
+    public void enqueueRenderSpecAndWait(int layoutId, CanvasClient canvasClient, String webViewUrl,
+            @Nullable ViewInitializer viewInitializer, boolean useHardware) {
+        ((RenderSpecHandler) mHandler).setViewInitializer(viewInitializer);
+        int arg2 = (useHardware ? View.LAYER_TYPE_NONE : View.LAYER_TYPE_SOFTWARE);
+        if (canvasClient != null) {
+            mHandler.obtainMessage(RenderSpecHandler.CANVAS_MSG, 0, arg2, canvasClient).sendToTarget();
+        } else if (webViewUrl != null) {
+            mHandler.obtainMessage(RenderSpecHandler.WEB_VIEW_MSG, 0, arg2, webViewUrl).sendToTarget();
+        } else {
+            mHandler.obtainMessage(RenderSpecHandler.LAYOUT_MSG, layoutId, arg2).sendToTarget();
+        }
+
+        synchronized (mLock) {
+            try {
+                mLock.wait(TIME_OUT);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    private class RenderSpecHandler extends Handler {
+        public static final int LAYOUT_MSG = 1;
+        public static final int CANVAS_MSG = 2;
+        public static final int WEB_VIEW_MSG = 3;
+
+        private ViewInitializer mViewInitializer;
+
+        public void setViewInitializer(ViewInitializer viewInitializer) {
+            mViewInitializer = viewInitializer;
+        }
+
+        public void handleMessage(Message message) {
+            int webViewBuffer = 0;
+            switch (message.what) {
+                case LAYOUT_MSG: {
+                    setContentView(message.arg1);
+                } break;
+
+                case CANVAS_MSG: {
+                    mView = new CanvasClientView(getApplicationContext(),
+                            (CanvasClient) (message.obj), ActivityTestBase.TEST_WIDTH,
+                            ActivityTestBase.TEST_HEIGHT);
+                    setContentView(mView);
+                } break;
+
+                case WEB_VIEW_MSG: {
+                    mView = new WebView(getApplicationContext());
+                    ((WebView) mView).loadUrl((String) message.obj);
+                    ((WebView) mView).setInitialScale(100);
+                    setContentView(mView);
+                    webViewBuffer = 10;
+                } break;
+            }
+
+            if (mViewInitializer != null) {
+                mViewInitializer.intializeView(mView);
+            }
+
+            mView.setLayerType(message.arg2, null);
+
+            DrawCounterListener onDrawListener = new DrawCounterListener(webViewBuffer);
+
+            mView.getViewTreeObserver().addOnPreDrawListener(onDrawListener);
+
+            mView.postInvalidate();
+        }
+    }
+
+    private class DrawCounterListener implements ViewTreeObserver.OnPreDrawListener {
+        private int mCurrentDraws = 0;
+        private int mExtraDraws;
+
+        public DrawCounterListener(int extraDraws) {
+            mExtraDraws = extraDraws;
+        }
+
+        @Override
+        public boolean onPreDraw() {
+            mCurrentDraws++;
+            if (mCurrentDraws < MIN_NUMBER_OF_DRAWS + mExtraDraws) {
+                mView.postInvalidate();
+            } else {
+                synchronized (mLock) {
+                    mLock.notify();
+                }
+                mView.getViewTreeObserver().removeOnPreDrawListener(this);
+            }
+            return true;
+        }
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ResourceModifier.java b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ResourceModifier.java
new file mode 100644
index 0000000..5564b96
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ResourceModifier.java
@@ -0,0 +1,133 @@
+/*
+  * 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.uirendering.cts.testinfrastructure;
+
+import com.android.cts.uirendering.R;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.BitmapShader;
+import android.graphics.Color;
+import android.graphics.ComposeShader;
+import android.graphics.LinearGradient;
+import android.graphics.Matrix;
+import android.graphics.PorterDuff;
+import android.graphics.RadialGradient;
+import android.graphics.Shader;
+import android.graphics.SweepGradient;
+
+/**
+ * This will contain the resource-based content for the DisplayModifiers
+ */
+public class ResourceModifier {
+    private static ResourceModifier sInstance = null;
+
+    public final BitmapShader repeatShader;
+    public final BitmapShader translatedShader;
+    public final BitmapShader scaledShader;
+    public final LinearGradient horGradient;
+    public final LinearGradient diagGradient;
+    public final LinearGradient vertGradient;
+    public final RadialGradient radGradient;
+    public final SweepGradient sweepGradient;
+    public final ComposeShader composeShader;
+    public final ComposeShader nestedComposeShader;
+    public final ComposeShader doubleGradientComposeShader;
+    public final Bitmap bitmap;
+    public final float[] bitmapVertices;
+    public final int[] bitmapColors;
+
+    public ResourceModifier(Resources resources) {
+        bitmap = BitmapFactory.decodeResource(resources, R.drawable.sunset1);
+        int texWidth = bitmap.getWidth();
+        int texHeight = bitmap.getHeight();
+
+        int drawWidth = ActivityTestBase.TEST_WIDTH;
+        int drawHeight = ActivityTestBase.TEST_HEIGHT;
+
+        repeatShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT,
+                Shader.TileMode.REPEAT);
+
+        translatedShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT,
+                Shader.TileMode.REPEAT);
+        Matrix matrix = new Matrix();
+        matrix.setTranslate(texWidth / 2.0f, texHeight / 2.0f);
+        matrix.postRotate(45, 0, 0);
+        translatedShader.setLocalMatrix(matrix);
+
+        scaledShader = new BitmapShader(bitmap, Shader.TileMode.MIRROR,
+                Shader.TileMode.MIRROR);
+        matrix = new Matrix();
+        matrix.setScale(0.5f, 0.5f);
+        scaledShader.setLocalMatrix(matrix);
+
+        horGradient = new LinearGradient(0.0f, 0.0f, 1.0f, 0.0f,
+                Color.RED, Color.GREEN, Shader.TileMode.CLAMP);
+        matrix = new Matrix();
+        matrix.setScale(drawHeight, 1.0f);
+        matrix.postRotate(-90.0f);
+        matrix.postTranslate(0.0f, drawHeight);
+        horGradient.setLocalMatrix(matrix);
+
+        diagGradient = new LinearGradient(0.0f, 0.0f, drawWidth / 2.0f, drawHeight / 2.0f,
+                Color.BLUE, Color.RED, Shader.TileMode.CLAMP);
+
+        vertGradient = new LinearGradient(0.0f, 0.0f, 0.0f, drawHeight / 2.0f,
+                Color.YELLOW, Color.MAGENTA, Shader.TileMode.MIRROR);
+
+        sweepGradient = new SweepGradient(drawWidth / 2.0f, drawHeight / 2.0f,
+                Color.YELLOW, Color.MAGENTA);
+
+        composeShader = new ComposeShader(repeatShader, horGradient,
+                PorterDuff.Mode.MULTIPLY);
+
+        final float width = bitmap.getWidth() / 8.0f;
+        final float height = bitmap.getHeight() / 8.0f;
+
+        bitmapVertices = new float[]{
+                0.0f, 0.0f, width, 0.0f, width * 2, 0.0f, width * 3, 0.0f,
+                0.0f, height, width, height, width * 2, height, width * 4, height,
+                0.0f, height * 2, width, height * 2, width * 2, height * 2, width * 3, height * 2,
+                0.0f, height * 4, width, height * 4, width * 2, height * 4, width * 4, height * 4,
+        };
+
+        bitmapColors = new int[]{
+                0xffff0000, 0xff00ff00, 0xff0000ff, 0xffff0000,
+                0xff0000ff, 0xffff0000, 0xff00ff00, 0xff00ff00,
+                0xff00ff00, 0xff0000ff, 0xffff0000, 0xff00ff00,
+                0x00ff0000, 0x0000ff00, 0x000000ff, 0x00ff0000,
+        };
+
+        // Use a repeating gradient with many colors to test the non simple case.
+        radGradient = new RadialGradient(drawWidth / 4.0f, drawHeight / 4.0f, 4.0f,
+                bitmapColors, null, Shader.TileMode.REPEAT);
+
+        nestedComposeShader = new ComposeShader(radGradient, composeShader,
+                PorterDuff.Mode.MULTIPLY);
+
+        doubleGradientComposeShader = new ComposeShader(radGradient, vertGradient,
+                PorterDuff.Mode.MULTIPLY);
+    }
+
+    public static ResourceModifier instance() {
+        return sInstance;
+    }
+
+    public static void init(Resources resources) {
+        sInstance = new ResourceModifier(resources);
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ViewInitializer.java b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ViewInitializer.java
new file mode 100644
index 0000000..8980df3
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ViewInitializer.java
@@ -0,0 +1,25 @@
+/*
+ * 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.uirendering.cts.testinfrastructure;
+
+import android.view.View;
+
+/**
+ * Called after a view is created to set various properties on the view
+ */
+public abstract class ViewInitializer {
+    public abstract void intializeView(View view);
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/util/BitmapDumper.java b/tests/tests/uirendering/src/android/uirendering/cts/util/BitmapDumper.java
new file mode 100644
index 0000000..41e255b
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/util/BitmapDumper.java
@@ -0,0 +1,120 @@
+/*
+ * 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.uirendering.cts.util;
+
+import android.graphics.Bitmap;
+import android.uirendering.cts.differencevisualizers.DifferenceVisualizer;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import libcore.io.IoUtils;
+
+/**
+ * A utility class that will allow the user to save bitmaps to the sdcard on the device.
+ */
+public final class BitmapDumper {
+    private final static String TAG = "BitmapDumper";
+    private final static String IDEAL_RENDERING_FILE_NAME = "idealCapture.png";
+    private final static String TESTED_RENDERING_FILE_NAME = "testedCapture.png";
+    private final static String VISUALIZER_RENDERING_FILE_NAME = "visualizer.png";
+    private final static String SINGULAR_FILE_NAME = "capture.png";
+    private final static String CAPTURE_SUB_DIRECTORY = "/sdcard/UiRenderingCaptures/";
+
+    private BitmapDumper() {}
+
+    /**
+     * Deletes the specific files for the given test in a given class.
+     */
+    public static void deleteFileInClassFolder(String className, String testName) {
+        File directory = new File(CAPTURE_SUB_DIRECTORY + className);
+
+        String[] children = directory.list();
+        if (children == null) {
+            return;
+        }
+        for (String file : children) {
+            if (file.startsWith(testName)) {
+                new File(directory, file).delete();
+            }
+        }
+    }
+
+    public static void createSubDirectory(String className) {
+        File saveDirectory = new File(CAPTURE_SUB_DIRECTORY + className);
+        if (saveDirectory.exists()) {
+            return;
+        }
+        // Create the directory if it isn't already created.
+        saveDirectory.mkdirs();
+    }
+
+    /**
+     * Saves two files, one the capture of an ideal drawing, and one the capture of the tested
+     * drawing. The third file saved is a bitmap that is returned from the given visualizer's
+     * method.
+     * The files are saved to the sdcard directory
+     */
+    public static void dumpBitmaps(Bitmap idealBitmap, Bitmap testedBitmap, String testName,
+            String className, DifferenceVisualizer differenceVisualizer) {
+        Bitmap visualizerBitmap;
+
+        int width = idealBitmap.getWidth();
+        int height = idealBitmap.getHeight();
+        int[] testedArray = new int[width * height];
+        int[] idealArray = new int[width * height];
+        idealBitmap.getPixels(testedArray, 0, width, 0, 0, width, height);
+        testedBitmap.getPixels(idealArray, 0, width, 0, 0, width, height);
+        int[] visualizerArray = differenceVisualizer.getDifferences(idealArray, testedArray);
+        visualizerBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        visualizerBitmap.setPixels(visualizerArray, 0, width, 0, 0, width, height);
+        Bitmap croppedBitmap = Bitmap.createBitmap(testedBitmap, 0, 0, width, height);
+
+        saveFile(className, testName, IDEAL_RENDERING_FILE_NAME, idealBitmap);
+        saveFile(className, testName, TESTED_RENDERING_FILE_NAME, croppedBitmap);
+        saveFile(className, testName, VISUALIZER_RENDERING_FILE_NAME, visualizerBitmap);
+    }
+
+    public static void dumpBitmap(Bitmap bitmap, String testName, String className) {
+        if (bitmap == null) {
+            Log.d(TAG, "File not saved, bitmap was null for test : " + testName);
+            return;
+        }
+        saveFile(className, testName, SINGULAR_FILE_NAME, bitmap);
+    }
+
+    private static void saveFile(String className, String testName, String fileName, Bitmap bitmap) {
+        Log.d(TAG, "Saving file : " + testName + "_" + fileName + " in directory : " + className);
+        File file = new File(CAPTURE_SUB_DIRECTORY + className, testName + "_" + fileName);
+        FileOutputStream fileStream = null;
+        try {
+            fileStream = new FileOutputStream(file);
+            bitmap.compress(Bitmap.CompressFormat.PNG, 85, fileStream);
+            fileStream.flush();
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            if (fileStream != null) {
+                IoUtils.closeQuietly(fileStream);
+            }
+        }
+    }
+}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/util/CompareUtils.java b/tests/tests/uirendering/src/android/uirendering/cts/util/CompareUtils.java
new file mode 100644
index 0000000..4f246a4
--- /dev/null
+++ b/tests/tests/uirendering/src/android/uirendering/cts/util/CompareUtils.java
@@ -0,0 +1,15 @@
+package android.uirendering.cts.util;
+
+import android.graphics.Color;
+
+public class CompareUtils {
+    /**
+     * @return True if close enough
+     */
+    public static boolean verifyPixelWithThreshold(int color, int expectedColor, int threshold) {
+        int diff = Math.abs(Color.red(color) - Color.red(expectedColor))
+                + Math.abs(Color.green(color) - Color.green(expectedColor))
+                + Math.abs(Color.blue(color) - Color.blue(expectedColor));
+        return diff <= threshold;
+    }
+}
diff --git a/tests/tests/util/Android.mk b/tests/tests/util/Android.mk
index f1c75dc..75d23d7 100644
--- a/tests/tests/util/Android.mk
+++ b/tests/tests/util/Android.mk
@@ -21,16 +21,12 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsUtilTestCases
 
-LOCAL_INSTRUMENTATION_FOR := CtsTestStubs
-
 LOCAL_SDK_VERSION := current
 
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/util/AndroidManifest.xml b/tests/tests/util/AndroidManifest.xml
index 3969ac8..e40087a 100644
--- a/tests/tests/util/AndroidManifest.xml
+++ b/tests/tests/util/AndroidManifest.xml
@@ -19,13 +19,17 @@
     package="com.android.cts.util">
 
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+    <uses-permission android:name="android.permission.READ_LOGS" />
     <application>
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="com.android.cts.stub"
-                     android:label="CTS tests of android.util"/>
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.util"
+                     android:label="CTS tests of android.util">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/res/layout/xml_test.xml b/tests/tests/util/res/layout/xml_test.xml
similarity index 100%
rename from tests/res/layout/xml_test.xml
rename to tests/tests/util/res/layout/xml_test.xml
diff --git a/tests/tests/util/src/android/util/cts/ArrayMapTest.java b/tests/tests/util/src/android/util/cts/ArrayMapTest.java
new file mode 100644
index 0000000..7fdd0da
--- /dev/null
+++ b/tests/tests/util/src/android/util/cts/ArrayMapTest.java
@@ -0,0 +1,500 @@
+/*
+ * 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.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.test.AndroidTestCase;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+public class ArrayMapTest extends AndroidTestCase {
+    static final boolean DEBUG = false;
+
+    static final int OP_ADD = 1;
+    static final int OP_REM = 2;
+
+    static int[] OPS = new int[] {
+            OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+            OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+            OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+            OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+
+            OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+            OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+
+            OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+            OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+
+            OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+            OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+
+            OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+            OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD, OP_ADD,
+            OP_ADD, OP_ADD, OP_ADD,
+            OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+            OP_REM, OP_REM, OP_REM,
+            OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM, OP_REM,
+    };
+
+    static int[] KEYS = new int[] {
+            // General adding and removing.
+              -1,   1900,    600,    200,   1200,   1500,   1800,    100,   1900,
+            2100,    300,    800,    600,   1100,   1300,   2000,   1000,   1400,
+             600,     -1,   1900,    600,    300,   2100,    200,    800,    800,
+            1800,   1500,   1300,   1100,   2000,   1400,   1000,   1200,   1900,
+
+            // Shrink when removing item from end.
+             100,    200,    300,    400,    500,    600,    700,    800,    900,
+             900,    800,    700,    600,    500,    400,    300,    200,    100,
+
+            // Shrink when removing item from middle.
+             100,    200,    300,    400,    500,    600,    700,    800,    900,
+             900,    800,    700,    600,    500,    400,    200,    300,    100,
+
+            // Shrink when removing item from front.
+             100,    200,    300,    400,    500,    600,    700,    800,    900,
+             900,    800,    700,    600,    500,    400,    100,    200,    300,
+
+            // Test hash collisions.
+             105,    106,    108,    104,    102,    102,    107,      5,    205,
+               4,    202,    203,      3,      5,    101,    109,    200,    201,
+               0,     -1,    100,
+             106,    108,    104,    102,    103,    105,    107,    101,    109,
+              -1,    100,      0,
+               4,      5,      3,      5,    200,    203,    202,    201,    205,
+    };
+
+    public static class ControlledHash implements Parcelable {
+        final int mValue;
+
+        ControlledHash(int value) {
+            mValue = value;
+        }
+
+        @Override
+        public final boolean equals(Object o) {
+            if (o == null) {
+                return false;
+            }
+            return mValue == ((ControlledHash)o).mValue;
+        }
+
+        @Override
+        public final int hashCode() {
+            return mValue/100;
+        }
+
+        @Override
+        public final String toString() {
+            return Integer.toString(mValue);
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeInt(mValue);
+        }
+
+        public static final Parcelable.Creator<ControlledHash> CREATOR
+                = new Parcelable.Creator<ControlledHash>() {
+            public ControlledHash createFromParcel(Parcel in) {
+                return new ControlledHash(in.readInt());
+            }
+
+            public ControlledHash[] newArray(int size) {
+                return new ControlledHash[size];
+            }
+        };
+    }
+
+    private static boolean compare(Object v1, Object v2) {
+        if (v1 == null) {
+            return v2 == null;
+        }
+        if (v2 == null) {
+            return false;
+        }
+        return v1.equals(v2);
+    }
+
+    private static void compareMaps(HashMap map, ArrayMap array) {
+        if (map.size() != array.size()) {
+            fail("Bad size: expected " + map.size() + ", got " + array.size());
+        }
+
+        Set<Map.Entry> mapSet = map.entrySet();
+        for (Map.Entry entry : mapSet) {
+            Object expValue = entry.getValue();
+            Object gotValue = array.get(entry.getKey());
+            if (!compare(expValue, gotValue)) {
+                fail("Bad value: expected " + expValue + ", got " + gotValue
+                        + " at key " + entry.getKey());
+            }
+        }
+
+        for (int i=0; i<array.size(); i++) {
+            Object gotValue = array.valueAt(i);
+            Object key = array.keyAt(i);
+            Object expValue = map.get(key);
+            if (!compare(expValue, gotValue)) {
+                fail("Bad value: expected " + expValue + ", got " + gotValue
+                        + " at key " + key);
+            }
+        }
+
+        if (map.entrySet().hashCode() != array.entrySet().hashCode()) {
+            fail("Entry set hash codes differ: map=0x"
+                    + Integer.toHexString(map.entrySet().hashCode()) + " array=0x"
+                    + Integer.toHexString(array.entrySet().hashCode()));
+        }
+
+        if (!map.entrySet().equals(array.entrySet())) {
+            fail("Failed calling equals on map entry set against array set");
+        }
+
+        if (!array.entrySet().equals(map.entrySet())) {
+            fail("Failed calling equals on array entry set against map set");
+        }
+
+        if (map.keySet().hashCode() != array.keySet().hashCode()) {
+            fail("Key set hash codes differ: map=0x"
+                    + Integer.toHexString(map.keySet().hashCode()) + " array=0x"
+                    + Integer.toHexString(array.keySet().hashCode()));
+        }
+
+        if (!map.keySet().equals(array.keySet())) {
+            fail("Failed calling equals on map key set against array set");
+        }
+
+        if (!array.keySet().equals(map.keySet())) {
+            fail("Failed calling equals on array key set against map set");
+        }
+
+        if (!map.keySet().containsAll(array.keySet())) {
+            fail("Failed map key set contains all of array key set");
+        }
+
+        if (!array.keySet().containsAll(map.keySet())) {
+            fail("Failed array key set contains all of map key set");
+        }
+
+        if (!array.containsAll(map.keySet())) {
+            fail("Failed array contains all of map key set");
+        }
+
+        if (!map.entrySet().containsAll(array.entrySet())) {
+            fail("Failed map entry set contains all of array entry set");
+        }
+
+        if (!array.entrySet().containsAll(map.entrySet())) {
+            fail("Failed array entry set contains all of map entry set");
+        }
+    }
+
+    private static void validateArrayMap(ArrayMap array) {
+        Set<Map.Entry> entrySet = array.entrySet();
+        int index=0;
+        Iterator<Map.Entry> entryIt = entrySet.iterator();
+        while (entryIt.hasNext()) {
+            Map.Entry entry = entryIt.next();
+            Object value = entry.getKey();
+            Object realValue = array.keyAt(index);
+            if (!compare(realValue, value)) {
+                fail("Bad array map entry set: expected key " + realValue
+                        + ", got " + value + " at index " + index);
+            }
+            value = entry.getValue();
+            realValue = array.valueAt(index);
+            if (!compare(realValue, value)) {
+                fail("Bad array map entry set: expected value " + realValue
+                        + ", got " + value + " at index " + index);
+            }
+            index++;
+        }
+
+        index = 0;
+        Set keySet = array.keySet();
+        Iterator keyIt = keySet.iterator();
+        while (keyIt.hasNext()) {
+            Object value = keyIt.next();
+            Object realValue = array.keyAt(index);
+            if (!compare(realValue, value)) {
+                fail("Bad array map key set: expected key " + realValue
+                        + ", got " + value + " at index " + index);
+            }
+            index++;
+        }
+
+        index = 0;
+        Collection valueCol = array.values();
+        Iterator valueIt = valueCol.iterator();
+        while (valueIt.hasNext()) {
+            Object value = valueIt.next();
+            Object realValue = array.valueAt(index);
+            if (!compare(realValue, value)) {
+                fail("Bad array map value col: expected value " + realValue
+                        + ", got " + value + " at index " + index);
+            }
+            index++;
+        }
+    }
+
+    private static void compareBundles(Bundle bundle1, Bundle bundle2) {
+        Set<String> keySet1 = bundle1.keySet();
+        Iterator<String> iterator1 = keySet1.iterator();
+        while (iterator1.hasNext()) {
+            String key = iterator1.next();
+            int value1 = bundle1.getInt(key);
+            if (bundle2.get(key) == null) {
+                fail("Bad Bundle: bundle2 didn't have expected key " + key);
+            }
+            int value2 = bundle2.getInt(key);
+            if (value1 != value2) {
+                fail("Bad Bundle: at key key " + key + " expected " + value1 + ", got " + value2);
+            }
+        }
+        Set<String> keySet2 = bundle2.keySet();
+        Iterator<String> iterator2 = keySet2.iterator();
+        while (iterator2.hasNext()) {
+            String key = iterator2.next();
+            if (bundle1.get(key) == null) {
+                fail("Bad Bundle: bundle1 didn't have expected key " + key);
+            }
+            int value1 = bundle1.getInt(key);
+            int value2 = bundle2.getInt(key);
+            if (value1 != value2) {
+                fail("Bad Bundle: at key key " + key + " expected " + value1 + ", got " + value2);
+            }
+        }
+    }
+
+    private static void dump(Map map, ArrayMap array) {
+        Log.e("test", "HashMap of " + map.size() + " entries:");
+        Set<Map.Entry> mapSet = map.entrySet();
+        for (Map.Entry entry : mapSet) {
+            Log.e("test", "    " + entry.getKey() + " -> " + entry.getValue());
+        }
+        Log.e("test", "ArrayMap of " + array.size() + " entries:");
+        for (int i=0; i<array.size(); i++) {
+            Log.e("test", "    " + array.keyAt(i) + " -> " + array.valueAt(i));
+        }
+    }
+
+    private static void dump(ArrayMap map1, ArrayMap map2) {
+        Log.e("test", "ArrayMap of " + map1.size() + " entries:");
+        for (int i=0; i<map2.size(); i++) {
+            Log.e("test", "    " + map1.keyAt(i) + " -> " + map1.valueAt(i));
+        }
+        Log.e("test", "ArrayMap of " + map2.size() + " entries:");
+        for (int i=0; i<map2.size(); i++) {
+            Log.e("test", "    " + map2.keyAt(i) + " -> " + map2.valueAt(i));
+        }
+    }
+
+    private static void dump(Bundle bundle1, Bundle bundle2) {
+        Log.e("test", "First Bundle of " + bundle1.size() + " entries:");
+        Set<String> keys1 = bundle1.keySet();
+        for (String key : keys1) {
+            Log.e("test", "    " + key + " -> " + bundle1.get(key));
+        }
+        Log.e("test", "Second Bundle of " + bundle2.size() + " entries:");
+        Set<String> keys2 = bundle2.keySet();
+        for (String key : keys2) {
+            Log.e("test", "    " + key + " -> " + bundle2.get(key));
+        }
+    }
+
+    public void testBasicArrayMap() {
+        HashMap<ControlledHash, Integer> hashMap = new HashMap<ControlledHash, Integer>();
+        ArrayMap<ControlledHash, Integer> arrayMap = new ArrayMap<ControlledHash, Integer>();
+        Bundle bundle = new Bundle();
+
+        for (int i=0; i<OPS.length; i++) {
+            Integer oldHash;
+            Integer oldArray;
+            ControlledHash key = KEYS[i] < 0 ? null : new ControlledHash(KEYS[i]);
+            String strKey = KEYS[i] < 0 ? null : Integer.toString(KEYS[i]);
+            switch (OPS[i]) {
+                case OP_ADD:
+                    if (DEBUG) Log.i("test", "Adding key: " + key);
+                    oldHash = hashMap.put(key, i);
+                    oldArray = arrayMap.put(key, i);
+                    bundle.putInt(strKey, i);
+                    break;
+                case OP_REM:
+                    if (DEBUG) Log.i("test", "Removing key: " + key);
+                    oldHash = hashMap.remove(key);
+                    oldArray = arrayMap.remove(key);
+                    bundle.remove(strKey);
+                    break;
+                default:
+                    fail("Bad operation " + OPS[i] + " @ " + i);
+                    return;
+            }
+            if (!compare(oldHash, oldArray)) {
+                String msg = "Bad result: expected " + oldHash + ", got " + oldArray;
+                Log.e("test", msg);
+                dump(hashMap, arrayMap);
+                fail(msg);
+            }
+            try {
+                validateArrayMap(arrayMap);
+            } catch (Throwable e) {
+                Log.e("test", e.getMessage());
+                dump(hashMap, arrayMap);
+                throw e;
+            }
+            try {
+                compareMaps(hashMap, arrayMap);
+            } catch (Throwable e) {
+                Log.e("test", e.getMessage());
+                dump(hashMap, arrayMap);
+                throw e;
+            }
+            Parcel parcel = Parcel.obtain();
+            bundle.writeToParcel(parcel, 0);
+            parcel.setDataPosition(0);
+            Bundle bundle2 = parcel.readBundle();
+            try {
+                compareBundles(bundle, bundle2);
+            } catch (Throwable e) {
+                Log.e("test", e.getMessage());
+                dump(bundle, bundle2);
+                throw e;
+            }
+        }
+
+        arrayMap.put(new ControlledHash(50000), 100);
+        ControlledHash lookup = new ControlledHash(50000);
+        Iterator<ControlledHash> it = arrayMap.keySet().iterator();
+        while (it.hasNext()) {
+            if (it.next().equals(lookup)) {
+                it.remove();
+            }
+        }
+        if (arrayMap.containsKey(lookup)) {
+            String msg = "Bad map iterator: didn't remove test key";
+            Log.e("test", msg);
+            dump(hashMap, arrayMap);
+            fail(msg);
+        }
+
+        //Log.e("test", "Test successful; printing final map.");
+        //dump(hashMap, arrayMap);
+    }
+
+    public void testCopyArrayMap() {
+        // map copy constructor test
+        ArrayMap newMap = new ArrayMap<Integer, String>();
+        for (int i = 0; i < 10; ++i) {
+            newMap.put(i, String.valueOf(i));
+        }
+        ArrayMap mapCopy = new ArrayMap(newMap);
+        if (!compare(mapCopy, newMap)) {
+            String msg = "ArrayMap copy constructor failure: expected " +
+                    newMap + ", got " + mapCopy;
+            Log.e("test", msg);
+            dump(newMap, mapCopy);
+            fail(msg);
+            return;
+        }
+    }
+
+    public void testEqualsArrayMap() {
+        ArrayMap<Integer, String> map1 = new ArrayMap<Integer, String>();
+        ArrayMap<Integer, String> map2 = new ArrayMap<Integer, String>();
+        HashMap<Integer, String> map3 = new HashMap<Integer, String>();
+        if (!compare(map1, map2) || !compare(map1, map3) || !compare(map3, map2)) {
+            fail("ArrayMap equals failure for empty maps " + map1 + ", " +
+                    map2 + ", " + map3);
+        }
+
+        for (int i = 0; i < 10; ++i) {
+            String value = String.valueOf(i);
+            map1.put(i, value);
+            map2.put(i, value);
+            map3.put(i, value);
+        }
+        if (!compare(map1, map2) || !compare(map1, map3) || !compare(map3, map2)) {
+            fail("ArrayMap equals failure for populated maps " + map1 + ", " +
+                    map2 + ", " + map3);
+        }
+
+        map1.remove(0);
+        if (compare(map1, map2) || compare(map1, map3) || compare(map3, map1)) {
+            fail("ArrayMap equals failure for map size " + map1 + ", " +
+                    map2 + ", " + map3);
+        }
+
+        map1.put(0, "-1");
+        if (compare(map1, map2) || compare(map1, map3) || compare(map3, map1)) {
+            fail("ArrayMap equals failure for map contents " + map1 + ", " +
+                    map2 + ", " + map3);
+        }
+    }
+
+    /**
+     * Test creating a malformed array map with duplicated keys and that we will catch this
+     * when unparcelling.
+     */
+    public void testDuplicateKeys() throws NoSuchMethodException,
+            InvocationTargetException, IllegalAccessException, NoSuchFieldException {
+        ArrayMap<String, Object> map1 = new ArrayMap(2);
+
+        Method appendMethod = ArrayMap.class.getMethod("append", Object.class, Object.class);
+        appendMethod.invoke(map1, Integer.toString(100000), "foo");
+        appendMethod.invoke(map1, Integer.toString(100000), "bar");
+
+        // Now parcel/unparcel, and verify we get the expected error.
+        Parcel parcel = Parcel.obtain();
+        Method writeArrayMapMethod = Parcel.class.getMethod("writeArrayMap", ArrayMap.class);
+        writeArrayMapMethod.invoke(parcel, map1);
+        parcel.setDataPosition(0);
+        ArrayMap<String, Object> map2 = new ArrayMap(2);
+
+        try {
+            Parcel.class.getMethod("readArrayMap", ArrayMap.class, ClassLoader.class).invoke(
+                    parcel, map2, null);
+        } catch (InvocationTargetException e) {
+            Throwable cause = e.getCause();
+            if (cause instanceof IllegalArgumentException) {
+                // Good!
+                return;
+            }
+            throw e;
+        }
+
+        String msg = "Didn't throw expected IllegalArgumentException";
+        Log.e("test", msg);
+        dump(map1, map2);
+        fail(msg);
+    }
+}
diff --git a/tests/tests/util/src/android/util/cts/EventLogTest.java b/tests/tests/util/src/android/util/cts/EventLogTest.java
index 318b010..12df64f 100644
--- a/tests/tests/util/src/android/util/cts/EventLogTest.java
+++ b/tests/tests/util/src/android/util/cts/EventLogTest.java
@@ -69,7 +69,8 @@
         EventLog.writeEvent(ANSWER_TAG, 12345L, longString.toString());
         EventLog.writeEvent(ANSWER_TAG, longString.toString(), longString.toString());
         EventLog.writeEvent(ANSWER_TAG, longArray);
-
+        // Give the message some time to show up in the log
+        Thread.sleep(10);
         List<Event> events = getEventsAfterMarker(markerData, ANSWER_TAG);
         assertEquals(6, events.size());
 
diff --git a/tests/tests/util/src/android/util/cts/JsonReaderTest.java b/tests/tests/util/src/android/util/cts/JsonReaderTest.java
new file mode 100644
index 0000000..5a9b336
--- /dev/null
+++ b/tests/tests/util/src/android/util/cts/JsonReaderTest.java
@@ -0,0 +1,955 @@
+/*
+ * Copyright (C) 2010 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 java.io.IOException;
+import java.io.StringReader;
+import java.util.Arrays;
+import junit.framework.TestCase;
+
+import android.util.MalformedJsonException;
+import android.util.JsonReader;
+import android.util.JsonToken;
+
+public final class JsonReaderTest extends TestCase {
+
+    private static final int READER_BUFFER_SIZE = 1024;
+
+    public void testReadArray() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("[true, true]"));
+        reader.beginArray();
+        assertEquals(true, reader.nextBoolean());
+        assertEquals(true, reader.nextBoolean());
+        reader.endArray();
+        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
+    }
+
+    public void testReadEmptyArray() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("[]"));
+        reader.beginArray();
+        assertFalse(reader.hasNext());
+        reader.endArray();
+        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
+    }
+
+    public void testReadObject() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader(
+                "{\"a\": \"android\", \"b\": \"banana\"}"));
+        reader.beginObject();
+        assertEquals("a", reader.nextName());
+        assertEquals("android", reader.nextString());
+        assertEquals("b", reader.nextName());
+        assertEquals("banana", reader.nextString());
+        reader.endObject();
+        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
+    }
+
+    public void testReadEmptyObject() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("{}"));
+        reader.beginObject();
+        assertFalse(reader.hasNext());
+        reader.endObject();
+        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
+    }
+
+    public void testSkipObject() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader(
+                "{\"a\": { \"c\": [], \"d\": [true, true, {}] }, \"b\": \"banana\"}"));
+        reader.beginObject();
+        assertEquals("a", reader.nextName());
+        reader.skipValue();
+        assertEquals("b", reader.nextName());
+        reader.skipValue();
+        reader.endObject();
+        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
+    }
+
+    public void testSkipBeforeEndOfObject() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("{}"));
+        reader.beginObject();
+        try {
+            reader.skipValue();
+            fail("Should not be possible to skip without elements.");
+        } catch (IllegalStateException expected) {
+        }
+    }
+
+    public void testSkipBeforeEndOfArray() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("[]"));
+        reader.beginArray();
+        try {
+            reader.skipValue();
+            fail("Should not be possible to skip without elements.");
+        } catch (IllegalStateException expected) {
+        }
+    }
+
+    public void testSkipAfterEndOfDocument() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("{}"));
+        reader.beginObject();
+        reader.endObject();
+        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
+        try {
+            reader.skipValue();
+            fail("Should not be possible to skip without elements.");
+        } catch (IllegalStateException expected) {
+        }
+    }
+
+    public void testHelloWorld() throws IOException {
+        String json = "{\n" +
+                "   \"hello\": true,\n" +
+                "   \"foo\": [\"world\"]\n" +
+                "}";
+        JsonReader reader = new JsonReader(new StringReader(json));
+        reader.beginObject();
+        assertEquals("hello", reader.nextName());
+        assertEquals(true, reader.nextBoolean());
+        assertEquals("foo", reader.nextName());
+        reader.beginArray();
+        assertEquals("world", reader.nextString());
+        reader.endArray();
+        reader.endObject();
+        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
+    }
+
+    public void testNulls() {
+        try {
+            new JsonReader(null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    public void testEmptyString() throws IOException {
+        try {
+            new JsonReader(new StringReader("")).beginArray();
+        } catch (IOException expected) {
+        }
+        try {
+            new JsonReader(new StringReader("")).beginObject();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void testNoTopLevelObject() throws IOException {
+        try {
+            new JsonReader(new StringReader("true")).nextBoolean();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void testCharacterUnescaping() throws IOException {
+        String json = "[\"a\","
+                + "\"a\\\"\","
+                + "\"\\\"\","
+                + "\":\","
+                + "\",\","
+                + "\"\\b\","
+                + "\"\\f\","
+                + "\"\\n\","
+                + "\"\\r\","
+                + "\"\\t\","
+                + "\" \","
+                + "\"\\\\\","
+                + "\"{\","
+                + "\"}\","
+                + "\"[\","
+                + "\"]\","
+                + "\"\\u0000\","
+                + "\"\\u0019\","
+                + "\"\\u20AC\""
+                + "]";
+        JsonReader reader = new JsonReader(new StringReader(json));
+        reader.beginArray();
+        assertEquals("a", reader.nextString());
+        assertEquals("a\"", reader.nextString());
+        assertEquals("\"", reader.nextString());
+        assertEquals(":", reader.nextString());
+        assertEquals(",", reader.nextString());
+        assertEquals("\b", reader.nextString());
+        assertEquals("\f", reader.nextString());
+        assertEquals("\n", reader.nextString());
+        assertEquals("\r", reader.nextString());
+        assertEquals("\t", reader.nextString());
+        assertEquals(" ", reader.nextString());
+        assertEquals("\\", reader.nextString());
+        assertEquals("{", reader.nextString());
+        assertEquals("}", reader.nextString());
+        assertEquals("[", reader.nextString());
+        assertEquals("]", reader.nextString());
+        assertEquals("\0", reader.nextString());
+        assertEquals("\u0019", reader.nextString());
+        assertEquals("\u20AC", reader.nextString());
+        reader.endArray();
+        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
+    }
+
+    public void testIntegersWithFractionalPartSpecified() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("[1.0,1.0,1.0]"));
+        reader.beginArray();
+        assertEquals(1.0, reader.nextDouble());
+        assertEquals(1, reader.nextInt());
+        assertEquals(1L, reader.nextLong());
+    }
+
+    public void testDoubles() throws IOException {
+        String json = "[-0.0,"
+                + "1.0,"
+                + "1.7976931348623157E308,"
+                + "4.9E-324,"
+                + "0.0,"
+                + "-0.5,"
+                + "2.2250738585072014E-308,"
+                + "3.141592653589793,"
+                + "2.718281828459045,"
+                + "\"1.0\","
+                + "\"011.0\","
+                + "\"NaN\","
+                + "\"Infinity\","
+                + "\"-Infinity\""
+                + "]";
+        JsonReader reader = new JsonReader(new StringReader(json));
+        reader.beginArray();
+        assertEquals(-0.0, reader.nextDouble());
+        assertEquals(1.0, reader.nextDouble());
+        assertEquals(1.7976931348623157E308, reader.nextDouble());
+        assertEquals(4.9E-324, reader.nextDouble());
+        assertEquals(0.0, reader.nextDouble());
+        assertEquals(-0.5, reader.nextDouble());
+        assertEquals(2.2250738585072014E-308, reader.nextDouble());
+        assertEquals(3.141592653589793, reader.nextDouble());
+        assertEquals(2.718281828459045, reader.nextDouble());
+        assertEquals(1,0, reader.nextDouble());
+        assertEquals(11.0, reader.nextDouble());
+        assertTrue(Double.isNaN(reader.nextDouble()));
+        assertEquals(Double.POSITIVE_INFINITY, reader.nextDouble());
+        assertEquals(Double.NEGATIVE_INFINITY, reader.nextDouble());
+        reader.endArray();
+        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
+    }
+
+    public void testLenientDoubles() throws IOException {
+        String json = "["
+                + "011.0,"
+                + "NaN,"
+                + "NAN,"
+                + "Infinity,"
+                + "INFINITY,"
+                + "-Infinity"
+                + "]";
+        JsonReader reader = new JsonReader(new StringReader(json));
+        reader.setLenient(true);
+        reader.beginArray();
+        assertEquals(11.0, reader.nextDouble());
+        assertTrue(Double.isNaN(reader.nextDouble()));
+        try {
+            reader.nextDouble();
+            fail();
+        } catch (NumberFormatException expected) {
+        }
+        assertEquals("NAN", reader.nextString());
+        assertEquals(Double.POSITIVE_INFINITY, reader.nextDouble());
+        try {
+            reader.nextDouble();
+            fail();
+        } catch (NumberFormatException expected) {
+        }
+        assertEquals("INFINITY", reader.nextString());
+        assertEquals(Double.NEGATIVE_INFINITY, reader.nextDouble());
+        reader.endArray();
+        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
+    }
+
+    public void testBufferBoundary() throws IOException {
+        char[] pad = new char[READER_BUFFER_SIZE - 8];
+        Arrays.fill(pad, '5');
+        String json = "[\"" + new String(pad) + "\",33333]";
+        JsonReader reader = new JsonReader(new StringReader(json));
+        reader.beginArray();
+        assertEquals(JsonToken.STRING, reader.peek());
+        assertEquals(new String(pad), reader.nextString());
+        assertEquals(JsonToken.NUMBER, reader.peek());
+        assertEquals(33333, reader.nextInt());
+    }
+
+    public void testTruncatedBufferBoundary() throws IOException {
+        char[] pad = new char[READER_BUFFER_SIZE - 8];
+        Arrays.fill(pad, '5');
+        String json = "[\"" + new String(pad) + "\",33333";
+        JsonReader reader = new JsonReader(new StringReader(json));
+        reader.setLenient(true);
+        reader.beginArray();
+        assertEquals(JsonToken.STRING, reader.peek());
+        assertEquals(new String(pad), reader.nextString());
+        assertEquals(JsonToken.NUMBER, reader.peek());
+        assertEquals(33333, reader.nextInt());
+        try {
+            reader.endArray();
+            fail();
+        } catch (IOException e) {
+        }
+    }
+
+    public void testLongestSupportedNumericLiterals() throws IOException {
+        testLongNumericLiterals(READER_BUFFER_SIZE - 1, JsonToken.NUMBER);
+    }
+
+    public void testLongerNumericLiterals() throws IOException {
+        testLongNumericLiterals(READER_BUFFER_SIZE, JsonToken.STRING);
+    }
+
+    private void testLongNumericLiterals(int length, JsonToken expectedToken) throws IOException {
+        char[] longNumber = new char[length];
+        Arrays.fill(longNumber, '9');
+        longNumber[0] = '1';
+        longNumber[1] = '.';
+
+        String json = "[" + new String(longNumber) + "]";
+        JsonReader reader = new JsonReader(new StringReader(json));
+        reader.setLenient(true);
+        reader.beginArray();
+        assertEquals(expectedToken, reader.peek());
+        assertEquals(2.0d, reader.nextDouble());
+        reader.endArray();
+    }
+
+    public void testLongs() throws IOException {
+        String json = "[0,0,0,"
+                + "1,1,1,"
+                + "-1,-1,-1,"
+                + "-9223372036854775808,"
+                + "9223372036854775807,"
+                + "5.0,"
+                + "1.0e2,"
+                + "\"011\","
+                + "\"5.0\","
+                + "\"1.0e2\""
+                + "]";
+        JsonReader reader = new JsonReader(new StringReader(json));
+        reader.beginArray();
+        assertEquals(0L, reader.nextLong());
+        assertEquals(0, reader.nextInt());
+        assertEquals(0.0, reader.nextDouble());
+        assertEquals(1L, reader.nextLong());
+        assertEquals(1, reader.nextInt());
+        assertEquals(1.0, reader.nextDouble());
+        assertEquals(-1L, reader.nextLong());
+        assertEquals(-1, reader.nextInt());
+        assertEquals(-1.0, reader.nextDouble());
+        try {
+            reader.nextInt();
+            fail();
+        } catch (NumberFormatException expected) {
+        }
+        assertEquals(Long.MIN_VALUE, reader.nextLong());
+        try {
+            reader.nextInt();
+            fail();
+        } catch (NumberFormatException expected) {
+        }
+        assertEquals(Long.MAX_VALUE, reader.nextLong());
+        assertEquals(5, reader.nextLong());
+        assertEquals(100, reader.nextLong());
+        assertEquals(11, reader.nextLong());
+        assertEquals(5, reader.nextLong());
+        assertEquals(100, reader.nextLong());
+        reader.endArray();
+        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
+    }
+
+    public void testHighPrecisionDouble_losesPrecision() throws IOException {
+        // The presence of a fractional part forces us to use Double.parseDouble
+        // instead of Long.parseLong (even though the fractional part is 0).
+        //
+        // A 52 bit mantissa isn't sufficient to precisely represent any of these
+        // values, so we will lose some precision, thereby storing it as
+        // ~(9.223372036854776E18). This value is then implicitly converted into
+        // a long and is required by the JLS to be clamped to Long.MAX_VALUE since
+        // it's larger than the largest long.
+        String json = "["
+                + "9223372036854775806.000,"  // Long.MAX_VALUE - 1
+                + "9223372036854775807.000,"  // Long.MAX_VALUE
+                + "9223372036854775808.000"   // Long.MAX_VALUE + 1
+                + "]";
+        JsonReader reader = new JsonReader(new StringReader(json));
+        reader.beginArray();
+        assertEquals(Long.MAX_VALUE, reader.nextLong());
+        assertEquals(Long.MAX_VALUE, reader.nextLong());
+        assertEquals(Long.MAX_VALUE, reader.nextLong());
+        reader.endArray();
+    }
+
+    public void testMatchingValidNumbers() throws IOException {
+        String json = "[-1,99,-0,0,0e1,0e+1,0e-1,0E1,0E+1,0E-1,0.0,1.0,-1.0,1.0e0,1.0e+1,1.0e-1]";
+        JsonReader reader = new JsonReader(new StringReader(json));
+        reader.beginArray();
+        for (int i = 0; i < 16; i++) {
+            assertEquals(JsonToken.NUMBER, reader.peek());
+            reader.nextDouble();
+        }
+        reader.endArray();
+    }
+
+    public void testRecognizingInvalidNumbers() throws IOException {
+        String json = "[-00,00,001,+1,1f,0x,0xf,0x0,0f1,0ee1,1..0,1e0.1,1.-01,1.+1,1.0x,1.0+]";
+        JsonReader reader = new JsonReader(new StringReader(json));
+        reader.setLenient(true);
+        reader.beginArray();
+        for (int i = 0; i < 16; i++) {
+            assertEquals(JsonToken.STRING, reader.peek());
+            reader.nextString();
+        }
+        reader.endArray();
+    }
+
+    public void testNonFiniteDouble() throws IOException {
+        String json = "[NaN]";
+        JsonReader reader = new JsonReader(new StringReader(json));
+        reader.beginArray();
+        try {
+            reader.nextDouble();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void testNumberWithHexPrefix() throws IOException {
+        String json = "[0x11]";
+        JsonReader reader = new JsonReader(new StringReader(json));
+        reader.beginArray();
+        try {
+            reader.nextLong();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void testNumberWithOctalPrefix() throws IOException {
+        String json = "[01]";
+        JsonReader reader = new JsonReader(new StringReader(json));
+        reader.beginArray();
+        try {
+            reader.nextInt();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void testBooleans() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("[true,false]"));
+        reader.beginArray();
+        assertEquals(true, reader.nextBoolean());
+        assertEquals(false, reader.nextBoolean());
+        reader.endArray();
+        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
+    }
+
+    public void testMixedCaseLiterals() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("[True,TruE,False,FALSE,NULL,nulL]"));
+        reader.beginArray();
+        assertEquals(true, reader.nextBoolean());
+        assertEquals(true, reader.nextBoolean());
+        assertEquals(false, reader.nextBoolean());
+        assertEquals(false, reader.nextBoolean());
+        reader.nextNull();
+        reader.nextNull();
+        reader.endArray();
+        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
+    }
+
+    public void testMissingValue() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("{\"a\":}"));
+        reader.beginObject();
+        assertEquals("a", reader.nextName());
+        try {
+            reader.nextString();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void testPrematureEndOfInput() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("{\"a\":true,"));
+        reader.beginObject();
+        assertEquals("a", reader.nextName());
+        assertEquals(true, reader.nextBoolean());
+        try {
+            reader.nextName();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void testPrematurelyClosed() throws IOException {
+        try {
+            JsonReader reader = new JsonReader(new StringReader("{\"a\":[]}"));
+            reader.beginObject();
+            reader.close();
+            reader.nextName();
+            fail();
+        } catch (IllegalStateException expected) {
+        }
+
+        try {
+            JsonReader reader = new JsonReader(new StringReader("{\"a\":[]}"));
+            reader.close();
+            reader.beginObject();
+            fail();
+        } catch (IllegalStateException expected) {
+        }
+
+        try {
+            JsonReader reader = new JsonReader(new StringReader("{\"a\":true}"));
+            reader.beginObject();
+            reader.nextName();
+            reader.peek();
+            reader.close();
+            reader.nextBoolean();
+            fail();
+        } catch (IllegalStateException expected) {
+        }
+    }
+
+    public void testNextFailuresDoNotAdvance() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("{\"a\":true}"));
+        reader.beginObject();
+        try {
+            reader.nextString();
+            fail();
+        } catch (IllegalStateException expected) {
+        }
+        assertEquals("a", reader.nextName());
+        try {
+            reader.nextName();
+            fail();
+        } catch (IllegalStateException expected) {
+        }
+        try {
+            reader.beginArray();
+            fail();
+        } catch (IllegalStateException expected) {
+        }
+        try {
+            reader.endArray();
+            fail();
+        } catch (IllegalStateException expected) {
+        }
+        try {
+            reader.beginObject();
+            fail();
+        } catch (IllegalStateException expected) {
+        }
+        try {
+            reader.endObject();
+            fail();
+        } catch (IllegalStateException expected) {
+        }
+        assertEquals(true, reader.nextBoolean());
+        try {
+            reader.nextString();
+            fail();
+        } catch (IllegalStateException expected) {
+        }
+        try {
+            reader.nextName();
+            fail();
+        } catch (IllegalStateException expected) {
+        }
+        try {
+            reader.beginArray();
+            fail();
+        } catch (IllegalStateException expected) {
+        }
+        try {
+            reader.endArray();
+            fail();
+        } catch (IllegalStateException expected) {
+        }
+        reader.endObject();
+        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
+        reader.close();
+    }
+
+    public void testStringNullIsNotNull() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("[\"null\"]"));
+        reader.beginArray();
+        try {
+            reader.nextNull();
+            fail();
+        } catch (IllegalStateException expected) {
+        }
+    }
+
+    public void testNullLiteralIsNotAString() throws IOException {
+       JsonReader reader = new JsonReader(new StringReader("[null]"));
+        reader.beginArray();
+        try {
+            reader.nextString();
+            fail();
+        } catch (IllegalStateException expected) {
+        }
+    }
+
+    public void testStrictNameValueSeparator() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("{\"a\"=true}"));
+        reader.beginObject();
+        assertEquals("a", reader.nextName());
+        try {
+            reader.nextBoolean();
+            fail();
+        } catch (IOException expected) {
+        }
+
+        reader = new JsonReader(new StringReader("{\"a\"=>true}"));
+        reader.beginObject();
+        assertEquals("a", reader.nextName());
+        try {
+            reader.nextBoolean();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void testLenientNameValueSeparator() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("{\"a\"=true}"));
+        reader.setLenient(true);
+        reader.beginObject();
+        assertEquals("a", reader.nextName());
+        assertEquals(true, reader.nextBoolean());
+
+        reader = new JsonReader(new StringReader("{\"a\"=>true}"));
+        reader.setLenient(true);
+        reader.beginObject();
+        assertEquals("a", reader.nextName());
+        assertEquals(true, reader.nextBoolean());
+    }
+
+    public void testStrictComments() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("[// comment \n true]"));
+        reader.beginArray();
+        try {
+            reader.nextBoolean();
+            fail();
+        } catch (IOException expected) {
+        }
+
+        reader = new JsonReader(new StringReader("[# comment \n true]"));
+        reader.beginArray();
+        try {
+            reader.nextBoolean();
+            fail();
+        } catch (IOException expected) {
+        }
+
+        reader = new JsonReader(new StringReader("[/* comment */ true]"));
+        reader.beginArray();
+        try {
+            reader.nextBoolean();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void testLenientComments() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("[// comment \n true]"));
+        reader.setLenient(true);
+        reader.beginArray();
+        assertEquals(true, reader.nextBoolean());
+
+        reader = new JsonReader(new StringReader("[# comment \n true]"));
+        reader.setLenient(true);
+        reader.beginArray();
+        assertEquals(true, reader.nextBoolean());
+
+        reader = new JsonReader(new StringReader("[/* comment */ true]"));
+        reader.setLenient(true);
+        reader.beginArray();
+        assertEquals(true, reader.nextBoolean());
+    }
+
+    public void testStrictUnquotedNames() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("{a:true}"));
+        reader.beginObject();
+        try {
+            reader.nextName();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void testLenientUnquotedNames() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("{a:true}"));
+        reader.setLenient(true);
+        reader.beginObject();
+        assertEquals("a", reader.nextName());
+    }
+
+    public void testStrictSingleQuotedNames() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("{'a':true}"));
+        reader.beginObject();
+        try {
+            reader.nextName();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void testLenientSingleQuotedNames() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("{'a':true}"));
+        reader.setLenient(true);
+        reader.beginObject();
+        assertEquals("a", reader.nextName());
+    }
+
+    public void testStrictUnquotedStrings() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("[a]"));
+        reader.beginArray();
+        try {
+            reader.nextString();
+            fail();
+        } catch (MalformedJsonException expected) {
+        }
+    }
+
+    public void testLenientUnquotedStrings() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("[a]"));
+        reader.setLenient(true);
+        reader.beginArray();
+        assertEquals("a", reader.nextString());
+    }
+
+    public void testStrictSingleQuotedStrings() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("['a']"));
+        reader.beginArray();
+        try {
+            reader.nextString();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void testLenientSingleQuotedStrings() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("['a']"));
+        reader.setLenient(true);
+        reader.beginArray();
+        assertEquals("a", reader.nextString());
+    }
+
+    public void testStrictSemicolonDelimitedArray() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("[true;true]"));
+        reader.beginArray();
+        try {
+            reader.nextBoolean();
+            reader.nextBoolean();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void testLenientSemicolonDelimitedArray() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("[true;true]"));
+        reader.setLenient(true);
+        reader.beginArray();
+        assertEquals(true, reader.nextBoolean());
+        assertEquals(true, reader.nextBoolean());
+    }
+
+    public void testStrictSemicolonDelimitedNameValuePair() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("{\"a\":true;\"b\":true}"));
+        reader.beginObject();
+        assertEquals("a", reader.nextName());
+        try {
+            reader.nextBoolean();
+            reader.nextName();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void testLenientSemicolonDelimitedNameValuePair() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("{\"a\":true;\"b\":true}"));
+        reader.setLenient(true);
+        reader.beginObject();
+        assertEquals("a", reader.nextName());
+        assertEquals(true, reader.nextBoolean());
+        assertEquals("b", reader.nextName());
+    }
+
+    public void testStrictUnnecessaryArraySeparators() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("[true,,true]"));
+        reader.beginArray();
+        assertEquals(true, reader.nextBoolean());
+        try {
+            reader.nextNull();
+            fail();
+        } catch (IOException expected) {
+        }
+
+        reader = new JsonReader(new StringReader("[,true]"));
+        reader.beginArray();
+        try {
+            reader.nextNull();
+            fail();
+        } catch (IOException expected) {
+        }
+
+        reader = new JsonReader(new StringReader("[true,]"));
+        reader.beginArray();
+        assertEquals(true, reader.nextBoolean());
+        try {
+            reader.nextNull();
+            fail();
+        } catch (IOException expected) {
+        }
+
+        reader = new JsonReader(new StringReader("[,]"));
+        reader.beginArray();
+        try {
+            reader.nextNull();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void testLenientUnnecessaryArraySeparators() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("[true,,true]"));
+        reader.setLenient(true);
+        reader.beginArray();
+        assertEquals(true, reader.nextBoolean());
+        reader.nextNull();
+        assertEquals(true, reader.nextBoolean());
+        reader.endArray();
+
+        reader = new JsonReader(new StringReader("[,true]"));
+        reader.setLenient(true);
+        reader.beginArray();
+        reader.nextNull();
+        assertEquals(true, reader.nextBoolean());
+        reader.endArray();
+
+        reader = new JsonReader(new StringReader("[true,]"));
+        reader.setLenient(true);
+        reader.beginArray();
+        assertEquals(true, reader.nextBoolean());
+        reader.nextNull();
+        reader.endArray();
+
+        reader = new JsonReader(new StringReader("[,]"));
+        reader.setLenient(true);
+        reader.beginArray();
+        reader.nextNull();
+        reader.nextNull();
+        reader.endArray();
+    }
+
+    public void testStrictMultipleTopLevelValues() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("[] []"));
+        reader.beginArray();
+        reader.endArray();
+        try {
+            reader.peek();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void testLenientMultipleTopLevelValues() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("[] true {}"));
+        reader.setLenient(true);
+        reader.beginArray();
+        reader.endArray();
+        assertEquals(true, reader.nextBoolean());
+        reader.beginObject();
+        reader.endObject();
+        assertEquals(JsonToken.END_DOCUMENT, reader.peek());
+    }
+
+    public void testStrictTopLevelValueType() {
+        JsonReader reader = new JsonReader(new StringReader("true"));
+        try {
+            reader.nextBoolean();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void testLenientTopLevelValueType() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("true"));
+        reader.setLenient(true);
+        assertEquals(true, reader.nextBoolean());
+    }
+
+    public void testStrictNonExecutePrefix() {
+        JsonReader reader = new JsonReader(new StringReader(")]}'\n []"));
+        try {
+            reader.beginArray();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void testBomIgnoredAsFirstCharacterOfDocument() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("\ufeff[]"));
+        reader.beginArray();
+        reader.endArray();
+    }
+
+    public void testBomForbiddenAsOtherCharacterInDocument() throws IOException {
+        JsonReader reader = new JsonReader(new StringReader("[\ufeff]"));
+        reader.beginArray();
+        try {
+            reader.endArray();
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
+    public void testFailWithPosition() throws IOException {
+        testFailWithPosition("Expected literal value at line 6 column 3",
+                "[\n\n\n\n\n0,}]");
+    }
+
+    public void testFailWithPositionIsOffsetByBom() throws IOException {
+        testFailWithPosition("Expected literal value at line 1 column 4",
+                "\ufeff[0,}]");
+    }
+
+    public void testFailWithPositionGreaterThanBufferSize() throws IOException {
+        String spaces = repeat(' ', 8192);
+        testFailWithPosition("Expected literal value at line 6 column 3",
+                "[\n\n" + spaces + "\n\n\n0,}]");
+    }
+
+    private void testFailWithPosition(String message, String json) throws IOException {
+        JsonReader reader = new JsonReader(new StringReader(json));
+        reader.beginArray();
+        reader.nextInt();
+        try {
+            reader.peek();
+            fail();
+        } catch (IOException expected) {
+            assertEquals(message, expected.getMessage());
+        }
+    }
+
+    private String repeat(char c, int count) {
+        char[] array = new char[count];
+        Arrays.fill(array, c);
+        return new String(array);
+    }
+}
diff --git a/tests/tests/util/src/android/util/cts/JsonWriterTest.java b/tests/tests/util/src/android/util/cts/JsonWriterTest.java
new file mode 100644
index 0000000..d0207d2
--- /dev/null
+++ b/tests/tests/util/src/android/util/cts/JsonWriterTest.java
@@ -0,0 +1,468 @@
+/*
+ * Copyright (C) 2010 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 java.io.IOException;
+import java.io.StringWriter;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import junit.framework.TestCase;
+
+import android.util.JsonWriter;
+
+public final class JsonWriterTest extends TestCase {
+
+    public void testWrongTopLevelType() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        try {
+            jsonWriter.value("a");
+            fail();
+        } catch (IllegalStateException expected) {
+        }
+    }
+
+    public void testTwoNames() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginObject();
+        jsonWriter.name("a");
+        try {
+            jsonWriter.name("a");
+            fail();
+        } catch (IllegalStateException expected) {
+        }
+    }
+
+    public void testNameWithoutValue() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginObject();
+        jsonWriter.name("a");
+        try {
+            jsonWriter.endObject();
+            fail();
+        } catch (IllegalStateException expected) {
+        }
+    }
+
+    public void testValueWithoutName() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginObject();
+        try {
+            jsonWriter.value(true);
+            fail();
+        } catch (IllegalStateException expected) {
+        }
+    }
+
+    public void testMultipleTopLevelValues() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginArray().endArray();
+        try {
+            jsonWriter.beginArray();
+            fail();
+        } catch (IllegalStateException expected) {
+        }
+    }
+
+    public void testBadNestingObject() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginArray();
+        jsonWriter.beginObject();
+        try {
+            jsonWriter.endArray();
+            fail();
+        } catch (IllegalStateException expected) {
+        }
+    }
+
+    public void testBadNestingArray() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginArray();
+        jsonWriter.beginArray();
+        try {
+            jsonWriter.endObject();
+            fail();
+        } catch (IllegalStateException expected) {
+        }
+    }
+
+    public void testNullName() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginObject();
+        try {
+            jsonWriter.name(null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    public void testNullStringValue() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginObject();
+        jsonWriter.name("a");
+        jsonWriter.value((String) null);
+        jsonWriter.endObject();
+        assertEquals("{\"a\":null}", stringWriter.toString());
+    }
+
+    public void testNonFiniteDoubles() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginArray();
+        try {
+            jsonWriter.value(Double.NaN);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            jsonWriter.value(Double.NEGATIVE_INFINITY);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            jsonWriter.value(Double.POSITIVE_INFINITY);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    public void testNonFiniteBoxedDoubles() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginArray();
+        try {
+            jsonWriter.value(new Double(Double.NaN));
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            jsonWriter.value(new Double(Double.NEGATIVE_INFINITY));
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            jsonWriter.value(new Double(Double.POSITIVE_INFINITY));
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    public void testDoubles() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginArray();
+        jsonWriter.value(-0.0);
+        jsonWriter.value(1.0);
+        jsonWriter.value(Double.MAX_VALUE);
+        jsonWriter.value(Double.MIN_VALUE);
+        jsonWriter.value(0.0);
+        jsonWriter.value(-0.5);
+        jsonWriter.value(Double.MIN_NORMAL);
+        jsonWriter.value(Math.PI);
+        jsonWriter.value(Math.E);
+        jsonWriter.endArray();
+        jsonWriter.close();
+        assertEquals("[-0.0,"
+                + "1.0,"
+                + "1.7976931348623157E308,"
+                + "4.9E-324,"
+                + "0.0,"
+                + "-0.5,"
+                + "2.2250738585072014E-308,"
+                + "3.141592653589793,"
+                + "2.718281828459045]", stringWriter.toString());
+    }
+
+    public void testLongs() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginArray();
+        jsonWriter.value(0);
+        jsonWriter.value(1);
+        jsonWriter.value(-1);
+        jsonWriter.value(Long.MIN_VALUE);
+        jsonWriter.value(Long.MAX_VALUE);
+        jsonWriter.endArray();
+        jsonWriter.close();
+        assertEquals("[0,"
+                + "1,"
+                + "-1,"
+                + "-9223372036854775808,"
+                + "9223372036854775807]", stringWriter.toString());
+    }
+
+    public void testNumbers() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginArray();
+        jsonWriter.value(new BigInteger("0"));
+        jsonWriter.value(new BigInteger("9223372036854775808"));
+        jsonWriter.value(new BigInteger("-9223372036854775809"));
+        jsonWriter.value(new BigDecimal("3.141592653589793238462643383"));
+        jsonWriter.endArray();
+        jsonWriter.close();
+        assertEquals("[0,"
+                + "9223372036854775808,"
+                + "-9223372036854775809,"
+                + "3.141592653589793238462643383]", stringWriter.toString());
+    }
+
+    public void testBooleans() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginArray();
+        jsonWriter.value(true);
+        jsonWriter.value(false);
+        jsonWriter.endArray();
+        assertEquals("[true,false]", stringWriter.toString());
+    }
+
+    public void testNulls() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginArray();
+        jsonWriter.nullValue();
+        jsonWriter.endArray();
+        assertEquals("[null]", stringWriter.toString());
+    }
+
+    public void testStrings() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginArray();
+        jsonWriter.value("a");
+        jsonWriter.value("a\"");
+        jsonWriter.value("\"");
+        jsonWriter.value(":");
+        jsonWriter.value(",");
+        jsonWriter.value("\b");
+        jsonWriter.value("\f");
+        jsonWriter.value("\n");
+        jsonWriter.value("\r");
+        jsonWriter.value("\t");
+        jsonWriter.value(" ");
+        jsonWriter.value("\\");
+        jsonWriter.value("{");
+        jsonWriter.value("}");
+        jsonWriter.value("[");
+        jsonWriter.value("]");
+        jsonWriter.value("\0");
+        jsonWriter.value("\u0019");
+        jsonWriter.endArray();
+        assertEquals("[\"a\","
+                + "\"a\\\"\","
+                + "\"\\\"\","
+                + "\":\","
+                + "\",\","
+                + "\"\\b\","
+                + "\"\\f\","
+                + "\"\\n\","
+                + "\"\\r\","
+                + "\"\\t\","
+                + "\" \","
+                + "\"\\\\\","
+                + "\"{\","
+                + "\"}\","
+                + "\"[\","
+                + "\"]\","
+                + "\"\\u0000\","
+                + "\"\\u0019\"]", stringWriter.toString());
+    }
+
+    public void testUnicodeLineBreaksEscaped() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginArray();
+        jsonWriter.value("\u2028 \u2029");
+        jsonWriter.endArray();
+        assertEquals("[\"\\u2028 \\u2029\"]", stringWriter.toString());
+    }
+
+    public void testEmptyArray() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginArray();
+        jsonWriter.endArray();
+        assertEquals("[]", stringWriter.toString());
+    }
+
+    public void testEmptyObject() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginObject();
+        jsonWriter.endObject();
+        assertEquals("{}", stringWriter.toString());
+    }
+
+    public void testObjectsInArrays() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginArray();
+        jsonWriter.beginObject();
+        jsonWriter.name("a").value(5);
+        jsonWriter.name("b").value(false);
+        jsonWriter.endObject();
+        jsonWriter.beginObject();
+        jsonWriter.name("c").value(6);
+        jsonWriter.name("d").value(true);
+        jsonWriter.endObject();
+        jsonWriter.endArray();
+        assertEquals("[{\"a\":5,\"b\":false},"
+                + "{\"c\":6,\"d\":true}]", stringWriter.toString());
+    }
+
+    public void testArraysInObjects() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginObject();
+        jsonWriter.name("a");
+        jsonWriter.beginArray();
+        jsonWriter.value(5);
+        jsonWriter.value(false);
+        jsonWriter.endArray();
+        jsonWriter.name("b");
+        jsonWriter.beginArray();
+        jsonWriter.value(6);
+        jsonWriter.value(true);
+        jsonWriter.endArray();
+        jsonWriter.endObject();
+        assertEquals("{\"a\":[5,false],"
+                + "\"b\":[6,true]}", stringWriter.toString());
+    }
+
+    public void testDeepNestingArrays() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        for (int i = 0; i < 20; i++) {
+            jsonWriter.beginArray();
+        }
+        for (int i = 0; i < 20; i++) {
+            jsonWriter.endArray();
+        }
+        assertEquals("[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]", stringWriter.toString());
+    }
+
+    public void testDeepNestingObjects() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginObject();
+        for (int i = 0; i < 20; i++) {
+            jsonWriter.name("a");
+            jsonWriter.beginObject();
+        }
+        for (int i = 0; i < 20; i++) {
+            jsonWriter.endObject();
+        }
+        jsonWriter.endObject();
+        assertEquals("{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":"
+                + "{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{"
+                + "}}}}}}}}}}}}}}}}}}}}}", stringWriter.toString());
+    }
+
+    public void testRepeatedName() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.beginObject();
+        jsonWriter.name("a").value(true);
+        jsonWriter.name("a").value(false);
+        jsonWriter.endObject();
+        // JsonWriter doesn't attempt to detect duplicate names
+        assertEquals("{\"a\":true,\"a\":false}", stringWriter.toString());
+    }
+
+    public void testPrettyPrintObject() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.setIndent("   ");
+
+        jsonWriter.beginObject();
+        jsonWriter.name("a").value(true);
+        jsonWriter.name("b").value(false);
+        jsonWriter.name("c").value(5.0);
+        jsonWriter.name("e").nullValue();
+        jsonWriter.name("f").beginArray();
+        jsonWriter.value(6.0);
+        jsonWriter.value(7.0);
+        jsonWriter.endArray();
+        jsonWriter.name("g").beginObject();
+        jsonWriter.name("h").value(8.0);
+        jsonWriter.name("i").value(9.0);
+        jsonWriter.endObject();
+        jsonWriter.endObject();
+
+        String expected = "{\n"
+                + "   \"a\": true,\n"
+                + "   \"b\": false,\n"
+                + "   \"c\": 5.0,\n"
+                + "   \"e\": null,\n"
+                + "   \"f\": [\n"
+                + "      6.0,\n"
+                + "      7.0\n"
+                + "   ],\n"
+                + "   \"g\": {\n"
+                + "      \"h\": 8.0,\n"
+                + "      \"i\": 9.0\n"
+                + "   }\n"
+                + "}";
+        assertEquals(expected, stringWriter.toString());
+    }
+
+    public void testPrettyPrintArray() throws IOException {
+        StringWriter stringWriter = new StringWriter();
+        JsonWriter jsonWriter = new JsonWriter(stringWriter);
+        jsonWriter.setIndent("   ");
+
+        jsonWriter.beginArray();
+        jsonWriter.value(true);
+        jsonWriter.value(false);
+        jsonWriter.value(5.0);
+        jsonWriter.nullValue();
+        jsonWriter.beginObject();
+        jsonWriter.name("a").value(6.0);
+        jsonWriter.name("b").value(7.0);
+        jsonWriter.endObject();
+        jsonWriter.beginArray();
+        jsonWriter.value(8.0);
+        jsonWriter.value(9.0);
+        jsonWriter.endArray();
+        jsonWriter.endArray();
+
+        String expected = "[\n"
+                + "   true,\n"
+                + "   false,\n"
+                + "   5.0,\n"
+                + "   null,\n"
+                + "   {\n"
+                + "      \"a\": 6.0,\n"
+                + "      \"b\": 7.0\n"
+                + "   },\n"
+                + "   [\n"
+                + "      8.0,\n"
+                + "      9.0\n"
+                + "   ]\n"
+                + "]";
+        assertEquals(expected, stringWriter.toString());
+    }
+}
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..abab17b
--- /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.contains(needle));
+    }
+
+    private static <T extends Comparable<? super T>> void assertOutOfRange(Range<T> object,
+            T needle) {
+        assertAction("out-of-range", object, needle, false, object.contains(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/util/src/android/util/cts/XmlTest.java b/tests/tests/util/src/android/util/cts/XmlTest.java
index 24f8c74..833bd3c 100644
--- a/tests/tests/util/src/android/util/cts/XmlTest.java
+++ b/tests/tests/util/src/android/util/cts/XmlTest.java
@@ -391,7 +391,7 @@
 
     public void testAsAttributeSet() {
         XmlResourceParser xp = getContext().getResources().getLayout(
-                com.android.cts.stub.R.layout.xml_test);
+                com.android.cts.util.R.layout.xml_test);
         int eventType = -1;
         try {
             eventType = xp.getEventType();
diff --git a/tests/tests/view/Android.mk b/tests/tests/view/Android.mk
index 2c07cc3..027e321 100644
--- a/tests/tests/view/Android.mk
+++ b/tests/tests/view/Android.mk
@@ -17,18 +17,16 @@
 include $(CLEAR_VARS)
 
 # don't include this package in any target
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsViewTestCases
 
-LOCAL_INSTRUMENTATION_FOR := CtsTestStubs
-
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/view/AndroidManifest.xml b/tests/tests/view/AndroidManifest.xml
index 233dc44..6806d29 100644
--- a/tests/tests/view/AndroidManifest.xml
+++ b/tests/tests/view/AndroidManifest.xml
@@ -19,13 +19,170 @@
     package="com.android.cts.view">
 
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
-    <application>
+    <application android:label="Android TestCase"
+                android:icon="@drawable/size_48x48"
+                android:maxRecents="1"
+                android:multiArch="true"
+                android:name="android.view.cts.MockApplication"
+                android:supportsRtl="true">
         <uses-library android:name="android.test.runner" />
+        
+        <activity android:name="android.view.cts.ViewStubCtsActivity"
+            android:label="ViewStubCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+        
+        <activity android:name="android.view.cts.UsingViewsCtsActivity"
+            android:label="Using Views Test">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+        
+        <activity android:name="android.view.cts.FocusHandlingCtsActivity"
+            android:label="Focus Handling Test">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+        
+        <activity android:name="android.view.cts.ViewGroupCtsActivity" android:label="ViewGroupCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+        
+        <activity android:name="android.view.cts.ViewTestCtsActivity"
+            android:label="ViewTestCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+        
+        <activity android:name="android.view.cts.ViewLayoutPositionTestCtsActivity"
+            android:label="ViewTestCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.view.cts.WindowCtsActivity"
+            android:theme="@android:style/Theme.Holo.NoActionBar"
+            android:label="WindowCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+        
+        <activity android:name="android.view.animation.cts.AnimationTestCtsActivity"
+            android:label="AnimationTestCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.view.animation.cts.GridLayoutAnimCtsActivity"
+            android:label="GridLayoutAnimCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.view.animation.cts.LayoutAnimCtsActivity"
+            android:label="LayoutAnimCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+        
+        <activity android:name="android.view.inputmethod.cts.InputMethodCtsActivity"
+            android:label="InputMethodCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+        <service android:name="android.view.inputmethod.cts.InputMethodInfoStub"
+            android:label="InputMethodInfoStub">
+            <intent-filter>
+                <action android:name="android.view.InputMethod" />
+            </intent-filter>
+            <meta-data android:name="android.view.im"
+                android:resource="@xml/method" />
+        </service>
+
+        <activity android:name="android.view.cts.MenuInflaterCtsActivity"
+            android:label="MenuInflaterCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.view.cts.SurfaceViewCtsActivity"
+            android:label="SurfaceViewCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.view.cts.FocusFinderCtsActivity"
+            android:label="FocusFinderCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.view.cts.GestureDetectorCtsActivity"
+            android:label="GestureDetectorCtsActivity"
+            android:theme="@android:style/Theme.NoTitleBar.Fullscreen" />
+            
+        <activity android:name="android.view.cts.GLSurfaceViewCtsActivity"
+            android:label="GLSurfaceViewCts"/>
+
+        <activity android:name="android.view.cts.MockActivity" android:label="MockActivity">
+            <meta-data android:name="android.view.merge"
+                android:resource="@xml/merge" />
+        </activity>
+
+        <activity android:name="android.view.cts.ViewGroupCtsActivity"
+            android:label="WidgetViewGroupCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.view.cts.CtsActivity"
+            android:label="CtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="com.android.cts.stub"
-                     android:label="CTS tests of android.view"/>
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.view"
+                     android:label="CTS tests of android.view">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/res/anim/accelerate_alpha.xml b/tests/tests/view/res/anim/accelerate_alpha.xml
similarity index 100%
rename from tests/res/anim/accelerate_alpha.xml
rename to tests/tests/view/res/anim/accelerate_alpha.xml
diff --git a/tests/res/anim/accelerate_decelerate_alpha.xml b/tests/tests/view/res/anim/accelerate_decelerate_alpha.xml
similarity index 100%
rename from tests/res/anim/accelerate_decelerate_alpha.xml
rename to tests/tests/view/res/anim/accelerate_decelerate_alpha.xml
diff --git a/tests/res/anim/alpha.xml b/tests/tests/view/res/anim/alpha.xml
similarity index 100%
rename from tests/res/anim/alpha.xml
rename to tests/tests/view/res/anim/alpha.xml
diff --git a/tests/res/anim/anim_alpha.xml b/tests/tests/view/res/anim/anim_alpha.xml
similarity index 100%
rename from tests/res/anim/anim_alpha.xml
rename to tests/tests/view/res/anim/anim_alpha.xml
diff --git a/tests/res/anim/anim_gridlayout.xml b/tests/tests/view/res/anim/anim_gridlayout.xml
similarity index 100%
rename from tests/res/anim/anim_gridlayout.xml
rename to tests/tests/view/res/anim/anim_gridlayout.xml
diff --git a/tests/res/anim/anim_rotate.xml b/tests/tests/view/res/anim/anim_rotate.xml
similarity index 100%
rename from tests/res/anim/anim_rotate.xml
rename to tests/tests/view/res/anim/anim_rotate.xml
diff --git a/tests/res/anim/anim_scale.xml b/tests/tests/view/res/anim/anim_scale.xml
similarity index 100%
rename from tests/res/anim/anim_scale.xml
rename to tests/tests/view/res/anim/anim_scale.xml
diff --git a/tests/res/anim/anim_set.xml b/tests/tests/view/res/anim/anim_set.xml
similarity index 100%
rename from tests/res/anim/anim_set.xml
rename to tests/tests/view/res/anim/anim_set.xml
diff --git a/tests/res/anim/anim_translate.xml b/tests/tests/view/res/anim/anim_translate.xml
similarity index 100%
rename from tests/res/anim/anim_translate.xml
rename to tests/tests/view/res/anim/anim_translate.xml
diff --git a/tests/res/anim/cycle_alpha.xml b/tests/tests/view/res/anim/cycle_alpha.xml
similarity index 100%
rename from tests/res/anim/cycle_alpha.xml
rename to tests/tests/view/res/anim/cycle_alpha.xml
diff --git a/tests/res/anim/cycle_interpolator.xml b/tests/tests/view/res/anim/cycle_interpolator.xml
similarity index 100%
rename from tests/res/anim/cycle_interpolator.xml
rename to tests/tests/view/res/anim/cycle_interpolator.xml
diff --git a/tests/res/anim/decelerate_alpha.xml b/tests/tests/view/res/anim/decelerate_alpha.xml
similarity index 100%
rename from tests/res/anim/decelerate_alpha.xml
rename to tests/tests/view/res/anim/decelerate_alpha.xml
diff --git a/tests/res/anim/layout_anim_controller_animation.xml b/tests/tests/view/res/anim/layout_anim_controller_animation.xml
similarity index 100%
rename from tests/res/anim/layout_anim_controller_animation.xml
rename to tests/tests/view/res/anim/layout_anim_controller_animation.xml
diff --git a/tests/res/drawable/faces.jpg b/tests/tests/view/res/drawable/faces.jpg
similarity index 100%
rename from tests/res/drawable/faces.jpg
rename to tests/tests/view/res/drawable/faces.jpg
Binary files differ
diff --git a/tests/res/drawable/failed.jpg b/tests/tests/view/res/drawable/failed.jpg
similarity index 100%
rename from tests/res/drawable/failed.jpg
rename to tests/tests/view/res/drawable/failed.jpg
Binary files differ
diff --git a/tests/res/drawable/icon_black.jpg b/tests/tests/view/res/drawable/icon_black.jpg
similarity index 100%
copy from tests/res/drawable/icon_black.jpg
copy to tests/tests/view/res/drawable/icon_black.jpg
Binary files differ
diff --git a/tests/res/drawable/icon_blue.jpg b/tests/tests/view/res/drawable/icon_blue.jpg
similarity index 100%
copy from tests/res/drawable/icon_blue.jpg
copy to tests/tests/view/res/drawable/icon_blue.jpg
Binary files differ
diff --git a/tests/res/drawable/icon_green.jpg b/tests/tests/view/res/drawable/icon_green.jpg
similarity index 100%
copy from tests/res/drawable/icon_green.jpg
copy to tests/tests/view/res/drawable/icon_green.jpg
Binary files differ
diff --git a/tests/res/drawable/icon_red.jpg b/tests/tests/view/res/drawable/icon_red.jpg
similarity index 100%
copy from tests/res/drawable/icon_red.jpg
copy to tests/tests/view/res/drawable/icon_red.jpg
Binary files differ
diff --git a/tests/res/drawable/icon_yellow.jpg b/tests/tests/view/res/drawable/icon_yellow.jpg
similarity index 100%
copy from tests/res/drawable/icon_yellow.jpg
copy to tests/tests/view/res/drawable/icon_yellow.jpg
Binary files differ
diff --git a/tests/res/drawable/ninepatch_0.9.png b/tests/tests/view/res/drawable/ninepatch_0.9.png
similarity index 100%
copy from tests/res/drawable/ninepatch_0.9.png
copy to tests/tests/view/res/drawable/ninepatch_0.9.png
Binary files differ
diff --git a/tests/res/drawable/ninepatch_1.9.png b/tests/tests/view/res/drawable/ninepatch_1.9.png
similarity index 100%
copy from tests/res/drawable/ninepatch_1.9.png
copy to tests/tests/view/res/drawable/ninepatch_1.9.png
Binary files differ
diff --git a/tests/res/drawable/no_padding.png b/tests/tests/view/res/drawable/no_padding.png
similarity index 100%
rename from tests/res/drawable/no_padding.png
rename to tests/tests/view/res/drawable/no_padding.png
Binary files differ
diff --git a/tests/res/drawable/padding_0.9.png b/tests/tests/view/res/drawable/padding_0.9.png
similarity index 100%
rename from tests/res/drawable/padding_0.9.png
rename to tests/tests/view/res/drawable/padding_0.9.png
Binary files differ
diff --git a/tests/res/drawable/pass.jpg b/tests/tests/view/res/drawable/pass.jpg
similarity index 100%
copy from tests/res/drawable/pass.jpg
copy to tests/tests/view/res/drawable/pass.jpg
Binary files differ
diff --git a/tests/res/drawable/scenery.jpg b/tests/tests/view/res/drawable/scenery.jpg
similarity index 100%
copy from tests/res/drawable/scenery.jpg
copy to tests/tests/view/res/drawable/scenery.jpg
Binary files differ
diff --git a/tests/res/drawable/size_48x48.jpg b/tests/tests/view/res/drawable/size_48x48.jpg
similarity index 100%
copy from tests/res/drawable/size_48x48.jpg
copy to tests/tests/view/res/drawable/size_48x48.jpg
Binary files differ
diff --git a/tests/res/drawable/start.jpg b/tests/tests/view/res/drawable/start.jpg
similarity index 100%
rename from tests/res/drawable/start.jpg
rename to tests/tests/view/res/drawable/start.jpg
Binary files differ
diff --git a/tests/res/layout/abslistview_layout.xml b/tests/tests/view/res/layout/abslistview_layout.xml
similarity index 100%
rename from tests/res/layout/abslistview_layout.xml
rename to tests/tests/view/res/layout/abslistview_layout.xml
diff --git a/tests/res/layout/anim_layout.xml b/tests/tests/view/res/layout/anim_layout.xml
similarity index 100%
rename from tests/res/layout/anim_layout.xml
rename to tests/tests/view/res/layout/anim_layout.xml
diff --git a/tests/res/layout/focus_finder_layout.xml b/tests/tests/view/res/layout/focus_finder_layout.xml
similarity index 100%
rename from tests/res/layout/focus_finder_layout.xml
rename to tests/tests/view/res/layout/focus_finder_layout.xml
diff --git a/tests/res/layout/focus_handling_layout.xml b/tests/tests/view/res/layout/focus_handling_layout.xml
similarity index 100%
rename from tests/res/layout/focus_handling_layout.xml
rename to tests/tests/view/res/layout/focus_handling_layout.xml
diff --git a/tests/res/layout/gridlayout_anim_controller_layout.xml b/tests/tests/view/res/layout/gridlayout_anim_controller_layout.xml
similarity index 100%
rename from tests/res/layout/gridlayout_anim_controller_layout.xml
rename to tests/tests/view/res/layout/gridlayout_anim_controller_layout.xml
diff --git a/tests/res/layout/inflater_layout.xml b/tests/tests/view/res/layout/inflater_layout.xml
similarity index 100%
rename from tests/res/layout/inflater_layout.xml
rename to tests/tests/view/res/layout/inflater_layout.xml
diff --git a/tests/tests/view/res/layout/inflater_layout_tags.xml b/tests/tests/view/res/layout/inflater_layout_tags.xml
new file mode 100644
index 0000000..dc3eb29
--- /dev/null
+++ b/tests/tests/view/res/layout/inflater_layout_tags.xml
@@ -0,0 +1,39 @@
+<?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.
+ */
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/viewlayout_root"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical" >
+
+    <tag
+        android:id="@+id/tag_viewlayout_root"
+        android:value="@string/tag1" />
+
+    <View
+        android:id="@+id/mock_view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" >
+
+        <tag
+            android:id="@+id/tag_mock_view"
+            android:value="@string/tag2" />
+    </View>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/tests/view/res/layout/inflater_override_theme_layout.xml b/tests/tests/view/res/layout/inflater_override_theme_layout.xml
new file mode 100644
index 0000000..2d2a578
--- /dev/null
+++ b/tests/tests/view/res/layout/inflater_override_theme_layout.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2013 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:theme="@style/Theme_OverrideOuter" >
+
+    <View
+        android:id="@+id/view_outer"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:theme="@style/Theme_OverrideInner" >
+
+        <View
+            android:id="@+id/view_inner"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" />
+        <View
+            android:id="@+id/view_attr"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:theme="?attr/themeOverrideAttr" />
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/tests/res/layout/inputmethod_edittext.xml b/tests/tests/view/res/layout/inputmethod_edittext.xml
similarity index 100%
rename from tests/res/layout/inputmethod_edittext.xml
rename to tests/tests/view/res/layout/inputmethod_edittext.xml
diff --git a/tests/tests/view/res/layout/scrollview_layout.xml b/tests/tests/view/res/layout/scrollview_layout.xml
new file mode 100644
index 0000000..c5b7b43
--- /dev/null
+++ b/tests/tests/view/res/layout/scrollview_layout.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<android.view.cts.MyScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/scroll_view"
+    android:layout_width="100dip"
+    android:layout_height="100dip">
+
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_width="250dip"
+        android:layout_height="wrap_content">
+
+        <Button
+            android:id="@+id/first_child"
+            android:layout_width="250dip"
+            android:layout_height="100dip"
+            android:text="@string/vertical_text_1"/>
+
+        <Button
+            android:layout_width="250dip"
+            android:layout_height="100dip"
+            android:text="@string/vertical_text_2"/>
+
+        <Button
+            android:layout_width="250dip"
+            android:layout_height="100dip"
+            android:text="@string/vertical_text_3"/>
+
+        <Button
+            android:layout_width="250dip"
+            android:layout_height="100dip"
+            android:text="@string/vertical_text_1"/>
+
+        <Button
+            android:layout_width="250dip"
+            android:layout_height="100dip"
+            android:text="@string/vertical_text_2"/>
+
+        <Button
+            android:layout_width="250dip"
+            android:layout_height="100dip"
+            android:text="@string/vertical_text_3"/>
+
+        <Button
+            android:layout_width="250dip"
+            android:layout_height="100dip"
+            android:text="@string/vertical_text_1"/>
+
+        <Button
+            android:layout_width="250dip"
+            android:layout_height="100dip"
+            android:text="@string/vertical_text_2"/>
+
+        <Button
+            android:layout_width="250dip"
+            android:layout_height="100dip"
+            android:text="@string/vertical_text_3"/>
+
+        <Button
+            android:layout_width="250dip"
+            android:layout_height="100dip"
+            android:text="@string/vertical_text_1"/>
+
+        <Button
+            android:layout_width="250dip"
+            android:layout_height="100dip"
+            android:text="@string/vertical_text_2"/>
+
+        <Button
+            android:layout_width="250dip"
+            android:layout_height="100dip"
+            android:text="@string/vertical_text_3"/>
+
+        <Button
+            android:layout_width="250dip"
+            android:layout_height="100dip"
+            android:text="@string/vertical_text_1"/>
+
+        <Button
+            android:layout_width="250dip"
+            android:layout_height="100dip"
+            android:text="@string/vertical_text_2"/>
+
+        <Button
+            android:id="@+id/last_child"
+            android:layout_width="250dip"
+            android:layout_height="100dip"
+            android:text="@string/vertical_text_3"/>
+    </LinearLayout>
+
+</android.view.cts.MyScrollView>
diff --git a/tests/res/layout/searchview.xml b/tests/tests/view/res/layout/searchview.xml
similarity index 100%
rename from tests/res/layout/searchview.xml
rename to tests/tests/view/res/layout/searchview.xml
diff --git a/tests/tests/view/res/layout/textview_layout.xml b/tests/tests/view/res/layout/textview_layout.xml
new file mode 100644
index 0000000..c09b93a
--- /dev/null
+++ b/tests/tests/view/res/layout/textview_layout.xml
@@ -0,0 +1,220 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:id="@+id/layout_textviewtest">
+
+    <ScrollView android:layout_width="match_parent"
+            android:layout_height="match_parent">
+
+        <LinearLayout android:orientation="vertical"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent">
+
+            <TextView android:id="@+id/textview_textAttr"
+                    android:text="@string/text_view_hello"
+                    android:textColor="@drawable/black"
+                    android:textColorHighlight="@drawable/yellow"
+                    android:textColorHint="@drawable/red"
+                    android:textColorLink="@drawable/blue"
+                    android:textScaleX="1.2"
+                    android:typeface="normal"
+                    android:textSize="20px"
+                    android:textStyle="normal"
+                    android:textAppearance="@null"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"/>
+        
+            <TextView android:id="@+id/textview_password"
+                    android:password="true"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"/>
+        
+            <TextView android:id="@+id/textview_singleLine"
+                    android:singleLine="true"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"/>
+        
+            <TextView android:id="@+id/textview_text"
+                    android:text="@string/text_view_hello"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"/>
+
+            <TextView android:id="@+id/textview_text_two_lines"
+                    android:text="@string/text_view_hello_two_lines"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"/>
+
+            <android.view.cts.MockTextView
+                    android:id="@+id/mock_textview_left"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:requiresFadingEdge="horizontal"
+                    android:singleLine="true"
+                    android:text="@string/long_text"
+                    android:gravity="left"
+                    />
+
+            <android.view.cts.MockTextView
+                    android:id="@+id/mock_textview_right"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:requiresFadingEdge="horizontal"
+                    android:singleLine="true"
+                    android:text="@string/long_text"
+                    android:gravity="right"
+                    />
+
+            <android.view.cts.MockTextView
+                    android:id="@+id/mock_textview_center"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:requiresFadingEdge="horizontal"
+                    android:singleLine="true"
+                    android:text="@string/long_text"
+                    android:gravity="center"
+                    />
+        </LinearLayout>
+
+    </ScrollView>
+
+    <TextView android:id="@+id/textview_ltr"
+              android:layout_height="wrap_content"
+              android:layout_width="wrap_content"/>
+
+    <TextView android:id="@+id/textview_rtl"
+              android:layout_height="wrap_content"
+              android:layout_width="wrap_content"/>
+
+    <TextView android:id="@+id/textview_drawable_1_1"
+              android:layout_height="wrap_content"
+              android:layout_width="wrap_content"
+              android:drawableLeft="@drawable/icon_blue"
+              android:drawableRight="@drawable/icon_red"
+              android:drawableTop="@drawable/icon_green"
+              android:drawableBottom="@drawable/icon_yellow"
+            />
+
+    <TextView android:id="@+id/textview_drawable_1_2"
+              android:layout_height="wrap_content"
+              android:layout_width="wrap_content"
+              android:drawableLeft="@drawable/icon_blue"
+              android:drawableRight="@drawable/icon_red"
+              android:drawableTop="@drawable/icon_green"
+              android:drawableBottom="@drawable/icon_yellow"
+              android:layoutDirection="rtl"
+            />
+
+    <TextView android:id="@+id/textview_drawable_2_1"
+              android:layout_height="wrap_content"
+              android:layout_width="wrap_content"
+              android:drawableStart="@drawable/icon_blue"
+              android:drawableEnd="@drawable/icon_red"
+              android:drawableTop="@drawable/icon_green"
+              android:drawableBottom="@drawable/icon_yellow"
+            />
+
+    <TextView android:id="@+id/textview_drawable_2_2"
+              android:layout_height="wrap_content"
+              android:layout_width="wrap_content"
+              android:drawableStart="@drawable/icon_blue"
+              android:drawableEnd="@drawable/icon_red"
+              android:drawableTop="@drawable/icon_green"
+              android:drawableBottom="@drawable/icon_yellow"
+              android:layoutDirection="rtl"
+            />
+
+    <TextView android:id="@+id/textview_drawable_3_1"
+              android:layout_height="wrap_content"
+              android:layout_width="wrap_content"
+              android:drawableLeft="@drawable/icon_black"
+              android:drawableRight="@drawable/icon_black"
+              android:drawableStart="@drawable/icon_blue"
+              android:drawableEnd="@drawable/icon_red"
+              android:drawableTop="@drawable/icon_green"
+              android:drawableBottom="@drawable/icon_yellow"
+            />
+
+    <TextView android:id="@+id/textview_drawable_3_2"
+              android:layout_height="wrap_content"
+              android:layout_width="wrap_content"
+              android:drawableLeft="@drawable/icon_black"
+              android:drawableRight="@drawable/icon_black"
+              android:drawableStart="@drawable/icon_blue"
+              android:drawableEnd="@drawable/icon_red"
+              android:drawableTop="@drawable/icon_green"
+              android:drawableBottom="@drawable/icon_yellow"
+              android:layoutDirection="rtl"
+            />
+
+
+    <LinearLayout android:orientation="vertical"
+                  android:layout_width="match_parent"
+                  android:layout_height="match_parent"
+                  android:layoutDirection="ltr">
+
+        <TextView android:id="@+id/textview_drawable_4_1"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:drawableStart="@drawable/icon_blue"
+                  android:drawableEnd="@drawable/icon_red"
+                  android:drawableTop="@drawable/icon_green"
+                  android:drawableBottom="@drawable/icon_yellow"
+                />
+
+        <TextView android:id="@+id/textview_drawable_5_1"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:drawableLeft="@drawable/icon_black"
+                  android:drawableRight="@drawable/icon_black"
+                  android:drawableStart="@drawable/icon_blue"
+                  android:drawableEnd="@drawable/icon_red"
+                  android:drawableTop="@drawable/icon_green"
+                  android:drawableBottom="@drawable/icon_yellow"
+                />
+
+    </LinearLayout>
+
+    <LinearLayout android:orientation="vertical"
+                  android:layout_width="match_parent"
+                  android:layout_height="match_parent"
+                  android:layoutDirection="rtl">
+
+        <TextView android:id="@+id/textview_drawable_4_2"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:drawableStart="@drawable/icon_blue"
+                  android:drawableEnd="@drawable/icon_red"
+                  android:drawableTop="@drawable/icon_green"
+                  android:drawableBottom="@drawable/icon_yellow"
+                />
+
+        <TextView android:id="@+id/textview_drawable_5_2"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:drawableLeft="@drawable/icon_black"
+                  android:drawableRight="@drawable/icon_black"
+                  android:drawableStart="@drawable/icon_blue"
+                  android:drawableEnd="@drawable/icon_red"
+                  android:drawableTop="@drawable/icon_green"
+                  android:drawableBottom="@drawable/icon_yellow"
+                />
+
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/tests/res/layout/using_views_layout.xml b/tests/tests/view/res/layout/using_views_layout.xml
similarity index 100%
rename from tests/res/layout/using_views_layout.xml
rename to tests/tests/view/res/layout/using_views_layout.xml
diff --git a/tests/tests/view/res/layout/view_layout.xml b/tests/tests/view/res/layout/view_layout.xml
new file mode 100644
index 0000000..fa817dc
--- /dev/null
+++ b/tests/tests/view/res/layout/view_layout.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2008 Esmertec AG.
+ * Copyright (C) 2008 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.
+ */
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/viewlayout_root"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <android.view.cts.MockView
+        android:id="@+id/mock_view"
+        android:layout_width="100px"
+        android:layout_height="200px"/>
+
+    <android.view.cts.MockView
+        android:id="@+id/scroll_view"
+        android:layout_width="100px"
+        android:layout_height="200px"
+        android:scrollbars="horizontal|vertical"
+        android:fadingEdge="horizontal|vertical"
+        android:fadingEdgeLength="20px"/>
+
+    <android.view.cts.MockView
+        android:id="@+id/scroll_view_2"
+        android:layout_width="100px"
+        android:layout_height="200px"
+        android:scrollbars="horizontal|vertical"
+        android:requiresFadingEdge="horizontal|vertical"
+        android:fadingEdgeLength="20px"/>
+
+    <View
+        android:id="@+id/fit_windows"
+        android:fitsSystemWindows="true"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"/>
+
+    <android.view.cts.MockView
+            android:id="@+id/mock_view_padding_full"
+            android:layout_width="200px"
+            android:layout_height="200px"
+            android:padding="0px"
+            android:background="@drawable/padding_0" />
+
+    <android.view.cts.MockView
+            android:id="@+id/mock_view_padding_left"
+            android:layout_width="200px"
+            android:layout_height="200px"
+            android:paddingLeft="0px"
+            android:background="@drawable/padding_0" />
+
+    <android.view.cts.MockView
+            android:id="@+id/mock_view_padding_right"
+            android:layout_width="200px"
+            android:layout_height="200px"
+            android:paddingRight="0px"
+            android:background="@drawable/padding_0" />
+
+    <android.view.cts.MockView
+            android:id="@+id/mock_view_padding_top"
+            android:layout_width="200px"
+            android:layout_height="200px"
+            android:paddingTop="0px"
+            android:background="@drawable/padding_0" />
+
+    <android.view.cts.MockView
+            android:id="@+id/mock_view_padding_bottom"
+            android:layout_width="200px"
+            android:layout_height="200px"
+            android:paddingBottom="0dp"
+            android:background="@drawable/padding_0" />
+
+    <android.view.cts.MockView
+            android:id="@+id/mock_view_padding_runtime_updated"
+            android:layout_width="200px"
+            android:layout_height="200px"
+            android:paddingStart="8px"
+            android:paddingEnd="8px"
+            android:background="@drawable/no_padding" />
+
+    <View
+        android:id="@+id/background_tint"
+        android:backgroundTint="@android:color/white"
+        android:backgroundTintMode="src_over"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+</LinearLayout>
diff --git a/tests/res/layout/view_layout_position.xml b/tests/tests/view/res/layout/view_layout_position.xml
similarity index 100%
rename from tests/res/layout/view_layout_position.xml
rename to tests/tests/view/res/layout/view_layout_position.xml
diff --git a/tests/res/layout/view_visibility_layout.xml b/tests/tests/view/res/layout/view_visibility_layout.xml
similarity index 100%
rename from tests/res/layout/view_visibility_layout.xml
rename to tests/tests/view/res/layout/view_visibility_layout.xml
diff --git a/tests/res/layout/viewgroup_margin_layout.xml b/tests/tests/view/res/layout/viewgroup_margin_layout.xml
similarity index 100%
rename from tests/res/layout/viewgroup_margin_layout.xml
rename to tests/tests/view/res/layout/viewgroup_margin_layout.xml
diff --git a/tests/tests/view/res/layout/viewgrouptest_stub.xml b/tests/tests/view/res/layout/viewgrouptest_stub.xml
new file mode 100644
index 0000000..1160d0e
--- /dev/null
+++ b/tests/tests/view/res/layout/viewgrouptest_stub.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Copyright (C) 2008 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.
+ -->
+
+<android.view.cts.MockLinearLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:id="@+id/mocklinearlayout">
+
+    <!-- view1 goes on top -->
+    <TextView
+        android:id="@+id/viewgrouptest_stub"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+    />
+
+</android.view.cts.MockLinearLayout>
+
diff --git a/tests/res/layout/viewstub_layout.xml b/tests/tests/view/res/layout/viewstub_layout.xml
similarity index 100%
rename from tests/res/layout/viewstub_layout.xml
rename to tests/tests/view/res/layout/viewstub_layout.xml
diff --git a/tests/res/layout/viewtreeobserver_layout.xml b/tests/tests/view/res/layout/viewtreeobserver_layout.xml
similarity index 100%
rename from tests/res/layout/viewtreeobserver_layout.xml
rename to tests/tests/view/res/layout/viewtreeobserver_layout.xml
diff --git a/tests/res/layout/windowstub_addlayout.xml b/tests/tests/view/res/layout/windowstub_addlayout.xml
similarity index 100%
rename from tests/res/layout/windowstub_addlayout.xml
rename to tests/tests/view/res/layout/windowstub_addlayout.xml
diff --git a/tests/res/layout/windowstub_layout.xml b/tests/tests/view/res/layout/windowstub_layout.xml
similarity index 100%
rename from tests/res/layout/windowstub_layout.xml
rename to tests/tests/view/res/layout/windowstub_layout.xml
diff --git a/tests/res/layout/windowstub_presentation.xml b/tests/tests/view/res/layout/windowstub_presentation.xml
similarity index 100%
rename from tests/res/layout/windowstub_presentation.xml
rename to tests/tests/view/res/layout/windowstub_presentation.xml
diff --git a/tests/res/menu/browser.xml b/tests/tests/view/res/menu/browser.xml
similarity index 100%
copy from tests/res/menu/browser.xml
copy to tests/tests/view/res/menu/browser.xml
diff --git a/tests/res/menu/category_order.xml b/tests/tests/view/res/menu/category_order.xml
similarity index 100%
rename from tests/res/menu/category_order.xml
rename to tests/tests/view/res/menu/category_order.xml
diff --git a/tests/res/menu/checkable.xml b/tests/tests/view/res/menu/checkable.xml
similarity index 100%
rename from tests/res/menu/checkable.xml
rename to tests/tests/view/res/menu/checkable.xml
diff --git a/tests/res/menu/menu_searchview.xml b/tests/tests/view/res/menu/menu_searchview.xml
similarity index 100%
rename from tests/res/menu/menu_searchview.xml
rename to tests/tests/view/res/menu/menu_searchview.xml
diff --git a/tests/res/menu/title_icon.xml b/tests/tests/view/res/menu/title_icon.xml
similarity index 100%
rename from tests/res/menu/title_icon.xml
rename to tests/tests/view/res/menu/title_icon.xml
diff --git a/tests/res/menu/visible_shortcut.xml b/tests/tests/view/res/menu/visible_shortcut.xml
similarity index 100%
rename from tests/res/menu/visible_shortcut.xml
rename to tests/tests/view/res/menu/visible_shortcut.xml
diff --git a/tests/res/values/arrays.xml b/tests/tests/view/res/values/arrays.xml
similarity index 100%
copy from tests/res/values/arrays.xml
copy to tests/tests/view/res/values/arrays.xml
diff --git a/tests/tests/view/res/values/attrs.xml b/tests/tests/view/res/values/attrs.xml
new file mode 100644
index 0000000..4c3d9db
--- /dev/null
+++ b/tests/tests/view/res/values/attrs.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2008 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>
+    <declare-styleable name="Style1">
+        <attr name="Type1" format="integer">
+            <enum name="type" value="28" />
+            <enum name="data" value="0xff00ff00" />
+            <enum name="asset_cookie" value="0" />
+            <enum name="resource_id" value="0" />
+            <enum name="changing_config" value="0" />
+        </attr>
+        <attr name="Type2" format="integer">
+            <enum name="type" value="28" />
+            <enum name="data" value="0xff0000ff" />
+            <enum name="asset_cookie" value="0" />
+            <enum name="resource_id" value="0" />
+            <enum name="changing_config" value="0" />
+        </attr>
+    </declare-styleable>
+    <attr name="type1" format="boolean"/>
+    <attr name="type2" format="boolean"/>
+    <attr name="type3" format="color"/>
+    <attr name="type4" format="reference|color"/>
+    <attr name="type5" format="dimension"/>
+    <attr name="type6" format="dimension"/>
+    <attr name="type7" format="dimension"/>
+    <attr name="type8" format="reference"/>
+    <attr name="type9" format="float"/>
+    <attr name="type10" format="fraction"/>
+    <attr name="type11" format="integer"/>
+    <attr name="type12" format="integer"/>
+    <attr name="type13" format="reference|string"/>
+    <attr name="type14" format="string"/>
+    <attr name="type15" format="reference"/>
+    <attr name="type16" format="string"/>
+    <declare-styleable name="style1">
+        <attr name="type1"/>
+        <attr name="type2"/>
+        <attr name="type3"/>
+        <attr name="type4"/>
+        <attr name="type5"/>
+        <attr name="type6"/>
+        <attr name="type7"/>
+        <attr name="type8"/>
+        <attr name="type9"/>
+        <attr name="type10"/>
+        <attr name="type11"/>
+        <attr name="type12"/>
+        <attr name="type13"/>
+        <attr name="type14"/>
+        <attr name="type15"/>
+        <attr name="type16"/>
+    </declare-styleable>
+    <attr name="testEnum">
+        <enum name="val1" value="1" />
+        <enum name="val2" value="2" />
+        <enum name="val10" value="10" />
+    </attr>
+    <attr name="testFlags">
+        <flag name="bit1" value="0x1" />
+        <flag name="bit2" value="0x2" />
+        <flag name="bit31" value="0x40000000" />
+    </attr>
+    <attr name="testString" format="string" />
+    <declare-styleable name="EnumStyle">
+        <attr name="testEnum" />
+    </declare-styleable>
+    <declare-styleable name="FlagStyle">
+        <attr name="testFlags" />
+    </declare-styleable>
+    <declare-styleable name="TestConfig">
+        <attr name="testString" />
+    </declare-styleable>
+    <!-- Size of text. Recommended dimension type for text is "sp" for scaled-pixels (example: 15sp).
+         Supported values include the following:<p/>
+    <ul>
+        <li><b>px</b> Pixels</li>
+        <li><b>sp</b> Scaled pixels (scaled to relative pixel size on screen). See {@link android.util.DisplayMetrics} for more information.</li>
+        <li><b>pt</b> Points</li>
+        <li><b>dip</b> Device independent pixels. See {@link android.util.DisplayMetrics} for more information.</li>
+    </ul>
+    -->
+    <attr name="textSize" format="dimension" />
+    <attr name="typeface">
+        <enum name="normal" value="0" />
+        <enum name="sans" value="1" />
+        <enum name="serif" value="2" />
+        <enum name="monospace" value="3" />
+    </attr>
+    <!-- Default text typeface style. -->
+    <attr name="textStyle">
+        <flag name="normal" value="0" />
+        <flag name="bold" value="1" />
+        <flag name="italic" value="2" />
+    </attr>
+    <!-- Color of text (usually same as colorForeground). -->
+    <attr name="textColor" format="reference|color" />
+    <!-- Color of highlighted text. -->
+    <attr name="textColorHighlight" format="reference|color" />
+    <!-- Color of hint text (displayed when the field is empty). -->
+    <attr name="textColorHint" format="reference|color" />
+    <!-- Color of link text (URLs). -->
+    <attr name="textColorLink" format="reference|color" />
+    <declare-styleable name="TextAppearance">
+        <attr name="textColor"/>
+        <attr name="textSize"/>
+        <attr name="textStyle"/>
+        <attr name="typeface"/>
+        <attr name="textColorHighlight"/>
+        <attr name="textColorHint"/>
+        <attr name="textColorLink"/>
+    </declare-styleable>
+    <!-- Integer used to uniquely identify theme overrides. -->
+    <attr name="themeType" format="integer"/>
+    <!-- Theme reference used to override parent theme. -->
+    <attr name="themeOverrideAttr" format="reference"/>
+
+    <!-- Drawable theming attributes -->
+    <attr name="themeBoolean" />
+    <attr name="themeColor" />
+    <attr name="themeFloat" />
+    <attr name="themeInteger" />
+    <attr name="themeDimension" />
+    <attr name="themeDrawable" />
+    <attr name="themeBitmap" />
+    <attr name="themeNinePatch" />
+    <attr name="themeGravity" />
+    <attr name="themeTileMode" />
+    <attr name="themeAngle" />
+</resources>
diff --git a/tests/res/values/colors.xml b/tests/tests/view/res/values/colors.xml
similarity index 100%
copy from tests/res/values/colors.xml
copy to tests/tests/view/res/values/colors.xml
diff --git a/tests/tests/view/res/values/strings.xml b/tests/tests/view/res/values/strings.xml
new file mode 100644
index 0000000..c167278
--- /dev/null
+++ b/tests/tests/view/res/values/strings.xml
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="permlab_testGranted">Test Granted</string>
+    <string name="permdesc_testGranted">Used for running CTS tests, for testing operations
+        where we have the permission.</string>
+    <string name="permlab_testDynamic">Test Dynamic</string>
+    <string name="permdesc_testDynamic">Used for running CTS tests, for testing adding
+        dynamic permissions.</string>
+    <string name="permlab_testDenied">Test Denied</string>
+    <string name="permdesc_testDenied">Used for running CTS tests, for testing operations
+        where we do not have the permission.</string>
+    <string name="explain">1. click start. \n2. if above image shaked, then press pass button,
+         else press failed button.</string>
+    <string name="text_view_hello">Hello! Text view!</string>
+    <string name="text_view_hello_two_lines">Hello! \nText view!</string>
+    <string name="text_view_simple_hint">This is a hint.</string>
+    <string name="text_view_hint">This is a string for testing hint of textview.</string>
+    <string name="activity_forwarding">App/Forwarding</string>
+    <string name="forwarding">$$$</string>
+    <string name="go">Go</string>
+    <string name="back">Back</string>
+    <string name="forward_target">
+        Press back button and notice we don\'t see the previous activity.
+    </string>
+    <string name="edit_text">testing</string>
+    <string name="text">DialogTest</string>
+    <string name="text_country">Country</string>
+    <string name="text_name">Name</string>
+    <string name="hello_world">Hello, World!</string>
+    <string name="hello_android">Hello, Android!</string>
+    <string name="alert_dialog_username">Name:</string>
+    <string name="alert_dialog_password">Password:</string>
+    <string name="alert_dialog_positive">Positive</string>
+    <string name="alert_dialog_negative">Negative</string>
+    <string name="alert_dialog_neutral">Neutral</string>
+    <string name="notify">Notify </string>
+    <string name="tabs_1">testing</string>
+    <string name="table_layout_first">first</string>
+    <string name="table_layout_second">second</string>
+    <string name="table_layout_third">third</string>
+    <string name="table_layout_long">Very long to make the string out of the screen</string>
+    <string name="chronometer_text">Test Chronometer</string>
+    <string name="am">AM</string>
+    <string name="pm">PM</string>
+    <string name="viewgroup_test">ViewGroup test</string>
+    <string name="viewanimator_test">ViewAnimator test</string>
+    <string name="id_ok">OK</string>
+    <string name="id_cancel">Cancel</string>
+    <string name="context_test_string1">This is %s string.</string>
+    <string name="context_test_string2">This is test string.</string>
+    <string name="animationutils_test_instructions">Choose different animations</string>
+    <string name="animationutils_test_alpha">Alpha animation</string>
+    <string name="animationutils_test_scale">Scale animation</string>
+    <string name="animationutils_test_rotate">Rotate animation</string>
+    <string name="animationutils_test_translate">Translate animation</string>
+    <string name="animationutils_test_set">Animation set</string>
+    <string name="animationutils_test_layout">Layout animation</string>
+    <string name="animationutils_test_gridlayout">Grid layout animation</string>
+    <string name="twolinelistitem_test_text1">text1</string>
+    <string name="twolinelistitem_test_text2">text2</string>
+    <string name="metadata_text">metadata text</string>
+    <string name="horizontal_text_1">horizontal 1</string>
+    <string name="horizontal_text_2">horizontal 2</string>
+    <string name="horizontal_text_3">horizontal 3</string>
+    <string name="vertical_text_1">vertical 1</string>
+    <string name="vertical_text_2">vertical 2</string>
+    <string name="vertical_text_3">vertical 3</string>
+    <string name="reference">here</string>
+    <string name="coerceIntegerToString">100</string>
+    <string name="coerceBooleanToString">true</string>
+    <string name="coerceColorToString">#fff</string>
+    <string name="coerceFloatToString">100.0</string>
+    <string name="coerceDimensionToString">100px</string>
+    <string name="coerceFractionToString">100<xliff:g id="percent">%</xliff:g></string>
+    <string name="formattedStringNone">Format[]</string>
+    <string name="formattedStringOne">Format[<xliff:g id="format">%d</xliff:g>]</string>
+    <string name="formattedStringTwo">Format[<xliff:g id="format">%3$d,%2$s</xliff:g>]</string>
+    <string name="checkboxpref_key">checkboxpref_key</string>
+   <string name="checkboxpref_title">title of preference</string>
+   <string name="checkboxpref_summary">summary of preference</string>
+   <string name="checkboxpref_summary_on">summary on of preference</string>
+   <string name="checkboxpref_summary_off">summary off of preference</string>
+   <string name="checkboxpref_depend">checkboxpref_depend</string>
+   <string name="checkboxpref_depend_title"> depend title of preference</string>
+   <string name="checkboxpref_depend_summary"> depend summary of preference</string>
+   <string name="edittextpref_key">edittextpref_key</string>
+   <string name="edittextpref_default_value">default value of preference</string>
+   <string name="edittextpref_title">title of edit text preference</string>
+   <string name="edittextpref_summary">summary of edit text preference</string>
+   <string name="edittextpref_dialog_title">dialog title of edit text preference</string>
+   <string name="edittextpref_text">text of  edit text preference</string>
+   <string name="listpref_key">listpref_key</string>
+   <string name="listpref_title">title of list preference</string>
+   <string name="listpref_summary">summary of list preference</string>
+   <string name="listpref_dialogtitle">dialog title of list preference</string>
+   <string name="easy">Easy</string>
+   <string name="medium">Medium</string>
+   <string name="hard">Hard</string>
+   <string name="footer_view">Footer view</string>
+   <string name="header_view">Header view</string>
+   <string name="dialogpref_title">title of dialog preference </string>
+   <string name="dialogpref_dialog_title">dialog title of dialog preference </string>
+   <string name="dialogpref_key">dialogpref_key</string>
+   <string name="dialogpref_default_value">default value of dialog preference</string>
+   <string name="dialogpref_summary">summary of dialog preference</string>
+   <string name="dialogpref_message">message of dialog preference</string>
+   <string name="dialogpref_sure">Sure</string>
+   <string name="dialogpref_cancel">Cancel</string>
+   <string name="pref_key">pref_key</string>
+   <string name="pref_title">title of preference</string>
+   <string name="pref_summary">summary of preference</string>
+   <string name="pref_depend_key">pref_depend_key</string>
+   <string name="pref_depend_title"> depend title of preference</string>
+   <string name="pref_depend_summary"> depend summary of preference</string>
+   <string name="android_intent_action_preference">android.intent.action.PREFERENCE</string>
+   <string name="def_pref_key">def_pref_key</string>
+   <string name="def_pref_title">default preference</string>
+   <string name="def_pref_summary">This is default preference of cts</string>
+   <string name="relative_view1">view 1</string>
+   <string name="relative_view2">view 2</string>
+   <string name="relative_view3">view 3</string>
+   <string name="relative_view4">view 4</string>
+   <string name="relative_view5">view 5</string>
+   <string name="relative_view6">view 6</string>
+   <string name="relative_view7">view 7</string>
+   <string name="relative_view8">view 8</string>
+   <string name="relative_view9">view 9</string>
+   <string name="relative_view10">view 10</string>
+   <string name="relative_view11">view 11</string>
+   <string name="relative_view12">view 12</string>
+   <string name="relative_view13">view 13</string>
+   <string name="country">Country:</string>
+   <string name="symbol">Symbol:</string>
+   <string name="country_warning">No such country registered</string>
+   <string name="version_cur">base</string>
+   <string name="version_old">base</string>
+   <string name="version_v3">base</string>
+   <string name="authenticator_label">Android CTS</string>
+   <string name="search_label">Android CTS</string>
+   <string name="tag1">tag 1</string>
+   <string name="tag2">tag 2</string>
+
+   <string name="button">Button</string>
+   <string name="holo_test">Holo Test</string>
+   <string name="holo_generator">Holo Generator</string>
+   <string name="holo_light_test">Holo Light Test</string>
+   <string name="holo_light_generator">Holo Light Generator</string>
+   <string name="reference_image">Reference Image: </string>
+   <string name="generated_image">Generated Image: </string>
+   <string name="themes_prompt">Select a Theme:</string>
+   <string name="sample_text">Sample text goes here. I wanted something creative and whimsical
+but then I just got bored...</string>
+    <string name="long_text">This is a really long string which exceeds the width of the view.
+New devices have a much larger screen which actually enables long strings to be displayed
+with no fading. I have made this string longer to fix this case. If you are correcting this
+text, I would love to see the kind of devices you guys now use! Guys, maybe some devices need longer string!
+I think so, so how about double this string, like copy and paste!
+This is a really long string which exceeds the width of the view.
+New devices have a much larger screen which actually enables long strings to be displayed
+with no fading. I have made this string longer to fix this case. If you are correcting this
+text, I would love to see the kind of devices you guys now use! Guys, maybe some devices need longer string!
+I think so, so how about double this string, like copy and paste! </string>
+    <string name="rectangle200">"M 0,0 l 200,0 l 0, 200 l -200, 0 z"</string>
+</resources>
diff --git a/tests/tests/view/res/values/styles.xml b/tests/tests/view/res/values/styles.xml
new file mode 100644
index 0000000..20c80f8
--- /dev/null
+++ b/tests/tests/view/res/values/styles.xml
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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 xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <style name="Whatever">
+        <item name="type1">true</item>
+        <item name="type2">false</item>
+        <item name="type3">#ff0000ff</item>
+        <item name="type4">#ff00ff00</item>
+        <item name="type5">0.75px</item>
+        <item name="type6">10px</item>
+        <item name="type7">18px</item>
+        <item name="type8">@drawable/pass</item>
+        <item name="type9">3.14</item>
+        <item name="type10">100%</item>
+        <item name="type11">365</item>
+        <item name="type12">86400</item>
+        <item name="type13">@string/hello_android</item>
+        <item name="type14">TypedArray Test!</item>
+        <item name="type15">@array/difficultyLevel</item>
+        <item name="type16">Typed Value!</item>
+    </style>
+
+    <style name="TextViewWithoutColorAndAppearance">
+        <item name="android:textSize">18sp</item>
+    </style>
+
+    <style name="TextViewWithColorButWithOutAppearance">
+        <item name="android:textColor">#ff0000ff</item>
+    </style>
+
+    <style name="TextViewWithColorAndAppearance">
+        <item name="android:textColor">#ff0000ff</item>
+        <item name="android:textAppearance">@style/TextAppearance.WithColor</item>
+    </style>
+
+    <style name="TextViewWithoutColorButWithAppearance">
+        <item name="android:textAppearance">@style/TextAppearance.WithColor</item>
+    </style>
+
+    <style name="TextAppearance" parent="android:TextAppearance">
+    </style>
+
+    <style name="TextAppearance.WithColor">
+        <item name="android:textColor">#ffff0000</item>
+    </style>
+
+    <style name="TextAppearance.All">
+        <item name="android:textColor">@drawable/black</item>
+        <item name="android:textSize">20px</item>
+        <item name="android:textStyle">bold</item>
+        <item name="android:textColorHint">@drawable/red</item>
+        <item name="android:textColorLink">@drawable/blue</item>
+        <item name="android:textColorHighlight">@drawable/yellow</item>
+    </style>
+
+    <style name="TextAppearance.Colors">
+        <item name="android:textColor">@drawable/black</item>
+        <item name="android:textColorHint">@drawable/blue</item>
+        <item name="android:textColorLink">@drawable/yellow</item>
+        <item name="android:textColorHighlight">@drawable/red</item>
+    </style>
+
+    <style name="TextAppearance.NotColors">
+        <item name="android:textSize">17px</item>
+        <item name="android:typeface">sans</item>
+        <item name="android:textStyle">normal</item>
+    </style>
+
+    <style name="TextAppearance.Style">
+        <item name="android:textStyle">normal</item>
+    </style>
+
+    <style name="TestEnum1">
+        <item name="testEnum">val1</item>
+    </style>
+
+    <style name="TestEnum2">
+        <item name="testEnum">val2</item>
+    </style>
+
+    <style name="TestEnum10">
+        <item name="testEnum">val10</item>
+    </style>
+
+    <style name="TestFlag1">
+        <item name="testFlags">bit1</item>
+    </style>
+
+    <style name="TestFlag2">
+        <item name="testFlags">bit2</item>
+    </style>
+
+    <style name="TestFlag31">
+        <item name="testFlags">bit31</item>
+    </style>
+
+    <style name="TestFlag1And2">
+        <item name="testFlags">bit1|bit2</item>
+    </style>
+
+    <style name="TestFlag1And2And31">
+        <item name="testFlags">bit1|bit2|bit31</item>
+    </style>
+
+    <style name="TestEnum1.EmptyInherit" />
+
+    <style name="Theme_AlertDialog">
+        <item name="android:textSize">18sp</item>
+    </style>
+
+    <style name="TestProgressBar">
+        <item name="android:indeterminateOnly">false</item>
+        <item name="android:progressDrawable">?android:drawable/progress_horizontal</item>
+        <item name="android:indeterminateDrawable">?android:drawable/progress_horizontal</item>
+        <item name="android:minHeight">20dip</item>
+        <item name="android:maxHeight">20dip</item>
+        <item name="android:focusable">true</item>
+    </style>
+
+    <style name="Test_Theme">
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:panelColorForeground">#ff000000</item>
+        <item name="android:panelColorBackground">#ffffffff</item>
+    </style>
+
+    <style name="Theme_OverrideOuter">
+        <item name="themeType">1</item>
+    </style>
+
+    <style name="Theme_OverrideInner">
+        <item name="themeType">2</item>
+        <item name="themeOverrideAttr">@style/Theme_OverrideAttr</item>
+    </style>
+
+    <style name="Theme_OverrideAttr">
+        <item name="themeType">3</item>
+    </style>
+    
+    <style name="Theme_ThemedDrawableTest">
+        <item name="themeBoolean">true</item>
+        <item name="themeColor">@android:color/black</item>
+        <item name="themeFloat">1.0</item>
+        <item name="themeAngle">45.0</item>
+        <item name="themeInteger">1</item>
+        <item name="themeDimension">1px</item>
+        <item name="themeDrawable">@drawable/icon_black</item>
+        <item name="themeBitmap">@drawable/icon_black</item>
+        <item name="themeNinePatch">@drawable/ninepatch_0</item>
+        <item name="themeGravity">48</item>
+        <item name="themeTileMode">2</item>
+    </style>
+
+    <style name="Theme_NoSwipeDismiss">
+        <item name="android:windowSwipeToDismiss">false</item>
+    </style>
+
+</resources>
diff --git a/tests/res/xml/merge.xml b/tests/tests/view/res/xml/merge.xml
similarity index 100%
rename from tests/res/xml/merge.xml
rename to tests/tests/view/res/xml/merge.xml
diff --git a/tests/res/xml/method.xml b/tests/tests/view/res/xml/method.xml
similarity index 100%
rename from tests/res/xml/method.xml
rename to tests/tests/view/res/xml/method.xml
diff --git a/tests/tests/view/src/android/view/animation/cts/AccelerateDecelerateInterpolatorTest.java b/tests/tests/view/src/android/view/animation/cts/AccelerateDecelerateInterpolatorTest.java
index 20ddb83..6e80d00 100644
--- a/tests/tests/view/src/android/view/animation/cts/AccelerateDecelerateInterpolatorTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/AccelerateDecelerateInterpolatorTest.java
@@ -16,7 +16,7 @@
 
 package android.view.animation.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 
 
 import android.app.Activity;
@@ -33,7 +33,7 @@
 import android.view.animation.Transformation;
 
 public class AccelerateDecelerateInterpolatorTest
-        extends ActivityInstrumentationTestCase2<AnimationTestStubActivity> {
+        extends ActivityInstrumentationTestCase2<AnimationTestCtsActivity> {
 
     private Activity mActivity;
     private static final float ALPHA_DELTA = 0.001f;
@@ -41,7 +41,7 @@
     private static final long ALPHA_DURATION = 2000;
 
     public AccelerateDecelerateInterpolatorTest() {
-        super("com.android.cts.stub", AnimationTestStubActivity.class);
+        super("com.android.cts.view", AnimationTestCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/view/src/android/view/animation/cts/AccelerateInterpolatorTest.java b/tests/tests/view/src/android/view/animation/cts/AccelerateInterpolatorTest.java
index c009533..51b2b09 100644
--- a/tests/tests/view/src/android/view/animation/cts/AccelerateInterpolatorTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/AccelerateInterpolatorTest.java
@@ -16,7 +16,7 @@
 
 package android.view.animation.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 
 
 import android.app.Activity;
@@ -33,10 +33,10 @@
 import android.view.animation.Transformation;
 
 public class AccelerateInterpolatorTest
-        extends ActivityInstrumentationTestCase2<AnimationTestStubActivity> {
+        extends ActivityInstrumentationTestCase2<AnimationTestCtsActivity> {
 
     public AccelerateInterpolatorTest() {
-        super("com.android.cts.stub", AnimationTestStubActivity.class);
+        super("com.android.cts.view", AnimationTestCtsActivity.class);
     }
 
     private Activity mActivity;
diff --git a/tests/tests/view/src/android/view/animation/cts/AlphaAnimationTest.java b/tests/tests/view/src/android/view/animation/cts/AlphaAnimationTest.java
index bcd4ccd3..acfe1a6 100644
--- a/tests/tests/view/src/android/view/animation/cts/AlphaAnimationTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/AlphaAnimationTest.java
@@ -23,7 +23,7 @@
 import android.view.animation.AlphaAnimation;
 import android.view.animation.Transformation;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 
 /**
  * Test {@link AlphaAnimation}.
diff --git a/tests/tests/view/src/android/view/animation/cts/AnimationSetTest.java b/tests/tests/view/src/android/view/animation/cts/AnimationSetTest.java
index b42c239..0b3bf49 100644
--- a/tests/tests/view/src/android/view/animation/cts/AnimationSetTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/AnimationSetTest.java
@@ -33,11 +33,11 @@
 import android.view.animation.Transformation;
 import android.view.animation.TranslateAnimation;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 
 
 public class AnimationSetTest
-        extends ActivityInstrumentationTestCase2<AnimationTestStubActivity> {
+        extends ActivityInstrumentationTestCase2<AnimationTestCtsActivity> {
 
     private static final float DELTA = 0.001f;
     private static final long SHORT_CHILD_DURATION = 400;
@@ -51,7 +51,7 @@
     private Activity mActivity;
 
     public AnimationSetTest() {
-        super("com.android.cts.stub", AnimationTestStubActivity.class);
+        super("com.android.cts.view", AnimationTestCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/view/src/android/view/animation/cts/AnimationTest.java b/tests/tests/view/src/android/view/animation/cts/AnimationTest.java
index 2d88dc4..31440df 100644
--- a/tests/tests/view/src/android/view/animation/cts/AnimationTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/AnimationTest.java
@@ -16,7 +16,7 @@
 
 package android.view.animation.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 
 
 import android.app.Activity;
@@ -38,7 +38,7 @@
 /**
  * Test {@link Animation}.
  */
-public class AnimationTest extends ActivityInstrumentationTestCase2<AnimationTestStubActivity> {
+public class AnimationTest extends ActivityInstrumentationTestCase2<AnimationTestCtsActivity> {
     private static final float ALPHA_DELTA = 0.001f;
 
     /** It is defined in R.anim.accelerate_alpha */
@@ -51,7 +51,7 @@
     private Object mLockObject = new Object();
 
     public AnimationTest() {
-        super("com.android.cts.stub", AnimationTestStubActivity.class);
+        super("com.android.cts.view", AnimationTestCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/view/src/android/view/animation/cts/AnimationTestCtsActivity.java b/tests/tests/view/src/android/view/animation/cts/AnimationTestCtsActivity.java
new file mode 100644
index 0000000..48692f1
--- /dev/null
+++ b/tests/tests/view/src/android/view/animation/cts/AnimationTestCtsActivity.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2008 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.view.animation.cts;
+
+import com.android.cts.view.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class AnimationTestCtsActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.anim_layout);
+    }
+}
diff --git a/tests/src/android/view/animation/cts/AnimationTestUtils.java b/tests/tests/view/src/android/view/animation/cts/AnimationTestUtils.java
similarity index 100%
rename from tests/src/android/view/animation/cts/AnimationTestUtils.java
rename to tests/tests/view/src/android/view/animation/cts/AnimationTestUtils.java
diff --git a/tests/tests/view/src/android/view/animation/cts/AnimationUtilsTest.java b/tests/tests/view/src/android/view/animation/cts/AnimationUtilsTest.java
index cddbfdf..9de0d87 100644
--- a/tests/tests/view/src/android/view/animation/cts/AnimationUtilsTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/AnimationUtilsTest.java
@@ -16,7 +16,7 @@
 
 package android.view.animation.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 
 
 import android.content.Context;
@@ -30,22 +30,22 @@
 import android.view.animation.LayoutAnimationController;
 
 public class AnimationUtilsTest extends
-        ActivityInstrumentationTestCase2<AnimationTestStubActivity> {
+        ActivityInstrumentationTestCase2<AnimationTestCtsActivity> {
 
-    private AnimationTestStubActivity mActivity;
+    private AnimationTestCtsActivity mActivity;
 
     public AnimationUtilsTest() {
-        super("com.android.cts.stub", AnimationTestStubActivity.class);
+        super("com.android.cts.view", AnimationTestCtsActivity.class);
     }
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mActivity = (AnimationTestStubActivity) getActivity();
+        mActivity = (AnimationTestCtsActivity) getActivity();
     }
 
     public void testLoad() {
-        // XML file of com.android.cts.stub.R.anim.anim_alpha
+        // XML file of com.android.cts.view.R.anim.anim_alpha
         // <alpha xmlns:android="http://schemas.android.com/apk/res/android"
         //      android:interpolator="@android:anim/accelerate_interpolator"
         //      android:fromAlpha="0.0"
@@ -61,7 +61,7 @@
                 android.R.anim.accelerate_interpolator);
         assertTrue(interpolator instanceof AccelerateInterpolator);
 
-        // Load LayoutAnimationController from com.android.cts.stub.R.anim.anim_gridlayout
+        // Load LayoutAnimationController from com.android.cts.view.R.anim.anim_gridlayout
         // <gridLayoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
         //      android:delay="10%"
         //      android:rowDelay="50%"
diff --git a/tests/tests/view/src/android/view/animation/cts/CycleInterpolatorTest.java b/tests/tests/view/src/android/view/animation/cts/CycleInterpolatorTest.java
index 56cb32c..3297377 100644
--- a/tests/tests/view/src/android/view/animation/cts/CycleInterpolatorTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/CycleInterpolatorTest.java
@@ -29,14 +29,14 @@
 import android.view.animation.Interpolator;
 import android.view.animation.Transformation;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 
 
 /**
  * Test {@link CycleInterpolator}.
  */
 public class CycleInterpolatorTest
-        extends ActivityInstrumentationTestCase2<AnimationTestStubActivity> {
+        extends ActivityInstrumentationTestCase2<AnimationTestCtsActivity> {
 
     private Activity mActivity;
 
@@ -45,7 +45,7 @@
     private static final float ALPHA_DELTA = 0.001f;
 
     public CycleInterpolatorTest() {
-        super("com.android.cts.stub", AnimationTestStubActivity.class);
+        super("com.android.cts.view", AnimationTestCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/view/src/android/view/animation/cts/DecelerateInterpolatorTest.java b/tests/tests/view/src/android/view/animation/cts/DecelerateInterpolatorTest.java
index 5bae1f7..deb52dd 100644
--- a/tests/tests/view/src/android/view/animation/cts/DecelerateInterpolatorTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/DecelerateInterpolatorTest.java
@@ -16,7 +16,7 @@
 
 package android.view.animation.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 
 
 import android.app.Activity;
@@ -36,7 +36,7 @@
  * Test {@link DecelerateInterpolator}.
  */
 public class DecelerateInterpolatorTest
-        extends ActivityInstrumentationTestCase2<AnimationTestStubActivity> {
+        extends ActivityInstrumentationTestCase2<AnimationTestCtsActivity> {
 
     private Activity mActivity;
     private static final float ALPHA_DELTA = 0.001f;
@@ -45,7 +45,7 @@
     private static final long DECELERATE_ALPHA_DURATION = 2000;
 
     public DecelerateInterpolatorTest() {
-        super("com.android.cts.stub", AnimationTestStubActivity.class);
+        super("com.android.cts.view", AnimationTestCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/view/src/android/view/animation/cts/GridLayoutAnimCtsActivity.java b/tests/tests/view/src/android/view/animation/cts/GridLayoutAnimCtsActivity.java
new file mode 100644
index 0000000..bf95077
--- /dev/null
+++ b/tests/tests/view/src/android/view/animation/cts/GridLayoutAnimCtsActivity.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2009 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.view.animation.cts;
+
+import com.android.cts.view.R;
+
+import android.app.Activity;
+import android.database.DataSetObserver;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AbsListView;
+import android.widget.GridView;
+import android.widget.ImageView;
+import android.widget.ListAdapter;
+
+public class GridLayoutAnimCtsActivity extends Activity {
+
+    private GridView mGridView;
+    private static final int GRID_NUM = 9;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.gridlayout_anim_controller_layout);
+        mGridView = (GridView) findViewById(R.id.gridlayout_anim_gridview);
+        mGridView.setAdapter(new MockGridViewAdapter(GRID_NUM));
+    }
+
+    public GridView getGridView() {
+        return mGridView;
+    }
+
+    private class MockGridViewAdapter implements ListAdapter {
+        private final int mCount;
+
+        MockGridViewAdapter(int count) {
+            mCount = count;
+        }
+
+        MockGridViewAdapter() {
+            this(1);
+        }
+
+        public boolean areAllItemsEnabled() {
+            return true;
+        }
+
+        public boolean isEnabled(int position) {
+            return true;
+        }
+
+        public void registerDataSetObserver(DataSetObserver observer) {
+        }
+
+        public void unregisterDataSetObserver(DataSetObserver observer) {
+        }
+
+        public int getCount() {
+            return mCount;
+        }
+
+        public Object getItem(int position) {
+            return position;
+        }
+
+        public long getItemId(int position) {
+            return position;
+        }
+
+        public boolean hasStableIds() {
+            return false;
+        }
+
+        public View getView(int position, View convertView, ViewGroup parent) {
+            if ((convertView != null) && (convertView instanceof ImageView)) {
+                ((ImageView) convertView).setImageResource(R.drawable.size_48x48);
+                return convertView;
+            }
+
+            ImageView newView = new ImageView(GridLayoutAnimCtsActivity.this);
+            AbsListView.LayoutParams params = new AbsListView.LayoutParams(
+                    AbsListView.LayoutParams.WRAP_CONTENT, AbsListView.LayoutParams.WRAP_CONTENT);
+            newView.setLayoutParams(params);
+            newView.setImageResource(R.drawable.size_48x48);
+            return newView;
+        }
+
+        public int getItemViewType(int position) {
+            return 0;
+        }
+
+        public int getViewTypeCount() {
+            return 1;
+        }
+
+        public boolean isEmpty() {
+            return false;
+        }
+    }
+}
diff --git a/tests/tests/view/src/android/view/animation/cts/GridLayoutAnimationControllerTest.java b/tests/tests/view/src/android/view/animation/cts/GridLayoutAnimationControllerTest.java
index 80c40fa..54898b4 100644
--- a/tests/tests/view/src/android/view/animation/cts/GridLayoutAnimationControllerTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/GridLayoutAnimationControllerTest.java
@@ -16,7 +16,7 @@
 
 package android.view.animation.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 
 
 import android.content.Context;
@@ -35,9 +35,9 @@
 import android.widget.GridView;
 
 public class GridLayoutAnimationControllerTest
-    extends ActivityInstrumentationTestCase2<GridLayoutAnimStubActivity> {
+    extends ActivityInstrumentationTestCase2<GridLayoutAnimCtsActivity> {
 
-    private GridLayoutAnimStubActivity mActivity;
+    private GridLayoutAnimCtsActivity mActivity;
     private Animation mDefaultAnimation;
     private GridLayoutAnimationController mController;
     /** The GridView will be 3*3 */
@@ -58,7 +58,7 @@
     private static final int INDEX_OF_CHILD9 = 8;
 
     public GridLayoutAnimationControllerTest() {
-        super("com.android.cts.stub", GridLayoutAnimStubActivity.class);
+        super("com.android.cts.view", GridLayoutAnimCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/view/src/android/view/animation/cts/LayoutAnimCtsActivity.java b/tests/tests/view/src/android/view/animation/cts/LayoutAnimCtsActivity.java
new file mode 100644
index 0000000..0b9203f
--- /dev/null
+++ b/tests/tests/view/src/android/view/animation/cts/LayoutAnimCtsActivity.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2009 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.view.animation.cts;
+
+import android.app.ListActivity;
+import android.os.Bundle;
+import android.widget.ArrayAdapter;
+
+
+public class LayoutAnimCtsActivity extends ListActivity {
+
+    private String[] mStrings = {
+            "Android",
+            "CTS",
+            "Test",
+    };
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setListAdapter(new ArrayAdapter<String>(this,
+                android.R.layout.simple_list_item_1, mStrings));
+    }
+}
diff --git a/tests/tests/view/src/android/view/animation/cts/LayoutAnimationControllerTest.java b/tests/tests/view/src/android/view/animation/cts/LayoutAnimationControllerTest.java
index cccf0a6..2f8f36d 100644
--- a/tests/tests/view/src/android/view/animation/cts/LayoutAnimationControllerTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/LayoutAnimationControllerTest.java
@@ -16,7 +16,7 @@
 
 package android.view.animation.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 
 
 import android.app.ListActivity;
@@ -40,7 +40,7 @@
 import android.widget.ListView;
 
 public class LayoutAnimationControllerTest
-        extends ActivityInstrumentationTestCase2<LayoutAnimStubActivity> {
+        extends ActivityInstrumentationTestCase2<LayoutAnimCtsActivity> {
 
     private ListActivity mActivity;
     private Animation mDefaultAnimation;
@@ -58,7 +58,7 @@
     private static final long DEFAULT_MAX_DURATION = 2000;
 
     public LayoutAnimationControllerTest() {
-        super("com.android.cts.stub", LayoutAnimStubActivity.class);
+        super("com.android.cts.view", LayoutAnimCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/view/src/android/view/animation/cts/LinearInterpolatorTest.java b/tests/tests/view/src/android/view/animation/cts/LinearInterpolatorTest.java
index ff9e734..28407f9 100644
--- a/tests/tests/view/src/android/view/animation/cts/LinearInterpolatorTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/LinearInterpolatorTest.java
@@ -26,13 +26,13 @@
 import android.view.animation.LinearInterpolator;
 import android.view.animation.Transformation;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 
 
 /**
  * Test {@link LinearInterpolator}.
  */
-public class LinearInterpolatorTest extends ActivityInstrumentationTestCase2<AnimationTestStubActivity> {
+public class LinearInterpolatorTest extends ActivityInstrumentationTestCase2<AnimationTestCtsActivity> {
 
     private Activity mActivity;
     private static final float ALPHA_DELTA = 0.001f;
@@ -42,7 +42,7 @@
     private static final long LINEAR_ALPHA_TIME_STEP = LINEAR_ALPHA_DURATION / 5;
 
     public LinearInterpolatorTest() {
-        super("com.android.cts.stub", AnimationTestStubActivity.class);
+        super("com.android.cts.view", AnimationTestCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/view/src/android/view/animation/cts/RotateAnimationTest.java b/tests/tests/view/src/android/view/animation/cts/RotateAnimationTest.java
index 0bc7ab0..958133a 100644
--- a/tests/tests/view/src/android/view/animation/cts/RotateAnimationTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/RotateAnimationTest.java
@@ -28,11 +28,11 @@
 import android.view.animation.RotateAnimation;
 import android.view.animation.Transformation;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 
 
 public class RotateAnimationTest
-        extends ActivityInstrumentationTestCase2<AnimationTestStubActivity> {
+        extends ActivityInstrumentationTestCase2<AnimationTestCtsActivity> {
 
     private Activity mActivity;
 
@@ -42,7 +42,7 @@
     private static final float TO_DEGREE = 90.0f;
 
     public RotateAnimationTest() {
-        super("com.android.cts.stub", AnimationTestStubActivity.class);
+        super("com.android.cts.view", AnimationTestCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/view/src/android/view/animation/cts/ScaleAnimationTest.java b/tests/tests/view/src/android/view/animation/cts/ScaleAnimationTest.java
index 243dace..e17435e 100644
--- a/tests/tests/view/src/android/view/animation/cts/ScaleAnimationTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/ScaleAnimationTest.java
@@ -16,7 +16,7 @@
 
 package android.view.animation.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 
 
 import android.content.res.XmlResourceParser;
@@ -30,7 +30,7 @@
 import android.view.animation.Transformation;
 
 public class ScaleAnimationTest
-        extends ActivityInstrumentationTestCase2<AnimationTestStubActivity> {
+        extends ActivityInstrumentationTestCase2<AnimationTestCtsActivity> {
     private static long DURATION = 1000;
     private static float DELTA = 0.001f;
     private static float FROM_X = 1.0f;
@@ -41,10 +41,10 @@
     private static float PIVOT_Y = 0.6f;
     private static float MID_X = 0.8f;
     private static float MID_Y = 3.3f;
-    private AnimationTestStubActivity mActivity;
+    private AnimationTestCtsActivity mActivity;
 
     public ScaleAnimationTest() {
-        super("com.android.cts.stub", AnimationTestStubActivity.class);
+        super("com.android.cts.view", AnimationTestCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/view/src/android/view/animation/cts/TranslateAnimationTest.java b/tests/tests/view/src/android/view/animation/cts/TranslateAnimationTest.java
index 959e506..94ab558 100644
--- a/tests/tests/view/src/android/view/animation/cts/TranslateAnimationTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/TranslateAnimationTest.java
@@ -28,11 +28,11 @@
 import android.view.animation.Transformation;
 import android.view.animation.TranslateAnimation;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 
 
 public class TranslateAnimationTest
-        extends ActivityInstrumentationTestCase2<AnimationTestStubActivity> {
+        extends ActivityInstrumentationTestCase2<AnimationTestCtsActivity> {
 
     private Activity mActivity;
 
@@ -48,7 +48,7 @@
     private static final float RELATIVE_TO_Y_DELTA = 0.4f;
 
     public TranslateAnimationTest() {
-        super("com.android.cts.stub", AnimationTestStubActivity.class);
+        super("com.android.cts.view", AnimationTestCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/view/src/android/view/cts/ChoreographerTest.java b/tests/tests/view/src/android/view/cts/ChoreographerTest.java
index 3a34b2c..6862fac 100644
--- a/tests/tests/view/src/android/view/cts/ChoreographerTest.java
+++ b/tests/tests/view/src/android/view/cts/ChoreographerTest.java
@@ -16,16 +16,27 @@
 
 package android.view.cts;
 
-import android.test.AndroidTestCase;
+import android.test.InstrumentationTestCase;
 import android.view.Choreographer;
 
-public class ChoreographerTest extends AndroidTestCase {
+public class ChoreographerTest extends InstrumentationTestCase {
     private static final long NOMINAL_VSYNC_PERIOD = 16;
     private static final long DELAY_PERIOD = NOMINAL_VSYNC_PERIOD * 5;
     private static final long NANOS_PER_MS = 1000000;
     private static final Object TOKEN = new Object();
 
-    private Choreographer mChoreographer = Choreographer.getInstance();
+    private Choreographer mChoreographer;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                mChoreographer = Choreographer.getInstance();
+            }
+        });
+    }
 
     public void testFrameDelay() {
         assertTrue(Choreographer.getFrameDelay() > 0);
diff --git a/tests/tests/view/src/android/view/cts/ContextThemeWrapperTest.java b/tests/tests/view/src/android/view/cts/ContextThemeWrapperTest.java
index 33d1682..c40f095 100644
--- a/tests/tests/view/src/android/view/cts/ContextThemeWrapperTest.java
+++ b/tests/tests/view/src/android/view/cts/ContextThemeWrapperTest.java
@@ -23,7 +23,7 @@
 import android.test.AndroidTestCase;
 import android.view.ContextThemeWrapper;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 
 
 public class ContextThemeWrapperTest extends AndroidTestCase {
diff --git a/tests/tests/view/src/android/view/cts/CtsActivity.java b/tests/tests/view/src/android/view/cts/CtsActivity.java
new file mode 100644
index 0000000..08607d2
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/CtsActivity.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2009 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.view.cts;
+
+import android.app.Activity;
+
+/**
+ * Stub activity for helping test. It's an empty activity.
+ */
+public class CtsActivity extends Activity {
+
+}
diff --git a/tests/tests/view/src/android/view/cts/DisplayRefreshRateTest.java b/tests/tests/view/src/android/view/cts/DisplayRefreshRateTest.java
index cc2517d..5120604 100644
--- a/tests/tests/view/src/android/view/cts/DisplayRefreshRateTest.java
+++ b/tests/tests/view/src/android/view/cts/DisplayRefreshRateTest.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.opengl.GLSurfaceView;
-import android.opengl.cts.GLSurfaceViewStubActivity;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
 import android.view.Display;
@@ -39,7 +38,7 @@
  * way of measuring the actual refresh rate.
  */
 public class DisplayRefreshRateTest extends
-        ActivityInstrumentationTestCase2<GLSurfaceViewStubActivity> {
+        ActivityInstrumentationTestCase2<GLSurfaceViewCtsActivity> {
 
     // The test passes if
     //   abs(measured_fps - Display.getRefreshRate()) <= FPS_TOLERANCE.
@@ -157,21 +156,21 @@
     private FpsResult mResult;
 
     public DisplayRefreshRateTest() {
-        super(GLSurfaceViewStubActivity.class);
+        super(GLSurfaceViewCtsActivity.class);
         mResult = new FpsResult();
     }
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        GLSurfaceViewStubActivity.setRenderer(new Renderer(mResult));
-        GLSurfaceViewStubActivity.setRenderMode(
+        GLSurfaceViewCtsActivity.setRenderer(new Renderer(mResult));
+        GLSurfaceViewCtsActivity.setRenderMode(
                 GLSurfaceView.RENDERMODE_CONTINUOUSLY);
     }
 
     public void testRefreshRate() throws java.lang.InterruptedException {
         boolean fpsOk = false;
-        GLSurfaceViewStubActivity activity = getActivity();
+        GLSurfaceViewCtsActivity activity = getActivity();
 
         WindowManager wm = (WindowManager)activity
                 .getView()
diff --git a/tests/tests/view/src/android/view/cts/FocusFinderCtsActivity.java b/tests/tests/view/src/android/view/cts/FocusFinderCtsActivity.java
new file mode 100644
index 0000000..14ab577
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/FocusFinderCtsActivity.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2008 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.view.cts;
+
+import com.android.cts.view.R;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+public class FocusFinderCtsActivity extends Activity {
+
+    public ViewGroup layout;
+
+    public Button topLeftButton;
+
+    public Button topRightButton;
+
+    public Button bottomLeftButton;
+
+    public Button bottomRightButton;
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.focus_finder_layout);
+        layout = (ViewGroup) findViewById(R.id.layout);
+        topLeftButton = (Button) findViewById(R.id.top_left_button);
+        topRightButton = (Button) findViewById(R.id.top_right_button);
+        bottomLeftButton = (Button) findViewById(R.id.bottom_left_button);
+        bottomRightButton = (Button) findViewById(R.id.bottom_right_button);
+    }
+}
+
diff --git a/tests/tests/view/src/android/view/cts/FocusFinderTest.java b/tests/tests/view/src/android/view/cts/FocusFinderTest.java
index 6e54603..55c288e 100644
--- a/tests/tests/view/src/android/view/cts/FocusFinderTest.java
+++ b/tests/tests/view/src/android/view/cts/FocusFinderTest.java
@@ -24,7 +24,7 @@
 import android.view.ViewGroup;
 import android.widget.Button;
 
-public class FocusFinderTest extends ActivityInstrumentationTestCase2<FocusFinderStubActivity> {
+public class FocusFinderTest extends ActivityInstrumentationTestCase2<FocusFinderCtsActivity> {
 
     private FocusFinder mFocusFinder;
     private ViewGroup mLayout;
@@ -34,7 +34,7 @@
     private Button mBottomRight;
 
     public FocusFinderTest() {
-        super("com.android.cts.stub", FocusFinderStubActivity.class);
+        super("com.android.cts.view", FocusFinderCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/view/src/android/view/cts/FocusHandlingCtsActivity.java b/tests/tests/view/src/android/view/cts/FocusHandlingCtsActivity.java
new file mode 100644
index 0000000..5489e2a
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/FocusHandlingCtsActivity.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2009 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.view.cts;
+
+import com.android.cts.view.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * A simple activity to test "Focus Handling"
+ */
+public class FocusHandlingCtsActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setTheme(android.R.style.Theme_Holo_NoActionBar);
+        setContentView(R.layout.focus_handling_layout);
+    }
+}
diff --git a/tests/tests/view/src/android/view/cts/GLSurfaceViewCtsActivity.java b/tests/tests/view/src/android/view/cts/GLSurfaceViewCtsActivity.java
new file mode 100644
index 0000000..bc916a7
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/GLSurfaceViewCtsActivity.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2010 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.view.cts;
+
+import android.app.Activity;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.view.Window;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+/**
+ * A minimal activity for testing {@link android.opengl.GLSurfaceView}.
+ * Also accepts non-blank renderers to allow its use for more complex tests.
+ */
+public class GLSurfaceViewCtsActivity extends Activity {
+
+    private static class Renderer implements GLSurfaceView.Renderer {
+
+        public void onDrawFrame(GL10 gl) {
+            // Do nothing.
+        }
+
+        public void onSurfaceChanged(GL10 gl, int width, int height) {
+            // Do nothing.
+        }
+
+        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+            // Do nothing.
+        }
+    }
+
+    private GLSurfaceView mView;
+
+    /** To override the blank renderer, or other settings, these
+     * static set* methods must be called before onCreate() is called.
+     * If using ActivityInstrumentationTestCase2, that means the set
+     * methods need to be called before calling getActivity in the
+     * test setUp().
+     */
+    private static GLSurfaceView.Renderer mRenderer = null;
+    public static void setRenderer(GLSurfaceView.Renderer renderer) {
+        mRenderer = renderer;
+    }
+    public static void resetRenderer() {
+        mRenderer = null;
+    }
+
+    private static int mRenderMode = 0;
+    private static boolean mRenderModeSet = false;
+    public static void setRenderMode(int renderMode) {
+        mRenderModeSet = true;
+        mRenderMode = renderMode;
+    }
+    public static void resetRenderMode() {
+        mRenderModeSet = false;
+        mRenderMode = 0;
+    }
+
+    private static int mGlVersion = 0;
+    private static boolean mGlVersionSet = false;
+    public static void setGlVersion(int glVersion) {
+        mGlVersionSet = true;
+        mGlVersion = glVersion;
+    }
+    public static void resetGlVersion() {
+        mGlVersionSet = false;
+        mGlVersion = 0;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mView = new GLSurfaceView(this);
+        // Only set this if explicitly asked for
+        if (mGlVersionSet) {
+            mView.setEGLContextClientVersion(mGlVersion);
+        }
+        // Use no-op renderer by default
+        if (mRenderer == null) {
+            mView.setRenderer(new Renderer());
+        } else {
+            mView.setRenderer(mRenderer);
+        }
+        // Only set this if explicitly asked for
+        if (mRenderModeSet) {
+            mView.setRenderMode(mRenderMode);
+        }
+        this.requestWindowFeature(Window.FEATURE_NO_TITLE);
+        setContentView(mView);
+    }
+
+    public GLSurfaceView getView() {
+        return mView;
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        mView.onResume();
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        mView.onPause();
+    }
+}
diff --git a/tests/tests/view/src/android/view/cts/GestureDetectorCtsActivity.java b/tests/tests/view/src/android/view/cts/GestureDetectorCtsActivity.java
new file mode 100644
index 0000000..f02a0d6
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/GestureDetectorCtsActivity.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2009 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.view.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.GestureDetector.SimpleOnGestureListener;
+import android.view.View.OnTouchListener;
+import android.widget.Button;
+
+public class GestureDetectorCtsActivity extends Activity {
+
+    public boolean isDown;
+    public boolean isScroll;
+    public boolean isFling;
+    public boolean isSingleTapUp;
+    public boolean onShowPress;
+    public boolean onLongPress;
+    public boolean onDoubleTap;
+    public boolean onDoubleTapEvent;
+    public boolean onSingleTapConfirmed;
+
+    private GestureDetector mGestureDetector;
+    private MockOnGestureListener mOnGestureListener;
+    private Handler mHandler;
+    private View mView;
+    private Button mTop;
+    private Button mButton;
+    private ViewGroup mViewGroup;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        mOnGestureListener = new MockOnGestureListener();
+        mHandler = new Handler();
+
+        mGestureDetector = new GestureDetector(this, mOnGestureListener, mHandler);
+        mGestureDetector.setOnDoubleTapListener(mOnGestureListener);
+        mView = new View(this);
+        mButton = new Button(this);
+        mTop = new Button(this);
+        mView.setOnTouchListener(new MockOnTouchListener());
+
+        mViewGroup = new ViewGroup(this) {
+            @Override
+            protected void onLayout(boolean changed, int l, int t, int r, int b) {
+            }
+        };
+        mViewGroup.addView(mView);
+        mViewGroup.addView(mTop);
+        mViewGroup.addView(mButton);
+        mViewGroup.setOnTouchListener(new MockOnTouchListener());
+        setContentView(mViewGroup);
+
+    }
+
+    public View getView() {
+        return mView;
+    }
+
+    public ViewGroup getViewGroup() {
+        return mViewGroup;
+    }
+
+    public GestureDetector getGestureDetector() {
+        return mGestureDetector;
+    }
+
+    public class MockOnGestureListener extends SimpleOnGestureListener {
+        public boolean onDown(MotionEvent e) {
+            isDown = true;
+            return true;
+        }
+
+        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+            isFling = true;
+            return true;
+        }
+
+        public void onLongPress(MotionEvent e) {
+            onLongPress = true;
+        }
+
+        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+            isScroll = true;
+            return true;
+        }
+
+        public void onShowPress(MotionEvent e) {
+            onShowPress = true;
+        }
+
+        public boolean onSingleTapUp(MotionEvent e) {
+            isSingleTapUp = true;
+            return true;
+        }
+
+        public boolean onDoubleTap(MotionEvent e) {
+            onDoubleTap = true;
+            return false;
+        }
+
+        public boolean onDoubleTapEvent(MotionEvent e) {
+            onDoubleTapEvent = true;
+            return false;
+        }
+
+        public boolean onSingleTapConfirmed(MotionEvent e) {
+            onSingleTapConfirmed = true;
+            return false;
+        }
+    }
+
+    class MockOnTouchListener implements OnTouchListener {
+
+        public boolean onTouch(View v, MotionEvent event) {
+            mGestureDetector.onTouchEvent(event);
+            return true;
+        }
+    }
+
+}
diff --git a/tests/tests/view/src/android/view/cts/GestureDetectorTest.java b/tests/tests/view/src/android/view/cts/GestureDetectorTest.java
index e2e5465..c568cf1 100644
--- a/tests/tests/view/src/android/view/cts/GestureDetectorTest.java
+++ b/tests/tests/view/src/android/view/cts/GestureDetectorTest.java
@@ -18,19 +18,21 @@
 
 import android.content.Context;
 import android.os.Handler;
+import android.os.Looper;
 import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
 import android.view.GestureDetector;
 import android.view.GestureDetector.SimpleOnGestureListener;
 
 public class GestureDetectorTest extends
-        ActivityInstrumentationTestCase2<GestureDetectorStubActivity> {
+        ActivityInstrumentationTestCase2<GestureDetectorCtsActivity> {
 
     private GestureDetector mGestureDetector;
-    private GestureDetectorStubActivity mActivity;
+    private GestureDetectorCtsActivity mActivity;
     private Context mContext;
 
     public GestureDetectorTest() {
-        super("com.android.cts.stub", GestureDetectorStubActivity.class);
+        super("com.android.cts.view", GestureDetectorCtsActivity.class);
     }
 
     @Override
@@ -50,11 +52,13 @@
         mActivity.onSingleTapConfirmed = false;
     }
 
+    @UiThreadTest
     public void testConstructor() {
 
-        new GestureDetector(mContext, new SimpleOnGestureListener(), new Handler());
+        new GestureDetector(
+                mContext, new SimpleOnGestureListener(), new Handler(Looper.getMainLooper()));
         new GestureDetector(mContext, new SimpleOnGestureListener());
-        new GestureDetector(new SimpleOnGestureListener(), new Handler());
+        new GestureDetector(new SimpleOnGestureListener(), new Handler(Looper.getMainLooper()));
         new GestureDetector(new SimpleOnGestureListener());
 
         try {
diff --git a/tests/tests/view/src/android/view/cts/LayoutInflaterTest.java b/tests/tests/view/src/android/view/cts/LayoutInflaterTest.java
index b33a312..bf83086 100644
--- a/tests/tests/view/src/android/view/cts/LayoutInflaterTest.java
+++ b/tests/tests/view/src/android/view/cts/LayoutInflaterTest.java
@@ -16,21 +16,22 @@
 
 package android.view.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 import com.android.internal.util.XmlUtils;
 
-
 import org.xmlpull.v1.XmlPullParser;
 
-import android.app.cts.MockActivity;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
+import android.content.res.Resources.Theme;
 import android.content.res.XmlResourceParser;
 import android.test.AndroidTestCase;
+import android.text.TextUtils;
 import android.util.AttributeSet;
+import android.util.TypedValue;
 import android.util.Xml;
 import android.view.Gravity;
 import android.view.InflateException;
@@ -42,20 +43,21 @@
 import android.widget.LinearLayout;
 
 public class LayoutInflaterTest extends AndroidTestCase {
-
     private LayoutInflater mLayoutInflater;
-    private Context mContext;
-    private final Factory mFactory = new Factory() {
-        public View onCreateView(String name, Context context,
-                AttributeSet attrs) {
 
+    @SuppressWarnings("hiding")
+    private Context mContext;
+
+    private final Factory mFactory = new Factory() {
+        @Override
+        public View onCreateView(String name, Context context, AttributeSet attrs) {
             return null;
         }
     };
     private boolean isOnLoadClass;
     private final Filter mFilter = new Filter() {
-
-        @SuppressWarnings("unchecked")
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        @Override
         public boolean onLoadClass(Class clazz) {
             isOnLoadClass = true;
             return true;
@@ -148,7 +150,8 @@
         mLayoutInflater = LayoutInflater.from(mContext);
         isOnLoadClass = false;
         mLayoutInflater.setFilter(new Filter() {
-            @SuppressWarnings("unchecked")
+            @SuppressWarnings({ "unchecked", "rawtypes" })
+            @Override
             public boolean onLoadClass(Class clazz) {
                 isOnLoadClass = true;
                 return false;
@@ -208,7 +211,7 @@
 
     public void testInflate() {
         View view = mLayoutInflater.inflate(
-                com.android.cts.stub.R.layout.inflater_layout, null);
+                com.android.cts.view.R.layout.inflater_layout, null);
         assertNotNull(view);
         view = null;
         try {
@@ -307,60 +310,99 @@
     }
 
     public void testInflate4() {
-       XmlResourceParser parser = getContext().getResources().getLayout(
-               R.layout.inflater_layout);
-       View view = mLayoutInflater.inflate(parser, null, false);
-       assertNotNull(view);
-       view = null;
-       try {
-           view = mLayoutInflater.inflate(null, null, false);
-           fail("should throw exception");
-       } catch (NullPointerException e) {
-       }
-       LinearLayout mLayout;
-       mLayout = new LinearLayout(mContext);
-       mLayout.setOrientation(LinearLayout.VERTICAL);
-       mLayout.setHorizontalGravity(Gravity.LEFT);
-       mLayout.setLayoutParams(new ViewGroup.LayoutParams(
-               ViewGroup.LayoutParams.MATCH_PARENT,
-               ViewGroup.LayoutParams.MATCH_PARENT));
-       assertEquals(0, mLayout.getChildCount());
+        XmlResourceParser parser = getContext().getResources().getLayout(
+                R.layout.inflater_layout);
+        View view = mLayoutInflater.inflate(parser, null, false);
+        assertNotNull(view);
+        view = null;
+        try {
+            view = mLayoutInflater.inflate(null, null, false);
+            fail("should throw exception");
+        } catch (NullPointerException e) {
+        }
+        LinearLayout mLayout;
+        mLayout = new LinearLayout(mContext);
+        mLayout.setOrientation(LinearLayout.VERTICAL);
+        mLayout.setHorizontalGravity(Gravity.LEFT);
+        mLayout.setLayoutParams(new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.MATCH_PARENT));
+        assertEquals(0, mLayout.getChildCount());
 
-       try {
-           view = mLayoutInflater.inflate(parser, mLayout, false);
-           fail("should throw exception");
-       } catch (NullPointerException e) {
-       }
-       parser = getContext().getResources().getLayout(
-               R.layout.inflater_layout);
-       view = mLayoutInflater.inflate(parser, mLayout, false);
-       assertNull(view.getParent());
-       assertNotNull(view);
-       assertEquals(0, mLayout.getChildCount());
-       parser = getContext().getResources().getLayout(
-               R.layout.inflater_layout);
-       assertEquals(0, mLayout.getChildCount());
-       view = mLayoutInflater.inflate(parser, mLayout, true);
-       assertNotNull(view);
-       assertNull(view.getParent());
-       assertEquals(1, mLayout.getChildCount());
+        try {
+            view = mLayoutInflater.inflate(parser, mLayout, false);
+            fail("should throw exception");
+        } catch (NullPointerException e) {
+        }
+        parser = getContext().getResources().getLayout(
+                R.layout.inflater_layout);
+        view = mLayoutInflater.inflate(parser, mLayout, false);
+        assertNull(view.getParent());
+        assertNotNull(view);
+        assertEquals(0, mLayout.getChildCount());
+        parser = getContext().getResources().getLayout(
+                R.layout.inflater_layout);
+        assertEquals(0, mLayout.getChildCount());
+        view = mLayoutInflater.inflate(parser, mLayout, true);
+        assertNotNull(view);
+        assertNull(view.getParent());
+        assertEquals(1, mLayout.getChildCount());
 
-       parser = null;
-       parser = getParser();
-       try {
-           view = mLayoutInflater.inflate(parser, mLayout, false);
-           fail("should throw exception");
-       } catch (InflateException e) {
-       }
+        parser = null;
+        parser = getParser();
+        try {
+            view = mLayoutInflater.inflate(parser, mLayout, false);
+            fail("should throw exception");
+        } catch (InflateException e) {
+        }
 
-       parser = null;
-       view = null;
-       parser = getParser();
+        parser = null;
+        view = null;
+        parser = getParser();
 
-       view = mLayoutInflater.inflate(parser, mLayout, true);
-       assertNotNull(view);
-       assertEquals(2, mLayout.getChildCount());
-   }
+        view = mLayoutInflater.inflate(parser, mLayout, true);
+        assertNotNull(view);
+        assertEquals(2, mLayout.getChildCount());
+    }
+
+    public void testOverrideTheme() {
+        View container = mLayoutInflater.inflate(R.layout.inflater_override_theme_layout, null);
+        verifyThemeType(container, "view_outer", R.id.view_outer, 1);
+        verifyThemeType(container, "view_inner", R.id.view_inner, 2);
+        verifyThemeType(container, "view_attr", R.id.view_attr, 3);
+    }
+
+    private void verifyThemeType(View container, String tag, int id, int type) {
+        TypedValue outValue = new TypedValue();
+        View view = container.findViewById(id);
+        assertNotNull("Found " + tag, view);
+        Theme theme = view.getContext().getTheme();
+        boolean resolved = theme.resolveAttribute(R.attr.themeType, outValue, true);
+        assertTrue("Resolved themeType for " + tag, resolved);
+        assertEquals(tag + " has themeType " + type, type, outValue.data);
+    }
+
+    public void testInflateTags() {
+        final View view = mLayoutInflater.inflate(
+                com.android.cts.view.R.layout.inflater_layout_tags, null);
+        assertNotNull(view);
+
+        checkViewTag(view, R.id.viewlayout_root, R.id.tag_viewlayout_root, R.string.tag1);
+        checkViewTag(view, R.id.mock_view, R.id.tag_mock_view, R.string.tag2);
+    }
+
+    private void checkViewTag(View parent, int viewId, int tagId, int valueResId) {
+        final View target = parent.findViewById(viewId);
+        assertNotNull("Found target view for " + viewId, target);
+
+        final Object tag = target.getTag(tagId);
+        assertNotNull("Tag is set", tag);
+        assertTrue("Tag is a character sequence", tag instanceof CharSequence);
+
+        final Context targetContext = target.getContext();
+        final CharSequence expectedValue = targetContext.getString(valueResId);
+        assertEquals(tagId + " has tag " + expectedValue, expectedValue, tag);
+    }
 
     static class MockLayoutInflater extends LayoutInflater {
 
diff --git a/tests/tests/view/src/android/view/cts/MenuInflaterCtsActivity.java b/tests/tests/view/src/android/view/cts/MenuInflaterCtsActivity.java
new file mode 100644
index 0000000..75adede
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/MenuInflaterCtsActivity.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2008 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.view.cts;
+
+import android.app.Activity;
+import android.view.MenuInflater;
+
+/**
+ * Stub activity for testing {@link MenuInflater}.
+ *
+ * @see MenuInflaterTest
+ */
+public class MenuInflaterCtsActivity extends Activity {
+}
diff --git a/tests/tests/view/src/android/view/cts/MenuInflaterTest.java b/tests/tests/view/src/android/view/cts/MenuInflaterTest.java
index cf1047e..40d1d3d 100644
--- a/tests/tests/view/src/android/view/cts/MenuInflaterTest.java
+++ b/tests/tests/view/src/android/view/cts/MenuInflaterTest.java
@@ -16,13 +16,14 @@
 
 package android.view.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 import com.android.internal.view.menu.MenuBuilder;
 
 
 import android.app.Activity;
 import android.content.Context;
 import android.content.res.Resources;
+import android.cts.util.WidgetTestUtils;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.drawable.BitmapDrawable;
@@ -30,18 +31,17 @@
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.SubMenu;
-import android.widget.cts.WidgetTestUtils;
 
 /**
  * Test {@link MenuInflater}.
  */
-public class MenuInflaterTest extends ActivityInstrumentationTestCase2<MenuInflaterStubActivity> {
+public class MenuInflaterTest extends ActivityInstrumentationTestCase2<MenuInflaterCtsActivity> {
     private MenuInflater mMenuInflater;
 
     private Activity mActivity;
 
     public MenuInflaterTest() {
-        super("com.android.cts.stub", MenuInflaterStubActivity.class);
+        super("com.android.cts.view", MenuInflaterCtsActivity.class);
     }
 
     @Override
@@ -59,7 +59,7 @@
         Menu menu = new MenuBuilder(mActivity);
         assertEquals(0, menu.size());
 
-        mMenuInflater.inflate(com.android.cts.stub.R.menu.browser, menu);
+        mMenuInflater.inflate(com.android.cts.view.R.menu.browser, menu);
         assertNotNull(menu);
         assertEquals(1, menu.size());
 
@@ -70,7 +70,7 @@
         }
 
         try {
-            mMenuInflater.inflate(com.android.cts.stub.R.menu.browser, null);
+            mMenuInflater.inflate(com.android.cts.view.R.menu.browser, null);
             fail("should throw NullPointerException");
         } catch (NullPointerException e) {
         }
@@ -94,7 +94,7 @@
 
         // the titles and icons
         menu = new MenuBuilder(mActivity);
-        mMenuInflater.inflate(com.android.cts.stub.R.menu.title_icon, menu);
+        mMenuInflater.inflate(com.android.cts.view.R.menu.title_icon, menu);
 
         assertEquals("Start", menu.findItem(R.id.start).getTitle());
         assertIconUsingDrawableRes((BitmapDrawable) menu.findItem(R.id.start).getIcon(),
@@ -110,7 +110,7 @@
 
         // the orders and categories
         menu = new MenuBuilder(mActivity);
-        mMenuInflater.inflate(com.android.cts.stub.R.menu.category_order, menu);
+        mMenuInflater.inflate(com.android.cts.view.R.menu.category_order, menu);
         // default category
         assertEquals(R.id.most_used_items, menu.findItem(R.id.first_most_item).getGroupId());
         assertEquals(1, menu.findItem(R.id.first_most_item).getOrder());
@@ -134,7 +134,7 @@
 
         // the checkables
         menu = new MenuBuilder(mActivity);
-        mMenuInflater.inflate(com.android.cts.stub.R.menu.checkable, menu);
+        mMenuInflater.inflate(com.android.cts.view.R.menu.checkable, menu);
         // noncheckables
         assertEquals(R.id.noncheckable_group,
                 menu.findItem(R.id.noncheckable_item_1).getGroupId());
diff --git a/tests/tests/view/src/android/view/cts/MockActivity.java b/tests/tests/view/src/android/view/cts/MockActivity.java
new file mode 100644
index 0000000..6e12901
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/MockActivity.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2008 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.view.cts;
+
+import android.app.Activity;
+
+public class MockActivity extends Activity {
+
+}
diff --git a/tests/tests/view/src/android/view/cts/MockApplication.java b/tests/tests/view/src/android/view/cts/MockApplication.java
new file mode 100644
index 0000000..e99e6b8
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/MockApplication.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2008 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.view.cts;
+
+import android.app.Application;
+import android.content.res.Configuration;
+
+
+public class MockApplication extends Application {
+
+    public boolean isOnCreateCalled;
+    public boolean isConstructorCalled;
+    public boolean isOnConfigurationChangedCalled;
+    public boolean isOnLowMemoryCalled;
+
+    public MockApplication() {
+        super();
+        isConstructorCalled = true;
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        isOnCreateCalled = true;
+    }
+
+    @Override
+    public void onTerminate() {
+        super.onTerminate();
+        // The documentation states that one cannot rely on this method being called. No need to
+        // test it here.
+    }
+
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        isOnConfigurationChangedCalled = true;
+    }
+
+    @Override
+    public void onLowMemory() {
+        super.onLowMemory();
+        isOnLowMemoryCalled = true;
+    }
+}
diff --git a/tests/tests/view/src/android/view/cts/MockLinearLayout.java b/tests/tests/view/src/android/view/cts/MockLinearLayout.java
new file mode 100644
index 0000000..9fe425b
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/MockLinearLayout.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2008 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.view.cts;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.ViewParent;
+import android.widget.LinearLayout;
+
+public class MockLinearLayout extends LinearLayout {
+
+    public boolean mIsInvalidateChildInParentCalled;
+
+    public MockLinearLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public MockLinearLayout(Context context) {
+        super(context);
+    }
+
+    @Override
+    public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
+        mIsInvalidateChildInParentCalled = true;
+        return super.invalidateChildInParent(location, dirty);
+    }
+
+}
+
diff --git a/tests/tests/view/src/android/view/cts/MockTextView.java b/tests/tests/view/src/android/view/cts/MockTextView.java
new file mode 100644
index 0000000..dc9420d
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/MockTextView.java
@@ -0,0 +1,224 @@
+/*
+ * 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.
+ */
+
+package android.view.cts;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.text.method.MovementMethod;
+import android.util.AttributeSet;
+import android.view.ContextMenu;
+import android.view.KeyEvent;
+import android.widget.TextView;
+
+public class MockTextView extends TextView {
+    private boolean mHasCalledOnCreateContextMenu;
+    private boolean mHasCalledOnFocusChanged;
+    private boolean mHasCalledOnMeasure;
+    private boolean mHasCalledOnTextChanged;
+    private boolean mHasCalledDrawableStateChanged;
+    private boolean mHasCalledOnWindowFocusChanged;
+    private boolean mHasCalledOnPrivateIMECommand;
+    private boolean mHasCalledOnKeyMultiple;
+
+    public MockTextView(Context context) {
+        super(context);
+    }
+
+    public MockTextView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public MockTextView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    public boolean hasCalledOnWindowFocusChanged() {
+        return mHasCalledOnWindowFocusChanged;
+    }
+
+    public boolean hasCalledOnCreateContextMenu() {
+        return mHasCalledOnCreateContextMenu;
+    }
+
+    public boolean hasCalledDrawableStateChanged() {
+        return mHasCalledDrawableStateChanged;
+    }
+
+    public boolean hasCalledOnFocusChanged() {
+        return mHasCalledOnFocusChanged;
+    }
+
+    public boolean hasCalledOnMeasure() {
+        return mHasCalledOnMeasure;
+    }
+
+    public boolean hasCalledOnTextChanged() {
+        return mHasCalledOnTextChanged;
+    }
+
+    public boolean hasCalledOnPrivateIMECommand() {
+        return mHasCalledOnPrivateIMECommand;
+    }
+
+    public boolean hasCalledOnKeyMultiple(){
+        return mHasCalledOnKeyMultiple;
+    }
+
+    public void reset() {
+        mHasCalledOnWindowFocusChanged = false;
+        mHasCalledDrawableStateChanged = false;
+        mHasCalledOnCreateContextMenu = false;
+        mHasCalledOnFocusChanged = false;
+        mHasCalledOnMeasure = false;
+        mHasCalledOnTextChanged = false;
+        mHasCalledOnPrivateIMECommand = false;
+        mHasCalledOnKeyMultiple = false;
+    }
+
+    public int computeHorizontalScrollRange() {
+        return super.computeHorizontalScrollRange();
+    }
+
+    public int computeVerticalScrollRange() {
+        return super.computeVerticalScrollRange();
+    }
+
+    @Override
+    protected void drawableStateChanged() {
+        super.drawableStateChanged();
+        mHasCalledDrawableStateChanged = true;
+    }
+
+    public boolean getDefaultEditable() {
+        return super.getDefaultEditable();
+    }
+
+    public MovementMethod getDefaultMovementMethod() {
+        return super.getDefaultMovementMethod();
+    }
+
+    @Override
+    protected void onCreateContextMenu(ContextMenu menu) {
+        super.onCreateContextMenu(menu);
+        mHasCalledOnCreateContextMenu = true;
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+    }
+
+    @Override
+    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
+        super.onFocusChanged(focused, direction, previouslyFocusedRect);
+        mHasCalledOnFocusChanged = true;
+    }
+
+    @Override
+    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
+        mHasCalledOnKeyMultiple = true;
+        return super.onKeyMultiple(keyCode, repeatCount, event);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        mHasCalledOnMeasure = true;
+    }
+
+    @Override
+    protected void onTextChanged(CharSequence text, int start, int before, int after) {
+        super.onTextChanged(text, start, before, after);
+        mHasCalledOnTextChanged = true;
+    }
+
+    public boolean setFrame(int l, int t, int r, int b) {
+        return super.setFrame(l, t, r, b);
+    }
+
+    @Override
+    public void onWindowFocusChanged(boolean hasWindowFocus) {
+        super.onWindowFocusChanged(hasWindowFocus);
+        mHasCalledOnWindowFocusChanged = true;
+    }
+
+    public float getLeftFadingEdgeStrength() {
+        return super.getLeftFadingEdgeStrength();
+    }
+
+    public float getRightFadingEdgeStrength() {
+        return super.getRightFadingEdgeStrength();
+    }
+
+    @Override
+    public boolean onPrivateIMECommand(String action, Bundle data) {
+        mHasCalledOnPrivateIMECommand = true;
+        return super.onPrivateIMECommand(action, data);
+    }
+
+    public int getFrameLeft() {
+        return mLeft;
+    }
+
+    public int getFrameTop() {
+        return mTop;
+    }
+
+    public int getFrameRight() {
+        return mRight;
+    }
+
+    public int getFrameBottom() {
+        return mBottom;
+    }
+
+    public int getBottomPaddingOffset() {
+        return super.getBottomPaddingOffset();
+    }
+
+    public int getLeftPaddingOffset() {
+        return super.getLeftPaddingOffset();
+    }
+
+    public int getRightPaddingOffset() {
+        return super.getRightPaddingOffset();
+    }
+
+    public int getTopPaddingOffset() {
+        return super.getTopPaddingOffset();
+    }
+
+    public boolean isPaddingOffsetRequired() {
+        return super.isPaddingOffsetRequired();
+    }
+
+    public boolean verifyDrawable(Drawable who) {
+        return super.verifyDrawable(who);
+    }
+
+    public int computeVerticalScrollExtent() {
+        return super.computeVerticalScrollExtent();
+    }
+}
diff --git a/tests/src/android/view/cts/MockView.java b/tests/tests/view/src/android/view/cts/MockView.java
similarity index 100%
rename from tests/src/android/view/cts/MockView.java
rename to tests/tests/view/src/android/view/cts/MockView.java
diff --git a/tests/src/android/view/cts/MockViewStub.java b/tests/tests/view/src/android/view/cts/MockViewStub.java
similarity index 100%
rename from tests/src/android/view/cts/MockViewStub.java
rename to tests/tests/view/src/android/view/cts/MockViewStub.java
diff --git a/tests/tests/view/src/android/view/cts/MyScrollView.java b/tests/tests/view/src/android/view/cts/MyScrollView.java
new file mode 100644
index 0000000..3701ab0
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/MyScrollView.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2009 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.view.cts;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ScrollView;
+
+public class MyScrollView extends ScrollView {
+    public MyScrollView(Context context) {
+        super(context);
+    }
+
+    public MyScrollView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public MyScrollView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    @Override
+    protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) {
+        return super.computeScrollDeltaToGetChildRectOnScreen(rect);
+    }
+
+    @Override
+    protected int computeVerticalScrollRange() {
+        return super.computeVerticalScrollRange();
+    }
+
+    @Override
+    protected float getBottomFadingEdgeStrength() {
+        return super.getBottomFadingEdgeStrength();
+    }
+
+    @Override
+    protected float getTopFadingEdgeStrength() {
+        return super.getTopFadingEdgeStrength();
+    }
+
+    @Override
+    protected void measureChild(View c, int pWidthMeasureSpec, int pHeightMeasureSpec) {
+        super.measureChild(c, pWidthMeasureSpec, pHeightMeasureSpec);
+    }
+
+    @Override
+    protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed,
+            int parentHeightMeasureSpec, int heightUsed) {
+        super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed,
+                parentHeightMeasureSpec, heightUsed);
+    }
+}
diff --git a/tests/tests/view/src/android/view/cts/SurfaceViewCtsActivity.java b/tests/tests/view/src/android/view/cts/SurfaceViewCtsActivity.java
new file mode 100644
index 0000000..a6bc5fb
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/SurfaceViewCtsActivity.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2009 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.view.cts;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PorterDuff.Mode;
+import android.os.Bundle;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+public class SurfaceViewCtsActivity extends Activity {
+    private MockSurfaceView mSurfaceView;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // New a MockSurfaceView
+        mSurfaceView = new MockSurfaceView(this);
+        setContentView(mSurfaceView);
+    }
+
+    public MockSurfaceView getSurfaceView() {
+        return mSurfaceView;
+    }
+
+    public class MockSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
+        private static final int FIX_WIDTH = 240;
+        private static final int FIX_HEIGHT = 240;
+        private static final int BITMAP_WIDTH = 100;
+        private static final int BITMAP_HEIGHT = 100;
+        private static final int RECT_LEFT = 20;
+        private static final int RECT_TOP = 100;
+        private static final int RECT_RIGHT = 200;
+        private static final int RECT_BOTTOM = 200;
+
+        private SurfaceHolder mHolder;
+        private MockCanvas mCanvas;
+
+        private boolean mIsDraw;
+        private boolean mIsAttachedToWindow;
+        private boolean mIsDetachedFromWindow;
+        private boolean mIsOnMeasure;
+        private boolean mIsOnScrollChanged;
+        private boolean mIsOnSizeChanged;
+        private boolean mIsOnWindowVisibilityChanged;
+        private boolean mIsDispatchDraw;
+        private boolean mIsSurfaceChanged;
+
+        private int mWidthInOnMeasure;
+        private int mHeightInOnMeasure;
+        private int mOldLOnScrollChanged;
+        private int mOldTOnScrollChanged;
+        private int mOldWOnSizeChanged;
+        private int mOldHOnSizeChanged;
+        private int mVisibilityOnWindowVisibilityChanged;
+
+        public MockSurfaceView(Context context) {
+            super(context);
+            mHolder = getHolder();
+            mHolder.addCallback(this);
+            mHolder.setFixedSize(FIX_WIDTH, FIX_HEIGHT);
+        }
+
+        @Override
+        public void onWindowVisibilityChanged(int visibility) {
+            super.onWindowVisibilityChanged(visibility);
+            mVisibilityOnWindowVisibilityChanged = visibility;
+            mIsOnWindowVisibilityChanged = true;
+        }
+
+        public int getVInOnWindowVisibilityChanged() {
+            return mVisibilityOnWindowVisibilityChanged;
+        }
+
+        @Override
+        public void draw(Canvas canvas) {
+            super.draw(canvas);
+            mIsDraw = true;
+        }
+
+        @Override
+        public void onAttachedToWindow() {
+            super.onAttachedToWindow();
+            mIsAttachedToWindow = true;
+        }
+
+        @Override
+        public void onDetachedFromWindow() {
+            super.onDetachedFromWindow();
+            mIsDetachedFromWindow = true;
+        }
+
+        @Override
+        public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+            mWidthInOnMeasure = getDefaultSize(FIX_WIDTH, widthMeasureSpec);
+            mHeightInOnMeasure = getDefaultSize(FIX_HEIGHT, heightMeasureSpec);
+            mIsOnMeasure = true;
+        }
+
+        public int getWidthInOnMeasure() {
+            return mWidthInOnMeasure;
+        }
+
+        public int getHeightInOnMeasure() {
+            return mHeightInOnMeasure;
+        }
+
+        @Override
+        public void onScrollChanged(int l, int t, int oldl, int oldt) {
+            super.onScrollChanged(l, t, oldl, oldt);
+
+            mOldLOnScrollChanged = oldl;
+            mOldTOnScrollChanged = oldt;
+            mIsOnScrollChanged = true;
+        }
+
+        public int getOldHorizontal() {
+            return mOldLOnScrollChanged;
+        }
+
+        public int getOldVertical() {
+            return mOldTOnScrollChanged;
+        }
+
+        @Override
+        public void onSizeChanged(int w, int h, int oldw, int oldh) {
+            super.onSizeChanged(w, h, oldw, oldh);
+
+            mOldWOnSizeChanged = oldw;
+            mOldHOnSizeChanged = oldh;
+            mIsOnSizeChanged = true;
+        }
+
+        public int getOldWidth() {
+            return mOldWOnSizeChanged;
+        }
+
+        public int getOldHeight() {
+            return mOldHOnSizeChanged;
+        }
+
+        @Override
+        protected void dispatchDraw(Canvas canvas) {
+            super.dispatchDraw(canvas);
+            mIsDispatchDraw = true;
+        }
+
+        public void setFormat(int format) {
+            getHolder().setFormat(format);
+        }
+
+        public void surfaceCreated(SurfaceHolder holder) {
+            // Use mock canvas listening to the drawColor() calling.
+            mCanvas = new MockCanvas(Bitmap.createBitmap( BITMAP_WIDTH,
+                                                          BITMAP_HEIGHT,
+                                                          Bitmap.Config.ARGB_8888));
+            draw(mCanvas);
+
+            // Lock the surface, this returns a Canvas that can be used to render into.
+            Canvas canvas = mHolder.lockCanvas();
+            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
+            paint.setColor(Color.BLUE);
+            canvas.drawRect(RECT_LEFT, RECT_TOP, RECT_RIGHT, RECT_BOTTOM, paint);
+
+            // And finally unlock and post the surface.
+            mHolder.unlockCanvasAndPost(canvas);
+        }
+
+        public void surfaceDestroyed(SurfaceHolder holder) {
+        }
+
+        public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+            mIsSurfaceChanged = true;
+        }
+
+        public boolean isDraw() {
+            return mIsDraw;
+        }
+
+        public boolean isOnAttachedToWindow() {
+            return mIsAttachedToWindow;
+        }
+
+        public boolean isDetachedFromWindow() {
+            return mIsDetachedFromWindow;
+        }
+
+        public boolean isOnMeasureCalled() {
+            return mIsOnMeasure;
+        }
+
+        public boolean isOnScrollChanged() {
+            return mIsOnScrollChanged;
+        }
+
+        public boolean isOnSizeChangedCalled() {
+            return mIsOnSizeChanged;
+        }
+
+        public void resetOnSizeChangedFlag(boolean b) {
+            mIsOnSizeChanged = b;
+        }
+
+        public boolean isOnWindowVisibilityChanged() {
+            return mIsOnWindowVisibilityChanged;
+        }
+
+        public boolean isDispatchDraw() {
+            return mIsDispatchDraw;
+        }
+
+        public boolean isDrawColor() {
+            if (mCanvas != null) {
+                return mCanvas.isDrawColor();
+            } else {
+                return false;
+            }
+        }
+
+        public boolean isSurfaceChanged() {
+            return mIsSurfaceChanged;
+        }
+
+        public void setDrawColor(boolean isDrawColor) {
+            if (mCanvas != null) {
+                mCanvas.setDrawColor(isDrawColor);
+            }
+        }
+    }
+
+    class MockCanvas extends Canvas {
+        private boolean mIsDrawColor;
+
+        public MockCanvas(Bitmap bitmap) {
+            super(bitmap);
+        }
+
+        @Override
+        public void drawColor(int color, Mode mode) {
+            super.drawColor(color, mode);
+            mIsDrawColor = true;
+        }
+
+        public boolean isDrawColor() {
+            return mIsDrawColor;
+        }
+
+        public void setDrawColor(boolean isDrawColor) {
+            this.mIsDrawColor = isDrawColor;
+        }
+    }
+}
diff --git a/tests/tests/view/src/android/view/cts/SurfaceViewTest.java b/tests/tests/view/src/android/view/cts/SurfaceViewTest.java
index 65f05b8..a84653d 100644
--- a/tests/tests/view/src/android/view/cts/SurfaceViewTest.java
+++ b/tests/tests/view/src/android/view/cts/SurfaceViewTest.java
@@ -28,16 +28,16 @@
 import android.view.KeyEvent;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
-import android.view.cts.SurfaceViewStubActivity.MockSurfaceView;
+import android.view.cts.SurfaceViewCtsActivity.MockSurfaceView;
 
-public class SurfaceViewTest extends ActivityInstrumentationTestCase2<SurfaceViewStubActivity> {
+public class SurfaceViewTest extends ActivityInstrumentationTestCase2<SurfaceViewCtsActivity> {
 
     private Context mContext;
     private Instrumentation mInstrumentation;
     private MockSurfaceView mMockSurfaceView;
 
     public SurfaceViewTest() {
-        super("com.android.cts.stub", SurfaceViewStubActivity.class);
+        super("com.android.cts.view", SurfaceViewCtsActivity.class);
     }
 
     @Override
@@ -45,7 +45,7 @@
         super.setUp();
         mInstrumentation = getInstrumentation();
         mContext = mInstrumentation.getContext();
-        final SurfaceViewStubActivity activity = getActivity();
+        final SurfaceViewCtsActivity activity = getActivity();
         new PollingCheck() {
             @Override
                 protected boolean check() {
@@ -55,6 +55,7 @@
         mMockSurfaceView = activity.getSurfaceView();
     }
 
+    @UiThreadTest
     public void testConstructor() {
         new SurfaceView(mContext);
         new SurfaceView(mContext, null);
diff --git a/tests/src/android/view/cts/TestButton.java b/tests/tests/view/src/android/view/cts/TestButton.java
similarity index 100%
rename from tests/src/android/view/cts/TestButton.java
rename to tests/tests/view/src/android/view/cts/TestButton.java
diff --git a/tests/tests/view/src/android/view/cts/TouchDelegateTest.java b/tests/tests/view/src/android/view/cts/TouchDelegateTest.java
index 4e582a1..34d96bc 100644
--- a/tests/tests/view/src/android/view/cts/TouchDelegateTest.java
+++ b/tests/tests/view/src/android/view/cts/TouchDelegateTest.java
@@ -19,7 +19,6 @@
 
 import android.app.Activity;
 import android.app.Instrumentation;
-import android.app.cts.MockActivity;
 import android.graphics.Rect;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
@@ -45,7 +44,7 @@
     private Exception mException;
 
     public TouchDelegateTest() {
-        super("com.android.cts.stub", MockActivity.class);
+        super("com.android.cts.view", MockActivity.class);
     }
 
     @Override
diff --git a/tests/tests/view/src/android/view/cts/UsingViewsCtsActivity.java b/tests/tests/view/src/android/view/cts/UsingViewsCtsActivity.java
new file mode 100644
index 0000000..a5ccbcd
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/UsingViewsCtsActivity.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2009 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.view.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import com.android.cts.view.R;
+
+/**
+ * A simple activity to test "Using Views"
+ */
+public class UsingViewsCtsActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.using_views_layout);
+    }
+}
diff --git a/tests/tests/view/src/android/view/cts/ViewGroupCtsActivity.java b/tests/tests/view/src/android/view/cts/ViewGroupCtsActivity.java
new file mode 100644
index 0000000..880a450
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/ViewGroupCtsActivity.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2008 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.view.cts;
+
+import android.app.Activity;
+import android.cts.util.CTSResult;
+import android.os.Bundle;
+import android.os.Handler;
+import android.widget.TextView;
+
+public class ViewGroupCtsActivity extends Activity {
+
+    public static final String ACTION_INVALIDATE_CHILD = "invalidateChild";
+
+    private final Handler mHandler = new Handler();
+    private static CTSResult sResult;
+    public static void setResult(CTSResult result) {
+        sResult = result;
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(com.android.cts.view.R.layout.viewgrouptest_stub);
+        TextView textView = (TextView)findViewById(com.android.cts.view.R.id.viewgrouptest_stub);
+        textView.setText("test");
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+
+        String action = getIntent().getAction();
+        if (action.equals(ACTION_INVALIDATE_CHILD)) {
+            mHandler.postDelayed(new Runnable() {
+                public void run() {
+                    MockLinearLayout mll =
+                        (MockLinearLayout) findViewById(com.android.cts.view.R.id.
+                                                                        mocklinearlayout);
+                    if (!mll.mIsInvalidateChildInParentCalled) {
+                        fail();
+                        return;
+                    }
+                    sResult.setResult(CTSResult.RESULT_OK);
+                    finish();
+                }
+            }, 2000);
+        }
+    }
+
+    private void fail() {
+        sResult.setResult(CTSResult.RESULT_FAIL);
+        finish();
+    }
+}
+
diff --git a/tests/tests/view/src/android/view/cts/ViewGroupTest.java b/tests/tests/view/src/android/view/cts/ViewGroupTest.java
index b46c031..f1064a7 100644
--- a/tests/tests/view/src/android/view/cts/ViewGroupTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewGroupTest.java
@@ -19,9 +19,9 @@
 import com.android.internal.util.XmlUtils;
 
 
-import android.app.cts.CTSResult;
 import android.content.Context;
 import android.content.Intent;
+import android.cts.util.CTSResult;
 import android.content.res.XmlResourceParser;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
@@ -54,7 +54,6 @@
 import android.view.animation.Transformation;
 import android.view.animation.Animation.AnimationListener;
 import android.widget.TextView;
-import android.widget.cts.ViewGroupStubActivity;
 
 import java.util.ArrayList;
 
@@ -723,7 +722,7 @@
     public void testGenerateLayoutParamsWithParaAttributeSet() throws Exception{
         MockViewGroup vg = new MockViewGroup(mContext);
         XmlResourceParser set = mContext.getResources().getLayout(
-                com.android.cts.stub.R.layout.abslistview_layout);
+                com.android.cts.view.R.layout.abslistview_layout);
         XmlUtils.beginDocument(set, "ViewGroup_Layout");
         LayoutParams lp = vg.generateLayoutParams(set);
         assertNotNull(lp);
@@ -862,15 +861,15 @@
     private void setupActivity(String action) {
 
         Intent intent = new Intent(getInstrumentation().getTargetContext(),
-                ViewGroupStubActivity.class);
+                ViewGroupCtsActivity.class);
         intent.setAction(action);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         getInstrumentation().getTargetContext().startActivity(intent);
     }
 
     public void testInvalidateChild() {
-        ViewGroupStubActivity.setResult(this);
-        setupActivity(ViewGroupStubActivity.ACTION_INVALIDATE_CHILD);
+        ViewGroupCtsActivity.setResult(this);
+        setupActivity(ViewGroupCtsActivity.ACTION_INVALIDATE_CHILD);
         waitForResult();
         assertEquals(CTSResult.RESULT_OK, mResultCode);
     }
diff --git a/tests/tests/view/src/android/view/cts/ViewGroup_LayoutParamsTest.java b/tests/tests/view/src/android/view/cts/ViewGroup_LayoutParamsTest.java
index 37bac7c..ded715a 100644
--- a/tests/tests/view/src/android/view/cts/ViewGroup_LayoutParamsTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewGroup_LayoutParamsTest.java
@@ -28,7 +28,7 @@
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 import com.android.internal.util.XmlUtils;
 
 
diff --git a/tests/tests/view/src/android/view/cts/ViewGroup_MarginLayoutParamsTest.java b/tests/tests/view/src/android/view/cts/ViewGroup_MarginLayoutParamsTest.java
index fe364bc..d3fed0d 100644
--- a/tests/tests/view/src/android/view/cts/ViewGroup_MarginLayoutParamsTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewGroup_MarginLayoutParamsTest.java
@@ -25,7 +25,7 @@
 
 import android.widget.LinearLayout;
 import com.android.internal.util.XmlUtils;
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 
 
 public class ViewGroup_MarginLayoutParamsTest extends InstrumentationTestCase {
diff --git a/tests/tests/view/src/android/view/cts/ViewLayoutPositionTestCtsActivity.java b/tests/tests/view/src/android/view/cts/ViewLayoutPositionTestCtsActivity.java
new file mode 100644
index 0000000..69dc70f
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/ViewLayoutPositionTestCtsActivity.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2008 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.view.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import com.android.cts.view.R;
+
+public class ViewLayoutPositionTestCtsActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.view_layout_position);
+    }
+}
diff --git a/tests/tests/view/src/android/view/cts/ViewStubCtsActivity.java b/tests/tests/view/src/android/view/cts/ViewStubCtsActivity.java
new file mode 100644
index 0000000..d2f2a4f
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/ViewStubCtsActivity.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2008 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.view.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import com.android.cts.view.R;
+
+public class ViewStubCtsActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.viewstub_layout);
+    }
+}
diff --git a/tests/tests/view/src/android/view/cts/ViewStubTest.java b/tests/tests/view/src/android/view/cts/ViewStubTest.java
index 07834d2..53e251a 100644
--- a/tests/tests/view/src/android/view/cts/ViewStubTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewStubTest.java
@@ -16,7 +16,7 @@
 
 package android.view.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 
 import dalvik.annotation.KnownFailure;
 
@@ -37,12 +37,12 @@
 /**
  * Test {@link ViewStub}.
  */
-public class ViewStubTest extends ActivityInstrumentationTestCase<ViewStubStubActivity> {
+public class ViewStubTest extends ActivityInstrumentationTestCase<ViewStubCtsActivity> {
     private Context mContext;
     private Activity mActivity;
 
     public ViewStubTest() {
-        super("com.android.cts.stub", ViewStubStubActivity.class);
+        super("com.android.cts.view", ViewStubCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/view/src/android/view/cts/ViewTest.java b/tests/tests/view/src/android/view/cts/ViewTest.java
index 95a365f..e8da40e 100644
--- a/tests/tests/view/src/android/view/cts/ViewTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewTest.java
@@ -16,11 +16,16 @@
 
 package android.view.cts;
 
-import com.android.cts.stub.R;
+import android.content.res.ColorStateList;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.PorterDuff;
+
+import com.android.cts.view.R;
 import com.android.internal.view.menu.ContextMenuBuilder;
 import com.google.android.collect.Lists;
 
-import android.app.Activity;
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
@@ -54,7 +59,6 @@
 import android.view.SoundEffectConstants;
 import android.view.TouchDelegate;
 import android.view.View;
-import android.view.MotionEvent.PointerProperties;
 import android.view.View.BaseSavedState;
 import android.view.View.OnClickListener;
 import android.view.View.OnCreateContextMenuListener;
@@ -77,7 +81,6 @@
 import android.widget.EditText;
 import android.widget.LinearLayout;
 import android.widget.ListView;
-import android.widget.cts.StubActivity;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -86,14 +89,14 @@
 /**
  * Test {@link View}.
  */
-public class ViewTest extends ActivityInstrumentationTestCase2<ViewTestStubActivity> {
+public class ViewTest extends ActivityInstrumentationTestCase2<ViewTestCtsActivity> {
     public ViewTest() {
-        super(ViewTestStubActivity.class);
+        super(ViewTestCtsActivity.class);
     }
 
     private Resources mResources;
     private MockViewParent mMockParent;
-    private ViewTestStubActivity mActivity;
+    private ViewTestCtsActivity mActivity;
 
     /** timeout delta when wait in case the system is sluggish */
     private static final long TIMEOUT_DELTA = 10000;
@@ -2470,7 +2473,7 @@
         assertFalse(view.hasCalledOnWindowFocusChanged());
         assertFalse(view.hasCalledDispatchWindowFocusChanged());
 
-        StubActivity activity = launchActivity("com.android.cts.stub", StubActivity.class, null);
+        CtsActivity activity = launchActivity("com.android.cts.view", CtsActivity.class, null);
 
         // Wait until the window lost focus.
         new PollingCheck(TIMEOUT_DELTA) {
@@ -3338,6 +3341,63 @@
         touchListener.reset();
     }
 
+    public void testBackgroundTint() {
+        View inflatedView = mActivity.findViewById(R.id.background_tint);
+
+        assertEquals("Background tint inflated correctly",
+                Color.WHITE, inflatedView.getBackgroundTintList().getDefaultColor());
+        assertEquals("Background tint mode inflated correctly",
+                PorterDuff.Mode.SRC_OVER, inflatedView.getBackgroundTintMode());
+
+        MockDrawable bg = new MockDrawable();
+        View view = new View(mActivity);
+
+        view.setBackground(bg);
+        assertFalse("No background tint applied by default", bg.hasCalledSetTint());
+
+        view.setBackgroundTintList(ColorStateList.valueOf(Color.WHITE));
+        assertTrue("Background tint applied when setBackgroundTints() called after setBackground()",
+                bg.hasCalledSetTint());
+
+        bg.reset();
+        view.setBackground(null);
+        view.setBackground(bg);
+        assertTrue("Background tint applied when setBackgroundTints() called before setBackground()",
+                bg.hasCalledSetTint());
+    }
+
+    private static class MockDrawable extends Drawable {
+        private boolean mCalledSetTint = false;
+
+        @Override
+        public void draw(Canvas canvas) {}
+
+        @Override
+        public void setAlpha(int alpha) {}
+
+        @Override
+        public void setColorFilter(ColorFilter cf) {}
+
+        @Override
+        public int getOpacity() {
+            return 0;
+        }
+
+        @Override
+        public void setTintList(ColorStateList tint) {
+            super.setTintList(tint);
+            mCalledSetTint = true;
+        }
+
+        public boolean hasCalledSetTint() {
+            return mCalledSetTint;
+        }
+
+        public void reset() {
+            mCalledSetTint = false;
+        }
+    }
+
     private static class MockEditText extends EditText {
         private boolean mCalledCheckInputConnectionProxy = false;
         private boolean mCalledOnCreateInputConnection = false;
@@ -3574,6 +3634,39 @@
             View source, int changeType) {
 
         }
+
+        @Override
+        public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
+            return false;
+        }
+
+        @Override
+        public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes) {
+        }
+
+        @Override
+        public void onStopNestedScroll(View target) {
+        }
+
+        @Override
+        public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
+                                   int dxUnconsumed, int dyUnconsumed) {
+        }
+
+        @Override
+        public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
+        }
+
+        @Override
+        public boolean onNestedFling(View target, float velocityX, float velocityY,
+                boolean consumed) {
+            return false;
+        }
+
+        @Override
+        public boolean onNestedPreFling(View target, float velocityX, float velocityY) {
+            return false;
+        }
     }
 
     private final class OnCreateContextMenuListenerImpl implements OnCreateContextMenuListener {
diff --git a/tests/tests/view/src/android/view/cts/ViewTestCtsActivity.java b/tests/tests/view/src/android/view/cts/ViewTestCtsActivity.java
new file mode 100644
index 0000000..01215bc
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/ViewTestCtsActivity.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2008 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.view.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.SystemClock;
+import android.util.Log;
+import com.android.cts.view.R;
+
+public class ViewTestCtsActivity extends Activity {
+    private boolean mHasWindowFocus = false;
+    private Object mHasWindowFocusLock = new Object();
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.view_layout);
+    }
+
+    @Override
+    public void onWindowFocusChanged(boolean hasFocus) {
+        super.onWindowFocusChanged(hasFocus);
+        if (!hasFocus) {
+            Log.w("ViewTestCtsActivity", "ViewTestCtsActivity lost window focus");
+        }
+        synchronized(mHasWindowFocusLock) {
+            mHasWindowFocus = hasFocus;
+            mHasWindowFocusLock.notify();
+        }
+    }
+
+    /**
+     * Blocks the calling thread until the {@link ViewTestCtsActivity} has window focus or the
+     * specified duration (in milliseconds) has passed.
+     */
+    public boolean waitForWindowFocus(long durationMillis) {
+        long elapsedMillis = SystemClock.elapsedRealtime();
+        synchronized(mHasWindowFocusLock) {
+            mHasWindowFocus = hasWindowFocus();
+            while (!mHasWindowFocus && durationMillis > 0) {
+                long newElapsedMillis = SystemClock.elapsedRealtime();
+                durationMillis -= (newElapsedMillis - elapsedMillis);
+                elapsedMillis = newElapsedMillis;
+                if (durationMillis > 0) {
+                    try {
+                        mHasWindowFocusLock.wait(durationMillis);
+                    } catch (InterruptedException e) {
+                    }
+                }
+            }
+            return mHasWindowFocus;
+        }
+    }
+}
diff --git a/tests/tests/view/src/android/view/cts/ViewTreeObserverTest.java b/tests/tests/view/src/android/view/cts/ViewTreeObserverTest.java
index cc05853..1b21dac 100644
--- a/tests/tests/view/src/android/view/cts/ViewTreeObserverTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewTreeObserverTest.java
@@ -16,11 +16,10 @@
 
 package android.view.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 
 import android.app.Activity;
 import android.app.Instrumentation;
-import android.app.cts.MockActivity;
 import android.cts.util.PollingCheck;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.TouchUtils;
diff --git a/tests/tests/view/src/android/view/cts/View_AnimationTest.java b/tests/tests/view/src/android/view/cts/View_AnimationTest.java
index bd86ed9..64bb2f7 100644
--- a/tests/tests/view/src/android/view/cts/View_AnimationTest.java
+++ b/tests/tests/view/src/android/view/cts/View_AnimationTest.java
@@ -24,13 +24,13 @@
 import android.view.animation.TranslateAnimation;
 import android.view.animation.cts.AnimationTestUtils;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 
 
 /**
  * Test {@link View}.
  */
-public class View_AnimationTest extends ActivityInstrumentationTestCase2<ViewTestStubActivity> {
+public class View_AnimationTest extends ActivityInstrumentationTestCase2<ViewTestCtsActivity> {
 
     private static final int TIME_OUT = 5000;
     private static final int DURATION = 2000;
@@ -40,7 +40,7 @@
     private TranslateAnimation mAnimation;
 
     public View_AnimationTest() {
-        super("com.android.cts.stub", ViewTestStubActivity.class);
+        super("com.android.cts.view", ViewTestCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/view/src/android/view/cts/View_FocusHandlingTest.java b/tests/tests/view/src/android/view/cts/View_FocusHandlingTest.java
index 929ac7f..97992ee 100644
--- a/tests/tests/view/src/android/view/cts/View_FocusHandlingTest.java
+++ b/tests/tests/view/src/android/view/cts/View_FocusHandlingTest.java
@@ -16,7 +16,7 @@
 
 package android.view.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 
 
 import android.app.Activity;
@@ -26,9 +26,9 @@
 import android.view.View;
 
 public class View_FocusHandlingTest
-        extends ActivityInstrumentationTestCase2<FocusHandlingStubActivity> {
+        extends ActivityInstrumentationTestCase2<FocusHandlingCtsActivity> {
     public View_FocusHandlingTest() {
-        super("com.android.cts.stub", FocusHandlingStubActivity.class);
+        super("com.android.cts.view", FocusHandlingCtsActivity.class);
     }
 
     @UiThreadTest
diff --git a/tests/tests/view/src/android/view/cts/View_IdsTest.java b/tests/tests/view/src/android/view/cts/View_IdsTest.java
index ce94771..e65ccf5 100644
--- a/tests/tests/view/src/android/view/cts/View_IdsTest.java
+++ b/tests/tests/view/src/android/view/cts/View_IdsTest.java
@@ -16,7 +16,7 @@
 
 package android.view.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 
 
 import android.app.Activity;
@@ -27,9 +27,9 @@
 import android.widget.EditText;
 import android.widget.TextView;
 
-public class View_IdsTest extends ActivityInstrumentationTestCase2<UsingViewsStubActivity> {
+public class View_IdsTest extends ActivityInstrumentationTestCase2<UsingViewsCtsActivity> {
     public View_IdsTest() {
-        super("com.android.cts.stub", UsingViewsStubActivity.class);
+        super("com.android.cts.view", UsingViewsCtsActivity.class);
     }
 
     @UiThreadTest
diff --git a/tests/tests/view/src/android/view/cts/View_LayoutPositionTest.java b/tests/tests/view/src/android/view/cts/View_LayoutPositionTest.java
index db21be1..3938607 100644
--- a/tests/tests/view/src/android/view/cts/View_LayoutPositionTest.java
+++ b/tests/tests/view/src/android/view/cts/View_LayoutPositionTest.java
@@ -16,7 +16,7 @@
 
 package android.view.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 
 
 import android.app.Activity;
@@ -31,12 +31,12 @@
  * This part contains size, padding, margin, layout and drawing
  */
 public class View_LayoutPositionTest
-        extends ActivityInstrumentationTestCase2<ViewLayoutPositionTestStubActivity> {
+        extends ActivityInstrumentationTestCase2<ViewLayoutPositionTestCtsActivity> {
 
     private Activity mActivity;
 
     public View_LayoutPositionTest() {
-        super("com.android.cts.stub", ViewLayoutPositionTestStubActivity.class);
+        super("com.android.cts.view", ViewLayoutPositionTestCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/view/src/android/view/cts/View_UsingViewsTest.java b/tests/tests/view/src/android/view/cts/View_UsingViewsTest.java
index 74f3c13..f6d067d 100644
--- a/tests/tests/view/src/android/view/cts/View_UsingViewsTest.java
+++ b/tests/tests/view/src/android/view/cts/View_UsingViewsTest.java
@@ -16,7 +16,7 @@
 
 package android.view.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 
 
 import android.app.Activity;
@@ -37,7 +37,7 @@
 import android.widget.TextView;
 
 
-public class View_UsingViewsTest extends ActivityInstrumentationTestCase2<UsingViewsStubActivity> {
+public class View_UsingViewsTest extends ActivityInstrumentationTestCase2<UsingViewsCtsActivity> {
     /**
      * country of Argentina
      */
@@ -78,7 +78,7 @@
     private TextView mWarningTextView;
 
     public View_UsingViewsTest() {
-        super("com.android.cts.stub", UsingViewsStubActivity.class);
+        super("com.android.cts.view", UsingViewsCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/view/src/android/view/cts/WindowCtsActivity.java b/tests/tests/view/src/android/view/cts/WindowCtsActivity.java
new file mode 100644
index 0000000..8af808c
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/WindowCtsActivity.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2008 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.view.cts;
+
+import com.android.cts.view.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.Window;
+
+public class WindowCtsActivity extends Activity {
+
+    private static boolean mIsOnCreateOptionsMenuCalled;
+    private static boolean mIsOnOptionsMenuClosedCalled;
+    private static boolean mIsOnKeyDownCalled;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        getWindow().requestFeature(Window.FEATURE_LEFT_ICON);
+        setContentView(R.layout.windowstub_layout);
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        menu.add(Menu.NONE, Menu.NONE, Menu.NONE, "Quit").setShortcut('1', 'q');
+        menu.add(Menu.NONE, Menu.NONE, Menu.NONE, "Action").setShortcut('2', 'a');
+        mIsOnCreateOptionsMenuCalled = true;
+        return super.onCreateOptionsMenu(menu);
+    }
+
+    @Override
+    public void onOptionsMenuClosed(Menu menu) {
+        super.onOptionsMenuClosed(menu);
+        mIsOnOptionsMenuClosedCalled = true;
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        mIsOnKeyDownCalled = true;
+        return super.onKeyDown(keyCode, event);
+    }
+
+    public boolean isOnCreateOptionsMenuCalled() {
+        return mIsOnCreateOptionsMenuCalled;
+    }
+
+    public boolean isOnOptionsMenuClosedCalled() {
+        return mIsOnOptionsMenuClosedCalled;
+    }
+
+    public boolean isOnKeyDownCalled() {
+        return mIsOnKeyDownCalled;
+    }
+
+    public void setFlagFalse() {
+        mIsOnCreateOptionsMenuCalled = false;
+        mIsOnOptionsMenuClosedCalled = false;
+    }
+}
diff --git a/tests/tests/view/src/android/view/cts/WindowTest.java b/tests/tests/view/src/android/view/cts/WindowTest.java
index fb670a9..ead4d5b 100644
--- a/tests/tests/view/src/android/view/cts/WindowTest.java
+++ b/tests/tests/view/src/android/view/cts/WindowTest.java
@@ -16,7 +16,7 @@
 
 package android.view.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 
 import android.app.Instrumentation;
 import android.app.Presentation;
@@ -36,6 +36,7 @@
 import android.os.Handler;
 import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.ActionMode;
@@ -62,12 +63,13 @@
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 
-public class WindowTest extends ActivityInstrumentationTestCase2<WindowStubActivity> {
+public class WindowTest extends ActivityInstrumentationTestCase2<WindowCtsActivity> {
     static final String TAG = "WindowTest";
     private Window mWindow;
     private Context mContext;
     private Instrumentation mInstrumentation;
-    private WindowStubActivity mActivity;
+    private WindowCtsActivity mActivity;
+    private SurfaceView surfaceView;
 
     private static final int VIEWGROUP_LAYOUT_HEIGHT = 100;
     private static final int VIEWGROUP_LAYOUT_WIDTH = 200;
@@ -77,7 +79,7 @@
     private VirtualDisplay mVirtualDisplay;
 
     public WindowTest() {
-        super("com.android.cts.stub", WindowStubActivity.class);
+        super("com.android.cts.view", WindowCtsActivity.class);
     }
 
     @Override
@@ -97,6 +99,7 @@
         super.tearDown();
     }
 
+    @UiThreadTest
     public void testConstructor() throws Exception {
         mWindow = new MockWindow(mContext);
         assertSame(mContext, mWindow.getContext());
@@ -652,7 +655,13 @@
      * Test setLocalFocus together with injectInputEvent.
      */
     public void testSetLocalFocus() throws Throwable {
-        final SurfaceView surfaceView = new SurfaceView(mContext);
+        runTestOnUiThread(new Runnable() {
+            public void run() {
+                surfaceView = new SurfaceView(mContext);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+
         final Semaphore waitingSemaphore = new Semaphore(0);
         surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
             @Override
@@ -676,6 +685,7 @@
                 mWindow.setContentView(surfaceView);
             }
         });
+        mInstrumentation.waitForIdleSync();
         assertTrue(waitingSemaphore.tryAcquire(5, TimeUnit.SECONDS));
         assertNotNull(mVirtualDisplay);
         assertNotNull(mPresentation);
@@ -997,6 +1007,24 @@
         @Override
         public void takeInputQueue(InputQueue.Callback callback) {
         }
+
+        @Override
+        public void setStatusBarColor(int color) {
+        }
+
+        @Override
+        public int getStatusBarColor() {
+            return 0;
+        }
+
+        @Override
+        public void setNavigationBarColor(int color) {
+        }
+
+        @Override
+        public int getNavigationBarColor() {
+            return 0;
+        }
     }
 
     private class MockWindowCallback implements Window.Callback {
diff --git a/tests/tests/view/src/android/view/inputmethod/cts/BaseInputConnectionTest.java b/tests/tests/view/src/android/view/inputmethod/cts/BaseInputConnectionTest.java
index 247578b..30edecb 100644
--- a/tests/tests/view/src/android/view/inputmethod/cts/BaseInputConnectionTest.java
+++ b/tests/tests/view/src/android/view/inputmethod/cts/BaseInputConnectionTest.java
@@ -16,7 +16,7 @@
 
 package android.view.inputmethod.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 
 
 import android.app.Instrumentation;
@@ -39,16 +39,16 @@
 import android.widget.EditText;
 
 public class BaseInputConnectionTest extends
-        ActivityInstrumentationTestCase2<InputMethodStubActivity> {
+        ActivityInstrumentationTestCase2<InputMethodCtsActivity> {
 
-    private InputMethodStubActivity mActivity;
+    private InputMethodCtsActivity mActivity;
     private Window mWindow;
     private EditText mView;
     private BaseInputConnection mConnection;
     private Instrumentation mInstrumentation;
 
     public BaseInputConnectionTest() {
-        super("com.android.cts.stub", InputMethodStubActivity.class);
+        super("com.android.cts.view", InputMethodCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/view/src/android/view/inputmethod/cts/EditorInfoTest.java b/tests/tests/view/src/android/view/inputmethod/cts/EditorInfoTest.java
index 5bc4515..1981d6f 100644
--- a/tests/tests/view/src/android/view/inputmethod/cts/EditorInfoTest.java
+++ b/tests/tests/view/src/android/view/inputmethod/cts/EditorInfoTest.java
@@ -41,7 +41,7 @@
         info.initialSelStart = 0;
         info.inputType = EditorInfo.TYPE_MASK_CLASS;
         info.label = "label";
-        info.packageName = "com.android.cts.stub";
+        info.packageName = "com.android.cts.view";
         info.privateImeOptions = "privateIme";
         Bundle b = new Bundle();
         String key = "bundleKey";
diff --git a/tests/tests/view/src/android/view/inputmethod/cts/InputConnectionWrapperTest.java b/tests/tests/view/src/android/view/inputmethod/cts/InputConnectionWrapperTest.java
index 17147cf..8913d6e 100644
--- a/tests/tests/view/src/android/view/inputmethod/cts/InputConnectionWrapperTest.java
+++ b/tests/tests/view/src/android/view/inputmethod/cts/InputConnectionWrapperTest.java
@@ -84,6 +84,8 @@
         assertTrue(inputConnection.isGetSelectedTextCalled);
         wrapper.setComposingRegion(0, 3);
         assertTrue(inputConnection.isSetComposingRegionCalled);
+        wrapper.requestCursorUpdates(InputConnection.CURSOR_UPDATE_IMMEDIATE);
+        assertTrue(inputConnection.isRequestCursorUpdatesCalled);
     }
 
     private class MockInputConnection implements InputConnection {
@@ -108,6 +110,7 @@
         public boolean isSetComposingTextCalled;
         public boolean isSetComposingRegionCalled;
         public boolean isSetSelectionCalled;
+        public boolean isRequestCursorUpdatesCalled;
 
         public boolean beginBatchEdit() {
             isBeginBatchEditCalled = true;
@@ -213,5 +216,10 @@
             isSetSelectionCalled = true;
             return false;
         }
+
+        public boolean requestCursorUpdates(int cursorUpdateMode) {
+            isRequestCursorUpdatesCalled = true;
+            return false;
+        }
     }
 }
diff --git a/tests/tests/view/src/android/view/inputmethod/cts/InputMethodCtsActivity.java b/tests/tests/view/src/android/view/inputmethod/cts/InputMethodCtsActivity.java
new file mode 100644
index 0000000..45e5ff2
--- /dev/null
+++ b/tests/tests/view/src/android/view/inputmethod/cts/InputMethodCtsActivity.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2008 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.view.inputmethod.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import com.android.cts.view.R;
+
+public class InputMethodCtsActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.inputmethod_edittext);
+    }
+}
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 12ce833..1a067b4 100644
--- a/tests/tests/view/src/android/view/inputmethod/cts/InputMethodInfoTest.java
+++ b/tests/tests/view/src/android/view/inputmethod/cts/InputMethodInfoTest.java
@@ -164,6 +164,7 @@
         mInputMethodInfo.writeToParcel(p, 0);
         p.setDataPosition(0);
         final InputMethodInfo imi = InputMethodInfo.CREATOR.createFromParcel(p);
+        p.recycle();
 
         assertEquals(mInputMethodInfo.getPackageName(), imi.getPackageName());
         assertEquals(mInputMethodInfo.getServiceName(), imi.getServiceName());
@@ -178,6 +179,7 @@
         mInputMethodSubtype.writeToParcel(p, 0);
         p.setDataPosition(0);
         final InputMethodSubtype subtype = InputMethodSubtype.CREATOR.createFromParcel(p);
+        p.recycle();
 
         assertEquals(mInputMethodSubtype.containsExtraValueKey(mSubtypeExtraValue_key),
                 subtype.containsExtraValueKey(mSubtypeExtraValue_key));
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 033deb2..b84292f 100644
--- a/tests/tests/view/src/android/view/inputmethod/cts/InputMethodManagerTest.java
+++ b/tests/tests/view/src/android/view/inputmethod/cts/InputMethodManagerTest.java
@@ -15,7 +15,7 @@
  */
 package android.view.inputmethod.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.view.R;
 
 import android.app.Instrumentation;
 import android.content.Context;
@@ -35,13 +35,13 @@
 import java.util.List;
 
 public class InputMethodManagerTest
-                  extends ActivityInstrumentationTestCase2<InputMethodStubActivity> {
+                  extends ActivityInstrumentationTestCase2<InputMethodCtsActivity> {
 
     public InputMethodManagerTest() {
-        super("com.android.cts.stub", InputMethodStubActivity.class);
+        super("com.android.cts.view", InputMethodCtsActivity.class);
     }
 
-    private InputMethodStubActivity mActivity;
+    private InputMethodCtsActivity mActivity;
     private Instrumentation mInstrumentation;
 
     @Override
diff --git a/tests/src/android/view/inputmethod/cts/InputMethodSettingsActivityStub.java b/tests/tests/view/src/android/view/inputmethod/cts/InputMethodSettingsActivityStub.java
similarity index 100%
rename from tests/src/android/view/inputmethod/cts/InputMethodSettingsActivityStub.java
rename to tests/tests/view/src/android/view/inputmethod/cts/InputMethodSettingsActivityStub.java
diff --git a/tests/tests/webkit/Android.mk b/tests/tests/webkit/Android.mk
index a307f99..c2d8c3c 100644
--- a/tests/tests/webkit/Android.mk
+++ b/tests/tests/webkit/Android.mk
@@ -23,14 +23,12 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctsdeviceutillegacy ctstestserver ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CtsWebkitTestCases
 
-LOCAL_INSTRUMENTATION_FOR := CtsTestStubs
-
 # uncomment when dalvik.annotation.Test* are removed or part of SDK
 #LOCAL_SDK_VERSION := current
 
diff --git a/tests/tests/webkit/AndroidManifest.xml b/tests/tests/webkit/AndroidManifest.xml
index f4424a8..a5bc2bb 100644
--- a/tests/tests/webkit/AndroidManifest.xml
+++ b/tests/tests/webkit/AndroidManifest.xml
@@ -21,16 +21,49 @@
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
     <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
     <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>
-    <application>
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+    <application android:maxRecents="1">
         <provider android:name="android.webkit.cts.MockContentProvider"
                   android:exported="true"
                   android:authorities="android.webkit.cts.MockContentProvider" />
         <uses-library android:name="android.test.runner" />
+
+        <activity android:name="android.webkit.cts.CookieSyncManagerCtsActivity"
+            android:label="CookieSyncManagerCtsActivity"
+            android:screenOrientation="nosensor">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.webkit.cts.WebViewCtsActivity"
+            android:label="WebViewCtsActivity"
+            android:screenOrientation="nosensor">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.webkit.cts.WebViewStartupCtsActivity"
+            android:label="WebViewStartupCtsActivity"
+            android:screenOrientation="nosensor">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="com.android.cts.stub"
-                     android:label="CTS tests of android.webkit"/>
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.webkit"
+                     android:label="CTS tests of android.webkit">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/assets/images/robot.png b/tests/tests/webkit/assets/images/robot.png
similarity index 100%
rename from tests/assets/images/robot.png
rename to tests/tests/webkit/assets/images/robot.png
Binary files differ
diff --git a/tests/assets/images/tomato.png b/tests/tests/webkit/assets/images/tomato.png
similarity index 100%
rename from tests/assets/images/tomato.png
rename to tests/tests/webkit/assets/images/tomato.png
Binary files differ
diff --git a/tests/assets/webkit/blank_tag.html b/tests/tests/webkit/assets/webkit/blank_tag.html
similarity index 100%
rename from tests/assets/webkit/blank_tag.html
rename to tests/tests/webkit/assets/webkit/blank_tag.html
diff --git a/tests/assets/webkit/embedded_image.html b/tests/tests/webkit/assets/webkit/embedded_image.html
similarity index 100%
rename from tests/assets/webkit/embedded_image.html
rename to tests/tests/webkit/assets/webkit/embedded_image.html
diff --git a/tests/assets/webkit/favicon.png b/tests/tests/webkit/assets/webkit/favicon.png
similarity index 100%
rename from tests/assets/webkit/favicon.png
rename to tests/tests/webkit/assets/webkit/favicon.png
Binary files differ
diff --git a/tests/assets/webkit/fonts.html b/tests/tests/webkit/assets/webkit/fonts.html
similarity index 100%
rename from tests/assets/webkit/fonts.html
rename to tests/tests/webkit/assets/webkit/fonts.html
diff --git a/tests/tests/webkit/assets/webkit/iframe_blank_tag.html b/tests/tests/webkit/assets/webkit/iframe_blank_tag.html
new file mode 100644
index 0000000..fbc6dc6
--- /dev/null
+++ b/tests/tests/webkit/assets/webkit/iframe_blank_tag.html
@@ -0,0 +1,22 @@
+<!-- Copyright (C) 2013 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.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+  <script type='text/javascript'> window.open('page_with_link.html'); </script>
+</head>
+</html>
+
diff --git a/tests/assets/webkit/javascript.html b/tests/tests/webkit/assets/webkit/javascript.html
similarity index 100%
rename from tests/assets/webkit/javascript.html
rename to tests/tests/webkit/assets/webkit/javascript.html
diff --git a/tests/assets/webkit/jsalert.html b/tests/tests/webkit/assets/webkit/jsalert.html
similarity index 100%
rename from tests/assets/webkit/jsalert.html
rename to tests/tests/webkit/assets/webkit/jsalert.html
diff --git a/tests/assets/webkit/jsconfirm.html b/tests/tests/webkit/assets/webkit/jsconfirm.html
similarity index 100%
rename from tests/assets/webkit/jsconfirm.html
rename to tests/tests/webkit/assets/webkit/jsconfirm.html
diff --git a/tests/assets/webkit/jsform.html b/tests/tests/webkit/assets/webkit/jsform.html
similarity index 100%
rename from tests/assets/webkit/jsform.html
rename to tests/tests/webkit/assets/webkit/jsform.html
diff --git a/tests/assets/webkit/jsprompt.html b/tests/tests/webkit/assets/webkit/jsprompt.html
similarity index 100%
rename from tests/assets/webkit/jsprompt.html
rename to tests/tests/webkit/assets/webkit/jsprompt.html
diff --git a/tests/assets/webkit/jsunload.html b/tests/tests/webkit/assets/webkit/jsunload.html
similarity index 100%
rename from tests/assets/webkit/jsunload.html
rename to tests/tests/webkit/assets/webkit/jsunload.html
diff --git a/tests/assets/webkit/jswindow.html b/tests/tests/webkit/assets/webkit/jswindow.html
similarity index 100%
rename from tests/assets/webkit/jswindow.html
rename to tests/tests/webkit/assets/webkit/jswindow.html
diff --git a/tests/assets/webkit/network_state.html b/tests/tests/webkit/assets/webkit/network_state.html
similarity index 100%
rename from tests/assets/webkit/network_state.html
rename to tests/tests/webkit/assets/webkit/network_state.html
diff --git a/tests/tests/webkit/assets/webkit/page_with_link.html b/tests/tests/webkit/assets/webkit/page_with_link.html
new file mode 100644
index 0000000..50fb78a
--- /dev/null
+++ b/tests/tests/webkit/assets/webkit/page_with_link.html
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2013 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.
+-->
+
+<html>
+  <body>
+    <a href="http://foo.com" id="link">a link</a>
+  </body>
+</html>
diff --git a/tests/assets/webkit/popup.html b/tests/tests/webkit/assets/webkit/popup.html
similarity index 100%
rename from tests/assets/webkit/popup.html
rename to tests/tests/webkit/assets/webkit/popup.html
diff --git a/tests/assets/webkit/popup_base.html b/tests/tests/webkit/assets/webkit/popup_base.html
similarity index 100%
rename from tests/assets/webkit/popup_base.html
rename to tests/tests/webkit/assets/webkit/popup_base.html
diff --git a/tests/assets/webkit/test_anchor.html b/tests/tests/webkit/assets/webkit/test_anchor.html
similarity index 100%
rename from tests/assets/webkit/test_anchor.html
rename to tests/tests/webkit/assets/webkit/test_anchor.html
diff --git a/tests/assets/webkit/test_blankPage.html b/tests/tests/webkit/assets/webkit/test_blankPage.html
similarity index 100%
rename from tests/assets/webkit/test_blankPage.html
rename to tests/tests/webkit/assets/webkit/test_blankPage.html
diff --git a/tests/assets/webkit/test_br_tag.html b/tests/tests/webkit/assets/webkit/test_br_tag.html
similarity index 100%
rename from tests/assets/webkit/test_br_tag.html
rename to tests/tests/webkit/assets/webkit/test_br_tag.html
diff --git a/tests/assets/webkit/test_databaseaccess.html b/tests/tests/webkit/assets/webkit/test_databaseaccess.html
similarity index 100%
rename from tests/assets/webkit/test_databaseaccess.html
rename to tests/tests/webkit/assets/webkit/test_databaseaccess.html
diff --git a/tests/assets/webkit/test_favicon.html b/tests/tests/webkit/assets/webkit/test_favicon.html
similarity index 100%
rename from tests/assets/webkit/test_favicon.html
rename to tests/tests/webkit/assets/webkit/test_favicon.html
diff --git a/tests/assets/webkit/test_firstPage.html b/tests/tests/webkit/assets/webkit/test_firstPage.html
similarity index 100%
rename from tests/assets/webkit/test_firstPage.html
rename to tests/tests/webkit/assets/webkit/test_firstPage.html
diff --git a/tests/assets/webkit/test_hello_world.html b/tests/tests/webkit/assets/webkit/test_hello_world.html
similarity index 100%
rename from tests/assets/webkit/test_hello_world.html
rename to tests/tests/webkit/assets/webkit/test_hello_world.html
diff --git a/tests/assets/webkit/test_iframeaccess.html b/tests/tests/webkit/assets/webkit/test_iframeaccess.html
similarity index 100%
rename from tests/assets/webkit/test_iframeaccess.html
rename to tests/tests/webkit/assets/webkit/test_iframeaccess.html
diff --git a/tests/assets/webkit/test_imageaccess.html b/tests/tests/webkit/assets/webkit/test_imageaccess.html
similarity index 100%
rename from tests/assets/webkit/test_imageaccess.html
rename to tests/tests/webkit/assets/webkit/test_imageaccess.html
diff --git a/tests/assets/webkit/test_jsInterface.html b/tests/tests/webkit/assets/webkit/test_jsInterface.html
similarity index 100%
rename from tests/assets/webkit/test_jsInterface.html
rename to tests/tests/webkit/assets/webkit/test_jsInterface.html
diff --git a/tests/assets/webkit/test_queryparam.html b/tests/tests/webkit/assets/webkit/test_queryparam.html
similarity index 100%
rename from tests/assets/webkit/test_queryparam.html
rename to tests/tests/webkit/assets/webkit/test_queryparam.html
diff --git a/tests/assets/webkit/test_secondPage.html b/tests/tests/webkit/assets/webkit/test_secondPage.html
similarity index 100%
rename from tests/assets/webkit/test_secondPage.html
rename to tests/tests/webkit/assets/webkit/test_secondPage.html
diff --git a/tests/assets/webkit/test_stop_loading.html b/tests/tests/webkit/assets/webkit/test_stop_loading.html
similarity index 100%
rename from tests/assets/webkit/test_stop_loading.html
rename to tests/tests/webkit/assets/webkit/test_stop_loading.html
diff --git a/tests/assets/webkit/test_thirdPage.html b/tests/tests/webkit/assets/webkit/test_thirdPage.html
similarity index 100%
rename from tests/assets/webkit/test_thirdPage.html
rename to tests/tests/webkit/assets/webkit/test_thirdPage.html
diff --git a/tests/assets/webkit/test_timer.html b/tests/tests/webkit/assets/webkit/test_timer.html
similarity index 100%
rename from tests/assets/webkit/test_timer.html
rename to tests/tests/webkit/assets/webkit/test_timer.html
diff --git a/tests/res/layout/webview_layout.xml b/tests/tests/webkit/res/layout/webview_layout.xml
similarity index 100%
copy from tests/res/layout/webview_layout.xml
copy to tests/tests/webkit/res/layout/webview_layout.xml
diff --git a/tests/tests/webkit/src/android/webkit/cts/CookieManagerTest.java b/tests/tests/webkit/src/android/webkit/cts/CookieManagerTest.java
index ead235e..c612886 100644
--- a/tests/tests/webkit/src/android/webkit/cts/CookieManagerTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/CookieManagerTest.java
@@ -16,38 +16,52 @@
 
 package android.webkit.cts;
 
+import android.cts.util.NullWebViewUtils;
 import android.cts.util.PollingCheck;
 import android.test.ActivityInstrumentationTestCase2;
 import android.webkit.CookieManager;
 import android.webkit.CookieSyncManager;
 import android.webkit.WebView;
+import android.webkit.ValueCallback;
 
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import java.util.Date;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 public class CookieManagerTest extends
-        ActivityInstrumentationTestCase2<CookieSyncManagerStubActivity> {
+        ActivityInstrumentationTestCase2<CookieSyncManagerCtsActivity> {
 
     private static final int TEST_TIMEOUT = 5000;
 
-    private WebViewOnUiThread mOnUiThread;
+    private WebView mWebView;
     private CookieManager mCookieManager;
+    private WebViewOnUiThread mOnUiThread;
 
     public CookieManagerTest() {
-        super("com.android.cts.stub", CookieSyncManagerStubActivity.class);
+        super("com.android.cts.webkit", CookieSyncManagerCtsActivity.class);
     }
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        WebView webview = getActivity().getWebView();
-        if (webview != null) {
-            mOnUiThread = new WebViewOnUiThread(this, webview);
+        mWebView = getActivity().getWebView();
+        if (mWebView != null) {
+            mOnUiThread = new WebViewOnUiThread(this, mWebView);
 
             mCookieManager = CookieManager.getInstance();
             assertNotNull(mCookieManager);
+
+            // We start with no cookies.
+            mCookieManager.removeAllCookie();
+            assertFalse(mCookieManager.hasCookies());
+
+            // But accepting cookies.
+            mCookieManager.setAcceptCookie(false);
+            assertFalse(mCookieManager.acceptCookie());
         }
     }
 
@@ -68,14 +82,20 @@
         }
     }
 
+    public void testFlush() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+        mCookieManager.flush();
+    }
+
     public void testAcceptCookie() throws Exception {
         if (!NullWebViewUtils.isWebViewAvailable()) {
             return;
         }
-        mCookieManager.removeAllCookie();
+
         mCookieManager.setAcceptCookie(false);
         assertFalse(mCookieManager.acceptCookie());
-        assertFalse(mCookieManager.hasCookies());
 
         CtsTestServer server = new CtsTestServer(getActivity(), false);
         String url = server.getCookieUrl("conquest.html");
@@ -119,115 +139,245 @@
         m = pat.matcher(cookie);
         assertTrue(m.matches());
         assertEquals("42", m.group(1)); // value got incremented
-
-        // clean up all cookies
-        mCookieManager.removeAllCookie();
     }
 
-    public void testCookieManager() {
+    public void testSetCookie() {
         if (!NullWebViewUtils.isWebViewAvailable()) {
             return;
         }
-        // enable cookie
-        mCookieManager.setAcceptCookie(true);
-        assertTrue(mCookieManager.acceptCookie());
-
-        // first there should be no cookie stored
-        assertFalse(mCookieManager.hasCookies());
 
         String url = "http://www.example.com";
         String cookie = "name=test";
         mCookieManager.setCookie(url, cookie);
         assertEquals(cookie, mCookieManager.getCookie(url));
+        assertTrue(mCookieManager.hasCookies());
+    }
 
-        // sync cookie from RAM to FLASH, because hasCookies() only counts FLASH cookies
-        CookieSyncManager.getInstance().sync();
+    public void testSetCookieNullCallback() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
+        final String url = "http://www.example.com";
+        final String cookie = "name=test";
+        mCookieManager.setCookie(url, cookie, null);
         new PollingCheck(TEST_TIMEOUT) {
             @Override
             protected boolean check() {
-                return mCookieManager.hasCookies();
+                String c = mCookieManager.getCookie(url);
+                return mCookieManager.getCookie(url).contains(cookie);
+            }
+        }.run();
+    }
+
+    public void testSetCookieCallback() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
+        final Semaphore s = new Semaphore(0);
+        final AtomicBoolean status = new AtomicBoolean();
+        final ValueCallback<Boolean> callback = new ValueCallback<Boolean>() {
+            @Override
+            public void onReceiveValue(Boolean success) {
+                status.set(success);
+                s.release();
+            }
+        };
+    }
+
+    public void testRemoveCookies() throws InterruptedException {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
+        final String url = "http://www.example.com";
+        final String sessionCookie = "cookie1=peter";
+        final String longCookie = "cookie2=sue";
+        final String quickCookie = "cookie3=marc";
+
+        mCookieManager.setCookie(url, sessionCookie);
+        mCookieManager.setCookie(url, makeExpiringCookie(longCookie, 600));
+        mCookieManager.setCookie(url, makeExpiringCookieMs(quickCookie, 1500));
+
+        String allCookies = mCookieManager.getCookie(url);
+        assertTrue(allCookies.contains(sessionCookie));
+        assertTrue(allCookies.contains(longCookie));
+        assertTrue(allCookies.contains(quickCookie));
+
+        mCookieManager.removeSessionCookie();
+        allCookies = mCookieManager.getCookie(url);
+        assertFalse(allCookies.contains(sessionCookie));
+        assertTrue(allCookies.contains(longCookie));
+        assertTrue(allCookies.contains(quickCookie));
+
+        Thread.sleep(2000); // wait for quick cookie to expire
+        mCookieManager.removeExpiredCookie();
+        allCookies = mCookieManager.getCookie(url);
+        assertFalse(allCookies.contains(sessionCookie));
+        assertTrue(allCookies.contains(longCookie));
+        assertFalse(allCookies.contains(quickCookie));
+
+        mCookieManager.removeAllCookie();
+        assertNull(mCookieManager.getCookie(url));
+        assertFalse(mCookieManager.hasCookies());
+    }
+
+    public void testRemoveCookiesNullCallback() throws InterruptedException {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
+        final String url = "http://www.example.com";
+        final String sessionCookie = "cookie1=peter";
+        final String longCookie = "cookie2=sue";
+        final String quickCookie = "cookie3=marc";
+
+        mCookieManager.setCookie(url, sessionCookie);
+        mCookieManager.setCookie(url, makeExpiringCookie(longCookie, 600));
+        mCookieManager.setCookie(url, makeExpiringCookieMs(quickCookie, 1500));
+
+        String allCookies = mCookieManager.getCookie(url);
+        assertTrue(allCookies.contains(sessionCookie));
+        assertTrue(allCookies.contains(longCookie));
+        assertTrue(allCookies.contains(quickCookie));
+
+        mCookieManager.removeSessionCookies(null);
+        allCookies = mCookieManager.getCookie(url);
+        new PollingCheck(TEST_TIMEOUT) {
+            @Override
+            protected boolean check() {
+                String c = mCookieManager.getCookie(url);
+                return !c.contains(sessionCookie) &&
+                        c.contains(longCookie) &&
+                        c.contains(quickCookie);
             }
         }.run();
 
-        // clean up all cookies
-        mCookieManager.removeAllCookie();
+        mCookieManager.removeAllCookies(null);
         new PollingCheck(TEST_TIMEOUT) {
             @Override
             protected boolean check() {
                 return !mCookieManager.hasCookies();
             }
         }.run();
+        assertNull(mCookieManager.getCookie(url));
     }
 
-    @SuppressWarnings("deprecation")
-    public void testRemoveCookies() throws InterruptedException {
+    public void testRemoveCookiesCallback() throws InterruptedException {
         if (!NullWebViewUtils.isWebViewAvailable()) {
             return;
         }
-        // enable cookie
-        mCookieManager.setAcceptCookie(true);
-        assertTrue(mCookieManager.acceptCookie());
-        assertFalse(mCookieManager.hasCookies());
+
+        final Semaphore s = new Semaphore(0);
+        final AtomicBoolean anyDeleted = new AtomicBoolean();
+        final ValueCallback<Boolean> callback = new ValueCallback<Boolean>() {
+            @Override
+            public void onReceiveValue(Boolean n) {
+                anyDeleted.set(n);
+                s.release();
+            }
+        };
 
         final String url = "http://www.example.com";
-        final String cookie1 = "cookie1=peter";
-        final String cookie2 = "cookie2=sue";
-        final String cookie3 = "cookie3=marc";
+        final String sessionCookie = "cookie1=peter";
+        final String normalCookie = "cookie2=sue";
 
-        mCookieManager.setCookie(url, cookie1); // session cookie
-
-        Date date = new Date();
-        date.setTime(date.getTime() + 1000 * 600);
-        String value2 = cookie2 + "; expires=" + date.toGMTString();
-        mCookieManager.setCookie(url, value2); // expires in 10min
-
-        long expiration = 3000;
-        date = new Date();
-        date.setTime(date.getTime() + expiration);
-        String value3 = cookie3 + "; expires=" + date.toGMTString();
-        mCookieManager.setCookie(url, value3); // expires in 3s
+        // We set one session cookie and one normal cookie.
+        mCookieManager.setCookie(url, sessionCookie);
+        mCookieManager.setCookie(url, makeExpiringCookie(normalCookie, 600));
 
         String allCookies = mCookieManager.getCookie(url);
-        assertTrue(allCookies.contains(cookie1));
-        assertTrue(allCookies.contains(cookie2));
-        assertTrue(allCookies.contains(cookie3));
+        assertTrue(allCookies.contains(sessionCookie));
+        assertTrue(allCookies.contains(normalCookie));
 
-        mCookieManager.removeSessionCookie();
-        new PollingCheck(TEST_TIMEOUT) {
-            @Override
-            protected boolean check() {
-                String c = mCookieManager.getCookie(url);
-                return !c.contains(cookie1) && c.contains(cookie2) && c.contains(cookie3);
-            }
-        }.run();
+        // When we remove session cookies there are some to remove.
+        removeSessionCookiesOnUiThread(callback);
+        assertTrue(s.tryAcquire(TEST_TIMEOUT, TimeUnit.MILLISECONDS));
+        assertTrue(anyDeleted.get());
 
-        Thread.sleep(expiration + 1000); // wait for cookie to expire
-        mCookieManager.removeExpiredCookie();
-        new PollingCheck(TEST_TIMEOUT) {
-            @Override
-            protected boolean check() {
-                String c = mCookieManager.getCookie(url);
-                return !c.contains(cookie1) && c.contains(cookie2) && !c.contains(cookie3);
-            }
-        }.run();
+        // The normal cookie is not removed.
+        assertTrue(mCookieManager.getCookie(url).contains(normalCookie));
 
-        mCookieManager.removeAllCookie();
-        new PollingCheck(TEST_TIMEOUT) {
-            @Override
-            protected boolean check() {
-                return mCookieManager.getCookie(url) == null;
-            }
-        }.run();
+        // When we remove session cookies again there are none to remove.
+        removeSessionCookiesOnUiThread(callback);
+        assertTrue(s.tryAcquire(TEST_TIMEOUT, TimeUnit.MILLISECONDS));
+        assertFalse(anyDeleted.get());
+
+        // When we remove all cookies there are some to remove.
+        removeAllCookiesOnUiThread(callback);
+        assertTrue(s.tryAcquire(TEST_TIMEOUT, TimeUnit.MILLISECONDS));
+        assertTrue(anyDeleted.get());
+
+        // Now we have no cookies.
+        assertFalse(mCookieManager.hasCookies());
+        assertNull(mCookieManager.getCookie(url));
+
+        // When we remove all cookies again there are none to remove.
+        removeAllCookiesOnUiThread(callback);
+        assertTrue(s.tryAcquire(TEST_TIMEOUT, TimeUnit.MILLISECONDS));
+        assertFalse(anyDeleted.get());
     }
 
-    private void waitForCookie(final String url) {
-        new PollingCheck(TEST_TIMEOUT) {
-            @Override
-            protected boolean check() {
-                return mCookieManager.getCookie(url) != null;
-            }
-        }.run();
+    /*
+    TODO: uncomment when acceptThirdPartyCookies implementation lands
+    public void testThirdPartyCookie() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+        CtsTestServer server = null;
+        try {
+            // In theory we need two servers to test this, one server ('the first party')
+            // which returns a response with a link to a second server ('the third party')
+            // at different origin. This second server attempts to set a cookie which should
+            // fail if AcceptThirdPartyCookie() is false.
+            // Strictly according to the letter of RFC6454 it should be possible to set this
+            // situation up with two TestServers on different ports (these count as having
+            // different origins) but Chrome is not strict about this and does not check the
+            // port. Instead we cheat making some of the urls come from localhost and some
+            // from 127.0.0.1 which count (both in theory and pratice) as having different
+            // origins.
+            server = new CtsTestServer(getActivity());
+
+            // Turn on Javascript (otherwise <script> aren't fetched spoiling the test).
+            mOnUiThread.getSettings().setJavaScriptEnabled(true);
+
+            // Turn global allow on.
+            mCookieManager.setAcceptCookie(true);
+            assertTrue(mCookieManager.acceptCookie());
+
+            // When third party cookies are disabled...
+            mOnUiThread.setAcceptThirdPartyCookies(false);
+            assertFalse(mOnUiThread.acceptThirdPartyCookies());
+
+            // ...we can't set third party cookies.
+            // First on the third party server we get a url which tries to set a cookie.
+            String cookieUrl = toThirdPartyUrl(
+                    server.getSetCookieUrl("cookie_1.js", "test1", "value1"));
+            // Then we create a url on the first party server which links to the first url.
+            String url = server.getLinkedScriptUrl("/content_1.html", cookieUrl);
+            mOnUiThread.loadUrlAndWaitForCompletion(url);
+            assertNull(mCookieManager.getCookie(cookieUrl));
+
+            // When third party cookies are enabled...
+            mOnUiThread.setAcceptThirdPartyCookies(true);
+            assertTrue(mOnUiThread.acceptThirdPartyCookies());
+
+            // ...we can set third party cookies.
+            cookieUrl = toThirdPartyUrl(
+                    server.getSetCookieUrl("/cookie_2.js", "test2", "value2"));
+            url = server.getLinkedScriptUrl("/content_2.html", cookieUrl);
+            mOnUiThread.loadUrlAndWaitForCompletion(url);
+            waitForCookie(cookieUrl);
+            String cookie = mCookieManager.getCookie(cookieUrl);
+            assertNotNull(cookie);
+            assertTrue(cookie.contains("test2"));
+        } finally {
+            if (server != null) server.shutdown();
+            mOnUiThread.getSettings().setJavaScriptEnabled(false);
+        }
     }
+    */
 
     public void testb3167208() throws Exception {
         if (!NullWebViewUtils.isWebViewAvailable()) {
@@ -241,4 +391,70 @@
         assertNotNull(cookie);
         assertTrue(cookie.contains("foo=bar"));
     }
-}
+
+    private void waitForCookie(final String url) {
+        new PollingCheck(TEST_TIMEOUT) {
+            @Override
+            protected boolean check() {
+                return mCookieManager.getCookie(url) != null;
+            }
+        }.run();
+    }
+
+    @SuppressWarnings("deprecation")
+    private String makeExpiringCookie(String cookie, int secondsTillExpiry) {
+        return makeExpiringCookieMs(cookie, 1000*secondsTillExpiry);
+    }
+
+    @SuppressWarnings("deprecation")
+    private String makeExpiringCookieMs(String cookie, int millisecondsTillExpiry) {
+        Date date = new Date();
+        date.setTime(date.getTime() + millisecondsTillExpiry);
+        return cookie + "; expires=" + date.toGMTString();
+    }
+
+    private void removeAllCookiesOnUiThread(final ValueCallback<Boolean> callback) {
+        runTestOnUiThreadAndCatch(new Runnable() {
+            @Override
+            public void run() {
+                mCookieManager.removeAllCookies(callback);
+            }
+        });
+    }
+
+    private void removeSessionCookiesOnUiThread(final ValueCallback<Boolean> callback) {
+        runTestOnUiThreadAndCatch(new Runnable() {
+            @Override
+            public void run() {
+                mCookieManager.removeSessionCookies(callback);
+            }
+        });
+    }
+
+    private void setCookieOnUiThread(final String url, final String cookie,
+            final ValueCallback<Boolean> callback) {
+        runTestOnUiThreadAndCatch(new Runnable() {
+            @Override
+            public void run() {
+                mCookieManager.setCookie(url, cookie, callback);
+            }
+        });
+    }
+
+    private void runTestOnUiThreadAndCatch(Runnable runnable) {
+        try {
+            runTestOnUiThread(runnable);
+        } catch (Throwable t) {
+            fail("Unexpected error while running on UI thread: " + t.getMessage());
+        }
+    }
+
+    /**
+     * Makes a url look as if it comes from a different host.
+     * @param url the url to fake.
+     * @return the resulting url after faking.
+     */
+    public String toThirdPartyUrl(String url) {
+        return url.replace("localhost", "127.0.0.1");
+    }
+ }
diff --git a/tests/tests/webkit/src/android/webkit/cts/CookieSyncManagerCtsActivity.java b/tests/tests/webkit/src/android/webkit/cts/CookieSyncManagerCtsActivity.java
new file mode 100644
index 0000000..e623405
--- /dev/null
+++ b/tests/tests/webkit/src/android/webkit/cts/CookieSyncManagerCtsActivity.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2009 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.webkit.cts;
+
+import android.app.Activity;
+import android.cts.util.NullWebViewUtils;
+import android.os.Bundle;
+import android.webkit.CookieSyncManager;
+import android.webkit.WebView;
+
+public class CookieSyncManagerCtsActivity extends Activity {
+    private WebView mWebView;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        try {
+            CookieSyncManager.createInstance(this);
+
+            mWebView = new WebView(this);
+            setContentView(mWebView);
+        } catch (Exception e) {
+            NullWebViewUtils.determineIfWebViewAvailable(this, e);
+        }
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        try {
+            CookieSyncManager.getInstance().startSync();
+        } catch (Exception e) {
+            // May throw on a device with no webview, OK to ignore at this point.
+        }
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+        try {
+            CookieSyncManager.getInstance().stopSync();
+        } catch (Exception e) {
+            // May throw on a device with no webview, OK to ignore at this point.
+        }
+    }
+
+    public WebView getWebView(){
+        return mWebView;
+    }
+}
diff --git a/tests/tests/webkit/src/android/webkit/cts/CookieSyncManagerTest.java b/tests/tests/webkit/src/android/webkit/cts/CookieSyncManagerTest.java
deleted file mode 100644
index 95e3add..0000000
--- a/tests/tests/webkit/src/android/webkit/cts/CookieSyncManagerTest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2010 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.webkit.cts;
-
-
-import android.content.Context;
-import android.cts.util.PollingCheck;
-import android.test.ActivityInstrumentationTestCase2;
-import android.webkit.CookieManager;
-import android.webkit.CookieSyncManager;
-
-public class CookieSyncManagerTest
-        extends ActivityInstrumentationTestCase2<CookieSyncManagerStubActivity> {
-
-    private final static int COOKIE_MANAGER_TIMEOUT = 5000;
-
-    public CookieSyncManagerTest() {
-        super("com.android.cts.stub", CookieSyncManagerStubActivity.class);
-    }
-
-    public void testCookieSyncManager() throws Exception {
-        if (getActivity().getWebView() == null) {
-            return;
-        }
-        CookieSyncManager csm1 = CookieSyncManager.createInstance(getActivity());
-        assertNotNull(csm1);
-
-        CookieSyncManager csm2 = CookieSyncManager.getInstance();
-        assertNotNull(csm2);
-
-        assertSame(csm1, csm2);
-
-        final CookieManager cookieManager = CookieManager.getInstance();
-
-        // Remove all cookies from the database.
-        cookieManager.removeAllCookie();
-        new PollingCheck(COOKIE_MANAGER_TIMEOUT) {
-            @Override
-            protected boolean check() {
-                return !cookieManager.hasCookies();
-            }
-        }.run();
-
-        cookieManager.setAcceptCookie(true);
-        assertTrue(cookieManager.acceptCookie());
-
-        CtsTestServer server = new CtsTestServer(getActivity(), false);
-        String url = server.getCookieUrl("conquest.html");
-        String cookieValue = "a=b";
-        cookieManager.setCookie(url, cookieValue);
-        assertEquals(cookieValue, cookieManager.getCookie(url));
-
-        // Store the cookie to the database.
-        csm1.sync();
-        new PollingCheck(COOKIE_MANAGER_TIMEOUT) {
-            @Override
-            protected boolean check() {
-                return cookieManager.hasCookies();
-            }
-        }.run();
-
-        // Remove all cookies from the database.
-        cookieManager.removeAllCookie();
-        new PollingCheck(COOKIE_MANAGER_TIMEOUT) {
-            @Override
-            protected boolean check() {
-                return !cookieManager.hasCookies();
-            }
-        }.run();
-    }
-}
diff --git a/tests/tests/webkit/src/android/webkit/cts/CookieTest.java b/tests/tests/webkit/src/android/webkit/cts/CookieTest.java
index 7f3b183..555266b 100644
--- a/tests/tests/webkit/src/android/webkit/cts/CookieTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/CookieTest.java
@@ -16,6 +16,7 @@
 
 package android.webkit.cts;
 
+import android.cts.util.NullWebViewUtils;
 import android.test.ActivityInstrumentationTestCase2;
 import android.webkit.CookieManager;
 import android.webkit.CookieSyncManager;
@@ -23,13 +24,13 @@
 /**
  * Original framework tests for CookieManager
  */
-public class CookieTest extends ActivityInstrumentationTestCase2<CookieSyncManagerStubActivity> {
+public class CookieTest extends ActivityInstrumentationTestCase2<CookieSyncManagerCtsActivity> {
 
     private CookieManager mCookieManager;
     private static final long WAIT_TIME = 50;
 
     public CookieTest() {
-        super("com.android.cts.stub", CookieSyncManagerStubActivity.class);
+        super("com.android.cts.webkit", CookieSyncManagerCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/webkit/src/android/webkit/cts/GeolocationTest.java b/tests/tests/webkit/src/android/webkit/cts/GeolocationTest.java
index 8ab9eb6..ba0e0e9 100644
--- a/tests/tests/webkit/src/android/webkit/cts/GeolocationTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/GeolocationTest.java
@@ -17,6 +17,7 @@
 package android.webkit.cts;
 
 import android.content.Context;
+import android.cts.util.NullWebViewUtils;
 import android.cts.util.PollingCheck;
 import android.graphics.Bitmap;
 import android.location.Criteria;
@@ -52,7 +53,7 @@
 
 import junit.framework.Assert;
 
-public class GeolocationTest extends ActivityInstrumentationTestCase2<WebViewStubActivity> {
+public class GeolocationTest extends ActivityInstrumentationTestCase2<WebViewCtsActivity> {
 
     // TODO Write additional tests to cover:
     // - test that the errors are correct
@@ -108,7 +109,7 @@
     private List<String> mProviders;
 
     public GeolocationTest() throws Exception {
-        super("com.android.cts.stub", WebViewStubActivity.class);
+        super("com.android.cts.webkit", WebViewCtsActivity.class);
     }
 
     // Both this test and WebViewOnUiThread need to override some of the methods on WebViewClient,
@@ -166,6 +167,7 @@
                     break;
                 }
             }
+            mProviders.add(LocationManager.FUSED_PROVIDER);
             addTestProviders();
         }
     }
diff --git a/tests/tests/webkit/src/android/webkit/cts/HttpAuthHandlerTest.java b/tests/tests/webkit/src/android/webkit/cts/HttpAuthHandlerTest.java
index b078c7a..5c86987 100644
--- a/tests/tests/webkit/src/android/webkit/cts/HttpAuthHandlerTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/HttpAuthHandlerTest.java
@@ -16,6 +16,7 @@
 
 package android.webkit.cts;
 
+import android.cts.util.NullWebViewUtils;
 import android.test.ActivityInstrumentationTestCase2;
 import android.webkit.HttpAuthHandler;
 import android.webkit.WebView;
@@ -24,7 +25,7 @@
 
 import org.apache.http.HttpStatus;
 
-public class HttpAuthHandlerTest extends ActivityInstrumentationTestCase2<WebViewStubActivity> {
+public class HttpAuthHandlerTest extends ActivityInstrumentationTestCase2<WebViewCtsActivity> {
 
     private static final long TIMEOUT = 10000;
 
@@ -37,7 +38,7 @@
     private WebViewOnUiThread mOnUiThread;
 
     public HttpAuthHandlerTest() {
-        super("com.android.cts.stub", WebViewStubActivity.class);
+        super("com.android.cts.webkit", WebViewCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/webkit/src/android/webkit/cts/TestHtmlConstants.java b/tests/tests/webkit/src/android/webkit/cts/TestHtmlConstants.java
index 11cc1a5..30b8210 100644
--- a/tests/tests/webkit/src/android/webkit/cts/TestHtmlConstants.java
+++ b/tests/tests/webkit/src/android/webkit/cts/TestHtmlConstants.java
@@ -50,6 +50,7 @@
     public static final String HTML_URL1 = "webkit/test_firstPage.html";
     public static final String HTML_URL2 = "webkit/test_secondPage.html";
     public static final String HTML_URL3 = "webkit/test_thirdPage.html";
+    public static final String HTML_URL1_TITLE = "First page";
 
     public static final String BLANK_PAGE_URL = "webkit/test_blankPage.html";
     public static final String ADD_JAVA_SCRIPT_INTERFACE_URL = "webkit/test_jsInterface.html";
@@ -65,6 +66,7 @@
     public static final String DATABASE_ACCESS_URL = "webkit/test_databaseaccess.html";
     public static final String STOP_LOADING_URL = "webkit/test_stop_loading.html";
     public static final String BLANK_TAG_URL = "webkit/blank_tag.html";
+    public static final String PAGE_WITH_LINK_URL = "webkit/page_with_link.html";
 
     // Must match the title of the page at
     // android/frameworks/base/core/res/res/raw/loaderror.html
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebBackForwardListTest.java b/tests/tests/webkit/src/android/webkit/cts/WebBackForwardListTest.java
index 71893f4..7d25b84 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebBackForwardListTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebBackForwardListTest.java
@@ -16,6 +16,7 @@
 
 package android.webkit.cts;
 
+import android.cts.util.NullWebViewUtils;
 import android.cts.util.PollingCheck;
 import android.test.ActivityInstrumentationTestCase2;
 import android.webkit.WebBackForwardList;
@@ -23,14 +24,14 @@
 import android.webkit.WebView;
 
 
-public class WebBackForwardListTest extends ActivityInstrumentationTestCase2<WebViewStubActivity> {
+public class WebBackForwardListTest extends ActivityInstrumentationTestCase2<WebViewCtsActivity> {
 
     private static final int TEST_TIMEOUT = 10000;
 
     private WebViewOnUiThread mOnUiThread;
 
     public WebBackForwardListTest() {
-        super("com.android.cts.stub", WebViewStubActivity.class);
+        super("com.android.cts.webkit", WebViewCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebChromeClientTest.java b/tests/tests/webkit/src/android/webkit/cts/WebChromeClientTest.java
index 31422985..150fd86 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebChromeClientTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebChromeClientTest.java
@@ -16,6 +16,7 @@
 
 package android.webkit.cts;
 
+import android.cts.util.NullWebViewUtils;
 import android.cts.util.PollingCheck;
 import android.graphics.Bitmap;
 import android.os.Message;
@@ -28,7 +29,7 @@
 import android.webkit.WebView;
 import android.webkit.cts.WebViewOnUiThread.WaitForProgressClient;
 
-public class WebChromeClientTest extends ActivityInstrumentationTestCase2<WebViewStubActivity> {
+public class WebChromeClientTest extends ActivityInstrumentationTestCase2<WebViewCtsActivity> {
     private static final long TEST_TIMEOUT = 5000L;
 
     private CtsTestServer mWebServer;
@@ -38,7 +39,7 @@
     private boolean mBlockWindowCreationAsync;
 
     public WebChromeClientTest() {
-        super(WebViewStubActivity.class);
+        super(WebViewCtsActivity.class);
     }
 
     @Override
@@ -126,6 +127,7 @@
         Thread.sleep(100); // Wait for open to be received on the icon db thread.
 
         assertFalse(webChromeClient.hadOnReceivedIcon());
+        assertNull(mOnUiThread.getFavicon());
 
         String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
         mOnUiThread.loadUrlAndWaitForCompletion(url);
@@ -136,6 +138,7 @@
                 return webChromeClient.hadOnReceivedIcon();
             }
         }.run();
+        assertNotNull(mOnUiThread.getFavicon());
     }
 
     public void runWindowTest(boolean expectWindowClose) throws Exception {
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebHistoryItemTest.java b/tests/tests/webkit/src/android/webkit/cts/WebHistoryItemTest.java
index 7d276e9..a6b647df 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebHistoryItemTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebHistoryItemTest.java
@@ -16,6 +16,7 @@
 
 package android.webkit.cts;
 
+import android.cts.util.NullWebViewUtils;
 import android.cts.util.PollingCheck;
 import android.graphics.Bitmap;
 import android.test.ActivityInstrumentationTestCase2;
@@ -25,7 +26,7 @@
 import android.webkit.WebIconDatabase;
 import android.webkit.WebView;
 
-public class WebHistoryItemTest extends ActivityInstrumentationTestCase2<WebViewStubActivity> {
+public class WebHistoryItemTest extends ActivityInstrumentationTestCase2<WebViewCtsActivity> {
     private final static long TEST_TIMEOUT = 10000;
     private CtsTestServer mWebServer;
     private WebViewOnUiThread mOnUiThread;
@@ -47,7 +48,7 @@
     };
 
     public WebHistoryItemTest() {
-        super("com.android.cts.stub", WebViewStubActivity.class);
+        super("com.android.cts.webkit", WebViewCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java b/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
index b25a0cf..33a9cee 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
@@ -16,17 +16,22 @@
 package android.webkit.cts;
 
 import android.content.Context;
+import android.cts.util.NullWebViewUtils;
 import android.cts.util.PollingCheck;
 import android.graphics.Bitmap;
+import android.net.http.SslError;
 import android.os.Build;
 import android.test.ActivityInstrumentationTestCase2;
 import android.util.Log;
 import android.webkit.ConsoleMessage;
+import android.webkit.SslErrorHandler;
 import android.webkit.WebIconDatabase;
 import android.webkit.WebSettings;
 import android.webkit.WebSettings.TextSize;
 import android.webkit.WebStorage;
 import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.webkit.cts.WebViewOnUiThread.WaitForLoadedClient;
 import android.webkit.cts.WebViewOnUiThread.WaitForProgressClient;
 import java.io.FileOutputStream;
 import java.util.Locale;
@@ -36,7 +41,7 @@
 /**
  * Tests for {@link android.webkit.WebSettings}
  */
-public class WebSettingsTest extends ActivityInstrumentationTestCase2<WebViewStubActivity> {
+public class WebSettingsTest extends ActivityInstrumentationTestCase2<WebViewCtsActivity> {
 
     private static final int WEBVIEW_TIMEOUT = 5000;
     private static final String LOG_TAG = "WebSettingsTest";
@@ -59,7 +64,7 @@
     private Context mContext;
 
     public WebSettingsTest() {
-        super("com.android.cts.stub", WebViewStubActivity.class);
+        super("com.android.cts.webkit", WebViewCtsActivity.class);
     }
 
     @Override
@@ -226,7 +231,14 @@
             }
         }.run();
         int firstFetch = mWebServer.getRequestCount();
+        iconListener.mReceivedIcon = false;
         loadAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
+        new PollingCheck(WEBVIEW_TIMEOUT) {
+            @Override
+            protected boolean check() {
+                return iconListener.mReceivedIcon;
+            }
+        }.run();
         assertEquals(firstFetch, mWebServer.getRequestCount());
 
         mSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
@@ -925,6 +937,71 @@
         fos.close();
     }
 
+    public void testAllowMixedMode() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+        final class SslWebViewClient extends WaitForLoadedClient {
+            public SslWebViewClient() {
+                super(mOnUiThread);
+            }
+            @Override
+            public void onReceivedSslError(WebView view,
+                    SslErrorHandler handler, SslError error) {
+                handler.proceed();
+            }
+        }
+
+        mSettings.setJavaScriptEnabled(true);
+        TestWebServer httpsServer = null;
+        TestWebServer httpServer = null;
+        try {
+            httpsServer = new TestWebServer(true);
+            httpServer = new TestWebServer(false);
+            final String JS_URL = "/insecure.js";
+            final String IMG_URL = "/insecure.png";
+            final String SECURE_URL = "/secure.html";
+            final String JS_HTML = "<script src=\"" + httpServer.getResponseUrl(JS_URL) +
+                "\"></script>";
+            final String IMG_HTML = "<img src=\"" + httpServer.getResponseUrl(IMG_URL) + "\" />";
+            final String SECURE_HTML = "<body>" + IMG_HTML + " " + JS_HTML + "</body>";
+            httpServer.setResponse(JS_URL, "window.loaded_js = 42;", null);
+            httpServer.setResponseBase64(IMG_URL,
+                    "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",
+                    null);
+            String secureUrl = httpsServer.setResponse(SECURE_URL, SECURE_HTML, null);
+
+            mOnUiThread.clearSslPreferences();
+
+            mOnUiThread.setWebViewClient(new SslWebViewClient());
+
+            mSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_NEVER_ALLOW);
+            mOnUiThread.loadUrlAndWaitForCompletion(secureUrl);
+            assertEquals(1, httpsServer.getRequestCount(SECURE_URL));
+            assertEquals(0, httpServer.getRequestCount(JS_URL));
+            assertEquals(0, httpServer.getRequestCount(IMG_URL));
+
+            mSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
+            mOnUiThread.loadUrlAndWaitForCompletion(secureUrl);
+            assertEquals(2, httpsServer.getRequestCount(SECURE_URL));
+            assertEquals(1, httpServer.getRequestCount(JS_URL));
+            assertEquals(1, httpServer.getRequestCount(IMG_URL));
+
+            mSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
+            mOnUiThread.loadUrlAndWaitForCompletion(secureUrl);
+            assertEquals(3, httpsServer.getRequestCount(SECURE_URL));
+            assertEquals(1, httpServer.getRequestCount(JS_URL));
+            assertEquals(2, httpServer.getRequestCount(IMG_URL));
+        } finally {
+            if (httpServer != null) {
+                httpServer.shutdown();
+            }
+            if (httpsServer != null) {
+                httpsServer.shutdown();
+            }
+        }
+    }
+
     /**
      * Starts the internal web server. The server will be shut down automatically
      * during tearDown().
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
index 7872dbe..5b906ba 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
@@ -17,6 +17,7 @@
 package android.webkit.cts;
 
 import android.cts.util.EvaluateJsResultPollingCheck;
+import android.cts.util.NullWebViewUtils;
 import android.cts.util.PollingCheck;
 import android.graphics.Bitmap;
 import android.os.Message;
@@ -26,13 +27,19 @@
 import android.webkit.HttpAuthHandler;
 import android.webkit.ValueCallback;
 import android.webkit.WebChromeClient;
+import android.webkit.WebResourceRequest;
+import android.webkit.WebResourceResponse;
 import android.webkit.WebSettings;
 import android.webkit.WebView;
 import android.webkit.WebViewClient;
 import android.webkit.cts.WebViewOnUiThread.WaitForLoadedClient;
 
+import java.io.ByteArrayInputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
 
-public class WebViewClientTest extends ActivityInstrumentationTestCase2<WebViewStubActivity> {
+public class WebViewClientTest extends ActivityInstrumentationTestCase2<WebViewCtsActivity> {
     private static final long TEST_TIMEOUT = 5000;
     private static final String TEST_URL = "http://foo.com/";
 
@@ -40,13 +47,13 @@
     private CtsTestServer mWebServer;
 
     public WebViewClientTest() {
-        super("com.android.cts.stub", WebViewStubActivity.class);
+        super("com.android.cts.webkit", WebViewCtsActivity.class);
     }
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        final WebViewStubActivity activity = getActivity();
+        final WebViewCtsActivity activity = getActivity();
         WebView webview = activity.getWebView();
         if (webview != null) {
             new PollingCheck(TEST_TIMEOUT) {
@@ -92,11 +99,12 @@
                 "<a href=\"" + TEST_URL + "\" id=\"link\">new page</a>" +
                 "</body></html>";
         mOnUiThread.loadDataAndWaitForCompletion(data, "text/html", null);
-        clickOnLinkUsingJs("link");
+        clickOnLinkUsingJs("link", mOnUiThread);
         assertEquals(TEST_URL, webViewClient.getLastShouldOverrideUrl());
     }
 
     // Verify shouldoverrideurlloading called on webview called via onCreateWindow
+    // TODO(sgurun) upstream this test to Aw.
     public void testShouldOverrideUrlLoadingOnCreateWindow() throws Exception {
         if (!NullWebViewUtils.isWebViewAvailable()) {
             return;
@@ -110,12 +118,14 @@
         mOnUiThread.getSettings().setJavaScriptEnabled(true);
         mOnUiThread.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
         mOnUiThread.getSettings().setSupportMultipleWindows(true);
+
+        final WebView childWebView = mOnUiThread.createWebView();
+
         mOnUiThread.setWebChromeClient(new WebChromeClient() {
             @Override
             public boolean onCreateWindow(
                 WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
                 WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
-                WebView childWebView = new WebView(view.getContext());
                 childWebView.setWebViewClient(childWebViewClient);
                 childWebView.getSettings().setJavaScriptEnabled(true);
                 transport.setWebView(childWebView);
@@ -134,13 +144,30 @@
                 return childWebViewClient.hasOnPageFinishedCalled();
             }
         }.run();
-        assertEquals(mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL),
+        assertEquals(mWebServer.getAssetUrl(TestHtmlConstants.PAGE_WITH_LINK_URL),
                 childWebViewClient.getLastShouldOverrideUrl());
+
+        // Now test a navigation within the page
+        //TODO(hush) Enable this portion when b/12804986 is fixed.
+        /*
+        WebViewOnUiThread childWebViewOnUiThread = new WebViewOnUiThread(this, childWebView);
+        final int childCallCount = childWebViewClient.getShouldOverrideUrlLoadingCallCount();
+        final int mainCallCount = mainWebViewClient.getShouldOverrideUrlLoadingCallCount();
+        clickOnLinkUsingJs("link", childWebViewOnUiThread);
+        new PollingCheck(TEST_TIMEOUT) {
+            @Override
+            protected boolean check() {
+                return childWebViewClient.getShouldOverrideUrlLoadingCallCount() > childCallCount;
+            }
+        }.run();
+        assertEquals(mainCallCount, mainWebViewClient.getShouldOverrideUrlLoadingCallCount());
+        assertEquals(TEST_URL, childWebViewClient.getLastShouldOverrideUrl());
+        */
     }
 
-    private void clickOnLinkUsingJs(final String linkId) {
+    private void clickOnLinkUsingJs(final String linkId, WebViewOnUiThread webViewOnUiThread) {
         EvaluateJsResultPollingCheck jsResult = new EvaluateJsResultPollingCheck("null");
-        mOnUiThread.evaluateJavascript(
+        webViewOnUiThread.evaluateJavascript(
                 "document.getElementById('" + linkId + "').click();" +
                 "console.log('element with id [" + linkId + "] clicked');", jsResult);
         jsResult.run();
@@ -319,6 +346,152 @@
         }.run();
     }
 
+    // Test that shouldInterceptRequest is called with the correct parameters
+    public void testShouldInterceptRequestParams() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
+        final String mainPath = "/main";
+        final String mainPage = "<head></head><body>test page</body>";
+        final String headerName = "x-test-header-name";
+        final String headerValue = "testheadervalue";
+        HashMap<String, String> headers = new HashMap<String, String>(1);
+        headers.put(headerName, headerValue);
+
+        // A client which saves the WebResourceRequest as interceptRequest
+        final class TestClient extends WaitForLoadedClient {
+            public TestClient() {
+                super(mOnUiThread);
+            }
+
+            @Override
+            public WebResourceResponse shouldInterceptRequest(WebView view,
+                    WebResourceRequest request) {
+                assertNotNull(view);
+                assertNotNull(request);
+
+                assertEquals(view, mOnUiThread.getWebView());
+
+                // Save the main page request; discard any other requests (e.g. for favicon.ico)
+                if (request.getUrl().getPath().equals(mainPath)) {
+                    assertNull(interceptRequest);
+                    interceptRequest = request;
+                }
+
+                return null;
+            }
+
+            public volatile WebResourceRequest interceptRequest;
+        }
+
+        TestClient client = new TestClient();
+        mOnUiThread.setWebViewClient(client);
+
+        TestWebServer server = new TestWebServer(false);
+        try {
+            String mainUrl = server.setResponse(mainPath, mainPage, null);
+
+            mOnUiThread.loadUrlAndWaitForCompletion(mainUrl, headers);
+
+            // Inspect the fields of the saved WebResourceRequest
+            assertNotNull(client.interceptRequest);
+            assertEquals(mainUrl, client.interceptRequest.getUrl().toString());
+            assertTrue(client.interceptRequest.isForMainFrame());
+            assertEquals(server.getLastRequest(mainPath).getRequestLine().getMethod(),
+                client.interceptRequest.getMethod());
+
+            // Web request headers are case-insensitive. We provided lower-case headerName and
+            // headerValue. This will pass implementations which either do not mangle case,
+            // convert to lowercase, or convert to uppercase but return a case-insensitive map.
+            Map<String, String> interceptHeaders = client.interceptRequest.getRequestHeaders();
+            assertTrue(interceptHeaders.containsKey(headerName));
+            assertEquals(headerValue, interceptHeaders.get(headerName));
+        } finally {
+            server.shutdown();
+        }
+    }
+
+    // Test that the WebResourceResponse returned by shouldInterceptRequest is handled correctly
+    public void testShouldInterceptRequestResponse() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
+        final String mainPath = "/main";
+        final String mainPage = "<head></head><body>test page</body>";
+        final String interceptPath = "/intercept_me";
+
+        // A client which responds to requests for interceptPath with a saved interceptResponse
+        final class TestClient extends WaitForLoadedClient {
+            public TestClient() {
+                super(mOnUiThread);
+            }
+
+            @Override
+            public WebResourceResponse shouldInterceptRequest(WebView view,
+                    WebResourceRequest request) {
+                if (request.getUrl().toString().contains(interceptPath)) {
+                    assertNotNull(interceptResponse);
+                    return interceptResponse;
+                }
+
+                return null;
+            }
+
+            volatile public WebResourceResponse interceptResponse;
+        }
+
+        mOnUiThread.getSettings().setJavaScriptEnabled(true);
+
+        TestClient client = new TestClient();
+        mOnUiThread.setWebViewClient(client);
+
+        TestWebServer server = new TestWebServer(false);
+        try {
+            String interceptUrl = server.getResponseUrl(interceptPath);
+
+            // JavaScript which makes a synchronous AJAX request and logs and returns the status
+            String js =
+                "(function() {" +
+                "  var xhr = new XMLHttpRequest();" +
+                "  xhr.open('GET', '" + interceptUrl + "', false);" +
+                "  xhr.send(null);" +
+                "  console.info('xhr.status = ' + xhr.status);" +
+                "  console.info('xhr.statusText = ' + xhr.statusText);" +
+                "  return '[' + xhr.status + '][' + xhr.statusText + ']';" +
+                "})();";
+
+            String mainUrl = server.setResponse(mainPath, mainPage, null);
+            mOnUiThread.loadUrlAndWaitForCompletion(mainUrl, null);
+
+            EvaluateJsResultPollingCheck jsResult;
+
+            // Test a nonexistent page
+            client.interceptResponse = new WebResourceResponse("text/html", "UTF-8", null);
+            jsResult = new EvaluateJsResultPollingCheck("\"[404][Not Found]\"");
+            mOnUiThread.evaluateJavascript(js, jsResult);
+            jsResult.run();
+
+            // Test an empty page
+            client.interceptResponse = new WebResourceResponse("text/html", "UTF-8",
+                new ByteArrayInputStream(new byte[0]));
+            jsResult = new EvaluateJsResultPollingCheck("\"[200][OK]\"");
+            mOnUiThread.evaluateJavascript(js, jsResult);
+            jsResult.run();
+
+            // Test a nonempty page with unusual response code/text
+            client.interceptResponse =
+                new WebResourceResponse("text/html", "UTF-8", 123, "unusual", null,
+                    new ByteArrayInputStream("nonempty page".getBytes(StandardCharsets.UTF_8)));
+            jsResult = new EvaluateJsResultPollingCheck("\"[123][unusual]\"");
+            mOnUiThread.evaluateJavascript(js, jsResult);
+            jsResult.run();
+        } finally {
+            server.shutdown();
+        }
+    }
+
     private void requireLoadedPage() throws Throwable {
         if (!NullWebViewUtils.isWebViewAvailable()) {
             return;
@@ -336,6 +509,7 @@
         private boolean mOnReceivedHttpAuthRequestCalled;
         private boolean mOnUnhandledKeyEventCalled;
         private boolean mOnScaleChangedCalled;
+        private int mShouldOverrideUrlLoadingCallCount;
         private String mLastShouldOverrideUrl;
 
         public MockWebViewClient() {
@@ -378,6 +552,10 @@
             return mOnScaleChangedCalled;
         }
 
+        public int getShouldOverrideUrlLoadingCallCount() {
+            return mShouldOverrideUrlLoadingCallCount;
+        }
+
         public String getLastShouldOverrideUrl() {
             return mLastShouldOverrideUrl;
         }
@@ -444,6 +622,7 @@
         @Override
         public boolean shouldOverrideUrlLoading(WebView view, String url) {
             mLastShouldOverrideUrl = url;
+            mShouldOverrideUrlLoadingCallCount++;
             return false;
         }
     }
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewCtsActivity.java b/tests/tests/webkit/src/android/webkit/cts/WebViewCtsActivity.java
new file mode 100644
index 0000000..9af7266
--- /dev/null
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewCtsActivity.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2009 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.webkit.cts;
+
+import com.android.cts.webkit.R;
+
+import android.app.Activity;
+import android.cts.util.NullWebViewUtils;
+import android.os.Bundle;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.webkit.WebView;
+
+public class WebViewCtsActivity extends Activity {
+    private WebView mWebView;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        try {
+            super.onCreate(savedInstanceState);
+            setContentView(R.layout.webview_layout);
+            mWebView = (WebView) findViewById(R.id.web_page);
+        } catch (Exception e) {
+            NullWebViewUtils.determineIfWebViewAvailable(this, e);
+        }
+    }
+
+    public WebView getWebView() {
+        return mWebView;
+    }
+
+    @Override
+    public void onDestroy() {
+        if (mWebView != null) {
+            ViewParent parent =  mWebView.getParent();
+            if (parent instanceof ViewGroup) {
+                ((ViewGroup) parent).removeView(mWebView);
+            }
+            mWebView.destroy();
+        }
+        super.onDestroy();
+    }
+}
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewSslTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewSslTest.java
new file mode 100644
index 0000000..378bf6e
--- /dev/null
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewSslTest.java
@@ -0,0 +1,967 @@
+/*
+ * Copyright (C) 2009 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.webkit.cts;
+
+import android.cts.util.NullWebViewUtils;
+import android.cts.util.PollingCheck;
+import android.net.Uri;
+import android.net.http.SslCertificate;
+import android.net.http.SslError;
+import android.os.StrictMode;
+import android.os.StrictMode.ThreadPolicy;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.util.Log;
+import android.webkit.ClientCertRequest;
+import android.webkit.SslErrorHandler;
+import android.webkit.ValueCallback;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.webkit.cts.WebViewOnUiThread.WaitForLoadedClient;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+import java.security.Principal;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.Callable;
+
+import javax.net.ssl.X509TrustManager;
+
+public class WebViewSslTest extends ActivityInstrumentationTestCase2<WebViewCtsActivity> {
+    private static final String LOGTAG = "WebViewSslTest";
+
+    /**
+     * Taken verbatim from AndroidKeyStoreTest.java. Copying the build notes here for reference.
+     * The keys and certificates below are generated with:
+     *
+     * openssl req -new -x509 -days 3650 -extensions v3_ca -keyout cakey.pem -out cacert.pem
+     * openssl req -newkey rsa:1024 -keyout userkey.pem -nodes -days 3650 -out userkey.req
+     * mkdir -p demoCA/newcerts
+     * touch demoCA/index.txt
+     * echo "01" > demoCA/serial
+     * openssl ca -out usercert.pem -in userkey.req -cert cacert.pem -keyfile cakey.pem -days 3650
+     */
+
+    /**
+     * Generated from above and converted with:
+     *
+     * openssl x509 -outform d -in usercert.pem | xxd -i | sed 's/0x/(byte) 0x/g'
+     */
+    private static final byte[] FAKE_RSA_USER_1 = new byte[] {
+            (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x95, (byte) 0x30, (byte) 0x82,
+            (byte) 0x01, (byte) 0xfe, (byte) 0xa0, (byte) 0x03, (byte) 0x02, (byte) 0x01,
+            (byte) 0x02, (byte) 0x02, (byte) 0x01, (byte) 0x01, (byte) 0x30, (byte) 0x0d,
+            (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86,
+            (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x05,
+            (byte) 0x00, (byte) 0x30, (byte) 0x4f, (byte) 0x31, (byte) 0x0b, (byte) 0x30,
+            (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x06,
+            (byte) 0x13, (byte) 0x02, (byte) 0x55, (byte) 0x53, (byte) 0x31, (byte) 0x0b,
+            (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+            (byte) 0x08, (byte) 0x13, (byte) 0x02, (byte) 0x43, (byte) 0x41, (byte) 0x31,
+            (byte) 0x16, (byte) 0x30, (byte) 0x14, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x04, (byte) 0x07, (byte) 0x13, (byte) 0x0d, (byte) 0x4d, (byte) 0x6f,
+            (byte) 0x75, (byte) 0x6e, (byte) 0x74, (byte) 0x61, (byte) 0x69, (byte) 0x6e,
+            (byte) 0x20, (byte) 0x56, (byte) 0x69, (byte) 0x65, (byte) 0x77, (byte) 0x31,
+            (byte) 0x1b, (byte) 0x30, (byte) 0x19, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x04, (byte) 0x0a, (byte) 0x13, (byte) 0x12, (byte) 0x41, (byte) 0x6e,
+            (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64, (byte) 0x20,
+            (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x20, (byte) 0x43,
+            (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x73, (byte) 0x30, (byte) 0x1e,
+            (byte) 0x17, (byte) 0x0d, (byte) 0x31, (byte) 0x32, (byte) 0x30, (byte) 0x38,
+            (byte) 0x31, (byte) 0x34, (byte) 0x32, (byte) 0x33, (byte) 0x32, (byte) 0x35,
+            (byte) 0x34, (byte) 0x38, (byte) 0x5a, (byte) 0x17, (byte) 0x0d, (byte) 0x32,
+            (byte) 0x32, (byte) 0x30, (byte) 0x38, (byte) 0x31, (byte) 0x32, (byte) 0x32,
+            (byte) 0x33, (byte) 0x32, (byte) 0x35, (byte) 0x34, (byte) 0x38, (byte) 0x5a,
+            (byte) 0x30, (byte) 0x55, (byte) 0x31, (byte) 0x0b, (byte) 0x30, (byte) 0x09,
+            (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x06, (byte) 0x13,
+            (byte) 0x02, (byte) 0x55, (byte) 0x53, (byte) 0x31, (byte) 0x0b, (byte) 0x30,
+            (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x08,
+            (byte) 0x13, (byte) 0x02, (byte) 0x43, (byte) 0x41, (byte) 0x31, (byte) 0x1b,
+            (byte) 0x30, (byte) 0x19, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+            (byte) 0x0a, (byte) 0x13, (byte) 0x12, (byte) 0x41, (byte) 0x6e, (byte) 0x64,
+            (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64, (byte) 0x20, (byte) 0x54,
+            (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x20, (byte) 0x43, (byte) 0x61,
+            (byte) 0x73, (byte) 0x65, (byte) 0x73, (byte) 0x31, (byte) 0x1c, (byte) 0x30,
+            (byte) 0x1a, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x03,
+            (byte) 0x13, (byte) 0x13, (byte) 0x73, (byte) 0x65, (byte) 0x72, (byte) 0x76,
+            (byte) 0x65, (byte) 0x72, (byte) 0x31, (byte) 0x2e, (byte) 0x65, (byte) 0x78,
+            (byte) 0x61, (byte) 0x6d, (byte) 0x70, (byte) 0x6c, (byte) 0x65, (byte) 0x2e,
+            (byte) 0x63, (byte) 0x6f, (byte) 0x6d, (byte) 0x30, (byte) 0x81, (byte) 0x9f,
+            (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86,
+            (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01,
+            (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x03, (byte) 0x81, (byte) 0x8d,
+            (byte) 0x00, (byte) 0x30, (byte) 0x81, (byte) 0x89, (byte) 0x02, (byte) 0x81,
+            (byte) 0x81, (byte) 0x00, (byte) 0xce, (byte) 0x29, (byte) 0xeb, (byte) 0xf6,
+            (byte) 0x5b, (byte) 0x25, (byte) 0xdc, (byte) 0xa1, (byte) 0xa6, (byte) 0x2c,
+            (byte) 0x66, (byte) 0xcb, (byte) 0x20, (byte) 0x90, (byte) 0x27, (byte) 0x86,
+            (byte) 0x8a, (byte) 0x44, (byte) 0x71, (byte) 0x50, (byte) 0xda, (byte) 0xd3,
+            (byte) 0x02, (byte) 0x77, (byte) 0x55, (byte) 0xe9, (byte) 0xe8, (byte) 0x08,
+            (byte) 0xf3, (byte) 0x36, (byte) 0x9a, (byte) 0xae, (byte) 0xab, (byte) 0x04,
+            (byte) 0x6d, (byte) 0x00, (byte) 0x99, (byte) 0xbf, (byte) 0x7d, (byte) 0x0f,
+            (byte) 0x67, (byte) 0x8b, (byte) 0x1d, (byte) 0xd4, (byte) 0x2b, (byte) 0x7c,
+            (byte) 0xcb, (byte) 0xcd, (byte) 0x33, (byte) 0xc7, (byte) 0x84, (byte) 0x30,
+            (byte) 0xe2, (byte) 0x45, (byte) 0x21, (byte) 0xb3, (byte) 0x75, (byte) 0xf5,
+            (byte) 0x79, (byte) 0x02, (byte) 0xda, (byte) 0x50, (byte) 0xa3, (byte) 0x8b,
+            (byte) 0xce, (byte) 0xc3, (byte) 0x8e, (byte) 0x0f, (byte) 0x25, (byte) 0xeb,
+            (byte) 0x08, (byte) 0x2c, (byte) 0xdd, (byte) 0x1c, (byte) 0xcf, (byte) 0xff,
+            (byte) 0x3b, (byte) 0xde, (byte) 0xb6, (byte) 0xaa, (byte) 0x2a, (byte) 0xa9,
+            (byte) 0xc4, (byte) 0x8a, (byte) 0x24, (byte) 0x24, (byte) 0xe6, (byte) 0x29,
+            (byte) 0x0d, (byte) 0x98, (byte) 0x4c, (byte) 0x32, (byte) 0xa1, (byte) 0x7b,
+            (byte) 0x23, (byte) 0x2b, (byte) 0x42, (byte) 0x30, (byte) 0xee, (byte) 0x78,
+            (byte) 0x08, (byte) 0x47, (byte) 0xad, (byte) 0xf2, (byte) 0x96, (byte) 0xd5,
+            (byte) 0xf1, (byte) 0x62, (byte) 0x42, (byte) 0x2d, (byte) 0x35, (byte) 0x19,
+            (byte) 0xb4, (byte) 0x3c, (byte) 0xc9, (byte) 0xc3, (byte) 0x5f, (byte) 0x03,
+            (byte) 0x16, (byte) 0x3a, (byte) 0x23, (byte) 0xac, (byte) 0xcb, (byte) 0xce,
+            (byte) 0x9e, (byte) 0x51, (byte) 0x2e, (byte) 0x6d, (byte) 0x02, (byte) 0x03,
+            (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0xa3, (byte) 0x7b, (byte) 0x30,
+            (byte) 0x79, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x1d, (byte) 0x13, (byte) 0x04, (byte) 0x02, (byte) 0x30, (byte) 0x00,
+            (byte) 0x30, (byte) 0x2c, (byte) 0x06, (byte) 0x09, (byte) 0x60, (byte) 0x86,
+            (byte) 0x48, (byte) 0x01, (byte) 0x86, (byte) 0xf8, (byte) 0x42, (byte) 0x01,
+            (byte) 0x0d, (byte) 0x04, (byte) 0x1f, (byte) 0x16, (byte) 0x1d, (byte) 0x4f,
+            (byte) 0x70, (byte) 0x65, (byte) 0x6e, (byte) 0x53, (byte) 0x53, (byte) 0x4c,
+            (byte) 0x20, (byte) 0x47, (byte) 0x65, (byte) 0x6e, (byte) 0x65, (byte) 0x72,
+            (byte) 0x61, (byte) 0x74, (byte) 0x65, (byte) 0x64, (byte) 0x20, (byte) 0x43,
+            (byte) 0x65, (byte) 0x72, (byte) 0x74, (byte) 0x69, (byte) 0x66, (byte) 0x69,
+            (byte) 0x63, (byte) 0x61, (byte) 0x74, (byte) 0x65, (byte) 0x30, (byte) 0x1d,
+            (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x0e, (byte) 0x04,
+            (byte) 0x16, (byte) 0x04, (byte) 0x14, (byte) 0x32, (byte) 0xa1, (byte) 0x1e,
+            (byte) 0x6b, (byte) 0x69, (byte) 0x04, (byte) 0xfe, (byte) 0xb3, (byte) 0xcd,
+            (byte) 0xf8, (byte) 0xbb, (byte) 0x14, (byte) 0xcd, (byte) 0xff, (byte) 0xd4,
+            (byte) 0x16, (byte) 0xc3, (byte) 0xab, (byte) 0x44, (byte) 0x2f, (byte) 0x30,
+            (byte) 0x1f, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x23,
+            (byte) 0x04, (byte) 0x18, (byte) 0x30, (byte) 0x16, (byte) 0x80, (byte) 0x14,
+            (byte) 0x33, (byte) 0x05, (byte) 0xee, (byte) 0xfe, (byte) 0x6f, (byte) 0x60,
+            (byte) 0xc7, (byte) 0xf9, (byte) 0xa9, (byte) 0xd2, (byte) 0x73, (byte) 0x5c,
+            (byte) 0x8f, (byte) 0x6d, (byte) 0xa2, (byte) 0x2f, (byte) 0x97, (byte) 0x8e,
+            (byte) 0x5d, (byte) 0x51, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09,
+            (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d,
+            (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x05, (byte) 0x00, (byte) 0x03,
+            (byte) 0x81, (byte) 0x81, (byte) 0x00, (byte) 0x46, (byte) 0x42, (byte) 0xef,
+            (byte) 0x56, (byte) 0x89, (byte) 0x78, (byte) 0x90, (byte) 0x38, (byte) 0x24,
+            (byte) 0x9f, (byte) 0x8c, (byte) 0x7a, (byte) 0xce, (byte) 0x7a, (byte) 0xa5,
+            (byte) 0xb5, (byte) 0x1e, (byte) 0x74, (byte) 0x96, (byte) 0x34, (byte) 0x49,
+            (byte) 0x8b, (byte) 0xed, (byte) 0x44, (byte) 0xb3, (byte) 0xc9, (byte) 0x05,
+            (byte) 0xd7, (byte) 0x48, (byte) 0x55, (byte) 0x52, (byte) 0x59, (byte) 0x15,
+            (byte) 0x0b, (byte) 0xaa, (byte) 0x16, (byte) 0x86, (byte) 0xd2, (byte) 0x8e,
+            (byte) 0x16, (byte) 0x99, (byte) 0xe8, (byte) 0x5f, (byte) 0x11, (byte) 0x71,
+            (byte) 0x42, (byte) 0x55, (byte) 0xd1, (byte) 0xc4, (byte) 0x6f, (byte) 0x2e,
+            (byte) 0xa9, (byte) 0x64, (byte) 0x6f, (byte) 0xd8, (byte) 0xfd, (byte) 0x43,
+            (byte) 0x13, (byte) 0x24, (byte) 0xaa, (byte) 0x67, (byte) 0xe6, (byte) 0xf5,
+            (byte) 0xca, (byte) 0x80, (byte) 0x5e, (byte) 0x3a, (byte) 0x3e, (byte) 0xcc,
+            (byte) 0x4f, (byte) 0xba, (byte) 0x87, (byte) 0xe6, (byte) 0xae, (byte) 0xbf,
+            (byte) 0x8f, (byte) 0xd5, (byte) 0x28, (byte) 0x38, (byte) 0x58, (byte) 0x30,
+            (byte) 0x24, (byte) 0xf6, (byte) 0x53, (byte) 0x5b, (byte) 0x41, (byte) 0x53,
+            (byte) 0xe6, (byte) 0x45, (byte) 0xbc, (byte) 0xbe, (byte) 0xe6, (byte) 0xbb,
+            (byte) 0x5d, (byte) 0xd8, (byte) 0xa7, (byte) 0xf9, (byte) 0x64, (byte) 0x99,
+            (byte) 0x04, (byte) 0x43, (byte) 0x75, (byte) 0xd7, (byte) 0x2d, (byte) 0x32,
+            (byte) 0x0a, (byte) 0x94, (byte) 0xaf, (byte) 0x06, (byte) 0x34, (byte) 0xae,
+            (byte) 0x46, (byte) 0xbd, (byte) 0xda, (byte) 0x00, (byte) 0x0e, (byte) 0x25,
+            (byte) 0xc2, (byte) 0xf7, (byte) 0xc9, (byte) 0xc3, (byte) 0x65, (byte) 0xd2,
+            (byte) 0x08, (byte) 0x41, (byte) 0x0a, (byte) 0xf3, (byte) 0x72
+    };
+
+    /**
+     * Generated from above and converted with:
+     *
+     * openssl x509 -outform d -in cacert.pem | xxd -i | sed 's/0x/(byte) 0x/g'
+     */
+    private static final byte[] FAKE_RSA_CA_1 = {
+            (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0xce, (byte) 0x30, (byte) 0x82,
+            (byte) 0x02, (byte) 0x37, (byte) 0xa0, (byte) 0x03, (byte) 0x02, (byte) 0x01,
+            (byte) 0x02, (byte) 0x02, (byte) 0x09, (byte) 0x00, (byte) 0xe1, (byte) 0x6a,
+            (byte) 0xa2, (byte) 0xf4, (byte) 0x2e, (byte) 0x55, (byte) 0x48, (byte) 0x0a,
+            (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86,
+            (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01,
+            (byte) 0x05, (byte) 0x05, (byte) 0x00, (byte) 0x30, (byte) 0x4f, (byte) 0x31,
+            (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x04, (byte) 0x06, (byte) 0x13, (byte) 0x02, (byte) 0x55, (byte) 0x53,
+            (byte) 0x31, (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03,
+            (byte) 0x55, (byte) 0x04, (byte) 0x08, (byte) 0x13, (byte) 0x02, (byte) 0x43,
+            (byte) 0x41, (byte) 0x31, (byte) 0x16, (byte) 0x30, (byte) 0x14, (byte) 0x06,
+            (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x07, (byte) 0x13, (byte) 0x0d,
+            (byte) 0x4d, (byte) 0x6f, (byte) 0x75, (byte) 0x6e, (byte) 0x74, (byte) 0x61,
+            (byte) 0x69, (byte) 0x6e, (byte) 0x20, (byte) 0x56, (byte) 0x69, (byte) 0x65,
+            (byte) 0x77, (byte) 0x31, (byte) 0x1b, (byte) 0x30, (byte) 0x19, (byte) 0x06,
+            (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x13, (byte) 0x12,
+            (byte) 0x41, (byte) 0x6e, (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69,
+            (byte) 0x64, (byte) 0x20, (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74,
+            (byte) 0x20, (byte) 0x43, (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x73,
+            (byte) 0x30, (byte) 0x1e, (byte) 0x17, (byte) 0x0d, (byte) 0x31, (byte) 0x32,
+            (byte) 0x30, (byte) 0x38, (byte) 0x31, (byte) 0x34, (byte) 0x31, (byte) 0x36,
+            (byte) 0x35, (byte) 0x35, (byte) 0x34, (byte) 0x34, (byte) 0x5a, (byte) 0x17,
+            (byte) 0x0d, (byte) 0x32, (byte) 0x32, (byte) 0x30, (byte) 0x38, (byte) 0x31,
+            (byte) 0x32, (byte) 0x31, (byte) 0x36, (byte) 0x35, (byte) 0x35, (byte) 0x34,
+            (byte) 0x34, (byte) 0x5a, (byte) 0x30, (byte) 0x4f, (byte) 0x31, (byte) 0x0b,
+            (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+            (byte) 0x06, (byte) 0x13, (byte) 0x02, (byte) 0x55, (byte) 0x53, (byte) 0x31,
+            (byte) 0x0b, (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x04, (byte) 0x08, (byte) 0x13, (byte) 0x02, (byte) 0x43, (byte) 0x41,
+            (byte) 0x31, (byte) 0x16, (byte) 0x30, (byte) 0x14, (byte) 0x06, (byte) 0x03,
+            (byte) 0x55, (byte) 0x04, (byte) 0x07, (byte) 0x13, (byte) 0x0d, (byte) 0x4d,
+            (byte) 0x6f, (byte) 0x75, (byte) 0x6e, (byte) 0x74, (byte) 0x61, (byte) 0x69,
+            (byte) 0x6e, (byte) 0x20, (byte) 0x56, (byte) 0x69, (byte) 0x65, (byte) 0x77,
+            (byte) 0x31, (byte) 0x1b, (byte) 0x30, (byte) 0x19, (byte) 0x06, (byte) 0x03,
+            (byte) 0x55, (byte) 0x04, (byte) 0x0a, (byte) 0x13, (byte) 0x12, (byte) 0x41,
+            (byte) 0x6e, (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64,
+            (byte) 0x20, (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x20,
+            (byte) 0x43, (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x73, (byte) 0x30,
+            (byte) 0x81, (byte) 0x9f, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09,
+            (byte) 0x2a, (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d,
+            (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x03,
+            (byte) 0x81, (byte) 0x8d, (byte) 0x00, (byte) 0x30, (byte) 0x81, (byte) 0x89,
+            (byte) 0x02, (byte) 0x81, (byte) 0x81, (byte) 0x00, (byte) 0xa3, (byte) 0x72,
+            (byte) 0xab, (byte) 0xd0, (byte) 0xe4, (byte) 0xad, (byte) 0x2f, (byte) 0xe7,
+            (byte) 0xe2, (byte) 0x79, (byte) 0x07, (byte) 0x36, (byte) 0x3d, (byte) 0x0c,
+            (byte) 0x8d, (byte) 0x42, (byte) 0x9a, (byte) 0x0a, (byte) 0x33, (byte) 0x64,
+            (byte) 0xb3, (byte) 0xcd, (byte) 0xb2, (byte) 0xd7, (byte) 0x3a, (byte) 0x42,
+            (byte) 0x06, (byte) 0x77, (byte) 0x45, (byte) 0x29, (byte) 0xe9, (byte) 0xcb,
+            (byte) 0xb7, (byte) 0x4a, (byte) 0xd6, (byte) 0xee, (byte) 0xad, (byte) 0x01,
+            (byte) 0x91, (byte) 0x9b, (byte) 0x0c, (byte) 0x59, (byte) 0xa1, (byte) 0x03,
+            (byte) 0xfa, (byte) 0xf0, (byte) 0x5a, (byte) 0x7c, (byte) 0x4f, (byte) 0xf7,
+            (byte) 0x8d, (byte) 0x36, (byte) 0x0f, (byte) 0x1f, (byte) 0x45, (byte) 0x7d,
+            (byte) 0x1b, (byte) 0x31, (byte) 0xa1, (byte) 0x35, (byte) 0x0b, (byte) 0x00,
+            (byte) 0xed, (byte) 0x7a, (byte) 0xb6, (byte) 0xc8, (byte) 0x4e, (byte) 0xa9,
+            (byte) 0x86, (byte) 0x4c, (byte) 0x7b, (byte) 0x99, (byte) 0x57, (byte) 0x41,
+            (byte) 0x12, (byte) 0xef, (byte) 0x6b, (byte) 0xbc, (byte) 0x3d, (byte) 0x60,
+            (byte) 0xf2, (byte) 0x99, (byte) 0x1a, (byte) 0xcd, (byte) 0xed, (byte) 0x56,
+            (byte) 0xa4, (byte) 0xe5, (byte) 0x36, (byte) 0x9f, (byte) 0x24, (byte) 0x1f,
+            (byte) 0xdc, (byte) 0x89, (byte) 0x40, (byte) 0xc8, (byte) 0x99, (byte) 0x92,
+            (byte) 0xab, (byte) 0x4a, (byte) 0xb5, (byte) 0x61, (byte) 0x45, (byte) 0x62,
+            (byte) 0xff, (byte) 0xa3, (byte) 0x45, (byte) 0x65, (byte) 0xaf, (byte) 0xf6,
+            (byte) 0x27, (byte) 0x30, (byte) 0x51, (byte) 0x0e, (byte) 0x0e, (byte) 0xeb,
+            (byte) 0x79, (byte) 0x0c, (byte) 0xbe, (byte) 0xb3, (byte) 0x0a, (byte) 0x6f,
+            (byte) 0x29, (byte) 0x06, (byte) 0xdc, (byte) 0x2f, (byte) 0x6b, (byte) 0x51,
+            (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0xa3,
+            (byte) 0x81, (byte) 0xb1, (byte) 0x30, (byte) 0x81, (byte) 0xae, (byte) 0x30,
+            (byte) 0x1d, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x0e,
+            (byte) 0x04, (byte) 0x16, (byte) 0x04, (byte) 0x14, (byte) 0x33, (byte) 0x05,
+            (byte) 0xee, (byte) 0xfe, (byte) 0x6f, (byte) 0x60, (byte) 0xc7, (byte) 0xf9,
+            (byte) 0xa9, (byte) 0xd2, (byte) 0x73, (byte) 0x5c, (byte) 0x8f, (byte) 0x6d,
+            (byte) 0xa2, (byte) 0x2f, (byte) 0x97, (byte) 0x8e, (byte) 0x5d, (byte) 0x51,
+            (byte) 0x30, (byte) 0x7f, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x1d,
+            (byte) 0x23, (byte) 0x04, (byte) 0x78, (byte) 0x30, (byte) 0x76, (byte) 0x80,
+            (byte) 0x14, (byte) 0x33, (byte) 0x05, (byte) 0xee, (byte) 0xfe, (byte) 0x6f,
+            (byte) 0x60, (byte) 0xc7, (byte) 0xf9, (byte) 0xa9, (byte) 0xd2, (byte) 0x73,
+            (byte) 0x5c, (byte) 0x8f, (byte) 0x6d, (byte) 0xa2, (byte) 0x2f, (byte) 0x97,
+            (byte) 0x8e, (byte) 0x5d, (byte) 0x51, (byte) 0xa1, (byte) 0x53, (byte) 0xa4,
+            (byte) 0x51, (byte) 0x30, (byte) 0x4f, (byte) 0x31, (byte) 0x0b, (byte) 0x30,
+            (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04, (byte) 0x06,
+            (byte) 0x13, (byte) 0x02, (byte) 0x55, (byte) 0x53, (byte) 0x31, (byte) 0x0b,
+            (byte) 0x30, (byte) 0x09, (byte) 0x06, (byte) 0x03, (byte) 0x55, (byte) 0x04,
+            (byte) 0x08, (byte) 0x13, (byte) 0x02, (byte) 0x43, (byte) 0x41, (byte) 0x31,
+            (byte) 0x16, (byte) 0x30, (byte) 0x14, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x04, (byte) 0x07, (byte) 0x13, (byte) 0x0d, (byte) 0x4d, (byte) 0x6f,
+            (byte) 0x75, (byte) 0x6e, (byte) 0x74, (byte) 0x61, (byte) 0x69, (byte) 0x6e,
+            (byte) 0x20, (byte) 0x56, (byte) 0x69, (byte) 0x65, (byte) 0x77, (byte) 0x31,
+            (byte) 0x1b, (byte) 0x30, (byte) 0x19, (byte) 0x06, (byte) 0x03, (byte) 0x55,
+            (byte) 0x04, (byte) 0x0a, (byte) 0x13, (byte) 0x12, (byte) 0x41, (byte) 0x6e,
+            (byte) 0x64, (byte) 0x72, (byte) 0x6f, (byte) 0x69, (byte) 0x64, (byte) 0x20,
+            (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x20, (byte) 0x43,
+            (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x73, (byte) 0x82, (byte) 0x09,
+            (byte) 0x00, (byte) 0xe1, (byte) 0x6a, (byte) 0xa2, (byte) 0xf4, (byte) 0x2e,
+            (byte) 0x55, (byte) 0x48, (byte) 0x0a, (byte) 0x30, (byte) 0x0c, (byte) 0x06,
+            (byte) 0x03, (byte) 0x55, (byte) 0x1d, (byte) 0x13, (byte) 0x04, (byte) 0x05,
+            (byte) 0x30, (byte) 0x03, (byte) 0x01, (byte) 0x01, (byte) 0xff, (byte) 0x30,
+            (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, (byte) 0x86, (byte) 0x48,
+            (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, (byte) 0x01, (byte) 0x05,
+            (byte) 0x05, (byte) 0x00, (byte) 0x03, (byte) 0x81, (byte) 0x81, (byte) 0x00,
+            (byte) 0x8c, (byte) 0x30, (byte) 0x42, (byte) 0xfa, (byte) 0xeb, (byte) 0x1a,
+            (byte) 0x26, (byte) 0xeb, (byte) 0xda, (byte) 0x56, (byte) 0x32, (byte) 0xf2,
+            (byte) 0x9d, (byte) 0xa5, (byte) 0x24, (byte) 0xd8, (byte) 0x3a, (byte) 0xda,
+            (byte) 0x30, (byte) 0xa6, (byte) 0x8b, (byte) 0x46, (byte) 0xfe, (byte) 0xfe,
+            (byte) 0xdb, (byte) 0xf1, (byte) 0xe6, (byte) 0xe1, (byte) 0x7c, (byte) 0x1b,
+            (byte) 0xe7, (byte) 0x77, (byte) 0x00, (byte) 0xa1, (byte) 0x1c, (byte) 0x19,
+            (byte) 0x17, (byte) 0x73, (byte) 0xb0, (byte) 0xf0, (byte) 0x9d, (byte) 0xf3,
+            (byte) 0x4f, (byte) 0xb6, (byte) 0xbc, (byte) 0xc7, (byte) 0x47, (byte) 0x85,
+            (byte) 0x2a, (byte) 0x4a, (byte) 0xa1, (byte) 0xa5, (byte) 0x58, (byte) 0xf5,
+            (byte) 0xc5, (byte) 0x1a, (byte) 0x51, (byte) 0xb1, (byte) 0x04, (byte) 0x80,
+            (byte) 0xee, (byte) 0x3a, (byte) 0xec, (byte) 0x2f, (byte) 0xe1, (byte) 0xfd,
+            (byte) 0x58, (byte) 0xeb, (byte) 0xed, (byte) 0x82, (byte) 0x9e, (byte) 0x38,
+            (byte) 0xa3, (byte) 0x24, (byte) 0x75, (byte) 0xf7, (byte) 0x3e, (byte) 0xc2,
+            (byte) 0xc5, (byte) 0x27, (byte) 0xeb, (byte) 0x6f, (byte) 0x7b, (byte) 0x50,
+            (byte) 0xda, (byte) 0x43, (byte) 0xdc, (byte) 0x3b, (byte) 0x0b, (byte) 0x6f,
+            (byte) 0x78, (byte) 0x8f, (byte) 0xb0, (byte) 0x66, (byte) 0xe1, (byte) 0x12,
+            (byte) 0x87, (byte) 0x5f, (byte) 0x97, (byte) 0x7b, (byte) 0xca, (byte) 0x14,
+            (byte) 0x79, (byte) 0xf7, (byte) 0xe8, (byte) 0x6c, (byte) 0x72, (byte) 0xdb,
+            (byte) 0x91, (byte) 0x65, (byte) 0x17, (byte) 0x54, (byte) 0xe0, (byte) 0x74,
+            (byte) 0x1d, (byte) 0xac, (byte) 0x47, (byte) 0x04, (byte) 0x12, (byte) 0xe0,
+            (byte) 0xc3, (byte) 0x66, (byte) 0x19, (byte) 0x05, (byte) 0x2e, (byte) 0x7e,
+            (byte) 0xf1, (byte) 0x61
+    };
+
+    /**
+     * Generated from above and converted with:
+     *
+     * openssl pkcs8 -topk8 -outform d -in userkey.pem -nocrypt | xxd -i | sed 's/0x/(byte) 0x/g'
+     */
+    private static final byte[] FAKE_RSA_KEY_1 = new byte[] {
+            (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x78, (byte) 0x02, (byte) 0x01,
+            (byte) 0x00, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a,
+            (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01,
+            (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x82,
+            (byte) 0x02, (byte) 0x62, (byte) 0x30, (byte) 0x82, (byte) 0x02, (byte) 0x5e,
+            (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x02, (byte) 0x81, (byte) 0x81,
+            (byte) 0x00, (byte) 0xce, (byte) 0x29, (byte) 0xeb, (byte) 0xf6, (byte) 0x5b,
+            (byte) 0x25, (byte) 0xdc, (byte) 0xa1, (byte) 0xa6, (byte) 0x2c, (byte) 0x66,
+            (byte) 0xcb, (byte) 0x20, (byte) 0x90, (byte) 0x27, (byte) 0x86, (byte) 0x8a,
+            (byte) 0x44, (byte) 0x71, (byte) 0x50, (byte) 0xda, (byte) 0xd3, (byte) 0x02,
+            (byte) 0x77, (byte) 0x55, (byte) 0xe9, (byte) 0xe8, (byte) 0x08, (byte) 0xf3,
+            (byte) 0x36, (byte) 0x9a, (byte) 0xae, (byte) 0xab, (byte) 0x04, (byte) 0x6d,
+            (byte) 0x00, (byte) 0x99, (byte) 0xbf, (byte) 0x7d, (byte) 0x0f, (byte) 0x67,
+            (byte) 0x8b, (byte) 0x1d, (byte) 0xd4, (byte) 0x2b, (byte) 0x7c, (byte) 0xcb,
+            (byte) 0xcd, (byte) 0x33, (byte) 0xc7, (byte) 0x84, (byte) 0x30, (byte) 0xe2,
+            (byte) 0x45, (byte) 0x21, (byte) 0xb3, (byte) 0x75, (byte) 0xf5, (byte) 0x79,
+            (byte) 0x02, (byte) 0xda, (byte) 0x50, (byte) 0xa3, (byte) 0x8b, (byte) 0xce,
+            (byte) 0xc3, (byte) 0x8e, (byte) 0x0f, (byte) 0x25, (byte) 0xeb, (byte) 0x08,
+            (byte) 0x2c, (byte) 0xdd, (byte) 0x1c, (byte) 0xcf, (byte) 0xff, (byte) 0x3b,
+            (byte) 0xde, (byte) 0xb6, (byte) 0xaa, (byte) 0x2a, (byte) 0xa9, (byte) 0xc4,
+            (byte) 0x8a, (byte) 0x24, (byte) 0x24, (byte) 0xe6, (byte) 0x29, (byte) 0x0d,
+            (byte) 0x98, (byte) 0x4c, (byte) 0x32, (byte) 0xa1, (byte) 0x7b, (byte) 0x23,
+            (byte) 0x2b, (byte) 0x42, (byte) 0x30, (byte) 0xee, (byte) 0x78, (byte) 0x08,
+            (byte) 0x47, (byte) 0xad, (byte) 0xf2, (byte) 0x96, (byte) 0xd5, (byte) 0xf1,
+            (byte) 0x62, (byte) 0x42, (byte) 0x2d, (byte) 0x35, (byte) 0x19, (byte) 0xb4,
+            (byte) 0x3c, (byte) 0xc9, (byte) 0xc3, (byte) 0x5f, (byte) 0x03, (byte) 0x16,
+            (byte) 0x3a, (byte) 0x23, (byte) 0xac, (byte) 0xcb, (byte) 0xce, (byte) 0x9e,
+            (byte) 0x51, (byte) 0x2e, (byte) 0x6d, (byte) 0x02, (byte) 0x03, (byte) 0x01,
+            (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x81, (byte) 0x80, (byte) 0x16,
+            (byte) 0x59, (byte) 0xc3, (byte) 0x24, (byte) 0x1d, (byte) 0x33, (byte) 0x98,
+            (byte) 0x9c, (byte) 0xc9, (byte) 0xc8, (byte) 0x2c, (byte) 0x88, (byte) 0xbf,
+            (byte) 0x0a, (byte) 0x01, (byte) 0xce, (byte) 0xfb, (byte) 0x34, (byte) 0x7a,
+            (byte) 0x58, (byte) 0x7a, (byte) 0xb0, (byte) 0xbf, (byte) 0xa6, (byte) 0xb2,
+            (byte) 0x60, (byte) 0xbe, (byte) 0x70, (byte) 0x21, (byte) 0xf5, (byte) 0xfc,
+            (byte) 0x85, (byte) 0x0d, (byte) 0x33, (byte) 0x58, (byte) 0xa1, (byte) 0xe5,
+            (byte) 0x09, (byte) 0x36, (byte) 0x84, (byte) 0xb2, (byte) 0x04, (byte) 0x0a,
+            (byte) 0x02, (byte) 0xd3, (byte) 0x88, (byte) 0x1f, (byte) 0x0c, (byte) 0x2b,
+            (byte) 0x1d, (byte) 0xe9, (byte) 0x3d, (byte) 0xe7, (byte) 0x79, (byte) 0xf9,
+            (byte) 0x32, (byte) 0x5c, (byte) 0x8a, (byte) 0x75, (byte) 0x49, (byte) 0x12,
+            (byte) 0xe4, (byte) 0x05, (byte) 0x26, (byte) 0xd4, (byte) 0x2e, (byte) 0x9e,
+            (byte) 0x1f, (byte) 0xcc, (byte) 0x54, (byte) 0xad, (byte) 0x33, (byte) 0x8d,
+            (byte) 0x99, (byte) 0x00, (byte) 0xdc, (byte) 0xf5, (byte) 0xb4, (byte) 0xa2,
+            (byte) 0x2f, (byte) 0xba, (byte) 0xe5, (byte) 0x62, (byte) 0x30, (byte) 0x6d,
+            (byte) 0xe6, (byte) 0x3d, (byte) 0xeb, (byte) 0x24, (byte) 0xc2, (byte) 0xdc,
+            (byte) 0x5f, (byte) 0xb7, (byte) 0x16, (byte) 0x35, (byte) 0xa3, (byte) 0x98,
+            (byte) 0x98, (byte) 0xa8, (byte) 0xef, (byte) 0xe8, (byte) 0xc4, (byte) 0x96,
+            (byte) 0x6d, (byte) 0x38, (byte) 0xab, (byte) 0x26, (byte) 0x6d, (byte) 0x30,
+            (byte) 0xc2, (byte) 0xa0, (byte) 0x44, (byte) 0xe4, (byte) 0xff, (byte) 0x7e,
+            (byte) 0xbe, (byte) 0x7c, (byte) 0x33, (byte) 0xa5, (byte) 0x10, (byte) 0xad,
+            (byte) 0xd7, (byte) 0x1e, (byte) 0x13, (byte) 0x20, (byte) 0xb3, (byte) 0x1f,
+            (byte) 0x41, (byte) 0x02, (byte) 0x41, (byte) 0x00, (byte) 0xf1, (byte) 0x89,
+            (byte) 0x07, (byte) 0x0f, (byte) 0xe8, (byte) 0xcf, (byte) 0xab, (byte) 0x13,
+            (byte) 0x2a, (byte) 0x8f, (byte) 0x88, (byte) 0x80, (byte) 0x11, (byte) 0x9a,
+            (byte) 0x79, (byte) 0xb6, (byte) 0x59, (byte) 0x3a, (byte) 0x50, (byte) 0x6e,
+            (byte) 0x57, (byte) 0x37, (byte) 0xab, (byte) 0x2a, (byte) 0xd2, (byte) 0xaa,
+            (byte) 0xd9, (byte) 0x72, (byte) 0x73, (byte) 0xff, (byte) 0x8b, (byte) 0x47,
+            (byte) 0x76, (byte) 0xdd, (byte) 0xdc, (byte) 0xf5, (byte) 0x97, (byte) 0x44,
+            (byte) 0x3a, (byte) 0x78, (byte) 0xbe, (byte) 0x17, (byte) 0xb4, (byte) 0x22,
+            (byte) 0x6f, (byte) 0xe5, (byte) 0x23, (byte) 0x70, (byte) 0x1d, (byte) 0x10,
+            (byte) 0x5d, (byte) 0xba, (byte) 0x16, (byte) 0x81, (byte) 0xf1, (byte) 0x45,
+            (byte) 0xce, (byte) 0x30, (byte) 0xb4, (byte) 0xab, (byte) 0x80, (byte) 0xe4,
+            (byte) 0x98, (byte) 0x31, (byte) 0x02, (byte) 0x41, (byte) 0x00, (byte) 0xda,
+            (byte) 0x82, (byte) 0x9d, (byte) 0x3f, (byte) 0xca, (byte) 0x2f, (byte) 0xe1,
+            (byte) 0xd4, (byte) 0x86, (byte) 0x77, (byte) 0x48, (byte) 0xa6, (byte) 0xab,
+            (byte) 0xab, (byte) 0x1c, (byte) 0x42, (byte) 0x5c, (byte) 0xd5, (byte) 0xc7,
+            (byte) 0x46, (byte) 0x59, (byte) 0x91, (byte) 0x3f, (byte) 0xfc, (byte) 0xcc,
+            (byte) 0xec, (byte) 0xc2, (byte) 0x40, (byte) 0x12, (byte) 0x2c, (byte) 0x8d,
+            (byte) 0x1f, (byte) 0xa2, (byte) 0x18, (byte) 0x88, (byte) 0xee, (byte) 0x82,
+            (byte) 0x4a, (byte) 0x5a, (byte) 0x5e, (byte) 0x88, (byte) 0x20, (byte) 0xe3,
+            (byte) 0x7b, (byte) 0xe0, (byte) 0xd8, (byte) 0x3a, (byte) 0x52, (byte) 0x9a,
+            (byte) 0x26, (byte) 0x6a, (byte) 0x04, (byte) 0xec, (byte) 0xe8, (byte) 0xb9,
+            (byte) 0x48, (byte) 0x40, (byte) 0xe1, (byte) 0xe1, (byte) 0x83, (byte) 0xa6,
+            (byte) 0x67, (byte) 0xa6, (byte) 0xfd, (byte) 0x02, (byte) 0x41, (byte) 0x00,
+            (byte) 0x89, (byte) 0x72, (byte) 0x3e, (byte) 0xb0, (byte) 0x90, (byte) 0xfd,
+            (byte) 0x4c, (byte) 0x0e, (byte) 0xd6, (byte) 0x13, (byte) 0x63, (byte) 0xcb,
+            (byte) 0xed, (byte) 0x38, (byte) 0x88, (byte) 0xb6, (byte) 0x79, (byte) 0xc4,
+            (byte) 0x33, (byte) 0x6c, (byte) 0xf6, (byte) 0xf8, (byte) 0xd8, (byte) 0xd0,
+            (byte) 0xbf, (byte) 0x9d, (byte) 0x35, (byte) 0xac, (byte) 0x69, (byte) 0xd2,
+            (byte) 0x2b, (byte) 0xc1, (byte) 0xf9, (byte) 0x24, (byte) 0x7b, (byte) 0xce,
+            (byte) 0xcd, (byte) 0xcb, (byte) 0xa7, (byte) 0xb2, (byte) 0x7a, (byte) 0x0a,
+            (byte) 0x27, (byte) 0x19, (byte) 0xc9, (byte) 0xaf, (byte) 0x0d, (byte) 0x21,
+            (byte) 0x89, (byte) 0x88, (byte) 0x7c, (byte) 0xad, (byte) 0x9e, (byte) 0x8d,
+            (byte) 0x47, (byte) 0x6d, (byte) 0x3f, (byte) 0xce, (byte) 0x7b, (byte) 0xa1,
+            (byte) 0x74, (byte) 0xf1, (byte) 0xa0, (byte) 0xa1, (byte) 0x02, (byte) 0x41,
+            (byte) 0x00, (byte) 0xd9, (byte) 0xa8, (byte) 0xf5, (byte) 0xfe, (byte) 0xce,
+            (byte) 0xe6, (byte) 0x77, (byte) 0x6b, (byte) 0xfe, (byte) 0x2d, (byte) 0xe0,
+            (byte) 0x1e, (byte) 0xb6, (byte) 0x2e, (byte) 0x12, (byte) 0x4e, (byte) 0x40,
+            (byte) 0xaf, (byte) 0x6a, (byte) 0x7b, (byte) 0x37, (byte) 0x49, (byte) 0x2a,
+            (byte) 0x96, (byte) 0x25, (byte) 0x83, (byte) 0x49, (byte) 0xd4, (byte) 0x0c,
+            (byte) 0xc6, (byte) 0x78, (byte) 0x25, (byte) 0x24, (byte) 0x90, (byte) 0x90,
+            (byte) 0x06, (byte) 0x15, (byte) 0x9e, (byte) 0xfe, (byte) 0xf9, (byte) 0xdf,
+            (byte) 0x5b, (byte) 0xf3, (byte) 0x7e, (byte) 0x38, (byte) 0x70, (byte) 0xeb,
+            (byte) 0x57, (byte) 0xd0, (byte) 0xd9, (byte) 0xa7, (byte) 0x0e, (byte) 0x14,
+            (byte) 0xf7, (byte) 0x95, (byte) 0x68, (byte) 0xd5, (byte) 0xc8, (byte) 0xab,
+            (byte) 0x9d, (byte) 0x3a, (byte) 0x2b, (byte) 0x51, (byte) 0xf9, (byte) 0x02,
+            (byte) 0x41, (byte) 0x00, (byte) 0x96, (byte) 0xdf, (byte) 0xe9, (byte) 0x67,
+            (byte) 0x6c, (byte) 0xdc, (byte) 0x90, (byte) 0x14, (byte) 0xb4, (byte) 0x1d,
+            (byte) 0x22, (byte) 0x33, (byte) 0x4a, (byte) 0x31, (byte) 0xc1, (byte) 0x9d,
+            (byte) 0x2e, (byte) 0xff, (byte) 0x9a, (byte) 0x2a, (byte) 0x95, (byte) 0x4b,
+            (byte) 0x27, (byte) 0x74, (byte) 0xcb, (byte) 0x21, (byte) 0xc3, (byte) 0xd2,
+            (byte) 0x0b, (byte) 0xb2, (byte) 0x46, (byte) 0x87, (byte) 0xf8, (byte) 0x28,
+            (byte) 0x01, (byte) 0x8b, (byte) 0xd8, (byte) 0xb9, (byte) 0x4b, (byte) 0xcd,
+            (byte) 0x9a, (byte) 0x96, (byte) 0x41, (byte) 0x0e, (byte) 0x36, (byte) 0x6d,
+            (byte) 0x40, (byte) 0x42, (byte) 0xbc, (byte) 0xd9, (byte) 0xd3, (byte) 0x7b,
+            (byte) 0xbc, (byte) 0xa7, (byte) 0x92, (byte) 0x90, (byte) 0xdd, (byte) 0xa1,
+            (byte) 0x9c, (byte) 0xce, (byte) 0xa1, (byte) 0x87, (byte) 0x11, (byte) 0x51
+    };
+
+    private WebView mWebView;
+    private CtsTestServer mWebServer;
+    private WebViewOnUiThread mOnUiThread;
+
+    public WebViewSslTest() {
+        super("com.android.cts.webkit", WebViewCtsActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        final WebViewCtsActivity activity = getActivity();
+        mWebView = activity.getWebView();
+        if (mWebView != null) {
+            new PollingCheck() {
+                @Override
+                    protected boolean check() {
+                        return activity.hasWindowFocus();
+                }
+            }.run();
+            File f = activity.getFileStreamPath("snapshot");
+            if (f.exists()) {
+                f.delete();
+            }
+
+            mOnUiThread = new WebViewOnUiThread(this, mWebView);
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mOnUiThread != null) {
+            mOnUiThread.cleanUp();
+        }
+        if (mWebServer != null) {
+            stopWebServer();
+        }
+        super.tearDown();
+    }
+
+    private void startWebServer(boolean secure) throws Exception {
+        assertNull(mWebServer);
+        mWebServer = new CtsTestServer(getActivity(), secure);
+    }
+
+    private void stopWebServer() throws Exception {
+        assertNotNull(mWebServer);
+        ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
+        ThreadPolicy tmpPolicy = new ThreadPolicy.Builder(oldPolicy)
+                .permitNetwork()
+                .build();
+        StrictMode.setThreadPolicy(tmpPolicy);
+        mWebServer.shutdown();
+        mWebServer = null;
+        StrictMode.setThreadPolicy(oldPolicy);
+    }
+
+    @UiThreadTest
+    public void testInsecureSiteClearsCertificate() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+        final class MockWebViewClient extends WaitForLoadedClient {
+            public MockWebViewClient() {
+                super(mOnUiThread);
+            }
+            @Override
+            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
+                handler.proceed();
+            }
+        }
+
+        startWebServer(true);
+        mOnUiThread.setWebViewClient(new MockWebViewClient());
+        mOnUiThread.loadUrlAndWaitForCompletion(
+                mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL));
+        SslCertificate cert = mWebView.getCertificate();
+        assertNotNull(cert);
+        assertEquals("Android", cert.getIssuedTo().getUName());
+
+        stopWebServer();
+
+        startWebServer(false);
+        mOnUiThread.loadUrlAndWaitForCompletion(
+                mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL));
+        assertNull(mWebView.getCertificate());
+    }
+
+    @UiThreadTest
+    public void testSecureSiteSetsCertificate() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+        final class MockWebViewClient extends WaitForLoadedClient {
+            public MockWebViewClient() {
+                super(mOnUiThread);
+            }
+            @Override
+            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
+                handler.proceed();
+            }
+        }
+
+        startWebServer(false);
+        mOnUiThread.loadUrlAndWaitForCompletion(
+                mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL));
+        assertNull(mWebView.getCertificate());
+
+        stopWebServer();
+
+        startWebServer(true);
+        mOnUiThread.setWebViewClient(new MockWebViewClient());
+        mOnUiThread.loadUrlAndWaitForCompletion(
+                mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL));
+        SslCertificate cert = mWebView.getCertificate();
+        assertNotNull(cert);
+        assertEquals("Android", cert.getIssuedTo().getUName());
+    }
+
+    @UiThreadTest
+    public void testClearSslPreferences() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+        // Load the first page. We expect a call to
+        // WebViewClient.onReceivedSslError().
+        final SslErrorWebViewClient webViewClient = new SslErrorWebViewClient(mOnUiThread);
+        startWebServer(true);
+        final String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
+        mOnUiThread.setWebViewClient(webViewClient);
+        mOnUiThread.clearSslPreferences();
+        mOnUiThread.loadUrlAndWaitForCompletion(url);
+        assertTrue(webViewClient.wasOnReceivedSslErrorCalled());
+
+        // Load the page again. We expect another call to
+        // WebViewClient.onReceivedSslError() since we cleared sslpreferences.
+        mOnUiThread.clearSslPreferences();
+        webViewClient.resetWasOnReceivedSslErrorCalled();
+        mOnUiThread.loadUrlAndWaitForCompletion(url);
+        assertTrue(webViewClient.wasOnReceivedSslErrorCalled());
+        assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle());
+
+        // Load the page once again, without clearing the sslpreferences.
+        // Make sure we do not get the callback.
+        webViewClient.resetWasOnReceivedSslErrorCalled();
+        mOnUiThread.loadUrlAndWaitForCompletion(url);
+        assertFalse(webViewClient.wasOnReceivedSslErrorCalled());
+        assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle());
+    }
+
+    public void testOnReceivedSslError() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+        final class MockWebViewClient extends WaitForLoadedClient {
+            private String mErrorUrl;
+            private WebView mWebView;
+
+            public MockWebViewClient() {
+                super(mOnUiThread);
+            }
+            @Override
+            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
+                mWebView = view;
+                mErrorUrl = error.getUrl();
+                handler.proceed();
+            }
+            public String errorUrl() {
+                return mErrorUrl;
+            }
+            public WebView webView() {
+                return mWebView;
+            }
+        }
+
+        startWebServer(true);
+        final String errorUrl = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
+        final MockWebViewClient webViewClient = new MockWebViewClient();
+        mOnUiThread.setWebViewClient(webViewClient);
+        mOnUiThread.clearSslPreferences();
+        mOnUiThread.loadUrlAndWaitForCompletion(errorUrl);
+
+        assertEquals(mWebView, webViewClient.webView());
+        assertEquals(errorUrl, webViewClient.errorUrl());
+    }
+
+    public void testOnReceivedSslErrorProceed() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+        final class MockWebViewClient extends WaitForLoadedClient {
+            public MockWebViewClient() {
+                super(mOnUiThread);
+            }
+            @Override
+            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
+                handler.proceed();
+            }
+        }
+
+        startWebServer(true);
+        final String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
+        mOnUiThread.setWebViewClient(new MockWebViewClient());
+        mOnUiThread.loadUrlAndWaitForCompletion(url);
+        assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle());
+    }
+
+    public void testOnReceivedSslErrorCancel() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+        final class MockWebViewClient extends WaitForLoadedClient {
+            public MockWebViewClient() {
+                super(mOnUiThread);
+            }
+            @Override
+            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
+                handler.cancel();
+            }
+        }
+
+        startWebServer(true);
+        final String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
+        mOnUiThread.setWebViewClient(new MockWebViewClient());
+        mOnUiThread.clearSslPreferences();
+        mOnUiThread.loadUrlAndWaitForCompletion(url);
+        assertFalse(TestHtmlConstants.HELLO_WORLD_TITLE.equals(mOnUiThread.getTitle()));
+    }
+
+    public void testSslErrorProceedResponseReusedForSameHost() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+        // Load the first page. We expect a call to
+        // WebViewClient.onReceivedSslError().
+        final SslErrorWebViewClient webViewClient = new SslErrorWebViewClient(mOnUiThread);
+        startWebServer(true);
+        final String firstUrl = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL1);
+        mOnUiThread.setWebViewClient(webViewClient);
+        mOnUiThread.clearSslPreferences();
+        mOnUiThread.loadUrlAndWaitForCompletion(firstUrl);
+        assertTrue(webViewClient.wasOnReceivedSslErrorCalled());
+
+        // Load the second page. We don't expect a call to
+        // WebViewClient.onReceivedSslError(), but the page should load.
+        webViewClient.resetWasOnReceivedSslErrorCalled();
+        final String sameHostUrl = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL2);
+        mOnUiThread.loadUrlAndWaitForCompletion(sameHostUrl);
+        assertFalse(webViewClient.wasOnReceivedSslErrorCalled());
+        assertEquals("Second page", mOnUiThread.getTitle());
+    }
+
+    public void testSslErrorProceedResponseNotReusedForDifferentHost() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+        // Load the first page. We expect a call to
+        // WebViewClient.onReceivedSslError().
+        final SslErrorWebViewClient webViewClient = new SslErrorWebViewClient(mOnUiThread);
+        startWebServer(true);
+        final String firstUrl = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL1);
+        mOnUiThread.setWebViewClient(webViewClient);
+        mOnUiThread.clearSslPreferences();
+        mOnUiThread.loadUrlAndWaitForCompletion(firstUrl);
+        assertTrue(webViewClient.wasOnReceivedSslErrorCalled());
+
+        // Load the second page. We expect another call to
+        // WebViewClient.onReceivedSslError().
+        webViewClient.resetWasOnReceivedSslErrorCalled();
+        // The test server uses the host "localhost". "127.0.0.1" works as an
+        // alias, but will be considered unique by the WebView.
+        final String differentHostUrl = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL2).replace(
+                "localhost", "127.0.0.1");
+        mOnUiThread.loadUrlAndWaitForCompletion(differentHostUrl);
+        assertTrue(webViewClient.wasOnReceivedSslErrorCalled());
+        assertEquals("Second page", mOnUiThread.getTitle());
+    }
+
+    public void testSecureServerRequestingClientCertDoesNotCancelRequest() throws Throwable {
+        mWebServer = new CtsTestServer(getActivity(), CtsTestServer.SslMode.WANTS_CLIENT_AUTH);
+        final String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
+        final SslErrorWebViewClient webViewClient = new SslErrorWebViewClient(mOnUiThread);
+        mOnUiThread.setWebViewClient(webViewClient);
+        mOnUiThread.clearSslPreferences();
+        mOnUiThread.loadUrlAndWaitForCompletion(url);
+        // Page loaded OK...
+        assertTrue(webViewClient.wasOnReceivedSslErrorCalled());
+        assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle());
+        assertEquals(0, webViewClient.onReceivedErrorCode());
+    }
+
+    public void testSecureServerRequiringClientCertDoesCancelRequest() throws Throwable {
+        mWebServer = new CtsTestServer(getActivity(), CtsTestServer.SslMode.NEEDS_CLIENT_AUTH);
+        final String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
+        final SslErrorWebViewClient webViewClient = new SslErrorWebViewClient(mOnUiThread);
+        mOnUiThread.setWebViewClient(webViewClient);
+        mOnUiThread.clearSslPreferences();
+        mOnUiThread.loadUrlAndWaitForCompletion(url);
+        // Page NOT loaded OK...
+        // In this case, we must NOT have received the onReceivedSslError callback as that is for
+        // recoverable (e.g. server auth) errors, whereas failing mandatory client auth is non-
+        // recoverable and should drop straight through to a load error.
+        assertFalse(webViewClient.wasOnReceivedSslErrorCalled());
+        assertFalse(TestHtmlConstants.HELLO_WORLD_TITLE.equals(mOnUiThread.getTitle()));
+        assertEquals(WebViewClient.ERROR_FAILED_SSL_HANDSHAKE, webViewClient.onReceivedErrorCode());
+    }
+
+    public void testProceedClientCertRequest() throws Throwable {
+        mWebServer = new CtsTestServer(getActivity(), CtsTestServer.SslMode.NEEDS_CLIENT_AUTH);
+        String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
+        final ClientCertWebViewClient webViewClient = new ClientCertWebViewClient(mOnUiThread);
+        mOnUiThread.setWebViewClient(webViewClient);
+        clearClientCertPreferences();
+        mOnUiThread.loadUrlAndWaitForCompletion(url);
+        assertTrue(TestHtmlConstants.HELLO_WORLD_TITLE.equals(mOnUiThread.getTitle()));
+
+        // Test that the user's response for this server is kept in cache. Load a different
+        // page from the same server and make sure we don't receive a client cert request callback.
+        int callCount = webViewClient.getClientCertRequestCount();
+        url = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL1);
+        mOnUiThread.loadUrlAndWaitForCompletion(url);
+        assertTrue(TestHtmlConstants.HTML_URL1_TITLE.equals(mOnUiThread.getTitle()));
+        assertEquals(callCount, webViewClient.getClientCertRequestCount());
+
+        // Now clear the cache and reload the page. We should receive a new callback.
+        clearClientCertPreferences();
+        mOnUiThread.loadUrlAndWaitForCompletion(url);
+        assertTrue(TestHtmlConstants.HTML_URL1_TITLE.equals(mOnUiThread.getTitle()));
+        assertEquals(callCount + 1, webViewClient.getClientCertRequestCount());
+    }
+
+    public void testIgnoreClientCertRequest() throws Throwable {
+        mWebServer = new CtsTestServer(getActivity(), CtsTestServer.SslMode.NEEDS_CLIENT_AUTH);
+        String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
+        final ClientCertWebViewClient webViewClient = new ClientCertWebViewClient(mOnUiThread);
+        mOnUiThread.setWebViewClient(webViewClient);
+        clearClientCertPreferences();
+        // Ignore the request. Load should fail.
+        webViewClient.setAction(ClientCertWebViewClient.IGNORE);
+        mOnUiThread.loadUrlAndWaitForCompletion(url);
+        assertFalse(TestHtmlConstants.HELLO_WORLD_TITLE.equals(mOnUiThread.getTitle()));
+        assertEquals(WebViewClient.ERROR_FAILED_SSL_HANDSHAKE, webViewClient.onReceivedErrorCode());
+
+        // Load a different page from the same domain, ignoring the request. We should get a callback,
+        // and load should fail.
+        int callCount = webViewClient.getClientCertRequestCount();
+        url = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL1);
+        mOnUiThread.loadUrlAndWaitForCompletion(url);
+        assertFalse(TestHtmlConstants.HTML_URL1_TITLE.equals(mOnUiThread.getTitle()));
+        assertEquals(WebViewClient.ERROR_FAILED_SSL_HANDSHAKE, webViewClient.onReceivedErrorCode());
+        assertEquals(callCount + 1, webViewClient.getClientCertRequestCount());
+
+        // Reload, proceeding the request. Load should succeed.
+        webViewClient.setAction(ClientCertWebViewClient.PROCEED);
+        url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
+        mOnUiThread.loadUrlAndWaitForCompletion(url);
+        assertTrue(TestHtmlConstants.HELLO_WORLD_TITLE.equals(mOnUiThread.getTitle()));
+    }
+
+    public void testCancelClientCertRequest() throws Throwable {
+        mWebServer = new CtsTestServer(getActivity(), CtsTestServer.SslMode.NEEDS_CLIENT_AUTH);
+        final String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
+        final ClientCertWebViewClient webViewClient = new ClientCertWebViewClient(mOnUiThread);
+        mOnUiThread.setWebViewClient(webViewClient);
+        clearClientCertPreferences();
+        // Cancel the request. Load should fail.
+        webViewClient.setAction(ClientCertWebViewClient.CANCEL);
+        mOnUiThread.loadUrlAndWaitForCompletion(url);
+        assertFalse(TestHtmlConstants.HELLO_WORLD_TITLE.equals(mOnUiThread.getTitle()));
+        assertEquals(WebViewClient.ERROR_FAILED_SSL_HANDSHAKE, webViewClient.onReceivedErrorCode());
+
+        // Reload. The request should fail without generating a new callback.
+        int callCount = webViewClient.getClientCertRequestCount();
+        mOnUiThread.loadUrlAndWaitForCompletion(url);
+        assertEquals(callCount, webViewClient.getClientCertRequestCount());
+        assertFalse(TestHtmlConstants.HELLO_WORLD_TITLE.equals(mOnUiThread.getTitle()));
+        assertEquals(WebViewClient.ERROR_FAILED_SSL_HANDSHAKE, webViewClient.onReceivedErrorCode());
+    }
+
+    /**
+     * {@link X509TrustManager} that trusts everybody.
+     */
+    private static class TrustManager implements X509TrustManager {
+        public void checkClientTrusted(X509Certificate[] chain, String authType) {
+            // Trust the CtSTestServer's client...
+        }
+
+        public void checkServerTrusted(X509Certificate[] chain, String authType) {
+            // Trust the CtSTestServer...
+        }
+
+        public X509Certificate[] getAcceptedIssuers() {
+            try {
+                CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+                return new X509Certificate[] {
+                        (X509Certificate) certFactory.generateCertificate(
+                                new ByteArrayInputStream(FAKE_RSA_CA_1))
+                        };
+            } catch (Exception ex) {
+                Log.e(LOGTAG, "failed creating certificate chain" + ex);
+                return null;
+            }
+        }
+    }
+
+    public void testClientCertIssuersReceivedCorrectly() throws Throwable {
+        mWebServer = new CtsTestServer(getActivity(), CtsTestServer.SslMode.NEEDS_CLIENT_AUTH,
+                new TrustManager());
+        final String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
+        final ClientCertWebViewClient webViewClient = new ClientCertWebViewClient(mOnUiThread);
+        mOnUiThread.setWebViewClient(webViewClient);
+        clearClientCertPreferences();
+        mOnUiThread.loadUrlAndWaitForCompletion(url);
+        // Verify that issuers sent by the server are received correctly
+        CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+        X509Certificate  cert = (X509Certificate) certFactory.generateCertificate(
+                                new ByteArrayInputStream(FAKE_RSA_CA_1));
+        Principal[] principals = webViewClient.getPrincipals();
+        assertEquals(1, principals.length);
+        // TODO: should we issue getIssuerX500Principal instead?
+        assertEquals(cert.getIssuerDN(), principals[0]);
+    }
+
+    private void clearClientCertPreferences() {
+       final AtomicBoolean cleared = new AtomicBoolean(false);
+        mOnUiThread.clearClientCertPreferences(new Runnable() {
+            @Override
+            public void run() {
+                cleared.set(true);
+            }
+        });
+        // Wait until clearclientcertpreferences clears the preferences. Generally this is just a
+        // thread hopping.
+        new PollingCheck(WebViewTest.TEST_TIMEOUT) {
+            @Override
+            protected boolean check() {
+                return cleared.get();
+            }
+        }.run();
+    }
+
+    // Note that this class is not thread-safe.
+    static class SslErrorWebViewClient extends WaitForLoadedClient {
+        private boolean mWasOnReceivedSslErrorCalled;
+        private String mErrorUrl;
+        private int mErrorCode;
+
+        public SslErrorWebViewClient(WebViewOnUiThread onUiThread) {
+            super(onUiThread);
+        }
+        @Override
+        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
+            mWasOnReceivedSslErrorCalled = true;
+            mErrorUrl = error.getUrl();
+            handler.proceed();
+        }
+        @Override
+        public void onReceivedError(WebView view, int errorCode, String description,
+                String failingUrl) {
+            mErrorCode = errorCode;
+        }
+        public void resetWasOnReceivedSslErrorCalled() {
+            mWasOnReceivedSslErrorCalled = false;
+        }
+        public boolean wasOnReceivedSslErrorCalled() {
+            return mWasOnReceivedSslErrorCalled;
+        }
+        public String errorUrl() {
+            return mErrorUrl;
+        }
+        public int onReceivedErrorCode() {
+            return mErrorCode;
+        }
+    }
+
+    // Modifies the default behavior of SslErrorWebViewClient to accept the request, and provide
+    // certs.
+    static class ClientCertWebViewClient extends SslErrorWebViewClient {
+        // User Actions
+        public static final int PROCEED = 1;
+        public static final int CANCEL = 2;
+        public static final int IGNORE = 3;
+
+        private int mClientCertRequests;
+        private int mAction = PROCEED;
+        private Principal[] mPrincipals;
+
+        public ClientCertWebViewClient(WebViewOnUiThread onUiThread) {
+            super(onUiThread);
+        }
+
+        public int getClientCertRequestCount() {
+            return mClientCertRequests;
+        }
+
+        public Principal[] getPrincipals() {
+            return mPrincipals;
+        }
+
+        public void resetClientCertRequestCount() {
+            mClientCertRequests = 0;
+        }
+
+        public void setAction(int action) {
+            mAction = action;
+        }
+
+        @Override
+        public void onReceivedClientCertRequest(WebView view, ClientCertRequest request) {
+            mClientCertRequests++;
+            mPrincipals = request.getPrincipals();
+            if (mAction == IGNORE) {
+                request.ignore();
+                return;
+            }
+            if (mAction == CANCEL) {
+                request.cancel();
+                return;
+            }
+            if (mAction == PROCEED) {
+                try {
+                    CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+                    X509Certificate[] certChain =  new X509Certificate[] {
+                            (X509Certificate) certFactory.generateCertificate(
+                                    new ByteArrayInputStream(FAKE_RSA_USER_1)),
+                            (X509Certificate) certFactory.generateCertificate(
+                                    new ByteArrayInputStream(FAKE_RSA_CA_1))
+                    };
+                    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+                    PrivateKey key = keyFactory.generatePrivate(
+                        new PKCS8EncodedKeySpec(FAKE_RSA_KEY_1));
+                    request.proceed(key, certChain);
+                    return;
+                } catch (Exception e) {
+                    Log.e(LOGTAG,  "Fatal error" + e);
+                }
+            }
+            throw new IllegalStateException("unknown action");
+        }
+    }
+}
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewStartupCtsActivity.java b/tests/tests/webkit/src/android/webkit/cts/WebViewStartupCtsActivity.java
new file mode 100644
index 0000000..933d0ed
--- /dev/null
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewStartupCtsActivity.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2013 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.webkit.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.ViewGroup;
+import android.webkit.WebView;
+
+public class WebViewStartupCtsActivity extends Activity {
+    private WebView mWebView;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+
+    public WebView createAndAttachWebView() {
+        mWebView = new WebView(this);
+        setContentView(mWebView);
+        return mWebView;
+    }
+
+    public WebView getWebView() {
+        return mWebView;
+    }
+
+    public void detachAndDestroyWebView() {
+        if (mWebView != null) {
+            ViewGroup vg = (ViewGroup)mWebView.getParent();
+            vg.removeView(mWebView);
+            mWebView.destroy();
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        detachAndDestroyWebView();
+        super.onDestroy();
+    }
+}
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java
index 56f8f61..776cfab 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java
@@ -18,6 +18,7 @@
 
 
 import android.content.Context;
+import android.cts.util.NullWebViewUtils;
 import android.cts.util.PollingCheck;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
@@ -30,15 +31,15 @@
 import java.util.regex.Pattern;
 
 public class WebViewStartupTest
-        extends ActivityInstrumentationTestCase2<WebViewStartupStubActivity> {
+        extends ActivityInstrumentationTestCase2<WebViewStartupCtsActivity> {
 
     private static final int TEST_TIMEOUT = 5000;
     private static final String TAG = "WebViewStartupTest";
 
-    private WebViewStartupStubActivity mActivity;
+    private WebViewStartupCtsActivity mActivity;
 
     public WebViewStartupTest() {
-        super("com.android.cts.stub", WebViewStartupStubActivity.class);
+        super("com.android.cts.webkit", WebViewStartupCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
old mode 100644
new mode 100755
index d339a62..ef64f4d
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.res.AssetManager;
 import android.cts.util.EvaluateJsResultPollingCheck;
+import android.cts.util.NullWebViewUtils;
 import android.cts.util.PollingCheck;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.Config;
@@ -29,8 +30,6 @@
 import android.graphics.Picture;
 import android.graphics.Rect;
 import android.net.Uri;
-import android.net.http.SslCertificate;
-import android.net.http.SslError;
 import android.os.Bundle;
 import android.os.CancellationSignal;
 import android.os.Handler;
@@ -58,7 +57,6 @@
 import android.webkit.CookieSyncManager;
 import android.webkit.DownloadListener;
 import android.webkit.JavascriptInterface;
-import android.webkit.SslErrorHandler;
 import android.webkit.ValueCallback;
 import android.webkit.WebBackForwardList;
 import android.webkit.WebChromeClient;
@@ -75,24 +73,37 @@
 
 import junit.framework.Assert;
 
+import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.IOException;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+
 import java.util.Collections;
 import java.util.Date;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.FutureTask;
+import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 import java.util.HashMap;
+import java.util.Map;
 
 import org.apache.http.Header;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpEntityEnclosingRequest;
 import org.apache.http.HttpRequest;
+import org.apache.http.util.EncodingUtils;
+import org.apache.http.util.EntityUtils;
 
-public class WebViewTest extends ActivityInstrumentationTestCase2<WebViewStubActivity> {
-    private static final String LOGTAG = "WebViewTest";
+public class WebViewTest extends ActivityInstrumentationTestCase2<WebViewCtsActivity> {
+    public static final long TEST_TIMEOUT = 20000L;
     private static final int INITIAL_PROGRESS = 100;
-    private static long TEST_TIMEOUT = 20000L;
     private static final String X_REQUESTED_WITH = "X-Requested-With";
     private static final String PRINTER_TEST_FILE = "print.pdf";
     private static final String PDF_PREAMBLE = "%PDF-1";
@@ -117,13 +128,13 @@
     private WebIconDatabase mIconDb;
 
     public WebViewTest() {
-        super("com.android.cts.stub", WebViewStubActivity.class);
+        super("com.android.cts.webkit", WebViewCtsActivity.class);
     }
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        final WebViewStubActivity activity = getActivity();
+        final WebViewCtsActivity activity = getActivity();
         mWebView = activity.getWebView();
         if (mWebView != null) {
             new PollingCheck() {
@@ -147,7 +158,7 @@
             mOnUiThread.cleanUp();
         }
         if (mWebServer != null) {
-            mWebServer.shutdown();
+            stopWebServer();
         }
         if (mIconDb != null) {
             mIconDb.removeAllIcons();
@@ -278,6 +289,20 @@
         currScale = mOnUiThread.getScale();
         assertTrue(currScale < previousScale);
 
+        mOnUiThread.zoomBy(1.25f); // zoom in
+        previousScale = currScale;
+        webViewClient.waitForScaleChanged();
+
+        currScale = mOnUiThread.getScale();
+        assertTrue(currScale > previousScale);
+
+        mOnUiThread.zoomBy(0.8f); // zoom out
+        previousScale = currScale;
+        webViewClient.waitForScaleChanged();
+
+        currScale = mOnUiThread.getScale();
+        assertTrue(currScale < previousScale);
+
         // enable zoom support
         settings.setSupportZoom(true);
         assertTrue(settings.supportZoom());
@@ -300,16 +325,17 @@
         previousScale = currScale;
         // can not zoom in further
         assertFalse(mOnUiThread.zoomIn());
+
         // We sleep to assert to the best of our ability
         // that a scale change does *not* happen.
         Thread.sleep(500);
         currScale = mOnUiThread.getScale();
         assertEquals(currScale, previousScale);
 
-        // zoom out
         assertTrue(mOnUiThread.zoomOut());
         previousScale = currScale;
         webViewClient.waitForScaleChanged();
+
         currScale = mOnUiThread.getScale();
         assertTrue(currScale < previousScale);
 
@@ -329,6 +355,54 @@
         Thread.sleep(500);
         currScale = mOnUiThread.getScale();
         assertEquals(currScale, previousScale);
+
+        mOnUiThread.zoomBy(1.25f);
+        previousScale = currScale;
+        webViewClient.waitForScaleChanged();
+
+        currScale = mOnUiThread.getScale();
+        assertTrue(currScale > previousScale);
+
+        // zoom in until it reaches maximum scale
+        while (mOnUiThread.canZoomIn()) {
+            previousScale = currScale;
+            mOnUiThread.zoomBy(1.25f);
+            webViewClient.waitForScaleChanged();
+            currScale = mOnUiThread.getScale();
+            assertTrue(currScale > previousScale);
+        }
+
+        previousScale = currScale;
+
+        // We sleep to assert to the best of our ability
+        // that a scale change does *not* happen.
+        Thread.sleep(500);
+        currScale = mOnUiThread.getScale();
+        assertEquals(currScale, previousScale);
+
+        mOnUiThread.zoomBy(0.8f);
+        previousScale = currScale;
+        webViewClient.waitForScaleChanged();
+
+        currScale = mOnUiThread.getScale();
+        assertTrue(currScale < previousScale);
+
+        // zoom out until it reaches minimum scale
+        while (mOnUiThread.canZoomOut()) {
+            previousScale = currScale;
+            mOnUiThread.zoomBy(0.8f);
+            webViewClient.waitForScaleChanged();
+            currScale = mOnUiThread.getScale();
+            assertTrue(currScale < previousScale);
+        }
+
+        previousScale = currScale;
+
+        // We sleep to assert to the best of our ability
+        // that a scale change does *not* happen.
+        Thread.sleep(500);
+        currScale = mOnUiThread.getScale();
+        assertEquals(currScale, previousScale);
     }
 
     @UiThreadTest
@@ -399,6 +473,36 @@
     }
 
     @UiThreadTest
+    public void testPostUrlWithNonNetworkUrl() throws Exception {
+        final String nonNetworkUrl = "file:///android_asset/" + TestHtmlConstants.HELLO_WORLD_URL;
+
+        mOnUiThread.postUrlAndWaitForCompletion(nonNetworkUrl, new byte[1]);
+
+        // Test if the nonNetworkUrl is loaded
+        assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mWebView.getTitle());
+    }
+
+    @UiThreadTest
+    public void testPostUrlWithNetworkUrl() throws Exception {
+        startWebServer(false);
+        final String networkUrl = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
+        final String postDataString = "username=my_username&password=my_password";
+        final byte[] postData = EncodingUtils.getBytes(postDataString, "BASE64");
+
+        mOnUiThread.postUrlAndWaitForCompletion(networkUrl, postData);
+
+        HttpRequest request = mWebServer.getLastRequest(TestHtmlConstants.HELLO_WORLD_URL);
+        // The last request should be POST
+        assertEquals(request.getRequestLine().getMethod(), "POST");
+
+        // The last request should have a request body
+        assertTrue(request instanceof HttpEntityEnclosingRequest);
+        HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
+        String entityString = EntityUtils.toString(entity);
+        assertEquals(entityString, postDataString);
+    }
+
+    @UiThreadTest
     public void testLoadUrlDoesNotStripParamsWhenLoadingContentUrls() throws Exception {
         if (!NullWebViewUtils.isWebViewAvailable()) {
             return;
@@ -460,6 +564,28 @@
         assertEquals(requester, header.getValue());
     }
 
+    public void testCanInjectHeaders() throws Exception {
+        final String X_FOO = "X-foo";
+        final String X_FOO_VALUE = "test";
+
+        final String X_REFERER = "Referer";
+        final String X_REFERER_VALUE = "http://www.example.com/";
+        startWebServer(false);
+        String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
+        HashMap<String, String> map = new HashMap<String, String>();
+        map.put(X_FOO, X_FOO_VALUE);
+        map.put(X_REFERER, X_REFERER_VALUE);
+        mOnUiThread.loadUrlAndWaitForCompletion(url, map);
+
+        HttpRequest request = mWebServer.getLastRequest(TestHtmlConstants.HELLO_WORLD_URL);
+        for (Map.Entry<String,String> value : map.entrySet()) {
+            String header = value.getKey();
+            Header[] matchingHeaders = request.getHeaders(header);
+            assertEquals("header " + header + " not found", 1, matchingHeaders.length);
+            assertEquals(value.getValue(), matchingHeaders[0].getValue());
+        }
+    }
+
     @SuppressWarnings("deprecation")
     @UiThreadTest
     public void testGetVisibleTitleHeight() throws Exception {
@@ -634,6 +760,30 @@
         String url = mWebServer.getAssetUrl(TestHtmlConstants.ADD_JAVA_SCRIPT_INTERFACE_URL);
         mOnUiThread.loadUrlAndWaitForCompletion(url);
         assertEquals("Original title", obj.waitForResult());
+
+        // Verify that only methods annotated with @JavascriptInterface are exposed
+        // on the JavaScript interface object.
+        mOnUiThread.evaluateJavascript("typeof dummy.provideResult",
+                new ValueCallback<String>() {
+                    @Override
+                    public void onReceiveValue(String result) {
+                        assertEquals("\"function\"", result);
+                    }
+                });
+        mOnUiThread.evaluateJavascript("typeof dummy.wasProvideResultCalled",
+                new ValueCallback<String>() {
+                    @Override
+                    public void onReceiveValue(String result) {
+                        assertEquals("\"undefined\"", result);
+                    }
+                });
+        mOnUiThread.evaluateJavascript("typeof dummy.getClass",
+                new ValueCallback<String>() {
+                    @Override
+                    public void onReceiveValue(String result) {
+                        assertEquals("\"undefined\"", result);
+                    }
+                });
     }
 
     @UiThreadTest
@@ -748,6 +898,42 @@
         assertEquals("removedObject", resultObject.getResult());
     }
 
+    public void testAddJavascriptInterfaceExceptions() throws Exception {
+        WebSettings settings = mOnUiThread.getSettings();
+        settings.setJavaScriptEnabled(true);
+        settings.setJavaScriptCanOpenWindowsAutomatically(true);
+
+        final AtomicBoolean mJsInterfaceWasCalled = new AtomicBoolean(false) {
+            @JavascriptInterface
+            public synchronized void call() {
+                set(true);
+                // The main purpose of this test is to ensure an exception here does not
+                // crash the implementation.
+                throw new RuntimeException("Javascript Interface exception");
+            }
+        };
+
+        mOnUiThread.addJavascriptInterface(mJsInterfaceWasCalled, "dummy");
+
+        mOnUiThread.loadUrlAndWaitForCompletion("about:blank");
+
+        assertFalse(mJsInterfaceWasCalled.get());
+
+        final CountDownLatch resultLatch = new CountDownLatch(1);
+        mOnUiThread.evaluateJavascript(
+                "try {dummy.call(); 'fail'; } catch (exception) { 'pass'; } ",
+                new ValueCallback<String>() {
+                        @Override
+                        public void onReceiveValue(String result) {
+                            assertEquals("\"pass\"", result);
+                            resultLatch.countDown();
+                        }
+                    });
+
+        assertTrue(resultLatch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS));
+        assertTrue(mJsInterfaceWasCalled.get());
+    }
+
     public void testJavascriptInterfaceCustomPropertiesClearedOnReload() throws Exception {
         if (!NullWebViewUtils.isWebViewAvailable()) {
             return;
@@ -776,6 +962,66 @@
         jsResult.run();
     }
 
+    public void testJavascriptInterfaceForClientPopup() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
+        mOnUiThread.getSettings().setJavaScriptEnabled(true);
+        mOnUiThread.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
+        mOnUiThread.getSettings().setSupportMultipleWindows(true);
+
+        class DummyJavaScriptInterface {
+            @JavascriptInterface
+            public int test() {
+                return 42;
+            }
+        }
+        final DummyJavaScriptInterface obj = new DummyJavaScriptInterface();
+
+        final WebView childWebView = mOnUiThread.createWebView();
+        WebViewOnUiThread childOnUiThread = new WebViewOnUiThread(this, childWebView);
+        childOnUiThread.getSettings().setJavaScriptEnabled(true);
+        childOnUiThread.addJavascriptInterface(obj, "dummy");
+
+        final boolean[] hadOnCreateWindow = new boolean[1];
+        hadOnCreateWindow[0] = false;
+        mOnUiThread.setWebChromeClient(new WebViewOnUiThread.WaitForProgressClient(mOnUiThread) {
+            @Override
+            public boolean onCreateWindow(
+                WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
+                getActivity().addContentView(childWebView, new ViewGroup.LayoutParams(
+                            ViewGroup.LayoutParams.FILL_PARENT,
+                            ViewGroup.LayoutParams.WRAP_CONTENT));
+                WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
+                transport.setWebView(childWebView);
+                resultMsg.sendToTarget();
+                hadOnCreateWindow[0] = true;
+                return true;
+            }
+        });
+
+        startWebServer(false);
+        mOnUiThread.loadUrlAndWaitForCompletion(mWebServer.
+                getAssetUrl(TestHtmlConstants.POPUP_URL));
+        new PollingCheck(TEST_TIMEOUT) {
+            @Override
+            protected boolean check() {
+                return hadOnCreateWindow[0];
+            }
+        }.run();
+
+        childOnUiThread.loadUrlAndWaitForCompletion("about:blank");
+        EvaluateJsResultPollingCheck jsResult;
+        jsResult = new EvaluateJsResultPollingCheck("true");
+        childOnUiThread.evaluateJavascript("'dummy' in window", jsResult);
+        jsResult.run();
+        // Verify that the injected object is functional.
+        jsResult = new EvaluateJsResultPollingCheck("42");
+        childOnUiThread.evaluateJavascript("dummy.test()", jsResult);
+        jsResult.run();
+    }
+
     private final class TestPictureListener implements PictureListener {
         public int callCount;
 
@@ -1003,7 +1249,6 @@
         // Verify that the resource request makes it to the server.
         assertTrue(mWebServer.wasResourceRequested(imgUrl));
         assertEquals(historyUrl, mWebView.getUrl());
-        assertEquals(historyUrl, mWebView.getOriginalUrl());
 
         // Check that reported URL is "about:blank" when supplied history URL
         // is null.
@@ -1013,7 +1258,6 @@
                 "text/html", "UTF-8", null);
         assertTrue(mWebServer.wasResourceRequested(imgUrl));
         assertEquals("about:blank", mWebView.getUrl());
-        assertEquals("about:blank", mWebView.getOriginalUrl());
 
         // Test that JavaScript can access content from the same origin as the base URL.
         mWebView.getSettings().setJavaScriptEnabled(true);
@@ -1038,19 +1282,106 @@
         mOnUiThread.loadDataWithBaseURLAndWaitForCompletion("http://www.foo.com",
                 HTML_HEADER + "<title>Hello World%21</title><body>bar</body></html>",
                 "text/html", "UTF-8", null);
-        assertEquals("Hello World%21", mWebView.getTitle());
+        assertEquals("Hello World%21", mOnUiThread.getTitle());
 
         // Check that when a data: base URL is used, we treat the String to load as a data: URL
         // and run load steps such as decoding URL entities (i.e., contrary to the test case
         // above.)
         mOnUiThread.loadDataWithBaseURLAndWaitForCompletion("data:foo",
                 HTML_HEADER + "<title>Hello World%21</title></html>", "text/html", "UTF-8", null);
-        assertEquals("Hello World!", mWebView.getTitle());
+        assertEquals("Hello World!", mOnUiThread.getTitle());
 
         // Check the method is null input safe.
         mOnUiThread.loadDataWithBaseURLAndWaitForCompletion(null, null, null, null, null);
-        assertEquals("about:blank", mWebView.getUrl());
-        assertEquals("about:blank", mWebView.getOriginalUrl());
+        assertEquals("about:blank", mOnUiThread.getUrl());
+    }
+
+    private void deleteIfExists(File file) throws IOException {
+        if (file.exists()) {
+            file.delete();
+        }
+    }
+
+    private String readTextFile(File file, Charset encoding)
+            throws FileNotFoundException, IOException {
+        FileInputStream stream = new FileInputStream(file);
+        byte[] bytes = new byte[(int)file.length()];
+        stream.read(bytes);
+        stream.close();
+        return new String(bytes, encoding);
+    }
+
+    private void doSaveWebArchive(String baseName, boolean autoName, final String expectName)
+            throws Throwable {
+        final Semaphore saving = new Semaphore(0);
+        ValueCallback<String> callback = new ValueCallback<String>() {
+            @Override
+            public void onReceiveValue(String savedName) {
+                assertEquals(expectName, savedName);
+                saving.release();
+            }
+        };
+
+        mOnUiThread.saveWebArchive(baseName, autoName, callback);
+        assertTrue(saving.tryAcquire(TEST_TIMEOUT, TimeUnit.MILLISECONDS));
+    }
+
+    public void testSaveWebArchive() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
+        final String testPage = "testSaveWebArchive test page";
+
+        File dir = getActivity().getFilesDir();
+        String dirStr = dir.toString();
+
+        File test = new File(dir, "test.mht");
+        deleteIfExists(test);
+        String testStr = test.getAbsolutePath();
+
+        File index = new File(dir, "index.mht");
+        deleteIfExists(index);
+        String indexStr = index.getAbsolutePath();
+
+        File index1 = new File(dir, "index-1.mht");
+        deleteIfExists(index1);
+        String index1Str = index1.getAbsolutePath();
+
+        mOnUiThread.loadDataAndWaitForCompletion(testPage, "text/html", "UTF-8");
+
+        try {
+            // Save test.mht
+            doSaveWebArchive(testStr, false, testStr);
+
+            // Check the contents of test.mht
+            String testMhtml = readTextFile(test, StandardCharsets.UTF_8);
+            assertTrue(testMhtml.contains(testPage));
+
+            // Save index.mht
+            doSaveWebArchive(dirStr + "/", true, indexStr);
+
+            // Check the contents of index.mht
+            String indexMhtml = readTextFile(index, StandardCharsets.UTF_8);
+            assertTrue(indexMhtml.contains(testPage));
+
+            // Save index-1.mht since index.mht already exists
+            doSaveWebArchive(dirStr + "/", true, index1Str);
+
+            // Check the contents of index-1.mht
+            String index1Mhtml = readTextFile(index1, StandardCharsets.UTF_8);
+            assertTrue(index1Mhtml.contains(testPage));
+
+            // Try a file in a bogus directory
+            doSaveWebArchive("/bogus/path/test.mht", false, null);
+
+            // Try a bogus directory
+            doSaveWebArchive("/bogus/path/", true, null);
+        } finally {
+            deleteIfExists(test);
+            deleteIfExists(index);
+            deleteIfExists(index1);
+        }
     }
 
     private static class WaitForFindResultsListener extends FutureTask<Integer>
@@ -1112,10 +1443,14 @@
                 "Find all instances of a word on the page and highlight them.</p>";
 
         mOnUiThread.loadDataAndWaitForCompletion("<html><body>" + p + p + "</body></html>", "text/html", null);
+        WaitForFindResultsListener l = new WaitForFindResultsListener();
+        mOnUiThread.setFindListener(l);
 
         // highlight all the strings found
         mOnUiThread.findAll("all");
-        getInstrumentation().waitForIdleSync();
+        // make sure the findAll action is completed before findNext
+        l.get();
+        mOnUiThread.setFindListener(null);
 
         int previousScrollY = mOnUiThread.getScrollY();
 
@@ -1636,19 +1971,6 @@
     }
 
     @UiThreadTest
-    public void testGetFavicon() throws Exception {
-        if (!NullWebViewUtils.isWebViewAvailable()) {
-            return;
-        }
-        startWebServer(false);
-        String url = mWebServer.getAssetUrl(TestHtmlConstants.TEST_FAVICON_URL);
-        mOnUiThread.loadUrlAndWaitForCompletion(url);
-        mWebView.getFavicon();
-        // ToBeFixed: Favicon is not loaded automatically.
-        // assertNotNull(mWebView.getFavicon());
-    }
-
-    @UiThreadTest
     public void testClearHistory() throws Exception {
         if (!NullWebViewUtils.isWebViewAvailable()) {
             return;
@@ -1716,7 +2038,7 @@
         assertNotNull(restoreList);
         assertEquals(3, restoreList.getSize());
         assertEquals(2, saveList.getCurrentIndex());
-        /* ToBeFixed: The WebHistoryItems do not get inflated. Uncomment remaining tests when fixed.
+
         // wait for the list items to get inflated
         new PollingCheck(TEST_TIMEOUT) {
             @Override
@@ -1737,7 +2059,6 @@
         assertEquals(url1, copyListAfterRestore.getItemAtIndex(0).getUrl());
         assertEquals(url2, copyListAfterRestore.getItemAtIndex(1).getUrl());
         assertEquals(url3, copyListAfterRestore.getItemAtIndex(2).getUrl());
-        */
     }
 
     public void testSetWebViewClient() throws Throwable {
@@ -1757,227 +2078,6 @@
         webViewClient.waitForScaleChanged();
     }
 
-    @UiThreadTest
-    public void testInsecureSiteClearsCertificate() throws Throwable {
-        if (!NullWebViewUtils.isWebViewAvailable()) {
-            return;
-        }
-        final class MockWebViewClient extends WaitForLoadedClient {
-            public MockWebViewClient() {
-                super(mOnUiThread);
-            }
-            @Override
-            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
-                handler.proceed();
-            }
-        }
-
-        startWebServer(true);
-        mOnUiThread.setWebViewClient(new MockWebViewClient());
-        mOnUiThread.loadUrlAndWaitForCompletion(
-                mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL));
-        SslCertificate cert = mWebView.getCertificate();
-        assertNotNull(cert);
-        assertEquals("Android", cert.getIssuedTo().getUName());
-
-        stopWebServer();
-
-        startWebServer(false);
-        mOnUiThread.loadUrlAndWaitForCompletion(
-                mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL));
-        assertNull(mWebView.getCertificate());
-    }
-
-    @UiThreadTest
-    public void testSecureSiteSetsCertificate() throws Throwable {
-        if (!NullWebViewUtils.isWebViewAvailable()) {
-            return;
-        }
-        final class MockWebViewClient extends WaitForLoadedClient {
-            public MockWebViewClient() {
-                super(mOnUiThread);
-            }
-            @Override
-            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
-                handler.proceed();
-            }
-        }
-
-        startWebServer(false);
-        mOnUiThread.loadUrlAndWaitForCompletion(
-                mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL));
-        assertNull(mWebView.getCertificate());
-
-        stopWebServer();
-
-        startWebServer(true);
-        mOnUiThread.setWebViewClient(new MockWebViewClient());
-        mOnUiThread.loadUrlAndWaitForCompletion(
-                mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL));
-        SslCertificate cert = mWebView.getCertificate();
-        assertNotNull(cert);
-        assertEquals("Android", cert.getIssuedTo().getUName());
-    }
-
-    @UiThreadTest
-    public void testClearSslPreferences() throws Throwable {
-        if (!NullWebViewUtils.isWebViewAvailable()) {
-            return;
-        }
-        // Load the first page. We expect a call to
-        // WebViewClient.onReceivedSslError().
-        final SslErrorWebViewClient webViewClient = new SslErrorWebViewClient();
-        startWebServer(true);
-        final String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
-        mOnUiThread.setWebViewClient(webViewClient);
-        mOnUiThread.clearSslPreferences();
-        mOnUiThread.loadUrlAndWaitForCompletion(url);
-        assertTrue(webViewClient.wasOnReceivedSslErrorCalled());
-
-        // Load the page again. We expect another call to
-        // WebViewClient.onReceivedSslError() since we cleared sslpreferences.
-        mOnUiThread.clearSslPreferences();
-        webViewClient.resetWasOnReceivedSslErrorCalled();
-        mOnUiThread.loadUrlAndWaitForCompletion(url);
-        assertTrue(webViewClient.wasOnReceivedSslErrorCalled());
-        assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle());
-
-        // Load the page once again, without clearing the sslpreferences.
-        // Make sure we do not get the callback.
-        webViewClient.resetWasOnReceivedSslErrorCalled();
-        mOnUiThread.loadUrlAndWaitForCompletion(url);
-        assertFalse(webViewClient.wasOnReceivedSslErrorCalled());
-        assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle());
-    }
-
-    public void testOnReceivedSslError() throws Throwable {
-        if (!NullWebViewUtils.isWebViewAvailable()) {
-            return;
-        }
-        final class MockWebViewClient extends WaitForLoadedClient {
-            private String mErrorUrl;
-            private WebView mWebView;
-
-            public MockWebViewClient() {
-                super(mOnUiThread);
-            }
-            @Override
-            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
-                mWebView = view;
-                mErrorUrl = error.getUrl();
-                handler.proceed();
-            }
-            public String errorUrl() {
-                return mErrorUrl;
-            }
-            public WebView webView() {
-                return mWebView;
-            }
-        }
-
-        startWebServer(true);
-        final String errorUrl = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
-        final MockWebViewClient webViewClient = new MockWebViewClient();
-        mOnUiThread.setWebViewClient(webViewClient);
-        mOnUiThread.clearSslPreferences();
-        mOnUiThread.loadUrlAndWaitForCompletion(errorUrl);
-
-        assertEquals(mWebView, webViewClient.webView());
-        assertEquals(errorUrl, webViewClient.errorUrl());
-    }
-
-    public void testOnReceivedSslErrorProceed() throws Throwable {
-        if (!NullWebViewUtils.isWebViewAvailable()) {
-            return;
-        }
-        final class MockWebViewClient extends WaitForLoadedClient {
-            public MockWebViewClient() {
-                super(mOnUiThread);
-            }
-            @Override
-            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
-                handler.proceed();
-            }
-        }
-
-        startWebServer(true);
-        final String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
-        mOnUiThread.setWebViewClient(new MockWebViewClient());
-        mOnUiThread.loadUrlAndWaitForCompletion(url);
-        assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle());
-    }
-
-    public void testOnReceivedSslErrorCancel() throws Throwable {
-        if (!NullWebViewUtils.isWebViewAvailable()) {
-            return;
-        }
-        final class MockWebViewClient extends WaitForLoadedClient {
-            public MockWebViewClient() {
-                super(mOnUiThread);
-            }
-            @Override
-            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
-                handler.cancel();
-            }
-        }
-
-        startWebServer(true);
-        final String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
-        mOnUiThread.setWebViewClient(new MockWebViewClient());
-        mOnUiThread.clearSslPreferences();
-        mOnUiThread.loadUrlAndWaitForCompletion(url);
-        assertFalse(TestHtmlConstants.HELLO_WORLD_TITLE.equals(mOnUiThread.getTitle()));
-    }
-
-    public void testSslErrorProceedResponseReusedForSameHost() throws Throwable {
-        if (!NullWebViewUtils.isWebViewAvailable()) {
-            return;
-        }
-        // Load the first page. We expect a call to
-        // WebViewClient.onReceivedSslError().
-        final SslErrorWebViewClient webViewClient = new SslErrorWebViewClient();
-        startWebServer(true);
-        final String firstUrl = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL1);
-        mOnUiThread.setWebViewClient(webViewClient);
-        mOnUiThread.clearSslPreferences();
-        mOnUiThread.loadUrlAndWaitForCompletion(firstUrl);
-        assertTrue(webViewClient.wasOnReceivedSslErrorCalled());
-
-        // Load the second page. We don't expect a call to
-        // WebViewClient.onReceivedSslError(), but the page should load.
-        webViewClient.resetWasOnReceivedSslErrorCalled();
-        final String sameHostUrl = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL2);
-        mOnUiThread.loadUrlAndWaitForCompletion(sameHostUrl);
-        assertFalse(webViewClient.wasOnReceivedSslErrorCalled());
-        assertEquals("Second page", mOnUiThread.getTitle());
-    }
-
-    public void testSslErrorProceedResponseNotReusedForDifferentHost() throws Throwable {
-        if (!NullWebViewUtils.isWebViewAvailable()) {
-            return;
-        }
-        // Load the first page. We expect a call to
-        // WebViewClient.onReceivedSslError().
-        final SslErrorWebViewClient webViewClient = new SslErrorWebViewClient();
-        startWebServer(true);
-        final String firstUrl = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL1);
-        mOnUiThread.setWebViewClient(webViewClient);
-        mOnUiThread.clearSslPreferences();
-        mOnUiThread.loadUrlAndWaitForCompletion(firstUrl);
-        assertTrue(webViewClient.wasOnReceivedSslErrorCalled());
-
-        // Load the second page. We expect another call to
-        // WebViewClient.onReceivedSslError().
-        webViewClient.resetWasOnReceivedSslErrorCalled();
-        // The test server uses the host "localhost". "127.0.0.1" works as an
-        // alias, but will be considered unique by the WebView.
-        final String differentHostUrl = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL2).replace(
-                "localhost", "127.0.0.1");
-        mOnUiThread.loadUrlAndWaitForCompletion(differentHostUrl);
-        assertTrue(webViewClient.wasOnReceivedSslErrorCalled());
-        assertEquals("Second page", mOnUiThread.getTitle());
-    }
-
     public void testRequestChildRectangleOnScreen() throws Throwable {
         if (!NullWebViewUtils.isWebViewAvailable()) {
             return;
@@ -2008,12 +2108,13 @@
         if (!NullWebViewUtils.isWebViewAvailable()) {
             return;
         }
+
+        final CountDownLatch resultLatch = new CountDownLatch(1);
         final class MyDownloadListener implements DownloadListener {
             public String url;
             public String mimeType;
             public long contentLength;
             public String contentDisposition;
-            public boolean called;
 
             @Override
             public void onDownloadStart(String url, String userAgent, String contentDisposition,
@@ -2022,7 +2123,7 @@
                 this.mimeType = mimetype;
                 this.contentLength = contentLength;
                 this.contentDisposition = contentDisposition;
-                this.called = true;
+                resultLatch.countDown();
             }
         }
 
@@ -2039,27 +2140,17 @@
         // the WebView will load the new URL.
         mOnUiThread.setDownloadListener(listener);
         mOnUiThread.getSettings().setJavaScriptEnabled(true);
-
-        // See b/13675265 for discussion on why the setTimeout is necessary.
-        // Works around a Blink bug.
         mOnUiThread.loadDataAndWaitForCompletion(
-                "<html><body onload=\"setTimeout(" +
-                "function() { window.location = \'" + url + "\'; }, 100);\">" +
-                "</body></html>", "text/html", null);
+                "<html><body onload=\"window.location = \'" + url + "\'\"></body></html>",
+                "text/html", null);
         // Wait for layout to complete before setting focus.
         getInstrumentation().waitForIdleSync();
 
-        new PollingCheck(TEST_TIMEOUT) {
-            @Override
-            protected boolean check() {
-                return listener.called;
-            }
-        }.run();
+        assertTrue(resultLatch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS));
         assertEquals(url, listener.url);
         assertTrue(listener.contentDisposition.contains("test.bin"));
-        // ToBeFixed: uncomment the following tests after fixing the framework
-        // assertEquals(mimeType, listener.mimeType);
-        // assertEquals(length, listener.contentLength);
+        assertEquals(length, listener.contentLength);
+        assertEquals(mimeType, listener.mimeType);
     }
 
     @UiThreadTest
@@ -2278,7 +2369,7 @@
                 .setResolution(new PrintAttributes.Resolution("foo", "bar", 300, 300))
                 .setMinMargins(PrintAttributes.Margins.NO_MARGINS)
                 .build();
-        final WebViewStubActivity activity = getActivity();
+        final WebViewCtsActivity activity = getActivity();
         final File file = activity.getFileStreamPath(PRINTER_TEST_FILE);
         final ParcelFileDescriptor descriptor = ParcelFileDescriptor.open(file,
                 ParcelFileDescriptor.parseMode("w"));
@@ -2349,11 +2440,6 @@
         });
     }
 
-    @UiThreadTest
-    public void testInternals() {
-        // Do not test these APIs. They are implementation details.
-    }
-
     private static class HrefCheckHandler extends Handler {
         private boolean mHadRecieved;
 
@@ -2448,51 +2534,6 @@
         return true;
     }
 
-    // Find b1 inside b2
-    private boolean checkBitmapInsideAnother(Bitmap b1, Bitmap b2) {
-        int w = b1.getWidth();
-        int h = b1.getHeight();
-
-        for (int i = 0; i < (b2.getWidth()-w+1); i++) {
-            for (int j = 0; j < (b2.getHeight()-h+1); j++) {
-                if (checkBitmapInsideAnother(b1, b2, i, j))
-                    return true;
-            }
-        }
-        return false;
-    }
-
-    private boolean comparePixel(int p1, int p2, int maxError) {
-        int err;
-        err = Math.abs(((p1&0xff000000)>>>24) - ((p2&0xff000000)>>>24));
-        if (err > maxError)
-            return false;
-
-        err = Math.abs(((p1&0x00ff0000)>>>16) - ((p2&0x00ff0000)>>>16));
-        if (err > maxError)
-            return false;
-
-        err = Math.abs(((p1&0x0000ff00)>>>8) - ((p2&0x0000ff00)>>>8));
-        if (err > maxError)
-            return false;
-
-        err = Math.abs(((p1&0x000000ff)>>>0) - ((p2&0x000000ff)>>>0));
-        if (err > maxError)
-            return false;
-
-        return true;
-    }
-
-    private boolean checkBitmapInsideAnother(Bitmap b1, Bitmap b2, int x, int y) {
-        for (int i = 0; i < b1.getWidth(); i++)
-            for (int j = 0; j < b1.getHeight(); j++) {
-                if (!comparePixel(b1.getPixel(i, j), b2.getPixel(x + i, y + j), 10)) {
-                    return false;
-                }
-            }
-        return true;
-    }
-
     /**
      * Waits at least MIN_SCROLL_WAIT_MS for scrolling to start. Once started,
      * scrolling is checked every SCROLL_WAIT_INTERVAL_MS for changes. Once
@@ -2518,31 +2559,6 @@
         }
     }
 
-    // Note that this class is not thread-safe.
-    final class SslErrorWebViewClient extends WaitForLoadedClient {
-        private boolean mWasOnReceivedSslErrorCalled;
-        private String mErrorUrl;
-
-        public SslErrorWebViewClient() {
-            super(mOnUiThread);
-        }
-        @Override
-        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
-            mWasOnReceivedSslErrorCalled = true;
-            mErrorUrl = error.getUrl();
-            handler.proceed();
-        }
-        public void resetWasOnReceivedSslErrorCalled() {
-            mWasOnReceivedSslErrorCalled = false;
-        }
-        public boolean wasOnReceivedSslErrorCalled() {
-            return mWasOnReceivedSslErrorCalled;
-        }
-        public String errorUrl() {
-            return mErrorUrl;
-        }
-    }
-
     private void pollingCheckForCanZoomIn() {
         new PollingCheck(TEST_TIMEOUT) {
             @Override
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebView_WebViewTransportTest.java b/tests/tests/webkit/src/android/webkit/cts/WebView_WebViewTransportTest.java
index cb72ef0..1db7fca 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebView_WebViewTransportTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebView_WebViewTransportTest.java
@@ -16,6 +16,7 @@
 
 package android.webkit.cts;
 
+import android.cts.util.NullWebViewUtils;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
 import android.webkit.WebView;
@@ -23,10 +24,10 @@
 
 
 public class WebView_WebViewTransportTest
-        extends ActivityInstrumentationTestCase2<WebViewStubActivity> {
+        extends ActivityInstrumentationTestCase2<WebViewCtsActivity> {
 
     public WebView_WebViewTransportTest() {
-        super("com.android.cts.stub", WebViewStubActivity.class);
+        super("com.android.cts.webkit", WebViewCtsActivity.class);
     }
 
     @UiThreadTest
diff --git a/tests/tests/widget/Android.mk b/tests/tests/widget/Android.mk
index f6be07d..505f82c 100644
--- a/tests/tests/widget/Android.mk
+++ b/tests/tests/widget/Android.mk
@@ -21,7 +21,7 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_STATIC_JAVA_LIBRARIES += android-common ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES += android-common ctsdeviceutil ctstestrunner
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
@@ -29,6 +29,4 @@
 
 LOCAL_PACKAGE_NAME := CtsWidgetTestCases
 
-LOCAL_INSTRUMENTATION_FOR := CtsTestStubs
-
 include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/widget/AndroidManifest.xml b/tests/tests/widget/AndroidManifest.xml
index e69a7d5..4b88c01 100644
--- a/tests/tests/widget/AndroidManifest.xml
+++ b/tests/tests/widget/AndroidManifest.xml
@@ -19,13 +19,339 @@
     package="com.android.cts.widget">
 
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
-    <application>
+    <application android:label="Android TestCase"
+            android:icon="@drawable/size_48x48"
+            android:maxRecents="1"
+            android:multiArch="true"
+            android:name="android.widget.cts.MockApplication"
+            android:supportsRtl="true">
+
         <uses-library android:name="android.test.runner" />
+
+        <activity android:name="android.widget.cts.TwoLineListItemCtsActivity"
+            android:label="TwoLineListItemCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.ViewFlipperCtsActivity"
+            android:label="ViewFlipperCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.HorizontalScrollViewCtsActivity"
+            android:label="HorizontalScrollViewCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.SlidingDrawerCtsActivity"
+            android:label="SlidingDrawerCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.DigitalClockCtsActivity"
+            android:label="DigitalClockCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.ImageViewCtsActivity"
+            android:label="ImageViewCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.SeekBarCtsActivity"
+            android:label="SeekBarCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.ScrollViewCtsActivity"
+            android:label="ScrollViewCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.FrameLayoutCtsActivity"
+            android:label="FrameLayoutCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.LinearLayoutCtsActivity"
+            android:label="LinearLayoutCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.GridLayoutCtsActivity"
+            android:label="GridLayoutCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.LayoutDirectionCtsActivity"
+            android:label="LayoutDirectionCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.ProgressBarCtsActivity"
+            android:label="ProgressBarCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.ChronometerCtsActivity"
+            android:label="ChronometerCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.MediaControllerCtsActivity"
+            android:label="MediaControllerCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.RatingBarCtsActivity"
+            android:label="RatingBarCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.RemoteViewsCtsActivity"
+            android:label="RemoteViewsCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.ExpandableListSimple"
+            android:label="ExpandableListSimple">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.CtsActivity"
+            android:label="CtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.ExpandableListWithHeaders"
+            android:label="ExpandableListWithHeaders">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.GalleryCtsActivity"
+            android:label="GalleryCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.MockPopupWindowCtsActivity"
+            android:label="MockPopupWindowCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.ListViewCtsActivity"
+            android:label="ListViewCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.TextViewCtsActivity"
+            android:label="TextViewCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.DialerFilterCtsActivity"
+            android:label="DialerFilterCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.MultiAutoCompleteTextViewCtsActivity"
+            android:label="MultiAutoCompleteTextView Test Activity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.ViewGroupCtsActivity"
+            android:label="WidgetViewGroupCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.VideoViewCtsActivity"
+            android:configChanges="keyboardHidden|orientation|screenSize">
+            android:label="VideoViewCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.AutoCompleteCtsActivity"
+            android:label="AutoCompleteCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.ViewAnimatorCtsActivity" android:label="ViewAnimatorCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.GridViewCtsActivity"
+            android:label="GridViewCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.RelativeLayoutCtsActivity"
+            android:label="RelativeLayoutCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.FrameLayoutCtsActivity"
+            android:label="FrameLayoutCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.AdapterViewCtsActivity"
+            android:label="AdapterViewCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.CheckedTextViewCtsActivity"
+            android:label="CheckedTextViewCtsActivity"/>
+
+        <activity android:name="android.widget.cts.TableCtsActivity"
+            android:label="TableCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.TabHostCtsActivity"
+            android:label="TabHostCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.widget.cts.ZoomButtonCtsActivity"
+            android:label="ZoomButtonCtsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="android.app.ActivityGroup"
+            android:label="ActivityGroup" />
+
+        <activity android:name="android.widget.cts.MockURLSpanTestActivity"
+            android:label="MockURLSpanTestActivity"
+            android:launchMode="singleTask"
+            android:alwaysRetainTaskState="true"
+            android:configChanges="orientation|keyboardHidden">
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.BROWSABLE" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+                <data android:scheme="ctstest" />
+            </intent-filter>
+        </activity>
+
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="com.android.cts.stub"
-                     android:label="CTS tests of android.widget"/>
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.cts.widget"
+                     android:label="CTS tests of android.widget">
+        <meta-data android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
 
 </manifest>
 
diff --git a/tests/res/anim/anim_alpha.xml b/tests/tests/widget/res/anim/anim_alpha.xml
similarity index 100%
copy from tests/res/anim/anim_alpha.xml
copy to tests/tests/widget/res/anim/anim_alpha.xml
diff --git a/tests/res/drawable/animated.gif b/tests/tests/widget/res/drawable/animated.gif
similarity index 100%
copy from tests/res/drawable/animated.gif
copy to tests/tests/widget/res/drawable/animated.gif
Binary files differ
diff --git a/tests/res/drawable/faces.jpg b/tests/tests/widget/res/drawable/faces.jpg
similarity index 100%
copy from tests/res/drawable/faces.jpg
copy to tests/tests/widget/res/drawable/faces.jpg
Binary files differ
diff --git a/tests/res/drawable/failed.jpg b/tests/tests/widget/res/drawable/failed.jpg
similarity index 100%
copy from tests/res/drawable/failed.jpg
copy to tests/tests/widget/res/drawable/failed.jpg
Binary files differ
diff --git a/tests/res/drawable/icon_black.jpg b/tests/tests/widget/res/drawable/icon_black.jpg
similarity index 100%
copy from tests/res/drawable/icon_black.jpg
copy to tests/tests/widget/res/drawable/icon_black.jpg
Binary files differ
diff --git a/tests/res/drawable/icon_blue.jpg b/tests/tests/widget/res/drawable/icon_blue.jpg
similarity index 100%
copy from tests/res/drawable/icon_blue.jpg
copy to tests/tests/widget/res/drawable/icon_blue.jpg
Binary files differ
diff --git a/tests/res/drawable/icon_green.jpg b/tests/tests/widget/res/drawable/icon_green.jpg
similarity index 100%
copy from tests/res/drawable/icon_green.jpg
copy to tests/tests/widget/res/drawable/icon_green.jpg
Binary files differ
diff --git a/tests/res/drawable/icon_red.jpg b/tests/tests/widget/res/drawable/icon_red.jpg
similarity index 100%
copy from tests/res/drawable/icon_red.jpg
copy to tests/tests/widget/res/drawable/icon_red.jpg
Binary files differ
diff --git a/tests/res/drawable/icon_yellow.jpg b/tests/tests/widget/res/drawable/icon_yellow.jpg
similarity index 100%
copy from tests/res/drawable/icon_yellow.jpg
copy to tests/tests/widget/res/drawable/icon_yellow.jpg
Binary files differ
diff --git a/tests/res/drawable/ninepatch_0.9.png b/tests/tests/widget/res/drawable/ninepatch_0.9.png
similarity index 100%
copy from tests/res/drawable/ninepatch_0.9.png
copy to tests/tests/widget/res/drawable/ninepatch_0.9.png
Binary files differ
diff --git a/tests/res/drawable/ninepatch_1.9.png b/tests/tests/widget/res/drawable/ninepatch_1.9.png
similarity index 100%
copy from tests/res/drawable/ninepatch_1.9.png
copy to tests/tests/widget/res/drawable/ninepatch_1.9.png
Binary files differ
diff --git a/tests/res/drawable/pass.jpg b/tests/tests/widget/res/drawable/pass.jpg
similarity index 100%
copy from tests/res/drawable/pass.jpg
copy to tests/tests/widget/res/drawable/pass.jpg
Binary files differ
diff --git a/tests/res/drawable/scenery.jpg b/tests/tests/widget/res/drawable/scenery.jpg
similarity index 100%
copy from tests/res/drawable/scenery.jpg
copy to tests/tests/widget/res/drawable/scenery.jpg
Binary files differ
diff --git a/tests/res/drawable/size_48x48.jpg b/tests/tests/widget/res/drawable/size_48x48.jpg
similarity index 100%
copy from tests/res/drawable/size_48x48.jpg
copy to tests/tests/widget/res/drawable/size_48x48.jpg
Binary files differ
diff --git a/tests/res/drawable/start.jpg b/tests/tests/widget/res/drawable/start.jpg
similarity index 100%
copy from tests/res/drawable/start.jpg
copy to tests/tests/widget/res/drawable/start.jpg
Binary files differ
diff --git a/tests/res/drawable/testimage.jpg b/tests/tests/widget/res/drawable/testimage.jpg
similarity index 100%
copy from tests/res/drawable/testimage.jpg
copy to tests/tests/widget/res/drawable/testimage.jpg
Binary files differ
diff --git a/tests/res/layout/abslistview_layout.xml b/tests/tests/widget/res/layout/abslistview_layout.xml
similarity index 100%
copy from tests/res/layout/abslistview_layout.xml
copy to tests/tests/widget/res/layout/abslistview_layout.xml
diff --git a/tests/res/layout/absolute_layout.xml b/tests/tests/widget/res/layout/absolute_layout.xml
similarity index 100%
rename from tests/res/layout/absolute_layout.xml
rename to tests/tests/widget/res/layout/absolute_layout.xml
diff --git a/tests/res/layout/adapterview_layout.xml b/tests/tests/widget/res/layout/adapterview_layout.xml
similarity index 100%
rename from tests/res/layout/adapterview_layout.xml
rename to tests/tests/widget/res/layout/adapterview_layout.xml
diff --git a/tests/res/layout/analogclock.xml b/tests/tests/widget/res/layout/analogclock.xml
similarity index 100%
rename from tests/res/layout/analogclock.xml
rename to tests/tests/widget/res/layout/analogclock.xml
diff --git a/tests/tests/widget/res/layout/autocompletetextview_layout.xml b/tests/tests/widget/res/layout/autocompletetextview_layout.xml
new file mode 100644
index 0000000..25a8541
--- /dev/null
+++ b/tests/tests/widget/res/layout/autocompletetextview_layout.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+
+    <TextView android:id="@+id/autocompletetv_title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/notify" />
+
+    <AutoCompleteTextView android:id="@+id/autocompletetv_edit"
+        android:completionThreshold="1"
+        android:completionHint="@string/tabs_1"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:inputType="none"/>
+</LinearLayout>
diff --git a/tests/res/layout/checkbox_layout.xml b/tests/tests/widget/res/layout/checkbox_layout.xml
similarity index 100%
copy from tests/res/layout/checkbox_layout.xml
copy to tests/tests/widget/res/layout/checkbox_layout.xml
diff --git a/tests/res/layout/checkedtextview_layout.xml b/tests/tests/widget/res/layout/checkedtextview_layout.xml
similarity index 100%
rename from tests/res/layout/checkedtextview_layout.xml
rename to tests/tests/widget/res/layout/checkedtextview_layout.xml
diff --git a/tests/res/layout/chronometer_stub_layout.xml b/tests/tests/widget/res/layout/chronometer_stub_layout.xml
similarity index 100%
rename from tests/res/layout/chronometer_stub_layout.xml
rename to tests/tests/widget/res/layout/chronometer_stub_layout.xml
diff --git a/tests/res/layout/cursoradapter_group0.xml b/tests/tests/widget/res/layout/cursoradapter_group0.xml
similarity index 100%
rename from tests/res/layout/cursoradapter_group0.xml
rename to tests/tests/widget/res/layout/cursoradapter_group0.xml
diff --git a/tests/res/layout/cursoradapter_group1.xml b/tests/tests/widget/res/layout/cursoradapter_group1.xml
similarity index 100%
rename from tests/res/layout/cursoradapter_group1.xml
rename to tests/tests/widget/res/layout/cursoradapter_group1.xml
diff --git a/tests/res/layout/cursoradapter_host.xml b/tests/tests/widget/res/layout/cursoradapter_host.xml
similarity index 100%
rename from tests/res/layout/cursoradapter_host.xml
rename to tests/tests/widget/res/layout/cursoradapter_host.xml
diff --git a/tests/res/layout/cursoradapter_item0.xml b/tests/tests/widget/res/layout/cursoradapter_item0.xml
similarity index 100%
rename from tests/res/layout/cursoradapter_item0.xml
rename to tests/tests/widget/res/layout/cursoradapter_item0.xml
diff --git a/tests/res/layout/cursoradapter_item1.xml b/tests/tests/widget/res/layout/cursoradapter_item1.xml
similarity index 100%
rename from tests/res/layout/cursoradapter_item1.xml
rename to tests/tests/widget/res/layout/cursoradapter_item1.xml
diff --git a/tests/res/layout/datepicker_layout.xml b/tests/tests/widget/res/layout/datepicker_layout.xml
similarity index 100%
rename from tests/res/layout/datepicker_layout.xml
rename to tests/tests/widget/res/layout/datepicker_layout.xml
diff --git a/tests/res/layout/dialerfilter_layout.xml b/tests/tests/widget/res/layout/dialerfilter_layout.xml
similarity index 100%
rename from tests/res/layout/dialerfilter_layout.xml
rename to tests/tests/widget/res/layout/dialerfilter_layout.xml
diff --git a/tests/tests/widget/res/layout/digitalclock_layout.xml b/tests/tests/widget/res/layout/digitalclock_layout.xml
new file mode 100644
index 0000000..d405af2
--- /dev/null
+++ b/tests/tests/widget/res/layout/digitalclock_layout.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<com.android.cts.widget.alarmclock.DigitalClock android:id="@+id/digitalClock"
+     xmlns:android="http://schemas.android.com/apk/res/android"
+     android:layout_width="wrap_content"
+     android:layout_height="208dip"
+     android:gravity="center">
+     <!-- Includes vertical padding so animated background doesn't
+          stretch much -->
+     <TextView android:id="@+id/timeDisplay"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:textSize="64sp"
+         android:paddingRight="4dip"
+         android:paddingTop="48dip"
+         android:paddingBottom="48dip"/>
+     <LinearLayout android:id="@+id/am_pm"
+         android:layout_width="wrap_content"
+         android:layout_height="wrap_content"
+         android:orientation="vertical">
+         <TextView android:id="@+id/am"
+             android:layout_width="wrap_content"
+             android:layout_height="wrap_content"
+             android:layout_marginTop="-7dp"
+             android:text="@string/am"
+             android:textSize="28sp"/>
+         <TextView android:id="@+id/pm"
+             android:layout_width="wrap_content"
+             android:layout_height="wrap_content"
+             android:layout_marginTop="-4dp"
+             android:text="@string/pm"
+             android:textSize="28sp"/>
+     </LinearLayout>
+</com.android.cts.widget.alarmclock.DigitalClock>
diff --git a/tests/res/layout/digitalclock_simplelayout.xml b/tests/tests/widget/res/layout/digitalclock_simplelayout.xml
similarity index 100%
rename from tests/res/layout/digitalclock_simplelayout.xml
rename to tests/tests/widget/res/layout/digitalclock_simplelayout.xml
diff --git a/tests/res/layout/edittext_layout.xml b/tests/tests/widget/res/layout/edittext_layout.xml
similarity index 100%
rename from tests/res/layout/edittext_layout.xml
rename to tests/tests/widget/res/layout/edittext_layout.xml
diff --git a/tests/res/layout/expandablelistview_layout.xml b/tests/tests/widget/res/layout/expandablelistview_layout.xml
similarity index 100%
rename from tests/res/layout/expandablelistview_layout.xml
rename to tests/tests/widget/res/layout/expandablelistview_layout.xml
diff --git a/tests/tests/widget/res/layout/framelayout_layout.xml b/tests/tests/widget/res/layout/framelayout_layout.xml
new file mode 100644
index 0000000..78b7b47
--- /dev/null
+++ b/tests/tests/widget/res/layout/framelayout_layout.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2008 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.
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:id="@+id/framelayout_container"
+                android:background="@drawable/red"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_gravity="bottom"
+                android:orientation="vertical">
+
+    <FrameLayout
+        android:layout_width="100dip"
+        android:layout_height="100dip"
+        android:background="@drawable/yellow"
+        android:id="@+id/framelayout">
+    </FrameLayout>
+
+    <FrameLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:background="@drawable/yellow"
+        android:id="@+id/framelayout_measureall">
+
+        <TextView android:id="@+id/framelayout_textview"
+            android:background="@drawable/blue"
+            android:layout_width="60dip"
+            android:layout_height="30dip"
+            android:text="@string/hello_world"/>
+
+        <Button android:id="@+id/framelayout_button"
+            android:layout_width="50dip"
+            android:layout_height="15dip"
+            android:text="@string/go"/>
+
+    </FrameLayout>
+
+    <FrameLayout
+        android:id="@+id/foreground_tint"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:foregroundTint="@android:color/white"
+        android:foregroundTintMode="src_over" />
+
+</LinearLayout>
diff --git a/tests/res/layout/gallery_test.xml b/tests/tests/widget/res/layout/gallery_test.xml
similarity index 100%
rename from tests/res/layout/gallery_test.xml
rename to tests/tests/widget/res/layout/gallery_test.xml
diff --git a/tests/res/layout/gridlayout_layout.xml b/tests/tests/widget/res/layout/gridlayout_layout.xml
similarity index 100%
rename from tests/res/layout/gridlayout_layout.xml
rename to tests/tests/widget/res/layout/gridlayout_layout.xml
diff --git a/tests/res/layout/gridview_layout.xml b/tests/tests/widget/res/layout/gridview_layout.xml
similarity index 100%
rename from tests/res/layout/gridview_layout.xml
rename to tests/tests/widget/res/layout/gridview_layout.xml
diff --git a/tests/res/layout/horizontal_scrollview.xml b/tests/tests/widget/res/layout/horizontal_scrollview.xml
similarity index 100%
rename from tests/res/layout/horizontal_scrollview.xml
rename to tests/tests/widget/res/layout/horizontal_scrollview.xml
diff --git a/tests/res/layout/imagebutton_test.xml b/tests/tests/widget/res/layout/imagebutton_test.xml
similarity index 100%
rename from tests/res/layout/imagebutton_test.xml
rename to tests/tests/widget/res/layout/imagebutton_test.xml
diff --git a/tests/res/layout/imageswitcher_test.xml b/tests/tests/widget/res/layout/imageswitcher_test.xml
similarity index 100%
rename from tests/res/layout/imageswitcher_test.xml
rename to tests/tests/widget/res/layout/imageswitcher_test.xml
diff --git a/tests/tests/widget/res/layout/imageview_layout.xml b/tests/tests/widget/res/layout/imageview_layout.xml
new file mode 100644
index 0000000..e56a9c9
--- /dev/null
+++ b/tests/tests/widget/res/layout/imageview_layout.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2008 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.
+ */
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <ImageView
+        android:id="@+id/imageview"
+        android:layout_width="320px"
+        android:layout_height="240px"/>
+
+    <ImageView
+        android:id="@+id/image_tint"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:tint="@android:color/white"
+        android:tintMode="src_over" />
+
+</LinearLayout>
+
diff --git a/tests/res/layout/layoutdirection_layout.xml b/tests/tests/widget/res/layout/layoutdirection_layout.xml
similarity index 100%
rename from tests/res/layout/layoutdirection_layout.xml
rename to tests/tests/widget/res/layout/layoutdirection_layout.xml
diff --git a/tests/res/layout/linearlayout_layout.xml b/tests/tests/widget/res/layout/linearlayout_layout.xml
similarity index 100%
rename from tests/res/layout/linearlayout_layout.xml
rename to tests/tests/widget/res/layout/linearlayout_layout.xml
diff --git a/tests/res/layout/listview_layout.xml b/tests/tests/widget/res/layout/listview_layout.xml
similarity index 100%
rename from tests/res/layout/listview_layout.xml
rename to tests/tests/widget/res/layout/listview_layout.xml
diff --git a/tests/res/layout/mediacontroller_layout.xml b/tests/tests/widget/res/layout/mediacontroller_layout.xml
similarity index 100%
rename from tests/res/layout/mediacontroller_layout.xml
rename to tests/tests/widget/res/layout/mediacontroller_layout.xml
diff --git a/tests/res/layout/multi_auto_complete_text_view_layout.xml b/tests/tests/widget/res/layout/multi_auto_complete_text_view_layout.xml
similarity index 100%
rename from tests/res/layout/multi_auto_complete_text_view_layout.xml
rename to tests/tests/widget/res/layout/multi_auto_complete_text_view_layout.xml
diff --git a/tests/tests/widget/res/layout/popupwindow.xml b/tests/tests/widget/res/layout/popupwindow.xml
new file mode 100644
index 0000000..f93f965
--- /dev/null
+++ b/tests/tests/widget/res/layout/popupwindow.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <View android:id="@+id/anchor_upper"
+        android:layout_width="10dp"
+        android:layout_height="10dp"
+        android:layout_alignParentTop="true"
+        android:layout_centerHorizontal="true"
+        android:background="#f00" />
+
+    <View android:id="@+id/anchor_lower"
+        android:layout_width="10dp"
+        android:layout_height="10dp"
+        android:layout_alignParentBottom="true"
+        android:layout_centerHorizontal="true"
+        android:background="#0f0" />
+
+    <View android:id="@+id/anchor_middle_left"
+        android:layout_width="10dp"
+        android:layout_height="10dp"
+        android:layout_alignParentLeft="true"
+        android:layout_centerVertical="true"
+        android:background="#00f" />
+
+    <View android:id="@+id/anchor_middle_right"
+        android:layout_width="10dp"
+        android:layout_height="10dp"
+        android:layout_alignParentRight="true"
+        android:layout_centerVertical="true"
+        android:background="#ff0" />
+
+</RelativeLayout>
diff --git a/tests/tests/widget/res/layout/progressbar_layout.xml b/tests/tests/widget/res/layout/progressbar_layout.xml
new file mode 100644
index 0000000..a1786b8
--- /dev/null
+++ b/tests/tests/widget/res/layout/progressbar_layout.xml
@@ -0,0 +1,41 @@
+<?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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <ProgressBar
+        android:id="@+id/progress_tint"
+        android:progressTint="@android:color/white"
+        android:progressTintMode="src_over"
+        android:progressBackgroundTint="@android:color/white"
+        android:progressBackgroundTintMode="src_over"
+        android:secondaryProgressTint="@android:color/white"
+        android:secondaryProgressTintMode="src_over"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        style="@android:style/Widget.ProgressBar.Horizontal" />
+
+    <ProgressBar
+        android:id="@+id/indeterminate_tint"
+        android:indeterminateTint="@android:color/white"
+        android:indeterminateTintMode="src_over"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        style="@android:style/Widget.ProgressBar.Large" />
+
+</LinearLayout>
diff --git a/tests/res/layout/radiogroup_1.xml b/tests/tests/widget/res/layout/radiogroup_1.xml
similarity index 100%
rename from tests/res/layout/radiogroup_1.xml
rename to tests/tests/widget/res/layout/radiogroup_1.xml
diff --git a/tests/res/layout/ratingbar_layout.xml b/tests/tests/widget/res/layout/ratingbar_layout.xml
similarity index 100%
rename from tests/res/layout/ratingbar_layout.xml
rename to tests/tests/widget/res/layout/ratingbar_layout.xml
diff --git a/tests/res/layout/relative_layout.xml b/tests/tests/widget/res/layout/relative_layout.xml
similarity index 100%
rename from tests/res/layout/relative_layout.xml
rename to tests/tests/widget/res/layout/relative_layout.xml
diff --git a/tests/res/layout/remote_view_test_bad_1.xml b/tests/tests/widget/res/layout/remote_view_test_bad_1.xml
similarity index 100%
rename from tests/res/layout/remote_view_test_bad_1.xml
rename to tests/tests/widget/res/layout/remote_view_test_bad_1.xml
diff --git a/tests/res/layout/remote_view_test_bad_2.xml b/tests/tests/widget/res/layout/remote_view_test_bad_2.xml
similarity index 100%
rename from tests/res/layout/remote_view_test_bad_2.xml
rename to tests/tests/widget/res/layout/remote_view_test_bad_2.xml
diff --git a/tests/res/layout/remote_view_test_good.xml b/tests/tests/widget/res/layout/remote_view_test_good.xml
similarity index 100%
rename from tests/res/layout/remote_view_test_good.xml
rename to tests/tests/widget/res/layout/remote_view_test_good.xml
diff --git a/tests/res/layout/remoteviews_good.xml b/tests/tests/widget/res/layout/remoteviews_good.xml
similarity index 100%
rename from tests/res/layout/remoteviews_good.xml
rename to tests/tests/widget/res/layout/remoteviews_good.xml
diff --git a/tests/res/layout/remoteviews_host.xml b/tests/tests/widget/res/layout/remoteviews_host.xml
similarity index 100%
rename from tests/res/layout/remoteviews_host.xml
rename to tests/tests/widget/res/layout/remoteviews_host.xml
diff --git a/tests/res/layout/scrollview_layout.xml b/tests/tests/widget/res/layout/scrollview_layout.xml
similarity index 100%
rename from tests/res/layout/scrollview_layout.xml
rename to tests/tests/widget/res/layout/scrollview_layout.xml
diff --git a/tests/tests/widget/res/layout/seekbar_layout.xml b/tests/tests/widget/res/layout/seekbar_layout.xml
new file mode 100644
index 0000000..5c311fd
--- /dev/null
+++ b/tests/tests/widget/res/layout/seekbar_layout.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+     <SeekBar android:id="@+id/seekBar"
+         android:layout_width="match_parent"
+         android:layout_height="wrap_content"
+         android:max="100"
+         android:progress="50"
+         android:secondaryProgress="75" />
+
+    <SeekBar
+        android:id="@+id/thumb_tint"
+        android:thumbTint="@android:color/white"
+        android:thumbTintMode="src_over"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" />
+
+</LinearLayout>
diff --git a/tests/res/layout/simple_dropdown_item_1line.xml b/tests/tests/widget/res/layout/simple_dropdown_item_1line.xml
similarity index 100%
rename from tests/res/layout/simple_dropdown_item_1line.xml
rename to tests/tests/widget/res/layout/simple_dropdown_item_1line.xml
diff --git a/tests/tests/widget/res/layout/simple_spinner_item.xml b/tests/tests/widget/res/layout/simple_spinner_item.xml
new file mode 100644
index 0000000..d52922a
--- /dev/null
+++ b/tests/tests/widget/res/layout/simple_spinner_item.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@android:id/text1"
+    style="?android:attr/spinnerItemStyle"
+    android:singleLine="true"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content" />
diff --git a/tests/res/layout/sliding_drawer_layout.xml b/tests/tests/widget/res/layout/sliding_drawer_layout.xml
similarity index 100%
rename from tests/res/layout/sliding_drawer_layout.xml
rename to tests/tests/widget/res/layout/sliding_drawer_layout.xml
diff --git a/tests/res/layout/tabhost_layout.xml b/tests/tests/widget/res/layout/tabhost_layout.xml
similarity index 100%
rename from tests/res/layout/tabhost_layout.xml
rename to tests/tests/widget/res/layout/tabhost_layout.xml
diff --git a/tests/res/layout/table_layout_1.xml b/tests/tests/widget/res/layout/table_layout_1.xml
similarity index 100%
rename from tests/res/layout/table_layout_1.xml
rename to tests/tests/widget/res/layout/table_layout_1.xml
diff --git a/tests/res/layout/table_layout_2.xml b/tests/tests/widget/res/layout/table_layout_2.xml
similarity index 100%
rename from tests/res/layout/table_layout_2.xml
rename to tests/tests/widget/res/layout/table_layout_2.xml
diff --git a/tests/res/layout/textview_autolink.xml b/tests/tests/widget/res/layout/textview_autolink.xml
similarity index 100%
rename from tests/res/layout/textview_autolink.xml
rename to tests/tests/widget/res/layout/textview_autolink.xml
diff --git a/tests/res/layout/textview_ellipsize.xml b/tests/tests/widget/res/layout/textview_ellipsize.xml
similarity index 100%
rename from tests/res/layout/textview_ellipsize.xml
rename to tests/tests/widget/res/layout/textview_ellipsize.xml
diff --git a/tests/res/layout/textview_gravity.xml b/tests/tests/widget/res/layout/textview_gravity.xml
similarity index 100%
rename from tests/res/layout/textview_gravity.xml
rename to tests/tests/widget/res/layout/textview_gravity.xml
diff --git a/tests/res/layout/textview_hint_linksclickable_freezestext.xml b/tests/tests/widget/res/layout/textview_hint_linksclickable_freezestext.xml
similarity index 100%
rename from tests/res/layout/textview_hint_linksclickable_freezestext.xml
rename to tests/tests/widget/res/layout/textview_hint_linksclickable_freezestext.xml
diff --git a/tests/tests/widget/res/layout/textview_layout.xml b/tests/tests/widget/res/layout/textview_layout.xml
new file mode 100644
index 0000000..419bbf9
--- /dev/null
+++ b/tests/tests/widget/res/layout/textview_layout.xml
@@ -0,0 +1,220 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:id="@+id/layout_textviewtest">
+
+    <ScrollView android:layout_width="match_parent"
+            android:layout_height="match_parent">
+
+        <LinearLayout android:orientation="vertical"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent">
+
+            <TextView android:id="@+id/textview_textAttr"
+                    android:text="@string/text_view_hello"
+                    android:textColor="@drawable/black"
+                    android:textColorHighlight="@drawable/yellow"
+                    android:textColorHint="@drawable/red"
+                    android:textColorLink="@drawable/blue"
+                    android:textScaleX="1.2"
+                    android:typeface="normal"
+                    android:textSize="20px"
+                    android:textStyle="normal"
+                    android:textAppearance="@null"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"/>
+
+            <TextView android:id="@+id/textview_password"
+                    android:password="true"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"/>
+
+            <TextView android:id="@+id/textview_singleLine"
+                    android:singleLine="true"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"/>
+
+            <TextView android:id="@+id/textview_text"
+                    android:text="@string/text_view_hello"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"/>
+
+            <TextView android:id="@+id/textview_text_two_lines"
+                    android:text="@string/text_view_hello_two_lines"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"/>
+
+            <android.widget.cts.MockTextView
+                    android:id="@+id/mock_textview_left"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:requiresFadingEdge="horizontal"
+                    android:singleLine="true"
+                    android:text="@string/long_text"
+                    android:gravity="left"
+                    />
+
+            <android.widget.cts.MockTextView
+                    android:id="@+id/mock_textview_right"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:requiresFadingEdge="horizontal"
+                    android:singleLine="true"
+                    android:text="@string/long_text"
+                    android:gravity="right"
+                    />
+
+            <android.widget.cts.MockTextView
+                    android:id="@+id/mock_textview_center"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:requiresFadingEdge="horizontal"
+                    android:singleLine="true"
+                    android:text="@string/long_text"
+                    android:gravity="center"
+                    />
+        </LinearLayout>
+
+    </ScrollView>
+
+    <TextView android:id="@+id/textview_ltr"
+              android:layout_height="wrap_content"
+              android:layout_width="wrap_content"/>
+
+    <TextView android:id="@+id/textview_rtl"
+              android:layout_height="wrap_content"
+              android:layout_width="wrap_content"/>
+
+    <TextView android:id="@+id/textview_drawable_1_1"
+              android:layout_height="wrap_content"
+              android:layout_width="wrap_content"
+              android:drawableLeft="@drawable/icon_blue"
+              android:drawableRight="@drawable/icon_red"
+              android:drawableTop="@drawable/icon_green"
+              android:drawableBottom="@drawable/icon_yellow"
+            />
+
+    <TextView android:id="@+id/textview_drawable_1_2"
+              android:layout_height="wrap_content"
+              android:layout_width="wrap_content"
+              android:drawableLeft="@drawable/icon_blue"
+              android:drawableRight="@drawable/icon_red"
+              android:drawableTop="@drawable/icon_green"
+              android:drawableBottom="@drawable/icon_yellow"
+              android:layoutDirection="rtl"
+            />
+
+    <TextView android:id="@+id/textview_drawable_2_1"
+              android:layout_height="wrap_content"
+              android:layout_width="wrap_content"
+              android:drawableStart="@drawable/icon_blue"
+              android:drawableEnd="@drawable/icon_red"
+              android:drawableTop="@drawable/icon_green"
+              android:drawableBottom="@drawable/icon_yellow"
+            />
+
+    <TextView android:id="@+id/textview_drawable_2_2"
+              android:layout_height="wrap_content"
+              android:layout_width="wrap_content"
+              android:drawableStart="@drawable/icon_blue"
+              android:drawableEnd="@drawable/icon_red"
+              android:drawableTop="@drawable/icon_green"
+              android:drawableBottom="@drawable/icon_yellow"
+              android:layoutDirection="rtl"
+            />
+
+    <TextView android:id="@+id/textview_drawable_3_1"
+              android:layout_height="wrap_content"
+              android:layout_width="wrap_content"
+              android:drawableLeft="@drawable/icon_black"
+              android:drawableRight="@drawable/icon_black"
+              android:drawableStart="@drawable/icon_blue"
+              android:drawableEnd="@drawable/icon_red"
+              android:drawableTop="@drawable/icon_green"
+              android:drawableBottom="@drawable/icon_yellow"
+            />
+
+    <TextView android:id="@+id/textview_drawable_3_2"
+              android:layout_height="wrap_content"
+              android:layout_width="wrap_content"
+              android:drawableLeft="@drawable/icon_black"
+              android:drawableRight="@drawable/icon_black"
+              android:drawableStart="@drawable/icon_blue"
+              android:drawableEnd="@drawable/icon_red"
+              android:drawableTop="@drawable/icon_green"
+              android:drawableBottom="@drawable/icon_yellow"
+              android:layoutDirection="rtl"
+            />
+
+
+    <LinearLayout android:orientation="vertical"
+                  android:layout_width="match_parent"
+                  android:layout_height="match_parent"
+                  android:layoutDirection="ltr">
+
+        <TextView android:id="@+id/textview_drawable_4_1"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:drawableStart="@drawable/icon_blue"
+                  android:drawableEnd="@drawable/icon_red"
+                  android:drawableTop="@drawable/icon_green"
+                  android:drawableBottom="@drawable/icon_yellow"
+                />
+
+        <TextView android:id="@+id/textview_drawable_5_1"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:drawableLeft="@drawable/icon_black"
+                  android:drawableRight="@drawable/icon_black"
+                  android:drawableStart="@drawable/icon_blue"
+                  android:drawableEnd="@drawable/icon_red"
+                  android:drawableTop="@drawable/icon_green"
+                  android:drawableBottom="@drawable/icon_yellow"
+                />
+
+    </LinearLayout>
+
+    <LinearLayout android:orientation="vertical"
+                  android:layout_width="match_parent"
+                  android:layout_height="match_parent"
+                  android:layoutDirection="rtl">
+
+        <TextView android:id="@+id/textview_drawable_4_2"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:drawableStart="@drawable/icon_blue"
+                  android:drawableEnd="@drawable/icon_red"
+                  android:drawableTop="@drawable/icon_green"
+                  android:drawableBottom="@drawable/icon_yellow"
+                />
+
+        <TextView android:id="@+id/textview_drawable_5_2"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:drawableLeft="@drawable/icon_black"
+                  android:drawableRight="@drawable/icon_black"
+                  android:drawableStart="@drawable/icon_blue"
+                  android:drawableEnd="@drawable/icon_red"
+                  android:drawableTop="@drawable/icon_green"
+                  android:drawableBottom="@drawable/icon_yellow"
+                />
+
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/tests/res/layout/textview_selectallonfocus.xml b/tests/tests/widget/res/layout/textview_selectallonfocus.xml
similarity index 100%
rename from tests/res/layout/textview_selectallonfocus.xml
rename to tests/tests/widget/res/layout/textview_selectallonfocus.xml
diff --git a/tests/res/layout/timepicker.xml b/tests/tests/widget/res/layout/timepicker.xml
similarity index 100%
rename from tests/res/layout/timepicker.xml
rename to tests/tests/widget/res/layout/timepicker.xml
diff --git a/tests/tests/widget/res/layout/togglebutton_layout.xml b/tests/tests/widget/res/layout/togglebutton_layout.xml
new file mode 100644
index 0000000..a6c08e1
--- /dev/null
+++ b/tests/tests/widget/res/layout/togglebutton_layout.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2008 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.
+ -->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+
+        <ToggleButton android:id="@+id/toggle1"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+
+        <ToggleButton android:id="@+id/toggle2"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+
+        <ToggleButton android:id="@+id/button_tint"
+            android:buttonTint="@android:color/white"
+            android:buttonTintMode="src_over"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+
+    </LinearLayout>
+
+</ScrollView>
diff --git a/tests/res/layout/twolinelistitem.xml b/tests/tests/widget/res/layout/twolinelistitem.xml
similarity index 100%
rename from tests/res/layout/twolinelistitem.xml
rename to tests/tests/widget/res/layout/twolinelistitem.xml
diff --git a/tests/res/layout/urlspan_layout.xml b/tests/tests/widget/res/layout/urlspan_layout.xml
similarity index 100%
copy from tests/res/layout/urlspan_layout.xml
copy to tests/tests/widget/res/layout/urlspan_layout.xml
diff --git a/tests/res/layout/videoview_layout.xml b/tests/tests/widget/res/layout/videoview_layout.xml
similarity index 100%
rename from tests/res/layout/videoview_layout.xml
rename to tests/tests/widget/res/layout/videoview_layout.xml
diff --git a/tests/res/layout/viewanimator_layout.xml b/tests/tests/widget/res/layout/viewanimator_layout.xml
similarity index 100%
rename from tests/res/layout/viewanimator_layout.xml
rename to tests/tests/widget/res/layout/viewanimator_layout.xml
diff --git a/tests/res/layout/viewflipper_layout.xml b/tests/tests/widget/res/layout/viewflipper_layout.xml
similarity index 100%
rename from tests/res/layout/viewflipper_layout.xml
rename to tests/tests/widget/res/layout/viewflipper_layout.xml
diff --git a/tests/res/layout/viewgrouptest_stub.xml b/tests/tests/widget/res/layout/viewgrouptest_stub.xml
similarity index 100%
rename from tests/res/layout/viewgrouptest_stub.xml
rename to tests/tests/widget/res/layout/viewgrouptest_stub.xml
diff --git a/tests/res/layout/viewswitcher_layout.xml b/tests/tests/widget/res/layout/viewswitcher_layout.xml
similarity index 100%
rename from tests/res/layout/viewswitcher_layout.xml
rename to tests/tests/widget/res/layout/viewswitcher_layout.xml
diff --git a/tests/res/layout/zoombutton_layout.xml b/tests/tests/widget/res/layout/zoombutton_layout.xml
similarity index 100%
rename from tests/res/layout/zoombutton_layout.xml
rename to tests/tests/widget/res/layout/zoombutton_layout.xml
diff --git a/tests/res/raw/scenery.jpg b/tests/tests/widget/res/raw/scenery.jpg
similarity index 100%
rename from tests/res/raw/scenery.jpg
rename to tests/tests/widget/res/raw/scenery.jpg
Binary files differ
diff --git a/tests/res/raw/testimage.jpg b/tests/tests/widget/res/raw/testimage.jpg
similarity index 100%
copy from tests/res/raw/testimage.jpg
copy to tests/tests/widget/res/raw/testimage.jpg
Binary files differ
diff --git a/tests/res/raw/testvideo.3gp b/tests/tests/widget/res/raw/testvideo.3gp
similarity index 100%
rename from tests/res/raw/testvideo.3gp
rename to tests/tests/widget/res/raw/testvideo.3gp
Binary files differ
diff --git a/tests/res/values/arrays.xml b/tests/tests/widget/res/values/arrays.xml
similarity index 100%
copy from tests/res/values/arrays.xml
copy to tests/tests/widget/res/values/arrays.xml
diff --git a/tests/tests/widget/res/values/attrs.xml b/tests/tests/widget/res/values/attrs.xml
new file mode 100644
index 0000000..4c3d9db
--- /dev/null
+++ b/tests/tests/widget/res/values/attrs.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2008 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>
+    <declare-styleable name="Style1">
+        <attr name="Type1" format="integer">
+            <enum name="type" value="28" />
+            <enum name="data" value="0xff00ff00" />
+            <enum name="asset_cookie" value="0" />
+            <enum name="resource_id" value="0" />
+            <enum name="changing_config" value="0" />
+        </attr>
+        <attr name="Type2" format="integer">
+            <enum name="type" value="28" />
+            <enum name="data" value="0xff0000ff" />
+            <enum name="asset_cookie" value="0" />
+            <enum name="resource_id" value="0" />
+            <enum name="changing_config" value="0" />
+        </attr>
+    </declare-styleable>
+    <attr name="type1" format="boolean"/>
+    <attr name="type2" format="boolean"/>
+    <attr name="type3" format="color"/>
+    <attr name="type4" format="reference|color"/>
+    <attr name="type5" format="dimension"/>
+    <attr name="type6" format="dimension"/>
+    <attr name="type7" format="dimension"/>
+    <attr name="type8" format="reference"/>
+    <attr name="type9" format="float"/>
+    <attr name="type10" format="fraction"/>
+    <attr name="type11" format="integer"/>
+    <attr name="type12" format="integer"/>
+    <attr name="type13" format="reference|string"/>
+    <attr name="type14" format="string"/>
+    <attr name="type15" format="reference"/>
+    <attr name="type16" format="string"/>
+    <declare-styleable name="style1">
+        <attr name="type1"/>
+        <attr name="type2"/>
+        <attr name="type3"/>
+        <attr name="type4"/>
+        <attr name="type5"/>
+        <attr name="type6"/>
+        <attr name="type7"/>
+        <attr name="type8"/>
+        <attr name="type9"/>
+        <attr name="type10"/>
+        <attr name="type11"/>
+        <attr name="type12"/>
+        <attr name="type13"/>
+        <attr name="type14"/>
+        <attr name="type15"/>
+        <attr name="type16"/>
+    </declare-styleable>
+    <attr name="testEnum">
+        <enum name="val1" value="1" />
+        <enum name="val2" value="2" />
+        <enum name="val10" value="10" />
+    </attr>
+    <attr name="testFlags">
+        <flag name="bit1" value="0x1" />
+        <flag name="bit2" value="0x2" />
+        <flag name="bit31" value="0x40000000" />
+    </attr>
+    <attr name="testString" format="string" />
+    <declare-styleable name="EnumStyle">
+        <attr name="testEnum" />
+    </declare-styleable>
+    <declare-styleable name="FlagStyle">
+        <attr name="testFlags" />
+    </declare-styleable>
+    <declare-styleable name="TestConfig">
+        <attr name="testString" />
+    </declare-styleable>
+    <!-- Size of text. Recommended dimension type for text is "sp" for scaled-pixels (example: 15sp).
+         Supported values include the following:<p/>
+    <ul>
+        <li><b>px</b> Pixels</li>
+        <li><b>sp</b> Scaled pixels (scaled to relative pixel size on screen). See {@link android.util.DisplayMetrics} for more information.</li>
+        <li><b>pt</b> Points</li>
+        <li><b>dip</b> Device independent pixels. See {@link android.util.DisplayMetrics} for more information.</li>
+    </ul>
+    -->
+    <attr name="textSize" format="dimension" />
+    <attr name="typeface">
+        <enum name="normal" value="0" />
+        <enum name="sans" value="1" />
+        <enum name="serif" value="2" />
+        <enum name="monospace" value="3" />
+    </attr>
+    <!-- Default text typeface style. -->
+    <attr name="textStyle">
+        <flag name="normal" value="0" />
+        <flag name="bold" value="1" />
+        <flag name="italic" value="2" />
+    </attr>
+    <!-- Color of text (usually same as colorForeground). -->
+    <attr name="textColor" format="reference|color" />
+    <!-- Color of highlighted text. -->
+    <attr name="textColorHighlight" format="reference|color" />
+    <!-- Color of hint text (displayed when the field is empty). -->
+    <attr name="textColorHint" format="reference|color" />
+    <!-- Color of link text (URLs). -->
+    <attr name="textColorLink" format="reference|color" />
+    <declare-styleable name="TextAppearance">
+        <attr name="textColor"/>
+        <attr name="textSize"/>
+        <attr name="textStyle"/>
+        <attr name="typeface"/>
+        <attr name="textColorHighlight"/>
+        <attr name="textColorHint"/>
+        <attr name="textColorLink"/>
+    </declare-styleable>
+    <!-- Integer used to uniquely identify theme overrides. -->
+    <attr name="themeType" format="integer"/>
+    <!-- Theme reference used to override parent theme. -->
+    <attr name="themeOverrideAttr" format="reference"/>
+
+    <!-- Drawable theming attributes -->
+    <attr name="themeBoolean" />
+    <attr name="themeColor" />
+    <attr name="themeFloat" />
+    <attr name="themeInteger" />
+    <attr name="themeDimension" />
+    <attr name="themeDrawable" />
+    <attr name="themeBitmap" />
+    <attr name="themeNinePatch" />
+    <attr name="themeGravity" />
+    <attr name="themeTileMode" />
+    <attr name="themeAngle" />
+</resources>
diff --git a/tests/res/values/colors.xml b/tests/tests/widget/res/values/colors.xml
similarity index 100%
copy from tests/res/values/colors.xml
copy to tests/tests/widget/res/values/colors.xml
diff --git a/tests/tests/widget/res/values/strings.xml b/tests/tests/widget/res/values/strings.xml
new file mode 100644
index 0000000..c167278
--- /dev/null
+++ b/tests/tests/widget/res/values/strings.xml
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="permlab_testGranted">Test Granted</string>
+    <string name="permdesc_testGranted">Used for running CTS tests, for testing operations
+        where we have the permission.</string>
+    <string name="permlab_testDynamic">Test Dynamic</string>
+    <string name="permdesc_testDynamic">Used for running CTS tests, for testing adding
+        dynamic permissions.</string>
+    <string name="permlab_testDenied">Test Denied</string>
+    <string name="permdesc_testDenied">Used for running CTS tests, for testing operations
+        where we do not have the permission.</string>
+    <string name="explain">1. click start. \n2. if above image shaked, then press pass button,
+         else press failed button.</string>
+    <string name="text_view_hello">Hello! Text view!</string>
+    <string name="text_view_hello_two_lines">Hello! \nText view!</string>
+    <string name="text_view_simple_hint">This is a hint.</string>
+    <string name="text_view_hint">This is a string for testing hint of textview.</string>
+    <string name="activity_forwarding">App/Forwarding</string>
+    <string name="forwarding">$$$</string>
+    <string name="go">Go</string>
+    <string name="back">Back</string>
+    <string name="forward_target">
+        Press back button and notice we don\'t see the previous activity.
+    </string>
+    <string name="edit_text">testing</string>
+    <string name="text">DialogTest</string>
+    <string name="text_country">Country</string>
+    <string name="text_name">Name</string>
+    <string name="hello_world">Hello, World!</string>
+    <string name="hello_android">Hello, Android!</string>
+    <string name="alert_dialog_username">Name:</string>
+    <string name="alert_dialog_password">Password:</string>
+    <string name="alert_dialog_positive">Positive</string>
+    <string name="alert_dialog_negative">Negative</string>
+    <string name="alert_dialog_neutral">Neutral</string>
+    <string name="notify">Notify </string>
+    <string name="tabs_1">testing</string>
+    <string name="table_layout_first">first</string>
+    <string name="table_layout_second">second</string>
+    <string name="table_layout_third">third</string>
+    <string name="table_layout_long">Very long to make the string out of the screen</string>
+    <string name="chronometer_text">Test Chronometer</string>
+    <string name="am">AM</string>
+    <string name="pm">PM</string>
+    <string name="viewgroup_test">ViewGroup test</string>
+    <string name="viewanimator_test">ViewAnimator test</string>
+    <string name="id_ok">OK</string>
+    <string name="id_cancel">Cancel</string>
+    <string name="context_test_string1">This is %s string.</string>
+    <string name="context_test_string2">This is test string.</string>
+    <string name="animationutils_test_instructions">Choose different animations</string>
+    <string name="animationutils_test_alpha">Alpha animation</string>
+    <string name="animationutils_test_scale">Scale animation</string>
+    <string name="animationutils_test_rotate">Rotate animation</string>
+    <string name="animationutils_test_translate">Translate animation</string>
+    <string name="animationutils_test_set">Animation set</string>
+    <string name="animationutils_test_layout">Layout animation</string>
+    <string name="animationutils_test_gridlayout">Grid layout animation</string>
+    <string name="twolinelistitem_test_text1">text1</string>
+    <string name="twolinelistitem_test_text2">text2</string>
+    <string name="metadata_text">metadata text</string>
+    <string name="horizontal_text_1">horizontal 1</string>
+    <string name="horizontal_text_2">horizontal 2</string>
+    <string name="horizontal_text_3">horizontal 3</string>
+    <string name="vertical_text_1">vertical 1</string>
+    <string name="vertical_text_2">vertical 2</string>
+    <string name="vertical_text_3">vertical 3</string>
+    <string name="reference">here</string>
+    <string name="coerceIntegerToString">100</string>
+    <string name="coerceBooleanToString">true</string>
+    <string name="coerceColorToString">#fff</string>
+    <string name="coerceFloatToString">100.0</string>
+    <string name="coerceDimensionToString">100px</string>
+    <string name="coerceFractionToString">100<xliff:g id="percent">%</xliff:g></string>
+    <string name="formattedStringNone">Format[]</string>
+    <string name="formattedStringOne">Format[<xliff:g id="format">%d</xliff:g>]</string>
+    <string name="formattedStringTwo">Format[<xliff:g id="format">%3$d,%2$s</xliff:g>]</string>
+    <string name="checkboxpref_key">checkboxpref_key</string>
+   <string name="checkboxpref_title">title of preference</string>
+   <string name="checkboxpref_summary">summary of preference</string>
+   <string name="checkboxpref_summary_on">summary on of preference</string>
+   <string name="checkboxpref_summary_off">summary off of preference</string>
+   <string name="checkboxpref_depend">checkboxpref_depend</string>
+   <string name="checkboxpref_depend_title"> depend title of preference</string>
+   <string name="checkboxpref_depend_summary"> depend summary of preference</string>
+   <string name="edittextpref_key">edittextpref_key</string>
+   <string name="edittextpref_default_value">default value of preference</string>
+   <string name="edittextpref_title">title of edit text preference</string>
+   <string name="edittextpref_summary">summary of edit text preference</string>
+   <string name="edittextpref_dialog_title">dialog title of edit text preference</string>
+   <string name="edittextpref_text">text of  edit text preference</string>
+   <string name="listpref_key">listpref_key</string>
+   <string name="listpref_title">title of list preference</string>
+   <string name="listpref_summary">summary of list preference</string>
+   <string name="listpref_dialogtitle">dialog title of list preference</string>
+   <string name="easy">Easy</string>
+   <string name="medium">Medium</string>
+   <string name="hard">Hard</string>
+   <string name="footer_view">Footer view</string>
+   <string name="header_view">Header view</string>
+   <string name="dialogpref_title">title of dialog preference </string>
+   <string name="dialogpref_dialog_title">dialog title of dialog preference </string>
+   <string name="dialogpref_key">dialogpref_key</string>
+   <string name="dialogpref_default_value">default value of dialog preference</string>
+   <string name="dialogpref_summary">summary of dialog preference</string>
+   <string name="dialogpref_message">message of dialog preference</string>
+   <string name="dialogpref_sure">Sure</string>
+   <string name="dialogpref_cancel">Cancel</string>
+   <string name="pref_key">pref_key</string>
+   <string name="pref_title">title of preference</string>
+   <string name="pref_summary">summary of preference</string>
+   <string name="pref_depend_key">pref_depend_key</string>
+   <string name="pref_depend_title"> depend title of preference</string>
+   <string name="pref_depend_summary"> depend summary of preference</string>
+   <string name="android_intent_action_preference">android.intent.action.PREFERENCE</string>
+   <string name="def_pref_key">def_pref_key</string>
+   <string name="def_pref_title">default preference</string>
+   <string name="def_pref_summary">This is default preference of cts</string>
+   <string name="relative_view1">view 1</string>
+   <string name="relative_view2">view 2</string>
+   <string name="relative_view3">view 3</string>
+   <string name="relative_view4">view 4</string>
+   <string name="relative_view5">view 5</string>
+   <string name="relative_view6">view 6</string>
+   <string name="relative_view7">view 7</string>
+   <string name="relative_view8">view 8</string>
+   <string name="relative_view9">view 9</string>
+   <string name="relative_view10">view 10</string>
+   <string name="relative_view11">view 11</string>
+   <string name="relative_view12">view 12</string>
+   <string name="relative_view13">view 13</string>
+   <string name="country">Country:</string>
+   <string name="symbol">Symbol:</string>
+   <string name="country_warning">No such country registered</string>
+   <string name="version_cur">base</string>
+   <string name="version_old">base</string>
+   <string name="version_v3">base</string>
+   <string name="authenticator_label">Android CTS</string>
+   <string name="search_label">Android CTS</string>
+   <string name="tag1">tag 1</string>
+   <string name="tag2">tag 2</string>
+
+   <string name="button">Button</string>
+   <string name="holo_test">Holo Test</string>
+   <string name="holo_generator">Holo Generator</string>
+   <string name="holo_light_test">Holo Light Test</string>
+   <string name="holo_light_generator">Holo Light Generator</string>
+   <string name="reference_image">Reference Image: </string>
+   <string name="generated_image">Generated Image: </string>
+   <string name="themes_prompt">Select a Theme:</string>
+   <string name="sample_text">Sample text goes here. I wanted something creative and whimsical
+but then I just got bored...</string>
+    <string name="long_text">This is a really long string which exceeds the width of the view.
+New devices have a much larger screen which actually enables long strings to be displayed
+with no fading. I have made this string longer to fix this case. If you are correcting this
+text, I would love to see the kind of devices you guys now use! Guys, maybe some devices need longer string!
+I think so, so how about double this string, like copy and paste!
+This is a really long string which exceeds the width of the view.
+New devices have a much larger screen which actually enables long strings to be displayed
+with no fading. I have made this string longer to fix this case. If you are correcting this
+text, I would love to see the kind of devices you guys now use! Guys, maybe some devices need longer string!
+I think so, so how about double this string, like copy and paste! </string>
+    <string name="rectangle200">"M 0,0 l 200,0 l 0, 200 l -200, 0 z"</string>
+</resources>
diff --git a/tests/tests/widget/res/values/styles.xml b/tests/tests/widget/res/values/styles.xml
new file mode 100644
index 0000000..81925cc
--- /dev/null
+++ b/tests/tests/widget/res/values/styles.xml
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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 xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <style name="Whatever">
+        <item name="type1">true</item>
+        <item name="type2">false</item>
+        <item name="type3">#ff0000ff</item>
+        <item name="type4">#ff00ff00</item>
+        <item name="type5">0.75px</item>
+        <item name="type6">10px</item>
+        <item name="type7">18px</item>
+        <item name="type8">@drawable/pass</item>
+        <item name="type9">3.14</item>
+        <item name="type10">100%</item>
+        <item name="type11">365</item>
+        <item name="type12">86400</item>
+        <item name="type13">@string/hello_android</item>
+        <item name="type14">TypedArray Test!</item>
+        <item name="type15">@array/difficultyLevel</item>
+        <item name="type16">Typed Value!</item>
+    </style>
+
+    <style name="TextViewWithoutColorAndAppearance">
+        <item name="android:textSize">18sp</item>
+    </style>
+
+    <style name="TextViewWithColorButWithOutAppearance">
+        <item name="android:textColor">#ff0000ff</item>
+    </style>
+
+    <style name="TextViewWithColorAndAppearance">
+        <item name="android:textColor">#ff0000ff</item>
+        <item name="android:textAppearance">@style/TextAppearance.WithColor</item>
+    </style>
+
+    <style name="TextViewWithoutColorButWithAppearance">
+        <item name="android:textAppearance">@style/TextAppearance.WithColor</item>
+    </style>
+
+    <style name="TextAppearance" parent="android:TextAppearance">
+    </style>
+
+    <style name="TextAppearance.WithColor">
+        <item name="android:textColor">#ffff0000</item>
+    </style>
+
+    <style name="TextAppearance.All">
+        <item name="android:textColor">@drawable/black</item>
+        <item name="android:textSize">20px</item>
+        <item name="android:textStyle">bold</item>
+        <item name="android:textColorHint">@drawable/red</item>
+        <item name="android:textColorLink">@drawable/blue</item>
+        <item name="android:textColorHighlight">@drawable/yellow</item>
+    </style>
+
+    <style name="TextAppearance.Colors">
+        <item name="android:textColor">@drawable/black</item>
+        <item name="android:textColorHint">@drawable/blue</item>
+        <item name="android:textColorLink">@drawable/yellow</item>
+        <item name="android:textColorHighlight">@drawable/red</item>
+    </style>
+
+    <style name="TextAppearance.NotColors">
+        <item name="android:textSize">17px</item>
+        <item name="android:typeface">sans</item>
+        <item name="android:textStyle">normal</item>
+    </style>
+
+    <style name="TextAppearance.Style">
+        <item name="android:textStyle">normal</item>
+    </style>
+
+    <style name="TestEnum1">
+        <item name="testEnum">val1</item>
+    </style>
+
+    <style name="TestEnum2">
+        <item name="testEnum">val2</item>
+    </style>
+
+    <style name="TestEnum10">
+        <item name="testEnum">val10</item>
+    </style>
+
+    <style name="TestFlag1">
+        <item name="testFlags">bit1</item>
+    </style>
+
+    <style name="TestFlag2">
+        <item name="testFlags">bit2</item>
+    </style>
+
+    <style name="TestFlag31">
+        <item name="testFlags">bit31</item>
+    </style>
+
+    <style name="TestFlag1And2">
+        <item name="testFlags">bit1|bit2</item>
+    </style>
+
+    <style name="TestFlag1And2And31">
+        <item name="testFlags">bit1|bit2|bit31</item>
+    </style>
+
+    <style name="TestEnum1.EmptyInherit" />
+
+    <style name="Theme_AlertDialog">
+        <item name="android:textSize">18sp</item>
+    </style>
+
+    <style name="TestProgressBar">
+        <item name="android:indeterminateOnly">false</item>
+        <item name="android:progressDrawable">?android:drawable/progress_horizontal</item>
+        <item name="android:indeterminateDrawable">?android:drawable/progress_horizontal</item>
+        <item name="android:minHeight">20dip</item>
+        <item name="android:maxHeight">20dip</item>
+        <item name="android:focusable">true</item>
+    </style>
+
+    <style name="Test_Theme">
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:panelColorForeground">#ff000000</item>
+        <item name="android:panelColorBackground">#ffffffff</item>
+    </style>
+
+    <style name="Theme_OverrideOuter">
+        <item name="themeType">1</item>
+    </style>
+
+    <style name="Theme_OverrideInner">
+        <item name="themeType">2</item>
+        <item name="themeOverrideAttr">@style/Theme_OverrideAttr</item>
+    </style>
+
+    <style name="Theme_OverrideAttr">
+        <item name="themeType">3</item>
+    </style>
+
+    <style name="Theme_ThemedDrawableTest">
+        <item name="themeBoolean">true</item>
+        <item name="themeColor">@android:color/black</item>
+        <item name="themeFloat">1.0</item>
+        <item name="themeAngle">45.0</item>
+        <item name="themeInteger">1</item>
+        <item name="themeDimension">1px</item>
+        <item name="themeDrawable">@drawable/icon_black</item>
+        <item name="themeBitmap">@drawable/icon_black</item>
+        <item name="themeNinePatch">@drawable/ninepatch_0</item>
+        <item name="themeGravity">48</item>
+        <item name="themeTileMode">2</item>
+    </style>
+
+    <style name="Theme_NoSwipeDismiss">
+        <item name="android:windowSwipeToDismiss">false</item>
+    </style>
+
+</resources>
diff --git a/tests/res/xml/base_attributes.xml b/tests/tests/widget/res/xml/base_attributes.xml
similarity index 100%
rename from tests/res/xml/base_attributes.xml
rename to tests/tests/widget/res/xml/base_attributes.xml
diff --git a/tests/res/xml/input_extras.xml b/tests/tests/widget/res/xml/input_extras.xml
similarity index 100%
rename from tests/res/xml/input_extras.xml
rename to tests/tests/widget/res/xml/input_extras.xml
diff --git a/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java b/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java
index 7dcae28..9d8c7d2 100644
--- a/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -25,6 +25,7 @@
 import android.app.Instrumentation;
 import android.content.Context;
 import android.cts.util.PollingCheck;
+import android.cts.util.WidgetTestUtils;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Rect;
@@ -52,7 +53,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
-public class AbsListViewTest extends ActivityInstrumentationTestCase2<ListViewStubActivity> {
+public class AbsListViewTest extends ActivityInstrumentationTestCase2<ListViewCtsActivity> {
     private final String[] mShortList = new String[] {
         "This", "is", "short", "!",
     };
@@ -72,7 +73,7 @@
     private static final float DELTA = 0.001f;
 
     public AbsListViewTest() {
-        super("com.android.cts.stub", ListViewStubActivity.class);
+        super("com.android.cts.widget", ListViewCtsActivity.class);
     }
 
 
diff --git a/tests/tests/widget/src/android/widget/cts/AbsListView_LayoutParamsTest.java b/tests/tests/widget/src/android/widget/cts/AbsListView_LayoutParamsTest.java
index 655b5ee..305a9e2 100644
--- a/tests/tests/widget/src/android/widget/cts/AbsListView_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AbsListView_LayoutParamsTest.java
@@ -16,11 +16,12 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import org.xmlpull.v1.XmlPullParser;
 
+import android.cts.util.WidgetTestUtils;
 import android.test.AndroidTestCase;
 import android.util.AttributeSet;
 import android.util.Xml;
diff --git a/tests/tests/widget/src/android/widget/cts/AbsSeekBarTest.java b/tests/tests/widget/src/android/widget/cts/AbsSeekBarTest.java
index 4881a24..419a1c8 100644
--- a/tests/tests/widget/src/android/widget/cts/AbsSeekBarTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AbsSeekBarTest.java
@@ -16,7 +16,12 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import android.content.res.ColorStateList;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.test.UiThreadTest;
+
+import com.android.cts.widget.R;
 
 
 import android.app.Activity;
@@ -29,16 +34,15 @@
 import android.test.ActivityInstrumentationTestCase2;
 import android.util.AttributeSet;
 import android.view.KeyEvent;
-import android.view.MotionEvent;
 import android.widget.AbsSeekBar;
 import android.widget.SeekBar;
 
 /**
  * Test {@link AbsSeekBar}.
  */
-public class AbsSeekBarTest extends ActivityInstrumentationTestCase2<ProgressBarStubActivity> {
+public class AbsSeekBarTest extends ActivityInstrumentationTestCase2<ProgressBarCtsActivity> {
     public AbsSeekBarTest() {
-        super("com.android.cts.stub", ProgressBarStubActivity.class);
+        super("com.android.cts.widget", ProgressBarCtsActivity.class);
     }
 
     private Activity mActivity;
@@ -147,7 +151,7 @@
         // AbsSeekBar is an abstract class, use its subclass: SeekBar to do this test.
         runTestOnUiThread(new Runnable() {
             public void run() {
-                mActivity.setContentView(R.layout.seekbar);
+                mActivity.setContentView(R.layout.seekbar_layout);
             }
         });
         getInstrumentation().waitForIdleSync();
@@ -207,6 +211,34 @@
         assertEquals(keyProgressIncrement + 1, myAbsSeekBar.getKeyProgressIncrement());
     }
 
+    @UiThreadTest
+    public void testThumbTint() {
+        mActivity.setContentView(R.layout.seekbar_layout);
+
+        SeekBar inflatedView = (SeekBar) mActivity.findViewById(R.id.thumb_tint);
+
+        assertEquals("Thumb tint inflated correctly",
+                Color.WHITE, inflatedView.getThumbTintList().getDefaultColor());
+        assertEquals("Thumb tint mode inflated correctly",
+                PorterDuff.Mode.SRC_OVER, inflatedView.getThumbTintMode());
+
+        MockDrawable thumb = new MockDrawable();
+        SeekBar view = new SeekBar(mActivity);
+
+        view.setThumb(thumb);
+        assertFalse("No thumb tint applied by default", thumb.hasCalledSetTint());
+
+        view.setThumbTintList(ColorStateList.valueOf(Color.WHITE));
+        assertTrue("Thumb tint applied when setThumbTintList() called after setThumb()",
+                thumb.hasCalledSetTint());
+
+        thumb.reset();
+        view.setThumb(null);
+        view.setThumb(thumb);
+        assertTrue("Thumb tint applied when setThumbTintList() called before setThumb()",
+                thumb.hasCalledSetTint());
+    }
+
     public void testFoo() {
         // Do not test these APIs. They are callbacks which:
         // 1. The callback machanism has been tested in super class
@@ -240,6 +272,7 @@
     private static class MockDrawable extends Drawable {
         private int mAlpha;
         private boolean mCalledDraw = false;
+        private boolean mCalledSetTint = false;
 
         @Override
         public void draw(Canvas canvas) {
@@ -252,6 +285,7 @@
 
         public void reset() {
             mCalledDraw = false;
+            mCalledSetTint = false;
         }
 
         @Override
@@ -269,7 +303,16 @@
         }
 
         @Override
-        public void setColorFilter(ColorFilter cf) {
+        public void setColorFilter(ColorFilter cf) { }
+
+        @Override
+        public void setTintList(ColorStateList tint) {
+            super.setTintList(tint);
+            mCalledSetTint = true;
+        }
+
+        public boolean hasCalledSetTint() {
+            return mCalledSetTint;
         }
     }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/AbsSpinnerTest.java b/tests/tests/widget/src/android/widget/cts/AbsSpinnerTest.java
index fc37a64..10e1658 100644
--- a/tests/tests/widget/src/android/widget/cts/AbsSpinnerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AbsSpinnerTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import org.xmlpull.v1.XmlPullParser;
@@ -39,11 +39,11 @@
 import android.widget.Spinner;
 import android.widget.SpinnerAdapter;
 
-public class AbsSpinnerTest extends ActivityInstrumentationTestCase2<RelativeLayoutStubActivity> {
+public class AbsSpinnerTest extends ActivityInstrumentationTestCase2<RelativeLayoutCtsActivity> {
     private Context mContext;
 
     public AbsSpinnerTest() {
-        super("com.android.cts.stub", RelativeLayoutStubActivity.class);
+        super("com.android.cts.widget", RelativeLayoutCtsActivity.class);
     }
 
     @Override
@@ -52,7 +52,7 @@
         mContext = getInstrumentation().getTargetContext();
     }
 
-
+    @UiThreadTest
     public void testConstructor() {
         new Spinner(mContext);
 
@@ -78,7 +78,7 @@
     public void testSetSelectionIntBoolean() {
         AbsSpinner absSpinner = (AbsSpinner) getActivity().findViewById(R.id.spinner1);
         ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mContext,
-                com.android.cts.stub.R.array.string, android.R.layout.simple_spinner_item);
+                com.android.cts.widget.R.array.string, android.R.layout.simple_spinner_item);
         adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
         absSpinner.setAdapter(adapter);
         assertEquals(0, absSpinner.getSelectedItemPosition());
@@ -101,7 +101,7 @@
     public void testSetSelectionInt() {
         AbsSpinner absSpinner = (AbsSpinner) getActivity().findViewById(R.id.spinner1);
         ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mContext,
-                com.android.cts.stub.R.array.string, android.R.layout.simple_spinner_item);
+                com.android.cts.widget.R.array.string, android.R.layout.simple_spinner_item);
         adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
         absSpinner.setAdapter(adapter);
         assertEquals(0, absSpinner.getSelectedItemPosition());
@@ -123,7 +123,7 @@
     public void testAccessAdapter() {
         AbsSpinner absSpinner = (AbsSpinner) getActivity().findViewById(R.id.spinner1);
         ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mContext,
-                com.android.cts.stub.R.array.string, android.R.layout.simple_spinner_item);
+                com.android.cts.widget.R.array.string, android.R.layout.simple_spinner_item);
         adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
 
         absSpinner.setAdapter(adapter);
@@ -139,6 +139,7 @@
         // There is neither limit in code nor description about it in javadoc.
     }
 
+    @UiThreadTest
     public void testRequestLayout() {
         AbsSpinner absSpinner = new Spinner(mContext);
         absSpinner.layout(0, 0, 200, 300);
@@ -158,7 +159,7 @@
         AbsSpinner absSpinner = (AbsSpinner) getActivity().findViewById(R.id.spinner1);
 
         ArrayAdapter<CharSequence> adapter1 = ArrayAdapter.createFromResource(mContext,
-                com.android.cts.stub.R.array.string, android.R.layout.simple_spinner_item);
+                com.android.cts.widget.R.array.string, android.R.layout.simple_spinner_item);
 
         absSpinner.setAdapter(adapter1);
         assertEquals(adapter1.getCount(), absSpinner.getCount());
@@ -176,6 +177,7 @@
      * 1. Should return the position of the item which contains the specified point.
      * 2. Should return INVALID_POSITION if the point does not intersect an item
      */
+    @UiThreadTest
     public void testPointToPosition() {
         AbsSpinner absSpinner = new Gallery(mContext);
         MockSpinnerAdapter adapter = new MockSpinnerAdapter();
@@ -210,6 +212,7 @@
      * 1. Should return the view corresponding to the currently selected item.
      * 2. Should return null if nothing is selected.
      */
+    @UiThreadTest
     public void testGetSelectedView() {
         AbsSpinner absSpinner = new Gallery(mContext);
         MockSpinnerAdapter adapter = new MockSpinnerAdapter();
@@ -233,7 +236,7 @@
     public void testOnSaveAndRestoreInstanceState() {
         AbsSpinner absSpinner = (AbsSpinner) getActivity().findViewById(R.id.spinner1);
         ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mContext,
-                com.android.cts.stub.R.array.string, android.R.layout.simple_spinner_item);
+                com.android.cts.widget.R.array.string, android.R.layout.simple_spinner_item);
         adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
         absSpinner.setAdapter(adapter);
         assertEquals(0, absSpinner.getSelectedItemPosition());
diff --git a/tests/tests/widget/src/android/widget/cts/AbsoluteLayoutTest.java b/tests/tests/widget/src/android/widget/cts/AbsoluteLayoutTest.java
index 8d2b6cd..bac2479 100644
--- a/tests/tests/widget/src/android/widget/cts/AbsoluteLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AbsoluteLayoutTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import org.xmlpull.v1.XmlPullParser;
@@ -24,6 +24,7 @@
 
 import android.app.Activity;
 import android.content.Context;
+import android.cts.util.WidgetTestUtils;
 import android.test.ActivityInstrumentationTestCase2;
 import android.util.AttributeSet;
 import android.util.Xml;
@@ -34,7 +35,7 @@
 import java.io.IOException;
 
 @SuppressWarnings("deprecation")
-public class AbsoluteLayoutTest extends ActivityInstrumentationTestCase2<StubActivity> {
+public class AbsoluteLayoutTest extends ActivityInstrumentationTestCase2<CtsActivity> {
     private static final int DEFAULT_X      = 5;
     private static final int DEFAULT_Y      = 10;
     private static final int DEFAULT_WIDTH  = 20;
@@ -45,7 +46,7 @@
     private LayoutParams mAbsoluteLayoutParams;
 
     public AbsoluteLayoutTest() {
-        super("com.android.cts.stub", StubActivity.class);
+        super("com.android.cts.widget", CtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/widget/src/android/widget/cts/AbsoluteLayout_LayoutParamsTest.java b/tests/tests/widget/src/android/widget/cts/AbsoluteLayout_LayoutParamsTest.java
index 63be7d4..ebc4e74 100644
--- a/tests/tests/widget/src/android/widget/cts/AbsoluteLayout_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AbsoluteLayout_LayoutParamsTest.java
@@ -16,12 +16,13 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
+import android.cts.util.WidgetTestUtils;
 import android.test.AndroidTestCase;
 import android.util.AttributeSet;
 import android.util.Xml;
diff --git a/tests/tests/widget/src/android/widget/cts/AdapterViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/AdapterViewCtsActivity.java
new file mode 100644
index 0000000..956ff9a
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/AdapterViewCtsActivity.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2008 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.widget.cts;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+import com.android.cts.widget.R;
+
+/**
+ * A minimal application for AdapterView test.
+ */
+public class AdapterViewCtsActivity extends Activity {
+    private ListView mView;
+
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mView = new ListView(this);
+        mView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
+                LayoutParams.WRAP_CONTENT));
+        setContentView(mView);
+    }
+
+    public ListView getListView() {
+        return mView;
+    }
+
+    public ArrayAdapter<String> getArrayAdapter() {
+        final List<String> list = new ArrayList<String>();
+        for (int i = 0; i < 4; i++) {
+            list.add("test:" + i);
+        }
+        return new ArrayAdapter<String>(this, R.layout.adapterview_layout, list);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java b/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java
index b91ca73..81a1a4b 100644
--- a/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java
@@ -38,10 +38,10 @@
 import android.widget.AdapterView.OnItemLongClickListener;
 import android.widget.AdapterView.OnItemSelectedListener;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
-public class AdapterViewTest extends ActivityInstrumentationTestCase2<AdapterViewStubActivity> {
+public class AdapterViewTest extends ActivityInstrumentationTestCase2<AdapterViewCtsActivity> {
 
     private final static int INVALID_ID = -1;
 
@@ -54,7 +54,7 @@
     private AdapterView<ListAdapter> mAdapterView;
 
     public AdapterViewTest() {
-        super("com.android.cts.stub", AdapterViewStubActivity.class);
+        super("com.android.cts.widget", AdapterViewCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/widget/src/android/widget/cts/AnalogClockTest.java b/tests/tests/widget/src/android/widget/cts/AnalogClockTest.java
index f3b02b0..ef1a45d 100644
--- a/tests/tests/widget/src/android/widget/cts/AnalogClockTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AnalogClockTest.java
@@ -16,23 +16,24 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import org.xmlpull.v1.XmlPullParser;
 
 import android.app.Activity;
 import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
 import android.util.AttributeSet;
 import android.util.Xml;
 import android.widget.AnalogClock;
 
-public class AnalogClockTest extends ActivityInstrumentationTestCase2<FrameLayoutStubActivity> {
+public class AnalogClockTest extends ActivityInstrumentationTestCase2<FrameLayoutCtsActivity> {
     private AttributeSet mAttrSet;
     private Activity mActivity;
 
     public AnalogClockTest() {
-        super("com.android.cts.stub", FrameLayoutStubActivity.class);
+        super("com.android.cts.widget", FrameLayoutCtsActivity.class);
     }
 
     @Override
@@ -44,6 +45,7 @@
         mActivity = getActivity();
     }
 
+    @UiThreadTest
     public void testConstructor() {
         new AnalogClock(mActivity);
         new AnalogClock(mActivity, mAttrSet);
diff --git a/tests/tests/widget/src/android/widget/cts/ArrayAdapterTest.java b/tests/tests/widget/src/android/widget/cts/ArrayAdapterTest.java
index 101b271..1e17ea7 100644
--- a/tests/tests/widget/src/android/widget/cts/ArrayAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ArrayAdapterTest.java
@@ -20,16 +20,18 @@
 import java.util.Comparator;
 import java.util.List;
 
+import android.content.Context;
 import android.database.DataSetObserver;
-import android.test.AndroidTestCase;
+import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
 import android.widget.ArrayAdapter;
 import android.widget.Filter;
 import android.widget.TextView;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
-public class ArrayAdapterTest extends AndroidTestCase {
+public class ArrayAdapterTest extends InstrumentationTestCase {
 
     private static final int INVALD_ID = -1;
     private static final String STR1 = "string1";
@@ -37,10 +39,13 @@
     private static final String STR3 = "string3";
 
     private ArrayAdapter<String> mArrayAdapter;
+    private Context mContext;
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-          mArrayAdapter = new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line);
+        mContext = getInstrumentation().getTargetContext();
+        mArrayAdapter = new ArrayAdapter<String>(mContext, R.layout.simple_dropdown_item_1line);
     }
 
     public void testConstructor() {
@@ -167,6 +172,7 @@
         }
     }
 
+    @UiThreadTest
     public void testGetFilter() {
         Filter filter = mArrayAdapter.getFilter();
 
diff --git a/tests/tests/widget/src/android/widget/cts/AutoCompleteCtsActivity.java b/tests/tests/widget/src/android/widget/cts/AutoCompleteCtsActivity.java
new file mode 100644
index 0000000..3d68f3e
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/AutoCompleteCtsActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008 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.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.cts.widget.R;
+
+/**
+ * A minimal application for AutoCompleteTextView test.
+ */
+public class AutoCompleteCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.autocompletetextview_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java b/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java
index 373c03b..da99fa3 100644
--- a/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import org.xmlpull.v1.XmlPullParser;
@@ -24,7 +24,9 @@
 
 import android.app.Activity;
 import android.app.Instrumentation;
+import android.app.UiModeManager;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.cts.util.PollingCheck;
 import android.graphics.Rect;
 import android.test.ActivityInstrumentationTestCase2;
@@ -45,13 +47,13 @@
 import java.io.IOException;
 
 public class AutoCompleteTextViewTest extends
-        ActivityInstrumentationTestCase2<AutoCompleteStubActivity> {
+        ActivityInstrumentationTestCase2<AutoCompleteCtsActivity> {
 
     /**
      * Instantiates a new text view test.
      */
     public AutoCompleteTextViewTest() {
-        super("com.android.cts.stub", AutoCompleteStubActivity.class);
+        super("com.android.cts.widget", AutoCompleteCtsActivity.class);
     }
 
     /** The m activity. */
@@ -104,6 +106,13 @@
         }
     }
 
+    boolean isTvMode() {
+        UiModeManager uiModeManager = (UiModeManager) getActivity().getSystemService(
+                Context.UI_MODE_SERVICE);
+        return uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION;
+    }
+
+    @UiThreadTest
     public void testConstructor() {
         XmlPullParser parser;
 
@@ -159,6 +168,7 @@
         assertFalse(mAutoCompleteTextView.enoughToFilter());
     }
 
+    @UiThreadTest
     public void testAccessAdapter() {
         MockAutoCompleteTextView autoCompleteTextView = new MockAutoCompleteTextView(mActivity);
 
@@ -222,6 +232,7 @@
         assertNull(mAutoCompleteTextView.getOnItemSelectedListener());
     }
 
+    @UiThreadTest
     public void testConvertSelectionToString() {
         MockAutoCompleteTextView autoCompleteTextView = new MockAutoCompleteTextView(mActivity);
 
@@ -234,6 +245,7 @@
         assertEquals(STRING_TEST, autoCompleteTextView.convertSelectionToString(STRING_TEST));
     }
 
+    @UiThreadTest
     public void testOnTextChanged() {
         MockAutoCompleteTextView autoCompleteTextView = new MockAutoCompleteTextView(mActivity);
 
@@ -287,6 +299,7 @@
         assertEquals(STRING_VALIDATED, mAutoCompleteTextView.getText().toString());
     }
 
+    @UiThreadTest
     public void testReplaceText() {
         MockAutoCompleteTextView autoCompleteTextView = new MockAutoCompleteTextView(mActivity);
 
@@ -303,6 +316,7 @@
         assertTrue(autoCompleteTextView.isOnTextChanged());
     }
 
+    @UiThreadTest
     public void testSetFrame() {
         MockAutoCompleteTextView autoCompleteTextView = new MockAutoCompleteTextView(mActivity);
 
@@ -426,6 +440,9 @@
     }
 
     public void testPerformFiltering() throws Throwable {
+        if (isTvMode()) {
+            return;
+        }
         runTestOnUiThread(new Runnable() {
             public void run() {
                 mAutoCompleteTextView.setAdapter(mAdapter);
@@ -496,6 +513,9 @@
     }
 
     public void testPerformCompletion() throws Throwable {
+        if (isTvMode()) {
+            return;
+        }
         final MockOnItemClickListener listener = new MockOnItemClickListener();
         assertFalse(mAutoCompleteTextView.isPerformingCompletion());
 
diff --git a/tests/tests/widget/src/android/widget/cts/ButtonTest.java b/tests/tests/widget/src/android/widget/cts/ButtonTest.java
index 98b3318..47d7108 100644
--- a/tests/tests/widget/src/android/widget/cts/ButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ButtonTest.java
@@ -24,7 +24,7 @@
 import android.util.Xml;
 import android.widget.Button;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 public class ButtonTest extends AndroidTestCase {
diff --git a/tests/tests/widget/src/android/widget/cts/CheckBoxTest.java b/tests/tests/widget/src/android/widget/cts/CheckBoxTest.java
index 55960f9..21e463f 100644
--- a/tests/tests/widget/src/android/widget/cts/CheckBoxTest.java
+++ b/tests/tests/widget/src/android/widget/cts/CheckBoxTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import org.xmlpull.v1.XmlPullParser;
diff --git a/tests/tests/widget/src/android/widget/cts/CheckedTextViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/CheckedTextViewCtsActivity.java
new file mode 100644
index 0000000..a0ed498
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/CheckedTextViewCtsActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2009 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.widget.cts;
+
+import com.android.cts.widget.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * A minimal application for CheckedTextView test.
+ */
+public class CheckedTextViewCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.checkedtextview_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/CheckedTextViewTest.java b/tests/tests/widget/src/android/widget/cts/CheckedTextViewTest.java
index 6aa44c1..c5d3bd1 100644
--- a/tests/tests/widget/src/android/widget/cts/CheckedTextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/CheckedTextViewTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import android.app.Activity;
@@ -38,13 +38,13 @@
 import java.util.Arrays;
 
 public class CheckedTextViewTest extends
-        ActivityInstrumentationTestCase2<CheckedTextViewStubActivity> {
+        ActivityInstrumentationTestCase2<CheckedTextViewCtsActivity> {
     private Resources mResources;
     private Activity mActivity;
     private Instrumentation mInstrumentation;
 
     public CheckedTextViewTest() {
-        super("com.android.cts.stub", CheckedTextViewStubActivity.class);
+        super("com.android.cts.widget", CheckedTextViewCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/widget/src/android/widget/cts/ChronometerCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ChronometerCtsActivity.java
new file mode 100644
index 0000000..3a7833d
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ChronometerCtsActivity.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2008 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.widget.cts;
+
+import com.android.cts.widget.R;
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.ViewGroup;
+import android.widget.Chronometer;
+
+public class ChronometerCtsActivity extends Activity {
+
+    private Chronometer chronometer;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.chronometer_stub_layout);
+        chronometer = (Chronometer) findViewById(R.id.test_chronometer);
+    }
+
+    public Chronometer getChronometer() {
+        return chronometer;
+    }
+
+    public ViewGroup getViewGroup() {
+        return (ViewGroup) findViewById(R.id.chronometer_view_group);
+    }
+
+}
+
diff --git a/tests/tests/widget/src/android/widget/cts/ChronometerTest.java b/tests/tests/widget/src/android/widget/cts/ChronometerTest.java
index 7fbb58a7..7910274 100644
--- a/tests/tests/widget/src/android/widget/cts/ChronometerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ChronometerTest.java
@@ -25,10 +25,10 @@
 /**
  * Test {@link Chronometer}.
  */
-public class ChronometerTest extends ActivityInstrumentationTestCase2<ChronometerStubActivity> {
-    private ChronometerStubActivity mActivity;
+public class ChronometerTest extends ActivityInstrumentationTestCase2<ChronometerCtsActivity> {
+    private ChronometerCtsActivity mActivity;
     public ChronometerTest() {
-        super("com.android.cts.stub", ChronometerStubActivity.class);
+        super("com.android.cts.widget", ChronometerCtsActivity.class);
     }
 
     @Override
@@ -37,6 +37,7 @@
         mActivity = getActivity();
     }
 
+    @UiThreadTest
     public void testConstructor() {
         new Chronometer(mActivity);
 
diff --git a/tests/tests/widget/src/android/widget/cts/CompoundButtonTest.java b/tests/tests/widget/src/android/widget/cts/CompoundButtonTest.java
index 252e237..bf5382a 100644
--- a/tests/tests/widget/src/android/widget/cts/CompoundButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/CompoundButtonTest.java
@@ -16,7 +16,13 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import android.content.res.ColorStateList;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.PorterDuff;
+import android.view.LayoutInflater;
+import android.widget.ToggleButton;
+import com.android.cts.widget.R;
 
 
 import org.xmlpull.v1.XmlPullParser;
@@ -321,6 +327,65 @@
         assertTrue(compoundButton.verifyDrawable(drawable));
     }
 
+    public void testButtonTint() {
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        View layout = inflater.inflate(R.layout.togglebutton_layout, null);
+        CompoundButton inflatedView = (CompoundButton) layout.findViewById(R.id.button_tint);
+
+        assertEquals("Button tint inflated correctly",
+                Color.WHITE, inflatedView.getButtonTintList().getDefaultColor());
+        assertEquals("Button tint mode inflated correctly",
+                PorterDuff.Mode.SRC_OVER, inflatedView.getButtonTintMode());
+
+        MockDrawable button = new MockDrawable();
+        CompoundButton view = new ToggleButton(mContext);
+
+        view.setButtonDrawable(button);
+        assertFalse("No button tint applied by default", button.hasCalledSetTint());
+
+        view.setButtonTintList(ColorStateList.valueOf(Color.WHITE));
+        assertTrue("Button tint applied when setButtonTintList() called after setButton()",
+                button.hasCalledSetTint());
+
+        button.reset();
+        view.setButtonDrawable(null);
+        view.setButtonDrawable(button);
+        assertTrue("Button tint applied when setButtonTintList() called before setButton()",
+                button.hasCalledSetTint());
+    }
+
+    private static class MockDrawable extends Drawable {
+        private boolean mCalledSetTint = false;
+
+        @Override
+        public void draw(Canvas canvas) {}
+
+        @Override
+        public void setAlpha(int alpha) {}
+
+        @Override
+        public void setColorFilter(ColorFilter cf) {}
+
+        @Override
+        public void setTintList(ColorStateList tint) {
+            super.setTintList(tint);
+            mCalledSetTint = true;
+        }
+
+        @Override
+        public int getOpacity() {
+            return 0;
+        }
+
+        public boolean hasCalledSetTint() {
+            return mCalledSetTint;
+        }
+
+        public void reset() {
+            mCalledSetTint = false;
+        }
+    }
+
     private final class MockCompoundButton extends CompoundButton {
         public MockCompoundButton(Context context) {
             super(context);
diff --git a/tests/tests/widget/src/android/widget/cts/CtsActivity.java b/tests/tests/widget/src/android/widget/cts/CtsActivity.java
new file mode 100644
index 0000000..e099694
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/CtsActivity.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2009 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.widget.cts;
+
+import android.app.Activity;
+
+/**
+ * Stub activity for helping test. It's an empty activity.
+ */
+public class CtsActivity extends Activity {
+
+}
diff --git a/tests/tests/widget/src/android/widget/cts/CursorAdapterTest.java b/tests/tests/widget/src/android/widget/cts/CursorAdapterTest.java
index 963c392..0916e59 100644
--- a/tests/tests/widget/src/android/widget/cts/CursorAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/CursorAdapterTest.java
@@ -20,13 +20,15 @@
 
 import android.content.Context;
 import android.cts.util.PollingCheck;
+import android.cts.util.ReadElf;
+import android.cts.util.TestThread;
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.database.DataSetObserver;
 import android.database.sqlite.SQLiteDatabase;
 import android.os.Looper;
-import android.os.cts.TestThread;
-import android.test.AndroidTestCase;
+import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -35,13 +37,13 @@
 import android.widget.FilterQueryProvider;
 import android.widget.TextView;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 /**
  * Test {@link CursorAdapter}.
  */
-public class CursorAdapterTest extends AndroidTestCase {
+public class CursorAdapterTest extends InstrumentationTestCase {
     private static final long TEST_TIME_OUT = 5000;
     private static final int NUMBER_INDEX = 1;
     private static final String FIRST_NUMBER = "123";
@@ -57,11 +59,13 @@
     private Cursor mCursor;
     private ViewGroup mParent;
     private MockCursorAdapter mMockCursorAdapter;
+    private Context mContext;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        File dbDir = getContext().getDir("tests", Context.MODE_WORLD_WRITEABLE);
+        mContext = getInstrumentation().getTargetContext();
+        File dbDir = mContext.getDir("tests", Context.MODE_WORLD_WRITEABLE);
         mDatabaseFile = new File(dbDir, "database_test.db");
         if (mDatabaseFile.exists()) {
             mDatabaseFile.delete();
@@ -90,6 +94,7 @@
         super.tearDown();
     }
 
+    @UiThreadTest
     public void testConstructor() {
         new MockCursorAdapter(mContext, mCursor);
 
@@ -100,6 +105,7 @@
         new MockCursorAdapter(null, null, false);
     }
 
+    @UiThreadTest
     public void testInit() {
         MockCursorAdapter cursorAdapter = new MockCursorAdapter(null, null, false);
         cursorAdapter.init(null, null, false);
@@ -144,6 +150,7 @@
         }
     }
 
+    @UiThreadTest
     public void testGetCount() {
         CursorAdapter cursorAdapter = new MockCursorAdapter(mContext, null);
         assertEquals(0, cursorAdapter.getCount());
@@ -152,6 +159,7 @@
         assertEquals(mCursor.getCount(), cursorAdapter.getCount());
     }
 
+    @UiThreadTest
     public void testAccessCursor() {
         CursorAdapter cursorAdapter = new MockCursorAdapter(mContext, null);
         assertNull(cursorAdapter.getCursor());
@@ -163,6 +171,7 @@
         assertNull(cursorAdapter.getCursor());
     }
 
+    @UiThreadTest
     public void testConvertToString() {
         CursorAdapter cursorAdapter = new MockCursorAdapter(mContext, null);
         assertEquals("", cursorAdapter.convertToString(null));
@@ -170,6 +179,7 @@
         assertEquals(mCursor.toString(), cursorAdapter.convertToString(mCursor));
     }
 
+    @UiThreadTest
     public void testHasStableIds() {
         CursorAdapter cursorAdapter = new MockCursorAdapter(mContext, mCursor);
         assertTrue(cursorAdapter.hasStableIds());
@@ -178,6 +188,7 @@
         assertTrue(cursorAdapter.hasStableIds());
     }
 
+    @UiThreadTest
     public void testGetView() {
         TextView textView = new TextView(mContext);
         textView.setText("getView test");
@@ -209,6 +220,7 @@
         assertEquals(SECOND_NUMBER, retView.getText().toString());
     }
 
+    @UiThreadTest
     public void testNewDropDownView() {
         CursorAdapter cursorAdapter = new MockCursorAdapter(mContext, mCursor);
         // null cursor
@@ -218,6 +230,7 @@
         assertEquals(FIRST_NUMBER, textView.getText().toString());
     }
 
+    @UiThreadTest
     public void testGetDropDownView() {
         MockCursorAdapter cursorAdapter = new MockCursorAdapter(mContext, null);
         // null cursor
@@ -239,12 +252,14 @@
         assertEquals(SECOND_NUMBER, retView.getText().toString());
     }
 
+    @UiThreadTest
     public void testGetFilter() {
         CursorAdapter cursorAdapter = new MockCursorAdapter(mContext, mCursor);
         Filter filter = cursorAdapter.getFilter();
         assertNotNull(filter);
     }
 
+    @UiThreadTest
     public void testGetItem() {
         CursorAdapter cursorAdapter = new MockCursorAdapter(mContext, null);
         // cursor is null
@@ -262,6 +277,7 @@
         assertEquals(SECOND_NUMBER, c.getString(NUMBER_INDEX));
     }
 
+    @UiThreadTest
     public void testGetItemId() {
         CursorAdapter cursorAdapter = new MockCursorAdapter(mContext, null);
         // cursor is null
@@ -276,6 +292,7 @@
         assertEquals(0, cursorAdapter.getItemId(2));
     }
 
+    @UiThreadTest
     public void testAccessFilterQueryProvider() {
         CursorAdapter cursorAdapter = new MockCursorAdapter(mContext, mCursor);
         FilterQueryProvider filterProvider = new MockFilterQueryProvider();
@@ -287,6 +304,7 @@
         assertSame(filterProvider, cursorAdapter.getFilterQueryProvider());
     }
 
+    @UiThreadTest
     public void testRunQueryOnBackgroundThread() {
         CursorAdapter cursorAdapter = new MockCursorAdapter(mContext, mCursor);
         final String constraint = "constraint";
diff --git a/tests/tests/widget/src/android/widget/cts/CursorTreeAdapterTest.java b/tests/tests/widget/src/android/widget/cts/CursorTreeAdapterTest.java
index 1d26777..f74b9972 100644
--- a/tests/tests/widget/src/android/widget/cts/CursorTreeAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/CursorTreeAdapterTest.java
@@ -22,7 +22,8 @@
 import android.database.Cursor;
 import android.database.DataSetObserver;
 import android.database.sqlite.SQLiteDatabase;
-import android.test.AndroidTestCase;
+import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -31,13 +32,13 @@
 import android.widget.FilterQueryProvider;
 import android.widget.TextView;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 /**
  * Test {@link CursorTreeAdapter}.
  */
-public class CursorTreeAdapterTest extends AndroidTestCase {
+public class CursorTreeAdapterTest extends InstrumentationTestCase {
     private static final int NAME_INDEX = 1;
     private static final int VALUE_INDEX = 1;
     private static final String GROUP_ONE         = "group_one";
@@ -61,6 +62,7 @@
     private Cursor mChildCursor1;
     private Cursor mChildCursor2;
     private ViewGroup mParent;
+    private Context mContext;
 
     private Cursor createGroupCursor() {
         mDatabase.execSQL("CREATE TABLE group_table (_id INTEGER PRIMARY KEY, name TEXT);");
@@ -93,7 +95,8 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        File dbDir = getContext().getDir("tests", Context.MODE_WORLD_WRITEABLE);
+        mContext = getInstrumentation().getTargetContext();
+        File dbDir = mContext.getDir("tests", Context.MODE_WORLD_WRITEABLE);
         mDatabaseFile = new File(dbDir, "database_test.db");
         if (mDatabaseFile.exists()) {
             mDatabaseFile.delete();
@@ -136,6 +139,7 @@
         super.tearDown();
     }
 
+    @UiThreadTest
     public void testConstructor() {
         new MockCursorTreeAdapter(mGroupCursor, mContext);
 
@@ -146,6 +150,7 @@
         new MockCursorTreeAdapter(null, null, false);
     }
 
+    @UiThreadTest
     public void testGetCursor() {
         CursorTreeAdapter adapter = new MockCursorTreeAdapter(mGroupCursor, mContext);
         assertSame(mGroupCursor, adapter.getCursor());
@@ -157,6 +162,7 @@
         assertSame(mGroupCursor, adapter.getCursor());
     }
 
+    @UiThreadTest
     public void testSetGroupCursor() {
         CursorTreeAdapter adapter = new MockCursorTreeAdapter(mGroupCursor, mContext);
         assertSame(mGroupCursor, adapter.getCursor());
@@ -168,6 +174,7 @@
         assertSame(mGroupCursor, adapter.getCursor());
     }
 
+    @UiThreadTest
     public void testSetChildrenCursor() {
         MockCursorTreeAdapter adapter = new MockCursorTreeAdapter(mGroupCursor, mContext);
         assertTrue(mGroupCursor.moveToFirst());
@@ -177,6 +184,7 @@
         assertSame(mChildCursor2, adapter.getChild(0, 0));
     }
 
+    @UiThreadTest
     public void testChangeCursor() {
         CursorTreeAdapter adapter = new MockCursorTreeAdapter(null, mContext);
         assertNull(adapter.getCursor());
@@ -188,6 +196,7 @@
         assertNull(adapter.getCursor());
     }
 
+    @UiThreadTest
     public void testNotifyDataSetChangedBoolean() {
         MockCursorTreeAdapter adapter = new MockCursorTreeAdapter(mGroupCursor, mContext);
         MockDataSetObserver observer = new MockDataSetObserver();
@@ -226,6 +235,7 @@
         assertFalse(adapter.hasAddedChild2IntoCache());
     }
 
+    @UiThreadTest
     public void testNotifyDataSetChanged() {
         MockCursorTreeAdapter adapter = new MockCursorTreeAdapter(mGroupCursor, mContext);
         MockDataSetObserver observer = new MockDataSetObserver();
@@ -251,6 +261,7 @@
         assertTrue(adapter.hasAddedChild2IntoCache());
     }
 
+    @UiThreadTest
     public void testNotifyDataSetInvalidated() {
         MockCursorTreeAdapter adapter = new MockCursorTreeAdapter(mGroupCursor, mContext);
         MockDataSetObserver observer = new MockDataSetObserver();
@@ -276,6 +287,7 @@
         assertTrue(adapter.hasAddedChild2IntoCache());
     }
 
+    @UiThreadTest
     public void testOnGroupCollapsed() {
         MockCursorTreeAdapter adapter = new MockCursorTreeAdapter(mGroupCursor, mContext);
 
@@ -313,6 +325,7 @@
         }
     }
 
+    @UiThreadTest
     public void testHasStableIds() {
         CursorTreeAdapter adapter = new MockCursorTreeAdapter(mGroupCursor, mContext);
         assertTrue(adapter.hasStableIds());
@@ -321,6 +334,7 @@
         assertTrue(adapter.hasStableIds());
     }
 
+    @UiThreadTest
     public void testIsChildSelectable() {
         CursorTreeAdapter adapter = new MockCursorTreeAdapter(mGroupCursor, mContext);
         assertTrue(adapter.isChildSelectable(0, 0));
@@ -330,6 +344,7 @@
         assertTrue(adapter.isChildSelectable(0, 0));
     }
 
+    @UiThreadTest
     public void testConvertToString() {
         CursorTreeAdapter adapter = new MockCursorTreeAdapter(mGroupCursor, mContext);
         assertEquals("", adapter.convertToString(null));
@@ -337,6 +352,7 @@
         assertEquals(mGroupCursor.toString(), adapter.convertToString(mGroupCursor));
     }
 
+    @UiThreadTest
     public void testGetFilter() {
         MockCursorTreeAdapter adapter = new MockCursorTreeAdapter(mGroupCursor, mContext);
         Filter filter = adapter.getFilter();
@@ -348,6 +364,7 @@
         assertTrue(adapter.hasCalledConvertToString());
     }
 
+    @UiThreadTest
     public void testAccessQueryProvider() {
         CursorTreeAdapter adapter = new MockCursorTreeAdapter(mGroupCursor, mContext);
         FilterQueryProvider filterProvider = new MockFilterQueryProvider();
@@ -359,6 +376,7 @@
         assertSame(filterProvider, adapter.getFilterQueryProvider());
     }
 
+    @UiThreadTest
     public void testRunQueryOnBackgroundThread() {
         CursorTreeAdapter adapter = new MockCursorTreeAdapter(mGroupCursor, mContext);
         final String constraint = "constraint";
@@ -372,6 +390,7 @@
         assertNull(adapter.runQueryOnBackgroundThread(constraint));
     }
 
+    @UiThreadTest
     public void testGetGroup() {
         CursorTreeAdapter adapter = new MockCursorTreeAdapter(null, mContext);
 
@@ -391,6 +410,7 @@
         assertNull(adapter.getGroup(2));
     }
 
+    @UiThreadTest
     public void testGetGroupCount() {
         CursorTreeAdapter adapter = new MockCursorTreeAdapter(mGroupCursor, mContext);
         assertEquals(mGroupCursor.getCount(), adapter.getGroupCount());
@@ -399,6 +419,7 @@
         assertEquals(0, adapter.getGroupCount());
     }
 
+    @UiThreadTest
     public void testGetGroupId() {
         CursorTreeAdapter adapter = new MockCursorTreeAdapter(null, mContext);
 
@@ -414,6 +435,7 @@
         assertEquals(0, adapter.getGroupId(2));
     }
 
+    @UiThreadTest
     public void testGetGroupView() {
         final String expectedStr = "getGroupView test";
         TextView retView;
@@ -449,6 +471,7 @@
         assertEquals(GROUP_ONE, retView.getText().toString());
     }
 
+    @UiThreadTest
     public void testGetChild() {
         CursorTreeAdapter adapter = new MockCursorTreeAdapter(mGroupCursor, mContext);
         assertEquals(2, adapter.getGroupCount());
@@ -476,6 +499,7 @@
         assertEquals(CHILD_VALUE_THREE, retCursor.getString(VALUE_INDEX));
     }
 
+    @UiThreadTest
     public void testGetChildId() {
         CursorTreeAdapter adapter = new MockCursorTreeAdapter(null, mContext);
 
@@ -504,6 +528,7 @@
         assertEquals(0, adapter.getChildId(0, 2));
     }
 
+    @UiThreadTest
     public void testGetChildrenCount() {
         CursorTreeAdapter adapter = new MockCursorTreeAdapter(null, mContext);
 
@@ -519,6 +544,7 @@
         assertEquals(0, adapter.getChildrenCount(2));
     }
 
+    @UiThreadTest
     public void testGetChildView() {
         final String expectedStr = "getChildView test";
         TextView retView;
diff --git a/tests/tests/widget/src/android/widget/cts/DatePickerTest.java b/tests/tests/widget/src/android/widget/cts/DatePickerTest.java
index ad9da7c..fdadc2c 100644
--- a/tests/tests/widget/src/android/widget/cts/DatePickerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/DatePickerTest.java
@@ -16,14 +16,14 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 import com.android.internal.util.XmlUtils;
 
-
 import android.content.Context;
 import android.content.res.XmlResourceParser;
 import android.os.Parcelable;
-import android.test.AndroidTestCase;
+import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
 import android.util.AttributeSet;
 import android.util.SparseArray;
 import android.util.Xml;
@@ -33,7 +33,16 @@
 /**
  * Test {@link DatePicker}.
  */
-public class DatePickerTest extends AndroidTestCase {
+public class DatePickerTest extends InstrumentationTestCase {
+
+    private Context mContext;
+
+    @Override
+    public void setUp() {
+        mContext = getInstrumentation().getTargetContext();
+    }
+
+    @UiThreadTest
     public void testConstructor() {
         new DatePicker(mContext);
 
@@ -53,6 +62,7 @@
         }
     }
 
+    @UiThreadTest
     public void testSetEnabled() {
         MockDatePicker datePicker = createDatePicker();
 
@@ -65,6 +75,7 @@
         assertTrue(datePicker.isEnabled());
     }
 
+    @UiThreadTest
     public void testInit() {
         MockOnDateChangedListener onDateChangedListener = new MockOnDateChangedListener();
         DatePicker datePicker = createDatePicker();
@@ -78,6 +89,7 @@
         assertEquals(15, datePicker.getDayOfMonth());
     }
 
+    @UiThreadTest
     public void testAccessDate() {
         DatePicker datePicker = createDatePicker();
 
@@ -96,6 +108,7 @@
         assertEquals(19, datePicker.getDayOfMonth());
     }
 
+    @UiThreadTest
     public void testUpdateDate() {
         DatePicker datePicker = createDatePicker();
 
@@ -109,6 +122,7 @@
         assertEquals(19, datePicker.getDayOfMonth());
     }
 
+    @UiThreadTest
     public void testOnSaveInstanceState() {
         MockDatePicker datePicker = createDatePicker();
 
diff --git a/tests/tests/widget/src/android/widget/cts/DialerFilterCtsActivity.java b/tests/tests/widget/src/android/widget/cts/DialerFilterCtsActivity.java
new file mode 100644
index 0000000..572d3fb
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/DialerFilterCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2008 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.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import com.android.cts.widget.R;
+
+/**
+ * A minimal application for DialerFilter test.
+ */
+public class DialerFilterCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.dialerfilter_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/DialerFilterTest.java b/tests/tests/widget/src/android/widget/cts/DialerFilterTest.java
index 1c5c7ff..a8584ae 100644
--- a/tests/tests/widget/src/android/widget/cts/DialerFilterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/DialerFilterTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import org.xmlpull.v1.XmlPullParser;
@@ -39,13 +39,13 @@
 import android.widget.EditText;
 import android.widget.RelativeLayout;
 
-public class DialerFilterTest extends ActivityInstrumentationTestCase2<DialerFilterStubActivity> {
+public class DialerFilterTest extends ActivityInstrumentationTestCase2<DialerFilterCtsActivity> {
     private Activity mActivity;
     private Instrumentation mInstrumentation;
     private DialerFilter mDialerFilter;
 
     public DialerFilterTest() {
-        super("com.android.cts.stub", DialerFilterStubActivity.class);
+        super("com.android.cts.widget", DialerFilterCtsActivity.class);
     }
 
     @Override
@@ -64,6 +64,7 @@
         mDialerFilter = (DialerFilter) mActivity.findViewById(R.id.dialer_filter);
     }
 
+    @UiThreadTest
     public void testConstructor() {
         final XmlPullParser parser = mActivity.getResources().getXml(R.layout.dialerfilter_layout);
         final AttributeSet attrs = Xml.asAttributeSet(parser);
@@ -72,6 +73,7 @@
         new DialerFilter(mActivity, attrs);
     }
 
+    @UiThreadTest
     public void testIsQwertyKeyboard() {
         // Simply call the method. Return value may depend on the default keyboard.
         mDialerFilter.isQwertyKeyboard();
@@ -81,7 +83,7 @@
         // The exact behavior depends on the implementation of DialerKeyListener and
         // TextKeyListener, but even that may be changed. Simply assert basic scenarios.
 
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivity.runOnUiThread(new Runnable() {
             public void run() {
                 mDialerFilter.setMode(DialerFilter.DIGITS_ONLY);
                 mDialerFilter.requestFocus();
@@ -95,7 +97,7 @@
         assertEquals("", mDialerFilter.getLetters().toString());
         assertEquals("123", mDialerFilter.getDigits().toString());
 
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivity.runOnUiThread(new Runnable() {
             public void run() {
                 mDialerFilter.clearText();
                 mDialerFilter.setMode(DialerFilter.LETTERS_ONLY);
@@ -116,7 +118,7 @@
         assertEquals("ADG", mDialerFilter.getLetters().toString());
         assertEquals("", mDialerFilter.getDigits().toString());
 
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivity.runOnUiThread(new Runnable() {
             public void run() {
                 mDialerFilter.clearText();
                 mDialerFilter.setMode(DialerFilter.DIGITS_AND_LETTERS);
@@ -135,7 +137,7 @@
         assertEquals("ADG", mDialerFilter.getLetters().toString());
         // A, D, K may map to numbers on some keyboards. Don't test.
 
-        mInstrumentation.runOnMainSync(new Runnable() {
+        mActivity.runOnUiThread(new Runnable() {
             public void run() {
                 mDialerFilter.clearText();
                 mDialerFilter.setMode(DialerFilter.DIGITS_AND_LETTERS);
diff --git a/tests/tests/widget/src/android/widget/cts/DigitalClockCtsActivity.java b/tests/tests/widget/src/android/widget/cts/DigitalClockCtsActivity.java
new file mode 100644
index 0000000..68cb3f0
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/DigitalClockCtsActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008 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.widget.cts;
+
+import com.android.cts.widget.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * A minimal application for TextView test.
+ */
+public class DigitalClockCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.digitalclock_simplelayout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/DigitalClockTest.java b/tests/tests/widget/src/android/widget/cts/DigitalClockTest.java
index 4184cdd..2f2cc1a 100644
--- a/tests/tests/widget/src/android/widget/cts/DigitalClockTest.java
+++ b/tests/tests/widget/src/android/widget/cts/DigitalClockTest.java
@@ -30,19 +30,19 @@
 import android.widget.DigitalClock;
 import android.widget.LinearLayout;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 import com.android.internal.util.XmlUtils;
 
 
 /**
  * Test {@link DigitalClock}.
  */
-public class DigitalClockTest extends ActivityInstrumentationTestCase<DigitalClockStubActivity> {
+public class DigitalClockTest extends ActivityInstrumentationTestCase<DigitalClockCtsActivity> {
     private Activity mActivity;
     private Context mContext;
 
     public DigitalClockTest() {
-        super("com.android.cts.stub", DigitalClockStubActivity.class);
+        super("com.android.cts.widget", DigitalClockCtsActivity.class);
     }
 
     @Override
@@ -52,6 +52,7 @@
         mContext = getInstrumentation().getContext();
     }
 
+    @UiThreadTest
     public void testConstructor() {
         // new the DigitalClock instance
         new DigitalClock(mContext);
@@ -113,7 +114,7 @@
     private AttributeSet getAttributeSet(int resourceId) {
         XmlResourceParser parser = mActivity.getResources().getXml(resourceId);
         try {
-            XmlUtils.beginDocument(parser, "com.android.cts.stub.alarmclock.DigitalClock");
+            XmlUtils.beginDocument(parser, "com.android.cts.widget.alarmclock.DigitalClock");
         } catch (XmlPullParserException e) {
             fail("unexpected XmlPullParserException.");
         } catch (IOException e) {
diff --git a/tests/tests/widget/src/android/widget/cts/EditTextTest.java b/tests/tests/widget/src/android/widget/cts/EditTextTest.java
index ee10900..7a71a58 100644
--- a/tests/tests/widget/src/android/widget/cts/EditTextTest.java
+++ b/tests/tests/widget/src/android/widget/cts/EditTextTest.java
@@ -28,7 +28,7 @@
 import android.widget.EditText;
 import android.widget.TextView.BufferType;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 public class EditTextTest extends AndroidTestCase {
diff --git a/tests/src/android/widget/cts/ExpandableListSimple.java b/tests/tests/widget/src/android/widget/cts/ExpandableListSimple.java
similarity index 100%
rename from tests/src/android/widget/cts/ExpandableListSimple.java
rename to tests/tests/widget/src/android/widget/cts/ExpandableListSimple.java
diff --git a/tests/tests/widget/src/android/widget/cts/ExpandableListViewTest.java b/tests/tests/widget/src/android/widget/cts/ExpandableListViewTest.java
index 6a68ed9..ac48ed8 100644
--- a/tests/tests/widget/src/android/widget/cts/ExpandableListViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ExpandableListViewTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import org.xmlpull.v1.XmlPullParser;
@@ -390,7 +390,7 @@
 
     public void testDispatchDraw() {
         MockExpandableListView expandableListView = new MockExpandableListView(mContext);
-        expandableListView.dispatchDraw(null);
+        expandableListView.dispatchDraw(new Canvas());
     }
 
     private class MockExpandableListAdapter implements ExpandableListAdapter {
diff --git a/tests/src/android/widget/cts/ExpandableListWithHeaders.java b/tests/tests/widget/src/android/widget/cts/ExpandableListWithHeaders.java
similarity index 100%
rename from tests/src/android/widget/cts/ExpandableListWithHeaders.java
rename to tests/tests/widget/src/android/widget/cts/ExpandableListWithHeaders.java
diff --git a/tests/tests/widget/src/android/widget/cts/FilterTest.java b/tests/tests/widget/src/android/widget/cts/FilterTest.java
index 394f861..2c598dd 100644
--- a/tests/tests/widget/src/android/widget/cts/FilterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/FilterTest.java
@@ -18,29 +18,43 @@
 
 
 import android.cts.util.PollingCheck;
+import android.cts.util.ReadElf;
+import android.cts.util.TestThread;
+import android.os.Looper;
 import android.test.ActivityInstrumentationTestCase2;
 import android.widget.Filter;
 import android.widget.Filter.FilterListener;
 
-public class FilterTest extends ActivityInstrumentationTestCase2<StubActivity> {
+public class FilterTest extends ActivityInstrumentationTestCase2<CtsActivity> {
     private static final long TIME_OUT = 10000;
+    private static final long RUN_TIME = 1000;
     private static final String TEST_CONSTRAINT = "filter test";
     private MockFilter mMockFilter;
 
     public FilterTest() {
-        super("com.android.cts.stub", StubActivity.class);
+        super("com.android.cts.widget", CtsActivity.class);
     }
 
-    public void testConstructor() {
-        new MockFilter();
+    public void testConstructor() throws Throwable {
+        TestThread t = new TestThread(new Runnable() {
+            public void run() {
+                Looper.prepare();
+                new MockFilter();
+            }
+        });
+        t.runTest(RUN_TIME);
     }
 
-    public void testConvertResultToString() {
-        final MockFilter filter = new MockFilter();
-        assertEquals("", filter.convertResultToString(null));
-
+    public void testConvertResultToString() throws Throwable {
         final String testStr = "Test";
-        assertEquals(testStr, filter.convertResultToString(testStr));
+        new TestThread(new Runnable() {
+            public void run() {
+                Looper.prepare();
+                MockFilter filter = new MockFilter();
+                assertEquals("", filter.convertResultToString(null));
+                assertEquals(testStr, filter.convertResultToString(testStr));
+            }
+        }).runTest(RUN_TIME);
     }
 
     public void testFilter1() {
diff --git a/tests/tests/widget/src/android/widget/cts/FrameLayoutCtsActivity.java b/tests/tests/widget/src/android/widget/cts/FrameLayoutCtsActivity.java
new file mode 100644
index 0000000..c638313
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/FrameLayoutCtsActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008 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.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import com.android.cts.widget.R;
+
+/**
+ * A minimal application for frame layout test.
+ */
+public class FrameLayoutCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.framelayout_layout);
+    }
+}
+
diff --git a/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java b/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java
index 6564ce0..31d9fff 100644
--- a/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/FrameLayoutTest.java
@@ -16,7 +16,14 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import android.content.res.ColorStateList;
+import android.cts.util.WidgetTestUtils;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.PorterDuff;
+
+import com.android.cts.widget.R;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -43,13 +50,13 @@
 
 import java.io.IOException;
 
-public class FrameLayoutTest extends ActivityInstrumentationTestCase2<FrameLayoutStubActivity> {
+public class FrameLayoutTest extends ActivityInstrumentationTestCase2<FrameLayoutCtsActivity> {
     private Activity mActivity;
     private Instrumentation mInstrumentation;
     private FrameLayout mFrameLayout;
 
     public FrameLayoutTest() {
-        super("com.android.cts.stub", FrameLayoutStubActivity.class);
+        super("com.android.cts.widget", FrameLayoutCtsActivity.class);
     }
 
     @Override
@@ -268,6 +275,31 @@
         assertTrue(myFrameLayout.verifyDrawable(null));
     }
 
+    public void testForegroundTint() {
+        FrameLayout inflatedView = (FrameLayout) mActivity.findViewById(R.id.foreground_tint);
+
+        assertEquals("Foreground tint inflated correctly",
+                Color.WHITE, inflatedView.getForegroundTintList().getDefaultColor());
+        assertEquals("Foreground tint mode inflated correctly",
+                PorterDuff.Mode.SRC_OVER, inflatedView.getForegroundTintMode());
+
+        MockDrawable foreground = new MockDrawable();
+        FrameLayout view = new FrameLayout(mActivity);
+
+        view.setForeground(foreground);
+        assertFalse("No foreground tint applied by default", foreground.hasCalledSetTint());
+
+        view.setForegroundTintList(ColorStateList.valueOf(Color.WHITE));
+        assertTrue("Foreground tint applied when setForegroundTintList() called after setForeground()",
+                foreground.hasCalledSetTint());
+
+        foreground.reset();
+        view.setForeground(null);
+        view.setForeground(foreground);
+        assertTrue("Foreground tint applied when setForegroundTintList() called before setForeground()",
+                foreground.hasCalledSetTint());
+    }
+
     private static void assertCenterAligned(View container, Drawable drawable) {
         Rect rect = drawable.getBounds();
         int leftDelta = rect.left - container.getLeft();
@@ -285,6 +317,38 @@
         return Xml.asAttributeSet(parser);
     }
 
+    private static class MockDrawable extends Drawable {
+        private boolean mCalledSetTint = false;
+
+        @Override
+        public void draw(Canvas canvas) {}
+
+        @Override
+        public void setAlpha(int alpha) {}
+
+        @Override
+        public void setColorFilter(ColorFilter cf) {}
+
+        @Override
+        public void setTintList(ColorStateList tint) {
+            super.setTintList(tint);
+            mCalledSetTint = true;
+        }
+
+        @Override
+        public int getOpacity() {
+            return 0;
+        }
+
+        public boolean hasCalledSetTint() {
+            return mCalledSetTint;
+        }
+
+        public void reset() {
+            mCalledSetTint = false;
+        }
+    }
+
     private static class MyFrameLayout extends FrameLayout {
         public MyFrameLayout(Context context) {
             super(context);
diff --git a/tests/tests/widget/src/android/widget/cts/FrameLayout_LayoutParamsTest.java b/tests/tests/widget/src/android/widget/cts/FrameLayout_LayoutParamsTest.java
index 89529a2..1e7082f 100644
--- a/tests/tests/widget/src/android/widget/cts/FrameLayout_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/FrameLayout_LayoutParamsTest.java
@@ -16,12 +16,13 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
+import android.cts.util.WidgetTestUtils;
 import android.test.AndroidTestCase;
 import android.util.AttributeSet;
 import android.util.Xml;
diff --git a/tests/tests/widget/src/android/widget/cts/GalleryCtsActivity.java b/tests/tests/widget/src/android/widget/cts/GalleryCtsActivity.java
new file mode 100644
index 0000000..8d32717
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/GalleryCtsActivity.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2008 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.widget.cts;
+
+import com.android.cts.widget.R;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.Gallery;
+import android.widget.ImageView;
+
+/**
+ * A minimal application for {@link Gallery} test.
+ */
+public class GalleryCtsActivity extends Activity {
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.gallery_test);
+
+        Gallery gallery = (Gallery) findViewById(R.id.gallery_test);
+        ImageAdapter adapter = new ImageAdapter(this);
+        gallery.setAdapter(adapter);
+    }
+
+    private static class ImageAdapter extends BaseAdapter {
+        public ImageAdapter(Context c) {
+            mContext = c;
+        }
+
+        public int getCount() {
+            return mImageIds.length;
+        }
+
+        public Object getItem(int position) {
+            return position;
+        }
+
+        public long getItemId(int position) {
+            return position;
+        }
+
+        public View getView(int position, View convertView, ViewGroup parent) {
+            ImageView i = new ImageView(mContext);
+
+            i.setImageResource(mImageIds[position]);
+            i.setScaleType(ImageView.ScaleType.FIT_XY);
+            // let the item's width be 136, height be 88
+            i.setLayoutParams(new Gallery.LayoutParams(136, 88));
+
+            return i;
+        }
+
+        private Context mContext;
+
+        private Integer[] mImageIds = {
+                R.drawable.faces,
+                R.drawable.scenery,
+                R.drawable.testimage,
+                R.drawable.faces,
+                R.drawable.scenery,
+                R.drawable.testimage,
+                R.drawable.faces,
+                R.drawable.scenery,
+                R.drawable.testimage,
+        };
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/GalleryTest.java b/tests/tests/widget/src/android/widget/cts/GalleryTest.java
index 0aacda4..2813965 100644
--- a/tests/tests/widget/src/android/widget/cts/GalleryTest.java
+++ b/tests/tests/widget/src/android/widget/cts/GalleryTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 import com.android.internal.view.menu.ContextMenuBuilder;
 
 
@@ -26,6 +26,7 @@
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.content.Context;
+import android.cts.util.WidgetTestUtils;
 import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
@@ -53,7 +54,7 @@
 /**
  * Test {@link Gallery}.
  */
-public class GalleryTest extends ActivityInstrumentationTestCase2<GalleryStubActivity>  {
+public class GalleryTest extends ActivityInstrumentationTestCase2<GalleryCtsActivity>  {
     private Gallery mGallery;
     private Activity mActivity;
     private Instrumentation mInstrumentation;
@@ -61,7 +62,7 @@
     private final static float DELTA = 0.01f;
 
     public GalleryTest() {
-        super("com.android.cts.stub", GalleryStubActivity.class);
+        super("com.android.cts.widget", GalleryCtsActivity.class);
     }
 
     @Override
@@ -73,6 +74,7 @@
         mGallery = (Gallery) mActivity.findViewById(R.id.gallery_test);
     }
 
+    @UiThreadTest
     public void testConstructor() {
         new Gallery(mContext);
 
@@ -154,6 +156,7 @@
         assertEquals(alpha, t.getAlpha(), DELTA);
     }
 
+    @UiThreadTest
     public void testGenerateLayoutParams() throws XmlPullParserException, IOException {
         final int width = 320;
         final int height = 240;
@@ -187,6 +190,7 @@
         // how to check whether the context menu is showing.
     }
 
+    @UiThreadTest
     public void testDispatchKeyEvent() {
         mGallery = new Gallery(mContext);
         final KeyEvent validKeyEvent = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER);
@@ -222,6 +226,7 @@
         mInstrumentation.waitForIdleSync();
     }
 
+    @UiThreadTest
     public void testCheckLayoutParams() {
         MyGallery gallery = new MyGallery(mContext);
         ViewGroup.LayoutParams p1 = new ViewGroup.LayoutParams(320, 480);
@@ -231,6 +236,7 @@
         assertTrue(gallery.checkLayoutParams(p2));
     }
 
+    @UiThreadTest
     public void testComputeHorizontalScrollExtent() {
         MyGallery gallery = new MyGallery(mContext);
 
@@ -238,6 +244,7 @@
         assertEquals(1, gallery.computeHorizontalScrollExtent());
     }
 
+    @UiThreadTest
     public void testComputeHorizontalScrollOffset() {
         MyGallery gallery = new MyGallery(mContext);
         assertEquals(AdapterView.INVALID_POSITION, gallery.computeHorizontalScrollOffset());
@@ -247,6 +254,7 @@
         assertEquals(gallery.getSelectedItemPosition(), gallery.computeHorizontalScrollOffset());
     }
 
+    @UiThreadTest
     public void testComputeHorizontalScrollRange() {
         MyGallery gallery = new MyGallery(mContext);
         ImageAdapter adapter = new ImageAdapter(mActivity);
@@ -270,6 +278,7 @@
         assertFalse(gallery.getChildAt(1).isPressed());
     }
 
+    @UiThreadTest
     public void testGenerateDefaultLayoutParams() {
         MyGallery gallery = new MyGallery(mContext);
         ViewGroup.LayoutParams p = gallery.generateDefaultLayoutParams();
@@ -296,6 +305,7 @@
         assertEquals(index + 1, gallery.getChildDrawingOrder(childCount, index));
     }
 
+    @UiThreadTest
     public void testGetContextMenuInfo() {
         MockOnCreateContextMenuListener listener = new MockOnCreateContextMenuListener();
         MyGallery gallery = new MyGallery(mContext);
diff --git a/tests/tests/widget/src/android/widget/cts/Gallery_LayoutParamsTest.java b/tests/tests/widget/src/android/widget/cts/Gallery_LayoutParamsTest.java
index af031e4..0502e38 100644
--- a/tests/tests/widget/src/android/widget/cts/Gallery_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/Gallery_LayoutParamsTest.java
@@ -16,12 +16,13 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import org.xmlpull.v1.XmlPullParserException;
 
 import android.content.res.XmlResourceParser;
+import android.cts.util.WidgetTestUtils;
 import android.test.AndroidTestCase;
 import android.widget.Gallery.LayoutParams;
 
diff --git a/tests/tests/widget/src/android/widget/cts/GridLayoutCtsActivity.java b/tests/tests/widget/src/android/widget/cts/GridLayoutCtsActivity.java
new file mode 100644
index 0000000..3277ee8
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/GridLayoutCtsActivity.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012 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.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import com.android.cts.widget.R;
+
+/**
+ * A minimal application for {@link android.widget.GridLayout} test.
+ */
+public class GridLayoutCtsActivity extends Activity {
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.gridlayout_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/GridLayoutTest.java b/tests/tests/widget/src/android/widget/cts/GridLayoutTest.java
index 638fe96..d701623 100644
--- a/tests/tests/widget/src/android/widget/cts/GridLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/GridLayoutTest.java
@@ -27,7 +27,7 @@
 import android.widget.Button;
 import android.widget.GridLayout;
 import android.widget.TextView;
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 import org.xmlpull.v1.XmlPullParser;
 
 import static android.view.ViewGroup.LAYOUT_MODE_OPTICAL_BOUNDS;
@@ -36,7 +36,7 @@
 /**
  * Test {@link android.widget.GridLayout}.
  */
-public class GridLayoutTest extends ActivityInstrumentationTestCase<GridLayoutStubActivity> {
+public class GridLayoutTest extends ActivityInstrumentationTestCase<GridLayoutCtsActivity> {
 
     // The size of the off-screen test container in which we we will testing layout.
     public static final int MAX_X = 2000;
@@ -117,7 +117,7 @@
     private Context mContext;
 
     public GridLayoutTest() {
-        super("com.android.cts.stub", GridLayoutStubActivity.class);
+        super("com.android.cts.widget", GridLayoutCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/widget/src/android/widget/cts/GridViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/GridViewCtsActivity.java
new file mode 100644
index 0000000..7a1182d
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/GridViewCtsActivity.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2008 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.widget.cts;
+
+import com.android.cts.widget.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * A minimal application for {@link GridView} test.
+ */
+public class GridViewCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.gridview_layout);
+    }
+}
+
diff --git a/tests/tests/widget/src/android/widget/cts/GridViewTest.java b/tests/tests/widget/src/android/widget/cts/GridViewTest.java
index 1dd4764..042986c 100644
--- a/tests/tests/widget/src/android/widget/cts/GridViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/GridViewTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import org.xmlpull.v1.XmlPullParser;
@@ -51,13 +51,13 @@
 /**
  * Test {@link GridView}.
  */
-public class GridViewTest extends ActivityInstrumentationTestCase<GridViewStubActivity> {
+public class GridViewTest extends ActivityInstrumentationTestCase<GridViewCtsActivity> {
     private GridView mGridView;
     private Activity mActivity;
     private Instrumentation mInstrumentation;
 
     public GridViewTest() {
-        super("com.android.cts.stub", GridViewStubActivity.class);
+        super("com.android.cts.widget", GridViewCtsActivity.class);
     }
 
     private GridView findGridViewById(int id) {
@@ -234,7 +234,21 @@
     }
 
     public void testSetHorizontalSpacing() {
+        testSetHorizontalSpacing(View.LAYOUT_DIRECTION_LTR);
+    }
+
+    public void testSetHorizontalSpacingRTL() {
+        testSetHorizontalSpacing(View.LAYOUT_DIRECTION_RTL);
+    }
+
+    public void testSetHorizontalSpacing(final int layoutDir) {
         mGridView = findGridViewById(R.id.gridview);
+        mActivity.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mGridView.setLayoutDirection(layoutDir);
+            }
+        });
         mGridView.setStretchMode(GridView.NO_STRETCH);
         // Number of columns should be big enough, otherwise the
         // horizontal spacing cannot be correctly verified.
@@ -252,7 +266,11 @@
 
         View child0 = mGridView.getChildAt(0);
         View child1 = mGridView.getChildAt(1);
-        assertEquals(0, child1.getLeft() - child0.getRight());
+        if (layoutDir == View.LAYOUT_DIRECTION_LTR) {
+            assertEquals(0, child1.getLeft() - child0.getRight());
+        } else {
+            assertEquals(0, child0.getLeft() - child1.getRight());
+        }
 
         mActivity.runOnUiThread(new Runnable() {
             public void run() {
@@ -263,7 +281,11 @@
 
         child0 = mGridView.getChildAt(0);
         child1 = mGridView.getChildAt(1);
-        assertEquals(5, child1.getLeft() - child0.getRight());
+        if (layoutDir == View.LAYOUT_DIRECTION_LTR) {
+            assertEquals(5, child1.getLeft() - child0.getRight());
+        } else {
+            assertEquals(5, child0.getLeft() - child1.getRight());
+        }
     }
 
     public void testSetVerticalSpacing() {
diff --git a/tests/tests/widget/src/android/widget/cts/HeaderViewListAdapterTest.java b/tests/tests/widget/src/android/widget/cts/HeaderViewListAdapterTest.java
index e583dce..2b92a4d 100644
--- a/tests/tests/widget/src/android/widget/cts/HeaderViewListAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/HeaderViewListAdapterTest.java
@@ -16,9 +16,10 @@
 
 package android.widget.cts;
 
-
+import android.content.Context;
 import android.database.DataSetObserver;
-import android.test.AndroidTestCase;
+import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.AdapterView;
@@ -33,13 +34,16 @@
 /**
  * Test {@link HeaderViewListAdapter}.
  */
-public class HeaderViewListAdapterTest extends AndroidTestCase {
+public class HeaderViewListAdapterTest extends InstrumentationTestCase {
 
+    private Context mContext;
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+        mContext = getInstrumentation().getTargetContext();
     }
 
+    @UiThreadTest
     public void testConstructor() {
         ArrayList<ListView.FixedViewInfo> header = new ArrayList<ListView.FixedViewInfo>();
         ArrayList<ListView.FixedViewInfo> footer = new ArrayList<ListView.FixedViewInfo>(5);
@@ -52,7 +56,7 @@
         HeaderViewListAdapter headerViewListAdapter = new HeaderViewListAdapter(null, null, null);
         assertEquals(0, headerViewListAdapter.getHeadersCount());
 
-        ListView lv = new ListView(getContext());
+        ListView lv = new ListView(mContext);
         ArrayList<ListView.FixedViewInfo> header = new ArrayList<ListView.FixedViewInfo>(4);
         header.add(lv.new FixedViewInfo());
         headerViewListAdapter = new HeaderViewListAdapter(header, null, null);
@@ -63,13 +67,14 @@
         HeaderViewListAdapter headerViewListAdapter = new HeaderViewListAdapter(null, null, null);
         assertEquals(0, headerViewListAdapter.getFootersCount());
 
-        ListView lv = new ListView(getContext());
+        ListView lv = new ListView(mContext);
         ArrayList<ListView.FixedViewInfo> footer = new ArrayList<ListView.FixedViewInfo>(4);
         footer.add(lv.new FixedViewInfo());
         headerViewListAdapter = new HeaderViewListAdapter(null, footer, null);
         assertEquals(1, headerViewListAdapter.getFootersCount());
     }
 
+    @UiThreadTest
     public void testIsEmpty() {
         HeaderViewListAdapter headerViewListAdapter = new HeaderViewListAdapter(null, null, null);
         assertTrue(headerViewListAdapter.isEmpty());
@@ -84,10 +89,10 @@
     }
 
     public void testRemoveHeader() {
-        ListView lv = new ListView(getContext());
+        ListView lv = new ListView(mContext);
         ArrayList<ListView.FixedViewInfo> header = new ArrayList<ListView.FixedViewInfo>(4);
-        ListView lv1 = new ListView(getContext());
-        ListView lv2 = new ListView(getContext());
+        ListView lv1 = new ListView(mContext);
+        ListView lv2 = new ListView(mContext);
         ListView.FixedViewInfo info1 = lv.new FixedViewInfo();
         info1.view = lv1;
         ListView.FixedViewInfo info2 = lv.new FixedViewInfo();
@@ -96,7 +101,7 @@
         header.add(info2);
         HeaderViewListAdapter headerViewListAdapter = new HeaderViewListAdapter(header, null, null);
         assertEquals(2, headerViewListAdapter.getHeadersCount());
-        assertFalse(headerViewListAdapter.removeHeader(new ListView(getContext())));
+        assertFalse(headerViewListAdapter.removeHeader(new ListView(mContext)));
         assertTrue(headerViewListAdapter.removeHeader(lv1));
         assertEquals(1, headerViewListAdapter.getHeadersCount());
 
@@ -110,10 +115,10 @@
     }
 
     public void testRemoveFooter() {
-        ListView lv = new ListView(getContext());
+        ListView lv = new ListView(mContext);
         ArrayList<ListView.FixedViewInfo> footer = new ArrayList<ListView.FixedViewInfo>(4);
-        ListView lv1 = new ListView(getContext());
-        ListView lv2 = new ListView(getContext());
+        ListView lv1 = new ListView(mContext);
+        ListView lv2 = new ListView(mContext);
         ListView.FixedViewInfo info1 = lv.new FixedViewInfo();
         info1.view = lv1;
         ListView.FixedViewInfo info2 = lv.new FixedViewInfo();
@@ -122,7 +127,7 @@
         footer.add(info2);
         HeaderViewListAdapter headerViewListAdapter = new HeaderViewListAdapter(null, footer, null);
         assertEquals(2, headerViewListAdapter.getFootersCount());
-        assertFalse(headerViewListAdapter.removeFooter(new ListView(getContext())));
+        assertFalse(headerViewListAdapter.removeFooter(new ListView(mContext)));
         assertTrue(headerViewListAdapter.removeFooter(lv1));
         assertEquals(1, headerViewListAdapter.getFootersCount());
 
@@ -135,11 +140,12 @@
         }
     }
 
+    @UiThreadTest
     public void testGetCount() {
         HeaderViewListAdapter headerViewListAdapter = new HeaderViewListAdapter(null, null, null);
         assertEquals(0, headerViewListAdapter.getCount());
 
-        ListView lv = new ListView(getContext());
+        ListView lv = new ListView(mContext);
         ArrayList<ListView.FixedViewInfo> header = new ArrayList<ListView.FixedViewInfo>(4);
         Object data1 = new Object();
         Object data2 = new Object();
@@ -170,6 +176,7 @@
         assertEquals(5, headerViewListAdapter.getCount());
     }
 
+    @UiThreadTest
     public void testAreAllItemsEnabled() {
         HeaderViewListAdapter headerViewListAdapter = new HeaderViewListAdapter(null, null, null);
         assertTrue(headerViewListAdapter.areAllItemsEnabled());
@@ -189,7 +196,7 @@
             new HeaderViewListAdapter(null, null, fullAdapter);
         assertTrue(headerViewListAdapter.isEnabled(0));
         
-        ListView lv = new ListView(getContext());
+        ListView lv = new ListView(mContext);
         ArrayList<ListView.FixedViewInfo> header = new ArrayList<ListView.FixedViewInfo>(4);
         header.add(lv.new FixedViewInfo());
         headerViewListAdapter = new HeaderViewListAdapter(header, null, fullAdapter);
@@ -212,7 +219,7 @@
     }
 
     public void testGetItem() {
-        ListView lv = new ListView(getContext());
+        ListView lv = new ListView(mContext);
         ArrayList<ListView.FixedViewInfo> header = new ArrayList<ListView.FixedViewInfo>(4);
         Object data1 = new Object();
         Object data2 = new Object();
@@ -243,10 +250,10 @@
     }
 
     public void testGetItemId() {
-        ListView lv = new ListView(getContext());
+        ListView lv = new ListView(mContext);
         ArrayList<ListView.FixedViewInfo> header = new ArrayList<ListView.FixedViewInfo>(4);
-        ListView lv1 = new ListView(getContext());
-        ListView lv2 = new ListView(getContext());
+        ListView lv1 = new ListView(mContext);
+        ListView lv2 = new ListView(mContext);
         ListView.FixedViewInfo info1 = lv.new FixedViewInfo();
         info1.view = lv1;
         ListView.FixedViewInfo info2 = lv.new FixedViewInfo();
@@ -271,10 +278,10 @@
     }
 
     public void testGetView() {
-        ListView lv = new ListView(getContext());
+        ListView lv = new ListView(mContext);
         ArrayList<ListView.FixedViewInfo> header = new ArrayList<ListView.FixedViewInfo>(4);
-        ListView lv1 = new ListView(getContext());
-        ListView lv2 = new ListView(getContext());
+        ListView lv1 = new ListView(mContext);
+        ListView lv2 = new ListView(mContext);
         ListView.FixedViewInfo info1 = lv.new FixedViewInfo();
         info1.view = lv1;
         ListView.FixedViewInfo info2 = lv.new FixedViewInfo();
@@ -345,6 +352,7 @@
         assertNull(fullAdapter.getDataSetObserver());
     }
 
+    @UiThreadTest
     public void testGetFilter() {
         HeaderViewListAdapter headerViewListAdapter = new HeaderViewListAdapter(null, null, null);
         assertNull(headerViewListAdapter.getFilter());
@@ -426,7 +434,7 @@
     private class HeaderViewFullAdapter implements ListAdapter {
         private DataSetObserver mObserver;
         private Object mItem;
-        private final View mView = new View(getContext());
+        private final View mView = new View(mContext);
 
         public DataSetObserver getDataSetObserver() {
             return mObserver;
diff --git a/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewCtsActivity.java
new file mode 100644
index 0000000..312111a
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewCtsActivity.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2009 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.widget.cts;
+
+import com.android.cts.widget.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class HorizontalScrollViewCtsActivity extends Activity {
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.horizontal_scrollview);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java b/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java
index 5d75006..36398c3 100644
--- a/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import org.xmlpull.v1.XmlPullParser;
@@ -24,6 +24,7 @@
 import android.app.Activity;
 import android.content.Context;
 import android.cts.util.PollingCheck;
+import android.cts.util.WidgetTestUtils;
 import android.graphics.Rect;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
@@ -42,7 +43,7 @@
  * Test {@link HorizontalScrollView}.
  */
 public class HorizontalScrollViewTest
-        extends ActivityInstrumentationTestCase2<HorizontalScrollViewStubActivity> {
+        extends ActivityInstrumentationTestCase2<HorizontalScrollViewCtsActivity> {
     private static final int ITEM_WIDTH  = 250;
     private static final int ITEM_HEIGHT = 100;
     private static final int ITEM_COUNT  = 15;
@@ -53,7 +54,7 @@
     private Activity mActivity;
 
     public HorizontalScrollViewTest() {
-        super("com.android.cts.stub", HorizontalScrollViewStubActivity.class);
+        super("com.android.cts.widget", HorizontalScrollViewCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/widget/src/android/widget/cts/ImageButtonTest.java b/tests/tests/widget/src/android/widget/cts/ImageButtonTest.java
index a71ec9d..374c9c2 100644
--- a/tests/tests/widget/src/android/widget/cts/ImageButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ImageButtonTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import org.xmlpull.v1.XmlPullParser;
diff --git a/tests/tests/widget/src/android/widget/cts/ImageSwitcherTest.java b/tests/tests/widget/src/android/widget/cts/ImageSwitcherTest.java
index 49bf3c6..eb75557 100644
--- a/tests/tests/widget/src/android/widget/cts/ImageSwitcherTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ImageSwitcherTest.java
@@ -16,13 +16,14 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import org.xmlpull.v1.XmlPullParser;
 
 import android.content.Context;
 import android.content.res.Resources;
+import android.cts.util.WidgetTestUtils;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.drawable.BitmapDrawable;
diff --git a/tests/tests/widget/src/android/widget/cts/ImageViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ImageViewCtsActivity.java
new file mode 100644
index 0000000..295f3da
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ImageViewCtsActivity.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2008 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.widget.cts;
+
+import com.android.cts.widget.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * A minimal application for {@link ImageView} test.
+ */
+public class ImageViewCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.imageview_layout);
+    }
+}
+
diff --git a/tests/tests/widget/src/android/widget/cts/ImageViewTest.java b/tests/tests/widget/src/android/widget/cts/ImageViewTest.java
index a213f05..c93d4a1 100644
--- a/tests/tests/widget/src/android/widget/cts/ImageViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ImageViewTest.java
@@ -22,10 +22,14 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 
+import android.content.res.ColorStateList;
+import android.graphics.Color;
+
 import org.xmlpull.v1.XmlPullParser;
 
 import android.app.Activity;
 import android.content.Context;
+import android.cts.util.WidgetTestUtils;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
@@ -44,18 +48,18 @@
 import android.widget.ImageView;
 import android.widget.ImageView.ScaleType;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 /**
  * Test {@link ImageView}.
  */
-public class ImageViewTest extends ActivityInstrumentationTestCase<ImageViewStubActivity> {
+public class ImageViewTest extends ActivityInstrumentationTestCase<ImageViewCtsActivity> {
     private ImageView mImageView;
     private Activity mActivity;
 
     public ImageViewTest() {
-        super("com.android.cts.stub", ImageViewStubActivity.class);
+        super("com.android.cts.widget", ImageViewCtsActivity.class);
     }
 
     /**
@@ -437,6 +441,31 @@
         assertTrue(mockImageView.verifyDrawable(bgdrawable));
     }
 
+    public void testImageTint() {
+        ImageView inflatedView = (ImageView) mActivity.findViewById(R.id.image_tint);
+
+        assertEquals("Image tint inflated correctly",
+                Color.WHITE, inflatedView.getImageTintList().getDefaultColor());
+        assertEquals("Image tint mode inflated correctly",
+                PorterDuff.Mode.SRC_OVER, inflatedView.getImageTintMode());
+
+        MockDrawable image = new MockDrawable();
+        ImageView view = new ImageView(mActivity);
+
+        view.setImageDrawable(image);
+        assertFalse("No image tint applied by default", image.hasCalledSetTint());
+
+        view.setImageTintList(ColorStateList.valueOf(Color.WHITE));
+        assertTrue("Image tint applied when setImageTintList() called after set()",
+                image.hasCalledSetTint());
+
+        image.reset();
+        view.setImageDrawable(null);
+        view.setImageDrawable(image);
+        assertTrue("Image tint applied when setImageTintList() called before set()",
+                image.hasCalledSetTint());
+    }
+
     private static class MockImageView extends ImageView {
         private boolean mOnSizeChangedCalled = false;
 
@@ -500,6 +529,7 @@
     private class MockDrawable extends Drawable {
         private ColorFilter mColorFilter;
         private boolean mDrawCalled = false;
+        private boolean mCalledSetTint = false;
         private int mAlpha;
 
         public boolean hasDrawCalled() {
@@ -537,5 +567,19 @@
         public boolean isStateful() {
             return true;
         }
+
+        @Override
+        public void setTintList(ColorStateList tint) {
+            super.setTintList(tint);
+            mCalledSetTint = true;
+        }
+
+        public boolean hasCalledSetTint() {
+            return mCalledSetTint;
+        }
+
+        public void reset() {
+            mCalledSetTint = false;
+        }
     }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/LayoutDirectionCtsActivity.java b/tests/tests/widget/src/android/widget/cts/LayoutDirectionCtsActivity.java
new file mode 100644
index 0000000..093f554
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/LayoutDirectionCtsActivity.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012 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.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import com.android.cts.widget.R;
+
+/**
+ * A minimal application for layout direction test.
+ */
+public class LayoutDirectionCtsActivity extends Activity {
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.layoutdirection_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/LayoutDirectionTest.java b/tests/tests/widget/src/android/widget/cts/LayoutDirectionTest.java
index 5c8be24..c393e95 100644
--- a/tests/tests/widget/src/android/widget/cts/LayoutDirectionTest.java
+++ b/tests/tests/widget/src/android/widget/cts/LayoutDirectionTest.java
@@ -20,17 +20,17 @@
 import android.test.UiThreadTest;
 import android.view.ViewGroup;
 import android.widget.*;
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 import static android.view.View.LAYOUT_DIRECTION_LTR;
 import static android.view.View.LAYOUT_DIRECTION_RTL;
 import static android.view.View.LAYOUT_DIRECTION_INHERIT;
 import static android.view.View.LAYOUT_DIRECTION_LOCALE;
 
-public class LayoutDirectionTest extends ActivityInstrumentationTestCase2<LayoutDirectionStubActivity> {
+public class LayoutDirectionTest extends ActivityInstrumentationTestCase2<LayoutDirectionCtsActivity> {
 
     public LayoutDirectionTest() {
-        super(LayoutDirectionStubActivity.class);
+        super(LayoutDirectionCtsActivity.class);
     }
 
     private void checkDefaultDirectionForOneLayoutWithCode(ViewGroup vg) {
diff --git a/tests/tests/widget/src/android/widget/cts/LinearLayoutCtsActivity.java b/tests/tests/widget/src/android/widget/cts/LinearLayoutCtsActivity.java
new file mode 100644
index 0000000..0cb5bc0
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/LinearLayoutCtsActivity.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2008 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.widget.cts;
+
+import com.android.cts.widget.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * A minimal application for {@link LinearLayout} test.
+ */
+public class LinearLayoutCtsActivity extends Activity {
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.linearlayout_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/LinearLayoutTest.java b/tests/tests/widget/src/android/widget/cts/LinearLayoutTest.java
index 4465533..5815f9a 100644
--- a/tests/tests/widget/src/android/widget/cts/LinearLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/LinearLayoutTest.java
@@ -31,17 +31,17 @@
 import android.widget.ListView;
 import android.widget.TextView;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 /**
  * Test {@link LinearLayout}.
  */
-public class LinearLayoutTest extends ActivityInstrumentationTestCase<LinearLayoutStubActivity> {
+public class LinearLayoutTest extends ActivityInstrumentationTestCase<LinearLayoutCtsActivity> {
     private Context mContext;
     private Activity mActivity;
 
     public LinearLayoutTest() {
-        super("com.android.cts.stub", LinearLayoutStubActivity.class);
+        super("com.android.cts.widget", LinearLayoutCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/widget/src/android/widget/cts/LinearLayout_LayoutParamsTest.java b/tests/tests/widget/src/android/widget/cts/LinearLayout_LayoutParamsTest.java
index 72f3ff6..8ecca6f 100644
--- a/tests/tests/widget/src/android/widget/cts/LinearLayout_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/LinearLayout_LayoutParamsTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 import com.android.internal.util.XmlUtils;
 
 
diff --git a/tests/tests/widget/src/android/widget/cts/ListViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ListViewCtsActivity.java
new file mode 100644
index 0000000..186e47b
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ListViewCtsActivity.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2009 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.widget.cts;
+
+import com.android.cts.widget.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class ListViewCtsActivity extends Activity {
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.listview_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/ListViewTest.java b/tests/tests/widget/src/android/widget/cts/ListViewTest.java
index 7af8c2e..5f0967a 100644
--- a/tests/tests/widget/src/android/widget/cts/ListViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ListViewTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 import com.google.android.collect.Lists;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -51,7 +51,7 @@
 
 import junit.framework.Assert;
 
-public class ListViewTest extends ActivityInstrumentationTestCase2<ListViewStubActivity> {
+public class ListViewTest extends ActivityInstrumentationTestCase2<ListViewCtsActivity> {
     private final String[] mCountryList = new String[] {
         "Argentina", "Australia", "China", "France", "Germany", "Italy", "Japan", "United States"
     };
@@ -69,7 +69,7 @@
     private ArrayAdapter<String> mAdapter_empty;
 
     public ListViewTest() {
-        super("com.android.cts.stub", ListViewStubActivity.class);
+        super("com.android.cts.widget", ListViewCtsActivity.class);
     }
 
     protected void setUp() throws Exception {
diff --git a/tests/tests/widget/src/android/widget/cts/MediaControllerCtsActivity.java b/tests/tests/widget/src/android/widget/cts/MediaControllerCtsActivity.java
new file mode 100644
index 0000000..5dfcc59
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/MediaControllerCtsActivity.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2008 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.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.MediaController;
+
+import com.android.cts.widget.R;
+
+/**
+ * A minimal application for {@link MediaController} test.
+ */
+public class MediaControllerCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.mediacontroller_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/MediaControllerTest.java b/tests/tests/widget/src/android/widget/cts/MediaControllerTest.java
index 5ae692b..49bc767 100644
--- a/tests/tests/widget/src/android/widget/cts/MediaControllerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/MediaControllerTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import org.xmlpull.v1.XmlPullParser;
@@ -43,14 +43,14 @@
  * Test {@link MediaController}.
  */
 public class MediaControllerTest extends
-        ActivityInstrumentationTestCase2<MediaControllerStubActivity> {
+        ActivityInstrumentationTestCase2<MediaControllerCtsActivity> {
     private MediaController mMediaController;
     private Activity mActivity;
     private Instrumentation mInstrumentation;
     private static final long DEFAULT_TIMEOUT = 3000;
 
     public MediaControllerTest() {
-        super("com.android.cts.stub", MediaControllerStubActivity.class);
+        super("com.android.cts.widget", MediaControllerCtsActivity.class);
     }
 
     @Override
@@ -60,6 +60,7 @@
         mInstrumentation = getInstrumentation();
     }
 
+    @UiThreadTest
     public void testConstructor() {
         new MediaController(mActivity, null);
 
@@ -109,7 +110,12 @@
     }
 
     public void testShow() {
-        mMediaController = new MediaController(mActivity, true);
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mMediaController = new MediaController(mActivity, true);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
         assertFalse(mMediaController.isShowing());
 
         final MockMediaPlayerControl mediaPlayerControl = new MockMediaPlayerControl();
@@ -185,7 +191,12 @@
     }
 
     public void testOnTrackballEvent() {
-        mMediaController = new MediaController(mActivity);
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                mMediaController = new MediaController(mActivity);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
         final MockMediaPlayerControl mediaPlayerControl = new MockMediaPlayerControl();
         mMediaController.setMediaPlayer(mediaPlayerControl);
 
@@ -238,6 +249,7 @@
         assertFalse(mMediaController.isEnabled());
     }
 
+    @UiThreadTest
     public void testSetPrevNextListeners() {
         final View videoView = mActivity.findViewById(R.id.mediacontroller_videoview);
         final MockMediaPlayerControl mediaPlayerControl = new MockMediaPlayerControl();
diff --git a/tests/tests/widget/src/android/widget/cts/MockApplication.java b/tests/tests/widget/src/android/widget/cts/MockApplication.java
new file mode 100644
index 0000000..827599d
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/MockApplication.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2008 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.widget.cts;
+
+import android.app.Application;
+import android.content.res.Configuration;
+
+
+public class MockApplication extends Application {
+
+    public boolean isOnCreateCalled;
+    public boolean isConstructorCalled;
+    public boolean isOnConfigurationChangedCalled;
+    public boolean isOnLowMemoryCalled;
+
+    public MockApplication() {
+        super();
+        isConstructorCalled = true;
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        isOnCreateCalled = true;
+    }
+
+    @Override
+    public void onTerminate() {
+        super.onTerminate();
+        // The documentation states that one cannot rely on this method being called. No need to
+        // test it here.
+    }
+
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        isOnConfigurationChangedCalled = true;
+    }
+
+    @Override
+    public void onLowMemory() {
+        super.onLowMemory();
+        isOnLowMemoryCalled = true;
+    }
+}
diff --git a/tests/src/android/widget/cts/MockLinearLayout.java b/tests/tests/widget/src/android/widget/cts/MockLinearLayout.java
similarity index 100%
rename from tests/src/android/widget/cts/MockLinearLayout.java
rename to tests/tests/widget/src/android/widget/cts/MockLinearLayout.java
diff --git a/tests/tests/widget/src/android/widget/cts/MockPopupWindowCtsActivity.java b/tests/tests/widget/src/android/widget/cts/MockPopupWindowCtsActivity.java
new file mode 100644
index 0000000..a68286a
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/MockPopupWindowCtsActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2008 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.widget.cts;
+
+import com.android.cts.widget.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.PopupWindow;
+
+/**
+ * Stub activity for testing {@link PopupWindow}
+ */
+public class MockPopupWindowCtsActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.popupwindow);
+    }
+}
+
diff --git a/tests/src/android/widget/cts/MockTextView.java b/tests/tests/widget/src/android/widget/cts/MockTextView.java
similarity index 100%
rename from tests/src/android/widget/cts/MockTextView.java
rename to tests/tests/widget/src/android/widget/cts/MockTextView.java
diff --git a/tests/tests/widget/src/android/widget/cts/MockURLSpanTestActivity.java b/tests/tests/widget/src/android/widget/cts/MockURLSpanTestActivity.java
new file mode 100644
index 0000000..ab4940c
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/MockURLSpanTestActivity.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2009 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.widget.cts;
+
+import com.android.cts.widget.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * A Mock application for {@link URLSpan} test.
+ */
+public class MockURLSpanTestActivity extends Activity {
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.urlspan_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextViewCtsActivity.java
new file mode 100644
index 0000000..1379150
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextViewCtsActivity.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2009 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.widget.cts;
+
+import com.android.cts.widget.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * A minimal application for MultiAutoCompleteTextView test.
+ */
+public class MultiAutoCompleteTextViewCtsActivity extends Activity {
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.multi_auto_complete_text_view_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextViewTest.java b/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextViewTest.java
index b37b4ef..4afdb80 100644
--- a/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/MultiAutoCompleteTextViewTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import org.xmlpull.v1.XmlPullParser;
@@ -38,13 +38,13 @@
 import android.widget.MultiAutoCompleteTextView.Tokenizer;
 
 public class MultiAutoCompleteTextViewTest extends ActivityInstrumentationTestCase2
-        <MultiAutoCompleteTextViewStubActivity> {
+        <MultiAutoCompleteTextViewCtsActivity> {
     private MultiAutoCompleteTextView mMultiAutoCompleteTextView_country;
     private MultiAutoCompleteTextView mMultiAutoCompleteTextView_name;
     private Activity mActivity;
 
     public MultiAutoCompleteTextViewTest() {
-        super("com.android.cts.stub", MultiAutoCompleteTextViewStubActivity.class);
+        super("com.android.cts.widget", MultiAutoCompleteTextViewCtsActivity.class);
     }
 
     @Override
@@ -59,6 +59,7 @@
                 .findViewById(R.id.name_edit);
     }
 
+    @UiThreadTest
     public void testConstructor() {
         XmlPullParser parser = mActivity.getResources()
                 .getXml(R.layout.multi_auto_complete_text_view_layout);
@@ -151,6 +152,7 @@
         assertEquals(str + ", ", mMultiAutoCompleteTextView_country.getText().toString());
     }
 
+    @UiThreadTest
     public void testPerformFiltering() {
         MyMultiAutoCompleteTextView multiAutoCompleteTextView =
             new MyMultiAutoCompleteTextView(mActivity);
@@ -175,6 +177,7 @@
         assertNotNull(multiAutoCompleteTextView.getFilter());
     }
 
+    @UiThreadTest
     public void testReplaceText() {
         MyMultiAutoCompleteTextView multiAutoCompleteTextView =
             new MyMultiAutoCompleteTextView(mActivity);
diff --git a/tests/src/android/widget/cts/MyGallery.java b/tests/tests/widget/src/android/widget/cts/MyGallery.java
similarity index 100%
rename from tests/src/android/widget/cts/MyGallery.java
rename to tests/tests/widget/src/android/widget/cts/MyGallery.java
diff --git a/tests/src/android/widget/cts/MyHorizontalScrollView.java b/tests/tests/widget/src/android/widget/cts/MyHorizontalScrollView.java
similarity index 100%
rename from tests/src/android/widget/cts/MyHorizontalScrollView.java
rename to tests/tests/widget/src/android/widget/cts/MyHorizontalScrollView.java
diff --git a/tests/src/android/widget/cts/MyScrollView.java b/tests/tests/widget/src/android/widget/cts/MyScrollView.java
similarity index 100%
rename from tests/src/android/widget/cts/MyScrollView.java
rename to tests/tests/widget/src/android/widget/cts/MyScrollView.java
diff --git a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
index 997c2e9..e1742c8 100644
--- a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import android.app.Activity;
@@ -25,8 +25,10 @@
 import android.graphics.Color;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.os.Debug;
 import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
 import android.view.Display;
 import android.view.Gravity;
 import android.view.MotionEvent;
@@ -41,7 +43,7 @@
 import android.widget.PopupWindow.OnDismissListener;
 
 public class PopupWindowTest extends
-        ActivityInstrumentationTestCase2<MockPopupWindowStubActivity> {
+        ActivityInstrumentationTestCase2<MockPopupWindowCtsActivity> {
     private Instrumentation mInstrumentation;
     private Activity mActivity;
     /** The popup window. */
@@ -51,7 +53,7 @@
      * Instantiates a new popup window test.
      */
     public PopupWindowTest() {
-        super("com.android.cts.stub", MockPopupWindowStubActivity.class);
+        super("com.android.cts.widget", MockPopupWindowCtsActivity.class);
     }
 
     /*
@@ -366,6 +368,7 @@
         assertTrue(maxAvailableHeight <= avaliable);
     }
 
+    @UiThreadTest
     public void testDismiss() {
         mPopupWindow = createPopupWindow(createPopupContent());
         assertFalse(mPopupWindow.isShowing());
@@ -447,7 +450,13 @@
         int[] sndXY = new int[2];
         int[] viewInWindowXY = new int[2];
 
-        mPopupWindow = createPopupWindow(createPopupContent());
+        mInstrumentation.runOnMainSync(new Runnable() {
+            public void run() {
+                mPopupWindow = createPopupWindow(createPopupContent());
+            }
+        });
+
+        mInstrumentation.waitForIdleSync();
         // Do not update if it is not shown
         assertFalse(mPopupWindow.isShowing());
         assertEquals(100, mPopupWindow.getWidth());
@@ -492,30 +501,54 @@
     }
 
     public void testUpdateDimensionAndAlignAnchorView() {
-        mPopupWindow = createPopupWindow(createPopupContent());
+        mInstrumentation.runOnMainSync(new Runnable() {
+            public void run() {
+                mPopupWindow = createPopupWindow(createPopupContent());
+            }
+        });
+        mInstrumentation.waitForIdleSync();
 
-        View anchorView = mActivity.findViewById(R.id.anchor_upper);
+        final View anchorView = mActivity.findViewById(R.id.anchor_upper);
         mPopupWindow.update(anchorView, 50, 50);
         // Do not update if it is not shown
         assertFalse(mPopupWindow.isShowing());
         assertEquals(100, mPopupWindow.getWidth());
         assertEquals(100, mPopupWindow.getHeight());
 
-        mPopupWindow.showAsDropDown(anchorView);
+        mInstrumentation.runOnMainSync(new Runnable() {
+            public void run() {
+                mPopupWindow.showAsDropDown(anchorView);
+            }
+        });
         mInstrumentation.waitForIdleSync();
         // update if it is shown
-        mPopupWindow.update(anchorView, 50, 50);
+        mInstrumentation.runOnMainSync(new Runnable() {
+            public void run() {
+                mPopupWindow.update(anchorView, 50, 50);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
         assertTrue(mPopupWindow.isShowing());
         assertEquals(50, mPopupWindow.getWidth());
         assertEquals(50, mPopupWindow.getHeight());
 
         // ignore if width or height is -1
-        mPopupWindow.update(anchorView, -1, -1);
+        mInstrumentation.runOnMainSync(new Runnable() {
+            public void run() {
+                mPopupWindow.update(anchorView, -1, -1);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
         assertTrue(mPopupWindow.isShowing());
         assertEquals(50, mPopupWindow.getWidth());
         assertEquals(50, mPopupWindow.getHeight());
 
-        mPopupWindow.dismiss();
+        mInstrumentation.runOnMainSync(new Runnable() {
+            public void run() {
+                mPopupWindow.dismiss();
+            }
+        });
+        mInstrumentation.waitForIdleSync();
     }
 
     public void testUpdateDimensionAndAlignAnchorViewWithOffsets() {
@@ -548,7 +581,8 @@
         assertEquals(50, mPopupWindow.getHeight());
 
         mPopupWindow.getContentView().getLocationOnScreen(viewXY);
-        // the position should be changed
+
+        // The popup should appear below and to right with an offset.
         assertEquals(anchorXY[0] + 20 + viewInWindowOff[0], viewXY[0]);
         assertEquals(anchorXY[1] + anchorView.getHeight() + 50 + viewInWindowOff[1], viewXY[1]);
 
@@ -565,14 +599,15 @@
         assertEquals(50, mPopupWindow.getHeight());
 
         mPopupWindow.getContentView().getLocationOnScreen(viewXY);
-        // the position should be changed
+
+        // The popup should appear below and to right with an offset.
         assertEquals(anchorXY[0] + 10 + viewInWindowOff[0], viewXY[0]);
         assertEquals(anchorXY[1] + anchorView.getHeight() + 50 + viewInWindowOff[1], viewXY[1]);
 
-        final View anthoterView = mActivity.findViewById(R.id.anchor_middle_right);
+        final View anotherView = mActivity.findViewById(R.id.anchor_middle_left);
         mInstrumentation.runOnMainSync(new Runnable() {
             public void run() {
-                mPopupWindow.update(anthoterView, 0, 0, 60, 60);
+                mPopupWindow.update(anotherView, 0, 0, 60, 60);
             }
         });
         mInstrumentation.waitForIdleSync();
@@ -582,11 +617,12 @@
         assertEquals(60, mPopupWindow.getHeight());
 
         int[] newXY = new int[2];
-        anthoterView.getLocationOnScreen(newXY);
+        anotherView.getLocationOnScreen(newXY);
         mPopupWindow.getContentView().getLocationOnScreen(viewXY);
-        // the position should be changed
+
+        // The popup should appear below and to the right.
         assertEquals(newXY[0] + viewInWindowOff[0], viewXY[0]);
-        assertEquals(newXY[1] + anthoterView.getHeight() + viewInWindowOff[1], viewXY[1]);
+        assertEquals(newXY[1] + anotherView.getHeight() + viewInWindowOff[1], viewXY[1]);
 
         dismissPopup();
     }
@@ -633,7 +669,12 @@
     }
 
     public void testIsAboveAnchor() {
-        mPopupWindow = createPopupWindow(createPopupContent());
+        mInstrumentation.runOnMainSync(new Runnable() {
+            public void run() {
+                mPopupWindow = createPopupWindow(createPopupContent());
+            }
+        });
+        mInstrumentation.waitForIdleSync();
         final View upperAnchor = mActivity.findViewById(R.id.anchor_upper);
 
         mInstrumentation.runOnMainSync(new Runnable() {
@@ -778,8 +819,7 @@
     }
 
     private View createPopupContent() {
-        TextView popupView = new TextView(mActivity);
-        popupView.setText("Popup");
+        View popupView = new View(mActivity);
         popupView.setLayoutParams(new ViewGroup.LayoutParams(50, 50));
         popupView.setBackgroundColor(Color.WHITE);
 
diff --git a/tests/tests/widget/src/android/widget/cts/ProgressBarCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ProgressBarCtsActivity.java
new file mode 100644
index 0000000..8298d5f
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ProgressBarCtsActivity.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2008 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.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * An application for ProgressBar test
+ *
+ */
+public class ProgressBarCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/ProgressBarTest.java b/tests/tests/widget/src/android/widget/cts/ProgressBarTest.java
index 8a0b9a0..e57d298 100644
--- a/tests/tests/widget/src/android/widget/cts/ProgressBarTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ProgressBarTest.java
@@ -16,7 +16,12 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import android.content.res.ColorStateList;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.view.LayoutInflater;
+
+import com.android.cts.widget.R;
 
 
 import android.content.Context;
@@ -314,8 +319,81 @@
         // Do not test, it's controlled by View. Implementation details
     }
 
+    public void testProgressTint() {
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        View layout = inflater.inflate(R.layout.progressbar_layout, null);
+        ProgressBar inflatedView = (ProgressBar) layout.findViewById(R.id.progress_tint);
+
+        assertEquals("Progress tint inflated correctly",
+                Color.WHITE, inflatedView.getProgressTintList().getDefaultColor());
+        assertEquals("Progress tint mode inflated correctly",
+                PorterDuff.Mode.SRC_OVER, inflatedView.getProgressTintMode());
+
+        assertEquals("Progress background tint inflated correctly",
+                Color.WHITE, inflatedView.getProgressBackgroundTintList().getDefaultColor());
+        assertEquals("Progress background tint mode inflated correctly",
+                PorterDuff.Mode.SRC_OVER, inflatedView.getProgressBackgroundTintMode());
+
+        assertEquals("Secondary progress tint inflated correctly",
+                Color.WHITE, inflatedView.getSecondaryProgressTintList().getDefaultColor());
+        assertEquals("Secondary progress tint mode inflated correctly",
+                PorterDuff.Mode.SRC_OVER, inflatedView.getSecondaryProgressTintMode());
+
+        MockDrawable progress = new MockDrawable();
+        ProgressBar view = new ProgressBar(mContext);
+
+        view.setProgressDrawable(progress);
+        assertFalse("No progress tint applied by default", progress.hasCalledSetTint());
+
+        view.setProgressBackgroundTintList(ColorStateList.valueOf(Color.WHITE));
+        assertFalse("Progress background tint not applied when layer missing",
+                progress.hasCalledSetTint());
+
+        view.setSecondaryProgressTintList(ColorStateList.valueOf(Color.WHITE));
+        assertFalse("Secondary progress tint not applied when layer missing",
+                progress.hasCalledSetTint());
+
+        view.setProgressTintList(ColorStateList.valueOf(Color.WHITE));
+        assertTrue("Progress tint applied when setProgressTintList() called after setProgress()",
+                progress.hasCalledSetTint());
+
+        progress.reset();
+        view.setProgressDrawable(null);
+        view.setProgressDrawable(progress);
+        assertTrue("Progress tint applied when setProgressTintList() called before setProgress()",
+                progress.hasCalledSetTint());
+    }
+
+    public void testIndeterminateTint() {
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        View layout = inflater.inflate(R.layout.progressbar_layout, null);
+        ProgressBar inflatedView = (ProgressBar) layout.findViewById(R.id.indeterminate_tint);
+
+        assertEquals("Indeterminate tint inflated correctly",
+                Color.WHITE, inflatedView.getIndeterminateTintList().getDefaultColor());
+        assertEquals("Indeterminate tint mode inflated correctly",
+                PorterDuff.Mode.SRC_OVER, inflatedView.getIndeterminateTintMode());
+
+        MockDrawable indeterminate = new MockDrawable();
+        ProgressBar view = new ProgressBar(mContext);
+
+        view.setIndeterminateDrawable(indeterminate);
+        assertFalse("No indeterminate tint applied by default", indeterminate.hasCalledSetTint());
+
+        view.setIndeterminateTintList(ColorStateList.valueOf(Color.WHITE));
+        assertTrue("Indeterminate tint applied when setIndeterminateTintList() called after "
+                + "setIndeterminate()", indeterminate.hasCalledSetTint());
+
+        indeterminate.reset();
+        view.setIndeterminateDrawable(null);
+        view.setIndeterminateDrawable(indeterminate);
+        assertTrue("Indeterminate tint applied when setIndeterminateTintList() called before "
+                + "setIndeterminate()", indeterminate.hasCalledSetTint());
+    }
+
     private class MockDrawable extends Drawable {
         private boolean mCalledDraw = false;
+        private boolean mCalledSetTint = false;
 
         @Override
         public void draw(Canvas canvas) {
@@ -335,12 +413,23 @@
         public void setColorFilter(ColorFilter cf) {
         }
 
+        @Override
+        public void setTintList(ColorStateList tint) {
+            super.setTintList(tint);
+            mCalledSetTint = true;
+        }
+
+        public boolean hasCalledSetTint() {
+            return mCalledSetTint;
+        }
+
         public boolean hasCalledDraw() {
             return mCalledDraw;
         }
 
         public void reset() {
             mCalledDraw = false;
+            mCalledSetTint = false;
         }
 
     }
diff --git a/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java b/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java
index 79a51c8..4ec4eb5 100644
--- a/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RadioButtonTest.java
@@ -16,11 +16,12 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import android.content.Context;
 import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
 import android.util.AttributeSet;
 import android.widget.RadioButton;
 
@@ -66,6 +67,7 @@
         new RadioButton(mContext, attrs, Integer.MIN_VALUE);
     }
 
+    @UiThreadTest
     public void testToggle() {
         RadioButton button = new RadioButton(mContext);
         assertFalse(button.isChecked());
diff --git a/tests/tests/widget/src/android/widget/cts/RadioGroupTest.java b/tests/tests/widget/src/android/widget/cts/RadioGroupTest.java
index f7baab7..a172ecb 100644
--- a/tests/tests/widget/src/android/widget/cts/RadioGroupTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RadioGroupTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import org.xmlpull.v1.XmlPullParser;
@@ -24,6 +24,7 @@
 
 import android.content.Context;
 import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
 import android.util.AttributeSet;
 import android.util.Xml;
 import android.view.Gravity;
@@ -107,6 +108,7 @@
         assertEquals(0, newButton.getId() & 0xFF000000);
     }
 
+    @UiThreadTest
     public void testInternalCheckedStateTracker() {
         mDefaultRadioGroup = new RadioGroup(mContext);
         RadioButton newButton = new RadioButton(mContext);
@@ -138,6 +140,7 @@
         assertHaveNotCalledOnCheckedChanged(listener);
     }
 
+    @UiThreadTest
     public void testGetCheckedRadioButtonId() {
         assertEquals(-1, mDefaultRadioGroup.getCheckedRadioButtonId());
 
@@ -158,6 +161,7 @@
         assertEquals(-3, mDefaultRadioGroup.getCheckedRadioButtonId());
     }
 
+    @UiThreadTest
     public void testClearCheck() {
         MockOnCheckedChangeListener listener = new MockOnCheckedChangeListener();
         mDefaultRadioGroup.setOnCheckedChangeListener(listener);
@@ -194,6 +198,7 @@
         assertOnCheckedChangedParams(listener, 0, mDefaultRadioGroup, -1);
     }
 
+    @UiThreadTest
     public void testCheck() {
         MockOnCheckedChangeListener listener = new MockOnCheckedChangeListener();
         mDefaultRadioGroup.setOnCheckedChangeListener(listener);
@@ -238,6 +243,7 @@
         mDefaultRadioGroup.check(0);
     }
 
+    @UiThreadTest
     public void testSetOnCheckedChangeListener() {
         MockOnCheckedChangeListener listener = new MockOnCheckedChangeListener();
         mDefaultRadioGroup.setOnCheckedChangeListener(listener);
@@ -333,6 +339,7 @@
         assertEquals(RadioGroup.LayoutParams.WRAP_CONTENT, p.height);
     }
 
+    @UiThreadTest
     public void testOnFinishInflate() {
         MockRadioGroup radioGroup = new MockRadioGroup(mContext);
         int checkId = 100;
@@ -371,6 +378,7 @@
         assertFalse(button.isChecked());
     }
 
+    @UiThreadTest
     public void testAddView() {
         mDefaultRadioGroup.check(BUTTON_ID_0);
         assertEquals(BUTTON_ID_0, mDefaultRadioGroup.getCheckedRadioButtonId());
diff --git a/tests/tests/widget/src/android/widget/cts/RadioGroup_LayoutParamsTest.java b/tests/tests/widget/src/android/widget/cts/RadioGroup_LayoutParamsTest.java
index 23155c7..4b1aa5b 100644
--- a/tests/tests/widget/src/android/widget/cts/RadioGroup_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RadioGroup_LayoutParamsTest.java
@@ -113,8 +113,8 @@
         } catch (NullPointerException e) {
         }
 
-        mLayoutParams = new LayoutParams(getContext(), 
-                getAttributeSet(com.android.cts.stub.R.layout.radiogroup_1));
+        mLayoutParams = new LayoutParams(getContext(),
+                getAttributeSet(com.android.cts.widget.R.layout.radiogroup_1));
         assertNotNull(mLayoutParams);
         assertEquals(0.5, mLayoutParams.weight, 0);
         assertEquals(Gravity.BOTTOM, mLayoutParams.gravity);
@@ -130,8 +130,8 @@
         assertEquals(RadioGroup.LayoutParams.WRAP_CONTENT, mLayoutParams.height);
 
         try {
-            new RadioGroup.LayoutParams(null, 
-                    getAttributeSet(com.android.cts.stub.R.layout.radiogroup_1));
+            new RadioGroup.LayoutParams(null,
+                    getAttributeSet(com.android.cts.widget.R.layout.radiogroup_1));
             fail("The constructor should throw NullPointerException when param Context is null.");
         } catch (NullPointerException e) {
         }
@@ -143,7 +143,7 @@
         assertEquals(LayoutParams.WRAP_CONTENT, layoutParams.width);
         assertEquals(LayoutParams.WRAP_CONTENT, layoutParams.height);
 
-        AttributeSet attrs = getAttributeSet(com.android.cts.stub.R.layout.radiogroup_1);
+        AttributeSet attrs = getAttributeSet(com.android.cts.widget.R.layout.radiogroup_1);
         TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.ViewGroup_MarginLayout);
         layoutParams.setBaseAttributes(a,
                 R.styleable.ViewGroup_MarginLayout_layout_width,
diff --git a/tests/tests/widget/src/android/widget/cts/RatingBarCtsActivity.java b/tests/tests/widget/src/android/widget/cts/RatingBarCtsActivity.java
new file mode 100644
index 0000000..7d4e232
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/RatingBarCtsActivity.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2008 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.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.cts.widget.R;
+
+/**
+ * An application for ProgressBar test
+ *
+ */
+public class RatingBarCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.ratingbar_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/RatingBarTest.java b/tests/tests/widget/src/android/widget/cts/RatingBarTest.java
index fe0e647..1bb42e8 100644
--- a/tests/tests/widget/src/android/widget/cts/RatingBarTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RatingBarTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import android.content.Context;
@@ -28,12 +28,12 @@
 /**
  * Test {@link RatingBar}.
  */
-public class RatingBarTest extends ActivityInstrumentationTestCase2<RatingBarStubActivity> {
+public class RatingBarTest extends ActivityInstrumentationTestCase2<RatingBarCtsActivity> {
     private Context mContext;
-    private RatingBarStubActivity mActivity;
+    private RatingBarCtsActivity mActivity;
 
     public RatingBarTest() {
-        super("com.android.cts.stub", RatingBarStubActivity.class);
+        super("com.android.cts.widget", RatingBarCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/widget/src/android/widget/cts/RelativeLayoutCtsActivity.java b/tests/tests/widget/src/android/widget/cts/RelativeLayoutCtsActivity.java
new file mode 100644
index 0000000..df83f54
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/RelativeLayoutCtsActivity.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2008 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.widget.cts;
+
+import com.android.cts.widget.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * A minimal application for RelativeLayout test.
+ */
+public class RelativeLayoutCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.relative_layout);
+    }
+}
+
diff --git a/tests/tests/widget/src/android/widget/cts/RelativeLayoutTest.java b/tests/tests/widget/src/android/widget/cts/RelativeLayoutTest.java
index 9d15160..b5ce5c9 100644
--- a/tests/tests/widget/src/android/widget/cts/RelativeLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RelativeLayoutTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 import com.android.internal.util.XmlUtils;
 
 
@@ -43,11 +43,11 @@
  * Test {@link RelativeLayout}.
  */
 public class RelativeLayoutTest extends
-        ActivityInstrumentationTestCase2<RelativeLayoutStubActivity> {
+        ActivityInstrumentationTestCase2<RelativeLayoutCtsActivity> {
     private Activity mActivity;
 
     public RelativeLayoutTest() {
-        super("com.android.cts.stub", RelativeLayoutStubActivity.class);
+        super("com.android.cts.widget", RelativeLayoutCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/widget/src/android/widget/cts/RelativeLayout_LayoutParamsTest.java b/tests/tests/widget/src/android/widget/cts/RelativeLayout_LayoutParamsTest.java
index 04682cb..a3bd95c 100644
--- a/tests/tests/widget/src/android/widget/cts/RelativeLayout_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RelativeLayout_LayoutParamsTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import android.test.ActivityInstrumentationTestCase2;
@@ -29,10 +29,10 @@
  * Test {@link RelativeLayout.LayoutParams}.
  */
 public class RelativeLayout_LayoutParamsTest extends
-        ActivityInstrumentationTestCase2<RelativeLayoutStubActivity> {
+        ActivityInstrumentationTestCase2<RelativeLayoutCtsActivity> {
 
     public RelativeLayout_LayoutParamsTest() {
-        super("com.android.cts.stub", RelativeLayoutStubActivity.class);
+        super("com.android.cts.widget", RelativeLayoutCtsActivity.class);
     }
 
     public void testConstructor() {
@@ -53,7 +53,7 @@
 
         // Test RelativeLayout.Params which generated from the xml file.
         int rules[];
-        RelativeLayoutStubActivity activity = getActivity();
+        RelativeLayoutCtsActivity activity = getActivity();
 
         // test attributes used in RelativeLayout.
         RelativeLayout relativeLayout = (RelativeLayout) activity.findViewById(
@@ -160,7 +160,7 @@
 
         // Test RelativeLayout.Params which generated from the xml file.
         int rules[];
-        RelativeLayoutStubActivity activity = getActivity();
+        RelativeLayoutCtsActivity activity = getActivity();
 
         // test attributes used in RelativeLayout.
         RelativeLayout relativeLayout = (RelativeLayout) activity.findViewById(
diff --git a/tests/tests/widget/src/android/widget/cts/RemoteViewsActivityTest.java b/tests/tests/widget/src/android/widget/cts/RemoteViewsActivityTest.java
index b3c0915..ab109b1 100644
--- a/tests/tests/widget/src/android/widget/cts/RemoteViewsActivityTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RemoteViewsActivityTest.java
@@ -17,24 +17,24 @@
 package android.widget.cts;
 
 import android.app.Activity;
+import android.cts.util.NullWebViewUtils;
 import android.os.Parcel;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.MediumTest;
 import android.view.InflateException;
 import android.view.View;
 import android.view.ViewGroup;
-import android.webkit.cts.NullWebViewUtils;
 import android.widget.RemoteViews;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 public class RemoteViewsActivityTest
-        extends ActivityInstrumentationTestCase2<RemoteViewsStubActivity> {
-    private static final String PACKAGE_NAME = "com.android.cts.stub";
+        extends ActivityInstrumentationTestCase2<RemoteViewsCtsActivity> {
+    private static final String PACKAGE_NAME = "com.android.cts.widget";
     private Activity mActivity;
 
     public RemoteViewsActivityTest() {
-        super(PACKAGE_NAME, RemoteViewsStubActivity.class);
+        super(PACKAGE_NAME, RemoteViewsCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/widget/src/android/widget/cts/RemoteViewsCtsActivity.java b/tests/tests/widget/src/android/widget/cts/RemoteViewsCtsActivity.java
new file mode 100644
index 0000000..4da5aa2
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/RemoteViewsCtsActivity.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2008 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.widget.cts;
+
+import com.android.cts.widget.R;
+
+import android.app.Activity;
+import android.cts.util.NullWebViewUtils;
+import android.os.Bundle;
+import android.widget.RemoteViews;
+
+/**
+ * Stub activity for testing {@link RemoteViews}
+ */
+public class RemoteViewsCtsActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        try {
+            super.onCreate(savedInstanceState);
+            setContentView(R.layout.remoteviews_host);
+        } catch (Exception e) {
+            NullWebViewUtils.determineIfWebViewAvailable(this, e);
+        }
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/RemoteViewsTest.java b/tests/tests/widget/src/android/widget/cts/RemoteViewsTest.java
index 891bdf7..328f9f3 100644
--- a/tests/tests/widget/src/android/widget/cts/RemoteViewsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RemoteViewsTest.java
@@ -16,7 +16,8 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import android.test.UiThreadTest;
+import com.android.cts.widget.R;
 
 
 import android.app.Activity;
@@ -25,13 +26,13 @@
 import android.app.Instrumentation.ActivityMonitor;
 import android.content.Intent;
 import android.content.res.ColorStateList;
+import android.cts.util.WidgetTestUtils;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.drawable.BitmapDrawable;
 import android.net.Uri;
 import android.os.Parcel;
 import android.test.ActivityInstrumentationTestCase2;
-import android.text.style.cts.MockURLSpanTestActivity;
 import android.view.View;
 import android.widget.AbsoluteLayout;
 import android.widget.Chronometer;
@@ -56,8 +57,8 @@
 /**
  * Test {@link RemoteViews}.
  */
-public class RemoteViewsTest extends ActivityInstrumentationTestCase2<RemoteViewsStubActivity> {
-    private static final String PACKAGE_NAME = "com.android.cts.stub";
+public class RemoteViewsTest extends ActivityInstrumentationTestCase2<RemoteViewsCtsActivity> {
+    private static final String PACKAGE_NAME = "com.android.cts.widget";
 
     private static final int INVALD_ID = -1;
 
@@ -70,15 +71,20 @@
     private Activity mActivity;
 
     public RemoteViewsTest() {
-        super(PACKAGE_NAME, RemoteViewsStubActivity.class);
+        super(PACKAGE_NAME, RemoteViewsCtsActivity.class);
     }
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
         mActivity = getActivity();
-        mRemoteViews = new RemoteViews(PACKAGE_NAME, R.layout.remoteviews_good);
-        mResult = mRemoteViews.apply(mActivity, null);
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                mRemoteViews = new RemoteViews(PACKAGE_NAME, R.layout.remoteviews_good);
+                mResult = mRemoteViews.apply(mActivity, null);
+            }
+        });
     }
 
     public void testConstructor() {
@@ -308,6 +314,7 @@
         mRemoteViews.describeContents();
     }
 
+    @UiThreadTest
     public void testWriteToParcel() {
         mRemoteViews.setTextViewText(R.id.remoteView_text, "This is content");
         mRemoteViews.setViewVisibility(R.id.remoteView_frame, View.GONE);
diff --git a/tests/tests/widget/src/android/widget/cts/ResourceCursorAdapterTest.java b/tests/tests/widget/src/android/widget/cts/ResourceCursorAdapterTest.java
index d91094c..28bfd06 100644
--- a/tests/tests/widget/src/android/widget/cts/ResourceCursorAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ResourceCursorAdapterTest.java
@@ -16,13 +16,14 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import android.content.Context;
 import android.database.Cursor;
 import android.database.MatrixCursor;
 import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -51,6 +52,7 @@
         mCursor = createTestCursor(3, 3);
     }
 
+    @UiThreadTest
     public void testConstructor() {
         MockResourceCursorAdapter adapter = new MockResourceCursorAdapter(mContext, -1, null);
         // the default is true
@@ -68,6 +70,7 @@
         assertSame(mCursor, adapter.getCursor());
     }
 
+    @UiThreadTest
     public void testSetViewResource() {
         mResourceCursorAdapter = new MockResourceCursorAdapter(mContext,
                 R.layout.cursoradapter_item0, mCursor);
@@ -83,6 +86,7 @@
         assertEquals(R.id.cursorAdapter_item1, result.getId());
     }
 
+    @UiThreadTest
     public void testSetDropDownViewResource() {
         mResourceCursorAdapter = new MockResourceCursorAdapter(mContext,
                 R.layout.cursoradapter_item0, mCursor);
@@ -107,6 +111,7 @@
     }
 
     // parameters Context and Cursor are never readin the method
+    @UiThreadTest
     public void testNewDropDownView() {
         mResourceCursorAdapter = new MockResourceCursorAdapter(mContext,
                 R.layout.cursoradapter_item0, mCursor);
@@ -122,6 +127,7 @@
     }
 
     // The parameters Context and Cursor are never read in the method
+    @UiThreadTest
     public void testNewView() {
         mResourceCursorAdapter = new MockResourceCursorAdapter(mContext,
                 R.layout.cursoradapter_item0, mCursor);
diff --git a/tests/tests/widget/src/android/widget/cts/ResourceCursorTreeAdapterTest.java b/tests/tests/widget/src/android/widget/cts/ResourceCursorTreeAdapterTest.java
index 4a5a9c9..760f7e4 100644
--- a/tests/tests/widget/src/android/widget/cts/ResourceCursorTreeAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ResourceCursorTreeAdapterTest.java
@@ -16,13 +16,14 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import android.content.Context;
 import android.database.Cursor;
 import android.database.MatrixCursor;
 import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -71,6 +72,7 @@
         mParent = (ViewGroup) layoutInflater.inflate(R.layout.cursoradapter_host, null);
     }
 
+    @UiThreadTest
     public void testConstructor() {
         mResourceCursorTreeAdapter = new MockResourceCursorTreeAdapter(mContext, null,
                 mGroupLayout, mChildLayout);
@@ -95,6 +97,7 @@
     }
 
     // The parameters Context and Cursor are never readin the method
+    @UiThreadTest
     public void testNewChildView() {
         mResourceCursorTreeAdapter = new MockResourceCursorTreeAdapter(mContext, null,
                 mGroupLayout, mChildLayout);
@@ -116,6 +119,7 @@
     }
 
     // The parameters Context and Cursor are never readin the method
+    @UiThreadTest
     public void testNewGroupView() {
         mResourceCursorTreeAdapter = new MockResourceCursorTreeAdapter(mContext, null,
                 mGroupLayout, mChildLayout);
diff --git a/tests/tests/widget/src/android/widget/cts/ScrollViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ScrollViewCtsActivity.java
new file mode 100644
index 0000000..8965610
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ScrollViewCtsActivity.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2009 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.widget.cts;
+
+import com.android.cts.widget.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class ScrollViewCtsActivity extends Activity {
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.scrollview_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/ScrollViewTest.java b/tests/tests/widget/src/android/widget/cts/ScrollViewTest.java
index e297744..a8fb224 100644
--- a/tests/tests/widget/src/android/widget/cts/ScrollViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ScrollViewTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import org.xmlpull.v1.XmlPullParser;
@@ -41,7 +41,7 @@
 /**
  * Test {@link ScrollView}.
  */
-public class ScrollViewTest extends ActivityInstrumentationTestCase2<ScrollViewStubActivity> {
+public class ScrollViewTest extends ActivityInstrumentationTestCase2<ScrollViewCtsActivity> {
     // view dpi constants. Must match those defined in scroll_view layout
     private static final int ITEM_WIDTH_DPI  = 250;
     private static final int ITEM_HEIGHT_DPI = 100;
@@ -61,7 +61,7 @@
     private Activity mActivity;
 
     public ScrollViewTest() {
-        super("com.android.cts.stub", ScrollViewStubActivity.class);
+        super("com.android.cts.widget", ScrollViewCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/widget/src/android/widget/cts/SeekBarCtsActivity.java b/tests/tests/widget/src/android/widget/cts/SeekBarCtsActivity.java
new file mode 100644
index 0000000..e7842c2
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/SeekBarCtsActivity.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2008 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.widget.cts;
+
+import com.android.cts.widget.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.SeekBar;
+
+/**
+ * Stub activity for testing {@link SeekBar}
+ */
+public class SeekBarCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.seekbar_layout);
+
+        View v = findViewById(R.id.seekBar);
+        v.setEnabled(true);
+        v.setFocusable(true);
+        v.setFocusableInTouchMode(true);
+        v.requestFocus();
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/SeekBarTest.java b/tests/tests/widget/src/android/widget/cts/SeekBarTest.java
index 266583f..54bbedf 100644
--- a/tests/tests/widget/src/android/widget/cts/SeekBarTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SeekBarTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import android.app.Activity;
@@ -30,7 +30,7 @@
 /**
  * Test {@link SeekBar}.
  */
-public class SeekBarTest extends ActivityInstrumentationTestCase2<SeekBarStubActivity> {
+public class SeekBarTest extends ActivityInstrumentationTestCase2<SeekBarCtsActivity> {
     private SeekBar mSeekBar;
 
     private Activity mActivity;
@@ -38,7 +38,7 @@
     private Instrumentation mInstrumentation;
 
     public SeekBarTest() {
-        super("com.android.cts.stub", SeekBarStubActivity.class);
+        super("com.android.cts.widget", SeekBarCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/widget/src/android/widget/cts/SimpleAdapterTest.java b/tests/tests/widget/src/android/widget/cts/SimpleAdapterTest.java
index 8b35a2f..c530293 100644
--- a/tests/tests/widget/src/android/widget/cts/SimpleAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SimpleAdapterTest.java
@@ -20,9 +20,11 @@
 
 
 import android.content.Context;
+import android.cts.util.WidgetTestUtils;
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.ImageView;
@@ -89,7 +91,7 @@
         mContext = getInstrumentation().getTargetContext();
         mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         mAdapterHost = (LinearLayout) mInflater.inflate(
-                com.android.cts.stub.R.layout.cursoradapter_host, null);
+                com.android.cts.widget.R.layout.cursoradapter_host, null);
 
         // new the SimpleAdapter instance
         mSimpleAdapter = new SimpleAdapter(mContext,
@@ -280,9 +282,9 @@
         // String represents resId
         ImageView view = new ImageView(mContext);
         assertNull(view.getDrawable());
-        mSimpleAdapter.setViewImage(view, String.valueOf(com.android.cts.stub.R.drawable.scenery));
+        mSimpleAdapter.setViewImage(view, String.valueOf(com.android.cts.widget.R.drawable.scenery));
         BitmapDrawable d = (BitmapDrawable) mContext.getResources().getDrawable(
-                com.android.cts.stub.R.drawable.scenery);
+                com.android.cts.widget.R.drawable.scenery);
         WidgetTestUtils.assertEquals(d.getBitmap(),
                 ((BitmapDrawable) view.getDrawable()).getBitmap());
 
@@ -305,9 +307,9 @@
         // resId
         view = new ImageView(mContext);
         assertNull(view.getDrawable());
-        mSimpleAdapter.setViewImage(view, com.android.cts.stub.R.drawable.scenery);
+        mSimpleAdapter.setViewImage(view, com.android.cts.widget.R.drawable.scenery);
         d = (BitmapDrawable) mContext.getResources()
-                .getDrawable(com.android.cts.stub.R.drawable.scenery);
+                .getDrawable(com.android.cts.widget.R.drawable.scenery);
         WidgetTestUtils.assertEquals(d.getBitmap(),
                 ((BitmapDrawable) view.getDrawable()).getBitmap());
 
@@ -322,11 +324,11 @@
         assertNull(view.getDrawable());
         try {
             mSimpleAdapter.setViewImage(view, SimpleCursorAdapterTest.createTestImage(mContext,
-                    "testimage", com.android.cts.stub.R.raw.testimage));
+                    "testimage", com.android.cts.widget.R.raw.testimage));
             assertNotNull(view.getDrawable());
             Bitmap actualBitmap = ((BitmapDrawable) view.getDrawable()).getBitmap();
             Bitmap testBitmap = WidgetTestUtils.getUnscaledAndDitheredBitmap(mContext.getResources(),
-                    com.android.cts.stub.R.raw.testimage, actualBitmap.getConfig());
+                    com.android.cts.widget.R.raw.testimage, actualBitmap.getConfig());
             WidgetTestUtils.assertEquals(testBitmap, actualBitmap);
         } finally {
             SimpleCursorAdapterTest.destroyTestImage(mContext,"testimage");
@@ -342,6 +344,7 @@
         assertEquals("", view.getText().toString());
     }
 
+    @UiThreadTest
     public void testGetFilter() {
         assertNotNull(mSimpleAdapter.getFilter());
     }
diff --git a/tests/tests/widget/src/android/widget/cts/SimpleCursorAdapterTest.java b/tests/tests/widget/src/android/widget/cts/SimpleCursorAdapterTest.java
index 59660e0..13184de 100644
--- a/tests/tests/widget/src/android/widget/cts/SimpleCursorAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SimpleCursorAdapterTest.java
@@ -16,15 +16,17 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import android.content.Context;
+import android.cts.util.WidgetTestUtils;
 import android.database.Cursor;
 import android.database.MatrixCursor;
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -41,6 +43,9 @@
 
 /**
  * Test {@link SimpleCursorAdapter}.
+ * The simple cursor adapter's cursor will be set to
+ * {@link SimpleCursorAdapterTest#mCursor} It will use internal
+ * R.layout.simple_list_item_1.
  */
 public class SimpleCursorAdapterTest extends InstrumentationTestCase {
     private static final int ADAPTER_ROW_COUNT = 20;
@@ -53,13 +58,6 @@
 
     private static final String SAMPLE_IMAGE_NAME = "testimage.jpg";
 
-    /**
-     * The simple cursor adapter. Its cursor will be set to
-     * {@link SimpleCursorAdapterTest#mCursor} It will use internal
-     * R.layout.simple_list_item_1.
-     */
-    private SimpleCursorAdapter mSimpleCursorAdapter;
-
     private Context mContext;
 
     /**
@@ -96,89 +94,101 @@
         mContext = getInstrumentation().getTargetContext();
 
         mCursor = createTestCursor(DEFAULT_COLUMN_COUNT, ADAPTER_ROW_COUNT);
-        mSimpleCursorAdapter = new SimpleCursorAdapter(mContext, R.layout.cursoradapter_item0,
-                mCursor, COLUMNS_FROM, VIEWS_TO);
     }
 
+    private SimpleCursorAdapter makeSimpleCursorAdapter() {
+        return new SimpleCursorAdapter(
+                mContext, R.layout.cursoradapter_item0, mCursor, COLUMNS_FROM, VIEWS_TO);
+    }
+
+    @UiThreadTest
     public void testConstructor() {
         new SimpleCursorAdapter(mContext, R.layout.cursoradapter_item0,
                 createTestCursor(DEFAULT_COLUMN_COUNT, ADAPTER_ROW_COUNT),
                 COLUMNS_FROM, VIEWS_TO);
     }
 
+    @UiThreadTest
     public void testBindView() {
-        TextView listItem = (TextView) mSimpleCursorAdapter.newView(mContext, null, null);
+        SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
+        TextView listItem = (TextView) simpleCursorAdapter.newView(mContext, null, null);
 
         listItem.setText("");
         mCursor.moveToFirst();
-        mSimpleCursorAdapter.bindView(listItem, null, mCursor);
+        simpleCursorAdapter.bindView(listItem, null, mCursor);
         assertEquals("01", listItem.getText().toString());
 
         mCursor.moveToLast();
-        mSimpleCursorAdapter.bindView(listItem, null, mCursor);
+        simpleCursorAdapter.bindView(listItem, null, mCursor);
         assertEquals("191", listItem.getText().toString());
 
         // the binder take care of binding
         listItem.setText("");
         MockViewBinder binder = new MockViewBinder(true);
-        mSimpleCursorAdapter.setViewBinder(binder);
+        simpleCursorAdapter.setViewBinder(binder);
         binder.reset();
         mCursor.moveToFirst();
-        mSimpleCursorAdapter.bindView(listItem, null, mCursor);
+        simpleCursorAdapter.bindView(listItem, null, mCursor);
         assertTrue(binder.hasCalledSetViewValueCalledCount());
         assertEquals("", listItem.getText().toString());
 
         // the binder try to bind but fail
         binder = new MockViewBinder(false);
-        mSimpleCursorAdapter.setViewBinder(binder);
+        simpleCursorAdapter.setViewBinder(binder);
         mCursor.moveToLast();
-        mSimpleCursorAdapter.bindView(listItem, null, mCursor);
+        simpleCursorAdapter.bindView(listItem, null, mCursor);
         assertTrue(binder.hasCalledSetViewValueCalledCount());
         assertEquals("191", listItem.getText().toString());
 
         final int [] to = { R.id.cursorAdapter_host };
-        mSimpleCursorAdapter = new SimpleCursorAdapter(mContext, R.layout.cursoradapter_host,
+        simpleCursorAdapter = new SimpleCursorAdapter(mContext, R.layout.cursoradapter_host,
                 mCursor, COLUMNS_FROM, to);
-        LinearLayout illegalView = (LinearLayout)mSimpleCursorAdapter.newView(mContext, null, null);
+        LinearLayout illegalView = (LinearLayout)simpleCursorAdapter.newView(mContext, null, null);
         try {
             // The IllegalStateException already gets thrown in the line above.
-            mSimpleCursorAdapter.bindView(illegalView, null, mCursor);
+            simpleCursorAdapter.bindView(illegalView, null, mCursor);
             fail("Should throw IllegalStateException if the view is not TextView or ImageView");
         } catch (IllegalStateException e) {
             // expected
         }
     }
 
+    @UiThreadTest
     public void testAccessViewBinder() {
-        assertNull(mSimpleCursorAdapter.getViewBinder());
+        SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
+        assertNull(simpleCursorAdapter.getViewBinder());
 
         MockViewBinder binder = new MockViewBinder(true);
-        mSimpleCursorAdapter.setViewBinder(binder);
-        assertSame(binder, mSimpleCursorAdapter.getViewBinder());
+        simpleCursorAdapter.setViewBinder(binder);
+        assertSame(binder, simpleCursorAdapter.getViewBinder());
 
         binder = new MockViewBinder(false);
-        mSimpleCursorAdapter.setViewBinder(binder);
-        assertSame(binder, mSimpleCursorAdapter.getViewBinder());
+        simpleCursorAdapter.setViewBinder(binder);
+        assertSame(binder, simpleCursorAdapter.getViewBinder());
 
-        mSimpleCursorAdapter.setViewBinder(null);
-        assertNull(mSimpleCursorAdapter.getViewBinder());
+        simpleCursorAdapter.setViewBinder(null);
+        assertNull(simpleCursorAdapter.getViewBinder());
     }
 
+    @UiThreadTest
     public void testSetViewText() {
+        SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
         TextView view = new TextView(mContext);
-        mSimpleCursorAdapter.setViewText(view, "expected");
+        simpleCursorAdapter.setViewText(view, "expected");
         assertEquals("expected", view.getText().toString());
 
-        mSimpleCursorAdapter.setViewText(view, null);
+        simpleCursorAdapter.setViewText(view, null);
         assertEquals("", view.getText().toString());
     }
 
+    @UiThreadTest
     public void testSetViewImage() {
+        SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
         // resId
-        int sceneryImgResId = com.android.cts.stub.R.drawable.scenery;
+        int sceneryImgResId = com.android.cts.widget.R.drawable.scenery;
         ImageView view = new ImageView(mContext);
         assertNull(view.getDrawable());
-        mSimpleCursorAdapter.setViewImage(view, String.valueOf(sceneryImgResId));
+        simpleCursorAdapter.setViewImage(view, String.valueOf(sceneryImgResId));
         assertNotNull(view.getDrawable());
         BitmapDrawable d = (BitmapDrawable) mContext.getResources().getDrawable(
                 sceneryImgResId);
@@ -188,7 +198,7 @@
         // blank
         view = new ImageView(mContext);
         assertNull(view.getDrawable());
-        mSimpleCursorAdapter.setViewImage(view, "");
+        simpleCursorAdapter.setViewImage(view, "");
         assertNull(view.getDrawable());
 
         // null
@@ -196,7 +206,7 @@
         assertNull(view.getDrawable());
         try {
             // Should declare NullPoinertException if the uri or value is null
-            mSimpleCursorAdapter.setViewImage(view, null);
+            simpleCursorAdapter.setViewImage(view, null);
             fail("Should throw NullPointerException if the uri or value is null");
         } catch (NullPointerException e) {
             // expected
@@ -206,8 +216,8 @@
         view = new ImageView(mContext);
         assertNull(view.getDrawable());
         try {
-            int testimgRawId = com.android.cts.stub.R.raw.testimage;
-            mSimpleCursorAdapter.setViewImage(view,
+            int testimgRawId = com.android.cts.widget.R.raw.testimage;
+            simpleCursorAdapter.setViewImage(view,
                     createTestImage(mContext, SAMPLE_IMAGE_NAME, testimgRawId));
             assertNotNull(view.getDrawable());
             Bitmap actualBitmap = ((BitmapDrawable) view.getDrawable()).getBitmap();
@@ -219,44 +229,50 @@
         }
     }
 
+    @UiThreadTest
     public void testAccessStringConversionColumn() {
+        SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
         // default is -1
-        assertEquals(-1, mSimpleCursorAdapter.getStringConversionColumn());
+        assertEquals(-1, simpleCursorAdapter.getStringConversionColumn());
 
-        mSimpleCursorAdapter.setStringConversionColumn(1);
-        assertEquals(1, mSimpleCursorAdapter.getStringConversionColumn());
+        simpleCursorAdapter.setStringConversionColumn(1);
+        assertEquals(1, simpleCursorAdapter.getStringConversionColumn());
 
         // Should check whether the column index is out of bounds
-        mSimpleCursorAdapter.setStringConversionColumn(Integer.MAX_VALUE);
-        assertEquals(Integer.MAX_VALUE, mSimpleCursorAdapter.getStringConversionColumn());
+        simpleCursorAdapter.setStringConversionColumn(Integer.MAX_VALUE);
+        assertEquals(Integer.MAX_VALUE, simpleCursorAdapter.getStringConversionColumn());
 
         // Should check whether the column index is out of bounds
-        mSimpleCursorAdapter.setStringConversionColumn(Integer.MIN_VALUE);
-        assertEquals(Integer.MIN_VALUE, mSimpleCursorAdapter.getStringConversionColumn());
+        simpleCursorAdapter.setStringConversionColumn(Integer.MIN_VALUE);
+        assertEquals(Integer.MIN_VALUE, simpleCursorAdapter.getStringConversionColumn());
     }
 
+    @UiThreadTest
     public void testAccessCursorToStringConverter() {
+        SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
         // default is null
-        assertNull(mSimpleCursorAdapter.getCursorToStringConverter());
+        assertNull(simpleCursorAdapter.getCursorToStringConverter());
 
         CursorToStringConverter converter = new MockCursorToStringConverter();
-        mSimpleCursorAdapter.setCursorToStringConverter(converter);
-        assertSame(converter, mSimpleCursorAdapter.getCursorToStringConverter());
+        simpleCursorAdapter.setCursorToStringConverter(converter);
+        assertSame(converter, simpleCursorAdapter.getCursorToStringConverter());
 
-        mSimpleCursorAdapter.setCursorToStringConverter(null);
-        assertNull(mSimpleCursorAdapter.getCursorToStringConverter());
+        simpleCursorAdapter.setCursorToStringConverter(null);
+        assertNull(simpleCursorAdapter.getCursorToStringConverter());
     }
 
+    @UiThreadTest
     public void testChangeCursor() {
+        SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
         // have "column1"
         Cursor curWith3Columns = createTestCursor(3, ADAPTER_ROW_COUNT);
-        mSimpleCursorAdapter.changeCursor(curWith3Columns);
-        assertSame(curWith3Columns, mSimpleCursorAdapter.getCursor());
+        simpleCursorAdapter.changeCursor(curWith3Columns);
+        assertSame(curWith3Columns, simpleCursorAdapter.getCursor());
 
         // does not have "column1"
         Cursor curWith1Column = createTestCursor(1, ADAPTER_ROW_COUNT);
         try {
-            mSimpleCursorAdapter.changeCursor(curWith1Column);
+            simpleCursorAdapter.changeCursor(curWith1Column);
             fail("Should throw exception if the cursor does not have the "
                     + "original column passed in the constructor");
         } catch (IllegalArgumentException e) {
@@ -264,23 +280,25 @@
         }
     }
 
+    @UiThreadTest
     public void testConvertToString() {
+        SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
         mCursor.moveToFirst();
-        assertEquals("", mSimpleCursorAdapter.convertToString(null));
+        assertEquals("", simpleCursorAdapter.convertToString(null));
 
         // converter is null, StringConversionColumn is set to negative
-        mSimpleCursorAdapter.setStringConversionColumn(Integer.MIN_VALUE);
-        assertEquals(mCursor.toString(), mSimpleCursorAdapter.convertToString(mCursor));
+        simpleCursorAdapter.setStringConversionColumn(Integer.MIN_VALUE);
+        assertEquals(mCursor.toString(), simpleCursorAdapter.convertToString(mCursor));
 
         // converter is null, StringConversionColumn is set to 1
-        mSimpleCursorAdapter.setStringConversionColumn(1);
-        assertEquals("01", mSimpleCursorAdapter.convertToString(mCursor));
+        simpleCursorAdapter.setStringConversionColumn(1);
+        assertEquals("01", simpleCursorAdapter.convertToString(mCursor));
 
         // converter is null, StringConversionColumn is set to 3 (larger than columns count)
         // the cursor has 3 columns including column0, column1 and _id which is added automatically
-        mSimpleCursorAdapter.setStringConversionColumn(DEFAULT_COLUMN_COUNT + 1);
+        simpleCursorAdapter.setStringConversionColumn(DEFAULT_COLUMN_COUNT + 1);
         try {
-            mSimpleCursorAdapter.convertToString(mCursor);
+            simpleCursorAdapter.convertToString(mCursor);
             fail("Should throw IndexOutOfBoundsException if index is beyond the columns count");
         } catch (IndexOutOfBoundsException e) {
             // expected
@@ -291,69 +309,75 @@
 
         // converter is null, StringConversionColumn is set to 3
         // and covert with a cursor which has 4 columns
-        mSimpleCursorAdapter.setStringConversionColumn(2);
-        assertEquals("02", mSimpleCursorAdapter.convertToString(curWith3Columns));
+        simpleCursorAdapter.setStringConversionColumn(2);
+        assertEquals("02", simpleCursorAdapter.convertToString(curWith3Columns));
 
         // converter is not null, StringConversionColumn is 1
         CursorToStringConverter converter = new MockCursorToStringConverter();
-        mSimpleCursorAdapter.setCursorToStringConverter(converter);
-        mSimpleCursorAdapter.setStringConversionColumn(1);
+        simpleCursorAdapter.setCursorToStringConverter(converter);
+        simpleCursorAdapter.setStringConversionColumn(1);
         ((MockCursorToStringConverter) converter).reset();
-        mSimpleCursorAdapter.convertToString(curWith3Columns);
+        simpleCursorAdapter.convertToString(curWith3Columns);
         assertTrue(((MockCursorToStringConverter) converter).hasCalledConvertToString());
     }
 
+    @UiThreadTest
     public void testNewView() {
+        SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
         LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(
                 Context.LAYOUT_INFLATER_SERVICE);
         ViewGroup viewGroup = (ViewGroup) layoutInflater.inflate(
-                com.android.cts.stub.R.layout.cursoradapter_host, null);
-        View result = mSimpleCursorAdapter.newView(mContext, null, viewGroup);
+                com.android.cts.widget.R.layout.cursoradapter_host, null);
+        View result = simpleCursorAdapter.newView(mContext, null, viewGroup);
         assertNotNull(result);
         assertEquals(R.id.cursorAdapter_item0, result.getId());
 
-        result = mSimpleCursorAdapter.newView(mContext, null, null);
+        result = simpleCursorAdapter.newView(mContext, null, null);
         assertNotNull(result);
         assertEquals(R.id.cursorAdapter_item0, result.getId());
     }
 
+    @UiThreadTest
     public void testNewDropDownView() {
+        SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
         LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(
                 Context.LAYOUT_INFLATER_SERVICE);
         ViewGroup viewGroup = (ViewGroup) layoutInflater.inflate(
-                com.android.cts.stub.R.layout.cursoradapter_host, null);
-        View result = mSimpleCursorAdapter.newDropDownView(null, null, viewGroup);
+                com.android.cts.widget.R.layout.cursoradapter_host, null);
+        View result = simpleCursorAdapter.newDropDownView(null, null, viewGroup);
         assertNotNull(result);
         assertEquals(R.id.cursorAdapter_item0, result.getId());
     }
 
+    @UiThreadTest
     public void testChangeCursorAndColumns() {
-        assertSame(mCursor, mSimpleCursorAdapter.getCursor());
+        SimpleCursorAdapter simpleCursorAdapter = makeSimpleCursorAdapter();
+        assertSame(mCursor, simpleCursorAdapter.getCursor());
 
-        TextView listItem = (TextView) mSimpleCursorAdapter.newView(mContext, null, null);
+        TextView listItem = (TextView) simpleCursorAdapter.newView(mContext, null, null);
 
         mCursor.moveToFirst();
-        mSimpleCursorAdapter.bindView(listItem, null, mCursor);
+        simpleCursorAdapter.bindView(listItem, null, mCursor);
         assertEquals("01", listItem.getText().toString());
 
         mCursor.moveToLast();
-        mSimpleCursorAdapter.bindView(listItem, null, mCursor);
+        simpleCursorAdapter.bindView(listItem, null, mCursor);
         assertEquals("191", listItem.getText().toString());
 
         Cursor newCursor = createTestCursor(3, ADAPTER_ROW_COUNT);
         final String[] from = new String[] { "column2" };
-        mSimpleCursorAdapter.changeCursorAndColumns(newCursor, from, VIEWS_TO);
-        assertSame(newCursor, mSimpleCursorAdapter.getCursor());
+        simpleCursorAdapter.changeCursorAndColumns(newCursor, from, VIEWS_TO);
+        assertSame(newCursor, simpleCursorAdapter.getCursor());
         newCursor.moveToFirst();
-        mSimpleCursorAdapter.bindView(listItem, null, newCursor);
+        simpleCursorAdapter.bindView(listItem, null, newCursor);
         assertEquals("02", listItem.getText().toString());
 
         newCursor.moveToLast();
-        mSimpleCursorAdapter.bindView(listItem, null, newCursor);
+        simpleCursorAdapter.bindView(listItem, null, newCursor);
         assertEquals("192", listItem.getText().toString());
 
-        mSimpleCursorAdapter.changeCursorAndColumns(null, null, null);
-        assertNull(mSimpleCursorAdapter.getCursor());
+        simpleCursorAdapter.changeCursorAndColumns(null, null, null);
+        assertNull(simpleCursorAdapter.getCursor());
     }
 
     /**
diff --git a/tests/tests/widget/src/android/widget/cts/SimpleCursorTreeAdapterTest.java b/tests/tests/widget/src/android/widget/cts/SimpleCursorTreeAdapterTest.java
index bf9e358..c9fdbc3 100644
--- a/tests/tests/widget/src/android/widget/cts/SimpleCursorTreeAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SimpleCursorTreeAdapterTest.java
@@ -16,15 +16,17 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import android.content.Context;
+import android.cts.util.WidgetTestUtils;
 import android.database.Cursor;
 import android.database.MatrixCursor;
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.SimpleCursorTreeAdapter;
@@ -70,6 +72,7 @@
         mContext = getInstrumentation().getTargetContext();
     }
 
+    @UiThreadTest
     public void testConstructor() {
         mGroupCursor = createTestCursor(2, 20, "group");
         new MockSimpleCursorTreeAdapter(mContext, mGroupCursor,
@@ -85,6 +88,7 @@
                 CHILD_LAYOUT, CHILD_LAYOUT, COLUMNS_CHILD_FROM, VIEWS_CHILD_TO);
     }
 
+    @UiThreadTest
     public void testBindChildView() {
         mGroupCursor = createTestCursor(2, 20, "group");
         mChildCursor = createTestCursor(3, 4, "child");
@@ -104,6 +108,7 @@
     }
 
     // The param context and isExpanded is never readed.
+    @UiThreadTest
     public void testBindGroupView() {
         mGroupCursor = createTestCursor(2, 20, "group");
         mGroupCursor.moveToFirst();
@@ -120,6 +125,7 @@
         assertEquals("group11", view.getText().toString());
     }
 
+    @UiThreadTest
     public void testSetViewImage() {
         mGroupCursor = createTestCursor(2, 20, "group");
         mSimpleCursorTreeAdapter = new MockSimpleCursorTreeAdapter(mContext, mGroupCursor,
@@ -130,9 +136,9 @@
         ImageView view = new ImageView(mContext);
         assertNull(view.getDrawable());
         mSimpleCursorTreeAdapter.setViewImage(view,
-                String.valueOf(com.android.cts.stub.R.drawable.scenery));
+                String.valueOf(com.android.cts.widget.R.drawable.scenery));
         BitmapDrawable d = (BitmapDrawable) mContext.getResources().getDrawable(
-                com.android.cts.stub.R.drawable.scenery);
+                com.android.cts.widget.R.drawable.scenery);
         WidgetTestUtils.assertEquals(d.getBitmap(),
                 ((BitmapDrawable) view.getDrawable()).getBitmap());
 
@@ -158,10 +164,10 @@
         try {
             mSimpleCursorTreeAdapter.setViewImage(view,
                     SimpleCursorAdapterTest.createTestImage(mContext, SAMPLE_IMAGE_NAME,
-                            com.android.cts.stub.R.raw.testimage));
+                            com.android.cts.widget.R.raw.testimage));
             Bitmap actualBitmap = ((BitmapDrawable) view.getDrawable()).getBitmap();
             Bitmap test = WidgetTestUtils.getUnscaledAndDitheredBitmap(mContext.getResources(),
-                    com.android.cts.stub.R.raw.testimage, actualBitmap.getConfig());
+                    com.android.cts.widget.R.raw.testimage, actualBitmap.getConfig());
             WidgetTestUtils.assertEquals(test, actualBitmap);
         } finally {
             SimpleCursorAdapterTest.destroyTestImage(mContext, SAMPLE_IMAGE_NAME);
diff --git a/tests/tests/widget/src/android/widget/cts/SimpleExpandableListAdapterTest.java b/tests/tests/widget/src/android/widget/cts/SimpleExpandableListAdapterTest.java
index 7c4fe23..a7bfc31 100644
--- a/tests/tests/widget/src/android/widget/cts/SimpleExpandableListAdapterTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SimpleExpandableListAdapterTest.java
@@ -98,7 +98,7 @@
 
         mAdapterHost = (LinearLayout) ((LayoutInflater) mContext
                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(
-                com.android.cts.stub.R.layout.cursoradapter_host, null);
+                com.android.cts.widget.R.layout.cursoradapter_host, null);
     }
 
     public void testConstructor() {
diff --git a/tests/tests/widget/src/android/widget/cts/SlidingDrawerCtsActivity.java b/tests/tests/widget/src/android/widget/cts/SlidingDrawerCtsActivity.java
new file mode 100644
index 0000000..8b55e63
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/SlidingDrawerCtsActivity.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2009 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.widget.cts;
+
+import com.android.cts.widget.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class SlidingDrawerCtsActivity extends Activity {
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.sliding_drawer_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/SlidingDrawerTest.java b/tests/tests/widget/src/android/widget/cts/SlidingDrawerTest.java
index 60666ae..862fccf 100644
--- a/tests/tests/widget/src/android/widget/cts/SlidingDrawerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SlidingDrawerTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import org.xmlpull.v1.XmlPullParser;
@@ -44,14 +44,14 @@
  * Test {@link SlidingDrawer}.
  */
 public class SlidingDrawerTest
-        extends ActivityInstrumentationTestCase2<SlidingDrawerStubActivity> {
+        extends ActivityInstrumentationTestCase2<SlidingDrawerCtsActivity> {
 
     private static final long TEST_TIMEOUT = 5000L;
     private Activity mActivity;
     private Object mLock;
 
     public SlidingDrawerTest() {
-        super("com.android.cts.stub", SlidingDrawerStubActivity.class);
+        super("com.android.cts.widget", SlidingDrawerCtsActivity.class);
     }
 
     @Override
@@ -61,6 +61,7 @@
         mLock = new Object();
     }
 
+    @UiThreadTest
     public void testConstructor() throws XmlPullParserException, IOException {
         XmlPullParser parser = mActivity.getResources().getLayout(R.layout.sliding_drawer_layout);
         AttributeSet attrs = Xml.asAttributeSet(parser);
diff --git a/tests/tests/widget/src/android/widget/cts/SpinnerTest.java b/tests/tests/widget/src/android/widget/cts/SpinnerTest.java
index 8ffd90b..1989626 100644
--- a/tests/tests/widget/src/android/widget/cts/SpinnerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SpinnerTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import android.app.AlertDialog;
@@ -31,11 +31,11 @@
 /**
  * Test {@link Spinner}.
  */
-public class SpinnerTest extends ActivityInstrumentationTestCase2<RelativeLayoutStubActivity> {
+public class SpinnerTest extends ActivityInstrumentationTestCase2<RelativeLayoutCtsActivity> {
     private Context mTargetContext;
 
     public SpinnerTest() {
-        super("com.android.cts.stub", RelativeLayoutStubActivity.class);
+        super("com.android.cts.widget", RelativeLayoutCtsActivity.class);
     }
 
     @Override
@@ -44,6 +44,7 @@
         mTargetContext = getInstrumentation().getTargetContext();
     }
 
+    @UiThreadTest
     public void testConstructor() {
         new Spinner(mTargetContext);
 
@@ -63,12 +64,13 @@
 
         spinner = (Spinner) getActivity().findViewById(R.id.spinner1);
         ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(mTargetContext,
-                com.android.cts.stub.R.array.string, android.R.layout.simple_spinner_item);
+                com.android.cts.widget.R.array.string, android.R.layout.simple_spinner_item);
         adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
         spinner.setAdapter(adapter);
         assertTrue(spinner.getBaseline() > 0);
     }
 
+    @UiThreadTest
     public void testSetOnItemClickListener() {
         Spinner spinner = new Spinner(mTargetContext);
 
@@ -89,6 +91,7 @@
         // Or do UI check?
     }
 
+    @UiThreadTest
     public void testOnClick() {
         Spinner spinner = new Spinner(mTargetContext);
         // normal value
@@ -129,7 +132,8 @@
         // TODO: find the dialog and get its title to assert whether setPrompt() takes effect?
     }
 
-    public void testsetPromptId() {
+    @UiThreadTest
+    public void testSetPromptId() {
         Spinner spinner = new Spinner(mTargetContext);
 
         spinner.setPromptId(R.string.hello_world);
diff --git a/tests/tests/widget/src/android/widget/cts/TabHostCtsActivity.java b/tests/tests/widget/src/android/widget/cts/TabHostCtsActivity.java
new file mode 100644
index 0000000..9703dd7
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/TabHostCtsActivity.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2009 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.widget.cts;
+
+import android.app.TabActivity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.TabHost;
+import android.widget.TextView;
+
+import com.android.cts.widget.R;
+
+/**
+ * A minimal application for TabHost test.
+ * It contains an initial tab whose tag is INITIAL_TAB_TAG and label is INITIAL_TAB_LABEL.
+ */
+public class TabHostCtsActivity extends TabActivity {
+    public static final String INITIAL_TAB_TAG = "initial tag";
+    public static final String INITIAL_TAB_LABEL = "initial label";
+    public static final String INITIAL_VIEW_TEXT = "initial view text";
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.tabhost_layout);
+
+        TabHost tabHost = getTabHost();
+
+        // at least one tab
+        tabHost.addTab(tabHost.newTabSpec(INITIAL_TAB_TAG)
+                .setIndicator(INITIAL_TAB_LABEL)
+                .setContent(new MyTabContentFactory()));
+    }
+
+    private class MyTabContentFactory implements TabHost.TabContentFactory {
+        public View createTabContent(String tag) {
+            final TextView tv = new TextView(getApplicationContext());
+            tv.setText(INITIAL_VIEW_TEXT);
+            return tv;
+        }
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/TabHostTest.java b/tests/tests/widget/src/android/widget/cts/TabHostTest.java
index 07334ad..00ecd40 100644
--- a/tests/tests/widget/src/android/widget/cts/TabHostTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TabHostTest.java
@@ -16,12 +16,13 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import android.app.Activity;
 import android.app.ActivityGroup;
 import android.content.Intent;
+import android.cts.util.WidgetTestUtils;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
 import android.view.View;
@@ -34,15 +35,15 @@
 /**
  * Test {@link TabHost}.
  */
-public class TabHostTest extends ActivityInstrumentationTestCase2<TabHostStubActivity> {
+public class TabHostTest extends ActivityInstrumentationTestCase2<TabHostCtsActivity> {
     private static final String TAG_TAB1 = "tab 1";
     private static final String TAG_TAB2 = "tab 2";
     private static final int TAB_HOST_ID = android.R.id.tabhost;
 
-    private TabHostStubActivity mActivity;
+    private TabHostCtsActivity mActivity;
 
     public TabHostTest() {
-        super("com.android.cts.stub", TabHostStubActivity.class);
+        super("com.android.cts.widget", TabHostCtsActivity.class);
     }
 
     @Override
@@ -71,7 +72,7 @@
      * 2. no exception occurs when doing normal operation after setup().
      */
     public void testSetup1() throws Throwable {
-        final Activity activity = launchActivity("com.android.cts.stub", StubActivity.class, null);
+        final Activity activity = launchActivity("com.android.cts.widget", CtsActivity.class, null);
 
         runTestOnUiThread(new Runnable() {
             public void run() {
@@ -102,7 +103,7 @@
      * 2. no exception occurs when uses TabSpec.setContent(android.content.Intent) after setup().
      */
     public void testSetup2() throws Throwable {
-        final ActivityGroup activity = launchActivity("com.android.cts.stub",
+        final ActivityGroup activity = launchActivity("com.android.cts.widget",
                 ActivityGroup.class, null);
 
 
@@ -120,7 +121,7 @@
                 TabSpec tabSpec = tabHost.newTabSpec(TAG_TAB1);
                 tabSpec.setIndicator(TAG_TAB1);
                 Intent intent = new Intent(Intent.ACTION_VIEW, null,
-                        mActivity, StubActivity.class);
+                        mActivity, CtsActivity.class);
                 tabSpec.setContent(intent);
                 tabHost.addTab(tabSpec);
                 tabHost.setCurrentTab(0);
@@ -249,7 +250,7 @@
     public void testGetCurrentView() {
         TabHost tabHost = mActivity.getTabHost();
         TextView textView = (TextView) tabHost.getCurrentView();
-        assertEquals(TabHostStubActivity.INITIAL_VIEW_TEXT, textView.getText().toString());
+        assertEquals(TabHostCtsActivity.INITIAL_VIEW_TEXT, textView.getText().toString());
 
         TabSpec tabSpec = tabHost.newTabSpec(TAG_TAB2);
         tabSpec.setIndicator(TAG_TAB2);
@@ -272,7 +273,7 @@
         tabHost.setCurrentTabByTag(TAG_TAB2);
         assertEquals(1, tabHost.getCurrentTab());
 
-        tabHost.setCurrentTabByTag(TabHostStubActivity.INITIAL_TAB_TAG);
+        tabHost.setCurrentTabByTag(TabHostCtsActivity.INITIAL_TAB_TAG);
         assertEquals(0, tabHost.getCurrentTab());
 
         // exceptional value
@@ -294,7 +295,7 @@
         assertTrue(tabHost.getTabContentView().getChildAt(1) instanceof ListView);
         TextView child2 = (TextView) tabHost.getTabContentView().getChildAt(2);
         tabHost.setCurrentTab(0);
-        assertEquals(TabHostStubActivity.INITIAL_VIEW_TEXT, child2.getText().toString());
+        assertEquals(TabHostCtsActivity.INITIAL_VIEW_TEXT, child2.getText().toString());
 
         TabSpec tabSpec = tabHost.newTabSpec(TAG_TAB2);
         tabSpec.setIndicator(TAG_TAB2);
@@ -310,7 +311,7 @@
         assertTrue(tabHost.getTabContentView().getChildAt(1) instanceof ListView);
         child2 = (TextView) tabHost.getTabContentView().getChildAt(2);
         tabHost.setCurrentTab(0);
-        assertEquals(TabHostStubActivity.INITIAL_VIEW_TEXT, child2.getText().toString());
+        assertEquals(TabHostCtsActivity.INITIAL_VIEW_TEXT, child2.getText().toString());
     }
 
     @UiThreadTest
@@ -357,7 +358,7 @@
     @UiThreadTest
     public void testGetCurrentTabTag() {
         TabHost tabHost = mActivity.getTabHost();
-        assertEquals(TabHostStubActivity.INITIAL_TAB_TAG, tabHost.getCurrentTabTag());
+        assertEquals(TabHostCtsActivity.INITIAL_TAB_TAG, tabHost.getCurrentTabTag());
 
         TabSpec tabSpec = tabHost.newTabSpec(TAG_TAB2);
         tabSpec.setIndicator(TAG_TAB2);
diff --git a/tests/tests/widget/src/android/widget/cts/TabHost_TabSpecTest.java b/tests/tests/widget/src/android/widget/cts/TabHost_TabSpecTest.java
index 470a666..1363491 100644
--- a/tests/tests/widget/src/android/widget/cts/TabHost_TabSpecTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TabHost_TabSpecTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import android.app.Activity;
@@ -29,7 +29,6 @@
 import android.net.Uri;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
-import android.text.style.cts.MockURLSpanTestActivity;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.ListView;
@@ -40,14 +39,14 @@
 /**
  * Test {@link TabSpec}.
  */
-public class TabHost_TabSpecTest extends ActivityInstrumentationTestCase2<TabHostStubActivity> {
+public class TabHost_TabSpecTest extends ActivityInstrumentationTestCase2<TabHostCtsActivity> {
     private static final String TAG_TAB2 = "tab 2";
 
     private TabHost mTabHost;
-    private TabHostStubActivity mActivity;
+    private TabHostCtsActivity mActivity;
 
     public TabHost_TabSpecTest() {
-        super("com.android.cts.stub", TabHostStubActivity.class);
+        super("com.android.cts.widget", TabHostCtsActivity.class);
     }
 
     @Override
@@ -138,7 +137,7 @@
         TabSpec tabSpec2 = mTabHost.newTabSpec("tab spec 2");
         tabSpec2.setIndicator("tab 2");
         // TabContentFactory to create a TextView as the content of the tab.
-        tabSpec2.setContent(com.android.cts.stub.R.id.tabhost_textview);
+        tabSpec2.setContent(com.android.cts.widget.R.id.tabhost_textview);
         mTabHost.addTab(tabSpec2);
         mTabHost.setCurrentTab(1);
         TextView currentView = (TextView) mTabHost.getCurrentView();
@@ -148,7 +147,7 @@
         TabSpec tabSpec3 = mTabHost.newTabSpec("tab spec 3");
         tabSpec3.setIndicator("tab 3");
         // TabContentFactory to create a ListView as the content of the tab.
-        tabSpec3.setContent(com.android.cts.stub.R.id.tabhost_listview);
+        tabSpec3.setContent(com.android.cts.widget.R.id.tabhost_listview);
         mTabHost.addTab(tabSpec3);
         mTabHost.setCurrentTab(2);
         assertTrue(mTabHost.getCurrentView() instanceof ListView);
diff --git a/tests/tests/widget/src/android/widget/cts/TabWidgetTest.java b/tests/tests/widget/src/android/widget/cts/TabWidgetTest.java
index b5c46c5..1f2e66c 100644
--- a/tests/tests/widget/src/android/widget/cts/TabWidgetTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TabWidgetTest.java
@@ -32,11 +32,11 @@
 /**
  * Test {@link TabWidget}.
  */
-public class TabWidgetTest extends ActivityInstrumentationTestCase2<TabHostStubActivity> {
+public class TabWidgetTest extends ActivityInstrumentationTestCase2<TabHostCtsActivity> {
     private Activity mActivity;
 
     public TabWidgetTest() {
-        super("com.android.cts.stub", TabHostStubActivity.class);
+        super("com.android.cts.widget", TabHostCtsActivity.class);
     }
 
     @Override
@@ -79,7 +79,7 @@
 
     @UiThreadTest
     public void testSetCurrentTab() {
-        TabHostStubActivity activity = getActivity();
+        TabHostCtsActivity activity = getActivity();
         TabWidget tabWidget = activity.getTabWidget();
         tabWidget.addView(new TextView(mActivity));
 
@@ -97,7 +97,7 @@
 
     @UiThreadTest
     public void testFocusCurrentTab() {
-        TabHostStubActivity activity = getActivity();
+        TabHostCtsActivity activity = getActivity();
         TabWidget tabWidget = activity.getTabWidget();
         tabWidget.addView(new TextView(mActivity));
 
diff --git a/tests/tests/widget/src/android/widget/cts/TableCtsActivity.java b/tests/tests/widget/src/android/widget/cts/TableCtsActivity.java
new file mode 100644
index 0000000..f76caed
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/TableCtsActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008 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.widget.cts;
+
+import com.android.cts.widget.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * A minimal application for TableLayout test.
+ */
+public class TableCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.table_layout_1);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/TableLayoutTest.java b/tests/tests/widget/src/android/widget/cts/TableLayoutTest.java
index ea84071..c8211f6 100644
--- a/tests/tests/widget/src/android/widget/cts/TableLayoutTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TableLayoutTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import android.content.Context;
@@ -39,11 +39,11 @@
 /**
  * Test {@link TableLayout}.
  */
-public class TableLayoutTest extends ActivityInstrumentationTestCase2<TableStubActivity> {
+public class TableLayoutTest extends ActivityInstrumentationTestCase2<TableCtsActivity> {
     private Context mContext;
 
     public TableLayoutTest() {
-        super("com.android.cts.stub", TableStubActivity.class);
+        super("com.android.cts.widget", TableCtsActivity.class);
     }
 
     @Override
@@ -58,15 +58,15 @@
 
         new TableLayout(mContext, null);
 
-        TableStubActivity activity = getActivity();
-        activity.setContentView(com.android.cts.stub.R.layout.table_layout_1);
+        TableCtsActivity activity = getActivity();
+        activity.setContentView(com.android.cts.widget.R.layout.table_layout_1);
         TableLayout tableLayout = (TableLayout) activity
-                .findViewById(com.android.cts.stub.R.id.table1);
+                .findViewById(com.android.cts.widget.R.id.table1);
         assertTrue(tableLayout.isColumnCollapsed(0));
         assertTrue(tableLayout.isColumnStretchable(2));
 
-        activity.setContentView(com.android.cts.stub.R.layout.table_layout_2);
-        tableLayout = (TableLayout) activity.findViewById(com.android.cts.stub.R.id.table2);
+        activity.setContentView(com.android.cts.widget.R.layout.table_layout_2);
+        tableLayout = (TableLayout) activity.findViewById(com.android.cts.widget.R.id.table2);
         assertTrue(tableLayout.isColumnShrinkable(1));
     }
 
@@ -203,15 +203,15 @@
     }
 
     public void testColumnStretchableEffect() {
-        final TableStubActivity activity = getActivity();
+        final TableCtsActivity activity = getActivity();
         getInstrumentation().runOnMainSync(new Runnable() {
             public void run() {
-                activity.setContentView(com.android.cts.stub.R.layout.table_layout_1);
+                activity.setContentView(com.android.cts.widget.R.layout.table_layout_1);
             }
         });
         getInstrumentation().waitForIdleSync();
         final TableLayout tableLayout =
-                (TableLayout) activity.findViewById(com.android.cts.stub.R.id.table1);
+                (TableLayout) activity.findViewById(com.android.cts.widget.R.id.table1);
 
         // Preparation: remove Collapsed mark for column 0.
         getInstrumentation().runOnMainSync(new Runnable() {
@@ -554,7 +554,7 @@
     public void testGenerateLayoutParams1() {
         TableLayout tableLayout = new TableLayout(mContext);
 
-        TableStubActivity activity = getActivity();
+        TableCtsActivity activity = getActivity();
         XmlResourceParser parser = activity.getResources().getLayout(R.layout.table_layout_1);
         AttributeSet attr = Xml.asAttributeSet(parser);
 
diff --git a/tests/tests/widget/src/android/widget/cts/TableLayout_LayoutParamsTest.java b/tests/tests/widget/src/android/widget/cts/TableLayout_LayoutParamsTest.java
index d63979a..20a9937 100644
--- a/tests/tests/widget/src/android/widget/cts/TableLayout_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TableLayout_LayoutParamsTest.java
@@ -139,7 +139,7 @@
         AttributeSet attrs = null;
         try {
             parser = mTargetContext.getResources()
-                    .getXml(com.android.cts.stub.R.xml.base_attributes);
+                    .getXml(com.android.cts.widget.R.xml.base_attributes);
 
             int type;
             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
diff --git a/tests/tests/widget/src/android/widget/cts/TableRowTest.java b/tests/tests/widget/src/android/widget/cts/TableRowTest.java
index 9ab4d13..6012f59 100644
--- a/tests/tests/widget/src/android/widget/cts/TableRowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TableRowTest.java
@@ -33,18 +33,18 @@
 import android.widget.TableRow;
 import android.widget.TextView;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 /**
  * Test {@link TableRow}.
  */
-public class TableRowTest extends ActivityInstrumentationTestCase2<TableStubActivity> {
+public class TableRowTest extends ActivityInstrumentationTestCase2<TableCtsActivity> {
     Context mContext;
     Context mTargetContext;
 
     public TableRowTest() {
-        super("com.android.cts.stub", TableStubActivity.class);
+        super("com.android.cts.widget", TableCtsActivity.class);
     }
 
     @Override
@@ -82,10 +82,10 @@
 
     @UiThreadTest
     public void testGetVirtualChildAt() {
-        TableStubActivity activity = getActivity();
-        activity.setContentView(com.android.cts.stub.R.layout.table_layout_1);
+        TableCtsActivity activity = getActivity();
+        activity.setContentView(com.android.cts.widget.R.layout.table_layout_1);
         TableLayout tableLayout = (TableLayout) activity
-                .findViewById(com.android.cts.stub.R.id.table1);
+                .findViewById(com.android.cts.widget.R.id.table1);
 
         TableRow tableRow = (TableRow) tableLayout.getChildAt(0);
         Resources resources = activity.getResources();
@@ -96,8 +96,8 @@
         assertEquals(resources.getString(R.string.table_layout_third),
                 ((TextView) tableRow.getVirtualChildAt(2)).getText().toString());
 
-        activity.setContentView(com.android.cts.stub.R.layout.table_layout_2);
-        tableLayout = (TableLayout) activity.findViewById(com.android.cts.stub.R.id.table2);
+        activity.setContentView(com.android.cts.widget.R.layout.table_layout_2);
+        tableLayout = (TableLayout) activity.findViewById(com.android.cts.widget.R.id.table2);
 
         tableRow = (TableRow) tableLayout.getChildAt(0);
         assertNull(tableRow.getVirtualChildAt(0));
@@ -113,16 +113,16 @@
 
     @UiThreadTest
     public void testGetVirtualChildCount() {
-        TableStubActivity activity = getActivity();
-        activity.setContentView(com.android.cts.stub.R.layout.table_layout_1);
+        TableCtsActivity activity = getActivity();
+        activity.setContentView(com.android.cts.widget.R.layout.table_layout_1);
         TableLayout tableLayout = (TableLayout) activity
-                .findViewById(com.android.cts.stub.R.id.table1);
+                .findViewById(com.android.cts.widget.R.id.table1);
 
         TableRow tableRow = (TableRow) tableLayout.getChildAt(0);
         assertEquals(3, tableRow.getVirtualChildCount());
 
-        activity.setContentView(com.android.cts.stub.R.layout.table_layout_2);
-        tableLayout = (TableLayout) activity.findViewById(com.android.cts.stub.R.id.table2);
+        activity.setContentView(com.android.cts.widget.R.layout.table_layout_2);
+        tableLayout = (TableLayout) activity.findViewById(com.android.cts.widget.R.id.table2);
 
         tableRow = (TableRow) tableLayout.getChildAt(0);
         assertEquals(5, tableRow.getVirtualChildCount());
diff --git a/tests/tests/widget/src/android/widget/cts/TableRow_LayoutParamsTest.java b/tests/tests/widget/src/android/widget/cts/TableRow_LayoutParamsTest.java
index 1d6793f..cf2603f 100644
--- a/tests/tests/widget/src/android/widget/cts/TableRow_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TableRow_LayoutParamsTest.java
@@ -39,11 +39,11 @@
  * Test {@link TableRow.LayoutParams}.
  */
 public class TableRow_LayoutParamsTest
-        extends ActivityInstrumentationTestCase2<TableStubActivity> {
+        extends ActivityInstrumentationTestCase2<TableCtsActivity> {
     Context mTargetContext;
 
     public TableRow_LayoutParamsTest() {
-        super("com.android.cts.stub", TableStubActivity.class);
+        super("com.android.cts.widget", TableCtsActivity.class);
     }
 
     @Override
@@ -91,9 +91,9 @@
         assertEquals(0, layoutParams.column);
         assertEquals(0, layoutParams.span);
 
-        TableStubActivity activity = getActivity();
-        activity.setContentView(com.android.cts.stub.R.layout.table_layout_2);
-        int idTable = com.android.cts.stub.R.id.table2;
+        TableCtsActivity activity = getActivity();
+        activity.setContentView(com.android.cts.widget.R.layout.table_layout_2);
+        int idTable = com.android.cts.widget.R.id.table2;
         TableLayout tableLayout = (TableLayout) activity.findViewById(idTable);
         View vVitural1 = ((TableRow) tableLayout.getChildAt(0)).getVirtualChildAt(1);
         layoutParams = (TableRow.LayoutParams) vVitural1.getLayoutParams();
@@ -186,7 +186,7 @@
         AttributeSet attrs = null;
         try {
             parser = mTargetContext.getResources()
-                    .getXml(com.android.cts.stub.R.xml.base_attributes);
+                    .getXml(com.android.cts.widget.R.xml.base_attributes);
 
             int type;
             while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/TextViewCtsActivity.java
new file mode 100644
index 0000000..888f215
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/TextViewCtsActivity.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2008 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.widget.cts;
+
+import com.android.cts.widget.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * A minimal application for TextView test.
+ */
+public class TextViewCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.textview_layout);
+    }
+}
+
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index 36ace30..72193e7 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 import com.android.internal.util.FastMath;
 
 import org.xmlpull.v1.XmlPullParserException;
@@ -28,6 +28,7 @@
 import android.content.res.ColorStateList;
 import android.content.res.Resources.NotFoundException;
 import android.cts.util.PollingCheck;
+import android.cts.util.WidgetTestUtils;
 import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.graphics.Paint;
@@ -69,7 +70,6 @@
 import android.text.method.TimeKeyListener;
 import android.text.method.TransformationMethod;
 import android.text.style.URLSpan;
-import android.text.style.cts.MockURLSpanTestActivity;
 import android.text.util.Linkify;
 import android.util.DisplayMetrics;
 import android.util.TypedValue;
@@ -98,7 +98,7 @@
 /**
  * Test {@link TextView}.
  */
-public class TextViewTest extends ActivityInstrumentationTestCase2<TextViewStubActivity> {
+public class TextViewTest extends ActivityInstrumentationTestCase2<TextViewCtsActivity> {
 
     private TextView mTextView;
     private Activity mActivity;
@@ -112,7 +112,7 @@
     private CharSequence mTransformedText;
 
     public TextViewTest() {
-        super("com.android.cts.stub", TextViewStubActivity.class);
+        super("com.android.cts.widget", TextViewCtsActivity.class);
     }
 
     @Override
@@ -1300,7 +1300,7 @@
         mTextView = findTextView(R.id.textview_text);
         assertNull(mTextView.getError());
 
-        final String errorText = "Opps! There is an error";
+        final String errorText = "Oops! There is an error";
 
         mActivity.runOnUiThread(new Runnable() {
             public void run() {
@@ -1344,7 +1344,7 @@
         // a key event that will not change the TextView's text
         assertEquals("", mTextView.getText().toString());
         // The icon and error message will not be reset to null
-        assertNull(mTextView.getError());
+        assertEquals(errorText, mTextView.getError().toString());
 
         mActivity.runOnUiThread(new Runnable() {
             public void run() {
@@ -1810,7 +1810,8 @@
 
         // getTypeface
         // getTypeface will be null if android:typeface is set to normal,
-        // and android:style is not set or is set to normal
+        // and android:style is not set or is set to normal, and
+        // android:fontFamily is not set
         assertNull(mTextView.getTypeface());
 
         mTextView.setTypeface(Typeface.DEFAULT);
@@ -3293,7 +3294,7 @@
 
     @UiThreadTest
     public void testResetTextAlignment() {
-        TextViewStubActivity activity = getActivity();
+        TextViewCtsActivity activity = getActivity();
 
         LinearLayout ll = (LinearLayout) activity.findViewById(R.id.layout_textviewtest);
         TextView tv = (TextView) activity.findViewById(R.id.textview_rtl);
@@ -3319,7 +3320,7 @@
         final int RIGHT = 2;
         final int BOTTOM = 3;
 
-        TextViewStubActivity activity = getActivity();
+        TextViewCtsActivity activity = getActivity();
 
         // Case 1.1: left / right drawable defined in default LTR mode
         TextView tv = (TextView) activity.findViewById(R.id.textview_drawable_1_1);
@@ -3463,7 +3464,7 @@
         final int RIGHT = 2;
         final int BOTTOM = 3;
 
-        TextViewStubActivity activity = getActivity();
+        TextViewCtsActivity activity = getActivity();
 
         // Case 1.1: left / right drawable defined in default LTR mode
         TextView tv = (TextView) activity.findViewById(R.id.textview_drawable_1_1);
diff --git a/tests/tests/widget/src/android/widget/cts/TimePickerTest.java b/tests/tests/widget/src/android/widget/cts/TimePickerTest.java
index 2ab01a3..fcf787a 100644
--- a/tests/tests/widget/src/android/widget/cts/TimePickerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TimePickerTest.java
@@ -29,7 +29,7 @@
 /**
  * Test {@link TimePicker}.
  */
-public class TimePickerTest extends ActivityInstrumentationTestCase2<StubActivity> {
+public class TimePickerTest extends ActivityInstrumentationTestCase2<CtsActivity> {
     private TimePicker mTimePicker;
 
     private Activity mActivity;
@@ -39,7 +39,7 @@
     private Instrumentation mInstrumentation;
 
     public TimePickerTest() {
-        super("com.android.cts.stub", StubActivity.class);
+        super("com.android.cts.widget", CtsActivity.class);
     }
 
     @Override
@@ -52,7 +52,7 @@
 
     public void testConstructors() {
         AttributeSet attrs =
-            mContext.getResources().getLayout(com.android.cts.stub.R.layout.timepicker);
+            mContext.getResources().getLayout(com.android.cts.widget.R.layout.timepicker);
         assertNotNull(attrs);
 
         new TimePicker(mContext);
diff --git a/tests/tests/widget/src/android/widget/cts/ToastTest.java b/tests/tests/widget/src/android/widget/cts/ToastTest.java
index 9c7846b..90a161e 100644
--- a/tests/tests/widget/src/android/widget/cts/ToastTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ToastTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import android.app.Activity;
@@ -33,7 +33,7 @@
 import android.widget.ImageView;
 import android.widget.Toast;
 
-public class ToastTest extends ActivityInstrumentationTestCase2<StubActivity> {
+public class ToastTest extends ActivityInstrumentationTestCase2<CtsActivity> {
     private static final String TEST_TOAST_TEXT = "test toast";
     private static final long TIME_FOR_UI_OPERATION  = 1000L;
     private static final long TIME_OUT = 5000L;
@@ -44,7 +44,7 @@
     private ViewTreeObserver.OnGlobalLayoutListener mLayoutListener;
 
     public ToastTest() {
-        super("com.android.cts.stub", StubActivity.class);
+        super("com.android.cts.widget", CtsActivity.class);
     }
 
     @Override
@@ -53,7 +53,6 @@
 
         mActivity = getActivity();
         mInstrumentation = getInstrumentation();
-        mToast = new Toast(mActivity);
         mLayoutDone = false;
         mLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
             public void onGlobalLayout() {
@@ -62,6 +61,7 @@
         };
     }
 
+    @UiThreadTest
     public void testConstructor() {
         new Toast(mActivity);
 
@@ -113,13 +113,17 @@
         view.getViewTreeObserver().removeOnGlobalLayoutListener(mLayoutListener);
     }
 
-    public void testShow() {
+    private void makeToast() {
         mActivity.runOnUiThread(new Runnable() {
             public void run() {
                 mToast = Toast.makeText(mActivity, TEST_TOAST_TEXT, Toast.LENGTH_LONG);
             }
         });
         mInstrumentation.waitForIdleSync();
+    }
+
+    public void testShow() {
+        makeToast();
 
         final View view = mToast.getView();
 
@@ -141,10 +145,11 @@
 
     @UiThreadTest
     public void testShowFailure() {
+        Toast toast = new Toast(mActivity);
         // do not have any views.
-        assertNull(mToast.getView());
+        assertNull(toast.getView());
         try {
-            mToast.show();
+            toast.show();
             fail("did not throw RuntimeException when did not set any views.");
         } catch (RuntimeException e) {
             // expected, test success.
@@ -152,12 +157,7 @@
     }
 
     public void testCancel() throws InterruptedException {
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                mToast = Toast.makeText(mActivity, TEST_TOAST_TEXT, Toast.LENGTH_LONG);
-            }
-        });
-        mInstrumentation.waitForIdleSync();
+        makeToast();
 
         final View view = mToast.getView();
 
@@ -175,12 +175,7 @@
     }
 
     public void testAccessView() {
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                mToast = Toast.makeText(mActivity, TEST_TOAST_TEXT, Toast.LENGTH_LONG);
-            }
-        });
-        mInstrumentation.waitForIdleSync();
+        makeToast();
         assertFalse(mToast.getView() instanceof ImageView);
 
         final ImageView imageView = new ImageView(mActivity);
@@ -197,11 +192,12 @@
         assertSame(imageView, mToast.getView());
         assertShowAndHide(imageView);
     }
+
     public void testAccessDuration() {
         long start = SystemClock.uptimeMillis();
+        makeToast();
         mActivity.runOnUiThread(new Runnable() {
             public void run() {
-                mToast = Toast.makeText(mActivity, TEST_TOAST_TEXT, Toast.LENGTH_LONG);
                 mToast.show();
             }
         });
@@ -230,12 +226,7 @@
     }
 
     public void testAccessMargin() {
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                mToast = Toast.makeText(mActivity, TEST_TOAST_TEXT, Toast.LENGTH_SHORT);
-            }
-        });
-        mInstrumentation.waitForIdleSync();
+        makeToast();
         View view = mToast.getView();
         assertFalse(view.getLayoutParams() instanceof WindowManager.LayoutParams);
 
@@ -289,9 +280,9 @@
     }
 
     public void testAccessGravity() {
+        makeToast();
         mActivity.runOnUiThread(new Runnable() {
             public void run() {
-                mToast = Toast.makeText(mActivity, TEST_TOAST_TEXT, Toast.LENGTH_SHORT);
                 mToast.setGravity(Gravity.CENTER, 0, 0);
                 mToast.show();
                 registerLayoutListener(mToast.getView());
@@ -357,26 +348,26 @@
 
     @UiThreadTest
     public void testMakeText1() {
-        mToast = Toast.makeText(mActivity, "android", Toast.LENGTH_SHORT);
-        assertNotNull(mToast);
-        assertEquals(Toast.LENGTH_SHORT, mToast.getDuration());
-        View view = mToast.getView();
+        Toast toast = Toast.makeText(mActivity, "android", Toast.LENGTH_SHORT);
+        assertNotNull(toast);
+        assertEquals(Toast.LENGTH_SHORT, toast.getDuration());
+        View view = toast.getView();
         assertNotNull(view);
 
-        mToast = Toast.makeText(mActivity, "cts", Toast.LENGTH_LONG);
-        assertNotNull(mToast);
-        assertEquals(Toast.LENGTH_LONG, mToast.getDuration());
-        view = mToast.getView();
+        toast = Toast.makeText(mActivity, "cts", Toast.LENGTH_LONG);
+        assertNotNull(toast);
+        assertEquals(Toast.LENGTH_LONG, toast.getDuration());
+        view = toast.getView();
         assertNotNull(view);
 
-        mToast = Toast.makeText(mActivity, null, Toast.LENGTH_LONG);
-        assertNotNull(mToast);
-        assertEquals(Toast.LENGTH_LONG, mToast.getDuration());
-        view = mToast.getView();
+        toast = Toast.makeText(mActivity, null, Toast.LENGTH_LONG);
+        assertNotNull(toast);
+        assertEquals(Toast.LENGTH_LONG, toast.getDuration());
+        view = toast.getView();
         assertNotNull(view);
 
         try {
-            mToast = Toast.makeText(null, "test", Toast.LENGTH_LONG);
+            toast = Toast.makeText(null, "test", Toast.LENGTH_LONG);
             fail("did not throw NullPointerException when context is null.");
         } catch (NullPointerException e) {
             //expected, test success.
@@ -385,21 +376,21 @@
 
     @UiThreadTest
     public void testMakeText2() {
-        mToast = Toast.makeText(mActivity, R.string.hello_world, Toast.LENGTH_LONG);
+        Toast toast = Toast.makeText(mActivity, R.string.hello_world, Toast.LENGTH_LONG);
 
-        assertNotNull(mToast);
-        assertEquals(Toast.LENGTH_LONG, mToast.getDuration());
-        View view = mToast.getView();
+        assertNotNull(toast);
+        assertEquals(Toast.LENGTH_LONG, toast.getDuration());
+        View view = toast.getView();
         assertNotNull(view);
 
-        mToast = Toast.makeText(mActivity, R.string.hello_android, Toast.LENGTH_SHORT);
-        assertNotNull(mToast);
-        assertEquals(Toast.LENGTH_SHORT, mToast.getDuration());
-        view = mToast.getView();
+        toast = Toast.makeText(mActivity, R.string.hello_android, Toast.LENGTH_SHORT);
+        assertNotNull(toast);
+        assertEquals(Toast.LENGTH_SHORT, toast.getDuration());
+        view = toast.getView();
         assertNotNull(view);
 
         try {
-            mToast = Toast.makeText(null, R.string.hello_android, Toast.LENGTH_SHORT);
+            toast = Toast.makeText(null, R.string.hello_android, Toast.LENGTH_SHORT);
             fail("did not throw NullPointerException when context is null.");
         } catch (NullPointerException e) {
             //expected, test success.
@@ -408,16 +399,16 @@
 
     @UiThreadTest
     public void testSetText1() {
-        mToast = Toast.makeText(mActivity, R.string.text, Toast.LENGTH_LONG);
+        Toast toast = Toast.makeText(mActivity, R.string.text, Toast.LENGTH_LONG);
 
-        mToast.setText(R.string.hello_world);
+        toast.setText(R.string.hello_world);
         // TODO: how to getText to assert?
 
-        mToast.setText(R.string.hello_android);
+        toast.setText(R.string.hello_android);
         // TODO: how to getText to assert?
 
         try {
-            mToast.setText(-1);
+            toast.setText(-1);
             fail("did not throw RuntimeException when resource id is negative.");
         } catch (RuntimeException e) {
             //expected, test success.
@@ -426,17 +417,17 @@
 
     @UiThreadTest
     public void testSetText2() {
-        mToast = Toast.makeText(mActivity, R.string.text, Toast.LENGTH_LONG);
+        Toast toast = Toast.makeText(mActivity, R.string.text, Toast.LENGTH_LONG);
 
-        mToast.setText("cts");
+        toast.setText("cts");
         // TODO: how to getText to assert?
 
-        mToast.setText("android");
+        toast.setText("android");
         // TODO: how to getText to assert?
 
         try {
-            mToast.setView(null);
-            mToast.setText(null);
+            toast.setView(null);
+            toast.setText(null);
             fail("did not throw RuntimeException when view is null.");
         } catch (RuntimeException e) {
             //expected, test success.
diff --git a/tests/tests/widget/src/android/widget/cts/ToggleButtonTest.java b/tests/tests/widget/src/android/widget/cts/ToggleButtonTest.java
index ca1c94f..b3bc31e 100644
--- a/tests/tests/widget/src/android/widget/cts/ToggleButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ToggleButtonTest.java
@@ -21,18 +21,19 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
-import android.test.AndroidTestCase;
+import android.test.InstrumentationTestCase;
+import android.test.UiThreadTest;
 import android.util.AttributeSet;
 import android.util.Xml;
 import android.widget.ToggleButton;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 /**
  * Test {@link ToggleButton}.
  */
-public class ToggleButtonTest extends AndroidTestCase {
+public class ToggleButtonTest extends InstrumentationTestCase {
     private static final String TEXT_OFF = "text off";
     private static final String TEXT_ON = "text on";
     ToggleButton mToggleButton;
@@ -43,7 +44,7 @@
     protected void setUp() throws Exception {
         super.setUp();
 
-        mContext = getContext();
+        mContext = getInstrumentation().getTargetContext();
         XmlPullParser parser = mContext.getResources().getXml(R.layout.togglebutton_layout);
         mAttrSet = Xml.asAttributeSet(parser);
         mToggleButton = new ToggleButton(mContext, mAttrSet);
@@ -88,6 +89,7 @@
         assertEquals("", mToggleButton.getTextOff());
     }
 
+    @UiThreadTest
     public void testDrawableStateChanged() {
         MockToggleButton toggleButton = new MockToggleButton(mContext);
 
@@ -111,6 +113,7 @@
         toggleButton.onFinishInflate();
     }
 
+    @UiThreadTest
     public void testSetChecked() {
         assertFalse(mToggleButton.isChecked());
 
@@ -121,6 +124,7 @@
         assertFalse(mToggleButton.isChecked());
     }
 
+    @UiThreadTest
     public void testToggleText() {
         mToggleButton.setText("default text");
         mToggleButton.setTextOn(TEXT_ON);
diff --git a/tests/tests/widget/src/android/widget/cts/TwoLineListItemCtsActivity.java b/tests/tests/widget/src/android/widget/cts/TwoLineListItemCtsActivity.java
new file mode 100644
index 0000000..bd2c36d
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/TwoLineListItemCtsActivity.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2008 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.widget.cts;
+
+import com.android.cts.widget.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TwoLineListItem;
+
+/**
+ * Stub activity for testing {@link TwoLineListItem}
+ */
+public class TwoLineListItemCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.twolinelistitem);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/TwoLineListItemTest.java b/tests/tests/widget/src/android/widget/cts/TwoLineListItemTest.java
index 5ef5961..0d5807f 100644
--- a/tests/tests/widget/src/android/widget/cts/TwoLineListItemTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TwoLineListItemTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import android.app.Activity;
@@ -32,11 +32,11 @@
  * Test {@link TwoLineListItem}.
  */
 public class TwoLineListItemTest extends
-        ActivityInstrumentationTestCase<TwoLineListItemStubActivity> {
+        ActivityInstrumentationTestCase<TwoLineListItemCtsActivity> {
     private Activity mActivity;
 
     public TwoLineListItemTest() {
-        super("com.android.cts.stub", TwoLineListItemStubActivity.class);
+        super("com.android.cts.widget", TwoLineListItemCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/widget/src/android/widget/cts/VideoViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/VideoViewCtsActivity.java
new file mode 100644
index 0000000..ad0d6eb
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/VideoViewCtsActivity.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2009 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.widget.cts;
+
+import com.android.cts.widget.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.VideoView;
+
+/**
+ * A minimal application for {@link VideoView} test.
+ */
+public class VideoViewCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.videoview_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/VideoViewTest.java b/tests/tests/widget/src/android/widget/cts/VideoViewTest.java
index c8d9fc7..6e514f8 100644
--- a/tests/tests/widget/src/android/widget/cts/VideoViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/VideoViewTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 import android.app.Activity;
 import android.app.Instrumentation;
@@ -29,6 +29,7 @@
 import android.media.MediaPlayer.OnErrorListener;
 import android.media.MediaPlayer.OnPreparedListener;
 import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
 import android.util.Log;
 import android.view.View.MeasureSpec;
 import android.widget.MediaController;
@@ -41,7 +42,7 @@
 /**
  * Test {@link VideoView}.
  */
-public class VideoViewTest extends ActivityInstrumentationTestCase2<VideoViewStubActivity> {
+public class VideoViewTest extends ActivityInstrumentationTestCase2<VideoViewCtsActivity> {
     /** Debug TAG. **/
     private static final String TAG = "VideoViewTest";
     /** The maximum time to wait for an operation. */
@@ -62,7 +63,6 @@
     private Activity mActivity;
     private Instrumentation mInstrumentation;
     private String mVideoPath;
-    private MediaController mMediaController;
 
     private static class MockListener {
         private boolean mTriggered;
@@ -127,7 +127,7 @@
      * Instantiates a new video view test.
      */
     public VideoViewTest() {
-        super("com.android.cts.stub", VideoViewStubActivity.class);
+        super("com.android.cts.widget", VideoViewCtsActivity.class);
     }
 
     /**
@@ -180,10 +180,19 @@
         mVideoPath = prepareSampleVideo();
         assertNotNull(mVideoPath);
         mVideoView = findVideoViewById(R.id.videoview);
-        mMediaController = new MediaController(mActivity);
-        mVideoView.setMediaController(mMediaController);
     }
 
+    private void makeVideoView() {
+        mActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                MediaController mediaController = new MediaController(mActivity);
+                mVideoView.setMediaController(mediaController);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+    }
+
+    @UiThreadTest
     public void testConstructor() {
         new VideoView(mActivity);
 
@@ -193,6 +202,7 @@
     }
 
     public void testPlayVideo1() throws Throwable {
+        makeVideoView();
         // 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.");
@@ -232,6 +242,7 @@
     }
 
     public void testSetOnErrorListener() throws Throwable {
+        makeVideoView();
         final MockOnErrorListener listener = new MockOnErrorListener();
         mVideoView.setOnErrorListener(listener);
 
@@ -253,6 +264,7 @@
     }
 
     public void testGetBufferPercentage() throws Throwable {
+        makeVideoView();
         // 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.");
@@ -279,6 +291,7 @@
         assertTrue(percent >= 0 && percent <= 100);
     }
 
+    @UiThreadTest
     public void testResolveAdjustedSize() {
         mVideoView = new VideoView(mActivity);
 
@@ -310,6 +323,7 @@
         assertTrue(Math.abs(mVideoView.getDuration() - TEST_VIDEO_DURATION) < DURATION_DELTA);
     }
 
+    @UiThreadTest
     public void testSetMediaController() {
         final MediaController ctlr = new MediaController(mActivity);
         mVideoView.setMediaController(ctlr);
diff --git a/tests/tests/widget/src/android/widget/cts/ViewAnimatorCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ViewAnimatorCtsActivity.java
new file mode 100644
index 0000000..21deef7
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ViewAnimatorCtsActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008 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.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import com.android.cts.widget.R;
+
+/**
+ * A minimal application for ViewAnimator test.
+ */
+public class ViewAnimatorCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.viewanimator_layout);
+    }
+}
+
diff --git a/tests/tests/widget/src/android/widget/cts/ViewAnimatorTest.java b/tests/tests/widget/src/android/widget/cts/ViewAnimatorTest.java
index 72f5559..024e3ee 100644
--- a/tests/tests/widget/src/android/widget/cts/ViewAnimatorTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ViewAnimatorTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import org.xmlpull.v1.XmlPullParser;
@@ -36,14 +36,14 @@
 import android.widget.ViewAnimator;
 
 public class ViewAnimatorTest extends
-        ActivityInstrumentationTestCase2<ViewAnimatorStubActivity> {
+        ActivityInstrumentationTestCase2<ViewAnimatorCtsActivity> {
     private ViewAnimator mViewAnimator;
     private Activity mActivity;
     private Instrumentation mInstrumentation;
     private AttributeSet mAttributeSet;
 
     public ViewAnimatorTest() {
-        super("com.android.cts.stub", ViewAnimatorStubActivity.class);
+        super("com.android.cts.widget", ViewAnimatorCtsActivity.class);
     }
 
     @Override
diff --git a/tests/tests/widget/src/android/widget/cts/ViewFlipperCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ViewFlipperCtsActivity.java
new file mode 100644
index 0000000..7f13f6c
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ViewFlipperCtsActivity.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2008 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.widget.cts;
+
+import com.android.cts.widget.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class ViewFlipperCtsActivity extends Activity {
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.viewflipper_layout);
+    }
+}
+
diff --git a/tests/tests/widget/src/android/widget/cts/ViewFlipperTest.java b/tests/tests/widget/src/android/widget/cts/ViewFlipperTest.java
index f223466..025fae4 100644
--- a/tests/tests/widget/src/android/widget/cts/ViewFlipperTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ViewFlipperTest.java
@@ -16,13 +16,14 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import org.xmlpull.v1.XmlPullParser;
 
 import android.app.Activity;
 import android.test.ActivityInstrumentationTestCase;
+import android.test.UiThreadTest;
 import android.util.AttributeSet;
 import android.util.Xml;
 import android.view.View;
@@ -32,11 +33,11 @@
 /**
  * Test {@link ViewFlipper}.
  */
-public class ViewFlipperTest extends ActivityInstrumentationTestCase<ViewFlipperStubActivity> {
+public class ViewFlipperTest extends ActivityInstrumentationTestCase<ViewFlipperCtsActivity> {
     private Activity mActivity;
 
     public ViewFlipperTest() {
-        super("com.android.cts.stub", ViewFlipperStubActivity.class);
+        super("com.android.cts.widget", ViewFlipperCtsActivity.class);
     }
 
     protected void setUp() throws Exception {
@@ -45,6 +46,7 @@
         assertNotNull(mActivity);
     }
 
+    @UiThreadTest
     public void testConstructor() {
         new ViewFlipper(mActivity);
 
@@ -61,6 +63,7 @@
         }
     }
 
+    @UiThreadTest
     public void testSetFlipInterval() {
         ViewFlipper viewFlipper = new ViewFlipper(mActivity);
         viewFlipper.setFlipInterval(0);
diff --git a/tests/tests/widget/src/android/widget/cts/ViewGroupCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ViewGroupCtsActivity.java
new file mode 100644
index 0000000..4e14fc2
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ViewGroupCtsActivity.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2008 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.widget.cts;
+
+import android.app.Activity;
+import android.cts.util.CTSResult;
+import android.os.Bundle;
+import android.os.Handler;
+import android.widget.TextView;
+
+public class ViewGroupCtsActivity extends Activity {
+
+    public static final String ACTION_INVALIDATE_CHILD = "invalidateChild";
+
+    private final Handler mHandler = new Handler();
+    private static CTSResult sResult;
+    public static void setResult(CTSResult result) {
+        sResult = result;
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(com.android.cts.widget.R.layout.viewgrouptest_stub);
+        TextView textView = (TextView)findViewById(com.android.cts.widget.R.id.viewgrouptest_stub);
+        textView.setText("test");
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+
+        String action = getIntent().getAction();
+        if (action.equals(ACTION_INVALIDATE_CHILD)) {
+            mHandler.postDelayed(new Runnable() {
+                public void run() {
+                    MockLinearLayout mll =
+                        (MockLinearLayout) findViewById(com.android.cts.widget.R.id.
+                                                                        mocklinearlayout);
+                    if (!mll.mIsInvalidateChildInParentCalled) {
+                        fail();
+                        return;
+                    }
+                    sResult.setResult(CTSResult.RESULT_OK);
+                    finish();
+                }
+            }, 2000);
+        }
+    }
+
+    private void fail() {
+        sResult.setResult(CTSResult.RESULT_FAIL);
+        finish();
+    }
+}
+
diff --git a/tests/tests/widget/src/android/widget/cts/ViewSwitcherTest.java b/tests/tests/widget/src/android/widget/cts/ViewSwitcherTest.java
index b7bac6c..ce18267 100644
--- a/tests/tests/widget/src/android/widget/cts/ViewSwitcherTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ViewSwitcherTest.java
@@ -28,7 +28,7 @@
 import android.widget.ViewSwitcher;
 import android.widget.ViewSwitcher.ViewFactory;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 /**
diff --git a/tests/tests/widget/src/android/widget/cts/ZoomButtonCtsActivity.java b/tests/tests/widget/src/android/widget/cts/ZoomButtonCtsActivity.java
new file mode 100644
index 0000000..e371b3f
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/ZoomButtonCtsActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2009 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.widget.cts;
+
+import com.android.cts.widget.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * A minimal application for {@link ZoomButton} test.
+ */
+public class ZoomButtonCtsActivity extends Activity {
+    /**
+     * Called with the activity is first created.
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.zoombutton_layout);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java b/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java
index 94c2669..3d906db 100644
--- a/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ZoomButtonTest.java
@@ -16,7 +16,7 @@
 
 package android.widget.cts;
 
-import com.android.cts.stub.R;
+import com.android.cts.widget.R;
 
 
 import org.xmlpull.v1.XmlPullParser;
@@ -32,12 +32,12 @@
 import android.widget.ListView;
 import android.widget.ZoomButton;
 
-public class ZoomButtonTest extends ActivityInstrumentationTestCase2<ZoomButtonStubActivity> {
+public class ZoomButtonTest extends ActivityInstrumentationTestCase2<ZoomButtonCtsActivity> {
     private ZoomButton mZoomButton;
     private Activity mActivity;
 
     public ZoomButtonTest() {
-        super("com.android.cts.stub", ZoomButtonStubActivity.class);
+        super("com.android.cts.widget", ZoomButtonCtsActivity.class);
     }
 
     @Override
@@ -48,6 +48,7 @@
         mActivity = getActivity();
     }
 
+    @UiThreadTest
     public void testConstructor() {
         new ZoomButton(mActivity);
 
diff --git a/tests/tests/widget/src/android/widget/cts/ZoomControlsTest.java b/tests/tests/widget/src/android/widget/cts/ZoomControlsTest.java
index 5dc7a0e..9b3ffba 100644
--- a/tests/tests/widget/src/android/widget/cts/ZoomControlsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ZoomControlsTest.java
@@ -36,12 +36,14 @@
         mContext = getInstrumentation().getContext();
     }
 
+    @UiThreadTest
     public void testConstructor() {
         new ZoomControls(mContext);
 
         new ZoomControls(mContext, null);
     }
 
+    @UiThreadTest
     public void testSetOnZoomInClickListener() {
         ZoomControls zoomControls = new ZoomControls(mContext);
 
@@ -59,6 +61,7 @@
         }
     }
 
+    @UiThreadTest
     public void testSetOnZoomOutClickListener() {
         ZoomControls zoomControls = new ZoomControls(mContext);
 
@@ -70,6 +73,7 @@
         zoomControls.setOnZoomOutClickListener(null);
     }
 
+    @UiThreadTest
     public void testSetZoomSpeed() {
         ZoomControls zoomControls = new ZoomControls(mContext);
 
@@ -82,6 +86,7 @@
         // onTouchEvent() is implementation details, do NOT test
     }
 
+    @UiThreadTest
     public void testShowAndHide() {
         final ZoomControls zoomControls = new ZoomControls(mContext);
         assertEquals(View.VISIBLE, zoomControls.getVisibility());
@@ -93,12 +98,14 @@
         assertEquals(View.VISIBLE, zoomControls.getVisibility());
     }
 
+    @UiThreadTest
     public void testSetIsZoomInEnabled() {
         ZoomControls zoomControls = new ZoomControls(mContext);
         zoomControls.setIsZoomInEnabled(false);
         zoomControls.setIsZoomInEnabled(true);
     }
 
+    @UiThreadTest
     public void testSetIsZoomOutEnabled() {
         ZoomControls zoomControls = new ZoomControls(mContext);
         zoomControls.setIsZoomOutEnabled(false);
diff --git a/tests/src/android/widget/cts/util/ExpandableListScenario.java b/tests/tests/widget/src/android/widget/cts/util/ExpandableListScenario.java
similarity index 100%
rename from tests/src/android/widget/cts/util/ExpandableListScenario.java
rename to tests/tests/widget/src/android/widget/cts/util/ExpandableListScenario.java
diff --git a/tests/src/android/widget/cts/util/ListItemFactory.java b/tests/tests/widget/src/android/widget/cts/util/ListItemFactory.java
similarity index 100%
rename from tests/src/android/widget/cts/util/ListItemFactory.java
rename to tests/tests/widget/src/android/widget/cts/util/ListItemFactory.java
diff --git a/tests/src/android/widget/cts/util/ListScenario.java b/tests/tests/widget/src/android/widget/cts/util/ListScenario.java
similarity index 100%
rename from tests/src/android/widget/cts/util/ListScenario.java
rename to tests/tests/widget/src/android/widget/cts/util/ListScenario.java
diff --git a/tests/src/android/widget/cts/util/ListUtil.java b/tests/tests/widget/src/android/widget/cts/util/ListUtil.java
similarity index 100%
rename from tests/src/android/widget/cts/util/ListUtil.java
rename to tests/tests/widget/src/android/widget/cts/util/ListUtil.java
diff --git a/tests/webgl/Android.mk b/tests/webgl/Android.mk
new file mode 100755
index 0000000..ce22dd8
--- /dev/null
+++ b/tests/webgl/Android.mk
@@ -0,0 +1,34 @@
+# 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)
+
+include $(CLEAR_VARS)
+
+# Don't include this package in any target.
+LOCAL_MODULE_TAGS := optional
+
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil ctstestrunner
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# Must match the package name in CtsTestCaseList.mk
+LOCAL_PACKAGE_NAME := CtsWebGLTestCases
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/webgl/AndroidManifest.xml b/tests/webgl/AndroidManifest.xml
new file mode 100755
index 0000000..d648032
--- /dev/null
+++ b/tests/webgl/AndroidManifest.xml
@@ -0,0 +1,45 @@
+<?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.webgl.cts">
+
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+    <uses-permission android:name="android.permission.INTERNET" />
+
+    <application android:maxRecents="1">
+        <uses-library android:name="android.test.runner" />
+        <activity android:name="android.webgl.WebGLActivity" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+
+    <!--  self-instrumenting test package. -->
+    <instrumentation
+        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:label="CTS WebGL tests"
+        android:targetPackage="android.webgl.cts" >
+        <meta-data
+            android:name="listener"
+            android:value="com.android.cts.runner.CtsTestRunListener" />
+    </instrumentation>
+</manifest>
+
diff --git a/tests/webgl/res/raw/extract_webgl_tests.py b/tests/webgl/res/raw/extract_webgl_tests.py
new file mode 100755
index 0000000..1511632
--- /dev/null
+++ b/tests/webgl/res/raw/extract_webgl_tests.py
@@ -0,0 +1,69 @@
+# 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.
+
+import sys
+import os
+
+if len(sys.argv) != 3:
+  raise Exception("Usage: extract_webgl_tests.py <webgl_sdk_tests_path> <version>")
+
+top_list = sys.argv[1] + "/00_test_list.txt"
+version = sys.argv[2]
+tests = []
+lists = []
+lists.append(top_list)
+
+def filter_by_version(lines):
+  version_lines = [ line for line in lines if "--min-version" in line ]
+  version_lines.extend([ line for line in lines if "--max-version" in line ])
+  lines = [ line for line in lines if not line in version_lines ]
+  for line in version_lines:
+    assert len(line.split()) == 3
+    min_version = line.split()[1] if line.split()[0] == "--min-version" else "0.0.0"
+    max_version = line.split()[1] if line.split()[0] == "--max-version" else "9.9.9"
+    test = line.split()[2]
+    if (version >= min_version and version <= max_version):
+      lines.append(test)
+  return lines
+
+while not len(lists) == 0:
+  lists2 = lists
+  lists = []
+  for list in lists2:
+    directory = os.path.dirname(os.path.realpath(list))
+    with open(list) as file:
+      # Filter out comments and --min-version
+      lines = [ line.strip() for line in file.readlines()]
+      lines = [ line for line in lines if not "//" in line ]
+      lines = [ line for line in lines if not "#" in line ]
+      lines = [ line.replace("--slow","") for line in lines ]
+      lines = filter_by_version(lines)
+      # Append lists and tests found in this list.
+      lines = [ directory + "/" + line for line in lines ]
+      lists.extend([ line for line in lines if "00_test_list.txt" in line ])
+      tests.extend([ line for line in lines if ".html" in line ])
+
+# Directories for formating test-names/relative-paths.
+name_directory = os.path.dirname(os.path.realpath(top_list))
+path_directory = os.path.realpath(os.path.join(name_directory, os.pardir))
+
+tests = sorted(tests)
+for test in tests:
+  test_path = test.replace(path_directory + "/", "")
+  test_name = test.replace(name_directory + "/", "")
+  test_name = test_name.replace("/","_")
+  test_name = test_name.replace(".","_")
+  test_name = test_name.replace("-","_")
+  print "    public void test_" + test_name + "() throws Exception { doTest(\"" + test_path + "\"); }"
+
diff --git a/tests/webgl/res/raw/harness.html b/tests/webgl/res/raw/harness.html
new file mode 100644
index 0000000..5ae56ef
--- /dev/null
+++ b/tests/webgl/res/raw/harness.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!-- saved from url=(0057)http://www.corp.google.com/~vollick/timing-functions.html -->
+<html>
+<head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+
+<script type="text/javascript">
+    // Check for WebGL Support.
+    function supportsWebGL() {
+        var canvas = document.createElement('canvas');
+        gl = canvas.getContext("webgl");
+        return !!gl;
+    }
+
+    // Pass the WebGL harness calls through to the native app.
+    webglTestHarness = {
+        notifyFinished: function() {
+            WebGLCallback.notifyFinished();
+        },
+        reportResults: function(type, success, msg) {
+            WebGLCallback.reportResults(type, success, msg);
+        }
+    }
+    function navigateToTest() {
+        if (supportsWebGL())
+            window.open(WebGLCallback.getUrlToTest(), "TestFrame");
+        else
+            WebGLCallback.notifyFinished();
+    }
+    window.addEventListener('load', navigateToTest, false);
+</script>
+
+<style type="text/css">
+body, html { margin: 0; padding: 0; height: 100%; overflow: hidden; }
+#content { position:absolute; left: 0; right: 0; bottom: 0; top: 0px; }
+</style>
+
+</head>
+
+<body>
+  <div id="content">
+    <iframe name="TestFrame" width="100%" height="100%" frameborder="0"/>
+  </div>
+</body>
+</html>
diff --git a/tests/webgl/res/raw/webgl_sdk_tests.zip b/tests/webgl/res/raw/webgl_sdk_tests.zip
new file mode 100644
index 0000000..a2086b0
--- /dev/null
+++ b/tests/webgl/res/raw/webgl_sdk_tests.zip
Binary files differ
diff --git a/tests/webgl/src/android/webgl/WebGLActivity.java b/tests/webgl/src/android/webgl/WebGLActivity.java
new file mode 100644
index 0000000..3f911c4
--- /dev/null
+++ b/tests/webgl/src/android/webgl/WebGLActivity.java
@@ -0,0 +1,142 @@
+/*
+ * 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.webgl;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Resources;
+import android.cts.util.NullWebViewUtils;
+import android.os.Bundle;
+import android.util.Log;
+import android.webgl.cts.R;
+import android.webkit.WebView;
+import android.webkit.JavascriptInterface;
+import android.webkit.WebViewClient;
+import android.widget.Toast;
+import java.lang.Override;
+import java.io.InputStream;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A simple activity for testing WebGL Conformance with WebView.
+ */
+public class WebGLActivity extends Activity {
+
+    Semaphore mFinished = new Semaphore(0, false);
+    Semaphore mDestroyed = new Semaphore(0, false);
+    String mWebGlHarnessUrl;
+    WebView mWebView;
+
+    // The following members are synchronized.
+    String mWebGLTestUrl;
+    boolean mPassed = true;
+    StringBuilder mMessage = new StringBuilder("\n");
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        mWebGlHarnessUrl = "file://" + getCacheDir() + "/harness.html";
+        try {
+            mWebView = new WebView(this);
+        } catch (Exception e) {
+            NullWebViewUtils.determineIfWebViewAvailable(this, e);
+        }
+
+        if (mWebView == null) {
+            return;
+        }
+
+        mWebView.getSettings().setJavaScriptEnabled(true);
+        mWebView.getSettings().setAllowFileAccessFromFileURLs(true);
+        mWebView.getSettings().setMediaPlaybackRequiresUserGesture(false);
+        mWebView.setWebViewClient(new WebViewClient() {
+            @Override
+            public boolean shouldOverrideUrlLoading(WebView webView, String url) {
+                return false;
+            }
+        });
+
+        mWebView.addJavascriptInterface(new Object() {
+            @JavascriptInterface
+            public String getUrlToTest() {
+                synchronized(WebGLActivity.this) {
+                    return mWebGLTestUrl;
+                }
+            }
+
+            @JavascriptInterface
+            public void reportResults(String type, boolean success, String message) {
+                synchronized(WebGLActivity.this) {
+                    mMessage.append((success ? "PASS " : "FAIL ") + message + "\n");
+                    mPassed &= success;
+                }
+            }
+
+            @JavascriptInterface
+            public void notifyFinished() {
+                mFinished.release();
+            }
+
+            @JavascriptInterface
+            public void alert(String string) {
+                Log.i(mWebGLTestUrl, string);
+            }
+        }, "WebGLCallback");
+        setContentView(mWebView);
+    }
+
+    public void navigateToTest(String url) throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
+        synchronized(WebGLActivity.this) {
+            mWebGLTestUrl = url;
+        }
+
+        // Load harness.html, which will load mWebGLTestUrl in an <iframe>.
+        runOnUiThread(new Runnable() {
+            public void run() {
+                mWebView.loadUrl(mWebGlHarnessUrl);
+            }
+        });
+
+        // Wait on test completion.
+        boolean finished = mFinished.tryAcquire(60, TimeUnit.SECONDS);
+        String message;
+        synchronized(WebGLActivity.this) {
+            message = mMessage.toString();
+        }
+
+        // Destroy the webview and wait for it.
+        runOnUiThread(new Runnable() {
+            public void run() {
+                mWebView.destroy();
+                finish();
+                mDestroyed.release();
+            }
+        });
+        mDestroyed.acquire();
+
+        if (!finished)
+            throw new Exception("\n" + url + "\n Test timed-out after 60 seconds: " + message);
+        if(!mPassed)
+            throw new Exception("\n" + url + "\n Test failed: " + message);
+    }
+}
diff --git a/tests/webgl/src/android/webgl/cts/WebGLConformanceSuite.java b/tests/webgl/src/android/webgl/cts/WebGLConformanceSuite.java
new file mode 100644
index 0000000..60f663a
--- /dev/null
+++ b/tests/webgl/src/android/webgl/cts/WebGLConformanceSuite.java
@@ -0,0 +1,51 @@
+/*
+ * 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.webgl.cts;
+
+import android.util.Log;
+import android.webgl.cts.R;
+import android.webgl.WebGLActivity;
+import java.lang.Override;
+import java.io.File;
+import java.io.InputStream;
+
+/**
+ * A Singleton class to wrap the WebGL Conformance Test Suite.
+ */
+public class WebGLConformanceSuite {
+    private final String TAG = "WebGLConformanceSuite";
+    private static volatile WebGLConformanceSuite mInstance = null;
+
+    private WebGLConformanceSuite(WebGLActivity activity) throws Exception {
+        Log.i(TAG, "Unzipping WebGL Conformance Suite: "
+                + activity.getCacheDir().getPath());
+        InputStream suite = activity.getResources().openRawResource(R.raw.webgl_sdk_tests);
+        ZipUtil.unzipToPath(suite, activity.getCacheDir());
+        InputStream harness = activity.getResources().openRawResource(R.raw.harness);
+        ZipUtil.streamToPath(harness, activity.getCacheDir(), "harness.html");
+    }
+
+    public static WebGLConformanceSuite init(WebGLActivity activity)
+            throws Exception {
+        if (mInstance == null) {
+            synchronized (WebGLConformanceSuite.class) {
+                mInstance = new WebGLConformanceSuite(activity);
+            }
+        }
+        return mInstance;
+    }
+}
diff --git a/tests/webgl/src/android/webgl/cts/WebGLTest.java b/tests/webgl/src/android/webgl/cts/WebGLTest.java
new file mode 100644
index 0000000..d45c190
--- /dev/null
+++ b/tests/webgl/src/android/webgl/cts/WebGLTest.java
@@ -0,0 +1,419 @@
+/*
+ * 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.webgl.cts;
+
+import android.webgl.WebGLActivity;
+import android.webgl.cts.R;
+import android.test.ActivityInstrumentationTestCase2;
+import java.io.InputStream;
+
+/**
+ * A simple wrapper to load each WebGL conformance test in WebView.
+ *
+ * This test uses {@link android.test.ActivityInstrumentationTestCase2} to instrument the
+ * {@link android.webgl.WebGLActivity}.
+ */
+public class WebGLTest extends ActivityInstrumentationTestCase2<WebGLActivity> {
+
+    /**
+     * A reference to the activity whose shared preferences are being tested.
+     */
+    private WebGLActivity mActivity;
+    private WebGLConformanceSuite mWebGL_1_0_1;
+
+    public WebGLTest() {
+        super(WebGLActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        // Start the activity and get a reference to it.
+        mActivity = getActivity();
+        // Wait for the UI Thread to become idle.
+        getInstrumentation().waitForIdleSync();
+        mWebGL_1_0_1 = WebGLConformanceSuite.init(mActivity);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        // Scrub the activity so it can be freed. The next time the setUp will create a new activity
+        // rather than reusing the old one.
+        mActivity = null;
+        super.tearDown();
+    }
+
+    protected void doTest(String testPage) throws Exception {
+        mActivity.navigateToTest(testPage);
+    }
+
+    /**
+     * The remainder of this file is generated using this command:
+     * extract_webgl_tests.py tests 1.0.1
+     */
+    public void test_conformance_attribs_gl_enable_vertex_attrib_html() throws Exception { doTest("tests/conformance/attribs/gl-enable-vertex-attrib.html"); }
+    public void test_conformance_attribs_gl_vertex_attrib_zero_issues_html() throws Exception { doTest("tests/conformance/attribs/gl-vertex-attrib-zero-issues.html"); }
+    public void test_conformance_attribs_gl_vertex_attrib_html() throws Exception { doTest("tests/conformance/attribs/gl-vertex-attrib.html"); }
+    public void test_conformance_attribs_gl_vertexattribpointer_offsets_html() throws Exception { doTest("tests/conformance/attribs/gl-vertexattribpointer-offsets.html"); }
+    public void test_conformance_attribs_gl_vertexattribpointer_html() throws Exception { doTest("tests/conformance/attribs/gl-vertexattribpointer.html"); }
+    public void test_conformance_buffers_buffer_bind_test_html() throws Exception { doTest("tests/conformance/buffers/buffer-bind-test.html"); }
+    public void test_conformance_buffers_buffer_data_array_buffer_html() throws Exception { doTest("tests/conformance/buffers/buffer-data-array-buffer.html"); }
+    public void test_conformance_buffers_index_validation_copies_indices_html() throws Exception { doTest("tests/conformance/buffers/index-validation-copies-indices.html"); }
+    public void test_conformance_buffers_index_validation_crash_with_buffer_sub_data_html() throws Exception { doTest("tests/conformance/buffers/index-validation-crash-with-buffer-sub-data.html"); }
+    public void test_conformance_buffers_index_validation_verifies_too_many_indices_html() throws Exception { doTest("tests/conformance/buffers/index-validation-verifies-too-many-indices.html"); }
+    public void test_conformance_buffers_index_validation_with_resized_buffer_html() throws Exception { doTest("tests/conformance/buffers/index-validation-with-resized-buffer.html"); }
+    public void test_conformance_buffers_index_validation_html() throws Exception { doTest("tests/conformance/buffers/index-validation.html"); }
+    public void test_conformance_canvas_buffer_offscreen_test_html() throws Exception { doTest("tests/conformance/canvas/buffer-offscreen-test.html"); }
+    public void test_conformance_canvas_buffer_preserve_test_html() throws Exception { doTest("tests/conformance/canvas/buffer-preserve-test.html"); }
+    public void test_conformance_canvas_canvas_test_html() throws Exception { doTest("tests/conformance/canvas/canvas-test.html"); }
+    public void test_conformance_canvas_canvas_zero_size_html() throws Exception { doTest("tests/conformance/canvas/canvas-zero-size.html"); }
+    public void test_conformance_canvas_drawingbuffer_static_canvas_test_html() throws Exception { doTest("tests/conformance/canvas/drawingbuffer-static-canvas-test.html"); }
+    public void test_conformance_canvas_drawingbuffer_test_html() throws Exception { doTest("tests/conformance/canvas/drawingbuffer-test.html"); }
+    public void test_conformance_canvas_viewport_unchanged_upon_resize_html() throws Exception { doTest("tests/conformance/canvas/viewport-unchanged-upon-resize.html"); }
+    public void test_conformance_context_constants_and_properties_html() throws Exception { doTest("tests/conformance/context/constants-and-properties.html"); }
+    public void test_conformance_context_context_attributes_alpha_depth_stencil_antialias_html() throws Exception { doTest("tests/conformance/context/context-attributes-alpha-depth-stencil-antialias.html"); }
+    public void test_conformance_context_context_lost_restored_html() throws Exception { doTest("tests/conformance/context/context-lost-restored.html"); }
+    public void test_conformance_context_context_lost_html() throws Exception { doTest("tests/conformance/context/context-lost.html"); }
+    public void test_conformance_context_context_type_test_html() throws Exception { doTest("tests/conformance/context/context-type-test.html"); }
+    public void test_conformance_context_incorrect_context_object_behaviour_html() throws Exception { doTest("tests/conformance/context/incorrect-context-object-behaviour.html"); }
+    public void test_conformance_context_methods_html() throws Exception { doTest("tests/conformance/context/methods.html"); }
+    public void test_conformance_context_premultiplyalpha_test_html() throws Exception { doTest("tests/conformance/context/premultiplyalpha-test.html"); }
+    public void test_conformance_context_resource_sharing_test_html() throws Exception { doTest("tests/conformance/context/resource-sharing-test.html"); }
+    public void test_conformance_extensions_oes_standard_derivatives_html() throws Exception { doTest("tests/conformance/extensions/oes-standard-derivatives.html"); }
+    public void test_conformance_extensions_oes_texture_float_with_canvas_html() throws Exception { doTest("tests/conformance/extensions/oes-texture-float-with-canvas.html"); }
+    public void test_conformance_extensions_oes_texture_float_with_image_data_html() throws Exception { doTest("tests/conformance/extensions/oes-texture-float-with-image-data.html"); }
+    public void test_conformance_extensions_oes_texture_float_with_image_html() throws Exception { doTest("tests/conformance/extensions/oes-texture-float-with-image.html"); }
+    public void test_conformance_extensions_oes_texture_float_with_video_html() throws Exception { doTest("tests/conformance/extensions/oes-texture-float-with-video.html"); }
+    public void test_conformance_extensions_oes_texture_float_html() throws Exception { doTest("tests/conformance/extensions/oes-texture-float.html"); }
+    public void test_conformance_extensions_oes_vertex_array_object_html() throws Exception { doTest("tests/conformance/extensions/oes-vertex-array-object.html"); }
+    public void test_conformance_extensions_webgl_debug_renderer_info_html() throws Exception { doTest("tests/conformance/extensions/webgl-debug-renderer-info.html"); }
+    public void test_conformance_extensions_webgl_debug_shaders_html() throws Exception { doTest("tests/conformance/extensions/webgl-debug-shaders.html"); }
+    public void test_conformance_glsl_functions_glsl_function_abs_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-abs.html"); }
+    public void test_conformance_glsl_functions_glsl_function_acos_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-acos.html"); }
+    public void test_conformance_glsl_functions_glsl_function_asin_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-asin.html"); }
+    public void test_conformance_glsl_functions_glsl_function_atan_xy_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-atan-xy.html"); }
+    public void test_conformance_glsl_functions_glsl_function_atan_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-atan.html"); }
+    public void test_conformance_glsl_functions_glsl_function_ceil_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-ceil.html"); }
+    public void test_conformance_glsl_functions_glsl_function_clamp_float_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-clamp-float.html"); }
+    public void test_conformance_glsl_functions_glsl_function_clamp_gentype_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-clamp-gentype.html"); }
+    public void test_conformance_glsl_functions_glsl_function_cos_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-cos.html"); }
+    public void test_conformance_glsl_functions_glsl_function_cross_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-cross.html"); }
+    public void test_conformance_glsl_functions_glsl_function_distance_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-distance.html"); }
+    public void test_conformance_glsl_functions_glsl_function_dot_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-dot.html"); }
+    public void test_conformance_glsl_functions_glsl_function_faceforward_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-faceforward.html"); }
+    public void test_conformance_glsl_functions_glsl_function_floor_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-floor.html"); }
+    public void test_conformance_glsl_functions_glsl_function_fract_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-fract.html"); }
+    public void test_conformance_glsl_functions_glsl_function_length_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-length.html"); }
+    public void test_conformance_glsl_functions_glsl_function_max_float_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-max-float.html"); }
+    public void test_conformance_glsl_functions_glsl_function_max_gentype_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-max-gentype.html"); }
+    public void test_conformance_glsl_functions_glsl_function_min_float_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-min-float.html"); }
+    public void test_conformance_glsl_functions_glsl_function_min_gentype_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-min-gentype.html"); }
+    public void test_conformance_glsl_functions_glsl_function_mix_float_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-mix-float.html"); }
+    public void test_conformance_glsl_functions_glsl_function_mix_gentype_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-mix-gentype.html"); }
+    public void test_conformance_glsl_functions_glsl_function_mod_float_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-mod-float.html"); }
+    public void test_conformance_glsl_functions_glsl_function_mod_gentype_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-mod-gentype.html"); }
+    public void test_conformance_glsl_functions_glsl_function_normalize_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-normalize.html"); }
+    public void test_conformance_glsl_functions_glsl_function_reflect_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-reflect.html"); }
+    public void test_conformance_glsl_functions_glsl_function_sign_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-sign.html"); }
+    public void test_conformance_glsl_functions_glsl_function_sin_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-sin.html"); }
+    public void test_conformance_glsl_functions_glsl_function_smoothstep_float_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-smoothstep-float.html"); }
+    public void test_conformance_glsl_functions_glsl_function_smoothstep_gentype_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-smoothstep-gentype.html"); }
+    public void test_conformance_glsl_functions_glsl_function_step_float_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-step-float.html"); }
+    public void test_conformance_glsl_functions_glsl_function_step_gentype_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function-step-gentype.html"); }
+    public void test_conformance_glsl_functions_glsl_function_html() throws Exception { doTest("tests/conformance/glsl/functions/glsl-function.html"); }
+    public void test_conformance_glsl_implicit_add_int_float_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/add_int_float.vert.html"); }
+    public void test_conformance_glsl_implicit_add_int_mat2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/add_int_mat2.vert.html"); }
+    public void test_conformance_glsl_implicit_add_int_mat3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/add_int_mat3.vert.html"); }
+    public void test_conformance_glsl_implicit_add_int_mat4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/add_int_mat4.vert.html"); }
+    public void test_conformance_glsl_implicit_add_int_vec2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/add_int_vec2.vert.html"); }
+    public void test_conformance_glsl_implicit_add_int_vec3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/add_int_vec3.vert.html"); }
+    public void test_conformance_glsl_implicit_add_int_vec4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/add_int_vec4.vert.html"); }
+    public void test_conformance_glsl_implicit_add_ivec2_vec2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/add_ivec2_vec2.vert.html"); }
+    public void test_conformance_glsl_implicit_add_ivec3_vec3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/add_ivec3_vec3.vert.html"); }
+    public void test_conformance_glsl_implicit_add_ivec4_vec4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/add_ivec4_vec4.vert.html"); }
+    public void test_conformance_glsl_implicit_assign_int_to_float_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/assign_int_to_float.vert.html"); }
+    public void test_conformance_glsl_implicit_assign_ivec2_to_vec2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/assign_ivec2_to_vec2.vert.html"); }
+    public void test_conformance_glsl_implicit_assign_ivec3_to_vec3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/assign_ivec3_to_vec3.vert.html"); }
+    public void test_conformance_glsl_implicit_assign_ivec4_to_vec4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/assign_ivec4_to_vec4.vert.html"); }
+    public void test_conformance_glsl_implicit_construct_struct_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/construct_struct.vert.html"); }
+    public void test_conformance_glsl_implicit_divide_int_float_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/divide_int_float.vert.html"); }
+    public void test_conformance_glsl_implicit_divide_int_mat2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/divide_int_mat2.vert.html"); }
+    public void test_conformance_glsl_implicit_divide_int_mat3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/divide_int_mat3.vert.html"); }
+    public void test_conformance_glsl_implicit_divide_int_mat4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/divide_int_mat4.vert.html"); }
+    public void test_conformance_glsl_implicit_divide_int_vec2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/divide_int_vec2.vert.html"); }
+    public void test_conformance_glsl_implicit_divide_int_vec3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/divide_int_vec3.vert.html"); }
+    public void test_conformance_glsl_implicit_divide_int_vec4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/divide_int_vec4.vert.html"); }
+    public void test_conformance_glsl_implicit_divide_ivec2_vec2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/divide_ivec2_vec2.vert.html"); }
+    public void test_conformance_glsl_implicit_divide_ivec3_vec3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/divide_ivec3_vec3.vert.html"); }
+    public void test_conformance_glsl_implicit_divide_ivec4_vec4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/divide_ivec4_vec4.vert.html"); }
+    public void test_conformance_glsl_implicit_equal_int_float_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/equal_int_float.vert.html"); }
+    public void test_conformance_glsl_implicit_equal_ivec2_vec2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/equal_ivec2_vec2.vert.html"); }
+    public void test_conformance_glsl_implicit_equal_ivec3_vec3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/equal_ivec3_vec3.vert.html"); }
+    public void test_conformance_glsl_implicit_equal_ivec4_vec4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/equal_ivec4_vec4.vert.html"); }
+    public void test_conformance_glsl_implicit_function_int_float_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/function_int_float.vert.html"); }
+    public void test_conformance_glsl_implicit_function_ivec2_vec2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/function_ivec2_vec2.vert.html"); }
+    public void test_conformance_glsl_implicit_function_ivec3_vec3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/function_ivec3_vec3.vert.html"); }
+    public void test_conformance_glsl_implicit_function_ivec4_vec4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/function_ivec4_vec4.vert.html"); }
+    public void test_conformance_glsl_implicit_greater_than_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/greater_than.vert.html"); }
+    public void test_conformance_glsl_implicit_greater_than_equal_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/greater_than_equal.vert.html"); }
+    public void test_conformance_glsl_implicit_less_than_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/less_than.vert.html"); }
+    public void test_conformance_glsl_implicit_less_than_equal_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/less_than_equal.vert.html"); }
+    public void test_conformance_glsl_implicit_multiply_int_float_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/multiply_int_float.vert.html"); }
+    public void test_conformance_glsl_implicit_multiply_int_mat2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/multiply_int_mat2.vert.html"); }
+    public void test_conformance_glsl_implicit_multiply_int_mat3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/multiply_int_mat3.vert.html"); }
+    public void test_conformance_glsl_implicit_multiply_int_mat4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/multiply_int_mat4.vert.html"); }
+    public void test_conformance_glsl_implicit_multiply_int_vec2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/multiply_int_vec2.vert.html"); }
+    public void test_conformance_glsl_implicit_multiply_int_vec3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/multiply_int_vec3.vert.html"); }
+    public void test_conformance_glsl_implicit_multiply_int_vec4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/multiply_int_vec4.vert.html"); }
+    public void test_conformance_glsl_implicit_multiply_ivec2_vec2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/multiply_ivec2_vec2.vert.html"); }
+    public void test_conformance_glsl_implicit_multiply_ivec3_vec3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/multiply_ivec3_vec3.vert.html"); }
+    public void test_conformance_glsl_implicit_multiply_ivec4_vec4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/multiply_ivec4_vec4.vert.html"); }
+    public void test_conformance_glsl_implicit_not_equal_int_float_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/not_equal_int_float.vert.html"); }
+    public void test_conformance_glsl_implicit_not_equal_ivec2_vec2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/not_equal_ivec2_vec2.vert.html"); }
+    public void test_conformance_glsl_implicit_not_equal_ivec3_vec3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/not_equal_ivec3_vec3.vert.html"); }
+    public void test_conformance_glsl_implicit_not_equal_ivec4_vec4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/not_equal_ivec4_vec4.vert.html"); }
+    public void test_conformance_glsl_implicit_subtract_int_float_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/subtract_int_float.vert.html"); }
+    public void test_conformance_glsl_implicit_subtract_int_mat2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/subtract_int_mat2.vert.html"); }
+    public void test_conformance_glsl_implicit_subtract_int_mat3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/subtract_int_mat3.vert.html"); }
+    public void test_conformance_glsl_implicit_subtract_int_mat4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/subtract_int_mat4.vert.html"); }
+    public void test_conformance_glsl_implicit_subtract_int_vec2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/subtract_int_vec2.vert.html"); }
+    public void test_conformance_glsl_implicit_subtract_int_vec3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/subtract_int_vec3.vert.html"); }
+    public void test_conformance_glsl_implicit_subtract_int_vec4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/subtract_int_vec4.vert.html"); }
+    public void test_conformance_glsl_implicit_subtract_ivec2_vec2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/subtract_ivec2_vec2.vert.html"); }
+    public void test_conformance_glsl_implicit_subtract_ivec3_vec3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/subtract_ivec3_vec3.vert.html"); }
+    public void test_conformance_glsl_implicit_subtract_ivec4_vec4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/subtract_ivec4_vec4.vert.html"); }
+    public void test_conformance_glsl_implicit_ternary_int_float_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/ternary_int_float.vert.html"); }
+    public void test_conformance_glsl_implicit_ternary_ivec2_vec2_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/ternary_ivec2_vec2.vert.html"); }
+    public void test_conformance_glsl_implicit_ternary_ivec3_vec3_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/ternary_ivec3_vec3.vert.html"); }
+    public void test_conformance_glsl_implicit_ternary_ivec4_vec4_vert_html() throws Exception { doTest("tests/conformance/glsl/implicit/ternary_ivec4_vec4.vert.html"); }
+    public void test_conformance_glsl_misc_attrib_location_length_limits_html() throws Exception { doTest("tests/conformance/glsl/misc/attrib-location-length-limits.html"); }
+    public void test_conformance_glsl_misc_embedded_struct_definitions_forbidden_html() throws Exception { doTest("tests/conformance/glsl/misc/embedded-struct-definitions-forbidden.html"); }
+    public void test_conformance_glsl_misc_empty_main_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/empty_main.vert.html"); }
+    public void test_conformance_glsl_misc_gl_position_unset_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/gl_position_unset.vert.html"); }
+    public void test_conformance_glsl_misc_glsl_function_nodes_html() throws Exception { doTest("tests/conformance/glsl/misc/glsl-function-nodes.html"); }
+    public void test_conformance_glsl_misc_glsl_long_variable_names_html() throws Exception { doTest("tests/conformance/glsl/misc/glsl-long-variable-names.html"); }
+    public void test_conformance_glsl_misc_non_ascii_comments_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/non-ascii-comments.vert.html"); }
+    public void test_conformance_glsl_misc_non_ascii_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/non-ascii.vert.html"); }
+    public void test_conformance_glsl_misc_shader_with_256_character_identifier_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-256-character-identifier.frag.html"); }
+    public void test_conformance_glsl_misc_shader_with_257_character_identifier_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-257-character-identifier.frag.html"); }
+    public void test_conformance_glsl_misc_shader_with__webgl_identifier_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-_webgl-identifier.vert.html"); }
+    public void test_conformance_glsl_misc_shader_with_arbitrary_indexing_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-arbitrary-indexing.frag.html"); }
+    public void test_conformance_glsl_misc_shader_with_arbitrary_indexing_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-arbitrary-indexing.vert.html"); }
+    public void test_conformance_glsl_misc_shader_with_attrib_array_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-attrib-array.vert.html"); }
+    public void test_conformance_glsl_misc_shader_with_attrib_struct_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-attrib-struct.vert.html"); }
+    public void test_conformance_glsl_misc_shader_with_clipvertex_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-clipvertex.vert.html"); }
+    public void test_conformance_glsl_misc_shader_with_default_precision_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-default-precision.frag.html"); }
+    public void test_conformance_glsl_misc_shader_with_default_precision_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-default-precision.vert.html"); }
+    public void test_conformance_glsl_misc_shader_with_define_line_continuation_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-define-line-continuation.frag.html"); }
+    public void test_conformance_glsl_misc_shader_with_dfdx_no_ext_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-dfdx-no-ext.frag.html"); }
+    public void test_conformance_glsl_misc_shader_with_dfdx_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-dfdx.frag.html"); }
+    public void test_conformance_glsl_misc_shader_with_error_directive_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-error-directive.html"); }
+    public void test_conformance_glsl_misc_shader_with_explicit_int_cast_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-explicit-int-cast.vert.html"); }
+    public void test_conformance_glsl_misc_shader_with_float_return_value_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-float-return-value.frag.html"); }
+    public void test_conformance_glsl_misc_shader_with_frag_depth_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-frag-depth.frag.html"); }
+    public void test_conformance_glsl_misc_shader_with_function_recursion_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-function-recursion.frag.html"); }
+    public void test_conformance_glsl_misc_shader_with_glcolor_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-glcolor.vert.html"); }
+    public void test_conformance_glsl_misc_shader_with_gles_1_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-gles-1.frag.html"); }
+    public void test_conformance_glsl_misc_shader_with_gles_symbol_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-gles-symbol.frag.html"); }
+    public void test_conformance_glsl_misc_shader_with_glprojectionmatrix_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-glprojectionmatrix.vert.html"); }
+    public void test_conformance_glsl_misc_shader_with_implicit_vec3_to_vec4_cast_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-implicit-vec3-to-vec4-cast.vert.html"); }
+    public void test_conformance_glsl_misc_shader_with_include_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-include.vert.html"); }
+    public void test_conformance_glsl_misc_shader_with_int_return_value_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-int-return-value.frag.html"); }
+    public void test_conformance_glsl_misc_shader_with_invalid_identifier_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-invalid-identifier.frag.html"); }
+    public void test_conformance_glsl_misc_shader_with_ivec2_return_value_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-ivec2-return-value.frag.html"); }
+    public void test_conformance_glsl_misc_shader_with_ivec3_return_value_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-ivec3-return-value.frag.html"); }
+    public void test_conformance_glsl_misc_shader_with_ivec4_return_value_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-ivec4-return-value.frag.html"); }
+    public void test_conformance_glsl_misc_shader_with_limited_indexing_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-limited-indexing.frag.html"); }
+    public void test_conformance_glsl_misc_shader_with_long_line_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-long-line.html"); }
+    public void test_conformance_glsl_misc_shader_with_non_ascii_error_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-non-ascii-error.frag.html"); }
+    public void test_conformance_glsl_misc_shader_with_precision_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-precision.frag.html"); }
+    public void test_conformance_glsl_misc_shader_with_quoted_error_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-quoted-error.frag.html"); }
+    public void test_conformance_glsl_misc_shader_with_undefined_preprocessor_symbol_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-undefined-preprocessor-symbol.frag.html"); }
+    public void test_conformance_glsl_misc_shader_with_uniform_in_loop_condition_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-uniform-in-loop-condition.vert.html"); }
+    public void test_conformance_glsl_misc_shader_with_vec2_return_value_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-vec2-return-value.frag.html"); }
+    public void test_conformance_glsl_misc_shader_with_vec3_return_value_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-vec3-return-value.frag.html"); }
+    public void test_conformance_glsl_misc_shader_with_vec4_return_value_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-vec4-return-value.frag.html"); }
+    public void test_conformance_glsl_misc_shader_with_version_100_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-version-100.frag.html"); }
+    public void test_conformance_glsl_misc_shader_with_version_100_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-version-100.vert.html"); }
+    public void test_conformance_glsl_misc_shader_with_version_120_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-version-120.vert.html"); }
+    public void test_conformance_glsl_misc_shader_with_version_130_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-version-130.vert.html"); }
+    public void test_conformance_glsl_misc_shader_with_webgl_identifier_vert_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-with-webgl-identifier.vert.html"); }
+    public void test_conformance_glsl_misc_shader_without_precision_frag_html() throws Exception { doTest("tests/conformance/glsl/misc/shader-without-precision.frag.html"); }
+    public void test_conformance_glsl_misc_shared_html() throws Exception { doTest("tests/conformance/glsl/misc/shared.html"); }
+    public void test_conformance_glsl_misc_struct_nesting_exceeds_maximum_html() throws Exception { doTest("tests/conformance/glsl/misc/struct-nesting-exceeds-maximum.html"); }
+    public void test_conformance_glsl_misc_struct_nesting_under_maximum_html() throws Exception { doTest("tests/conformance/glsl/misc/struct-nesting-under-maximum.html"); }
+    public void test_conformance_glsl_misc_uniform_location_length_limits_html() throws Exception { doTest("tests/conformance/glsl/misc/uniform-location-length-limits.html"); }
+    public void test_conformance_glsl_reserved__webgl_field_vert_html() throws Exception { doTest("tests/conformance/glsl/reserved/_webgl_field.vert.html"); }
+    public void test_conformance_glsl_reserved__webgl_function_vert_html() throws Exception { doTest("tests/conformance/glsl/reserved/_webgl_function.vert.html"); }
+    public void test_conformance_glsl_reserved__webgl_struct_vert_html() throws Exception { doTest("tests/conformance/glsl/reserved/_webgl_struct.vert.html"); }
+    public void test_conformance_glsl_reserved__webgl_variable_vert_html() throws Exception { doTest("tests/conformance/glsl/reserved/_webgl_variable.vert.html"); }
+    public void test_conformance_glsl_reserved_webgl_field_vert_html() throws Exception { doTest("tests/conformance/glsl/reserved/webgl_field.vert.html"); }
+    public void test_conformance_glsl_reserved_webgl_function_vert_html() throws Exception { doTest("tests/conformance/glsl/reserved/webgl_function.vert.html"); }
+    public void test_conformance_glsl_reserved_webgl_struct_vert_html() throws Exception { doTest("tests/conformance/glsl/reserved/webgl_struct.vert.html"); }
+    public void test_conformance_glsl_reserved_webgl_variable_vert_html() throws Exception { doTest("tests/conformance/glsl/reserved/webgl_variable.vert.html"); }
+    public void test_conformance_glsl_variables_gl_fragcoord_html() throws Exception { doTest("tests/conformance/glsl/variables/gl-fragcoord.html"); }
+    public void test_conformance_glsl_variables_gl_frontfacing_html() throws Exception { doTest("tests/conformance/glsl/variables/gl-frontfacing.html"); }
+    public void test_conformance_glsl_variables_gl_pointcoord_html() throws Exception { doTest("tests/conformance/glsl/variables/gl-pointcoord.html"); }
+    public void test_conformance_limits_gl_max_texture_dimensions_html() throws Exception { doTest("tests/conformance/limits/gl-max-texture-dimensions.html"); }
+    public void test_conformance_limits_gl_min_attribs_html() throws Exception { doTest("tests/conformance/limits/gl-min-attribs.html"); }
+    public void test_conformance_limits_gl_min_textures_html() throws Exception { doTest("tests/conformance/limits/gl-min-textures.html"); }
+    public void test_conformance_limits_gl_min_uniforms_html() throws Exception { doTest("tests/conformance/limits/gl-min-uniforms.html"); }
+    public void test_conformance_misc_bad_arguments_test_html() throws Exception { doTest("tests/conformance/misc/bad-arguments-test.html"); }
+    public void test_conformance_misc_error_reporting_html() throws Exception { doTest("tests/conformance/misc/error-reporting.html"); }
+    public void test_conformance_misc_functions_returning_strings_html() throws Exception { doTest("tests/conformance/misc/functions-returning-strings.html"); }
+    public void test_conformance_misc_instanceof_test_html() throws Exception { doTest("tests/conformance/misc/instanceof-test.html"); }
+    public void test_conformance_misc_invalid_passed_params_html() throws Exception { doTest("tests/conformance/misc/invalid-passed-params.html"); }
+    public void test_conformance_misc_is_object_html() throws Exception { doTest("tests/conformance/misc/is-object.html"); }
+    public void test_conformance_misc_null_object_behaviour_html() throws Exception { doTest("tests/conformance/misc/null-object-behaviour.html"); }
+    public void test_conformance_misc_object_deletion_behaviour_html() throws Exception { doTest("tests/conformance/misc/object-deletion-behaviour.html"); }
+    public void test_conformance_misc_shader_precision_format_html() throws Exception { doTest("tests/conformance/misc/shader-precision-format.html"); }
+    public void test_conformance_misc_type_conversion_test_html() throws Exception { doTest("tests/conformance/misc/type-conversion-test.html"); }
+    public void test_conformance_misc_uninitialized_test_html() throws Exception { doTest("tests/conformance/misc/uninitialized-test.html"); }
+    public void test_conformance_misc_webgl_specific_html() throws Exception { doTest("tests/conformance/misc/webgl-specific.html"); }
+    public void test_conformance_more_conformance_constants_html() throws Exception { doTest("tests/conformance/more/conformance/constants.html"); }
+    public void test_conformance_more_conformance_getContext_html() throws Exception { doTest("tests/conformance/more/conformance/getContext.html"); }
+    public void test_conformance_more_conformance_methods_html() throws Exception { doTest("tests/conformance/more/conformance/methods.html"); }
+    public void test_conformance_more_conformance_quickCheckAPI_A_html() throws Exception { doTest("tests/conformance/more/conformance/quickCheckAPI-A.html"); }
+    public void test_conformance_more_conformance_quickCheckAPI_B1_html() throws Exception { doTest("tests/conformance/more/conformance/quickCheckAPI-B1.html"); }
+    public void test_conformance_more_conformance_quickCheckAPI_B2_html() throws Exception { doTest("tests/conformance/more/conformance/quickCheckAPI-B2.html"); }
+    public void test_conformance_more_conformance_quickCheckAPI_B3_html() throws Exception { doTest("tests/conformance/more/conformance/quickCheckAPI-B3.html"); }
+    public void test_conformance_more_conformance_quickCheckAPI_B4_html() throws Exception { doTest("tests/conformance/more/conformance/quickCheckAPI-B4.html"); }
+    public void test_conformance_more_conformance_quickCheckAPI_C_html() throws Exception { doTest("tests/conformance/more/conformance/quickCheckAPI-C.html"); }
+    public void test_conformance_more_conformance_quickCheckAPI_D_G_html() throws Exception { doTest("tests/conformance/more/conformance/quickCheckAPI-D_G.html"); }
+    public void test_conformance_more_conformance_quickCheckAPI_G_I_html() throws Exception { doTest("tests/conformance/more/conformance/quickCheckAPI-G_I.html"); }
+    public void test_conformance_more_conformance_quickCheckAPI_L_S_html() throws Exception { doTest("tests/conformance/more/conformance/quickCheckAPI-L_S.html"); }
+    public void test_conformance_more_conformance_quickCheckAPI_S_V_html() throws Exception { doTest("tests/conformance/more/conformance/quickCheckAPI-S_V.html"); }
+    public void test_conformance_more_conformance_webGLArrays_html() throws Exception { doTest("tests/conformance/more/conformance/webGLArrays.html"); }
+    public void test_conformance_more_functions_bindBuffer_html() throws Exception { doTest("tests/conformance/more/functions/bindBuffer.html"); }
+    public void test_conformance_more_functions_bindBufferBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/bindBufferBadArgs.html"); }
+    public void test_conformance_more_functions_bindFramebufferLeaveNonZero_html() throws Exception { doTest("tests/conformance/more/functions/bindFramebufferLeaveNonZero.html"); }
+    public void test_conformance_more_functions_bufferData_html() throws Exception { doTest("tests/conformance/more/functions/bufferData.html"); }
+    public void test_conformance_more_functions_bufferDataBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/bufferDataBadArgs.html"); }
+    public void test_conformance_more_functions_bufferSubData_html() throws Exception { doTest("tests/conformance/more/functions/bufferSubData.html"); }
+    public void test_conformance_more_functions_bufferSubDataBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/bufferSubDataBadArgs.html"); }
+    public void test_conformance_more_functions_copyTexImage2D_html() throws Exception { doTest("tests/conformance/more/functions/copyTexImage2D.html"); }
+    public void test_conformance_more_functions_copyTexImage2DBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/copyTexImage2DBadArgs.html"); }
+    public void test_conformance_more_functions_copyTexSubImage2D_html() throws Exception { doTest("tests/conformance/more/functions/copyTexSubImage2D.html"); }
+    public void test_conformance_more_functions_copyTexSubImage2DBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/copyTexSubImage2DBadArgs.html"); }
+    public void test_conformance_more_functions_deleteBufferBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/deleteBufferBadArgs.html"); }
+    public void test_conformance_more_functions_drawArrays_html() throws Exception { doTest("tests/conformance/more/functions/drawArrays.html"); }
+    public void test_conformance_more_functions_drawArraysOutOfBounds_html() throws Exception { doTest("tests/conformance/more/functions/drawArraysOutOfBounds.html"); }
+    public void test_conformance_more_functions_drawElements_html() throws Exception { doTest("tests/conformance/more/functions/drawElements.html"); }
+    public void test_conformance_more_functions_drawElementsBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/drawElementsBadArgs.html"); }
+    public void test_conformance_more_functions_isTests_html() throws Exception { doTest("tests/conformance/more/functions/isTests.html"); }
+    public void test_conformance_more_functions_readPixels_html() throws Exception { doTest("tests/conformance/more/functions/readPixels.html"); }
+    public void test_conformance_more_functions_readPixelsBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/readPixelsBadArgs.html"); }
+    public void test_conformance_more_functions_texImage2D_html() throws Exception { doTest("tests/conformance/more/functions/texImage2D.html"); }
+    public void test_conformance_more_functions_texImage2DBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/texImage2DBadArgs.html"); }
+    public void test_conformance_more_functions_texImage2DHTML_html() throws Exception { doTest("tests/conformance/more/functions/texImage2DHTML.html"); }
+    public void test_conformance_more_functions_texImage2DHTMLBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/texImage2DHTMLBadArgs.html"); }
+    public void test_conformance_more_functions_texSubImage2D_html() throws Exception { doTest("tests/conformance/more/functions/texSubImage2D.html"); }
+    public void test_conformance_more_functions_texSubImage2DBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/texSubImage2DBadArgs.html"); }
+    public void test_conformance_more_functions_texSubImage2DHTML_html() throws Exception { doTest("tests/conformance/more/functions/texSubImage2DHTML.html"); }
+    public void test_conformance_more_functions_texSubImage2DHTMLBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/texSubImage2DHTMLBadArgs.html"); }
+    public void test_conformance_more_functions_uniformMatrix_html() throws Exception { doTest("tests/conformance/more/functions/uniformMatrix.html"); }
+    public void test_conformance_more_functions_uniformMatrixBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/uniformMatrixBadArgs.html"); }
+    public void test_conformance_more_functions_uniformf_html() throws Exception { doTest("tests/conformance/more/functions/uniformf.html"); }
+    public void test_conformance_more_functions_uniformfArrayLen1_html() throws Exception { doTest("tests/conformance/more/functions/uniformfArrayLen1.html"); }
+    public void test_conformance_more_functions_uniformfBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/uniformfBadArgs.html"); }
+    public void test_conformance_more_functions_uniformi_html() throws Exception { doTest("tests/conformance/more/functions/uniformi.html"); }
+    public void test_conformance_more_functions_uniformiBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/uniformiBadArgs.html"); }
+    public void test_conformance_more_functions_vertexAttrib_html() throws Exception { doTest("tests/conformance/more/functions/vertexAttrib.html"); }
+    public void test_conformance_more_functions_vertexAttribBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/vertexAttribBadArgs.html"); }
+    public void test_conformance_more_functions_vertexAttribPointer_html() throws Exception { doTest("tests/conformance/more/functions/vertexAttribPointer.html"); }
+    public void test_conformance_more_functions_vertexAttribPointerBadArgs_html() throws Exception { doTest("tests/conformance/more/functions/vertexAttribPointerBadArgs.html"); }
+    public void test_conformance_more_glsl_arrayOutOfBounds_html() throws Exception { doTest("tests/conformance/more/glsl/arrayOutOfBounds.html"); }
+    public void test_conformance_more_glsl_uniformOutOfBounds_html() throws Exception { doTest("tests/conformance/more/glsl/uniformOutOfBounds.html"); }
+    public void test_conformance_programs_get_active_test_html() throws Exception { doTest("tests/conformance/programs/get-active-test.html"); }
+    public void test_conformance_programs_gl_bind_attrib_location_test_html() throws Exception { doTest("tests/conformance/programs/gl-bind-attrib-location-test.html"); }
+    public void test_conformance_programs_gl_get_active_attribute_html() throws Exception { doTest("tests/conformance/programs/gl-get-active-attribute.html"); }
+    public void test_conformance_programs_gl_get_active_uniform_html() throws Exception { doTest("tests/conformance/programs/gl-get-active-uniform.html"); }
+    public void test_conformance_programs_gl_getshadersource_html() throws Exception { doTest("tests/conformance/programs/gl-getshadersource.html"); }
+    public void test_conformance_programs_gl_shader_test_html() throws Exception { doTest("tests/conformance/programs/gl-shader-test.html"); }
+    public void test_conformance_programs_invalid_UTF_16_html() throws Exception { doTest("tests/conformance/programs/invalid-UTF-16.html"); }
+    public void test_conformance_programs_program_test_html() throws Exception { doTest("tests/conformance/programs/program-test.html"); }
+    public void test_conformance_reading_read_pixels_pack_alignment_html() throws Exception { doTest("tests/conformance/reading/read-pixels-pack-alignment.html"); }
+    public void test_conformance_reading_read_pixels_test_html() throws Exception { doTest("tests/conformance/reading/read-pixels-test.html"); }
+    public void test_conformance_renderbuffers_framebuffer_object_attachment_html() throws Exception { doTest("tests/conformance/renderbuffers/framebuffer-object-attachment.html"); }
+    public void test_conformance_renderbuffers_framebuffer_test_html() throws Exception { doTest("tests/conformance/renderbuffers/framebuffer-test.html"); }
+    public void test_conformance_renderbuffers_renderbuffer_initialization_html() throws Exception { doTest("tests/conformance/renderbuffers/renderbuffer-initialization.html"); }
+    public void test_conformance_rendering_draw_arrays_out_of_bounds_html() throws Exception { doTest("tests/conformance/rendering/draw-arrays-out-of-bounds.html"); }
+    public void test_conformance_rendering_draw_elements_out_of_bounds_html() throws Exception { doTest("tests/conformance/rendering/draw-elements-out-of-bounds.html"); }
+    public void test_conformance_rendering_gl_clear_html() throws Exception { doTest("tests/conformance/rendering/gl-clear.html"); }
+    public void test_conformance_rendering_gl_drawelements_html() throws Exception { doTest("tests/conformance/rendering/gl-drawelements.html"); }
+    public void test_conformance_rendering_gl_scissor_test_html() throws Exception { doTest("tests/conformance/rendering/gl-scissor-test.html"); }
+    public void test_conformance_rendering_line_loop_tri_fan_html() throws Exception { doTest("tests/conformance/rendering/line-loop-tri-fan.html"); }
+    public void test_conformance_rendering_more_than_65536_indices_html() throws Exception { doTest("tests/conformance/rendering/more-than-65536-indices.html"); }
+    public void test_conformance_rendering_multisample_corruption_html() throws Exception { doTest("tests/conformance/rendering/multisample-corruption.html"); }
+    public void test_conformance_rendering_point_size_html() throws Exception { doTest("tests/conformance/rendering/point-size.html"); }
+    public void test_conformance_rendering_triangle_html() throws Exception { doTest("tests/conformance/rendering/triangle.html"); }
+    public void test_conformance_state_gl_enable_enum_test_html() throws Exception { doTest("tests/conformance/state/gl-enable-enum-test.html"); }
+    public void test_conformance_state_gl_enum_tests_html() throws Exception { doTest("tests/conformance/state/gl-enum-tests.html"); }
+    public void test_conformance_state_gl_get_calls_html() throws Exception { doTest("tests/conformance/state/gl-get-calls.html"); }
+    public void test_conformance_state_gl_geterror_html() throws Exception { doTest("tests/conformance/state/gl-geterror.html"); }
+    public void test_conformance_state_gl_getstring_html() throws Exception { doTest("tests/conformance/state/gl-getstring.html"); }
+    public void test_conformance_state_gl_object_get_calls_html() throws Exception { doTest("tests/conformance/state/gl-object-get-calls.html"); }
+    public void test_conformance_textures_compressed_tex_image_html() throws Exception { doTest("tests/conformance/textures/compressed-tex-image.html"); }
+    public void test_conformance_textures_copy_tex_image_and_sub_image_2d_html() throws Exception { doTest("tests/conformance/textures/copy-tex-image-and-sub-image-2d.html"); }
+    public void test_conformance_textures_gl_pixelstorei_html() throws Exception { doTest("tests/conformance/textures/gl-pixelstorei.html"); }
+    public void test_conformance_textures_gl_teximage_html() throws Exception { doTest("tests/conformance/textures/gl-teximage.html"); }
+    public void test_conformance_textures_origin_clean_conformance_html() throws Exception { doTest("tests/conformance/textures/origin-clean-conformance.html"); }
+    public void test_conformance_textures_tex_image_and_sub_image_2d_with_array_buffer_view_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-array-buffer-view.html"); }
+    public void test_conformance_textures_tex_image_and_sub_image_2d_with_canvas_rgb565_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-canvas-rgb565.html"); }
+    public void test_conformance_textures_tex_image_and_sub_image_2d_with_canvas_rgba4444_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-canvas-rgba4444.html"); }
+    public void test_conformance_textures_tex_image_and_sub_image_2d_with_canvas_rgba5551_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-canvas-rgba5551.html"); }
+    public void test_conformance_textures_tex_image_and_sub_image_2d_with_canvas_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-canvas.html"); }
+    public void test_conformance_textures_tex_image_and_sub_image_2d_with_image_data_rgb565_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-image-data-rgb565.html"); }
+    public void test_conformance_textures_tex_image_and_sub_image_2d_with_image_data_rgba4444_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-image-data-rgba4444.html"); }
+    public void test_conformance_textures_tex_image_and_sub_image_2d_with_image_data_rgba5551_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-image-data-rgba5551.html"); }
+    public void test_conformance_textures_tex_image_and_sub_image_2d_with_image_data_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-image-data.html"); }
+    public void test_conformance_textures_tex_image_and_sub_image_2d_with_image_rgb565_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-image-rgb565.html"); }
+    public void test_conformance_textures_tex_image_and_sub_image_2d_with_image_rgba4444_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-image-rgba4444.html"); }
+    public void test_conformance_textures_tex_image_and_sub_image_2d_with_image_rgba5551_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-image-rgba5551.html"); }
+    public void test_conformance_textures_tex_image_and_sub_image_2d_with_image_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-image.html"); }
+    public void test_conformance_textures_tex_image_and_sub_image_2d_with_video_rgb565_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-video-rgb565.html"); }
+    public void test_conformance_textures_tex_image_and_sub_image_2d_with_video_rgba4444_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-video-rgba4444.html"); }
+    public void test_conformance_textures_tex_image_and_sub_image_2d_with_video_rgba5551_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-video-rgba5551.html"); }
+    public void test_conformance_textures_tex_image_and_sub_image_2d_with_video_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-sub-image-2d-with-video.html"); }
+    public void test_conformance_textures_tex_image_and_uniform_binding_bugs_html() throws Exception { doTest("tests/conformance/textures/tex-image-and-uniform-binding-bugs.html"); }
+    public void test_conformance_textures_tex_image_with_format_and_type_html() throws Exception { doTest("tests/conformance/textures/tex-image-with-format-and-type.html"); }
+    public void test_conformance_textures_tex_image_with_invalid_data_html() throws Exception { doTest("tests/conformance/textures/tex-image-with-invalid-data.html"); }
+    public void test_conformance_textures_tex_input_validation_html() throws Exception { doTest("tests/conformance/textures/tex-input-validation.html"); }
+    public void test_conformance_textures_tex_sub_image_2d_bad_args_html() throws Exception { doTest("tests/conformance/textures/tex-sub-image-2d-bad-args.html"); }
+    public void test_conformance_textures_tex_sub_image_2d_html() throws Exception { doTest("tests/conformance/textures/tex-sub-image-2d.html"); }
+    public void test_conformance_textures_texparameter_test_html() throws Exception { doTest("tests/conformance/textures/texparameter-test.html"); }
+    public void test_conformance_textures_texture_active_bind_2_html() throws Exception { doTest("tests/conformance/textures/texture-active-bind-2.html"); }
+    public void test_conformance_textures_texture_active_bind_html() throws Exception { doTest("tests/conformance/textures/texture-active-bind.html"); }
+    public void test_conformance_textures_texture_complete_html() throws Exception { doTest("tests/conformance/textures/texture-complete.html"); }
+    public void test_conformance_textures_texture_mips_html() throws Exception { doTest("tests/conformance/textures/texture-mips.html"); }
+    public void test_conformance_textures_texture_npot_video_html() throws Exception { doTest("tests/conformance/textures/texture-npot-video.html"); }
+    public void test_conformance_textures_texture_npot_html() throws Exception { doTest("tests/conformance/textures/texture-npot.html"); }
+    public void test_conformance_textures_texture_size_cube_maps_html() throws Exception { doTest("tests/conformance/textures/texture-size-cube-maps.html"); }
+    public void test_conformance_textures_texture_size_html() throws Exception { doTest("tests/conformance/textures/texture-size.html"); }
+    public void test_conformance_textures_texture_transparent_pixels_initialized_html() throws Exception { doTest("tests/conformance/textures/texture-transparent-pixels-initialized.html"); }
+    public void test_conformance_typedarrays_array_buffer_crash_html() throws Exception { doTest("tests/conformance/typedarrays/array-buffer-crash.html"); }
+    public void test_conformance_typedarrays_array_buffer_view_crash_html() throws Exception { doTest("tests/conformance/typedarrays/array-buffer-view-crash.html"); }
+    public void test_conformance_typedarrays_array_unit_tests_html() throws Exception { doTest("tests/conformance/typedarrays/array-unit-tests.html"); }
+    public void test_conformance_typedarrays_data_view_crash_html() throws Exception { doTest("tests/conformance/typedarrays/data-view-crash.html"); }
+    public void test_conformance_typedarrays_data_view_test_html() throws Exception { doTest("tests/conformance/typedarrays/data-view-test.html"); }
+    public void test_conformance_uniforms_gl_uniform_arrays_html() throws Exception { doTest("tests/conformance/uniforms/gl-uniform-arrays.html"); }
+    public void test_conformance_uniforms_gl_uniform_bool_html() throws Exception { doTest("tests/conformance/uniforms/gl-uniform-bool.html"); }
+    public void test_conformance_uniforms_gl_uniformmatrix4fv_html() throws Exception { doTest("tests/conformance/uniforms/gl-uniformmatrix4fv.html"); }
+    public void test_conformance_uniforms_gl_unknown_uniform_html() throws Exception { doTest("tests/conformance/uniforms/gl-unknown-uniform.html"); }
+    public void test_conformance_uniforms_null_uniform_location_html() throws Exception { doTest("tests/conformance/uniforms/null-uniform-location.html"); }
+    public void test_conformance_uniforms_uniform_location_html() throws Exception { doTest("tests/conformance/uniforms/uniform-location.html"); }
+    public void test_conformance_uniforms_uniform_samplers_test_html() throws Exception { doTest("tests/conformance/uniforms/uniform-samplers-test.html"); }
+}
diff --git a/tests/webgl/src/android/webgl/cts/ZipUtil.java b/tests/webgl/src/android/webgl/cts/ZipUtil.java
new file mode 100644
index 0000000..4b28e63
--- /dev/null
+++ b/tests/webgl/src/android/webgl/cts/ZipUtil.java
@@ -0,0 +1,117 @@
+/*
+ * 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.webgl.cts;
+
+import android.util.Log;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.String;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+
+/**
+ * Some boilerplate code to unzip files.
+ */
+public class ZipUtil {
+    private final static String TAG = "ZipUtil";
+
+    /**
+     * Stream to a file.
+     */
+    public static void streamToPath(InputStream is,
+                                  File directory,
+                                  String name) throws Exception {
+        File file = new File(directory, name);
+        streamToPath(is, file);
+    }
+
+    public static void streamToPath(InputStream is,
+                                  File file) throws Exception {
+        Log.i(TAG, "Streaming to path " + file.getPath());
+        OutputStream os = null;
+        os = new FileOutputStream(file);
+        int count = -1;
+        byte[] buffer = new byte[10 * 1024];
+        while ((count = is.read(buffer)) != -1) {
+            os.write(buffer, 0, count);
+        }
+        os.close();
+    }
+
+    /**
+     * Unzip to a directory.
+     */
+    public static void unzipToPath(InputStream is,
+                                   File filePath) throws Exception {
+        ZipInputStream zis = new ZipInputStream(is);
+        unzipToPath(zis, filePath.getPath());
+    }
+
+    public static void unzipToPath(ZipInputStream zis,
+                                   String path) throws Exception {
+        Log.i(TAG, "Unzipping to path " + path);
+        byte[] buffer = new byte[10 * 1024];
+        ZipEntry entry;
+        while ((entry = zis.getNextEntry()) != null) {
+            File entryFile = new File(path, entry.getName());
+            if (entry.isDirectory()) {
+                if (!entryFile.exists()) {
+                   entryFile.mkdirs();
+                }
+                continue;
+            }
+            if (entryFile.getParentFile() != null &&
+                    !entryFile.getParentFile().exists()) {
+                entryFile.getParentFile().mkdirs();
+            }
+            if (!entryFile.exists()) {
+                entryFile.createNewFile();
+                entryFile.setReadable(true);
+                entryFile.setExecutable(true);
+            }
+            streamToPath(zis, entryFile);
+        }
+        zis.close();
+    }
+
+    /**
+     * Cleanup a directory.
+     */
+    static public boolean deleteDirectory(String directoryPath) {
+        File path = new File(directoryPath);
+        return deleteDirectory(path);
+    }
+
+    static public boolean deleteDirectory(File path) {
+        if (path.exists()) {
+            File[] files = path.listFiles();
+            for(int i = 0; i < files.length; i++) {
+                if(files[i].isDirectory()) {
+                    deleteDirectory(files[i]);
+                } else {
+                    files[i].delete();
+                }
+            }
+            return path.delete();
+        }
+        return false;
+    }
+}
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsApiCoverage.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsApiCoverage.java
index 2109bbf..d596cba 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsApiCoverage.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsApiCoverage.java
@@ -176,8 +176,15 @@
         DexDepsXmlHandler dexDepsXmlHandler = new DexDepsXmlHandler(apiCoverage);
         xmlReader.setContentHandler(dexDepsXmlHandler);
 
-        Process process = new ProcessBuilder(dexdeps, "--format=xml", testApk.getPath()).start();
-        xmlReader.parse(new InputSource(process.getInputStream()));
+        String apkPath = testApk.getPath();
+        Process process = new ProcessBuilder(dexdeps, "--format=xml", apkPath).start();
+        try {
+            xmlReader.parse(new InputSource(process.getInputStream()));
+        } catch (SAXException e) {
+          // Catch this exception, but continue. SAXException is acceptable in cases
+          // where the apk does not contain a classes.dex and therefore parsing won't work.
+          System.err.println("warning: dexdeps failed for: " + apkPath);
+        }
     }
 
     private static void outputCoverageReport(ApiCoverage apiCoverage, List<File> testApks,
diff --git a/tools/cts-holo-generation/Android.mk b/tools/cts-holo-generation/Android.mk
index 5f12ef0..2affc5e 100644
--- a/tools/cts-holo-generation/Android.mk
+++ b/tools/cts-holo-generation/Android.mk
@@ -23,7 +23,7 @@
 LOCAL_DEX_PREOPT := false
 LOCAL_PROGUARD_ENABLED := disabled
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tools/cts-holo-generation/AndroidManifest.xml b/tools/cts-holo-generation/AndroidManifest.xml
index d7de891..ad4ae22 100644
--- a/tools/cts-holo-generation/AndroidManifest.xml
+++ b/tools/cts-holo-generation/AndroidManifest.xml
@@ -7,7 +7,7 @@
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 
     <instrumentation
-        android:name="android.test.InstrumentationTestRunner"
+        android:name="android.support.test.runner.AndroidJUnitRunner"
         android:targetPackage="com.android.cts.holo_capture" />
 
     <application>
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..78d4249 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("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());
+                                    }
                                 }
                             }
                         }
+                    } 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/cts-java-scanner/src/com/android/cts/javascanner/DocletRunner.java b/tools/cts-java-scanner/src/com/android/cts/javascanner/DocletRunner.java
index e56a7cf..06951b9 100644
--- a/tools/cts-java-scanner/src/com/android/cts/javascanner/DocletRunner.java
+++ b/tools/cts-java-scanner/src/com/android/cts/javascanner/DocletRunner.java
@@ -77,8 +77,6 @@
         sourcePath.add("./cts/tests/src");
         sourcePath.add("./cts/libs/commonutil/src");
         sourcePath.add("./cts/libs/deviceutil/src");
-        sourcePath.add("./frameworks/testing/uiautomator/library/testrunner-src");
-        sourcePath.add("./frameworks/testing/uiautomator_test_libraries/src");
         sourcePath.add(sourceDir.toString());
         return join(sourcePath, ":");
     }
@@ -86,6 +84,7 @@
     private String getClassPath() {
         List<String> classPath = new ArrayList<String>();
         classPath.add("./prebuilts/misc/common/tradefed/tradefed-prebuilt.jar");
+        classPath.add("./prebuilts/misc/common/ub-uiautomator/ub-uiautomator.jar");
         return join(classPath, ":");
     }
 
diff --git a/tools/cts-native-scanner/tests/Android.mk b/tools/cts-native-scanner/tests/Android.mk
index 6044b0d..29c5514 100644
--- a/tools/cts-native-scanner/tests/Android.mk
+++ b/tools/cts-native-scanner/tests/Android.mk
@@ -21,7 +21,7 @@
 
 LOCAL_MODULE := cts-native-scanner-tests
 LOCAL_MODULE_TAGS := optional
-LOCAL_JAVA_LIBRARIES := ddmlib-prebuilt tradefed-prebuilt cts-native-scanner
+LOCAL_JAVA_LIBRARIES := tradefed-prebuilt cts-native-scanner
 
 include $(BUILD_HOST_JAVA_LIBRARY)
 
diff --git a/tools/cts-reference-app-lib/Android.mk b/tools/cts-reference-app-lib/Android.mk
index 8341970..fae85b4 100644
--- a/tools/cts-reference-app-lib/Android.mk
+++ b/tools/cts-reference-app-lib/Android.mk
@@ -24,7 +24,7 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_SDK_VERSION := current
 
 LOCAL_MODULE := android.cts.refapp
 
diff --git a/tools/cts-xml-generator/src/Android.mk b/tools/cts-xml-generator/src/Android.mk
index 62f8692..a6d85b6 100644
--- a/tools/cts-xml-generator/src/Android.mk
+++ b/tools/cts-xml-generator/src/Android.mk
@@ -14,12 +14,14 @@
 
 LOCAL_PATH := $(call my-dir)
 
-
 # cts-xml-generator java library
 # ============================================================
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_SRC_FILES := \
+    $(call all-subdir-java-files) \
+    ../../../libs/commonutil/src/com/android/cts/util/AbiUtils.java
+
 LOCAL_JAR_MANIFEST := MANIFEST.mf
 
 LOCAL_MODULE := cts-xml-generator
diff --git a/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/CtsXmlGenerator.java b/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/CtsXmlGenerator.java
index c5b253a..f194edf 100644
--- a/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/CtsXmlGenerator.java
+++ b/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/CtsXmlGenerator.java
@@ -24,7 +24,9 @@
 
 import java.io.File;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Set;
 
 import javax.xml.parsers.DocumentBuilderFactory;
@@ -36,7 +38,8 @@
         System.err.println("Arguments: " + Arrays.asList(args));
         System.err.println("Usage: cts-xml-generator -p PACKAGE_NAME -n NAME [-t TEST_TYPE]"
                 + " [-j JAR_PATH] [-i INSTRUMENTATION] [-m MANIFEST_FILE] [-e EXPECTATION_FILE]"
-                + " [-o OUTPUT_FILE]");
+                + " [-b UNSUPPORTED_ABI_FILE] [-a ARCHITECTURE] [-o OUTPUT_FILE]"
+                + " [-s APP_NAME_SPACE] [-x ADDITIONAL_ATTRIBUTE_KEY->VALUE]");
         System.exit(1);
     }
 
@@ -45,12 +48,15 @@
         String name = null;
         String outputPath = null;
         Set<File> expectationFiles = new HashSet<File>();
+        Set<File> abiFiles = new HashSet<File>();
+        String architecture = null;
         File manifestFile = null;
         String instrumentation = null;
         String testType = null;
         String jarPath = null;
         String appNameSpace = null;
         String targetNameSpace = null;
+        Map<String, String> additionalAttributes = new HashMap<String, String>();
 
         for (int i = 0; i < args.length; i++) {
             if ("-p".equals(args[i])) {
@@ -68,12 +74,30 @@
             } else if ("-e".equals(args[i])) {
                 expectationFiles.add(new File(getArg(args, ++i,
                         "Missing value for expectation store")));
+            } else if ("-b".equals(args[i])) {
+                abiFiles.add(new File(getArg(args, ++i, "Missing value for abi store")));
+            } else if ("-a".equals(args[i])) {
+                architecture = getArg(args, ++i, "Missing value for architecture");
             } else if ("-o".equals(args[i])) {
                 outputPath = getArg(args, ++i, "Missing value for output file");
-            } else if ("-a".equals(args[i])) {
+            } else if ("-s".equals(args[i])) {
                 appNameSpace =  getArg(args, ++i, "Missing value for app name space");
             } else if ("-r".equals(args[i])) {
                 targetNameSpace =  getArg(args, ++i, "Missing value for target name space");
+            } else if ("-x".equals(args[i])) {
+                String value = getArg(args, ++i, "Missing value for additional attribute");
+                String[] tokens = value.split("->");
+                if (tokens.length != 2) {
+                    System.err.println(
+                            "For specifying additional attributes; use the format KEY->VALUE");
+                    usage(args);
+                }
+                if (additionalAttributes.containsKey(tokens[0])) {
+                    System.err.println(String.format(
+                            "Additional attribute %s has already been specified", tokens[0]));
+                    usage(args);
+                }
+                additionalAttributes.put(tokens[0], tokens[1]);
             } else {
                 System.err.println("Unsupported flag: " + args[i]);
                 usage(args);
@@ -101,9 +125,11 @@
             usage(args);
         }
 
-        ExpectationStore store = ExpectationStore.parse(expectationFiles, ModeId.DEVICE);
-        XmlGenerator generator = new XmlGenerator(store, appNameSpace, appPackageName,
-                name, runner, instrumentation, targetNameSpace, jarPath, testType, outputPath);
+        ExpectationStore failuresStore = ExpectationStore.parse(expectationFiles, ModeId.DEVICE);
+        ExpectationStore abiStore = ExpectationStore.parse(abiFiles, ModeId.DEVICE);
+        XmlGenerator generator = new XmlGenerator(failuresStore, abiStore, architecture,
+                appNameSpace, appPackageName, name, runner, instrumentation, targetNameSpace,
+                jarPath, testType, outputPath, additionalAttributes);
         generator.writePackageXml();
     }
 
diff --git a/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/XmlGenerator.java b/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/XmlGenerator.java
index 7b1996d..833bf69 100644
--- a/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/XmlGenerator.java
+++ b/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/XmlGenerator.java
@@ -16,6 +16,8 @@
 
 package com.android.cts.xmlgenerator;
 
+import com.android.cts.util.AbiUtils;
+
 import vogar.Expectation;
 import vogar.ExpectationStore;
 
@@ -27,7 +29,9 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Map;
 import java.util.List;
+import java.util.Set;
 
 /**
  * Generator of TestPackage XML files for native tests.
@@ -70,11 +74,19 @@
     private final String mOutputPath;
 
     /** ExpectationStore to filter out known failures. */
-    private final ExpectationStore mExpectations;
+    private final ExpectationStore mKnownFailures;
 
-    XmlGenerator(ExpectationStore expectations, String appNameSpace, String appPackageName,
-            String name, String runner, String targetBinaryName, String targetNameSpace,
-            String jarPath, String testType, String outputPath) {
+    /** ExpectationStore to filter out unsupported abis. */
+    private final ExpectationStore mUnsupportedAbis;
+
+    private final String mArchitecture;
+
+    private final Map<String, String> mAdditionalAttributes;
+
+    XmlGenerator(ExpectationStore knownFailures, ExpectationStore unsupportedAbis,
+            String architecture, String appNameSpace, String appPackageName, String name,
+            String runner, String targetBinaryName, String targetNameSpace, String jarPath,
+            String testType, String outputPath, Map<String, String> additionalAttributes) {
         mAppNamespace = appNameSpace;
         mAppPackageName = appPackageName;
         mName = name;
@@ -84,7 +96,10 @@
         mJarPath = jarPath;
         mTestType = testType;
         mOutputPath = outputPath;
-        mExpectations = expectations;
+        mKnownFailures = knownFailures;
+        mUnsupportedAbis = unsupportedAbis;
+        mArchitecture = architecture;
+        mAdditionalAttributes = additionalAttributes;
     }
 
     public void writePackageXml() throws IOException {
@@ -133,6 +148,10 @@
             writer.append(" jarPath=\"").append(mJarPath).append("\"");
         }
 
+        for (Map.Entry<String, String> entry : mAdditionalAttributes.entrySet()) {
+            writer.append(String.format(" %s=\"%s\"", entry.getKey(), entry.getValue()));
+        }
+
         writer.println(" version=\"1.0\">");
 
         TestListParser parser = new TestListParser();
@@ -183,9 +202,13 @@
             StringBuilder nameCollector) {
         Collection<Test> sorted = sortCollection(tests);
         for (Test test : sorted) {
+            String className = nameCollector.toString();
             nameCollector.append('#').append(test.getName());
             writer.append("<Test name=\"").append(test.getName()).append("\"");
-            if (isKnownFailure(mExpectations, nameCollector.toString())) {
+            String abis = getSupportedAbis(mUnsupportedAbis, mArchitecture,
+                    className, nameCollector.toString()).toString();
+            writer.append(" abis=\"" + abis.substring(1, abis.length() - 1) + "\"");
+            if (isKnownFailure(mKnownFailures, nameCollector.toString())) {
                 writer.append(" expectation=\"failure\"");
             }
             if (test.getTimeout() >= 0) {
@@ -207,4 +230,39 @@
     public static boolean isKnownFailure(ExpectationStore expectationStore, String testName) {
         return expectationStore != null && expectationStore.get(testName) != Expectation.SUCCESS;
     }
+
+    // Returns the list of ABIs supported by this TestCase on this architecture.
+    public static Set<String> getSupportedAbis(ExpectationStore expectationStore,
+            String architecture, String className, String testName) {
+        Set<String> supportedAbis = AbiUtils.getAbisForArch(architecture);
+        if (expectationStore == null) {
+            return supportedAbis;
+        }
+
+        removeUnsupportedAbis(expectationStore.get(className), supportedAbis);
+        removeUnsupportedAbis(expectationStore.get(testName), supportedAbis);
+        return supportedAbis;
+    }
+
+    public static void removeUnsupportedAbis(Expectation expectation, Set<String> supportedAbis) {
+        if (expectation == null) {
+            return;
+        }
+
+        String description = expectation.getDescription();
+        if (description.isEmpty()) {
+            return;
+        }
+
+        String[] unsupportedAbis = description.split(":")[1].split(",");
+        for (String a : unsupportedAbis) {
+            String abi = a.trim();
+            if (!AbiUtils.isAbiSupportedByCts(abi)) {
+                throw new RuntimeException(
+                        String.format("Unrecognised ABI %s in %s", abi, description));
+            }
+            supportedAbis.remove(abi);
+        }
+    }
+
 }
diff --git a/tools/dasm/src/dasm/DAsm.java b/tools/dasm/src/dasm/DAsm.java
index 72436acc..aa55a23 100644
--- a/tools/dasm/src/dasm/DAsm.java
+++ b/tools/dasm/src/dasm/DAsm.java
@@ -55,6 +55,7 @@
 import com.android.dx.rop.type.StdTypeList;
 import com.android.dx.rop.type.Type;
 import com.android.dx.rop.type.TypeList;
+import com.android.dx.rop.type.Prototype;
 import com.android.dx.util.IntList;
 
 import java.io.FileWriter;
@@ -84,7 +85,6 @@
 
     // options for dex output
     DexOptions dexOptions = new DexOptions();
-
     // file being processed
     DexFile dexFile;
     int line_num;
@@ -1522,8 +1522,12 @@
      * Creates processor of instruction list.
      */
     private void createOutputFinisher() {
-        if (output_finisher == null)
-            output_finisher = new OutputFinisher(dexOptions, 5, regs_count);
+        if (output_finisher == null) {
+            dexOptions.ALIGN_64BIT_REGS_IN_OUTPUT_FINISHER = false;
+            int paramSize = Prototype.intern(method_nat.getDescriptor()
+                .getString()).getParameterTypes().getWordCount();
+            output_finisher = new OutputFinisher(dexOptions, 5, regs_count, paramSize);
+        }
     }
 
     /**
diff --git a/tools/device-setup/TestDeviceSetup/Android.mk b/tools/device-setup/TestDeviceSetup/Android.mk
index ba1998c..44e66bb 100644
--- a/tools/device-setup/TestDeviceSetup/Android.mk
+++ b/tools/device-setup/TestDeviceSetup/Android.mk
@@ -25,8 +25,6 @@
 LOCAL_DEX_PREOPT := false
 LOCAL_PROGUARD_ENABLED := disabled
 
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
 LOCAL_SDK_VERSION := current
 
 LOCAL_PACKAGE_NAME := TestDeviceSetup
diff --git a/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoActivity.java b/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoActivity.java
index ed82b08..00845bd 100644
--- a/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoActivity.java
+++ b/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoActivity.java
@@ -57,6 +57,7 @@
             final CountDownLatch done = new CountDownLatch(1);
             final int version = i;
             DeviceInfoActivity.this.runOnUiThread(new Runnable() {
+                @Override
                 public void run() {
                     setContentView(new GLESSurfaceView(DeviceInfoActivity.this, version, done));
                 }
@@ -121,6 +122,7 @@
         ConfigurationInfo info = am.getDeviceConfigurationInfo();
         final int glVersion = (info.reqGlEsVersion & 0xffff0000) >> 16;
         new Thread() {
+            @Override
             public void run() {
                 runIterations(glVersion);
             }
diff --git a/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoConstants.java b/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoConstants.java
index d77a44c..1eb4acb 100644
--- a/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoConstants.java
+++ b/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoConstants.java
@@ -51,6 +51,9 @@
     public static final String VERSION_RELEASE = "buildVersion";
     public static final String BUILD_ABI = "build_abi";
     public static final String BUILD_ABI2 = "build_abi2";
+    public static final String BUILD_ABIS = "build_abis";
+    public static final String BUILD_ABIS_32 = "build_abis_32";
+    public static final String BUILD_ABIS_64 = "build_abis_64";
     public static final String BUILD_FINGERPRINT = "build_fingerprint";
     public static final String BUILD_TYPE = "build_type";
     public static final String BUILD_MODEL = "build_model";
diff --git a/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoInstrument.java b/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoInstrument.java
index cdf1df3..19349e5 100644
--- a/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoInstrument.java
+++ b/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoInstrument.java
@@ -28,6 +28,7 @@
 import android.os.Environment;
 import android.os.UserManager;
 import android.telephony.TelephonyManager;
+import android.text.TextUtils;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.Display;
@@ -38,6 +39,7 @@
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Scanner;
@@ -71,6 +73,9 @@
         addResult(BUILD_FINGERPRINT, Build.FINGERPRINT);
         addResult(BUILD_ABI, Build.CPU_ABI);
         addResult(BUILD_ABI2, Build.CPU_ABI2);
+        addResult(BUILD_ABIS, TextUtils.join(",", Build.SUPPORTED_ABIS));
+        addResult(BUILD_ABIS_32, TextUtils.join(",", Build.SUPPORTED_32_BIT_ABIS));
+        addResult(BUILD_ABIS_64, TextUtils.join(",", Build.SUPPORTED_64_BIT_ABIS));
         addResult(SERIAL_NUMBER, Build.SERIAL);
 
         addResult(VERSION_RELEASE, Build.VERSION.RELEASE);
@@ -163,7 +168,7 @@
      * @param key the string of the key name.
      * @param value integer value.
      */
-    private void addResult(final String key, final int value){
+    static void addResult(final String key, final int value){
         mResults.putInt(key, value);
     }
 
@@ -173,7 +178,7 @@
      * @param key the string of the key name.
      * @param value float value.
      */
-    private void addResult(final String key, final float value){
+    static void addResult(final String key, final float value){
         mResults.putFloat(key, value);
     }
 
@@ -361,7 +366,6 @@
                 count, getContext().getExternalFilesDirs(Environment.DIRECTORY_PICTURES).length);
         count = Math.max(count, getContext().getObbDirs().length);
 
-        final String result;
         if (Environment.isExternalStorageEmulated()) {
             if (count == 1) {
                 return "1 emulated";
diff --git a/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/GLESSurfaceView.java b/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/GLESSurfaceView.java
index 1d3bf7f..04289e9 100644
--- a/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/GLESSurfaceView.java
+++ b/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/GLESSurfaceView.java
@@ -16,7 +16,6 @@
 
 package android.tests.getinfo;
 
-import android.content.Context;
 import android.opengl.GLES20;
 import android.opengl.GLES30;
 import android.opengl.GLSurfaceView;
@@ -89,7 +88,7 @@
                     }
                 }
             }
-
+            scanner.close();
             mDone.countDown();
         }
 
diff --git a/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/RootProcessScanner.java b/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/RootProcessScanner.java
index fefff99..d8018a1 100644
--- a/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/RootProcessScanner.java
+++ b/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/RootProcessScanner.java
@@ -146,13 +146,13 @@
         try {
             scanner = new Scanner(status);
 
-            scanner = findToken(scanner, "Name:");
+            findToken(scanner, "Name:");
             String name = scanner.next();
 
-            scanner = findToken(scanner, "Uid:");
+            findToken(scanner, "Uid:");
             boolean rootUid = hasRootId(scanner);
 
-            scanner = findToken(scanner, "Gid:");
+            findToken(scanner, "Gid:");
             boolean rootGid = hasRootId(scanner);
 
             return !ROOT_PROCESS_WHITELIST_PATTERN.matcher(name).matches()
@@ -182,13 +182,12 @@
      *
      * @param scanner to call next() until the token is found
      * @param token to find like "Name:"
-     * @return scanner after finding token
      */
-    private static Scanner findToken(Scanner scanner, String token) {
+    private static void findToken(Scanner scanner, String token) {
         while (true) {
             String next = scanner.next();
             if (next.equals(token)) {
-                return scanner;
+                return;
             }
         }
 
@@ -214,7 +213,7 @@
         File status = getProcessStatus(processDir);
         Scanner scanner = new Scanner(status);
         try {
-            scanner = findToken(scanner, "Name:");
+            findToken(scanner, "Name:");
             return scanner.next();
         } finally {
             scanner.close();
diff --git a/tools/junit/Android.mk b/tools/junit/Android.mk
new file mode 100644
index 0000000..b581149
--- /dev/null
+++ b/tools/junit/Android.mk
@@ -0,0 +1,23 @@
+# 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)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES :=  $(call all-java-files-under, src)
+LOCAL_MODULE := cts-junit
+LOCAL_MODULE_TAGS := optional
+LOCAL_STATIC_JAVA_LIBRARIES := junit4-target
+LOCAL_DEX_PREOPT := false
+include $(BUILD_JAVA_LIBRARY)
diff --git a/tools/junit/src/com/android/cts/junit/SingleJUnitTestRunListener.java b/tools/junit/src/com/android/cts/junit/SingleJUnitTestRunListener.java
new file mode 100644
index 0000000..06e9bc46
--- /dev/null
+++ b/tools/junit/src/com/android/cts/junit/SingleJUnitTestRunListener.java
@@ -0,0 +1,67 @@
+/*
+ * 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 com.android.cts.junit;
+
+import org.junit.runner.Description;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+
+public class SingleJUnitTestRunListener extends RunListener {
+    private static class Prefixes {
+        @SuppressWarnings("unused")
+        private static final String INFORMATIONAL_MARKER = "[----------]";
+        private static final String START_TEST_RUN_MARKER = "[==========] Running";
+        private static final String TEST_RUN_MARKER = "[==========]";
+        private static final String START_TEST_MARKER = "[ RUN      ]";
+        private static final String OK_TEST_MARKER = "[       OK ]";
+        private static final String FAILED_TEST_MARKER = "[  FAILED  ]";
+    }
+
+    @Override
+    public void testRunStarted(Description description) throws Exception {
+    }
+
+    @Override
+    public void testRunFinished(Result result) throws Exception {
+        String status = result.wasSuccessful() ? Prefixes.OK_TEST_MARKER
+                : Prefixes.FAILED_TEST_MARKER;
+        System.out.println(status);
+    }
+
+    @Override
+    public void testStarted(Description description) throws Exception {
+        System.out.println(String.format("%s %s.%s", Prefixes.START_TEST_MARKER,
+                description.getClassName(), description.getMethodName()));
+    }
+
+    @Override
+    public void testFinished(Description description) throws Exception {
+    }
+
+    @Override
+    public void testFailure(Failure failure) throws Exception {
+    }
+
+    @Override
+    public void testAssumptionFailure(Failure failure) {
+    }
+
+    @Override
+    public void testIgnored(Description description) throws Exception {
+    }
+}
diff --git a/tools/junit/src/com/android/cts/junit/SingleJUnitTestRunner.java b/tools/junit/src/com/android/cts/junit/SingleJUnitTestRunner.java
new file mode 100644
index 0000000..2eb9f3a
--- /dev/null
+++ b/tools/junit/src/com/android/cts/junit/SingleJUnitTestRunner.java
@@ -0,0 +1,48 @@
+/*
+ * 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 com.android.cts.junit;
+
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Request;
+import org.junit.runner.Result;
+
+/**
+ * Test runner to run a single JUnit test. It will output either [PASSED] or [FAILED] at the end.
+ */
+public class SingleJUnitTestRunner {
+    private static String mUsage = "Usage: java -cp <classpath> SingleJUnitTestRunner" +
+            " class#testmethod";
+    private static final String PASSED_TEST_MARKER = "[ PASSED ]";
+    private static final String FAILED_TEST_MARKER = "[ FAILED ]";
+
+    public static void main(String... args) throws ClassNotFoundException {
+        if (args.length != 1) {
+            throw new IllegalArgumentException(mUsage);
+        }
+        String[] classAndMethod = args[0].split("#");
+        if (classAndMethod.length != 2) {
+            throw new IllegalArgumentException(mUsage);
+        }
+        Request request = Request.method(Class.forName(classAndMethod[0]),
+                classAndMethod[1]);
+        JUnitCore jUnitCore = new JUnitCore();
+        Result result = jUnitCore.run(request);
+        String status = result.wasSuccessful() ? PASSED_TEST_MARKER : FAILED_TEST_MARKER;
+        System.out.println(String.format("%s %s.%s", status,
+                classAndMethod[0], classAndMethod[1]));
+    }
+}
diff --git a/tools/selinux/src/SELinux_CTS.py b/tools/selinux/src/SELinux_CTS.py
new file mode 100644
index 0000000..ec12be0e
--- /dev/null
+++ b/tools/selinux/src/SELinux_CTS.py
@@ -0,0 +1,542 @@
+import pdb
+import re
+from xml.etree.ElementTree import Element, SubElement, tostring
+
+#define equivalents
+TYPE = 0
+ATTRIBUTE = 1
+TYPEATTRIBUTE = 2
+CLASS = 3
+COMMON = 4
+ALLOW_RULE = 5
+NEVERALLOW_RULE = 6
+OTHER = 7
+
+#define helper methods
+# advance_past_whitespace(): helper function to skip whitespace at current
+# position in file.
+# returns: the non-whitespace character at the file's new position
+#TODO: should I deal with comments here as well?
+def advance_past_whitespace(file_obj):
+    c = file_obj.read(1)
+    while c.isspace():
+        c = file_obj.read(1)
+    file_obj.seek(-1, 1)
+    return c
+
+# advance_until_whitespace(): helper function to grab the string represented
+# by the current position in file until next whitespace.
+# returns: string until next whitespace.  overlooks comments.
+def advance_until_whitespace(file_obj):
+    ret_string = ""
+    c = file_obj.read(1)
+    #TODO: make a better way to deal with ':' and ';'
+    while not (c.isspace() or c == ':' or c == '' or c == ';'):
+        #don't count comments
+        if c == '#':
+            file_obj.readline()
+            return ret_string
+        else:
+            ret_string+=c
+            c = file_obj.read(1)
+    if not c == ':':
+        file_obj.seek(-1, 1)
+    return ret_string
+
+# expand_avc_rule - takes a processed avc rule and converts it into a list of
+# 4-tuples for use in an access check of form:
+    # (source_type, target_type, class, permission)
+def expand_avc_rule(policy, avc_rule):
+    ret_list = [ ]
+
+    #expand source_types
+    source_types = avc_rule['source_types']['set']
+    source_types = policy.expand_types(source_types)
+    if(avc_rule['source_types']['flags']['complement']):
+        #TODO: deal with negated 'self', not present in current policy.conf, though (I think)
+        source_types = policy.types - source_types #complement these types
+    if len(source_types) == 0:
+        print "ERROR: source_types empty after expansion"
+        print "Before: "
+        print avc_rule['source_types']['set']
+        return
+
+    #expand target_types
+    target_types = avc_rule['target_types']['set']
+    target_types = policy.expand_types(target_types)
+    if(avc_rule['target_types']['flags']['complement']):
+        #TODO: deal with negated 'self', not present in current policy.conf, though (I think)
+        target_types = policy.types - target_types #complement these types
+    if len(target_types) == 0:
+        print "ERROR: target_types empty after expansion"
+        print "Before: "
+        print avc_rule['target_types']['set']
+        return
+
+    # get classes
+    rule_classes = avc_rule['classes']['set']
+    if '' in rule_classes:
+        print "FOUND EMPTY STRING IN CLASSES"
+        print "Total sets:"
+        print avc_rule['source_types']['set']
+        print avc_rule['target_types']['set']
+        print rule_classes
+        print avc_rule['permissions']['set']
+
+    if len(rule_classes) == 0:
+        print "ERROR: empy set of object classes in avc rule"
+        return
+
+    # get permissions
+    permissions = avc_rule['permissions']['set']
+    if len(permissions) == 0:
+        print "ERROR: empy set of permissions in avc rule\n"
+        return
+
+    #create the list with collosal nesting, n^4 baby!
+    for s in source_types:
+        for t in target_types:
+            for c in rule_classes:
+                if c == '':
+                   continue
+                #expand permissions on a per-class basis
+                exp_permissions = policy.expand_permissions(c, permissions)
+                if(avc_rule['permissions']['flags']['complement']):
+                    exp_permissions = policy.classes[c] - exp_permissions
+                if len(exp_permissions) == 0:
+                    print "ERROR: permissions empty after expansion\n"
+                    print "Before: "
+                    print avc_rule['permissions']['set']
+                    return
+                for p in exp_permissions:
+                    source = s
+                    if t == 'self':
+                        target = s
+                    else:
+                        target = t
+                    obj_class = c
+                    permission = p
+                    ret_list.append((source, target, obj_class, permission))
+    return ret_list
+
+# expand_avc_rule - takes a processed avc rule and converts it into an xml
+# representation with the information needed in a checkSELinuxAccess() call.
+# (source_type, target_type, class, permission)
+def expand_avc_rule_to_xml(policy, avc_rule, rule_name, rule_type):
+    rule_xml = Element('avc_rule')
+    rule_xml.set('name', rule_name)
+    rule_xml.set('type', rule_type)
+
+    #expand source_types
+    source_types = avc_rule['source_types']['set']
+    source_types = policy.expand_types(source_types)
+    if(avc_rule['source_types']['flags']['complement']):
+        #TODO: deal with negated 'self', not present in current policy.conf, though (I think)
+        source_types = policy.types - source_types #complement these types
+    if len(source_types) == 0:
+        print "ERROR: source_types empty after expansion"
+        print "Before: "
+        print avc_rule['source_types']['set']
+        return
+    for s in source_types:
+        elem = SubElement(rule_xml, 'type')
+        elem.set('type', 'source')
+        elem.text = s
+
+    #expand target_types
+    target_types = avc_rule['target_types']['set']
+    target_types = policy.expand_types(target_types)
+    if(avc_rule['target_types']['flags']['complement']):
+        #TODO: deal with negated 'self', not present in current policy.conf, though (I think)
+        target_types = policy.types - target_types #complement these types
+    if len(target_types) == 0:
+        print "ERROR: target_types empty after expansion"
+        print "Before: "
+        print avc_rule['target_types']['set']
+        return
+    for t in target_types:
+        elem = SubElement(rule_xml, 'type')
+        elem.set('type', 'target')
+        elem.text = t
+
+    # get classes
+    rule_classes = avc_rule['classes']['set']
+
+    if len(rule_classes) == 0:
+        print "ERROR: empy set of object classes in avc rule"
+        return
+
+    # get permissions
+    permissions = avc_rule['permissions']['set']
+    if len(permissions) == 0:
+        print "ERROR: empy set of permissions in avc rule\n"
+        return
+
+    # permissions are class-dependent, so bundled together
+    for c in rule_classes:
+        if c == '':
+            print "AH!!! empty class found!\n"
+            continue
+        c_elem = SubElement(rule_xml, 'obj_class')
+        c_elem.set('name', c)
+        #expand permissions on a per-class basis
+        exp_permissions = policy.expand_permissions(c, permissions)
+        if(avc_rule['permissions']['flags']['complement']):
+            exp_permissions = policy.classes[c] - exp_permissions
+        if len(exp_permissions) == 0:
+            print "ERROR: permissions empty after expansion\n"
+            print "Before: "
+            print avc_rule['permissions']['set']
+            return
+
+        for p in exp_permissions:
+            p_elem = SubElement(c_elem, 'permission')
+            p_elem.text = p
+
+    return rule_xml
+
+# expand_brackets - helper function which reads a file into a string until '{ }'s
+# are balanced.  Brackets are removed from the string.  This function is based
+# on the understanding that nested brackets in our policy.conf file occur only due
+# to macro expansion, and we just need to know how much is included in a given
+# policy sub-component.
+def expand_brackets(file_obj):
+    ret_string = ""
+    c = file_obj.read(1)
+    if not c == '{':
+        print "Invalid bracket expression: " + c + "\n"
+        file_obj.seek(-1, 1)
+        return ""
+    else:
+        bracket_count = 1
+    while bracket_count > 0:
+        c = file_obj.read(1)
+        if c == '{':
+            bracket_count+=1
+        elif c == '}':
+            bracket_count-=1
+        elif c == '#':
+            #get rid of comment and replace with whitespace
+            file_obj.readline()
+            ret_string+=' '
+        else:
+            ret_string+=c
+    return ret_string
+
+# get_avc_rule_component - grabs the next component from an avc rule.  Basically,
+# just reads the next word or bracketed set of words.
+# returns - a set of the word, or words with metadata
+def get_avc_rule_component(file_obj):
+    ret_dict = { 'flags': {}, 'set': set() }
+    c = advance_past_whitespace(file_obj)
+    if c == '~':
+        ret_dict['flags']['complement'] = True
+        file_obj.read(1) #move to next char
+        c = advance_past_whitespace(file_obj)
+    else:
+        ret_dict['flags']['complement'] = False
+    if not c == '{':
+        #TODO: change operations on file to operations on string?
+        single_type =  advance_until_whitespace(file_obj)
+        ret_dict['set'].add(single_type)
+    else:
+        mult_types = expand_brackets(file_obj)
+        mult_types = mult_types.split()
+        for t in mult_types:
+            ret_dict['set'].add(t)
+    return ret_dict
+
+def get_line_type(line):
+    if re.search(r'^type\s', line):
+        return TYPE
+    if re.search(r'^attribute\s', line):
+        return ATTRIBUTE
+    if re.search(r'^typeattribute\s', line):
+        return TYPEATTRIBUTE
+    if re.search(r'^class\s', line):
+        return CLASS
+    if re.search(r'^common\s', line):
+        return COMMON
+    if re.search(r'^allow\s', line):
+        return ALLOW_RULE
+    if re.search(r'^neverallow\s', line):
+        return NEVERALLOW_RULE
+    else:
+        return OTHER
+
+def is_multi_line(line_type):
+    if line_type == CLASS:
+        return True
+    elif line_type == COMMON:
+        return True
+    elif line_type == ALLOW_RULE:
+        return True
+    elif line_type == NEVERALLOW_RULE:
+        return True
+    else:
+        return False
+
+
+#should only be called with file pointing to the 'i' in 'inherits' segment
+def process_inherits_segment(file_obj):
+    inherit_keyword = file_obj.read(8)
+    if not inherit_keyword == 'inherits':
+        #TODO: handle error, invalid class statement
+        print "ERROR: invalid inherits statement"
+        return
+    else:
+        advance_past_whitespace(file_obj)
+        ret_inherited_common = advance_until_whitespace(file_obj)
+        return ret_inherited_common
+
+class SELinuxPolicy:
+
+    def __init__(self):
+        self.types = set()
+        self.attributes = { }
+        self.classes = { }
+        self.common_classes = { }
+        self.allow_rules = [ ]
+        self.neverallow_rules = [ ]
+
+    # create policy directly from policy file
+    #@classmethod
+    def from_file_name(self, policy_file_name):
+        self.types = set()
+        self.attributes = { }
+        self.classes = { }
+        self.common_classes = { }
+        self.allow_rules = [ ]
+        self.neverallow_rules = [ ]
+        with open(policy_file_name, 'r') as policy_file:
+            line = policy_file.readline()
+            while line:
+                line_type = get_line_type(line)
+                if is_multi_line(line_type):
+                    self.parse_multi_line(line, line_type, policy_file)
+                else:
+                    self.parse_single_line(line, line_type)
+                line = policy_file.readline()
+
+    # expand_permissions - generates the actual permission set based on the listed
+    # permissions with wildcards and the given class on which they're based.
+    def expand_permissions(self, obj_class, permission_set):
+        ret_set = set()
+        neg_set = set()
+        for p in permission_set:
+            if p[0] == '-':
+                real_p = p[1:]
+                if real_p in self.classes[obj_class]:
+                    neg_set.add(real_p)
+                else:
+                    print "ERROR: invalid permission in avc rule " + real_t + "\n"
+                    return
+            else:
+                if p in self.classes[obj_class]:
+                    ret_set.add(p)
+                elif p == '*':  #pretty sure this can't be negated? eg -*
+                    ret_set |= self.classes[obj_class]  #All of the permissions
+                else:
+                    print "ERROR: invalid permission in avc rule " + p + "\n"
+                    return
+        return ret_set - neg_set
+
+    # expand_types - generates the actual type set based on the listed types,
+    # attributes, wildcards and negation.  self is left as-is, and is processed
+    # specially when generating checkAccess() 4-tuples
+    def expand_types(self, type_set):
+        ret_set = set()
+        neg_set = set()
+        for t in type_set:
+            if t[0] == '-':
+                real_t = t[1:]
+                if real_t in self.attributes:
+                    neg_set |= self.attributes[real_t]
+                elif real_t in self.types:
+                    neg_set.add(real_t)
+                elif real_t == 'self':
+                    ret_set |= real_t
+                else:
+                    print "ERROR: invalid type in avc rule " + real_t + "\nTYPE SET:"
+                    print type_set
+                    return
+            else:
+                if t in self.attributes:
+                     ret_set |= self.attributes[t]
+                elif t in self.types:
+                    ret_set.add(t)
+                elif t == 'self':
+                    ret_set.add(t)
+                elif t == '*':  #pretty sure this can't be negated?
+                     ret_set |= self.types  #All of the types
+                else:
+                    print "ERROR: invalid type in avc rule " + t + "\nTYPE SET"
+                    print type_set
+                    return
+        return ret_set - neg_set
+
+    def parse_multi_line(self, line, line_type, file_obj):
+        if line_type == CLASS:
+            self.process_class_line(line, file_obj)
+        elif line_type == COMMON:
+            self.process_common_line(line, file_obj)
+        elif line_type == ALLOW_RULE:
+            self.process_avc_rule_line(line, file_obj)
+        elif line_type == NEVERALLOW_RULE:
+            self.process_avc_rule_line(line, file_obj)
+        else:
+            print "Error: This is not a multi-line input"
+
+    def parse_single_line(self, line, line_type):
+        if line_type == TYPE:
+            self.process_type_line(line)
+        elif line_type == ATTRIBUTE:
+            self.process_attribute_line(line)
+        elif line_type == TYPEATTRIBUTE:
+            self.process_typeattribute_line(line)
+        return
+
+    def process_attribute_line(self, line):
+        match = re.search(r'^attribute\s+(.+);', line)
+        if match:
+            declared_attribute = match.group(1)
+            self.attributes[declared_attribute] = set()
+        else:
+            #TODO: handle error? (no state changed)
+            return
+
+    def process_class_line(self, line, file_obj):
+        match = re.search(r'^class\s([^\s]+)\s(.*$)', line)
+        if match:
+            declared_class = match.group(1)
+            #first class declaration has no perms
+            if not declared_class in self.classes:
+                self.classes[declared_class] = set()
+                return
+            else:
+                #need to parse file from after class name until end of '{ }'s
+                file_obj.seek(-(len(match.group(2)) + 1), 1)
+                c = advance_past_whitespace(file_obj)
+                if not (c == 'i' or c == '{'):
+                    print "ERROR: invalid class statement"
+                    return
+                elif c == 'i':
+                    #add inherited permissions
+                    inherited = process_inherits_segment(file_obj)
+                    self.classes[declared_class] |= self.common_classes[inherited]
+                    c = advance_past_whitespace(file_obj)
+                if c == '{':
+                    permissions = expand_brackets(file_obj)
+                    permissions = re.sub(r'#[^\n]*\n','\n' , permissions) #get rid of all comments
+                    permissions = permissions.split()
+                    for p in permissions:
+                        self.classes[declared_class].add(p)
+
+    def process_common_line(self, line, file_obj):
+        match = re.search(r'^common\s([^\s]+)(.*$)', line)
+        if match:
+            declared_common_class = match.group(1)
+            #TODO: common classes should only be declared once...
+            if not declared_common_class in self.common_classes:
+                self.common_classes[declared_common_class] = set()
+            #need to parse file from after common_class name until end of '{ }'s
+            file_obj.seek(-(len(match.group(2)) + 1), 1)
+            c = advance_past_whitespace(file_obj)
+            if not c == '{':
+                print "ERROR: invalid common statement"
+                return
+            permissions = expand_brackets(file_obj)
+            permissions = permissions.split()
+            for p in permissions:
+                self.common_classes[declared_common_class].add(p)
+        return
+
+    def process_avc_rule_line(self, line, file_obj):
+        match = re.search(r'^(never)?allow\s(.*$)', line)
+        if match:
+            if(match.group(1)):
+                rule_type = 'neverallow'
+            else:
+                rule_type = 'allow'
+            #need to parse file from after class name until end of '{ }'s
+            file_obj.seek(-(len(match.group(2)) + 1), 1)
+
+            #grab source type(s)
+            source_types = get_avc_rule_component(file_obj)
+            if len(source_types['set']) == 0:
+                print "ERROR: no source types for avc rule at line: " + line
+                return
+
+            #grab target type(s)
+            target_types = get_avc_rule_component(file_obj)
+            if len(target_types['set']) == 0:
+                print "ERROR: no target types for avc rule at line: " + line
+                return
+
+            #skip ':' potentially already handled by advance_until_whitespace
+            c = advance_past_whitespace(file_obj)
+            if c == ':':
+                file_obj.read(1)
+
+            #grab class(es)
+            classes = get_avc_rule_component(file_obj)
+            if len(classes['set']) == 0:
+                print "ERROR: no classes for avc rule at line: " + line
+                return
+
+            #grab permission(s)
+            permissions = get_avc_rule_component(file_obj)
+            if len(permissions['set']) == 0:
+                print "ERROR: no permissions for avc rule at line: " + line
+                return
+            rule_dict = {
+                'source_types': source_types,
+                'target_types': target_types,
+                'classes': classes,
+                'permissions': permissions }
+
+            if rule_type == 'allow':
+                self.allow_rules.append(rule_dict)
+            elif rule_type == 'neverallow':
+                self.neverallow_rules.append(rule_dict)
+
+    def process_type_line(self, line):
+        #TODO: add support for aliases (not yet in current policy.conf)
+        match = re.search(r'^type\s([^,]+),?(.*);', line)
+        if match:
+            declared_type = match.group(1)
+            self.types.add(declared_type)
+            if match.group(2):
+                declared_attributes = match.group(2)
+                declared_attributes = declared_attributes.replace(" ", "") #remove whitespace
+                declared_attributes = declared_attributes.split(',') #separate based on delimiter
+                for a in declared_attributes:
+                    if not a in self.attributes:
+                        #TODO: hanlde error? attribute should already exist
+                        self.attributes[a] = set()
+                    self.attributes[a].add(declared_type)
+        else:
+            #TODO: handle error? (no state changed)
+            return
+
+    def process_typeattribute_line(self, line):
+        match = re.search(r'^typeattribute\s([^\s]+)\s(.*);', line)
+        if match:
+            declared_type = match.group(1)
+            if not declared_type in self.types:
+                #TODO: handle error? type should already exist
+                self.types.add(declared_type)
+            if match.group(2):
+                declared_attributes = match.group(2)
+                declared_attributes = declared_attributes.replace(" ", "") #remove whitespace
+                declared_attributes = declared_attributes.split(',') #separate based on delimiter
+                for a in declared_attributes:
+                    if not a in self.attributes:
+                        #TODO: hanlde error? attribute should already exist
+                        self.attributes[a] = set()
+                    self.attributes[a].add(declared_type)
+            else:
+                return
+        else:
+            #TODO: handle error? (no state changed)
+            return
diff --git a/tools/selinux/src/example_input_policy.conf b/tools/selinux/src/example_input_policy.conf
new file mode 100644
index 0000000..aeef5f8
--- /dev/null
+++ b/tools/selinux/src/example_input_policy.conf
@@ -0,0 +1,9850 @@
+#line 1 "external/sepolicy/security_classes"
+# FLASK
+
+#
+# Define the security object classes
+#
+
+# Classes marked as userspace are classes
+# for userspace object managers
+
+class security
+class process
+class system
+class capability
+
+# file-related classes
+class filesystem
+class file
+class dir
+class fd
+class lnk_file
+class chr_file
+class blk_file
+class sock_file
+class fifo_file
+
+# network-related classes
+class socket
+class tcp_socket
+class udp_socket
+class rawip_socket
+class node
+class netif
+class netlink_socket
+class packet_socket
+class key_socket
+class unix_stream_socket
+class unix_dgram_socket
+
+# sysv-ipc-related classes
+class sem
+class msg
+class msgq
+class shm
+class ipc
+
+#
+# userspace object manager classes
+#
+
+# passwd/chfn/chsh
+class passwd			# userspace
+
+# SE-X Windows stuff (more classes below)
+class x_drawable		# userspace
+class x_screen			# userspace
+class x_gc			# userspace
+class x_font			# userspace
+class x_colormap		# userspace
+class x_property		# userspace
+class x_selection		# userspace
+class x_cursor			# userspace
+class x_client			# userspace
+class x_device			# userspace
+class x_server			# userspace
+class x_extension		# userspace
+
+# extended netlink sockets
+class netlink_route_socket
+class netlink_firewall_socket
+class netlink_tcpdiag_socket
+class netlink_nflog_socket
+class netlink_xfrm_socket
+class netlink_selinux_socket
+class netlink_audit_socket
+class netlink_ip6fw_socket
+class netlink_dnrt_socket
+
+class dbus			# userspace
+class nscd			# userspace
+
+# IPSec association
+class association
+
+# Updated Netlink class for KOBJECT_UEVENT family.
+class netlink_kobject_uevent_socket
+
+class appletalk_socket
+
+class packet
+
+# Kernel access key retention
+class key
+
+class context			# userspace
+
+class dccp_socket
+
+class memprotect
+
+class db_database		# userspace
+class db_table			# userspace
+class db_procedure		# userspace
+class db_column			# userspace
+class db_tuple			# userspace
+class db_blob			# userspace
+
+# network peer labels
+class peer
+
+# Capabilities >= 32
+class capability2
+
+# More SE-X Windows stuff
+class x_resource		# userspace
+class x_event			# userspace
+class x_synthetic_event		# userspace
+class x_application_data	# userspace
+
+# kernel services that need to override task security, e.g. cachefiles
+class kernel_service
+
+class tun_socket
+
+# Still More SE-X Windows stuff
+class x_pointer			# userspace
+class x_keyboard		# userspace
+
+# More Database stuff
+class db_schema			# userspace
+class db_view			# userspace
+class db_sequence		# userspace
+class db_language		# userspace
+
+class binder
+class zygote
+
+# Property service
+class property_service          # userspace
+
+# FLASK
+#line 1 "external/sepolicy/initial_sids"
+# FLASK
+
+#
+# Define initial security identifiers
+#
+
+sid kernel
+sid security
+sid unlabeled
+sid fs
+sid file
+sid file_labels
+sid init
+sid any_socket
+sid port
+sid netif
+sid netmsg
+sid node
+sid igmp_packet
+sid icmp_socket
+sid tcp_socket
+sid sysctl_modprobe
+sid sysctl
+sid sysctl_fs
+sid sysctl_kernel
+sid sysctl_net
+sid sysctl_net_unix
+sid sysctl_vm
+sid sysctl_dev
+sid kmod
+sid policy
+sid scmp_packet
+sid devnull
+
+# FLASK
+#line 1 "external/sepolicy/access_vectors"
+#
+# Define common prefixes for access vectors
+#
+# common common_name { permission_name ... }
+
+
+#
+# Define a common prefix for file access vectors.
+#
+
+common file
+{
+	ioctl
+	read
+	write
+	create
+	getattr
+	setattr
+	lock
+	relabelfrom
+	relabelto
+	append
+	unlink
+	link
+	rename
+	execute
+	swapon
+	quotaon
+	mounton
+}
+
+
+#
+# Define a common prefix for socket access vectors.
+#
+
+common socket
+{
+# inherited from file
+	ioctl
+	read
+	write
+	create
+	getattr
+	setattr
+	lock
+	relabelfrom
+	relabelto
+	append
+# socket-specific
+	bind
+	connect
+	listen
+	accept
+	getopt
+	setopt
+	shutdown
+	recvfrom
+	sendto
+	recv_msg
+	send_msg
+	name_bind
+}
+
+#
+# Define a common prefix for ipc access vectors.
+#
+
+common ipc
+{
+	create
+	destroy
+	getattr
+	setattr
+	read
+	write
+	associate
+	unix_read
+	unix_write
+}
+
+#
+#  Define a common prefix for userspace database object access vectors.
+#
+
+common database
+{
+	create
+	drop
+	getattr
+	setattr
+	relabelfrom
+	relabelto
+}
+
+#
+# Define a common prefix for pointer and keyboard access vectors.
+#
+
+common x_device
+{
+	getattr
+	setattr
+	use
+	read
+	write
+	getfocus
+	setfocus
+	bell
+	force_cursor
+	freeze
+	grab
+	manage
+	list_property
+	get_property
+	set_property
+	add
+	remove
+	create
+	destroy
+}
+
+#
+# Define the access vectors.
+#
+# class class_name [ inherits common_name ] { permission_name ... }
+
+
+#
+# Define the access vector interpretation for file-related objects.
+#
+
+class filesystem
+{
+	mount
+	remount
+	unmount
+	getattr
+	relabelfrom
+	relabelto
+	transition
+	associate
+	quotamod
+	quotaget
+}
+
+class dir
+inherits file
+{
+	add_name
+	remove_name
+	reparent
+	search
+	rmdir
+	open
+	audit_access
+	execmod
+}
+
+class file
+inherits file
+{
+	execute_no_trans
+	entrypoint
+	execmod
+	open
+	audit_access
+}
+
+class lnk_file
+inherits file
+{
+	open
+	audit_access
+	execmod
+}
+
+class chr_file
+inherits file
+{
+	execute_no_trans
+	entrypoint
+	execmod
+	open
+	audit_access
+}
+
+class blk_file
+inherits file
+{
+	open
+	audit_access
+	execmod
+}
+
+class sock_file
+inherits file
+{
+	open
+	audit_access
+	execmod
+}
+
+class fifo_file
+inherits file
+{
+	open
+	audit_access
+	execmod
+}
+
+class fd
+{
+	use
+}
+
+
+#
+# Define the access vector interpretation for network-related objects.
+#
+
+class socket
+inherits socket
+
+class tcp_socket
+inherits socket
+{
+	connectto
+	newconn
+	acceptfrom
+	node_bind
+	name_connect
+}
+
+class udp_socket
+inherits socket
+{
+	node_bind
+}
+
+class rawip_socket
+inherits socket
+{
+	node_bind
+}
+
+class node
+{
+	tcp_recv
+	tcp_send
+	udp_recv
+	udp_send
+	rawip_recv
+	rawip_send
+	enforce_dest
+	dccp_recv
+	dccp_send
+	recvfrom
+	sendto
+}
+
+class netif
+{
+	tcp_recv
+	tcp_send
+	udp_recv
+	udp_send
+	rawip_recv
+	rawip_send
+	dccp_recv
+	dccp_send
+	ingress
+	egress
+}
+
+class netlink_socket
+inherits socket
+
+class packet_socket
+inherits socket
+
+class key_socket
+inherits socket
+
+class unix_stream_socket
+inherits socket
+{
+	connectto
+	newconn
+	acceptfrom
+}
+
+class unix_dgram_socket
+inherits socket
+
+#
+# Define the access vector interpretation for process-related objects
+#
+
+class process
+{
+	fork
+	transition
+	sigchld # commonly granted from child to parent
+	sigkill # cannot be caught or ignored
+	sigstop # cannot be caught or ignored
+	signull # for kill(pid, 0)
+	signal  # all other signals
+	ptrace
+	getsched
+	setsched
+	getsession
+	getpgid
+	setpgid
+	getcap
+	setcap
+	share
+	getattr
+	setexec
+	setfscreate
+	noatsecure
+	siginh
+	setrlimit
+	rlimitinh
+	dyntransition
+	setcurrent
+	execmem
+	execstack
+	execheap
+	setkeycreate
+	setsockcreate
+}
+
+
+#
+# Define the access vector interpretation for ipc-related objects
+#
+
+class ipc
+inherits ipc
+
+class sem
+inherits ipc
+
+class msgq
+inherits ipc
+{
+	enqueue
+}
+
+class msg
+{
+	send
+	receive
+}
+
+class shm
+inherits ipc
+{
+	lock
+}
+
+
+#
+# Define the access vector interpretation for the security server.
+#
+
+class security
+{
+	compute_av
+	compute_create
+	compute_member
+	check_context
+	load_policy
+	compute_relabel
+	compute_user
+	setenforce     # was avc_toggle in system class
+	setbool
+	setsecparam
+	setcheckreqprot
+	read_policy
+}
+
+
+#
+# Define the access vector interpretation for system operations.
+#
+
+class system
+{
+	ipc_info
+	syslog_read
+	syslog_mod
+	syslog_console
+	module_request
+}
+
+#
+# Define the access vector interpretation for controling capabilies
+#
+
+class capability
+{
+	# The capabilities are defined in include/linux/capability.h
+	# Capabilities >= 32 are defined in the capability2 class.
+	# Care should be taken to ensure that these are consistent with
+	# those definitions. (Order matters)
+
+	chown
+	dac_override
+	dac_read_search
+	fowner
+	fsetid
+	kill
+	setgid
+	setuid
+	setpcap
+	linux_immutable
+	net_bind_service
+	net_broadcast
+	net_admin
+	net_raw
+	ipc_lock
+	ipc_owner
+	sys_module
+	sys_rawio
+	sys_chroot
+	sys_ptrace
+	sys_pacct
+	sys_admin
+	sys_boot
+	sys_nice
+	sys_resource
+	sys_time
+	sys_tty_config
+	mknod
+	lease
+	audit_write
+	audit_control
+	setfcap
+}
+
+class capability2
+{
+	mac_override	# unused by SELinux
+	mac_admin	# unused by SELinux
+	syslog
+	wake_alarm
+	block_suspend
+}
+
+#
+# Define the access vector interpretation for controlling
+# changes to passwd information.
+#
+class passwd
+{
+	passwd	# change another user passwd
+	chfn	# change another user finger info
+	chsh	# change another user shell
+	rootok  # pam_rootok check (skip auth)
+	crontab # crontab on another user
+}
+
+#
+# SE-X Windows stuff
+#
+class x_drawable
+{
+	create
+	destroy
+	read
+	write
+	blend
+	getattr
+	setattr
+	list_child
+	add_child
+	remove_child
+	list_property
+	get_property
+	set_property
+	manage
+	override
+	show
+	hide
+	send
+	receive
+}
+
+class x_screen
+{
+	getattr
+	setattr
+	hide_cursor
+	show_cursor
+	saver_getattr
+	saver_setattr
+	saver_hide
+	saver_show
+}
+
+class x_gc
+{
+	create
+	destroy
+	getattr
+	setattr
+	use
+}
+
+class x_font
+{
+	create
+	destroy
+	getattr
+	add_glyph
+	remove_glyph
+	use
+}
+
+class x_colormap
+{
+	create
+	destroy
+	read
+	write
+	getattr
+	add_color
+	remove_color
+	install
+	uninstall
+	use
+}
+
+class x_property
+{
+	create
+	destroy
+	read
+	write
+	append
+	getattr
+	setattr
+}
+
+class x_selection
+{
+	read
+	write
+	getattr
+	setattr
+}
+
+class x_cursor
+{
+	create
+	destroy
+	read
+	write
+	getattr
+	setattr
+	use
+}
+
+class x_client
+{
+	destroy
+	getattr
+	setattr
+	manage
+}
+
+class x_device
+inherits x_device
+
+class x_server
+{
+	getattr
+	setattr
+	record
+	debug
+	grab
+	manage
+}
+
+class x_extension
+{
+	query
+	use
+}
+
+class x_resource
+{
+	read
+	write
+}
+
+class x_event
+{
+	send
+	receive
+}
+
+class x_synthetic_event
+{
+	send
+	receive
+}
+
+#
+# Extended Netlink classes
+#
+class netlink_route_socket
+inherits socket
+{
+	nlmsg_read
+	nlmsg_write
+}
+
+class netlink_firewall_socket
+inherits socket
+{
+	nlmsg_read
+	nlmsg_write
+}
+
+class netlink_tcpdiag_socket
+inherits socket
+{
+	nlmsg_read
+	nlmsg_write
+}
+
+class netlink_nflog_socket
+inherits socket
+
+class netlink_xfrm_socket
+inherits socket
+{
+	nlmsg_read
+	nlmsg_write
+}
+
+class netlink_selinux_socket
+inherits socket
+
+class netlink_audit_socket
+inherits socket
+{
+	nlmsg_read
+	nlmsg_write
+	nlmsg_relay
+	nlmsg_readpriv
+	nlmsg_tty_audit
+}
+
+class netlink_ip6fw_socket
+inherits socket
+{
+	nlmsg_read
+	nlmsg_write
+}
+
+class netlink_dnrt_socket
+inherits socket
+
+# Define the access vector interpretation for controlling
+# access and communication through the D-BUS messaging
+# system.
+#
+class dbus
+{
+	acquire_svc
+	send_msg
+}
+
+# Define the access vector interpretation for controlling
+# access through the name service cache daemon (nscd).
+#
+class nscd
+{
+	getpwd
+	getgrp
+	gethost
+	getstat
+	admin
+	shmempwd
+	shmemgrp
+	shmemhost
+	getserv
+	shmemserv
+}
+
+# Define the access vector interpretation for controlling
+# access to IPSec network data by association
+#
+class association
+{
+	sendto
+	recvfrom
+	setcontext
+	polmatch
+}
+
+# Updated Netlink class for KOBJECT_UEVENT family.
+class netlink_kobject_uevent_socket
+inherits socket
+
+class appletalk_socket
+inherits socket
+
+class packet
+{
+	send
+	recv
+	relabelto
+	flow_in		# deprecated
+	flow_out	# deprecated
+	forward_in
+	forward_out
+}
+
+class key
+{
+	view
+	read
+	write
+	search
+	link
+	setattr
+	create
+}
+
+class context
+{
+	translate
+	contains
+}
+
+class dccp_socket
+inherits socket
+{
+	node_bind
+	name_connect
+}
+
+class memprotect
+{
+	mmap_zero
+}
+
+class db_database
+inherits database
+{
+	access
+	install_module
+	load_module
+	get_param	# deprecated
+	set_param	# deprecated
+}
+
+class db_table
+inherits database
+{
+	use		# deprecated
+	select
+	update
+	insert
+	delete
+	lock
+}
+
+class db_procedure
+inherits database
+{
+	execute
+	entrypoint
+	install
+}
+
+class db_column
+inherits database
+{
+	use		# deprecated
+	select
+	update
+	insert
+}
+
+class db_tuple
+{
+	relabelfrom
+	relabelto
+	use		# deprecated
+	select
+	update
+	insert
+	delete
+}
+
+class db_blob
+inherits database
+{
+	read
+	write
+	import
+	export
+}
+
+# network peer labels
+class peer
+{
+	recv
+}
+
+class x_application_data
+{
+	paste
+	paste_after_confirm
+	copy
+}
+
+class kernel_service
+{
+	use_as_override
+	create_files_as
+}
+
+class tun_socket
+inherits socket
+
+class x_pointer
+inherits x_device
+
+class x_keyboard
+inherits x_device
+
+class db_schema
+inherits database
+{
+	search
+	add_name
+	remove_name
+}
+
+class db_view
+inherits database
+{
+	expand
+}
+
+class db_sequence
+inherits database
+{
+	get_value
+	next_value
+	set_value
+}
+
+class db_language
+inherits database
+{
+	implement
+	execute
+}
+
+class binder
+{
+	impersonate
+	call
+	set_context_mgr
+	transfer
+}
+
+class zygote
+{
+	specifyids
+	specifyrlimits
+	specifycapabilities
+	specifyinvokewith
+	specifyseinfo
+}
+
+class property_service
+{
+	set
+}
+#line 1 "external/sepolicy/global_macros"
+#####################################
+# Common groupings of object classes.
+#
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#####################################
+# Common groupings of permissions.
+#
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#####################################
+# Common socket permission sets.
+
+
+#line 1 "external/sepolicy/mls_macros"
+########################################
+#
+# gen_cats(N)
+#
+# declares categores c0 to c(N-1)
+#
+#line 10
+
+
+
+
+########################################
+#
+# gen_sens(N)
+#
+# declares sensitivites s0 to s(N-1) with dominance
+# in increasing numeric order with s0 lowest, s(N-1) highest
+#
+#line 24
+
+
+
+
+#line 34
+
+
+########################################
+#
+# gen_levels(N,M)
+#
+# levels from s0 to (N-1) with categories c0 to (M-1)
+#
+#line 45
+
+
+
+
+########################################
+#
+# Basic level names for system low and high
+#
+
+
+#line 1 "external/sepolicy/mls"
+#########################################
+# MLS declarations
+#
+
+# Generate the desired number of sensitivities and categories.
+
+#line 6
+# Each sensitivity has a name and zero or more aliases.
+#line 6
+sensitivity s0;
+#line 6
+
+#line 6
+
+#line 6
+# Define the ordering of the sensitivity levels (least to greatest)
+#line 6
+dominance { s0  }
+#line 6
+
+category c0;
+#line 7
+category c1;
+#line 7
+category c2;
+#line 7
+category c3;
+#line 7
+category c4;
+#line 7
+category c5;
+#line 7
+category c6;
+#line 7
+category c7;
+#line 7
+category c8;
+#line 7
+category c9;
+#line 7
+category c10;
+#line 7
+category c11;
+#line 7
+category c12;
+#line 7
+category c13;
+#line 7
+category c14;
+#line 7
+category c15;
+#line 7
+category c16;
+#line 7
+category c17;
+#line 7
+category c18;
+#line 7
+category c19;
+#line 7
+category c20;
+#line 7
+category c21;
+#line 7
+category c22;
+#line 7
+category c23;
+#line 7
+category c24;
+#line 7
+category c25;
+#line 7
+category c26;
+#line 7
+category c27;
+#line 7
+category c28;
+#line 7
+category c29;
+#line 7
+category c30;
+#line 7
+category c31;
+#line 7
+category c32;
+#line 7
+category c33;
+#line 7
+category c34;
+#line 7
+category c35;
+#line 7
+category c36;
+#line 7
+category c37;
+#line 7
+category c38;
+#line 7
+category c39;
+#line 7
+category c40;
+#line 7
+category c41;
+#line 7
+category c42;
+#line 7
+category c43;
+#line 7
+category c44;
+#line 7
+category c45;
+#line 7
+category c46;
+#line 7
+category c47;
+#line 7
+category c48;
+#line 7
+category c49;
+#line 7
+category c50;
+#line 7
+category c51;
+#line 7
+category c52;
+#line 7
+category c53;
+#line 7
+category c54;
+#line 7
+category c55;
+#line 7
+category c56;
+#line 7
+category c57;
+#line 7
+category c58;
+#line 7
+category c59;
+#line 7
+category c60;
+#line 7
+category c61;
+#line 7
+category c62;
+#line 7
+category c63;
+#line 7
+category c64;
+#line 7
+category c65;
+#line 7
+category c66;
+#line 7
+category c67;
+#line 7
+category c68;
+#line 7
+category c69;
+#line 7
+category c70;
+#line 7
+category c71;
+#line 7
+category c72;
+#line 7
+category c73;
+#line 7
+category c74;
+#line 7
+category c75;
+#line 7
+category c76;
+#line 7
+category c77;
+#line 7
+category c78;
+#line 7
+category c79;
+#line 7
+category c80;
+#line 7
+category c81;
+#line 7
+category c82;
+#line 7
+category c83;
+#line 7
+category c84;
+#line 7
+category c85;
+#line 7
+category c86;
+#line 7
+category c87;
+#line 7
+category c88;
+#line 7
+category c89;
+#line 7
+category c90;
+#line 7
+category c91;
+#line 7
+category c92;
+#line 7
+category c93;
+#line 7
+category c94;
+#line 7
+category c95;
+#line 7
+category c96;
+#line 7
+category c97;
+#line 7
+category c98;
+#line 7
+category c99;
+#line 7
+category c100;
+#line 7
+category c101;
+#line 7
+category c102;
+#line 7
+category c103;
+#line 7
+category c104;
+#line 7
+category c105;
+#line 7
+category c106;
+#line 7
+category c107;
+#line 7
+category c108;
+#line 7
+category c109;
+#line 7
+category c110;
+#line 7
+category c111;
+#line 7
+category c112;
+#line 7
+category c113;
+#line 7
+category c114;
+#line 7
+category c115;
+#line 7
+category c116;
+#line 7
+category c117;
+#line 7
+category c118;
+#line 7
+category c119;
+#line 7
+category c120;
+#line 7
+category c121;
+#line 7
+category c122;
+#line 7
+category c123;
+#line 7
+category c124;
+#line 7
+category c125;
+#line 7
+category c126;
+#line 7
+category c127;
+#line 7
+category c128;
+#line 7
+category c129;
+#line 7
+category c130;
+#line 7
+category c131;
+#line 7
+category c132;
+#line 7
+category c133;
+#line 7
+category c134;
+#line 7
+category c135;
+#line 7
+category c136;
+#line 7
+category c137;
+#line 7
+category c138;
+#line 7
+category c139;
+#line 7
+category c140;
+#line 7
+category c141;
+#line 7
+category c142;
+#line 7
+category c143;
+#line 7
+category c144;
+#line 7
+category c145;
+#line 7
+category c146;
+#line 7
+category c147;
+#line 7
+category c148;
+#line 7
+category c149;
+#line 7
+category c150;
+#line 7
+category c151;
+#line 7
+category c152;
+#line 7
+category c153;
+#line 7
+category c154;
+#line 7
+category c155;
+#line 7
+category c156;
+#line 7
+category c157;
+#line 7
+category c158;
+#line 7
+category c159;
+#line 7
+category c160;
+#line 7
+category c161;
+#line 7
+category c162;
+#line 7
+category c163;
+#line 7
+category c164;
+#line 7
+category c165;
+#line 7
+category c166;
+#line 7
+category c167;
+#line 7
+category c168;
+#line 7
+category c169;
+#line 7
+category c170;
+#line 7
+category c171;
+#line 7
+category c172;
+#line 7
+category c173;
+#line 7
+category c174;
+#line 7
+category c175;
+#line 7
+category c176;
+#line 7
+category c177;
+#line 7
+category c178;
+#line 7
+category c179;
+#line 7
+category c180;
+#line 7
+category c181;
+#line 7
+category c182;
+#line 7
+category c183;
+#line 7
+category c184;
+#line 7
+category c185;
+#line 7
+category c186;
+#line 7
+category c187;
+#line 7
+category c188;
+#line 7
+category c189;
+#line 7
+category c190;
+#line 7
+category c191;
+#line 7
+category c192;
+#line 7
+category c193;
+#line 7
+category c194;
+#line 7
+category c195;
+#line 7
+category c196;
+#line 7
+category c197;
+#line 7
+category c198;
+#line 7
+category c199;
+#line 7
+category c200;
+#line 7
+category c201;
+#line 7
+category c202;
+#line 7
+category c203;
+#line 7
+category c204;
+#line 7
+category c205;
+#line 7
+category c206;
+#line 7
+category c207;
+#line 7
+category c208;
+#line 7
+category c209;
+#line 7
+category c210;
+#line 7
+category c211;
+#line 7
+category c212;
+#line 7
+category c213;
+#line 7
+category c214;
+#line 7
+category c215;
+#line 7
+category c216;
+#line 7
+category c217;
+#line 7
+category c218;
+#line 7
+category c219;
+#line 7
+category c220;
+#line 7
+category c221;
+#line 7
+category c222;
+#line 7
+category c223;
+#line 7
+category c224;
+#line 7
+category c225;
+#line 7
+category c226;
+#line 7
+category c227;
+#line 7
+category c228;
+#line 7
+category c229;
+#line 7
+category c230;
+#line 7
+category c231;
+#line 7
+category c232;
+#line 7
+category c233;
+#line 7
+category c234;
+#line 7
+category c235;
+#line 7
+category c236;
+#line 7
+category c237;
+#line 7
+category c238;
+#line 7
+category c239;
+#line 7
+category c240;
+#line 7
+category c241;
+#line 7
+category c242;
+#line 7
+category c243;
+#line 7
+category c244;
+#line 7
+category c245;
+#line 7
+category c246;
+#line 7
+category c247;
+#line 7
+category c248;
+#line 7
+category c249;
+#line 7
+category c250;
+#line 7
+category c251;
+#line 7
+category c252;
+#line 7
+category c253;
+#line 7
+category c254;
+#line 7
+category c255;
+#line 7
+category c256;
+#line 7
+category c257;
+#line 7
+category c258;
+#line 7
+category c259;
+#line 7
+category c260;
+#line 7
+category c261;
+#line 7
+category c262;
+#line 7
+category c263;
+#line 7
+category c264;
+#line 7
+category c265;
+#line 7
+category c266;
+#line 7
+category c267;
+#line 7
+category c268;
+#line 7
+category c269;
+#line 7
+category c270;
+#line 7
+category c271;
+#line 7
+category c272;
+#line 7
+category c273;
+#line 7
+category c274;
+#line 7
+category c275;
+#line 7
+category c276;
+#line 7
+category c277;
+#line 7
+category c278;
+#line 7
+category c279;
+#line 7
+category c280;
+#line 7
+category c281;
+#line 7
+category c282;
+#line 7
+category c283;
+#line 7
+category c284;
+#line 7
+category c285;
+#line 7
+category c286;
+#line 7
+category c287;
+#line 7
+category c288;
+#line 7
+category c289;
+#line 7
+category c290;
+#line 7
+category c291;
+#line 7
+category c292;
+#line 7
+category c293;
+#line 7
+category c294;
+#line 7
+category c295;
+#line 7
+category c296;
+#line 7
+category c297;
+#line 7
+category c298;
+#line 7
+category c299;
+#line 7
+category c300;
+#line 7
+category c301;
+#line 7
+category c302;
+#line 7
+category c303;
+#line 7
+category c304;
+#line 7
+category c305;
+#line 7
+category c306;
+#line 7
+category c307;
+#line 7
+category c308;
+#line 7
+category c309;
+#line 7
+category c310;
+#line 7
+category c311;
+#line 7
+category c312;
+#line 7
+category c313;
+#line 7
+category c314;
+#line 7
+category c315;
+#line 7
+category c316;
+#line 7
+category c317;
+#line 7
+category c318;
+#line 7
+category c319;
+#line 7
+category c320;
+#line 7
+category c321;
+#line 7
+category c322;
+#line 7
+category c323;
+#line 7
+category c324;
+#line 7
+category c325;
+#line 7
+category c326;
+#line 7
+category c327;
+#line 7
+category c328;
+#line 7
+category c329;
+#line 7
+category c330;
+#line 7
+category c331;
+#line 7
+category c332;
+#line 7
+category c333;
+#line 7
+category c334;
+#line 7
+category c335;
+#line 7
+category c336;
+#line 7
+category c337;
+#line 7
+category c338;
+#line 7
+category c339;
+#line 7
+category c340;
+#line 7
+category c341;
+#line 7
+category c342;
+#line 7
+category c343;
+#line 7
+category c344;
+#line 7
+category c345;
+#line 7
+category c346;
+#line 7
+category c347;
+#line 7
+category c348;
+#line 7
+category c349;
+#line 7
+category c350;
+#line 7
+category c351;
+#line 7
+category c352;
+#line 7
+category c353;
+#line 7
+category c354;
+#line 7
+category c355;
+#line 7
+category c356;
+#line 7
+category c357;
+#line 7
+category c358;
+#line 7
+category c359;
+#line 7
+category c360;
+#line 7
+category c361;
+#line 7
+category c362;
+#line 7
+category c363;
+#line 7
+category c364;
+#line 7
+category c365;
+#line 7
+category c366;
+#line 7
+category c367;
+#line 7
+category c368;
+#line 7
+category c369;
+#line 7
+category c370;
+#line 7
+category c371;
+#line 7
+category c372;
+#line 7
+category c373;
+#line 7
+category c374;
+#line 7
+category c375;
+#line 7
+category c376;
+#line 7
+category c377;
+#line 7
+category c378;
+#line 7
+category c379;
+#line 7
+category c380;
+#line 7
+category c381;
+#line 7
+category c382;
+#line 7
+category c383;
+#line 7
+category c384;
+#line 7
+category c385;
+#line 7
+category c386;
+#line 7
+category c387;
+#line 7
+category c388;
+#line 7
+category c389;
+#line 7
+category c390;
+#line 7
+category c391;
+#line 7
+category c392;
+#line 7
+category c393;
+#line 7
+category c394;
+#line 7
+category c395;
+#line 7
+category c396;
+#line 7
+category c397;
+#line 7
+category c398;
+#line 7
+category c399;
+#line 7
+category c400;
+#line 7
+category c401;
+#line 7
+category c402;
+#line 7
+category c403;
+#line 7
+category c404;
+#line 7
+category c405;
+#line 7
+category c406;
+#line 7
+category c407;
+#line 7
+category c408;
+#line 7
+category c409;
+#line 7
+category c410;
+#line 7
+category c411;
+#line 7
+category c412;
+#line 7
+category c413;
+#line 7
+category c414;
+#line 7
+category c415;
+#line 7
+category c416;
+#line 7
+category c417;
+#line 7
+category c418;
+#line 7
+category c419;
+#line 7
+category c420;
+#line 7
+category c421;
+#line 7
+category c422;
+#line 7
+category c423;
+#line 7
+category c424;
+#line 7
+category c425;
+#line 7
+category c426;
+#line 7
+category c427;
+#line 7
+category c428;
+#line 7
+category c429;
+#line 7
+category c430;
+#line 7
+category c431;
+#line 7
+category c432;
+#line 7
+category c433;
+#line 7
+category c434;
+#line 7
+category c435;
+#line 7
+category c436;
+#line 7
+category c437;
+#line 7
+category c438;
+#line 7
+category c439;
+#line 7
+category c440;
+#line 7
+category c441;
+#line 7
+category c442;
+#line 7
+category c443;
+#line 7
+category c444;
+#line 7
+category c445;
+#line 7
+category c446;
+#line 7
+category c447;
+#line 7
+category c448;
+#line 7
+category c449;
+#line 7
+category c450;
+#line 7
+category c451;
+#line 7
+category c452;
+#line 7
+category c453;
+#line 7
+category c454;
+#line 7
+category c455;
+#line 7
+category c456;
+#line 7
+category c457;
+#line 7
+category c458;
+#line 7
+category c459;
+#line 7
+category c460;
+#line 7
+category c461;
+#line 7
+category c462;
+#line 7
+category c463;
+#line 7
+category c464;
+#line 7
+category c465;
+#line 7
+category c466;
+#line 7
+category c467;
+#line 7
+category c468;
+#line 7
+category c469;
+#line 7
+category c470;
+#line 7
+category c471;
+#line 7
+category c472;
+#line 7
+category c473;
+#line 7
+category c474;
+#line 7
+category c475;
+#line 7
+category c476;
+#line 7
+category c477;
+#line 7
+category c478;
+#line 7
+category c479;
+#line 7
+category c480;
+#line 7
+category c481;
+#line 7
+category c482;
+#line 7
+category c483;
+#line 7
+category c484;
+#line 7
+category c485;
+#line 7
+category c486;
+#line 7
+category c487;
+#line 7
+category c488;
+#line 7
+category c489;
+#line 7
+category c490;
+#line 7
+category c491;
+#line 7
+category c492;
+#line 7
+category c493;
+#line 7
+category c494;
+#line 7
+category c495;
+#line 7
+category c496;
+#line 7
+category c497;
+#line 7
+category c498;
+#line 7
+category c499;
+#line 7
+category c500;
+#line 7
+category c501;
+#line 7
+category c502;
+#line 7
+category c503;
+#line 7
+category c504;
+#line 7
+category c505;
+#line 7
+category c506;
+#line 7
+category c507;
+#line 7
+category c508;
+#line 7
+category c509;
+#line 7
+category c510;
+#line 7
+category c511;
+#line 7
+category c512;
+#line 7
+category c513;
+#line 7
+category c514;
+#line 7
+category c515;
+#line 7
+category c516;
+#line 7
+category c517;
+#line 7
+category c518;
+#line 7
+category c519;
+#line 7
+category c520;
+#line 7
+category c521;
+#line 7
+category c522;
+#line 7
+category c523;
+#line 7
+category c524;
+#line 7
+category c525;
+#line 7
+category c526;
+#line 7
+category c527;
+#line 7
+category c528;
+#line 7
+category c529;
+#line 7
+category c530;
+#line 7
+category c531;
+#line 7
+category c532;
+#line 7
+category c533;
+#line 7
+category c534;
+#line 7
+category c535;
+#line 7
+category c536;
+#line 7
+category c537;
+#line 7
+category c538;
+#line 7
+category c539;
+#line 7
+category c540;
+#line 7
+category c541;
+#line 7
+category c542;
+#line 7
+category c543;
+#line 7
+category c544;
+#line 7
+category c545;
+#line 7
+category c546;
+#line 7
+category c547;
+#line 7
+category c548;
+#line 7
+category c549;
+#line 7
+category c550;
+#line 7
+category c551;
+#line 7
+category c552;
+#line 7
+category c553;
+#line 7
+category c554;
+#line 7
+category c555;
+#line 7
+category c556;
+#line 7
+category c557;
+#line 7
+category c558;
+#line 7
+category c559;
+#line 7
+category c560;
+#line 7
+category c561;
+#line 7
+category c562;
+#line 7
+category c563;
+#line 7
+category c564;
+#line 7
+category c565;
+#line 7
+category c566;
+#line 7
+category c567;
+#line 7
+category c568;
+#line 7
+category c569;
+#line 7
+category c570;
+#line 7
+category c571;
+#line 7
+category c572;
+#line 7
+category c573;
+#line 7
+category c574;
+#line 7
+category c575;
+#line 7
+category c576;
+#line 7
+category c577;
+#line 7
+category c578;
+#line 7
+category c579;
+#line 7
+category c580;
+#line 7
+category c581;
+#line 7
+category c582;
+#line 7
+category c583;
+#line 7
+category c584;
+#line 7
+category c585;
+#line 7
+category c586;
+#line 7
+category c587;
+#line 7
+category c588;
+#line 7
+category c589;
+#line 7
+category c590;
+#line 7
+category c591;
+#line 7
+category c592;
+#line 7
+category c593;
+#line 7
+category c594;
+#line 7
+category c595;
+#line 7
+category c596;
+#line 7
+category c597;
+#line 7
+category c598;
+#line 7
+category c599;
+#line 7
+category c600;
+#line 7
+category c601;
+#line 7
+category c602;
+#line 7
+category c603;
+#line 7
+category c604;
+#line 7
+category c605;
+#line 7
+category c606;
+#line 7
+category c607;
+#line 7
+category c608;
+#line 7
+category c609;
+#line 7
+category c610;
+#line 7
+category c611;
+#line 7
+category c612;
+#line 7
+category c613;
+#line 7
+category c614;
+#line 7
+category c615;
+#line 7
+category c616;
+#line 7
+category c617;
+#line 7
+category c618;
+#line 7
+category c619;
+#line 7
+category c620;
+#line 7
+category c621;
+#line 7
+category c622;
+#line 7
+category c623;
+#line 7
+category c624;
+#line 7
+category c625;
+#line 7
+category c626;
+#line 7
+category c627;
+#line 7
+category c628;
+#line 7
+category c629;
+#line 7
+category c630;
+#line 7
+category c631;
+#line 7
+category c632;
+#line 7
+category c633;
+#line 7
+category c634;
+#line 7
+category c635;
+#line 7
+category c636;
+#line 7
+category c637;
+#line 7
+category c638;
+#line 7
+category c639;
+#line 7
+category c640;
+#line 7
+category c641;
+#line 7
+category c642;
+#line 7
+category c643;
+#line 7
+category c644;
+#line 7
+category c645;
+#line 7
+category c646;
+#line 7
+category c647;
+#line 7
+category c648;
+#line 7
+category c649;
+#line 7
+category c650;
+#line 7
+category c651;
+#line 7
+category c652;
+#line 7
+category c653;
+#line 7
+category c654;
+#line 7
+category c655;
+#line 7
+category c656;
+#line 7
+category c657;
+#line 7
+category c658;
+#line 7
+category c659;
+#line 7
+category c660;
+#line 7
+category c661;
+#line 7
+category c662;
+#line 7
+category c663;
+#line 7
+category c664;
+#line 7
+category c665;
+#line 7
+category c666;
+#line 7
+category c667;
+#line 7
+category c668;
+#line 7
+category c669;
+#line 7
+category c670;
+#line 7
+category c671;
+#line 7
+category c672;
+#line 7
+category c673;
+#line 7
+category c674;
+#line 7
+category c675;
+#line 7
+category c676;
+#line 7
+category c677;
+#line 7
+category c678;
+#line 7
+category c679;
+#line 7
+category c680;
+#line 7
+category c681;
+#line 7
+category c682;
+#line 7
+category c683;
+#line 7
+category c684;
+#line 7
+category c685;
+#line 7
+category c686;
+#line 7
+category c687;
+#line 7
+category c688;
+#line 7
+category c689;
+#line 7
+category c690;
+#line 7
+category c691;
+#line 7
+category c692;
+#line 7
+category c693;
+#line 7
+category c694;
+#line 7
+category c695;
+#line 7
+category c696;
+#line 7
+category c697;
+#line 7
+category c698;
+#line 7
+category c699;
+#line 7
+category c700;
+#line 7
+category c701;
+#line 7
+category c702;
+#line 7
+category c703;
+#line 7
+category c704;
+#line 7
+category c705;
+#line 7
+category c706;
+#line 7
+category c707;
+#line 7
+category c708;
+#line 7
+category c709;
+#line 7
+category c710;
+#line 7
+category c711;
+#line 7
+category c712;
+#line 7
+category c713;
+#line 7
+category c714;
+#line 7
+category c715;
+#line 7
+category c716;
+#line 7
+category c717;
+#line 7
+category c718;
+#line 7
+category c719;
+#line 7
+category c720;
+#line 7
+category c721;
+#line 7
+category c722;
+#line 7
+category c723;
+#line 7
+category c724;
+#line 7
+category c725;
+#line 7
+category c726;
+#line 7
+category c727;
+#line 7
+category c728;
+#line 7
+category c729;
+#line 7
+category c730;
+#line 7
+category c731;
+#line 7
+category c732;
+#line 7
+category c733;
+#line 7
+category c734;
+#line 7
+category c735;
+#line 7
+category c736;
+#line 7
+category c737;
+#line 7
+category c738;
+#line 7
+category c739;
+#line 7
+category c740;
+#line 7
+category c741;
+#line 7
+category c742;
+#line 7
+category c743;
+#line 7
+category c744;
+#line 7
+category c745;
+#line 7
+category c746;
+#line 7
+category c747;
+#line 7
+category c748;
+#line 7
+category c749;
+#line 7
+category c750;
+#line 7
+category c751;
+#line 7
+category c752;
+#line 7
+category c753;
+#line 7
+category c754;
+#line 7
+category c755;
+#line 7
+category c756;
+#line 7
+category c757;
+#line 7
+category c758;
+#line 7
+category c759;
+#line 7
+category c760;
+#line 7
+category c761;
+#line 7
+category c762;
+#line 7
+category c763;
+#line 7
+category c764;
+#line 7
+category c765;
+#line 7
+category c766;
+#line 7
+category c767;
+#line 7
+category c768;
+#line 7
+category c769;
+#line 7
+category c770;
+#line 7
+category c771;
+#line 7
+category c772;
+#line 7
+category c773;
+#line 7
+category c774;
+#line 7
+category c775;
+#line 7
+category c776;
+#line 7
+category c777;
+#line 7
+category c778;
+#line 7
+category c779;
+#line 7
+category c780;
+#line 7
+category c781;
+#line 7
+category c782;
+#line 7
+category c783;
+#line 7
+category c784;
+#line 7
+category c785;
+#line 7
+category c786;
+#line 7
+category c787;
+#line 7
+category c788;
+#line 7
+category c789;
+#line 7
+category c790;
+#line 7
+category c791;
+#line 7
+category c792;
+#line 7
+category c793;
+#line 7
+category c794;
+#line 7
+category c795;
+#line 7
+category c796;
+#line 7
+category c797;
+#line 7
+category c798;
+#line 7
+category c799;
+#line 7
+category c800;
+#line 7
+category c801;
+#line 7
+category c802;
+#line 7
+category c803;
+#line 7
+category c804;
+#line 7
+category c805;
+#line 7
+category c806;
+#line 7
+category c807;
+#line 7
+category c808;
+#line 7
+category c809;
+#line 7
+category c810;
+#line 7
+category c811;
+#line 7
+category c812;
+#line 7
+category c813;
+#line 7
+category c814;
+#line 7
+category c815;
+#line 7
+category c816;
+#line 7
+category c817;
+#line 7
+category c818;
+#line 7
+category c819;
+#line 7
+category c820;
+#line 7
+category c821;
+#line 7
+category c822;
+#line 7
+category c823;
+#line 7
+category c824;
+#line 7
+category c825;
+#line 7
+category c826;
+#line 7
+category c827;
+#line 7
+category c828;
+#line 7
+category c829;
+#line 7
+category c830;
+#line 7
+category c831;
+#line 7
+category c832;
+#line 7
+category c833;
+#line 7
+category c834;
+#line 7
+category c835;
+#line 7
+category c836;
+#line 7
+category c837;
+#line 7
+category c838;
+#line 7
+category c839;
+#line 7
+category c840;
+#line 7
+category c841;
+#line 7
+category c842;
+#line 7
+category c843;
+#line 7
+category c844;
+#line 7
+category c845;
+#line 7
+category c846;
+#line 7
+category c847;
+#line 7
+category c848;
+#line 7
+category c849;
+#line 7
+category c850;
+#line 7
+category c851;
+#line 7
+category c852;
+#line 7
+category c853;
+#line 7
+category c854;
+#line 7
+category c855;
+#line 7
+category c856;
+#line 7
+category c857;
+#line 7
+category c858;
+#line 7
+category c859;
+#line 7
+category c860;
+#line 7
+category c861;
+#line 7
+category c862;
+#line 7
+category c863;
+#line 7
+category c864;
+#line 7
+category c865;
+#line 7
+category c866;
+#line 7
+category c867;
+#line 7
+category c868;
+#line 7
+category c869;
+#line 7
+category c870;
+#line 7
+category c871;
+#line 7
+category c872;
+#line 7
+category c873;
+#line 7
+category c874;
+#line 7
+category c875;
+#line 7
+category c876;
+#line 7
+category c877;
+#line 7
+category c878;
+#line 7
+category c879;
+#line 7
+category c880;
+#line 7
+category c881;
+#line 7
+category c882;
+#line 7
+category c883;
+#line 7
+category c884;
+#line 7
+category c885;
+#line 7
+category c886;
+#line 7
+category c887;
+#line 7
+category c888;
+#line 7
+category c889;
+#line 7
+category c890;
+#line 7
+category c891;
+#line 7
+category c892;
+#line 7
+category c893;
+#line 7
+category c894;
+#line 7
+category c895;
+#line 7
+category c896;
+#line 7
+category c897;
+#line 7
+category c898;
+#line 7
+category c899;
+#line 7
+category c900;
+#line 7
+category c901;
+#line 7
+category c902;
+#line 7
+category c903;
+#line 7
+category c904;
+#line 7
+category c905;
+#line 7
+category c906;
+#line 7
+category c907;
+#line 7
+category c908;
+#line 7
+category c909;
+#line 7
+category c910;
+#line 7
+category c911;
+#line 7
+category c912;
+#line 7
+category c913;
+#line 7
+category c914;
+#line 7
+category c915;
+#line 7
+category c916;
+#line 7
+category c917;
+#line 7
+category c918;
+#line 7
+category c919;
+#line 7
+category c920;
+#line 7
+category c921;
+#line 7
+category c922;
+#line 7
+category c923;
+#line 7
+category c924;
+#line 7
+category c925;
+#line 7
+category c926;
+#line 7
+category c927;
+#line 7
+category c928;
+#line 7
+category c929;
+#line 7
+category c930;
+#line 7
+category c931;
+#line 7
+category c932;
+#line 7
+category c933;
+#line 7
+category c934;
+#line 7
+category c935;
+#line 7
+category c936;
+#line 7
+category c937;
+#line 7
+category c938;
+#line 7
+category c939;
+#line 7
+category c940;
+#line 7
+category c941;
+#line 7
+category c942;
+#line 7
+category c943;
+#line 7
+category c944;
+#line 7
+category c945;
+#line 7
+category c946;
+#line 7
+category c947;
+#line 7
+category c948;
+#line 7
+category c949;
+#line 7
+category c950;
+#line 7
+category c951;
+#line 7
+category c952;
+#line 7
+category c953;
+#line 7
+category c954;
+#line 7
+category c955;
+#line 7
+category c956;
+#line 7
+category c957;
+#line 7
+category c958;
+#line 7
+category c959;
+#line 7
+category c960;
+#line 7
+category c961;
+#line 7
+category c962;
+#line 7
+category c963;
+#line 7
+category c964;
+#line 7
+category c965;
+#line 7
+category c966;
+#line 7
+category c967;
+#line 7
+category c968;
+#line 7
+category c969;
+#line 7
+category c970;
+#line 7
+category c971;
+#line 7
+category c972;
+#line 7
+category c973;
+#line 7
+category c974;
+#line 7
+category c975;
+#line 7
+category c976;
+#line 7
+category c977;
+#line 7
+category c978;
+#line 7
+category c979;
+#line 7
+category c980;
+#line 7
+category c981;
+#line 7
+category c982;
+#line 7
+category c983;
+#line 7
+category c984;
+#line 7
+category c985;
+#line 7
+category c986;
+#line 7
+category c987;
+#line 7
+category c988;
+#line 7
+category c989;
+#line 7
+category c990;
+#line 7
+category c991;
+#line 7
+category c992;
+#line 7
+category c993;
+#line 7
+category c994;
+#line 7
+category c995;
+#line 7
+category c996;
+#line 7
+category c997;
+#line 7
+category c998;
+#line 7
+category c999;
+#line 7
+category c1000;
+#line 7
+category c1001;
+#line 7
+category c1002;
+#line 7
+category c1003;
+#line 7
+category c1004;
+#line 7
+category c1005;
+#line 7
+category c1006;
+#line 7
+category c1007;
+#line 7
+category c1008;
+#line 7
+category c1009;
+#line 7
+category c1010;
+#line 7
+category c1011;
+#line 7
+category c1012;
+#line 7
+category c1013;
+#line 7
+category c1014;
+#line 7
+category c1015;
+#line 7
+category c1016;
+#line 7
+category c1017;
+#line 7
+category c1018;
+#line 7
+category c1019;
+#line 7
+category c1020;
+#line 7
+category c1021;
+#line 7
+category c1022;
+#line 7
+category c1023;
+#line 7
+
+
+# Generate level definitions for each sensitivity and category.
+level s0:c0.c1023;
+#line 10
+
+
+
+#################################################
+# MLS policy constraints
+#
+
+#
+# Process constraints
+#
+
+# Process transition:  Require equivalence unless the subject is trusted.
+mlsconstrain process { transition dyntransition }
+	     ((h1 eq h2 and l1 eq l2) or t1 == mlstrustedsubject);
+
+# Process read operations: No read up unless trusted.
+mlsconstrain process { getsched getsession getpgid getcap getattr ptrace share }
+	     (l1 dom l2 or t1 == mlstrustedsubject);
+
+# Process write operations:  No write down unless trusted.
+mlsconstrain process { sigkill sigstop signal setsched setpgid setcap setrlimit ptrace share }
+	     (l1 domby l2 or t1 == mlstrustedsubject);
+
+#
+# Socket constraints
+#
+
+# Create/relabel operations:  Subject must be equivalent to object unless
+# the subject is trusted.  Sockets inherit the range of their creator.
+mlsconstrain { socket tcp_socket udp_socket rawip_socket netlink_socket packet_socket key_socket unix_stream_socket unix_dgram_socket appletalk_socket netlink_route_socket netlink_firewall_socket netlink_tcpdiag_socket netlink_nflog_socket netlink_xfrm_socket netlink_selinux_socket netlink_audit_socket netlink_ip6fw_socket netlink_dnrt_socket netlink_kobject_uevent_socket tun_socket } { create relabelfrom relabelto }
+	     ((h1 eq h2 and l1 eq l2) or t1 == mlstrustedsubject);
+
+# Datagram send: Sender must be dominated by receiver unless one of them is
+# trusted.
+mlsconstrain unix_dgram_socket { sendto }
+	     (l1 domby l2 or t1 == mlstrustedsubject or t2 == mlstrustedsubject);
+
+# Stream connect:  Client must be equivalent to server unless one of them
+# is trusted.
+mlsconstrain unix_stream_socket { connectto }
+	     (l1 eq l2 or t1 == mlstrustedsubject or t2 == mlstrustedsubject);
+
+#
+# Directory/file constraints
+#
+
+# Create/relabel operations:  Subject must be equivalent to object unless
+# the subject is trusted. Also, files should always be single-level.
+# Do NOT exempt mlstrustedobject types from this constraint.
+mlsconstrain { dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } } { create relabelfrom relabelto }
+	     (l2 eq h2 and (l1 eq l2 or t1 == mlstrustedsubject));
+
+#
+# Constraints for app data files only.
+#
+
+# Only constrain open, not read/write.
+# Also constrain other forms of manipulation, e.g. chmod/chown, unlink, rename, etc.
+# Subject must be equivalent to object unless the subject is trusted.
+mlsconstrain dir { open search setattr rename add_name remove_name reparent rmdir }
+	     (t2 != app_data_file or l1 eq l2 or t1 == mlstrustedsubject);
+mlsconstrain { file lnk_file sock_file } { open setattr unlink link rename }
+	     (t2 != app_data_file or l1 eq l2 or t1 == mlstrustedsubject);
+
+#
+# Constraints for file types other than app data files.
+#
+
+# Read operations: Subject must dominate object unless the subject
+# or the object is trusted.
+mlsconstrain dir { read getattr search }
+	     (t2 == app_data_file or l1 dom l2 or t1 == mlstrustedsubject or t2 == mlstrustedobject);
+
+mlsconstrain { file lnk_file sock_file chr_file blk_file } { read getattr execute }
+	     (t2 == app_data_file or l1 dom l2 or t1 == mlstrustedsubject or t2 == mlstrustedobject);
+
+# Write operations: Subject must be dominated by the object unless the
+# subject or the object is trusted.
+mlsconstrain dir { write setattr rename add_name remove_name reparent rmdir }
+	     (t2 == app_data_file or l1 domby l2 or t1 == mlstrustedsubject or t2 == mlstrustedobject);
+
+mlsconstrain { file lnk_file sock_file chr_file blk_file } { write setattr append unlink link rename }
+	     (t2 == app_data_file or l1 domby l2 or t1 == mlstrustedsubject or t2 == mlstrustedobject);
+
+# Special case for FIFOs.
+# These can be unnamed pipes, in which case they will be labeled with the
+# creating process' label. Thus we also have an exemption when the "object"
+# is a MLS trusted subject and can receive data at any level.
+mlsconstrain fifo_file { read getattr }
+	     (l1 dom l2 or t1 == mlstrustedsubject or t2 == mlstrustedobject or t2 == mlstrustedsubject);
+
+mlsconstrain fifo_file { write setattr append unlink link rename }
+	     (l1 domby l2 or t1 == mlstrustedsubject or t2 == mlstrustedobject or t2 == mlstrustedsubject);
+
+#
+# IPC constraints
+#
+
+# Create/destroy: equivalence or trusted.
+mlsconstrain { sem msgq shm ipc } { create destroy }
+	     (l2 eq h2 and (l1 eq l2 or t1 == mlstrustedsubject));
+
+# Read ops: No read up unless trusted.
+mlsconstrain { sem msgq shm ipc } { getattr read associate unix_read }
+	     (l1 dom l2 or t1 == mlstrustedsubject);
+
+# Write ops: No write down unless trusted.
+mlsconstrain { sem msgq shm ipc } { write unix_write }
+	     (l1 domby l2 or t1 == mlstrustedsubject);
+
+#
+# Binder IPC constraints
+#
+# Presently commented out, as apps are expected to call one another.
+# This would only make sense if apps were assigned categories
+# based on allowable communications rather than per-app categories.
+#mlsconstrain binder call
+#	(l1 eq l2 or t1 == mlstrustedsubject or t2 == mlstrustedsubject);
+#line 1 "external/sepolicy/policy_capabilities"
+# Enable new networking controls.
+policycap network_peer_controls;
+
+# Enable open permission check.
+policycap open_perms;
+#line 1 "external/sepolicy/te_macros"
+#####################################
+# domain_trans(olddomain, type, newdomain)
+# Allow a transition from olddomain to newdomain
+# upon executing a file labeled with type.
+# This only allows the transition; it does not
+# cause it to occur automatically - use domain_auto_trans
+# if that is what you want.
+#
+#line 21
+
+
+#####################################
+# domain_auto_trans(olddomain, type, newdomain)
+# Automatically transition from olddomain to newdomain
+# upon executing a file labeled with type.
+#
+#line 33
+
+
+#####################################
+# file_type_trans(domain, dir_type, file_type)
+# Allow domain to create a file labeled file_type in a
+# directory labeled dir_type.
+# This only allows the transition; it does not
+# cause it to occur automatically - use file_type_auto_trans
+# if that is what you want.
+#
+#line 49
+
+
+#####################################
+# file_type_auto_trans(domain, dir_type, file_type)
+# Automatically label new files with file_type when
+# they are created by domain in directories labeled dir_type.
+#
+#line 62
+
+
+#####################################
+# r_dir_file(domain, type)
+# Allow the specified domain to read directories, files
+# and symbolic links of the specified type.
+#line 71
+
+
+#####################################
+# unconfined_domain(domain)
+# Allow the specified domain to perform more privileged operations
+# than would be typically allowed. Please see the comments at the
+# top of unconfined.te.
+#
+#line 82
+
+
+#####################################
+# tmpfs_domain(domain)
+# Define and allow access to a unique type for
+# this domain when creating tmpfs / shmem / ashmem files.
+#line 92
+
+
+#####################################
+# init_daemon_domain(domain)
+# Set up a transition from init to the daemon domain
+# upon executing its binary.
+#line 101
+
+
+#####################################
+# app_domain(domain)
+# Allow a base set of permissions required for all apps.
+#line 112
+
+
+#####################################
+# relabelto_domain(domain)
+# Allows this domain to use the relabelto permission
+#line 119
+
+
+#####################################
+# platform_app_domain(domain)
+# Allow permissions specific to platform apps.
+#line 127
+
+
+#####################################
+# net_domain(domain)
+# Allow a base set of permissions required for network access.
+#line 134
+
+
+#####################################
+# bluetooth_domain(domain)
+# Allow a base set of permissions required for bluetooth access.
+#line 141
+
+
+#####################################
+# unix_socket_connect(clientdomain, socket, serverdomain)
+# Allow a local socket connection from clientdomain via
+# socket to serverdomain.
+#line 150
+
+
+#####################################
+# unix_socket_send(clientdomain, socket, serverdomain)
+# Allow a local socket send from clientdomain via
+# socket to serverdomain.
+#line 159
+
+
+#####################################
+# binder_use(domain)
+# Allow domain to use Binder IPC.
+#line 169
+
+
+#####################################
+# binder_call(clientdomain, serverdomain)
+# Allow clientdomain to perform binder IPC to serverdomain.
+#line 181
+
+
+#####################################
+# binder_service(domain)
+# Mark a domain as being a Binder service domain.
+# Used to allow binder IPC to the various system services.
+#line 189
+
+
+#####################################
+# selinux_check_access(domain)
+# Allow domain to check SELinux permissions via selinuxfs.
+#line 199
+
+
+#####################################
+# selinux_check_context(domain)
+# Allow domain to check SELinux contexts via selinuxfs.
+#line 208
+
+
+#####################################
+# selinux_getenforce(domain)
+# Allow domain to check whether SELinux is enforcing.
+#line 216
+
+
+#####################################
+# selinux_setenforce(domain)
+# Allow domain to set SELinux to enforcing.
+#line 225
+
+
+#####################################
+# selinux_setbool(domain)
+# Allow domain to set SELinux booleans.
+#line 234
+
+
+#####################################
+# security_access_policy(domain)
+# Read only access to all policy files and
+# selinuxfs
+#line 248
+
+
+#####################################
+# selinux_manage_policy(domain)
+# Ability to manage policy files and
+# trigger runtime reload.
+#line 261
+
+
+#####################################
+# mmac_manage_policy(domain)
+# Ability to manage mmac policy files,
+# trigger runtime reload, change
+# mmac enforcing mode and access logcat.
+#line 274
+
+
+#####################################
+# access_kmsg(domain)
+# Ability to read from kernel logs
+# and execute the klogctl syscall
+# in a non destructive manner. See
+# man 2 klogctl
+#line 284
+
+
+#####################################
+# write_klog(domain)
+# Ability to write to kernel log via
+# klog_write()
+# See system/core/libcutil/klog.c
+#line 295
+
+
+#####################################
+# create_pty(domain)
+# Allow domain to create and use a pty, isolated from any other domain ptys.
+#line 309
+
+
+#####################################
+# Non system_app application set
+#
+
+
+#####################################
+# Userdebug or eng builds
+# SELinux rules which apply only to userdebug or eng builds
+#
+
+
+#####################################
+# permissive_or_unconfined
+# Returns "permissive $1" if FORCE_PERMISSIVE_TO_UNCONFINED is false,
+# and "unconfined($1)" otherwise.
+#
+# This is used for experimental domains, where we want to ensure
+# the domain is unconfined+enforcing once new SELinux policy development
+# has ceased.
+#
+
+
+#####################################
+# write_logd(domain)
+# Ability to write to android log
+# daemon via sockets
+#line 345
+
+
+#####################################
+# read_logd(domain)
+# Ability to read from android
+# log daemon via sockets
+#line 353
+
+
+#####################################
+# control_logd(domain)
+# Ability to control
+# android log daemon via sockets
+#line 363
+
+#line 1 "external/sepolicy/attributes"
+######################################
+# Attribute declarations
+#
+
+# All types used for devices.
+attribute dev_type;
+
+# All types used for processes.
+attribute domain;
+
+# All types used for filesystems.
+attribute fs_type;
+
+# All types used for files that can exist on a labeled fs.
+# Do not use for pseudo file types.
+attribute file_type;
+
+# All types used for domain entry points.
+attribute exec_type;
+
+# All types used for /data files.
+attribute data_file_type;
+
+# All types use for sysfs files.
+attribute sysfs_type;
+
+# Attribute used for all sdcards
+attribute sdcard_type;
+
+# All types used for nodes/hosts.
+attribute node_type;
+
+# All types used for network interfaces.
+attribute netif_type;
+
+# All types used for network ports.
+attribute port_type;
+
+# All types used for property service
+attribute property_type;
+
+# All domains that can override MLS restrictions.
+# i.e. processes that can read up and write down.
+attribute mlstrustedsubject;
+
+# All types that can override MLS restrictions.
+# i.e. files that can be read by lower and written by higher
+attribute mlstrustedobject;
+
+# Domains that are allowed all permissions ("unconfined").
+attribute unconfineddomain;
+
+# All domains used for shells.
+attribute shelldomain;
+
+# All domains used for apps.
+attribute appdomain;
+
+# All domains used for apps with network access.
+attribute netdomain;
+
+# All domains used for apps with bluetooth access.
+attribute bluetoothdomain;
+
+# All domains used for binder service domains.
+attribute binderservicedomain;
+
+# Allow domains used for platform (signed by build key) apps.
+attribute platformappdomain;
+
+# All domains which are allowed the "relabelto" permission
+attribute relabeltodomain;
+#line 1 "external/sepolicy/adbd.te"
+# adbd seclabel is specified in init.rc since
+# it lives in the rootfs and has no unique file type.
+type adbd, domain;
+
+#line 7
+
+
+
+#line 9
+# Allow the necessary permissions.
+#line 9
+
+#line 9
+# Old domain may exec the file and transition to the new domain.
+#line 9
+allow adbd shell_exec:file { getattr open read execute };
+#line 9
+allow adbd shell:process transition;
+#line 9
+# New domain is entered by executing the file.
+#line 9
+allow shell shell_exec:file { entrypoint read execute };
+#line 9
+# New domain can send SIGCHLD to its caller.
+#line 9
+allow shell adbd:process sigchld;
+#line 9
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 9
+dontaudit adbd shell:process noatsecure;
+#line 9
+# XXX dontaudit candidate but requires further study.
+#line 9
+allow adbd shell:process { siginh rlimitinh };
+#line 9
+
+#line 9
+# Make the transition occur by default.
+#line 9
+type_transition adbd shell_exec:process shell;
+#line 9
+
+# this is an entrypoint
+allow adbd rootfs:file entrypoint;
+
+# Do not sanitize the environment or open fds of the shell.
+allow adbd shell:process noatsecure;
+
+# Set UID and GID to shell.  Set supplementary groups.
+allow adbd self:capability { setuid setgid };
+
+# Drop capabilities from bounding set on user builds.
+allow adbd self:capability setpcap;
+
+# Create and use network sockets.
+
+#line 23
+typeattribute adbd netdomain;
+#line 23
+
+
+# Access /dev/android_adb.
+allow adbd adb_device:chr_file { { getattr open read ioctl lock } { open append write } };
+
+# On emulator, access /dev/qemu*.
+allow adbd qemu_device:chr_file { { getattr open read ioctl lock } { open append write } };
+
+# Use a pseudo tty.
+allow adbd devpts:chr_file { { getattr open read ioctl lock } { open append write } };
+
+# adb push/pull /data/local/tmp.
+allow adbd shell_data_file:dir { { open getattr read search ioctl } { open search write add_name remove_name } };
+allow adbd shell_data_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+
+# adb push/pull sdcard.
+allow adbd sdcard_type:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow adbd sdcard_type:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+
+# Set service.adb.*, sys.powerctl properties.
+
+#line 43
+allow adbd property_socket:sock_file write;
+#line 43
+allow adbd init:unix_stream_socket connectto;
+#line 43
+
+allow adbd shell_prop:property_service set;
+allow adbd powerctl_prop:property_service set;
+
+# XXX Run /system/bin/vdc to connect to vold.  Run in a separate domain?
+# Also covers running /system/bin/bu.
+allow adbd system_file:file { { getattr open read ioctl lock } { getattr execute execute_no_trans } };
+
+#line 50
+allow adbd vold_socket:sock_file write;
+#line 50
+allow adbd vold:unix_stream_socket connectto;
+#line 50
+
+
+# Perform binder IPC to surfaceflinger (screencap)
+# XXX Run screencap in a separate domain?
+
+#line 54
+# Call the servicemanager and transfer references to it.
+#line 54
+allow adbd servicemanager:binder { call transfer };
+#line 54
+# rw access to /dev/binder and /dev/ashmem is presently granted to
+#line 54
+# all domains in domain.te.
+#line 54
+
+
+#line 55
+# Call the server domain and optionally transfer references to it.
+#line 55
+allow adbd surfaceflinger:binder { call transfer };
+#line 55
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 55
+allow surfaceflinger adbd:binder transfer;
+#line 55
+# Receive and use open files from the server.
+#line 55
+allow adbd surfaceflinger:fd use;
+#line 55
+
+
+# Read /data/misc/adb/adb_keys.
+allow adbd adb_keys_file:dir search;
+allow adbd adb_keys_file:file { getattr open read ioctl lock };
+
+# Allow access in case /data/misc/adb still has the old type.
+allow adbd system_data_file:dir search;
+allow adbd system_data_file:file { getattr open read ioctl lock };
+
+# ndk-gdb invokes adb forward to forward the gdbserver socket.
+allow adbd app_data_file:dir search;
+allow adbd app_data_file:sock_file write;
+allow adbd appdomain:unix_stream_socket connectto;
+
+# ndk-gdb invokes adb pull of app_process, linker, and libc.so.
+allow adbd zygote_exec:file { getattr open read ioctl lock };
+allow adbd system_file:file { getattr open read ioctl lock };
+#line 1 "external/sepolicy/app.te"
+###
+### Domain for all zygote spawned apps
+###
+### This file is the base policy for all zygote spawned apps.
+### Other policy files, such as isolated_app.te, untrusted_app.te, etc
+### extend from this policy. Only policies which should apply to ALL
+### zygote spawned apps should be added here.
+###
+
+# Dalvik Compiler JIT Mapping.
+allow appdomain self:process execmem;
+allow appdomain ashmem_device:chr_file execute;
+
+# Allow apps to connect to the keystore
+
+#line 15
+allow appdomain keystore_socket:sock_file write;
+#line 15
+allow appdomain keystore:unix_stream_socket connectto;
+#line 15
+
+
+# Receive and use open file descriptors inherited from zygote.
+allow appdomain zygote:fd use;
+
+# gdbserver for ndk-gdb reads the zygote.
+allow appdomain zygote_exec:file { getattr open read ioctl lock };
+
+# gdbserver for ndk-gdb ptrace attaches to app process.
+allow appdomain self:process ptrace;
+
+# Read system properties managed by zygote.
+allow appdomain zygote_tmpfs:file read;
+
+# Notify zygote of death;
+allow appdomain zygote:process sigchld;
+
+# Notify shell and adbd of death when spawned via runas for ndk-gdb.
+allow appdomain shell:process sigchld;
+allow appdomain adbd:process sigchld;
+
+# child shell or gdbserver pty access for runas.
+allow appdomain devpts:chr_file { getattr read write ioctl };
+
+# Communicate with system_server.
+allow appdomain system_server:fifo_file { { getattr open read ioctl lock } { open append write } };
+allow appdomain system_server:unix_stream_socket { read write setopt };
+
+#line 42
+# Call the server domain and optionally transfer references to it.
+#line 42
+allow appdomain system_server:binder { call transfer };
+#line 42
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 42
+allow system_server appdomain:binder transfer;
+#line 42
+# Receive and use open files from the server.
+#line 42
+allow appdomain system_server:fd use;
+#line 42
+
+
+# Communication with other apps via fifos
+allow appdomain appdomain:fifo_file { { getattr open read ioctl lock } { open append write } };
+
+# Communicate with surfaceflinger.
+allow appdomain surfaceflinger:unix_stream_socket { read write setopt };
+
+#line 49
+# Call the server domain and optionally transfer references to it.
+#line 49
+allow appdomain surfaceflinger:binder { call transfer };
+#line 49
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 49
+allow surfaceflinger appdomain:binder transfer;
+#line 49
+# Receive and use open files from the server.
+#line 49
+allow appdomain surfaceflinger:fd use;
+#line 49
+
+
+# App sandbox file accesses.
+allow appdomain app_data_file:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow appdomain app_data_file:{ file lnk_file sock_file fifo_file } { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+
+# Read/write data files created by the platform apps if they
+# were passed to the app via binder or local IPC.  Do not allow open.
+allow appdomain platform_app_data_file:file { getattr read write };
+
+# lib subdirectory of /data/data dir is system-owned.
+allow appdomain system_data_file:dir { open getattr read search ioctl };
+allow appdomain system_data_file:file { execute execute_no_trans open };
+
+# Execute the shell or other system executables.
+allow appdomain shell_exec:file { { getattr open read ioctl lock } { getattr execute execute_no_trans } };
+allow appdomain system_file:file { { getattr open read ioctl lock } { getattr execute execute_no_trans } };
+
+# Read/write wallpaper file (opened by system).
+allow appdomain wallpaper_file:file { getattr read write };
+
+# Write to /data/anr/traces.txt.
+allow appdomain anr_data_file:dir search;
+allow appdomain anr_data_file:file { open append };
+
+# Allow apps to send dump information to dumpstate
+allow appdomain dumpstate:fd use;
+allow appdomain dumpstate:unix_stream_socket { read write getopt getattr };
+allow appdomain shell_data_file:file { write getattr };
+
+# Write to /proc/net/xt_qtaguid/ctrl file.
+allow appdomain qtaguid_proc:file { { getattr open read ioctl lock } { open append write } };
+# Everybody can read the xt_qtaguid resource tracking misc dev.
+# So allow all apps to read from /dev/xt_qtaguid.
+allow appdomain qtaguid_device:chr_file { getattr open read ioctl lock };
+
+# Grant GPU access to all processes started by Zygote.
+# They need that to render the standard UI.
+allow appdomain gpu_device:chr_file { { { getattr open read ioctl lock } { open append write } } execute };
+
+# Use the Binder.
+
+#line 90
+# Call the servicemanager and transfer references to it.
+#line 90
+allow appdomain servicemanager:binder { call transfer };
+#line 90
+# rw access to /dev/binder and /dev/ashmem is presently granted to
+#line 90
+# all domains in domain.te.
+#line 90
+
+# Perform binder IPC to binder services.
+
+#line 92
+# Call the server domain and optionally transfer references to it.
+#line 92
+allow appdomain binderservicedomain:binder { call transfer };
+#line 92
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 92
+allow binderservicedomain appdomain:binder transfer;
+#line 92
+# Receive and use open files from the server.
+#line 92
+allow appdomain binderservicedomain:fd use;
+#line 92
+
+# Perform binder IPC to other apps.
+
+#line 94
+# Call the server domain and optionally transfer references to it.
+#line 94
+allow appdomain appdomain:binder { call transfer };
+#line 94
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 94
+allow appdomain appdomain:binder transfer;
+#line 94
+# Receive and use open files from the server.
+#line 94
+allow appdomain appdomain:fd use;
+#line 94
+
+
+# Appdomain interaction with isolated apps
+
+#line 97
+allow appdomain isolated_app:dir { open getattr read search ioctl };
+#line 97
+allow appdomain isolated_app:{ file lnk_file } { getattr open read ioctl lock };
+#line 97
+
+
+# Already connected, unnamed sockets being passed over some other IPC
+# hence no sock_file or connectto permission. This appears to be how
+# Chrome works, may need to be updated as more apps using isolated services
+# are examined.
+allow appdomain isolated_app:unix_stream_socket { read write };
+
+# Backup ability for every app. BMS opens and passes the fd
+# to any app that has backup ability. Hence, no open permissions here.
+allow appdomain backup_data_file:file { read write getattr };
+allow appdomain cache_backup_file:file { read write getattr };
+# Backup ability using 'adb backup'
+allow appdomain system_data_file:lnk_file getattr;
+
+# Allow all applications to read downloaded files
+allow appdomain download_file:dir search;
+allow appdomain download_file:file { getattr open read ioctl lock };
+
+# Allow applications to communicate with netd via /dev/socket/dnsproxyd
+# to do DNS resolution
+
+#line 118
+allow appdomain dnsproxyd_socket:sock_file write;
+#line 118
+allow appdomain netd:unix_stream_socket connectto;
+#line 118
+
+
+# Allow applications to communicate with drmserver over binder
+
+#line 121
+# Call the server domain and optionally transfer references to it.
+#line 121
+allow appdomain drmserver:binder { call transfer };
+#line 121
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 121
+allow drmserver appdomain:binder transfer;
+#line 121
+# Receive and use open files from the server.
+#line 121
+allow appdomain drmserver:fd use;
+#line 121
+
+
+# Allow applications to communicate with mediaserver over binder
+
+#line 124
+# Call the server domain and optionally transfer references to it.
+#line 124
+allow appdomain mediaserver:binder { call transfer };
+#line 124
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 124
+allow mediaserver appdomain:binder transfer;
+#line 124
+# Receive and use open files from the server.
+#line 124
+allow appdomain mediaserver:fd use;
+#line 124
+
+
+# Allow applications to make outbound tcp connections to any port
+allow appdomain port_type:tcp_socket name_connect;
+
+# Allow apps to see changes to the routing table.
+allow appdomain self:netlink_route_socket {
+    read
+    bind
+    create
+    nlmsg_read
+    ioctl
+    getattr
+    setattr
+    getopt
+    setopt
+    shutdown
+};
+
+# Allow apps to use rawip sockets. This is needed for apps which execute
+# /system/bin/ping, for example.
+allow appdomain self:rawip_socket { create { ioctl read getattr write setattr append bind connect getopt setopt shutdown } };
+
+# Allow apps to use the USB Accessory interface.
+# http://developer.android.com/guide/topics/connectivity/usb/accessory.html
+#
+# USB devices are first opened by the system server (USBDeviceManagerService)
+# and the file descriptor is passed to the right Activity via binder.
+allow appdomain usb_device:chr_file { read write getattr ioctl };
+allow appdomain usbaccessory_device:chr_file { read write getattr };
+
+# For art.
+allow appdomain dalvikcache_data_file:file execute;
+
+# For legacy unlabeled userdata on existing devices.
+# See discussion of Unlabeled files in domain.te for more information.
+allow appdomain unlabeled:file { getattr execute execute_no_trans };
+
+###
+### CTS-specific rules
+###
+
+# For cts/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/RootProcessScanner.java.
+# Reads /proc/pid/status and statm entries to check that
+# no unexpected root processes are running.
+# Also for cts/tests/tests/security/src/android/security/cts/VoldExploitTest.java
+# Reads /proc/pid/cmdline of vold.
+allow appdomain domain:dir { open read search getattr };
+allow appdomain domain:{ file lnk_file } { open read getattr };
+
+# For cts/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java.
+# testRunAsHasCorrectCapabilities
+allow appdomain runas_exec:file getattr;
+# Others are either allowed elsewhere or not desired.
+
+# For cts/tests/tests/security/src/android/security/cts/SELinuxTest.java
+# Check SELinux policy and contexts.
+
+#line 181
+allow appdomain selinuxfs:dir { open getattr read search ioctl };
+#line 181
+allow appdomain selinuxfs:file { { getattr open read ioctl lock } { open append write } };
+#line 181
+allow appdomain kernel:security compute_av;
+#line 181
+allow appdomain self:netlink_selinux_socket *;
+#line 181
+
+
+#line 182
+allow appdomain selinuxfs:dir { open getattr read search ioctl };
+#line 182
+allow appdomain selinuxfs:file { { getattr open read ioctl lock } { open append write } };
+#line 182
+allow appdomain kernel:security check_context;
+#line 182
+
+# Validate that each process is running in the correct security context.
+allow appdomain domain:process getattr;
+
+# logd access
+
+#line 187
+
+#line 187
+allow appdomain logdr_socket:sock_file write;
+#line 187
+allow appdomain logd:unix_stream_socket connectto;
+#line 187
+
+#line 187
+
+# application inherit logd write socket (urge is to deprecate this long term)
+allow appdomain zygote:unix_dgram_socket write;
+
+###
+### Neverallow rules
+###
+### These are things that Android apps should NEVER be able to do
+###
+
+# Superuser capabilities.
+# bluetooth requires net_admin.
+neverallow { appdomain -unconfineddomain -bluetooth } self:capability *;
+neverallow { appdomain -unconfineddomain } self:capability2 *;
+
+# Block device access.
+neverallow { appdomain -unconfineddomain } dev_type:blk_file { read write };
+
+# Access to any of the following character devices.
+neverallow { appdomain -unconfineddomain } {
+    audio_device
+    camera_device
+    dm_device
+    radio_device
+    gps_device
+    rpmsg_device
+}:chr_file { read write };
+
+# Note: Try expanding list of app domains in the future.
+neverallow { untrusted_app isolated_app shell -unconfineddomain }
+    graphics_device:chr_file { read write };
+
+neverallow { appdomain -nfc -unconfineddomain } nfc_device:chr_file
+    { read write };
+neverallow { appdomain -bluetooth -unconfineddomain } hci_attach_dev:chr_file
+    { read write };
+neverallow { appdomain -unconfineddomain } tee_device:chr_file { read write };
+
+# Set SELinux enforcing mode, booleans or any other SELinux settings.
+neverallow { appdomain -unconfineddomain } kernel:security
+    { setenforce setbool setsecparam setcheckreqprot };
+
+# Load security policy.
+neverallow appdomain kernel:security load_policy;
+
+# Privileged netlink socket interfaces.
+neverallow { appdomain -unconfineddomain }
+    self:{
+        netlink_socket
+        netlink_firewall_socket
+        netlink_tcpdiag_socket
+        netlink_nflog_socket
+        netlink_xfrm_socket
+        netlink_audit_socket
+        netlink_ip6fw_socket
+        netlink_dnrt_socket
+        netlink_kobject_uevent_socket
+    } *;
+
+# Sockets under /dev/socket that are not specifically typed.
+neverallow { appdomain -unconfineddomain } socket_device:sock_file write;
+
+# Unix domain sockets.
+neverallow { appdomain -unconfineddomain } adbd_socket:sock_file write;
+neverallow { appdomain -unconfineddomain } installd_socket:sock_file write;
+neverallow { appdomain -bluetooth -radio -shell -system_app -unconfineddomain }
+    property_socket:sock_file write;
+neverallow { appdomain -radio -unconfineddomain } rild_socket:sock_file write;
+neverallow { appdomain -unconfineddomain } vold_socket:sock_file write;
+neverallow { appdomain -unconfineddomain } zygote_socket:sock_file write;
+
+# ptrace access to non-app domains.
+neverallow { appdomain -unconfineddomain } { domain -appdomain }:process ptrace;
+
+# Write access to /proc/pid entries for any non-app domain.
+neverallow { appdomain -unconfineddomain } { domain -appdomain }:file write;
+
+# signal access to non-app domains.
+# sigchld allowed for parent death notification.
+# signull allowed for kill(pid, 0) existence test.
+# All others prohibited.
+neverallow { appdomain -unconfineddomain } { domain -appdomain }:process
+    { sigkill sigstop signal };
+
+# Transition to a non-app domain.
+# Exception for the shell domain, can transition to runas, etc.
+neverallow { appdomain -shell -unconfineddomain } ~appdomain:process
+    { transition dyntransition };
+
+# Map low memory.
+# Note: Take to domain.te and apply to all domains in the future.
+neverallow { appdomain -unconfineddomain } self:memprotect mmap_zero;
+
+# Write to rootfs.
+neverallow { appdomain -unconfineddomain } rootfs:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } }
+    { create write setattr relabelfrom relabelto append unlink link rename };
+
+# Write to /system.
+neverallow { appdomain -unconfineddomain } system_file:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } }
+    { create write setattr relabelfrom relabelto append unlink link rename };
+
+# Write to entrypoint executables.
+neverallow { appdomain -unconfineddomain } exec_type:file
+    { create write setattr relabelfrom relabelto append unlink link rename };
+
+# Write to system-owned parts of /data.
+# This is the default type for anything under /data not otherwise
+# specified in file_contexts.  Define a different type for portions
+# that should be writable by apps.
+# Exception for system_app for Settings.
+neverallow { appdomain -unconfineddomain -system_app }
+    system_data_file:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } }
+    { create write setattr relabelfrom relabelto append unlink link rename };
+
+# Write to various other parts of /data.
+neverallow { appdomain -system_app -unconfineddomain }
+    security_file:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } }
+    { create write setattr relabelfrom relabelto append unlink link rename };
+neverallow { appdomain -unconfineddomain } drm_data_file:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } }
+    { create write setattr relabelfrom relabelto append unlink link rename };
+neverallow { appdomain -unconfineddomain } gps_data_file:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } }
+    { create write setattr relabelfrom relabelto append unlink link rename };
+neverallow { appdomain -platform_app -unconfineddomain }
+    apk_data_file:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } }
+    { create write setattr relabelfrom relabelto append unlink link rename };
+neverallow { appdomain -platform_app -unconfineddomain }
+    apk_tmp_file:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } }
+    { create write setattr relabelfrom relabelto append unlink link rename };
+neverallow { appdomain -platform_app -unconfineddomain }
+    apk_private_data_file:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } }
+    { create write setattr relabelfrom relabelto append unlink link rename };
+neverallow { appdomain -platform_app -unconfineddomain }
+    apk_private_tmp_file:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } }
+    { create write setattr relabelfrom relabelto append unlink link rename };
+neverallow { appdomain -shell -unconfineddomain }
+    shell_data_file:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } }
+    { create setattr relabelfrom relabelto append unlink link rename };
+neverallow { appdomain -bluetooth -unconfineddomain }
+    bluetooth_data_file:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } }
+    { create write setattr relabelfrom relabelto append unlink link rename };
+neverallow { appdomain -unconfineddomain }
+    keystore_data_file:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } }
+    { create write setattr relabelfrom relabelto append unlink link rename };
+neverallow { appdomain -unconfineddomain }
+    systemkeys_data_file:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } }
+    { create write setattr relabelfrom relabelto append unlink link rename };
+neverallow { appdomain -unconfineddomain }
+    wifi_data_file:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } }
+    { create write setattr relabelfrom relabelto append unlink link rename };
+neverallow { appdomain -unconfineddomain }
+    dhcp_data_file:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } }
+    { create write setattr relabelfrom relabelto append unlink link rename };
+
+# Access to factory files.
+neverallow { appdomain -unconfineddomain }
+    efs_file:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } } { read write };
+
+# Write to various pseudo file systems.
+neverallow { appdomain -bluetooth -nfc -unconfineddomain }
+    sysfs:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } } write;
+neverallow { appdomain -unconfineddomain }
+    proc:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } } write;
+
+# Access to syslog(2) or /proc/kmsg.
+neverallow { appdomain -system_app -unconfineddomain }
+    kernel:system { syslog_read syslog_mod syslog_console };
+
+# Ability to perform any filesystem operation other than statfs(2).
+# i.e. no mount(2), unmount(2), etc.
+neverallow { appdomain -unconfineddomain } fs_type:filesystem ~getattr;
+
+# Ability to set system properties.
+neverallow { appdomain -system_app -radio -shell -bluetooth -unconfineddomain }
+    property_type:property_service set;
+#line 1 "external/sepolicy/binderservicedomain.te"
+# Rules common to all binder service domains
+
+# Allow dumpstate to collect information from binder services
+allow binderservicedomain dumpstate:fd use;
+allow binderservicedomain dumpstate:unix_stream_socket { read write getopt getattr };
+allow binderservicedomain shell_data_file:file { getattr write };
+
+# Allow dumpsys to work from adb shell
+allow binderservicedomain devpts:chr_file { { getattr open read ioctl lock } { open append write } };
+#line 1 "external/sepolicy/bluetooth.te"
+# bluetooth subsystem
+type bluetooth, domain;
+
+#line 3
+typeattribute bluetooth appdomain;
+#line 3
+# Label ashmem objects with our own unique type.
+#line 3
+
+#line 3
+type bluetooth_tmpfs, file_type;
+#line 3
+type_transition bluetooth tmpfs:file bluetooth_tmpfs;
+#line 3
+allow bluetooth bluetooth_tmpfs:file { read write };
+#line 3
+
+#line 3
+# Map with PROT_EXEC.
+#line 3
+allow bluetooth bluetooth_tmpfs:file execute;
+#line 3
+
+
+# Data file accesses.
+allow bluetooth bluetooth_data_file:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow bluetooth bluetooth_data_file:{ file lnk_file sock_file fifo_file } { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+
+# Socket creation under /data/misc/bluedroid.
+type_transition bluetooth bluetooth_data_file:sock_file bluetooth_socket;
+allow bluetooth bluetooth_socket:sock_file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+
+# bluetooth factory file accesses.
+
+#line 14
+allow bluetooth bluetooth_efs_file:dir { open getattr read search ioctl };
+#line 14
+allow bluetooth bluetooth_efs_file:{ file lnk_file } { getattr open read ioctl lock };
+#line 14
+
+
+# Device accesses.
+allow bluetooth { tun_device uhid_device hci_attach_dev }:chr_file { { getattr open read ioctl lock } { open append write } };
+
+# Other domains that can create and use bluetooth sockets.
+# SELinux does not presently define a specific socket class for
+# bluetooth sockets, nor does it distinguish among the bluetooth protocols.
+allow bluetoothdomain self:socket *;
+
+# sysfs access.
+allow bluetooth sysfs_bluetooth_writable:file { { getattr open read ioctl lock } { open append write } };
+allow bluetooth self:capability net_admin;
+
+# Allow clients to use a socket provided by the bluetooth app.
+allow bluetoothdomain bluetooth:unix_stream_socket { read write shutdown };
+
+# tethering
+allow bluetooth self:{ tun_socket udp_socket } { ioctl create };
+allow bluetooth efs_file:dir search;
+
+# Talk to init over the property socket.
+
+#line 36
+allow bluetooth property_socket:sock_file write;
+#line 36
+allow bluetooth init:unix_stream_socket connectto;
+#line 36
+
+
+# proc access.
+allow bluetooth proc_bluetooth_writable:file { { getattr open read ioctl lock } { open append write } };
+
+# bluetooth file transfers
+allow bluetooth sdcard_internal:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow bluetooth sdcard_internal:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+
+# Allow reading of media_rw_data_file file descriptors
+# passed to bluetooth
+allow bluetooth media_rw_data_file:file { read getattr };
+
+# Allow write access to bluetooth specific properties
+allow bluetooth bluetooth_prop:property_service set;
+
+###
+### Neverallow rules
+###
+### These are things that the bluetooth app should NEVER be able to do
+###
+
+# Superuser capabilities.
+# bluetooth requires net_admin.
+neverallow { bluetooth -unconfineddomain } self:capability ~net_admin;
+#line 1 "external/sepolicy/bootanim.te"
+# bootanimation oneshot service
+type bootanim, domain;
+type bootanim_exec, exec_type, file_type;
+
+
+#line 5
+
+#line 5
+# Allow the necessary permissions.
+#line 5
+
+#line 5
+# Old domain may exec the file and transition to the new domain.
+#line 5
+allow init bootanim_exec:file { getattr open read execute };
+#line 5
+allow init bootanim:process transition;
+#line 5
+# New domain is entered by executing the file.
+#line 5
+allow bootanim bootanim_exec:file { entrypoint read execute };
+#line 5
+# New domain can send SIGCHLD to its caller.
+#line 5
+allow bootanim init:process sigchld;
+#line 5
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 5
+dontaudit init bootanim:process noatsecure;
+#line 5
+# XXX dontaudit candidate but requires further study.
+#line 5
+allow init bootanim:process { siginh rlimitinh };
+#line 5
+
+#line 5
+# Make the transition occur by default.
+#line 5
+type_transition init bootanim_exec:process bootanim;
+#line 5
+
+#line 5
+
+#line 5
+type bootanim_tmpfs, file_type;
+#line 5
+type_transition bootanim tmpfs:file bootanim_tmpfs;
+#line 5
+allow bootanim bootanim_tmpfs:file { read write };
+#line 5
+
+#line 5
+
+
+
+#line 7
+# Call the servicemanager and transfer references to it.
+#line 7
+allow bootanim servicemanager:binder { call transfer };
+#line 7
+# rw access to /dev/binder and /dev/ashmem is presently granted to
+#line 7
+# all domains in domain.te.
+#line 7
+
+
+#line 8
+# Call the server domain and optionally transfer references to it.
+#line 8
+allow bootanim surfaceflinger:binder { call transfer };
+#line 8
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 8
+allow surfaceflinger bootanim:binder transfer;
+#line 8
+# Receive and use open files from the server.
+#line 8
+allow bootanim surfaceflinger:fd use;
+#line 8
+
+
+allow bootanim gpu_device:chr_file { { getattr open read ioctl lock } { open append write } };
+#line 1 "external/sepolicy/clatd.te"
+# 464xlat daemon
+type clatd, domain;
+
+#line 3
+typeattribute clatd mlstrustedsubject;
+#line 3
+typeattribute clatd unconfineddomain;
+#line 3
+
+type clatd_exec, exec_type, file_type;
+
+
+#line 6
+
+#line 6
+# Allow the necessary permissions.
+#line 6
+
+#line 6
+# Old domain may exec the file and transition to the new domain.
+#line 6
+allow init clatd_exec:file { getattr open read execute };
+#line 6
+allow init clatd:process transition;
+#line 6
+# New domain is entered by executing the file.
+#line 6
+allow clatd clatd_exec:file { entrypoint read execute };
+#line 6
+# New domain can send SIGCHLD to its caller.
+#line 6
+allow clatd init:process sigchld;
+#line 6
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 6
+dontaudit init clatd:process noatsecure;
+#line 6
+# XXX dontaudit candidate but requires further study.
+#line 6
+allow init clatd:process { siginh rlimitinh };
+#line 6
+
+#line 6
+# Make the transition occur by default.
+#line 6
+type_transition init clatd_exec:process clatd;
+#line 6
+
+#line 6
+
+#line 6
+type clatd_tmpfs, file_type;
+#line 6
+type_transition clatd tmpfs:file clatd_tmpfs;
+#line 6
+allow clatd clatd_tmpfs:file { read write };
+#line 6
+
+#line 6
+
+
+#line 7
+typeattribute clatd netdomain;
+#line 7
+
+#line 1 "external/sepolicy/debuggerd.te"
+# debugger interface
+type debuggerd, domain;
+type debuggerd_exec, exec_type, file_type;
+
+
+#line 5
+
+#line 5
+# Allow the necessary permissions.
+#line 5
+
+#line 5
+# Old domain may exec the file and transition to the new domain.
+#line 5
+allow init debuggerd_exec:file { getattr open read execute };
+#line 5
+allow init debuggerd:process transition;
+#line 5
+# New domain is entered by executing the file.
+#line 5
+allow debuggerd debuggerd_exec:file { entrypoint read execute };
+#line 5
+# New domain can send SIGCHLD to its caller.
+#line 5
+allow debuggerd init:process sigchld;
+#line 5
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 5
+dontaudit init debuggerd:process noatsecure;
+#line 5
+# XXX dontaudit candidate but requires further study.
+#line 5
+allow init debuggerd:process { siginh rlimitinh };
+#line 5
+
+#line 5
+# Make the transition occur by default.
+#line 5
+type_transition init debuggerd_exec:process debuggerd;
+#line 5
+
+#line 5
+
+#line 5
+type debuggerd_tmpfs, file_type;
+#line 5
+type_transition debuggerd tmpfs:file debuggerd_tmpfs;
+#line 5
+allow debuggerd debuggerd_tmpfs:file { read write };
+#line 5
+
+#line 5
+
+typeattribute debuggerd mlstrustedsubject;
+allow debuggerd self:capability { dac_override sys_ptrace chown kill fowner };
+allow debuggerd self:capability2 { syslog };
+allow debuggerd domain:dir { open getattr read search ioctl };
+allow debuggerd domain:file { getattr open read ioctl lock };
+allow debuggerd { domain -init -ueventd -watchdogd -healthd -adbd }:process ptrace;
+
+#line 12
+allow debuggerd security_file:dir { open getattr read search ioctl };
+#line 12
+allow debuggerd security_file:file { getattr open read ioctl lock };
+#line 12
+allow debuggerd security_file:lnk_file { getattr open read ioctl lock };
+#line 12
+allow debuggerd selinuxfs:dir { open getattr read search ioctl };
+#line 12
+allow debuggerd selinuxfs:file { getattr open read ioctl lock };
+#line 12
+allow debuggerd rootfs:dir { open getattr read search ioctl };
+#line 12
+allow debuggerd rootfs:file { getattr open read ioctl lock };
+#line 12
+
+allow debuggerd system_data_file:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow debuggerd system_data_file:dir relabelfrom;
+
+#line 15
+typeattribute debuggerd relabeltodomain;
+#line 15
+
+allow debuggerd tombstone_data_file:dir relabelto;
+allow debuggerd tombstone_data_file:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow debuggerd tombstone_data_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+allow debuggerd domain:process { sigstop signal };
+allow debuggerd exec_type:file { getattr open read ioctl lock };
+# Access app library
+allow debuggerd system_data_file:file open;
+
+# Connect to system_server via /data/system/ndebugsocket.
+
+#line 25
+allow debuggerd system_ndebug_socket:sock_file write;
+#line 25
+allow debuggerd system_server:unix_stream_socket connectto;
+#line 25
+
+
+#line 30
+
+
+# logd access
+
+#line 33
+
+#line 33
+allow debuggerd logdr_socket:sock_file write;
+#line 33
+allow debuggerd logd:unix_stream_socket connectto;
+#line 33
+
+#line 33
+
+#line 1 "external/sepolicy/device.te"
+# Device types
+type device, dev_type, fs_type;
+type alarm_device, dev_type, mlstrustedobject;
+type adb_device, dev_type;
+type ashmem_device, dev_type, mlstrustedobject;
+type audio_device, dev_type;
+type binder_device, dev_type, mlstrustedobject;
+type block_device, dev_type;
+type camera_device, dev_type;
+type dm_device, dev_type;
+type loop_device, dev_type;
+type radio_device, dev_type;
+type ram_device, dev_type;
+type console_device, dev_type;
+type cpuctl_device, dev_type;
+type fscklogs, dev_type;
+type full_device, dev_type;
+# GPU (used by most UI apps)
+type gpu_device, dev_type, mlstrustedobject;
+type graphics_device, dev_type;
+type hw_random_device, dev_type;
+type input_device, dev_type;
+type kmem_device, dev_type;
+type log_device, dev_type, mlstrustedobject;
+type mtd_device, dev_type;
+type mtp_device, dev_type, mlstrustedobject;
+type nfc_device, dev_type;
+type ptmx_device, dev_type, mlstrustedobject;
+type qemu_device, dev_type;
+type kmsg_device, dev_type;
+type null_device, dev_type, mlstrustedobject;
+type random_device, dev_type;
+type sensors_device, dev_type;
+type serial_device, dev_type;
+type socket_device, dev_type;
+type owntty_device, dev_type, mlstrustedobject;
+type tty_device, dev_type;
+type urandom_device, dev_type;
+type video_device, dev_type;
+type vcs_device, dev_type;
+type zero_device, dev_type;
+type fuse_device, dev_type;
+type iio_device, dev_type;
+type ion_device, dev_type, mlstrustedobject;
+type gps_device, dev_type;
+type qtaguid_device, dev_type;
+type watchdog_device, dev_type;
+type uhid_device, dev_type;
+type tun_device, dev_type, mlstrustedobject;
+type usbaccessory_device, dev_type;
+type usb_device, dev_type;
+type klog_device, dev_type;
+type properties_device, dev_type;
+
+# All devices have a uart for the hci
+# attach service. The uart dev node
+# varies per device. This type
+# is used in per device policy
+type hci_attach_dev, dev_type;
+
+# All devices have a rpmsg device for
+# achieving remoteproc and rpmsg modules
+type rpmsg_device, dev_type;
+
+# Partition layout block device
+type root_block_device, dev_type;
+#line 1 "external/sepolicy/dhcp.te"
+type dhcp, domain;
+
+#line 2
+typeattribute dhcp mlstrustedsubject;
+#line 2
+typeattribute dhcp unconfineddomain;
+#line 2
+
+type dhcp_exec, exec_type, file_type;
+type dhcp_data_file, file_type, data_file_type;
+
+
+#line 6
+
+#line 6
+# Allow the necessary permissions.
+#line 6
+
+#line 6
+# Old domain may exec the file and transition to the new domain.
+#line 6
+allow init dhcp_exec:file { getattr open read execute };
+#line 6
+allow init dhcp:process transition;
+#line 6
+# New domain is entered by executing the file.
+#line 6
+allow dhcp dhcp_exec:file { entrypoint read execute };
+#line 6
+# New domain can send SIGCHLD to its caller.
+#line 6
+allow dhcp init:process sigchld;
+#line 6
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 6
+dontaudit init dhcp:process noatsecure;
+#line 6
+# XXX dontaudit candidate but requires further study.
+#line 6
+allow init dhcp:process { siginh rlimitinh };
+#line 6
+
+#line 6
+# Make the transition occur by default.
+#line 6
+type_transition init dhcp_exec:process dhcp;
+#line 6
+
+#line 6
+
+#line 6
+type dhcp_tmpfs, file_type;
+#line 6
+type_transition dhcp tmpfs:file dhcp_tmpfs;
+#line 6
+allow dhcp dhcp_tmpfs:file { read write };
+#line 6
+
+#line 6
+
+
+#line 7
+typeattribute dhcp netdomain;
+#line 7
+
+
+allow dhcp cgroup:dir { create write add_name };
+allow dhcp self:capability { setgid setuid net_admin net_raw net_bind_service };
+allow dhcp self:packet_socket { create { ioctl read getattr write setattr append bind connect getopt setopt shutdown } };
+allow dhcp self:netlink_route_socket { { create { ioctl read getattr write setattr append bind connect getopt setopt shutdown } } nlmsg_write };
+allow dhcp self:rawip_socket { create { ioctl read getattr write setattr append bind connect getopt setopt shutdown } };
+allow dhcp shell_exec:file { { getattr open read ioctl lock } { getattr execute execute_no_trans } };
+allow dhcp system_file:file { { getattr open read ioctl lock } { getattr execute execute_no_trans } };
+# For /proc/sys/net/ipv4/conf/*/promote_secondaries
+allow dhcp proc_net:file write;
+allow dhcp system_prop:property_service set ;
+
+#line 19
+allow dhcp property_socket:sock_file write;
+#line 19
+allow dhcp init:unix_stream_socket connectto;
+#line 19
+
+allow dhcp owntty_device:chr_file { { getattr open read ioctl lock } { open append write } };
+
+type_transition dhcp system_data_file:{ dir file } dhcp_data_file;
+allow dhcp dhcp_data_file:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow dhcp dhcp_data_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+
+# PAN connections
+allow dhcp netd:fd use;
+allow dhcp netd:fifo_file { { getattr open read ioctl lock } { open append write } };
+allow dhcp netd:{ { udp_socket unix_dgram_socket } unix_stream_socket } { read write };
+allow dhcp netd:{ netlink_kobject_uevent_socket netlink_route_socket netlink_nflog_socket } { read write };
+#line 1 "external/sepolicy/dnsmasq.te"
+# DNS, DHCP services
+type dnsmasq, domain;
+
+#line 3
+typeattribute dnsmasq mlstrustedsubject;
+#line 3
+typeattribute dnsmasq unconfineddomain;
+#line 3
+
+type dnsmasq_exec, exec_type, file_type;
+
+allow dnsmasq self:capability { net_bind_service setgid setuid };
+allow dnsmasq self:tcp_socket { create { ioctl read getattr write setattr append bind connect getopt setopt shutdown } };
+
+allow dnsmasq dhcp_data_file:dir { open search write add_name remove_name };
+allow dnsmasq dhcp_data_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+allow dnsmasq port:tcp_socket name_bind;
+allow dnsmasq node:tcp_socket node_bind;
+#line 1 "external/sepolicy/domain.te"
+# Rules for all domains.
+
+# Allow reaping by init.
+allow domain init:process sigchld;
+
+# Read access to properties mapping.
+allow domain kernel:fd use;
+allow domain tmpfs:file { read getattr };
+
+# Search /storage/emulated tmpfs mount.
+allow domain tmpfs:dir { open getattr read search ioctl };
+
+# Intra-domain accesses.
+allow domain self:process ~{ execmem execstack execheap ptrace };
+allow domain self:fd use;
+allow domain self:dir { open getattr read search ioctl };
+allow domain self:lnk_file { getattr open read ioctl lock };
+allow domain self:{ fifo_file file } { { getattr open read ioctl lock } { open append write } };
+allow domain self:{ unix_dgram_socket unix_stream_socket } *;
+
+# Inherit or receive open files from others.
+allow domain init:fd use;
+allow domain system_server:fd use;
+
+# Connect to adbd and use a socket transferred from it.
+# This is used for e.g. adb backup/restore.
+allow domain adbd:unix_stream_socket connectto;
+allow domain adbd:fd use;
+allow domain adbd:unix_stream_socket { getattr getopt read write shutdown };
+
+#line 43
+
+
+###
+### Talk to debuggerd.
+###
+allow domain debuggerd:process sigchld;
+allow domain debuggerd:unix_stream_socket connectto;
+
+# Root fs.
+allow domain rootfs:dir { open getattr read search ioctl };
+allow domain rootfs:file { getattr open read ioctl lock };
+allow domain rootfs:lnk_file { getattr open read ioctl lock };
+
+# Device accesses.
+allow domain device:dir search;
+allow domain dev_type:lnk_file { getattr open read ioctl lock };
+allow domain devpts:dir search;
+allow domain device:file read;
+allow domain socket_device:dir search;
+allow domain owntty_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow domain null_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow domain zero_device:chr_file { getattr open read ioctl lock };
+allow domain ashmem_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow domain binder_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow domain ptmx_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow domain log_device:dir search;
+allow domain log_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow domain alarm_device:chr_file { getattr open read ioctl lock };
+allow domain urandom_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow domain random_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow domain properties_device:file { getattr open read ioctl lock };
+
+# logd access
+
+#line 76
+
+#line 76
+
+#line 76
+allow domain logdw_socket:sock_file write;
+#line 76
+allow domain logd:unix_dgram_socket sendto;
+#line 76
+
+#line 76
+
+
+# Filesystem accesses.
+allow domain fs_type:filesystem getattr;
+allow domain fs_type:dir getattr;
+
+# System file accesses.
+allow domain system_file:dir { open getattr read search ioctl };
+allow domain system_file:file { getattr open read ioctl lock };
+allow domain system_file:file execute;
+allow domain system_file:lnk_file { getattr open read ioctl lock };
+
+# Read files already opened under /data.
+allow domain system_data_file:dir { search getattr };
+allow domain system_data_file:file { getattr read };
+allow domain system_data_file:lnk_file { getattr open read ioctl lock };
+
+# Read apk files under /data/app.
+allow domain apk_data_file:dir { getattr search };
+allow domain apk_data_file:file { getattr open read ioctl lock };
+
+# Read /data/dalvik-cache.
+allow domain dalvikcache_data_file:dir { search getattr };
+allow domain dalvikcache_data_file:file { getattr open read ioctl lock };
+
+# Read already opened /cache files.
+allow domain cache_file:dir { open getattr read search ioctl };
+allow domain cache_file:file { getattr read };
+allow domain cache_file:lnk_file { getattr open read ioctl lock };
+
+# Read timezone related information
+
+#line 107
+allow domain zoneinfo_data_file:dir { open getattr read search ioctl };
+#line 107
+allow domain zoneinfo_data_file:{ file lnk_file } { getattr open read ioctl lock };
+#line 107
+
+
+# For /acct/uid/*/tasks.
+allow domain cgroup:dir { search write };
+allow domain cgroup:file { open append write };
+
+#Allow access to ion memory allocation device
+allow domain ion_device:chr_file { { getattr open read ioctl lock } { open append write } };
+
+# Read access to pseudo filesystems.
+
+#line 117
+allow domain proc:dir { open getattr read search ioctl };
+#line 117
+allow domain proc:{ file lnk_file } { getattr open read ioctl lock };
+#line 117
+
+
+#line 118
+allow domain sysfs:dir { open getattr read search ioctl };
+#line 118
+allow domain sysfs:{ file lnk_file } { getattr open read ioctl lock };
+#line 118
+
+
+#line 119
+allow domain sysfs_devices_system_cpu:dir { open getattr read search ioctl };
+#line 119
+allow domain sysfs_devices_system_cpu:{ file lnk_file } { getattr open read ioctl lock };
+#line 119
+
+
+#line 120
+allow domain inotify:dir { open getattr read search ioctl };
+#line 120
+allow domain inotify:{ file lnk_file } { getattr open read ioctl lock };
+#line 120
+
+
+#line 121
+allow domain cgroup:dir { open getattr read search ioctl };
+#line 121
+allow domain cgroup:{ file lnk_file } { getattr open read ioctl lock };
+#line 121
+
+
+#line 122
+allow domain proc_net:dir { open getattr read search ioctl };
+#line 122
+allow domain proc_net:{ file lnk_file } { getattr open read ioctl lock };
+#line 122
+
+
+# debugfs access
+allow domain debugfs:dir { open getattr read search ioctl };
+allow domain debugfs:file { open append write };
+
+# Get SELinux enforcing status.
+
+#line 129
+allow domain selinuxfs:dir { open getattr read search ioctl };
+#line 129
+allow domain selinuxfs:file { getattr open read ioctl lock };
+#line 129
+
+
+# security files
+allow domain security_file:dir { search getattr };
+allow domain security_file:file getattr;
+
+# World readable asec image contents
+allow domain asec_public_file:file { getattr open read ioctl lock };
+allow domain { asec_public_file asec_apk_file }:dir { open getattr read search ioctl };
+
+######## Backwards compatibility - Unlabeled files ############
+
+# Revert to DAC rules when looking at unlabeled files. Over time, the number
+# of unlabeled files should decrease.
+# TODO: delete these rules in the future.
+#
+# Note on relabelfrom: We allow any app relabelfrom, but without the relabelto
+# capability, it's essentially useless. This is needed to allow an app with
+# relabelto to relabel unlabeled files.
+#
+allow domain unlabeled:{ file lnk_file sock_file fifo_file } { { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } } relabelfrom };
+allow domain unlabeled:dir { { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } } relabelfrom };
+neverallow { domain -relabeltodomain } *:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } } relabelto;
+
+###
+### neverallow rules
+###
+
+# Limit ability to ptrace or read sensitive /proc/pid files of processes
+# with other UIDs to these whitelisted domains.
+neverallow { domain -debuggerd -vold -dumpstate -system_server } self:capability sys_ptrace;
+
+# Limit device node creation and raw I/O to these whitelisted domains.
+neverallow { domain -kernel -init -recovery -ueventd -watchdogd -healthd -vold -uncrypt } self:capability { sys_rawio mknod };
+
+# No domain needs mac_override as it is unused by SELinux.
+neverallow domain self:capability2 mac_override;
+
+# Only recovery needs mac_admin to set contexts not defined in current policy.
+neverallow { domain -recovery } self:capability2 mac_admin;
+
+# Only init should be able to load SELinux policies.
+# The first load technically occurs while still in the kernel domain,
+# but this does not trigger a denial since there is no policy yet.
+# Policy reload requires allowing this to the init domain.
+neverallow { domain -init } kernel:security load_policy;
+
+# Only init prior to switching context should be able to set enforcing mode.
+# init starts in kernel domain and switches to init domain via setcon in
+# the init.rc, so the setenforce occurs while still in kernel. After
+# switching domains, there is never any need to setenforce again by init.
+neverallow { domain -kernel } kernel:security { setenforce setcheckreqprot };
+
+# Only init, ueventd and system_server should be able to access HW RNG
+neverallow { domain -init -system_server -ueventd -unconfineddomain } hw_random_device:chr_file *;
+
+# Ensure that all entrypoint executables are in exec_type.
+neverallow domain { file_type -exec_type }:file entrypoint;
+
+# Ensure that nothing in userspace can access /dev/mem or /dev/kmem
+neverallow { domain -kernel -ueventd -init } kmem_device:chr_file *;
+neverallow domain kmem_device:chr_file ~{ create relabelto unlink setattr };
+
+# Only init should be able to configure kernel usermodehelpers or
+# security-sensitive proc settings.
+neverallow { domain -init } usermodehelper:file { append write };
+neverallow { domain -init } proc_security:file { append write };
+
+# No domain should be allowed to ptrace init.
+neverallow domain init:process ptrace;
+
+# Init can't receive binder calls. If this neverallow rule is being
+# triggered, it's probably due to a service with no SELinux domain.
+neverallow domain init:binder call;
+
+# Don't allow raw read/write/open access to block_device
+# Rather force a relabel to a more specific type
+neverallow { domain -kernel -init -recovery -vold -uncrypt } block_device:blk_file { open read write };
+
+# Don't allow raw read/write/open access to generic devices.
+# Rather force a relabel to a more specific type.
+# ueventd is exempt from this, as its managing these devices.
+neverallow { domain -unconfineddomain -ueventd } device:chr_file { open read write };
+
+# Limit what domains can mount filesystems or change their mount flags.
+# sdcard_type / vfat is exempt as a larger set of domains need
+# this capability, including device-specific domains.
+neverallow { domain -kernel -init -recovery -vold -zygote } { fs_type -sdcard_type }:filesystem { mount remount relabelfrom relabelto };
+#line 1 "external/sepolicy/drmserver.te"
+# drmserver - DRM service
+type drmserver, domain;
+type drmserver_exec, exec_type, file_type;
+
+
+#line 5
+
+#line 5
+# Allow the necessary permissions.
+#line 5
+
+#line 5
+# Old domain may exec the file and transition to the new domain.
+#line 5
+allow init drmserver_exec:file { getattr open read execute };
+#line 5
+allow init drmserver:process transition;
+#line 5
+# New domain is entered by executing the file.
+#line 5
+allow drmserver drmserver_exec:file { entrypoint read execute };
+#line 5
+# New domain can send SIGCHLD to its caller.
+#line 5
+allow drmserver init:process sigchld;
+#line 5
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 5
+dontaudit init drmserver:process noatsecure;
+#line 5
+# XXX dontaudit candidate but requires further study.
+#line 5
+allow init drmserver:process { siginh rlimitinh };
+#line 5
+
+#line 5
+# Make the transition occur by default.
+#line 5
+type_transition init drmserver_exec:process drmserver;
+#line 5
+
+#line 5
+
+#line 5
+type drmserver_tmpfs, file_type;
+#line 5
+type_transition drmserver tmpfs:file drmserver_tmpfs;
+#line 5
+allow drmserver drmserver_tmpfs:file { read write };
+#line 5
+
+#line 5
+
+typeattribute drmserver mlstrustedsubject;
+
+# Perform Binder IPC to system server.
+
+#line 9
+# Call the servicemanager and transfer references to it.
+#line 9
+allow drmserver servicemanager:binder { call transfer };
+#line 9
+# rw access to /dev/binder and /dev/ashmem is presently granted to
+#line 9
+# all domains in domain.te.
+#line 9
+
+
+#line 10
+# Call the server domain and optionally transfer references to it.
+#line 10
+allow drmserver system_server:binder { call transfer };
+#line 10
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 10
+allow system_server drmserver:binder transfer;
+#line 10
+# Receive and use open files from the server.
+#line 10
+allow drmserver system_server:fd use;
+#line 10
+
+
+#line 11
+# Call the server domain and optionally transfer references to it.
+#line 11
+allow drmserver appdomain:binder { call transfer };
+#line 11
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 11
+allow appdomain drmserver:binder transfer;
+#line 11
+# Receive and use open files from the server.
+#line 11
+allow drmserver appdomain:fd use;
+#line 11
+
+
+#line 12
+typeattribute drmserver binderservicedomain;
+#line 12
+
+
+# Perform Binder IPC to mediaserver
+
+#line 15
+# Call the server domain and optionally transfer references to it.
+#line 15
+allow drmserver mediaserver:binder { call transfer };
+#line 15
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 15
+allow mediaserver drmserver:binder transfer;
+#line 15
+# Receive and use open files from the server.
+#line 15
+allow drmserver mediaserver:fd use;
+#line 15
+
+
+allow drmserver sdcard_type:dir search;
+allow drmserver drm_data_file:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow drmserver drm_data_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+allow drmserver self:{ tcp_socket udp_socket } *;
+allow drmserver port:tcp_socket name_connect;
+allow drmserver tee_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow drmserver platform_app_data_file:file { read write getattr };
+allow drmserver app_data_file:file { read write getattr };
+allow drmserver sdcard_type:file { read write getattr };
+
+#line 26
+allow drmserver efs_file:dir { open getattr read search ioctl };
+#line 26
+allow drmserver efs_file:{ file lnk_file } { getattr open read ioctl lock };
+#line 26
+
+
+type drmserver_socket, file_type;
+
+# /data/app/tlcd_sock socket file.
+# Clearly, /data/app is the most logical place to create a socket.  Not.
+allow drmserver apk_data_file:dir { { open getattr read search ioctl } { open search write add_name remove_name } };
+type_transition drmserver apk_data_file:sock_file drmserver_socket;
+allow drmserver drmserver_socket:sock_file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+allow drmserver tee:unix_stream_socket connectto;
+# Delete old socket file if present.
+allow drmserver apk_data_file:sock_file unlink;
+
+# After taking a video, drmserver looks at the video file.
+
+#line 40
+allow drmserver media_rw_data_file:dir { open getattr read search ioctl };
+#line 40
+allow drmserver media_rw_data_file:{ file lnk_file } { getattr open read ioctl lock };
+#line 40
+
+#line 1 "external/sepolicy/dumpstate.te"
+# dumpstate
+type dumpstate, domain;
+
+#line 3
+typeattribute dumpstate mlstrustedsubject;
+#line 3
+typeattribute dumpstate unconfineddomain;
+#line 3
+
+type dumpstate_exec, exec_type, file_type;
+
+
+#line 6
+
+#line 6
+# Allow the necessary permissions.
+#line 6
+
+#line 6
+# Old domain may exec the file and transition to the new domain.
+#line 6
+allow init dumpstate_exec:file { getattr open read execute };
+#line 6
+allow init dumpstate:process transition;
+#line 6
+# New domain is entered by executing the file.
+#line 6
+allow dumpstate dumpstate_exec:file { entrypoint read execute };
+#line 6
+# New domain can send SIGCHLD to its caller.
+#line 6
+allow dumpstate init:process sigchld;
+#line 6
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 6
+dontaudit init dumpstate:process noatsecure;
+#line 6
+# XXX dontaudit candidate but requires further study.
+#line 6
+allow init dumpstate:process { siginh rlimitinh };
+#line 6
+
+#line 6
+# Make the transition occur by default.
+#line 6
+type_transition init dumpstate_exec:process dumpstate;
+#line 6
+
+#line 6
+
+#line 6
+type dumpstate_tmpfs, file_type;
+#line 6
+type_transition dumpstate tmpfs:file dumpstate_tmpfs;
+#line 6
+allow dumpstate dumpstate_tmpfs:file { read write };
+#line 6
+
+#line 6
+
+
+#line 7
+typeattribute dumpstate netdomain;
+#line 7
+
+
+#line 8
+typeattribute dumpstate relabeltodomain;
+#line 8
+
+
+#line 9
+# Call the servicemanager and transfer references to it.
+#line 9
+allow dumpstate servicemanager:binder { call transfer };
+#line 9
+# rw access to /dev/binder and /dev/ashmem is presently granted to
+#line 9
+# all domains in domain.te.
+#line 9
+
+
+# Drop privileges by switching UID / GID
+allow dumpstate self:capability { setuid setgid };
+
+# Allow dumpstate to scan through /proc/pid for all processes
+
+#line 15
+allow dumpstate domain:dir { open getattr read search ioctl };
+#line 15
+allow dumpstate domain:{ file lnk_file } { getattr open read ioctl lock };
+#line 15
+
+
+# Send signals to processes
+allow dumpstate self:capability kill;
+
+# Allow executing files on system, such as:
+#   /system/bin/toolbox
+#   /system/bin/logcat
+#   /system/bin/dumpsys
+allow dumpstate system_file:file execute_no_trans;
+
+# Create and write into /data/anr/
+allow dumpstate self:capability { dac_override chown fowner fsetid };
+allow dumpstate anr_data_file:dir { { { open getattr read search ioctl } { open search write add_name remove_name } } relabelto };
+allow dumpstate anr_data_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+allow dumpstate system_data_file:dir { { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } } relabelfrom };
+
+# Allow reading /data/system/uiderrors.txt
+# TODO: scope this down.
+allow dumpstate system_data_file:file { getattr open read ioctl lock };
+
+# Read dmesg
+allow dumpstate self:capability2 syslog;
+allow dumpstate kernel:system syslog_read;
+
+# Get process attributes
+allow dumpstate domain:process getattr;
+
+# Signal java processes to dump their stack
+allow dumpstate { appdomain system_server }:process signal;
+
+# Signal native processes to dump their stack.
+# This list comes from native_processes_to_dump in dumpstate/utils.c
+allow dumpstate { drmserver mediaserver sdcardd surfaceflinger }:process signal;
+
+# The /system/bin/ip command needs this for routing table information.
+allow dumpstate self:netlink_route_socket { write getattr setopt };
+
+# The vdc command needs to talk to the vold socket.
+
+#line 54
+allow dumpstate vold_socket:sock_file write;
+#line 54
+allow dumpstate vold:unix_stream_socket connectto;
+#line 54
+
+
+# Vibrate the device after we're done collecting the bugreport
+# /sys/class/timed_output/vibrator/enable
+# TODO: create a new file class, instead of allowing write access to all of /sys
+allow dumpstate sysfs:file { open append write };
+
+# Other random bits of data we want to collect
+allow dumpstate qtaguid_proc:file { getattr open read ioctl lock };
+allow dumpstate debugfs:file { getattr open read ioctl lock };
+
+# Allow dumpstate to make binder calls to any binder service
+
+#line 66
+# Call the server domain and optionally transfer references to it.
+#line 66
+allow dumpstate binderservicedomain:binder { call transfer };
+#line 66
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 66
+allow binderservicedomain dumpstate:binder transfer;
+#line 66
+# Receive and use open files from the server.
+#line 66
+allow dumpstate binderservicedomain:fd use;
+#line 66
+
+
+#line 67
+# Call the server domain and optionally transfer references to it.
+#line 67
+allow dumpstate appdomain:binder { call transfer };
+#line 67
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 67
+allow appdomain dumpstate:binder transfer;
+#line 67
+# Receive and use open files from the server.
+#line 67
+allow dumpstate appdomain:fd use;
+#line 67
+
+
+# Reading /proc/PID/maps of other processes
+allow dumpstate self:capability sys_ptrace;
+
+# Allow the bugreport service to create a file in
+# /data/data/com.android.shell/files/bugreports/bugreport
+allow dumpstate shell_data_file:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow dumpstate shell_data_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+
+# Run a shell.
+allow dumpstate shell_exec:file { { getattr open read ioctl lock } { getattr execute execute_no_trans } };
+
+# For running am and similar framework commands.
+# Run /system/bin/app_process.
+allow dumpstate zygote_exec:file { { getattr open read ioctl lock } { getattr execute execute_no_trans } };
+# Dalvik Compiler JIT.
+allow dumpstate ashmem_device:chr_file execute;
+allow dumpstate dumpstate_tmpfs:file execute;
+allow dumpstate self:process execmem;
+# For art.
+allow dumpstate dalvikcache_data_file:file execute;
+
+# logd access
+
+#line 91
+
+#line 91
+allow dumpstate logdr_socket:sock_file write;
+#line 91
+allow dumpstate logd:unix_stream_socket connectto;
+#line 91
+
+#line 91
+
+
+#line 92
+# Group AID_LOG checked by filesystem & logd
+#line 92
+# to permit control commands
+#line 92
+
+#line 92
+allow dumpstate logd_socket:sock_file write;
+#line 92
+allow dumpstate logd:unix_stream_socket connectto;
+#line 92
+
+#line 92
+
+#line 1 "external/sepolicy/file.te"
+# Filesystem types
+type labeledfs, fs_type;
+type pipefs, fs_type;
+type sockfs, fs_type;
+type rootfs, fs_type;
+type proc, fs_type;
+# Security-sensitive proc nodes that should not be writable to most.
+type proc_security, fs_type;
+# proc, sysfs, or other nodes that permit configuration of kernel usermodehelpers.
+type usermodehelper, fs_type, sysfs_type;
+type qtaguid_proc, fs_type, mlstrustedobject;
+type proc_bluetooth_writable, fs_type;
+type proc_net, fs_type;
+type selinuxfs, fs_type;
+type cgroup, fs_type, mlstrustedobject;
+type sysfs, fs_type, mlstrustedobject;
+type sysfs_writable, fs_type, sysfs_type, mlstrustedobject;
+type sysfs_bluetooth_writable, fs_type, sysfs_type, mlstrustedobject;
+type sysfs_nfc_power_writable, fs_type, sysfs_type, mlstrustedobject;
+type sysfs_wake_lock, fs_type, sysfs_type;
+# /sys/devices/system/cpu
+type sysfs_devices_system_cpu, fs_type, sysfs_type;
+# /sys/module/lowmemorykiller
+type sysfs_lowmemorykiller, fs_type, sysfs_type;
+type inotify, fs_type, mlstrustedobject;
+type devpts, fs_type, mlstrustedobject;
+type tmpfs, fs_type;
+type shm, fs_type;
+type mqueue, fs_type;
+type sdcard_internal, sdcard_type, fs_type, mlstrustedobject;
+type sdcard_external, sdcard_type, fs_type, mlstrustedobject;
+type debugfs, fs_type, mlstrustedobject;
+
+# File types
+type unlabeled, file_type;
+# Default type for anything under /system.
+type system_file, file_type;
+# Default type for anything under /data.
+type system_data_file, file_type, data_file_type;
+# /data/drm - DRM plugin data
+type drm_data_file, file_type, data_file_type;
+# /data/anr - ANR traces
+type anr_data_file, file_type, data_file_type, mlstrustedobject;
+# /data/tombstones - core dumps
+type tombstone_data_file, file_type, data_file_type;
+# /data/app - user-installed apps
+type apk_data_file, file_type, data_file_type;
+type apk_tmp_file, file_type, data_file_type, mlstrustedobject;
+# /data/app-private - forward-locked apps
+type apk_private_data_file, file_type, data_file_type;
+type apk_private_tmp_file, file_type, data_file_type, mlstrustedobject;
+# /data/dalvik-cache
+type dalvikcache_data_file, file_type, data_file_type;
+# /data/local - writable by shell
+type shell_data_file, file_type, data_file_type;
+# /data/gps
+type gps_data_file, file_type, data_file_type;
+
+# /data/misc subdirectories
+type adb_keys_file, file_type, data_file_type;
+type audio_data_file, file_type, data_file_type;
+type bluetooth_data_file, file_type, data_file_type;
+type camera_data_file, file_type, data_file_type;
+type keystore_data_file, file_type, data_file_type;
+type media_data_file, file_type, data_file_type;
+type media_rw_data_file, file_type, data_file_type;
+type nfc_data_file, file_type, data_file_type;
+type radio_data_file, file_type, data_file_type;
+type systemkeys_data_file, file_type, data_file_type;
+type vpn_data_file, file_type, data_file_type;
+type wifi_data_file, file_type, data_file_type;
+type zoneinfo_data_file, file_type, data_file_type;
+
+# Compatibility with type names used in vanilla Android 4.3 and 4.4.
+typealias audio_data_file alias audio_firmware_file;
+# /data/data subdirectories - app sandboxes
+type app_data_file, file_type, data_file_type;
+type platform_app_data_file, file_type, data_file_type, mlstrustedobject;
+# Default type for anything under /cache
+type cache_file, file_type, mlstrustedobject;
+# Type for /cache/.*\.{data|restore} and default
+# type for anything under /cache/backup
+type cache_backup_file, file_type, mlstrustedobject;
+# Default type for anything under /efs
+type efs_file, file_type;
+# Type for wallpaper file.
+type wallpaper_file, file_type, mlstrustedobject;
+# /mnt/asec
+type asec_apk_file, file_type, data_file_type;
+# Elements of asec files (/mnt/asec) that are world readable
+type asec_public_file, file_type, data_file_type;
+# /data/app-asec
+type asec_image_file, file_type, data_file_type;
+# /data/backup and /data/secure/backup
+type backup_data_file, file_type, data_file_type, mlstrustedobject;
+# For /data/security
+type security_file, file_type;
+# All devices have bluetooth efs files. But they
+# vary per device, so this type is used in per
+# device policy
+type bluetooth_efs_file, file_type;
+# Downloaded files
+type download_file, file_type;
+
+# Socket types
+type adbd_socket, file_type;
+type bluetooth_socket, file_type;
+type dnsproxyd_socket, file_type, mlstrustedobject;
+type dumpstate_socket, file_type;
+type gps_socket, file_type;
+type installd_socket, file_type;
+type keystore_socket, file_type;
+type lmkd_socket, file_type;
+type logd_debug, file_type;
+type logd_socket, file_type;
+type logdr_socket, file_type;
+type logdw_socket, file_type;
+type mdns_socket, file_type;
+type netd_socket, file_type;
+type property_socket, file_type;
+type qemud_socket, file_type;
+type racoon_socket, file_type;
+type rild_socket, file_type;
+type rild_debug_socket, file_type;
+type system_wpa_socket, file_type;
+type system_ndebug_socket, file_type;
+type vold_socket, file_type;
+type wpa_socket, file_type;
+type zygote_socket, file_type;
+
+# UART (for GPS) control proc file
+type gps_control, file_type;
+
+# Allow files to be created in their appropriate filesystems.
+allow fs_type self:filesystem associate;
+allow sysfs_type sysfs:filesystem associate;
+allow file_type labeledfs:filesystem associate;
+allow file_type tmpfs:filesystem associate;
+allow file_type rootfs:filesystem associate;
+allow dev_type tmpfs:filesystem associate;
+#line 1 "external/sepolicy/gpsd.te"
+# gpsd - GPS daemon
+type gpsd, domain;
+
+#line 3
+typeattribute gpsd mlstrustedsubject;
+#line 3
+typeattribute gpsd unconfineddomain;
+#line 3
+
+type gpsd_exec, exec_type, file_type;
+
+
+#line 6
+
+#line 6
+# Allow the necessary permissions.
+#line 6
+
+#line 6
+# Old domain may exec the file and transition to the new domain.
+#line 6
+allow init gpsd_exec:file { getattr open read execute };
+#line 6
+allow init gpsd:process transition;
+#line 6
+# New domain is entered by executing the file.
+#line 6
+allow gpsd gpsd_exec:file { entrypoint read execute };
+#line 6
+# New domain can send SIGCHLD to its caller.
+#line 6
+allow gpsd init:process sigchld;
+#line 6
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 6
+dontaudit init gpsd:process noatsecure;
+#line 6
+# XXX dontaudit candidate but requires further study.
+#line 6
+allow init gpsd:process { siginh rlimitinh };
+#line 6
+
+#line 6
+# Make the transition occur by default.
+#line 6
+type_transition init gpsd_exec:process gpsd;
+#line 6
+
+#line 6
+
+#line 6
+type gpsd_tmpfs, file_type;
+#line 6
+type_transition gpsd tmpfs:file gpsd_tmpfs;
+#line 6
+allow gpsd gpsd_tmpfs:file { read write };
+#line 6
+
+#line 6
+
+
+#line 7
+typeattribute gpsd netdomain;
+#line 7
+
+allow gpsd gps_data_file:dir { { open getattr read search ioctl } { open search write add_name remove_name } };
+allow gpsd gps_data_file:{ file lnk_file sock_file fifo_file } { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+# Socket is created by the daemon, not by init, and under /data/gps,
+# not under /dev/socket.
+type_transition gpsd gps_data_file:sock_file gps_socket;
+allow gpsd gps_socket:sock_file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+# XXX Label sysfs files with a specific type?
+allow gpsd sysfs:file { { getattr open read ioctl lock } { open append write } };
+
+allow gpsd gps_device:chr_file { { getattr open read ioctl lock } { open append write } };
+
+# Execute the shell or system commands.
+allow gpsd shell_exec:file { { getattr open read ioctl lock } { getattr execute execute_no_trans } };
+allow gpsd system_file:file { { getattr open read ioctl lock } { getattr execute execute_no_trans } };
+#line 1 "external/sepolicy/hci_attach.te"
+type hci_attach, domain;
+type hci_attach_exec, exec_type, file_type;
+
+
+#line 4
+
+#line 4
+# Allow the necessary permissions.
+#line 4
+
+#line 4
+# Old domain may exec the file and transition to the new domain.
+#line 4
+allow init hci_attach_exec:file { getattr open read execute };
+#line 4
+allow init hci_attach:process transition;
+#line 4
+# New domain is entered by executing the file.
+#line 4
+allow hci_attach hci_attach_exec:file { entrypoint read execute };
+#line 4
+# New domain can send SIGCHLD to its caller.
+#line 4
+allow hci_attach init:process sigchld;
+#line 4
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 4
+dontaudit init hci_attach:process noatsecure;
+#line 4
+# XXX dontaudit candidate but requires further study.
+#line 4
+allow init hci_attach:process { siginh rlimitinh };
+#line 4
+
+#line 4
+# Make the transition occur by default.
+#line 4
+type_transition init hci_attach_exec:process hci_attach;
+#line 4
+
+#line 4
+
+#line 4
+type hci_attach_tmpfs, file_type;
+#line 4
+type_transition hci_attach tmpfs:file hci_attach_tmpfs;
+#line 4
+allow hci_attach hci_attach_tmpfs:file { read write };
+#line 4
+
+#line 4
+
+
+allow hci_attach kernel:system module_request;
+allow hci_attach hci_attach_dev:chr_file { { getattr open read ioctl lock } { open append write } };
+allow hci_attach bluetooth_efs_file:dir { open getattr read search ioctl };
+allow hci_attach bluetooth_efs_file:file { getattr open read ioctl lock };
+#line 1 "external/sepolicy/healthd.te"
+# healthd seclabel is specified in init.rc since
+# it lives in the rootfs and has no unique file type.
+type healthd, domain;
+
+allow healthd rootfs:file { read entrypoint };
+
+#line 6
+type_transition healthd device:chr_file klog_device "__kmsg__";
+#line 6
+allow healthd klog_device:chr_file { create open write unlink };
+#line 6
+allow healthd device:dir { write add_name remove_name };
+#line 6
+
+# /dev/__null__ created by init prior to policy load,
+# open fd inherited by healthd.
+allow healthd tmpfs:chr_file { read write };
+
+allow healthd self:capability { net_admin mknod };
+allow healthd self:capability2 block_suspend;
+allow healthd self:netlink_kobject_uevent_socket { create { ioctl read getattr write setattr append bind connect getopt setopt shutdown } };
+
+#line 14
+# Call the servicemanager and transfer references to it.
+#line 14
+allow healthd servicemanager:binder { call transfer };
+#line 14
+# rw access to /dev/binder and /dev/ashmem is presently granted to
+#line 14
+# all domains in domain.te.
+#line 14
+
+
+#line 15
+typeattribute healthd binderservicedomain;
+#line 15
+
+
+#line 16
+# Call the server domain and optionally transfer references to it.
+#line 16
+allow healthd system_server:binder { call transfer };
+#line 16
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 16
+allow system_server healthd:binder transfer;
+#line 16
+# Receive and use open files from the server.
+#line 16
+allow healthd system_server:fd use;
+#line 16
+
+
+###
+### healthd: charger mode
+###
+
+allow healthd graphics_device:dir { open getattr read search ioctl };
+allow healthd graphics_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow healthd input_device:dir { open getattr read search ioctl };
+allow healthd input_device:chr_file { getattr open read ioctl lock };
+allow healthd ashmem_device:chr_file execute;
+allow healthd self:process execmem;
+#line 1 "external/sepolicy/hostapd.te"
+# userspace wifi access points
+type hostapd, domain;
+
+#line 3
+typeattribute hostapd mlstrustedsubject;
+#line 3
+typeattribute hostapd unconfineddomain;
+#line 3
+
+type hostapd_exec, exec_type, file_type;
+
+allow hostapd self:capability { net_admin net_raw setuid setgid };
+allow hostapd self:netlink_socket { create { ioctl read getattr write setattr append bind connect getopt setopt shutdown } };
+allow hostapd self:packet_socket { create write read };
+allow hostapd self:netlink_route_socket { bind create write nlmsg_write read };
+allow hostapd self:udp_socket { create ioctl };
+
+allow hostapd wifi_data_file:file { { getattr open read ioctl lock } { open append write } };
+allow hostapd wifi_data_file:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow hostapd wpa_socket:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow hostapd wpa_socket:sock_file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+allow hostapd netd:fd use;
+allow hostapd netd:udp_socket { read write };
+allow hostapd netd:netlink_kobject_uevent_socket { read write };
+allow hostapd netd:netlink_nflog_socket { read write };
+allow hostapd netd:netlink_route_socket { read write };
+allow hostapd netd:unix_stream_socket { read write };
+allow hostapd netd:fifo_file { read write };
+#line 1 "external/sepolicy/init_shell.te"
+# Restricted domain for shell processes spawned by init
+type init_shell, domain, shelldomain;
+
+#line 3
+# Allow the necessary permissions.
+#line 3
+
+#line 3
+# Old domain may exec the file and transition to the new domain.
+#line 3
+allow init shell_exec:file { getattr open read execute };
+#line 3
+allow init init_shell:process transition;
+#line 3
+# New domain is entered by executing the file.
+#line 3
+allow init_shell shell_exec:file { entrypoint read execute };
+#line 3
+# New domain can send SIGCHLD to its caller.
+#line 3
+allow init_shell init:process sigchld;
+#line 3
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 3
+dontaudit init init_shell:process noatsecure;
+#line 3
+# XXX dontaudit candidate but requires further study.
+#line 3
+allow init init_shell:process { siginh rlimitinh };
+#line 3
+
+#line 3
+# Make the transition occur by default.
+#line 3
+type_transition init shell_exec:process init_shell;
+#line 3
+
+
+#line 4
+typeattribute init_shell mlstrustedsubject;
+#line 4
+typeattribute init_shell unconfineddomain;
+#line 4
+
+
+# inherits from shelldomain.te
+#line 1 "external/sepolicy/init.te"
+# init switches to init domain (via init.rc).
+type init, domain;
+# init is unconfined.
+
+#line 4
+typeattribute init mlstrustedsubject;
+#line 4
+typeattribute init unconfineddomain;
+#line 4
+
+
+#line 5
+type init_tmpfs, file_type;
+#line 5
+type_transition init tmpfs:file init_tmpfs;
+#line 5
+allow init init_tmpfs:file { read write };
+#line 5
+
+
+#line 6
+typeattribute init relabeltodomain;
+#line 6
+
+# add a rule to handle unlabelled mounts
+allow init unlabeled:filesystem mount;
+
+allow init self:capability { sys_rawio mknod };
+
+allow init dev_type:blk_file { { getattr open read ioctl lock } { open append write } };
+allow init fs_type:filesystem *;
+allow init {fs_type dev_type file_type}:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } } relabelto;
+allow init kernel:security load_policy;
+allow init usermodehelper:file { { getattr open read ioctl lock } { open append write } };
+allow init proc_security:file { { getattr open read ioctl lock } { open append write } };
+
+# Transitions to seclabel processes in init.rc
+allow init adbd:process transition;
+allow init healthd:process transition;
+allow init recovery:process transition;
+allow init shell:process transition;
+allow init ueventd:process transition;
+allow init watchdogd:process transition;
+#line 1 "external/sepolicy/inputflinger.te"
+# inputflinger
+type inputflinger, domain;
+
+#line 3
+typeattribute inputflinger mlstrustedsubject;
+#line 3
+typeattribute inputflinger unconfineddomain;
+#line 3
+
+type inputflinger_exec, exec_type, file_type;
+
+
+#line 6
+
+#line 6
+# Allow the necessary permissions.
+#line 6
+
+#line 6
+# Old domain may exec the file and transition to the new domain.
+#line 6
+allow init inputflinger_exec:file { getattr open read execute };
+#line 6
+allow init inputflinger:process transition;
+#line 6
+# New domain is entered by executing the file.
+#line 6
+allow inputflinger inputflinger_exec:file { entrypoint read execute };
+#line 6
+# New domain can send SIGCHLD to its caller.
+#line 6
+allow inputflinger init:process sigchld;
+#line 6
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 6
+dontaudit init inputflinger:process noatsecure;
+#line 6
+# XXX dontaudit candidate but requires further study.
+#line 6
+allow init inputflinger:process { siginh rlimitinh };
+#line 6
+
+#line 6
+# Make the transition occur by default.
+#line 6
+type_transition init inputflinger_exec:process inputflinger;
+#line 6
+
+#line 6
+
+#line 6
+type inputflinger_tmpfs, file_type;
+#line 6
+type_transition inputflinger tmpfs:file inputflinger_tmpfs;
+#line 6
+allow inputflinger inputflinger_tmpfs:file { read write };
+#line 6
+
+#line 6
+
+
+#line 7
+# Call the servicemanager and transfer references to it.
+#line 7
+allow inputflinger servicemanager:binder { call transfer };
+#line 7
+# rw access to /dev/binder and /dev/ashmem is presently granted to
+#line 7
+# all domains in domain.te.
+#line 7
+
+
+#line 8
+typeattribute inputflinger binderservicedomain;
+#line 8
+
+#line 1 "external/sepolicy/installd.te"
+# installer daemon
+type installd, domain;
+type installd_exec, exec_type, file_type;
+
+
+#line 5
+
+#line 5
+# Allow the necessary permissions.
+#line 5
+
+#line 5
+# Old domain may exec the file and transition to the new domain.
+#line 5
+allow init installd_exec:file { getattr open read execute };
+#line 5
+allow init installd:process transition;
+#line 5
+# New domain is entered by executing the file.
+#line 5
+allow installd installd_exec:file { entrypoint read execute };
+#line 5
+# New domain can send SIGCHLD to its caller.
+#line 5
+allow installd init:process sigchld;
+#line 5
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 5
+dontaudit init installd:process noatsecure;
+#line 5
+# XXX dontaudit candidate but requires further study.
+#line 5
+allow init installd:process { siginh rlimitinh };
+#line 5
+
+#line 5
+# Make the transition occur by default.
+#line 5
+type_transition init installd_exec:process installd;
+#line 5
+
+#line 5
+
+#line 5
+type installd_tmpfs, file_type;
+#line 5
+type_transition installd tmpfs:file installd_tmpfs;
+#line 5
+allow installd installd_tmpfs:file { read write };
+#line 5
+
+#line 5
+
+
+#line 6
+typeattribute installd relabeltodomain;
+#line 6
+
+typeattribute installd mlstrustedsubject;
+allow installd self:capability { chown dac_override fowner fsetid setgid setuid };
+allow installd system_data_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+allow installd system_data_file:lnk_file create;
+allow installd dalvikcache_data_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+allow installd data_file_type:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow installd data_file_type:dir { relabelfrom relabelto };
+allow installd data_file_type:{ { { chr_file blk_file } { file lnk_file sock_file fifo_file } } } { getattr unlink };
+allow installd apk_data_file:file { getattr open read ioctl lock };
+allow installd apk_tmp_file:file { getattr open read ioctl lock };
+allow installd system_file:file { getattr execute execute_no_trans };
+allow installd cgroup:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow installd download_file:dir { { open getattr read search ioctl } write remove_name };
+allow installd download_file:file { { getattr open read ioctl lock } unlink };
+dontaudit installd self:capability sys_admin;
+# Check validity of SELinux context before use.
+
+#line 23
+allow installd selinuxfs:dir { open getattr read search ioctl };
+#line 23
+allow installd selinuxfs:file { { getattr open read ioctl lock } { open append write } };
+#line 23
+allow installd kernel:security check_context;
+#line 23
+
+# Read /seapp_contexts and /data/security/seapp_contexts
+
+#line 25
+allow installd security_file:dir { open getattr read search ioctl };
+#line 25
+allow installd security_file:file { getattr open read ioctl lock };
+#line 25
+allow installd security_file:lnk_file { getattr open read ioctl lock };
+#line 25
+allow installd selinuxfs:dir { open getattr read search ioctl };
+#line 25
+allow installd selinuxfs:file { getattr open read ioctl lock };
+#line 25
+allow installd rootfs:dir { open getattr read search ioctl };
+#line 25
+allow installd rootfs:file { getattr open read ioctl lock };
+#line 25
+
+# ASEC
+allow installd platform_app_data_file:lnk_file { create setattr };
+allow installd app_data_file:lnk_file { create setattr };
+allow installd asec_apk_file:file { getattr open read ioctl lock };
+allow installd bluetooth_data_file:lnk_file { create setattr };
+allow installd nfc_data_file:lnk_file { create setattr };
+allow installd radio_data_file:lnk_file { create setattr };
+allow installd shell_data_file:lnk_file { create setattr };
+#line 1 "external/sepolicy/isolated_app.te"
+###
+### Services with isolatedProcess=true in their manifest.
+###
+### This file defines the rules for isolated apps. An "isolated
+### app" is an APP with UID between AID_ISOLATED_START (99000)
+### and AID_ISOLATED_END (99999).
+###
+### isolated_app includes all the appdomain rules, plus the
+### additional following rules:
+###
+
+type isolated_app, domain;
+
+#line 13
+typeattribute isolated_app appdomain;
+#line 13
+# Label ashmem objects with our own unique type.
+#line 13
+
+#line 13
+type isolated_app_tmpfs, file_type;
+#line 13
+type_transition isolated_app tmpfs:file isolated_app_tmpfs;
+#line 13
+allow isolated_app isolated_app_tmpfs:file { read write };
+#line 13
+
+#line 13
+# Map with PROT_EXEC.
+#line 13
+allow isolated_app isolated_app_tmpfs:file execute;
+#line 13
+
+
+# Already connected, unnamed sockets being passed over some other IPC
+# hence no sock_file or connectto permission. This appears to be how
+# Chrome works, may need to be updated as more apps using isolated services
+# are examined.
+allow isolated_app appdomain:unix_stream_socket { read write };
+
+allow isolated_app dalvikcache_data_file:file execute;
+allow isolated_app apk_data_file:dir getattr;
+#line 1 "external/sepolicy/kernel.te"
+# Life begins with the kernel.
+type kernel, domain;
+
+allow kernel init:process dyntransition;
+
+# The kernel is unconfined.
+
+#line 7
+typeattribute kernel mlstrustedsubject;
+#line 7
+typeattribute kernel unconfineddomain;
+#line 7
+
+
+#line 8
+typeattribute kernel relabeltodomain;
+#line 8
+
+
+allow kernel {fs_type dev_type file_type}:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } } relabelto;
+allow kernel unlabeled:filesystem mount;
+allow kernel fs_type:filesystem *;
+
+# Initial setenforce by init prior to switching to init domain.
+allow kernel self:security setenforce;
+
+# Set checkreqprot by init.rc prior to switching to init domain.
+allow kernel self:security setcheckreqprot;
+
+# For operations performed by kernel or init prior to switching to init domain.
+## TODO: Investigate whether it is safe to remove these
+allow kernel self:capability { sys_rawio mknod };
+auditallow kernel self:capability { sys_rawio mknod };
+allow kernel dev_type:blk_file { { getattr open read ioctl lock } { open append write } };
+auditallow kernel dev_type:blk_file { { getattr open read ioctl lock } { open append write } };
+#line 1 "external/sepolicy/keystore.te"
+type keystore, domain;
+type keystore_exec, exec_type, file_type;
+
+# keystore daemon
+
+#line 5
+
+#line 5
+# Allow the necessary permissions.
+#line 5
+
+#line 5
+# Old domain may exec the file and transition to the new domain.
+#line 5
+allow init keystore_exec:file { getattr open read execute };
+#line 5
+allow init keystore:process transition;
+#line 5
+# New domain is entered by executing the file.
+#line 5
+allow keystore keystore_exec:file { entrypoint read execute };
+#line 5
+# New domain can send SIGCHLD to its caller.
+#line 5
+allow keystore init:process sigchld;
+#line 5
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 5
+dontaudit init keystore:process noatsecure;
+#line 5
+# XXX dontaudit candidate but requires further study.
+#line 5
+allow init keystore:process { siginh rlimitinh };
+#line 5
+
+#line 5
+# Make the transition occur by default.
+#line 5
+type_transition init keystore_exec:process keystore;
+#line 5
+
+#line 5
+
+#line 5
+type keystore_tmpfs, file_type;
+#line 5
+type_transition keystore tmpfs:file keystore_tmpfs;
+#line 5
+allow keystore keystore_tmpfs:file { read write };
+#line 5
+
+#line 5
+
+typeattribute keystore mlstrustedsubject;
+
+#line 7
+# Call the servicemanager and transfer references to it.
+#line 7
+allow keystore servicemanager:binder { call transfer };
+#line 7
+# rw access to /dev/binder and /dev/ashmem is presently granted to
+#line 7
+# all domains in domain.te.
+#line 7
+
+
+#line 8
+typeattribute keystore binderservicedomain;
+#line 8
+
+allow keystore keystore_data_file:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow keystore keystore_data_file:{ file lnk_file sock_file fifo_file } { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+allow keystore keystore_exec:file { getattr };
+allow keystore tee_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow keystore tee:unix_stream_socket connectto;
+#line 1 "external/sepolicy/lmkd.te"
+# lmkd low memory killer daemon
+type lmkd, domain;
+type lmkd_exec, exec_type, file_type;
+
+
+#line 5
+
+#line 5
+# Allow the necessary permissions.
+#line 5
+
+#line 5
+# Old domain may exec the file and transition to the new domain.
+#line 5
+allow init lmkd_exec:file { getattr open read execute };
+#line 5
+allow init lmkd:process transition;
+#line 5
+# New domain is entered by executing the file.
+#line 5
+allow lmkd lmkd_exec:file { entrypoint read execute };
+#line 5
+# New domain can send SIGCHLD to its caller.
+#line 5
+allow lmkd init:process sigchld;
+#line 5
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 5
+dontaudit init lmkd:process noatsecure;
+#line 5
+# XXX dontaudit candidate but requires further study.
+#line 5
+allow init lmkd:process { siginh rlimitinh };
+#line 5
+
+#line 5
+# Make the transition occur by default.
+#line 5
+type_transition init lmkd_exec:process lmkd;
+#line 5
+
+#line 5
+
+#line 5
+type lmkd_tmpfs, file_type;
+#line 5
+type_transition lmkd tmpfs:file lmkd_tmpfs;
+#line 5
+allow lmkd lmkd_tmpfs:file { read write };
+#line 5
+
+#line 5
+
+
+allow lmkd self:capability { dac_override sys_resource };
+
+## Open and write to /proc/PID/oom_score_adj
+## TODO: maybe scope this down?
+
+#line 11
+allow lmkd appdomain:dir { open getattr read search ioctl };
+#line 11
+allow lmkd appdomain:{ file lnk_file } { getattr open read ioctl lock };
+#line 11
+
+allow lmkd appdomain:file write;
+
+#line 13
+allow lmkd system_server:dir { open getattr read search ioctl };
+#line 13
+allow lmkd system_server:{ file lnk_file } { getattr open read ioctl lock };
+#line 13
+
+allow lmkd system_server:file write;
+
+## Writes to /sys/module/lowmemorykiller/parameters/minfree
+allow lmkd sysfs_lowmemorykiller:file { open append write };
+#line 1 "external/sepolicy/logd.te"
+# android user-space log manager
+type logd, domain;
+type logd_exec, exec_type, file_type;
+
+
+#line 5
+
+#line 5
+# Allow the necessary permissions.
+#line 5
+
+#line 5
+# Old domain may exec the file and transition to the new domain.
+#line 5
+allow init logd_exec:file { getattr open read execute };
+#line 5
+allow init logd:process transition;
+#line 5
+# New domain is entered by executing the file.
+#line 5
+allow logd logd_exec:file { entrypoint read execute };
+#line 5
+# New domain can send SIGCHLD to its caller.
+#line 5
+allow logd init:process sigchld;
+#line 5
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 5
+dontaudit init logd:process noatsecure;
+#line 5
+# XXX dontaudit candidate but requires further study.
+#line 5
+allow init logd:process { siginh rlimitinh };
+#line 5
+
+#line 5
+# Make the transition occur by default.
+#line 5
+type_transition init logd_exec:process logd;
+#line 5
+
+#line 5
+
+#line 5
+type logd_tmpfs, file_type;
+#line 5
+type_transition logd tmpfs:file logd_tmpfs;
+#line 5
+allow logd logd_tmpfs:file { read write };
+#line 5
+
+#line 5
+
+allow logd self:unix_stream_socket *;
+
+allow logd self:capability { setuid setgid sys_nice };
+
+
+#line 10
+allow logd domain:dir { open getattr read search ioctl };
+#line 10
+allow logd domain:{ file lnk_file } { getattr open read ioctl lock };
+#line 10
+
+
+#line 17
+
+
+###
+### Neverallow rules
+###
+### logd should NEVER do any of this
+
+# Block device access.
+neverallow logd dev_type:blk_file { read write };
+
+# ptrace any other app
+neverallow logd domain:process ptrace;
+
+# Write to /system.
+neverallow logd system_file:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } } write;
+
+# Write to files in /data/data or system files on /data
+neverallow logd { app_data_file system_data_file }:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } } write;
+#line 1 "external/sepolicy/media_app.te"
+###
+### Apps signed with the media key.
+###
+
+type media_app, domain;
+
+#line 6
+typeattribute media_app appdomain;
+#line 6
+# Label ashmem objects with our own unique type.
+#line 6
+
+#line 6
+type media_app_tmpfs, file_type;
+#line 6
+type_transition media_app tmpfs:file media_app_tmpfs;
+#line 6
+allow media_app media_app_tmpfs:file { read write };
+#line 6
+
+#line 6
+# Map with PROT_EXEC.
+#line 6
+allow media_app media_app_tmpfs:file execute;
+#line 6
+
+
+#line 7
+typeattribute media_app platformappdomain;
+#line 7
+typeattribute media_app mlstrustedsubject;
+#line 7
+
+
+#line 8
+typeattribute media_app binderservicedomain;
+#line 8
+
+# Access the network.
+
+#line 10
+typeattribute media_app netdomain;
+#line 10
+
+# Access /dev/mtp_usb.
+allow media_app mtp_device:chr_file { { getattr open read ioctl lock } { open append write } };
+# Write to /cache.
+allow media_app cache_file:dir { { open getattr read search ioctl } { open search write add_name remove_name } };
+allow media_app cache_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+# Stat /cache/lost+found
+allow media_app unlabeled:file getattr;
+allow media_app unlabeled:dir getattr;
+# Stat /cache/backup
+allow media_app cache_backup_file:file getattr;
+allow media_app cache_backup_file:dir getattr;
+# Read files in the rootdir (in particular, file_contexts for restorecon).
+allow media_app rootfs:file { getattr open read ioctl lock };
+allow media_app download_file:dir { { open getattr read search ioctl } { open search write add_name remove_name } };
+allow media_app download_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+# Allow platform apps to mark platform app data files as download files
+
+#line 27
+typeattribute media_app relabeltodomain;
+#line 27
+
+allow media_app platform_app_data_file:dir relabelfrom;
+allow media_app download_file:dir relabelto;
+#line 1 "external/sepolicy/mediaserver.te"
+# mediaserver - multimedia daemon
+type mediaserver, domain;
+
+#line 3
+typeattribute mediaserver mlstrustedsubject;
+#line 3
+typeattribute mediaserver unconfineddomain;
+#line 3
+
+type mediaserver_exec, exec_type, file_type;
+
+typeattribute mediaserver mlstrustedsubject;
+
+
+#line 8
+typeattribute mediaserver netdomain;
+#line 8
+
+
+#line 9
+
+#line 9
+# Allow the necessary permissions.
+#line 9
+
+#line 9
+# Old domain may exec the file and transition to the new domain.
+#line 9
+allow init mediaserver_exec:file { getattr open read execute };
+#line 9
+allow init mediaserver:process transition;
+#line 9
+# New domain is entered by executing the file.
+#line 9
+allow mediaserver mediaserver_exec:file { entrypoint read execute };
+#line 9
+# New domain can send SIGCHLD to its caller.
+#line 9
+allow mediaserver init:process sigchld;
+#line 9
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 9
+dontaudit init mediaserver:process noatsecure;
+#line 9
+# XXX dontaudit candidate but requires further study.
+#line 9
+allow init mediaserver:process { siginh rlimitinh };
+#line 9
+
+#line 9
+# Make the transition occur by default.
+#line 9
+type_transition init mediaserver_exec:process mediaserver;
+#line 9
+
+#line 9
+
+#line 9
+type mediaserver_tmpfs, file_type;
+#line 9
+type_transition mediaserver tmpfs:file mediaserver_tmpfs;
+#line 9
+allow mediaserver mediaserver_tmpfs:file { read write };
+#line 9
+
+#line 9
+
+
+#line 10
+allow mediaserver property_socket:sock_file write;
+#line 10
+allow mediaserver init:unix_stream_socket connectto;
+#line 10
+
+
+
+#line 12
+allow mediaserver sdcard_type:dir { open getattr read search ioctl };
+#line 12
+allow mediaserver sdcard_type:{ file lnk_file } { getattr open read ioctl lock };
+#line 12
+
+
+
+#line 14
+# Call the servicemanager and transfer references to it.
+#line 14
+allow mediaserver servicemanager:binder { call transfer };
+#line 14
+# rw access to /dev/binder and /dev/ashmem is presently granted to
+#line 14
+# all domains in domain.te.
+#line 14
+
+
+#line 15
+# Call the server domain and optionally transfer references to it.
+#line 15
+allow mediaserver binderservicedomain:binder { call transfer };
+#line 15
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 15
+allow binderservicedomain mediaserver:binder transfer;
+#line 15
+# Receive and use open files from the server.
+#line 15
+allow mediaserver binderservicedomain:fd use;
+#line 15
+
+
+#line 16
+# Call the server domain and optionally transfer references to it.
+#line 16
+allow mediaserver appdomain:binder { call transfer };
+#line 16
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 16
+allow appdomain mediaserver:binder transfer;
+#line 16
+# Receive and use open files from the server.
+#line 16
+allow mediaserver appdomain:fd use;
+#line 16
+
+
+#line 17
+typeattribute mediaserver binderservicedomain;
+#line 17
+
+
+allow mediaserver self:process execmem;
+allow mediaserver kernel:system module_request;
+allow mediaserver media_data_file:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow mediaserver media_data_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+allow mediaserver app_data_file:dir search;
+allow mediaserver app_data_file:file { { getattr open read ioctl lock } { open append write } };
+allow mediaserver platform_app_data_file:file { getattr read };
+allow mediaserver sdcard_type:file write;
+allow mediaserver { gpu_device graphics_device }:chr_file { { getattr open read ioctl lock } { open append write } };
+allow mediaserver video_device:dir { open getattr read search ioctl };
+allow mediaserver video_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow mediaserver audio_device:dir { open getattr read search ioctl };
+allow mediaserver qemu_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow mediaserver tee_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow mediaserver audio_prop:property_service set;
+
+# Access audio devices at all.
+allow mediaserver audio_device:chr_file { { getattr open read ioctl lock } { open append write } };
+
+# XXX Label with a specific type?
+allow mediaserver sysfs:file { { getattr open read ioctl lock } { open append write } };
+
+# XXX Why?
+allow mediaserver apk_data_file:file { read getattr };
+
+# Access camera device.
+allow mediaserver camera_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow mediaserver rpmsg_device:chr_file { { getattr open read ioctl lock } { open append write } };
+
+# Inter System processes communicate over named pipe (FIFO)
+allow mediaserver system_server:fifo_file { getattr open read ioctl lock };
+
+# Camera data
+
+#line 52
+allow mediaserver camera_data_file:dir { open getattr read search ioctl };
+#line 52
+allow mediaserver camera_data_file:{ file lnk_file } { getattr open read ioctl lock };
+#line 52
+
+
+#line 53
+allow mediaserver media_rw_data_file:dir { open getattr read search ioctl };
+#line 53
+allow mediaserver media_rw_data_file:{ file lnk_file } { getattr open read ioctl lock };
+#line 53
+
+
+# Grant access to audio files to mediaserver
+allow mediaserver audio_data_file:dir { { open getattr read search ioctl } add_name write };
+allow mediaserver audio_data_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+
+# Read/[write] to /proc/net/xt_qtaguid/ctrl and /dev/xt_qtaguid
+allow mediaserver qtaguid_proc:file { { getattr open read ioctl lock } { open append write } };
+allow mediaserver qtaguid_device:chr_file { getattr open read ioctl lock };
+
+# Allow abstract socket connection
+allow mediaserver rild:unix_stream_socket { connectto read write setopt };
+
+# Needed on some devices for playing DRM protected content,
+# but seems expected and appropriate for all devices.
+
+#line 68
+allow mediaserver drmserver_socket:sock_file write;
+#line 68
+allow mediaserver drmserver:unix_stream_socket connectto;
+#line 68
+
+
+# Needed on some devices for playing audio on paired BT device,
+# but seems appropriate for all devices.
+
+#line 72
+allow mediaserver bluetooth_socket:sock_file write;
+#line 72
+allow mediaserver bluetooth:unix_stream_socket connectto;
+#line 72
+
+#line 1 "external/sepolicy/mtp.te"
+# vpn tunneling protocol manager
+type mtp, domain;
+
+#line 3
+typeattribute mtp mlstrustedsubject;
+#line 3
+typeattribute mtp unconfineddomain;
+#line 3
+
+type mtp_exec, exec_type, file_type;
+
+
+#line 6
+
+#line 6
+# Allow the necessary permissions.
+#line 6
+
+#line 6
+# Old domain may exec the file and transition to the new domain.
+#line 6
+allow init mtp_exec:file { getattr open read execute };
+#line 6
+allow init mtp:process transition;
+#line 6
+# New domain is entered by executing the file.
+#line 6
+allow mtp mtp_exec:file { entrypoint read execute };
+#line 6
+# New domain can send SIGCHLD to its caller.
+#line 6
+allow mtp init:process sigchld;
+#line 6
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 6
+dontaudit init mtp:process noatsecure;
+#line 6
+# XXX dontaudit candidate but requires further study.
+#line 6
+allow init mtp:process { siginh rlimitinh };
+#line 6
+
+#line 6
+# Make the transition occur by default.
+#line 6
+type_transition init mtp_exec:process mtp;
+#line 6
+
+#line 6
+
+#line 6
+type mtp_tmpfs, file_type;
+#line 6
+type_transition mtp tmpfs:file mtp_tmpfs;
+#line 6
+allow mtp mtp_tmpfs:file { read write };
+#line 6
+
+#line 6
+
+
+#line 7
+typeattribute mtp netdomain;
+#line 7
+
+
+# pptp policy
+allow mtp self:tcp_socket { create { ioctl read getattr write setattr append bind connect getopt setopt shutdown } };
+allow mtp self:socket { create { ioctl read getattr write setattr append bind connect getopt setopt shutdown } };
+allow mtp self:rawip_socket { create { ioctl read getattr write setattr append bind connect getopt setopt shutdown } };
+allow mtp self:capability net_raw;
+allow mtp ppp:process signal;
+allow mtp port:tcp_socket name_connect;
+allow mtp vpn_data_file:dir search;
+#line 1 "external/sepolicy/netd.te"
+# network manager
+type netd, domain;
+type netd_exec, exec_type, file_type;
+
+
+#line 5
+
+#line 5
+# Allow the necessary permissions.
+#line 5
+
+#line 5
+# Old domain may exec the file and transition to the new domain.
+#line 5
+allow init netd_exec:file { getattr open read execute };
+#line 5
+allow init netd:process transition;
+#line 5
+# New domain is entered by executing the file.
+#line 5
+allow netd netd_exec:file { entrypoint read execute };
+#line 5
+# New domain can send SIGCHLD to its caller.
+#line 5
+allow netd init:process sigchld;
+#line 5
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 5
+dontaudit init netd:process noatsecure;
+#line 5
+# XXX dontaudit candidate but requires further study.
+#line 5
+allow init netd:process { siginh rlimitinh };
+#line 5
+
+#line 5
+# Make the transition occur by default.
+#line 5
+type_transition init netd_exec:process netd;
+#line 5
+
+#line 5
+
+#line 5
+type netd_tmpfs, file_type;
+#line 5
+type_transition netd tmpfs:file netd_tmpfs;
+#line 5
+allow netd netd_tmpfs:file { read write };
+#line 5
+
+#line 5
+
+
+#line 6
+typeattribute netd netdomain;
+#line 6
+
+
+allow netd self:capability { net_admin net_raw kill fsetid };
+allow netd self:netlink_kobject_uevent_socket *;
+allow netd self:netlink_route_socket *;
+allow netd self:netlink_nflog_socket *;
+allow netd self:rawip_socket *;
+allow netd self:unix_stream_socket *;
+allow netd shell_exec:file { { getattr open read ioctl lock } { getattr execute execute_no_trans } };
+allow netd system_file:file { getattr execute execute_no_trans };
+allow netd devpts:chr_file { { getattr open read ioctl lock } { open append write } };
+
+# For /proc/sys/net/ipv[46]/route/flush.
+allow netd proc_net:file write;
+
+# For /sys/modules/bcmdhd/parameters/firmware_path
+# XXX Split into its own type.
+allow netd sysfs:file write;
+
+# Set dhcp lease for PAN connection
+
+#line 26
+allow netd property_socket:sock_file write;
+#line 26
+allow netd init:unix_stream_socket connectto;
+#line 26
+
+allow netd system_prop:property_service set;
+
+# Connect to PAN
+
+#line 30
+# Allow the necessary permissions.
+#line 30
+
+#line 30
+# Old domain may exec the file and transition to the new domain.
+#line 30
+allow netd dhcp_exec:file { getattr open read execute };
+#line 30
+allow netd dhcp:process transition;
+#line 30
+# New domain is entered by executing the file.
+#line 30
+allow dhcp dhcp_exec:file { entrypoint read execute };
+#line 30
+# New domain can send SIGCHLD to its caller.
+#line 30
+allow dhcp netd:process sigchld;
+#line 30
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 30
+dontaudit netd dhcp:process noatsecure;
+#line 30
+# XXX dontaudit candidate but requires further study.
+#line 30
+allow netd dhcp:process { siginh rlimitinh };
+#line 30
+
+#line 30
+# Make the transition occur by default.
+#line 30
+type_transition netd dhcp_exec:process dhcp;
+#line 30
+
+allow netd dhcp:process signal;
+
+# Needed to update /data/misc/wifi/hostapd.conf
+# TODO: See what we can do to reduce the need for
+# these capabilities
+allow netd self:capability { dac_override chown fowner };
+allow netd wifi_data_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+allow netd wifi_data_file:dir { { open getattr read search ioctl } { open search write add_name remove_name } };
+
+# Allow netd to spawn hostapd in it's own domain
+
+#line 41
+# Allow the necessary permissions.
+#line 41
+
+#line 41
+# Old domain may exec the file and transition to the new domain.
+#line 41
+allow netd hostapd_exec:file { getattr open read execute };
+#line 41
+allow netd hostapd:process transition;
+#line 41
+# New domain is entered by executing the file.
+#line 41
+allow hostapd hostapd_exec:file { entrypoint read execute };
+#line 41
+# New domain can send SIGCHLD to its caller.
+#line 41
+allow hostapd netd:process sigchld;
+#line 41
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 41
+dontaudit netd hostapd:process noatsecure;
+#line 41
+# XXX dontaudit candidate but requires further study.
+#line 41
+allow netd hostapd:process { siginh rlimitinh };
+#line 41
+
+#line 41
+# Make the transition occur by default.
+#line 41
+type_transition netd hostapd_exec:process hostapd;
+#line 41
+
+allow netd hostapd:process signal;
+
+# Allow netd to spawn dnsmasq in it's own domain
+
+#line 45
+# Allow the necessary permissions.
+#line 45
+
+#line 45
+# Old domain may exec the file and transition to the new domain.
+#line 45
+allow netd dnsmasq_exec:file { getattr open read execute };
+#line 45
+allow netd dnsmasq:process transition;
+#line 45
+# New domain is entered by executing the file.
+#line 45
+allow dnsmasq dnsmasq_exec:file { entrypoint read execute };
+#line 45
+# New domain can send SIGCHLD to its caller.
+#line 45
+allow dnsmasq netd:process sigchld;
+#line 45
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 45
+dontaudit netd dnsmasq:process noatsecure;
+#line 45
+# XXX dontaudit candidate but requires further study.
+#line 45
+allow netd dnsmasq:process { siginh rlimitinh };
+#line 45
+
+#line 45
+# Make the transition occur by default.
+#line 45
+type_transition netd dnsmasq_exec:process dnsmasq;
+#line 45
+
+allow netd dnsmasq:process signal;
+
+# Allow netd to start clatd in its own domain
+
+#line 49
+# Allow the necessary permissions.
+#line 49
+
+#line 49
+# Old domain may exec the file and transition to the new domain.
+#line 49
+allow netd clatd_exec:file { getattr open read execute };
+#line 49
+allow netd clatd:process transition;
+#line 49
+# New domain is entered by executing the file.
+#line 49
+allow clatd clatd_exec:file { entrypoint read execute };
+#line 49
+# New domain can send SIGCHLD to its caller.
+#line 49
+allow clatd netd:process sigchld;
+#line 49
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 49
+dontaudit netd clatd:process noatsecure;
+#line 49
+# XXX dontaudit candidate but requires further study.
+#line 49
+allow netd clatd:process { siginh rlimitinh };
+#line 49
+
+#line 49
+# Make the transition occur by default.
+#line 49
+type_transition netd clatd_exec:process clatd;
+#line 49
+
+allow netd clatd:process signal;
+
+# Support netd running mdnsd
+# TODO: prune this back further
+allow netd ctl_default_prop:property_service set;
+allow netd device:sock_file write;
+
+###
+### Neverallow rules
+###
+### netd should NEVER do any of this
+
+# Block device access.
+neverallow netd dev_type:blk_file { read write };
+
+# Setting SELinux enforcing status or booleans.
+neverallow netd kernel:security { setenforce setbool };
+
+# Load security policy.
+neverallow netd kernel:security load_policy;
+
+# ptrace any other app
+neverallow netd { domain }:process ptrace;
+
+# Write to /system.
+neverallow netd system_file:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } } write;
+
+# Write to files in /data/data or system files on /data
+neverallow netd { app_data_file system_data_file }:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } } write;
+#line 1 "external/sepolicy/net.te"
+# Network types
+type node, node_type;
+type netif, netif_type;
+type port, port_type;
+
+# Use network sockets.
+allow netdomain self:{ tcp_socket udp_socket } *;
+# Connect to ports.
+allow netdomain port_type:tcp_socket name_connect;
+# Bind to ports.
+allow netdomain node_type:{ tcp_socket udp_socket } node_bind;
+allow netdomain port_type:udp_socket name_bind;
+allow netdomain port_type:tcp_socket name_bind;
+# Get route information.
+allow netdomain self:netlink_route_socket { create bind read nlmsg_read };
+
+# Talks to netd via dnsproxyd socket.
+
+#line 18
+allow netdomain dnsproxyd_socket:sock_file write;
+#line 18
+allow netdomain netd:unix_stream_socket connectto;
+#line 18
+
+#line 1 "external/sepolicy/nfc.te"
+# nfc subsystem
+type nfc, domain;
+
+#line 3
+typeattribute nfc appdomain;
+#line 3
+# Label ashmem objects with our own unique type.
+#line 3
+
+#line 3
+type nfc_tmpfs, file_type;
+#line 3
+type_transition nfc tmpfs:file nfc_tmpfs;
+#line 3
+allow nfc nfc_tmpfs:file { read write };
+#line 3
+
+#line 3
+# Map with PROT_EXEC.
+#line 3
+allow nfc nfc_tmpfs:file execute;
+#line 3
+
+
+#line 4
+typeattribute nfc binderservicedomain;
+#line 4
+
+
+# NFC device access.
+allow nfc nfc_device:chr_file { { getattr open read ioctl lock } { open append write } };
+
+# Data file accesses.
+allow nfc nfc_data_file:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow nfc nfc_data_file:{ file lnk_file sock_file fifo_file } { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+
+allow nfc sysfs_nfc_power_writable:file { { getattr open read ioctl lock } { open append write } };
+allow nfc sysfs:file write;
+
+allow nfc sdcard_type:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow nfc sdcard_type:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+#line 1 "external/sepolicy/platform_app.te"
+###
+### Apps signed with the platform key.
+###
+
+type platform_app, domain;
+
+#line 6
+typeattribute platform_app mlstrustedsubject;
+#line 6
+typeattribute platform_app unconfineddomain;
+#line 6
+
+
+#line 7
+typeattribute platform_app appdomain;
+#line 7
+# Label ashmem objects with our own unique type.
+#line 7
+
+#line 7
+type platform_app_tmpfs, file_type;
+#line 7
+type_transition platform_app tmpfs:file platform_app_tmpfs;
+#line 7
+allow platform_app platform_app_tmpfs:file { read write };
+#line 7
+
+#line 7
+# Map with PROT_EXEC.
+#line 7
+allow platform_app platform_app_tmpfs:file execute;
+#line 7
+
+
+#line 8
+typeattribute platform_app platformappdomain;
+#line 8
+typeattribute platform_app mlstrustedsubject;
+#line 8
+
+# Access the network.
+
+#line 10
+typeattribute platform_app netdomain;
+#line 10
+
+# Access bluetooth.
+
+#line 12
+typeattribute platform_app bluetoothdomain;
+#line 12
+
+# Write to /cache.
+allow platform_app cache_file:dir { { open getattr read search ioctl } { open search write add_name remove_name } };
+allow platform_app cache_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+# Read from /data/local.
+allow platform_app shell_data_file:dir search;
+allow platform_app shell_data_file:file { open getattr read };
+allow platform_app shell_data_file:lnk_file read;
+# Populate /data/app/vmdl*.tmp, /data/app-private/vmdl*.tmp files
+# created by system server.
+allow platform_app { apk_tmp_file apk_private_tmp_file }:file { { getattr open read ioctl lock } { open append write } };
+allow platform_app apk_private_data_file:dir search;
+# ASEC
+allow platform_app asec_apk_file:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow platform_app asec_apk_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+# Access download files.
+allow platform_app download_file:file { { getattr open read ioctl lock } { open append write } };
+# Allow BackupManagerService to backup all app domains
+allow platform_app appdomain:fifo_file write;
+
+#
+# Rules for all platform app domains.
+#
+
+# App sandbox file accesses.
+allow platformappdomain platform_app_data_file:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow platformappdomain platform_app_data_file:{ file lnk_file sock_file fifo_file } { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+allow platformappdomain platform_app_data_file:file execute;
+# App sdcard file accesses
+allow platformappdomain sdcard_type:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow platformappdomain sdcard_type:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+# Access to /data/media.
+allow platformappdomain media_rw_data_file:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow platformappdomain media_rw_data_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+#line 1 "external/sepolicy/ppp.te"
+# Point to Point Protocol daemon
+type ppp, domain;
+
+#line 3
+typeattribute ppp mlstrustedsubject;
+#line 3
+typeattribute ppp unconfineddomain;
+#line 3
+
+type ppp_device, dev_type;
+type ppp_exec, exec_type, file_type;
+
+#line 6
+# Allow the necessary permissions.
+#line 6
+
+#line 6
+# Old domain may exec the file and transition to the new domain.
+#line 6
+allow mtp ppp_exec:file { getattr open read execute };
+#line 6
+allow mtp ppp:process transition;
+#line 6
+# New domain is entered by executing the file.
+#line 6
+allow ppp ppp_exec:file { entrypoint read execute };
+#line 6
+# New domain can send SIGCHLD to its caller.
+#line 6
+allow ppp mtp:process sigchld;
+#line 6
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 6
+dontaudit mtp ppp:process noatsecure;
+#line 6
+# XXX dontaudit candidate but requires further study.
+#line 6
+allow mtp ppp:process { siginh rlimitinh };
+#line 6
+
+#line 6
+# Make the transition occur by default.
+#line 6
+type_transition mtp ppp_exec:process ppp;
+#line 6
+
+
+allow ppp mtp:socket { ioctl read getattr write setattr append bind connect getopt setopt shutdown };
+allow ppp ppp_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow ppp self:capability net_admin;
+allow ppp self:udp_socket { create { ioctl read getattr write setattr append bind connect getopt setopt shutdown } };
+allow ppp system_file:file { { getattr open read ioctl lock } { getattr execute execute_no_trans } };
+allow ppp vpn_data_file:dir { open search write add_name remove_name };
+allow ppp vpn_data_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+allow ppp mtp:fd use;
+#line 1 "external/sepolicy/property.te"
+type default_prop, property_type;
+type shell_prop, property_type;
+type debug_prop, property_type;
+type debuggerd_prop, property_type;
+type radio_prop, property_type;
+type system_prop, property_type;
+type vold_prop, property_type;
+type rild_prop, property_type;
+type ctl_default_prop, property_type;
+type ctl_dumpstate_prop, property_type;
+type ctl_rildaemon_prop, property_type;
+type audio_prop, property_type;
+type security_prop, property_type;
+type bluetooth_prop, property_type;
+type powerctl_prop, property_type;
+#line 1 "external/sepolicy/qemud.te"
+# qemu support daemon
+type qemud, domain;
+type qemud_exec, exec_type, file_type;
+
+
+#line 5
+
+#line 5
+# Allow the necessary permissions.
+#line 5
+
+#line 5
+# Old domain may exec the file and transition to the new domain.
+#line 5
+allow init qemud_exec:file { getattr open read execute };
+#line 5
+allow init qemud:process transition;
+#line 5
+# New domain is entered by executing the file.
+#line 5
+allow qemud qemud_exec:file { entrypoint read execute };
+#line 5
+# New domain can send SIGCHLD to its caller.
+#line 5
+allow qemud init:process sigchld;
+#line 5
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 5
+dontaudit init qemud:process noatsecure;
+#line 5
+# XXX dontaudit candidate but requires further study.
+#line 5
+allow init qemud:process { siginh rlimitinh };
+#line 5
+
+#line 5
+# Make the transition occur by default.
+#line 5
+type_transition init qemud_exec:process qemud;
+#line 5
+
+#line 5
+
+#line 5
+type qemud_tmpfs, file_type;
+#line 5
+type_transition qemud tmpfs:file qemud_tmpfs;
+#line 5
+allow qemud qemud_tmpfs:file { read write };
+#line 5
+
+#line 5
+
+
+#line 6
+typeattribute qemud mlstrustedsubject;
+#line 6
+typeattribute qemud unconfineddomain;
+#line 1 "external/sepolicy/racoon.te"
+# IKE key management daemon
+type racoon, domain;
+
+#line 3
+typeattribute racoon mlstrustedsubject;
+#line 3
+typeattribute racoon unconfineddomain;
+#line 3
+
+type racoon_exec, exec_type, file_type;
+
+
+#line 6
+
+#line 6
+# Allow the necessary permissions.
+#line 6
+
+#line 6
+# Old domain may exec the file and transition to the new domain.
+#line 6
+allow init racoon_exec:file { getattr open read execute };
+#line 6
+allow init racoon:process transition;
+#line 6
+# New domain is entered by executing the file.
+#line 6
+allow racoon racoon_exec:file { entrypoint read execute };
+#line 6
+# New domain can send SIGCHLD to its caller.
+#line 6
+allow racoon init:process sigchld;
+#line 6
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 6
+dontaudit init racoon:process noatsecure;
+#line 6
+# XXX dontaudit candidate but requires further study.
+#line 6
+allow init racoon:process { siginh rlimitinh };
+#line 6
+
+#line 6
+# Make the transition occur by default.
+#line 6
+type_transition init racoon_exec:process racoon;
+#line 6
+
+#line 6
+
+#line 6
+type racoon_tmpfs, file_type;
+#line 6
+type_transition racoon tmpfs:file racoon_tmpfs;
+#line 6
+allow racoon racoon_tmpfs:file { read write };
+#line 6
+
+#line 6
+
+typeattribute racoon mlstrustedsubject;
+
+
+#line 9
+# Call the server domain and optionally transfer references to it.
+#line 9
+allow racoon servicemanager:binder { call transfer };
+#line 9
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 9
+allow servicemanager racoon:binder transfer;
+#line 9
+# Receive and use open files from the server.
+#line 9
+allow racoon servicemanager:fd use;
+#line 9
+
+
+#line 10
+# Call the server domain and optionally transfer references to it.
+#line 10
+allow racoon keystore:binder { call transfer };
+#line 10
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 10
+allow keystore racoon:binder transfer;
+#line 10
+# Receive and use open files from the server.
+#line 10
+allow racoon keystore:fd use;
+#line 10
+
+
+allow racoon tun_device:chr_file { getattr open read ioctl lock };
+allow racoon cgroup:dir { add_name create };
+allow racoon kernel:system module_request;
+allow racoon port:udp_socket name_bind;
+allow racoon node:udp_socket node_bind;
+
+allow racoon self:{ key_socket udp_socket } { create { ioctl read getattr write setattr append bind connect getopt setopt shutdown } };
+allow racoon self:tun_socket create;
+allow racoon self:capability { net_admin net_bind_service net_raw setuid };
+
+# XXX: should we give ip-up-vpn its own label (currently racoon domain)
+allow racoon system_file:file { { getattr open read ioctl lock } { getattr execute execute_no_trans } };
+allow racoon vpn_data_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+allow racoon vpn_data_file:dir { open search write add_name remove_name };
+#line 1 "external/sepolicy/radio.te"
+# phone subsystem
+type radio, domain;
+
+#line 3
+typeattribute radio appdomain;
+#line 3
+# Label ashmem objects with our own unique type.
+#line 3
+
+#line 3
+type radio_tmpfs, file_type;
+#line 3
+type_transition radio tmpfs:file radio_tmpfs;
+#line 3
+allow radio radio_tmpfs:file { read write };
+#line 3
+
+#line 3
+# Map with PROT_EXEC.
+#line 3
+allow radio radio_tmpfs:file execute;
+#line 3
+
+
+#line 4
+typeattribute radio netdomain;
+#line 4
+
+
+#line 5
+typeattribute radio bluetoothdomain;
+#line 5
+
+
+#line 6
+typeattribute radio binderservicedomain;
+#line 6
+
+
+# Talks to init via the property socket.
+
+#line 9
+allow radio property_socket:sock_file write;
+#line 9
+allow radio init:unix_stream_socket connectto;
+#line 9
+
+
+# Talks to rild via the rild socket.
+
+#line 12
+allow radio rild_socket:sock_file write;
+#line 12
+allow radio rild:unix_stream_socket connectto;
+#line 12
+
+
+# Data file accesses.
+allow radio radio_data_file:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow radio radio_data_file:{ file lnk_file sock_file fifo_file } { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+
+allow radio alarm_device:chr_file { { getattr open read ioctl lock } { open append write } };
+
+# Property service
+allow radio radio_prop:property_service set;
+
+# ctl interface
+allow radio ctl_rildaemon_prop:property_service set;
+#line 1 "external/sepolicy/recovery.te"
+# recovery console (used in recovery init.rc for /sbin/recovery)
+type recovery, domain;
+allow recovery rootfs:file entrypoint;
+
+#line 4
+typeattribute recovery mlstrustedsubject;
+#line 4
+typeattribute recovery unconfineddomain;
+#line 4
+
+
+#line 5
+typeattribute recovery relabeltodomain;
+#line 5
+
+
+allow recovery self:capability2 mac_admin;
+
+allow recovery {fs_type dev_type -kmem_device file_type}:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } } relabelto;
+allow recovery unlabeled:filesystem mount;
+allow recovery fs_type:filesystem *;
+
+# Required to e.g. wipe userdata/cache.
+allow recovery dev_type:blk_file { { getattr open read ioctl lock } { open append write } };
+
+allow recovery self:process execmem;
+allow recovery ashmem_device:chr_file execute;
+allow recovery tmpfs:file { { getattr open read ioctl lock } { getattr execute execute_no_trans } };
+
+## TODO: Investigate whether it is safe to remove these
+allow recovery self:capability { sys_rawio mknod };
+auditallow recovery self:capability { sys_rawio mknod };
+#line 1 "external/sepolicy/release_app.te"
+###
+### Apps signed with the release key (testkey in AOSP).
+###
+
+type release_app, domain;
+
+#line 6
+typeattribute release_app mlstrustedsubject;
+#line 6
+typeattribute release_app unconfineddomain;
+#line 6
+
+
+#line 7
+typeattribute release_app appdomain;
+#line 7
+# Label ashmem objects with our own unique type.
+#line 7
+
+#line 7
+type release_app_tmpfs, file_type;
+#line 7
+type_transition release_app tmpfs:file release_app_tmpfs;
+#line 7
+allow release_app release_app_tmpfs:file { read write };
+#line 7
+
+#line 7
+# Map with PROT_EXEC.
+#line 7
+allow release_app release_app_tmpfs:file execute;
+#line 7
+
+
+#line 8
+typeattribute release_app platformappdomain;
+#line 8
+typeattribute release_app mlstrustedsubject;
+#line 8
+
+# Access the network.
+
+#line 10
+typeattribute release_app netdomain;
+#line 10
+
+# Access bluetooth.
+
+#line 12
+typeattribute release_app bluetoothdomain;
+#line 12
+
+
+# Write to /cache.
+allow release_app cache_file:dir { { open getattr read search ioctl } { open search write add_name remove_name } };
+allow release_app cache_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+#line 1 "external/sepolicy/rild.te"
+# rild - radio interface layer daemon
+type rild, domain;
+
+#line 3
+typeattribute rild mlstrustedsubject;
+#line 3
+typeattribute rild unconfineddomain;
+#line 3
+
+type rild_exec, exec_type, file_type;
+
+
+#line 6
+
+#line 6
+# Allow the necessary permissions.
+#line 6
+
+#line 6
+# Old domain may exec the file and transition to the new domain.
+#line 6
+allow init rild_exec:file { getattr open read execute };
+#line 6
+allow init rild:process transition;
+#line 6
+# New domain is entered by executing the file.
+#line 6
+allow rild rild_exec:file { entrypoint read execute };
+#line 6
+# New domain can send SIGCHLD to its caller.
+#line 6
+allow rild init:process sigchld;
+#line 6
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 6
+dontaudit init rild:process noatsecure;
+#line 6
+# XXX dontaudit candidate but requires further study.
+#line 6
+allow init rild:process { siginh rlimitinh };
+#line 6
+
+#line 6
+# Make the transition occur by default.
+#line 6
+type_transition init rild_exec:process rild;
+#line 6
+
+#line 6
+
+#line 6
+type rild_tmpfs, file_type;
+#line 6
+type_transition rild tmpfs:file rild_tmpfs;
+#line 6
+allow rild rild_tmpfs:file { read write };
+#line 6
+
+#line 6
+
+
+#line 7
+typeattribute rild netdomain;
+#line 7
+
+allow rild self:netlink_route_socket { setopt write };
+allow rild kernel:system module_request;
+
+#line 10
+allow rild property_socket:sock_file write;
+#line 10
+allow rild init:unix_stream_socket connectto;
+#line 10
+
+
+#line 11
+allow rild qemud_socket:sock_file write;
+#line 11
+allow rild qemud:unix_stream_socket connectto;
+#line 11
+
+allow rild self:capability { setuid net_admin net_raw };
+allow rild alarm_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow rild cgroup:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow rild radio_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow rild radio_device:blk_file { getattr open read ioctl lock };
+allow rild qemu_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow rild mtd_device:dir search;
+allow rild efs_file:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow rild efs_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+allow rild shell_exec:file { { getattr open read ioctl lock } { getattr execute execute_no_trans } };
+allow rild bluetooth_efs_file:file { getattr open read ioctl lock };
+allow rild bluetooth_efs_file:dir { open getattr read search ioctl };
+allow rild radio_data_file:dir { { open getattr read search ioctl } { open search write add_name remove_name } };
+allow rild radio_data_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+allow rild sdcard_type:dir { open getattr read search ioctl };
+allow rild system_data_file:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow rild system_data_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+allow rild system_file:file { getattr execute execute_no_trans };
+dontaudit rild self:capability sys_admin;
+
+# property service
+allow rild rild_prop:property_service set;
+allow rild radio_prop:property_service set;
+
+# Read/Write to uart driver (for GPS)
+allow rild gps_device:chr_file { { getattr open read ioctl lock } { open append write } };
+
+allow rild tty_device:chr_file { { getattr open read ioctl lock } { open append write } };
+
+# Allow rild to create, bind, read, write to itself through a netlink socket
+allow rild self:netlink_socket { create bind read write };
+
+allow rild self:netlink_kobject_uevent_socket { bind create getopt read setopt };
+
+# Access to wake locks
+allow rild sysfs_wake_lock:file { { getattr open read ioctl lock } { open append write } };
+
+allow rild self:socket { create { ioctl read getattr write setattr append bind connect getopt setopt shutdown } };
+#line 1 "external/sepolicy/runas.te"
+type runas, domain, mlstrustedsubject;
+type runas_exec, exec_type, file_type;
+
+# ndk-gdb invokes adb shell run-as.
+
+#line 5
+# Allow the necessary permissions.
+#line 5
+
+#line 5
+# Old domain may exec the file and transition to the new domain.
+#line 5
+allow shell runas_exec:file { getattr open read execute };
+#line 5
+allow shell runas:process transition;
+#line 5
+# New domain is entered by executing the file.
+#line 5
+allow runas runas_exec:file { entrypoint read execute };
+#line 5
+# New domain can send SIGCHLD to its caller.
+#line 5
+allow runas shell:process sigchld;
+#line 5
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 5
+dontaudit shell runas:process noatsecure;
+#line 5
+# XXX dontaudit candidate but requires further study.
+#line 5
+allow shell runas:process { siginh rlimitinh };
+#line 5
+
+#line 5
+# Make the transition occur by default.
+#line 5
+type_transition shell runas_exec:process runas;
+#line 5
+
+allow runas adbd:process sigchld;
+allow runas shell:fd  use;
+allow runas devpts:chr_file { read write ioctl };
+
+# run-as reads package information.
+allow runas system_data_file:file { getattr open read ioctl lock };
+
+# run-as checks and changes to the app data dir.
+dontaudit runas self:capability dac_override;
+allow runas app_data_file:dir { getattr search };
+
+# run-as switches to the app UID/GID.
+allow runas self:capability { setuid setgid };
+
+# run-as switches to the app security context.
+# read /seapp_contexts and /data/security/seapp_contexts
+
+#line 22
+allow runas security_file:dir { open getattr read search ioctl };
+#line 22
+allow runas security_file:file { getattr open read ioctl lock };
+#line 22
+allow runas security_file:lnk_file { getattr open read ioctl lock };
+#line 22
+allow runas selinuxfs:dir { open getattr read search ioctl };
+#line 22
+allow runas selinuxfs:file { getattr open read ioctl lock };
+#line 22
+allow runas rootfs:dir { open getattr read search ioctl };
+#line 22
+allow runas rootfs:file { getattr open read ioctl lock };
+#line 22
+
+
+#line 23
+allow runas selinuxfs:dir { open getattr read search ioctl };
+#line 23
+allow runas selinuxfs:file { { getattr open read ioctl lock } { open append write } };
+#line 23
+allow runas kernel:security check_context;
+#line 23
+ # validate context
+allow runas { appdomain -system_app }:process dyntransition; # setcon
+#line 1 "external/sepolicy/sdcardd.te"
+type sdcardd, domain;
+type sdcardd_exec, exec_type, file_type;
+
+
+#line 4
+
+#line 4
+# Allow the necessary permissions.
+#line 4
+
+#line 4
+# Old domain may exec the file and transition to the new domain.
+#line 4
+allow init sdcardd_exec:file { getattr open read execute };
+#line 4
+allow init sdcardd:process transition;
+#line 4
+# New domain is entered by executing the file.
+#line 4
+allow sdcardd sdcardd_exec:file { entrypoint read execute };
+#line 4
+# New domain can send SIGCHLD to its caller.
+#line 4
+allow sdcardd init:process sigchld;
+#line 4
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 4
+dontaudit init sdcardd:process noatsecure;
+#line 4
+# XXX dontaudit candidate but requires further study.
+#line 4
+allow init sdcardd:process { siginh rlimitinh };
+#line 4
+
+#line 4
+# Make the transition occur by default.
+#line 4
+type_transition init sdcardd_exec:process sdcardd;
+#line 4
+
+#line 4
+
+#line 4
+type sdcardd_tmpfs, file_type;
+#line 4
+type_transition sdcardd tmpfs:file sdcardd_tmpfs;
+#line 4
+allow sdcardd sdcardd_tmpfs:file { read write };
+#line 4
+
+#line 4
+
+
+allow sdcardd cgroup:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow sdcardd fuse_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow sdcardd rootfs:dir mounton;
+allow sdcardd sdcard_type:filesystem mount;
+allow sdcardd self:capability { setuid setgid dac_override sys_admin sys_resource };
+
+allow sdcardd sdcard_type:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow sdcardd sdcard_type:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+
+type_transition sdcardd system_data_file:{ dir file } media_rw_data_file;
+allow sdcardd media_rw_data_file:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow sdcardd media_rw_data_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+
+# Read /data/system/packages.list.
+allow sdcardd system_data_file:file { getattr open read ioctl lock };
+
+# Compatibility for existing devices with /data/media in system_data_file.
+# TODO: Remove these lines after we have guaranteed that /data/media has been relabeled to media_rw_data_file.
+allow sdcardd system_data_file:dir  { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow sdcardd system_data_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+#line 1 "external/sepolicy/servicemanager.te"
+# servicemanager - the Binder context manager
+type servicemanager, domain;
+type servicemanager_exec, exec_type, file_type;
+
+
+#line 5
+
+#line 5
+# Allow the necessary permissions.
+#line 5
+
+#line 5
+# Old domain may exec the file and transition to the new domain.
+#line 5
+allow init servicemanager_exec:file { getattr open read execute };
+#line 5
+allow init servicemanager:process transition;
+#line 5
+# New domain is entered by executing the file.
+#line 5
+allow servicemanager servicemanager_exec:file { entrypoint read execute };
+#line 5
+# New domain can send SIGCHLD to its caller.
+#line 5
+allow servicemanager init:process sigchld;
+#line 5
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 5
+dontaudit init servicemanager:process noatsecure;
+#line 5
+# XXX dontaudit candidate but requires further study.
+#line 5
+allow init servicemanager:process { siginh rlimitinh };
+#line 5
+
+#line 5
+# Make the transition occur by default.
+#line 5
+type_transition init servicemanager_exec:process servicemanager;
+#line 5
+
+#line 5
+
+#line 5
+type servicemanager_tmpfs, file_type;
+#line 5
+type_transition servicemanager tmpfs:file servicemanager_tmpfs;
+#line 5
+allow servicemanager servicemanager_tmpfs:file { read write };
+#line 5
+
+#line 5
+
+
+# Note that we do not use the binder_* macros here.
+# servicemanager is unique in that it only provides
+# name service (aka context manager) for Binder.
+# As such, it only ever receives and transfers other references
+# created by other domains.  It never passes its own references
+# or initiates a Binder IPC.
+allow servicemanager self:binder set_context_mgr;
+allow servicemanager domain:binder transfer;
+#line 1 "external/sepolicy/shared_app.te"
+###
+### Apps signed with the shared key.
+###
+
+type shared_app, domain;
+
+#line 6
+typeattribute shared_app mlstrustedsubject;
+#line 6
+typeattribute shared_app unconfineddomain;
+#line 6
+
+
+#line 7
+typeattribute shared_app appdomain;
+#line 7
+# Label ashmem objects with our own unique type.
+#line 7
+
+#line 7
+type shared_app_tmpfs, file_type;
+#line 7
+type_transition shared_app tmpfs:file shared_app_tmpfs;
+#line 7
+allow shared_app shared_app_tmpfs:file { read write };
+#line 7
+
+#line 7
+# Map with PROT_EXEC.
+#line 7
+allow shared_app shared_app_tmpfs:file execute;
+#line 7
+
+
+#line 8
+typeattribute shared_app platformappdomain;
+#line 8
+typeattribute shared_app mlstrustedsubject;
+#line 8
+
+# Access the network.
+
+#line 10
+typeattribute shared_app netdomain;
+#line 10
+
+# Access bluetooth.
+
+#line 12
+typeattribute shared_app bluetoothdomain;
+#line 12
+
+#line 1 "external/sepolicy/shelldomain.te"
+# Rules for all shell domains (e.g. console service and adb shell).
+
+# Access /data/local/tmp.
+allow shelldomain shell_data_file:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow shelldomain shell_data_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+allow shelldomain shell_data_file:file { { getattr open read ioctl lock } { getattr execute execute_no_trans } };
+
+# Access sdcard.
+allow shelldomain sdcard_type:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow shelldomain sdcard_type:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+
+# adb bugreport
+
+#line 13
+allow shelldomain dumpstate_socket:sock_file write;
+#line 13
+allow shelldomain dumpstate:unix_stream_socket connectto;
+#line 13
+
+
+allow shelldomain rootfs:dir { open getattr read search ioctl };
+allow shelldomain devpts:chr_file { { getattr open read ioctl lock } { open append write } };
+allow shelldomain tty_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow shelldomain console_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow shelldomain input_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow shelldomain system_file:file { getattr execute execute_no_trans };
+allow shelldomain shell_exec:file { { getattr open read ioctl lock } { getattr execute execute_no_trans } };
+allow shelldomain zygote_exec:file { { getattr open read ioctl lock } { getattr execute execute_no_trans } };
+
+
+#line 24
+allow shelldomain apk_data_file:dir { open getattr read search ioctl };
+#line 24
+allow shelldomain apk_data_file:{ file lnk_file } { getattr open read ioctl lock };
+#line 24
+
+
+# Set properties.
+
+#line 27
+allow shelldomain property_socket:sock_file write;
+#line 27
+allow shelldomain init:unix_stream_socket connectto;
+#line 27
+
+allow shelldomain shell_prop:property_service set;
+allow shelldomain ctl_dumpstate_prop:property_service set;
+allow shelldomain debug_prop:property_service set;
+allow shelldomain powerctl_prop:property_service set;
+
+# ndk-gdb invokes adb shell ps to find the app PID.
+
+#line 34
+allow shelldomain { appdomain -system_app }:dir { open getattr read search ioctl };
+#line 34
+allow shelldomain { appdomain -system_app }:{ file lnk_file } { getattr open read ioctl lock };
+#line 34
+
+
+# ndk-gdb invokes adb shell ls to check the app data dir.
+allow shelldomain app_data_file:dir search;
+
+# ps and ps -Z output for app processes.
+
+#line 40
+allow shelldomain appdomain:dir { open getattr read search ioctl };
+#line 40
+allow shelldomain appdomain:{ file lnk_file } { getattr open read ioctl lock };
+#line 40
+
+allow shelldomain appdomain:process getattr;
+#line 1 "external/sepolicy/shell.te"
+# Domain for shell processes spawned by ADB
+type shell, domain, shelldomain, mlstrustedsubject;
+type shell_exec, exec_type, file_type;
+
+# Create and use network sockets.
+
+#line 6
+typeattribute shell netdomain;
+#line 6
+
+
+# Run app_process.
+# XXX Transition into its own domain?
+
+#line 10
+typeattribute shell appdomain;
+#line 10
+# Label ashmem objects with our own unique type.
+#line 10
+
+#line 10
+type shell_tmpfs, file_type;
+#line 10
+type_transition shell tmpfs:file shell_tmpfs;
+#line 10
+allow shell shell_tmpfs:file { read write };
+#line 10
+
+#line 10
+# Map with PROT_EXEC.
+#line 10
+allow shell shell_tmpfs:file execute;
+#line 10
+
+
+# inherits from shelldomain.te
+#line 1 "external/sepolicy/surfaceflinger.te"
+# surfaceflinger - display compositor service
+type surfaceflinger, domain;
+
+#line 3
+typeattribute surfaceflinger mlstrustedsubject;
+#line 3
+typeattribute surfaceflinger unconfineddomain;
+#line 3
+
+type surfaceflinger_exec, exec_type, file_type;
+
+
+#line 6
+
+#line 6
+# Allow the necessary permissions.
+#line 6
+
+#line 6
+# Old domain may exec the file and transition to the new domain.
+#line 6
+allow init surfaceflinger_exec:file { getattr open read execute };
+#line 6
+allow init surfaceflinger:process transition;
+#line 6
+# New domain is entered by executing the file.
+#line 6
+allow surfaceflinger surfaceflinger_exec:file { entrypoint read execute };
+#line 6
+# New domain can send SIGCHLD to its caller.
+#line 6
+allow surfaceflinger init:process sigchld;
+#line 6
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 6
+dontaudit init surfaceflinger:process noatsecure;
+#line 6
+# XXX dontaudit candidate but requires further study.
+#line 6
+allow init surfaceflinger:process { siginh rlimitinh };
+#line 6
+
+#line 6
+# Make the transition occur by default.
+#line 6
+type_transition init surfaceflinger_exec:process surfaceflinger;
+#line 6
+
+#line 6
+
+#line 6
+type surfaceflinger_tmpfs, file_type;
+#line 6
+type_transition surfaceflinger tmpfs:file surfaceflinger_tmpfs;
+#line 6
+allow surfaceflinger surfaceflinger_tmpfs:file { read write };
+#line 6
+
+#line 6
+
+typeattribute surfaceflinger mlstrustedsubject;
+
+# Talk to init over the property socket.
+
+#line 10
+allow surfaceflinger property_socket:sock_file write;
+#line 10
+allow surfaceflinger init:unix_stream_socket connectto;
+#line 10
+
+
+# Perform Binder IPC.
+
+#line 13
+# Call the servicemanager and transfer references to it.
+#line 13
+allow surfaceflinger servicemanager:binder { call transfer };
+#line 13
+# rw access to /dev/binder and /dev/ashmem is presently granted to
+#line 13
+# all domains in domain.te.
+#line 13
+
+
+#line 14
+# Call the server domain and optionally transfer references to it.
+#line 14
+allow surfaceflinger system_server:binder { call transfer };
+#line 14
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 14
+allow system_server surfaceflinger:binder transfer;
+#line 14
+# Receive and use open files from the server.
+#line 14
+allow surfaceflinger system_server:fd use;
+#line 14
+
+
+#line 15
+# Call the server domain and optionally transfer references to it.
+#line 15
+allow surfaceflinger nfc:binder { call transfer };
+#line 15
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 15
+allow nfc surfaceflinger:binder transfer;
+#line 15
+# Receive and use open files from the server.
+#line 15
+allow surfaceflinger nfc:fd use;
+#line 15
+
+
+#line 16
+# Call the server domain and optionally transfer references to it.
+#line 16
+allow surfaceflinger mediaserver:binder { call transfer };
+#line 16
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 16
+allow mediaserver surfaceflinger:binder transfer;
+#line 16
+# Receive and use open files from the server.
+#line 16
+allow surfaceflinger mediaserver:fd use;
+#line 16
+
+
+#line 17
+typeattribute surfaceflinger binderservicedomain;
+#line 17
+
+
+# Access the GPU.
+allow surfaceflinger gpu_device:chr_file { { getattr open read ioctl lock } { open append write } };
+
+# Access /dev/graphics/fb0.
+allow surfaceflinger graphics_device:dir search;
+allow surfaceflinger graphics_device:chr_file { { getattr open read ioctl lock } { open append write } };
+
+# Access /dev/video1.
+allow surfaceflinger video_device:dir { open getattr read search ioctl };
+allow surfaceflinger video_device:chr_file { { getattr open read ioctl lock } { open append write } };
+
+# Create and use netlink kobject uevent sockets.
+allow surfaceflinger self:netlink_kobject_uevent_socket *;
+
+# Set properties.
+allow surfaceflinger system_prop:property_service set;
+allow surfaceflinger ctl_default_prop:property_service set;
+
+# Use open files supplied by an app.
+allow surfaceflinger appdomain:fd use;
+allow surfaceflinger platform_app_data_file:file { read write };
+allow surfaceflinger app_data_file:file { read write };
+
+# Use open file provided by bootanim.
+allow surfaceflinger bootanim:fd use;
+
+# Allow a dumpstate triggered screenshot
+
+#line 46
+# Call the server domain and optionally transfer references to it.
+#line 46
+allow surfaceflinger dumpstate:binder { call transfer };
+#line 46
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 46
+allow dumpstate surfaceflinger:binder transfer;
+#line 46
+# Receive and use open files from the server.
+#line 46
+allow surfaceflinger dumpstate:fd use;
+#line 46
+
+
+#line 47
+# Call the server domain and optionally transfer references to it.
+#line 47
+allow surfaceflinger shell:binder { call transfer };
+#line 47
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 47
+allow shell surfaceflinger:binder transfer;
+#line 47
+# Receive and use open files from the server.
+#line 47
+allow surfaceflinger shell:fd use;
+#line 47
+
+
+# Needed on some devices for playing DRM protected content,
+# but seems expected and appropriate for all devices.
+allow surfaceflinger tee:unix_stream_socket connectto;
+allow surfaceflinger tee_device:chr_file { { getattr open read ioctl lock } { open append write } };
+#line 1 "external/sepolicy/su.te"
+# File types must be defined for file_contexts.
+type su_exec, exec_type, file_type;
+
+#line 23
+
+#line 1 "external/sepolicy/system_app.te"
+#
+# Apps that run with the system UID, e.g. com.android.system.ui,
+# com.android.settings.  These are not as privileged as the system
+# server.
+#
+type system_app, domain;
+
+#line 7
+typeattribute system_app mlstrustedsubject;
+#line 7
+typeattribute system_app unconfineddomain;
+#line 7
+
+
+#line 8
+typeattribute system_app appdomain;
+#line 8
+# Label ashmem objects with our own unique type.
+#line 8
+
+#line 8
+type system_app_tmpfs, file_type;
+#line 8
+type_transition system_app tmpfs:file system_app_tmpfs;
+#line 8
+allow system_app system_app_tmpfs:file { read write };
+#line 8
+
+#line 8
+# Map with PROT_EXEC.
+#line 8
+allow system_app system_app_tmpfs:file execute;
+#line 8
+
+
+#line 9
+typeattribute system_app binderservicedomain;
+#line 9
+
+
+# Perform binder IPC to any app domain.
+
+#line 12
+# Call the server domain and optionally transfer references to it.
+#line 12
+allow system_app appdomain:binder { call transfer };
+#line 12
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 12
+allow appdomain system_app:binder transfer;
+#line 12
+# Receive and use open files from the server.
+#line 12
+allow system_app appdomain:fd use;
+#line 12
+
+
+# Read and write system data files.
+# May want to split into separate types.
+allow system_app system_data_file:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow system_app system_data_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+
+# Read wallpaper file.
+allow system_app wallpaper_file:file { getattr open read ioctl lock };
+
+# Write to dalvikcache.
+allow system_app dalvikcache_data_file:file { write setattr };
+
+# Talk to keystore.
+
+#line 26
+allow system_app keystore_socket:sock_file write;
+#line 26
+allow system_app keystore:unix_stream_socket connectto;
+#line 26
+
+
+# Read SELinux enforcing status.
+
+#line 29
+allow system_app selinuxfs:dir { open getattr read search ioctl };
+#line 29
+allow system_app selinuxfs:file { getattr open read ioctl lock };
+#line 29
+
+
+# Settings app reads sdcard for storage stats
+allow system_app sdcard_type:dir { open getattr read search ioctl };
+
+# Write to properties
+
+#line 35
+allow system_app property_socket:sock_file write;
+#line 35
+allow system_app init:unix_stream_socket connectto;
+#line 35
+
+allow system_app debug_prop:property_service set;
+allow system_app radio_prop:property_service set;
+allow system_app system_prop:property_service set;
+#line 1 "external/sepolicy/system_server.te"
+#
+# System Server aka system_server spawned by zygote.
+# Most of the framework services run in this process.
+#
+type system_server, domain, mlstrustedsubject;
+
+#line 6
+typeattribute system_server mlstrustedsubject;
+#line 6
+typeattribute system_server unconfineddomain;
+#line 6
+
+
+# Define a type for tmpfs-backed ashmem regions.
+
+#line 9
+type system_server_tmpfs, file_type;
+#line 9
+type_transition system_server tmpfs:file system_server_tmpfs;
+#line 9
+allow system_server system_server_tmpfs:file { read write };
+#line 9
+
+
+# Dalvik Compiler JIT Mapping.
+allow system_server self:process execmem;
+allow system_server ashmem_device:chr_file execute;
+allow system_server system_server_tmpfs:file execute;
+
+# For art.
+allow system_server dalvikcache_data_file:file execute;
+
+# Child of the zygote.
+allow system_server zygote:fd use;
+allow system_server zygote:process sigchld;
+allow system_server zygote_tmpfs:file read;
+
+# Needed to close the zygote socket, which involves getopt / getattr
+# This should be deleted after b/12061011 is fixed
+allow system_server zygote:unix_stream_socket { getopt getattr };
+
+# system server gets network and bluetooth permissions.
+
+#line 29
+typeattribute system_server netdomain;
+#line 29
+
+
+#line 30
+typeattribute system_server bluetoothdomain;
+#line 30
+
+
+# These are the capabilities assigned by the zygote to the
+# system server.
+allow system_server self:capability {
+    kill
+    net_admin
+    net_bind_service
+    net_broadcast
+    net_raw
+    sys_boot
+    sys_module
+    sys_nice
+    sys_resource
+    sys_time
+    sys_tty_config
+};
+
+allow system_server self:capability2 block_suspend;
+
+# Triggered by /proc/pid accesses, not allowed.
+dontaudit system_server self:capability sys_ptrace;
+
+# Trigger module auto-load.
+allow system_server kernel:system module_request;
+
+# Use netlink uevent sockets.
+allow system_server self:netlink_kobject_uevent_socket *;
+
+# Kill apps.
+allow system_server appdomain:process { sigkill signal };
+
+# Set scheduling info for apps.
+allow system_server appdomain:process { getsched setsched };
+allow system_server mediaserver:process { getsched setsched };
+
+# Read /proc data for apps.
+allow system_server appdomain:dir { open getattr read search ioctl };
+allow system_server appdomain:{ file lnk_file } { { getattr open read ioctl lock } { open append write } };
+
+# Read/Write to /proc/net/xt_qtaguid/ctrl and and /dev/xt_qtaguid.
+allow system_server qtaguid_proc:file { { getattr open read ioctl lock } { open append write } };
+allow system_server qtaguid_device:chr_file { { getattr open read ioctl lock } { open append write } };
+
+# Read /sys/kernel/debug/wakeup_sources.
+allow system_server debugfs:file { getattr open read ioctl lock };
+
+# WifiWatchdog uses a packet_socket
+allow system_server self:packet_socket *;
+
+# 3rd party VPN clients require a tun_socket to be created
+allow system_server self:tun_socket create;
+
+# Notify init of death.
+allow system_server init:process sigchld;
+
+# Talk to init and various daemons via sockets.
+
+#line 87
+allow system_server property_socket:sock_file write;
+#line 87
+allow system_server init:unix_stream_socket connectto;
+#line 87
+
+
+#line 88
+allow system_server qemud_socket:sock_file write;
+#line 88
+allow system_server qemud:unix_stream_socket connectto;
+#line 88
+
+
+#line 89
+allow system_server installd_socket:sock_file write;
+#line 89
+allow system_server installd:unix_stream_socket connectto;
+#line 89
+
+
+#line 90
+allow system_server lmkd_socket:sock_file write;
+#line 90
+allow system_server lmkd:unix_stream_socket connectto;
+#line 90
+
+
+#line 91
+allow system_server netd_socket:sock_file write;
+#line 91
+allow system_server netd:unix_stream_socket connectto;
+#line 91
+
+
+#line 92
+allow system_server vold_socket:sock_file write;
+#line 92
+allow system_server vold:unix_stream_socket connectto;
+#line 92
+
+
+#line 93
+allow system_server zygote_socket:sock_file write;
+#line 93
+allow system_server zygote:unix_stream_socket connectto;
+#line 93
+
+
+#line 94
+allow system_server keystore_socket:sock_file write;
+#line 94
+allow system_server keystore:unix_stream_socket connectto;
+#line 94
+
+
+#line 95
+allow system_server gps_socket:sock_file write;
+#line 95
+allow system_server gpsd:unix_stream_socket connectto;
+#line 95
+
+
+#line 96
+allow system_server racoon_socket:sock_file write;
+#line 96
+allow system_server racoon:unix_stream_socket connectto;
+#line 96
+
+
+#line 97
+allow system_server wpa_socket:sock_file write;
+#line 97
+allow system_server wpa:unix_dgram_socket sendto;
+#line 97
+
+
+# Communicate over a socket created by surfaceflinger.
+allow system_server surfaceflinger:unix_stream_socket { read write setopt };
+
+# Perform Binder IPC.
+
+#line 103
+# Call the servicemanager and transfer references to it.
+#line 103
+allow system_server servicemanager:binder { call transfer };
+#line 103
+# rw access to /dev/binder and /dev/ashmem is presently granted to
+#line 103
+# all domains in domain.te.
+#line 103
+
+
+#line 104
+# Call the server domain and optionally transfer references to it.
+#line 104
+allow system_server binderservicedomain:binder { call transfer };
+#line 104
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 104
+allow binderservicedomain system_server:binder transfer;
+#line 104
+# Receive and use open files from the server.
+#line 104
+allow system_server binderservicedomain:fd use;
+#line 104
+
+
+#line 105
+# Call the server domain and optionally transfer references to it.
+#line 105
+allow system_server appdomain:binder { call transfer };
+#line 105
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 105
+allow appdomain system_server:binder transfer;
+#line 105
+# Receive and use open files from the server.
+#line 105
+allow system_server appdomain:fd use;
+#line 105
+
+
+#line 106
+# Call the server domain and optionally transfer references to it.
+#line 106
+allow system_server healthd:binder { call transfer };
+#line 106
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 106
+allow healthd system_server:binder transfer;
+#line 106
+# Receive and use open files from the server.
+#line 106
+allow system_server healthd:fd use;
+#line 106
+
+
+#line 107
+# Call the server domain and optionally transfer references to it.
+#line 107
+allow system_server dumpstate:binder { call transfer };
+#line 107
+# Allow the serverdomain to transfer references to the client on the reply.
+#line 107
+allow dumpstate system_server:binder transfer;
+#line 107
+# Receive and use open files from the server.
+#line 107
+allow system_server dumpstate:fd use;
+#line 107
+
+
+#line 108
+typeattribute system_server binderservicedomain;
+#line 108
+
+
+# Read /proc/pid files for Binder clients.
+
+#line 111
+allow system_server appdomain:dir { open getattr read search ioctl };
+#line 111
+allow system_server appdomain:{ file lnk_file } { getattr open read ioctl lock };
+#line 111
+
+
+#line 112
+allow system_server mediaserver:dir { open getattr read search ioctl };
+#line 112
+allow system_server mediaserver:{ file lnk_file } { getattr open read ioctl lock };
+#line 112
+
+allow system_server appdomain:process getattr;
+allow system_server mediaserver:process getattr;
+
+# Check SELinux permissions.
+
+#line 117
+allow system_server selinuxfs:dir { open getattr read search ioctl };
+#line 117
+allow system_server selinuxfs:file { { getattr open read ioctl lock } { open append write } };
+#line 117
+allow system_server kernel:security compute_av;
+#line 117
+allow system_server self:netlink_selinux_socket *;
+#line 117
+
+
+# XXX Label sysfs files with a specific type?
+allow system_server sysfs:file { { getattr open read ioctl lock } { open append write } };
+allow system_server sysfs_nfc_power_writable:file { { getattr open read ioctl lock } { open append write } };
+
+# Access devices.
+allow system_server device:dir { open getattr read search ioctl };
+allow system_server mdns_socket:sock_file { { getattr open read ioctl lock } { open append write } };
+allow system_server alarm_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow system_server gpu_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow system_server graphics_device:dir search;
+allow system_server graphics_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow system_server iio_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow system_server input_device:dir { open getattr read search ioctl };
+allow system_server input_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow system_server tty_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow system_server urandom_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow system_server usbaccessory_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow system_server video_device:dir { open getattr read search ioctl };
+allow system_server video_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow system_server qemu_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow system_server adbd_socket:sock_file { { getattr open read ioctl lock } { open append write } };
+
+# tun device used for 3rd party vpn apps
+allow system_server tun_device:chr_file { { getattr open read ioctl lock } { open append write } };
+
+# Manage data files.
+allow system_server data_file_type:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow system_server data_file_type:{ file lnk_file sock_file fifo_file } { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+
+# Read /file_contexts and /data/security/file_contexts
+
+#line 149
+allow system_server security_file:dir { open getattr read search ioctl };
+#line 149
+allow system_server security_file:file { getattr open read ioctl lock };
+#line 149
+allow system_server security_file:lnk_file { getattr open read ioctl lock };
+#line 149
+allow system_server selinuxfs:dir { open getattr read search ioctl };
+#line 149
+allow system_server selinuxfs:file { getattr open read ioctl lock };
+#line 149
+allow system_server rootfs:dir { open getattr read search ioctl };
+#line 149
+allow system_server rootfs:file { getattr open read ioctl lock };
+#line 149
+
+
+# Relabel apk files.
+
+#line 152
+typeattribute system_server relabeltodomain;
+#line 152
+
+allow system_server { apk_tmp_file apk_private_tmp_file }:file { relabelfrom relabelto };
+allow system_server { apk_data_file apk_private_data_file }:file { relabelfrom relabelto };
+
+# Relabel wallpaper.
+allow system_server system_data_file:file relabelfrom;
+allow system_server wallpaper_file:file relabelto;
+allow system_server wallpaper_file:file { { getattr open read ioctl lock } { open append write } };
+
+# Relabel /data/anr.
+allow system_server system_data_file:dir relabelfrom;
+allow system_server anr_data_file:dir relabelto;
+
+# Property Service write
+allow system_server system_prop:property_service set;
+allow system_server radio_prop:property_service set;
+allow system_server debug_prop:property_service set;
+allow system_server powerctl_prop:property_service set;
+
+# ctl interface
+allow system_server ctl_default_prop:property_service set;
+
+# Create a socket for receiving info from wpa.
+type_transition system_server wifi_data_file:sock_file system_wpa_socket;
+type_transition system_server wpa_socket:sock_file system_wpa_socket;
+allow system_server wpa_socket:dir { { open getattr read search ioctl } { open search write add_name remove_name } };
+allow system_server system_wpa_socket:sock_file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+
+# Remove sockets created by wpa_supplicant
+allow system_server wpa_socket:sock_file unlink;
+
+# Create a socket for connections from debuggerd.
+type_transition system_server system_data_file:sock_file system_ndebug_socket "ndebugsocket";
+allow system_server system_ndebug_socket:sock_file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+
+# Specify any arguments to zygote.
+allow system_server self:zygote { specifyids specifyrlimits specifyseinfo };
+
+# Manage cache files.
+allow system_server cache_file:dir { relabelfrom { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } } };
+allow system_server cache_file:file { relabelfrom { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } } };
+
+# Run system programs, e.g. dexopt.
+allow system_server system_file:file { getattr execute execute_no_trans };
+
+# Allow reading of /proc/pid data for other domains.
+# XXX dontaudit candidate
+allow system_server domain:dir { open getattr read search ioctl };
+allow system_server domain:file { getattr open read ioctl lock };
+
+# LocationManager(e.g, GPS) needs to read and write
+# to uart driver and ctrl proc entry
+allow system_server gps_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow system_server gps_control:file { { getattr open read ioctl lock } { open append write } };
+
+# Allow system_server to use app-created sockets.
+allow system_server appdomain:{ tcp_socket udp_socket } { setopt read write };
+
+# Allow abstract socket connection
+allow system_server rild:unix_stream_socket connectto;
+
+# connect to vpn tunnel
+allow system_server mtp:unix_stream_socket { connectto };
+
+# BackupManagerService lets PMS create a data backup file
+allow system_server cache_backup_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+# Relabel /data/backup
+allow system_server backup_data_file:dir { relabelto relabelfrom };
+# Relabel /cache/.*\.{data|restore}
+allow system_server cache_backup_file:file { relabelto relabelfrom };
+# LocalTransport creates and relabels /cache/backup
+allow system_server cache_backup_file:dir { relabelto relabelfrom { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } } };
+
+# Allow system to talk to usb device
+allow system_server usb_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow system_server usb_device:dir { open getattr read search ioctl };
+
+# Allow system to talk to sensors
+allow system_server sensors_device:chr_file { { getattr open read ioctl lock } { open append write } };
+
+# Read from HW RNG (needed by EntropyMixer).
+allow system_server hw_random_device:chr_file { getattr open read ioctl lock };
+
+# Access to wake locks
+allow system_server sysfs_wake_lock:file { { getattr open read ioctl lock } { open append write } };
+
+# Read and delete files under /dev/fscklogs.
+
+#line 239
+allow system_server fscklogs:dir { open getattr read search ioctl };
+#line 239
+allow system_server fscklogs:{ file lnk_file } { getattr open read ioctl lock };
+#line 239
+
+allow system_server fscklogs:dir { write remove_name };
+allow system_server fscklogs:file unlink;
+
+# For SELinuxPolicyInstallReceiver
+
+#line 244
+
+#line 244
+allow system_server security_file:dir { open getattr read search ioctl };
+#line 244
+allow system_server security_file:file { getattr open read ioctl lock };
+#line 244
+allow system_server security_file:lnk_file { getattr open read ioctl lock };
+#line 244
+allow system_server selinuxfs:dir { open getattr read search ioctl };
+#line 244
+allow system_server selinuxfs:file { getattr open read ioctl lock };
+#line 244
+allow system_server rootfs:dir { open getattr read search ioctl };
+#line 244
+allow system_server rootfs:file { getattr open read ioctl lock };
+#line 244
+
+#line 244
+
+#line 244
+allow system_server property_socket:sock_file write;
+#line 244
+allow system_server init:unix_stream_socket connectto;
+#line 244
+
+#line 244
+allow system_server security_file:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+#line 244
+allow system_server security_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+#line 244
+allow system_server security_file:lnk_file { create rename unlink };
+#line 244
+allow system_server security_prop:property_service set;
+#line 244
+
+
+# For legacy unlabeled userdata on existing devices.
+# See discussion of Unlabeled files in domain.te for more information.
+# This rule is for dalvikcache mmap/mprotect PROT_EXEC.
+allow system_server unlabeled:file execute;
+
+# logd access, system_server inherit logd write socket
+# (urge is to deprecate this long term)
+allow system_server zygote:unix_dgram_socket write;
+
+# Be consistent with DAC permissions. Allow system_server to write to
+# /sys/module/lowmemorykiller/parameters/adj
+# /sys/module/lowmemorykiller/parameters/minfree
+allow system_server sysfs_lowmemorykiller:file { open append write };
+#line 1 "external/sepolicy/tee.te"
+##
+# trusted execution environment (tee) daemon
+#
+type tee, domain;
+type tee_exec, exec_type, file_type;
+type tee_device, dev_type;
+type tee_data_file, file_type, data_file_type;
+
+
+#line 9
+
+#line 9
+# Allow the necessary permissions.
+#line 9
+
+#line 9
+# Old domain may exec the file and transition to the new domain.
+#line 9
+allow init tee_exec:file { getattr open read execute };
+#line 9
+allow init tee:process transition;
+#line 9
+# New domain is entered by executing the file.
+#line 9
+allow tee tee_exec:file { entrypoint read execute };
+#line 9
+# New domain can send SIGCHLD to its caller.
+#line 9
+allow tee init:process sigchld;
+#line 9
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 9
+dontaudit init tee:process noatsecure;
+#line 9
+# XXX dontaudit candidate but requires further study.
+#line 9
+allow init tee:process { siginh rlimitinh };
+#line 9
+
+#line 9
+# Make the transition occur by default.
+#line 9
+type_transition init tee_exec:process tee;
+#line 9
+
+#line 9
+
+#line 9
+type tee_tmpfs, file_type;
+#line 9
+type_transition tee tmpfs:file tee_tmpfs;
+#line 9
+allow tee tee_tmpfs:file { read write };
+#line 9
+
+#line 9
+
+allow tee self:capability { dac_override };
+allow tee tee_device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow tee tee_data_file:dir { { open getattr read search ioctl } { open search write add_name remove_name } };
+allow tee tee_data_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+allow tee self:netlink_socket { create bind read };
+#line 1 "external/sepolicy/ueventd.te"
+# ueventd seclabel is specified in init.rc since
+# it lives in the rootfs and has no unique file type.
+type ueventd, domain;
+
+#line 4
+type ueventd_tmpfs, file_type;
+#line 4
+type_transition ueventd tmpfs:file ueventd_tmpfs;
+#line 4
+allow ueventd ueventd_tmpfs:file { read write };
+#line 4
+
+
+#line 5
+type_transition ueventd device:chr_file klog_device "__kmsg__";
+#line 5
+allow ueventd klog_device:chr_file { create open write unlink };
+#line 5
+allow ueventd device:dir { write add_name remove_name };
+#line 5
+
+
+#line 6
+allow ueventd security_file:dir { open getattr read search ioctl };
+#line 6
+allow ueventd security_file:file { getattr open read ioctl lock };
+#line 6
+allow ueventd security_file:lnk_file { getattr open read ioctl lock };
+#line 6
+allow ueventd selinuxfs:dir { open getattr read search ioctl };
+#line 6
+allow ueventd selinuxfs:file { getattr open read ioctl lock };
+#line 6
+allow ueventd rootfs:dir { open getattr read search ioctl };
+#line 6
+allow ueventd rootfs:file { getattr open read ioctl lock };
+#line 6
+
+
+#line 7
+typeattribute ueventd relabeltodomain;
+#line 7
+
+allow ueventd rootfs:file entrypoint;
+allow ueventd init:process sigchld;
+allow ueventd self:capability { chown mknod net_admin setgid fsetid sys_rawio dac_override fowner };
+allow ueventd device:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+allow ueventd device:chr_file { { getattr open read ioctl lock } { open append write } };
+allow ueventd sysfs:file { { getattr open read ioctl lock } { open append write } };
+allow ueventd sysfs:file setattr;
+allow ueventd sysfs_type:file { relabelfrom relabelto };
+allow ueventd sysfs_devices_system_cpu:file { { getattr open read ioctl lock } { open append write } };
+allow ueventd tmpfs:chr_file { { getattr open read ioctl lock } { open append write } };
+allow ueventd dev_type:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow ueventd dev_type:lnk_file { create unlink };
+allow ueventd dev_type:chr_file { create setattr unlink };
+allow ueventd dev_type:blk_file { create setattr unlink };
+allow ueventd self:netlink_kobject_uevent_socket *;
+allow ueventd efs_file:dir search;
+allow ueventd efs_file:file { getattr open read ioctl lock };
+#line 1 "external/sepolicy/unconfined.te"
+#######################################################
+#
+# This is the unconfined template. This template is the base policy
+# which is used by daemons and other privileged components of
+# Android.
+#
+# Historically, this template was called "unconfined" because it
+# allowed the domain to do anything it wanted. Over time,
+# this has changed, and will continue to change in the future.
+# The rules in this file will be removed when no remaining
+# unconfined domains require it, or when the rules contradict
+# Android security best practices. Domains which need rules not
+# provided by the unconfined template should add them directly to
+# the relevant policy.
+#
+# The use of this template is discouraged.
+######################################################
+
+allow unconfineddomain self:capability ~{ sys_ptrace sys_rawio mknod sys_module };
+allow unconfineddomain self:capability2 ~{ mac_override mac_admin };
+allow unconfineddomain kernel:security ~{ load_policy setenforce setcheckreqprot };
+allow unconfineddomain kernel:system *;
+allow unconfineddomain domain:process ~{ execmem execstack execheap ptrace transition dyntransition };
+allow unconfineddomain domain:fd *;
+allow unconfineddomain domain:dir { open getattr read search ioctl };
+allow unconfineddomain domain:lnk_file { getattr open read ioctl lock };
+allow unconfineddomain domain:{ fifo_file file } { { getattr open read ioctl lock } { open append write } };
+allow unconfineddomain domain:{ socket tcp_socket udp_socket rawip_socket netlink_socket packet_socket key_socket unix_stream_socket unix_dgram_socket appletalk_socket netlink_route_socket netlink_firewall_socket netlink_tcpdiag_socket netlink_nflog_socket netlink_xfrm_socket netlink_selinux_socket netlink_audit_socket netlink_ip6fw_socket netlink_dnrt_socket netlink_kobject_uevent_socket tun_socket } *;
+allow unconfineddomain domain:{ sem msgq shm ipc } *;
+allow unconfineddomain domain:key *;
+allow unconfineddomain {fs_type dev_type file_type}:{ dir lnk_file sock_file fifo_file } ~relabelto;
+allow unconfineddomain {fs_type -usermodehelper -proc_security}:{ chr_file file } ~{entrypoint execmod execute relabelto};
+allow unconfineddomain {dev_type -kmem_device}:{ chr_file file } ~{entrypoint execmod execute relabelto};
+allow unconfineddomain file_type:{ chr_file file } ~{entrypoint execmod execute relabelto};
+allow unconfineddomain { rootfs system_file exec_type }:file execute;
+allow unconfineddomain node_type:node *;
+allow unconfineddomain node_type:{ tcp_socket udp_socket rawip_socket } node_bind;
+allow unconfineddomain netif_type:netif *;
+allow unconfineddomain port_type:{ socket tcp_socket udp_socket rawip_socket netlink_socket packet_socket key_socket unix_stream_socket unix_dgram_socket appletalk_socket netlink_route_socket netlink_firewall_socket netlink_tcpdiag_socket netlink_nflog_socket netlink_xfrm_socket netlink_selinux_socket netlink_audit_socket netlink_ip6fw_socket netlink_dnrt_socket netlink_kobject_uevent_socket tun_socket } name_bind;
+allow unconfineddomain port_type:{ tcp_socket dccp_socket } name_connect;
+allow unconfineddomain domain:peer recv;
+allow unconfineddomain { domain -init }:binder { call transfer set_context_mgr };
+allow unconfineddomain property_type:property_service set;
+#line 1 "external/sepolicy/uncrypt.te"
+# uncrypt
+type uncrypt, domain;
+type uncrypt_exec, exec_type, file_type;
+
+
+#line 5
+
+#line 5
+# Allow the necessary permissions.
+#line 5
+
+#line 5
+# Old domain may exec the file and transition to the new domain.
+#line 5
+allow init uncrypt_exec:file { getattr open read execute };
+#line 5
+allow init uncrypt:process transition;
+#line 5
+# New domain is entered by executing the file.
+#line 5
+allow uncrypt uncrypt_exec:file { entrypoint read execute };
+#line 5
+# New domain can send SIGCHLD to its caller.
+#line 5
+allow uncrypt init:process sigchld;
+#line 5
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 5
+dontaudit init uncrypt:process noatsecure;
+#line 5
+# XXX dontaudit candidate but requires further study.
+#line 5
+allow init uncrypt:process { siginh rlimitinh };
+#line 5
+
+#line 5
+# Make the transition occur by default.
+#line 5
+type_transition init uncrypt_exec:process uncrypt;
+#line 5
+
+#line 5
+
+#line 5
+type uncrypt_tmpfs, file_type;
+#line 5
+type_transition uncrypt tmpfs:file uncrypt_tmpfs;
+#line 5
+allow uncrypt uncrypt_tmpfs:file { read write };
+#line 5
+
+#line 5
+
+
+#line 6
+typeattribute uncrypt mlstrustedsubject;
+#line 6
+typeattribute uncrypt unconfineddomain;
+#line 6
+
+
+allow uncrypt self:capability dac_override;
+
+# Read OTA zip file from /data/data/com.google.android.gsf/app_download
+
+#line 11
+allow uncrypt app_data_file:dir { open getattr read search ioctl };
+#line 11
+allow uncrypt app_data_file:{ file lnk_file } { getattr open read ioctl lock };
+#line 11
+
+
+#line 16
+
+
+# Create tmp file /cache/recovery/command.tmp
+# Read /cache/recovery/command
+# Rename /cache/recovery/command.tmp to /cache/recovery/command
+allow uncrypt cache_file:dir { { open getattr read search ioctl } { open search write add_name remove_name } };
+allow uncrypt cache_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+
+# Set a property to reboot the device.
+
+#line 25
+allow uncrypt property_socket:sock_file write;
+#line 25
+allow uncrypt init:unix_stream_socket connectto;
+#line 25
+
+allow uncrypt powerctl_prop:property_service set;
+
+# Raw writes to block device
+allow uncrypt self:capability sys_rawio;
+allow uncrypt block_device:blk_file { open append write };
+#line 1 "external/sepolicy/untrusted_app.te"
+###
+### Untrusted apps.
+###
+### This file defines the rules for untrusted apps. An "untrusted
+### app" is an APP with UID between APP_AID (10000)
+### and AID_ISOLATED_START (99000).
+###
+### untrusted_app includes all the appdomain rules, plus the
+### additional following rules:
+###
+
+type untrusted_app, domain;
+
+#line 13
+typeattribute untrusted_app mlstrustedsubject;
+#line 13
+typeattribute untrusted_app unconfineddomain;
+#line 13
+
+
+#line 14
+typeattribute untrusted_app appdomain;
+#line 14
+# Label ashmem objects with our own unique type.
+#line 14
+
+#line 14
+type untrusted_app_tmpfs, file_type;
+#line 14
+type_transition untrusted_app tmpfs:file untrusted_app_tmpfs;
+#line 14
+allow untrusted_app untrusted_app_tmpfs:file { read write };
+#line 14
+
+#line 14
+# Map with PROT_EXEC.
+#line 14
+allow untrusted_app untrusted_app_tmpfs:file execute;
+#line 14
+
+
+#line 15
+typeattribute untrusted_app netdomain;
+#line 15
+
+
+#line 16
+typeattribute untrusted_app bluetoothdomain;
+#line 16
+
+
+# Some apps ship with shared libraries and binaries that they write out
+# to their sandbox directory and then execute.
+allow untrusted_app app_data_file:file { { getattr open read ioctl lock } { getattr execute execute_no_trans } };
+
+allow untrusted_app tun_device:chr_file { { getattr open read ioctl lock } { open append write } };
+
+# Internal SDCard rw access.
+allow untrusted_app sdcard_internal:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow untrusted_app sdcard_internal:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+
+# External SDCard rw access.
+allow untrusted_app sdcard_external:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow untrusted_app sdcard_external:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+
+# ASEC
+allow untrusted_app asec_apk_file:dir { getattr };
+allow untrusted_app asec_apk_file:file { getattr open read ioctl lock };
+# Execute libs in asec containers.
+allow untrusted_app asec_public_file:file execute;
+
+# Create tcp/udp sockets
+allow untrusted_app node_type:{ tcp_socket udp_socket } node_bind;
+allow untrusted_app self:{ tcp_socket udp_socket } { { create { ioctl read getattr write setattr append bind connect getopt setopt shutdown } } accept listen };
+# Bind to a particular hostname/address/interface (e.g., localhost) instead of
+# ANY. Normally, apps should not be listening on all interfaces.
+allow untrusted_app port:{ tcp_socket udp_socket } name_bind;
+
+# Allow the allocation and use of ptys
+# Used by: https://play.google.com/store/apps/details?id=jackpal.androidterm
+
+#line 47
+# Each domain gets a unique devpts type.
+#line 47
+type untrusted_app_devpts, fs_type;
+#line 47
+# Label the pty with the unique type when created.
+#line 47
+type_transition untrusted_app devpts:chr_file untrusted_app_devpts;
+#line 47
+# Allow use of the pty after creation.
+#line 47
+allow untrusted_app untrusted_app_devpts:chr_file { open getattr read write ioctl };
+#line 47
+# Note: devpts:dir search and ptmx_device:chr_file rw_file_perms
+#line 47
+# allowed to everyone via domain.te.
+#line 47
+
+
+# Used by Finsky / Android "Verify Apps" functionality when
+# running "adb install foo.apk".
+# TODO: Long term, we don't want apps probing into shell data files.
+# Figure out a way to remove these rules.
+allow untrusted_app shell_data_file:file { getattr open read ioctl lock };
+allow untrusted_app shell_data_file:dir { open getattr read search ioctl };
+#line 1 "external/sepolicy/vold.te"
+# volume manager
+type vold, domain;
+type vold_exec, exec_type, file_type;
+
+
+#line 5
+
+#line 5
+# Allow the necessary permissions.
+#line 5
+
+#line 5
+# Old domain may exec the file and transition to the new domain.
+#line 5
+allow init vold_exec:file { getattr open read execute };
+#line 5
+allow init vold:process transition;
+#line 5
+# New domain is entered by executing the file.
+#line 5
+allow vold vold_exec:file { entrypoint read execute };
+#line 5
+# New domain can send SIGCHLD to its caller.
+#line 5
+allow vold init:process sigchld;
+#line 5
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 5
+dontaudit init vold:process noatsecure;
+#line 5
+# XXX dontaudit candidate but requires further study.
+#line 5
+allow init vold:process { siginh rlimitinh };
+#line 5
+
+#line 5
+# Make the transition occur by default.
+#line 5
+type_transition init vold_exec:process vold;
+#line 5
+
+#line 5
+
+#line 5
+type vold_tmpfs, file_type;
+#line 5
+type_transition vold tmpfs:file vold_tmpfs;
+#line 5
+allow vold vold_tmpfs:file { read write };
+#line 5
+
+#line 5
+
+
+typeattribute vold mlstrustedsubject;
+allow vold system_file:file { getattr execute execute_no_trans };
+allow vold block_device:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow vold block_device:blk_file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+allow vold device:dir write;
+allow vold devpts:chr_file { { getattr open read ioctl lock } { open append write } };
+allow vold rootfs:dir mounton;
+allow vold sdcard_type:dir mounton;
+allow vold sdcard_type:filesystem { mount remount unmount };
+allow vold sdcard_type:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow vold sdcard_type:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+allow vold tmpfs:filesystem { mount unmount };
+allow vold tmpfs:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow vold tmpfs:dir mounton;
+allow vold self:capability { net_admin dac_override mknod sys_admin chown fowner fsetid };
+allow vold self:netlink_kobject_uevent_socket *;
+allow vold app_data_file:dir search;
+allow vold app_data_file:file { { getattr open read ioctl lock } { open append write } };
+allow vold loop_device:blk_file { { getattr open read ioctl lock } { open append write } };
+allow vold dm_device:chr_file { { getattr open read ioctl lock } { open append write } };
+# For vold Process::killProcessesWithOpenFiles function.
+allow vold domain:dir { open getattr read search ioctl };
+allow vold domain:{ file lnk_file } { getattr open read ioctl lock };
+allow vold domain:process { signal sigkill };
+allow vold self:capability { sys_ptrace kill };
+
+# For blkid
+allow vold shell_exec:file { { getattr open read ioctl lock } { getattr execute execute_no_trans } };
+
+# XXX Label sysfs files with a specific type?
+allow vold sysfs:file { { getattr open read ioctl lock } { open append write } };
+
+
+#line 39
+type_transition vold device:chr_file klog_device "__kmsg__";
+#line 39
+allow vold klog_device:chr_file { create open write unlink };
+#line 39
+allow vold device:dir { write add_name remove_name };
+#line 39
+
+
+# Log fsck results
+allow vold fscklogs:dir { { open getattr read search ioctl } { open search write add_name remove_name } };
+allow vold fscklogs:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+
+#
+# Rules to support encrypted fs support.
+#
+
+# Set property.
+
+#line 50
+allow vold property_socket:sock_file write;
+#line 50
+allow vold init:unix_stream_socket connectto;
+#line 50
+
+
+# Unmount and mount the fs.
+allow vold labeledfs:filesystem { mount unmount remount };
+
+# Access /efs/userdata_footer.
+# XXX Split into a separate type?
+allow vold efs_file:file { { getattr open read ioctl lock } { open append write } };
+
+# Create and mount on /data/tmp_mnt.
+allow vold system_data_file:dir { create { { open getattr read search ioctl } { open search write add_name remove_name } } mounton };
+
+# Set scheduling policy of kernel processes
+allow vold kernel:process setsched;
+
+# Property Service
+allow vold vold_prop:property_service set;
+allow vold powerctl_prop:property_service set;
+allow vold ctl_default_prop:property_service set;
+
+# ASEC
+allow vold asec_image_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+allow vold asec_image_file:dir { { open getattr read search ioctl } { open search write add_name remove_name } };
+
+#line 73
+allow vold security_file:dir { open getattr read search ioctl };
+#line 73
+allow vold security_file:file { getattr open read ioctl lock };
+#line 73
+allow vold security_file:lnk_file { getattr open read ioctl lock };
+#line 73
+allow vold selinuxfs:dir { open getattr read search ioctl };
+#line 73
+allow vold selinuxfs:file { getattr open read ioctl lock };
+#line 73
+allow vold rootfs:dir { open getattr read search ioctl };
+#line 73
+allow vold rootfs:file { getattr open read ioctl lock };
+#line 73
+
+
+#line 74
+typeattribute vold relabeltodomain;
+#line 74
+
+allow vold asec_apk_file:dir { { { open getattr read search ioctl } { open search write add_name remove_name } } setattr relabelfrom };
+allow vold asec_public_file:dir { relabelto setattr };
+allow vold asec_apk_file:file { { getattr open read ioctl lock } setattr relabelfrom };
+allow vold asec_public_file:file { relabelto setattr };
+
+# Handle wake locks (used for device encryption)
+allow vold sysfs_wake_lock:file { { getattr open read ioctl lock } { open append write } };
+allow vold self:capability2 block_suspend;
+#line 1 "external/sepolicy/watchdogd.te"
+# watchdogd seclabel is specified in init.<board>.rc
+type watchdogd, domain;
+allow watchdogd rootfs:file { entrypoint { getattr open read ioctl lock } };
+allow watchdogd self:capability mknod;
+allow watchdogd device:dir { add_name write remove_name };
+allow watchdogd watchdog_device:chr_file { { getattr open read ioctl lock } { open append write } };
+# because of /dev/__kmsg__ and /dev/__null__
+
+#line 8
+type_transition watchdogd device:chr_file klog_device "__kmsg__";
+#line 8
+allow watchdogd klog_device:chr_file { create open write unlink };
+#line 8
+allow watchdogd device:dir { write add_name remove_name };
+#line 8
+
+type_transition watchdogd device:chr_file null_device "__null__";
+allow watchdogd null_device:chr_file { create unlink };
+#line 1 "external/sepolicy/wpa_supplicant.te"
+# wpa - wpa supplicant or equivalent
+type wpa, domain;
+type wpa_exec, exec_type, file_type;
+
+
+#line 5
+
+#line 5
+# Allow the necessary permissions.
+#line 5
+
+#line 5
+# Old domain may exec the file and transition to the new domain.
+#line 5
+allow init wpa_exec:file { getattr open read execute };
+#line 5
+allow init wpa:process transition;
+#line 5
+# New domain is entered by executing the file.
+#line 5
+allow wpa wpa_exec:file { entrypoint read execute };
+#line 5
+# New domain can send SIGCHLD to its caller.
+#line 5
+allow wpa init:process sigchld;
+#line 5
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 5
+dontaudit init wpa:process noatsecure;
+#line 5
+# XXX dontaudit candidate but requires further study.
+#line 5
+allow init wpa:process { siginh rlimitinh };
+#line 5
+
+#line 5
+# Make the transition occur by default.
+#line 5
+type_transition init wpa_exec:process wpa;
+#line 5
+
+#line 5
+
+#line 5
+type wpa_tmpfs, file_type;
+#line 5
+type_transition wpa tmpfs:file wpa_tmpfs;
+#line 5
+allow wpa wpa_tmpfs:file { read write };
+#line 5
+
+#line 5
+
+allow wpa kernel:system module_request;
+allow wpa self:capability { setuid net_admin setgid net_raw };
+allow wpa cgroup:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow wpa self:netlink_route_socket *;
+allow wpa self:netlink_socket *;
+allow wpa self:packet_socket *;
+allow wpa self:udp_socket *;
+allow wpa wifi_data_file:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow wpa wifi_data_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+
+#line 15
+allow wpa system_wpa_socket:sock_file write;
+#line 15
+allow wpa system_server:unix_dgram_socket sendto;
+#line 15
+
+allow wpa random_device:chr_file { getattr open read ioctl lock };
+
+# Create a socket for receiving info from wpa
+type_transition wpa wifi_data_file:sock_file wpa_socket;
+allow wpa wpa_socket:dir { { { open getattr read search ioctl } { open search write add_name remove_name } } setattr };
+allow wpa wpa_socket:sock_file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+
+# Allow wpa_cli to work. wpa_cli creates a socket in
+# /data/misc/wifi/sockets which wpa supplicant communicates with.
+#line 27
+
+#line 1 "external/sepolicy/zygote.te"
+# zygote
+type zygote, domain;
+type zygote_exec, exec_type, file_type;
+
+
+#line 5
+
+#line 5
+# Allow the necessary permissions.
+#line 5
+
+#line 5
+# Old domain may exec the file and transition to the new domain.
+#line 5
+allow init zygote_exec:file { getattr open read execute };
+#line 5
+allow init zygote:process transition;
+#line 5
+# New domain is entered by executing the file.
+#line 5
+allow zygote zygote_exec:file { entrypoint read execute };
+#line 5
+# New domain can send SIGCHLD to its caller.
+#line 5
+allow zygote init:process sigchld;
+#line 5
+# Enable AT_SECURE, i.e. libc secure mode.
+#line 5
+dontaudit init zygote:process noatsecure;
+#line 5
+# XXX dontaudit candidate but requires further study.
+#line 5
+allow init zygote:process { siginh rlimitinh };
+#line 5
+
+#line 5
+# Make the transition occur by default.
+#line 5
+type_transition init zygote_exec:process zygote;
+#line 5
+
+#line 5
+
+#line 5
+type zygote_tmpfs, file_type;
+#line 5
+type_transition zygote tmpfs:file zygote_tmpfs;
+#line 5
+allow zygote zygote_tmpfs:file { read write };
+#line 5
+
+#line 5
+
+typeattribute zygote mlstrustedsubject;
+# Override DAC on files and switch uid/gid.
+allow zygote self:capability { dac_override setgid setuid fowner };
+# Drop capabilities from bounding set.
+allow zygote self:capability setpcap;
+# Switch SELinux context to app domains.
+allow zygote system_server:process dyntransition;
+allow zygote appdomain:process dyntransition;
+# Allow zygote to read app /proc/pid dirs (b/10455872)
+allow zygote appdomain:dir { getattr search };
+allow zygote appdomain:file { { getattr open read ioctl lock } };
+# Move children into the peer process group.
+allow zygote system_server:process { getpgid setpgid };
+allow zygote appdomain:process { getpgid setpgid };
+# Write to system data.
+allow zygote system_data_file:dir { { open getattr read search ioctl } { open search write add_name remove_name } };
+allow zygote system_data_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+allow zygote dalvikcache_data_file:dir { { open getattr read search ioctl } { open search write add_name remove_name } };
+allow zygote dalvikcache_data_file:file { create setattr { { getattr open read ioctl lock } { open append write } } { getattr link unlink rename } };
+# For art.
+allow zygote dalvikcache_data_file:file execute;
+# Execute dexopt.
+allow zygote system_file:file { getattr execute execute_no_trans };
+# Control cgroups.
+allow zygote cgroup:dir { create reparent rmdir setattr { { open getattr read search ioctl } { open search write add_name remove_name } } { getattr link unlink rename } };
+allow zygote self:capability sys_admin;
+# Check validity of SELinux context before use.
+
+#line 33
+allow zygote selinuxfs:dir { open getattr read search ioctl };
+#line 33
+allow zygote selinuxfs:file { { getattr open read ioctl lock } { open append write } };
+#line 33
+allow zygote kernel:security check_context;
+#line 33
+
+# Check SELinux permissions.
+
+#line 35
+allow zygote selinuxfs:dir { open getattr read search ioctl };
+#line 35
+allow zygote selinuxfs:file { { getattr open read ioctl lock } { open append write } };
+#line 35
+allow zygote kernel:security compute_av;
+#line 35
+allow zygote self:netlink_selinux_socket *;
+#line 35
+
+# Read /seapp_contexts and /data/security/seapp_contexts
+
+#line 37
+allow zygote security_file:dir { open getattr read search ioctl };
+#line 37
+allow zygote security_file:file { getattr open read ioctl lock };
+#line 37
+allow zygote security_file:lnk_file { getattr open read ioctl lock };
+#line 37
+allow zygote selinuxfs:dir { open getattr read search ioctl };
+#line 37
+allow zygote selinuxfs:file { getattr open read ioctl lock };
+#line 37
+allow zygote rootfs:dir { open getattr read search ioctl };
+#line 37
+allow zygote rootfs:file { getattr open read ioctl lock };
+#line 37
+
+
+# Setting up /storage/emulated.
+allow zygote rootfs:dir mounton;
+allow zygote sdcard_type:dir { write search setattr create add_name mounton };
+dontaudit zygote self:capability fsetid;
+allow zygote tmpfs:dir { write create add_name setattr mounton search };
+allow zygote tmpfs:filesystem mount;
+allow zygote labeledfs:filesystem remount;
+
+# Handle --invoke-with command when launching Zygote with a wrapper command.
+allow zygote zygote_exec:file { execute_no_trans open };
+
+# handle bugreports b/10498304
+allow zygote ashmem_device:chr_file execute;
+allow zygote shell_data_file:file { write getattr };
+allow zygote system_server:binder { transfer call };
+allow zygote servicemanager:binder { call };
+
+# For legacy unlabeled userdata on existing devices.
+# See discussion of Unlabeled files in domain.te for more information.
+# This rule is for dalvikcache mmap/mprotect PROT_EXEC.
+allow zygote unlabeled:file execute;
+#line 1 "build/target/board/generic/sepolicy/bootanim.te"
+allow bootanim self:process execmem;
+allow bootanim ashmem_device:chr_file execute;
+#line 1 "build/target/board/generic/sepolicy/domain.te"
+# For /sys/qemu_trace files in the emulator.
+allow domain sysfs_writable:file { { getattr open read ioctl lock } { open append write } };
+#line 1 "build/target/board/generic/sepolicy/surfaceflinger.te"
+allow surfaceflinger self:process execmem;
+allow surfaceflinger ashmem_device:chr_file execute;
+#line 1 "external/sepolicy/roles"
+role r;
+role r types domain;
+#line 1 "external/sepolicy/users"
+user u roles { r } level s0 range s0 - s0:c0.c1023;
+#line 1 "external/sepolicy/initial_sid_contexts"
+sid kernel u:r:kernel:s0
+sid security u:object_r:kernel:s0
+sid unlabeled u:object_r:unlabeled:s0
+sid fs u:object_r:labeledfs:s0
+sid file u:object_r:unlabeled:s0
+sid file_labels u:object_r:unlabeled:s0
+sid init u:object_r:unlabeled:s0
+sid any_socket u:object_r:unlabeled:s0
+sid port u:object_r:port:s0
+sid netif u:object_r:netif:s0
+sid netmsg u:object_r:unlabeled:s0
+sid node u:object_r:node:s0
+sid igmp_packet u:object_r:unlabeled:s0
+sid icmp_socket u:object_r:unlabeled:s0
+sid tcp_socket u:object_r:unlabeled:s0
+sid sysctl_modprobe u:object_r:unlabeled:s0
+sid sysctl u:object_r:proc:s0
+sid sysctl_fs u:object_r:unlabeled:s0
+sid sysctl_kernel u:object_r:unlabeled:s0
+sid sysctl_net u:object_r:unlabeled:s0
+sid sysctl_net_unix u:object_r:unlabeled:s0
+sid sysctl_vm u:object_r:unlabeled:s0
+sid sysctl_dev u:object_r:unlabeled:s0
+sid kmod u:object_r:unlabeled:s0
+sid policy u:object_r:unlabeled:s0
+sid scmp_packet u:object_r:unlabeled:s0
+sid devnull u:object_r:null_device:s0
+#line 1 "external/sepolicy/fs_use"
+# Label inodes via getxattr.
+fs_use_xattr yaffs2 u:object_r:labeledfs:s0;
+fs_use_xattr jffs2 u:object_r:labeledfs:s0;
+fs_use_xattr ext2 u:object_r:labeledfs:s0;
+fs_use_xattr ext3 u:object_r:labeledfs:s0;
+fs_use_xattr ext4 u:object_r:labeledfs:s0;
+fs_use_xattr xfs u:object_r:labeledfs:s0;
+fs_use_xattr btrfs u:object_r:labeledfs:s0;
+
+# Label inodes from task label.
+fs_use_task pipefs u:object_r:pipefs:s0;
+fs_use_task sockfs u:object_r:sockfs:s0;
+
+# Label inodes from combination of task label and fs label.
+# Define type_transition rules if you want per-domain types.
+fs_use_trans devpts u:object_r:devpts:s0;
+fs_use_trans tmpfs u:object_r:tmpfs:s0;
+fs_use_trans devtmpfs u:object_r:device:s0;
+fs_use_trans shm u:object_r:shm:s0;
+fs_use_trans mqueue u:object_r:mqueue:s0;
+
+#line 1 "external/sepolicy/genfs_contexts"
+# Label inodes with the fs label.
+genfscon rootfs / u:object_r:rootfs:s0
+# proc labeling can be further refined (longest matching prefix).
+genfscon proc / u:object_r:proc:s0
+genfscon proc /net u:object_r:proc_net:s0
+genfscon proc /net/xt_qtaguid/ctrl u:object_r:qtaguid_proc:s0
+genfscon proc /sys/fs/protected_hardlinks u:object_r:proc_security:s0
+genfscon proc /sys/fs/protected_symlinks u:object_r:proc_security:s0
+genfscon proc /sys/fs/suid_dumpable u:object_r:proc_security:s0
+genfscon proc /sys/kernel/core_pattern u:object_r:usermodehelper:s0
+genfscon proc /sys/kernel/dmesg_restrict u:object_r:proc_security:s0
+genfscon proc /sys/kernel/hotplug u:object_r:usermodehelper:s0
+genfscon proc /sys/kernel/kptr_restrict u:object_r:proc_security:s0
+genfscon proc /sys/kernel/modprobe u:object_r:usermodehelper:s0
+genfscon proc /sys/kernel/modules_disabled u:object_r:proc_security:s0
+genfscon proc /sys/kernel/poweroff_cmd u:object_r:usermodehelper:s0
+genfscon proc /sys/kernel/randomize_va_space u:object_r:proc_security:s0
+genfscon proc /sys/kernel/usermodehelper u:object_r:usermodehelper:s0
+genfscon proc /sys/net u:object_r:proc_net:s0
+genfscon proc /sys/vm/mmap_min_addr u:object_r:proc_security:s0
+# selinuxfs booleans can be individually labeled.
+genfscon selinuxfs / u:object_r:selinuxfs:s0
+genfscon cgroup / u:object_r:cgroup:s0
+# sysfs labels can be set by userspace.
+genfscon sysfs / u:object_r:sysfs:s0
+genfscon inotifyfs / u:object_r:inotify:s0
+genfscon vfat / u:object_r:sdcard_external:s0
+genfscon debugfs / u:object_r:debugfs:s0
+genfscon fuse / u:object_r:sdcard_internal:s0
+#line 1 "external/sepolicy/port_contexts"
+# portcon statements go here, e.g.
+# portcon tcp 80 u:object_r:http_port:s0
+
diff --git a/tools/selinux/src/gen_SELinux_CTS.py b/tools/selinux/src/gen_SELinux_CTS.py
new file mode 100755
index 0000000..85d49a8
--- /dev/null
+++ b/tools/selinux/src/gen_SELinux_CTS.py
@@ -0,0 +1,58 @@
+#!/usr/bin/python
+# genCheckAccessCTS.py - takes an input SELinux policy.conf file and generates
+# an XML file based on the allow and neverallow rules.  The file contains rules,
+# which are created by expanding the SELinux rule notation into the individual
+# components which a checkAccess() check, that a policy manager would have to
+# perform, needs.
+#
+# This test does not work with all valid SELinux policy.conf files.  It is meant
+# to simply use a given AOSP generated policy.conf file to create sets
+# representing the policy's types, attributes, classes and permissions, which
+# are used to expand the allow and neverallow rules found.  For a full parser
+# and compiler of SELinux, see external/checkpolicy.
+# @dcashman
+
+import pdb
+import re
+import sys
+from xml.etree.ElementTree import Element, SubElement, tostring
+from xml.dom import minidom
+
+import SELinux_CTS
+from SELinux_CTS import SELinuxPolicy
+
+usage = "Usage: ./gen_SELinux_CTS.py input_policy_file output_xml_avc_rules_file neverallow_only=[t/f]"
+
+if __name__ == "__main__":
+    # check usage
+    if len(sys.argv) != 4:
+        print usage
+        exit()
+    input_file = sys.argv[1]
+    output_file = sys.argv[2]
+    neverallow_only = (sys.argv[3] == "neverallow_only=t")
+    policy = SELinuxPolicy()
+    policy.from_file_name(input_file) #load data from file
+
+    # expand rules into 4-tuples for SELinux.h checkAccess() check
+    xml_root = Element('SELinux_AVC_Rules')
+    if not neverallow_only:
+        count = 1
+        for a in policy.allow_rules:
+            expanded_xml = SELinux_CTS.expand_avc_rule_to_xml(policy, a, str(count), 'allow')
+            if len(expanded_xml):
+                xml_root.append(expanded_xml)
+                count += 1
+    count = 1
+    for n in policy.neverallow_rules:
+        expanded_xml = SELinux_CTS.expand_avc_rule_to_xml(policy, n, str(count), 'neverallow')
+        if len(expanded_xml):
+            xml_root.append(expanded_xml)
+            count += 1
+
+    #print out the xml file
+    s = tostring(xml_root)
+    s_parsed = minidom.parseString(s)
+    output = s_parsed.toprettyxml(indent="    ")
+    with open(output_file, 'w') as out_file:
+        out_file.write(output)
diff --git a/tools/selinux/test/policy_clean_test.conf b/tools/selinux/test/policy_clean_test.conf
new file mode 100644
index 0000000..074a63b
--- /dev/null
+++ b/tools/selinux/test/policy_clean_test.conf
@@ -0,0 +1,2230 @@
+#line 1 "external/sepolicy/security_classes"
+# FLASK
+
+#
+# Define the security object classes
+#
+
+# Classes marked as userspace are classes
+# for userspace object managers
+
+class capability
+
+# file-related classes
+class file
+
+#
+# Define a common prefix for file access vectors.
+#
+
+common file
+{
+	ioctl
+	read
+	write
+	create
+	getattr
+	setattr
+	lock
+	relabelfrom
+	relabelto
+	append
+	unlink
+	link
+	rename
+	execute
+	swapon
+	quotaon
+	mounton
+}
+
+class file
+inherits file
+{
+	execute_no_trans
+	entrypoint
+	execmod
+	open
+	audit_access
+}
+
+class capability
+{
+	# The capabilities are defined in include/linux/capability.h
+	# Capabilities >= 32 are defined in the capability2 class.
+	# Care should be taken to ensure that these are consistent with
+	# those definitions. (Order matters)
+
+	chown
+	dac_override
+	dac_read_search
+	fowner
+	fsetid
+	kill
+	setgid
+	setuid
+	setpcap
+	linux_immutable
+	net_bind_service
+	net_broadcast
+	net_admin
+	net_raw
+	ipc_lock
+	ipc_owner
+	sys_module
+	sys_rawio
+	sys_chroot
+	sys_ptrace
+	sys_pacct
+	sys_admin
+	sys_boot
+	sys_nice
+	sys_resource
+	sys_time
+	sys_tty_config
+	mknod
+	lease
+	audit_write
+	audit_control
+	setfcap
+}
+
+########################################
+#
+# Basic level names for system low and high
+#
+
+
+#line 1 "external/sepolicy/mls"
+#########################################
+# MLS declarations
+#
+
+# Generate the desired number of sensitivities and categories.
+
+#line 6
+# Each sensitivity has a name and zero or more aliases.
+#line 6
+sensitivity s0;
+#line 6
+
+#line 6
+
+#line 6
+# Define the ordering of the sensitivity levels (least to greatest)
+#line 6
+dominance { s0  }
+#line 6
+
+category c0;
+#line 7
+category c1;
+#line 7
+category c2;
+#line 7
+category c3;
+#line 7
+category c4;
+#line 7
+category c5;
+#line 7
+category c6;
+#line 7
+category c7;
+#line 7
+category c8;
+#line 7
+category c9;
+#line 7
+category c10;
+#line 7
+category c11;
+#line 7
+category c12;
+#line 7
+category c13;
+#line 7
+category c14;
+#line 7
+category c15;
+#line 7
+category c16;
+#line 7
+category c17;
+#line 7
+category c18;
+#line 7
+category c19;
+#line 7
+category c20;
+#line 7
+category c21;
+#line 7
+category c22;
+#line 7
+category c23;
+#line 7
+category c24;
+#line 7
+category c25;
+#line 7
+category c26;
+#line 7
+category c27;
+#line 7
+category c28;
+#line 7
+category c29;
+#line 7
+category c30;
+#line 7
+category c31;
+#line 7
+category c32;
+#line 7
+category c33;
+#line 7
+category c34;
+#line 7
+category c35;
+#line 7
+category c36;
+#line 7
+category c37;
+#line 7
+category c38;
+#line 7
+category c39;
+#line 7
+category c40;
+#line 7
+category c41;
+#line 7
+category c42;
+#line 7
+category c43;
+#line 7
+category c44;
+#line 7
+category c45;
+#line 7
+category c46;
+#line 7
+category c47;
+#line 7
+category c48;
+#line 7
+category c49;
+#line 7
+category c50;
+#line 7
+category c51;
+#line 7
+category c52;
+#line 7
+category c53;
+#line 7
+category c54;
+#line 7
+category c55;
+#line 7
+category c56;
+#line 7
+category c57;
+#line 7
+category c58;
+#line 7
+category c59;
+#line 7
+category c60;
+#line 7
+category c61;
+#line 7
+category c62;
+#line 7
+category c63;
+#line 7
+category c64;
+#line 7
+category c65;
+#line 7
+category c66;
+#line 7
+category c67;
+#line 7
+category c68;
+#line 7
+category c69;
+#line 7
+category c70;
+#line 7
+category c71;
+#line 7
+category c72;
+#line 7
+category c73;
+#line 7
+category c74;
+#line 7
+category c75;
+#line 7
+category c76;
+#line 7
+category c77;
+#line 7
+category c78;
+#line 7
+category c79;
+#line 7
+category c80;
+#line 7
+category c81;
+#line 7
+category c82;
+#line 7
+category c83;
+#line 7
+category c84;
+#line 7
+category c85;
+#line 7
+category c86;
+#line 7
+category c87;
+#line 7
+category c88;
+#line 7
+category c89;
+#line 7
+category c90;
+#line 7
+category c91;
+#line 7
+category c92;
+#line 7
+category c93;
+#line 7
+category c94;
+#line 7
+category c95;
+#line 7
+category c96;
+#line 7
+category c97;
+#line 7
+category c98;
+#line 7
+category c99;
+#line 7
+category c100;
+#line 7
+category c101;
+#line 7
+category c102;
+#line 7
+category c103;
+#line 7
+category c104;
+#line 7
+category c105;
+#line 7
+category c106;
+#line 7
+category c107;
+#line 7
+category c108;
+#line 7
+category c109;
+#line 7
+category c110;
+#line 7
+category c111;
+#line 7
+category c112;
+#line 7
+category c113;
+#line 7
+category c114;
+#line 7
+category c115;
+#line 7
+category c116;
+#line 7
+category c117;
+#line 7
+category c118;
+#line 7
+category c119;
+#line 7
+category c120;
+#line 7
+category c121;
+#line 7
+category c122;
+#line 7
+category c123;
+#line 7
+category c124;
+#line 7
+category c125;
+#line 7
+category c126;
+#line 7
+category c127;
+#line 7
+category c128;
+#line 7
+category c129;
+#line 7
+category c130;
+#line 7
+category c131;
+#line 7
+category c132;
+#line 7
+category c133;
+#line 7
+category c134;
+#line 7
+category c135;
+#line 7
+category c136;
+#line 7
+category c137;
+#line 7
+category c138;
+#line 7
+category c139;
+#line 7
+category c140;
+#line 7
+category c141;
+#line 7
+category c142;
+#line 7
+category c143;
+#line 7
+category c144;
+#line 7
+category c145;
+#line 7
+category c146;
+#line 7
+category c147;
+#line 7
+category c148;
+#line 7
+category c149;
+#line 7
+category c150;
+#line 7
+category c151;
+#line 7
+category c152;
+#line 7
+category c153;
+#line 7
+category c154;
+#line 7
+category c155;
+#line 7
+category c156;
+#line 7
+category c157;
+#line 7
+category c158;
+#line 7
+category c159;
+#line 7
+category c160;
+#line 7
+category c161;
+#line 7
+category c162;
+#line 7
+category c163;
+#line 7
+category c164;
+#line 7
+category c165;
+#line 7
+category c166;
+#line 7
+category c167;
+#line 7
+category c168;
+#line 7
+category c169;
+#line 7
+category c170;
+#line 7
+category c171;
+#line 7
+category c172;
+#line 7
+category c173;
+#line 7
+category c174;
+#line 7
+category c175;
+#line 7
+category c176;
+#line 7
+category c177;
+#line 7
+category c178;
+#line 7
+category c179;
+#line 7
+category c180;
+#line 7
+category c181;
+#line 7
+category c182;
+#line 7
+category c183;
+#line 7
+category c184;
+#line 7
+category c185;
+#line 7
+category c186;
+#line 7
+category c187;
+#line 7
+category c188;
+#line 7
+category c189;
+#line 7
+category c190;
+#line 7
+category c191;
+#line 7
+category c192;
+#line 7
+category c193;
+#line 7
+category c194;
+#line 7
+category c195;
+#line 7
+category c196;
+#line 7
+category c197;
+#line 7
+category c198;
+#line 7
+category c199;
+#line 7
+category c200;
+#line 7
+category c201;
+#line 7
+category c202;
+#line 7
+category c203;
+#line 7
+category c204;
+#line 7
+category c205;
+#line 7
+category c206;
+#line 7
+category c207;
+#line 7
+category c208;
+#line 7
+category c209;
+#line 7
+category c210;
+#line 7
+category c211;
+#line 7
+category c212;
+#line 7
+category c213;
+#line 7
+category c214;
+#line 7
+category c215;
+#line 7
+category c216;
+#line 7
+category c217;
+#line 7
+category c218;
+#line 7
+category c219;
+#line 7
+category c220;
+#line 7
+category c221;
+#line 7
+category c222;
+#line 7
+category c223;
+#line 7
+category c224;
+#line 7
+category c225;
+#line 7
+category c226;
+#line 7
+category c227;
+#line 7
+category c228;
+#line 7
+category c229;
+#line 7
+category c230;
+#line 7
+category c231;
+#line 7
+category c232;
+#line 7
+category c233;
+#line 7
+category c234;
+#line 7
+category c235;
+#line 7
+category c236;
+#line 7
+category c237;
+#line 7
+category c238;
+#line 7
+category c239;
+#line 7
+category c240;
+#line 7
+category c241;
+#line 7
+category c242;
+#line 7
+category c243;
+#line 7
+category c244;
+#line 7
+category c245;
+#line 7
+category c246;
+#line 7
+category c247;
+#line 7
+category c248;
+#line 7
+category c249;
+#line 7
+category c250;
+#line 7
+category c251;
+#line 7
+category c252;
+#line 7
+category c253;
+#line 7
+category c254;
+#line 7
+category c255;
+#line 7
+category c256;
+#line 7
+category c257;
+#line 7
+category c258;
+#line 7
+category c259;
+#line 7
+category c260;
+#line 7
+category c261;
+#line 7
+category c262;
+#line 7
+category c263;
+#line 7
+category c264;
+#line 7
+category c265;
+#line 7
+category c266;
+#line 7
+category c267;
+#line 7
+category c268;
+#line 7
+category c269;
+#line 7
+category c270;
+#line 7
+category c271;
+#line 7
+category c272;
+#line 7
+category c273;
+#line 7
+category c274;
+#line 7
+category c275;
+#line 7
+category c276;
+#line 7
+category c277;
+#line 7
+category c278;
+#line 7
+category c279;
+#line 7
+category c280;
+#line 7
+category c281;
+#line 7
+category c282;
+#line 7
+category c283;
+#line 7
+category c284;
+#line 7
+category c285;
+#line 7
+category c286;
+#line 7
+category c287;
+#line 7
+category c288;
+#line 7
+category c289;
+#line 7
+category c290;
+#line 7
+category c291;
+#line 7
+category c292;
+#line 7
+category c293;
+#line 7
+category c294;
+#line 7
+category c295;
+#line 7
+category c296;
+#line 7
+category c297;
+#line 7
+category c298;
+#line 7
+category c299;
+#line 7
+category c300;
+#line 7
+category c301;
+#line 7
+category c302;
+#line 7
+category c303;
+#line 7
+category c304;
+#line 7
+category c305;
+#line 7
+category c306;
+#line 7
+category c307;
+#line 7
+category c308;
+#line 7
+category c309;
+#line 7
+category c310;
+#line 7
+category c311;
+#line 7
+category c312;
+#line 7
+category c313;
+#line 7
+category c314;
+#line 7
+category c315;
+#line 7
+category c316;
+#line 7
+category c317;
+#line 7
+category c318;
+#line 7
+category c319;
+#line 7
+category c320;
+#line 7
+category c321;
+#line 7
+category c322;
+#line 7
+category c323;
+#line 7
+category c324;
+#line 7
+category c325;
+#line 7
+category c326;
+#line 7
+category c327;
+#line 7
+category c328;
+#line 7
+category c329;
+#line 7
+category c330;
+#line 7
+category c331;
+#line 7
+category c332;
+#line 7
+category c333;
+#line 7
+category c334;
+#line 7
+category c335;
+#line 7
+category c336;
+#line 7
+category c337;
+#line 7
+category c338;
+#line 7
+category c339;
+#line 7
+category c340;
+#line 7
+category c341;
+#line 7
+category c342;
+#line 7
+category c343;
+#line 7
+category c344;
+#line 7
+category c345;
+#line 7
+category c346;
+#line 7
+category c347;
+#line 7
+category c348;
+#line 7
+category c349;
+#line 7
+category c350;
+#line 7
+category c351;
+#line 7
+category c352;
+#line 7
+category c353;
+#line 7
+category c354;
+#line 7
+category c355;
+#line 7
+category c356;
+#line 7
+category c357;
+#line 7
+category c358;
+#line 7
+category c359;
+#line 7
+category c360;
+#line 7
+category c361;
+#line 7
+category c362;
+#line 7
+category c363;
+#line 7
+category c364;
+#line 7
+category c365;
+#line 7
+category c366;
+#line 7
+category c367;
+#line 7
+category c368;
+#line 7
+category c369;
+#line 7
+category c370;
+#line 7
+category c371;
+#line 7
+category c372;
+#line 7
+category c373;
+#line 7
+category c374;
+#line 7
+category c375;
+#line 7
+category c376;
+#line 7
+category c377;
+#line 7
+category c378;
+#line 7
+category c379;
+#line 7
+category c380;
+#line 7
+category c381;
+#line 7
+category c382;
+#line 7
+category c383;
+#line 7
+category c384;
+#line 7
+category c385;
+#line 7
+category c386;
+#line 7
+category c387;
+#line 7
+category c388;
+#line 7
+category c389;
+#line 7
+category c390;
+#line 7
+category c391;
+#line 7
+category c392;
+#line 7
+category c393;
+#line 7
+category c394;
+#line 7
+category c395;
+#line 7
+category c396;
+#line 7
+category c397;
+#line 7
+category c398;
+#line 7
+category c399;
+#line 7
+category c400;
+#line 7
+category c401;
+#line 7
+category c402;
+#line 7
+category c403;
+#line 7
+category c404;
+#line 7
+category c405;
+#line 7
+category c406;
+#line 7
+category c407;
+#line 7
+category c408;
+#line 7
+category c409;
+#line 7
+category c410;
+#line 7
+category c411;
+#line 7
+category c412;
+#line 7
+category c413;
+#line 7
+category c414;
+#line 7
+category c415;
+#line 7
+category c416;
+#line 7
+category c417;
+#line 7
+category c418;
+#line 7
+category c419;
+#line 7
+category c420;
+#line 7
+category c421;
+#line 7
+category c422;
+#line 7
+category c423;
+#line 7
+category c424;
+#line 7
+category c425;
+#line 7
+category c426;
+#line 7
+category c427;
+#line 7
+category c428;
+#line 7
+category c429;
+#line 7
+category c430;
+#line 7
+category c431;
+#line 7
+category c432;
+#line 7
+category c433;
+#line 7
+category c434;
+#line 7
+category c435;
+#line 7
+category c436;
+#line 7
+category c437;
+#line 7
+category c438;
+#line 7
+category c439;
+#line 7
+category c440;
+#line 7
+category c441;
+#line 7
+category c442;
+#line 7
+category c443;
+#line 7
+category c444;
+#line 7
+category c445;
+#line 7
+category c446;
+#line 7
+category c447;
+#line 7
+category c448;
+#line 7
+category c449;
+#line 7
+category c450;
+#line 7
+category c451;
+#line 7
+category c452;
+#line 7
+category c453;
+#line 7
+category c454;
+#line 7
+category c455;
+#line 7
+category c456;
+#line 7
+category c457;
+#line 7
+category c458;
+#line 7
+category c459;
+#line 7
+category c460;
+#line 7
+category c461;
+#line 7
+category c462;
+#line 7
+category c463;
+#line 7
+category c464;
+#line 7
+category c465;
+#line 7
+category c466;
+#line 7
+category c467;
+#line 7
+category c468;
+#line 7
+category c469;
+#line 7
+category c470;
+#line 7
+category c471;
+#line 7
+category c472;
+#line 7
+category c473;
+#line 7
+category c474;
+#line 7
+category c475;
+#line 7
+category c476;
+#line 7
+category c477;
+#line 7
+category c478;
+#line 7
+category c479;
+#line 7
+category c480;
+#line 7
+category c481;
+#line 7
+category c482;
+#line 7
+category c483;
+#line 7
+category c484;
+#line 7
+category c485;
+#line 7
+category c486;
+#line 7
+category c487;
+#line 7
+category c488;
+#line 7
+category c489;
+#line 7
+category c490;
+#line 7
+category c491;
+#line 7
+category c492;
+#line 7
+category c493;
+#line 7
+category c494;
+#line 7
+category c495;
+#line 7
+category c496;
+#line 7
+category c497;
+#line 7
+category c498;
+#line 7
+category c499;
+#line 7
+category c500;
+#line 7
+category c501;
+#line 7
+category c502;
+#line 7
+category c503;
+#line 7
+category c504;
+#line 7
+category c505;
+#line 7
+category c506;
+#line 7
+category c507;
+#line 7
+category c508;
+#line 7
+category c509;
+#line 7
+category c510;
+#line 7
+category c511;
+#line 7
+category c512;
+#line 7
+category c513;
+#line 7
+category c514;
+#line 7
+category c515;
+#line 7
+category c516;
+#line 7
+category c517;
+#line 7
+category c518;
+#line 7
+category c519;
+#line 7
+category c520;
+#line 7
+category c521;
+#line 7
+category c522;
+#line 7
+category c523;
+#line 7
+category c524;
+#line 7
+category c525;
+#line 7
+category c526;
+#line 7
+category c527;
+#line 7
+category c528;
+#line 7
+category c529;
+#line 7
+category c530;
+#line 7
+category c531;
+#line 7
+category c532;
+#line 7
+category c533;
+#line 7
+category c534;
+#line 7
+category c535;
+#line 7
+category c536;
+#line 7
+category c537;
+#line 7
+category c538;
+#line 7
+category c539;
+#line 7
+category c540;
+#line 7
+category c541;
+#line 7
+category c542;
+#line 7
+category c543;
+#line 7
+category c544;
+#line 7
+category c545;
+#line 7
+category c546;
+#line 7
+category c547;
+#line 7
+category c548;
+#line 7
+category c549;
+#line 7
+category c550;
+#line 7
+category c551;
+#line 7
+category c552;
+#line 7
+category c553;
+#line 7
+category c554;
+#line 7
+category c555;
+#line 7
+category c556;
+#line 7
+category c557;
+#line 7
+category c558;
+#line 7
+category c559;
+#line 7
+category c560;
+#line 7
+category c561;
+#line 7
+category c562;
+#line 7
+category c563;
+#line 7
+category c564;
+#line 7
+category c565;
+#line 7
+category c566;
+#line 7
+category c567;
+#line 7
+category c568;
+#line 7
+category c569;
+#line 7
+category c570;
+#line 7
+category c571;
+#line 7
+category c572;
+#line 7
+category c573;
+#line 7
+category c574;
+#line 7
+category c575;
+#line 7
+category c576;
+#line 7
+category c577;
+#line 7
+category c578;
+#line 7
+category c579;
+#line 7
+category c580;
+#line 7
+category c581;
+#line 7
+category c582;
+#line 7
+category c583;
+#line 7
+category c584;
+#line 7
+category c585;
+#line 7
+category c586;
+#line 7
+category c587;
+#line 7
+category c588;
+#line 7
+category c589;
+#line 7
+category c590;
+#line 7
+category c591;
+#line 7
+category c592;
+#line 7
+category c593;
+#line 7
+category c594;
+#line 7
+category c595;
+#line 7
+category c596;
+#line 7
+category c597;
+#line 7
+category c598;
+#line 7
+category c599;
+#line 7
+category c600;
+#line 7
+category c601;
+#line 7
+category c602;
+#line 7
+category c603;
+#line 7
+category c604;
+#line 7
+category c605;
+#line 7
+category c606;
+#line 7
+category c607;
+#line 7
+category c608;
+#line 7
+category c609;
+#line 7
+category c610;
+#line 7
+category c611;
+#line 7
+category c612;
+#line 7
+category c613;
+#line 7
+category c614;
+#line 7
+category c615;
+#line 7
+category c616;
+#line 7
+category c617;
+#line 7
+category c618;
+#line 7
+category c619;
+#line 7
+category c620;
+#line 7
+category c621;
+#line 7
+category c622;
+#line 7
+category c623;
+#line 7
+category c624;
+#line 7
+category c625;
+#line 7
+category c626;
+#line 7
+category c627;
+#line 7
+category c628;
+#line 7
+category c629;
+#line 7
+category c630;
+#line 7
+category c631;
+#line 7
+category c632;
+#line 7
+category c633;
+#line 7
+category c634;
+#line 7
+category c635;
+#line 7
+category c636;
+#line 7
+category c637;
+#line 7
+category c638;
+#line 7
+category c639;
+#line 7
+category c640;
+#line 7
+category c641;
+#line 7
+category c642;
+#line 7
+category c643;
+#line 7
+category c644;
+#line 7
+category c645;
+#line 7
+category c646;
+#line 7
+category c647;
+#line 7
+category c648;
+#line 7
+category c649;
+#line 7
+category c650;
+#line 7
+category c651;
+#line 7
+category c652;
+#line 7
+category c653;
+#line 7
+category c654;
+#line 7
+category c655;
+#line 7
+category c656;
+#line 7
+category c657;
+#line 7
+category c658;
+#line 7
+category c659;
+#line 7
+category c660;
+#line 7
+category c661;
+#line 7
+category c662;
+#line 7
+category c663;
+#line 7
+category c664;
+#line 7
+category c665;
+#line 7
+category c666;
+#line 7
+category c667;
+#line 7
+category c668;
+#line 7
+category c669;
+#line 7
+category c670;
+#line 7
+category c671;
+#line 7
+category c672;
+#line 7
+category c673;
+#line 7
+category c674;
+#line 7
+category c675;
+#line 7
+category c676;
+#line 7
+category c677;
+#line 7
+category c678;
+#line 7
+category c679;
+#line 7
+category c680;
+#line 7
+category c681;
+#line 7
+category c682;
+#line 7
+category c683;
+#line 7
+category c684;
+#line 7
+category c685;
+#line 7
+category c686;
+#line 7
+category c687;
+#line 7
+category c688;
+#line 7
+category c689;
+#line 7
+category c690;
+#line 7
+category c691;
+#line 7
+category c692;
+#line 7
+category c693;
+#line 7
+category c694;
+#line 7
+category c695;
+#line 7
+category c696;
+#line 7
+category c697;
+#line 7
+category c698;
+#line 7
+category c699;
+#line 7
+category c700;
+#line 7
+category c701;
+#line 7
+category c702;
+#line 7
+category c703;
+#line 7
+category c704;
+#line 7
+category c705;
+#line 7
+category c706;
+#line 7
+category c707;
+#line 7
+category c708;
+#line 7
+category c709;
+#line 7
+category c710;
+#line 7
+category c711;
+#line 7
+category c712;
+#line 7
+category c713;
+#line 7
+category c714;
+#line 7
+category c715;
+#line 7
+category c716;
+#line 7
+category c717;
+#line 7
+category c718;
+#line 7
+category c719;
+#line 7
+category c720;
+#line 7
+category c721;
+#line 7
+category c722;
+#line 7
+category c723;
+#line 7
+category c724;
+#line 7
+category c725;
+#line 7
+category c726;
+#line 7
+category c727;
+#line 7
+category c728;
+#line 7
+category c729;
+#line 7
+category c730;
+#line 7
+category c731;
+#line 7
+category c732;
+#line 7
+category c733;
+#line 7
+category c734;
+#line 7
+category c735;
+#line 7
+category c736;
+#line 7
+category c737;
+#line 7
+category c738;
+#line 7
+category c739;
+#line 7
+category c740;
+#line 7
+category c741;
+#line 7
+category c742;
+#line 7
+category c743;
+#line 7
+category c744;
+#line 7
+category c745;
+#line 7
+category c746;
+#line 7
+category c747;
+#line 7
+category c748;
+#line 7
+category c749;
+#line 7
+category c750;
+#line 7
+category c751;
+#line 7
+category c752;
+#line 7
+category c753;
+#line 7
+category c754;
+#line 7
+category c755;
+#line 7
+category c756;
+#line 7
+category c757;
+#line 7
+category c758;
+#line 7
+category c759;
+#line 7
+category c760;
+#line 7
+category c761;
+#line 7
+category c762;
+#line 7
+category c763;
+#line 7
+category c764;
+#line 7
+category c765;
+#line 7
+category c766;
+#line 7
+category c767;
+#line 7
+category c768;
+#line 7
+category c769;
+#line 7
+category c770;
+#line 7
+category c771;
+#line 7
+category c772;
+#line 7
+category c773;
+#line 7
+category c774;
+#line 7
+category c775;
+#line 7
+category c776;
+#line 7
+category c777;
+#line 7
+category c778;
+#line 7
+category c779;
+#line 7
+category c780;
+#line 7
+category c781;
+#line 7
+category c782;
+#line 7
+category c783;
+#line 7
+category c784;
+#line 7
+category c785;
+#line 7
+category c786;
+#line 7
+category c787;
+#line 7
+category c788;
+#line 7
+category c789;
+#line 7
+category c790;
+#line 7
+category c791;
+#line 7
+category c792;
+#line 7
+category c793;
+#line 7
+category c794;
+#line 7
+category c795;
+#line 7
+category c796;
+#line 7
+category c797;
+#line 7
+category c798;
+#line 7
+category c799;
+#line 7
+category c800;
+#line 7
+category c801;
+#line 7
+category c802;
+#line 7
+category c803;
+#line 7
+category c804;
+#line 7
+category c805;
+#line 7
+category c806;
+#line 7
+category c807;
+#line 7
+category c808;
+#line 7
+category c809;
+#line 7
+category c810;
+#line 7
+category c811;
+#line 7
+category c812;
+#line 7
+category c813;
+#line 7
+category c814;
+#line 7
+category c815;
+#line 7
+category c816;
+#line 7
+category c817;
+#line 7
+category c818;
+#line 7
+category c819;
+#line 7
+category c820;
+#line 7
+category c821;
+#line 7
+category c822;
+#line 7
+category c823;
+#line 7
+category c824;
+#line 7
+category c825;
+#line 7
+category c826;
+#line 7
+category c827;
+#line 7
+category c828;
+#line 7
+category c829;
+#line 7
+category c830;
+#line 7
+category c831;
+#line 7
+category c832;
+#line 7
+category c833;
+#line 7
+category c834;
+#line 7
+category c835;
+#line 7
+category c836;
+#line 7
+category c837;
+#line 7
+category c838;
+#line 7
+category c839;
+#line 7
+category c840;
+#line 7
+category c841;
+#line 7
+category c842;
+#line 7
+category c843;
+#line 7
+category c844;
+#line 7
+category c845;
+#line 7
+category c846;
+#line 7
+category c847;
+#line 7
+category c848;
+#line 7
+category c849;
+#line 7
+category c850;
+#line 7
+category c851;
+#line 7
+category c852;
+#line 7
+category c853;
+#line 7
+category c854;
+#line 7
+category c855;
+#line 7
+category c856;
+#line 7
+category c857;
+#line 7
+category c858;
+#line 7
+category c859;
+#line 7
+category c860;
+#line 7
+category c861;
+#line 7
+category c862;
+#line 7
+category c863;
+#line 7
+category c864;
+#line 7
+category c865;
+#line 7
+category c866;
+#line 7
+category c867;
+#line 7
+category c868;
+#line 7
+category c869;
+#line 7
+category c870;
+#line 7
+category c871;
+#line 7
+category c872;
+#line 7
+category c873;
+#line 7
+category c874;
+#line 7
+category c875;
+#line 7
+category c876;
+#line 7
+category c877;
+#line 7
+category c878;
+#line 7
+category c879;
+#line 7
+category c880;
+#line 7
+category c881;
+#line 7
+category c882;
+#line 7
+category c883;
+#line 7
+category c884;
+#line 7
+category c885;
+#line 7
+category c886;
+#line 7
+category c887;
+#line 7
+category c888;
+#line 7
+category c889;
+#line 7
+category c890;
+#line 7
+category c891;
+#line 7
+category c892;
+#line 7
+category c893;
+#line 7
+category c894;
+#line 7
+category c895;
+#line 7
+category c896;
+#line 7
+category c897;
+#line 7
+category c898;
+#line 7
+category c899;
+#line 7
+category c900;
+#line 7
+category c901;
+#line 7
+category c902;
+#line 7
+category c903;
+#line 7
+category c904;
+#line 7
+category c905;
+#line 7
+category c906;
+#line 7
+category c907;
+#line 7
+category c908;
+#line 7
+category c909;
+#line 7
+category c910;
+#line 7
+category c911;
+#line 7
+category c912;
+#line 7
+category c913;
+#line 7
+category c914;
+#line 7
+category c915;
+#line 7
+category c916;
+#line 7
+category c917;
+#line 7
+category c918;
+#line 7
+category c919;
+#line 7
+category c920;
+#line 7
+category c921;
+#line 7
+category c922;
+#line 7
+category c923;
+#line 7
+category c924;
+#line 7
+category c925;
+#line 7
+category c926;
+#line 7
+category c927;
+#line 7
+category c928;
+#line 7
+category c929;
+#line 7
+category c930;
+#line 7
+category c931;
+#line 7
+category c932;
+#line 7
+category c933;
+#line 7
+category c934;
+#line 7
+category c935;
+#line 7
+category c936;
+#line 7
+category c937;
+#line 7
+category c938;
+#line 7
+category c939;
+#line 7
+category c940;
+#line 7
+category c941;
+#line 7
+category c942;
+#line 7
+category c943;
+#line 7
+category c944;
+#line 7
+category c945;
+#line 7
+category c946;
+#line 7
+category c947;
+#line 7
+category c948;
+#line 7
+category c949;
+#line 7
+category c950;
+#line 7
+category c951;
+#line 7
+category c952;
+#line 7
+category c953;
+#line 7
+category c954;
+#line 7
+category c955;
+#line 7
+category c956;
+#line 7
+category c957;
+#line 7
+category c958;
+#line 7
+category c959;
+#line 7
+category c960;
+#line 7
+category c961;
+#line 7
+category c962;
+#line 7
+category c963;
+#line 7
+category c964;
+#line 7
+category c965;
+#line 7
+category c966;
+#line 7
+category c967;
+#line 7
+category c968;
+#line 7
+category c969;
+#line 7
+category c970;
+#line 7
+category c971;
+#line 7
+category c972;
+#line 7
+category c973;
+#line 7
+category c974;
+#line 7
+category c975;
+#line 7
+category c976;
+#line 7
+category c977;
+#line 7
+category c978;
+#line 7
+category c979;
+#line 7
+category c980;
+#line 7
+category c981;
+#line 7
+category c982;
+#line 7
+category c983;
+#line 7
+category c984;
+#line 7
+category c985;
+#line 7
+category c986;
+#line 7
+category c987;
+#line 7
+category c988;
+#line 7
+category c989;
+#line 7
+category c990;
+#line 7
+category c991;
+#line 7
+category c992;
+#line 7
+category c993;
+#line 7
+category c994;
+#line 7
+category c995;
+#line 7
+category c996;
+#line 7
+category c997;
+#line 7
+category c998;
+#line 7
+category c999;
+#line 7
+category c1000;
+#line 7
+category c1001;
+#line 7
+category c1002;
+#line 7
+category c1003;
+#line 7
+category c1004;
+#line 7
+category c1005;
+#line 7
+category c1006;
+#line 7
+category c1007;
+#line 7
+category c1008;
+#line 7
+category c1009;
+#line 7
+category c1010;
+#line 7
+category c1011;
+#line 7
+category c1012;
+#line 7
+category c1013;
+#line 7
+category c1014;
+#line 7
+category c1015;
+#line 7
+category c1016;
+#line 7
+category c1017;
+#line 7
+category c1018;
+#line 7
+category c1019;
+#line 7
+category c1020;
+#line 7
+category c1021;
+#line 7
+category c1022;
+#line 7
+category c1023;
+#line 7
+
+
+# Generate level definitions for each sensitivity and category.
+level s0:c0.c1023;
+#line 10
+
+######################################
+# Attribute declarations
+#
+
+# All types used for processes.
+attribute domain;
+
+# Domains that are allowed all permissions ("unconfined").
+attribute unconfineddomain;
+
+# All domains used for apps.
+attribute appdomain;
+
+# All types used for files that can exist on a labeled fs.
+# Do not use for pseudo file types.
+attribute file_type;
+
+# All types used for domain entry points.
+attribute exec_type;
+
+#line 1 "external/sepolicy/bluetooth.te"
+# bluetooth subsystem
+type bluetooth, domain;
+permissive bluetooth;
+
+#line 4
+typeattribute bluetooth appdomain;
+
+#line 5
+typeattribute bluetooth unconfineddomain;
+#line 5
+
+#line 1 "external/sepolicy/healthd.te"
+# healthd seclabel is specified in init.rc since
+# it lives in the rootfs and has no unique file type.
+type healthd, domain;
+permissive healthd;
+type healthd_exec, exec_type, file_type;
+
+# New domain is entered by executing the file.
+#line 7
+allow healthd healthd_exec:file { entrypoint read execute };
+
+###
+### Neverallow rules
+###
+### These are things that Android apps should NEVER be able to do
+###
+
+# Superuser capabilities.
+# bluetooth requires net_admin.
+neverallow { appdomain -unconfineddomain -bluetooth } self:capability *;
+
+# Added to make the neverallow rule make sense in a limited environment.
+# Added at the bottom to not throw off file seek numbers in test suite.  
+# This is not a problem, because allow rules are processed after all types
+# are gathered.
+type testTYPE, appdomain, domain;
diff --git a/tools/selinux/test/policy_test.conf b/tools/selinux/test/policy_test.conf
new file mode 100644
index 0000000..d0962cd
--- /dev/null
+++ b/tools/selinux/test/policy_test.conf
@@ -0,0 +1,2244 @@
+#line 1 "external/sepolicy/security_classes"
+# FLASK
+
+#
+# Define the security object classes
+#
+
+# Classes marked as userspace are classes
+# for userspace object managers
+
+class capability
+
+# file-related classes
+class file
+
+#
+# Define a common prefix for file access vectors.
+#
+
+common file
+{
+	ioctl
+	read
+	write
+	create
+	getattr
+	setattr
+	lock
+	relabelfrom
+	relabelto
+	append
+	unlink
+	link
+	rename
+	execute
+	swapon
+	quotaon
+	mounton
+}
+
+class file
+inherits file
+{
+	execute_no_trans
+	entrypoint
+	execmod
+	open
+	audit_access
+}
+
+class capability
+{
+	# The capabilities are defined in include/linux/capability.h
+	# Capabilities >= 32 are defined in the capability2 class.
+	# Care should be taken to ensure that these are consistent with
+	# those definitions. (Order matters)
+
+	chown
+	dac_override
+	dac_read_search
+	fowner
+	fsetid
+	kill
+	setgid
+	setuid
+	setpcap
+	linux_immutable
+	net_bind_service
+	net_broadcast
+	net_admin
+	net_raw
+	ipc_lock
+	ipc_owner
+	sys_module
+	sys_rawio
+	sys_chroot
+	sys_ptrace
+	sys_pacct
+	sys_admin
+	sys_boot
+	sys_nice
+	sys_resource
+	sys_time
+	sys_tty_config
+	mknod
+	lease
+	audit_write
+	audit_control
+	setfcap
+}
+
+########################################
+#
+# Basic level names for system low and high
+#
+
+
+#line 1 "external/sepolicy/mls"
+#########################################
+# MLS declarations
+#
+
+# Generate the desired number of sensitivities and categories.
+
+#line 6
+# Each sensitivity has a name and zero or more aliases.
+#line 6
+sensitivity s0;
+#line 6
+
+#line 6
+
+#line 6
+# Define the ordering of the sensitivity levels (least to greatest)
+#line 6
+dominance { s0  }
+#line 6
+
+category c0;
+#line 7
+category c1;
+#line 7
+category c2;
+#line 7
+category c3;
+#line 7
+category c4;
+#line 7
+category c5;
+#line 7
+category c6;
+#line 7
+category c7;
+#line 7
+category c8;
+#line 7
+category c9;
+#line 7
+category c10;
+#line 7
+category c11;
+#line 7
+category c12;
+#line 7
+category c13;
+#line 7
+category c14;
+#line 7
+category c15;
+#line 7
+category c16;
+#line 7
+category c17;
+#line 7
+category c18;
+#line 7
+category c19;
+#line 7
+category c20;
+#line 7
+category c21;
+#line 7
+category c22;
+#line 7
+category c23;
+#line 7
+category c24;
+#line 7
+category c25;
+#line 7
+category c26;
+#line 7
+category c27;
+#line 7
+category c28;
+#line 7
+category c29;
+#line 7
+category c30;
+#line 7
+category c31;
+#line 7
+category c32;
+#line 7
+category c33;
+#line 7
+category c34;
+#line 7
+category c35;
+#line 7
+category c36;
+#line 7
+category c37;
+#line 7
+category c38;
+#line 7
+category c39;
+#line 7
+category c40;
+#line 7
+category c41;
+#line 7
+category c42;
+#line 7
+category c43;
+#line 7
+category c44;
+#line 7
+category c45;
+#line 7
+category c46;
+#line 7
+category c47;
+#line 7
+category c48;
+#line 7
+category c49;
+#line 7
+category c50;
+#line 7
+category c51;
+#line 7
+category c52;
+#line 7
+category c53;
+#line 7
+category c54;
+#line 7
+category c55;
+#line 7
+category c56;
+#line 7
+category c57;
+#line 7
+category c58;
+#line 7
+category c59;
+#line 7
+category c60;
+#line 7
+category c61;
+#line 7
+category c62;
+#line 7
+category c63;
+#line 7
+category c64;
+#line 7
+category c65;
+#line 7
+category c66;
+#line 7
+category c67;
+#line 7
+category c68;
+#line 7
+category c69;
+#line 7
+category c70;
+#line 7
+category c71;
+#line 7
+category c72;
+#line 7
+category c73;
+#line 7
+category c74;
+#line 7
+category c75;
+#line 7
+category c76;
+#line 7
+category c77;
+#line 7
+category c78;
+#line 7
+category c79;
+#line 7
+category c80;
+#line 7
+category c81;
+#line 7
+category c82;
+#line 7
+category c83;
+#line 7
+category c84;
+#line 7
+category c85;
+#line 7
+category c86;
+#line 7
+category c87;
+#line 7
+category c88;
+#line 7
+category c89;
+#line 7
+category c90;
+#line 7
+category c91;
+#line 7
+category c92;
+#line 7
+category c93;
+#line 7
+category c94;
+#line 7
+category c95;
+#line 7
+category c96;
+#line 7
+category c97;
+#line 7
+category c98;
+#line 7
+category c99;
+#line 7
+category c100;
+#line 7
+category c101;
+#line 7
+category c102;
+#line 7
+category c103;
+#line 7
+category c104;
+#line 7
+category c105;
+#line 7
+category c106;
+#line 7
+category c107;
+#line 7
+category c108;
+#line 7
+category c109;
+#line 7
+category c110;
+#line 7
+category c111;
+#line 7
+category c112;
+#line 7
+category c113;
+#line 7
+category c114;
+#line 7
+category c115;
+#line 7
+category c116;
+#line 7
+category c117;
+#line 7
+category c118;
+#line 7
+category c119;
+#line 7
+category c120;
+#line 7
+category c121;
+#line 7
+category c122;
+#line 7
+category c123;
+#line 7
+category c124;
+#line 7
+category c125;
+#line 7
+category c126;
+#line 7
+category c127;
+#line 7
+category c128;
+#line 7
+category c129;
+#line 7
+category c130;
+#line 7
+category c131;
+#line 7
+category c132;
+#line 7
+category c133;
+#line 7
+category c134;
+#line 7
+category c135;
+#line 7
+category c136;
+#line 7
+category c137;
+#line 7
+category c138;
+#line 7
+category c139;
+#line 7
+category c140;
+#line 7
+category c141;
+#line 7
+category c142;
+#line 7
+category c143;
+#line 7
+category c144;
+#line 7
+category c145;
+#line 7
+category c146;
+#line 7
+category c147;
+#line 7
+category c148;
+#line 7
+category c149;
+#line 7
+category c150;
+#line 7
+category c151;
+#line 7
+category c152;
+#line 7
+category c153;
+#line 7
+category c154;
+#line 7
+category c155;
+#line 7
+category c156;
+#line 7
+category c157;
+#line 7
+category c158;
+#line 7
+category c159;
+#line 7
+category c160;
+#line 7
+category c161;
+#line 7
+category c162;
+#line 7
+category c163;
+#line 7
+category c164;
+#line 7
+category c165;
+#line 7
+category c166;
+#line 7
+category c167;
+#line 7
+category c168;
+#line 7
+category c169;
+#line 7
+category c170;
+#line 7
+category c171;
+#line 7
+category c172;
+#line 7
+category c173;
+#line 7
+category c174;
+#line 7
+category c175;
+#line 7
+category c176;
+#line 7
+category c177;
+#line 7
+category c178;
+#line 7
+category c179;
+#line 7
+category c180;
+#line 7
+category c181;
+#line 7
+category c182;
+#line 7
+category c183;
+#line 7
+category c184;
+#line 7
+category c185;
+#line 7
+category c186;
+#line 7
+category c187;
+#line 7
+category c188;
+#line 7
+category c189;
+#line 7
+category c190;
+#line 7
+category c191;
+#line 7
+category c192;
+#line 7
+category c193;
+#line 7
+category c194;
+#line 7
+category c195;
+#line 7
+category c196;
+#line 7
+category c197;
+#line 7
+category c198;
+#line 7
+category c199;
+#line 7
+category c200;
+#line 7
+category c201;
+#line 7
+category c202;
+#line 7
+category c203;
+#line 7
+category c204;
+#line 7
+category c205;
+#line 7
+category c206;
+#line 7
+category c207;
+#line 7
+category c208;
+#line 7
+category c209;
+#line 7
+category c210;
+#line 7
+category c211;
+#line 7
+category c212;
+#line 7
+category c213;
+#line 7
+category c214;
+#line 7
+category c215;
+#line 7
+category c216;
+#line 7
+category c217;
+#line 7
+category c218;
+#line 7
+category c219;
+#line 7
+category c220;
+#line 7
+category c221;
+#line 7
+category c222;
+#line 7
+category c223;
+#line 7
+category c224;
+#line 7
+category c225;
+#line 7
+category c226;
+#line 7
+category c227;
+#line 7
+category c228;
+#line 7
+category c229;
+#line 7
+category c230;
+#line 7
+category c231;
+#line 7
+category c232;
+#line 7
+category c233;
+#line 7
+category c234;
+#line 7
+category c235;
+#line 7
+category c236;
+#line 7
+category c237;
+#line 7
+category c238;
+#line 7
+category c239;
+#line 7
+category c240;
+#line 7
+category c241;
+#line 7
+category c242;
+#line 7
+category c243;
+#line 7
+category c244;
+#line 7
+category c245;
+#line 7
+category c246;
+#line 7
+category c247;
+#line 7
+category c248;
+#line 7
+category c249;
+#line 7
+category c250;
+#line 7
+category c251;
+#line 7
+category c252;
+#line 7
+category c253;
+#line 7
+category c254;
+#line 7
+category c255;
+#line 7
+category c256;
+#line 7
+category c257;
+#line 7
+category c258;
+#line 7
+category c259;
+#line 7
+category c260;
+#line 7
+category c261;
+#line 7
+category c262;
+#line 7
+category c263;
+#line 7
+category c264;
+#line 7
+category c265;
+#line 7
+category c266;
+#line 7
+category c267;
+#line 7
+category c268;
+#line 7
+category c269;
+#line 7
+category c270;
+#line 7
+category c271;
+#line 7
+category c272;
+#line 7
+category c273;
+#line 7
+category c274;
+#line 7
+category c275;
+#line 7
+category c276;
+#line 7
+category c277;
+#line 7
+category c278;
+#line 7
+category c279;
+#line 7
+category c280;
+#line 7
+category c281;
+#line 7
+category c282;
+#line 7
+category c283;
+#line 7
+category c284;
+#line 7
+category c285;
+#line 7
+category c286;
+#line 7
+category c287;
+#line 7
+category c288;
+#line 7
+category c289;
+#line 7
+category c290;
+#line 7
+category c291;
+#line 7
+category c292;
+#line 7
+category c293;
+#line 7
+category c294;
+#line 7
+category c295;
+#line 7
+category c296;
+#line 7
+category c297;
+#line 7
+category c298;
+#line 7
+category c299;
+#line 7
+category c300;
+#line 7
+category c301;
+#line 7
+category c302;
+#line 7
+category c303;
+#line 7
+category c304;
+#line 7
+category c305;
+#line 7
+category c306;
+#line 7
+category c307;
+#line 7
+category c308;
+#line 7
+category c309;
+#line 7
+category c310;
+#line 7
+category c311;
+#line 7
+category c312;
+#line 7
+category c313;
+#line 7
+category c314;
+#line 7
+category c315;
+#line 7
+category c316;
+#line 7
+category c317;
+#line 7
+category c318;
+#line 7
+category c319;
+#line 7
+category c320;
+#line 7
+category c321;
+#line 7
+category c322;
+#line 7
+category c323;
+#line 7
+category c324;
+#line 7
+category c325;
+#line 7
+category c326;
+#line 7
+category c327;
+#line 7
+category c328;
+#line 7
+category c329;
+#line 7
+category c330;
+#line 7
+category c331;
+#line 7
+category c332;
+#line 7
+category c333;
+#line 7
+category c334;
+#line 7
+category c335;
+#line 7
+category c336;
+#line 7
+category c337;
+#line 7
+category c338;
+#line 7
+category c339;
+#line 7
+category c340;
+#line 7
+category c341;
+#line 7
+category c342;
+#line 7
+category c343;
+#line 7
+category c344;
+#line 7
+category c345;
+#line 7
+category c346;
+#line 7
+category c347;
+#line 7
+category c348;
+#line 7
+category c349;
+#line 7
+category c350;
+#line 7
+category c351;
+#line 7
+category c352;
+#line 7
+category c353;
+#line 7
+category c354;
+#line 7
+category c355;
+#line 7
+category c356;
+#line 7
+category c357;
+#line 7
+category c358;
+#line 7
+category c359;
+#line 7
+category c360;
+#line 7
+category c361;
+#line 7
+category c362;
+#line 7
+category c363;
+#line 7
+category c364;
+#line 7
+category c365;
+#line 7
+category c366;
+#line 7
+category c367;
+#line 7
+category c368;
+#line 7
+category c369;
+#line 7
+category c370;
+#line 7
+category c371;
+#line 7
+category c372;
+#line 7
+category c373;
+#line 7
+category c374;
+#line 7
+category c375;
+#line 7
+category c376;
+#line 7
+category c377;
+#line 7
+category c378;
+#line 7
+category c379;
+#line 7
+category c380;
+#line 7
+category c381;
+#line 7
+category c382;
+#line 7
+category c383;
+#line 7
+category c384;
+#line 7
+category c385;
+#line 7
+category c386;
+#line 7
+category c387;
+#line 7
+category c388;
+#line 7
+category c389;
+#line 7
+category c390;
+#line 7
+category c391;
+#line 7
+category c392;
+#line 7
+category c393;
+#line 7
+category c394;
+#line 7
+category c395;
+#line 7
+category c396;
+#line 7
+category c397;
+#line 7
+category c398;
+#line 7
+category c399;
+#line 7
+category c400;
+#line 7
+category c401;
+#line 7
+category c402;
+#line 7
+category c403;
+#line 7
+category c404;
+#line 7
+category c405;
+#line 7
+category c406;
+#line 7
+category c407;
+#line 7
+category c408;
+#line 7
+category c409;
+#line 7
+category c410;
+#line 7
+category c411;
+#line 7
+category c412;
+#line 7
+category c413;
+#line 7
+category c414;
+#line 7
+category c415;
+#line 7
+category c416;
+#line 7
+category c417;
+#line 7
+category c418;
+#line 7
+category c419;
+#line 7
+category c420;
+#line 7
+category c421;
+#line 7
+category c422;
+#line 7
+category c423;
+#line 7
+category c424;
+#line 7
+category c425;
+#line 7
+category c426;
+#line 7
+category c427;
+#line 7
+category c428;
+#line 7
+category c429;
+#line 7
+category c430;
+#line 7
+category c431;
+#line 7
+category c432;
+#line 7
+category c433;
+#line 7
+category c434;
+#line 7
+category c435;
+#line 7
+category c436;
+#line 7
+category c437;
+#line 7
+category c438;
+#line 7
+category c439;
+#line 7
+category c440;
+#line 7
+category c441;
+#line 7
+category c442;
+#line 7
+category c443;
+#line 7
+category c444;
+#line 7
+category c445;
+#line 7
+category c446;
+#line 7
+category c447;
+#line 7
+category c448;
+#line 7
+category c449;
+#line 7
+category c450;
+#line 7
+category c451;
+#line 7
+category c452;
+#line 7
+category c453;
+#line 7
+category c454;
+#line 7
+category c455;
+#line 7
+category c456;
+#line 7
+category c457;
+#line 7
+category c458;
+#line 7
+category c459;
+#line 7
+category c460;
+#line 7
+category c461;
+#line 7
+category c462;
+#line 7
+category c463;
+#line 7
+category c464;
+#line 7
+category c465;
+#line 7
+category c466;
+#line 7
+category c467;
+#line 7
+category c468;
+#line 7
+category c469;
+#line 7
+category c470;
+#line 7
+category c471;
+#line 7
+category c472;
+#line 7
+category c473;
+#line 7
+category c474;
+#line 7
+category c475;
+#line 7
+category c476;
+#line 7
+category c477;
+#line 7
+category c478;
+#line 7
+category c479;
+#line 7
+category c480;
+#line 7
+category c481;
+#line 7
+category c482;
+#line 7
+category c483;
+#line 7
+category c484;
+#line 7
+category c485;
+#line 7
+category c486;
+#line 7
+category c487;
+#line 7
+category c488;
+#line 7
+category c489;
+#line 7
+category c490;
+#line 7
+category c491;
+#line 7
+category c492;
+#line 7
+category c493;
+#line 7
+category c494;
+#line 7
+category c495;
+#line 7
+category c496;
+#line 7
+category c497;
+#line 7
+category c498;
+#line 7
+category c499;
+#line 7
+category c500;
+#line 7
+category c501;
+#line 7
+category c502;
+#line 7
+category c503;
+#line 7
+category c504;
+#line 7
+category c505;
+#line 7
+category c506;
+#line 7
+category c507;
+#line 7
+category c508;
+#line 7
+category c509;
+#line 7
+category c510;
+#line 7
+category c511;
+#line 7
+category c512;
+#line 7
+category c513;
+#line 7
+category c514;
+#line 7
+category c515;
+#line 7
+category c516;
+#line 7
+category c517;
+#line 7
+category c518;
+#line 7
+category c519;
+#line 7
+category c520;
+#line 7
+category c521;
+#line 7
+category c522;
+#line 7
+category c523;
+#line 7
+category c524;
+#line 7
+category c525;
+#line 7
+category c526;
+#line 7
+category c527;
+#line 7
+category c528;
+#line 7
+category c529;
+#line 7
+category c530;
+#line 7
+category c531;
+#line 7
+category c532;
+#line 7
+category c533;
+#line 7
+category c534;
+#line 7
+category c535;
+#line 7
+category c536;
+#line 7
+category c537;
+#line 7
+category c538;
+#line 7
+category c539;
+#line 7
+category c540;
+#line 7
+category c541;
+#line 7
+category c542;
+#line 7
+category c543;
+#line 7
+category c544;
+#line 7
+category c545;
+#line 7
+category c546;
+#line 7
+category c547;
+#line 7
+category c548;
+#line 7
+category c549;
+#line 7
+category c550;
+#line 7
+category c551;
+#line 7
+category c552;
+#line 7
+category c553;
+#line 7
+category c554;
+#line 7
+category c555;
+#line 7
+category c556;
+#line 7
+category c557;
+#line 7
+category c558;
+#line 7
+category c559;
+#line 7
+category c560;
+#line 7
+category c561;
+#line 7
+category c562;
+#line 7
+category c563;
+#line 7
+category c564;
+#line 7
+category c565;
+#line 7
+category c566;
+#line 7
+category c567;
+#line 7
+category c568;
+#line 7
+category c569;
+#line 7
+category c570;
+#line 7
+category c571;
+#line 7
+category c572;
+#line 7
+category c573;
+#line 7
+category c574;
+#line 7
+category c575;
+#line 7
+category c576;
+#line 7
+category c577;
+#line 7
+category c578;
+#line 7
+category c579;
+#line 7
+category c580;
+#line 7
+category c581;
+#line 7
+category c582;
+#line 7
+category c583;
+#line 7
+category c584;
+#line 7
+category c585;
+#line 7
+category c586;
+#line 7
+category c587;
+#line 7
+category c588;
+#line 7
+category c589;
+#line 7
+category c590;
+#line 7
+category c591;
+#line 7
+category c592;
+#line 7
+category c593;
+#line 7
+category c594;
+#line 7
+category c595;
+#line 7
+category c596;
+#line 7
+category c597;
+#line 7
+category c598;
+#line 7
+category c599;
+#line 7
+category c600;
+#line 7
+category c601;
+#line 7
+category c602;
+#line 7
+category c603;
+#line 7
+category c604;
+#line 7
+category c605;
+#line 7
+category c606;
+#line 7
+category c607;
+#line 7
+category c608;
+#line 7
+category c609;
+#line 7
+category c610;
+#line 7
+category c611;
+#line 7
+category c612;
+#line 7
+category c613;
+#line 7
+category c614;
+#line 7
+category c615;
+#line 7
+category c616;
+#line 7
+category c617;
+#line 7
+category c618;
+#line 7
+category c619;
+#line 7
+category c620;
+#line 7
+category c621;
+#line 7
+category c622;
+#line 7
+category c623;
+#line 7
+category c624;
+#line 7
+category c625;
+#line 7
+category c626;
+#line 7
+category c627;
+#line 7
+category c628;
+#line 7
+category c629;
+#line 7
+category c630;
+#line 7
+category c631;
+#line 7
+category c632;
+#line 7
+category c633;
+#line 7
+category c634;
+#line 7
+category c635;
+#line 7
+category c636;
+#line 7
+category c637;
+#line 7
+category c638;
+#line 7
+category c639;
+#line 7
+category c640;
+#line 7
+category c641;
+#line 7
+category c642;
+#line 7
+category c643;
+#line 7
+category c644;
+#line 7
+category c645;
+#line 7
+category c646;
+#line 7
+category c647;
+#line 7
+category c648;
+#line 7
+category c649;
+#line 7
+category c650;
+#line 7
+category c651;
+#line 7
+category c652;
+#line 7
+category c653;
+#line 7
+category c654;
+#line 7
+category c655;
+#line 7
+category c656;
+#line 7
+category c657;
+#line 7
+category c658;
+#line 7
+category c659;
+#line 7
+category c660;
+#line 7
+category c661;
+#line 7
+category c662;
+#line 7
+category c663;
+#line 7
+category c664;
+#line 7
+category c665;
+#line 7
+category c666;
+#line 7
+category c667;
+#line 7
+category c668;
+#line 7
+category c669;
+#line 7
+category c670;
+#line 7
+category c671;
+#line 7
+category c672;
+#line 7
+category c673;
+#line 7
+category c674;
+#line 7
+category c675;
+#line 7
+category c676;
+#line 7
+category c677;
+#line 7
+category c678;
+#line 7
+category c679;
+#line 7
+category c680;
+#line 7
+category c681;
+#line 7
+category c682;
+#line 7
+category c683;
+#line 7
+category c684;
+#line 7
+category c685;
+#line 7
+category c686;
+#line 7
+category c687;
+#line 7
+category c688;
+#line 7
+category c689;
+#line 7
+category c690;
+#line 7
+category c691;
+#line 7
+category c692;
+#line 7
+category c693;
+#line 7
+category c694;
+#line 7
+category c695;
+#line 7
+category c696;
+#line 7
+category c697;
+#line 7
+category c698;
+#line 7
+category c699;
+#line 7
+category c700;
+#line 7
+category c701;
+#line 7
+category c702;
+#line 7
+category c703;
+#line 7
+category c704;
+#line 7
+category c705;
+#line 7
+category c706;
+#line 7
+category c707;
+#line 7
+category c708;
+#line 7
+category c709;
+#line 7
+category c710;
+#line 7
+category c711;
+#line 7
+category c712;
+#line 7
+category c713;
+#line 7
+category c714;
+#line 7
+category c715;
+#line 7
+category c716;
+#line 7
+category c717;
+#line 7
+category c718;
+#line 7
+category c719;
+#line 7
+category c720;
+#line 7
+category c721;
+#line 7
+category c722;
+#line 7
+category c723;
+#line 7
+category c724;
+#line 7
+category c725;
+#line 7
+category c726;
+#line 7
+category c727;
+#line 7
+category c728;
+#line 7
+category c729;
+#line 7
+category c730;
+#line 7
+category c731;
+#line 7
+category c732;
+#line 7
+category c733;
+#line 7
+category c734;
+#line 7
+category c735;
+#line 7
+category c736;
+#line 7
+category c737;
+#line 7
+category c738;
+#line 7
+category c739;
+#line 7
+category c740;
+#line 7
+category c741;
+#line 7
+category c742;
+#line 7
+category c743;
+#line 7
+category c744;
+#line 7
+category c745;
+#line 7
+category c746;
+#line 7
+category c747;
+#line 7
+category c748;
+#line 7
+category c749;
+#line 7
+category c750;
+#line 7
+category c751;
+#line 7
+category c752;
+#line 7
+category c753;
+#line 7
+category c754;
+#line 7
+category c755;
+#line 7
+category c756;
+#line 7
+category c757;
+#line 7
+category c758;
+#line 7
+category c759;
+#line 7
+category c760;
+#line 7
+category c761;
+#line 7
+category c762;
+#line 7
+category c763;
+#line 7
+category c764;
+#line 7
+category c765;
+#line 7
+category c766;
+#line 7
+category c767;
+#line 7
+category c768;
+#line 7
+category c769;
+#line 7
+category c770;
+#line 7
+category c771;
+#line 7
+category c772;
+#line 7
+category c773;
+#line 7
+category c774;
+#line 7
+category c775;
+#line 7
+category c776;
+#line 7
+category c777;
+#line 7
+category c778;
+#line 7
+category c779;
+#line 7
+category c780;
+#line 7
+category c781;
+#line 7
+category c782;
+#line 7
+category c783;
+#line 7
+category c784;
+#line 7
+category c785;
+#line 7
+category c786;
+#line 7
+category c787;
+#line 7
+category c788;
+#line 7
+category c789;
+#line 7
+category c790;
+#line 7
+category c791;
+#line 7
+category c792;
+#line 7
+category c793;
+#line 7
+category c794;
+#line 7
+category c795;
+#line 7
+category c796;
+#line 7
+category c797;
+#line 7
+category c798;
+#line 7
+category c799;
+#line 7
+category c800;
+#line 7
+category c801;
+#line 7
+category c802;
+#line 7
+category c803;
+#line 7
+category c804;
+#line 7
+category c805;
+#line 7
+category c806;
+#line 7
+category c807;
+#line 7
+category c808;
+#line 7
+category c809;
+#line 7
+category c810;
+#line 7
+category c811;
+#line 7
+category c812;
+#line 7
+category c813;
+#line 7
+category c814;
+#line 7
+category c815;
+#line 7
+category c816;
+#line 7
+category c817;
+#line 7
+category c818;
+#line 7
+category c819;
+#line 7
+category c820;
+#line 7
+category c821;
+#line 7
+category c822;
+#line 7
+category c823;
+#line 7
+category c824;
+#line 7
+category c825;
+#line 7
+category c826;
+#line 7
+category c827;
+#line 7
+category c828;
+#line 7
+category c829;
+#line 7
+category c830;
+#line 7
+category c831;
+#line 7
+category c832;
+#line 7
+category c833;
+#line 7
+category c834;
+#line 7
+category c835;
+#line 7
+category c836;
+#line 7
+category c837;
+#line 7
+category c838;
+#line 7
+category c839;
+#line 7
+category c840;
+#line 7
+category c841;
+#line 7
+category c842;
+#line 7
+category c843;
+#line 7
+category c844;
+#line 7
+category c845;
+#line 7
+category c846;
+#line 7
+category c847;
+#line 7
+category c848;
+#line 7
+category c849;
+#line 7
+category c850;
+#line 7
+category c851;
+#line 7
+category c852;
+#line 7
+category c853;
+#line 7
+category c854;
+#line 7
+category c855;
+#line 7
+category c856;
+#line 7
+category c857;
+#line 7
+category c858;
+#line 7
+category c859;
+#line 7
+category c860;
+#line 7
+category c861;
+#line 7
+category c862;
+#line 7
+category c863;
+#line 7
+category c864;
+#line 7
+category c865;
+#line 7
+category c866;
+#line 7
+category c867;
+#line 7
+category c868;
+#line 7
+category c869;
+#line 7
+category c870;
+#line 7
+category c871;
+#line 7
+category c872;
+#line 7
+category c873;
+#line 7
+category c874;
+#line 7
+category c875;
+#line 7
+category c876;
+#line 7
+category c877;
+#line 7
+category c878;
+#line 7
+category c879;
+#line 7
+category c880;
+#line 7
+category c881;
+#line 7
+category c882;
+#line 7
+category c883;
+#line 7
+category c884;
+#line 7
+category c885;
+#line 7
+category c886;
+#line 7
+category c887;
+#line 7
+category c888;
+#line 7
+category c889;
+#line 7
+category c890;
+#line 7
+category c891;
+#line 7
+category c892;
+#line 7
+category c893;
+#line 7
+category c894;
+#line 7
+category c895;
+#line 7
+category c896;
+#line 7
+category c897;
+#line 7
+category c898;
+#line 7
+category c899;
+#line 7
+category c900;
+#line 7
+category c901;
+#line 7
+category c902;
+#line 7
+category c903;
+#line 7
+category c904;
+#line 7
+category c905;
+#line 7
+category c906;
+#line 7
+category c907;
+#line 7
+category c908;
+#line 7
+category c909;
+#line 7
+category c910;
+#line 7
+category c911;
+#line 7
+category c912;
+#line 7
+category c913;
+#line 7
+category c914;
+#line 7
+category c915;
+#line 7
+category c916;
+#line 7
+category c917;
+#line 7
+category c918;
+#line 7
+category c919;
+#line 7
+category c920;
+#line 7
+category c921;
+#line 7
+category c922;
+#line 7
+category c923;
+#line 7
+category c924;
+#line 7
+category c925;
+#line 7
+category c926;
+#line 7
+category c927;
+#line 7
+category c928;
+#line 7
+category c929;
+#line 7
+category c930;
+#line 7
+category c931;
+#line 7
+category c932;
+#line 7
+category c933;
+#line 7
+category c934;
+#line 7
+category c935;
+#line 7
+category c936;
+#line 7
+category c937;
+#line 7
+category c938;
+#line 7
+category c939;
+#line 7
+category c940;
+#line 7
+category c941;
+#line 7
+category c942;
+#line 7
+category c943;
+#line 7
+category c944;
+#line 7
+category c945;
+#line 7
+category c946;
+#line 7
+category c947;
+#line 7
+category c948;
+#line 7
+category c949;
+#line 7
+category c950;
+#line 7
+category c951;
+#line 7
+category c952;
+#line 7
+category c953;
+#line 7
+category c954;
+#line 7
+category c955;
+#line 7
+category c956;
+#line 7
+category c957;
+#line 7
+category c958;
+#line 7
+category c959;
+#line 7
+category c960;
+#line 7
+category c961;
+#line 7
+category c962;
+#line 7
+category c963;
+#line 7
+category c964;
+#line 7
+category c965;
+#line 7
+category c966;
+#line 7
+category c967;
+#line 7
+category c968;
+#line 7
+category c969;
+#line 7
+category c970;
+#line 7
+category c971;
+#line 7
+category c972;
+#line 7
+category c973;
+#line 7
+category c974;
+#line 7
+category c975;
+#line 7
+category c976;
+#line 7
+category c977;
+#line 7
+category c978;
+#line 7
+category c979;
+#line 7
+category c980;
+#line 7
+category c981;
+#line 7
+category c982;
+#line 7
+category c983;
+#line 7
+category c984;
+#line 7
+category c985;
+#line 7
+category c986;
+#line 7
+category c987;
+#line 7
+category c988;
+#line 7
+category c989;
+#line 7
+category c990;
+#line 7
+category c991;
+#line 7
+category c992;
+#line 7
+category c993;
+#line 7
+category c994;
+#line 7
+category c995;
+#line 7
+category c996;
+#line 7
+category c997;
+#line 7
+category c998;
+#line 7
+category c999;
+#line 7
+category c1000;
+#line 7
+category c1001;
+#line 7
+category c1002;
+#line 7
+category c1003;
+#line 7
+category c1004;
+#line 7
+category c1005;
+#line 7
+category c1006;
+#line 7
+category c1007;
+#line 7
+category c1008;
+#line 7
+category c1009;
+#line 7
+category c1010;
+#line 7
+category c1011;
+#line 7
+category c1012;
+#line 7
+category c1013;
+#line 7
+category c1014;
+#line 7
+category c1015;
+#line 7
+category c1016;
+#line 7
+category c1017;
+#line 7
+category c1018;
+#line 7
+category c1019;
+#line 7
+category c1020;
+#line 7
+category c1021;
+#line 7
+category c1022;
+#line 7
+category c1023;
+#line 7
+
+
+# Generate level definitions for each sensitivity and category.
+level s0:c0.c1023;
+#line 10
+
+######################################
+# Attribute declarations
+#
+
+# All types used for processes.
+attribute domain;
+
+# Domains that are allowed all permissions ("unconfined").
+attribute unconfineddomain;
+
+# All domains used for apps.
+attribute appdomain;
+
+# All types used for files that can exist on a labeled fs.
+# Do not use for pseudo file types.
+attribute file_type;
+
+# All types used for domain entry points.
+attribute exec_type;
+
+#line 1 "external/sepolicy/bluetooth.te"
+# bluetooth subsystem
+type bluetooth, domain;
+permissive bluetooth;
+
+#line 4
+typeattribute bluetooth appdomain;
+
+#line 5
+typeattribute bluetooth unconfineddomain;
+#line 5
+
+#line 1 "external/sepolicy/healthd.te"
+# healthd seclabel is specified in init.rc since
+# it lives in the rootfs and has no unique file type.
+type healthd, domain;
+permissive healthd;
+type healthd_exec, exec_type, file_type;
+
+# New domain is entered by executing the file.
+#line 7
+allow healthd healthd_exec:file { entrypoint read execute };
+
+###
+### Neverallow rules
+###
+### These are things that Android apps should NEVER be able to do
+###
+
+# Superuser capabilities.
+# bluetooth requires net_admin.
+neverallow { appdomain -unconfineddomain -bluetooth } self:capability *;
+
+# Added to make the neverallow rule make sense in a limited environment.
+# Added at the bottom to not throw off file seek numbers in test suite.  
+# This is not a problem, because allow rules are processed after all types
+# are gathered.
+type testTYPE, appdomain, domain;
+
+# added rules for further testing (display full range of needed functionality)
+allow unconfineddomain {fs_type dev_type file_type}:{ chr_file file } ~{entrypoint relabelto};
+
+allow init {fs_type dev_type file_type}:{ dir { { chr_file blk_file } { file lnk_file sock_file fifo_file } } } relabelto;
+
+neverallow { appdomain -unconfineddomain } {
+    audio_device
+    camera_device
+    dm_device
+    radio_device
+    gps_device
+    rpmsg_device
+}:chr_file { read write };
\ No newline at end of file
diff --git a/tools/selinux/test/testrunner.py b/tools/selinux/test/testrunner.py
new file mode 100755
index 0000000..bc424e9
--- /dev/null
+++ b/tools/selinux/test/testrunner.py
@@ -0,0 +1,442 @@
+#!/usr/bin/python
+import sys
+sys.path.append('../src')
+import unittest
+import SELinux_CTS
+from SELinux_CTS import SELinuxPolicy
+
+policy_file_name = 'policy_test.conf'
+types = set([
+        'bluetooth',
+        'healthd',
+        'healthd_exec',
+        'testTYPE' ])  #testTYPE added for neverallow rule to make sense
+attributes = {
+    'domain': set(['bluetooth', 'healthd', 'testTYPE']),
+    'unconfineddomain': set(['bluetooth']),
+    'appdomain': set(['bluetooth', 'testTYPE']),
+    'file_type': set(['healthd_exec']),
+    'exec_type': set(['healthd_exec']) }
+common_classes = {
+    'file': set([
+            'ioctl',
+            'read',
+            'write',
+            'create',
+            'getattr',
+            'setattr',
+            'lock',
+            'relabelfrom',
+            'relabelto',
+            'append',
+            'unlink',
+            'link',
+            'rename',
+            'execute',
+            'swapon',
+            'quotaon',
+            'mounton' ]) }
+classes = {
+    'capability': set([
+            'chown',
+            'dac_override',
+            'dac_read_search',
+            'fowner',
+            'fsetid',
+            'kill',
+            'setgid',
+            'setuid',
+            'setpcap',
+            'linux_immutable',
+            'net_bind_service',
+            'net_broadcast',
+            'net_admin',
+            'net_raw',
+            'ipc_lock',
+            'ipc_owner',
+            'sys_module',
+            'sys_rawio',
+            'sys_chroot',
+            'sys_ptrace',
+            'sys_pacct',
+            'sys_admin',
+            'sys_boot',
+            'sys_nice',
+            'sys_resource',
+            'sys_time',
+            'sys_tty_config',
+            'mknod',
+            'lease',
+            'audit_write',
+            'audit_control',
+            'setfcap' ]),
+    'file': (set([
+                'execute_no_trans',
+                'entrypoint',
+                'execmod',
+                'open',
+                'audit_access' ]) | common_classes['file']) }
+
+# allow healthd healthd_exec:file { entrypoint read execute };
+allow_rules = [
+    { 'source_types': {
+        'set': set([
+                'healthd']),
+        'flags': { 'complement': False } },
+      'target_types': {
+        'set': set([
+                'healthd_exec']),
+        'flags': { 'complement': False } },
+      'classes': {
+        'set': set([
+                'file']),
+        'flags': { 'complement': False } },
+      'permissions': {
+        'set': set([
+                'entrypoint',
+                'read',
+                'execute' ]),
+        'flags': { 'complement': False } } } ]
+
+# neverallow { appdomain -unconfineddomain -bluetooth } self:capability *;
+neverallow_rules = [
+    { 'source_types': {
+        'set': set([
+                'appdomain',
+                '-unconfineddomain',
+                '-bluetooth' ]),
+        'flags': { 'complement': False } },
+      'target_types': {
+        'set': set([
+                'self']),
+        'flags': { 'complement': False } },
+      'classes': {
+        'set': set([
+                'capability']),
+        'flags': { 'complement': False } },
+      'permissions': {
+        'set': set([
+                '*' ]),
+        'flags': { 'complement': False } } } ]
+
+expected_final_allow_list = [
+        [ ('healthd', 'healthd_exec', 'file', 'entrypoint'),
+                ('healthd', 'healthd_exec', 'file', 'read'),
+                ('healthd', 'healthd_exec', 'file', 'execute') ] ]
+
+expected_final_neverallow_list = [
+        [ ('testTYPE', 'testTYPE', 'capability', 'chown'),
+                ('testTYPE', 'testTYPE', 'capability', 'dac_override'),
+                ('testTYPE', 'testTYPE', 'capability', 'dac_read_search'),
+                ('testTYPE', 'testTYPE', 'capability', 'fowner'),
+                ('testTYPE', 'testTYPE', 'capability', 'fsetid'),
+                ('testTYPE', 'testTYPE', 'capability', 'kill'),
+                ('testTYPE', 'testTYPE', 'capability', 'setgid'),
+                ('testTYPE', 'testTYPE', 'capability', 'setuid'),
+                ('testTYPE', 'testTYPE', 'capability', 'setpcap'),
+                ('testTYPE', 'testTYPE', 'capability', 'linux_immutable'),
+                ('testTYPE', 'testTYPE', 'capability', 'net_bind_service'),
+                ('testTYPE', 'testTYPE', 'capability', 'net_broadcast'),
+                ('testTYPE', 'testTYPE', 'capability', 'net_admin'),
+                ('testTYPE', 'testTYPE', 'capability', 'net_raw'),
+                ('testTYPE', 'testTYPE', 'capability', 'ipc_lock'),
+                ('testTYPE', 'testTYPE', 'capability', 'ipc_owner'),
+                ('testTYPE', 'testTYPE', 'capability', 'sys_module'),
+                ('testTYPE', 'testTYPE', 'capability', 'sys_rawio'),
+                ('testTYPE', 'testTYPE', 'capability', 'sys_chroot'),
+                ('testTYPE', 'testTYPE', 'capability', 'sys_ptrace'),
+                ('testTYPE', 'testTYPE', 'capability', 'sys_pacct'),
+                ('testTYPE', 'testTYPE', 'capability', 'sys_admin'),
+                ('testTYPE', 'testTYPE', 'capability', 'sys_boot'),
+                ('testTYPE', 'testTYPE', 'capability', 'sys_nice'),
+                ('testTYPE', 'testTYPE', 'capability', 'sys_resource'),
+                ('testTYPE', 'testTYPE', 'capability', 'sys_time'),
+                ('testTYPE', 'testTYPE', 'capability', 'sys_tty_config'),
+                ('testTYPE', 'testTYPE', 'capability', 'mknod'),
+                ('testTYPE', 'testTYPE', 'capability', 'lease'),
+                ('testTYPE', 'testTYPE', 'capability', 'audit_write'),
+                ('testTYPE', 'testTYPE', 'capability', 'audit_control'),
+                ('testTYPE', 'testTYPE', 'capability', 'setfcap') ] ]
+
+
+class SELinuxPolicyTests(unittest.TestCase):
+
+
+    def setUp(self):
+        self.test_policy = SELinuxPolicy()
+        self.test_file = open(policy_file_name, 'r')
+        self.test_policy.types = types
+        self.test_policy.attributes = attributes
+        self.test_policy.common_classes = common_classes
+        self.test_policy.classes = classes
+        self.test_policy.allow_rules = allow_rules
+        self.test_policy.neverallow_rules = neverallow_rules
+        return
+
+    def testExpandAvcRule(self):
+        #TODO: add more examples here to cover different cases
+        expanded_allow_list = SELinux_CTS.expand_avc_rule(self.test_policy, self.test_policy.allow_rules[0])
+        for a in expected_final_allow_list[0]:
+            self.failUnless(a in expanded_allow_list)
+        expanded_neverallow_list = SELinux_CTS.expand_avc_rule(self.test_policy, self.test_policy.neverallow_rules[0])
+        for n in expected_final_neverallow_list[0]:
+            self.failUnless(n in expanded_neverallow_list)
+
+    def testExpandBrackets(self):
+        #test position without bracket:
+        self.test_file.seek(279)
+        self.failIf(SELinux_CTS.expand_brackets(self.test_file))
+
+        #test position with bracket:
+        self.test_file.seek(26123)
+        self.failUnless(SELinux_CTS.expand_brackets(self.test_file) == " entrypoint read execute ")
+
+        #test position with nested brackets:
+        self.test_file.seek(26873)
+        self.failUnless(SELinux_CTS.expand_brackets(self.test_file)
+               == " dir   chr_file blk_file   file lnk_file sock_file fifo_file   ")
+
+    def testGetAvcRuleComponent(self):
+        #test against normal ('allow healthd healthd_exec:file ...)
+        self.test_file.seek(26096)
+        normal_src = { 'flags': { 'complement': False },
+                'set': set(['healthd']) }
+        normal_tgt = { 'flags': { 'complement': False },
+                'set': set(['healthd_exec']) }
+        normal_class = { 'flags': { 'complement': False },
+                'set': set(['file']) }
+        normal_perm = { 'flags': { 'complement': False },
+                'set': set(['entrypoint', 'read', 'execute']) }
+        self.failUnless(SELinux_CTS.get_avc_rule_component(self.test_file)
+            == normal_src)
+        self.failUnless(SELinux_CTS.get_avc_rule_component(self.test_file)
+            == normal_tgt)
+        c = SELinux_CTS.advance_past_whitespace(self.test_file)
+        if c == ':':
+            self.test_file.read(1)
+        self.failUnless(SELinux_CTS.get_avc_rule_component(self.test_file)
+            == normal_class)
+        self.failUnless(SELinux_CTS.get_avc_rule_component(self.test_file)
+            == normal_perm)
+
+        #test against 'hard' ('init {fs_type  ...' )
+        self.test_file.seek(26838)
+        hard_src = { 'flags': { 'complement': False },
+                'set': set(['init']) }
+        hard_tgt = { 'flags': { 'complement': False },
+                'set': set(['fs_type', 'dev_type', 'file_type']) }
+        hard_class = { 'flags': { 'complement': False },
+                'set': set(['dir', 'chr_file', 'blk_file', 'file', 'lnk_file', 'sock_file', 'fifo_file']) }
+        hard_perm = { 'flags': { 'complement': False },
+                'set': set(['relabelto']) }
+        self.failUnless(SELinux_CTS.get_avc_rule_component(self.test_file)
+            == hard_src)
+        self.failUnless(SELinux_CTS.get_avc_rule_component(self.test_file)
+            == hard_tgt)
+        #mimic ':' check:
+        c = SELinux_CTS.advance_past_whitespace(self.test_file)
+        if c == ':':
+            self.test_file.read(1)
+        self.failUnless(SELinux_CTS.get_avc_rule_component(self.test_file)
+            == hard_class)
+        self.failUnless(SELinux_CTS.get_avc_rule_component(self.test_file)
+            == hard_perm)
+
+        #test against 'multi-line' ('init {fs_type  ...' )
+        self.test_file.seek(26967)
+        multi_src = { 'flags': { 'complement': False },
+                'set': set(['appdomain', '-unconfineddomain']) }
+        multi_tgt = { 'flags': { 'complement': False },
+                'set': set(['audio_device', 'camera_device', 'dm_device', 'radio_device', 'gps_device', 'rpmsg_device']) }
+        multi_class = { 'flags': { 'complement': False },
+                'set': set(['chr_file']) }
+        multi_perm = { 'flags': { 'complement': False },
+                'set': set(['read', 'write']) }
+        self.failUnless(SELinux_CTS.get_avc_rule_component(self.test_file)
+            == multi_src)
+        self.failUnless(SELinux_CTS.get_avc_rule_component(self.test_file)
+            == multi_tgt)
+        c = SELinux_CTS.advance_past_whitespace(self.test_file)
+        if c == ':':
+            self.test_file.read(1)
+        self.failUnless(SELinux_CTS.get_avc_rule_component(self.test_file)
+            == multi_class)
+        self.failUnless(SELinux_CTS.get_avc_rule_component(self.test_file)
+            == multi_perm)
+
+        #test against 'complement'
+        self.test_file.seek(26806)
+        complement = { 'flags': { 'complement': True },
+                'set': set(['entrypoint', 'relabelto']) }
+        self.failUnless(SELinux_CTS.get_avc_rule_component(self.test_file)
+            == complement)
+
+    def testGetLineType(self):
+        self.failUnless(SELinux_CTS.get_line_type('type bluetooth, domain;')
+                == SELinux_CTS.TYPE)
+        self.failUnless(SELinux_CTS.get_line_type('attribute unconfineddomain;')
+                == SELinux_CTS.ATTRIBUTE)
+        self.failUnless(SELinux_CTS.get_line_type('typeattribute bluetooth appdomain;')
+                == SELinux_CTS.TYPEATTRIBUTE)
+        self.failUnless(SELinux_CTS.get_line_type('class file')
+                == SELinux_CTS.CLASS)
+        self.failUnless(SELinux_CTS.get_line_type('common file')
+                == SELinux_CTS.COMMON)
+        self.failUnless(SELinux_CTS.get_line_type('allow healthd healthd_exec:file { entrypoint read execute };')
+                == SELinux_CTS.ALLOW_RULE)
+        self.failUnless(SELinux_CTS.get_line_type('neverallow { appdomain -unconfineddomain -bluetooth } self:capability *;')
+                == SELinux_CTS.NEVERALLOW_RULE)
+        self.failUnless(SELinux_CTS.get_line_type('# FLASK')
+                == SELinux_CTS.OTHER)
+
+    def testIsMultiLine(self):
+        self.failIf(SELinux_CTS.is_multi_line(SELinux_CTS.TYPE))
+        self.failIf(SELinux_CTS.is_multi_line(SELinux_CTS.ATTRIBUTE))
+        self.failIf(SELinux_CTS.is_multi_line(SELinux_CTS.TYPEATTRIBUTE))
+        self.failUnless(SELinux_CTS.is_multi_line(SELinux_CTS.CLASS))
+        self.failUnless(SELinux_CTS.is_multi_line(SELinux_CTS.COMMON))
+        self.failUnless(SELinux_CTS.is_multi_line(SELinux_CTS.ALLOW_RULE))
+        self.failUnless(SELinux_CTS.is_multi_line(SELinux_CTS.NEVERALLOW_RULE))
+        self.failIf(SELinux_CTS.is_multi_line(SELinux_CTS.OTHER))
+
+    def testProcessInheritsSegment(self):
+        inherit_offset = 448 # needs changing if file changes
+        self.test_file.seek(inherit_offset, 0)
+        inherit_result = SELinux_CTS.process_inherits_segment(self.test_file)
+        self.failUnless(inherit_result == 'file')
+        return
+
+    def testFromFileName(self):
+        #using a special file, since the test_file has some lines which don't 'jive'
+        clean_policy_file = 'policy_clean_test.conf'
+        from_file_policy = SELinuxPolicy()
+        from_file_policy.from_file_name(clean_policy_file)
+        self.failUnless(from_file_policy.types == self.test_policy.types)
+        self.failUnless(from_file_policy.attributes == self.test_policy.attributes)
+        self.failUnless(from_file_policy.classes == self.test_policy.classes)
+        self.failUnless(from_file_policy.common_classes == self.test_policy.common_classes)
+        self.failUnless(from_file_policy.allow_rules == self.test_policy.allow_rules)
+        self.failUnless(from_file_policy.neverallow_rules == self.test_policy.neverallow_rules)
+
+    def testExpandPermissions(self):
+        #test general case
+        test_class_obj = 'file'
+        general_set = set(['read', 'write', 'execute'])
+        expanded_general_set = general_set
+        self.failUnless(self.test_policy.expand_permissions(test_class_obj, general_set)
+                == general_set)
+        star_set = set(['*'])
+        expanded_star_set = self.test_policy.classes['file'] #everything in the class
+        self.failUnless(self.test_policy.expand_permissions(test_class_obj, star_set)
+                == expanded_star_set)
+        complement_set = set(['*', '-open'])
+        expanded_complement_set = self.test_policy.classes['file'] - set(['open'])
+        self.failUnless(self.test_policy.expand_permissions(test_class_obj, complement_set)
+                == expanded_complement_set)
+
+    def testExpandTypes(self):
+
+        #test general case and '-' handling
+        test_source_set = set([
+                'domain',
+                '-bluetooth' ])
+        expanded_test_source_set = set([
+                'healthd', 'testTYPE' ])
+        self.failUnless(self.test_policy.expand_types(test_source_set) == expanded_test_source_set)
+
+        #test '*' handling
+        test_source_set = set([ '*' ])
+        expanded_test_source_set = set([
+                'bluetooth', 'healthd', 'testTYPE' ])
+        self.failUnless(self.test_policy.expand_types(test_source_set) == types)
+        #test - handling
+        test_source_set = set([
+                '*',
+                '-bluetooth'])
+        expanded_test_source_set = set([
+                'healthd', 'healthd_exec', 'testTYPE' ])
+        self.failUnless(self.test_policy.expand_types(test_source_set) == expanded_test_source_set)
+
+    def testProcessAttributeLine(self):
+        attribute_policy = SELinuxPolicy()
+        #test with 'normal input'
+        test_normal_string = 'attribute TEST_att;'
+        test_attribute = 'TEST_att'
+        attribute_policy.process_attribute_line(test_normal_string)
+        self.failUnless( test_attribute in attribute_policy.attributes)
+        #TODO: test on bogus inputs
+
+    def testProcessClassLine(self):
+        class_policy = SELinuxPolicy()
+        #offsets need changing if test file changes
+        common_offset  = 279
+        class_initial_offset  = 212
+        class_perm_offset = 437
+        self.test_file.seek(common_offset, 0)
+        line = self.test_file.readline()
+        class_policy.process_common_line(line, self.test_file)
+        self.test_file.seek(class_initial_offset, 0)
+        line = self.test_file.readline()
+        class_policy.process_class_line(line, self.test_file)
+        self.failUnless('file' in class_policy.classes)
+        self.test_file.seek(class_perm_offset, 0)
+        line = self.test_file.readline()
+        class_policy.process_class_line(line, self.test_file)
+        self.failUnless(class_policy.classes['file'] == classes['file'])
+
+    def testProcessCommonLine(self):
+        common_policy = SELinuxPolicy()
+        common_offset  = 279 # needs changing if file changes
+        self.test_file.seek(common_offset, 0)
+        line = self.test_file.readline()
+        common_policy.process_common_line(line, self.test_file)
+        self.failUnless('file' in common_policy.common_classes )
+        self.failUnless(common_policy.common_classes['file'] == common_classes['file'])
+
+    def testProcessAvcRuleLine(self):
+        avc_policy = SELinuxPolicy()
+        allow_offset  =  26091 # needs changing if file changes
+        neverallow_offset  = 26311  # needs changing if file changes
+        self.test_file.seek(allow_offset, 0)
+        line = self.test_file.readline()
+        avc_policy.process_avc_rule_line(line, self.test_file)
+        self.failUnless(avc_policy.allow_rules[0] == allow_rules[0] ) # always '0'?
+        self.test_file.seek(neverallow_offset, 0)
+        line = self.test_file.readline()
+        avc_policy.process_avc_rule_line(line, self.test_file)
+        self.failUnless(avc_policy.neverallow_rules[0] == neverallow_rules[0] ) # always '0'?
+
+    def testProcessTypeLine(self):
+        type_policy = SELinuxPolicy()
+        test_normal_string = 'type TEST_type, TEST_att1, TEST_att2;'
+        test_type = 'TEST_type'
+        test_atts = ['TEST_att1', 'TEST_att2']
+        #test with 'normal input'
+        type_policy.process_type_line(test_normal_string)
+        self.failUnless(test_type in type_policy.types)
+        for a in test_atts:
+            self.failUnless(a in type_policy.attributes)
+            self.failUnless(test_type in type_policy.attributes[a])
+        #TODO: test with domain only, no attributes
+        # and test on bogus inputs
+
+    def testProcessTypeattributeLine(self):
+        typ_att_policy = SELinuxPolicy()
+        test_normal_string = 'typeattribute TEST_type TEST_att1, TEST_att2;'
+        test_type = 'TEST_type'
+        test_atts = ['TEST_att1', 'TEST_att2']
+        #test with 'normal input' (type should already be declared)
+        typ_att_policy.process_type_line('type ' + test_type + ';')
+        typ_att_policy.process_typeattribute_line(test_normal_string)
+        self.failUnless(test_type in typ_att_policy.types)
+        for a in test_atts:
+            self.failUnless(a in typ_att_policy.attributes)
+            self.failUnless(test_type in typ_att_policy.attributes[a])
+        #TODO: test with domain only, no attributes
+        # and test on bogus inputs
+
+def main():
+    unittest.main()
+
+if __name__ == '__main__':
+    main()
diff --git a/tools/tradefed-host/.classpath b/tools/tradefed-host/.classpath
index 0b1866d..e716219 100644
--- a/tools/tradefed-host/.classpath
+++ b/tools/tradefed-host/.classpath
@@ -2,10 +2,10 @@
 <classpath>
 	<classpathentry kind="src" path="src"/>
 	<classpathentry kind="src" path="res"/>
+	<classpathentry kind="src" path="commonutil-src"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
 	<classpathentry exported="true" kind="var" path="CTS_SRC_ROOT/out/host/common/obj/JAVA_LIBRARIES/ctsdeviceinfolib_intermediates/javalib.jar"/>
-	<classpathentry exported="true" kind="var" path="CTS_SRC_ROOT/out/host/common/obj/JAVA_LIBRARIES/hosttestlib_intermediates/javalib.jar"/>
-	<classpathentry kind="var" path="CTS_SRC_ROOT/out/host/common/obj/JAVA_LIBRARIES/ddmlib-prebuilt_intermediates/ddmlib-prebuilt.jar" sourcepath="/SDK_SRC_ROOT"/>
-	<classpathentry kind="var" path="CTS_SRC_ROOT/out/host/common/obj/JAVA_LIBRARIES/tradefed-prebuilt_intermediates/tradefed-prebuilt.jar" sourcepath="/TRADEFED_ROOT/tools/tradefederation/src"/>
+	<classpathentry kind="var" path="CTS_SRC_ROOT/out/host/common/obj/JAVA_LIBRARIES/hosttestlib_intermediates/javalib.jar"/>
+	<classpathentry kind="var" path="CTS_SRC_ROOT/prebuilts/misc/common/tradefed/tradefed-prebuilt.jar"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/tools/tradefed-host/.project b/tools/tradefed-host/.project
index 990c63e..ffd16af 100644
--- a/tools/tradefed-host/.project
+++ b/tools/tradefed-host/.project
@@ -14,4 +14,11 @@
 	<natures>
 		<nature>org.eclipse.jdt.core.javanature</nature>
 	</natures>
+	<linkedResources>
+		<link>
+			<name>commonutil-src</name>
+			<type>2</type>
+			<locationURI>CTS_SRC_ROOT/cts/libs/commonutil/src</locationURI>
+		</link>
+	</linkedResources>
 </projectDescription>
diff --git a/tools/tradefed-host/Android.mk b/tools/tradefed-host/Android.mk
index 0b5d764..bd28575 100644
--- a/tools/tradefed-host/Android.mk
+++ b/tools/tradefed-host/Android.mk
@@ -24,7 +24,7 @@
 
 LOCAL_MODULE := cts-tradefed
 LOCAL_MODULE_TAGS := optional
-LOCAL_JAVA_LIBRARIES := ddmlib-prebuilt tradefed-prebuilt hosttestlib
+LOCAL_JAVA_LIBRARIES := tradefed-prebuilt hosttestlib
 LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceinfolib
 
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
diff --git a/tools/tradefed-host/etc/cts-tradefed b/tools/tradefed-host/etc/cts-tradefed
index bc5c07a..9a643de 100755
--- a/tools/tradefed-host/etc/cts-tradefed
+++ b/tools/tradefed-host/etc/cts-tradefed
@@ -35,7 +35,7 @@
 checkPath java
 
 # check java version
-JAVA_VERSION=$(java -version 2>&1 | head -n 1 | grep '[ "]1\.[67][\. "$$]')
+JAVA_VERSION=$(java -version 2>&1 | head -n 2 | grep '[ "]1\.[67][\. "$$]')
 if [ "${JAVA_VERSION}" == "" ]; then
     echo "Wrong java version. 1.6 or 1.7 is required."
     exit
@@ -51,17 +51,21 @@
 
 
 # check if in Android build env
-if [ ! -z ${ANDROID_BUILD_TOP} ]; then
-    HOST=`uname`
-    if [ "$HOST" == "Linux" ]; then
-        OS="linux-x86"
-    elif [ "$HOST" == "Darwin" ]; then
-        OS="darwin-x86"
+if [ ! -z "${ANDROID_BUILD_TOP}" ]; then
+    if [ ! -z "${ANDROID_HOST_OUT}" ]; then
+      CTS_ROOT=${ANDROID_HOST_OUT}/cts
     else
-        echo "Unrecognized OS"
-        exit
-    fi;
-    CTS_ROOT=${ANDROID_BUILD_TOP}/out/host/${OS}/cts
+      HOST=`uname`
+      if [ "$HOST" == "Linux" ]; then
+          OS="linux-x86"
+      elif [ "$HOST" == "Darwin" ]; then
+          OS="darwin-x86"
+      else
+          echo "Unrecognized OS"
+          exit
+      fi
+      CTS_ROOT=${ANDROID_BUILD_TOP}/${OUT_DIR:-out}/host/${OS}/cts
+    fi
     if [ ! -d ${CTS_ROOT} ]; then
         echo "Could not find $CTS_ROOT in Android build environment. Try 'make cts'"
         exit
@@ -74,7 +78,7 @@
 fi;
 
 JAR_DIR=${CTS_ROOT}/android-cts/tools
-JARS="ddmlib-prebuilt.jar tradefed-prebuilt.jar hosttestlib.jar cts-tradefed.jar"
+JARS="tradefed-prebuilt.jar hosttestlib.jar cts-tradefed.jar"
 
 for JAR in $JARS; do
     checkFile ${JAR_DIR}/${JAR}
diff --git a/tools/tradefed-host/res/config/cts.xml b/tools/tradefed-host/res/config/cts.xml
index 158f49d..416b400 100644
--- a/tools/tradefed-host/res/config/cts.xml
+++ b/tools/tradefed-host/res/config/cts.xml
@@ -22,6 +22,7 @@
     <test class="com.android.cts.tradefed.testtype.CtsTest" />
     <logger class="com.android.tradefed.log.FileLogger" />
     <result_reporter class="com.android.cts.tradefed.result.CtsXmlResultReporter" />
+    <result_reporter class="com.android.cts.tradefed.result.CtsTestLogReporter" />
     <result_reporter class="com.android.cts.tradefed.result.IssueReporter" />
 
 </configuration>
diff --git a/tools/tradefed-host/res/report/cts_result.xsl b/tools/tradefed-host/res/report/cts_result.xsl
index fe49308..7bc216b 100644
--- a/tools/tradefed-host/res/report/cts_result.xsl
+++ b/tools/tradefed-host/res/report/cts_result.xsl
@@ -339,8 +339,7 @@
                             <TD class="rowtitle">Host Info</TD>
                             <TD>
                                 <xsl:value-of select="TestResult/HostInfo/@name"/>
-                                (<xsl:value-of select="TestResult/HostInfo/Os/@name"/> - 
-                                  <xsl:value-of select="TestResult/HostInfo/Os/@version"/>)
+                                (<xsl:value-of select="TestResult/HostInfo/Os/@name"/> - <xsl:value-of select="TestResult/HostInfo/Os/@version"/>)
                             </TD>
                         </TR>
                         <TR>
@@ -466,7 +465,11 @@
                         <TR>
                             <TD class="package" colspan="3">
                                 <xsl:variable name="href"><xsl:value-of select="@appPackageName"/></xsl:variable>
-                                <a name="{$href}">Compatibility Test Package: <xsl:value-of select="@appPackageName"/></a>
+                                <a name="{$href}">Compatibility Test Package: <xsl:value-of select="@appPackageName"/>
+                                <xsl:if test="@abi">
+                                  ABI: <xsl:value-of select="@abi"/>
+                                </xsl:if>
+                                </a>
                             </TD>
                         </TR>
 
@@ -510,7 +513,7 @@
                                                 <xsl:if test="@result='pass'">
                                                     <TD class="pass">
                                                         <div style="text-align: center; margin-left:auto; margin-right:auto;">
-                                                            known problem
+                                                            Known problem
                                                         </div>
                                                     </TD>
                                                     <TD class="failuredetails"></TD>
@@ -583,7 +586,7 @@
         </DIV>
     </xsl:template>
 
-    <!-- Take a delimited string and insert line breaks after a some number of elements. --> 
+    <!-- Take a delimited string and insert line breaks after a some number of elements. -->
     <xsl:template name="formatDelimitedString">
         <xsl:param name="string" />
         <xsl:param name="numTokensPerRow" select="10" />
@@ -593,7 +596,7 @@
             <xsl:variable name="token" select="substring-before($string, ';')" />
             <xsl:value-of select="$token" />
             <xsl:text>&#160;</xsl:text>
-          
+
             <xsl:if test="$tokenIndex mod $numTokensPerRow = 0">
                 <br />
             </xsl:if>
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildHelper.java b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildHelper.java
index 61b4b43..0940355 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildHelper.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildHelper.java
@@ -33,7 +33,7 @@
     private final String mSuiteName = "CTS";
     /** The root location of the extracted CTS package */
     private final File mRootDir;
-    /** the {@link CTS_DIR_NAME} directory */
+    /** the {@link #CTS_DIR_NAME} directory */
     private final File mCtsDir;
 
     /**
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
index d62531c..25431b2 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
@@ -31,7 +31,7 @@
     @Option(name="cts-install-path", description="the path to the cts installation to use")
     private String mCtsRootDirPath = System.getProperty("CTS_ROOT");
 
-    public static final String CTS_BUILD_VERSION = "4.4W_r4";
+    public static final String CTS_BUILD_VERSION = "5.0_r2";
 
     /**
      * {@inheritDoc}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/command/CtsConsole.java b/tools/tradefed-host/src/com/android/cts/tradefed/command/CtsConsole.java
index 40145dd..ca4e050 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/command/CtsConsole.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/command/CtsConsole.java
@@ -23,6 +23,7 @@
 import com.android.cts.tradefed.result.TestResultRepo;
 import com.android.cts.tradefed.testtype.ITestPackageRepo;
 import com.android.cts.tradefed.testtype.TestPackageRepo;
+import com.android.cts.util.AbiUtils;
 import com.android.tradefed.command.Console;
 import com.android.tradefed.config.ArgsOptionParser;
 import com.android.tradefed.config.ConfigurationException;
@@ -38,6 +39,7 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * Specialization of trade federation console that adds CTS commands to list plans and packages.
@@ -114,7 +116,8 @@
                 }
                 CtsBuildHelper ctsBuild = getCtsBuild();
                 if (ctsBuild != null) {
-                    addDerivedPlan(ctsBuild, flatArgs);
+                    // FIXME may want to only add certain ABIs
+                    addDerivedPlan(ctsBuild, AbiUtils.getAbisSupportedByCts(), flatArgs);
                 }
             }
         };
@@ -151,7 +154,7 @@
         helpBuilder.append("method\n");
         helpBuilder.append("  run cts --continue-session session_ID: run all not executed ");
         helpBuilder.append("tests from a previous CTS session\n");
-        helpBuilder.append("  run cts [options] --serial/s device_ID: run CTS on specified ");
+        helpBuilder.append("  run cts [options] --serial/-s device_ID: run CTS on specified ");
         helpBuilder.append("device\n");
         helpBuilder.append("  run cts [options] --shards number_of_shards: shard a CTS run into ");
         helpBuilder.append("given number of independent chunks, to run on multiple devices in");
@@ -192,8 +195,8 @@
 
     private void listPackages(CtsBuildHelper ctsBuild) {
         ITestPackageRepo testCaseRepo = new TestPackageRepo(ctsBuild.getTestCasesDir(), false);
-        for (String packageUri : testCaseRepo.getPackageNames()) {
-            printLine(packageUri);
+        for (String packageName : testCaseRepo.getPackageNames()) {
+            printLine(packageName);
         }
     }
 
@@ -215,12 +218,12 @@
         tableFormatter.displayTable(table, new PrintWriter(System.out, true));
     }
 
-    private void addDerivedPlan(CtsBuildHelper ctsBuild, String[] flatArgs) {
+    private void addDerivedPlan(CtsBuildHelper ctsBuild, Set<String> abis, String[] flatArgs) {
         PlanCreator creator = new PlanCreator();
         try {
             ArgsOptionParser optionParser = new ArgsOptionParser(creator);
             optionParser.parse(Arrays.asList(flatArgs));
-            creator.createAndSerializeDerivedPlan(ctsBuild);
+            creator.createAndSerializeDerivedPlan(ctsBuild, abis);
         } catch (ConfigurationException e) {
             printLine("Error: " + e.getMessage());
             printLine(ArgsOptionParser.getOptionHelp(false, creator));
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/device/DeviceInfoCollector.java b/tools/tradefed-host/src/com/android/cts/tradefed/device/DeviceInfoCollector.java
index 3aa57a0..903ac74 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/device/DeviceInfoCollector.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/device/DeviceInfoCollector.java
@@ -15,6 +15,7 @@
  */
 package com.android.cts.tradefed.device;
 
+import com.android.cts.util.AbiUtils;
 import com.android.ddmlib.Log;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
@@ -22,6 +23,8 @@
 import com.android.tradefed.testtype.InstrumentationTest;
 
 import java.io.File;
+import java.util.HashSet;
+import java.util.Set;
 
 /**
  * Collects info from device under test.
@@ -36,16 +39,22 @@
     private static final String APK_NAME = "TestDeviceSetup";
     public static final String APP_PACKAGE_NAME = "android.tests.devicesetup";
     private static final String INSTRUMENTATION_NAME = "android.tests.getinfo.DeviceInfoInstrument";
+    public static final Set<String> IDS = new HashSet<String>();
+    static {
+        for (String abi : AbiUtils.getAbisSupportedByCts()) {
+            IDS.add(AbiUtils.createId(abi, APP_PACKAGE_NAME));
+        }
+    }
 
     /**
      * Installs and runs the device info collector instrumentation, and forwards results
-     * to the <var>listener</var>
+     * to the listener.
      *
      * @param device
      * @param listener
      * @throws DeviceNotAvailableException
      */
-    public static void collectDeviceInfo(ITestDevice device, File testApkDir,
+    public static void collectDeviceInfo(ITestDevice device, String abi, File testApkDir,
             ITestInvocationListener listener) throws DeviceNotAvailableException {
         File apkFile = new File(testApkDir, String.format("%s.apk", APK_NAME));
         if (!apkFile.exists()) {
@@ -59,6 +68,7 @@
         // no need to collect tests and re-run
         instrTest.setRerunMode(false);
         instrTest.setPackageName(APP_PACKAGE_NAME);
+        instrTest.setRunName(AbiUtils.createId(abi, APP_PACKAGE_NAME));
         instrTest.setRunnerName(INSTRUMENTATION_NAME);
         instrTest.run(listener);
     }
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsReportUtil.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsReportUtil.java
deleted file mode 100644
index 97f607e..0000000
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsReportUtil.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.cts.tradefed.result;
-
-import java.util.Map;
-
-/**
- * Static utility class for handling Cts Results.
- */
-public class CtsReportUtil {
-    private static final String CTS_RESULT_KEY = "CTS_RESULT";
-
-    /**
-     * Utility method to extract CTS result from test metrics
-     * @param testMetrics
-     * @return result or null if not found
-     */
-    public static String getCtsResultFromMetrics(Map<String, String> testMetrics) {
-        for (Map.Entry<String, String> entry: testMetrics.entrySet()) {
-            if (CTS_RESULT_KEY.equals(entry.getKey())) {
-                return entry.getValue();
-            }
-        }
-        return null;
-    }
-}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsTestLogReporter.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsTestLogReporter.java
new file mode 100644
index 0000000..5029dfe
--- /dev/null
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsTestLogReporter.java
@@ -0,0 +1,151 @@
+/*
+ * 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 com.android.cts.tradefed.result;
+
+import com.android.cts.tradefed.device.DeviceInfoCollector;
+import com.android.cts.util.AbiUtils;
+import com.android.ddmlib.Log;
+import com.android.ddmlib.Log.LogLevel;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.config.OptionCopier;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.result.IShardableListener;
+import com.android.tradefed.result.StubTestInvocationListener;
+
+import java.util.Map;
+
+/**
+ * Dumps tests in progress to stdout
+ */
+public class CtsTestLogReporter extends StubTestInvocationListener implements IShardableListener {
+
+    @Option(name = "quiet-output", description = "Mute display of test results.")
+    private boolean mQuietOutput = false;
+
+    protected IBuildInfo mBuildInfo;
+    private String mDeviceSerial;
+    private TestResults mResults = new TestResults();
+    private TestPackageResult mCurrentPkgResult = null;
+    private boolean mIsDeviceInfoRun = false;
+
+    @Override
+    public void invocationStarted(IBuildInfo buildInfo) {
+        mDeviceSerial = buildInfo.getDeviceSerial() == null ? "unknown_device" : buildInfo.getDeviceSerial();
+    }
+
+    /**
+     * Reports the start of a test run.
+     *
+     * @param id the unique identifier of this test run, generated by
+     * {@link AbiUtils#createId(String, String)}.
+     * @param numTests total number of tests in test run
+     */
+    @Override
+    public void testRunStarted(String id, int numTests) {
+        if (mCurrentPkgResult != null && !id.equals(mCurrentPkgResult.getId())) {
+            // display results from previous run
+            logCompleteRun(mCurrentPkgResult);
+        }
+        mIsDeviceInfoRun = DeviceInfoCollector.IDS.contains(id);
+        if (mIsDeviceInfoRun) {
+            logResult("Collecting device info");
+        } else  {
+            if (mCurrentPkgResult == null || !id.equals(mCurrentPkgResult.getId())) {
+                logResult("-----------------------------------------");
+                logResult("Test package %s started", id);
+                logResult("-----------------------------------------");
+            }
+            mCurrentPkgResult = mResults.getOrCreatePackage(id);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void testStarted(TestIdentifier test) {
+        mCurrentPkgResult.insertTest(test);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void testFailed(TestIdentifier test, String trace) {
+        mCurrentPkgResult.reportTestFailure(test, CtsTestStatus.FAIL, trace);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void testAssumptionFailure(TestIdentifier test, String trace) {
+        // TODO: do something different here?
+        mCurrentPkgResult.reportTestFailure(test, CtsTestStatus.FAIL, trace);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void testEnded(TestIdentifier test, Map<String, String> testMetrics) {
+        mCurrentPkgResult.reportTestEnded(test, testMetrics);
+        Test result = mCurrentPkgResult.findTest(test);
+        String stack = result.getStackTrace() == null ? "" : "\n" + result.getStackTrace();
+        logResult("%s#%s %s %s", test.getClassName(), test.getTestName(), result.getResult(),
+                stack);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void invocationEnded(long elapsedTime) {
+        // display the results of the last completed run
+        if (mCurrentPkgResult != null) {
+            logCompleteRun(mCurrentPkgResult);
+        }
+    }
+
+    private void logResult(String format, Object... args) {
+        if (mQuietOutput) {
+            CLog.i(format, args);
+        } else {
+            Log.logAndDisplay(LogLevel.INFO, mDeviceSerial, String.format(format, args));
+        }
+    }
+
+    private void logCompleteRun(TestPackageResult pkgResult) {
+        if (pkgResult.getAppPackageName().equals(DeviceInfoCollector.APP_PACKAGE_NAME)) {
+            logResult("Device info collection complete");
+            return;
+        }
+        logResult("%s package complete: Passed %d, Failed %d, Not Executed %d",
+                pkgResult.getId(), pkgResult.countTests(CtsTestStatus.PASS),
+                pkgResult.countTests(CtsTestStatus.FAIL),
+                pkgResult.countTests(CtsTestStatus.NOT_EXECUTED));
+    }
+
+    @Override
+    public IShardableListener clone() {
+        CtsTestLogReporter clone = new CtsTestLogReporter();
+        OptionCopier.copyOptionsNoThrow(this, clone);
+        return clone;
+    }
+}
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 70310ca..8cb4072 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
@@ -19,17 +19,21 @@
 import com.android.cts.tradefed.build.CtsBuildHelper;
 import com.android.cts.tradefed.device.DeviceInfoCollector;
 import com.android.cts.tradefed.testtype.CtsTest;
-import com.android.cts.tradefed.util.CtsHostStore;
 import com.android.ddmlib.Log;
 import com.android.ddmlib.Log.LogLevel;
 import com.android.ddmlib.testrunner.TestIdentifier;
 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.ILogSaver;
+import com.android.tradefed.result.ILogSaverListener;
 import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.result.ITestSummaryListener;
 import com.android.tradefed.result.InputStreamSource;
 import com.android.tradefed.result.LogDataType;
+import com.android.tradefed.result.LogFile;
 import com.android.tradefed.result.LogFileSaver;
 import com.android.tradefed.result.TestSummary;
 import com.android.tradefed.util.FileUtil;
@@ -43,9 +47,8 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.List;
 import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 /**
  * Writes results to an XML files in the CTS format.
@@ -54,7 +57,9 @@
  * <p/>
  * Outputs xml in format governed by the cts_result.xsd
  */
-public class CtsXmlResultReporter implements ITestInvocationListener {
+public class CtsXmlResultReporter
+        implements ITestInvocationListener, ITestSummaryListener, ILogSaverListener {
+
     private static final String LOG_TAG = "CtsXmlResultReporter";
 
     static final String TEST_RESULT_FILE_NAME = "testResult.xml";
@@ -69,6 +74,9 @@
     static final String PLAN_ATTR = "testPlan";
     static final String STARTTIME_ATTR = "starttime";
 
+    @Option(name = "quiet-output", description = "Mute display of test results.")
+    private boolean mQuietOutput = false;
+
     private static final String REPORT_DIR_NAME = "output-file-path";
     @Option(name=REPORT_DIR_NAME, description="root file system path to directory to store xml " +
             "test results and associated logs. If not specified, results will be stored at " +
@@ -83,28 +91,33 @@
     @Option(name = CtsTest.CONTINUE_OPTION, description = "the test result session to continue.")
     private Integer mContinueSessionId = null;
 
-    @Option(name = "quiet-output", description = "Mute display of test results.")
-    private boolean mQuietOutput = false;
-
     @Option(name = "result-server", description = "Server to publish test results.")
     private String mResultServer;
 
+    @Option(name = "include-test-log-tags", description = "Include test log tags in XML report.")
+    private boolean mIncludeTestLogTags = false;
+
     protected IBuildInfo mBuildInfo;
     private String mStartTime;
     private String mDeviceSerial;
     private TestResults mResults = new TestResults();
     private TestPackageResult mCurrentPkgResult = null;
+    private Test mCurrentTest = null;
     private boolean mIsDeviceInfoRun = false;
     private ResultReporter mReporter;
     private File mLogDir;
     private String mSuiteName;
-
-    private static final Pattern mCtsLogPattern = Pattern.compile("(.*)\\+\\+\\+\\+(.*)");
+    private String mReferenceUrl;
 
     public void setReportDir(File reportDir) {
         mReportDir = reportDir;
     }
 
+    /** Set whether to include TestLog tags in the XML reports. */
+    public void setIncludeTestLogTags(boolean include) {
+        mIncludeTestLogTags = include;
+    }
+
     /**
      * {@inheritDoc}
      */
@@ -212,6 +225,20 @@
     }
 
     /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void testLogSaved(String dataName, LogDataType dataType, InputStreamSource dataStream,
+            LogFile logFile) {
+        if (mIncludeTestLogTags && mCurrentTest != null) {
+            TestLog log = TestLog.fromDataName(dataName, logFile.getUrl());
+            if (log != null) {
+                mCurrentTest.addTestLog(log);
+            }
+        }
+    }
+
+    /**
      * Return the {@link LogFileSaver} to use.
      * <p/>
      * Exposed for unit testing.
@@ -220,27 +247,18 @@
         return new LogFileSaver(mLogDir);
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
-    public void testRunStarted(String name, int numTests) {
-        if (mCurrentPkgResult != null && !name.equals(mCurrentPkgResult.getAppPackageName())) {
-            // display results from previous run
-            logCompleteRun(mCurrentPkgResult);
-        }
-        mIsDeviceInfoRun = name.equals(DeviceInfoCollector.APP_PACKAGE_NAME);
-        if (mIsDeviceInfoRun) {
-            logResult("Collecting device info");
-        } else  {
-            if (mCurrentPkgResult == null || !name.equals(mCurrentPkgResult.getAppPackageName())) {
-                logResult("-----------------------------------------");
-                logResult("Test package %s started", name);
-                logResult("-----------------------------------------");
-            }
-            mCurrentPkgResult = mResults.getOrCreatePackage(name);
-        }
+    public void setLogSaver(ILogSaver logSaver) {
+      // Don't need to keep a reference to logSaver, because we don't save extra logs in this class.
+    }
 
+    @Override
+    public void testRunStarted(String id, int numTests) {
+        mIsDeviceInfoRun = DeviceInfoCollector.IDS.contains(id);
+        if (!mIsDeviceInfoRun) {
+            mCurrentPkgResult = mResults.getOrCreatePackage(id);
+            mCurrentPkgResult.setDeviceSerial(mDeviceSerial);
+        }
     }
 
     /**
@@ -248,15 +266,38 @@
      */
     @Override
     public void testStarted(TestIdentifier test) {
-        mCurrentPkgResult.insertTest(test);
+        if (!mIsDeviceInfoRun) {
+            mCurrentTest = mCurrentPkgResult.insertTest(test);
+        }
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public void testFailed(TestFailure status, TestIdentifier test, String trace) {
-        mCurrentPkgResult.reportTestFailure(test, CtsTestStatus.FAIL, trace);
+    public void testFailed(TestIdentifier test, String trace) {
+        if (!mIsDeviceInfoRun) {
+            mCurrentPkgResult.reportTestFailure(test, CtsTestStatus.FAIL, trace);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void testAssumptionFailure(TestIdentifier test, String trace) {
+        // TODO: do something different here?
+        if (!mIsDeviceInfoRun) {
+            mCurrentPkgResult.reportTestFailure(test, CtsTestStatus.FAIL, trace);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void testIgnored(TestIdentifier test) {
+        // TODO: ??
     }
 
     /**
@@ -264,36 +305,8 @@
      */
     @Override
     public void testEnded(TestIdentifier test, Map<String, String> testMetrics) {
-        collectCtsResults(test, testMetrics);
-        mCurrentPkgResult.reportTestEnded(test);
-        Test result = mCurrentPkgResult.findTest(test);
-        String stack = result.getStackTrace() == null ? "" : "\n" + result.getStackTrace();
-        logResult("%s#%s %s %s", test.getClassName(), test.getTestName(), result.getResult(),
-                stack);
-    }
-
-    /**
-     * Collect Cts results for both device and host tests to the package result.
-     * @param test test ran
-     * @param testMetrics test metrics which can contain performance result for device tests
-     */
-    private void collectCtsResults(TestIdentifier test, Map<String, String> testMetrics) {
-        // device test can have performance results in testMetrics
-        String perfResult = CtsReportUtil.getCtsResultFromMetrics(testMetrics);
-        // host test should be checked in CtsHostStore.
-        if (perfResult == null) {
-            perfResult = CtsHostStore.removeCtsResult(mDeviceSerial, test.toString());
-        }
-        if (perfResult != null) {
-            // CTS result is passed in Summary++++Details format.
-            // Extract Summary and Details, and pass them.
-            Matcher m = mCtsLogPattern.matcher(perfResult);
-            if (m.find()) {
-                mCurrentPkgResult.reportPerformanceResult(test, CtsTestStatus.PASS, m.group(1),
-                        m.group(2));
-            } else {
-                logResult("CTS Result unrecognizable:" + perfResult);
-            }
+        if (!mIsDeviceInfoRun) {
+            mCurrentPkgResult.reportTestEnded(test, testMetrics);
         }
     }
 
@@ -314,10 +327,6 @@
      */
     @Override
     public void invocationEnded(long elapsedTime) {
-        // display the results of the last completed run
-        if (mCurrentPkgResult != null) {
-            logCompleteRun(mCurrentPkgResult);
-        }
         if (mReportDir == null || mStartTime == null) {
             // invocationStarted must have failed, abort
             CLog.w("Unable to create XML report");
@@ -330,7 +339,7 @@
         zipResults(mReportDir);
 
         try {
-            mReporter.reportResult(reportFile);
+            mReporter.reportResult(reportFile, mReferenceUrl);
         } catch (IOException e) {
             CLog.e(e);
         }
@@ -344,17 +353,6 @@
         }
     }
 
-    private void logCompleteRun(TestPackageResult pkgResult) {
-        if (pkgResult.getAppPackageName().equals(DeviceInfoCollector.APP_PACKAGE_NAME)) {
-            logResult("Device info collection complete");
-            return;
-        }
-        logResult("%s package complete: Passed %d, Failed %d, Not Executed %d",
-                pkgResult.getAppPackageName(), pkgResult.countTests(CtsTestStatus.PASS),
-                pkgResult.countTests(CtsTestStatus.FAIL),
-                pkgResult.countTests(CtsTestStatus.NOT_EXECUTED));
-    }
-
     /**
      * Creates a report file and populates it with the report data from the completed tests.
      */
@@ -382,7 +380,7 @@
         } catch (IOException e) {
             Log.e(LOG_TAG, "Failed to generate report data");
         } finally {
-            StreamUtil.closeStream(stream);
+            StreamUtil.close(stream);
         }
     }
 
@@ -402,7 +400,6 @@
         serializer.attribute(ns, "endtime", endTime);
         serializer.attribute(ns, "version", CTS_RESULT_FILE_VERSION);
         serializer.attribute(ns, "suite", mSuiteName);
-
         mResults.serialize(serializer);
         // TODO: not sure why, but the serializer doesn't like this statement
         //serializer.endTag(ns, RESULT_TAG);
@@ -498,4 +495,17 @@
     public TestSummary getSummary() {
         return null;
     }
+
+    /**
+     * {@inheritDoc}
+     */
+     @Override
+     public void putSummary(List<TestSummary> summaries) {
+         // By convention, only store the first summary that we see as the summary URL.
+         if (summaries.isEmpty()) {
+             return;
+         }
+
+         mReferenceUrl = summaries.get(0).getSummary().getString();
+     }
 }
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/DeviceInfoResult.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/DeviceInfoResult.java
index dd91af0..0c947c3 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/DeviceInfoResult.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/DeviceInfoResult.java
@@ -358,7 +358,8 @@
                 DeviceInfoConstants.BUILD_MANUFACTURER, DeviceInfoConstants.BUILD_BOARD,
                 DeviceInfoConstants.BUILD_DEVICE, DeviceInfoConstants.PRODUCT_NAME,
                 DeviceInfoConstants.BUILD_ABI, DeviceInfoConstants.BUILD_ABI2,
-                DeviceInfoConstants.SCREEN_SIZE);
+                DeviceInfoConstants.BUILD_ABIS, DeviceInfoConstants.BUILD_ABIS_32,
+                DeviceInfoConstants.BUILD_ABIS_64, DeviceInfoConstants.SCREEN_SIZE);
     }
 
     private void combineMetrics(Map<String, String> metrics, String... keysToCombine) {
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/ITestResultRepo.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/ITestResultRepo.java
index d672f41..19b0540 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/ITestResultRepo.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/ITestResultRepo.java
@@ -41,7 +41,7 @@
     /**
      * Get the report directory for given result
      * @param sessionId
-     * @return
+     * @return A {@link File} representing the report directory for the given sessionId
      */
     public File getReportDir(int sessionId);
 
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/ITestSummary.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/ITestSummary.java
index 98494ee..e7041ec 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/ITestSummary.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/ITestSummary.java
@@ -23,43 +23,43 @@
     /**
      * @return the session id
      */
-    int getId();
+    public int getId();
 
     /**
      * @return the starting timestamp, also known as result directory name
      */
-    String getTimestamp();
+    public String getTimestamp();
 
     /**
      * @return the num of not executed tests
      */
-    int getNumIncomplete();
+    public int getNumIncomplete();
 
     /**
      * @return the number of failed tests
      */
-    int getNumFailed();
+    public int getNumFailed();
 
     /**
      * @return the number of passed tests
      */
-    int getNumPassed();
+    public int getNumPassed();
 
     /**
      * @return the test plan associated with result
      */
-    String getTestPlan();
+    public String getTestPlan();
 
     /**
      * Return the user-friendly displayed start time stored in result XML.
      * <p/>
      * Expected format: {@link TimeUtil#getTimestamp()}
      */
-    String getStartTime();
+    public String getStartTime();
 
     /**
      * @return a comma separated list of device serials associated with result
      */
-    String getDeviceSerials();
+    public String getDeviceSerials();
 
 }
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/IssueReporter.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/IssueReporter.java
index 9d903dd..ed5f238 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/IssueReporter.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/IssueReporter.java
@@ -58,13 +58,25 @@
     private String mProductName;
 
     @Override
-    public void testFailed(TestFailure status, TestIdentifier test, String trace) {
+    public void testFailed(TestIdentifier test, String trace) {
         mCurrentIssue = new Issue();
         mCurrentIssue.mTestName = test.toString();
         mCurrentIssue.mStackTrace = trace;
     }
 
     @Override
+    public void testAssumptionFailure(TestIdentifier test, String trace) {
+        mCurrentIssue = new Issue();
+        mCurrentIssue.mTestName = test.toString();
+        mCurrentIssue.mStackTrace = trace;
+    }
+
+    @Override
+    public void testIgnored(TestIdentifier test) {
+        // TODO: ??
+    }
+
+    @Override
     public void testLog(String dataName, LogDataType dataType, InputStreamSource dataStream) {
         if (dataName.startsWith("bug-")) {
             try {
@@ -194,7 +206,7 @@
     }
 
     @Override
-    public void testRunStarted(String name, int numTests) {
+    public void testRunStarted(String id, int numTests) {
     }
 
     @Override
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/PlanCreator.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/PlanCreator.java
index d263bc8..3881c0e 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/PlanCreator.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/PlanCreator.java
@@ -22,6 +22,7 @@
 import com.android.cts.tradefed.testtype.ITestPlan;
 import com.android.cts.tradefed.testtype.TestPackageRepo;
 import com.android.cts.tradefed.testtype.TestPlan;
+import com.android.cts.util.AbiUtils;
 import com.android.ddmlib.Log;
 import com.android.ddmlib.Log.LogLevel;
 import com.android.ddmlib.testrunner.TestIdentifier;
@@ -37,6 +38,7 @@
 import java.io.IOException;
 import java.util.Collection;
 import java.util.LinkedHashSet;
+import java.util.Set;
 
 /**
  * Class for creating test plans from CTS result XML.
@@ -88,8 +90,9 @@
      * {@link Option} values must all be set before this is called.
      * @throws ConfigurationException
      */
-    public void createAndSerializeDerivedPlan(CtsBuildHelper build) throws ConfigurationException {
-        ITestPlan derivedPlan = createDerivedPlan(build);
+    public void createAndSerializeDerivedPlan(CtsBuildHelper build, Set<String> abis)
+            throws ConfigurationException {
+        ITestPlan derivedPlan = createDerivedPlan(build, abis);
         if (derivedPlan != null) {
             try {
                 derivedPlan.serialize(new BufferedOutputStream(new FileOutputStream(mPlanFile)));
@@ -110,25 +113,24 @@
      * @return test plan
      * @throws ConfigurationException
      */
-    public ITestPlan createDerivedPlan(CtsBuildHelper build) throws ConfigurationException {
+    public ITestPlan createDerivedPlan(CtsBuildHelper build, Set<String> abis)
+            throws ConfigurationException {
         checkFields(build);
-        ITestPackageRepo pkgDefRepo = new TestPackageRepo(build.getTestCasesDir(),
-                mIncludeKnownFailures);
-        ITestPlan derivedPlan = new TestPlan(mPlanName);
+        ITestPackageRepo pkgDefRepo =
+                new TestPackageRepo(build.getTestCasesDir(), mIncludeKnownFailures);
+        ITestPlan derivedPlan = new TestPlan(mPlanName, abis);
         for (TestPackageResult pkg : mResult.getPackages()) {
             Collection<TestIdentifier> filteredTests = pkg.getTestsWithStatus(mResultFilter);
-            if (!filteredTests.isEmpty()) {
-                String pkgUri = pkg.getAppPackageName();
-                ITestPackageDef pkgDef = pkgDefRepo.getTestPackage(pkgUri);
-                if (pkgDef != null) {
-                    Collection<TestIdentifier> excludedTests = new LinkedHashSet<TestIdentifier>(
-                            pkgDef.getTests());
-                    excludedTests.removeAll(filteredTests);
-                    derivedPlan.addPackage(pkgUri);
-                    derivedPlan.addExcludedTests(pkgUri, excludedTests);
-                } else {
-                    CLog.e("Could not find package %s in repository", pkgUri);
-                }
+            String pkgId = pkg.getId();
+            ITestPackageDef pkgDef = pkgDefRepo.getTestPackage(pkgId);
+            if (pkgDef != null) {
+                Collection<TestIdentifier> excludedTests =
+                        new LinkedHashSet<TestIdentifier>(pkgDef.getTests());
+                excludedTests.removeAll(filteredTests);
+                derivedPlan.addPackage(pkgId);
+                derivedPlan.addExcludedTests(pkgId, excludedTests);
+            } else {
+                CLog.e("Could not find package %s in repository", pkgId);
             }
         }
         return derivedPlan;
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/ResultReporter.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/ResultReporter.java
index 199cbc5..39969d3 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/ResultReporter.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/ResultReporter.java
@@ -21,6 +21,8 @@
 import java.io.IOException;
 import java.io.InputStream;
 
+import javax.annotation.Nullable;
+
 /**
  * Class that sends a HTTP POST multipart/form-data request containing
  * the test result XML.
@@ -37,7 +39,7 @@
         mSuiteName = suiteName;
     }
 
-    public void reportResult(File reportFile) throws IOException {
+    public void reportResult(File reportFile, @Nullable String referenceUrl) throws IOException {
         if (isEmpty(mServerUrl)) {
             return;
         }
@@ -45,16 +47,19 @@
         InputStream input = new FileInputStream(reportFile);
         try {
             byte[] data = IssueReporter.getBytes(input, RESULT_XML_BYTES);
-            new MultipartForm(mServerUrl)
+            MultipartForm multipartForm = new MultipartForm(mServerUrl)
                     .addFormValue("suite", mSuiteName)
-                    .addFormFile("resultXml", "testResult.xml.gz", data)
-                    .submit();
+                    .addFormFile("resultXml", "testResult.xml.gz", data);
+            if (!isEmpty(referenceUrl)) {
+                multipartForm.addFormValue("referenceUrl", referenceUrl);
+            }
+            multipartForm.submit();
         } finally {
             input.close();
         }
     }
 
-    private boolean isEmpty(String value) {
+    private static boolean isEmpty(String value) {
         return value == null || value.trim().isEmpty();
     }
 }
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/Test.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/Test.java
index 8c5b8d1..12a2b29 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/Test.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/Test.java
@@ -16,13 +16,15 @@
 package com.android.cts.tradefed.result;
 
 import com.android.ddmlib.Log;
-import com.android.tradefed.result.TestResult;
+import com.android.cts.tradefed.result.TestLog.TestLogType;
 
 import org.kxml2.io.KXmlSerializer;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Data structure that represents a "Test" result XML element.
@@ -59,6 +61,12 @@
     private String mDetails;
 
     /**
+     * Log info for this test like a logcat dump or bugreport.
+     * Use *Locked methods instead of mutating this directly.
+     */
+    private List<TestLog> mTestLogs;
+
+    /**
      * Create an empty {@link Test}
      */
     public Test() {
@@ -77,6 +85,13 @@
     }
 
     /**
+     * Add a test log to this Test.
+     */
+    public void addTestLog(TestLog testLog) {
+        addTestLogLocked(testLog);
+    }
+
+    /**
      * Set the name of this {@link Test}
      */
     public void setName(String name) {
@@ -158,6 +173,8 @@
         serializer.attribute(CtsXmlResultReporter.ns, STARTTIME_ATTR, mStartTime);
         serializer.attribute(CtsXmlResultReporter.ns, ENDTIME_ATTR, mEndTime);
 
+        serializeTestLogsLocked(serializer);
+
         if (mMessage != null) {
             serializer.startTag(CtsXmlResultReporter.ns, SCENE_TAG);
             serializer.attribute(CtsXmlResultReporter.ns, MESSAGE_ATTR, mMessage);
@@ -329,10 +346,38 @@
                 mMessage = getAttribute(parser, MESSAGE_ATTR);
             } else if (eventType == XmlPullParser.START_TAG && parser.getName().equals(STACK_TAG)) {
                 mStackTrace = parser.nextText();
+            } else if (eventType == XmlPullParser.START_TAG && TestLog.isTag(parser.getName())) {
+                parseTestLog(parser);
             } else if (eventType == XmlPullParser.END_TAG && parser.getName().equals(TAG)) {
                 return;
             }
             eventType = parser.next();
         }
     }
+
+    /** Parse a TestLog entry from the parser positioned at a TestLog tag. */
+    private void parseTestLog(XmlPullParser parser) throws XmlPullParserException{
+        TestLog log = TestLog.fromXml(parser);
+        if (log == null) {
+            throw new XmlPullParserException("invalid XML: bad test log tag");
+        }
+        addTestLog(log);
+    }
+
+    /** Add a TestLog to the test in a thread safe manner. */
+    private synchronized void addTestLogLocked(TestLog testLog) {
+        if (mTestLogs == null) {
+            mTestLogs = new ArrayList<>(TestLogType.values().length);
+        }
+        mTestLogs.add(testLog);
+    }
+
+    /** Serialize the TestLogs of this test in a thread safe manner. */
+    private synchronized void serializeTestLogsLocked(KXmlSerializer serializer) throws IOException {
+        if (mTestLogs != null) {
+            for (TestLog log : mTestLogs) {
+                log.serialize(serializer);
+            }
+        }
+    }
 }
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/TestLog.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestLog.java
new file mode 100644
index 0000000..1210432
--- /dev/null
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestLog.java
@@ -0,0 +1,148 @@
+/*
+ * 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 com.android.cts.tradefed.result;
+
+import org.kxml2.io.KXmlSerializer;
+import org.xmlpull.v1.XmlPullParser;
+
+import java.io.IOException;
+
+import javax.annotation.Nullable;
+
+/**
+ * TestLog describes a log for a test. It corresponds to the "TestLog" XML element.
+ */
+class TestLog {
+
+    private static final String TAG = "TestLog";
+    private static final String TYPE_ATTR = "type";
+    private static final String URL_ATTR = "url";
+
+    /** Type of log. */
+    public enum TestLogType {
+        LOGCAT("logcat-"),
+        BUGREPORT("bug-"),
+
+        ;
+
+        // This enum restricts the type of logs reported back to the server,
+        // because we do not intend to support them all. Using an enum somewhat
+        // assures that we will only see these expected types on the server side.
+
+        /**
+         * Returns the TestLogType from an ILogSaver data name or null
+         * if the data name is not supported.
+         */
+        @Nullable
+        static TestLogType fromDataName(String dataName) {
+            if (dataName == null) {
+                return null;
+            }
+
+            for (TestLogType type : values()) {
+                if (dataName.startsWith(type.dataNamePrefix)) {
+                    return type;
+                }
+            }
+            return null;
+        }
+
+        private final String dataNamePrefix;
+
+        private TestLogType(String dataNamePrefix) {
+            this.dataNamePrefix = dataNamePrefix;
+        }
+
+        String getAttrValue() {
+            return name().toLowerCase();
+        }
+    }
+
+    /** Type of the log like LOGCAT or BUGREPORT. */
+    private final TestLogType mLogType;
+
+    /** Url pointing to the log file. */
+    private final String mUrl;
+
+    /** Create a TestLog from an ILogSaver callback. */
+    @Nullable
+    static TestLog fromDataName(String dataName, String url) {
+        TestLogType logType = TestLogType.fromDataName(dataName);
+        if (logType == null) {
+            return null;
+        }
+
+        if (url == null) {
+            return null;
+        }
+
+        return new TestLog(logType, url);
+    }
+
+    /** Create a TestLog from XML given a XmlPullParser positioned at the TestLog tag. */
+    @Nullable
+    static TestLog fromXml(XmlPullParser parser) {
+        String type = parser.getAttributeValue(null, TYPE_ATTR);
+        if (type == null) {
+            return null;
+        }
+
+        String url = parser.getAttributeValue(null, URL_ATTR);
+        if (url == null) {
+            return null;
+        }
+
+        try {
+            TestLogType logType = TestLogType.valueOf(type.toUpperCase());
+            return new TestLog(logType, url);
+        } catch (IllegalArgumentException e) {
+            return null;
+        }
+    }
+
+    /** Create a TestLog directly given a log type and url. */
+    public static TestLog of(TestLogType logType, String url) {
+        return new TestLog(logType, url);
+    }
+
+    private TestLog(TestLogType logType, String url) {
+        this.mLogType = logType;
+        this.mUrl = url;
+    }
+
+    /** Returns this TestLog's log type. */
+    TestLogType getLogType() {
+        return mLogType;
+    }
+
+    /** Returns this TestLog's URL. */
+    String getUrl() {
+        return mUrl;
+    }
+
+    /** Serialize the TestLog to XML. */
+    public void serialize(KXmlSerializer serializer) throws IOException {
+        serializer.startTag(CtsXmlResultReporter.ns, TAG);
+        serializer.attribute(CtsXmlResultReporter.ns, TYPE_ATTR, mLogType.getAttrValue());
+        serializer.attribute(CtsXmlResultReporter.ns, URL_ATTR, mUrl);
+        serializer.endTag(CtsXmlResultReporter.ns, TAG);
+    }
+
+    /** Returns true if the tag is a TestLog tag. */
+    public static boolean isTag(String tagName) {
+        return TAG.equals(tagName);
+    }
+}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/TestPackageResult.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestPackageResult.java
index 015a7ae..f5a3d02 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/TestPackageResult.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestPackageResult.java
@@ -15,10 +15,9 @@
  */
 package com.android.cts.tradefed.result;
 
-import android.tests.getinfo.DeviceInfoConstants;
-
-import com.android.cts.tradefed.device.DeviceInfoCollector;
 import com.android.cts.tradefed.testtype.CtsTest;
+import com.android.cts.tradefed.util.CtsHostStore;
+import com.android.cts.util.AbiUtils;
 import com.android.ddmlib.testrunner.TestIdentifier;
 import com.android.tradefed.log.LogUtil.CLog;
 
@@ -31,34 +30,55 @@
 import java.util.Collections;
 import java.util.Deque;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * Data structure for a CTS test package result.
  * <p/>
  * Provides methods to serialize to XML.
  */
-class TestPackageResult  extends AbstractXmlPullParser {
+class TestPackageResult extends AbstractXmlPullParser {
 
     static final String TAG = "TestPackage";
+
+    public static final String CTS_RESULT_KEY = "CTS_TEST_RESULT";
+
     private static final String DIGEST_ATTR = "digest";
     private static final String APP_PACKAGE_NAME_ATTR = "appPackageName";
     private static final String NAME_ATTR = "name";
+    private static final String ABI_ATTR = "abi";
     private static final String ns = CtsXmlResultReporter.ns;
     private static final String SIGNATURE_TEST_PKG = "android.tests.sigtest";
 
+    private static final Pattern mCtsLogPattern = Pattern.compile("(.*)\\+\\+\\+\\+(.*)");
+
+    private String mDeviceSerial;
     private String mAppPackageName;
     private String mName;
+    private String mAbi;
     private String mDigest;
 
     private Map<String, String> mMetrics = new HashMap<String, String>();
+    private Map<TestIdentifier, Map<String, String>> mTestMetrics = new HashMap<TestIdentifier, Map<String, String>>();
 
     private TestSuite mSuiteRoot = new TestSuite(null);
 
+    public void setDeviceSerial(String deviceSerial) {
+        mDeviceSerial = deviceSerial;
+    }
+
+    public String getDeviceSerial() {
+        return mDeviceSerial;
+    }
+
+    public String getId() {
+        return AbiUtils.createId(getAbi(), getAppPackageName());
+    }
+
     public void setAppPackageName(String appPackageName) {
         mAppPackageName = appPackageName;
     }
@@ -75,6 +95,14 @@
         return mName;
     }
 
+    public void setAbi(String abi) {
+        mAbi = abi;
+    }
+
+    public String getAbi() {
+        return mAbi;
+    }
+
     public void setDigest(String digest) {
         mDigest = digest;
     }
@@ -94,7 +122,6 @@
      * Adds a test result to this test package
      *
      * @param testId
-     * @param testResult
      */
     public Test insertTest(TestIdentifier testId) {
         return findTest(testId, true);
@@ -109,8 +136,8 @@
             // should never happen
             classNameSegments.add("UnknownTestClass");
         }
-            String testCaseName = classNameSegments.remove(classNameSegments.size()-1);
-            return mSuiteRoot.findTest(classNameSegments, testCaseName, testId.getTestName(), insertIfMissing);
+        String testCaseName = classNameSegments.remove(classNameSegments.size() - 1);
+        return mSuiteRoot.findTest(classNameSegments, testCaseName, testId.getTestName(), insertIfMissing);
     }
 
 
@@ -133,6 +160,7 @@
         serializer.startTag(ns, TAG);
         serializeAttribute(serializer, NAME_ATTR, mName);
         serializeAttribute(serializer, APP_PACKAGE_NAME_ATTR, mAppPackageName);
+        serializeAttribute(serializer, ABI_ATTR, mAbi);
         serializeAttribute(serializer, DIGEST_ATTR, getDigest());
         if (SIGNATURE_TEST_PKG.equals(mName)) {
             serializer.attribute(ns, "signatureCheck", "true");
@@ -170,6 +198,7 @@
         }
         setAppPackageName(getAttribute(parser, APP_PACKAGE_NAME_ATTR));
         setName(getAttribute(parser, NAME_ATTR));
+        setAbi(getAttribute(parser, ABI_ATTR));
         setDigest(getAttribute(parser, DIGEST_ATTR));
         int eventType = parser.getEventType();
         while (eventType != XmlPullParser.END_DOCUMENT) {
@@ -186,10 +215,10 @@
     }
 
     /**
-     * Return a list of {@link TestIdentifer}s contained in this result with the given status
+     * Return a list of {@link TestIdentifier}s contained in this result with the given status
      *
      * @param resultFilter the {@link CtsTestStatus} to filter by
-     * @return a collection of {@link TestIdentifer}s
+     * @return a collection of {@link TestIdentifier}s
      */
     public Collection<TestIdentifier> getTestsWithStatus(CtsTestStatus resultFilter) {
         Collection<TestIdentifier> tests = new LinkedList<TestIdentifier>();
@@ -200,63 +229,43 @@
 
     /**
      * Populate values in this package result from run metrics
-     * @param runResult
+     * @param metrics A map of metrics from the completed test run.
      */
     public void populateMetrics(Map<String, String> metrics) {
         String name = metrics.get(CtsTest.PACKAGE_NAME_METRIC);
         if (name != null) {
             setName(name);
         }
+        String abi = metrics.get(CtsTest.PACKAGE_ABI_METRIC);
+        if (abi != null) {
+            setAbi(abi);
+        }
         String digest = metrics.get(CtsTest.PACKAGE_DIGEST_METRIC);
         if (digest != null) {
             setDigest(digest);
         }
-        if (DeviceInfoCollector.APP_PACKAGE_NAME.equals(getAppPackageName())) {
-            storeDeviceMetrics(metrics);
-        } else {
-            mMetrics.putAll(metrics);
-        }
-    }
+        mMetrics.putAll(metrics);
 
-    /**
-     * Check that the provided device info metrics are consistent with the currently stored metrics.
-     * <p/>
-     * If any inconsistencies occur, logs errors and stores error messages in the metrics map
-     *
-     * @param metrics
-     */
-    private void storeDeviceMetrics(Map<String, String> metrics) {
-        // TODO centralize all the device metrics handling into a single class
-        if (mMetrics.isEmpty()) {
-            // nothing to check!
-            mMetrics.putAll(metrics);
-            return;
-        }
-        // ensure all the metrics we expect to be identical actually are
-        checkMetrics(metrics, DeviceInfoConstants.BUILD_FINGERPRINT,
-                DeviceInfoConstants.BUILD_MODEL, DeviceInfoConstants.BUILD_BRAND,
-                DeviceInfoConstants.BUILD_MANUFACTURER, DeviceInfoConstants.BUILD_BOARD,
-                DeviceInfoConstants.BUILD_DEVICE, DeviceInfoConstants.PRODUCT_NAME,
-                DeviceInfoConstants.BUILD_ABI, DeviceInfoConstants.BUILD_ABI2,
-                DeviceInfoConstants.SCREEN_SIZE);
-    }
-
-    private void checkMetrics(Map<String, String> metrics, String... keysToCheck) {
-        Set<String> keyCheckSet = new HashSet<String>();
-        Collections.addAll(keyCheckSet, keysToCheck);
-        for (Map.Entry<String, String> metricEntry : metrics.entrySet()) {
-            String currentValue = mMetrics.get(metricEntry.getKey());
-            if (keyCheckSet.contains(metricEntry.getKey()) && currentValue != null
-                    && !metricEntry.getValue().equals(currentValue)) {
-                CLog.e("Inconsistent info collected from devices. "
-                        + "Current result has %s='%s', Received '%s'. Are you sharding or " +
-                        "resuming a test run across different devices and/or builds?",
-                        metricEntry.getKey(), currentValue, metricEntry.getValue());
-                mMetrics.put(metricEntry.getKey(),
-                        String.format("ERROR: Inconsistent results: %s, %s",
-                                metricEntry.getValue(), currentValue));
-            } else {
-                mMetrics.put(metricEntry.getKey(), metricEntry.getValue());
+        // Collect performance results
+        for (TestIdentifier test : mTestMetrics.keySet()) {
+            // device test can have performance results in test metrics
+            String perfResult = mTestMetrics.get(test).get(CTS_RESULT_KEY);
+            // host test should be checked in CtsHostStore.
+            if (perfResult == null) {
+                perfResult = CtsHostStore.removeCtsResult(mDeviceSerial, mAbi, test.toString());
+            }
+            if (perfResult != null) {
+                // CTS result is passed in Summary++++Details format.
+                // Extract Summary and Details, and pass them.
+                Matcher m = mCtsLogPattern.matcher(perfResult);
+                if (m.find()) {
+                    Test result = findTest(test);
+                    result.setResultStatus(CtsTestStatus.PASS);
+                    result.setSummary(m.group(1));
+                    result.setDetails(m.group(2));
+                } else {
+                    CLog.e("CTS Result unrecognizable:" + perfResult);
+                }
             }
         }
     }
@@ -275,29 +284,22 @@
     }
 
     /**
-     * report performance result
-     * @param test
-     * @param status
-     * @param perf
-     */
-    public void reportPerformanceResult(TestIdentifier test, CtsTestStatus status, String summary, String details) {
-        Test result = findTest(test);
-        result.setResultStatus(status);
-        result.setSummary(summary);
-        result.setDetails(details);
-    }
-
-    /**
      * Report that the given test has completed.
      *
-     * @param test
+     * @param test The {@link TestIdentifier} of the completed test.
+     * @param testMetrics A map holding metrics about the completed test, if any.
      */
-    public void reportTestEnded(TestIdentifier test) {
+    public void reportTestEnded(TestIdentifier test, Map<String, String> testMetrics) {
         Test result = findTest(test);
         if (!result.getResult().equals(CtsTestStatus.FAIL)) {
             result.setResultStatus(CtsTestStatus.PASS);
         }
         result.updateEndTime();
+        if (mTestMetrics.containsKey(test)) {
+            CLog.e("Test metrics already contains key: " + test);
+        }
+        mTestMetrics.put(test, testMetrics);
+        CLog.i("Test metrics:" + testMetrics);
     }
 
     /**
@@ -311,9 +313,10 @@
     }
 
     /**
-     * @return
+     * @return A map holding the metrics from the test run.
      */
     public Map<String, String> getMetrics() {
         return mMetrics;
     }
+
 }
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/TestResults.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestResults.java
index 2f9eadd..8c1a5bd 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/TestResults.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestResults.java
@@ -16,6 +16,7 @@
 package com.android.cts.tradefed.result;
 
 import com.android.cts.tradefed.build.CtsBuildProvider;
+import com.android.cts.util.AbiUtils;
 import com.android.tradefed.log.LogUtil.CLog;
 
 import org.kxml2.io.KXmlSerializer;
@@ -49,7 +50,7 @@
     static final String NOT_EXECUTED_ATTR = "notExecuted";
     static final String FAILED_ATTR = "failed";
 
-    private Map<String, TestPackageResult> mPackageMap =
+    private Map<String, TestPackageResult> mPackageResults =
             new LinkedHashMap<String, TestPackageResult>();
     private DeviceInfoResult mDeviceInfo = new DeviceInfoResult();
 
@@ -68,10 +69,10 @@
                     TestPackageResult.TAG)) {
                 TestPackageResult pkg = new TestPackageResult();
                 pkg.parse(parser);
-                if (pkg.getAppPackageName() != null) {
-                    mPackageMap.put(pkg.getAppPackageName(), pkg);
+                if (pkg.getId() != null) {
+                    mPackageResults.put(pkg.getId(), pkg);
                 } else {
-                    CLog.w("Found package with no app package name");
+                    CLog.w("Found package with no id");
                 }
             }
             eventType = parser.next();
@@ -82,17 +83,16 @@
      * @return the list of {@link TestPackageResult}.
      */
     public Collection<TestPackageResult> getPackages() {
-        return mPackageMap.values();
+        return mPackageResults.values();
     }
 
     /**
      * Count the number of tests with given status
-     * @param pass
-     * @return
+     * @param status
      */
     public int countTests(CtsTestStatus status) {
         int total = 0;
-        for (TestPackageResult result : mPackageMap.values()) {
+        for (TestPackageResult result : mPackageResults.values()) {
             total += result.countTests(status);
         }
         return total;
@@ -109,7 +109,7 @@
         serializeHostInfo(serializer);
         serializeTestSummary(serializer);
         // sort before serializing
-        List<TestPackageResult> pkgs = new ArrayList<TestPackageResult>(mPackageMap.values());
+        List<TestPackageResult> pkgs = new ArrayList<TestPackageResult>(mPackageResults.values());
         Collections.sort(pkgs, new PkgComparator());
         for (TestPackageResult r : pkgs) {
             r.serialize(serializer);
@@ -174,27 +174,25 @@
 
     private static class PkgComparator implements Comparator<TestPackageResult> {
 
-        /**
-         * {@inheritDoc}
-         */
         @Override
-        public int compare(TestPackageResult o1, TestPackageResult o2) {
-            return o1.getAppPackageName().compareTo(o2.getAppPackageName());
+        public int compare(TestPackageResult lhs, TestPackageResult rhs) {
+            return lhs.getId().compareTo(rhs.getId());
         }
-
     }
 
     /**
-     * Return existing package with given app package name. If not found, create a new one.
-     * @param name
+     * Return existing package with given id. If not found, create a new one.
+     * @param id
      * @return
      */
-    public TestPackageResult getOrCreatePackage(String appPackageName) {
-        TestPackageResult pkgResult = mPackageMap.get(appPackageName);
+    public TestPackageResult getOrCreatePackage(String id) {
+        TestPackageResult pkgResult = mPackageResults.get(id);
         if (pkgResult == null) {
             pkgResult = new TestPackageResult();
-            pkgResult.setAppPackageName(appPackageName);
-            mPackageMap.put(appPackageName, pkgResult);
+            String[] abiAndName = AbiUtils.parseId(id);
+            pkgResult.setAbi(abiAndName[0]);
+            pkgResult.setAppPackageName(abiAndName[1]);
+            mPackageResults.put(id, pkgResult);
         }
         return pkgResult;
     }
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/TestSuite.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestSuite.java
index df1dceb..ca287ca 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/TestSuite.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestSuite.java
@@ -16,7 +16,6 @@
 package com.android.cts.tradefed.result;
 
 import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.tradefed.result.TestResult;
 
 import org.kxml2.io.KXmlSerializer;
 import org.xmlpull.v1.XmlPullParser;
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/Abi.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/Abi.java
new file mode 100644
index 0000000..926e14b
--- /dev/null
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/Abi.java
@@ -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.
+ */
+package com.android.cts.tradefed.testtype;
+
+import com.android.tradefed.testtype.IAbi;
+/**
+ * A class representing an ABI.
+ */
+public class Abi implements IAbi {
+
+    private String mName;
+    private String mBitness;
+
+    public Abi(String name, String bitness) {
+        mName = name;
+        mBitness = bitness;
+    }
+
+    @Override
+    public String getName() {
+        return mName;
+    }
+
+    @Override
+    public String getBitness() {
+        return mBitness;
+    }
+
+}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/AccessibilityServiceTestRunner.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/AccessibilityServiceTestRunner.java
index 4cfd263..eafd608 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/AccessibilityServiceTestRunner.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/AccessibilityServiceTestRunner.java
@@ -16,8 +16,8 @@
 
 package com.android.cts.tradefed.testtype;
 
-import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.tradefed.build.IBuildInfo;
+import com.android.cts.util.AbiUtils;
+import com.android.ddmlib.Log;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.result.ITestInvocationListener;
 import com.android.tradefed.util.FileUtil;
@@ -39,7 +39,10 @@
  * maintained so cts-tradefed can run against older CTS builds that still
  * require this class.
  */
-public class AccessibilityServiceTestRunner extends InstrumentationApkTest {
+@Deprecated
+public class AccessibilityServiceTestRunner extends CtsInstrumentationApkTest {
+
+    private static final String LOG_TAG = AccessibilityServiceTestRunner.class.getSimpleName();
 
     private static final String DELEGATING_ACCESSIBLITY_SERVICE_PACKAGE_NAME =
         "android.accessibilityservice.delegate";
@@ -50,14 +53,6 @@
     private static final String DELEGATING_ACCESSIBLITY_SERVICE_APK =
         "CtsDelegatingAccessibilityService.apk";
 
-    private CtsBuildHelper mCtsBuild;
-
-    @Override
-    public void setBuild(IBuildInfo build) {
-        super.setBuild(build);
-        mCtsBuild  = CtsBuildHelper.createBuildHelper(build);
-    }
-
     @Override
     public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
         beforeTest();
@@ -77,7 +72,8 @@
 
     private void installApkAndAssert(String apkName) throws DeviceNotAvailableException {
         File file = FileUtil.getFileForPath(mCtsBuild.getTestCasesDir(), apkName);
-        String errorMessage = getDevice().installPackage(file, true);
+        String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+        String errorMessage = getDevice().installPackage(file, true, options);
         TestCase.assertNull("Error installing: " + apkName, errorMessage);
     }
 
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/AccessibilityTestRunner.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/AccessibilityTestRunner.java
index 2a4239a..9ba4109 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/AccessibilityTestRunner.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/AccessibilityTestRunner.java
@@ -16,9 +16,9 @@
 
 package com.android.cts.tradefed.testtype;
 
-import com.android.cts.tradefed.build.CtsBuildHelper;
 import com.android.cts.tradefed.targetprep.SettingsToggler;
-import com.android.tradefed.build.IBuildInfo;
+import com.android.cts.util.AbiUtils;
+import com.android.ddmlib.Log;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.result.ITestInvocationListener;
@@ -37,7 +37,9 @@
  * these services, running the tests, disabling the services, and removing
  * the accessibility services package.
  */
-public class AccessibilityTestRunner extends InstrumentationApkTest {
+public class AccessibilityTestRunner extends CtsInstrumentationApkTest {
+
+    private static final String LOG_TAG = AccessibilityTestRunner.class.getSimpleName();
 
     private static final String SOME_ACCESSIBLITY_SERVICES_PACKAGE_NAME =
         "android.view.accessibility.services";
@@ -51,14 +53,6 @@
     private static final String SOME_ACCESSIBLITY_SERVICES_APK =
         "CtsSomeAccessibilityServices.apk";
 
-    private CtsBuildHelper mCtsBuild;
-
-    @Override
-    public void setBuild(IBuildInfo build) {
-        super.setBuild(build);
-        mCtsBuild  = CtsBuildHelper.createBuildHelper(build);
-    }
-
     @Override
     public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
         beforeTest();
@@ -78,7 +72,8 @@
 
     private void installApkAndAssert(String apkName) throws DeviceNotAvailableException {
         File file = FileUtil.getFileForPath(mCtsBuild.getTestCasesDir(), apkName);
-        String errorMessage = getDevice().installPackage(file, true);
+        String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+        String errorMessage = getDevice().installPackage(file, true, options);
         TestCase.assertNull("Error installing: " + apkName, errorMessage);
     }
 
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsInstrumentationApkTest.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsInstrumentationApkTest.java
new file mode 100644
index 0000000..66d1135f
--- /dev/null
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsInstrumentationApkTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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 com.android.cts.tradefed.testtype;
+
+import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.cts.util.AbiUtils;
+import com.android.ddmlib.Log;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.testtype.InstrumentationTest;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * An {@link InstrumentationTest} that will install CTS apks
+ * before test execution, and uninstall on execution completion.
+ */
+public class CtsInstrumentationApkTest extends InstrumentationTest implements IBuildReceiver {
+
+    private static final String LOG_TAG = "CtsInstrumentationApkTest";
+
+    /** the file names of the CTS apks to install */
+    private Collection<String> mInstallFileNames = new ArrayList<String>();
+    private Collection<String> mUninstallPackages = new ArrayList<String>();
+    protected CtsBuildHelper mCtsBuild = null;
+    protected IAbi mAbi = null;
+
+    /**
+     * @param abi the ABI to run the test on
+     */
+    public void setAbi(IAbi abi) {
+        mAbi = abi;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setBuild(IBuildInfo build) {
+        mCtsBuild = CtsBuildHelper.createBuildHelper(build);
+    }
+
+    /**
+     * Add an apk to install.
+     *
+     * @param apkFileName the apk file name
+     * @param packageName the apk's Android package name
+     */
+    public void addInstallApk(String apkFileName, String packageName) {
+        mInstallFileNames.add(apkFileName);
+        mUninstallPackages.add(packageName);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void run(final ITestInvocationListener listener)
+            throws DeviceNotAvailableException {
+        ITestDevice testDevice = getDevice();
+
+        if (testDevice == null) {
+            Log.e(LOG_TAG, "Missing device.");
+            return;
+        }
+        if (mCtsBuild == null) {
+            Log.e(LOG_TAG, "Missing build");
+            return;
+        }
+        boolean success = true;
+        for (String apkFileName : mInstallFileNames) {
+            Log.d(LOG_TAG, String.format("Installing %s on %s", apkFileName,
+                    testDevice.getSerialNumber()));
+            try {
+                File apkFile = mCtsBuild.getTestApp(apkFileName);
+                String errorCode = null;
+                String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+                errorCode = testDevice.installPackage(apkFile, true, options);
+                if (errorCode != null) {
+                    Log.e(LOG_TAG, String.format("Failed to install %s on %s. Reason: %s",
+                          apkFileName, testDevice.getSerialNumber(), errorCode));
+                    success = false;
+                }
+            } catch (FileNotFoundException e) {
+                Log.e(LOG_TAG, String.format("Could not find file %s", apkFileName));
+                success = false;
+            }
+        }
+        if (success) {
+            super.run(listener);
+        }
+        for (String packageName : mUninstallPackages) {
+            Log.d(LOG_TAG, String.format("Uninstalling %s on %s", packageName,
+                    testDevice.getSerialNumber()));
+            testDevice.uninstallPackage(packageName);
+        }
+    }
+}
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 48f4773..ce48664 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
@@ -20,6 +20,7 @@
 import com.android.cts.tradefed.device.DeviceInfoCollector;
 import com.android.cts.tradefed.result.CtsTestStatus;
 import com.android.cts.tradefed.result.PlanCreator;
+import com.android.cts.util.AbiUtils;
 import com.android.ddmlib.Log;
 import com.android.ddmlib.Log.LogLevel;
 import com.android.ddmlib.testrunner.TestIdentifier;
@@ -27,6 +28,7 @@
 import com.android.tradefed.config.ConfigurationException;
 import com.android.tradefed.config.Option;
 import com.android.tradefed.config.Option.Importance;
+import com.android.tradefed.config.OptionCopier;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.device.TestDeviceOptions;
@@ -35,11 +37,13 @@
 import com.android.tradefed.result.InputStreamSource;
 import com.android.tradefed.result.LogDataType;
 import com.android.tradefed.result.ResultForwarder;
+import com.android.tradefed.testtype.IAbi;
 import com.android.tradefed.testtype.IBuildReceiver;
 import com.android.tradefed.testtype.IDeviceTest;
 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;
 
@@ -53,15 +57,16 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
-import java.util.Queue;
 import java.util.Set;
 
+
 /**
  * A {@link Test} for running CTS tests.
  * <p/>
@@ -74,14 +79,14 @@
     private static final String PACKAGE_OPTION = "package";
     private static final String CLASS_OPTION = "class";
     private static final String METHOD_OPTION = "method";
+    private static final String TEST_OPTION = "test";
     public static final String CONTINUE_OPTION = "continue-session";
     public static final String RUN_KNOWN_FAILURES_OPTION = "run-known-failures";
 
     public static final String PACKAGE_NAME_METRIC = "packageName";
+    public static final String PACKAGE_ABI_METRIC = "packageAbi";
     public static final String PACKAGE_DIGEST_METRIC = "packageDigest";
 
-    private ITestDevice mDevice;
-
     @Option(name = PLAN_OPTION, description = "the test plan to run.",
             importance = Importance.IF_UNSET)
     private String mPlanName = null;
@@ -102,6 +107,10 @@
             importance = Importance.IF_UNSET)
     private String mMethodName = null;
 
+    @Option(name = TEST_OPTION, shortName = 't', description = "run a specific test",
+            importance = Importance.IF_UNSET)
+    private String mTestName = null;
+
     @Option(name = CONTINUE_OPTION,
             description = "continue a previous test session.",
             importance = Importance.IF_UNSET)
@@ -157,24 +166,48 @@
             "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.")
     private int mMaxLogcatBytes = 500 * 1024; // 500K
 
-    private long mPrevRebootTime; // last reboot time
+    @Option(name = "collect-deqp-logs", description =
+            "Collect dEQP logs from the device.")
+    private boolean mCollectDeqpLogs = false;
+
+    @Option(name = "min-pre-reboot-package-count", description =
+            "The minimum number of packages to require a pre test reboot")
+
+    private int mMinPreRebootPackageCount = 2;
+    private final int mShardAssignment;
+    private final int mTotalShards;
+    private ITestDevice mDevice = null;
+    private CtsBuildHelper mCtsBuild = null;
+    private IBuildInfo mBuildInfo = null;
+    // last reboot time
+    private long mPrevRebootTime;
+    // The list of packages to run. populated in {@code setupTestPackageList}
+    // This is a member variable so that run can be called more than once
+    // and the test run is resumed.
+    private List<TestPackage> mTestPackageList = new ArrayList<>();
+    // The index in the pacakge list of the last test to complete
+    private int mLastTestPackageIndex = 0;
 
     /** data structure for a {@link IRemoteTest} and its known tests */
-    class TestPackage {
+    static class TestPackage {
         private final IRemoteTest mTestForPackage;
-        private final Collection<TestIdentifier> mKnownTests;
         private final ITestPackageDef mPackageDef;
+        private final Collection<TestIdentifier> mKnownTests;
 
-        TestPackage(ITestPackageDef packageDef, IRemoteTest testForPackage,
-                Collection<TestIdentifier> knownTests) {
+        TestPackage(ITestPackageDef packageDef, IRemoteTest testForPackage) {
             mPackageDef = packageDef;
             mTestForPackage = testForPackage;
-            mKnownTests = knownTests;
+            mKnownTests = packageDef.getTests();
         }
 
         IRemoteTest getTestForPackage() {
@@ -190,10 +223,17 @@
         }
 
         /**
-         * Return the test run name that should be used for the TestPackage
+         * @return the test run name that should be used for the TestPackage.
          */
         String getTestRunName() {
-            return mPackageDef.getUri();
+            return mPackageDef.getId();
+        }
+
+        /**
+         * @return the ABI on which the test will run.
+         */
+        IAbi getAbi() {
+            return mPackageDef.getAbi();
         }
     }
 
@@ -209,8 +249,8 @@
         }
 
         @Override
-        public void testFailed(TestFailure status, TestIdentifier test, String trace) {
-            super.testFailed(status, test, trace);
+        public void testFailed(TestIdentifier test, String trace) {
+            super.testFailed(test, trace);
             InputStreamSource bugSource = mDevice.getBugreport();
             super.testLog(String.format("bug-%s_%s", test.getClassName(), test.getTestName()),
                     LogDataType.TEXT, bugSource);
@@ -233,8 +273,8 @@
         }
 
         @Override
-        public void testFailed(TestFailure status, TestIdentifier test, String trace) {
-            super.testFailed(status, test, trace);
+        public void testFailed(TestIdentifier test, String trace) {
+            super.testFailed(test, trace);
             // sleep a small amount of time to ensure test failure stack trace makes it into logcat
             // capture
             RunUtil.getDefault().sleep(10);
@@ -258,8 +298,8 @@
         }
 
         @Override
-        public void testFailed(TestFailure status, TestIdentifier test, String trace) {
-            super.testFailed(status, test, trace);
+        public void testFailed(TestIdentifier test, String trace) {
+            super.testFailed(test, trace);
 
             try {
                 InputStreamSource screenSource = mDevice.getScreenshot();
@@ -274,11 +314,28 @@
         }
     }
 
-    /** list of remaining tests to execute */
-    private List<TestPackage> mRemainingTestPkgs = null;
+    /**
+     * Create a new {@link CtsTest} that will run the default list of {@link TestPackage}s.
+     */
+    public CtsTest() {
+        this(0 /*shardAssignment*/, 1 /*totalShards*/);
+    }
 
-    private CtsBuildHelper mCtsBuild = null;
-    private IBuildInfo mBuildInfo = null;
+    /**
+     * Create a new {@link CtsTest} that will run the given {@link List} of {@link TestPackage}s.
+     */
+    public CtsTest(int shardAssignment, int totalShards) {
+        if (shardAssignment < 0) {
+            throw new IllegalArgumentException(
+                "shardAssignment cannot be negative. found:" + shardAssignment);
+        }
+        if (totalShards < 1) {
+            throw new IllegalArgumentException(
+                "shardAssignment must be at least 1. found:" + totalShards);
+        }
+        this.mShardAssignment = shardAssignment;
+        this.mTotalShards = totalShards;
+    }
 
     /**
      * {@inheritDoc}
@@ -351,6 +408,15 @@
     }
 
     /**
+     * Set the test name to run e.g. android.test.cts.SampleTest#testSample
+     * <p/>
+     * Exposed for unit testing
+     */
+    void setTestName(String testName) {
+        mTestName = testName;
+    }
+
+    /**
      * Sets the test session id to continue.
      * <p/>
      * Exposed for unit testing
@@ -380,8 +446,6 @@
      * Set the CTS build container.
      * <p/>
      * Exposed so unit tests can mock the provided build.
-     *
-     * @param buildHelper
      */
     void setBuildHelper(CtsBuildHelper buildHelper) {
         mCtsBuild = buildHelper;
@@ -396,64 +460,81 @@
             throw new IllegalArgumentException("missing device");
         }
 
-        if (mRemainingTestPkgs == null) {
-            checkFields();
-            mRemainingTestPkgs = buildTestsToRun();
+        Set<String> abiSet = getAbis();
+        if (abiSet == null || abiSet.isEmpty()) {
+            throw new IllegalArgumentException("could not get device's ABIs");
         }
+        Log.logAndDisplay(LogLevel.INFO, LOG_TAG, "ABIs: " + abiSet);
+
+        checkFields();
+        setupTestPackageList(abiSet);
         if (mBugreport) {
-            FailedTestBugreportGenerator bugListener = new FailedTestBugreportGenerator(listener,
-                    getDevice());
-            listener = bugListener;
+            listener = new FailedTestBugreportGenerator(listener, getDevice());
         }
         if (mScreenshotOnFailures) {
-            FailedTestScreenshotGenerator screenListener = new FailedTestScreenshotGenerator(
-                    listener, getDevice());
-            listener = screenListener;
+            listener = new FailedTestScreenshotGenerator(listener, getDevice());
         }
         if (mLogcatOnFailures) {
-            FailedTestLogcatGenerator logcatListener = new FailedTestLogcatGenerator(
-                    listener, getDevice(), mMaxLogcatBytes);
-            listener = logcatListener;
+            listener = new FailedTestLogcatGenerator(listener, getDevice(), mMaxLogcatBytes);
+        }
+
+        // Setup the a map of Test id to ResultFilter
+        Map<String, ResultFilter> filterMap = new HashMap<>();
+        int totalTestCount = 0;
+        for (TestPackage testPackage : mTestPackageList) {
+            ResultFilter resultFilter = new ResultFilter(listener, testPackage);
+            totalTestCount += resultFilter.getKnownTestCount();
+            filterMap.put(testPackage.getPackageDef().getId(), resultFilter);
         }
 
         // collect and install the prerequisiteApks first, to save time when multiple test
-        // packages are using the same prerequisite apk (I'm looking at you, CtsTestStubs!)
-        Collection<String> prerequisiteApks = getPrerequisiteApks(mRemainingTestPkgs);
-        Collection<String> uninstallPackages = getPrerequisitePackageNames(mRemainingTestPkgs);
-        ResultFilter filter = new ResultFilter(listener, mRemainingTestPkgs);
+        // packages are using the same prerequisite apk
+        Map<String, Set<String>> prerequisiteApks = getPrerequisiteApks(mTestPackageList, abiSet);
+        Collection<String> uninstallPackages = getPrerequisitePackageNames(mTestPackageList);
 
         try {
-            installPrerequisiteApks(prerequisiteApks);
-
             // always collect the device info, even for resumed runs, since test will likely be
             // running on a different device
             collectDeviceInfo(getDevice(), mCtsBuild, listener);
-            if (mRemainingTestPkgs.size() > 1 && !mDisableReboot) {
-                Log.i(LOG_TAG, "Initial reboot for multiple packages");
-                rebootDevice();
-            }
+            preRebootIfNecessary(mTestPackageList);
+
             mPrevRebootTime = System.currentTimeMillis();
+            int remainingPackageCount = mTestPackageList.size();
+            Log.logAndDisplay(LogLevel.INFO, LOG_TAG,
+                String.format("Start test run of %,d packages, containing %,d tests",
+                    remainingPackageCount, totalTestCount));
+            IAbi currentAbi = null;
 
-            while (!mRemainingTestPkgs.isEmpty()) {
-                TestPackage knownTests = mRemainingTestPkgs.get(0);
+            for (int i = mLastTestPackageIndex; i < mTestPackageList.size(); i++) {
+                TestPackage testPackage = mTestPackageList.get(i);
 
-                IRemoteTest test = knownTests.getTestForPackage();
-                if (test instanceof IDeviceTest) {
-                    ((IDeviceTest)test).setDevice(getDevice());
+                if (currentAbi == null ||
+                    !currentAbi.getName().equals(testPackage.getAbi().getName())) {
+                    currentAbi = testPackage.getAbi();
+                    installPrerequisiteApks(
+                        prerequisiteApks.get(currentAbi.getName()), currentAbi);
                 }
+
+                IRemoteTest test = testPackage.getTestForPackage();
                 if (test instanceof IBuildReceiver) {
-                    ((IBuildReceiver)test).setBuild(mBuildInfo);
+                    ((IBuildReceiver) test).setBuild(mBuildInfo);
+                }
+                if (test instanceof IDeviceTest) {
+                    ((IDeviceTest) test).setDevice(getDevice());
+                }
+                if (test instanceof DeqpTestRunner) {
+                    ((DeqpTestRunner)test).setCollectLogs(mCollectDeqpLogs);
                 }
 
-                forwardPackageDetails(knownTests.getPackageDef(), listener);
-                test.run(filter);
-                mRemainingTestPkgs.remove(0);
-                if (mRemainingTestPkgs.size() > 0) {
-                    rebootIfNecessary(knownTests, mRemainingTestPkgs.get(0));
-                    // remove artifacts like status bar from the previous test.
-                    // But this cannot dismiss dialog popped-up.
+                forwardPackageDetails(testPackage.getPackageDef(), listener);
+                test.run(filterMap.get(testPackage.getPackageDef().getId()));
+                if (i < mTestPackageList.size() - 1) {
+                    TestPackage nextPackage = mTestPackageList.get(i + 1);
+                    rebootIfNecessary(testPackage, nextPackage);
                     changeToHomeScreen();
                 }
+                // Track of the last complete test package index for resume
+                mLastTestPackageIndex = i;
             }
 
             if (mScreenshot) {
@@ -467,11 +548,61 @@
 
             uninstallPrequisiteApks(uninstallPackages);
 
+        } catch (RuntimeException e) {
+            CLog.e(e);
+            throw e;
+        } catch (Error e) {
+            CLog.e(e);
+            throw e;
         } finally {
-            filter.reportUnexecutedTests();
+            for (ResultFilter filter : filterMap.values()) {
+                filter.reportUnexecutedTests();
+            }
         }
     }
 
+    /**
+     * @param allTestPackageDefList The package list to filter
+     * @param deviceAbiSet The ABIs supported by the device being tested
+     * @return A {@link List} of {@link ITestPackageDef}s that should be tested
+     */
+    private static List<ITestPackageDef> filterByAbi(
+            List<ITestPackageDef> allTestPackageDefList, Set<String> deviceAbiSet) {
+        List<ITestPackageDef> filteredTestPackageDefList = new LinkedList<>();
+        for (ITestPackageDef testPackageDef : allTestPackageDefList) {
+            if (deviceAbiSet.contains(testPackageDef.getAbi().getName())) {
+                // We only need test packages that are not empty and of matching ABIs
+                filteredTestPackageDefList.add(testPackageDef);
+            }
+        }
+        return filteredTestPackageDefList;
+    }
+
+    /** Reboot then the device iff the list of packages exceeds the minimum */
+    private void preRebootIfNecessary(List<TestPackage> testPackageList)
+            throws DeviceNotAvailableException {
+        if (mDisableReboot) {
+            return;
+        }
+
+        Set<String> packageNameSet = new HashSet<>();
+        for (TestPackage testPackage : testPackageList) {
+            // Parse the package name
+            packageNameSet.add(AbiUtils.parseTestName(testPackage.getPackageDef().getId()));
+        }
+        if (packageNameSet.size() < mMinPreRebootPackageCount) {
+            // There is actually only one unique package name. No need to reboot.
+            return;
+        }
+
+        // Reboot is needed
+        Log.logAndDisplay(LogLevel.INFO, LOG_TAG,
+            String.format("Pre-test reboot (%,d packages). Use --disable-reboot to skip",
+                packageNameSet.size()));
+
+        rebootDevice();
+    }
+
     private void rebootIfNecessary(TestPackage testFinished, TestPackage testToRun)
             throws DeviceNotAvailableException {
         // If there comes spurious failure like INJECT_EVENTS for a package,
@@ -486,21 +617,19 @@
                 "CtsViewTestCases",
                 "CtsWidgetTestCases" );
         long intervalInMSec = mRebootIntervalMin * 60 * 1000;
-        if (mDevice.getSerialNumber().startsWith("emulator-")) {
+        if (mDisableReboot || mDevice.getSerialNumber().startsWith("emulator-")) {
             return;
         }
-        if (!mDisableReboot) {
-            long currentTime = System.currentTimeMillis();
-            if (((currentTime - mPrevRebootTime) > intervalInMSec) ||
-                    rebootAfterList.contains(testFinished.getPackageDef().getName()) ||
-                    rebootBeforeList.contains(testToRun.getPackageDef().getName()) ) {
-                Log.i(LOG_TAG,
-                        String.format("Rebooting after running package %s, before package %s",
-                                testFinished.getPackageDef().getName(),
-                                testToRun.getPackageDef().getName()));
-                rebootDevice();
-                mPrevRebootTime = System.currentTimeMillis();
-            }
+        long currentTime = System.currentTimeMillis();
+        if (((currentTime - mPrevRebootTime) > intervalInMSec) ||
+                rebootAfterList.contains(testFinished.getPackageDef().getName()) ||
+                rebootBeforeList.contains(testToRun.getPackageDef().getName()) ) {
+            Log.i(LOG_TAG,
+                    String.format("Rebooting after running package %s, before package %s",
+                            testFinished.getPackageDef().getName(),
+                            testToRun.getPackageDef().getName()));
+            rebootDevice();
+            mPrevRebootTime = System.currentTimeMillis();
         }
     }
 
@@ -528,6 +657,10 @@
         }
     }
 
+    /**
+     * Remove artifacts like status bar from the previous test.
+     * But this cannot dismiss dialog popped-up.
+     */
     private void changeToHomeScreen() throws DeviceNotAvailableException {
         final String homeCmd = "input keyevent 3";
 
@@ -538,112 +671,128 @@
             //ignore
         }
     }
-    /**
-     * Build the list of test packages to run
-     */
-    private List<TestPackage> buildTestsToRun() {
-        List<TestPackage> testPkgList = new LinkedList<TestPackage>();
-        try {
-            ITestPackageRepo testRepo = createTestCaseRepo();
-            Collection<ITestPackageDef> testPkgDefs = getTestPackagesToRun(testRepo);
 
-            for (ITestPackageDef testPkgDef : testPkgDefs) {
-                addTestPackage(testPkgList, testPkgDef);
+    /**
+     * Set {@code mTestPackageList} to the list of test packages to run filtered by ABI.
+     */
+    private void setupTestPackageList(Set<String> abis) throws DeviceNotAvailableException {
+        if (!mTestPackageList.isEmpty()) {
+            Log.logAndDisplay(LogLevel.INFO, LOG_TAG, "Resume tests using existing package list");
+            return;
+        }
+        try {
+            // Collect ALL tests
+            ITestPackageRepo testRepo = createTestCaseRepo();
+            List<ITestPackageDef> testPkgDefs = new ArrayList<>(getAvailableTestPackages(testRepo));
+            testPkgDefs = filterByAbi(testPkgDefs, abis);
+            // Note: run() relies on the fact that the list is reliably sorted for sharding purposes
+            Collections.sort(testPkgDefs);
+            // Create test package list.
+            List<TestPackage> testPackageList = new ArrayList<>();
+            for (ITestPackageDef testPackageDef : testPkgDefs) {
+                // Note: createTest filters the test list inside of testPackageDef by exclusion list
+                IRemoteTest testForPackage = testPackageDef.createTest(mCtsBuild.getTestCasesDir());
+                if (testPackageDef.getTests().size() > 0) {
+                    testPackageList.add(new TestPackage(testPackageDef, testForPackage));
+                }
             }
-            if (testPkgList.isEmpty()) {
-                Log.logAndDisplay(LogLevel.WARN, LOG_TAG, "No tests to run");
+
+            // Filter by shard
+            int numTestPackages = testPackageList.size();
+            int totalShards = Math.min(mTotalShards, numTestPackages);
+
+            List<TestPackage> shardTestPackageList = new ArrayList<>();
+            for (int i = mShardAssignment; i < numTestPackages; i += totalShards) {
+                shardTestPackageList.add(testPackageList.get(i));
             }
+            mTestPackageList.addAll(shardTestPackageList);
         } catch (FileNotFoundException e) {
-            throw new IllegalArgumentException("failed to find CTS plan file", e);
+            throw new IllegalArgumentException("failed to find XTS plan file", e);
         } catch (ParseException e) {
-            throw new IllegalArgumentException("failed to parse CTS plan file", e);
+            throw new IllegalArgumentException("failed to parse XTS plan file", e);
         } catch (ConfigurationException e) {
             throw new IllegalArgumentException("failed to process arguments", e);
         }
-        return testPkgList;
     }
 
     /**
-     * Adds a test package to the list of packages to test
+     * Return the {@link Set} of {@link ITestPackageDef}s to run unfiltered by ABI
      *
-     * @param testList
-     * @param testPkgDef
-     */
-    private void addTestPackage(List<TestPackage> testList, ITestPackageDef testPkgDef) {
-        IRemoteTest testForPackage = testPkgDef.createTest(mCtsBuild.getTestCasesDir());
-        if (testForPackage != null) {
-            Collection<TestIdentifier> knownTests = testPkgDef.getTests();
-            testList.add(new TestPackage(testPkgDef, testForPackage, knownTests));
-        }
-    }
-
-    /**
-     * Return the list of test package defs to run
-     *
-     * @return the list of test package defs to run
+     * @return the {@link Set} of {@link ITestPackageDef}s to run
      * @throws ParseException
      * @throws FileNotFoundException
      * @throws ConfigurationException
      */
-    private Collection<ITestPackageDef> getTestPackagesToRun(ITestPackageRepo testRepo)
-            throws ParseException, FileNotFoundException, ConfigurationException {
+    private Set<ITestPackageDef> getAvailableTestPackages(ITestPackageRepo testRepo)
+                throws ParseException, FileNotFoundException, ConfigurationException {
         // use LinkedHashSet to have predictable iteration order
-        Set<ITestPackageDef> testPkgDefs = new LinkedHashSet<ITestPackageDef>();
+        Set<ITestPackageDef> testPkgDefs = new LinkedHashSet<>();
         if (mPlanName != null) {
             Log.i(LOG_TAG, String.format("Executing CTS test plan %s", mPlanName));
             File ctsPlanFile = mCtsBuild.getTestPlanFile(mPlanName);
             ITestPlan plan = createPlan(mPlanName);
             plan.parse(createXmlStream(ctsPlanFile));
-            for (String uri : plan.getTestUris()) {
-                if (!mExcludedPackageNames.contains(uri)) {
-                    ITestPackageDef testPackage = testRepo.getTestPackage(uri);
-                    if (testPackage != null) {
-                        testPackage.setExcludedTestFilter(plan.getExcludedTestFilter(uri));
-                        testPkgDefs.add(testPackage);
-                    } else {
-                        CLog.e("Could not find test package uri %s referenced in plan %s", uri,
-                                mPlanName);
-                    }
+
+            for (String testId : plan.getTestIds()) {
+                if (mExcludedPackageNames.contains(AbiUtils.parseTestName(testId))) {
+                    continue;
                 }
+                ITestPackageDef testPackageDef = testRepo.getTestPackage(testId);
+                if (testPackageDef == null) {
+                    CLog.e("Could not find test id %s referenced in plan %s", testId, mPlanName);
+                    continue;
+                }
+
+                testPackageDef.setTestFilter(plan.getTestFilter(testId));
+                testPkgDefs.add(testPackageDef);
             }
         } else if (mPackageNames.size() > 0){
-            Log.i(LOG_TAG, String.format("Executing CTS test packages %s", mPackageNames));
-            for (String uri : mPackageNames) {
-                ITestPackageDef testPackage = testRepo.getTestPackage(uri);
-                if (testPackage != null) {
-                    testPkgDefs.add(testPackage);
-                } else {
+            Log.i(LOG_TAG, String.format("Executing XTS test packages %s", mPackageNames));
+
+            Map<String, List<ITestPackageDef>> testPackageDefMap =
+                    testRepo.getTestPackageDefsByName();
+
+            for (String name : mPackageNames) {
+                if (!testPackageDefMap.containsKey(name)) {
                     throw new IllegalArgumentException(String.format(
                             "Could not find test package %s. " +
-                            "Use 'list packages' to see available packages." , uri));
+                                    "Use 'list packages' to see available packages.", name));
                 }
+                testPkgDefs.addAll(testPackageDefMap.get(name));
             }
         } else if (mClassName != null) {
             Log.i(LOG_TAG, String.format("Executing CTS test class %s", mClassName));
-            // try to find package to run from class name
-            String packageUri = testRepo.findPackageForTest(mClassName);
-            if (packageUri != null) {
-                ITestPackageDef testPackageDef = testRepo.getTestPackage(packageUri);
-                testPackageDef.setClassName(mClassName, mMethodName);
-                testPkgDefs.add(testPackageDef);
-            } else {
+            testPkgDefs.addAll(buildTestPackageDefSet(testRepo, mClassName, mMethodName));
+        } else if (mTestName != null) {
+            Log.i(LOG_TAG, String.format("Executing CTS test %s", mTestName));
+            String [] split = mTestName.split("#");
+            if (split.length != 2) {
                 Log.logAndDisplay(LogLevel.WARN, LOG_TAG, String.format(
-                        "Could not find package for test class %s", mClassName));
+                        "Could not parse class and method from test %s", mTestName));
+            } else {
+                String className = split[0];
+                String methodName = split[1];
+                testPkgDefs.addAll(buildTestPackageDefSet(testRepo, className, methodName));
             }
         } else if (mContinueSessionId != null) {
             // create an in-memory derived plan that contains the notExecuted tests from previous
-            // session
-            // use timestamp as plan name so it will hopefully be unique
+            // session use timestamp as plan name so it will hopefully be unique
             String uniquePlanName = Long.toString(System.currentTimeMillis());
             PlanCreator planCreator = new PlanCreator(uniquePlanName, mContinueSessionId,
                     CtsTestStatus.NOT_EXECUTED);
             ITestPlan plan = createPlan(planCreator);
-            for (String uri : plan.getTestUris()) {
-                if (!mExcludedPackageNames.contains(uri)) {
-                    ITestPackageDef testPackage = testRepo.getTestPackage(uri);
-                    testPackage.setExcludedTestFilter(plan.getExcludedTestFilter(uri));
-                    testPkgDefs.add(testPackage);
+            for (String testId : plan.getTestIds()) {
+                if (mExcludedPackageNames.contains(AbiUtils.parseTestName(testId))) {
+                    continue;
                 }
+                ITestPackageDef testPackageDef = testRepo.getTestPackage(testId);
+                if (testPackageDef == null) {
+                    CLog.e("Could not find test id %s referenced in plan %s", testId, mPlanName);
+                    continue;
+                }
+
+                testPackageDef.setTestFilter(plan.getTestFilter(testId));
+                testPkgDefs.add(testPackageDef);
             }
         } else {
             // should never get here - was checkFields() not called?
@@ -654,10 +803,11 @@
 
     /**
      * Return the list of unique prerequisite Android package names
-     * @param testPackages
+     *
+     * @param testPackages The {@link TestPackage}s that contain prerequisites
      */
     private Collection<String> getPrerequisitePackageNames(List<TestPackage> testPackages) {
-        Set<String> pkgNames = new HashSet<String>();
+        Set<String> pkgNames = new HashSet<>();
         for (TestPackage testPkg : testPackages) {
             String pkgName = testPkg.mPackageDef.getTargetPackageName();
             if (pkgName != null) {
@@ -668,32 +818,78 @@
     }
 
     /**
-     * Return the list of unique prerequisite apks to install
-     * @param testPackages
+     * @return a {@link Set} containing {@link ITestPackageDef}s pertaining to the given
+     *     {@code className} and {@code methodName}.
      */
-    private Collection<String> getPrerequisiteApks(List<TestPackage> testPackages) {
-        Set<String> apkNames = new HashSet<String>();
-        for (TestPackage testPkg : testPackages) {
-            String apkName = testPkg.mPackageDef.getTargetApkName();
-            if (apkName != null) {
-                apkNames.add(apkName);
+    private static Set<ITestPackageDef> buildTestPackageDefSet(
+            ITestPackageRepo testRepo, String className, String methodName) {
+        Set<ITestPackageDef> testPkgDefs = new LinkedHashSet<>();
+        // try to find packages to run from class name
+        List<String> packageIds = testRepo.findPackageIdsForTest(className);
+        if (packageIds.isEmpty()) {
+            Log.logAndDisplay(LogLevel.WARN, LOG_TAG, String.format(
+                    "Could not find package for test class %s", className));
+        }
+        for (String packageId: packageIds) {
+            ITestPackageDef testPackageDef = testRepo.getTestPackage(packageId);
+            if (testPackageDef != null) {
+                testPackageDef.setClassName(className, methodName);
+                testPkgDefs.add(testPackageDef);
             }
         }
-        return apkNames;
+        return testPkgDefs;
     }
 
     /**
+     * Return the list (by abi) of unique prerequisite apks to install
+     *
+     * @param testPackages The {@link List} of {@link TestPackage} that contain prerequisite APKs
+     */
+    private Map<String, Set<String>> getPrerequisiteApks(
+            List<TestPackage> testPackages, Set<String> abiSet) {
+        Map<String, Set<String>> abiToApkMap = new HashMap<>();
+        for (TestPackage testPkg : testPackages) {
+            if (testPkg.getKnownTests().size() == 0) {
+                // No tests, no point in installing pre-reqs
+                continue;
+            }
+            String apkName = testPkg.mPackageDef.getTargetApkName();
+            if (apkName == null) {
+                continue;
+            }
+            String abiName = testPkg.getAbi().getName();
+            if (!abiSet.contains(abiName)) {
+                continue;
+            }
+
+            if (!abiToApkMap.containsKey(abiName)) {
+                abiToApkMap.put(abiName, new HashSet<String>());
+            }
+            abiToApkMap.get(abiName).add(apkName);
+        }
+        return abiToApkMap;
+    }
+
+    /**
+     * FIXME eventually this should be removed once we get rid of CtsTestStubs, any other
+     * prerequisite apks should be installed by the test runner
+     *
      * Install the collection of test apk file names
      *
-     * @param prerequisiteApks
+     * @param prerequisiteApks The APKs that must be installed
      * @throws DeviceNotAvailableException
      */
-    private void installPrerequisiteApks(Collection<String> prerequisiteApks)
+    private void installPrerequisiteApks(Collection<String> prerequisiteApks, IAbi abi)
             throws DeviceNotAvailableException {
+        if (prerequisiteApks == null) {
+            return;
+        }
+        Log.logAndDisplay(LogLevel.INFO, LOG_TAG, "Installing prerequisites");
         for (String apkName : prerequisiteApks) {
             try {
                 File apkFile = mCtsBuild.getTestApp(apkName);
-                String errorCode = getDevice().installPackage(apkFile, true);
+                String[] options = {AbiUtils.createAbiFlag(abi.getName())};
+                String errorCode = getDevice().installPackage(apkFile, true, options);
                 if (errorCode != null) {
                     CLog.e("Failed to install %s. Reason: %s", apkName, errorCode);
                 }
@@ -706,7 +902,7 @@
     /**
      * Uninstalls the collection of android package names from device.
      *
-     * @param uninstallPackages
+     * @param uninstallPackages The packages that must be uninstalled
      */
     private void uninstallPrequisiteApks(Collection<String> uninstallPackages)
             throws DeviceNotAvailableException {
@@ -724,27 +920,17 @@
             return null;
         }
         checkFields();
-        List<TestPackage> allTests = buildTestsToRun();
 
-        if (allTests.size() <= 1) {
-            Log.w(LOG_TAG, "no tests to shard!");
-            return null;
+        List<IRemoteTest> shardQueue = new LinkedList<>();
+        for (int shardAssignment = 0; shardAssignment < mShards; shardAssignment++) {
+            CtsTest ctsTest = new CtsTest(shardAssignment, mShards /* totalShards */);
+            OptionCopier.copyOptionsNoThrow(this, ctsTest);
+            // Set the shard count because the copy option on the previous line copies
+            // over the mShard value
+            ctsTest.mShards = 0;
+            shardQueue.add(ctsTest);
         }
 
-        // treat shardQueue as a circular queue, to sequentially distribute tests among shards
-        Queue<IRemoteTest> shardQueue = new LinkedList<IRemoteTest>();
-        // don't create more shards than the number of tests we have!
-        for (int i = 0; i < mShards && i < allTests.size(); i++) {
-            CtsTest shard = new CtsTest();
-            shard.mRemainingTestPkgs = new LinkedList<TestPackage>();
-            shardQueue.add(shard);
-        }
-        while (!allTests.isEmpty()) {
-            TestPackage testPair = allTests.remove(0);
-            CtsTest shard = (CtsTest)shardQueue.poll();
-            shard.mRemainingTestPkgs.add(testPair);
-            shardQueue.add(shard);
-        }
         return shardQueue;
     }
 
@@ -759,7 +945,8 @@
     void collectDeviceInfo(ITestDevice device, CtsBuildHelper ctsBuild,
             ITestInvocationListener listener) throws DeviceNotAvailableException {
         if (!mSkipDeviceInfo) {
-            DeviceInfoCollector.collectDeviceInfo(device, ctsBuild.getTestCasesDir(), listener);
+            String abi = AbiFormatter.getDefaultAbi(device, "");
+            DeviceInfoCollector.collectDeviceInfo(device, abi, ctsBuild.getTestCasesDir(), listener);
         }
     }
 
@@ -778,7 +965,25 @@
      * Exposed for unit testing
      */
     ITestPlan createPlan(String planName) {
-        return new TestPlan(planName);
+        return new TestPlan(planName, AbiUtils.getAbisSupportedByCts());
+    }
+
+    /**
+     * Gets the set of ABIs supported by both CTS and the device under test
+     * <p/>
+     * Exposed for unit testing
+     * @return The set of ABIs to run the tests on
+     * @throws DeviceNotAvailableException
+     */
+    Set<String> getAbis() throws DeviceNotAvailableException {
+        String bitness = (mForceAbi == null) ? "" : mForceAbi;
+        Set<String> abis = new HashSet<>();
+        for (String abi : AbiFormatter.getSupportedAbis(mDevice, bitness)) {
+            if (AbiUtils.isAbiSupportedByCts(abi)) {
+                abis.add(abi);
+            }
+        }
+        return abis;
     }
 
     /**
@@ -787,8 +992,9 @@
      * Exposed for unit testing
      * @throws ConfigurationException
      */
-    ITestPlan createPlan(PlanCreator planCreator) throws ConfigurationException {
-        return planCreator.createDerivedPlan(mCtsBuild);
+    ITestPlan createPlan(PlanCreator planCreator)
+            throws ConfigurationException {
+        return planCreator.createDerivedPlan(mCtsBuild, AbiUtils.getAbisSupportedByCts());
     }
 
     /**
@@ -801,10 +1007,10 @@
     }
 
     private void checkFields() {
-        // for simplicity of command line usage, make --plan, --package, and --class mutually
+        // for simplicity of command line usage, make --plan, --package, --test and --class mutually
         // exclusive
         boolean mutualExclusiveArgs = xor(mPlanName != null, mPackageNames.size() > 0,
-                mClassName != null, mContinueSessionId != null);
+                mClassName != null, mContinueSessionId != null, mTestName != null);
 
         if (!mutualExclusiveArgs) {
             throw new IllegalArgumentException(String.format(
@@ -828,7 +1034,7 @@
      * @return <code>true</code> if one and only one of <var>args</code> is <code>true</code>.
      *         Otherwise return <code>false</code>.
      */
-    private boolean xor(boolean... args) {
+    private static boolean xor(boolean... args) {
         boolean currentVal = args[0];
         for (int i=1; i < args.length; i++) {
             if (currentVal && args[i]) {
@@ -842,13 +1048,14 @@
     /**
      * Forward the digest and package name to the listener as a metric
      *
-     * @param listener
+     * @param listener Handles test results
      */
-    private void forwardPackageDetails(ITestPackageDef def, ITestInvocationListener listener) {
-        Map<String, String> metrics = new HashMap<String, String>(2);
+    private static void forwardPackageDetails(ITestPackageDef def, ITestInvocationListener listener) {
+        Map<String, String> metrics = new HashMap<>(3);
         metrics.put(PACKAGE_NAME_METRIC, def.getName());
+        metrics.put(PACKAGE_ABI_METRIC, def.getAbi().getName());
         metrics.put(PACKAGE_DIGEST_METRIC, def.getDigest());
-        listener.testRunStarted(def.getUri(), 0);
+        listener.testRunStarted(def.getId(), 0);
         listener.testRunEnded(0, metrics);
     }
 }
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DeqpTestRunner.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DeqpTestRunner.java
new file mode 100644
index 0000000..8eb1621
--- /dev/null
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DeqpTestRunner.java
@@ -0,0 +1,548 @@
+package com.android.cts.tradefed.testtype;
+
+import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.cts.util.AbiUtils;
+import com.android.ddmlib.MultiLineReceiver;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.result.ByteArrayInputStreamSource;
+import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.result.LogDataType;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.testtype.IDeviceTest;
+import com.android.tradefed.testtype.IRemoteTest;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Test runner for dEQP tests
+ *
+ * Supports running drawElements Quality Program tests found under external/deqp.
+ */
+public class DeqpTestRunner implements IBuildReceiver, IDeviceTest, IRemoteTest {
+
+    private static final String DEQP_ONDEVICE_APK = "com.drawelements.deqp.apk";
+    private static final String DEQP_ONDEVICE_PKG = "com.drawelements.deqp";
+    private static final String INCOMPLETE_LOG_MESSAGE = "Crash: Incomplete test log";
+
+    private final int TESTCASE_BATCH_LIMIT = 1000;
+
+    private boolean mLogData;
+
+    private ITestDevice mDevice;
+
+    private final String mPackageName;
+    private final String mName;
+    private Collection<TestIdentifier> mTests;
+    private IAbi mAbi;
+    private CtsBuildHelper mCtsBuild;
+
+    private TestIdentifier mCurrentTestId;
+    private boolean mGotTestResult;
+    private String mCurrentTestLog;
+
+    private ITestInvocationListener mListener;
+
+    public DeqpTestRunner(String packageName, String name, Collection<TestIdentifier> tests) {
+        mPackageName = packageName;
+        mName = name;
+        mTests = tests;
+        mLogData = false;
+    }
+
+    /**
+     * @param abi the ABI to run the test on
+     */
+    public void setAbi(IAbi abi) {
+        mAbi = abi;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+    }
+
+    /**
+     * Set the CTS build container.
+     * <p/>
+     * Exposed so unit tests can mock the provided build.
+     *
+     * @param buildHelper
+     */
+    public void setBuildHelper(CtsBuildHelper buildHelper) {
+        mCtsBuild = buildHelper;
+    }
+
+    /**
+     * Enable or disable raw dEQP test log collection.
+     */
+    public void setCollectLogs(boolean logData) {
+        mLogData = logData;
+    }
+
+    /**
+     * dEQP instrumentation parser
+     */
+    class InstrumentationParser extends MultiLineReceiver {
+        private DeqpTestRunner mDeqpTests;
+
+        private Map<String, String> mValues;
+        private String mCurrentName;
+        private String mCurrentValue;
+
+
+        public InstrumentationParser(DeqpTestRunner tests) {
+            mDeqpTests = tests;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void processNewLines(String[] lines) {
+            for (String line : lines) {
+                if (mValues == null) mValues = new HashMap<String, String>();
+
+                if (line.startsWith("INSTRUMENTATION_STATUS_CODE: ")) {
+                    if (mCurrentName != null) {
+                        mValues.put(mCurrentName, mCurrentValue);
+
+                        mCurrentName = null;
+                        mCurrentValue = null;
+                    }
+
+                    mDeqpTests.handleStatus(mValues);
+                    mValues = null;
+                } else if (line.startsWith("INSTRUMENTATION_STATUS: dEQP-")) {
+                    if (mCurrentName != null) {
+                        mValues.put(mCurrentName, mCurrentValue);
+
+                        mCurrentValue = null;
+                        mCurrentName = null;
+                    }
+
+                    String prefix = "INSTRUMENTATION_STATUS: ";
+                    int nameBegin = prefix.length();
+                    int nameEnd = line.indexOf('=');
+                    int valueBegin = nameEnd + 1;
+
+                    mCurrentName = line.substring(nameBegin, nameEnd);
+                    mCurrentValue = line.substring(valueBegin);
+                } else if (mCurrentValue != null) {
+                    mCurrentValue = mCurrentValue + line;
+                }
+            }
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void done() {
+            if (mCurrentName != null) {
+                mValues.put(mCurrentName, mCurrentValue);
+
+                mCurrentName = null;
+                mCurrentValue = null;
+            }
+
+            if (mValues != null) {
+                mDeqpTests.handleStatus(mValues);
+                mValues = null;
+            }
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public boolean isCancelled() {
+            return false;
+        }
+    }
+
+    /**
+     * Converts dEQP testcase path to TestIdentifier.
+     */
+    private TestIdentifier pathToIdentifier(String testPath) {
+        String[] components = testPath.split("\\.");
+        String name = components[components.length - 1];
+        String className = null;
+
+        for (int i = 0; i < components.length - 1; i++) {
+            if (className == null) {
+                className = components[i];
+            } else {
+                className = className + "." + components[i];
+            }
+        }
+
+        return new TestIdentifier(className, name);
+    }
+
+    /**
+     * Handles beginning of dEQP session.
+     */
+    private void handleBeginSession(Map<String, String> values) {
+        String id = AbiUtils.createId(mAbi.getName(), mPackageName);
+        mListener.testRunStarted(id, mTests.size());
+    }
+
+    /**
+     * Handles end of dEQP session.
+     */
+    private void handleEndSession(Map<String, String> values) {
+        Map <String, String> emptyMap = Collections.emptyMap();
+        mListener.testRunEnded(0, emptyMap);
+    }
+
+    /**
+     * Handles beginning of dEQP testcase.
+     */
+    private void handleBeginTestCase(Map<String, String> values) {
+        mCurrentTestId = pathToIdentifier(values.get("dEQP-BeginTestCase-TestCasePath"));
+        mCurrentTestLog = "";
+        mGotTestResult = false;
+
+        mListener.testStarted(mCurrentTestId);
+        mTests.remove(mCurrentTestId);
+    }
+
+    /**
+     * Handles end of dEQP testcase.
+     */
+    private void handleEndTestCase(Map<String, String> values) {
+        Map <String, String> emptyMap = Collections.emptyMap();
+
+        if (!mGotTestResult) {
+            mListener.testFailed(mCurrentTestId,
+                    INCOMPLETE_LOG_MESSAGE);
+        }
+
+        if (mLogData && mCurrentTestLog != null && mCurrentTestLog.length() > 0) {
+            ByteArrayInputStreamSource source
+                    = new ByteArrayInputStreamSource(mCurrentTestLog.getBytes());
+
+            mListener.testLog(mCurrentTestId.getClassName() + "."
+                    + mCurrentTestId.getTestName(), LogDataType.XML, source);
+
+            source.cancel();
+        }
+
+        mListener.testEnded(mCurrentTestId, emptyMap);
+        mCurrentTestId = null;
+    }
+
+    /**
+     * Handles dEQP testcase result.
+     */
+    private void handleTestCaseResult(Map<String, String> values) {
+        String code = values.get("dEQP-TestCaseResult-Code");
+        String details = values.get("dEQP-TestCaseResult-Details");
+
+        if (code.compareTo("Pass") == 0) {
+            mGotTestResult = true;
+        } else if (code.compareTo("NotSupported") == 0) {
+            mGotTestResult = true;
+        } else if (code.compareTo("QualityWarning") == 0) {
+            mGotTestResult = true;
+        } else if (code.compareTo("CompatibilityWarning") == 0) {
+            mGotTestResult = true;
+        } else if (code.compareTo("Fail") == 0 || code.compareTo("ResourceError") == 0
+                || code.compareTo("InternalError") == 0 || code.compareTo("Crash") == 0
+                || code.compareTo("Timeout") == 0) {
+            mListener.testFailed(mCurrentTestId,
+                    code + ": " + details);
+            mGotTestResult = true;
+        } else {
+            mListener.testFailed(mCurrentTestId,
+                    "Unknown result code: " + code + ": " + details);
+            mGotTestResult = true;
+        }
+    }
+
+    /**
+     * Handles terminated dEQP testcase.
+     */
+    private void handleTestCaseTerminate(Map<String, String> values) {
+        Map <String, String> emptyMap = Collections.emptyMap();
+
+        String reason = values.get("dEQP-TerminateTestCase-Reason");
+        mListener.testFailed(mCurrentTestId,
+                "Terminated: " + reason);
+        mListener.testEnded(mCurrentTestId, emptyMap);
+
+        if (mLogData && mCurrentTestLog != null && mCurrentTestLog.length() > 0) {
+            ByteArrayInputStreamSource source
+                    = new ByteArrayInputStreamSource(mCurrentTestLog.getBytes());
+
+            mListener.testLog(mCurrentTestId.getClassName() + "."
+                    + mCurrentTestId.getTestName(), LogDataType.XML, source);
+
+            source.cancel();
+        }
+
+        mCurrentTestId = null;
+        mGotTestResult = true;
+    }
+
+    /**
+     * Handles dEQP testlog data.
+     */
+    private void handleTestLogData(Map<String, String> values) {
+        mCurrentTestLog = mCurrentTestLog + values.get("dEQP-TestLogData-Log");
+    }
+
+    /**
+     * Handles new instrumentation status message.
+     */
+    public void handleStatus(Map<String, String> values) {
+        String eventType = values.get("dEQP-EventType");
+
+        if (eventType == null) {
+            return;
+        }
+
+        if (eventType.compareTo("BeginSession") == 0) {
+            handleBeginSession(values);
+        } else if (eventType.compareTo("EndSession") == 0) {
+            handleEndSession(values);
+        } else if (eventType.compareTo("BeginTestCase") == 0) {
+            handleBeginTestCase(values);
+        } else if (eventType.compareTo("EndTestCase") == 0) {
+            handleEndTestCase(values);
+        } else if (eventType.compareTo("TestCaseResult") == 0) {
+            handleTestCaseResult(values);
+        } else if (eventType.compareTo("TerminateTestCase") == 0) {
+            handleTestCaseTerminate(values);
+        } else if (eventType.compareTo("TestLogData") == 0) {
+            handleTestLogData(values);
+        }
+    }
+
+    /**
+     * Generates tescase trie from dEQP testcase paths. Used to define which testcases to execute.
+     */
+    private String generateTestCaseTrieFromPaths(Collection<String> tests) {
+        String result = "{";
+        boolean first = true;
+
+        // Add testcases to results
+        for (Iterator<String> iter = tests.iterator(); iter.hasNext();) {
+            String test = iter.next();
+            String[] components = test.split("\\.");
+
+            if (components.length == 1) {
+                if (!first) {
+                    result = result + ",";
+                }
+                first = false;
+
+                result += components[0];
+                iter.remove();
+            }
+        }
+
+        if (!tests.isEmpty()) {
+            HashMap<String, ArrayList<String> > testGroups = new HashMap<>();
+
+            // Collect all sub testgroups
+            for (String test : tests) {
+                String[] components = test.split("\\.");
+                ArrayList<String> testGroup = testGroups.get(components[0]);
+
+                if (testGroup == null) {
+                    testGroup = new ArrayList<String>();
+                    testGroups.put(components[0], testGroup);
+                }
+
+                testGroup.add(test.substring(components[0].length()+1));
+            }
+
+            for (String testGroup : testGroups.keySet()) {
+                if (!first) {
+                    result = result + ",";
+                }
+
+                first = false;
+                result = result + testGroup
+                        + generateTestCaseTrieFromPaths(testGroups.get(testGroup));
+            }
+        }
+
+        return result + "}";
+    }
+
+    /**
+     * Generates testcase trie from TestIdentifiers.
+     */
+    private String generateTestCaseTrie(Collection<TestIdentifier> tests) {
+        ArrayList<String> testPaths = new ArrayList<String>();
+
+        for (TestIdentifier test : tests) {
+            testPaths.add(test.getClassName() + "." + test.getTestName());
+
+            // Limit number of testcases for each run
+            if (testPaths.size() > TESTCASE_BATCH_LIMIT)
+                break;
+        }
+
+        return generateTestCaseTrieFromPaths(testPaths);
+    }
+
+    /**
+     * Executes tests on the device.
+     */
+    private void executeTests(ITestInvocationListener listener) throws DeviceNotAvailableException {
+        InstrumentationParser parser = new InstrumentationParser(this);
+        String caseListFileName = "/sdcard/dEQP-TestCaseList.txt";
+        String logFileName = "/sdcard/TestLog.qpa";
+        String testCases = generateTestCaseTrie(mTests);
+
+        mDevice.executeShellCommand("rm " + caseListFileName);
+        mDevice.executeShellCommand("rm " + logFileName);
+        mDevice.pushString(testCases + "\n", caseListFileName);
+
+        String instrumentationName =
+                "com.drawelements.deqp/com.drawelements.deqp.testercore.DeqpInstrumentation";
+
+        String command = String.format(
+                "am instrument %s -w -e deqpLogFileName \"%s\" -e deqpCmdLine \""
+                    + "--deqp-caselist-file=%s --deqp-gl-config-name=rgba8888d24s8\""
+                    + " -e deqpLogData \"%s\" %s",
+                AbiUtils.createAbiFlag(mAbi.getName()), logFileName, caseListFileName, mLogData,
+                instrumentationName);
+
+        mDevice.executeShellCommand(command, parser);
+        parser.flush();
+    }
+
+    /**
+     * Check if device supports OpenGL ES version.
+     */
+    static boolean isSupportedGles(ITestDevice device, int requiredMajorVersion, int requiredMinorVersion) throws DeviceNotAvailableException {
+        String roOpenglesVersion = device.getProperty("ro.opengles.version");
+
+        if (roOpenglesVersion == null)
+            return false;
+
+        int intValue = Integer.parseInt(roOpenglesVersion);
+
+        int majorVersion = ((intValue & 0xffff0000) >> 16);
+        int minorVersion = (intValue & 0xffff);
+
+        return (majorVersion > requiredMajorVersion)
+                || (majorVersion == requiredMajorVersion && minorVersion >= requiredMinorVersion);
+    }
+
+    /**
+     * Install dEQP OnDevice Package
+     */
+    private void installTestApk() throws DeviceNotAvailableException {
+        try {
+            File apkFile = mCtsBuild.getTestApp(DEQP_ONDEVICE_APK);
+            String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+            String errorCode = getDevice().installPackage(apkFile, true, options);
+            if (errorCode != null) {
+                CLog.e("Failed to install %s. Reason: %s", DEQP_ONDEVICE_APK, errorCode);
+            }
+        } catch (FileNotFoundException e) {
+            CLog.e("Could not find test apk %s", DEQP_ONDEVICE_APK);
+        }
+    }
+
+    /**
+     * Uninstall dEQP OnDevice Package
+     */
+    private void uninstallTestApk() throws DeviceNotAvailableException {
+        getDevice().uninstallPackage(DEQP_ONDEVICE_PKG);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
+        mListener = listener;
+
+        if ((mName.equals( "dEQP-GLES3") && isSupportedGles(mDevice, 3, 0))
+            || (mName.equals("dEQP-GLES31") && isSupportedGles(mDevice, 3, 1))) {
+
+            // Make sure there is no pre-existing package form earlier interrupted test run.
+            uninstallTestApk();
+            installTestApk();
+
+            while (!mTests.isEmpty()) {
+                executeTests(listener);
+
+                // Set test to failed if it didn't receive test result
+                if (mCurrentTestId != null) {
+                    Map <String, String> emptyMap = Collections.emptyMap();
+
+                    if (mLogData && mCurrentTestLog != null && mCurrentTestLog.length() > 0) {
+                        ByteArrayInputStreamSource source
+                                = new ByteArrayInputStreamSource(mCurrentTestLog.getBytes());
+
+                        mListener.testLog(mCurrentTestId.getClassName() + "."
+                                + mCurrentTestId.getTestName(), LogDataType.XML, source);
+
+                        source.cancel();
+                    }
+                    if (!mGotTestResult) {
+                        mListener.testFailed(mCurrentTestId,
+                            INCOMPLETE_LOG_MESSAGE);
+                    }
+
+                    mListener.testEnded(mCurrentTestId, emptyMap);
+                    mCurrentTestId = null;
+                    mListener.testRunEnded(0, emptyMap);
+                }
+            }
+
+            uninstallTestApk();
+        } else {
+            /* Pass all tests if OpenGL ES version is not supported */
+            Map <String, String> emptyMap = Collections.emptyMap();
+            String id = AbiUtils.createId(mAbi.getName(), mPackageName);
+            mListener.testRunStarted(id, mTests.size());
+
+            for (TestIdentifier test : mTests) {
+                CLog.d("Skipping test '%s', Opengl ES version not supported", test.toString());
+                mListener.testStarted(test);
+                mListener.testEnded(test, emptyMap);
+            }
+
+            mListener.testRunEnded(0, emptyMap);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setDevice(ITestDevice device) {
+        mDevice = device;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public ITestDevice getDevice() {
+        return mDevice;
+    }
+}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DisplayTestRunner.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DisplayTestRunner.java
index 4c83aa9..59bfcf8 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DisplayTestRunner.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DisplayTestRunner.java
@@ -25,7 +25,7 @@
  * Secure settings cannot be changed from device CTS tests since system signature permission is
  * required. Such settings can be modified by the shell user, so a host side test is used.
  */
-public class DisplayTestRunner extends InstrumentationApkTest {
+public class DisplayTestRunner extends CtsInstrumentationApkTest {
     private static final String OVERLAY_DISPLAY_DEVICES_SETTING_NAME = "overlay_display_devices";
 
     // Use a non-standard pattern, must match values in tests/tests/display/.../DisplayTest.java
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/GeeTest.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/GeeTest.java
index 5cfafc6..6c2ed65 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/GeeTest.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/GeeTest.java
@@ -23,6 +23,7 @@
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.log.LogUtil.CLog;
 import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.testtype.IAbi;
 import com.android.tradefed.testtype.IBuildReceiver;
 import com.android.tradefed.testtype.IDeviceTest;
 import com.android.tradefed.testtype.IRemoteTest;
@@ -40,20 +41,31 @@
 public class GeeTest implements IBuildReceiver, IDeviceTest, IRemoteTest {
 
     private static final String NATIVE_TESTS_DIRECTORY = "/data/local/tmp/cts-native-tests";
+    private static final String NATIVE_TESTS_DIRECTORY_TMP = "/data/local/tmp";
+    private static final String ANDROID_PATH_SEPARATOR = "/";
 
     private int mMaxTestTimeMs = 1 * 60 * 1000;
 
     private CtsBuildHelper mCtsBuild;
     private ITestDevice mDevice;
+    private IAbi mAbi;
+    private String mExeName;
 
     private final String mPackageName;
-    private final String mExeName;
 
     public GeeTest(String packageName, String exeName) {
         mPackageName = packageName;
         mExeName = exeName;
     }
 
+    /**
+     * @param abi The ABI to run the test on
+     */
+    public void setAbi(IAbi abi) {
+        mAbi = abi;
+        mExeName += mAbi.getBitness();
+    }
+
     @Override
     public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
         if (installTest()) {
@@ -75,8 +87,8 @@
             return false;
         }
 
-        File devicePath = new File(NATIVE_TESTS_DIRECTORY, mExeName);
-        if (!mDevice.pushFile(nativeExe, devicePath.toString())) {
+        String devicePath = NATIVE_TESTS_DIRECTORY + ANDROID_PATH_SEPARATOR + mExeName;
+        if (!mDevice.pushFile(nativeExe, devicePath)) {
             CLog.e("Failed to push native test to device");
             return false;
         }
@@ -87,13 +99,11 @@
         if (mDevice.doesFileExist(remoteFilePath)) {
             return true;
         }
-        File remoteFile = new File(remoteFilePath);
-        String parentPath = remoteFile.getParent();
-        if (parentPath != null) {
-            if (!createRemoteDir(parentPath)) {
-                return false;
-            }
+        if (!(mDevice.doesFileExist(NATIVE_TESTS_DIRECTORY_TMP))) {
+            CLog.e("Could not find the /data/local/tmp directory");
+            return false;
         }
+
         mDevice.executeShellCommand(String.format("mkdir %s", remoteFilePath));
         return mDevice.doesFileExist(remoteFilePath);
     }
@@ -102,7 +112,7 @@
         GeeTestResultParser resultParser = new GeeTestResultParser(mPackageName, listener);
         resultParser.setFakePackagePrefix(mPackageName + ".");
 
-        String fullPath = NATIVE_TESTS_DIRECTORY + File.separator + mExeName;
+        String fullPath = NATIVE_TESTS_DIRECTORY + ANDROID_PATH_SEPARATOR + mExeName;
         String flags = "";
         CLog.v("Running gtest %s %s on %s", fullPath, flags, mDevice.getSerialNumber());
         // force file to be executable
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/GeeTestResultParser.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/GeeTestResultParser.java
index c01da20..d0ea0cf 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/GeeTestResultParser.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/GeeTestResultParser.java
@@ -99,7 +99,7 @@
     private long mTotalRunTime = 0;
     private boolean mTestInProgress = false;
     private boolean mTestRunInProgress = false;
-    private final String mTestRunName;
+    private final String mTestRunId;
     private final Collection<ITestRunListener> mTestListeners;
 
     /** Fake adding a package prefix if the test listener needs it. */
@@ -200,24 +200,24 @@
     /**
      * Creates the GTestResultParser.
      *
-     * @param testRunName the test run name to provide to
+     * @param testRunId the test run id to provide to
      *            {@link ITestRunListener#testRunStarted(String, int)}
      * @param listeners informed of test results as the tests are executing
      */
-    public GeeTestResultParser(String testRunName, Collection<ITestRunListener> listeners) {
-        mTestRunName = testRunName;
+    public GeeTestResultParser(String testRunId, Collection<ITestRunListener> listeners) {
+        mTestRunId = testRunId;
         mTestListeners = new ArrayList<ITestRunListener>(listeners);
     }
 
     /**
      * Creates the GTestResultParser for a single listener.
      *
-     * @param testRunName the test run name to provide to
+     * @param testRunId the test run id to provide to
      *            {@link ITestRunListener#testRunStarted(String, int)}
      * @param listener informed of test results as the tests are executing
      */
-    public GeeTestResultParser(String testRunName, ITestRunListener listener) {
-        mTestRunName = testRunName;
+    public GeeTestResultParser(String testRunId, ITestRunListener listener) {
+        mTestRunId = testRunId;
         mTestListeners = new ArrayList<ITestRunListener>(1);
         mTestListeners.add(listener);
     }
@@ -311,6 +311,7 @@
      *
      * @see IShellOutputReceiver#isCancelled()
      */
+    @Override
     public boolean isCancelled() {
         return mIsCancelled;
     }
@@ -355,7 +356,7 @@
         // if start test run not reported yet
         if (!mTestRunStartReported) {
             for (ITestRunListener listener : mTestListeners) {
-                listener.testRunStarted(mTestRunName, mNumTestsExpected);
+                listener.testRunStarted(mTestRunId, mNumTestsExpected);
             }
             mTestRunStartReported = true;
         }
@@ -548,14 +549,12 @@
             // If the test name of the result changed from what we started with, report that
             // the last known test failed, regardless of whether we received a pass or fail tag.
             for (ITestRunListener listener : mTestListeners) {
-                listener.testFailed(ITestRunListener.TestFailure.ERROR, testId,
-                                mCurrentTestResult.getTrace());
+                listener.testFailed(testId, mCurrentTestResult.getTrace());
             }
         }
         else if (!testPassed) {  // test failed
             for (ITestRunListener listener : mTestListeners) {
-                listener.testFailed(ITestRunListener.TestFailure.FAILURE, testId,
-                                mCurrentTestResult.getTrace());
+                listener.testFailed(testId, mCurrentTestResult.getTrace());
             }
         }
         // For all cases (pass or fail), we ultimately need to report test has ended
@@ -629,8 +628,7 @@
                 testRunStackTrace = mCurrentTestResult.getTrace();
             }
             for (ITestRunListener listener : mTestListeners) {
-                listener.testFailed(ITestRunListener.TestFailure.ERROR, testId,
-                        "No test results.\r\n" + testRunStackTrace);
+                listener.testFailed(testId, "No test results.\r\n" + testRunStackTrace);
                 listener.testEnded(testId, emptyMap);
             }
             clearCurrentTestResult();
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ITestPackageDef.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ITestPackageDef.java
index 68d6743..8a5c822 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ITestPackageDef.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ITestPackageDef.java
@@ -17,6 +17,7 @@
 package com.android.cts.tradefed.testtype;
 
 import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.tradefed.testtype.IAbi;
 import com.android.tradefed.testtype.IRemoteTest;
 
 import java.io.File;
@@ -27,44 +28,24 @@
  * <p/>
  * Knows how to translate this info into a runnable {@link IRemoteTest}.
  */
-public interface ITestPackageDef {
+public interface ITestPackageDef extends Comparable<ITestPackageDef> {
 
     /**
-     * Get the unique URI, aka the appPackageName, of the test package.
-     * @return the {@link String} uri
+     * Get the id of the test package.
+     * @return the {@link String} id
      */
-    public String getUri();
+    public String getId();
 
     /**
      * Creates a runnable {@link IRemoteTest} from info stored in this definition.
      *
      * @param testCaseDir {@link File} representing directory of test case data
-     * @param className the test class to restrict this run to or <code>null</code> to run all tests
-     *            in package
-     * @param methodName the optional test method to restrict this run to, or <code>null</code> to
-     *            run all tests in class/package
      * @return a {@link IRemoteTest} with all necessary data populated to run the test or
      *         <code>null</code> if test could not be created
      */
     public IRemoteTest createTest(File testCaseDir);
 
     /**
-     * Determine if given test is defined in this package.
-     *
-     * @param testDef the {@link TestIdentifier}
-     * @return <code>true</code> if test is defined
-     */
-    public boolean isKnownTest(TestIdentifier testDef);
-
-    /**
-     * Determine if given test class is defined in this package.
-     *
-     * @param testClassName the fully qualified test class name
-     * @return <code>true</code> if test class is defined
-     */
-    public boolean isKnownTestClass(String testClassName);
-
-    /**
      * Get the collection of tests in this test package.
      */
     public Collection<TestIdentifier> getTests();
@@ -72,8 +53,7 @@
     /**
      * Return the sha1sum of the binary file for this test package.
      * <p/>
-     * Will only return a valid value after {@link #createTest(File, String, String)} has been
-     * called.
+     * Will only return a valid value after {@link #createTest(File)} has been called.
      *
      * @return the sha1sum in {@link String} form
      */
@@ -85,11 +65,16 @@
     public String getName();
 
     /**
-     * Set the filter to use to exclude tests
-     *
-     * @param excludedTestFilter
+     * @return the ABI of this test package.
      */
-    public void setExcludedTestFilter(TestFilter excludedTestFilter);
+    public IAbi getAbi();
+
+    /**
+     * Set the filter to use for tests
+     *
+     * @param testFilter
+     */
+    public void setTestFilter(TestFilter testFilter);
 
     /**
      * Restrict this test package to run a specific class and method name
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ITestPackageRepo.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ITestPackageRepo.java
index 53451f1..234f437 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ITestPackageRepo.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ITestPackageRepo.java
@@ -16,8 +16,10 @@
 
 package com.android.cts.tradefed.testtype;
 
-import java.util.Collection;
+import com.android.cts.util.AbiUtils;
 
+import java.util.List;
+import java.util.Map;
 
 /**
  * Interface for accessing tests from the CTS repository.
@@ -25,24 +27,34 @@
 public interface ITestPackageRepo {
 
     /**
-     * Get a {@link TestPackageDef} given a uri
+     * Get a {@link TestPackageDef} given an id.
      *
-     * @param testUri the string uris
-     * @return a {@link TestPackageDef} or <code>null</code> if the uri cannot be found in repo
+     * @param id the unique identifier of this test package, generated by
+     * {@link AbiUtils#createId(String, String)}.
+     * @return a {@link TestPackageDef}
      */
-    public ITestPackageDef getTestPackage(String testUri);
+    public ITestPackageDef getTestPackage(String id);
 
     /**
-     * Attempt to find the package uri for a given test class name
+     * @return a sorted {@link List} of all package ids found in repo.
+     */
+    public List<String> getPackageIds();
+
+    /**
+     * @return a sorted {@link List} of test package names
+     */
+    public List<String> getPackageNames();
+
+    /**
+     * @return A {@link Map} of test package name to a {@link List} of {@link ITestPackageDef}s.
+     */
+    public Map<String, List<ITestPackageDef>> getTestPackageDefsByName();
+
+    /**
+     * Attempt to find the package ids for a given test class name
      *
      * @param testClassName the test class name
-     * @return the package uri or <code>null</code> if the package cannot be found
+     * @return a {@link List} of package ids.
      */
-    public String findPackageForTest(String testClassName);
-
-    /**
-     * Return a sorted {@link Collection} of all package names found in repo.
-     */
-    public Collection<String> getPackageNames();
-
+    public List<String> findPackageIdsForTest(String testClassName);
 }
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ITestPlan.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ITestPlan.java
index 191cefd..2d5f4a7 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ITestPlan.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ITestPlan.java
@@ -23,6 +23,7 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.Collection;
+import java.util.List;
 
 /**
  * Interface for accessing test plan data.
@@ -37,36 +38,41 @@
     public void parse(InputStream xmlStream) throws ParseException;
 
     /**
-     * Gets the list of test uris contained in this plan.
+     * Gets a sorted list of test ids contained in this plan.
      */
-    public Collection<String> getTestUris();
+    public Collection<String> getTestIds();
 
     /**
-     * Gets the {@link TestFilter} that should be used to exclude tests from given package.
+     * Gets a sorted {@link List} of test names contained in this plan.
      */
-    public TestFilter getExcludedTestFilter(String uri);
+    public List<String> getTestNames();
+
+    /**
+     * Gets the {@link TestFilter} that should be used to filter tests from given package.
+     */
+    public TestFilter getTestFilter(String id);
 
     /**
      * Add a package to this test plan
-     * @param uri
+     * @param id
      */
-    public void addPackage(String uri);
+    public void addPackage(String id);
 
     /**
      * Add a excluded test to this test plan
      *
-     * @param uri the package uri
+     * @param id the package id
      * @param testToExclude the test to exclude for given package
      */
-    public void addExcludedTest(String uri, TestIdentifier testToExclude);
+    public void addExcludedTest(String id, TestIdentifier testToExclude);
 
     /**
      * Adds the list of excluded tests for given package
      *
-     * @param pkgUri
+     * @param id
      * @param excludedTests
      */
-    public void addExcludedTests(String uri, Collection<TestIdentifier> excludedTests);
+    public void addExcludedTests(String id, Collection<TestIdentifier> excludedTests);
 
     /**
      * Serialize the contents of this test plan.
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
deleted file mode 100644
index 77189cd..0000000
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/InstrumentationApkTest.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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.
- */
-package com.android.cts.tradefed.testtype;
-
-import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.ddmlib.Log;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.testtype.IBuildReceiver;
-import com.android.tradefed.testtype.InstrumentationTest;
-
-import java.io.FileNotFoundException;
-import java.util.ArrayList;
-import java.util.Collection;
-
-import junit.framework.Assert;
-
-/**
- * A {@link InstrumentationTest} that will install CTS apks 
- * before test execution, and uninstall on execution completion.
- */
-public class InstrumentationApkTest extends InstrumentationTest implements IBuildReceiver {
-
-    private static final String LOG_TAG = "InstrumentationApkTest";
-
-    /** the file names of the CTS apks to install */
-    private Collection<String> mInstallFileNames = new ArrayList<String>();
-    private Collection<String> mUninstallPackages = new ArrayList<String>();
-
-    private CtsBuildHelper mCtsBuild = null;
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void setBuild(IBuildInfo build) {
-        mCtsBuild  = CtsBuildHelper.createBuildHelper(build);
-    }
-
-    /**
-     * Add an apk to install.
-     *
-     * @param apkFileName the apk file name
-     * @param packageName the apk's Android package name
-     */
-    public void addInstallApk(String apkFileName, String packageName) {
-        mInstallFileNames.add(apkFileName);
-        mUninstallPackages.add(packageName);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void run(final ITestInvocationListener listener)
-            throws DeviceNotAvailableException {
-        ITestDevice mTestDevice = getDevice();
-
-        if (mTestDevice == null) {
-            Log.e(LOG_TAG, String.format("Missing device."));
-            return;
-        }
-        if (mCtsBuild == null) {
-            Log.e(LOG_TAG, String.format("Missing build %s", mCtsBuild));
-            return;
-        }
-
-        for (String apkFileName : mInstallFileNames) {
-            Log.d(LOG_TAG, String.format("Installing %s on %s", apkFileName,
-                    mTestDevice.getSerialNumber()));
-            try {
-                String installCode = mTestDevice.installPackage(mCtsBuild.getTestApp(apkFileName),
-                        true);
-                if (installCode != null) {
-                    Log.e(LOG_TAG, String.format("Failed to install %s on %s. Reason: %s",
-                          apkFileName, mTestDevice.getSerialNumber(), installCode));
-                }
-            } catch (FileNotFoundException e) {
-                Log.e(LOG_TAG, String.format("Could not find file %s", apkFileName));
-            }
-        }
-        super.run(listener);
-        for (String packageName : mUninstallPackages) {
-            Log.d(LOG_TAG, String.format("Uninstalling %s on %s", packageName,
-                    getDevice().getSerialNumber()));
-            getDevice().uninstallPackage(packageName);
-        }
-    }
-}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/JUnitDeviceTest.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/JUnitDeviceTest.java
new file mode 100644
index 0000000..5efa7cd
--- /dev/null
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/JUnitDeviceTest.java
@@ -0,0 +1,226 @@
+/*
+ * 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 com.android.cts.tradefed.testtype;
+
+import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.ddmlib.testrunner.TestIdentifier;
+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;
+import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.testtype.IAbi;
+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 com.android.tradefed.util.ArrayUtil;
+
+import junit.framework.Assert;
+import junit.framework.Test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * {@link Test} for running CTS JUnit tests on the device.
+ */
+public class JUnitDeviceTest implements IDeviceTest, IRemoteTest, IBuildReceiver {
+
+    private static final String TMP_DIR = "/data/local/tmp/";
+
+    @Option(name = "junit-device-runtime",
+            description = "The name of the runtime to use on the device",
+            importance = Importance.ALWAYS)
+    private String mRuntimePath = "dalvikvm|#ABI#|";
+
+    @Option(name = "junit-device-tmpdir", description = "Device path where to store the test jars."
+            , importance = Importance.IF_UNSET)
+    private String mDeviceTestTmpPath = TMP_DIR;
+
+
+
+    // default to no timeout
+    private long mMaxTimeToOutputResponse = 0;
+
+    private ITestDevice mDevice;
+    private String mRunName;
+    private Collection<TestIdentifier> mTests;
+    private CtsBuildHelper mCtsBuild = null;
+
+    private List<String> mJarPaths = new ArrayList<String>();
+
+    private String mRuntimeArgs;
+
+    private IAbi mAbi;
+
+    private static final String JUNIT_JAR = "cts-junit.jar";
+
+    private Set<String> mTestJars = new HashSet<String>(Arrays.asList(JUNIT_JAR));
+
+    /**
+     * @param abi The ABI to run the test on
+     */
+    public void setAbi(IAbi abi) {
+        mAbi = abi;
+    }
+
+    @Override
+    public ITestDevice getDevice() {
+        return mDevice;
+    }
+
+    @Override
+    public void setDevice(ITestDevice device) {
+        mDevice = device;
+    }
+
+    public void addTestJarFileName(String jarFileName) {
+        mTestJars.add(jarFileName);
+    }
+
+    public void setRunName(String runName) {
+        mRunName = runName;
+    }
+
+    public void setTests(Collection<TestIdentifier> tests) {
+        mTests = tests;
+    }
+
+    public Collection<TestIdentifier> getTests() {
+        return mTests;
+    }
+
+    @Override
+    public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
+        addTestJarFileName(JUNIT_JAR);
+        checkFields();
+        long startTime = System.currentTimeMillis();
+        listener.testRunStarted(mRunName, mTests.size());
+        try {
+            installJars();
+            String jarPath = ArrayUtil.join(":", mJarPaths);
+            for (TestIdentifier testId : mTests) {
+                SingleJUnitTestResultParser resultParser = new SingleJUnitTestResultParser(
+                        testId, listener);
+                String cmdLine = String.format("ANDROID_DATA=%s %s -cp %s %s " +
+                        "com.android.cts.junit.SingleJUnitTestRunner %s#%s",
+                        mDeviceTestTmpPath, mRuntimePath, jarPath, mRuntimeArgs,
+                        testId.getClassName(), testId.getTestName());
+                String cmd = AbiFormatter.formatCmdForAbi(cmdLine, mAbi.getBitness());
+                CLog.d("Running %s", cmd);
+                listener.testStarted(testId);
+                mDevice.executeShellCommand(cmd, resultParser, mMaxTimeToOutputResponse,
+                        TimeUnit.MILLISECONDS, 0);
+            }
+        } finally {
+            listener.testRunEnded(System.currentTimeMillis() - startTime,
+                    Collections.<String, String> emptyMap());
+            // Remove jar files from device
+            removeJars();
+        }
+    }
+
+    /**
+     * Installs the jar files on the device under test.
+     *
+     * @throws DeviceNotAvailableException
+     */
+    protected void installJars() throws DeviceNotAvailableException {
+        for (String f : mTestJars) {
+            CLog.d("Installing %s on %s", f, getDevice().getSerialNumber());
+            File jarFile;
+            try {
+                String fullJarPath = String.format("%s%s", mDeviceTestTmpPath, f);
+                jarFile = mCtsBuild.getTestApp(f);
+                boolean result = getDevice().pushFile(jarFile, fullJarPath);
+                Assert.assertTrue(String.format("Failed to push file to %s", fullJarPath), result);
+                mJarPaths.add(fullJarPath);
+            } catch (FileNotFoundException e) {
+                Assert.fail(String.format("Could not find file %s", f));
+            }
+        }
+    }
+
+    /**
+     * Cleans up the jar files from the device under test.
+     *
+     * @throws DeviceNotAvailableException
+     */
+    protected void removeJars() throws DeviceNotAvailableException {
+        for (String f : mTestJars) {
+            String fullJarPath = String.format("%s%s", mDeviceTestTmpPath, f);
+            CLog.d("Uninstalling %s on %s", fullJarPath, getDevice().getSerialNumber());
+            getDevice().executeShellCommand(String.format("rm %s", fullJarPath));
+        }
+    }
+
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+    }
+
+    /**
+     * Checks that all mandatory member fields has been set.
+     */
+    protected void checkFields() {
+        if (mRunName == null) {
+            throw new IllegalArgumentException("run name has not been set");
+        }
+        if (mDevice == null) {
+            throw new IllegalArgumentException("Device has not been set");
+        }
+        if (mTestJars.isEmpty()) {
+            throw new IllegalArgumentException("No test jar has been set");
+        }
+        if (mTests == null) {
+            throw new IllegalArgumentException("tests has not been set");
+        }
+        if (mCtsBuild == null) {
+            throw new IllegalArgumentException("build has not been set");
+        }
+        for (String f : mTestJars) {
+            try {
+
+                mCtsBuild.getTestApp(f);
+            } catch (FileNotFoundException e) {
+                throw new IllegalArgumentException(String.format(
+                        "Could not find jar %s in CTS build %s", f,
+                        mCtsBuild.getRootDir().getAbsolutePath()));
+            }
+        }
+    }
+
+    /**
+     * Add runtime arguments to run the tests with.
+     *
+     * @param mRunTimeArgs
+     */
+    public void addRunTimeArgs(String mRunTimeArgs) {
+        mRuntimeArgs = mRunTimeArgs;
+    }
+}
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..9d9596e 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,10 +19,13 @@
 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.IAbi;
+import com.android.tradefed.testtype.IAbiReceiver;
 import com.android.tradefed.testtype.IBuildReceiver;
 import com.android.tradefed.testtype.IDeviceTest;
 import com.android.tradefed.testtype.IRemoteTest;
@@ -57,10 +60,17 @@
     private String mRunName;
     private CtsBuildHelper mCtsBuild = null;
     private IBuildInfo mBuildInfo = null;
-
+    private IAbi mAbi;
     private ClassLoader mClassLoader;
 
     /**
+     * @param abi the ABI to run the test on
+     */
+    public void setAbi(IAbi abi) {
+        mAbi = abi;
+    }
+
+    /**
      * {@inheritDoc}
      */
     @Override
@@ -131,7 +141,7 @@
      * Tests that take longer than this amount will be failed with a {@link TestTimeoutException}
      * as the cause.
      *
-     * @param testTimeout
+     * @param testTimeoutMs
      */
     void setTimeout(long testTimeoutMs) {
         mTimeoutMs = testTimeoutMs;
@@ -200,6 +210,9 @@
             deviceTest.setDevice(getDevice().getIDevice());
             deviceTest.setTestAppPath(mCtsBuild.getTestCasesDir().getAbsolutePath());
         }
+        if (junitTest instanceof IAbiReceiver) {
+            ((IAbiReceiver)junitTest).setAbi(mAbi);
+        }
         if (junitTest instanceof IBuildReceiver) {
             ((IBuildReceiver)junitTest).setBuild(mBuildInfo);
         }
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/PrintTestRemoteTestRunner.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/PrintTestRemoteTestRunner.java
new file mode 100644
index 0000000..3d92eb3
--- /dev/null
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/PrintTestRemoteTestRunner.java
@@ -0,0 +1,277 @@
+/*
+ * 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 com.android.cts.tradefed.testtype;
+
+import com.android.ddmlib.AdbCommandRejectedException;
+import com.android.ddmlib.IShellEnabledDevice;
+import com.android.ddmlib.Log;
+import com.android.ddmlib.ShellCommandUnresponsiveException;
+import com.android.ddmlib.TimeoutException;
+import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner;
+import com.android.ddmlib.testrunner.ITestRunListener;
+import com.android.ddmlib.testrunner.InstrumentationResultParser;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.TimeUnit;
+
+public class PrintTestRemoteTestRunner implements IRemoteAndroidTestRunner {
+
+    private final String mPackageName;
+    private final String mRunnerName;
+    private IShellEnabledDevice mRemoteDevice;
+    // default to no timeout
+    private long mMaxTimeToOutputResponse = 0;
+    private TimeUnit mMaxTimeUnits = TimeUnit.MILLISECONDS;
+    private String mRunName = null;
+
+    /** map of name-value instrumentation argument pairs */
+    private Map<String, String> mArgMap;
+    private InstrumentationResultParser mParser;
+
+    private static final String LOG_TAG = "RemoteAndroidTest";
+    private static final String DEFAULT_RUNNER_NAME = "android.test.InstrumentationTestRunner";
+
+    private static final char CLASS_SEPARATOR = ',';
+    private static final char METHOD_SEPARATOR = '#';
+    private static final char RUNNER_SEPARATOR = '/';
+
+    // defined instrumentation argument names
+    private static final String CLASS_ARG_NAME = "class";
+    private static final String LOG_ARG_NAME = "log";
+    private static final String DEBUG_ARG_NAME = "debug";
+    private static final String COVERAGE_ARG_NAME = "coverage";
+    private static final String PACKAGE_ARG_NAME = "package";
+    private static final String SIZE_ARG_NAME = "size";
+
+    // This command starts a shell Java program (installed by this class)
+    // in the folder owned by the shell user. This app creates a proxy
+    // which does privileged operations such as wiping a package's user
+    // data and then starts the tests passing the proxy. This enables
+    // the tests to clear the print spooler data.
+    private static final String INSTRUMENTATION_COMMAND =
+            "chmod 755 /data/local/tmp/print-instrument && "
+            + "/data/local/tmp/print-instrument instrument -w -r %1$s %2$s";
+
+    /**
+     * Creates a remote Android test runner.
+     *
+     * @param packageName the Android application package that contains the
+     *            tests to run
+     * @param runnerName the instrumentation test runner to execute. If null,
+     *            will use default runner
+     * @param remoteDevice the Android device to execute tests on
+     */
+    public PrintTestRemoteTestRunner(String packageName, String runnerName,
+            IShellEnabledDevice remoteDevice) {
+
+        mPackageName = packageName;
+        mRunnerName = runnerName;
+        mRemoteDevice = remoteDevice;
+        mArgMap = new Hashtable<String, String>();
+    }
+
+    /**
+     * Alternate constructor. Uses default instrumentation runner.
+     *
+     * @param packageName the Android application package that contains the
+     *            tests to run
+     * @param remoteDevice the Android device to execute tests on
+     */
+    public PrintTestRemoteTestRunner(String packageName, IShellEnabledDevice remoteDevice) {
+        this(packageName, null, remoteDevice);
+    }
+
+    @Override
+    public String getPackageName() {
+        return mPackageName;
+    }
+
+    @Override
+    public String getRunnerName() {
+        if (mRunnerName == null) {
+            return DEFAULT_RUNNER_NAME;
+        }
+        return mRunnerName;
+    }
+
+    /**
+     * Returns the complete instrumentation component path.
+     */
+    private String getRunnerPath() {
+        return getPackageName() + RUNNER_SEPARATOR + getRunnerName();
+    }
+
+    @Override
+    public void setClassName(String className) {
+        addInstrumentationArg(CLASS_ARG_NAME, className);
+    }
+
+    @Override
+    public void setClassNames(String[] classNames) {
+        StringBuilder classArgBuilder = new StringBuilder();
+
+        for (int i = 0; i < classNames.length; i++) {
+            if (i != 0) {
+                classArgBuilder.append(CLASS_SEPARATOR);
+            }
+            classArgBuilder.append(classNames[i]);
+        }
+        setClassName(classArgBuilder.toString());
+    }
+
+    @Override
+    public void setMethodName(String className, String testName) {
+        setClassName(className + METHOD_SEPARATOR + testName);
+    }
+
+    @Override
+    public void setTestPackageName(String packageName) {
+        addInstrumentationArg(PACKAGE_ARG_NAME, packageName);
+    }
+
+    @Override
+    public void addInstrumentationArg(String name, String value) {
+        if (name == null || value == null) {
+            throw new IllegalArgumentException("name or value arguments cannot be null");
+        }
+        mArgMap.put(name, value);
+    }
+
+    @Override
+    public void removeInstrumentationArg(String name) {
+        if (name == null) {
+            throw new IllegalArgumentException("name argument cannot be null");
+        }
+        mArgMap.remove(name);
+    }
+
+    @Override
+    public void addBooleanArg(String name, boolean value) {
+        addInstrumentationArg(name, Boolean.toString(value));
+    }
+
+    @Override
+    public void setLogOnly(boolean logOnly) {
+        addBooleanArg(LOG_ARG_NAME, logOnly);
+    }
+
+    @Override
+    public void setDebug(boolean debug) {
+        addBooleanArg(DEBUG_ARG_NAME, debug);
+    }
+
+    @Override
+    public void setCoverage(boolean coverage) {
+        addBooleanArg(COVERAGE_ARG_NAME, coverage);
+    }
+
+    @Override
+    public void setTestSize(TestSize size) {
+        addInstrumentationArg(SIZE_ARG_NAME, ""/*size.getRunnerValue()*/);
+    }
+
+    @Override
+    public void setMaxtimeToOutputResponse(int maxTimeToOutputResponse) {
+        setMaxTimeToOutputResponse(maxTimeToOutputResponse, TimeUnit.MILLISECONDS);
+    }
+
+    @Override
+    public void setMaxTimeToOutputResponse(long maxTimeToOutputResponse, TimeUnit maxTimeUnits) {
+        mMaxTimeToOutputResponse = maxTimeToOutputResponse;
+        mMaxTimeUnits = maxTimeUnits;
+    }
+
+    @Override
+    public void setRunName(String runName) {
+        mRunName = runName;
+    }
+
+    @Override
+    public void run(ITestRunListener... listeners) throws TimeoutException,
+            AdbCommandRejectedException, ShellCommandUnresponsiveException, IOException {
+        run(Arrays.asList(listeners));
+    }
+
+    @Override
+    public void run(Collection<ITestRunListener> listeners) throws TimeoutException,
+            AdbCommandRejectedException, ShellCommandUnresponsiveException, IOException {
+        final String runCaseCommandStr = String.format(INSTRUMENTATION_COMMAND,
+              getArgsCommand(), getRunnerPath());
+        Log.i(LOG_TAG,
+                String.format("Running %1$s on %2$s", runCaseCommandStr, mRemoteDevice.getName()));
+        String runName = mRunName == null ? mPackageName : mRunName;
+        mParser = new InstrumentationResultParser(runName, listeners);
+
+        try {
+            mRemoteDevice.executeShellCommand(runCaseCommandStr, mParser, mMaxTimeToOutputResponse,
+                    mMaxTimeUnits);
+        } catch (IOException e) {
+            Log.w(LOG_TAG, String.format("IOException %1$s when running tests %2$s on %3$s",
+                    e.toString(), getPackageName(), mRemoteDevice.getName()));
+            // rely on parser to communicate results to listeners
+            mParser.handleTestRunFailed(e.toString());
+            throw e;
+        } catch (ShellCommandUnresponsiveException e) {
+            Log.w(LOG_TAG, String.format(
+                    "ShellCommandUnresponsiveException %1$s when running tests %2$s on %3$s",
+                    e.toString(), getPackageName(), mRemoteDevice.getName()));
+            mParser.handleTestRunFailed(String
+                    .format("Failed to receive adb shell test output within %1$d ms. "
+                            + "Test may have timed out, or adb connection to device became"
+                            + "unresponsive", mMaxTimeToOutputResponse));
+            throw e;
+        } catch (TimeoutException e) {
+            Log.w(LOG_TAG, String.format("TimeoutException when running tests %1$s on %2$s",
+                    getPackageName(), mRemoteDevice.getName()));
+            mParser.handleTestRunFailed(e.toString());
+            throw e;
+        } catch (AdbCommandRejectedException e) {
+            Log.w(LOG_TAG, String.format(
+                    "AdbCommandRejectedException %1$s when running tests %2$s on %3$s",
+                    e.toString(), getPackageName(), mRemoteDevice.getName()));
+            mParser.handleTestRunFailed(e.toString());
+            throw e;
+        }
+    }
+
+    @Override
+    public void cancel() {
+        if (mParser != null) {
+            mParser.cancel();
+        }
+    }
+
+    /**
+     * Returns the full instrumentation command line syntax for the provided
+     * instrumentation arguments. Returns an empty string if no arguments were
+     * specified.
+     */
+    private String getArgsCommand() {
+        StringBuilder commandBuilder = new StringBuilder();
+        for (Entry<String, String> argPair : mArgMap.entrySet()) {
+            final String argCmd = String.format(" -e %1$s %2$s", argPair.getKey(),
+                    argPair.getValue());
+            commandBuilder.append(argCmd);
+        }
+        return commandBuilder.toString();
+    }
+}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/PrintTestRunner.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/PrintTestRunner.java
new file mode 100644
index 0000000..44d2d3a
--- /dev/null
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/PrintTestRunner.java
@@ -0,0 +1,232 @@
+/*
+ * 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 com.android.cts.tradefed.testtype;
+
+import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.cts.tradefed.targetprep.SettingsToggler;
+import com.android.cts.util.AbiUtils;
+import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner;
+import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner.TestSize;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.testtype.IAbi;
+import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.testtype.IDeviceTest;
+import com.android.tradefed.testtype.IRemoteTest;
+import com.android.tradefed.util.StringEscapeUtils;
+
+import java.io.FileNotFoundException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Running the print tests requires modification of secure settings. Secure
+ * settings cannot be changed from device CTS tests since system signature
+ * permission is required. Such settings can be modified by the shell user,
+ * so a host side test driver is used for enabling these services, running
+ * the tests, and disabling the services.
+ */
+public class PrintTestRunner implements IBuildReceiver, IRemoteTest, IDeviceTest  {
+
+    private static final String PRINT_TEST_AND_SERVICES_APP_NAME =
+            "CtsPrintTestCases.apk";
+
+    private static final String PRINT_TESTS_PACKAGE_NAME =
+            "com.android.cts.print";
+
+    private static final String FIRST_PRINT_SERVICE_NAME =
+            "android.print.cts.services.FirstPrintService";
+
+    private static final String SECOND_PRINT_SERVICE_NAME =
+            "android.print.cts.services.SecondPrintService";
+
+    private static final String SHELL_USER_FOLDER = "data/local/tmp";
+
+    private static final String PRINT_INSTRUMENT_JAR = "CtsPrintInstrument.jar";
+
+    private static final String PRINT_INSTRUMENT_SCRIPT = "print-instrument";
+
+    private ITestDevice mDevice;
+
+    private CtsBuildHelper mCtsBuild;
+
+    private IAbi mAbi;
+    private String mPackageName;
+    private String mRunnerName = "android.test.InstrumentationTestRunner";
+    private String mTestClassName;
+    private String mTestMethodName;
+    private String mTestPackageName;
+    private int mTestTimeout = 10 * 60 * 1000;  // 10 minutes
+    private String mTestSize;
+    private String mRunName = null;
+    private Map<String, String> mInstrArgMap = new HashMap<String, String>();
+
+    /**
+     * @param abi The ABI to run the test on
+     */
+    public void setAbi(IAbi abi) {
+        mAbi = abi;
+    }
+
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+    }
+
+    @Override
+    public void setDevice(ITestDevice device) {
+        mDevice = device;
+    }
+
+    @Override
+    public ITestDevice getDevice() {
+        return mDevice;
+    }
+
+    public void setPackageName(String packageName) {
+        mPackageName = packageName;
+    }
+
+    public void setRunnerName(String runnerName) {
+        mRunnerName = runnerName;
+    }
+
+    public void setClassName(String testClassName) {
+        mTestClassName = testClassName;
+    }
+
+    public void setMethodName(String testMethodName) {
+        mTestMethodName = StringEscapeUtils.escapeShell(testMethodName);
+    }
+
+    public void setTestPackageName(String testPackageName) {
+        mTestPackageName = testPackageName;
+    }
+
+    public void setTestSize(String size) {
+        mTestSize = size;
+    }
+
+    public void setRunName(String runName) {
+        mRunName = runName;
+    }
+
+    @Override
+    public void run(final ITestInvocationListener listener) throws DeviceNotAvailableException {
+        installShellProgramAndScriptFiles();
+        installTestsAndServicesApk();
+        enablePrintServices();
+        doRunTests(listener);
+        disablePrintServices();
+        uninstallTestsAndServicesApk();
+        uninstallShellProgramAndScriptFiles();
+    }
+
+    private void doRunTests(ITestInvocationListener listener)
+            throws DeviceNotAvailableException {
+        if (mPackageName == null) {
+            throw new IllegalArgumentException("package name has not been set");
+        }
+        if (mDevice == null) {
+            throw new IllegalArgumentException("Device has not been set");
+        }
+
+        IRemoteAndroidTestRunner runner =  new PrintTestRemoteTestRunner(mPackageName,
+                mRunnerName, mDevice.getIDevice());
+
+        if (mTestClassName != null) {
+            if (mTestMethodName != null) {
+                runner.setMethodName(mTestClassName, mTestMethodName);
+            } else {
+                runner.setClassName(mTestClassName);
+            }
+        } else if (mTestPackageName != null) {
+            runner.setTestPackageName(mTestPackageName);
+        }
+        if (mTestSize != null) {
+            runner.setTestSize(TestSize.getTestSize(mTestSize));
+        }
+        runner.setMaxTimeToOutputResponse(mTestTimeout, TimeUnit.MILLISECONDS);
+        if (mRunName != null) {
+            runner.setRunName(mRunName);
+        }
+        for (Map.Entry<String, String> argEntry : mInstrArgMap.entrySet()) {
+            runner.addInstrumentationArg(argEntry.getKey(), argEntry.getValue());
+        }
+
+        mDevice.runInstrumentationTests(runner, listener);
+    }
+
+    private void installShellProgramAndScriptFiles() throws DeviceNotAvailableException {
+        installFile(PRINT_INSTRUMENT_JAR);
+        installFile(PRINT_INSTRUMENT_SCRIPT);
+    }
+
+    private void installFile(String fileName) throws DeviceNotAvailableException {
+        try {
+            final boolean success = getDevice().pushFile(mCtsBuild.getTestApp(
+                    fileName), SHELL_USER_FOLDER + "/" + fileName);
+            if (!success) {
+                throw new IllegalArgumentException("Failed to install "
+                        + fileName + " on " + getDevice().getSerialNumber());
+           }
+        } catch (FileNotFoundException fnfe) {
+            throw new IllegalArgumentException("Cannot find file: " + fileName);
+        }
+    }
+
+    private void uninstallShellProgramAndScriptFiles() throws DeviceNotAvailableException {
+        getDevice().executeShellCommand("rm " + SHELL_USER_FOLDER + "/"
+                + PRINT_INSTRUMENT_JAR);
+        getDevice().executeShellCommand("rm " + SHELL_USER_FOLDER + "/"
+                + PRINT_INSTRUMENT_SCRIPT);
+    }
+
+    private void installTestsAndServicesApk() throws DeviceNotAvailableException {
+        try {
+            String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+            String installCode = getDevice().installPackage(mCtsBuild.getTestApp(
+                    PRINT_TEST_AND_SERVICES_APP_NAME), true, options);
+            if (installCode != null) {
+                throw new IllegalArgumentException("Failed to install "
+                        + PRINT_TEST_AND_SERVICES_APP_NAME + " on " + getDevice().getSerialNumber()
+                        + ". Reason: " + installCode);
+           }
+        } catch (FileNotFoundException fnfe) {
+            throw new IllegalArgumentException("Cannot find file: "
+                    + PRINT_TEST_AND_SERVICES_APP_NAME);
+        }
+    }
+
+    private void uninstallTestsAndServicesApk() throws DeviceNotAvailableException {
+        getDevice().uninstallPackage(PRINT_TESTS_PACKAGE_NAME);
+    }
+
+    private void enablePrintServices() throws DeviceNotAvailableException {
+        String enabledServicesValue = PRINT_TESTS_PACKAGE_NAME + "/" + FIRST_PRINT_SERVICE_NAME
+                + ":" + PRINT_TESTS_PACKAGE_NAME + "/" + SECOND_PRINT_SERVICE_NAME;
+        SettingsToggler.setSecureString(getDevice(), "enabled_print_services",
+                enabledServicesValue);
+    }
+
+    private void disablePrintServices() throws DeviceNotAvailableException {
+        SettingsToggler.setSecureString(getDevice(), "enabled_print_services", "");
+    }
+}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ResultFilter.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ResultFilter.java
index e8fdad81..f4f2f5d 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ResultFilter.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/ResultFilter.java
@@ -24,10 +24,9 @@
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
-import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * A {@link ITestInvocationListener} that filters test results based on the set of expected tests
@@ -38,37 +37,35 @@
  */
 class ResultFilter extends ResultForwarder {
 
-    private final Map<String, Collection<TestIdentifier>> mKnownTestsMap;
-    private final Map<String, Collection<TestIdentifier>> mRemainingTestsMap;
-    private String mCurrentTestRun = null;
+    private final Set<TestIdentifier> mKnownTests;
+    private final Set<TestIdentifier> mRemainingTests;
+    private final String mTestRun;
 
     /**
      * Create a {@link ResultFilter}.
      *
      * @param listener the real {@link ITestInvocationListener} to forward results to
      */
-    ResultFilter(ITestInvocationListener listener, List<TestPackage> testPackages) {
+    ResultFilter(ITestInvocationListener listener, TestPackage testPackage) {
         super(listener);
-
-        mKnownTestsMap = new HashMap<String, Collection<TestIdentifier>>();
+        mTestRun = testPackage.getTestRunName();
+        Collection<TestIdentifier> tests = testPackage.getKnownTests();
+        mKnownTests = new HashSet<TestIdentifier>(tests);
         // use LinkedHashMap for predictable test order
-        mRemainingTestsMap = new LinkedHashMap<String, Collection<TestIdentifier>>();
-
-        for (TestPackage testPkg : testPackages) {
-            mKnownTestsMap.put(testPkg.getTestRunName(), new HashSet<TestIdentifier>(
-                    testPkg.getKnownTests()));
-            mRemainingTestsMap.put(testPkg.getTestRunName(), new LinkedHashSet<TestIdentifier>(
-                    testPkg.getKnownTests()));
-        }
+        mRemainingTests = new LinkedHashSet<TestIdentifier>(tests);
     }
 
+
     /**
      * {@inheritDoc}
      */
     @Override
     public void testRunStarted(String runName, int testCount) {
-        super.testRunStarted(runName, testCount);
-        mCurrentTestRun = runName;
+        if (mTestRun.equals(runName)) {
+            super.testRunStarted(runName, testCount);
+        } else {
+            CLog.d("Skipping reporting unknown test run %s", runName);
+        }
     }
 
     /**
@@ -87,9 +84,9 @@
      * {@inheritDoc}
      */
     @Override
-    public void testFailed(TestFailure status, TestIdentifier test, String trace) {
+    public void testFailed(TestIdentifier test, String trace) {
         if (isKnownTest(test)) {
-            super.testFailed(status, test, trace);
+            super.testFailed(test, trace);
         }
     }
 
@@ -109,10 +106,7 @@
      * @return
      */
     private boolean isKnownTest(TestIdentifier test) {
-        if (mCurrentTestRun != null && mKnownTestsMap.containsKey(mCurrentTestRun)) {
-            return mKnownTestsMap.get(mCurrentTestRun).contains(test);
-        }
-        return false;
+        return mKnownTests.contains(test);
     }
 
     /**
@@ -120,26 +114,28 @@
      * @param test
      */
     private void removeExecutedTest(TestIdentifier test) {
-        if (mCurrentTestRun != null && mRemainingTestsMap.containsKey(mCurrentTestRun)) {
-             mRemainingTestsMap.get(mCurrentTestRun).remove(test);
-        }
+        mRemainingTests.remove(test);
     }
 
     /**
      * Report the set of expected tests that were not executed
      */
     public void reportUnexecutedTests() {
-        for (Map.Entry<String, Collection<TestIdentifier>> entry : mRemainingTestsMap.entrySet()) {
-            if (!entry.getValue().isEmpty()) {
-                super.testRunStarted(entry.getKey(), entry.getValue().size());
-                for (TestIdentifier test : entry.getValue()) {
-                    // an unexecuted test is currently reported as a 'testStarted' event without a
-                    // 'testEnded'. TODO: consider adding an explict API for reporting an unexecuted
-                    // test
-                    super.testStarted(test);
-                }
-                super.testRunEnded(0, new HashMap<String,String>());
-            }
+        if (mRemainingTests.isEmpty()) {
+            return;
         }
+        super.testRunStarted(mTestRun, mRemainingTests.size());
+        for (TestIdentifier test : mRemainingTests) {
+            // an unexecuted test is currently reported as a 'testStarted' event without a
+            // 'testEnded'. TODO: consider adding an explict API for reporting an unexecuted
+            // test
+            super.testStarted(test);
+        }
+        super.testRunEnded(0, new HashMap<String, String>());
+    }
+
+    /** @return the number of known tests */
+    public int getKnownTestCount() {
+        return mKnownTests.size();
     }
 }
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/SingleJUnitTestResultParser.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/SingleJUnitTestResultParser.java
new file mode 100644
index 0000000..150d265
--- /dev/null
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/SingleJUnitTestResultParser.java
@@ -0,0 +1,96 @@
+/*
+ * 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 com.android.cts.tradefed.testtype;
+
+import com.android.ddmlib.MultiLineReceiver;
+import com.android.ddmlib.testrunner.ITestRunListener;
+import com.android.ddmlib.testrunner.TestIdentifier;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * Parses the test results from {@link com.android.cts.junit.SingleJUnitTestRunner}
+ */
+public class SingleJUnitTestResultParser extends MultiLineReceiver {
+
+    private static final String PASSED_TEST_MARKER = "[ PASSED ]";
+    private static final String FAILED_TEST_MARKER = "[ FAILED ]";
+    private final TestIdentifier mTestId;
+    private final Collection<ITestRunListener> mTestListeners;
+    private StringBuilder mStackTrace = new StringBuilder();
+
+    public SingleJUnitTestResultParser(TestIdentifier testId, Collection<ITestRunListener> listeners) {
+        mTestId = testId;
+        mTestListeners = new ArrayList<ITestRunListener>(listeners);
+    }
+
+    public SingleJUnitTestResultParser(TestIdentifier testId, ITestRunListener listener) {
+        mTestId = testId;
+        mTestListeners = new ArrayList<ITestRunListener>(1);
+        mTestListeners.add(listener);
+    }
+
+    @Override
+    public boolean isCancelled() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public void processNewLines(String[] lines) {
+        for (String line : lines) {
+            parse(line);
+        }
+    }
+
+    /**
+     * Parses a given string.
+     * @param line
+     */
+    private void parse(String line) {
+        if (line.startsWith(PASSED_TEST_MARKER)) {
+            doTestEnded(true);
+        } else if (line.startsWith(FAILED_TEST_MARKER)) {
+            doTestEnded(false);
+        } else {
+            // Store everything in case there is a failure.
+            mStackTrace.append("\n");
+            mStackTrace.append(line);
+        }
+    }
+
+    /**
+     * Handle cases when test ends.
+     * @param testPassed whether or not the test passed.
+     */
+    private void doTestEnded(boolean testPassed) {
+        // If test failed.
+        if (!testPassed) {
+            for (ITestRunListener listener : mTestListeners) {
+                listener.testFailed(mTestId, mStackTrace.toString());
+            }
+        }
+        Map<String, String> emptyMap = Collections.emptyMap();
+        for (ITestRunListener listener : mTestListeners) {
+            listener.testEnded(mTestId, emptyMap);
+        }
+        mStackTrace = new StringBuilder();
+    }
+}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestFilter.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestFilter.java
index f1a0485..4d1b3e2 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestFilter.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestFilter.java
@@ -25,6 +25,7 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.regex.Pattern;
 
 /**
  * Filter for {@link TestIdentifier}s.
@@ -38,7 +39,7 @@
     private final Set<TestIdentifier> mIncludedTests;
 
     private String mIncludedClass = null;
-    private String mIncludedMethod = null;
+    private Pattern mIncludedMethod = null;
 
     /**
      * Creates a {@link TestFilter}
@@ -124,7 +125,9 @@
      */
     public void setTestInclusion(String className, String method) {
         mIncludedClass = className;
-        mIncludedMethod = method;
+        if (method != null) {
+            mIncludedMethod = Pattern.compile(method);
+        }
     }
 
     /**
@@ -140,7 +143,7 @@
                 // skip
                 continue;
             }
-            if (mIncludedMethod != null && !test.getTestName().equals(mIncludedMethod)) {
+            if (mIncludedMethod != null && !mIncludedMethod.matcher(test.getTestName()).matches()) {
                 // skip
                 continue;
             }
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java
index 8ab5d18..9ef6257 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java
@@ -16,9 +16,11 @@
 
 package com.android.cts.tradefed.testtype;
 
+import com.android.cts.util.AbiUtils;
 import com.android.ddmlib.Log.LogLevel;
 import com.android.ddmlib.testrunner.TestIdentifier;
 import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.testtype.IAbi;
 import com.android.tradefed.testtype.IRemoteTest;
 import com.android.tradefed.testtype.InstrumentationTest;
 import com.android.tradefed.util.StreamUtil;
@@ -46,27 +48,28 @@
     public static final String NATIVE_TEST = "native";
     public static final String WRAPPED_NATIVE_TEST = "wrappednative";
     public static final String VM_HOST_TEST = "vmHostTest";
+    public static final String DEQP_TEST = "deqpTest";
     public static final String ACCESSIBILITY_TEST =
-        "com.android.cts.tradefed.testtype.AccessibilityTestRunner";
+            "com.android.cts.tradefed.testtype.AccessibilityTestRunner";
     public static final String ACCESSIBILITY_SERVICE_TEST =
-        "com.android.cts.tradefed.testtype.AccessibilityServiceTestRunner";
+            "com.android.cts.tradefed.testtype.AccessibilityServiceTestRunner";
+    public static final String PRINT_TEST =
+            "com.android.cts.tradefed.testtype.PrintTestRunner";
     public static final String DISPLAY_TEST =
             "com.android.cts.tradefed.testtype.DisplayTestRunner";
     public static final String UIAUTOMATOR_TEST = "uiAutomator";
+    public static final String JUNIT_DEVICE_TEST = "jUnitDeviceTest";
 
-    private static final String SIGNATURE_TEST_METHOD = "testSignature";
-    private static final String SIGNATURE_TEST_CLASS = "android.tests.sigtest.SignatureTest";
-
-    private String mUri = null;
+    private String mAppPackageName = null;
     private String mAppNameSpace = null;
     private String mName = null;
     private String mRunner = null;
-    private boolean mIsVMHostTest = false;
     private String mTestType = null;
     private String mJarPath = null;
-    private boolean mIsSignatureTest = false;
+    private String mRunTimeArgs = null;
     private String mTestPackageName = null;
     private String mDigest = null;
+    private IAbi mAbi = null;
 
     // use a LinkedHashSet for predictable iteration insertion-order, and fast
     // lookups
@@ -77,7 +80,7 @@
     // dynamic options, not parsed from package xml
     private String mClassName;
     private String mMethodName;
-    private TestFilter mExcludedTestFilter = new TestFilter();
+    private TestFilter mTestFilter = new TestFilter();
     private String mTargetBinaryName;
     private String mTargetNameSpace;
     // only timeout per package is supported. To change this to method granularity,
@@ -85,16 +88,36 @@
     // So for now, only max timeout for the package is used.
     private int mTimeoutInMins = -1;
 
-    void setUri(String uri) {
-        mUri = uri;
+    @Override
+    public IAbi getAbi() {
+        return mAbi;
     }
 
     /**
-     * {@inheritDoc}
+     * @param abi the ABI to run this package on
+     */
+    public void setAbi(IAbi abi) {
+        mAbi = abi;
+    }
+
+    /**
+     * @return unique id representing this test package for this ABI.
      */
     @Override
-    public String getUri() {
-        return mUri;
+    public String getId() {
+        return AbiUtils.createId(getAbi().getName(), getAppPackageName());
+    }
+
+    void setAppPackageName(String appPackageName) {
+        mAppPackageName = appPackageName;
+    }
+
+    String getAppPackageName() {
+        return mAppPackageName;
+    }
+
+    void setRunTimeArgs(String runTimeArgs) {
+        mRunTimeArgs = runTimeArgs;
     }
 
     void setAppNameSpace(String appNameSpace) {
@@ -141,14 +164,6 @@
         return mJarPath;
     }
 
-    void setIsSignatureCheck(boolean isSignatureCheckTest) {
-        mIsSignatureTest = isSignatureCheckTest;
-    }
-
-    boolean isSignatureCheck() {
-        return mIsSignatureTest;
-    }
-
     void setTestPackageName(String testPackageName) {
         mTestPackageName = testPackageName;
     }
@@ -181,8 +196,8 @@
      * {@inheritDoc}
      */
     @Override
-    public void setExcludedTestFilter(TestFilter excludeFilter) {
-        mExcludedTestFilter = excludeFilter;
+    public void setTestFilter(TestFilter testFilter) {
+        mTestFilter = testFilter;
     }
 
     /**
@@ -199,7 +214,7 @@
      */
     @Override
     public IRemoteTest createTest(File testCaseDir) {
-        mExcludedTestFilter.setTestInclusion(mClassName, mMethodName);
+        mTestFilter.setTestInclusion(mClassName, mMethodName);
         mTests = filterTests();
 
         if (HOST_SIDE_ONLY_TEST.equals(mTestType)) {
@@ -209,28 +224,42 @@
                 CLog.d("Setting new timeout to " + mTimeoutInMins + " mins");
                 hostTest.setTimeout(mTimeoutInMins * 60 * 1000);
             }
-            hostTest.setRunName(getUri());
+            hostTest.setRunName(mAppPackageName);
             hostTest.setJarFileName(mJarPath);
             hostTest.setTests(mTests);
+            hostTest.setAbi(mAbi);
             mDigest = generateDigest(testCaseDir, mJarPath);
             return hostTest;
         } else if (VM_HOST_TEST.equals(mTestType)) {
             CLog.d("Creating vm host test for %s", mName);
             VMHostTest vmHostTest = new VMHostTest();
-            vmHostTest.setRunName(getUri());
+            vmHostTest.setRunName(mAppPackageName);
             vmHostTest.setJarFileName(mJarPath);
             vmHostTest.setTests(mTests);
+            vmHostTest.setAbi(mAbi);
             mDigest = generateDigest(testCaseDir, mJarPath);
             return vmHostTest;
+        } else if (DEQP_TEST.equals(mTestType)) {
+            DeqpTestRunner deqpTest = new DeqpTestRunner(mAppPackageName, mName, mTests);
+            deqpTest.setAbi(mAbi);
+            return deqpTest;
         } else if (NATIVE_TEST.equals(mTestType)) {
-            return new GeeTest(mUri, mName);
+            GeeTest geeTest = new GeeTest(mAppPackageName, mName);
+            geeTest.setAbi(mAbi);
+            return geeTest;
         } else if (WRAPPED_NATIVE_TEST.equals(mTestType)) {
             CLog.d("Creating new wrapped native test for %s", mName);
-            return new WrappedGTest(mAppNameSpace, mUri, mName, mRunner);
+            WrappedGTest wrappedGeeTest = new WrappedGTest(mAppNameSpace, mAppPackageName, mName, mRunner);
+            wrappedGeeTest.setAbi(mAbi);
+            return wrappedGeeTest;
         } else if (ACCESSIBILITY_TEST.equals(mTestType)) {
             AccessibilityTestRunner test = new AccessibilityTestRunner();
             return setInstrumentationTest(test, testCaseDir);
+        } else if (PRINT_TEST.equals(mTestType)) {
+            PrintTestRunner test = new PrintTestRunner();
+            return setPrintTest(test, testCaseDir);
         } else if (ACCESSIBILITY_SERVICE_TEST.equals(mTestType)) {
+            @SuppressWarnings("deprecation")
             AccessibilityServiceTestRunner test = new AccessibilityServiceTestRunner();
             return setInstrumentationTest(test, testCaseDir);
         } else if (DISPLAY_TEST.equals(mTestType)) {
@@ -239,27 +268,19 @@
         } else if (UIAUTOMATOR_TEST.equals(mTestType)) {
             UiAutomatorJarTest uiautomatorTest = new UiAutomatorJarTest();
             return setUiAutomatorTest(uiautomatorTest);
-        } else if (mIsSignatureTest) {
-            // TODO: hardcode the runner/class/method for now, since current package xml points to
-            // specialized instrumentation. Eventually this special case for signatureTest can be
-            // removed, and it can be treated just like a normal InstrumentationTest
-            CLog.d("Creating signature test %s", mName);
-            InstrumentationApkTest instrTest = new InstrumentationApkTest();
-            instrTest.setPackageName(mAppNameSpace);
-            instrTest.setRunnerName("android.test.InstrumentationTestRunner");
-            instrTest.setClassName(SIGNATURE_TEST_CLASS);
-            instrTest.setMethodName(SIGNATURE_TEST_METHOD);
-            // set expected tests to the single signature test
-            TestIdentifier t = new TestIdentifier(SIGNATURE_TEST_CLASS, SIGNATURE_TEST_METHOD);
-            mTests.clear();
-            mTests.add(t);
-            // mName means 'apk file name' for instrumentation tests
-            instrTest.addInstallApk(String.format("%s.apk", mName), mAppNameSpace);
-            mDigest = generateDigest(testCaseDir, String.format("%s.apk", mName));
-            return instrTest;
+        } else if (JUNIT_DEVICE_TEST.equals(mTestType)){
+            CLog.d("Creating JUnit device test %s", mName);
+            JUnitDeviceTest jUnitDeviceTest = new JUnitDeviceTest();
+            jUnitDeviceTest.setRunName(mAppPackageName);
+            jUnitDeviceTest.addTestJarFileName(mJarPath);
+            jUnitDeviceTest.addRunTimeArgs(mRunTimeArgs);
+            jUnitDeviceTest.setTests(mTests);
+            jUnitDeviceTest.setAbi(mAbi);
+            mDigest = generateDigest(testCaseDir, mJarPath);
+            return jUnitDeviceTest;
         } else {
             CLog.d("Creating instrumentation test for %s", mName);
-            InstrumentationApkTest instrTest = new InstrumentationApkTest();
+            CtsInstrumentationApkTest instrTest = new CtsInstrumentationApkTest();
             if (mTimeoutInMins >= 0) {
                 // as timeout cannot be set for each test,
                 // increase the time-out of the whole package
@@ -270,24 +291,38 @@
         }
     }
 
+    private PrintTestRunner setPrintTest(PrintTestRunner printTest,
+            File testCaseDir) {
+        printTest.setRunName(mAppPackageName);
+        printTest.setPackageName(mAppNameSpace);
+        printTest.setRunnerName(mRunner);
+        printTest.setTestPackageName(mTestPackageName);
+        printTest.setClassName(mClassName);
+        printTest.setMethodName(mMethodName);
+        printTest.setAbi(mAbi);
+        mDigest = generateDigest(testCaseDir, String.format("%s.apk", mName));
+        return printTest;
+    }
+
     /**
-     * Populates given {@link InstrumentationApkTest} with data from the package xml.
+     * Populates given {@link CtsInstrumentationApkTest} with data from the package xml.
      *
      * @param testCaseDir
      * @param instrTest
      * @return the populated {@link InstrumentationTest} or <code>null</code>
      */
-    private InstrumentationTest setInstrumentationTest(InstrumentationApkTest instrTest,
+    private InstrumentationTest setInstrumentationTest(CtsInstrumentationApkTest instrTest,
             File testCaseDir) {
-        instrTest.setRunName(getUri());
+        instrTest.setRunName(mAppPackageName);
         instrTest.setPackageName(mAppNameSpace);
         instrTest.setRunnerName(mRunner);
         instrTest.setTestPackageName(mTestPackageName);
         instrTest.setClassName(mClassName);
         instrTest.setMethodName(mMethodName);
-        instrTest.setTestsToRun(mTests,
-                !mExcludedTestFilter.hasExclusion()
-                /* only force batch mode if no tests are excluded */);
+        instrTest.setAbi(mAbi);
+        instrTest.setTestsToRun(mTests, false
+            /* force batch mode off to always run using testFile */);
+        instrTest.setReRunUsingTestFile(true);
         // mName means 'apk file name' for instrumentation tests
         instrTest.addInstallApk(String.format("%s.apk", mName), mAppNameSpace);
         mDigest = generateDigest(testCaseDir, String.format("%s.apk", mName));
@@ -304,6 +339,7 @@
      * @param uiautomatorTest
      * @return the populated {@link UiAutomatorJarTest} or <code>null</code>
      */
+    @SuppressWarnings("deprecation")
     private IRemoteTest setUiAutomatorTest(UiAutomatorJarTest uiautomatorTest) {
         uiautomatorTest.setInstallArtifacts(getJarPath());
         if (mClassName != null) {
@@ -315,34 +351,22 @@
         } else {
             uiautomatorTest.addClassNames(mTestClasses);
         }
-        uiautomatorTest.setRunName(getUri());
+        uiautomatorTest.setRunName(mAppPackageName);
         uiautomatorTest.setCaptureLogs(false);
         return uiautomatorTest;
     }
 
     /**
-     * Filter the tests to run based on list of excluded tests, class and method name.
+     * Filter the tests to run based on list of included/excluded tests, class and method name.
      *
      * @return the filtered collection of tests
      */
     private Collection<TestIdentifier> filterTests() {
-        mExcludedTestFilter.setTestInclusion(mClassName, mMethodName);
-        return mExcludedTestFilter.filter(mTests);
+        mTestFilter.setTestInclusion(mClassName, mMethodName);
+        return mTestFilter.filter(mTests);
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean isKnownTest(TestIdentifier testDef) {
-        return mTests.contains(testDef);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean isKnownTestClass(String className) {
+    boolean isKnownTestClass(String className) {
         return mTestClasses.contains(className);
     }
 
@@ -362,7 +386,7 @@
     }
 
     /**
-     * Get the collection of tests in this test package.
+     * {@inheritDoc}
      */
     @Override
     public Collection<TestIdentifier> getTests() {
@@ -427,10 +451,15 @@
      * @return The hex encoded string.
      */
     private String toHexString(byte[] arr) {
-        StringBuffer buf = new StringBuffer(arr.length * 2);
+        StringBuilder buf = new StringBuilder(arr.length * 2);
         for (byte b : arr) {
             buf.append(String.format("%02x", b & 0xFF));
         }
         return buf.toString();
     }
+
+    @Override
+    public int compareTo(ITestPackageDef testPackageDef) {
+        return getId().compareTo(testPackageDef.getId());
+    }
 }
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageRepo.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageRepo.java
index 0f3704d..aea6613 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageRepo.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageRepo.java
@@ -15,6 +15,7 @@
  */
 package com.android.cts.tradefed.testtype;
 
+import com.android.cts.util.AbiUtils;
 import com.android.ddmlib.Log;
 import com.android.tradefed.util.xml.AbstractXmlParser.ParseException;
 
@@ -25,11 +26,12 @@
 import java.io.FilenameFilter;
 import java.io.InputStream;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
-import java.util.Hashtable;
+import java.util.HashSet;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * Retrieves CTS test package definitions from the repository.
@@ -38,23 +40,21 @@
 
     private static final String LOG_TAG = "TestCaseRepo";
 
-    private final File mTestCaseDir;
-
-    /** mapping of uri to test definition */
-    private final Map<String, TestPackageDef> mTestMap;
-
+    /** mapping of ABI to a mapping of appPackageName to test definition */
+    private final Map<String, Map<String, TestPackageDef>> mTestMap;
     private final boolean mIncludeKnownFailures;
 
     /**
      * Creates a {@link TestPackageRepo}, initialized from provided repo files
      *
      * @param testCaseDir directory containing all test case definition xml and build files
+     * ABIs supported by the device under test.
+     * @param includeKnownFailures Whether to run tests which are known to fail.
      */
     public TestPackageRepo(File testCaseDir, boolean includeKnownFailures) {
-        mTestCaseDir = testCaseDir;
-        mTestMap = new Hashtable<String, TestPackageDef>();
+        mTestMap = new HashMap<>();
         mIncludeKnownFailures = includeKnownFailures;
-        parse(mTestCaseDir);
+        parse(testCaseDir);
     }
 
     /**
@@ -71,13 +71,19 @@
         TestPackageXmlParser parser = new TestPackageXmlParser(mIncludeKnownFailures);
         try {
             parser.parse(createStreamFromFile(xmlFile));
-            TestPackageDef def = parser.getTestPackageDef();
-            if (def != null) {
-                mTestMap.put(def.getUri(), def);
-            } else {
+            Set<TestPackageDef> defs = parser.getTestPackageDefs();
+            if (defs.isEmpty()) {
                 Log.w(LOG_TAG, String.format("Could not find test package info in xml file %s",
                         xmlFile.getAbsolutePath()));
             }
+            for (TestPackageDef def : defs) {
+                String name = def.getAppPackageName();
+                String abi = def.getAbi().getName();
+                if (!mTestMap.containsKey(abi)) {
+                    mTestMap.put(abi, new HashMap<String, TestPackageDef>());
+                }
+                mTestMap.get(abi).put(name, def);
+            }
         } catch (FileNotFoundException e) {
             Log.e(LOG_TAG, String.format("Could not find test case xml file %s",
                     xmlFile.getAbsolutePath()));
@@ -94,7 +100,7 @@
      * <p/>
      * Exposed for unit testing
      *
-     * @param xmlFile
+     * @param xmlFile The file containing the xml description of the package
      * @return stream to read data
      *
      */
@@ -117,31 +123,85 @@
      * {@inheritDoc}
      */
     @Override
-    public ITestPackageDef getTestPackage(String testUri) {
-        return mTestMap.get(testUri);
+    public ITestPackageDef getTestPackage(String id) {
+        String[] parts = AbiUtils.parseId(id);
+        String abi = parts[0];
+        String name = parts[1];
+        if (mTestMap.containsKey(abi) && mTestMap.get(abi).containsKey(name)) {
+            return mTestMap.get(abi).get(name);
+        }
+        return null;
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public String findPackageForTest(String testClassName) {
-        for (Map.Entry<String, TestPackageDef> entry : mTestMap.entrySet()) {
-            if (entry.getValue().isKnownTestClass(testClassName)) {
-                return entry.getKey();
+    public List<String> getPackageIds() {
+        Set<String> ids = new HashSet<>();
+        for (String abi : mTestMap.keySet()) {
+            Map<String, TestPackageDef> testNameMap = mTestMap.get(abi);
+            for (TestPackageDef testPackageDef : testNameMap.values()) {
+                ids.add(testPackageDef.getId());
             }
         }
-        return null;
+        List<String> idList = new ArrayList<>(ids);
+        Collections.sort(idList);
+        return idList;
     }
 
     /**
-     * @return list of all package names found in repo
+     * {@inheritDoc}
      */
     @Override
-    public Collection<String> getPackageNames() {
-        List<String> packageNames = new ArrayList<String>();
-        packageNames.addAll(mTestMap.keySet());
-        Collections.sort(packageNames);
-        return packageNames;
+    public List<String> getPackageNames() {
+        Set<String> nameSet = new HashSet<String>();
+        for (String abi : mTestMap.keySet()) {
+            Map<String, TestPackageDef> testNameMap = mTestMap.get(abi);
+            for (TestPackageDef testPackageDef : testNameMap.values()) {
+                nameSet.add(AbiUtils.parseTestName(testPackageDef.getId()));
+            }
+        }
+        List<String> nameList = new ArrayList<>(nameSet);
+        Collections.sort(nameList);
+        return nameList;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Map<String, List<ITestPackageDef>> getTestPackageDefsByName() {
+        Map<String, List<ITestPackageDef>> packageDefMap =
+                new HashMap<String, List<ITestPackageDef>>();
+
+        for (String abi : mTestMap.keySet()) {
+            Map<String, TestPackageDef> testNameMap = mTestMap.get(abi);
+            for (String packageName : testNameMap.keySet()) {
+                if (!packageDefMap.containsKey(packageName)) {
+                    packageDefMap.put(packageName, new ArrayList<ITestPackageDef>());
+                }
+                packageDefMap.get(packageName).add(testNameMap.get(packageName));
+            }
+        }
+        return packageDefMap;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public List<String> findPackageIdsForTest(String testClassName) {
+        Set<String> ids = new HashSet<String>();
+        for (String abi : mTestMap.keySet()) {
+            for (String name : mTestMap.get(abi).keySet()) {
+                if (mTestMap.get(abi).get(name).isKnownTestClass(testClassName)) {
+                    ids.add(AbiUtils.createId(abi, name));
+                }
+            }
+        }
+        List<String> idList = new ArrayList<String>(ids);
+        Collections.sort(idList);
+        return idList;
     }
 }
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageXmlParser.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageXmlParser.java
index bd67f78..baceb8b 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageXmlParser.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageXmlParser.java
@@ -15,6 +15,7 @@
  */
 package com.android.cts.tradefed.testtype;
 
+import com.android.cts.util.AbiUtils;
 import com.android.ddmlib.Log;
 import com.android.ddmlib.testrunner.TestIdentifier;
 import com.android.tradefed.util.xml.AbstractXmlParser;
@@ -22,7 +23,11 @@
 import org.xml.sax.Attributes;
 import org.xml.sax.helpers.DefaultHandler;
 
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
 import java.util.Stack;
 
 /**
@@ -37,8 +42,11 @@
 
     private final boolean mIncludeKnownFailures;
 
-    private TestPackageDef mPackageDef;
+    private Map<String, TestPackageDef> mPackageDefs = new HashMap<String, TestPackageDef>();
 
+    /**
+     * @param includeKnownFailures Whether to run tests which are known to fail.
+     */
     public TestPackageXmlParser(boolean includeKnownFailures) {
         mIncludeKnownFailures = includeKnownFailures;
     }
@@ -65,30 +73,35 @@
         @Override
         public void startElement(String uri, String localName, String name, Attributes attributes) {
             if (TEST_PACKAGE_TAG.equals(localName)) {
-                // appPackageName is used as the uri
-                final String entryUriValue = attributes.getValue("appPackageName");
+                final String appPackageName = attributes.getValue("appPackageName");
                 final String testPackageNameSpace = attributes.getValue("appNameSpace");
                 final String packageName = attributes.getValue("name");
                 final String runnerName = attributes.getValue("runner");
                 final String jarPath = attributes.getValue("jarPath");
-                final String signatureCheck = attributes.getValue("signatureCheck");
                 final String javaPackageFilter = attributes.getValue("javaPackageFilter");
                 final String targetBinaryName = attributes.getValue("targetBinaryName");
                 final String targetNameSpace = attributes.getValue("targetNameSpace");
+                final String runTimeArgs = attributes.getValue("runtimeArgs");
+                final String testType = getTestType(attributes);
 
-                mPackageDef = new TestPackageDef();
-                mPackageDef.setUri(entryUriValue);
-                mPackageDef.setAppNameSpace(testPackageNameSpace);
-                mPackageDef.setName(packageName);
-                mPackageDef.setRunner(runnerName);
-                mPackageDef.setTestType(getTestType(attributes));
-                mPackageDef.setJarPath(jarPath);
-                mPackageDef.setIsSignatureCheck(parseBoolean(signatureCheck));
-                if (!"".equals(javaPackageFilter)) {
-                    mPackageDef.setTestPackageName(javaPackageFilter);
+                for (String abiName : AbiUtils.getAbisSupportedByCts()) {
+                    Abi abi = new Abi(abiName, AbiUtils.getBitness(abiName));
+                    TestPackageDef packageDef = new TestPackageDef();
+                    packageDef.setAppPackageName(appPackageName);
+                    packageDef.setAppNameSpace(testPackageNameSpace);
+                    packageDef.setName(packageName);
+                    packageDef.setRunner(runnerName);
+                    packageDef.setTestType(testType);
+                    packageDef.setJarPath(jarPath);
+                    packageDef.setRunTimeArgs(runTimeArgs);
+                    if (!"".equals(javaPackageFilter)) {
+                        packageDef.setTestPackageName(javaPackageFilter);
+                    }
+                    packageDef.setTargetBinaryName(targetBinaryName);
+                    packageDef.setTargetNameSpace(targetNameSpace);
+                    packageDef.setAbi(abi);
+                    mPackageDefs.put(abiName, packageDef);
                 }
-                mPackageDef.setTargetBinaryName(targetBinaryName);
-                mPackageDef.setTargetNameSpace(targetNameSpace);
 
                 // reset the class name
                 mClassNameStack = new Stack<String>();
@@ -110,7 +123,7 @@
                 }
             } else if (TEST_TAG.equals(localName)) {
                 String methodName = attributes.getValue("name");
-                if (mPackageDef == null) {
+                if (mPackageDefs.isEmpty()) {
                     Log.e(LOG_TAG, String.format(
                             "Invalid XML: encountered a '%s' tag not enclosed within a '%s' tag",
                             TEST_TAG, TEST_PACKAGE_TAG));
@@ -131,11 +144,24 @@
                     if (timeoutStr != null) {
                         timeout = Integer.parseInt(timeoutStr);
                     }
-                    TestIdentifier testId = new TestIdentifier(classNameBuilder.toString(),
-                            methodName);
                     boolean isKnownFailure = "failure".equals(attributes.getValue("expectation"));
                     if (!isKnownFailure || mIncludeKnownFailures) {
-                        mPackageDef.addTest(testId, timeout);
+                        String abiList = attributes.getValue("abis");
+                        Set<String> abis = new HashSet<String>();
+                        if (abiList == null) {
+                            // If no specification, add all supported abis
+                            abis.addAll(AbiUtils.getAbisSupportedByCts());
+                        } else {
+                            for (String abi : abiList.split(",")) {
+                                // Else only add the abi which are supported
+                                abis.add(abi.trim());
+                            }
+                        }
+                        for (String abi : abis) {
+                            TestIdentifier testId = new TestIdentifier(
+                                    classNameBuilder.toString(), methodName);
+                            mPackageDefs.get(abi).addTest(testId, timeout);
+                        }
                     }
                 }
             }
@@ -168,19 +194,15 @@
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
     protected DefaultHandler createXmlHandler() {
         return new TestPackageHandler();
     }
 
     /**
-     * @returns the {@link TestPackageDef} containing data parsed from xml or <code>null</code> if
-     *          xml did not contain the correct information.
+     * @return the set of {@link TestPackageDef} containing data parsed from xml
      */
-    public TestPackageDef getTestPackageDef() {
-        return mPackageDef;
+    public Set<TestPackageDef> getTestPackageDefs() {
+        return new HashSet<>(mPackageDefs.values());
     }
 }
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPlan.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPlan.java
index c2a1348..2419784 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPlan.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPlan.java
@@ -16,6 +16,7 @@
 
 package com.android.cts.tradefed.testtype;
 
+import com.android.cts.util.AbiUtils;
 import com.android.ddmlib.testrunner.TestIdentifier;
 import com.android.tradefed.util.ArrayUtil;
 import com.android.tradefed.util.xml.AbstractXmlParser;
@@ -29,9 +30,12 @@
 import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
 
 /**
  * Implementation of {@link TestPlan}.
@@ -39,18 +43,20 @@
 public class TestPlan extends AbstractXmlParser implements ITestPlan {
 
     /**
-     * Map of uri names found in plan, and their excluded tests
+     * Map of ids found in plan, and their filters
      */
-    private Map<String, TestFilter> mUriExcludedTestsMap;
+    private Map<String, TestFilter> mIdFilterMap;
 
     private static final String ENTRY_TAG = "Entry";
     private static final String TEST_DELIM = ";";
     private static final String METHOD_DELIM = "#";
     private static final String EXCLUDE_ATTR = "exclude";
     private static final String INCLUDE_ATTR = "include";
-    private static final String URI_ATTR = "uri";
+    private static final String ABI_ATTR = "abi";
+    private static final String NAME_ATTR = "name";
 
     private final String mName;
+    private final Set<String> mAbis;
 
     /**
      * SAX callback object. Handles parsing data from the xml tags.
@@ -61,10 +67,17 @@
         public void startElement(String uri, String localName, String name, Attributes attributes)
                 throws SAXException {
             if (ENTRY_TAG.equals(localName)) {
-                final String entryUriValue = attributes.getValue(URI_ATTR);
                 TestFilter filter = parseTestList(
                         attributes.getValue(EXCLUDE_ATTR), attributes.getValue(INCLUDE_ATTR));
-                mUriExcludedTestsMap.put(entryUriValue, filter);
+                final String entryNameValue = attributes.getValue(NAME_ATTR);
+                final String entryAbiValue = attributes.getValue(ABI_ATTR);
+                if (entryAbiValue != null) {
+                    mIdFilterMap.put(AbiUtils.createId(entryAbiValue, entryNameValue), filter);
+                } else {
+                    for (String abi : mAbis) {
+                        mIdFilterMap.put(AbiUtils.createId(abi, entryNameValue), filter);
+                    }
+                }
             }
         }
 
@@ -109,10 +122,11 @@
         }
     }
 
-    public TestPlan(String name) {
+    public TestPlan(String name, Set<String> abis) {
         mName = name;
+        mAbis = abis;
         // Uses a LinkedHashMap to have predictable iteration order
-        mUriExcludedTestsMap = new LinkedHashMap<String, TestFilter>();
+        mIdFilterMap = new LinkedHashMap<String, TestFilter>();
     }
 
     /**
@@ -127,24 +141,38 @@
      * {@inheritDoc}
      */
     @Override
-    public Collection<String> getTestUris() {
-        return mUriExcludedTestsMap.keySet();
+    public Collection<String> getTestIds() {
+        List<String> ids = new ArrayList<String>(mIdFilterMap.keySet());
+        Collections.sort(ids);
+        return ids;
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public TestFilter getExcludedTestFilter(String uri) {
-        return mUriExcludedTestsMap.get(uri);
+    public List<String> getTestNames() {
+        TreeSet<String> testNameSet = new TreeSet<>();
+        for (String id : mIdFilterMap.keySet()) {
+            testNameSet.add(AbiUtils.parseTestName(id));
+        }
+        return new ArrayList<>(testNameSet);
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public void addPackage(String uri) {
-        mUriExcludedTestsMap.put(uri, new TestFilter());
+    public TestFilter getTestFilter(String id) {
+        return mIdFilterMap.get(id);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void addPackage(String id) {
+        mIdFilterMap.put(id, new TestFilter());
     }
 
     /**
@@ -159,12 +187,12 @@
      * {@inheritDoc}
      */
     @Override
-    public void addExcludedTest(String uri, TestIdentifier testToExclude) {
-        TestFilter filter = mUriExcludedTestsMap.get(uri);
+    public void addExcludedTest(String id, TestIdentifier testToExclude) {
+        TestFilter filter = mIdFilterMap.get(id);
         if (filter != null) {
             filter.addExcludedTest(testToExclude);
         } else {
-            throw new IllegalArgumentException(String.format("Could not find package %s", uri));
+            throw new IllegalArgumentException(String.format("Could not find package %s", id));
         }
     }
 
@@ -172,12 +200,12 @@
      * {@inheritDoc}
      */
     @Override
-    public void addExcludedTests(String uri, Collection<TestIdentifier> excludedTests) {
-        TestFilter filter = mUriExcludedTestsMap.get(uri);
+    public void addExcludedTests(String id, Collection<TestIdentifier> excludedTests) {
+        TestFilter filter = mIdFilterMap.get(id);
         if (filter != null) {
             filter.getExcludedTests().addAll(excludedTests);
         } else {
-            throw new IllegalArgumentException(String.format("Could not find package %s", uri));
+            throw new IllegalArgumentException(String.format("Could not find package %s", id));
         }
     }
 
@@ -193,9 +221,11 @@
                 "http://xmlpull.org/v1/doc/features.html#indent-output", true);
         serializer.startTag(null, "TestPlan");
         serializer.attribute(null, "version", "1.0");
-        for (Map.Entry<String, TestFilter> packageEntry : mUriExcludedTestsMap.entrySet()) {
+        for (Map.Entry<String, TestFilter> packageEntry : mIdFilterMap.entrySet()) {
             serializer.startTag(null, ENTRY_TAG);
-            serializer.attribute(null, "uri", packageEntry.getKey());
+            String[] parts = AbiUtils.parseId(packageEntry.getKey());
+            serializer.attribute(null, ABI_ATTR, parts[0]);
+            serializer.attribute(null, NAME_ATTR, parts[1]);
             serializeFilter(serializer, packageEntry.getValue());
             serializer.endTag(null, ENTRY_TAG);
         }
@@ -206,10 +236,10 @@
     /**
      * Adds an xml attribute containing {@link TestFilter} contents.
      * <p/>
-     * If {@link TestFilter} is empty, no data will be outputted.
+     * If {@link TestFilter} is empty, no data will be output.
      *
      * @param serializer
-     * @param value
+     * @param testFilter
      * @throws IOException
      */
     private void serializeFilter(KXmlSerializer serializer, TestFilter testFilter)
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 e972640..0ebdeea 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
@@ -33,6 +33,7 @@
 public class VMHostTest extends JarHostTest {
 
     private static final String VM_TEST_TEMP_DIR = "/data/local/tmp/vm-tests";
+    private static final String EMULATOR_TEMP_DIR = "/data/local/tmp";
 
     /**
      * {@inheritDoc}
@@ -66,7 +67,7 @@
         CLog.d("Creating device temp directory, including dalvik-cache.");
         createRemoteDir(device, VM_TEST_TEMP_DIR + "/dalvik-cache" );
         try {
-            File localTmpDir = FileUtil.createTempDir("cts-vm", new File("/tmp/"));
+            File localTmpDir = FileUtil.createTempDir("cts-vm", new File(System.getProperty("java.io.tmpdir")));
             CLog.d("Creating host temp dir %s", localTmpDir.getPath());
             File jarFile = new File(ctsBuild.getTestCasesDir(), getJarFileName());
             if (!jarFile.exists()) {
@@ -119,11 +120,10 @@
         if (device.doesFileExist(remoteFilePath)) {
             return;
         }
-        File f = new File(remoteFilePath);
-        String parentPath = f.getParent();
-        if (parentPath != null) {
-            createRemoteDir(device, parentPath);
+	 if (!(device.doesFileExist(EMULATOR_TEMP_DIR))) {
+            CLog.e("Error: Can not found the /data/local/tmp directory!!!");
         }
+        device.executeShellCommand(String.format("mkdir %s", VM_TEST_TEMP_DIR));
         device.executeShellCommand(String.format("mkdir %s", remoteFilePath));
     }
 }
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..e3ff8257 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
@@ -17,12 +17,14 @@
 package com.android.cts.tradefed.testtype;
 
 import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.cts.util.AbiUtils;
 import com.android.ddmlib.testrunner.ITestRunListener;
 import com.android.tradefed.build.IBuildInfo;
 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.testtype.IAbi;
 import com.android.tradefed.testtype.IBuildReceiver;
 import com.android.tradefed.testtype.IDeviceTest;
 import com.android.tradefed.testtype.IRemoteTest;
@@ -35,22 +37,31 @@
  */
 public class WrappedGTest implements IBuildReceiver, IDeviceTest, IRemoteTest {
 
+    private static final String LOG_TAG = WrappedGTest.class.getSimpleName();
+
     private int mMaxTestTimeMs = 1 * 60 * 1000;
 
     private CtsBuildHelper mCtsBuild;
     private ITestDevice mDevice;
+    private IAbi mAbi;
 
     private final String mAppNameSpace;
-    private final String mRunner;
+    private final String mPackageName;
     private final String mName;
-    private final String mUri;
+    private final String mRunner;
 
-
-    public WrappedGTest(String appNameSpace, String uri, String name, String runner) {
+    public WrappedGTest(String appNameSpace, String packageName, String name, String runner) {
         mAppNameSpace = appNameSpace;
-        mRunner = runner;
+        mPackageName = packageName;
         mName = name;
-        mUri = uri;
+        mRunner = runner;
+    }
+
+    /**
+     * @param abi The ABI to run the test on
+     */
+    public void setAbi(IAbi abi) {
+        mAbi = abi;
     }
 
     @Override
@@ -81,7 +92,8 @@
     private boolean installTest() throws DeviceNotAvailableException {
         try {
             File testApp = mCtsBuild.getTestApp(String.format("%s.apk", mName));
-            String installCode = mDevice.installPackage(testApp, true);
+            String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+            String installCode = mDevice.installPackage(testApp, true, options);
 
             if (installCode != null) {
                 CLog.e("Failed to install %s.apk on %s. Reason: %s", mName,
@@ -97,10 +109,12 @@
     }
 
     private void runTest(ITestRunListener listener) throws DeviceNotAvailableException {
-        WrappedGTestResultParser resultParser = new WrappedGTestResultParser(mUri, listener);
-        resultParser.setFakePackagePrefix(mUri + ".");
+        String id = AbiUtils.createId(mAbi.getName(), mPackageName);
+        WrappedGTestResultParser resultParser = new WrappedGTestResultParser(id, listener);
+        resultParser.setFakePackagePrefix(mPackageName + ".");
         try {
-            String command = String.format("am instrument -w %s/.%s", mAppNameSpace, mRunner);
+            String options = mAbi == null ? "" : String.format("--abi %s ", mAbi.getName());
+            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/tradefed-host/src/com/android/cts/tradefed/testtype/WrappedGTestResultParser.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/WrappedGTestResultParser.java
index cc3c53a..3050738 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/WrappedGTestResultParser.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/WrappedGTestResultParser.java
@@ -29,23 +29,23 @@
     /**
      * Creates the WrappedGTestResultParser.
      *
-     * @param testRunName the test run name to provide to
+     * @param testRunId the test run id to provide to
      *            {@link ITestRunListener#testRunStarted(String, int)}
      * @param listeners informed of test results as the tests are executing
      */
-    public WrappedGTestResultParser(String testRunName, Collection<ITestRunListener> listeners) {
-        super(testRunName, listeners);
+    public WrappedGTestResultParser(String testRunId, Collection<ITestRunListener> listeners) {
+        super(testRunId, listeners);
     }
 
     /**
      * Creates the WrappedGTestResultParser for a single listener.
      *
-     * @param testRunName the test run name to provide to
+     * @param testRunId the test run id to provide to
      *            {@link ITestRunListener#testRunStarted(String, int)}
      * @param listener informed of test results as the tests are executing
      */
-    public WrappedGTestResultParser(String testRunName, ITestRunListener listener) {
-        super(testRunName, listener);
+    public WrappedGTestResultParser(String testRunId, ITestRunListener listener) {
+        super(testRunId, listener);
     }
 
     /**
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/util/CtsHostStore.java b/tools/tradefed-host/src/com/android/cts/tradefed/util/CtsHostStore.java
index 9c1e283..288b48c 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/util/CtsHostStore.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/util/CtsHostStore.java
@@ -23,7 +23,7 @@
  */
 public class CtsHostStore {
 
-    // needs concurrent verion as there can be multiple client accessing this.
+    // needs concurrent version as there can be multiple client accessing this.
     // But there is no additional protection for the same key as that should not happen.
     private static final ConcurrentHashMap<String, String> mMap =
             new ConcurrentHashMap<String, String>();
@@ -33,26 +33,27 @@
      * Note that key is generated in the form of device_serial#class#method name.
      * So there should be no concurrent test for the same (serial, class, method).
      * @param deviceSerial
+     * @param abi
      * @param classMethodName
      * @param result CTS result string
      */
-    public static void storeCtsResult(String deviceSerial, String classMethodName, String result) {
-        mMap.put(generateTestKey(deviceSerial, classMethodName), result);
+    public static void storeCtsResult(String deviceSerial, String abi, String classMethodName, String result) {
+        mMap.put(generateTestKey(deviceSerial, abi, classMethodName), result);
     }
 
     /**
      * retrieves a CTS result for the given condition and remove it from the internal
      * storage. If there is no result for the given condition, it will return null.
      */
-    public static String removeCtsResult(String deviceSerial, String classMethodName) {
-        return mMap.remove(generateTestKey(deviceSerial, classMethodName));
+    public static String removeCtsResult(String deviceSerial, String abi, String classMethodName) {
+        return mMap.remove(generateTestKey(deviceSerial, abi, classMethodName));
     }
 
     /**
-     * return test key in the form of device_serial#class_name#method_name
+     * @return test key in the form of device_serial#abi#class_name#method_name
      */
-    private static String generateTestKey(String deviceSerial, String classMethodName) {
-        return String.format("%s#%s", deviceSerial, classMethodName);
+    private static String generateTestKey(String deviceSerial, String abi, String classMethodName) {
+        return String.format("%s#%s#%s", deviceSerial, abi, classMethodName);
 
     }
 }
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/util/HostReportLog.java b/tools/tradefed-host/src/com/android/cts/tradefed/util/HostReportLog.java
index 125c56e..645dbb9 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/util/HostReportLog.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/util/HostReportLog.java
@@ -23,20 +23,23 @@
  * Note that setTestInfo should be set before throwing report
  */
 public class HostReportLog extends ReportLog {
-    private String mDeviceSerial;
-    private String mClassMethodName;
+    private final String mDeviceSerial;
+    private final String mAbiName;
+    private final String mClassMethodName;
 
     /**
      * @param deviceSerial serial number of the device
+     * @param abiName the name of the ABI on which the test was run
      * @param classMethodName class name and method name of the test in class#method format.
      *        Note that ReportLog.getClassMethodNames() provide this.
      */
-    public HostReportLog(String deviceSerial, String classMethodName) {
+    public HostReportLog(String deviceSerial, String abiName, String classMethodName) {
         mDeviceSerial = deviceSerial;
+        mAbiName = abiName;
         mClassMethodName = classMethodName;
     }
 
     public void deliverReportToHost() {
-        CtsHostStore.storeCtsResult(mDeviceSerial, mClassMethodName, generateReport());
+        CtsHostStore.storeCtsResult(mDeviceSerial, mAbiName, mClassMethodName, generateReport());
     }
 }
diff --git a/tools/tradefed-host/tests/Android.mk b/tools/tradefed-host/tests/Android.mk
index d3b94cd..2734a5b 100644
--- a/tools/tradefed-host/tests/Android.mk
+++ b/tools/tradefed-host/tests/Android.mk
@@ -21,9 +21,7 @@
 
 LOCAL_MODULE := cts-tradefed-tests
 LOCAL_MODULE_TAGS := optional
-LOCAL_JAVA_LIBRARIES := ddmlib-prebuilt tradefed-prebuilt cts-tradefed
+LOCAL_JAVA_LIBRARIES := tradefed-prebuilt cts-tradefed
 LOCAL_STATIC_JAVA_LIBRARIES := easymock
 
-include $(BUILD_HOST_JAVA_LIBRARY)
-
-
+include $(BUILD_HOST_JAVA_LIBRARY)
\ No newline at end of file
diff --git a/tools/tradefed-host/tests/run_unit_tests.sh b/tools/tradefed-host/tests/run_unit_tests.sh
index fc19a02..771dc75 100755
--- a/tools/tradefed-host/tests/run_unit_tests.sh
+++ b/tools/tradefed-host/tests/run_unit_tests.sh
@@ -37,7 +37,7 @@
 fi;
 
 JAR_DIR=${ANDROID_BUILD_TOP}/out/host/$OS/framework
-JARS="ddmlib-prebuilt.jar tradefed-prebuilt.jar hosttestlib.jar cts-tradefed.jar cts-tradefed-tests.jar"
+JARS="tradefed-prebuilt.jar hosttestlib.jar cts-tradefed.jar cts-tradefed-tests.jar"
 
 for JAR in $JARS; do
     checkFile ${JAR_DIR}/${JAR}
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/UnitTests.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/UnitTests.java
index 3c36a3d..ad1430e 100644
--- a/tools/tradefed-host/tests/src/com/android/cts/tradefed/UnitTests.java
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/UnitTests.java
@@ -21,13 +21,17 @@
 import com.android.cts.tradefed.result.TestResultsTest;
 import com.android.cts.tradefed.result.TestSummaryXmlTest;
 import com.android.cts.tradefed.result.TestTest;
+import com.android.cts.tradefed.result.TestLogTest;
+import com.android.cts.tradefed.testtype.Abi;
 import com.android.cts.tradefed.testtype.CtsTestTest;
+import com.android.cts.tradefed.testtype.DeqpTestRunnerTest;
 import com.android.cts.tradefed.testtype.JarHostTestTest;
 import com.android.cts.tradefed.testtype.TestFilterTest;
 import com.android.cts.tradefed.testtype.TestPackageDefTest;
 import com.android.cts.tradefed.testtype.TestPackageXmlParserTest;
 import com.android.cts.tradefed.testtype.TestPlanTest;
 import com.android.cts.tradefed.testtype.WrappedGTestResultParserTest;
+import com.android.tradefed.testtype.IAbi;
 
 import junit.framework.Test;
 import junit.framework.TestSuite;
@@ -40,6 +44,8 @@
  */
 public class UnitTests extends TestSuite {
 
+    public static final IAbi ABI = new Abi("armeabi-v7a", "32");
+
     public UnitTests() {
         super();
 
@@ -50,6 +56,7 @@
         addTestSuite(TestResultsTest.class);
         addTestSuite(TestSummaryXmlTest.class);
         addTestSuite(TestTest.class);
+        addTestSuite(TestLogTest.class);
 
         // testtype package
         addTestSuite(CtsTestTest.class);
@@ -59,6 +66,7 @@
         addTestSuite(TestPackageXmlParserTest.class);
         addTestSuite(TestPlanTest.class);
         addTestSuite(WrappedGTestResultParserTest.class);
+        addTestSuite(DeqpTestRunnerTest.class);
     }
 
     public static Test suite() {
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/device/DeviceInfoCollectorFuncTest.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/device/DeviceInfoCollectorFuncTest.java
index b0c9e6d..52a205b 100644
--- a/tools/tradefed-host/tests/src/com/android/cts/tradefed/device/DeviceInfoCollectorFuncTest.java
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/device/DeviceInfoCollectorFuncTest.java
@@ -15,6 +15,7 @@
  */
 package com.android.cts.tradefed.device;
 
+import com.android.cts.tradefed.UnitTests;
 import com.android.tradefed.build.BuildInfo;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.result.CollectingTestListener;
@@ -34,7 +35,7 @@
         CollectingTestListener testListener = new CollectingTestListener();
 
         testListener.invocationStarted(new BuildInfo());
-        DeviceInfoCollector.collectDeviceInfo(getDevice(), new File(
+        DeviceInfoCollector.collectDeviceInfo(getDevice(), UnitTests.ABI.getName(), new File(
                 System.getProperty("java.io.tmpdir")), testListener);
         assertNotNull(testListener.getCurrentRunResults());
         assertTrue(testListener.getCurrentRunResults().getRunMetrics().size() > 0);
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/CtsXmlResultReporterTest.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/CtsXmlResultReporterTest.java
index 5776568..ae4a41e 100644
--- a/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/CtsXmlResultReporterTest.java
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/CtsXmlResultReporterTest.java
@@ -17,10 +17,14 @@
 
 import static com.android.cts.tradefed.result.CtsXmlResultReporter.CTS_RESULT_FILE_VERSION;
 
-import com.android.ddmlib.testrunner.ITestRunListener.TestFailure;
+import com.android.cts.tradefed.UnitTests;
+import com.android.cts.util.AbiUtils;
 import com.android.ddmlib.testrunner.TestIdentifier;
 import com.android.tradefed.build.IFolderBuildInfo;
 import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.result.LogDataType;
+import com.android.tradefed.result.LogFile;
+import com.android.tradefed.result.TestSummary;
 import com.android.tradefed.result.XmlResultReporter;
 import com.android.tradefed.util.FileUtil;
 
@@ -32,7 +36,10 @@
 import java.io.File;
 import java.io.IOException;
 import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -40,8 +47,11 @@
  */
 public class CtsXmlResultReporterTest extends TestCase {
 
+    private static final List<TestSummary> SUMMARY_LIST =
+            new ArrayList<>(Arrays.asList(new TestSummary("TEST_SUMMARY_URL")));
     private CtsXmlResultReporter mResultReporter;
     private ByteArrayOutputStream mOutputStream;
+    private File mBuildDir;
     private File mReportDir;
     private IFolderBuildInfo mMockBuild;
 
@@ -67,8 +77,16 @@
         // TODO: use mock file dir instead
         mReportDir = FileUtil.createTempDir("foo");
         mResultReporter.setReportDir(mReportDir);
+        mBuildDir = FileUtil.createTempDir("build");
+        File ctsDir = new File(mBuildDir, "android-cts");
+        File repoDir = new File(ctsDir, "repository");
+        File casesDir = new File(repoDir, "testcases");
+        File plansDir = new File(repoDir, "plans");
+        assertTrue(casesDir.mkdirs());
+        assertTrue(plansDir.mkdirs());
         mMockBuild = EasyMock.createNiceMock(IFolderBuildInfo.class);
         EasyMock.expect(mMockBuild.getDeviceSerial()).andStubReturn(null);
+        EasyMock.expect(mMockBuild.getRootDir()).andStubReturn(mBuildDir);
         EasyMock.replay(mMockBuild);
     }
 
@@ -77,6 +95,9 @@
         if (mReportDir != null) {
             FileUtil.recursiveDelete(mReportDir);
         }
+        if (mBuildDir != null) {
+            FileUtil.recursiveDelete(mBuildDir);
+        }
         super.tearDown();
     }
 
@@ -111,18 +132,18 @@
         Map<String, String> emptyMap = Collections.emptyMap();
         final TestIdentifier testId = new TestIdentifier("com.foo.FooTest", "testFoo");
         mResultReporter.invocationStarted(mMockBuild);
-        mResultReporter.testRunStarted("run", 1);
+        mResultReporter.testRunStarted(AbiUtils.createId(UnitTests.ABI.getName(), "run"), 1);
         mResultReporter.testStarted(testId);
         mResultReporter.testEnded(testId, emptyMap);
         mResultReporter.testRunEnded(3000, emptyMap);
         mResultReporter.invocationEnded(1);
+        mResultReporter.putSummary(SUMMARY_LIST);
         String output =  getOutput();
-        CLog.d("Actual output: %s", output);
-        System.out.println(output);
         // TODO: consider doing xml based compare
         assertTrue(output.contains(
-                "<Summary failed=\"0\" notExecuted=\"0\" timeout=\"0\" pass=\"1\" />"));
-        assertTrue(output.contains("<TestPackage name=\"\" appPackageName=\"run\" digest=\"\">"));
+              "<Summary failed=\"0\" notExecuted=\"0\" timeout=\"0\" pass=\"1\" />"));
+        assertTrue(output.contains("<TestPackage name=\"\" appPackageName=\"run\" abi=\"" +
+              UnitTests.ABI.getName() + "\" digest=\"\">"));
         assertTrue(output.contains("<TestCase name=\"FooTest\" priority=\"\">"));
 
         final String testCaseTag = String.format(
@@ -138,21 +159,68 @@
         final TestIdentifier testId = new TestIdentifier("FooTest", "testFoo");
         final String trace = "this is a trace\nmore trace\nyet more trace";
         mResultReporter.invocationStarted(mMockBuild);
-        mResultReporter.testRunStarted("run", 1);
+        mResultReporter.testRunStarted(AbiUtils.createId(UnitTests.ABI.getName(), "run"), 1);
         mResultReporter.testStarted(testId);
-        mResultReporter.testFailed(TestFailure.FAILURE, testId, trace);
+        mResultReporter.testFailed(testId, trace);
         mResultReporter.testEnded(testId, emptyMap);
         mResultReporter.testRunEnded(3, emptyMap);
+        mResultReporter.testLogSaved("logcat-foo-bar", LogDataType.TEXT, null,
+                new LogFile("path", "url"));
         mResultReporter.invocationEnded(1);
-        String output =  getOutput();
-        System.out.print(getOutput());
+        String output = getOutput();
         // TODO: consider doing xml based compare
         assertTrue(output.contains(
                 "<Summary failed=\"1\" notExecuted=\"0\" timeout=\"0\" pass=\"0\" />"));
         final String failureTag =
-            "<FailedScene message=\"this is a trace&#10;more trace\">     " +
-            "<StackTrace>this is a tracemore traceyet more trace</StackTrace>";
+                "<FailedScene message=\"this is a trace&#10;more trace\">     " +
+                "<StackTrace>this is a tracemore traceyet more trace</StackTrace>";
         assertTrue(output.contains(failureTag));
+
+        // Check that no TestLog tags were added, because the flag wasn't enabled.
+        final String testLogTag = String.format("<TestLog type=\"logcat\" url=\"url\" />");
+        assertFalse(output, output.contains(testLogTag));
+    }
+
+    /**
+     * Test that flips the include-test-log-tags flag and checks that logs are written to the XML.
+     */
+    public void testIncludeTestLogTags() {
+        Map<String, String> emptyMap = Collections.emptyMap();
+        final TestIdentifier testId = new TestIdentifier("FooTest", "testFoo");
+        final String trace = "this is a trace\nmore trace\nyet more trace";
+
+        // Include TestLogTags in the XML.
+        mResultReporter.setIncludeTestLogTags(true);
+
+        mResultReporter.invocationStarted(mMockBuild);
+        mResultReporter.testRunStarted(AbiUtils.createId(UnitTests.ABI.getName(), "run"), 1);
+        mResultReporter.testStarted(testId);
+        mResultReporter.testFailed(testId, trace);
+        mResultReporter.testEnded(testId, emptyMap);
+        mResultReporter.testRunEnded(3, emptyMap);
+        mResultReporter.testLogSaved("logcat-foo-bar", LogDataType.TEXT, null,
+                new LogFile("path", "url"));
+        mResultReporter.invocationEnded(1);
+
+        // Check for TestLog tags because the flag was enabled via setIncludeTestLogTags.
+        final String output = getOutput();
+        final String testLogTag = String.format("<TestLog type=\"logcat\" url=\"url\" />");
+        assertTrue(output, output.contains(testLogTag));
+    }
+
+    public void testDeviceSetup() {
+        Map<String, String> emptyMap = Collections.emptyMap();
+        final TestIdentifier testId = new TestIdentifier("android.tests.devicesetup", "TestDeviceSetup");
+        mResultReporter.invocationStarted(mMockBuild);
+        mResultReporter.testRunStarted(AbiUtils.createId(UnitTests.ABI.getName(), testId.getClassName()), 1);
+        mResultReporter.testStarted(testId);
+        mResultReporter.testEnded(testId, emptyMap);
+        mResultReporter.testRunEnded(3, emptyMap);
+        mResultReporter.invocationEnded(1);
+        String output = getOutput();
+        // TODO: consider doing xml based compare
+        final String deviceSetupTag = "appPackageName=\"android.tests.devicesetup\"";
+        assertFalse(output, output.contains(deviceSetupTag));
     }
 
     /**
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/TestLogTest.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/TestLogTest.java
new file mode 100644
index 0000000..55c3071
--- /dev/null
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/TestLogTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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 com.android.cts.tradefed.result;
+
+import com.android.cts.tradefed.result.TestLog.TestLogType;
+
+import org.kxml2.io.KXmlSerializer;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+
+import junit.framework.TestCase;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+
+/** Tests for {@link TestLog}. */
+public class TestLogTest extends TestCase {
+
+    public void testTestLogType_fromDataName() {
+        assertNull(TestLogType.fromDataName(null));
+        assertNull(TestLogType.fromDataName(""));
+        assertNull(TestLogType.fromDataName("kmsg-foo_bar_test"));
+
+        assertEquals(TestLogType.LOGCAT,
+            TestLogType.fromDataName("logcat-foo_bar_test"));
+        assertEquals(TestLogType.BUGREPORT,
+            TestLogType.fromDataName("bug-foo_bar_test"));
+    }
+
+    public void testTestLogType_getAttrValue() {
+        assertEquals("logcat", TestLogType.LOGCAT.getAttrValue());
+        assertEquals("bugreport", TestLogType.BUGREPORT.getAttrValue());
+    }
+
+    public void testFromDataName() {
+        TestLog log = TestLog.fromDataName("logcat-baz_test", "http://logs/baz_test");
+        assertEquals(TestLogType.LOGCAT, log.getLogType());
+        assertEquals("http://logs/baz_test", log.getUrl());
+    }
+
+    public void testFromDataName_unrecognizedDataName() {
+        assertNull(TestLog.fromDataName("kmsg-baz_test", null));
+    }
+
+    public void testFromDataName_nullDataName() {
+        assertNull(TestLog.fromDataName(null, "http://logs/baz_test"));
+    }
+
+    public void testFromDataName_nullUrl() {
+        assertNull(TestLog.fromDataName("logcat-bar_test", null));
+    }
+
+    public void testFromDataName_allNull() {
+        assertNull(TestLog.fromDataName(null, null));
+    }
+
+    public void testFromXml() throws Exception {
+        TestLog log = TestLog.fromXml(newXml("<TestLog type=\"logcat\" url=\"http://logs/baz_test\">"));
+        assertEquals(TestLogType.LOGCAT, log.getLogType());
+        assertEquals("http://logs/baz_test", log.getUrl());
+    }
+
+    public void testFromXml_unrecognizedType() throws Exception {
+        assertNull(TestLog.fromXml(newXml("<TestLog type=\"kmsg\" url=\"http://logs/baz_test\">")));
+    }
+
+    public void testFromXml_noTypeAttribute() throws Exception {
+        assertNull(TestLog.fromXml(newXml("<TestLog url=\"http://logs/baz_test\">")));
+    }
+
+    public void testFromXml_noUrlAttribute() throws Exception {
+        assertNull(TestLog.fromXml(newXml("<TestLog type=\"bugreport\">")));
+    }
+
+    public void testFromXml_allNull() throws Exception {
+        assertNull(TestLog.fromXml(newXml("<TestLog>")));
+    }
+
+    public void testSerialize() throws Exception {
+        KXmlSerializer serializer = new KXmlSerializer();
+        StringWriter writer = new StringWriter();
+        serializer.setOutput(writer);
+
+        TestLog log = TestLog.of(TestLogType.LOGCAT, "http://logs/foo/bar");
+        log.serialize(serializer);
+        assertEquals("<TestLog type=\"logcat\" url=\"http://logs/foo/bar\" />", writer.toString());
+    }
+
+    public void testIsTag() {
+        assertTrue(TestLog.isTag("TestLog"));
+        assertFalse(TestLog.isTag("TestResult"));
+    }
+
+    private XmlPullParser newXml(String xml) throws Exception {
+        XmlPullParserFactory factory = org.xmlpull.v1.XmlPullParserFactory.newInstance();
+        XmlPullParser parser = factory.newPullParser();
+        parser.setInput(new StringReader(xml));
+
+        // Move the parser from the START_DOCUMENT stage to the START_TAG of the data.
+        parser.next();
+
+        return parser;
+    }
+}
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/TestPackageResultTest.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/TestPackageResultTest.java
index df80dbb..57d322e 100644
--- a/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/TestPackageResultTest.java
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/TestPackageResultTest.java
@@ -20,6 +20,7 @@
 import junit.framework.TestCase;
 
 import java.util.Collection;
+import java.util.HashMap;
 
 /**
  * Unit tests for {@link TestPackageResult}.
@@ -33,7 +34,7 @@
         TestPackageResult pkgResult = new TestPackageResult();
         TestIdentifier excludedTest = new TestIdentifier("com.example.ExampleTest", "testPass");
         pkgResult.insertTest(excludedTest);
-        pkgResult.reportTestEnded(excludedTest);
+        pkgResult.reportTestEnded(excludedTest, new HashMap<String, String>());
         TestIdentifier includedTest = new TestIdentifier("com.example.ExampleTest",
                 "testNotExecuted");
         pkgResult.insertTest(includedTest);
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/TestSummaryXmlTest.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/TestSummaryXmlTest.java
index 3fc7dd2..f8b135a 100644
--- a/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/TestSummaryXmlTest.java
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/TestSummaryXmlTest.java
@@ -38,7 +38,7 @@
             "<Foo failed=\"1\" notExecuted=\"2\" pass=\"3\" timeout=\"4\"/>" +
         "</TestResult>";
 
-    public void testConstructor() throws ParseException  {
+    public void testConstructor()  {
         TestSummaryXml result = new TestSummaryXml(1, "2011-11-01");
         assertEquals(1, result.getId());
         assertEquals("2011-11-01", result.getTimestamp());
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/CtsTestTest.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/CtsTestTest.java
index f0fd536..30e2ba8 100644
--- a/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/CtsTestTest.java
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/CtsTestTest.java
@@ -15,8 +15,10 @@
  */
 package com.android.cts.tradefed.testtype;
 
+import com.android.cts.tradefed.UnitTests;
 import com.android.cts.tradefed.build.StubCtsBuildHelper;
 import com.android.cts.tradefed.result.PlanCreator;
+import com.android.cts.util.AbiUtils;
 import com.android.ddmlib.testrunner.TestIdentifier;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
@@ -33,14 +35,32 @@
 import java.io.FileNotFoundException;
 import java.io.InputStream;
 import java.util.ArrayList;
-import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 /**
  * Unit tests for {@link CtsTest}.
  */
 public class CtsTestTest extends TestCase {
 
-    private static final String PACKAGE_NAME = "test-uri";
+    private static final String PLAN_NAME = "CTS";
+    private static final String PACKAGE_NAME = "test-name";
+    private static final String ID = AbiUtils.createId(UnitTests.ABI.getName(), PACKAGE_NAME);
+    private static final TestIdentifier TEST_IDENTIFIER =
+            new TestIdentifier("CLASS_NAME", "TEST_NAME");
+    private static final List<String> NAMES = new ArrayList<>();
+    private static final List<String> IDS = new ArrayList<>();
+    private static final List<TestIdentifier> TEST_IDENTIFIER_LIST = new ArrayList<>();
+
+    static {
+        NAMES.add(PACKAGE_NAME);
+        IDS.add(ID);
+        TEST_IDENTIFIER_LIST.add(TEST_IDENTIFIER);
+    }
+
     /** the test fixture under test, with all external dependencies mocked out */
     private CtsTest mCtsTest;
     private ITestPackageRepo mMockRepo;
@@ -49,10 +69,9 @@
     private ITestInvocationListener mMockListener;
     private StubCtsBuildHelper mStubBuildHelper;
     private ITestPackageDef mMockPackageDef;
+    private Set<ITestPackageDef> mMockPackageDefs;
     private IRemoteTest mMockTest;
 
-    private static final String PLAN_NAME = "CTS";
-
     /**
      * {@inheritDoc}
      */
@@ -64,7 +83,11 @@
         mMockDevice = EasyMock.createMock(ITestDevice.class);
         mMockListener = EasyMock.createNiceMock(ITestInvocationListener.class);
         mStubBuildHelper = new StubCtsBuildHelper();
+        mMockPackageDefs = new HashSet<>();
         mMockPackageDef = EasyMock.createMock(ITestPackageDef.class);
+        mMockPackageDefs.add(mMockPackageDef);
+        EasyMock.expect(mMockPackageDef.getTargetApkName()).andStubReturn(null);
+        EasyMock.expect(mMockPackageDef.getTargetPackageName()).andStubReturn(null);
         mMockTest = EasyMock.createMock(IRemoteTest.class);
 
         mCtsTest = new CtsTest() {
@@ -93,16 +116,17 @@
         mCtsTest.setBuildHelper(mStubBuildHelper);
         // turn off device collection for simplicity
         mCtsTest.setSkipDeviceInfo(true);
-        EasyMock.expect(mMockPackageDef.getTargetApkName()).andStubReturn(null);
-        EasyMock.expect(mMockPackageDef.getTargetPackageName()).andStubReturn(null);
+        // only run tests on one ABI
+        EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist"))
+                .andReturn(UnitTests.ABI.getName()).anyTimes();
     }
 
     /**
-     * Test normal case {@link CtsTest#run(java.util.List)} when running a plan.
+     * Test normal case {@link CtsTest#run(ITestInvocationListener)} when running a plan.
      */
     @SuppressWarnings("unchecked")
     public void testRun_plan() throws DeviceNotAvailableException, ParseException {
-        setParsePlanExceptations();
+        setParsePlanExpectations();
 
         setCreateAndRunTestExpectations();
 
@@ -112,11 +136,17 @@
     }
 
     /**
-     * Test normal case {@link CtsTest#run(java.util.List)} when running a package.
+     * Test normal case {@link CtsTest#run(ITestInvocationListener)} when running a package.
      */
     @SuppressWarnings("unchecked")
     public void testRun_package() throws DeviceNotAvailableException {
         mCtsTest.addPackageName(PACKAGE_NAME);
+        Map<String, List<ITestPackageDef>> nameMap = new HashMap<>();
+        List<ITestPackageDef> testPackageDefList = new ArrayList<>();
+        testPackageDefList.add(mMockPackageDef);
+        nameMap.put(PACKAGE_NAME, testPackageDefList);
+
+        EasyMock.expect(mMockRepo.getTestPackageDefsByName()).andReturn(nameMap);
 
         setCreateAndRunTestExpectations();
 
@@ -131,15 +161,18 @@
     @SuppressWarnings("unchecked")
     public void testRun_resume() throws DeviceNotAvailableException {
         mCtsTest.addPackageName(PACKAGE_NAME);
+        Map<String, List<ITestPackageDef>> nameMap = new HashMap<>();
+        List<ITestPackageDef> testPackageDefList = new ArrayList<>();
+        testPackageDefList.add(mMockPackageDef);
+        nameMap.put(PACKAGE_NAME, testPackageDefList);
 
+        EasyMock.expect(mMockRepo.getTestPackageDefsByName()).andReturn(nameMap);
         setCreateAndRunTestExpectations();
         // abort the first run
         EasyMock.expectLastCall().andThrow(new DeviceNotAvailableException());
 
         // now expect test to be resumed
         mMockTest.run((ITestInvocationListener)EasyMock.anyObject());
-        EasyMock.expect(mMockPackageDef.getName()).andReturn(PACKAGE_NAME);
-        EasyMock.expect(mMockPackageDef.getDigest()).andReturn("digest");
 
         replayMocks();
         try {
@@ -154,7 +187,7 @@
     }
 
     /**
-     * Test normal case {@link CtsTest#run(java.util.List)} when running a class.
+     * Test normal case {@link CtsTest#run(ITestInvocationListener)} when running a class.
      */
     @SuppressWarnings("unchecked")
     public void testRun_class() throws DeviceNotAvailableException {
@@ -163,7 +196,7 @@
         mCtsTest.setClassName(className);
         mCtsTest.setMethodName(methodName);
 
-        EasyMock.expect(mMockRepo.findPackageForTest(className)).andReturn(PACKAGE_NAME);
+        EasyMock.expect(mMockRepo.findPackageIdsForTest(className)).andReturn(IDS);
         mMockPackageDef.setClassName(className, methodName);
 
         setCreateAndRunTestExpectations();
@@ -174,14 +207,32 @@
     }
 
     /**
-     * Test {@link CtsTest#run(java.util.List)} when --excluded-package is specified
+     * Test normal case {@link CtsTest#run(ITestInvocationListener)} when running a class.
+     */
+    @SuppressWarnings("unchecked")
+    public void testRun_test() throws DeviceNotAvailableException {
+        final String className = "className";
+        final String methodName = "methodName";
+        final String testName = String.format("%s#%s", className, methodName);
+        mCtsTest.setTestName(testName);
+
+        EasyMock.expect(mMockRepo.findPackageIdsForTest(className)).andReturn(IDS);
+        mMockPackageDef.setClassName(className, methodName);
+
+        setCreateAndRunTestExpectations();
+
+        replayMocks();
+        mCtsTest.run(mMockListener);
+        verifyMocks();
+    }
+
+    /**
+     * Test {@link CtsTest#run(ITestInvocationListener)} when --excluded-package is specified
      */
     public void testRun_excludedPackage() throws DeviceNotAvailableException, ParseException {
         mCtsTest.setPlanName(PLAN_NAME);
-        mMockPlan.parse((InputStream)EasyMock.anyObject());
-        Collection<String> uris = new ArrayList<String>(1);
-        uris.add(PACKAGE_NAME);
-        EasyMock.expect(mMockPlan.getTestUris()).andReturn(uris);
+        mMockPlan.parse((InputStream) EasyMock.anyObject());
+        EasyMock.expect(mMockPlan.getTestIds()).andReturn(IDS);
 
         mCtsTest.addExcludedPackageName(PACKAGE_NAME);
 
@@ -192,17 +243,15 @@
     }
 
     /**
-     * Test {@link CtsTest#run(ITestInvocationListener))} when --continue-session is specified
+     * Test {@link CtsTest#run(ITestInvocationListener)} when --continue-session is specified
      */
-    public void testRun_continueSession() throws DeviceNotAvailableException, ParseException {
+    public void testRun_continueSession() throws DeviceNotAvailableException {
         mCtsTest.setContinueSessionId(1);
-        Collection<String> uris = new ArrayList<String>(1);
-        uris.add(PACKAGE_NAME);
-        EasyMock.expect(mMockPlan.getTestUris()).andReturn(uris);
+        EasyMock.expect(mMockPlan.getTestIds()).andReturn(IDS);
         TestFilter filter = new TestFilter();
-        EasyMock.expect(mMockPlan.getExcludedTestFilter(PACKAGE_NAME)).andReturn(
-                filter);
-        mMockPackageDef.setExcludedTestFilter(filter);
+        EasyMock.expect(mMockPlan.getTestFilter(ID)).andReturn(filter);
+
+        mMockPackageDef.setTestFilter(filter);
 
         setCreateAndRunTestExpectations();
 
@@ -214,36 +263,34 @@
     /**
      * Set EasyMock expectations for parsing {@link #PLAN_NAME}
      */
-    private void setParsePlanExceptations() throws ParseException {
+    private void setParsePlanExpectations() throws ParseException {
         mCtsTest.setPlanName(PLAN_NAME);
-        mMockPlan.parse((InputStream)EasyMock.anyObject());
-        Collection<String> uris = new ArrayList<String>(1);
-        uris.add(PACKAGE_NAME);
-        EasyMock.expect(mMockPlan.getTestUris()).andReturn(uris);
+        mMockPlan.parse((InputStream) EasyMock.anyObject());
+        EasyMock.expect(mMockPlan.getTestIds()).andReturn(IDS);
         TestFilter filter = new TestFilter();
-        EasyMock.expect(mMockPlan.getExcludedTestFilter(PACKAGE_NAME)).andReturn(
-                filter);
-        mMockPackageDef.setExcludedTestFilter(filter);
+        EasyMock.expect(mMockPlan.getTestFilter(ID)).andReturn(filter);
+        mMockPackageDef.setTestFilter(filter);
     }
 
     /**
      * Set EasyMock expectations for creating and running a package with PACKAGE_NAME
      */
     private void setCreateAndRunTestExpectations() throws DeviceNotAvailableException {
-        EasyMock.expect(mMockRepo.getTestPackage(PACKAGE_NAME)).andReturn(mMockPackageDef);
-        EasyMock.expect(mMockPackageDef.createTest((File)EasyMock.anyObject())).andReturn(
-                mMockTest);
-        EasyMock.expect(mMockPackageDef.getTests()).andReturn(new ArrayList<TestIdentifier>());
-        EasyMock.expect(mMockPackageDef.getUri()).andStubReturn(PACKAGE_NAME);
-        EasyMock.expect(mMockPackageDef.getName()).andReturn(PACKAGE_NAME);
-        EasyMock.expect(mMockPackageDef.getDigest()).andReturn("digest");
-
-        mMockTest.run((ITestInvocationListener)EasyMock.anyObject());
+        EasyMock.expect(mMockRepo.getPackageNames()).andReturn(NAMES).anyTimes();
+        EasyMock.expect(mMockRepo.getPackageIds()).andReturn(IDS).anyTimes();
+        EasyMock.expect(mMockRepo.getTestPackage(ID)).andReturn(mMockPackageDef).anyTimes();
+        EasyMock.expect(mMockPackageDef.createTest((File) EasyMock.anyObject())).andReturn(mMockTest);
+        EasyMock.expect(mMockPackageDef.getTests()).andReturn(TEST_IDENTIFIER_LIST).times(2);
+        EasyMock.expect(mMockPackageDef.getName()).andReturn(PACKAGE_NAME).atLeastOnce();
+        EasyMock.expect(mMockPackageDef.getAbi()).andReturn(UnitTests.ABI).atLeastOnce();
+        EasyMock.expect(mMockPackageDef.getId()).andReturn(ID).atLeastOnce();
+        EasyMock.expect(mMockPackageDef.getDigest()).andReturn("digest").atLeastOnce();
+        mMockTest.run((ITestInvocationListener) EasyMock.anyObject());
     }
 
     /**
-     * Test {@link CtsTest#run(java.util.List)} when --plan and --package options have not been
-     * specified
+     * Test {@link CtsTest#run(ITestInvocationListener)} when --plan and --package options have not
+     * been specified
      */
     public void testRun_nothingToRun() throws DeviceNotAvailableException {
         try {
@@ -255,7 +302,7 @@
     }
 
     /**
-     * Test {@link CtsTest#run(ITestInvocationListener))} when --plan and --package options have
+     * Test {@link CtsTest#run(ITestInvocationListener)} when --plan and --package options have
      * been specified.
      */
     public void testRun_packagePlan() throws DeviceNotAvailableException {
@@ -270,7 +317,7 @@
     }
 
     /**
-     * Test {@link CtsTest#run(java.util.List)} when --plan and --class options have been
+     * Test {@link CtsTest#run(ITestInvocationListener)} when --plan and --class options have been
      * specified
      */
     public void testRun_planClass() throws DeviceNotAvailableException {
@@ -285,8 +332,8 @@
     }
 
     /**
-     * Test {@link CtsTest#run(java.util.List)} when --package and --class options have been
-     * specified
+     * Test {@link CtsTest#run(ITestInvocationListener)} when --package and --class options have
+     * been specified
      */
     public void testRun_packageClass() throws DeviceNotAvailableException {
         mCtsTest.addPackageName(PACKAGE_NAME);
@@ -300,8 +347,8 @@
     }
 
     /**
-     * Test {@link CtsTest#run(java.util.List)} when --plan, --package and --class options have been
-     * specified
+     * Test {@link CtsTest#run(ITestInvocationListener)} when --plan, --package and --class options
+     * have been specified
      */
     public void testRun_planPackageClass() throws DeviceNotAvailableException {
         mCtsTest.setPlanName(PLAN_NAME);
@@ -316,8 +363,8 @@
     }
 
     /**
-     * Test {@link CtsTest#run(java.util.List)} when --plan, --continue-option options have been
-     * specified
+     * Test {@link CtsTest#run(ITestInvocationListener)} when --plan, --continue-option options
+     * have been specified
      */
     public void testRun_planContinue() throws DeviceNotAvailableException {
         mCtsTest.setPlanName(PLAN_NAME);
@@ -331,14 +378,12 @@
     }
 
     private void replayMocks(Object... mocks) {
-        EasyMock.replay(mMockRepo, mMockPlan, mMockDevice, mMockListener, mMockPackageDef,
-                mMockTest);
+        EasyMock.replay(mMockRepo, mMockPlan, mMockDevice, mMockPackageDef, mMockListener, mMockTest);
         EasyMock.replay(mocks);
     }
 
     private void verifyMocks(Object... mocks) {
-        EasyMock.verify(mMockRepo, mMockPlan, mMockDevice, mMockListener, mMockPackageDef,
-                mMockTest);
+        EasyMock.verify(mMockRepo, mMockPlan, mMockDevice, mMockPackageDef, mMockListener, mMockTest);
         EasyMock.verify(mocks);
     }
 }
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/DeqpTestRunnerTest.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/DeqpTestRunnerTest.java
new file mode 100644
index 0000000..c41793f
--- /dev/null
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/DeqpTestRunnerTest.java
@@ -0,0 +1,599 @@
+/*
+ * 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 com.android.cts.tradefed.testtype;
+
+import com.android.cts.tradefed.build.StubCtsBuildHelper;
+import com.android.cts.tradefed.UnitTests;
+import com.android.cts.util.AbiUtils;
+import com.android.ddmlib.IShellOutputReceiver;
+import com.android.ddmlib.testrunner.ITestRunListener;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.testtype.IAbi;
+
+import junit.framework.TestCase;
+
+import org.easymock.EasyMock;
+import org.easymock.IAnswer;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Unit tests for {@link DeqpTestRunner}.
+ */
+public class DeqpTestRunnerTest extends TestCase {
+    private static final String NAME = "dEQP-GLES3";
+    private static final String ID = AbiUtils.createId(UnitTests.ABI.getName(), NAME);
+    private static final String CASE_LIST_FILE_NAME = "/sdcard/dEQP-TestCaseList.txt";
+    private static final String LOG_FILE_NAME = "/sdcard/TestLog.qpa";
+    private static final String INSTRUMENTATION_NAME =
+            "com.drawelements.deqp/com.drawelements.deqp.testercore.DeqpInstrumentation";
+    private static final String DEQP_ONDEVICE_APK = "com.drawelements.deqp.apk";
+    private static final String DEQP_ONDEVICE_PKG = "com.drawelements.deqp";
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    /**
+     * Test version of OpenGL ES.
+     */
+    private void testGlesVersion(int requiredMajorVersion, int requiredMinorVersion, int majorVersion, int minorVersion) throws Exception {
+        final TestIdentifier testId = new TestIdentifier("dEQP-GLES"
+                + Integer.toString(requiredMajorVersion) + Integer.toString(requiredMinorVersion)
+                + ".info", "version");
+
+        final String testPath = "dEQP-GLES"
+                + Integer.toString(requiredMajorVersion) + Integer.toString(requiredMinorVersion)
+                +".info.version";
+
+        final String testTrie = "{dEQP-GLES"
+                + Integer.toString(requiredMajorVersion) + Integer.toString(requiredMinorVersion)
+                + "{info{version}}}";
+
+        final String resultCode = "Pass";
+
+        /* MultiLineReceiver expects "\r\n" line ending. */
+        final String output = "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=releaseName\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=2014.x\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=releaseId\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=0xcafebabe\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=targetName\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=android\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginSession\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginTestCase\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-BeginTestCase-TestCasePath=" + testPath + "\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Code=" + resultCode + "\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Details=Detail" + resultCode + "\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=TestCaseResult\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=EndTestCase\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=EndSession\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_CODE: 0\r\n";
+
+        ITestDevice mockDevice = EasyMock.createMock(ITestDevice.class);
+        ITestInvocationListener mockListener
+                = EasyMock.createStrictMock(ITestInvocationListener.class);
+        Collection<TestIdentifier> tests = new ArrayList<TestIdentifier>();
+
+        tests.add(testId);
+
+        DeqpTestRunner deqpTest = new DeqpTestRunner(NAME,
+                "dEQP-GLES" + Integer.toString(requiredMajorVersion)
+                + (requiredMinorVersion > 0 ? Integer.toString(requiredMinorVersion) : ""),
+                tests);
+        deqpTest.setAbi(UnitTests.ABI);
+
+        int version = (majorVersion << 16) | minorVersion;
+        EasyMock.expect(mockDevice.getProperty("ro.opengles.version"))
+            .andReturn(Integer.toString(version)).atLeastOnce();
+
+        if (majorVersion > requiredMajorVersion
+                || (majorVersion == requiredMajorVersion && minorVersion >= requiredMinorVersion)) {
+
+            EasyMock.expect(mockDevice.uninstallPackage(EasyMock.eq(DEQP_ONDEVICE_PKG)))
+                    .andReturn("").once();
+            EasyMock.expect(mockDevice.installPackage(EasyMock.<File>anyObject(),
+                    EasyMock.eq(true),
+                    EasyMock.eq(AbiUtils.createAbiFlag(UnitTests.ABI.getName()))))
+                    .andReturn(null).once();
+
+            EasyMock.expect(mockDevice.executeShellCommand(
+                    EasyMock.eq("rm " + CASE_LIST_FILE_NAME))).andReturn("").once();
+
+            EasyMock.expect(mockDevice.executeShellCommand(EasyMock.eq("rm " + LOG_FILE_NAME)))
+                    .andReturn("").once();
+
+            EasyMock.expect(mockDevice.pushString(testTrie + "\n", CASE_LIST_FILE_NAME))
+                    .andReturn(true).once();
+
+            String command = String.format(
+                    "am instrument %s -w -e deqpLogFileName \"%s\" -e deqpCmdLine \""
+                        + "--deqp-caselist-file=%s --deqp-gl-config-name=rgba8888d24s8\" "
+                        + "-e deqpLogData \"%s\" %s",
+                    AbiUtils.createAbiFlag(UnitTests.ABI.getName()), LOG_FILE_NAME,
+                    CASE_LIST_FILE_NAME, false, INSTRUMENTATION_NAME);
+
+            mockDevice.executeShellCommand(EasyMock.eq(command),
+                    EasyMock.<IShellOutputReceiver>notNull());
+
+            EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
+                @Override
+                public Object answer() {
+                    IShellOutputReceiver receiver
+                            = (IShellOutputReceiver)EasyMock.getCurrentArguments()[1];
+
+                    receiver.addOutput(output.getBytes(), 0, output.length());
+                    receiver.flush();
+
+                    return null;
+                }
+            });
+
+            EasyMock.expect(mockDevice.uninstallPackage(EasyMock.eq(DEQP_ONDEVICE_PKG)))
+                    .andReturn("").once();
+        }
+
+        mockListener.testRunStarted(ID, 1);
+        EasyMock.expectLastCall().once();
+
+        mockListener.testStarted(EasyMock.eq(testId));
+        EasyMock.expectLastCall().once();
+
+        mockListener.testEnded(EasyMock.eq(testId), EasyMock.<Map<String, String>>notNull());
+        EasyMock.expectLastCall().once();
+
+        mockListener.testRunEnded(EasyMock.anyLong(), EasyMock.<Map<String, String>>notNull());
+        EasyMock.expectLastCall().once();
+
+        EasyMock.replay(mockDevice);
+        EasyMock.replay(mockListener);
+
+        deqpTest.setDevice(mockDevice);
+        deqpTest.setBuildHelper(new StubCtsBuildHelper());
+        deqpTest.run(mockListener);
+
+        EasyMock.verify(mockListener);
+        EasyMock.verify(mockDevice);
+    }
+
+    /**
+     * Test that result code produces correctly pass or fail.
+     */
+    private void testResultCode(final String resultCode, boolean pass) throws Exception {
+        final TestIdentifier testId = new TestIdentifier("dEQP-GLES3.info", "version");
+        final String testPath = "dEQP-GLES3.info.version";
+        final String testTrie = "{dEQP-GLES3{info{version}}}";
+
+        /* MultiLineReceiver expects "\r\n" line ending. */
+        final String output = "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=releaseName\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=2014.x\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=releaseId\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=0xcafebabe\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=targetName\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=android\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginSession\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginTestCase\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-BeginTestCase-TestCasePath=" + testPath + "\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Code=" + resultCode + "\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Details=Detail" + resultCode + "\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=TestCaseResult\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=EndTestCase\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=EndSession\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_CODE: 0\r\n";
+
+        ITestDevice mockDevice = EasyMock.createMock(ITestDevice.class);
+        ITestInvocationListener mockListener
+                = EasyMock.createStrictMock(ITestInvocationListener.class);
+        Collection<TestIdentifier> tests = new ArrayList<TestIdentifier>();
+
+        tests.add(testId);
+
+        DeqpTestRunner deqpTest = new DeqpTestRunner(NAME, NAME, tests);
+        deqpTest.setAbi(UnitTests.ABI);
+
+        int version = 3 << 16;
+        EasyMock.expect(mockDevice.getProperty("ro.opengles.version"))
+                .andReturn(Integer.toString(version)).atLeastOnce();
+
+        EasyMock.expect(mockDevice.uninstallPackage(EasyMock.eq(DEQP_ONDEVICE_PKG))).andReturn("")
+                .once();
+
+        EasyMock.expect(mockDevice.installPackage(EasyMock.<File>anyObject(),
+                EasyMock.eq(true), EasyMock.eq(AbiUtils.createAbiFlag(UnitTests.ABI.getName()))))
+                .andReturn(null).once();
+
+        EasyMock.expect(mockDevice.executeShellCommand(EasyMock.eq("rm " + CASE_LIST_FILE_NAME)))
+                .andReturn("").once();
+
+        EasyMock.expect(mockDevice.executeShellCommand(EasyMock.eq("rm " + LOG_FILE_NAME)))
+                .andReturn("").once();
+
+        EasyMock.expect(mockDevice.pushString(testTrie + "\n", CASE_LIST_FILE_NAME)).andReturn(true)
+                .once();
+
+        String command = String.format(
+                "am instrument %s -w -e deqpLogFileName \"%s\" -e deqpCmdLine \""
+                    + "--deqp-caselist-file=%s --deqp-gl-config-name=rgba8888d24s8\" "
+                    + "-e deqpLogData \"%s\" %s",
+                AbiUtils.createAbiFlag(UnitTests.ABI.getName()), LOG_FILE_NAME,
+                CASE_LIST_FILE_NAME, false, INSTRUMENTATION_NAME);
+
+        mockDevice.executeShellCommand(EasyMock.eq(command),
+                EasyMock.<IShellOutputReceiver>notNull());
+
+        EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
+            @Override
+            public Object answer() {
+                IShellOutputReceiver receiver
+                        = (IShellOutputReceiver)EasyMock.getCurrentArguments()[1];
+
+                receiver.addOutput(output.getBytes(), 0, output.length());
+                receiver.flush();
+
+                return null;
+            }
+        });
+
+        mockListener.testRunStarted(ID, 1);
+        EasyMock.expectLastCall().once();
+
+        mockListener.testStarted(EasyMock.eq(testId));
+        EasyMock.expectLastCall().once();
+
+        if (!pass) {
+            mockListener.testFailed(testId,
+                    resultCode + ": Detail" + resultCode);
+
+            EasyMock.expectLastCall().once();
+        }
+
+        mockListener.testEnded(EasyMock.eq(testId), EasyMock.<Map<String, String>>notNull());
+        EasyMock.expectLastCall().once();
+
+        mockListener.testRunEnded(EasyMock.anyLong(), EasyMock.<Map<String, String>>notNull());
+        EasyMock.expectLastCall().once();
+
+        EasyMock.expect(mockDevice.uninstallPackage(EasyMock.eq(DEQP_ONDEVICE_PKG))).andReturn("")
+                .once();
+
+        EasyMock.replay(mockDevice);
+        EasyMock.replay(mockListener);
+
+        deqpTest.setDevice(mockDevice);
+        deqpTest.setBuildHelper(new StubCtsBuildHelper());
+        deqpTest.run(mockListener);
+
+        EasyMock.verify(mockListener);
+        EasyMock.verify(mockDevice);
+    }
+
+    /**
+     * Test running multiple test cases.
+     */
+    public void testRun_multipleTests() throws Exception {
+        /* MultiLineReceiver expects "\r\n" line ending. */
+        final String output = "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=releaseName\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=2014.x\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=releaseId\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=0xcafebabe\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=targetName\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=android\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginSession\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginTestCase\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-BeginTestCase-TestCasePath=dEQP-GLES3.info.vendor\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Code=Pass\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Details=Pass\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=TestCaseResult\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=EndTestCase\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginTestCase\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-BeginTestCase-TestCasePath=dEQP-GLES3.info.renderer\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Code=Pass\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Details=Pass\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=TestCaseResult\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=EndTestCase\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginTestCase\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-BeginTestCase-TestCasePath=dEQP-GLES3.info.version\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Code=Pass\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Details=Pass\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=TestCaseResult\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=EndTestCase\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginTestCase\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-BeginTestCase-TestCasePath=dEQP-GLES3.info.shading_language_version\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Code=Pass\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Details=Pass\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=TestCaseResult\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=EndTestCase\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginTestCase\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-BeginTestCase-TestCasePath=dEQP-GLES3.info.extensions\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Code=Pass\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Details=Pass\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=TestCaseResult\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=EndTestCase\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginTestCase\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-BeginTestCase-TestCasePath=dEQP-GLES3.info.render_target\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Code=Pass\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Details=Pass\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=TestCaseResult\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=EndTestCase\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_STATUS: dEQP-EventType=EndSession\r\n"
+                + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+                + "INSTRUMENTATION_CODE: 0\r\n";
+
+        final TestIdentifier[] testIds = {
+                new TestIdentifier("dEQP-GLES3.info", "vendor"),
+                new TestIdentifier("dEQP-GLES3.info", "renderer"),
+                new TestIdentifier("dEQP-GLES3.info", "version"),
+                new TestIdentifier("dEQP-GLES3.info", "shading_language_version"),
+                new TestIdentifier("dEQP-GLES3.info", "extensions"),
+                new TestIdentifier("dEQP-GLES3.info", "render_target")
+        };
+
+        final String[] testPaths = {
+                "dEQP-GLES3.info.vendor",
+                "dEQP-GLES3.info.renderer",
+                "dEQP-GLES3.info.version",
+                "dEQP-GLES3.info.shading_language_version",
+                "dEQP-GLES3.info.extensions",
+                "dEQP-GLES3.info.render_target"
+        };
+
+        final String testTrie
+                = "{dEQP-GLES3{info{vendor,renderer,version,shading_language_version,extensions,render_target}}}";
+
+        ITestDevice mockDevice = EasyMock.createMock(ITestDevice.class);
+        ITestInvocationListener mockListener
+                = EasyMock.createStrictMock(ITestInvocationListener.class);
+        Collection<TestIdentifier> tests = new ArrayList<TestIdentifier>();
+
+        for (TestIdentifier id : testIds) {
+            tests.add(id);
+        }
+
+        DeqpTestRunner deqpTest = new DeqpTestRunner(NAME, NAME, tests);
+        deqpTest.setAbi(UnitTests.ABI);
+
+        int version = 3 << 16;
+        EasyMock.expect(mockDevice.getProperty("ro.opengles.version"))
+                .andReturn(Integer.toString(version)).atLeastOnce();
+
+        EasyMock.expect(mockDevice.uninstallPackage(EasyMock.eq(DEQP_ONDEVICE_PKG))).andReturn("")
+                .once();
+        EasyMock.expect(mockDevice.installPackage(EasyMock.<File>anyObject(),
+                EasyMock.eq(true), EasyMock.eq(AbiUtils.createAbiFlag(UnitTests.ABI.getName()))))
+                .andReturn(null).once();
+
+        EasyMock.expect(mockDevice.executeShellCommand(EasyMock.eq("rm " + CASE_LIST_FILE_NAME)))
+                .andReturn("").once();
+
+        EasyMock.expect(mockDevice.executeShellCommand(EasyMock.eq("rm " + LOG_FILE_NAME)))
+                .andReturn("").once();
+
+        EasyMock.expect(mockDevice.pushString(testTrie + "\n", CASE_LIST_FILE_NAME))
+                .andReturn(true).once();
+
+        String command = String.format(
+                "am instrument %s -w -e deqpLogFileName \"%s\" -e deqpCmdLine \""
+                    + "--deqp-caselist-file=%s --deqp-gl-config-name=rgba8888d24s8\" "
+                    + "-e deqpLogData \"%s\" %s",
+                AbiUtils.createAbiFlag(UnitTests.ABI.getName()), LOG_FILE_NAME,
+                CASE_LIST_FILE_NAME, false, INSTRUMENTATION_NAME);
+
+        mockDevice.executeShellCommand(EasyMock.eq(command),
+                EasyMock.<IShellOutputReceiver>notNull());
+
+        EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
+            @Override
+            public Object answer() {
+                IShellOutputReceiver receiver
+                        = (IShellOutputReceiver)EasyMock.getCurrentArguments()[1];
+
+                receiver.addOutput(output.getBytes(), 0, output.length());
+                receiver.flush();
+
+                return null;
+            }
+        });
+
+        mockListener.testRunStarted(ID, testPaths.length);
+        EasyMock.expectLastCall().once();
+
+        for (int i = 0; i < testPaths.length; i++) {
+            mockListener.testStarted(EasyMock.eq(testIds[i]));
+            EasyMock.expectLastCall().once();
+
+            mockListener.testEnded(EasyMock.eq(testIds[i]),
+                    EasyMock.<Map<String, String>>notNull());
+
+            EasyMock.expectLastCall().once();
+        }
+
+        mockListener.testRunEnded(EasyMock.anyLong(), EasyMock.<Map<String, String>>notNull());
+        EasyMock.expectLastCall().once();
+
+        EasyMock.expect(mockDevice.uninstallPackage(EasyMock.eq(DEQP_ONDEVICE_PKG))).andReturn("")
+                .once();
+
+        EasyMock.replay(mockDevice);
+        EasyMock.replay(mockListener);
+
+        deqpTest.setDevice(mockDevice);
+        deqpTest.setBuildHelper(new StubCtsBuildHelper());
+        deqpTest.run(mockListener);
+
+        EasyMock.verify(mockListener);
+        EasyMock.verify(mockDevice);
+    }
+
+    /**
+     * Test OpeGL ES3 tests on device with OpenGL ES2.
+     */
+    public void testRun_require30DeviceVersion20() throws Exception {
+        testGlesVersion(3, 0, 2, 0);
+    }
+
+    /**
+     * Test OpeGL ES3.1 tests on device with OpenGL ES2.
+     */
+    public void testRun_require31DeviceVersion20() throws Exception {
+        testGlesVersion(3, 1, 2, 0);
+    }
+
+    /**
+     * Test OpeGL ES3 tests on device with OpenGL ES3.
+     */
+    public void testRun_require30DeviceVersion30() throws Exception {
+        testGlesVersion(3, 0, 3, 0);
+    }
+
+    /**
+     * Test OpeGL ES3.1 tests on device with OpenGL ES3.
+     */
+    public void testRun_require31DeviceVersion30() throws Exception {
+        testGlesVersion(3, 1, 3, 0);
+    }
+
+    /**
+     * Test OpeGL ES3 tests on device with OpenGL ES3.1.
+     */
+    public void testRun_require30DeviceVersion31() throws Exception {
+        testGlesVersion(3, 0, 3, 1);
+    }
+
+    /**
+     * Test OpeGL ES3.1 tests on device with OpenGL ES3.1.
+     */
+    public void testRun_require31DeviceVersion31() throws Exception {
+        testGlesVersion(3, 1, 3, 1);
+    }
+
+    /**
+     * Test dEQP Pass result code.
+     */
+    public void testRun_resultPass() throws Exception {
+        testResultCode("Pass", true);
+    }
+
+    /**
+     * Test dEQP Fail result code.
+     */
+    public void testRun_resultFail() throws Exception {
+        testResultCode("Fail", false);
+    }
+
+    /**
+     * Test dEQP NotSupported result code.
+     */
+    public void testRun_resultNotSupported() throws Exception {
+        testResultCode("NotSupported", true);
+    }
+
+    /**
+     * Test dEQP QualityWarning result code.
+     */
+    public void testRun_resultQualityWarning() throws Exception {
+        testResultCode("QualityWarning", true);
+    }
+
+    /**
+     * Test dEQP CompatibilityWarning result code.
+     */
+    public void testRun_resultCompatibilityWarning() throws Exception {
+        testResultCode("CompatibilityWarning", true);
+    }
+
+    /**
+     * Test dEQP ResourceError result code.
+     */
+    public void testRun_resultResourceError() throws Exception {
+        testResultCode("ResourceError", false);
+    }
+
+    /**
+     * Test dEQP InternalError result code.
+     */
+    public void testRun_resultInternalError() throws Exception {
+        testResultCode("InternalError", false);
+    }
+
+    /**
+     * Test dEQP Crash result code.
+     */
+    public void testRun_resultCrash() throws Exception {
+        testResultCode("Crash", false);
+    }
+
+    /**
+     * Test dEQP Timeout result code.
+     */
+    public void testRun_resultTimeout() throws Exception {
+        testResultCode("Timeout", false);
+    }
+}
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/TestPackageXmlParserTest.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/TestPackageXmlParserTest.java
index ac3d394..6d87a61 100644
--- a/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/TestPackageXmlParserTest.java
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/TestPackageXmlParserTest.java
@@ -16,27 +16,28 @@
 
 package com.android.cts.tradefed.testtype;
 
+import com.android.cts.util.AbiUtils;
 import com.android.ddmlib.testrunner.TestIdentifier;
 import com.android.tradefed.util.xml.AbstractXmlParser.ParseException;
 
+import junit.framework.TestCase;
+
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.util.Iterator;
 
-import junit.framework.TestCase;
-
 /**
  * Unit tests for {@link TestPackageXmlParser}.
  */
 public class TestPackageXmlParserTest extends TestCase {
 
-    private static String INSTR_TEST_DATA =
+    private static final String INSTR_TEST_DATA =
         "<TestPackage AndroidFramework=\"Android 1.0\" appNameSpace=\"com.example\" " +
         "appPackageName=\"android.example\" name=\"CtsExampleTestCases\" " +
         "runner=\"android.test.InstrumentationTestRunner\" version=\"1.0\">" +
         "</TestPackage>";
 
-    private static String HOST_TEST_DATA =
+    private static final String HOST_TEST_DATA =
         "<TestPackage hostSideOnly=\"true\" >\n" +
         "    <TestSuite name=\"com\" >\n" +
         "        <TestSuite name=\"example\" >\n" +
@@ -53,16 +54,16 @@
         "    </TestSuite>\n" +
         "</TestPackage>";
 
-    private static String BAD_HOST_TEST_DATA =
+    private static final String BAD_HOST_TEST_DATA =
         "<TestPackage hostSideOnly=\"blah\" >" +
         "</TestPackage>";
 
-    private static String VM_HOST_TEST_XML = "<TestPackage vmHostTest=\"true\"></TestPackage>";
+    private static final String VM_HOST_TEST_XML =
+            "<TestPackage vmHostTest=\"true\"></TestPackage>";
 
-    private static String NATIVE_TEST_XML = "<TestPackage testType=\"native\"></TestPackage>";
+    private static final String NATIVE_TEST_XML = "<TestPackage testType=\"native\"></TestPackage>";
 
-    private static String NO_TEST_DATA =
-        "<invalid />";
+    private static final String NO_TEST_DATA = "<invalid />";
 
     /**
      * Test parsing test case xml containing an instrumentation test definition.
@@ -70,10 +71,12 @@
     public void testParse_instrPackage() throws ParseException  {
         TestPackageXmlParser parser = new TestPackageXmlParser(true);
         parser.parse(getStringAsStream(INSTR_TEST_DATA));
-        TestPackageDef def = parser.getTestPackageDef();
-        assertEquals("com.example", def.getAppNameSpace());
-        assertEquals("android.example", def.getUri());
-        assertEquals("android.test.InstrumentationTestRunner", def.getRunner());
+        for (TestPackageDef def : parser.getTestPackageDefs()) {
+            assertEquals("com.example", def.getAppNameSpace());
+            assertEquals("android.example", def.getAppPackageName());
+            assertEquals("android.test.InstrumentationTestRunner", def.getRunner());
+            assertTrue(AbiUtils.isAbiSupportedByCts(def.getAbi().getName()));
+        }
     }
 
     /**
@@ -82,43 +85,45 @@
     public void testParse_hostTest() throws ParseException  {
         TestPackageXmlParser parser = new TestPackageXmlParser(true);
         parser.parse(getStringAsStream(HOST_TEST_DATA));
-        TestPackageDef def = parser.getTestPackageDef();
-        assertEquals(TestPackageDef.HOST_SIDE_ONLY_TEST, def.getTestType());
-        assertEquals(3, def.getTests().size());
-        Iterator<TestIdentifier> iterator = def.getTests().iterator();
+        for (TestPackageDef def : parser.getTestPackageDefs()) {
+            assertEquals(TestPackageDef.HOST_SIDE_ONLY_TEST, def.getTestType());
+            assertEquals(3, def.getTests().size());
+            Iterator<TestIdentifier> iterator = def.getTests().iterator();
 
-        TestIdentifier firstTest = iterator.next();
-        assertEquals("com.example.ExampleTest", firstTest.getClassName());
-        assertEquals("testFoo", firstTest.getTestName());
+            TestIdentifier firstTest = iterator.next();
+            assertEquals("com.example.ExampleTest", firstTest.getClassName());
+            assertEquals("testFoo", firstTest.getTestName());
 
-        TestIdentifier secondTest = iterator.next();
-        assertEquals("com.example.ExampleTest", secondTest.getClassName());
-        assertEquals("testFoo2", secondTest.getTestName());
+            TestIdentifier secondTest = iterator.next();
+            assertEquals("com.example.ExampleTest", secondTest.getClassName());
+            assertEquals("testFoo2", secondTest.getTestName());
 
-        TestIdentifier thirdTest = iterator.next();
-        assertEquals("com.example2.Example2Test", thirdTest.getClassName());
-        assertEquals("testFoo", thirdTest.getTestName());
+            TestIdentifier thirdTest = iterator.next();
+            assertEquals("com.example2.Example2Test", thirdTest.getClassName());
+            assertEquals("testFoo", thirdTest.getTestName());
 
-        assertFalse(iterator.hasNext());
+            assertFalse(iterator.hasNext());
+        }
     }
 
     public void testParse_hostTest_noKnownFailures() throws ParseException  {
         TestPackageXmlParser parser = new TestPackageXmlParser(false);
         parser.parse(getStringAsStream(HOST_TEST_DATA));
-        TestPackageDef def = parser.getTestPackageDef();
-        assertEquals(TestPackageDef.HOST_SIDE_ONLY_TEST, def.getTestType());
-        assertEquals(2, def.getTests().size());
-        Iterator<TestIdentifier> iterator = def.getTests().iterator();
+        for (TestPackageDef def : parser.getTestPackageDefs()) {
+            assertEquals(TestPackageDef.HOST_SIDE_ONLY_TEST, def.getTestType());
+            assertEquals(2, def.getTests().size());
+            Iterator<TestIdentifier> iterator = def.getTests().iterator();
 
-        TestIdentifier firstTest = iterator.next();
-        assertEquals("com.example.ExampleTest", firstTest.getClassName());
-        assertEquals("testFoo", firstTest.getTestName());
+            TestIdentifier firstTest = iterator.next();
+            assertEquals("com.example.ExampleTest", firstTest.getClassName());
+            assertEquals("testFoo", firstTest.getTestName());
 
-        TestIdentifier thirdTest = iterator.next();
-        assertEquals("com.example2.Example2Test", thirdTest.getClassName());
-        assertEquals("testFoo", thirdTest.getTestName());
+            TestIdentifier thirdTest = iterator.next();
+            assertEquals("com.example2.Example2Test", thirdTest.getClassName());
+            assertEquals("testFoo", thirdTest.getTestName());
 
-        assertFalse(iterator.hasNext());
+            assertFalse(iterator.hasNext());
+        }
     }
 
     /**
@@ -127,8 +132,9 @@
     public void testParse_badHostTest() throws ParseException  {
         TestPackageXmlParser parser = new TestPackageXmlParser(true);
         parser.parse(getStringAsStream(BAD_HOST_TEST_DATA));
-        TestPackageDef def = parser.getTestPackageDef();
-        assertFalse(TestPackageDef.HOST_SIDE_ONLY_TEST.equals(def.getTestType()));
+        for (TestPackageDef def : parser.getTestPackageDefs()) {
+            assertFalse(TestPackageDef.HOST_SIDE_ONLY_TEST.equals(def.getTestType()));
+        }
     }
 
     public void testParse_vmHostTest() throws ParseException  {
@@ -142,8 +148,9 @@
     private void assertTestType(String expectedType, String xml) throws ParseException {
         TestPackageXmlParser parser = new TestPackageXmlParser(true);
         parser.parse(getStringAsStream(xml));
-        TestPackageDef def = parser.getTestPackageDef();
-        assertEquals(expectedType, def.getTestType());
+        for (TestPackageDef def : parser.getTestPackageDefs()) {
+            assertEquals(expectedType, def.getTestType());
+        }
     }
 
     /**
@@ -152,7 +159,7 @@
     public void testParse_noData() throws ParseException  {
         TestPackageXmlParser parser = new TestPackageXmlParser(true);
         parser.parse(getStringAsStream(NO_TEST_DATA));
-        assertNull(parser.getTestPackageDef());
+        assertTrue(parser.getTestPackageDefs().isEmpty());
     }
 
     private InputStream getStringAsStream(String input) {
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/TestPlanTest.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/TestPlanTest.java
index 18d4776..5b28539 100644
--- a/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/TestPlanTest.java
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/TestPlanTest.java
@@ -16,6 +16,7 @@
 
 package com.android.cts.tradefed.testtype;
 
+import com.android.cts.util.AbiUtils;
 import com.android.ddmlib.testrunner.TestIdentifier;
 import com.android.tradefed.util.xml.AbstractXmlParser.ParseException;
 
@@ -25,15 +26,19 @@
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
 
 /**
  * Unit tests for {@link TestPlan}.
  */
 public class TestPlanTest extends TestCase {
 
-    private static final String TEST_URI1 = "foo";
-    private static final String TEST_URI2 = "foo2";
+    private static final String TEST_NAME1 = "foo";
+    private static final String TEST_NAME2 = "foo2";
     private static final String EXCLUDE_TEST_CLASS = "com.example.FooTest";
     private static final String EXCLUDE_TEST_METHOD = "testFoo";
     private static final String EXCLUDE_TEST_METHOD2 = "testFoo2";
@@ -42,26 +47,26 @@
 
     static final String TEST_DATA =
         "<TestPlan version=\"1.0\">" +
-            String.format("<Entry uri=\"%s\" />", TEST_URI1) +
-            String.format("<Entry uri=\"%s\" />", TEST_URI2) +
+            String.format("<Entry name=\"%s\" />", TEST_NAME1) +
+            String.format("<Entry name=\"%s\" />", TEST_NAME2) +
         "</TestPlan>";
 
     static final String TEST_EXCLUDED_DATA =
         "<TestPlan version=\"1.0\">" +
-            String.format("<Entry uri=\"%s\" exclude=\"%s#%s\" />", TEST_URI1, EXCLUDE_TEST_CLASS,
+            String.format("<Entry name=\"%s\" exclude=\"%s#%s\" />", TEST_NAME1, EXCLUDE_TEST_CLASS,
                     EXCLUDE_TEST_METHOD) +
         "</TestPlan>";
 
     static final String TEST_MULTI_EXCLUDED_DATA =
         "<TestPlan version=\"1.0\">" +
-            String.format("<Entry uri=\"%s\" exclude=\"%s#%s;%s#%s\" />", TEST_URI1,
+            String.format("<Entry name=\"%s\" exclude=\"%s#%s;%s#%s\" />", TEST_NAME1,
                     EXCLUDE_TEST_CLASS, EXCLUDE_TEST_METHOD, EXCLUDE_TEST_CLASS,
                     EXCLUDE_TEST_METHOD2) +
         "</TestPlan>";
 
     static final String TEST_CLASS_EXCLUDED_DATA =
         "<TestPlan version=\"1.0\">" +
-            String.format("<Entry uri=\"%s\" exclude=\"%s\" />", TEST_URI1,
+            String.format("<Entry name=\"%s\" exclude=\"%s\" />", TEST_NAME1,
                     EXCLUDE_TEST_CLASS) +
         "</TestPlan>";
 
@@ -70,11 +75,11 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mPlan = new TestPlan("plan");
+        mPlan = new TestPlan("plan", AbiUtils.getAbisSupportedByCts());
     }
 
     /**
-     * Simple test for parsing a plan containing two uris
+     * Simple test for parsing a plan containing two names
      */
     public void testParse() throws ParseException  {
         mPlan.parse(getStringAsStream(TEST_DATA));
@@ -86,13 +91,20 @@
      * @param plan
      */
     private void assertTestData(TestPlan plan) {
-        assertEquals(2, plan.getTestUris().size());
-        Iterator<String> iter = plan.getTestUris().iterator();
-        // assert uris in order
-        assertEquals(TEST_URI1, iter.next());
-        assertEquals(TEST_URI2, iter.next());
-        assertFalse(plan.getExcludedTestFilter(TEST_URI1).hasExclusion());
-        assertFalse(plan.getExcludedTestFilter(TEST_URI2).hasExclusion());
+        Set<String> abis = AbiUtils.getAbisSupportedByCts();
+        assertEquals(2 * abis.size(), plan.getTestIds().size());
+        List<String> sortedAbis = new ArrayList<String>(abis);
+        Collections.sort(sortedAbis);
+        Iterator<String> iter = plan.getTestIds().iterator();
+        for (String abi : sortedAbis) {
+            String test1Id = AbiUtils.createId(abi, TEST_NAME1);
+            String test2Id = AbiUtils.createId(abi, TEST_NAME2);
+            // assert names in order
+            assertEquals(test1Id, iter.next());
+            assertEquals(test2Id, iter.next());
+            assertFalse(plan.getTestFilter(test1Id).hasExclusion());
+            assertFalse(plan.getTestFilter(test2Id).hasExclusion());
+        }
     }
 
     /**
@@ -100,10 +112,15 @@
      */
     public void testParse_exclude() throws ParseException  {
         mPlan.parse(getStringAsStream(TEST_EXCLUDED_DATA));
-        assertEquals(1, mPlan.getTestUris().size());
-        TestFilter filter = mPlan.getExcludedTestFilter(TEST_URI1);
-        assertTrue(filter.getExcludedTests().contains(new TestIdentifier(EXCLUDE_TEST_CLASS,
-                EXCLUDE_TEST_METHOD)));
+        Set<String> abis = AbiUtils.getAbisSupportedByCts();
+        assertEquals(abis.size(), mPlan.getTestIds().size());
+
+        for (String abi : abis) {
+            String test1Id = AbiUtils.createId(abi, TEST_NAME1);
+            TestFilter filter = mPlan.getTestFilter(test1Id);
+            assertTrue(filter.getExcludedTests().contains(new TestIdentifier(EXCLUDE_TEST_CLASS,
+                    EXCLUDE_TEST_METHOD)));
+        }
     }
 
     /**
@@ -119,12 +136,17 @@
      * @param plan
      */
     private void assertMultiExcluded(TestPlan plan) {
-        assertEquals(1, plan.getTestUris().size());
-        TestFilter filter = plan.getExcludedTestFilter(TEST_URI1);
-        assertTrue(filter.getExcludedTests().contains(new TestIdentifier(EXCLUDE_TEST_CLASS,
-                EXCLUDE_TEST_METHOD)));
-        assertTrue(filter.getExcludedTests().contains(new TestIdentifier(EXCLUDE_TEST_CLASS,
-                EXCLUDE_TEST_METHOD2)));
+        Set<String> abis = AbiUtils.getAbisSupportedByCts();
+        assertEquals(abis.size(), plan.getTestIds().size());
+
+        for (String abi : abis) {
+            String test1Id = AbiUtils.createId(abi, TEST_NAME1);
+            TestFilter filter = plan.getTestFilter(test1Id);
+            assertTrue(filter.getExcludedTests().contains(new TestIdentifier(EXCLUDE_TEST_CLASS,
+                    EXCLUDE_TEST_METHOD)));
+            assertTrue(filter.getExcludedTests().contains(new TestIdentifier(EXCLUDE_TEST_CLASS,
+                    EXCLUDE_TEST_METHOD2)));
+        }
     }
 
     /**
@@ -132,16 +154,21 @@
      */
     public void testParse_classExclude() throws ParseException  {
         mPlan.parse(getStringAsStream(TEST_CLASS_EXCLUDED_DATA));
-        assertEquals(1, mPlan.getTestUris().size());
-        TestFilter filter = mPlan.getExcludedTestFilter(TEST_URI1);
-        assertTrue(filter.getExcludedClasses().contains(EXCLUDE_TEST_CLASS));
+        Set<String> abis = AbiUtils.getAbisSupportedByCts();
+        assertEquals(abis.size(), mPlan.getTestIds().size());
+
+        for (String abi : abis) {
+            String test1Id = AbiUtils.createId(abi, TEST_NAME1);
+            TestFilter filter = mPlan.getTestFilter(test1Id);
+            assertTrue(filter.getExcludedClasses().contains(EXCLUDE_TEST_CLASS));
+        }
     }
 
     /**
      * Test serializing an empty plan
      * @throws IOException
      */
-    public void testSerialize_empty() throws ParseException, IOException  {
+    public void testSerialize_empty() throws IOException  {
         ByteArrayOutputStream outStream = new ByteArrayOutputStream();
         mPlan.serialize(outStream);
         assertTrue(outStream.toString().contains(EMPTY_DATA));
@@ -152,11 +179,14 @@
      * @throws IOException
      */
     public void testSerialize_packages() throws ParseException, IOException  {
-        mPlan.addPackage(TEST_URI1);
-        mPlan.addPackage(TEST_URI2);
+        Set<String> abis = AbiUtils.getAbisSupportedByCts();
+        for (String abi : abis) {
+            mPlan.addPackage(AbiUtils.createId(abi, TEST_NAME1));
+            mPlan.addPackage(AbiUtils.createId(abi, TEST_NAME2));
+        }
         ByteArrayOutputStream outStream = new ByteArrayOutputStream();
         mPlan.serialize(outStream);
-        TestPlan parsedPlan = new TestPlan("parsed");
+        TestPlan parsedPlan = new TestPlan("parsed", AbiUtils.getAbisSupportedByCts());
         parsedPlan.parse(getStringAsStream(outStream.toString()));
         // parsedPlan should contain same contents as TEST_DATA
         assertTestData(parsedPlan);
@@ -166,14 +196,19 @@
      * Test serializing and deserializing plan with multiple excluded tests
      */
     public void testSerialize_multiExclude() throws ParseException, IOException  {
-        mPlan.addPackage(TEST_URI1);
-        mPlan.addExcludedTest(TEST_URI1, new TestIdentifier(EXCLUDE_TEST_CLASS,
-                EXCLUDE_TEST_METHOD));
-        mPlan.addExcludedTest(TEST_URI1, new TestIdentifier(EXCLUDE_TEST_CLASS,
-                EXCLUDE_TEST_METHOD2));
+        Set<String> abis = AbiUtils.getAbisSupportedByCts();
+
+        for (String abi : abis) {
+            String test1Id = AbiUtils.createId(abi, TEST_NAME1);
+            mPlan.addPackage(test1Id);
+            mPlan.addExcludedTest(test1Id, new TestIdentifier(EXCLUDE_TEST_CLASS,
+                    EXCLUDE_TEST_METHOD));
+            mPlan.addExcludedTest(test1Id, new TestIdentifier(EXCLUDE_TEST_CLASS,
+                    EXCLUDE_TEST_METHOD2));
+        }
         ByteArrayOutputStream outStream = new ByteArrayOutputStream();
         mPlan.serialize(outStream);
-        TestPlan parsedPlan = new TestPlan("parsed");
+        TestPlan parsedPlan = new TestPlan("parsed", AbiUtils.getAbisSupportedByCts());
         parsedPlan.parse(getStringAsStream(outStream.toString()));
         // parsedPlan should contain same contents as TEST_DATA
         assertMultiExcluded(parsedPlan);
diff --git a/tools/utils/Android.mk b/tools/utils/Android.mk
index 36081ca..0ba5cf4 100644
--- a/tools/utils/Android.mk
+++ b/tools/utils/Android.mk
@@ -25,6 +25,6 @@
 LOCAL_CLASSPATH := $(HOST_JDK_TOOLS_JAR)
 
 LOCAL_JAVA_LIBRARIES := junit
-LOCAL_STATIC_JAVA_LIBRARIES := vogarexpectlib
+LOCAL_STATIC_JAVA_LIBRARIES := ctsabiutilslib vogarexpectlib
 
 include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/tools/utils/CollectAllTests.java b/tools/utils/CollectAllTests.java
index fe13e00..ed74824 100644
--- a/tools/utils/CollectAllTests.java
+++ b/tools/utils/CollectAllTests.java
@@ -13,7 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+import com.android.cts.util.AbiUtils;
 
+import org.junit.runner.RunWith;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
@@ -21,20 +23,16 @@
 
 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 +45,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 {
 
@@ -69,9 +63,9 @@
     private static final String TEST_TYPE = "LOCAL_TEST_TYPE :";
 
     public static void main(String[] args) {
-        if (args.length < 4 || args.length > 6) {
+        if (args.length < 5 || args.length > 7) {
             System.err.println("usage: CollectAllTests <output-file> <manifest-file> <jar-file> "
-                               + "<java-package> [expectation-dir [makefile-file]]");
+                               + "<java-package> <architecture> [expectation-dir [makefile-file]]");
             if (args.length != 0) {
                 System.err.println("received:");
                 for (String arg : args) {
@@ -94,8 +88,14 @@
                 return;
             }
         }
-        String libcoreExpectationDir = (args.length > 4) ? args[4] : null;
-        String androidMakeFile = (args.length > 5) ? args[5] : null;
+        String architecture = args[4];
+        if (architecture == null || architecture.equals("")) {
+            System.err.println("Invalid architecture");
+            System.exit(1);
+            return;
+        }
+        String libcoreExpectationDir = (args.length > 5) ? args[5] : null;
+        String androidMakeFile = (args.length > 6) ? args[6] : null;
 
         final TestType testType = TestType.getTestType(androidMakeFile);
 
@@ -203,18 +203,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, architecture, testCases, klass);
                     continue;
                 } catch (NoSuchMethodException e) {
                 } catch (SecurityException e) {
@@ -222,9 +223,10 @@
                             + className);
                     e.printStackTrace();
                 }
+
                 try {
                     klass.getConstructor(new Class<?>[0]);
-                    addToTests(expectations, testCases, klass.asSubclass(TestCase.class));
+                    addToTests(expectations, architecture, testCases, klass);
                     continue;
                 } catch (NoSuchMethodException e) {
                 } catch (SecurityException e) {
@@ -276,7 +278,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,32 +316,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 isBrokenTest(final Class<? extends TestCase> testClass,
-            final String testName)  {
-        return getAnnotation(testClass, testName, BROKEN_TEST) != 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 boolean hasSideEffects(final Class<? extends TestCase> testClass,
-            final String testName) {
-        return getAnnotation(testClass, testName, SIDE_EFFECT) != 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);
@@ -372,39 +364,45 @@
     }
 
     private static void addToTests(ExpectationStore[] expectations,
+                                   String architecture,
                                    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, architecture, testCases, testClass, testName);
         }
     }
 
     private static void addToTests(ExpectationStore[] expectations,
+                                   String architecture,
                                    Map<String,TestClass> testCases,
-                                   Class<? extends TestCase> test,
+                                   Class<?> test,
                                    String testName) {
 
         String testClassName = test.getName();
@@ -413,15 +411,9 @@
         if (isKnownFailure(test, testName)) {
             System.out.println("ignoring known failure: " + test + "#" + testName);
             return;
-        } else if (isBrokenTest(test, testName)) {
-            System.out.println("ignoring broken test: " + test + "#" + testName);
-            return;
         } else if (isSuppressed(test, testName)) {
             System.out.println("ignoring suppressed test: " + test + "#" + testName);
             return;
-        } else if (hasSideEffects(test, testName)) {
-            System.out.println("ignoring test with side effects: " + test + "#" + testName);
-            return;
         } else if (VogarUtils.isVogarKnownFailure(expectations,
                                                   testClassName,
                                                   testName)) {
@@ -430,7 +422,11 @@
             return;
         }
 
-        TestClass testClass = null;
+        Set<String> supportedAbis = VogarUtils.extractSupportedAbis(architecture,
+                                                                    expectations,
+                                                                    testClassName,
+                                                                    testName);
+        TestClass testClass;
         if (testCases.containsKey(testClassName)) {
             testClass = testCases.get(testClassName);
         } else {
@@ -438,7 +434,42 @@
             testCases.put(testClassName, testClass);
         }
 
-        testClass.mCases.add(new TestMethod(testName, "", "", knownFailure, false, false));
+        testClass.mCases.add(new TestMethod(testName, "", "", supportedAbis,
+              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;
     }
 
     /**
diff --git a/tools/utils/DescriptionGenerator.java b/tools/utils/DescriptionGenerator.java
index 0731b49..09e1118 100644
--- a/tools/utils/DescriptionGenerator.java
+++ b/tools/utils/DescriptionGenerator.java
@@ -22,6 +22,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
+import java.util.Set;
 
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
@@ -38,6 +39,7 @@
 import org.w3c.dom.NodeList;
 
 import vogar.ExpectationStore;
+import vogar.Expectation;
 
 import com.sun.javadoc.AnnotationDesc;
 import com.sun.javadoc.AnnotationTypeDoc;
@@ -66,8 +68,6 @@
 public class DescriptionGenerator extends Doclet {
     static final String HOST_CONTROLLER = "dalvik.annotation.HostController";
     static final String KNOWN_FAILURE = "dalvik.annotation.KnownFailure";
-    static final String BROKEN_TEST = "dalvik.annotation.BrokenTest";
-    static final String SIDE_EFFECT = "dalvik.annotation.SideEffect";
     static final String SUPPRESSED_TEST = "android.test.suitebuilder.annotation.Suppress";
     static final String CTS_EXPECTATION_DIR = "cts/tests/expectations";
 
@@ -84,11 +84,13 @@
     static final String ATTRIBUTE_VALUE_FRAMEWORK = "Android 1.0";
 
     static final String ATTRIBUTE_NAME = "name";
+    static final String ATTRIBUTE_ABIS = "abis";
     static final String ATTRIBUTE_HOST_CONTROLLER = "HostController";
 
     static final String XML_OUTPUT_PATH = "./description.xml";
 
     static final String OUTPUT_PATH_OPTION = "-o";
+    static final String ARCHITECTURE_OPTION = "-a";
 
     /**
      * Start to parse the classes passed in by javadoc, and generate
@@ -105,12 +107,21 @@
         }
 
         String outputPath = XML_OUTPUT_PATH;
+        String architecture = null;
         String[][] options = root.options();
         for (String[] option : options) {
-            if (option.length == 2 && option[0].equals(OUTPUT_PATH_OPTION)) {
-                outputPath = option[1];
+            if (option.length == 2) {
+                if (option[0].equals(OUTPUT_PATH_OPTION)) {
+                    outputPath = option[1];
+                } else if (option[0].equals(ARCHITECTURE_OPTION)) {
+                    architecture = option[1];
+                }
             }
         }
+        if (architecture == null || architecture.equals("")) {
+            Log.e("Missing architecture!", null);
+            return false;
+        }
 
         XMLGenerator xmlGenerator = null;
         try {
@@ -130,7 +141,7 @@
 
         for (ClassDoc clazz : classes) {
             if ((!clazz.isAbstract()) && (isValidJUnitTestCase(clazz))) {
-                xmlGenerator.addTestClass(new TestClass(clazz, ctsExpectationStore));
+                xmlGenerator.addTestClass(new TestClass(clazz, ctsExpectationStore, architecture));
             }
         }
 
@@ -422,6 +433,8 @@
                     Node caseNode = elem.appendChild(mDoc.createElement(TAG_TEST));
 
                     setAttribute(caseNode, ATTRIBUTE_NAME, caze.mName);
+                    String abis = caze.mAbis.toString();
+                    setAttribute(caseNode, ATTRIBUTE_ABIS, abis.substring(1, abis.length() - 1));
                     if ((caze.mController != null) && (caze.mController.length() != 0)) {
                         setAttribute(caseNode, ATTRIBUTE_HOST_CONTROLLER, caze.mController);
                     }
@@ -511,9 +524,9 @@
          *
          * @param clazz The specified ClassDoc.
          */
-        TestClass(ClassDoc clazz, ExpectationStore expectationStore) {
+        TestClass(ClassDoc clazz, ExpectationStore expectationStore, String architecture) {
             mName = clazz.toString();
-            mCases = getTestMethods(expectationStore, clazz);
+            mCases = getTestMethods(expectationStore, architecture, clazz);
         }
 
         /**
@@ -522,7 +535,8 @@
          * @param clazz The specified ClassDoc.
          * @return A collection of TestMethod.
          */
-        Collection<TestMethod> getTestMethods(ExpectationStore expectationStore, ClassDoc clazz) {
+        Collection<TestMethod> getTestMethods(ExpectationStore expectationStore,
+                String architecture, ClassDoc clazz) {
             Collection<MethodDoc> methods = getAllMethods(clazz);
 
             ArrayList<TestMethod> cases = new ArrayList<TestMethod>();
@@ -545,8 +559,6 @@
                         controller = getAnnotationDescription(cAnnot);
                     } else if (atype.toString().equals(KNOWN_FAILURE)) {
                         knownFailure = getAnnotationDescription(cAnnot);
-                    } else if (atype.toString().equals(BROKEN_TEST)) {
-                        isBroken = true;
                     } else if (atype.toString().equals(SUPPRESSED_TEST)) {
                         isSuppressed = true;
                     }
@@ -557,8 +569,13 @@
                 }
 
                 if (name.startsWith("test")) {
-                    cases.add(new TestMethod(name, method.commentText(), controller, knownFailure,
-                            isBroken, isSuppressed));
+                    Expectation expectation = expectationStore.get(
+                            VogarUtils.buildFullTestName(clazz.toString(), name));
+                    Set<String> supportedAbis =
+                            VogarUtils.extractSupportedAbis(architecture, expectation);
+                    cases.add(new TestMethod(
+                            name, method.commentText(), controller, supportedAbis,
+                                    knownFailure, isBroken, isSuppressed));
                 }
             }
 
@@ -614,6 +631,7 @@
         String mName;
         String mDescription;
         String mController;
+        Set<String> mAbis;
         String mKnownFailure;
         boolean mIsBroken;
         boolean mIsSuppressed;
@@ -625,11 +643,12 @@
          * @param description The description of the test case.
          * @param knownFailure The reason of known failure.
          */
-        TestMethod(String name, String description, String controller, String knownFailure,
-                boolean isBroken, boolean isSuppressed) {
+        TestMethod(String name, String description, String controller, Set<String> abis,
+                String knownFailure, boolean isBroken, boolean isSuppressed) {
             mName = name;
             mDescription = description;
             mController = controller;
+            mAbis = abis;
             mKnownFailure = knownFailure;
             mIsBroken = isBroken;
             mIsSuppressed = isSuppressed;
diff --git a/tools/utils/VogarUtils.java b/tools/utils/VogarUtils.java
index c7070a5..5e8b944 100644
--- a/tools/utils/VogarUtils.java
+++ b/tools/utils/VogarUtils.java
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+import com.android.cts.util.AbiUtils;
+
 import vogar.Expectation;
 import vogar.ExpectationStore;
 import vogar.ModeId;
@@ -38,12 +40,26 @@
         return false;
     }
 
+    /**
+     * @return true iff the class/name is found in the vogar known failure list and it is not
+     * a known failure that is a result of an unsupported abi.
+     */
     public static boolean isVogarKnownFailure(ExpectationStore expectationStore,
             final String testClassName,
             final String testMethodName) {
-        String fullTestName = String.format("%s#%s", testClassName, testMethodName);
-        return expectationStore != null
-                && expectationStore.get(fullTestName) != Expectation.SUCCESS;
+        if (expectationStore == null) {
+            return false;
+        }
+        String fullTestName = buildFullTestName(testClassName, testMethodName);
+        Expectation expectation = expectationStore.get(fullTestName);
+        if (expectation == Expectation.SUCCESS) {
+            return false;
+        }
+
+        String description = expectation.getDescription();
+        boolean foundAbi = AbiUtils.parseAbiList(description).size() > 0;
+
+        return expectation != Expectation.SUCCESS && !foundAbi;
     }
 
     public static ExpectationStore provideExpectationStore(String dir) throws IOException {
@@ -67,4 +83,49 @@
         }
         return expectSet;
     }
+
+    /** @return the test name in the form of com.android.myclass.TestClass#testMyMethod */
+    public static String buildFullTestName(String testClass, String testMethodName) {
+        return String.format("%s#%s", testClass, testMethodName);
+    }
+
+    /**
+     * This method looks in the description field of the Vogar entry for the ABI_LIST_MARKER
+     * and returns the list of abis found there.
+     *
+     * @return The Set of supported abis parsed from the {@code expectation}'s description.
+     */
+    public static Set<String> extractSupportedAbis(String architecture, Expectation expectation) {
+        Set<String> supportedAbiSet = AbiUtils.getAbisForArch(architecture);
+        if (expectation == null || expectation.getDescription().isEmpty()) {
+            // Include all abis since there was no limitation found in the description
+            return supportedAbiSet;
+        }
+
+        // Remove any abis that are not supported for the test.
+        supportedAbiSet.removeAll(AbiUtils.parseAbiList(expectation.getDescription()));
+
+        return supportedAbiSet;
+    }
+
+    /**
+     * Determine the correct set of ABIs for the given className/testName.
+     *
+     * @return the set of ABIs that can be expected to pass for the given combination of
+     * {@code architecture}, {@code className} and {@code testName}.
+     */
+    public static Set<String> extractSupportedAbis(String architecture,
+                                                   ExpectationStore[] expectationStores,
+                                                   String className,
+                                                   String testName) {
+
+        String fullTestName = VogarUtils.buildFullTestName(className, testName);
+        Set<String> supportedAbiSet = AbiUtils.getAbisForArch(architecture);
+        for (ExpectationStore expectationStore : expectationStores) {
+            Expectation expectation = expectationStore.get(fullTestName);
+            supportedAbiSet.retainAll(extractSupportedAbis(architecture, expectation));
+        }
+
+        return supportedAbiSet;
+    }
 }
diff --git a/tools/utils/buildCts.py b/tools/utils/buildCts.py
index fd91c40..4d04e1a 100755
--- a/tools/utils/buildCts.py
+++ b/tools/utils/buildCts.py
@@ -78,9 +78,6 @@
     """Generate test descriptions for all packages."""
     pool = Pool(processes=2)
 
-    # individually generate descriptions not following conventions
-    pool.apply_async(GenerateSignatureCheckDescription, [self.test_repository])
-
     # generate test descriptions for android tests
     results = []
     pool.close()
@@ -118,23 +115,25 @@
     plan.Exclude('android\.performance.*')
     self.__WritePlan(plan, 'SDK')
 
-    plan.Exclude(r'android\.tests\.sigtest')
+    plan.Exclude(r'android\.signature')
     plan.Exclude(r'android\.core.*')
     self.__WritePlan(plan, 'Android')
 
     plan = tools.TestPlan(packages)
     plan.Include(r'android\.core\.tests.*')
+    plan.Exclude(r'android\.core\.tests\.libcore.\package.\harmony*')
     self.__WritePlan(plan, 'Java')
 
+    # TODO: remove this once the tests are fixed and merged into Java plan above.
+    plan = tools.TestPlan(packages)
+    plan.Include(r'android\.core\.tests\.libcore.\package.\harmony*')
+    self.__WritePlan(plan, 'Harmony')
+
     plan = tools.TestPlan(packages)
     plan.Include(r'android\.core\.vm-tests-tf')
     self.__WritePlan(plan, 'VM-TF')
 
     plan = tools.TestPlan(packages)
-    plan.Include(r'android\.tests\.sigtest')
-    self.__WritePlan(plan, 'Signature')
-
-    plan = tools.TestPlan(packages)
     plan.Include(r'android\.tests\.appsecurity')
     self.__WritePlan(plan, 'AppSecurity')
 
@@ -158,121 +157,270 @@
 
     # CTS Stable plan
     plan = tools.TestPlan(packages)
-    plan.Exclude(r'android\.display')
+    plan.Exclude(r'com\.android\.cts\.browserbench')
     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
+    # CTS Flaky plan - list of tests known to be flaky in lab environment
     plan = tools.TestPlan(packages)
     plan.Exclude('.*')
-    plan.Include(r'android\.display')
+    plan.Include(r'com\.android\.cts\.browserbench')
     for package, test_list in flaky_tests.iteritems():
-      plan.Include(package)
+      plan.Include(package+'$')
       plan.IncludeTests(package, test_list)
     self.__WritePlan(plan, 'CTS-flaky')
 
+    small_tests = BuildAospSmallSizeTestList()
+    medium_tests = BuildAospMediumSizeTestList()
+    new_test_packages = BuildCtsVettedNewPackagesList()
+
+    # CTS - sub plan for public, small size tests
+    plan = tools.TestPlan(packages)
+    plan.Exclude('.*')
+    for package, test_list in small_tests.iteritems():
+      plan.Include(package+'$')
+    plan.Exclude(r'com\.android\.cts\.browserbench')
+    for package, test_list in flaky_tests.iteritems():
+      plan.ExcludeTests(package, test_list)
+    self.__WritePlan(plan, 'CTS-kitkat-small')
+
+    # CTS - sub plan for public, medium size tests
+    plan = tools.TestPlan(packages)
+    plan.Exclude('.*')
+    for package, test_list in medium_tests.iteritems():
+      plan.Include(package+'$')
+    plan.Exclude(r'com\.android\.cts\.browserbench')
+    for package, test_list in flaky_tests.iteritems():
+      plan.ExcludeTests(package, test_list)
+    self.__WritePlan(plan, 'CTS-kitkat-medium')
+
+    # CTS - sub plan for hardware tests which is public, large
+    plan = tools.TestPlan(packages)
+    plan.Exclude('.*')
+    plan.Include(r'android\.hardware$')
+    plan.Exclude(r'com\.android\.cts\.browserbench')
+    for package, test_list in flaky_tests.iteritems():
+      plan.ExcludeTests(package, test_list)
+    self.__WritePlan(plan, 'CTS-hardware')
+
+    # CTS - sub plan for media tests which is public, large
+    plan = tools.TestPlan(packages)
+    plan.Exclude('.*')
+    plan.Include(r'android\.media$')
+    plan.Include(r'android\.view$')
+    plan.Exclude(r'com\.android\.cts\.browserbench')
+    for package, test_list in flaky_tests.iteritems():
+      plan.ExcludeTests(package, test_list)
+    self.__WritePlan(plan, 'CTS-media')
+
+    # CTS - sub plan for mediastress tests which is public, large
+    plan = tools.TestPlan(packages)
+    plan.Exclude('.*')
+    plan.Include(r'android\.mediastress$')
+    plan.Exclude(r'com\.android\.cts\.browserbench')
+    for package, test_list in flaky_tests.iteritems():
+      plan.ExcludeTests(package, test_list)
+    self.__WritePlan(plan, 'CTS-mediastress')
+
+    # CTS - sub plan for new tests that is vetted for L launch
+    plan = tools.TestPlan(packages)
+    plan.Exclude('.*')
+    for package, test_list in new_test_packages.iteritems():
+      plan.Include(package+'$')
+    plan.Exclude(r'com\.android\.cts\.browserbench')
+    for package, test_list in flaky_tests.iteritems():
+      plan.ExcludeTests(package, test_list)
+    self.__WritePlan(plan, 'CTS-l-tests')
+
+    #CTS - sub plan for new test packages added for staging
+    plan = tools.TestPlan(packages)
+    for package, test_list in small_tests.iteritems():
+      plan.Exclude(package+'$')
+    for package, test_list in medium_tests.iteritems():
+      plan.Exclude(package+'$')
+    for package, tests_list in new_test_packages.iteritems():
+      plan.Exclude(package+'$')
+    plan.Exclude(r'android\.hardware$')
+    plan.Exclude(r'android\.media$')
+    plan.Exclude(r'android\.view$')
+    plan.Exclude(r'android\.mediastress$')
+    plan.Exclude(r'com\.android\.cts\.browserbench')
+    for package, test_list in flaky_tests.iteritems():
+      plan.ExcludeTests(package, test_list)
+    self.__WritePlan(plan, 'CTS-staging')
+
+    plan = tools.TestPlan(packages)
+    plan.Exclude('.*')
+    plan.Include(r'com\.drawelements\.')
+    self.__WritePlan(plan, 'CTS-DEQP')
+
+    plan = tools.TestPlan(packages)
+    plan.Exclude('.*')
+    plan.Include(r'android\.webgl')
+    self.__WritePlan(plan, 'CTS-webview')
+
+
+def BuildAospMediumSizeTestList():
+  """ Construct a defaultdic that lists package names of medium tests
+      already published to aosp. """
+  return {
+      'android.app' : [],
+      'android.core.tests.libcore.package.libcore' : [],
+      'android.core.tests.libcore.package.org' : [],
+      'android.core.vm-tests-tf' : [],
+      'android.dpi' : [],
+      'android.host.security' : [],
+      'android.net' : [],
+      'android.os' : [],
+      'android.permission2' : [],
+      'android.security' : [],
+      'android.telephony' : [],
+      'android.webkit' : [],
+      'android.widget' : [],
+      'com.android.cts.browserbench' : []}
+
+def BuildAospSmallSizeTestList():
+  """ Construct a defaultdict that lists packages names of small tests
+      already published to aosp. """
+  return {
+      'android.aadb' : [],
+      'android.acceleration' : [],
+      'android.accessibility' : [],
+      'android.accessibilityservice' : [],
+      'android.accounts' : [],
+      'android.admin' : [],
+      'android.animation' : [],
+      'android.bionic' : [],
+      'android.bluetooth' : [],
+      'android.calendarcommon' : [],
+      'android.content' : [],
+      'android.core.tests.libcore.package.com' : [],
+      'android.core.tests.libcore.package.conscrypt' : [],
+      'android.core.tests.libcore.package.dalvik' : [],
+      'android.core.tests.libcore.package.sun' : [],
+      'android.core.tests.libcore.package.tests' : [],
+      'android.database' : [],
+      'android.dreams' : [],
+      'android.drm' : [],
+      'android.effect' : [],
+      'android.gesture' : [],
+      'android.graphics' : [],
+      'android.graphics2' : [],
+      'android.jni' : [],
+      'android.keystore' : [],
+      'android.location' : [],
+      'android.nativemedia.sl' : [],
+      'android.nativemedia.xa' : [],
+      'android.nativeopengl' : [],
+      'android.ndef' : [],
+      'android.opengl' : [],
+      'android.openglperf' : [],
+      'android.permission' : [],
+      'android.preference' : [],
+      'android.preference2' : [],
+      'android.provider' : [],
+      'android.renderscript' : [],
+      'android.rscpp' : [],
+      'android.rsg' : [],
+      'android.sax' : [],
+      'android.signature' : [],
+      'android.speech' : [],
+      'android.tests.appsecurity' : [],
+      'android.text' : [],
+      'android.textureview' : [],
+      'android.theme' : [],
+      'android.usb' : [],
+      'android.util' : [],
+      'com.android.cts.dram' : [],
+      'com.android.cts.filesystemperf' : [],
+      'com.android.cts.jank' : [],
+      'com.android.cts.opengl' : [],
+      'com.android.cts.simplecpu' : [],
+      'com.android.cts.ui' : [],
+      'com.android.cts.uihost' : [],
+      'com.android.cts.videoperf' : [],
+      'zzz.android.monkey' : []}
+
+def BuildCtsVettedNewPackagesList():
+  """ Construct a defaultdict that maps package names that is vetted for L. """
+  return {
+      'android.JobScheduler' : [],
+      'android.core.tests.libcore.package.harmony_annotation' : [],
+      'android.core.tests.libcore.package.harmony_beans' : [],
+      'android.core.tests.libcore.package.harmony_java_io' : [],
+      'android.core.tests.libcore.package.harmony_java_lang' : [],
+      'android.core.tests.libcore.package.harmony_java_math' : [],
+      'android.core.tests.libcore.package.harmony_java_net' : [],
+      'android.core.tests.libcore.package.harmony_java_nio' : [],
+      'android.core.tests.libcore.package.harmony_java_util' : [],
+      'android.core.tests.libcore.package.harmony_java_text' : [],
+      'android.core.tests.libcore.package.harmony_javax_security' : [],
+      'android.core.tests.libcore.package.harmony_logging' : [],
+      'android.core.tests.libcore.package.harmony_prefs' : [],
+      'android.core.tests.libcore.package.harmony_sql' : [],
+      'android.core.tests.libcore.package.jsr166' : [],
+      'android.core.tests.libcore.package.okhttp' : [],
+      'android.display' : [],
+      'android.host.theme' : [],
+      'android.jdwp' : [],
+      'android.location2' : [],
+      'android.print' : [],
+      'android.renderscriptlegacy' : [],
+      'android.signature' : [],
+      'android.tv' : [],
+      'android.uiautomation' : [],
+      'android.uirendering' : [],
+      'android.webgl' : [],
+      'com.drawelements.deqp.gles3' : [],
+      'com.drawelements.deqp.gles31' : []}
 
 def BuildCtsFlakyTestList():
   """ Construct a defaultdict that maps package name to a list of tests
-      that are known to be flaky. """
+      that are known to be flaky in the lab or not passing on userdebug builds. """
   return {
       'android.app' : [
-          'cts.ActivityManagerTest#testIsRunningInTestHarness',
-          'cts.AlertDialogTest#testAlertDialogCancelable',
-          'cts.ExpandableListActivityTest#testCallback',],
+          'cts.ActivityManagerTest#testIsRunningInTestHarness',],
+      'android.dpi' : [
+          'cts.DefaultManifestAttributesSdkTest#testPackageHasExpectedSdkVersion',],
       'android.hardware' : [
-          'cts.SensorIntegrationTests#testAccelerometerDoesNotStopGyroscope',
-          'cts.SensorIntegrationTests#testsAccelerometerDoesnNotStopMagnetometer',
-          'cts.SensorIntegrationTests#testAndroidTestCaseSetupProperly',
-          'cts.SensorIntegrationTests#testBatchAndFlush',
-          'cts.SensorIntegrationTests#testGyroscopeDoesNotStopAccelerometer',
-          'cts.SensorIntegrationTests#testGyroscopeDoesNotStopMagnetometer',
-          'cts.SensorIntegrationTests#testMagnetometerDoesNotStopAccelerometer',
-          'cts.SensorIntegrationTests#testMagnetometerDoesNotStopGyroscope',
-          'cts.SensorMagneticFieldTest#testBatchingStoppingOtherClients',
-          'cts.SensorMagneticFieldTest#testBatchingStoppingOtherClientsBatching',
-          'cts.SensorMagneticFieldTest#testFrequencyAccuracy',
-          'cts.SensorMagneticFieldTest#testOneClientSeveralThreads',
-          'cts.SensorMagneticFieldTest#testOneClientSeveralThreadsBatching',
-          'cts.SensorMagneticFieldTest#testStandardDeviationWhileStatic',
-          'cts.SensorMagneticFieldTest#testStoppingOtherClients',
-          'cts.SensorMagneticFieldTest#testStoppingOtherClientsBatching',
-          'cts.SensorAccelerometerTest#testBatchingStoppingOtherClients',
-          'cts.SensorAccelerometerTest#testBatchingStoppingOtherClientsBatching',
-          'cts.SensorAccelerometerTest#testFrequencyAccuracy',
-          'cts.SensorAccelerometerTest#testOneClientSeveralThreads',
-          'cts.SensorAccelerometerTest#testOneClientSeveralThreadsBatching',
-          'cts.SensorGyroscopeTest#testBatchingStoppingOtherClients',
-          'cts.SensorGyroscopeTest#testBatchingStoppingOtherClientsBatching',
-          'cts.SensorGyroscopeTest#testFrequencyAccuracy',
-          'cts.SensorGyroscopeTest#testOneClientSeveralThreads',
-          'cts.SensorGyroscopeTest#testOneClientSeveralThreadsBatching',
-          'cts.SensorGyroscopeTest#testStandardDeviationWhilStatic',
-          'cts.SensorGyroscopeTest#testStoppingOtherClients',
-          'cts.SensorGyroscopeTest#testStoppingOtherClientsBatching',
-          'cts.SensorAccelerometerTest#testStandardDeviationWhileStatic',
-          'cts.SensorAccelerometerTest#testStoppingOtherClients',
-          'cts.SensorAccelerometerTest#testStoppingOtherClientsBatching',
-          'camera2.cts.CameraDeviceTest#testCameraDeviceRepeatingRequest',
-          'camera2.cts.ImageReaderTest#testImageReaderFromCameraJpeg',
-          'cts.CameraGLTest#testCameraToSurfaceTextureMetadata',
-          'cts.CameraTest#testImmediateZoom',
-          'cts.CameraTest#testPreviewCallback',
-          'cts.CameraTest#testSmoothZoom',
           'cts.CameraTest#testVideoSnapshot',
+          'cts.CameraGLTest#testCameraToSurfaceTextureMetadata',
           'cts.CameraGLTest#testSetPreviewTextureBothCallbacks',
-          'cts.CameraGLTest#testSetPreviewTexturePreviewCallback',
           'cts.CameraGLTest#testSetPreviewTexturePreviewCallback',],
       'android.media' : [
           'cts.DecoderTest#testCodecResetsH264WithSurface',
           'cts.StreamingMediaPlayerTest#testHLS',],
-      'android.mediastress' : [
-          'cts.NativeMediaTest#test480pPlay',],
       'android.net' : [
           'cts.ConnectivityManagerTest#testStartUsingNetworkFeature_enableHipri',
-          'wifi.cts.ScanResultTest#testScanResultTimeStamp',
           'cts.DnsTest#testDnsWorks',
-          'cts.TrafficStatsTest#testTrafficStatsForLocalhost',
-          'wifi.cts.ScanResultTest#testAndroidTestCaseSetupProperly',
-          'wifi.cts.NsdManagerTest#testAndroidTestCaseSetupProperly',
           'cts.SSLCertificateSocketFactoryTest#testCreateSocket',
           'cts.SSLCertificateSocketFactoryTest#test_createSocket_bind',
           'cts.SSLCertificateSocketFactoryTest#test_createSocket_simple',
-          'cts.SSLCertificateSocketFactoryTest#test_createSocket_wrapping',],
+          'cts.SSLCertificateSocketFactoryTest#test_createSocket_wrapping',
+          'cts.TrafficStatsTest#testTrafficStatsForLocalhost',
+          'wifi.cts.NsdManagerTest#testAndroidTestCaseSetupProperly',],
+      'android.os' : [
+          'cts.BuildVersionTest#testReleaseVersion',
+          'cts.BuildTest#testIsSecureUserBuild',],
       'android.security' : [
           'cts.BannedFilesTest#testNoSu',
           'cts.BannedFilesTest#testNoSuInPath',
           'cts.ListeningPortsTest#testNoRemotelyAccessibleListeningUdp6Ports',
           'cts.ListeningPortsTest#testNoRemotelyAccessibleListeningUdpPorts',
-          'cts.PackageSignatureTest#testPackageSignatures',],
+          'cts.PackageSignatureTest#testPackageSignatures',
+          'cts.SELinuxDomainTest#testSuDomain',
+          'cts.SELinuxHostTest#testAllEnforcing',],
       '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',],
-      'android.widget' : [
-          'cts.GridViewTest#testSetNumColumns',],}
+          'cts.WebViewClientTest#testOnUnhandledKeyEvent',],
+      'com.android.cts.filesystemperf' : [
+          'RandomRWTest#testRandomRead',
+          'RandomRWTest#testRandomUpdate',],
+      '' : []}
 
 def LogGenerateDescription(name):
   print 'Generating test description for package %s' % name
 
-def GenerateSignatureCheckDescription(test_repository):
-  """Generate the test description for the signature check."""
-  LogGenerateDescription('android.tests.sigtest')
-  package = tools.TestPackage('SignatureTest', 'android.tests.sigtest')
-  package.AddAttribute('appNameSpace', 'android.tests.sigtest')
-  package.AddAttribute('signatureCheck', 'true')
-  package.AddAttribute('runner', '.InstrumentationRunner')
-  package.AddTest('android.tests.sigtest.SignatureTest.testSignature')
-  description = open(os.path.join(test_repository, 'SignatureTest.xml'), 'w')
-  package.WriteDescription(description)
-  description.close()
-
 if __name__ == '__main__':
   builder = CtsBuilder(sys.argv)
   result = builder.GenerateTestDescriptions()
diff --git a/tools/utils/cts/tools.py b/tools/utils/cts/tools.py
index 0a4c97c..649e4d7 100644
--- a/tools/utils/cts/tools.py
+++ b/tools/utils/cts/tools.py
@@ -205,7 +205,7 @@
     for package in self.all_packages:
       if self.map[package]:
         entry = doc.createElement('Entry')
-        entry.setAttribute('uri', package)
+        entry.setAttribute('name', package)
         if package in self.excludedTestsMap:
           entry.setAttribute('exclude', ';'.join(self.excludedTestsMap[package]))
         if package in self.includedTestsMap:
diff --git a/tools/utils/monsoon.py b/tools/utils/monsoon.py
new file mode 100755
index 0000000..f3d63c5
--- /dev/null
+++ b/tools/utils/monsoon.py
@@ -0,0 +1,422 @@
+#!/usr/bin/python2.6
+
+# 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.
+
+"""Interface for a USB-connected Monsoon power meter
+(http://msoon.com/LabEquipment/PowerMonitor/).
+This file requires gflags, which requires setuptools.
+To install setuptools: sudo apt-get install python-setuptools
+To install gflags, see http://code.google.com/p/python-gflags/
+To install pyserial, see http://pyserial.sourceforge.net/
+
+Example usages:
+  Set the voltage of the device 7536 to 4.0V
+  python2.6 monsoon.py --voltage=4.0 --serialno 7536
+
+  Get 5000hz data from device number 7536, with unlimited number of samples
+  python2.6 monsoon.py --samples -1 --hz 5000 --serialno 7536
+
+  Get 200Hz data for 5 seconds (1000 events) from default device
+  python2.6 monsoon.py --samples 100 --hz 200
+
+  Get unlimited 200Hz data from device attached at /dev/ttyACM0
+  python2.6 monsoon.py --samples -1 --hz 200 --device /dev/ttyACM0
+"""
+
+import fcntl
+import os
+import select
+import signal
+import stat
+import struct
+import sys
+import time
+import collections
+
+import gflags as flags  # http://code.google.com/p/python-gflags/
+
+import serial           # http://pyserial.sourceforge.net/
+
+FLAGS = flags.FLAGS
+
+class Monsoon:
+  """
+  Provides a simple class to use the power meter, e.g.
+  mon = monsoon.Monsoon()
+  mon.SetVoltage(3.7)
+  mon.StartDataCollection()
+  mydata = []
+  while len(mydata) < 1000:
+    mydata.extend(mon.CollectData())
+  mon.StopDataCollection()
+  """
+
+  def __init__(self, device=None, serialno=None, wait=1):
+    """
+    Establish a connection to a Monsoon.
+    By default, opens the first available port, waiting if none are ready.
+    A particular port can be specified with "device", or a particular Monsoon
+    can be specified with "serialno" (using the number printed on its back).
+    With wait=0, IOError is thrown if a device is not immediately available.
+    """
+
+    self._coarse_ref = self._fine_ref = self._coarse_zero = self._fine_zero = 0
+    self._coarse_scale = self._fine_scale = 0
+    self._last_seq = 0
+    self.start_voltage = 0
+
+    if device:
+      self.ser = serial.Serial(device, timeout=1)
+      return
+
+    while True:  # try all /dev/ttyACM* until we find one we can use
+      for dev in os.listdir("/dev"):
+        if not dev.startswith("ttyACM"): continue
+        tmpname = "/tmp/monsoon.%s.%s" % (os.uname()[0], dev)
+        self._tempfile = open(tmpname, "w")
+        try:
+          os.chmod(tmpname, 0666)
+        except OSError:
+          pass
+        try:  # use a lockfile to ensure exclusive access
+          fcntl.lockf(self._tempfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
+        except IOError as e:
+          print >>sys.stderr, "device %s is in use" % dev
+          continue
+
+        try:  # try to open the device
+          self.ser = serial.Serial("/dev/%s" % dev, timeout=1)
+          self.StopDataCollection()  # just in case
+          self._FlushInput()  # discard stale input
+          status = self.GetStatus()
+        except Exception as e:
+          print >>sys.stderr, "error opening device %s: %s" % (dev, e)
+          continue
+
+        if not status:
+          print >>sys.stderr, "no response from device %s" % dev
+        elif serialno and status["serialNumber"] != serialno:
+          print >>sys.stderr, ("Note: another device serial #%d seen on %s" %
+                               (status["serialNumber"], dev))
+        else:
+          self.start_voltage = status["voltage1"]
+          return
+
+      self._tempfile = None
+      if not wait: raise IOError("No device found")
+      print >>sys.stderr, "waiting for device..."
+      time.sleep(1)
+
+
+  def GetStatus(self):
+    """ Requests and waits for status.  Returns status dictionary. """
+
+    # status packet format
+    STATUS_FORMAT = ">BBBhhhHhhhHBBBxBbHBHHHHBbbHHBBBbbbbbbbbbBH"
+    STATUS_FIELDS = [
+        "packetType", "firmwareVersion", "protocolVersion",
+        "mainFineCurrent", "usbFineCurrent", "auxFineCurrent", "voltage1",
+        "mainCoarseCurrent", "usbCoarseCurrent", "auxCoarseCurrent", "voltage2",
+        "outputVoltageSetting", "temperature", "status", "leds",
+        "mainFineResistor", "serialNumber", "sampleRate",
+        "dacCalLow", "dacCalHigh",
+        "powerUpCurrentLimit", "runTimeCurrentLimit", "powerUpTime",
+        "usbFineResistor", "auxFineResistor",
+        "initialUsbVoltage", "initialAuxVoltage",
+        "hardwareRevision", "temperatureLimit", "usbPassthroughMode",
+        "mainCoarseResistor", "usbCoarseResistor", "auxCoarseResistor",
+        "defMainFineResistor", "defUsbFineResistor", "defAuxFineResistor",
+        "defMainCoarseResistor", "defUsbCoarseResistor", "defAuxCoarseResistor",
+        "eventCode", "eventData", ]
+
+    self._SendStruct("BBB", 0x01, 0x00, 0x00)
+    while True:  # Keep reading, discarding non-status packets
+      bytes = self._ReadPacket()
+      if not bytes: return None
+      if len(bytes) != struct.calcsize(STATUS_FORMAT) or bytes[0] != "\x10":
+        print >>sys.stderr, "wanted status, dropped type=0x%02x, len=%d" % (
+                ord(bytes[0]), len(bytes))
+        continue
+
+      status = dict(zip(STATUS_FIELDS, struct.unpack(STATUS_FORMAT, bytes)))
+      assert status["packetType"] == 0x10
+      for k in status.keys():
+        if k.endswith("VoltageSetting"):
+          status[k] = 2.0 + status[k] * 0.01
+        elif k.endswith("FineCurrent"):
+          pass # needs calibration data
+        elif k.endswith("CoarseCurrent"):
+          pass # needs calibration data
+        elif k.startswith("voltage") or k.endswith("Voltage"):
+          status[k] = status[k] * 0.000125
+        elif k.endswith("Resistor"):
+          status[k] = 0.05 + status[k] * 0.0001
+          if k.startswith("aux") or k.startswith("defAux"): status[k] += 0.05
+        elif k.endswith("CurrentLimit"):
+          status[k] = 8 * (1023 - status[k]) / 1023.0
+      return status
+
+  def RampVoltage(self, start, end):
+    v = start
+    if v < 3.0: v = 3.0       # protocol doesn't support lower than this
+    while (v < end):
+      self.SetVoltage(v)
+      v += .1
+      time.sleep(.1)
+    self.SetVoltage(end)
+
+  def SetVoltage(self, v):
+    """ Set the output voltage, 0 to disable. """
+    if v == 0:
+      self._SendStruct("BBB", 0x01, 0x01, 0x00)
+    else:
+      self._SendStruct("BBB", 0x01, 0x01, int((v - 2.0) * 100))
+
+
+  def SetMaxCurrent(self, i):
+    """Set the max output current."""
+    assert i >= 0 and i <= 8
+
+    val = 1023 - int((i/8)*1023)
+    self._SendStruct("BBB", 0x01, 0x0a, val & 0xff)
+    self._SendStruct("BBB", 0x01, 0x0b, val >> 8)
+
+  def SetUsbPassthrough(self, val):
+    """ Set the USB passthrough mode: 0 = off, 1 = on,  2 = auto. """
+    self._SendStruct("BBB", 0x01, 0x10, val)
+
+
+  def StartDataCollection(self):
+    """ Tell the device to start collecting and sending measurement data. """
+    self._SendStruct("BBB", 0x01, 0x1b, 0x01) # Mystery command
+    self._SendStruct("BBBBBBB", 0x02, 0xff, 0xff, 0xff, 0xff, 0x03, 0xe8)
+
+
+  def StopDataCollection(self):
+    """ Tell the device to stop collecting measurement data. """
+    self._SendStruct("BB", 0x03, 0x00) # stop
+
+
+  def CollectData(self):
+    """ Return some current samples.  Call StartDataCollection() first. """
+    while True:  # loop until we get data or a timeout
+      bytes = self._ReadPacket()
+      if not bytes: return None
+      if len(bytes) < 4 + 8 + 1 or bytes[0] < "\x20" or bytes[0] > "\x2F":
+        print >>sys.stderr, "wanted data, dropped type=0x%02x, len=%d" % (
+            ord(bytes[0]), len(bytes))
+        continue
+
+      seq, type, x, y = struct.unpack("BBBB", bytes[:4])
+      data = [struct.unpack(">hhhh", bytes[x:x+8])
+              for x in range(4, len(bytes) - 8, 8)]
+
+      if self._last_seq and seq & 0xF != (self._last_seq + 1) & 0xF:
+        print >>sys.stderr, "data sequence skipped, lost packet?"
+      self._last_seq = seq
+
+      if type == 0:
+        if not self._coarse_scale or not self._fine_scale:
+          print >>sys.stderr, "waiting for calibration, dropped data packet"
+          continue
+
+        out = []
+        for main, usb, aux, voltage in data:
+          if main & 1:
+            out.append(((main & ~1) - self._coarse_zero) * self._coarse_scale)
+          else:
+            out.append((main - self._fine_zero) * self._fine_scale)
+        return out
+
+      elif type == 1:
+        self._fine_zero = data[0][0]
+        self._coarse_zero = data[1][0]
+        # print >>sys.stderr, "zero calibration: fine 0x%04x, coarse 0x%04x" % (
+        #     self._fine_zero, self._coarse_zero)
+
+      elif type == 2:
+        self._fine_ref = data[0][0]
+        self._coarse_ref = data[1][0]
+        # print >>sys.stderr, "ref calibration: fine 0x%04x, coarse 0x%04x" % (
+        #     self._fine_ref, self._coarse_ref)
+
+      else:
+        print >>sys.stderr, "discarding data packet type=0x%02x" % type
+        continue
+
+      if self._coarse_ref != self._coarse_zero:
+        self._coarse_scale = 2.88 / (self._coarse_ref - self._coarse_zero)
+      if self._fine_ref != self._fine_zero:
+        self._fine_scale = 0.0332 / (self._fine_ref - self._fine_zero)
+
+
+  def _SendStruct(self, fmt, *args):
+    """ Pack a struct (without length or checksum) and send it. """
+    data = struct.pack(fmt, *args)
+    data_len = len(data) + 1
+    checksum = (data_len + sum(struct.unpack("B" * len(data), data))) % 256
+    out = struct.pack("B", data_len) + data + struct.pack("B", checksum)
+    self.ser.write(out)
+
+
+  def _ReadPacket(self):
+    """ Read a single data record as a string (without length or checksum). """
+    len_char = self.ser.read(1)
+    if not len_char:
+      print >>sys.stderr, "timeout reading from serial port"
+      return None
+
+    data_len = struct.unpack("B", len_char)
+    data_len = ord(len_char)
+    if not data_len: return ""
+
+    result = self.ser.read(data_len)
+    if len(result) != data_len: return None
+    body = result[:-1]
+    checksum = (data_len + sum(struct.unpack("B" * len(body), body))) % 256
+    if result[-1] != struct.pack("B", checksum):
+      print >>sys.stderr, "invalid checksum from serial port"
+      return None
+    return result[:-1]
+
+  def _FlushInput(self):
+    """ Flush all read data until no more available. """
+    self.ser.flush()
+    flushed = 0
+    while True:
+      ready_r, ready_w, ready_x = select.select([self.ser], [], [self.ser], 0)
+      if len(ready_x) > 0:
+        print >>sys.stderr, "exception from serial port"
+        return None
+      elif len(ready_r) > 0:
+        flushed += 1
+        self.ser.read(1)  # This may cause underlying buffering.
+        self.ser.flush()  # Flush the underlying buffer too.
+      else:
+        break
+    if flushed > 0:
+      print >>sys.stderr, "dropped >%d bytes" % flushed
+
+def main(argv):
+  """ Simple command-line interface for Monsoon."""
+  useful_flags = ["voltage", "status", "usbpassthrough", "samples", "current"]
+  if not [f for f in useful_flags if FLAGS.get(f, None) is not None]:
+    print __doc__.strip()
+    print FLAGS.MainModuleHelp()
+    return
+
+  if FLAGS.avg and FLAGS.avg < 0:
+    print "--avg must be greater than 0"
+    return
+
+  mon = Monsoon(device=FLAGS.device, serialno=FLAGS.serialno)
+
+  if FLAGS.voltage is not None:
+    if FLAGS.ramp is not None:
+      mon.RampVoltage(mon.start_voltage, FLAGS.voltage)
+    else:
+      mon.SetVoltage(FLAGS.voltage)
+
+  if FLAGS.current is not None:
+    mon.SetMaxCurrent(FLAGS.current)
+
+  if FLAGS.status:
+    items = sorted(mon.GetStatus().items())
+    print "\n".join(["%s: %s" % item for item in items])
+
+  if FLAGS.usbpassthrough:
+    if FLAGS.usbpassthrough == 'off':
+      mon.SetUsbPassthrough(0)
+    elif FLAGS.usbpassthrough == 'on':
+      mon.SetUsbPassthrough(1)
+    elif FLAGS.usbpassthrough == 'auto':
+      mon.SetUsbPassthrough(2)
+    else:
+      sys.exit('bad passthrough flag: %s' % FLAGS.usbpassthrough)
+
+  if FLAGS.samples:
+    # Make sure state is normal
+    mon.StopDataCollection()
+    status = mon.GetStatus()
+    native_hz = status["sampleRate"] * 1000
+
+    # Collect and average samples as specified
+    mon.StartDataCollection()
+
+    # In case FLAGS.hz doesn't divide native_hz exactly, use this invariant:
+    # 'offset' = (consumed samples) * FLAGS.hz - (emitted samples) * native_hz
+    # This is the error accumulator in a variation of Bresenham's algorithm.
+    emitted = offset = 0
+    collected = []
+    history_deque = collections.deque() # past n samples for rolling average
+
+    try:
+      last_flush = time.time()
+      while emitted < FLAGS.samples or FLAGS.samples == -1:
+        # The number of raw samples to consume before emitting the next output
+        need = (native_hz - offset + FLAGS.hz - 1) / FLAGS.hz
+        if need > len(collected):     # still need more input samples
+          samples = mon.CollectData()
+          if not samples: break
+          collected.extend(samples)
+        else:
+          # Have enough data, generate output samples.
+          # Adjust for consuming 'need' input samples.
+          offset += need * FLAGS.hz
+          while offset >= native_hz:  # maybe multiple, if FLAGS.hz > native_hz
+            this_sample = sum(collected[:need]) / need
+
+            if FLAGS.timestamp: print int(time.time()),
+
+            if FLAGS.avg:
+              history_deque.appendleft(this_sample)
+              if len(history_deque) > FLAGS.avg: history_deque.pop()
+              print "%f %f" % (this_sample,
+                               sum(history_deque) / len(history_deque))
+            else:
+              print "%f" % this_sample
+            sys.stdout.flush()
+
+            offset -= native_hz
+            emitted += 1              # adjust for emitting 1 output sample
+          collected = collected[need:]
+          now = time.time()
+          if now - last_flush >= 0.99:  # flush every second
+            sys.stdout.flush()
+            last_flush = now
+    except KeyboardInterrupt:
+      print >>sys.stderr, "interrupted"
+
+    mon.StopDataCollection()
+
+
+if __name__ == '__main__':
+  # Define flags here to avoid conflicts with people who use us as a library
+  flags.DEFINE_boolean("status", None, "Print power meter status")
+  flags.DEFINE_integer("avg", None,
+                       "Also report average over last n data points")
+  flags.DEFINE_float("voltage", None, "Set output voltage (0 for off)")
+  flags.DEFINE_float("current", None, "Set max output current")
+  flags.DEFINE_string("usbpassthrough", None, "USB control (on, off, auto)")
+  flags.DEFINE_integer("samples", None, "Collect and print this many samples")
+  flags.DEFINE_integer("hz", 5000, "Print this many samples/sec")
+  flags.DEFINE_string("device", None,
+                      "Path to the device in /dev/... (ex:/dev/ttyACM1)")
+  flags.DEFINE_integer("serialno", None, "Look for a device with this serial number")
+  flags.DEFINE_boolean("timestamp", None,
+                       "Also print integer (seconds) timestamp on each line")
+  flags.DEFINE_boolean("ramp", True, "Gradually increase voltage")
+
+  main(FLAGS(sys.argv))
diff --git a/tools/vm-tests-tf/etc/starttests b/tools/vm-tests-tf/etc/starttests
new file mode 100755
index 0000000..be8fad4
--- /dev/null
+++ b/tools/vm-tests-tf/etc/starttests
@@ -0,0 +1,296 @@
+#!/bin/bash
+#
+# Copyright (C) 2008 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.
+
+# Set up prog to be the path of this script, including following symlinks,
+# and set up progdir to be the fully-qualified pathname of its directory.
+
+prog="$0"
+while [ -h "${prog}" ]; do
+    newProg=`/bin/ls -ld "${prog}"`
+    newProg=`expr "${newProg}" : ".* -> \(.*\)$"`
+    if expr "x${newProg}" : 'x/' >/dev/null; then
+        prog="${newProg}"
+    else
+        progdir=`dirname "${prog}"`
+        prog="${progdir}/${newProg}"
+    fi
+done
+oldwd=`pwd`
+progdir=`dirname "${prog}"`
+cd "${progdir}"
+progdir=`pwd`
+prog="${progdir}"/`basename "${prog}"`
+cd "${oldwd}"
+
+libdir=`dirname $progdir`/framework
+
+javaOpts=""
+while expr "x$1" : 'x-J' >/dev/null; do
+    opt=`expr "$1" : '-J\(.*\)'`
+    javaOpts="${javaOpts} -${opt}"
+    shift
+done
+
+
+#######################################################################
+# Original content of invocation script follows. Uses values cleverly
+# deduced by the above code.
+#######################################################################
+
+selection=$1
+interpreter="fast"
+if [ "$selection" = "--portable" ]; then
+    selection=$2;
+    interpreter="portable"
+fi
+
+dalviktest=$ANDROID_BUILD_TOP/out/host/common/obj/JAVA_LIBRARIES/vm-tests-tf_intermediates
+dalviktestdir=$dalviktest/tests
+dexcore=$dalviktest/tests/dot/junit/dexcore.jar
+scriptdata=$dalviktestdir/data/scriptdata
+report=$dalviktest/report.html
+curdate=`date`
+curmode=""
+datadir=/tmp/${USER}
+base=$OUT
+framework=$base/system/framework
+export ANDROID_PRINTF_LOG=tag
+export ANDROID_LOG_TAGS='*:s' # was: jdwp:i dalvikvm:i dalvikvmi:i'
+export ANDROID_DATA=$datadir
+export ANDROID_ROOT=$base/system
+export LD_LIBRARY_PATH=$base/system/lib
+export DYLD_LIBRARY_PATH=$base/system/lib
+debug_opts="-Xcheck:jni -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n"
+exe=$base/system/bin/dalvikvm
+bpath=$framework/core.jar
+
+echo "--------------------------------------------------"
+echo "Dalvik VM Test Suite"
+echo "Version 1.0"
+echo "Copyright (c) 2008 The Android Open Source Project"
+echo ""
+
+if [ "$selection" = "--help" ]; then
+    echo "Usage: vm-tests [--help|--portable] [<mnemonic>]"
+    echo ""
+    echo "    --help      prints this help message"
+    echo "    --portable  uses the portable interpreter;"
+    echo "                default is the fast one"
+    echo ""
+    echo "    <mnemonic>  specifies the instruction to test;"
+    echo "                default is to run all tests"
+    echo ""
+    exit 1;
+fi
+
+rm -rf --preserve-root $datadir/dalvik-cache
+mkdir -p $datadir
+mkdir -p $datadir/dalvik-cache
+
+if [ "$TARGET_SIMULATOR" = "true" ]; then
+    echo "Simulator mode, $interpreter interpreter";
+    curmode="simulator"
+else
+    echo "Emulator mode, $interpreter interpreter";
+    curmode="emulator"
+fi
+
+echo ""
+
+pre_report="<html><head><style>
+table tr.ok { background:#a0ffa0; }
+table tr.nok { background:#ffa0a0; }
+table tr.wok { background:#ffffa0; }
+table tr.lok { background:#aaaaff; }
+</style></head>
+<body>
+<h1>Dalvik VM test suite results</h1>
+Generated $curdate (using the $curmode)
+<p>
+<table width='100%'>
+<tr><td>Status</td><td>Target</td><td>Category</td><td>Details</td></tr>"
+post_report="</body></html>"
+
+rm -f $report
+echo $pre_report > $report
+
+# ----------- running each opcode test ------------
+
+export jpassedcnt=0
+export jfailedcnt=0
+export jvfefailedcnt=0
+export jwarningcnt=0
+export jallcnt=0
+export jcolumns=0
+
+# TODO unhack
+if [ "$TARGET_SIMULATOR" = "true" ]; then
+    echo -n ""
+else
+    adb push $dexcore /data/local/tmp/dexcore.jar >> /dev/null 2>&1
+fi
+
+function classnameToJar()
+{
+    echo $1 | sed -e 's#\.#/#g;s#$#.jar#'
+}
+
+while read -u 3 myline;
+do
+    # dot.junit.opcodes.add_double.Main_testB1;dot.junit.opcodes.add_double.d.T_add_double_1 ;opcode add_double;test B #1 (border edge case)
+    # ->
+    # mainclass: dot.junit.opcodes.add_double.Main_testB1
+    # testcasedir: opcodes/add_double
+    # testname: testB1 ->
+    # dir dot/junit/opcodes/add_double/testB1
+
+    # e.g dot.junit.opcodes.add_double.Main_testB1
+    mainclass=`echo $myline | cut -d";" -f1`
+    # e.g dot.junit.opcodes.add_double.d.T_add_double_1, space sep. >=1 entries
+    deps=`echo $myline | cut -d";" -f2`
+
+    jtitle=`echo $myline | cut -d";" -f3`
+    jcomment=`echo $myline | cut -d";" -f4`
+    details=`echo $myline | cut -d";" -f5`
+
+    if [ "$selection" == "" ] || [ "$jtitle" == "$selection" ]; then
+
+        (( jallcnt += 1 ))
+
+        cd $dalviktestdir
+        rm -f $datadir/dalvikout
+        # write dalvik output to file
+        echo -n "mk_b:" > $datadir/dalvikout
+
+        if [ "$TARGET_SIMULATOR" = "true" ]; then
+            classpath=`classnameToJar ${mainclass}`
+            for dep in ${deps}; do
+                depJar=`classnameToJar ${dep}`
+                classpath=${classpath}:${depJar}
+            done
+            $valgrind $exe -Xmx512M -Xss32K -Xbootclasspath:$bpath $debug_opts \
+                -classpath $dexcore:$classpath $mainclass >> $datadir/dalvikout 2>&1
+
+            RESULTCODE=$?
+            if [ ${RESULTCODE} -ne 0 ]; then
+                echo "Dalvik VM failed, result=${RESULTCODE}" >> $datadir/dalvikout 2>&1
+            fi
+        else
+            classpath="/data/local/tmp/dexcore.jar"
+            deps=${deps}" "${mainclass}
+            pushedjars=""
+            for dep in ${deps}; do
+                depJar=`classnameToJar ${dep}`
+                depFileName=`basename ${depJar}`
+                deviceFileName=/data/local/tmp/${depFileName}
+                adb push ${depJar} ${deviceFileName} &> /dev/null
+                classpath=${classpath}:${deviceFileName}
+                pushedjars=${pushedjars}" "${deviceFileName}
+            done
+
+            adb shell dalvikvm -Djava.io.tmpdir=/data/local/tmp \
+                -classpath $classpath $mainclass >> $datadir/dalvikout 2>&1 && \
+                echo -n dvmpassed: >> $datadir/dalvikout 2>&1
+
+            for jar in ${pushedjars}; do
+                adb shell rm ${jar} &> /dev/null
+            done
+        fi
+
+        echo -n "mk_s:" >> $datadir/dalvikout
+        # Verify tmpout only contains mkdxc_start;mkdxc_stop -> no system.out/err
+        # because of exception. If ok -> green report line else red report with info
+        # between mkdxc_start and stop
+        vmresult=`cat $datadir/dalvikout`
+
+        if [[ ("$vmresult" == "mk_b:mk_s:") || ("$vmresult" == "mk_b:dvmpassed:mk_s:") ]]; then
+            (( jpassedcnt += 1 ))
+            echo -n "<tr class=\"ok\"><td>Success</td><td>$jtitle</td>" >> $report
+            echo "<td>$jcomment</td><td>$details</td></tr>" >> $report
+            echo -n "."
+        else
+            vmres=`cat $datadir/dalvikout | sed -e 's/mk_b://;s/mk_s://'`
+            vmres="$details<br><pre>$vmres</pre>"
+
+            stacktraces=`echo $vmresult | grep "java\.lang\." | grep -c "at dot\.junit\."`
+            if [[ $stacktraces > 0 ]]; then
+                jtype=`echo "$mainclass" | sed -e 's/.*_test\([^0-9]*\)[0-9].*/\1/' `
+                if [ "$jtype" == "VFE" ]; then
+                    (( jvfefailedcnt += 1 ))
+                    echo -n "V"
+                else
+                    (( jfailedcnt += 1 ))
+                    echo -n "F"
+                fi
+
+                echo "<tr class=\"nok\"><td>Failure</td><td>$jtitle</td><td>" >> $report
+                echo "$jcomment</td><td>$vmres</td></tr>" >> $report
+            else
+                (( jwarningcnt += 1 ))
+                echo "<tr class=\"wok\"><td>Failure</td><td>$jtitle</td><td>" >> $report
+                echo "$jcomment</td><td>(No stacktrace, but errors on console)" >> $report
+                echo "<br>$vmres</td></tr>" >> $report
+                echo -n "C"
+            fi
+        fi
+
+        (( jcolumns += 1 ))
+        if [ ${jcolumns} -eq 40 ]; then
+            echo ""
+            (( jcolumns = 0 ))
+        fi
+
+    fi
+# Use fd nr 3 to avoid subshelling via cat since this looses all
+# variables(and thus also the counters we are interested in).
+done 3<$scriptdata
+
+echo "</table>" >> $report
+let jallcalccnt=$jpassedcnt+$jfailedcnt+$jvfefailedcnt+$jwarningcnt
+if [ $jallcalccnt -ne $jallcnt ]; then
+    echo "<br>error: green & red != total , $jallcalccnt -ne $jallcnt" >> $report
+    exit 1;
+fi
+
+echo $post_report >> $report
+
+echo "<br>Tests run: ${jallcnt}" >> $report
+echo "<br>Functional failures: ${jfailedcnt}" >> $report
+echo "<br>Verifier failures: ${jvfefailedcnt}" >> $report
+echo "<br>Console errors: ${jwarningcnt}" >> $report
+
+echo $post_report >> $report
+
+if [[ jcolumns -ne 0 ]]; then
+    echo ""
+fi
+
+echo ""
+
+if [[ jallcnt -eq jpassedcnt ]]; then
+    echo "OK (${jpassedcnt} tests)"
+else
+    echo "FAILURES!!!"
+    echo ""
+    echo "Tests run          : ${jallcnt}"
+    echo "Functional failures: ${jfailedcnt}"
+    echo "Verifier failures  : ${jvfefailedcnt}"
+    echo "Console errors     : ${jwarningcnt}"
+fi
+
+echo ""
+echo "Please see complete report in ${report}"
+echo "--------------------------------------------------"
diff --git a/tools/vm-tests-tf/src/dot/junit/DxAbstractMain.java b/tools/vm-tests-tf/src/dot/junit/DxAbstractMain.java
index d40fb94..dac6dcf 100644
--- a/tools/vm-tests-tf/src/dot/junit/DxAbstractMain.java
+++ b/tools/vm-tests-tf/src/dot/junit/DxAbstractMain.java
@@ -17,15 +17,104 @@
 package dot.junit;
 
 public class DxAbstractMain {
-    
+
+    /* NOTE: Because of how tests are generated, this is replicated between
+     *       this class and DxTestCase.
+     */
+
+    private static void checkError(Class<?> expectedErrorClass, Throwable thrown,
+                                   boolean in_invocation_exc) {
+        if (expectedErrorClass != null && thrown == null) {
+            fail("Expected error of type " + expectedErrorClass);
+        } else if (expectedErrorClass == null && thrown != null) {
+            fail("Unexpected error " + thrown);
+        } else if (expectedErrorClass != null && thrown != null) {
+            if (in_invocation_exc) {
+                if (!(thrown instanceof java.lang.reflect.InvocationTargetException)) {
+                    fail("Expected invocation target exception, but got " + thrown);
+                }
+                thrown = thrown.getCause();
+            }
+            if (!expectedErrorClass.equals(thrown.getClass())) {
+                thrown.printStackTrace(System.err);
+                fail("Expected error of type " + expectedErrorClass + ", but got " +
+                     thrown.getClass());
+            }
+        }
+    }
+
+    /**
+     * Try to load the class with the given name, and check for the expected error.
+     */
+    public static Class<?> load(String className, Class<?> expectedErrorClass) {
+        try {
+            Class<?> c = Class.forName(className);
+            checkError(expectedErrorClass, null, false);
+            return c;
+        } catch (Throwable t) {
+            if (expectedErrorClass != null) {
+                checkError(expectedErrorClass, t, false);
+            } else {
+                t.printStackTrace(System.err);
+                fail("Could not load class " + className + ": " + t);
+            }
+            return null;
+        }
+    }
+
+    /**
+     * Try to load the class with the given name, find the "run" method and run it.
+     * If expectedErrorClass is not null, check for an exception of that class.
+     */
+    public static void loadAndRun(String className, boolean isStatic, boolean wrapped,
+                                  Class<?> expectedErrorClass, Object... args) {
+        Class<?> c = load(className, null);
+
+        java.lang.reflect.Method method = null;
+        // We expect only ever one declared method named run, but don't know the arguments. So
+        // search for one.
+        for (java.lang.reflect.Method m : c.getDeclaredMethods()) {
+            if (m.getName().equals("run")) {
+                method = m;
+                break;
+            }
+        }
+        if (method == null) {
+            fail("Could not find method 'run'");
+        }
+
+        Object receiver = null;
+        if (!isStatic) {
+            try {
+                receiver = c.newInstance();
+            } catch (Exception exc) {
+                fail("Could not instantiate " + className + ": " + exc.getMessage());
+            }
+        }
+
+        try {
+            method.invoke(receiver, args);
+            checkError(expectedErrorClass, null, false);
+        } catch (Throwable t) {
+            checkError(expectedErrorClass, t, wrapped);
+        }
+    }
+
+    public static void loadAndRun(String className, Class<?> expectedErrorClass) {
+        loadAndRun(className, false, true, expectedErrorClass);
+    }
+
+    public static void loadAndRun(String className, Class<?> expectedErrorClass, Object... args) {
+        loadAndRun(className, false, true, expectedErrorClass, args);
+    }
+
     static public void assertEquals(int expected, int actual) {
         if (expected != actual) throw new RuntimeException("AssertionFailedError: not equals. Expected " + expected + " actual " + actual);
     }
-    
+
     static public void assertEquals(String message, int expected, int actual) {
         if (expected != actual) throw new RuntimeException("AssertionFailedError: not equals: " + message + " Expected " + expected + " actual " + actual);
     }
-    
 
     static public void assertEquals(long expected, long actual) {
         if (expected != actual) throw new RuntimeException("AssertionFailedError: not equals. Expected " + expected + " actual " + actual);
@@ -34,7 +123,7 @@
     static public void assertEquals(double expected, double actual, double delta) {
         if(!(Math.abs(expected-actual) <= delta)) throw new RuntimeException("AssertionFailedError: not within delta");
     }
-    
+
     static public void assertEquals(Object expected, Object actual) {
         if (expected == null && actual == null)
             return;
@@ -42,26 +131,24 @@
             return;
         throw new RuntimeException("AssertionFailedError: not the same");
     }
-    
+
     static public void assertTrue(boolean condition) {
         if (!condition) throw new RuntimeException("AssertionFailedError: condition was false");
     }
-    
+
     static public void assertFalse(boolean condition) {
         if (condition) throw new RuntimeException("AssertionFailedError: condition was true");
     }
-    
+
     static public void assertNotNull(Object object) {
         if (object == null) throw new RuntimeException("AssertionFailedError: object was null");
     }
-    
+
     static public void assertNull(Object object) {
         if (object != null) throw new RuntimeException("AssertionFailedError: object was not null");
     }
-    
+
     static public void fail(String message) {
         throw new RuntimeException("AssertionFailedError msg:"+message);
     }
-    
-    
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/DxTestCase.java b/tools/vm-tests-tf/src/dot/junit/DxTestCase.java
index 00eb6fe..20142e0 100644
--- a/tools/vm-tests-tf/src/dot/junit/DxTestCase.java
+++ b/tools/vm-tests-tf/src/dot/junit/DxTestCase.java
@@ -19,7 +19,91 @@
 import junit.framework.TestCase;
 
 public class DxTestCase extends TestCase {
-    
+
+    private static void checkError(Class<?> expectedErrorClass, Throwable thrown,
+                                   boolean in_invocation_exc) {
+        if (expectedErrorClass != null && thrown == null) {
+            fail("Expected error of type " + expectedErrorClass);
+        } else if (expectedErrorClass == null && thrown != null) {
+            fail("Unexpected error " + thrown);
+        } else if (expectedErrorClass != null && thrown != null) {
+            if (in_invocation_exc) {
+                if (!(thrown instanceof java.lang.reflect.InvocationTargetException)) {
+                    fail("Expected invocation target exception, but got " + thrown);
+                }
+                thrown = thrown.getCause();
+            }
+            if (!expectedErrorClass.equals(thrown.getClass())) {
+                fail("Expected error of type " + expectedErrorClass + ", but got " +
+                     thrown.getClass());
+            }
+        }
+    }
+
+    /**
+     * Try to load the class with the given name, and check for the expected error.
+     */
+    public static Class<?> load(String className, Class<?> expectedErrorClass) {
+        try {
+            Class<?> c = Class.forName(className);
+            checkError(expectedErrorClass, null, false);
+            return c;
+        } catch (Throwable t) {
+            if (expectedErrorClass != null) {
+                checkError(expectedErrorClass, t, false);
+            } else {
+                fail("Could not load class " + className + ": " + t);
+            }
+            return null;
+        }
+    }
+
+    /**
+     * Try to load the class with the given name, find the "run" method and run it.
+     * If expectedErrorClass is not null, check for an exception of that class.
+     */
+    public static void loadAndRun(String className, boolean isStatic, boolean wrapped,
+                                  Class<?> expectedErrorClass, Object... args) {
+        Class<?> c = load(className, null);
+
+        java.lang.reflect.Method method = null;
+        // We expect only ever one declared method named run, but don't know the arguments. So
+        // search for one.
+        for (java.lang.reflect.Method m : c.getDeclaredMethods()) {
+            if (m.getName().equals("run")) {
+                method = m;
+                break;
+            }
+        }
+        if (method == null) {
+            fail("Could not find method 'run'");
+        }
+
+        Object receiver = null;
+        if (!isStatic) {
+            try {
+                receiver = c.newInstance();
+            } catch (Exception exc) {
+                fail("Could not instantiate " + className + ": " + exc.getMessage());
+            }
+        }
+
+        try {
+            method.invoke(receiver, args);
+            checkError(expectedErrorClass, null, false);
+        } catch (Throwable t) {
+            checkError(expectedErrorClass, t, wrapped);
+        }
+    }
+
+    public static void loadAndRun(String className, Class<?> expectedErrorClass) {
+        loadAndRun(className, false, true, expectedErrorClass);
+    }
+
+    public static void loadAndRun(String className, Class<?> expectedErrorClass, Object... args) {
+        loadAndRun(className, false, true, expectedErrorClass, args);
+    }
+
     // omit the "extends TestCase" and uncomment the following methods if you would like to run the tests as rolled-out, separate tests.
     
 /*    
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/add_double/Test_add_double.java b/tools/vm-tests-tf/src/dot/junit/opcodes/add_double/Test_add_double.java
index cbae239..d18db90 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/add_double/Test_add_double.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/add_double/Test_add_double.java
@@ -132,12 +132,7 @@
      * @title  types of arguments - float, double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.add_double.d.T_add_double_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_double.d.T_add_double_2", VerifyError.class);
     }
 
 
@@ -146,12 +141,7 @@
      * @title  types of arguments - double, reference
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.add_double.d.T_add_double_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_double.d.T_add_double_4", VerifyError.class);
     }
     
     /**
@@ -159,12 +149,7 @@
      * @title  number of registers
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.add_double.d.T_add_double_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_double.d.T_add_double_5", VerifyError.class);
     }
     
     /**
@@ -172,12 +157,7 @@
      * @title  types of arguments - int, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.add_double.d.T_add_double_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_double.d.T_add_double_6", VerifyError.class);
     }
 
     /**
@@ -186,11 +166,6 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.add_double.d.T_add_double_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_double.d.T_add_double_3", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/add_double_2addr/Test_add_double_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/add_double_2addr/Test_add_double_2addr.java
index cdcee13..6880719 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/add_double_2addr/Test_add_double_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/add_double_2addr/Test_add_double_2addr.java
@@ -129,12 +129,7 @@
      * @title types of arguments - float, double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.add_double_2addr.d.T_add_double_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_double_2addr.d.T_add_double_2addr_2", VerifyError.class);
     }
 
     /**
@@ -142,12 +137,7 @@
      * @title types of arguments - double, reference
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.add_double_2addr.d.T_add_double_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_double_2addr.d.T_add_double_2addr_4", VerifyError.class);
     }
     
     /**
@@ -155,12 +145,7 @@
      * @title number of registers
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.add_double_2addr.d.T_add_double_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_double_2addr.d.T_add_double_2addr_6", VerifyError.class);
     }
     
     /**
@@ -168,12 +153,7 @@
      * @title  types of arguments - double, reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.add_double_2addr.d.T_add_double_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_double_2addr.d.T_add_double_2addr_4", VerifyError.class);
     }
 
     /**
@@ -182,11 +162,6 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.add_double_2addr.d.T_add_double_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_double_2addr.d.T_add_double_2addr_3", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/add_float/Test_add_float.java b/tools/vm-tests-tf/src/dot/junit/opcodes/add_float/Test_add_float.java
index 56288c2..74f1dfa 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/add_float/Test_add_float.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/add_float/Test_add_float.java
@@ -131,12 +131,7 @@
      * @title  types of arguments - float, double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.add_float.d.T_add_float_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_float.d.T_add_float_2", VerifyError.class);
     }
 
     /**
@@ -144,12 +139,7 @@
      * @title  types of arguments - long, float
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.add_float.d.T_add_float_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_float.d.T_add_float_3", VerifyError.class);
     }
 
     /**
@@ -157,12 +147,7 @@
      * @title  types of arguments - float, reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.add_float.d.T_add_float_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_float.d.T_add_float_4", VerifyError.class);
     }
     
     /**
@@ -170,12 +155,7 @@
      * @title  number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.add_float.d.T_add_float_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_float.d.T_add_float_6", VerifyError.class);
     }
 
     /**
@@ -184,12 +164,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.add_float.d.T_add_float_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_float.d.T_add_float_5", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/add_float_2addr/Test_add_float_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/add_float_2addr/Test_add_float_2addr.java
index a9b5aca..9d8a8ad 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/add_float_2addr/Test_add_float_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/add_float_2addr/Test_add_float_2addr.java
@@ -131,12 +131,7 @@
      * @title types of arguments - float, double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.add_float_2addr.d.T_add_float_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_float_2addr.d.T_add_float_2addr_2", VerifyError.class);
     }
 
     /**
@@ -144,12 +139,7 @@
      * @title types of arguments - long, float
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.add_float_2addr.d.T_add_float_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_float_2addr.d.T_add_float_2addr_3", VerifyError.class);
     }
 
     /**
@@ -157,12 +147,7 @@
      * @title types of arguments - float, reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.add_float_2addr.d.T_add_float_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_float_2addr.d.T_add_float_2addr_4", VerifyError.class);
     }
     
     /**
@@ -170,12 +155,7 @@
      * @title number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.add_float_2addr.d.T_add_float_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_float_2addr.d.T_add_float_2addr_6", VerifyError.class);
     }
 
     /**
@@ -184,12 +164,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.add_float_2addr.d.T_add_float_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_float_2addr.d.T_add_float_2addr_5", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/add_int/Test_add_int.java b/tools/vm-tests-tf/src/dot/junit/opcodes/add_int/Test_add_int.java
index a6d619b..3f66616 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/add_int/Test_add_int.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/add_int/Test_add_int.java
@@ -127,12 +127,7 @@
      * @title types of arguments - int, double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.add_int.d.T_add_int_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_int.d.T_add_int_2", VerifyError.class);
     }
 
     /**
@@ -140,12 +135,7 @@
      * @title types of arguments - long, int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.add_int.d.T_add_int_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_int.d.T_add_int_3", VerifyError.class);
     }
 
     /**
@@ -153,12 +143,7 @@
      * @title  types of arguments - reference, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.add_int.d.T_add_int_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_int.d.T_add_int_4", VerifyError.class);
     }
     
     /**
@@ -166,12 +151,7 @@
      * @title  number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.add_int.d.T_add_int_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_int.d.T_add_int_6", VerifyError.class);
     }
 
     /**
@@ -180,11 +160,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.add_int.d.T_add_int_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_int.d.T_add_int_5", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/add_int_2addr/Test_add_int_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/add_int_2addr/Test_add_int_2addr.java
index 3253c9c..40ff8b9 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/add_int_2addr/Test_add_int_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/add_int_2addr/Test_add_int_2addr.java
@@ -126,12 +126,7 @@
      * @title types of arguments - int, double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.add_int_2addr.d.T_add_int_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_int_2addr.d.T_add_int_2addr_2", VerifyError.class);
     }
 
     /**
@@ -139,12 +134,7 @@
      * @title types of arguments - long, int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.add_int_2addr.d.T_add_int_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_int_2addr.d.T_add_int_2addr_3", VerifyError.class);
     }
 
     /**
@@ -152,12 +142,7 @@
      * @title types of arguments - reference, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.add_int_2addr.d.T_add_int_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_int_2addr.d.T_add_int_2addr_4", VerifyError.class);
     }
     
     /**
@@ -165,12 +150,7 @@
      * @title number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.add_int_2addr.d.T_add_int_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_int_2addr.d.T_add_int_2addr_6", VerifyError.class);
     }
 
     /**
@@ -179,11 +159,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.add_int_2addr.d.T_add_int_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_int_2addr.d.T_add_int_2addr_5", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/add_int_lit16/Test_add_int_lit16.java b/tools/vm-tests-tf/src/dot/junit/opcodes/add_int_lit16/Test_add_int_lit16.java
index b94058a..77e5660 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/add_int_lit16/Test_add_int_lit16.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/add_int_lit16/Test_add_int_lit16.java
@@ -137,12 +137,7 @@
      * @title types of arguments - int, double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.add_int_lit16.d.T_add_int_lit16_13");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_int_lit16.d.T_add_int_lit16_13", VerifyError.class);
     }
 
     /**
@@ -150,12 +145,7 @@
      * @title types of arguments - long, int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.add_int_lit16.d.T_add_int_lit16_14");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_int_lit16.d.T_add_int_lit16_14", VerifyError.class);
     }
 
     /**
@@ -163,12 +153,7 @@
      * @title types of arguments - reference, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.add_int_lit16.d.T_add_int_lit16_15");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_int_lit16.d.T_add_int_lit16_15", VerifyError.class);
     }
     
     /**
@@ -176,12 +161,7 @@
      * @title  number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.add_int_lit16.d.T_add_int_lit16_17");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_int_lit16.d.T_add_int_lit16_17", VerifyError.class);
     }
 
     /**
@@ -190,11 +170,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.add_int_lit16.d.T_add_int_lit16_16");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_int_lit16.d.T_add_int_lit16_16", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/add_int_lit8/Test_add_int_lit8.java b/tools/vm-tests-tf/src/dot/junit/opcodes/add_int_lit8/Test_add_int_lit8.java
index b1fab12..6924a13 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/add_int_lit8/Test_add_int_lit8.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/add_int_lit8/Test_add_int_lit8.java
@@ -137,12 +137,7 @@
      * @title types of arguments - int, double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.add_int_lit8.d.T_add_int_lit8_13");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_int_lit8.d.T_add_int_lit8_13", VerifyError.class);
     }
 
     /**
@@ -150,12 +145,7 @@
      * @title types of arguments - long, int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.add_int_lit8.d.T_add_int_lit8_14");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_int_lit8.d.T_add_int_lit8_14", VerifyError.class);
     }
 
     /**
@@ -163,12 +153,7 @@
      * @title types of arguments - reference, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.add_int_lit8.d.T_add_int_lit8_15");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_int_lit8.d.T_add_int_lit8_15", VerifyError.class);
     }
     
     /**
@@ -176,12 +161,7 @@
      * @title number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.add_int_lit8.d.T_add_int_lit8_17");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_int_lit8.d.T_add_int_lit8_17", VerifyError.class);
     }
 
     /**
@@ -190,11 +170,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.add_int_lit8.d.T_add_int_lit8_16");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_int_lit8.d.T_add_int_lit8_16", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/add_long/Test_add_long.java b/tools/vm-tests-tf/src/dot/junit/opcodes/add_long/Test_add_long.java
index 1d403b2..5f6e4f7 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/add_long/Test_add_long.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/add_long/Test_add_long.java
@@ -118,12 +118,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.add_long.d.T_add_long_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_long.d.T_add_long_2", VerifyError.class);
     }
 
     /**
@@ -131,12 +126,7 @@
      * @title types of arguments - long / integer
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.add_long.d.T_add_long_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_long.d.T_add_long_3", VerifyError.class);
     }
 
     /**
@@ -144,12 +134,7 @@
      * @title types of arguments - long / float
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.add_long.d.T_add_long_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_long.d.T_add_long_4", VerifyError.class);
     }
 
     /**
@@ -157,12 +142,7 @@
      * @title types of arguments - reference / long
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.add_long.d.T_add_long_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_long.d.T_add_long_5", VerifyError.class);
     }
 
     /**
@@ -171,11 +151,6 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.add_long.d.T_add_long_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_long.d.T_add_long_6", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/add_long_2addr/Test_add_long_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/add_long_2addr/Test_add_long_2addr.java
index f801cf8..0fcbd17 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/add_long_2addr/Test_add_long_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/add_long_2addr/Test_add_long_2addr.java
@@ -118,12 +118,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.add_long_2addr.d.T_add_long_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_long_2addr.d.T_add_long_2addr_2", VerifyError.class);
     }
 
     /**
@@ -131,12 +126,7 @@
      * @title types of arguments - long / integer
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.add_long_2addr.d.T_add_long_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_long_2addr.d.T_add_long_2addr_3", VerifyError.class);
     }
 
     /**
@@ -144,12 +134,7 @@
      * @title types of arguments - long / float
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.add_long_2addr.d.T_add_long_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_long_2addr.d.T_add_long_2addr_4", VerifyError.class);
     }
 
     /**
@@ -157,12 +142,7 @@
      * @title  types of arguments - reference / long
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.add_long_2addr.d.T_add_long_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.add_long_2addr.d.T_add_long_2addr_5", VerifyError.class);
     }
 
    /**
@@ -171,11 +151,6 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE6() {
-       try {
-            Class.forName("dot.junit.opcodes.add_long_2addr.d.T_add_long_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-       }
+       load("dot.junit.opcodes.add_long_2addr.d.T_add_long_2addr_6", VerifyError.class);
    }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/aget/Test_aget.java b/tools/vm-tests-tf/src/dot/junit/opcodes/aget/Test_aget.java
index da94745..3ac061d 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/aget/Test_aget.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/aget/Test_aget.java
@@ -46,56 +46,31 @@
      * @title expected ArrayIndexOutOfBoundsException
      */
     public void testE1() {
-        T_aget_1 t = new T_aget_1();
-        int[] arr = new int[2];
-        try {
-            t.run(arr, 2);
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aget.d.T_aget_1", ArrayIndexOutOfBoundsException.class,
+                   new int[2], 2);
     }
 
     /**
      * @title expected NullPointerException
      */
     public void testE2() {
-        T_aget_1 t = new T_aget_1();
-        try {
-            t.run(null, 2);
-            fail("expected NullPointerException");
-        } catch (NullPointerException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aget.d.T_aget_1", NullPointerException.class, null, 2);
     }
 
     /**
      * @title expected ArrayIndexOutOfBoundsException (negative index)
      */
     public void testE3() {
-        T_aget_1 t = new T_aget_1();
-        int[] arr = new int[2];
-        try {
-            t.run(arr, -1);
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aget.d.T_aget_1", ArrayIndexOutOfBoundsException.class,
+                   new int[2], -1);
     }
 
-    
-
     /**
      * @constraint B1 
      * @title types of arguments - array, double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.aget.d.T_aget_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget.d.T_aget_2", VerifyError.class);
     }
     
     /**
@@ -103,12 +78,7 @@
      * @title  types of arguments - array, long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.aget.d.T_aget_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget.d.T_aget_3", VerifyError.class);
     }
 
     /**
@@ -116,12 +86,7 @@
      * @title  types of arguments - Object, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.aget.d.T_aget_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget.d.T_aget_4", VerifyError.class);
     }
 
     /**
@@ -129,12 +94,7 @@
      * @title  types of arguments - double[], int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.aget.d.T_aget_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget.d.T_aget_5", VerifyError.class);
     }
 
     /**
@@ -142,12 +102,7 @@
      * @title types of arguments - long[], int
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.aget.d.T_aget_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget.d.T_aget_6", VerifyError.class);
     }
 
     /**
@@ -155,12 +110,7 @@
      * @title types of arguments - array, reference
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.aget.d.T_aget_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget.d.T_aget_7", VerifyError.class);
     }
 
     /**
@@ -168,12 +118,7 @@
      * @title  number of registers
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.aget.d.T_aget_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget.d.T_aget_9", VerifyError.class);
     }
 
     /**
@@ -182,12 +127,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.aget.d.T_aget_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget.d.T_aget_8", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/aget_boolean/Test_aget_boolean.java b/tools/vm-tests-tf/src/dot/junit/opcodes/aget_boolean/Test_aget_boolean.java
index 2e2a3e8..3578f07 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/aget_boolean/Test_aget_boolean.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/aget_boolean/Test_aget_boolean.java
@@ -46,41 +46,24 @@
      * @title expected ArrayIndexOutOfBoundsException
      */
     public void testE1() {
-        T_aget_boolean_1 t = new T_aget_boolean_1();
-        boolean[] arr = new boolean[2];
-        try {
-            t.run(arr, 2);
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aget_boolean.d.T_aget_boolean_1",
+                   ArrayIndexOutOfBoundsException.class, new boolean[2], 2);
     }
 
     /**
      * @title expected NullPointerException
      */
     public void testE2() {
-        T_aget_boolean_1 t = new T_aget_boolean_1();
-        try {
-            t.run(null, 2);
-            fail("expected NullPointerException");
-        } catch (NullPointerException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aget_boolean.d.T_aget_boolean_1", NullPointerException.class,
+                   null, 2);
     }
 
     /**
      * @title expected ArrayIndexOutOfBoundsException (negative index)
      */
     public void testE3() {
-        T_aget_boolean_1 t = new T_aget_boolean_1();
-        boolean[] arr = new boolean[2];
-        try {
-            t.run(arr, -1);
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aget_boolean.d.T_aget_boolean_1",
+                   ArrayIndexOutOfBoundsException.class, new boolean[2], -1);
     }
 
     
@@ -90,12 +73,7 @@
      * @title types of arguments - array, double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_boolean.d.T_aget_boolean_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_boolean.d.T_aget_boolean_2", VerifyError.class);
     }
     
     /**
@@ -103,12 +81,7 @@
      * @title types of arguments - array, long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_boolean.d.T_aget_boolean_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_boolean.d.T_aget_boolean_3", VerifyError.class);
     }
 
     /**
@@ -116,12 +89,7 @@
      * @title types of arguments - Object, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_boolean.d.T_aget_boolean_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_boolean.d.T_aget_boolean_4", VerifyError.class);
     }
 
     /**
@@ -129,12 +97,7 @@
      * @title types of arguments - double[], int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_boolean.d.T_aget_boolean_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_boolean.d.T_aget_boolean_5", VerifyError.class);
     }
 
     /**
@@ -142,12 +105,7 @@
      * @title types of arguments - long[], int
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_boolean.d.T_aget_boolean_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_boolean.d.T_aget_boolean_6", VerifyError.class);
     }
 
     /**
@@ -155,12 +113,7 @@
      * @title types of arguments - array, reference
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_boolean.d.T_aget_boolean_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_boolean.d.T_aget_boolean_7", VerifyError.class);
     }
     
     /**
@@ -168,12 +121,7 @@
      * @title number of registers
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_boolean.d.T_aget_boolean_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_boolean.d.T_aget_boolean_9", VerifyError.class);
     }
 
     /**
@@ -182,11 +130,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_boolean.d.T_aget_boolean_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_boolean.d.T_aget_boolean_8", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/aget_byte/Test_aget_byte.java b/tools/vm-tests-tf/src/dot/junit/opcodes/aget_byte/Test_aget_byte.java
index 57ca7e4..f5b2b8a 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/aget_byte/Test_aget_byte.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/aget_byte/Test_aget_byte.java
@@ -47,56 +47,32 @@
      * @title expected ArrayIndexOutOfBoundsException
      */
     public void testE1() {
-        T_aget_byte_1 t = new T_aget_byte_1();
-        byte[] arr = new byte[2];
-        try {
-            t.run(arr, 2);
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aget_byte.d.T_aget_byte_1",
+                   ArrayIndexOutOfBoundsException.class, new byte[2], 2);
     }
 
     /**
      * @title expected NullPointerException
      */
     public void testE2() {
-        T_aget_byte_1 t = new T_aget_byte_1();
-        try {
-            t.run(null, 2);
-            fail("expected NullPointerException");
-        } catch (NullPointerException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aget_byte.d.T_aget_byte_1", NullPointerException.class, null,
+                   2);
     }
 
     /**
      * @title expected ArrayIndexOutOfBoundsException (negative index)
      */
     public void testE3() {
-        T_aget_byte_1 t = new T_aget_byte_1();
-        byte[] arr = new byte[2];
-        try {
-            t.run(arr, -1);
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aget_byte.d.T_aget_byte_1",
+                   ArrayIndexOutOfBoundsException.class, new byte[2], -1);
     }
 
-    
-
     /**
      * @constraint B1
      * @title types of arguments - array, double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_byte.d.T_aget_byte_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_byte.d.T_aget_byte_2", VerifyError.class);
     }
 
     /**
@@ -104,12 +80,7 @@
      * @title types of arguments - array, long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_byte.d.T_aget_byte_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_byte.d.T_aget_byte_3", VerifyError.class);
     }
 
     /**
@@ -117,12 +88,7 @@
      * @title types of arguments - Object, short
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_byte.d.T_aget_byte_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_byte.d.T_aget_byte_4", VerifyError.class);
     }
 
     /**
@@ -130,12 +96,7 @@
      * @title types of arguments - double[], int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_byte.d.T_aget_byte_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_byte.d.T_aget_byte_5", VerifyError.class);
     }
 
     /**
@@ -143,12 +104,7 @@
      * @title types of arguments - int[], int
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_byte.d.T_aget_byte_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_byte.d.T_aget_byte_6", VerifyError.class);
     }
 
     /**
@@ -156,12 +112,7 @@
      * @title types of arguments - array, reference
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_byte.d.T_aget_byte_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_byte.d.T_aget_byte_7", VerifyError.class);
     }
     
     /**
@@ -169,12 +120,7 @@
      * @title number of registers
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_byte.d.T_aget_byte_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_byte.d.T_aget_byte_9", VerifyError.class);
     }
 
     /**
@@ -183,12 +129,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_byte.d.T_aget_byte_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_byte.d.T_aget_byte_8", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/aget_char/Test_aget_char.java b/tools/vm-tests-tf/src/dot/junit/opcodes/aget_char/Test_aget_char.java
index e9c8ca6..09dabc7 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/aget_char/Test_aget_char.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/aget_char/Test_aget_char.java
@@ -46,41 +46,24 @@
      * @title expected ArrayIndexOutOfBoundsException
      */
     public void testE1() {
-        T_aget_char_1 t = new T_aget_char_1();
-        char[] arr = new char[2];
-        try {
-            t.run(arr, 2);
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aget_char.d.T_aget_char_1",
+                   ArrayIndexOutOfBoundsException.class, new char[2], 2);
     }
 
     /**
      * @title expected NullPointerException
      */
     public void testE2() {
-        T_aget_char_1 t = new T_aget_char_1();
-        try {
-            t.run(null, 2);
-            fail("expected NullPointerException");
-        } catch (NullPointerException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aget_char.d.T_aget_char_1",
+                   NullPointerException.class, null, 2);
     }
 
     /**
      * @title expected ArrayIndexOutOfBoundsException (negative index)
      */
     public void testE3() {
-        T_aget_char_1 t = new T_aget_char_1();
-        char[] arr = new char[2];
-        try {
-            t.run(arr, -1);
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aget_char.d.T_aget_char_1",
+                   ArrayIndexOutOfBoundsException.class, new char[2], -1);
     }
 
     
@@ -90,12 +73,7 @@
      * @title types of arguments - array, double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_char.d.T_aget_char_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_char.d.T_aget_char_2", VerifyError.class);
     }
 
     /**
@@ -103,12 +81,7 @@
      * @title types of arguments - array, long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_char.d.T_aget_char_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_char.d.T_aget_char_3", VerifyError.class);
     }
 
     /**
@@ -116,12 +89,7 @@
      * @title types of arguments - Object, char
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_char.d.T_aget_char_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_char.d.T_aget_char_4", VerifyError.class);
     }
 
     /**
@@ -129,12 +97,7 @@
      * @title types of arguments - double[], char
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_char.d.T_aget_char_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_char.d.T_aget_char_5", VerifyError.class);
     }
 
     /**
@@ -142,12 +105,7 @@
      * @title types of arguments - int[], int
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_char.d.T_aget_char_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_char.d.T_aget_char_6", VerifyError.class);
     }
 
     /**
@@ -155,12 +113,7 @@
      * @title types of arguments - array, reference
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_char.d.T_aget_char_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_char.d.T_aget_char_7", VerifyError.class);
     }
     
     /**
@@ -168,12 +121,7 @@
      * @title number of registers
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_char.d.T_aget_char_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_char.d.T_aget_char_9", VerifyError.class);
     }
 
     /**
@@ -182,11 +130,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_char.d.T_aget_char_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_char.d.T_aget_char_8", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/aget_object/Test_aget_object.java b/tools/vm-tests-tf/src/dot/junit/opcodes/aget_object/Test_aget_object.java
index a99bae1..7afe803 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/aget_object/Test_aget_object.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/aget_object/Test_aget_object.java
@@ -45,42 +45,24 @@
      * @title expected ArrayIndexOutOfBoundsException
      */
     public void testE1() {
-        T_aget_object_1 t = new T_aget_object_1();
-        String[] arr = new String[] {"a", "b"};
-        try {
-            t.run(arr, 2);
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aioobe) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aget_object.d.T_aget_object_1",
+                   ArrayIndexOutOfBoundsException.class, new String[2], 2);
     }
 
     /**
      * @title expected ArrayIndexOutOfBoundsException (negative index)
      */
     public void testE2() {
-        T_aget_object_1 t = new T_aget_object_1();
-        String[] arr = new String[] {"a", "b"};
-        try {
-            t.run(arr, -1);
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aioobe) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aget_object.d.T_aget_object_1",
+                   ArrayIndexOutOfBoundsException.class, new String[2], -1);
     }
 
     /**
      * @title expected NullPointerException
      */
     public void testE3() {
-        T_aget_object_1 t = new T_aget_object_1();
-        String[] arr = null;
-        try {
-            t.run(arr, 0);
-            fail("expected NullPointerException");
-        } catch (NullPointerException npe) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aget_object.d.T_aget_object_1", NullPointerException.class,
+                   null, 0);
     }
 
     /**
@@ -88,12 +70,7 @@
      * @title types of arguments - array, double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_object.d.T_aget_object_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_object.d.T_aget_object_2", VerifyError.class);
     }
 
     /**
@@ -101,12 +78,7 @@
      * @title types of arguments - array, long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_object.d.T_aget_object_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_object.d.T_aget_object_3", VerifyError.class);
     }
 
     /**
@@ -114,12 +86,7 @@
      * @title types of arguments - Object, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_object.d.T_aget_object_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_object.d.T_aget_object_4", VerifyError.class);
     }
 
     /**
@@ -127,12 +94,7 @@
      * @title types of arguments - float[], int
      */
     public void testVFE4() {
-        try { 
-            Class.forName("dot.junit.opcodes.aget_object.d.T_aget_object_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_object.d.T_aget_object_5", VerifyError.class);
     }
 
     /**
@@ -140,12 +102,7 @@
      * @title types of arguments - long[], int
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_object.d.T_aget_object_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_object.d.T_aget_object_6", VerifyError.class);
     }
 
     /**
@@ -153,12 +110,7 @@
      * @title types of arguments - array, reference
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_object.d.T_aget_object_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_object.d.T_aget_object_7", VerifyError.class);
     }
     
     /**
@@ -166,12 +118,7 @@
      * @title number of registers
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_object.d.T_aget_object_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_object.d.T_aget_object_9", VerifyError.class);
     }
 
     /**
@@ -180,12 +127,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_object.d.T_aget_object_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_object.d.T_aget_object_8", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/aget_short/Test_aget_short.java b/tools/vm-tests-tf/src/dot/junit/opcodes/aget_short/Test_aget_short.java
index e5801ae..334f8c1 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/aget_short/Test_aget_short.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/aget_short/Test_aget_short.java
@@ -46,56 +46,32 @@
      * @title expected ArrayIndexOutOfBoundsException
      */
     public void testE1() {
-        T_aget_short_1 t = new T_aget_short_1();
-        short[] arr = new short[2];
-        try {
-            t.run(arr, 2);
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aget_short.d.T_aget_short_1",
+                   ArrayIndexOutOfBoundsException.class, new short[2], 2);
     }
 
     /**
      * @title expected NullPointerException
      */
     public void testE2() {
-        T_aget_short_1 t = new T_aget_short_1();
-        try {
-            t.run(null, 2);
-            fail("expected NullPointerException");
-        } catch (NullPointerException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aget_short.d.T_aget_short_1", NullPointerException.class,
+                   null, 2);
     }
 
     /**
      * @title expected ArrayIndexOutOfBoundsException (negative index)
      */
     public void testE3() {
-        T_aget_short_1 t = new T_aget_short_1();
-        short[] arr = new short[2];
-        try {
-            t.run(arr, -1);
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aget_short.d.T_aget_short_1",
+                   ArrayIndexOutOfBoundsException.class, new short[2], -1);
     }
 
-    
-
     /**
      * @constraint B1 
      * @title types of arguments - array, double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_short.d.T_aget_short_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_short.d.T_aget_short_2", VerifyError.class);
     }
 
     /**
@@ -103,12 +79,7 @@
      * @title types of arguments - array, long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_short.d.T_aget_short_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_short.d.T_aget_short_3", VerifyError.class);
     }
 
     /**
@@ -116,12 +87,7 @@
      * @title types of arguments - Object, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_short.d.T_aget_short_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_short.d.T_aget_short_4", VerifyError.class);
     }
 
     /**
@@ -129,12 +95,7 @@
      * @title types of arguments - double[], int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_short.d.T_aget_short_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_short.d.T_aget_short_5", VerifyError.class);
     }
 
     /**
@@ -142,12 +103,7 @@
      * @title types of arguments - int[], int
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_short.d.T_aget_short_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_short.d.T_aget_short_6", VerifyError.class);
     }
 
     /**
@@ -155,12 +111,7 @@
      * @title types of arguments - array, reference
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_short.d.T_aget_short_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_short.d.T_aget_short_7", VerifyError.class);
     }
     
     /**
@@ -168,12 +119,7 @@
      * @title number of registers
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_short.d.T_aget_short_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_short.d.T_aget_short_9", VerifyError.class);
     }
 
     /**
@@ -182,11 +128,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_short.d.T_aget_short_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_short.d.T_aget_short_8", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/aget_wide/Test_aget_wide.java b/tools/vm-tests-tf/src/dot/junit/opcodes/aget_wide/Test_aget_wide.java
index fb9744d..fbbde61 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/aget_wide/Test_aget_wide.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/aget_wide/Test_aget_wide.java
@@ -59,56 +59,32 @@
      * @title expected ArrayIndexOutOfBoundsException
      */
     public void testE1() {
-        T_aget_wide_1 t = new T_aget_wide_1();
-        long[] arr = new long[2];
-        try {
-            t.run(arr, 2);
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aget_wide.d.T_aget_wide_1",
+                   ArrayIndexOutOfBoundsException.class, new long[2], 2);
     }
 
     /**
      * @title expected NullPointerException
      */
     public void testE2() {
-        T_aget_wide_1 t = new T_aget_wide_1();
-        try {
-            t.run(null, 2);
-            fail("expected NullPointerException");
-        } catch (NullPointerException np) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aget_wide.d.T_aget_wide_1", NullPointerException.class,
+                   null, 2);
     }
 
     /**
      * @title expected ArrayIndexOutOfBoundsException (negative index)
      */
     public void testE3() {
-        T_aget_wide_1 t = new T_aget_wide_1();
-        long[] arr = new long[2];
-        try {
-            t.run(arr, -1);
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aget_wide.d.T_aget_wide_1",
+                   ArrayIndexOutOfBoundsException.class, new long[2], -1);
     }
 
-    
-
     /**
      * @constraint B1 
      * @title types of arguments - array, double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_wide.d.T_aget_wide_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_wide.d.T_aget_wide_3", VerifyError.class);
     }
 
     /**
@@ -116,12 +92,7 @@
      * @title types of arguments - array, long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_wide.d.T_aget_wide_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_wide.d.T_aget_wide_5", VerifyError.class);
     }
    
     /**
@@ -129,12 +100,7 @@
      * @title types of arguments - Object, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_wide.d.T_aget_wide_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_wide.d.T_aget_wide_6", VerifyError.class);
     }
 
     /**
@@ -142,12 +108,7 @@
      * @title types of arguments - int[], int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_wide.d.T_aget_wide_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_wide.d.T_aget_wide_7", VerifyError.class);
     }
 
     /**
@@ -155,12 +116,7 @@
      * @title types of arguments - array, reference
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_wide.d.T_aget_wide_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_wide.d.T_aget_wide_8", VerifyError.class);
     }
 
     /**
@@ -168,12 +124,7 @@
      * @title number of registers
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_wide.d.T_aget_wide_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_wide.d.T_aget_wide_9", VerifyError.class);
     }
     
     /**
@@ -181,12 +132,7 @@
      * @title number of registers
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_wide.d.T_aget_wide_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_wide.d.T_aget_wide_11", VerifyError.class);
     }
 
     /**
@@ -195,11 +141,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.aget_wide.d.T_aget_wide_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aget_wide.d.T_aget_wide_10", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/and_int/Test_and_int.java b/tools/vm-tests-tf/src/dot/junit/opcodes/and_int/Test_and_int.java
index 0afc0bc..fa75935 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/and_int/Test_and_int.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/and_int/Test_and_int.java
@@ -71,12 +71,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.and_int.d.T_and_int_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_int.d.T_and_int_5", VerifyError.class);
     }
 
     /**
@@ -84,12 +79,7 @@
      * @title types of arguments - double & int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.and_int.d.T_and_int_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_int.d.T_and_int_2", VerifyError.class);
     }
 
     /**
@@ -97,12 +87,7 @@
      * @title types of arguments - long & int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.and_int.d.T_and_int_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_int.d.T_and_int_3", VerifyError.class);
     }
 
     /**
@@ -110,12 +95,7 @@
      * @title types of arguments - int & reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.and_int.d.T_and_int_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_int.d.T_and_int_4", VerifyError.class);
     }
     
     /**
@@ -123,11 +103,6 @@
      * @title number of registers
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.and_int.d.T_and_int_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_int.d.T_and_int_6", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/and_int_2addr/Test_and_int_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/and_int_2addr/Test_and_int_2addr.java
index 7a13653..1ea0b9d 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/and_int_2addr/Test_and_int_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/and_int_2addr/Test_and_int_2addr.java
@@ -70,12 +70,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.and_int_2addr.d.T_and_int_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_int_2addr.d.T_and_int_2addr_5", VerifyError.class);
     }
 
     /**
@@ -83,12 +78,7 @@
      * @title types of arguments - double & int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.and_int_2addr.d.T_and_int_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_int_2addr.d.T_and_int_2addr_2", VerifyError.class);
     }
 
     /**
@@ -96,12 +86,7 @@
      * @title types of arguments - long & int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.and_int_2addr.d.T_and_int_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_int_2addr.d.T_and_int_2addr_3", VerifyError.class);
     }
 
     /**
@@ -109,12 +94,7 @@
      * @title types of arguments - int & reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.and_int_2addr.d.T_and_int_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_int_2addr.d.T_and_int_2addr_4", VerifyError.class);
     }
     
     /**
@@ -122,11 +102,6 @@
      * @title number of registers
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.and_int_2addr.d.T_and_int_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_int_2addr.d.T_and_int_2addr_6", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/and_int_lit16/Test_and_int_lit16.java b/tools/vm-tests-tf/src/dot/junit/opcodes/and_int_lit16/Test_and_int_lit16.java
index 2593da4..1a89ca1 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/and_int_lit16/Test_and_int_lit16.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/and_int_lit16/Test_and_int_lit16.java
@@ -73,12 +73,7 @@
      * @title  types of arguments - double & int
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.and_int_lit16.d.T_and_int_lit16_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_int_lit16.d.T_and_int_lit16_6", VerifyError.class);
     }
 
     /**
@@ -86,12 +81,7 @@
      * @title types of arguments - long & int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.and_int_lit16.d.T_and_int_lit16_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_int_lit16.d.T_and_int_lit16_7", VerifyError.class);
     }
 
     /**
@@ -99,12 +89,7 @@
      * @title types of arguments - int & reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.and_int_lit16.d.T_and_int_lit16_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_int_lit16.d.T_and_int_lit16_8", VerifyError.class);
     }
 
     /**
@@ -112,12 +97,7 @@
      * @title number of registers
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.and_int_lit16.d.T_and_int_lit16_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_int_lit16.d.T_and_int_lit16_10", VerifyError.class);
     }
 
     /**
@@ -126,11 +106,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.and_int_lit16.d.T_and_int_lit16_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_int_lit16.d.T_and_int_lit16_9", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/and_int_lit8/Test_and_int_lit8.java b/tools/vm-tests-tf/src/dot/junit/opcodes/and_int_lit8/Test_and_int_lit8.java
index 578e857..343bb3a 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/and_int_lit8/Test_and_int_lit8.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/and_int_lit8/Test_and_int_lit8.java
@@ -73,12 +73,7 @@
      * @title types of arguments - double & int
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.and_int_lit8.d.T_and_int_lit8_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_int_lit8.d.T_and_int_lit8_6", VerifyError.class);
     }
 
     /**
@@ -86,12 +81,7 @@
      * @title types of arguments - long & int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.and_int_lit8.d.T_and_int_lit8_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_int_lit8.d.T_and_int_lit8_7", VerifyError.class);
     }
 
     /**
@@ -99,12 +89,7 @@
      * @title types of arguments - int & reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.and_int_lit8.d.T_and_int_lit8_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_int_lit8.d.T_and_int_lit8_8", VerifyError.class);
     }
 
     /**
@@ -112,12 +97,7 @@
      * @title number of registers
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.and_int_lit8.d.T_and_int_lit8_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_int_lit8.d.T_and_int_lit8_10", VerifyError.class);
     }
 
     /**
@@ -126,11 +106,6 @@
      * and longs are not used interchangeably.
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.and_int_lit8.d.T_and_int_lit8_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_int_lit8.d.T_and_int_lit8_9", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/and_long/Test_and_long.java b/tools/vm-tests-tf/src/dot/junit/opcodes/and_long/Test_and_long.java
index b0ba073..03e60ea 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/and_long/Test_and_long.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/and_long/Test_and_long.java
@@ -71,12 +71,7 @@
      * @title types of arguments - float & long
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.and_long.d.T_and_long_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_long.d.T_and_long_2", VerifyError.class);
     }
 
     /**
@@ -84,12 +79,7 @@
      * @title types of arguments - int & long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.and_long.d.T_and_long_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_long.d.T_and_long_3", VerifyError.class);
     }
 
     /**
@@ -97,12 +87,7 @@
      * @title types of arguments - reference & long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.and_long.d.T_and_long_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_long.d.T_and_long_4", VerifyError.class);
     }
     
     /**
@@ -110,12 +95,7 @@
      * @title number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.and_long.d.T_and_long_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_long.d.T_and_long_5", VerifyError.class);
     }
 
     /**
@@ -124,11 +104,6 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.and_long.d.T_and_long_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_long.d.T_and_long_6", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/and_long_2addr/Test_and_long_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/and_long_2addr/Test_and_long_2addr.java
index e3b8969..b791342 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/and_long_2addr/Test_and_long_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/and_long_2addr/Test_and_long_2addr.java
@@ -70,12 +70,7 @@
      * @title types of arguments - float & long
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.and_long_2addr.d.T_and_long_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_long_2addr.d.T_and_long_2addr_2", VerifyError.class);
     }
 
     /**
@@ -83,12 +78,7 @@
      * @title types of arguments - int & long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.and_long_2addr.d.T_and_long_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_long_2addr.d.T_and_long_2addr_3", VerifyError.class);
     }
 
     /**
@@ -96,12 +86,7 @@
      * @title types of arguments - reference & long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.and_long_2addr.d.T_and_long_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_long_2addr.d.T_and_long_2addr_4", VerifyError.class);
     }
     
     /**
@@ -109,12 +94,7 @@
      * @title number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.and_long_2addr.d.T_and_long_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_long_2addr.d.T_and_long_2addr_5", VerifyError.class);
     }
 
     /**
@@ -123,11 +103,6 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.and_long_2addr.d.T_and_long_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.and_long_2addr.d.T_and_long_2addr_6", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/aput/Test_aput.java b/tools/vm-tests-tf/src/dot/junit/opcodes/aput/Test_aput.java
index a41dc58..3bf95c8 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/aput/Test_aput.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/aput/Test_aput.java
@@ -47,41 +47,24 @@
      * @title expected ArrayIndexOutOfBoundsException
      */
     public void testE1() {
-        T_aput_1 t = new T_aput_1();
-        int[] arr = new int[2];
-        try {
-            t.run(arr, 2, 100000000);
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aput.d.T_aput_1", ArrayIndexOutOfBoundsException.class,
+                   new int[2], 2, 100000000);
     }
 
     /**
      * @title expected NullPointerException
      */
     public void testE2() {
-        T_aput_1 t = new T_aput_1();
-        try {
-            t.run(null, 2, 100000000);
-            fail("expected NullPointerException");
-        } catch (NullPointerException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aput.d.T_aput_1", NullPointerException.class,
+                   null, 2, 100000000);
     }
 
     /**
      * @title expected ArrayIndexOutOfBoundsException (negative index)
      */
     public void testE3() {
-        T_aput_1 t = new T_aput_1();
-        int[] arr = new int[2];
-        try {
-            t.run(arr, -1, 100000000);
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aput.d.T_aput_1", ArrayIndexOutOfBoundsException.class,
+                   new int[2], -1, 100000000);
     }
 
     
@@ -91,12 +74,7 @@
      * @title types of arguments - array, double, int
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.aput.d.T_aput_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput.d.T_aput_2", VerifyError.class);
     }
 
     /**
@@ -104,12 +82,7 @@
      * @title types of arguments - array, int, long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.aput.d.T_aput_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput.d.T_aput_3", VerifyError.class);
     }
 
     /**
@@ -117,12 +90,7 @@
      * @title types of arguments - object, int, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.aput.d.T_aput_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput.d.T_aput_4", VerifyError.class);
     }
 
     /**
@@ -130,12 +98,7 @@
      * @title types of arguments - double[], int, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.aput.d.T_aput_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput.d.T_aput_5", VerifyError.class);
     }
 
     /**
@@ -143,12 +106,7 @@
      * @title types of arguments - long[], int, int
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.aput.d.T_aput_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput.d.T_aput_6", VerifyError.class);
     }
 
     /**
@@ -156,12 +114,7 @@
      * @title types of arguments - array, reference, int
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.aput.d.T_aput_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput.d.T_aput_7", VerifyError.class);
     }
     
     /**
@@ -169,12 +122,7 @@
      * @title number of registers
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.aput.d.T_aput_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput.d.T_aput_9", VerifyError.class);
     }
 
     /**
@@ -183,11 +131,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.aput.d.T_aput_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput.d.T_aput_8", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/aput_boolean/Test_aput_boolean.java b/tools/vm-tests-tf/src/dot/junit/opcodes/aput_boolean/Test_aput_boolean.java
index f4fe940..fb31499 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/aput_boolean/Test_aput_boolean.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/aput_boolean/Test_aput_boolean.java
@@ -46,56 +46,32 @@
      * @title expected ArrayIndexOutOfBoundsException
      */
     public void testE1() {
-        T_aput_boolean_1 t = new T_aput_boolean_1();
-        boolean[] arr = new boolean[2];
-        try {
-            t.run(arr, 2, true);
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aput_boolean.d.T_aput_boolean_1",
+                   ArrayIndexOutOfBoundsException.class, new boolean[2], 2, true);
     }
 
     /**
      * @title expected NullPointerException
      */
     public void testE2() {
-        T_aput_boolean_1 t = new T_aput_boolean_1();
-        try {
-            t.run(null, 2, true);
-            fail("expected NullPointerException");
-        } catch (NullPointerException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aput_boolean.d.T_aput_boolean_1",
+                   NullPointerException.class, null, 2, true);
     }
 
     /**
      * @title expected ArrayIndexOutOfBoundsException (negative index)
      */
     public void testE3() {
-        T_aput_boolean_1 t = new T_aput_boolean_1();
-        boolean[] arr = new boolean[2];
-        try {
-            t.run(arr, -1, true);
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aput_boolean.d.T_aput_boolean_1",
+                   ArrayIndexOutOfBoundsException.class, new boolean[2], -1, true);
     }
 
-    
-
     /**
      * @constraint B1 
      * @title types of arguments - array, double, int
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_boolean.d.T_aput_boolean_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_boolean.d.T_aput_boolean_2", VerifyError.class);
     }
 
     /**
@@ -103,12 +79,7 @@
      * @title types of arguments - array, int, long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_boolean.d.T_aput_boolean_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_boolean.d.T_aput_boolean_3", VerifyError.class);
     }
 
     /**
@@ -116,12 +87,7 @@
      * @title types of arguments - object, int, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_boolean.d.T_aput_boolean_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_boolean.d.T_aput_boolean_4", VerifyError.class);
     }
 
     /**
@@ -129,12 +95,7 @@
      * @title types of arguments - double[], int, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_boolean.d.T_aput_boolean_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_boolean.d.T_aput_boolean_5", VerifyError.class);
     }
 
     /**
@@ -142,12 +103,7 @@
      * @title types of arguments - long[], int, int
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_boolean.d.T_aput_boolean_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_boolean.d.T_aput_boolean_6", VerifyError.class);
     }
 
     /**
@@ -155,12 +111,7 @@
      * @title types of arguments - array, reference, int
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_boolean.d.T_aput_boolean_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_boolean.d.T_aput_boolean_7", VerifyError.class);
     }
     
     /**
@@ -168,12 +119,7 @@
      * @title number of registers
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_boolean.d.T_aput_boolean_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_boolean.d.T_aput_boolean_9", VerifyError.class);
     }
 
     /**
@@ -182,12 +128,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE10() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_boolean.d.T_aput_boolean_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_boolean.d.T_aput_boolean_8", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/aput_byte/Test_aput_byte.java b/tools/vm-tests-tf/src/dot/junit/opcodes/aput_byte/Test_aput_byte.java
index 396e5b7..60352c3 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/aput_byte/Test_aput_byte.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/aput_byte/Test_aput_byte.java
@@ -46,41 +46,24 @@
      * @title expected ArrayIndexOutOfBoundsException
      */
     public void testE1() {
-        T_aput_byte_1 t = new T_aput_byte_1();
-        byte[] arr = new byte[2];
-        try {
-            t.run(arr, 2, (byte) 100);
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aput_byte.d.T_aput_byte_1",
+                   ArrayIndexOutOfBoundsException.class, new byte[2], 2, (byte) 100);
     }
 
     /**
      * @title expected NullPointerException
      */
     public void testE2() {
-        T_aput_byte_1 t = new T_aput_byte_1();
-        try {
-            t.run(null, 2, (byte) 100);
-            fail("expected NullPointerException");
-        } catch (NullPointerException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aput_byte.d.T_aput_byte_1",
+                   NullPointerException.class, null, 2, (byte) 100);
     }
 
     /**
      * @title expected ArrayIndexOutOfBoundsException (negative index)
      */
     public void testE3() {
-        T_aput_byte_1 t = new T_aput_byte_1();
-        byte[] arr = new byte[2];
-        try {
-            t.run(arr, -1, (byte) 100);
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aput_byte.d.T_aput_byte_1",
+                   ArrayIndexOutOfBoundsException.class, new byte[2], -1, (byte) 100);
     }
 
 
@@ -91,12 +74,7 @@
      * @title types of arguments - array, double, short
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_byte.d.T_aput_byte_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_byte.d.T_aput_byte_2", VerifyError.class);
     }
 
     /**
@@ -104,12 +82,7 @@
      * @title types of arguments - array, int, long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_byte.d.T_aput_byte_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_byte.d.T_aput_byte_3", VerifyError.class);
     }
 
     /**
@@ -117,12 +90,7 @@
      * @title types of arguments - object, int, short
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_byte.d.T_aput_byte_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_byte.d.T_aput_byte_4", VerifyError.class);
     }
 
     /**
@@ -130,12 +98,7 @@
      * @title types of arguments - double[], int, short
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_byte.d.T_aput_byte_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_byte.d.T_aput_byte_5", VerifyError.class);
     }
 
     /**
@@ -143,12 +106,7 @@
      * @title types of arguments - long[], int, short
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_byte.d.T_aput_byte_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_byte.d.T_aput_byte_6", VerifyError.class);
     }
 
     /**
@@ -156,12 +114,7 @@
      * @title types of arguments - array, reference, short
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_byte.d.T_aput_byte_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_byte.d.T_aput_byte_7", VerifyError.class);
     }
     
     /**
@@ -169,12 +122,7 @@
      * @title number of registers
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_byte.d.T_aput_byte_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_byte.d.T_aput_byte_9", VerifyError.class);
     }
 
     /**
@@ -183,12 +131,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE9() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_byte.d.T_aput_byte_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_byte.d.T_aput_byte_8", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/aput_char/Test_aput_char.java b/tools/vm-tests-tf/src/dot/junit/opcodes/aput_char/Test_aput_char.java
index 8698034..952f4dd 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/aput_char/Test_aput_char.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/aput_char/Test_aput_char.java
@@ -47,57 +47,32 @@
      * @title expected ArrayIndexOutOfBoundsException
      */
     public void testE1() {
-        T_aput_char_1 t = new T_aput_char_1();
-        char[] arr = new char[2];
-        try {
-            t.run(arr, 2, 'g');
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aput_char.d.T_aput_char_1",
+                   ArrayIndexOutOfBoundsException.class, new char[2], 2, 'g');
     }
 
     /**
      * @title expected NullPointerException
      */
     public void testE2() {
-        T_aput_char_1 t = new T_aput_char_1();
-        try {
-            t.run(null, 2, 'g');
-            fail("expected NullPointerException");
-        } catch (NullPointerException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aput_char.d.T_aput_char_1", NullPointerException.class, null,
+                   0, 'g');
     }
 
     /**
      * @title expected ArrayIndexOutOfBoundsException (negative index)
      */
     public void testE3() {
-        T_aput_char_1 t = new T_aput_char_1();
-        char[] arr = new char[2];
-        try {
-            t.run(arr, -1, 'g');
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aput_char.d.T_aput_char_1",
+                   ArrayIndexOutOfBoundsException.class, new char[2], -1, 'g');
     }
 
- 
-    
-
     /**
      * @constraint B1 
      * @title types of arguments - array, double, char
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_char.d.T_aput_char_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_char.d.T_aput_char_2", VerifyError.class);
     }
 
     /**
@@ -105,12 +80,7 @@
      * @title types of arguments - array, int, long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_char.d.T_aput_char_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_char.d.T_aput_char_3", VerifyError.class);
     }
 
     /**
@@ -118,12 +88,7 @@
      * @title types of arguments - object, int, char
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_char.d.T_aput_char_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_char.d.T_aput_char_4", VerifyError.class);
     }
 
     /**
@@ -131,12 +96,7 @@
      * @title types of arguments - double[], int, char
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_char.d.T_aput_char_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_char.d.T_aput_char_5", VerifyError.class);
     }
 
     /**
@@ -144,12 +104,7 @@
      * @title types of arguments - long[], int, char
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_char.d.T_aput_char_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_char.d.T_aput_char_6", VerifyError.class);
     }
 
     /**
@@ -157,12 +112,7 @@
      * @title types of arguments - array, reference, char
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_char.d.T_aput_char_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_char.d.T_aput_char_7", VerifyError.class);
     }
     
     /**
@@ -170,12 +120,7 @@
      * @title number of registers
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_char.d.T_aput_char_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_char.d.T_aput_char_9", VerifyError.class);
     }
 
     /**
@@ -184,12 +129,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_char.d.T_aput_char_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_char.d.T_aput_char_8", VerifyError.class);
     }
-
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/aput_object/Test_aput_object.java b/tools/vm-tests-tf/src/dot/junit/opcodes/aput_object/Test_aput_object.java
index 86c3159..4dce800 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/aput_object/Test_aput_object.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/aput_object/Test_aput_object.java
@@ -72,56 +72,33 @@
      * @title expected ArrayIndexOutOfBoundsException
      */
     public void testE1() {
-        T_aput_object_1 t = new T_aput_object_1();
-        String[] arr = new String[2];
-        try {
-            t.run(arr, arr.length, "abc");
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aput_object.d.T_aput_object_1",
+                   ArrayIndexOutOfBoundsException.class, new String[2], 2, "abc");
     }
 
     /**
      * @title expected ArrayIndexOutOfBoundsException (negative index)
      */
     public void testE2() {
-        T_aput_object_1 t = new T_aput_object_1();
-        String[] arr = new String[2];
-        try {
-            t.run(arr, -1, "abc");
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aput_object.d.T_aput_object_1",
+                   ArrayIndexOutOfBoundsException.class, new String[2], -1, "abc");
+
     }
 
     /**
      * @title expected NullPointerException
      */
     public void testE3() {
-        T_aput_object_1 t = new T_aput_object_1();
-        String[] arr = null;
-        try {
-            t.run(arr, 0, "abc");
-            fail("expected NullPointerException");
-        } catch (NullPointerException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aput_object.d.T_aput_object_1", NullPointerException.class,
+                   null, 0, "abc");
     }
 
     /**
      * @title expected ArrayStoreException
      */
     public void testE4() {
-        T_aput_object_4 t = new T_aput_object_4();
-        String[] arr = new String[2];
-        try {
-            t.run(arr, 0, t);
-            fail("expected ArrayStoreException");
-        } catch (ArrayStoreException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aput_object.d.T_aput_object_4", ArrayStoreException.class,
+                   new String[2], 0, new Integer(1));
     }
 
 
@@ -130,12 +107,7 @@
      * @title types of arguments - array, double, String
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_object.d.T_aput_object_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_object.d.T_aput_object_5", VerifyError.class);
     }
 
     /**
@@ -143,12 +115,7 @@
      * @title types of arguments - array, int, long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_object.d.T_aput_object_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_object.d.T_aput_object_6", VerifyError.class);
     }
 
     /**
@@ -156,12 +123,7 @@
      * @title types of arguments - object, int, String
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_object.d.T_aput_object_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_object.d.T_aput_object_7", VerifyError.class);
     }
 
     /**
@@ -169,12 +131,7 @@
      * @title types of arguments - float[], int, String
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_object.d.T_aput_object_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_object.d.T_aput_object_8", VerifyError.class);
     }
 
     /**
@@ -182,12 +139,7 @@
      * @title types of arguments - long[], int, String
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_object.d.T_aput_object_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_object.d.T_aput_object_9", VerifyError.class);
     }
 
     /**
@@ -195,12 +147,7 @@
      * @title types of arguments - array, reference, String
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_object.d.T_aput_object_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_object.d.T_aput_object_10", VerifyError.class);
     }
     
     /**
@@ -208,12 +155,7 @@
      * @title number of registers
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_object.d.T_aput_object_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_object.d.T_aput_object_11", VerifyError.class);
     }
     
     /**
@@ -221,12 +163,7 @@
      * @title put integer into array of references
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_object.d.T_aput_object_13");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_object.d.T_aput_object_13", VerifyError.class);
     }
 
     /**
@@ -235,11 +172,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE9() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_object.d.T_aput_object_12");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_object.d.T_aput_object_12", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/aput_short/Test_aput_short.java b/tools/vm-tests-tf/src/dot/junit/opcodes/aput_short/Test_aput_short.java
index a3dcf18..14a5eb4 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/aput_short/Test_aput_short.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/aput_short/Test_aput_short.java
@@ -46,56 +46,32 @@
      * @title expected ArrayIndexOutOfBoundsException
      */
     public void testE1() {
-        T_aput_short_1 t = new T_aput_short_1();
-        short[] arr = new short[2];
-        try {
-            t.run(arr, 2, (short) 10000);
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aput_short.d.T_aput_short_1",
+                   ArrayIndexOutOfBoundsException.class, new short[2], 2, (short) 10000);
     }
 
     /**
      * @title expected NullPointerException
      */
     public void testE2() {
-        T_aput_short_1 t = new T_aput_short_1();
-        try {
-            t.run(null, 2, (short) 10000);
-            fail("expected NullPointerException");
-        } catch (NullPointerException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aput_short.d.T_aput_short_1", NullPointerException.class,
+                   null, 2, (short) 10000);
     }
 
     /**
      * @title expected ArrayIndexOutOfBoundsException (negative index)
      */
     public void testE3() {
-        T_aput_short_1 t = new T_aput_short_1();
-        short[] arr = new short[2];
-        try {
-            t.run(arr, -1, (short) 10000);
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aput_short.d.T_aput_short_1",
+                   ArrayIndexOutOfBoundsException.class, new short[2], -1, (short) 10000);
     }
 
-    
-
     /**
      * @constraint B1 
      * @title types of arguments - array, double, int
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_short.d.T_aput_short_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_short.d.T_aput_short_2", VerifyError.class);
     }
 
     /**
@@ -103,12 +79,7 @@
      * @title types of arguments - array, int, long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_short.d.T_aput_short_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_short.d.T_aput_short_3", VerifyError.class);
     }
 
     /**
@@ -116,12 +87,7 @@
      * @title types of arguments - object, int, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_short.d.T_aput_short_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_short.d.T_aput_short_4", VerifyError.class);
     }
 
     /**
@@ -129,12 +95,7 @@
      * @title types of arguments - double[], int, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_short.d.T_aput_short_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_short.d.T_aput_short_5", VerifyError.class);
     }
 
     /**
@@ -142,12 +103,7 @@
      * @title types of arguments - long[], int, int
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_short.d.T_aput_short_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_short.d.T_aput_short_6", VerifyError.class);
     }
 
     /**
@@ -155,12 +111,7 @@
      * @title types of arguments - array, reference, int
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_short.d.T_aput_short_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_short.d.T_aput_short_7", VerifyError.class);
     }
 
     /**
@@ -168,12 +119,7 @@
      * @title number of registers
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_short.d.T_aput_short_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_short.d.T_aput_short_9", VerifyError.class);
     }
 
     /**
@@ -182,12 +128,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE9() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_short.d.T_aput_short_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_short.d.T_aput_short_8", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/aput_wide/Test_aput_wide.java b/tools/vm-tests-tf/src/dot/junit/opcodes/aput_wide/Test_aput_wide.java
index 735b0e4..03da8ae 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/aput_wide/Test_aput_wide.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/aput_wide/Test_aput_wide.java
@@ -59,41 +59,24 @@
      * @title expected ArrayIndexOutOfBoundsException
      */
     public void testE1() {
-        T_aput_wide_1 t = new T_aput_wide_1();
-        long[] arr = new long[2];
-        try {
-            t.run(arr, 2, 100000000000l);
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aput_wide.d.T_aput_wide_1",
+                   ArrayIndexOutOfBoundsException.class, new long[2], 2, 100000000000l);
     }
 
     /**
      * @title expected NullPointerException
      */
     public void testE2() {
-        T_aput_wide_1 t = new T_aput_wide_1();
-        try {
-            t.run(null, 1, 100000000000l);
-            fail("expected NullPointerException");
-        } catch (NullPointerException np) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aput_wide.d.T_aput_wide_1", NullPointerException.class,
+                   null, 2, 100000000000l);
     }
 
     /**
      * @title expected ArrayIndexOutOfBoundsException (negative index)
      */
     public void testE3() {
-        T_aput_wide_1 t = new T_aput_wide_1();
-        long[] arr = new long[2];
-        try {
-            t.run(arr, -1, 100000000000l);
-            fail("expected ArrayIndexOutOfBoundsException");
-        } catch (ArrayIndexOutOfBoundsException aie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.aput_wide.d.T_aput_wide_1",
+                   ArrayIndexOutOfBoundsException.class, new long[2], -1, 100000000000l);
     }
 
 
@@ -102,12 +85,7 @@
      * @title types of arguments - array, double, long
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_wide.d.T_aput_wide_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_wide.d.T_aput_wide_3", VerifyError.class);
     }
 
     /**
@@ -115,12 +93,7 @@
      * @title types of arguments - array, int, int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_wide.d.T_aput_wide_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_wide.d.T_aput_wide_4", VerifyError.class);
     }
 
     /**
@@ -128,12 +101,7 @@
      * @title types of arguments - object, int, long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_wide.d.T_aput_wide_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_wide.d.T_aput_wide_5", VerifyError.class);
     }
 
     /**
@@ -142,12 +110,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_wide.d.T_aput_wide_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_wide.d.T_aput_wide_9", VerifyError.class);
     }
 
     /**
@@ -155,12 +118,7 @@
      * @title types of arguments - int[], int, long
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_wide.d.T_aput_wide_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_wide.d.T_aput_wide_7", VerifyError.class);
     }
 
     /**
@@ -168,12 +126,7 @@
      * @title types of arguments - array, reference, long
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_wide.d.T_aput_wide_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_wide.d.T_aput_wide_8", VerifyError.class);
     }
     
     /**
@@ -181,12 +134,7 @@
      * @title number of registers
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_wide.d.T_aput_wide_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_wide.d.T_aput_wide_10", VerifyError.class);
     }
 
     /**
@@ -195,11 +143,6 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.aput_wide.d.T_aput_wide_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.aput_wide.d.T_aput_wide_6", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/array_length/Test_array_length.java b/tools/vm-tests-tf/src/dot/junit/opcodes/array_length/Test_array_length.java
index f49cccb..e284880 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/array_length/Test_array_length.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/array_length/Test_array_length.java
@@ -45,28 +45,16 @@
      * @title expected NullPointerException
      */
     public void testNPE1() {
-        T_array_length_1 t = new T_array_length_1();
-        try {
-            t.run(null);
-            fail("NPE expected");
-        } catch (NullPointerException npe) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.array_length.d.T_array_length_1", NullPointerException.class,
+                   new Object[] {null});
     }
 
-
-
     /**
      * @constraint B1 
      * @title types of arguments - Object
      */
     public void testVFE1() {
-        try {
-            Class.forName("dxc.junit.opcodes.array_length.jm.T_array_length_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.array_length.d.T_array_length_2", VerifyError.class);
     }
 
     /**
@@ -74,12 +62,7 @@
      * @title types of arguments - int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dxc.junit.opcodes.array_length.jm.T_array_length_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.array_length.d.T_array_length_3", VerifyError.class);
     }
     
     /**
@@ -87,11 +70,6 @@
      * @title number of registers
      */
     public void testVFE3() {
-        try {
-            Class.forName("dxc.junit.opcodes.array_length.jm.T_array_length_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.array_length.d.T_array_length_5", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/check_cast/Test_check_cast.java b/tools/vm-tests-tf/src/dot/junit/opcodes/check_cast/Test_check_cast.java
index 78a0479..bbff2f2 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/check_cast/Test_check_cast.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/check_cast/Test_check_cast.java
@@ -56,13 +56,8 @@
      * @title expected ClassCastException
      */
     public void testE1() {
-        T_check_cast_1 t = new T_check_cast_1();
-        try {
-            t.run(t);
-            fail("expected ClassCastException");
-        } catch (ClassCastException iae) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.check_cast.d.T_check_cast_1", ClassCastException.class,
+                   new Integer(1));
     }
 
     /**
@@ -70,12 +65,7 @@
      * @title  constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.check_cast.d.T_check_cast_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.check_cast.d.T_check_cast_4", VerifyError.class);
     }
 
     /**
@@ -84,12 +74,7 @@
      * @title  type of argument - int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.check_cast.d.T_check_cast_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.check_cast.d.T_check_cast_5", VerifyError.class);
     }
 
     /**
@@ -98,12 +83,7 @@
      * @title  type of argument - long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.check_cast.d.T_check_cast_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.check_cast.d.T_check_cast_8", VerifyError.class);
     }
     
     /**
@@ -112,12 +92,7 @@
      * @title  number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.check_cast.d.T_check_cast_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.check_cast.d.T_check_cast_6", VerifyError.class);
     }
 
     /**
@@ -126,14 +101,7 @@
      */
     public void testVFE5() {
         //@uses dot.junit.opcodes.check_cast.TestStubs
-        //@uses dot.junit.opcodes.check_cast.d.T_check_cast_3
-        T_check_cast_3 t = new T_check_cast_3();
-        try {
-            t.run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError iae) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.check_cast.d.T_check_cast_3", IllegalAccessError.class);
     }
 
     /**
@@ -142,13 +110,7 @@
      * first access
      */
     public void testVFE6() {
-        T_check_cast_7 t = new T_check_cast_7();
-        try {
-            t.run();
-            fail("expected NoClassDefFoundError");
-        } catch (NoClassDefFoundError iae) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.check_cast.d.T_check_cast_7", NoClassDefFoundError.class);
     }
     
     /**
@@ -156,12 +118,7 @@
      * @title  constant pool type
      */    
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.check_cast.d.T_check_cast_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.check_cast.d.T_check_cast_9", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/cmp_long/Test_cmp_long.java b/tools/vm-tests-tf/src/dot/junit/opcodes/cmp_long/Test_cmp_long.java
index 5edd117..aea844b 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/cmp_long/Test_cmp_long.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/cmp_long/Test_cmp_long.java
@@ -100,12 +100,7 @@
      * @title types of arguments - float, long
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.cmp_long.d.T_cmp_long_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.cmp_long.d.T_cmp_long_3", VerifyError.class);
     }
 
     /**
@@ -113,12 +108,7 @@
      * @title types of arguments - int, long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.cmp_long.d.T_cmp_long_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.cmp_long.d.T_cmp_long_4", VerifyError.class);
     }
 
     /**
@@ -126,12 +116,7 @@
      * @title types of arguments - reference, long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.cmp_long.d.T_cmp_long_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.cmp_long.d.T_cmp_long_5", VerifyError.class);
     }
     
     /**
@@ -139,12 +124,7 @@
      * @title number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.cmp_long.d.T_cmp_long_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.cmp_long.d.T_cmp_long_6", VerifyError.class);
     }
 
     /**
@@ -153,11 +133,6 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.cmp_long.d.T_cmp_long_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.cmp_long.d.T_cmp_long_2", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/cmpg_double/Test_cmpg_double.java b/tools/vm-tests-tf/src/dot/junit/opcodes/cmpg_double/Test_cmpg_double.java
index 4afc0d2..c7f9946 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/cmpg_double/Test_cmpg_double.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/cmpg_double/Test_cmpg_double.java
@@ -94,12 +94,7 @@
      * @title  types of arguments - double, float
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.cmpg_double.d.T_cmpg_double_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.cmpg_double.d.T_cmpg_double_2", VerifyError.class);
     }
 
     /**
@@ -107,12 +102,7 @@
      * @title  number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.cmpg_double.d.T_cmpg_double_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.cmpg_double.d.T_cmpg_double_5", VerifyError.class);
     }
 
     /**
@@ -120,12 +110,7 @@
      * @title  types of arguments - double, reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.cmpg_double.d.T_cmpg_double_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.cmpg_double.d.T_cmpg_double_4", VerifyError.class);
     }
     
     /**
@@ -133,12 +118,7 @@
      * @title  types of arguments - int, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.cmpg_double.d.T_cmpg_double_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.cmpg_double.d.T_cmpg_double_6", VerifyError.class);
     }
 
     /**
@@ -147,12 +127,7 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.cmpg_double.d.T_cmpg_double_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.cmpg_double.d.T_cmpg_double_3", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/cmpg_float/Test_cmpg_float.java b/tools/vm-tests-tf/src/dot/junit/opcodes/cmpg_float/Test_cmpg_float.java
index 3e5f4af..49f8fe3 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/cmpg_float/Test_cmpg_float.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/cmpg_float/Test_cmpg_float.java
@@ -95,12 +95,7 @@
      * @title types of arguments - float, double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.cmpg_float.d.T_cmpg_float_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.cmpg_float.d.T_cmpg_float_2", VerifyError.class);
     }
 
     /**
@@ -108,12 +103,7 @@
      * @title types of arguments - long, float
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.cmpg_float.d.T_cmpg_float_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.cmpg_float.d.T_cmpg_float_3", VerifyError.class);
     }
 
     /**
@@ -121,12 +111,7 @@
      * @title types of arguments - reference, float
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.cmpg_float.d.T_cmpg_float_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.cmpg_float.d.T_cmpg_float_4", VerifyError.class);
     }
 
     /**
@@ -134,12 +119,7 @@
      * @title number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.cmpg_float.d.T_cmpg_float_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.cmpg_float.d.T_cmpg_float_5", VerifyError.class);
     }
 
     /**
@@ -148,12 +128,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.cmpg_float.d.T_cmpg_float_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.cmpg_float.d.T_cmpg_float_6", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/cmpl_double/Test_cmpl_double.java b/tools/vm-tests-tf/src/dot/junit/opcodes/cmpl_double/Test_cmpl_double.java
index efade2c..e3c9629 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/cmpl_double/Test_cmpl_double.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/cmpl_double/Test_cmpl_double.java
@@ -96,12 +96,7 @@
      * @title  types of arguments - double, float
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.cmpl_double.d.T_cmpl_double_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.cmpl_double.d.T_cmpl_double_2", VerifyError.class);
     }
 
     /**
@@ -109,12 +104,7 @@
     * @title number of registers
     */
     public void testVFE2() {
-       try {
-           Class.forName("dot.junit.opcodes.cmpl_double.d.T_cmpl_double_5");
-           fail("expected a verification exception");
-       } catch (Throwable t) {
-           DxUtil.checkVerifyException(t);
-       }
+        load("dot.junit.opcodes.cmpl_double.d.T_cmpl_double_5", VerifyError.class);
     }
 
     /**
@@ -122,12 +112,7 @@
      * @title  types of arguments - double, reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.cmpl_double.d.T_cmpl_double_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.cmpl_double.d.T_cmpl_double_4", VerifyError.class);
     }
 
     /**
@@ -135,12 +120,7 @@
      * @title  types of arguments - int, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.cmpl_double.d.T_cmpl_double_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.cmpl_double.d.T_cmpl_double_6", VerifyError.class);
     }
 
     /**
@@ -149,12 +129,7 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.cmpl_double.d.T_cmpl_double_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.cmpl_double.d.T_cmpl_double_3", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/cmpl_float/Test_cmpl_float.java b/tools/vm-tests-tf/src/dot/junit/opcodes/cmpl_float/Test_cmpl_float.java
index 0ef9efc..364dd75 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/cmpl_float/Test_cmpl_float.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/cmpl_float/Test_cmpl_float.java
@@ -94,12 +94,7 @@
      * @title  types of arguments - float, double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.cmpl_float.d.T_cmpl_float_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.cmpl_float.d.T_cmpl_float_2", VerifyError.class);
     }
 
     /**
@@ -107,12 +102,7 @@
      * @title types of arguments - long, float
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.cmpl_float.d.T_cmpl_float_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.cmpl_float.d.T_cmpl_float_3", VerifyError.class);
     }
 
     /**
@@ -120,12 +110,7 @@
      * @title  types of arguments - reference, float
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.cmpl_float.d.T_cmpl_float_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.cmpl_float.d.T_cmpl_float_4", VerifyError.class);
     }
     
     /**
@@ -133,12 +118,7 @@
      * @title number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.cmpl_float.d.T_cmpl_float_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.cmpl_float.d.T_cmpl_float_5", VerifyError.class);
     }
 
     /**
@@ -147,12 +127,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.cmpl_float.d.T_cmpl_float_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.cmpl_float.d.T_cmpl_float_6", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/const_16/Test_const_16.java b/tools/vm-tests-tf/src/dot/junit/opcodes/const_16/Test_const_16.java
index 00e6b78..3328118 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/const_16/Test_const_16.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/const_16/Test_const_16.java
@@ -37,12 +37,7 @@
      * @title  number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.const_16.d.T_const_16_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.const_16.d.T_const_16_3", VerifyError.class);
     }
     
     /**
@@ -52,12 +47,7 @@
      * other register involved in it becomes undefined
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.const_16.d.T_const_16_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.const_16.d.T_const_16_4", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/const_4/Test_const_4.java b/tools/vm-tests-tf/src/dot/junit/opcodes/const_4/Test_const_4.java
index d9bb26b..aad3a48 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/const_4/Test_const_4.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/const_4/Test_const_4.java
@@ -36,12 +36,7 @@
      * @title  number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.const_4.d.T_const_4_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.const_4.d.T_const_4_3", VerifyError.class);
     }
     
     /**
@@ -51,11 +46,6 @@
      * other register involved in it becomes undefined
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.const_4.d.T_const_4_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.const_4.d.T_const_4_4", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/const_class/Test_const_class.java b/tools/vm-tests-tf/src/dot/junit/opcodes/const_class/Test_const_class.java
index 93f5ee4..20fa270 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/const_class/Test_const_class.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/const_class/Test_const_class.java
@@ -46,15 +46,7 @@
      * @title Class definition not found
      */
     public void testE1() {
-        try {
-            T_const_class_6 t = new T_const_class_6();
-            t.run();
-            fail("expected a verification exception");
-        } catch (NoClassDefFoundError e) {
-            // expected
-        } catch(VerifyError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.const_class.d.T_const_class_6", NoClassDefFoundError.class);
     }
     
     /**
@@ -62,14 +54,7 @@
      */
     public void testE2() {
         //@uses dot.junit.opcodes.const_class.TestStubs
-        //@uses dot.junit.opcodes.const_class.d.T_const_class_7
-        try {
-            T_const_class_7 t = new T_const_class_7();
-            t.run();
-            fail("expected an IllegalAccessError exception");
-        } catch (IllegalAccessError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.const_class.d.T_const_class_7", IllegalAccessError.class);
     }
     
     /**
@@ -77,12 +62,7 @@
      * @title  number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.const_class.d.T_const_class_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.const_class.d.T_const_class_3", VerifyError.class);
     }
     
     /**
@@ -92,12 +72,7 @@
      * other register involved in it becomes undefined
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.const_class.d.T_const_class_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.const_class.d.T_const_class_4", VerifyError.class);
     }
     
     /**
@@ -105,12 +80,7 @@
      * @title  constant pool index
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.const_class.d.T_const_class_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.const_class.d.T_const_class_5", VerifyError.class);
     }
     
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/const_high16/Test_const_high16.java b/tools/vm-tests-tf/src/dot/junit/opcodes/const_high16/Test_const_high16.java
index 68340a8..642a8ef 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/const_high16/Test_const_high16.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/const_high16/Test_const_high16.java
@@ -34,12 +34,7 @@
      * @title  number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.const_high16.d.T_const_high16_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.const_high16.d.T_const_high16_3", VerifyError.class);
     }
     
     /**
@@ -49,12 +44,7 @@
      * other register involved in it becomes undefined
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.const_high16.d.T_const_high16_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.const_high16.d.T_const_high16_4", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/const_string/Test_const_string.java b/tools/vm-tests-tf/src/dot/junit/opcodes/const_string/Test_const_string.java
index b5c778d..5e76157 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/const_string/Test_const_string.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/const_string/Test_const_string.java
@@ -38,12 +38,7 @@
      * @title  number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.const_string.d.T_const_string_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.const_string.d.T_const_string_3", VerifyError.class);
     }
     
     /**
@@ -53,12 +48,7 @@
      * other register involved in it becomes undefined
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.const_string.d.T_const_string_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.const_string.d.T_const_string_4", VerifyError.class);
     }
     
     /**
@@ -66,12 +56,7 @@
      * @title  constant pool index
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.const_string.d.T_const_string_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.const_string.d.T_const_string_5", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/const_string_jumbo/Test_const_string_jumbo.java b/tools/vm-tests-tf/src/dot/junit/opcodes/const_string_jumbo/Test_const_string_jumbo.java
index 6234730..93dd391 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/const_string_jumbo/Test_const_string_jumbo.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/const_string_jumbo/Test_const_string_jumbo.java
@@ -38,12 +38,7 @@
      * @title  number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.const_string_jumbo.d.T_const_string_jumbo_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.const_string_jumbo.d.T_const_string_jumbo_3", VerifyError.class);
     }
     
     /**
@@ -53,12 +48,7 @@
      * other register involved in it becomes undefined
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.const_string_jumbo.d.T_const_string_jumbo_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.const_string_jumbo.d.T_const_string_jumbo_4", VerifyError.class);
     }
     
     /**
@@ -66,12 +56,7 @@
      * @title constant pool index
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.const_string_jumbo.d.T_const_string_jumbo_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.const_string_jumbo.d.T_const_string_jumbo_5", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/const_wide/Test_const_wide.java b/tools/vm-tests-tf/src/dot/junit/opcodes/const_wide/Test_const_wide.java
index 1ce3caa..f36a560 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/const_wide/Test_const_wide.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/const_wide/Test_const_wide.java
@@ -47,12 +47,7 @@
      * @title  number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.const_wide.d.T_const_wide_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.const_wide.d.T_const_wide_3", VerifyError.class);
     }
     
     /**
@@ -62,12 +57,7 @@
      * other register involved in it becomes undefined
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.const_wide.d.T_const_wide_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.const_wide.d.T_const_wide_4", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/const_wide_16/Test_const_wide_16.java b/tools/vm-tests-tf/src/dot/junit/opcodes/const_wide_16/Test_const_wide_16.java
index 941b00d..dff7947 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/const_wide_16/Test_const_wide_16.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/const_wide_16/Test_const_wide_16.java
@@ -37,12 +37,7 @@
      * @title  number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.const_wide_16.d.T_const_wide_16_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.const_wide_16.d.T_const_wide_16_3", VerifyError.class);
     }
     
     /**
@@ -52,12 +47,7 @@
      * other register involved in it becomes undefined
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.const_wide_16.d.T_const_wide_16_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.const_wide_16.d.T_const_wide_16_4", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/const_wide_32/Test_const_wide_32.java b/tools/vm-tests-tf/src/dot/junit/opcodes/const_wide_32/Test_const_wide_32.java
index 0847b3b..0a93390 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/const_wide_32/Test_const_wide_32.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/const_wide_32/Test_const_wide_32.java
@@ -36,12 +36,7 @@
      * @title  number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.const_wide_32.d.T_const_wide_32_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.const_wide_32.d.T_const_wide_32_3", VerifyError.class);
     }
     
     /**
@@ -51,12 +46,7 @@
      * other register involved in it becomes undefined
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.const_wide_32.d.T_const_wide_32_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.const_wide_32.d.T_const_wide_32_4", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/const_wide_high16/Test_const_wide_high16.java b/tools/vm-tests-tf/src/dot/junit/opcodes/const_wide_high16/Test_const_wide_high16.java
index 2dd3e32..7ece9ae 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/const_wide_high16/Test_const_wide_high16.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/const_wide_high16/Test_const_wide_high16.java
@@ -34,12 +34,7 @@
      * @title  number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.const_wide_high16.d.T_const_wide_high16_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.const_wide_high16.d.T_const_wide_high16_3", VerifyError.class);
     }
     
     /**
@@ -49,12 +44,7 @@
      * other register involved in it becomes undefined
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.const_wide_high16.d.T_const_wide_high16_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.const_wide_high16.d.T_const_wide_high16_4", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/div_double/Test_div_double.java b/tools/vm-tests-tf/src/dot/junit/opcodes/div_double/Test_div_double.java
index 1af5e66..090754a 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/div_double/Test_div_double.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/div_double/Test_div_double.java
@@ -131,12 +131,7 @@
      * @title  types of arguments - float / double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.div_double.d.T_div_double_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_double.d.T_div_double_2", VerifyError.class);
     }
 
     /**
@@ -144,12 +139,7 @@
      * @title  number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.div_double.d.T_div_double_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_double.d.T_div_double_5", VerifyError.class);
     }
 
     /**
@@ -157,12 +147,7 @@
      * @title  types of arguments - double / reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.div_double.d.T_div_double_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_double.d.T_div_double_4", VerifyError.class);
     }
     
     /**
@@ -170,12 +155,7 @@
      * @title  types of arguments - int / int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.div_double.d.T_div_double_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_double.d.T_div_double_6", VerifyError.class);
     }
 
     /**
@@ -184,12 +164,7 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.div_double.d.T_div_double_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_double.d.T_div_double_3", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/div_double_2addr/Test_div_double_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/div_double_2addr/Test_div_double_2addr.java
index dfd238e..864969e 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/div_double_2addr/Test_div_double_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/div_double_2addr/Test_div_double_2addr.java
@@ -131,12 +131,7 @@
      * @title  types of arguments - float / double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.div_double_2addr.d.T_div_double_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_double_2addr.d.T_div_double_2addr_2", VerifyError.class);
     }
 
     /**
@@ -144,12 +139,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.div_double_2addr.d.T_div_double_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_double_2addr.d.T_div_double_2addr_5", VerifyError.class);
     }
 
     /**
@@ -157,12 +147,7 @@
      * @title types of arguments - double / reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.div_double_2addr.d.T_div_double_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_double_2addr.d.T_div_double_2addr_4", VerifyError.class);
     }
 
     /**
@@ -170,12 +155,7 @@
      * @title  types of arguments - int / int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.div_double_2addr.d.T_div_double_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_double_2addr.d.T_div_double_2addr_6", VerifyError.class);
     }
 
     /**
@@ -184,12 +164,7 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.div_double_2addr.d.T_div_double_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_double_2addr.d.T_div_double_2addr_3", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/div_float/Test_div_float.java b/tools/vm-tests-tf/src/dot/junit/opcodes/div_float/Test_div_float.java
index f4672af..e3bb16e 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/div_float/Test_div_float.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/div_float/Test_div_float.java
@@ -129,12 +129,7 @@
      * @title  types of arguments - float / double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.div_float.d.T_div_float_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_float.d.T_div_float_2", VerifyError.class);
     }
 
     /**
@@ -142,12 +137,7 @@
      * @title  types of arguments - long / float
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.div_float.d.T_div_float_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_float.d.T_div_float_3", VerifyError.class);
     }
 
     /**
@@ -155,12 +145,7 @@
      * @title types of arguments - reference / float
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.div_float.d.T_div_float_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_float.d.T_div_float_4", VerifyError.class);
     }
 
     /**
@@ -168,12 +153,7 @@
      * @title number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.div_float.d.T_div_float_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_float.d.T_div_float_6", VerifyError.class);
     }
 
     /**
@@ -182,12 +162,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.div_float.d.T_div_float_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_float.d.T_div_float_5", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/div_float_2addr/Test_div_float_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/div_float_2addr/Test_div_float_2addr.java
index f4c3c9c..3746d9d 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/div_float_2addr/Test_div_float_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/div_float_2addr/Test_div_float_2addr.java
@@ -129,12 +129,7 @@
      * @title types of arguments - float / double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.div_float_2addr.d.T_div_float_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_float_2addr.d.T_div_float_2addr_2", VerifyError.class);
     }
 
     /**
@@ -142,12 +137,7 @@
      * @title types of arguments - long / float
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.div_float_2addr.d.T_div_float_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_float_2addr.d.T_div_float_2addr_3", VerifyError.class);
     }
 
     /**
@@ -155,12 +145,7 @@
      * @title types of arguments - reference / float
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.div_float_2addr.d.T_div_float_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_float_2addr.d.T_div_float_2addr_4", VerifyError.class);
     }
     
     /**
@@ -168,12 +153,7 @@
      * @title number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.div_float_2addr.d.T_div_float_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_float_2addr.d.T_div_float_2addr_6", VerifyError.class);
     }
 
     /**
@@ -182,12 +162,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.div_float_2addr.d.T_div_float_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_float_2addr.d.T_div_float_2addr_5", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/div_int/Test_div_int.java b/tools/vm-tests-tf/src/dot/junit/opcodes/div_int/Test_div_int.java
index 6fc8e05..ef375f5 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/div_int/Test_div_int.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/div_int/Test_div_int.java
@@ -125,28 +125,15 @@
      * @title Divisor is 0
      */
     public void testE1() {
-        T_div_int_1 t = new T_div_int_1();
-        try {
-            t.run(1, 0);
-            fail("expected ArithmeticException");
-        } catch (ArithmeticException ae) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.div_int.d.T_div_int_1", ArithmeticException.class, 1, 0);
     }
 
-    
-
     /**
      * @constraint B1 
      * @title types of arguments - int / double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.div_int.d.T_div_int_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_int.d.T_div_int_2", VerifyError.class);
     }
 
     /**
@@ -154,12 +141,7 @@
      * @title types of arguments - long / int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.div_int.d.T_div_int_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_int.d.T_div_int_3", VerifyError.class);
     }
 
     /**
@@ -167,12 +149,7 @@
      * @title types of arguments - reference / int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.div_int.d.T_div_int_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_int.d.T_div_int_4", VerifyError.class);
     }
 
     /**
@@ -180,12 +157,7 @@
      * @title  number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.div_int.d.T_div_int_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_int.d.T_div_int_6", VerifyError.class);
     }
 
     /**
@@ -194,12 +166,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.div_int.d.T_div_int_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_int.d.T_div_int_5", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/div_int_2addr/Test_div_int_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/div_int_2addr/Test_div_int_2addr.java
index d43aadd..6a27841 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/div_int_2addr/Test_div_int_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/div_int_2addr/Test_div_int_2addr.java
@@ -123,28 +123,16 @@
      * @title Divisor is 0
      */
     public void testE1() {
-        T_div_int_2addr_1 t = new T_div_int_2addr_1();
-        try {
-            t.run(1, 0);
-            fail("expected ArithmeticException");
-        } catch (ArithmeticException ae) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.div_int_2addr.d.T_div_int_2addr_1", ArithmeticException.class,
+                   1, 0);
     }
 
-    
-
     /**
      * @constraint B1 
      * @title types of arguments - int, double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.div_int_2addr.d.T_div_int_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_int_2addr.d.T_div_int_2addr_2", VerifyError.class);
     }
 
     /**
@@ -152,12 +140,7 @@
      * @title  types of arguments - long, int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.div_int_2addr.d.T_div_int_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_int_2addr.d.T_div_int_2addr_3", VerifyError.class);
     }
 
     /**
@@ -165,12 +148,7 @@
      * @title  types of arguments - reference, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.div_int_2addr.d.T_div_int_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_int_2addr.d.T_div_int_2addr_4", VerifyError.class);
     }
     
     /**
@@ -178,12 +156,7 @@
      * @title number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.div_int_2addr.d.T_div_int_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_int_2addr.d.T_div_int_2addr_6", VerifyError.class);
     }
 
     /**
@@ -192,11 +165,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.div_int_2addr.d.T_div_int_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_int_2addr.d.T_div_int_2addr_5", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/div_int_lit16/Test_div_int_lit16.java b/tools/vm-tests-tf/src/dot/junit/opcodes/div_int_lit16/Test_div_int_lit16.java
index 0b03a93..75e0016 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/div_int_lit16/Test_div_int_lit16.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/div_int_lit16/Test_div_int_lit16.java
@@ -136,28 +136,16 @@
      * @title Divisor is 0
      */
     public void testE1() {
-        T_div_int_lit16_13 t = new T_div_int_lit16_13();
-        try {
-            t.run();
-            fail("expected ArithmeticException");
-        } catch (ArithmeticException ae) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.div_int_lit16.d.T_div_int_lit16_13",
+                   ArithmeticException.class);
     }
 
-    
-
     /**
      * @constraint B1 
      * @title types of arguments - int / double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.div_int_lit16.d.T_div_int_lit16_14");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_int_lit16.d.T_div_int_lit16_14", VerifyError.class);
     }
 
     /**
@@ -165,12 +153,7 @@
      * @title types of arguments - long / int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.div_int_lit16.d.T_div_int_lit16_15");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_int_lit16.d.T_div_int_lit16_15", VerifyError.class);
     }
 
     /**
@@ -178,12 +161,7 @@
      * @title types of arguments - reference / int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.div_int_lit16.d.T_div_int_lit16_16");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_int_lit16.d.T_div_int_lit16_16", VerifyError.class);
     }
 
     /**
@@ -191,12 +169,7 @@
      * @title  number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.div_int_lit16.d.T_div_int_lit16_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_int_lit16.d.T_div_int_lit16_18", VerifyError.class);
     }
 
     /**
@@ -205,11 +178,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.div_int_lit16.d.T_div_int_lit16_17");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_int_lit16.d.T_div_int_lit16_17", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/div_int_lit8/Test_div_int_lit8.java b/tools/vm-tests-tf/src/dot/junit/opcodes/div_int_lit8/Test_div_int_lit8.java
index e86ea75..14d4d4c 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/div_int_lit8/Test_div_int_lit8.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/div_int_lit8/Test_div_int_lit8.java
@@ -135,13 +135,7 @@
      * @title Divisor is 0
      */
     public void testE1() {
-        T_div_int_lit8_13 t = new T_div_int_lit8_13();
-        try {
-            t.run();
-            fail("expected ArithmeticException");
-        } catch (ArithmeticException ae) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.div_int_lit8.d.T_div_int_lit8_13", ArithmeticException.class);
     }
 
     
@@ -151,12 +145,7 @@
      * @title types of arguments - int / double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.div_int_lit8.d.T_div_int_lit8_14");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_int_lit8.d.T_div_int_lit8_14", VerifyError.class);
     }
 
     /**
@@ -164,12 +153,7 @@
      * @title types of arguments - long / int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.div_int_lit8.d.T_div_int_lit8_15");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_int_lit8.d.T_div_int_lit8_15", VerifyError.class);
     }
 
     /**
@@ -177,12 +161,7 @@
      * @title types of arguments - reference / int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.div_int_lit8.d.T_div_int_lit8_16");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_int_lit8.d.T_div_int_lit8_16", VerifyError.class);
     }
 
     /**
@@ -190,12 +169,7 @@
      * @title  number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.div_int_lit8.d.T_div_int_lit8_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_int_lit8.d.T_div_int_lit8_18", VerifyError.class);
     }
 
     /**
@@ -204,11 +178,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.div_int_lit8.d.T_div_int_lit8_17");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_int_lit8.d.T_div_int_lit8_17", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/div_long/Test_div_long.java b/tools/vm-tests-tf/src/dot/junit/opcodes/div_long/Test_div_long.java
index ce3713c..46c0c94 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/div_long/Test_div_long.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/div_long/Test_div_long.java
@@ -123,28 +123,16 @@
      * @title Divisor is 0
      */
     public void testE1() {
-        T_div_long_1 t = new T_div_long_1();
-        try {
-            t.run(12345678912345l, 0);
-            fail("expected ArithmeticException");
-        } catch (ArithmeticException ae) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.div_long.d.T_div_long_1", ArithmeticException.class,
+                   12345678912345l, 0);
     }
 
-    
-
     /**
      * @constraint A24 
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.div_long.d.T_div_long_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_long.d.T_div_long_6", VerifyError.class);
     }
 
     /**
@@ -152,12 +140,7 @@
      * @title types of arguments - int / long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.div_long.d.T_div_long_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_long.d.T_div_long_3", VerifyError.class);
     }
 
     /**
@@ -165,12 +148,7 @@
      * @title types of arguments - float / long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.div_long.d.T_div_long_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_long.d.T_div_long_4", VerifyError.class);
     }
 
     /**
@@ -178,12 +156,7 @@
      * @title types of arguments - reference / long
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.div_long.d.T_div_long_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_long.d.T_div_long_5", VerifyError.class);
     }
 
     /**
@@ -192,12 +165,7 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.div_long.d.T_div_long_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_long.d.T_div_long_2", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/div_long_2addr/Test_div_long_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/div_long_2addr/Test_div_long_2addr.java
index 4bc3cf1..ca446fd 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/div_long_2addr/Test_div_long_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/div_long_2addr/Test_div_long_2addr.java
@@ -122,13 +122,8 @@
      * @title Divisor is 0
      */
     public void testE1() {
-        T_div_long_2addr_1 t = new T_div_long_2addr_1();
-        try {
-            t.run(12345678912345l, 0);
-            fail("expected ArithmeticException");
-        } catch (ArithmeticException ae) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.div_long_2addr.d.T_div_long_2addr_1",
+                   ArithmeticException.class, 12345678912345l, 0);
     }
 
     
@@ -138,12 +133,7 @@
      * @title  number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.div_long_2addr.d.T_div_long_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_long_2addr.d.T_div_long_2addr_6", VerifyError.class);
     }
 
     /**
@@ -151,12 +141,7 @@
      * @title types of arguments - int / long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.div_long_2addr.d.T_div_long_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_long_2addr.d.T_div_long_2addr_3", VerifyError.class);
     }
 
     /**
@@ -164,12 +149,7 @@
      * @title  types of arguments - float / long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.div_long_2addr.d.T_div_long_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_long_2addr.d.T_div_long_2addr_4", VerifyError.class);
     }
 
     /**
@@ -177,12 +157,7 @@
      * @title types of arguments - reference / long
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.div_long_2addr.d.T_div_long_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_long_2addr.d.T_div_long_2addr_5", VerifyError.class);
     }
 
     /**
@@ -191,12 +166,7 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.div_long_2addr.d.T_div_long_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.div_long_2addr.d.T_div_long_2addr_2", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/double_to_float/Test_double_to_float.java b/tools/vm-tests-tf/src/dot/junit/opcodes/double_to_float/Test_double_to_float.java
index bcaa4c8..bf0c070 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/double_to_float/Test_double_to_float.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/double_to_float/Test_double_to_float.java
@@ -110,12 +110,7 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.double_to_float.d.T_double_to_float_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.double_to_float.d.T_double_to_float_3", VerifyError.class);
     }
 
     /**
@@ -123,12 +118,7 @@
      * @title  type of argument - float
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.double_to_float.d.T_double_to_float_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.double_to_float.d.T_double_to_float_2", VerifyError.class);
     }
 
     /**
@@ -137,12 +127,7 @@
      * @title  number of registers
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.double_to_float.d.T_double_to_float_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.double_to_float.d.T_double_to_float_5", VerifyError.class);
     }
 
     /**
@@ -151,12 +136,7 @@
      * @title  type of argument - reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.double_to_float.d.T_double_to_float_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.double_to_float.d.T_double_to_float_4", VerifyError.class);
     }
     
     /**
@@ -165,12 +145,7 @@
      * @title  type of argument - int
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.double_to_float.d.T_double_to_float_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.double_to_float.d.T_double_to_float_6", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/double_to_int/Test_double_to_int.java b/tools/vm-tests-tf/src/dot/junit/opcodes/double_to_int/Test_double_to_int.java
index ccd8618..cb0a5a6 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/double_to_int/Test_double_to_int.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/double_to_int/Test_double_to_int.java
@@ -102,12 +102,7 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.double_to_int.d.T_double_to_int_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.double_to_int.d.T_double_to_int_3", VerifyError.class);
     }
 
     /**
@@ -115,12 +110,7 @@
      * @title  type of argument - float
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.double_to_int.d.T_double_to_int_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.double_to_int.d.T_double_to_int_2", VerifyError.class);
     }
 
     /**
@@ -129,12 +119,7 @@
      * @title  number of registers
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.double_to_int.d.T_double_to_int_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.double_to_int.d.T_double_to_int_5", VerifyError.class);
     }
 
     /**
@@ -143,12 +128,7 @@
      * @title  type of argument - reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.double_to_int.d.T_double_to_int_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.double_to_int.d.T_double_to_int_4", VerifyError.class);
     }
     
     /**
@@ -157,12 +137,7 @@
      * @title  type of argument - reference
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.double_to_int.d.T_double_to_int_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.double_to_int.d.T_double_to_int_6", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/double_to_long/Test_double_to_long.java b/tools/vm-tests-tf/src/dot/junit/opcodes/double_to_long/Test_double_to_long.java
index 0785280..5e98b03 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/double_to_long/Test_double_to_long.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/double_to_long/Test_double_to_long.java
@@ -99,12 +99,7 @@
      * @title  type of argument - float
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.double_to_long.d.T_double_to_long_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.double_to_long.d.T_double_to_long_2", VerifyError.class);
     }
 
     /**
@@ -113,12 +108,7 @@
      * @title  number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.double_to_long.d.T_double_to_long_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.double_to_long.d.T_double_to_long_5", VerifyError.class);
     }
 
     /**
@@ -127,12 +117,7 @@
      * @title  type of argument - reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.double_to_long.d.T_double_to_long_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.double_to_long.d.T_double_to_long_4", VerifyError.class);
     }
 
     
@@ -142,12 +127,7 @@
      * @title  type of argument - int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.double_to_long.d.T_double_to_long_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.double_to_long.d.T_double_to_long_6", VerifyError.class);
     }
 
     /**
@@ -156,11 +136,6 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.double_to_long.d.T_double_to_long_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.double_to_long.d.T_double_to_long_3", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/fill_array_data/Test_fill_array_data.java b/tools/vm-tests-tf/src/dot/junit/opcodes/fill_array_data/Test_fill_array_data.java
index 5bac3cd..7c22076 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/fill_array_data/Test_fill_array_data.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/fill_array_data/Test_fill_array_data.java
@@ -88,12 +88,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.fill_array_data.d.T_fill_array_data_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.fill_array_data.d.T_fill_array_data_3", VerifyError.class);
     }
 
     /**
@@ -101,12 +96,7 @@
      * @title type of argument - double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.fill_array_data.d.T_fill_array_data_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.fill_array_data.d.T_fill_array_data_4", VerifyError.class);
     }
     
     /**
@@ -114,12 +104,7 @@
      * @title type of argument - long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.fill_array_data.d.T_fill_array_data_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.fill_array_data.d.T_fill_array_data_5", VerifyError.class);
     }
     
     /**
@@ -127,12 +112,7 @@
      * @title type of argument - reference (not array)
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.fill_array_data.d.T_fill_array_data_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.fill_array_data.d.T_fill_array_data_6", VerifyError.class);
     }
     
     /**
@@ -140,12 +120,7 @@
      * @title array of Objects
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.fill_array_data.d.T_fill_array_data_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.fill_array_data.d.T_fill_array_data_7", VerifyError.class);
     }
     
     /**
@@ -153,12 +128,7 @@
      * @title array type and data size shall be consistent
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.fill_array_data.d.T_fill_array_data_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.fill_array_data.d.T_fill_array_data_8", VerifyError.class);
     }
 
     /**
@@ -166,12 +136,7 @@
      * @title offset to table shall be inside method
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.fill_array_data.d.T_fill_array_data_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.fill_array_data.d.T_fill_array_data_9", VerifyError.class);
     }
 
     /**
@@ -179,12 +144,7 @@
      * @title the size and the list must be consistent. 
      */
     public void testVFE9() {
-        try {
-            Class.forName("dot.junit.opcodes.fill_array_data.d.T_fill_array_data_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.fill_array_data.d.T_fill_array_data_11", VerifyError.class);
     }
 
     
@@ -193,12 +153,7 @@
      * @title packed-switch-data pseudo-instructions must not be reachable by control flow 
      */
     public void testVFE10() {
-        try {
-            Class.forName("dot.junit.opcodes.fill_array_data.d.T_fill_array_data_12");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.fill_array_data.d.T_fill_array_data_12", VerifyError.class);
     }
     
     /**
@@ -206,11 +161,6 @@
      * @title table has wrong ident code
      */
     public void testVFE11() {
-        try {
-            Class.forName("dot.junit.opcodes.fill_array_data.d.T_fill_array_data_13");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.fill_array_data.d.T_fill_array_data_13", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/filled_new_array/Test_filled_new_array.java b/tools/vm-tests-tf/src/dot/junit/opcodes/filled_new_array/Test_filled_new_array.java
index b17c29b..8a85a6d 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/filled_new_array/Test_filled_new_array.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/filled_new_array/Test_filled_new_array.java
@@ -54,12 +54,7 @@
      * @title invalid constant pool index
      */
     public void testVFE1() {
-         try {
-             Class.forName("dot.junit.opcodes.filled_new_array.d.T_filled_new_array_3");
-             fail("expected a verification exception");
-         } catch (Throwable t) {
-             DxUtil.checkVerifyException(t);
-         }
+        load("dot.junit.opcodes.filled_new_array.d.T_filled_new_array_3", VerifyError.class);
     }
 
     /**
@@ -67,12 +62,7 @@
      * @title  number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.filled_new_array.d.T_filled_new_array_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.filled_new_array.d.T_filled_new_array_4", VerifyError.class);
  
     }
     
@@ -81,12 +71,7 @@
      * @title try to pass obj ref instead of int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.filled_new_array.d.T_filled_new_array_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.filled_new_array.d.T_filled_new_array_5", VerifyError.class);
     }
     
     /**
@@ -94,12 +79,7 @@
      * @title try to pass long instead of int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.filled_new_array.d.T_filled_new_array_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.filled_new_array.d.T_filled_new_array_6", VerifyError.class);
     }
     
     /**
@@ -107,12 +87,7 @@
      * @title try to create non-array type
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.filled_new_array.d.T_filled_new_array_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.filled_new_array.d.T_filled_new_array_7", VerifyError.class);
     }
     
     /**
@@ -120,12 +95,7 @@
      * @title invalid arg count
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.filled_new_array.d.T_filled_new_array_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.filled_new_array.d.T_filled_new_array_8", VerifyError.class);
     }
     
     /**
@@ -133,12 +103,7 @@
      * @title attempt to instantiate String[] and fill it with reference to assignment-incompatible class
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.filled_new_array.d.T_filled_new_array_9");
-            fail("expected a verification exception"); 
-        } catch(Throwable t) { 
-            DxUtil.checkVerifyException(t);    
-        }
+        load("dot.junit.opcodes.filled_new_array.d.T_filled_new_array_9", VerifyError.class);
     }
     
     /**
@@ -146,14 +111,8 @@
      * @title attempt to instantiate array of non-existent class
      */
     public void testVFE8() {
-        //@uses dot.junit.opcodes.filled_new_array.d.T_filled_new_array_10
-        try {
-            T_filled_new_array_10 T = new T_filled_new_array_10();
-            T.run();
-            fail("expected a NoClassDefFoundError exception");
-        } catch(NoClassDefFoundError t) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.filled_new_array.d.T_filled_new_array_10",
+                   NoClassDefFoundError.class);
     }
     
     /**
@@ -161,15 +120,9 @@
      * @title attempt to instantiate array of inaccessible class
      */
     public void testVFE9() {
-        //@uses dot.junit.opcodes.filled_new_array.d.T_filled_new_array_11
         //@uses dot.junit.opcodes.filled_new_array.TestStubs
-        try {
-            T_filled_new_array_11 T = new T_filled_new_array_11();
-            T.run();
-            fail("expected a IllegalAccessError exception");
-        } catch(IllegalAccessError t) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.filled_new_array.d.T_filled_new_array_11",
+                   IllegalAccessError.class);
     }
     
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/filled_new_array_range/Test_filled_new_array_range.java b/tools/vm-tests-tf/src/dot/junit/opcodes/filled_new_array_range/Test_filled_new_array_range.java
index 84b1379..b6da488 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/filled_new_array_range/Test_filled_new_array_range.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/filled_new_array_range/Test_filled_new_array_range.java
@@ -54,12 +54,8 @@
      * @title invalid constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.filled_new_array_range.d.T_filled_new_array_range_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.filled_new_array_range.d.T_filled_new_array_range_3",
+             VerifyError.class);
     }
 
     /**
@@ -67,12 +63,8 @@
      * @title  number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.filled_new_array_range.d.T_filled_new_array_range_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.filled_new_array_range.d.T_filled_new_array_range_4",
+             VerifyError.class);
     }
     
     /**
@@ -80,12 +72,8 @@
      * @title try to pass obj ref instead of int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.filled_new_array_range.d.T_filled_new_array_range_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.filled_new_array_range.d.T_filled_new_array_range_5",
+             VerifyError.class);
     }
     
     /**
@@ -93,12 +81,8 @@
      * @title try to pass long instead of int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.filled_new_array_range.d.T_filled_new_array_range_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.filled_new_array_range.d.T_filled_new_array_range_6",
+             VerifyError.class);
     }
     
     /**
@@ -106,12 +90,8 @@
      * @title try to create non-array type
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.filled_new_array_range.d.T_filled_new_array_range_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.filled_new_array_range.d.T_filled_new_array_range_7",
+             VerifyError.class);
     }
     
     /**
@@ -119,12 +99,8 @@
      * @title invalid arg count
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.filled_new_array_range.d.T_filled_new_array_range_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.filled_new_array_range.d.T_filled_new_array_range_8",
+             VerifyError.class);
     }
     
     /**
@@ -132,12 +108,8 @@
      * @title attempt to instantiate String[] and fill it with reference to assignment-incompatible class
      */
     public void testVFE7() {
-        try {
-        	Class.forName("dot.junit.opcodes.filled_new_array_range.d.T_filled_new_array_range_9");
-        	fail("expected a verification exception"); 
-        } catch(Throwable t) { 
-        	DxUtil.checkVerifyException(t);	
-        }
+        load("dot.junit.opcodes.filled_new_array_range.d.T_filled_new_array_range_9",
+             VerifyError.class);
     }
     
     /**
@@ -145,13 +117,8 @@
      * @title attempt to instantiate array of non-existent class
      */
     public void testVFE8() {
-        T_filled_new_array_range_10 t = new T_filled_new_array_range_10();
-        try {
-            t.run();
-            fail("expected NoClassDefFoundError exception");
-        } catch (NoClassDefFoundError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.filled_new_array_range.d.T_filled_new_array_range_10",
+                   NoClassDefFoundError.class);
     }
 
     /**
@@ -159,14 +126,8 @@
      * @title attempt to instantiate array of inaccessible class
      */
     public void testVFE9() {
-        //@uses dot.junit.opcodes.filled_new_array_range.d.T_filled_new_array_range_11
         //@uses dot.junit.opcodes.filled_new_array_range.TestStubs
-        T_filled_new_array_range_11 t = new T_filled_new_array_range_11();
-        try {
-            t.run();
-            fail("expected IllegalAccessError exception");
-        } catch (IllegalAccessError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.filled_new_array_range.d.T_filled_new_array_range_11",
+                   IllegalAccessError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/float_to_double/Test_float_to_double.java b/tools/vm-tests-tf/src/dot/junit/opcodes/float_to_double/Test_float_to_double.java
index 4f53011..1c4d788 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/float_to_double/Test_float_to_double.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/float_to_double/Test_float_to_double.java
@@ -103,12 +103,7 @@
      * @title type of argument - double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.float_to_double.d.T_float_to_double_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.float_to_double.d.T_float_to_double_2", VerifyError.class);
     }
 
     /**
@@ -117,12 +112,7 @@
      * @title type of argument - long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.float_to_double.d.T_float_to_double_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.float_to_double.d.T_float_to_double_3", VerifyError.class);
     }
 
     /**
@@ -130,12 +120,7 @@
      * @title number of registers
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.float_to_double.d.T_float_to_double_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.float_to_double.d.T_float_to_double_4", VerifyError.class);
     }
 
     /**
@@ -143,12 +128,7 @@
      * @title type of argument - reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.float_to_double.d.T_float_to_double_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.float_to_double.d.T_float_to_double_5", VerifyError.class);
     }
     
     /**
@@ -156,12 +136,7 @@
      * @title number of registers
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.float_to_double.d.T_float_to_double_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.float_to_double.d.T_float_to_double_6", VerifyError.class);
     }
 
     /**
@@ -170,12 +145,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.float_to_double.d.T_float_to_double_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.float_to_double.d.T_float_to_double_7", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/float_to_int/Test_float_to_int.java b/tools/vm-tests-tf/src/dot/junit/opcodes/float_to_int/Test_float_to_int.java
index e8b7f86..0c0b8cc 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/float_to_int/Test_float_to_int.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/float_to_int/Test_float_to_int.java
@@ -101,12 +101,7 @@
      * @title type of argument - double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.float_to_int.d.T_float_to_int_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.float_to_int.d.T_float_to_int_2", VerifyError.class);
     }
 
     /**
@@ -115,12 +110,7 @@
      * @title  type of argument - long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.float_to_int.d.T_float_to_int_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.float_to_int.d.T_float_to_int_3", VerifyError.class);
     }
 
     /**
@@ -129,12 +119,7 @@
      * @title type of argument - reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.float_to_int.d.T_float_to_int_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.float_to_int.d.T_float_to_int_4", VerifyError.class);
     }
     
     /**
@@ -142,12 +127,7 @@
      * @title number of registers
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.float_to_int.d.T_float_to_int_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.float_to_int.d.T_float_to_int_6", VerifyError.class);
     }
 
     /**
@@ -156,11 +136,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.float_to_int.d.T_float_to_int_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.float_to_int.d.T_float_to_int_5", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/float_to_long/Test_float_to_long.java b/tools/vm-tests-tf/src/dot/junit/opcodes/float_to_long/Test_float_to_long.java
index 9627d82..39d4cf8 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/float_to_long/Test_float_to_long.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/float_to_long/Test_float_to_long.java
@@ -99,13 +99,7 @@
      * @title number of arguments
      */
     public void testVFE1() {
-        try
-        {
-            Class.forName("dxc.junit.opcodes.float_to_long.jm.T_float_to_long_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.float_to_long.d.T_float_to_long_2", VerifyError.class);
     }
     
     
@@ -115,13 +109,7 @@
      * @title type of argument - double
      */
     public void testVFE2() {
-        try
-        {
-            Class.forName("dot.junit.opcodes.float_to_long.d.T_float_to_long_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.float_to_long.d.T_float_to_long_2", VerifyError.class);
     }
     
     /**
@@ -130,13 +118,7 @@
      * @title type of argument - long
      */
     public void testVFE3() {
-        try
-        {
-            Class.forName("dot.junit.opcodes.float_to_long.d.T_float_to_long_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.float_to_long.d.T_float_to_long_3", VerifyError.class);
     }
     
     /**
@@ -144,13 +126,7 @@
      * @title number of registers
      */
     public void testVFE4() {
-        try
-        {
-            Class.forName("dot.junit.opcodes.float_to_long.d.T_float_to_long_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.float_to_long.d.T_float_to_long_4", VerifyError.class);
     }
     
     /**
@@ -158,13 +134,7 @@
      * @title type of argument - reference
      */
     public void testVFE5() {
-        try
-        {
-            Class.forName("dot.junit.opcodes.float_to_long.d.T_float_to_long_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.float_to_long.d.T_float_to_long_5", VerifyError.class);
     }
 
     /**
@@ -172,12 +142,7 @@
      * @title  number of registers
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.float_to_long.d.T_float_to_long_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.float_to_long.d.T_float_to_long_6", VerifyError.class);
     }
 
     /**
@@ -186,11 +151,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.float_to_long.d.T_float_to_long_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.float_to_long.d.T_float_to_long_7", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/goto_16/Test_goto_16.java b/tools/vm-tests-tf/src/dot/junit/opcodes/goto_16/Test_goto_16.java
index 2891fc4..48f3b71 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/goto_16/Test_goto_16.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/goto_16/Test_goto_16.java
@@ -35,12 +35,7 @@
         * @title branch target is inside instruction
         */
        public void testVFE1() {
-           try {
-               Class.forName("dot.junit.opcodes.goto_16.d.T_goto_16_3");
-               fail("expected a verification exception");
-           } catch (Throwable t) {
-               DxUtil.checkVerifyException(t);
-           }
+        load("dot.junit.opcodes.goto_16.d.T_goto_16_3", VerifyError.class);
        }
 
        /**
@@ -48,12 +43,7 @@
         * @title branch target shall be inside the method
         */
        public void testVFE2() {
-           try {
-               Class.forName("dot.junit.opcodes.goto_16.d.T_goto_16_2");
-               fail("expected a verification exception");
-           } catch (Throwable t) {
-               DxUtil.checkVerifyException(t);
-           }
+        load("dot.junit.opcodes.goto_16.d.T_goto_16_2", VerifyError.class);
        }
 
        /**
@@ -61,11 +51,6 @@
         * @title zero offset
         */
        public void testVFE3() {
-           try {
-               Class.forName("dot.junit.opcodes.goto_16.d.T_goto_16_4");
-               fail("expected a verification exception");
-           } catch (Throwable t) {
-               DxUtil.checkVerifyException(t);
-           }
+        load("dot.junit.opcodes.goto_16.d.T_goto_16_4", VerifyError.class);
        }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/goto_32/Test_goto_32.java b/tools/vm-tests-tf/src/dot/junit/opcodes/goto_32/Test_goto_32.java
index 5f7a4dc..0e8b373 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/goto_32/Test_goto_32.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/goto_32/Test_goto_32.java
@@ -35,12 +35,7 @@
         * @title branch target is inside instruction
         */
        public void testVFE1() {
-           try {
-               Class.forName("dot.junit.opcodes.goto_32.d.T_goto_32_2");
-               fail("expected a verification exception");
-           } catch (Throwable t) {
-               DxUtil.checkVerifyException(t);
-           }
+        load("dot.junit.opcodes.goto_32.d.T_goto_32_2", VerifyError.class);
        }
 
        /**
@@ -48,12 +43,7 @@
         * @title branch target shall be inside the method
         */
        public void testVFE2() {
-           try {
-               Class.forName("dot.junit.opcodes.goto_32.d.T_goto_32_3");
-               fail("expected a verification exception");
-           } catch (Throwable t) {
-               DxUtil.checkVerifyException(t);
-           }
+        load("dot.junit.opcodes.goto_32.d.T_goto_32_3", VerifyError.class);
        }
 
        /**
@@ -62,12 +52,7 @@
         * @title zero offset - no exception expected
         */
        public void testVFE3() {
-           try {
-               Class.forName("dot.junit.opcodes.goto_32.d.T_goto_32_4");
-               // no exception is expected
-           } catch (Throwable t) {
-               fail("not expected" + t);
-           }
+           load("dot.junit.opcodes.goto_32.d.T_goto_32_4", null);
        }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/if_eq/Test_if_eq.java b/tools/vm-tests-tf/src/dot/junit/opcodes/if_eq/Test_if_eq.java
index bb89f67..c68525a 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/if_eq/Test_if_eq.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/if_eq/Test_if_eq.java
@@ -125,12 +125,7 @@
      * @title  number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.if_eq.d.T_if_eq_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_eq.d.T_if_eq_5", VerifyError.class);
     }
 
 
@@ -139,12 +134,7 @@
      * @title  types of arguments - int, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.if_eq.d.T_if_eq_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_eq.d.T_if_eq_7", VerifyError.class);
     }
 
     /**
@@ -152,12 +142,7 @@
      * @title  types of arguments - long, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.if_eq.d.T_if_eq_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_eq.d.T_if_eq_8", VerifyError.class);
     }
     
     /**
@@ -165,12 +150,7 @@
      * @title  types of arguments - int, reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.if_eq.d.T_if_eq_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_eq.d.T_if_eq_9", VerifyError.class);
     }
 
     /**
@@ -178,12 +158,7 @@
      * @title  branch target shall be inside the method
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.if_eq.d.T_if_eq_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_eq.d.T_if_eq_10", VerifyError.class);
     }
 
     /**
@@ -191,12 +166,7 @@
      * @title  branch target shall not be "inside" instruction
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.if_eq.d.T_if_eq_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_eq.d.T_if_eq_11", VerifyError.class);
     }
     
     /**
@@ -204,12 +174,7 @@
      * @title  zero offset
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.if_eq.d.T_if_eq_12");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_eq.d.T_if_eq_12", VerifyError.class);
     }
 
     /**
@@ -218,11 +183,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.if_eq.d.T_if_eq_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_eq.d.T_if_eq_4", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/if_eqz/Test_if_eqz.java b/tools/vm-tests-tf/src/dot/junit/opcodes/if_eqz/Test_if_eqz.java
index ebedd7f..fac0c9b 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/if_eqz/Test_if_eqz.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/if_eqz/Test_if_eqz.java
@@ -68,12 +68,7 @@
      * @title  number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.if_eqz.d.T_if_eqz_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_eqz.d.T_if_eqz_5", VerifyError.class);
     }
 
 
@@ -82,12 +77,7 @@
      * @title  types of arguments - double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.if_eqz.d.T_if_eqz_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_eqz.d.T_if_eqz_6", VerifyError.class);
     }
 
     /**
@@ -95,12 +85,7 @@
      * @title  types of arguments - long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.if_eqz.d.T_if_eqz_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_eqz.d.T_if_eqz_7", VerifyError.class);
     }
     
     /**
@@ -108,12 +93,7 @@
      * @title  branch target shall be inside the method
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.if_eqz.d.T_if_eqz_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_eqz.d.T_if_eqz_9", VerifyError.class);
     }
 
     /**
@@ -121,12 +101,7 @@
      * @title  branch target shall not be "inside" instruction
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.if_eqz.d.T_if_eqz_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_eqz.d.T_if_eqz_10", VerifyError.class);
     }
     
     /**
@@ -134,12 +109,7 @@
      * @title  branch must not be 0
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.if_eqz.d.T_if_eqz_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_eqz.d.T_if_eqz_11", VerifyError.class);
     }
 
    /**
@@ -148,12 +118,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.if_eqz.d.T_if_eqz_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_eqz.d.T_if_eqz_3", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/if_ge/Test_if_ge.java b/tools/vm-tests-tf/src/dot/junit/opcodes/if_ge/Test_if_ge.java
index c56a616..e5a4f1e 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/if_ge/Test_if_ge.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/if_ge/Test_if_ge.java
@@ -76,12 +76,7 @@
      * @title  number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.if_ge.d.T_if_ge_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_ge.d.T_if_ge_4", VerifyError.class);
     }
     
 
@@ -91,12 +86,7 @@
      * @title  types of arguments - int, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.if_ge.d.T_if_ge_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_ge.d.T_if_ge_5", VerifyError.class);
     }
 
     /**
@@ -104,12 +94,7 @@
      * @title  types of arguments - long, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.if_ge.d.T_if_ge_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_ge.d.T_if_ge_6", VerifyError.class);
     }
     
     /**
@@ -117,12 +102,7 @@
      * @title  types of arguments - int, reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.if_ge.d.T_if_ge_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_ge.d.T_if_ge_7", VerifyError.class);
     }
 
     /**
@@ -131,12 +111,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.if_ge.d.T_if_ge_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_ge.d.T_if_ge_3", VerifyError.class);
     }
 
      /**
@@ -144,12 +119,7 @@
      * @title  branch target shall be inside the method
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.if_ge.d.T_if_ge_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_ge.d.T_if_ge_9", VerifyError.class);
     }
 
     /**
@@ -157,12 +127,7 @@
      * @title  branch target shall not be "inside" instruction
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.if_ge.d.T_if_ge_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_ge.d.T_if_ge_10", VerifyError.class);
     }
     
     /**
@@ -170,12 +135,7 @@
      * @title  branch target shall 0
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.if_ge.d.T_if_ge_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_ge.d.T_if_ge_11", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/if_gez/Test_if_gez.java b/tools/vm-tests-tf/src/dot/junit/opcodes/if_gez/Test_if_gez.java
index 432485f..5042943 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/if_gez/Test_if_gez.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/if_gez/Test_if_gez.java
@@ -52,12 +52,7 @@
      * @title  number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.if_gez.d.T_if_gez_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_gez.d.T_if_gez_3", VerifyError.class);
     }
 
 
@@ -67,12 +62,7 @@
      * @title  types of arguments - double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.if_gez.d.T_if_gez_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_gez.d.T_if_gez_4", VerifyError.class);
     }
 
     /**
@@ -80,12 +70,7 @@
      * @title  types of arguments - long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.if_gez.d.T_if_gez_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_gez.d.T_if_gez_5", VerifyError.class);
     }
     
     /**
@@ -93,12 +78,7 @@
      * @title  types of arguments - reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.if_gez.d.T_if_gez_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_gez.d.T_if_gez_6", VerifyError.class);
     }
     
     /**
@@ -106,12 +86,7 @@
      * @title branch target shall be inside the method
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.if_gez.d.T_if_gez_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_gez.d.T_if_gez_8", VerifyError.class);
     }
 
     /**
@@ -119,12 +94,7 @@
      * @title  branch target shall not be "inside" instruction
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.if_gez.d.T_if_gez_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_gez.d.T_if_gez_9", VerifyError.class);
     }
     
     /**
@@ -132,12 +102,7 @@
      * @title  branch must not be 0
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.if_gez.d.T_if_gez_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_gez.d.T_if_gez_10", VerifyError.class);
     }
 
     /**
@@ -146,12 +111,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.if_gez.d.T_if_gez_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_gez.d.T_if_gez_2", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/if_gt/Test_if_gt.java b/tools/vm-tests-tf/src/dot/junit/opcodes/if_gt/Test_if_gt.java
index b977e57..8209480 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/if_gt/Test_if_gt.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/if_gt/Test_if_gt.java
@@ -76,12 +76,7 @@
      * @title  number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.if_gt.d.T_if_gt_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_gt.d.T_if_gt_4", VerifyError.class);
     }
     
 
@@ -90,12 +85,7 @@
      * @title  types of arguments - int, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.if_gt.d.T_if_gt_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_gt.d.T_if_gt_5", VerifyError.class);
     }
 
     /**
@@ -103,12 +93,7 @@
      * @title  types of arguments - long, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.if_gt.d.T_if_gt_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_gt.d.T_if_gt_6", VerifyError.class);
     }
     
     /**
@@ -116,12 +101,7 @@
      * @title  types of arguments - int, reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.if_gt.d.T_if_gt_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_gt.d.T_if_gt_7", VerifyError.class);
     }
     
     /**
@@ -129,12 +109,7 @@
      * @title  branch target shall be inside the method
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.if_gt.d.T_if_gt_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_gt.d.T_if_gt_9", VerifyError.class);
     }
 
     /**
@@ -142,12 +117,7 @@
      * @title  branch target shall not be "inside" instruction
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.if_gt.d.T_if_gt_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_gt.d.T_if_gt_10", VerifyError.class);
     }
 
     /**
@@ -155,12 +125,7 @@
      * @title  branch target shall not be 0
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.if_gt.d.T_if_gt_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_gt.d.T_if_gt_11", VerifyError.class);
     }
 
     /**
@@ -169,12 +134,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.if_gt.d.T_if_gt_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_gt.d.T_if_gt_3", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/if_gtz/Test_if_gtz.java b/tools/vm-tests-tf/src/dot/junit/opcodes/if_gtz/Test_if_gtz.java
index 242cf26..ead93fe 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/if_gtz/Test_if_gtz.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/if_gtz/Test_if_gtz.java
@@ -52,12 +52,7 @@
      * @title  number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.if_gtz.d.T_if_gtz_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_gtz.d.T_if_gtz_3", VerifyError.class);
     }
 
 
@@ -66,12 +61,7 @@
      * @title  types of arguments - double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.if_gtz.d.T_if_gtz_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_gtz.d.T_if_gtz_4", VerifyError.class);
     }
 
     /**
@@ -79,12 +69,7 @@
      * @title  types of arguments - long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.if_gtz.d.T_if_gtz_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_gtz.d.T_if_gtz_5", VerifyError.class);
     }
     
     /**
@@ -92,12 +77,7 @@
      * @title  types of arguments - reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.if_gtz.d.T_if_gtz_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_gtz.d.T_if_gtz_6", VerifyError.class);
     }
     
     /**
@@ -105,12 +85,7 @@
      * @title  branch target shall be inside the method
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.if_gtz.d.T_if_gtz_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_gtz.d.T_if_gtz_8", VerifyError.class);
     }
 
     /**
@@ -118,12 +93,7 @@
      * @title  branch target shall not be "inside" instruction
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.if_gtz.d.T_if_gtz_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_gtz.d.T_if_gtz_9", VerifyError.class);
     }
     
     /**
@@ -131,12 +101,7 @@
      * @title  branch must not be 0
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.if_gtz.d.T_if_gtz_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_gtz.d.T_if_gtz_10", VerifyError.class);
     }
 
     /**
@@ -145,12 +110,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.if_gtz.d.T_if_gtz_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_gtz.d.T_if_gtz_2", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/if_le/Test_if_le.java b/tools/vm-tests-tf/src/dot/junit/opcodes/if_le/Test_if_le.java
index e0653b4..49e9bf8 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/if_le/Test_if_le.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/if_le/Test_if_le.java
@@ -76,12 +76,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.if_le.d.T_if_le_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_le.d.T_if_le_4", VerifyError.class);
     }
     
 
@@ -91,12 +86,7 @@
      * @title  types of arguments - int, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.if_le.d.T_if_le_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_le.d.T_if_le_5", VerifyError.class);
     }
 
     /**
@@ -104,12 +94,7 @@
      * @title  types of arguments - long, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.if_le.d.T_if_le_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_le.d.T_if_le_6", VerifyError.class);
     }
     
     /**
@@ -117,12 +102,7 @@
      * @title types of arguments - int, reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.if_le.d.T_if_le_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_le.d.T_if_le_7", VerifyError.class);
     }
 
     /**
@@ -130,12 +110,7 @@
      * @title  branch target shall be inside the method
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.if_le.d.T_if_le_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_le.d.T_if_le_9", VerifyError.class);
     }
 
     /**
@@ -143,12 +118,7 @@
      * @title branch target shall not be "inside" instruction
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.if_le.d.T_if_le_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_le.d.T_if_le_10", VerifyError.class);
     }
     
     /**
@@ -156,12 +126,7 @@
      * @title branch target shall not be 0
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.if_le.d.T_if_le_12");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_le.d.T_if_le_12", VerifyError.class);
     }
 
     /**
@@ -170,11 +135,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.if_le.d.T_if_le_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_le.d.T_if_le_11", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/if_lez/Test_if_lez.java b/tools/vm-tests-tf/src/dot/junit/opcodes/if_lez/Test_if_lez.java
index 74599d5..a6097fe 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/if_lez/Test_if_lez.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/if_lez/Test_if_lez.java
@@ -52,12 +52,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.if_lez.d.T_if_lez_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_lez.d.T_if_lez_3", VerifyError.class);
     }
 
 
@@ -67,12 +62,7 @@
      * @title types of arguments - double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.if_lez.d.T_if_lez_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_lez.d.T_if_lez_4", VerifyError.class);
     }
 
     /**
@@ -80,12 +70,7 @@
      * @title types of arguments - long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.if_lez.d.T_if_lez_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_lez.d.T_if_lez_5", VerifyError.class);
     }
     
     /**
@@ -93,12 +78,7 @@
      * @title types of arguments - reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.if_lez.d.T_if_lez_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_lez.d.T_if_lez_6", VerifyError.class);
     }
     
     /**
@@ -106,12 +86,7 @@
      * @title  branch target shall be inside the method
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.if_lez.d.T_if_lez_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_lez.d.T_if_lez_8", VerifyError.class);
     }
 
     /**
@@ -119,12 +94,7 @@
      * @title branch target shall not be "inside" instruction
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.if_lez.d.T_if_lez_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_lez.d.T_if_lez_9", VerifyError.class);
     }
     
     /**
@@ -132,12 +102,7 @@
      * @title branch must not be 0
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.if_lez.d.T_if_lez_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_lez.d.T_if_lez_10", VerifyError.class);
     }
 
     /**
@@ -146,12 +111,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.if_lez.d.T_if_lez_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_lez.d.T_if_lez_2", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/if_lt/Test_if_lt.java b/tools/vm-tests-tf/src/dot/junit/opcodes/if_lt/Test_if_lt.java
index 7f186d9..3be2998 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/if_lt/Test_if_lt.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/if_lt/Test_if_lt.java
@@ -76,12 +76,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.if_lt.d.T_if_lt_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_lt.d.T_if_lt_4", VerifyError.class);
     }
 
 
@@ -90,12 +85,7 @@
      * @title  types of arguments - int, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.if_lt.d.T_if_lt_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_lt.d.T_if_lt_5", VerifyError.class);
     }
 
     /**
@@ -103,12 +93,7 @@
      * @title  types of arguments - long, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.if_lt.d.T_if_lt_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_lt.d.T_if_lt_6", VerifyError.class);
     }
     
     /**
@@ -116,12 +101,7 @@
      * @title  types of arguments - int, reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.if_lt.d.T_if_lt_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_lt.d.T_if_lt_7", VerifyError.class);
     }
     
     /**
@@ -129,12 +109,7 @@
      * @title branch target shall be inside the method
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.if_lt.d.T_if_lt_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_lt.d.T_if_lt_9", VerifyError.class);
     }
 
     /**
@@ -142,12 +117,7 @@
      * @title branch target shall not be "inside" instruction
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.if_lt.d.T_if_lt_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_lt.d.T_if_lt_10", VerifyError.class);
     }
 
     /**
@@ -155,12 +125,7 @@
      * @title branch target shall not be 0
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.if_lt.d.T_if_lt_12");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_lt.d.T_if_lt_12", VerifyError.class);
     }
 
     /**
@@ -169,12 +134,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.if_lt.d.T_if_lt_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_lt.d.T_if_lt_11", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/if_ltz/Test_if_ltz.java b/tools/vm-tests-tf/src/dot/junit/opcodes/if_ltz/Test_if_ltz.java
index a73b95b..471deee 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/if_ltz/Test_if_ltz.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/if_ltz/Test_if_ltz.java
@@ -52,12 +52,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.if_ltz.d.T_if_ltz_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_ltz.d.T_if_ltz_3", VerifyError.class);
     }
 
 
@@ -66,12 +61,7 @@
      * @title types of arguments - double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.if_ltz.d.T_if_ltz_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_ltz.d.T_if_ltz_4", VerifyError.class);
     }
 
     /**
@@ -79,12 +69,7 @@
      * @title types of arguments - long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.if_ltz.d.T_if_ltz_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_ltz.d.T_if_ltz_5", VerifyError.class);
     }
     
     /**
@@ -92,12 +77,7 @@
      * @title types of arguments - reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.if_ltz.d.T_if_ltz_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_ltz.d.T_if_ltz_6", VerifyError.class);
     }
     
     /**
@@ -105,12 +85,7 @@
      * @title  branch target shall be inside the method
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.if_ltz.d.T_if_ltz_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_ltz.d.T_if_ltz_8", VerifyError.class);
     }
 
     /**
@@ -118,12 +93,7 @@
      * @title branch target shall not be "inside" instruction
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.if_ltz.d.T_if_ltz_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_ltz.d.T_if_ltz_9", VerifyError.class);
     }
     
     /**
@@ -131,12 +101,7 @@
      * @title branch must not be 0
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.if_ltz.d.T_if_ltz_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_ltz.d.T_if_ltz_7", VerifyError.class);
     }
 
     /**
@@ -145,12 +110,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.if_ltz.d.T_if_ltz_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_ltz.d.T_if_ltz_2", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/if_ne/Test_if_ne.java b/tools/vm-tests-tf/src/dot/junit/opcodes/if_ne/Test_if_ne.java
index 9f69a12..e104de6 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/if_ne/Test_if_ne.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/if_ne/Test_if_ne.java
@@ -105,12 +105,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.if_ne.d.T_if_ne_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_ne.d.T_if_ne_5", VerifyError.class);
     }
 
 
@@ -120,12 +115,7 @@
      * @title types of arguments - int, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.if_ne.d.T_if_ne_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_ne.d.T_if_ne_7", VerifyError.class);
     }
 
     /**
@@ -133,12 +123,7 @@
      * @title types of arguments - long, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.if_ne.d.T_if_ne_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_ne.d.T_if_ne_8", VerifyError.class);
     }
     
     /**
@@ -146,12 +131,7 @@
      * @title  types of arguments - int, reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.if_ne.d.T_if_ne_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_ne.d.T_if_ne_9", VerifyError.class);
     }
 
     /**
@@ -159,12 +139,7 @@
      * @title  branch target shall be inside the method
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.if_ne.d.T_if_ne_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_ne.d.T_if_ne_10", VerifyError.class);
     }
 
     /**
@@ -172,12 +147,7 @@
      * @title branch target shall not be "inside" instruction
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.if_ne.d.T_if_ne_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_ne.d.T_if_ne_11", VerifyError.class);
     }
 
     /**
@@ -185,12 +155,7 @@
      * @title branch target shall not be 0
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.if_ne.d.T_if_ne_12");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_ne.d.T_if_ne_12", VerifyError.class);
     }
 
     /**
@@ -199,12 +164,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.if_ne.d.T_if_ne_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_ne.d.T_if_ne_4", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/if_nez/Test_if_nez.java b/tools/vm-tests-tf/src/dot/junit/opcodes/if_nez/Test_if_nez.java
index a8dece5..2a7761a 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/if_nez/Test_if_nez.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/if_nez/Test_if_nez.java
@@ -73,12 +73,7 @@
      * @title  number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.if_nez.d.T_if_nez_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_nez.d.T_if_nez_5", VerifyError.class);
     }
 
 
@@ -87,12 +82,7 @@
      * @title types of arguments - double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.if_nez.d.T_if_nez_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_nez.d.T_if_nez_6", VerifyError.class);
     }
 
     /**
@@ -100,12 +90,7 @@
      * @title types of arguments - long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.if_nez.d.T_if_nez_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_nez.d.T_if_nez_7", VerifyError.class);
     }
 
     /**
@@ -114,12 +99,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.if_nez.d.T_if_nez_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_nez.d.T_if_nez_3", VerifyError.class);
     }
 
     /**
@@ -127,12 +107,7 @@
      * @title branch target shall be inside the method
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.if_nez.d.T_if_nez_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_nez.d.T_if_nez_9", VerifyError.class);
     }
 
     /**
@@ -140,12 +115,7 @@
      * @title branch target shall not be "inside" instruction
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.if_nez.d.T_if_nez_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_nez.d.T_if_nez_10", VerifyError.class);
     }
     
     /**
@@ -153,11 +123,6 @@
      * @title branch must not be 0
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.if_nez.d.T_if_nez_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.if_nez.d.T_if_nez_11", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iget/Test_iget.java b/tools/vm-tests-tf/src/dot/junit/opcodes/iget/Test_iget.java
index 50658ce..c3a0f09 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/iget/Test_iget.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iget/Test_iget.java
@@ -62,13 +62,7 @@
      * @title expected NullPointerException
      */
     public void testE2() {
-        T_iget_9 t = new T_iget_9();
-        try {
-            t.run();
-            fail("expected NullPointerException");
-        } catch (NullPointerException e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget.d.T_iget_9", NullPointerException.class);
     }
     
     /**
@@ -76,12 +70,7 @@
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.iget.d.T_iget_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget.d.T_iget_4", VerifyError.class);
     }
 
     /**
@@ -90,12 +79,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.iget.d.T_iget_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget.d.T_iget_3", VerifyError.class);
     }
     
     /**
@@ -104,12 +88,7 @@
      * different type exist
      */
     public void testVFE3() {
-        try {
-            new T_iget_13().run();
-            fail("expected a NoSuchFieldError exception");
-        } catch (NoSuchFieldError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget.d.T_iget_13", NoSuchFieldError.class);
     }
     
     /**
@@ -117,14 +96,8 @@
      * @title Attempt to read inaccessible private field.
      */
     public void testVFE4() {
-        //@uses dot.junit.opcodes.iget.d.T_iget_6
         //@uses dot.junit.opcodes.iget.TestStubs
-        try {
-            new T_iget_6().run();
-            fail("expected an IllegalAccessError exception");
-        } catch (IllegalAccessError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget.d.T_iget_6",  IllegalAccessError.class);
     }
 
     /**
@@ -132,12 +105,7 @@
      * @title Attempt to read field of undefined class.
      */
     public void testVFE5() {
-        try {
-            new T_iget_7().run();
-            fail("expected a NoClassDefFoundError exception");
-        } catch (NoClassDefFoundError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget.d.T_iget_7", NoClassDefFoundError.class);
     }
 
     /**
@@ -145,12 +113,7 @@
      * @title Attempt to read undefined field.
      */
     public void testVFE6() {
-        try {
-            new T_iget_8().run();
-            fail("expected a NoSuchFieldError exception");
-        } catch (NoSuchFieldError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget.d.T_iget_8", NoSuchFieldError.class);
     }
     
     /**
@@ -158,14 +121,8 @@
      * @title Attempt to read superclass' private field from subclass.
      */
     public void testVFE7() {
-        //@uses dot.junit.opcodes.iget.d.T_iget_12
         //@uses dot.junit.opcodes.iget.d.T_iget_1
-        try {
-            new T_iget_12().run();
-            fail("expected an IllegalAccessError exception");
-        } catch (IllegalAccessError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget.d.T_iget_12", IllegalAccessError.class);
     }
    
     /**
@@ -173,12 +130,7 @@
      * @title iget shall not work for reference fields
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.iget.d.T_iget_14");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget.d.T_iget_14", VerifyError.class);
     }
     
     /**
@@ -187,12 +139,7 @@
      * @title iget shall not work for short fields
      */
     public void testVFE9() {
-        try {
-            Class.forName("dot.junit.opcodes.iget.d.T_iget_15");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget.d.T_iget_15", VerifyError.class);
     }
     
     /**
@@ -201,12 +148,7 @@
      * @title iget shall not work for boolean fields
      */
     public void testVFE10() {
-        try {
-            Class.forName("dot.junit.opcodes.iget.d.T_iget_16");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget.d.T_iget_16", VerifyError.class);
     }
     
     /**
@@ -215,12 +157,7 @@
      * @title iget shall not work for char fields
      */
     public void testVFE11() {
-        try {
-            Class.forName("dot.junit.opcodes.iget.d.T_iget_17");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget.d.T_iget_17", VerifyError.class);
     }
     
     /**
@@ -229,12 +166,7 @@
      * @title iget shall not work for byte fields
      */
     public void testVFE12() {
-        try {
-            Class.forName("dot.junit.opcodes.iget.d.T_iget_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget.d.T_iget_18", VerifyError.class);
     }    
     
     /**
@@ -243,12 +175,7 @@
      * @title iget shall not work for double fields
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.iget.d.T_iget_19");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget.d.T_iget_19", VerifyError.class);
     } 
     
     /**
@@ -257,12 +184,7 @@
      * @title iget shall not work for long fields
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.iget.d.T_iget_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget.d.T_iget_20", VerifyError.class);
     }
     
     /**
@@ -270,14 +192,8 @@
      * @title Attempt to read protected field of unrelated class.
      */
     public void testVFE15() {
-        //@uses dot.junit.opcodes.iget.d.T_iget_21
         //@uses dot.junit.opcodes.iget.TestStubs
-        try {
-            new T_iget_21().run();
-            fail("expected an IllegalAccessError exception");
-        } catch (IllegalAccessError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget.d.T_iget_21", IllegalAccessError.class);
     }
     
     /**
@@ -285,27 +201,24 @@
      * @title Attempt to read static field.
      */
     public void testVFE16() {
-        //@uses dot.junit.opcodes.iget.d.T_iget_5
         //@uses dot.junit.opcodes.iget.TestStubs
-        try {
-            new T_iget_5().run();
-            fail("expected an IncompatibleClassChangeError exception");
-        } catch (IncompatibleClassChangeError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget.d.T_iget_5", IncompatibleClassChangeError.class);
     }
 
     /**
      * @constraint B6 
-     * @title instance fields may only be accessed on already initialized instances. 
+     * @title instance fields may only be accessed on already initialized instances.
      */
     public void testVFE30() {
-        try {
-            Class.forName("dot.junit.opcodes.iget.d.T_iget_30");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget.d.T_iget_30", VerifyError.class);
+    }
+
+    /**
+     * @constraint N/A 
+     * @title instance fields may only be accessed on reference values.
+     */
+    public void testVFE31() {
+        load("dot.junit.opcodes.iget.d.T_iget_31", VerifyError.class);
     }
 }
 
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iget/d/T_iget_31.d b/tools/vm-tests-tf/src/dot/junit/opcodes/iget/d/T_iget_31.d
new file mode 100644
index 0000000..3659b15
--- /dev/null
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iget/d/T_iget_31.d
@@ -0,0 +1,32 @@
+; 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.
+
+.source T_iget_31.java
+.class public dot.junit.opcodes.iget.d.T_iget_31
+.super java/lang/Object
+
+.field public  st_i1 I
+
+.method public <init>()V
+.limit regs 1
+       invoke-direct {v0}, java/lang/Object/<init>()V
+       return-void
+.end method
+
+.method public run()I
+.limit regs 3
+    iget v0, v0, dot.junit.opcodes.iget.d.T_iget_31.st_i1 I
+    return v0
+.end method
+
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iget_boolean/Test_iget_boolean.java b/tools/vm-tests-tf/src/dot/junit/opcodes/iget_boolean/Test_iget_boolean.java
index b23f330..f16b89c 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/iget_boolean/Test_iget_boolean.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iget_boolean/Test_iget_boolean.java
@@ -54,28 +54,16 @@
      * @title expected NullPointerException
      */
     public void testE2() {
-        T_iget_boolean_9 t = new T_iget_boolean_9();
-        try {
-            t.run();
-            fail("expected NullPointerException");
-        } catch (NullPointerException e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_9",
+                   NullPointerException.class);
     }
 
-   
-
     /**
      * @constraint A11 
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_4", VerifyError.class);
     }
 
     /**
@@ -83,12 +71,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_3", VerifyError.class);
     }
     
     /**
@@ -97,12 +80,7 @@
      * different type exists
      */
     public void testVFE3() {
-        try {
-            new T_iget_boolean_13().run();
-            fail("expected a NoSuchFieldError exception");
-        } catch (NoSuchFieldError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_13", NoSuchFieldError.class);
     }
     
     /**
@@ -110,14 +88,8 @@
      * @title Attempt to read inaccessible field
      */
     public void testVFE4() {
-        //@uses dot.junit.opcodes.iget_boolean.d.T_iget_boolean_6
         //@uses dot.junit.opcodes.iget_boolean.TestStubs
-        try {
-            new T_iget_boolean_6().run();
-            fail("expected an IllegalAccessError exception");
-        } catch (IllegalAccessError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_6", IllegalAccessError.class);
     }
 
     /**
@@ -125,12 +97,8 @@
      * @title Attempt to read field of undefined class.
      */
     public void testVFE5() {
-        try {
-            new T_iget_boolean_7().run();
-            fail("expected a NoClassDefFoundError exception");
-        } catch (NoClassDefFoundError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_7",
+                   NoClassDefFoundError.class);
     }
 
     /**
@@ -138,12 +106,7 @@
      * @title Attempt to read undefined field.
      */
     public void testVFE6() {
-        try {
-            new T_iget_boolean_8().run();
-            fail("expected a NoSuchFieldError exception");
-        } catch (NoSuchFieldError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_8", NoSuchFieldError.class);
     }
     
     /**
@@ -151,14 +114,9 @@
      * @title Attempt to read superclass' private field from subclass.
      */
     public void testVFE7() {
-        //@uses dot.junit.opcodes.iget_boolean.d.T_iget_boolean_12
         //@uses dot.junit.opcodes.iget_boolean.d.T_iget_boolean_1
-        try {
-            new T_iget_boolean_12().run();
-            fail("expected an IllegalAccessError exception");
-        } catch (IllegalAccessError e) {
-            // expected
-        }
+        //@uses dot.junit.opcodes.iget_boolean.d.T_iget_boolean_12
+        loadAndRun("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_12", IllegalAccessError.class);
     }
    
     /**
@@ -166,12 +124,7 @@
      * @title iget_boolean shall not work for reference fields
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_14");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_14", VerifyError.class);
     }
     
     /**
@@ -180,12 +133,7 @@
      * @title iget_boolean shall not work for short fields
      */
     public void testVFE9() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_15");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_15", VerifyError.class);
     }
     
     /**
@@ -193,12 +141,7 @@
      * @title iget_boolean shall not work for int fields
      */
     public void testVFE10() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_16");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_16", VerifyError.class);
     }
     
     /**
@@ -206,12 +149,7 @@
      * @title iget_boolean shall not work for char fields
      */
     public void testVFE11() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_17");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_17", VerifyError.class);
     }
     
     /**
@@ -219,12 +157,7 @@
      * @title iget_boolean shall not work for byte fields
      */
     public void testVFE12() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_18", VerifyError.class);
     }    
     
     /**
@@ -232,12 +165,7 @@
      * @title iget_boolean shall not work for double fields
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_19");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_19", VerifyError.class);
     } 
     
     /**
@@ -245,12 +173,7 @@
      * @title iget_boolean shall not work for long fields
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_20", VerifyError.class);
     }
     
     /**
@@ -258,14 +181,8 @@
      * @title Attempt to read inaccessible protected field.
      */
     public void testVFE15() {
-        //@uses dot.junit.opcodes.iget_boolean.d.T_iget_boolean_21
         //@uses dot.junit.opcodes.iget_boolean.TestStubs
-        try {
-            new T_iget_boolean_21().run();
-            fail("expected an IllegalAccessError exception");
-        } catch (IllegalAccessError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_21", IllegalAccessError.class);
     }
 
 
@@ -274,14 +191,9 @@
      * @title Attempt to read static field.
      */
     public void testVFE16() {
-        //@uses dot.junit.opcodes.iget_boolean.d.T_iget_boolean_5
         //@uses dot.junit.opcodes.iget_boolean.TestStubs
-        try {
-            new T_iget_boolean_5().run();
-            fail("expected an IncompatibleClassChangeError exception");
-        } catch (IncompatibleClassChangeError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_5",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -289,11 +201,14 @@
      * @title instance fields may only be accessed on already initialized instances. 
      */
     public void testVFE30() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_30");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_30", VerifyError.class);
+    }
+
+    /**
+     * @constraint N/A
+     * @title instance fields may only be accessed on reference values.
+     */
+    public void testVFE31() {
+        load("dot.junit.opcodes.iget_boolean.d.T_iget_boolean_31", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iget_boolean/d/T_iget_boolean_31.d b/tools/vm-tests-tf/src/dot/junit/opcodes/iget_boolean/d/T_iget_boolean_31.d
new file mode 100644
index 0000000..ade9e7b
--- /dev/null
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iget_boolean/d/T_iget_boolean_31.d
@@ -0,0 +1,32 @@
+; 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.
+
+.source T_iget_boolean_31.java
+.class public dot.junit.opcodes.iget_boolean.d.T_iget_boolean_31
+.super java/lang/Object
+
+.field public  st_i1 Z
+
+.method public <init>()V
+.limit regs 1
+       invoke-direct {v0}, java/lang/Object/<init>()V
+       return-void
+.end method
+
+.method public run()Z
+.limit regs 3
+    iget v0, v0, dot.junit.opcodes.iget_boolean.d.T_iget_boolean_31.st_i1 Z
+    return v0
+.end method
+
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iget_byte/Test_iget_byte.java b/tools/vm-tests-tf/src/dot/junit/opcodes/iget_byte/Test_iget_byte.java
index de48192..410dad4 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/iget_byte/Test_iget_byte.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iget_byte/Test_iget_byte.java
@@ -54,13 +54,7 @@
      * @title expected NullPointerException
      */
     public void testE2() {
-        T_iget_byte_9 t = new T_iget_byte_9();
-        try {
-            t.run();
-            fail("expected NullPointerException");
-        } catch (NullPointerException e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_byte.d.T_iget_byte_9", NullPointerException.class);
     }   
 
     /**
@@ -68,12 +62,7 @@
      * @title  constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_byte.d.T_iget_byte_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_byte.d.T_iget_byte_4", VerifyError.class);
     }
 
     /**
@@ -81,12 +70,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_byte.d.T_iget_byte_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_byte.d.T_iget_byte_3", VerifyError.class);
     }
     
     /**
@@ -95,12 +79,7 @@
      * different type exists
      */
     public void testVFE3() {
-        try {
-            new T_iget_byte_13().run();
-            fail("expected a NoSuchFieldError exception");
-        } catch (NoSuchFieldError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_byte.d.T_iget_byte_13", NoSuchFieldError.class);
     }
     
     /**
@@ -108,14 +87,8 @@
      * @title Attempt to read inaccessible field.
      */
     public void testVFE4() {
-        //@uses dot.junit.opcodes.iget_byte.d.T_iget_byte_6
         //@uses dot.junit.opcodes.iget_byte.TestStubs
-        try {
-            new T_iget_byte_6().run();
-            fail("expected an IllegalAccessError exception");
-        }  catch (IllegalAccessError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_byte.d.T_iget_byte_6", IllegalAccessError.class);
     }
 
     /**
@@ -123,12 +96,7 @@
      * @title Attempt to read field of undefined class.
      */
     public void testVFE5() {
-        try {
-            new T_iget_byte_7().run();
-            fail("expected a NoClassDefFoundError exception");
-        } catch (NoClassDefFoundError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_byte.d.T_iget_byte_7", NoClassDefFoundError.class);
     }
 
     /**
@@ -136,12 +104,7 @@
      * @title Attempt to read undefined field.
      */
     public void testVFE6() {
-        try {
-            new T_iget_byte_8().run();
-            fail("expected a NoSuchFieldError exception");
-        } catch (NoSuchFieldError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_byte.d.T_iget_byte_8", NoSuchFieldError.class);
     }
     
     /**
@@ -149,14 +112,8 @@
      * @title Attempt to read superclass' private field from subclass.
      */
     public void testVFE7() {
-        //@uses dot.junit.opcodes.iget_byte.d.T_iget_byte_12
         //@uses dot.junit.opcodes.iget_byte.d.T_iget_byte_1
-        try {
-            new T_iget_byte_12().run();
-            fail("expected an IllegalAccessError exception");
-        }  catch (IllegalAccessError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_byte.d.T_iget_byte_12", IllegalAccessError.class);
     }
    
     /**
@@ -164,12 +121,7 @@
      * @title iget_byte shall not work for reference fields
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_byte.d.T_iget_byte_14");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_byte.d.T_iget_byte_14", VerifyError.class);
     }
     
     /**
@@ -177,12 +129,7 @@
      * @title iget_byte shall not work for short fields
      */
     public void testVFE9() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_byte.d.T_iget_byte_15");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_byte.d.T_iget_byte_15", VerifyError.class);
     }
     
     /**
@@ -190,12 +137,7 @@
      * @title iget_byte shall not work for int fields
      */
     public void testVFE10() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_byte.d.T_iget_byte_16");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_byte.d.T_iget_byte_16", VerifyError.class);
     }
     
     /**
@@ -203,12 +145,7 @@
      * @title iget_byte shall not work for char fields
      */
     public void testVFE11() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_byte.d.T_iget_byte_17");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_byte.d.T_iget_byte_17", VerifyError.class);
     }
     
     /**
@@ -216,12 +153,7 @@
      * @title iget_byte shall not work for boolean fields
      */
     public void testVFE12() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_byte.d.T_iget_byte_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_byte.d.T_iget_byte_18", VerifyError.class);
     }    
     
     /**
@@ -229,12 +161,7 @@
      * @title iget_byte shall not work for double fields
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_byte.d.T_iget_byte_19");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_byte.d.T_iget_byte_19", VerifyError.class);
     } 
     
     /**
@@ -242,12 +169,7 @@
      * @title iget_byte shall not work for long fields
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_byte.d.T_iget_byte_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_byte.d.T_iget_byte_20", VerifyError.class);
     }
     
     /**
@@ -255,14 +177,8 @@
      * @title Attempt to read inaccessible protected field.
      */
     public void testVFE15() {
-        //@uses dot.junit.opcodes.iget_byte.d.T_iget_byte_21
         //@uses dot.junit.opcodes.iget_byte.TestStubs
-        try {
-            new T_iget_byte_21().run();
-            fail("expected an IllegalAccessError exception");
-        }  catch (IllegalAccessError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_byte.d.T_iget_byte_21", IllegalAccessError.class);
     }
 
 
@@ -271,14 +187,9 @@
      * @title Attempt to read static  field.
      */
     public void testVFE16() {
-        //@uses dot.junit.opcodes.iget_byte.d.T_iget_byte_5
-        //@uses dot.junit.opcodes.iget_byte.TestStubs        
-        try {
-            new T_iget_byte_5().run();
-            fail("expected an IncompatibleClassChangeError exception");
-        }  catch (IncompatibleClassChangeError e) {
-            // expected
-        }
+        //@uses dot.junit.opcodes.iget_byte.TestStubs
+        loadAndRun("dot.junit.opcodes.iget_byte.d.T_iget_byte_5",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -286,11 +197,14 @@
      * @title instance fields may only be accessed on already initialized instances. 
      */
     public void testVFE30() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_byte.d.T_iget_byte_30");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_byte.d.T_iget_byte_30", VerifyError.class);
+    }
+
+    /**
+     * @constraint N/A
+     * @title instance fields may only be accessed on reference values.
+     */
+    public void testVFE31() {
+        load("dot.junit.opcodes.iget_byte.d.T_iget_byte_31", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iget_byte/d/T_iget_byte_31.d b/tools/vm-tests-tf/src/dot/junit/opcodes/iget_byte/d/T_iget_byte_31.d
new file mode 100644
index 0000000..0a84091
--- /dev/null
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iget_byte/d/T_iget_byte_31.d
@@ -0,0 +1,32 @@
+; 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.
+
+.source T_iget_byte_31.java
+.class public dot.junit.opcodes.iget_byte.d.T_iget_byte_31
+.super java/lang/Object
+
+.field public  st_i1 B
+
+.method public <init>()V
+.limit regs 1
+       invoke-direct {v0}, java/lang/Object/<init>()V
+       return-void
+.end method
+
+.method public run()B
+.limit regs 3
+    iget v0, v0, dot.junit.opcodes.iget_byte.d.T_iget_byte_31.st_i1 B
+    return v0
+.end method
+
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iget_char/Test_iget_char.java b/tools/vm-tests-tf/src/dot/junit/opcodes/iget_char/Test_iget_char.java
index c7516e8..ff86ae3 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/iget_char/Test_iget_char.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iget_char/Test_iget_char.java
@@ -54,13 +54,7 @@
      * @title expected NullPointerException
      */
     public void testE2() {
-        T_iget_char_9 t = new T_iget_char_9();
-        try {
-            t.run();
-            fail("expected NullPointerException");
-        } catch (NullPointerException e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_char.d.T_iget_char_9", NullPointerException.class);
     }
    
 
@@ -69,12 +63,7 @@
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_char.d.T_iget_char_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_char.d.T_iget_char_4", VerifyError.class);
     }
 
     /**
@@ -83,12 +72,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_char.d.T_iget_char_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_char.d.T_iget_char_3", VerifyError.class);
     }
     
     /**
@@ -98,12 +82,7 @@
      * different type exists
      */
     public void testVFE3() {
-        try {
-            new T_iget_char_13().run();
-            fail("expected a NoSuchFieldError exception");
-        } catch (NoSuchFieldError t) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_char.d.T_iget_char_13", NoSuchFieldError.class);
     }
     
     /**
@@ -111,14 +90,8 @@
      * @title Attempt to read inaccessible field.
      */
     public void testVFE4() {
-        //@uses dot.junit.opcodes.iget_char.d.T_iget_char_6
         //@uses dot.junit.opcodes.iget_char.TestStubs
-        try {
-            new T_iget_char_6().run();
-            fail("expected an IllegalAccessError exception");
-        } catch (IllegalAccessError t) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_char.d.T_iget_char_6", IllegalAccessError.class);
     }
 
     /**
@@ -126,12 +99,7 @@
      * @title Attempt to read field of undefined class.
      */
     public void testVFE5() {
-        try {
-            new T_iget_char_7().run();
-            fail("expected a NoClassDefFoundError exception");
-        } catch (NoClassDefFoundError t) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_char.d.T_iget_char_7", NoClassDefFoundError.class);
     }
 
     /**
@@ -139,12 +107,7 @@
      * @title Attempt to read undefined field.
      */
     public void testVFE6() {
-        try {
-            new T_iget_char_8().run();
-            fail("expected a NoSuchFieldError exception");
-        } catch (NoSuchFieldError t) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_char.d.T_iget_char_8", NoSuchFieldError.class);
     }
     
     /**
@@ -152,14 +115,8 @@
      * @title Attempt to read superclass' private field from subclass.
      */
     public void testVFE7() {
-        //@uses dot.junit.opcodes.iget_char.d.T_iget_char_12
         //@uses dot.junit.opcodes.iget_char.d.T_iget_char_1
-        try {
-            new T_iget_char_12().run();
-            fail("expected an IllegalAccessError exception");
-        } catch (IllegalAccessError t) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_char.d.T_iget_char_12", IllegalAccessError.class);
     }
    
     /**
@@ -167,12 +124,7 @@
      * @title iget_char shall not work for reference fields
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_char.d.T_iget_char_14");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_char.d.T_iget_char_14", VerifyError.class);
     }
     
     /**
@@ -181,12 +133,7 @@
      * @title iget_char shall not work for short fields
      */
     public void testVFE9() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_char.d.T_iget_char_15");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_char.d.T_iget_char_15", VerifyError.class);
     }
     
     /**
@@ -195,12 +142,7 @@
      * @title iget_char shall not work for int fields
      */
     public void testVFE10() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_char.d.T_iget_char_16");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_char.d.T_iget_char_16", VerifyError.class);
     }
     
     /**
@@ -209,12 +151,7 @@
      * @title iget_char shall not work for byte fields
      */
     public void testVFE11() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_char.d.T_iget_char_17");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_char.d.T_iget_char_17", VerifyError.class);
     }
     
     /**
@@ -223,12 +160,7 @@
      * @title iget_char shall not work for boolean fields
      */
     public void testVFE12() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_char.d.T_iget_char_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_char.d.T_iget_char_18", VerifyError.class);
     }    
     
     /**
@@ -236,12 +168,7 @@
      * @title iget_char shall not work for double fields
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_char.d.T_iget_char_19");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_char.d.T_iget_char_19", VerifyError.class);
     } 
     
     /**
@@ -249,12 +176,7 @@
      * @title iget_char shall not work for long fields
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_char.d.T_iget_char_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_char.d.T_iget_char_20", VerifyError.class);
     }
     
     /**
@@ -262,14 +184,8 @@
      * @title Attempt to read inaccessible protected field.
      */
     public void testVFE15() {
-        //@uses dot.junit.opcodes.iget_char.d.T_iget_char_21
         //@uses dot.junit.opcodes.iget_char.TestStubs
-        try {
-            new T_iget_char_21().run();
-            fail("expected an IllegalAccessError exception");
-        } catch (IllegalAccessError t) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_char.d.T_iget_char_21", IllegalAccessError.class);
     }
 
 
@@ -278,14 +194,9 @@
      * @title Attempt to read static  field.
      */
     public void testVFE16() {
-        //@uses dot.junit.opcodes.iget_char.d.T_iget_char_5
         //@uses dot.junit.opcodes.iget_char.TestStubs
-        try {
-            new T_iget_char_5().run();
-            fail("expected an IncompatibleClassChangeError exception");
-        } catch (IncompatibleClassChangeError t) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_char.d.T_iget_char_5",
+                   IncompatibleClassChangeError.class);
     }
     
 
@@ -294,11 +205,14 @@
      * @title instance fields may only be accessed on already initialized instances. 
      */
     public void testVFE30() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_char.d.T_iget_char_30");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_char.d.T_iget_char_30", VerifyError.class);
+    }
+
+    /**
+     * @constraint N/A
+     * @title instance fields may only be accessed on reference values.
+     */
+    public void testVFE31() {
+        load("dot.junit.opcodes.iget_char.d.T_iget_char_31", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iget_char/d/T_iget_char_31.d b/tools/vm-tests-tf/src/dot/junit/opcodes/iget_char/d/T_iget_char_31.d
new file mode 100644
index 0000000..0f5c6d7
--- /dev/null
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iget_char/d/T_iget_char_31.d
@@ -0,0 +1,32 @@
+; 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.
+
+.source T_iget_char_31.java
+.class public dot.junit.opcodes.iget_char.d.T_iget_char_31
+.super java/lang/Object
+
+.field public  st_i1 C
+
+.method public <init>()V
+.limit regs 1
+       invoke-direct {v0}, java/lang/Object/<init>()V
+       return-void
+.end method
+
+.method public run()C
+.limit regs 3
+    iget v0, v0, dot.junit.opcodes.iget_char.d.T_iget_char_31.st_i1 C
+    return v0
+.end method
+
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iget_object/Test_iget_object.java b/tools/vm-tests-tf/src/dot/junit/opcodes/iget_object/Test_iget_object.java
index 3a735b6..7314141 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/iget_object/Test_iget_object.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iget_object/Test_iget_object.java
@@ -55,13 +55,7 @@
      * @title expected NullPointerException
      */
     public void testE2() {
-        T_iget_object_9 t = new T_iget_object_9();
-        try {
-            t.run();
-            fail("expected NullPointerException");
-        } catch (NullPointerException e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_object.d.T_iget_object_9", NullPointerException.class);
     }  
 
     /**
@@ -69,12 +63,7 @@
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_object.d.T_iget_object_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_object.d.T_iget_object_4", VerifyError.class);
     }
 
     /**
@@ -83,12 +72,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_object.d.T_iget_object_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_object.d.T_iget_object_3", VerifyError.class);
     }
     
     /**
@@ -98,12 +82,7 @@
      * different type exists)
      */
     public void testVFE3() {
-        try {
-            new T_iget_object_13().run();
-            fail("expected a NoSuchFieldError exception");
-        } catch (NoSuchFieldError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_object.d.T_iget_object_13", NoSuchFieldError.class);
     }
     
     /**
@@ -111,14 +90,8 @@
      * @title Attempt to read inaccessible field.
      */
     public void testVFE4() {
-        //@uses dot.junit.opcodes.iget_object.d.T_iget_object_6
         //@uses dot.junit.opcodes.iget_object.TestStubs
-        try {
-            new T_iget_object_6().run();
-            fail("expected an IllegalAccessError exception");
-        } catch (IllegalAccessError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_object.d.T_iget_object_6", IllegalAccessError.class);
     }
 
     /**
@@ -126,12 +99,7 @@
      * @title Attempt to read field of undefined class.
      */
     public void testVFE5() {
-        try {
-            new T_iget_object_7().run();
-            fail("expected a NoClassDefFoundError exception");
-        } catch (NoClassDefFoundError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_object.d.T_iget_object_7", NoClassDefFoundError.class);
     }
 
     /**
@@ -139,12 +107,7 @@
      * @title Attempt to read undefined field.
      */
     public void testVFE6() {
-        try {
-            new T_iget_object_8().run();
-            fail("expected a NoSuchFieldError exception");
-        } catch (NoSuchFieldError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_object.d.T_iget_object_8", NoSuchFieldError.class);
     }
     
     /**
@@ -152,14 +115,8 @@
      * @title Attempt to read superclass' private field from subclass.
      */
     public void testVFE7() {
-        //@uses dot.junit.opcodes.iget_object.d.T_iget_object_12
         //@uses dot.junit.opcodes.iget_object.d.T_iget_object_1
-        try {
-            new T_iget_object_12().run();
-            fail("expected an IllegalAccessError exception");
-        } catch (IllegalAccessError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_object.d.T_iget_object_12", IllegalAccessError.class);
     }
    
     /**
@@ -167,12 +124,7 @@
      * @title iget_object shall not work for short fields
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_object.d.T_iget_object_14");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_object.d.T_iget_object_14", VerifyError.class);
     }
     
     /**
@@ -181,12 +133,7 @@
      * @title iget_object shall not work for char fields
      */
     public void testVFE9() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_object.d.T_iget_object_15");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_object.d.T_iget_object_15", VerifyError.class);
     }
     
     /**
@@ -195,12 +142,7 @@
      * @title iget_object shall not work for int fields
      */
     public void testVFE10() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_object.d.T_iget_object_16");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_object.d.T_iget_object_16", VerifyError.class);
     }
     
     /**
@@ -209,12 +151,7 @@
      * @title iget_object shall not work for byte fields
      */
     public void testVFE11() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_object.d.T_iget_object_17");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_object.d.T_iget_object_17", VerifyError.class);
     }
     
     /**
@@ -223,12 +160,7 @@
      * @title iget_object shall not work for boolean fields
      */
     public void testVFE12() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_object.d.T_iget_object_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_object.d.T_iget_object_18", VerifyError.class);
     }    
     
     /**
@@ -237,12 +169,7 @@
      * @title iget_object shall not work for double fields
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_object.d.T_iget_object_19");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_object.d.T_iget_object_19", VerifyError.class);
     } 
     
     /**
@@ -251,12 +178,7 @@
      * @title iget_object shall not work for long fields
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_object.d.T_iget_object_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_object.d.T_iget_object_20", VerifyError.class);
     } 
     
     /**
@@ -265,12 +187,7 @@
      * @title  only field of different type exists
      */
     public void testVFE15() {
-        try {
-            new T_iget_object_21().run();
-            fail("expected a NoSuchFieldError exception");
-        } catch (NoSuchFieldError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_object.d.T_iget_object_21", NoSuchFieldError.class);
     }
     
     /**
@@ -278,14 +195,8 @@
      * @title Attempt to read inaccessible protected field.
      */
     public void testVFE16() {
-        //@uses dot.junit.opcodes.iget_object.d.T_iget_object_22
         //@uses dot.junit.opcodes.iget_object.TestStubs
-        try {
-            new T_iget_object_22().run();
-            fail("expected an IllegalAccessError exception");
-        } catch (IllegalAccessError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_object.d.T_iget_object_22", IllegalAccessError.class);
     }
 
     /**
@@ -293,14 +204,9 @@
      * @title Attempt to read static field.
      */
     public void testVFE17() {
-        //@uses dot.junit.opcodes.iget_object.d.T_iget_object_5
         //@uses dot.junit.opcodes.iget_object.TestStubs
-        try {
-            new T_iget_object_5().run();
-            fail("expected an IncompatibleClassChangeError exception");
-        } catch (IncompatibleClassChangeError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_object.d.T_iget_object_5",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -308,11 +214,14 @@
      * @title instance fields may only be accessed on already initialized instances. 
      */
     public void testVFE30() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_object.d.T_iget_object_30");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_object.d.T_iget_object_30", VerifyError.class);
+    }
+
+    /**
+     * @constraint N/A
+     * @title instance fields may only be accessed on already initialized instances. 
+     */
+    public void testVFE31() {
+        load("dot.junit.opcodes.iget_object.d.T_iget_object_31", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iget_object/d/T_iget_object_31.d b/tools/vm-tests-tf/src/dot/junit/opcodes/iget_object/d/T_iget_object_31.d
new file mode 100644
index 0000000..f194ecd
--- /dev/null
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iget_object/d/T_iget_object_31.d
@@ -0,0 +1,32 @@
+; 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.
+
+.source T_iget_object_31.java
+.class public dot.junit.opcodes.iget_object.d.T_iget_object_31
+.super java/lang/Object
+
+.field public st_i1 Ldot/junit/opcodes/iget_object/d/T_iget_object_31;
+
+.method public <init>()V
+.limit regs 1
+       invoke-direct {v0}, java/lang/Object/<init>()V
+       return-void
+.end method
+
+.method public run()Ldot/junit/opcodes/iget_object/d/T_iget_object_31;
+.limit regs 3
+    iget v0, v0, dot.junit.opcodes.iget_object.d.T_iget_object_31.st_i1 Ldot/junit/opcodes/iget_object/d/T_iget_object_31;
+    return v0
+.end method
+
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iget_short/Test_iget_short.java b/tools/vm-tests-tf/src/dot/junit/opcodes/iget_short/Test_iget_short.java
index a7d3658..566ec3f 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/iget_short/Test_iget_short.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iget_short/Test_iget_short.java
@@ -54,28 +54,15 @@
      * @title expected NullPointerException
      */
     public void testE2() {
-        T_iget_short_9 t = new T_iget_short_9();
-        try {
-            t.run();
-            fail("expected NullPointerException");
-        } catch (NullPointerException e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_short.d.T_iget_short_9", NullPointerException.class);
     }
 
-  
-
     /**
      * @constraint A11 
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_short.d.T_iget_short_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_short.d.T_iget_short_4", VerifyError.class);
     }
 
     /**
@@ -84,12 +71,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_short.d.T_iget_short_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_short.d.T_iget_short_3", VerifyError.class);
     }
     
     /**
@@ -99,12 +81,7 @@
      * different type exists
      */
     public void testVFE3() {
-        try {
-            new T_iget_short_13().run();
-            fail("expected a NoSuchFieldError exception");
-        } catch (NoSuchFieldError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_short.d.T_iget_short_13", NoSuchFieldError.class);
     }
     
     /**
@@ -112,14 +89,8 @@
      * @title Attempt to read inaccessible field.
      */
     public void testVFE4() {
-        //@uses dot.junit.opcodes.iget_short.d.T_iget_short_6
         //@uses dot.junit.opcodes.iget_short.TestStubs
-        try {
-            new T_iget_short_6().run();
-            fail("expected an IllegalAccessError exception");
-        } catch (IllegalAccessError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_short.d.T_iget_short_6", IllegalAccessError.class);
     }
 
     /**
@@ -127,12 +98,7 @@
      * @title Attempt to read field of undefined class.
      */
     public void testVFE5() {
-        try {
-            new T_iget_short_7().run();
-            fail("expected a NoClassDefFoundError exception");
-        } catch (NoClassDefFoundError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_short.d.T_iget_short_7", NoClassDefFoundError.class);
     }
 
     /**
@@ -140,12 +106,7 @@
      * @title Attempt to read undefined field.
      */
     public void testVFE6() {
-        try {
-            new T_iget_short_8().run();
-            fail("expected a NoSuchFieldError exception");
-        } catch (NoSuchFieldError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_short.d.T_iget_short_8", NoSuchFieldError.class);
     }
     
     /**
@@ -153,14 +114,8 @@
      * @title Attempt to read superclass' private field from subclass.
      */
     public void testVFE7() {
-        //@uses dot.junit.opcodes.iget_short.d.T_iget_short_12
         //@uses dot.junit.opcodes.iget_short.d.T_iget_short_1
-        try {
-            new T_iget_short_12().run();
-            fail("expected an IllegalAccessError exception");
-        } catch (IllegalAccessError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_short.d.T_iget_short_12", IllegalAccessError.class);
     }
    
     /**
@@ -168,12 +123,7 @@
      * @title iget_short shall not work for reference fields
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_short.d.T_iget_short_14");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_short.d.T_iget_short_14", VerifyError.class);
     }
     
     /**
@@ -182,12 +132,7 @@
      * @title iget_short shall not work for char fields
      */
     public void testVFE9() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_short.d.T_iget_short_15");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_short.d.T_iget_short_15", VerifyError.class);
     }
     
     /**
@@ -196,12 +141,7 @@
      * @title iget_short shall not work for int fields
      */
     public void testVFE10() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_short.d.T_iget_short_16");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_short.d.T_iget_short_16", VerifyError.class);
     }
     
     /**
@@ -210,12 +150,7 @@
      * @title iget_short shall not work for byte fields
      */
     public void testVFE11() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_short.d.T_iget_short_17");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_short.d.T_iget_short_17", VerifyError.class);
     }
     
     /**
@@ -224,12 +159,7 @@
      * @title iget_short shall not work for boolean fields
      */
     public void testVFE12() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_short.d.T_iget_short_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_short.d.T_iget_short_18", VerifyError.class);
     }    
     
     /**
@@ -238,12 +168,7 @@
      * @title iget_short shall not work for double fields
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_short.d.T_iget_short_19");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_short.d.T_iget_short_19", VerifyError.class);
     } 
     
     /**
@@ -252,12 +177,7 @@
      * @title iget_short shall not work for long fields
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_short.d.T_iget_short_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_short.d.T_iget_short_20", VerifyError.class);
     }
     
     /**
@@ -265,30 +185,18 @@
      * @title Attempt to read inaccessible protected field.
      */
     public void testVFE15() {
-        //@uses dot.junit.opcodes.iget_short.d.T_iget_short_21
         //@uses dot.junit.opcodes.iget_short.TestStubs
-        try {
-            new T_iget_short_21().run();
-            fail("expected an IllegalAccessError exception");
-        } catch (IllegalAccessError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_short.d.T_iget_short_21", IllegalAccessError.class);
     }
 
-
     /**
      * @constraint A11
      * @title Attempt to read static  field.
      */
     public void testVFE16() {
-        //@uses dot.junit.opcodes.iget_short.d.T_iget_short_5
         //@uses dot.junit.opcodes.iget_short.TestStubs
-        try {
-            new T_iget_short_5().run();
-            fail("expected an IncompatibleClassChangeError exception");
-        } catch (IncompatibleClassChangeError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_short.d.T_iget_short_5",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -296,11 +204,14 @@
      * @title instance fields may only be accessed on already initialized instances. 
      */
     public void testVFE30() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_short.d.T_iget_short_30");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_short.d.T_iget_short_30", VerifyError.class);
+    }
+
+    /**
+     * @constraint N/A 
+     * @title instance fields may only be accessed on already initialized instances. 
+     */
+    public void testVFE31() {
+        load("dot.junit.opcodes.iget_short.d.T_iget_short_31", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iget_short/d/T_iget_short_31.d b/tools/vm-tests-tf/src/dot/junit/opcodes/iget_short/d/T_iget_short_31.d
new file mode 100644
index 0000000..af8a395
--- /dev/null
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iget_short/d/T_iget_short_31.d
@@ -0,0 +1,32 @@
+; 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.
+
+.source T_iget_short_31.java
+.class public dot.junit.opcodes.iget_short.d.T_iget_short_31
+.super java/lang/Object
+
+.field public  st_i1 S
+
+.method public <init>()V
+.limit regs 1
+       invoke-direct {v0}, java/lang/Object/<init>()V
+       return-void
+.end method
+
+.method public run()S
+.limit regs 3
+    iget v0, v0, dot.junit.opcodes.iget_short.d.T_iget_short_31.st_i1 S
+    return v0
+.end method
+
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iget_wide/Test_iget_wide.java b/tools/vm-tests-tf/src/dot/junit/opcodes/iget_wide/Test_iget_wide.java
index 7e42d32..f82a1d3 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/iget_wide/Test_iget_wide.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iget_wide/Test_iget_wide.java
@@ -62,13 +62,7 @@
      * @title expected NullPointerException
      */
     public void testE2() {
-        T_iget_wide_9 t = new T_iget_wide_9();
-        try {
-            t.run();
-            fail("expected NullPointerException");
-        } catch (NullPointerException e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_wide.d.T_iget_wide_9", NullPointerException.class);
     }   
 
     /**
@@ -76,12 +70,7 @@
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_wide.d.T_iget_wide_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_wide.d.T_iget_wide_4", VerifyError.class);
     }
 
     /**
@@ -90,12 +79,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_wide.d.T_iget_wide_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_wide.d.T_iget_wide_3", VerifyError.class);
     }
     
     /**
@@ -105,12 +89,7 @@
      * different type exists
      */
     public void testVFE3() {
-        try {
-            new T_iget_wide_13().run();
-            fail("expected a NoSuchFieldError exception");
-        } catch (NoSuchFieldError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_wide.d.T_iget_wide_13", NoSuchFieldError.class);
     }
     
     /**
@@ -118,14 +97,8 @@
      * @title Attempt to read inaccessible field.
      */
     public void testVFE4() {
-        //@uses dot.junit.opcodes.iget_wide.d.T_iget_wide_6
         //@uses dot.junit.opcodes.iget_wide.TestStubs
-        try {
-            new T_iget_wide_6().run();
-            fail("expected an IllegalAccessError exception");
-        } catch (IllegalAccessError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_wide.d.T_iget_wide_6", IllegalAccessError.class);
     }
 
     /**
@@ -133,12 +106,7 @@
      * @title Attempt to read field of undefined class. 
      */
     public void testVFE5() {
-        try {
-            new T_iget_wide_7().run();
-            fail("expected a NoClassDefFoundError exception");
-        } catch (NoClassDefFoundError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_wide.d.T_iget_wide_7", NoClassDefFoundError.class);
     }
 
     /**
@@ -146,12 +114,7 @@
      * @title Attempt to read undefined field.
      */
     public void testVFE6() {
-        try {
-            new T_iget_wide_8().run();
-            fail("expected a NoSuchFieldError exception");
-        } catch (NoSuchFieldError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_wide.d.T_iget_wide_8", NoSuchFieldError.class);
     }
 
     /**
@@ -159,14 +122,8 @@
      * @title Attempt to read superclass' private field from subclass.
      */
     public void testVFE7() {
-        //@uses dot.junit.opcodes.iget_wide.d.T_iget_wide_12
         //@uses dot.junit.opcodes.iget_wide.d.T_iget_wide_1
-        try {
-            new T_iget_wide_12().run();
-            fail("expected a IllegalAccessError exception");
-        } catch (IllegalAccessError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_wide.d.T_iget_wide_12", IllegalAccessError.class);
     }
    
     /**
@@ -174,12 +131,7 @@
      * @title iget-wide shall not work for reference fields
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_wide.d.T_iget_wide_14");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_wide.d.T_iget_wide_14", VerifyError.class);
     }
     
     /**
@@ -188,12 +140,7 @@
      * @title iget-wide shall not work for short fields
      */
     public void testVFE9() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_wide.d.T_iget_wide_15");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_wide.d.T_iget_wide_15", VerifyError.class);
     }
     
     /**
@@ -202,12 +149,7 @@
      * @title iget-wide shall not work for boolean fields
      */
     public void testVFE10() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_wide.d.T_iget_wide_16");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_wide.d.T_iget_wide_16", VerifyError.class);
     }
     
     /**
@@ -216,12 +158,7 @@
      * @title iget-wide shall not work for char fields
      */
     public void testVFE11() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_wide.d.T_iget_wide_17");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_wide.d.T_iget_wide_17", VerifyError.class);
     }
     
     /**
@@ -230,12 +167,7 @@
      * @title iget-wide shall not work for byte fields
      */
     public void testVFE12() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_wide.d.T_iget_wide_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_wide.d.T_iget_wide_18", VerifyError.class);
     }    
     
     /**
@@ -244,12 +176,7 @@
      * @title iget-wide shall not work for float fields
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_wide.d.T_iget_wide_19");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_wide.d.T_iget_wide_19", VerifyError.class);
     } 
     
     /**
@@ -258,12 +185,7 @@
      * @title iget-wide shall not work for int fields
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_wide.d.T_iget_wide_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_wide.d.T_iget_wide_20", VerifyError.class);
     }
     
     /**
@@ -271,14 +193,8 @@
      * @title Attempt to read inaccessible protected field.
      */
     public void testVFE15() {
-        //@uses dot.junit.opcodes.iget_wide.d.T_iget_wide_21
         //@uses dot.junit.opcodes.iget_wide.TestStubs
-        try {
-            new T_iget_wide_21().run();
-            fail("expected an IllegalAccessError exception");
-        } catch (IllegalAccessError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_wide.d.T_iget_wide_21", IllegalAccessError.class);
     }
 
     /**
@@ -286,14 +202,9 @@
      * @title Attempt to read static  field.
      */
     public void testVFE16() {
-        //@uses dot.junit.opcodes.iget_wide.d.T_iget_wide_5
         //@uses dot.junit.opcodes.iget_wide.TestStubs
-        try {
-            new T_iget_wide_5().run();
-            fail("expected a IncompatibleClassChangeError exception");
-        } catch (IncompatibleClassChangeError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iget_wide.d.T_iget_wide_5", 
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -301,11 +212,14 @@
      * @title instance fields may only be accessed on already initialized instances. 
      */
     public void testVFE30() {
-        try {
-            Class.forName("dot.junit.opcodes.iget_wide.d.T_iget_wide_30");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iget_wide.d.T_iget_wide_30", VerifyError.class);
+    }
+
+    /**
+     * @constraint N/A
+     * @title instance fields may only be accessed on already initialized instances. 
+     */
+    public void testVFE31() {
+        load("dot.junit.opcodes.iget_wide.d.T_iget_wide_31", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iget_wide/d/T_iget_wide_31.d b/tools/vm-tests-tf/src/dot/junit/opcodes/iget_wide/d/T_iget_wide_31.d
new file mode 100644
index 0000000..7f97a07
--- /dev/null
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iget_wide/d/T_iget_wide_31.d
@@ -0,0 +1,32 @@
+; 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.
+
+.source T_iget_wide_31.java
+.class public dot.junit.opcodes.iget_wide.d.T_iget_wide_31
+.super java/lang/Object
+
+.field public  st_i1 J
+
+.method public <init>()V
+.limit regs 1
+       invoke-direct {v0}, java/lang/Object/<init>()V
+       return-void
+.end method
+
+.method public run()J
+.limit regs 3
+    iget v0, v0, dot.junit.opcodes.iget_wide.d.T_iget_wide_31.st_i1 J
+    return v0
+.end method
+
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/instance_of/Test_instance_of.java b/tools/vm-tests-tf/src/dot/junit/opcodes/instance_of/Test_instance_of.java
index b0a6cc6..f35e147 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/instance_of/Test_instance_of.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/instance_of/Test_instance_of.java
@@ -64,28 +64,14 @@
      */
     public void testE2() {
         //@uses dot.junit.opcodes.instance_of.TestStubs
-        //@uses dot.junit.opcodes.instance_of.d.T_instance_of_3
-        try {
-            T_instance_of_3 tt = new T_instance_of_3();
-            tt.run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError e) {
-        }
+        loadAndRun("dot.junit.opcodes.instance_of.d.T_instance_of_3", IllegalAccessError.class);
     }
 
     /**
      * @title Attempt to access undefined class.
      */
     public void testE3() {
-        try {
-            T_instance_of_7 tt = new T_instance_of_7();
-            tt.run();
-            fail("expected a verification exception");
-        } catch (NoClassDefFoundError e) {
-            // expected
-        } catch(VerifyError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.instance_of.d.T_instance_of_7", NoClassDefFoundError.class);
     }
 
     /**
@@ -93,12 +79,7 @@
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.instance_of.d.T_instance_of_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.instance_of.d.T_instance_of_4", VerifyError.class);
     }
 
     /**
@@ -107,12 +88,7 @@
      * @title type of argument - int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.instance_of.d.T_instance_of_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.instance_of.d.T_instance_of_5", VerifyError.class);
     }
 
     /**
@@ -121,12 +97,7 @@
      * @title type of argument - long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.instance_of.d.T_instance_of_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.instance_of.d.T_instance_of_8", VerifyError.class);
     }
 
     /**
@@ -135,12 +106,7 @@
      * @title number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.instance_of.d.T_instance_of_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.instance_of.d.T_instance_of_6", VerifyError.class);
     }
 
 
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/int_to_byte/Test_int_to_byte.java b/tools/vm-tests-tf/src/dot/junit/opcodes/int_to_byte/Test_int_to_byte.java
index ad50cb6..9401e14 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/int_to_byte/Test_int_to_byte.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/int_to_byte/Test_int_to_byte.java
@@ -134,12 +134,7 @@
      * @title type of argument - double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_byte.d.T_int_to_byte_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_byte.d.T_int_to_byte_2", VerifyError.class);
     }
 
     /**
@@ -148,12 +143,7 @@
      * @title type of argument - long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_byte.d.T_int_to_byte_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_byte.d.T_int_to_byte_3", VerifyError.class);
     }
 
     /**
@@ -162,12 +152,7 @@
      * @title type of argument - reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_byte.d.T_int_to_byte_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_byte.d.T_int_to_byte_4", VerifyError.class);
     }
     
     /**
@@ -175,12 +160,7 @@
      * @title number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_byte.d.T_int_to_byte_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_byte.d.T_int_to_byte_6", VerifyError.class);
     }
 
     /**
@@ -189,12 +169,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_byte.d.T_int_to_byte_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_byte.d.T_int_to_byte_5", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/int_to_char/Test_int_to_char.java b/tools/vm-tests-tf/src/dot/junit/opcodes/int_to_char/Test_int_to_char.java
index c6aa047..4c3f8ac 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/int_to_char/Test_int_to_char.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/int_to_char/Test_int_to_char.java
@@ -93,12 +93,7 @@
      * @title type of argument - double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_char.d.T_int_to_char_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_char.d.T_int_to_char_2", VerifyError.class);
     }
 
     /**
@@ -106,12 +101,7 @@
      * @title type of argument - long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_char.d.T_int_to_char_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_char.d.T_int_to_char_3", VerifyError.class);
     }
 
     /**
@@ -119,12 +109,7 @@
      * @title type of argument - reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_char.d.T_int_to_char_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_char.d.T_int_to_char_4", VerifyError.class);
     }
     
     /**
@@ -132,12 +117,7 @@
      * @title number of registers
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_char.d.T_int_to_char_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_char.d.T_int_to_char_6", VerifyError.class);
     }
 
     /**
@@ -146,12 +126,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_char.d.T_int_to_char_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_char.d.T_int_to_char_5", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/int_to_double/Test_int_to_double.java b/tools/vm-tests-tf/src/dot/junit/opcodes/int_to_double/Test_int_to_double.java
index 675821b..892f461 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/int_to_double/Test_int_to_double.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/int_to_double/Test_int_to_double.java
@@ -77,12 +77,7 @@
      * @title  type of argument - long
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_double.d.T_int_to_double_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_double.d.T_int_to_double_3", VerifyError.class);
     }
 
     /**
@@ -90,12 +85,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_double.d.T_int_to_double_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_double.d.T_int_to_double_4", VerifyError.class);
     }
 
     /**
@@ -103,12 +93,7 @@
      * @title  type of argument - reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_double.d.T_int_to_double_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_double.d.T_int_to_double_5", VerifyError.class);
     }
 
     /**
@@ -116,12 +101,7 @@
      * @title  number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_double.d.T_int_to_double_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_double.d.T_int_to_double_7", VerifyError.class);
     }
 
     /**
@@ -130,11 +110,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_double.d.T_int_to_double_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_double.d.T_int_to_double_6", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/int_to_float/Test_int_to_float.java b/tools/vm-tests-tf/src/dot/junit/opcodes/int_to_float/Test_int_to_float.java
index eaa7a31..a6f1742 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/int_to_float/Test_int_to_float.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/int_to_float/Test_int_to_float.java
@@ -85,12 +85,7 @@
      * @title  (type of argument - double)
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_float.d.T_int_to_float_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_float.d.T_int_to_float_2", VerifyError.class);
     }
 
     /**
@@ -99,12 +94,7 @@
      * @title type of argument - long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_float.d.T_int_to_float_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_float.d.T_int_to_float_3", VerifyError.class);
     }
 
     /**
@@ -113,12 +103,7 @@
      * @title type of argument - reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_float.d.T_int_to_float_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_float.d.T_int_to_float_4", VerifyError.class);
     }
     
     /**
@@ -126,12 +111,7 @@
      * @title number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_float.d.T_int_to_float_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_float.d.T_int_to_float_6", VerifyError.class);
     }
 
     /**
@@ -140,12 +120,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_float.d.T_int_to_float_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_float.d.T_int_to_float_5", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/int_to_long/Test_int_to_long.java b/tools/vm-tests-tf/src/dot/junit/opcodes/int_to_long/Test_int_to_long.java
index 41db35d..931b79c 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/int_to_long/Test_int_to_long.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/int_to_long/Test_int_to_long.java
@@ -77,12 +77,7 @@
      * @title type of argument - double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_long.d.T_int_to_long_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_long.d.T_int_to_long_2", VerifyError.class);
     }
 
     /**
@@ -91,12 +86,7 @@
      * @title type of argument - long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_long.d.T_int_to_long_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_long.d.T_int_to_long_3", VerifyError.class);
     }
 
     /**
@@ -104,12 +94,7 @@
      * @title number of registers
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_long.d.T_int_to_long_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_long.d.T_int_to_long_4", VerifyError.class);
     }
 
     /**
@@ -117,12 +102,7 @@
      * @title type of argument - reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_long.d.T_int_to_long_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_long.d.T_int_to_long_5", VerifyError.class);
     }
 
     /**
@@ -130,12 +110,7 @@
      * @title number of registers
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_long.d.T_int_to_long_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_long.d.T_int_to_long_7", VerifyError.class);
     }
 
     /**
@@ -144,11 +119,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_long.d.T_int_to_long_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_long.d.T_int_to_long_6", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/int_to_short/Test_int_to_short.java b/tools/vm-tests-tf/src/dot/junit/opcodes/int_to_short/Test_int_to_short.java
index b245fc1..898b8ad 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/int_to_short/Test_int_to_short.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/int_to_short/Test_int_to_short.java
@@ -109,12 +109,7 @@
      * @title type of argument - double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_short.d.T_int_to_short_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_short.d.T_int_to_short_2", VerifyError.class);
     }
 
     /**
@@ -123,12 +118,7 @@
      * @title type of argument - long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_short.d.T_int_to_short_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_short.d.T_int_to_short_3", VerifyError.class);
     }
 
     /**
@@ -137,12 +127,7 @@
      * @title  type of argument - reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_short.d.T_int_to_short_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_short.d.T_int_to_short_4", VerifyError.class);
     }
     
     /**
@@ -150,12 +135,7 @@
      * @title  number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_short.d.T_int_to_short_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_short.d.T_int_to_short_6", VerifyError.class);
     }
 
     /**
@@ -164,12 +144,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.int_to_short.d.T_int_to_short_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.int_to_short.d.T_int_to_short_5", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_direct/Test_invoke_direct.java b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_direct/Test_invoke_direct.java
index 1772f22..34462f6 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_direct/Test_invoke_direct.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_direct/Test_invoke_direct.java
@@ -54,26 +54,16 @@
      * @title objref is null
      */
     public void testE3() {
-        T_invoke_direct_8 t = new T_invoke_direct_8();
-        try {
-            assertEquals(5, t.run());
-            fail("expected NullPointerException");
-        } catch (NullPointerException e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_8",
+                   NullPointerException.class);
     }
 
     /**
      * @title Native method can't be linked
      */
     public void testE5() {
-        T_invoke_direct_9 t = new T_invoke_direct_9();
-        try {
-            assertEquals(5, t.run());
-            fail("expected UnsatisfiedLinkError");
-        } catch (UnsatisfiedLinkError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_9",
+                   UnsatisfiedLinkError.class);
     }
 
     /**
@@ -81,12 +71,7 @@
      * @title invalid constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_3", VerifyError.class);
     }
 
     /**
@@ -94,12 +79,7 @@
      * @title invoke-direct may not be used to invoke &lt;clinit&gt;
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_4", VerifyError.class);
     }
 
     /**
@@ -107,13 +87,8 @@
      * @title invoke-direct target must be in self or superclass
      */
     public void testVFE4() {
-        //@uses dot.junit.opcodes.invoke_direct.d.T_invoke_direct_6
         //@uses dot.junit.opcodes.invoke_direct.TSuper
-        try {
-            new T_invoke_direct_6();
-            fail("expected NoSuchMethodError");
-        } catch (NoSuchMethodError t) {
-        }
+        load("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_6", VerifyError.class);
     }
 
     /**
@@ -121,12 +96,7 @@
      * @title number of arguments
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_5", VerifyError.class);
     }
 
     /**
@@ -134,12 +104,7 @@
      * @title int is passed instead of obj ref
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_10", VerifyError.class);
     }
 
 
@@ -148,12 +113,7 @@
      * @title number of arguments passed to method
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_14");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_14", VerifyError.class);
     }
 
     /**
@@ -161,12 +121,7 @@
      * @title types of arguments passed to method
      */
     public void testVFE9() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_24");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_24", VerifyError.class);
     }
 
     /**
@@ -174,15 +129,9 @@
      * @title assignment incompatible references when accessing protected method
      */
     public void testVFE10() {
-        //@uses dot.junit.opcodes.invoke_direct.d.T_invoke_direct_25
         //@uses dot.junit.opcodes.invoke_direct.TPlain
         //@uses dot.junit.opcodes.invoke_direct.TSuper
-        try {
-            Class.forName("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_25");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_25", VerifyError.class);
     }
 
     /**
@@ -190,14 +139,9 @@
      * @title  Superclass' method call
      */
     public void testVFE11() {
-        //@uses dot.junit.opcodes.invoke_direct.d.T_invoke_direct_25
         //@uses dot.junit.opcodes.invoke_direct.TSuper
-        try {
-            Class.forName("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_1");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        loadAndRun("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_1",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -205,12 +149,7 @@
      * @title number of registers
      */
     public void testVFE12() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_15");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_15", VerifyError.class);
     }
 
 
@@ -219,11 +158,7 @@
      * @title Attempt to call undefined method.
      */
     public void testVFE13() {
-        try {
-            new T_invoke_direct_7().run();
-            fail("expected NoSuchMethodError");
-        } catch (NoSuchMethodError t) {
-        }
+        loadAndRun("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_7", NoSuchMethodError.class);
     }
 
     /**
@@ -231,25 +166,17 @@
      * @title Method has different signature.
      */
     public void testVFE14() {
-        try {
-            new T_invoke_direct_16().run();
-            fail("expected NoSuchMethodError");
-        } catch (NoSuchMethodError t) {
-        }
+        loadAndRun("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_16", NoSuchMethodError.class);
     }
 
     /**
      * @constraint n/a
      * @title Attempt to invoke static method. Java throws IncompatibleClassChangeError
-     * on first access but Dalvik throws VerifyError on class loading.
+     * on first access. Dalvik threw VerifyError on class loading.
      */
     public void testVFE15() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        loadAndRun("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_11",
+                   IncompatibleClassChangeError.class);
     }
 
 
@@ -258,13 +185,9 @@
      * @title Attempt to invoke private method of superclass.
      */
     public void testVFE16() {
-        //@uses dot.junit.opcodes.invoke_direct.d.T_invoke_direct_12
         //@uses dot.junit.opcodes.invoke_direct.TSuper
-        try {
-            new T_invoke_direct_12().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_12",
+                   IllegalAccessError.class);
     }
 
 
@@ -273,15 +196,9 @@
      * @title Attempt to invoke abstract method
      */
     public void testVFE17() {
-        //@uses dot.junit.opcodes.invoke_direct.d.T_invoke_direct_13
         //@uses dot.junit.opcodes.invoke_direct.TAbstract
-        try {
-            new T_invoke_direct_13().run();
-            fail("expected NoSuchMethodError or verification exception");
-        } catch (NoSuchMethodError t) {
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        loadAndRun("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_13",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -289,12 +206,7 @@
      * @title An instance initializer must only be invoked on an uninitialized instance.
      */
     public void testVFE18() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_17");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_17", VerifyError.class);
     }
 
     /**
@@ -302,14 +214,8 @@
      * @title attempt to access inherited instance field before <init> is called
      */
     public void testVFE19() {
-        //@uses dot.junit.opcodes.invoke_direct.d.T_invoke_direct_18
         //@uses dot.junit.opcodes.invoke_direct.TSuper
-        try {
-            Class.forName("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_18", VerifyError.class);
     }
 
     /**
@@ -317,13 +223,8 @@
      * @title attempt to invoke interface method
      */
     public void testVFE20() {
-        //@uses dot.junit.opcodes.invoke_direct.d.T_invoke_direct_26
-        try {
-            new T_invoke_direct_26().run();
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        loadAndRun("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_26",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -331,11 +232,6 @@
      * @title instance methods may only be invoked on already initialized instances.
      */
     public void testVFE21() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_27");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_direct.d.T_invoke_direct_27", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_direct/d/T_invoke_direct_7.d b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_direct/d/T_invoke_direct_7.d
index 2c1b99b..13432bd 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_direct/d/T_invoke_direct_7.d
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_direct/d/T_invoke_direct_7.d
@@ -27,7 +27,7 @@
 .method public run()I
 .limit regs 3
 
-       invoke-direct {v1}, dot/junit/opcodes/invoke_direct/d/T_invoke_direct_7/toInt()I
+       invoke-direct {v2}, dot/junit/opcodes/invoke_direct/d/T_invoke_direct_7/toInt()I
        const v0, 0
        return v0
 .end method
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_direct_range/Test_invoke_direct_range.java b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_direct_range/Test_invoke_direct_range.java
index d4f194b..2a926e7 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_direct_range/Test_invoke_direct_range.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_direct_range/Test_invoke_direct_range.java
@@ -54,26 +54,16 @@
      * @title objref is null
      */
     public void testE3() {
-        T_invoke_direct_range_8 t = new T_invoke_direct_range_8();
-        try {
-            assertEquals(5, t.run());
-            fail("expected NullPointerException");
-        } catch (NullPointerException e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_8",
+                   NullPointerException.class);
     }
 
     /**
      * @title Native method can't be linked
      */
     public void testE5() {
-        T_invoke_direct_range_9 t = new T_invoke_direct_range_9();
-        try {
-            assertEquals(5, t.run());
-            fail("expected UnsatisfiedLinkError");
-        } catch (UnsatisfiedLinkError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_9",
+                   UnsatisfiedLinkError.class);
     }
 
     /**
@@ -81,12 +71,7 @@
      * @title invalid constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_3", VerifyError.class);
     }
 
     /**
@@ -94,12 +79,7 @@
      * @title invoke-direct may not be used to invoke &lt;clinit&gt;
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_4", VerifyError.class);
     }
 
     /**
@@ -107,13 +87,8 @@
      * @title invoke-direct target must be in self or superclass
      */
     public void testVFE4() {
-        //@uses dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_6
         //@uses dot.junit.opcodes.invoke_direct_range.TSuper
-        try {
-            new T_invoke_direct_range_6();
-            fail("expected NoSuchMethodError");
-        } catch (NoSuchMethodError t) {
-        }
+        load("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_6", VerifyError.class);
     }
 
     /**
@@ -121,12 +96,7 @@
      * @title number of arguments
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_5", VerifyError.class);
     }
 
     /**
@@ -134,12 +104,7 @@
      * @title int is passed instead of obj ref
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_10", VerifyError.class);
     }
 
 
@@ -148,12 +113,7 @@
      * @title number of arguments passed to method
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_14");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_14", VerifyError.class);
     }
 
     /**
@@ -161,12 +121,7 @@
      * @title types of arguments passed to method
      */
     public void testVFE9() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_24");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_24", VerifyError.class);
     }
 
     /**
@@ -174,15 +129,9 @@
      * @title assignment incompatible references when accessing protected method
      */
     public void testVFE10() {
-        //@uses dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_25
         //@uses dot.junit.opcodes.invoke_direct_range.TPlain
         //@uses dot.junit.opcodes.invoke_direct_range.TSuper
-        try {
-            Class.forName("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_25");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_25", VerifyError.class);
     }
 
     /**
@@ -190,14 +139,9 @@
      * @title  Superclass' method call
      */
     public void testVFE11() {
-        //@uses dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_25
         //@uses dot.junit.opcodes.invoke_direct_range.TSuper
-        try {
-            Class.forName("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_1");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        loadAndRun("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_1", 
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -205,12 +149,7 @@
      * @title number of registers
      */
     public void testVFE12() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_15");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_15", VerifyError.class);
     }
 
 
@@ -219,11 +158,8 @@
      * @title Attempt to call undefined method.
      */
     public void testVFE13() {
-        try {
-            new T_invoke_direct_range_7().run();
-            fail("expected NoSuchMethodError");
-        } catch (NoSuchMethodError t) {
-        }
+        loadAndRun("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_7",
+                   NoSuchMethodError.class);
     }
 
     /**
@@ -231,25 +167,18 @@
      * @title Method has different signature.
      */
     public void testVFE14() {
-        try {
-            new T_invoke_direct_range_16().run();
-            fail("expected NoSuchMethodError");
-        } catch (NoSuchMethodError t) {
-        }
+        loadAndRun("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_16",
+                   NoSuchMethodError.class);
     }
 
     /**
      * @constraint n/a
      * @title Attempt to invoke static method. Java throws IncompatibleClassChangeError
-     * on first access but Dalvik throws VerifyError on class loading.
+     * on first access. Dalvik threw VerifyError on class loading.
      */
     public void testVFE15() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        loadAndRun("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_11",
+                   IncompatibleClassChangeError.class);
     }
 
 
@@ -259,13 +188,9 @@
      * on first access but Dalvik throws VerifyError on class loading.
      */
     public void testVFE16() {
-        //@uses dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_12
         //@uses dot.junit.opcodes.invoke_direct_range.TSuper
-        try {
-            new T_invoke_direct_range_12().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_12",
+                   IllegalAccessError.class);
     }
 
 
@@ -274,15 +199,9 @@
      * @title Attempt to invoke abstract method
      */
     public void testVFE17() {
-        //@uses dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_13
         //@uses dot.junit.opcodes.invoke_direct_range.TAbstract
-        try {
-            new T_invoke_direct_range_13().run();
-            fail("expected NoSuchMethodError or verification exception");
-        } catch (NoSuchMethodError t) {
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        loadAndRun("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_13",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -290,12 +209,7 @@
      * @title An instance initializer must only be invoked on an uninitialized instance.
      */
     public void testVFE18() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_17");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_17", VerifyError.class);
     }
 
     /**
@@ -303,14 +217,8 @@
      * @title attempt to access inherited instance field before <init> is called
      */
     public void testVFE19() {
-        //@uses dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_18
         //@uses dot.junit.opcodes.invoke_direct_range.TSuper
-        try {
-            Class.forName("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_18", VerifyError.class);
     }
 
     /**
@@ -318,13 +226,8 @@
      * @title attempt to invoke interface method
      */
     public void testVFE20() {
-        //@uses dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_26
-        try {
-            new T_invoke_direct_range_26().run();
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        loadAndRun("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_26",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -332,11 +235,6 @@
      * @title instance methods may only be invoked on already initialized instances.
      */
     public void testVFE21() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_27");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_direct_range.d.T_invoke_direct_range_27", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_direct_range/d/T_invoke_direct_range_7.d b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_direct_range/d/T_invoke_direct_range_7.d
index f0254f4..0e7aab0 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_direct_range/d/T_invoke_direct_range_7.d
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_direct_range/d/T_invoke_direct_range_7.d
@@ -27,7 +27,7 @@
 .method public run()I
 .limit regs 3
 
-       invoke-direct/range {v1}, dot/junit/opcodes/invoke_direct_range/d/T_invoke_direct_range_7/toInt()I
+       invoke-direct/range {v2}, dot/junit/opcodes/invoke_direct_range/d/T_invoke_direct_range_7/toInt()I
        const v0, 0
        return v0
 .end method
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_interface/Test_invoke_interface.java b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_interface/Test_invoke_interface.java
index f846374..6972253 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_interface/Test_invoke_interface.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_interface/Test_invoke_interface.java
@@ -63,30 +63,19 @@
      * @title objref is null
      */
     public void testE3() {
-        //@uses dot.junit.opcodes.invoke_interface.d.T_invoke_interface_3
         //@uses dot.junit.opcodes.invoke_interface.ITest
-        try {
-            new T_invoke_interface_3(null);
-            fail("expected NullPointerException");
-        } catch (NullPointerException npe) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_interface.d.T_invoke_interface_3",
+                   NullPointerException.class);
     }
 
     /**
      * @title object doesn't implement interface
      */
     public void testE4() {
-        //@uses dot.junit.opcodes.invoke_interface.d.T_invoke_interface_11
         //@uses dot.junit.opcodes.invoke_interface.ITest
         //@uses dot.junit.opcodes.invoke_interface.ITestImpl
-        T_invoke_interface_11 t = new T_invoke_interface_11();
-        try {
-            t.run();
-            fail("expected IncompatibleClassChangeError");
-        } catch (IncompatibleClassChangeError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_interface.d.T_invoke_interface_11",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -99,51 +88,31 @@
         //@uses dot.junit.opcodes.invoke_interface.d.T_invoke_interface_11
         //@uses dot.junit.opcodes.invoke_interface.ITest
         //@uses dot.junit.opcodes.invoke_interface.ITestImpl
-        T_invoke_interface_11 t = new T_invoke_interface_11();
-        try {
-            t.run();
-            fail("expected IncompatibleClassChangeError");
-        } catch (IncompatibleClassChangeError expected) {
-        }
-        try {
-            t.run();
-            fail("expected IncompatibleClassChangeError");
-        } catch (IncompatibleClassChangeError expected) {
-        }
+        loadAndRun("dot.junit.opcodes.invoke_interface.d.T_invoke_interface_11",
+                   IncompatibleClassChangeError.class);
+        loadAndRun("dot.junit.opcodes.invoke_interface.d.T_invoke_interface_11",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
      * @title Native method can't be linked
      */
     public void testE5() {
-        //@uses dot.junit.opcodes.invoke_interface.d.T_invoke_interface_12
         //@uses dot.junit.opcodes.invoke_interface.ITest
         //@uses dot.junit.opcodes.invoke_interface.ITestImpl
-        T_invoke_interface_12 t = new T_invoke_interface_12();
-        ITestImpl impl = new ITestImpl();
-        try {
-            t.run(impl);
-            fail("expected UnsatisfiedLinkError");
-        } catch (UnsatisfiedLinkError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_interface.d.T_invoke_interface_12",
+                   UnsatisfiedLinkError.class, new ITestImpl());
     }
 
     /**
      * @title Attempt to invoke abstract method
      */
     public void testE6() {
-        //@uses dot.junit.opcodes.invoke_interface.d.T_invoke_interface_13
         //@uses dot.junit.opcodes.invoke_interface.ITest
         //@uses dot.junit.opcodes.invoke_interface.ITestImpl
         //@uses dot.junit.opcodes.invoke_interface.ITestImplAbstract
-        T_invoke_interface_13 t = new T_invoke_interface_13();
-        try {
-            t.run();
-            fail("expected AbstractMethodError");
-        } catch (AbstractMethodError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_interface.d.T_invoke_interface_13",
+                   AbstractMethodError.class);
     }
 
     /**
@@ -151,12 +120,7 @@
      * @title invalid constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_interface.d.T_invoke_interface_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_interface.d.T_invoke_interface_2", VerifyError.class);
     }
 
     /**
@@ -164,12 +128,8 @@
      * @title The referenced method_id must belong to an interface (not a class).
      */
     public void testVFE2() {
-        try {
-            new T_invoke_interface_4().run();
-            fail("expected NoSuchMethodError or IncompatibleClassChangeError");
-        } catch (NoSuchMethodError t) {
-        } catch (IncompatibleClassChangeError e) {
-        }
+        loadAndRun("dot.junit.opcodes.invoke_interface.d.T_invoke_interface_4",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -179,11 +139,7 @@
     public void testVFE5() {
         //@uses dot.junit.opcodes.invoke_interface.ITest
         //@uses dot.junit.opcodes.invoke_interface.ITestImpl
-        try {
-            new T_invoke_interface_5(new ITestImpl());
-            fail("expected VerifyError");
-        } catch (VerifyError t) {
-        }
+        load("dot.junit.opcodes.invoke_interface.d.T_invoke_interface_5", VerifyError.class);
     }
 
     /**
@@ -191,12 +147,7 @@
      * @title int is passed instead of objref
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_interface.d.T_invoke_interface_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_interface.d.T_invoke_interface_10", VerifyError.class);
     }
 
     /**
@@ -204,12 +155,7 @@
      * @title number of arguments passed to method
      */
     public void testVFE9() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_interface.d.T_invoke_interface_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_interface.d.T_invoke_interface_9", VerifyError.class);
     }
 
     /**
@@ -218,13 +164,7 @@
      */
     public void testVFE10() {
         //@uses dot.junit.opcodes.invoke_interface.d.T_invoke_interface_18
-        try {
-            new T_invoke_interface_18().run(new ITestImpl());
-            fail("expected NoSuchMethodError or verification exception");
-        } catch (NoSuchMethodError t) {
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_interface.d.T_invoke_interface_18", VerifyError.class);
     }
 
     /**
@@ -234,13 +174,7 @@
     public void testVFE11() {
         //@uses dot.junit.opcodes.invoke_interface.ITest
         //@uses dot.junit.opcodes.invoke_interface.ITestImpl
-        try {
-            new T_invoke_interface_20().run(new ITestImpl());
-            fail("expected NoSuchMethodError or verification exception");
-        } catch (NoSuchMethodError t) {
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_interface.d.T_invoke_interface_20", VerifyError.class);
     }
 
     /**
@@ -250,11 +184,7 @@
     public void testVFE12() {
         //@uses dot.junit.opcodes.invoke_interface.ITest
         //@uses dot.junit.opcodes.invoke_interface.ITestImpl
-        try {
-            new T_invoke_interface_21().run(new ITestImpl());
-            fail("expected VerifyError");
-        } catch (VerifyError t) {
-        }
+        load("dot.junit.opcodes.invoke_interface.d.T_invoke_interface_21", VerifyError.class);
     }
 
     /**
@@ -262,12 +192,7 @@
      * @title number of registers
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_interface.d.T_invoke_interface_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_interface.d.T_invoke_interface_8", VerifyError.class);
     }
 
     /**
@@ -275,14 +200,10 @@
      * @title Attempt to call undefined method.
      */
     public void testVFE14() {
-        //@uses dot.junit.opcodes.invoke_interface.d.T_invoke_interface_7
         //@uses dot.junit.opcodes.invoke_interface.ITest
         //@uses dot.junit.opcodes.invoke_interface.ITestImpl
-        try {
-            new T_invoke_interface_7().run(new ITestImpl());
-            fail("expected NoSuchMethodError");
-        } catch (NoSuchMethodError t) {
-        }
+        loadAndRun("dot.junit.opcodes.invoke_interface.d.T_invoke_interface_7",
+                   NoSuchMethodError.class, new ITestImpl());
     }
 
     /**
@@ -290,14 +211,10 @@
      * @title Method has different signature.
      */
     public void testVFE15() {
-        //@uses dot.junit.opcodes.invoke_interface.d.T_invoke_interface_16
         //@uses dot.junit.opcodes.invoke_interface.ITest
         //@uses dot.junit.opcodes.invoke_interface.ITestImpl
-        try {
-            new T_invoke_interface_16().run(new ITestImpl());
-            fail("expected NoSuchMethodError");
-        } catch (NoSuchMethodError t) {
-        }
+        loadAndRun("dot.junit.opcodes.invoke_interface.d.T_invoke_interface_16",
+                   NoSuchMethodError.class, new ITestImpl());
     }
 
 
@@ -306,14 +223,8 @@
      * @title instance methods may only be invoked on already initialized instances.
      */
     public void testVFE21() {
-        //@uses dot.junit.opcodes.invoke_interface.d.T_invoke_interface_22
         //@uses dot.junit.opcodes.invoke_interface.ITest
         //@uses dot.junit.opcodes.invoke_interface.ITestImpl
-        try {
-            Class.forName("dot.junit.opcodes.invoke_interface.d.T_invoke_interface_22");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_interface.d.T_invoke_interface_22", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_interface/d/T_invoke_interface_3.d b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_interface/d/T_invoke_interface_3.d
index debf41a..44251bf 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_interface/d/T_invoke_interface_3.d
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_interface/d/T_invoke_interface_3.d
@@ -16,14 +16,15 @@
 .class public dot.junit.opcodes.invoke_interface.d.T_invoke_interface_3
 .super java/lang/Object
 
-
-.method public <init>(Ldot/junit/opcodes/invoke_interface/ITest;)V
-.limit regs 5
-Label0:
-       invoke-direct {v3}, java/lang/Object/<init>()V
-
-       invoke-interface {v4}, dot/junit/opcodes/invoke_interface/ITest/doit()V
+.method public <init>()V
+.limit regs 2
+       invoke-direct {v1}, java/lang/Object/<init>()V
        return-void
 .end method
 
-
+.method public run()V
+.limit regs 5
+       const/4 v1, 0
+       invoke-interface {v1}, dot/junit/opcodes/invoke_interface/ITest/doit()V
+       return-void
+.end method
\ No newline at end of file
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_interface_range/Test_invoke_interface_range.java b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_interface_range/Test_invoke_interface_range.java
index 9f98d4c..8faa506 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_interface_range/Test_invoke_interface_range.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_interface_range/Test_invoke_interface_range.java
@@ -63,64 +63,40 @@
      * @title objref is null
      */
     public void testE3() {
-        //@uses dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_3
         //@uses dot.junit.opcodes.invoke_interface_range.ITest
-        try {
-            new T_invoke_interface_range_3(null);
-            fail("expected NullPointerException");
-        } catch (NullPointerException npe) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_3",
+                   NullPointerException.class);
     }
 
     /**
      * @title object doesn't implement interface
      */
     public void testE4() {
-        //@uses dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_11
         //@uses dot.junit.opcodes.invoke_interface_range.ITest
         //@uses dot.junit.opcodes.invoke_interface_range.ITestImpl
-        T_invoke_interface_range_11 t = new T_invoke_interface_range_11();
-        try {
-            t.run();
-            fail("expected IncompatibleClassChangeError");
-        } catch (IncompatibleClassChangeError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_11",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
      * @title Native method can't be linked
      */
     public void testE5() {
-        //@uses dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_12
         //@uses dot.junit.opcodes.invoke_interface_range.ITest
         //@uses dot.junit.opcodes.invoke_interface_range.ITestImpl
-        T_invoke_interface_range_12 t = new T_invoke_interface_range_12();
-        ITestImpl impl = new ITestImpl();
-        try {
-            t.run(impl);
-            fail("expected UnsatisfiedLinkError");
-        } catch (UnsatisfiedLinkError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_12",
+                   UnsatisfiedLinkError.class, new ITestImpl());
     }
 
     /**
      * @title Attempt to invoke abstract method
      */
     public void testE6() {
-        //@uses dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_13
         //@uses dot.junit.opcodes.invoke_interface_range.ITest
         //@uses dot.junit.opcodes.invoke_interface_range.ITestImpl
         //@uses dot.junit.opcodes.invoke_interface_range.ITestImplAbstract
-        T_invoke_interface_range_13 t = new T_invoke_interface_range_13();
-        try {
-            t.run();
-            fail("expected AbstractMethodError");
-        } catch (AbstractMethodError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_13",
+                   AbstractMethodError.class);
     }
 
     /**
@@ -128,12 +104,8 @@
      * @title invalid constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_2",
+             VerifyError.class);
     }
 
     /**
@@ -141,12 +113,8 @@
      * @title The referenced method_id must belong to an interface (not a class).
      */
     public void testVFE2() {
-        try {
-            new T_invoke_interface_range_4().run();
-            fail("expected NoSuchMethodError or IncompatibleClassChangeError");
-        } catch (NoSuchMethodError t) {
-        } catch (IncompatibleClassChangeError e) {
-        }
+        loadAndRun("dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_4",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -156,11 +124,8 @@
     public void testVFE5() {
         //@uses dot.junit.opcodes.invoke_interface_range.ITest
         //@uses dot.junit.opcodes.invoke_interface_range.ITestImpl
-        try {
-            new T_invoke_interface_range_5(new ITestImpl());
-            fail("expected VerifyError");
-        } catch (VerifyError t) {
-        }
+        load("dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_5",
+             VerifyError.class);
     }
 
     /**
@@ -168,12 +133,8 @@
      * @title int is passed instead of objref
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_10",
+             VerifyError.class);
     }
 
     /**
@@ -181,12 +142,8 @@
      * @title number of arguments passed to method
      */
     public void testVFE9() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_9",
+             VerifyError.class);
     }
 
     /**
@@ -194,14 +151,10 @@
      * @title invoke-interface may not be used to call <init>.
      */
     public void testVFE10() {
-        //@uses dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_18
-        try {
-            new T_invoke_interface_range_18().run(new ITestImpl());
-            fail("expected NoSuchMethodError or verification exception");
-        } catch (NoSuchMethodError t) {
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        //@uses dot.junit.opcodes.invoke_interface_range.ITest
+        //@uses dot.junit.opcodes.invoke_interface_range.ITestImpl
+        load("dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_18",
+             VerifyError.class);
     }
 
     /**
@@ -211,13 +164,8 @@
     public void testVFE11() {
         //@uses dot.junit.opcodes.invoke_interface_range.ITest
         //@uses dot.junit.opcodes.invoke_interface_range.ITestImpl
-        try {
-            new T_invoke_interface_range_20().run(new ITestImpl());
-            fail("expected NoSuchMethodError or verification exception");
-        } catch (NoSuchMethodError t) {
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_20",
+             VerifyError.class);
     }
 
     /**
@@ -227,11 +175,8 @@
     public void testVFE12() {
         //@uses dot.junit.opcodes.invoke_interface_range.ITest
         //@uses dot.junit.opcodes.invoke_interface_range.ITestImpl
-        try {
-            new T_invoke_interface_range_21().run(new ITestImpl());
-            fail("expected VerifyError");
-        } catch (VerifyError t) {
-        }
+        load("dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_21",
+             VerifyError.class);
     }
 
     /**
@@ -239,12 +184,8 @@
      * @title number of registers
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_8",
+             VerifyError.class);
     }
 
     /**
@@ -252,14 +193,10 @@
      * @title Attempt to call undefined method.
      */
     public void testVFE14() {
-        //@uses dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_7
         //@uses dot.junit.opcodes.invoke_interface_range.ITest
         //@uses dot.junit.opcodes.invoke_interface_range.ITestImpl
-        try {
-            new T_invoke_interface_range_7().run(new ITestImpl());
-            fail("expected NoSuchMethodError");
-        } catch (NoSuchMethodError t) {
-        }
+        loadAndRun("dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_7",
+                   NoSuchMethodError.class, new ITestImpl());
     }
 
     /**
@@ -267,15 +204,10 @@
      * @title Method has different signature.
      */
     public void testVFE15() {
-        //@uses dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_16
         //@uses dot.junit.opcodes.invoke_interface_range.ITest
         //@uses dot.junit.opcodes.invoke_interface_range.ITestImpl
-        try {
-            new T_invoke_interface_range_16().run(new ITestImpl());
-            fail("expected NoSuchMethodError");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        loadAndRun("dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_16",
+                   NoSuchMethodError.class, new ITestImpl());
     }
 
     /**
@@ -286,11 +218,7 @@
         //@uses dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_22
         //@uses dot.junit.opcodes.invoke_interface_range.ITest
         //@uses dot.junit.opcodes.invoke_interface_range.ITestImpl
-        try {
-            Class.forName("dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_22");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_22",
+             VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_interface_range/d/T_invoke_interface_range_3.d b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_interface_range/d/T_invoke_interface_range_3.d
index ca4948d..eaf5408 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_interface_range/d/T_invoke_interface_range_3.d
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_interface_range/d/T_invoke_interface_range_3.d
@@ -16,13 +16,16 @@
 .class public dot.junit.opcodes.invoke_interface_range.d.T_invoke_interface_range_3
 .super java/lang/Object
 
+.method public <init>()V
+.limit regs 2
+       invoke-direct {v1}, java/lang/Object/<init>()V
+       return-void
+.end method
 
-.method public <init>(Ldot/junit/opcodes/invoke_interface_range/ITest;)V
+.method public run()V
 .limit regs 5
-Label0:
-       invoke-direct {v3}, java/lang/Object/<init>()V
-
-       invoke-interface/range {v4}, dot/junit/opcodes/invoke_interface_range/ITest/doit()V
+       const/4 v1, 0
+       invoke-interface/range {v1}, dot/junit/opcodes/invoke_interface_range/ITest/doit()V
        return-void
 .end method
 
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_static/Test_invoke_static.java b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_static/Test_invoke_static.java
index 02793fd..efcdf23 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_static/Test_invoke_static.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_static/Test_invoke_static.java
@@ -87,41 +87,24 @@
      *
      */
     public void testE2() {
-        T_invoke_static_6 t = new T_invoke_static_6();
-        try {
-            t.run();
-            fail("expected UnsatisfiedLinkError");
-        } catch (UnsatisfiedLinkError ule) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_static.d.T_invoke_static_6",
+                   UnsatisfiedLinkError.class);
     }
 
-
     /**
      * @title initialization of referenced class throws exception
      */
     public void testE7() {
-        T_invoke_static_14 t = new T_invoke_static_14();
-        try {
-            t.run();
-            fail("expected Error");
-        } catch (Error e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_static.d.T_invoke_static_14", 
+                   ExceptionInInitializerError.class);
     }
 
-
     /**
      * @constraint A13
      * @title  invalid constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_static.d.T_invoke_static_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_static.d.T_invoke_static_3", VerifyError.class);
     }
 
     /**
@@ -129,12 +112,7 @@
      * @title &lt;clinit&gt; may not be called using invoke-static
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_static.d.T_invoke_static_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_static.d.T_invoke_static_10", VerifyError.class);
     }
 
     /**
@@ -142,12 +120,7 @@
      * @title number of arguments passed to method.
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_static.d.T_invoke_static_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_static.d.T_invoke_static_11", VerifyError.class);
     }
 
     /**
@@ -155,12 +128,7 @@
      * @title &lt;init&gt; may not be called using invoke_static
      */
     public void testVFE5() {
-        try {
-            new T_invoke_static_19().run();
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_static.d.T_invoke_static_19", VerifyError.class);
     }
 
     /**
@@ -168,12 +136,7 @@
      * @title types of arguments passed to method
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_static.d.T_invoke_static_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_static.d.T_invoke_static_20", VerifyError.class);
     }
 
 
@@ -182,11 +145,8 @@
      * @title Attempt to call non-static method.
      */
     public void testVFE7() {
-         try {
-             new T_invoke_static_5().run();
-             fail("expected IncompatibleClassChangeError");
-         } catch (IncompatibleClassChangeError t) {
-         }
+        loadAndRun("dot.junit.opcodes.invoke_static.d.T_invoke_static_5",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -194,11 +154,7 @@
      * @title Attempt to call undefined method.
      */
     public void testVFE8() {
-        try {
-            new T_invoke_static_7().run();
-            fail("expected NoSuchMethodError");
-        } catch (NoSuchMethodError t) {
-        }
+        loadAndRun("dot.junit.opcodes.invoke_static.d.T_invoke_static_7", NoSuchMethodError.class);
     }
 
     /**
@@ -206,13 +162,8 @@
      * @title Attempt to call private method of other class.
      */
     public void testVFE9() {
-        //@uses dot.junit.opcodes.invoke_static.d.T_invoke_static_8
         //@uses dot.junit.opcodes.invoke_static.TestClass
-        try {
-            new T_invoke_static_8().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.invoke_static.d.T_invoke_static_8", IllegalAccessError.class);
     }
 
     /**
@@ -220,28 +171,18 @@
      * @title Method has different signature.
      */
     public void testVFE10() {
-        //@uses dot.junit.opcodes.invoke_static.d.T_invoke_static_13
         //@uses dot.junit.opcodes.invoke_static.TestClass
-        try {
-            new T_invoke_static_13().run();
-            fail("expected NoSuchMethodError");
-        } catch (NoSuchMethodError t) {
-        }
+        loadAndRun("dot.junit.opcodes.invoke_static.d.T_invoke_static_13", NoSuchMethodError.class);
     }
 
-
     /**
      * @constraint B12
      * @title Attempt to call protected method of unrelated class.
      */
     public void testVFE12() {
-        //@uses dot.junit.opcodes.invoke_static.d.T_invoke_static_17
         //@uses dot.junit.opcodes.invoke_static.TestClass
-        try {
-            new T_invoke_static_17().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.invoke_static.d.T_invoke_static_17",
+                   IllegalAccessError.class);
     }
 
     /**
@@ -249,12 +190,7 @@
      * @title number of registers
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_static.d.T_invoke_static_16");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_static.d.T_invoke_static_16", VerifyError.class);
     }
 
     /**
@@ -262,12 +198,6 @@
      * @title attempt to invoke interface method
      */
     public void testVFE18() {
-        //@uses dot.junit.opcodes.invoke_static.d.T_invoke_static_24
-        try {
-            new T_invoke_static_24().run();
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_static.d.T_invoke_static_24", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_static/d/T_invoke_static_14.d b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_static/d/T_invoke_static_14.d
index ed2aa2b..ed833e2 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_static/d/T_invoke_static_14.d
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_static/d/T_invoke_static_14.d
@@ -22,6 +22,7 @@
     const v0, 1
     const v1, 0
     div-int v0, v0, v1
+    return-void
 .end method
 
 .method static public test()V
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_static_range/Test_invoke_static_range.java b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_static_range/Test_invoke_static_range.java
index 7db6776..a2db910 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_static_range/Test_invoke_static_range.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_static_range/Test_invoke_static_range.java
@@ -87,13 +87,8 @@
      *
      */
     public void testE2() {
-        T_invoke_static_range_6 t = new T_invoke_static_range_6();
-        try {
-            t.run();
-            fail("expected UnsatisfiedLinkError");
-        } catch (UnsatisfiedLinkError ule) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_static_range.d.T_invoke_static_range_6",
+                   UnsatisfiedLinkError.class);
     }
 
 
@@ -101,13 +96,8 @@
      * @title initialization of referenced class throws exception
      */
     public void testE7() {
-        T_invoke_static_range_14 t = new T_invoke_static_range_14();
-        try {
-            t.run();
-            fail("expected Error");
-        } catch (Error e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_static_range.d.T_invoke_static_range_14", 
+                   ExceptionInInitializerError.class);
     }
 
     /**
@@ -115,12 +105,7 @@
      * @title invalid constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_static_range.d.T_invoke_static_range_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_static_range.d.T_invoke_static_range_3", VerifyError.class);
     }
 
     /**
@@ -128,12 +113,7 @@
      * @title &lt;clinit&gt; may not be called using invoke_static_range
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_static_range.d.T_invoke_static_range_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_static_range.d.T_invoke_static_range_10", VerifyError.class);
     }
 
     /**
@@ -141,12 +121,7 @@
      * @title number of arguments passed to method
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_static_range.d.T_invoke_static_range_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_static_range.d.T_invoke_static_range_11", VerifyError.class);
     }
 
     /**
@@ -154,12 +129,7 @@
      * @title &lt;init&gt; may not be called using invoke_static_range
      */
     public void testVFE5() {
-        try {
-            new T_invoke_static_range_19().run();
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_static_range.d.T_invoke_static_range_19", VerifyError.class);
     }
 
     /**
@@ -167,12 +137,7 @@
      * @title types of arguments passed to method
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_static_range.d.T_invoke_static_range_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_static_range.d.T_invoke_static_range_20", VerifyError.class);
     }
 
 
@@ -181,11 +146,8 @@
      * @title Attempt to call non-static method.
      */
     public void testVFE7() {
-         try {
-             new T_invoke_static_range_5().run();
-             fail("expected IncompatibleClassChangeError");
-         } catch (IncompatibleClassChangeError t) {
-         }
+        loadAndRun("dot.junit.opcodes.invoke_static_range.d.T_invoke_static_range_5",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -193,11 +155,8 @@
      * @title Attempt to call undefined method.
      */
     public void testVFE8() {
-        try {
-            new T_invoke_static_range_7().run();
-            fail("expected NoSuchMethodError");
-        } catch (NoSuchMethodError t) {
-        }
+        loadAndRun("dot.junit.opcodes.invoke_static_range.d.T_invoke_static_range_7",
+                   NoSuchMethodError.class);
     }
 
     /**
@@ -205,13 +164,9 @@
      * @title Attempt to call private method of other class.
      */
     public void testVFE9() {
-        //@uses dot.junit.opcodes.invoke_static_range.d.T_invoke_static_range_8
         //@uses dot.junit.opcodes.invoke_static_range.TestClass
-        try {
-            new T_invoke_static_range_8().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.invoke_static_range.d.T_invoke_static_range_8",
+                   IllegalAccessError.class);
     }
 
     /**
@@ -219,13 +174,9 @@
      * @title Method has different signature.
      */
     public void testVFE10() {
-        //@uses dot.junit.opcodes.invoke_static_range.d.T_invoke_static_range_13
         //@uses dot.junit.opcodes.invoke_static_range.TestClass
-        try {
-            new T_invoke_static_range_13().run();
-            fail("expected NoSuchMethodError");
-        } catch (NoSuchMethodError t) {
-        }
+        loadAndRun("dot.junit.opcodes.invoke_static_range.d.T_invoke_static_range_13",
+                   NoSuchMethodError.class);
     }
 
 
@@ -234,13 +185,9 @@
      * @title Attempt to call protected method of unrelated class.
      */
     public void testVFE12() {
-        //@uses dot.junit.opcodes.invoke_static_range.d.T_invoke_static_range_17
         //@uses dot.junit.opcodes.invoke_static_range.TestClass
-        try {
-            new T_invoke_static_range_17().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.invoke_static_range.d.T_invoke_static_range_17",
+                   IllegalAccessError.class);
     }
 
     /**
@@ -248,12 +195,7 @@
      * @title number of registers
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_static_range.d.T_invoke_static_range_16");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_static_range.d.T_invoke_static_range_16", VerifyError.class);
     }
 
     /**
@@ -261,12 +203,6 @@
      * @title attempt to invoke interface method
      */
     public void testVFE18() {
-        //@uses dot.junit.opcodes.invoke_static_range.d.T_invoke_static_range_24
-        try {
-            new T_invoke_static_range_24().run();
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_static_range.d.T_invoke_static_range_24", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_static_range/d/T_invoke_static_range_14.d b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_static_range/d/T_invoke_static_range_14.d
index e4c1bd3..08c04ff 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_static_range/d/T_invoke_static_range_14.d
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_static_range/d/T_invoke_static_range_14.d
@@ -22,6 +22,7 @@
     const v0, 1
     const v1, 0
     div-int v0, v0, v1
+    return-void
 .end method
 
 .method static public test()V
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_super/Test_invoke_super.java b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_super/Test_invoke_super.java
index b1602b6..0995fb0 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_super/Test_invoke_super.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_super/Test_invoke_super.java
@@ -82,45 +82,25 @@
      * @title obj ref is null
      */
     public void testE1() {
-        //@uses dot.junit.opcodes.invoke_super.d.T_invoke_super_1
         //@uses dot.junit.opcodes.invoke_super.d.TSuper
+        loadAndRun("dot.junit.opcodes.invoke_super.d.T_invoke_super_2", NullPointerException.class);
         T_invoke_super_2 t = new T_invoke_super_2();
-        try {
-            t.run();
-            fail("expected NullPointerException");
-        } catch (NullPointerException npe) {
-            // expected
-        }
     }
 
     /**
      * @title Native method can't be linked
      */
     public void testE2() {
-        //@uses dot.junit.opcodes.invoke_super.d.T_invoke_super_4
         //@uses dot.junit.opcodes.invoke_super.d.TSuper
-        T_invoke_super_4 t = new T_invoke_super_4();
-        try {
-            t.run();
-            fail("expected UnsatisfiedLinkError");
-        } catch (UnsatisfiedLinkError ule) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_super.d.T_invoke_super_4", UnsatisfiedLinkError.class);
     }
 
     /**
      * @title Attempt to invoke abstract method
      */
     public void testE4() {
-        //@uses dot.junit.opcodes.invoke_super.d.T_invoke_super_6
         //@uses dot.junit.opcodes.invoke_super.ATest
-        T_invoke_super_6 t = new T_invoke_super_6();
-        try {
-            t.run();
-            fail("expected AbstractMethodError");
-        } catch (AbstractMethodError iae) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_super.d.T_invoke_super_6", AbstractMethodError.class);
     }
 
     /**
@@ -128,12 +108,7 @@
      * @title invalid constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_super.d.T_invoke_super_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_super.d.T_invoke_super_8", ClassNotFoundException.class);
     }
 
     /**
@@ -141,12 +116,7 @@
      * @title &lt;clinit&gt; may not be called using invoke-super
      */
     public void testVFE3() {
-        try {
-            new T_invoke_super_10().run();
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_super.d.T_invoke_super_10", VerifyError.class);
     }
 
     /**
@@ -154,12 +124,7 @@
      * @title number of arguments passed to method
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_super.d.T_invoke_super_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_super.d.T_invoke_super_11", VerifyError.class);
     }
 
     /**
@@ -167,14 +132,8 @@
      * @title types of arguments passed to method.
      */
     public void testVFE5() {
-        //@uses dot.junit.opcodes.invoke_super.d.T_invoke_super_12
         //@uses dot.junit.opcodes.invoke_super.d.TSuper
-        try {
-            Class.forName("dot.junit.opcodes.invoke_super.d.T_invoke_super_12");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_super.d.T_invoke_super_12", VerifyError.class);
     }
 
     /**
@@ -182,12 +141,7 @@
      * @title &lt;init&gt; may not be called using invoke_super
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_super.d.T_invoke_super_16");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_super.d.T_invoke_super_16", VerifyError.class);
     }
 
     /**
@@ -196,15 +150,9 @@
      *                  protected method
      */
     public void testVFE8() {
-        //@uses dot.junit.opcodes.invoke_super.d.T_invoke_super_22
         //@uses dot.junit.opcodes.invoke_super.d.TSuper
         //@uses dot.junit.opcodes.invoke_super.d.TPlain
-        try {
-            Class.forName("dot.junit.opcodes.invoke_super.d.T_invoke_super_22");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_super.d.T_invoke_super_22", VerifyError.class);
     }
 
     /**
@@ -213,15 +161,9 @@
      *                  public method
      */
     public void testVFE9() {
-        //@uses dot.junit.opcodes.invoke_super.d.T_invoke_super_23
         //@uses dot.junit.opcodes.invoke_super.d.TSuper
         //@uses dot.junit.opcodes.invoke_super.d.TSuper2
-        try {
-            Class.forName("dot.junit.opcodes.invoke_super.d.T_invoke_super_23");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_super.d.T_invoke_super_23", VerifyError.class);
     }
 
     /**
@@ -229,13 +171,9 @@
      * @title Attempt to call static method.
      */
     public void testVFE10() {
-        //@uses dot.junit.opcodes.invoke_super.d.T_invoke_super_5
         //@uses dot.junit.opcodes.invoke_super.d.TSuper
-         try {
-             new T_invoke_super_5().run();
-             fail("expected IncompatibleClassChangeError");
-         } catch (IncompatibleClassChangeError t) {
-         }
+        loadAndRun("dot.junit.opcodes.invoke_super.d.T_invoke_super_5",
+                   IncompatibleClassChangeError.class);
     }
 
 
@@ -244,11 +182,7 @@
      * @title Attempt to invoke non-existing method.
      */
     public void testVFE12() {
-         try {
-             new T_invoke_super_15().run();
-             fail("expected NoSuchMethodError");
-         } catch (NoSuchMethodError t) {
-         }
+        loadAndRun("dot.junit.opcodes.invoke_super.d.T_invoke_super_15", NoSuchMethodError.class);
     }
 
     /**
@@ -256,13 +190,9 @@
      * @title Attempt to invoke private method of other class.
      */
     public void testVFE13() {
-        //@uses dot.junit.opcodes.invoke_super.d.T_invoke_super_18
         //@uses dot.junit.opcodes.invoke_super.TestStubs
-         try {
-             new T_invoke_super_18().run(new TestStubs());
-             fail("expected IllegalAccessError");
-         } catch (IllegalAccessError t) {
-         }
+        loadAndRun("dot.junit.opcodes.invoke_super.d.T_invoke_super_18", IllegalAccessError.class,
+                   new TestStubs());
     }
 
     /**
@@ -270,13 +200,9 @@
      * @title Attempt to invoke protected method of unrelated class.
      */
     public void testVFE14() {
-        //@uses dot.junit.opcodes.invoke_super.d.T_invoke_super_20
         //@uses dot.junit.opcodes.invoke_super.TestStubs
-         try {
-             new T_invoke_super_20().run(new TestStubs());
-             fail("expected IllegalAccessError");
-         } catch (IllegalAccessError t) {
-         }
+        loadAndRun("dot.junit.opcodes.invoke_super.d.T_invoke_super_20", IllegalAccessError.class,
+                   new TestStubs());
     }
 
     /**
@@ -284,13 +210,8 @@
      * @title Method has different signature.
      */
     public void testVFE15() {
-        //@uses dot.junit.opcodes.invoke_super.d.T_invoke_super_19
         //@uses dot.junit.opcodes.invoke_super.d.TSuper
-         try {
-             new T_invoke_super_19().run();
-             fail("expected NoSuchMethodError");
-         } catch (NoSuchMethodError t) {
-         }
+        loadAndRun("dot.junit.opcodes.invoke_super.d.T_invoke_super_19", NoSuchMethodError.class);
     }
 
     /**
@@ -298,14 +219,8 @@
      * @title invoke-super shall be used to invoke private methods
      */
     public void testVFE16() {
-        //@uses dot.junit.opcodes.invoke_super.d.T_invoke_super_13
         //@uses dot.junit.opcodes.invoke_super.d.TSuper
-         try {
-             Class.forName("dot.junit.opcodes.invoke_super.d.T_invoke_super_13");
-             fail("expected a verification exception");
-         } catch (Throwable t) {
-             DxUtil.checkVerifyException(t);
-         }
+        load("dot.junit.opcodes.invoke_super.d.T_invoke_super_13", VerifyError.class);
     }
 
     /**
@@ -313,12 +228,7 @@
      * @title number of registers
      */
     public void testVFE17() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_super.d.T_invoke_super_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_super.d.T_invoke_super_9", VerifyError.class);
     }
 
     /**
@@ -326,13 +236,8 @@
      * @title attempt to invoke interface method
      */
     public void testVFE18() {
-        //@uses dot.junit.opcodes.invoke_super.d.T_invoke_super_24
-        try {
-            new T_invoke_super_24().run();
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        loadAndRun("dot.junit.opcodes.invoke_super.d.T_invoke_super_24", 
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -340,13 +245,7 @@
      * @title instance methods may only be invoked on already initialized instances.
      */
     public void testVFE19() {
-        //@uses dot.junit.opcodes.invoke_super.d.T_invoke_super_25
         //@uses dot.junit.opcodes.invoke_super.d.TSuper
-         try {
-             Class.forName("dot.junit.opcodes.invoke_super.d.T_invoke_super_25");
-             fail("expected a verification exception");
-         } catch (Throwable t) {
-             DxUtil.checkVerifyException(t);
-         }
+        load("dot.junit.opcodes.invoke_super.d.T_invoke_super_25", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_super/d/T_invoke_super_24.java b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_super/d/T_invoke_super_24.java
index 38ebc44..58bbd63 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_super/d/T_invoke_super_24.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_super/d/T_invoke_super_24.java
@@ -18,7 +18,6 @@
 
 public class T_invoke_super_24 {
 
-    public int run() {
-        return 0;
+    public void run() {
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_super_range/Test_invoke_super_range.java b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_super_range/Test_invoke_super_range.java
index 51291f1..9007ef4 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_super_range/Test_invoke_super_range.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_super_range/Test_invoke_super_range.java
@@ -82,45 +82,27 @@
      * @title obj ref is null
      */
     public void testE1() {
-        //@uses dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_1
         //@uses dot.junit.opcodes.invoke_super_range.d.TSuper
-        T_invoke_super_range_2 t = new T_invoke_super_range_2();
-        try {
-            t.run();
-            fail("expected NullPointerException");
-        } catch (NullPointerException npe) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_2",
+                   NullPointerException.class);
     }
 
     /**
      * @title Native method can't be linked
      */
     public void testE2() {
-        //@uses dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_4
         //@uses dot.junit.opcodes.invoke_super_range.d.TSuper
-        T_invoke_super_range_4 t = new T_invoke_super_range_4();
-        try {
-            t.run();
-            fail("expected UnsatisfiedLinkError");
-        } catch (UnsatisfiedLinkError ule) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_4",
+                   UnsatisfiedLinkError.class);
     }
 
     /**
      * @title Attempt to invoke abstract method
      */
     public void testE4() {
-        //@uses dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_6
         //@uses dot.junit.opcodes.invoke_super_range.ATest
-        T_invoke_super_range_6 t = new T_invoke_super_range_6();
-        try {
-            t.run();
-            fail("expected AbstractMethodError");
-        } catch (AbstractMethodError iae) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_6",
+                   AbstractMethodError.class);
     }
 
     /**
@@ -128,12 +110,7 @@
      * @title invalid constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_8", VerifyError.class);
     }
 
     /**
@@ -141,12 +118,7 @@
      * @title &lt;clinit&gt; may not be called using invoke-super
      */
     public void testVFE3() {
-        try {
-            new T_invoke_super_range_10().run();
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_10", VerifyError.class);
     }
 
     /**
@@ -154,12 +126,7 @@
      * @title number of arguments passed to method
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_11", VerifyError.class);
     }
 
     /**
@@ -167,14 +134,8 @@
      * @title types of arguments passed to method.
      */
     public void testVFE5() {
-        //@uses dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_12
         //@uses dot.junit.opcodes.invoke_super_range.d.TSuper
-        try {
-            Class.forName("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_12");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_12", VerifyError.class);
     }
 
     /**
@@ -182,12 +143,7 @@
      * @title &lt;init&gt; may not be called using invoke_super_range
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_16");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_16", VerifyError.class);
     }
 
     /**
@@ -196,15 +152,9 @@
      *                  protected method
      */
     public void testVFE8() {
-        //@uses dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_22
         //@uses dot.junit.opcodes.invoke_super_range.d.TSuper
         //@uses dot.junit.opcodes.invoke_super_range.d.TPlain
-        try {
-            Class.forName("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_22");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_22", VerifyError.class);
     }
 
     /**
@@ -213,15 +163,9 @@
      *                  public method
      */
     public void testVFE9() {
-        //@uses dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_23
         //@uses dot.junit.opcodes.invoke_super_range.d.TSuper
         //@uses dot.junit.opcodes.invoke_super_range.d.TSuper2
-        try {
-            Class.forName("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_23");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_23", VerifyError.class);
     }
 
     /**
@@ -229,13 +173,9 @@
      * @title Attempt to call static method.
      */
     public void testVFE10() {
-        //@uses dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_5
         //@uses dot.junit.opcodes.invoke_super_range.d.TSuper
-         try {
-             new T_invoke_super_range_5().run();
-             fail("expected IncompatibleClassChangeError");
-         } catch (IncompatibleClassChangeError t) {
-         }
+        loadAndRun("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_5",
+                   IncompatibleClassChangeError.class);
     }
 
 
@@ -244,11 +184,8 @@
      * @title Attempt to invoke non-existing method.
      */
     public void testVFE12() {
-         try {
-             new T_invoke_super_range_15().run();
-             fail("expected NoSuchMethodError");
-         } catch (NoSuchMethodError t) {
-         }
+        loadAndRun("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_15",
+                   NoSuchMethodError.class);
     }
 
     /**
@@ -256,13 +193,9 @@
      * @title Attempt to invoke private method of other class.
      */
     public void testVFE13() {
-        //@uses dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_18
         //@uses dot.junit.opcodes.invoke_super_range.TestStubs
-         try {
-             new T_invoke_super_range_18().run(new TestStubs());
-             fail("expected IllegalAccessError");
-         } catch (IllegalAccessError t) {
-         }
+        loadAndRun("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_18",
+                   IllegalAccessError.class, new TestStubs());
     }
 
     /**
@@ -270,13 +203,9 @@
      * @title Attempt to invoke protected method of unrelated class.
      */
     public void testVFE14() {
-        //@uses dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_20
         //@uses dot.junit.opcodes.invoke_super_range.TestStubs
-         try {
-             new T_invoke_super_range_20().run(new TestStubs());
-             fail("expected IllegalAccessError");
-         } catch (IllegalAccessError t) {
-         }
+        loadAndRun("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_20",
+                   IllegalAccessError.class, new TestStubs());
     }
 
     /**
@@ -284,13 +213,9 @@
      * @title Method has different signature.
      */
     public void testVFE15() {
-        //@uses dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_19
         //@uses dot.junit.opcodes.invoke_super_range.d.TSuper
-         try {
-             new T_invoke_super_range_19().run();
-             fail("expected NoSuchMethodError");
-         } catch (NoSuchMethodError t) {
-         }
+        loadAndRun("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_19",
+                   NoSuchMethodError.class);
     }
 
     /**
@@ -300,12 +225,7 @@
     public void testVFE16() {
         //@uses dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_13
         //@uses dot.junit.opcodes.invoke_super_range.d.TSuper
-         try {
-             Class.forName("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_13");
-             fail("expected a verification exception");
-         } catch (Throwable t) {
-             DxUtil.checkVerifyException(t);
-         }
+        load("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_13", VerifyError.class);
     }
 
     /**
@@ -313,12 +233,7 @@
      * @title number of registers
      */
     public void testVFE17() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_9", VerifyError.class);
     }
 
     /**
@@ -327,12 +242,8 @@
      */
     public void testVFE18() {
         //@uses dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_24
-        try {
-            new T_invoke_super_range_24().run();
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        loadAndRun("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_24",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -340,14 +251,8 @@
      * @title instance methods may only be invoked on already initialized instances.
      */
     public void testVFE19() {
-        //@uses dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_25
         //@uses dot.junit.opcodes.invoke_super_range.d.TSuper
-         try {
-             Class.forName("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_25");
-             fail("expected a verification exception");
-         } catch (Throwable t) {
-             DxUtil.checkVerifyException(t);
-         }
+        load("dot.junit.opcodes.invoke_super_range.d.T_invoke_super_range_25", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_virtual/Test_invoke_virtual.java b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_virtual/Test_invoke_virtual.java
index 03f2bb6..55423f4 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_virtual/Test_invoke_virtual.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_virtual/Test_invoke_virtual.java
@@ -82,42 +82,25 @@
      * @title expected NullPointerException
      */
     public void testE1() {
-        T_invoke_virtual_1 t = new T_invoke_virtual_1();
-        String s = "s";
-        try {
-            t.run(null, s);
-            fail("expected NullPointerException");
-        } catch (NullPointerException npe) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_1",
+                   NullPointerException.class, null, "Test");
     }
 
     /**
      * @title Native method can't be linked
      */
     public void testE2() {
-        T_invoke_virtual_4 t = new T_invoke_virtual_4();
-        try {
-            t.run();
-            fail("expected UnsatisfiedLinkError");
-        } catch (UnsatisfiedLinkError ule) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_4",
+                   UnsatisfiedLinkError.class);
     }
 
     /**
      * @title Attempt to invoke abstract method
      */
     public void testE4() {
-        //@uses dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_6
         //@uses dot.junit.opcodes.invoke_virtual.ATest
-        T_invoke_virtual_6 t = new T_invoke_virtual_6();
-        try {
-            t.run();
-            fail("expected AbstractMethodError");
-        } catch (AbstractMethodError iae) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_6",
+                   AbstractMethodError.class);
     }
 
     /**
@@ -125,12 +108,7 @@
      * @title invalid constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_8", VerifyError.class);
     }
 
     /**
@@ -138,12 +116,7 @@
      * @title &lt;clinit&gt; may not be called using invoke-virtual
      */
     public void testVFE3() {
-        try {
-            new T_invoke_virtual_10().run();
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_10", VerifyError.class);
     }
 
     /**
@@ -151,12 +124,7 @@
      * @title number of arguments passed to method
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_11", VerifyError.class);
     }
 
     /**
@@ -164,12 +132,7 @@
      * @title types of arguments passed to method
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_12");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_12", VerifyError.class);
     }
 
     /**
@@ -177,12 +140,7 @@
      * @title &lt;init&gt; may not be called using invoke_virtual
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_16");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_16", VerifyError.class);
     }
 
     /**
@@ -194,12 +152,7 @@
         //@uses dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_22
         //@uses dot.junit.opcodes.invoke_virtual.d.TSuper
         //@uses dot.junit.opcodes.invoke_virtual.d.TPlain
-        try {
-            Class.forName("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_22");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_22", VerifyError.class);
     }
 
     /**
@@ -211,12 +164,7 @@
         //@uses dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_23
         //@uses dot.junit.opcodes.invoke_virtual.d.TSuper
         //@uses dot.junit.opcodes.invoke_virtual.d.TSuper2
-        try {
-            Class.forName("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_23");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_23", VerifyError.class);
     }
 
 
@@ -225,11 +173,8 @@
      * @title Attempt to call static method.
      */
     public void testVFE10() {
-         try {
-             new T_invoke_virtual_5().run();
-             fail("expected IncompatibleClassChangeError");
-         } catch (IncompatibleClassChangeError t) {
-         }
+        loadAndRun("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_5",
+                   IncompatibleClassChangeError.class);
     }
 
 
@@ -238,11 +183,8 @@
      * @title Attempt to invoke non-existing method.
      */
     public void testVFE12() {
-         try {
-             new T_invoke_virtual_15().run();
-             fail("expected NoSuchMethodError");
-         } catch (NoSuchMethodError t) {
-         }
+        loadAndRun("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_15",
+                   NoSuchMethodError.class);
     }
 
     /**
@@ -250,13 +192,9 @@
      * @title Attempt to invoke private method of other class.
      */
     public void testVFE13() {
-        //@uses dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_18
         //@uses dot.junit.opcodes.invoke_virtual.TestStubs
-         try {
-             new T_invoke_virtual_18().run(new TestStubs());
-             fail("expected IllegalAccessError");
-         } catch (IllegalAccessError t) {
-         }
+        loadAndRun("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_18",
+                   IllegalAccessError.class, new TestStubs());
     }
 
     /**
@@ -264,13 +202,9 @@
      * @title Attempt to invoke protected method of unrelated class.
      */
     public void testVFE14() {
-        //@uses dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_20
         //@uses dot.junit.opcodes.invoke_virtual.TestStubs
-         try {
-             new T_invoke_virtual_20().run(new TestStubs());
-             fail("expected IllegalAccessError");
-         } catch (IllegalAccessError t) {
-         }
+        loadAndRun("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_20",
+                   IllegalAccessError.class, new TestStubs());
     }
 
     /**
@@ -278,13 +212,9 @@
      * @title Method has different signature.
      */
     public void testVFE15() {
-        //@uses dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_19
         //@uses dot.junit.opcodes.invoke_virtual.d.TSuper
-         try {
-             new T_invoke_virtual_19().run();
-             fail("expected NoSuchMethodError");
-         } catch (NoSuchMethodError t) {
-         }
+        loadAndRun("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_19",
+                   NoSuchMethodError.class);
     }
 
     /**
@@ -292,12 +222,7 @@
      * @title invoke-virtual shall be used to invoke private methods
      */
     public void testVFE16() {
-         try {
-             Class.forName("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_13");
-             fail("expected a verification exception");
-         } catch (Throwable t) {
-             DxUtil.checkVerifyException(t);
-         }
+        load("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_13", VerifyError.class);
     }
 
     /**
@@ -305,12 +230,7 @@
      * @title number of registers
      */
     public void testVFE17() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_9", VerifyError.class);
     }
 
     /**
@@ -318,13 +238,8 @@
      * @title attempt to invoke interface method
      */
     public void testVFE18() {
-        //@uses dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_24
-        try {
-            new T_invoke_virtual_24().run();
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        loadAndRun("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_24",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -332,12 +247,7 @@
      * @title instance methods may only be invoked on already initialized instances.
      */
     public void testVFE19() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_25");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_virtual.d.T_invoke_virtual_25", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_virtual/d/T_invoke_virtual_12.d b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_virtual/d/T_invoke_virtual_12.d
index 02d509a..8068732 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_virtual/d/T_invoke_virtual_12.d
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_virtual/d/T_invoke_virtual_12.d
@@ -25,6 +25,7 @@
 .end method
 
 .method public test(Ljava/lang/String;)V
+.limit regs 2
     return-void
 .end method
 
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_virtual_range/Test_invoke_virtual_range.java b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_virtual_range/Test_invoke_virtual_range.java
index 6200ce7..5aa7d33 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_virtual_range/Test_invoke_virtual_range.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_virtual_range/Test_invoke_virtual_range.java
@@ -91,42 +91,25 @@
      * @title expected NullPointerException
      */
     public void testE1() {
-        T_invoke_virtual_range_1 t = new T_invoke_virtual_range_1();
-        String s = "s";
-        try {
-            t.run(null, s);
-            fail("expected NullPointerException");
-        } catch (NullPointerException npe) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_1",
+                   NullPointerException.class, null, "Test");
     }
 
     /**
      * @title Native method can't be linked
      */
     public void testE2() {
-        T_invoke_virtual_range_4 t = new T_invoke_virtual_range_4();
-        try {
-            t.run();
-            fail("expected UnsatisfiedLinkError");
-        } catch (UnsatisfiedLinkError ule) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_4",
+                   UnsatisfiedLinkError.class);
     }
 
     /**
      * @title Attempt to invoke abstract method
      */
     public void testE4() {
-        //@uses dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_6
         //@uses dot.junit.opcodes.invoke_virtual_range.ATest
-        T_invoke_virtual_range_6 t = new T_invoke_virtual_range_6();
-        try {
-            t.run();
-            fail("expected AbstractMethodError");
-        } catch (AbstractMethodError iae) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_6",
+                   AbstractMethodError.class);
     }
 
     /**
@@ -134,12 +117,8 @@
      * @title invalid constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_8",
+             VerifyError.class);
     }
 
     /**
@@ -147,12 +126,8 @@
      * @title &lt;clinit&gt; may not be called using invoke-virtual
      */
     public void testVFE3() {
-        try {
-            new T_invoke_virtual_range_10().run();
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_10",
+             VerifyError.class);
     }
 
     /**
@@ -160,12 +135,8 @@
      * @title number of arguments passed to method
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_11",
+             VerifyError.class);
     }
 
     /**
@@ -173,12 +144,8 @@
      * @title types of arguments passed to method
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_12");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_12",
+             VerifyError.class);
     }
 
     /**
@@ -186,12 +153,8 @@
      * @title &lt;init&gt; may not be called using invoke_virtual_range
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_16");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_16",
+             VerifyError.class);
     }
 
     /**
@@ -200,15 +163,10 @@
      *                  protected method
      */
     public void testVFE8() {
-        //@uses dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_22
         //@uses dot.junit.opcodes.invoke_virtual_range.d.TSuper
         //@uses dot.junit.opcodes.invoke_virtual_range.d.TPlain
-        try {
-            Class.forName("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_22");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_22",
+             VerifyError.class);
     }
 
     /**
@@ -217,15 +175,10 @@
      *                  public method
      */
     public void testVFE9() {
-        //@uses dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_23
         //@uses dot.junit.opcodes.invoke_virtual_range.d.TSuper
         //@uses dot.junit.opcodes.invoke_virtual_range.d.TSuper2
-        try {
-            Class.forName("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_23");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_23",
+             VerifyError.class);
     }
 
     /**
@@ -233,11 +186,8 @@
      * @title Attempt to call static method.
      */
     public void testVFE10() {
-         try {
-             new T_invoke_virtual_range_5().run();
-             fail("expected IncompatibleClassChangeError");
-         } catch (IncompatibleClassChangeError t) {
-         }
+        loadAndRun("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_5",
+                   IncompatibleClassChangeError.class);
     }
 
 
@@ -246,11 +196,8 @@
      * @title Attempt to invoke non-existing method.
      */
     public void testVFE12() {
-         try {
-             new T_invoke_virtual_range_15().run();
-             fail("expected NoSuchMethodError");
-         } catch (NoSuchMethodError t) {
-         }
+        loadAndRun("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_15",
+                   NoSuchMethodError.class);
     }
 
     /**
@@ -258,13 +205,9 @@
      * @title Attempt to invoke private method of other class.
      */
     public void testVFE13() {
-        //@uses dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_18
         //@uses dot.junit.opcodes.invoke_virtual_range.TestStubs
-         try {
-             new T_invoke_virtual_range_18().run(new TestStubs());
-             fail("expected IllegalAccessError");
-         } catch (IllegalAccessError t) {
-         }
+        loadAndRun("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_18",
+                   IllegalAccessError.class, new TestStubs());
     }
 
     /**
@@ -272,13 +215,9 @@
      * @title Attempt to invoke protected method of unrelated class.
      */
     public void testVFE14() {
-        //@uses dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_20
         //@uses dot.junit.opcodes.invoke_virtual_range.TestStubs
-         try {
-             new T_invoke_virtual_range_20().run(new TestStubs());
-             fail("expected IllegalAccessError");
-         } catch (IllegalAccessError t) {
-         }
+        loadAndRun("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_20",
+                   IllegalAccessError.class, new TestStubs());
     }
 
     /**
@@ -286,13 +225,9 @@
      * @title Method has different signature.
      */
     public void testVFE15() {
-        //@uses dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_19
         //@uses dot.junit.opcodes.invoke_virtual_range.d.TSuper
-         try {
-             new T_invoke_virtual_range_19().run();
-             fail("expected NoSuchMethodError");
-         } catch (NoSuchMethodError t) {
-         }
+        loadAndRun("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_19",
+                   NoSuchMethodError.class);
     }
 
     /**
@@ -300,12 +235,8 @@
      * @title invoke-virtual/range shall be used to invoke private methods
      */
     public void testVFE16() {
-         try {
-             Class.forName("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_13");
-             fail("expected a verification exception");
-         } catch (Throwable t) {
-             DxUtil.checkVerifyException(t);
-         }
+        load("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_13",
+             VerifyError.class);
     }
 
     /**
@@ -313,12 +244,8 @@
      * @title number of registers
      */
     public void testVFE17() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_9",
+             VerifyError.class);
     }
 
     /**
@@ -326,13 +253,8 @@
      * @title attempt to invoke interface method
      */
     public void testVFE18() {
-        //@uses dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_24
-        try {
-            new T_invoke_virtual_range_24().run();
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        loadAndRun("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_24",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -340,11 +262,7 @@
      * @title instance methods may only be invoked on already initialized instances.
      */
     public void testVFE19() {
-        try {
-            Class.forName("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_25");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.invoke_virtual_range.d.T_invoke_virtual_range_25",
+             VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_virtual_range/d/T_invoke_virtual_range_12.d b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_virtual_range/d/T_invoke_virtual_range_12.d
index 9b63ef8..93df0f5 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_virtual_range/d/T_invoke_virtual_range_12.d
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/invoke_virtual_range/d/T_invoke_virtual_range_12.d
@@ -25,6 +25,7 @@
 .end method
 
 .method public test(Ljava/lang/String;)V
+.limit regs 2
     return-void
 .end method
 
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iput/Test_iput.java b/tools/vm-tests-tf/src/dot/junit/opcodes/iput/Test_iput.java
index daa6b24..cc3e8c8 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/iput/Test_iput.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iput/Test_iput.java
@@ -82,13 +82,7 @@
      * @title expected NullPointerException
      */
     public void testE2() {
-        T_iput_13 t = new T_iput_13();
-        try {
-            t.run();
-            fail("expected NullPointerException");
-        } catch (NullPointerException e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iput.d.T_iput_13", NullPointerException.class);
     }
 
     /**
@@ -96,12 +90,7 @@
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.iput.d.T_iput_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput.d.T_iput_3", VerifyError.class);
     }
 
     /**
@@ -110,12 +99,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.iput.d.T_iput_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput.d.T_iput_4", VerifyError.class);
     }
 
 
@@ -126,12 +110,7 @@
      * different type exists
      */
     public void testVFE5() {
-        try {
-            new T_iput_17().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-            DxUtil.checkVerifyException(t);
-        }
+        loadAndRun("dot.junit.opcodes.iput.d.T_iput_17", NoSuchFieldError.class);
     }
 
     /**
@@ -140,12 +119,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.iput.d.T_iput_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput.d.T_iput_5", VerifyError.class);
     }
 
     /**
@@ -155,12 +129,7 @@
      * with single-width register
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.iput.d.T_iput_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput.d.T_iput_18", VerifyError.class);
     }
 
     /**
@@ -168,11 +137,7 @@
      * @title Attempt to set static field.
      */
     public void testVFE8() {
-         try {
-             new T_iput_7().run();
-             fail("expected IncompatibleClassChangeError");
-         } catch (IncompatibleClassChangeError t) {
-         }
+        loadAndRun("dot.junit.opcodes.iput.d.T_iput_7", IncompatibleClassChangeError.class);
     }
 
     /**
@@ -181,12 +146,7 @@
      */
     public void testVFE9() {
         //@uses dot.junit.opcodes.iput.TestStubs
-        //@uses dot.junit.opcodes.iput.d.T_iput_8
-        try {
-            new T_iput_8().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput.d.T_iput_8", IllegalAccessError.class);
     }
 
     /**
@@ -194,11 +154,7 @@
      * @title Attempt to modify field of undefined class.
      */
     public void testVFE10() {
-        try {
-            new T_iput_9().run();
-            fail("expected NoClassDefFoundError");
-        } catch (NoClassDefFoundError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput.d.T_iput_9", NoClassDefFoundError.class);
     }
 
     /**
@@ -206,42 +162,24 @@
      * @title Attempt to modify undefined field.
      */
     public void testVFE11() {
-        try {
-            new T_iput_10().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput.d.T_iput_10", NoSuchFieldError.class);
     }
 
-
-
     /**
      * @constraint n/a
      * @title Attempt to modify superclass' private field from subclass.
      */
     public void testVFE12() {
         //@uses dot.junit.opcodes.iput.d.T_iput_1
-        //@uses dot.junit.opcodes.iput.d.T_iput_15
-        try {
-            new T_iput_15().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-            DxUtil.checkVerifyException(t);
-        }
+        loadAndRun("dot.junit.opcodes.iput.d.T_iput_15", IllegalAccessError.class);
     }
 
-
     /**
      * @constraint B1
      * @title iput shall not work for wide numbers
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.iput.d.T_iput_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput.d.T_iput_2", VerifyError.class);
     }
 
     /**
@@ -250,12 +188,7 @@
      * @title iput shall not work for reference fields
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.iput.d.T_iput_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput.d.T_iput_20", VerifyError.class);
     }
 
     /**
@@ -264,12 +197,7 @@
      * @title iput shall not work for short fields
      */
     public void testVFE15() {
-        try {
-            Class.forName("dot.junit.opcodes.iput.d.T_iput_21");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput.d.T_iput_21", VerifyError.class);
     }
 
     /**
@@ -278,12 +206,7 @@
      * @title iput shall not work for boolean fields
      */
     public void testVFE16() {
-        try {
-            Class.forName("dot.junit.opcodes.iput.d.T_iput_22");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput.d.T_iput_22", VerifyError.class);
     }
 
     /**
@@ -292,12 +215,7 @@
      * @title iput shall not work for char fields
      */
     public void testVFE17() {
-        try {
-            Class.forName("dot.junit.opcodes.iput.d.T_iput_23");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput.d.T_iput_23", VerifyError.class);
     }
 
     /**
@@ -306,12 +224,7 @@
      * @title iput shall not work for byte fields
      */
     public void testVFE18() {
-        try {
-            Class.forName("dot.junit.opcodes.iput.d.T_iput_24");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput.d.T_iput_24", VerifyError.class);
     }
 
 
@@ -320,12 +233,15 @@
      * @title instance fields may only be accessed on already initialized instances.
      */
     public void testVFE30() {
-        try {
-            Class.forName("dot.junit.opcodes.iput.d.T_iput_30");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput.d.T_iput_30", VerifyError.class);
+    }
+
+    /**
+     * @constraint N/A
+     * @title instance fields may only be accessed on reference registers
+     */
+    public void testVFE31() {
+        load("dot.junit.opcodes.iput.d.T_iput_31", VerifyError.class);
     }
 
     /**
@@ -334,11 +250,6 @@
      */
     public void testE5() {
         //@uses dot.junit.opcodes.iput.TestStubs
-        //@uses dot.junit.opcodes.iput.d.T_iput_11
-    	try {
-            new T_iput_11().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput.d.T_iput_11", IllegalAccessError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iput/d/T_iput_31.d b/tools/vm-tests-tf/src/dot/junit/opcodes/iput/d/T_iput_31.d
new file mode 100644
index 0000000..dd8b4f0
--- /dev/null
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iput/d/T_iput_31.d
@@ -0,0 +1,31 @@
+; 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.
+
+.source T_iput_31.java
+.class public dot.junit.opcodes.iput.d.T_iput_31
+.super java/lang/Object
+
+.field public  st_i1 I
+
+.method public <init>()V
+.limit regs 1
+       invoke-direct {v0}, java/lang/Object/<init>()V
+       return-void
+.end method
+
+.method public run()V
+.limit regs 3
+    const v1, 0
+    iput v1, v0, dot.junit.opcodes.iput.d.T_iput_31.st_i1 I
+.end method
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iput_boolean/Test_iput_boolean.java b/tools/vm-tests-tf/src/dot/junit/opcodes/iput_boolean/Test_iput_boolean.java
index 5736c7c..9903cbb 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/iput_boolean/Test_iput_boolean.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iput_boolean/Test_iput_boolean.java
@@ -72,13 +72,8 @@
      * @title expected NullPointerException
      */
     public void testE2() {
-        T_iput_boolean_13 t = new T_iput_boolean_13();
-        try {
-            t.run();
-            fail("expected NullPointerException");
-        } catch (NullPointerException e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_13",
+                   NullPointerException.class);
     }
 
     /**
@@ -86,12 +81,7 @@
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_3", VerifyError.class);
     }
 
     /**
@@ -99,26 +89,16 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_4", VerifyError.class);
     }
 
-
     /**
      * @constraint B14
      * @title put boolean into long field - only field with same name but
      * different type exists
      */
     public void testVFE5() {
-        try {
-            new T_iput_boolean_17().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_17", NoSuchFieldError.class);
     }
 
     /**
@@ -128,12 +108,7 @@
      * field with single-width register
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_18", VerifyError.class);
     }
 
     /**
@@ -142,11 +117,8 @@
      * @title Attempt to set static field.
      */
     public void testVFE8() {
-         try {
-             new T_iput_boolean_7().run();
-             fail("expected IncompatibleClassChangeError");
-         } catch (IncompatibleClassChangeError t) {
-         }
+        loadAndRun("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_7",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -155,12 +127,7 @@
      */
     public void testVFE9() {
         //@uses dot.junit.opcodes.iput_boolean.TestStubs
-        //@uses dot.junit.opcodes.iput_boolean.d.T_iput_boolean_8
-        try {
-            new T_iput_boolean_8().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_8", IllegalAccessError.class);
     }
 
     /**
@@ -168,11 +135,7 @@
      * @title Attempt to modify field of undefined class.
      */
     public void testVFE10() {
-        try {
-            new T_iput_boolean_9().run();
-            fail("expected NoClassDefFoundError");
-        } catch (NoClassDefFoundError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_9", NoClassDefFoundError.class);
     }
 
     /**
@@ -180,27 +143,16 @@
      * @title Attempt to modify undefined field.
      */
     public void testVFE11() {
-        try {
-            new T_iput_boolean_10().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_10", NoSuchFieldError.class);
     }
 
-
-
     /**
      * @constraint n/a
      * @title Attempt to modify superclass' private field from subclass.
      */
     public void testVFE12() {
         //@uses dot.junit.opcodes.iput_boolean.d.T_iput_boolean_1
-        //@uses dot.junit.opcodes.iput_boolean.d.T_iput_boolean_15
-        try {
-            new T_iput_boolean_15().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_15", IllegalAccessError.class);
     }
 
 
@@ -209,12 +161,7 @@
      * @title iput_boolean shall not work for wide numbers
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_2", VerifyError.class);
     }
 
     /**
@@ -223,12 +170,7 @@
      * @title iput_boolean shall not work for reference fields
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_20", VerifyError.class);
     }
 
     /**
@@ -237,12 +179,7 @@
      * @title iput_boolean shall not work for short fields
      */
     public void testVFE15() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_21");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_21", VerifyError.class);
     }
 
     /**
@@ -251,12 +188,7 @@
      * @title iput_boolean shall not work for int fields
      */
     public void testVFE16() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_22");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_22", VerifyError.class);
     }
 
     /**
@@ -264,12 +196,7 @@
      * @title iput_boolean shall not work for char fields
      */
     public void testVFE17() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_23");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_23", VerifyError.class);
     }
 
     /**
@@ -277,12 +204,7 @@
      * @title iput_boolean shall not work for byte fields
      */
     public void testVFE18() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_24");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_24", VerifyError.class);
     }
 
     /**
@@ -290,12 +212,15 @@
      * @title instance fields may only be accessed on already initialized instances.
      */
     public void testVFE30() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_30");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_30", VerifyError.class);
+    }
+
+    /**
+     * @constraint N/A
+     * @title instance fields may only be accessed on reference registers.
+     */
+    public void testVFE31() {
+        load("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_31", VerifyError.class);
     }
 
     /**
@@ -304,12 +229,7 @@
      */
     public void testVFE19() {
         //@uses dot.junit.opcodes.iput_boolean.TestStubs
-        //@uses dot.junit.opcodes.iput_boolean.d.T_iput_boolean_11
-        try {
-            new T_iput_boolean_11().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_boolean.d.T_iput_boolean_11", IllegalAccessError.class);
     }
 }
 
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iput_boolean/d/T_iput_boolean_31.d b/tools/vm-tests-tf/src/dot/junit/opcodes/iput_boolean/d/T_iput_boolean_31.d
new file mode 100644
index 0000000..039f79f
--- /dev/null
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iput_boolean/d/T_iput_boolean_31.d
@@ -0,0 +1,32 @@
+; 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.
+
+.source T_iput_boolean_31.java
+.class public dot.junit.opcodes.iput_boolean.d.T_iput_boolean_31
+.super java/lang/Object
+
+.field public  st_i1 Z
+
+.method public <init>()V
+.limit regs 1
+       invoke-direct {v0}, java/lang/Object/<init>()V
+       return-void
+.end method
+
+.method public run()V
+.limit regs 3
+    const v1, 0
+    iput-boolean v1, v0, dot.junit.opcodes.iput_boolean.d.T_iput_boolean_31.st_i1 Z
+.end method
+
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iput_byte/Test_iput_byte.java b/tools/vm-tests-tf/src/dot/junit/opcodes/iput_byte/Test_iput_byte.java
index d421980..e87831b 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/iput_byte/Test_iput_byte.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iput_byte/Test_iput_byte.java
@@ -68,13 +68,7 @@
      * @title expected NullPointerException
      */
     public void testE2() {
-        T_iput_byte_13 t = new T_iput_byte_13();
-        try {
-            t.run();
-            fail("expected NullPointerException");
-        } catch (NullPointerException e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iput_byte.d.T_iput_byte_13", NullPointerException.class);
     }
 
     /**
@@ -82,12 +76,7 @@
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_byte.d.T_iput_byte_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_byte.d.T_iput_byte_3", VerifyError.class);
     }
 
     /**
@@ -96,12 +85,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_byte.d.T_iput_byte_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_byte.d.T_iput_byte_4", VerifyError.class);
     }
 
 
@@ -112,11 +96,7 @@
      * different type exists
      */
     public void testVFE5() {
-        try {
-            new T_iput_byte_17().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_byte.d.T_iput_byte_17", NoSuchFieldError.class);
     }
 
     /**
@@ -126,12 +106,7 @@
      * field with single-width register
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_byte.d.T_iput_byte_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_byte.d.T_iput_byte_18", VerifyError.class);
     }
 
     /**
@@ -140,11 +115,8 @@
      * @title Attempt to set static field.
      */
     public void testVFE8() {
-         try {
-             new T_iput_byte_7().run();
-             fail("expected IncompatibleClassChangeError");
-         } catch (IncompatibleClassChangeError t) {
-         }
+        loadAndRun("dot.junit.opcodes.iput_byte.d.T_iput_byte_7",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -153,12 +125,7 @@
      */
     public void testVFE9() {
         //@uses dot.junit.opcodes.iput_byte.TestStubs
-        //@uses dot.junit.opcodes.iput_byte.d.T_iput_byte_8
-        try {
-            new T_iput_byte_8().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_byte.d.T_iput_byte_8", IllegalAccessError.class);
     }
 
     /**
@@ -166,11 +133,7 @@
      * @title Attempt to modify field of undefined class.
      */
     public void testVFE10() {
-        try {
-            new T_iput_byte_9().run();
-            fail("expected NoClassDefFoundError");
-        } catch (NoClassDefFoundError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_byte.d.T_iput_byte_9", NoClassDefFoundError.class);
     }
 
     /**
@@ -178,11 +141,7 @@
      * @title Attempt to modify undefined field.
      */
     public void testVFE11() {
-        try {
-            new T_iput_byte_10().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_byte.d.T_iput_byte_10", NoSuchFieldError.class);
     }
 
 
@@ -193,12 +152,7 @@
      */
     public void testVFE12() {
         //@uses dot.junit.opcodes.iput_byte.d.T_iput_byte_1
-        //@uses dot.junit.opcodes.iput_byte.d.T_iput_byte_15
-        try {
-            new T_iput_byte_15().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_byte.d.T_iput_byte_15", IllegalAccessError.class);
     }
 
 
@@ -207,12 +161,7 @@
      * @title iput-byte shall not work for wide numbers
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_byte.d.T_iput_byte_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_byte.d.T_iput_byte_2", VerifyError.class);
     }
 
     /**
@@ -221,12 +170,7 @@
      * @title iput-byte shall not work for reference fields
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_byte.d.T_iput_byte_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_byte.d.T_iput_byte_20", VerifyError.class);
     }
 
     /**
@@ -235,12 +179,7 @@
      * @title iput-byte shall not work for short fields
      */
     public void testVFE15() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_byte.d.T_iput_byte_21");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_byte.d.T_iput_byte_21", VerifyError.class);
     }
 
     /**
@@ -249,12 +188,7 @@
      * @title iput-byte shall not work for int fields
      */
     public void testVFE16() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_byte.d.T_iput_byte_22");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_byte.d.T_iput_byte_22", VerifyError.class);
     }
 
     /**
@@ -263,12 +197,7 @@
      * @title iput-byte shall not work for char fields
      */
     public void testVFE17() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_byte.d.T_iput_byte_23");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_byte.d.T_iput_byte_23", VerifyError.class);
     }
 
     /**
@@ -277,12 +206,7 @@
      * @title iput-byte shall not work for boolean fields
      */
     public void testVFE18() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_byte.d.T_iput_byte_24");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_byte.d.T_iput_byte_24", VerifyError.class);
     }
 
 
@@ -291,12 +215,15 @@
      * @title instance fields may only be accessed on already initialized instances.
      */
     public void testVFE30() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_byte.d.T_iput_byte_30");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_byte.d.T_iput_byte_30", VerifyError.class);
+    }
+
+    /**
+     * @constraint N/A
+     * @title instance fields may only be accessed on reference registers.
+     */
+    public void testVFE31() {
+        load("dot.junit.opcodes.iput_byte.d.T_iput_byte_31", VerifyError.class);
     }
 
     /**
@@ -305,12 +232,7 @@
      */
     public void testVFE19() {
         //@uses dot.junit.opcodes.iput_byte.TestStubs
-        //@uses dot.junit.opcodes.iput_byte.d.T_iput_byte_11
-    	try {
-            new T_iput_byte_11().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_byte.d.T_iput_byte_11", IllegalAccessError.class);
     }
 }
 
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iput_byte/d/T_iput_byte_31.d b/tools/vm-tests-tf/src/dot/junit/opcodes/iput_byte/d/T_iput_byte_31.d
new file mode 100644
index 0000000..7c26ab6
--- /dev/null
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iput_byte/d/T_iput_byte_31.d
@@ -0,0 +1,32 @@
+; 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.
+
+.source T_iput_byte_31.java
+.class public dot.junit.opcodes.iput_byte.d.T_iput_byte_31
+.super java/lang/Object
+
+.field public  st_i1 B
+
+.method public <init>()V
+.limit regs 1
+       invoke-direct {v0}, java/lang/Object/<init>()V
+       return-void
+.end method
+
+.method public run()V
+.limit regs 3
+    const v1, 0
+    iput-byte v1, v0, dot.junit.opcodes.iput_byte.d.T_iput_byte_31.st_i1 B
+.end method
+
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iput_char/Test_iput_char.java b/tools/vm-tests-tf/src/dot/junit/opcodes/iput_char/Test_iput_char.java
index 87634c7..57eee7b 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/iput_char/Test_iput_char.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iput_char/Test_iput_char.java
@@ -68,13 +68,7 @@
      * @title expected NullPointerException
      */
     public void testE2() {
-        T_iput_char_13 t = new T_iput_char_13();
-        try {
-            t.run();
-            fail("expected NullPointerException");
-        } catch (NullPointerException e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iput_char.d.T_iput_char_13", NullPointerException.class);
     }
 
 
@@ -83,12 +77,7 @@
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_char.d.T_iput_char_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_char.d.T_iput_char_3", VerifyError.class);
     }
 
     /**
@@ -97,12 +86,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_char.d.T_iput_char_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_char.d.T_iput_char_4", VerifyError.class);
     }
 
 
@@ -113,11 +97,7 @@
      * different type exists
      */
     public void testVFE5() {
-        try {
-            new T_iput_char_17().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_char.d.T_iput_char_17", NoSuchFieldError.class);
     }
 
     /**
@@ -127,12 +107,7 @@
      * field with single-width register
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_char.d.T_iput_char_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_char.d.T_iput_char_18", VerifyError.class);
     }
 
     /**
@@ -141,11 +116,8 @@
      * @title Attempt to set static field.
      */
     public void testVFE8() {
-         try {
-             new T_iput_char_7().run();
-             fail("expected IncompatibleClassChangeError");
-         } catch (IncompatibleClassChangeError t) {
-         }
+        loadAndRun("dot.junit.opcodes.iput_char.d.T_iput_char_7",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -154,12 +126,7 @@
      */
     public void testVFE9() {
         //@uses dot.junit.opcodes.iput_char.TestStubs
-        //@uses dot.junit.opcodes.iput_char.d.T_iput_char_8
-        try {
-            new T_iput_char_8().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_char.d.T_iput_char_8", IllegalAccessError.class);
     }
 
     /**
@@ -167,11 +134,7 @@
      * @title Attempt to modify field of undefined class.
      */
     public void testVFE10() {
-        try {
-            new T_iput_char_9().run();
-            fail("expected NoClassDefFoundError");
-        } catch (NoClassDefFoundError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_char.d.T_iput_char_9", NoClassDefFoundError.class);
     }
 
 
@@ -180,11 +143,7 @@
      * @title Attempt to modify undefined field.
      */
     public void testVFE11() {
-        try {
-            new T_iput_char_10().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_char.d.T_iput_char_10", NoSuchFieldError.class);
     }
 
 
@@ -195,12 +154,7 @@
      */
     public void testVFE12() {
         //@uses dot.junit.opcodes.iput_char.d.T_iput_char_1
-        //@uses dot.junit.opcodes.iput_char.d.T_iput_char_15
-        try {
-            new T_iput_char_15().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_char.d.T_iput_char_15", IllegalAccessError.class);
     }
 
 
@@ -209,12 +163,7 @@
      * @title iput-char shall not work for wide numbers
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_char.d.T_iput_char_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_char.d.T_iput_char_2", VerifyError.class);
     }
 
     /**
@@ -223,12 +172,7 @@
      * @title iput-char shall not work for reference fields
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_char.d.T_iput_char_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_char.d.T_iput_char_20", VerifyError.class);
     }
 
     /**
@@ -237,12 +181,7 @@
      * @title iput-char shall not work for short fields
      */
     public void testVFE15() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_char.d.T_iput_char_21");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_char.d.T_iput_char_21", VerifyError.class);
     }
 
     /**
@@ -251,12 +190,7 @@
      * @title iput-char shall not work for int fields
      */
     public void testVFE16() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_char.d.T_iput_char_22");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_char.d.T_iput_char_22", VerifyError.class);
     }
 
     /**
@@ -265,12 +199,7 @@
      * @title iput-char shall not work for byte fields
      */
     public void testVFE17() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_char.d.T_iput_char_23");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_char.d.T_iput_char_23", VerifyError.class);
     }
 
     /**
@@ -279,12 +208,7 @@
      * @title iput-char shall not work for boolean fields
      */
     public void testVFE18() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_char.d.T_iput_char_24");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_char.d.T_iput_char_24", VerifyError.class);
     }
 
 
@@ -293,12 +217,15 @@
      * @title instance fields may only be accessed on already initialized instances.
      */
     public void testVFE30() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_char.d.T_iput_char_30");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_char.d.T_iput_char_30", VerifyError.class);
+    }
+
+    /**
+     * @constraint N/A
+     * @title instance fields may only be accessed on reference registers.
+     */
+    public void testVFE31() {
+        load("dot.junit.opcodes.iput_char.d.T_iput_char_31", VerifyError.class);
     }
 
     /**
@@ -307,12 +234,7 @@
      */
     public void testVFE19() {
         //@uses dot.junit.opcodes.iput_char.TestStubs
-        //@uses dot.junit.opcodes.iput_char.d.T_iput_char_11
-    	try {
-            new T_iput_char_11().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_char.d.T_iput_char_11", IllegalAccessError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iput_char/d/T_iput_char_31.d b/tools/vm-tests-tf/src/dot/junit/opcodes/iput_char/d/T_iput_char_31.d
new file mode 100644
index 0000000..bd52754
--- /dev/null
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iput_char/d/T_iput_char_31.d
@@ -0,0 +1,32 @@
+; 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.
+
+.source T_iput_char_31.java
+.class public dot.junit.opcodes.iput_char.d.T_iput_char_31
+.super java/lang/Object
+
+.field public  st_i1 C
+
+.method public <init>()V
+.limit regs 1
+       invoke-direct {v0}, java/lang/Object/<init>()V
+       return-void
+.end method
+
+.method public run()V
+.limit regs 3
+    const v1, 0
+    iput-char v1, v0, dot.junit.opcodes.iput_char.d.T_iput_char_31.st_i1 C
+.end method
+
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iput_object/Test_iput_object.java b/tools/vm-tests-tf/src/dot/junit/opcodes/iput_object/Test_iput_object.java
index e2f8fa4..d52c55c 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/iput_object/Test_iput_object.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iput_object/Test_iput_object.java
@@ -68,13 +68,7 @@
      * @title expected NullPointerException
      */
     public void testE2() {
-        T_iput_object_13 t = new T_iput_object_13();
-        try {
-            t.run();
-            fail("expected NullPointerException");
-        } catch (NullPointerException e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iput_object.d.T_iput_object_13", NullPointerException.class);
     }
 
 
@@ -83,12 +77,7 @@
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_object.d.T_iput_object_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_object.d.T_iput_object_3", VerifyError.class);
     }
 
     /**
@@ -97,12 +86,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_object.d.T_iput_object_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_object.d.T_iput_object_4", VerifyError.class);
     }
 
 
@@ -113,11 +97,7 @@
      * different type exists
      */
     public void testVFE5() {
-        try {
-            new T_iput_object_17().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_object.d.T_iput_object_17", NoSuchFieldError.class);
     }
 
 
@@ -128,12 +108,7 @@
      * field with single-width register
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_object.d.T_iput_object_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_object.d.T_iput_object_18", VerifyError.class);
     }
 
     /**
@@ -142,11 +117,8 @@
      * @title Attempt to set non-static field.
      */
     public void testVFE8() {
-         try {
-             new T_iput_object_7().run();
-             fail("expected IncompatibleClassChangeError");
-         } catch (IncompatibleClassChangeError t) {
-         }
+        loadAndRun("dot.junit.opcodes.iput_object.d.T_iput_object_7",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -155,12 +127,7 @@
      */
     public void testVFE9() {
         //@uses dot.junit.opcodes.iput_object.TestStubs
-        //@uses dot.junit.opcodes.iput_object.d.T_iput_object_8
-        try {
-            new T_iput_object_8().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_object.d.T_iput_object_8", IllegalAccessError.class);
     }
 
     /**
@@ -168,11 +135,7 @@
      * @title Attempt to modify field of undefined class.
      */
     public void testVFE10() {
-        try {
-            new T_iput_object_9().run();
-            fail("expected NoClassDefFoundError");
-        } catch (NoClassDefFoundError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_object.d.T_iput_object_9", NoClassDefFoundError.class);
     }
 
     /**
@@ -180,11 +143,7 @@
      * @title Attempt to modify undefined field.
      */
     public void testVFE11() {
-        try {
-            new T_iput_object_10().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_object.d.T_iput_object_10", NoSuchFieldError.class);
     }
 
 
@@ -195,12 +154,7 @@
      */
     public void testVFE12() {
         //@uses dot.junit.opcodes.iput_object.d.T_iput_object_1
-        //@uses dot.junit.opcodes.iput_object.d.T_iput_object_15
-        try {
-            new T_iput_object_15().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_object.d.T_iput_object_15", IllegalAccessError.class);
     }
 
 
@@ -209,12 +163,7 @@
      * @title iput-object shall not work for wide numbers
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_object.d.T_iput_object_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_object.d.T_iput_object_2", VerifyError.class);
     }
 
     /**
@@ -223,12 +172,7 @@
      * @title assignment incompatible references
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_object.d.T_iput_object_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_object.d.T_iput_object_20", VerifyError.class);
     }
 
     /**
@@ -237,12 +181,7 @@
      * @title iput-object shall not work for char fields
      */
     public void testVFE15() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_object.d.T_iput_object_21");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_object.d.T_iput_object_21", VerifyError.class);
     }
 
     /**
@@ -251,12 +190,7 @@
      * @title iput-object shall not work for int fields
      */
     public void testVFE16() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_object.d.T_iput_object_22");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_object.d.T_iput_object_22", VerifyError.class);
     }
 
     /**
@@ -265,12 +199,7 @@
      * @title iput-object shall not work for byte fields
      */
     public void testVFE17() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_object.d.T_iput_object_23");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_object.d.T_iput_object_23", VerifyError.class);
     }
 
     /**
@@ -279,12 +208,7 @@
      * @title iput-object shall not work for boolean fields
      */
     public void testVFE18() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_object.d.T_iput_object_24");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_object.d.T_iput_object_24", VerifyError.class);
     }
 
     /**
@@ -293,27 +217,23 @@
      * @title iput-object shall not work for short fields
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_object.d.T_iput_object_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_object.d.T_iput_object_6", VerifyError.class);
     }
 
-
-
     /**
      * @constraint B6
      * @title instance fields may only be accessed on already initialized instances.
      */
     public void testVFE30() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_object.d.T_iput_object_30");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_object.d.T_iput_object_30", VerifyError.class);
+    }
+
+    /**
+     * @constraint N/A
+     * @title instance fields may only be accessed on reference registers.
+     */
+    public void testVFE31() {
+        load("dot.junit.opcodes.iput_object.d.T_iput_object_31", VerifyError.class);
     }
 
     /**
@@ -322,12 +242,7 @@
      */
     public void testVFE19() {
         //@uses dot.junit.opcodes.iput_object.TestStubs
-        //@uses dot.junit.opcodes.iput_object.d.T_iput_object_11
-    	try {
-            new T_iput_object_11().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_object.d.T_iput_object_11", IllegalAccessError.class);
     }
 }
 
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iput_object/d/T_iput_object_31.d b/tools/vm-tests-tf/src/dot/junit/opcodes/iput_object/d/T_iput_object_31.d
new file mode 100644
index 0000000..7b1b507
--- /dev/null
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iput_object/d/T_iput_object_31.d
@@ -0,0 +1,32 @@
+; 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.
+
+.source T_iput_object_31.java
+.class public dot.junit.opcodes.iput_object.d.T_iput_object_31
+.super java/lang/Object
+
+.field public  st_i1 Ljava/lang/Object;
+
+.method public <init>()V
+.limit regs 1
+       invoke-direct {v0}, java/lang/Object/<init>()V
+       return-void
+.end method
+
+.method public run()V
+.limit regs 3
+    const v1, 0
+    iput-object v1, v0, dot.junit.opcodes.iput_object.d.T_iput_object_31.st_i1 Ljava/lang/Object;
+.end method
+
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iput_short/Test_iput_short.java b/tools/vm-tests-tf/src/dot/junit/opcodes/iput_short/Test_iput_short.java
index 1895953..1d9f6d3 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/iput_short/Test_iput_short.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iput_short/Test_iput_short.java
@@ -68,13 +68,7 @@
      * @title expected NullPointerException
      */
     public void testE2() {
-        T_iput_short_13 t = new T_iput_short_13();
-        try {
-            t.run();
-            fail("expected NullPointerException");
-        } catch (NullPointerException e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iput_short.d.T_iput_short_13", NullPointerException.class);
     }
 
 
@@ -84,12 +78,7 @@
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_short.d.T_iput_short_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_short.d.T_iput_short_3", VerifyError.class);
     }
 
     /**
@@ -98,12 +87,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_short.d.T_iput_short_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_short.d.T_iput_short_4", VerifyError.class);
     }
 
 
@@ -114,11 +98,7 @@
      * different type exists
      */
     public void testVFE5() {
-        try {
-            new T_iput_short_17().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_short.d.T_iput_short_17", NoSuchFieldError.class);
     }
 
     /**
@@ -128,12 +108,7 @@
      * field with single-width register
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_short.d.T_iput_short_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_short.d.T_iput_short_18", VerifyError.class);
     }
 
     /**
@@ -142,11 +117,8 @@
      * @title Attempt to set static field.
      */
     public void testVFE8() {
-         try {
-             new T_iput_short_7().run();
-             fail("expected IncompatibleClassChangeError");
-         } catch (IncompatibleClassChangeError t) {
-         }
+        loadAndRun("dot.junit.opcodes.iput_short.d.T_iput_short_7",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -155,12 +127,7 @@
      */
     public void testVFE9() {
         //@uses dot.junit.opcodes.iput_short.TestStubs
-        //@uses dot.junit.opcodes.iput_short.d.T_iput_short_8
-        try {
-            new T_iput_short_8().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_short.d.T_iput_short_8", IllegalAccessError.class);
     }
 
     /**
@@ -168,11 +135,7 @@
      * @title Attempt to modify field of undefined class.
      */
     public void testVFE10() {
-        try {
-            new T_iput_short_9().run();
-            fail("expected NoClassDefFoundError");
-        } catch (NoClassDefFoundError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_short.d.T_iput_short_9", NoClassDefFoundError.class);
     }
 
     /**
@@ -180,11 +143,7 @@
      * @title Attempt to modify undefined field.
      */
     public void testVFE11() {
-        try {
-            new T_iput_short_10().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_short.d.T_iput_short_10", NoSuchFieldError.class);
     }
 
 
@@ -195,12 +154,7 @@
      */
     public void testVFE12() {
         //@uses dot.junit.opcodes.iput_short.d.T_iput_short_1
-        //@uses dot.junit.opcodes.iput_short.d.T_iput_short_15
-        try {
-            new T_iput_short_15().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_short.d.T_iput_short_15", IllegalAccessError.class);
     }
 
 
@@ -209,12 +163,7 @@
      * @title iput-short shall not work for wide numbers
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_short.d.T_iput_short_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_short.d.T_iput_short_2", VerifyError.class);
     }
 
     /**
@@ -223,12 +172,7 @@
      * @title iput-short shall not work for reference fields
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_short.d.T_iput_short_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_short.d.T_iput_short_20", VerifyError.class);
     }
 
     /**
@@ -237,12 +181,7 @@
      * @title iput-short shall not work for char fields
      */
     public void testVFE15() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_short.d.T_iput_short_21");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_short.d.T_iput_short_21", VerifyError.class);
     }
 
     /**
@@ -251,12 +190,7 @@
      * @title iput-short shall not work for int fields
      */
     public void testVFE16() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_short.d.T_iput_short_22");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_short.d.T_iput_short_22", VerifyError.class);
     }
 
     /**
@@ -265,12 +199,7 @@
      * @title iput-short shall not work for byte fields
      */
     public void testVFE17() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_short.d.T_iput_short_23");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_short.d.T_iput_short_23", VerifyError.class);
     }
 
     /**
@@ -279,26 +208,23 @@
      * @title iput-short shall not work for boolean fields
      */
     public void testVFE18() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_short.d.T_iput_short_24");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_short.d.T_iput_short_24", VerifyError.class);
     }
 
-
     /**
      * @constraint B6
      * @title instance fields may only be accessed on already initialized instances.
      */
     public void testVFE30() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_short.d.T_iput_short_30");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_short.d.T_iput_short_30", VerifyError.class);
+    }
+
+    /**
+     * @constraint N/A
+     * @title instance fields may only be accessed on reference registers.
+     */
+    public void testVFE31() {
+        load("dot.junit.opcodes.iput_short.d.T_iput_short_31", VerifyError.class);
     }
 
     /**
@@ -307,12 +233,7 @@
      */
     public void testVFE19() {
         //@uses dot.junit.opcodes.iput_short.TestStubs
-        //@uses dot.junit.opcodes.iput_short.d.T_iput_short_11
-    	try {
-            new T_iput_short_11().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_short.d.T_iput_short_11", IllegalAccessError.class);
     }
 }
 
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iput_short/d/T_iput_short_31.d b/tools/vm-tests-tf/src/dot/junit/opcodes/iput_short/d/T_iput_short_31.d
new file mode 100644
index 0000000..790c99e
--- /dev/null
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iput_short/d/T_iput_short_31.d
@@ -0,0 +1,32 @@
+; 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.
+
+.source T_iput_short_31.java
+.class public dot.junit.opcodes.iput_short.d.T_iput_short_31
+.super java/lang/Object
+
+.field public  st_i1 S
+
+.method public <init>()V
+.limit regs 1
+       invoke-direct {v0}, java/lang/Object/<init>()V
+       return-void
+.end method
+
+.method public run()V
+.limit regs 3
+    const v1, 0
+    iput-short v1, v0, dot.junit.opcodes.iput_short.d.T_iput_short_31.st_i1 S
+.end method
+
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iput_wide/Test_iput_wide.java b/tools/vm-tests-tf/src/dot/junit/opcodes/iput_wide/Test_iput_wide.java
index a61bb70..2a3bf63 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/iput_wide/Test_iput_wide.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iput_wide/Test_iput_wide.java
@@ -79,13 +79,7 @@
      * @title expected NullPointerException
      */
     public void testE2() {
-        T_iput_wide_13 t = new T_iput_wide_13();
-        try {
-            t.run();
-            fail("expected NullPointerException");
-        } catch (NullPointerException e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.iput_wide.d.T_iput_wide_13", NullPointerException.class);
     }
 
 
@@ -95,12 +89,7 @@
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_wide.d.T_iput_wide_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_wide.d.T_iput_wide_3", VerifyError.class);
     }
 
     /**
@@ -109,15 +98,9 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_wide.d.T_iput_wide_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_wide.d.T_iput_wide_4", VerifyError.class);
     }
 
-
     /**
      *
      * @constraint B14
@@ -125,15 +108,9 @@
      * different type exists
      */
     public void testVFE5() {
-        try {
-            new T_iput_wide_17().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_wide.d.T_iput_wide_17", NoSuchFieldError.class);
     }
 
-
-
     /**
      *
      * @constraint B14
@@ -141,12 +118,7 @@
      * field with double-width register
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_wide.d.T_iput_wide_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_wide.d.T_iput_wide_18", VerifyError.class);
     }
 
     /**
@@ -155,11 +127,8 @@
      * @title Attempt to set non-static field.
      */
     public void testVFE8() {
-         try {
-             new T_iput_wide_7().run();
-             fail("expected IncompatibleClassChangeError");
-         } catch (IncompatibleClassChangeError t) {
-         }
+        loadAndRun("dot.junit.opcodes.iput_wide.d.T_iput_wide_7",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -168,25 +137,15 @@
      */
     public void testVFE9() {
         //@uses dot.junit.opcodes.iput_wide.TestStubs
-        //@uses dot.junit.opcodes.iput_wide.d.T_iput_wide_8
-        try {
-            new T_iput_wide_8().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_wide.d.T_iput_wide_8", IllegalAccessError.class);
     }
 
-
     /**
      * @constraint n/a
      * @title Attempt to modify field of undefined class.
      */
     public void testVFE10() {
-        try {
-            new T_iput_wide_9().run();
-            fail("expected NoClassDefFoundError");
-        } catch (NoClassDefFoundError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_wide.d.T_iput_wide_9", NoClassDefFoundError.class);
     }
 
     /**
@@ -194,41 +153,24 @@
      * @title Attempt to modify undefined field.
      */
     public void testVFE11() {
-        try {
-            new T_iput_wide_10().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_wide.d.T_iput_wide_10", NoSuchFieldError.class);
     }
 
-
-
     /**
      * @constraint n/a
      * @title Attempt to modify superclass' private field from subclass.
      */
     public void testVFE12() {
         //@uses dot.junit.opcodes.iput_wide.d.T_iput_wide_1
-        //@uses dot.junit.opcodes.iput_wide.d.T_iput_wide_15
-        try {
-            new T_iput_wide_15().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_wide.d.T_iput_wide_15", IllegalAccessError.class);
     }
 
-
     /**
      * @constraint B1
      * @title iput-wide shall not work for single-width numbers
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_wide.d.T_iput_wide_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_wide.d.T_iput_wide_2", VerifyError.class);
     }
 
     /**
@@ -237,12 +179,7 @@
      * @title iput-wide shall not work for reference fields
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_wide.d.T_iput_wide_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_wide.d.T_iput_wide_20", VerifyError.class);
     }
 
     /**
@@ -251,12 +188,7 @@
      * @title iput-wide shall not work for char fields
      */
     public void testVFE15() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_wide.d.T_iput_wide_21");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_wide.d.T_iput_wide_21", VerifyError.class);
     }
 
     /**
@@ -265,12 +197,7 @@
      * @title iput-wide shall not work for int fields
      */
     public void testVFE16() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_wide.d.T_iput_wide_22");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_wide.d.T_iput_wide_22", VerifyError.class);
     }
 
     /**
@@ -279,12 +206,7 @@
      * @title iput-wide shall not work for byte fields
      */
     public void testVFE17() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_wide.d.T_iput_wide_23");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_wide.d.T_iput_wide_23", VerifyError.class);
     }
 
     /**
@@ -293,12 +215,7 @@
      * @title iput-wide shall not work for boolean fields
      */
     public void testVFE18() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_wide.d.T_iput_wide_24");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_wide.d.T_iput_wide_24", VerifyError.class);
     }
 
     /**
@@ -307,27 +224,23 @@
      * @title iput-wide shall not work for short fields
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_wide.d.T_iput_wide_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_wide.d.T_iput_wide_6", VerifyError.class);
     }
 
-
-
     /**
      * @constraint B6
      * @title instance fields may only be accessed on already initialized instances.
      */
     public void testVFE30() {
-        try {
-            Class.forName("dot.junit.opcodes.iput_wide.d.T_iput_wide_30");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.iput_wide.d.T_iput_wide_30", VerifyError.class);
+    }
+
+    /**
+     * @constraint N/A
+     * @title instance fields may only be accessed on reference registers.
+     */
+    public void testVFE31() {
+        load("dot.junit.opcodes.iput_wide.d.T_iput_wide_31", VerifyError.class);
     }
 
     /**
@@ -336,12 +249,7 @@
      */
     public void testE5() {
         //@uses dot.junit.opcodes.iput_wide.TestStubs
-        //@uses dot.junit.opcodes.iput_wide.d.T_iput_wide_11
-        try {
-            new T_iput_wide_11().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.iput_wide.d.T_iput_wide_11", IllegalAccessError.class);
     }
 }
 
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/iput_wide/d/T_iput_wide_31.d b/tools/vm-tests-tf/src/dot/junit/opcodes/iput_wide/d/T_iput_wide_31.d
new file mode 100644
index 0000000..0e5e112
--- /dev/null
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/iput_wide/d/T_iput_wide_31.d
@@ -0,0 +1,32 @@
+; 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.
+
+.source T_iput_wide_31.java
+.class public dot.junit.opcodes.iput_wide.d.T_iput_wide_31
+.super java/lang/Object
+
+.field public  st_i1 J
+
+.method public <init>()V
+.limit regs 1
+       invoke-direct {v0}, java/lang/Object/<init>()V
+       return-void
+.end method
+
+.method public run()V
+.limit regs 3
+    const-wide v1, 0
+    iput-wide v1, v0, dot.junit.opcodes.iput_wide.d.T_iput_wide_31.st_i1 J
+.end method
+
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/long_to_double/Test_long_to_double.java b/tools/vm-tests-tf/src/dot/junit/opcodes/long_to_double/Test_long_to_double.java
index f432220..c1a1f1c 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/long_to_double/Test_long_to_double.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/long_to_double/Test_long_to_double.java
@@ -77,12 +77,7 @@
      * @title type of argument - float
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.long_to_double.d.T_long_to_double_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.long_to_double.d.T_long_to_double_2", VerifyError.class);
     }
 
     /**
@@ -91,12 +86,7 @@
      * @title type of argument - integer
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.long_to_double.d.T_long_to_double_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.long_to_double.d.T_long_to_double_3", VerifyError.class);
     }
 
     /**
@@ -105,12 +95,7 @@
      * @title type of argument - reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.long_to_double.d.T_long_to_double_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.long_to_double.d.T_long_to_double_4", VerifyError.class);
     }
     
     /**
@@ -119,12 +104,7 @@
      * @title number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.long_to_double.d.T_long_to_double_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.long_to_double.d.T_long_to_double_5", VerifyError.class);
     }
 
     /**
@@ -133,12 +113,7 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.long_to_double.d.T_long_to_double_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.long_to_double.d.T_long_to_double_6", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/long_to_float/Test_long_to_float.java b/tools/vm-tests-tf/src/dot/junit/opcodes/long_to_float/Test_long_to_float.java
index e769e6b..d2cedd9 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/long_to_float/Test_long_to_float.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/long_to_float/Test_long_to_float.java
@@ -79,12 +79,7 @@
      * doubles are not used interchangeably.
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.long_to_float.d.T_long_to_float_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.long_to_float.d.T_long_to_float_2", VerifyError.class);
     }
 
     /**
@@ -92,12 +87,7 @@
      * @title type of argument - integer
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.long_to_float.d.T_long_to_float_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.long_to_float.d.T_long_to_float_3", VerifyError.class);
     }
 
     /**
@@ -106,12 +96,7 @@
      * @title type of argument - reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.long_to_float.d.T_long_to_float_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.long_to_float.d.T_long_to_float_4", VerifyError.class);
     }
     
     /**
@@ -120,12 +105,7 @@
      * @title number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.long_to_float.d.T_long_to_float_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.long_to_float.d.T_long_to_float_5", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/long_to_int/Test_long_to_int.java b/tools/vm-tests-tf/src/dot/junit/opcodes/long_to_int/Test_long_to_int.java
index dd39d3e..a6b6cda 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/long_to_int/Test_long_to_int.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/long_to_int/Test_long_to_int.java
@@ -85,12 +85,7 @@
      * @title  type of argument - float
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.long_to_int.d.T_long_to_int_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.long_to_int.d.T_long_to_int_3", VerifyError.class);
     }
 
     /**
@@ -99,12 +94,7 @@
      * @title  type of argument - reference
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.long_to_int.d.T_long_to_int_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.long_to_int.d.T_long_to_int_4", VerifyError.class);
     }
 
     /**
@@ -113,12 +103,7 @@
      * @title  number of registers
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.long_to_int.d.T_long_to_int_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.long_to_int.d.T_long_to_int_5", VerifyError.class);
     }
     
     /**
@@ -126,12 +111,7 @@
      * @title  type of argument - int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.long_to_int.d.T_long_to_int_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.long_to_int.d.T_long_to_int_6", VerifyError.class);
     }
 
     /**
@@ -140,11 +120,6 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.long_to_int.d.T_long_to_int_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.long_to_int.d.T_long_to_int_2", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/monitor_enter/Test_monitor_enter.java b/tools/vm-tests-tf/src/dot/junit/opcodes/monitor_enter/Test_monitor_enter.java
index 3608793..fbff132 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/monitor_enter/Test_monitor_enter.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/monitor_enter/Test_monitor_enter.java
@@ -83,12 +83,7 @@
      * @title  number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.monitor_enter.d.T_monitor_enter_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.monitor_enter.d.T_monitor_enter_4", VerifyError.class);
     }
 
     /**
@@ -96,12 +91,7 @@
      * @title  types of arguments - int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.monitor_enter.d.T_monitor_enter_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.monitor_enter.d.T_monitor_enter_5", VerifyError.class);
     }
     
     /**
@@ -109,12 +99,7 @@
      * @title  types of arguments - float
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.monitor_enter.d.T_monitor_enter_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.monitor_enter.d.T_monitor_enter_6", VerifyError.class);
     }
     
     /**
@@ -122,12 +107,7 @@
      * @title  types of arguments - long
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.monitor_enter.d.T_monitor_enter_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.monitor_enter.d.T_monitor_enter_7", VerifyError.class);
     }
 
     /**
@@ -135,12 +115,7 @@
      * @title  types of arguments - double
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.monitor_enter.d.T_monitor_enter_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.monitor_enter.d.T_monitor_enter_8", VerifyError.class);
     }
     
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/monitor_exit/Test_monitor_exit.java b/tools/vm-tests-tf/src/dot/junit/opcodes/monitor_exit/Test_monitor_exit.java
index d4f5842..051e951 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/monitor_exit/Test_monitor_exit.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/monitor_exit/Test_monitor_exit.java
@@ -47,13 +47,7 @@
      * @title expected NullPointerException
      */
     public void testE3() {
-        T_monitor_exit_3 t = new T_monitor_exit_3();
-        try {
-            t.run();
-            fail("expected NullPointerException");
-        } catch (NullPointerException npe) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.monitor_exit.d.T_monitor_exit_3", NullPointerException.class);
     }
 
     /**
@@ -61,12 +55,7 @@
      * @title  number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.monitor_exit.d.T_monitor_exit_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.monitor_exit.d.T_monitor_exit_4", VerifyError.class);
     }
 
 
@@ -76,12 +65,7 @@
      * @title  type of arguments - int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.monitor_exit.d.T_monitor_exit_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.monitor_exit.d.T_monitor_exit_5", VerifyError.class);
     }
     
     /**
@@ -89,12 +73,7 @@
      * @title  type of arguments - float
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.monitor_exit.d.T_monitor_exit_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.monitor_exit.d.T_monitor_exit_6", VerifyError.class);
     }
     
     /**
@@ -102,12 +81,7 @@
      * @title  type of arguments - long
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.monitor_exit.d.T_monitor_exit_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.monitor_exit.d.T_monitor_exit_7", VerifyError.class);
     }
     
     /**
@@ -115,12 +89,7 @@
      * @title  type of arguments - double
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.monitor_exit.d.T_monitor_exit_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.monitor_exit.d.T_monitor_exit_8", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/move/Test_move.java b/tools/vm-tests-tf/src/dot/junit/opcodes/move/Test_move.java
index d503890..8269dc9 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/move/Test_move.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/move/Test_move.java
@@ -34,12 +34,7 @@
      * @title number of registers - src is not valid
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.move.d.T_move_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move.d.T_move_2", VerifyError.class);
     }
     
     /**
@@ -47,12 +42,7 @@
      * @title number of registers - dst is not valid
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.move.d.T_move_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move.d.T_move_3", VerifyError.class);
     }
 
     /**
@@ -60,12 +50,7 @@
      * @title src register contains reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.move.d.T_move_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move.d.T_move_4", VerifyError.class);
     }
     
     /**
@@ -73,12 +58,7 @@
      * @title src register contains wide
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.move.d.T_move_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move.d.T_move_5", VerifyError.class);
     }
     
     /**
@@ -86,12 +66,7 @@
      * @title src register is a part of reg pair
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.move.d.T_move_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move.d.T_move_6", VerifyError.class);
     }
     
     /**
@@ -101,12 +76,7 @@
      * up, and the other register involved in it becomes undefined.
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.move.d.T_move_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move.d.T_move_7", VerifyError.class);
     }
     
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/move_16/Test_move_16.java b/tools/vm-tests-tf/src/dot/junit/opcodes/move_16/Test_move_16.java
index f3e2ab0..c27e5d9 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/move_16/Test_move_16.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/move_16/Test_move_16.java
@@ -41,12 +41,7 @@
      * @title  number of registers - src is not valid
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.move_16.d.T_move_16_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_16.d.T_move_16_3", VerifyError.class);
     }
     
     /**
@@ -54,12 +49,7 @@
      * @title number of registers - dst is not valid
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.move_16.d.T_move_16_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_16.d.T_move_16_4", VerifyError.class);
     }
 
     /**
@@ -67,12 +57,7 @@
      * @title src register contains reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.move_16.d.T_move_16_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_16.d.T_move_16_5", VerifyError.class);
     }
     
     /**
@@ -80,12 +65,7 @@
      * @title  src register contains wide
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.move_16.d.T_move_16_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_16.d.T_move_16_6", VerifyError.class);
     }
     
     /**
@@ -93,12 +73,7 @@
      * @title src register is a part of reg pair
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.move_16.d.T_move_16_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_16.d.T_move_16_7", VerifyError.class);
     }
     
     /**
@@ -108,11 +83,6 @@
      * up, and the other register involved in it becomes undefined.
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.move_16.d.T_move_16_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_16.d.T_move_16_8", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/move_exception/Test_move_exception.java b/tools/vm-tests-tf/src/dot/junit/opcodes/move_exception/Test_move_exception.java
index b4fd87c..be22e89 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/move_exception/Test_move_exception.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/move_exception/Test_move_exception.java
@@ -27,15 +27,8 @@
      * @title tests move-exception functionality
      */
     public void testN1() {
-        T_move_exception_1 t = new T_move_exception_1();
-        try {
-            t.run();
-            fail("ArithmeticException was not thrown");
-        } catch (ArithmeticException ae) {
-            //expected
-        } catch (Exception ex) {
-            fail("Exception " + ex + " was thrown instead off ArithmeticException");
-        }
+        loadAndRun("dot.junit.opcodes.move_exception.d.T_move_exception_1",
+                   ArithmeticException.class);
     }
     
     /**
@@ -51,12 +44,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.move_exception.d.T_move_exception_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_exception.d.T_move_exception_3", VerifyError.class);
     }
     
     /**
@@ -64,12 +52,7 @@
      * @title  move-exception is not first instruction in an exception handler
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.move_exception.d.T_move_exception_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_exception.d.T_move_exception_5", VerifyError.class);
     }    
     
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/move_from16/Test_move_from16.java b/tools/vm-tests-tf/src/dot/junit/opcodes/move_from16/Test_move_from16.java
index 725cbd86e..f6de2c3 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/move_from16/Test_move_from16.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/move_from16/Test_move_from16.java
@@ -33,12 +33,7 @@
      * @title number of registers - src is not valid
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.move_from16.d.T_move_from16_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_from16.d.T_move_from16_3", VerifyError.class);
     }
     
     /**
@@ -46,12 +41,7 @@
      * @title number of registers - dst is not valid
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.move_from16.d.T_move_from16_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_from16.d.T_move_from16_4", VerifyError.class);
     }
 
     /**
@@ -59,12 +49,7 @@
      * @title src register contains reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.move_from16.d.T_move_from16_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_from16.d.T_move_from16_5", VerifyError.class);
     }
     
     /**
@@ -72,12 +57,7 @@
      * @title src register contains wide
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.move_from16.d.T_move_from16_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_from16.d.T_move_from16_6", VerifyError.class);
     }
     
     /**
@@ -85,12 +65,7 @@
      * @title src register is a part of reg pair
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.move_from16.d.T_move_from16_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_from16.d.T_move_from16_7", VerifyError.class);
     }
     
     /**
@@ -100,12 +75,7 @@
      * up, and the other register involved in it becomes undefined.
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.move_from16.d.T_move_from16_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_from16.d.T_move_from16_8", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/move_object/Test_move_object.java b/tools/vm-tests-tf/src/dot/junit/opcodes/move_object/Test_move_object.java
index d67be88..8ec2368 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/move_object/Test_move_object.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/move_object/Test_move_object.java
@@ -35,12 +35,7 @@
      * @title  number of registers - src is not valid
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.move_object.d.T_move_object_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_object.d.T_move_object_2", VerifyError.class);
     }
     
     /**
@@ -48,12 +43,7 @@
      * @title number of registers - dst is not valid
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.move_object.d.T_move_object_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_object.d.T_move_object_3", VerifyError.class);
     }
 
     /**
@@ -61,12 +51,7 @@
      * @title src register contains integer
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.move_object.d.T_move_object_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_object.d.T_move_object_4", VerifyError.class);
     }
     
     /**
@@ -74,12 +59,7 @@
      * @title src register contains wide
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.move_object.d.T_move_object_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_object.d.T_move_object_5", VerifyError.class);
     }
     
     /**
@@ -87,12 +67,7 @@
      * @title src register is a part of reg pair
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.move_object.d.T_move_object_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_object.d.T_move_object_6", VerifyError.class);
     }
     
     /**
@@ -102,11 +77,6 @@
      * up, and the other register involved in it becomes undefined.
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.move_object.d.T_move_object_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_object.d.T_move_object_7", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/move_object_16/Test_move_object_16.java b/tools/vm-tests-tf/src/dot/junit/opcodes/move_object_16/Test_move_object_16.java
index c3780cf..e8847bd 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/move_object_16/Test_move_object_16.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/move_object_16/Test_move_object_16.java
@@ -34,12 +34,7 @@
      * @title  number of registers - src is not valid
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.move_object_16.d.T_move_object_16_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_object_16.d.T_move_object_16_3", VerifyError.class);
     }
     
     /**
@@ -47,12 +42,7 @@
      * @title number of registers - dst is not valid
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.move_object_16.d.T_move_object_16_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_object_16.d.T_move_object_16_4", VerifyError.class);
     }
 
     /**
@@ -60,12 +50,7 @@
      * @title src register contains integer
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.move_object_16.d.T_move_object_16_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_object_16.d.T_move_object_16_5", VerifyError.class);
     }
     
     /**
@@ -73,12 +58,7 @@
      * @title src register contains wide
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.move_object_16.d.T_move_object_16_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_object_16.d.T_move_object_16_6", VerifyError.class);
     }
     
     /**
@@ -86,12 +66,7 @@
      * @title src register is a part of reg pair
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.move_object_16.d.T_move_object_16_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_object_16.d.T_move_object_16_7", VerifyError.class);
     }
     
     /**
@@ -101,11 +76,6 @@
      * up, and the other register involved in it becomes undefined.
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.move_object_16.d.T_move_object_16_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_object_16.d.T_move_object_16_8", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/move_object_from16/Test_move_object_from16.java b/tools/vm-tests-tf/src/dot/junit/opcodes/move_object_from16/Test_move_object_from16.java
index 2fe17d3..a07f889 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/move_object_from16/Test_move_object_from16.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/move_object_from16/Test_move_object_from16.java
@@ -35,12 +35,7 @@
      * @title number of registers - src is not valid
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.move_object_from16.d.T_move_object_from16_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_object_from16.d.T_move_object_from16_3", VerifyError.class);
     }
     
     /**
@@ -48,12 +43,7 @@
      * @title number of registers - dst is not valid
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.move_object_from16.d.T_move_object_from16_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_object_from16.d.T_move_object_from16_4", VerifyError.class);
     }
 
     /**
@@ -61,12 +51,7 @@
      * @title src register contains integer
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.move_object_from16.d.T_move_object_from16_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_object_from16.d.T_move_object_from16_5", VerifyError.class);
     }
     
     /**
@@ -74,12 +59,7 @@
      * @title src register contains wide
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.move_object_from16.d.T_move_object_from16_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_object_from16.d.T_move_object_from16_6", VerifyError.class);
     }
     
     /**
@@ -87,12 +67,7 @@
      * @title src register is a part of reg pair
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.move_object_from16.d.T_move_object_from16_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_object_from16.d.T_move_object_from16_7", VerifyError.class);
     }
     
     /**
@@ -102,12 +77,7 @@
      * up, and the other register involved in it becomes undefined.
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.move_object_from16.d.T_move_object_from16_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_object_from16.d.T_move_object_from16_8", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/move_result/Test_move_result.java b/tools/vm-tests-tf/src/dot/junit/opcodes/move_result/Test_move_result.java
index 9a0eaba..b9dc99d 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/move_result/Test_move_result.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/move_result/Test_move_result.java
@@ -34,12 +34,7 @@
      * @title number of registers - dest is not valid
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.move_result.d.T_move_result_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_result.d.T_move_result_2", VerifyError.class);
     }
 
 
@@ -48,12 +43,7 @@
      * @title  reference
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.move_result.d.T_move_result_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_result.d.T_move_result_3", VerifyError.class);
     }
     
     /**
@@ -61,12 +51,7 @@
      * @title wide
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.move_result.d.T_move_result_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_result.d.T_move_result_4", VerifyError.class);
     }
 
     
@@ -77,12 +62,7 @@
      * up, and the other register involved in it becomes undefined.
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.move_result.d.T_move_result_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_result.d.T_move_result_5", VerifyError.class);
     }
     
     /**
@@ -91,12 +71,7 @@
      * (in the insns array) by an <invoke-kind> instruction
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.move_result.d.T_move_result_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_result.d.T_move_result_6", VerifyError.class);
     }
     
     /**
@@ -105,12 +80,7 @@
      * (in actual control flow) by an <invoke-kind> instruction
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.move_result.d.T_move_result_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_result.d.T_move_result_7", VerifyError.class);
     }
     
     /**
@@ -118,11 +88,6 @@
      * @title number of registers
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.move_result.d.T_move_result_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_result.d.T_move_result_8", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/move_result_object/Test_move_result_object.java b/tools/vm-tests-tf/src/dot/junit/opcodes/move_result_object/Test_move_result_object.java
index 9ee2ed1..4371f53 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/move_result_object/Test_move_result_object.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/move_result_object/Test_move_result_object.java
@@ -45,12 +45,7 @@
      * @title number of registers - dest is not valid
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.move_result_object.d.T_move_result_object_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_result_object.d.T_move_result_object_2", VerifyError.class);
     }
 
 
@@ -59,12 +54,7 @@
      * @title integer
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.move_result_object.d.T_move_result_object_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_result_object.d.T_move_result_object_3", VerifyError.class);
     }
     
     /**
@@ -72,12 +62,7 @@
      * @title wide
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.move_result_object.d.T_move_result_object_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_result_object.d.T_move_result_object_4", VerifyError.class);
     }
 
     
@@ -88,12 +73,7 @@
      * up, and the other register involved in it becomes undefined.
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.move_result_object.d.T_move_result_object_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_result_object.d.T_move_result_object_5", VerifyError.class);
     }
     
     /**
@@ -102,12 +82,7 @@
      * (in the insns array) by an <invoke-kind> instruction
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.move_result_object.d.T_move_result_object_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_result_object.d.T_move_result_object_6", VerifyError.class);
     }
     
     /**
@@ -116,12 +91,7 @@
      * (in actual control flow) by an <invoke-kind> instruction
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.move_result_object.d.T_move_result_object_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_result_object.d.T_move_result_object_7", VerifyError.class);
     }
     
     /**
@@ -129,12 +99,7 @@
      * @title number of registers
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.move_result_object.d.T_move_result_object_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_result_object.d.T_move_result_object_9", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/move_result_wide/Test_move_result_wide.java b/tools/vm-tests-tf/src/dot/junit/opcodes/move_result_wide/Test_move_result_wide.java
index 6c849dc..7ad8925 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/move_result_wide/Test_move_result_wide.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/move_result_wide/Test_move_result_wide.java
@@ -34,12 +34,7 @@
      * @title  number of registers - dest is not valid
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.move_result_wide.d.T_move_result_wide_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_result_wide.d.T_move_result_wide_2", VerifyError.class);
     }
 
 
@@ -48,12 +43,7 @@
      * @title reference
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.move_result_wide.d.T_move_result_wide_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_result_wide.d.T_move_result_wide_3", VerifyError.class);
     }
     
     /**
@@ -61,12 +51,7 @@
      * @title  32-bit value
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.move_result_wide.d.T_move_result_wide_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_result_wide.d.T_move_result_wide_4", VerifyError.class);
     }
 
     
@@ -77,12 +62,7 @@
      * up, and the other register involved in it becomes undefined.
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.move_result_wide.d.T_move_result_wide_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_result_wide.d.T_move_result_wide_5", VerifyError.class);
     }
     
     /**
@@ -91,12 +71,7 @@
      * (in the insns array) by an <invoke-kind> instruction
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.move_result_wide.d.T_move_result_wide_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_result_wide.d.T_move_result_wide_6", VerifyError.class);
     }
     
     /**
@@ -105,12 +80,7 @@
      * (in actual control flow) by an <invoke-kind> instruction
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.move_result_wide.d.T_move_result_wide_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_result_wide.d.T_move_result_wide_7", VerifyError.class);
     }
 
     /**
@@ -118,12 +88,7 @@
      * @title number of registers
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.move_result_wide.d.T_move_result_wide_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_result_wide.d.T_move_result_wide_8", VerifyError.class);
     }
     
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/move_wide/Test_move_wide.java b/tools/vm-tests-tf/src/dot/junit/opcodes/move_wide/Test_move_wide.java
index 4ab7421..a83bf41 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/move_wide/Test_move_wide.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/move_wide/Test_move_wide.java
@@ -42,12 +42,7 @@
      * @title number of registers - src is not valid
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.move_wide.d.T_move_wide_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_wide.d.T_move_wide_2", VerifyError.class);
     }
     
     /**
@@ -55,12 +50,7 @@
      * @title number of registers - dst is not valid
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.move_wide.d.T_move_wide_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_wide.d.T_move_wide_3", VerifyError.class);
     }
 
     /**
@@ -68,12 +58,7 @@
      * @title src register contains reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.move_wide.d.T_move_wide_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_wide.d.T_move_wide_4", VerifyError.class);
     }
     
     /**
@@ -81,12 +66,7 @@
      * @title  src register contains 32-bit value
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.move_wide.d.T_move_wide_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_wide.d.T_move_wide_5", VerifyError.class);
     }
     
     /**
@@ -96,12 +76,7 @@
      * up, and the other register involved in it becomes undefined.
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.move_wide.d.T_move_wide_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_wide.d.T_move_wide_7", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/move_wide_16/Test_move_wide_16.java b/tools/vm-tests-tf/src/dot/junit/opcodes/move_wide_16/Test_move_wide_16.java
index a2b776d..7c34b61 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/move_wide_16/Test_move_wide_16.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/move_wide_16/Test_move_wide_16.java
@@ -48,12 +48,7 @@
      * @title number of registers - src is not valid
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.move_wide_16.d.T_move_wide_16_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_wide_16.d.T_move_wide_16_3", VerifyError.class);
     }
     
     /**
@@ -61,12 +56,7 @@
      * @title number of registers - dst is not valid
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.move_wide_16.d.T_move_wide_16_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_wide_16.d.T_move_wide_16_4", VerifyError.class);
     }
 
     /**
@@ -74,12 +64,7 @@
      * @title src register contains reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.move_wide_16.d.T_move_wide_16_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_wide_16.d.T_move_wide_16_5", VerifyError.class);
     }
     
     /**
@@ -87,12 +72,7 @@
      * @title src register contains 32-bit value
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.move_wide_16.d.T_move_wide_16_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_wide_16.d.T_move_wide_16_6", VerifyError.class);
     }
     
     /**
@@ -100,12 +80,7 @@
      * @title src register is a part of reg pair
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.move_wide_16.d.T_move_wide_16_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_wide_16.d.T_move_wide_16_7", VerifyError.class);
     }
     
     /**
@@ -115,12 +90,7 @@
      * up, and the other register involved in it becomes undefined.
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.move_wide_16.d.T_move_wide_16_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_wide_16.d.T_move_wide_16_8", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/move_wide_from16/Test_move_wide_from16.java b/tools/vm-tests-tf/src/dot/junit/opcodes/move_wide_from16/Test_move_wide_from16.java
index 2434e92..3c8918f 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/move_wide_from16/Test_move_wide_from16.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/move_wide_from16/Test_move_wide_from16.java
@@ -41,12 +41,7 @@
      * @title number of registers - src is not valid
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.move_wide_from16.d.T_move_wide_from16_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_wide_from16.d.T_move_wide_from16_3", VerifyError.class);
     }
     
     /**
@@ -54,12 +49,7 @@
      * @title number of registers - dst is not valid
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.move_wide_from16.d.T_move_wide_from16_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_wide_from16.d.T_move_wide_from16_4", VerifyError.class);
     }
 
     /**
@@ -67,12 +57,7 @@
      * @title src register contains reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.move_wide_from16.d.T_move_wide_from16_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_wide_from16.d.T_move_wide_from16_5", VerifyError.class);
     }
     
     /**
@@ -80,12 +65,7 @@
      * @title src register contains 32-bit value
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.move_wide_from16.d.T_move_wide_from16_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_wide_from16.d.T_move_wide_from16_6", VerifyError.class);
     }
     
     /**
@@ -93,12 +73,7 @@
      * @title src register is a part of reg pair
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.move_wide_from16.d.T_move_wide_from16_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_wide_from16.d.T_move_wide_from16_7", VerifyError.class);
     }
     
     /**
@@ -108,12 +83,7 @@
      * up, and the other register involved in it becomes undefined.
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.move_wide_from16.d.T_move_wide_from16_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.move_wide_from16.d.T_move_wide_from16_8", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/mul_double/Test_mul_double.java b/tools/vm-tests-tf/src/dot/junit/opcodes/mul_double/Test_mul_double.java
index 9f5f173..85718da 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/mul_double/Test_mul_double.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/mul_double/Test_mul_double.java
@@ -120,12 +120,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_double.d.T_mul_double_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_double.d.T_mul_double_2", VerifyError.class);
     }
 
     
@@ -135,12 +130,7 @@
      * @title types of arguments - float, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_double.d.T_mul_double_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_double.d.T_mul_double_3", VerifyError.class);
     }
 
     /**
@@ -148,12 +138,7 @@
      * @title types of arguments - double, reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_double.d.T_mul_double_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_double.d.T_mul_double_5", VerifyError.class);
     }
 
     /**
@@ -162,11 +147,6 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_double.d.T_mul_double_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_double.d.T_mul_double_4", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/mul_double_2addr/Test_mul_double_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/mul_double_2addr/Test_mul_double_2addr.java
index 8689e85..9770407 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/mul_double_2addr/Test_mul_double_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/mul_double_2addr/Test_mul_double_2addr.java
@@ -121,12 +121,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_double_2addr.d.T_mul_double_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_double_2addr.d.T_mul_double_2addr_2", VerifyError.class);
     }
 
     
@@ -136,12 +131,7 @@
      * @title types of arguments - float, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_double_2addr.d.T_mul_double_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_double_2addr.d.T_mul_double_2addr_3", VerifyError.class);
     }
 
     /**
@@ -149,12 +139,7 @@
      * @title types of arguments - double, reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_double_2addr.d.T_mul_double_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_double_2addr.d.T_mul_double_2addr_5", VerifyError.class);
     }
 
     /**
@@ -163,12 +148,7 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_double_2addr.d.T_mul_double_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_double_2addr.d.T_mul_double_2addr_4", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/mul_float/Test_mul_float.java b/tools/vm-tests-tf/src/dot/junit/opcodes/mul_float/Test_mul_float.java
index f486966..9506361 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/mul_float/Test_mul_float.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/mul_float/Test_mul_float.java
@@ -120,12 +120,7 @@
      * @title  number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_float.d.T_mul_float_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_float.d.T_mul_float_2", VerifyError.class);
     }
 
     
@@ -135,12 +130,7 @@
      * @title  types of arguments - float, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_float.d.T_mul_float_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_float.d.T_mul_float_3", VerifyError.class);
     }
 
     /**
@@ -148,12 +138,7 @@
      * @title types of arguments - long, float
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_float.d.T_mul_float_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_float.d.T_mul_float_4", VerifyError.class);
     }
 
     /**
@@ -161,12 +146,7 @@
      * @title types of arguments - reference, float
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_float.d.T_mul_float_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_float.d.T_mul_float_5", VerifyError.class);
     }
 
     /**
@@ -175,11 +155,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_float.d.T_mul_float_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_float.d.T_mul_float_6", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/mul_float_2addr/Test_mul_float_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/mul_float_2addr/Test_mul_float_2addr.java
index 3a222bb..9b9271b 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/mul_float_2addr/Test_mul_float_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/mul_float_2addr/Test_mul_float_2addr.java
@@ -120,12 +120,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_float_2addr.d.T_mul_float_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_float_2addr.d.T_mul_float_2addr_2", VerifyError.class);
     }
 
     
@@ -135,12 +130,7 @@
      * @title types of arguments - float, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_float_2addr.d.T_mul_float_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_float_2addr.d.T_mul_float_2addr_3", VerifyError.class);
     }
 
     /**
@@ -148,12 +138,7 @@
      * @title types of arguments - long, float
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_float_2addr.d.T_mul_float_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_float_2addr.d.T_mul_float_2addr_4", VerifyError.class);
     }
 
     /**
@@ -161,12 +146,7 @@
      * @title types of arguments - reference, float
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_float_2addr.d.T_mul_float_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_float_2addr.d.T_mul_float_2addr_5", VerifyError.class);
     }
 
     /**
@@ -175,11 +155,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_float_2addr.d.T_mul_float_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_float_2addr.d.T_mul_float_2addr_6", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/mul_int/Test_mul_int.java b/tools/vm-tests-tf/src/dot/junit/opcodes/mul_int/Test_mul_int.java
index d363abc..1797c4d 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/mul_int/Test_mul_int.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/mul_int/Test_mul_int.java
@@ -101,12 +101,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_int.d.T_mul_int_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_int.d.T_mul_int_2", VerifyError.class);
     }
 
     
@@ -116,12 +111,7 @@
      * @title types of arguments - int, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_int.d.T_mul_int_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_int.d.T_mul_int_3", VerifyError.class);
     }
 
     /**
@@ -129,12 +119,7 @@
      * @title types of arguments - long, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_int.d.T_mul_int_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_int.d.T_mul_int_4", VerifyError.class);
     }
 
     /**
@@ -142,12 +127,7 @@
      * @title types of arguments - reference, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_int.d.T_mul_int_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_int.d.T_mul_int_5", VerifyError.class);
     }
 
     /**
@@ -156,11 +136,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_int.d.T_mul_int_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_int.d.T_mul_int_6", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/mul_int_2addr/Test_mul_int_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/mul_int_2addr/Test_mul_int_2addr.java
index 744d73ea..5cd574f 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/mul_int_2addr/Test_mul_int_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/mul_int_2addr/Test_mul_int_2addr.java
@@ -101,12 +101,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_int_2addr.d.T_mul_int_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_int_2addr.d.T_mul_int_2addr_2", VerifyError.class);
     }
 
     
@@ -116,12 +111,7 @@
      * @title types of arguments - int, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_int_2addr.d.T_mul_int_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_int_2addr.d.T_mul_int_2addr_3", VerifyError.class);
     }
 
     /**
@@ -129,12 +119,7 @@
      * @title types of arguments - long, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_int_2addr.d.T_mul_int_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_int_2addr.d.T_mul_int_2addr_4", VerifyError.class);
     }
 
     /**
@@ -142,12 +127,7 @@
      * @title types of arguments - reference, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_int_2addr.d.T_mul_int_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_int_2addr.d.T_mul_int_2addr_5", VerifyError.class);
     }
 
     /**
@@ -156,11 +136,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_int_2addr.d.T_mul_int_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_int_2addr.d.T_mul_int_2addr_6", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/mul_int_lit16/Test_mul_int_lit16.java b/tools/vm-tests-tf/src/dot/junit/opcodes/mul_int_lit16/Test_mul_int_lit16.java
index 9ff4b9a..2fcfd83 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/mul_int_lit16/Test_mul_int_lit16.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/mul_int_lit16/Test_mul_int_lit16.java
@@ -104,12 +104,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_int_lit16.d.T_mul_int_lit16_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_int_lit16.d.T_mul_int_lit16_7", VerifyError.class);
     }
 
     
@@ -119,12 +114,7 @@
      * @title types of arguments - int * double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_int_lit16.d.T_mul_int_lit16_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_int_lit16.d.T_mul_int_lit16_8", VerifyError.class);
     }
 
     /**
@@ -132,12 +122,7 @@
      * @title types of arguments - long * int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_int_lit16.d.T_mul_int_lit16_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_int_lit16.d.T_mul_int_lit16_9", VerifyError.class);
     }
 
     /**
@@ -145,12 +130,7 @@
      * @title types of arguments - reference * int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_int_lit16.d.T_mul_int_lit16_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_int_lit16.d.T_mul_int_lit16_10", VerifyError.class);
     }
 
     /**
@@ -159,11 +139,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_int_lit16.d.T_mul_int_lit16_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_int_lit16.d.T_mul_int_lit16_3", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/mul_int_lit8/Test_mul_int_lit8.java b/tools/vm-tests-tf/src/dot/junit/opcodes/mul_int_lit8/Test_mul_int_lit8.java
index 86031b8..84b2620 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/mul_int_lit8/Test_mul_int_lit8.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/mul_int_lit8/Test_mul_int_lit8.java
@@ -104,12 +104,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_int_lit8.d.T_mul_int_lit8_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_int_lit8.d.T_mul_int_lit8_7", VerifyError.class);
     }
 
     
@@ -119,12 +114,7 @@
      * @title types of arguments - int * double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_int_lit8.d.T_mul_int_lit8_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_int_lit8.d.T_mul_int_lit8_8", VerifyError.class);
     }
 
     /**
@@ -132,12 +122,7 @@
      * @title types of arguments - long * int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_int_lit8.d.T_mul_int_lit8_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_int_lit8.d.T_mul_int_lit8_9", VerifyError.class);
     }
 
     /**
@@ -145,12 +130,7 @@
      * @title types of arguments - reference * int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_int_lit8.d.T_mul_int_lit8_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_int_lit8.d.T_mul_int_lit8_10", VerifyError.class);
     }
 
     /**
@@ -159,11 +139,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_int_lit8.d.T_mul_int_lit8_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_int_lit8.d.T_mul_int_lit8_3", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/mul_long/Test_mul_long.java b/tools/vm-tests-tf/src/dot/junit/opcodes/mul_long/Test_mul_long.java
index dbf08de..a3e4bf2 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/mul_long/Test_mul_long.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/mul_long/Test_mul_long.java
@@ -109,12 +109,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_long.d.T_mul_long_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_long.d.T_mul_long_2", VerifyError.class);
     }
 
     
@@ -125,12 +120,7 @@
      * @title types of arguments - long * int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_long.d.T_mul_long_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_long.d.T_mul_long_4", VerifyError.class);
     }
 
     /**
@@ -138,12 +128,7 @@
      * @title types of arguments - float * long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_long.d.T_mul_long_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_long.d.T_mul_long_5", VerifyError.class);
     }
 
     /**
@@ -151,12 +136,7 @@
      * @title types of arguments - reference * long
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_long.d.T_mul_long_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_long.d.T_mul_long_6", VerifyError.class);
     }
 
     /**
@@ -165,11 +145,6 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_long.d.T_mul_long_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_long.d.T_mul_long_3", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/mul_long_2addr/Test_mul_long_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/mul_long_2addr/Test_mul_long_2addr.java
index 1e66348..95e0469 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/mul_long_2addr/Test_mul_long_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/mul_long_2addr/Test_mul_long_2addr.java
@@ -109,12 +109,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_long_2addr.d.T_mul_long_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_long_2addr.d.T_mul_long_2addr_2", VerifyError.class);
     }
 
     
@@ -124,12 +119,7 @@
      * @title types of arguments - long * int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_long_2addr.d.T_mul_long_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_long_2addr.d.T_mul_long_2addr_4", VerifyError.class);
     }
 
     /**
@@ -137,12 +127,7 @@
      * @title types of arguments - float * long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_long_2addr.d.T_mul_long_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_long_2addr.d.T_mul_long_2addr_5", VerifyError.class);
     }
 
     /**
@@ -150,12 +135,7 @@
      * @title types of arguments - reference * long
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_long_2addr.d.T_mul_long_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_long_2addr.d.T_mul_long_2addr_6", VerifyError.class);
     }
 
     /**
@@ -164,11 +144,6 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.mul_long_2addr.d.T_mul_long_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.mul_long_2addr.d.T_mul_long_2addr_3", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/neg_double/Test_neg_double.java b/tools/vm-tests-tf/src/dot/junit/opcodes/neg_double/Test_neg_double.java
index a16763f..1618921 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/neg_double/Test_neg_double.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/neg_double/Test_neg_double.java
@@ -101,12 +101,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.neg_double.d.T_neg_double_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.neg_double.d.T_neg_double_2", VerifyError.class);
     }
 
 
@@ -117,12 +112,7 @@
      * @title type of argument - float
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.neg_double.d.T_neg_double_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.neg_double.d.T_neg_double_3", VerifyError.class);
     }
 
     /**
@@ -131,12 +121,7 @@
      * @title type of argument - int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.neg_double.d.T_neg_double_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.neg_double.d.T_neg_double_5", VerifyError.class);
     }
 
     /**
@@ -145,12 +130,7 @@
      * @title type of argument - reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.neg_double.d.T_neg_double_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.neg_double.d.T_neg_double_6", VerifyError.class);
     }
 
     /**
@@ -159,12 +139,7 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.neg_double.d.T_neg_double_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.neg_double.d.T_neg_double_4", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/neg_float/Test_neg_float.java b/tools/vm-tests-tf/src/dot/junit/opcodes/neg_float/Test_neg_float.java
index 8544b18..a5933d7 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/neg_float/Test_neg_float.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/neg_float/Test_neg_float.java
@@ -100,12 +100,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.neg_float.d.T_neg_float_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.neg_float.d.T_neg_float_2", VerifyError.class);
     }
 
 
@@ -116,12 +111,7 @@
      * @title type of argument - double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.neg_float.d.T_neg_float_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.neg_float.d.T_neg_float_3", VerifyError.class);
     }
 
     /**
@@ -130,12 +120,7 @@
      * @title type of argument - long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.neg_float.d.T_neg_float_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.neg_float.d.T_neg_float_4", VerifyError.class);
     }
 
     /**
@@ -144,12 +129,7 @@
      * @title type of argument - reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.neg_float.d.T_neg_float_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.neg_float.d.T_neg_float_5", VerifyError.class);
     }
 
     /**
@@ -158,11 +138,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.neg_float.d.T_neg_float_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.neg_float.d.T_neg_float_6", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/neg_int/Test_neg_int.java b/tools/vm-tests-tf/src/dot/junit/opcodes/neg_int/Test_neg_int.java
index 97290f6..47b29f0 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/neg_int/Test_neg_int.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/neg_int/Test_neg_int.java
@@ -85,12 +85,7 @@
      * @title  number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.neg_int.d.T_neg_int_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.neg_int.d.T_neg_int_3", VerifyError.class);
     }
 
 
@@ -101,12 +96,7 @@
      * @title  type of argument - double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.neg_int.d.T_neg_int_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.neg_int.d.T_neg_int_4", VerifyError.class);
     }
 
     /**
@@ -115,12 +105,7 @@
      * @title  type of argument - long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.neg_int.d.T_neg_int_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.neg_int.d.T_neg_int_5", VerifyError.class);
     }
 
     /**
@@ -129,12 +114,7 @@
      * @title  type of argument - reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.neg_int.d.T_neg_int_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.neg_int.d.T_neg_int_6", VerifyError.class);
     }
 
     /**
@@ -143,11 +123,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.neg_int.d.T_neg_int_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.neg_int.d.T_neg_int_7", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/neg_long/Test_neg_long.java b/tools/vm-tests-tf/src/dot/junit/opcodes/neg_long/Test_neg_long.java
index 6880c94..8a1049e 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/neg_long/Test_neg_long.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/neg_long/Test_neg_long.java
@@ -86,12 +86,7 @@
      * @title  number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.neg_long.d.T_neg_long_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.neg_long.d.T_neg_long_3", VerifyError.class);
     }
 
 
@@ -101,12 +96,7 @@
      * @title type of argument - int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.neg_long.d.T_neg_long_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.neg_long.d.T_neg_long_5", VerifyError.class);
     }
 
     /**
@@ -115,12 +105,7 @@
      * @title type of argument - float
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.neg_long.d.T_neg_long_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.neg_long.d.T_neg_long_6", VerifyError.class);
     }
 
     /**
@@ -129,12 +114,7 @@
      * @title type of argument - reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.neg_long.d.T_neg_long_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.neg_long.d.T_neg_long_7", VerifyError.class);
     }
 
     /**
@@ -143,11 +123,6 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.neg_long.d.T_neg_long_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.neg_long.d.T_neg_long_4", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/new_array/Test_new_array.java b/tools/vm-tests-tf/src/dot/junit/opcodes/new_array/Test_new_array.java
index 44aedaa1..1e990c2 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/new_array/Test_new_array.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/new_array/Test_new_array.java
@@ -86,13 +86,8 @@
      * @title expected NegativeArraySizeException
      */
     public void testE1() {
-        T_new_array_2 t = new T_new_array_2();
-        try {
-            t.run(-1);
-            fail("expected NegativeArraySizeException");
-        } catch (NegativeArraySizeException nase) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.new_array.d.T_new_array_2", NegativeArraySizeException.class,
+                   -1);
     }
 
 
@@ -101,12 +96,7 @@
      * @title  number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.new_array.d.T_new_array_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.new_array.d.T_new_array_4", VerifyError.class);
     }
 
     /**
@@ -115,12 +105,7 @@
      * @title  size argument - long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.new_array.d.T_new_array_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.new_array.d.T_new_array_5", VerifyError.class);
     }
 
     /**
@@ -129,12 +114,7 @@
      * @title  size argument - reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.new_array.d.T_new_array_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.new_array.d.T_new_array_9", VerifyError.class);
     }
 
     /**
@@ -143,12 +123,7 @@
      * @title  constant pool index
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.new_array.d.T_new_array_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.new_array.d.T_new_array_6", VerifyError.class);
     }
 
     /**
@@ -157,12 +132,7 @@
      * @title  attempt to create object
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.new_array.d.T_new_array_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.new_array.d.T_new_array_7", VerifyError.class);
     }
 
     /**
@@ -171,12 +141,7 @@
      * @title  array of more than 255 dimensions
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.new_array.d.T_new_array_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.new_array.d.T_new_array_8", ClassNotFoundException.class);
     }
 
     /**
@@ -184,11 +149,7 @@
      * @title Attempt to instantiate array of non-existent class.
      */
     public void testVFE7() {
-        try {
-            new T_new_array_11().run();
-            fail("expected NoClassDefFoundError");
-        } catch (NoClassDefFoundError t) {
-        }
+        loadAndRun("dot.junit.opcodes.new_array.d.T_new_array_11", NoClassDefFoundError.class);
     }
 
     /**
@@ -197,11 +158,7 @@
      */
     public void testVFE8() {
         //@uses dot.junit.opcodes.new_array.TestStubs
-        try {
-            new T_new_array_10().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.new_array.d.T_new_array_10", IllegalAccessError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/new_instance/Test_new_instance.java b/tools/vm-tests-tf/src/dot/junit/opcodes/new_instance/Test_new_instance.java
index d994f65..3209553 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/new_instance/Test_new_instance.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/new_instance/Test_new_instance.java
@@ -42,12 +42,8 @@
      * @title class initialization throws exception
      */
     public void testE1() {
-        try {
-            T_new_instance_3.run();
-            fail("expected Error");
-        } catch (Error e) {
-            // expected
-        }
+        load("dot.junit.opcodes.new_instance.d.T_new_instance_3",
+             ExceptionInInitializerError.class);
     }
 
     /**
@@ -56,14 +52,7 @@
      */
     public void testE4() {
         //@uses dot.junit.opcodes.new_instance.d.TestAbstractClass
-        //@uses dot.junit.opcodes.new_instance.d.T_new_instance_8
-        T_new_instance_8 t = new T_new_instance_8();
-        try {
-            t.run();
-            fail("expected InstantiationError");
-        } catch (InstantiationError ie) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.new_instance.d.T_new_instance_8", InstantiationError.class);
     }
 
     /**
@@ -73,14 +62,7 @@
      */
     public void testE5() {
         //@uses dot.junit.opcodes.new_instance.d.TestAbstractClass
-        //@uses dot.junit.opcodes.new_instance.d.T_new_instance_9
-        T_new_instance_9 t = new T_new_instance_9();
-        try {
-            t.run();
-            fail("expected Error");
-        } catch (Error iae) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.new_instance.d.T_new_instance_9", InstantiationError.class);
     }
 
     /**
@@ -88,12 +70,7 @@
      * @title  constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.new_instance.d.T_new_instance_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.new_instance.d.T_new_instance_6", VerifyError.class);
     }
 
     /**
@@ -102,12 +79,7 @@
      * @title  attempt to create array using new
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.new_instance.d.T_new_instance_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.new_instance.d.T_new_instance_7", VerifyError.class);
     }
 
     /**
@@ -116,12 +88,7 @@
      * called
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.new_instance.d.T_new_instance_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.new_instance.d.T_new_instance_2", VerifyError.class);
     }
 
     /**
@@ -129,12 +96,7 @@
      * @title number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.new_instance.d.T_new_instance_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.new_instance.d.T_new_instance_10", VerifyError.class);
     }
 
     /**
@@ -143,12 +105,7 @@
      */
     public void testVFE5() {
         //@uses dot.junit.opcodes.new_instance.TestStubs
-        //@uses dot.junit.opcodes.new_instance.d.T_new_instance_4
-        try {
-            new T_new_instance_4().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.new_instance.d.T_new_instance_4", IllegalAccessError.class);
     }
 
     /**
@@ -156,11 +113,7 @@
      * @title Attempt to instantiate array of non-existent class.
      */
     public void testVFE6() {
-        try {
-            new T_new_instance_5().run();
-            fail("expected NoClassDefFoundError");
-        } catch (NoClassDefFoundError t) {
-        }
+        loadAndRun("dot.junit.opcodes.new_instance.d.T_new_instance_5", NoClassDefFoundError.class);
     }
 
     /**
@@ -169,12 +122,7 @@
      * if the same new-instance  instruction is again executed before the instance is initialized
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.new_instance.d.T_new_instance_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.new_instance.d.T_new_instance_11", VerifyError.class);
     }
 
     /**
@@ -183,11 +131,6 @@
      * if the same new-instance  instruction is again executed before the instance is initialized
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.new_instance.d.T_new_instance_12");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.new_instance.d.T_new_instance_12", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/not_int/Test_not_int.java b/tools/vm-tests-tf/src/dot/junit/opcodes/not_int/Test_not_int.java
index 110a842..1bf3f15 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/not_int/Test_not_int.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/not_int/Test_not_int.java
@@ -111,12 +111,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.not_int.d.T_not_int_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.not_int.d.T_not_int_3", VerifyError.class);
     }
 
     
@@ -126,12 +121,7 @@
      * @title types of arguments - double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.not_int.d.T_not_int_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.not_int.d.T_not_int_4", VerifyError.class);
     }
 
     /**
@@ -139,12 +129,7 @@
      * @title types of arguments - long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.not_int.d.T_not_int_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.not_int.d.T_not_int_5", VerifyError.class);
     }
 
     /**
@@ -152,12 +137,7 @@
      * @title types of arguments - reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.not_int.d.T_not_int_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.not_int.d.T_not_int_6", VerifyError.class);
     }
 
     /**
@@ -166,12 +146,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.not_int.d.T_not_int_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.not_int.d.T_not_int_2", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/not_long/Test_not_long.java b/tools/vm-tests-tf/src/dot/junit/opcodes/not_long/Test_not_long.java
index 9e3c614..acb656d 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/not_long/Test_not_long.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/not_long/Test_not_long.java
@@ -93,12 +93,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.not_long.d.T_not_long_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.not_long.d.T_not_long_3", VerifyError.class);
     }
 
     
@@ -108,12 +103,7 @@
      * @title types of arguments - int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.not_long.d.T_not_long_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.not_long.d.T_not_long_4", VerifyError.class);
     }
 
     /**
@@ -121,12 +111,7 @@
      * @title types of arguments - float
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.not_long.d.T_not_long_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.not_long.d.T_not_long_5", VerifyError.class);
     }
 
     /**
@@ -134,12 +119,7 @@
      * @title types of arguments - reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.not_long.d.T_not_long_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.not_long.d.T_not_long_6", VerifyError.class);
     }
 
     /**
@@ -148,11 +128,6 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.not_long.d.T_not_long_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.not_long.d.T_not_long_2", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/opc_const/Test_opc_const.java b/tools/vm-tests-tf/src/dot/junit/opcodes/opc_const/Test_opc_const.java
index aa19e6c..87383ce 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/opc_const/Test_opc_const.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/opc_const/Test_opc_const.java
@@ -48,12 +48,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.opc_const.d.T_opc_const_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.opc_const.d.T_opc_const_3", VerifyError.class);
     }
     
     /**
@@ -63,12 +58,7 @@
      * other register involved in it becomes undefined
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.opc_const.d.T_opc_const_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.opc_const.d.T_opc_const_4", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/opc_goto/Test_opc_goto.java b/tools/vm-tests-tf/src/dot/junit/opcodes/opc_goto/Test_opc_goto.java
index a3558fe..64f0d5a 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/opc_goto/Test_opc_goto.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/opc_goto/Test_opc_goto.java
@@ -35,12 +35,7 @@
     * @title branch target is inside instruction
     */
    public void testVFE1() {
-       try {
-           Class.forName("dot.junit.opcodes.opc_goto.d.T_opc_goto_2");
-           fail("expected a verification exception");
-       } catch (Throwable t) {
-           DxUtil.checkVerifyException(t);
-       }
+        load("dot.junit.opcodes.opc_goto.d.T_opc_goto_2", VerifyError.class);
    }
 
    /**
@@ -48,12 +43,7 @@
     * @title branch target shall be inside the method
     */
    public void testVFE2() {
-       try {
-           Class.forName("dot.junit.opcodes.opc_goto.d.T_opc_goto_3");
-           fail("expected a verification exception");
-       } catch (Throwable t) {
-           DxUtil.checkVerifyException(t);
-       }
+        load("dot.junit.opcodes.opc_goto.d.T_opc_goto_3", VerifyError.class);
    }
 
    /**
@@ -61,12 +51,7 @@
     * @title zero offset
     */
    public void testVFE3() {
-       try {
-           Class.forName("dot.junit.opcodes.opc_goto.d.T_opc_goto_4");
-           fail("expected a verification exception");
-       } catch (Throwable t) {
-           DxUtil.checkVerifyException(t);
-       }
+        load("dot.junit.opcodes.opc_goto.d.T_opc_goto_4", VerifyError.class);
    }
    
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/opc_return/Test_opc_return.java b/tools/vm-tests-tf/src/dot/junit/opcodes/opc_return/Test_opc_return.java
index 2fe8323..3d69bfa 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/opc_return/Test_opc_return.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/opc_return/Test_opc_return.java
@@ -30,32 +30,20 @@
         assertEquals(123456, t.run());
     }
 
-
     /**
      * @title Method is synchronized but thread is not monitor owner
      */
     public void testE1() {
-        T_opc_return_3 t = new T_opc_return_3();
-        try {
-            assertTrue(t.run());
-            fail("expected IllegalMonitorStateException");
-        } catch (IllegalMonitorStateException imse) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.opc_return.d.T_opc_return_3",
+                   IllegalMonitorStateException.class);
     }
 
-
     /**
      * @constraint B11 
      * @title method's return type - long
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.opc_return.d.T_opc_return_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.opc_return.d.T_opc_return_5", VerifyError.class);
     }
 
     /**
@@ -63,12 +51,7 @@
      * @title method's return type - reference
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.opc_return.d.T_opc_return_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.opc_return.d.T_opc_return_6", VerifyError.class);
     }
 
     /**
@@ -76,12 +59,7 @@
      * @title number of registers
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.opc_return.d.T_opc_return_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.opc_return.d.T_opc_return_7", VerifyError.class);
     }
     
     /**
@@ -89,12 +67,6 @@
      * @title return on wide register pair
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.opc_return.d.T_opc_return_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.opc_return.d.T_opc_return_8", VerifyError.class);
     }
-
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/opc_throw/Test_opc_throw.java b/tools/vm-tests-tf/src/dot/junit/opcodes/opc_throw/Test_opc_throw.java
index 5055336..7baf67d 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/opc_throw/Test_opc_throw.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/opc_throw/Test_opc_throw.java
@@ -79,26 +79,15 @@
      * a NullPointerException instead of objectref
      */
     public void testE1() {
-        T_opc_throw_4 t = new T_opc_throw_4();
-        try {
-            t.run();
-            fail("expected NullPointerException");
-        } catch (NullPointerException npe) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.opc_throw.d.T_opc_throw_4", NullPointerException.class);
     }
 
     /**
      * @title expected IllegalMonitorStateException
      */
     public void testE2() {
-        T_opc_throw_5 t = new T_opc_throw_5();
-        try {
-            t.run();
-            fail("expected IllegalMonitorStateException");
-        } catch (IllegalMonitorStateException imse) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.opc_throw.d.T_opc_throw_5", 
+                   IllegalMonitorStateException.class);
     }
 
     /**
@@ -106,12 +95,7 @@
      * @title  (number of registers)
      */
     public void testVFE2() {
-        try {
-            Class.forName("dxc.junit.opcodes.opc_throw.jm.T_opc_throw_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.opc_throw.d.T_opc_throw_6", VerifyError.class);
     }
 
     
@@ -122,12 +106,7 @@
      * @title type of argument - float
      */
     public void testVFE3() {
-        try {
-            Class.forName("dxc.junit.opcodes.opc_throw.jm.T_opc_throw_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.opc_throw.d.T_opc_throw_7", VerifyError.class);
     }
     
     /**
@@ -136,12 +115,7 @@
      * @title type of argument - long
      */
     public void testVFE4() {
-        try {
-            Class.forName("dxc.junit.opcodes.opc_throw.jm.T_opc_throw_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.opc_throw.d.T_opc_throw_7", VerifyError.class);
     }
 
     /**
@@ -151,11 +125,6 @@
 
      */
     public void testVFE5() {
-        try {
-            Class.forName("dxc.junit.opcodes.opc_throw.jm.T_opc_throw_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.opc_throw.d.T_opc_throw_10", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/or_int/Test_or_int.java b/tools/vm-tests-tf/src/dot/junit/opcodes/or_int/Test_or_int.java
index a7eb005..7a34434 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/or_int/Test_or_int.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/or_int/Test_or_int.java
@@ -68,12 +68,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.or_int.d.T_or_int_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_int.d.T_or_int_2", VerifyError.class);
     }
 
     
@@ -83,12 +78,7 @@
      * @title types of arguments - double & int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.or_int.d.T_or_int_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_int.d.T_or_int_3", VerifyError.class);
     }
 
     /**
@@ -96,12 +86,7 @@
      * @title types of arguments - long & int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.or_int.d.T_or_int_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_int.d.T_or_int_4", VerifyError.class);
     }
 
     /**
@@ -109,12 +94,7 @@
      * @title types of arguments - reference & int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.or_int.d.T_or_int_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_int.d.T_or_int_5", VerifyError.class);
     }
 
     /**
@@ -123,11 +103,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.or_int.d.T_or_int_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_int.d.T_or_int_6", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/or_int_2addr/Test_or_int_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/or_int_2addr/Test_or_int_2addr.java
index 0a0a66c..b453125 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/or_int_2addr/Test_or_int_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/or_int_2addr/Test_or_int_2addr.java
@@ -68,12 +68,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.or_int_2addr.d.T_or_int_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_int_2addr.d.T_or_int_2addr_2", VerifyError.class);
     }
 
     
@@ -83,12 +78,7 @@
      * @title types of arguments - double & int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.or_int_2addr.d.T_or_int_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_int_2addr.d.T_or_int_2addr_3", VerifyError.class);
     }
 
     /**
@@ -96,12 +86,7 @@
      * @title types of arguments - long & int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.or_int_2addr.d.T_or_int_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_int_2addr.d.T_or_int_2addr_4", VerifyError.class);
     }
 
     /**
@@ -109,12 +94,7 @@
      * @title types of arguments - reference & int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.or_int_2addr.d.T_or_int_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_int_2addr.d.T_or_int_2addr_5", VerifyError.class);
     }
 
     /**
@@ -123,11 +103,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.or_int_2addr.d.T_or_int_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_int_2addr.d.T_or_int_2addr_6", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/or_int_lit16/Test_or_int_lit16.java b/tools/vm-tests-tf/src/dot/junit/opcodes/or_int_lit16/Test_or_int_lit16.java
index eff9cbc..efabaec 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/or_int_lit16/Test_or_int_lit16.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/or_int_lit16/Test_or_int_lit16.java
@@ -71,12 +71,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.or_int_lit16.d.T_or_int_lit16_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_int_lit16.d.T_or_int_lit16_6", VerifyError.class);
     }
 
     
@@ -86,12 +81,7 @@
      * @title types of arguments - double & int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.or_int_lit16.d.T_or_int_lit16_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_int_lit16.d.T_or_int_lit16_7", VerifyError.class);
     }
 
     /**
@@ -99,12 +89,7 @@
      * @title types of arguments - long & int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.or_int_lit16.d.T_or_int_lit16_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_int_lit16.d.T_or_int_lit16_8", VerifyError.class);
     }
 
     /**
@@ -112,12 +97,7 @@
      * @title types of arguments - reference & int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.or_int_lit16.d.T_or_int_lit16_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_int_lit16.d.T_or_int_lit16_9", VerifyError.class);
     }
 
     /**
@@ -126,11 +106,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.or_int_lit16.d.T_or_int_lit16_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_int_lit16.d.T_or_int_lit16_4", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/or_int_lit8/Test_or_int_lit8.java b/tools/vm-tests-tf/src/dot/junit/opcodes/or_int_lit8/Test_or_int_lit8.java
index cfddb9b..90f4679 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/or_int_lit8/Test_or_int_lit8.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/or_int_lit8/Test_or_int_lit8.java
@@ -71,12 +71,7 @@
      * @title  number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.or_int_lit8.d.T_or_int_lit8_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_int_lit8.d.T_or_int_lit8_6", VerifyError.class);
     }
 
     
@@ -86,12 +81,7 @@
      * @title  types of arguments - double & int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.or_int_lit8.d.T_or_int_lit8_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_int_lit8.d.T_or_int_lit8_7", VerifyError.class);
     }
 
     /**
@@ -99,12 +89,7 @@
      * @title  types of arguments - long & int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.or_int_lit8.d.T_or_int_lit8_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_int_lit8.d.T_or_int_lit8_8", VerifyError.class);
     }
 
     /**
@@ -112,12 +97,7 @@
      * @title  types of arguments - reference & int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.or_int_lit8.d.T_or_int_lit8_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_int_lit8.d.T_or_int_lit8_9", VerifyError.class);
     }
 
     /**
@@ -126,11 +106,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.or_int_lit8.d.T_or_int_lit8_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_int_lit8.d.T_or_int_lit8_4", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/or_long/Test_or_long.java b/tools/vm-tests-tf/src/dot/junit/opcodes/or_long/Test_or_long.java
index 6076ad3..7b3e50f 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/or_long/Test_or_long.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/or_long/Test_or_long.java
@@ -69,12 +69,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.or_long.d.T_or_long_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_long.d.T_or_long_2", VerifyError.class);
     }
 
     
@@ -84,12 +79,7 @@
      * @title types of arguments - int & long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.or_long.d.T_or_long_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_long.d.T_or_long_4", VerifyError.class);
     }
 
     /**
@@ -97,12 +87,7 @@
      * @title types of arguments - float & long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.or_long.d.T_or_long_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_long.d.T_or_long_5", VerifyError.class);
     }
 
     /**
@@ -110,12 +95,7 @@
      * @title types of arguments - reference & long
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.or_long.d.T_or_long_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_long.d.T_or_long_6", VerifyError.class);
     }
 
     /**
@@ -124,11 +104,6 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.or_long.d.T_or_long_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_long.d.T_or_long_3", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/or_long_2addr/Test_or_long_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/or_long_2addr/Test_or_long_2addr.java
index c9aa587..98532de 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/or_long_2addr/Test_or_long_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/or_long_2addr/Test_or_long_2addr.java
@@ -69,12 +69,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.or_long_2addr.d.T_or_long_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_long_2addr.d.T_or_long_2addr_2", VerifyError.class);
     }
 
     
@@ -84,12 +79,7 @@
      * @title types of arguments - int & long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.or_long_2addr.d.T_or_long_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_long_2addr.d.T_or_long_2addr_4", VerifyError.class);
     }
 
     /**
@@ -97,12 +87,7 @@
      * @title types of arguments - float & long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.or_long_2addr.d.T_or_long_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_long_2addr.d.T_or_long_2addr_5", VerifyError.class);
     }
 
     /**
@@ -110,12 +95,7 @@
      * @title types of arguments - reference & long
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.or_long_2addr.d.T_or_long_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_long_2addr.d.T_or_long_2addr_6", VerifyError.class);
     }
 
     /**
@@ -124,11 +104,6 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.or_long_2addr.d.T_or_long_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.or_long_2addr.d.T_or_long_2addr_3", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/packed_switch/Test_packed_switch.java b/tools/vm-tests-tf/src/dot/junit/opcodes/packed_switch/Test_packed_switch.java
index 5b983e1..992dd59 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/packed_switch/Test_packed_switch.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/packed_switch/Test_packed_switch.java
@@ -68,12 +68,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.packed_switch.d.T_packed_switch_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.packed_switch.d.T_packed_switch_3", VerifyError.class);
     }
 
 
@@ -83,12 +78,7 @@
      * @title type of argument - double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.packed_switch.d.T_packed_switch_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.packed_switch.d.T_packed_switch_4", VerifyError.class);
     }
     
     /**
@@ -96,12 +86,7 @@
      * @title type of argument - long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.packed_switch.d.T_packed_switch_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.packed_switch.d.T_packed_switch_5", VerifyError.class);
     }
     
     /**
@@ -109,12 +94,7 @@
      * @title type of argument - reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.packed_switch.d.T_packed_switch_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.packed_switch.d.T_packed_switch_6", VerifyError.class);
     }
 
     /**
@@ -122,12 +102,7 @@
      * @title branch target shall be inside the method
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.packed_switch.d.T_packed_switch_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.packed_switch.d.T_packed_switch_7", VerifyError.class);
     }
 
     /**
@@ -135,12 +110,7 @@
      * @title branch target shall not be "inside" instruction
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.packed_switch.d.T_packed_switch_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.packed_switch.d.T_packed_switch_8", VerifyError.class);
     }
 
 
@@ -149,12 +119,7 @@
      * @title offset to table shall be inside method
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.packed_switch.d.T_packed_switch_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.packed_switch.d.T_packed_switch_9", VerifyError.class);
     }
 
     /**
@@ -163,12 +128,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.packed_switch.d.T_packed_switch_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.packed_switch.d.T_packed_switch_2", VerifyError.class);
     }
 
     /**
@@ -176,12 +136,7 @@
      * @title the size and the list of targets must be consistent. 
      */
     public void testVFE9() {
-        try {
-            Class.forName("dot.junit.opcodes.packed_switch.d.T_packed_switch_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.packed_switch.d.T_packed_switch_11", VerifyError.class);
     }
 
     
@@ -190,12 +145,7 @@
      * @title packed-switch-data pseudo-instructions must not be reachable by control flow 
      */
     public void testVFE10() {
-        try {
-            Class.forName("dot.junit.opcodes.packed_switch.d.T_packed_switch_12");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.packed_switch.d.T_packed_switch_12", VerifyError.class);
     }
     
     /**
@@ -203,11 +153,6 @@
      * @title table has wrong ident code
      */
     public void testVFE11() {
-        try {
-            Class.forName("dot.junit.opcodes.packed_switch.d.T_packed_switch_13");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.packed_switch.d.T_packed_switch_13", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/rem_double/Test_rem_double.java b/tools/vm-tests-tf/src/dot/junit/opcodes/rem_double/Test_rem_double.java
index b3a9c92..c019053 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/rem_double/Test_rem_double.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/rem_double/Test_rem_double.java
@@ -127,12 +127,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_double.d.T_rem_double_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_double.d.T_rem_double_2", VerifyError.class);
     }
 
     
@@ -142,12 +137,7 @@
      * @title types of arguments - float, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_double.d.T_rem_double_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_double.d.T_rem_double_3", VerifyError.class);
     }
 
     /**
@@ -155,12 +145,7 @@
      * @title types of arguments - double, reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_double.d.T_rem_double_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_double.d.T_rem_double_5", VerifyError.class);
     }
     
     /**
@@ -168,12 +153,7 @@
      * @title types of arguments - double, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_double.d.T_rem_double_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_double.d.T_rem_double_6", VerifyError.class);
     }
 
     /**
@@ -182,11 +162,6 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_double.d.T_rem_double_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_double.d.T_rem_double_4", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/rem_double_2addr/Test_rem_double_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/rem_double_2addr/Test_rem_double_2addr.java
index 15020da..6e32b1a 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/rem_double_2addr/Test_rem_double_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/rem_double_2addr/Test_rem_double_2addr.java
@@ -127,12 +127,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_double_2addr.d.T_rem_double_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_double_2addr.d.T_rem_double_2addr_2", VerifyError.class);
     }
 
     
@@ -142,12 +137,7 @@
      * @title types of arguments - float, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_double_2addr.d.T_rem_double_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_double_2addr.d.T_rem_double_2addr_3", VerifyError.class);
     }
 
     /**
@@ -155,12 +145,7 @@
      * @title types of arguments - double, reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_double_2addr.d.T_rem_double_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_double_2addr.d.T_rem_double_2addr_5", VerifyError.class);
     }
     
     /**
@@ -168,12 +153,7 @@
      * @title types of arguments - double, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_double_2addr.d.T_rem_double_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_double_2addr.d.T_rem_double_2addr_6", VerifyError.class);
     }
 
     /**
@@ -182,11 +162,6 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_double_2addr.d.T_rem_double_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_double_2addr.d.T_rem_double_2addr_4", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/rem_float/Test_rem_float.java b/tools/vm-tests-tf/src/dot/junit/opcodes/rem_float/Test_rem_float.java
index b028af7..004f4ad 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/rem_float/Test_rem_float.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/rem_float/Test_rem_float.java
@@ -126,12 +126,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_float.d.T_rem_float_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_float.d.T_rem_float_2", VerifyError.class);
     }
 
     
@@ -141,12 +136,7 @@
      * @title types of arguments - float, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_float.d.T_rem_float_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_float.d.T_rem_float_3", VerifyError.class);
     }
 
     /**
@@ -154,12 +144,7 @@
      * @title types of arguments - long, float
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_float.d.T_rem_float_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_float.d.T_rem_float_4", VerifyError.class);
     }
 
     /**
@@ -167,12 +152,7 @@
      * @title types of arguments - reference, float
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_float.d.T_rem_float_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_float.d.T_rem_float_5", VerifyError.class);
     }
 
     /**
@@ -181,11 +161,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_float.d.T_rem_float_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_float.d.T_rem_float_6", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/rem_float_2addr/Test_rem_float_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/rem_float_2addr/Test_rem_float_2addr.java
index 29a1e49..f5055b2 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/rem_float_2addr/Test_rem_float_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/rem_float_2addr/Test_rem_float_2addr.java
@@ -126,12 +126,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_float_2addr.d.T_rem_float_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_float_2addr.d.T_rem_float_2addr_2", VerifyError.class);
     }
 
     
@@ -141,12 +136,7 @@
      * @title types of arguments - float, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_float_2addr.d.T_rem_float_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_float_2addr.d.T_rem_float_2addr_3", VerifyError.class);
     }
 
     /**
@@ -154,12 +144,7 @@
      * @title types of arguments - long, float
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_float_2addr.d.T_rem_float_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_float_2addr.d.T_rem_float_2addr_4", VerifyError.class);
     }
 
     /**
@@ -167,12 +152,7 @@
      * @title types of arguments - reference, float
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_float_2addr.d.T_rem_float_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_float_2addr.d.T_rem_float_2addr_5", VerifyError.class);
     }
 
     /**
@@ -182,11 +162,6 @@
      * Note: This test works only in ICS and beyond.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_float_2addr.d.T_rem_float_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_float_2addr.d.T_rem_float_2addr_6", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/rem_int/Test_rem_int.java b/tools/vm-tests-tf/src/dot/junit/opcodes/rem_int/Test_rem_int.java
index 5dd0915..dbecced 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/rem_int/Test_rem_int.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/rem_int/Test_rem_int.java
@@ -123,13 +123,7 @@
      * @title Divisor is 0
      */
     public void testE1() {
-        T_rem_int_1 t = new T_rem_int_1();
-        try {
-            t.run(1, 0);
-            fail("expected ArithmeticException");
-        } catch (ArithmeticException ae) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.rem_int.d.T_rem_int_1", ArithmeticException.class, 1, 0);
     }
 
     /**
@@ -137,12 +131,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_int.d.T_rem_int_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_int.d.T_rem_int_2", VerifyError.class);
     }
 
     
@@ -152,12 +141,7 @@
      * @title types of arguments - int, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_int.d.T_rem_int_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_int.d.T_rem_int_3", VerifyError.class);
     }
 
     /**
@@ -165,12 +149,7 @@
      * @title types of arguments - long, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_int.d.T_rem_int_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_int.d.T_rem_int_4", VerifyError.class);
     }
 
     /**
@@ -178,12 +157,7 @@
      * @title types of arguments - reference, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_int.d.T_rem_int_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_int.d.T_rem_int_5", VerifyError.class);
     }
 
     /**
@@ -192,12 +166,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_int.d.T_rem_int_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_int.d.T_rem_int_6", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/rem_int_2addr/Test_rem_int_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/rem_int_2addr/Test_rem_int_2addr.java
index 5972821..9c5d1df 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/rem_int_2addr/Test_rem_int_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/rem_int_2addr/Test_rem_int_2addr.java
@@ -123,13 +123,8 @@
      * @title Divisor is 0
      */
     public void testE1() {
-        T_rem_int_2addr_1 t = new T_rem_int_2addr_1();
-        try {
-            t.run(1, 0);
-            fail("expected ArithmeticException");
-        } catch (ArithmeticException ae) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.rem_int_2addr.d.T_rem_int_2addr_1", ArithmeticException.class,
+                   1, 0);
     }
 
     /**
@@ -137,12 +132,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_int_2addr.d.T_rem_int_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_int_2addr.d.T_rem_int_2addr_2", VerifyError.class);
     }
 
     
@@ -152,12 +142,7 @@
      * @title types of arguments - int, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_int_2addr.d.T_rem_int_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_int_2addr.d.T_rem_int_2addr_3", VerifyError.class);
     }
 
     /**
@@ -165,12 +150,7 @@
      * @title types of arguments - long, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_int_2addr.d.T_rem_int_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_int_2addr.d.T_rem_int_2addr_4", VerifyError.class);
     }
 
     /**
@@ -178,12 +158,7 @@
      * @title types of arguments - reference, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_int_2addr.d.T_rem_int_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_int_2addr.d.T_rem_int_2addr_5", VerifyError.class);
     }
 
     /**
@@ -192,12 +167,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_int_2addr.d.T_rem_int_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_int_2addr.d.T_rem_int_2addr_6", VerifyError.class);
     }
     
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/rem_int_lit16/Test_rem_int_lit16.java b/tools/vm-tests-tf/src/dot/junit/opcodes/rem_int_lit16/Test_rem_int_lit16.java
index 725391c..ce4c842 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/rem_int_lit16/Test_rem_int_lit16.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/rem_int_lit16/Test_rem_int_lit16.java
@@ -130,13 +130,8 @@
      * @title Divisor is 0
      */
     public void testE1() {
-        T_rem_int_lit16_9 t = new T_rem_int_lit16_9();
-        try {
-            t.run(1);
-            fail("expected ArithmeticException");
-        } catch (ArithmeticException ae) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.rem_int_lit16.d.T_rem_int_lit16_9", ArithmeticException.class,
+                   1);
     }
 
     /**
@@ -144,12 +139,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_int_lit16.d.T_rem_int_lit16_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_int_lit16.d.T_rem_int_lit16_10", VerifyError.class);
     }
 
     
@@ -159,12 +149,7 @@
      * @title types of arguments - int, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_int_lit16.d.T_rem_int_lit16_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_int_lit16.d.T_rem_int_lit16_11", VerifyError.class);
     }
 
     /**
@@ -172,12 +157,7 @@
      * @title types of arguments - long, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_int_lit16.d.T_rem_int_lit16_12");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_int_lit16.d.T_rem_int_lit16_12", VerifyError.class);
     }
 
     /**
@@ -185,12 +165,7 @@
      * @title types of arguments - reference, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_int_lit16.d.T_rem_int_lit16_13");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_int_lit16.d.T_rem_int_lit16_13", VerifyError.class);
     }
 
     /**
@@ -199,11 +174,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_int_lit16.d.T_rem_int_lit16_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_int_lit16.d.T_rem_int_lit16_4", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/rem_int_lit8/Test_rem_int_lit8.java b/tools/vm-tests-tf/src/dot/junit/opcodes/rem_int_lit8/Test_rem_int_lit8.java
index 62b4f5b..54c2e6c 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/rem_int_lit8/Test_rem_int_lit8.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/rem_int_lit8/Test_rem_int_lit8.java
@@ -130,13 +130,8 @@
      * @title Divisor is 0
      */
     public void testE1() {
-        T_rem_int_lit8_9 t = new T_rem_int_lit8_9();
-        try {
-            t.run(1);
-            fail("expected ArithmeticException");
-        } catch (ArithmeticException ae) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.rem_int_lit8.d.T_rem_int_lit8_9", ArithmeticException.class,
+                   1);
     }
 
     /**
@@ -144,12 +139,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_int_lit8.d.T_rem_int_lit8_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_int_lit8.d.T_rem_int_lit8_10", VerifyError.class);
     }
 
     
@@ -159,12 +149,7 @@
      * @title types of arguments - int, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_int_lit8.d.T_rem_int_lit8_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_int_lit8.d.T_rem_int_lit8_11", VerifyError.class);
     }
 
     /**
@@ -172,12 +157,7 @@
      * @title types of arguments - long, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_int_lit8.d.T_rem_int_lit8_12");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_int_lit8.d.T_rem_int_lit8_12", VerifyError.class);
     }
 
     /**
@@ -185,12 +165,7 @@
      * @title types of arguments - reference, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_int_lit8.d.T_rem_int_lit8_13");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_int_lit8.d.T_rem_int_lit8_13", VerifyError.class);
     }
 
     /**
@@ -199,12 +174,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_int_lit8.d.T_rem_int_lit8_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_int_lit8.d.T_rem_int_lit8_4", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/rem_long/Test_rem_long.java b/tools/vm-tests-tf/src/dot/junit/opcodes/rem_long/Test_rem_long.java
index d5493a7..c3edea6 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/rem_long/Test_rem_long.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/rem_long/Test_rem_long.java
@@ -123,13 +123,8 @@
      * @title Divisor is 0
      */
     public void testE1() {
-        T_rem_long_1 t = new T_rem_long_1();
-        try {
-            t.run(1234567890123l, 0l);
-            fail("expected ArithmeticException");
-        } catch (ArithmeticException ae) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.rem_long.d.T_rem_long_1", ArithmeticException.class,
+                   1234567890123l, 0l);
     }
 
     /**
@@ -137,12 +132,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_long.d.T_rem_long_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_long.d.T_rem_long_2", VerifyError.class);
     }
 
     
@@ -152,12 +142,7 @@
      * @title types of arguments - int, long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_long.d.T_rem_long_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_long.d.T_rem_long_4", VerifyError.class);
     }
 
     /**
@@ -165,12 +150,7 @@
      * @title types of arguments - long, float
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_long.d.T_rem_long_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_long.d.T_rem_long_5", VerifyError.class);
     }
 
     /**
@@ -178,12 +158,7 @@
      * @title types of arguments - reference, long
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_long.d.T_rem_long_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_long.d.T_rem_long_6", VerifyError.class);
     }
 
     /**
@@ -192,11 +167,6 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_long.d.T_rem_long_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_long.d.T_rem_long_3", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/rem_long_2addr/Test_rem_long_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/rem_long_2addr/Test_rem_long_2addr.java
index 16f38a6..6919e22 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/rem_long_2addr/Test_rem_long_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/rem_long_2addr/Test_rem_long_2addr.java
@@ -123,13 +123,8 @@
      * @title Divisor is 0
      */
     public void testE1() {
-        T_rem_long_2addr_1 t = new T_rem_long_2addr_1();
-        try {
-            t.run(1234567890123l, 0l);
-            fail("expected ArithmeticException");
-        } catch (ArithmeticException ae) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.rem_long_2addr.d.T_rem_long_2addr_1",
+                   ArithmeticException.class, 1234567890123l, 0l);
     }
 
     /**
@@ -137,12 +132,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_long_2addr.d.T_rem_long_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_long_2addr.d.T_rem_long_2addr_2", VerifyError.class);
     }
 
     
@@ -152,12 +142,7 @@
      * @title  (types of arguments - int, long).
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_long_2addr.d.T_rem_long_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_long_2addr.d.T_rem_long_2addr_4", VerifyError.class);
     }
 
     /**
@@ -165,12 +150,7 @@
      * @title types of arguments - long, float
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_long_2addr.d.T_rem_long_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_long_2addr.d.T_rem_long_2addr_5", VerifyError.class);
     }
 
     /**
@@ -178,12 +158,7 @@
      * @title types of arguments - reference, long
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_long_2addr.d.T_rem_long_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_long_2addr.d.T_rem_long_2addr_6", VerifyError.class);
     }
 
     /**
@@ -192,12 +167,7 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.rem_long_2addr.d.T_rem_long_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rem_long_2addr.d.T_rem_long_2addr_3", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/return_object/Test_return_object.java b/tools/vm-tests-tf/src/dot/junit/opcodes/return_object/Test_return_object.java
index 9336829..9f0e639 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/return_object/Test_return_object.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/return_object/Test_return_object.java
@@ -88,13 +88,8 @@
      * @title Method is synchronized but thread is not monitor owner
      */
     public void testE1() {
-        T_return_object_8 t = new T_return_object_8();
-        try {
-            assertTrue(t.run());
-            fail("expected IllegalMonitorStateException");
-        } catch (IllegalMonitorStateException imse) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.return_object.d.T_return_object_8",
+                   IllegalMonitorStateException.class);
     }
 
 
@@ -103,12 +98,7 @@
      * @title method's return type - void
      */
     public void testVFE1() {
-        try {
-            Class.forName("dxc.junit.opcodes.return_object.jm.T_return_object_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.return_object.d.T_return_object_3", VerifyError.class);
     }
 
     /**
@@ -116,12 +106,7 @@
      * @title method's return type - float
      */
     public void testVFE2() {
-        try {
-            Class.forName("dxc.junit.opcodes.return_object.jm.T_return_object_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.return_object.d.T_return_object_4", VerifyError.class);
     }
     
     /**
@@ -129,12 +114,7 @@
      * @title method's return type - long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dxc.junit.opcodes.return_object.jm.T_return_object_16");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.return_object.d.T_return_object_16", VerifyError.class);
     }
 
     /**
@@ -142,12 +122,7 @@
      * @title number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dxc.junit.opcodes.return_object.jm.T_return_object_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.return_object.d.T_return_object_5", VerifyError.class);
     }
 
   
@@ -156,12 +131,7 @@
      * @title types of argument - int
      */
     public void testVFE6() {
-        try {
-            Class.forName("dxc.junit.opcodes.return_object.jm.T_return_object_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.return_object.d.T_return_object_10", VerifyError.class);
     }
 
     /**
@@ -169,12 +139,7 @@
      * @title types of argument - long
      */
     public void testVFE7() {
-        try {
-            Class.forName("dxc.junit.opcodes.return_object.jm.T_return_object_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.return_object.d.T_return_object_11", VerifyError.class);
     }
 
     /**
@@ -186,12 +151,7 @@
         //@uses dot.junit.opcodes.return_object.d.TChild
         //@uses dot.junit.opcodes.return_object.d.TSuper
         //@uses dot.junit.opcodes.return_object.d.TInterface
-        try {
-            Class.forName("dxc.junit.opcodes.return_object.jm.T_return_object_14");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.return_object.d.T_return_object_14", VerifyError.class);
     }
 
     /**
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/return_void/Test_return_void.java b/tools/vm-tests-tf/src/dot/junit/opcodes/return_void/Test_return_void.java
index e5903e3..634ec7a 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/return_void/Test_return_void.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/return_void/Test_return_void.java
@@ -30,33 +30,20 @@
         assertEquals(123456, t.run());
     }
 
-
     /**
      * @title Method is synchronized but thread is not monitor owner
      */
     public void testE1() {
-        T_return_void_3 t = new T_return_void_3();
-        try {
-            assertTrue(t.run());
-            fail("expected IllegalMonitorStateException");
-        } catch (IllegalMonitorStateException imse) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.return_void.d.T_return_void_3",
+                   IllegalMonitorStateException.class);
     }
 
-
-
     /**
      * @constraint B11 
      * @title method's return type - int
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.return_void.d.T_return_void_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.return_void.d.T_return_void_5", VerifyError.class);
     }
 
     /**
@@ -64,12 +51,7 @@
      * @title method's return type - reference
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.return_void.d.T_return_void_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.return_void.d.T_return_void_6", VerifyError.class);
     }
 
     /**
@@ -77,12 +59,7 @@
      * @title method's return type - wide
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.return_void.d.T_return_void_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.return_void.d.T_return_void_7", VerifyError.class);
     }
     
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/return_wide/Test_return_wide.java b/tools/vm-tests-tf/src/dot/junit/opcodes/return_wide/Test_return_wide.java
index c97f0d2..e8afde0 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/return_wide/Test_return_wide.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/return_wide/Test_return_wide.java
@@ -34,13 +34,8 @@
      * @title Method is synchronized but thread is not monitor owner
      */
     public void testE1() {
-        T_return_wide_3 t = new T_return_wide_3();
-        try {
-            assertTrue(t.run());
-            fail("expected IllegalMonitorStateException");
-        } catch (IllegalMonitorStateException imse) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.return_wide.d.T_return_wide_3",
+                   IllegalMonitorStateException.class);
     }
 
 
@@ -49,12 +44,7 @@
      * @title method's return type - int
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.return_wide.d.T_return_wide_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.return_wide.d.T_return_wide_5", VerifyError.class);
     }
 
     /**
@@ -62,12 +52,7 @@
      * @title method's return type - reference
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.return_wide.d.T_return_wide_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.return_wide.d.T_return_wide_6", VerifyError.class);
     }
 
     /**
@@ -75,12 +60,7 @@
      * @title number of registers
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.return_wide.d.T_return_wide_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.return_wide.d.T_return_wide_7", VerifyError.class);
     }
     
     /**
@@ -88,12 +68,7 @@
      * @title return-wide on single-width register
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.return_wide.d.T_return_wide_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.return_wide.d.T_return_wide_8", VerifyError.class);
     }
 
 
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/rsub_int/Test_rsub_int.java b/tools/vm-tests-tf/src/dot/junit/opcodes/rsub_int/Test_rsub_int.java
index 334d79f..ae25759 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/rsub_int/Test_rsub_int.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/rsub_int/Test_rsub_int.java
@@ -192,12 +192,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.rsub_int.d.T_rsub_int_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rsub_int.d.T_rsub_int_8", VerifyError.class);
     }
     
     
@@ -207,12 +202,7 @@
      * @title types of arguments - double, int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.rsub_int.d.T_rsub_int_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rsub_int.d.T_rsub_int_9", VerifyError.class);
     }
     
     /**
@@ -220,12 +210,7 @@
      * @title types of arguments - long, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.rsub_int.d.T_rsub_int_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rsub_int.d.T_rsub_int_10", VerifyError.class);
     }
 
     /**
@@ -233,12 +218,7 @@
      * @title types of arguments - reference, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.rsub_int.d.T_rsub_int_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rsub_int.d.T_rsub_int_11", VerifyError.class);
     }
 
     /**
@@ -247,11 +227,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.rsub_int.d.T_rsub_int_12");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rsub_int.d.T_rsub_int_12", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/rsub_int_lit8/Test_rsub_int_lit8.java b/tools/vm-tests-tf/src/dot/junit/opcodes/rsub_int_lit8/Test_rsub_int_lit8.java
index 1f4b602..4c38f79 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/rsub_int_lit8/Test_rsub_int_lit8.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/rsub_int_lit8/Test_rsub_int_lit8.java
@@ -192,12 +192,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.rsub_int_lit8.d.T_rsub_int_lit8_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rsub_int_lit8.d.T_rsub_int_lit8_8", VerifyError.class);
     }
     
     
@@ -207,12 +202,7 @@
      * @title types of arguments - double, int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.rsub_int_lit8.d.T_rsub_int_lit8_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rsub_int_lit8.d.T_rsub_int_lit8_9", VerifyError.class);
     }
     
     /**
@@ -220,12 +210,7 @@
      * @title types of arguments - long, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.rsub_int_lit8.d.T_rsub_int_lit8_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rsub_int_lit8.d.T_rsub_int_lit8_10", VerifyError.class);
     }
 
     /**
@@ -233,12 +218,7 @@
      * @title types of arguments - reference, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.rsub_int_lit8.d.T_rsub_int_lit8_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rsub_int_lit8.d.T_rsub_int_lit8_11", VerifyError.class);
     }
 
     /**
@@ -247,11 +227,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.rsub_int_lit8.d.T_rsub_int_lit8_12");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.rsub_int_lit8.d.T_rsub_int_lit8_12", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/sget/Test_sget.java b/tools/vm-tests-tf/src/dot/junit/opcodes/sget/Test_sget.java
index 981b19a..f45f7e6 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/sget/Test_sget.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/sget/Test_sget.java
@@ -62,26 +62,14 @@
      * @title attempt to access non-static field
      */
     public void testE1() {
-        T_sget_5 t = new T_sget_5();
-        try {
-            t.run();
-            fail("expected IncompatibleClassChangeError");
-        } catch (IncompatibleClassChangeError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.sget.d.T_sget_5", IncompatibleClassChangeError.class);
     }
 
     /**
      * @title initialization of referenced class throws exception
      */
     public void testE6() {
-        T_sget_9 t = new T_sget_9();
-        try {
-            t.run();
-            fail("expected Error");
-        } catch (Error e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.sget.d.T_sget_9", ExceptionInInitializerError.class);
     }
 
     /**
@@ -89,12 +77,7 @@
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.sget.d.T_sget_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget.d.T_sget_4", VerifyError.class);
     }
 
     /**
@@ -103,12 +86,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.sget.d.T_sget_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget.d.T_sget_3", VerifyError.class);
     }
 
     /**
@@ -118,11 +96,7 @@
      * different type exists
      */
     public void testVFE3() {
-        try {
-            new T_sget_13().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget.d.T_sget_13", NoSuchFieldError.class);
     }
 
     /**
@@ -130,13 +104,8 @@
      * @title Attempt to read inaccessible field.
      */
     public void testVFE4() {
-        //@uses dot.junit.opcodes.sget.d.T_sget_6
         //@uses dot.junit.opcodes.sget.TestStubs
-        try {
-            new T_sget_6().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget.d.T_sget_6", IllegalAccessError.class);
     }
 
     /**
@@ -144,11 +113,7 @@
      * @title Attempt to read field of undefined class.
      */
     public void testVFE5() {
-        try {
-            new T_sget_7().run();
-            fail("expected NoClassDefFoundError");
-        } catch (NoClassDefFoundError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget.d.T_sget_7", NoClassDefFoundError.class);
     }
 
     /**
@@ -156,11 +121,7 @@
      * @title Attempt to read undefined field.
      */
     public void testVFE6() {
-        try {
-            new T_sget_8().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget.d.T_sget_8", NoSuchFieldError.class);
     }
 
     /**
@@ -168,13 +129,8 @@
      * @title Attempt to read superclass' private field from subclass.
      */
     public void testVFE7() {
-        //@uses dot.junit.opcodes.sget.d.T_sget_12
         //@uses dot.junit.opcodes.sget.d.T_sget_1
-        try {
-            new T_sget_12().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget.d.T_sget_12", IllegalAccessError.class);
     }
 
     /**
@@ -182,12 +138,7 @@
      * @title sget shall not work for reference fields
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.sget.d.T_sget_14");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget.d.T_sget_14", VerifyError.class);
     }
 
     /**
@@ -196,12 +147,7 @@
      * @title sget shall not work for short fields
      */
     public void testVFE9() {
-        try {
-            Class.forName("dot.junit.opcodes.sget.d.T_sget_15");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget.d.T_sget_15", VerifyError.class);
     }
 
     /**
@@ -210,12 +156,7 @@
      * @title sget shall not work for boolean fields
      */
     public void testVFE10() {
-        try {
-            Class.forName("dot.junit.opcodes.sget.d.T_sget_16");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget.d.T_sget_16", VerifyError.class);
     }
 
     /**
@@ -224,12 +165,7 @@
      * @title sget shall not work for char fields
      */
     public void testVFE11() {
-        try {
-            Class.forName("dot.junit.opcodes.sget.d.T_sget_17");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget.d.T_sget_17", VerifyError.class);
     }
 
     /**
@@ -238,12 +174,7 @@
      * @title sget shall not work for byte fields
      */
     public void testVFE12() {
-        try {
-            Class.forName("dot.junit.opcodes.sget.d.T_sget_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget.d.T_sget_18", VerifyError.class);
     }
 
     /**
@@ -252,12 +183,7 @@
      * @title sget shall not work for double fields
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.sget.d.T_sget_19");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget.d.T_sget_19", VerifyError.class);
     }
 
     /**
@@ -266,11 +192,6 @@
      * @title sget shall not work for long fields
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.sget.d.T_sget_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget.d.T_sget_20", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/sget_boolean/Test_sget_boolean.java b/tools/vm-tests-tf/src/dot/junit/opcodes/sget_boolean/Test_sget_boolean.java
index ccbeb09..855c8fd 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/sget_boolean/Test_sget_boolean.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/sget_boolean/Test_sget_boolean.java
@@ -54,42 +54,24 @@
      * @title attempt to access non-static field
      */
     public void testE1() {
-
-        T_sget_boolean_5 t = new T_sget_boolean_5();
-        try {
-            t.run();
-            fail("expected IncompatibleClassChangeError");
-        } catch (IncompatibleClassChangeError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.sget_boolean.d.T_sget_boolean_5",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
      * @title initialization of referenced class throws exception
      */
     public void testE6() {
-        T_sget_boolean_9 t = new T_sget_boolean_9();
-        try {
-            t.run();
-            fail("expected Error");
-        } catch (Error e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.sget_boolean.d.T_sget_boolean_9",
+                   ExceptionInInitializerError.class);
     }
 
-
-
     /**
      * @constraint A12
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_boolean.d.T_sget_boolean_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_boolean.d.T_sget_boolean_4", VerifyError.class);
     }
 
     /**
@@ -98,12 +80,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_boolean.d.T_sget_boolean_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_boolean.d.T_sget_boolean_3", VerifyError.class);
     }
 
     /**
@@ -113,11 +90,7 @@
      * different type exists
      */
     public void testVFE3() {
-        try {
-            new T_sget_boolean_13().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_boolean.d.T_sget_boolean_13", NoSuchFieldError.class);
     }
 
     /**
@@ -125,12 +98,8 @@
      * @title Attempt to read inaccessible field.
      */
     public void testVFE4() {
-        //@uses dot.junit.opcodes.sget_boolean.d.T_sget_boolean_6
         //@uses dot.junit.opcodes.sget_boolean.TestStubs
-        try {
-            new T_sget_boolean_6().run();
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_boolean.d.T_sget_boolean_6", IllegalAccessError.class);
     }
 
     /**
@@ -138,11 +107,7 @@
      * @title Attempt to read field of undefined class.
      */
     public void testVFE5() {
-        try {
-            new T_sget_boolean_7().run();
-            fail("expected NoClassDefFoundError");
-        } catch (NoClassDefFoundError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_boolean.d.T_sget_boolean_7", NoClassDefFoundError.class);
     }
 
     /**
@@ -150,11 +115,7 @@
      * @title Attempt to read undefined field.
      */
     public void testVFE6() {
-        try {
-            new T_sget_boolean_8().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_boolean.d.T_sget_boolean_8", NoSuchFieldError.class);
     }
 
     /**
@@ -162,13 +123,8 @@
      * @title Attempt to read superclass' private field from subclass.
      */
     public void testVFE7() {
-        //@uses dot.junit.opcodes.sget_boolean.d.T_sget_boolean_12
         //@uses dot.junit.opcodes.sget_boolean.d.T_sget_boolean_1
-        try {
-            new T_sget_boolean_12().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_boolean.d.T_sget_boolean_12", IllegalAccessError.class);
     }
 
     /**
@@ -176,12 +132,7 @@
      * @title sget_boolean shall not work for reference fields
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_boolean.d.T_sget_boolean_14");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_boolean.d.T_sget_boolean_14", VerifyError.class);
     }
 
     /**
@@ -190,12 +141,7 @@
      * @title sget_boolean shall not work for short fields
      */
     public void testVFE9() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_boolean.d.T_sget_boolean_15");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_boolean.d.T_sget_boolean_15", VerifyError.class);
     }
 
     /**
@@ -204,12 +150,7 @@
      * @title sget_boolean shall not work for int fields
      */
     public void testVFE10() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_boolean.d.T_sget_boolean_16");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_boolean.d.T_sget_boolean_16", VerifyError.class);
     }
 
     /**
@@ -218,12 +159,7 @@
      * @title sget_boolean shall not work for char fields
      */
     public void testVFE11() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_boolean.d.T_sget_boolean_17");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_boolean.d.T_sget_boolean_17", VerifyError.class);
     }
 
     /**
@@ -232,12 +168,7 @@
      * @title sget_boolean shall not work for byte fields
      */
     public void testVFE12() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_boolean.d.T_sget_boolean_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_boolean.d.T_sget_boolean_18", VerifyError.class);
     }
 
     /**
@@ -246,12 +177,7 @@
      * @title sget_boolean shall not work for double fields
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_boolean.d.T_sget_boolean_19");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_boolean.d.T_sget_boolean_19", VerifyError.class);
     }
 
     /**
@@ -260,11 +186,6 @@
      * @title sget_boolean shall not work for long fields
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_boolean.d.T_sget_boolean_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_boolean.d.T_sget_boolean_20", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/sget_byte/Test_sget_byte.java b/tools/vm-tests-tf/src/dot/junit/opcodes/sget_byte/Test_sget_byte.java
index 9a19f98..9cf4306 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/sget_byte/Test_sget_byte.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/sget_byte/Test_sget_byte.java
@@ -54,27 +54,16 @@
      * @title attempt to access non-static field
      */
     public void testE1() {
-
-        T_sget_byte_5 t = new T_sget_byte_5();
-        try {
-            t.run();
-            fail("expected IncompatibleClassChangeError");
-        } catch (IncompatibleClassChangeError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.sget_byte.d.T_sget_byte_5",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
      * @title initialization of referenced class throws exception
      */
     public void testE6() {
-        T_sget_byte_9 t = new T_sget_byte_9();
-        try {
-            t.run();
-            fail("expected Error");
-        } catch (Error e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.sget_byte.d.T_sget_byte_9",
+                   ExceptionInInitializerError.class);
     }
 
 
@@ -84,12 +73,7 @@
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_byte.d.T_sget_byte_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_byte.d.T_sget_byte_4", VerifyError.class);
     }
 
     /**
@@ -98,12 +82,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_byte.d.T_sget_byte_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_byte.d.T_sget_byte_3", VerifyError.class);
     }
 
     /**
@@ -113,11 +92,7 @@
      * different type exists
      */
     public void testVFE3() {
-        try {
-            new T_sget_byte_13().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_byte.d.T_sget_byte_13", NoSuchFieldError.class);
     }
 
     /**
@@ -125,13 +100,8 @@
      * @title Attempt to read inaccessible field.
      */
     public void testVFE4() {
-        //@uses dot.junit.opcodes.sget_byte.d.T_sget_byte_6
         //@uses dot.junit.opcodes.sget_byte.TestStubs
-        try {
-            new T_sget_byte_6().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_byte.d.T_sget_byte_6", IllegalAccessError.class);
     }
 
     /**
@@ -139,11 +109,7 @@
      * @title Attempt to read field of undefined class.
      */
     public void testVFE5() {
-        try {
-            new T_sget_byte_7().run();
-            fail("expected NoClassDefFoundError");
-        } catch (NoClassDefFoundError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_byte.d.T_sget_byte_7", NoClassDefFoundError.class);
     }
 
     /**
@@ -151,11 +117,7 @@
      * @title Attempt to read undefined field.
      */
     public void testVFE6() {
-        try {
-            new T_sget_byte_8().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_byte.d.T_sget_byte_8", NoSuchFieldError.class);
     }
 
     /**
@@ -163,13 +125,8 @@
      * @title Attempt to read superclass' private field from subclass.
      */
     public void testVFE7() {
-        //@uses dot.junit.opcodes.sget_byte.d.T_sget_byte_12
         //@uses dot.junit.opcodes.sget_byte.d.T_sget_byte_1
-        try {
-            new T_sget_byte_12().run();
-            fail("expected a verification exception");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_byte.d.T_sget_byte_12", IllegalAccessError.class);
     }
 
     /**
@@ -177,12 +134,7 @@
      * @title sget_byte shall not work for reference fields
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_byte.d.T_sget_byte_14");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_byte.d.T_sget_byte_14", VerifyError.class);
     }
 
     /**
@@ -191,12 +143,7 @@
      * @title sget_byte shall not work for short fields
      */
     public void testVFE9() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_byte.d.T_sget_byte_15");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_byte.d.T_sget_byte_15", VerifyError.class);
     }
 
     /**
@@ -205,12 +152,7 @@
      * @title sget_byte shall not work for int fields
      */
     public void testVFE10() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_byte.d.T_sget_byte_16");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_byte.d.T_sget_byte_16", VerifyError.class);
     }
 
     /**
@@ -219,12 +161,7 @@
      * @title sget_byte shall not work for char fields
      */
     public void testVFE11() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_byte.d.T_sget_byte_17");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_byte.d.T_sget_byte_17", VerifyError.class);
     }
 
     /**
@@ -233,12 +170,7 @@
      * @title sget_byte shall not work for boolean fields
      */
     public void testVFE12() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_byte.d.T_sget_byte_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_byte.d.T_sget_byte_18", VerifyError.class);
     }
 
     /**
@@ -247,12 +179,7 @@
      * @title sget_byte shall not work for double fields
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_byte.d.T_sget_byte_19");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_byte.d.T_sget_byte_19", VerifyError.class);
     }
 
     /**
@@ -261,11 +188,6 @@
      * @title sget_byte shall not work for long fields
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_byte.d.T_sget_byte_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_byte.d.T_sget_byte_20", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/sget_char/Test_sget_char.java b/tools/vm-tests-tf/src/dot/junit/opcodes/sget_char/Test_sget_char.java
index 10324a5..babc8f986 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/sget_char/Test_sget_char.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/sget_char/Test_sget_char.java
@@ -54,27 +54,16 @@
      * @title attempt to access non-static field
      */
     public void testE1() {
-
-        T_sget_char_5 t = new T_sget_char_5();
-        try {
-            t.run();
-            fail("expected IncompatibleClassChangeError");
-        } catch (IncompatibleClassChangeError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.sget_char.d.T_sget_char_5",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
      * @title initialization of referenced class throws exception
      */
     public void testE6() {
-        T_sget_char_9 t = new T_sget_char_9();
-        try {
-            t.run();
-            fail("expected Error");
-        } catch (Error e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.sget_char.d.T_sget_char_9",
+                   ExceptionInInitializerError.class);
     }
 
 
@@ -84,12 +73,7 @@
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_char.d.T_sget_char_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_char.d.T_sget_char_4", VerifyError.class);
     }
 
     /**
@@ -98,12 +82,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_char.d.T_sget_char_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_char.d.T_sget_char_3", VerifyError.class);
     }
 
     /**
@@ -113,11 +92,7 @@
      * different type exists
      */
     public void testVFE3() {
-        try {
-            new T_sget_char_13().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_char.d.T_sget_char_13", NoSuchFieldError.class);
     }
 
     /**
@@ -125,13 +100,8 @@
      * @title Attempt to read inaccessible field.
      */
     public void testVFE4() {
-        //@uses dot.junit.opcodes.sget_char.d.T_sget_char_6
         //@uses dot.junit.opcodes.sget_char.TestStubs
-        try {
-            new T_sget_char_6().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_char.d.T_sget_char_6", IllegalAccessError.class);
     }
 
     /**
@@ -139,11 +109,7 @@
      * @title Attempt to read field of undefined class.
      */
     public void testVFE5() {
-        try {
-            new T_sget_char_7().run();
-            fail("expected NoClassDefFoundError");
-        } catch (NoClassDefFoundError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_char.d.T_sget_char_7", NoClassDefFoundError.class);
     }
 
     /**
@@ -151,11 +117,7 @@
      * @title Attempt to read undefined field.
      */
     public void testVFE6() {
-        try {
-            new T_sget_char_8().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_char.d.T_sget_char_8", NoSuchFieldError.class);
     }
 
     /**
@@ -163,13 +125,8 @@
      * @title Attempt to read superclass' private field from subclass.
      */
     public void testVFE7() {
-        //@uses dot.junit.opcodes.sget_char.d.T_sget_char_12
         //@uses dot.junit.opcodes.sget_char.d.T_sget_char_1
-        try {
-            new T_sget_char_12().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_char.d.T_sget_char_12", IllegalAccessError.class);
     }
 
     /**
@@ -177,12 +134,7 @@
      * @title sget_char shall not work for reference fields
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_char.d.T_sget_char_14");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_char.d.T_sget_char_14", VerifyError.class);
     }
 
     /**
@@ -191,12 +143,7 @@
      * @title sget_char shall not work for short fields
      */
     public void testVFE9() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_char.d.T_sget_char_15");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_char.d.T_sget_char_15", VerifyError.class);
     }
 
     /**
@@ -205,12 +152,7 @@
      * @title sget_char shall not work for int fields
      */
     public void testVFE10() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_char.d.T_sget_char_16");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_char.d.T_sget_char_16", VerifyError.class);
     }
 
     /**
@@ -219,12 +161,7 @@
      * @title sget_char shall not work for byte fields
      */
     public void testVFE11() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_char.d.T_sget_char_17");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_char.d.T_sget_char_17", VerifyError.class);
     }
 
     /**
@@ -233,12 +170,7 @@
      * @title sget_char shall not work for boolean fields
      */
     public void testVFE12() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_char.d.T_sget_char_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_char.d.T_sget_char_18", VerifyError.class);
     }
 
     /**
@@ -247,12 +179,7 @@
      * @title sget_char shall not work for double fields
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_char.d.T_sget_char_19");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_char.d.T_sget_char_19", VerifyError.class);
     }
 
     /**
@@ -261,11 +188,6 @@
      * @title sget_char shall not work for long fields
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_char.d.T_sget_char_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_char.d.T_sget_char_20", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/sget_object/Test_sget_object.java b/tools/vm-tests-tf/src/dot/junit/opcodes/sget_object/Test_sget_object.java
index 88aa4cb..db118e5 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/sget_object/Test_sget_object.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/sget_object/Test_sget_object.java
@@ -55,27 +55,16 @@
      * @title attempt to access non-static field
      */
     public void testE1() {
-
-        T_sget_object_5 t = new T_sget_object_5();
-        try {
-            t.run();
-            fail("expected IncompatibleClassChangeError");
-        } catch (IncompatibleClassChangeError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.sget_object.d.T_sget_object_5",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
      * @title initialization of referenced class throws exception
      */
     public void testE6() {
-        T_sget_object_9 t = new T_sget_object_9();
-        try {
-            t.run();
-            fail("expected Error");
-        } catch (Error e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.sget_object.d.T_sget_object_9",
+                   ExceptionInInitializerError.class);
     }
 
 
@@ -85,12 +74,7 @@
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_object.d.T_sget_object_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_object.d.T_sget_object_4", VerifyError.class);
     }
 
     /**
@@ -99,12 +83,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_object.d.T_sget_object_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_object.d.T_sget_object_3", VerifyError.class);
     }
 
     /**
@@ -114,11 +93,7 @@
      * different type exists
      */
     public void testVFE3() {
-        try {
-            new T_sget_object_13().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_object.d.T_sget_object_13", NoSuchFieldError.class);
     }
 
     /**
@@ -126,13 +101,8 @@
      * @title Attempt to read inaccessible field.
      */
     public void testVFE4() {
-        //@uses dot.junit.opcodes.sget_object.d.T_sget_object_6
         //@uses dot.junit.opcodes.sget_object.TestStubs
-        try {
-            new T_sget_object_6().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_object.d.T_sget_object_6", IllegalAccessError.class);
     }
 
     /**
@@ -140,11 +110,7 @@
      * @title Attempt to read field of undefined class.
      */
     public void testVFE5() {
-        try {
-            new T_sget_object_7().run();
-            fail("expected NoClassDefFoundError");
-        } catch (NoClassDefFoundError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_object.d.T_sget_object_7", NoClassDefFoundError.class);
     }
 
     /**
@@ -152,11 +118,7 @@
      * @title Attempt to read undefined field.
      */
     public void testVFE6() {
-        try {
-            new T_sget_object_8().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_object.d.T_sget_object_8", NoSuchFieldError.class);
     }
 
     /**
@@ -164,13 +126,8 @@
      * @title Attempt to read superclass' private field from subclass.
      */
     public void testVFE7() {
-        //@uses dot.junit.opcodes.sget_object.d.T_sget_object_12
         //@uses dot.junit.opcodes.sget_object.d.T_sget_object_1
-        try {
-            new T_sget_object_12().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_object.d.T_sget_object_12", IllegalAccessError.class);
     }
 
     /**
@@ -178,12 +135,7 @@
      * @title sget_object shall not work for short fields
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_object.d.T_sget_object_14");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_object.d.T_sget_object_14", VerifyError.class);
     }
 
     /**
@@ -192,12 +144,7 @@
      * @title sget_object shall not work for char fields
      */
     public void testVFE9() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_object.d.T_sget_object_15");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_object.d.T_sget_object_15", VerifyError.class);
     }
 
     /**
@@ -206,12 +153,7 @@
      * @title sget_object shall not work for int fields
      */
     public void testVFE10() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_object.d.T_sget_object_16");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_object.d.T_sget_object_16", VerifyError.class);
     }
 
     /**
@@ -220,12 +162,7 @@
      * @title sget_object shall not work for byte fields
      */
     public void testVFE11() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_object.d.T_sget_object_17");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_object.d.T_sget_object_17", VerifyError.class);
     }
 
     /**
@@ -234,12 +171,7 @@
      * @title sget_object shall not work for boolean fields
      */
     public void testVFE12() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_object.d.T_sget_object_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_object.d.T_sget_object_18", VerifyError.class);
     }
 
     /**
@@ -248,12 +180,7 @@
      * @title sget_object shall not work for double fields
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_object.d.T_sget_object_19");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_object.d.T_sget_object_19", VerifyError.class);
     }
 
     /**
@@ -262,12 +189,7 @@
      * @title sget_object shall not work for long fields
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_object.d.T_sget_object_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_object.d.T_sget_object_20", VerifyError.class);
     }
 
     /**
@@ -276,10 +198,6 @@
      * @title only field of different type exists)
      */
     public void testVFE15() {
-        try {
-            new T_sget_object_21().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_object.d.T_sget_object_21", NoSuchFieldError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/sget_short/Test_sget_short.java b/tools/vm-tests-tf/src/dot/junit/opcodes/sget_short/Test_sget_short.java
index b38ef29..fa7c3c4 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/sget_short/Test_sget_short.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/sget_short/Test_sget_short.java
@@ -54,27 +54,16 @@
      * @title attempt to access non-static field
      */
     public void testE1() {
-
-        T_sget_short_5 t = new T_sget_short_5();
-        try {
-            t.run();
-            fail("expected IncompatibleClassChangeError");
-        } catch (IncompatibleClassChangeError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.sget_short.d.T_sget_short_5",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
      * @title initialization of referenced class throws exception
      */
     public void testE6() {
-        T_sget_short_9 t = new T_sget_short_9();
-        try {
-            t.run();
-            fail("expected Error");
-        } catch (Error e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.sget_short.d.T_sget_short_9",
+                   ExceptionInInitializerError.class);
     }
 
 
@@ -84,12 +73,7 @@
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_short.d.T_sget_short_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_short.d.T_sget_short_4", VerifyError.class);
     }
 
     /**
@@ -98,12 +82,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_short.d.T_sget_short_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_short.d.T_sget_short_3", VerifyError.class);
     }
 
     /**
@@ -113,11 +92,7 @@
      * different type exists
      */
     public void testVFE3() {
-        try {
-            new T_sget_short_13().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_short.d.T_sget_short_13", NoSuchFieldError.class);
     }
 
     /**
@@ -125,13 +100,8 @@
      * @title Attempt to read inaccessible field.
      */
     public void testVFE4() {
-        //@uses dot.junit.opcodes.sget_short.d.T_sget_short_6
         //@uses dot.junit.opcodes.sget_short.TestStubs
-        try {
-            new T_sget_short_6().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_short.d.T_sget_short_6", IllegalAccessError.class);
     }
 
     /**
@@ -139,11 +109,7 @@
      * @title Attempt to read field of undefined class.
      */
     public void testVFE5() {
-        try {
-            new T_sget_short_7().run();
-            fail("expected NoClassDefFoundError");
-        } catch (NoClassDefFoundError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_short.d.T_sget_short_7", NoClassDefFoundError.class);
     }
 
     /**
@@ -151,11 +117,7 @@
      * @title Attempt to read undefined field.
      */
     public void testVFE6() {
-        try {
-            new T_sget_short_8().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_short.d.T_sget_short_8", NoSuchFieldError.class);
     }
 
     /**
@@ -163,13 +125,8 @@
      * @title Attempt to read superclass' private field from subclass.
      */
     public void testVFE7() {
-        //@uses dot.junit.opcodes.sget_short.d.T_sget_short_12
         //@uses dot.junit.opcodes.sget_short.d.T_sget_short_1
-        try {
-            new T_sget_short_12().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_short.d.T_sget_short_12", IllegalAccessError.class);
     }
 
     /**
@@ -177,12 +134,7 @@
      * @title sget_short shall not work for reference fields
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_short.d.T_sget_short_14");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_short.d.T_sget_short_14", VerifyError.class);
     }
 
     /**
@@ -191,12 +143,7 @@
      * @title sget_short shall not work for char fields
      */
     public void testVFE9() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_short.d.T_sget_short_15");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_short.d.T_sget_short_15", VerifyError.class);
     }
 
     /**
@@ -205,12 +152,7 @@
      * @title sget_short shall not work for int fields
      */
     public void testVFE10() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_short.d.T_sget_short_16");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_short.d.T_sget_short_16", VerifyError.class);
     }
 
     /**
@@ -219,12 +161,7 @@
      * @title sget_short shall not work for byte fields
      */
     public void testVFE11() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_short.d.T_sget_short_17");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_short.d.T_sget_short_17", VerifyError.class);
     }
 
     /**
@@ -233,12 +170,7 @@
      * @title sget_short shall not work for boolean fields
      */
     public void testVFE12() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_short.d.T_sget_short_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_short.d.T_sget_short_18", VerifyError.class);
     }
 
     /**
@@ -247,12 +179,7 @@
      * @title sget_short shall not work for double fields
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_short.d.T_sget_short_19");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_short.d.T_sget_short_19", VerifyError.class);
     }
 
     /**
@@ -261,11 +188,6 @@
      * @title sget_short shall not work for long fields
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_short.d.T_sget_short_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_short.d.T_sget_short_20", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/sget_wide/Test_sget_wide.java b/tools/vm-tests-tf/src/dot/junit/opcodes/sget_wide/Test_sget_wide.java
index 8ecbeb7..bcf7497 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/sget_wide/Test_sget_wide.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/sget_wide/Test_sget_wide.java
@@ -62,28 +62,16 @@
      * @title attempt to access non-static field
      */
     public void testE1() {
-
-        T_sget_wide_5 t = new T_sget_wide_5();
-        try {
-            t.run();
-            fail("expected IncompatibleClassChangeError");
-        } catch (IncompatibleClassChangeError e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.sget_wide.d.T_sget_wide_5",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
      * @title initialization of referenced class throws exception
      */
     public void testE6() {
-
-        T_sget_wide_9 t = new T_sget_wide_9();
-        try {
-            t.run();
-            fail("expected Error");
-        } catch (Error e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.sget_wide.d.T_sget_wide_9",
+                   ExceptionInInitializerError.class);
     }
 
 
@@ -93,12 +81,7 @@
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_wide.d.T_sget_wide_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_wide.d.T_sget_wide_4", VerifyError.class);
     }
 
     /**
@@ -107,12 +90,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_wide.d.T_sget_wide_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_wide.d.T_sget_wide_3", VerifyError.class);
     }
 
     /**
@@ -122,11 +100,7 @@
      * different type exists
      */
     public void testVFE3() {
-        try {
-            new T_sget_wide_13().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_wide.d.T_sget_wide_13", NoSuchFieldError.class);
     }
 
     /**
@@ -134,13 +108,8 @@
      * @title Attempt to read inaccessible field.
      */
     public void testVFE4() {
-        //@uses dot.junit.opcodes.sget_wide.d.T_sget_wide_6
         //@uses dot.junit.opcodes.sget_wide.TestStubs
-        try {
-            new T_sget_wide_6().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_wide.d.T_sget_wide_6", IllegalAccessError.class);
     }
 
     /**
@@ -148,11 +117,7 @@
      * @title Attempt to read field of undefined class.
      */
     public void testVFE5() {
-        try {
-            new T_sget_wide_7().run();
-            fail("expected NoClassDefFoundError");
-        } catch (NoClassDefFoundError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_wide.d.T_sget_wide_7", NoClassDefFoundError.class);
     }
 
     /**
@@ -160,11 +125,7 @@
      * @title Attempt to read undefined field.
      */
     public void testVFE6() {
-        try {
-            new T_sget_wide_8().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_wide.d.T_sget_wide_8", NoSuchFieldError.class);
     }
 
     /**
@@ -172,13 +133,8 @@
      * @title Attempt to read superclass' private field from subclass.
      */
     public void testVFE7() {
-        //@uses dot.junit.opcodes.sget_wide.d.T_sget_wide_12
         //@uses dot.junit.opcodes.sget_wide.d.T_sget_wide_1
-        try {
-            new T_sget_wide_12().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sget_wide.d.T_sget_wide_12", IllegalAccessError.class);
     }
 
     /**
@@ -186,12 +142,7 @@
      * @title sget-wide shall not work for reference fields
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_wide.d.T_sget_wide_14");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_wide.d.T_sget_wide_14", VerifyError.class);
     }
 
     /**
@@ -200,12 +151,7 @@
      * @title sget-wide shall not work for short fields
      */
     public void testVFE9() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_wide.d.T_sget_wide_15");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_wide.d.T_sget_wide_15", VerifyError.class);
     }
 
     /**
@@ -214,12 +160,7 @@
      * @title sget-wide shall not work for boolean fields
      */
     public void testVFE10() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_wide.d.T_sget_wide_16");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_wide.d.T_sget_wide_16", VerifyError.class);
     }
 
     /**
@@ -228,12 +169,7 @@
      * @title sget-wide shall not work for char fields
      */
     public void testVFE11() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_wide.d.T_sget_wide_17");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_wide.d.T_sget_wide_17", VerifyError.class);
     }
 
     /**
@@ -242,12 +178,7 @@
      * @title sget-wide shall not work for byte fields
      */
     public void testVFE12() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_wide.d.T_sget_wide_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_wide.d.T_sget_wide_18", VerifyError.class);
     }
 
     /**
@@ -256,12 +187,7 @@
      * @title sget-wide shall not work for float fields
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_wide.d.T_sget_wide_19");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_wide.d.T_sget_wide_19", VerifyError.class);
     }
 
     /**
@@ -270,11 +196,6 @@
      * @title sget-wide shall not work for int fields
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.sget_wide.d.T_sget_wide_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sget_wide.d.T_sget_wide_20", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/shl_int/Test_shl_int.java b/tools/vm-tests-tf/src/dot/junit/opcodes/shl_int/Test_shl_int.java
index 55b7cb9..07b0ba9 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/shl_int/Test_shl_int.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/shl_int/Test_shl_int.java
@@ -85,12 +85,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_int.d.T_shl_int_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_int.d.T_shl_int_2", VerifyError.class);
     }
 
     
@@ -100,12 +95,7 @@
      * @title types of arguments - double & int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_int.d.T_shl_int_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_int.d.T_shl_int_3", VerifyError.class);
     }
 
     /**
@@ -113,12 +103,7 @@
      * @title types of arguments - long & int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_int.d.T_shl_int_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_int.d.T_shl_int_4", VerifyError.class);
     }
 
     /**
@@ -126,12 +111,7 @@
      * @title types of arguments - reference & int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_int.d.T_shl_int_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_int.d.T_shl_int_5", VerifyError.class);
     }
 
     /**
@@ -140,12 +120,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_int.d.T_shl_int_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_int.d.T_shl_int_6", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/shl_int_2addr/Test_shl_int_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/shl_int_2addr/Test_shl_int_2addr.java
index f44959a..ff46973 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/shl_int_2addr/Test_shl_int_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/shl_int_2addr/Test_shl_int_2addr.java
@@ -85,12 +85,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_int_2addr.d.T_shl_int_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_int_2addr.d.T_shl_int_2addr_2", VerifyError.class);
     }
 
     
@@ -100,12 +95,7 @@
      * @title types of arguments - double & int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_int_2addr.d.T_shl_int_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_int_2addr.d.T_shl_int_2addr_3", VerifyError.class);
     }
 
     /**
@@ -113,12 +103,7 @@
      * @title types of arguments - long & int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_int_2addr.d.T_shl_int_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_int_2addr.d.T_shl_int_2addr_4", VerifyError.class);
     }
 
     /**
@@ -126,12 +111,7 @@
      * @title types of arguments - reference & int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_int_2addr.d.T_shl_int_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_int_2addr.d.T_shl_int_2addr_5", VerifyError.class);
     }
 
     /**
@@ -140,12 +120,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_int_2addr.d.T_shl_int_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_int_2addr.d.T_shl_int_2addr_6", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/shl_int_lit8/Test_shl_int_lit8.java b/tools/vm-tests-tf/src/dot/junit/opcodes/shl_int_lit8/Test_shl_int_lit8.java
index 47e10bb..5cfcdc8 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/shl_int_lit8/Test_shl_int_lit8.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/shl_int_lit8/Test_shl_int_lit8.java
@@ -90,12 +90,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_int_lit8.d.T_shl_int_lit8_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_int_lit8.d.T_shl_int_lit8_7", VerifyError.class);
     }
 
     
@@ -105,12 +100,7 @@
      * @title types of arguments - double & int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_int_lit8.d.T_shl_int_lit8_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_int_lit8.d.T_shl_int_lit8_8", VerifyError.class);
     }
 
     /**
@@ -118,12 +108,7 @@
      * @title types of arguments - long & int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_int_lit8.d.T_shl_int_lit8_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_int_lit8.d.T_shl_int_lit8_9", VerifyError.class);
     }
 
     /**
@@ -131,12 +116,7 @@
      * @title types of arguments - reference & int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_int_lit8.d.T_shl_int_lit8_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_int_lit8.d.T_shl_int_lit8_10", VerifyError.class);
     }
 
     /**
@@ -145,11 +125,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_int_lit8.d.T_shl_int_lit8_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_int_lit8.d.T_shl_int_lit8_6", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/shl_long/Test_shl_long.java b/tools/vm-tests-tf/src/dot/junit/opcodes/shl_long/Test_shl_long.java
index 7e29009..d51b29b 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/shl_long/Test_shl_long.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/shl_long/Test_shl_long.java
@@ -86,12 +86,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_long.d.T_shl_long_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_long.d.T_shl_long_2", VerifyError.class);
     }
 
     
@@ -101,12 +96,7 @@
      * @title types of arguments - long & double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_long.d.T_shl_long_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_long.d.T_shl_long_3", VerifyError.class);
     }
 
     /**
@@ -114,12 +104,7 @@
      * @title types of arguments - int & int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_long.d.T_shl_long_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_long.d.T_shl_long_4", VerifyError.class);
     }
 
     /**
@@ -127,12 +112,7 @@
      * @title types of arguments - float & int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_long.d.T_shl_long_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_long.d.T_shl_long_5", VerifyError.class);
     }
 
     /**
@@ -140,12 +120,7 @@
      * @title  types of arguments - reference & int
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_long.d.T_shl_long_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_long.d.T_shl_long_6", VerifyError.class);
     }
 
     /**
@@ -154,12 +129,7 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_long.d.T_shl_long_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_long.d.T_shl_long_7", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/shl_long_2addr/Test_shl_long_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/shl_long_2addr/Test_shl_long_2addr.java
index 0dbe218..b065c35 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/shl_long_2addr/Test_shl_long_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/shl_long_2addr/Test_shl_long_2addr.java
@@ -86,12 +86,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_long_2addr.d.T_shl_long_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_long_2addr.d.T_shl_long_2addr_2", VerifyError.class);
     }
 
     
@@ -101,12 +96,7 @@
      * @title types of arguments - long, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_long_2addr.d.T_shl_long_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_long_2addr.d.T_shl_long_2addr_3", VerifyError.class);
     }
 
     /**
@@ -114,12 +104,7 @@
      * @title types of arguments - int, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_long_2addr.d.T_shl_long_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_long_2addr.d.T_shl_long_2addr_4", VerifyError.class);
     }
 
     /**
@@ -127,12 +112,7 @@
      * @title types of arguments - float, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_long_2addr.d.T_shl_long_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_long_2addr.d.T_shl_long_2addr_5", VerifyError.class);
     }
 
     /**
@@ -140,12 +120,7 @@
      * @title types of arguments - reference, int
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_long_2addr.d.T_shl_long_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_long_2addr.d.T_shl_long_2addr_6", VerifyError.class);
     }
 
     /**
@@ -154,12 +129,7 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.shl_long_2addr.d.T_shl_long_2addr_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shl_long_2addr.d.T_shl_long_2addr_7", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/shr_int/Test_shr_int.java b/tools/vm-tests-tf/src/dot/junit/opcodes/shr_int/Test_shr_int.java
index f7f1ae8..1f056e3 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/shr_int/Test_shr_int.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/shr_int/Test_shr_int.java
@@ -86,12 +86,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_int.d.T_shr_int_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_int.d.T_shr_int_2", VerifyError.class);
     }
 
     
@@ -101,12 +96,7 @@
      * @title types of arguments - double, int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_int.d.T_shr_int_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_int.d.T_shr_int_3", VerifyError.class);
     }
 
     /**
@@ -114,12 +104,7 @@
      * @title types of arguments - long, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_int.d.T_shr_int_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_int.d.T_shr_int_4", VerifyError.class);
     }
 
     /**
@@ -127,12 +112,7 @@
      * @title types of arguments - reference, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_int.d.T_shr_int_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_int.d.T_shr_int_5", VerifyError.class);
     }
 
     /**
@@ -141,12 +121,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_int.d.T_shr_int_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_int.d.T_shr_int_6", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/shr_int_2addr/Test_shr_int_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/shr_int_2addr/Test_shr_int_2addr.java
index 5b31961..2ace377 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/shr_int_2addr/Test_shr_int_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/shr_int_2addr/Test_shr_int_2addr.java
@@ -86,12 +86,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_int_2addr.d.T_shr_int_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_int_2addr.d.T_shr_int_2addr_2", VerifyError.class);
     }
 
     
@@ -101,12 +96,7 @@
      * @title types of arguments - double, int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_int_2addr.d.T_shr_int_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_int_2addr.d.T_shr_int_2addr_3", VerifyError.class);
     }
 
     /**
@@ -114,12 +104,7 @@
      * @title types of arguments - long, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_int_2addr.d.T_shr_int_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_int_2addr.d.T_shr_int_2addr_4", VerifyError.class);
     }
 
     /**
@@ -127,12 +112,7 @@
      * @title types of arguments - reference, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_int_2addr.d.T_shr_int_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_int_2addr.d.T_shr_int_2addr_5", VerifyError.class);
     }
 
     /**
@@ -141,12 +121,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_int_2addr.d.T_shr_int_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_int_2addr.d.T_shr_int_2addr_6", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/shr_int_lit8/Test_shr_int_lit8.java b/tools/vm-tests-tf/src/dot/junit/opcodes/shr_int_lit8/Test_shr_int_lit8.java
index 3c86bbb..cb90cbe 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/shr_int_lit8/Test_shr_int_lit8.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/shr_int_lit8/Test_shr_int_lit8.java
@@ -89,12 +89,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_int_lit8.d.T_shr_int_lit8_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_int_lit8.d.T_shr_int_lit8_7", VerifyError.class);
     }
 
     
@@ -104,12 +99,7 @@
      * @title types of arguments - double, int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_int_lit8.d.T_shr_int_lit8_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_int_lit8.d.T_shr_int_lit8_8", VerifyError.class);
     }
 
     /**
@@ -117,12 +107,7 @@
      * @title types of arguments - long, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_int_lit8.d.T_shr_int_lit8_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_int_lit8.d.T_shr_int_lit8_9", VerifyError.class);
     }
 
     /**
@@ -130,12 +115,7 @@
      * @title types of arguments - reference, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_int_lit8.d.T_shr_int_lit8_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_int_lit8.d.T_shr_int_lit8_10", VerifyError.class);
     }
 
     /**
@@ -144,11 +124,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_int_lit8.d.T_shr_int_lit8_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_int_lit8.d.T_shr_int_lit8_6", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/shr_long/Test_shr_long.java b/tools/vm-tests-tf/src/dot/junit/opcodes/shr_long/Test_shr_long.java
index 42afd24..b6c5fc3 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/shr_long/Test_shr_long.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/shr_long/Test_shr_long.java
@@ -86,12 +86,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_long.d.T_shr_long_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_long.d.T_shr_long_2", VerifyError.class);
     }
 
     
@@ -101,12 +96,7 @@
      * @title types of arguments - long, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_long.d.T_shr_long_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_long.d.T_shr_long_3", VerifyError.class);
     }
 
     /**
@@ -114,12 +104,7 @@
      * @title types of arguments - int, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_long.d.T_shr_long_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_long.d.T_shr_long_4", VerifyError.class);
     }
 
     /**
@@ -127,12 +112,7 @@
      * @title types of arguments - float, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_long.d.T_shr_long_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_long.d.T_shr_long_5", VerifyError.class);
     }
 
     /**
@@ -140,12 +120,7 @@
      * @title types of arguments - reference, int
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_long.d.T_shr_long_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_long.d.T_shr_long_6", VerifyError.class);
     }
 
     /**
@@ -154,11 +129,6 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_long.d.T_shr_long_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_long.d.T_shr_long_7", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/shr_long_2addr/Test_shr_long_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/shr_long_2addr/Test_shr_long_2addr.java
index bb3c2ad..74548cf 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/shr_long_2addr/Test_shr_long_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/shr_long_2addr/Test_shr_long_2addr.java
@@ -86,12 +86,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_long_2addr.d.T_shr_long_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_long_2addr.d.T_shr_long_2addr_2", VerifyError.class);
     }
 
     
@@ -101,12 +96,7 @@
      * @title types of arguments - long, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_long_2addr.d.T_shr_long_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_long_2addr.d.T_shr_long_2addr_3", VerifyError.class);
     }
 
     /**
@@ -114,12 +104,7 @@
      * @title types of arguments - int, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_long_2addr.d.T_shr_long_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_long_2addr.d.T_shr_long_2addr_4", VerifyError.class);
     }
 
     /**
@@ -127,12 +112,7 @@
      * @title types of arguments - float, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_long_2addr.d.T_shr_long_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_long_2addr.d.T_shr_long_2addr_5", VerifyError.class);
     }
 
     /**
@@ -140,12 +120,7 @@
      * @title types of arguments - reference, int
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_long_2addr.d.T_shr_long_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_long_2addr.d.T_shr_long_2addr_6", VerifyError.class);
     }
 
     /**
@@ -154,12 +129,7 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.shr_long_2addr.d.T_shr_long_2addr_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.shr_long_2addr.d.T_shr_long_2addr_7", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/sparse_switch/Test_sparse_switch.java b/tools/vm-tests-tf/src/dot/junit/opcodes/sparse_switch/Test_sparse_switch.java
index 7579dae..6ed7986 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/sparse_switch/Test_sparse_switch.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/sparse_switch/Test_sparse_switch.java
@@ -69,12 +69,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.sparse_switch.d.T_sparse_switch_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sparse_switch.d.T_sparse_switch_3", VerifyError.class);
     }
 
 
@@ -84,12 +79,7 @@
      * @title type of argument - double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.sparse_switch.d.T_sparse_switch_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sparse_switch.d.T_sparse_switch_4", VerifyError.class);
     }
     
     /**
@@ -97,12 +87,7 @@
      * @title  type of argument - long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.sparse_switch.d.T_sparse_switch_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sparse_switch.d.T_sparse_switch_5", VerifyError.class);
     }
     
     /**
@@ -110,12 +95,7 @@
      * @title type of argument - reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.sparse_switch.d.T_sparse_switch_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sparse_switch.d.T_sparse_switch_6", VerifyError.class);
     }
 
     /**
@@ -123,12 +103,7 @@
      * @title branch target shall be inside the method
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.sparse_switch.d.T_sparse_switch_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sparse_switch.d.T_sparse_switch_7", VerifyError.class);
     }
 
     /**
@@ -136,12 +111,7 @@
      * @title branch target shall not be "inside" instruction
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.sparse_switch.d.T_sparse_switch_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sparse_switch.d.T_sparse_switch_8", VerifyError.class);
     }
 
     /**
@@ -149,12 +119,7 @@
      * @title offset to table shall be inside method
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.sparse_switch.d.T_sparse_switch_9");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sparse_switch.d.T_sparse_switch_9", VerifyError.class);
     }
 
     /**
@@ -163,12 +128,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE8() {
-        try {
-            Class.forName("dot.junit.opcodes.sparse_switch.d.T_sparse_switch_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sparse_switch.d.T_sparse_switch_2", VerifyError.class);
     }
 
     /**
@@ -176,12 +136,7 @@
      * @title pairs shall be sorted in ascending order
      */
     public void testVFE9() {
-        try {
-            Class.forName("dot.junit.opcodes.sparse_switch.d.T_sparse_switch_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sparse_switch.d.T_sparse_switch_11", VerifyError.class);
     }
 
     /**
@@ -189,12 +144,7 @@
      * @title number of entries in jump table
      */
     public void testVFE10() {
-        try {
-            Class.forName("dot.junit.opcodes.sparse_switch.d.T_sparse_switch_12");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sparse_switch.d.T_sparse_switch_12", VerifyError.class);
     }
     
     /**
@@ -202,12 +152,7 @@
      * @title sparse-switch-data pseudo-instructions must not be reachable by control flow 
      */
     public void testVFE11() {
-        try {
-            Class.forName("dot.junit.opcodes.sparse_switch.d.T_sparse_switch_13");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sparse_switch.d.T_sparse_switch_13", VerifyError.class);
     }
     
     /**
@@ -215,11 +160,6 @@
      * @title table has wrong ident code 
      */
     public void testVFE12() {
-        try {
-            Class.forName("dot.junit.opcodes.sparse_switch.d.T_sparse_switch_14");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sparse_switch.d.T_sparse_switch_14", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/sput/Test_sput.java b/tools/vm-tests-tf/src/dot/junit/opcodes/sput/Test_sput.java
index 0c432f3..7f27ae9 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/sput/Test_sput.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/sput/Test_sput.java
@@ -84,13 +84,7 @@
      * @title initialization of referenced class throws exception
      */
     public void testE6() {
-        T_sput_13 t = new T_sput_13();
-        try {
-            t.run();
-            fail("expected Error");
-        } catch (Error e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.sput.d.T_sput_13", ExceptionInInitializerError.class);
     }
 
     /**
@@ -98,12 +92,7 @@
      * @title  constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.sput.d.T_sput_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput.d.T_sput_3", VerifyError.class);
     }
 
     /**
@@ -112,12 +101,7 @@
      * @title  number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.sput.d.T_sput_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput.d.T_sput_4", VerifyError.class);
     }
 
 
@@ -128,11 +112,7 @@
      * different type exists
      */
     public void testVFE5() {
-        try {
-            new T_sput_17().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput.d.T_sput_17", NoSuchFieldError.class);
     }
 
     /**
@@ -141,12 +121,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.sput.d.T_sput_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput.d.T_sput_5", VerifyError.class);
     }
 
     /**
@@ -156,12 +131,7 @@
      * with single-width register
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.sput.d.T_sput_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput.d.T_sput_18", VerifyError.class);
     }
 
     /**
@@ -170,11 +140,7 @@
      * @title Attempt to set non-static field.
      */
     public void testVFE8() {
-         try {
-             new T_sput_7().run();
-             fail("expected IncompatibleClassChangeError");
-         } catch (IncompatibleClassChangeError t) {
-         }
+        loadAndRun("dot.junit.opcodes.sput.d.T_sput_7", IncompatibleClassChangeError.class);
     }
 
     /**
@@ -183,12 +149,7 @@
      */
     public void testVFE9() {
         //@uses dot.junit.opcodes.sput.TestStubs
-        //@uses dot.junit.opcodes.sput.d.T_sput_8
-        try {
-            new T_sput_8().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput.d.T_sput_8", IllegalAccessError.class);
     }
 
     /**
@@ -196,11 +157,7 @@
      * @title Attempt to modify field of undefined class.
      */
     public void testVFE10() {
-        try {
-            new T_sput_9().run();
-            fail("expected NoClassDefFoundError");
-        } catch (NoClassDefFoundError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput.d.T_sput_9", NoClassDefFoundError.class);
     }
 
     /**
@@ -208,11 +165,7 @@
      * @title Attempt to modify undefined field.
      */
     public void testVFE11() {
-        try {
-            new T_sput_10().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput.d.T_sput_10", NoSuchFieldError.class);
     }
 
 
@@ -223,12 +176,7 @@
      */
     public void testVFE12() {
         //@uses dot.junit.opcodes.sput.d.T_sput_1
-        //@uses dot.junit.opcodes.sput.d.T_sput_15
-        try {
-             new T_sput_15().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput.d.T_sput_15", IllegalAccessError.class);
     }
 
 
@@ -237,12 +185,7 @@
      * @title sput shall not work for wide numbers
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.sput.d.T_sput_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput.d.T_sput_2", VerifyError.class);
     }
 
     /**
@@ -251,12 +194,7 @@
      * @title sput shall not work for reference fields
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.sput.d.T_sput_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput.d.T_sput_20", VerifyError.class);
     }
 
     /**
@@ -265,12 +203,7 @@
      * @title sput shall not work for short fields
      */
     public void testVFE15() {
-        try {
-            Class.forName("dot.junit.opcodes.sput.d.T_sput_21");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput.d.T_sput_21", VerifyError.class);
     }
 
     /**
@@ -279,12 +212,7 @@
      * @title sput shall not work for boolean fields
      */
     public void testVFE16() {
-        try {
-            Class.forName("dot.junit.opcodes.sput.d.T_sput_22");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput.d.T_sput_22", VerifyError.class);
     }
 
     /**
@@ -293,12 +221,7 @@
      * @title sput shall not work for char fields
      */
     public void testVFE17() {
-        try {
-            Class.forName("dot.junit.opcodes.sput.d.T_sput_23");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput.d.T_sput_23", VerifyError.class);
     }
 
     /**
@@ -307,12 +230,7 @@
      * @title sput shall not work for byte fields
      */
     public void testVFE18() {
-        try {
-            Class.forName("dot.junit.opcodes.sput.d.T_sput_24");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput.d.T_sput_24", VerifyError.class);
     }
 
     /**
@@ -321,12 +239,7 @@
      */
     public void testVFE19() {
         //@uses dot.junit.opcodes.sput.TestStubs
-        //@uses dot.junit.opcodes.sput.d.T_sput_11
-    	try {
-            new T_sput_11().run();
-            fail("expected a verification exception");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput.d.T_sput_11", IllegalAccessError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/sput_boolean/Test_sput_boolean.java b/tools/vm-tests-tf/src/dot/junit/opcodes/sput_boolean/Test_sput_boolean.java
index 1b8d96c..aae04aa 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/sput_boolean/Test_sput_boolean.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/sput_boolean/Test_sput_boolean.java
@@ -71,13 +71,8 @@
      * @title initialization of referenced class throws exception
      */
     public void testE6() {
-        T_sput_boolean_13 t = new T_sput_boolean_13();
-        try {
-            t.run();
-            fail("expected Error");
-        } catch (Error e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.sput_boolean.d.T_sput_boolean_13",
+                   ExceptionInInitializerError.class);
     }
 
     /**
@@ -85,12 +80,7 @@
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_boolean.d.T_sput_boolean_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_boolean.d.T_sput_boolean_3", VerifyError.class);
     }
 
     /**
@@ -99,12 +89,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_boolean.d.T_sput_boolean_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_boolean.d.T_sput_boolean_4", VerifyError.class);
     }
 
 
@@ -115,11 +100,7 @@
      * different type exists
      */
     public void testVFE5() {
-        try {
-            new T_sput_boolean_17().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_boolean.d.T_sput_boolean_17", NoSuchFieldError.class);
     }
 
     /**
@@ -129,12 +110,7 @@
      * field with single-width register
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_boolean.d.T_sput_boolean_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_boolean.d.T_sput_boolean_18", VerifyError.class);
     }
 
     /**
@@ -143,11 +119,8 @@
      * @title Attempt to set non-static field.
      */
     public void testVFE8() {
-         try {
-             new T_sput_boolean_7().run();
-             fail("expected IncompatibleClassChangeError");
-         } catch (IncompatibleClassChangeError t) {
-         }
+        loadAndRun("dot.junit.opcodes.sput_boolean.d.T_sput_boolean_7",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -156,12 +129,7 @@
      */
     public void testVFE9() {
         //@uses dot.junit.opcodes.sput_boolean.TestStubs
-        //@uses dot.junit.opcodes.sput_boolean.d.T_sput_boolean_8
-        try {
-            new T_sput_boolean_8().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_boolean.d.T_sput_boolean_8", IllegalAccessError.class);
     }
 
     /**
@@ -169,11 +137,7 @@
      * @title Attempt to modify field of undefined class.
      */
     public void testVFE10() {
-        try {
-            new T_sput_boolean_9().run();
-            fail("expected NoClassDefFoundError");
-        } catch (NoClassDefFoundError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_boolean.d.T_sput_boolean_9", NoClassDefFoundError.class);
     }
 
     /**
@@ -181,11 +145,7 @@
      * @title Attempt to modify undefined field.
      */
     public void testVFE11() {
-        try {
-            new T_sput_boolean_10().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_boolean.d.T_sput_boolean_10", NoSuchFieldError.class);
     }
 
 
@@ -196,12 +156,7 @@
      */
     public void testVFE12() {
         //@uses dot.junit.opcodes.sput_boolean.d.T_sput_boolean_1
-        //@uses dot.junit.opcodes.sput_boolean.d.T_sput_boolean_15
-        try {
-            new T_sput_boolean_15().run();
-            fail("expected a verification exception");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_boolean.d.T_sput_boolean_15", IllegalAccessError.class);
     }
 
 
@@ -210,12 +165,7 @@
      * @title sput_boolean shall not work for wide numbers
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_boolean.d.T_sput_boolean_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_boolean.d.T_sput_boolean_2", VerifyError.class);
     }
 
     /**
@@ -224,12 +174,7 @@
      * @title sput_boolean shall not work for reference fields
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_boolean.d.T_sput_boolean_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_boolean.d.T_sput_boolean_20", VerifyError.class);
     }
 
     /**
@@ -238,12 +183,7 @@
      * @title sput_boolean shall not work for short fields
      */
     public void testVFE15() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_boolean.d.T_sput_boolean_21");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_boolean.d.T_sput_boolean_21", VerifyError.class);
     }
 
     /**
@@ -252,12 +192,7 @@
      * @title sput_boolean shall not work for int fields
      */
     public void testVFE16() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_boolean.d.T_sput_boolean_22");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_boolean.d.T_sput_boolean_22", VerifyError.class);
     }
 
     /**
@@ -266,12 +201,7 @@
      * @title sput_boolean shall not work for char fields
      */
     public void testVFE17() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_boolean.d.T_sput_boolean_23");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_boolean.d.T_sput_boolean_23", VerifyError.class);
     }
 
     /**
@@ -280,12 +210,7 @@
      * @title sput_boolean shall not work for byte fields
      */
     public void testVFE18() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_boolean.d.T_sput_boolean_24");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_boolean.d.T_sput_boolean_24", VerifyError.class);
     }
 
     /**
@@ -294,12 +219,6 @@
      */
     public void testVFE19() {
         //@uses dot.junit.opcodes.sput_boolean.TestStubs
-        //@uses dot.junit.opcodes.sput_boolean.d.T_sput_boolean_11
-
-    	try {
-    		new T_sput_boolean_11().run();
-    		fail("expected IllegalAccessError");
-    	} catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_boolean.d.T_sput_boolean_11", IllegalAccessError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/sput_byte/Test_sput_byte.java b/tools/vm-tests-tf/src/dot/junit/opcodes/sput_byte/Test_sput_byte.java
index 5ac828d..6791589 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/sput_byte/Test_sput_byte.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/sput_byte/Test_sput_byte.java
@@ -69,13 +69,8 @@
      * @title initialization of referenced class throws exception
      */
     public void testE6() {
-        T_sput_byte_13 t = new T_sput_byte_13();
-        try {
-            t.run();
-            fail("expected Error");
-        } catch (Error e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.sput_byte.d.T_sput_byte_13",
+                   ExceptionInInitializerError.class);
     }
 
     /**
@@ -83,12 +78,7 @@
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_byte.d.T_sput_byte_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_byte.d.T_sput_byte_3", VerifyError.class);
     }
 
     /**
@@ -97,12 +87,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_byte.d.T_sput_byte_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_byte.d.T_sput_byte_4", VerifyError.class);
     }
 
 
@@ -113,11 +98,7 @@
      * different type exists
      */
     public void testVFE5() {
-        try {
-            new T_sput_byte_17().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_byte.d.T_sput_byte_17", NoSuchFieldError.class);
     }
 
     /**
@@ -127,12 +108,7 @@
      * field with single-width register
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_byte.d.T_sput_byte_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_byte.d.T_sput_byte_18", VerifyError.class);
     }
 
     /**
@@ -141,11 +117,8 @@
      * @title Attempt to set non-static field.
      */
     public void testVFE8() {
-         try {
-             new T_sput_byte_7().run();
-             fail("expected IncompatibleClassChangeError");
-         } catch (IncompatibleClassChangeError t) {
-         }
+        loadAndRun("dot.junit.opcodes.sput_byte.d.T_sput_byte_7",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -154,12 +127,7 @@
      */
     public void testVFE9() {
         //@uses dot.junit.opcodes.sput_byte.TestStubs
-        //@uses dot.junit.opcodes.sput_byte.d.T_sput_byte_8
-        try {
-            new T_sput_byte_8().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_byte.d.T_sput_byte_8", IllegalAccessError.class);
     }
 
     /**
@@ -167,11 +135,7 @@
      * @title Attempt to modify field of undefined class.
      */
     public void testVFE10() {
-        try {
-            new T_sput_byte_9().run();
-            fail("expected NoClassDefFoundError");
-        } catch (NoClassDefFoundError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_byte.d.T_sput_byte_9", NoClassDefFoundError.class);
     }
 
     /**
@@ -179,11 +143,7 @@
      * @title Attempt to modify undefined field.
      */
     public void testVFE11() {
-        try {
-            new T_sput_byte_10().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_byte.d.T_sput_byte_10", NoSuchFieldError.class);
     }
 
 
@@ -194,12 +154,7 @@
      */
     public void testVFE12() {
         //@uses dot.junit.opcodes.sput_byte.d.T_sput_byte_1
-        //@uses dot.junit.opcodes.sput_byte.d.T_sput_byte_15
-        try {
-            new T_sput_byte_15().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_byte.d.T_sput_byte_15", IllegalAccessError.class);
     }
 
 
@@ -208,12 +163,7 @@
      * @title sput-byte shall not work for wide numbers
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_byte.d.T_sput_byte_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_byte.d.T_sput_byte_2", VerifyError.class);
     }
 
     /**
@@ -222,12 +172,7 @@
      * @title sput-byte shall not work for reference fields
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_byte.d.T_sput_byte_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_byte.d.T_sput_byte_20", VerifyError.class);
     }
 
     /**
@@ -236,12 +181,7 @@
      * @title sput-byte shall not work for short fields
      */
     public void testVFE15() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_byte.d.T_sput_byte_21");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_byte.d.T_sput_byte_21", VerifyError.class);
     }
 
     /**
@@ -250,12 +190,7 @@
      * @title sput-byte shall not work for int fields
      */
     public void testVFE16() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_byte.d.T_sput_byte_22");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_byte.d.T_sput_byte_22", VerifyError.class);
     }
 
     /**
@@ -264,12 +199,7 @@
      * @title sput-byte shall not work for char fields
      */
     public void testVFE17() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_byte.d.T_sput_byte_23");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_byte.d.T_sput_byte_23", VerifyError.class);
     }
 
     /**
@@ -277,12 +207,7 @@
      * @title sput-byte shall not work for boolean fields
      */
     public void testVFE18() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_byte.d.T_sput_byte_24");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_byte.d.T_sput_byte_24", VerifyError.class);
     }
 
     /**
@@ -291,12 +216,7 @@
      */
     public void testVFE19() {
         //@uses dot.junit.opcodes.sput_byte.TestStubs
-        //@uses dot.junit.opcodes.sput_byte.d.T_sput_byte_11
-    	try {
-            new T_sput_byte_11().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_byte.d.T_sput_byte_11", IllegalAccessError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/sput_char/Test_sput_char.java b/tools/vm-tests-tf/src/dot/junit/opcodes/sput_char/Test_sput_char.java
index 8585365..a525c7e 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/sput_char/Test_sput_char.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/sput_char/Test_sput_char.java
@@ -69,13 +69,8 @@
      * @title initialization of referenced class throws exception
      */
     public void testE6() {
-        T_sput_char_13 t = new T_sput_char_13();
-        try {
-            t.run();
-            fail("expected Error");
-        } catch (Error e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.sput_char.d.T_sput_char_13",
+                   ExceptionInInitializerError.class);
     }
 
     /**
@@ -83,12 +78,7 @@
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_char.d.T_sput_char_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_char.d.T_sput_char_3", VerifyError.class);
     }
 
     /**
@@ -97,12 +87,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_char.d.T_sput_char_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_char.d.T_sput_char_4", VerifyError.class);
     }
 
 
@@ -113,11 +98,7 @@
      * different type exists
      */
     public void testVFE5() {
-        try {
-            new T_sput_char_17().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_char.d.T_sput_char_17", NoSuchFieldError.class);
     }
 
     /**
@@ -127,12 +108,7 @@
      * field with single-width register
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_char.d.T_sput_char_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_char.d.T_sput_char_18", VerifyError.class);
     }
 
     /**
@@ -141,11 +117,8 @@
      * @title Attempt to set non-static field.
      */
     public void testVFE8() {
-         try {
-             new T_sput_char_7().run();
-             fail("expected IncompatibleClassChangeError");
-         } catch (IncompatibleClassChangeError t) {
-         }
+        loadAndRun("dot.junit.opcodes.sput_char.d.T_sput_char_7",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -154,12 +127,7 @@
      */
     public void testVFE9() {
         //@uses dot.junit.opcodes.sput_char.TestStubs
-        //@uses dot.junit.opcodes.sput_char.d.T_sput_char_8
-        try {
-            new T_sput_char_8().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_char.d.T_sput_char_8", IllegalAccessError.class);
     }
 
     /**
@@ -167,11 +135,7 @@
      * @title Attempt to modify field of undefined class.
      */
     public void testVFE10() {
-        try {
-            new T_sput_char_9().run();
-            fail("expected NoClassDefFoundError");
-        } catch (NoClassDefFoundError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_char.d.T_sput_char_9", NoClassDefFoundError.class);
     }
 
     /**
@@ -179,11 +143,7 @@
      * @title Attempt to modify undefined field.
      */
     public void testVFE11() {
-        try {
-            new T_sput_char_10().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_char.d.T_sput_char_10", NoSuchFieldError.class);
     }
 
 
@@ -194,12 +154,7 @@
      */
     public void testVFE12() {
         //@uses dot.junit.opcodes.sput_char.d.T_sput_char_1
-        //@uses dot.junit.opcodes.sput_char.d.T_sput_char_15
-        try {
-            new T_sput_char_15().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_char.d.T_sput_char_15", IllegalAccessError.class);
     }
 
 
@@ -208,12 +163,7 @@
      * @title sput-char shall not work for wide numbers
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_char.d.T_sput_char_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_char.d.T_sput_char_2", VerifyError.class);
     }
 
     /**
@@ -222,12 +172,7 @@
      * @title sput-char shall not work for reference fields
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_char.d.T_sput_char_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_char.d.T_sput_char_20", VerifyError.class);
     }
 
     /**
@@ -236,12 +181,7 @@
      * @title sput-char shall not work for short fields
      */
     public void testVFE15() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_char.d.T_sput_char_21");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_char.d.T_sput_char_21", VerifyError.class);
     }
 
     /**
@@ -250,12 +190,7 @@
      * @title sput-char shall not work for int fields
      */
     public void testVFE16() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_char.d.T_sput_char_22");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_char.d.T_sput_char_22", VerifyError.class);
     }
 
     /**
@@ -264,12 +199,7 @@
      * @title sput-char shall not work for byte fields
      */
     public void testVFE17() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_char.d.T_sput_char_23");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_char.d.T_sput_char_23", VerifyError.class);
     }
 
     /**
@@ -278,12 +208,7 @@
      * @title sput-char shall not work for boolean fields
      */
     public void testVFE18() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_char.d.T_sput_char_24");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_char.d.T_sput_char_24", VerifyError.class);
     }
 
     /**
@@ -292,11 +217,6 @@
      */
     public void testVFE19() {
         //@uses dot.junit.opcodes.sput_char.TestStubs
-        //@uses dot.junit.opcodes.sput_char.d.T_sput_char_11
-    	try {
-            new T_sput_char_11().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_char.d.T_sput_char_11", IllegalAccessError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/sput_object/Test_sput_object.java b/tools/vm-tests-tf/src/dot/junit/opcodes/sput_object/Test_sput_object.java
index cd070a7..8d52f7f 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/sput_object/Test_sput_object.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/sput_object/Test_sput_object.java
@@ -69,13 +69,8 @@
      * @title initialization of referenced class throws exception
      */
     public void testE6() {
-        T_sput_object_13 t = new T_sput_object_13();
-        try {
-            t.run();
-            fail("expected Error");
-        } catch (Error e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.sput_object.d.T_sput_object_13",
+                   ExceptionInInitializerError.class);
     }
 
     /**
@@ -83,12 +78,7 @@
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_object.d.T_sput_object_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_object.d.T_sput_object_3", VerifyError.class);
     }
 
     /**
@@ -97,12 +87,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_object.d.T_sput_object_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_object.d.T_sput_object_4", VerifyError.class);
     }
 
 
@@ -113,11 +98,7 @@
      * different type exists
      */
     public void testVFE5() {
-        try {
-            new T_sput_object_17().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_object.d.T_sput_object_17", NoSuchFieldError.class);
     }
 
 
@@ -128,12 +109,7 @@
      * field with single-width register
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_object.d.T_sput_object_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_object.d.T_sput_object_18", VerifyError.class);
     }
 
     /**
@@ -142,12 +118,9 @@
      * @title Attempt to set non-static field.
      */
     public void testVFE8() {
-         try {
-             new T_sput_object_7().run();
-             fail("expected IncompatibleClassChangeError");
-         } catch (IncompatibleClassChangeError t) {
-         }
-    }
+        loadAndRun("dot.junit.opcodes.sput_object.d.T_sput_object_7",
+                   IncompatibleClassChangeError.class);
+   }
 
     /**
      * @constraint n/a
@@ -155,12 +128,7 @@
      */
     public void testVFE9() {
         //@uses dot.junit.opcodes.sput_object.TestStubs
-        //@uses dot.junit.opcodes.sput_object.d.T_sput_object_8
-        try {
-            new T_sput_object_8().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_object.d.T_sput_object_8", IllegalAccessError.class);
     }
 
     /**
@@ -168,11 +136,7 @@
      * @title Attempt to modify field of undefined class.
      */
     public void testVFE10() {
-        try {
-            new T_sput_object_9().run();
-            fail("expected NoClassDefFoundError");
-        } catch (NoClassDefFoundError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_object.d.T_sput_object_9", NoClassDefFoundError.class);
     }
 
     /**
@@ -180,11 +144,7 @@
      * @title Attempt to modify undefined field.
      */
     public void testVFE11() {
-        try {
-            new T_sput_object_10().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_object.d.T_sput_object_10", NoSuchFieldError.class);
     }
 
 
@@ -195,12 +155,7 @@
      */
     public void testVFE12() {
         //@uses dot.junit.opcodes.sput_object.d.T_sput_object_1
-        //@uses dot.junit.opcodes.sput_object.d.T_sput_object_15
-        try {
-            new T_sput_object_15().run();
-            fail("expected a verification exception");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_object.d.T_sput_object_15", IllegalAccessError.class);
     }
 
 
@@ -209,12 +164,7 @@
      * @title sput-object shall not work for wide numbers
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_object.d.T_sput_object_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_object.d.T_sput_object_2", VerifyError.class);
     }
 
     /**
@@ -223,12 +173,7 @@
      * @title assignment incompatible references
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_object.d.T_sput_object_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_object.d.T_sput_object_20", VerifyError.class);
     }
 
     /**
@@ -237,12 +182,7 @@
      * @title sput-object shall not work for char fields
      */
     public void testVFE15() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_object.d.T_sput_object_21");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_object.d.T_sput_object_21", VerifyError.class);
     }
 
     /**
@@ -251,12 +191,7 @@
      * @title sput-object shall not work for int fields
      */
     public void testVFE16() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_object.d.T_sput_object_22");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_object.d.T_sput_object_22", VerifyError.class);
     }
 
     /**
@@ -265,12 +200,7 @@
      * @title sput-object shall not work for byte fields
      */
     public void testVFE17() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_object.d.T_sput_object_23");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_object.d.T_sput_object_23", VerifyError.class);
     }
 
     /**
@@ -279,12 +209,7 @@
      * @title sput-object shall not work for boolean fields
      */
     public void testVFE18() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_object.d.T_sput_object_24");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_object.d.T_sput_object_24", VerifyError.class);
     }
 
     /**
@@ -293,12 +218,7 @@
      * @title sput-object shall not work for short fields
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_object.d.T_sput_object_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_object.d.T_sput_object_6", VerifyError.class);
     }
 
 
@@ -308,11 +228,6 @@
      */
     public void testVFE19() {
         //@uses dot.junit.opcodes.sput_object.TestStubs
-        //@uses dot.junit.opcodes.sput_object.d.T_sput_object_11
-    	try {
-            new T_sput_object_11().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_object.d.T_sput_object_11", IllegalAccessError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/sput_short/Test_sput_short.java b/tools/vm-tests-tf/src/dot/junit/opcodes/sput_short/Test_sput_short.java
index 5fcbe58..b6ec230 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/sput_short/Test_sput_short.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/sput_short/Test_sput_short.java
@@ -69,13 +69,8 @@
      * @title initialization of referenced class throws exception
      */
     public void testE6() {
-        T_sput_short_13 t = new T_sput_short_13();
-        try {
-            t.run();
-            fail("expected Error");
-        } catch (Error e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.sput_short.d.T_sput_short_13",
+                   ExceptionInInitializerError.class);
     }
 
     /**
@@ -83,12 +78,7 @@
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_short.d.T_sput_short_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_short.d.T_sput_short_3", VerifyError.class);
     }
 
     /**
@@ -97,12 +87,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_short.d.T_sput_short_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_short.d.T_sput_short_4", VerifyError.class);
     }
 
 
@@ -113,11 +98,7 @@
      * different type exists
      */
     public void testVFE5() {
-        try {
-            new T_sput_short_17().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_short.d.T_sput_short_17", NoSuchFieldError.class);
     }
 
     /**
@@ -127,12 +108,7 @@
      * field with single-width register
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_short.d.T_sput_short_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_short.d.T_sput_short_18", VerifyError.class);
     }
 
     /**
@@ -141,11 +117,8 @@
      * @title Attempt to set non-static field.
      */
     public void testVFE8() {
-         try {
-             new T_sput_short_7().run();
-             fail("expected IncompatibleClassChangeError");
-         } catch (IncompatibleClassChangeError t) {
-         }
+        loadAndRun("dot.junit.opcodes.sput_short.d.T_sput_short_7",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -154,12 +127,7 @@
      */
     public void testVFE9() {
         //@uses dot.junit.opcodes.sput_short.TestStubs
-        //@uses dot.junit.opcodes.sput_short.d.T_sput_short_8
-        try {
-            new T_sput_short_8().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_short.d.T_sput_short_8", IllegalAccessError.class);
     }
 
     /**
@@ -167,11 +135,7 @@
      * @title Attempt to modify field of undefined class.
      */
     public void testVFE10() {
-        try {
-            new T_sput_short_9().run();
-            fail("expected NoClassDefFoundError");
-        } catch (NoClassDefFoundError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_short.d.T_sput_short_9", NoClassDefFoundError.class);
     }
 
     /**
@@ -179,11 +143,7 @@
      * @title Attempt to modify undefined field.
      */
     public void testVFE11() {
-        try {
-            new T_sput_short_10().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_short.d.T_sput_short_10", NoSuchFieldError.class);
     }
 
 
@@ -194,12 +154,7 @@
      */
     public void testVFE12() {
         //@uses dot.junit.opcodes.sput_short.d.T_sput_short_1
-        //@uses dot.junit.opcodes.sput_short.d.T_sput_short_15
-        try {
-            new T_sput_short_15().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_short.d.T_sput_short_15", IllegalAccessError.class);
     }
 
 
@@ -208,12 +163,7 @@
      * @title sput-short shall not work for wide numbers
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_short.d.T_sput_short_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_short.d.T_sput_short_2", VerifyError.class);
     }
 
     /**
@@ -222,12 +172,7 @@
      * @title sput-short shall not work for reference fields
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_short.d.T_sput_short_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_short.d.T_sput_short_20", VerifyError.class);
     }
 
     /**
@@ -236,12 +181,7 @@
      * @title sput-short shall not work for char fields
      */
     public void testVFE15() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_short.d.T_sput_short_21");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_short.d.T_sput_short_21", VerifyError.class);
     }
 
     /**
@@ -250,12 +190,7 @@
      * @title sput-short shall not work for int fields
      */
     public void testVFE16() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_short.d.T_sput_short_22");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_short.d.T_sput_short_22", VerifyError.class);
     }
 
     /**
@@ -264,12 +199,7 @@
      * @title sput-short shall not work for byte fields
      */
     public void testVFE17() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_short.d.T_sput_short_23");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_short.d.T_sput_short_23", VerifyError.class);
     }
 
     /**
@@ -278,12 +208,7 @@
      * @title sput-short shall not work for boolean fields
      */
     public void testVFE18() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_short.d.T_sput_short_24");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_short.d.T_sput_short_24", VerifyError.class);
     }
 
     /**
@@ -292,11 +217,6 @@
      */
     public void testVFE19() {
         //@uses dot.junit.opcodes.sput_short.TestStubs
-        //@uses dot.junit.opcodes.sput_short.d.T_sput_short_11
-    	try {
-            new T_sput_short_11().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_short.d.T_sput_short_11", IllegalAccessError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/sput_wide/Test_sput_wide.java b/tools/vm-tests-tf/src/dot/junit/opcodes/sput_wide/Test_sput_wide.java
index 29ff21b..d015912 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/sput_wide/Test_sput_wide.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/sput_wide/Test_sput_wide.java
@@ -79,13 +79,8 @@
      * @title initialization of referenced class throws exception
      */
     public void testE6() {
-        T_sput_wide_13 t = new T_sput_wide_13();
-        try {
-            t.run();
-            fail("expected Error");
-        } catch (Error e) {
-            // expected
-        }
+        loadAndRun("dot.junit.opcodes.sput_wide.d.T_sput_wide_13",
+                   ExceptionInInitializerError.class);
     }
 
     /**
@@ -93,12 +88,7 @@
      * @title constant pool index
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_wide.d.T_sput_wide_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_wide.d.T_sput_wide_3", VerifyError.class);
     }
 
     /**
@@ -107,12 +97,7 @@
      * @title number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_wide.d.T_sput_wide_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_wide.d.T_sput_wide_4", VerifyError.class);
     }
 
 
@@ -123,11 +108,7 @@
      * different type exists
      */
     public void testVFE5() {
-        try {
-            new T_sput_wide_17().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_wide.d.T_sput_wide_17", NoSuchFieldError.class);
     }
 
 
@@ -139,12 +120,7 @@
      * field with double-width register
      */
     public void testVFE7() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_wide.d.T_sput_wide_18");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_wide.d.T_sput_wide_18", VerifyError.class);
     }
 
     /**
@@ -154,11 +130,8 @@
      * executing the code.
      */
     public void testVFE8() {
-         try {
-             new T_sput_wide_7().run();
-             fail("expected IncompatibleClassChangeError");
-         } catch (IncompatibleClassChangeError t) {
-         }
+        loadAndRun("dot.junit.opcodes.sput_wide.d.T_sput_wide_7",
+                   IncompatibleClassChangeError.class);
     }
 
     /**
@@ -168,12 +141,7 @@
      */
     public void testVFE9() {
         //@uses dot.junit.opcodes.sput_wide.TestStubs
-        //@uses dot.junit.opcodes.sput_wide.d.T_sput_wide_8
-        try {
-            new T_sput_wide_8().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_wide.d.T_sput_wide_8", IllegalAccessError.class);
     }
 
     /**
@@ -182,12 +150,7 @@
      * executing the code.
      */
     public void testVFE10() {
-        //@uses dot.junit.opcodes.sput_wide.d.T_sput_wide_9
-        try {
-            new T_sput_wide_9().run();
-            fail("expected NoClassDefFoundError");
-        } catch (NoClassDefFoundError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_wide.d.T_sput_wide_9", NoClassDefFoundError.class);
     }
 
     /**
@@ -196,12 +159,7 @@
      * code.
      */
     public void testVFE11() {
-        //@uses dot.junit.opcodes.sput_wide.d.T_sput_wide_10
-        try {
-            new T_sput_wide_10().run();
-            fail("expected NoSuchFieldError");
-        } catch (NoSuchFieldError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_wide.d.T_sput_wide_10", NoSuchFieldError.class);
     }
 
 
@@ -213,13 +171,7 @@
      */
     public void testVFE12() {
         //@uses dot.junit.opcodes.sput_wide.d.T_sput_wide_1
-        //@uses dot.junit.opcodes.sput_wide.d.T_sput_wide_15
-        try {
-            new T_sput_wide_15().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-            DxUtil.checkVerifyException(t);
-        }
+        loadAndRun("dot.junit.opcodes.sput_wide.d.T_sput_wide_15", IllegalAccessError.class);
     }
 
 
@@ -228,12 +180,7 @@
      * @title sput-wide shall not work for single-width numbers
      */
     public void testVFE13() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_wide.d.T_sput_wide_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_wide.d.T_sput_wide_2", VerifyError.class);
     }
 
     /**
@@ -242,12 +189,7 @@
      * @title sput-wide shall not work for reference fields
      */
     public void testVFE14() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_wide.d.T_sput_wide_20");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_wide.d.T_sput_wide_20", VerifyError.class);
     }
 
     /**
@@ -256,12 +198,7 @@
      * @title sput-wide shall not work for char fields
      */
     public void testVFE15() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_wide.d.T_sput_wide_21");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_wide.d.T_sput_wide_21", VerifyError.class);
     }
 
     /**
@@ -270,12 +207,7 @@
      * @title sput-wide shall not work for int fields
      */
     public void testVFE16() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_wide.d.T_sput_wide_22");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_wide.d.T_sput_wide_22", VerifyError.class);
     }
 
     /**
@@ -284,12 +216,7 @@
      * @title sput-wide shall not work for byte fields
      */
     public void testVFE17() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_wide.d.T_sput_wide_23");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_wide.d.T_sput_wide_23", VerifyError.class);
     }
 
     /**
@@ -298,12 +225,7 @@
      * @title sput-wide shall not work for boolean fields
      */
     public void testVFE18() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_wide.d.T_sput_wide_24");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_wide.d.T_sput_wide_24", VerifyError.class);
     }
 
     /**
@@ -312,12 +234,7 @@
      * @title sput-wide shall not work for short fields
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.sput_wide.d.T_sput_wide_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sput_wide.d.T_sput_wide_6", VerifyError.class);
     }
 
     /**
@@ -326,12 +243,7 @@
      */
     public void testVFE19() {
         //@uses dot.junit.opcodes.sput_wide.TestStubs
-        //@uses dot.junit.opcodes.sput_wide.d.T_sput_wide_11
-    	try {
-            new T_sput_wide_11().run();
-            fail("expected IllegalAccessError");
-        } catch (IllegalAccessError t) {
-        }
+        loadAndRun("dot.junit.opcodes.sput_wide.d.T_sput_wide_11", IllegalAccessError.class);
     }
 
 
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/sput_wide/d/T_sput_wide_13.d b/tools/vm-tests-tf/src/dot/junit/opcodes/sput_wide/d/T_sput_wide_13.d
index a130809..ae7d1df 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/sput_wide/d/T_sput_wide_13.d
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/sput_wide/d/T_sput_wide_13.d
@@ -25,7 +25,8 @@
        const/4 v1, 5
        div-int/2addr v1, v0
 
-       sput-wide v1, dot.junit.opcodes.sput_wide.d.JtubInitError.value J
+       int-to-long v0, v0
+       sput-wide v0, dot.junit.opcodes.sput_wide.d.JtubInitError.value J
        return-void
 .end method
 
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/sub_double/Test_sub_double.java b/tools/vm-tests-tf/src/dot/junit/opcodes/sub_double/Test_sub_double.java
index 78bd961..36996cb 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/sub_double/Test_sub_double.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/sub_double/Test_sub_double.java
@@ -140,12 +140,7 @@
      * @title types of arguments - float, double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_double.d.T_sub_double_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_double.d.T_sub_double_2", VerifyError.class);
     }
 
     /**
@@ -153,12 +148,7 @@
      * @title  number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_double.d.T_sub_double_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_double.d.T_sub_double_5", VerifyError.class);
     }
 
     /**
@@ -166,12 +156,7 @@
      * @title types of arguments - double, reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_double.d.T_sub_double_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_double.d.T_sub_double_4", VerifyError.class);
     }
 
     /**
@@ -179,12 +164,7 @@
      * @title types of arguments - int, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_double.d.T_sub_double_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_double.d.T_sub_double_6", VerifyError.class);
     }
 
     /**
@@ -193,12 +173,7 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_double.d.T_sub_double_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_double.d.T_sub_double_3", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/sub_double_2addr/Test_sub_double_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/sub_double_2addr/Test_sub_double_2addr.java
index 058a3ac..3369e31 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/sub_double_2addr/Test_sub_double_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/sub_double_2addr/Test_sub_double_2addr.java
@@ -139,12 +139,7 @@
      * @title  types of arguments - float, double
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_double_2addr.d.T_sub_double_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_double_2addr.d.T_sub_double_2addr_2", VerifyError.class);
     }
 
     /**
@@ -152,12 +147,7 @@
      * @title  number of registers
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_double_2addr.d.T_sub_double_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_double_2addr.d.T_sub_double_2addr_5", VerifyError.class);
     }
 
     /**
@@ -165,12 +155,7 @@
      * @title  types of arguments - double, reference
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_double_2addr.d.T_sub_double_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_double_2addr.d.T_sub_double_2addr_4", VerifyError.class);
     }
     
     /**
@@ -178,12 +163,7 @@
      * @title  types of arguments - int, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_double_2addr.d.T_sub_double_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_double_2addr.d.T_sub_double_2addr_6", VerifyError.class);
     }
 
     /**
@@ -192,12 +172,7 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_double_2addr.d.T_sub_double_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_double_2addr.d.T_sub_double_2addr_3", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/sub_float/Test_sub_float.java b/tools/vm-tests-tf/src/dot/junit/opcodes/sub_float/Test_sub_float.java
index 0b30a66..44d33e4 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/sub_float/Test_sub_float.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/sub_float/Test_sub_float.java
@@ -151,12 +151,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_float.d.T_sub_float_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_float.d.T_sub_float_5", VerifyError.class);
     }
 
     /**
@@ -164,12 +159,7 @@
      * @title types of arguments - float, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_float.d.T_sub_float_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_float.d.T_sub_float_2", VerifyError.class);
     }
 
     /**
@@ -177,12 +167,7 @@
      * @title types of arguments - long, float
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_float.d.T_sub_float_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_float.d.T_sub_float_3", VerifyError.class);
     }
 
     /**
@@ -190,12 +175,7 @@
      * @title types of arguments - reference, float
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_float.d.T_sub_float_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_float.d.T_sub_float_4", VerifyError.class);
     }
     
     /**
@@ -203,12 +183,7 @@
      * @title number of registers
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_float.d.T_sub_float_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_float.d.T_sub_float_6", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/sub_float_2addr/Test_sub_float_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/sub_float_2addr/Test_sub_float_2addr.java
index 36c7408..5ae37cd 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/sub_float_2addr/Test_sub_float_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/sub_float_2addr/Test_sub_float_2addr.java
@@ -149,12 +149,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_float_2addr.d.T_sub_float_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_float_2addr.d.T_sub_float_2addr_5", VerifyError.class);
     }
 
     /**
@@ -162,12 +157,7 @@
      * @title types of arguments - float, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_float_2addr.d.T_sub_float_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_float_2addr.d.T_sub_float_2addr_2", VerifyError.class);
     }
 
     /**
@@ -175,12 +165,7 @@
      * @title types of arguments - long, float
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_float_2addr.d.T_sub_float_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_float_2addr.d.T_sub_float_2addr_3", VerifyError.class);
     }
 
     /**
@@ -188,12 +173,7 @@
      * @title types of arguments - reference, float
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_float_2addr.d.T_sub_float_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_float_2addr.d.T_sub_float_2addr_4", VerifyError.class);
     }
 
     /**
@@ -201,12 +181,7 @@
      * @title number of registers
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_float_2addr.d.T_sub_float_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_float_2addr.d.T_sub_float_2addr_6", VerifyError.class);
     }
     
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/sub_int/Test_sub_int.java b/tools/vm-tests-tf/src/dot/junit/opcodes/sub_int/Test_sub_int.java
index 3b7ef07..ae00539 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/sub_int/Test_sub_int.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/sub_int/Test_sub_int.java
@@ -135,12 +135,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_int.d.T_sub_int_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_int.d.T_sub_int_5", VerifyError.class);
     }
 
     /**
@@ -148,12 +143,7 @@
      * @title types of arguments - int, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_int.d.T_sub_int_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_int.d.T_sub_int_2", VerifyError.class);
     }
 
     /**
@@ -161,12 +151,7 @@
      * @title types of arguments - long, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_int.d.T_sub_int_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_int.d.T_sub_int_3", VerifyError.class);
     }
 
     /**
@@ -174,12 +159,7 @@
      * @title types of arguments - reference, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_int.d.T_sub_int_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_int.d.T_sub_int_4", VerifyError.class);
     }
     
     /**
@@ -187,12 +167,7 @@
      * @title number of registers
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_int.d.T_sub_int_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_int.d.T_sub_int_6", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/sub_int_2addr/Test_sub_int_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/sub_int_2addr/Test_sub_int_2addr.java
index 0ec67f4..275c7ec 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/sub_int_2addr/Test_sub_int_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/sub_int_2addr/Test_sub_int_2addr.java
@@ -134,12 +134,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_int_2addr.d.T_sub_int_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_int_2addr.d.T_sub_int_2addr_5", VerifyError.class);
     }
 
     /**
@@ -147,12 +142,7 @@
      * @title types of arguments - int, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_int_2addr.d.T_sub_int_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_int_2addr.d.T_sub_int_2addr_2", VerifyError.class);
     }
 
     /**
@@ -160,12 +150,7 @@
      * @title types of arguments - long, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_int_2addr.d.T_sub_int_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_int_2addr.d.T_sub_int_2addr_3", VerifyError.class);
     }
 
     /**
@@ -173,12 +158,7 @@
      * @title types of arguments - reference, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_int_2addr.d.T_sub_int_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_int_2addr.d.T_sub_int_2addr_4", VerifyError.class);
     }
     
     /**
@@ -186,11 +166,6 @@
      * @title number of registers
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_int_2addr.d.T_sub_int_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_int_2addr.d.T_sub_int_2addr_6", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/sub_long/Test_sub_long.java b/tools/vm-tests-tf/src/dot/junit/opcodes/sub_long/Test_sub_long.java
index 77f30d6..f306375 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/sub_long/Test_sub_long.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/sub_long/Test_sub_long.java
@@ -102,12 +102,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_long.d.T_sub_long_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_long.d.T_sub_long_6", VerifyError.class);
     }
 
     /**
@@ -115,12 +110,7 @@
      * @title types of arguments - int, long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_long.d.T_sub_long_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_long.d.T_sub_long_3", VerifyError.class);
     }
 
     /**
@@ -128,12 +118,7 @@
      * @title types of arguments - long, float
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_long.d.T_sub_long_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_long.d.T_sub_long_4", VerifyError.class);
     }
 
     /**
@@ -141,12 +126,7 @@
      * @title types of arguments - long, reference
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_long.d.T_sub_long_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_long.d.T_sub_long_5", VerifyError.class);
     }
 
     /**
@@ -155,12 +135,7 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_long.d.T_sub_long_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_long.d.T_sub_long_2", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/sub_long_2addr/Test_sub_long_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/sub_long_2addr/Test_sub_long_2addr.java
index 1f2161d..2a784e1 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/sub_long_2addr/Test_sub_long_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/sub_long_2addr/Test_sub_long_2addr.java
@@ -102,12 +102,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_long_2addr.d.T_sub_long_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_long_2addr.d.T_sub_long_2addr_6", VerifyError.class);
     }
 
     /**
@@ -116,12 +111,7 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_long_2addr.d.T_sub_long_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_long_2addr.d.T_sub_long_2addr_2", VerifyError.class);
     }
 
     /**
@@ -129,12 +119,7 @@
      * @title types of arguments - int, long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_long_2addr.d.T_sub_long_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_long_2addr.d.T_sub_long_2addr_3", VerifyError.class);
     }
 
     /**
@@ -142,12 +127,7 @@
      * @title types of arguments - long, float
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_long_2addr.d.T_sub_long_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_long_2addr.d.T_sub_long_2addr_4", VerifyError.class);
     }
 
     /**
@@ -155,11 +135,6 @@
      * @title types of arguments - long, reference
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.sub_long_2addr.d.T_sub_long_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.sub_long_2addr.d.T_sub_long_2addr_5", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/ushr_int/Test_ushr_int.java b/tools/vm-tests-tf/src/dot/junit/opcodes/ushr_int/Test_ushr_int.java
index 09f2948..763e1c5 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/ushr_int/Test_ushr_int.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/ushr_int/Test_ushr_int.java
@@ -102,12 +102,7 @@
      * @title types of arguments - double, int
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_int.d.T_ushr_int_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_int.d.T_ushr_int_2", VerifyError.class);
     }
 
     /**
@@ -115,12 +110,7 @@
      * @title types of arguments - int, long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_int.d.T_ushr_int_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_int.d.T_ushr_int_3", VerifyError.class);
     }
 
     /**
@@ -128,12 +118,7 @@
      * @title types of arguments - reference, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_int.d.T_ushr_int_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_int.d.T_ushr_int_4", VerifyError.class);
     }
     
     /**
@@ -141,12 +126,7 @@
      * @title number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_int.d.T_ushr_int_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_int.d.T_ushr_int_6", VerifyError.class);
     }
 
     /**
@@ -155,12 +135,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_int.d.T_ushr_int_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_int.d.T_ushr_int_5", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/ushr_int_2addr/Test_ushr_int_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/ushr_int_2addr/Test_ushr_int_2addr.java
index fadd00c..ff00a78 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/ushr_int_2addr/Test_ushr_int_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/ushr_int_2addr/Test_ushr_int_2addr.java
@@ -102,12 +102,7 @@
      * @title types of arguments - double, int
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_int_2addr.d.T_ushr_int_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_int_2addr.d.T_ushr_int_2addr_2", VerifyError.class);
     }
 
     /**
@@ -115,12 +110,7 @@
      * @title types of arguments - int, long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_int_2addr.d.T_ushr_int_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_int_2addr.d.T_ushr_int_2addr_3", VerifyError.class);
     }
 
     /**
@@ -128,12 +118,7 @@
      * @title types of arguments - reference, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_int_2addr.d.T_ushr_int_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_int_2addr.d.T_ushr_int_2addr_4", VerifyError.class);
     }
     
     /**
@@ -141,12 +126,7 @@
      * @title  number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_int_2addr.d.T_ushr_int_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_int_2addr.d.T_ushr_int_2addr_6", VerifyError.class);
     }
 
     /**
@@ -155,11 +135,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_int_2addr.d.T_ushr_int_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_int_2addr.d.T_ushr_int_2addr_5", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/ushr_int_lit8/Test_ushr_int_lit8.java b/tools/vm-tests-tf/src/dot/junit/opcodes/ushr_int_lit8/Test_ushr_int_lit8.java
index 7739b3e..420acbc 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/ushr_int_lit8/Test_ushr_int_lit8.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/ushr_int_lit8/Test_ushr_int_lit8.java
@@ -111,12 +111,7 @@
      * @title types of arguments - double, int
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_int_lit8.d.T_ushr_int_lit8_10");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_int_lit8.d.T_ushr_int_lit8_10", VerifyError.class);
     }
 
     /**
@@ -124,12 +119,7 @@
      * @title types of arguments - long, int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_int_lit8.d.T_ushr_int_lit8_11");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_int_lit8.d.T_ushr_int_lit8_11", VerifyError.class);
     }
 
     /**
@@ -137,12 +127,7 @@
      * @title types of arguments - reference, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_int_lit8.d.T_ushr_int_lit8_12");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_int_lit8.d.T_ushr_int_lit8_12", VerifyError.class);
     }
     
     /**
@@ -150,12 +135,7 @@
      * @title number of registers
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_int_lit8.d.T_ushr_int_lit8_14");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_int_lit8.d.T_ushr_int_lit8_14", VerifyError.class);
     }
 
     /**
@@ -164,12 +144,7 @@
      * and floats are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_int_lit8.d.T_ushr_int_lit8_13");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_int_lit8.d.T_ushr_int_lit8_13", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/ushr_long/Test_ushr_long.java b/tools/vm-tests-tf/src/dot/junit/opcodes/ushr_long/Test_ushr_long.java
index d8541dd..6b4e4d2 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/ushr_long/Test_ushr_long.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/ushr_long/Test_ushr_long.java
@@ -107,12 +107,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_long.d.T_ushr_long_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_long.d.T_ushr_long_6", VerifyError.class);
     }
     
     
@@ -122,12 +117,7 @@
      * @title types of arguments - long, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_long.d.T_ushr_long_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_long.d.T_ushr_long_7", VerifyError.class);
     }
 
     /**
@@ -135,12 +125,7 @@
      * @title types of arguments - int, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_long.d.T_ushr_long_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_long.d.T_ushr_long_3", VerifyError.class);
     }
 
     /**
@@ -148,12 +133,7 @@
      * @title types of arguments - float, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_long.d.T_ushr_long_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_long.d.T_ushr_long_4", VerifyError.class);
     }
 
     /**
@@ -161,12 +141,7 @@
      * @title types of arguments - long, reference
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_long.d.T_ushr_long_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_long.d.T_ushr_long_5", VerifyError.class);
     }
 
     /**
@@ -175,12 +150,7 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_long.d.T_ushr_long_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_long.d.T_ushr_long_2", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/ushr_long_2addr/Test_ushr_long_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/ushr_long_2addr/Test_ushr_long_2addr.java
index 09e0880..99501f4 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/ushr_long_2addr/Test_ushr_long_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/ushr_long_2addr/Test_ushr_long_2addr.java
@@ -108,12 +108,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_long_2addr.d.T_ushr_long_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_long_2addr.d.T_ushr_long_2addr_6", VerifyError.class);
     }
 
     
@@ -123,12 +118,7 @@
      * @title types of arguments - long, double
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_long_2addr.d.T_ushr_long_2addr_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_long_2addr.d.T_ushr_long_2addr_7", VerifyError.class);
     }
 
     /**
@@ -136,12 +126,7 @@
      * @title types of arguments - int, int
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_long_2addr.d.T_ushr_long_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_long_2addr.d.T_ushr_long_2addr_3", VerifyError.class);
     }
 
     /**
@@ -149,12 +134,7 @@
      * @title types of arguments - float, int
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_long_2addr.d.T_ushr_long_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_long_2addr.d.T_ushr_long_2addr_4", VerifyError.class);
     }
 
     /**
@@ -162,12 +142,7 @@
      * @title types of arguments - long, reference
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_long_2addr.d.T_ushr_long_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_long_2addr.d.T_ushr_long_2addr_5", VerifyError.class);
     }
 
     /**
@@ -176,12 +151,7 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE6() {
-        try {
-            Class.forName("dot.junit.opcodes.ushr_long_2addr.d.T_ushr_long_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.ushr_long_2addr.d.T_ushr_long_2addr_2", VerifyError.class);
     }
 
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/xor_int/Test_xor_int.java b/tools/vm-tests-tf/src/dot/junit/opcodes/xor_int/Test_xor_int.java
index 2f2197f..4081a96 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/xor_int/Test_xor_int.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/xor_int/Test_xor_int.java
@@ -69,12 +69,7 @@
      * @title types of arguments - long, int
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.xor_int.d.T_xor_int_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.xor_int.d.T_xor_int_2", VerifyError.class);
     }
 
     /**
@@ -82,12 +77,7 @@
      * @title types of arguments - reference, int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.xor_int.d.T_xor_int_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.xor_int.d.T_xor_int_3", VerifyError.class);
     }
     
     
@@ -96,12 +86,7 @@
      * @title  number of registers
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.xor_int.d.T_xor_int_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.xor_int.d.T_xor_int_6", VerifyError.class);
     }
 
     /**
@@ -110,11 +95,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.xor_int.d.T_xor_int_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.xor_int.d.T_xor_int_5", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/xor_int_2addr/Test_xor_int_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/xor_int_2addr/Test_xor_int_2addr.java
index 0ee2ca7..dbac319 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/xor_int_2addr/Test_xor_int_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/xor_int_2addr/Test_xor_int_2addr.java
@@ -69,12 +69,7 @@
      * @title types of arguments - long, int
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.xor_int_2addr.d.T_xor_int_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.xor_int_2addr.d.T_xor_int_2addr_2", VerifyError.class);
     }
 
     /**
@@ -82,12 +77,7 @@
      * @title  types of arguments - reference, int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.xor_int_2addr.d.T_xor_int_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.xor_int_2addr.d.T_xor_int_2addr_3", VerifyError.class);
     }
     
     /**
@@ -95,12 +85,7 @@
      * @title number of registers
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.xor_int_2addr.d.T_xor_int_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.xor_int_2addr.d.T_xor_int_2addr_5", VerifyError.class);
     }
 
     /**
@@ -109,11 +94,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.xor_int_2addr.d.T_xor_int_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.xor_int_2addr.d.T_xor_int_2addr_4", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/xor_int_lit16/Test_xor_int_lit16.java b/tools/vm-tests-tf/src/dot/junit/opcodes/xor_int_lit16/Test_xor_int_lit16.java
index 383f82f..4a3c635 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/xor_int_lit16/Test_xor_int_lit16.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/xor_int_lit16/Test_xor_int_lit16.java
@@ -65,12 +65,7 @@
      * @title types of arguments - long & int
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.xor_int_lit16.d.T_xor_int_lit16_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.xor_int_lit16.d.T_xor_int_lit16_5", VerifyError.class);
     }
 
     /**
@@ -78,12 +73,7 @@
      * @title  types of arguments - reference & int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.xor_int_lit16.d.T_xor_int_lit16_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.xor_int_lit16.d.T_xor_int_lit16_6", VerifyError.class);
     }
     
     /**
@@ -91,12 +81,7 @@
      * @title  number of registers
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.xor_int_lit16.d.T_xor_int_lit16_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.xor_int_lit16.d.T_xor_int_lit16_8", VerifyError.class);
     }
 
     /**
@@ -105,11 +90,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.xor_int_lit16.d.T_xor_int_lit16_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.xor_int_lit16.d.T_xor_int_lit16_7", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/xor_int_lit8/Test_xor_int_lit8.java b/tools/vm-tests-tf/src/dot/junit/opcodes/xor_int_lit8/Test_xor_int_lit8.java
index a87103b..770ffa8 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/xor_int_lit8/Test_xor_int_lit8.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/xor_int_lit8/Test_xor_int_lit8.java
@@ -64,12 +64,7 @@
      * @title types of arguments - long, int
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.xor_int_lit8.d.T_xor_int_lit8_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.xor_int_lit8.d.T_xor_int_lit8_5", VerifyError.class);
     }
 
     /**
@@ -77,12 +72,7 @@
      * @title  types of arguments - reference, int
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.xor_int_lit8.d.T_xor_int_lit8_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.xor_int_lit8.d.T_xor_int_lit8_6", VerifyError.class);
     }
     
     /**
@@ -90,12 +80,7 @@
      * @title  number of registers
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.xor_int_lit8.d.T_xor_int_lit8_8");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.xor_int_lit8.d.T_xor_int_lit8_8", VerifyError.class);
     }
 
     /**
@@ -104,11 +89,6 @@
      * and floats are not used interchangeably.
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.xor_int_lit8.d.T_xor_int_lit8_7");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.xor_int_lit8.d.T_xor_int_lit8_7", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/xor_long/Test_xor_long.java b/tools/vm-tests-tf/src/dot/junit/opcodes/xor_long/Test_xor_long.java
index a24d884..7e94a03 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/xor_long/Test_xor_long.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/xor_long/Test_xor_long.java
@@ -75,12 +75,7 @@
      * @title number of registers
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.xor_long.d.T_xor_long_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.xor_long.d.T_xor_long_6", VerifyError.class);
     }
     
     
@@ -91,12 +86,7 @@
      * @title types of arguments - int, long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.xor_long.d.T_xor_long_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.xor_long.d.T_xor_long_3", VerifyError.class);
     }
 
     /**
@@ -105,12 +95,7 @@
      * @title types of arguments - float, long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.xor_long.d.T_xor_long_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.xor_long.d.T_xor_long_4", VerifyError.class);
     }
 
     /**
@@ -119,12 +104,7 @@
      * @title types of arguments - reference, long
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.xor_long.d.T_xor_long_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.xor_long.d.T_xor_long_5", VerifyError.class);
     }
 
     /**
@@ -133,11 +113,6 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.xor_long.d.T_xor_long_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.xor_long.d.T_xor_long_2", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/dot/junit/opcodes/xor_long_2addr/Test_xor_long_2addr.java b/tools/vm-tests-tf/src/dot/junit/opcodes/xor_long_2addr/Test_xor_long_2addr.java
index 93885fb..af4ee9b 100644
--- a/tools/vm-tests-tf/src/dot/junit/opcodes/xor_long_2addr/Test_xor_long_2addr.java
+++ b/tools/vm-tests-tf/src/dot/junit/opcodes/xor_long_2addr/Test_xor_long_2addr.java
@@ -76,12 +76,7 @@
      * @title  (number of registers).
      */
     public void testVFE1() {
-        try {
-            Class.forName("dot.junit.opcodes.xor_long_2addr.d.T_xor_long_2addr_6");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.xor_long_2addr.d.T_xor_long_2addr_6", VerifyError.class);
     }
     
     
@@ -92,12 +87,7 @@
      * @title types of arguments - int, long
      */
     public void testVFE2() {
-        try {
-            Class.forName("dot.junit.opcodes.xor_long_2addr.d.T_xor_long_2addr_3");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.xor_long_2addr.d.T_xor_long_2addr_3", VerifyError.class);
     }
 
     /**
@@ -106,12 +96,7 @@
      * @title types of arguments - float, long
      */
     public void testVFE3() {
-        try {
-            Class.forName("dot.junit.opcodes.xor_long_2addr.d.T_xor_long_2addr_4");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.xor_long_2addr.d.T_xor_long_2addr_4", VerifyError.class);
     }
 
     /**
@@ -120,12 +105,7 @@
      * @title types of arguments - reference, long
      */
     public void testVFE4() {
-        try {
-            Class.forName("dot.junit.opcodes.xor_long_2addr.d.T_xor_long_2addr_5");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.xor_long_2addr.d.T_xor_long_2addr_5", VerifyError.class);
     }
 
     /**
@@ -134,11 +114,6 @@
      * and doubles are not used interchangeably.
      */
     public void testVFE5() {
-        try {
-            Class.forName("dot.junit.opcodes.xor_long_2addr.d.T_xor_long_2addr_2");
-            fail("expected a verification exception");
-        } catch (Throwable t) {
-            DxUtil.checkVerifyException(t);
-        }
+        load("dot.junit.opcodes.xor_long_2addr.d.T_xor_long_2addr_2", VerifyError.class);
     }
 }
diff --git a/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java b/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java
index 9d4bbed..c772c33 100644
--- a/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java
+++ b/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java
@@ -211,18 +211,22 @@
         curJunitFileData = getWarningMessage() +
         "package " + pName + ";\n" +
         "import java.io.IOException;\n" +
+        "import com.android.tradefed.testtype.IAbi;\n" +
+        "import com.android.tradefed.testtype.IAbiReceiver;\n" +
         "import com.android.tradefed.testtype.DeviceTestCase;\n" +
+        "import com.android.tradefed.util.AbiFormatter;\n" +
         "\n" +
-        "public class " + sourceName + " extends DeviceTestCase {\n";
+        "public class " + sourceName + " extends DeviceTestCase implements IAbiReceiver {\n";
     }
 
     private String getShellExecJavaLine(String classpath, String mainclass) {
-      String cmd = String.format("ANDROID_DATA=%s dalvikvm -Xint:portable -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 + "\", mAbi.getBitness());\n" +
+              "    String res = getDevice().executeShellCommand(cmd);\n" +
+              "    // A sucessful adb shell command returns an empty string.\n" +
+              "    assertEquals(cmd, \"\", res);";
     }
 
     private String getWarningMessage() {
@@ -253,13 +257,14 @@
 
         //"dot.junit.opcodes.add_double_2addr.Main_testN2";
         String mainclass = pName + ".Main_" + method;
-        curJunitFileData += "    " + getShellExecJavaLine(cp, mainclass);
-        curJunitFileData += "}\n\n";
+        curJunitFileData += getShellExecJavaLine(cp, mainclass);
+        curJunitFileData += "\n}\n\n";
     }
 
     private void handleTests() throws IOException {
         System.out.println("collected " + testMethodsCnt + " test methods in " +
                 testClassCnt + " junit test classes");
+        String datafileContent = "";
         Set<BuildStep> targets = new TreeSet<BuildStep>();
 
         javacHostJunitBuildStep = new JavacBuildStep(HOSTJUNIT_CLASSES_OUTPUT_FOLDER, CLASS_PATH);
@@ -278,6 +283,13 @@
 
             openCTSHostFileFor(pName, classOnlyName);
 
+            curJunitFileData += "\n" +
+                    "protected IAbi mAbi;\n" +
+                    "@Override\n" +
+                    "public void setAbi(IAbi abi) {\n" +
+                    "    mAbi = abi;\n" +
+                    "}\n\n";
+
             List<String> methods = entry.getValue();
             Collections.sort(methods, new Comparator<String>() {
                 public int compare(String s1, String s2) {
@@ -336,6 +348,86 @@
                 targets.add(dexBuildStep);
                 // }
 
+
+                // prepare the entry in the data file for the bash script.
+                // e.g.
+                // main class to execute; opcode/constraint; test purpose
+                // dxc.junit.opcodes.aaload.Main_testN1;aaload;normal case test
+                // (#1)
+
+                char ca = method.charAt("test".length()); // either N,B,E,
+                // or V (VFE)
+                String comment;
+                switch (ca) {
+                case 'N':
+                    comment = "Normal #" + method.substring(5);
+                    break;
+                case 'B':
+                    comment = "Boundary #" + method.substring(5);
+                    break;
+                case 'E':
+                    comment = "Exception #" + method.substring(5);
+                    break;
+                case 'V':
+                    comment = "Verifier #" + method.substring(7);
+                    break;
+                default:
+                    throw new RuntimeException("unknown test abbreviation:"
+                            + method + " for " + fqcn);
+                }
+
+                String line = pName + ".Main_" + method + ";";
+                for (String className : dependentTestClassNames) {
+                    line += className + " ";
+                }
+
+
+                // test description
+                String[] pparts = pName.split("\\.");
+                // detail e.g. add_double
+                String detail = pparts[pparts.length-1];
+                // type := opcode | verify
+                String type = pparts[pparts.length-2];
+
+                String description;
+                if ("format".equals(type)) {
+                    description = "format";
+                } else if ("opcodes".equals(type)) {
+                    // Beautify name, so it matches the actual mnemonic
+                    detail = detail.replaceAll("_", "-");
+                    detail = detail.replace("-from16", "/from16");
+                    detail = detail.replace("-high16", "/high16");
+                    detail = detail.replace("-lit8", "/lit8");
+                    detail = detail.replace("-lit16", "/lit16");
+                    detail = detail.replace("-4", "/4");
+                    detail = detail.replace("-16", "/16");
+                    detail = detail.replace("-32", "/32");
+                    detail = detail.replace("-jumbo", "/jumbo");
+                    detail = detail.replace("-range", "/range");
+                    detail = detail.replace("-2addr", "/2addr");
+
+                    // Unescape reserved words
+                    detail = detail.replace("opc-", "");
+
+                    description = detail;
+                } else if ("verify".equals(type)) {
+                    description = "verifier";
+                } else {
+                    description = type + " " + detail;
+                }
+
+                String details = (md.title != null ? md.title : "");
+                if (md.constraint != null) {
+                    details = " Constraint " + md.constraint + ", " + details;
+                }
+                if (details.length() != 0) {
+                    details = details.substring(0, 1).toUpperCase()
+                            + details.substring(1);
+                }
+
+                line += ";" + description + ";" + comment + ";" + details;
+
+                datafileContent += line + "\n";
                 generateBuildStepFor(pName, method, dependentTestClassNames,
                         targets);
             }
@@ -346,6 +438,10 @@
         // write latest HOSTJUNIT generated file.
         flushHostJunitFile();
 
+        File scriptDataDir = new File(OUTPUT_FOLDER + "/data/");
+        scriptDataDir.mkdirs();
+        writeToFile(new File(scriptDataDir, "scriptdata"), datafileContent);
+
         if (!javacHostJunitBuildStep.build()) {
             System.out.println("main javac cts-host-hostjunit-classes build step failed");
             System.exit(1);
@@ -506,6 +602,22 @@
             entries.add(res.trim());
         }
 
+        // search for " load(\"...\" " and add as dependency
+        Pattern loadPattern = Pattern.compile("load\\(\"([^\"]*)\"", Pattern.MULTILINE);
+        Matcher loadMatcher = loadPattern.matcher(methodSource);
+        while (loadMatcher.find()) {
+            String res = loadMatcher.group(1);
+            entries.add(res.trim());
+        }
+
+        // search for " loadAndRun(\"...\" " and add as dependency
+        Pattern loadAndRunPattern = Pattern.compile("loadAndRun\\(\"([^\"]*)\"", Pattern.MULTILINE);
+        Matcher loadAndRunMatcher = loadAndRunPattern.matcher(methodSource);
+        while (loadAndRunMatcher.find()) {
+            String res = loadAndRunMatcher.group(1);
+            entries.add(res.trim());
+        }
+
         // lines with the form @uses
         // dot.junit.opcodes.add_double.jm.T_add_double_2
         // one dependency per one @uses